Patch switch OpenVZ XML format to generic. main changes: - I used generic virDomainNetDef to define network in container. And wrote function to apply virDomainNetDef for container. Method virDomainNetDefParseXML is public now. - tag "container" is changed to "devices" - changed format of tag "filesystem" - added processing "vcpu" tag.
Index: src/domain_conf.c =================================================================== RCS file: /data/cvs/libvirt/src/domain_conf.c,v retrieving revision 1.5 diff -u -p -r1.5 domain_conf.c --- src/domain_conf.c 19 Jul 2008 07:42:34 -0000 1.5 +++ src/domain_conf.c 25 Jul 2008 12:40:17 -0000 @@ -633,7 +633,7 @@ static void virDomainNetRandomMAC(virDom * @param node XML nodeset to parse for net definition * @return 0 on success, -1 on failure */ -static virDomainNetDefPtr +virDomainNetDefPtr virDomainNetDefParseXML(virConnectPtr conn, xmlNodePtr node) { virDomainNetDefPtr def; Index: src/domain_conf.h =================================================================== RCS file: /data/cvs/libvirt/src/domain_conf.h,v retrieving revision 1.1 diff -u -p -r1.1 domain_conf.h --- src/domain_conf.h 11 Jul 2008 16:23:36 -0000 1.1 +++ src/domain_conf.h 25 Jul 2008 12:40:17 -0000 @@ -472,6 +472,9 @@ int virDomainLoadAllConfigs(virConnectPt int virDomainDeleteConfig(virConnectPtr conn, virDomainObjPtr dom); +virDomainNetDefPtr virDomainNetDefParseXML(virConnectPtr conn, + xmlNodePtr node); + VIR_ENUM_DECL(virDomainVirt) VIR_ENUM_DECL(virDomainBoot) VIR_ENUM_DECL(virDomainFeature) Index: src/openvz_conf.c =================================================================== RCS file: /data/cvs/libvirt/src/openvz_conf.c,v retrieving revision 1.30 diff -u -p -r1.30 openvz_conf.c --- src/openvz_conf.c 21 Jul 2008 13:34:19 -0000 1.30 +++ src/openvz_conf.c 25 Jul 2008 12:40:17 -0000 @@ -56,6 +56,8 @@ #include "buf.h" #include "memory.h" #include "util.h" +#include "xml.h" +#include "domain_conf.h" static char *openvzLocateConfDir(void); static struct openvz_vm_def *openvzParseXML(virConnectPtr conn, xmlDocPtr xml); @@ -136,6 +138,34 @@ strtoI(const char *str) return val; } +/* function checks MAC address is empty + return 0 - empty + 1 - not +*/ +int openvzCheckEmptyMac(const unsigned char *mac) +{ + int i; + for (i = 0; i < VIR_DOMAIN_NET_MAC_SIZE; i++) + if (mac[i] != 0x00) + return 1; + + return 0; +} + +/* convert mac address to string + return pointer to string or NULL +*/ +char *openvzMacToString(const unsigned char *mac) +{ + char str[20]; + if (snprintf(str, 18, "%02X:%02X:%02X:%02X:%02X:%02X", + mac[0], mac[1], mac[2], + mac[3], mac[4], mac[5]) >= 18) + return NULL; + + return strdup(str); +} + void openvzRemoveInactiveVM(struct openvz_driver *driver, struct openvz_vm *vm) { @@ -148,30 +178,7 @@ void openvzFreeVMDef(struct openvz_vm_def *def) { if (def) { - struct ovz_quota *quota = def->fs.quota; - struct ovz_ip *ip = def->net.ips; - struct ovz_ns *ns = def->net.ns; - - while (quota) { - struct ovz_quota *prev = quota; - - quota = quota->next; - VIR_FREE(prev); - } - while (ip) { - struct ovz_ip *prev = ip; - - ip = ip->next; - VIR_FREE(prev); - } - while (ns) { - struct ovz_ns *prev = ns; - - ns = ns->next; - VIR_FREE(prev); - } - - VIR_FREE(def); + virDomainNetDefFree(def->net); } } @@ -285,6 +292,74 @@ struct openvz_vm_def return def; } +/* Parse filesystem section +Sample: +<filesystem type="template"> + <source name="fedora-core-5-i386"/> + <quota type="size" max="10000"/> + <quota type="inodes" max="100"/> +</filesystem> +*/ +static int openvzParseDomainFS(virConnectPtr conn, + struct openvz_fs_def *fs, + xmlXPathContextPtr ctxt) +{ + xmlNodePtr cur, obj; + char *type; + + obj = virXPathNode("/domain/devices/filesystem[1]", ctxt); + if (obj == NULL) { + openvzError(conn, VIR_ERR_INTERNAL_ERROR, + _("missing filesystem tag")); + return -1; + } + + /*check template type*/ + type = virXMLPropString(obj, "type"); + if (!type) { + openvzError(conn, VIR_ERR_INTERNAL_ERROR, + _("missing type attribute")); + return -1; + } + + if (STRNEQ(type, "template")) { + openvzError(conn, VIR_ERR_INTERNAL_ERROR, + _("Unknown type attribute %s"), type); + return -1; + } + VIR_FREE(type); + + cur = obj->children; + while(cur != NULL) + { + if (cur->type == XML_ELEMENT_NODE) { + if (xmlStrEqual(cur->name, BAD_CAST "source")) { + char * name = virXMLPropString(cur, "name"); + + if (name != NULL) { + strncpy(fs->tmpl, name,sizeof(fs->tmpl)); + fs->tmpl[sizeof(fs->tmpl) - 1] = '\0'; + } + VIR_FREE(name); + } else if (xmlStrEqual(cur->name, BAD_CAST "quota")) { + char * qtype = virXMLPropString(cur, "type"); + char * max = virXMLPropString(cur, "max"); + + if (qtype != NULL && STREQ(qtype, "size") && max != NULL) + fs->disksize = strtoI(max); + else if (qtype != NULL && STREQ(qtype, "inodes") && max != NULL) + fs->diskinodes = strtoI(max); + VIR_FREE(qtype); + VIR_FREE(max); + } + } + cur = cur->next; + } + + return 0; +} + + /* * Parses a libvirt XML definition of a guest, and populates the * the openvz_vm struct with matching data about the guests config @@ -293,12 +368,12 @@ static struct openvz_vm_def *openvzParseXML(virConnectPtr conn, xmlDocPtr xml) { xmlNodePtr root = NULL; - xmlChar *prop = NULL; + char *prop = NULL; xmlXPathContextPtr ctxt = NULL; xmlXPathObjectPtr obj = NULL; struct openvz_vm_def *def; - struct ovz_ip *ovzIp; - struct ovz_ns *ovzNs; + xmlNodePtr *nodes = NULL; + int i, n; if (VIR_ALLOC(def) < 0) { openvzError(conn, VIR_ERR_NO_MEMORY, _("xmlXPathContext")); @@ -306,7 +381,6 @@ static struct openvz_vm_def } /* Prepare parser / xpath context */ - root = xmlDocGetRootElement(xml); if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "domain"))) { openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("incorrect root element")); @@ -320,12 +394,12 @@ static struct openvz_vm_def } /* Find out what type of OPENVZ virtualization to use */ - if (!(prop = xmlGetProp(root, BAD_CAST "type"))) { + if (!(prop = virXMLPropString(root, "type"))) { openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("missing domain type attribute")); goto bail_out; } - if (STRNEQ((char *)prop, "openvz")){ + if (STRNEQ(prop, "openvz")){ openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("invalid domain type attribute")); goto bail_out; } @@ -349,140 +423,54 @@ static struct openvz_vm_def xmlXPathFreeObject(obj); /* Extract domain uuid */ - obj = xmlXPathEval(BAD_CAST "string(/domain/uuid[1])", ctxt); - if ((obj == NULL) || (obj->type != XPATH_STRING) || - (obj->stringval == NULL) || (obj->stringval[0] == 0)) { + prop = virXPathString("string(./uuid[1])", ctxt); + if (!prop) { int err; - if ((err = virUUIDGenerate(def->uuid))) { - openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("Failed to generate UUID")); + openvzError(conn, VIR_ERR_INTERNAL_ERROR, + _("Failed to generate UUID: %s"), + strerror(err)); goto bail_out; } - } else if (virUUIDParse((const char *)obj->stringval, def->uuid) < 0) { - openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("malformed uuid element")); - goto bail_out; - } - xmlXPathFreeObject(obj); - - /* Extract filesystem info */ - obj = xmlXPathEval(BAD_CAST "string(/domain/container/filesystem/template[1])", ctxt); - if ((obj == NULL) || (obj->type != XPATH_STRING) || (obj->stringval == NULL) - || (obj->stringval[0] == 0)) { - openvzError(conn, VIR_ERR_OS_TYPE, NULL); - goto bail_out; + } else { + if (virUUIDParse(prop, def->uuid) < 0) { + openvzError(conn, VIR_ERR_INTERNAL_ERROR, + _("malformed uuid element")); + goto bail_out; + } + VIR_FREE(prop); } - strncpy(def->fs.tmpl, (const char *) obj->stringval, OPENVZ_TMPL_MAX); - xmlXPathFreeObject(obj); - /* TODO Add quota processing here */ - /* TODO analysis of the network devices */ + /* extract virtual CPUs */ + if (virXPathULong("string(./vcpu[1])", ctxt, &def->vcpus) < 0) + def->vcpus = 0; //use default CPUs count - /* Extract network */ - /* Extract ipaddress */ - obj = xmlXPathEval(BAD_CAST"string(/domain/container/network/ipaddress[1])", ctxt); - if ((obj == NULL) || (obj->type != XPATH_STRING) || (obj->stringval == NULL) - || (obj->stringval[0] == 0)) { - openvzLog(OPENVZ_WARN, - _("No IP address in the given xml config file '%s'"), - xml->name); - } - if (xmlStrlen(obj->stringval) >= (OPENVZ_IP_MAX)) { - openvzError(conn, VIR_ERR_INTERNAL_ERROR, - _("ipaddress length too long")); - goto bail_out; - } - if (VIR_ALLOC(ovzIp) < 0) { - openvzLog(OPENVZ_ERR, - _("Failed to Create Memory for 'ovz_ip' structure")); + /* Extract filesystem info */ + if (openvzParseDomainFS(conn, &(def->fs), ctxt)) { + openvzError(conn, VIR_ERR_INTERNAL_ERROR, + _("malformed filesystem tag")); goto bail_out; } - strncpy(ovzIp->ip, (const char *) obj->stringval, OPENVZ_IP_MAX); - def->net.ips = ovzIp; - xmlXPathFreeObject(obj); - /* Extract netmask */ - obj = xmlXPathEval(BAD_CAST "string(/domain/container/network/netmask[1])", ctxt); - if ((obj == NULL) || (obj->type != XPATH_STRING) - || (obj->stringval == NULL) || (obj->stringval[0] == 0)) - openvzLog(OPENVZ_WARN, - _("No Netmask address in the given xml config file '%s'"), - xml->name); - - if (strlen((const char *) obj->stringval) >= (OPENVZ_IP_MAX)) { + /* analysis of the network devices */ + if ((n = virXPathNodeSet("/domain/devices/interface", ctxt, &nodes)) < 0) { openvzError(conn, VIR_ERR_INTERNAL_ERROR, - _("netmask length too long")); + "%s", _("cannot extract network devices")); goto bail_out; } - strncpy(def->net.ips->netmask, (const char *) obj->stringval, OPENVZ_IP_MAX); - xmlXPathFreeObject(obj); - - /* Extract hostname */ - obj = xmlXPathEval(BAD_CAST "string(/domain/container/network/hostname[1])", ctxt); - if ((obj == NULL) || (obj->type != XPATH_STRING) || (obj->stringval == NULL) - || (obj->stringval[0] == 0)) - openvzLog(OPENVZ_WARN, - _("No hostname in the given xml config file '%s'"), - xml->name); - if (strlen((const char *) obj->stringval) >= (OPENVZ_HOSTNAME_MAX - 1)) { - openvzError(conn, VIR_ERR_INTERNAL_ERROR, - _("hostname length too long")); - goto bail_out; - } - strncpy(def->net.hostname, (const char *) obj->stringval, OPENVZ_HOSTNAME_MAX - 1); - xmlXPathFreeObject(obj); - - /* Extract gateway */ - obj = xmlXPathEval(BAD_CAST"string(/domain/container/network/gateway[1])", ctxt); - if ((obj == NULL) || (obj->type != XPATH_STRING) || (obj->stringval == NULL) - || (obj->stringval[0] == 0)) - openvzLog(OPENVZ_WARN, - _("No Gateway address in the given xml config file '%s'"), - xml->name); - - if (strlen((const char *) obj->stringval) >= (OPENVZ_IP_MAX)) { - openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("gateway length too long")); - goto bail_out; - } - strncpy(def->net.def_gw, (const char *) obj->stringval, OPENVZ_IP_MAX); - xmlXPathFreeObject(obj); - - /* Extract nameserver */ - obj = xmlXPathEval(BAD_CAST "string(/domain/container/network/nameserver[1])", ctxt); - if ((obj == NULL) || (obj->type != XPATH_STRING) || (obj->stringval == NULL) - || (obj->stringval[0] == 0)) - openvzLog(OPENVZ_WARN, - _("No Nameserver address inthe given xml config file '%s'"), - xml->name); - - if (strlen((const char *) obj->stringval) >= (OPENVZ_IP_MAX)) { - openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("nameserver length too long")); - goto bail_out; - } - if (VIR_ALLOC(ovzNs) < 0) { - openvzLog(OPENVZ_ERR, - _("Failed to Create Memory for 'ovz_ns' structure")); - goto bail_out; - } - strncpy(ovzNs->ip, (const char *) obj->stringval, OPENVZ_IP_MAX); - def->net.ns = ovzNs; - xmlXPathFreeObject(obj); + for (i = n - 1 ; i >= 0 ; i--) { + virDomainNetDefPtr net = virDomainNetDefParseXML(conn, + nodes[i]); + if (!net) + goto bail_out; - /* Extract profile */ - obj = xmlXPathEval(BAD_CAST "string(/domain/container/profile[1])", ctxt); - if ((obj == NULL) || (obj->type != XPATH_STRING) || (obj->stringval == NULL) - || (obj->stringval[0] == 0)) { - openvzError(conn, VIR_ERR_INTERNAL_ERROR, NULL); - goto bail_out; - } - if (strlen((const char *) obj->stringval) >= (OPENVZ_PROFILE_MAX - 1)) { - openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("profile length too long")); - goto bail_out; + net->next = def->net; + def->net = net; } - strncpy(def->profile, (const char *) obj->stringval, OPENVZ_PROFILE_MAX - 1); - xmlXPathFreeObject(obj); + VIR_FREE(nodes); xmlXPathFreeContext(ctxt); return def; Index: src/openvz_conf.h =================================================================== RCS file: /data/cvs/libvirt/src/openvz_conf.h,v retrieving revision 1.9 diff -u -p -r1.9 openvz_conf.h --- src/openvz_conf.h 10 Jul 2008 12:21:09 -0000 1.9 +++ src/openvz_conf.h 25 Jul 2008 12:40:17 -0000 @@ -29,6 +29,7 @@ #define OPENVZ_CONF_H #include "openvz_driver.h" +#include "domain_conf.h" enum { OPENVZ_WARN, OPENVZ_ERR }; @@ -61,33 +62,16 @@ struct vps_props { struct openvz_fs_def { char tmpl[OPENVZ_TMPL_MAX]; - struct ovz_quota *quota; -}; - -struct ovz_ip { - char ip[OPENVZ_IP_MAX]; - char netmask[OPENVZ_IP_MAX]; - struct ovz_ip *next; -}; - -struct ovz_ns { - char ip[OPENVZ_IP_MAX]; - struct ovz_ns *next; -}; - -struct openvz_net_def { - char hostname[OPENVZ_HOSTNAME_MAX]; - char def_gw[OPENVZ_IP_MAX]; - struct ovz_ip *ips; - struct ovz_ns *ns; + long int disksize, diskinodes; }; struct openvz_vm_def { char name[OPENVZ_NAME_MAX]; unsigned char uuid[VIR_UUID_BUFLEN]; char profile[OPENVZ_PROFILE_MAX]; + unsigned long vcpus; struct openvz_fs_def fs; - struct openvz_net_def net; + virDomainNetDefPtr net; }; struct ovz_quota { @@ -133,4 +117,7 @@ void openvzFreeDriver(struct openvz_driv void openvzFreeVM(struct openvz_driver *driver, struct openvz_vm *vm, int checkCallee); void openvzFreeVMDef(struct openvz_vm_def *def); int strtoI(const char *str); +int openvzCheckEmptyMac(const unsigned char *mac); +char *openvzMacToString(const unsigned char *mac); + #endif /* OPENVZ_CONF_H */ Index: src/openvz_driver.c =================================================================== RCS file: /data/cvs/libvirt/src/openvz_driver.c,v retrieving revision 1.34 diff -u -p -r1.34 openvz_driver.c --- src/openvz_driver.c 21 Jul 2008 13:34:19 -0000 1.34 +++ src/openvz_driver.c 25 Jul 2008 12:40:17 -0000 @@ -176,14 +176,6 @@ static int openvzDomainDefineCmd(virConn ADD_ARG_LIT("--config"); ADD_ARG_LIT(vmdef->profile); } - if ((vmdef->net.ips->ip && *(vmdef->net.ips->ip))) { - ADD_ARG_LIT("--ipadd"); - ADD_ARG_LIT(vmdef->net.ips->ip); - } - if ((vmdef->net.hostname && *(vmdef->net.hostname))) { - ADD_ARG_LIT("--hostname"); - ADD_ARG_LIT(vmdef->net.hostname); - } ADD_ARG(NULL); return 0; @@ -357,6 +349,98 @@ static int openvzDomainReboot(virDomainP return 0; } +static int +openvzDomainSetNetwork(virConnectPtr conn, const char *vpsid, + virDomainNetDefPtr net) +{ + int rc = 0, narg; + char *prog[OPENVZ_MAX_ARG]; + char *mac = NULL; + +#define ADD_ARG_LIT(thisarg) \ + do { \ + if (narg >= OPENVZ_MAX_ARG) \ + goto no_memory; \ + if ((prog[narg++] = strdup(thisarg)) == NULL) \ + goto no_memory; \ + } while (0) + + + if (net == NULL) + return 0; + if (vpsid == NULL) { + openvzError(conn, VIR_ERR_INTERNAL_ERROR, + _("Container ID is not specified")); + return -1; + } + + for (narg = 0; narg < OPENVZ_MAX_ARG; narg++) + prog[narg] = NULL; + + narg = 0; + + if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE || + net->type == VIR_DOMAIN_NET_TYPE_ETHERNET) { + ADD_ARG_LIT(VZCTL); + ADD_ARG_LIT("--quiet"); + ADD_ARG_LIT("set"); + ADD_ARG_LIT(vpsid); + } + + if (openvzCheckEmptyMac(net->mac) > 0) + mac = openvzMacToString(net->mac); + + if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE && + net->data.bridge.brname != NULL) { + char opt[1024]; + //--netif_add ifname[,mac,host_ifname,host_mac] + ADD_ARG_LIT("--netif_add") ; + strncpy(opt, net->data.bridge.brname, 256); + if (mac != NULL) { + strcat(opt, ","); + strcat(opt, mac); + } + ADD_ARG_LIT(opt) ; + }else if (net->type == VIR_DOMAIN_NET_TYPE_ETHERNET && + net->data.ethernet.ipaddr != NULL) { + //--ipadd ip + ADD_ARG_LIT("--ipadd") ; + ADD_ARG_LIT(net->data.ethernet.ipaddr) ; + } + + //TODO: processing NAT and phisical device + + if (prog[0] != NULL){ + ADD_ARG_LIT("--save"); + if (virRun(conn, (char **)prog, NULL) < 0) { + openvzError(conn, VIR_ERR_INTERNAL_ERROR, + _("Could not exec %s"), VZCTL); + rc = -1; + goto exit; + } + } + + if (net->next != NULL) + if (openvzDomainSetNetwork(conn, vpsid, net->next) < 0) { + rc = -1; + goto exit; + } + + exit: + cmdExecFree(prog); + VIR_FREE(mac); + return rc; + + no_memory: + openvzError(conn, VIR_ERR_INTERNAL_ERROR, + _("Could not put argument to %s"), VZCTL); + cmdExecFree(prog); + VIR_FREE(mac); + return -1; + +#undef ADD_ARG_LIT +} + static virDomainPtr openvzDomainDefineXML(virConnectPtr conn, const char *xml) { @@ -387,6 +471,9 @@ openvzDomainDefineXML(virConnectPtr conn goto exit; } + //TODO: set number virtual CPUs + //TODO: set quota + if (virRun(conn, (char **)prog, NULL) < 0) { openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("Could not exec %s"), VZCTL); @@ -396,7 +483,14 @@ openvzDomainDefineXML(virConnectPtr conn dom = virGetDomain(conn, vm->vmdef->name, vm->vmdef->uuid); if (dom) dom->id = vm->vpsid; - exit: + + if (openvzDomainSetNetwork(conn, vmdef->name, vmdef->net) < 0) { + openvzError(conn, VIR_ERR_INTERNAL_ERROR, + _("Could not configure network")); + goto exit; + } + + exit: cmdExecFree(prog); return dom; } @@ -441,6 +535,12 @@ openvzDomainCreateLinux(virConnectPtr co goto exit; } + if (openvzDomainSetNetwork(conn, vmdef->name, vmdef->net) < 0) { + openvzError(conn, VIR_ERR_INTERNAL_ERROR, + _("Could not configure network")); + goto exit; + } + progstart[3] = vmdef->name; if (virRun(conn, (char **)progstart, NULL) < 0) {
-- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list