diff --git a/ChangeLog b/ChangeLog index 4b2883daf74393cb7d94f442bdb22043eb1b5396..677904d2c9b031d5cbe3d83c8056ee99664f9de0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Wed Aug 13 13:40:36 BST 2008 Daniel Berrange + + * src/lxc_conf.c, src/lxc_conf.h: Remove all domain XML + parsing / formatting methods, and all helpers for loading + and saving files on disk. Added capabilities data object + * src/lxc_container.c, src/lxc_container.h, src/lxc_driver.c, + src/lxc_controller.h, src/lxc_controller.c: Switch over + to use generic domain XML processing APIs. + Wed Aug 13 11:48:36 BST 2008 Daniel Berrange * configure.in: Add check for termios.h diff --git a/src/lxc_conf.c b/src/lxc_conf.c index 875651eaedb12a60d6d839136b9b044a9d429c29..94837d90c1f4f532b94652ff65bc5121d31ffea9 100644 --- a/src/lxc_conf.c +++ b/src/lxc_conf.c @@ -27,22 +27,8 @@ #ifdef WITH_LXC -#include -#include -#include -#include -#include +#include -#include -#include -#include -#include - -#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 @@ void lxcError(virConnectPtr conn, virDomainPtr dom, int code, 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,771 +57,42 @@ void lxcError(virConnectPtr conn, virDomainPtr dom, int code, 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) -{ - int rc = -1; - xmlNodePtr cur; - xmlChar *type = NULL; - xmlChar *parentIfName = NULL; - xmlChar *network = NULL; - xmlChar *bridge = NULL; - xmlChar *macaddr = NULL; - - netDef->type = LXC_NET_NETWORK; - - 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; - } - } - - 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 (netDef->type == LXC_NET_NETWORK) { - if (network == NULL) { - lxcError(conn, NULL, VIR_ERR_XML_ERROR, - _("No 'network' attribute specified with ")); - goto error_out; - } - - netDef->txName = strdup((char *)network); - if (NULL == netDef->txName) { - lxcError(conn, NULL, VIR_ERR_NO_MEMORY, - _("No storage for network name")); - goto error_out; - } - - } else if (netDef->type == LXC_NET_BRIDGE) { - if (bridge == NULL) { - lxcError(conn, NULL, VIR_ERR_XML_ERROR, - _("No 'bridge' attribute specified with ")); - 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) +virCapsPtr lxcCapsInit(void) { - 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; - } + struct utsname utsname; + virCapsPtr caps; + virCapsGuestPtr guest; - /* verify the container process still exists */ - if (1 != lxcCheckContainerProcess(containerDef)) { - containerDef->id = -1; - } + uname(&utsname); - } 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); + if ((caps = virCapabilitiesNew(utsname.machine, + 0, 0)) == NULL) + goto no_memory; - return containerDef; + if ((guest = virCapabilitiesAddGuest(caps, + "exe", + utsname.machine, + sizeof(int) == 4 ? 32 : 8, + NULL, + NULL, + 0, + NULL)) == NULL) + goto no_memory; - error: - VIR_FREE(xmlProp); - xmlXPathFreeContext(contextPtr); - lxcFreeVMDef(containerDef); + if (virCapabilitiesAddGuestDomain(guest, + "lxc", + NULL, + NULL, + 0, + NULL) == NULL) + goto no_memory; + return caps; +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 */ @@ -853,254 +110,5 @@ no_memory: 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, "\n", - LXC_DOMAIN_TYPE, vm->def->id); - else - virBufferVSprintf(&buf, "\n", - LXC_DOMAIN_TYPE); - - virBufferVSprintf(&buf, " %s\n", def->name); - - uuid = def->uuid; - virUUIDFormat(uuid, uuidstr); - virBufferVSprintf(&buf, " %s\n", uuidstr); - virBufferAddLit(&buf, " \n"); - virBufferVSprintf(&buf, " %s\n", def->init); - virBufferAddLit(&buf, " \n"); - virBufferVSprintf(&buf, " %d\n", def->maxMemory); - virBufferAddLit(&buf, " \n"); - - /* loop adding mounts */ - for (mount = def->mounts; mount; mount = mount->next) { - virBufferAddLit(&buf, " \n"); - virBufferVSprintf(&buf, " \n", - mount->source); - virBufferVSprintf(&buf, " \n", - mount->target); - virBufferAddLit(&buf, " \n"); - } - - /* loop adding nets */ - for (net = def->nets; net; net = net->next) { - if (net->type == LXC_NET_NETWORK) { - virBufferAddLit(&buf, " \n"); - virBufferVSprintf(&buf, " \n", - net->txName); - } else { - virBufferAddLit(&buf, " \n"); - virBufferVSprintf(&buf, " \n", - net->txName); - } - - if (NULL != net->parentVeth) { - virBufferVSprintf(&buf, " \n", - net->parentVeth); - } - - virBufferAddLit(&buf, " \n"); - - } - - virBufferVSprintf(&buf, " \n", def->tty); - virBufferAddLit(&buf, " \n"); - virBufferAddLit(&buf, "\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 --git a/src/lxc_conf.h b/src/lxc_conf.h index b3fe86b36425e22b1c91fcf74cd46cbdcc779990..931f24f15b4a1dccdfa19ad1dbfcd2b885f1a9b8 100644 --- a/src/lxc_conf.h +++ b/src/lxc_conf.h @@ -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 --git a/src/lxc_container.c b/src/lxc_container.c index 36ab654928999696afaa1c2766766a4a1d78aa61..142ae7c3aa9d847d120c859d37d229a5d4454aaa 100644 --- a/src/lxc_container.c +++ b/src/lxc_container.c @@ -68,7 +68,7 @@ typedef char lxc_message_t; typedef struct __lxc_child_argv lxc_child_argv_t; struct __lxc_child_argv { - lxc_vm_def_t *config; + virDomainDefPtr config; unsigned int nveths; char **veths; int monitor; @@ -85,10 +85,10 @@ struct __lxc_child_argv { * * 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, }; @@ -269,8 +269,8 @@ static int lxcContainerChild( void *data ) { 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) { @@ -281,17 +281,20 @@ static int lxcContainerChild( void *data ) /* 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; } } @@ -329,7 +332,7 @@ static int lxcContainerChild( void *data ) * * Returns PID of container on success or -1 in case of error */ -int lxcContainerStart(lxc_vm_def_t *def, +int lxcContainerStart(virDomainDefPtr def, unsigned int nveths, char **veths, int control, diff --git a/src/lxc_container.h b/src/lxc_container.h index 1b492a69ede1f0736e5b6aeb5df81e2b6d97d611..5da3772f1eeef3207a6ce2e20f8b7ff9f45cf923 100644 --- a/src/lxc_container.h +++ b/src/lxc_container.h @@ -34,7 +34,7 @@ enum { int lxcContainerSendContinue(int control); -int lxcContainerStart(lxc_vm_def_t *def, +int lxcContainerStart(virDomainDefPtr def, unsigned int nveths, char **veths, int control, diff --git a/src/lxc_controller.c b/src/lxc_controller.c index b2c07182a8eb9161ca804e7c39e37e8707f9696b..9f67ce574d887cbc73e0f3e8aa76203217f2cc65 100644 --- a/src/lxc_controller.c +++ b/src/lxc_controller.c @@ -306,7 +306,7 @@ static int lxcControllerCleanupInterfaces(unsigned int nveths, static int lxcControllerRun(const char *stateDir, - lxc_vm_def_t *def, + virDomainDefPtr def, unsigned int nveths, char **veths, int monitor, @@ -368,7 +368,7 @@ cleanup: int lxcControllerStart(const char *stateDir, - lxc_vm_def_t *def, + virDomainDefPtr def, unsigned int nveths, char **veths, int monitor, diff --git a/src/lxc_controller.h b/src/lxc_controller.h index d390dc27613dfe97946a17ca885ce7d2424358c7..8bfb8c88a937da52abd76001cc534d3e5655d46a 100644 --- a/src/lxc_controller.h +++ b/src/lxc_controller.h @@ -29,7 +29,7 @@ #include "lxc_conf.h" int lxcControllerStart(const char *stateDir, - lxc_vm_def_t *def, + virDomainDefPtr def, unsigned int nveths, char **veths, int monitor, diff --git a/src/lxc_driver.c b/src/lxc_driver.c index 515bfd76d67ba1a079d59a9c2d2655afad04ecfb..629f51bcb5fa6afdf9fcb6230b714941eee499e4 100644 --- a/src/lxc_driver.c +++ b/src/lxc_driver.c @@ -37,7 +37,6 @@ #include #include -#include "internal.h" #include "lxc_conf.h" #include "lxc_container.h" #include "lxc_driver.h" @@ -111,7 +110,7 @@ static virDomainPtr lxcDomainLookupByID(virConnectPtr conn, 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) { @@ -131,7 +130,7 @@ static virDomainPtr lxcDomainLookupByUUID(virConnectPtr conn, 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) { @@ -151,7 +150,7 @@ static virDomainPtr lxcDomainLookupByName(virConnectPtr conn, 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) { @@ -167,90 +166,96 @@ static virDomainPtr lxcDomainLookupByName(virConnectPtr conn, 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; } @@ -265,7 +270,7 @@ static virDomainPtr lxcDomainDefine(virConnectPtr conn, const char *xml) 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, @@ -273,19 +278,18 @@ static int lxcDomainUndefine(virDomainPtr dom) 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; } @@ -294,7 +298,7 @@ static int lxcDomainGetInfo(virDomainPtr dom, 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, @@ -304,30 +308,38 @@ static int lxcDomainGetInfo(virDomainPtr dom, 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) +static char *lxcGetOSType(virDomainPtr dom) { - /* Linux containers only run on Linux */ - return strdup("linux"); + 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 strdup(vm->def->os.type); } static char *lxcDomainDumpXML(virDomainPtr dom, - int flags ATTRIBUTE_UNUSED) + int flags) { 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, @@ -335,7 +347,10 @@ static char *lxcDomainDumpXML(virDomainPtr dom, return NULL; } - return lxcGenerateXML(dom->conn, driver, vm, vm->def); + return virDomainDefFormat(dom->conn, + (flags & VIR_DOMAIN_XML_INACTIVE) && + vm->newDef ? vm->newDef : vm->def, + flags); } @@ -351,7 +366,7 @@ static char *lxcDomainDumpXML(virDomainPtr dom, */ static int lxcVMCleanup(virConnectPtr conn, lxc_driver_t *driver, - lxc_vm_t * vm) + virDomainObjPtr vm) { int rc = -1; int waitRc; @@ -383,8 +398,6 @@ static int lxcVMCleanup(virConnectPtr conn, vm->pid = -1; vm->def->id = -1; vm->monitor = -1; - driver->nactivevms--; - driver->ninactivevms++; return rc; } @@ -400,12 +413,12 @@ static int lxcVMCleanup(virConnectPtr conn, * Returns 0 on success or -1 in case of error */ static int lxcSetupInterfaces(virConnectPtr conn, - lxc_vm_def_t *def, + virDomainDefPtr def, unsigned 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] = ""; @@ -415,8 +428,11 @@ static int lxcSetupInterfaces(virConnectPtr conn, 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; } @@ -424,8 +440,11 @@ static int lxcSetupInterfaces(virConnectPtr conn, 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); @@ -436,8 +455,8 @@ static int lxcSetupInterfaces(virConnectPtr conn, } 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))) { @@ -445,15 +464,15 @@ static int lxcSetupInterfaces(virConnectPtr conn, _("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; @@ -485,7 +504,7 @@ error_exit: static int lxcMonitorServer(virConnectPtr conn, lxc_driver_t * driver, - lxc_vm_t *vm) + virDomainObjPtr vm) { char *sockpath = NULL; int fd; @@ -535,7 +554,7 @@ error: static int lxcMonitorClient(virConnectPtr conn, lxc_driver_t * driver, - lxc_vm_t *vm) + virDomainObjPtr vm) { char *sockpath = NULL; int fd; @@ -578,7 +597,7 @@ error: static int lxcVmTerminate(virConnectPtr conn, lxc_driver_t *driver, - lxc_vm_t *vm, + virDomainObjPtr vm, int signum) { if (signum == 0) @@ -603,7 +622,7 @@ static void lxcMonitorEvent(int fd, void *data) { lxc_driver_t *driver = data; - lxc_vm_t *vm = driver->vms; + virDomainObjPtr vm = driver->domains; while (vm) { if (vm->monitor == fd) @@ -632,12 +651,13 @@ static void lxcMonitorEvent(int fd, */ static int lxcVmStart(virConnectPtr conn, lxc_driver_t * driver, - lxc_vm_t * vm) + virDomainObjPtr vm) { int rc = -1; unsigned int i; int monitor; int parentTty; + char *parentTtyPath = NULL; char *logfile = NULL; int logfd = -1; unsigned int nveths = 0; @@ -660,13 +680,19 @@ static int lxcVmStart(virConnectPtr conn, 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)); goto cleanup; } + 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) goto cleanup; @@ -705,8 +731,6 @@ static int lxcVmStart(virConnectPtr conn, vm->def->id = vm->pid; vm->state = VIR_DOMAIN_RUNNING; - driver->ninactivevms--; - driver->nactivevms++; if (virEventAddHandle(vm->monitor, POLLERR | POLLHUP, @@ -751,7 +775,7 @@ static int lxcDomainStart(virDomainPtr dom) 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, @@ -759,6 +783,12 @@ static int lxcDomainStart(virDomainPtr dom) goto cleanup; } + if ((vm->def->nets != NULL) && !(driver->have_netns)) { + lxcError(conn, NULL, VIR_ERR_NO_SUPPORT, + _("System lacks NETNS support")); + goto cleanup; + } + rc = lxcVmStart(conn, driver, vm); cleanup: @@ -780,26 +810,28 @@ lxcDomainCreateAndStart(virConnectPtr conn, 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 = lxcAssignVMDef(conn, driver, def))) { - lxcFreeVMDef(def); + if ((def->nets != NULL) && !(driver->have_netns)) { + virDomainDefFree(def); + lxcError(conn, NULL, VIR_ERR_NO_SUPPORT, + _("System lacks NETNS support")); goto return_point; } - if (lxcSaveVMDef(conn, driver, vm, def) < 0) { - lxcRemoveInactiveVM(driver, vm); - return NULL; + + if (!(vm = virDomainAssignDef(conn, &driver->domains, def))) { + virDomainDefFree(def); + goto return_point; } if (lxcVmStart(conn, driver, vm) < 0) { - lxcRemoveInactiveVM(driver, vm); + virDomainRemoveInactive(&driver->domains, vm); goto return_point; } @@ -823,7 +855,7 @@ return_point: static int lxcDomainShutdown(virDomainPtr dom) { 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, @@ -846,7 +878,7 @@ static int lxcDomainShutdown(virDomainPtr dom) static int lxcDomainDestroy(virDomainPtr dom) { 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, @@ -875,7 +907,7 @@ static int lxcCheckNetNsSupport(void) static int lxcStartup(void) { uid_t uid = getuid(); - lxc_vm_t *vm; + virDomainObjPtr vm; /* Check that the user is root */ if (0 != uid) { @@ -898,13 +930,21 @@ static int lxcStartup(void) 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) { int rc; if ((vm->monitor = lxcMonitorClient(NULL, lxc_driver, vm)) < 0) { @@ -923,8 +963,6 @@ static int lxcStartup(void) if (vm->pid != 0) { vm->def->id = vm->pid; vm->state = VIR_DOMAIN_RUNNING; - lxc_driver->ninactivevms--; - lxc_driver->nactivevms++; } else { vm->def->id = -1; close(vm->monitor); @@ -940,6 +978,7 @@ static int lxcStartup(void) 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); @@ -947,10 +986,15 @@ static void lxcFreeDriver(lxc_driver_t *driver) 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; @@ -966,13 +1010,17 @@ static int lxcShutdown(void) */ 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;