[PATCH 0 of 4] Add support for new storage volume template RASDS

There's not too much that can be done with the template RASD until support for the image creation methods are in place. For now, the new storage volume template RASDs can be viewed by following SDC: wbemcli ai -ac KVM_SettingsDefineCapabilities 'http://localhost/root/virt:KVM_AllocationCapabilities.InstanceID="DiskPool/data"' -nl

# HG changeset patch # User Kaitlin Rupert <karupert@us.ibm.com> # Date 1248123211 25200 # Node ID 5eefe23b2be112a925b834931897e61b97d2cd06 # Parent 1f48bb4249af07d7598308b8ac7c1aad5e2e3743 Make get_node_content(), get_attr_value() non static This makes these functions to be available for use in pool_parsing.c Also, move XSTREQ() and STRPROP() to device_parsing.h so it can be used in pool_parsing.c Signed-off-by: Kaitlin Rupert <karupert@us.ibm.com> diff -r 1f48bb4249af -r 5eefe23b2be1 libxkutil/device_parsing.c --- a/libxkutil/device_parsing.c Tue Jul 14 22:13:01 2009 -0700 +++ b/libxkutil/device_parsing.c Mon Jul 20 13:53:31 2009 -0700 @@ -27,9 +27,6 @@ #include <stdbool.h> #include <inttypes.h> #include <sys/stat.h> -#include <libxml/tree.h> -#include <libxml/parser.h> -#include <libxml/xpath.h> #include <libcmpiutil/libcmpiutil.h> @@ -49,7 +46,6 @@ #define DEFAULT_BRIDGE "xenbr0" #define DEFAULT_NETWORK "default" -#define XSTREQ(x, y) (STREQ((char *)x, y)) #define MAX(a,b) (((a)>(b))?(a):(b)) static void cleanup_disk_device(struct disk_device *dev) @@ -123,7 +119,7 @@ *_devs = NULL; } -static char *get_attr_value(xmlNode *node, char *attrname) +char *get_attr_value(xmlNode *node, char *attrname) { char *buf = NULL; char *ret = NULL; @@ -137,7 +133,7 @@ return ret; } -static char *get_node_content(xmlNode *node) +char *get_node_content(xmlNode *node) { char *buf = NULL; xmlChar *ret = NULL; @@ -809,8 +805,6 @@ return 1; } -#define STRPROP(d, p, n) (d->p = get_node_content(n)) - static int parse_os(struct domain *dominfo, xmlNode *os) { xmlNode *child; diff -r 1f48bb4249af -r 5eefe23b2be1 libxkutil/device_parsing.h --- a/libxkutil/device_parsing.h Tue Jul 14 22:13:01 2009 -0700 +++ b/libxkutil/device_parsing.h Mon Jul 20 13:53:31 2009 -0700 @@ -27,6 +27,9 @@ #include <stdint.h> #include <stdbool.h> #include <libvirt/libvirt.h> +#include <libxml/tree.h> +#include <libxml/parser.h> +#include <libxml/xpath.h> #include "../src/svpc_types.h" @@ -169,6 +172,9 @@ void cleanup_virt_device(struct virt_device *dev); void cleanup_virt_devices(struct virt_device **devs, int count); +char *get_node_content(xmlNode *node); +char *get_attr_value(xmlNode *node, char *attrname); + char *get_fq_devid(char *host, char *_devid); int parse_fq_devid(const char *devid, char **host, char **device); @@ -176,6 +182,9 @@ int detach_device(virDomainPtr dom, struct virt_device *dev); int change_device(virDomainPtr dom, struct virt_device *dev); +#define XSTREQ(x, y) (STREQ((char *)x, y)) +#define STRPROP(d, p, n) (d->p = get_node_content(n)) + #endif /*

