linux countainers cleanup patches

* src/lxc_conf.c src/lxc_conf.h: cleanup patch for the conf driver
  of linux countainers, reuse XPath helpers, make string fields dynamic
  and remove a memory leak.
* src/lxc_driver.c: avoid some problems when the config directory is
  not accessible and for regression tests
Daniel
This commit is contained in:
Daniel Veillard 2008-03-31 12:02:12 +00:00
parent 038b434f14
commit 497f252015
4 changed files with 100 additions and 130 deletions

View File

@ -1,3 +1,11 @@
Mon Mar 31 13:58:25 CEST 2008 Daniel Veillard <veillard@redhat.com>
* src/lxc_conf.c src/lxc_conf.h: cleanup patch for the conf driver
of linux countainers, reuse XPath helpers, make string fields dynamic
and remove a memory leak.
* src/lxc_driver.c: avoid some problems when the config directory is
not accessible and for regression tests
Fri Mar 28 16:34:56 EDT 2008 Daniel P. Berrange <berrange@redhat.com> Fri Mar 28 16:34:56 EDT 2008 Daniel P. Berrange <berrange@redhat.com>
* src/network.rng: Add new routed networking schema * src/network.rng: Add new routed networking schema

View File

@ -41,6 +41,7 @@
#include "buf.h" #include "buf.h"
#include "util.h" #include "util.h"
#include "uuid.h" #include "uuid.h"
#include "xml.h"
#include "lxc_conf.h" #include "lxc_conf.h"
@ -70,18 +71,6 @@ void lxcError(virConnectPtr conn, virDomainPtr dom, int code,
codeErrorMessage, errorMessage); codeErrorMessage, errorMessage);
} }
static inline int lxcIsEmptyXPathStringObj(xmlXPathObjectPtr xpathObj)
{
if ((xpathObj == NULL) ||
(xpathObj->type != XPATH_STRING) ||
(xpathObj->stringval == NULL) ||
(xpathObj->stringval[0] == 0)) {
return 1;
} else {
return 0;
}
}
static int lxcParseMountXML(virConnectPtr conn, xmlNodePtr nodePtr, static int lxcParseMountXML(virConnectPtr conn, xmlNodePtr nodePtr,
lxc_mount_t *lxcMount) lxc_mount_t *lxcMount)
{ {
@ -92,7 +81,8 @@ static int lxcParseMountXML(virConnectPtr conn, xmlNodePtr nodePtr,
int strLen; int strLen;
int rc = -1; int rc = -1;
if (NULL == (fsType = xmlGetProp(nodePtr, BAD_CAST "type"))) { fsType = xmlGetProp(nodePtr, BAD_CAST "type");
if (NULL == fsType) {
lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR,
_("missing filesystem type")); _("missing filesystem type"));
goto error; goto error;
@ -155,6 +145,7 @@ static int lxcParseMountXML(virConnectPtr conn, xmlNodePtr nodePtr,
rc = 0; rc = 0;
error: error:
xmlFree(fsType);
xmlFree(mountSource); xmlFree(mountSource);
xmlFree(mountTarget); xmlFree(mountTarget);
@ -164,55 +155,40 @@ error:
static int lxcParseDomainName(virConnectPtr conn, char **name, static int lxcParseDomainName(virConnectPtr conn, char **name,
xmlXPathContextPtr contextPtr) xmlXPathContextPtr contextPtr)
{ {
int rc = -1; char *res;
xmlXPathObjectPtr xpathObj = NULL;
xpathObj = xmlXPathEval(BAD_CAST "string(/domain/name[1])", contextPtr); res = virXPathString("string(/domain/name[1])", contextPtr);
if (lxcIsEmptyXPathStringObj(xpathObj)) { if (res == NULL) {
lxcError(conn, NULL, VIR_ERR_NO_NAME, NULL); lxcError(conn, NULL, VIR_ERR_NO_NAME, NULL);
goto parse_complete; return(-1);
} }
*name = strdup((const char *)xpathObj->stringval); *name = res;
if (NULL == *name) { return(0);
lxcError(conn, NULL, VIR_ERR_NO_MEMORY, NULL);
goto parse_complete;
}
rc = 0;
parse_complete:
xmlXPathFreeObject(xpathObj);
return rc;
} }
static int lxcParseDomainUUID(virConnectPtr conn, unsigned char *uuid, static int lxcParseDomainUUID(virConnectPtr conn, unsigned char *uuid,
xmlXPathContextPtr contextPtr) xmlXPathContextPtr contextPtr)
{ {
int rc = -1; char *res;
xmlXPathObjectPtr xpathObj = NULL;
xpathObj = xmlXPathEval(BAD_CAST "string(/domain/uuid[1])", contextPtr); res = virXPathString("string(/domain/uuid[1])", contextPtr);
if (lxcIsEmptyXPathStringObj(xpathObj)) { if (res == NULL) {
if ((rc = virUUIDGenerate(uuid))) { if (virUUIDGenerate(uuid)) {
lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR,
_("failed to generate uuid: %s"), strerror(rc)); _("failed to generate uuid"));
goto parse_complete; return(-1);
} }
} else { } else {
if (virUUIDParse((const char *)xpathObj->stringval, uuid) < 0) { if (virUUIDParse(res, uuid) < 0) {
lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR,
_("invalid uuid element")); _("invalid uuid element"));
goto parse_complete; free(res);
return(-1);
} }
free(res);
} }
return(0);
rc = 0;
parse_complete:
xmlXPathFreeObject(xpathObj);
return rc;
} }
static int lxcParseDomainMounts(virConnectPtr conn, static int lxcParseDomainMounts(virConnectPtr conn,
@ -220,27 +196,23 @@ static int lxcParseDomainMounts(virConnectPtr conn,
xmlXPathContextPtr contextPtr) xmlXPathContextPtr contextPtr)
{ {
int rc = -1; int rc = -1;
xmlXPathObjectPtr xpathObj = NULL;
int i; int i;
lxc_mount_t *mountObj; lxc_mount_t *mountObj;
lxc_mount_t *prevObj = NULL; lxc_mount_t *prevObj = NULL;
int nmounts = 0; int nmounts = 0;
xmlNodePtr *list;
int res;
xpathObj = xmlXPathEval(BAD_CAST "/domain/devices/filesystem", res = virXPathNodeSet("/domain/devices/filesystem", contextPtr, &list);
contextPtr); if (res > 0) {
if ((xpathObj != NULL) && for (i = 0; i < res; ++i) {
(xpathObj->type == XPATH_NODESET) &&
(xpathObj->nodesetval != NULL) &&
(xpathObj->nodesetval->nodeNr >= 0)) {
for (i = 0; i < xpathObj->nodesetval->nodeNr; ++i) {
mountObj = calloc(1, sizeof(lxc_mount_t)); mountObj = calloc(1, sizeof(lxc_mount_t));
if (NULL == mountObj) { if (NULL == mountObj) {
lxcError(conn, NULL, VIR_ERR_NO_MEMORY, "mount"); lxcError(conn, NULL, VIR_ERR_NO_MEMORY, "mount");
goto parse_complete; goto parse_complete;
} }
rc = lxcParseMountXML(conn, xpathObj->nodesetval->nodeTab[i], rc = lxcParseMountXML(conn, list[i], mountObj);
mountObj);
if (0 > rc) { if (0 > rc) {
free(mountObj); free(mountObj);
goto parse_complete; goto parse_complete;
@ -256,101 +228,76 @@ static int lxcParseDomainMounts(virConnectPtr conn,
} }
prevObj = mountObj; prevObj = mountObj;
} }
free(list);
} }
rc = nmounts; rc = nmounts;
parse_complete: parse_complete:
xmlXPathFreeObject(xpathObj);
return rc; return rc;
} }
static int lxcParseDomainInit(virConnectPtr conn, char* init, xmlXPathContextPtr contextPtr) static int lxcParseDomainInit(virConnectPtr conn, char** init,
xmlXPathContextPtr contextPtr)
{ {
int rc = -1; char *res;
xmlXPathObjectPtr xpathObj = NULL;
xpathObj = xmlXPathEval(BAD_CAST "string(/domain/os/init[1])", res = virXPathString("string(/domain/os/init[1])", contextPtr);
contextPtr); if (res == NULL) {
if (lxcIsEmptyXPathStringObj(xpathObj)) {
lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR,
_("invalid or missing init element")); _("invalid or missing init element"));
goto parse_complete; return(-1);
} }
if (strlen((const char*)xpathObj->stringval) >= PATH_MAX - 1) { if (strlen(res) >= PATH_MAX - 1) {
lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR,
_("init string too long")); _("init string too long"));
goto parse_complete; free(res);
return(-1);
} }
strcpy(init, (const char *)xpathObj->stringval); *init = res;
rc = 0; return(0);
parse_complete:
xmlXPathFreeObject(xpathObj);
return rc;
} }
static int lxcParseDomainTty(virConnectPtr conn, char *tty, xmlXPathContextPtr contextPtr) static int lxcParseDomainTty(virConnectPtr conn, char **tty, xmlXPathContextPtr contextPtr)
{ {
int rc = -1; char *res;
xmlXPathObjectPtr xpathObj = NULL;
xpathObj = xmlXPathEval(BAD_CAST "string(/domain/devices/console[1]/@tty)", res = virXPathString("string(/domain/devices/console[1]/@tty)", contextPtr);
contextPtr); if (res == NULL) {
if (lxcIsEmptyXPathStringObj(xpathObj)) {
/* make sure the tty string is empty */ /* make sure the tty string is empty */
tty[0] = 0x00; *tty = strdup("");
if (*tty == NULL) {
lxcError(conn, NULL, VIR_ERR_NO_MEMORY, NULL);
return(-1);
}
} else { } else {
/* check the source string length */ *tty = res;
if (strlen((const char*)xpathObj->stringval) >= LXC_MAX_TTY_NAME - 1) {
lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR,
_("tty name is too long"));
goto parse_complete;
}
strcpy(tty, (const char *)xpathObj->stringval);
} }
rc = 0; return(0);
parse_complete:
xmlXPathFreeObject(xpathObj);
return rc;
} }
static int lxcParseDomainMemory(virConnectPtr conn, int* memory, xmlXPathContextPtr contextPtr) static int lxcParseDomainMemory(virConnectPtr conn, int* memory, xmlXPathContextPtr contextPtr)
{ {
int rc = -1; long res;
xmlXPathObjectPtr xpathObj = NULL; int rc;
char *endChar = NULL;
xpathObj = xmlXPathEval(BAD_CAST "string(/domain/memory[1])", contextPtr); rc = virXPathLong("string(/domain/memory[1])", contextPtr, &res);
if (lxcIsEmptyXPathStringObj(xpathObj)) { 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 */ /* not an error, default to an invalid value so it's not used */
*memory = -1; *memory = -1;
} else { } else {
*memory = strtoll((const char*)xpathObj->stringval, *memory = (int) res;
&endChar, 10);
if ((endChar == (const char*)xpathObj->stringval) ||
(*endChar != '\0')) {
lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR,
_("invalid memory value"));
goto parse_complete;
} }
} return(0);
rc = 0;
parse_complete:
xmlXPathFreeObject(xpathObj);
return rc;
} }
static lxc_vm_def_t * lxcParseXML(virConnectPtr conn, xmlDocPtr docPtr) static lxc_vm_def_t * lxcParseXML(virConnectPtr conn, xmlDocPtr docPtr)
@ -411,7 +358,7 @@ static lxc_vm_def_t * lxcParseXML(virConnectPtr conn, xmlDocPtr docPtr)
goto error; goto error;
} }
if (lxcParseDomainInit(conn, containerDef->init, contextPtr) < 0) { if (lxcParseDomainInit(conn, &(containerDef->init), contextPtr) < 0) {
goto error; goto error;
} }
@ -425,7 +372,7 @@ static lxc_vm_def_t * lxcParseXML(virConnectPtr conn, xmlDocPtr docPtr)
goto error; goto error;
} }
if (lxcParseDomainTty(conn, containerDef->tty, contextPtr) < 0) { if (lxcParseDomainTty(conn, &(containerDef->tty), contextPtr) < 0) {
goto error; goto error;
} }
@ -708,7 +655,8 @@ int lxcLoadContainerInfo(lxc_driver_t *driver)
rc = 0; rc = 0;
} else { } else {
lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("failed to open config directory: %s"), strerror(errno)); _("failed to open config directory %s: %s"),
driver->configDir, strerror(errno));
} }
goto load_complete; goto load_complete;
@ -837,9 +785,13 @@ no_memory:
void lxcFreeVMDef(lxc_vm_def_t *vmdef) void lxcFreeVMDef(lxc_vm_def_t *vmdef)
{ {
lxc_mount_t *curMount = vmdef->mounts; lxc_mount_t *curMount;
lxc_mount_t *nextMount; lxc_mount_t *nextMount;
if (vmdef == NULL)
return;
curMount = vmdef->mounts;
while (curMount) { while (curMount) {
nextMount = curMount->next; nextMount = curMount->next;
free(curMount); free(curMount);
@ -847,8 +799,9 @@ void lxcFreeVMDef(lxc_vm_def_t *vmdef)
} }
free(vmdef->name); free(vmdef->name);
vmdef->name = NULL; free(vmdef->init);
free(vmdef->tty);
free(vmdef);
} }
void lxcFreeVMs(lxc_vm_t *vms) void lxcFreeVMs(lxc_vm_t *vms)
@ -859,7 +812,6 @@ void lxcFreeVMs(lxc_vm_t *vms)
while (curVm) { while (curVm) {
lxcFreeVM(curVm); lxcFreeVM(curVm);
nextVm = curVm->next; nextVm = curVm->next;
free(curVm);
curVm = nextVm; curVm = nextVm;
} }
} }
@ -867,7 +819,7 @@ void lxcFreeVMs(lxc_vm_t *vms)
void lxcFreeVM(lxc_vm_t *vm) void lxcFreeVM(lxc_vm_t *vm)
{ {
lxcFreeVMDef(vm->def); lxcFreeVMDef(vm->def);
free(vm->def); free(vm);
} }
lxc_vm_t *lxcFindVMByID(const lxc_driver_t *driver, int id) lxc_vm_t *lxcFindVMByID(const lxc_driver_t *driver, int id)

