add/change/delete a Disk/NIC of an inactive domains

* src/xm_internal.[ch]: applied patch from Shigeki Sakamoto to
  add/change/delete a Disk/NIC of an inactive domains
Daniel
This commit is contained in:
Daniel Veillard 2008-02-06 17:57:10 +00:00
parent eecd68364a
commit 594af3eb22
4 changed files with 660 additions and 16 deletions

View File

@ -1,3 +1,8 @@
Wed Feb 6 18:55:37 CET 2008 Daniel Veillard <veillard@redhat.com>
* src/xm_internal.[ch]: applied patch from Shigeki Sakamoto to
add/change/delete a Disk/NIC of an inactive domains
Wed Feb 6 17:22:34 CET 2008 Daniel Veillard <veillard@redhat.com> Wed Feb 6 17:22:34 CET 2008 Daniel Veillard <veillard@redhat.com>
* src/qemu_conf.c: applied 2 patches from Guido Guenther to avoid * src/qemu_conf.c: applied 2 patches from Guido Guenther to avoid

28
NEWS
View File

@ -17,7 +17,7 @@ Releases
various english fixes (Bruce Montague), OCaml docs links (Richard Jones), various english fixes (Bruce Montague), OCaml docs links (Richard Jones),
describe the various bindings add Ruby link, Windows support page describe the various bindings add Ruby link, Windows support page
(Richard Jones), authentication documentation updates (Daniel Berrange) (Richard Jones), authentication documentation updates (Daniel Berrange)
- Bug fixes: NUMA topology error handling (Beth Kon), NUMA topology - Bug fixes: NUMA topology error handling (Beth Kon), NUMA topology
cells without CPU (Beth Kon), XML to/from XM bridge config (Daniel cells without CPU (Beth Kon), XML to/from XM bridge config (Daniel
Berrange), XM processing of vnc parameters (Daniel Berrange), Reset Berrange), XM processing of vnc parameters (Daniel Berrange), Reset
@ -42,7 +42,7 @@ Releases
parameter setting in XM config (Saori Fukuta), credential handling parameter setting in XM config (Saori Fukuta), credential handling
fixes (Daniel Berrange), fix compatibility with Xen 3.2.0 (Daniel fixes (Daniel Berrange), fix compatibility with Xen 3.2.0 (Daniel
Berrange) Berrange)
- Improvements: /etc/libvirt/qemu.conf configuration for QEMU driver - Improvements: /etc/libvirt/qemu.conf configuration for QEMU driver
(Daniel Berrange), NUMA cpu pinning in config files (DV and Saori Fukuta), (Daniel Berrange), NUMA cpu pinning in config files (DV and Saori Fukuta),
CDRom media change in KVM/QEMU (Daniel Berrange), tests for CDRom media change in KVM/QEMU (Daniel Berrange), tests for
@ -51,7 +51,7 @@ Releases
--without-libvirtd config option (Richard Jones), Python bindings for --without-libvirtd config option (Richard Jones), Python bindings for
NUMA, add extra utility functions to buffer (Richard Jones), NUMA, add extra utility functions to buffer (Richard Jones),
separate qparams module for handling query parameters (Richard Jones) separate qparams module for handling query parameters (Richard Jones)
- Code cleanups: remove virDomainRestart from API as it was never used - Code cleanups: remove virDomainRestart from API as it was never used
(Richard Jones), constify params for attach/detach APIs (Daniel Berrange), (Richard Jones), constify params for attach/detach APIs (Daniel Berrange),
gcc printf attribute checkings (Jim Meyering), refactoring of device gcc printf attribute checkings (Jim Meyering), refactoring of device
@ -72,13 +72,13 @@ Releases
port (Richard Jones), disable the proxy if using PolicyKit, readline port (Richard Jones), disable the proxy if using PolicyKit, readline
availability detection, test libvirtd's config-processing code (Jim availability detection, test libvirtd's config-processing code (Jim
Meyering), use a variable name as sizeof argument (Jim Meyering) Meyering), use a variable name as sizeof argument (Jim Meyering)
0.3.3: Sep 30 2007: 0.3.3: Sep 30 2007:
- New features: Avahi mDNS daemon export (Daniel Berrange), - New features: Avahi mDNS daemon export (Daniel Berrange),
NUMA support (Beth Kan) NUMA support (Beth Kan)
- Documentation: cleanups (Toth Istvan), typos (Eduardo Pereira), - Documentation: cleanups (Toth Istvan), typos (Eduardo Pereira),
- Bug fixes: memory corruption on large dumps (Masayuki Sunou), fix - Bug fixes: memory corruption on large dumps (Masayuki Sunou), fix
virsh vncdisplay command exit (Masayuki Sunou), Fix network stats virsh vncdisplay command exit (Masayuki Sunou), Fix network stats
TX/RX result (Richard Jones), warning on Xen 3.0.3 (Richard Jones), TX/RX result (Richard Jones), warning on Xen 3.0.3 (Richard Jones),
@ -124,10 +124,10 @@ Releases
speedup of domain queries on Xen (Daniel berrange), augment XML dumps speedup of domain queries on Xen (Daniel berrange), augment XML dumps
with interface devices names (Richard Jones), internal API to query with interface devices names (Richard Jones), internal API to query
drivers for features (Richard Jones). drivers for features (Richard Jones).
- Cleanups: Improve virNodeGetInfo implentation (Daniel berrange), - Cleanups: Improve virNodeGetInfo implentation (Daniel berrange),
general UUID code cleanup (Daniel berrange), fix API generator general UUID code cleanup (Daniel berrange), fix API generator
file selection. file selection.
0.3.1: Jul 24 2007: 0.3.1: Jul 24 2007:
@ -161,7 +161,7 @@ Releases
- Secure Remote support (Richard Jones). - Secure Remote support (Richard Jones).
See the remote page See the remote page
of the documentation of the documentation
- Documentation: remote support (Richard Jones), description of - Documentation: remote support (Richard Jones), description of
the URI connection strings (Richard Jones), update of virsh man the URI connection strings (Richard Jones), update of virsh man
page, matrix of libvirt API/hypervisor support with version page, matrix of libvirt API/hypervisor support with version
@ -202,7 +202,7 @@ Releases
0.2.3: Jun 8 2007: 0.2.3: Jun 8 2007:
- Documentation: documentation for upcoming remote access (Richard Jones), - Documentation: documentation for upcoming remote access (Richard Jones),
virConnectNumOfDefinedDomains doc (Jan Michael), virsh help messages virConnectNumOfDefinedDomains doc (Jan Michael), virsh help messages
for dumpxml and net-dumpxml (Chris Wright), for dumpxml and net-dumpxml (Chris Wright),
- Bug fixes: RelaxNG schemas regexp fix (Robin Green), RelaxNG arch bug - Bug fixes: RelaxNG schemas regexp fix (Robin Green), RelaxNG arch bug
(Mark McLoughlin), large buffers bug fixes (Shigeki Sakamoto), error (Mark McLoughlin), large buffers bug fixes (Shigeki Sakamoto), error
on out of memory condition (Shigeki Sakamoto), virshStrdup fix, non-root on out of memory condition (Shigeki Sakamoto), virshStrdup fix, non-root
@ -262,7 +262,7 @@ Releases
signal handler error cleanup (Richard Jones), iptables internal code signal handler error cleanup (Richard Jones), iptables internal code
claenup (Mark McLoughlin), unified Xen driver (Richard Jones), claenup (Mark McLoughlin), unified Xen driver (Richard Jones),
cleanup XPath libxml2 calls, IPTables rules tightening (Daniel cleanup XPath libxml2 calls, IPTables rules tightening (Daniel
Berrange), Berrange),
- Improvements: more regression tests on XML (Daniel Berrange), Python - Improvements: more regression tests on XML (Daniel Berrange), Python
bindings now generate exception in error cases (Richard Jones), bindings now generate exception in error cases (Richard Jones),
Python bindings for vir*GetAutoStart (Daniel Berrange), Python bindings for vir*GetAutoStart (Daniel Berrange),
@ -270,7 +270,7 @@ Releases
fix hypervisor call to work with Xen 3.0.5 (Daniel Berrange), fix hypervisor call to work with Xen 3.0.5 (Daniel Berrange),
DomainGetOSType for inactive domains (Daniel Berrange), multiple boot DomainGetOSType for inactive domains (Daniel Berrange), multiple boot
devices for HVM (Daniel Berrange), devices for HVM (Daniel Berrange),
0.2.1: Mar 16 2007: 0.2.1: Mar 16 2007:
@ -375,7 +375,7 @@ Releases
- Support for localization of strings using gettext (Daniel Berrange) - Support for localization of strings using gettext (Daniel Berrange)
- Support for new Xen-3.0.3 cdrom and disk configuration (Daniel Berrange) - Support for new Xen-3.0.3 cdrom and disk configuration (Daniel Berrange)
- Support for setting VNC port when creating domains with new - Support for setting VNC port when creating domains with new
xend config files (Daniel Berrange) xend config files (Daniel Berrange)
- Fix bug when running against xen-3.0.2 hypercalls (Jim Fehlig) - Fix bug when running against xen-3.0.2 hypercalls (Jim Fehlig)
- Fix reconnection problem when talking directly to http xend - Fix reconnection problem when talking directly to http xend
@ -409,7 +409,7 @@ Releases
floppy and cdrom (Daniel Berrange), features block in XML to report/ask floppy and cdrom (Daniel Berrange), features block in XML to report/ask
PAE, ACPI, APIC for HVM domains (Daniel Berrange), fail saide-effect PAE, ACPI, APIC for HVM domains (Daniel Berrange), fail saide-effect
operations when using read-only connection, large improvements to test operations when using read-only connection, large improvements to test
driver (Daniel Berrange) driver (Daniel Berrange)
- documentation: spelling (Daniel Berrange), test driver examples. - documentation: spelling (Daniel Berrange), test driver examples.

