[libvirt] [PATCH 1/2] Fix spelling mistake: seek
by Philipp Hahn
Replace wrong "set" by correct "seek" in error message.
Signed-off-by: Philipp Hahn <hahn(a)univention.de>
---
src/util/storage_file.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
13 years, 9 months
[libvirt] [PATCHv2 0/5] audit: add some more audit hooks
by Eric Blake
I'm following up on danpb's patches to add initial audit support to
qemu actions (see around commit 8dc136b in Oct 2010). This series
adds the following additional audit points:
All changes to the device ACL whitelist via the cgroup device controller
All changes to memory balloon and vcpu sizes
All changes to pci and usb device passthrough
Here's an example audit, using audit-2.0.6-1.el6.x86_64 from RHEL,
where I hot-unplugged a PCI device from a guest:
type=VIRT_RESOURCE msg=audit(1298504227.432:914): user pid=13400 uid=0 auid=500 ses=3 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 msg='resrc=dev reason=detach vm="fedora_12" uuid=51c6fc83-65a4-e627-b698-042b00145201 type=pci device="0000:0a:0a.0": exe="/home/dummy/libvirt/daemon/.libs/lt-libvirtd" hostname=? addr=? terminal=pts/0 res=success'
And one where I reduced memory via ballooning:
type=VIRT_RESOURCE msg=audit(1298505060.916:927): user pid=13400 uid=0 auid=500 ses=3 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 msg='resrc=mem reason=update vm="fedora_12" uuid=51c6fc83-65a4-e627-b698-042b00145201 old-mem=786432 new-mem=524288: exe="/home/dummy/libvirt/daemon/.libs/lt-libvirtd" hostname=? addr=? terminal=pts/0 res=success'
Changes since v1[1]:
Rebased (assumes that Jirka's patch series[2] to clean up qemuCmdFlags
will go in first, otherwise you will get minor conflicts when applying)
Added some patches
Reworked the cgroup ACL patches to avoid spamming the audit log when
visiting a regular file instead of a device
[1] https://www.redhat.com/archives/libvir-list/2011-February/msg00565.html
[2] https://www.redhat.com/archives/libvir-list/2011-February/msg00985.html
Eric Blake (5):
cgroup: determine when skipping non-devices
audit: prepare qemu for listing vm in cgroup audits
audit: add qemu hooks for auditing cgroup events
audit: audit qemu memory and vcpu adjusments
audit: audit qemu pci and usb device passthrough
src/qemu/qemu_audit.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++-
src/qemu/qemu_audit.h | 23 ++++++-
src/qemu/qemu_cgroup.c | 95 +++++++++++++++----------
src/qemu/qemu_cgroup.h | 21 +++---
src/qemu/qemu_driver.c | 28 +++++--
src/qemu/qemu_hotplug.c | 35 ++++-----
src/util/cgroup.c | 7 +-
7 files changed, 305 insertions(+), 82 deletions(-)
--
1.7.4
13 years, 9 months
[libvirt] [PATCH] virExec: avoid uninitialized memory usage
by Eric Blake
valgrind warns:
==21079== Syscall param rt_sigaction(act->sa_mask) points to uninitialised byte(s)
==21079== at 0x329840F63E: __libc_sigaction (sigaction.c:67)
==21079== by 0x4E5A8E7: __virExec (util.c:661)
Regression introduced in commit ab07533e. Technically, sa_mask
shouldn't affect operation if sa_flags selects sa_handler, and
sa_handler selects SIG_IGN, but better safe than sorry.
* src/util/util.c (__virExec): Supply missing sigemptyset.
---
src/util/util.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/src/util/util.c b/src/util/util.c
index 965e96d..9bd7015 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -657,6 +657,7 @@ __virExec(const char *const*argv,
struct sigaction waxon, waxoff;
waxoff.sa_handler = SIG_IGN;
waxoff.sa_flags = 0;
+ sigemptyset(&waxoff.sa_mask);
memset(&waxon, 0, sizeof(waxon));
if (sigaction(SIGPIPE, &waxoff, &waxon) < 0) {
virReportSystemError(errno, "%s",
--
1.7.4
13 years, 9 months
[libvirt] [libvirt-snmp][PATCH] Add SNMP trap/notification support.
by Michal Privoznik
This patch adds support for domain lifecycle notification support
over SNMP traps. SNMP subagent monitors any domain events and when
something interesting happens, it sends trap.
Monitoring is done in a joinable thread using polling (used
domain-events example from libvirt) so we won't block agent itself.
Some debug info can be printed out by setting VERBOSE environment
variable.
---
Finally, we have a proof-of-concept implementation of SNMP trap.
Two new files were first generated using mib2c then edited, so be
careful when re-generating them.
Destination of traps is defined in snmpd.conf (trap2sink), and to
recieve them snmptrapd must be configured an up.
The idea behind is - create a thread in which we poll for domain
events. Once we receive event notification, we just fire up
trap sending.
I know it is a quite big patch, but nearly a half of it is just
domain event registration.
INSTALL | 4 +-
configure.ac | 7 +
src/LIBVIRT-MIB.txt | 9 +
src/Makefile.am | 9 +-
src/README.txt | 6 +
src/libvirtNotifications.c | 105 +++++++++
src/libvirtNotifications.h | 16 ++
src/libvirtSnmp.c | 541 +++++++++++++++++++++++++++++++++-----------
src/libvirtSnmp.h | 15 +-
9 files changed, 571 insertions(+), 141 deletions(-)
create mode 100644 src/libvirtNotifications.c
create mode 100644 src/libvirtNotifications.h
diff --git a/INSTALL b/INSTALL
index 31345d8..5c26d1e 100644
--- a/INSTALL
+++ b/INSTALL
@@ -18,10 +18,12 @@ Now it's time for make:
This compile all sources producing runable SNMP subagent
libvirtMib_subagent, which is installed right after.
But before we run it, we need to edit /etc/snmp/snmpd.conf
-so it contains this two lines:
+so it contains this four lines:
rwcommunity public
master agentx
+trap2sink localhost
+trapcommunity public
and then restart snmpd:
/etc/init.d/snmpd restart
diff --git a/configure.ac b/configure.ac
index a5fcb4e..58d26b2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -86,5 +86,12 @@ fi
AC_SUBST([MIB_DIR])
+dnl pthread
+PTHREAD_LIBS=
+AC_CHECK_HEADERS(pthread.h, [], [AC_MSG_ERROR([pthread.h required])])
+AC_CHECK_LIB(pthread, pthread_create, [PTHREAD_LIBS="-lpthread"])
+
+AC_SUBST([PTHREAD_LIBS])
+
AC_OUTPUT(Makefile src/Makefile libvirt-snmp.spec)
diff --git a/src/LIBVIRT-MIB.txt b/src/LIBVIRT-MIB.txt
index 607d441..932dec9 100644
--- a/src/LIBVIRT-MIB.txt
+++ b/src/LIBVIRT-MIB.txt
@@ -201,5 +201,14 @@ libvirtGuestGroup OBJECT-GROUP
guests."
::= { libvirtGroups 1 }
+libvirtGuestNotif NOTIFICATION-TYPE
+ STATUS current
+ OBJECTS { libvirtGuestName,
+ libvirtGuestUUID,
+ libvirtGuestState,
+ libvirtGuestRowStatus }
+ DESCRIPTION
+ "Guest lifecycle notification."
+ ::= { libvirtNotifications 1 }
END
diff --git a/src/Makefile.am b/src/Makefile.am
index c781e23..98fe562 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -9,19 +9,22 @@ AM_CFLAGS = \
AM_LDFLAGS = \
$(COVERAGE_LDFLAGS) \
- $(SNMP_LIBS)
+ $(SNMP_LIBS) \
+ $(PTHREAD_LIBS)
USER_SRCS = \
libvirtGuestTable_data_get.c \
libvirtGuestTable_data_set.c \
libvirtGuestTable_data_access.c \
- libvirtSnmp.c
+ libvirtSnmp.c \
+ libvirtNotifications.c
USER_HDRS = \
libvirtGuestTable_data_get.h \
libvirtGuestTable_data_set.h \
libvirtGuestTable_data_access.h \
- libvirtSnmp.h
+ libvirtSnmp.h \
+ libvirtNotifications.h
SRCS = \
${USER_SRCS} \
diff --git a/src/README.txt b/src/README.txt
index 22dd2af..9334a14 100644
--- a/src/README.txt
+++ b/src/README.txt
@@ -34,6 +34,10 @@ libvirtGuestTable*
- I've done everything necessary for simple read-write access.
- This code must be regenerated when the definition of libvirtGuestTable in the MIB file is changed! There is some automatic merging tool, which merges my changes with newly generated code, but I wouldn't rely on it.
+libvirtNotifications.[c|h]
+- The SNMP trap (notification) stuff
+- Generated by this command: 'MIBDIRS="+." MIBS="+LIBVIRT-MIB" mib2c -c mib2c.notify.conf libvirtNotifications'
+- and slightly modified (especially filling up trap variables which are going to be send).
Usage (tested on Fedora 14 and RHEL6)
-------------------------------------
@@ -44,6 +48,8 @@ $ make
2. use following /etc/snmp/snmpd.conf:
rwcommunity public
master agentx
+trap2sink localhost
+trapcommunity public
3. service snmpd start
diff --git a/src/libvirtNotifications.c b/src/libvirtNotifications.c
new file mode 100644
index 0000000..90402a6
--- /dev/null
+++ b/src/libvirtNotifications.c
@@ -0,0 +1,105 @@
+
+/*
+ * Note: this file originally auto-generated by mib2c using
+ * : mib2c.notify.conf 17455 2009-04-05 09:53:29Z magfr $
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include <string.h>
+#include "libvirtNotifications.h"
+#include "libvirtGuestTable_enums.h"
+
+static const oid snmptrap_oid[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 };
+
+int
+send_libvirtGuestNotif_trap(virDomainPtr dom)
+{
+ netsnmp_variable_list *var_list = NULL;
+ const oid libvirtGuestNotif_oid[] = { 1, 3, 6, 1, 4, 1, 12345, 0, 1 };
+ const oid libvirtGuestName_oid[] =
+ { 1, 3, 6, 1, 4, 1, 12345, 1, 1, 1, 2, 0 };
+ const oid libvirtGuestUUID_oid[] =
+ { 1, 3, 6, 1, 4, 1, 12345, 1, 1, 1, 1, 1 };
+ const oid libvirtGuestState_oid[] =
+ { 1, 3, 6, 1, 4, 1, 12345, 1, 1, 1, 3, 2 };
+ const oid libvirtGuestRowStatus_oid[] =
+ { 1, 3, 6, 1, 4, 1, 12345, 1, 1, 1, 9, 3 };
+
+
+ const char *domName = virDomainGetName(dom);
+ char domUUID[VIR_UUID_STRING_BUFLEN];
+ virDomainInfo info;
+ int rowstatus = ROWSTATUS_ACTIVE;
+
+ if (virDomainGetUUIDString(dom, domUUID)) {
+ fprintf(stderr, "Failed to get domain UUID\n");
+ return SNMP_ERR_GENERR;
+ }
+
+ if (virDomainGetInfo(dom, &info)) {
+ fprintf(stderr, "Failed to get domain info\n");
+ return SNMP_ERR_GENERR;
+ }
+
+ /*
+ * If domain is shuting down, row in libvirtGuestTable will
+ * not be accessible anymore.
+ */
+ switch (info.state) {
+ case VIR_DOMAIN_SHUTDOWN:
+ case VIR_DOMAIN_SHUTOFF:
+ case VIR_DOMAIN_CRASHED:
+ rowstatus = ROWSTATUS_NOTINSERVICE;
+ break;
+
+ default:
+ rowstatus = ROWSTATUS_ACTIVE;
+ break;
+ };
+
+ /*
+ * Set the snmpTrapOid.0 value
+ */
+ snmp_varlist_add_variable(&var_list,
+ snmptrap_oid, OID_LENGTH(snmptrap_oid),
+ ASN_OBJECT_ID,
+ libvirtGuestNotif_oid,
+ sizeof(libvirtGuestNotif_oid));
+
+ /*
+ * Add any objects from the trap definition
+ */
+ snmp_varlist_add_variable(&var_list,
+ libvirtGuestName_oid,
+ OID_LENGTH(libvirtGuestName_oid),
+ ASN_OCTET_STR, domName, strlen(domName));
+ snmp_varlist_add_variable(&var_list,
+ libvirtGuestUUID_oid,
+ OID_LENGTH(libvirtGuestUUID_oid),
+ ASN_OCTET_STR, domUUID, sizeof(domUUID));
+ snmp_varlist_add_variable(&var_list,
+ libvirtGuestState_oid,
+ OID_LENGTH(libvirtGuestState_oid),
+ ASN_INTEGER,
+ (u_char *) & rowstatus, sizeof(rowstatus));
+ snmp_varlist_add_variable(&var_list,
+ libvirtGuestRowStatus_oid,
+ OID_LENGTH(libvirtGuestRowStatus_oid),
+ ASN_INTEGER,
+ (u_char *) & info.state, sizeof(info.state));
+
+ /*
+ * Add any extra (optional) objects here
+ */
+
+ /*
+ * Send the trap to the list of configured destinations
+ * and clean up
+ */
+ send_v2trap(var_list);
+ snmp_free_varbind(var_list);
+
+ return SNMP_ERR_NOERROR;
+}
diff --git a/src/libvirtNotifications.h b/src/libvirtNotifications.h
new file mode 100644
index 0000000..aed4560
--- /dev/null
+++ b/src/libvirtNotifications.h
@@ -0,0 +1,16 @@
+
+/*
+ * Note: this file originally auto-generated by mib2c using
+ * : mib2c.notify.conf 17455 2009-04-05 09:53:29Z magfr $
+ */
+#ifndef LIBVIRTNOTIFICATIONS_H
+#define LIBVIRTNOTIFICATIONS_H
+
+#include "libvirtSnmp.h"
+
+/*
+ * function declarations
+ */
+int send_libvirtGuestNotif_trap(virDomainPtr dom);
+
+#endif /* LIBVIRTNOTIFICATIONS_H */
diff --git a/src/libvirtSnmp.c b/src/libvirtSnmp.c
index c15431a..4698f89 100644
--- a/src/libvirtSnmp.c
+++ b/src/libvirtSnmp.c
@@ -1,3 +1,4 @@
+
/* This file contains trivial example code to connect to the running
* hypervisor and gather a few bits of information. */
@@ -9,12 +10,171 @@ gcc -lvirt activeguests.c
#include <stdio.h>
#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/poll.h>
+#include <pthread.h>
+#include <signal.h>
#include "libvirtSnmp.h"
+
/* include our MIB structures*/
#include "libvirtGuestTable.h"
+#include "libvirtNotifications.h"
+
+#define DEBUG0(fmt) if (verbose) printf("%s:%d :: " fmt "\n", \
+ __func__, __LINE__)
+#define DEBUG(fmt, ...) if (verbose) printf("%s:%d: " fmt "\n", \
+ __func__, __LINE__, __VA_ARGS__)
+#define STREQ(a,b) (strcmp(a,b) == 0)
+#ifndef ATTRIBUTE_UNUSED
+#define ATTRIBUTE_UNUSED __attribute__((__unused__))
+#endif
+
+int verbose = 0;
virConnectPtr conn;
+int callbackRet = -1;
+int run = 1;
+pthread_t poll_thread;
+
+/* handle globals */
+int h_fd = 0;
+virEventHandleType h_event = 0;
+virEventHandleCallback h_cb = NULL;
+virFreeCallback h_ff = NULL;
+void *h_opaque = NULL;
+
+/* timeout globals */
+#define TIMEOUT_MS 1000
+int t_active = 0;
+int t_timeout = -1;
+virEventTimeoutCallback t_cb = NULL;
+virFreeCallback t_ff = NULL;
+void *t_opaque = NULL;
+
+
+static int
+domainEventCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom, int event, int detail,
+ void *opaque ATTRIBUTE_UNUSED)
+{
+ DEBUG("%s EVENT: Domain %s(%d) %d %d\n", __func__,
+ virDomainGetName(dom), virDomainGetID(dom), event, detail);
+
+ send_libvirtGuestNotif_trap(dom);
+ return 0;
+}
+
+static void
+myFreeFunc(void *opaque)
+{
+ if (opaque)
+ free(opaque);
+}
+
+/* EventImpl Functions */
+int
+myEventHandleTypeToPollEvent(virEventHandleType events)
+{
+ int ret = 0;
+
+ if (events & VIR_EVENT_HANDLE_READABLE)
+ ret |= POLLIN;
+ if (events & VIR_EVENT_HANDLE_WRITABLE)
+ ret |= POLLOUT;
+ if (events & VIR_EVENT_HANDLE_ERROR)
+ ret |= POLLERR;
+ if (events & VIR_EVENT_HANDLE_HANGUP)
+ ret |= POLLHUP;
+ return ret;
+}
+
+virEventHandleType
+myPollEventToEventHandleType(int events)
+{
+ virEventHandleType ret = 0;
+
+ if (events & POLLIN)
+ ret |= VIR_EVENT_HANDLE_READABLE;
+ if (events & POLLOUT)
+ ret |= VIR_EVENT_HANDLE_WRITABLE;
+ if (events & POLLERR)
+ ret |= VIR_EVENT_HANDLE_ERROR;
+ if (events & POLLHUP)
+ ret |= VIR_EVENT_HANDLE_HANGUP;
+ return ret;
+}
+
+int
+myEventAddHandleFunc(int fd, int event,
+ virEventHandleCallback cb,
+ void *opaque, virFreeCallback ff)
+{
+ DEBUG("Add handle %d %d %p %p", fd, event, cb, opaque);
+ h_fd = fd;
+ h_event = myEventHandleTypeToPollEvent(event);
+ h_cb = cb;
+ h_ff = ff;
+ h_opaque = opaque;
+ return 0;
+}
+
+void
+myEventUpdateHandleFunc(int fd, int event)
+{
+ DEBUG("Updated Handle %d %d", fd, event);
+ h_event = myEventHandleTypeToPollEvent(event);
+ return;
+}
+
+int
+myEventRemoveHandleFunc(int fd)
+{
+ DEBUG("Removed Handle %d", fd);
+ h_fd = 0;
+ if (h_ff)
+ (h_ff) (h_opaque);
+ return 0;
+}
+
+int
+myEventAddTimeoutFunc(int timeout,
+ virEventTimeoutCallback cb,
+ void *opaque, virFreeCallback ff)
+{
+ DEBUG("Adding Timeout %d %p %p", timeout, cb, opaque);
+ t_active = 1;
+ t_timeout = timeout;
+ t_cb = cb;
+ t_ff = ff;
+ t_opaque = opaque;
+ return 0;
+}
+
+void
+myEventUpdateTimeoutFunc(int timer ATTRIBUTE_UNUSED, int timeout)
+{
+ /*DEBUG("Timeout updated %d %d", timer, timeout); */
+ t_timeout = timeout;
+}
+
+int
+myEventRemoveTimeoutFunc(int timer)
+{
+ DEBUG("Timeout removed %d", timer);
+ t_active = 0;
+ if (t_ff)
+ (t_ff) (t_opaque);
+ return 0;
+}
+
+/* Signal trap function */
+static void
+stop(int sig)
+{
+ run = 0;
+}
+
static void
showError(virConnectPtr conn)
@@ -31,23 +191,24 @@ showError(virConnectPtr conn)
ret = virConnCopyLastError(conn, err);
switch (ret) {
- case 0:
- snmp_log(LOG_ERR, "No error found\n");
- break;
-
- case -1:
- snmp_log(LOG_ERR, "Parameter error when attempting to get last error\n");
- break;
-
- default:
- snmp_log(LOG_ERR, "libvirt reported: \"%s\"\n", err->message);
- break;
+ case 0:
+ snmp_log(LOG_ERR, "No error found\n");
+ break;
+
+ case -1:
+ snmp_log(LOG_ERR,
+ "Parameter error when attempting to get last error\n");
+ break;
+
+ default:
+ snmp_log(LOG_ERR, "libvirt reported: \"%s\"\n", err->message);
+ break;
}
virResetError(err);
free(err);
-out:
+ out:
return;
}
@@ -55,7 +216,7 @@ out:
* Populate libvirtGuestTable into given container.
*/
int
-libvirtSnmpLoadGuests(netsnmp_container *container)
+libvirtSnmpLoadGuests(netsnmp_container * container)
{
int ret = 0, i, numIds, numActiveDomains;
int *idList = NULL;
@@ -80,9 +241,7 @@ libvirtSnmpLoadGuests(netsnmp_container *container)
goto out;
}
- numIds = virConnectListDomains(conn,
- idList,
- numActiveDomains);
+ numIds = virConnectListDomains(conn, idList, numActiveDomains);
if (-1 == numIds) {
ret = -1;
@@ -91,14 +250,14 @@ libvirtSnmpLoadGuests(netsnmp_container *container)
goto out;
}
- for (i = 0 ; i < numIds ; i++) {
- unsigned char uuid[16];
+ for (i = 0; i < numIds; i++) {
+ unsigned char uuid[16];
domain = virDomainLookupByID(conn, *(idList + i));
if (NULL == domain) {
printf("Failed to lookup domain\n");
showError(conn);
- ret = -1;
+ ret = -1;
goto out;
}
@@ -106,47 +265,49 @@ libvirtSnmpLoadGuests(netsnmp_container *container)
printf("Failed to get domain info\n");
showError(conn);
virDomainFree(domain);
- ret = -1;
+ ret = -1;
goto out;
}
/* create new row in the container */
row_ctx = libvirtGuestTable_allocate_rowreq_ctx(NULL);
if (!row_ctx) {
- virDomainFree(domain);
- snmp_log(LOG_ERR, "Error creating row");
- ret = -1;
- goto out;
+ virDomainFree(domain);
+ snmp_log(LOG_ERR, "Error creating row");
+ ret = -1;
+ goto out;
}
/* set the index of the row */
ret = virDomainGetUUID(domain, uuid);
if (ret) {
- virDomainFree(domain);
- snmp_log(LOG_ERR, "Cannot get UUID");
- libvirtGuestTable_release_rowreq_ctx(row_ctx);
- ret = -1;
- goto out;
- }
- if (MFD_SUCCESS != libvirtGuestTable_indexes_set(row_ctx, (char*) uuid,
- sizeof(uuid))) {
- virDomainFree(domain);
- snmp_log(LOG_ERR, "Error setting row index");
- libvirtGuestTable_release_rowreq_ctx(row_ctx);
- ret = -1;
- goto out;
+ virDomainFree(domain);
+ snmp_log(LOG_ERR, "Cannot get UUID");
+ libvirtGuestTable_release_rowreq_ctx(row_ctx);
+ ret = -1;
+ goto out;
+ }
+ if (MFD_SUCCESS !=
+ libvirtGuestTable_indexes_set(row_ctx, (char *) uuid,
+ sizeof(uuid))) {
+ virDomainFree(domain);
+ snmp_log(LOG_ERR, "Error setting row index");
+ libvirtGuestTable_release_rowreq_ctx(row_ctx);
+ ret = -1;
+ goto out;
}
/* set the data */
name = virDomainGetName(domain);
if (name)
- row_ctx->data.libvirtGuestName = strdup(name);
+ row_ctx->data.libvirtGuestName = strdup(name);
else
- row_ctx->data.libvirtGuestName = strdup("");
+ row_ctx->data.libvirtGuestName = strdup("");
if (!row_ctx->data.libvirtGuestName) {
- snmp_log(LOG_ERR, "Not enough memory for domain name '%s'", name);
- libvirtGuestTable_release_rowreq_ctx(row_ctx);
- ret = -1;
- goto out;
+ snmp_log(LOG_ERR, "Not enough memory for domain name '%s'",
+ name);
+ libvirtGuestTable_release_rowreq_ctx(row_ctx);
+ ret = -1;
+ goto out;
}
row_ctx->data.libvirtGuestState = info.state;
@@ -162,25 +323,133 @@ libvirtSnmpLoadGuests(netsnmp_container *container)
ret = CONTAINER_INSERT(container, row_ctx);
if (ret) {
- snmp_log(LOG_ERR, "Cannot insert domain '%s' to container", name);
- libvirtGuestTable_release_rowreq_ctx(row_ctx);
- ret = -1;
- goto out;
- }
+ snmp_log(LOG_ERR, "Cannot insert domain '%s' to container",
+ name);
+ libvirtGuestTable_release_rowreq_ctx(row_ctx);
+ ret = -1;
+ goto out;
+ }
}
-out:
+ out:
free(idList);
return ret;
}
-int libvirtSnmpInit(void)
+/* Polling thread function */
+void *
+pollingThreadFunc(void *foo)
{
+ int sts;
+
+ while (run) {
+ struct pollfd pfd = {.fd = h_fd,
+ .events = h_event,
+ .revents = 0
+ };
+
+ sts = poll(&pfd, 1, TIMEOUT_MS);
+
+ /* if t_timeout < 0 then t_cb must not be called */
+ if (t_cb && t_active && t_timeout >= 0) {
+ t_cb(t_timeout, t_opaque);
+ }
+
+ if (sts == 0) {
+ /* DEBUG0("Poll timeout"); */
+ continue;
+ }
+ if (sts < 0) {
+ DEBUG0("Poll failed");
+ continue;
+ }
+ if (pfd.revents & POLLHUP) {
+ DEBUG0("Reset by peer");
+ pthread_exit(NULL);
+ }
+
+ if (h_cb) {
+ h_cb(0,
+ h_fd,
+ myPollEventToEventHandleType(pfd.revents & h_event),
+ h_opaque);
+ }
+
+ }
+
+ pthread_exit(NULL);
+}
+
+/* Function to register domain lifecycle events collection */
+int
+libvirtRegisterEvents(virConnectPtr conn)
+{
+ struct sigaction action_stop;
+ pthread_attr_t thread_attr;
+
+ memset(&action_stop, 0, sizeof action_stop);
+
+ action_stop.sa_handler = stop;
+
+ sigaction(SIGTERM, &action_stop, NULL);
+ sigaction(SIGINT, &action_stop, NULL);
+
+ DEBUG0("Registering domain event callback");
+
+ callbackRet = virConnectDomainEventRegisterAny(conn, NULL,
+ VIR_DOMAIN_EVENT_ID_LIFECYCLE,
+ VIR_DOMAIN_EVENT_CALLBACK
+ (domainEventCallback),
+ NULL, myFreeFunc);
+
+ if (callbackRet == -1)
+ return -1;
+
+ /* we need a thread to poll for events */
+ pthread_attr_init(&thread_attr);
+ pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
+
+ if (pthread_create
+ (&poll_thread, &thread_attr, pollingThreadFunc, NULL))
+ return -1;
+
+ pthread_attr_destroy(&thread_attr);
+
+ return 0;
+}
+
+/* Unregister domain events collection */
+int
+libvirtUnregisterEvents(virConnectPtr conn)
+{
+ void *status;
+
+ pthread_join(poll_thread, &status);
+ virConnectDomainEventDeregisterAny(conn, callbackRet);
+ callbackRet = -1;
+ return 0;
+}
+
+int
+libvirtSnmpInit(void)
+{
+ char *verbose_env = getenv("VERBOSE");
+
+ verbose = verbose_env != NULL;
+
+ /* if we don't already have registered callback */
+ if (callbackRet == -1)
+ virEventRegisterImpl(myEventAddHandleFunc,
+ myEventUpdateHandleFunc,
+ myEventRemoveHandleFunc,
+ myEventAddTimeoutFunc,
+ myEventUpdateTimeoutFunc,
+ myEventRemoveTimeoutFunc);
+
/* virConnectOpenAuth is called here with all default parameters,
- * except, possibly, the URI of the hypervisor. */
- /* TODO: configure the URI */
- /* Use libvirt env variable LIBVIRT_DEFAULT_URI by default*/
+ * /* TODO: configure the URI */
+ /* Use libvirt env variable LIBVIRT_DEFAULT_URI by default */
conn = virConnectOpenAuth(NULL, virConnectAuthPtrDefault, 0);
if (NULL == conn) {
@@ -188,11 +457,22 @@ int libvirtSnmpInit(void)
showError(conn);
return -1;
}
+
+ if ((callbackRet == -1) && libvirtRegisterEvents(conn)) {
+ printf("Unable to register domain events\n");
+ return -1;
+ }
+
return 0;
}
-void libvirtSnmpShutdown(void)
+void
+libvirtSnmpShutdown(void)
{
+ if (libvirtUnregisterEvents(conn)) {
+ printf("Failed to unregister domain events\n");
+ }
+
if (0 != virConnectClose(conn)) {
printf("Failed to disconnect from hypervisor\n");
showError(conn);
@@ -202,95 +482,98 @@ void libvirtSnmpShutdown(void)
int
libvirtSnmpCheckDomainExists(unsigned char *uuid)
{
- virDomainPtr d = virDomainLookupByUUID(conn, uuid);
- if (d == NULL)
- return -1;
+ virDomainPtr d = virDomainLookupByUUID(conn, uuid);
- virDomainFree(d);
- return 0;
+ if (d == NULL)
+ return -1;
+
+ virDomainFree(d);
+ return 0;
}
int
libvirtSnmpCreate(unsigned char *uuid, int state)
{
- virDomainPtr dom;
- int ret;
- unsigned int flags = 0;
-
- dom = virDomainLookupByUUID(conn, uuid);
- if (dom == NULL) {
- printf("Cannot find domain to create\n");
- return -1;
- }
-
- switch(state) {
- case VIR_DOMAIN_RUNNING:
- flags = 0;
- break;
- case VIR_DOMAIN_PAUSED:
- flags = VIR_DOMAIN_START_PAUSED;
- break;
- default:
- printf("Can't create domain with state %d\n", flags);
- return -1;
- }
-
- ret = virDomainCreateWithFlags(dom, flags);
- if (ret) {
- showError(conn);
- }
- virDomainFree(dom);
- return ret;
+ virDomainPtr dom;
+ int ret;
+ unsigned int flags = 0;
+
+ dom = virDomainLookupByUUID(conn, uuid);
+ if (dom == NULL) {
+ printf("Cannot find domain to create\n");
+ return -1;
+ }
+
+ switch (state) {
+ case VIR_DOMAIN_RUNNING:
+ flags = 0;
+ break;
+ case VIR_DOMAIN_PAUSED:
+ flags = VIR_DOMAIN_START_PAUSED;
+ break;
+ default:
+ printf("Can't create domain with state %d\n", flags);
+ return -1;
+ }
+
+ ret = virDomainCreateWithFlags(dom, flags);
+ if (ret) {
+ showError(conn);
+ }
+ virDomainFree(dom);
+ return ret;
}
int
libvirtSnmpDestroy(unsigned char *uuid)
{
- virDomainPtr dom;
- int ret;
-
- dom = virDomainLookupByUUID(conn, uuid);
- if (dom == NULL) {
- printf("Cannot find domain to destroy\n");
- return -1;
- }
-
- ret = virDomainDestroy(dom);
- if (ret) {
- showError(conn);
- }
- virDomainFree(dom);
- return ret;
+ virDomainPtr dom;
+ int ret;
+
+ dom = virDomainLookupByUUID(conn, uuid);
+ if (dom == NULL) {
+ printf("Cannot find domain to destroy\n");
+ return -1;
+ }
+
+ ret = virDomainDestroy(dom);
+ if (ret) {
+ showError(conn);
+ }
+ virDomainFree(dom);
+ return ret;
}
int
libvirtSnmpChangeState(unsigned char *uuid, int newstate, int oldstate)
{
- virDomainPtr dom;
- int ret = 0;
-
- dom = virDomainLookupByUUID(conn, uuid);
- if (dom == NULL) {
- printf("Cannot find domain to change\n");
- return 1;
- }
-
- if (oldstate == VIR_DOMAIN_RUNNING && newstate == VIR_DOMAIN_PAUSED)
- ret = virDomainSuspend(dom);
- else if (oldstate == VIR_DOMAIN_PAUSED && newstate == VIR_DOMAIN_RUNNING)
- ret = virDomainResume(dom);
- else if (newstate == VIR_DOMAIN_SHUTDOWN)
- ret = virDomainShutdown(dom);
- else {
- printf("Wrong state transition from %d to %d\n", oldstate, newstate);
- ret = -1;
- goto out;
- }
-
- if (ret != 0) {
- showError(conn);
- }
-out:
- virDomainFree(dom);
- return ret;
+ virDomainPtr dom;
+ int ret = 0;
+
+ dom = virDomainLookupByUUID(conn, uuid);
+ if (dom == NULL) {
+ printf("Cannot find domain to change\n");
+ return 1;
+ }
+
+ if (oldstate == VIR_DOMAIN_RUNNING && newstate == VIR_DOMAIN_PAUSED)
+ ret = virDomainSuspend(dom);
+ else if (oldstate == VIR_DOMAIN_PAUSED
+ && newstate == VIR_DOMAIN_RUNNING)
+ ret = virDomainResume(dom);
+ else if (newstate == VIR_DOMAIN_SHUTDOWN)
+ ret = virDomainShutdown(dom);
+ else {
+ printf("Wrong state transition from %d to %d\n", oldstate,
+ newstate);
+ ret = -1;
+ goto out;
+ }
+
+ if (ret != 0) {
+ showError(conn);
+ }
+ out:
+ virDomainFree(dom);
+ return ret;
}
diff --git a/src/libvirtSnmp.h b/src/libvirtSnmp.h
index 4ac6130..5812c91 100644
--- a/src/libvirtSnmp.h
+++ b/src/libvirtSnmp.h
@@ -14,29 +14,28 @@
* Populate libvirtGuestTable into given container.
*/
extern int
-libvirtSnmpLoadGuests(netsnmp_container *container);
+ libvirtSnmpLoadGuests(netsnmp_container * container);
extern int
-libvirtSnmpInit(void);
+ libvirtSnmpInit(void);
extern void
-libvirtSnmpShutdown(void);
+ libvirtSnmpShutdown(void);
/**
* Check that domain with given UUID exists.
* Return 0 if so, -1 if not.
*/
extern int
-libvirtSnmpCheckDomainExists(unsigned char *uuid);
+ libvirtSnmpCheckDomainExists(unsigned char *uuid);
extern int
-libvirtSnmpCreate(unsigned char *uuid, int state);
+ libvirtSnmpCreate(unsigned char *uuid, int state);
extern int
-libvirtSnmpDestroy(unsigned char *uuid);
+ libvirtSnmpDestroy(unsigned char *uuid);
extern int
-libvirtSnmpChangeState(unsigned char *uuid, int newstate, int oldstate);
+ libvirtSnmpChangeState(unsigned char *uuid, int newstate, int oldstate);
#endif /* __VIR_SNMP_H__ */
-
--
1.7.3.5
13 years, 9 months
[libvirt] [PATCH] Make commandtest more robust wrt its execution environment
by Daniel P. Berrange
When executed from cron, commandtest would failure to correctly
identified daemon processes. Set session ID and process group
IDs at startup to ensure we have a consistent environment to
run in.
* tests/commandtest.c: Call setsid() and setpgid()
---
tests/commandtest.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/tests/commandtest.c b/tests/commandtest.c
index 7157c51..dc2f8a1 100644
--- a/tests/commandtest.c
+++ b/tests/commandtest.c
@@ -730,6 +730,9 @@ mymain(int argc, char **argv)
if (chdir("/tmp") < 0)
return(EXIT_FAILURE);
+ setpgid(0, 0);
+ setsid();
+
/* Kill off any inherited fds that might interfere with our
* testing. */
fd = 3;
--
1.7.4
13 years, 9 months
[libvirt] [Xen-devel] Re: [PATCH V2] Add libxenlight driver
by Ian Jackson
Paolo Bonzini writes ("[Xen-devel] Re: [PATCH V2] Add libxenlight driver"):
> On 02/23/2011 03:56 AM, Jim Fehlig wrote:
> > Add a new xen driver based on libxenlight [1], which is the primary
> > toolstack starting with Xen 4.1.0. The driver is stateful, runs
> > privileged only, and is accessed with libxl:/// URI.
>
> Why not let the user keep xen:/// ?
Because for now you want to be able to have both drivers. Unless,
perhaps, it's somehow possible to select between them at runtime for
the same URI scheme ?
Ian.
13 years, 9 months
[libvirt] [PATCH v2 0/7] Switch over qemu command line capabilities to virBitmap
by Jiri Denemark
There are two main reasons behind this patchset:
- we are getting very close to 64 flags which is the maximum we can use with
unsigned long long
- by using LL constants in enum we already violates C99 constraint that enum
values have to fit into int
Patches 3/7 and 5/7 are fully and 4/7 mostly mechanical. 6/7 and 7/7 need to be
squashed into a single patch but are provided separately for easier review.
Changes in version 2 are described in each patch separately.
Jiri Denemark (7):
util: Use unsigned long as a base type for virBitmap
util: Add API for converting virBitmap into printable string
qemu: Rename QEMUD_CMD_FLAG_* to QEMU_CAPS_*
qemu: Use helper functions for handling cmd line capabilities
qemu: Rename qemud\?CmdFlags to qemuCaps
qemu: Switch over command line capabilities to virBitmap
tests: Use virBitmap for qemu command line caps
cfg.mk | 3 +-
src/libvirt_private.syms | 1 +
src/qemu/qemu_capabilities.c | 238 +++++++++-----
src/qemu/qemu_capabilities.h | 152 +++++----
src/qemu/qemu_command.c | 392 +++++++++++-----------
src/qemu/qemu_command.h | 30 +-
src/qemu/qemu_driver.c | 48 ++--
src/qemu/qemu_hotplug.c | 162 +++++-----
src/qemu/qemu_hotplug.h | 32 +-
src/qemu/qemu_migration.c | 22 +-
src/qemu/qemu_process.c | 29 +-
src/util/bitmap.c | 51 +++-
src/util/bitmap.h | 3 +
tests/qemuargv2xmltest.c | 2 +-
tests/qemuhelptest.c | 747 +++++++++++++++++++++---------------------
tests/qemuxml2argvtest.c | 474 +++++++++++++-------------
16 files changed, 1263 insertions(+), 1123 deletions(-)
--
1.7.4.1
13 years, 9 months
[libvirt] [PATCH 1/2] libvirt/qemu - support updating inactive domains (take 2)
by KAMEZAWA Hiroyuki
>From d6c65102224c493f67008b6521b0115d798f5a67 Mon Sep 17 00:00:00 2001
From: KAMEZAWA Hiroyuki <kamezawa(a)bluextal.(none)>
Date: Thu, 24 Feb 2011 12:14:25 +0900
Subject: [PATCH 1/2] libvirt/qemu - support updating inactive domains.
Now, virsh attach-disk/detach-disk has --persistent option and
it can update XML definition of inactive domains. But, it's only
supported in Xen.
This patch adds support for attach-disk/detach-disk for qemu.
Changelog v1->v2:
- fixed TABs
- fixed PCI address assignment for VIRTIO driver.
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu(a)jp.fujitsu.com>
---
src/qemu/qemu_driver.c | 168 +++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 158 insertions(+), 10 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 8b15a3e..e75478a 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4085,14 +4085,164 @@ cleanup:
return ret;
}
-static int qemudDomainAttachDeviceFlags(virDomainPtr dom,
+static int qemuDomainFindDiskByName(virDomainDefPtr vmdef, const char *name)
+{
+ virDomainDiskDefPtr vdisk;
+ int i;
+
+ for (i = 0; i < vmdef->ndisks; i++) {
+ vdisk = vmdef->disks[i];
+ if (!strcmp(vdisk->dst, name))
+ return i;
+ }
+ return -1;
+}
+/*
+ * Attach a device given by XML, the change will be persistent
+ * and domain XML definition file is updated.
+ */
+static int qemuDomainAttachDevicePersistent(virDomainDefPtr vmdef,
+ virDomainDeviceDefPtr newdev)
+{
+ virDomainDiskDefPtr disk;
+
+ /* At first, check device confliction */
+ switch(newdev->type) {
+ case VIR_DOMAIN_DEVICE_DISK:
+ disk = newdev->data.disk;
+ if (qemuDomainFindDiskByName(vmdef, disk->dst) >= 0) {
+ qemuReportError(VIR_ERR_INVALID_ARG,
+ _("target %s already exists."), disk->dst);
+ return -1;
+ }
+
+ if (virDomainDiskInsert(vmdef, disk)) {
+ virReportOOMError();
+ return -1;
+ }
+ if (disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) {
+ /*
+ * Address/Drive information is NULL. If virtio, PCI address
+ * shoule be fixed. Other devices as IDE, SCSI...will get ID
+ * automatically
+ */
+ qemuDomainAssignPCIAddresses(vmdef);
+
+ }
+ newdev->data.disk = NULL;
+ break;
+ default:
+ qemuReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("Sorry, the device is not suppored for now"));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int qemuDomainDetachDevicePersistent(virDomainDefPtr vmdef,
+ virDomainDeviceDefPtr device)
+{
+ int x;
+ virDomainDiskDefPtr disk;
+
+ switch(device->type) {
+ case VIR_DOMAIN_DEVICE_DISK:
+ disk = device->data.disk;
+ x = qemuDomainFindDiskByName(vmdef, disk->dst);
+ if (x < 0) {
+ qemuReportError(VIR_ERR_INVALID_ARG,
+ _("target %s doesn't exist."), disk->dst);
+ return -1;
+ }
+ virDomainDiskRemove(vmdef, x);
+ break;
+ default:
+ qemuReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("Sorry, the device is not suppored for now"));
+ return -1;
+ }
+ return 0;
+}
+
+static int qemuDomainModifyDevicePersistent(virDomainPtr dom,
const char *xml,
- unsigned int flags) {
- if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
- qemuReportError(VIR_ERR_OPERATION_INVALID,
- "%s", _("cannot modify the persistent configuration of a domain"));
+ unsigned int attach)
+{
+ struct qemud_driver *driver;
+ virDomainDeviceDefPtr device;
+ virDomainDefPtr vmdef;
+ virDomainObjPtr vm;
+ int ret = -1;
+
+ if (!dom || !dom->conn || !dom->name || !xml) {
+ qemuReportError(VIR_ERR_INVALID_ARG,
+ _("internal error : %s"), __FUNCTION__);
+ return -1;
+ }
+
+ if (dom->conn->flags & VIR_CONNECT_RO)
return -1;
+
+ driver = dom->conn->privateData;
+ qemuDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+ if (!vm) {
+ qemuReportError(VIR_ERR_NO_DOMAIN, _("cannot find domain '%s'"),
+ dom->name);
+ goto unlock_out;
+ }
+
+ if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) {
+ /*
+ * For now, just allow updating inactive domains. Further development
+ * will allow updating both active domain and its config file at
+ * the same time.
+ */
+ qemuReportError(VIR_ERR_INVALID_ARG,
+ _("cannot update alive domain : %s"), __FUNCTION__);
+ goto endjob;
+ }
+ vmdef = virDomainObjGetPersistentDef(driver->caps, vm);
+
+ if (!vmdef)
+ goto endjob;
+
+ device = virDomainDeviceDefParse(driver->caps,
+ vmdef, xml, VIR_DOMAIN_XML_INACTIVE);
+ if (!device)
+ goto endjob;
+
+ if (attach) {
+ ret = qemuDomainAttachDevicePersistent(vmdef, device);
+ if (ret < 0)
+ goto out;
+ } else {
+ ret = qemuDomainDetachDevicePersistent(vmdef, device);
+ if (ret < 0)
+ goto out;
}
+ ret = virDomainSaveConfig(driver->configDir, vmdef);
+
+out:
+ virDomainDeviceDefFree(device);
+endjob:
+ if (qemuDomainObjEndJob(vm) == 0)
+ vm = NULL;
+ if (vm)
+ virDomainObjUnlock(vm);
+ /* Note: insert of newdev is done by copy */
+unlock_out:
+ qemuDriverUnlock(driver);
+ return ret;
+}
+
+static int qemudDomainAttachDeviceFlags(virDomainPtr dom,
+ const char *xml,
+ unsigned int flags) {
+
+ if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG)
+ return qemuDomainModifyDevicePersistent(dom, xml, 1);
return qemudDomainAttachDevice(dom, xml);
}
@@ -4306,11 +4456,9 @@ cleanup:
static int qemudDomainDetachDeviceFlags(virDomainPtr dom,
const char *xml,
unsigned int flags) {
- if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
- qemuReportError(VIR_ERR_OPERATION_INVALID,
- "%s", _("cannot modify the persistent configuration of a domain"));
- return -1;
- }
+
+ if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG)
+ return qemuDomainModifyDevicePersistent(dom, xml, 0);
return qemudDomainDetachDevice(dom, xml);
}
--
1.7.1
13 years, 9 months