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