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>
|
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
28
NEWS
@ -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.
|
||||||
|
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user