From: Xu Wang <cngesaint(a)gmail.com>
Signed-off-by: Xu Wang <gesaint(a)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