The re-architecting of the LXC controller/container process relationship in the previous patch removed the last obstacle to switching over to the generic domain XML routines. So this patch switches the driver over. First the domain_conf.c file gets support for a new type of device, a 'filesystem'. This contains a source, and a mount point. The source can be either an existing directory, or a file or a block device. If it is a directory the source is just bind mounted into the container; for a block device just a regular filesystem mount is done. A file must first be attached to a loop device. LXC only handles directory bind mounts at this time, but it seemed sensible to let the XML parser handle all three options. Then the vast majority of lxc_conf.h/c is deleted - this is all redundant when using the domain_conf.h APIs. Finally, all references to lxc_vm_t are changed to virDomainObj, and lxc_vm_def_t switches to virDomainDef. Finally the LXC driver registers its capabilities data. For this I have chosen an OS type of 'exe', since the 'operating system' we're running in the container is just any plain executable process. domain_conf.c | 178 +++++++++ domain_conf.h | 27 + lxc_conf.c | 1054 +------------------------------------------------------ lxc_conf.h | 121 ------ lxc_container.c | 23 - lxc_container.h | 2 lxc_controller.c | 4 lxc_controller.h | 2 lxc_driver.c | 276 ++++++++------ 9 files changed, 416 insertions(+), 1271 deletions(-) Daniel diff -r 7059fd49ed7e src/domain_conf.c --- a/src/domain_conf.c Mon Jul 14 21:03:46 2008 +0100 +++ b/src/domain_conf.c Mon Jul 14 21:34:06 2008 +0100 @@ -86,6 +86,11 @@ "virtio", "xen") +VIR_ENUM_IMPL(virDomainFS, VIR_DOMAIN_FS_TYPE_LAST, + "mount", + "block", + "file") + VIR_ENUM_IMPL(virDomainNet, VIR_DOMAIN_NET_TYPE_LAST, "user", "ethernet", @@ -230,6 +235,18 @@ VIR_FREE(def->driverType); virDomainDiskDefFree(def->next); + VIR_FREE(def); +} + +void virDomainFSDefFree(virDomainFSDefPtr def) +{ + if (!def) + return; + + VIR_FREE(def->src); + VIR_FREE(def->dst); + + virDomainFSDefFree(def->next); VIR_FREE(def); } @@ -341,6 +358,7 @@ virDomainGraphicsDefFree(def->graphics); virDomainInputDefFree(def->inputs); virDomainDiskDefFree(def->disks); + virDomainFSDefFree(def->fss); virDomainNetDefFree(def->nets); virDomainChrDefFree(def->serials); virDomainChrDefFree(def->parallels); @@ -351,6 +369,7 @@ VIR_FREE(def->os.type); VIR_FREE(def->os.arch); VIR_FREE(def->os.machine); + VIR_FREE(def->os.init); VIR_FREE(def->os.kernel); VIR_FREE(def->os.initrd); VIR_FREE(def->os.cmdline); @@ -610,6 +629,87 @@ error: virDomainDiskDefFree(def); + def = NULL; + goto cleanup; +} + + +/* Parse the XML definition for a disk + * @param node XML nodeset to parse for disk definition + */ +static virDomainFSDefPtr +virDomainFSDefParseXML(virConnectPtr conn, + xmlNodePtr node) { + virDomainFSDefPtr def; + xmlNodePtr cur; + char *type = NULL; + char *source = NULL; + char *target = NULL; + + if (VIR_ALLOC(def) < 0) { + virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); + return NULL; + } + + type = virXMLPropString(node, "type"); + if (type) { + if ((def->type = virDomainFSTypeFromString(type)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown filesystem type '%s'"), type); + goto error; + } + } else { + def->type = VIR_DOMAIN_FS_TYPE_MOUNT; + } + + cur = node->children; + while (cur != NULL) { + if (cur->type == XML_ELEMENT_NODE) { + if ((source == NULL) && + (xmlStrEqual(cur->name, BAD_CAST "source"))) { + + if (def->type == VIR_DOMAIN_FS_TYPE_MOUNT) + source = virXMLPropString(cur, "dir"); + else if (def->type == VIR_DOMAIN_FS_TYPE_FILE) + source = virXMLPropString(cur, "file"); + else if (def->type == VIR_DOMAIN_FS_TYPE_BLOCK) + source = virXMLPropString(cur, "dev"); + } else if ((target == NULL) && + (xmlStrEqual(cur->name, BAD_CAST "target"))) { + target = virXMLPropString(cur, "dir"); + } else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) { + def->readonly = 1; + } + } + cur = cur->next; + } + + if (source == NULL) { + virDomainReportError(conn, VIR_ERR_NO_SOURCE, + target ? "%s" : NULL, target); + goto error; + } + + if (target == NULL) { + virDomainReportError(conn, VIR_ERR_NO_TARGET, + source ? "%s" : NULL, source); + goto error; + } + + def->src = source; + source = NULL; + def->dst = target; + target = NULL; + +cleanup: + VIR_FREE(type); + VIR_FREE(target); + VIR_FREE(source); + + return def; + + error: + virDomainFSDefFree(def); def = NULL; goto cleanup; } @@ -1344,6 +1444,10 @@ dev->type = VIR_DOMAIN_DEVICE_DISK; if (!(dev->data.disk = virDomainDiskDefParseXML(conn, node))) goto error; + } else if (xmlStrEqual(node->name, BAD_CAST "filesystem")) { + dev->type = VIR_DOMAIN_DEVICE_FS; + if (!(dev->data.fs = virDomainFSDefParseXML(conn, node))) + goto error; } else if (xmlStrEqual(node->name, BAD_CAST "interface")) { dev->type = VIR_DOMAIN_DEVICE_NET; if (!(dev->data.net = virDomainNetDefParseXML(conn, node))) @@ -1554,6 +1658,7 @@ } if (!def->os.bootloader) { + def->os.init = virXPathString(conn, "string(./os/init[1])", ctxt); def->os.kernel = virXPathString(conn, "string(./os/kernel[1])", ctxt); def->os.initrd = virXPathString(conn, "string(./os/initrd[1])", ctxt); def->os.cmdline = virXPathString(conn, "string(./os/cmdline[1])", ctxt); @@ -1603,12 +1708,15 @@ def->os.type, def->os.arch, type); +#if 0 if (!emulator) { virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("unsupported guest type")); goto error; } - if (!(def->emulator = strdup(emulator))) { +#endif + if (emulator && + !(def->emulator = strdup(emulator))) { virDomainReportError(conn, VIR_ERR_NO_MEMORY, NULL); goto error; } @@ -1641,6 +1749,23 @@ ptr = ptr->next; } } + } + VIR_FREE(nodes); + + /* analysis of the filesystems */ + if ((n = virXPathNodeSet(conn, "./devices/filesystem", ctxt, &nodes)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("cannot extract filesystem devices")); + goto error; + } + for (i = n - 1 ; i >= 0 ; i--) { + virDomainFSDefPtr fs = virDomainFSDefParseXML(conn, + nodes[i]); + if (!fs) + goto error; + + fs->next = def->fss; + def->fss = fs; } VIR_FREE(nodes); @@ -2195,6 +2320,46 @@ } static int +virDomainFSDefFormat(virConnectPtr conn, + virBufferPtr buf, + virDomainFSDefPtr def) +{ + const char *type = virDomainFSTypeToString(def->type); + + if (!type) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected filesystem type %d"), def->type); + return -1; + } + + virBufferVSprintf(buf, + " <filesystem type='%s'>\n", + type); + + if (def->src) { + if (def->type == VIR_DOMAIN_FS_TYPE_MOUNT) + virBufferEscapeString(buf, " <source dir='%s'/>\n", + def->src); + else if (def->type == VIR_DOMAIN_FS_TYPE_BLOCK) + virBufferEscapeString(buf, " <source dev='%s'/>\n", + def->src); + else + virBufferEscapeString(buf, " <source file='%s'/>\n", + def->src); + } + + virBufferVSprintf(buf, " <target dir='%s'/>\n", + def->dst); + + if (def->readonly) + virBufferAddLit(buf, " <readonly/>\n"); + + virBufferAddLit(buf, " </filesystem>\n"); + + return 0; +} + +static int virDomainNetDefFormat(virConnectPtr conn, virBufferPtr buf, virDomainNetDefPtr def) @@ -2472,6 +2637,7 @@ unsigned char *uuid; char uuidstr[VIR_UUID_STRING_BUFLEN]; virDomainDiskDefPtr disk; + virDomainFSDefPtr fs; virDomainNetDefPtr net; virDomainSoundDefPtr sound; virDomainInputDefPtr input; @@ -2541,6 +2707,9 @@ else virBufferVSprintf(&buf, ">%s</type>\n", def->os.type); + if (def->os.init) + virBufferEscapeString(&buf, " <init>%s</init>\n", + def->os.init); if (def->os.loader) virBufferEscapeString(&buf, " <loader>%s</loader>\n", def->os.loader); @@ -2614,6 +2783,13 @@ if (virDomainDiskDefFormat(conn, &buf, disk) < 0) goto cleanup; disk = disk->next; + } + + fs = def->fss; + while (fs) { + if (virDomainFSDefFormat(conn, &buf, fs) < 0) + goto cleanup; + fs = fs->next; } net = def->nets; diff -r 7059fd49ed7e src/domain_conf.h --- a/src/domain_conf.h Mon Jul 14 21:03:46 2008 +0100 +++ b/src/domain_conf.h Mon Jul 14 21:34:06 2008 +0100 @@ -91,6 +91,27 @@ unsigned int shared : 1; virDomainDiskDefPtr next; +}; + + +/* Two types of disk backends */ +enum virDomainFSType { + VIR_DOMAIN_FS_TYPE_MOUNT, + VIR_DOMAIN_FS_TYPE_BLOCK, + VIR_DOMAIN_FS_TYPE_FILE, + + VIR_DOMAIN_FS_TYPE_LAST +}; + +typedef struct _virDomainFSDef virDomainFSDef; +typedef virDomainFSDef *virDomainFSDefPtr; +struct _virDomainFSDef { + int type; + char *src; + char *dst; + unsigned int readonly : 1; + + virDomainFSDefPtr next; }; @@ -262,6 +283,7 @@ /* Flags for the 'type' field in next struct */ enum virDomainDeviceType { VIR_DOMAIN_DEVICE_DISK, + VIR_DOMAIN_DEVICE_FS, VIR_DOMAIN_DEVICE_NET, VIR_DOMAIN_DEVICE_INPUT, VIR_DOMAIN_DEVICE_SOUND, @@ -273,6 +295,7 @@ int type; union { virDomainDiskDefPtr disk; + virDomainFSDefPtr fs; virDomainNetDefPtr net; virDomainInputDefPtr input; virDomainSoundDefPtr sound; @@ -318,6 +341,7 @@ char *machine; int nBootDevs; int bootDevs[VIR_DOMAIN_BOOT_LAST]; + char *init; char *kernel; char *initrd; char *cmdline; @@ -357,6 +381,7 @@ virDomainGraphicsDefPtr graphics; virDomainDiskDefPtr disks; + virDomainFSDefPtr fss; virDomainNetDefPtr nets; virDomainInputDefPtr inputs; virDomainSoundDefPtr sounds; @@ -411,6 +436,7 @@ void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def); void virDomainInputDefFree(virDomainInputDefPtr def); void virDomainDiskDefFree(virDomainDiskDefPtr def); +void virDomainFSDefFree(virDomainFSDefPtr def); void virDomainNetDefFree(virDomainNetDefPtr def); void virDomainChrDefFree(virDomainChrDefPtr def); void virDomainSoundDefFree(virDomainSoundDefPtr def); @@ -481,6 +507,7 @@ VIR_ENUM_DECL(virDomainDisk) VIR_ENUM_DECL(virDomainDiskDevice) VIR_ENUM_DECL(virDomainDiskBus) +VIR_ENUM_DECL(virDomainFS) VIR_ENUM_DECL(virDomainNet) VIR_ENUM_DECL(virDomainChr) VIR_ENUM_DECL(virDomainSoundModel) diff -r 7059fd49ed7e src/lxc_conf.c --- a/src/lxc_conf.c Mon Jul 14 21:03:46 2008 +0100 +++ b/src/lxc_conf.c Mon Jul 14 21:34:06 2008 +0100 @@ -27,22 +27,8 @@ #ifdef WITH_LXC -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <string.h> -#include <unistd.h> +#include <sys/utsname.h> -#include <libxml/parser.h> -#include <libxml/tree.h> -#include <libxml/uri.h> -#include <libxml/xpath.h> - -#include "buf.h" -#include "util.h" -#include "uuid.h" -#include "xml.h" -#include "memory.h" #include "lxc_conf.h" /* debug macros */ @@ -54,12 +40,12 @@ const char *fmt, ...) { va_list args; - char errorMessage[LXC_MAX_ERROR_LEN]; + char errorMessage[1024]; const char *codeErrorMessage; if (fmt) { va_start(args, fmt); - vsnprintf(errorMessage, LXC_MAX_ERROR_LEN-1, fmt, args); + vsnprintf(errorMessage, sizeof(errorMessage)-1, fmt, args); va_end(args); } else { errorMessage[0] = '\0'; @@ -71,775 +57,51 @@ codeErrorMessage, errorMessage); } -/** - * lxcParseInterfaceXML: - * @conn: pointer to connection - * @nodePtr: pointer to xml node structure - * @vm: pointer to net definition structure to fill in - * - * Parses the XML for a network interface and places the configuration - * in the given structure. - * - * Returns 0 on success or -1 in case of error - */ -static int lxcParseInterfaceXML(virConnectPtr conn, xmlNodePtr nodePtr, - lxc_net_def_t *netDef) +virCapsPtr lxcCapsInit(void) { - int rc = -1; - xmlNodePtr cur; - xmlChar *type = NULL; - xmlChar *parentIfName = NULL; - xmlChar *network = NULL; - xmlChar *bridge = NULL; - xmlChar *macaddr = NULL; + struct utsname utsname; + virCapsPtr caps; + virCapsGuestPtr guest; - netDef->type = LXC_NET_NETWORK; + /* Really, this never fails - look at the man-page. */ + uname (&utsname); - type = xmlGetProp(nodePtr, BAD_CAST "type"); - if (type != NULL) { - if (xmlStrEqual(type, BAD_CAST "network")) { - netDef->type = LXC_NET_NETWORK; - } - else if (xmlStrEqual(type, BAD_CAST "bridge")) { - netDef->type = LXC_NET_BRIDGE; - } - else { - lxcError(conn, NULL, VIR_ERR_XML_ERROR, - _("invalid interface type: %s"), type); - goto error_out; - } - } + if ((caps = virCapabilitiesNew(utsname.machine, + 0, 0)) == NULL) + goto no_memory; - cur = nodePtr->children; - for (cur = nodePtr->children; cur != NULL; cur = cur->next) { - if (cur->type == XML_ELEMENT_NODE) { - DEBUG("cur->name: %s", (char*)(cur->name)); - if ((macaddr == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "mac"))) { - macaddr = xmlGetProp(cur, BAD_CAST "address"); - } else if ((network == NULL) && - (netDef->type == LXC_NET_NETWORK) && - (xmlStrEqual(cur->name, BAD_CAST "source"))) { - network = xmlGetProp(cur, BAD_CAST "network"); - parentIfName = xmlGetProp(cur, BAD_CAST "dev"); - } else if ((bridge == NULL) && - (netDef->type == LXC_NET_BRIDGE) && - (xmlStrEqual(cur->name, BAD_CAST "source"))) { - bridge = xmlGetProp(cur, BAD_CAST "bridge"); - } else if ((parentIfName == NULL) && - (xmlStrEqual(cur->name, BAD_CAST "target"))) { - parentIfName = xmlGetProp(cur, BAD_CAST "dev"); - } - } - } + if ((guest = virCapabilitiesAddGuest(caps, + "exe", + utsname.machine, + sizeof(int) == 4 ? 32 : 8, + NULL, + NULL, + 0, + NULL)) == NULL) + goto no_memory; - if (netDef->type == LXC_NET_NETWORK) { - if (network == NULL) { - lxcError(conn, NULL, VIR_ERR_XML_ERROR, - _("No <source> 'network' attribute specified with <interface type='network'/>")); - goto error_out; - } + if (virCapabilitiesAddGuestDomain(guest, + "lxc", + NULL, + NULL, + 0, + NULL) == NULL) + goto no_memory; - netDef->txName = strdup((char *)network); - if (NULL == netDef->txName) { - lxcError(conn, NULL, VIR_ERR_NO_MEMORY, - _("No storage for network name")); - goto error_out; - } + return caps; - } else if (netDef->type == LXC_NET_BRIDGE) { - if (bridge == NULL) { - lxcError(conn, NULL, VIR_ERR_XML_ERROR, - _("No <source> 'bridge' attribute specified with <interface type='bridge'/>")); - goto error_out; - } - - netDef->txName = strdup((char *)bridge); - if (NULL == netDef->txName) { - lxcError(conn, NULL, VIR_ERR_NO_MEMORY, - _("No storage for bridge name")); - goto error_out; - } - } - - if (parentIfName != NULL) { - DEBUG("set netDef->parentVeth: %s", netDef->parentVeth); - netDef->parentVeth = strdup((char *)parentIfName); - if (NULL == netDef->parentVeth) { - lxcError(conn, NULL, VIR_ERR_NO_MEMORY, - _("No storage for parent veth device name")); - goto error_out; - } - } else { - netDef->parentVeth = NULL; - DEBUG0("set netDef->parentVeth: NULL"); - } - - rc = 0; - -error_out: - xmlFree(macaddr); - xmlFree(network); - xmlFree(bridge); - xmlFree(parentIfName); - - return rc; -} - -/** - * lxcParseDomainInterfaces: - * @conn: pointer to connection - * @nets: on success, points to an list of net def structs - * @contextPtr: pointer to xml context - * - * Parses the domain network interfaces and returns the information in a list - * - * Returns 0 on success or -1 in case of error - */ -static int lxcParseDomainInterfaces(virConnectPtr conn, - lxc_net_def_t **nets, - xmlXPathContextPtr contextPtr) -{ - int rc = -1; - int i; - lxc_net_def_t *netDef; - lxc_net_def_t *prevDef = NULL; - int numNets = 0; - xmlNodePtr *list; - int res; - - DEBUG0("parsing nets"); - - res = virXPathNodeSet(conn, "/domain/devices/interface", contextPtr, &list); - if (res > 0) { - for (i = 0; i < res; ++i) { - netDef = calloc(1, sizeof(lxc_net_def_t)); - if (NULL == netDef) { - lxcError(conn, NULL, VIR_ERR_NO_MEMORY, - _("No storage for net def structure")); - free(list); - goto parse_complete; - } - - rc = lxcParseInterfaceXML(conn, list[i], netDef); - if (0 > rc) { - DEBUG("failed parsing a net: %d", rc); - - free(netDef); - free(list); - goto parse_complete; - } - - DEBUG0("parsed a net"); - - /* set the linked list pointers */ - numNets++; - netDef->next = NULL; - if (0 == i) { - *nets = netDef; - } else { - prevDef->next = netDef; - } - prevDef = netDef; - } - free(list); - } - - rc = numNets; - -parse_complete: - DEBUG("parsed %d nets", rc); - return rc; -} - -static int lxcParseMountXML(virConnectPtr conn, xmlNodePtr nodePtr, - lxc_mount_t *lxcMount) -{ - xmlChar *fsType = NULL; - xmlNodePtr curNode; - xmlChar *mountSource = NULL; - xmlChar *mountTarget = NULL; - int strLen; - int rc = -1; - - fsType = xmlGetProp(nodePtr, BAD_CAST "type"); - if (NULL == fsType) { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("missing filesystem type")); - goto error; - } - - if (xmlStrEqual(fsType, BAD_CAST "mount") == 0) { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("invalid filesystem type")); - goto error; - } - - for (curNode = nodePtr->children; - NULL != curNode; - curNode = curNode->next) { - if (curNode->type != XML_ELEMENT_NODE) { - continue; - } - - if ((mountSource == NULL) && - (xmlStrEqual(curNode->name, BAD_CAST "source"))) { - mountSource = xmlGetProp(curNode, BAD_CAST "dir"); - } else if ((mountTarget == NULL) && - (xmlStrEqual(curNode->name, BAD_CAST "target"))) { - mountTarget = xmlGetProp(curNode, BAD_CAST "dir"); - } - } - - if (mountSource == NULL) { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("missing mount source")); - goto error; - } - - strLen = xmlStrlen(mountSource); - if ((strLen > (PATH_MAX-1)) || (0 == strLen)) { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("empty or invalid mount source")); - goto error; - } - - strncpy(lxcMount->source, (char *)mountSource, strLen); - lxcMount->source[strLen] = '\0'; - - if (mountTarget == NULL) { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("missing mount target")); - goto error; - } - - strLen = xmlStrlen(mountTarget); - if ((strLen > (PATH_MAX-1)) || (0 == strLen)) { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("empty or invalid mount target")); - goto error; - } - - strncpy(lxcMount->target, (char *)mountTarget, strLen); - lxcMount->target[strLen] = '\0'; - - rc = 0; - -error: - xmlFree(fsType); - xmlFree(mountSource); - xmlFree(mountTarget); - - return rc; -} - -static int lxcParseDomainName(virConnectPtr conn, char **name, - xmlXPathContextPtr contextPtr) -{ - char *res; - - res = virXPathString(conn, "string(/domain/name[1])", contextPtr); - if (res == NULL) { - lxcError(conn, NULL, VIR_ERR_NO_NAME, NULL); - return(-1); - } - - *name = res; - return(0); -} - -static int lxcParseDomainUUID(virConnectPtr conn, unsigned char *uuid, - xmlXPathContextPtr contextPtr) -{ - char *res; - - res = virXPathString(conn, "string(/domain/uuid[1])", contextPtr); - if (res == NULL) { - if (virUUIDGenerate(uuid)) { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("failed to generate uuid")); - return(-1); - } - } else { - if (virUUIDParse(res, uuid) < 0) { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("invalid uuid element")); - VIR_FREE(res); - return(-1); - } - VIR_FREE(res); - } - return(0); -} - -static int lxcParseDomainMounts(virConnectPtr conn, - lxc_mount_t **mounts, - xmlXPathContextPtr contextPtr) -{ - int rc = -1; - int i; - lxc_mount_t *mountObj; - lxc_mount_t *prevObj = NULL; - int nmounts = 0; - xmlNodePtr *list; - int res; - - res = virXPathNodeSet(conn, "/domain/devices/filesystem", contextPtr, &list); - if (res > 0) { - for (i = 0; i < res; ++i) { - if (VIR_ALLOC(mountObj) < 0) { - lxcError(conn, NULL, VIR_ERR_NO_MEMORY, "mount"); - goto parse_complete; - } - - rc = lxcParseMountXML(conn, list[i], mountObj); - if (0 > rc) { - VIR_FREE(mountObj); - goto parse_complete; - } - - /* set the linked list pointers */ - nmounts++; - mountObj->next = NULL; - if (0 == i) { - *mounts = mountObj; - } else { - prevObj->next = mountObj; - } - prevObj = mountObj; - } - VIR_FREE(list); - } - - rc = nmounts; - -parse_complete: - return rc; -} - -static int lxcParseDomainInit(virConnectPtr conn, char** init, - xmlXPathContextPtr contextPtr) -{ - char *res; - - res = virXPathString(conn, "string(/domain/os/init[1])", contextPtr); - if (res == NULL) { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("invalid or missing init element")); - return(-1); - } - - if (strlen(res) >= PATH_MAX - 1) { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("init string too long")); - VIR_FREE(res); - return(-1); - } - - *init = res; - - return(0); -} - - -static int lxcParseDomainTty(virConnectPtr conn, char **tty, xmlXPathContextPtr contextPtr) -{ - char *res; - - res = virXPathString(conn, "string(/domain/devices/console[1]/@tty)", contextPtr); - if (res == NULL) { - /* make sure the tty string is empty */ - *tty = strdup(""); - if (*tty == NULL) { - lxcError(conn, NULL, VIR_ERR_NO_MEMORY, NULL); - return(-1); - } - } else { - *tty = res; - } - - return(0); -} - -static int lxcParseDomainMemory(virConnectPtr conn, int* memory, xmlXPathContextPtr contextPtr) -{ - long res; - int rc; - - rc = virXPathLong(conn, "string(/domain/memory[1])", contextPtr, &res); - if ((rc == -2) || ((rc == 0) && (res <= 0))) { - *memory = -1; - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("invalid memory value")); - } else if (rc < 0) { - /* not an error, default to an invalid value so it's not used */ - *memory = -1; - } else { - *memory = (int) res; - } - return(0); -} - -static lxc_vm_def_t * lxcParseXML(virConnectPtr conn, xmlDocPtr docPtr) -{ - xmlNodePtr rootNodePtr = NULL; - xmlXPathContextPtr contextPtr = NULL; - xmlChar *xmlProp = NULL; - lxc_vm_def_t *containerDef; - - if (VIR_ALLOC(containerDef) < 0) { - lxcError(conn, NULL, VIR_ERR_NO_MEMORY, "containerDef"); - return NULL; - } - - /* Prepare parser / xpath context */ - rootNodePtr = xmlDocGetRootElement(docPtr); - if ((rootNodePtr == NULL) || - (!xmlStrEqual(rootNodePtr->name, BAD_CAST "domain"))) { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("invalid root element")); - goto error; - } - - contextPtr = xmlXPathNewContext(docPtr); - if (contextPtr == NULL) { - lxcError(conn, NULL, VIR_ERR_NO_MEMORY, "context"); - goto error; - } - - /* Verify the domain type is linuxcontainer */ - if (!(xmlProp = xmlGetProp(rootNodePtr, BAD_CAST "type"))) { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("missing domain type")); - goto error; - } - - if (!(xmlStrEqual(xmlProp, BAD_CAST LXC_DOMAIN_TYPE))) { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("invalid domain type")); - goto error; - } - VIR_FREE(xmlProp); - - if ((xmlProp = xmlGetProp(rootNodePtr, BAD_CAST "id"))) { - if (0 > virStrToLong_i((char*)xmlProp, NULL, 10, &(containerDef->id))) { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("invalid domain id")); - goto error; - } - - /* verify the container process still exists */ - if (1 != lxcCheckContainerProcess(containerDef)) { - containerDef->id = -1; - } - - } else { - containerDef->id = -1; - } - VIR_FREE(xmlProp); - - if (lxcParseDomainName(conn, &(containerDef->name), contextPtr) < 0) { - goto error; - } - - if (lxcParseDomainInit(conn, &(containerDef->init), contextPtr) < 0) { - goto error; - } - - if (lxcParseDomainUUID(conn, containerDef->uuid, contextPtr) < 0) { - goto error; - } - - containerDef->nmounts = lxcParseDomainMounts(conn, &(containerDef->mounts), - contextPtr); - if (0 > containerDef->nmounts) { - goto error; - } - - containerDef->numNets = lxcParseDomainInterfaces(conn, - &(containerDef->nets), - contextPtr); - if (0 > containerDef->numNets) { - goto error; - } - - if (lxcParseDomainTty(conn, &(containerDef->tty), contextPtr) < 0) { - goto error; - } - - if (lxcParseDomainMemory(conn, &(containerDef->maxMemory), contextPtr) < 0) { - goto error; - } - - xmlXPathFreeContext(contextPtr); - - return containerDef; - - error: - VIR_FREE(xmlProp); - xmlXPathFreeContext(contextPtr); - lxcFreeVMDef(containerDef); - + no_memory: + virCapabilitiesFree(caps); return NULL; } - -lxc_vm_def_t * lxcParseVMDef(virConnectPtr conn, - const char* xmlString, - const char* fileName) -{ - xmlDocPtr xml; - lxc_vm_def_t *containerDef; - - xml = xmlReadDoc(BAD_CAST xmlString, - fileName ? fileName : "domain.xml", - NULL, XML_PARSE_NOENT | - XML_PARSE_NONET | XML_PARSE_NOERROR | - XML_PARSE_NOWARNING); - if (!xml) { - lxcError(conn, NULL, VIR_ERR_XML_ERROR, NULL); - return NULL; - } - - containerDef = lxcParseXML(conn, xml); - - xmlFreeDoc(xml); - - return containerDef; -} - -lxc_vm_t * lxcAssignVMDef(virConnectPtr conn, - lxc_driver_t *driver, - lxc_vm_def_t *def) -{ - lxc_vm_t *vm = NULL; - - if ((vm = lxcFindVMByName(driver, def->name))) { - if (!lxcIsActiveVM(vm)) { - lxcFreeVMDef(vm->def); - vm->def = def; - } else { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("Can't redefine active VM with name %s"), def->name); - return NULL; - } - - return vm; - } - - if (VIR_ALLOC(vm) < 0) { - lxcError(conn, NULL, VIR_ERR_NO_MEMORY, "vm"); - return NULL; - } - - vm->pid = -1; - vm->def = def; - vm->next = driver->vms; - - driver->vms = vm; - - if (lxcIsActiveVM(vm)) { - vm->state = VIR_DOMAIN_RUNNING; - driver->nactivevms++; - } else { - vm->state = VIR_DOMAIN_SHUTOFF; - driver->ninactivevms++; - } - - return vm; -} - -/** - * lxcCheckContainerProcess: - * @def: Ptr to VM definition - * - * Checks if the container process (stored at def->id is running - * - * Returns on success or -1 in case of error - * 0 - no process with id vm->def->id - * 1 - container process exists - * -1 - error - */ -int lxcCheckContainerProcess(lxc_vm_def_t *def) -{ - int rc = -1; - - if (1 < def->id) { - if (-1 == kill(def->id, 0)) { - if (ESRCH == errno) { - rc = 0; - DEBUG("pid %d no longer exists", def->id); - goto done; - } - - lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("error checking container process: %d %s"), - def->id, strerror(errno)); - goto done; - } - - DEBUG("pid %d still exists", def->id); - rc = 1; - goto done; - } - - rc = 0; - -done: - return rc; -} - -void lxcRemoveInactiveVM(lxc_driver_t *driver, - lxc_vm_t *vm) -{ - lxc_vm_t *prevVm = NULL; - lxc_vm_t *curVm; - - for (curVm = driver->vms; - (curVm != vm) && (NULL != curVm); - curVm = curVm->next) { - prevVm = curVm; - } - - if (curVm) { - if (prevVm) { - prevVm->next = curVm->next; - } else { - driver->vms = curVm->next; - } - - driver->ninactivevms--; - } - - lxcFreeVM(vm); -} - -/* Save a container's config data into a persistent file */ -int lxcSaveConfig(virConnectPtr conn, - lxc_driver_t *driver, - lxc_vm_t *vm, - lxc_vm_def_t *def) -{ - int rc = -1; - char *xmlDef; - int fd = -1; - int amtToWrite; - - if (!(xmlDef = lxcGenerateXML(conn, driver, vm, def))) { - return -1; - } - - if ((fd = open(vm->configFile, - O_WRONLY | O_CREAT | O_TRUNC, - S_IRUSR | S_IWUSR )) < 0) { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("cannot create config file %s: %s"), - vm->configFile, strerror(errno)); - goto cleanup; - } - - amtToWrite = strlen(xmlDef); - if (safewrite(fd, xmlDef, amtToWrite) < 0) { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("cannot write config file %s: %s"), - vm->configFile, strerror(errno)); - goto cleanup; - } - - if (close(fd) < 0) { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("cannot save config file %s: %s"), - vm->configFile, strerror(errno)); - goto cleanup; - } - - rc = 0; - - cleanup: - if (fd != -1) { - close(fd); - } - - VIR_FREE(xmlDef); - - return rc; -} - -int lxcSaveVMDef(virConnectPtr conn, - lxc_driver_t *driver, - lxc_vm_t *vm, - lxc_vm_def_t *def) -{ - int rc = -1; - - if (vm->configFile[0] == '\0') { - if ((rc = virFileMakePath(driver->configDir))) { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("cannot create config directory %s: %s"), - driver->configDir, strerror(rc)); - goto save_complete; - } - - if (virFileBuildPath(driver->configDir, vm->def->name, ".xml", - vm->configFile, PATH_MAX) < 0) { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("cannot construct config file path")); - goto save_complete; - } - - strncpy(vm->configFileBase, vm->def->name, PATH_MAX-1); - strncat(vm->configFileBase, ".xml", PATH_MAX - strlen(vm->def->name)-1); - - } - - rc = lxcSaveConfig(conn, driver, vm, def); - -save_complete: - return rc; -} - - - -static lxc_vm_t * lxcLoadConfig(lxc_driver_t *driver, - const char *file, - const char *fullFilePath, - const char *xmlData) -{ - lxc_vm_def_t *containerDef; - lxc_vm_t * vm; - - containerDef = lxcParseVMDef(NULL, xmlData, file); - if (NULL == containerDef) { - DEBUG0("Error parsing container config"); - return NULL; - } - - if (!virFileMatchesNameSuffix(file, containerDef->name, ".xml")) { - DEBUG0("Container name does not match config file name"); - lxcFreeVMDef(containerDef); - return NULL; - } - - vm = lxcAssignVMDef(NULL, driver, containerDef); - if (NULL == vm) { - DEBUG0("Failed to load container config"); - lxcFreeVMDef(containerDef); - return NULL; - } - - strncpy(vm->configFile, fullFilePath, PATH_MAX); - vm->configFile[PATH_MAX-1] = '\0'; - - strncpy(vm->configFileBase, file, PATH_MAX); - vm->configFile[PATH_MAX-1] = '\0'; - - return vm; -} int lxcLoadDriverConfig(lxc_driver_t *driver) { /* Set the container configuration directory */ if ((driver->configDir = strdup(SYSCONF_DIR "/libvirt/lxc")) == NULL) + goto no_memory; + if ((driver->autostartDir = strdup(SYSCONF_DIR "/libvirt/lxc/autostart")) == NULL) goto no_memory; if ((driver->stateDir = strdup(LOCAL_STATE_DIR "/run/libvirt/lxc")) == NULL) goto no_memory; @@ -853,255 +115,5 @@ return -1; } -int lxcLoadContainerConfigFile(lxc_driver_t *driver, - const char *file) -{ - int rc = -1; - char tempPath[PATH_MAX]; - char* xmlData; - - rc = virFileBuildPath(driver->configDir, file, NULL, tempPath, - PATH_MAX); - if (0 > rc) { - DEBUG0("config file name too long"); - goto load_complete; - } - - if ((rc = virFileReadAll(tempPath, LXC_MAX_XML_LENGTH, &xmlData)) < 0) { - goto load_complete; - } - - lxcLoadConfig(driver, file, tempPath, xmlData); - - VIR_FREE(xmlData); - -load_complete: - return rc; -} - -int lxcLoadContainerInfo(lxc_driver_t *driver) -{ - int rc = -1; - DIR *dir; - struct dirent *dirEntry; - - if (!(dir = opendir(driver->configDir))) { - if (ENOENT == errno) { - /* no config dir => no containers */ - rc = 0; - } else { - lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("failed to open config directory %s: %s"), - driver->configDir, strerror(errno)); - } - - goto load_complete; - } - - while ((dirEntry = readdir(dir))) { - if (dirEntry->d_name[0] == '.') { - continue; - } - - if (!virFileHasSuffix(dirEntry->d_name, ".xml")) { - continue; - } - - lxcLoadContainerConfigFile(driver, dirEntry->d_name); - } - - closedir(dir); - - rc = 0; - -load_complete: - return rc; -} - -/* Generate an XML document describing the vm's configuration */ -char *lxcGenerateXML(virConnectPtr conn, - lxc_driver_t *driver ATTRIBUTE_UNUSED, - lxc_vm_t *vm, - lxc_vm_def_t *def) -{ - virBuffer buf = VIR_BUFFER_INITIALIZER; - unsigned char *uuid; - char uuidstr[VIR_UUID_STRING_BUFLEN]; - lxc_mount_t *mount; - lxc_net_def_t *net; - - if (lxcIsActiveVM(vm)) - virBufferVSprintf(&buf, "<domain type='%s' id='%d'>\n", - LXC_DOMAIN_TYPE, vm->def->id); - else - virBufferVSprintf(&buf, "<domain type='%s'>\n", - LXC_DOMAIN_TYPE); - - virBufferVSprintf(&buf, " <name>%s</name>\n", def->name); - - uuid = def->uuid; - virUUIDFormat(uuid, uuidstr); - virBufferVSprintf(&buf, " <uuid>%s</uuid>\n", uuidstr); - virBufferAddLit(&buf, " <os>\n"); - virBufferVSprintf(&buf, " <init>%s</init>\n", def->init); - virBufferAddLit(&buf, " </os>\n"); - virBufferVSprintf(&buf, " <memory>%d</memory>\n", def->maxMemory); - virBufferAddLit(&buf, " <devices>\n"); - - /* loop adding mounts */ - for (mount = def->mounts; mount; mount = mount->next) { - virBufferAddLit(&buf, " <filesystem type='mount'>\n"); - virBufferVSprintf(&buf, " <source dir='%s'/>\n", - mount->source); - virBufferVSprintf(&buf, " <target dir='%s'/>\n", - mount->target); - virBufferAddLit(&buf, " </filesystem>\n"); - } - - /* loop adding nets */ - for (net = def->nets; net; net = net->next) { - if (net->type == LXC_NET_NETWORK) { - virBufferAddLit(&buf, " <interface type='network'>\n"); - virBufferVSprintf(&buf, " <source network='%s'/>\n", - net->txName); - } else { - virBufferAddLit(&buf, " <interface type='bridge'>\n"); - virBufferVSprintf(&buf, " <source bridge='%s'/>\n", - net->txName); - } - - if (NULL != net->parentVeth) { - virBufferVSprintf(&buf, " <target dev='%s'/>\n", - net->parentVeth); - } - - virBufferAddLit(&buf, " </interface>\n"); - - } - - virBufferVSprintf(&buf, " <console tty='%s'/>\n", def->tty); - virBufferAddLit(&buf, " </devices>\n"); - virBufferAddLit(&buf, "</domain>\n"); - - if (virBufferError(&buf)) { - lxcError(conn, NULL, VIR_ERR_NO_MEMORY,_("allocate buffer")); - return NULL; - } - - return virBufferContentAndReset(&buf); -} - -void lxcFreeVMDef(lxc_vm_def_t *vmdef) -{ - lxc_mount_t *curMount; - lxc_mount_t *nextMount; - lxc_net_def_t *curNet; - lxc_net_def_t *nextNet; - - if (vmdef == NULL) - return; - - curMount = vmdef->mounts; - while (curMount) { - nextMount = curMount->next; - VIR_FREE(curMount); - curMount = nextMount; - } - - curNet = vmdef->nets; - while (curNet) { - nextNet = curNet->next; - VIR_FREE(curNet->parentVeth); - VIR_FREE(curNet->txName); - VIR_FREE(curNet); - curNet = nextNet; - } - - VIR_FREE(vmdef->name); - VIR_FREE(vmdef->init); - VIR_FREE(vmdef->tty); - VIR_FREE(vmdef); -} - -void lxcFreeVMs(lxc_vm_t *vms) -{ - lxc_vm_t *curVm = vms; - lxc_vm_t *nextVm; - - while (curVm) { - nextVm = curVm->next; - lxcFreeVM(curVm); - curVm = nextVm; - } -} - -void lxcFreeVM(lxc_vm_t *vm) -{ - lxcFreeVMDef(vm->def); - VIR_FREE(vm); -} - -lxc_vm_t *lxcFindVMByID(const lxc_driver_t *driver, int id) -{ - lxc_vm_t *vm; - - for (vm = driver->vms; vm; vm = vm->next) { - if (lxcIsActiveVM(vm) && (vm->def->id == id)) { - return vm; - } - - } - - return NULL; -} - -lxc_vm_t *lxcFindVMByUUID(const lxc_driver_t *driver, - const unsigned char *uuid) -{ - lxc_vm_t *vm; - - for (vm = driver->vms; vm; vm = vm->next) { - if (!memcmp(vm->def->uuid, uuid, VIR_UUID_BUFLEN)) { - return vm; - } - } - - return NULL; -} - -lxc_vm_t *lxcFindVMByName(const lxc_driver_t *driver, - const char *name) -{ - lxc_vm_t *vm; - - for (vm = driver->vms; vm; vm = vm->next) { - if (STREQ(vm->def->name, name)) { - return vm; - } - } - - return NULL; -} - -int lxcDeleteConfig(virConnectPtr conn, - lxc_driver_t *driver ATTRIBUTE_UNUSED, - const char *configFile, - const char *name) -{ - if (!configFile[0]) { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("no config file for %s"), name); - return -1; - } - - if (unlink(configFile) < 0) { - lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, - _("cannot remove config for %s"), name); - return -1; - } - - return 0; -} - #endif /* WITH_LXC */ diff -r 7059fd49ed7e src/lxc_conf.h --- a/src/lxc_conf.h Mon Jul 14 21:03:46 2008 +0100 +++ b/src/lxc_conf.h Mon Jul 14 21:34:06 2008 +0100 @@ -29,130 +29,23 @@ #ifdef WITH_LXC #include "internal.h" - -/* Defines */ -#define LXC_MAX_TTY_NAME 32 -#define LXC_MAX_XML_LENGTH 16384 -#define LXC_MAX_ERROR_LEN 1024 -#define LXC_DOMAIN_TYPE "lxc" - -/* types of networks for containers */ -enum lxc_net_type { - LXC_NET_NETWORK, - LXC_NET_BRIDGE -}; - -typedef struct __lxc_net_def lxc_net_def_t; -struct __lxc_net_def { - int type; - char *parentVeth; /* veth device in parent namespace */ - char *txName; /* bridge or network name */ - - lxc_net_def_t *next; -}; - -typedef struct __lxc_mount lxc_mount_t; -struct __lxc_mount { - char source[PATH_MAX]; /* user's directory */ - char target[PATH_MAX]; - - lxc_mount_t *next; -}; - -typedef struct __lxc_vm_def lxc_vm_def_t; -struct __lxc_vm_def { - unsigned char uuid[VIR_UUID_BUFLEN]; - char* name; - int id; - - /* init command string */ - char *init; - - int maxMemory; - - /* mounts - list of mount structs */ - int nmounts; - lxc_mount_t *mounts; - - /* tty device */ - char *tty; - - /* network devices */ - int numNets; - lxc_net_def_t *nets; -}; - -typedef struct __lxc_vm lxc_vm_t; -struct __lxc_vm { - int pid; - int state; - int monitor; - - char configFile[PATH_MAX]; - char configFileBase[PATH_MAX]; - - lxc_vm_def_t *def; - - lxc_vm_t *next; -}; +#include "domain_conf.h" +#include "capabilities.h" typedef struct __lxc_driver lxc_driver_t; struct __lxc_driver { - lxc_vm_t *vms; - int nactivevms; - int ninactivevms; + virCapsPtr caps; + + virDomainObjPtr domains; char *configDir; + char *autostartDir; char *stateDir; char *logDir; int have_netns; }; -/* Types and structs */ - -/* Inline Functions */ -static inline int lxcIsActiveVM(lxc_vm_t *vm) -{ - return vm->def->id != -1; -} - -/* Function declarations */ -lxc_vm_def_t * lxcParseVMDef(virConnectPtr conn, - const char* xmlString, - const char* fileName); -int lxcSaveVMDef(virConnectPtr conn, - lxc_driver_t *driver, - lxc_vm_t *vm, - lxc_vm_def_t *def); int lxcLoadDriverConfig(lxc_driver_t *driver); -int lxcSaveConfig(virConnectPtr conn, - lxc_driver_t *driver, - lxc_vm_t *vm, - lxc_vm_def_t *def); -int lxcLoadContainerInfo(lxc_driver_t *driver); -int lxcLoadContainerConfigFile(lxc_driver_t *driver, - const char *file); -lxc_vm_t * lxcAssignVMDef(virConnectPtr conn, - lxc_driver_t *driver, - lxc_vm_def_t *def); -char *lxcGenerateXML(virConnectPtr conn, - lxc_driver_t *driver, - lxc_vm_t *vm, - lxc_vm_def_t *def); -lxc_vm_t *lxcFindVMByID(const lxc_driver_t *driver, int id); -lxc_vm_t *lxcFindVMByUUID(const lxc_driver_t *driver, - const unsigned char *uuid); -lxc_vm_t *lxcFindVMByName(const lxc_driver_t *driver, - const char *name); -int lxcCheckContainerProcess(lxc_vm_def_t *vm); -void lxcRemoveInactiveVM(lxc_driver_t *driver, - lxc_vm_t *vm); -void lxcFreeVMs(lxc_vm_t *vms); -void lxcFreeVM(lxc_vm_t *vm); -void lxcFreeVMDef(lxc_vm_def_t *vmdef); -int lxcDeleteConfig(virConnectPtr conn, - lxc_driver_t *driver, - const char *configFile, - const char *name); +virCapsPtr lxcCapsInit(void); void lxcError(virConnectPtr conn, virDomainPtr dom, diff -r 7059fd49ed7e src/lxc_container.c --- a/src/lxc_container.c Mon Jul 14 21:03:46 2008 +0100 +++ b/src/lxc_container.c Mon Jul 14 21:34:06 2008 +0100 @@ -68,7 +68,7 @@ typedef struct __lxc_child_argv lxc_child_argv_t; struct __lxc_child_argv { - lxc_vm_def_t *config; + virDomainDefPtr config; int nveths; char **veths; int monitor; @@ -85,10 +85,10 @@ * * Does not return */ -static int lxcContainerExecInit(const lxc_vm_def_t *vmDef) +static int lxcContainerExecInit(virDomainDefPtr vmDef) { const char *const argv[] = { - vmDef->init, + vmDef->os.init, NULL, }; @@ -268,8 +268,8 @@ { int rc = -1; lxc_child_argv_t *argv = data; - lxc_vm_def_t *vmDef = argv->config; - lxc_mount_t *curMount; + virDomainDefPtr vmDef = argv->config; + virDomainFSDefPtr curMount; int i; if (NULL == vmDef) { @@ -280,17 +280,20 @@ /* handle the bind mounts first before doing anything else that may */ /* then access those mounted dirs */ - curMount = vmDef->mounts; + curMount = vmDef->fss; for (i = 0; curMount; curMount = curMount->next) { - rc = mount(curMount->source, - curMount->target, + // XXX fix + if (curMount->type != VIR_DOMAIN_FS_TYPE_MOUNT) + continue; + rc = mount(curMount->src, + curMount->dst, NULL, MS_BIND, NULL); if (0 != rc) { lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("failed to mount %s at %s for container: %s"), - curMount->source, curMount->target, strerror(errno)); + curMount->src, curMount->dst, strerror(errno)); return -1; } } @@ -328,7 +331,7 @@ * * Returns PID of container on success or -1 in case of error */ -int lxcContainerStart(lxc_vm_def_t *def, +int lxcContainerStart(virDomainDefPtr def, int nveths, char **veths, int control, diff -r 7059fd49ed7e src/lxc_container.h --- a/src/lxc_container.h Mon Jul 14 21:03:46 2008 +0100 +++ b/src/lxc_container.h Mon Jul 14 21:34:06 2008 +0100 @@ -34,7 +34,7 @@ int lxcContainerSendContinue(int control); -int lxcContainerStart(lxc_vm_def_t *def, +int lxcContainerStart(virDomainDefPtr def, int nveths, char **veths, int control, diff -r 7059fd49ed7e src/lxc_controller.c --- a/src/lxc_controller.c Mon Jul 14 21:03:46 2008 +0100 +++ b/src/lxc_controller.c Mon Jul 14 21:34:06 2008 +0100 @@ -320,7 +320,7 @@ static int -lxcControllerRun(lxc_vm_def_t *def, +lxcControllerRun(virDomainDefPtr def, int nveths, char **veths, int monitor, @@ -381,7 +381,7 @@ } -int lxcControllerStart(lxc_vm_def_t *def, +int lxcControllerStart(virDomainDefPtr def, int nveths, char **veths, int monitor, diff -r 7059fd49ed7e src/lxc_controller.h --- a/src/lxc_controller.h Mon Jul 14 21:03:46 2008 +0100 +++ b/src/lxc_controller.h Mon Jul 14 21:34:06 2008 +0100 @@ -30,7 +30,7 @@ pid_t lxcControllerPID(int monitor); -int lxcControllerStart(lxc_vm_def_t *def, +int lxcControllerStart(virDomainDefPtr def, int nveths, char **veths, int monitor, diff -r 7059fd49ed7e src/lxc_driver.c --- a/src/lxc_driver.c Mon Jul 14 21:03:46 2008 +0100 +++ b/src/lxc_driver.c Mon Jul 14 21:34:06 2008 +0100 @@ -36,7 +36,6 @@ #include <unistd.h> #include <wait.h> -#include "internal.h" #include "lxc_conf.h" #include "lxc_container.h" #include "lxc_driver.h" @@ -108,7 +107,7 @@ int id) { lxc_driver_t *driver = (lxc_driver_t *)conn->privateData; - lxc_vm_t *vm = lxcFindVMByID(driver, id); + virDomainObjPtr vm = virDomainFindByID(driver->domains, id); virDomainPtr dom; if (!vm) { @@ -128,7 +127,7 @@ const unsigned char *uuid) { lxc_driver_t *driver = (lxc_driver_t *)conn->privateData; - lxc_vm_t *vm = lxcFindVMByUUID(driver, uuid); + virDomainObjPtr vm = virDomainFindByUUID(driver->domains, uuid); virDomainPtr dom; if (!vm) { @@ -148,7 +147,7 @@ const char *name) { lxc_driver_t *driver = (lxc_driver_t *)conn->privateData; - lxc_vm_t *vm = lxcFindVMByName(driver, name); + virDomainObjPtr vm = virDomainFindByName(driver->domains, name); virDomainPtr dom; if (!vm) { @@ -164,90 +163,96 @@ return dom; } -static int lxcListDomains(virConnectPtr conn, int *ids, int nids) -{ +static int lxcListDomains(virConnectPtr conn, int *ids, int nids) { lxc_driver_t *driver = (lxc_driver_t *)conn->privateData; - lxc_vm_t *vm; - int numDoms = 0; - - for (vm = driver->vms; vm && (numDoms < nids); vm = vm->next) { - if (lxcIsActiveVM(vm)) { - ids[numDoms] = vm->def->id; - numDoms++; + virDomainObjPtr vm = driver->domains; + int got = 0; + while (vm && got < nids) { + if (virDomainIsActive(vm)) { + ids[got] = vm->def->id; + got++; } + vm = vm->next; } - - return numDoms; + return got; } - -static int lxcNumDomains(virConnectPtr conn) -{ +static int lxcNumDomains(virConnectPtr conn) { lxc_driver_t *driver = (lxc_driver_t *)conn->privateData; - return driver->nactivevms; + int n = 0; + virDomainObjPtr dom = driver->domains; + while (dom) { + if (virDomainIsActive(dom)) + n++; + dom = dom->next; + } + return n; } static int lxcListDefinedDomains(virConnectPtr conn, - char **const names, int nnames) -{ + char **const names, int nnames) { lxc_driver_t *driver = (lxc_driver_t *)conn->privateData; - lxc_vm_t *vm; - int numDoms = 0; - int i; - - for (vm = driver->vms; vm && (numDoms < nnames); vm = vm->next) { - if (!lxcIsActiveVM(vm)) { - if (!(names[numDoms] = strdup(vm->def->name))) { - lxcError(conn, NULL, VIR_ERR_NO_MEMORY, "names"); + virDomainObjPtr vm = driver->domains; + int got = 0, i; + while (vm && got < nnames) { + if (!virDomainIsActive(vm)) { + if (!(names[got] = strdup(vm->def->name))) { + lxcError(conn, NULL, VIR_ERR_NO_MEMORY, NULL); goto cleanup; } - - numDoms++; + got++; } - + vm = vm->next; } - - return numDoms; + return got; cleanup: - for (i = 0 ; i < numDoms ; i++) { + for (i = 0 ; i < got ; i++) VIR_FREE(names[i]); - } - return -1; } -static int lxcNumDefinedDomains(virConnectPtr conn) -{ +static int lxcNumDefinedDomains(virConnectPtr conn) { lxc_driver_t *driver = (lxc_driver_t *)conn->privateData; - return driver->ninactivevms; + int n = 0; + virDomainObjPtr dom = driver->domains; + while (dom) { + if (!virDomainIsActive(dom)) + n++; + dom = dom->next; + } + return n; } + + static virDomainPtr lxcDomainDefine(virConnectPtr conn, const char *xml) { lxc_driver_t *driver = (lxc_driver_t *)conn->privateData; - lxc_vm_def_t *def; - lxc_vm_t *vm; + virDomainDefPtr def; + virDomainObjPtr vm; virDomainPtr dom; - if (!(def = lxcParseVMDef(conn, xml, NULL))) { + if (!(def = virDomainDefParseString(conn, driver->caps, xml))) return NULL; - } if ((def->nets != NULL) && !(driver->have_netns)) { lxcError(conn, NULL, VIR_ERR_NO_SUPPORT, _("System lacks NETNS support")); - lxcFreeVMDef(def); + virDomainDefFree(def); return NULL; } - if (!(vm = lxcAssignVMDef(conn, driver, def))) { - lxcFreeVMDef(def); + if (!(vm = virDomainAssignDef(conn, &driver->domains, def))) { + virDomainDefFree(def); return NULL; } - if (lxcSaveVMDef(conn, driver, vm, def) < 0) { - lxcRemoveInactiveVM(driver, vm); + if (virDomainSaveConfig(conn, + driver->configDir, + driver->autostartDir, + vm) < 0) { + virDomainRemoveInactive(&driver->domains, vm); return NULL; } @@ -262,7 +267,7 @@ static int lxcDomainUndefine(virDomainPtr dom) { lxc_driver_t *driver = (lxc_driver_t *)dom->conn->privateData; - lxc_vm_t *vm = lxcFindVMByUUID(driver, dom->uuid); + virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid); if (!vm) { lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN, @@ -270,19 +275,18 @@ return -1; } - if (lxcIsActiveVM(vm)) { + if (virDomainIsActive(vm)) { lxcError(dom->conn, dom, VIR_ERR_INTERNAL_ERROR, _("cannot delete active domain")); return -1; } - if (lxcDeleteConfig(dom->conn, driver, vm->configFile, vm->def->name) < 0) { + if (virDomainDeleteConfig(dom->conn, vm) <0) return -1; - } vm->configFile[0] = '\0'; - lxcRemoveInactiveVM(driver, vm); + virDomainRemoveInactive(&driver->domains, vm); return 0; } @@ -291,7 +295,7 @@ virDomainInfoPtr info) { lxc_driver_t *driver = (lxc_driver_t *)dom->conn->privateData; - lxc_vm_t *vm = lxcFindVMByUUID(driver, dom->uuid); + virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid); if (!vm) { lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN, @@ -301,30 +305,23 @@ info->state = vm->state; - if (!lxcIsActiveVM(vm)) { + if (!virDomainIsActive(vm)) { info->cpuTime = 0; } else { info->cpuTime = 0; } - info->maxMem = vm->def->maxMemory; - info->memory = vm->def->maxMemory; + info->maxMem = vm->def->maxmem; + info->memory = vm->def->memory; info->nrVirtCpu = 1; return 0; } -static char *lxcGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED) -{ - /* Linux containers only run on Linux */ - return strdup("linux"); -} - -static char *lxcDomainDumpXML(virDomainPtr dom, - int flags ATTRIBUTE_UNUSED) +static char *lxcGetOSType(virDomainPtr dom) { lxc_driver_t *driver = (lxc_driver_t *)dom->conn->privateData; - lxc_vm_t *vm = lxcFindVMByUUID(driver, dom->uuid); + virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid); if (!vm) { lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN, @@ -332,7 +329,25 @@ return NULL; } - return lxcGenerateXML(dom->conn, driver, vm, vm->def); + return strdup(vm->def->os.type); +} + +static char *lxcDomainDumpXML(virDomainPtr dom, + int flags) +{ + lxc_driver_t *driver = (lxc_driver_t *)dom->conn->privateData; + virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid); + + if (!vm) { + lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN, + _("no domain with matching uuid")); + return NULL; + } + + return virDomainDefFormat(dom->conn, + (flags & VIR_DOMAIN_XML_INACTIVE) && + vm->newDef ? vm->newDef : vm->def, + flags); } @@ -346,7 +361,7 @@ * * Returns 0 on success or -1 in case of error */ -static int lxcVMCleanup(lxc_driver_t *driver, lxc_vm_t * vm) +static int lxcVMCleanup(virDomainObjPtr vm) { int rc = -1; int waitRc; @@ -371,8 +386,6 @@ vm->state = VIR_DOMAIN_SHUTOFF; vm->pid = -1; vm->def->id = -1; - driver->nactivevms--; - driver->ninactivevms++; return rc; } @@ -388,12 +401,12 @@ * Returns 0 on success or -1 in case of error */ static int lxcSetupInterfaces(virConnectPtr conn, - lxc_vm_def_t *def, + virDomainDefPtr def, int *nveths, char ***veths) { int rc = -1; - lxc_net_def_t *net; + virDomainNetDefPtr net; char *bridge = NULL; char parentVeth[PATH_MAX] = ""; char containerVeth[PATH_MAX] = ""; @@ -403,8 +416,11 @@ return -1; for (net = def->nets; net; net = net->next) { - if (LXC_NET_NETWORK == net->type) { - virNetworkPtr network = virNetworkLookupByName(conn, net->txName); + switch (net->type) { + case VIR_DOMAIN_NET_TYPE_NETWORK: + { + virNetworkPtr network = virNetworkLookupByName(conn, + net->data.network.name); if (!network) { goto error_exit; } @@ -412,8 +428,11 @@ bridge = virNetworkGetBridgeName(network); virNetworkFree(network); - } else { - bridge = net->txName; + break; + } + case VIR_DOMAIN_NET_TYPE_BRIDGE: + bridge = net->data.bridge.brname; + break; } DEBUG("bridge: %s", bridge); @@ -424,8 +443,8 @@ } DEBUG0("calling vethCreate()"); - if (NULL != net->parentVeth) { - strcpy(parentVeth, net->parentVeth); + if (NULL != net->ifname) { + strcpy(parentVeth, net->ifname); } DEBUG("parentVeth: %s, containerVeth: %s", parentVeth, containerVeth); if (0 != (rc = vethCreate(parentVeth, PATH_MAX, containerVeth, PATH_MAX))) { @@ -433,15 +452,15 @@ _("failed to create veth device pair: %d"), rc); goto error_exit; } - if (NULL == net->parentVeth) { - net->parentVeth = strdup(parentVeth); + if (NULL == net->ifname) { + net->ifname = strdup(parentVeth); } if (VIR_REALLOC_N(*veths, (*nveths)+1) < 0) goto error_exit; if (((*veths)[(*nveths)++] = strdup(containerVeth)) == NULL) goto error_exit; - if (NULL == net->parentVeth) { + if (NULL == net->ifname) { lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("failed to allocate veth names")); goto error_exit; @@ -473,7 +492,7 @@ static int lxcMonitorServer(virConnectPtr conn, lxc_driver_t * driver, - lxc_vm_t *vm) + virDomainObjPtr vm) { char *sockpath = NULL; int fd; @@ -523,7 +542,7 @@ static int lxcMonitorClient(virConnectPtr conn, lxc_driver_t * driver, - lxc_vm_t *vm) + virDomainObjPtr vm) { char *sockpath = NULL; int fd; @@ -576,11 +595,12 @@ */ static int lxcVmStart(virConnectPtr conn, lxc_driver_t * driver, - lxc_vm_t * vm) + virDomainObjPtr vm) { int rc = -1, i; int monitor; int parentTty; + char *parentTtyPath = NULL; char *logfile = NULL; pid_t pid; int nveths = 0; @@ -603,11 +623,17 @@ goto cleanup; /* open parent tty */ - VIR_FREE(vm->def->tty); - if (virFileOpenTty(&parentTty, &vm->def->tty, 1) < 0) { + if (virFileOpenTty(&parentTty, &parentTtyPath, 1) < 0) { lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, _("failed to allocate tty: %s"), strerror(errno)); + } + if (vm->def->console && + vm->def->console->type == VIR_DOMAIN_CHR_TYPE_PTY) { + VIR_FREE(vm->def->console->data.file.path); + vm->def->console->data.file.path = parentTtyPath; + } else { + VIR_FREE(parentTtyPath); } if (lxcSetupInterfaces(conn, vm->def, &nveths, &veths) < 0) @@ -626,8 +652,6 @@ vm->pid = vm->def->id = pid; vm->state = VIR_DOMAIN_RUNNING; - driver->ninactivevms--; - driver->nactivevms++; rc = 0; @@ -662,7 +686,7 @@ int rc = -1; virConnectPtr conn = dom->conn; lxc_driver_t *driver = (lxc_driver_t *)(conn->privateData); - lxc_vm_t *vm = lxcFindVMByName(driver, dom->name); + virDomainObjPtr vm = virDomainFindByName(driver->domains, dom->name); if (!vm) { lxcError(conn, dom, VIR_ERR_INVALID_DOMAIN, @@ -691,26 +715,20 @@ const char *xml, unsigned int flags ATTRIBUTE_UNUSED) { lxc_driver_t *driver = (lxc_driver_t *)conn->privateData; - lxc_vm_t *vm; - lxc_vm_def_t *def; + virDomainObjPtr vm; + virDomainDefPtr def; virDomainPtr dom = NULL; - if (!(def = lxcParseVMDef(conn, xml, NULL))) { + if (!(def = virDomainDefParseString(conn, driver->caps, xml))) + goto return_point; + + if (!(vm = virDomainAssignDef(conn, &driver->domains, def))) { + virDomainDefFree(def); goto return_point; } - if (!(vm = lxcAssignVMDef(conn, driver, def))) { - lxcFreeVMDef(def); - goto return_point; - } - - if (lxcSaveVMDef(conn, driver, vm, def) < 0) { - lxcRemoveInactiveVM(driver, vm); - return NULL; - } - if (lxcVmStart(conn, driver, vm) < 0) { - lxcRemoveInactiveVM(driver, vm); + virDomainRemoveInactive(&driver->domains, vm); goto return_point; } @@ -735,7 +753,7 @@ { int rc = -1; lxc_driver_t *driver = (lxc_driver_t*)dom->conn->privateData; - lxc_vm_t *vm = lxcFindVMByID(driver, dom->id); + virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id); if (!vm) { lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN, @@ -754,7 +772,7 @@ vm->state = VIR_DOMAIN_SHUTDOWN; - rc = lxcVMCleanup(driver, vm); + rc = lxcVMCleanup(vm); error_out: return rc; @@ -773,7 +791,7 @@ { int rc = -1; lxc_driver_t *driver = (lxc_driver_t*)dom->conn->privateData; - lxc_vm_t *vm = lxcFindVMByID(driver, dom->id); + virDomainObjPtr vm = virDomainFindByID(driver->domains, dom->id); if (!vm) { lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN, @@ -792,7 +810,7 @@ vm->state = VIR_DOMAIN_SHUTDOWN; - rc = lxcVMCleanup(driver, vm); + rc = lxcVMCleanup(vm); error_out: return rc; @@ -816,7 +834,7 @@ static int lxcStartup(void) { uid_t uid = getuid(); - lxc_vm_t *vm; + virDomainObjPtr vm; /* Check that the user is root */ if (0 != uid) { @@ -839,13 +857,21 @@ return -1; } - /* Call function to load the container configuration files */ - if (lxcLoadContainerInfo(lxc_driver) < 0) { + if ((lxc_driver->caps = lxcCapsInit()) == NULL) { lxcShutdown(); return -1; } - vm = lxc_driver->vms; + if (virDomainLoadAllConfigs(NULL, + lxc_driver->caps, + &lxc_driver->domains, + lxc_driver->configDir, + lxc_driver->autostartDir) < 0) { + lxcShutdown(); + return -1; + } + + vm = lxc_driver->domains; while (vm) { pid_t pid; if ((vm->monitor = lxcMonitorClient(NULL, lxc_driver, vm)) < 0) { @@ -863,8 +889,6 @@ vm->pid = vm->def->id = pid; vm->state = VIR_DOMAIN_RUNNING; - lxc_driver->ninactivevms--; - lxc_driver->nactivevms++; vm = vm->next; } @@ -875,6 +899,7 @@ static void lxcFreeDriver(lxc_driver_t *driver) { VIR_FREE(driver->configDir); + VIR_FREE(driver->autostartDir); VIR_FREE(driver->stateDir); VIR_FREE(driver->logDir); VIR_FREE(driver); @@ -882,10 +907,15 @@ static int lxcShutdown(void) { + virDomainObjPtr vm; if (lxc_driver == NULL) return(-1); - lxcFreeVMs(lxc_driver->vms); - lxc_driver->vms = NULL; + vm = lxc_driver->domains; + while (vm) { + virDomainObjPtr next = vm->next; + virDomainObjFree(vm); + vm = next; + } lxcFreeDriver(lxc_driver); lxc_driver = NULL; @@ -901,13 +931,17 @@ */ static int lxcActive(void) { + virDomainObjPtr dom; + if (lxc_driver == NULL) return(0); - /* If we've any active networks or guests, then we - * mark this driver as active - */ - if (lxc_driver->nactivevms) - return 1; + + dom = lxc_driver->domains; + while (dom) { + if (virDomainIsActive(dom)) + return 1; + dom = dom->next; + } /* Otherwise we're happy to deal with a shutdown */ return 0; -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list