mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-27 02:51:16 +00:00
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:
parent
eecd68364a
commit
594af3eb22
@ -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>
|
||||
|
||||
* src/qemu_conf.c: applied 2 patches from Guido Guenther to avoid
|
||||
|
28
NEWS
28
NEWS
@ -17,7 +17,7 @@ Releases
|
||||
various english fixes (Bruce Montague), OCaml docs links (Richard Jones),
|
||||
describe the various bindings add Ruby link, Windows support page
|
||||
(Richard Jones), authentication documentation updates (Daniel Berrange)
|
||||
|
||||
|
||||
- Bug fixes: NUMA topology error handling (Beth Kon), NUMA topology
|
||||
cells without CPU (Beth Kon), XML to/from XM bridge config (Daniel
|
||||
Berrange), XM processing of vnc parameters (Daniel Berrange), Reset
|
||||
@ -42,7 +42,7 @@ Releases
|
||||
parameter setting in XM config (Saori Fukuta), credential handling
|
||||
fixes (Daniel Berrange), fix compatibility with Xen 3.2.0 (Daniel
|
||||
Berrange)
|
||||
|
||||
|
||||
- Improvements: /etc/libvirt/qemu.conf configuration for QEMU driver
|
||||
(Daniel Berrange), NUMA cpu pinning in config files (DV and Saori Fukuta),
|
||||
CDRom media change in KVM/QEMU (Daniel Berrange), tests for
|
||||
@ -51,7 +51,7 @@ Releases
|
||||
--without-libvirtd config option (Richard Jones), Python bindings for
|
||||
NUMA, add extra utility functions to buffer (Richard Jones),
|
||||
separate qparams module for handling query parameters (Richard Jones)
|
||||
|
||||
|
||||
- Code cleanups: remove virDomainRestart from API as it was never used
|
||||
(Richard Jones), constify params for attach/detach APIs (Daniel Berrange),
|
||||
gcc printf attribute checkings (Jim Meyering), refactoring of device
|
||||
@ -72,13 +72,13 @@ Releases
|
||||
port (Richard Jones), disable the proxy if using PolicyKit, readline
|
||||
availability detection, test libvirtd's config-processing code (Jim
|
||||
Meyering), use a variable name as sizeof argument (Jim Meyering)
|
||||
|
||||
|
||||
|
||||
|
||||
0.3.3: Sep 30 2007:
|
||||
- New features: Avahi mDNS daemon export (Daniel Berrange),
|
||||
NUMA support (Beth Kan)
|
||||
- Documentation: cleanups (Toth Istvan), typos (Eduardo Pereira),
|
||||
NUMA support (Beth Kan)
|
||||
- Documentation: cleanups (Toth Istvan), typos (Eduardo Pereira),
|
||||
- Bug fixes: memory corruption on large dumps (Masayuki Sunou), fix
|
||||
virsh vncdisplay command exit (Masayuki Sunou), Fix network stats
|
||||
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
|
||||
with interface devices names (Richard Jones), internal API to query
|
||||
drivers for features (Richard Jones).
|
||||
|
||||
|
||||
- Cleanups: Improve virNodeGetInfo implentation (Daniel berrange),
|
||||
general UUID code cleanup (Daniel berrange), fix API generator
|
||||
file selection.
|
||||
file selection.
|
||||
|
||||
|
||||
0.3.1: Jul 24 2007:
|
||||
@ -161,7 +161,7 @@ Releases
|
||||
- Secure Remote support (Richard Jones).
|
||||
See the remote page
|
||||
of the documentation
|
||||
|
||||
|
||||
- Documentation: remote support (Richard Jones), description of
|
||||
the URI connection strings (Richard Jones), update of virsh man
|
||||
page, matrix of libvirt API/hypervisor support with version
|
||||
@ -202,7 +202,7 @@ Releases
|
||||
0.2.3: Jun 8 2007:
|
||||
- Documentation: documentation for upcoming remote access (Richard Jones),
|
||||
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
|
||||
(Mark McLoughlin), large buffers bug fixes (Shigeki Sakamoto), error
|
||||
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
|
||||
claenup (Mark McLoughlin), unified Xen driver (Richard Jones),
|
||||
cleanup XPath libxml2 calls, IPTables rules tightening (Daniel
|
||||
Berrange),
|
||||
Berrange),
|
||||
- Improvements: more regression tests on XML (Daniel Berrange), Python
|
||||
bindings now generate exception in error cases (Richard Jones),
|
||||
Python bindings for vir*GetAutoStart (Daniel Berrange),
|
||||
@ -270,7 +270,7 @@ Releases
|
||||
fix hypervisor call to work with Xen 3.0.5 (Daniel Berrange),
|
||||
DomainGetOSType for inactive domains (Daniel Berrange), multiple boot
|
||||
devices for HVM (Daniel Berrange),
|
||||
|
||||
|
||||
|
||||
|
||||
0.2.1: Mar 16 2007:
|
||||
@ -375,7 +375,7 @@ Releases
|
||||
- Support for localization of strings using gettext (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
|
||||
xend config files (Daniel Berrange)
|
||||
xend config files (Daniel Berrange)
|
||||
- Fix bug when running against xen-3.0.2 hypercalls (Jim Fehlig)
|
||||
- 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
|
||||
PAE, ACPI, APIC for HVM domains (Daniel Berrange), fail saide-effect
|
||||
operations when using read-only connection, large improvements to test
|
||||
driver (Daniel Berrange)
|
||||
driver (Daniel Berrange)
|
||||
- documentation: spelling (Daniel Berrange), test driver examples.
|
||||
|
||||
|
||||
|
@ -72,6 +72,12 @@ static virHashTablePtr nameConfigMap = NULL;
|
||||
static int nconnections = 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_CONFIG_DIR "/etc/xen"
|
||||
@ -79,6 +85,7 @@ static time_t lastRefresh = 0;
|
||||
#define XEND_CONFIG_FILE "xend-config.sxp"
|
||||
#define XEND_PCI_CONFIG_PREFIX "xend-pci-"
|
||||
#define QEMU_IF_SCRIPT "qemu-ifup"
|
||||
#define XM_XML_ERROR "Invalid xml"
|
||||
|
||||
struct xenUnifiedDriver xenXMDriver = {
|
||||
xenXMOpen, /* open */
|
||||
@ -113,8 +120,8 @@ struct xenUnifiedDriver xenXMDriver = {
|
||||
xenXMDomainCreate, /* domainCreate */
|
||||
xenXMDomainDefineXML, /* domainDefineXML */
|
||||
xenXMDomainUndefine, /* domainUndefine */
|
||||
NULL, /* domainAttachDevice */
|
||||
NULL, /* domainDetachDevice */
|
||||
xenXMDomainAttachDevice, /* domainAttachDevice */
|
||||
xenXMDomainDetachDevice, /* domainDetachDevice */
|
||||
NULL, /* domainGetAutostart */
|
||||
NULL, /* domainSetAutostart */
|
||||
NULL, /* domainGetSchedulerType */
|
||||
@ -2515,6 +2522,635 @@ int xenXMNumOfDefinedDomains(virConnectPtr conn) {
|
||||
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 */
|
||||
/*
|
||||
* Local variables:
|
||||
|
@ -61,6 +61,9 @@ int xenXMDomainUndefine(virDomainPtr domain);
|
||||
virConfPtr xenXMParseXMLToConfig(virConnectPtr conn, const char *xml);
|
||||
char *xenXMDomainFormatXML(virConnectPtr conn, virConfPtr conf);
|
||||
|
||||
static int xenXMDomainAttachDevice(virDomainPtr domain, const char *xml);
|
||||
static int xenXMDomainDetachDevice(virDomainPtr domain, const char *xml);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user