[Libvirt-cim] [PATCH 04/20] Fix xml parsing algorithm for parse_fs_device()

John Ferlan jferlan at redhat.com
Fri Nov 15 00:23:53 UTC 2013


From: Xu Wang <cngesaint at gmail.com>

Signed-off-by: Xu Wang <gesaint at linux.vnet.ibm.com>
---
 libxkutil/device_parsing.c | 156 ++++++++++++++++++++++++++++++++++++++-------
 libxkutil/device_parsing.h |   1 +
 2 files changed, 134 insertions(+), 23 deletions(-)

diff --git a/libxkutil/device_parsing.c b/libxkutil/device_parsing.c
index 610712f..20b35e1 100644
--- a/libxkutil/device_parsing.c
+++ b/libxkutil/device_parsing.c
@@ -116,6 +116,7 @@ static void cleanup_disk_device(struct disk_device *dev)
         free(dev->bus_type);
         free(dev->access_mode);
         cleanup_device_address(&dev->address);
+        cleanup_others(dev->others);
 }
 
 static void cleanup_vsi_device(struct vsi_device *dev)
@@ -453,6 +454,45 @@ static int parse_device_address(xmlNode *anode, struct device_address *devaddr)
 }
 
 /*
+ * Device addresses can have many forms based on the 'type' field, so rather
+ * than try to create a function that could parse each particular option, we
+ * will just fetch all the name/value pairs with "address" as the parent name
+ * and store them in a devaddr array to be parsed elsewhere.
+ *
+ * This function will also assume that the 'id' and 'parentid' values are -1
+ * at least for now
+ */
+static int fetch_device_address_from_others(struct others **head,
+                                            struct device_address *devaddr)
+{
+        struct others *tmp = *head;
+
+        while (tmp) {
+                if (compare_param_int(tmp->id, -1) &&
+                    compare_param_int(tmp->parent_id, -1) &&
+                    compare_param_str(tmp->parent_name, "address") &&
+                    tmp->type == TYPE_PROP &&
+                    tmp->status == ACTIVE) {
+
+                    if (!add_device_address_property(devaddr, tmp->name,
+                                                     tmp->value))
+                            goto err;
+
+                    /* Since we're now managing it... */
+                    tmp->status = INACTIVE;
+                }
+                tmp = tmp->next;
+        }
+
+        return 1;
+
+ err:
+        cleanup_device_address(devaddr);
+
+        return 0;
+}
+
+/*
  * This function is just used for debugging. If you found something wrong
  * please call this function and check the result of output in the logs.
  */
@@ -753,7 +793,8 @@ static int parse_fs_device(xmlNode *dnode, struct virt_device **vdevs)
 {
         struct virt_device *vdev = NULL;
         struct disk_device *ddev = NULL;
-        xmlNode *child = NULL;
+
+        CU_DEBUG("Enter parse_fs_device().");
 
         vdev = calloc(1, sizeof(*vdev));
         if (vdev == NULL)
@@ -761,37 +802,106 @@ static int parse_fs_device(xmlNode *dnode, struct virt_device **vdevs)
 
         ddev = (&vdev->dev.disk);
 
-        ddev->type = get_attr_value(dnode, "type");
+        ddev->others = parse_data_to_others(ddev->others,
+                                            dnode,
+                                            0,
+                                            BAD_CAST "devices");
+        if (ddev->others == NULL) {
+                CU_DEBUG("parse xml failed.");
+                goto err;
+        }
+
+        /* fetch out <filesystem> tag from others. It will be removed
+         * after others management finished. */
+        fetch_from_others(&ddev->others,
+                          -1,
+                          "filesystem",
+                          TYPE_NODE,
+                          -1,
+                          "devices");
+
+        ddev->type = fetch_from_others(&ddev->others,
+                                       -1,
+                                       "type",
+                                       TYPE_PROP,
+                                       -1,
+                                       (char *)dnode->name);
         if (ddev->type == NULL) {
                 CU_DEBUG("No type");
                 goto err;
         }
 
-        ddev->access_mode = get_attr_value(dnode, "accessmode");
+        ddev->access_mode = fetch_from_others(&ddev->others,
+                                              -1,
+                                              "accessmode",
+                                              TYPE_PROP,
+                                              -1,
+                                              (char *)dnode->name);
+
+        if (seek_in_others(&ddev->others,
+                           -1,
+                           "source",
+                           TYPE_NODE,
+                           -1,
+                           (char *)dnode->name)) {
+                ddev->source = fetch_from_others(&ddev->others,
+                                                 -1,
+                                                 "dir",
+                                                 TYPE_PROP,
+                                                 -1,
+                                                 "source");
+
+
+                if (ddev->source == NULL) {
+                        CU_DEBUG("no source dir");
+                        goto err;
+                }
+        }
 
-        for (child = dnode->children; child != NULL; child = child->next) {
-                if (XSTREQ(child->name, "source")) {
-                        ddev->source = get_attr_value(child, "dir");
-                        if (ddev->source == NULL) {
-                                CU_DEBUG("No source dir");
-                                goto err;
-                        }
-                } else if (XSTREQ(child->name, "target")) {
-                        ddev->virtual_dev = get_attr_value(child, "dir");
-                        if (ddev->virtual_dev == NULL) {
-                                CU_DEBUG("No target dir");
-                                goto err;
-                        }
-                } else if (XSTREQ(child->name, "driver")) {
-                       ddev->driver_type = get_attr_value(child, "type");
-                } else if (XSTREQ(child->name, "address")) {
-                        parse_device_address(child, &ddev->address);
+        if (seek_in_others(&ddev->others,
+                           -1,
+                           "target",
+                           TYPE_NODE,
+                           -1,
+                           (char *)dnode->name)) {
+                ddev->virtual_dev = fetch_from_others(&ddev->others,
+                                                      -1,
+                                                      "dir",
+                                                      TYPE_PROP,
+                                                      -1,
+                                                      "target");
+
+                if (ddev->virtual_dev == NULL) {
+                        CU_DEBUG("no target dir");
+                        goto err;
                 }
         }
 
-        if ((ddev->source == NULL) || (ddev->virtual_dev == NULL)) {
-                CU_DEBUG("S: %s D: %s", ddev->source, ddev->virtual_dev);
-                goto err;
+        if (seek_in_others(&ddev->others,
+                           -1,
+                           "driver",
+                           TYPE_NODE,
+                           -1,
+                           (char *)dnode->name)) {
+                ddev->driver_type = fetch_from_others(&ddev->others,
+                                                      -1,
+                                                      "type",
+                                                      TYPE_PROP,
+                                                      -1,
+                                                      "driver");
+        }
+
+        if (seek_in_others(&ddev->others,
+                           -1,
+                           "address",
+                           TYPE_NODE,
+                           -1,
+                           (char *)dnode->name)) {
+                if (!fetch_device_address_from_others(&ddev->others,
+                                                      &ddev->address)) {
+                        CU_DEBUG("error fetching device address");
+                        goto err;
+                }
         }
 
         ddev->disk_type = DISK_FS;
diff --git a/libxkutil/device_parsing.h b/libxkutil/device_parsing.h
index 92d8638..6e8fe25 100644
--- a/libxkutil/device_parsing.h
+++ b/libxkutil/device_parsing.h
@@ -84,6 +84,7 @@ struct disk_device {
         char *cache;
         char *access_mode; /* access modes for DISK_FS (filesystem) type */
         struct device_address address;
+        struct others *others;
 };
 
 struct net_device {
-- 
1.8.3.1




More information about the Libvirt-cim mailing list