# HG changeset patch # User Kaitlin Rupert <karupert@us.ibm.com> # Date 1248121657 25200 # Node ID 67c4f2ab76c74753438aa94db0bc4867e869ff97 # Parent 5eefe23b2be112a925b834931897e61b97d2cd06 Add code to be able to parse an existing storage pool's XML This is needed in order to determine the storage pool type. For the upcoming image creation support, only directory type pools will be supported initially. Signed-off-by: Kaitlin Rupert <karupert@us.ibm.com> diff -r 5eefe23b2be1 -r 67c4f2ab76c7 libxkutil/pool_parsing.c --- a/libxkutil/pool_parsing.c Mon Jul 20 13:53:31 2009 -0700 +++ b/libxkutil/pool_parsing.c Mon Jul 20 13:27:37 2009 -0700 @@ -31,6 +31,7 @@ #include <libcmpiutil/libcmpiutil.h> #include "pool_parsing.h" +#include "device_parsing.h" #include "../src/svpc_types.h" /* @@ -86,6 +87,160 @@ *pool = NULL; } +static int parse_disk_target(xmlNode *node, struct disk_pool *pool) +{ + xmlNode *child; + + for (child = node->children; child != NULL; child = child->next) { + if (XSTREQ(child->name, "path")) { + STRPROP(pool, path, child); + break; + } + } + + return 1; +} + +static int parse_disk_source(xmlNode *node, struct disk_pool *pool) +{ + xmlNode *child; + + for (child = node->children; child != NULL; child = child->next) { + if (XSTREQ(child->name, "device")) { + const char *path; + path = get_attr_value(child, "path"); + /* Build device path array here */ + } else if (XSTREQ(child->name, "host")) { + pool->host = get_attr_value(child, "name"); + if (pool->host == NULL) + goto err; + } else if (XSTREQ(child->name, "dir")) { + pool->src_dir = get_attr_value(child, "path"); + if (pool->src_dir == NULL) + goto err; + } else if (XSTREQ(child->name, "dir")) { + pool->src_dir = get_attr_value(child, "path"); + if (pool->src_dir == NULL) + goto err; + } else if (XSTREQ(child->name, "adapter")) { + pool->adapter = get_attr_value(child, "name"); + pool->port_name = get_attr_value(child, "wwpn"); + pool->node_name = get_attr_value(child, "wwnn"); + } + } + + err: + + return 1; +} + +static const char *parse_disk_pool(xmlNodeSet *nsv, struct disk_pool *pool) +{ + xmlNode **nodes = nsv->nodeTab; + xmlNode *child; + const char *type_str; + const char *name; + int type = 0; + + type_str = get_attr_value(nodes[0], "type"); + + if (STREQC(type_str, "dir")) + type = DISK_POOL_DIR; + else if (STREQC(type_str, "fs")) + type = DISK_POOL_FS; + else if (STREQC(type_str, "netfs")) + type = DISK_POOL_NETFS; + else if (STREQC(type_str, "disk")) + type = DISK_POOL_DISK; + else if (STREQC(type_str, "iscsi")) + type = DISK_POOL_ISCSI; + else if (STREQC(type_str, "logical")) + type = DISK_POOL_LOGICAL; + else if (STREQC(type_str, "scsi")) + type = DISK_POOL_SCSI; + else + type = DISK_POOL_UNKNOWN; + + pool->pool_type = type; + + for (child = nodes[0]->children; child != NULL; child = child->next) { + if (XSTREQ(child->name, "name")) { + name = get_node_content(child); + } else if (XSTREQ(child->name, "target")) + parse_disk_target(child, pool); + else if (XSTREQ(child->name, "source")) + parse_disk_source(child, pool); + } + + return name; +} + +int get_pool_from_xml(const char *xml, struct virt_pool *pool, int type) +{ + int len; + int ret = 0; + xmlDoc *xmldoc; + xmlXPathContext *xpathctx; + xmlXPathObject *xpathobj; + const xmlChar *xpathstr = (xmlChar *)"/pool"; + const char *name; + + len = strlen(xml) + 1; + + if ((xmldoc = xmlParseMemory(xml, len)) == NULL) + goto err1; + + if ((xpathctx = xmlXPathNewContext(xmldoc)) == NULL) + goto err2; + + if ((xpathobj = xmlXPathEvalExpression(xpathstr, xpathctx)) == NULL) + goto err3; + + /* FIXME: Add support for parsing network pools */ + if (type == CIM_RES_TYPE_NET) { + ret = 0; + goto err1; + } + + memset(pool, 0, sizeof(*pool)); + + pool->type = CIM_RES_TYPE_DISK; + name = parse_disk_pool(xpathobj->nodesetval, + &(pool)->pool_info.disk); + if (name == NULL) + ret = 0; + + pool->id = strdup(name); + + xmlXPathFreeObject(xpathobj); + err3: + xmlXPathFreeContext(xpathctx); + err2: + xmlFreeDoc(xmldoc); + err1: + return ret; +} + +int get_disk_pool(virStoragePoolPtr poolptr, struct virt_pool **pool) +{ + char *xml; + int ret; + + xml = virStoragePoolGetXMLDesc(poolptr, 0); + if (xml == NULL) + return 0; + + *pool = malloc(sizeof(**pool)); + if (*pool == NULL) + return 0; + + ret = get_pool_from_xml(xml, *pool, CIM_RES_TYPE_DISK); + + free(xml); + + return ret; +} + int define_pool(virConnectPtr conn, const char *xml, int res_type) { int ret = 1; diff -r 5eefe23b2be1 -r 67c4f2ab76c7 libxkutil/pool_parsing.h --- a/libxkutil/pool_parsing.h Mon Jul 20 13:53:31 2009 -0700 +++ b/libxkutil/pool_parsing.h Mon Jul 20 13:27:37 2009 -0700 @@ -66,6 +66,9 @@ void cleanup_virt_pool(struct virt_pool **pool); +int get_pool_from_xml(const char *xml, struct virt_pool *pool, int type); +int get_disk_pool(virStoragePoolPtr poolptr, struct virt_pool **pool); + int define_pool(virConnectPtr conn, const char *xml, int res_type); int destroy_pool(virConnectPtr conn, const char *name, int res_type);

