Convert the LXC driver to use virNetClient

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>
This commit is contained in:
Daniel P. Berrange 2012-07-17 11:55:38 +01:00
parent 4343fee0a8
commit 357866c379
4 changed files with 73 additions and 111 deletions

View File

@ -32,9 +32,6 @@ static void *virLXCDomainObjPrivateAlloc(void)
if (VIR_ALLOC(priv) < 0) if (VIR_ALLOC(priv) < 0)
return NULL; return NULL;
priv->monitor = -1;
priv->monitorWatch = -1;
return priv; return priv;
} }

View File

@ -24,12 +24,14 @@
# define __LXC_DOMAIN_H__ # define __LXC_DOMAIN_H__
# include "lxc_conf.h" # include "lxc_conf.h"
# include "rpc/virnetclient.h"
typedef struct _virLXCDomainObjPrivate virLXCDomainObjPrivate; typedef struct _virLXCDomainObjPrivate virLXCDomainObjPrivate;
typedef virLXCDomainObjPrivate *virLXCDomainObjPrivatePtr; typedef virLXCDomainObjPrivate *virLXCDomainObjPrivatePtr;
struct _virLXCDomainObjPrivate { struct _virLXCDomainObjPrivate {
int monitor; virNetClientPtr monitor;
int monitorWatch; bool doneStopEvent;
}; };
void virLXCDomainSetPrivateDataHooks(virCapsPtr caps); void virLXCDomainSetPrivateDataHooks(virCapsPtr caps);

View File

