From 60623a7ce01e4fb89bb10007d8f1e3e736a1b4b0 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Tue, 24 Mar 2009 10:59:13 +0000 Subject: [PATCH] Add support for a non-template filesystem root. (Florian Vichot) --- AUTHORS | 1 + ChangeLog | 5 ++ src/openvz_conf.c | 215 +++++++++++++++++++++++++++++++++++++------- src/openvz_conf.h | 6 +- src/openvz_driver.c | 119 ++++++++++++++++-------- 5 files changed, 272 insertions(+), 74 deletions(-) diff --git a/AUTHORS b/AUTHORS index 1c4f3b8668..16463d88f5 100644 --- a/AUTHORS +++ b/AUTHORS @@ -66,6 +66,7 @@ Patches have also been contributed by: Ryota Ozaki Pritesh Kothari Amit Shah + Florian Vichot [....send patches to get your name here....] diff --git a/ChangeLog b/ChangeLog index 1ee016d803..6f57180d06 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Tue Mar 24 10:51:22 GMT 2009 Daniel P. Berrange + + * src/openvz_conf.c, src/openvz_conf.h, src/openvz_driver.c: Add + support for a non-template filesystem root. (Florian Vichot) + Mon Mar 23 17:33:17 CET 2009 Daniel Veillard * src/virsh.c: fix missing authentication when command are issued diff --git a/src/openvz_conf.c b/src/openvz_conf.c index ff3d607fbd..c5f4a14587 100644 --- a/src/openvz_conf.c +++ b/src/openvz_conf.c @@ -192,7 +192,7 @@ openvzReadNetworkConf(virConnectPtr conn, * IP_ADDRESS="1.1.1.1 1.1.1.2" * splited IPs by space */ - ret = openvzReadConfigParam(veid, "IP_ADDRESS", temp, sizeof(temp)); + ret = openvzReadVPSConfigParam(veid, "IP_ADDRESS", temp, sizeof(temp)); if (ret < 0) { openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("Cound not read 'IP_ADDRESS' from config for container %d"), @@ -224,7 +224,7 @@ openvzReadNetworkConf(virConnectPtr conn, *NETIF="ifname=eth10,mac=00:18:51:C1:05:EE,host_ifname=veth105.10,host_mac=00:18:51:8F:D9:F3" *devices splited by ';' */ - ret = openvzReadConfigParam(veid, "NETIF", temp, sizeof(temp)); + ret = openvzReadVPSConfigParam(veid, "NETIF", temp, sizeof(temp)); if (ret < 0) { openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("Cound not read 'NETIF' from config for container %d"), @@ -314,15 +314,46 @@ error: } +/* utility function to replace 'from' by 'to' in 'str' */ +static char* +openvz_replace(const char* str, + const char* from, + const char* to) { + const char* offset = NULL; + const char* str_start = str; + int to_len = strlen(to); + int from_len = strlen(from); + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if(!from) + return NULL; + + while((offset = strstr(str_start, from))) + { + virBufferAdd(&buf, str_start, offset-str_start); + virBufferAdd(&buf, to, to_len); + str_start = offset + from_len; + } + + virBufferAdd(&buf, str_start, strlen(str_start)); + + if(virBufferError(&buf)) + return NULL; + + return virBufferContentAndReset(&buf); +} + + static int openvzReadFSConf(virConnectPtr conn, virDomainDefPtr def, int veid) { int ret; virDomainFSDefPtr fs = NULL; - char temp[4096]; + char* veid_str = NULL; + char temp[100]; - ret = openvzReadConfigParam(veid, "OSTEMPLATE", temp, sizeof(temp)); + ret = openvzReadVPSConfigParam(veid, "OSTEMPLATE", temp, sizeof(temp)); if (ret < 0) { openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("Cound not read 'OSTEMPLATE' from config for container %d"), @@ -334,18 +365,38 @@ openvzReadFSConf(virConnectPtr conn, fs->type = VIR_DOMAIN_FS_TYPE_TEMPLATE; fs->src = strdup(temp); - fs->dst = strdup("/"); + } else { + /* OSTEMPLATE was not found, VE was booted from a private dir directly */ + ret = openvzReadVPSConfigParam(veid, "VE_PRIVATE", temp, sizeof(temp)); + if (ret <= 0) { + openvzError(conn, VIR_ERR_INTERNAL_ERROR, + _("Cound not read 'VE_PRIVATE' from config for container %d"), + veid); + goto error; + } - if (fs->src == NULL || fs->dst == NULL) + if (VIR_ALLOC(fs) < 0) goto no_memory; - if (VIR_REALLOC_N(def->fss, def->nfss + 1) < 0) - goto no_memory; - def->fss[def->nfss++] = fs; - fs = NULL; + if(virAsprintf(&veid_str, "%d", veid) < 0) + goto error; + + fs->type = VIR_DOMAIN_FS_TYPE_MOUNT; + fs->src = openvz_replace(temp, "$VEID", veid_str); + VIR_FREE(veid_str); } + fs->dst = strdup("/"); + + if (fs->src == NULL || fs->dst == NULL) + goto no_memory; + + if (VIR_REALLOC_N(def->fss, def->nfss + 1) < 0) + goto no_memory; + def->fss[def->nfss++] = fs; + fs = NULL; + return 0; no_memory: virReportOOMError(conn); @@ -432,7 +483,7 @@ int openvzLoadDomains(struct openvz_driver *driver) { if (!(dom->def->os.init = strdup("/sbin/init"))) goto no_memory; - ret = openvzReadConfigParam(veid, "CPUS", temp, sizeof(temp)); + ret = openvzReadVPSConfigParam(veid, "CPUS", temp, sizeof(temp)); if (ret < 0) { openvzError(NULL, VIR_ERR_INTERNAL_ERROR, _("Cound not read config for container %d"), @@ -485,26 +536,23 @@ openvzGetNodeCPUs(void) return nodeinfo.cpus; } -int -openvzWriteConfigParam(int vpsid, const char *param, const char *value) +static int +openvzWriteConfigParam(const char * conf_file, const char *param, const char *value) { - char conf_file[PATH_MAX]; - char temp_file[PATH_MAX]; + char * temp_file = NULL; + int fd = -1, temp_fd = -1; char line[PATH_MAX] ; - int fd, temp_fd; - if (openvzLocateConfFile(vpsid, conf_file, PATH_MAX, "conf")<0) - return -1; - if (openvzLocateConfFile(vpsid, temp_file, PATH_MAX, "tmp")<0) + if (virAsprintf(&temp_file, "%s.tmp", conf_file)<0) return -1; fd = open(conf_file, O_RDONLY); if (fd == -1) - return -1; + goto error; temp_fd = open(temp_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (temp_fd == -1) { close(fd); - return -1; + goto error; } while(1) { @@ -541,30 +589,32 @@ error: close(fd); if (temp_fd != -1) close(temp_fd); - unlink(temp_file); + if(temp_file) + unlink(temp_file); + VIR_FREE(temp_file); return -1; } -/* -* Read parameter from container config -* sample: 133, "OSTEMPLATE", value, 1024 -* return: -1 - error -* 0 - don't found -* 1 - OK -*/ int -openvzReadConfigParam(int vpsid ,const char * param, char *value, int maxlen) +openvzWriteVPSConfigParam(int vpsid, const char *param, const char *value) +{ + char conf_file[PATH_MAX]; + + if (openvzLocateConfFile(vpsid, conf_file, PATH_MAX, "conf")<0) + return -1; + + return openvzWriteConfigParam(conf_file, param, value); +} + +static int +openvzReadConfigParam(const char * conf_file ,const char * param, char *value, int maxlen) { - char conf_file[PATH_MAX] ; char line[PATH_MAX] ; int ret, found = 0; int fd ; char * sf, * token; char *saveptr = NULL; - if (openvzLocateConfFile(vpsid, conf_file, PATH_MAX, "conf")<0) - return -1; - value[0] = 0; fd = open(conf_file, O_RDONLY); @@ -597,6 +647,103 @@ openvzReadConfigParam(int vpsid ,const char * param, char *value, int maxlen) return ret ; } +/* +* Read parameter from container config +* sample: 133, "OSTEMPLATE", value, 1024 +* return: -1 - error +* 0 - don't found +* 1 - OK +*/ +int +openvzReadVPSConfigParam(int vpsid ,const char * param, char *value, int maxlen) +{ + char conf_file[PATH_MAX] ; + + if (openvzLocateConfFile(vpsid, conf_file, PATH_MAX, "conf")<0) + return -1; + + return openvzReadConfigParam(conf_file, param, value, maxlen); +} + +static int +openvz_copyfile(char* from_path, char* to_path) +{ + char line[PATH_MAX]; + int fd, copy_fd; + int bytes_read; + + fd = open(from_path, O_RDONLY); + if (fd == -1) + return -1; + copy_fd = open(to_path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (copy_fd == -1) { + close(fd); + return -1; + } + + while(1) { + if (openvz_readline(fd, line, sizeof(line)) <= 0) + break; + + bytes_read = strlen(line); + if (safewrite(copy_fd, line, bytes_read) != bytes_read) + goto error; + } + + if (close(fd) < 0) + goto error; + fd = -1; + if (close(copy_fd) < 0) + goto error; + copy_fd = -1; + + return 0; + +error: + if (fd != -1) + close(fd); + if (copy_fd != -1) + close(copy_fd); + return -1; +} + +/* +* Copy the default config to the VE conf file +* return: -1 - error +* 0 - OK +*/ +int +openvzCopyDefaultConfig(int vpsid) +{ + char * confdir = NULL; + char * default_conf_file = NULL; + char configfile_value[PATH_MAX]; + char conf_file[PATH_MAX]; + int ret = -1; + + if(openvzReadConfigParam(VZ_CONF_FILE, "CONFIGFILE", configfile_value, PATH_MAX) < 0) + goto cleanup; + + confdir = openvzLocateConfDir(); + if (confdir == NULL) + goto cleanup; + + if (virAsprintf(&default_conf_file, "%s/ve-%s.conf-sample", confdir, configfile_value) < 0) + goto cleanup; + + if (openvzLocateConfFile(vpsid, conf_file, PATH_MAX, "conf")<0) + goto cleanup; + + if (openvz_copyfile(default_conf_file, conf_file)<0) + goto cleanup; + + ret = 0; +cleanup: + VIR_FREE(confdir); + VIR_FREE(default_conf_file); + return ret; +} + /* Locate config file of container * return -1 - error * 0 - OK diff --git a/src/openvz_conf.h b/src/openvz_conf.h index 8e02056fd8..00e18b4325 100644 --- a/src/openvz_conf.h +++ b/src/openvz_conf.h @@ -42,6 +42,7 @@ enum { OPENVZ_WARN, OPENVZ_ERR }; /* OpenVZ commands - Replace with wrapper scripts later? */ #define VZLIST "/usr/sbin/vzlist" #define VZCTL "/usr/sbin/vzctl" +#define VZ_CONF_FILE "/etc/vz/vz.conf" #define VZCTL_BRIDGE_MIN_VERSION ((3 * 1000 * 1000) + (0 * 1000) + 22 + 1) @@ -56,8 +57,9 @@ struct openvz_driver { int openvz_readline(int fd, char *ptr, int maxlen); int openvzExtractVersion(virConnectPtr conn, struct openvz_driver *driver); -int openvzReadConfigParam(int vpsid ,const char * param, char *value, int maxlen); -int openvzWriteConfigParam(int vpsid, const char *param, const char *value); +int openvzReadVPSConfigParam(int vpsid ,const char * param, char *value, int maxlen); +int openvzWriteVPSConfigParam(int vpsid, const char *param, const char *value); +int openvzCopyDefaultConfig(int vpsid); virCapsPtr openvzCapsInit(void); int openvzLoadDomains(struct openvz_driver *driver); void openvzFreeDriver(struct openvz_driver *driver); diff --git a/src/openvz_driver.c b/src/openvz_driver.c index d6c4362dc0..ac2c089813 100644 --- a/src/openvz_driver.c +++ b/src/openvz_driver.c @@ -132,19 +132,9 @@ static int openvzDomainDefineCmd(virConnectPtr conn, ADD_ARG_LIT("create"); ADD_ARG_LIT(vmdef->name); - if (vmdef->nfss) { - if (vmdef->fss[0]->type != VIR_DOMAIN_FS_TYPE_TEMPLATE) { - openvzError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("only filesystem templates are supported")); - return -1; - } - - if (vmdef->nfss > 1) { - openvzError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("only one filesystem supported")); - return -1; - } - + if (vmdef->nfss == 1 && + vmdef->fss[0]->type == VIR_DOMAIN_FS_TYPE_TEMPLATE) + { ADD_ARG_LIT("--ostemplate"); ADD_ARG_LIT(vmdef->fss[0]->src); } @@ -166,6 +156,77 @@ static int openvzDomainDefineCmd(virConnectPtr conn, } +static int openvzSetInitialConfig(virConnectPtr conn, + virDomainDefPtr vmdef) +{ + int ret = -1; + int vpsid; + char * confdir = NULL; + const char *prog[OPENVZ_MAX_ARG]; + prog[0] = NULL; + + if (vmdef->nfss > 1) { + openvzError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("only one filesystem supported")); + goto cleanup; + } + + if (vmdef->nfss == 1 && + vmdef->fss[0]->type != VIR_DOMAIN_FS_TYPE_TEMPLATE && + vmdef->fss[0]->type != VIR_DOMAIN_FS_TYPE_MOUNT) + { + openvzError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("filesystem is not of type 'template' or 'mount'")); + goto cleanup; + } + + + if (vmdef->nfss == 1 && + vmdef->fss[0]->type == VIR_DOMAIN_FS_TYPE_MOUNT) + { + + if(virStrToLong_i(vmdef->name, NULL, 10, &vpsid) < 0) { + openvzError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("Could not convert domain name to VEID")); + goto cleanup; + } + + if (openvzCopyDefaultConfig(vpsid) < 0) { + openvzError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("Could not copy default config")); + goto cleanup; + } + + if (openvzWriteVPSConfigParam(vpsid, "VE_PRIVATE", vmdef->fss[0]->src) < 0) { + openvzError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("Could not set the source dir for the filesystem")); + goto cleanup; + } + } + else + { + if (openvzDomainDefineCmd(conn, prog, OPENVZ_MAX_ARG, vmdef) < 0) { + openvzError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("Error creating command for container")); + goto cleanup; + } + + if (virRun(conn, prog, NULL) < 0) { + openvzError(conn, VIR_ERR_INTERNAL_ERROR, + _("Could not exec %s"), VZCTL); + goto cleanup; + } + } + + ret = 0; + +cleanup: + VIR_FREE(confdir); + cmdExecFree(prog); + return ret; +} + + static virDomainPtr openvzDomainLookupByID(virConnectPtr conn, int id) { struct openvz_driver *driver = conn->privateData; @@ -447,7 +508,7 @@ openvzGenerateContainerVethName(int veid) char temp[1024]; /* try to get line "^NETIF=..." from config */ - if ( (ret = openvzReadConfigParam(veid, "NETIF", temp, sizeof(temp))) <= 0) { + if ( (ret = openvzReadVPSConfigParam(veid, "NETIF", temp, sizeof(temp))) <= 0) { snprintf(temp, sizeof(temp), "eth0"); } else { char *saveptr; @@ -630,7 +691,7 @@ openvzDomainSetNetworkConfig(virConnectPtr conn, if (driver->version < VZCTL_BRIDGE_MIN_VERSION && def->nnets) { param = virBufferContentAndReset(&buf); if (param) { - if (openvzWriteConfigParam(strtoI(def->name), "NETIF", param) < 0) { + if (openvzWriteVPSConfigParam(strtoI(def->name), "NETIF", param) < 0) { VIR_FREE(param); openvzError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot replace NETIF config")); @@ -656,8 +717,6 @@ openvzDomainDefineXML(virConnectPtr conn, const char *xml) virDomainDefPtr vmdef = NULL; virDomainObjPtr vm = NULL; virDomainPtr dom = NULL; - const char *prog[OPENVZ_MAX_ARG]; - prog[0] = NULL; openvzDriverLock(driver); if ((vmdef = virDomainDefParseString(conn, driver->caps, xml, @@ -680,20 +739,14 @@ openvzDomainDefineXML(virConnectPtr conn, const char *xml) goto cleanup; vmdef = NULL; - if (openvzDomainDefineCmd(conn, prog, OPENVZ_MAX_ARG, vm->def) < 0) { + if (openvzSetInitialConfig(conn, vm->def) < 0) { openvzError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("Error creating command for container")); + "%s", _("Error creating intial configuration")); goto cleanup; } //TODO: set quota - if (virRun(conn, prog, NULL) < 0) { - openvzError(conn, VIR_ERR_INTERNAL_ERROR, - _("Could not exec %s"), VZCTL); - goto cleanup; - } - if (openvzSetDefinedUUID(strtoI(vm->def->name), vm->def->uuid) < 0) { openvzError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("Could not set UUID")); @@ -717,7 +770,6 @@ openvzDomainDefineXML(virConnectPtr conn, const char *xml) cleanup: virDomainDefFree(vmdef); - cmdExecFree(prog); if (vm) virDomainObjUnlock(vm); openvzDriverUnlock(driver); @@ -733,8 +785,6 @@ openvzDomainCreateXML(virConnectPtr conn, const char *xml, virDomainObjPtr vm = NULL; virDomainPtr dom = NULL; const char *progstart[] = {VZCTL, "--quiet", "start", PROGRAM_SENTINAL, NULL}; - const char *progcreate[OPENVZ_MAX_ARG]; - progcreate[0] = NULL; openvzDriverLock(driver); if ((vmdef = virDomainDefParseString(conn, driver->caps, xml, @@ -756,15 +806,9 @@ openvzDomainCreateXML(virConnectPtr conn, const char *xml, goto cleanup; vmdef = NULL; - if (openvzDomainDefineCmd(conn, progcreate, OPENVZ_MAX_ARG, vm->def) < 0) { - openvzError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("Error creating command for container")); - goto cleanup; - } - - if (virRun(conn, progcreate, NULL) < 0) { + if (openvzSetInitialConfig(conn, vm->def) < 0) { openvzError(conn, VIR_ERR_INTERNAL_ERROR, - _("Could not exec %s"), VZCTL); + "%s", _("Error creating intial configuration")); goto cleanup; } @@ -803,7 +847,6 @@ openvzDomainCreateXML(virConnectPtr conn, const char *xml, cleanup: virDomainDefFree(vmdef); - cmdExecFree(progcreate); if (vm) virDomainObjUnlock(vm); openvzDriverUnlock(driver); @@ -940,7 +983,7 @@ openvzDomainGetAutostart(virDomainPtr dom, int *autostart) goto cleanup; } - if (openvzReadConfigParam(strtoI(vm->def->name), "ONBOOT", value, sizeof(value)) < 0) { + if (openvzReadVPSConfigParam(strtoI(vm->def->name), "ONBOOT", value, sizeof(value)) < 0) { openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("Could not read container config")); goto cleanup; -- GitLab