# HG changeset patch # User Kaitlin Rupert <karupert@us.ibm.com> # Date 1248121657 25200 # Node ID 67c4f2ab76c74753438aa94db0bc4867e869ff97 # Parent 5eefe23b2be112a925b834931897e61b97d2cd06 Add code to be able to parse an existing storage pool's XML
This is needed in order to determine the storage pool type. For the upcoming image creation support, only directory type pools will be supported initially.
Signed-off-by: Kaitlin Rupert <karupert@us.ibm.com>
diff -r 5eefe23b2be1 -r 67c4f2ab76c7 libxkutil/pool_parsing.c --- a/libxkutil/pool_parsing.c Mon Jul 20 13:53:31 2009 -0700 +++ b/libxkutil/pool_parsing.c Mon Jul 20 13:27:37 2009 -0700 @@ -31,6 +31,7 @@ #include <libcmpiutil/libcmpiutil.h>
#include "pool_parsing.h" +#include "device_parsing.h" #include "../src/svpc_types.h"
/* @@ -86,6 +87,160 @@ *pool = NULL; }
+static int parse_disk_target(xmlNode *node, struct disk_pool *pool) +{ + xmlNode *child; + + for (child = node->children; child != NULL; child = child->next) { + if (XSTREQ(child->name, "path")) { + STRPROP(pool, path, child); + break; + } + } + + return 1; +} + +static int parse_disk_source(xmlNode *node, struct disk_pool *pool) +{ + xmlNode *child; + + for (child = node->children; child != NULL; child = child->next) { + if (XSTREQ(child->name, "device")) { + const char *path; + path = get_attr_value(child, "path"); + /* Build device path array here */ + } else if (XSTREQ(child->name, "host")) { + pool->host = get_attr_value(child, "name"); + if (pool->host == NULL) + goto err; + } else if (XSTREQ(child->name, "dir")) { + pool->src_dir = get_attr_value(child, "path"); + if (pool->src_dir == NULL) + goto err; + } else if (XSTREQ(child->name, "dir")) { + pool->src_dir = get_attr_value(child, "path"); + if (pool->src_dir == NULL) + goto err; Duplicate code for node "dir". Also, I can't find the "dir" node in the
Kaitlin Rupert wrote: libvirt xml documentation, storage pool section.
+ } else if (XSTREQ(child->name, "adapter")) { + pool->adapter = get_attr_value(child, "name"); + pool->port_name = get_attr_value(child, "wwpn"); + pool->node_name = get_attr_value(child, "wwnn"); + } + } + + err: + + return 1; +} + +static const char *parse_disk_pool(xmlNodeSet *nsv, struct disk_pool *pool) +{ + xmlNode **nodes = nsv->nodeTab; + xmlNode *child; + const char *type_str; + const char *name; + int type = 0; + + type_str = get_attr_value(nodes[0], "type"); + + if (STREQC(type_str, "dir")) + type = DISK_POOL_DIR; + else if (STREQC(type_str, "fs")) + type = DISK_POOL_FS; + else if (STREQC(type_str, "netfs")) + type = DISK_POOL_NETFS; + else if (STREQC(type_str, "disk")) + type = DISK_POOL_DISK; + else if (STREQC(type_str, "iscsi")) + type = DISK_POOL_ISCSI; + else if (STREQC(type_str, "logical")) + type = DISK_POOL_LOGICAL; + else if (STREQC(type_str, "scsi")) + type = DISK_POOL_SCSI; + else + type = DISK_POOL_UNKNOWN; + + pool->pool_type = type; + + for (child = nodes[0]->children; child != NULL; child = child->next) { + if (XSTREQ(child->name, "name")) { + name = get_node_content(child); + } else if (XSTREQ(child->name, "target")) + parse_disk_target(child, pool); + else if (XSTREQ(child->name, "source")) + parse_disk_source(child, pool); + } + + return name; +} + +int get_pool_from_xml(const char *xml, struct virt_pool *pool, int type) +{ + int len; + int ret = 0; + xmlDoc *xmldoc; + xmlXPathContext *xpathctx; + xmlXPathObject *xpathobj; + const xmlChar *xpathstr = (xmlChar *)"/pool"; + const char *name; + + len = strlen(xml) + 1; + + if ((xmldoc = xmlParseMemory(xml, len)) == NULL) + goto err1; + + if ((xpathctx = xmlXPathNewContext(xmldoc)) == NULL) + goto err2; + + if ((xpathobj = xmlXPathEvalExpression(xpathstr, xpathctx)) == NULL) + goto err3; + + /* FIXME: Add support for parsing network pools */ + if (type == CIM_RES_TYPE_NET) { + ret = 0; + goto err1; + } + + memset(pool, 0, sizeof(*pool)); + + pool->type = CIM_RES_TYPE_DISK; + name = parse_disk_pool(xpathobj->nodesetval, + &(pool)->pool_info.disk); + if (name == NULL) + ret = 0; + + pool->id = strdup(name); + + xmlXPathFreeObject(xpathobj); + err3: + xmlXPathFreeContext(xpathctx); + err2: + xmlFreeDoc(xmldoc); + err1: + return ret; +} + +int get_disk_pool(virStoragePoolPtr poolptr, struct virt_pool **pool) +{ + char *xml; + int ret; + + xml = virStoragePoolGetXMLDesc(poolptr, 0); + if (xml == NULL) + return 0; + + *pool = malloc(sizeof(**pool)); + if (*pool == NULL) + return 0; + + ret = get_pool_from_xml(xml, *pool, CIM_RES_TYPE_DISK); + + free(xml); + + return ret; +} + int define_pool(virConnectPtr conn, const char *xml, int res_type) { int ret = 1; diff -r 5eefe23b2be1 -r 67c4f2ab76c7 libxkutil/pool_parsing.h --- a/libxkutil/pool_parsing.h Mon Jul 20 13:53:31 2009 -0700 +++ b/libxkutil/pool_parsing.h Mon Jul 20 13:27:37 2009 -0700 @@ -66,6 +66,9 @@
void cleanup_virt_pool(struct virt_pool **pool);
+int get_pool_from_xml(const char *xml, struct virt_pool *pool, int type); +int get_disk_pool(virStoragePoolPtr poolptr, struct virt_pool **pool); + int define_pool(virConnectPtr conn, const char *xml, int res_type); int destroy_pool(virConnectPtr conn, const char *name, int res_type);
_______________________________________________ Libvirt-cim mailing list Libvirt-cim@redhat.com https://www.redhat.com/mailman/listinfo/libvirt-cim
-- Richard Maciel, MSc IBM Linux Technology Center rmaciel@linux.vnet.ibm.com

+ for (child = node->children; child != NULL; child = child->next) { + if (XSTREQ(child->name, "device")) { + const char *path; + path = get_attr_value(child, "path"); + /* Build device path array here */ + } else if (XSTREQ(child->name, "host")) { + pool->host = get_attr_value(child, "name"); + if (pool->host == NULL) + goto err; + } else if (XSTREQ(child->name, "dir")) { + pool->src_dir = get_attr_value(child, "path"); + if (pool->src_dir == NULL) + goto err; + } else if (XSTREQ(child->name, "dir")) { + pool->src_dir = get_attr_value(child, "path"); + if (pool->src_dir == NULL) + goto err; Duplicate code for node "dir". Also, I can't find the "dir" node in the libvirt xml documentation, storage pool section.
Good catch - not sure what I was thinking there... Check out netfs type pools - they have a dir node. -- Kaitlin Rupert IBM Linux Technology Center kaitlin@linux.vnet.ibm.com

# HG changeset patch # User Kaitlin Rupert <karupert@us.ibm.com> # Date 1248121657 25200 # Node ID 5fad1c4642449d39d40c7f8c90b8e71371b90d58 # Parent 67c4f2ab76c74753438aa94db0bc4867e869ff97 Add StorageVolumeResourceAllocationSettingData class, new resource type The new class and resource type will be used to distinguish a template RASD used for defining a new storage volume (image file) from template RASDs that can be used to create a new virtual disk (assign an existing storage volume to a guest). Signed-off-by: Kaitlin Rupert <karupert@us.ibm.com> diff -r 67c4f2ab76c7 -r 5fad1c464244 schema/ResourceAllocationSettingData.mof --- a/schema/ResourceAllocationSettingData.mof Mon Jul 20 13:27:37 2009 -0700 +++ b/schema/ResourceAllocationSettingData.mof Mon Jul 20 13:27:37 2009 -0700 @@ -290,3 +290,22 @@ string NodeName; }; + +[Description ("Xen storage volume settings"), + Provider("cmpi::Virt_SettingsDefineCapabilities") +] +class Xen_StorageVolumeResourceAllocationSettingData : Xen_ResourceAllocationSettingData +{ + string Path; + uint16 Type; +}; + +[Description ("KVM storage volume settings"), + Provider("cmpi::Virt_SettingsDefineCapabilities") +] +class KVM_StorageVolumeResourceAllocationSettingData : KVM_ResourceAllocationSettingData +{ + string Path; + uint16 Type; +}; + diff -r 67c4f2ab76c7 -r 5fad1c464244 src/svpc_types.h --- a/src/svpc_types.h Mon Jul 20 13:27:37 2009 -0700 +++ b/src/svpc_types.h Mon Jul 20 13:27:37 2009 -0700 @@ -33,6 +33,7 @@ #define CIM_RES_TYPE_GRAPHICS 24 #define CIM_RES_TYPE_INPUT 13 #define CIM_RES_TYPE_UNKNOWN 1000 +#define CIM_RES_TYPE_IMAGE 32768 #define CIM_RES_TYPE_COUNT 6 const static int cim_res_types[CIM_RES_TYPE_COUNT] =

# HG changeset patch # User Kaitlin Rupert <karupert@us.ibm.com> # Date 1248121657 25200 # Node ID 3976c5e9c8ace6b1c6d23d14ab80d5b737d6702f # Parent 5fad1c4642449d39d40c7f8c90b8e71371b90d58 Expose template RASDs that can be used for defining new storage volumes Also: -Change volume_template() to avail_volume_template() to distinguish from template RASDs that represent existing storage volumes in a pool vs the template RASDs that are used for creating a new storage volume within a given pool -Change disk_dev_or_pool_template() to disk_res_template() since it now handles more than existing storage volumes and disk pool templates. Signed-off-by: Kaitlin Rupert <karupert@us.ibm.com> diff -r 5fad1c464244 -r 3976c5e9c8ac src/Virt_SettingsDefineCapabilities.c --- a/src/Virt_SettingsDefineCapabilities.c Mon Jul 20 13:27:37 2009 -0700 +++ b/src/Virt_SettingsDefineCapabilities.c Mon Jul 20 13:27:37 2009 -0700 @@ -71,6 +71,7 @@ #define DEVICE_RASD 0 #define POOL_RASD 1 +#define NEW_VOL_RASD 2 static bool system_has_vt(virConnectPtr conn) { @@ -280,6 +281,10 @@ ret = rasd_classname_from_type(resource_type, &base); else if (rasd_type == POOL_RASD) ret = pool_rasd_classname_from_type(resource_type, &base); + else if (rasd_type == NEW_VOL_RASD) { + base = "StorageVolumeResourceAllocationSettingData"; + ret = 0; + } if (ret != CMPI_RC_OK) { cu_statusf(_BROKER, s, @@ -1023,10 +1028,76 @@ } #if VIR_USE_LIBVIRT_STORAGE -static CMPIStatus volume_template(const CMPIObjectPath *ref, - int template_type, - virStorageVolPtr volume_ptr, - struct inst_list *list) +static CMPIStatus new_volume_template(const CMPIObjectPath *ref, + int template_type, + virStoragePoolPtr poolptr, + struct inst_list *list) +{ + const char *id; + CMPIStatus s = {CMPI_RC_OK, NULL}; + int ret = 0; + struct virt_pool *pool = NULL; + CMPIInstance *inst = NULL; + int type = 0; + const char *path; + + switch(template_type) { + case SDC_RASD_MIN: + id = "New Storage Volume Minimum"; + break; + case SDC_RASD_MAX: + id = "New Storage Volume Maximum"; + break; + case SDC_RASD_INC: + id = "New Storage Volume Increment"; + break; + case SDC_RASD_DEF: + id = "New Storage Volume Default"; + break; + default: + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Unsupported sdc_rasd type"); + goto out; + } + + ret = get_disk_pool(poolptr, &pool); + if (ret == 1) { + virt_set_status(_BROKER, &s, + CMPI_RC_ERR_FAILED, + virStoragePoolGetConnect(poolptr), + "Error getting referenced configuration"); + goto out; + } + + type = pool->pool_info.disk.pool_type; + if (type != DISK_POOL_DIR) { + CU_DEBUG("Image creation for this pool type is not supported"); + goto out; + } + + inst = sdc_rasd_inst(&s, ref, CIM_RES_TYPE_IMAGE, NEW_VOL_RASD); + if ((inst == NULL) || (s.rc != CMPI_RC_OK)) + goto out; + + CMSetProperty(inst, "InstanceID", (CMPIValue *)id, CMPI_chars); + CMSetProperty(inst, "Type", (CMPIValue *)&type, CMPI_uint16); + + path = "/var/lib/libvirt/images/"; + CMSetProperty(inst, "Path", (CMPIValue *)path, CMPI_chars); + + inst_list_add(list, inst); + + out: + cleanup_virt_pool(&pool); + + return s; +} + +static CMPIStatus avail_volume_template(const CMPIObjectPath *ref, + int template_type, + virStorageVolPtr volume_ptr, + struct inst_list *list) { char *pfx = NULL; const char *id; @@ -1163,6 +1234,10 @@ goto out; } + s = new_volume_template(ref, template_type, poolptr, list); + if (s.rc != CMPI_RC_OK) + goto out; + if ((numvols = virStoragePoolNumOfVolumes(poolptr)) == -1) { virt_set_status(_BROKER, &s, CMPI_RC_ERR_FAILED, @@ -1206,7 +1281,7 @@ goto out; } - s = volume_template(ref, template_type, volptr, list); + s = avail_volume_template(ref, template_type, volptr, list); virStorageVolFree(volptr); @@ -1388,9 +1463,9 @@ return s; } -static CMPIStatus disk_dev_or_pool_template(const CMPIObjectPath *ref, - int template_type, - struct inst_list *list) +static CMPIStatus disk_res_template(const CMPIObjectPath *ref, + int template_type, + struct inst_list *list) { CMPIStatus s = {CMPI_RC_OK, NULL}; CMPIInstance *inst; @@ -1421,7 +1496,7 @@ if (val) s = disk_pool_template(ref, template_type, list); - else + else s = disk_template(ref, template_type, list); out: @@ -1648,7 +1723,7 @@ else if (type == CIM_RES_TYPE_NET) s = net_dev_or_pool_template(ref, i, list); else if (type == CIM_RES_TYPE_DISK) - s = disk_dev_or_pool_template(ref, i, list); + s = disk_res_template(ref, i, list); else if (type == CIM_RES_TYPE_GRAPHICS) s = graphics_template(ref, i, list); else if (type == CIM_RES_TYPE_INPUT)
participants (2)
-
Kaitlin Rupert
-
Richard Maciel