@ -1276,6 +1276,7 @@ lxcDomainDestroyFlags(virDomainPtr dom,
virDomainObjPtr vm; virDomainObjPtr vm;
virDomainEventPtr event = NULL; virDomainEventPtr event = NULL;
int ret = -1; int ret = -1;
virLXCDomainObjPrivatePtr priv;
virCheckFlags(0, -1); virCheckFlags(0, -1);
@ -1295,10 +1296,12 @@ lxcDomainDestroyFlags(virDomainPtr dom,
goto cleanup; goto cleanup;
} }
priv = vm->privateData;
ret = virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED); ret = virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED);
event = virDomainEventNewFromObj(vm, event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_STOPPED, VIR_DOMAIN_EVENT_STOPPED,
VIR_DOMAIN_EVENT_STOPPED_DESTROYED); VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
priv->doneStopEvent = true;
virDomainAuditStop(vm, "destroyed"); virDomainAuditStop(vm, "destroyed");
if (!vm->persistent) { if (!vm->persistent) {
virDomainRemoveInactive(&driver->domains, vm); virDomainRemoveInactive(&driver->domains, vm);

View File

@ -71,6 +71,7 @@ static void virLXCProcessAutoDestroyDom(void *payload,
unsigned char uuid[VIR_UUID_BUFLEN]; unsigned char uuid[VIR_UUID_BUFLEN];
virDomainObjPtr dom; virDomainObjPtr dom;
virDomainEventPtr event = NULL; virDomainEventPtr event = NULL;
virLXCDomainObjPrivatePtr priv;
VIR_DEBUG("conn=%p uuidstr=%s thisconn=%p", conn, uuidstr, data->conn); VIR_DEBUG("conn=%p uuidstr=%s thisconn=%p", conn, uuidstr, data->conn);
@ -88,12 +89,14 @@ static void virLXCProcessAutoDestroyDom(void *payload,
return; return;
} }
priv = dom->privateData;
VIR_DEBUG("Killing domain"); VIR_DEBUG("Killing domain");
virLXCProcessStop(data->driver, dom, VIR_DOMAIN_SHUTOFF_DESTROYED); virLXCProcessStop(data->driver, dom, VIR_DOMAIN_SHUTOFF_DESTROYED);
virDomainAuditStop(dom, "destroyed"); virDomainAuditStop(dom, "destroyed");
event = virDomainEventNewFromObj(dom, event = virDomainEventNewFromObj(dom,
VIR_DOMAIN_EVENT_STOPPED, VIR_DOMAIN_EVENT_STOPPED,
VIR_DOMAIN_EVENT_STOPPED_DESTROYED); VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
priv->doneStopEvent = true;
if (dom && !dom->persistent) if (dom && !dom->persistent)
virDomainRemoveInactive(&data->driver->domains, dom); virDomainRemoveInactive(&data->driver->domains, dom);
@ -178,8 +181,9 @@ static void virLXCProcessCleanup(virLXCDriverPtr driver,
/* Stop autodestroy in case guest is restarted */ /* Stop autodestroy in case guest is restarted */
virLXCProcessAutoDestroyRemove(driver, vm); virLXCProcessAutoDestroyRemove(driver, vm);
virEventRemoveHandle(priv->monitorWatch); virNetClientClose(priv->monitor);
VIR_FORCE_CLOSE(priv->monitor); virNetClientFree(priv->monitor);
priv->monitor = NULL;
virPidFileDelete(driver->stateDir, vm->def->name); virPidFileDelete(driver->stateDir, vm->def->name);
virDomainDeleteConfig(driver->stateDir, NULL, vm); virDomainDeleteConfig(driver->stateDir, NULL, vm);
@ -187,8 +191,6 @@ static void virLXCProcessCleanup(virLXCDriverPtr driver,
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason); virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason);
vm->pid = -1; vm->pid = -1;
vm->def->id = -1; vm->def->id = -1;
priv->monitor = -1;
priv->monitorWatch = -1;
for (i = 0 ; i < vm->def->nnets ; i++) { for (i = 0 ; i < vm->def->nnets ; i++) {
virDomainNetDefPtr iface = vm->def->nets[i]; virDomainNetDefPtr iface = vm->def->nets[i];
@ -472,60 +474,76 @@ cleanup:
} }
static int virLXCProcessMonitorClient(virLXCDriverPtr driver, extern virLXCDriverPtr lxc_driver;
virDomainObjPtr vm) static void virLXCProcessMonitorEOFNotify(virNetClientPtr client ATTRIBUTE_UNUSED,
int reason ATTRIBUTE_UNUSED,
void *opaque)
{
virLXCDriverPtr driver = lxc_driver;
virDomainObjPtr vm = opaque;
virDomainEventPtr event = NULL;
virLXCDomainObjPrivatePtr priv;
lxcDriverLock(driver);
virDomainObjLock(vm);
lxcDriverUnlock(driver);
priv = vm->privateData;
virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
if (!priv->doneStopEvent) {
event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_STOPPED,
VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
virDomainAuditStop(vm, "shutdown");
} else {
VIR_DEBUG("Stop event has already been sent");
}
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; char *sockpath = NULL;
int fd = -1; virNetClientPtr monitor = NULL;
struct sockaddr_un addr;
if (virAsprintf(&sockpath, "%s/%s.sock", if (virAsprintf(&sockpath, "%s/%s.sock",
driver->stateDir, vm->def->name) < 0) { driver->stateDir, vm->def->name) < 0) {
virReportOOMError(); virReportOOMError();
return -1; return NULL;
} }
if (virSecurityManagerSetSocketLabel(driver->securityManager, vm->def) < 0) { if (virSecurityManagerSetSocketLabel(driver->securityManager, vm->def) < 0)
VIR_ERROR(_("Failed to set security context for monitor for %s"), goto cleanup;
vm->def->name);
goto error;
}
fd = socket(PF_UNIX, SOCK_STREAM, 0); monitor = virNetClientNewUNIX(sockpath, false, NULL);
if (virSecurityManagerClearSocketLabel(driver->securityManager, vm->def) < 0) { if (virSecurityManagerClearSocketLabel(driver->securityManager, vm->def) < 0) {
VIR_ERROR(_("Failed to clear security context for monitor for %s"), virNetClientFree(monitor);
vm->def->name); monitor = NULL;
goto error; goto cleanup;
} }
if (fd < 0) { if (!monitor)
virReportSystemError(errno, "%s", goto cleanup;
_("Failed to create client socket"));
goto error;
}
memset(&addr, 0, sizeof(addr)); virNetClientSetCloseCallback(monitor, virLXCProcessMonitorEOFNotify, vm, NULL);
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;
}
if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
virReportSystemError(errno, "%s",
_("Failed to connect to client socket"));
goto error;
}
cleanup:
VIR_FREE(sockpath); VIR_FREE(sockpath);
return fd; return monitor;
error:
VIR_FREE(sockpath);
VIR_FORCE_CLOSE(fd);
return -1;
} }
@ -581,51 +599,6 @@ cleanup:
return rc; 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 static virCommandPtr
virLXCProcessBuildControllerCmd(virLXCDriverPtr driver, virLXCProcessBuildControllerCmd(virLXCDriverPtr driver,
@ -1003,7 +976,7 @@ int virLXCProcessStart(virConnectPtr conn,
/* Connect to the controller as a client *first* because /* Connect to the controller as a client *first* because
* this will block until the child has written their * this will block until the child has written their
* pid file out to disk */ * pid file out to disk */
if ((priv->monitor = virLXCProcessMonitorClient(driver, vm)) < 0) if (!(priv->monitor = virLXCProcessConnectMonitor(driver, vm)))
goto cleanup; goto cleanup;
/* And get its pid */ /* And get its pid */
@ -1016,6 +989,7 @@ int virLXCProcessStart(virConnectPtr conn,
vm->def->id = vm->pid; vm->def->id = vm->pid;
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason); virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason);
priv->doneStopEvent = false;
if (lxcContainerWaitForContinue(handshakefds[0]) < 0) { if (lxcContainerWaitForContinue(handshakefds[0]) < 0) {
char out[1024]; char out[1024];
@ -1028,14 +1002,6 @@ int virLXCProcessStart(virConnectPtr conn,
goto error; goto error;
} }
if ((priv->monitorWatch = virEventAddHandle(
priv->monitor,
VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_HANGUP,
virLXCProcessMonitorEvent,
vm, NULL)) < 0) {
goto error;
}
if (autoDestroy && if (autoDestroy &&
virLXCProcessAutoDestroyAdd(driver, vm, conn) < 0) virLXCProcessAutoDestroyAdd(driver, vm, conn) < 0)
goto error; goto error;
@ -1085,7 +1051,9 @@ cleanup:
VIR_FREE(veths[i]); VIR_FREE(veths[i]);
} }
if (rc != 0) { if (rc != 0) {
VIR_FORCE_CLOSE(priv->monitor); virNetClientClose(priv->monitor);
virNetClientFree(priv->monitor);
priv->monitor = NULL;
virDomainConfVMNWFilterTeardown(vm); virDomainConfVMNWFilterTeardown(vm);
virSecurityManagerRestoreAllLabel(driver->securityManager, virSecurityManagerRestoreAllLabel(driver->securityManager,
@ -1191,14 +1159,7 @@ virLXCProcessReconnectDomain(void *payload, const void *name ATTRIBUTE_UNUSED, v
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
VIR_DOMAIN_RUNNING_UNKNOWN); VIR_DOMAIN_RUNNING_UNKNOWN);
if ((priv->monitor = virLXCProcessMonitorClient(driver, vm)) < 0) if (!(priv->monitor = virLXCProcessConnectMonitor(driver, vm)))
goto error;
if ((priv->monitorWatch = virEventAddHandle(
priv->monitor,
VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_HANGUP,
virLXCProcessMonitorEvent,
vm, NULL)) < 0)
goto error; goto error;
if (virSecurityManagerReserveLabel(driver->securityManager, if (virSecurityManagerReserveLabel(driver->securityManager,
@ -1221,7 +1182,6 @@ virLXCProcessReconnectDomain(void *payload, const void *name ATTRIBUTE_UNUSED, v
} else { } else {
vm->def->id = -1; vm->def->id = -1;
VIR_FORCE_CLOSE(priv->monitor);
} }
cleanup: cleanup: