|
|
c55d09 |
From 4f74864c72ffbb05c8b02ab9d12c581e22da359f Mon Sep 17 00:00:00 2001
|
|
|
c55d09 |
From: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com>
|
|
|
c55d09 |
Date: Mon, 14 Oct 2013 17:29:41 +0200
|
|
|
c55d09 |
Subject: [PATCH 26/60] libxkutil: Support for device addresses
|
|
|
c55d09 |
|
|
|
c55d09 |
New data type for device addresses based on the generic
|
|
|
c55d09 |
"address" element of the libvirt domain XML.
|
|
|
c55d09 |
Contains XML parsing and generation code for device addresses.
|
|
|
c55d09 |
|
|
|
c55d09 |
Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com>
|
|
|
c55d09 |
Signed-off-by: John Ferlan <jferlan@redhat.com>
|
|
|
c55d09 |
---
|
|
|
c55d09 |
libxkutil/device_parsing.c | 113 +++++++++++++++++++++++++++++++++++++++++++++
|
|
|
c55d09 |
libxkutil/device_parsing.h | 11 +++++
|
|
|
c55d09 |
libxkutil/xmlgen.c | 28 +++++++++++
|
|
|
c55d09 |
3 files changed, 152 insertions(+)
|
|
|
c55d09 |
|
|
|
c55d09 |
diff --git a/libxkutil/device_parsing.c b/libxkutil/device_parsing.c
|
|
|
c55d09 |
index aecca4c..97419d2 100644
|
|
|
c55d09 |
--- a/libxkutil/device_parsing.c
|
|
|
c55d09 |
+++ b/libxkutil/device_parsing.c
|
|
|
c55d09 |
@@ -63,6 +63,22 @@
|
|
|
c55d09 |
/* Device parse function */
|
|
|
c55d09 |
typedef int (*dev_parse_func_t)(xmlNode *, struct virt_device **);
|
|
|
c55d09 |
|
|
|
c55d09 |
+static void cleanup_device_address(struct device_address *addr)
|
|
|
c55d09 |
+{
|
|
|
c55d09 |
+ int i;
|
|
|
c55d09 |
+ if (addr == NULL)
|
|
|
c55d09 |
+ return;
|
|
|
c55d09 |
+
|
|
|
c55d09 |
+ for (i = 0; i < addr->ct; i++) {
|
|
|
c55d09 |
+ free(addr->key[i]);
|
|
|
c55d09 |
+ free(addr->value[i]);
|
|
|
c55d09 |
+ }
|
|
|
c55d09 |
+
|
|
|
c55d09 |
+ free(addr->key);
|
|
|
c55d09 |
+ free(addr->value);
|
|
|
c55d09 |
+ addr->ct = 0;
|
|
|
c55d09 |
+}
|
|
|
c55d09 |
+
|
|
|
c55d09 |
static void cleanup_disk_device(struct disk_device *dev)
|
|
|
c55d09 |
{
|
|
|
c55d09 |
if (dev == NULL)
|
|
|
c55d09 |
@@ -77,6 +93,7 @@ static void cleanup_disk_device(struct disk_device *dev)
|
|
|
c55d09 |
free(dev->virtual_dev);
|
|
|
c55d09 |
free(dev->bus_type);
|
|
|
c55d09 |
free(dev->access_mode);
|
|
|
c55d09 |
+ cleanup_device_address(&dev->address);
|
|
|
c55d09 |
}
|
|
|
c55d09 |
|
|
|
c55d09 |
static void cleanup_vsi_device(struct vsi_device *dev)
|
|
|
c55d09 |
@@ -107,6 +124,7 @@ static void cleanup_net_device(struct net_device *dev)
|
|
|
c55d09 |
free(dev->filter_ref);
|
|
|
c55d09 |
free(dev->poolid);
|
|
|
c55d09 |
cleanup_vsi_device(&dev->vsi);
|
|
|
c55d09 |
+ cleanup_device_address(&dev->address);
|
|
|
c55d09 |
}
|
|
|
c55d09 |
|
|
|
c55d09 |
static void cleanup_emu_device(struct emu_device *dev)
|
|
|
c55d09 |
@@ -351,6 +369,67 @@ char *get_node_content(xmlNode *node)
|
|
|
c55d09 |
return buf;
|
|
|
c55d09 |
}
|
|
|
c55d09 |
|
|
|
c55d09 |
+int add_device_address_property(struct device_address *devaddr,
|
|
|
c55d09 |
+ const char *key,
|
|
|
c55d09 |
+ const char *value)
|
|
|
c55d09 |
+{
|
|
|
c55d09 |
+ char *k = NULL;
|
|
|
c55d09 |
+ char *v = NULL;
|
|
|
c55d09 |
+ char **list = NULL;
|
|
|
c55d09 |
+
|
|
|
c55d09 |
+ if (key != NULL && value != NULL) {
|
|
|
c55d09 |
+ k = strdup(key);
|
|
|
c55d09 |
+ v = strdup(value);
|
|
|
c55d09 |
+ if (k == NULL || v == NULL)
|
|
|
c55d09 |
+ goto err;
|
|
|
c55d09 |
+
|
|
|
c55d09 |
+ list = realloc(devaddr->key, sizeof(char*) * (devaddr->ct+1));
|
|
|
c55d09 |
+ if (list == NULL)
|
|
|
c55d09 |
+ goto err;
|
|
|
c55d09 |
+ devaddr->key = list;
|
|
|
c55d09 |
+
|
|
|
c55d09 |
+ list = realloc(devaddr->value, sizeof(char*) * (devaddr->ct+1));
|
|
|
c55d09 |
+ if (list == NULL)
|
|
|
c55d09 |
+ goto err;
|
|
|
c55d09 |
+ devaddr->value = list;
|
|
|
c55d09 |
+
|
|
|
c55d09 |
+ devaddr->key[devaddr->ct] = k;
|
|
|
c55d09 |
+ devaddr->value[devaddr->ct] = v;
|
|
|
c55d09 |
+ devaddr->ct += 1;
|
|
|
c55d09 |
+ return 1;
|
|
|
c55d09 |
+ }
|
|
|
c55d09 |
+
|
|
|
c55d09 |
+ err:
|
|
|
c55d09 |
+ free(k);
|
|
|
c55d09 |
+ free(v);
|
|
|
c55d09 |
+ free(list);
|
|
|
c55d09 |
+ return 0;
|
|
|
c55d09 |
+}
|
|
|
c55d09 |
+
|
|
|
c55d09 |
+
|
|
|
c55d09 |
+static int parse_device_address(xmlNode *anode, struct device_address *devaddr)
|
|
|
c55d09 |
+{
|
|
|
c55d09 |
+ xmlAttr *attr = NULL;
|
|
|
c55d09 |
+ char *name = NULL;
|
|
|
c55d09 |
+ char *value = NULL;
|
|
|
c55d09 |
+
|
|
|
c55d09 |
+ for (attr = anode->properties; attr != NULL; attr = attr->next) {
|
|
|
c55d09 |
+ name = (char*) attr->name;
|
|
|
c55d09 |
+ value = get_attr_value(anode, name);
|
|
|
c55d09 |
+ if (!add_device_address_property(devaddr, name, value))
|
|
|
c55d09 |
+ goto err;
|
|
|
c55d09 |
+ free(value);
|
|
|
c55d09 |
+ }
|
|
|
c55d09 |
+
|
|
|
c55d09 |
+ return 1;
|
|
|
c55d09 |
+
|
|
|
c55d09 |
+ err:
|
|
|
c55d09 |
+ cleanup_device_address(devaddr);
|
|
|
c55d09 |
+ free(value);
|
|
|
c55d09 |
+
|
|
|
c55d09 |
+ return 0;
|
|
|
c55d09 |
+}
|
|
|
c55d09 |
+
|
|
|
c55d09 |
static int parse_fs_device(xmlNode *dnode, struct virt_device **vdevs)
|
|
|
c55d09 |
{
|
|
|
c55d09 |
struct virt_device *vdev = NULL;
|
|
|
c55d09 |
@@ -386,6 +465,8 @@ static int parse_fs_device(xmlNode *dnode, struct virt_device **vdevs)
|
|
|
c55d09 |
}
|
|
|
c55d09 |
} else if (XSTREQ(child->name, "driver")) {
|
|
|
c55d09 |
ddev->driver_type = get_attr_value(child, "type");
|
|
|
c55d09 |
+ } else if (XSTREQ(child->name, "address")) {
|
|
|
c55d09 |
+ parse_device_address(child, &ddev->address);
|
|
|
c55d09 |
}
|
|
|
c55d09 |
}
|
|
|
c55d09 |
|
|
|
c55d09 |
@@ -459,6 +540,8 @@ static int parse_block_device(xmlNode *dnode, struct virt_device **vdevs)
|
|
|
c55d09 |
ddev->readonly = true;
|
|
|
c55d09 |
} else if (XSTREQ(child->name, "shareable")) {
|
|
|
c55d09 |
ddev->shareable = true;
|
|
|
c55d09 |
+ } else if (XSTREQ(child->name, "address")) {
|
|
|
c55d09 |
+ parse_device_address(child, &ddev->address);
|
|
|
c55d09 |
}
|
|
|
c55d09 |
}
|
|
|
c55d09 |
|
|
|
c55d09 |
@@ -598,6 +681,8 @@ static int parse_net_device(xmlNode *inode, struct virt_device **vdevs)
|
|
|
c55d09 |
ndev->filter_ref = get_attr_value(child, "filter");
|
|
|
c55d09 |
} else if (XSTREQ(child->name, "virtualport")) {
|
|
|
c55d09 |
parse_vsi_device(child, ndev);
|
|
|
c55d09 |
+ } else if (XSTREQ(child->name, "address")) {
|
|
|
c55d09 |
+ parse_device_address(child, &ndev->address);
|
|
|
c55d09 |
#if LIBVIR_VERSION_NUMBER >= 9000
|
|
|
c55d09 |
} else if (XSTREQ(child->name, "bandwidth")) {
|
|
|
c55d09 |
/* Network QoS bandwidth support */
|
|
|
c55d09 |
@@ -1167,6 +1252,32 @@ static int parse_devices(const char *xml, struct virt_device **_list, int type)
|
|
|
c55d09 |
return count;
|
|
|
c55d09 |
}
|
|
|
c55d09 |
|
|
|
c55d09 |
+static void duplicate_device_address(struct device_address *to, const struct device_address *from)
|
|
|
c55d09 |
+{
|
|
|
c55d09 |
+ int i;
|
|
|
c55d09 |
+
|
|
|
c55d09 |
+ if (from == NULL || to == NULL || from->ct == 0)
|
|
|
c55d09 |
+ return;
|
|
|
c55d09 |
+
|
|
|
c55d09 |
+ to->ct = from->ct;
|
|
|
c55d09 |
+ to->key = calloc(from->ct, sizeof(char*));
|
|
|
c55d09 |
+ to->value = calloc(from->ct, sizeof(char*));
|
|
|
c55d09 |
+ if (to->key == NULL || to->value == NULL)
|
|
|
c55d09 |
+ goto err;
|
|
|
c55d09 |
+
|
|
|
c55d09 |
+ for (i = 0; i < from->ct; i++) {
|
|
|
c55d09 |
+ to->key[i] = strdup(from->key[i]);
|
|
|
c55d09 |
+ to->value[i] = strdup(from->value[i]);
|
|
|
c55d09 |
+ if (to->key[i] == NULL || to->value[i] == NULL)
|
|
|
c55d09 |
+ goto err;
|
|
|
c55d09 |
+ }
|
|
|
c55d09 |
+
|
|
|
c55d09 |
+ return;
|
|
|
c55d09 |
+
|
|
|
c55d09 |
+ err:
|
|
|
c55d09 |
+ cleanup_device_address(to);
|
|
|
c55d09 |
+}
|
|
|
c55d09 |
+
|
|
|
c55d09 |
struct virt_device *virt_device_dup(struct virt_device *_dev)
|
|
|
c55d09 |
{
|
|
|
c55d09 |
struct virt_device *dev;
|
|
|
c55d09 |
@@ -1196,6 +1307,7 @@ struct virt_device *virt_device_dup(struct virt_device *_dev)
|
|
|
c55d09 |
DUP_FIELD(dev, _dev, dev.net.vsi.profile_id);
|
|
|
c55d09 |
dev->dev.net.reservation = _dev->dev.net.reservation;
|
|
|
c55d09 |
dev->dev.net.limit = _dev->dev.net.limit;
|
|
|
c55d09 |
+ duplicate_device_address(&dev->dev.net.address, &_dev->dev.net.address);
|
|
|
c55d09 |
} else if (dev->type == CIM_RES_TYPE_DISK) {
|
|
|
c55d09 |
DUP_FIELD(dev, _dev, dev.disk.type);
|
|
|
c55d09 |
DUP_FIELD(dev, _dev, dev.disk.device);
|
|
|
c55d09 |
@@ -1209,6 +1321,7 @@ struct virt_device *virt_device_dup(struct virt_device *_dev)
|
|
|
c55d09 |
dev->dev.disk.disk_type = _dev->dev.disk.disk_type;
|
|
|
c55d09 |
dev->dev.disk.readonly = _dev->dev.disk.readonly;
|
|
|
c55d09 |
dev->dev.disk.shareable = _dev->dev.disk.shareable;
|
|
|
c55d09 |
+ duplicate_device_address(&dev->dev.disk.address, &_dev->dev.disk.address);
|
|
|
c55d09 |
} else if (dev->type == CIM_RES_TYPE_MEM) {
|
|
|
c55d09 |
dev->dev.mem.size = _dev->dev.mem.size;
|
|
|
c55d09 |
dev->dev.mem.maxsize = _dev->dev.mem.maxsize;
|
|
|
c55d09 |
diff --git a/libxkutil/device_parsing.h b/libxkutil/device_parsing.h
|
|
|
c55d09 |
index 2803d6a..531703d 100644
|
|
|
c55d09 |
--- a/libxkutil/device_parsing.h
|
|
|
c55d09 |
+++ b/libxkutil/device_parsing.h
|
|
|
c55d09 |
@@ -33,6 +33,12 @@
|
|
|
c55d09 |
|
|
|
c55d09 |
#include "../src/svpc_types.h"
|
|
|
c55d09 |
|
|
|
c55d09 |
+struct device_address {
|
|
|
c55d09 |
+ uint32_t ct;
|
|
|
c55d09 |
+ char **key;
|
|
|
c55d09 |
+ char **value;
|
|
|
c55d09 |
+};
|
|
|
c55d09 |
+
|
|
|
c55d09 |
struct vsi_device {
|
|
|
c55d09 |
char *vsi_type;
|
|
|
c55d09 |
char *manager_id;
|
|
|
c55d09 |
@@ -56,6 +62,7 @@ struct disk_device {
|
|
|
c55d09 |
char *bus_type;
|
|
|
c55d09 |
char *cache;
|
|
|
c55d09 |
char *access_mode; /* access modes for DISK_FS (filesystem) type */
|
|
|
c55d09 |
+ struct device_address address;
|
|
|
c55d09 |
};
|
|
|
c55d09 |
|
|
|
c55d09 |
struct net_device {
|
|
|
c55d09 |
@@ -70,6 +77,7 @@ struct net_device {
|
|
|
c55d09 |
uint64_t reservation;
|
|
|
c55d09 |
uint64_t limit;
|
|
|
c55d09 |
struct vsi_device vsi;
|
|
|
c55d09 |
+ struct device_address address;
|
|
|
c55d09 |
};
|
|
|
c55d09 |
|
|
|
c55d09 |
struct mem_device {
|
|
|
c55d09 |
@@ -257,6 +265,9 @@ int get_devices(virDomainPtr dom, struct virt_device **list, int type,
|
|
|
c55d09 |
void cleanup_virt_device(struct virt_device *dev);
|
|
|
c55d09 |
void cleanup_virt_devices(struct virt_device **devs, int count);
|
|
|
c55d09 |
|
|
|
c55d09 |
+int add_device_address_property(struct device_address *devaddr,
|
|
|
c55d09 |
+ const char *key, const char *value);
|
|
|
c55d09 |
+
|
|
|
c55d09 |
char *get_node_content(xmlNode *node);
|
|
|
c55d09 |
char *get_attr_value(xmlNode *node, char *attrname);
|
|
|
c55d09 |
|
|
|
c55d09 |
diff --git a/libxkutil/xmlgen.c b/libxkutil/xmlgen.c
|
|
|
c55d09 |
index 7e8801d..40e2905 100644
|
|
|
c55d09 |
--- a/libxkutil/xmlgen.c
|
|
|
c55d09 |
+++ b/libxkutil/xmlgen.c
|
|
|
c55d09 |
@@ -178,6 +178,26 @@ static const char *console_xml(xmlNodePtr root, struct domain *dominfo)
|
|
|
c55d09 |
BAD_CAST cdev->target_type);
|
|
|
c55d09 |
}
|
|
|
c55d09 |
}
|
|
|
c55d09 |
+
|
|
|
c55d09 |
+ return NULL;
|
|
|
c55d09 |
+}
|
|
|
c55d09 |
+
|
|
|
c55d09 |
+static char *device_address_xml(xmlNodePtr root, struct device_address *addr)
|
|
|
c55d09 |
+{
|
|
|
c55d09 |
+ int i;
|
|
|
c55d09 |
+ xmlNodePtr address;
|
|
|
c55d09 |
+
|
|
|
c55d09 |
+ if (addr == NULL || addr->ct == 0)
|
|
|
c55d09 |
+ return NULL;
|
|
|
c55d09 |
+
|
|
|
c55d09 |
+ address = xmlNewChild(root, NULL, BAD_CAST "address", NULL);
|
|
|
c55d09 |
+ if (address == NULL)
|
|
|
c55d09 |
+ return XML_ERROR;
|
|
|
c55d09 |
+
|
|
|
c55d09 |
+ for (i = 0; i < addr->ct; i++) {
|
|
|
c55d09 |
+ xmlNewProp(address, BAD_CAST addr->key[i] , BAD_CAST addr->value[i]);
|
|
|
c55d09 |
+ }
|
|
|
c55d09 |
+
|
|
|
c55d09 |
return NULL;
|
|
|
c55d09 |
}
|
|
|
c55d09 |
|
|
|
c55d09 |
@@ -225,6 +245,9 @@ static char *disk_block_xml(xmlNodePtr root, struct disk_device *dev)
|
|
|
c55d09 |
if (dev->shareable)
|
|
|
c55d09 |
xmlNewChild(disk, NULL, BAD_CAST "shareable", NULL);
|
|
|
c55d09 |
|
|
|
c55d09 |
+ if (dev->address.ct > 0)
|
|
|
c55d09 |
+ return device_address_xml(disk, &dev->address);
|
|
|
c55d09 |
+
|
|
|
c55d09 |
return NULL;
|
|
|
c55d09 |
}
|
|
|
c55d09 |
|
|
|
c55d09 |
@@ -279,6 +302,8 @@ static const char *disk_file_xml(xmlNodePtr root, struct disk_device *dev)
|
|
|
c55d09 |
if (dev->shareable)
|
|
|
c55d09 |
xmlNewChild(disk, NULL, BAD_CAST "shareable", NULL);
|
|
|
c55d09 |
|
|
|
c55d09 |
+ if (dev->address.ct > 0)
|
|
|
c55d09 |
+ return device_address_xml(disk, &dev->address);
|
|
|
c55d09 |
|
|
|
c55d09 |
return NULL;
|
|
|
c55d09 |
}
|
|
|
c55d09 |
@@ -520,6 +545,9 @@ static const char *net_xml(xmlNodePtr root, struct domain *dominfo)
|
|
|
c55d09 |
}
|
|
|
c55d09 |
#endif
|
|
|
c55d09 |
|
|
|
c55d09 |
+ if (dev->dev.net.address.ct > 0)
|
|
|
c55d09 |
+ msg = device_address_xml(nic, &dev->dev.net.address);
|
|
|
c55d09 |
+
|
|
|
c55d09 |
if (STREQ(dev->dev.net.type, "network")) {
|
|
|
c55d09 |
msg = set_net_source(nic, net, "network");
|
|
|
c55d09 |
} else if (STREQ(dev->dev.net.type, "bridge")) {
|
|
|
c55d09 |
--
|
|
|
c55d09 |
2.1.0
|
|
|
c55d09 |
|