View File

@ -72,6 +72,12 @@ static virHashTablePtr nameConfigMap = NULL;
static int nconnections = 0; static int nconnections = 0;
static time_t lastRefresh = 0; static time_t lastRefresh = 0;
char * xenXMAutoAssignMac(void);
static int xenXMAttachDisk(virDomainPtr domain, xmlXPathContextPtr ctxt, int hvm,
xmlNodePtr node, xenXMConfCachePtr entry);
static int xenXMAttachInterface(virDomainPtr domain, xmlXPathContextPtr ctxt, int hvm,
xmlNodePtr node, xenXMConfCachePtr entry);
#define XM_REFRESH_INTERVAL 10 #define XM_REFRESH_INTERVAL 10
#define XM_CONFIG_DIR "/etc/xen" #define XM_CONFIG_DIR "/etc/xen"
@ -79,6 +85,7 @@ static time_t lastRefresh = 0;
#define XEND_CONFIG_FILE "xend-config.sxp" #define XEND_CONFIG_FILE "xend-config.sxp"
#define XEND_PCI_CONFIG_PREFIX "xend-pci-" #define XEND_PCI_CONFIG_PREFIX "xend-pci-"
#define QEMU_IF_SCRIPT "qemu-ifup" #define QEMU_IF_SCRIPT "qemu-ifup"
#define XM_XML_ERROR "Invalid xml"
struct xenUnifiedDriver xenXMDriver = { struct xenUnifiedDriver xenXMDriver = {
xenXMOpen, /* open */ xenXMOpen, /* open */
@ -113,8 +120,8 @@ struct xenUnifiedDriver xenXMDriver = {
xenXMDomainCreate, /* domainCreate */ xenXMDomainCreate, /* domainCreate */
xenXMDomainDefineXML, /* domainDefineXML */ xenXMDomainDefineXML, /* domainDefineXML */
xenXMDomainUndefine, /* domainUndefine */ xenXMDomainUndefine, /* domainUndefine */
NULL, /* domainAttachDevice */ xenXMDomainAttachDevice, /* domainAttachDevice */
NULL, /* domainDetachDevice */ xenXMDomainDetachDevice, /* domainDetachDevice */
NULL, /* domainGetAutostart */ NULL, /* domainGetAutostart */
NULL, /* domainSetAutostart */ NULL, /* domainSetAutostart */
NULL, /* domainGetSchedulerType */ NULL, /* domainGetSchedulerType */
@ -2515,6 +2522,635 @@ int xenXMNumOfDefinedDomains(virConnectPtr conn) {
return virHashSize(nameConfigMap); return virHashSize(nameConfigMap);
} }
/**
* xenXMDomainAttachDevice:
* @domain: pointer to domain object
* @xml: pointer to XML description of device
*
* Create a virtual device attachment to backend.
* XML description is translated into config file.
*
* Returns 0 in case of success, -1 in case of failure.
*/
static int
xenXMDomainAttachDevice(virDomainPtr domain, const char *xml) {
const char *filename = NULL;
xenXMConfCachePtr entry = NULL;
xmlDocPtr doc = NULL;
xmlNodePtr node = NULL;
xmlXPathContextPtr ctxt = NULL;
xmlXPathObjectPtr obj = NULL;
char *domxml = NULL;
int ret = -1, hvm = 0;
if ((!domain) || (!domain->conn) || (!domain->name) || (!xml)) {
xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
__FUNCTION__);
goto cleanup;
}
if (domain->conn->flags & VIR_CONNECT_RO)
goto cleanup;
if (domain->id != -1)
goto cleanup;
if (!(filename = virHashLookup(nameConfigMap, domain->name)))
goto cleanup;
if (!(entry = virHashLookup(configCache, filename)))
goto cleanup;
if (!(entry->conf))
goto cleanup;
if (!(domxml = xenXMDomainDumpXML(domain, 0)))
goto cleanup;
doc = xmlReadDoc((const xmlChar *) domxml, "domain.xml", NULL,
XML_PARSE_NOENT | XML_PARSE_NONET |
XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
if (!doc) {
xenXMError(domain->conn, VIR_ERR_XML_ERROR, "cannot read XML domain definition");
goto cleanup;
}
if (!(ctxt = xmlXPathNewContext(doc))) {
xenXMError(domain->conn, VIR_ERR_INTERNAL_ERROR, "cannot create XPath context");
goto cleanup;
}
obj = xmlXPathEval(BAD_CAST "string(/domain/os/type)", ctxt);
if ((obj != NULL) && (obj->type == XPATH_STRING) &&
(obj->stringval) && (STREQ((char *)obj->stringval, "hvm")))
hvm = 1;
if (ctxt)
xmlXPathFreeContext(ctxt);
ctxt = NULL;
if (doc)
xmlFreeDoc(doc);
doc = xmlReadDoc((const xmlChar *) xml, "device.xml", NULL,
XML_PARSE_NOENT | XML_PARSE_NONET |
XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
if (!doc) {
xenXMError(domain->conn, VIR_ERR_XML_ERROR,
"cannot read XML domain definition");
goto cleanup;
}
if (!(ctxt = xmlXPathNewContext(doc))) {
xenXMError(domain->conn, VIR_ERR_INTERNAL_ERROR,
"cannot create XPath context");
goto cleanup;
}
if ((node = virXPathNode("/disk", ctxt))) {
if (xenXMAttachDisk(domain, ctxt, hvm, node, entry))
goto cleanup;
} else if ((node = virXPathNode("/interface", ctxt))) {
if (xenXMAttachInterface(domain, ctxt, hvm, node, entry))
goto cleanup;
} else {
xenXMError(domain->conn, VIR_ERR_XML_ERROR, "unknown device");
goto cleanup;
}
/* If this fails, should we try to undo our changes to the
* in-memory representation of the config file. I say not!
*/
if (virConfWriteFile(entry->filename, entry->conf) < 0)
goto cleanup;
ret = 0;
cleanup:
if (domxml)
free(domxml);
if (obj)
xmlXPathFreeObject(obj);
if (ctxt)
xmlXPathFreeContext(ctxt);
if (doc)
xmlFreeDoc(doc);
return ret;
}
static int
xenXMAttachDisk(virDomainPtr domain, xmlXPathContextPtr ctxt, int hvm,
xmlNodePtr node, xenXMConfCachePtr entry) {
virConfValuePtr list_item = NULL, list_val = NULL, prev = NULL;
xenUnifiedPrivatePtr priv = NULL;
xmlChar *type = NULL, *source = NULL, *target = NULL;
int ret = -1;
char *dev;
priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
xenXMParseXMLDisk(node, hvm, ((xenUnifiedPrivatePtr) domain->conn->privateData)->xendConfigVersion, &dev);
if (!dev)
goto cleanup;
if (!(type = xmlGetProp(node, BAD_CAST "type"))) {
xenXMError(domain->conn, VIR_ERR_XML_ERROR, XM_XML_ERROR);
goto cleanup;
}
if (!(node = virXPathNode("/disk/source", ctxt))) {
xenXMError(domain->conn, VIR_ERR_XML_ERROR, XM_XML_ERROR);
goto cleanup;
}
if (!strcmp((const char *) type, "block"))
source = xmlGetProp(node, BAD_CAST "dev");
else if (!strcmp((const char *) type, "file"))
source = xmlGetProp(node, BAD_CAST "file");
else {
xenXMError(domain->conn, VIR_ERR_XML_ERROR, XM_XML_ERROR);
goto cleanup;
}
if (!(node = virXPathNode("/disk/target", ctxt))) {
xenXMError(domain->conn, VIR_ERR_XML_ERROR, XM_XML_ERROR);
goto cleanup;
}
target = xmlGetProp(node, BAD_CAST "dev");
list_item = virConfGetValue(entry->conf, "disk");
if (list_item && list_item->type == VIR_CONF_LIST) {
prev = list_item;
list_val = list_item->list;
while (list_val) {
if ((list_val->type != VIR_CONF_STRING) || (!list_val->str))
goto skip;
char domdev[NAME_MAX];
char *head;
char *offset;
char *tmp;
head = list_val->str;
/* Extract the source */
if (!(offset = strchr(head, ',')) || offset[0] == '\0')
goto skip;
if ((offset - head) >= (PATH_MAX-1))
goto skip;
head = offset + 1;
/* Extract the dest */
if (!(offset = strchr(head, ',')) || offset[0] == '\0')
goto skip;
if ((offset - head) >= (PATH_MAX-1))
goto skip;
strncpy(domdev, head, (offset - head));
domdev[(offset-head)] = '\0';
head = offset + 1;
/* Remove legacy ioemu: junk */
if (!strncmp(domdev, "ioemu:", 6)) {
memmove(domdev, domdev+6, strlen(domdev)-5);
}
/* Check for a :cdrom/:disk postfix */
if ((tmp = strchr(domdev, ':')))
tmp[0] = '\0';
if (!(strcmp(domdev, (const char *) target)))
break;
skip:
prev = list_val;
list_val = list_val->next;
}
} else if (!list_item) {
if (!(list_item = calloc(1, sizeof(virConfValue))))
goto cleanup;
list_item->type = VIR_CONF_LIST;
if(virConfSetValue(entry->conf, "disk", list_item)) {
free(list_item);
goto cleanup;
}
list_val = NULL;
prev = list_item;
} else
goto cleanup;
if (!list_val) {
/* insert */
if (!(list_val = malloc(sizeof(virConfValue))))
goto cleanup;
list_val->type = VIR_CONF_STRING;
list_val->next = NULL;
list_val->str = dev;
if (prev->type == VIR_CONF_LIST)
prev->list = list_val;
else
prev->next = list_val;
} else {
/* configure */
if (list_val->str)
free(list_val->str);
list_val->str = dev;
}
ret = 0;
goto cleanup;
cleanup:
if (type)
free(type);
if (source)
free(source);
if (target)
free(target);
return (ret);
}
static int
xenXMAttachInterface(virDomainPtr domain, xmlXPathContextPtr ctxt, int hvm,
xmlNodePtr node, xenXMConfCachePtr entry) {
virConfValuePtr list_item = NULL, list_val = NULL, prev = NULL;
xmlChar *type = NULL, *source = NULL, *mac = NULL;
int ret = -1, autoassign = 0;
char *dev;
xmlNodePtr node_cur = NULL, node_tmp = NULL;
xmlAttrPtr attr_node = NULL;
xmlNodePtr text_node = NULL;
if(!(type = xmlGetProp(node, BAD_CAST "type"))) {
xenXMError(domain->conn, VIR_ERR_XML_ERROR, XM_XML_ERROR);
goto cleanup;
}
if (!(node = virXPathNode("/interface/source", ctxt))) {
xenXMError(domain->conn, VIR_ERR_XML_ERROR, XM_XML_ERROR);
goto cleanup;
}
source = xmlGetProp(node, BAD_CAST type);
if (!(node = virXPathNode("/interface/mac", ctxt))) {
if (!(mac = (xmlChar *)xenXMAutoAssignMac()))
goto cleanup;
autoassign = 1;
} else
mac = xmlGetProp(node, BAD_CAST "address");
list_item = virConfGetValue(entry->conf, "vif");
if (list_item && list_item->type == VIR_CONF_LIST) {
prev = list_item;
list_val = list_item->list;
while (list_val) {
if ((list_val->type != VIR_CONF_STRING) || (!list_val->str))
goto skip;
char dommac[18];
char *key;
dommac[0] = '\0';
key = list_val->str;
while (key) {
char *data;
char *nextkey = strchr(key, ',');
if (!(data = strchr(key, '=')) || (data[0] == '\0'))
goto skip;
data++;
if (!strncmp(key, "mac=", 4)) {
int len = nextkey ? (nextkey - data) : 17;
if (len > 17)
len = 17;
strncpy(dommac, data, len);
dommac[len] = '\0';
}
while (nextkey && (nextkey[0] == ',' ||
nextkey[0] == ' ' ||
nextkey[0] == '\t'))
nextkey++;
key = nextkey;
}
if (!(strcmp(dommac, (const char *) mac))) {
if (autoassign) {
if (mac)
free(mac);
mac = NULL;
if (!(mac = (xmlChar *)xenXMAutoAssignMac()))
goto cleanup;
/* initialize the list */
list_item = virConfGetValue(entry->conf, "vif");
prev = list_item;
list_val = list_item->list;
continue;
} else
break;
}
skip:
prev = list_val;
list_val = list_val->next;
}
} else if (!list_item) {
if (!(list_item = calloc(1, sizeof(virConfValue))))
goto cleanup;
list_item->type = VIR_CONF_LIST;
if(virConfSetValue(entry->conf, "vif", list_item)) {
free(list_item);
goto cleanup;
}
list_val = NULL;
prev = list_item;
} else
goto cleanup;
if ((node = virXPathNode("/interface", ctxt))) {
if (autoassign) {
node_cur = node->children;
while (node_cur->next)
node_cur = node_cur->next;
if (!(node_tmp = calloc(1, sizeof(xmlNode))))
goto node_cleanup;
node_tmp->type = XML_ELEMENT_NODE;
if (!(node_tmp->name = malloc(4)))
goto node_cleanup;
strcpy((char *)node_tmp->name, "mac");
node_tmp->children = NULL;
if (!(attr_node = calloc(1, sizeof(xmlAttr))))
goto node_cleanup;
attr_node->type = XML_ATTRIBUTE_NODE;
attr_node->ns = NULL;
if (!(attr_node->name = malloc(8)))
goto node_cleanup;
strcpy((char *) attr_node->name, "address");
node_tmp->properties = attr_node;
if (!(text_node = calloc(1, sizeof(xmlNode))))
goto node_cleanup;
text_node->type = XML_TEXT_NODE;
text_node->_private = NULL;
if (!(text_node->name = malloc(8)))
goto node_cleanup;
strcpy((char *) text_node->name, "text");
text_node->children = NULL;
text_node->parent = (xmlNodePtr)attr_node;
text_node->content = mac;
mac = NULL;
attr_node->children = text_node;
attr_node->last = text_node;
attr_node->parent = node_tmp;
node_cur->next = node_tmp;
}
if (!(dev = xenXMParseXMLVif(domain->conn, node, hvm)))
goto cleanup;
} else
goto cleanup;
if (!list_val) {
/* insert */
if (!(list_val = malloc(sizeof(virConfValue))))
goto cleanup;
list_val->type = VIR_CONF_STRING;
list_val->next = NULL;
list_val->str = dev;
if (prev->type == VIR_CONF_LIST)
prev->list = list_val;
else
prev->next = list_val;
} else {
/* configure */
if (list_val->str)
free(list_val->str);
list_val->str = dev;
}
ret = 0;
goto cleanup;
node_cleanup:
if (node_tmp)
xmlFree(node_tmp);
if (attr_node)
xmlFree(attr_node);
if (text_node)
xmlFree(text_node);
cleanup:
if (type)
free(type);
if (source)
free(source);
if (mac)
free(mac);
return (ret);
}
/**
* xenXMAutoAssignMac:
* @mac: pointer to Mac String
*
* a mac is assigned automatically.
*
* Returns 0 in case of success, -1 in case of failure.
*/
char *
xenXMAutoAssignMac() {
char *buf;
if (!(buf = malloc(18)))
return 0;
srand((unsigned)time(NULL));
sprintf(buf, "00:16:3e:%02x:%02x:%02x"
,1 + (int)(256*(rand()/(RAND_MAX+1.0)))
,1 + (int)(256*(rand()/(RAND_MAX+1.0)))
,1 + (int)(256*(rand()/(RAND_MAX+1.0))));
return buf;
}
/**
* xenXMDomainDetachDevice:
* @domain: pointer to domain object
* @xml: pointer to XML description of device
*
* Destroy a virtual device attachment to backend.
*
* Returns 0 in case of success, -1 in case of failure.
*/
static int
xenXMDomainDetachDevice(virDomainPtr domain, const char *xml) {
const char *filename = NULL;
char device[8], *domdevice = NULL;
xenXMConfCachePtr entry = NULL;
virConfValuePtr prev = NULL, list_ptr = NULL, list_val = NULL;
xmlDocPtr doc = NULL;
xmlNodePtr node = NULL;
xmlXPathContextPtr ctxt = NULL;
xmlChar *key = NULL;
int ret = -1;
if ((!domain) || (!domain->conn) || (!domain->name) || (!xml)) {
xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
__FUNCTION__);
goto cleanup;
}
if (domain->conn->flags & VIR_CONNECT_RO)
goto cleanup;
if (domain->id != -1)
goto cleanup;
if (!(filename = virHashLookup(nameConfigMap, domain->name)))
goto cleanup;
doc = xmlReadDoc((const xmlChar *) xml, "device.xml", NULL,
XML_PARSE_NOENT | XML_PARSE_NONET |
XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
if (!doc) {
xenXMError(domain->conn, VIR_ERR_XML_ERROR, "cannot read XML domain definition");
goto cleanup;
}
if (!(ctxt = xmlXPathNewContext(doc))) {
xenXMError(domain->conn, VIR_ERR_INTERNAL_ERROR, "cannot create XPath context");
goto cleanup;
}
if ((node = virXPathNode("/disk", ctxt))) {
strcpy(device, "disk");
if (!(node = virXPathNode("/disk/target", ctxt)))
goto cleanup;
key = xmlGetProp(node, BAD_CAST "dev");
} else if ((node = virXPathNode("/interface", ctxt))) {
strcpy(device, "vif");
if (!(node = virXPathNode("/interface/mac", ctxt)))
goto cleanup;
key = xmlGetProp(node, BAD_CAST "address");
} else
goto cleanup;
if (!key || (strlen((char *)key) == 0))
goto cleanup;
if (!(entry = virHashLookup(configCache, filename)))
goto cleanup;
if (!entry->conf)
goto cleanup;
list_ptr = virConfGetValue(entry->conf, device);
if (!list_ptr)
goto cleanup;
else if (list_ptr && list_ptr->type == VIR_CONF_LIST) {
list_val = list_ptr->list;
while (list_val) {
if (!(strcmp(device, "disk"))) {
char domdev[NAME_MAX];
char *head;
char *offset;
char *tmp;
if ((list_val->type != VIR_CONF_STRING) || (!list_val->str))
goto skip;
head = list_val->str;
/* Extract the source */
if (!(offset = strchr(head, ',')) || offset[0] == '\0')
goto skip;
if ((offset - head) >= (PATH_MAX-1))
goto skip;
head = offset + 1;
/* Extract the dest */
if (!(offset = strchr(head, ',')) || offset[0] == '\0')
goto skip;
if ((offset - head) >= (PATH_MAX-1))
goto skip;
strncpy(domdev, head, (offset - head));
domdev[(offset-head)] = '\0';
head = offset + 1;
/* Remove legacy ioemu: junk */
if (!strncmp(domdev, "ioemu:", 6)) {
memmove(domdev, domdev+6, strlen(domdev)-5);
}
/* Check for a :cdrom/:disk postfix */
if ((tmp = strchr(domdev, ':')))
tmp[0] = '\0';
if (!(strcmp(domdev, (const char *) key)))
break;
} else {
char dommac[18];
char *mac;
dommac[0] = '\0';
if ((list_val->type != VIR_CONF_STRING) || (!list_val->str))
goto skip;
mac = list_val->str;
while (mac) {
char *data;
char *nextmac = strchr(mac, ',');
if (!(data = strchr(mac, '=')) || (data[0] == '\0'))
goto skip;
data++;
if (!strncmp(mac, "mac=", 4)) {
int len = nextmac ? (nextmac - data) : 17;
if (len > 17)
len = 17;
strncpy(dommac, data, len);
dommac[len] = '\0';
}
while (nextmac && (nextmac[0] == ',' ||
nextmac[0] == ' ' ||
nextmac[0] == '\t'))
nextmac++;
mac = nextmac;
}
if (!(strcmp(dommac, (const char *) key)))
break;
}
skip:
prev = list_val;
list_val = list_val->next;
}
}
if (!list_val)
goto cleanup;
else {
if (!prev) {
virConfValuePtr value;
if (!(value = calloc(1, sizeof(virConfValue))))
goto cleanup;
value->type = VIR_CONF_LIST;
value->list = list_val->next;
list_val->next = NULL;
if (virConfSetValue(entry->conf, device, value)) {
free(value);
goto cleanup;
}
} else
prev->next = list_val->next;
}
/* If this fails, should we try to undo our changes to the
* in-memory representation of the config file. I say not!
*/
if (virConfWriteFile(entry->filename, entry->conf) < 0)
goto cleanup;
ret = 0;
cleanup:
if (ctxt)
xmlXPathFreeContext(ctxt);
if (doc)
xmlFreeDoc(doc);
if (domdevice)
free(domdevice);
if (key)
free(key);
if (list_val)
free(list_val);
return (ret);
}
#endif /* WITH_XEN */ #endif /* WITH_XEN */
/* /*
* Local variables: * Local variables:

View File

@ -61,6 +61,9 @@ int xenXMDomainUndefine(virDomainPtr domain);
virConfPtr xenXMParseXMLToConfig(virConnectPtr conn, const char *xml); virConfPtr xenXMParseXMLToConfig(virConnectPtr conn, const char *xml);
char *xenXMDomainFormatXML(virConnectPtr conn, virConfPtr conf); char *xenXMDomainFormatXML(virConnectPtr conn, virConfPtr conf);
static int xenXMDomainAttachDevice(virDomainPtr domain, const char *xml);
static int xenXMDomainDetachDevice(virDomainPtr domain, const char *xml);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif