Signed-off-by: Shivaprasad G Bhat <sbhat(a)linux.vnet.ibm.com>
---
src/conf/domain_conf.c | 169 ++++++++++++++++++++++++++++++++++++++++------
src/conf/domain_conf.h | 36 ++++++++++
src/libvirt_private.syms | 6 ++
3 files changed, 190 insertions(+), 21 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 3deed8eb4d..5f4a5127d4 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -963,6 +963,83 @@ virDomainXMLOptionClassDispose(void *obj)
(xmlopt->config.privFree)(xmlopt->config.priv);
}
+/* virDomainDeviceDefListAddCopy - add a *copy* of the device to this list */
+int
+virDomainDeviceDefListAddCopy(virDomainDeviceDefListPtr list,
+ virDomainDeviceDefPtr dev,
+ virDomainDeviceDefListDataPtr data)
+{
+ virDomainDeviceDefPtr copy = virDomainDeviceDefCopy(dev, data->def, data->caps,
data->xmlopt);
+
+ if (!copy)
+ return -1;
+ if (VIR_APPEND_ELEMENT(list->devs, list->count, copy) < 0) {
+ virDomainDeviceDefFree(copy);
+ return -1;
+ }
+ return 0;
+}
+
+void virDomainDeviceDefListFree(virDomainDeviceDefListPtr list)
+{
+ size_t i;
+
+ if (!list)
+ return;
+ for (i = 0; i < list->count; i++)
+ virDomainDeviceDefFree(list->devs[i]);
+ VIR_FREE(list->devs);
+}
+
+void virDomainDeviceDefListFreeShallow(virDomainDeviceDefListPtr list)
+{
+ size_t i;
+
+ if (!list)
+ return;
+ for (i = 0; i < list->count; i++)
+ VIR_FREE(list->devs[i]);
+}
+
+
+/* virDomainDeviceDefListIter - Iterate through the list with the callback*/
+int
+virDomainDeviceDefListIterate(virDomainDeviceDefListPtr list,
+ virDomainDeviceDefListIterCallback cb,
+ void *data)
+{
+ size_t i;
+
+ for (i = 0; i < list->count; i++)
+ if (cb(list->devs[i], data))
+ return -1;
+
+ return 0;
+}
+
+virDomainDeviceDefListPtr
+virDomainDeviceDefListCopy(virDomainDeviceDefListPtr list,
+ virDomainDeviceDefListDataPtr data)
+{
+ size_t i;
+ virDomainDeviceDefListPtr devlist = NULL;
+
+ if (list && (VIR_ALLOC(devlist) < 0))
+ goto cleanup;
+
+ for (i = 0; i < list->count; i++) {
+ if (virDomainDeviceDefListAddCopy(devlist, list->devs[i], data) < 0)
+ goto cleanup;
+ }
+
+ return devlist;
+ cleanup:
+ virDomainDeviceDefListFree(devlist);
+ return NULL;
+}
+
+
+
/**
* virDomainKeyWrapCipherDefParseXML:
*
@@ -15677,25 +15754,16 @@ virDomainIOMMUDefParseXML(xmlNodePtr node,
return ret;
}
-
-virDomainDeviceDefPtr
-virDomainDeviceDefParse(const char *xmlStr,
- const virDomainDef *def,
- virCapsPtr caps,
- virDomainXMLOptionPtr xmlopt,
- unsigned int flags)
+static
+virDomainDeviceDefPtr virDomainDeviceDefParseXML(xmlNodePtr node,
+ const virDomainDef *def,
+ virCapsPtr caps,
+ virDomainXMLOptionPtr xmlopt,
+ xmlXPathContextPtr ctxt,
+ unsigned int flags)
{
- xmlDocPtr xml;
- xmlNodePtr node;
- xmlXPathContextPtr ctxt = NULL;
virDomainDeviceDefPtr dev = NULL;
char *netprefix;
-
- if (!(xml = virXMLParseStringCtxt(xmlStr, _("(device_definition)"),
&ctxt)))
- goto error;
-
- node = ctxt->node;
-
if (VIR_ALLOC(dev) < 0)
goto error;
@@ -15846,14 +15914,33 @@ virDomainDeviceDefParse(const char *xmlStr,
if (virDomainDeviceDefValidate(dev, def, flags, xmlopt) < 0)
goto error;
- cleanup:
+ return dev;
+ error:
+ return NULL;
+}
+
+virDomainDeviceDefPtr
+virDomainDeviceDefParse(const char *xmlStr,
+ const virDomainDef *def,
+ virCapsPtr caps,
+ virDomainXMLOptionPtr xmlopt,
+ unsigned int flags)
+{
+ xmlDocPtr xml;
+ xmlNodePtr node;
+ xmlXPathContextPtr ctxt = NULL;
+ virDomainDeviceDefPtr dev = NULL;
+
+ if (!(xml = virXMLParseStringCtxt(xmlStr, _("(device_definition)"),
&ctxt)))
+ return NULL;
+
+ node = ctxt->node;
+
+ dev = virDomainDeviceDefParseXML(node, def, caps, xmlopt, ctxt, flags);
+
xmlFreeDoc(xml);
xmlXPathFreeContext(ctxt);
return dev;
-
- error:
- VIR_FREE(dev);
- goto cleanup;
}
@@ -29394,3 +29481,43 @@ virDomainDiskTranslateSourcePool(virDomainDiskDefPtr def)
virStoragePoolDefFree(pooldef);
return ret;
}
+
+virDomainDeviceDefListPtr
+virDomainDeviceDefParseXMLMany(const char *xml,
+ const virDomainDef *def,
+ virCapsPtr caps,
+ virDomainXMLOptionPtr xmlopt,
+ unsigned int flags)
+{
+ xmlXPathContextPtr ctxt = NULL;
+ xmlDocPtr xmlPtr;
+ xmlNodePtr node, root;
+ virDomainDeviceDefPtr dev = NULL;
+ virDomainDeviceDefListPtr devlist;
+
+ if (!(xmlPtr = virXMLParseStringCtxt(xml, _("(device_definition)"),
&ctxt)))
+ return NULL;
+
+ if (VIR_ALLOC(devlist) < 0)
+ goto exit;
+
+ root = xmlDocGetRootElement(xmlPtr);
+ node = root->children;
+ while (node) {
+ if (node->type == XML_ELEMENT_NODE) {
+ dev = virDomainDeviceDefParseXML(node, def, caps, xmlopt, ctxt, flags);
+ if (VIR_APPEND_ELEMENT(devlist->devs, devlist->count, dev) < 0) {
+ virDomainDeviceDefFree(dev);
+ virDomainDeviceDefListFree(devlist);
+ goto exit;
+ }
+ dev = NULL;
+ }
+ node = node->next;
+ }
+
+ exit:
+ xmlFreeDoc(xmlPtr);
+ xmlXPathFreeContext(ctxt);
+ return devlist;
+}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index a3d686a5ca..828fe9f6d8 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2561,6 +2561,37 @@ typedef int (*virDomainDefPostParseBasicCallback)(virDomainDefPtr
def,
virCapsPtr caps,
void *opaque);
+typedef struct _virDomainDeviceDefListData virDomainDeviceDefListData;
+typedef virDomainDeviceDefListData *virDomainDeviceDefListDataPtr;
+struct _virDomainDeviceDefListData {
+ const virDomainDef *def;
+ virCapsPtr caps;
+ virDomainXMLOptionPtr xmlopt;
+};
+
+struct virDomainDeviceDefList {
+ virDomainDeviceDefPtr *devs;
+ size_t count;
+};
+typedef struct virDomainDeviceDefList *virDomainDeviceDefListPtr;
+
+typedef int (*virDomainDeviceDefListIterCallback)(virDomainDeviceDefPtr dev,
+ void *opaque);
+int virDomainDeviceDefListIterate(virDomainDeviceDefListPtr devlist,
+ virDomainDeviceDefListIterCallback cb,
+ void *data);
+int
+virDomainDeviceDefListAddCopy(virDomainDeviceDefListPtr list,
+ virDomainDeviceDefPtr dev,
+ virDomainDeviceDefListDataPtr data);
+virDomainDeviceDefListPtr
+virDomainDeviceDefListCopy(virDomainDeviceDefListPtr list,
+ virDomainDeviceDefListDataPtr data);
+
+void virDomainDeviceDefListFree(virDomainDeviceDefListPtr list);
+void virDomainDeviceDefListFreeShallow(virDomainDeviceDefListPtr list);
+
+
/* Called once after everything else has been parsed, for adjusting
* overall domain defaults.
* @parseOpaque is opaque data passed by virDomainDefParse* caller,
@@ -2935,6 +2966,11 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(const char *xmlStr,
virCapsPtr caps,
virDomainXMLOptionPtr xmlopt,
unsigned int flags);
+virDomainDeviceDefListPtr virDomainDeviceDefParseXMLMany(const char *xmlStr,
+ const virDomainDef *def,
+ virCapsPtr caps,
+ virDomainXMLOptionPtr xmlopt,
+ unsigned int flags);
virStorageSourcePtr virDomainDiskDefSourceParse(const char *xmlStr,
const virDomainDef *def,
virDomainXMLOptionPtr xmlopt,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index b0e8f2ca61..d1ff2f5f99 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -300,7 +300,13 @@ virDomainDeviceAddressTypeToString;
virDomainDeviceAliasIsUserAlias;
virDomainDeviceDefCopy;
virDomainDeviceDefFree;
+virDomainDeviceDefListAddCopy;
+virDomainDeviceDefListCopy;
+virDomainDeviceDefListFree;
+virDomainDeviceDefListFreeShallow;
+virDomainDeviceDefListIterate;
virDomainDeviceDefParse;
+virDomainDeviceDefParseXMLMany;
virDomainDeviceFindSCSIController;
virDomainDeviceGetInfo;
virDomainDeviceInfoIterate;