From 21213a4b13861344cca287def69e0c1a62ca703d Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Thu, 2 May 2013 10:56:31 +0100 Subject: [PATCH] Convert Xen domain device hotplug driver methods to use virDomainDefPtr Introduce use of a virDomainDefPtr in the domain hotplug APIs to simplify introduction of ACL security checks. The virDomainPtr cannot be safely used, since the app may have supplied mis-matching name/uuid/id fields. eg the name points to domain X, while the uuid points to domain Y. Resolving the virDomainPtr to a virDomainDefPtr ensures a consistent name/uuid/id set. Signed-off-by: Daniel P. Berrange --- src/xen/xen_driver.c | 68 +++++++++++++++++++++++------ src/xen/xend_internal.c | 94 ++++++++++++++++++++++------------------- src/xen/xend_internal.h | 10 +++-- src/xen/xm_internal.c | 28 ++++++------ src/xen/xm_internal.h | 6 ++- 5 files changed, 134 insertions(+), 72 deletions(-) diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 5adcb9b664..a7e02523e5 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -1693,6 +1693,8 @@ xenUnifiedDomainAttachDevice(virDomainPtr dom, const char *xml) { xenUnifiedPrivatePtr priv = dom->conn->privateData; unsigned int flags = VIR_DOMAIN_DEVICE_MODIFY_LIVE; + virDomainDefPtr def = NULL; + int ret = -1; /* * HACK: xend with xendConfigVersion >= 3 does not support changing live @@ -1702,12 +1704,17 @@ xenUnifiedDomainAttachDevice(virDomainPtr dom, const char *xml) if (priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4) flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG; - if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) - return xenXMDomainAttachDeviceFlags(dom, xml, flags); - else - return xenDaemonAttachDeviceFlags(dom, xml, flags); + if (!(def = xenGetDomainDefForDom(dom))) + goto cleanup; - return -1; + if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) + ret = xenXMDomainAttachDeviceFlags(dom->conn, def, xml, flags); + else + ret = xenDaemonAttachDeviceFlags(dom->conn, def, xml, flags); + +cleanup: + virDomainDefFree(def); + return ret; } static int @@ -1715,11 +1722,20 @@ xenUnifiedDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, unsigned int flags) { xenUnifiedPrivatePtr priv = dom->conn->privateData; + virDomainDefPtr def = NULL; + int ret = -1; + + if (!(def = xenGetDomainDefForDom(dom))) + goto cleanup; if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) - return xenXMDomainAttachDeviceFlags(dom, xml, flags); + ret = xenXMDomainAttachDeviceFlags(dom->conn, def, xml, flags); else - return xenDaemonAttachDeviceFlags(dom, xml, flags); + ret = xenDaemonAttachDeviceFlags(dom->conn, def, xml, flags); + +cleanup: + virDomainDefFree(def); + return ret; } static int @@ -1727,6 +1743,8 @@ xenUnifiedDomainDetachDevice(virDomainPtr dom, const char *xml) { xenUnifiedPrivatePtr priv = dom->conn->privateData; unsigned int flags = VIR_DOMAIN_DEVICE_MODIFY_LIVE; + virDomainDefPtr def = NULL; + int ret = -1; /* * HACK: xend with xendConfigVersion >= 3 does not support changing live @@ -1736,10 +1754,17 @@ xenUnifiedDomainDetachDevice(virDomainPtr dom, const char *xml) if (priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4) flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG; + if (!(def = xenGetDomainDefForDom(dom))) + goto cleanup; + if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) - return xenXMDomainDetachDeviceFlags(dom, xml, flags); + ret = xenXMDomainDetachDeviceFlags(dom->conn, def, xml, flags); else - return xenDaemonDetachDeviceFlags(dom, xml, flags); + ret = xenDaemonDetachDeviceFlags(dom->conn, def, xml, flags); + +cleanup: + virDomainDefFree(def); + return ret; } static int @@ -1747,18 +1772,37 @@ xenUnifiedDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, unsigned int flags) { xenUnifiedPrivatePtr priv = dom->conn->privateData; + virDomainDefPtr def = NULL; + int ret = -1; + + if (!(def = xenGetDomainDefForDom(dom))) + goto cleanup; if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) - return xenXMDomainDetachDeviceFlags(dom, xml, flags); + ret = xenXMDomainDetachDeviceFlags(dom->conn, def, xml, flags); else - return xenDaemonDetachDeviceFlags(dom, xml, flags); + ret = xenDaemonDetachDeviceFlags(dom->conn, def, xml, flags); + +cleanup: + virDomainDefFree(def); + return ret; } static int xenUnifiedDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, unsigned int flags) { - return xenDaemonUpdateDeviceFlags(dom, xml, flags); + virDomainDefPtr def = NULL; + int ret = -1; + + if (!(def = xenGetDomainDefForDom(dom))) + goto cleanup; + + ret = xenDaemonUpdateDeviceFlags(dom->conn, def, xml, flags); + +cleanup: + virDomainDefFree(def); + return ret; } static int diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index c296566a2c..a654190deb 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -70,7 +70,8 @@ #define XEND_RCV_BUF_MAX_LEN (256 * 1024) static int -virDomainXMLDevID(virDomainPtr domain, virDomainDeviceDefPtr dev, char *class, +virDomainXMLDevID(virConnectPtr conn, virDomainDefPtr domain, + virDomainDeviceDefPtr dev, char *class, char *ref, int ref_len); /** @@ -2205,7 +2206,8 @@ xenDaemonCreateXML(virConnectPtr conn, virDomainDefPtr def) /** * xenDaemonAttachDeviceFlags: - * @domain: pointer to domain object + * @conn: the connection object + * @minidef: domain configuration * @xml: pointer to XML description of device * @flags: an OR'ed set of virDomainDeviceModifyFlags * @@ -2215,11 +2217,12 @@ xenDaemonCreateXML(virConnectPtr conn, virDomainDefPtr def) * Returns 0 in case of success, -1 in case of failure. */ int -xenDaemonAttachDeviceFlags(virDomainPtr domain, +xenDaemonAttachDeviceFlags(virConnectPtr conn, + virDomainDefPtr minidef, const char *xml, unsigned int flags) { - xenUnifiedPrivatePtr priv = domain->conn->privateData; + xenUnifiedPrivatePtr priv = conn->privateData; char *sexpr = NULL; int ret = -1; virDomainDeviceDefPtr dev = NULL; @@ -2230,7 +2233,7 @@ xenDaemonAttachDeviceFlags(virDomainPtr domain, virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1); - if (domain->id < 0) { + if (minidef->id < 0) { /* Cannot modify live config if domain is inactive */ if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", @@ -2260,9 +2263,9 @@ xenDaemonAttachDeviceFlags(virDomainPtr domain, } } - if (!(def = xenDaemonDomainFetch(domain->conn, - domain->id, - domain->name, + if (!(def = xenDaemonDomainFetch(conn, + minidef->id, + minidef->name, NULL))) goto cleanup; @@ -2288,7 +2291,7 @@ xenDaemonAttachDeviceFlags(virDomainPtr domain, break; case VIR_DOMAIN_DEVICE_NET: - if (xenFormatSxprNet(domain->conn, + if (xenFormatSxprNet(conn, dev->data.net, &buf, STREQ(def->os.type, "hvm") ? 1 : 0, @@ -2333,9 +2336,9 @@ xenDaemonAttachDeviceFlags(virDomainPtr domain, sexpr = virBufferContentAndReset(&buf); - if (virDomainXMLDevID(domain, dev, class, ref, sizeof(ref))) { + if (virDomainXMLDevID(conn, minidef, dev, class, ref, sizeof(ref))) { /* device doesn't exist, define it */ - ret = xend_op(domain->conn, domain->name, "op", "device_create", + ret = xend_op(conn, def->name, "op", "device_create", "config", sexpr, NULL); } else { if (dev->data.disk->device != VIR_DOMAIN_DISK_DEVICE_CDROM) { @@ -2343,7 +2346,7 @@ xenDaemonAttachDeviceFlags(virDomainPtr domain, _("target '%s' already exists"), target); } else { /* device exists, attempt to modify it */ - ret = xend_op(domain->conn, domain->name, "op", "device_configure", + ret = xend_op(conn, minidef->name, "op", "device_configure", "config", sexpr, "dev", ref, NULL); } } @@ -2358,7 +2361,8 @@ cleanup: /** * xenDaemonUpdateDeviceFlags: - * @domain: pointer to domain object + * @conn: the connection object + * @minidef: domain configuration * @xml: pointer to XML description of device * @flags: an OR'ed set of virDomainDeviceModifyFlags * @@ -2368,11 +2372,12 @@ cleanup: * Returns 0 in case of success, -1 in case of failure. */ int -xenDaemonUpdateDeviceFlags(virDomainPtr domain, +xenDaemonUpdateDeviceFlags(virConnectPtr conn, + virDomainDefPtr minidef, const char *xml, unsigned int flags) { - xenUnifiedPrivatePtr priv = domain->conn->privateData; + xenUnifiedPrivatePtr priv = conn->privateData; char *sexpr = NULL; int ret = -1; virDomainDeviceDefPtr dev = NULL; @@ -2383,7 +2388,7 @@ xenDaemonUpdateDeviceFlags(virDomainPtr domain, virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE | VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); - if (domain->id < 0) { + if (minidef->id < 0) { /* Cannot modify live config if domain is inactive */ if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", @@ -2413,9 +2418,9 @@ xenDaemonUpdateDeviceFlags(virDomainPtr domain, } } - if (!(def = xenDaemonDomainFetch(domain->conn, - domain->id, - domain->name, + if (!(def = xenDaemonDomainFetch(conn, + minidef->id, + minidef->name, NULL))) goto cleanup; @@ -2441,13 +2446,13 @@ xenDaemonUpdateDeviceFlags(virDomainPtr domain, sexpr = virBufferContentAndReset(&buf); - if (virDomainXMLDevID(domain, dev, class, ref, sizeof(ref))) { + if (virDomainXMLDevID(conn, minidef, dev, class, ref, sizeof(ref))) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("requested device does not exist")); goto cleanup; } else { /* device exists, attempt to modify it */ - ret = xend_op(domain->conn, domain->name, "op", "device_configure", + ret = xend_op(conn, minidef->name, "op", "device_configure", "config", sexpr, "dev", ref, NULL); } @@ -2460,7 +2465,8 @@ cleanup: /** * xenDaemonDetachDeviceFlags: - * @domain: pointer to domain object + * @conn: the connection object + * @minidef: domain configuration * @xml: pointer to XML description of device * @flags: an OR'ed set of virDomainDeviceModifyFlags * @@ -2469,11 +2475,12 @@ cleanup: * Returns 0 in case of success, -1 in case of failure. */ int -xenDaemonDetachDeviceFlags(virDomainPtr domain, +xenDaemonDetachDeviceFlags(virConnectPtr conn, + virDomainDefPtr minidef, const char *xml, unsigned int flags) { - xenUnifiedPrivatePtr priv = domain->conn->privateData; + xenUnifiedPrivatePtr priv = conn->privateData; char class[8], ref[80]; virDomainDeviceDefPtr dev = NULL; virDomainDefPtr def = NULL; @@ -2483,7 +2490,7 @@ xenDaemonDetachDeviceFlags(virDomainPtr domain, virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1); - if (domain->id < 0) { + if (minidef->id < 0) { /* Cannot modify live config if domain is inactive */ if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", @@ -2513,9 +2520,9 @@ xenDaemonDetachDeviceFlags(virDomainPtr domain, } } - if (!(def = xenDaemonDomainFetch(domain->conn, - domain->id, - domain->name, + if (!(def = xenDaemonDomainFetch(conn, + minidef->id, + minidef->name, NULL))) goto cleanup; @@ -2523,7 +2530,7 @@ xenDaemonDetachDeviceFlags(virDomainPtr domain, VIR_DOMAIN_XML_INACTIVE))) goto cleanup; - if (virDomainXMLDevID(domain, dev, class, ref, sizeof(ref))) + if (virDomainXMLDevID(conn, minidef, dev, class, ref, sizeof(ref))) goto cleanup; if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) { @@ -2537,12 +2544,12 @@ xenDaemonDetachDeviceFlags(virDomainPtr domain, goto cleanup; } xendev = virBufferContentAndReset(&buf); - ret = xend_op(domain->conn, domain->name, "op", "device_configure", + ret = xend_op(conn, minidef->name, "op", "device_configure", "config", xendev, "dev", ref, NULL); VIR_FREE(xendev); } else { - ret = xend_op(domain->conn, domain->name, "op", "device_destroy", + ret = xend_op(conn, minidef->name, "op", "device_destroy", "type", class, "dev", ref, "force", "0", "rm_cfg", "1", NULL); } @@ -3347,13 +3354,14 @@ xenDaemonDomainBlockPeek(virDomainPtr domain, * Returns 0 in case of success, -1 in case of failure. */ static int -virDomainXMLDevID(virDomainPtr domain, +virDomainXMLDevID(virConnectPtr conn, + virDomainDefPtr def, virDomainDeviceDefPtr dev, char *class, char *ref, int ref_len) { - xenUnifiedPrivatePtr priv = domain->conn->privateData; + xenUnifiedPrivatePtr priv = conn->privateData; char *xref; char *tmp; @@ -3370,7 +3378,7 @@ virDomainXMLDevID(virDomainPtr domain, if (dev->data.disk->dst == NULL) return -1; xenUnifiedLock(priv); - xref = xenStoreDomainGetDiskID(domain->conn, domain->id, + xref = xenStoreDomainGetDiskID(conn, def->id, dev->data.disk->dst); xenUnifiedUnlock(priv); if (xref == NULL) @@ -3382,13 +3390,13 @@ virDomainXMLDevID(virDomainPtr domain, return -1; } else if (dev->type == VIR_DOMAIN_DEVICE_NET) { char mac[VIR_MAC_STRING_BUFLEN]; - virDomainNetDefPtr def = dev->data.net; - virMacAddrFormat(&def->mac, mac); + virDomainNetDefPtr netdef = dev->data.net; + virMacAddrFormat(&netdef->mac, mac); strcpy(class, "vif"); xenUnifiedLock(priv); - xref = xenStoreDomainGetNetworkID(domain->conn, domain->id, mac); + xref = xenStoreDomainGetNetworkID(conn, def->id, mac); xenUnifiedUnlock(priv); if (xref == NULL) return -1; @@ -3401,13 +3409,13 @@ virDomainXMLDevID(virDomainPtr domain, dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) { char *bdf; - virDomainHostdevDefPtr def = dev->data.hostdev; + virDomainHostdevDefPtr hostdef = dev->data.hostdev; if (virAsprintf(&bdf, "%04x:%02x:%02x.%0x", - def->source.subsys.u.pci.addr.domain, - def->source.subsys.u.pci.addr.bus, - def->source.subsys.u.pci.addr.slot, - def->source.subsys.u.pci.addr.function) < 0) { + hostdef->source.subsys.u.pci.addr.domain, + hostdef->source.subsys.u.pci.addr.bus, + hostdef->source.subsys.u.pci.addr.slot, + hostdef->source.subsys.u.pci.addr.function) < 0) { virReportOOMError(); return -1; } @@ -3415,7 +3423,7 @@ virDomainXMLDevID(virDomainPtr domain, strcpy(class, "pci"); xenUnifiedLock(priv); - xref = xenStoreDomainGetPCIID(domain->conn, domain->id, bdf); + xref = xenStoreDomainGetPCIID(conn, def->id, bdf); xenUnifiedUnlock(priv); VIR_FREE(bdf); if (xref == NULL) diff --git a/src/xen/xend_internal.h b/src/xen/xend_internal.h index 65a536378a..f5b494b5f4 100644 --- a/src/xen/xend_internal.h +++ b/src/xen/xend_internal.h @@ -133,10 +133,12 @@ int xenDaemonListDefinedDomains(virConnectPtr conn, char **const names, int maxnames); -int xenDaemonAttachDeviceFlags(virDomainPtr domain, +int xenDaemonAttachDeviceFlags(virConnectPtr conn, + virDomainDefPtr def, const char *xml, unsigned int flags); -int xenDaemonDetachDeviceFlags(virDomainPtr domain, +int xenDaemonDetachDeviceFlags(virConnectPtr conn, + virDomainDefPtr def, const char *xml, unsigned int flags); @@ -168,7 +170,9 @@ int xenDaemonDomainGetVcpus (virConnectPtr conn, int maxinfo, unsigned char *cpumaps, int maplen); -int xenDaemonUpdateDeviceFlags(virDomainPtr domain, const char *xml, +int xenDaemonUpdateDeviceFlags(virConnectPtr conn, + virDomainDefPtr def, + const char *xml, unsigned int flags); int xenDaemonDomainGetAutostart (virDomainPtr dom, int *autostart); diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c index 7b32be4c0c..c9950556be 100644 --- a/src/xen/xm_internal.c +++ b/src/xen/xm_internal.c @@ -1211,7 +1211,8 @@ cleanup: /** * xenXMDomainAttachDeviceFlags: - * @domain: pointer to domain object + * @conn: the connection object + * @minidef: domain configuration * @xml: pointer to XML description of device * @flags: an OR'ed set of virDomainDeviceModifyFlags * @@ -1223,7 +1224,8 @@ cleanup: * Returns 0 in case of success, -1 in case of failure. */ int -xenXMDomainAttachDeviceFlags(virDomainPtr domain, +xenXMDomainAttachDeviceFlags(virConnectPtr conn, + virDomainDefPtr minidef, const char *xml, unsigned int flags) { @@ -1232,12 +1234,12 @@ xenXMDomainAttachDeviceFlags(virDomainPtr domain, int ret = -1; virDomainDeviceDefPtr dev = NULL; virDomainDefPtr def; - xenUnifiedPrivatePtr priv = domain->conn->privateData; + xenUnifiedPrivatePtr priv = conn->privateData; virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1); if ((flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) || - (domain->id != -1 && flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT)) { + (minidef->id != -1 && flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Xm driver only supports modifying persistent config")); return -1; @@ -1245,7 +1247,7 @@ xenXMDomainAttachDeviceFlags(virDomainPtr domain, xenUnifiedLock(priv); - if (!(filename = virHashLookup(priv->nameConfigMap, domain->name))) + if (!(filename = virHashLookup(priv->nameConfigMap, minidef->name))) goto cleanup; if (!(entry = virHashLookup(priv->configCache, filename))) goto cleanup; @@ -1288,7 +1290,7 @@ xenXMDomainAttachDeviceFlags(virDomainPtr domain, /* If this fails, should we try to undo our changes to the * in-memory representation of the config file. I say not! */ - if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0) + if (xenXMConfigSaveFile(conn, entry->filename, entry->def) < 0) goto cleanup; ret = 0; @@ -1302,7 +1304,8 @@ xenXMDomainAttachDeviceFlags(virDomainPtr domain, /** * xenXMDomainDetachDeviceFlags: - * @domain: pointer to domain object + * @conn: the connection object + * @minidef: domain configuration * @xml: pointer to XML description of device * @flags: an OR'ed set of virDomainDeviceModifyFlags * @@ -1313,7 +1316,8 @@ xenXMDomainAttachDeviceFlags(virDomainPtr domain, * Returns 0 in case of success, -1 in case of failure. */ int -xenXMDomainDetachDeviceFlags(virDomainPtr domain, +xenXMDomainDetachDeviceFlags(virConnectPtr conn, + virDomainDefPtr minidef, const char *xml, unsigned int flags) { @@ -1323,12 +1327,12 @@ xenXMDomainDetachDeviceFlags(virDomainPtr domain, virDomainDefPtr def; int ret = -1; int i; - xenUnifiedPrivatePtr priv = domain->conn->privateData; + xenUnifiedPrivatePtr priv = conn->privateData; virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1); if ((flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) || - (domain->id != -1 && flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT)) { + (minidef->id != -1 && flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Xm driver only supports modifying persistent config")); return -1; @@ -1336,7 +1340,7 @@ xenXMDomainDetachDeviceFlags(virDomainPtr domain, xenUnifiedLock(priv); - if (!(filename = virHashLookup(priv->nameConfigMap, domain->name))) + if (!(filename = virHashLookup(priv->nameConfigMap, minidef->name))) goto cleanup; if (!(entry = virHashLookup(priv->configCache, filename))) goto cleanup; @@ -1394,7 +1398,7 @@ xenXMDomainDetachDeviceFlags(virDomainPtr domain, /* If this fails, should we try to undo our changes to the * in-memory representation of the config file. I say not! */ - if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0) + if (xenXMConfigSaveFile(conn, entry->filename, entry->def) < 0) goto cleanup; ret = 0; diff --git a/src/xen/xm_internal.h b/src/xen/xm_internal.h index 28087d3921..7d64dc618e 100644 --- a/src/xen/xm_internal.h +++ b/src/xen/xm_internal.h @@ -85,11 +85,13 @@ int xenXMDomainBlockPeek (virDomainPtr dom, const char *path, unsigned long long int xenXMDomainGetAutostart(virDomainPtr dom, int *autostart); int xenXMDomainSetAutostart(virDomainPtr dom, int autostart); -int xenXMDomainAttachDeviceFlags(virDomainPtr domain, +int xenXMDomainAttachDeviceFlags(virConnectPtr conn, + virDomainDefPtr def, const char *xml, unsigned int flags); -int xenXMDomainDetachDeviceFlags(virDomainPtr domain, +int xenXMDomainDetachDeviceFlags(virConnectPtr conn, + virDomainDefPtr def, const char *xml, unsigned int flags);