View File

@ -51,7 +51,7 @@ struct __lxc_vm_def {
int id; int id;
/* init command string */ /* init command string */
char init[PATH_MAX]; char *init;
int maxMemory; int maxMemory;
@ -60,7 +60,7 @@ struct __lxc_vm_def {
lxc_mount_t *mounts; lxc_mount_t *mounts;
/* tty device */ /* tty device */
char tty[LXC_MAX_TTY_NAME]; char *tty;
}; };
typedef struct __lxc_vm lxc_vm_t; typedef struct __lxc_vm lxc_vm_t;

View File

@ -61,7 +61,7 @@
static int lxcStartup(void); static int lxcStartup(void);
static int lxcShutdown(void); static int lxcShutdown(void);
static lxc_driver_t *lxc_driver; static lxc_driver_t *lxc_driver = NULL;
/* Functions */ /* Functions */
static int lxcDummyChild( void *argv ATTRIBUTE_UNUSED ) static int lxcDummyChild( void *argv ATTRIBUTE_UNUSED )
@ -378,6 +378,13 @@ static char *lxcDomainDumpXML(virDomainPtr dom,
static int lxcStartup(void) static int lxcStartup(void)
{ {
uid_t uid = getuid();
/* Check that the user is root */
if (0 != uid) {
return -1;
}
lxc_driver = calloc(1, sizeof(lxc_driver_t)); lxc_driver = calloc(1, sizeof(lxc_driver_t));
if (NULL == lxc_driver) { if (NULL == lxc_driver) {
return -1; return -1;
@ -412,11 +419,12 @@ static void lxcFreeDriver(lxc_driver_t *driver)
static int lxcShutdown(void) static int lxcShutdown(void)
{ {
lxc_vm_t *vms = lxc_driver->vms; if (lxc_driver == NULL)
return(NULL);
lxcFreeVMs(vms); lxcFreeVMs(lxc_driver->vms);
lxc_driver->vms = NULL; lxc_driver->vms = NULL;
lxcFreeDriver(lxc_driver); lxcFreeDriver(lxc_driver);
lxc_driver = NULL;
return 0; return 0;
} }
@ -430,6 +438,8 @@ static int lxcShutdown(void)
*/ */
static int static int
lxcActive(void) { lxcActive(void) {
if (lxc_driver == NULL)
return(0);
/* If we've any active networks or guests, then we /* If we've any active networks or guests, then we
* mark this driver as active * mark this driver as active
*/ */