[libvirt] Handle reboots in LXC driver

This is a series which makes it possible to properly handle reboots in the LXC driver. The lxc_controller can detect if the container asked for a reboot by looking at the exit status of the init process & checking for SIGHUP as the termination signal. The fun is that the lxc controller cannot actually restart the container itself though. It lacks the permissions todo so (it dropped all capabilities), and it is not able to configure the veth devices either. So we introduce an RPC protocol with an event notification on shutdown, to tell libvirtd that a restart is needed This applies on top of https://www.redhat.com/archives/libvir-list/2012-July/msg01309.html

From: "Daniel P. Berrange" <berrange@redhat.com> In the socket event handler for the RPC client we must deal with read/write events, before checking for EOF, otherwise we might close the socket before we've read & acted upon the last RPC messages Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/rpc/virnetclient.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c index aba58ec..f5d8189 100644 --- a/src/rpc/virnetclient.c +++ b/src/rpc/virnetclient.c @@ -1694,16 +1694,6 @@ void virNetClientIncomingEvent(virNetSocketPtr sock, VIR_DEBUG("Event fired %p %d", sock, events); - if (events & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR)) { - VIR_DEBUG("%s : VIR_EVENT_HANDLE_HANGUP or " - "VIR_EVENT_HANDLE_ERROR encountered", __FUNCTION__); - virNetClientMarkClose(client, - (events & VIR_EVENT_HANDLE_HANGUP) ? - VIR_CONNECT_CLOSE_REASON_EOF : - VIR_CONNECT_CLOSE_REASON_ERROR); - goto done; - } - if (events & VIR_EVENT_HANDLE_WRITABLE) { if (virNetClientIOHandleOutput(client) < 0) virNetClientMarkClose(client, VIR_CONNECT_CLOSE_REASON_ERROR); @@ -1714,6 +1704,16 @@ void virNetClientIncomingEvent(virNetSocketPtr sock, virNetClientMarkClose(client, VIR_CONNECT_CLOSE_REASON_ERROR); } + if (events & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR)) { + VIR_DEBUG("%s : VIR_EVENT_HANDLE_HANGUP or " + "VIR_EVENT_HANDLE_ERROR encountered", __FUNCTION__); + virNetClientMarkClose(client, + (events & VIR_EVENT_HANDLE_HANGUP) ? + VIR_CONNECT_CLOSE_REASON_EOF : + VIR_CONNECT_CLOSE_REASON_ERROR); + goto done; + } + /* Remove completed calls or signal their threads. */ virNetClientCallRemovePredicate(&client->waitDispatch, virNetClientIOEventLoopRemoveDone, -- 1.7.10.4

