From snmishra at linux.vnet.ibm.com Wed Feb 1 16:31:09 2012 From: snmishra at linux.vnet.ibm.com (Sharad Mishra) Date: Wed, 01 Feb 2012 08:31:09 -0800 Subject: [Libvirt-cim] [PATCH 3/4] FilterEntry: Update action property In-Reply-To: <4F2862AA.6000509@linux.vnet.ibm.com> References: <1327967871-24219-1-git-send-email-eblima@linux.vnet.ibm.com> <1327967871-24219-4-git-send-email-eblima@linux.vnet.ibm.com> <1328043642.4193.1272.camel@snmishra-desktop.beaverton.ibm.com> <4F2862AA.6000509@linux.vnet.ibm.com> Message-ID: <1328113869.4193.1280.camel@snmishra-desktop.beaverton.ibm.com> I saw this error after getting the latest libvirt-cim and cimtest from libvirt.org and applying this patchset and the cimtest patch that was posted along with this patchset. -Sharad On Tue, 2012-01-31 at 19:52 -0200, Eduardo Lima (Etrunko) wrote: > On 01/31/2012 07:00 PM, Sharad Mishra wrote: > > seeing following issue now - > > > > FilterList - 01_enum.py: PASS > > -------------------------------------------------------------------- > > FilterList - 02_assoc.py: FAIL > > ERROR - CIMError : (1, u'CIM_ERR_FAILED: Failed to load the Provider > > Manager for interface type "CMPI" from library "".') > > Traceback (most recent call last): > > File > > "/tmp/remove_me/cimtest/suites/libvirt-cim/lib/XenKvmLib/const.py", line > > 141, in do_try > > rc = f() > > File "02_assoc.py", line 50, in main > > cim_filters = _test.cim_entries_in_filter_lists() > > File > > "/tmp/remove_me/cimtest/suites/libvirt-cim/cimtest/FilterList/helper.py", line 269, in cim_entries_in_filter_lists > > l.extend(self.Associators(n, result_class="CIM_FilterEntryBase")) > > File > > "/tmp/remove_me/cimtest/suites/libvirt-cim/cimtest/FilterList/helper.py", line 88, in Associators > > return self.wbem.Associators(typed_class, **kargs) > > File "/usr/lib/python2.6/site-packages/pywbem/cim_operations.py", line > > 696, in Associators > > **params) > > File "/usr/lib/python2.6/site-packages/pywbem/cim_operations.py", line > > 219, in imethodcall > > raise CIMError(code, tt[1]['DESCRIPTION']) > > CIMError: (1, u'CIM_ERR_FAILED: Failed to load the Provider Manager for > > interface type "CMPI" from library "".') > > ERROR - None > > -------------------------------------------------------------------- > > FilterList - 03_create.py: PASS > > > > > > I don't think this error is related to this patch right? Anyway, I don't > see any failures with FilterList tests anymore. See the log attached. > > Best regards, > From eblima at linux.vnet.ibm.com Wed Feb 1 20:24:00 2012 From: eblima at linux.vnet.ibm.com (Eduardo Lima (Etrunko)) Date: Wed, 01 Feb 2012 18:24:00 -0200 Subject: [Libvirt-cim] [PATCH 3/4] FilterEntry: Update action property In-Reply-To: <1328113869.4193.1280.camel@snmishra-desktop.beaverton.ibm.com> References: <1327967871-24219-1-git-send-email-eblima@linux.vnet.ibm.com> <1327967871-24219-4-git-send-email-eblima@linux.vnet.ibm.com> <1328043642.4193.1272.camel@snmishra-desktop.beaverton.ibm.com> <4F2862AA.6000509@linux.vnet.ibm.com> <1328113869.4193.1280.camel@snmishra-desktop.beaverton.ibm.com> Message-ID: <4F299F60.4020105@linux.vnet.ibm.com> On 02/01/2012 02:31 PM, Sharad Mishra wrote: > I saw this error after getting the latest libvirt-cim and cimtest from > libvirt.org and applying this patchset and the cimtest patch that was > posted along with this patchset. > I used to have this kind of errors when I was running pegasus 2.9 in an old Fedora 14 install. Since I upgraded to 2.11.1 I haven't seen these happening anymore. Can you check the pegasus version you are running and if possible, upgrade to 2.11.1 (or later)? Best regards, Etrunko > -Sharad > > On Tue, 2012-01-31 at 19:52 -0200, Eduardo Lima (Etrunko) wrote: >> On 01/31/2012 07:00 PM, Sharad Mishra wrote: >>> seeing following issue now - >>> >>> FilterList - 01_enum.py: PASS >>> -------------------------------------------------------------------- >>> FilterList - 02_assoc.py: FAIL >>> ERROR - CIMError : (1, u'CIM_ERR_FAILED: Failed to load the Provider >>> Manager for interface type "CMPI" from library "".') >>> Traceback (most recent call last): >>> File >>> "/tmp/remove_me/cimtest/suites/libvirt-cim/lib/XenKvmLib/const.py", line >>> 141, in do_try >>> rc = f() >>> File "02_assoc.py", line 50, in main >>> cim_filters = _test.cim_entries_in_filter_lists() >>> File >>> "/tmp/remove_me/cimtest/suites/libvirt-cim/cimtest/FilterList/helper.py", line 269, in cim_entries_in_filter_lists >>> l.extend(self.Associators(n, result_class="CIM_FilterEntryBase")) >>> File >>> "/tmp/remove_me/cimtest/suites/libvirt-cim/cimtest/FilterList/helper.py", line 88, in Associators >>> return self.wbem.Associators(typed_class, **kargs) >>> File "/usr/lib/python2.6/site-packages/pywbem/cim_operations.py", line >>> 696, in Associators >>> **params) >>> File "/usr/lib/python2.6/site-packages/pywbem/cim_operations.py", line >>> 219, in imethodcall >>> raise CIMError(code, tt[1]['DESCRIPTION']) >>> CIMError: (1, u'CIM_ERR_FAILED: Failed to load the Provider Manager for >>> interface type "CMPI" from library "".') >>> ERROR - None >>> -------------------------------------------------------------------- >>> FilterList - 03_create.py: PASS >>> >>> >> >> I don't think this error is related to this patch right? Anyway, I don't >> see any failures with FilterList tests anymore. See the log attached. >> >> Best regards, >> > > -- Eduardo de Barros Lima Software Engineer, Open Virtualization Linux Technology Center - IBM/Brazil eblima at br.ibm.com From snmishra at linux.vnet.ibm.com Wed Feb 1 22:10:56 2012 From: snmishra at linux.vnet.ibm.com (Sharad Mishra) Date: Wed, 01 Feb 2012 14:10:56 -0800 Subject: [Libvirt-cim] [PATCH 3/3] ACL: Use linked list helper for filter refs In-Reply-To: <1328047125-22037-4-git-send-email-eblima@linux.vnet.ibm.com> References: <1328047125-22037-1-git-send-email-eblima@linux.vnet.ibm.com> <1328047125-22037-4-git-send-email-eblima@linux.vnet.ibm.com> Message-ID: <1328134256.4193.1482.camel@snmishra-desktop.beaverton.ibm.com> On Tue, 2012-01-31 at 19:58 -0200, Eduardo Lima (Etrunko) wrote: > From: "Eduardo Lima (Etrunko)" > > Signed-off-by: Eduardo Lima (Etrunko) > --- > libxkutil/acl_parsing.c | 58 +++++++++------------------------ > libxkutil/acl_parsing.h | 5 ++- > libxkutil/xmlgen.c | 30 +++++++++++++---- > src/Virt_NestedFilterList.c | 73 +++++++++++++++++++++++------------------- > 4 files changed, 82 insertions(+), 84 deletions(-) > > diff --git a/libxkutil/acl_parsing.c b/libxkutil/acl_parsing.c > index 9c4b4b2..6dd481b 100644 > --- a/libxkutil/acl_parsing.c > +++ b/libxkutil/acl_parsing.c > @@ -141,11 +141,7 @@ void cleanup_filter(struct acl_filter *filter) > free(filter->rules); > filter->rule_ct = 0; > > - for (i = 0; i < filter->ref_ct; i++) > - free(filter->refs[i]); > - > - free(filter->refs); > - filter->ref_ct = 0; > + list_free(filter->refs); > } > > void cleanup_filters(struct acl_filter **filters, int count) > @@ -610,58 +606,36 @@ int append_filter_rule(struct acl_filter *filter, struct acl_rule *rule) > return 1; > } > > -int append_filter_ref(struct acl_filter *filter, char *name) > + > +static int filter_ref_cmp(void *list_data, void *user_data) > { > - int i; > - char **old_refs = NULL; > + return strcmp((const char *)list_data, (const char *) user_data); > +} > > - if ((filter == NULL) || (name == NULL)) > +int append_filter_ref(struct acl_filter *filter, char *name) > +{ > + if (filter == NULL || name == NULL) > return 0; > > - for (i = 0; i < filter->ref_ct; i++) > - if (STREQC(filter->refs[i], name)) > - return 0; /* already exists */ > - > - old_refs = filter->refs; > - > - filter->refs = malloc((filter->ref_ct + 1) * sizeof(char *)); > + if (filter->refs == NULL) > + filter->refs = list_new(free, filter_ref_cmp); > > - if (filter->refs == NULL) { > - CU_DEBUG("Failed to allocate memory for new ref"); > - filter->refs = old_refs; > - return 0; > + if (list_find(filter->refs, name) != NULL) { > + free(name); > + return 0; /* already exists */ > } > > - memcpy(filter->refs, old_refs, filter->ref_ct * sizeof(char *)); > - > - filter->refs[filter->ref_ct] = name; > - filter->ref_ct++; > - > - free(old_refs); > + list_append(filter->refs, name); > > return 1; > } > > int remove_filter_ref(struct acl_filter *filter, const char *name) > { > - int i; > - char **old_refs = NULL; > - > - if ((filter == NULL) || (name == NULL)) > + if (filter == NULL || filter->refs == NULL || name == NULL) > return 0; > > - /* TODO: called infrequently, but needs optimization */ > - old_refs = filter->refs; > - filter->ref_ct = 0; > - > - for (i = 0; i < filter->ref_ct; i++) { > - if (STREQC(old_refs[i], name)) { > - free(old_refs[i]); > - } > - else if(append_filter_ref(filter, old_refs[i]) == 0) { > - return 0; > - } > - } > + list_remove(filter->refs, (void *) name); > > return 1; > } > diff --git a/libxkutil/acl_parsing.h b/libxkutil/acl_parsing.h > index 5b99175..e49f384 100644 > --- a/libxkutil/acl_parsing.h > +++ b/libxkutil/acl_parsing.h > @@ -26,6 +26,8 @@ > #include > #include > > +#include "list_util.h" > + > struct acl_mac_rule { > char *srcmacaddr; > char *srcmacmask; > @@ -152,8 +154,7 @@ struct acl_filter { > struct acl_rule **rules; > int rule_ct; > > - char **refs; > - int ref_ct; > + list_t *refs; > }; > > void cleanup_rule(struct acl_rule *rule); > diff --git a/libxkutil/xmlgen.c b/libxkutil/xmlgen.c > index 9a2ada9..5c16ebe 100644 > --- a/libxkutil/xmlgen.c > +++ b/libxkutil/xmlgen.c > @@ -28,6 +28,7 @@ > #include > > #include "xmlgen.h" > +#include "list_util.h" > > #ifndef TEST > #include "misc_util.h" > @@ -1467,12 +1468,31 @@ char *res_to_xml(struct virt_pool_res *res) { > return xml; > } > > +static bool filter_ref_foreach(void *list_data, void *user_data) > +{ > + char *filter = (char *) list_data; > + xmlNodePtr root = (xmlNodePtr) user_data; > + xmlNodePtr tmp = NULL; > + > + tmp = xmlNewChild(root, NULL, BAD_CAST "filterref", NULL); > + if (tmp == NULL) { > + CU_DEBUG("Error creating filterref node"); > + return false; > + } > + > + if (xmlNewProp(tmp, BAD_CAST "filter", BAD_CAST list_data) == NULL) { > + CU_DEBUG("Error adding filter attribute '%s'", filter); > + return false; > + } > + > + return true; > +} > + > char *filter_to_xml(struct acl_filter *filter) > { > char *xml = NULL; > xmlNodePtr root = NULL; > xmlNodePtr tmp = NULL; > - int i; > > root = xmlNewNode(NULL, BAD_CAST "filter"); > if (root == NULL) > @@ -1494,12 +1514,8 @@ char *filter_to_xml(struct acl_filter *filter) > goto out; > } > > - for (i = 0; i < filter->ref_ct; i++) { > - tmp = xmlNewChild(root, NULL, BAD_CAST "filterref", NULL); > - if (xmlNewProp(tmp, BAD_CAST "filter", > - BAD_CAST filter->refs[i]) == NULL) > - goto out; > - } > + if (!list_foreach(filter->refs, filter_ref_foreach, (void *) root)) why call list_foreach(), why not call filter_ref_foreach() directly? > + goto out; > > xml = tree_to_xml(root); > > diff --git a/src/Virt_NestedFilterList.c b/src/Virt_NestedFilterList.c > index 81c4408..a8565d6 100644 > --- a/src/Virt_NestedFilterList.c > +++ b/src/Virt_NestedFilterList.c > @@ -34,6 +34,7 @@ > > #include "acl_parsing.h" > #include "misc_util.h" > +#include "list_util.h" > #include "Virt_FilterList.h" > > static const CMPIBroker *_BROKER; > @@ -120,7 +121,7 @@ static CMPIStatus parent_to_child( > CMPIInstance *instance = NULL; > const char * name = NULL; > virConnectPtr conn = NULL; > - int i; > + list_node_t *head, *node; > > CU_DEBUG("Reference = %s", REF2STR(reference)); > > @@ -139,29 +140,39 @@ static CMPIStatus parent_to_child( > if (parent_filter == NULL) > goto out; > > - for (i = 0; i < parent_filter->ref_ct; i++) { > - get_filter_by_name(conn, parent_filter->refs[i], > - &child_filter); > - if (child_filter == NULL) > - continue; > - > - CU_DEBUG("Processing %s,", child_filter->name); > - > - s = instance_from_filter(_BROKER, > - info->context, > - reference, > - child_filter, > - &instance); > + /* Walk refs list */ > + if (parent_filter->refs == NULL) > + goto end; > + > + head = node = list_first_node(parent_filter->refs); > + if (head == NULL) > + goto end; > + > + do { > + name = (const char *) list_node_data_get(node); > + get_filter_by_name(conn, name, &child_filter); > + if (child_filter != NULL) { > + CU_DEBUG("Processing %s,", child_filter->name); > + > + s = instance_from_filter(_BROKER, > + info->context, > + reference, > + child_filter, > + &instance); > + > + if (instance != NULL) { > + CU_DEBUG("Adding instance to inst_list"); > + inst_list_add(list, instance); > + } > > - if (instance != NULL) { > - CU_DEBUG("Adding instance to inst_list"); > - inst_list_add(list, instance); > + cleanup_filters(&child_filter, 1); > } > > - cleanup_filters(&child_filter, 1); > instance = NULL; > - } > + node = list_node_next_node(node); > + } while (node != head); > > + end: > cleanup_filters(&parent_filter, 1); > > out: > @@ -183,7 +194,7 @@ static CMPIStatus child_to_parent( > CMPIInstance *instance = NULL; > const char *name = NULL; > virConnectPtr conn = NULL; > - int count, i, j; > + int count, i; > > CU_DEBUG("Reference = %s", REF2STR(reference)); > > @@ -206,24 +217,20 @@ static CMPIStatus child_to_parent( > > /* return any filter that has name in refs */ > for (i = 0; i < count; i++) { > - for (j = 0; j < _list[i].ref_ct; j++) { > - if (STREQC(name, _list[i].refs[j])) { > - CU_DEBUG("Processing %s,", _list[i].name); > + if (list_find_node(_list[i].refs, (void *) name) != NULL) { > + CU_DEBUG("Processing %s,", _list[i].name); > > - s = instance_from_filter(_BROKER, > - info->context, > - reference, > - &_list[i], > - &instance); > - > - if (instance != NULL) > - inst_list_add(list, instance); > + s = instance_from_filter(_BROKER, > + info->context, > + reference, > + &_list[i], > + &instance); > > + if (instance != NULL) { > + inst_list_add(list, instance); > instance = NULL; > } > - > } > - > } > > cleanup_filters(&_list, count); From snmishra at linux.vnet.ibm.com Wed Feb 1 22:11:05 2012 From: snmishra at linux.vnet.ibm.com (Sharad Mishra) Date: Wed, 01 Feb 2012 14:11:05 -0800 Subject: [Libvirt-cim] [PATCH 1/3] libxkutil: Linked list helper In-Reply-To: <1328047125-22037-2-git-send-email-eblima@linux.vnet.ibm.com> References: <1328047125-22037-1-git-send-email-eblima@linux.vnet.ibm.com> <1328047125-22037-2-git-send-email-eblima@linux.vnet.ibm.com> Message-ID: <1328134265.4193.1483.camel@snmishra-desktop.beaverton.ibm.com> On Tue, 2012-01-31 at 19:58 -0200, Eduardo Lima (Etrunko) wrote: > From: "Eduardo Lima (Etrunko)" > > Signed-off-by: Eduardo Lima (Etrunko) > --- > libxkutil/Makefile.am | 51 +++++++--- > libxkutil/list_util.c | 254 +++++++++++++++++++++++++++++++++++++++++++++++++ > libxkutil/list_util.h | 73 ++++++++++++++ > 3 files changed, 364 insertions(+), 14 deletions(-) > create mode 100644 libxkutil/list_util.c > create mode 100644 libxkutil/list_util.h > > diff --git a/libxkutil/Makefile.am b/libxkutil/Makefile.am > index f1adc03..8d436ad 100644 > --- a/libxkutil/Makefile.am > +++ b/libxkutil/Makefile.am > @@ -1,21 +1,44 @@ > # Copyright IBM Corp. 2007 > +AM_CFLAGS = \ > + $(CFLAGS_STRICT) \ > + -DLIBVIRTCIM_CONF=\"@sysconfdir@/@PACKAGE at .conf\" > > -AM_CFLAGS = $(CFLAGS_STRICT) \ > - -DLIBVIRTCIM_CONF=\"@sysconfdir@/@PACKAGE at .conf\" > +noinst_HEADERS = \ > + cs_util.h \ > + misc_util.h \ > + device_parsing.h \ > + xmlgen.h \ > + infostore.h \ > + pool_parsing.h \ > + acl_parsing.h \ > + list_util.h > > -noinst_HEADERS = cs_util.h misc_util.h device_parsing.h xmlgen.h infostore.h \ > - pool_parsing.h acl_parsing.h > +lib_LTLIBRARIES = \ > + libxkutil.la > > -lib_LTLIBRARIES = libxkutil.la > +libxkutil_la_SOURCES = \ > + cs_util_instance.c \ > + misc_util.c \ > + device_parsing.c \ > + xmlgen.c \ > + infostore.c \ > + pool_parsing.c \ > + acl_parsing.c \ > + list_util.c > > -libxkutil_la_SOURCES = cs_util_instance.c misc_util.c device_parsing.c \ > - xmlgen.c infostore.c pool_parsing.c acl_parsing.c > -libxkutil_la_LDFLAGS = -version-info @VERSION_INFO@ > -libxkutil_la_LIBADD = @LIBVIRT_LIBS@ \ > - @LIBUUID_LIBS@ > +libxkutil_la_LDFLAGS = \ > + -version-info @VERSION_INFO@ > > -noinst_PROGRAMS = xml_parse_test > +libxkutil_la_LIBADD = \ > + @LIBVIRT_LIBS@ \ > + @LIBUUID_LIBS@ > > -xml_parse_test_SOURCES = xml_parse_test.c > -xml_parse_test_LDADD = libxkutil.la \ > - @LIBVIRT_LIBS@ > +noinst_PROGRAMS = \ > + xml_parse_test > + > +xml_parse_test_SOURCES = \ > + xml_parse_test.c > + > +xml_parse_test_LDADD = \ > + libxkutil.la \ > + @LIBVIRT_LIBS@ > diff --git a/libxkutil/list_util.c b/libxkutil/list_util.c > new file mode 100644 > index 0000000..84b2ba0 > --- /dev/null > +++ b/libxkutil/list_util.c > @@ -0,0 +1,254 @@ > +/* > + * Copyright IBM Corp. 2012 > + * > + * Authors: > + * Eduardo Lima (Etrunko) > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + */ > +#ifdef HAVE_CONFIG_H > +# include "config.h" > +#endif > + > +#include > + > +#include "list_util.h" > + > +struct _list_node_t { > + list_node_t *prev; > + list_node_t *next; > + void *data; > +}; > + > +struct _list_t { > + unsigned int count; > + list_node_t *head; > + list_data_free_cb free_cb; > + list_data_cmp_cb cmp_cb; > +}; > + > +list_t *list_new(list_data_free_cb free_cb, list_data_cmp_cb cmp_cb) > +{ > + list_t *l = calloc(1, sizeof(*l)); > + if (l == NULL) > + return NULL; > + > + l->free_cb = free_cb; > + l->cmp_cb = cmp_cb; > + return l; > +} > + > +void list_free(list_t *list) > +{ > + list_node_t *n, *next; > + > + if (list == NULL || list->head == NULL) > + return; > + > + n = list->head; > + > + do { > + if (list->free_cb) > + list->free_cb(n->data); > + > + next = n->next; > + free(n); > + n = next; > + } while (n != list->head); > + > + free(list); > +} > + > +void list_append(list_t *list, void *data) > +{ > + list_node_t *n; > + > + if (list == NULL) > + return; > + > + n = calloc(1, sizeof(*n)); > + > + if (n == NULL) > + return; > + > + n->data = data; > + > + if (list->head == NULL) { /* empty list */ > + n->next = n->prev = n; > + list->head = n; shouldn't you be setting the list->count to "0" here ? > + goto end; > + } > + > + n->next = list->head; > + n->prev = list->head->prev; > + > + list->head->prev->next = n; > + list->head->prev = n; > + > + end: > + list->count += 1; > +} > + > +void list_prepend(list_t *list, void *data) > +{ > + list_append(list, data); > + list->head = list->head->prev; > +} > + > +void *list_find(list_t *list, void *user_data) > +{ > + list_node_t *n = list_find_node(list, user_data); > + return list_node_data_get(n); > +} > + > +list_node_t *list_find_node(list_t *list, void *user_data) > +{ > + list_node_t *n; > + > + if (list == NULL || list->head == NULL || list->cmp_cb == NULL) > + return NULL; > + > + n = list->head; > + do { > + if (list->cmp_cb(n->data, user_data) == 0) > + return n; > + > + n = n->next; > + } while (n != list->head); > + > + return NULL; > +} > + > +void list_remove(list_t *list, void *data) > +{ > + list_node_t *n = list_find_node(list, data); > + list_remove_node(list, n); > +} > + > +void list_remove_node(list_t *list, list_node_t *node) > +{ > + if (list == NULL || list->head == NULL || node == NULL) > + return; > + > + if (node->next == node) { /* only 1 item */ > + list->head = NULL; > + } else { > + if (node == list->head) /* first node */ > + list->head = node->next; > + > + node->prev->next = node->next; > + node->next->prev = node->prev; > + } > + > + if (list->free_cb) > + list->free_cb(node->data); > + > + free(node); > + list->count -= 1; > +} > + > +bool list_foreach(list_t *list, list_foreach_cb cb, void *user_data) What is the idea of this function. Isn't list_find_node doing something very similar? > +{ > + list_node_t *node; > + > + if (list == NULL || list->head == NULL) > + return true; /* nothing to do */ > + > + node = list->head; > + do { > + if (cb(node->data, user_data) == false) > + return false; > + > + node = node->next; > + } while (node != list->head); > + > + return true; > +} > + > +unsigned int list_count(list_t *list) > +{ > + if (list == NULL) > + return 0; > + > + return list->count; > +} > + > +void *list_node_data_get(list_node_t *node) > +{ > + if (node == NULL) > + return NULL; > + > + return node->data; > +} > + > +void list_node_data_set(list_node_t *node, void *data) > +{ > + if (node == NULL) > + return; > + > + node->data = data; > +} > + > +void *list_first(list_t *list) > +{ > + return list_node_data_get(list_first_node(list)); > +} > + > +list_node_t *list_first_node(list_t *list) > +{ > + if (list == NULL) > + return NULL; > + > + return list->head; > +} > + > +void *list_last(list_t *list) > +{ > + return list_node_data_get(list_last_node(list)); > +} > + > +list_node_t *list_last_node(list_t *list) > +{ > + if (list == NULL || list->head == NULL) > + return NULL; > + > + return list->head->prev; > +} > + > +void *list_node_next(list_node_t *node) > +{ > + return list_node_data_get(list_node_next_node(node)); > +} > + > +list_node_t *list_node_next_node(list_node_t *node) > +{ > + if (node == NULL) > + return NULL; > + > + return node->next; > +} > + > +void *list_node_prev(list_node_t *node) > +{ > + return list_node_data_get(list_node_prev_node(node)); > +} > + > +list_node_t *list_node_prev_node(list_node_t *node) > +{ > + if (node == NULL) > + return NULL; > + > + return node->prev; > +} > diff --git a/libxkutil/list_util.h b/libxkutil/list_util.h > new file mode 100644 > index 0000000..1809c2e > --- /dev/null > +++ b/libxkutil/list_util.h > @@ -0,0 +1,73 @@ > +/* > + * Copyright IBM Corp. 2012 > + * > + * Authors: > + * Eduardo Lima (Etrunko) > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + */ > + > +#ifndef __LIST_UTIL_H > +#define __LIST_UTIL_H > + > +#include > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +typedef void (*list_data_free_cb)(void *data); > +typedef int (*list_data_cmp_cb)(void *list_data, void *user_data); > +typedef bool (*list_foreach_cb)(void *list_data, void *user_data); > + > +typedef struct _list_node_t list_node_t; > +typedef struct _list_t list_t; > + > +list_t *list_new(list_data_free_cb free_cb, list_data_cmp_cb cmp_cb); > +void list_free(list_t *list); > + > +void list_append(list_t *list, void *data); > +void list_prepend(list_t *list, void *data); > + > +void *list_find(list_t *list, void *user_data); > +list_node_t *list_find_node(list_t *list, void *user_data); > + > +void list_remove(list_t *list, void *data); > +void list_remove_node(list_t *list, list_node_t *node); > + > +bool list_foreach(list_t *list, list_foreach_cb cb, void *user_data); > + > +inline unsigned int list_count(list_t *list); > + > +inline void *list_node_data_get(list_node_t *node); > +inline void list_node_data_set(list_node_t *node, void *data); > + > +inline void *list_first(list_t *list); > +inline list_node_t *list_first_node(list_t *list); > + > +inline void *list_last(list_t *list); > +inline list_node_t *list_last_node(list_t *list); > + > +inline void *list_node_next(list_node_t *node); > +inline list_node_t *list_node_next_node(list_node_t *node); > + > +inline void *list_node_prev(list_node_t *node); > +inline list_node_t *list_node_prev_node(list_node_t *node); > + > +#ifdef __cplusplus > +} /* extern "C" */ > +#endif > + > +#endif /* __LIST_UTIL_H */ From eblima at linux.vnet.ibm.com Wed Feb 1 23:46:51 2012 From: eblima at linux.vnet.ibm.com (Eduardo Lima (Etrunko)) Date: Wed, 01 Feb 2012 21:46:51 -0200 Subject: [Libvirt-cim] [PATCH 1/3] libxkutil: Linked list helper In-Reply-To: <1328134265.4193.1483.camel@snmishra-desktop.beaverton.ibm.com> References: <1328047125-22037-1-git-send-email-eblima@linux.vnet.ibm.com> <1328047125-22037-2-git-send-email-eblima@linux.vnet.ibm.com> <1328134265.4193.1483.camel@snmishra-desktop.beaverton.ibm.com> Message-ID: <4F29CEEB.9060003@linux.vnet.ibm.com> On 02/01/2012 08:11 PM, Sharad Mishra wrote: > On Tue, 2012-01-31 at 19:58 -0200, Eduardo Lima (Etrunko) wrote: >> From: "Eduardo Lima (Etrunko)" >> [snip] >> + >> +bool list_foreach(list_t *list, list_foreach_cb cb, void *user_data) > > What is the idea of this function. Isn't list_find_node doing something > very similar? > The idea here is to execute a function callback for each node of the list without needing to know which is the first node and the condition to stop walking he list. Of course the user can actually do all this manually if necessary, with functions like list_first_node() list_last_node(), list_node_next() and list_node_prev(). In the ACL patch there are cases of use of both list_foreach() and the manual process. The disadvantage of using foreach is that you need to have and agreement between the caller of the user_data parameter. This is similar to glib list/slist implementation. >> +{ >> + list_node_t *node; >> + >> + if (list == NULL || list->head == NULL) >> + return true; /* nothing to do */ >> + >> + node = list->head; >> + do { >> + if (cb(node->data, user_data) == false) >> + return false; >> + >> + node = node->next; >> + } while (node != list->head); >> + >> + return true; >> +} >> + -- Eduardo de Barros Lima Software Engineer, Open Virtualization Linux Technology Center - IBM/Brazil eblima at br.ibm.com From eblima at linux.vnet.ibm.com Wed Feb 1 23:49:41 2012 From: eblima at linux.vnet.ibm.com (Eduardo Lima (Etrunko)) Date: Wed, 01 Feb 2012 21:49:41 -0200 Subject: [Libvirt-cim] [PATCH 3/3] ACL: Use linked list helper for filter refs In-Reply-To: <1328134256.4193.1482.camel@snmishra-desktop.beaverton.ibm.com> References: <1328047125-22037-1-git-send-email-eblima@linux.vnet.ibm.com> <1328047125-22037-4-git-send-email-eblima@linux.vnet.ibm.com> <1328134256.4193.1482.camel@snmishra-desktop.beaverton.ibm.com> Message-ID: <4F29CF95.6050700@linux.vnet.ibm.com> On 02/01/2012 08:10 PM, Sharad Mishra wrote: > On Tue, 2012-01-31 at 19:58 -0200, Eduardo Lima (Etrunko) wrote: >> From: "Eduardo Lima (Etrunko)" >> [snip] >> char *filter_to_xml(struct acl_filter *filter) >> { >> char *xml = NULL; >> xmlNodePtr root = NULL; >> xmlNodePtr tmp = NULL; >> - int i; >> >> root = xmlNewNode(NULL, BAD_CAST "filter"); >> if (root == NULL) >> @@ -1494,12 +1514,8 @@ char *filter_to_xml(struct acl_filter *filter) >> goto out; >> } >> >> - for (i = 0; i < filter->ref_ct; i++) { >> - tmp = xmlNewChild(root, NULL, BAD_CAST "filterref", NULL); >> - if (xmlNewProp(tmp, BAD_CAST "filter", >> - BAD_CAST filter->refs[i]) == NULL) >> - goto out; >> - } >> + if (!list_foreach(filter->refs, filter_ref_foreach, (void *) root)) > > why call list_foreach(), why not call filter_ref_foreach() directly? Because I want to call the function for every node in the list. This is exactly what the previous loop was doing. If I call this filter_ref_foreach() directly, it will be called only once. Best regards, -- Eduardo de Barros Lima Software Engineer, Open Virtualization Linux Technology Center - IBM/Brazil eblima at br.ibm.com From eblima at linux.vnet.ibm.com Wed Feb 1 23:59:17 2012 From: eblima at linux.vnet.ibm.com (Eduardo Lima (Etrunko)) Date: Wed, 01 Feb 2012 21:59:17 -0200 Subject: [Libvirt-cim] [PATCH 1/3] libxkutil: Linked list helper In-Reply-To: <1328134265.4193.1483.camel@snmishra-desktop.beaverton.ibm.com> References: <1328047125-22037-1-git-send-email-eblima@linux.vnet.ibm.com> <1328047125-22037-2-git-send-email-eblima@linux.vnet.ibm.com> <1328134265.4193.1483.camel@snmishra-desktop.beaverton.ibm.com> Message-ID: <4F29D1D5.5030306@linux.vnet.ibm.com> On 02/01/2012 08:11 PM, Sharad Mishra wrote: > On Tue, 2012-01-31 at 19:58 -0200, Eduardo Lima (Etrunko) wrote: >> From: "Eduardo Lima (Etrunko)" >> >> Signed-off-by: Eduardo Lima (Etrunko) >> --- >> libxkutil/Makefile.am | 51 +++++++--- >> libxkutil/list_util.c | 254 +++++++++++++++++++++++++++++++++++++++++++++++++ >> libxkutil/list_util.h | 73 ++++++++++++++ >> 3 files changed, 364 insertions(+), 14 deletions(-) >> create mode 100644 libxkutil/list_util.c >> create mode 100644 libxkutil/list_util.h >> >> diff --git a/libxkutil/Makefile.am b/libxkutil/Makefile.am >> index f1adc03..8d436ad 100644 >> --- a/libxkutil/Makefile.am >> +++ b/libxkutil/Makefile.am >> @@ -1,21 +1,44 @@ >> # Copyright IBM Corp. 2007 >> +AM_CFLAGS = \ >> + $(CFLAGS_STRICT) \ >> + -DLIBVIRTCIM_CONF=\"@sysconfdir@/@PACKAGE at .conf\" >> >> -AM_CFLAGS = $(CFLAGS_STRICT) \ >> - -DLIBVIRTCIM_CONF=\"@sysconfdir@/@PACKAGE at .conf\" >> +noinst_HEADERS = \ >> + cs_util.h \ >> + misc_util.h \ >> + device_parsing.h \ >> + xmlgen.h \ >> + infostore.h \ >> + pool_parsing.h \ >> + acl_parsing.h \ >> + list_util.h >> >> -noinst_HEADERS = cs_util.h misc_util.h device_parsing.h xmlgen.h infostore.h \ >> - pool_parsing.h acl_parsing.h >> +lib_LTLIBRARIES = \ >> + libxkutil.la >> >> -lib_LTLIBRARIES = libxkutil.la >> +libxkutil_la_SOURCES = \ >> + cs_util_instance.c \ >> + misc_util.c \ >> + device_parsing.c \ >> + xmlgen.c \ >> + infostore.c \ >> + pool_parsing.c \ >> + acl_parsing.c \ >> + list_util.c >> >> -libxkutil_la_SOURCES = cs_util_instance.c misc_util.c device_parsing.c \ >> - xmlgen.c infostore.c pool_parsing.c acl_parsing.c >> -libxkutil_la_LDFLAGS = -version-info @VERSION_INFO@ >> -libxkutil_la_LIBADD = @LIBVIRT_LIBS@ \ >> - @LIBUUID_LIBS@ >> +libxkutil_la_LDFLAGS = \ >> + -version-info @VERSION_INFO@ >> >> -noinst_PROGRAMS = xml_parse_test >> +libxkutil_la_LIBADD = \ >> + @LIBVIRT_LIBS@ \ >> + @LIBUUID_LIBS@ >> >> -xml_parse_test_SOURCES = xml_parse_test.c >> -xml_parse_test_LDADD = libxkutil.la \ >> - @LIBVIRT_LIBS@ >> +noinst_PROGRAMS = \ >> + xml_parse_test >> + >> +xml_parse_test_SOURCES = \ >> + xml_parse_test.c >> + >> +xml_parse_test_LDADD = \ >> + libxkutil.la \ >> + @LIBVIRT_LIBS@ >> diff --git a/libxkutil/list_util.c b/libxkutil/list_util.c >> new file mode 100644 >> index 0000000..84b2ba0 >> --- /dev/null >> +++ b/libxkutil/list_util.c >> @@ -0,0 +1,254 @@ >> +/* >> + * Copyright IBM Corp. 2012 >> + * >> + * Authors: >> + * Eduardo Lima (Etrunko) >> + * >> + * This library is free software; you can redistribute it and/or >> + * modify it under the terms of the GNU Lesser General Public >> + * License as published by the Free Software Foundation; either >> + * version 2.1 of the License, or (at your option) any later version. >> + * >> + * This library is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >> + * Lesser General Public License for more details. >> + * >> + * You should have received a copy of the GNU Lesser General Public >> + * License along with this library; if not, write to the Free Software >> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >> + */ >> +#ifdef HAVE_CONFIG_H >> +# include "config.h" >> +#endif >> + >> +#include >> + >> +#include "list_util.h" >> + >> +struct _list_node_t { >> + list_node_t *prev; >> + list_node_t *next; >> + void *data; >> +}; >> + >> +struct _list_t { >> + unsigned int count; >> + list_node_t *head; >> + list_data_free_cb free_cb; >> + list_data_cmp_cb cmp_cb; >> +}; >> + >> +list_t *list_new(list_data_free_cb free_cb, list_data_cmp_cb cmp_cb) >> +{ >> + list_t *l = calloc(1, sizeof(*l)); >> + if (l == NULL) >> + return NULL; >> + >> + l->free_cb = free_cb; >> + l->cmp_cb = cmp_cb; >> + return l; >> +} >> + >> +void list_free(list_t *list) >> +{ >> + list_node_t *n, *next; >> + >> + if (list == NULL || list->head == NULL) >> + return; >> + >> + n = list->head; >> + >> + do { >> + if (list->free_cb) >> + list->free_cb(n->data); >> + >> + next = n->next; >> + free(n); >> + n = next; >> + } while (n != list->head); >> + >> + free(list); >> +} >> + >> +void list_append(list_t *list, void *data) >> +{ >> + list_node_t *n; >> + >> + if (list == NULL) >> + return; >> + >> + n = calloc(1, sizeof(*n)); >> + >> + if (n == NULL) >> + return; >> + >> + n->data = data; >> + >> + if (list->head == NULL) { /* empty list */ >> + n->next = n->prev = n; >> + list->head = n; > > shouldn't you be setting the list->count to "0" here ? > Sorry, missed this comment. Yes it could be set to 0 but I think it is a bit too zealous. There are only two cases where list->head will be NULL. First is when the list_new() function is called. It will calloc a new list struct which will then assign list->count to 0. The other case is when all nodes are removed with list_remove_node(), which will decrement the counter until 0. -- Eduardo de Barros Lima Software Engineer, Open Virtualization Linux Technology Center - IBM/Brazil eblima at br.ibm.com From cvincent at linux.vnet.ibm.com Thu Feb 2 18:24:00 2012 From: cvincent at linux.vnet.ibm.com (Chip Vincent) Date: Thu, 02 Feb 2012 13:24:00 -0500 Subject: [Libvirt-cim] [PATCH 0/4] Update Filter{Entry,List} providers In-Reply-To: <1327967871-24219-1-git-send-email-eblima@linux.vnet.ibm.com> References: <1327967871-24219-1-git-send-email-eblima@linux.vnet.ibm.com> Message-ID: <4F2AD4C0.3030508@linux.vnet.ibm.com> Thanks. Pushed series. On 01/30/2012 06:57 PM, Eduardo Lima (Etrunko) wrote: > From: "Eduardo Lima (Etrunko)" > > These changes are necessary due to recent changes in the libvirt network > filters specification. Cimtests were also updated to match these changes. > > http://libvirt.org/formatnwfilter.html > > Eduardo Lima (Etrunko) (4): > FilterEntry: Change 'Priority' property type > FilterList: Add 'Priority' property > FilterEntry: Update action property > FilterEntry: Accept protocol id string values > > libxkutil/acl_parsing.c | 2 + > libxkutil/acl_parsing.h | 1 + > schema/FilterEntry.mof | 26 ++++++++++++------------ > schema/FilterList.mof | 9 ++++++++ > src/Makefile.am | 4 +- > src/Virt_FilterEntry.c | 49 +++++++++++++++++++++++++++++++++++----------- > src/Virt_FilterEntry.h | 6 +++++ > src/Virt_FilterList.c | 5 +++- > 8 files changed, 74 insertions(+), 28 deletions(-) > -- Chip Vincent Open Virtualization IBM Linux Technology Center cvincent at linux.vnet.ibm.com From cvincent at linux.vnet.ibm.com Thu Feb 2 18:27:36 2012 From: cvincent at linux.vnet.ibm.com (Chip Vincent) Date: Thu, 02 Feb 2012 13:27:36 -0500 Subject: [Libvirt-cim] [PATCH] [TEST] Update FilterList tests and helper In-Reply-To: <1327967968-26939-1-git-send-email-eblima@linux.vnet.ibm.com> References: <1327967968-26939-1-git-send-email-eblima@linux.vnet.ibm.com> Message-ID: <4F2AD598.2070605@linux.vnet.ibm.com> +1 and pushed. On 01/30/2012 06:59 PM, Eduardo Lima (Etrunko) wrote: > From: "Eduardo Lima (Etrunko)" > > According to recent changes in FilterList and FilterEntry providers. > > 03_create.py: > - Creation and deletion of AppliedFilterList instance > - Deletion of NestedFilterList instance > - Deletion of FilterList instance > > helper.py: > - Removed warning about Deprecated use of lxml functionality > - New filter rule actions > - Match protocol id > > Signed-off-by: Eduardo Lima (Etrunko) > --- > suites/libvirt-cim/cimtest/FilterList/03_create.py | 35 +++++++++++++--- > suites/libvirt-cim/cimtest/FilterList/helper.py | 42 +++++++++++++++++--- > 2 files changed, 64 insertions(+), 13 deletions(-) > > diff --git a/suites/libvirt-cim/cimtest/FilterList/03_create.py b/suites/libvirt-cim/cimtest/FilterList/03_create.py > index e828e92..551a01f 100644 > --- a/suites/libvirt-cim/cimtest/FilterList/03_create.py > +++ b/suites/libvirt-cim/cimtest/FilterList/03_create.py > @@ -38,6 +38,9 @@ from VirtLib.utils import run_remote > sup_types = ["KVM",] > > domain = None > +flist_name = None > +nested_name = None > +applied_name = None > > def get_filter_inst_and_inst_name(name): > try: > @@ -89,6 +92,7 @@ def create_filter_list(name): > > # A NestedFilterList instance will add the "clean-traffic" filter > # as an entry of the newly created FilterList > + global nested_name > logger.info("Creating NestedFilterList instance") > nested_name = test.CreateFilterListInstance(None, "KVM_NestedFilterList", > {"Antecedent":flist_name, > @@ -125,8 +129,11 @@ def get_nwport_inst_and_inst_name(domain_name): > > def cleanup(): > try: > - # Destroy filter list > - test.wbem.DeleteInstance(flist_name) > + # Destroy filter list instances > + for n in [applied_name, nested_name, flist_name]: > + if n is not None: > + logger.info("Deleting instance %s", n) > + test.wbem.DeleteInstance(n) > except Exception, e: > logger.error("Error deleting filter list: %s", e) > > @@ -165,15 +172,29 @@ def main(): > > # An AppliedFilterList Instance will apply the filter to the network > # port of the defined domain > - test.CreateFilterListInstance(None, "KVM_AppliedFilterList", > - {"Antecedent":nwport_name, > - "Dependent":flist_name}) > + global applied_name > + logger.info ("Creating AppliedFilterList instance") > + applied_name = test.CreateFilterListInstance(None, "KVM_AppliedFilterList", > + {"Antecedent":nwport_name, > + "Dependent":flist_name}) > + logger.info("Got AppliedFilterList name '%s'", applied_name) > + #applied = test.GetInstance(applied_name) > + #logger.info("Got AppliedFilterList '%s'", applied) > + > + # Check results > + filterref = test.libvirt_applied_filter_lists(domain_name)[0] > + rule = helper.FilterRule(filterref) > + if rule.filter != test_flist: > + raise Exception("AppliedFilterList name '%s' does not match expected '%s'", > + rule.filter, test_flist) > + > + test.cim_applied_filter_lists(domain_name) > + logger.info("AppliedFilterList created succesfully") > + result = PASS > except Exception, e: > logger.error("Caught exception: %s", e) > result = FAIL > > - # Check results > - > # Cleanup > cleanup() > > diff --git a/suites/libvirt-cim/cimtest/FilterList/helper.py b/suites/libvirt-cim/cimtest/FilterList/helper.py > index 9ae2f62..5202fa6 100644 > --- a/suites/libvirt-cim/cimtest/FilterList/helper.py > +++ b/suites/libvirt-cim/cimtest/FilterList/helper.py > @@ -252,7 +252,7 @@ class FilterListTest(BaseTestObject): > d = {} > for f in filters: > root = self.libvirt_filter_dumpxml(f[0]) > - if not root: > + if root is None: > return None > > d[f] = root > @@ -307,6 +307,22 @@ class FilterListTest(BaseTestObject): > > return self.Associators(_inst_name, result_class="CIM_FilterEntryBase") > # cim_entries_in_filter_list > + > + def libvirt_applied_filter_lists(self, dom_name): > + cmd = "virsh -q -c %s dumpxml %s 2>/dev/null" % (self.uri, dom_name) > + ret, dom_xml = run_remote(self.server, cmd) > + if ret: > + logger.error("Error retrieving domain xml for %s", dom_name) > + return None > + > + xdoc = etree.fromstring(dom_xml) > + filter_list = xdoc.xpath("/domain/devices/interface/filterref") > + return filter_list > + # libvirt_applied_filter_lists > + > + def cim_applied_filter_lists(self, dom_name): > + pass > + # cim_applied_filter_lists > # FilterListTest > > > @@ -319,9 +335,17 @@ class FilterRule(object): > __versions = {"ip" : "4", > "ipv6": "6",} > > - __actions = {"accept" : "1", > - "deny" : "2", > - "drop" : "2",} > + __actions = {"accept" : "1", > + "deny" : "2", > + "drop" : "2", > + "reject" : "3", > + "return" : "4", > + "continue" : "5",} > + > + __protocolids = {"ipv4": "2048", > + "arp" : "2054", > + "rarp": "32821", > + "ipv6": "34525",} > > __baserule_map = {"action" : "Action", > "direction" : "Direction", > @@ -394,7 +418,7 @@ class FilterRule(object): > > for e in element: > self.__dict = dict(self.__dict, **e.attrib) > - if not self.__type: > + if self.__type is None: > self.__type = e.tag > > try: > @@ -415,6 +439,12 @@ class FilterRule(object): > return self.__actions[self.__dict[key]] > elif key == "type": > return self.__type > + elif key == "protocolid": > + value = self.__dict[key] > + try: > + return self.__protocolids[value] > + except KeyError: > + return value > > try: > return self.__dict[key] > @@ -470,7 +500,7 @@ class FilterRule(object): > # convert the property value to string > prop = instance.properties[inst_key] > val = self.__getattr__(key) > - if val.startswith("0x"): > + if isinstance(val, str) and val.startswith("0x"): > inst_val = hex(int(prop.value)) > else: > inst_val = str(prop.value) -- Chip Vincent Open Virtualization IBM Linux Technology Center cvincent at linux.vnet.ibm.com From snmishra at linux.vnet.ibm.com Thu Feb 2 18:38:14 2012 From: snmishra at linux.vnet.ibm.com (Sharad Mishra) Date: Thu, 02 Feb 2012 10:38:14 -0800 Subject: [Libvirt-cim] [PATCH v6 0/3] Implementation of a linked list helper In-Reply-To: <1328047125-22037-1-git-send-email-eblima@linux.vnet.ibm.com> References: <1328047125-22037-1-git-send-email-eblima@linux.vnet.ibm.com> Message-ID: <1328207894.4193.1484.camel@snmishra-desktop.beaverton.ibm.com> +1 run cimtest before pushing. -Sharad On Tue, 2012-01-31 at 19:58 -0200, Eduardo Lima (Etrunko) wrote: > From: "Eduardo Lima (Etrunko)" > > This series provides a generic linked list implementation for libxkutil that is > based on the one originally developed for the libvirt domain events support > recently integrated upstream. > > As test case I ported the ComputerSystemIndication provider code to use this > list implementation. In the near future it will be also used by the event loop > that I am currently working on to allow systems with libvirt older than 0.9.0 > to make use of the same feature. > > Other possible use cases would be to port the code of libxkutil/*_parsing* to > also use the list implementation instead of static arrays. > > Changes from v5: > - Fix possible NULL dereference in list_first() > > Changes from v4: > - Fix possible NULL dereference in list_last_node() > - Fix possible leak in acl_parsing.c > > Changes from v3: > - Fix crashes in list_free(), list_first_node() and list_count() > - Include patch that ports the acl filter ref code to use the linked list > implementation > > Changes from v2: > - Make list struct private > > Changes from v1: > - Fix version iformation in Makefile.am > > Eduardo Lima (Etrunko) (3): > libxkutil: Linked list helper > CSI: Use list helper implementation > ACL: Use linked list helper for filter refs > > libxkutil/Makefile.am | 51 +++++-- > libxkutil/acl_parsing.c | 58 +++------ > libxkutil/acl_parsing.h | 5 +- > libxkutil/list_util.c | 254 +++++++++++++++++++++++++++++++++++ > libxkutil/list_util.h | 73 ++++++++++ > libxkutil/xmlgen.c | 30 +++- > src/Virt_ComputerSystemIndication.c | 95 ++++---------- > src/Virt_NestedFilterList.c | 73 ++++++----- > 8 files changed, 472 insertions(+), 167 deletions(-) > create mode 100644 libxkutil/list_util.c > create mode 100644 libxkutil/list_util.h > From snmishra at linux.vnet.ibm.com Thu Feb 2 18:38:51 2012 From: snmishra at linux.vnet.ibm.com (Sharad Mishra) Date: Thu, 02 Feb 2012 10:38:51 -0800 Subject: [Libvirt-cim] [PATCH 1/3] libxkutil: Linked list helper In-Reply-To: <1328047125-22037-2-git-send-email-eblima@linux.vnet.ibm.com> References: <1328047125-22037-1-git-send-email-eblima@linux.vnet.ibm.com> <1328047125-22037-2-git-send-email-eblima@linux.vnet.ibm.com> Message-ID: <1328207931.4193.1485.camel@snmishra-desktop.beaverton.ibm.com> +1 run cimtest before pushing -Sharad On Tue, 2012-01-31 at 19:58 -0200, Eduardo Lima (Etrunko) wrote: > From: "Eduardo Lima (Etrunko)" > > Signed-off-by: Eduardo Lima (Etrunko) > --- > libxkutil/Makefile.am | 51 +++++++--- > libxkutil/list_util.c | 254 +++++++++++++++++++++++++++++++++++++++++++++++++ > libxkutil/list_util.h | 73 ++++++++++++++ > 3 files changed, 364 insertions(+), 14 deletions(-) > create mode 100644 libxkutil/list_util.c > create mode 100644 libxkutil/list_util.h > > diff --git a/libxkutil/Makefile.am b/libxkutil/Makefile.am > index f1adc03..8d436ad 100644 > --- a/libxkutil/Makefile.am > +++ b/libxkutil/Makefile.am > @@ -1,21 +1,44 @@ > # Copyright IBM Corp. 2007 > +AM_CFLAGS = \ > + $(CFLAGS_STRICT) \ > + -DLIBVIRTCIM_CONF=\"@sysconfdir@/@PACKAGE at .conf\" > > -AM_CFLAGS = $(CFLAGS_STRICT) \ > - -DLIBVIRTCIM_CONF=\"@sysconfdir@/@PACKAGE at .conf\" > +noinst_HEADERS = \ > + cs_util.h \ > + misc_util.h \ > + device_parsing.h \ > + xmlgen.h \ > + infostore.h \ > + pool_parsing.h \ > + acl_parsing.h \ > + list_util.h > > -noinst_HEADERS = cs_util.h misc_util.h device_parsing.h xmlgen.h infostore.h \ > - pool_parsing.h acl_parsing.h > +lib_LTLIBRARIES = \ > + libxkutil.la > > -lib_LTLIBRARIES = libxkutil.la > +libxkutil_la_SOURCES = \ > + cs_util_instance.c \ > + misc_util.c \ > + device_parsing.c \ > + xmlgen.c \ > + infostore.c \ > + pool_parsing.c \ > + acl_parsing.c \ > + list_util.c > > -libxkutil_la_SOURCES = cs_util_instance.c misc_util.c device_parsing.c \ > - xmlgen.c infostore.c pool_parsing.c acl_parsing.c > -libxkutil_la_LDFLAGS = -version-info @VERSION_INFO@ > -libxkutil_la_LIBADD = @LIBVIRT_LIBS@ \ > - @LIBUUID_LIBS@ > +libxkutil_la_LDFLAGS = \ > + -version-info @VERSION_INFO@ > > -noinst_PROGRAMS = xml_parse_test > +libxkutil_la_LIBADD = \ > + @LIBVIRT_LIBS@ \ > + @LIBUUID_LIBS@ > > -xml_parse_test_SOURCES = xml_parse_test.c > -xml_parse_test_LDADD = libxkutil.la \ > - @LIBVIRT_LIBS@ > +noinst_PROGRAMS = \ > + xml_parse_test > + > +xml_parse_test_SOURCES = \ > + xml_parse_test.c > + > +xml_parse_test_LDADD = \ > + libxkutil.la \ > + @LIBVIRT_LIBS@ > diff --git a/libxkutil/list_util.c b/libxkutil/list_util.c > new file mode 100644 > index 0000000..84b2ba0 > --- /dev/null > +++ b/libxkutil/list_util.c > @@ -0,0 +1,254 @@ > +/* > + * Copyright IBM Corp. 2012 > + * > + * Authors: > + * Eduardo Lima (Etrunko) > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + */ > +#ifdef HAVE_CONFIG_H > +# include "config.h" > +#endif > + > +#include > + > +#include "list_util.h" > + > +struct _list_node_t { > + list_node_t *prev; > + list_node_t *next; > + void *data; > +}; > + > +struct _list_t { > + unsigned int count; > + list_node_t *head; > + list_data_free_cb free_cb; > + list_data_cmp_cb cmp_cb; > +}; > + > +list_t *list_new(list_data_free_cb free_cb, list_data_cmp_cb cmp_cb) > +{ > + list_t *l = calloc(1, sizeof(*l)); > + if (l == NULL) > + return NULL; > + > + l->free_cb = free_cb; > + l->cmp_cb = cmp_cb; > + return l; > +} > + > +void list_free(list_t *list) > +{ > + list_node_t *n, *next; > + > + if (list == NULL || list->head == NULL) > + return; > + > + n = list->head; > + > + do { > + if (list->free_cb) > + list->free_cb(n->data); > + > + next = n->next; > + free(n); > + n = next; > + } while (n != list->head); > + > + free(list); > +} > + > +void list_append(list_t *list, void *data) > +{ > + list_node_t *n; > + > + if (list == NULL) > + return; > + > + n = calloc(1, sizeof(*n)); > + > + if (n == NULL) > + return; > + > + n->data = data; > + > + if (list->head == NULL) { /* empty list */ > + n->next = n->prev = n; > + list->head = n; > + goto end; > + } > + > + n->next = list->head; > + n->prev = list->head->prev; > + > + list->head->prev->next = n; > + list->head->prev = n; > + > + end: > + list->count += 1; > +} > + > +void list_prepend(list_t *list, void *data) > +{ > + list_append(list, data); > + list->head = list->head->prev; > +} > + > +void *list_find(list_t *list, void *user_data) > +{ > + list_node_t *n = list_find_node(list, user_data); > + return list_node_data_get(n); > +} > + > +list_node_t *list_find_node(list_t *list, void *user_data) > +{ > + list_node_t *n; > + > + if (list == NULL || list->head == NULL || list->cmp_cb == NULL) > + return NULL; > + > + n = list->head; > + do { > + if (list->cmp_cb(n->data, user_data) == 0) > + return n; > + > + n = n->next; > + } while (n != list->head); > + > + return NULL; > +} > + > +void list_remove(list_t *list, void *data) > +{ > + list_node_t *n = list_find_node(list, data); > + list_remove_node(list, n); > +} > + > +void list_remove_node(list_t *list, list_node_t *node) > +{ > + if (list == NULL || list->head == NULL || node == NULL) > + return; > + > + if (node->next == node) { /* only 1 item */ > + list->head = NULL; > + } else { > + if (node == list->head) /* first node */ > + list->head = node->next; > + > + node->prev->next = node->next; > + node->next->prev = node->prev; > + } > + > + if (list->free_cb) > + list->free_cb(node->data); > + > + free(node); > + list->count -= 1; > +} > + > +bool list_foreach(list_t *list, list_foreach_cb cb, void *user_data) > +{ > + list_node_t *node; > + > + if (list == NULL || list->head == NULL) > + return true; /* nothing to do */ > + > + node = list->head; > + do { > + if (cb(node->data, user_data) == false) > + return false; > + > + node = node->next; > + } while (node != list->head); > + > + return true; > +} > + > +unsigned int list_count(list_t *list) > +{ > + if (list == NULL) > + return 0; > + > + return list->count; > +} > + > +void *list_node_data_get(list_node_t *node) > +{ > + if (node == NULL) > + return NULL; > + > + return node->data; > +} > + > +void list_node_data_set(list_node_t *node, void *data) > +{ > + if (node == NULL) > + return; > + > + node->data = data; > +} > + > +void *list_first(list_t *list) > +{ > + return list_node_data_get(list_first_node(list)); > +} > + > +list_node_t *list_first_node(list_t *list) > +{ > + if (list == NULL) > + return NULL; > + > + return list->head; > +} > + > +void *list_last(list_t *list) > +{ > + return list_node_data_get(list_last_node(list)); > +} > + > +list_node_t *list_last_node(list_t *list) > +{ > + if (list == NULL || list->head == NULL) > + return NULL; > + > + return list->head->prev; > +} > + > +void *list_node_next(list_node_t *node) > +{ > + return list_node_data_get(list_node_next_node(node)); > +} > + > +list_node_t *list_node_next_node(list_node_t *node) > +{ > + if (node == NULL) > + return NULL; > + > + return node->next; > +} > + > +void *list_node_prev(list_node_t *node) > +{ > + return list_node_data_get(list_node_prev_node(node)); > +} > + > +list_node_t *list_node_prev_node(list_node_t *node) > +{ > + if (node == NULL) > + return NULL; > + > + return node->prev; > +} > diff --git a/libxkutil/list_util.h b/libxkutil/list_util.h > new file mode 100644 > index 0000000..1809c2e > --- /dev/null > +++ b/libxkutil/list_util.h > @@ -0,0 +1,73 @@ > +/* > + * Copyright IBM Corp. 2012 > + * > + * Authors: > + * Eduardo Lima (Etrunko) > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + */ > + > +#ifndef __LIST_UTIL_H > +#define __LIST_UTIL_H > + > +#include > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +typedef void (*list_data_free_cb)(void *data); > +typedef int (*list_data_cmp_cb)(void *list_data, void *user_data); > +typedef bool (*list_foreach_cb)(void *list_data, void *user_data); > + > +typedef struct _list_node_t list_node_t; > +typedef struct _list_t list_t; > + > +list_t *list_new(list_data_free_cb free_cb, list_data_cmp_cb cmp_cb); > +void list_free(list_t *list); > + > +void list_append(list_t *list, void *data); > +void list_prepend(list_t *list, void *data); > + > +void *list_find(list_t *list, void *user_data); > +list_node_t *list_find_node(list_t *list, void *user_data); > + > +void list_remove(list_t *list, void *data); > +void list_remove_node(list_t *list, list_node_t *node); > + > +bool list_foreach(list_t *list, list_foreach_cb cb, void *user_data); > + > +inline unsigned int list_count(list_t *list); > + > +inline void *list_node_data_get(list_node_t *node); > +inline void list_node_data_set(list_node_t *node, void *data); > + > +inline void *list_first(list_t *list); > +inline list_node_t *list_first_node(list_t *list); > + > +inline void *list_last(list_t *list); > +inline list_node_t *list_last_node(list_t *list); > + > +inline void *list_node_next(list_node_t *node); > +inline list_node_t *list_node_next_node(list_node_t *node); > + > +inline void *list_node_prev(list_node_t *node); > +inline list_node_t *list_node_prev_node(list_node_t *node); > + > +#ifdef __cplusplus > +} /* extern "C" */ > +#endif > + > +#endif /* __LIST_UTIL_H */ From snmishra at linux.vnet.ibm.com Thu Feb 2 18:39:59 2012 From: snmishra at linux.vnet.ibm.com (Sharad Mishra) Date: Thu, 02 Feb 2012 10:39:59 -0800 Subject: [Libvirt-cim] [PATCH 3/3] ACL: Use linked list helper for filter refs In-Reply-To: <1328047125-22037-4-git-send-email-eblima@linux.vnet.ibm.com> References: <1328047125-22037-1-git-send-email-eblima@linux.vnet.ibm.com> <1328047125-22037-4-git-send-email-eblima@linux.vnet.ibm.com> Message-ID: <1328207999.4193.1487.camel@snmishra-desktop.beaverton.ibm.com> +1 run cimtest before pushing -Sharad On Tue, 2012-01-31 at 19:58 -0200, Eduardo Lima (Etrunko) wrote: > From: "Eduardo Lima (Etrunko)" > > Signed-off-by: Eduardo Lima (Etrunko) > --- > libxkutil/acl_parsing.c | 58 +++++++++------------------------ > libxkutil/acl_parsing.h | 5 ++- > libxkutil/xmlgen.c | 30 +++++++++++++---- > src/Virt_NestedFilterList.c | 73 +++++++++++++++++++++++------------------- > 4 files changed, 82 insertions(+), 84 deletions(-) > > diff --git a/libxkutil/acl_parsing.c b/libxkutil/acl_parsing.c > index 9c4b4b2..6dd481b 100644 > --- a/libxkutil/acl_parsing.c > +++ b/libxkutil/acl_parsing.c > @@ -141,11 +141,7 @@ void cleanup_filter(struct acl_filter *filter) > free(filter->rules); > filter->rule_ct = 0; > > - for (i = 0; i < filter->ref_ct; i++) > - free(filter->refs[i]); > - > - free(filter->refs); > - filter->ref_ct = 0; > + list_free(filter->refs); > } > > void cleanup_filters(struct acl_filter **filters, int count) > @@ -610,58 +606,36 @@ int append_filter_rule(struct acl_filter *filter, struct acl_rule *rule) > return 1; > } > > -int append_filter_ref(struct acl_filter *filter, char *name) > + > +static int filter_ref_cmp(void *list_data, void *user_data) > { > - int i; > - char **old_refs = NULL; > + return strcmp((const char *)list_data, (const char *) user_data); > +} > > - if ((filter == NULL) || (name == NULL)) > +int append_filter_ref(struct acl_filter *filter, char *name) > +{ > + if (filter == NULL || name == NULL) > return 0; > > - for (i = 0; i < filter->ref_ct; i++) > - if (STREQC(filter->refs[i], name)) > - return 0; /* already exists */ > - > - old_refs = filter->refs; > - > - filter->refs = malloc((filter->ref_ct + 1) * sizeof(char *)); > + if (filter->refs == NULL) > + filter->refs = list_new(free, filter_ref_cmp); > > - if (filter->refs == NULL) { > - CU_DEBUG("Failed to allocate memory for new ref"); > - filter->refs = old_refs; > - return 0; > + if (list_find(filter->refs, name) != NULL) { > + free(name); > + return 0; /* already exists */ > } > > - memcpy(filter->refs, old_refs, filter->ref_ct * sizeof(char *)); > - > - filter->refs[filter->ref_ct] = name; > - filter->ref_ct++; > - > - free(old_refs); > + list_append(filter->refs, name); > > return 1; > } > > int remove_filter_ref(struct acl_filter *filter, const char *name) > { > - int i; > - char **old_refs = NULL; > - > - if ((filter == NULL) || (name == NULL)) > + if (filter == NULL || filter->refs == NULL || name == NULL) > return 0; > > - /* TODO: called infrequently, but needs optimization */ > - old_refs = filter->refs; > - filter->ref_ct = 0; > - > - for (i = 0; i < filter->ref_ct; i++) { > - if (STREQC(old_refs[i], name)) { > - free(old_refs[i]); > - } > - else if(append_filter_ref(filter, old_refs[i]) == 0) { > - return 0; > - } > - } > + list_remove(filter->refs, (void *) name); > > return 1; > } > diff --git a/libxkutil/acl_parsing.h b/libxkutil/acl_parsing.h > index 5b99175..e49f384 100644 > --- a/libxkutil/acl_parsing.h > +++ b/libxkutil/acl_parsing.h > @@ -26,6 +26,8 @@ > #include > #include > > +#include "list_util.h" > + > struct acl_mac_rule { > char *srcmacaddr; > char *srcmacmask; > @@ -152,8 +154,7 @@ struct acl_filter { > struct acl_rule **rules; > int rule_ct; > > - char **refs; > - int ref_ct; > + list_t *refs; > }; > > void cleanup_rule(struct acl_rule *rule); > diff --git a/libxkutil/xmlgen.c b/libxkutil/xmlgen.c > index 9a2ada9..5c16ebe 100644 > --- a/libxkutil/xmlgen.c > +++ b/libxkutil/xmlgen.c > @@ -28,6 +28,7 @@ > #include > > #include "xmlgen.h" > +#include "list_util.h" > > #ifndef TEST > #include "misc_util.h" > @@ -1467,12 +1468,31 @@ char *res_to_xml(struct virt_pool_res *res) { > return xml; > } > > +static bool filter_ref_foreach(void *list_data, void *user_data) > +{ > + char *filter = (char *) list_data; > + xmlNodePtr root = (xmlNodePtr) user_data; > + xmlNodePtr tmp = NULL; > + > + tmp = xmlNewChild(root, NULL, BAD_CAST "filterref", NULL); > + if (tmp == NULL) { > + CU_DEBUG("Error creating filterref node"); > + return false; > + } > + > + if (xmlNewProp(tmp, BAD_CAST "filter", BAD_CAST list_data) == NULL) { > + CU_DEBUG("Error adding filter attribute '%s'", filter); > + return false; > + } > + > + return true; > +} > + > char *filter_to_xml(struct acl_filter *filter) > { > char *xml = NULL; > xmlNodePtr root = NULL; > xmlNodePtr tmp = NULL; > - int i; > > root = xmlNewNode(NULL, BAD_CAST "filter"); > if (root == NULL) > @@ -1494,12 +1514,8 @@ char *filter_to_xml(struct acl_filter *filter) > goto out; > } > > - for (i = 0; i < filter->ref_ct; i++) { > - tmp = xmlNewChild(root, NULL, BAD_CAST "filterref", NULL); > - if (xmlNewProp(tmp, BAD_CAST "filter", > - BAD_CAST filter->refs[i]) == NULL) > - goto out; > - } > + if (!list_foreach(filter->refs, filter_ref_foreach, (void *) root)) > + goto out; > > xml = tree_to_xml(root); > > diff --git a/src/Virt_NestedFilterList.c b/src/Virt_NestedFilterList.c > index 81c4408..a8565d6 100644 > --- a/src/Virt_NestedFilterList.c > +++ b/src/Virt_NestedFilterList.c > @@ -34,6 +34,7 @@ > > #include "acl_parsing.h" > #include "misc_util.h" > +#include "list_util.h" > #include "Virt_FilterList.h" > > static const CMPIBroker *_BROKER; > @@ -120,7 +121,7 @@ static CMPIStatus parent_to_child( > CMPIInstance *instance = NULL; > const char * name = NULL; > virConnectPtr conn = NULL; > - int i; > + list_node_t *head, *node; > > CU_DEBUG("Reference = %s", REF2STR(reference)); > > @@ -139,29 +140,39 @@ static CMPIStatus parent_to_child( > if (parent_filter == NULL) > goto out; > > - for (i = 0; i < parent_filter->ref_ct; i++) { > - get_filter_by_name(conn, parent_filter->refs[i], > - &child_filter); > - if (child_filter == NULL) > - continue; > - > - CU_DEBUG("Processing %s,", child_filter->name); > - > - s = instance_from_filter(_BROKER, > - info->context, > - reference, > - child_filter, > - &instance); > + /* Walk refs list */ > + if (parent_filter->refs == NULL) > + goto end; > + > + head = node = list_first_node(parent_filter->refs); > + if (head == NULL) > + goto end; > + > + do { > + name = (const char *) list_node_data_get(node); > + get_filter_by_name(conn, name, &child_filter); > + if (child_filter != NULL) { > + CU_DEBUG("Processing %s,", child_filter->name); > + > + s = instance_from_filter(_BROKER, > + info->context, > + reference, > + child_filter, > + &instance); > + > + if (instance != NULL) { > + CU_DEBUG("Adding instance to inst_list"); > + inst_list_add(list, instance); > + } > > - if (instance != NULL) { > - CU_DEBUG("Adding instance to inst_list"); > - inst_list_add(list, instance); > + cleanup_filters(&child_filter, 1); > } > > - cleanup_filters(&child_filter, 1); > instance = NULL; > - } > + node = list_node_next_node(node); > + } while (node != head); > > + end: > cleanup_filters(&parent_filter, 1); > > out: > @@ -183,7 +194,7 @@ static CMPIStatus child_to_parent( > CMPIInstance *instance = NULL; > const char *name = NULL; > virConnectPtr conn = NULL; > - int count, i, j; > + int count, i; > > CU_DEBUG("Reference = %s", REF2STR(reference)); > > @@ -206,24 +217,20 @@ static CMPIStatus child_to_parent( > > /* return any filter that has name in refs */ > for (i = 0; i < count; i++) { > - for (j = 0; j < _list[i].ref_ct; j++) { > - if (STREQC(name, _list[i].refs[j])) { > - CU_DEBUG("Processing %s,", _list[i].name); > + if (list_find_node(_list[i].refs, (void *) name) != NULL) { > + CU_DEBUG("Processing %s,", _list[i].name); > > - s = instance_from_filter(_BROKER, > - info->context, > - reference, > - &_list[i], > - &instance); > - > - if (instance != NULL) > - inst_list_add(list, instance); > + s = instance_from_filter(_BROKER, > + info->context, > + reference, > + &_list[i], > + &instance); > > + if (instance != NULL) { > + inst_list_add(list, instance); > instance = NULL; > } > - > } > - > } > > cleanup_filters(&_list, count); From snmishra at linux.vnet.ibm.com Thu Feb 2 18:39:14 2012 From: snmishra at linux.vnet.ibm.com (Sharad Mishra) Date: Thu, 02 Feb 2012 10:39:14 -0800 Subject: [Libvirt-cim] [PATCH 2/3] CSI: Use list helper implementation In-Reply-To: <1328047125-22037-3-git-send-email-eblima@linux.vnet.ibm.com> References: <1328047125-22037-1-git-send-email-eblima@linux.vnet.ibm.com> <1328047125-22037-3-git-send-email-eblima@linux.vnet.ibm.com> Message-ID: <1328207954.4193.1486.camel@snmishra-desktop.beaverton.ibm.com> +1 run cimtest before pushing -Sharad On Tue, 2012-01-31 at 19:58 -0200, Eduardo Lima (Etrunko) wrote: > From: "Eduardo Lima (Etrunko)" > > Signed-off-by: Eduardo Lima (Etrunko) > --- > src/Virt_ComputerSystemIndication.c | 95 ++++++++++------------------------- > 1 files changed, 26 insertions(+), 69 deletions(-) > > diff --git a/src/Virt_ComputerSystemIndication.c b/src/Virt_ComputerSystemIndication.c > index 6ef2ddc..712e12c 100644 > --- a/src/Virt_ComputerSystemIndication.c > +++ b/src/Virt_ComputerSystemIndication.c > @@ -19,6 +19,10 @@ > * License along with this library; if not, write to the Free Software > * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > */ > +#ifdef HAVE_CONFIG_H > +# include "config.h" > +#endif > + > #include > #include > #include > @@ -34,11 +38,11 @@ > #include > > #include > -#include > #include > -#include > > -#include "config.h" > +#include > +#include > +#include > > #include "Virt_ComputerSystem.h" > #include "Virt_ComputerSystemIndication.h" > @@ -64,8 +68,6 @@ struct _csi_dom_xml_t { > char uuid[VIR_UUID_STRING_BUFLEN]; > char *name; > char *xml; > - csi_dom_xml_t *next; > - csi_dom_xml_t *prev; > }; > > typedef struct _csi_thread_data_t csi_thread_data_t; > @@ -73,7 +75,7 @@ struct _csi_thread_data_t { > CMPI_THREAD_TYPE id; > int active_filters; > int dom_count; > - csi_dom_xml_t *dom_list; > + list_t *dom_list; > struct ind_args *args; > }; > > @@ -83,15 +85,24 @@ static bool lifecycle_enabled = false; > static csi_thread_data_t csi_thread_data[CSI_NUM_PLATFORMS] = {{0}, {0}, {0}}; > > /* > - * Domain list manipulation > + * Domain manipulation > */ > -static void csi_dom_xml_free(csi_dom_xml_t *dom) > +static void csi_dom_xml_free(void *data) > { > + csi_dom_xml_t *dom = (csi_dom_xml_t *) data; > free(dom->xml); > free(dom->name); > free(dom); > } > > +static int csi_dom_xml_cmp(void *data, void *cmp_cb_data) > +{ > + csi_dom_xml_t *dom = (csi_dom_xml_t *) data; > + const char *uuid = (const char *) cmp_cb_data; > + > + return strcmp(dom->uuid, uuid); > +} > + > static int csi_dom_xml_set(csi_dom_xml_t *dom, virDomainPtr dom_ptr, CMPIStatus *s) > { > const char *name; > @@ -150,65 +161,10 @@ static csi_dom_xml_t *csi_dom_xml_new(virDomainPtr dom_ptr, CMPIStatus *s) > static void csi_thread_dom_list_append(csi_thread_data_t *thread, > csi_dom_xml_t *dom) > { > - /* empty list */ > - if (thread->dom_list == NULL) { > - dom->next = dom->prev = dom; > - thread->dom_list = dom; > - goto end; > - } > - > - dom->next = thread->dom_list; > - dom->prev = thread->dom_list->prev; > - > - thread->dom_list->prev->next = dom; > - thread->dom_list->prev = dom; > - > - end: > - thread->dom_count += 1; > -} > - > -static csi_dom_xml_t *csi_thread_dom_list_find(csi_thread_data_t *thread, > - const char *uuid) > -{ > - csi_dom_xml_t *dom; > - > if (thread->dom_list == NULL) > - return NULL; > - > - dom = thread->dom_list; > - > - do { > - if (STREQ(dom->uuid, uuid)) > - return dom; > - > - dom = dom->next; > - } while (dom != thread->dom_list); > + thread->dom_list = list_new(csi_dom_xml_free, csi_dom_xml_cmp); > > - return NULL; > -} > - > -static void csi_thread_dom_list_remove(csi_thread_data_t *thread, > - csi_dom_xml_t *dom) > -{ > - if (dom->next == dom) { /* Only one node */ > - thread->dom_list = NULL; > - } else { > - if (thread->dom_list == dom) /* First node */ > - thread->dom_list = dom->next; > - > - dom->prev->next = dom->next; > - dom->next->prev = dom->prev; > - } > - > - thread->dom_count -= 1; > - > - csi_dom_xml_free(dom); > -} > - > -static void csi_thread_dom_list_free(csi_thread_data_t *thread) > -{ > - while(thread->dom_list != NULL) > - csi_thread_dom_list_remove(thread, thread->dom_list); > + list_append(thread->dom_list, dom); > } > > static void csi_free_thread_data(void *data) > @@ -218,7 +174,8 @@ static void csi_free_thread_data(void *data) > if (data == NULL) > return; > > - csi_thread_dom_list_free(thread); > + list_free(thread->dom_list); > + thread->dom_list = NULL; > stdi_free_ind_args(&thread->args); > } > > @@ -512,7 +469,7 @@ static int update_domain_list(virConnectPtr conn, csi_thread_data_t *thread) > CMPIStatus s = {CMPI_RC_OK, NULL}; > int i, count; > > - csi_thread_dom_list_free(thread); > + list_free(thread->dom_list); > > count = get_domain_list(conn, &dom_ptr_list); > > @@ -574,7 +531,7 @@ static int csi_domain_event_cb(virConnectPtr conn, > if (cs_event != CS_CREATED) { > char uuid[VIR_UUID_STRING_BUFLEN] = {0}; > virDomainGetUUIDString(dom, &uuid[0]); > - dom_xml = csi_thread_dom_list_find(thread, uuid); > + dom_xml = list_find(thread->dom_list, uuid); > } > > if (dom_xml == NULL) { > @@ -595,7 +552,7 @@ static int csi_domain_event_cb(virConnectPtr conn, > } > } else if (event == VIR_DOMAIN_EVENT_DEFINED && > detail == VIR_DOMAIN_EVENT_UNDEFINED_REMOVED) { > - csi_thread_dom_list_remove(thread, dom_xml); > + list_remove(thread->dom_list, dom_xml); > } > > end: From bestor at us.ibm.com Thu Feb 2 22:13:04 2012 From: bestor at us.ibm.com (Gareth S Bestor) Date: Thu, 2 Feb 2012 16:13:04 -0600 Subject: [Libvirt-cim] [PATCH] Plan9fs (aka 9pfs, VirtFS) support for QEMU/KVM environment In-Reply-To: <20111209111656.20645.54429.stgit@deepak-ThinkPad-T60p> Message-ID: The schema changes for this patch look fairly innocent, and in keeping with how the KVM_DiskResourceAllocationSetting class has already extended the CIM_RASD superclass with implementation-specific properties. I also did not find any relevant 'prior art' in the existing DSP1041 'ResourceAllocationProfile' that would apply here. +1 wrt schema extensions. - G Dr. Gareth S. Bestor IBM Senior Software Engineer Systems & Technology Group - Systems Management Standards 971-285-6375 (mobile) bestor at us.ibm.com [Libvirt-cim] [PATCH] Plan9fs (aka 9pfs, VirtFS) support for QEMU/KVM environment Deepak C Shetty to: libvirt-cim 12/09/11 05:18 AM Sent by: libvirt-cim-bounces at redhat.com Please respond to List for discussion and development of libvirt CIM VirtFS is virtualization aware file system pass-through which provides the functionality to share host file system inside the guest. Its supported in libvirt via the xml node/tag. This patch introduces the filesystem support in KVM_DiskRASD and its associated changes needed to support VirtFS in libvirt-cim. For further details... Virtfs home page/wiki : http://v9fs.sourceforge.net/ Virtfs setup for QEMU : http://wiki.qemu.org/Documentation/9psetup Virtfs support in libvirt : http://libvirt.org/formatdomain.html#elementsFilesystems An example of the node in libvirt, supporting VirtFS... Signed-off-by: Deepak C Shetty --- libxkutil/device_parsing.c | 8 ++++++++ libxkutil/device_parsing.h | 1 + libxkutil/xmlgen.c | 15 +++++++++++++++ schema/ResourceAllocationSettingData.mof | 7 +++++-- src/Virt_RASD.c | 6 ++++++ src/Virt_RASD.h | 1 + src/Virt_VirtualSystemManagementService.c | 8 ++++++++ 7 files changed, 44 insertions(+), 2 deletions(-) diff --git a/libxkutil/device_parsing.c b/libxkutil/device_parsing.c index 371838f..6a09e7d 100644 --- a/libxkutil/device_parsing.c +++ b/libxkutil/device_parsing.c @@ -65,6 +65,7 @@ static void cleanup_disk_device(struct disk_device *dev) free(dev->source); free(dev->virtual_dev); free(dev->bus_type); + free(dev->access_mode); } static void cleanup_vsi_device(struct vsi_device *dev) @@ -220,6 +221,8 @@ static int parse_fs_device(xmlNode *dnode, struct virt_device **vdevs) goto err; } + ddev->access_mode = get_attr_value(dnode, "accessmode"); + for (child = dnode->children; child != NULL; child = child->next) { if (XSTREQ(child->name, "source")) { ddev->source = get_attr_value(child, "dir"); @@ -233,6 +236,8 @@ static int parse_fs_device(xmlNode *dnode, struct virt_device **vdevs) CU_DEBUG("No target dir"); goto err; } + } else if (XSTREQ(child->name, "driver")) { + ddev->driver_type = get_attr_value(child, "type"); } } @@ -870,6 +875,7 @@ struct virt_device *virt_device_dup(struct virt_device *_dev) DUP_FIELD(dev, _dev, dev.disk.source); DUP_FIELD(dev, _dev, dev.disk.virtual_dev); DUP_FIELD(dev, _dev, dev.disk.bus_type); + DUP_FIELD(dev, _dev, dev.disk.access_mode); dev->dev.disk.disk_type = _dev->dev.disk.disk_type; dev->dev.disk.readonly = _dev->dev.disk.readonly; dev->dev.disk.shareable = _dev->dev.disk.shareable; @@ -1436,6 +1442,8 @@ int disk_type_from_file(const char *path) return DISK_PHY; else if (S_ISREG(s.st_mode)) return DISK_FILE; + else if (S_ISDIR(s.st_mode)) + return DISK_FS; else return DISK_UNKNOWN; } diff --git a/libxkutil/device_parsing.h b/libxkutil/device_parsing.h index ab104d9..6bed040 100644 --- a/libxkutil/device_parsing.h +++ b/libxkutil/device_parsing.h @@ -55,6 +55,7 @@ struct disk_device { bool shareable; char *bus_type; char *cache; + char *access_mode; /* access modes for DISK_FS (filesystem) type */ }; struct net_device { diff --git a/libxkutil/xmlgen.c b/libxkutil/xmlgen.c index 4cca75b..44a6158 100644 --- a/libxkutil/xmlgen.c +++ b/libxkutil/xmlgen.c @@ -152,6 +152,21 @@ static const char *disk_fs_xml(xmlNodePtr root, struct disk_device *dev) if (fs == NULL) return XML_ERROR; + /* filesystem prop 'type' not needed to be generated, as it defaults + to 'mount' in libvirt, the only supported value for now. */ + + /* filesystem prop 'accessmode' defaults to 'passthrough' in libvirt. + So generate here if specified by user, else leave it to libvirt. */ + + if (dev->access_mode) { + xmlNewProp(fs, BAD_CAST "accessmode", BAD_CAST dev->access_mode); + } + + if(dev->driver_type) { + tmp = xmlNewChild(fs, NULL, BAD_CAST "driver", NULL); + xmlNewProp(tmp, BAD_CAST "type", BAD_CAST dev->driver_type); + } + tmp = xmlNewChild(fs, NULL, BAD_CAST "source", NULL); if (tmp == NULL) return XML_ERROR; diff --git a/schema/ResourceAllocationSettingData.mof b/schema/ResourceAllocationSettingData.mof index 3da503d..108dff7 100644 --- a/schema/ResourceAllocationSettingData.mof +++ b/schema/ResourceAllocationSettingData.mof @@ -40,8 +40,8 @@ class KVM_DiskResourceAllocationSettingData : KVM_ResourceAllocationSettingData string VirtualDevice; [Description ("Device emulation type"), - ValueMap {"0", "1", "2"}, - Values {"Disk", "CDROM", "floppy"}] + ValueMap {"0", "1", "2", "3"}, + Values {"Disk", "CDROM", "floppy", "filesystem"}] uint16 EmulatedType; [Description ("Bus type of the device")] @@ -58,6 +58,9 @@ class KVM_DiskResourceAllocationSettingData : KVM_ResourceAllocationSettingData [Description ("cache setting for device")] string DriverCache; + + [Description ("filesystem access mode")] + string AccessMode; }; [Description ("LXC virtual disk configuration"), diff --git a/src/Virt_RASD.c b/src/Virt_RASD.c index 9305c8d..29bf10d 100644 --- a/src/Virt_RASD.c +++ b/src/Virt_RASD.c @@ -397,6 +397,12 @@ static CMPIStatus set_disk_rasd_params(const CMPIBroker *broker, (CMPIValue *)dev->dev.disk.cache, CMPI_chars); + if(dev->dev.disk.access_mode) + CMSetProperty(inst, + "AccessMode", + (CMPIValue *)dev->dev.disk.access_mode, + CMPI_chars); + virStoragePoolFree(pool); virStorageVolFree(vol); virConnectClose(conn); diff --git a/src/Virt_RASD.h b/src/Virt_RASD.h index 550543a..cef4224 100644 --- a/src/Virt_RASD.h +++ b/src/Virt_RASD.h @@ -26,6 +26,7 @@ #define VIRT_DISK_TYPE_DISK 0 #define VIRT_DISK_TYPE_CDROM 1 #define VIRT_DISK_TYPE_FLOPPY 2 +#define VIRT_DISK_TYPE_FS 3 char *rasd_to_xml(CMPIInstance *rasd); diff --git a/src/Virt_VirtualSystemManagementService.c b/src/Virt_VirtualSystemManagementService.c index 21979c3..3cdca86 100644 --- a/src/Virt_VirtualSystemManagementService.c +++ b/src/Virt_VirtualSystemManagementService.c @@ -1022,6 +1022,8 @@ static const char *disk_rasd_to_vdev(CMPIInstance *inst, } else if (type == VIRT_DISK_TYPE_FLOPPY) dev->dev.disk.device = strdup("floppy"); + else if (type == VIRT_DISK_TYPE_FS) + dev->dev.disk.device = strdup("filesystem"); else return "Invalid value for EmulatedType"; @@ -1056,6 +1058,12 @@ static const char *disk_rasd_to_vdev(CMPIInstance *inst, else dev->dev.disk.cache = strdup(val); + free(dev->dev.disk.access_mode); + if (cu_get_str_prop(inst, "AccessMode", &val) != CMPI_RC_OK) + dev->dev.disk.access_mode = NULL; + else + dev->dev.disk.access_mode = strdup(val); + free(dev->id); dev->id = strdup(dev->dev.disk.virtual_dev); _______________________________________________ Libvirt-cim mailing list Libvirt-cim at redhat.com https://www.redhat.com/mailman/listinfo/libvirt-cim -------------- next part -------------- An HTML attachment was scrubbed... URL: From cvincent at linux.vnet.ibm.com Fri Feb 3 13:31:25 2012 From: cvincent at linux.vnet.ibm.com (Chip Vincent) Date: Fri, 03 Feb 2012 08:31:25 -0500 Subject: [Libvirt-cim] [PATCH v6 0/3] Implementation of a linked list helper In-Reply-To: <1328047125-22037-1-git-send-email-eblima@linux.vnet.ibm.com> References: <1328047125-22037-1-git-send-email-eblima@linux.vnet.ibm.com> Message-ID: <4F2BE1AD.7060903@linux.vnet.ibm.com> Pushed series. Thanks. On 01/31/2012 04:58 PM, Eduardo Lima (Etrunko) wrote: > From: "Eduardo Lima (Etrunko)" > > This series provides a generic linked list implementation for libxkutil that is > based on the one originally developed for the libvirt domain events support > recently integrated upstream. > > As test case I ported the ComputerSystemIndication provider code to use this > list implementation. In the near future it will be also used by the event loop > that I am currently working on to allow systems with libvirt older than 0.9.0 > to make use of the same feature. > > Other possible use cases would be to port the code of libxkutil/*_parsing* to > also use the list implementation instead of static arrays. > > Changes from v5: > - Fix possible NULL dereference in list_first() > > Changes from v4: > - Fix possible NULL dereference in list_last_node() > - Fix possible leak in acl_parsing.c > > Changes from v3: > - Fix crashes in list_free(), list_first_node() and list_count() > - Include patch that ports the acl filter ref code to use the linked list > implementation > > Changes from v2: > - Make list struct private > > Changes from v1: > - Fix version iformation in Makefile.am > > Eduardo Lima (Etrunko) (3): > libxkutil: Linked list helper > CSI: Use list helper implementation > ACL: Use linked list helper for filter refs > > libxkutil/Makefile.am | 51 +++++-- > libxkutil/acl_parsing.c | 58 +++------ > libxkutil/acl_parsing.h | 5 +- > libxkutil/list_util.c | 254 +++++++++++++++++++++++++++++++++++ > libxkutil/list_util.h | 73 ++++++++++ > libxkutil/xmlgen.c | 30 +++- > src/Virt_ComputerSystemIndication.c | 95 ++++---------- > src/Virt_NestedFilterList.c | 73 ++++++----- > 8 files changed, 472 insertions(+), 167 deletions(-) > create mode 100644 libxkutil/list_util.c > create mode 100644 libxkutil/list_util.h > -- Chip Vincent Open Virtualization IBM Linux Technology Center cvincent at linux.vnet.ibm.com From cvincent at linux.vnet.ibm.com Wed Feb 8 14:08:11 2012 From: cvincent at linux.vnet.ibm.com (Chip Vincent) Date: Wed, 08 Feb 2012 09:08:11 -0500 Subject: [Libvirt-cim] Release of libvirt-cim-0.6.1 Message-ID: <4F3281CB.3000705@linux.vnet.ibm.com> I'm happy announce the release of libvirt-cim-0.6.1. The new release is available at: ftp://libvirt.org/libvirt-cim/libvirt-cim-0.6.1.tar.gz libvirt-cim-0.6.1: * ACL: Use linked list helper for filter refs (Eduardo Lima (Etrunko)) * CSI: Use list helper implementation (Eduardo Lima (Etrunko)) * libxkutil: Linked list helper (Eduardo Lima (Etrunko)) * FilterEntry: Accept protocol id string values (Eduardo Lima (Etrunko)) * FilterEntry: Update action property (Eduardo Lima (Etrunko)) * FilterList: Add 'Priority' property (Eduardo Lima (Etrunko)) * FilterEntry: Change 'Priority' property type (Eduardo Lima (Etrunko)) * Fix AppliedFilterList creation and deletion (Chip Vincent) * autoconfiscate.sh: Use proper command for revision count (Eduardo Lima (Etr * libxkutil: Fix possible NULL dereferences (Eduardo Lima (Etrunko)) * Fix possible use of unitialized variables (Eduardo Lima (Etrunko)) * xml_parse_test: Fix invalid dereference (Eduardo Lima (Etrunko)) * Fix possible memory leaks (Eduardo Lima (Etrunko)) * Fix a problem with multi-arch (Daniel Veillard) * Remove compilation warnings (Eduardo Lima (Etrunko)) * VirtualSystemManagementService: Remove dead code (Eduardo Lima (Etrunko)) -- Chip Vincent Open Virtualization IBM Linux Technology Center cvincent at linux.vnet.ibm.com From xiawenc at linux.vnet.ibm.com Tue Feb 14 08:56:00 2012 From: xiawenc at linux.vnet.ibm.com (Wenchao Xia) Date: Tue, 14 Feb 2012 16:56:00 +0800 Subject: [Libvirt-cim] [PATCH V7 0/7] vlan 802.1.q extention Message-ID: <1329209760-14338-1-git-send-email-xiawenc@linux.vnet.ibm.com> These patches add vlan extention of host network. Many code are used to build up the network model, which is very similar to ComputerSystem. Patch 1 contains function library codes and C test program. From Patch 2 to 6, it is almost readonly codes, except VESS state change. Patch 7 are CIM model codes of writing network configuration. Limit: Now only DHCP on/off are supported about IP settings, mannually setting of address and netmask are not considered. v7: added portion of code about writing. v6: added CIM model for readonly usage. Code changes according to comments. v5: switched to libvirt API about to enable readonly library. v4: using netlink 1.0 as implemention to avoid runtime errors. v3: using netlink 3.0 and libbridge as implemention. v2: code fix and bug fix. v1: using string parsing and direct accessing with host configuration file, which require some utilities installed, such as IP, VCONFIG. git repository: git://gitorious.org/libvirt-cim_develop/libvirt-cim_develop.git branch vlan_v7 Wenchao Xia (7): vlan extention - function libarary vlan extention - CIM Model - helper and Makefile vlan extention - CIM Model - VESS vlan extention - CIM Model - VESSSD vlan extention - CIM Model - EthernetPort vlan extention - CIM Model - EASD vlan extention - CIM Model - VESSMS Makefile.am | 16 +- libxkutil/Makefile.am | 14 +- libxkutil/misc_util.c | 48 + libxkutil/misc_util.h | 3 + libxkutil/network_model_helper.c | 473 +++++++ libxkutil/network_model_helper.h | 101 ++ libxkutil/network_parsing.c | 1309 ++++++++++++++++++++ libxkutil/network_parsing.h | 217 ++++ libxkutil/network_parsing_test.c | 184 +++ libxkutil/xmlgen.c | 4 +- libxkutil/xmlgen.h | 4 + schema/EthernetPort.mof | 4 + schema/EthernetPort.registration | 3 + schema/EthernetPortAllocationSettingData.mof | 22 + .../EthernetPortAllocationSettingData.registration | 3 + schema/VirtualEthernetSwitchSystem.mof | 10 + schema/VirtualEthernetSwitchSystem.registration | 3 + ...irtualEthernetSwitchSystemManagementService.mof | 14 + ...ernetSwitchSystemManagementService.registration | 3 + schema/VirtualEthernetSwitchSystemSettingData.mof | 33 + ...ualEthernetSwitchSystemSettingData.registration | 3 + src/Makefile.am | 29 +- src/Virt_EASD.c | 711 +++++++++++ src/Virt_EASD.h | 59 + src/Virt_EthernetPort.c | 561 +++++++++ src/Virt_EthernetPort.h | 58 + src/Virt_HostSystem.c | 2 +- src/Virt_HostSystem.h | 2 + src/Virt_VESSSD.c | 392 ++++++ src/Virt_VESSSD.h | 39 + src/Virt_VirtualEthernetSwitchSystem.c | 477 +++++++ src/Virt_VirtualEthernetSwitchSystem.h | 52 + ..._VirtualEthernetSwitchSystemManagementService.c | 1289 +++++++++++++++++++ ..._VirtualEthernetSwitchSystemManagementService.h | 31 + src/Virt_VirtualSystemManagementService.c | 2 +- src/Virt_VirtualSystemManagementService.h | 4 + 36 files changed, 6167 insertions(+), 12 deletions(-) create mode 100644 libxkutil/network_model_helper.c create mode 100644 libxkutil/network_model_helper.h create mode 100644 libxkutil/network_parsing.c create mode 100644 libxkutil/network_parsing.h create mode 100644 libxkutil/network_parsing_test.c create mode 100644 schema/EthernetPort.mof create mode 100644 schema/EthernetPort.registration create mode 100644 schema/EthernetPortAllocationSettingData.mof create mode 100644 schema/EthernetPortAllocationSettingData.registration create mode 100644 schema/VirtualEthernetSwitchSystem.mof create mode 100644 schema/VirtualEthernetSwitchSystem.registration create mode 100644 schema/VirtualEthernetSwitchSystemManagementService.mof create mode 100644 schema/VirtualEthernetSwitchSystemManagementService.registration create mode 100644 schema/VirtualEthernetSwitchSystemSettingData.mof create mode 100644 schema/VirtualEthernetSwitchSystemSettingData.registration create mode 100644 src/Virt_EASD.c create mode 100644 src/Virt_EASD.h create mode 100644 src/Virt_EthernetPort.c create mode 100644 src/Virt_EthernetPort.h create mode 100644 src/Virt_VESSSD.c create mode 100644 src/Virt_VESSSD.h create mode 100644 src/Virt_VirtualEthernetSwitchSystem.c create mode 100644 src/Virt_VirtualEthernetSwitchSystem.h create mode 100644 src/Virt_VirtualEthernetSwitchSystemManagementService.c create mode 100644 src/Virt_VirtualEthernetSwitchSystemManagementService.h From xiawenc at linux.vnet.ibm.com Tue Feb 14 08:56:30 2012 From: xiawenc at linux.vnet.ibm.com (Wenchao Xia) Date: Tue, 14 Feb 2012 16:56:30 +0800 Subject: [Libvirt-cim] [PATCH V7 1/7] vlan extention - function libarary Message-ID: <1329209790-14406-1-git-send-email-xiawenc@linux.vnet.ibm.com> This patch add function libarary and test program with libvirt API. Limit: It have only DHCP property about IP settings. Other settings such IP and mask are ignored, in most cases ip are got by DHCP. V7: Add codes of writing about network configuration. Codes such as iface comparing and duplication are removed comparing to V2, which brings some limit to the usage of API and structure, but make things more simple. V6: Code changes according to comments. V5: Calling libvirt API instead of implement my own. Signed-off-by: Wenchao Xia --- libxkutil/Makefile.am | 14 +- libxkutil/misc_util.c | 48 ++ libxkutil/misc_util.h | 3 + libxkutil/network_parsing.c | 1309 ++++++++++++++++++++++++++++++++++++++ libxkutil/network_parsing.h | 217 +++++++ libxkutil/network_parsing_test.c | 184 ++++++ libxkutil/xmlgen.c | 4 +- libxkutil/xmlgen.h | 4 + 8 files changed, 1778 insertions(+), 5 deletions(-) create mode 100644 libxkutil/network_parsing.c create mode 100644 libxkutil/network_parsing.h create mode 100644 libxkutil/network_parsing_test.c diff --git a/libxkutil/Makefile.am b/libxkutil/Makefile.am index 8d436ad..d154ef6 100644 --- a/libxkutil/Makefile.am +++ b/libxkutil/Makefile.am @@ -11,7 +11,9 @@ noinst_HEADERS = \ infostore.h \ pool_parsing.h \ acl_parsing.h \ - list_util.h + list_util.h \ + network_parsing.h \ + network_model_helper.h lib_LTLIBRARIES = \ libxkutil.la @@ -24,7 +26,9 @@ libxkutil_la_SOURCES = \ infostore.c \ pool_parsing.c \ acl_parsing.c \ - list_util.c + list_util.c \ + network_parsing.c \ + network_model_helper.c libxkutil_la_LDFLAGS = \ -version-info @VERSION_INFO@ @@ -42,3 +46,9 @@ xml_parse_test_SOURCES = \ xml_parse_test_LDADD = \ libxkutil.la \ @LIBVIRT_LIBS@ + +noinst_PROGRAMS += network_parsing_test + +network_parsing_test_SOURCES = network_parsing_test.c +network_parsing_test_LDADD = libxkutil.la \ + @LIBVIRT_LIBS@ diff --git a/libxkutil/misc_util.c b/libxkutil/misc_util.c index 61893c3..564c6f2 100644 --- a/libxkutil/misc_util.c +++ b/libxkutil/misc_util.c @@ -184,6 +184,54 @@ virConnectPtr connect_by_classname(const CMPIBroker *broker, return conn; } +virConnectPtr connect_any(void) +{ + const char *uri = NULL; + virConnectPtr conn = NULL; + hypervisor_status_t *h = NULL; + const char *classname = NULL; + + for (h = &hypervisor_list[0]; h != NULL; h++) { + if (h->enabled) { + + classname = h->name; + + uri = cn_to_uri(classname); + if (!uri) { + CU_DEBUG("Unable to gen URI from classname," + " uri is %s.", uri); + return NULL; + } + CU_DEBUG("Connecting to libvirt with uri `%s'", uri); + + pthread_mutex_lock(&libvirt_mutex); + + if (is_read_only()) + conn = virConnectOpenReadOnly(uri); + else + conn = virConnectOpen(uri); + + pthread_mutex_unlock(&libvirt_mutex); + + if (!conn) { + virErrorPtr error = virGetLastError(); + if (error->code == VIR_ERR_NO_CONNECT) + set_hypervisor_disabled(classname); + + CU_DEBUG("Unable to connect to `%s'", uri); + continue; + } else { + break; + } + } + } + + if (classname == NULL) { + CU_DEBUG("Failed to find any hypervisor."); + } + return conn; +} + void free_domain_list(virDomainPtr *list, int count) { int i; diff --git a/libxkutil/misc_util.h b/libxkutil/misc_util.h index c7a2122..d1cc081 100644 --- a/libxkutil/misc_util.h +++ b/libxkutil/misc_util.h @@ -57,6 +57,9 @@ virConnectPtr connect_by_classname(const CMPIBroker *broker, const char *classname, CMPIStatus *s); +/* Try connect to any hypervisor available */ +virConnectPtr connect_any(void); + /* Establish a libvirt connection to the appropriate hypervisor, * as determined by the state of the system, or the value of the * HYPURI environment variable, if set. diff --git a/libxkutil/network_parsing.c b/libxkutil/network_parsing.c new file mode 100644 index 0000000..b043b40 --- /dev/null +++ b/libxkutil/network_parsing.c @@ -0,0 +1,1309 @@ +/* + * Copyright IBM Corp. 2012 + * + * Authors: + * Wenchao Xia + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "misc_util.h" +#include "xmlgen.h" +#include "device_parsing.h" +#include "network_parsing.h" + +#define LIST_INACTIVE_IFACE 1 +#define LIST_ACTIVE_IFACE 2 + +static void vlan_prop_print(struct VLAN_Prop *pvlan_prop) +{ + struct VLAN_Prop_8021q *p_8021q; + CU_DEBUG_OP(1, "--VLAN props: type %d.\n", + pvlan_prop->vlan_type); + if (pvlan_prop->vlan_type == VLAN_TYPE_802_1_Q) { + p_8021q = &(pvlan_prop->props.prop_8021q); + CU_DEBUG_OP(1, "----IEEE802.1.Q: id %d, parent %s.\n", + p_8021q->vlan_id, p_8021q->parent); + } +} + +static void br_prop_print(struct BR_Prop *pbr_prop) +{ + int i = 0; + CU_DEBUG_OP(1, "--Bridge props: stp %d, delay %d, port_num %d.\n", + pbr_prop->STP, pbr_prop->delay, pbr_prop->port_num); + if (pbr_prop->port_names != NULL) { + CU_DEBUG_OP(1, "----Ports attached: "); + while (i < pbr_prop->port_num) { + CU_DEBUG_OP(1, " %s,", *(pbr_prop->port_names+i)); + i++; + } + CU_DEBUG_OP(1, "\n"); + } +} + +void eth_iface_print(struct EthIface *piface) +{ + CU_DEBUG_OP(1, "Iface device: name %s.\n" + "--Main props: parent %s, attach to %s, mac %s, iface type %d," + " status %d, boot_mode %d," + " protocol ipv4 dhcp %d.\n", + piface->name, + piface->dep_ifname, piface->attach_bridge, piface->mac, piface->eth_type, + piface->run_prop.status, piface->run_prop.boot_mode, + piface->protocol_prop.ipv4_prop.DHCP); + if (piface->pbr_prop != NULL) { + br_prop_print(piface->pbr_prop); + } + if (piface->pvlan_prop != NULL) { + vlan_prop_print(piface->pvlan_prop); + } + return; +} + +void eth_ifaceslist_print(struct EthIfacesList *plist) +{ + int i = 0; + CU_DEBUG_OP(1, "Have %d ifaces in the list:\n", plist->count); + while (i < plist->count) { + CU_DEBUG_OP(1, "%04d ", i); + eth_iface_print(plist->pifaces[i]); + i++; + } +} + +static void vlan_prop_init(struct VLAN_Prop *pvlan_prop, int vlan_type) +{ + struct VLAN_Prop_8021q *p_8021q; + memset(pvlan_prop, 0, sizeof(struct VLAN_Prop)); + pvlan_prop->vlan_type = vlan_type; + if (pvlan_prop->vlan_type == VLAN_TYPE_802_1_Q) { + p_8021q = &(pvlan_prop->props.prop_8021q); + p_8021q->vlan_id = NUM_NONE; + } +} + +static void br_prop_init(struct BR_Prop *pbr_prop) +{ + memset(pbr_prop, 0, sizeof(struct BR_Prop)); + pbr_prop->STP = NUM_NONE; + pbr_prop->delay = NUM_NONE; + pbr_prop->port_num = NUM_NONE; +} + +void eth_iface_init(struct EthIface *piface) +{ + memset(piface, 0, sizeof(struct EthIface)); + piface->eth_type = ETH_TYPE_NOT_GOT; + piface->run_prop.status = NUM_NONE; + piface->run_prop.boot_mode = BOOT_MODE_NOT_GOT; + piface->protocol_prop.ipv4_prop.DHCP = NUM_NONE; + return; +} + +void eth_iface_add_br_prop(struct EthIface *piface) +{ + if (piface->pbr_prop != NULL) { + return; + } + CU_MALLOC(piface->pbr_prop, sizeof(struct BR_Prop)); + br_prop_init(piface->pbr_prop); +} + +static void eth_iface_add_br_prop_attached_iface(struct EthIface *pbridge, + const char *iface_name) +{ + char **ppchar = NULL; + + if (pbridge->pbr_prop->port_names == NULL) { + CU_CALLOC(pbridge->pbr_prop->port_names, + MAX_IFACE_NUM, sizeof(char *)); + pbridge->pbr_prop->port_num = 0; + } + + ppchar = pbridge->pbr_prop->port_names + + (pbridge->pbr_prop->port_num)++; + *ppchar = CU_STRDUP(iface_name); +} + +void eth_iface_add_vlan_prop(struct EthIface *piface, int vlan_type) +{ + if (piface->pvlan_prop != NULL) { + return; + } + CU_MALLOC(piface->pvlan_prop, sizeof(struct VLAN_Prop)); + vlan_prop_init(piface->pvlan_prop, vlan_type); +} + +static void vlan_prop_uninit(struct VLAN_Prop *pvlan_prop) +{ + struct VLAN_Prop_8021q *p_8021q; + if (pvlan_prop == NULL) { + return; + } + if (pvlan_prop->vlan_type == VLAN_TYPE_802_1_Q) { + p_8021q = &(pvlan_prop->props.prop_8021q); + CU_FREE(p_8021q->parent); + } +} + +static void br_prop_uninit(struct BR_Prop *pbr_prop) +{ + int i = 0; + if (pbr_prop == NULL) { + return; + } + if (pbr_prop->port_names != NULL) { + while (i < pbr_prop->port_num) { + CU_FREE(pbr_prop->port_names[i]); + i++; + } + CU_FREE(pbr_prop->port_names); + } +} + +void eth_iface_uninit(struct EthIface *piface) +{ + if (piface == NULL) { + return; + } + CU_FREE(piface->name); + CU_FREE(piface->dep_ifname); + CU_FREE(piface->attach_bridge); + CU_FREE(piface->mac); + br_prop_uninit(piface->pbr_prop); + CU_FREE(piface->pbr_prop); + vlan_prop_uninit(piface->pvlan_prop); + CU_FREE(piface->pvlan_prop); + return; +} + +void eth_ifaceslist_init(struct EthIfacesList *plist) +{ + plist->count = 0; +} + +void eth_ifaceslist_uninit(struct EthIfacesList *plist) +{ + struct EthIface **t = NULL; + int i = 0; + if (plist->count <= 0) { + return; + } + t = plist->pifaces; + while (i < plist->count) { + if (*t != NULL) { + eth_iface_uninit(*t); + CU_FREE(*t); + } + t++; + i++; + } + return; +} + +int eth_ifaceslist_add(struct EthIfacesList *plist, struct EthIface **ppiface) +{ + if (plist->count >= MAX_IFACE_NUM) { + CU_DEBUG("Too much device found."); + return 0; + } + plist->pifaces[plist->count] = *ppiface; + *ppiface = NULL; + plist->count++; + return 1; +} + +struct EthIface *eth_ifaceslist_search(struct EthIfacesList *plist, + char *name) +{ + int i = 0; + struct EthIface *piface = NULL; + + while (i < plist->count) { + piface = plist->pifaces[i]; + i++; + if (piface != NULL) { + if (strcmp(piface->name, name) == 0) { + return piface; + } + } + } + return NULL; +} + +static void vlan_prop_merge(struct VLAN_Prop *pdest, struct VLAN_Prop *psrc) +{ + struct VLAN_Prop_8021q *pd_8021q, *ps_8021q; + + NUM_MERGE(pdest->vlan_type, psrc->vlan_type, VLAN_TYPE_NOT_GOT); + + if (psrc->vlan_type == VLAN_TYPE_802_1_Q) { + pd_8021q = &(pdest->props.prop_8021q); + ps_8021q = &(psrc->props.prop_8021q); + NUM_MERGE(pd_8021q->vlan_id, ps_8021q->vlan_id, NUM_NONE); + CHARS_MERGE(pd_8021q->parent, ps_8021q->parent); + } +} + +static void br_prop_merge(struct BR_Prop *pdest, struct BR_Prop *psrc) +{ + int i; + + /*merge it when dest have not been set */ + if ((pdest->port_names == NULL) && (psrc->port_names != NULL)){ + CU_PSTR_ARRAY_DUP(pdest->port_names, pdest->port_num, + psrc->port_names, psrc->port_num, i); + } + + NUM_MERGE(pdest->STP, psrc->STP, NUM_NONE); + NUM_MERGE(pdest->delay, psrc->delay, NUM_NONE); +} + +static void eth_iface_merge(struct EthIface *dest, struct EthIface *src) +{ + CHARS_MERGE(dest->name, src->name); + CHARS_MERGE(dest->dep_ifname, src->dep_ifname); + CHARS_MERGE(dest->attach_bridge, src->attach_bridge); + CHARS_MERGE(dest->mac, src->mac); + NUM_MERGE(dest->eth_type, src->eth_type, NUM_NONE); + + NUM_MERGE(dest->run_prop.status, src->run_prop.status, + NUM_NONE); + NUM_MERGE(dest->run_prop.boot_mode, src->run_prop.boot_mode, + BOOT_MODE_NOT_GOT); + NUM_MERGE(dest->protocol_prop.ipv4_prop.DHCP, + src->protocol_prop.ipv4_prop.DHCP, + NUM_NONE); + if (src->pbr_prop != NULL) { + if (dest->pbr_prop == NULL) { + CU_MALLOC(dest->pbr_prop, sizeof(struct BR_Prop)); + br_prop_init(dest->pbr_prop); + } + br_prop_merge(dest->pbr_prop, src->pbr_prop); + } + + if (src->pvlan_prop != NULL) { + if (dest->pvlan_prop == NULL) { + CU_MALLOC(dest->pvlan_prop, sizeof(struct VLAN_Prop)); + vlan_prop_init(dest->pvlan_prop, src->pvlan_prop->vlan_type); + } + vlan_prop_merge(dest->pvlan_prop, src->pvlan_prop); + } + +} + +/* the judgement condition is weak, but I can't find a better way */ +int eth_iface_filter_peths(const struct EthIface *piface, void *nouse) +{ + if ((piface->eth_type != ETH_TYPE_ETHER_ANY) && + (piface->eth_type != ETH_TYPE_ETHER_PHYSICAL)) { + return 0; + } + if (piface->dep_ifname != NULL) { + return 0; + } + if (NULL != strstr(piface->name, ".")) { + return 0; + } + /* this filter NetUSB etc */ + if (NULL == strstr(piface->name, "eth")) { + return 0; + } + + return 1; +} + +int eth_iface_filter_by_name(const struct EthIface *piface, void *name) +{ + int comp_ret; + comp_ret = strcmp(piface->name, (char *)name); + if (comp_ret == 0) { + return 1; + } + return 0; +} + +char *get_host_iface_error_reason(int errno) +{ + char *ret = NULL; + switch (errno) { + case ERR_CONNECT: + ret = "Error in connect to hypervisor."; + break; + + case ERR_LIST_INTERFACE: + ret = "Error in listing the interfaces."; + break; + + case ERR_GENXML_INTERFACE: + ret = "Error in generating xml for interfaces."; + break; + + case ERR_CALL_LIBVIRT: + ret = "Libvirt API returns failure."; + break; + + case ERR_DEVICE_EXIST: + ret = "Interface already exist."; + break; + + case ERR_DEVICE_NOT_EXIST: + ret = "Interface do not exist."; + break; + + case ERR_NOT_SUPPORT: + ret = "Request for interfaces not supported."; + break; + + default: + ret = "Internal error in calling libvirt API for interfaces."; + break; + } + return ret; +} + +/* Dummy function to suppress error message from libxml2 */ +static void swallow_err_msg(void *ctx, const char *msg, ...) +{ + /* do nothing, just swallow the message. */ +} + + +static const char *gen_eth_xmlnode_iface(xmlNodePtr root, + struct EthIface *piface, + struct EthIfacesList *plist, + int bridge_port_flag) +{ + const char *msg = NULL; + xmlNodePtr temp_node1 = NULL, temp_node2 = NULL, temp_node3 = NULL; + char *str = NULL, buf[16] = {0,}; + int i = 0; + struct EthIface *pifaceport; + + if (piface->name == NULL) { + msg = "Iface have no name.\n"; + goto out; + } + /* netcfg have no xml for iface attatched to bridge */ + if ((piface->attach_bridge != NULL) && (bridge_port_flag != 1)) { + goto out; + } + + temp_node1 = xmlNewChild(root, NULL, BAD_CAST "interface", NULL); + if (temp_node1 == NULL) { + msg = XML_ERROR; + goto out; + } + xmlNewProp(temp_node1, BAD_CAST "name", BAD_CAST piface->name); + + if (piface->eth_type == ETH_TYPE_ETHER_BRIDGE) { + str = "bridge"; + } else if (piface->eth_type == ETH_TYPE_ETHER_VLAN) { + str = "vlan"; + } else { + str = "ethernet"; + } + xmlNewProp(temp_node1, BAD_CAST "type", BAD_CAST str); + + if ((piface->pvlan_prop != NULL) && + (piface->pvlan_prop->vlan_type == VLAN_TYPE_802_1_Q)) { + temp_node2 = xmlNewChild(temp_node1, NULL, BAD_CAST "vlan", NULL); + snprintf(buf, sizeof(buf), + "%d", piface->pvlan_prop->props.prop_8021q.vlan_id); + xmlNewProp(temp_node2, BAD_CAST "tag", BAD_CAST buf); + temp_node3 = xmlNewChild(temp_node2, NULL, BAD_CAST "interface", NULL); + xmlNewProp(temp_node3, BAD_CAST "name", + BAD_CAST piface->pvlan_prop->props.prop_8021q.parent); + } + + /* if it is attached to bridge, only above properties could be set */ + if (bridge_port_flag == 1) { + goto out; + } + + if (piface->protocol_prop.ipv4_prop.DHCP == 1) { + temp_node2 = xmlNewChild(temp_node1, NULL, BAD_CAST "protocol", NULL); + xmlNewProp(temp_node2, BAD_CAST "family", BAD_CAST "ipv4"); + temp_node3 = xmlNewChild(temp_node2, NULL, BAD_CAST "dhcp", NULL); + } + + if (piface->pbr_prop != NULL) { + temp_node2 = xmlNewChild(temp_node1, NULL, BAD_CAST "bridge", NULL); + if (piface->pbr_prop->STP == 1) { + snprintf(buf, sizeof(buf), "on"); + } else { + snprintf(buf, sizeof(buf), "off"); + } + xmlNewProp(temp_node2, BAD_CAST "stp", BAD_CAST buf); + if (piface->pbr_prop->delay >= 0) { + snprintf(buf, sizeof(buf), "%d", piface->pbr_prop->delay); + xmlNewProp(temp_node2, BAD_CAST "delay", BAD_CAST buf); + } + if ((piface->pbr_prop->port_names != NULL) && + (piface->pbr_prop->port_num > 0)) { + for (i = 0; i < piface->pbr_prop->port_num; i++) { + pifaceport = eth_ifaceslist_search(plist, + piface->pbr_prop->port_names[i]); + if (pifaceport == NULL) { + CU_DEBUG("failed to find port %s of bridge %s in list.", + piface->pbr_prop->port_names[i], piface->name); + } else { + gen_eth_xmlnode_iface(temp_node2, pifaceport, plist, 1); + } + } + } + } + + if (piface->run_prop.boot_mode == BOOT_MODE_AUTOSTART) { + temp_node2 = xmlNewChild(temp_node1, NULL, BAD_CAST "start", NULL); + xmlNewProp(temp_node2, BAD_CAST "mode", BAD_CAST "onboot"); + } else if (piface->run_prop.boot_mode == BOOT_MODE_NONE) { + temp_node2 = xmlNewChild(temp_node1, NULL, BAD_CAST "start", NULL); + xmlNewProp(temp_node2, BAD_CAST "mode", BAD_CAST "none"); + } + if (piface->mac != NULL) { + temp_node2 = xmlNewChild(temp_node1, NULL, BAD_CAST "mac", NULL); + xmlNewProp(temp_node2, BAD_CAST "address", BAD_CAST piface->mac); + } + + out: + return msg; +} + +static const char *gen_eth_xmlnode(xmlNodePtr root, + struct EthIfacesList *plist) +{ + const char *msg = NULL; + int i = 0; + struct EthIface *piface = NULL; + + while (i < plist->count) { + piface = plist->pifaces[i]; + i++; + msg = gen_eth_xmlnode_iface(root, piface, plist, 0); + if (msg != NULL) { + goto out; + } + } + + out: + return msg; +} + +static const char *EthIfaceListTOXML(char **ppxml, + struct EthIfacesList *plist, + int dump_all_flag) +{ + const char *msg = NULL; + xmlNodePtr root = NULL; + + root = xmlNewNode(NULL, BAD_CAST "tmp"); + if (root == NULL) { + msg = "Failed to create root node."; + goto out; + } + msg = gen_eth_xmlnode(root, plist); + if (msg == NULL) { + if (dump_all_flag == 1) { + *ppxml = tree_to_xml(root); + } else { + *ppxml = tree_to_xml(root->children); + } + } + + out: + xmlFreeNode(root); + return msg; +} + +static int host_iface_adjust(struct EthIface *piface) +{ + if (1 == eth_iface_filter_peths(piface, NULL)) { + piface->eth_type = ETH_TYPE_ETHER_PHYSICAL; + } + return 1; +} + +static int parse_eth_xmlnode(struct EthIfacesList *plist, xmlNode *inode, + int status, char *attached, + eth_iface_filter_func filter_func, + void *filter_opaque) +{ + struct EthIface *piface = NULL; + xmlNode *child1 = NULL, *child2 = NULL; + char *temp = NULL; + int filter_ret = 0; + + CU_MALLOC(piface, sizeof(struct EthIface)); + eth_iface_init(piface); + + piface->name = get_attr_value(inode, "name"); + piface->run_prop.status = status; + if (attached != NULL) { + piface->attach_bridge = strdup(attached); + } + temp = get_attr_value(inode, "type"); + if (temp != NULL) { + if (strcmp(temp, "ethernet") == 0) { + piface->eth_type = ETH_TYPE_ETHER_ANY; + } + if (strcmp(temp, "bridge") == 0) { + piface->eth_type = ETH_TYPE_ETHER_BRIDGE; + } + if (strcmp(temp, "vlan") == 0) { + piface->eth_type = ETH_TYPE_ETHER_VLAN; + } + CU_FREE(temp); + } + + for (child1 = inode->children; child1 != NULL; child1 = child1->next) { + if (XSTREQ(child1->name, "start")) { + temp = get_attr_value(child1, "mode"); + if (strcmp(temp, "onboot") == 0) { + piface->run_prop.boot_mode = BOOT_MODE_AUTOSTART; + } + if (strcmp(temp, "none") == 0) { + piface->run_prop.boot_mode = BOOT_MODE_NONE; + } + CU_FREE(temp); + } + if (XSTREQ(child1->name, "mac")) { + piface->mac = get_attr_value(child1, "address"); + } + if (XSTREQ(child1->name, "protocol")) { + temp = get_attr_value(child1, "family"); + if (strcmp(temp, "ipv4") == 0) { + for (child2 = child1->children; child2 != NULL; + child2 = child2->next) { + if (XSTREQ(child2->name, "dhcp")) { + piface->protocol_prop.ipv4_prop.DHCP = 1; + break; + } + } + } + CU_FREE(temp); + } + if (XSTREQ(child1->name, "bridge")) { + eth_iface_add_br_prop(piface); + temp = get_attr_value(child1, "stp"); + if (strcmp(temp, "on") == 0) { + piface->pbr_prop->STP = 1; + } + if (strcmp(temp, "off") == 0) { + piface->pbr_prop->STP = 0; + } + CU_FREE(temp); + temp = get_attr_value(child1, "delay"); + piface->pbr_prop->delay = strtol(temp, NULL, 10); + CU_FREE(temp); + } + if (XSTREQ(child1->name, "bridge")) { + eth_iface_add_br_prop(piface); + temp = get_attr_value(child1, "stp"); + if (strcmp(temp, "on") == 0) { + piface->pbr_prop->STP = 1; + } + if (strcmp(temp, "off") == 0) { + piface->pbr_prop->STP = 0; + } + CU_FREE(temp); + temp = get_attr_value(child1, "delay"); + piface->pbr_prop->delay = strtol(temp, NULL, 10); + CU_FREE(temp); + for (child2 = child1->children; child2 != NULL; + child2 = child2->next) { + if (XSTREQ(child2->name, "interface")) { + temp = get_attr_value(child2, "name"); + eth_iface_add_br_prop_attached_iface(piface, temp); + CU_FREE(temp); + parse_eth_xmlnode(plist, child2, status, piface->name, + filter_func, filter_opaque); + } + } + } + if (XSTREQ(child1->name, "vlan")) { + eth_iface_add_vlan_prop(piface, VLAN_TYPE_802_1_Q); + temp = get_attr_value(child1, "tag"); + piface->pvlan_prop->props.prop_8021q.vlan_id = + strtol(temp, NULL, 10); + CU_FREE(temp); + for (child2 = child1->children; child2 != NULL; + child2 = child2->next) { + if (XSTREQ(child2->name, "interface")) { + piface->pvlan_prop->props.prop_8021q.parent = + get_attr_value(child2, "name"); + piface->dep_ifname = + get_attr_value(child2, "name"); + } + } + } + } + + host_iface_adjust(piface); + + filter_ret = 1; + if (filter_func != NULL) { + filter_ret = filter_func(piface, filter_opaque); + } + if (filter_ret == 1) { + eth_ifaceslist_add(plist, &piface); + } + return 1; +} + +static const char *XMLToEthIfaceList(struct EthIfacesList *plist, + const char *xml, + int status, + eth_iface_filter_func filter_func, + void *filter_opaque) +{ + xmlDoc *xmldoc = NULL; + xmlXPathContext *xpathCtx = NULL; + xmlXPathObject *xpathObj = NULL; + xmlChar *xpathstr = NULL; + xmlNode **dev_nodes = NULL; + xmlNodeSet *nsv = NULL; + int count = 0; + int len = 0, devidx = 0; + const char *msg = NULL; + + len = strlen(xml) + 1; + xpathstr = (xmlChar *)"/interface"; + + xmlSetGenericErrorFunc(NULL, swallow_err_msg); + if ((xmldoc = xmlParseMemory(xml, len)) == NULL) { + msg = "Failed to get xmldoc."; + goto err1; + } + + if ((xpathCtx = xmlXPathNewContext(xmldoc)) == NULL) { + msg = "Failed to get pathCtx"; + goto err2; + } + + if ((xpathObj = xmlXPathEvalExpression(xpathstr, xpathCtx)) + == NULL) { + msg = "Failed to get xpathObj"; + goto err3; + } + + nsv = xpathObj->nodesetval; + if (nsv == NULL) { + msg = "Failed to get nodesetval."; + goto out; + } + + dev_nodes = nsv->nodeTab; + count = nsv->nodeNr; + + if (count <= 0) { + msg = "Nodesetval have less that 1 values."; + goto out; + } + + for (devidx = 0; devidx < count; devidx++) { + parse_eth_xmlnode(plist, dev_nodes[devidx], status, NULL, + filter_func, filter_opaque); + } + + out: + xmlSetGenericErrorFunc(NULL, NULL); + xmlXPathFreeObject(xpathObj); + + err3: + xmlXPathFreeContext(xpathCtx); + err2: + xmlFreeDoc(xmldoc); + err1: + return msg; +} + +int get_host_ifaces(struct EthIfacesList *plist, + eth_iface_filter_func filter_func, void *filter_opaque) +{ + virConnectPtr conn = NULL; + virInterfacePtr iface = NULL; + int ret = 0; + int num = 0, listnum = 0, i = 0; + char **names = NULL; + char *xml = NULL; + int flags = 0; + const char *msg = NULL; + int list_flag = LIST_INACTIVE_IFACE | LIST_ACTIVE_IFACE; + int xml_flag = VIR_INTERFACE_XML_INACTIVE; + + conn = connect_any(); + if (conn == NULL) { + CU_DEBUG("Connect for network failed."); + ret = ERR_CONNECT; + goto out; + } + + /* list defined interfaces*/ + if ((list_flag & LIST_INACTIVE_IFACE) == 0) { + goto list_active; + } + num = virConnectNumOfDefinedInterfaces(conn); + if (num < 0) { + CU_DEBUG("Failed to find number of defined interfaces."); + ret = ERR_LIST_INTERFACE; + goto out; + } + names = malloc(num * sizeof(char *)); + listnum = virConnectListDefinedInterfaces(conn, names, num); + if (listnum < 0) { + CU_DEBUG("Failed to list names of defined interfaces."); + ret = ERR_LIST_INTERFACE; + goto out; + } + CU_DEBUG("%d defined ifaces found from libvirt API.\n", listnum); + + flags = xml_flag; + for (i = 0; i < listnum; i++) { + iface = virInterfaceLookupByName(conn, names[i]); + if (!iface) { + CU_DEBUG("Failed to look up %s.\n", names[i]); + CU_FREE(names[i]); + continue; + } + CU_FREE(names[i]); + xml = virInterfaceGetXMLDesc(iface, flags); + CU_DEBUG_OP(3, "Defined interface %d xml:\n%s", i, xml); + msg = XMLToEthIfaceList(plist, xml, ETH_STATE_INACTIVE, + filter_func, filter_opaque); + if (msg != NULL) { + CU_DEBUG("Failed parsing eth xml, msg is: %s.", msg); + } + CU_FREE(xml); + virInterfaceFree(iface); + } + CU_FREE(names); + + list_active: + /* list active interfaces*/ + if ((list_flag & LIST_ACTIVE_IFACE) == 0) { + goto out; + } + num = virConnectNumOfInterfaces(conn); + if (num < 0) { + CU_DEBUG("Failed to find number of active interfaces."); + ret = ERR_LIST_INTERFACE; + goto out; + } + names = malloc(num * sizeof(char *)); + + listnum = virConnectListInterfaces(conn, names, num); + if (listnum < 0) { + CU_DEBUG("Failed to list names of active interfacess."); + ret = ERR_LIST_INTERFACE; + goto out; + } + CU_DEBUG("%d active ifaces found from libvirt API.\n", listnum); + + flags = xml_flag; + for (i = 0; i < listnum; i++) { + iface = virInterfaceLookupByName(conn, names[i]); + if (!iface) { + CU_DEBUG("Failed to look up %s.\n", names[i]); + CU_FREE(names[i]); + continue; + } + CU_FREE(names[i]); + xml = virInterfaceGetXMLDesc(iface, flags); + CU_DEBUG_OP(3, "Active interface %d xml:\n%s", i, xml); + msg = XMLToEthIfaceList(plist, xml, ETH_STATE_ACTIVE, + filter_func, filter_opaque); + if (msg != NULL) { + CU_DEBUG("Failed parsing eth xml, msg is: %s.", msg); + } + CU_FREE(xml); + virInterfaceFree(iface); + } + ret = 1; + + out: + if (conn != NULL) { + virConnectClose(conn); + } + CU_FREE(names); + return ret; +} + +int add_host_iface(struct EthIface *piface) +{ + struct EthIfacesList list; + const char *msg = NULL; + char *genxml = NULL; + int ret = 0; + virConnectPtr conn = NULL; + virInterfacePtr iface = NULL; + + /* the list do not need to be uninitilized to keep untouch of piface, + because now eth_ifaceslist_add function simply add piface to the + list instead of duplication. */ + eth_ifaceslist_init(&list); + + conn = connect_any(); + if (conn == NULL) { + CU_DEBUG("Connect for network failed."); + ret = ERR_CONNECT; + goto out; + } + + /* Fix me: now virInterfaceLookupByName sometimes return a valid pointer + even thought iface with name piface->name is deleted. So here a check + for it is skipped. */ + /* + iface = virInterfaceLookupByName(conn, piface->name); + if (iface != NULL) { + CU_DEBUG("iface %s already exist.", piface->name); + ret = ERR_DEVICE_EXIST; + goto out; + } + */ + + eth_ifaceslist_add(&list, &piface); + msg = EthIfaceListTOXML(&genxml, &list, 0); + if (msg != NULL) { + CU_DEBUG("Failed in generating xml for iface, msg is %s.", msg); + ret = ERR_GENXML_INTERFACE; + goto out; + } + + CU_DEBUG("Calling InterfaceDefine with XML:\n%s", genxml); + iface = virInterfaceDefineXML(conn, genxml, 0); + if (iface == NULL) { + CU_DEBUG("Failed in create iface, xml is:\n %s.", genxml); + ret = ERR_CALL_LIBVIRT; + goto out; + } + ret = 1; + + out: + if (conn != NULL) { + virConnectClose(conn); + } + if (iface != NULL) { + virInterfaceFree(iface); + } + CU_FREE(genxml); + return ret; +} + +int del_host_iface(struct EthIface *piface) +{ + int call_ret = 0; + int ret = 0; + virConnectPtr conn = NULL; + virInterfacePtr iface = NULL; + + conn = connect_any(); + if (conn == NULL) { + CU_DEBUG("Connect for network failed."); + ret = ERR_CONNECT; + goto out; + } + + iface = virInterfaceLookupByName(conn, piface->name); + if (iface == NULL) { + CU_DEBUG("Failed in find iface %s.", piface->name); + ret = ERR_DEVICE_NOT_EXIST; + goto out; + } + + call_ret = virInterfaceUndefine(iface); + if (call_ret != 0) { + CU_DEBUG("Failed in undefine iface %s, ret is %d.", + piface->name, call_ret); + ret = ERR_CALL_LIBVIRT; + goto out; + } + ret = 1; + + out: + if (conn != NULL) { + virConnectClose(conn); + } + if (iface != NULL) { + virInterfaceFree(iface); + } + return ret; +} + +/* piface would be changed because of internel merge, in order to save code of + struct EthIface duplication */ +int mod_host_iface(struct EthIface *piface) +{ + struct EthIfacesList list, list_new; + struct EthIface *pprev_iface = NULL; + int ret = 0; + const char *msg = NULL; + char *genxml = NULL; + virConnectPtr conn = NULL; + virInterfacePtr iface = NULL; + + eth_ifaceslist_init(&list); + ret = get_host_ifaces(&list, NULL, NULL); + if (ret != 1) { + CU_DEBUG("Failed in list host device."); + goto out; + } + + pprev_iface = eth_ifaceslist_search(&list, piface->name); + if (pprev_iface == NULL) { + CU_DEBUG("Failed in searching for iface %s", + piface->name); + ret = ERR_DEVICE_NOT_EXIST; + goto out; + } + + eth_iface_merge(piface, pprev_iface); + + /* list_new do not need to be uninited */ + eth_ifaceslist_init(&list_new); + eth_ifaceslist_add(&list_new, &piface); + + conn = connect_any(); + if (conn == NULL) { + CU_DEBUG("Connect for network failed."); + ret = ERR_CONNECT; + goto out; + } + + msg = EthIfaceListTOXML(&genxml, &list_new, 0); + if (msg != NULL) { + CU_DEBUG("Failed in generating xml for iface, msg is %s.", msg); + ret = ERR_GENXML_INTERFACE; + goto out; + } + + CU_DEBUG("Calling InterfaceDefine with XML:\n%s", genxml); + iface = virInterfaceDefineXML(conn, genxml, 0); + if (iface == NULL) { + CU_DEBUG("Failed in create iface, xml is:\n %s.", genxml); + ret = ERR_CALL_LIBVIRT; + goto out; + } + ret = 1; + + out: + if (conn != NULL) { + virConnectClose(conn); + } + if (iface != NULL) { + virInterfaceFree(iface); + } + CU_FREE(genxml); + eth_ifaceslist_uninit(&list); + return ret; +} + +/* assuming that pbridge have not added piface in its bridge property, + and piface have not set pbridge'name in its attach_bridge property. */ +int connect_two_ifaces(struct EthIface *p1, struct EthIface *p2) +{ + struct EthIface *pbridge = NULL, *piface = NULL; + struct EthIfacesList list, list_new; + struct EthIface *pprev_iface1 = NULL, *pprev_iface2 = NULL, + *pexist_port = NULL; + int ret = 0; + const char* msg = NULL; + char *genxml = NULL; + virConnectPtr conn = NULL; + virInterfacePtr iface = NULL; + int i; + + eth_ifaceslist_init(&list); + eth_ifaceslist_init(&list_new); + + ret = get_host_ifaces(&list, NULL, NULL); + if (ret != 1) { + CU_DEBUG("Failed in list host device."); + goto out; + } + + pprev_iface1 = eth_ifaceslist_search(&list, p1->name); + if (pprev_iface1 == NULL) { + CU_DEBUG("Failed in searching for iface %s", + p1->name); + ret = ERR_DEVICE_NOT_EXIST; + goto out; + } + + pprev_iface2 = eth_ifaceslist_search(&list, p2->name); + if (pprev_iface2 == NULL) { + CU_DEBUG("Failed in searching for iface %s", + p2->name); + ret = ERR_DEVICE_NOT_EXIST; + goto out; + } + + if ((pprev_iface1->eth_type == ETH_TYPE_ETHER_BRIDGE) && + ((pprev_iface2->eth_type == ETH_TYPE_ETHER_VLAN) || + (pprev_iface2->eth_type == ETH_TYPE_ETHER_PHYSICAL))) { + pbridge = pprev_iface1; + piface = pprev_iface2; + } + if ((pprev_iface2->eth_type == ETH_TYPE_ETHER_BRIDGE) && + ((pprev_iface1->eth_type == ETH_TYPE_ETHER_VLAN) || + (pprev_iface1->eth_type == ETH_TYPE_ETHER_PHYSICAL))) { + pbridge = pprev_iface2; + piface = pprev_iface1; + } + + if ((pbridge == NULL) || (piface == NULL)) { + CU_DEBUG("Cannot connect these devices, one must be bridge."); + ret = ERR_NOT_SUPPORT; + goto out; + } + + if (pbridge->pbr_prop == NULL) { + CU_DEBUG("pbridge %s have no bridge props added.", pbridge->name); + ret = ERR_NOT_SUPPORT; + goto out; + } + + /* adding piface to pbridge, list_new do not need uninitlized */ + eth_iface_add_br_prop_attached_iface(pbridge, piface->name); + eth_ifaceslist_add(&list_new, &pbridge); + pbridge = list_new.pifaces[0]; + /* adding existing port to list_new, despite new added port */ + if (pbridge->pbr_prop->port_num > 1) { + for (i = 0;i < (pbridge->pbr_prop->port_num - 1); i++) { + pexist_port = eth_ifaceslist_search(&list, + pbridge->pbr_prop->port_names[i]); + if (pexist_port == NULL) { + CU_DEBUG("Fail to find %s.", pbridge->pbr_prop->port_names[i]); + continue; + } + eth_ifaceslist_add(&list_new, &pexist_port); + } + } + piface->attach_bridge = CU_STRDUP(pbridge->name); + eth_ifaceslist_add(&list_new, &piface); + + msg = EthIfaceListTOXML(&genxml, &list_new, 0); + if (msg != NULL) { + CU_DEBUG("Failed in generating xml for iface, msg is %s.", msg); + ret = ERR_GENXML_INTERFACE; + goto out; + } + + conn = connect_any(); + if (conn == NULL) { + CU_DEBUG("Connect for network failed."); + ret = ERR_CONNECT; + goto out; + } + + CU_DEBUG("Calling InterfaceDefine with XML:\n%s", genxml); + iface = virInterfaceDefineXML(conn, genxml, 0); + if (iface == NULL) { + CU_DEBUG("Failed in create iface, xml is:\n %s.", genxml); + ret = ERR_CALL_LIBVIRT; + goto out; + } + ret = 1; + + out: + if (conn != NULL) { + virConnectClose(conn); + } + if (iface != NULL) { + virInterfaceFree(iface); + } + eth_ifaceslist_uninit(&list); + CU_FREE(genxml); + return ret; +} + +int disconnect_two_ifaces(struct EthIface *p1, struct EthIface *p2) +{ + struct EthIface *pbridge = NULL, *piface = NULL; + struct EthIfacesList list, list_new; + struct EthIface *pprev_iface1 = NULL, *pprev_iface2 = NULL; + int ret = 0; + const char* msg = NULL; + char *genxml = NULL; + virConnectPtr conn = NULL; + virInterfacePtr iface = NULL; + + eth_ifaceslist_init(&list); + eth_ifaceslist_init(&list_new); + + ret = get_host_ifaces(&list, NULL, NULL); + if (ret != 1) { + CU_DEBUG("Failed in list host device."); + goto out; + } + + pprev_iface1 = eth_ifaceslist_search(&list, p1->name); + if (pprev_iface1 == NULL) { + CU_DEBUG("Failed in searching for iface %s", + p1->name); + ret = ERR_DEVICE_NOT_EXIST; + goto out; + } + + pprev_iface2 = eth_ifaceslist_search(&list, p2->name); + if (pprev_iface2 == NULL) { + CU_DEBUG("Failed in searching for iface %s", + p2->name); + ret = ERR_DEVICE_NOT_EXIST; + goto out; + } + + if ((pprev_iface1->eth_type == ETH_TYPE_ETHER_BRIDGE) && + ((pprev_iface2->eth_type == ETH_TYPE_ETHER_VLAN) || + (pprev_iface2->eth_type == ETH_TYPE_ETHER_PHYSICAL))) { + pbridge = pprev_iface1; + piface = pprev_iface2; + } + if ((pprev_iface2->eth_type == ETH_TYPE_ETHER_BRIDGE) && + ((pprev_iface1->eth_type == ETH_TYPE_ETHER_VLAN) || + (pprev_iface1->eth_type == ETH_TYPE_ETHER_PHYSICAL))) { + pbridge = pprev_iface2; + piface = pprev_iface1; + } + + if ((pbridge == NULL) || (piface == NULL)) { + CU_DEBUG("Cannot disconnect these devices, one must be bridge."); + ret = ERR_NOT_SUPPORT; + goto out; + } + + /* for libvirt, just remove the attached bridge in piface and redefine it*/ + CU_FREE(piface->attach_bridge); + piface->attach_bridge = NULL; + /* for a stand alone piface, libvirt/netcf require it have boot_mode set */ + if (piface->run_prop.boot_mode == BOOT_MODE_NOT_GOT) { + piface->run_prop.boot_mode = BOOT_MODE_NONE; + } + eth_ifaceslist_add(&list_new, &piface); + + msg = EthIfaceListTOXML(&genxml, &list_new, 0); + if (msg != NULL) { + CU_DEBUG("Failed in generating xml for iface, msg is %s.", msg); + ret = ERR_GENXML_INTERFACE; + goto out; + } + + conn = connect_any(); + if (conn == NULL) { + CU_DEBUG("Connect for network failed."); + ret = ERR_CONNECT; + goto out; + } + + CU_DEBUG("Calling InterfaceDefine with XML:\n%s", genxml); + iface = virInterfaceDefineXML(conn, genxml, 0); + if (iface == NULL) { + CU_DEBUG("Failed in create iface, xml is:\n %s.", genxml); + ret = ERR_CALL_LIBVIRT; + goto out; + } + ret = 1; + + out: + if (conn != NULL) { + virConnectClose(conn); + } + if (iface != NULL) { + virInterfaceFree(iface); + } + eth_ifaceslist_uninit(&list); + CU_FREE(genxml); + return ret; +} + +int change_state_host_iface(struct EthIface *piface, int state) +{ + int ret = 0, call_ret = 0; + int prev_state = 0; + virConnectPtr conn = NULL; + virInterfacePtr iface = NULL; + + conn = connect_any(); + if (conn == NULL) { + CU_DEBUG("Connect for network failed."); + ret = ERR_CONNECT; + goto out; + } + + iface = virInterfaceLookupByName(conn, piface->name); + if (iface == NULL) { + CU_DEBUG("Failed in finding %s.", piface->name); + ret = ERR_DEVICE_NOT_EXIST; + goto out; + } + + prev_state = virInterfaceIsActive(iface); + if (prev_state == state) { + CU_DEBUG("iface %s already in state %d, request is %d.", piface->name, + prev_state, state); + ret = 1; + goto out; + } + + CU_DEBUG("Calling libvirt API to change state to %d.", state); + if (state == 1) { + call_ret = virInterfaceCreate(iface, 0); + if (call_ret != 0) { + CU_DEBUG("Failed to activate %s in libvirt.", piface->name); + ret = ERR_CALL_LIBVIRT; + goto out; + } + } else if (state == 0) { + call_ret = virInterfaceDestroy(iface, 0); + if (call_ret != 0) { + CU_DEBUG("Failed to destroy %s in libvirt.", piface->name); + ret = ERR_CALL_LIBVIRT; + goto out; + } + } + + ret = 1; + + out: + if (conn != NULL) { + virConnectClose(conn); + } + if (iface != NULL) { + virInterfaceFree(iface); + } + return ret; +} +/* + * Local Variables: + * mode: C + * c-set-style: "K&R" + * tab-width: 8 + * c-basic-offset: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/libxkutil/network_parsing.h b/libxkutil/network_parsing.h new file mode 100644 index 0000000..c8121a5 --- /dev/null +++ b/libxkutil/network_parsing.h @@ -0,0 +1,217 @@ +/* + * Copyright IBM Corp. 2012 + * + * Authors: + * Wenchao Xia + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + */ + +#ifndef NETWORK_PARSING_H +#define NETWORK_PARSING_H + +#include +#include +#include + +/* value defines */ +#define MAX_IFACE_NUM 4096 + +#define NUM_NONE -1 + +#define CU_DEBUG_LEVEL 2 + +#define ERR_CONNECT -1 +#define ERR_LIST_INTERFACE -2 +#define ERR_GENXML_INTERFACE -3 +#define ERR_CALL_LIBVIRT -4 +#define ERR_DEVICE_EXIST -5 +#define ERR_DEVICE_NOT_EXIST -6 +#define ERR_NOT_SUPPORT -7 + +/* macro functions */ +#define CU_DEBUG_OP(lvl, fmt, args...) do { \ + if (CU_DEBUG_LEVEL && (lvl) <= CU_DEBUG_LEVEL) { \ + debug_print(fmt, ##args); \ + } \ +} while (0) + +#define CU_MALLOC(p, size) \ +{ \ + (p) = malloc((size)); \ + if ((p) == NULL) { \ + CU_DEBUG("malloc failed."); \ + } \ +} + +#define CU_CALLOC(p, nmen, size) \ +{ \ + (p) = calloc((nmen), (size)); \ + if ((p) == NULL) { \ + CU_DEBUG("calloc failed."); \ + } \ +} + +#define CU_FREE(p) {free(p); (p) = NULL; } + +/* duplicate char* */ +#define CU_STRDUP(p) (p) == NULL ? NULL : strdup(p); + +/* duplicate char* array */ +#define CU_PSTR_ARRAY_DUP(ppdest, dest_num, ppsrc, src_num, iter) do { \ + (dest_num) = (src_num); \ + (ppdest) = NULL; \ + if (((ppsrc) != NULL) && ((src_num) > 0)) { \ + CU_CALLOC((ppdest), (src_num), sizeof(char *)); \ + (iter) = 0; \ + while ((iter) < (src_num)) { \ + *((ppdest)+(iter)) = CU_STRDUP(*((ppsrc)+(iter))); \ + (iter)++; \ + } \ + } \ +} while (0) + +/* merge integer if dest == default */ +#define NUM_MERGE(dest, src, default) do { \ + if ((dest) == (default)) { \ + (dest) = (src); \ + } \ +} while (0) + +/* merge char* if dest == NULL */ +#define CHARS_MERGE(dest, src) do { \ + if (((dest) == NULL) && ((src) != NULL)) { \ + (dest) = strdup((src)); \ + } \ +} while (0) + +typedef enum { + ETH_TYPE_NOT_GOT = NUM_NONE, + ETH_TYPE_ETHER_ANY = 0x0001, + ETH_TYPE_ETHER_PHYSICAL = 0x0002, + ETH_TYPE_ETHER_BRIDGE = 0x0004, + ETH_TYPE_ETHER_VLAN = 0x0008 +} EthType; + +typedef enum { + VLAN_TYPE_NOT_GOT = NUM_NONE, + VLAN_TYPE_802_1_Q = 1, + VLAN_TYPE_802_1_QBG = 2, + VLAN_TYPE_802_1_QBH = 4 +} VLANType; + +typedef enum { + BOOT_MODE_NOT_GOT = NUM_NONE, + BOOT_MODE_NONE = 0, + BOOT_MODE_AUTOSTART = 1 +} BootMode; + +typedef enum { + ETH_STATE_INACTIVE = 0, + ETH_STATE_ACTIVE = 1 +} Status; + +struct IPV4_Prop { + int DHCP; +} ; + +struct Protocol_Prop { + struct IPV4_Prop ipv4_prop; +} ; + +struct BR_Prop { + int STP; + int delay; + char **port_names; + int port_num; +} ; + +struct Run_Prop { + Status status; + BootMode boot_mode; +} ; + +struct VLAN_Prop_8021q { + int vlan_id; + char *parent; +} ; + +/* HP vlan standard, TBD */ +struct VLAN_Prop_8021qbg { + int invalid; +} ; + +/* Cisco and VMware vlan standard, TBD */ +struct VLAN_Prop_8021qbh { + int invalid; +} ; + +struct VLAN_Prop { + VLANType vlan_type; + union { + struct VLAN_Prop_8021q prop_8021q; + struct VLAN_Prop_8021qbg prop_8021qbg; + struct VLAN_Prop_8021qbh prop_8021qbh; + } props; +} ; + +/* EthIface is logical devices include eth ports and bridges */ +struct EthIface { + char *name; + char *dep_ifname; /* parent dev name */ + char *attach_bridge; /* bridge the iface is attached to */ + char *mac; + EthType eth_type; + struct Run_Prop run_prop; + struct Protocol_Prop protocol_prop; + /* optional properties */ + struct BR_Prop *pbr_prop; + struct VLAN_Prop *pvlan_prop; +} ; + +struct EthIfacesList { + struct EthIface *pifaces[MAX_IFACE_NUM]; + int count; +} ; + +void eth_iface_init(struct EthIface *piface); +void eth_iface_add_br_prop(struct EthIface *piface); +void eth_iface_add_vlan_prop(struct EthIface *piface, int vlan_type); +void eth_iface_uninit(struct EthIface *piface); + +void eth_ifaceslist_init(struct EthIfacesList *plist); +void eth_ifaceslist_uninit(struct EthIfacesList *plist); +/* ppiface must be allocated from heap and it is directly added to list, + to save code of struct duplication */ +int eth_ifaceslist_add(struct EthIfacesList *plist, struct EthIface **ppiface); +/* returned pointer is direct reference to a member in plist */ +struct EthIface *eth_ifaceslist_search(struct EthIfacesList *plist, + char *name); + +void eth_iface_print(struct EthIface *piface); +void eth_ifaceslist_print(struct EthIfacesList *plist); + +typedef int (*eth_iface_filter_func)(const struct EthIface *piface, + void *opaque); + +int eth_iface_filter_peths(const struct EthIface *piface, void *nouse); +int eth_iface_filter_by_name(const struct EthIface *piface, void *name); + +int get_host_ifaces(struct EthIfacesList *plist, + eth_iface_filter_func filter_func, void *filter_opaque); + +int add_host_iface(struct EthIface *piface); +int del_host_iface(struct EthIface *piface); +int mod_host_iface(struct EthIface *piface); + +int connect_two_ifaces(struct EthIface *p1, struct EthIface *p2); +int disconnect_two_ifaces(struct EthIface *p1, struct EthIface *p2); + +int change_state_host_iface(struct EthIface *piface, int state); + +char *get_host_iface_error_reason(int errno); + +#endif diff --git a/libxkutil/network_parsing_test.c b/libxkutil/network_parsing_test.c new file mode 100644 index 0000000..4531364 --- /dev/null +++ b/libxkutil/network_parsing_test.c @@ -0,0 +1,184 @@ +/* + * Copyright IBM Corp. 2012 + * + * Authors: + * Wenchao Xia + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "misc_util.h" +#include "device_parsing.h" +#include "network_parsing.h" + +static long print_and_ret_time_stamp(void) +{ + struct timeval tv; + long ret; + gettimeofday(&tv, NULL); + ret = tv.tv_sec*1000 + tv.tv_usec/1000; + CU_DEBUG("time is [%ld] ms.", ret); + return ret; +} + +static void check_iface_state(struct EthIface *piface, int expect_state) +{ + struct EthIfacesList list; + struct EthIface *piface_search; + + eth_ifaceslist_init(&list); + get_host_ifaces(&list, NULL, NULL); + piface_search = eth_ifaceslist_search(&list, piface->name); + if (piface_search != NULL) { + if (expect_state == 1) { + CU_DEBUG("piface exist, result is:\n"); + eth_iface_print(piface_search); + } else { + CU_DEBUG("Error!! piface %s still exist.", piface->name); + exit(1); + } + } else { + if (expect_state == 1) { + CU_DEBUG("Error!! piface %s do not exist.", piface->name); + exit(1); + } else { + CU_DEBUG("piface %s not exist.", piface->name); + } + } + eth_ifaceslist_uninit(&list); +} + +/* It is a simple test case, autocheck only covers if device exist, other + properties need to be checked manually, otherwise more code need to be + introduced about property comparation. Output of eth_iface_print() in + function check_iface_state() could be used to check the properties. */ +int main(int argc, char **argv) +{ + libvirt_cim_init(); + struct EthIfacesList *plist = NULL; + long start_time, end_time; + struct EthIface *piface_vlan, *piface_br; + + CU_MALLOC(plist, sizeof(struct EthIfacesList)); + eth_ifaceslist_init(plist); + + /* test listing the pifaces */ + start_time = print_and_ret_time_stamp(); + get_host_ifaces(plist, NULL, NULL); + end_time = print_and_ret_time_stamp(); + CU_DEBUG("cost [%d]ms in discovering host network. Result:\n" + "--------------------------------------------------", + end_time - start_time); + eth_ifaceslist_print(plist); + CU_DEBUG("---------------------------------------------"); + eth_ifaceslist_uninit(plist); + + /* test 802.1.q vlan */ + CU_MALLOC(piface_vlan, sizeof(struct EthIface)); + eth_iface_init(piface_vlan); + eth_iface_add_vlan_prop(piface_vlan, VLAN_TYPE_802_1_Q); + + piface_vlan->name = CU_STRDUP("eth0.100"); + piface_vlan->dep_ifname = CU_STRDUP("eth0"); + piface_vlan->eth_type = ETH_TYPE_ETHER_VLAN; + piface_vlan->run_prop.boot_mode = BOOT_MODE_AUTOSTART; + piface_vlan->protocol_prop.ipv4_prop.DHCP = 1; + piface_vlan->pvlan_prop->vlan_type = VLAN_TYPE_802_1_Q; + piface_vlan->pvlan_prop->props.prop_8021q.vlan_id = 100; + piface_vlan->pvlan_prop->props.prop_8021q.parent = CU_STRDUP("eth0"); + CU_DEBUG("********Adding vlan."); + add_host_iface(piface_vlan); + check_iface_state(piface_vlan, 1); + + eth_iface_uninit(piface_vlan); + eth_iface_init(piface_vlan); + piface_vlan->name = CU_STRDUP("eth0.100"); + piface_vlan->protocol_prop.ipv4_prop.DHCP = 0; + piface_vlan->run_prop.boot_mode = BOOT_MODE_NONE; + CU_DEBUG("********Modifying vlan."); + mod_host_iface(piface_vlan); + check_iface_state(piface_vlan, 1); + + /* test bridge */ + CU_MALLOC(piface_br, sizeof(struct EthIface)); + eth_iface_init(piface_br); + eth_iface_add_br_prop(piface_br); + piface_br->name = CU_STRDUP("testbr0"); + piface_br->eth_type = ETH_TYPE_ETHER_BRIDGE; + piface_br->run_prop.boot_mode = BOOT_MODE_AUTOSTART; + piface_br->protocol_prop.ipv4_prop.DHCP = 0; + piface_br->pbr_prop->STP = 1; + piface_br->pbr_prop->delay = 20; + CU_DEBUG("********Adding bridge."); + add_host_iface(piface_br); + check_iface_state(piface_br, 1); + + eth_iface_uninit(piface_br); + eth_iface_init(piface_br); + eth_iface_add_br_prop(piface_br); + piface_br->name = CU_STRDUP("testbr0"); + piface_br->pbr_prop->STP = 0; + piface_br->pbr_prop->delay = 0; + CU_DEBUG("********Modifying bridge."); + mod_host_iface(piface_br); + check_iface_state(piface_br, 1); + + /* test connection */ + CU_DEBUG("********Connect bridge."); + connect_two_ifaces(piface_br, piface_vlan); + check_iface_state(piface_br, 1); + + CU_DEBUG("********Disconnect bridge."); + disconnect_two_ifaces(piface_br, piface_vlan); + check_iface_state(piface_br, 1); + check_iface_state(piface_vlan, 1); + + /* test activation */ + CU_DEBUG("********Activate bridge and vlan"); + change_state_host_iface(piface_br, 1); + change_state_host_iface(piface_vlan, 1); + check_iface_state(piface_br, 1); + check_iface_state(piface_vlan, 1); + + CU_DEBUG("********Deactivate bridge and vlan"); + change_state_host_iface(piface_br, 0); + change_state_host_iface(piface_vlan, 0); + check_iface_state(piface_br, 1); + check_iface_state(piface_vlan, 1); + + /* delete them */ + CU_DEBUG("********Deleting vlan."); + del_host_iface(piface_vlan); + check_iface_state(piface_vlan, 0); + eth_iface_uninit(piface_vlan); + + CU_DEBUG("********Deleting bridge."); + del_host_iface(piface_br); + check_iface_state(piface_br, 0); + eth_iface_uninit(piface_br); + + CU_FREE(piface_br); + CU_FREE(piface_vlan); + CU_FREE(plist); + return 0; +} diff --git a/libxkutil/xmlgen.c b/libxkutil/xmlgen.c index 5c16ebe..23d6cc5 100644 --- a/libxkutil/xmlgen.c +++ b/libxkutil/xmlgen.c @@ -36,8 +36,6 @@ #include "cmpimacs.h" #endif -#define XML_ERROR "Failed to allocate XML memory" - typedef const char *(*devfn_t)(xmlNodePtr node, struct domain *dominfo); typedef const char *(*poolfn_t)(xmlNodePtr node, struct virt_pool *pool); typedef const char *(*resfn_t)(xmlNodePtr node, struct virt_pool_res *res); @@ -831,7 +829,7 @@ static char *features_xml(xmlNodePtr root, struct domain *domain) return NULL; } -static char *tree_to_xml(xmlNodePtr root) +char *tree_to_xml(xmlNodePtr root) { xmlBufferPtr buffer = NULL; xmlSaveCtxtPtr savectx = NULL; diff --git a/libxkutil/xmlgen.h b/libxkutil/xmlgen.h index 743fc82..9c88986 100644 --- a/libxkutil/xmlgen.h +++ b/libxkutil/xmlgen.h @@ -27,11 +27,15 @@ #include "cmpidt.h" +#define XML_ERROR "Failed to allocate XML memory" + struct kv { const char *key; const char *val; }; +char *tree_to_xml(xmlNodePtr root); + char *system_to_xml(struct domain *dominfo); char *device_to_xml(struct virt_device *dev); -- 1.7.1 From xiawenc at linux.vnet.ibm.com Tue Feb 14 08:57:09 2012 From: xiawenc at linux.vnet.ibm.com (Wenchao Xia) Date: Tue, 14 Feb 2012 16:57:09 +0800 Subject: [Libvirt-cim] [PATCH V7 3/7] vlan extention - CIM Model - VESS Message-ID: <1329209829-14503-1-git-send-email-xiawenc@linux.vnet.ibm.com> This patch add VESS according DSP1097. VESS is modeled similar to ComputerSystem. V7: added state change code which bring up or down ethiface. V6: little change about style. V5: Almost no change from V2, just removed one parameter when calling function library. Signed-off-by: Wenchao Xia --- schema/VirtualEthernetSwitchSystem.mof | 10 + schema/VirtualEthernetSwitchSystem.registration | 3 + src/Virt_VirtualEthernetSwitchSystem.c | 477 +++++++++++++++++++++++ src/Virt_VirtualEthernetSwitchSystem.h | 52 +++ 4 files changed, 542 insertions(+), 0 deletions(-) create mode 100644 schema/VirtualEthernetSwitchSystem.mof create mode 100644 schema/VirtualEthernetSwitchSystem.registration create mode 100644 src/Virt_VirtualEthernetSwitchSystem.c create mode 100644 src/Virt_VirtualEthernetSwitchSystem.h diff --git a/schema/VirtualEthernetSwitchSystem.mof b/schema/VirtualEthernetSwitchSystem.mof new file mode 100644 index 0000000..6c43719 --- /dev/null +++ b/schema/VirtualEthernetSwitchSystem.mof @@ -0,0 +1,10 @@ +// Copyright IBM Corp. 2012 +[Description ( + "A class derived from CIM_ComputerSystem to represent " + "the Virtual Bridge on the host."), + Provider("cmpi::Virt_VirtualEthernetSwitchSystem") +] +class Net_VirtualEthernetSwitchSystem : CIM_ComputerSystem +{ + +}; diff --git a/schema/VirtualEthernetSwitchSystem.registration b/schema/VirtualEthernetSwitchSystem.registration new file mode 100644 index 0000000..ac94e7c --- /dev/null +++ b/schema/VirtualEthernetSwitchSystem.registration @@ -0,0 +1,3 @@ +# Copyright IBM Corp. 2012 +# Classname Namespace ProviderName ProviderModule ProviderTypes +Net_VirtualEthernetSwitchSystem root/virt Virt_VirtualEthernetSwitchSystem Virt_VirtualEthernetSwitchSystem instance method diff --git a/src/Virt_VirtualEthernetSwitchSystem.c b/src/Virt_VirtualEthernetSwitchSystem.c new file mode 100644 index 0000000..d6de84c --- /dev/null +++ b/src/Virt_VirtualEthernetSwitchSystem.c @@ -0,0 +1,477 @@ +/* + * Copyright IBM Corp. 2011 + * + * Authors: + * Wenchao Xia + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "Virt_VirtualEthernetSwitchSystem.h" +#include "device_parsing.h" +#include "network_model_helper.h" + +static const CMPIBroker *_BROKER; + +static int set_primary_for_switch(const CMPIBroker *broker, + const struct EthIface *piface, CMPIInstance *instance) +{ + char *name; + uint16_t dedicated; + CMPIArray *array; + CMPIStatus s = {CMPI_RC_OK, NULL}; + + if (piface->name == NULL) { + return 0; + } + + name = get_switch_name_from_iface(piface->name); + CMSetProperty(instance, "Name", + (CMPIValue *)name, CMPI_chars); + CMSetProperty(instance, "ElementName", + (CMPIValue *)name, CMPI_chars); + CU_FREE(name); + + array = CMNewArray(broker, 1, CMPI_uint16, &s); + if ((s.rc != CMPI_RC_OK) || (CMIsNullObject(array))) { + return 0; + } + dedicated = CIM_NUM_SWITCH_DEDICATED; + CMSetArrayElementAt(array, 0, &dedicated, CMPI_uint16); + CMSetProperty(instance, "Dedicated", + (CMPIValue *)&array, CMPI_uint16A); + + return 1; +} + +static int set_secondary_for_switch(const CMPIBroker *broker, + struct EthIface *piface, CMPIInstance *instance) +{ + int state; + if (piface->run_prop.status == ETH_STATE_INACTIVE) { + state = CIM_STATE_DISABLED; + } else if (piface->run_prop.status == ETH_STATE_ACTIVE) { + state = CIM_STATE_ENABLED; + } else { + state = CIM_STATE_UNKNOWN; + } + CMSetProperty(instance, "EnabledState", + (CMPIValue *)&state, CMPI_uint16); + CMSetProperty(instance, "RequestedState", + (CMPIValue *)&state, CMPI_uint16); + + return 1; +} + +/* Populate an instance with information from a switch */ +static CMPIStatus set_properties(const CMPIBroker *broker, + struct EthIface *piface, + const char *prefix, + CMPIInstance *instance) +{ + CMPIStatus s = {CMPI_RC_ERR_FAILED, NULL}; + char *errstr; + + if (!set_primary_for_switch(broker, piface, instance)) { + errstr = "failed to set primary properties for instance."; + CU_DEBUG("%s, iface name %s.", errstr, piface->name); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + if (!set_secondary_for_switch(broker, piface, instance)) { + errstr = "failed to set secondary properties for instance."; + CU_DEBUG("%s, iface name %s.", errstr, piface->name); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + + cu_statusf(broker, &s, + CMPI_RC_OK, + ""); + + out: + return s; +} + +static CMPIStatus instance_from_switch(const CMPIBroker *broker, + const CMPIObjectPath *reference, + struct EthIface *piface, + CMPIInstance **_inst) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst = NULL; + + inst = get_typed_instance(broker, + NETWORK_CLASS_PREFIX, + "VirtualEthernetSwitchSystem", + NAMESPACE(reference)); + if (inst == NULL) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "Unable to init VirtualEthernetSwitchSystem instance"); + goto out; + } + + s = set_properties(broker, + piface, + NETWORK_CLASS_PREFIX, + inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + *_inst = inst; + + out: + return s; +} + +CMPIStatus enum_switches(const CMPIBroker *broker, + const CMPIObjectPath *reference, + const CMPIResult *results, + bool names_only) +{ + struct inst_list list; + CMPIStatus s = {CMPI_RC_OK, NULL}; + struct EthIfacesList ifaces_list; + int ret, i; + char *errstr; + + inst_list_init(&list); + eth_ifaceslist_init(&ifaces_list); + + ret = get_host_ifaces(&ifaces_list, + eth_iface_filter_cim_switch, NULL); + + if (ret != 1) { + errstr = get_host_iface_error_reason(ret); + CU_DEBUG("error num %d returned, reason %s.", ret, errstr); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + eth_ifaceslist_print(&ifaces_list); + + i = 0; + while (i < ifaces_list.count) { + CMPIInstance *inst = NULL; + + s = instance_from_switch(broker, + reference, + ifaces_list.pifaces[i], + &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + inst_list_add(&list, inst); + i++; + } + + if (names_only) { + cu_return_instance_names(results, &list); + } else { + cu_return_instances(results, &list); + } + + out: + inst_list_free(&list); + eth_ifaceslist_uninit(&ifaces_list); + + return s; +} + +CMPIStatus get_switch_by_name(const CMPIBroker *broker, + const char *name, + const CMPIObjectPath *reference, + CMPIInstance **_inst) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst = NULL; + char *eth_name = NULL; + char *errstr; + int ret; + struct EthIfacesList ifaces_list; + + eth_ifaceslist_init(&ifaces_list); + + eth_name = get_iface_name_from_switch(name); + if (eth_name == NULL) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "failed to convert switch_name"); + CU_DEBUG("switch name %s failed to convert.", name); + goto out; + } + + ret = get_host_ifaces(&ifaces_list, + eth_iface_filter_cim_switch_for_name, eth_name); + if (ret != 1) { + errstr = get_host_iface_error_reason(ret); + CU_DEBUG("error num %d returned, reason %s.", ret, errstr); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + if (ifaces_list.count != 1) { + errstr = "expected switch not found."; + CU_DEBUG("%s\n", errstr); + eth_ifaceslist_print(&ifaces_list); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + + s = instance_from_switch(broker, + reference, + ifaces_list.pifaces[0], + &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + *_inst = inst; + + out: + eth_ifaceslist_uninit(&ifaces_list); + CU_FREE(eth_name); + return s; +} + +CMPIStatus get_switch_by_ref(const CMPIBroker *broker, + const CMPIObjectPath *reference, + CMPIInstance **_inst) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst = NULL; + const char *name = NULL; + + if (cu_get_str_path(reference, "Name", &name) != CMPI_RC_OK) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "No domain name specified"); + goto out; + } + + s = get_switch_by_name(broker, name, reference, &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + s = cu_validate_ref(broker, reference, inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + *_inst = inst; + + out: + + return s; +} + +static CMPIStatus __state_change(const CMPIBroker *broker, + const char *name, + uint16_t state, + const CMPIObjectPath *ref) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + struct EthIface iface; + int iface_state; + int ret; + char *errstr; + + eth_iface_init(&iface); + iface.name = get_iface_name_from_switch(name); + if (iface.name == NULL) { + errstr = "failed to get iface name."; + CU_DEBUG("for %s, %s.", name, errstr); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + if (state == CIM_STATE_ENABLED) { + iface_state = ETH_STATE_ACTIVE; + } else if (state == CIM_STATE_DISABLED) { + iface_state = ETH_STATE_INACTIVE; + } else { + cu_statusf(broker, &s, + CMPI_RC_ERR_NOT_SUPPORTED, + "State not supported"); + goto out; + } + + ret = change_state_host_iface(&iface, iface_state); + if (ret != 1) { + errstr = get_host_iface_error_reason(ret); + CU_DEBUG("error num %d returned, reason %s.", ret, errstr); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + + + out: + eth_iface_uninit(&iface); + return s; +} + +static CMPIStatus EnumInstanceNames(CMPIInstanceMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference) +{ + return enum_switches(_BROKER, reference, results, true); +} + +static CMPIStatus EnumInstances(CMPIInstanceMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference, + const char **properties) +{ + return enum_switches(_BROKER, reference, results, false); +} + +static CMPIStatus GetInstance(CMPIInstanceMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference, + const char **properties) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst = NULL; + + s = get_switch_by_ref(_BROKER, reference, &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + CMReturnInstance(results, inst); + + out: + return s; +} + +DEFAULT_CI(); +DEFAULT_MI(); +DEFAULT_DI(); +DEFAULT_EQ(); +DEFAULT_INST_CLEANUP(); + +static CMPIStatus state_change(CMPIMethodMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference, + const CMPIArgs *argsin, + CMPIArgs *argsout) +{ + CMPIStatus s; + CMPIInstance *prev_inst = NULL; + uint16_t state; + int ret; + const char *name = NULL; + uint32_t rc = 1; + + ret = cu_get_u16_arg(argsin, "RequestedState", &state); + if (ret != CMPI_RC_OK) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_INVALID_PARAMETER, + "Invalid RequestedState"); + goto out; + } + + if (cu_get_str_path(reference, "Name", &name) != CMPI_RC_OK) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Name key not specified"); + goto out; + } + + s = get_switch_by_name(_BROKER, name, reference, &prev_inst); + if (s.rc != CMPI_RC_OK || prev_inst == NULL) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_INVALID_PARAMETER, + "Unable to get instance for guest '%s'", + name); + goto out; + } + + s = __state_change(_BROKER, name, state, reference); + + if (s.rc == CMPI_RC_OK) { + rc = 0; + } + out: + CMReturnData(results, &rc, CMPI_uint32); + + return s; +} + +STD_InstanceMIStub(, + Virt_VirtualEthernetSwitchSystem, + _BROKER, + libvirt_cim_init()); + +static struct method_handler RequestStateChange = { + .name = "RequestStateChange", + .handler = state_change, + .args = {{"RequestedState", CMPI_uint16, false}, + {"TimeoutPeriod", CMPI_dateTime, true}, + ARG_END + } +}; + +static struct method_handler *my_handlers[] = { + &RequestStateChange, + NULL +}; + +STDIM_MethodMIStub(, + Virt_VirtualEthernetSwitchSystem, + _BROKER, + libvirt_cim_init(), + my_handlers); + +/* + * Local Variables: + * mode: C + * c-set-style: "K&R" + * tab-width: 8 + * c-basic-offset: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/Virt_VirtualEthernetSwitchSystem.h b/src/Virt_VirtualEthernetSwitchSystem.h new file mode 100644 index 0000000..de8587b --- /dev/null +++ b/src/Virt_VirtualEthernetSwitchSystem.h @@ -0,0 +1,52 @@ +/* + * Copyright IBM Corp. 2011 + * + * Authors: + * Wenchao Xia + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __VIRT_VIRTUALETHERNETSWITCHSYSTEM_H +#define __VIRT_VIRTUALETHERNETSWITCHSYSTEM_H + +#include "misc_util.h" + +CMPIStatus enum_switches(const CMPIBroker *broker, + const CMPIObjectPath *reference, + const CMPIResult *results, + bool names_only); + +CMPIStatus get_switch_by_ref(const CMPIBroker *broker, + const CMPIObjectPath *reference, + CMPIInstance **_inst); + + +CMPIStatus get_switch_by_name(const CMPIBroker *broker, + const char *name, + const CMPIObjectPath *reference, + CMPIInstance **_inst); + + +#endif + +/* + * Local Variables: + * mode: C + * c-set-style: "K&R" + * tab-width: 8 + * c-basic-offset: 8 + * indent-tabs-mode: nil + * End: + */ -- 1.7.1 From xiawenc at linux.vnet.ibm.com Tue Feb 14 08:56:48 2012 From: xiawenc at linux.vnet.ibm.com (Wenchao Xia) Date: Tue, 14 Feb 2012 16:56:48 +0800 Subject: [Libvirt-cim] [PATCH V7 2/7] vlan extention - CIM Model - helper and Makefile Message-ID: <1329209808-14457-1-git-send-email-xiawenc@linux.vnet.ibm.com> This patch change the Makefile, and add helper functions for CIM model such as string parsing and generation. V7: add VESSMS in Makefile. V6: no change from V2. Signed-off-by: Wenchao Xia --- Makefile.am | 16 ++- libxkutil/network_model_helper.c | 473 ++++++++++++++++++++++++++++++++++++++ libxkutil/network_model_helper.h | 101 ++++++++ src/Makefile.am | 29 ++- 4 files changed, 614 insertions(+), 5 deletions(-) create mode 100644 libxkutil/network_model_helper.c create mode 100644 libxkutil/network_model_helper.h diff --git a/Makefile.am b/Makefile.am index 94dc5f3..0ecca54 100644 --- a/Makefile.am +++ b/Makefile.am @@ -63,7 +63,13 @@ MOFS = \ $(top_srcdir)/schema/EntriesInFilterList.mof \ $(top_srcdir)/schema/NestedFilterList.mof \ $(top_srcdir)/schema/AppliedFilterList.mof \ - $(top_srcdir)/schema/HostedFilterList.mof + $(top_srcdir)/schema/HostedFilterList.mof \ + $(top_srcdir)/schema/HostedFilterList.mof \ + $(top_srcdir)/schema/VirtualEthernetSwitchSystem.mof \ + $(top_srcdir)/schema/VirtualEthernetSwitchSystemSettingData.mof \ + $(top_srcdir)/schema/EthernetPort.mof \ + $(top_srcdir)/schema/EthernetPortAllocationSettingData.mof \ + $(top_srcdir)/schema/VirtualEthernetSwitchSystemManagementService.mof INTEROP_MOFS = \ $(top_srcdir)/schema/ComputerSystem.mof \ @@ -150,7 +156,13 @@ REGS = \ $(top_srcdir)/schema/EntriesInFilterList.registration \ $(top_srcdir)/schema/NestedFilterList.registration \ $(top_srcdir)/schema/AppliedFilterList.registration \ - $(top_srcdir)/schema/HostedFilterList.registration + $(top_srcdir)/schema/HostedFilterList.registration \ + $(top_srcdir)/schema/HostedFilterList.registration \ + $(top_srcdir)/schema/VirtualEthernetSwitchSystem.registration \ + $(top_srcdir)/schema/VirtualEthernetSwitchSystemSettingData.registration \ + $(top_srcdir)/schema/EthernetPort.registration \ + $(top_srcdir)/schema/EthernetPortAllocationSettingData.registration \ + $(top_srcdir)/schema/VirtualEthernetSwitchSystemManagementService.registration INTEROP_REGS = \ $(top_srcdir)/schema/RegisteredProfile.registration \ diff --git a/libxkutil/network_model_helper.c b/libxkutil/network_model_helper.c new file mode 100644 index 0000000..9bb3e83 --- /dev/null +++ b/libxkutil/network_model_helper.c @@ -0,0 +1,473 @@ +/* + * Copyright IBM Corp. 2012 + * + * Authors: + * Wenchao Xia + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "network_model_helper.h" +#include "device_parsing.h" + +#include "cmpidt.h" +#include "cmpift.h" +#include "cmpimacs.h" + +/* this function would return a new allocated string or NULL */ +char *compare_and_switch_prefix(const char *orig_str, + const char *orig_prefix, + const char *dest_prefix) +{ + int orig_prefix_len, dest_prefix_len, asret; + char *retstr = NULL; + const char *suffix; + if (orig_str == NULL) { + goto out; + } + orig_prefix_len = strlen(orig_prefix); + dest_prefix_len = strlen(dest_prefix); + if (0 != strncmp(orig_str, orig_prefix, orig_prefix_len)) { + goto out; + } + suffix = orig_str + orig_prefix_len; + asret = asprintf(&retstr, "%s%s", dest_prefix, suffix); + if (asret == -1) { + free(retstr); + retstr = NULL; + } + out: + return retstr; +} + +char *switch_device_id_prefix(const char *whole_id, + const char *orig_prefix, + const char *dest_prefix) +{ + char *system = NULL; + char *device = NULL; + char *new_id = NULL; + char *retstr = NULL; + int asret; + + + if (0 == parse_fq_devid(whole_id, &system, &device)) { + goto out; + } + + new_id = compare_and_switch_prefix(device, + orig_prefix, dest_prefix); + + if (new_id == NULL) { + goto out; + } + asret = asprintf(&retstr, "%s/%s", system, new_id); + if (asret == -1) { + free(retstr); + retstr = NULL; + } + + out: + free(system); + free(device); + free(new_id); + return retstr; +} + +char *ep_id_to_easdea_id(const char *epid) +{ + return switch_device_id_prefix(epid, + ETHPORT_PREFIX, ETHPORT_ALLOCATION_SD_PREFIX); +} + +char *easdea_id_to_ep_id(const char *epid) +{ + return switch_device_id_prefix(epid, + ETHPORT_ALLOCATION_SD_PREFIX, ETHPORT_PREFIX); +} + +char *ep_id_to_easdec_id(const char *epid) +{ + return switch_device_id_prefix(epid, + ETHPORT_PREFIX, ETHPORT_CONNECTION_SD_PREFIX); +} + +char *easdec_id_to_ep_id(const char *epid) +{ + return switch_device_id_prefix(epid, + ETHPORT_CONNECTION_SD_PREFIX, ETHPORT_PREFIX); +} + +char *vlanid_to_connection_name(const int id) +{ + int asret; + char *str = NULL; + char *prefix = CONNECTION_VLAN_PREFIX; + asret = asprintf(&str, "%s%d", prefix, id); + if (asret == -1) { + return NULL; + } + return str; +} + +int vlanid_from_connection_name(const char *name) +{ + int id = -1; + int temp = -1; + char *prefix = CONNECTION_VLAN_PREFIX; + char *dig_start, *dig_end; + if (name == NULL) { + goto out; + } + dig_start = strstr(name, prefix); + if (dig_start == NULL) { + goto out; + } + dig_start += strlen(prefix); + temp = strtol(dig_start, &dig_end, 10); + if ((dig_start == dig_end) || (temp < 0) || (temp > 4095)) { + goto out; + } + id = temp; + out: + return id; +} + +int eth_iface_filter_cim_ethport(const struct EthIface *piface, + void *nouse) +{ + if ((piface->eth_type != ETH_TYPE_NOT_GOT) && + (piface->eth_type != ETH_TYPE_ETHER_BRIDGE)) { + return 1; + } + return 0; +} + +int eth_iface_filter_cim_ethport_for_name(const struct EthIface *piface, + void *name) +{ + int cim_ethport_flag; + cim_ethport_flag = eth_iface_filter_cim_ethport(piface, NULL); + if (cim_ethport_flag == 1) { + if (0 == strcmp(piface->name, name)) { + return 1; + } + } + return 0; +} + +/* returned value need to be freed */ +char *get_ethportsd_name_from_iface(const char *iface_name, const int type) +{ + char *prefix; + char *name; + int size; + + if (iface_name == NULL) { + return NULL; + } + + if (type == EASD_TYPE_EA) { + prefix = ETHPORT_ALLOCATION_SD_PREFIX; + } else { + prefix = ETHPORT_CONNECTION_SD_PREFIX; + } + + size = strlen(iface_name)+strlen(prefix)+1; + CU_MALLOC(name, size); + snprintf(name, size, "%s%s", prefix, iface_name); + return name; +} + +/* returned value need to be freed */ +char *get_iface_name_from_ethportsd(const char *ethport_name, int *ptype) +{ + char *prefix; + char *name = NULL; + int size; + int prefix_len; + int t = -1; + + if (ethport_name == NULL) { + goto out; + } + + prefix = ETHPORT_ALLOCATION_SD_PREFIX; + prefix_len = strlen(prefix); + if (0 != strncmp(ethport_name, prefix, prefix_len)) { + prefix = ETHPORT_CONNECTION_SD_PREFIX; + prefix_len = strlen(prefix); + if (0 != strncmp(ethport_name, prefix, prefix_len)) { + goto out; + } else { + t = EASD_TYPE_EC; + } + } else { + t = EASD_TYPE_EA; + } + size = strlen(ethport_name)-strlen(prefix)+1; + CU_MALLOC(name, size); + snprintf(name, size, "%s", ethport_name+prefix_len); + + out: + if (ptype != NULL) { + *ptype = t; + } + return name; +} + +int eth_iface_filter_cim_switch(const struct EthIface *piface, + void *nouse) +{ + if (piface->eth_type == ETH_TYPE_ETHER_BRIDGE) { + return 1; + } + return eth_iface_filter_peths(piface, nouse); +} + +int eth_iface_filter_cim_switch_for_name(const struct EthIface *piface, + void *name) +{ + int cim_switch_flag; + cim_switch_flag = eth_iface_filter_cim_switch(piface, NULL); + if (cim_switch_flag == 1) { + if (0 == strcmp(piface->name, name)) { + return 1; + } + } + return 0; +} + +/* returned value need to be freed */ +char *get_switch_name_from_iface(const char *iface_name) +{ + char *prefix = SWITCH_PREFIX; + char *name; + int size; + + size = strlen(iface_name)+strlen(prefix)+1; + CU_MALLOC(name, size); + snprintf(name, size, "%s%s", prefix, iface_name); + return name; +} + +/* returned value need to be freed */ +char *get_iface_name_from_switch(const char *switch_name) +{ + char *prefix = SWITCH_PREFIX; + char *name; + int size; + int prefix_len; + + prefix_len = strlen(prefix); + if (0 != strncmp(switch_name, prefix, prefix_len)) { + return NULL; + } + size = strlen(switch_name)-strlen(prefix)+1; + CU_MALLOC(name, size); + snprintf(name, size, "%s", switch_name+prefix_len); + return name; +} + +/* returned value need to be freed */ +char *get_ethport_name_from_iface(const char *iface_name) +{ + char *prefix; + char *name; + int size; + + if (iface_name == NULL) { + return NULL; + } + + prefix = ETHPORT_PREFIX; + size = strlen(iface_name)+strlen(prefix)+1; + CU_MALLOC(name, size); + snprintf(name, size, "%s%s", prefix, iface_name); + return name; +} + +/* returned value need to be freed */ +char *get_iface_name_from_ethport(const char *ethport_name) +{ + char *prefix = ETHPORT_PREFIX; + char *name = NULL; + int size; + int prefix_len; + + if (ethport_name == NULL) { + goto out; + } + + prefix = ETHPORT_PREFIX; + prefix_len = strlen(prefix); + if (0 != strncmp(ethport_name, prefix, prefix_len)) { + goto out; + } + size = strlen(ethport_name)-prefix_len+1; + CU_MALLOC(name, size); + snprintf(name, size, "%s", ethport_name+prefix_len); + + out: + return name; +} + +/* determine the CIM switch from the piface */ +int get_possible_bridge_name_for_cim_model(struct EthIface *piface, + char **pbr1name, char **pbr2name) +{ + char *br1_name; + char *br2_name; + if (piface->attach_bridge != NULL) { + br1_name = get_switch_name_from_iface(piface->attach_bridge); + } else if (piface->dep_ifname != NULL) { + br1_name = get_switch_name_from_iface(piface->dep_ifname); + } else if (piface->eth_type == ETH_TYPE_ETHER_PHYSICAL) { + br1_name = get_switch_name_from_iface(piface->name); + } else { + br1_name = NULL; + } + + if ((piface->attach_bridge != NULL) && (piface->dep_ifname != NULL)) { + br2_name = get_switch_name_from_iface(piface->dep_ifname); + } else if ((piface->attach_bridge != NULL) && + (piface->eth_type == ETH_TYPE_ETHER_PHYSICAL)) { + br2_name = get_switch_name_from_iface(piface->name); + } else { + br2_name = NULL; + } + + /* incase some pifaces such as "lo" have no parent nor attaching + bridge */ + if (br1_name == NULL) { + br1_name = get_switch_name_from_iface(piface->name); + } + *pbr1name = br1_name; + *pbr2name = br2_name; + return 1; +} + +CMPIStatus get_array_uint16_from_instance(const CMPIBroker *broker, + CMPIInstance *inst, + char *array_name, + int *ret_result, + int *ret_size, + int max_size) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIArray *array; + CMPICount array_size; + CMPIData elem; + int i, ret, count = 0; + + ret = cu_get_array_prop(inst, array_name, &array); + if (ret != CMPI_RC_OK) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "array property not found."); + CU_DEBUG("Failed to get array property %s.", array_name); + goto out; + } + array_size = CMGetArrayCount(array, &s); + if ((s.rc != CMPI_RC_OK) || (array_size > max_size) || + (array_size <= 0)) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "failed to get size of array property," + " or its size is 0 or too big."); + CU_DEBUG("failed in getting size of %s property.", array_name); + goto out; + } + for (i = 0; i < array_size; i++) { + elem = CMGetArrayElementAt(array, i, NULL); + if (CMIsNullValue(elem)) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "NULL content of array property."); + CU_DEBUG("NULL content of %s property.", array_name); + goto out; + } + if (!(elem.type & CMPI_INTEGER)) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "wrong type of array property."); + CU_DEBUG("wrong type of %s property.", array_name); + goto out; + } + ret_result[count] = elem.value.uint16; + count++; + } + out: + *ret_size = count; + return s; +} + +CMPIStatus get_array_string_from_instance(const CMPIBroker *broker, + CMPIInstance *inst, + char *array_name, + char **ret_result, + int *ret_size, + int max_size) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIArray *array; + CMPICount array_size; + CMPIData elem; + const char *str; + int i, ret, count = 0; + + ret = cu_get_array_prop(inst, array_name, &array); + if (ret != CMPI_RC_OK) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "array property not found."); + CU_DEBUG("Failed to get array property %s.", array_name); + goto out; + } + array_size = CMGetArrayCount(array, &s); + if ((s.rc != CMPI_RC_OK) || (array_size > max_size) || + (array_size <= 0)) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "failed to get size of array property," + " or its size is 0 or too big."); + CU_DEBUG("failed in getting size of %s property.", array_name); + goto out; + } + for (i = 0; i < array_size; i++) { + elem = CMGetArrayElementAt(array, i, NULL); + if (CMIsNullValue(elem)) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "NULL content of array property."); + CU_DEBUG("NULL content of %s property.", array_name); + goto out; + } + str = NULL; + str = CMGetCharPtr(elem.value.string); + if (str == NULL) { + CU_DEBUG("Could not extract char pointer from " + "CMPIArray %s.", array_name); + goto out; + } + ret_result[count] = CU_STRDUP(str); + count++; + } + out: + *ret_size = count; + return s; +} diff --git a/libxkutil/network_model_helper.h b/libxkutil/network_model_helper.h new file mode 100644 index 0000000..6b3f151 --- /dev/null +++ b/libxkutil/network_model_helper.h @@ -0,0 +1,101 @@ +/* + * Copyright IBM Corp. 2012 + * + * Authors: + * Wenchao Xia + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef NETWORK_MODEL_HELPER_H +#define NETWORK_MODEL_HELPER_H + +#include "network_parsing.h" + +#define EASD_TYPE_EA 1 +#define EASD_TYPE_EC 2 + +#define NETWORK_CLASS_PREFIX "Net" + +#define SWITCH_PREFIX "VS_" +#define VESSD_SYSTEM_PREFIX "Virt" +#define ETHPORT_PREFIX "EP_" +#define ETHPORT_ALLOCATION_SD_PREFIX "EA_" +#define ETHPORT_CONNECTION_SD_PREFIX "EC_" + +#define CONNECTION_VLAN_PREFIX "VLAN" + +#define CIM_NUM_NET_ETHERNET 2 +#define CIM_NUM_SWITCH_DEDICATED 38 +#define CIM_NUM_SWITCHPORT 30 +#define CIM_NUM_VLAN_MODE_TRUNK 5 +#define CIM_NUM_CONSUMERVISIBILITY_PASSEDTHROUGH 2 +#define CIM_NUM_CONSUMERVISIBILITY_VIRTUALIZED 3 + +char *get_switch_name_from_iface(const char *iface_name); +char *get_iface_name_from_switch(const char *switch_name); + +char *get_ethport_name_from_iface(const char *iface_name); +char *get_iface_name_from_ethport(const char *ethport_name); + +char *get_ethportsd_name_from_iface(const char *iface_name, const int type); +char *get_iface_name_from_ethportsd(const char *ethport_name, int *ptype); + +char *ep_id_to_easdea_id(const char *epid); +char *easdea_id_to_ep_id(const char *epid); +char *ep_id_to_easdec_id(const char *epid); +char *easdec_id_to_ep_id(const char *epid); + +char *vlanid_to_connection_name(const int id); +int vlanid_from_connection_name(const char *name); + +int eth_iface_filter_cim_switch(const struct EthIface *piface, + void *nouse); +int eth_iface_filter_cim_switch_for_name(const struct EthIface *piface, + void *name); +int eth_iface_filter_cim_ethport(const struct EthIface *piface, + void *nouse); +int eth_iface_filter_cim_ethport_for_name(const struct EthIface *piface, + void *name); + +int get_possible_bridge_name_for_cim_model(struct EthIface *piface, + char **pbr1name, char **pbr2name); + + +char *compare_and_switch_prefix(const char *orig_str, + const char *orig_prefix, + const char *dest_prefix); + +char *switch_device_id_prefix(const char *whole_id, + const char *orig_prefix, + const char *dest_prefix); + +/* other help function related to CIM */ +CMPIStatus get_array_uint16_from_instance(const CMPIBroker *broker, + CMPIInstance *inst, + char *array_name, + int *ret_result, + int *ret_size, + int max_size); + +CMPIStatus get_array_string_from_instance(const CMPIBroker *broker, + CMPIInstance *inst, + char *array_name, + char **ret_result, + int *ret_size, + int max_size); + + +#endif diff --git a/src/Makefile.am b/src/Makefile.am index 3f90926..18afbb1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,11 +24,17 @@ noinst_HEADERS = profiles.h svpc_types.h \ Virt_ConsoleRedirectionServiceCapabilities.h \ Virt_KVMRedirectionSAP.h \ Virt_FilterList.h \ - Virt_FilterEntry.h + Virt_FilterEntry.h \ + Virt_VirtualEthernetSwitchSystem.h \ + Virt_VESSSD.h \ + Virt_EthernetPort.h \ + Virt_EASD.h \ + Virt_VirtualEthernetSwitchSystemManagementService.h XKUADD = $(top_builddir)/libxkutil/libxkutil.la +NTWADD = $(top_builddir)/libnetwork/libnetwork.la -CFLAGS += -I$(top_srcdir)/libxkutil $(CFLAGS_STRICT) +CFLAGS += -I$(top_srcdir)/libxkutil -I$(top_srcdir)/libnetwork $(CFLAGS_STRICT) AM_LDFLAGS = $(XKUADD) \ -version-info @VERSION_INFO@ @@ -85,7 +91,12 @@ provider_LTLIBRARIES = libVirt_ComputerSystem.la \ libVirt_EntriesInFilterList.la \ libVirt_NestedFilterList.la \ libVirt_HostedFilterList.la \ - libVirt_AppliedFilterList.la + libVirt_AppliedFilterList.la \ + libVirt_VirtualEthernetSwitchSystem.la \ + libVirt_VESSSD.la \ + libVirt_EthernetPort.la \ + libVirt_EASD.la \ + libVirt_VirtualEthernetSwitchSystemManagementService.la libVirt_ComputerSystem_la_SOURCES = Virt_ComputerSystem.c libVirt_ComputerSystem_la_DEPENDENCIES = libVirt_VirtualSystemSnapshotService.la @@ -274,3 +285,15 @@ libVirt_HostedFilterList_la_LIBADD = -lVirt_HostSystem -lVirt_FilterList libVirt_AppliedFilterList_la_DEPENDENCIES = libVirt_Device.la libVirt_FilterList.la libVirt_AppliedFilterList_la_SOURCES = Virt_AppliedFilterList.c libVirt_AppliedFilterList_la_LIBADD = -lVirt_Device -lVirt_FilterList + +libVirt_VirtualEthernetSwitchSystem_la_SOURCES = Virt_VirtualEthernetSwitchSystem.c + +libVirt_VESSSD_la_SOURCES = Virt_VESSSD.c + +libVirt_EthernetPort_la_SOURCES = Virt_EthernetPort.c + +libVirt_EASD_la_SOURCES = Virt_EASD.c + +libVirt_VirtualEthernetSwitchSystemManagementService_la_DEPENDENCIES = libVirt_VirtualSystemManagementService.la libVirt_HostSystem.la libVirt_EASD.la libVirt_VirtualEthernetSwitchSystem.la +libVirt_VirtualEthernetSwitchSystemManagementService_la_SOURCES = Virt_VirtualEthernetSwitchSystemManagementService.c +libVirt_VirtualEthernetSwitchSystemManagementService_la_LIBADD = -lVirt_VirtualSystemManagementService -lVirt_HostSystem -lVirt_EASD -lVirt_VirtualEthernetSwitchSystem -- 1.7.1 From xiawenc at linux.vnet.ibm.com Tue Feb 14 08:57:24 2012 From: xiawenc at linux.vnet.ibm.com (Wenchao Xia) Date: Tue, 14 Feb 2012 16:57:24 +0800 Subject: [Libvirt-cim] [PATCH V7 4/7] vlan extention - CIM Model - VESSSD Message-ID: <1329209844-14532-1-git-send-email-xiawenc@linux.vnet.ibm.com> This patch add VESSSD, VirtualSwitch are bridge and pNIC on host. V7: added Delay, AutoStart, DHCP properties which exist in libvirtAPI. V6: same with V2. Signed-off-by: Wenchao Xia --- schema/VirtualEthernetSwitchSystemSettingData.mof | 33 ++ ...ualEthernetSwitchSystemSettingData.registration | 3 + src/Virt_VESSSD.c | 392 ++++++++++++++++++++ src/Virt_VESSSD.h | 39 ++ 4 files changed, 467 insertions(+), 0 deletions(-) create mode 100644 schema/VirtualEthernetSwitchSystemSettingData.mof create mode 100644 schema/VirtualEthernetSwitchSystemSettingData.registration create mode 100644 src/Virt_VESSSD.c create mode 100644 src/Virt_VESSSD.h diff --git a/schema/VirtualEthernetSwitchSystemSettingData.mof b/schema/VirtualEthernetSwitchSystemSettingData.mof new file mode 100644 index 0000000..9dea980 --- /dev/null +++ b/schema/VirtualEthernetSwitchSystemSettingData.mof @@ -0,0 +1,33 @@ +// Copyright IBM Corp. 2012 + + +/* fix me: the libvirt-cim lacks parent class + "VirtualEthernetSwitchSettingData" defined in DSP1050 */ +[Description ( + "A class derived from Virt_VirtualEthernetSystemSettingData to represent " + "the config of ."), + Provider("cmpi::Virt_VESSSD") +] +class Net_VirtualEthernetSwitchSystemSettingData : CIM_VirtualSystemSettingData +{ + + [Description ("Virtual Switch System type number")] + string VirtualSystemType; + + string AssociatedResourcePool; + + uint16 VLAN_Connection[]; + + uint16 MaxNumAddress; + + uint16 EVBMode; + + uint16 STP; + + uint16 Delay; + + uint16 AutoStart; + + uint16 DHCP; + +}; diff --git a/schema/VirtualEthernetSwitchSystemSettingData.registration b/schema/VirtualEthernetSwitchSystemSettingData.registration new file mode 100644 index 0000000..1ba7e0c --- /dev/null +++ b/schema/VirtualEthernetSwitchSystemSettingData.registration @@ -0,0 +1,3 @@ +# Copyright IBM Corp. 2012 +# Classname Namespace ProviderName ProviderModule ProviderTypes +Net_VirtualEthernetSwitchSystemSettingData root/virt Virt_VESSSD Virt_VESSSD instance diff --git a/src/Virt_VESSSD.c b/src/Virt_VESSSD.c new file mode 100644 index 0000000..724d3b8 --- /dev/null +++ b/src/Virt_VESSSD.c @@ -0,0 +1,392 @@ +/* + * Copyright IBM Corp. 2012 + * + * Authors: + * Wenchao Xia + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "cs_util.h" +#include "misc_util.h" +#include "device_parsing.h" + +#include "Virt_VESSSD.h" +#include "network_model_helper.h" + +static const CMPIBroker *_BROKER; + +static int set_primary_for_vesssd(const char *prefix, const CMPIBroker *broker, + struct EthIface *piface, CMPIInstance *instance) +{ + char *name, *vesssd_name; + int asret; + + if (piface->name == NULL) { + return 0; + } + + CMSetProperty(instance, "VirtualSystemType", + (CMPIValue *)"DMTF:VirtualEthernetSwitch", CMPI_chars); + + name = get_switch_name_from_iface(piface->name); + asret = asprintf(&vesssd_name, "%s:%s", prefix, name); + + CMSetProperty(instance, "InstanceID", + (CMPIValue *)vesssd_name, CMPI_chars); + CMSetProperty(instance, "ElementName", + (CMPIValue *)name, CMPI_chars); + CMSetProperty(instance, "VirtualSystemIdentifier", + (CMPIValue *)name, CMPI_chars); + CMSetProperty(instance, "VirtualSystemType", + (CMPIValue *)prefix, CMPI_chars); + + + + free(vesssd_name); + CU_FREE(name); + + return 1; +} + +static int set_secondary_for_vesssd(const CMPIBroker *broker, + struct EthIface *piface, CMPIInstance *instance) +{ + uint16_t dhcp; + if (piface->eth_type == ETH_TYPE_ETHER_BRIDGE) { + if (piface->pbr_prop->STP >= 0) { + CMSetProperty(instance, "STP", + (CMPIValue *)&piface->pbr_prop->STP, CMPI_uint16); + } + if (piface->pbr_prop->delay >= 0) { + CMSetProperty(instance, "Delay", + (CMPIValue *)&piface->pbr_prop->delay, CMPI_uint16); + } + } + + if (piface->protocol_prop.ipv4_prop.DHCP == 1) { + dhcp = 1; + } else { + /* dhcp would be -1 because in xml of + in netcf it would never be 0. */ + dhcp = 0; + } + CMSetProperty(instance, "DHCP", (CMPIValue *)&dhcp, CMPI_uint16); + + if (piface->run_prop.boot_mode >= 0) { + CMSetProperty(instance, "AutoStart", + (CMPIValue *)&piface->run_prop.boot_mode, + CMPI_uint16); + } + + return 1; +} + +/* Populate an instance with information from a switch */ +static CMPIStatus set_properties(const CMPIBroker *broker, + struct EthIface *piface, + const char *prefix, + CMPIInstance *instance) +{ + CMPIStatus s = {CMPI_RC_ERR_FAILED, NULL}; + char *errstr; + + if (!set_primary_for_vesssd(prefix, broker, piface, instance)) { + errstr = "failed to set primary properties for instance."; + CU_DEBUG("%s, iface name %s.", errstr, piface->name); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + if (!set_secondary_for_vesssd(broker, piface, instance)) { + errstr = "failed to set secondary properties for instance."; + CU_DEBUG("%s, iface name %s.", errstr, piface->name); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + + cu_statusf(broker, &s, + CMPI_RC_OK, + ""); + + out: + return s; +} + +static CMPIStatus instance_from_vesssd(const CMPIBroker *broker, + const CMPIObjectPath *reference, + struct EthIface *piface, + CMPIInstance **_inst) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst = NULL; + + inst = get_typed_instance(broker, + NETWORK_CLASS_PREFIX, + "VirtualEthernetSwitchSystemSettingData", + NAMESPACE(reference)); + if (inst == NULL) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "Unable to init SwitchSystem instance"); + goto out; + } + + s = set_properties(broker, + piface, + VESSD_SYSTEM_PREFIX, + inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + *_inst = inst; + + out: + return s; +} + +CMPIStatus enum_vesssd(const CMPIBroker *broker, + const CMPIObjectPath *reference, + struct inst_list *plist) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + struct EthIfacesList ifaces_list; + int ret, i; + char *errstr; + + eth_ifaceslist_init(&ifaces_list); + + ret = get_host_ifaces(&ifaces_list, + eth_iface_filter_cim_switch, NULL); + + if (ret != 1) { + errstr = get_host_iface_error_reason(ret); + CU_DEBUG("error num %d returned, reason %s.", ret, errstr); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + + i = 0; + while (i < ifaces_list.count) { + CMPIInstance *inst = NULL; + + s = instance_from_vesssd(broker, + reference, + ifaces_list.pifaces[i], + &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + inst_list_add(plist, inst); + i++; + } + + out: + eth_ifaceslist_uninit(&ifaces_list); + + return s; +} + +static CMPIStatus return_enum_vesssd(const CMPIBroker *broker, + const CMPIObjectPath *reference, + const CMPIResult *results, + bool names_only) +{ + struct inst_list list; + CMPIStatus s = {CMPI_RC_OK, NULL}; + inst_list_init(&list); + + s = enum_vesssd(broker, reference, &list); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + if (names_only) { + cu_return_instance_names(results, &list); + } else { + cu_return_instances(results, &list); + } + out: + inst_list_free(&list); + return s; +} + +CMPIStatus get_vesssd_by_name(const CMPIBroker *broker, + const char *name, + const CMPIObjectPath *reference, + CMPIInstance **_inst) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst = NULL; + char *eth_name = NULL; + char *errstr; + int ret; + struct EthIfacesList ifaces_list; + + eth_ifaceslist_init(&ifaces_list); + + eth_name = get_iface_name_from_switch(name); + if (eth_name == NULL) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "failed to convert switch_name"); + CU_DEBUG("switch name %s failed to convert.", name); + goto out; + } + + ret = get_host_ifaces(&ifaces_list, + eth_iface_filter_cim_switch_for_name, eth_name); + + if (ret != 1) { + errstr = get_host_iface_error_reason(ret); + CU_DEBUG("error num %d returned, reason %s.", ret, errstr); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + if (ifaces_list.count != 1) { + errstr = "expected switch not found."; + CU_DEBUG("%s\n", errstr); + eth_ifaceslist_print(&ifaces_list); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + + s = instance_from_vesssd(broker, + reference, + ifaces_list.pifaces[0], + &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + *_inst = inst; + + out: + eth_ifaceslist_uninit(&ifaces_list); + CU_FREE(eth_name); + return s; +} + +CMPIStatus get_vesssd_by_ref(const CMPIBroker *broker, + const CMPIObjectPath *reference, + CMPIInstance **_inst) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst = NULL; + char *name = NULL; + + if ((!parse_instanceid(reference, NULL, &name)) || (name == NULL)) { + cu_statusf(broker, &s, + CMPI_RC_ERR_NOT_FOUND, + "No such instance (InstanceID)"); + goto out; + } + + s = get_vesssd_by_name(broker, name, reference, &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + s = cu_validate_ref(broker, reference, inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + *_inst = inst; + + out: + free(name); + + return s; +} + +static CMPIStatus EnumInstanceNames(CMPIInstanceMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference) +{ + return return_enum_vesssd(_BROKER, reference, results, true); +} + +static CMPIStatus EnumInstances(CMPIInstanceMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference, + const char **properties) +{ + return return_enum_vesssd(_BROKER, reference, results, false); +} + +static CMPIStatus GetInstance(CMPIInstanceMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference, + const char **properties) +{ + CMPIStatus s; + CMPIInstance *inst = NULL; + + s = get_vesssd_by_ref(_BROKER, reference, &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + CMReturnInstance(results, inst); + + out: + return s; +} + +DEFAULT_CI(); +DEFAULT_MI(); +DEFAULT_DI(); +DEFAULT_EQ(); +DEFAULT_INST_CLEANUP(); + +STD_InstanceMIStub(, + Virt_VESSSD, + _BROKER, + libvirt_cim_init()); + +/* + * Local Variables: + * mode: C + * c-set-style: "K&R" + * tab-width: 8 + * c-basic-offset: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/Virt_VESSSD.h b/src/Virt_VESSSD.h new file mode 100644 index 0000000..5105057 --- /dev/null +++ b/src/Virt_VESSSD.h @@ -0,0 +1,39 @@ +/* + * Copyright IBM Corp. 2011 + * + * Authors: + * Wenchao Xia + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __VIRT_VESSSD_H +#define __VIRT_VESSSD_H + + +CMPIStatus enum_vesssd(const CMPIBroker *broker, + const CMPIObjectPath *reference, + struct inst_list *plist); + +CMPIStatus get_vesssd_by_ref(const CMPIBroker *broker, + const CMPIObjectPath *reference, + CMPIInstance **_inst); + +CMPIStatus get_vesssd_by_name(const CMPIBroker *broker, + const char *name, + const CMPIObjectPath *reference, + CMPIInstance **_inst); + + +#endif -- 1.7.1 From xiawenc at linux.vnet.ibm.com Tue Feb 14 08:58:23 2012 From: xiawenc at linux.vnet.ibm.com (Wenchao Xia) Date: Tue, 14 Feb 2012 16:58:23 +0800 Subject: [Libvirt-cim] [PATCH V7 7/7] vlan extention - CIM Model - VESSMS Message-ID: <1329209903-14658-1-git-send-email-xiawenc@linux.vnet.ibm.com> This patch added a new service class VESSMS which can modify host network about adding, modifying, deleting 802.1.q vlan and bridge. The model of bridge modification is according to VSMS model, and on DSP1097 it says virtual switch should be managed similar to ComputerSystem. The model of allocation of vlan port, is on chapter 9.1.2 of DSP1050_1.0. Difference is that, this patch did not use Parent propety to identify which switch it should belongs to, but use property InstanceID to say it, such as VS_eth0/EA_eth0.10, because using Parent for port allocation needs to implement EC_POOL making things more complicate. The model of connecting of vlan port with bridge, is on chapter 9.1.4 of DSP1050_1.0. The patch matches it despite of that EA_POOL and EC_POOL are not implemented. V7: Some host network checking such as checking of existence for an EthIface before modify it, are moved to function library. Code style changed to fit libvirt-cim. Added properties AutoStart, DHCP, Delay. Other things are same with V2. Signed-off-by: Wenchao Xia --- ...irtualEthernetSwitchSystemManagementService.mof | 14 + ...ernetSwitchSystemManagementService.registration | 3 + src/Virt_HostSystem.c | 2 +- src/Virt_HostSystem.h | 2 + ..._VirtualEthernetSwitchSystemManagementService.c | 1289 ++++++++++++++++++++ ..._VirtualEthernetSwitchSystemManagementService.h | 31 + src/Virt_VirtualSystemManagementService.c | 2 +- src/Virt_VirtualSystemManagementService.h | 4 + 8 files changed, 1345 insertions(+), 2 deletions(-) create mode 100644 schema/VirtualEthernetSwitchSystemManagementService.mof create mode 100644 schema/VirtualEthernetSwitchSystemManagementService.registration create mode 100644 src/Virt_VirtualEthernetSwitchSystemManagementService.c create mode 100644 src/Virt_VirtualEthernetSwitchSystemManagementService.h diff --git a/schema/VirtualEthernetSwitchSystemManagementService.mof b/schema/VirtualEthernetSwitchSystemManagementService.mof new file mode 100644 index 0000000..5317305 --- /dev/null +++ b/schema/VirtualEthernetSwitchSystemManagementService.mof @@ -0,0 +1,14 @@ +// Copyright IBM Corp. 2011 + +[Provider("cmpi::Virt_VirtualEthernetSwitchSystemManagementService")] +class Net_VirtualEthernetSwitchSystemManagementService : CIM_VirtualSystemManagementService +{ + [Description("HG changeset id of the providers")] + string Changeset; + + [Description("HG revision number of the providers")] + string Revision; + + [Description("Package Version")] + string Release; +}; diff --git a/schema/VirtualEthernetSwitchSystemManagementService.registration b/schema/VirtualEthernetSwitchSystemManagementService.registration new file mode 100644 index 0000000..ef2b4b1 --- /dev/null +++ b/schema/VirtualEthernetSwitchSystemManagementService.registration @@ -0,0 +1,3 @@ +# Copyright IBM Corp. 2011 +# Classname Namespace ProviderName ProviderModule ProviderTypes +Net_VirtualEthernetSwitchSystemManagementService root/virt Virt_VirtualEthernetSwitchSystemManagementService Virt_VirtualEthernetSwitchSystemManagementService method instance diff --git a/src/Virt_HostSystem.c b/src/Virt_HostSystem.c index 724a5ea..de8ec13 100644 --- a/src/Virt_HostSystem.c +++ b/src/Virt_HostSystem.c @@ -76,7 +76,7 @@ static int resolve_host(char *host, char *buf, int size) return 0; } -static int get_fqdn(char *buf, int size) +int get_fqdn(char *buf, int size) { char host[256]; int ret = 0; diff --git a/src/Virt_HostSystem.h b/src/Virt_HostSystem.h index 53ebf1c..3b988c1 100644 --- a/src/Virt_HostSystem.h +++ b/src/Virt_HostSystem.h @@ -21,6 +21,8 @@ #ifndef __VIRT_HOSTSYSTEM_H #define __VIRT_HOSTSYSTEM_H +int get_fqdn(char *buf, int size); + CMPIStatus get_host(const CMPIBroker *broker, const CMPIContext *context, const CMPIObjectPath *reference, diff --git a/src/Virt_VirtualEthernetSwitchSystemManagementService.c b/src/Virt_VirtualEthernetSwitchSystemManagementService.c new file mode 100644 index 0000000..1048676 --- /dev/null +++ b/src/Virt_VirtualEthernetSwitchSystemManagementService.c @@ -0,0 +1,1289 @@ +/* + * Copyright IBM Corp. 2012 + * + * Authors: + * Wenchao Xia + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cmpidt.h" +#include "cmpift.h" +#include "cmpimacs.h" + +#include "cs_util.h" +#include "misc_util.h" +#include "device_parsing.h" +#include "xmlgen.h" + +#include +#include +#include +#include + +#include "misc_util.h" +#include "infostore.h" + +#include "Virt_VirtualSystemManagementService.h" +#include "Virt_VirtualEthernetSwitchSystemManagementService.h" +#include "Virt_VirtualEthernetSwitchSystem.h" +#include "Virt_HostSystem.h" +#include "Virt_EASD.h" +#include "network_model_helper.h" +#include "svpc_types.h" + +#include "config.h" + + +static const CMPIBroker *_BROKER; + +typedef enum ResourceAction { + RESOURCE_ADD, + RESOURCE_DEL, + RESOURCE_MOD, +} ResourceAction; + +static CMPIArray *set_result_res_vessms(struct inst_list *list, + const char *ns) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIObjectPath *op = NULL; + CMPIArray *res = NULL; + int i = 0; + + if (list->cur == 0) { + CU_DEBUG("No resources were added or modified"); + return res; + } + + res = CMNewArray(_BROKER, list->cur, CMPI_ref, &s); + if ((s.rc != CMPI_RC_OK) || (res == NULL)) { + CU_DEBUG("Unable to create results array"); + goto out; + } + + for (i = 0; list->list[i] != NULL; i++) { + op = CMGetObjectPath(list->list[i], NULL); + if (op == NULL) { + CU_DEBUG("Unable to EASD reference"); + goto out; + } + CMSetNameSpace(op, ns); + + s = CMSetArrayElementAt(res, i, (CMPIValue *)&op, CMPI_ref); + if (s.rc != CMPI_RC_OK) { + CU_DEBUG("Error setting results array element"); + goto out; + } + } + + out: + if (s.rc != CMPI_RC_OK) { + res = NULL; + } + + return res; +} + +static CMPIStatus check_piface_for_easd_ea(const CMPIBroker *broker, + struct EthIface *piface) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + struct VLAN_Prop_8021q *pvlan_8021q; + if ((piface->eth_type != ETH_TYPE_ETHER_VLAN) || + (piface->pvlan_prop->vlan_type != VLAN_TYPE_802_1_Q)) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "now only support opertaion for IEEE 802.1.q."); + CU_DEBUG("only support IEEE 802.1.q, request is:"); + eth_iface_print(piface); + goto out; + } + + pvlan_8021q = &(piface->pvlan_prop->props.prop_8021q); + if ((pvlan_8021q->vlan_id < 0) || (pvlan_8021q->vlan_id > 4095)) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "invalid vlan id set."); + CU_DEBUG("invalid vlan id %d set.", pvlan_8021q->vlan_id); + goto out; + } + + out: + return s; +} + +static CMPIStatus check_piface_for_easd_ec(const CMPIBroker *broker, + struct EthIface *piface_src, + struct EthIface *piface_dest) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + if ((piface_dest->eth_type != ETH_TYPE_ETHER_BRIDGE) || + (piface_dest->name == NULL)) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "now only support connection between bridge and " + "port, but the dest is not a bridge or " + "dest name not got."); + CU_DEBUG("requested connectting device %s is not a bridge.", + piface_dest->name); + goto out; + } + + if (piface_src->name == NULL) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "connection src port was not got."); + CU_DEBUG("connection src port was not got."); + goto out; + } + + out: + return s; +} + +/* piface need to be created before calling the funtion */ +static CMPIStatus instance_to_vesssd(const CMPIBroker *broker, + struct EthIface *piface, + CMPIInstance *inst) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIObjectPath *opathp = NULL; + const char *brname = NULL; + const char *cn = NULL; + char *pfx = NULL; + uint16_t stp, delay, dhcp, boot_mode; + int ret; + + opathp = CMGetObjectPath(inst, NULL); + if (opathp == NULL) { + cu_statusf(broker, &s, + CMPI_RC_ERR_NOT_FOUND, + "failed to get object path."); + goto out; + } + + cn = CLASSNAME(opathp); + pfx = class_prefix_name(cn); + if (pfx == NULL) { + cu_statusf(broker, &s, + CMPI_RC_ERR_NOT_FOUND, + "Unknown prefix for the class."); + goto out; + } + + ret = cu_get_str_prop(inst, "VirtualSystemIdentifier", &brname); + if (ret != CMPI_RC_OK) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "property VirtualSystemIdentifier not set."); + CU_DEBUG("failed to get property VirtualSystemIdentifier."); + goto out; + } + piface->name = get_iface_name_from_switch(brname); + if (piface->name == NULL) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "failed to convert switch_name"); + CU_DEBUG("switch name %s failed to convert.", brname); + goto out; + } + + ret = cu_get_u16_prop(inst, "STP", &stp); + if (ret == CMPI_RC_OK) { + piface->pbr_prop->STP = stp; + } + + ret = cu_get_u16_prop(inst, "Delay", &delay); + if (ret == CMPI_RC_OK) { + piface->pbr_prop->delay = delay; + } + + ret = cu_get_u16_prop(inst, "DHCP", &dhcp); + if (ret == CMPI_RC_OK) { + piface->protocol_prop.ipv4_prop.DHCP = dhcp; + } + + ret = cu_get_u16_prop(inst, "AutoStart", &boot_mode); + if (ret == CMPI_RC_OK) { + piface->run_prop.boot_mode = boot_mode; + } + + out: + free(pfx); + return s; +} + +static CMPIStatus instance_to_easd_ea(const CMPIBroker *broker, + struct EthIface *piface, + CMPIInstance *inst) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIStatus s_tmp; + int ret, temp; + uint16_t vlan_type = 0; + uint16_t dhcp, boot_mode; + char *charpvalues[8]; + int charpcount = 0; + struct VLAN_Prop_8021q *pvlan_8021q = NULL; + + ret = cu_get_u16_prop(inst, "VLANType", &vlan_type); + if (ret == CMPI_RC_OK) { + if (vlan_type == 1) { + piface->eth_type = ETH_TYPE_ETHER_VLAN; + piface->pvlan_prop->vlan_type = VLAN_TYPE_802_1_Q; + pvlan_8021q = &(piface->pvlan_prop->props.prop_8021q); + } else { + CU_DEBUG("unsupported VLANType " + "%d requested", vlan_type); + } + } else { + CU_DEBUG("VLANType is missing"); + } + + if ((pvlan_8021q == NULL) || + (piface->pvlan_prop->vlan_type != VLAN_TYPE_802_1_Q)) { + goto end_of_8021q; + } + + pvlan_8021q->parent = CU_STRDUP(piface->dep_ifname); + + s_tmp = get_array_string_from_instance(broker, inst, "Connection", + charpvalues, &charpcount, 8); + if ((s_tmp.rc == CMPI_RC_OK) && (charpcount == 1)) { + temp = vlanid_from_connection_name(charpvalues[0]); + if ((temp >= 0) && (temp < 4096)) { + pvlan_8021q->vlan_id = temp; + } + } else { + CU_DEBUG("Connnection property have %d settings.", charpcount); + } + + end_of_8021q: + + ret = cu_get_u16_prop(inst, "DHCP", &dhcp); + if (ret == CMPI_RC_OK) { + piface->protocol_prop.ipv4_prop.DHCP = dhcp; + } + + ret = cu_get_u16_prop(inst, "AutoStart", &boot_mode); + if (ret == CMPI_RC_OK) { + piface->run_prop.boot_mode = boot_mode; + } + + return s; +} + +static CMPIStatus instance_to_easd_ec(const CMPIBroker *broker, + struct EthIface *piface_src, + struct EthIface *piface_dest, + CMPIInstance *inst) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}, s_tmp; + int ret, i; + char *charpvalues[8]; + int charpcount = 0; + char *prefix = NULL, *portname = NULL; + const char *tmp; + + s_tmp = get_array_string_from_instance(broker, inst, "HostResource", + charpvalues, &charpcount, 8); + if ((s_tmp.rc == CMPI_RC_OK) && (charpcount == 1)) { + piface_dest->name = get_iface_name_from_switch(charpvalues[0]); + if (piface_dest->name != NULL) { + piface_dest->eth_type = ETH_TYPE_ETHER_BRIDGE; + } + } else { + CU_DEBUG("HostResource have %d settings.", charpcount); + } + i = 0; + while (i < charpcount) { + CU_FREE(charpvalues[i]); + i++; + } + + ret = cu_get_str_prop(inst, "Parent", &tmp); + if (ret == CMPI_RC_OK) { + if (1 == parse_fq_devid(tmp, &prefix, &portname)) { + CU_FREE(piface_src->name); + piface_src->name = get_iface_name_from_ethportsd(portname, + NULL); + } + } + piface_src->eth_type = ETH_TYPE_ETHER_ANY; + + CU_FREE(prefix); + CU_FREE(portname); + return s; +} + +/* pifaces need to be created before calling the funtion */ +static CMPIStatus instance_to_easd(const CMPIBroker *broker, + const char *preset_parent, + struct EthIface *piface_src, + struct EthIface *piface_dest, + CMPIInstance *inst, + int *type) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + char *prefix = NULL; + char *name = NULL; + char *port_name = NULL; + char *switch_name = NULL; + const char *tmp; + int request_type = 0; + int ret; + + CU_DEBUG("enter inst to easd, preset_parent is %s.", preset_parent); + /* If a preset_parent is set by the user, then the code use it as + parent device. This parameter was used when user call the method + with parameter AffectedSystem. */ + if (preset_parent == NULL) { + s = get_instanceid(inst, &prefix, &name); + if ((s.rc != CMPI_RC_OK) || + (prefix == NULL) || (name == NULL)) { + cu_statusf(broker, &s, + CMPI_RC_ERR_NOT_FOUND, + "failed to translate InstanceId"); + CU_DEBUG("failed to translate InstanceId, " + "prefix %s, name %s.", prefix, name); + goto out; + } + } else { + /*fix me, use value from Parent if ElementName was not set */ + ret = cu_get_str_prop(inst, "ElementName", &tmp); + if (ret == CMPI_RC_OK) { + name = CU_STRDUP(tmp); + prefix = CU_STRDUP(preset_parent); + } else { + s = get_instanceid(inst, &prefix, &name); + if ((s.rc != CMPI_RC_OK) || (name == NULL)) { + cu_statusf(broker, &s, + CMPI_RC_ERR_NOT_FOUND, + "failed to get port name, " + "InstanceID or ElementName " + "need to be set correctly."); + CU_DEBUG("failed to geto port name, " + "prefix %s, name %s.", prefix, name); + goto out; + } + } + } + + if (name == NULL) { + s = get_instanceid(inst, &prefix, &name); + if ((s.rc != CMPI_RC_OK) || + (prefix == NULL) || (name == NULL)) { + cu_statusf(broker, &s, + CMPI_RC_ERR_NOT_FOUND, + "failed to translate InstanceId"); + CU_DEBUG("failed to translate InstanceId, " + "prefix %s, name %s.", prefix, name); + goto out; + } + } + + switch_name = get_iface_name_from_switch(prefix); + if (switch_name == NULL) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "failed to convert instance prefix name"); + CU_DEBUG("switch name %s failed to convert.", prefix); + goto out; + } + port_name = get_iface_name_from_ethportsd(name, &request_type); + if (port_name == NULL) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "failed to convert instance suffix name"); + CU_DEBUG("ethport name %s failed to convert.", name); + goto out; + } + + if (request_type == EASD_TYPE_EA) { + piface_src->name = port_name; + piface_src->dep_ifname = switch_name; + port_name = NULL; + switch_name = NULL; + s = instance_to_easd_ea(broker, piface_src, inst); + } else { + piface_src->name = port_name; + port_name = NULL; + s = instance_to_easd_ec(broker, piface_src, piface_dest, inst); + } + + out: + *type = request_type; + CU_FREE(prefix); + CU_FREE(name); + CU_FREE(port_name); + CU_FREE(switch_name); + return s; +} + +static CMPIStatus _update_easd_for(const CMPIBroker *broker, + const CMPIContext *context, + const CMPIObjectPath *ref, + const char *preset_parent, + CMPIInstance *rasd, + ResourceAction action) +{ + CMPIStatus s; + int type; + struct EthIface iface_src, iface_dest; + int ret; + char *errstr; + + eth_iface_init(&iface_src); + eth_iface_init(&iface_dest); + eth_iface_add_br_prop(&iface_src); + eth_iface_add_vlan_prop(&iface_src, VLAN_TYPE_802_1_Q); + eth_iface_add_br_prop(&iface_dest); + eth_iface_add_vlan_prop(&iface_dest, VLAN_TYPE_802_1_Q); + + + CU_DEBUG("Enter _update_easd_for"); + s = instance_to_easd(broker, preset_parent, + &iface_src, &iface_dest, rasd, &type); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + if (type == EASD_TYPE_EA) { + s = check_piface_for_easd_ea(broker, &iface_src); + if (s.rc != CMPI_RC_OK) { + goto out; + } + CU_DEBUG("easd-EA operation with request type %d," + "iface settings is :", action); + eth_iface_print(&iface_src); + if (action == RESOURCE_ADD) { + ret = add_host_iface(&iface_src); + } else if (action == RESOURCE_MOD) { + ret = mod_host_iface(&iface_src); + } else if (action == RESOURCE_DEL) { + ret = del_host_iface(&iface_src); + } else { + errstr = "requested an unsupported operation."; + CU_DEBUG("%s", errstr); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + } else { + s = check_piface_for_easd_ec(broker, &iface_src, &iface_dest); + if (s.rc != CMPI_RC_OK) { + goto out; + } + CU_DEBUG("easd-EC operation with request type %d," + "iface settings are :", action); + eth_iface_print(&iface_src); + eth_iface_print(&iface_dest); + if (action == RESOURCE_ADD) { + ret = connect_two_ifaces(&iface_src, &iface_dest); + } else if (action == RESOURCE_DEL) { + ret = disconnect_two_ifaces(&iface_src, &iface_dest); + } else { + errstr = "requested an unsupported operation."; + CU_DEBUG("%s", errstr); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + } + + if (ret != 1) { + errstr = get_host_iface_error_reason(ret); + CU_DEBUG("error num %d returned, reason %s.", ret, errstr); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + + out: + eth_iface_uninit(&iface_src); + eth_iface_uninit(&iface_dest); + return s; +} + +static CMPIStatus _update_easd_settings(const CMPIContext *context, + const CMPIObjectPath *ref, + const char *bridge, + CMPIArray *resources, + const CMPIResult *results, + ResourceAction action, + struct inst_list *list) +{ + int i; + CMPIStatus s = {CMPI_RC_OK, NULL}; + int count = 0; + uint32_t rc = CIM_SVPC_RETURN_FAILED; + + CU_DEBUG("Enter _update_easd_settings"); + if (resources == NULL) { + CU_DEBUG("No easd settings."); + goto out; + } + + count = CMGetArrayCount(resources, &s); + if (s.rc != CMPI_RC_OK) { + CU_DEBUG("failed to get array size."); + goto out; + } + + i = 0; + CU_DEBUG("Trying update %d easds.", count); + while (i < count) { + CMPIData item; + CMPIInstance *inst; + item = CMGetArrayElementAt(resources, i, NULL); + inst = item.value.inst; + + s = _update_easd_for(_BROKER, + context, + ref, + bridge, + inst, + action); + if (s.rc != CMPI_RC_OK) { + break; + } + inst_list_add(list, inst); + i++; + } + + out: + if (s.rc == CMPI_RC_OK) { + rc = CIM_SVPC_RETURN_COMPLETED; + } + if ((results != NULL) && (resources != NULL)) { + CMReturnData(results, &rc, CMPI_uint32); + } + + return s; +} + +static CMPIStatus easd_refs_to_insts(const CMPIBroker *broker, + const CMPIContext *ctx, + const CMPIObjectPath *reference, + CMPIArray *arr, + CMPIArray **ret_arr) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIArray *tmp_arr; + int i; + int c; + + c = CMGetArrayCount(arr, &s); + if (s.rc != CMPI_RC_OK) { + return s; + } + + tmp_arr = CMNewArray(broker, + c, + CMPI_instance, + &s); + + for (i = 0; i < c; i++) { + CMPIData d; + CMPIObjectPath *ref; + CMPIInstance *inst = NULL; + const char *id; + + d = CMGetArrayElementAt(arr, i, &s); + ref = d.value.ref; + if (s.rc != CMPI_RC_OK) { + CU_DEBUG("Unable to get ResourceSettings[%i]", i); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "Unable to get ResourceSettings"); + goto out; + } + + if (cu_get_str_path(ref, "InstanceID", &id) != CMPI_RC_OK) { + CU_DEBUG("Unable to get InstanceID of `%s'", + REF2STR(ref)); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "Unable to get InstanceID"); + goto out; + } + + s = get_easd_by_id(broker, id, reference, NULL, &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + CMSetArrayElementAt(tmp_arr, i, + &inst, + CMPI_instance); + + } + + *ret_arr = tmp_arr; + + out: + return s; +} + +static CMPIInstance *create_switch_system(const CMPIContext *context, + CMPIInstance *vsssd, + CMPIArray *resources, + const CMPIObjectPath *ref, + const CMPIObjectPath *refconf, + CMPIStatus *s) +{ + CMPIInstance *inst = NULL; + struct EthIface iface_br; + int ret; + char *errstr; + char *br_name = NULL; + struct inst_list list; + + inst_list_init(&list); + eth_iface_init(&iface_br); + eth_iface_add_br_prop(&iface_br); + + CU_DEBUG("Enter create_switch_system"); + if (refconf != NULL) { + cu_statusf(_BROKER, s, + CMPI_RC_ERR_FAILED, + "creating switch system with" + " reference is not supported now."); + goto out; + } + + *s = instance_to_vesssd(_BROKER, &iface_br, vsssd); + if (s->rc != CMPI_RC_OK) { + cu_statusf(_BROKER, s, + CMPI_RC_ERR_FAILED, + "failed to translate settings."); + goto out; + } + iface_br.eth_type = ETH_TYPE_ETHER_BRIDGE; + CU_DEBUG("Creating Switch System as follow:"); + eth_iface_print(&iface_br); + + ret = add_host_iface(&iface_br); + if (ret != 1) { + errstr = get_host_iface_error_reason(ret); + CU_DEBUG("error num %d returned, reason %s.", ret, errstr); + cu_statusf(_BROKER, s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + + br_name = get_switch_name_from_iface(iface_br.name); + *s = _update_easd_settings(context, + ref, + br_name, + resources, + NULL, + RESOURCE_ADD, + &list); + + + *s = get_switch_by_name(_BROKER, + br_name, + ref, + &inst); + + out: + inst_list_free(&list); + eth_iface_uninit(&iface_br); + free(br_name); + + return inst; +} + +static CMPIStatus update_switchsystem_settings(const CMPIContext *context, + const CMPIObjectPath *ref, + CMPIInstance *vsssd) +{ + CMPIStatus s; + struct EthIface iface_br; + struct EthIfacesList ifaces_list; + int ret; + char *errstr; + + eth_ifaceslist_init(&ifaces_list); + eth_iface_init(&iface_br); + + eth_iface_add_br_prop(&iface_br); + + s = instance_to_vesssd(_BROKER, &iface_br, vsssd); + if (s.rc != CMPI_RC_OK || (iface_br.name == NULL)) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "failed to translate settings."); + goto out; + + } + + CU_DEBUG("update switch settings as following settings:"); + eth_iface_print(&iface_br); + ret = mod_host_iface(&iface_br); + if (ret != 1) { + errstr = get_host_iface_error_reason(ret); + CU_DEBUG("error num %d returned, reason %s.", ret, errstr); + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + + out: + eth_ifaceslist_uninit(&ifaces_list); + eth_iface_uninit(&iface_br); + return s; +} + +static CMPIStatus define_switch_system_parse_args(const CMPIArgs *argsin, + CMPIInstance **sys, + const char *ns, + CMPIArray **res, + CMPIObjectPath **refconf) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + + if (cu_get_inst_arg(argsin, "SystemSettings", sys) != CMPI_RC_OK) { + CU_DEBUG("No SystemSettings string argument"); + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_INVALID_PARAMETER, + "Missing argument `SystemSettings'"); + goto out; + } + + if (cu_get_array_arg(argsin, "ResourceSettings", res) != + CMPI_RC_OK) { + CU_DEBUG("Did not get ResourceSettings arg"); + *res = NULL; + } + + if (cu_get_ref_arg(argsin, "ReferenceConfiguration", refconf) != + CMPI_RC_OK) { + CU_DEBUG("Did not get ReferenceConfiguration arg"); + *refconf = NULL; + } + out: + return s; +} + +static CMPIStatus define_system(CMPIMethodMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference, + const CMPIArgs *argsin, + CMPIArgs *argsout) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *vsssd; + CMPIArray *res; + CMPIObjectPath *refconf; + CMPIInstance *sys = NULL; + CMPIObjectPath *result; + uint32_t rc = CIM_SVPC_RETURN_FAILED; + + CU_DEBUG("DefineSystem"); + + s = define_switch_system_parse_args(argsin, + &vsssd, + NAMESPACE(reference), + &res, + &refconf); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + sys = create_switch_system(context, vsssd, res, reference, refconf, &s); + if (sys == NULL) { + goto out; + } + + result = CMGetObjectPath(sys, &s); + if ((result != NULL) && (s.rc == CMPI_RC_OK)) { + CMSetNameSpace(result, NAMESPACE(reference)); + CMAddArg(argsout, "ResultingSystem", &result, CMPI_ref); + } + + + out: + if (s.rc == CMPI_RC_OK) { + rc = CIM_SVPC_RETURN_COMPLETED; + } + CMReturnData(results, &rc, CMPI_uint32); + + return s; +} + +static CMPIStatus destroy_system(CMPIMethodMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference, + const CMPIArgs *argsin, + CMPIArgs *argsout) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + const char *br_name = NULL; + struct EthIface iface_br; + uint32_t rc = IM_RC_FAILED; + CMPIObjectPath *sys; + int ret; + char *errstr; + + eth_iface_init(&iface_br); + CU_DEBUG("entering destroy switch system."); + + if (cu_get_ref_arg(argsin, "AffectedSystem", &sys) != CMPI_RC_OK) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "AffectedSystem not set"); + goto out; + } + + br_name = get_key_from_ref_arg(argsin, "AffectedSystem", "Name"); + if (br_name == NULL) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Failed get Name of AffectedSystem"); + goto out; + } + + iface_br.name = get_iface_name_from_switch(br_name); + if (iface_br.name == NULL) { + CU_DEBUG("failed to get iface name from %s.", br_name); + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Failed to translate Name of AffectedSystem"); + goto out; + } + + iface_br.eth_type = ETH_TYPE_ETHER_BRIDGE; + CU_DEBUG("Deleting Switch System as follow:"); + eth_iface_print(&iface_br); + + ret = del_host_iface(&iface_br); + if (ret != 1) { + errstr = get_host_iface_error_reason(ret); + CU_DEBUG("error num %d returned, reason %s.", ret, errstr); + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + + rc = IM_RC_OK; + + out: + eth_iface_uninit(&iface_br); + CMReturnData(results, &rc, CMPI_uint32); + return s; +} + + +static CMPIStatus mod_system_settings(CMPIMethodMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference, + const CMPIArgs *argsin, + CMPIArgs *argsout) +{ + CMPIInstance *inst; + CMPIStatus s; + uint32_t rc; + + if (cu_get_inst_arg(argsin, "SystemSettings", &inst) != CMPI_RC_OK) { + + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Missing SystemSettings"); + goto out; + } + + s = update_switchsystem_settings(context, reference, inst); + out: + if (s.rc == CMPI_RC_OK) { + rc = CIM_SVPC_RETURN_COMPLETED; + } else { + rc = CIM_SVPC_RETURN_FAILED; + } + + CMReturnData(results, &rc, CMPI_uint32); + + return s; +} + +static CMPIStatus add_resource_settings(CMPIMethodMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference, + const CMPIArgs *argsin, + CMPIArgs *argsout) +{ + CMPIArray *arr; + CMPIStatus s; + CMPIObjectPath *sys; + char *bridge = NULL; + CMPIArray *res = NULL; + struct inst_list list; + + inst_list_init(&list); + + if (cu_get_array_arg(argsin, "ResourceSettings", &arr) != CMPI_RC_OK) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Missing ResourceSettings"); + return s; + } + + if (cu_get_ref_arg(argsin, + "AffectedConfiguration", + &sys) != CMPI_RC_OK) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_INVALID_PARAMETER, + "Missing AffectedConfiguration parameter"); + return s; + } + + if (!parse_instanceid(sys, NULL, &bridge)) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_INVALID_PARAMETER, + "AffectedConfiguration has invalid InstanceID"); + return s; + } + + s = _update_easd_settings(context, + reference, + bridge, + arr, + results, + RESOURCE_ADD, + &list); + + free(bridge); + + res = set_result_res_vessms(&list, NAMESPACE(reference)); + inst_list_free(&list); + CMAddArg(argsout, "ResultingResourceSettings", &res, CMPI_refA); + + + return s; +} + +static CMPIStatus mod_resource_settings(CMPIMethodMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference, + const CMPIArgs *argsin, + CMPIArgs *argsout) +{ + CMPIArray *arr; + CMPIStatus s; + CMPIArray *res = NULL; + struct inst_list list; + + CU_DEBUG("Enter mod_resource_settings"); + inst_list_init(&list); + + if (cu_get_array_arg(argsin, "ResourceSettings", &arr) != CMPI_RC_OK) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Missing ResourceSettings"); + return s; + } + + s = _update_easd_settings(context, + reference, + NULL, + arr, + results, + RESOURCE_MOD, + &list); + + res = set_result_res_vessms(&list, NAMESPACE(reference)); + CMAddArg(argsout, "ResultingResourceSettings", &res, CMPI_refA); + inst_list_free(&list); + + return s; +} + +static CMPIStatus rm_resource_settings(CMPIMethodMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference, + const CMPIArgs *argsin, + CMPIArgs *argsout) +{ + /* The RemoveResources case is different from either Add or + * Modify, because it takes references instead of instances + */ + + CMPIArray *arr; + CMPIArray *resource_arr = NULL; + CMPIStatus s; + struct inst_list list; + + inst_list_init(&list); + + if (cu_get_array_arg(argsin, "ResourceSettings", &arr) != CMPI_RC_OK) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Missing ResourceSettings"); + goto out; + } + + /* delete is simple, just specify the names */ + s = easd_refs_to_insts(_BROKER, context, reference, arr, + &resource_arr); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + s = _update_easd_settings(context, + reference, + NULL, + resource_arr, + results, + RESOURCE_DEL, + &list); + out: + inst_list_free(&list); + + return s; +} + +static struct method_handler DefineSystem = { + .name = "DefineSystem", + .handler = define_system, + .args = {{"SystemSettings", CMPI_instance, false}, + {"ResourceSettings", CMPI_instanceA, true}, + {"ReferenceConfiguration", CMPI_ref, true}, + ARG_END + } +}; + +static struct method_handler DestroySystem = { + .name = "DestroySystem", + .handler = destroy_system, + .args = {{"AffectedSystem", CMPI_ref, false}, + ARG_END + } +}; + +static struct method_handler AddResourceSettings = { + .name = "AddResourceSettings", + .handler = add_resource_settings, + .args = {{"AffectedConfiguration", CMPI_ref, false}, + {"ResourceSettings", CMPI_instanceA, false}, + ARG_END + } +}; + +static struct method_handler ModifyResourceSettings = { + .name = "ModifyResourceSettings", + .handler = mod_resource_settings, + .args = {{"ResourceSettings", CMPI_instanceA, false}, + ARG_END + } +}; + +static struct method_handler ModifySystemSettings = { + .name = "ModifySystemSettings", + .handler = mod_system_settings, + .args = {{"SystemSettings", CMPI_instance, false}, + ARG_END + } +}; + +static struct method_handler RemoveResourceSettings = { + .name = "RemoveResourceSettings", + .handler = rm_resource_settings, + .args = {{"ResourceSettings", CMPI_refA, false}, + ARG_END + } +}; + +static struct method_handler *my_handlers[] = { + &DefineSystem, + &DestroySystem, + &AddResourceSettings, + &ModifyResourceSettings, + &ModifySystemSettings, + &RemoveResourceSettings, + NULL, +}; + +STDIM_MethodMIStub(, Virt_VirtualEthernetSwitchSystemManagementService, + _BROKER, libvirt_cim_init(), my_handlers); + + +CMPIStatus get_vessms(const CMPIObjectPath *reference, + CMPIInstance **_inst, + const CMPIBroker *broker, + const CMPIContext *context, + bool is_get_inst) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst = NULL; + char host_name[256]; + CMPIArray *array; + uint16_t op_status; + + *_inst = NULL; + + inst = get_typed_instance(broker, + NETWORK_CLASS_PREFIX, + "VirtualEthernetSwitchSystemManagementService", + NAMESPACE(reference)); + + if (inst == NULL) { + CU_DEBUG("Failed to get typed instance"); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "Failed to create instance"); + goto out; + } + + CMSetProperty(inst, "Caption", + (CMPIValue *)"VLAN and VBridge services", CMPI_chars); + + CMSetProperty(inst, "Name", + (CMPIValue *)"Management Service", CMPI_chars); + + if (0 == get_fqdn(host_name, sizeof(host_name))) { + CMSetProperty(inst, "SystemName", + (CMPIValue *)host_name, CMPI_chars); + } + + CMSetProperty(inst, "SystemCreationClassName", + (CMPIValue *)"KVM_HostSystem", CMPI_chars); + + + CMSetProperty(inst, "Revision", + (CMPIValue *)LIBVIRT_CIM_RV, CMPI_chars); + + CMSetProperty(inst, "Release", + (CMPIValue *)PACKAGE_VERSION, CMPI_chars); + + array = CMNewArray(broker, 1, CMPI_uint16, &s); + if ((s.rc != CMPI_RC_OK) || (CMIsNullObject(array))) { + goto out; + } + + op_status = CIM_OPERATIONAL_STATUS; + CMSetArrayElementAt(array, 0, &op_status, CMPI_uint16); + + CMSetProperty(inst, "OperationalStatus", + (CMPIValue *)&array, CMPI_uint16A); + + if (is_get_inst) { + s = cu_validate_ref(broker, reference, inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + } + + cu_statusf(broker, &s, + CMPI_RC_OK, + ""); + out: + *_inst = inst; + + return s; +} + +static CMPIStatus return_vessms(const CMPIContext *context, + const CMPIObjectPath *reference, + const CMPIResult *results, + bool name_only, + bool is_get_inst) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst; + + s = get_vessms(reference, &inst, _BROKER, context, is_get_inst); + if ((s.rc != CMPI_RC_OK) || (inst == NULL)) { + goto out; + } + + if (name_only) { + cu_return_instance_name(results, inst); + } else { + CMReturnInstance(results, inst); + } + out: + return s; +} + +static CMPIStatus EnumInstanceNames(CMPIInstanceMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference) +{ + return return_vessms(context, reference, results, true, false); +} + +static CMPIStatus EnumInstances(CMPIInstanceMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference, + const char **properties) +{ + + return return_vessms(context, reference, results, false, false); +} + +static CMPIStatus GetInstance(CMPIInstanceMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *ref, + const char **properties) +{ + return return_vessms(context, ref, results, false, true); +} + +DEFAULT_CI(); +DEFAULT_MI(); +DEFAULT_DI(); +DEFAULT_EQ(); +DEFAULT_INST_CLEANUP(); + +STD_InstanceMIStub(, + Virt_VirtualEthernetSwitchSystemManagementService, + _BROKER, + libvirt_cim_init()); + + +/* + * Local Variables: + * mode: C + * c-set-style: "K&R" + * tab-width: 8 + * c-basic-offset: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/Virt_VirtualEthernetSwitchSystemManagementService.h b/src/Virt_VirtualEthernetSwitchSystemManagementService.h new file mode 100644 index 0000000..07c0f4e --- /dev/null +++ b/src/Virt_VirtualEthernetSwitchSystemManagementService.h @@ -0,0 +1,31 @@ +/* + * Copyright IBM Corp. 2011 + * + * Authors: + * Wenchao Xia + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef VESSMS_H +#define VESSMS_H + +CMPIStatus get_vessms(const CMPIObjectPath *reference, + CMPIInstance **_inst, + const CMPIBroker *broker, + const CMPIContext *context, + bool is_get_inst); + +#endif diff --git a/src/Virt_VirtualSystemManagementService.c b/src/Virt_VirtualSystemManagementService.c index 6f42c42..761263b 100644 --- a/src/Virt_VirtualSystemManagementService.c +++ b/src/Virt_VirtualSystemManagementService.c @@ -2836,7 +2836,7 @@ static CMPIStatus _update_resources_for(const CMPIContext *context, return s; } -static CMPIStatus get_instanceid(CMPIInstance *rasd, +CMPIStatus get_instanceid(CMPIInstance *rasd, char **domain, char **devid) { diff --git a/src/Virt_VirtualSystemManagementService.h b/src/Virt_VirtualSystemManagementService.h index dbf17cb..d5ee4e4 100644 --- a/src/Virt_VirtualSystemManagementService.h +++ b/src/Virt_VirtualSystemManagementService.h @@ -34,3 +34,7 @@ CMPIStatus get_vsms(const CMPIObjectPath *reference, const CMPIBroker *broker, const CMPIContext *context, bool is_get_inst); + +CMPIStatus get_instanceid(CMPIInstance *rasd, + char **domain, + char **devid); -- 1.7.1 From xiawenc at linux.vnet.ibm.com Tue Feb 14 08:58:05 2012 From: xiawenc at linux.vnet.ibm.com (Wenchao Xia) Date: Tue, 14 Feb 2012 16:58:05 +0800 Subject: [Libvirt-cim] [PATCH V7 6/7] vlan extention - CIM Model - EASD Message-ID: <1329209885-14627-1-git-send-email-xiawenc@linux.vnet.ibm.com> Add EASD for EthernetPort. According DSP1050, There are two kinds of EASD: EA stands for Settings of EthernetPort, EC stands for Settings for Connection between EthernetPort. EA_POOL and EC_POOL are not implemented, the model standard is described with more details in next patch. V7: add CIM properties AutoStart, DHCP. V6: almost the same with V2. Signed-off-by: Wenchao Xia --- schema/EthernetPortAllocationSettingData.mof | 22 + .../EthernetPortAllocationSettingData.registration | 3 + src/Virt_EASD.c | 711 ++++++++++++++++++++ src/Virt_EASD.h | 59 ++ 4 files changed, 795 insertions(+), 0 deletions(-) create mode 100644 schema/EthernetPortAllocationSettingData.mof create mode 100644 schema/EthernetPortAllocationSettingData.registration create mode 100644 src/Virt_EASD.c create mode 100644 src/Virt_EASD.h diff --git a/schema/EthernetPortAllocationSettingData.mof b/schema/EthernetPortAllocationSettingData.mof new file mode 100644 index 0000000..726bb1f --- /dev/null +++ b/schema/EthernetPortAllocationSettingData.mof @@ -0,0 +1,22 @@ +// Copyright IBM Corp. 2012 + +[Description ("Virtutal EthernetPort Setting Data"), + Provider("cmpi::Virt_EASD") +] + +class Net_EthernetPortAllocationSettingData : CIM_EthernetPortAllocationSettingData +{ + uint16 PortVID; + uint16 DesiredEndPointMode; + + [Description("VLAN type of the port, " + "Now only support IEEE 802.1.q."), + ValueMap { "0", "1", "2", "3" }, + Values { "Not VLAN", "IEEE 802.1.q", "IEEE 802.1.qbg", "IEEE 802.1.qbh" }] + uint16 VLANType; + + uint16 AutoStart; + + uint16 DHCP; + +}; diff --git a/schema/EthernetPortAllocationSettingData.registration b/schema/EthernetPortAllocationSettingData.registration new file mode 100644 index 0000000..8925739 --- /dev/null +++ b/schema/EthernetPortAllocationSettingData.registration @@ -0,0 +1,3 @@ +# Copyright IBM Corp. 2012 +# Classname Namespace ProviderName ProviderModule ProviderTypes +Net_EthernetPortAllocationSettingData root/virt Virt_EASD Virt_EASD instance diff --git a/src/Virt_EASD.c b/src/Virt_EASD.c new file mode 100644 index 0000000..81243cd --- /dev/null +++ b/src/Virt_EASD.c @@ -0,0 +1,711 @@ +/* + * Copyright IBM Corp. 2011 + * + * Authors: + * Wenchao Xia + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "misc_util.h" +#include "cs_util.h" +#include "device_parsing.h" +#include "network_model_helper.h" + +#include "Virt_EASD.h" + +static const CMPIBroker *_BROKER; + +static int set_primary_for_easd(const CMPIBroker *broker, const char* prefix, + struct EthIface *piface, int type, CMPIInstance *instance) +{ + char *eth_name, *easd_name; + int asret; + uint16_t res_type = CIM_NUM_SWITCHPORT; + uint16_t vlan_mode; + + if (piface->name == NULL) { + return 0; + } + + eth_name = get_ethportsd_name_from_iface(piface->name, type); + asret = asprintf(&easd_name, "%s/%s", prefix, eth_name); + + CMSetProperty(instance, "InstanceID", + (CMPIValue *)easd_name, CMPI_chars); + CMSetProperty(instance, "ElementName", + (CMPIValue *)eth_name, CMPI_chars); + CU_FREE(easd_name); + CU_FREE(eth_name); + + CMSetProperty(instance, "ResourceType", + (CMPIValue *)&res_type, CMPI_uint16); + + if (piface->eth_type == ETH_TYPE_ETHER_PHYSICAL) { + vlan_mode = CIM_NUM_VLAN_MODE_TRUNK; + CMSetProperty(instance, "DesiredEndPointMode", + (CMPIValue *)&vlan_mode, CMPI_uint16); + } + + + if (piface->mac != NULL) { + CMSetProperty(instance, "Address", + (CMPIValue *)piface->mac, CMPI_chars); + } + + return 1; +} + +static int set_secondary_for_easd(const CMPIBroker *broker, + struct EthIface *piface, CMPIInstance *instance) +{ + struct VLAN_Prop *pvlan; + struct VLAN_Prop_8021q *pvlan8021q; + uint16_t vid, dhcp; + CMPIArray *conn_array; + CMPIString *cm_str; + char *str = NULL; + CMPIStatus s; + uint16_t vlantype = 0; + uint16_t visibility = CIM_NUM_CONSUMERVISIBILITY_VIRTUALIZED; + + if (piface->eth_type == ETH_TYPE_ETHER_PHYSICAL) { + visibility = CIM_NUM_CONSUMERVISIBILITY_PASSEDTHROUGH; + } + CMSetProperty(instance, "ConsumerVisibility", + (CMPIValue *)&visibility, CMPI_uint16); + + if (piface->protocol_prop.ipv4_prop.DHCP == 1) { + dhcp = 1; + } else { + /* dhcp would be -1 because in xml of + in netcf it would never be 0. */ + dhcp = 0; + } + CMSetProperty(instance, "DHCP", (CMPIValue *)&dhcp, CMPI_uint16); + + if (piface->run_prop.boot_mode >= 0) { + CMSetProperty(instance, "AutoStart", + (CMPIValue *)&piface->run_prop.boot_mode, + CMPI_uint16); + } + + if ((piface->eth_type != ETH_TYPE_ETHER_VLAN) || + (piface->pvlan_prop == NULL)) { + goto out; + } + pvlan = piface->pvlan_prop; + + if (pvlan->vlan_type == VLAN_TYPE_802_1_Q) { + pvlan8021q = &(pvlan->props.prop_8021q); + vid = pvlan8021q->vlan_id; + CMSetProperty(instance, "PortVID", + (CMPIValue *)&vid, CMPI_uint16); + + str = vlanid_to_connection_name(vid); + conn_array = CMNewArray(broker, 1, CMPI_string, &s); + if ((s.rc != CMPI_RC_OK) || (str == NULL)) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "Error creating Connection " + "list and its string"); + CU_DEBUG("CMNewArray or string creation failed"); + goto out; + } + cm_str = CMNewString(broker, str, &s); + if (s.rc != CMPI_RC_OK) { + CU_DEBUG("Error creating CMPIString"); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "Error creating CMPIString for " + "BootDevices item"); + + goto out; + } + CMSetArrayElementAt(conn_array, 0, (CMPIValue *)&cm_str, + CMPI_string); + CMSetProperty(instance, "Connection", + (CMPIValue *)&conn_array, CMPI_stringA); + + vlantype = 1; + } + CMSetProperty(instance, "VLANType", + (CMPIValue *)&vlantype, CMPI_uint16); + +out: + CU_FREE(str); + return 1; +} + +static CMPIStatus add_conn_properties(const CMPIBroker *broker, + struct EthIface *piface, + const char *prefix, + const char *dest, + CMPIInstance *instance) +{ + CMPIStatus s = {CMPI_RC_ERR_FAILED, NULL}; + char *eth_name, *easd_name; + int asret; + CMPIArray *array; + CMPIString *tmp; + + if (piface->name == NULL) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "device name not set"); + goto out; + } + if (dest == NULL) { + CU_DEBUG("warn: connection dest is NULL."); + } + + eth_name = get_ethportsd_name_from_iface(piface->name, EASD_TYPE_EA); + asret = asprintf(&easd_name, "%s:%s", prefix, eth_name); + CMSetProperty(instance, "Parent", + (CMPIValue *)easd_name, CMPI_chars); + CU_FREE(easd_name); + CU_FREE(eth_name); + + array = CMNewArray(broker, 1, CMPI_string, &s); + tmp = CMNewString(broker, dest, NULL); + CMSetArrayElementAt(array, 0, &(tmp), CMPI_string); + CMSetProperty(instance, "HostResource", + (CMPIValue *)&array, CMPI_stringA); + + + out: + return s; +} + +static CMPIStatus set_properties(const CMPIBroker *broker, + struct EthIface *piface, + const char *prefix, + const char *dest, + int type, + CMPIInstance *instance) +{ + CMPIStatus s = {CMPI_RC_ERR_FAILED, NULL}; + char *errstr; + + if (!set_primary_for_easd(broker, prefix, piface, type, instance)) { + errstr = "failed to set primary properties for instance."; + CU_DEBUG("%s, iface name %s.", errstr, piface->name); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + + if (type == EASD_TYPE_EA) { + if (!set_secondary_for_easd(broker, piface, instance)) { + errstr = "failed to set secondary properties" + " for instance."; + CU_DEBUG("%s, iface name %s.", errstr, piface->name); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + } else { + s = add_conn_properties(broker, + piface, + prefix, + dest, + instance); + if (s.rc != CMPI_RC_OK) { + goto out; + } + } + + cu_statusf(broker, &s, + CMPI_RC_OK, + ""); + + out: + return s; +} + +static CMPIStatus instance_from_easd_build(const CMPIBroker *broker, + struct EthIface *piface, + const char *prefix, + const char *dest, + int type, + const CMPIObjectPath *reference, + const char **properties, + CMPIInstance **_inst) +{ + CMPIInstance *inst = NULL; + CMPIStatus s = {CMPI_RC_OK, NULL}; + const char *keys[] = {"InstanceID", NULL}; + + inst = get_typed_instance(broker, + NETWORK_CLASS_PREFIX, + "EthernetPortAllocationSettingData", + NAMESPACE(reference)); + if (inst == NULL) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "Unable to init SwitchSystem instance"); + goto out; + } + + + s = CMSetPropertyFilter(inst, properties, keys); + if (s.rc != CMPI_RC_OK) { + CU_DEBUG("Unable to set property filter: %d", s.rc); + } + + s = set_properties(broker, + piface, + prefix, + dest, + type, + inst); + + if (s.rc != CMPI_RC_OK) { + goto out; + } + + *_inst = inst; + + out: + return s; +} + +/* vsname and req_type are filter conditions */ +static CMPIStatus instance_from_easd(const CMPIBroker *broker, + struct EthIface *piface, + const char *vsname, + int req_type, + const CMPIObjectPath *reference, + const char **properties, + struct inst_list *plist) +{ + + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst = NULL; + char *br1_name = NULL, *br2_name = NULL; + + CU_DEBUG("enter instance_for_easd with vsname %s, type %d.", + vsname, req_type); + get_possible_bridge_name_for_cim_model(piface, &br1_name, &br2_name); + if (br1_name == NULL) { + CU_DEBUG("failed to find any bridge for the port %s.", + piface->name); + } + + /* building the EA instance */ + if (!(req_type&EASD_TYPE_EA)) { + goto ea_build_end; + } + if ((vsname == NULL) || (br1_name == NULL) || + (0 == strcmp(vsname, br1_name))) { + inst = NULL; + s = instance_from_easd_build(broker, + piface, + br1_name, + NULL, + EASD_TYPE_EA, + reference, + properties, + &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + inst_list_add(plist, inst); + } + + /* following is to make it comform to CIM profile which require two + ethports connectted to pNIC and vswitch, but we have only one piface + on linux indicating it is connected to pNIC and bridge at sametime */ + if (br2_name == NULL) { + goto out; + } + + if ((vsname == NULL) || (0 == strcmp(vsname, br2_name))) { + inst = NULL; + s = instance_from_easd_build(broker, + piface, + br2_name, + NULL, + EASD_TYPE_EA, + reference, + properties, + &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + inst_list_add(plist, inst); + } + ea_build_end: + + /* building the EC instance */ + if (!(req_type&EASD_TYPE_EC)) { + goto ec_build_end; + } + if ((br1_name == NULL) || (br2_name == NULL)) { + goto ec_build_end; + } + /* connection exist, so a EC_easd should be added for each bridge */ + if ((vsname == NULL) || (0 == strcmp(vsname, br1_name))) { + inst = NULL; + s = instance_from_easd_build(broker, + piface, + br1_name, + br2_name, + EASD_TYPE_EC, + reference, + properties, + &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + inst_list_add(plist, inst); + } + if ((vsname == NULL) || (0 == strcmp(vsname, br2_name))) { + inst = NULL; + s = instance_from_easd_build(broker, + piface, + br2_name, + br1_name, + EASD_TYPE_EC, + reference, + properties, + &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + inst_list_add(plist, inst); + } + ec_build_end: + + out: + CU_FREE(br1_name); + CU_FREE(br2_name); + return s; +} + +CMPIStatus get_easd_by_name(const CMPIBroker *broker, + const char *prefix, + const char *name, + const CMPIObjectPath *reference, + const char **properties, + CMPIInstance **_inst) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst = NULL; + char *eth_name = NULL; + char *dest = NULL; + char *errstr; + int ret; + int type; + struct EthIfacesList ifaces_list; + struct inst_list list; + + eth_ifaceslist_init(&ifaces_list); + inst_list_init(&list); + + eth_name = get_iface_name_from_ethportsd(name, &type); + if (eth_name == NULL) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "failed to convert instance name"); + CU_DEBUG("ethport name %s failed to convert.", name); + goto out; + } + + ret = get_host_ifaces(&ifaces_list, + eth_iface_filter_cim_ethport_for_name, eth_name); + + if (ret != 1) { + errstr = get_host_iface_error_reason(ret); + CU_DEBUG("error num %d returned, reason %s.", ret, errstr); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + if (ifaces_list.count != 1) { + errstr = "expected ethport not found."; + CU_DEBUG("%d ethportd found.", ifaces_list.count); + eth_ifaceslist_print(&ifaces_list); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + + inst = NULL; + s = instance_from_easd(broker, + ifaces_list.pifaces[0], + prefix, + type, + reference, + properties, + &list); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + if (list.cur == 0) { + CU_DEBUG("%d instance found, expect is 1.", list.cur); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "no such instance."); + goto out; + } + + if (list.cur > 1) { + CU_DEBUG("%d instance found, expect is 1.", list.cur); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "instance found do not match expectation"); + goto out; + } + + *_inst = list.list[0]; + list.list[0] = NULL; + + out: + eth_ifaceslist_uninit(&ifaces_list); + inst_list_free(&list); + CU_FREE(eth_name); + CU_FREE(dest); + return s; +} + +CMPIStatus get_easd_by_id(const CMPIBroker *broker, + const char *id, + const CMPIObjectPath *reference, + const char **properties, + CMPIInstance **_inst) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + char *prefix = NULL; + char *suffix = NULL; + if (id == NULL) { + cu_statusf(broker, &s, + CMPI_RC_ERR_INVALID_PARAMETER, + "ID is NULL'", id); + } + if (!parse_fq_devid(id, &prefix, &suffix) || (prefix == NULL) || + (suffix == NULL)) { + cu_statusf(broker, &s, + CMPI_RC_ERR_INVALID_PARAMETER, + "Invalid InstanceID `%s'", id); + goto out; + } + s = get_easd_by_name(broker, prefix, suffix, reference, + properties, _inst); + + out: + CU_FREE(prefix); + CU_FREE(suffix); + return s; +} + +CMPIStatus get_easd_by_ref(const CMPIBroker *broker, + const CMPIObjectPath *reference, + const char **properties, + CMPIInstance **_inst) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst = NULL; + char *name = NULL; + char *prefix = NULL; + const char *id; + + if (cu_get_str_path(reference, "InstanceID", &id) != CMPI_RC_OK) { + cu_statusf(broker, &s, + CMPI_RC_ERR_NOT_FOUND, + "No such instance (InstanceID)"); + goto out; + } + if ((!parse_fq_devid(id, &prefix, &name)) || + (name == NULL) || (prefix == NULL)) { + cu_statusf(broker, &s, + CMPI_RC_ERR_NOT_FOUND, + "Failed to translate (InstanceID)"); + goto out; + } + + s = get_easd_by_name(broker, prefix, name, reference, + properties, &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + s = cu_validate_ref(broker, reference, inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + *_inst = inst; + + out: + free(name); + free(prefix); + + return s; +} + + +CMPIStatus enum_easds(const CMPIBroker *broker, + const char *ref_vsname, + const CMPIObjectPath *reference, + const char **properties, + struct inst_list *plist) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + struct EthIfacesList ifaces_list; + int ret, i; + char *errstr; + + eth_ifaceslist_init(&ifaces_list); + + ret = get_host_ifaces(&ifaces_list, + eth_iface_filter_cim_ethport, NULL); + if (ret != 1) { + errstr = get_host_iface_error_reason(ret); + CU_DEBUG("error num %d returned, reason %s.", ret, errstr); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + CU_DEBUG("enum easd, found following devices.") + eth_ifaceslist_print(&ifaces_list); + + i = 0; + while (i < ifaces_list.count) { + s = instance_from_easd(broker, + ifaces_list.pifaces[i], + ref_vsname, + EASD_TYPE_EA|EASD_TYPE_EC, + reference, + properties, + plist); + i++; + /* this should never fail */ + if (s.rc != CMPI_RC_OK) { + CU_DEBUG("unexpected fail."); + break; + } + } + + + out: + eth_ifaceslist_uninit(&ifaces_list); + + return s; +} + +static CMPIStatus return_enum_easds(const CMPIBroker *broker, + const CMPIObjectPath *reference, + const CMPIResult *results, + const char **properties, + const bool names_only) +{ + struct inst_list list; + CMPIStatus s = {CMPI_RC_OK, NULL}; + inst_list_init(&list); + s = enum_easds(broker, NULL, reference, properties, &list); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + if (names_only) { + cu_return_instance_names(results, &list); + } else { + cu_return_instances(results, &list); + } + + out: + inst_list_free(&list); + return s; +} + +static CMPIStatus EnumInstanceNames(CMPIInstanceMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference) +{ + return return_enum_easds(_BROKER, reference, results, + NULL, true); +} + +static CMPIStatus EnumInstances(CMPIInstanceMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference, + const char **properties) +{ + + return return_enum_easds(_BROKER, reference, results, + properties, false); +} + +static CMPIStatus GetInstance(CMPIInstanceMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *ref, + const char **properties) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst = NULL; + + s = get_easd_by_ref(_BROKER, ref, properties, &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + CMReturnInstance(results, inst); + + out: + return s; +} + +DEFAULT_CI(); +DEFAULT_MI(); +DEFAULT_DI(); +DEFAULT_INST_CLEANUP(); +DEFAULT_EQ(); + +STD_InstanceMIStub(, + Virt_EASD, + _BROKER, + libvirt_cim_init()); + +/* + * Local Variables: + * mode: C + * c-set-style: "K&R" + * tab-width: 8 + * c-basic-offset: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/Virt_EASD.h b/src/Virt_EASD.h new file mode 100644 index 0000000..f9d13ec --- /dev/null +++ b/src/Virt_EASD.h @@ -0,0 +1,59 @@ +/* + * Copyright IBM Corp. 2011 + * + * Authors: + * Wenchao Xia + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __VIRT_EASD_H +#define __VIRT_EASD_H + +CMPIStatus enum_easds(const CMPIBroker *broker, + const char *ref_vsname, + const CMPIObjectPath *reference, + const char **properties, + struct inst_list *plist); + +CMPIStatus get_easd_by_name(const CMPIBroker *broker, + const char *prefix, + const char *name, + const CMPIObjectPath *reference, + const char **properties, + CMPIInstance **_inst); + +CMPIStatus get_easd_by_id(const CMPIBroker *broker, + const char *id, + const CMPIObjectPath *reference, + const char **properties, + CMPIInstance **_inst); + +CMPIStatus get_easd_by_ref(const CMPIBroker *broker, + const CMPIObjectPath *reference, + const char **properties, + CMPIInstance **_inst); + + +#endif + +/* + * Local Variables: + * mode: C + * c-set-style: "K&R" + * tab-width: 8 + * c-basic-offset: 8 + * indent-tabs-mode: nil + * End: + */ -- 1.7.1 From xiawenc at linux.vnet.ibm.com Tue Feb 14 08:59:40 2012 From: xiawenc at linux.vnet.ibm.com (Wenchao Xia) Date: Tue, 14 Feb 2012 16:59:40 +0800 Subject: [Libvirt-cim] [PATCH V2 1/4] cimtest - vlan extention - helper Message-ID: <1329209980-14752-1-git-send-email-xiawenc@linux.vnet.ibm.com> This patch added core functions as test units. Generaly, the test process is: Modify it, Enum it to check the result. All operation were done by libvirt-cim. In adding a network device, it would automatically delete it if it exist, before call libvirt-cim. Signed-off-by: Wenchao Xia --- suites/libvirt-cim/lib/XenKvmLib/host_network.py | 455 ++++++++++++++++++++++ 1 files changed, 455 insertions(+), 0 deletions(-) create mode 100644 suites/libvirt-cim/lib/XenKvmLib/host_network.py diff --git a/suites/libvirt-cim/lib/XenKvmLib/host_network.py b/suites/libvirt-cim/lib/XenKvmLib/host_network.py new file mode 100644 index 0000000..cb17f55 --- /dev/null +++ b/suites/libvirt-cim/lib/XenKvmLib/host_network.py @@ -0,0 +1,455 @@ +#!/usr/bin/env python + +# +# Copyright 2012 IBM Corp. +# +# Authors: +# Wenchao Xia (Wayne) +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +# This file have basic functions for testing of host network in libvirt-cim + + +import sys +import os +import pywbem + +from CimTest.Globals import logger, CIM_USER, CIM_PASS, CIM_NS +from XenKvmLib.classes import get_typed_class +from XenKvmLib.vxml import get_class + +network_clas_prefix = "Net_" +vesssd_parent = "Virt" +vs_prefix = "VS_" +ea_prefix = "EA_" +ec_prefix = "EC_" +delimiter_System = """:""" +delimiter_Device = """/""" + +vess_cls_name = network_clas_prefix + "VirtualEthernetSwitchSystem" +vessms_cls_name = network_clas_prefix + "VirtualEthernetSwitchSystemManagementService" +vesssd_cls_name = network_clas_prefix + "VirtualEthernetSwitchSystemSettingData" +easd_cls_name = network_clas_prefix + "EthernetPortAllocationSettingData" + +vlan_8021q_type = 1 + +bridge_pNIC = "test_br1" +bridge_name = """%s%s""" % (vs_prefix, bridge_pNIC) +bridge_stp = 0 +bridge_delay = 0 +bridge_autostart = 0 +bridge_dhcp = 0 + +bridge_stp_modify = 1 + + +def set_vs_define(inst): + return """ +instance of %s { + VirtualSystemIdentifier="%s"; + STP=%d; + Delay=%d; + AutoStart=%d; + DHCP=%d; +};""" % (vesssd_cls_name, + inst["VirtualSystemIdentifier"], + inst["STP"], + inst["Delay"], + inst["AutoStart"], + inst["DHCP"],) + +def set_vs_modify(inst): + return """ +instance of %s { + VirtualSystemIdentifier="%s"; + STP=%d; +};""" % (vesssd_cls_name, + inst["VirtualSystemIdentifier"], + inst["STP"],) + + +def set_vs_destroy(inst): + inst = pywbem.CIMInstanceName(classname=vess_cls_name, keybindings=pywbem.NocaseDict({'CreationClassName': vess_cls_name, 'Name': inst["Name"]})) + return inst + +def get_vessms(cim): + _class = vessms_cls_name + sys_mgmt_service = cim.EnumerateInstanceNames(_class)[0] + #it is not supposed to fail here, the enum of VESSMS is very simple + logger.info("got vessms as: %s.", sys_mgmt_service) + return sys_mgmt_service + +def get_vess(cim, targetInst, name_only): + _class = vess_cls_name + if name_only == 1: + vess_list = cim.EnumerateInstanceNames(_class) + else : + vess_list = cim.EnumerateInstances(_class) + targetID = targetInst["Name"] + instanceList = "" + for inst in vess_list: + items = inst.items() + instanceList += str(items)+ "\n" + cmp_ret = cmp(inst["Name"], targetInst["Name"]) + if cmp_ret == 0: + logger.info("found the device., it is :\n %s", str(items)) + return inst + return None + +def try_chang_vess_state(cim, targetInst, state): + vess_inst = get_vess(cim, targetInst, 1) + if vess_inst == None : + logger.error("vess %s not found.", targetInst["Name"]) + val = pywbem.cim_types.Uint16(state) + method = "RequestStateChange" + par_name = "RequestedState" + param = {par_name: val} + logger.info("trying method %s of %s with parameter:\n %s", method, vess_inst, param) + ret = cim.InvokeMethod(method, vess_inst, **param) + vess_inst = get_vess(cim, targetInst, 0) + logger.info("result state is %d, requested is %d.", vess_inst["EnabledState"], state) + if vess_inst["EnabledState"] == state : + return 1 + else : + return 0 + +def check_vesssd(cim, targetInst, compareAll = False): + #check the result + _class = vesssd_cls_name + vesssd = cim.EnumerateInstances(_class) + targetID = targetInst["Name"] + instanceList = "" + found = 0 + for inst in vesssd: + items = inst.items() + instanceList += str(items)+ "\n" + (prefix, ID) = inst["InstanceID"].split(":",1) + cmp_ret = cmp(ID, targetID) or cmp(prefix, vesssd_parent) + if cmp_ret == 0: + logger.info("found the device., it is :\n %s", str(items)) + if compareAll == False : + found = 1 + else : + found = 1 + if inst["STP"] != targetInst["STP"]: + found = 0 + if inst["Delay"] != targetInst["Delay"]: + found = 0 + if inst["AutoStart"] != targetInst["AutoStart"]: + found = 0 + if inst["DHCP"] != targetInst["DHCP"]: + found = 0 + #logger.info("search for %s, found is %d, list is: \n%s", _class, found, instanceList) + logger.info("target vesssd searching result is %d.", found) + return found + +def try_delete_vs(cim, sys_mgmt_service, inst): + #delete the bridge + val = set_vs_destroy(inst) + method = "DestroySystem" + par_name = "AffectedSystem" + param = {par_name: val} + logger.info("trying method %s of %s with parameter:\n %s", method, sys_mgmt_service, param) + ret = cim.InvokeMethod(method, sys_mgmt_service, **param) + found = check_vesssd(cim, inst) + if found == 1 : + return 0 + else : + return 1 + +def try_create_vs(cim, sys_mgmt_service, inst): + #Check the Env + found = check_vesssd(cim, inst) + if found == 1: + logger.info("device exist, trying delete it"); + ret = try_delete_vs(cim, sys_mgmt_service, inst) + if ret != 1: + return 0 + + #add the bridge + val = set_vs_define(inst) + method = "DefineSystem" + logger.info("try method %s of %s with parameter %s", method, sys_mgmt_service, val) + ret = cim.InvokeMethod(method, sys_mgmt_service, **{"SystemSettings": val}) + found = check_vesssd(cim, inst) + if found == 1 : + return 1 + else : + return 0 + +def try_modify_vs(cim, sys_mgmt_service, inst): + #modify the bridge + val = set_vs_modify(inst) + method = "ModifySystemSettings" + par_name = "SystemSettings" + param = {par_name: val} + logger.info("trying method %s of %s with parameter:\n %s", method, sys_mgmt_service, param) + ret = cim.InvokeMethod(method, sys_mgmt_service, **param) + found = check_vesssd(cim, inst, True) + if found == 1 : + return 1 + else : + return 0 + + +#inst should be: +#{'Parent': "eth0", 'VLanID':10, 'ReorderHdr':1, 'Ingress':"1:2 2:3", 'Egress':'2:4'} +def set_ea_add_8021q(inst): + ParentSystem = """%s%s""" % (vs_prefix, inst['Parent']) + AffectedID = """%s%s%s""" % (vesssd_parent, delimiter_System, ParentSystem) + AffectedConfiguration = pywbem.CIMInstanceName(classname= vesssd_cls_name, keybindings=pywbem.NocaseDict({'InstanceID': AffectedID})) + EA_ID = """%s%s.%d""" % (ea_prefix, inst['Parent'], inst['VLanID']) + InstanceID_EA = """%s%s%s""" % (ParentSystem, delimiter_Device, EA_ID) + ea1 = """ +instance of %s { + InstanceID ="%s"; + VLANType = %d; + Connection = {"VLAN%d"}; + AutoStart=%d; + DHCP=%d; +};""" % (easd_cls_name, + InstanceID_EA, + vlan_8021q_type, + inst["VLanID"], + inst["AutoStart"], + inst["DHCP"]) + final_param = {"AffectedConfiguration" : AffectedConfiguration, "ResourceSettings" : [ea1,]} + return final_param + +def set_ea_mod_8021q(inst): + ParentSystem = """%s%s""" % (vs_prefix, inst['Parent']) + EA_ID = """%s%s.%d""" % (ea_prefix, inst['Parent'], inst['VLanID']) + InstanceID_EA = """%s%s%s""" % (ParentSystem, delimiter_Device, EA_ID) + ea1 = """ +instance of %s { + InstanceID ="%s"; + VLANType = %d; + Connection = {"VLAN%d"}; + AutoStart=%d; + DHCP=%d; +};""" % (easd_cls_name, + InstanceID_EA, + vlan_8021q_type, + inst["VLanID"], + inst["AutoStart"], + inst["DHCP"]) + final_param = {"ResourceSettings" : [ea1,]} + return final_param + +def set_ea_del_8021q(inst): + ParentSystem = """%s%s""" % (vs_prefix, inst['Parent']) + EA_ID = """%s%s.%d""" % (ea_prefix, inst['Parent'], inst['VLanID']) + InstanceID_EA = """%s%s%s""" % (ParentSystem, delimiter_Device, EA_ID) + del_ref = pywbem.CIMInstanceName(classname= easd_cls_name, keybindings=pywbem.NocaseDict({'InstanceID': InstanceID_EA})) + final_param = {"ResourceSettings" : [del_ref,],} + return final_param + + +def check_easd_ea(cim, targetInst, compareAll = False): + #check the result + _class = easd_cls_name + easds = cim.EnumerateInstances(_class) + + inst = targetInst + ParentSystem = """%s%s""" % (vs_prefix, inst['Parent']) + EA_ID = """%s%s.%d""" % (ea_prefix, inst['Parent'], inst['VLanID']) + InstanceID_EA = """%s%s%s""" % (ParentSystem, delimiter_Device, EA_ID) + vlanstr = """VLAN%d""" % (inst['VLanID']) + + instanceList = "" + found = 0 + for inst in easds: + items = inst.items() + instanceList += str(items)+ "\n" + cmp_ret = cmp(inst["InstanceID"], InstanceID_EA) + if cmp_ret == 0: + logger.info("found the device., it is :\n %s", str(items)) + cmp_ret = cmp(inst["Connection"][0], vlanstr) + if cmp_ret == 0: + found = 1 + else : + found = 0 + if compareAll == False : + pass + else : + if inst["AutoStart"] != targetInst["AutoStart"]: + found = 0 + if inst["DHCP"] != targetInst["DHCP"]: + found = 0 + break + #logger.info("search for %s, found is %d, list is: \n%s", _class, found, instanceList) + logger.info("target easd searching result is %d.", found) + return found + +def try_del_ea(cim, sys_mgmt_service, inst): + param = set_ea_del_8021q(inst) + method = "RemoveResourceSettings" + logger.info("trying method %s of %s with parameter:\n %s", method, sys_mgmt_service, param) + ret = cim.InvokeMethod(method, sys_mgmt_service, **param) + found = check_easd_ea(cim, inst) + if found == 1 : + return 0 + else : + return 1 + +def try_mod_ea(cim, sys_mgmt_service, inst): + param = set_ea_mod_8021q(inst) + method = "ModifyResourceSettings" + logger.info("trying method %s of %s with parameter:\n %s", method, sys_mgmt_service, param) + ret = cim.InvokeMethod(method, sys_mgmt_service, **param) + found = check_easd_ea(cim, inst, True) + if found == 1 : + return 1 + else : + return 0 + + +def try_add_ea(cim, sys_mgmt_service, inst): + #Check the Env + found = check_easd_ea(cim, inst) + if found == 1: + logger.info("device exist, trying delete it"); + ret = try_del_ea(cim, sys_mgmt_service, inst) + if ret != 1: + return 0 + + param = set_ea_add_8021q(inst) + method = "AddResourceSettings" + logger.info("trying method %s of %s with parameter:\n %s", method, sys_mgmt_service, param) + ret = cim.InvokeMethod(method, sys_mgmt_service, **param) + found = check_easd_ea(cim, inst) + if found == 1 : + return 1 + else : + return 0 + + +#inst should be: +#{'ParentBridge': "eth0", 'EthPort':eth0.10, 'TargetBridge': "test_br"} +def set_ec_add(inst): + ParentSystem = """%s%s""" % (vs_prefix, inst['ParentBridge']) + TargetSystem = """%s%s""" % (vs_prefix, inst['TargetBridge']) + AffectedID = """%s%s%s""" % (vesssd_parent, delimiter_System, ParentSystem) + AffectedConfiguration = pywbem.CIMInstanceName(classname= vesssd_cls_name, keybindings=pywbem.NocaseDict({'InstanceID': AffectedID})) + EA_ID = """%s%s""" % (ea_prefix, inst['EthPort']) + EC_ID = """%s%s""" % (ec_prefix, inst['EthPort']) + InstanceID_EA = """%s%s%s""" % (ParentSystem, delimiter_Device, EA_ID) + InstanceID_EC = """%s%s%s""" % (ParentSystem, delimiter_Device, EC_ID) + ea1 = """ +instance of %s { + InstanceID ="%s"; + HostResource = {"%s"}; + Parent = "%s"; +};""" % (easd_cls_name, + InstanceID_EC, + TargetSystem, + InstanceID_EA) + final_param = {"AffectedConfiguration" : AffectedConfiguration, "ResourceSettings" : [ea1,]} + return final_param + +def set_ec_del(inst): + ParentSystem = """%s%s""" % (vs_prefix, inst['ParentBridge']) + EC_ID = """%s%s""" % (ec_prefix, inst['EthPort']) + InstanceID_EC = """%s%s%s""" % (ParentSystem, delimiter_Device, EC_ID) + del_ref = pywbem.CIMInstanceName(classname= easd_cls_name, keybindings=pywbem.NocaseDict({'InstanceID': InstanceID_EC})) + final_param = {"ResourceSettings" : [del_ref,],} + return final_param + +def check_easd_ec(cim, targetInst, compareAll = False): + #check the result + _class = easd_cls_name + easds = cim.EnumerateInstances(_class) + + inst = targetInst + ParentSystem = """%s%s""" % (vs_prefix, inst['ParentBridge']) + TargetSystem = """%s%s""" % (vs_prefix, inst['TargetBridge']) + EC_ID = """%s%s""" % (ec_prefix, inst['EthPort']) + InstanceID_EC0 = """%s%s%s""" % (ParentSystem, delimiter_Device, EC_ID) + InstanceID_EC1 = """%s%s%s""" % (TargetSystem, delimiter_Device, EC_ID) + + instanceList = "" + EC0_found = 0 + EC1_found = 0 + for inst in easds: + items = inst.items() + instanceList += str(items)+ "\n" + cmp_ret = cmp(inst["InstanceID"], InstanceID_EC0) + if cmp_ret == 0: + logger.info("found the ec0., it is :\n %s", str(items)) + EC0_found = 1 + else : + cmp_ret = cmp(inst["InstanceID"], InstanceID_EC1) + if cmp_ret == 0: + logger.info("found the ec1., it is :\n %s", str(items)) + EC1_found = 1 + #logger.info("search for %s, list is: \n%s", _class, instanceList) + found = EC0_found and EC1_found + logger.info("target easd_ec searching result is %d and %d.", EC0_found, EC1_found) + if EC0_found != EC1_found : + logger.info("not all ec found as expected.") + found = -1 + return found + +def try_del_ec(cim, sys_mgmt_service, inst): + param = set_ec_del(inst) + method = "RemoveResourceSettings" + logger.info("trying method %s of %s with parameter:\n %s", method, sys_mgmt_service, param) + ret = cim.InvokeMethod(method, sys_mgmt_service, **param) + found = check_easd_ec(cim, inst) + if found == 0 : + return 1 + else : + return 0 + +def try_add_ec(cim, sys_mgmt_service, inst): + #Check the Env + found = check_easd_ec(cim, inst) + if found != 0: + logger.info("device exist, trying delete it"); + ret = try_del_ec(cim, sys_mgmt_service, inst) + if ret != 1: + return 0 + + param = set_ec_add(inst) + method = "AddResourceSettings" + logger.info("trying method %s of %s with parameter:\n %s", method, sys_mgmt_service, param) + ret = cim.InvokeMethod(method, sys_mgmt_service, **param) + found = check_easd_ec(cim, inst) + if found == 1 : + return 1 + else : + return 0 + +def FoundOnePNIC(cim): + #check the result + _class = vesssd_cls_name + vesssd = cim.EnumerateInstances(_class) + EthList = [] + found = 0 + for inst in vesssd: + (prefix, ID) = inst["InstanceID"].split(":",1) + if ID.find(vs_prefix) == 0 : + realname = ID[len(vs_prefix):] + if realname.find("eth") == 0 and realname.find(".") == -1 : + found = 1 + EthList.append(realname) + #logger.info("search for %s, found is %d, list is: \n%s", _class, found, instanceList) + ret_name = None + if found == 1 : + ret_name = EthList[0] + logger.info("pNIC searching result is %d, list %s, ret is %s.", found, EthList, ret_name) + return ret_name -- 1.7.1 From xiawenc at linux.vnet.ibm.com Tue Feb 14 08:59:55 2012 From: xiawenc at linux.vnet.ibm.com (Wenchao Xia) Date: Tue, 14 Feb 2012 16:59:55 +0800 Subject: [Libvirt-cim] [PATCH V2 2/4] cimtest - vlan extention - bridge Message-ID: <1329209995-14788-1-git-send-email-xiawenc@linux.vnet.ibm.com> This case try add, modify, delete host bridge. Signed-off-by: Wenchao Xia --- .../cimtest/HostNetwork/01_VESSMS_Bridge.py | 78 ++++++++++++++++++++ 1 files changed, 78 insertions(+), 0 deletions(-) create mode 100644 suites/libvirt-cim/cimtest/HostNetwork/01_VESSMS_Bridge.py diff --git a/suites/libvirt-cim/cimtest/HostNetwork/01_VESSMS_Bridge.py b/suites/libvirt-cim/cimtest/HostNetwork/01_VESSMS_Bridge.py new file mode 100644 index 0000000..0d4dd11 --- /dev/null +++ b/suites/libvirt-cim/cimtest/HostNetwork/01_VESSMS_Bridge.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python + +# +# Copyright 2012 IBM Corp. +# +# Authors: +# Wenchao Xia (Wayne) +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +# +# Create ,modify, delete a soft virtual switch system +# +# + +import sys +import os +import pywbem + +from CimTest.ReturnCodes import PASS, FAIL, XFAIL, SKIP +from CimTest.Globals import logger, CIM_USER, CIM_PASS, CIM_NS +from XenKvmLib.const import do_main +from XenKvmLib.classes import get_typed_class +from XenKvmLib.vxml import get_class +from XenKvmLib import host_network + +cim = None +sys_mgmt_service = None +supported = ['KVM',] + + at do_main(supported) +def main(): + options = main.options + server = options.ip + server_url = "http://%s" % server + #get cim + cim = pywbem.WBEMConnection(server_url, (CIM_USER, CIM_PASS), CIM_NS) + + sys_mgmt_service = host_network.get_vessms(cim) + + #add the bridge + inst = {'VirtualSystemIdentifier':host_network.bridge_name, 'Name': host_network.bridge_name, 'STP': host_network.bridge_stp, 'Delay': host_network.bridge_delay, 'DHCP': host_network.bridge_dhcp, 'AutoStart': host_network.bridge_autostart} + + ret = host_network.try_create_vs(cim, sys_mgmt_service, inst) + if ret != 1: + logger.error("Failed to add cim bridge") + return FAIL + + inst["STP"] = host_network.bridge_stp_modify + ret = host_network.try_modify_vs(cim, sys_mgmt_service, inst) + if ret != 1: + logger.error("Failed to modify cim bridge") + return FAIL + + ret = host_network.try_delete_vs(cim, sys_mgmt_service, inst) + if ret != 1: + logger.error("Failed to delete cim bridge") + return FAIL + return PASS + +# main() + +if __name__ == "__main__": + ret = main() + sys.exit(ret) -- 1.7.1 From xiawenc at linux.vnet.ibm.com Tue Feb 14 09:00:13 2012 From: xiawenc at linux.vnet.ibm.com (Wenchao Xia) Date: Tue, 14 Feb 2012 17:00:13 +0800 Subject: [Libvirt-cim] [PATCH V2 3/4] cimtest - vlan extention - vlan 802.1.q Message-ID: <1329210013-14835-1-git-send-email-xiawenc@linux.vnet.ibm.com> This case covers 802.1.q port allocation via EASD-EA. Signed-off-by: Wenchao Xia --- .../cimtest/HostNetwork/02_VESSMS_EASD_EA.py | 83 ++++++++++++++++++++ 1 files changed, 83 insertions(+), 0 deletions(-) create mode 100644 suites/libvirt-cim/cimtest/HostNetwork/02_VESSMS_EASD_EA.py diff --git a/suites/libvirt-cim/cimtest/HostNetwork/02_VESSMS_EASD_EA.py b/suites/libvirt-cim/cimtest/HostNetwork/02_VESSMS_EASD_EA.py new file mode 100644 index 0000000..964e0e0 --- /dev/null +++ b/suites/libvirt-cim/cimtest/HostNetwork/02_VESSMS_EASD_EA.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python + +# +# Copyright 2012 IBM Corp. +# +# Authors: +# Wenchao Xia (Wayne) +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +# +# Create, Modify, Delete IEEE802.1.q child port +# +# + +import sys +import os +import pywbem + +from CimTest.ReturnCodes import PASS, FAIL, XFAIL, SKIP +from CimTest.Globals import logger, CIM_USER, CIM_PASS, CIM_NS +from XenKvmLib.const import do_main +from XenKvmLib.classes import get_typed_class +from XenKvmLib.vxml import get_class +from XenKvmLib import host_network + +cim = None +sys_mgmt_service = None +supported = ['KVM',] + + + at do_main(supported) +def main(): + options = main.options + server = options.ip + server_url = "http://%s" % server + #get cim + cim = pywbem.WBEMConnection(server_url, (CIM_USER, CIM_PASS), CIM_NS) + + sys_mgmt_service = host_network.get_vessms(cim) + pNIC = host_network.FoundOnePNIC(cim) + if pNIC == None : + logger.error("Failed to find any pNIC on the host.") + return XFAIL + + inst = {'Parent': pNIC, 'VLanID':10, 'DHCP': 0, 'AutoStart': 0} + ret = host_network.try_add_ea(cim, sys_mgmt_service, inst) + if ret != 1: + logger.error("Failed to add 802.1.q ea") + return FAIL + + inst['DHCP'] = 1 + inst['AutoStart'] = 1 + ret = host_network.try_mod_ea(cim, sys_mgmt_service, inst) + if ret != 1: + logger.error("Failed to mod 802.1.q ea") + return FAIL + + ret = host_network.try_del_ea(cim, sys_mgmt_service, inst) + if ret != 1: + logger.error("Failed to remove 802.1.q ea") + return FAIL + + return PASS + +# main() + +if __name__ == "__main__": + ret = main() + sys.exit(ret) -- 1.7.1 From xiawenc at linux.vnet.ibm.com Tue Feb 14 09:00:30 2012 From: xiawenc at linux.vnet.ibm.com (Wenchao Xia) Date: Tue, 14 Feb 2012 17:00:30 +0800 Subject: [Libvirt-cim] [PATCH V2 4/4] cimtest - vlan extention - connection Message-ID: <1329210030-14864-1-git-send-email-xiawenc@linux.vnet.ibm.com> This test case trys: define a bridge, create a 802.1.q port, connect the port to the bridge, bring down the bridge, bring up the bridge. This case is very similiar to 802.1.q usage, except that bridge have no DHCP set in this case, for that it need external device support DHCP. Signed-off-by: Wenchao Xia --- .../cimtest/HostNetwork/03_VESSMS_EASD_EC.py | 113 ++++++++++++++++++++ 1 files changed, 113 insertions(+), 0 deletions(-) create mode 100644 suites/libvirt-cim/cimtest/HostNetwork/03_VESSMS_EASD_EC.py diff --git a/suites/libvirt-cim/cimtest/HostNetwork/03_VESSMS_EASD_EC.py b/suites/libvirt-cim/cimtest/HostNetwork/03_VESSMS_EASD_EC.py new file mode 100644 index 0000000..ece07cd --- /dev/null +++ b/suites/libvirt-cim/cimtest/HostNetwork/03_VESSMS_EASD_EC.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python + +# +# Copyright 2012 IBM Corp. +# +# Authors: +# Wenchao Xia (Wayne) +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +# +# try connect two CIM switch by attaching one eth to another bridge +# +# + +import sys +import os +import pywbem + +from CimTest.ReturnCodes import PASS, FAIL, XFAIL, SKIP +from CimTest.Globals import logger, CIM_USER, CIM_PASS, CIM_NS +from XenKvmLib.const import do_main +from XenKvmLib.classes import get_typed_class +from XenKvmLib.vxml import get_class +from XenKvmLib import host_network + +cim = None +sys_mgmt_service = None +supported = ['KVM',] + + + at do_main(supported) +def main(): + options = main.options + server = options.ip + server_url = "http://%s" % server + #get cim + cim = pywbem.WBEMConnection(server_url, (CIM_USER, CIM_PASS), CIM_NS) + + sys_mgmt_service = host_network.get_vessms(cim) + pNIC = host_network.FoundOnePNIC(cim) + if pNIC == None : + logger.error("Failed to find any pNIC on the host.") + return XFAIL + + #add the bridge + inst_br = {'VirtualSystemIdentifier':host_network.bridge_name, 'Name': host_network.bridge_name, 'STP': host_network.bridge_stp, 'Delay': host_network.bridge_delay, 'DHCP': 0, 'AutoStart': host_network.bridge_autostart} + + ret = host_network.try_create_vs(cim, sys_mgmt_service, inst_br) + if ret != 1: + logger.error("Failed to add cim bridge") + return FAIL + + inst_ea = {'Parent': pNIC, 'VLanID':10, 'DHCP': 0, 'AutoStart': 0} + ret = host_network.try_add_ea(cim, sys_mgmt_service, inst_ea) + if ret != 1: + logger.error("Failed to add 802.1.q ea") + return FAIL + + EthPort = """%s.%d""" % (inst_ea["Parent"], inst_ea["VLanID"]) + inst_ec = {'ParentBridge': pNIC, 'EthPort':EthPort, 'TargetBridge': host_network.bridge_pNIC} + ret = host_network.try_add_ec(cim, sys_mgmt_service, inst_ec) + if ret != 1: + logger.error("Failed to add connection") + return FAIL + + #bring down the iface + ret = host_network.try_chang_vess_state(cim, inst_br, 3) + if ret != 1: + logger.error("Failed to bring down these ifaces.") + return FAIL + + #bring up the iface + ret = host_network.try_chang_vess_state(cim, inst_br, 2) + if ret != 1: + logger.error("Failed to bring up these ifaces.") + return FAIL + + ret = host_network.try_del_ec(cim, sys_mgmt_service, inst_ec) + if ret != 1: + logger.error("Failed to add connection") + return FAIL + + ret = host_network.try_del_ea(cim, sys_mgmt_service, inst_ea) + if ret != 1: + logger.error("Failed to remove 802.1.q ea") + return FAIL + + ret = host_network.try_delete_vs(cim, sys_mgmt_service, inst_br) + if ret != 1: + logger.error("Failed to delete cim bridge") + return FAIL + + return PASS + +# main() + +if __name__ == "__main__": + ret = main() + sys.exit(ret) -- 1.7.1 From xiawenc at linux.vnet.ibm.com Tue Feb 14 09:04:46 2012 From: xiawenc at linux.vnet.ibm.com (Wayne Xia) Date: Tue, 14 Feb 2012 17:04:46 +0800 Subject: [Libvirt-cim] [PATCH V6 0/7] vlan extention - git repository In-Reply-To: <4F281ED7.6040600@linux.vnet.ibm.com> References: <1328015847-20342-1-git-send-email-xiaxia347work@163.com> <6637b4e0.12b5c.135343fb164.Coremail.xiaxia347work@163.com> <4F281ED7.6040600@linux.vnet.ibm.com> Message-ID: <4F3A23AE.6090908@linux.vnet.ibm.com> Thanks for the information. I tried to clone my own version on http://gitorious.org/libvirt-cim, it is a bit slow but succeed after several minutes, maybe next time I can use this repository. ? 2012-2-1 1:03, Eduardo Lima (Etrunko) ??: > On 01/31/2012 12:51 PM, xiaxia347work wrote: >> the patch could be get from following url: >> https://gitorious.org/libvirt-cim_develop/libvirt-cim_develop >> >> git repository: >> git://gitorious.org/libvirt-cim_develop/libvirt-cim_develop.git >> branch vlan_v6 > > Just a heads up, it was not necessary to create another project on > gitorious to host your tree. You can create as many clones as you want > on the libvirt-cim project page: > > http://gitorious.org/libvirt-cim > > The idea when I created the project in gitorious was to have a common > place for developers to host their trees with the work in progress, > since write access to libvirt.org repository is restricted to the > maintainers of the project. > > The next step would be to automate the synchronization between > libvirt.org and gitorious trees, the same way is done for libvirt > (http://gitorious.org/libvirt). Nowadays, I am doing this sync manually, > which I think is fine as the 'commit rate' is much lower when compared > to libvirt. > > Best regards, > -- Best Regards Wayne Xia mail:xiawenc at linux.vnet.ibm.com tel:86-010-82450803 From xiawenc at linux.vnet.ibm.com Tue Feb 14 08:57:40 2012 From: xiawenc at linux.vnet.ibm.com (Wenchao Xia) Date: Tue, 14 Feb 2012 16:57:40 +0800 Subject: [Libvirt-cim] [PATCH V7 5/7] vlan extention - CIM Model - EthernetPort Message-ID: <1329209860-14576-1-git-send-email-xiawenc@linux.vnet.ibm.com> This patch add EthernetPort. EthernetPort is always a port on a switch, So eth0.10 is modeled as VS_eth0/EP_eth0.10, and eth0 is modeled as VS_eth0/EP_Eth0. To make things simple enough, EtherPort belongs to VMs, are excluded from the patch and still be modeled as NetworkPort. This means the patch only concern about network on host side. V7: no change. V6: minior change according to comments. V5: almost the same with V2. Signed-off-by: Wenchao Xia --- schema/EthernetPort.mof | 4 + schema/EthernetPort.registration | 3 + src/Virt_EthernetPort.c | 561 ++++++++++++++++++++++++++++++++++++++ src/Virt_EthernetPort.h | 58 ++++ 4 files changed, 626 insertions(+), 0 deletions(-) create mode 100644 schema/EthernetPort.mof create mode 100644 schema/EthernetPort.registration create mode 100644 src/Virt_EthernetPort.c create mode 100644 src/Virt_EthernetPort.h diff --git a/schema/EthernetPort.mof b/schema/EthernetPort.mof new file mode 100644 index 0000000..9d5e23e --- /dev/null +++ b/schema/EthernetPort.mof @@ -0,0 +1,4 @@ +// Copyright IBM Corp. 2012 +class Net_EthernetPort : CIM_EthernetPort +{ +}; diff --git a/schema/EthernetPort.registration b/schema/EthernetPort.registration new file mode 100644 index 0000000..e0e0f0c --- /dev/null +++ b/schema/EthernetPort.registration @@ -0,0 +1,3 @@ +# Copyright IBM Corp. 2012 +# Classname Namespace ProviderName ProviderModule ProviderTypes +Net_EthernetPort root/virt Virt_EthernetPort Virt_EthernetPort instance diff --git a/src/Virt_EthernetPort.c b/src/Virt_EthernetPort.c new file mode 100644 index 0000000..cdef910 --- /dev/null +++ b/src/Virt_EthernetPort.c @@ -0,0 +1,561 @@ +/* + * Copyright IBM Corp. 2007 + * + * Authors: + * Wenchao Xia + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "misc_util.h" +#include "cs_util.h" +#include "device_parsing.h" +#include "network_model_helper.h" + +#include "Virt_EthernetPort.h" + +static const CMPIBroker *_BROKER; + +static int set_primary_for_ep(const CMPIBroker *broker, const char* prefix, + struct EthIface *piface, CMPIInstance *instance) +{ + char *eth_name, *ep_name; + const char *syscls_name = "Virt_VirtualEthernetSwitchSystem"; + int asret; + + if (piface->name == NULL) { + return 0; + } + + eth_name = get_ethport_name_from_iface(piface->name); + asret = asprintf(&ep_name, "%s/%s", prefix, eth_name); + + CMSetProperty(instance, "DeviceID", + (CMPIValue *)ep_name, CMPI_chars); + + CMSetProperty(instance, "InstanceID", + (CMPIValue *)ep_name, CMPI_chars); + + CMSetProperty(instance, "ElementName", + (CMPIValue *)eth_name, CMPI_chars); + CU_FREE(ep_name); + CU_FREE(eth_name); + + CMSetProperty(instance, "SystemCreationClassName", + (CMPIValue *)syscls_name, CMPI_chars); + + CMSetProperty(instance, "SystemName", + (CMPIValue *)prefix, CMPI_chars); + + return 1; +} + +static int set_secondary_for_ep(const CMPIBroker *broker, + struct EthIface *piface, CMPIInstance *instance) +{ + int state; + uint16_t cim_type; + CMPIArray *array; + CMPIStatus s; + CMPIString *str; + + if (piface->run_prop.status == ETH_STATE_INACTIVE) { + state = CIM_STATE_DISABLED; + } else if (piface->run_prop.status == ETH_STATE_ACTIVE) { + state = CIM_STATE_ENABLED; + } else { + state = CIM_STATE_UNKNOWN; + } + CMSetProperty(instance, "EnabledState", + (CMPIValue *)&state, CMPI_uint16); + CMSetProperty(instance, "RequestedState", + (CMPIValue *)&state, CMPI_uint16); + + cim_type = CIM_NUM_NET_ETHERNET; + CMSetProperty(instance, "LinkTechnology", + (CMPIValue *)&cim_type, CMPI_uint16); + + if (piface->mac != NULL) { + array = CMNewArray(broker, 1, CMPI_string, &s); + if ((s.rc != CMPI_RC_OK) || (CMIsNullObject(array))) { + CU_DEBUG("failed to create array."); + return 0; + } + str = CMNewString(broker, piface->mac, &s); + if ((s.rc != CMPI_RC_OK) || (CMIsNullObject(str))) { + CU_DEBUG("failed to create array."); + return 0; + } + + CMSetArrayElementAt(array, 0, &str, CMPI_string); + + CMSetProperty(instance, "NetworkAddresses", + (CMPIValue *)&array, CMPI_stringA); + } + + return 1; +} + +static CMPIStatus set_properties(const CMPIBroker *broker, + struct EthIface *piface, + const char *prefix, + CMPIInstance *instance) +{ + CMPIStatus s = {CMPI_RC_ERR_FAILED, NULL}; + char *errstr = NULL; + + if (!set_primary_for_ep(broker, prefix, piface, instance)) { + errstr = "failed to set primary properties for instance."; + CU_DEBUG("%s, iface name %s.", errstr, piface->name); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + + if (!set_secondary_for_ep(broker, piface, instance)) { + errstr = "failed to set secondary properties for instance."; + CU_DEBUG("%s, iface name %s.", errstr, piface->name); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + + cu_statusf(broker, &s, + CMPI_RC_OK, + ""); + + out: + return s; +} + + +static CMPIStatus instance_from_ep_build(const CMPIBroker *broker, + struct EthIface *piface, + const char *prefix, + const CMPIObjectPath *reference, + const char **properties, + CMPIInstance **_inst) +{ + CMPIInstance *inst = NULL; + CMPIStatus s = {CMPI_RC_OK, NULL}; + const char *keys[] = {"InstanceID", NULL}; + + inst = get_typed_instance(broker, + NETWORK_CLASS_PREFIX, + "EthernetPort", + NAMESPACE(reference)); + if (inst == NULL) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "Unable to init ep instance"); + goto out; + } + + s = CMSetPropertyFilter(inst, properties, keys); + if (s.rc != CMPI_RC_OK) { + CU_DEBUG("Unable to set property filter: %d", s.rc); + } + + s = set_properties(broker, + piface, + prefix, + inst); + + if (s.rc != CMPI_RC_OK) { + goto out; + } + + *_inst = inst; + + out: + return s; +} + + +static CMPIStatus instance_from_ep(const CMPIBroker *broker, + struct EthIface *piface, + const char *vsname, + const CMPIObjectPath *reference, + const char **properties, + struct inst_list *plist) +{ + + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst = NULL; + char *br1_name = NULL, *br2_name = NULL; + + get_possible_bridge_name_for_cim_model(piface, &br1_name, &br2_name); + if (br1_name == NULL) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "failed to find any bridge for the port."); + CU_DEBUG("failed to find any bridge for the port %s.", + piface->name); + goto out; + } + + /* building up the instance */ + if ((vsname == NULL) || (0 == strcmp(vsname, br1_name))) { + inst = NULL; + s = instance_from_ep_build(broker, + piface, + br1_name, + reference, + properties, + &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + inst_list_add(plist, inst); + } + + /* following is to make it comform to CIM profile which require two + ethports connectted to pNIC and vswitch, but we have only one piface + on linux indicating it is connected to pNIC and bridge at sametime */ + if (br2_name == NULL) { + goto out; + } + + if ((vsname == NULL) || (0 == strcmp(vsname, br2_name))) { + inst = NULL; + s = instance_from_ep_build(broker, + piface, + br2_name, + reference, + properties, + &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + inst_list_add(plist, inst); + } + + + out: + CU_FREE(br1_name); + CU_FREE(br2_name); + return s; +} + +CMPIStatus get_ep_by_name(const CMPIBroker *broker, + const char *prefix, + const char *name, + const CMPIObjectPath *reference, + const char **properties, + CMPIInstance **_inst) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst = NULL; + char *eth_name = NULL; + char *dest = NULL; + char *errstr; + int ret; + struct EthIfacesList ifaces_list; + struct inst_list list; + + eth_ifaceslist_init(&ifaces_list); + inst_list_init(&list); + + eth_name = get_iface_name_from_ethport(name); + if (eth_name == NULL) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "failed to convert instance name"); + CU_DEBUG("ethport name %s failed to convert.", name); + goto out; + } + + ret = get_host_ifaces(&ifaces_list, + eth_iface_filter_cim_ethport_for_name, eth_name); + + if (ret != 1) { + errstr = get_host_iface_error_reason(ret); + CU_DEBUG("error num %d returned, reason %s.", ret, errstr); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + if (ifaces_list.count != 1) { + errstr = "expected ethport not found."; + CU_DEBUG("%s\n", errstr); + eth_ifaceslist_print(&ifaces_list); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + + inst = NULL; + s = instance_from_ep(broker, + ifaces_list.pifaces[0], + prefix, + reference, + properties, + &list); + + if (s.rc != CMPI_RC_OK) { + goto out; + } + + if (list.cur == 0) { + CU_DEBUG("%d instance found, expect is 1.", list.cur); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "no such instance."); + goto out; + } + + if (list.cur > 1) { + CU_DEBUG("%d instance found, expect is 1.", list.cur); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "instance found do not match expectation"); + goto out; + } + + *_inst = list.list[0]; + list.list[0] = NULL; + + out: + eth_ifaceslist_uninit(&ifaces_list); + inst_list_free(&list); + CU_FREE(eth_name); + CU_FREE(dest); + return s; +} + +CMPIStatus get_ep_by_id(const CMPIBroker *broker, + const char *id, + const CMPIObjectPath *reference, + const char **properties, + CMPIInstance **_inst) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + char *prefix = NULL; + char *suffix = NULL; + if (id == NULL) { + cu_statusf(broker, &s, + CMPI_RC_ERR_INVALID_PARAMETER, + "ID is NULL'", id); + } + if (!parse_fq_devid(id, &prefix, &suffix) || (prefix == NULL) || + (suffix == NULL)) { + cu_statusf(broker, &s, + CMPI_RC_ERR_INVALID_PARAMETER, + "Invalid InstanceID `%s'", id); + goto out; + } + s = get_ep_by_name(broker, prefix, suffix, reference, + properties, _inst); + + out: + CU_FREE(prefix); + CU_FREE(suffix); + return s; +} + +CMPIStatus get_ep_by_ref(const CMPIBroker *broker, + const CMPIObjectPath *reference, + const char **properties, + CMPIInstance **_inst) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst = NULL; + char *name = NULL; + char *prefix = NULL; + const char *id; + + if (cu_get_str_path(reference, "DeviceID", &id) != CMPI_RC_OK) { + cu_statusf(broker, &s, + CMPI_RC_ERR_NOT_FOUND, + "No such instance (InstanceID)"); + goto out; + } + if ((!parse_fq_devid(id, &prefix, &name)) || + (name == NULL) || (prefix == NULL)) { + cu_statusf(broker, &s, + CMPI_RC_ERR_NOT_FOUND, + "Failed to translate (InstanceID)"); + goto out; + } + + s = get_ep_by_name(broker, prefix, name, reference, + properties, &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + s = cu_validate_ref(broker, reference, inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + *_inst = inst; + + out: + free(name); + free(prefix); + + return s; +} + + +CMPIStatus enum_eps(const CMPIBroker *broker, + const char *ref_vsname, + const CMPIObjectPath *reference, + const char **properties, + struct inst_list *plist) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + struct EthIfacesList ifaces_list; + int ret, i; + char *errstr; + + eth_ifaceslist_init(&ifaces_list); + + ret = get_host_ifaces(&ifaces_list, + eth_iface_filter_cim_ethport, NULL); + if (ret != 1) { + errstr = get_host_iface_error_reason(ret); + CU_DEBUG("error num %d returned, reason %s.", ret, errstr); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + CU_DEBUG("enum ep, found following devices.") + eth_ifaceslist_print(&ifaces_list); + + i = 0; + while (i < ifaces_list.count) { + s = instance_from_ep(broker, + ifaces_list.pifaces[i], + ref_vsname, + reference, + properties, + plist); + i++; + /* this should never fail */ + if (s.rc != CMPI_RC_OK) { + CU_DEBUG("unexpected fail."); + break; + } + } + + + out: + eth_ifaceslist_uninit(&ifaces_list); + + return s; +} + +static CMPIStatus return_enum_eps(const CMPIBroker *broker, + const CMPIObjectPath *reference, + const CMPIResult *results, + const char **properties, + const bool names_only) +{ + struct inst_list list; + CMPIStatus s = {CMPI_RC_OK, NULL}; + inst_list_init(&list); + s = enum_eps(broker, NULL, reference, properties, &list); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + if (names_only) { + cu_return_instance_names(results, &list); + } else { + cu_return_instances(results, &list); + } + + out: + inst_list_free(&list); + return s; +} + +static CMPIStatus EnumInstanceNames(CMPIInstanceMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference) +{ + return return_enum_eps(_BROKER, reference, results, NULL, true); +} + +static CMPIStatus EnumInstances(CMPIInstanceMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference, + const char **properties) +{ + + return return_enum_eps(_BROKER, reference, results, properties, false); +} + +static CMPIStatus GetInstance(CMPIInstanceMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *ref, + const char **properties) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst = NULL; + + s = get_ep_by_ref(_BROKER, ref, properties, &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + CMReturnInstance(results, inst); + + out: + return s; +} + +DEFAULT_CI(); +DEFAULT_MI(); +DEFAULT_DI(); +DEFAULT_INST_CLEANUP(); +DEFAULT_EQ(); + +STD_InstanceMIStub(, + Virt_EthernetPort, + _BROKER, + libvirt_cim_init()); + +/* + * Local Variables: + * mode: C + * c-set-style: "K&R" + * tab-width: 8 + * c-basic-offset: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/Virt_EthernetPort.h b/src/Virt_EthernetPort.h new file mode 100644 index 0000000..f474af2 --- /dev/null +++ b/src/Virt_EthernetPort.h @@ -0,0 +1,58 @@ +/* + * Copyright IBM Corp. 2011 + * + * Authors: + * Wencao Xia + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __VIRT_ETHERNETPORT_H +#define __VIRT_ETHERNETPORT_H + +CMPIStatus enum_eps(const CMPIBroker *broker, + const char *ref_vsname, + const CMPIObjectPath *reference, + const char **properties, + struct inst_list *plist); + +CMPIStatus get_ep_by_name(const CMPIBroker *broker, + const char *prefix, + const char *name, + const CMPIObjectPath *reference, + const char **properties, + CMPIInstance **_inst); + +CMPIStatus get_ep_by_id(const CMPIBroker *broker, + const char *id, + const CMPIObjectPath *reference, + const char **properties, + CMPIInstance **_inst); + +CMPIStatus get_ep_by_ref(const CMPIBroker *broker, + const CMPIObjectPath *reference, + const char **properties, + CMPIInstance **_inst); + +#endif + +/* + * Local Variables: + * mode: C + * c-set-style: "K&R" + * tab-width: 8 + * c-basic-offset: 8 + * indent-tabs-mode: nil + * End: + */ -- 1.7.1 From snmishra at linux.vnet.ibm.com Thu Feb 16 16:36:35 2012 From: snmishra at linux.vnet.ibm.com (Sharad Mishra) Date: Thu, 16 Feb 2012 08:36:35 -0800 Subject: [Libvirt-cim] SELinux support in libvirt-cim Message-ID: <1329410195.25195.1.camel@snmishra-desktop.beaverton.ibm.com> Using my imap account to send this email. Hopefully, it will make it this time. -Sharad > > Hi, > > In order to add support for selinux in libvirt-cim. I created the > following policy - > > > *********************************************** > module mypolicy 1.0; > > require { > type pegasus_var_run_t; > type pegasus_t; > class sock_file write; > class unix_stream_socket connectto; > } > > #============= pegasus_t ============== > allow pegasus_t pegasus_var_run_t:sock_file write; > allow pegasus_t self:unix_stream_socket connectto; > > ***************************************** > > To create this policy - > > 1. Turn on selinux in permissive mode > > # sestatus > SELinux status: enabled > SELinuxfs mount: /selinux > Current mode: permissive > Mode from config file: enforcing > Policy version: 24 > Policy from config file: targeted > > 2. Verified that /var/log/audit/audit.log was empty > > 3. Ran entire cimtest suite > > 4. ran 'audit2allow -M newpolicy < /var/log/audit/audit.log > > I am not familiar with selinux. Is this the right approach? Did I miss > anything? > > Regards, > Sharad Mishra > Open Virtualization > Linux Technology Center > IBM > From eblima at linux.vnet.ibm.com Fri Feb 17 13:53:45 2012 From: eblima at linux.vnet.ibm.com (Eduardo Lima (Etrunko)) Date: Fri, 17 Feb 2012 11:53:45 -0200 Subject: [Libvirt-cim] SELinux support in libvirt-cim In-Reply-To: <1329410195.25195.1.camel@snmishra-desktop.beaverton.ibm.com> References: <1329410195.25195.1.camel@snmishra-desktop.beaverton.ibm.com> Message-ID: <4F3E5BE9.4020904@linux.vnet.ibm.com> On 02/16/2012 02:36 PM, Sharad Mishra wrote: >> >> Hi, >> >> In order to add support for selinux in libvirt-cim. I created the >> following policy - >> >> >> *********************************************** >> module mypolicy 1.0; >> >> require { >> type pegasus_var_run_t; >> type pegasus_t; >> class sock_file write; >> class unix_stream_socket connectto; >> } >> >> #============= pegasus_t ============== >> allow pegasus_t pegasus_var_run_t:sock_file write; >> allow pegasus_t self:unix_stream_socket connectto; >> >> ***************************************** >> >> To create this policy - >> >> 1. Turn on selinux in permissive mode >> >> # sestatus >> SELinux status: enabled >> SELinuxfs mount: /selinux >> Current mode: permissive >> Mode from config file: enforcing >> Policy version: 24 >> Policy from config file: targeted >> >> 2. Verified that /var/log/audit/audit.log was empty >> >> 3. Ran entire cimtest suite >> >> 4. ran 'audit2allow -M newpolicy < /var/log/audit/audit.log >> >> I am not familiar with selinux. Is this the right approach? Did I miss >> anything? >> Hi Sharad, SELinux is indeed something I don't know even how to get it wrong. Sorry. Maybe others can help. Best regards, Eduardo -- Eduardo de Barros Lima Software Engineer, Open Virtualization Linux Technology Center - IBM/Brazil eblima at br.ibm.com From eblima at linux.vnet.ibm.com Mon Feb 20 19:36:04 2012 From: eblima at linux.vnet.ibm.com (Eduardo Lima (Etrunko)) Date: Mon, 20 Feb 2012 17:36:04 -0200 Subject: [Libvirt-cim] [PATCH 2/3] CSI: Cleanup code In-Reply-To: <1329766565-23194-1-git-send-email-eblima@linux.vnet.ibm.com> References: <1329766565-23194-1-git-send-email-eblima@linux.vnet.ibm.com> Message-ID: <1329766565-23194-3-git-send-email-eblima@linux.vnet.ibm.com> From: "Eduardo Lima (Etrunko)" Signed-off-by: Eduardo Lima (Etrunko) --- src/Virt_ComputerSystemIndication.c | 51 +++++++++++++++++------------------ 1 files changed, 25 insertions(+), 26 deletions(-) diff --git a/src/Virt_ComputerSystemIndication.c b/src/Virt_ComputerSystemIndication.c index ab6ffe4..b60138a 100644 --- a/src/Virt_ComputerSystemIndication.c +++ b/src/Virt_ComputerSystemIndication.c @@ -692,36 +692,35 @@ static CMPIStatus ActivateFilter(CMPIIndicationMI* mi, thread = &csi_thread_data[platform]; thread->active_filters += 1; - if (thread->id == 0) { - args = malloc(sizeof(*args)); - if (args == NULL) { - CU_DEBUG("Failed to allocate ind_args"); - cu_statusf(_BROKER, &s, - CMPI_RC_ERR_FAILED, - "Unable to allocate ind_args"); - error = true; - goto out; - } - - args->context = CBPrepareAttachThread(_BROKER, ctx); - if (args->context == NULL) { - CU_DEBUG("Failed to create thread context"); - cu_statusf(_BROKER, &s, - CMPI_RC_ERR_FAILED, - "Unable to create thread context"); - error = true; - goto out; - } + /* Check if thread is already running */ + if (thread->id > 0) + goto out; - args->ns = strdup(NAMESPACE(op)); - args->classname = strdup(CLASSNAME(op)); - args->_ctx = _ctx; + args = malloc(sizeof(*args)); + if (args == NULL) { + CU_DEBUG("Failed to allocate ind_args"); + cu_statusf(_BROKER, &s, CMPI_RC_ERR_FAILED, + "Unable to allocate ind_args"); + error = true; + goto out; + } - thread->args = args; - thread->id = _BROKER->xft->newThread(lifecycle_thread, - thread, 0); + args->context = CBPrepareAttachThread(_BROKER, ctx); + if (args->context == NULL) { + CU_DEBUG("Failed to create thread context"); + cu_statusf(_BROKER, &s, CMPI_RC_ERR_FAILED, + "Unable to create thread context"); + error = true; + goto out; } + args->ns = strdup(NAMESPACE(op)); + args->classname = strdup(CLASSNAME(op)); + args->_ctx = _ctx; + + thread->args = args; + thread->id = _BROKER->xft->newThread(lifecycle_thread, thread, 0); + out: if (error == true) { thread->active_filters -= 1; -- 1.7.7.6 From eblima at linux.vnet.ibm.com Mon Feb 20 19:36:05 2012 From: eblima at linux.vnet.ibm.com (Eduardo Lima (Etrunko)) Date: Mon, 20 Feb 2012 17:36:05 -0200 Subject: [Libvirt-cim] [PATCH 3/3] CSI: Fix log messages In-Reply-To: <1329766565-23194-1-git-send-email-eblima@linux.vnet.ibm.com> References: <1329766565-23194-1-git-send-email-eblima@linux.vnet.ibm.com> Message-ID: <1329766565-23194-4-git-send-email-eblima@linux.vnet.ibm.com> From: "Eduardo Lima (Etrunko)" To produce correct outputs, it is necessary to call CMGetCharPtr(s.msg) instead of using s.msg directly. Signed-off-by: Eduardo Lima (Etrunko) --- src/Virt_ComputerSystemIndication.c | 9 +++++---- 1 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Virt_ComputerSystemIndication.c b/src/Virt_ComputerSystemIndication.c index b60138a..2d0a94e 100644 --- a/src/Virt_ComputerSystemIndication.c +++ b/src/Virt_ComputerSystemIndication.c @@ -254,7 +254,7 @@ static bool _do_indication(const CMPIBroker *broker, ind_op = CMGetObjectPath(ind, &s); if (s.rc != CMPI_RC_OK) { - CU_DEBUG("Failed to get ind_op. Error: '%s'", s.msg); + CU_DEBUG("Failed to get ind_op. Error: '%s'", CMGetCharPtr(s.msg)); ret = false; goto out; } @@ -263,7 +263,7 @@ static bool _do_indication(const CMPIBroker *broker, affected_op = CMGetObjectPath(affected_inst, &s); if (s.rc != CMPI_RC_OK) { ret = false; - CU_DEBUG("problem getting affected_op: '%s'", s.msg); + CU_DEBUG("problem getting affected_op: '%s'", CMGetCharPtr(s.msg)); goto out; } @@ -368,7 +368,8 @@ static bool create_deleted_guest_inst(const char *xml, dominfo, inst); if (s.rc != CMPI_RC_OK) { - CU_DEBUG("instance from domain info error: %s", s.msg); + CU_DEBUG("instance from domain info error: %s", + CMGetCharPtr(s.msg)); goto out; } @@ -476,7 +477,7 @@ static int update_domain_list(virConnectPtr conn, csi_thread_data_t *thread) for (i = 0; i < count; i++) { dom = csi_dom_xml_new(dom_ptr_list[i], &s); if (dom == NULL) { - CU_DEBUG("Failed to get domain info %s", s.msg); + CU_DEBUG("Failed to get domain info %s", CMGetCharPtr(s.msg)); break; } -- 1.7.7.6 From eblima at linux.vnet.ibm.com Mon Feb 20 19:36:03 2012 From: eblima at linux.vnet.ibm.com (Eduardo Lima (Etrunko)) Date: Mon, 20 Feb 2012 17:36:03 -0200 Subject: [Libvirt-cim] [PATCH 1/3] CSI: Only execute callback if indications are enabled In-Reply-To: <1329766565-23194-1-git-send-email-eblima@linux.vnet.ibm.com> References: <1329766565-23194-1-git-send-email-eblima@linux.vnet.ibm.com> Message-ID: <1329766565-23194-2-git-send-email-eblima@linux.vnet.ibm.com> From: "Eduardo Lima (Etrunko)" Signed-off-by: Eduardo Lima (Etrunko) --- src/Virt_ComputerSystemIndication.c | 16 ++++++++++------ 1 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Virt_ComputerSystemIndication.c b/src/Virt_ComputerSystemIndication.c index 712e12c..ab6ffe4 100644 --- a/src/Virt_ComputerSystemIndication.c +++ b/src/Virt_ComputerSystemIndication.c @@ -489,11 +489,11 @@ static int update_domain_list(virConnectPtr conn, csi_thread_data_t *thread) return s.rc; } -static int csi_domain_event_cb(virConnectPtr conn, - virDomainPtr dom, - int event, - int detail, - void *data) +static void csi_domain_event_cb(virConnectPtr conn, + virDomainPtr dom, + int event, + int detail, + void *data) { int cs_event = CS_MODIFIED; csi_thread_data_t *thread = (csi_thread_data_t *) data; @@ -501,6 +501,11 @@ static int csi_domain_event_cb(virConnectPtr conn, char *prefix = class_prefix_name(thread->args->classname); CMPIStatus s = {CMPI_RC_OK, NULL}; + if (lifecycle_enabled == false || thread->active_filters <= 0) { + CU_DEBUG("%s indications deactivated, return"); + return; + } + CU_DEBUG("Event: Domain %s(%d) event: %d detail: %d\n", virDomainGetName(dom), virDomainGetID(dom), event, detail); @@ -557,7 +562,6 @@ static int csi_domain_event_cb(virConnectPtr conn, end: free(prefix); - return 0; } static CMPI_THREAD_RETURN lifecycle_thread(void *params) -- 1.7.7.6 From eblima at linux.vnet.ibm.com Mon Feb 20 19:36:02 2012 From: eblima at linux.vnet.ibm.com (Eduardo Lima (Etrunko)) Date: Mon, 20 Feb 2012 17:36:02 -0200 Subject: [Libvirt-cim] [PATCH 0/3] ComputerSystemIndication: code cleanups Message-ID: <1329766565-23194-1-git-send-email-eblima@linux.vnet.ibm.com> From: "Eduardo Lima (Etrunko)" Simple series of patches that fix some minor issues found in the CSI code. Eduardo Lima (Etrunko) (3): CSI: Only execute callback if indications are enabled CSI: Cleanup code CSI: Fix log messages src/Virt_ComputerSystemIndication.c | 76 ++++++++++++++++++---------------- 1 files changed, 40 insertions(+), 36 deletions(-) -- 1.7.7.6 From eblima at linux.vnet.ibm.com Mon Feb 20 19:43:20 2012 From: eblima at linux.vnet.ibm.com (Eduardo Lima (Etrunko)) Date: Mon, 20 Feb 2012 17:43:20 -0200 Subject: [Libvirt-cim] [PATCH 1/2] VSMigrationService: Move job state definitions to svpc_types.h In-Reply-To: <1329767001-23314-1-git-send-email-eblima@linux.vnet.ibm.com> References: <1329767001-23314-1-git-send-email-eblima@linux.vnet.ibm.com> Message-ID: <1329767001-23314-2-git-send-email-eblima@linux.vnet.ibm.com> From: "Eduardo Lima (Etrunko)" Further job implementations may reuse these values. Signed-off-by: Eduardo Lima (Etrunko) --- src/Virt_VSMigrationService.c | 14 +++++--------- src/svpc_types.h | 13 +++++++++++++ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/Virt_VSMigrationService.c b/src/Virt_VSMigrationService.c index 76e3d25..a6b5fc0 100644 --- a/src/Virt_VSMigrationService.c +++ b/src/Virt_VSMigrationService.c @@ -52,10 +52,6 @@ #include "config.h" -#define CIM_JOBSTATE_STARTING 3 -#define CIM_JOBSTATE_RUNNING 4 -#define CIM_JOBSTATE_COMPLETE 7 - #define MIGRATE_SHUTDOWN_TIMEOUT 120 #define METHOD_RETURN(r, v) do { \ @@ -1289,19 +1285,19 @@ static CMPI_THREAD_RETURN migration_thread(struct migration_job *job) CBAttachThread(_BROKER, job->context); CU_DEBUG("Migration Job %s started", job->uuid); - migrate_job_set_state(job, CIM_JOBSTATE_RUNNING, 0, "Running"); + migrate_job_set_state(job, CIM_JOB_STATE_RUNNING, 0, "Running"); s = migrate_vs(job); CU_DEBUG("Migration Job %s finished: %i", job->uuid, s.rc); if (s.rc != CMPI_RC_OK) migrate_job_set_state(job, - CIM_JOBSTATE_COMPLETE, + CIM_JOB_STATE_COMPLETED, s.rc, CMGetCharPtr(s.msg)); else migrate_job_set_state(job, - CIM_JOBSTATE_COMPLETE, + CIM_JOB_STATE_COMPLETED, 0, "Completed"); @@ -1361,7 +1357,7 @@ static CMPIInstance *_migrate_job_new_instance(const char *cn, } inst = CMNewInstance(_BROKER, op, &s); - if ((s.rc != CMPI_RC_OK) || (CMIsNullObject(op))) { + if ((s.rc != CMPI_RC_OK) || (CMIsNullObject(inst))) { CU_DEBUG("Failed to create instance from ref: %s", CMGetCharPtr(CMObjectPathToString(op, NULL))); return NULL; @@ -1378,7 +1374,7 @@ static CMPIStatus migrate_create_job_instance(const CMPIContext *context, CMPIInstance *jobinst; CMPIDateTime *start; CMPIBoolean autodelete = true; - uint16_t state = CIM_JOBSTATE_STARTING; + uint16_t state = CIM_JOB_STATE_STARTING; char *type = NULL; start = CMNewDateTime(_BROKER, &s); diff --git a/src/svpc_types.h b/src/svpc_types.h index 90bb608..338a7ef 100644 --- a/src/svpc_types.h +++ b/src/svpc_types.h @@ -167,5 +167,18 @@ enum CIM_op_status { CIM_OP_STATUS_POWER_MODE = 18, }; +enum CIM_job_state { + CIM_JOB_STATE_NEW = 2, + CIM_JOB_STATE_STARTING, + CIM_JOB_STATE_RUNNING, + CIM_JOB_STATE_SUSPENDED, + CIM_JOB_STATE_SHUTTING_DOWN, + CIM_JOB_STATE_COMPLETED, + CIM_JOB_STATE_TERMINATED, + CIM_JOB_STATE_KILLED, + CIM_JOB_STATE_EXCEPTION, + CIM_JOB_STATE_SERVICE, + CIM_JOB_STATE_QUERY_PENDING, +}; #endif -- 1.7.7.6 From eblima at linux.vnet.ibm.com Mon Feb 20 19:43:19 2012 From: eblima at linux.vnet.ibm.com (Eduardo Lima (Etrunko)) Date: Mon, 20 Feb 2012 17:43:19 -0200 Subject: [Libvirt-cim] [PATCH 0/2] ComputerSystem: Make reboot/shutdown work as a job Message-ID: <1329767001-23314-1-git-send-email-eblima@linux.vnet.ibm.com> From: "Eduardo Lima (Etrunko)" This code is based on the VSMigrationService for the job creation and on ComputerSystemIndication for the job thread, which will listen for the respective domain event to mark the job as finished. Unfortunately I could not make it work properly. In this case I need a help from more experienced people to help on the debug. The call in line 1318 will fail with status code 100. I am sending a simple python test program as a reply to this email so everyone can reproduce. Eduardo Lima (Etrunko) (2): VSMigrationService: Move job state definitions to svpc_types.h ComputerSystem: Reboot/Shutdown state changes as jobs schema/ComputerSystem.mof | 9 ++ src/Virt_ComputerSystem.c | 300 +++++++++++++++++++++++++++++++++++++++-- src/Virt_VSMigrationService.c | 14 +-- src/svpc_types.h | 13 ++ 4 files changed, 317 insertions(+), 19 deletions(-) -- 1.7.7.6 From eblima at linux.vnet.ibm.com Mon Feb 20 19:43:21 2012 From: eblima at linux.vnet.ibm.com (Eduardo Lima (Etrunko)) Date: Mon, 20 Feb 2012 17:43:21 -0200 Subject: [Libvirt-cim] [PATCH 2/2] ComputerSystem: Reboot/Shutdown state changes as jobs In-Reply-To: <1329767001-23314-1-git-send-email-eblima@linux.vnet.ibm.com> References: <1329767001-23314-1-git-send-email-eblima@linux.vnet.ibm.com> Message-ID: <1329767001-23314-3-git-send-email-eblima@linux.vnet.ibm.com> From: "Eduardo Lima (Etrunko)" For Reboot and Shutdown, th RequestStateChange method returns immediately with return code 0 (successful) even though the state change is still not completed. According to the DMTF specification DSP1052 (Computer System Profile) the RequestStateChange() method should return 0x1000 and a corresponding job reference in the return parameters which can be polled for completion. Signed-off-by: Eduardo Lima (Etrunko) --- schema/ComputerSystem.mof | 9 ++ src/Virt_ComputerSystem.c | 300 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 299 insertions(+), 10 deletions(-) diff --git a/schema/ComputerSystem.mof b/schema/ComputerSystem.mof index 10cb8c4..886c085 100644 --- a/schema/ComputerSystem.mof +++ b/schema/ComputerSystem.mof @@ -1,5 +1,14 @@ // Copyright IBM Corp. 2007 +class Xen_ComputerSystemStateChangeJob : CIM_ConcreteJob { +}; + +class KVM_ComputerSystemStateChangeJob : CIM_ConcreteJob { +}; + +class LXC_ComputerSystemStateChangeJob : CIM_ConcreteJob { +}; + [Description ( "A class derived from CIM_ComputerSystem to represent " "the Xen virtual machines/domains running on the system."), diff --git a/src/Virt_ComputerSystem.c b/src/Virt_ComputerSystem.c index e6c7e55..dee4ef7 100644 --- a/src/Virt_ComputerSystem.c +++ b/src/Virt_ComputerSystem.c @@ -30,23 +30,40 @@ #include #include +#include #include +#include -#include "cs_util.h" #include -#include "misc_util.h" -#include "infostore.h" -#include "device_parsing.h" #include #include #include +#include "cs_util.h" +#include "misc_util.h" +#include "infostore.h" +#include "device_parsing.h" +#include "svpc_types.h" + #include "Virt_ComputerSystem.h" #include "Virt_HostSystem.h" #include "Virt_VirtualSystemSnapshotService.h" + const static CMPIBroker *_BROKER; +typedef struct _state_change_job state_change_job_t; +struct _state_change_job { + char uuid[VIR_UUID_STRING_BUFLEN]; + CMPIContext *context; + CMPIObjectPath *obj_path; + char *dom_name; + uint16_t dom_state; + uint16_t status; /* job status */ +}; + +static bool events_registered = false; + /* Set the "Name" property of an instance from a domain */ static int set_name_from_dom(virDomainPtr dom, CMPIInstance *instance) { @@ -1189,19 +1206,20 @@ static CMPIStatus __state_change(const char *name, s = state_change_enable(dom, &info); else if (state == CIM_STATE_DISABLED) s = state_change_disable(dom, &info); - else if (state == CIM_STATE_SHUTDOWN) - s = state_change_shutdown(dom, &info); else if (state == CIM_STATE_PAUSED) s = state_change_pause(dom, &info); - else if (state == CIM_STATE_REBOOT) - s = state_change_reboot(dom, &info); else if (state == CIM_STATE_RESET) s = state_change_reset(dom, &info); + else if (state == CIM_STATE_SHUTDOWN || state == CIM_STATE_REBOOT) + s.rc = CIM_SVPC_RETURN_JOB_STARTED; else cu_statusf(_BROKER, &s, CMPI_RC_ERR_NOT_SUPPORTED, "State not supported"); + if (s.rc != CMPI_RC_OK || s.rc != CIM_SVPC_RETURN_JOB_STARTED) + goto out; + infostore = infostore_open(dom); if (infostore != NULL) { infostore_set_u64(infostore, "reqstate", (uint64_t)state); @@ -1215,6 +1233,248 @@ static CMPIStatus __state_change(const char *name, return s; } +static CMPIStatus create_state_change_job(const CMPIObjectPath *ref, + const CMPIContext *context, + state_change_job_t **job, + uint16_t state) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *job_inst; + CMPIDateTime *start; + CMPIBoolean autodelete = true; + CMPIObjectPath *obj_path; + uuid_t uuid; + char *type = NULL, *cn = NULL, *ns = NULL; + + start = CMNewDateTime(_BROKER, &s); + if ((s.rc != CMPI_RC_OK) || CMIsNullObject(start)) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Failed to get job start time"); + goto out; + } + + cn = strdup(CLASSNAME(ref)); + type = get_typed_class(cn, "ComputerSystemStateChangeJob"); + + obj_path = CMNewObjectPath(_BROKER, ns, type, &s); + if ((s.rc != CMPI_RC_OK) || (CMIsNullObject(obj_path))) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Failed to get new object path"); + goto out; + } + + job_inst = CMNewInstance(_BROKER, obj_path, &s); + if ((s.rc != CMPI_RC_OK) || (CMIsNullObject(job_inst))) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Failed to get new instance object"); + goto out; + } + + /* Alloc job struct */ + *job = calloc(1, sizeof(**job)); + if (*job == NULL) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Failed to allocate memory for job structure"); + goto out; + } + + (*job)->dom_state = state; + (*job)->status = CIM_JOB_STATE_STARTING; + + uuid_generate(uuid); + uuid_unparse(uuid, (*job)->uuid); + + /* Set Properties */ + CMSetProperty(job_inst, "InstanceID", + (CMPIValue *)(*job)->uuid, CMPI_chars); + CMSetProperty(job_inst, "Name", + (CMPIValue *) "ComputerSystemStateChange", CMPI_chars); + CMSetProperty(job_inst, "StartTime", + (CMPIValue *)&start, CMPI_dateTime); + CMSetProperty(job_inst, "JobState", + (CMPIValue *)&((*job)->status), CMPI_uint16); + CMSetProperty(job_inst, "Status", + (CMPIValue *) "Starting", CMPI_chars); + CMSetProperty(job_inst, "DeleteOnCompletion", + (CMPIValue *)&autodelete, CMPI_boolean); + + obj_path = CMGetObjectPath(job_inst, &s); + if ((obj_path == NULL) || (s.rc != CMPI_RC_OK)) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Failed to get path for ComputerSystemStateChangeJob instance"); + goto out; + } + + CMSetNameSpace(obj_path, ns); + + CU_DEBUG("Creating ComputerSystemStateChangeJob instance: %s", + CMGetCharPtr(CMObjectPathToString(obj_path, NULL))); + + obj_path = CBCreateInstance(_BROKER, context, obj_path, job_inst, &s); + if ((s.rc != CMPI_RC_OK) || (CMIsNullObject(obj_path))) { + CU_DEBUG("Failed to create ComputerSystemStateChangeJob instance: %i", s.rc); + goto out; + } + + ns = strdup(NAMESPACE(ref)); + CMSetNameSpace(obj_path, ns); + + (*job)->obj_path = obj_path; + (*job)->context = CBPrepareAttachThread(_BROKER, context); + + out: + free(type); + free(cn); + free(ns); + return s; +} + +static void state_change_reboot_cb(virConnectPtr conn, + virDomainPtr dom, + void *data) +{ + state_change_job_t *job = (state_change_job_t *) data; + job->status = CIM_JOB_STATE_COMPLETED; +} + +static void state_change_shutdown_cb(virConnectPtr conn, + virDomainPtr dom, + int event, + int detail, + void *data) +{ + state_change_job_t *job = (state_change_job_t *) data; + if (event == VIR_DOMAIN_EVENT_SHUTDOWN) + job->status = CIM_JOB_STATE_COMPLETED; +} + +static CMPI_THREAD_RETURN state_change_thread(void *data) +{ + CMPIStatus s; + CMPIInstance *inst = NULL; + state_change_job_t *job = (state_change_job_t *) data; + virConnectPtr conn = NULL; + virDomainPtr dom = NULL; + virDomainInfo info; + int job_cb = -1; + + /* Set job state */ + CBAttachThread(_BROKER, job->context); + CU_DEBUG("State change job %s started", job->uuid); + job->status = CIM_JOB_STATE_RUNNING; + + inst = CBGetInstance(_BROKER, job->context, job->obj_path, NULL, &s); + if ((inst == NULL) || (s.rc != CMPI_RC_OK)) { + CU_DEBUG("Failed to get job instance (%i)", s.rc); + return NULL; + } + + CMSetProperty(inst, "JobState", + (CMPIValue *)&(job->status), CMPI_uint16); + CMSetProperty(inst, "Status", + (CMPIValue *) "Running", CMPI_chars); + + /* Connect to domain event callback */ + conn = connect_by_classname(_BROKER, CLASSNAME(job->obj_path), &s); + if (conn == NULL) { + CU_DEBUG("Unable to connect to '%s' hypervisor", + CLASSNAME(job->obj_path)); + goto out; + } + + dom = virDomainLookupByName(conn, job->dom_name); + if (dom == NULL) { + CU_DEBUG("Unable to get domain '%s'", job->dom_name); + goto out; + } + + if (virDomainGetInfo(dom, &info) != 0) { + CU_DEBUG("Unable to get domain info for '%s'", job->dom_name); + goto out; + } + + if (events_registered == false) { + events_registered = true; + virEventRegisterDefaultImpl(); + } + + if (job->dom_state == CIM_STATE_REBOOT) { + job_cb = virConnectDomainEventRegisterAny(conn, NULL, + VIR_DOMAIN_EVENT_ID_REBOOT, + VIR_DOMAIN_EVENT_CALLBACK(state_change_reboot_cb), + job, NULL); + + if (job_cb == -1) { + CU_DEBUG("Unable to connect domain reboot callback"); + goto out; + } + + s = state_change_reboot(dom, &info); + + if (s.rc != CMPI_RC_OK) { + CU_DEBUG("Unable to trigger domain reboot: '%s'", + CMGetCharPtr(s.msg)); + goto out; + } + } else if (job->dom_state == CIM_STATE_SHUTDOWN) { + job_cb = virConnectDomainEventRegisterAny(conn, NULL, + VIR_DOMAIN_EVENT_ID_REBOOT, + VIR_DOMAIN_EVENT_CALLBACK(state_change_shutdown_cb), + job, NULL); + + if (job_cb == -1) { + CU_DEBUG("Unable to connect domain shutdown callback"); + goto out; + } + + s = state_change_shutdown(dom, &info); + + if (s.rc != CMPI_RC_OK) { + CU_DEBUG("Unable to trigger domain shutdown: '%s'", + CMGetCharPtr(s.msg)); + goto out; + } + } else { + CU_DEBUG("Unrecognized state '%d'", job->dom_state); + goto out; + } + + /* Wait for operation (shutdown/reboot) to complete */ + while (job->status == CIM_JOB_STATE_RUNNING) { + if (virEventRunDefaultImpl() < 0) { + virErrorPtr err = virGetLastError(); + CU_DEBUG("Failed to run event loop: %s\n", + err && err->message ? err->message : "Unknown error"); + } + } + + CU_DEBUG("Job completed"); + + /* Set job state */ + if (job->status == CIM_JOB_STATE_COMPLETED) { + CMSetProperty(inst, "JobState", + (CMPIValue *)&(job->status), CMPI_uint16); + CMSetProperty(inst, "Status", + (CMPIValue *) "Completed", CMPI_chars); + } + + virConnectDomainEventDeregisterAny(conn, job_cb); + + out: + virDomainFree(dom); + virConnectClose(conn); + + CBDetachThread(_BROKER, job->context); + free(job->dom_name); + free(job); + return NULL; +} + static CMPIStatus state_change(CMPIMethodMI *self, const CMPIContext *context, const CMPIResult *results, @@ -1244,7 +1504,8 @@ static CMPIStatus state_change(CMPIMethodMI *self, goto out; } - /* Retain original instance of the guest to use for the PreviousInstance attribute when generating an indication. */ + /* Retain original instance of the guest to use for the PreviousInstance + attribute when generating an indication. */ s = get_domain_by_name(_BROKER, reference, name, &prev_inst); if (s.rc != CMPI_RC_OK || prev_inst == NULL) { cu_statusf(_BROKER, &s, @@ -1256,8 +1517,27 @@ static CMPIStatus state_change(CMPIMethodMI *self, s = __state_change(name, state, reference); - if (s.rc == CMPI_RC_OK) + if (s.rc == CMPI_RC_OK) { rc = 0; + goto out; + } + + if (s.rc == CIM_SVPC_RETURN_JOB_STARTED) { + state_change_job_t *job = NULL; + s = create_state_change_job(reference, context, &job, state); + if (s.rc != CMPI_RC_OK) { + free(job); + goto out; + } + + job->dom_name = strdup(name); + + _BROKER->xft->newThread(state_change_thread, job, 0); + + CMAddArg(argsout, "Job", (CMPIValue *)&(job->obj_path), + CMPI_ref); + rc = s.rc; + } out: CMReturnData(results, &rc, CMPI_uint32); -- 1.7.7.6 From eblima at linux.vnet.ibm.com Mon Feb 20 19:51:39 2012 From: eblima at linux.vnet.ibm.com (Eduardo Lima (Etrunko)) Date: Mon, 20 Feb 2012 17:51:39 -0200 Subject: [Libvirt-cim] [PATCH 0/2] ComputerSystem: Make reboot/shutdown work as a job In-Reply-To: <1329767001-23314-1-git-send-email-eblima@linux.vnet.ibm.com> References: <1329767001-23314-1-git-send-email-eblima@linux.vnet.ibm.com> Message-ID: <4F42A44B.9080406@linux.vnet.ibm.com> On 02/20/2012 05:43 PM, Eduardo Lima (Etrunko) wrote: > From: "Eduardo Lima (Etrunko)" > > This code is based on the VSMigrationService for the job creation and on > ComputerSystemIndication for the job thread, which will listen for the > respective domain event to mark the job as finished. > > Unfortunately I could not make it work properly. In this case I need a help > from more experienced people to help on the debug. The call in line 1318 will > fail with status code 100. I am sending a simple python test program as a > reply to this email so everyone can reproduce. > Please find the test case attached. Best regards, Etrunko -- Eduardo de Barros Lima Software Engineer, Open Virtualization Linux Technology Center - IBM/Brazil eblima at br.ibm.com -------------- next part -------------- A non-text attachment was scrubbed... Name: state_change.py Type: text/x-python Size: 1051 bytes Desc: not available URL: From cvincent at linux.vnet.ibm.com Wed Feb 22 15:33:59 2012 From: cvincent at linux.vnet.ibm.com (Chip Vincent) Date: Wed, 22 Feb 2012 10:33:59 -0500 Subject: [Libvirt-cim] [PATCH 1/3] CSI: Only execute callback if indications are enabled In-Reply-To: <1329766565-23194-2-git-send-email-eblima@linux.vnet.ibm.com> References: <1329766565-23194-1-git-send-email-eblima@linux.vnet.ibm.com> <1329766565-23194-2-git-send-email-eblima@linux.vnet.ibm.com> Message-ID: <4F450AE7.3060006@linux.vnet.ibm.com> +1. On RHEL 6.2 (libvirt-0.9.4) I was able to run all cimtests without seeing a core, but my local indication tests still do not work properly. It's a configuration issue I need to resolve. I always see the following: ComputerSystemIndication - 01_created_indication.py: FAIL ERROR - Waited too long for define indication ERROR - Exception: Poll for indication Failed ERROR - Waited too long for start indication ERROR - Exception: Poll for indication Failed ERROR - Waited too long for destroy indication ERROR - Exception: Poll for indication Failed Sharad: Can you give this patchset a try and see if it resolves the problem you were seeing? On 02/20/2012 02:36 PM, Eduardo Lima (Etrunko) wrote: > From: "Eduardo Lima (Etrunko)" > > Signed-off-by: Eduardo Lima (Etrunko) > --- > src/Virt_ComputerSystemIndication.c | 16 ++++++++++------ > 1 files changed, 10 insertions(+), 6 deletions(-) > > diff --git a/src/Virt_ComputerSystemIndication.c b/src/Virt_ComputerSystemIndication.c > index 712e12c..ab6ffe4 100644 > --- a/src/Virt_ComputerSystemIndication.c > +++ b/src/Virt_ComputerSystemIndication.c > @@ -489,11 +489,11 @@ static int update_domain_list(virConnectPtr conn, csi_thread_data_t *thread) > return s.rc; > } > > -static int csi_domain_event_cb(virConnectPtr conn, > - virDomainPtr dom, > - int event, > - int detail, > - void *data) > +static void csi_domain_event_cb(virConnectPtr conn, > + virDomainPtr dom, > + int event, > + int detail, > + void *data) > { > int cs_event = CS_MODIFIED; > csi_thread_data_t *thread = (csi_thread_data_t *) data; > @@ -501,6 +501,11 @@ static int csi_domain_event_cb(virConnectPtr conn, > char *prefix = class_prefix_name(thread->args->classname); > CMPIStatus s = {CMPI_RC_OK, NULL}; > > + if (lifecycle_enabled == false || thread->active_filters<= 0) { > + CU_DEBUG("%s indications deactivated, return"); > + return; > + } > + > CU_DEBUG("Event: Domain %s(%d) event: %d detail: %d\n", > virDomainGetName(dom), virDomainGetID(dom), event, detail); > > @@ -557,7 +562,6 @@ static int csi_domain_event_cb(virConnectPtr conn, > > end: > free(prefix); > - return 0; > } > > static CMPI_THREAD_RETURN lifecycle_thread(void *params) -- Chip Vincent Open Virtualization IBM Linux Technology Center cvincent at linux.vnet.ibm.com From cvincent at linux.vnet.ibm.com Wed Feb 22 15:34:10 2012 From: cvincent at linux.vnet.ibm.com (Chip Vincent) Date: Wed, 22 Feb 2012 10:34:10 -0500 Subject: [Libvirt-cim] [PATCH 2/3] CSI: Cleanup code In-Reply-To: <1329766565-23194-3-git-send-email-eblima@linux.vnet.ibm.com> References: <1329766565-23194-1-git-send-email-eblima@linux.vnet.ibm.com> <1329766565-23194-3-git-send-email-eblima@linux.vnet.ibm.com> Message-ID: <4F450AF2.3070506@linux.vnet.ibm.com> +1 On 02/20/2012 02:36 PM, Eduardo Lima (Etrunko) wrote: > From: "Eduardo Lima (Etrunko)" > > Signed-off-by: Eduardo Lima (Etrunko) > --- > src/Virt_ComputerSystemIndication.c | 51 +++++++++++++++++------------------ > 1 files changed, 25 insertions(+), 26 deletions(-) > > diff --git a/src/Virt_ComputerSystemIndication.c b/src/Virt_ComputerSystemIndication.c > index ab6ffe4..b60138a 100644 > --- a/src/Virt_ComputerSystemIndication.c > +++ b/src/Virt_ComputerSystemIndication.c > @@ -692,36 +692,35 @@ static CMPIStatus ActivateFilter(CMPIIndicationMI* mi, > thread =&csi_thread_data[platform]; > thread->active_filters += 1; > > - if (thread->id == 0) { > - args = malloc(sizeof(*args)); > - if (args == NULL) { > - CU_DEBUG("Failed to allocate ind_args"); > - cu_statusf(_BROKER,&s, > - CMPI_RC_ERR_FAILED, > - "Unable to allocate ind_args"); > - error = true; > - goto out; > - } > - > - args->context = CBPrepareAttachThread(_BROKER, ctx); > - if (args->context == NULL) { > - CU_DEBUG("Failed to create thread context"); > - cu_statusf(_BROKER,&s, > - CMPI_RC_ERR_FAILED, > - "Unable to create thread context"); > - error = true; > - goto out; > - } > + /* Check if thread is already running */ > + if (thread->id> 0) > + goto out; > > - args->ns = strdup(NAMESPACE(op)); > - args->classname = strdup(CLASSNAME(op)); > - args->_ctx = _ctx; > + args = malloc(sizeof(*args)); > + if (args == NULL) { > + CU_DEBUG("Failed to allocate ind_args"); > + cu_statusf(_BROKER,&s, CMPI_RC_ERR_FAILED, > + "Unable to allocate ind_args"); > + error = true; > + goto out; > + } > > - thread->args = args; > - thread->id = _BROKER->xft->newThread(lifecycle_thread, > - thread, 0); > + args->context = CBPrepareAttachThread(_BROKER, ctx); > + if (args->context == NULL) { > + CU_DEBUG("Failed to create thread context"); > + cu_statusf(_BROKER,&s, CMPI_RC_ERR_FAILED, > + "Unable to create thread context"); > + error = true; > + goto out; > } > > + args->ns = strdup(NAMESPACE(op)); > + args->classname = strdup(CLASSNAME(op)); > + args->_ctx = _ctx; > + > + thread->args = args; > + thread->id = _BROKER->xft->newThread(lifecycle_thread, thread, 0); > + > out: > if (error == true) { > thread->active_filters -= 1; -- Chip Vincent Open Virtualization IBM Linux Technology Center cvincent at linux.vnet.ibm.com From cvincent at linux.vnet.ibm.com Wed Feb 22 15:34:23 2012 From: cvincent at linux.vnet.ibm.com (Chip Vincent) Date: Wed, 22 Feb 2012 10:34:23 -0500 Subject: [Libvirt-cim] [PATCH 3/3] CSI: Fix log messages In-Reply-To: <1329766565-23194-4-git-send-email-eblima@linux.vnet.ibm.com> References: <1329766565-23194-1-git-send-email-eblima@linux.vnet.ibm.com> <1329766565-23194-4-git-send-email-eblima@linux.vnet.ibm.com> Message-ID: <4F450AFF.8040801@linux.vnet.ibm.com> +1 On 02/20/2012 02:36 PM, Eduardo Lima (Etrunko) wrote: > From: "Eduardo Lima (Etrunko)" > > To produce correct outputs, it is necessary to call CMGetCharPtr(s.msg) instead > of using s.msg directly. > > Signed-off-by: Eduardo Lima (Etrunko) > --- > src/Virt_ComputerSystemIndication.c | 9 +++++---- > 1 files changed, 5 insertions(+), 4 deletions(-) > > diff --git a/src/Virt_ComputerSystemIndication.c b/src/Virt_ComputerSystemIndication.c > index b60138a..2d0a94e 100644 > --- a/src/Virt_ComputerSystemIndication.c > +++ b/src/Virt_ComputerSystemIndication.c > @@ -254,7 +254,7 @@ static bool _do_indication(const CMPIBroker *broker, > > ind_op = CMGetObjectPath(ind,&s); > if (s.rc != CMPI_RC_OK) { > - CU_DEBUG("Failed to get ind_op. Error: '%s'", s.msg); > + CU_DEBUG("Failed to get ind_op. Error: '%s'", CMGetCharPtr(s.msg)); > ret = false; > goto out; > } > @@ -263,7 +263,7 @@ static bool _do_indication(const CMPIBroker *broker, > affected_op = CMGetObjectPath(affected_inst,&s); > if (s.rc != CMPI_RC_OK) { > ret = false; > - CU_DEBUG("problem getting affected_op: '%s'", s.msg); > + CU_DEBUG("problem getting affected_op: '%s'", CMGetCharPtr(s.msg)); > goto out; > } > > @@ -368,7 +368,8 @@ static bool create_deleted_guest_inst(const char *xml, > dominfo, > inst); > if (s.rc != CMPI_RC_OK) { > - CU_DEBUG("instance from domain info error: %s", s.msg); > + CU_DEBUG("instance from domain info error: %s", > + CMGetCharPtr(s.msg)); > goto out; > } > > @@ -476,7 +477,7 @@ static int update_domain_list(virConnectPtr conn, csi_thread_data_t *thread) > for (i = 0; i< count; i++) { > dom = csi_dom_xml_new(dom_ptr_list[i],&s); > if (dom == NULL) { > - CU_DEBUG("Failed to get domain info %s", s.msg); > + CU_DEBUG("Failed to get domain info %s", CMGetCharPtr(s.msg)); > break; > } > -- Chip Vincent Open Virtualization IBM Linux Technology Center cvincent at linux.vnet.ibm.com From eblima at linux.vnet.ibm.com Thu Feb 23 13:29:19 2012 From: eblima at linux.vnet.ibm.com (Eduardo Lima (Etrunko)) Date: Thu, 23 Feb 2012 11:29:19 -0200 Subject: [Libvirt-cim] [PATCH 2/2] ComputerSystem: Reboot/Shutdown state changes as jobs In-Reply-To: <1329767001-23314-3-git-send-email-eblima@linux.vnet.ibm.com> References: <1329767001-23314-1-git-send-email-eblima@linux.vnet.ibm.com> <1329767001-23314-3-git-send-email-eblima@linux.vnet.ibm.com> Message-ID: <4F463F2F.2070601@linux.vnet.ibm.com> On 02/20/2012 05:43 PM, Eduardo Lima (Etrunko) wrote: > From: "Eduardo Lima (Etrunko)" > > For Reboot and Shutdown, th RequestStateChange method returns immediately with > return code 0 (successful) even though the state change is still not completed. > > According to the DMTF specification DSP1052 (Computer System Profile) the > RequestStateChange() method should return 0x1000 and a corresponding job > reference in the return parameters which can be polled for completion. > > Signed-off-by: Eduardo Lima (Etrunko) > --- > schema/ComputerSystem.mof | 9 ++ > src/Virt_ComputerSystem.c | 300 +++++++++++++++++++++++++++++++++++++++++++-- > 2 files changed, 299 insertions(+), 10 deletions(-) > > diff --git a/schema/ComputerSystem.mof b/schema/ComputerSystem.mof > index 10cb8c4..886c085 100644 > --- a/schema/ComputerSystem.mof > +++ b/schema/ComputerSystem.mof > @@ -1,5 +1,14 @@ > // Copyright IBM Corp. 2007 > > +class Xen_ComputerSystemStateChangeJob : CIM_ConcreteJob { > +}; > + > +class KVM_ComputerSystemStateChangeJob : CIM_ConcreteJob { > +}; > + > +class LXC_ComputerSystemStateChangeJob : CIM_ConcreteJob { > +}; > + > [Description ( > "A class derived from CIM_ComputerSystem to represent " > "the Xen virtual machines/domains running on the system."), > diff --git a/src/Virt_ComputerSystem.c b/src/Virt_ComputerSystem.c > index e6c7e55..dee4ef7 100644 > --- a/src/Virt_ComputerSystem.c > +++ b/src/Virt_ComputerSystem.c > @@ -30,23 +30,40 @@ > #include > #include > > +#include > #include > +#include > > -#include "cs_util.h" > #include > -#include "misc_util.h" > -#include "infostore.h" > -#include "device_parsing.h" > #include > #include > #include > > +#include "cs_util.h" > +#include "misc_util.h" > +#include "infostore.h" > +#include "device_parsing.h" > +#include "svpc_types.h" > + > #include "Virt_ComputerSystem.h" > #include "Virt_HostSystem.h" > #include "Virt_VirtualSystemSnapshotService.h" > > + > const static CMPIBroker *_BROKER; > > +typedef struct _state_change_job state_change_job_t; > +struct _state_change_job { > + char uuid[VIR_UUID_STRING_BUFLEN]; > + CMPIContext *context; > + CMPIObjectPath *obj_path; > + char *dom_name; > + uint16_t dom_state; > + uint16_t status; /* job status */ > +}; > + > +static bool events_registered = false; > + > /* Set the "Name" property of an instance from a domain */ > static int set_name_from_dom(virDomainPtr dom, CMPIInstance *instance) > { > @@ -1189,19 +1206,20 @@ static CMPIStatus __state_change(const char *name, > s = state_change_enable(dom, &info); > else if (state == CIM_STATE_DISABLED) > s = state_change_disable(dom, &info); > - else if (state == CIM_STATE_SHUTDOWN) > - s = state_change_shutdown(dom, &info); > else if (state == CIM_STATE_PAUSED) > s = state_change_pause(dom, &info); > - else if (state == CIM_STATE_REBOOT) > - s = state_change_reboot(dom, &info); > else if (state == CIM_STATE_RESET) > s = state_change_reset(dom, &info); > + else if (state == CIM_STATE_SHUTDOWN || state == CIM_STATE_REBOOT) > + s.rc = CIM_SVPC_RETURN_JOB_STARTED; > else > cu_statusf(_BROKER, &s, > CMPI_RC_ERR_NOT_SUPPORTED, > "State not supported"); > > + if (s.rc != CMPI_RC_OK || s.rc != CIM_SVPC_RETURN_JOB_STARTED) > + goto out; > + This block is wrong, should be && instead of ||. Best regards, Eduardo -- Eduardo de Barros Lima Software Engineer, Open Virtualization Linux Technology Center - IBM/Brazil eblima at br.ibm.com From bestor at us.ibm.com Fri Feb 24 19:20:22 2012 From: bestor at us.ibm.com (Gareth S Bestor) Date: Fri, 24 Feb 2012 11:20:22 -0800 Subject: [Libvirt-cim] [PATCH] Pool Refresh Patch2 Message-ID: <1330111222-3019-1-git-send-email-bestor@us.ibm.com> From: Gareth S. Bestor This patches earlier patch (from Sharad) that added pool refresh function to libvirt-cim. Previously, a pool refresh would be initiated whenever the pool's CIM instance was retreived; this turns out to be too expensive for some consumers. This patch removes that, and instead makes pool refresh an explicit CIM operation that a CIM client can request on the KVM_ResourcePoolConfigurationService (eg when pool resources are added or removed or changes outside of CIM). The previous patch also initiated a refresh whenever libvirt-cim was used to add or remove a pool resource; this fuction has been kept, because it makes sense for the CIM pool to immediately reflect any changes when resources are added/removed via CIM. The new extrinsic method is called RefreshResourcesInPool[] Signed-off-by: Gareth S. Bestor --- schema/ResourcePoolConfigurationService.mof | 12 ++++ src/Virt_DevicePool.c | 4 - src/Virt_ResourcePoolConfigurationService.c | 93 +++++++++++++++++++++++++++ 3 files changed, 105 insertions(+), 4 deletions(-) diff --git a/schema/ResourcePoolConfigurationService.mof b/schema/ResourcePoolConfigurationService.mof index 9199f08..7fd1cbd 100644 --- a/schema/ResourcePoolConfigurationService.mof +++ b/schema/ResourcePoolConfigurationService.mof @@ -76,6 +76,18 @@ class KVM_ResourcePoolConfigurationService : CIM_ResourcePoolConfigurationServic CIM_ConcreteJob REF Job ); + [Description ( "Refresh the list of resource within a specified pool to " + "reflect any external changes. If 0 is returned, the " + "function completed successfully." )] + uint32 RefreshResourcesInPool( + [IN, Description ( "The pool to refresh the resource in." )] + CIM_ResourcePool REF Pool, + + [IN ( false ), OUT, Description ( "Reference to the job (may be null " + "if job completed)." )] + CIM_ConcreteJob REF Job + ); + }; [Provider("cmpi::Virt_ResourcePoolConfigurationService")] diff --git a/src/Virt_DevicePool.c b/src/Virt_DevicePool.c index fe5573f..def8454 100644 --- a/src/Virt_DevicePool.c +++ b/src/Virt_DevicePool.c @@ -186,10 +186,6 @@ static bool diskpool_set_capacity(virConnectPtr conn, goto out; } - if ((virStoragePoolRefresh(pool, 0)) == -1) - CU_DEBUG("Unable to refresh storage pool"); - - if (virStoragePoolGetInfo(pool, &info) == -1) { CU_DEBUG("Failed to get info for pool `%s'", _pool->tag); goto out; diff --git a/src/Virt_ResourcePoolConfigurationService.c b/src/Virt_ResourcePoolConfigurationService.c index 7e76032..751d016 100644 --- a/src/Virt_ResourcePoolConfigurationService.c +++ b/src/Virt_ResourcePoolConfigurationService.c @@ -1075,6 +1075,90 @@ static CMPIStatus delete_resource_in_pool(CMPIMethodMI *self, return s; } +static CMPIStatus refresh_resources_parse_args(const CMPIArgs *argsin, + CMPIObjectPath **pool) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + + if (cu_get_ref_arg(argsin, "Pool", pool) != CMPI_RC_OK) { + CU_DEBUG("Failed to get Pool reference arg"); + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_INVALID_PARAMETER, + "Missing argument `Pool'"); + goto out; + } + + out: + return s; +} + +static CMPIStatus refresh_resources_in_pool(CMPIMethodMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference, + const CMPIArgs *argsin, + CMPIArgs *argsout) +{ + uint32_t rc = CIM_SVPC_RETURN_FAILED; + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIObjectPath *pool; + virStoragePoolPtr poolPtr; + char *pool_id = NULL; + const char *id = NULL; + virConnectPtr conn = NULL; + + CU_DEBUG("RefreshResourcesInPool"); + + s = refresh_resources_parse_args(argsin, &pool); + if (s.rc != CMPI_RC_OK) + goto out; + + if (cu_get_str_path(pool, "InstanceID", &id) != CMPI_RC_OK) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Missing InstanceID in resource pool"); + goto out; + } + + pool_id = name_from_pool_id(id); + if (pool_id == NULL) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_INVALID_PARAMETER, + "Pool has invalid InstanceID"); + goto out; + } + + conn = connect_by_classname(_BROKER, CLASSNAME(reference), &s); + if (conn == NULL) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Unable to connect to hypervisor"); + goto out; + } + + poolPtr = virStoragePoolLookupByName(conn, pool_id); + if (poolPtr == NULL) { + CU_DEBUG("Failed to lookup storage pool `%s'", pool_id); + goto out; + } + + if ((virStoragePoolRefresh(poolPtr, 0)) == -1) { + CU_DEBUG("Unable to refresh storage pool"); + } + else + CU_DEBUG("Refreshed resources in storage pool `%s'", pool_id); + virStoragePoolFree(poolPtr); + + out: + free(pool_id); + + if (s.rc == CMPI_RC_OK) + rc = CIM_SVPC_RETURN_COMPLETED; + CMReturnData(results, &rc, CMPI_uint32); + + return s; +} + static CMPIStatus dummy_handler(CMPIMethodMI *self, const CMPIContext *context, const CMPIResult *results, @@ -1139,6 +1223,14 @@ static struct method_handler DeleteResourceInPool = { } }; +static struct method_handler RefreshResourcesInPool = { + .name = "RefreshResourcesInPool", + .handler = refresh_resources_in_pool, + .args = {{"Pool", CMPI_ref, true}, + ARG_END + } +}; + static struct method_handler *my_handlers[] = { &CreateResourcePool, &CreateChildResourcePool, @@ -1147,6 +1239,7 @@ static struct method_handler *my_handlers[] = { &DeleteResourcePool, &CreateResourceInPool, &DeleteResourceInPool, + &RefreshResourcesInPool, NULL, }; -- 1.7.1 From cvincent at linux.vnet.ibm.com Tue Feb 28 18:00:49 2012 From: cvincent at linux.vnet.ibm.com (Chip Vincent) Date: Tue, 28 Feb 2012 13:00:49 -0500 Subject: [Libvirt-cim] [PATCH] Plan9fs (aka 9pfs, VirtFS) support for QEMU/KVM environment In-Reply-To: <4EF2C4F6.1080206@linux.vnet.ibm.com> References: <20111209111656.20645.54429.stgit@deepak-ThinkPad-T60p> <4EF2C4F6.1080206@linux.vnet.ibm.com> Message-ID: <4F4D1651.4060808@linux.vnet.ibm.com> Pushed. Sorry for the delay. On 12/22/2011 12:49 AM, Deepak C Shetty wrote: > On 12/15/2011 11:19 PM, Sharad Mishra wrote: >> The patch looks good. >> Gareth is looking if we need to update SettingsDefineCapabilities for >> template. >> >> Regards, >> Sharad Mishra >> Open Virtualization >> Linux Technology Center >> IBM >> > Hi, any outlook on when this patch be merged ? > Let me know if anything else is needed from my side. > > thanx > deepak > > > _______________________________________________ > Libvirt-cim mailing list > Libvirt-cim at redhat.com > https://www.redhat.com/mailman/listinfo/libvirt-cim -- Chip Vincent Open Virtualization IBM Linux Technology Center cvincent at linux.vnet.ibm.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From cvincent at linux.vnet.ibm.com Tue Feb 28 18:11:14 2012 From: cvincent at linux.vnet.ibm.com (Chip Vincent) Date: Tue, 28 Feb 2012 13:11:14 -0500 Subject: [Libvirt-cim] [PATCH] Pool Refresh Patch2 In-Reply-To: <1330111222-3019-1-git-send-email-bestor@us.ibm.com> References: <1330111222-3019-1-git-send-email-bestor@us.ibm.com> Message-ID: <4F4D18C2.9050102@linux.vnet.ibm.com> +1 and pushed. On 02/24/2012 02:20 PM, Gareth S Bestor wrote: > From: Gareth S. Bestor > > This patches earlier patch (from Sharad) that added pool refresh function to > libvirt-cim. Previously, a pool refresh would be initiated whenever the pool's > CIM instance was retreived; this turns out to be too expensive for some > consumers. This patch removes that, and instead makes pool refresh an > explicit CIM operation that a CIM client can request on the > KVM_ResourcePoolConfigurationService (eg when pool resources are added or > removed or changes outside of CIM). The previous patch also initiated a > refresh whenever libvirt-cim was used to add or remove a pool resource; this > fuction has been kept, because it makes sense for the CIM pool to immediately > reflect any changes when resources are added/removed via CIM. > The new extrinsic method is called RefreshResourcesInPool[] > > Signed-off-by: Gareth S. Bestor > --- > schema/ResourcePoolConfigurationService.mof | 12 ++++ > src/Virt_DevicePool.c | 4 - > src/Virt_ResourcePoolConfigurationService.c | 93 +++++++++++++++++++++++++++ > 3 files changed, 105 insertions(+), 4 deletions(-) > > diff --git a/schema/ResourcePoolConfigurationService.mof b/schema/ResourcePoolConfigurationService.mof > index 9199f08..7fd1cbd 100644 > --- a/schema/ResourcePoolConfigurationService.mof > +++ b/schema/ResourcePoolConfigurationService.mof > @@ -76,6 +76,18 @@ class KVM_ResourcePoolConfigurationService : CIM_ResourcePoolConfigurationServic > CIM_ConcreteJob REF Job > ); > > + [Description ( "Refresh the list of resource within a specified pool to " > + "reflect any external changes. If 0 is returned, the " > + "function completed successfully." )] > + uint32 RefreshResourcesInPool( > + [IN, Description ( "The pool to refresh the resource in." )] > + CIM_ResourcePool REF Pool, > + > + [IN ( false ), OUT, Description ( "Reference to the job (may be null " > + "if job completed)." )] > + CIM_ConcreteJob REF Job > + ); > + > }; > > [Provider("cmpi::Virt_ResourcePoolConfigurationService")] > diff --git a/src/Virt_DevicePool.c b/src/Virt_DevicePool.c > index fe5573f..def8454 100644 > --- a/src/Virt_DevicePool.c > +++ b/src/Virt_DevicePool.c > @@ -186,10 +186,6 @@ static bool diskpool_set_capacity(virConnectPtr conn, > goto out; > } > > - if ((virStoragePoolRefresh(pool, 0)) == -1) > - CU_DEBUG("Unable to refresh storage pool"); > - > - > if (virStoragePoolGetInfo(pool,&info) == -1) { > CU_DEBUG("Failed to get info for pool `%s'", _pool->tag); > goto out; > diff --git a/src/Virt_ResourcePoolConfigurationService.c b/src/Virt_ResourcePoolConfigurationService.c > index 7e76032..751d016 100644 > --- a/src/Virt_ResourcePoolConfigurationService.c > +++ b/src/Virt_ResourcePoolConfigurationService.c > @@ -1075,6 +1075,90 @@ static CMPIStatus delete_resource_in_pool(CMPIMethodMI *self, > return s; > } > > +static CMPIStatus refresh_resources_parse_args(const CMPIArgs *argsin, > + CMPIObjectPath **pool) > +{ > + CMPIStatus s = {CMPI_RC_OK, NULL}; > + > + if (cu_get_ref_arg(argsin, "Pool", pool) != CMPI_RC_OK) { > + CU_DEBUG("Failed to get Pool reference arg"); > + cu_statusf(_BROKER,&s, > + CMPI_RC_ERR_INVALID_PARAMETER, > + "Missing argument `Pool'"); > + goto out; > + } > + > + out: > + return s; > +} > + > +static CMPIStatus refresh_resources_in_pool(CMPIMethodMI *self, > + const CMPIContext *context, > + const CMPIResult *results, > + const CMPIObjectPath *reference, > + const CMPIArgs *argsin, > + CMPIArgs *argsout) > +{ > + uint32_t rc = CIM_SVPC_RETURN_FAILED; > + CMPIStatus s = {CMPI_RC_OK, NULL}; > + CMPIObjectPath *pool; > + virStoragePoolPtr poolPtr; > + char *pool_id = NULL; > + const char *id = NULL; > + virConnectPtr conn = NULL; > + > + CU_DEBUG("RefreshResourcesInPool"); > + > + s = refresh_resources_parse_args(argsin,&pool); > + if (s.rc != CMPI_RC_OK) > + goto out; > + > + if (cu_get_str_path(pool, "InstanceID",&id) != CMPI_RC_OK) { > + cu_statusf(_BROKER,&s, > + CMPI_RC_ERR_FAILED, > + "Missing InstanceID in resource pool"); > + goto out; > + } > + > + pool_id = name_from_pool_id(id); > + if (pool_id == NULL) { > + cu_statusf(_BROKER,&s, > + CMPI_RC_ERR_INVALID_PARAMETER, > + "Pool has invalid InstanceID"); > + goto out; > + } > + > + conn = connect_by_classname(_BROKER, CLASSNAME(reference),&s); > + if (conn == NULL) { > + cu_statusf(_BROKER,&s, > + CMPI_RC_ERR_FAILED, > + "Unable to connect to hypervisor"); > + goto out; > + } > + > + poolPtr = virStoragePoolLookupByName(conn, pool_id); > + if (poolPtr == NULL) { > + CU_DEBUG("Failed to lookup storage pool `%s'", pool_id); > + goto out; > + } > + > + if ((virStoragePoolRefresh(poolPtr, 0)) == -1) { > + CU_DEBUG("Unable to refresh storage pool"); > + } > + else > + CU_DEBUG("Refreshed resources in storage pool `%s'", pool_id); > + virStoragePoolFree(poolPtr); > + > + out: > + free(pool_id); > + > + if (s.rc == CMPI_RC_OK) > + rc = CIM_SVPC_RETURN_COMPLETED; > + CMReturnData(results,&rc, CMPI_uint32); > + > + return s; > +} > + > static CMPIStatus dummy_handler(CMPIMethodMI *self, > const CMPIContext *context, > const CMPIResult *results, > @@ -1139,6 +1223,14 @@ static struct method_handler DeleteResourceInPool = { > } > }; > > +static struct method_handler RefreshResourcesInPool = { > + .name = "RefreshResourcesInPool", > + .handler = refresh_resources_in_pool, > + .args = {{"Pool", CMPI_ref, true}, > + ARG_END > + } > +}; > + > static struct method_handler *my_handlers[] = { > &CreateResourcePool, > &CreateChildResourcePool, > @@ -1147,6 +1239,7 @@ static struct method_handler *my_handlers[] = { > &DeleteResourcePool, > &CreateResourceInPool, > &DeleteResourceInPool, > +&RefreshResourcesInPool, > NULL, > }; > -- Chip Vincent Open Virtualization IBM Linux Technology Center cvincent at linux.vnet.ibm.com From cvincent at linux.vnet.ibm.com Tue Feb 28 18:07:01 2012 From: cvincent at linux.vnet.ibm.com (Chip Vincent) Date: Tue, 28 Feb 2012 13:07:01 -0500 Subject: [Libvirt-cim] [PATCH 2/3] CSI: Cleanup code In-Reply-To: <4F450AF2.3070506@linux.vnet.ibm.com> References: <1329766565-23194-1-git-send-email-eblima@linux.vnet.ibm.com> <1329766565-23194-3-git-send-email-eblima@linux.vnet.ibm.com> <4F450AF2.3070506@linux.vnet.ibm.com> Message-ID: <4F4D17C5.6050407@linux.vnet.ibm.com> Pushed On 02/22/2012 10:34 AM, Chip Vincent wrote: > +1 > > On 02/20/2012 02:36 PM, Eduardo Lima (Etrunko) wrote: >> From: "Eduardo Lima (Etrunko)" >> >> Signed-off-by: Eduardo Lima (Etrunko) >> --- >> src/Virt_ComputerSystemIndication.c | 51 +++++++++++++++++------------------ >> 1 files changed, 25 insertions(+), 26 deletions(-) >> >> diff --git a/src/Virt_ComputerSystemIndication.c >> b/src/Virt_ComputerSystemIndication.c >> index ab6ffe4..b60138a 100644 >> --- a/src/Virt_ComputerSystemIndication.c >> +++ b/src/Virt_ComputerSystemIndication.c >> @@ -692,36 +692,35 @@ static CMPIStatus ActivateFilter(CMPIIndicationMI* mi, >> thread =&csi_thread_data[platform]; >> thread->active_filters += 1; >> >> - if (thread->id == 0) { >> - args = malloc(sizeof(*args)); >> - if (args == NULL) { >> - CU_DEBUG("Failed to allocate ind_args"); >> - cu_statusf(_BROKER,&s, >> - CMPI_RC_ERR_FAILED, >> - "Unable to allocate ind_args"); >> - error = true; >> - goto out; >> - } >> - >> - args->context = CBPrepareAttachThread(_BROKER, ctx); >> - if (args->context == NULL) { >> - CU_DEBUG("Failed to create thread context"); >> - cu_statusf(_BROKER,&s, >> - CMPI_RC_ERR_FAILED, >> - "Unable to create thread context"); >> - error = true; >> - goto out; >> - } >> + /* Check if thread is already running */ >> + if (thread->id> 0) >> + goto out; >> >> - args->ns = strdup(NAMESPACE(op)); >> - args->classname = strdup(CLASSNAME(op)); >> - args->_ctx = _ctx; >> + args = malloc(sizeof(*args)); >> + if (args == NULL) { >> + CU_DEBUG("Failed to allocate ind_args"); >> + cu_statusf(_BROKER,&s, CMPI_RC_ERR_FAILED, >> + "Unable to allocate ind_args"); >> + error = true; >> + goto out; >> + } >> >> - thread->args = args; >> - thread->id = _BROKER->xft->newThread(lifecycle_thread, >> - thread, 0); >> + args->context = CBPrepareAttachThread(_BROKER, ctx); >> + if (args->context == NULL) { >> + CU_DEBUG("Failed to create thread context"); >> + cu_statusf(_BROKER,&s, CMPI_RC_ERR_FAILED, >> + "Unable to create thread context"); >> + error = true; >> + goto out; >> } >> >> + args->ns = strdup(NAMESPACE(op)); >> + args->classname = strdup(CLASSNAME(op)); >> + args->_ctx = _ctx; >> + >> + thread->args = args; >> + thread->id = _BROKER->xft->newThread(lifecycle_thread, thread, 0); >> + >> out: >> if (error == true) { >> thread->active_filters -= 1; > > -- Chip Vincent Open Virtualization IBM Linux Technology Center cvincent at linux.vnet.ibm.com From cvincent at linux.vnet.ibm.com Tue Feb 28 18:19:45 2012 From: cvincent at linux.vnet.ibm.com (Chip Vincent) Date: Tue, 28 Feb 2012 13:19:45 -0500 Subject: [Libvirt-cim] [PATCH 3/3] CSI: Fix log messages In-Reply-To: <4F450AFF.8040801@linux.vnet.ibm.com> References: <1329766565-23194-1-git-send-email-eblima@linux.vnet.ibm.com> <1329766565-23194-4-git-send-email-eblima@linux.vnet.ibm.com> <4F450AFF.8040801@linux.vnet.ibm.com> Message-ID: <4F4D1AC1.8090203@linux.vnet.ibm.com> Pushed On 02/22/2012 10:34 AM, Chip Vincent wrote: > +1 > > On 02/20/2012 02:36 PM, Eduardo Lima (Etrunko) wrote: >> From: "Eduardo Lima (Etrunko)" >> >> To produce correct outputs, it is necessary to call CMGetCharPtr(s.msg) instead >> of using s.msg directly. >> >> Signed-off-by: Eduardo Lima (Etrunko) >> --- >> src/Virt_ComputerSystemIndication.c | 9 +++++---- >> 1 files changed, 5 insertions(+), 4 deletions(-) >> >> diff --git a/src/Virt_ComputerSystemIndication.c >> b/src/Virt_ComputerSystemIndication.c >> index b60138a..2d0a94e 100644 >> --- a/src/Virt_ComputerSystemIndication.c >> +++ b/src/Virt_ComputerSystemIndication.c >> @@ -254,7 +254,7 @@ static bool _do_indication(const CMPIBroker *broker, >> >> ind_op = CMGetObjectPath(ind,&s); >> if (s.rc != CMPI_RC_OK) { >> - CU_DEBUG("Failed to get ind_op. Error: '%s'", s.msg); >> + CU_DEBUG("Failed to get ind_op. Error: '%s'", >> CMGetCharPtr(s.msg)); >> ret = false; >> goto out; >> } >> @@ -263,7 +263,7 @@ static bool _do_indication(const CMPIBroker *broker, >> affected_op = CMGetObjectPath(affected_inst,&s); >> if (s.rc != CMPI_RC_OK) { >> ret = false; >> - CU_DEBUG("problem getting affected_op: '%s'", s.msg); >> + CU_DEBUG("problem getting affected_op: '%s'", >> CMGetCharPtr(s.msg)); >> goto out; >> } >> >> @@ -368,7 +368,8 @@ static bool create_deleted_guest_inst(const char *xml, >> dominfo, >> inst); >> if (s.rc != CMPI_RC_OK) { >> - CU_DEBUG("instance from domain info error: %s", s.msg); >> + CU_DEBUG("instance from domain info error: %s", >> + CMGetCharPtr(s.msg)); >> goto out; >> } >> >> @@ -476,7 +477,7 @@ static int update_domain_list(virConnectPtr conn, >> csi_thread_data_t *thread) >> for (i = 0; i< count; i++) { >> dom = csi_dom_xml_new(dom_ptr_list[i],&s); >> if (dom == NULL) { >> - CU_DEBUG("Failed to get domain info %s", s.msg); >> + CU_DEBUG("Failed to get domain info %s", >> CMGetCharPtr(s.msg)); >> break; >> } >> > > -- Chip Vincent Open Virtualization IBM Linux Technology Center cvincent at linux.vnet.ibm.com From cvincent at linux.vnet.ibm.com Tue Feb 28 18:19:49 2012 From: cvincent at linux.vnet.ibm.com (Chip Vincent) Date: Tue, 28 Feb 2012 13:19:49 -0500 Subject: [Libvirt-cim] [PATCH 1/3] CSI: Only execute callback if indications are enabled In-Reply-To: <4F450AE7.3060006@linux.vnet.ibm.com> References: <1329766565-23194-1-git-send-email-eblima@linux.vnet.ibm.com> <1329766565-23194-2-git-send-email-eblima@linux.vnet.ibm.com> <4F450AE7.3060006@linux.vnet.ibm.com> Message-ID: <4F4D1AC5.3080307@linux.vnet.ibm.com> Pushed On 02/22/2012 10:33 AM, Chip Vincent wrote: > +1. On RHEL 6.2 (libvirt-0.9.4) I was able to run all cimtests without seeing > a core, but my local indication tests still do not work properly. It's a > configuration issue I need to resolve. I always see the following: > > ComputerSystemIndication - 01_created_indication.py: FAIL > ERROR - Waited too long for define indication > ERROR - Exception: Poll for indication Failed > ERROR - Waited too long for start indication > ERROR - Exception: Poll for indication Failed > ERROR - Waited too long for destroy indication > ERROR - Exception: Poll for indication Failed > > Sharad: Can you give this patchset a try and see if it resolves the problem > you were seeing? > > > On 02/20/2012 02:36 PM, Eduardo Lima (Etrunko) wrote: >> From: "Eduardo Lima (Etrunko)" >> >> Signed-off-by: Eduardo Lima (Etrunko) >> --- >> src/Virt_ComputerSystemIndication.c | 16 ++++++++++------ >> 1 files changed, 10 insertions(+), 6 deletions(-) >> >> diff --git a/src/Virt_ComputerSystemIndication.c >> b/src/Virt_ComputerSystemIndication.c >> index 712e12c..ab6ffe4 100644 >> --- a/src/Virt_ComputerSystemIndication.c >> +++ b/src/Virt_ComputerSystemIndication.c >> @@ -489,11 +489,11 @@ static int update_domain_list(virConnectPtr conn, >> csi_thread_data_t *thread) >> return s.rc; >> } >> >> -static int csi_domain_event_cb(virConnectPtr conn, >> - virDomainPtr dom, >> - int event, >> - int detail, >> - void *data) >> +static void csi_domain_event_cb(virConnectPtr conn, >> + virDomainPtr dom, >> + int event, >> + int detail, >> + void *data) >> { >> int cs_event = CS_MODIFIED; >> csi_thread_data_t *thread = (csi_thread_data_t *) data; >> @@ -501,6 +501,11 @@ static int csi_domain_event_cb(virConnectPtr conn, >> char *prefix = class_prefix_name(thread->args->classname); >> CMPIStatus s = {CMPI_RC_OK, NULL}; >> >> + if (lifecycle_enabled == false || thread->active_filters<= 0) { >> + CU_DEBUG("%s indications deactivated, return"); >> + return; >> + } >> + >> CU_DEBUG("Event: Domain %s(%d) event: %d detail: %d\n", >> virDomainGetName(dom), virDomainGetID(dom), event, detail); >> >> @@ -557,7 +562,6 @@ static int csi_domain_event_cb(virConnectPtr conn, >> >> end: >> free(prefix); >> - return 0; >> } >> >> static CMPI_THREAD_RETURN lifecycle_thread(void *params) > > -- Chip Vincent Open Virtualization IBM Linux Technology Center cvincent at linux.vnet.ibm.com