On Tue, Jul 24, 2012 at 14:22:43 +0100, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
In the socket event handler for the RPC client we must deal with read/write events, before checking for EOF, otherwise we might close the socket before we've read & acted upon the last RPC messages
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/rpc/virnetclient.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c index aba58ec..f5d8189 100644 --- a/src/rpc/virnetclient.c +++ b/src/rpc/virnetclient.c @@ -1694,16 +1694,6 @@ void virNetClientIncomingEvent(virNetSocketPtr sock,
VIR_DEBUG("Event fired %p %d", sock, events);
- if (events & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR)) { - VIR_DEBUG("%s : VIR_EVENT_HANDLE_HANGUP or " - "VIR_EVENT_HANDLE_ERROR encountered", __FUNCTION__); - virNetClientMarkClose(client, - (events & VIR_EVENT_HANDLE_HANGUP) ? - VIR_CONNECT_CLOSE_REASON_EOF : - VIR_CONNECT_CLOSE_REASON_ERROR); - goto done; - } - if (events & VIR_EVENT_HANDLE_WRITABLE) { if (virNetClientIOHandleOutput(client) < 0) virNetClientMarkClose(client, VIR_CONNECT_CLOSE_REASON_ERROR); @@ -1714,6 +1704,16 @@ void virNetClientIncomingEvent(virNetSocketPtr sock, virNetClientMarkClose(client, VIR_CONNECT_CLOSE_REASON_ERROR); }
+ if (events & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR)) { + VIR_DEBUG("%s : VIR_EVENT_HANDLE_HANGUP or " + "VIR_EVENT_HANDLE_ERROR encountered", __FUNCTION__);
I know you are just copy&pasting but __FUNCTION__ is redundant here.
+ virNetClientMarkClose(client, + (events & VIR_EVENT_HANDLE_HANGUP) ? + VIR_CONNECT_CLOSE_REASON_EOF : + VIR_CONNECT_CLOSE_REASON_ERROR); + goto done; + } + /* Remove completed calls or signal their threads. */ virNetClientCallRemovePredicate(&client->waitDispatch, virNetClientIOEventLoopRemoveDone,
This is a good change but I think it's incomplete. If something fails (e.g. the connection is closed) while we are inside virNetClientIOHandleOutput(), we will still skip reading any data possibly waiting for us. Jirka

On Thu, Jul 26, 2012 at 04:00:22PM +0200, Jiri Denemark wrote:
On Tue, Jul 24, 2012 at 14:22:43 +0100, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
In the socket event handler for the RPC client we must deal with read/write events, before checking for EOF, otherwise we might close the socket before we've read & acted upon the last RPC messages
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/rpc/virnetclient.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c index aba58ec..f5d8189 100644 --- a/src/rpc/virnetclient.c +++ b/src/rpc/virnetclient.c @@ -1694,16 +1694,6 @@ void virNetClientIncomingEvent(virNetSocketPtr sock,
VIR_DEBUG("Event fired %p %d", sock, events);
- if (events & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR)) { - VIR_DEBUG("%s : VIR_EVENT_HANDLE_HANGUP or " - "VIR_EVENT_HANDLE_ERROR encountered", __FUNCTION__); - virNetClientMarkClose(client, - (events & VIR_EVENT_HANDLE_HANGUP) ? - VIR_CONNECT_CLOSE_REASON_EOF : - VIR_CONNECT_CLOSE_REASON_ERROR); - goto done; - } - if (events & VIR_EVENT_HANDLE_WRITABLE) { if (virNetClientIOHandleOutput(client) < 0) virNetClientMarkClose(client, VIR_CONNECT_CLOSE_REASON_ERROR); @@ -1714,6 +1704,16 @@ void virNetClientIncomingEvent(virNetSocketPtr sock, virNetClientMarkClose(client, VIR_CONNECT_CLOSE_REASON_ERROR); }
+ if (events & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR)) { + VIR_DEBUG("%s : VIR_EVENT_HANDLE_HANGUP or " + "VIR_EVENT_HANDLE_ERROR encountered", __FUNCTION__);
I know you are just copy&pasting but __FUNCTION__ is redundant here.
+ virNetClientMarkClose(client, + (events & VIR_EVENT_HANDLE_HANGUP) ? + VIR_CONNECT_CLOSE_REASON_EOF : + VIR_CONNECT_CLOSE_REASON_ERROR); + goto done; + } + /* Remove completed calls or signal their threads. */ virNetClientCallRemovePredicate(&client->waitDispatch, virNetClientIOEventLoopRemoveDone,
This is a good change but I think it's incomplete. If something fails (e.g. the connection is closed) while we are inside virNetClientIOHandleOutput(), we will still skip reading any data possibly waiting for us.
No, we should be ok in that respect, since we see the error, but don't 'goto', so we'll still run the input code if (events & VIR_EVENT_HANDLE_WRITABLE) { if (virNetClientIOHandleOutput(client) < 0) virNetClientMarkClose(client, VIR_CONNECT_CLOSE_REASON_ERROR); } if (events & VIR_EVENT_HANDLE_READABLE) { if (virNetClientIOHandleInput(client) < 0) virNetClientMarkClose(client, VIR_CONNECT_CLOSE_REASON_ERROR); } Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On Fri, Jul 27, 2012 at 13:33:06 +0100, Daniel P. Berrange wrote:
On Thu, Jul 26, 2012 at 04:00:22PM +0200, Jiri Denemark wrote:
On Tue, Jul 24, 2012 at 14:22:43 +0100, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
In the socket event handler for the RPC client we must deal with read/write events, before checking for EOF, otherwise we might close the socket before we've read & acted upon the last RPC messages
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/rpc/virnetclient.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c index aba58ec..f5d8189 100644 --- a/src/rpc/virnetclient.c +++ b/src/rpc/virnetclient.c @@ -1694,16 +1694,6 @@ void virNetClientIncomingEvent(virNetSocketPtr sock,
VIR_DEBUG("Event fired %p %d", sock, events);
- if (events & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR)) { - VIR_DEBUG("%s : VIR_EVENT_HANDLE_HANGUP or " - "VIR_EVENT_HANDLE_ERROR encountered", __FUNCTION__); - virNetClientMarkClose(client, - (events & VIR_EVENT_HANDLE_HANGUP) ? - VIR_CONNECT_CLOSE_REASON_EOF : - VIR_CONNECT_CLOSE_REASON_ERROR); - goto done; - } - if (events & VIR_EVENT_HANDLE_WRITABLE) { if (virNetClientIOHandleOutput(client) < 0) virNetClientMarkClose(client, VIR_CONNECT_CLOSE_REASON_ERROR); @@ -1714,6 +1704,16 @@ void virNetClientIncomingEvent(virNetSocketPtr sock, virNetClientMarkClose(client, VIR_CONNECT_CLOSE_REASON_ERROR); }
+ if (events & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR)) { + VIR_DEBUG("%s : VIR_EVENT_HANDLE_HANGUP or " + "VIR_EVENT_HANDLE_ERROR encountered", __FUNCTION__);
I know you are just copy&pasting but __FUNCTION__ is redundant here.
+ virNetClientMarkClose(client, + (events & VIR_EVENT_HANDLE_HANGUP) ? + VIR_CONNECT_CLOSE_REASON_EOF : + VIR_CONNECT_CLOSE_REASON_ERROR); + goto done; + } + /* Remove completed calls or signal their threads. */ virNetClientCallRemovePredicate(&client->waitDispatch, virNetClientIOEventLoopRemoveDone,
This is a good change but I think it's incomplete. If something fails (e.g. the connection is closed) while we are inside virNetClientIOHandleOutput(), we will still skip reading any data possibly waiting for us.
No, we should be ok in that respect, since we see the error, but don't 'goto', so we'll still run the input code
if (events & VIR_EVENT_HANDLE_WRITABLE) { if (virNetClientIOHandleOutput(client) < 0) virNetClientMarkClose(client, VIR_CONNECT_CLOSE_REASON_ERROR); }
if (events & VIR_EVENT_HANDLE_READABLE) { if (virNetClientIOHandleInput(client) < 0) virNetClientMarkClose(client, VIR_CONNECT_CLOSE_REASON_ERROR); }
Oh, right. ACK then. Jirka

From: "Daniel P. Berrange" <berrange@redhat.com> For consistency all the APIs in the lxc_process.c file should have a virLXCProcess prefix in their name Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/lxc/lxc_driver.c | 24 +++--- src/lxc/lxc_process.c | 216 ++++++++++++++++++++++++------------------------- src/lxc/lxc_process.h | 41 +++++----- 3 files changed, 141 insertions(+), 140 deletions(-) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index ba07a80..8416e15 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -126,7 +126,7 @@ static int lxcClose(virConnectPtr conn) lxc_driver_t *driver = conn->privateData; lxcDriverLock(driver); - lxcProcessAutoDestroyRun(driver, conn); + virLXCProcessAutoDestroyRun(driver, conn); lxcDriverUnlock(driver); conn->privateData = NULL; @@ -978,9 +978,9 @@ static int lxcDomainStartWithFlags(virDomainPtr dom, unsigned int flags) goto cleanup; } - ret = lxcVmStart(dom->conn, driver, vm, - (flags & VIR_DOMAIN_START_AUTODESTROY), - VIR_DOMAIN_RUNNING_BOOTED); + ret = virLXCProcessStart(dom->conn, driver, vm, + (flags & VIR_DOMAIN_START_AUTODESTROY), + VIR_DOMAIN_RUNNING_BOOTED); if (ret == 0) { event = virDomainEventNewFromObj(vm, @@ -1059,9 +1059,9 @@ lxcDomainCreateAndStart(virConnectPtr conn, goto cleanup; def = NULL; - if (lxcVmStart(conn, driver, vm, - (flags & VIR_DOMAIN_START_AUTODESTROY), - VIR_DOMAIN_RUNNING_BOOTED) < 0) { + if (virLXCProcessStart(conn, driver, vm, + (flags & VIR_DOMAIN_START_AUTODESTROY), + VIR_DOMAIN_RUNNING_BOOTED) < 0) { virDomainAuditStart(vm, "booted", false); virDomainRemoveInactive(&driver->domains, vm); vm = NULL; @@ -1296,7 +1296,7 @@ lxcDomainDestroyFlags(virDomainPtr dom, goto cleanup; } - ret = lxcVmTerminate(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED); + ret = virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED); event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED, VIR_DOMAIN_EVENT_STOPPED_DESTROYED); @@ -1436,7 +1436,7 @@ static int lxcStartup(int privileged) lxcDomainSetPrivateDataHooks(lxc_driver->caps); - if (lxcProcessAutoDestroyInit(lxc_driver) < 0) + if (virLXCProcessAutoDestroyInit(lxc_driver) < 0) goto cleanup; /* Get all the running persistent or transient configs first */ @@ -1448,7 +1448,7 @@ static int lxcStartup(int privileged) NULL, NULL) < 0) goto cleanup; - lxcReconnectAll(lxc_driver, &lxc_driver->domains); + virLXCProcessReconnectAll(lxc_driver, &lxc_driver->domains); /* Then inactive persistent configs */ if (virDomainLoadAllConfigs(lxc_driver->caps, @@ -1461,7 +1461,7 @@ static int lxcStartup(int privileged) lxcDriverUnlock(lxc_driver); - lxcAutostartConfigs(lxc_driver); + virLXCProcessAutostartAll(lxc_driver); return 0; @@ -1517,7 +1517,7 @@ static int lxcShutdown(void) virDomainObjListDeinit(&lxc_driver->domains); virDomainEventStateFree(lxc_driver->domainEventState); - lxcProcessAutoDestroyShutdown(lxc_driver); + virLXCProcessAutoDestroyShutdown(lxc_driver); virCapabilitiesFree(lxc_driver->caps); virSecurityManagerFree(lxc_driver->securityManager); diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index ab27cbe..c25a04b 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -48,7 +48,7 @@ #define START_POSTFIX ": starting up\n" -int lxcProcessAutoDestroyInit(lxc_driver_t *driver) +int virLXCProcessAutoDestroyInit(lxc_driver_t *driver) { if (!(driver->autodestroy = virHashCreate(5, NULL))) return -1; @@ -56,16 +56,16 @@ int lxcProcessAutoDestroyInit(lxc_driver_t *driver) return 0; } -struct lxcProcessAutoDestroyData { +struct virLXCProcessAutoDestroyData { lxc_driver_t *driver; virConnectPtr conn; }; -static void lxcProcessAutoDestroyDom(void *payload, - const void *name, - void *opaque) +static void virLXCProcessAutoDestroyDom(void *payload, + const void *name, + void *opaque) { - struct lxcProcessAutoDestroyData *data = opaque; + struct virLXCProcessAutoDestroyData *data = opaque; virConnectPtr conn = payload; const char *uuidstr = name; unsigned char uuid[VIR_UUID_BUFLEN]; @@ -89,7 +89,7 @@ static void lxcProcessAutoDestroyDom(void *payload, } VIR_DEBUG("Killing domain"); - lxcVmTerminate(data->driver, dom, VIR_DOMAIN_SHUTOFF_DESTROYED); + virLXCProcessStop(data->driver, dom, VIR_DOMAIN_SHUTOFF_DESTROYED); virDomainAuditStop(dom, "destroyed"); event = virDomainEventNewFromObj(dom, VIR_DOMAIN_EVENT_STOPPED, @@ -108,23 +108,23 @@ static void lxcProcessAutoDestroyDom(void *payload, /* * Precondition: driver is locked */ -void lxcProcessAutoDestroyRun(lxc_driver_t *driver, virConnectPtr conn) +void virLXCProcessAutoDestroyRun(lxc_driver_t *driver, virConnectPtr conn) { - struct lxcProcessAutoDestroyData data = { + struct virLXCProcessAutoDestroyData data = { driver, conn }; VIR_DEBUG("conn=%p", conn); - virHashForEach(driver->autodestroy, lxcProcessAutoDestroyDom, &data); + virHashForEach(driver->autodestroy, virLXCProcessAutoDestroyDom, &data); } -void lxcProcessAutoDestroyShutdown(lxc_driver_t *driver) +void virLXCProcessAutoDestroyShutdown(lxc_driver_t *driver) { virHashFree(driver->autodestroy); } -int lxcProcessAutoDestroyAdd(lxc_driver_t *driver, - virDomainObjPtr vm, - virConnectPtr conn) +int virLXCProcessAutoDestroyAdd(lxc_driver_t *driver, + virDomainObjPtr vm, + virConnectPtr conn) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(vm->def->uuid, uuidstr); @@ -134,8 +134,8 @@ int lxcProcessAutoDestroyAdd(lxc_driver_t *driver, return 0; } -int lxcProcessAutoDestroyRemove(lxc_driver_t *driver, - virDomainObjPtr vm) +int virLXCProcessAutoDestroyRemove(lxc_driver_t *driver, + virDomainObjPtr vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(vm->def->uuid, uuidstr); @@ -147,7 +147,7 @@ int lxcProcessAutoDestroyRemove(lxc_driver_t *driver, /** - * lxcVmCleanup: + * virLXCProcessCleanup: * @driver: pointer to driver structure * @vm: pointer to VM to clean up * @reason: reason for switching the VM to shutoff state @@ -155,9 +155,9 @@ int lxcProcessAutoDestroyRemove(lxc_driver_t *driver, * Cleanout resources associated with the now dead VM * */ -static void lxcVmCleanup(lxc_driver_t *driver, - virDomainObjPtr vm, - virDomainShutoffReason reason) +static void virLXCProcessCleanup(lxc_driver_t *driver, + virDomainObjPtr vm, + virDomainShutoffReason reason) { virCgroupPtr cgroup; int i; @@ -176,7 +176,7 @@ static void lxcVmCleanup(lxc_driver_t *driver, } /* Stop autodestroy in case guest is restarted */ - lxcProcessAutoDestroyRemove(driver, vm); + virLXCProcessAutoDestroyRemove(driver, vm); virEventRemoveHandle(priv->monitorWatch); VIR_FORCE_CLOSE(priv->monitor); @@ -230,12 +230,12 @@ static void lxcVmCleanup(lxc_driver_t *driver, } -static int lxcSetupInterfaceBridged(virConnectPtr conn, - virDomainDefPtr vm, - virDomainNetDefPtr net, - const char *brname, - unsigned int *nveths, - char ***veths) +static int virLXCProcessSetupInterfaceBridged(virConnectPtr conn, + virDomainDefPtr vm, + virDomainNetDefPtr net, + const char *brname, + unsigned int *nveths, + char ***veths) { int ret = -1; char *parentVeth; @@ -292,11 +292,11 @@ cleanup: } -static int lxcSetupInterfaceDirect(virConnectPtr conn, - virDomainDefPtr def, - virDomainNetDefPtr net, - unsigned int *nveths, - char ***veths) +static int virLXCProcessSetupInterfaceDirect(virConnectPtr conn, + virDomainDefPtr def, + virDomainNetDefPtr net, + unsigned int *nveths, + char ***veths) { int ret = 0; char *res_ifname = NULL; @@ -359,7 +359,7 @@ cleanup: /** - * lxcSetupInterfaces: + * virLXCProcessSetupInterfaces: * @conn: pointer to connection * @def: pointer to virtual machine structure * @nveths: number of interfaces @@ -371,10 +371,10 @@ cleanup: * * Returns 0 on success or -1 in case of error */ -static int lxcSetupInterfaces(virConnectPtr conn, - virDomainDefPtr def, - unsigned int *nveths, - char ***veths) +static int virLXCProcessSetupInterfaces(virConnectPtr conn, + virDomainDefPtr def, + unsigned int *nveths, + char ***veths) { int ret = -1; size_t i; @@ -401,12 +401,12 @@ static int lxcSetupInterfaces(virConnectPtr conn, if (!brname) goto cleanup; - if (lxcSetupInterfaceBridged(conn, - def, - def->nets[i], - brname, - nveths, - veths) < 0) { + if (virLXCProcessSetupInterfaceBridged(conn, + def, + def->nets[i], + brname, + nveths, + veths) < 0) { VIR_FREE(brname); goto cleanup; } @@ -420,21 +420,21 @@ static int lxcSetupInterfaces(virConnectPtr conn, _("No bridge name specified")); goto cleanup; } - if (lxcSetupInterfaceBridged(conn, - def, - def->nets[i], - brname, - nveths, - veths) < 0) + if (virLXCProcessSetupInterfaceBridged(conn, + def, + def->nets[i], + brname, + nveths, + veths) < 0) goto cleanup; } break; case VIR_DOMAIN_NET_TYPE_DIRECT: - if (lxcSetupInterfaceDirect(conn, - def, - def->nets[i], - nveths, - veths) < 0) + if (virLXCProcessSetupInterfaceDirect(conn, + def, + def->nets[i], + nveths, + veths) < 0) goto cleanup; break; @@ -472,8 +472,8 @@ cleanup: } -static int lxcMonitorClient(lxc_driver_t * driver, - virDomainObjPtr vm) +static int virLXCProcessMonitorClient(lxc_driver_t * driver, + virDomainObjPtr vm) { char *sockpath = NULL; int fd = -1; @@ -529,9 +529,9 @@ error: } -int lxcVmTerminate(lxc_driver_t *driver, - virDomainObjPtr vm, - virDomainShutoffReason reason) +int virLXCProcessStop(lxc_driver_t *driver, + virDomainObjPtr vm, + virDomainShutoffReason reason) { virCgroupPtr group = NULL; int rc; @@ -572,7 +572,7 @@ int lxcVmTerminate(lxc_driver_t *driver, */ } - lxcVmCleanup(driver, vm, reason); + virLXCProcessCleanup(driver, vm, reason); rc = 0; @@ -582,10 +582,10 @@ cleanup: } extern lxc_driver_t *lxc_driver; -static void lxcMonitorEvent(int watch, - int fd, - int events ATTRIBUTE_UNUSED, - void *data) +static void virLXCProcessMonitorEvent(int watch, + int fd, + int events ATTRIBUTE_UNUSED, + void *data) { lxc_driver_t *driver = lxc_driver; virDomainObjPtr vm = data; @@ -603,7 +603,7 @@ static void lxcMonitorEvent(int watch, goto cleanup; } - if (lxcVmTerminate(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN) < 0) { + if (virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN) < 0) { virEventRemoveHandle(watch); } else { event = virDomainEventNewFromObj(vm, @@ -628,13 +628,13 @@ cleanup: static virCommandPtr -lxcBuildControllerCmd(lxc_driver_t *driver, - virDomainObjPtr vm, - int nveths, - char **veths, - int *ttyFDs, - size_t nttyFDs, - int handshakefd) +virLXCProcessBuildControllerCmd(lxc_driver_t *driver, + virDomainObjPtr vm, + int nveths, + char **veths, + int *ttyFDs, + size_t nttyFDs, + int handshakefd) { size_t i; char *filterstr; @@ -704,11 +704,11 @@ cleanup: } static int -lxcReadLogOutput(virDomainObjPtr vm, - char *logfile, - off_t pos, - char *buf, - size_t buflen) +virLXCProcessReadLogOutput(virDomainObjPtr vm, + char *logfile, + off_t pos, + char *buf, + size_t buflen) { int fd; off_t off; @@ -777,7 +777,7 @@ cleanup: } /** - * lxcVmStart: + * virLXCProcessStart: * @conn: pointer to connection * @driver: pointer to driver structure * @vm: pointer to virtual machine structure @@ -788,11 +788,11 @@ cleanup: * * Returns 0 on success or -1 in case of error */ -int lxcVmStart(virConnectPtr conn, - lxc_driver_t * driver, - virDomainObjPtr vm, - bool autoDestroy, - virDomainRunningReason reason) +int virLXCProcessStart(virConnectPtr conn, + lxc_driver_t * driver, + virDomainObjPtr vm, + bool autoDestroy, + virDomainRunningReason reason) { int rc = -1, r; size_t nttyFDs = 0; @@ -927,7 +927,7 @@ int lxcVmStart(virConnectPtr conn, } } - if (lxcSetupInterfaces(conn, vm->def, &nveths, &veths) != 0) + if (virLXCProcessSetupInterfaces(conn, vm->def, &nveths, &veths) != 0) goto cleanup; /* Save the configuration for the controller */ @@ -948,11 +948,11 @@ int lxcVmStart(virConnectPtr conn, goto cleanup; } - if (!(cmd = lxcBuildControllerCmd(driver, - vm, - nveths, veths, - ttyFDs, nttyFDs, - handshakefds[1]))) + if (!(cmd = virLXCProcessBuildControllerCmd(driver, + vm, + nveths, veths, + ttyFDs, nttyFDs, + handshakefds[1]))) goto cleanup; virCommandSetOutputFD(cmd, &logfd); virCommandSetErrorFD(cmd, &logfd); @@ -1003,7 +1003,7 @@ int lxcVmStart(virConnectPtr conn, /* Connect to the controller as a client *first* because * this will block until the child has written their * pid file out to disk */ - if ((priv->monitor = lxcMonitorClient(driver, vm)) < 0) + if ((priv->monitor = virLXCProcessMonitorClient(driver, vm)) < 0) goto cleanup; /* And get its pid */ @@ -1020,7 +1020,7 @@ int lxcVmStart(virConnectPtr conn, if (lxcContainerWaitForContinue(handshakefds[0]) < 0) { char out[1024]; - if (!(lxcReadLogOutput(vm, logfile, pos, out, 1024) < 0)) { + if (!(virLXCProcessReadLogOutput(vm, logfile, pos, out, 1024) < 0)) { lxcError(VIR_ERR_INTERNAL_ERROR, _("guest failed to start: %s"), out); } @@ -1031,13 +1031,13 @@ int lxcVmStart(virConnectPtr conn, if ((priv->monitorWatch = virEventAddHandle( priv->monitor, VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_HANGUP, - lxcMonitorEvent, + virLXCProcessMonitorEvent, vm, NULL)) < 0) { goto error; } if (autoDestroy && - lxcProcessAutoDestroyAdd(driver, vm, conn) < 0) + virLXCProcessAutoDestroyAdd(driver, vm, conn) < 0) goto error; if (virDomainObjSetDefTransient(driver->caps, vm, false) < 0) @@ -1114,25 +1114,25 @@ cleanup: error: err = virSaveLastError(); - lxcVmTerminate(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED); + virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED); goto cleanup; } -struct lxcAutostartData { +struct virLXCAutostartData { lxc_driver_t *driver; virConnectPtr conn; }; static void -lxcAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque) +virLXCProcessAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque) { virDomainObjPtr vm = payload; - const struct lxcAutostartData *data = opaque; + const struct virLXCAutostartData *data = opaque; virDomainObjLock(vm); if (vm->autostart && !virDomainObjIsActive(vm)) { - int ret = lxcVmStart(data->conn, data->driver, vm, false, + int ret = virLXCProcessStart(data->conn, data->driver, vm, false, VIR_DOMAIN_RUNNING_BOOTED); virDomainAuditStart(vm, "booted", ret >= 0); if (ret < 0) { @@ -1154,7 +1154,7 @@ lxcAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaqu void -lxcAutostartConfigs(lxc_driver_t *driver) { +virLXCProcessAutostartAll(lxc_driver_t *driver) { /* XXX: Figure out a better way todo this. The domain * startup code needs a connection handle in order * to lookup the bridge associated with a virtual @@ -1163,10 +1163,10 @@ lxcAutostartConfigs(lxc_driver_t *driver) { virConnectPtr conn = virConnectOpen("lxc:///"); /* Ignoring NULL conn which is mostly harmless here */ - struct lxcAutostartData data = { driver, conn }; + struct virLXCAutostartData data = { driver, conn }; lxcDriverLock(driver); - virHashForEach(driver->domains.objs, lxcAutostartDomain, &data); + virHashForEach(driver->domains.objs, virLXCProcessAutostartDomain, &data); lxcDriverUnlock(driver); if (conn) @@ -1174,7 +1174,7 @@ lxcAutostartConfigs(lxc_driver_t *driver) { } static void -lxcReconnectVM(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque) +virLXCProcessReconnectDomain(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque) { virDomainObjPtr vm = payload; lxc_driver_t *driver = opaque; @@ -1190,13 +1190,13 @@ lxcReconnectVM(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque) virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNKNOWN); - if ((priv->monitor = lxcMonitorClient(driver, vm)) < 0) + if ((priv->monitor = virLXCProcessMonitorClient(driver, vm)) < 0) goto error; if ((priv->monitorWatch = virEventAddHandle( priv->monitor, VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_HANGUP, - lxcMonitorEvent, + virLXCProcessMonitorEvent, vm, NULL)) < 0) goto error; @@ -1228,15 +1228,15 @@ cleanup: return; error: - lxcVmTerminate(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED); + virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED); virDomainAuditStop(vm, "failed"); goto cleanup; } -int lxcReconnectAll(lxc_driver_t *driver, - virDomainObjListPtr doms) +int virLXCProcessReconnectAll(lxc_driver_t *driver, + virDomainObjListPtr doms) { - virHashForEach(doms->objs, lxcReconnectVM, driver); + virHashForEach(doms->objs, virLXCProcessReconnectDomain, driver); return 0; } diff --git a/src/lxc/lxc_process.h b/src/lxc/lxc_process.h index d763a69..d46eaf2 100644 --- a/src/lxc/lxc_process.h +++ b/src/lxc/lxc_process.h @@ -24,26 +24,27 @@ # include "lxc_conf.h" -int lxcVmStart(virConnectPtr conn, - lxc_driver_t * driver, - virDomainObjPtr vm, - bool autoDestroy, - virDomainRunningReason reason); -int lxcVmTerminate(lxc_driver_t *driver, - virDomainObjPtr vm, - virDomainShutoffReason reason); -int lxcProcessAutoDestroyInit(lxc_driver_t *driver); -void lxcProcessAutoDestroyRun(lxc_driver_t *driver, - virConnectPtr conn); -void lxcProcessAutoDestroyShutdown(lxc_driver_t *driver); -int lxcProcessAutoDestroyAdd(lxc_driver_t *driver, - virDomainObjPtr vm, - virConnectPtr conn); -int lxcProcessAutoDestroyRemove(lxc_driver_t *driver, - virDomainObjPtr vm); +int virLXCProcessStart(virConnectPtr conn, + lxc_driver_t * driver, + virDomainObjPtr vm, + bool autoDestroy, + virDomainRunningReason reason); +int virLXCProcessStop(lxc_driver_t *driver, + virDomainObjPtr vm, + virDomainShutoffReason reason); -void lxcAutostartConfigs(lxc_driver_t *driver); -int lxcReconnectAll(lxc_driver_t *driver, - virDomainObjListPtr doms); +int virLXCProcessAutoDestroyInit(lxc_driver_t *driver); +void virLXCProcessAutoDestroyRun(lxc_driver_t *driver, + virConnectPtr conn); +void virLXCProcessAutoDestroyShutdown(lxc_driver_t *driver); +int virLXCProcessAutoDestroyAdd(lxc_driver_t *driver, + virDomainObjPtr vm, + virConnectPtr conn); +int virLXCProcessAutoDestroyRemove(lxc_driver_t *driver, + virDomainObjPtr vm); + +void virLXCProcessAutostartAll(lxc_driver_t *driver); +int virLXCProcessReconnectAll(lxc_driver_t *driver, + virDomainObjListPtr doms); #endif /* __LXC_PROCESS_H__ */ -- 1.7.10.4

On Tue, Jul 24, 2012 at 14:22:44 +0100, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
For consistency all the APIs in the lxc_process.c file should have a virLXCProcess prefix in their name
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/lxc/lxc_driver.c | 24 +++--- src/lxc/lxc_process.c | 216 ++++++++++++++++++++++++------------------------- src/lxc/lxc_process.h | 41 +++++----- 3 files changed, 141 insertions(+), 140 deletions(-)
...
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index ab27cbe..c25a04b 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c ... @@ -56,16 +56,16 @@ int lxcProcessAutoDestroyInit(lxc_driver_t *driver) return 0; }
-struct lxcProcessAutoDestroyData { +struct virLXCProcessAutoDestroyData { lxc_driver_t *driver; virConnectPtr conn; }; ... @@ -1114,25 +1114,25 @@ cleanup:
error: err = virSaveLastError(); - lxcVmTerminate(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED); + virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED); goto cleanup; }
-struct lxcAutostartData { +struct virLXCAutostartData {
This should be virLXCProcessAutostartData for consistency.
lxc_driver_t *driver; virConnectPtr conn; };
... ACK Jirka

From: "Daniel P. Berrange" <berrange@redhat.com> For consistency all the APIs in the lxc_domain.c file should have a virLXCDomain prefix in their name Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/lxc/lxc_domain.c | 14 +++++++------- src/lxc/lxc_domain.h | 8 ++++---- src/lxc/lxc_driver.c | 2 +- src/lxc/lxc_process.c | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/lxc/lxc_domain.c b/src/lxc/lxc_domain.c index f78dc09..847aac7 100644 --- a/src/lxc/lxc_domain.c +++ b/src/lxc/lxc_domain.c @@ -25,9 +25,9 @@ #include "memory.h" -static void *lxcDomainObjPrivateAlloc(void) +static void *virLXCDomainObjPrivateAlloc(void) { - lxcDomainObjPrivatePtr priv; + virLXCDomainObjPrivatePtr priv; if (VIR_ALLOC(priv) < 0) return NULL; @@ -38,16 +38,16 @@ static void *lxcDomainObjPrivateAlloc(void) return priv; } -static void lxcDomainObjPrivateFree(void *data) +static void virLXCDomainObjPrivateFree(void *data) { - lxcDomainObjPrivatePtr priv = data; + virLXCDomainObjPrivatePtr priv = data; VIR_FREE(priv); } -void lxcDomainSetPrivateDataHooks(virCapsPtr caps) +void virLXCDomainSetPrivateDataHooks(virCapsPtr caps) { - caps->privateDataAllocFunc = lxcDomainObjPrivateAlloc; - caps->privateDataFreeFunc = lxcDomainObjPrivateFree; + caps->privateDataAllocFunc = virLXCDomainObjPrivateAlloc; + caps->privateDataFreeFunc = virLXCDomainObjPrivateFree; } diff --git a/src/lxc/lxc_domain.h b/src/lxc/lxc_domain.h index 9629465..8a2c892 100644 --- a/src/lxc/lxc_domain.h +++ b/src/lxc/lxc_domain.h @@ -25,13 +25,13 @@ # include "lxc_conf.h" -typedef struct _lxcDomainObjPrivate lxcDomainObjPrivate; -typedef lxcDomainObjPrivate *lxcDomainObjPrivatePtr; -struct _lxcDomainObjPrivate { +typedef struct _virLXCDomainObjPrivate virLXCDomainObjPrivate; +typedef virLXCDomainObjPrivate *virLXCDomainObjPrivatePtr; +struct _virLXCDomainObjPrivate { int monitor; int monitorWatch; }; -void lxcDomainSetPrivateDataHooks(virCapsPtr caps); +void virLXCDomainSetPrivateDataHooks(virCapsPtr caps); #endif /* __LXC_DOMAIN_H__ */ diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 8416e15..fc6190b 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -1434,7 +1434,7 @@ static int lxcStartup(int privileged) if ((lxc_driver->caps = lxcCapsInit(lxc_driver)) == NULL) goto cleanup; - lxcDomainSetPrivateDataHooks(lxc_driver->caps); + virLXCDomainSetPrivateDataHooks(lxc_driver->caps); if (virLXCProcessAutoDestroyInit(lxc_driver) < 0) goto cleanup; diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index c25a04b..c630136 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -161,7 +161,7 @@ static void virLXCProcessCleanup(lxc_driver_t *driver, { virCgroupPtr cgroup; int i; - lxcDomainObjPrivatePtr priv = vm->privateData; + virLXCDomainObjPrivatePtr priv = vm->privateData; virNetDevVPortProfilePtr vport = NULL; /* now that we know it's stopped call the hook if present */ @@ -590,7 +590,7 @@ static void virLXCProcessMonitorEvent(int watch, lxc_driver_t *driver = lxc_driver; virDomainObjPtr vm = data; virDomainEventPtr event = NULL; - lxcDomainObjPrivatePtr priv; + virLXCDomainObjPrivatePtr priv; lxcDriverLock(driver); virDomainObjLock(vm); @@ -807,7 +807,7 @@ int virLXCProcessStart(virConnectPtr conn, char ebuf[1024]; char *timestamp; virCommandPtr cmd = NULL; - lxcDomainObjPrivatePtr priv = vm->privateData; + virLXCDomainObjPrivatePtr priv = vm->privateData; virErrorPtr err = NULL; if (!lxc_driver->cgroup) { @@ -1178,7 +1178,7 @@ virLXCProcessReconnectDomain(void *payload, const void *name ATTRIBUTE_UNUSED, v { virDomainObjPtr vm = payload; lxc_driver_t *driver = opaque; - lxcDomainObjPrivatePtr priv; + virLXCDomainObjPrivatePtr priv; virDomainObjLock(vm); VIR_DEBUG("Reconnect %d %d %d\n", vm->def->id, vm->pid, vm->state.state); -- 1.7.10.4

On Tue, Jul 24, 2012 at 14:22:45 +0100, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
For consistency all the APIs in the lxc_domain.c file should have a virLXCDomain prefix in their name
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/lxc/lxc_domain.c | 14 +++++++------- src/lxc/lxc_domain.h | 8 ++++---- src/lxc/lxc_driver.c | 2 +- src/lxc/lxc_process.c | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-)
ACK Jirka

From: "Daniel P. Berrange" <berrange@redhat.com> Rename the lxc_driver_t struct typedef to virLXCDriver to more closely follow normal libvirt naming conventions Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/lxc/lxc_conf.c | 4 +- src/lxc/lxc_conf.h | 14 ++++--- src/lxc/lxc_driver.c | 101 ++++++++++++++++++++++++------------------------- src/lxc/lxc_process.c | 37 +++++++++--------- src/lxc/lxc_process.h | 18 ++++----- 5 files changed, 88 insertions(+), 86 deletions(-) diff --git a/src/lxc/lxc_conf.c b/src/lxc/lxc_conf.c index 81b3b3f..54839f5 100644 --- a/src/lxc/lxc_conf.c +++ b/src/lxc/lxc_conf.c @@ -49,7 +49,7 @@ static int lxcDefaultConsoleType(const char *ostype ATTRIBUTE_UNUSED) /* Functions */ -virCapsPtr lxcCapsInit(lxc_driver_t *driver) +virCapsPtr lxcCapsInit(virLXCDriverPtr driver) { struct utsname utsname; virCapsPtr caps; @@ -156,7 +156,7 @@ error: return NULL; } -int lxcLoadDriverConfig(lxc_driver_t *driver) +int lxcLoadDriverConfig(virLXCDriverPtr driver) { char *filename; virConfPtr conf; diff --git a/src/lxc/lxc_conf.h b/src/lxc/lxc_conf.h index 1c653e3..4a57a3d 100644 --- a/src/lxc/lxc_conf.h +++ b/src/lxc/lxc_conf.h @@ -43,8 +43,10 @@ # define LXC_LOG_DIR LOCALSTATEDIR "/log/libvirt/lxc" # define LXC_AUTOSTART_DIR LXC_CONFIG_DIR "/autostart" -typedef struct __lxc_driver lxc_driver_t; -struct __lxc_driver { +typedef struct _virLXCDriver virLXCDriver; +typedef virLXCDriver *virLXCDriverPtr; + +struct _virLXCDriver { virMutex lock; virCapsPtr caps; @@ -71,18 +73,18 @@ struct __lxc_driver { virHashTablePtr autodestroy; }; -int lxcLoadDriverConfig(lxc_driver_t *driver); -virCapsPtr lxcCapsInit(lxc_driver_t *driver); +int lxcLoadDriverConfig(virLXCDriverPtr driver); +virCapsPtr lxcCapsInit(virLXCDriverPtr driver); # define lxcError(code, ...) \ virReportErrorHelper(VIR_FROM_LXC, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) -static inline void lxcDriverLock(lxc_driver_t *driver) +static inline void lxcDriverLock(virLXCDriverPtr driver) { virMutexLock(&driver->lock); } -static inline void lxcDriverUnlock(lxc_driver_t *driver) +static inline void lxcDriverUnlock(virLXCDriverPtr driver) { virMutexUnlock(&driver->lock); } diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index fc6190b..fbbb1be 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -72,11 +72,10 @@ static int lxcStartup(int privileged); static int lxcShutdown(void); -lxc_driver_t *lxc_driver = NULL; +virLXCDriverPtr lxc_driver = NULL; /* Functions */ - static virDrvOpenStatus lxcOpen(virConnectPtr conn, virConnectAuthPtr auth ATTRIBUTE_UNUSED, unsigned int flags) @@ -123,7 +122,7 @@ static virDrvOpenStatus lxcOpen(virConnectPtr conn, static int lxcClose(virConnectPtr conn) { - lxc_driver_t *driver = conn->privateData; + virLXCDriverPtr driver = conn->privateData; lxcDriverLock(driver); virLXCProcessAutoDestroyRun(driver, conn); @@ -155,7 +154,7 @@ static int lxcIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED) static char *lxcGetCapabilities(virConnectPtr conn) { - lxc_driver_t *driver = conn->privateData; + virLXCDriverPtr driver = conn->privateData; char *xml; lxcDriverLock(driver); @@ -170,7 +169,7 @@ static char *lxcGetCapabilities(virConnectPtr conn) { static virDomainPtr lxcDomainLookupByID(virConnectPtr conn, int id) { - lxc_driver_t *driver = conn->privateData; + virLXCDriverPtr driver = conn->privateData; virDomainObjPtr vm; virDomainPtr dom = NULL; @@ -197,7 +196,7 @@ cleanup: static virDomainPtr lxcDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) { - lxc_driver_t *driver = conn->privateData; + virLXCDriverPtr driver = conn->privateData; virDomainObjPtr vm; virDomainPtr dom = NULL; @@ -226,7 +225,7 @@ cleanup: static virDomainPtr lxcDomainLookupByName(virConnectPtr conn, const char *name) { - lxc_driver_t *driver = conn->privateData; + virLXCDriverPtr driver = conn->privateData; virDomainObjPtr vm; virDomainPtr dom = NULL; @@ -252,7 +251,7 @@ cleanup: static int lxcDomainIsActive(virDomainPtr dom) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr obj; int ret = -1; @@ -277,7 +276,7 @@ cleanup: static int lxcDomainIsPersistent(virDomainPtr dom) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr obj; int ret = -1; @@ -301,7 +300,7 @@ cleanup: static int lxcDomainIsUpdated(virDomainPtr dom) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr obj; int ret = -1; @@ -324,7 +323,7 @@ cleanup: } static int lxcListDomains(virConnectPtr conn, int *ids, int nids) { - lxc_driver_t *driver = conn->privateData; + virLXCDriverPtr driver = conn->privateData; int n; lxcDriverLock(driver); @@ -335,7 +334,7 @@ static int lxcListDomains(virConnectPtr conn, int *ids, int nids) { } static int lxcNumDomains(virConnectPtr conn) { - lxc_driver_t *driver = conn->privateData; + virLXCDriverPtr driver = conn->privateData; int n; lxcDriverLock(driver); @@ -347,7 +346,7 @@ static int lxcNumDomains(virConnectPtr conn) { static int lxcListDefinedDomains(virConnectPtr conn, char **const names, int nnames) { - lxc_driver_t *driver = conn->privateData; + virLXCDriverPtr driver = conn->privateData; int n; lxcDriverLock(driver); @@ -359,7 +358,7 @@ static int lxcListDefinedDomains(virConnectPtr conn, static int lxcNumDefinedDomains(virConnectPtr conn) { - lxc_driver_t *driver = conn->privateData; + virLXCDriverPtr driver = conn->privateData; int n; lxcDriverLock(driver); @@ -373,7 +372,7 @@ static int lxcNumDefinedDomains(virConnectPtr conn) { static virDomainPtr lxcDomainDefine(virConnectPtr conn, const char *xml) { - lxc_driver_t *driver = conn->privateData; + virLXCDriverPtr driver = conn->privateData; virDomainDefPtr def = NULL; virDomainObjPtr vm = NULL; virDomainPtr dom = NULL; @@ -434,7 +433,7 @@ cleanup: static int lxcDomainUndefineFlags(virDomainPtr dom, unsigned int flags) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; virDomainEventPtr event = NULL; int ret = -1; @@ -492,7 +491,7 @@ static int lxcDomainUndefine(virDomainPtr dom) static int lxcDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; virCgroupPtr cgroup = NULL; int ret = -1, rc; @@ -556,7 +555,7 @@ lxcDomainGetState(virDomainPtr dom, int *reason, unsigned int flags) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; int ret = -1; @@ -585,7 +584,7 @@ cleanup: static char *lxcGetOSType(virDomainPtr dom) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; char *ret = NULL; @@ -616,7 +615,7 @@ cleanup: static unsigned long long lxcDomainGetMaxMemory(virDomainPtr dom) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; unsigned long long ret = 0; @@ -641,7 +640,7 @@ cleanup: } static int lxcDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; int ret = -1; @@ -673,7 +672,7 @@ cleanup: } static int lxcDomainSetMemory(virDomainPtr dom, unsigned long newmem) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; virCgroupPtr cgroup = NULL; int ret = -1; @@ -735,7 +734,7 @@ lxcDomainSetMemoryParameters(virDomainPtr dom, int nparams, unsigned int flags) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; int i; virCgroupPtr cgroup = NULL; virDomainObjPtr vm = NULL; @@ -813,7 +812,7 @@ lxcDomainGetMemoryParameters(virDomainPtr dom, int *nparams, unsigned int flags) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; int i; virCgroupPtr cgroup = NULL; virDomainObjPtr vm = NULL; @@ -909,7 +908,7 @@ cleanup: static char *lxcDomainGetXMLDesc(virDomainPtr dom, unsigned int flags) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; char *ret = NULL; @@ -949,7 +948,7 @@ cleanup: */ static int lxcDomainStartWithFlags(virDomainPtr dom, unsigned int flags) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; virDomainEventPtr event = NULL; int ret = -1; @@ -1027,7 +1026,7 @@ static virDomainPtr lxcDomainCreateAndStart(virConnectPtr conn, const char *xml, unsigned int flags) { - lxc_driver_t *driver = conn->privateData; + virLXCDriverPtr driver = conn->privateData; virDomainObjPtr vm = NULL; virDomainDefPtr def; virDomainPtr dom = NULL; @@ -1090,7 +1089,7 @@ cleanup: static int lxcDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr seclabel) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; int ret = -1; @@ -1149,7 +1148,7 @@ cleanup: static int lxcNodeGetSecurityModel(virConnectPtr conn, virSecurityModelPtr secmodel) { - lxc_driver_t *driver = conn->privateData; + virLXCDriverPtr driver = conn->privateData; int ret = 0; lxcDriverLock(driver); @@ -1190,7 +1189,7 @@ lxcDomainEventRegister(virConnectPtr conn, void *opaque, virFreeCallback freecb) { - lxc_driver_t *driver = conn->privateData; + virLXCDriverPtr driver = conn->privateData; int ret; lxcDriverLock(driver); @@ -1207,7 +1206,7 @@ static int lxcDomainEventDeregister(virConnectPtr conn, virConnectDomainEventCallback callback) { - lxc_driver_t *driver = conn->privateData; + virLXCDriverPtr driver = conn->privateData; int ret; lxcDriverLock(driver); @@ -1228,7 +1227,7 @@ lxcDomainEventRegisterAny(virConnectPtr conn, void *opaque, virFreeCallback freecb) { - lxc_driver_t *driver = conn->privateData; + virLXCDriverPtr driver = conn->privateData; int ret; lxcDriverLock(driver); @@ -1247,7 +1246,7 @@ static int lxcDomainEventDeregisterAny(virConnectPtr conn, int callbackID) { - lxc_driver_t *driver = conn->privateData; + virLXCDriverPtr driver = conn->privateData; int ret; lxcDriverLock(driver); @@ -1273,7 +1272,7 @@ static int lxcDomainDestroyFlags(virDomainPtr dom, unsigned int flags) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; virDomainEventPtr event = NULL; int ret = -1; @@ -1346,7 +1345,7 @@ static int lxcCheckNetNsSupport(void) static int -lxcSecurityInit(lxc_driver_t *driver) +lxcSecurityInit(virLXCDriverPtr driver) { VIR_INFO("lxcSecurityInit %s", driver->securityDriverName); virSecurityManagerPtr mgr = virSecurityManagerNew(driver->securityDriverName, @@ -1473,7 +1472,7 @@ cleanup: static void lxcNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque) { - lxc_driver_t *driver = opaque; + virLXCDriverPtr driver = opaque; if (newVM) { virDomainEventPtr event = @@ -1601,7 +1600,7 @@ cleanup: } -static bool lxcCgroupControllerActive(lxc_driver_t *driver, +static bool lxcCgroupControllerActive(virLXCDriverPtr driver, int controller) { if (driver->cgroup == NULL) @@ -1622,7 +1621,7 @@ static bool lxcCgroupControllerActive(lxc_driver_t *driver, static char *lxcGetSchedulerType(virDomainPtr domain, int *nparams) { - lxc_driver_t *driver = domain->conn->privateData; + virLXCDriverPtr driver = domain->conn->privateData; char *ret = NULL; int rc; @@ -1732,7 +1731,7 @@ lxcSetSchedulerParametersFlags(virDomainPtr dom, int nparams, unsigned int flags) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; int i; virCgroupPtr group = NULL; virDomainObjPtr vm = NULL; @@ -1872,7 +1871,7 @@ lxcGetSchedulerParametersFlags(virDomainPtr dom, int *nparams, unsigned int flags) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; virCgroupPtr group = NULL; virDomainObjPtr vm = NULL; virDomainDefPtr persistentDef; @@ -1992,7 +1991,7 @@ lxcDomainSetBlkioParameters(virDomainPtr dom, int nparams, unsigned int flags) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; int i; virCgroupPtr group = NULL; virDomainObjPtr vm = NULL; @@ -2093,7 +2092,7 @@ lxcDomainGetBlkioParameters(virDomainPtr dom, int *nparams, unsigned int flags) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; int i; virCgroupPtr group = NULL; virDomainObjPtr vm = NULL; @@ -2198,7 +2197,7 @@ lxcDomainInterfaceStats(virDomainPtr dom, const char *path, struct _virDomainInterfaceStats *stats) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; int i; int ret = -1; @@ -2254,7 +2253,7 @@ lxcDomainInterfaceStats(virDomainPtr dom, static int lxcDomainGetAutostart(virDomainPtr dom, int *autostart) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; int ret = -1; @@ -2281,7 +2280,7 @@ cleanup: static int lxcDomainSetAutostart(virDomainPtr dom, int autostart) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; char *configFile = NULL, *autostartLink = NULL; int ret = -1; @@ -2354,7 +2353,7 @@ cleanup: return ret; } -static int lxcFreezeContainer(lxc_driver_t *driver, virDomainObjPtr vm) +static int lxcFreezeContainer(virLXCDriverPtr driver, virDomainObjPtr vm) { int timeout = 1000; /* In milliseconds */ int check_interval = 1; /* In milliseconds */ @@ -2449,7 +2448,7 @@ cleanup: static int lxcDomainSuspend(virDomainPtr dom) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; virDomainEventPtr event = NULL; int ret = -1; @@ -2497,7 +2496,7 @@ cleanup: return ret; } -static int lxcUnfreezeContainer(lxc_driver_t *driver, virDomainObjPtr vm) +static int lxcUnfreezeContainer(virLXCDriverPtr driver, virDomainObjPtr vm) { int ret; virCgroupPtr cgroup = NULL; @@ -2514,7 +2513,7 @@ static int lxcUnfreezeContainer(lxc_driver_t *driver, virDomainObjPtr vm) static int lxcDomainResume(virDomainPtr dom) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; virDomainEventPtr event = NULL; int ret = -1; @@ -2569,7 +2568,7 @@ lxcDomainOpenConsole(virDomainPtr dom, virStreamPtr st, unsigned int flags) { - lxc_driver_t *driver = dom->conn->privateData; + virLXCDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm = NULL; char uuidstr[VIR_UUID_STRING_BUFLEN]; int ret = -1; @@ -2638,7 +2637,7 @@ lxcListAllDomains(virConnectPtr conn, virDomainPtr **domains, unsigned int flags) { - lxc_driver_t *driver = conn->privateData; + virLXCDriverPtr driver = conn->privateData; int ret = -1; virCheckFlags(VIR_CONNECT_LIST_FILTERS_ALL, -1); diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index c630136..bc087d7 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -48,7 +48,7 @@ #define START_POSTFIX ": starting up\n" -int virLXCProcessAutoDestroyInit(lxc_driver_t *driver) +int virLXCProcessAutoDestroyInit(virLXCDriverPtr driver) { if (!(driver->autodestroy = virHashCreate(5, NULL))) return -1; @@ -57,7 +57,7 @@ int virLXCProcessAutoDestroyInit(lxc_driver_t *driver) } struct virLXCProcessAutoDestroyData { - lxc_driver_t *driver; + virLXCDriverPtr driver; virConnectPtr conn; }; @@ -108,7 +108,7 @@ static void virLXCProcessAutoDestroyDom(void *payload, /* * Precondition: driver is locked */ -void virLXCProcessAutoDestroyRun(lxc_driver_t *driver, virConnectPtr conn) +void virLXCProcessAutoDestroyRun(virLXCDriverPtr driver, virConnectPtr conn) { struct virLXCProcessAutoDestroyData data = { driver, conn @@ -117,12 +117,12 @@ void virLXCProcessAutoDestroyRun(lxc_driver_t *driver, virConnectPtr conn) virHashForEach(driver->autodestroy, virLXCProcessAutoDestroyDom, &data); } -void virLXCProcessAutoDestroyShutdown(lxc_driver_t *driver) +void virLXCProcessAutoDestroyShutdown(virLXCDriverPtr driver) { virHashFree(driver->autodestroy); } -int virLXCProcessAutoDestroyAdd(lxc_driver_t *driver, +int virLXCProcessAutoDestroyAdd(virLXCDriverPtr driver, virDomainObjPtr vm, virConnectPtr conn) { @@ -134,7 +134,7 @@ int virLXCProcessAutoDestroyAdd(lxc_driver_t *driver, return 0; } -int virLXCProcessAutoDestroyRemove(lxc_driver_t *driver, +int virLXCProcessAutoDestroyRemove(virLXCDriverPtr driver, virDomainObjPtr vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; @@ -155,7 +155,7 @@ int virLXCProcessAutoDestroyRemove(lxc_driver_t *driver, * Cleanout resources associated with the now dead VM * */ -static void virLXCProcessCleanup(lxc_driver_t *driver, +static void virLXCProcessCleanup(virLXCDriverPtr driver, virDomainObjPtr vm, virDomainShutoffReason reason) { @@ -300,7 +300,7 @@ static int virLXCProcessSetupInterfaceDirect(virConnectPtr conn, { int ret = 0; char *res_ifname = NULL; - lxc_driver_t *driver = conn->privateData; + virLXCDriverPtr driver = conn->privateData; virNetDevBandwidthPtr bw; virNetDevVPortProfilePtr prof; @@ -472,7 +472,7 @@ cleanup: } -static int virLXCProcessMonitorClient(lxc_driver_t * driver, +static int virLXCProcessMonitorClient(virLXCDriverPtr driver, virDomainObjPtr vm) { char *sockpath = NULL; @@ -529,7 +529,7 @@ error: } -int virLXCProcessStop(lxc_driver_t *driver, +int virLXCProcessStop(virLXCDriverPtr driver, virDomainObjPtr vm, virDomainShutoffReason reason) { @@ -581,13 +581,13 @@ cleanup: return rc; } -extern lxc_driver_t *lxc_driver; +extern virLXCDriverPtr lxc_driver; static void virLXCProcessMonitorEvent(int watch, int fd, int events ATTRIBUTE_UNUSED, void *data) { - lxc_driver_t *driver = lxc_driver; + virLXCDriverPtr driver = lxc_driver; virDomainObjPtr vm = data; virDomainEventPtr event = NULL; virLXCDomainObjPrivatePtr priv; @@ -628,7 +628,7 @@ cleanup: static virCommandPtr -virLXCProcessBuildControllerCmd(lxc_driver_t *driver, +virLXCProcessBuildControllerCmd(virLXCDriverPtr driver, virDomainObjPtr vm, int nveths, char **veths, @@ -789,7 +789,7 @@ cleanup: * Returns 0 on success or -1 in case of error */ int virLXCProcessStart(virConnectPtr conn, - lxc_driver_t * driver, + virLXCDriverPtr driver, virDomainObjPtr vm, bool autoDestroy, virDomainRunningReason reason) @@ -1119,7 +1119,7 @@ error: } struct virLXCAutostartData { - lxc_driver_t *driver; + virLXCDriverPtr driver; virConnectPtr conn; }; @@ -1154,7 +1154,8 @@ virLXCProcessAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, v void -virLXCProcessAutostartAll(lxc_driver_t *driver) { +virLXCProcessAutostartAll(virLXCDriverPtr driver) +{ /* XXX: Figure out a better way todo this. The domain * startup code needs a connection handle in order * to lookup the bridge associated with a virtual @@ -1177,7 +1178,7 @@ static void virLXCProcessReconnectDomain(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque) { virDomainObjPtr vm = payload; - lxc_driver_t *driver = opaque; + virLXCDriverPtr driver = opaque; virLXCDomainObjPrivatePtr priv; virDomainObjLock(vm); @@ -1234,7 +1235,7 @@ error: } -int virLXCProcessReconnectAll(lxc_driver_t *driver, +int virLXCProcessReconnectAll(virLXCDriverPtr driver, virDomainObjListPtr doms) { virHashForEach(doms->objs, virLXCProcessReconnectDomain, driver); diff --git a/src/lxc/lxc_process.h b/src/lxc/lxc_process.h index d46eaf2..32fd1a7 100644 --- a/src/lxc/lxc_process.h +++ b/src/lxc/lxc_process.h @@ -25,26 +25,26 @@ # include "lxc_conf.h" int virLXCProcessStart(virConnectPtr conn, - lxc_driver_t * driver, + virLXCDriverPtr driver, virDomainObjPtr vm, bool autoDestroy, virDomainRunningReason reason); -int virLXCProcessStop(lxc_driver_t *driver, +int virLXCProcessStop(virLXCDriverPtr driver, virDomainObjPtr vm, virDomainShutoffReason reason); -int virLXCProcessAutoDestroyInit(lxc_driver_t *driver); -void virLXCProcessAutoDestroyRun(lxc_driver_t *driver, +int virLXCProcessAutoDestroyInit(virLXCDriverPtr driver); +void virLXCProcessAutoDestroyRun(virLXCDriverPtr driver, virConnectPtr conn); -void virLXCProcessAutoDestroyShutdown(lxc_driver_t *driver); -int virLXCProcessAutoDestroyAdd(lxc_driver_t *driver, +void virLXCProcessAutoDestroyShutdown(virLXCDriverPtr driver); +int virLXCProcessAutoDestroyAdd(virLXCDriverPtr driver, virDomainObjPtr vm, virConnectPtr conn); -int virLXCProcessAutoDestroyRemove(lxc_driver_t *driver, +int virLXCProcessAutoDestroyRemove(virLXCDriverPtr driver, virDomainObjPtr vm); -void virLXCProcessAutostartAll(lxc_driver_t *driver); -int virLXCProcessReconnectAll(lxc_driver_t *driver, +void virLXCProcessAutostartAll(virLXCDriverPtr driver); +int virLXCProcessReconnectAll(virLXCDriverPtr driver, virDomainObjListPtr doms); #endif /* __LXC_PROCESS_H__ */ -- 1.7.10.4

On Tue, Jul 24, 2012 at 14:22:46 +0100, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
Rename the lxc_driver_t struct typedef to virLXCDriver to more closely follow normal libvirt naming conventions
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/lxc/lxc_conf.c | 4 +- src/lxc/lxc_conf.h | 14 ++++--- src/lxc/lxc_driver.c | 101 ++++++++++++++++++++++++------------------------- src/lxc/lxc_process.c | 37 +++++++++--------- src/lxc/lxc_process.h | 18 ++++----- 5 files changed, 88 insertions(+), 86 deletions(-)
ACK Jirka

From: "Daniel P. Berrange" <berrange@redhat.com> Update all LXC code to use virReportError instead of the custom lxcError macro Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/lxc/lxc_conf.c | 10 +- src/lxc/lxc_conf.h | 5 - src/lxc/lxc_container.c | 30 ++--- src/lxc/lxc_controller.c | 58 ++++----- src/lxc/lxc_driver.c | 304 +++++++++++++++++++++++----------------------- src/lxc/lxc_process.c | 64 +++++----- 6 files changed, 233 insertions(+), 238 deletions(-) diff --git a/src/lxc/lxc_conf.c b/src/lxc/lxc_conf.c index 54839f5..a508f21 100644 --- a/src/lxc/lxc_conf.c +++ b/src/lxc/lxc_conf.c @@ -77,8 +77,8 @@ virCapsPtr lxcCapsInit(virLXCDriverPtr driver) VIR_WARN("Failed to get host power management capabilities"); if (virGetHostUUID(caps->host.host_uuid)) { - lxcError(VIR_ERR_INTERNAL_ERROR, - "%s", _("cannot get the host uuid")); + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("cannot get the host uuid")); goto error; } @@ -187,9 +187,9 @@ int lxcLoadDriverConfig(virLXCDriverPtr driver) goto done; #define CHECK_TYPE(name,typ) if (p && p->type != (typ)) { \ - lxcError(VIR_ERR_INTERNAL_ERROR, \ - "%s: %s: expected type " #typ, \ - filename, (name)); \ + virReportError(VIR_ERR_INTERNAL_ERROR, \ + "%s: %s: expected type " #typ, \ + filename, (name)); \ virConfFree(conf); \ return -1; \ } diff --git a/src/lxc/lxc_conf.h b/src/lxc/lxc_conf.h index 4a57a3d..68cd508 100644 --- a/src/lxc/lxc_conf.h +++ b/src/lxc/lxc_conf.h @@ -76,10 +76,6 @@ struct _virLXCDriver { int lxcLoadDriverConfig(virLXCDriverPtr driver); virCapsPtr lxcCapsInit(virLXCDriverPtr driver); -# define lxcError(code, ...) \ - virReportErrorHelper(VIR_FROM_LXC, code, __FILE__, \ - __FUNCTION__, __LINE__, __VA_ARGS__) - static inline void lxcDriverLock(virLXCDriverPtr driver) { virMutexLock(&driver->lock); @@ -89,5 +85,4 @@ static inline void lxcDriverUnlock(virLXCDriverPtr driver) virMutexUnlock(&driver->lock); } - #endif /* LXC_CONF_H */ diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index 74242b2..c555559 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -872,9 +872,9 @@ retry: * /etc/filesystems is only allowed to contain '*' on the last line */ if (gotStar && !tryProc) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("%s has unexpected '*' before last line"), - fslist); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("%s has unexpected '*' before last line"), + fslist); goto cleanup; } @@ -1066,14 +1066,14 @@ static int lxcContainerMountFS(virDomainFSDefPtr fs, /* We do actually support this, but the lxc controller * should have associated the file with a loopback * device and changed this to TYPE_BLOCK for us */ - lxcError(VIR_ERR_INTERNAL_ERROR, - _("Unexpected filesystem type %s"), - virDomainFSTypeToString(fs->type)); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unexpected filesystem type %s"), + virDomainFSTypeToString(fs->type)); break; default: - lxcError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Cannot mount filesystem type %s"), - virDomainFSTypeToString(fs->type)); + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Cannot mount filesystem type %s"), + virDomainFSTypeToString(fs->type)); break; } return 0; @@ -1599,14 +1599,14 @@ static int lxcContainerDropCapabilities(void) CAP_AUDIT_CONTROL, /* No messing with auditing status */ CAP_MAC_ADMIN, /* No messing with LSM config */ -1 /* sentinal */)) < 0) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("Failed to remove capabilities: %d"), ret); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to remove capabilities: %d"), ret); return -1; } if ((ret = capng_apply(CAPNG_SELECT_BOTH)) < 0) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("Failed to apply capabilities: %d"), ret); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to apply capabilities: %d"), ret); return -1; } @@ -1646,8 +1646,8 @@ static int lxcContainerChild( void *data ) virCommandPtr cmd = NULL; if (NULL == vmDef) { - lxcError(VIR_ERR_INTERNAL_ERROR, - "%s", _("lxcChild() passed invalid vm definition")); + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("lxcChild() passed invalid vm definition")); goto cleanup; } diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 10f0b8a..e39c236 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -291,9 +291,9 @@ static int virLXCControllerDaemonHandshake(virLXCControllerPtr ctrl) static int virLXCControllerValidateNICs(virLXCControllerPtr ctrl) { if (ctrl->def->nnets != ctrl->nveths) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("expecting %d veths, but got %zu"), - ctrl->def->nnets, ctrl->nveths); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("expecting %d veths, but got %zu"), + ctrl->def->nnets, ctrl->nveths); return -1; } @@ -304,9 +304,9 @@ static int virLXCControllerValidateNICs(virLXCControllerPtr ctrl) static int virLXCControllerValidateConsoles(virLXCControllerPtr ctrl) { if (ctrl->def->nconsoles != ctrl->nconsoles) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("expecting %d consoles, but got %zu tty file handlers"), - ctrl->def->nconsoles, ctrl->nconsoles); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("expecting %d consoles, but got %zu tty file handlers"), + ctrl->def->nconsoles, ctrl->nconsoles); return -1; } @@ -383,8 +383,8 @@ static int virLXCControllerSetupNUMAPolicy(virLXCControllerPtr ctrl) VIR_DEBUG("Setting NUMA memory policy"); if (numa_available() < 0) { - lxcError(VIR_ERR_CONFIG_UNSUPPORTED, - "%s", _("Host kernel is not aware of NUMA.")); + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("Host kernel is not aware of NUMA.")); return -1; } @@ -395,8 +395,8 @@ static int virLXCControllerSetupNUMAPolicy(virLXCControllerPtr ctrl) for (i = 0; i < VIR_DOMAIN_CPUMASK_LEN; i++) { if (ctrl->def->numatune.memory.nodemask[i]) { if (i > NUMA_NUM_NODES) { - lxcError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Host cannot support NUMA node %d"), i); + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Host cannot support NUMA node %d"), i); return -1; } if (i > maxnode && !warned) { @@ -424,9 +424,9 @@ static int virLXCControllerSetupNUMAPolicy(virLXCControllerPtr ctrl) } if (nnodes != 1) { - lxcError(VIR_ERR_CONFIG_UNSUPPORTED, - "%s", _("NUMA memory tuning in 'preferred' mode " - "only supports single node")); + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("NUMA memory tuning in 'preferred' mode " + "only supports single node")); goto cleanup; } @@ -435,9 +435,9 @@ static int virLXCControllerSetupNUMAPolicy(virLXCControllerPtr ctrl) } else if (mode == VIR_DOMAIN_NUMATUNE_MEM_INTERLEAVE) { numa_set_interleave_mask(&mask); } else { - lxcError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Unable to set NUMA policy %s"), - virDomainNumatuneMemModeTypeToString(mode)); + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Unable to set NUMA policy %s"), + virDomainNumatuneMemModeTypeToString(mode)); goto cleanup; } @@ -450,8 +450,8 @@ cleanup: static int virLXCControllerSetupNUMAPolicy(virLXCControllerPtr ctrl) { if (ctrl->def->numatune.memory.nodemask) { - lxcError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("NUMA policy is not available on this platform")); + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("NUMA policy is not available on this platform")); return -1; } @@ -602,8 +602,8 @@ static int lxcControllerClearCapabilities(void) capng_clear(CAPNG_SELECT_BOTH); if ((ret = capng_apply(CAPNG_SELECT_BOTH)) < 0) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("failed to apply capabilities: %d"), ret); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("failed to apply capabilities: %d"), ret); return -1; } #else @@ -913,8 +913,8 @@ static int virLXCControllerMain(virLXCControllerPtr ctrl) virLXCControllerConsoleEPoll, &(ctrl->consoles[i]), NULL)) < 0) { - lxcError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to watch epoll FD")); + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to watch epoll FD")); goto cleanup; } @@ -923,8 +923,8 @@ static int virLXCControllerMain(virLXCControllerPtr ctrl) virLXCControllerConsoleIO, &(ctrl->consoles[i]), NULL)) < 0) { - lxcError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to watch host console PTY")); + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to watch host console PTY")); goto cleanup; } @@ -933,8 +933,8 @@ static int virLXCControllerMain(virLXCControllerPtr ctrl) virLXCControllerConsoleIO, &(ctrl->consoles[i]), NULL)) < 0) { - lxcError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to watch host console PTY")); + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to watch host console PTY")); goto cleanup; } } @@ -1092,9 +1092,9 @@ virLXCControllerSetupDevPTS(virLXCControllerPtr ctrl) if (!root) { if (ctrl->nconsoles != 1) { - lxcError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Expected exactly one console, but got %zu"), - ctrl->nconsoles); + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Expected exactly one console, but got %zu"), + ctrl->nconsoles); return -1; } return 0; diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index fbbb1be..5f0d635 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -101,16 +101,16 @@ static virDrvOpenStatus lxcOpen(virConnectPtr conn, /* If path isn't '/' then they typoed, tell them correct path */ if (conn->uri->path != NULL && STRNEQ(conn->uri->path, "/")) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("Unexpected LXC URI path '%s', try lxc:///"), - conn->uri->path); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unexpected LXC URI path '%s', try lxc:///"), + conn->uri->path); return VIR_DRV_OPEN_ERROR; } /* URI was good, but driver isn't active */ if (lxc_driver == NULL) { - lxcError(VIR_ERR_INTERNAL_ERROR, - "%s", _("lxc state driver is not active")); + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("lxc state driver is not active")); return VIR_DRV_OPEN_ERROR; } } @@ -178,8 +178,8 @@ static virDomainPtr lxcDomainLookupByID(virConnectPtr conn, lxcDriverUnlock(driver); if (!vm) { - lxcError(VIR_ERR_NO_DOMAIN, - _("No domain with matching id %d"), id); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching id %d"), id); goto cleanup; } @@ -207,8 +207,8 @@ static virDomainPtr lxcDomainLookupByUUID(virConnectPtr conn, if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(uuid, uuidstr); - lxcError(VIR_ERR_NO_DOMAIN, - _("No domain with matching uuid '%s'"), uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } @@ -233,8 +233,8 @@ static virDomainPtr lxcDomainLookupByName(virConnectPtr conn, vm = virDomainFindByName(&driver->domains, name); lxcDriverUnlock(driver); if (!vm) { - lxcError(VIR_ERR_NO_DOMAIN, - _("No domain with matching name '%s'"), name); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching name '%s'"), name); goto cleanup; } @@ -261,8 +261,8 @@ static int lxcDomainIsActive(virDomainPtr dom) if (!obj) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); - lxcError(VIR_ERR_NO_DOMAIN, - _("No domain with matching uuid '%s'"), uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } ret = virDomainObjIsActive(obj); @@ -286,8 +286,8 @@ static int lxcDomainIsPersistent(virDomainPtr dom) if (!obj) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); - lxcError(VIR_ERR_NO_DOMAIN, - _("No domain with matching uuid '%s'"), uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } ret = obj->persistent; @@ -310,8 +310,8 @@ static int lxcDomainIsUpdated(virDomainPtr dom) if (!obj) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); - lxcError(VIR_ERR_NO_DOMAIN, - _("No domain with matching uuid '%s'"), uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } ret = obj->updated; @@ -392,8 +392,8 @@ static virDomainPtr lxcDomainDefine(virConnectPtr conn, const char *xml) goto cleanup; if ((def->nets != NULL) && !(driver->have_netns)) { - lxcError(VIR_ERR_OPERATION_INVALID, - "%s", _("System lacks NETNS support")); + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("System lacks NETNS support")); goto cleanup; } @@ -445,14 +445,14 @@ static int lxcDomainUndefineFlags(virDomainPtr dom, if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); - lxcError(VIR_ERR_NO_DOMAIN, - _("No domain with matching uuid '%s'"), uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } if (!vm->persistent) { - lxcError(VIR_ERR_OPERATION_INVALID, - "%s", _("Cannot undefine transient domain")); + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("Cannot undefine transient domain")); goto cleanup; } @@ -502,8 +502,8 @@ static int lxcDomainGetInfo(virDomainPtr dom, if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); - lxcError(VIR_ERR_NO_DOMAIN, - _("No domain with matching uuid '%s'"), uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } @@ -514,19 +514,19 @@ static int lxcDomainGetInfo(virDomainPtr dom, info->memory = vm->def->mem.cur_balloon; } else { if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("Unable to get cgroup for %s"), vm->def->name); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to get cgroup for %s"), vm->def->name); goto cleanup; } if (virCgroupGetCpuacctUsage(cgroup, &(info->cpuTime)) < 0) { - lxcError(VIR_ERR_OPERATION_FAILED, - "%s", _("Cannot read cputime for domain")); + virReportError(VIR_ERR_OPERATION_FAILED, + "%s", _("Cannot read cputime for domain")); goto cleanup; } if ((rc = virCgroupGetMemoryUsage(cgroup, &(info->memory))) < 0) { - lxcError(VIR_ERR_OPERATION_FAILED, - "%s", _("Cannot read memory usage for domain")); + virReportError(VIR_ERR_OPERATION_FAILED, + "%s", _("Cannot read memory usage for domain")); if (rc == -ENOENT) { /* Don't fail if we can't read memory usage due to a lack of * kernel support */ @@ -568,8 +568,8 @@ lxcDomainGetState(virDomainPtr dom, if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); - lxcError(VIR_ERR_NO_DOMAIN, - _("No domain with matching uuid '%s'"), uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } @@ -595,8 +595,8 @@ static char *lxcGetOSType(virDomainPtr dom) if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); - lxcError(VIR_ERR_NO_DOMAIN, - _("No domain with matching uuid '%s'"), uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } @@ -626,8 +626,8 @@ lxcDomainGetMaxMemory(virDomainPtr dom) if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); - lxcError(VIR_ERR_NO_DOMAIN, - _("No domain with matching uuid '%s'"), uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } @@ -651,14 +651,14 @@ static int lxcDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) { if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); - lxcError(VIR_ERR_NO_DOMAIN, - _("No domain with matching uuid '%s'"), uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } if (newmax < vm->def->mem.cur_balloon) { - lxcError(VIR_ERR_INVALID_ARG, - "%s", _("Cannot set max memory lower than current memory")); + virReportError(VIR_ERR_INVALID_ARG, + "%s", _("Cannot set max memory lower than current memory")); goto cleanup; } @@ -683,38 +683,38 @@ static int lxcDomainSetMemory(virDomainPtr dom, unsigned long newmem) { if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); - lxcError(VIR_ERR_NO_DOMAIN, - _("No domain with matching uuid '%s'"), uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } if (newmem > vm->def->mem.max_balloon) { - lxcError(VIR_ERR_INVALID_ARG, - "%s", _("Cannot set memory higher than max memory")); + virReportError(VIR_ERR_INVALID_ARG, + "%s", _("Cannot set memory higher than max memory")); goto cleanup; } if (!virDomainObjIsActive(vm)) { - lxcError(VIR_ERR_OPERATION_INVALID, - "%s", _("Domain is not running")); + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("Domain is not running")); goto cleanup; } if (driver->cgroup == NULL) { - lxcError(VIR_ERR_OPERATION_INVALID, - "%s", _("cgroups must be configured on the host")); + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("cgroups must be configured on the host")); goto cleanup; } if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("Unable to get cgroup for %s"), vm->def->name); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to get cgroup for %s"), vm->def->name); goto cleanup; } if (virCgroupSetMemory(cgroup, newmem) < 0) { - lxcError(VIR_ERR_OPERATION_FAILED, - "%s", _("Failed to set memory for domain")); + virReportError(VIR_ERR_OPERATION_FAILED, + "%s", _("Failed to set memory for domain")); goto cleanup; } @@ -758,14 +758,14 @@ lxcDomainSetMemoryParameters(virDomainPtr dom, if (vm == NULL) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); - lxcError(VIR_ERR_NO_DOMAIN, - _("No domain with matching uuid '%s'"), uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("cannot find cgroup for domain %s"), vm->def->name); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot find cgroup for domain %s"), vm->def->name); goto cleanup; } @@ -828,8 +828,8 @@ lxcDomainGetMemoryParameters(virDomainPtr dom, if (vm == NULL) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); - lxcError(VIR_ERR_NO_DOMAIN, - _("No domain with matching uuid '%s'"), uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } @@ -841,8 +841,8 @@ lxcDomainGetMemoryParameters(virDomainPtr dom, } if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("Unable to get cgroup for %s"), vm->def->name); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to get cgroup for %s"), vm->def->name); goto cleanup; } @@ -921,8 +921,8 @@ static char *lxcDomainGetXMLDesc(virDomainPtr dom, if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); - lxcError(VIR_ERR_NO_DOMAIN, - _("No domain with matching uuid '%s'"), uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } @@ -960,20 +960,20 @@ static int lxcDomainStartWithFlags(virDomainPtr dom, unsigned int flags) if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); - lxcError(VIR_ERR_NO_DOMAIN, - _("No domain with matching uuid '%s'"), uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } if ((vm->def->nets != NULL) && !(driver->have_netns)) { - lxcError(VIR_ERR_OPERATION_INVALID, - "%s", _("System lacks NETNS support")); + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("System lacks NETNS support")); goto cleanup; } if (virDomainObjIsActive(vm)) { - lxcError(VIR_ERR_OPERATION_INVALID, - "%s", _("Domain is already running")); + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("Domain is already running")); goto cleanup; } @@ -1047,8 +1047,8 @@ lxcDomainCreateAndStart(virConnectPtr conn, goto cleanup; if ((def->nets != NULL) && !(driver->have_netns)) { - lxcError(VIR_ERR_CONFIG_UNSUPPORTED, - "%s", _("System lacks NETNS support")); + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("System lacks NETNS support")); goto cleanup; } @@ -1101,15 +1101,15 @@ static int lxcDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr secla if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); - lxcError(VIR_ERR_NO_DOMAIN, - _("no domain with matching uuid '%s'"), uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("no domain with matching uuid '%s'"), uuidstr); goto cleanup; } if (!virDomainVirtTypeToString(vm->def->virtType)) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("unknown virt type in domain definition '%d'"), - vm->def->virtType); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown virt type in domain definition '%d'"), + vm->def->virtType); goto cleanup; } @@ -1130,8 +1130,8 @@ static int lxcDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr secla if (virDomainObjIsActive(vm)) { if (virSecurityManagerGetProcessLabel(driver->securityManager, vm->def, vm->pid, seclabel) < 0) { - lxcError(VIR_ERR_INTERNAL_ERROR, - "%s", _("Failed to get security label")); + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("Failed to get security label")); goto cleanup; } } @@ -1161,18 +1161,18 @@ static int lxcNodeGetSecurityModel(virConnectPtr conn, if (!virStrcpy(secmodel->model, driver->caps->host.secModel.model, VIR_SECURITY_MODEL_BUFLEN)) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("security model string exceeds max %d bytes"), - VIR_SECURITY_MODEL_BUFLEN - 1); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("security model string exceeds max %d bytes"), + VIR_SECURITY_MODEL_BUFLEN - 1); ret = -1; goto cleanup; } if (!virStrcpy(secmodel->doi, driver->caps->host.secModel.doi, VIR_SECURITY_DOI_BUFLEN)) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("security DOI string exceeds max %d bytes"), - VIR_SECURITY_DOI_BUFLEN-1); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("security DOI string exceeds max %d bytes"), + VIR_SECURITY_DOI_BUFLEN-1); ret = -1; goto cleanup; } @@ -1284,14 +1284,14 @@ lxcDomainDestroyFlags(virDomainPtr dom, if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); - lxcError(VIR_ERR_NO_DOMAIN, - _("No domain with matching uuid '%s'"), uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } if (!virDomainObjIsActive(vm)) { - lxcError(VIR_ERR_OPERATION_INVALID, - "%s", _("Domain is not running")); + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("Domain is not running")); goto cleanup; } @@ -1559,7 +1559,7 @@ static int lxcVersion(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned long *versio uname(&ver); if (virParseVersionString(ver.release, version, true) < 0) { - lxcError(VIR_ERR_INTERNAL_ERROR, _("Unknown release: %s"), ver.release); + virReportError(VIR_ERR_INTERNAL_ERROR, _("Unknown release: %s"), ver.release); return -1; } @@ -1627,8 +1627,8 @@ static char *lxcGetSchedulerType(virDomainPtr domain, lxcDriverLock(driver); if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) { - lxcError(VIR_ERR_OPERATION_INVALID, - "%s", _("cgroup CPU controller is not mounted")); + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("cgroup CPU controller is not mounted")); goto cleanup; } @@ -1756,8 +1756,8 @@ lxcSetSchedulerParametersFlags(virDomainPtr dom, vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (vm == NULL) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("No such domain %s"), dom->uuid); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("No such domain %s"), dom->uuid); goto cleanup; } @@ -1774,14 +1774,14 @@ lxcSetSchedulerParametersFlags(virDomainPtr dom, if (flags & VIR_DOMAIN_AFFECT_LIVE) { if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) { - lxcError(VIR_ERR_OPERATION_INVALID, - "%s", _("cgroup CPU controller is not mounted")); + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("cgroup CPU controller is not mounted")); goto cleanup; } if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("cannot find cgroup for domain %s"), - vm->def->name); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot find cgroup for domain %s"), + vm->def->name); goto cleanup; } } @@ -1898,8 +1898,8 @@ lxcGetSchedulerParametersFlags(virDomainPtr dom, vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (vm == NULL) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("No such domain %s"), dom->uuid); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("No such domain %s"), dom->uuid); goto cleanup; } @@ -1917,14 +1917,14 @@ lxcGetSchedulerParametersFlags(virDomainPtr dom, } if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) { - lxcError(VIR_ERR_OPERATION_INVALID, - "%s", _("cgroup CPU controller is not mounted")); + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("cgroup CPU controller is not mounted")); goto cleanup; } if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("cannot find cgroup for domain %s"), vm->def->name); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot find cgroup for domain %s"), vm->def->name); goto cleanup; } @@ -2011,8 +2011,8 @@ lxcDomainSetBlkioParameters(virDomainPtr dom, vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (vm == NULL) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("No such domain %s"), dom->uuid); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("No such domain %s"), dom->uuid); goto cleanup; } @@ -2022,13 +2022,13 @@ lxcDomainSetBlkioParameters(virDomainPtr dom, if (flags & VIR_DOMAIN_AFFECT_LIVE) { if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_BLKIO)) { - lxcError(VIR_ERR_OPERATION_INVALID, _("blkio cgroup isn't mounted")); + virReportError(VIR_ERR_OPERATION_INVALID, _("blkio cgroup isn't mounted")); goto cleanup; } if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("cannot find cgroup for domain %s"), vm->def->name); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot find cgroup for domain %s"), vm->def->name); goto cleanup; } @@ -2039,8 +2039,8 @@ lxcDomainSetBlkioParameters(virDomainPtr dom, int rc; if (params[i].value.ui > 1000 || params[i].value.ui < 100) { - lxcError(VIR_ERR_INVALID_ARG, "%s", - _("out of blkio weight range.")); + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("out of blkio weight range.")); goto cleanup; } @@ -2062,8 +2062,8 @@ lxcDomainSetBlkioParameters(virDomainPtr dom, if (STREQ(param->field, VIR_DOMAIN_BLKIO_WEIGHT)) { if (params[i].value.ui > 1000 || params[i].value.ui < 100) { - lxcError(VIR_ERR_INVALID_ARG, "%s", - _("out of blkio weight range.")); + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("out of blkio weight range.")); goto cleanup; } @@ -2108,8 +2108,8 @@ lxcDomainGetBlkioParameters(virDomainPtr dom, vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (vm == NULL) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("No such domain %s"), dom->uuid); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("No such domain %s"), dom->uuid); goto cleanup; } @@ -2126,13 +2126,13 @@ lxcDomainGetBlkioParameters(virDomainPtr dom, if (flags & VIR_DOMAIN_AFFECT_LIVE) { if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_BLKIO)) { - lxcError(VIR_ERR_OPERATION_INVALID, _("blkio cgroup isn't mounted")); + virReportError(VIR_ERR_OPERATION_INVALID, _("blkio cgroup isn't mounted")); goto cleanup; } if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("cannot find cgroup for domain %s"), vm->def->name); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot find cgroup for domain %s"), vm->def->name); goto cleanup; } @@ -2209,14 +2209,14 @@ lxcDomainInterfaceStats(virDomainPtr dom, if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); - lxcError(VIR_ERR_NO_DOMAIN, - _("No domain with matching uuid '%s'"), uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } if (!virDomainObjIsActive(vm)) { - lxcError(VIR_ERR_OPERATION_INVALID, - "%s", _("Domain is not running")); + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("Domain is not running")); goto cleanup; } @@ -2232,8 +2232,8 @@ lxcDomainInterfaceStats(virDomainPtr dom, if (ret == 0) ret = linuxDomainInterfaceStats(path, stats); else - lxcError(VIR_ERR_INVALID_ARG, - _("Invalid path, '%s' is not a known interface"), path); + virReportError(VIR_ERR_INVALID_ARG, + _("Invalid path, '%s' is not a known interface"), path); cleanup: if (vm) @@ -2246,7 +2246,7 @@ lxcDomainInterfaceStats(virDomainPtr dom, const char *path ATTRIBUTE_UNUSED, struct _virDomainInterfaceStats *stats ATTRIBUTE_UNUSED) { - lxcError(VIR_ERR_NO_SUPPORT, "%s", __FUNCTION__); + virReportError(VIR_ERR_NO_SUPPORT, "%s", __FUNCTION__); return -1; } #endif @@ -2264,8 +2264,8 @@ static int lxcDomainGetAutostart(virDomainPtr dom, if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); - lxcError(VIR_ERR_NO_DOMAIN, - _("No domain with matching uuid '%s'"), uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } @@ -2291,14 +2291,14 @@ static int lxcDomainSetAutostart(virDomainPtr dom, if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); - lxcError(VIR_ERR_NO_DOMAIN, - _("No domain with matching uuid '%s'"), uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } if (!vm->persistent) { - lxcError(VIR_ERR_OPERATION_INVALID, - "%s", _("Cannot set autostart for transient domain")); + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("Cannot set autostart for transient domain")); goto cleanup; } @@ -2459,21 +2459,21 @@ static int lxcDomainSuspend(virDomainPtr dom) if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); - lxcError(VIR_ERR_NO_DOMAIN, - _("No domain with matching uuid '%s'"), uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } if (!virDomainObjIsActive(vm)) { - lxcError(VIR_ERR_OPERATION_INVALID, - "%s", _("Domain is not running")); + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("Domain is not running")); goto cleanup; } if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) { if (lxcFreezeContainer(driver, vm) < 0) { - lxcError(VIR_ERR_OPERATION_FAILED, - "%s", _("Suspend operation failed")); + virReportError(VIR_ERR_OPERATION_FAILED, + "%s", _("Suspend operation failed")); goto cleanup; } virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER); @@ -2524,21 +2524,21 @@ static int lxcDomainResume(virDomainPtr dom) if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); - lxcError(VIR_ERR_NO_DOMAIN, - _("No domain with matching uuid '%s'"), uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } if (!virDomainObjIsActive(vm)) { - lxcError(VIR_ERR_OPERATION_INVALID, - "%s", _("Domain is not running")); + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("Domain is not running")); goto cleanup; } if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) { if (lxcUnfreezeContainer(driver, vm) < 0) { - lxcError(VIR_ERR_OPERATION_FAILED, - "%s", _("Resume operation failed")); + virReportError(VIR_ERR_OPERATION_FAILED, + "%s", _("Resume operation failed")); goto cleanup; } virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, @@ -2581,14 +2581,14 @@ lxcDomainOpenConsole(virDomainPtr dom, virUUIDFormat(dom->uuid, uuidstr); vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { - lxcError(VIR_ERR_NO_DOMAIN, - _("no domain with matching uuid '%s'"), uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("no domain with matching uuid '%s'"), uuidstr); goto cleanup; } if (!virDomainObjIsActive(vm)) { - lxcError(VIR_ERR_OPERATION_INVALID, - "%s", _("domain is not running")); + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not running")); goto cleanup; } @@ -2608,15 +2608,15 @@ lxcDomainOpenConsole(virDomainPtr dom, } if (!chr) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("cannot find console device '%s'"), - dev_name ? dev_name : _("default")); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot find console device '%s'"), + dev_name ? dev_name : _("default")); goto cleanup; } if (chr->source.type != VIR_DOMAIN_CHR_TYPE_PTY) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("character device %s is not using a PTY"), dev_name); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("character device %s is not using a PTY"), dev_name); goto cleanup; } diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index bc087d7..de11725 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -275,9 +275,9 @@ static int virLXCProcessSetupInterfaceBridged(virConnectPtr conn, if (virNetDevBandwidthSet(net->ifname, virDomainNetGetActualBandwidth(net)) < 0) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("cannot set bandwidth limits on %s"), - net->ifname); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot set bandwidth limits on %s"), + net->ifname); goto cleanup; } @@ -311,8 +311,8 @@ static int virLXCProcessSetupInterfaceDirect(virConnectPtr conn, */ bw = virDomainNetGetActualBandwidth(net); if (bw) { - lxcError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Unable to set network bandwidth on direct interfaces")); + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Unable to set network bandwidth on direct interfaces")); return -1; } @@ -325,8 +325,8 @@ static int virLXCProcessSetupInterfaceDirect(virConnectPtr conn, */ prof = virDomainNetGetActualVirtPortProfile(net); if (prof) { - lxcError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Unable to set port profile on direct interfaces")); + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Unable to set port profile on direct interfaces")); return -1; } @@ -416,8 +416,8 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn, case VIR_DOMAIN_NET_TYPE_BRIDGE: { const char *brname = virDomainNetGetActualBridgeName(def->nets[i]); if (!brname) { - lxcError(VIR_ERR_INTERNAL_ERROR, "%s", - _("No bridge name specified")); + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("No bridge name specified")); goto cleanup; } if (virLXCProcessSetupInterfaceBridged(conn, @@ -445,11 +445,11 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn, case VIR_DOMAIN_NET_TYPE_MCAST: case VIR_DOMAIN_NET_TYPE_INTERNAL: case VIR_DOMAIN_NET_TYPE_LAST: - lxcError(VIR_ERR_INTERNAL_ERROR, - _("Unsupported network type %s"), - virDomainNetTypeToString( - virDomainNetGetActualType(def->nets[i]) - )); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unsupported network type %s"), + virDomainNetTypeToString( + virDomainNetGetActualType(def->nets[i]) + )); goto cleanup; } } @@ -508,8 +508,8 @@ static int virLXCProcessMonitorClient(virLXCDriverPtr driver, memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; if (virStrcpyStatic(addr.sun_path, sockpath) == NULL) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("Socket path %s too big for destination"), sockpath); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Socket path %s too big for destination"), sockpath); goto error; } @@ -537,8 +537,8 @@ int virLXCProcessStop(virLXCDriverPtr driver, int rc; if (vm->pid <= 0) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("Invalid PID %d for container"), vm->pid); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid PID %d for container"), vm->pid); return -1; } @@ -561,8 +561,8 @@ int virLXCProcessStop(virLXCDriverPtr driver, goto cleanup; } if (rc == 1) { - lxcError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Some container PIDs refused to die")); + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Some container PIDs refused to die")); rc = -1; goto cleanup; } @@ -811,27 +811,27 @@ int virLXCProcessStart(virConnectPtr conn, virErrorPtr err = NULL; if (!lxc_driver->cgroup) { - lxcError(VIR_ERR_INTERNAL_ERROR, "%s", - _("The 'cpuacct', 'devices' & 'memory' cgroups controllers must be mounted")); + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("The 'cpuacct', 'devices' & 'memory' cgroups controllers must be mounted")); return -1; } if (!virCgroupMounted(lxc_driver->cgroup, VIR_CGROUP_CONTROLLER_CPUACCT)) { - lxcError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to find 'cpuacct' cgroups controller mount")); + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to find 'cpuacct' cgroups controller mount")); return -1; } if (!virCgroupMounted(lxc_driver->cgroup, VIR_CGROUP_CONTROLLER_DEVICES)) { - lxcError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to find 'devices' cgroups controller mount")); + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to find 'devices' cgroups controller mount")); return -1; } if (!virCgroupMounted(lxc_driver->cgroup, VIR_CGROUP_CONTROLLER_MEMORY)) { - lxcError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to find 'memory' cgroups controller mount")); + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to find 'memory' cgroups controller mount")); return -1; } @@ -906,8 +906,8 @@ int virLXCProcessStart(virConnectPtr conn, for (i = 0 ; i < vm->def->nconsoles ; i++) { char *ttyPath; if (vm->def->consoles[i]->source.type != VIR_DOMAIN_CHR_TYPE_PTY) { - lxcError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Only PTY console types are supported")); + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Only PTY console types are supported")); goto cleanup; } @@ -1021,8 +1021,8 @@ int virLXCProcessStart(virConnectPtr conn, char out[1024]; if (!(virLXCProcessReadLogOutput(vm, logfile, pos, out, 1024) < 0)) { - lxcError(VIR_ERR_INTERNAL_ERROR, - _("guest failed to start: %s"), out); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("guest failed to start: %s"), out); } goto error; -- 1.7.10.4

On Tue, Jul 24, 2012 at 14:22:47 +0100, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
Update all LXC code to use virReportError instead of the custom lxcError macro
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/lxc/lxc_conf.c | 10 +- src/lxc/lxc_conf.h | 5 - src/lxc/lxc_container.c | 30 ++--- src/lxc/lxc_controller.c | 58 ++++----- src/lxc/lxc_driver.c | 304 +++++++++++++++++++++++----------------------- src/lxc/lxc_process.c | 64 +++++----- 6 files changed, 233 insertions(+), 238 deletions(-)
ACK Jirka

From: "Daniel P. Berrange" <berrange@redhat.com> Update the LXC driver to use the virNetClient APIs for connecting to the libvirt_lxc monitor, instead of the low-level socket APIs. This is a step towards running a full RPC protocol with libvirt_lxc Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/lxc/lxc_domain.c | 3 - src/lxc/lxc_domain.h | 5 +- src/lxc/lxc_process.c | 162 +++++++++++++++++-------------------------------- 3 files changed, 59 insertions(+), 111 deletions(-) diff --git a/src/lxc/lxc_domain.c b/src/lxc/lxc_domain.c index 847aac7..2ce2a18 100644 --- a/src/lxc/lxc_domain.c +++ b/src/lxc/lxc_domain.c @@ -32,9 +32,6 @@ static void *virLXCDomainObjPrivateAlloc(void) if (VIR_ALLOC(priv) < 0) return NULL; - priv->monitor = -1; - priv->monitorWatch = -1; - return priv; } diff --git a/src/lxc/lxc_domain.h b/src/lxc/lxc_domain.h index 8a2c892..799248d 100644 --- a/src/lxc/lxc_domain.h +++ b/src/lxc/lxc_domain.h @@ -24,12 +24,13 @@ # define __LXC_DOMAIN_H__ # include "lxc_conf.h" +# include "rpc/virnetclient.h" + typedef struct _virLXCDomainObjPrivate virLXCDomainObjPrivate; typedef virLXCDomainObjPrivate *virLXCDomainObjPrivatePtr; struct _virLXCDomainObjPrivate { - int monitor; - int monitorWatch; + virNetClientPtr monitor; }; void virLXCDomainSetPrivateDataHooks(virCapsPtr caps); diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index de11725..3a1959f 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -178,8 +178,9 @@ static void virLXCProcessCleanup(virLXCDriverPtr driver, /* Stop autodestroy in case guest is restarted */ virLXCProcessAutoDestroyRemove(driver, vm); - virEventRemoveHandle(priv->monitorWatch); - VIR_FORCE_CLOSE(priv->monitor); + virNetClientClose(priv->monitor); + virNetClientFree(priv->monitor); + priv->monitor = NULL; virPidFileDelete(driver->stateDir, vm->def->name); virDomainDeleteConfig(driver->stateDir, NULL, vm); @@ -187,8 +188,6 @@ static void virLXCProcessCleanup(virLXCDriverPtr driver, virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason); vm->pid = -1; vm->def->id = -1; - priv->monitor = -1; - priv->monitorWatch = -1; for (i = 0 ; i < vm->def->nnets ; i++) { virDomainNetDefPtr iface = vm->def->nets[i]; @@ -472,60 +471,70 @@ cleanup: } -static int virLXCProcessMonitorClient(virLXCDriverPtr driver, - virDomainObjPtr vm) +extern virLXCDriverPtr lxc_driver; +static void virLXCProcessMonitorEOFNotify(virNetClientPtr client ATTRIBUTE_UNUSED, + int reason ATTRIBUTE_UNUSED, + void *opaque) +{ + virLXCDriverPtr driver = lxc_driver; + virDomainObjPtr vm = opaque; + virDomainEventPtr event = NULL; + + lxcDriverLock(driver); + virDomainObjLock(vm); + lxcDriverUnlock(driver); + + virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN); + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); + virDomainAuditStop(vm, "shutdown"); + if (!vm->persistent) { + virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } + + if (vm) + virDomainObjUnlock(vm); + if (event) { + lxcDriverLock(driver); + virDomainEventStateQueue(driver->domainEventState, event); + lxcDriverUnlock(driver); + } +} + + +static virNetClientPtr virLXCProcessConnectMonitor(virLXCDriverPtr driver, + virDomainObjPtr vm) { char *sockpath = NULL; - int fd = -1; - struct sockaddr_un addr; + virNetClientPtr monitor = NULL; if (virAsprintf(&sockpath, "%s/%s.sock", driver->stateDir, vm->def->name) < 0) { virReportOOMError(); - return -1; + return NULL; } - if (virSecurityManagerSetSocketLabel(driver->securityManager, vm->def) < 0) { - VIR_ERROR(_("Failed to set security context for monitor for %s"), - vm->def->name); - goto error; - } + if (virSecurityManagerSetSocketLabel(driver->securityManager, vm->def) < 0) + goto cleanup; - fd = socket(PF_UNIX, SOCK_STREAM, 0); + monitor = virNetClientNewUNIX(sockpath, false, NULL); if (virSecurityManagerClearSocketLabel(driver->securityManager, vm->def) < 0) { - VIR_ERROR(_("Failed to clear security context for monitor for %s"), - vm->def->name); - goto error; - } - - if (fd < 0) { - virReportSystemError(errno, "%s", - _("Failed to create client socket")); - goto error; - } - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - if (virStrcpyStatic(addr.sun_path, sockpath) == NULL) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Socket path %s too big for destination"), sockpath); - goto error; + virNetClientFree(monitor); + monitor = NULL; + goto cleanup; } - if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - virReportSystemError(errno, "%s", - _("Failed to connect to client socket")); - goto error; - } + if (!monitor) + goto cleanup; - VIR_FREE(sockpath); - return fd; + virNetClientSetCloseCallback(monitor, virLXCProcessMonitorEOFNotify, vm, NULL); -error: +cleanup: VIR_FREE(sockpath); - VIR_FORCE_CLOSE(fd); - return -1; + return monitor; } @@ -581,51 +590,6 @@ cleanup: return rc; } -extern virLXCDriverPtr lxc_driver; -static void virLXCProcessMonitorEvent(int watch, - int fd, - int events ATTRIBUTE_UNUSED, - void *data) -{ - virLXCDriverPtr driver = lxc_driver; - virDomainObjPtr vm = data; - virDomainEventPtr event = NULL; - virLXCDomainObjPrivatePtr priv; - - lxcDriverLock(driver); - virDomainObjLock(vm); - lxcDriverUnlock(driver); - - priv = vm->privateData; - - if (priv->monitor != fd || priv->monitorWatch != watch) { - virEventRemoveHandle(watch); - goto cleanup; - } - - if (virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN) < 0) { - virEventRemoveHandle(watch); - } else { - event = virDomainEventNewFromObj(vm, - VIR_DOMAIN_EVENT_STOPPED, - VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); - virDomainAuditStop(vm, "shutdown"); - } - if (!vm->persistent) { - virDomainRemoveInactive(&driver->domains, vm); - vm = NULL; - } - -cleanup: - if (vm) - virDomainObjUnlock(vm); - if (event) { - lxcDriverLock(driver); - virDomainEventStateQueue(driver->domainEventState, event); - lxcDriverUnlock(driver); - } -} - static virCommandPtr virLXCProcessBuildControllerCmd(virLXCDriverPtr driver, @@ -1003,7 +967,7 @@ int virLXCProcessStart(virConnectPtr conn, /* Connect to the controller as a client *first* because * this will block until the child has written their * pid file out to disk */ - if ((priv->monitor = virLXCProcessMonitorClient(driver, vm)) < 0) + if (!(priv->monitor = virLXCProcessConnectMonitor(driver, vm))) goto cleanup; /* And get its pid */ @@ -1028,14 +992,6 @@ int virLXCProcessStart(virConnectPtr conn, goto error; } - if ((priv->monitorWatch = virEventAddHandle( - priv->monitor, - VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_HANGUP, - virLXCProcessMonitorEvent, - vm, NULL)) < 0) { - goto error; - } - if (autoDestroy && virLXCProcessAutoDestroyAdd(driver, vm, conn) < 0) goto error; @@ -1085,7 +1041,9 @@ cleanup: VIR_FREE(veths[i]); } if (rc != 0) { - VIR_FORCE_CLOSE(priv->monitor); + virNetClientClose(priv->monitor); + virNetClientFree(priv->monitor); + priv->monitor = NULL; virDomainConfVMNWFilterTeardown(vm); virSecurityManagerRestoreAllLabel(driver->securityManager, @@ -1191,14 +1149,7 @@ virLXCProcessReconnectDomain(void *payload, const void *name ATTRIBUTE_UNUSED, v virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNKNOWN); - if ((priv->monitor = virLXCProcessMonitorClient(driver, vm)) < 0) - goto error; - - if ((priv->monitorWatch = virEventAddHandle( - priv->monitor, - VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_HANGUP, - virLXCProcessMonitorEvent, - vm, NULL)) < 0) + if (!(priv->monitor = virLXCProcessConnectMonitor(driver, vm))) goto error; if (virSecurityManagerReserveLabel(driver->securityManager, @@ -1221,7 +1172,6 @@ virLXCProcessReconnectDomain(void *payload, const void *name ATTRIBUTE_UNUSED, v } else { vm->def->id = -1; - VIR_FORCE_CLOSE(priv->monitor); } cleanup: -- 1.7.10.4

On Tue, Jul 24, 2012 at 14:22:48 +0100, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
Update the LXC driver to use the virNetClient APIs for connecting to the libvirt_lxc monitor, instead of the low-level socket APIs. This is a step towards running a full RPC protocol with libvirt_lxc
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/lxc/lxc_domain.c | 3 - src/lxc/lxc_domain.h | 5 +- src/lxc/lxc_process.c | 162 +++++++++++++++++-------------------------------- 3 files changed, 59 insertions(+), 111 deletions(-)
ACK Jirka

From: "Daniel P. Berrange" <berrange@redhat.com> Move the code that handles the LXC monitor out of the lxc_process.c file and into lxc_monitor.{c,h} Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- po/POTFILES.in | 1 + src/Makefile.am | 1 + src/lxc/lxc_domain.h | 4 +- src/lxc/lxc_monitor.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++++ src/lxc/lxc_monitor.h | 54 ++++++++++++++++ src/lxc/lxc_process.c | 70 ++++++++++++--------- 6 files changed, 262 insertions(+), 31 deletions(-) create mode 100644 src/lxc/lxc_monitor.c create mode 100644 src/lxc/lxc_monitor.h diff --git a/po/POTFILES.in b/po/POTFILES.in index 7587c61..025d7fa 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -47,6 +47,7 @@ src/lxc/lxc_container.c src/lxc/lxc_conf.c src/lxc/lxc_controller.c src/lxc/lxc_driver.c +src/lxc/lxc_monitor.c src/lxc/lxc_process.c src/libxl/libxl_driver.c src/libxl/libxl_conf.c diff --git a/src/Makefile.am b/src/Makefile.am index 93fcf3b..a910aa1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -352,6 +352,7 @@ LXC_DRIVER_SOURCES = \ lxc/lxc_container.c lxc/lxc_container.h \ lxc/lxc_cgroup.c lxc/lxc_cgroup.h \ lxc/lxc_domain.c lxc/lxc_domain.h \ + lxc/lxc_monitor.c lxc/lxc_monitor.h \ lxc/lxc_process.c lxc/lxc_process.h \ lxc/lxc_driver.c lxc/lxc_driver.h diff --git a/src/lxc/lxc_domain.h b/src/lxc/lxc_domain.h index 799248d..ff7c96f 100644 --- a/src/lxc/lxc_domain.h +++ b/src/lxc/lxc_domain.h @@ -24,13 +24,13 @@ # define __LXC_DOMAIN_H__ # include "lxc_conf.h" -# include "rpc/virnetclient.h" +# include "lxc_monitor.h" typedef struct _virLXCDomainObjPrivate virLXCDomainObjPrivate; typedef virLXCDomainObjPrivate *virLXCDomainObjPrivatePtr; struct _virLXCDomainObjPrivate { - virNetClientPtr monitor; + virLXCMonitorPtr monitor; }; void virLXCDomainSetPrivateDataHooks(virCapsPtr caps); diff --git a/src/lxc/lxc_monitor.c b/src/lxc/lxc_monitor.c new file mode 100644 index 0000000..6740aa7 --- /dev/null +++ b/src/lxc/lxc_monitor.c @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2010-2012 Red Hat, Inc. + * + * lxc_monitor.c: client for LXC controller monitor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <config.h> + +#include "lxc_monitor.h" +#include "lxc_conf.h" + +#include "memory.h" + +#include "virterror_internal.h" +#include "logging.h" +#include "threads.h" +#include "rpc/virnetclient.h" + +#define VIR_FROM_THIS VIR_FROM_LXC + +struct _virLXCMonitor { + int refs; + + virMutex lock; /* also used to protect fd */ + + virDomainObjPtr vm; + virLXCMonitorCallbacksPtr cb; + + virNetClientPtr client; +}; + +static void virLXCMonitorFree(virLXCMonitorPtr mon); + + +static void virLXCMonitorEOFNotify(virNetClientPtr client ATTRIBUTE_UNUSED, + int reason ATTRIBUTE_UNUSED, + void *opaque) +{ + virLXCMonitorPtr mon = opaque; + virLXCMonitorCallbackEOFNotify eofNotify; + virDomainObjPtr vm; + + virLXCMonitorLock(mon); + eofNotify = mon->cb->eofNotify; + vm = mon->vm; + virLXCMonitorUnlock(mon); + + eofNotify(mon, vm); +} + + +virLXCMonitorPtr virLXCMonitorNew(virDomainObjPtr vm, + const char *socketdir, + virLXCMonitorCallbacksPtr cb) +{ + virLXCMonitorPtr mon; + char *sockpath = NULL; + + if (VIR_ALLOC(mon) < 0) + return NULL; + + if (virMutexInit(&mon->lock) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot initialize monitor mutex")); + VIR_FREE(mon); + return NULL; + } + + if (virAsprintf(&sockpath, "%s/%s.sock", + socketdir, vm->def->name) < 0) + goto no_memory; + + if (!(mon->client = virNetClientNewUNIX(sockpath, false, NULL))) + goto error; + + + mon->vm = vm; + mon->cb = cb; + + virNetClientSetCloseCallback(mon->client, virLXCMonitorEOFNotify, mon, NULL); + +cleanup: + VIR_FREE(sockpath); + return mon; + +no_memory: + virReportOOMError(); +error: + virLXCMonitorClose(mon); + virLXCMonitorFree(mon); + mon = NULL; + goto cleanup; +} + + +static void virLXCMonitorFree(virLXCMonitorPtr mon) +{ + VIR_DEBUG("mon=%p", mon); + if (mon->client) + virLXCMonitorClose(mon); + + if (mon->cb && mon->cb->destroy) + (mon->cb->destroy)(mon, mon->vm); + virMutexDestroy(&mon->lock); + virNetClientFree(mon->client); + VIR_FREE(mon); +} + + +int virLXCMonitorRef(virLXCMonitorPtr mon) +{ + mon->refs++; + return mon->refs; +} + +int virLXCMonitorUnref(virLXCMonitorPtr mon) +{ + mon->refs--; + + if (mon->refs == 0) { + virLXCMonitorUnlock(mon); + virLXCMonitorFree(mon); + return 0; + } + + return mon->refs; +} + + +void virLXCMonitorClose(virLXCMonitorPtr mon) +{ + if (mon->client) { + virNetClientClose(mon->client); + virNetClientFree(mon->client); + mon->client = NULL; + } +} + + +void virLXCMonitorLock(virLXCMonitorPtr mon) +{ + virMutexLock(&mon->lock); +} + + +void virLXCMonitorUnlock(virLXCMonitorPtr mon) +{ + virMutexUnlock(&mon->lock); +} diff --git a/src/lxc/lxc_monitor.h b/src/lxc/lxc_monitor.h new file mode 100644 index 0000000..32b8d36 --- /dev/null +++ b/src/lxc/lxc_monitor.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2010-2012 Red Hat, Inc. + * + * lxc_monitor.h: client for LXC controller monitor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LXC_MONITOR_H__ +# define __LXC_MONITOR_H__ + +# include "domain_conf.h" + +typedef struct _virLXCMonitor virLXCMonitor; +typedef virLXCMonitor *virLXCMonitorPtr; + +typedef struct _virLXCMonitorCallbacks virLXCMonitorCallbacks; +typedef virLXCMonitorCallbacks *virLXCMonitorCallbacksPtr; + +typedef void (*virLXCMonitorCallbackDestroy)(virLXCMonitorPtr mon, + virDomainObjPtr vm); +typedef void (*virLXCMonitorCallbackEOFNotify)(virLXCMonitorPtr mon, + virDomainObjPtr vm); + +struct _virLXCMonitorCallbacks { + virLXCMonitorCallbackDestroy destroy; + virLXCMonitorCallbackEOFNotify eofNotify; +}; + +virLXCMonitorPtr virLXCMonitorNew(virDomainObjPtr vm, + const char *socketdir, + virLXCMonitorCallbacksPtr cb); + +void virLXCMonitorClose(virLXCMonitorPtr mon); + +void virLXCMonitorLock(virLXCMonitorPtr mon); +void virLXCMonitorUnlock(virLXCMonitorPtr mon); + +int virLXCMonitorRef(virLXCMonitorPtr mon); +int virLXCMonitorUnref(virLXCMonitorPtr mon); + +#endif /* __LXC_MONITOR_H__ */ diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 3a1959f..1bfd032 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -178,9 +178,11 @@ static void virLXCProcessCleanup(virLXCDriverPtr driver, /* Stop autodestroy in case guest is restarted */ virLXCProcessAutoDestroyRemove(driver, vm); - virNetClientClose(priv->monitor); - virNetClientFree(priv->monitor); - priv->monitor = NULL; + if (priv->monitor) { + virLXCMonitorClose(priv->monitor); + virLXCMonitorUnref(priv->monitor); + priv->monitor = NULL; + } virPidFileDelete(driver->stateDir, vm->def->name); virDomainDeleteConfig(driver->stateDir, NULL, vm); @@ -471,13 +473,25 @@ cleanup: } +static void virLXCProcessMonitorDestroy(virLXCMonitorPtr mon, + virDomainObjPtr vm) +{ + virLXCDomainObjPrivatePtr priv; + + virDomainObjLock(vm); + priv = vm->privateData; + if (priv->monitor == mon) + priv->monitor = NULL; + if (virDomainObjUnref(vm) > 0) + virDomainObjUnlock(vm); +} + + extern virLXCDriverPtr lxc_driver; -static void virLXCProcessMonitorEOFNotify(virNetClientPtr client ATTRIBUTE_UNUSED, - int reason ATTRIBUTE_UNUSED, - void *opaque) +static void virLXCProcessMonitorEOFNotify(virLXCMonitorPtr mon ATTRIBUTE_UNUSED, + virDomainObjPtr vm) { virLXCDriverPtr driver = lxc_driver; - virDomainObjPtr vm = opaque; virDomainEventPtr event = NULL; lxcDriverLock(driver); @@ -504,36 +518,32 @@ static void virLXCProcessMonitorEOFNotify(virNetClientPtr client ATTRIBUTE_UNUSE } -static virNetClientPtr virLXCProcessConnectMonitor(virLXCDriverPtr driver, - virDomainObjPtr vm) -{ - char *sockpath = NULL; - virNetClientPtr monitor = NULL; +static virLXCMonitorCallbacks monitorCallbacks = { + .eofNotify = virLXCProcessMonitorEOFNotify, + .destroy = virLXCProcessMonitorDestroy, +}; - if (virAsprintf(&sockpath, "%s/%s.sock", - driver->stateDir, vm->def->name) < 0) { - virReportOOMError(); - return NULL; - } + +static virLXCMonitorPtr virLXCProcessConnectMonitor(virLXCDriverPtr driver, + virDomainObjPtr vm) +{ + virLXCMonitorPtr monitor = NULL; if (virSecurityManagerSetSocketLabel(driver->securityManager, vm->def) < 0) goto cleanup; - monitor = virNetClientNewUNIX(sockpath, false, NULL); + monitor = virLXCMonitorNew(vm, driver->stateDir, &monitorCallbacks); if (virSecurityManagerClearSocketLabel(driver->securityManager, vm->def) < 0) { - virNetClientFree(monitor); - monitor = NULL; + if (monitor) { + virLXCMonitorClose(monitor); + virLXCMonitorUnref(monitor); + monitor = NULL; + } goto cleanup; } - if (!monitor) - goto cleanup; - - virNetClientSetCloseCallback(monitor, virLXCProcessMonitorEOFNotify, vm, NULL); - cleanup: - VIR_FREE(sockpath); return monitor; } @@ -1041,9 +1051,11 @@ cleanup: VIR_FREE(veths[i]); } if (rc != 0) { - virNetClientClose(priv->monitor); - virNetClientFree(priv->monitor); - priv->monitor = NULL; + if (priv->monitor) { + virLXCMonitorClose(priv->monitor); + virLXCMonitorUnref(priv->monitor); + priv->monitor = NULL; + } virDomainConfVMNWFilterTeardown(vm); virSecurityManagerRestoreAllLabel(driver->securityManager, -- 1.7.10.4

On Tue, Jul 24, 2012 at 14:22:49 +0100, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
Move the code that handles the LXC monitor out of the lxc_process.c file and into lxc_monitor.{c,h}
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- po/POTFILES.in | 1 + src/Makefile.am | 1 + src/lxc/lxc_domain.h | 4 +- src/lxc/lxc_monitor.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++++ src/lxc/lxc_monitor.h | 54 ++++++++++++++++ src/lxc/lxc_process.c | 70 ++++++++++++--------- 6 files changed, 262 insertions(+), 31 deletions(-) create mode 100644 src/lxc/lxc_monitor.c create mode 100644 src/lxc/lxc_monitor.h
diff --git a/po/POTFILES.in b/po/POTFILES.in index 7587c61..025d7fa 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -47,6 +47,7 @@ src/lxc/lxc_container.c src/lxc/lxc_conf.c src/lxc/lxc_controller.c src/lxc/lxc_driver.c +src/lxc/lxc_monitor.c src/lxc/lxc_process.c src/libxl/libxl_driver.c src/libxl/libxl_conf.c diff --git a/src/Makefile.am b/src/Makefile.am index 93fcf3b..a910aa1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -352,6 +352,7 @@ LXC_DRIVER_SOURCES = \ lxc/lxc_container.c lxc/lxc_container.h \ lxc/lxc_cgroup.c lxc/lxc_cgroup.h \ lxc/lxc_domain.c lxc/lxc_domain.h \ + lxc/lxc_monitor.c lxc/lxc_monitor.h \ lxc/lxc_process.c lxc/lxc_process.h \ lxc/lxc_driver.c lxc/lxc_driver.h
diff --git a/src/lxc/lxc_domain.h b/src/lxc/lxc_domain.h index 799248d..ff7c96f 100644 --- a/src/lxc/lxc_domain.h +++ b/src/lxc/lxc_domain.h @@ -24,13 +24,13 @@ # define __LXC_DOMAIN_H__
# include "lxc_conf.h" -# include "rpc/virnetclient.h" +# include "lxc_monitor.h"
typedef struct _virLXCDomainObjPrivate virLXCDomainObjPrivate; typedef virLXCDomainObjPrivate *virLXCDomainObjPrivatePtr; struct _virLXCDomainObjPrivate { - virNetClientPtr monitor; + virLXCMonitorPtr monitor; };
void virLXCDomainSetPrivateDataHooks(virCapsPtr caps); diff --git a/src/lxc/lxc_monitor.c b/src/lxc/lxc_monitor.c new file mode 100644 index 0000000..6740aa7 --- /dev/null +++ b/src/lxc/lxc_monitor.c @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2010-2012 Red Hat, Inc. + * + * lxc_monitor.c: client for LXC controller monitor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */
The last paragraph should rather be * You should have received a copy of the GNU Lesser General Public * License along with this library; If not, see * <http://www.gnu.org/licenses/>.
+ +#include <config.h> + +#include "lxc_monitor.h" +#include "lxc_conf.h" + +#include "memory.h" + +#include "virterror_internal.h" +#include "logging.h" +#include "threads.h" +#include "rpc/virnetclient.h" + +#define VIR_FROM_THIS VIR_FROM_LXC + +struct _virLXCMonitor { + int refs; + + virMutex lock; /* also used to protect fd */
Which fd are you referring to?
+ + virDomainObjPtr vm; + virLXCMonitorCallbacksPtr cb; + + virNetClientPtr client; +}; + +static void virLXCMonitorFree(virLXCMonitorPtr mon); + + +static void virLXCMonitorEOFNotify(virNetClientPtr client ATTRIBUTE_UNUSED, + int reason ATTRIBUTE_UNUSED, + void *opaque) +{ + virLXCMonitorPtr mon = opaque; + virLXCMonitorCallbackEOFNotify eofNotify; + virDomainObjPtr vm; + + virLXCMonitorLock(mon); + eofNotify = mon->cb->eofNotify; + vm = mon->vm; + virLXCMonitorUnlock(mon); + + eofNotify(mon, vm); +} + + +virLXCMonitorPtr virLXCMonitorNew(virDomainObjPtr vm, + const char *socketdir, + virLXCMonitorCallbacksPtr cb) +{ + virLXCMonitorPtr mon; + char *sockpath = NULL; + + if (VIR_ALLOC(mon) < 0)
virReportOOMError() is missing here
+ return NULL; + + if (virMutexInit(&mon->lock) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot initialize monitor mutex")); + VIR_FREE(mon); + return NULL; + } + + if (virAsprintf(&sockpath, "%s/%s.sock", + socketdir, vm->def->name) < 0) + goto no_memory; + + if (!(mon->client = virNetClientNewUNIX(sockpath, false, NULL))) + goto error; + + + mon->vm = vm; + mon->cb = cb; + + virNetClientSetCloseCallback(mon->client, virLXCMonitorEOFNotify, mon, NULL); + +cleanup: + VIR_FREE(sockpath); + return mon; + +no_memory: + virReportOOMError(); +error: + virLXCMonitorClose(mon); + virLXCMonitorFree(mon);
No need to explicitly call virLXCMonitorClose here, virLXCMonitorFree already calls virLXCMonitorClose if necessary.
+ mon = NULL; + goto cleanup; +} + + +static void virLXCMonitorFree(virLXCMonitorPtr mon) +{ + VIR_DEBUG("mon=%p", mon); + if (mon->client) + virLXCMonitorClose(mon); + + if (mon->cb && mon->cb->destroy) + (mon->cb->destroy)(mon, mon->vm); + virMutexDestroy(&mon->lock); + virNetClientFree(mon->client);
No need to call virNetClientFree here since mon->client will always be NULL at this point (virLXCMonitorClose already freed it).
+ VIR_FREE(mon); +} + + +int virLXCMonitorRef(virLXCMonitorPtr mon) +{ + mon->refs++; + return mon->refs; +} + +int virLXCMonitorUnref(virLXCMonitorPtr mon) +{ + mon->refs--; + + if (mon->refs == 0) { + virLXCMonitorUnlock(mon); + virLXCMonitorFree(mon); + return 0; + } + + return mon->refs; +} + + +void virLXCMonitorClose(virLXCMonitorPtr mon) +{ + if (mon->client) { + virNetClientClose(mon->client); + virNetClientFree(mon->client); + mon->client = NULL; + } +} + + +void virLXCMonitorLock(virLXCMonitorPtr mon) +{ + virMutexLock(&mon->lock); +} + + +void virLXCMonitorUnlock(virLXCMonitorPtr mon) +{ + virMutexUnlock(&mon->lock); +} diff --git a/src/lxc/lxc_monitor.h b/src/lxc/lxc_monitor.h new file mode 100644 index 0000000..32b8d36 --- /dev/null +++ b/src/lxc/lxc_monitor.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2010-2012 Red Hat, Inc. + * + * lxc_monitor.h: client for LXC controller monitor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Obsolete usage of FSF address again.
+ */ + +#ifndef __LXC_MONITOR_H__ +# define __LXC_MONITOR_H__ + +# include "domain_conf.h" + +typedef struct _virLXCMonitor virLXCMonitor; +typedef virLXCMonitor *virLXCMonitorPtr; + +typedef struct _virLXCMonitorCallbacks virLXCMonitorCallbacks; +typedef virLXCMonitorCallbacks *virLXCMonitorCallbacksPtr; + +typedef void (*virLXCMonitorCallbackDestroy)(virLXCMonitorPtr mon, + virDomainObjPtr vm); +typedef void (*virLXCMonitorCallbackEOFNotify)(virLXCMonitorPtr mon, + virDomainObjPtr vm); + +struct _virLXCMonitorCallbacks { + virLXCMonitorCallbackDestroy destroy; + virLXCMonitorCallbackEOFNotify eofNotify; +}; + +virLXCMonitorPtr virLXCMonitorNew(virDomainObjPtr vm, + const char *socketdir, + virLXCMonitorCallbacksPtr cb); + +void virLXCMonitorClose(virLXCMonitorPtr mon); + +void virLXCMonitorLock(virLXCMonitorPtr mon); +void virLXCMonitorUnlock(virLXCMonitorPtr mon); + +int virLXCMonitorRef(virLXCMonitorPtr mon); +int virLXCMonitorUnref(virLXCMonitorPtr mon); + +#endif /* __LXC_MONITOR_H__ */ diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 3a1959f..1bfd032 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -178,9 +178,11 @@ static void virLXCProcessCleanup(virLXCDriverPtr driver, /* Stop autodestroy in case guest is restarted */ virLXCProcessAutoDestroyRemove(driver, vm);
- virNetClientClose(priv->monitor); - virNetClientFree(priv->monitor); - priv->monitor = NULL; + if (priv->monitor) { + virLXCMonitorClose(priv->monitor); + virLXCMonitorUnref(priv->monitor);
Shouldn't we unlock the monitor if virLXCMonitorUnref returns positive number? If not because we know priv->monitor is the last reference, we don't need to explicitly call virLXCMonitorClose. In any case, virLXCMonitorUnref requires monitor to be locked.
+ priv->monitor = NULL; + }
virPidFileDelete(driver->stateDir, vm->def->name); virDomainDeleteConfig(driver->stateDir, NULL, vm); @@ -471,13 +473,25 @@ cleanup: }
+static void virLXCProcessMonitorDestroy(virLXCMonitorPtr mon, + virDomainObjPtr vm) +{ + virLXCDomainObjPrivatePtr priv; + + virDomainObjLock(vm); + priv = vm->privateData; + if (priv->monitor == mon) + priv->monitor = NULL; + if (virDomainObjUnref(vm) > 0) + virDomainObjUnlock(vm); +} + + extern virLXCDriverPtr lxc_driver; -static void virLXCProcessMonitorEOFNotify(virNetClientPtr client ATTRIBUTE_UNUSED, - int reason ATTRIBUTE_UNUSED, - void *opaque) +static void virLXCProcessMonitorEOFNotify(virLXCMonitorPtr mon ATTRIBUTE_UNUSED, + virDomainObjPtr vm) { virLXCDriverPtr driver = lxc_driver; - virDomainObjPtr vm = opaque; virDomainEventPtr event = NULL;
lxcDriverLock(driver); @@ -504,36 +518,32 @@ static void virLXCProcessMonitorEOFNotify(virNetClientPtr client ATTRIBUTE_UNUSE }
-static virNetClientPtr virLXCProcessConnectMonitor(virLXCDriverPtr driver, - virDomainObjPtr vm) -{ - char *sockpath = NULL; - virNetClientPtr monitor = NULL; +static virLXCMonitorCallbacks monitorCallbacks = { + .eofNotify = virLXCProcessMonitorEOFNotify, + .destroy = virLXCProcessMonitorDestroy, +};
- if (virAsprintf(&sockpath, "%s/%s.sock", - driver->stateDir, vm->def->name) < 0) { - virReportOOMError(); - return NULL; - } + +static virLXCMonitorPtr virLXCProcessConnectMonitor(virLXCDriverPtr driver, + virDomainObjPtr vm) +{ + virLXCMonitorPtr monitor = NULL;
if (virSecurityManagerSetSocketLabel(driver->securityManager, vm->def) < 0) goto cleanup;
- monitor = virNetClientNewUNIX(sockpath, false, NULL); + monitor = virLXCMonitorNew(vm, driver->stateDir, &monitorCallbacks);
if (virSecurityManagerClearSocketLabel(driver->securityManager, vm->def) < 0) { - virNetClientFree(monitor); - monitor = NULL; + if (monitor) { + virLXCMonitorClose(monitor); + virLXCMonitorUnref(monitor);
No need to explicitly call virLXCMonitorClose here. Not to mention that virLXCMonitorUnref requires monitor to be locked and virLXCMonitorNew doesn't return locked monitor nor does it initialize refs to 1. This code would just result in leaked memory and monitor->refs == -1.
+ monitor = NULL; + } goto cleanup; }
- if (!monitor) - goto cleanup; - - virNetClientSetCloseCallback(monitor, virLXCProcessMonitorEOFNotify, vm, NULL); - cleanup: - VIR_FREE(sockpath); return monitor; }
@@ -1041,9 +1051,11 @@ cleanup: VIR_FREE(veths[i]); } if (rc != 0) { - virNetClientClose(priv->monitor); - virNetClientFree(priv->monitor); - priv->monitor = NULL; + if (priv->monitor) { + virLXCMonitorClose(priv->monitor); + virLXCMonitorUnref(priv->monitor); + priv->monitor = NULL; + }
Another weired usage of virLXCMonitorUnref.
virDomainConfVMNWFilterTeardown(vm);
virSecurityManagerRestoreAllLabel(driver->securityManager,
The reference counting and locking is not ideal throughout this patch. Jirka

On Fri, Jul 27, 2012 at 12:22:23AM +0200, Jiri Denemark wrote:
On Tue, Jul 24, 2012 at 14:22:49 +0100, Daniel P. Berrange wrote:
+ +#define VIR_FROM_THIS VIR_FROM_LXC + +struct _virLXCMonitor { + int refs; + + virMutex lock; /* also used to protect fd */
Which fd are you referring to?
The 'fd' which no longer exists :-) I guess we only use this for the ref count now, since 'client' has its own internal locking. I'll update the comment.
+ + virDomainObjPtr vm; + virLXCMonitorCallbacksPtr cb; + + virNetClientPtr client; +};
virDomainConfVMNWFilterTeardown(vm);
virSecurityManagerRestoreAllLabel(driver->securityManager,
The reference counting and locking is not ideal throughout this patch.
I'll investigate this and re-post this patch. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

From: "Daniel P. Berrange" <berrange@redhat.com> Move the code that handles the LXC monitor out of the lxc_process.c file and into lxc_monitor.{c,h} Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- po/POTFILES.in | 1 + src/Makefile.am | 1 + src/lxc/lxc_domain.h | 4 +- src/lxc/lxc_monitor.c | 165 +++++++++++++++++++++++++++++++++++++++++++++++++ src/lxc/lxc_monitor.h | 54 ++++++++++++++++ src/lxc/lxc_process.c | 73 +++++++++++++--------- 6 files changed, 267 insertions(+), 31 deletions(-) create mode 100644 src/lxc/lxc_monitor.c create mode 100644 src/lxc/lxc_monitor.h diff --git a/po/POTFILES.in b/po/POTFILES.in index 0f32918..2b0bae5 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -47,6 +47,7 @@ src/lxc/lxc_container.c src/lxc/lxc_conf.c src/lxc/lxc_controller.c src/lxc/lxc_driver.c +src/lxc/lxc_monitor.c src/lxc/lxc_process.c src/libxl/libxl_driver.c src/libxl/libxl_conf.c diff --git a/src/Makefile.am b/src/Makefile.am index 13641ce..7018979 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -392,6 +392,7 @@ LXC_DRIVER_SOURCES = \ lxc/lxc_container.c lxc/lxc_container.h \ lxc/lxc_cgroup.c lxc/lxc_cgroup.h \ lxc/lxc_domain.c lxc/lxc_domain.h \ + lxc/lxc_monitor.c lxc/lxc_monitor.h \ lxc/lxc_process.c lxc/lxc_process.h \ lxc/lxc_driver.c lxc/lxc_driver.h diff --git a/src/lxc/lxc_domain.h b/src/lxc/lxc_domain.h index 799248d..ff7c96f 100644 --- a/src/lxc/lxc_domain.h +++ b/src/lxc/lxc_domain.h @@ -24,13 +24,13 @@ # define __LXC_DOMAIN_H__ # include "lxc_conf.h" -# include "rpc/virnetclient.h" +# include "lxc_monitor.h" typedef struct _virLXCDomainObjPrivate virLXCDomainObjPrivate; typedef virLXCDomainObjPrivate *virLXCDomainObjPrivatePtr; struct _virLXCDomainObjPrivate { - virNetClientPtr monitor; + virLXCMonitorPtr monitor; }; void virLXCDomainSetPrivateDataHooks(virCapsPtr caps); diff --git a/src/lxc/lxc_monitor.c b/src/lxc/lxc_monitor.c new file mode 100644 index 0000000..d334c10 --- /dev/null +++ b/src/lxc/lxc_monitor.c @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2010-2012 Red Hat, Inc. + * + * lxc_monitor.c: client for LXC controller monitor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; If not, see + * <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include "lxc_monitor.h" +#include "lxc_conf.h" + +#include "memory.h" + +#include "virterror_internal.h" +#include "logging.h" +#include "threads.h" +#include "rpc/virnetclient.h" + +#define VIR_FROM_THIS VIR_FROM_LXC + +struct _virLXCMonitor { + int refs; + + virMutex lock; /* also used to protect refs */ + + virDomainObjPtr vm; + virLXCMonitorCallbacksPtr cb; + + virNetClientPtr client; +}; + +static void virLXCMonitorFree(virLXCMonitorPtr mon); + + +static void virLXCMonitorEOFNotify(virNetClientPtr client ATTRIBUTE_UNUSED, + int reason ATTRIBUTE_UNUSED, + void *opaque) +{ + virLXCMonitorPtr mon = opaque; + virLXCMonitorCallbackEOFNotify eofNotify; + virDomainObjPtr vm; + + virLXCMonitorLock(mon); + eofNotify = mon->cb->eofNotify; + vm = mon->vm; + virLXCMonitorUnlock(mon); + + eofNotify(mon, vm); +} + + +virLXCMonitorPtr virLXCMonitorNew(virDomainObjPtr vm, + const char *socketdir, + virLXCMonitorCallbacksPtr cb) +{ + virLXCMonitorPtr mon; + char *sockpath = NULL; + + if (VIR_ALLOC(mon) < 0) { + virReportOOMError(); + return NULL; + } + + mon->refs = 1; + + if (virMutexInit(&mon->lock) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot initialize monitor mutex")); + VIR_FREE(mon); + return NULL; + } + + if (virAsprintf(&sockpath, "%s/%s.sock", + socketdir, vm->def->name) < 0) + goto no_memory; + + if (!(mon->client = virNetClientNewUNIX(sockpath, false, NULL))) + goto error; + + + mon->vm = vm; + mon->cb = cb; + + virNetClientSetCloseCallback(mon->client, virLXCMonitorEOFNotify, mon, NULL); + +cleanup: + VIR_FREE(sockpath); + return mon; + +no_memory: + virReportOOMError(); +error: + virLXCMonitorFree(mon); + mon = NULL; + goto cleanup; +} + + +static void virLXCMonitorFree(virLXCMonitorPtr mon) +{ + VIR_DEBUG("mon=%p", mon); + if (mon->client) + virLXCMonitorClose(mon); + + if (mon->cb && mon->cb->destroy) + (mon->cb->destroy)(mon, mon->vm); + virMutexDestroy(&mon->lock); + VIR_FREE(mon); +} + + +int virLXCMonitorRef(virLXCMonitorPtr mon) +{ + mon->refs++; + return mon->refs; +} + +int virLXCMonitorUnref(virLXCMonitorPtr mon) +{ + mon->refs--; + + if (mon->refs == 0) { + virLXCMonitorUnlock(mon); + virLXCMonitorFree(mon); + return 0; + } + + return mon->refs; +} + + +void virLXCMonitorClose(virLXCMonitorPtr mon) +{ + if (mon->client) { + virNetClientClose(mon->client); + virNetClientFree(mon->client); + mon->client = NULL; + } +} + + +void virLXCMonitorLock(virLXCMonitorPtr mon) +{ + virMutexLock(&mon->lock); +} + + +void virLXCMonitorUnlock(virLXCMonitorPtr mon) +{ + virMutexUnlock(&mon->lock); +} diff --git a/src/lxc/lxc_monitor.h b/src/lxc/lxc_monitor.h new file mode 100644 index 0000000..d3b6387 --- /dev/null +++ b/src/lxc/lxc_monitor.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2010-2012 Red Hat, Inc. + * + * lxc_monitor.h: client for LXC controller monitor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; If not, see + * <http://www.gnu.org/licenses/>. + */ + +#ifndef __LXC_MONITOR_H__ +# define __LXC_MONITOR_H__ + +# include "domain_conf.h" + +typedef struct _virLXCMonitor virLXCMonitor; +typedef virLXCMonitor *virLXCMonitorPtr; + +typedef struct _virLXCMonitorCallbacks virLXCMonitorCallbacks; +typedef virLXCMonitorCallbacks *virLXCMonitorCallbacksPtr; + +typedef void (*virLXCMonitorCallbackDestroy)(virLXCMonitorPtr mon, + virDomainObjPtr vm); +typedef void (*virLXCMonitorCallbackEOFNotify)(virLXCMonitorPtr mon, + virDomainObjPtr vm); + +struct _virLXCMonitorCallbacks { + virLXCMonitorCallbackDestroy destroy; + virLXCMonitorCallbackEOFNotify eofNotify; +}; + +virLXCMonitorPtr virLXCMonitorNew(virDomainObjPtr vm, + const char *socketdir, + virLXCMonitorCallbacksPtr cb); + +void virLXCMonitorClose(virLXCMonitorPtr mon); + +void virLXCMonitorLock(virLXCMonitorPtr mon); +void virLXCMonitorUnlock(virLXCMonitorPtr mon); + +int virLXCMonitorRef(virLXCMonitorPtr mon); +int virLXCMonitorUnref(virLXCMonitorPtr mon); + +#endif /* __LXC_MONITOR_H__ */ diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 1a6a209..67465b5 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -178,9 +178,13 @@ static void virLXCProcessCleanup(virLXCDriverPtr driver, /* Stop autodestroy in case guest is restarted */ virLXCProcessAutoDestroyRemove(driver, vm); - virNetClientClose(priv->monitor); - virNetClientFree(priv->monitor); - priv->monitor = NULL; + if (priv->monitor) { + virLXCMonitorClose(priv->monitor); + virLXCMonitorLock(priv->monitor); + if (virLXCMonitorUnref(priv->monitor) > 0) + virLXCMonitorUnlock(priv->monitor); + priv->monitor = NULL; + } virPidFileDelete(driver->stateDir, vm->def->name); virDomainDeleteConfig(driver->stateDir, NULL, vm); @@ -471,13 +475,25 @@ cleanup: } +static void virLXCProcessMonitorDestroy(virLXCMonitorPtr mon, + virDomainObjPtr vm) +{ + virLXCDomainObjPrivatePtr priv; + + virDomainObjLock(vm); + priv = vm->privateData; + if (priv->monitor == mon) + priv->monitor = NULL; + if (virDomainObjUnref(vm) > 0) + virDomainObjUnlock(vm); +} + + extern virLXCDriverPtr lxc_driver; -static void virLXCProcessMonitorEOFNotify(virNetClientPtr client ATTRIBUTE_UNUSED, - int reason ATTRIBUTE_UNUSED, - void *opaque) +static void virLXCProcessMonitorEOFNotify(virLXCMonitorPtr mon ATTRIBUTE_UNUSED, + virDomainObjPtr vm) { virLXCDriverPtr driver = lxc_driver; - virDomainObjPtr vm = opaque; virDomainEventPtr event = NULL; lxcDriverLock(driver); @@ -504,36 +520,32 @@ static void virLXCProcessMonitorEOFNotify(virNetClientPtr client ATTRIBUTE_UNUSE } -static virNetClientPtr virLXCProcessConnectMonitor(virLXCDriverPtr driver, - virDomainObjPtr vm) -{ - char *sockpath = NULL; - virNetClientPtr monitor = NULL; +static virLXCMonitorCallbacks monitorCallbacks = { + .eofNotify = virLXCProcessMonitorEOFNotify, + .destroy = virLXCProcessMonitorDestroy, +}; - if (virAsprintf(&sockpath, "%s/%s.sock", - driver->stateDir, vm->def->name) < 0) { - virReportOOMError(); - return NULL; - } + +static virLXCMonitorPtr virLXCProcessConnectMonitor(virLXCDriverPtr driver, + virDomainObjPtr vm) +{ + virLXCMonitorPtr monitor = NULL; if (virSecurityManagerSetSocketLabel(driver->securityManager, vm->def) < 0) goto cleanup; - monitor = virNetClientNewUNIX(sockpath, false, NULL); + monitor = virLXCMonitorNew(vm, driver->stateDir, &monitorCallbacks); if (virSecurityManagerClearSocketLabel(driver->securityManager, vm->def) < 0) { - virNetClientFree(monitor); - monitor = NULL; + if (monitor) { + virLXCMonitorLock(monitor); + virLXCMonitorUnref(monitor); + monitor = NULL; + } goto cleanup; } - if (!monitor) - goto cleanup; - - virNetClientSetCloseCallback(monitor, virLXCProcessMonitorEOFNotify, vm, NULL); - cleanup: - VIR_FREE(sockpath); return monitor; } @@ -1041,9 +1053,12 @@ cleanup: VIR_FREE(veths[i]); } if (rc != 0) { - virNetClientClose(priv->monitor); - virNetClientFree(priv->monitor); - priv->monitor = NULL; + if (priv->monitor) { + virLXCMonitorLock(priv->monitor); + if (virLXCMonitorUnref(priv->monitor) > 0) + virLXCMonitorUnlock(priv->monitor); + priv->monitor = NULL; + } virDomainConfVMNWFilterTeardown(vm); virSecurityManagerRestoreAllLabel(driver->securityManager, -- 1.7.10.4

On Fri, Jul 27, 2012 at 13:57:32 +0100, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
Move the code that handles the LXC monitor out of the lxc_process.c file and into lxc_monitor.{c,h}
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- po/POTFILES.in | 1 + src/Makefile.am | 1 + src/lxc/lxc_domain.h | 4 +- src/lxc/lxc_monitor.c | 165 +++++++++++++++++++++++++++++++++++++++++++++++++ src/lxc/lxc_monitor.h | 54 ++++++++++++++++ src/lxc/lxc_process.c | 73 +++++++++++++--------- 6 files changed, 267 insertions(+), 31 deletions(-) create mode 100644 src/lxc/lxc_monitor.c create mode 100644 src/lxc/lxc_monitor.h
ACK Jirka

From: "Daniel P. Berrange" <berrange@redhat.com> Update the gendispatch.pl script to get a little closer to being able to generate code for the LXC monitor, by passing in the struct prefix separately from the procedure prefix. Also allow method names using virCapitalLetters instead of vir_underscore_separator Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- daemon/Makefile.am | 4 +- src/Makefile.am | 4 +- src/rpc/gendispatch.pl | 107 ++++++++++++++++++++++++++++++++---------------- 3 files changed, 75 insertions(+), 40 deletions(-) diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 71e91cd..4de39bc 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -58,12 +58,12 @@ QEMU_PROTOCOL = $(top_srcdir)/src/remote/qemu_protocol.x $(srcdir)/remote_dispatch.h: $(srcdir)/../src/rpc/gendispatch.pl \ $(REMOTE_PROTOCOL) - $(AM_V_GEN)$(PERL) -w $(srcdir)/../src/rpc/gendispatch.pl -b remote \ + $(AM_V_GEN)$(PERL) -w $(srcdir)/../src/rpc/gendispatch.pl -b remote REMOTE \ $(REMOTE_PROTOCOL) > $@ $(srcdir)/qemu_dispatch.h: $(srcdir)/../src/rpc/gendispatch.pl \ $(QEMU_PROTOCOL) - $(AM_V_GEN)$(PERL) -w $(srcdir)/../src/rpc/gendispatch.pl -b qemu \ + $(AM_V_GEN)$(PERL) -w $(srcdir)/../src/rpc/gendispatch.pl -b qemu QEMU \ $(QEMU_PROTOCOL) > $@ if WITH_LIBVIRTD diff --git a/src/Makefile.am b/src/Makefile.am index a910aa1..492ce73 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -230,12 +230,12 @@ REMOTE_DRIVER_PROTOCOL = $(REMOTE_PROTOCOL) $(QEMU_PROTOCOL) $(srcdir)/remote/remote_client_bodies.h: $(srcdir)/rpc/gendispatch.pl \ $(REMOTE_PROTOCOL) $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl \ - -k remote $(REMOTE_PROTOCOL) > $@ + -k remote REMOTE $(REMOTE_PROTOCOL) > $@ $(srcdir)/remote/qemu_client_bodies.h: $(srcdir)/rpc/gendispatch.pl \ $(QEMU_PROTOCOL) $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl \ - -k qemu $(QEMU_PROTOCOL) > $@ + -k qemu QEMU $(QEMU_PROTOCOL) > $@ REMOTE_DRIVER_SOURCES = \ gnutls_1_0_compat.h \ diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl index 1fb5971..fe2c23d 100755 --- a/src/rpc/gendispatch.pl +++ b/src/rpc/gendispatch.pl @@ -20,25 +20,50 @@ use strict; use Getopt::Std; # Command line options. +# -k - client bodies +# -b - server bodies our ($opt_p, $opt_t, $opt_a, $opt_r, $opt_d, $opt_b, $opt_k); getopts ('ptardbk'); -my $structprefix = shift or die "missing prefix argument"; +my $structprefix = shift or die "missing struct prefix argument"; +my $procprefix = shift or die "missing procedure prefix argument"; my $protocol = shift or die "missing protocol argument"; my @autogen; -my $procprefix = uc $structprefix; # Convert name_of_call to NameOfCall. sub name_to_ProcName { my $name = shift; + + my @elems; + if ($name =~ /_/ || (lc $name) eq "open" || (lc $name) eq "close") { + @elems = split /_/, $name; + @elems = map lc, @elems; + @elems = map ucfirst, @elems; + } else { + @elems = $name; + } + @elems = map { $_ =~ s/Nwfilter/NWFilter/; $_ =~ s/Xml$/XML/; + $_ =~ s/Uri$/URI/; $_ =~ s/Uuid$/UUID/; $_ =~ s/Id$/ID/; + $_ =~ s/Mac$/MAC/; $_ =~ s/Cpu$/CPU/; $_ =~ s/Os$/OS/; + $_ =~ s/Nmi$/NMI/; $_ =~ s/Pm/PM/; $_ } @elems; + my $procname = join "", @elems; + + return $procname; +} + +sub name_to_TypeName { + my $name = shift; + my @elems = split /_/, $name; + @elems = map lc, @elems; @elems = map ucfirst, @elems; @elems = map { $_ =~ s/Nwfilter/NWFilter/; $_ =~ s/Xml$/XML/; - $_ =~ s/Uri$/URI/; $_ =~ s/Uuid$/UUID/; $_ =~ s/Id$/ID/; - $_ =~ s/Mac$/MAC/; $_ =~ s/Cpu$/CPU/; $_ =~ s/Os$/OS/; - $_ =~ s/Nmi$/NMI/; $_ =~ s/Pm/PM/; $_ } @elems; - join "", @elems + $_ =~ s/Uri$/URI/; $_ =~ s/Uuid$/UUID/; $_ =~ s/Id$/ID/; + $_ =~ s/Mac$/MAC/; $_ =~ s/Cpu$/CPU/; $_ =~ s/Os$/OS/; + $_ =~ s/Nmi$/NMI/; $_ =~ s/Pm/PM/; $_ } @elems; + my $typename = join "", @elems; + return $typename; } # Read the input file (usually remote_protocol.x) and form an @@ -64,18 +89,20 @@ while (<PROTOCOL>) { } elsif ($_ =~ m/^\s*(.*\S)\s*$/) { push(@{$calls{$name}->{ret_members}}, $1); } - } elsif (/^struct ${structprefix}_(.*)_args/) { - $name = $1; + } elsif (/^struct (${structprefix}_(.*)_args)/ || + /^struct (${structprefix}(.*)Args)/) { + my $structname = $1; + $name = $2; $ProcName = name_to_ProcName ($name); - - die "duplicate definition of ${structprefix}_${name}_args" + $name = lc $name; + $name =~ s/_//g; + die "duplicate definition of $_" if exists $calls{$name}; $calls{$name} = { name => $name, ProcName => $ProcName, - UC_NAME => uc $name, - args => "${structprefix}_${name}_args", + args => $structname, args_members => [], ret => "void" }; @@ -83,20 +110,23 @@ while (<PROTOCOL>) { $collect_args_members = 1; $collect_ret_members = 0; $last_name = $name; - } elsif (/^struct ${structprefix}_(.*)_ret\s+{(.*)$/) { - $name = $1; - $flags = $2; + } elsif (/^struct (${structprefix}_(.*)_ret)\s+{(.*)$/ || + /^struct (${structprefix}(.*)Ret)\s+{(.*)$/) { + my $structname = $1; + $name = $2; + $flags = $3; $ProcName = name_to_ProcName ($name); + $name = lc $name; + $name =~ s/_//g; if (exists $calls{$name}) { - $calls{$name}->{ret} = "${structprefix}_${name}_ret"; + $calls{$name}->{ret} = $structname; } else { $calls{$name} = { name => $name, ProcName => $ProcName, - UC_NAME => uc $name, args => "void", - ret => "${structprefix}_${name}_ret", + ret => $structname, ret_members => [] } } @@ -112,24 +142,29 @@ while (<PROTOCOL>) { $collect_args_members = 0; $collect_ret_members = 1; $last_name = $name; - } elsif (/^struct ${structprefix}_(.*)_msg/) { - $name = $1; + } elsif (/^struct (${structprefix}_(.*)_msg)/ || + /^struct (${structprefix}(.*)Msg)/) { + my $structname = $1; + $name = $2; $ProcName = name_to_ProcName ($name); - + $name = lc $name; + $name =~ s/_//g; $calls{$name} = { name => $name, ProcName => $ProcName, - UC_NAME => uc $name, - msg => "${structprefix}_${name}_msg" + msg => $structname, }; $collect_args_members = 0; $collect_ret_members = 0; - } elsif (/^\s*${procprefix}_PROC_(.*?)\s*=\s*(\d+)\s*,?(.*)$/) { - $name = lc $1; - $id = $2; - $flags = $3; + } elsif (/^\s*(${procprefix}_PROC_(.*?))\s*=\s*(\d+)\s*,?(.*)$/) { + my $constname = $1; + $name = $2; + $id = $3; + $flags = $4; $ProcName = name_to_ProcName ($name); + $name = lc $name; + $name =~ s/_//g; if (!exists $calls{$name}) { # that the argument and return value cases have not yet added @@ -139,15 +174,15 @@ while (<PROTOCOL>) { $calls{$name} = { name => $name, ProcName => $ProcName, - UC_NAME => uc $name, args => "void", ret => "void" } } + $calls{$name}->{constname} = $constname; if ($opt_b or $opt_k) { if (!($flags =~ m/^\s*\/\*\s*(\S+)\s+(\S+)\s*(\|.*)?\s+(priority:(\S+))?\s*\*\/\s*$/)) { - die "invalid generator flags for ${procprefix}_PROC_${name}" + die "invalid generator flags '$flags' for $constname" } my $genmode = $opt_b ? $1 : $2; @@ -371,7 +406,7 @@ elsif ($opt_b) { # ignore the name arg for node devices next } elsif ($args_member =~ m/^remote_nonnull_(domain|network|storage_pool|storage_vol|interface|secret|nwfilter) (\S+);/) { - my $type_name = name_to_ProcName($1); + my $type_name = name_to_TypeName($1); push(@vars_list, "vir${type_name}Ptr $2 = NULL"); push(@getters_list, @@ -580,7 +615,7 @@ elsif ($opt_b) { $single_ret_by_ref = 0; $single_ret_check = " == NULL"; } elsif ($ret_member =~ m/^remote_nonnull_(domain|network|storage_pool|storage_vol|interface|node_device|secret|nwfilter|domain_snapshot) (\S+);/) { - my $type_name = name_to_ProcName($1); + my $type_name = name_to_TypeName($1); if ($call->{ProcName} eq "DomainCreateWithFlags") { # SPECIAL: virDomainCreateWithFlags updates the given @@ -1031,7 +1066,7 @@ elsif ($opt_k) { } elsif ($args_member =~ m/^remote_nonnull_(domain|network|storage_pool|storage_vol|interface|secret|nwfilter|domain_snapshot) (\S+);/) { my $name = $1; my $arg_name = $2; - my $type_name = name_to_ProcName($name); + my $type_name = name_to_TypeName($name); if ($is_first_arg) { if ($name eq "domain_snapshot") { @@ -1254,7 +1289,7 @@ elsif ($opt_k) { } elsif ($ret_member =~ m/^remote_nonnull_(domain|network|storage_pool|storage_vol|node_device|interface|secret|nwfilter|domain_snapshot) (\S+);/) { my $name = $1; my $arg_name = $2; - my $type_name = name_to_ProcName($name); + my $type_name = name_to_TypeName($name); if ($name eq "node_device") { $priv_name = "devMonPrivateData"; @@ -1400,7 +1435,7 @@ elsif ($opt_k) { if ($call->{streamflag} ne "none") { print "\n"; - print " if (!(netst = virNetClientStreamNew(priv->remoteProgram, REMOTE_PROC_$call->{UC_NAME}, priv->counter)))\n"; + print " if (!(netst = virNetClientStreamNew(priv->remoteProgram, $call->{constname}, priv->counter)))\n"; print " goto done;\n"; print "\n"; print " if (virNetClientAddStream(priv->client, netst) < 0) {\n"; @@ -1474,7 +1509,7 @@ elsif ($opt_k) { } print "\n"; - print " if (call($priv_src, priv, $callflags, ${procprefix}_PROC_$call->{UC_NAME},\n"; + print " if (call($priv_src, priv, $callflags, $call->{constname},\n"; print " (xdrproc_t)xdr_$argtype, (char *)$call_args,\n"; print " (xdrproc_t)xdr_$rettype, (char *)$call_ret) == -1) {\n"; @@ -1542,7 +1577,7 @@ elsif ($opt_k) { if ($single_ret_as_list or $single_ret_cleanup) { print "\n"; print "cleanup:\n"; - print " xdr_free((xdrproc_t)xdr_remote_$call->{name}_ret, (char *)&ret);\n"; + print " xdr_free((xdrproc_t)xdr_$call->{ret}, (char *)&ret);\n"; } print "\n"; -- 1.7.10.4

On Tue, Jul 24, 2012 at 14:22:50 +0100, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
Update the gendispatch.pl script to get a little closer to being able to generate code for the LXC monitor, by passing in the struct prefix separately from the procedure prefix. Also allow method names using virCapitalLetters instead of vir_underscore_separator
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- daemon/Makefile.am | 4 +- src/Makefile.am | 4 +- src/rpc/gendispatch.pl | 107 ++++++++++++++++++++++++++++++++---------------- 3 files changed, 75 insertions(+), 40 deletions(-)
diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 71e91cd..4de39bc 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -58,12 +58,12 @@ QEMU_PROTOCOL = $(top_srcdir)/src/remote/qemu_protocol.x
$(srcdir)/remote_dispatch.h: $(srcdir)/../src/rpc/gendispatch.pl \ $(REMOTE_PROTOCOL) - $(AM_V_GEN)$(PERL) -w $(srcdir)/../src/rpc/gendispatch.pl -b remote \ + $(AM_V_GEN)$(PERL) -w $(srcdir)/../src/rpc/gendispatch.pl -b remote REMOTE \ $(REMOTE_PROTOCOL) > $@
$(srcdir)/qemu_dispatch.h: $(srcdir)/../src/rpc/gendispatch.pl \ $(QEMU_PROTOCOL) - $(AM_V_GEN)$(PERL) -w $(srcdir)/../src/rpc/gendispatch.pl -b qemu \ + $(AM_V_GEN)$(PERL) -w $(srcdir)/../src/rpc/gendispatch.pl -b qemu QEMU \ $(QEMU_PROTOCOL) > $@
if WITH_LIBVIRTD diff --git a/src/Makefile.am b/src/Makefile.am index a910aa1..492ce73 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -230,12 +230,12 @@ REMOTE_DRIVER_PROTOCOL = $(REMOTE_PROTOCOL) $(QEMU_PROTOCOL) $(srcdir)/remote/remote_client_bodies.h: $(srcdir)/rpc/gendispatch.pl \ $(REMOTE_PROTOCOL) $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl \ - -k remote $(REMOTE_PROTOCOL) > $@ + -k remote REMOTE $(REMOTE_PROTOCOL) > $@
$(srcdir)/remote/qemu_client_bodies.h: $(srcdir)/rpc/gendispatch.pl \ $(QEMU_PROTOCOL) $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl \ - -k qemu $(QEMU_PROTOCOL) > $@ + -k qemu QEMU $(QEMU_PROTOCOL) > $@
REMOTE_DRIVER_SOURCES = \ gnutls_1_0_compat.h \ diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl index 1fb5971..fe2c23d 100755 --- a/src/rpc/gendispatch.pl +++ b/src/rpc/gendispatch.pl @@ -20,25 +20,50 @@ use strict; use Getopt::Std;
# Command line options. +# -k - client bodies +# -b - server bodies our ($opt_p, $opt_t, $opt_a, $opt_r, $opt_d, $opt_b, $opt_k); getopts ('ptardbk');
-my $structprefix = shift or die "missing prefix argument"; +my $structprefix = shift or die "missing struct prefix argument"; +my $procprefix = shift or die "missing procedure prefix argument"; my $protocol = shift or die "missing protocol argument"; my @autogen;
-my $procprefix = uc $structprefix;
# Convert name_of_call to NameOfCall. sub name_to_ProcName { my $name = shift; + + my @elems; + if ($name =~ /_/ || (lc $name) eq "open" || (lc $name) eq "close") { + @elems = split /_/, $name; + @elems = map lc, @elems; + @elems = map ucfirst, @elems; + } else { + @elems = $name; + } + @elems = map { $_ =~ s/Nwfilter/NWFilter/; $_ =~ s/Xml$/XML/; + $_ =~ s/Uri$/URI/; $_ =~ s/Uuid$/UUID/; $_ =~ s/Id$/ID/; + $_ =~ s/Mac$/MAC/; $_ =~ s/Cpu$/CPU/; $_ =~ s/Os$/OS/; + $_ =~ s/Nmi$/NMI/; $_ =~ s/Pm/PM/; $_ } @elems;
This map is worth separating into a dedicated function as it is already used in two places.
+ my $procname = join "", @elems; + + return $procname; +} + +sub name_to_TypeName { + my $name = shift; + my @elems = split /_/, $name; + @elems = map lc, @elems; @elems = map ucfirst, @elems; @elems = map { $_ =~ s/Nwfilter/NWFilter/; $_ =~ s/Xml$/XML/; - $_ =~ s/Uri$/URI/; $_ =~ s/Uuid$/UUID/; $_ =~ s/Id$/ID/; - $_ =~ s/Mac$/MAC/; $_ =~ s/Cpu$/CPU/; $_ =~ s/Os$/OS/; - $_ =~ s/Nmi$/NMI/; $_ =~ s/Pm/PM/; $_ } @elems; - join "", @elems + $_ =~ s/Uri$/URI/; $_ =~ s/Uuid$/UUID/; $_ =~ s/Id$/ID/; + $_ =~ s/Mac$/MAC/; $_ =~ s/Cpu$/CPU/; $_ =~ s/Os$/OS/; + $_ =~ s/Nmi$/NMI/; $_ =~ s/Pm/PM/; $_ } @elems; + my $typename = join "", @elems; + return $typename; }
# Read the input file (usually remote_protocol.x) and form an @@ -64,18 +89,20 @@ while (<PROTOCOL>) { } elsif ($_ =~ m/^\s*(.*\S)\s*$/) { push(@{$calls{$name}->{ret_members}}, $1); } - } elsif (/^struct ${structprefix}_(.*)_args/) { - $name = $1; + } elsif (/^struct (${structprefix}_(.*)_args)/ || + /^struct (${structprefix}(.*)Args)/) { + my $structname = $1; + $name = $2; $ProcName = name_to_ProcName ($name); - - die "duplicate definition of ${structprefix}_${name}_args" + $name = lc $name; + $name =~ s/_//g; + die "duplicate definition of $_" if exists $calls{$name};
$calls{$name} = { name => $name, ProcName => $ProcName, - UC_NAME => uc $name, - args => "${structprefix}_${name}_args", + args => $structname, args_members => [], ret => "void" }; @@ -83,20 +110,23 @@ while (<PROTOCOL>) { $collect_args_members = 1; $collect_ret_members = 0; $last_name = $name; - } elsif (/^struct ${structprefix}_(.*)_ret\s+{(.*)$/) { - $name = $1; - $flags = $2; + } elsif (/^struct (${structprefix}_(.*)_ret)\s+{(.*)$/ || + /^struct (${structprefix}(.*)Ret)\s+{(.*)$/) { + my $structname = $1; + $name = $2; + $flags = $3; $ProcName = name_to_ProcName ($name); + $name = lc $name; + $name =~ s/_//g;
if (exists $calls{$name}) { - $calls{$name}->{ret} = "${structprefix}_${name}_ret"; + $calls{$name}->{ret} = $structname; } else { $calls{$name} = { name => $name, ProcName => $ProcName, - UC_NAME => uc $name, args => "void", - ret => "${structprefix}_${name}_ret", + ret => $structname, ret_members => [] } } @@ -112,24 +142,29 @@ while (<PROTOCOL>) { $collect_args_members = 0; $collect_ret_members = 1; $last_name = $name; - } elsif (/^struct ${structprefix}_(.*)_msg/) { - $name = $1; + } elsif (/^struct (${structprefix}_(.*)_msg)/ || + /^struct (${structprefix}(.*)Msg)/) { + my $structname = $1; + $name = $2; $ProcName = name_to_ProcName ($name); - + $name = lc $name; + $name =~ s/_//g; $calls{$name} = { name => $name, ProcName => $ProcName, - UC_NAME => uc $name, - msg => "${structprefix}_${name}_msg" + msg => $structname, };
$collect_args_members = 0; $collect_ret_members = 0; - } elsif (/^\s*${procprefix}_PROC_(.*?)\s*=\s*(\d+)\s*,?(.*)$/) { - $name = lc $1; - $id = $2; - $flags = $3; + } elsif (/^\s*(${procprefix}_PROC_(.*?))\s*=\s*(\d+)\s*,?(.*)$/) { + my $constname = $1; + $name = $2; + $id = $3; + $flags = $4; $ProcName = name_to_ProcName ($name); + $name = lc $name; + $name =~ s/_//g;
if (!exists $calls{$name}) { # that the argument and return value cases have not yet added @@ -139,15 +174,15 @@ while (<PROTOCOL>) { $calls{$name} = { name => $name, ProcName => $ProcName, - UC_NAME => uc $name, args => "void", ret => "void" } } + $calls{$name}->{constname} = $constname;
s/^/ / in the line above.
if ($opt_b or $opt_k) { if (!($flags =~ m/^\s*\/\*\s*(\S+)\s+(\S+)\s*(\|.*)?\s+(priority:(\S+))?\s*\*\/\s*$/)) { - die "invalid generator flags for ${procprefix}_PROC_${name}" + die "invalid generator flags '$flags' for $constname" }
my $genmode = $opt_b ? $1 : $2; @@ -371,7 +406,7 @@ elsif ($opt_b) { # ignore the name arg for node devices next } elsif ($args_member =~ m/^remote_nonnull_(domain|network|storage_pool|storage_vol|interface|secret|nwfilter) (\S+);/) { - my $type_name = name_to_ProcName($1); + my $type_name = name_to_TypeName($1);
push(@vars_list, "vir${type_name}Ptr $2 = NULL"); push(@getters_list, @@ -580,7 +615,7 @@ elsif ($opt_b) { $single_ret_by_ref = 0; $single_ret_check = " == NULL"; } elsif ($ret_member =~ m/^remote_nonnull_(domain|network|storage_pool|storage_vol|interface|node_device|secret|nwfilter|domain_snapshot) (\S+);/) { - my $type_name = name_to_ProcName($1); + my $type_name = name_to_TypeName($1);
if ($call->{ProcName} eq "DomainCreateWithFlags") { # SPECIAL: virDomainCreateWithFlags updates the given @@ -1031,7 +1066,7 @@ elsif ($opt_k) { } elsif ($args_member =~ m/^remote_nonnull_(domain|network|storage_pool|storage_vol|interface|secret|nwfilter|domain_snapshot) (\S+);/) { my $name = $1; my $arg_name = $2; - my $type_name = name_to_ProcName($name); + my $type_name = name_to_TypeName($name);
if ($is_first_arg) { if ($name eq "domain_snapshot") { @@ -1254,7 +1289,7 @@ elsif ($opt_k) { } elsif ($ret_member =~ m/^remote_nonnull_(domain|network|storage_pool|storage_vol|node_device|interface|secret|nwfilter|domain_snapshot) (\S+);/) { my $name = $1; my $arg_name = $2; - my $type_name = name_to_ProcName($name); + my $type_name = name_to_TypeName($name);
if ($name eq "node_device") { $priv_name = "devMonPrivateData"; @@ -1400,7 +1435,7 @@ elsif ($opt_k) {
if ($call->{streamflag} ne "none") { print "\n"; - print " if (!(netst = virNetClientStreamNew(priv->remoteProgram, REMOTE_PROC_$call->{UC_NAME}, priv->counter)))\n"; + print " if (!(netst = virNetClientStreamNew(priv->remoteProgram, $call->{constname}, priv->counter)))\n"; print " goto done;\n"; print "\n"; print " if (virNetClientAddStream(priv->client, netst) < 0) {\n"; @@ -1474,7 +1509,7 @@ elsif ($opt_k) { }
print "\n"; - print " if (call($priv_src, priv, $callflags, ${procprefix}_PROC_$call->{UC_NAME},\n"; + print " if (call($priv_src, priv, $callflags, $call->{constname},\n"; print " (xdrproc_t)xdr_$argtype, (char *)$call_args,\n"; print " (xdrproc_t)xdr_$rettype, (char *)$call_ret) == -1) {\n";
@@ -1542,7 +1577,7 @@ elsif ($opt_k) { if ($single_ret_as_list or $single_ret_cleanup) { print "\n"; print "cleanup:\n"; - print " xdr_free((xdrproc_t)xdr_remote_$call->{name}_ret, (char *)&ret);\n"; + print " xdr_free((xdrproc_t)xdr_$call->{ret}, (char *)&ret);\n"; }
print "\n";
ACK with the nits fixed. Jirka

From: "Daniel P. Berrange" <berrange@redhat.com> This defines a new RPC protocol to be used between the LXC controller and the libvirtd LXC driver. There is only a single RPC message defined thus far, an asynchronous "EXIT" event that is emitted just before the LXC controller process exits. This provides the LXC driver with details about how the container shutdown - normally, or abnormally (crashed), thus allowing the driver to emit better libvirt events. Emitting the event in the LXC controller requires a few little tricks with the RPC service. Simply calling the virNetServiceClientSendMessage does not work, since this merely queues the message for asynchronous processing. In addition the main event loop is no longer running at the point the event is emitted, so no I/O is processed. Thus after invoking virNetServiceClientSendMessage it is necessary to mark the client as being in "delayed close" mode. Then the event loop is run again, until the client completes its close - this happens only after the queued message has been fully transmitted. The final complexity is that it is not safe to run virNetServerQuit() from the client close callback, since that is invoked from a context where the server is locked. Thus a zero-second timer is used to trigger shutdown of the event loop, causing the controller to finally exit. * src/Makefile.am: Add rules for generating RPC protocol files and dispatch methods * src/lxc/lxc_controller.c: Emit an RPC event immediately before exiting * src/lxc/lxc_domain.h: Record the shutdown reason given by the controller * src/lxc/lxc_monitor.c, src/lxc/lxc_monitor.h: Register RPC program and event handler. Add callback to let driver receive EXIT event. * src/lxc/lxc_process.c: Use monitor exit event to decide what kind of domain event to emit * src/lxc/lxc_protocol.x: Define wire protocol for LXC controller monitor. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- .gitignore | 4 ++ src/Makefile.am | 50 +++++++++++++++++++ src/lxc/lxc_controller.c | 125 +++++++++++++++++++++++++++++++++++++++++++++- src/lxc/lxc_domain.h | 1 + src/lxc/lxc_monitor.c | 41 +++++++++++++++ src/lxc/lxc_monitor.h | 6 +++ src/lxc/lxc_process.c | 27 ++++++++++ src/lxc/lxc_protocol.x | 21 ++++++++ 8 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 src/lxc/lxc_protocol.x diff --git a/.gitignore b/.gitignore index b4cbb5f..e4b3932 100644 --- a/.gitignore +++ b/.gitignore @@ -105,6 +105,10 @@ /src/locking/qemu-sanlock.conf /src/locking/test_libvirt_sanlock.aug /src/lxc/test_libvirtd_lxc.aug +/src/lxc/lxc_controller_dispatch.h +/src/lxc/lxc_monitor_dispatch.h +/src/lxc/lxc_protocol.c +/src/lxc/lxc_protocol.h /src/qemu/test_libvirtd_qemu.aug /src/remote/*_client_bodies.h /src/remote/*_protocol.[ch] diff --git a/src/Makefile.am b/src/Makefile.am index 492ce73..44da1fa 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -347,7 +347,55 @@ if WITH_XEN_INOTIFY XEN_DRIVER_SOURCES += xen/xen_inotify.c xen/xen_inotify.h endif +EXTRA_DIST += \ + dtrace2systemtap.pl \ + rpc/gendispatch.pl \ + rpc/genprotocol.pl \ + rpc/gensystemtap.pl \ + rpc/virnetprotocol.x \ + rpc/virkeepaliveprotocol.x + +LXC_PROTOCOL_GENERATED = \ + $(srcdir)/lxc/lxc_protocol.h \ + $(srcdir)/lxc/lxc_protocol.c \ + $(NULL) + +LXC_MONITOR_GENERATED = \ + $(srcdir)/lxc/lxc_monitor_dispatch.h \ + $(NULL) + +LXC_CONTROLLER_GENERATED = \ + $(srcdir)/lxc/lxc_controller_dispatch.h \ + $(NULL) + +LXC_GENERATED = \ + $(LXC_PROTOCOL_GENERATED) \ + $(LXC_MONITOR_GENERATED) \ + $(LXC_CONTROLLER_GENERATED) \ + $(NULL) + +LXC_PROTOCOL = $(srcdir)/lxc/lxc_protocol.x + +$(srcdir)/lxc/lxc_monitor_dispatch.h: $(srcdir)/rpc/gendispatch.pl \ + $(LXC_PROTOCOL) + $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl \ + -k virLXCProtocol VIR_LXC_PROTOCOL $(LXC_PROTOCOL) > $@ + +$(srcdir)/lxc/lxc_controller_dispatch.h: $(srcdir)/../src/rpc/gendispatch.pl \ + $(REMOTE_PROTOCOL) + $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl \ + -b virLXCProtocol VIR_LXC_PROTOCOL $(LXC_PROTOCOL) > $@ + +EXTRA_DIST += \ + $(LXC_PROTOCOL) \ + $(LXC_GENERATED) \ + $(NULL) + +BUILT_SOURCES += $(LXC_GENERATED) + LXC_DRIVER_SOURCES = \ + $(LXC_PROTOCOL_GENERATED) \ + $(LXC_MONITOR_GENERATED) \ lxc/lxc_conf.c lxc/lxc_conf.h \ lxc/lxc_container.c lxc/lxc_container.h \ lxc/lxc_cgroup.c lxc/lxc_cgroup.h \ @@ -357,6 +405,8 @@ LXC_DRIVER_SOURCES = \ lxc/lxc_driver.c lxc/lxc_driver.h LXC_CONTROLLER_SOURCES = \ + $(LXC_PROTOCOL_GENERATED) \ + $(LXC_CONTROLLER_GENERATED) \ lxc/lxc_conf.c lxc/lxc_conf.h \ lxc/lxc_container.c lxc/lxc_container.h \ lxc/lxc_cgroup.c lxc/lxc_cgroup.h \ diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index e39c236..7fcc953 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -59,6 +59,7 @@ #include "lxc_conf.h" #include "lxc_container.h" #include "lxc_cgroup.h" +#include "lxc_protocol.h" #include "virnetdev.h" #include "virnetdevveth.h" #include "memory.h" @@ -121,10 +122,25 @@ struct _virLXCController { /* Server socket */ virNetServerPtr server; + virNetServerClientPtr client; + virNetServerProgramPtr prog; + bool inShutdown; + int timerShutdown; }; +#include "lxc_controller_dispatch.h" + static void virLXCControllerFree(virLXCControllerPtr ctrl); +static void virLXCControllerQuitTimer(int timer ATTRIBUTE_UNUSED, void *opaque) +{ + virLXCControllerPtr ctrl = opaque; + + VIR_DEBUG("Triggering event loop quit"); + virNetServerQuit(ctrl->server); +} + + static virLXCControllerPtr virLXCControllerNew(const char *name) { virLXCControllerPtr ctrl = NULL; @@ -134,6 +150,8 @@ static virLXCControllerPtr virLXCControllerNew(const char *name) if (VIR_ALLOC(ctrl) < 0) goto no_memory; + ctrl->timerShutdown = -1; + if (!(ctrl->name = strdup(name))) goto no_memory; @@ -150,6 +168,11 @@ static virLXCControllerPtr virLXCControllerNew(const char *name) 0)) == NULL) goto error; + if ((ctrl->timerShutdown = virEventAddTimeout(-1, + virLXCControllerQuitTimer, ctrl, + NULL)) < 0) + goto error; + cleanup: VIR_FREE(configFile); virCapabilitiesFree(caps); @@ -238,6 +261,9 @@ static void virLXCControllerFree(virLXCControllerPtr ctrl) virDomainDefFree(ctrl->def); VIR_FREE(ctrl->name); + if (ctrl->timerShutdown != -1) + virEventRemoveTimeout(ctrl->timerShutdown); + virNetServerFree(ctrl->server); VIR_FREE(ctrl); @@ -539,12 +565,28 @@ static int virLXCControllerSetupResourceLimits(virLXCControllerPtr ctrl) } +static void virLXCControllerClientCloseHook(virNetServerClientPtr client) +{ + virLXCControllerPtr ctrl = virNetServerClientGetPrivateData(client); + + VIR_DEBUG("Client %p has closed", client); + if (ctrl->client == client) + ctrl->client = NULL; + if (ctrl->inShutdown) { + VIR_DEBUG("Arm timer to quit event loop"); + virEventUpdateTimeout(ctrl->timerShutdown, 0); + } +} + static int virLXCControllerClientHook(virNetServerPtr server ATTRIBUTE_UNUSED, virNetServerClientPtr client, void *opaque) { virLXCControllerPtr ctrl = opaque; virNetServerClientSetPrivateData(client, ctrl, NULL); + virNetServerClientSetCloseHook(client, virLXCControllerClientCloseHook); + VIR_DEBUG("Got new client %p", client); + ctrl->client = client; return 0; } @@ -581,6 +623,12 @@ static int virLXCControllerSetupServer(virLXCControllerPtr ctrl) virNetServerServiceFree(svc); svc = NULL; + if (!(ctrl->prog = virNetServerProgramNew(VIR_LXC_PROTOCOL_PROGRAM, + VIR_LXC_PROTOCOL_PROGRAM_VERSION, + virLXCProtocolProcs, + virLXCProtocolNProcs))) + goto error; + virNetServerUpdateServices(ctrl->server, true); VIR_FREE(sockpath); return 0; @@ -1219,6 +1267,79 @@ virLXCControllerSetupConsoles(virLXCControllerPtr ctrl, } +static void +virLXCControllerEventSend(virLXCControllerPtr ctrl, + int procnr, + xdrproc_t proc, + void *data) +{ + virNetMessagePtr msg; + + if (!ctrl->client) + return; + + VIR_DEBUG("Send event %d client=%p", procnr, ctrl->client); + if (!(msg = virNetMessageNew(false))) + goto cleanup; + + msg->header.prog = virNetServerProgramGetID(ctrl->prog); + msg->header.vers = virNetServerProgramGetVersion(ctrl->prog); + msg->header.proc = procnr; + msg->header.type = VIR_NET_MESSAGE; + msg->header.serial = 1; + msg->header.status = VIR_NET_OK; + + if (virNetMessageEncodeHeader(msg) < 0) + goto cleanup; + + if (virNetMessageEncodePayload(msg, proc, data) < 0) + goto cleanup; + + VIR_DEBUG("Queue event %d %zu", procnr, msg->bufferLength); + virNetServerClientSendMessage(ctrl->client, msg); + + xdr_free(proc, data); + return; + +cleanup: + virNetMessageFree(msg); + xdr_free(proc, data); +} + + +static int +virLXCControllerEventSendExit(virLXCControllerPtr ctrl, + int exitstatus) +{ + virLXCProtocolExitEventMsg msg; + + VIR_DEBUG("Exit status %d", exitstatus); + memset(&msg, 0, sizeof(msg)); + switch (exitstatus) { + case 0: + msg.status = VIR_LXC_PROTOCOL_EXIT_STATUS_SHUTDOWN; + break; + default: + msg.status = VIR_LXC_PROTOCOL_EXIT_STATUS_ERROR; + break; + } + + virLXCControllerEventSend(ctrl, + VIR_LXC_PROTOCOL_PROC_EXIT_EVENT, + (xdrproc_t)xdr_virLXCProtocolExitEventMsg, + (void*)&msg); + + if (ctrl->client) { + VIR_DEBUG("Waiting for client to complete dispatch"); + ctrl->inShutdown = true; + virNetServerClientDelayedClose(ctrl->client); + virNetServerRun(ctrl->server); + } + VIR_DEBUG("Client has gone away"); + return 0; +} + + static int virLXCControllerRun(virLXCControllerPtr ctrl) { @@ -1306,6 +1427,8 @@ virLXCControllerRun(virLXCControllerPtr ctrl) rc = virLXCControllerMain(ctrl); + virLXCControllerEventSendExit(ctrl, rc); + cleanup: VIR_FORCE_CLOSE(control[0]); VIR_FORCE_CLOSE(control[1]); @@ -1527,5 +1650,5 @@ cleanup: virLXCControllerFree(ctrl); - return rc ? EXIT_FAILURE : EXIT_SUCCESS; + return rc < 0? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/src/lxc/lxc_domain.h b/src/lxc/lxc_domain.h index ff7c96f..9216c7a 100644 --- a/src/lxc/lxc_domain.h +++ b/src/lxc/lxc_domain.h @@ -31,6 +31,7 @@ typedef struct _virLXCDomainObjPrivate virLXCDomainObjPrivate; typedef virLXCDomainObjPrivate *virLXCDomainObjPrivatePtr; struct _virLXCDomainObjPrivate { virLXCMonitorPtr monitor; + int shutoffReason; }; void virLXCDomainSetPrivateDataHooks(virCapsPtr caps); diff --git a/src/lxc/lxc_monitor.c b/src/lxc/lxc_monitor.c index 6740aa7..e31b970 100644 --- a/src/lxc/lxc_monitor.c +++ b/src/lxc/lxc_monitor.c @@ -22,6 +22,8 @@ #include "lxc_monitor.h" #include "lxc_conf.h" +#include "lxc_protocol.h" +#include "lxc_monitor_dispatch.h" #include "memory.h" @@ -41,9 +43,35 @@ struct _virLXCMonitor { virLXCMonitorCallbacksPtr cb; virNetClientPtr client; + virNetClientProgramPtr program; }; static void virLXCMonitorFree(virLXCMonitorPtr mon); +static void +virLXCMonitorHandleEventExit(virNetClientProgramPtr prog, + virNetClientPtr client, + void *evdata, void *opaque); + +static virNetClientProgramEvent virLXCProtocolEvents[] = { + { VIR_LXC_PROTOCOL_PROC_EXIT_EVENT, + virLXCMonitorHandleEventExit, + sizeof(virLXCProtocolExitEventMsg), + (xdrproc_t)xdr_virLXCProtocolExitEventMsg }, +}; + + +static void +virLXCMonitorHandleEventExit(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, + virNetClientPtr client ATTRIBUTE_UNUSED, + void *evdata, void *opaque) +{ + virLXCMonitorPtr mon = opaque; + virLXCProtocolExitEventMsg *msg = evdata; + + VIR_DEBUG("Event exit %d", msg->status); + if (mon->cb->exitNotify) + mon->cb->exitNotify(mon, msg->status, mon->vm); +} static void virLXCMonitorEOFNotify(virNetClientPtr client ATTRIBUTE_UNUSED, @@ -54,6 +82,7 @@ static void virLXCMonitorEOFNotify(virNetClientPtr client ATTRIBUTE_UNUSED, virLXCMonitorCallbackEOFNotify eofNotify; virDomainObjPtr vm; + VIR_DEBUG("EOF notify"); virLXCMonitorLock(mon); eofNotify = mon->cb->eofNotify; vm = mon->vm; @@ -88,6 +117,17 @@ virLXCMonitorPtr virLXCMonitorNew(virDomainObjPtr vm, goto error; + if (!(mon->program = virNetClientProgramNew(VIR_LXC_PROTOCOL_PROGRAM, + VIR_LXC_PROTOCOL_PROGRAM_VERSION, + virLXCProtocolEvents, + ARRAY_CARDINALITY(virLXCProtocolEvents), + mon))) + goto error; + + if (virNetClientAddProgram(mon->client, + mon->program) < 0) + goto error; + mon->vm = vm; mon->cb = cb; @@ -117,6 +157,7 @@ static void virLXCMonitorFree(virLXCMonitorPtr mon) (mon->cb->destroy)(mon, mon->vm); virMutexDestroy(&mon->lock); virNetClientFree(mon->client); + virNetClientProgramFree(mon->program); VIR_FREE(mon); } diff --git a/src/lxc/lxc_monitor.h b/src/lxc/lxc_monitor.h index 32b8d36..cbcaffd 100644 --- a/src/lxc/lxc_monitor.h +++ b/src/lxc/lxc_monitor.h @@ -22,6 +22,7 @@ # define __LXC_MONITOR_H__ # include "domain_conf.h" +# include "lxc_protocol.h" typedef struct _virLXCMonitor virLXCMonitor; typedef virLXCMonitor *virLXCMonitorPtr; @@ -34,9 +35,14 @@ typedef void (*virLXCMonitorCallbackDestroy)(virLXCMonitorPtr mon, typedef void (*virLXCMonitorCallbackEOFNotify)(virLXCMonitorPtr mon, virDomainObjPtr vm); +typedef void (*virLXCMonitorCallbackExitNotify)(virLXCMonitorPtr mon, + virLXCProtocolExitStatus status, + virDomainObjPtr vm); + struct _virLXCMonitorCallbacks { virLXCMonitorCallbackDestroy destroy; virLXCMonitorCallbackEOFNotify eofNotify; + virLXCMonitorCallbackExitNotify exitNotify; }; virLXCMonitorPtr virLXCMonitorNew(virDomainObjPtr vm, diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 1bfd032..0b0a810 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -164,6 +164,9 @@ static void virLXCProcessCleanup(virLXCDriverPtr driver, virLXCDomainObjPrivatePtr priv = vm->privateData; virNetDevVPortProfilePtr vport = NULL; + VIR_DEBUG("Stopping VM name=%s pid=%d reason=%d", + vm->def->name, (int)vm->pid, (int)reason); + /* now that we know it's stopped call the hook if present */ if (virHookPresent(VIR_HOOK_DRIVER_LXC)) { char *xml = virDomainDefFormat(vm->def, 0); @@ -517,10 +520,31 @@ static void virLXCProcessMonitorEOFNotify(virLXCMonitorPtr mon ATTRIBUTE_UNUSED, } } +static void virLXCProcessMonitorExitNotify(virLXCMonitorPtr mon ATTRIBUTE_UNUSED, + virLXCProtocolExitStatus status, + virDomainObjPtr vm) +{ + virLXCDomainObjPrivatePtr priv = vm->privateData; + + switch (status) { + case VIR_LXC_PROTOCOL_EXIT_STATUS_SHUTDOWN: + priv->shutoffReason = VIR_DOMAIN_SHUTOFF_SHUTDOWN; + break; + case VIR_LXC_PROTOCOL_EXIT_STATUS_ERROR: + priv->shutoffReason = VIR_DOMAIN_SHUTOFF_CRASHED; + break; + default: + priv->shutoffReason = VIR_DOMAIN_SHUTOFF_UNKNOWN; + break; + } + VIR_DEBUG("Domain shutoff reason %d (from status %d)", + priv->shutoffReason, status); +} static virLXCMonitorCallbacks monitorCallbacks = { .eofNotify = virLXCProcessMonitorEOFNotify, .destroy = virLXCProcessMonitorDestroy, + .exitNotify = virLXCProcessMonitorExitNotify, }; @@ -555,6 +579,8 @@ int virLXCProcessStop(virLXCDriverPtr driver, virCgroupPtr group = NULL; int rc; + VIR_DEBUG("Stopping VM name=%s pid=%d reason=%d", + vm->def->name, (int)vm->pid, (int)reason); if (vm->pid <= 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid PID %d for container"), vm->pid); @@ -988,6 +1014,7 @@ int virLXCProcessStart(virConnectPtr conn, goto cleanup; } + priv->shutoffReason = VIR_DOMAIN_SHUTOFF_UNKNOWN; vm->def->id = vm->pid; virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason); diff --git a/src/lxc/lxc_protocol.x b/src/lxc/lxc_protocol.x new file mode 100644 index 0000000..4fdbe34 --- /dev/null +++ b/src/lxc/lxc_protocol.x @@ -0,0 +1,21 @@ +/* -*- c -*- + * Define wire protocol for communication between the + * LXC driver in libvirtd, and the LXC controller in + * the libvirt_lxc helper program. + */ + +enum virLXCProtocolExitStatus { + VIR_LXC_PROTOCOL_EXIT_STATUS_ERROR, + VIR_LXC_PROTOCOL_EXIT_STATUS_SHUTDOWN +}; + +struct virLXCProtocolExitEventMsg { + enum virLXCProtocolExitStatus status; +}; + +const VIR_LXC_PROTOCOL_PROGRAM = 0x12341234; +const VIR_LXC_PROTOCOL_PROGRAM_VERSION = 1; + +enum virLXCProtocolProcedure { + VIR_LXC_PROTOCOL_PROC_EXIT_EVENT = 1 /* skipgen skipgen */ +}; -- 1.7.10.4

On Tue, Jul 24, 2012 at 14:22:51 +0100, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
This defines a new RPC protocol to be used between the LXC controller and the libvirtd LXC driver. There is only a single RPC message defined thus far, an asynchronous "EXIT" event that is emitted just before the LXC controller process exits. This provides the LXC driver with details about how the container shutdown - normally, or abnormally (crashed), thus allowing the driver to emit better libvirt events.
Emitting the event in the LXC controller requires a few little tricks with the RPC service. Simply calling the virNetServiceClientSendMessage does not work, since this merely queues the message for asynchronous processing. In addition the main event loop is no longer running at the point the event is emitted, so no I/O is processed.
Thus after invoking virNetServiceClientSendMessage it is necessary to mark the client as being in "delayed close" mode. Then the event loop is run again, until the client completes its close - this happens only after the queued message has been fully transmitted. The final complexity is that it is not safe to run virNetServerQuit() from the client close callback, since that is invoked from a context where the server is locked. Thus a zero-second timer is used to trigger shutdown of the event loop, causing the controller to finally exit.
* src/Makefile.am: Add rules for generating RPC protocol files and dispatch methods * src/lxc/lxc_controller.c: Emit an RPC event immediately before exiting * src/lxc/lxc_domain.h: Record the shutdown reason given by the controller * src/lxc/lxc_monitor.c, src/lxc/lxc_monitor.h: Register RPC program and event handler. Add callback to let driver receive EXIT event. * src/lxc/lxc_process.c: Use monitor exit event to decide what kind of domain event to emit * src/lxc/lxc_protocol.x: Define wire protocol for LXC controller monitor.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- .gitignore | 4 ++ src/Makefile.am | 50 +++++++++++++++++++ src/lxc/lxc_controller.c | 125 +++++++++++++++++++++++++++++++++++++++++++++- src/lxc/lxc_domain.h | 1 + src/lxc/lxc_monitor.c | 41 +++++++++++++++ src/lxc/lxc_monitor.h | 6 +++ src/lxc/lxc_process.c | 27 ++++++++++ src/lxc/lxc_protocol.x | 21 ++++++++ 8 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 src/lxc/lxc_protocol.x
diff --git a/.gitignore b/.gitignore index b4cbb5f..e4b3932 100644 --- a/.gitignore +++ b/.gitignore @@ -105,6 +105,10 @@ /src/locking/qemu-sanlock.conf /src/locking/test_libvirt_sanlock.aug /src/lxc/test_libvirtd_lxc.aug +/src/lxc/lxc_controller_dispatch.h +/src/lxc/lxc_monitor_dispatch.h +/src/lxc/lxc_protocol.c +/src/lxc/lxc_protocol.h /src/qemu/test_libvirtd_qemu.aug /src/remote/*_client_bodies.h /src/remote/*_protocol.[ch] diff --git a/src/Makefile.am b/src/Makefile.am index 492ce73..44da1fa 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -347,7 +347,55 @@ if WITH_XEN_INOTIFY XEN_DRIVER_SOURCES += xen/xen_inotify.c xen/xen_inotify.h endif
+EXTRA_DIST += \ + dtrace2systemtap.pl \ + rpc/gendispatch.pl \ + rpc/genprotocol.pl \ + rpc/gensystemtap.pl \ + rpc/virnetprotocol.x \ + rpc/virkeepaliveprotocol.x
Did you want to move this EXTRA_DIST part and copied it instead? I don't see the corresponding - lines.
+ +LXC_PROTOCOL_GENERATED = \ + $(srcdir)/lxc/lxc_protocol.h \ + $(srcdir)/lxc/lxc_protocol.c \ + $(NULL)
Did you add $(NULL) because you want to be able to add new entries here without the need append '\' to the last line or is there another reason for it?
+ +LXC_MONITOR_GENERATED = \ + $(srcdir)/lxc/lxc_monitor_dispatch.h \ + $(NULL) + +LXC_CONTROLLER_GENERATED = \ + $(srcdir)/lxc/lxc_controller_dispatch.h \ + $(NULL) + +LXC_GENERATED = \ + $(LXC_PROTOCOL_GENERATED) \ + $(LXC_MONITOR_GENERATED) \ + $(LXC_CONTROLLER_GENERATED) \ + $(NULL) + +LXC_PROTOCOL = $(srcdir)/lxc/lxc_protocol.x + +$(srcdir)/lxc/lxc_monitor_dispatch.h: $(srcdir)/rpc/gendispatch.pl \ + $(LXC_PROTOCOL) + $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl \ + -k virLXCProtocol VIR_LXC_PROTOCOL $(LXC_PROTOCOL) > $@ + +$(srcdir)/lxc/lxc_controller_dispatch.h: $(srcdir)/../src/rpc/gendispatch.pl \
"../src" is redundant here.
+ $(REMOTE_PROTOCOL) + $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl \ + -b virLXCProtocol VIR_LXC_PROTOCOL $(LXC_PROTOCOL) > $@ + +EXTRA_DIST += \ + $(LXC_PROTOCOL) \ + $(LXC_GENERATED) \ + $(NULL) + +BUILT_SOURCES += $(LXC_GENERATED) + LXC_DRIVER_SOURCES = \ + $(LXC_PROTOCOL_GENERATED) \ + $(LXC_MONITOR_GENERATED) \ lxc/lxc_conf.c lxc/lxc_conf.h \ lxc/lxc_container.c lxc/lxc_container.h \ lxc/lxc_cgroup.c lxc/lxc_cgroup.h \ @@ -357,6 +405,8 @@ LXC_DRIVER_SOURCES = \ lxc/lxc_driver.c lxc/lxc_driver.h
LXC_CONTROLLER_SOURCES = \ + $(LXC_PROTOCOL_GENERATED) \ + $(LXC_CONTROLLER_GENERATED) \ lxc/lxc_conf.c lxc/lxc_conf.h \ lxc/lxc_container.c lxc/lxc_container.h \ lxc/lxc_cgroup.c lxc/lxc_cgroup.h \ diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index e39c236..7fcc953 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c ... @@ -1219,6 +1267,79 @@ virLXCControllerSetupConsoles(virLXCControllerPtr ctrl, }
+static void +virLXCControllerEventSend(virLXCControllerPtr ctrl, + int procnr, + xdrproc_t proc, + void *data) +{ + virNetMessagePtr msg; + + if (!ctrl->client) + return; + + VIR_DEBUG("Send event %d client=%p", procnr, ctrl->client); + if (!(msg = virNetMessageNew(false))) + goto cleanup; + + msg->header.prog = virNetServerProgramGetID(ctrl->prog); + msg->header.vers = virNetServerProgramGetVersion(ctrl->prog); + msg->header.proc = procnr; + msg->header.type = VIR_NET_MESSAGE; + msg->header.serial = 1; + msg->header.status = VIR_NET_OK; + + if (virNetMessageEncodeHeader(msg) < 0) + goto cleanup; + + if (virNetMessageEncodePayload(msg, proc, data) < 0) + goto cleanup; + + VIR_DEBUG("Queue event %d %zu", procnr, msg->bufferLength); + virNetServerClientSendMessage(ctrl->client, msg); + + xdr_free(proc, data); + return; + +cleanup:
I'd rename this label as "error" as it is only ever called in error path.
+ virNetMessageFree(msg); + xdr_free(proc, data); +} ... diff --git a/src/lxc/lxc_protocol.x b/src/lxc/lxc_protocol.x new file mode 100644 index 0000000..4fdbe34 --- /dev/null +++ b/src/lxc/lxc_protocol.x @@ -0,0 +1,21 @@ +/* -*- c -*- + * Define wire protocol for communication between the + * LXC driver in libvirtd, and the LXC controller in + * the libvirt_lxc helper program. + */ + +enum virLXCProtocolExitStatus { + VIR_LXC_PROTOCOL_EXIT_STATUS_ERROR, + VIR_LXC_PROTOCOL_EXIT_STATUS_SHUTDOWN +}; + +struct virLXCProtocolExitEventMsg { + enum virLXCProtocolExitStatus status; +}; + +const VIR_LXC_PROTOCOL_PROGRAM = 0x12341234;
Hopefully nobody will find anything offending in this constant :-)
+const VIR_LXC_PROTOCOL_PROGRAM_VERSION = 1; + +enum virLXCProtocolProcedure { + VIR_LXC_PROTOCOL_PROC_EXIT_EVENT = 1 /* skipgen skipgen */ +};
ACK with the nits addressed. Jirka

On Fri, Jul 27, 2012 at 09:41:29AM +0200, Jiri Denemark wrote:
On Tue, Jul 24, 2012 at 14:22:51 +0100, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
This defines a new RPC protocol to be used between the LXC controller and the libvirtd LXC driver. There is only a single RPC message defined thus far, an asynchronous "EXIT" event that is emitted just before the LXC controller process exits. This provides the LXC driver with details about how the container shutdown - normally, or abnormally (crashed), thus allowing the driver to emit better libvirt events.
Emitting the event in the LXC controller requires a few little tricks with the RPC service. Simply calling the virNetServiceClientSendMessage does not work, since this merely queues the message for asynchronous processing. In addition the main event loop is no longer running at the point the event is emitted, so no I/O is processed.
Thus after invoking virNetServiceClientSendMessage it is necessary to mark the client as being in "delayed close" mode. Then the event loop is run again, until the client completes its close - this happens only after the queued message has been fully transmitted. The final complexity is that it is not safe to run virNetServerQuit() from the client close callback, since that is invoked from a context where the server is locked. Thus a zero-second timer is used to trigger shutdown of the event loop, causing the controller to finally exit.
* src/Makefile.am: Add rules for generating RPC protocol files and dispatch methods * src/lxc/lxc_controller.c: Emit an RPC event immediately before exiting * src/lxc/lxc_domain.h: Record the shutdown reason given by the controller * src/lxc/lxc_monitor.c, src/lxc/lxc_monitor.h: Register RPC program and event handler. Add callback to let driver receive EXIT event. * src/lxc/lxc_process.c: Use monitor exit event to decide what kind of domain event to emit * src/lxc/lxc_protocol.x: Define wire protocol for LXC controller monitor.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- .gitignore | 4 ++ src/Makefile.am | 50 +++++++++++++++++++ src/lxc/lxc_controller.c | 125 +++++++++++++++++++++++++++++++++++++++++++++- src/lxc/lxc_domain.h | 1 + src/lxc/lxc_monitor.c | 41 +++++++++++++++ src/lxc/lxc_monitor.h | 6 +++ src/lxc/lxc_process.c | 27 ++++++++++ src/lxc/lxc_protocol.x | 21 ++++++++ 8 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 src/lxc/lxc_protocol.x
diff --git a/.gitignore b/.gitignore index b4cbb5f..e4b3932 100644 --- a/.gitignore +++ b/.gitignore @@ -105,6 +105,10 @@ /src/locking/qemu-sanlock.conf /src/locking/test_libvirt_sanlock.aug /src/lxc/test_libvirtd_lxc.aug +/src/lxc/lxc_controller_dispatch.h +/src/lxc/lxc_monitor_dispatch.h +/src/lxc/lxc_protocol.c +/src/lxc/lxc_protocol.h /src/qemu/test_libvirtd_qemu.aug /src/remote/*_client_bodies.h /src/remote/*_protocol.[ch] diff --git a/src/Makefile.am b/src/Makefile.am index 492ce73..44da1fa 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -347,7 +347,55 @@ if WITH_XEN_INOTIFY XEN_DRIVER_SOURCES += xen/xen_inotify.c xen/xen_inotify.h endif
+EXTRA_DIST += \ + dtrace2systemtap.pl \ + rpc/gendispatch.pl \ + rpc/genprotocol.pl \ + rpc/gensystemtap.pl \ + rpc/virnetprotocol.x \ + rpc/virkeepaliveprotocol.x
Did you want to move this EXTRA_DIST part and copied it instead? I don't see the corresponding - lines.
Hmm, not sure what went wrong here.
+ +LXC_PROTOCOL_GENERATED = \ + $(srcdir)/lxc/lxc_protocol.h \ + $(srcdir)/lxc/lxc_protocol.c \ + $(NULL)
Did you add $(NULL) because you want to be able to add new entries here without the need append '\' to the last line or is there another reason for it?
Yes, it means when you add new entries you only get a 1-line diff, instead of a 2-line diff from adding '\'. We should in fact make this change across all our makefiles some time. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

From: "Daniel P. Berrange" <berrange@redhat.com> Check whether the reboot() system call is virtualized, and if it is, then allow the container to keep CAP_SYS_REBOOT. Based on an original patch by Serge Hallyn Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/lxc/lxc_container.c | 88 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 3 deletions(-) diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index c555559..8696e08 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -36,6 +36,8 @@ #include <unistd.h> #include <mntent.h> #include <dirent.h> +#include <sys/reboot.h> +#include <linux/reboot.h> /* Yes, we want linux private one, for _syscall2() macro */ #include <linux/unistd.h> @@ -102,6 +104,82 @@ struct __lxc_child_argv { }; + + +/* + * reboot(LINUX_REBOOT_CMD_CAD_ON) will return -EINVAL + * in a child pid namespace if container reboot support exists. + * Otherwise, it will either succeed or return -EPERM. + */ +ATTRIBUTE_NORETURN static int +lxcContainerRebootChild(void *argv) +{ + int *cmd = argv; + int ret; + + ret = reboot(*cmd); + if (ret == -1 && errno == EINVAL) + _exit(1); + _exit(0); +} + + +static +int lxcContainerHasReboot(void) +{ + int flags = CLONE_NEWPID|CLONE_NEWNS|CLONE_NEWUTS| + CLONE_NEWIPC|SIGCHLD; + int cpid; + char *childStack; + char *stack; + char *buf; + int cmd, v; + int status; + char *tmp; + + if (virFileReadAll("/proc/sys/kernel/ctrl-alt-del", 10, &buf) < 0) + return -1; + + if ((tmp = strchr(buf, '\n'))) + *tmp = '\0'; + + if (virStrToLong_i(buf, NULL, 10, &v) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Malformed ctrl-alt-del setting '%s'"), buf); + VIR_FREE(buf); + return -1; + } + VIR_FREE(buf); + cmd = v ? LINUX_REBOOT_CMD_CAD_ON : LINUX_REBOOT_CMD_CAD_OFF; + + if (VIR_ALLOC_N(stack, getpagesize() * 4) < 0) { + virReportOOMError(); + return -1; + } + + childStack = stack + (getpagesize() * 4); + + cpid = clone(lxcContainerRebootChild, childStack, flags, &cmd); + VIR_FREE(stack); + if (cpid < 0) { + virReportSystemError(errno, "%s", + _("Unable to clone to check reboot support")); + return -1; + } else if (virPidWait(cpid, &status) < 0) { + return -1; + } + + if (WEXITSTATUS(status) != 1) { + VIR_DEBUG("No, containerized reboot support is missing " + "(kernel probably too old < 3.4)"); + return 0; + } + + VIR_DEBUG("Yes, there is containerized reboot support"); + return 1; +} + + /** * lxcContainerBuildInitCmd: * @vmDef: pointer to vm definition structure @@ -1583,7 +1661,7 @@ static int lxcContainerSetupMounts(virDomainDefPtr vmDef, * It removes some capabilities that could be dangerous to * host system, since they are not currently "containerized" */ -static int lxcContainerDropCapabilities(void) +static int lxcContainerDropCapabilities(bool keepReboot) { #if HAVE_CAPNG int ret; @@ -1593,11 +1671,11 @@ static int lxcContainerDropCapabilities(void) if ((ret = capng_updatev(CAPNG_DROP, CAPNG_EFFECTIVE | CAPNG_PERMITTED | CAPNG_INHERITABLE | CAPNG_BOUNDING_SET, - CAP_SYS_BOOT, /* No use of reboot */ CAP_SYS_MODULE, /* No kernel module loading */ CAP_SYS_TIME, /* No changing the clock */ CAP_AUDIT_CONTROL, /* No messing with auditing status */ CAP_MAC_ADMIN, /* No messing with LSM config */ + keepReboot ? -1 : CAP_SYS_BOOT, /* No use of reboot */ -1 /* sentinal */)) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Failed to remove capabilities: %d"), ret); @@ -1644,6 +1722,7 @@ static int lxcContainerChild( void *data ) char *ttyPath = NULL; virDomainFSDefPtr root; virCommandPtr cmd = NULL; + int hasReboot; if (NULL == vmDef) { virReportError(VIR_ERR_INTERNAL_ERROR, @@ -1651,6 +1730,9 @@ static int lxcContainerChild( void *data ) goto cleanup; } + if ((hasReboot = lxcContainerHasReboot()) < 0) + goto cleanup; + cmd = lxcContainerBuildInitCmd(vmDef); virCommandWriteArgLog(cmd, 1); @@ -1714,7 +1796,7 @@ static int lxcContainerChild( void *data ) } /* drop a set of root capabilities */ - if (lxcContainerDropCapabilities() < 0) + if (lxcContainerDropCapabilities(!!hasReboot) < 0) goto cleanup; if (lxcContainerSendContinue(argv->handshakefd) < 0) { -- 1.7.10.4

On Tue, Jul 24, 2012 at 14:22:52 +0100, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
Check whether the reboot() system call is virtualized, and if it is, then allow the container to keep CAP_SYS_REBOOT.
Based on an original patch by Serge Hallyn
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/lxc/lxc_container.c | 88 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 3 deletions(-)
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index c555559..8696e08 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -36,6 +36,8 @@ #include <unistd.h> #include <mntent.h> #include <dirent.h> +#include <sys/reboot.h> +#include <linux/reboot.h>
/* Yes, we want linux private one, for _syscall2() macro */ #include <linux/unistd.h> @@ -102,6 +104,82 @@ struct __lxc_child_argv { };
+ +
Looks like quite a few empty lines here :-)
+/* + * reboot(LINUX_REBOOT_CMD_CAD_ON) will return -EINVAL + * in a child pid namespace if container reboot support exists. + * Otherwise, it will either succeed or return -EPERM. + */ +ATTRIBUTE_NORETURN static int +lxcContainerRebootChild(void *argv) +{ + int *cmd = argv; + int ret; + + ret = reboot(*cmd); + if (ret == -1 && errno == EINVAL) + _exit(1); + _exit(0); +} + + +static +int lxcContainerHasReboot(void) +{ + int flags = CLONE_NEWPID|CLONE_NEWNS|CLONE_NEWUTS| + CLONE_NEWIPC|SIGCHLD; + int cpid; + char *childStack; + char *stack; + char *buf; + int cmd, v; + int status; + char *tmp; + + if (virFileReadAll("/proc/sys/kernel/ctrl-alt-del", 10, &buf) < 0) + return -1; + + if ((tmp = strchr(buf, '\n'))) + *tmp = '\0'; + + if (virStrToLong_i(buf, NULL, 10, &v) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Malformed ctrl-alt-del setting '%s'"), buf); + VIR_FREE(buf); + return -1; + } + VIR_FREE(buf); + cmd = v ? LINUX_REBOOT_CMD_CAD_ON : LINUX_REBOOT_CMD_CAD_OFF; + + if (VIR_ALLOC_N(stack, getpagesize() * 4) < 0) { + virReportOOMError(); + return -1; + } + + childStack = stack + (getpagesize() * 4); + + cpid = clone(lxcContainerRebootChild, childStack, flags, &cmd); + VIR_FREE(stack); + if (cpid < 0) { + virReportSystemError(errno, "%s", + _("Unable to clone to check reboot support")); + return -1; + } else if (virPidWait(cpid, &status) < 0) { + return -1; + } + + if (WEXITSTATUS(status) != 1) { + VIR_DEBUG("No, containerized reboot support is missing " + "(kernel probably too old < 3.4)"); + return 0; + } + + VIR_DEBUG("Yes, there is containerized reboot support"); + return 1; +}
The last two debug messages are strange, I think "Containerized reboot support is missing (kernel probably too old < 3.4)" and "Containerized reboot is supported" would be better.
+ + /** * lxcContainerBuildInitCmd: * @vmDef: pointer to vm definition structure @@ -1583,7 +1661,7 @@ static int lxcContainerSetupMounts(virDomainDefPtr vmDef, * It removes some capabilities that could be dangerous to * host system, since they are not currently "containerized" */ -static int lxcContainerDropCapabilities(void) +static int lxcContainerDropCapabilities(bool keepReboot) { #if HAVE_CAPNG int ret; @@ -1593,11 +1671,11 @@ static int lxcContainerDropCapabilities(void) if ((ret = capng_updatev(CAPNG_DROP, CAPNG_EFFECTIVE | CAPNG_PERMITTED | CAPNG_INHERITABLE | CAPNG_BOUNDING_SET, - CAP_SYS_BOOT, /* No use of reboot */ CAP_SYS_MODULE, /* No kernel module loading */ CAP_SYS_TIME, /* No changing the clock */ CAP_AUDIT_CONTROL, /* No messing with auditing status */ CAP_MAC_ADMIN, /* No messing with LSM config */ + keepReboot ? -1 : CAP_SYS_BOOT, /* No use of reboot */ -1 /* sentinal */)) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Failed to remove capabilities: %d"), ret); @@ -1644,6 +1722,7 @@ static int lxcContainerChild( void *data ) char *ttyPath = NULL; virDomainFSDefPtr root; virCommandPtr cmd = NULL; + int hasReboot;
if (NULL == vmDef) { virReportError(VIR_ERR_INTERNAL_ERROR, @@ -1651,6 +1730,9 @@ static int lxcContainerChild( void *data ) goto cleanup; }
+ if ((hasReboot = lxcContainerHasReboot()) < 0) + goto cleanup; + cmd = lxcContainerBuildInitCmd(vmDef); virCommandWriteArgLog(cmd, 1);
@@ -1714,7 +1796,7 @@ static int lxcContainerChild( void *data ) }
/* drop a set of root capabilities */ - if (lxcContainerDropCapabilities() < 0) + if (lxcContainerDropCapabilities(!!hasReboot) < 0) goto cleanup;
if (lxcContainerSendContinue(argv->handshakefd) < 0) {
I trust you the clone() and reboot() magic does the right thing :-) ACK. Jirka

On Fri, Jul 27, 2012 at 09:59:47AM +0200, Jiri Denemark wrote:
On Tue, Jul 24, 2012 at 14:22:52 +0100, Daniel P. Berrange wrote:
@@ -1651,6 +1730,9 @@ static int lxcContainerChild( void *data ) goto cleanup; }
+ if ((hasReboot = lxcContainerHasReboot()) < 0) + goto cleanup; + cmd = lxcContainerBuildInitCmd(vmDef); virCommandWriteArgLog(cmd, 1);
@@ -1714,7 +1796,7 @@ static int lxcContainerChild( void *data ) }
/* drop a set of root capabilities */ - if (lxcContainerDropCapabilities() < 0) + if (lxcContainerDropCapabilities(!!hasReboot) < 0) goto cleanup;
if (lxcContainerSendContinue(argv->handshakefd) < 0) {
I trust you the clone() and reboot() magic does the right thing :-) ACK.
Well it doesn't cause the host OS to reboot which is the important thing :-) Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

From: "Daniel P. Berrange" <berrange@redhat.com> The reboot() syscall is allowed by new kernels for LXC containers. The LXC controller can detect whether a reboot was requested (instead of a normal shutdown) by looking at the "init" process exit status. If a reboot was triggered, the exit status will record SIGHUP as the kill reason. The LXC controller has cleared all its capabilities, and the veth network devices will no longer exist at this time. Thus it cannot restart the container init process itself. Instead it emits an event which is picked up by the LXC driver in libvirtd. This will then re-create the container, using the same configuration as it was previously running with (ie it will not activate 'newDef'). Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/lxc/lxc_controller.c | 12 ++++- src/lxc/lxc_domain.h | 1 + src/lxc/lxc_process.c | 119 ++++++++++++++++++++++++++++++++++++++++++---- src/lxc/lxc_protocol.x | 3 +- 4 files changed, 122 insertions(+), 13 deletions(-) diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 7fcc953..a26eec2 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -661,6 +661,7 @@ static int lxcControllerClearCapabilities(void) } static bool quit = false; +static bool wantReboot = false; static virMutex lock; @@ -670,11 +671,15 @@ static void virLXCControllerSignalChildIO(virNetServerPtr server ATTRIBUTE_UNUSE { virLXCControllerPtr ctrl = opaque; int ret; + int status; - ret = waitpid(-1, NULL, WNOHANG); + ret = waitpid(-1, &status, WNOHANG); if (ret == ctrl->initpid) { virMutexLock(&lock); quit = true; + if (WIFSIGNALED(status) && + WTERMSIG(status) == SIGHUP) + wantReboot = true; virMutexUnlock(&lock); } } @@ -998,7 +1003,7 @@ static int virLXCControllerMain(virLXCControllerPtr ctrl) err = virGetLastError(); if (!err || err->code == VIR_ERR_OK) - rc = 0; + rc = wantReboot ? 1 : 0; cleanup: virMutexDestroy(&lock); @@ -1319,6 +1324,9 @@ virLXCControllerEventSendExit(virLXCControllerPtr ctrl, case 0: msg.status = VIR_LXC_PROTOCOL_EXIT_STATUS_SHUTDOWN; break; + case 1: + msg.status = VIR_LXC_PROTOCOL_EXIT_STATUS_REBOOT; + break; default: msg.status = VIR_LXC_PROTOCOL_EXIT_STATUS_ERROR; break; diff --git a/src/lxc/lxc_domain.h b/src/lxc/lxc_domain.h index 9216c7a..4301075 100644 --- a/src/lxc/lxc_domain.h +++ b/src/lxc/lxc_domain.h @@ -32,6 +32,7 @@ typedef virLXCDomainObjPrivate *virLXCDomainObjPrivatePtr; struct _virLXCDomainObjPrivate { virLXCMonitorPtr monitor; int shutoffReason; + bool wantReboot; }; void virLXCDomainSetPrivateDataHooks(virCapsPtr caps); diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 0b0a810..8a1ee7d 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -145,6 +145,58 @@ int virLXCProcessAutoDestroyRemove(virLXCDriverPtr driver, return 0; } +static virConnectPtr +virLXCProcessAutoDestroyGetConn(virLXCDriverPtr driver, + virDomainObjPtr vm) +{ + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(vm->def->uuid, uuidstr); + VIR_DEBUG("vm=%s uuid=%s", vm->def->name, uuidstr); + return virHashLookup(driver->autodestroy, uuidstr); +} + + +static int +virLXCProcessReboot(virLXCDriverPtr driver, + virDomainObjPtr vm) +{ + virConnectPtr conn = virLXCProcessAutoDestroyGetConn(driver, vm); + int reason = vm->state.reason; + bool autodestroy = false; + int ret = -1; + virDomainDefPtr savedDef; + + if (conn) { + virConnectRef(conn); + autodestroy = true; + } else { + conn = virConnectOpen("lxc:///"); + /* Ignoring NULL conn which is mostly harmless here */ + } + + /* In a reboot scenario, we need to make sure we continue + * to use the current 'def', and not switch to 'newDef'. + * So temporarily hide the newDef and then reinstate it + */ + savedDef = vm->newDef; + vm->newDef = NULL; + virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN); + vm->newDef = savedDef; + if (virLXCProcessStart(conn, driver, vm, autodestroy, reason) < 0) { + VIR_WARN("Unable to handle reboot of vm %s", + vm->def->name); + goto cleanup; + } + + if (conn) + virConnectClose(conn); + + ret = 0; + +cleanup: + return ret; +} + /** * virLXCProcessCleanup: @@ -395,14 +447,37 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn, case VIR_DOMAIN_NET_TYPE_NETWORK: { virNetworkPtr network; char *brname = NULL; + bool fail = false; + int active; + virErrorPtr errobj; if (!(network = virNetworkLookupByName(conn, def->nets[i]->data.network.name))) goto cleanup; - brname = virNetworkGetBridgeName(network); + active = virNetworkIsActive(network); + if (active != 1) { + fail = true; + if (active == 0) + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Network '%s' is not active."), + def->nets[i]->data.network.name); + goto cleanup; + } + + if (!fail) { + brname = virNetworkGetBridgeName(network); + if (brname == NULL) + fail = true; + } + + /* Make sure any above failure is preserved */ + errobj = virSaveLastError(); virNetworkFree(network); - if (!brname) + virSetError(errobj); + virFreeError(errobj); + + if (fail) goto cleanup; if (virLXCProcessSetupInterfaceBridged(conn, @@ -496,19 +571,38 @@ static void virLXCProcessMonitorEOFNotify(virLXCMonitorPtr mon ATTRIBUTE_UNUSED, { virLXCDriverPtr driver = lxc_driver; virDomainEventPtr event = NULL; + virLXCDomainObjPrivatePtr priv; lxcDriverLock(driver); virDomainObjLock(vm); lxcDriverUnlock(driver); - virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN); - event = virDomainEventNewFromObj(vm, - VIR_DOMAIN_EVENT_STOPPED, - VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); - virDomainAuditStop(vm, "shutdown"); - if (!vm->persistent) { - virDomainRemoveInactive(&driver->domains, vm); - vm = NULL; + priv = vm->privateData; + if (!priv->wantReboot) { + virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN); + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); + virDomainAuditStop(vm, "shutdown"); + if (!vm->persistent) { + virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } + } else { + int ret =virLXCProcessReboot(driver, vm); + virDomainAuditStop(vm, "reboot"); + virDomainAuditStart(vm, "reboot", ret == 0); + if (ret == 0) { + event = virDomainEventRebootNewFromObj(vm); + } else { + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); + if (!vm->persistent) { + virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } + } } if (vm) @@ -533,6 +627,10 @@ static void virLXCProcessMonitorExitNotify(virLXCMonitorPtr mon ATTRIBUTE_UNUSED case VIR_LXC_PROTOCOL_EXIT_STATUS_ERROR: priv->shutoffReason = VIR_DOMAIN_SHUTOFF_CRASHED; break; + case VIR_LXC_PROTOCOL_EXIT_STATUS_REBOOT: + priv->shutoffReason = VIR_DOMAIN_SHUTOFF_SHUTDOWN; + priv->wantReboot = true; + break; default: priv->shutoffReason = VIR_DOMAIN_SHUTOFF_UNKNOWN; break; @@ -1015,6 +1113,7 @@ int virLXCProcessStart(virConnectPtr conn, } priv->shutoffReason = VIR_DOMAIN_SHUTOFF_UNKNOWN; + priv->wantReboot = false; vm->def->id = vm->pid; virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason); diff --git a/src/lxc/lxc_protocol.x b/src/lxc/lxc_protocol.x index 4fdbe34..e437217 100644 --- a/src/lxc/lxc_protocol.x +++ b/src/lxc/lxc_protocol.x @@ -6,7 +6,8 @@ enum virLXCProtocolExitStatus { VIR_LXC_PROTOCOL_EXIT_STATUS_ERROR, - VIR_LXC_PROTOCOL_EXIT_STATUS_SHUTDOWN + VIR_LXC_PROTOCOL_EXIT_STATUS_SHUTDOWN, + VIR_LXC_PROTOCOL_EXIT_STATUS_REBOOT }; struct virLXCProtocolExitEventMsg { -- 1.7.10.4

On Tue, Jul 24, 2012 at 14:22:53 +0100, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
The reboot() syscall is allowed by new kernels for LXC containers. The LXC controller can detect whether a reboot was requested (instead of a normal shutdown) by looking at the "init" process exit status. If a reboot was triggered, the exit status will record SIGHUP as the kill reason.
The LXC controller has cleared all its capabilities, and the veth network devices will no longer exist at this time. Thus it cannot restart the container init process itself. Instead it emits an event which is picked up by the LXC driver in libvirtd. This will then re-create the container, using the same configuration as it was previously running with (ie it will not activate 'newDef').
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/lxc/lxc_controller.c | 12 ++++- src/lxc/lxc_domain.h | 1 + src/lxc/lxc_process.c | 119 ++++++++++++++++++++++++++++++++++++++++++---- src/lxc/lxc_protocol.x | 3 +- 4 files changed, 122 insertions(+), 13 deletions(-)
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 7fcc953..a26eec2 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -661,6 +661,7 @@ static int lxcControllerClearCapabilities(void) }
static bool quit = false; +static bool wantReboot = false; static virMutex lock;
@@ -670,11 +671,15 @@ static void virLXCControllerSignalChildIO(virNetServerPtr server ATTRIBUTE_UNUSE { virLXCControllerPtr ctrl = opaque; int ret; + int status;
- ret = waitpid(-1, NULL, WNOHANG); + ret = waitpid(-1, &status, WNOHANG); if (ret == ctrl->initpid) { virMutexLock(&lock); quit = true; + if (WIFSIGNALED(status) && + WTERMSIG(status) == SIGHUP) + wantReboot = true; virMutexUnlock(&lock); } } @@ -998,7 +1003,7 @@ static int virLXCControllerMain(virLXCControllerPtr ctrl)
err = virGetLastError(); if (!err || err->code == VIR_ERR_OK) - rc = 0; + rc = wantReboot ? 1 : 0;
cleanup: virMutexDestroy(&lock); @@ -1319,6 +1324,9 @@ virLXCControllerEventSendExit(virLXCControllerPtr ctrl, case 0: msg.status = VIR_LXC_PROTOCOL_EXIT_STATUS_SHUTDOWN; break; + case 1: + msg.status = VIR_LXC_PROTOCOL_EXIT_STATUS_REBOOT; + break; default: msg.status = VIR_LXC_PROTOCOL_EXIT_STATUS_ERROR; break; diff --git a/src/lxc/lxc_domain.h b/src/lxc/lxc_domain.h index 9216c7a..4301075 100644 --- a/src/lxc/lxc_domain.h +++ b/src/lxc/lxc_domain.h @@ -32,6 +32,7 @@ typedef virLXCDomainObjPrivate *virLXCDomainObjPrivatePtr; struct _virLXCDomainObjPrivate { virLXCMonitorPtr monitor; int shutoffReason; + bool wantReboot; };
void virLXCDomainSetPrivateDataHooks(virCapsPtr caps); diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 0b0a810..8a1ee7d 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -145,6 +145,58 @@ int virLXCProcessAutoDestroyRemove(virLXCDriverPtr driver, return 0; }
+static virConnectPtr +virLXCProcessAutoDestroyGetConn(virLXCDriverPtr driver, + virDomainObjPtr vm) +{ + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(vm->def->uuid, uuidstr); + VIR_DEBUG("vm=%s uuid=%s", vm->def->name, uuidstr); + return virHashLookup(driver->autodestroy, uuidstr); +} + + +static int +virLXCProcessReboot(virLXCDriverPtr driver, + virDomainObjPtr vm) +{ + virConnectPtr conn = virLXCProcessAutoDestroyGetConn(driver, vm); + int reason = vm->state.reason; + bool autodestroy = false; + int ret = -1; + virDomainDefPtr savedDef; + + if (conn) { + virConnectRef(conn); + autodestroy = true; + } else { + conn = virConnectOpen("lxc:///"); + /* Ignoring NULL conn which is mostly harmless here */
So why do we even try to connect here?
+ } + + /* In a reboot scenario, we need to make sure we continue + * to use the current 'def', and not switch to 'newDef'. + * So temporarily hide the newDef and then reinstate it + */ + savedDef = vm->newDef; + vm->newDef = NULL; + virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN); + vm->newDef = savedDef; + if (virLXCProcessStart(conn, driver, vm, autodestroy, reason) < 0) { + VIR_WARN("Unable to handle reboot of vm %s", + vm->def->name); + goto cleanup; + } + + if (conn) + virConnectClose(conn); + + ret = 0; + +cleanup: + return ret; +} +
/** * virLXCProcessCleanup: @@ -395,14 +447,37 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn, case VIR_DOMAIN_NET_TYPE_NETWORK: { virNetworkPtr network; char *brname = NULL; + bool fail = false; + int active; + virErrorPtr errobj;
if (!(network = virNetworkLookupByName(conn, def->nets[i]->data.network.name))) goto cleanup;
- brname = virNetworkGetBridgeName(network); + active = virNetworkIsActive(network); + if (active != 1) { + fail = true; + if (active == 0) + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Network '%s' is not active."), + def->nets[i]->data.network.name); + goto cleanup; + } + + if (!fail) { + brname = virNetworkGetBridgeName(network); + if (brname == NULL) + fail = true; + } + + /* Make sure any above failure is preserved */ + errobj = virSaveLastError(); virNetworkFree(network); - if (!brname) + virSetError(errobj); + virFreeError(errobj); + + if (fail) goto cleanup;
if (virLXCProcessSetupInterfaceBridged(conn, @@ -496,19 +571,38 @@ static void virLXCProcessMonitorEOFNotify(virLXCMonitorPtr mon ATTRIBUTE_UNUSED, { virLXCDriverPtr driver = lxc_driver; virDomainEventPtr event = NULL; + virLXCDomainObjPrivatePtr priv;
lxcDriverLock(driver); virDomainObjLock(vm); lxcDriverUnlock(driver);
- virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN); - event = virDomainEventNewFromObj(vm, - VIR_DOMAIN_EVENT_STOPPED, - VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); - virDomainAuditStop(vm, "shutdown"); - if (!vm->persistent) { - virDomainRemoveInactive(&driver->domains, vm); - vm = NULL; + priv = vm->privateData; + if (!priv->wantReboot) { + virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN); + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); + virDomainAuditStop(vm, "shutdown"); + if (!vm->persistent) { + virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } + } else { + int ret =virLXCProcessReboot(driver, vm);
s/=/= /
+ virDomainAuditStop(vm, "reboot");
Should we audit stopped domain before calling virLXCProcessReboot?
+ virDomainAuditStart(vm, "reboot", ret == 0); + if (ret == 0) { + event = virDomainEventRebootNewFromObj(vm); + } else { + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); + if (!vm->persistent) { + virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } + } }
if (vm) @@ -533,6 +627,10 @@ static void virLXCProcessMonitorExitNotify(virLXCMonitorPtr mon ATTRIBUTE_UNUSED case VIR_LXC_PROTOCOL_EXIT_STATUS_ERROR: priv->shutoffReason = VIR_DOMAIN_SHUTOFF_CRASHED; break; + case VIR_LXC_PROTOCOL_EXIT_STATUS_REBOOT: + priv->shutoffReason = VIR_DOMAIN_SHUTOFF_SHUTDOWN; + priv->wantReboot = true; + break; default: priv->shutoffReason = VIR_DOMAIN_SHUTOFF_UNKNOWN; break; @@ -1015,6 +1113,7 @@ int virLXCProcessStart(virConnectPtr conn, }
priv->shutoffReason = VIR_DOMAIN_SHUTOFF_UNKNOWN; + priv->wantReboot = false; vm->def->id = vm->pid; virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason);
diff --git a/src/lxc/lxc_protocol.x b/src/lxc/lxc_protocol.x index 4fdbe34..e437217 100644 --- a/src/lxc/lxc_protocol.x +++ b/src/lxc/lxc_protocol.x @@ -6,7 +6,8 @@
enum virLXCProtocolExitStatus { VIR_LXC_PROTOCOL_EXIT_STATUS_ERROR, - VIR_LXC_PROTOCOL_EXIT_STATUS_SHUTDOWN + VIR_LXC_PROTOCOL_EXIT_STATUS_SHUTDOWN, + VIR_LXC_PROTOCOL_EXIT_STATUS_REBOOT };
struct virLXCProtocolExitEventMsg {
ACK with nits addressed. Jirka

On Fri, Jul 27, 2012 at 10:18:48AM +0200, Jiri Denemark wrote:
On Tue, Jul 24, 2012 at 14:22:53 +0100, Daniel P. Berrange wrote:
+static int +virLXCProcessReboot(virLXCDriverPtr driver, + virDomainObjPtr vm) +{ + virConnectPtr conn = virLXCProcessAutoDestroyGetConn(driver, vm); + int reason = vm->state.reason; + bool autodestroy = false; + int ret = -1; + virDomainDefPtr savedDef; + + if (conn) { + virConnectRef(conn); + autodestroy = true; + } else { + conn = virConnectOpen("lxc:///"); + /* Ignoring NULL conn which is mostly harmless here */
So why do we even try to connect here?
This is basically the same logic we use in the autostart codepath. We need the connection available, if the container has any network interfaces to be configured with type=network. I think we should probably change autostart in all drivers to treat this as fatal though. For now I think this is OK until we do a global cleanup of this pattern.
@@ -496,19 +571,38 @@ static void virLXCProcessMonitorEOFNotify(virLXCMonitorPtr mon ATTRIBUTE_UNUSED, { virLXCDriverPtr driver = lxc_driver; virDomainEventPtr event = NULL; + virLXCDomainObjPrivatePtr priv;
lxcDriverLock(driver); virDomainObjLock(vm); lxcDriverUnlock(driver);
- virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN); - event = virDomainEventNewFromObj(vm, - VIR_DOMAIN_EVENT_STOPPED, - VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); - virDomainAuditStop(vm, "shutdown"); - if (!vm->persistent) { - virDomainRemoveInactive(&driver->domains, vm); - vm = NULL; + priv = vm->privateData; + if (!priv->wantReboot) { + virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN); + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); + virDomainAuditStop(vm, "shutdown"); + if (!vm->persistent) { + virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } + } else { + int ret =virLXCProcessReboot(driver, vm);
s/=/= /
+ virDomainAuditStop(vm, "reboot");
Should we audit stopped domain before calling virLXCProcessReboot?
The audit logs describe what has already happened, as opposed to what is going to happen. If virLXCProcessReboot SEGV'd for some reason, we'd get a bogus audit entry that the container had been stopped, when in fact it was still running. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
participants (2)
-
Daniel P. Berrange
-
Jiri Denemark