diff --git a/SOURCES/0001-proxy-Fix-persistent-session-with-oVirt-3.6.patch b/SOURCES/0001-proxy-Fix-persistent-session-with-oVirt-3.6.patch new file mode 100644 index 0000000..1038c18 --- /dev/null +++ b/SOURCES/0001-proxy-Fix-persistent-session-with-oVirt-3.6.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Christophe Fergeau +Date: Tue, 14 Jun 2016 14:38:07 +0200 +Subject: [PATCH] proxy: Fix persistent session with oVirt 3.6 + +commit d3683c2 "proxy: Only set 'Prefer: persistent-auth' with +jsession-id" was working as expected when using the +OvirtProxy::jsession-id and OvirtProxy::sso-token properties. + +However, when not using these properties and expecting the jsessionid to +be set as a cookie during a regular HTTP session, this was not working +properly as oVirt is not sending a jsessionid cookie when Prefer: +persistent-auth is not set. + +Consequently, we need to set it upon OvirtProxy creation in order not to +break this usecase. We don't add the header in RestProxyCall as was done +before as we want to be able to disable this addition after +OvirtProxy::sso-token has been set. +--- + govirt/ovirt-proxy.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/govirt/ovirt-proxy.c b/govirt/ovirt-proxy.c +index fc0273f..08e42d2 100644 +--- a/govirt/ovirt-proxy.c ++++ b/govirt/ovirt-proxy.c +@@ -801,9 +801,6 @@ static void ovirt_proxy_set_session_id(OvirtProxy *proxy, const char *session_id + cookie = soup_cookie_new("JSESSIONID", session_id, domain, "/ovirt-engine/api", -1); + soup_cookie_jar_add_cookie(proxy->priv->cookie_jar, cookie); + proxy->priv->jsessionid_cookie = cookie; +- ovirt_proxy_add_header(proxy, "Prefer", "persistent-auth"); +- } else { +- ovirt_proxy_add_header(proxy, "Prefer", NULL); + } + g_free(url); + } +@@ -815,6 +812,7 @@ static void ovirt_proxy_set_sso_token(OvirtProxy *proxy, const char *sso_token) + g_free(proxy->priv->sso_token); + proxy->priv->sso_token = g_strdup(sso_token); + ++ ovirt_proxy_add_header(proxy, "Prefer", NULL); + header_value = g_strdup_printf("Bearer %s", sso_token); + ovirt_proxy_add_header(proxy, "Authorization", header_value); + g_free(header_value); +@@ -903,6 +901,7 @@ static void ovirt_proxy_constructed(GObject *gobject) + g_warning("Disabling strict checking of SSL certificates"); + g_object_set(OVIRT_PROXY(gobject), "ssl-strict", FALSE, NULL); + } ++ ovirt_proxy_add_header(OVIRT_PROXY(gobject), "Prefer", "persistent-auth"); + + /* Chain up to the parent class */ + if (G_OBJECT_CLASS(ovirt_proxy_parent_class)->constructed) diff --git a/SOURCES/0002-Force-use-of-v3-REST-API.patch b/SOURCES/0002-Force-use-of-v3-REST-API.patch new file mode 100644 index 0000000..d5c2979 --- /dev/null +++ b/SOURCES/0002-Force-use-of-v3-REST-API.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Christophe Fergeau +Date: Thu, 16 Jun 2016 11:10:27 +0200 +Subject: [PATCH] Force use of v3 REST API + +oVirt 4.0 introduced a slightly incompatible REST API, see +https://github.com/oVirt/ovirt-engine/tree/master/backend/manager/modules/restapi +A short term fix is to send a "Version: 3" header with each request, +which this commit does. This might stop working with oVirt 4.1 though. + +Longer term fix is tracked in +https://bugzilla.gnome.org/show_bug.cgi?id=767724 +--- + govirt/ovirt-proxy.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/govirt/ovirt-proxy.c b/govirt/ovirt-proxy.c +index 08e42d2..efe3284 100644 +--- a/govirt/ovirt-proxy.c ++++ b/govirt/ovirt-proxy.c +@@ -902,6 +902,7 @@ static void ovirt_proxy_constructed(GObject *gobject) + g_object_set(OVIRT_PROXY(gobject), "ssl-strict", FALSE, NULL); + } + ovirt_proxy_add_header(OVIRT_PROXY(gobject), "Prefer", "persistent-auth"); ++ ovirt_proxy_add_header(OVIRT_PROXY(gobject), "Version", "3"); + + /* Chain up to the parent class */ + if (G_OBJECT_CLASS(ovirt_proxy_parent_class)->constructed) diff --git a/SOURCES/0003-New-storage-format-added-in-oVirt-4.1.patch b/SOURCES/0003-New-storage-format-added-in-oVirt-4.1.patch new file mode 100644 index 0000000..42b49dd --- /dev/null +++ b/SOURCES/0003-New-storage-format-added-in-oVirt-4.1.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Tue, 21 Feb 2017 11:20:38 -0300 +Subject: [PATCH] New storage format added in oVirt 4.1 + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-storage-domain.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/govirt/ovirt-storage-domain.h b/govirt/ovirt-storage-domain.h +index 15c3340..79f1741 100644 +--- a/govirt/ovirt-storage-domain.h ++++ b/govirt/ovirt-storage-domain.h +@@ -41,6 +41,7 @@ typedef enum { + OVIRT_STORAGE_DOMAIN_FORMAT_VERSION_V1, + OVIRT_STORAGE_DOMAIN_FORMAT_VERSION_V2, + OVIRT_STORAGE_DOMAIN_FORMAT_VERSION_V3, ++ OVIRT_STORAGE_DOMAIN_FORMAT_VERSION_V4, + } OvirtStorageDomainFormatVersion; + + typedef enum { diff --git a/SOURCES/0004-proxy-Hold-reference-to-cancellable-object.patch b/SOURCES/0004-proxy-Hold-reference-to-cancellable-object.patch new file mode 100644 index 0000000..2057920 --- /dev/null +++ b/SOURCES/0004-proxy-Hold-reference-to-cancellable-object.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Thu, 2 Feb 2017 15:11:42 -0200 +Subject: [PATCH] proxy: Hold reference to cancellable object + +Being an asynchronous operation, there is no guarantee that the object +is valid by the time of the cleanup, so we hold a reference to it to +ensure it. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-proxy.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/govirt/ovirt-proxy.c b/govirt/ovirt-proxy.c +index efe3284..2b690b6 100644 +--- a/govirt/ovirt-proxy.c ++++ b/govirt/ovirt-proxy.c +@@ -220,6 +220,7 @@ static void ovirt_proxy_call_async_data_free(OvirtProxyCallAsyncData *data) + if ((data->cancellable != NULL) && (data->cancellable_cb_id != 0)) { + g_cancellable_disconnect(data->cancellable, data->cancellable_cb_id); + } ++ g_clear_object(&data->cancellable); + g_slice_free(OvirtProxyCallAsyncData, data); + } + +@@ -284,7 +285,7 @@ void ovirt_rest_call_async(OvirtRestCall *call, + data->call_user_data = user_data; + data->destroy_call_data = destroy_func; + if (cancellable != NULL) { +- data->cancellable = cancellable; ++ data->cancellable = g_object_ref(cancellable); + data->cancellable_cb_id = g_cancellable_connect(cancellable, + G_CALLBACK (call_async_cancelled_cb), + call, NULL); diff --git a/SOURCES/0005-proxy-Check-if-operation-is-cancelled-before-disconn.patch b/SOURCES/0005-proxy-Check-if-operation-is-cancelled-before-disconn.patch new file mode 100644 index 0000000..c9a65ce --- /dev/null +++ b/SOURCES/0005-proxy-Check-if-operation-is-cancelled-before-disconn.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Thu, 2 Feb 2017 15:13:48 -0200 +Subject: [PATCH] proxy: Check if operation is cancelled before disconnecting + signal + +According to the documentation, g_cancellable_disconnect() waits for the +signal handler to finish, and if it is called from the handler itself, it +will result in a deadlock. To avoid it, we check if the operation is +cancelled and if so, call g_signal_handler_disconnect() instead of +g_cancellable_disconnect(). + +https://developer.gnome.org/gio/stable/GCancellable.html#g-cancellable-disconnect + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-proxy.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/govirt/ovirt-proxy.c b/govirt/ovirt-proxy.c +index 2b690b6..921e22e 100644 +--- a/govirt/ovirt-proxy.c ++++ b/govirt/ovirt-proxy.c +@@ -218,7 +218,15 @@ static void ovirt_proxy_call_async_data_free(OvirtProxyCallAsyncData *data) + g_object_unref(G_OBJECT(data->result)); + } + if ((data->cancellable != NULL) && (data->cancellable_cb_id != 0)) { +- g_cancellable_disconnect(data->cancellable, data->cancellable_cb_id); ++ if (g_cancellable_is_cancelled(data->cancellable)) { ++ /* Cancellable has already been cancelled, we don't need to use ++ * g_cancellable_disconnect() to disconnect the signal handler ++ * as we know the 'cancelled' signal is no longer going to be emitted ++ */ ++ g_signal_handler_disconnect(data->cancellable, data->cancellable_cb_id); ++ } else { ++ g_cancellable_disconnect(data->cancellable, data->cancellable_cb_id); ++ } + } + g_clear_object(&data->cancellable); + g_slice_free(OvirtProxyCallAsyncData, data); diff --git a/SOURCES/0006-storage-domain-Factor-out-property-value-setting-fro.patch b/SOURCES/0006-storage-domain-Factor-out-property-value-setting-fro.patch new file mode 100644 index 0000000..a1b2f28 --- /dev/null +++ b/SOURCES/0006-storage-domain-Factor-out-property-value-setting-fro.patch @@ -0,0 +1,107 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Wed, 10 May 2017 15:45:36 -0300 +Subject: [PATCH] storage-domain: Factor out property value setting from + ovirt_resource_parse_xml() + +Instead of using chained if/else blocks, use a switch for the type. With +this small refactor we prepare to move this function to ovirt-utils so +that it can be reused by other objects. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-storage-domain.c | 74 ++++++++++++++++++++++------------- + 1 file changed, 47 insertions(+), 27 deletions(-) + +diff --git a/govirt/ovirt-storage-domain.c b/govirt/ovirt-storage-domain.c +index e7308bb..4087d75 100644 +--- a/govirt/ovirt-storage-domain.c ++++ b/govirt/ovirt-storage-domain.c +@@ -277,6 +277,51 @@ OvirtStorageDomain *ovirt_storage_domain_new(void) + return OVIRT_STORAGE_DOMAIN(domain); + } + ++static gboolean ++_set_property_value_from_type(GValue *value, ++ GType type, ++ const char *value_str, ++ RestXmlNode *node) ++{ ++ gboolean ret = TRUE; ++ ++ if (g_type_is_a(type, OVIRT_TYPE_RESOURCE)) { ++ GObject *resource_value = g_initable_new(type, NULL, NULL, "xml-node", node, NULL); ++ g_value_set_object(value, resource_value); ++ goto end; ++ } ++ ++ /* All other types require valid value_str */ ++ if (value_str == NULL) ++ return FALSE; ++ ++ if (G_TYPE_IS_ENUM(type)) { ++ int enum_value = ovirt_utils_genum_get_value(type, value_str, 0); ++ g_value_set_enum(value, enum_value); ++ goto end; ++ } ++ ++ switch(type) { ++ case G_TYPE_BOOLEAN: { ++ gboolean bool_value = ovirt_utils_boolean_from_string(value_str); ++ g_value_set_boolean(value, bool_value); ++ break; ++ } ++ case G_TYPE_UINT64: { ++ guint64 int64_value = g_ascii_strtoull(value_str, NULL, 0); ++ g_value_set_uint64(value, int64_value); ++ break; ++ } ++ default: { ++ g_warning("Unexpected type '%s' with value '%s'", g_type_name(type), value_str); ++ ret = FALSE; ++ } ++ } ++ ++end: ++ return ret; ++} ++ + typedef struct { + const char *xml_node; + GType type; +@@ -296,34 +341,9 @@ ovirt_resource_parse_xml(OvirtResource *resource, + GValue value = { 0, }; + + value_str = ovirt_rest_xml_node_get_content_from_path(node, elements->xml_node); +- if (value_str == NULL) { +- continue; +- } + g_value_init(&value, elements->type); +- +- if (G_TYPE_IS_ENUM(elements->type)) { +- int enum_value; +- enum_value = ovirt_utils_genum_get_value(elements->type, +- value_str, 0); +- g_value_set_enum(&value, enum_value); +- } else if (elements->type == G_TYPE_BOOLEAN) { +- gboolean bool_value; +- +- bool_value = ovirt_utils_boolean_from_string(value_str); +- g_value_set_boolean(&value, bool_value); +- } else if (elements->type == G_TYPE_UINT64) { +- guint64 int64_value; +- +- int64_value = g_ascii_strtoull(value_str, NULL, 0); +- g_value_set_uint64(&value, int64_value); +- } else if (g_type_is_a(elements->type, OVIRT_TYPE_RESOURCE)) { +- GObject *resource_value; +- +- resource_value = g_initable_new(elements->type, NULL, NULL, +- "xml-node", node, NULL); +- g_value_set_object(&value, resource_value); +- } +- g_object_set_property(G_OBJECT(resource), elements->prop_name, &value); ++ if (_set_property_value_from_type(&value, elements->type, value_str, node)) ++ g_object_set_property(G_OBJECT(resource), elements->prop_name, &value); + g_value_unset(&value); + } diff --git a/SOURCES/0007-storage-domain-use-explicit-initialization-of-struct.patch b/SOURCES/0007-storage-domain-use-explicit-initialization-of-struct.patch new file mode 100644 index 0000000..a774a8e --- /dev/null +++ b/SOURCES/0007-storage-domain-use-explicit-initialization-of-struct.patch @@ -0,0 +1,89 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Wed, 10 May 2017 16:12:01 -0300 +Subject: [PATCH] storage-domain: use explicit initialization of struct + OvirtXmlElement members + +Also, members have been reordered and the xml_node field has been +renamed to more proper xml_path. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-storage-domain.c | 46 ++++++++++++++++++++++++++--------- + 1 file changed, 34 insertions(+), 12 deletions(-) + +diff --git a/govirt/ovirt-storage-domain.c b/govirt/ovirt-storage-domain.c +index 4087d75..07c0ef0 100644 +--- a/govirt/ovirt-storage-domain.c ++++ b/govirt/ovirt-storage-domain.c +@@ -323,9 +323,9 @@ end: + } + + typedef struct { +- const char *xml_node; +- GType type; + const char *prop_name; ++ GType type; ++ const char *xml_path; + } OvirtXmlElement; + + static gboolean +@@ -336,11 +336,12 @@ ovirt_resource_parse_xml(OvirtResource *resource, + g_return_val_if_fail(OVIRT_IS_RESOURCE(resource), FALSE); + g_return_val_if_fail(elements != NULL, FALSE); + +- for (;elements->xml_node != NULL; elements++) { ++ for (;elements->xml_path != NULL; elements++) { + const char *value_str; + GValue value = { 0, }; + +- value_str = ovirt_rest_xml_node_get_content_from_path(node, elements->xml_node); ++ value_str = ovirt_rest_xml_node_get_content_from_path(node, elements->xml_path); ++ + g_value_init(&value, elements->type); + if (_set_property_value_from_type(&value, elements->type, value_str, node)) + g_object_set_property(G_OBJECT(resource), elements->prop_name, &value); +@@ -355,14 +356,35 @@ ovirt_storage_domain_refresh_from_xml(OvirtStorageDomain *domain, + RestXmlNode *node) + { + OvirtXmlElement storage_domain_elements[] = { +- { "type", OVIRT_TYPE_STORAGE_DOMAIN_TYPE, "type" }, +- { "master", G_TYPE_BOOLEAN, "master" }, +- { "available", G_TYPE_UINT64, "available" }, +- { "used", G_TYPE_UINT64, "used" }, +- { "committed", G_TYPE_UINT64, "committed" }, +- { "storage_format", OVIRT_TYPE_STORAGE_DOMAIN_FORMAT_VERSION, "version" }, +- { "status/state", OVIRT_TYPE_STORAGE_DOMAIN_STATE, "state" }, +- { NULL, G_TYPE_INVALID, NULL } ++ { .prop_name = "type", ++ .type = OVIRT_TYPE_STORAGE_DOMAIN_TYPE, ++ .xml_path = "type", ++ }, ++ { .prop_name = "master", ++ .type = G_TYPE_BOOLEAN, ++ .xml_path = "master", ++ }, ++ { .prop_name = "available", ++ .type = G_TYPE_UINT64, ++ .xml_path = "available", ++ }, ++ { .prop_name = "used", ++ .type = G_TYPE_UINT64, ++ .xml_path = "used", ++ }, ++ { .prop_name = "committed", ++ .type = G_TYPE_UINT64, ++ .xml_path = "committed", ++ }, ++ { .prop_name = "version", ++ .type = OVIRT_TYPE_STORAGE_DOMAIN_FORMAT_VERSION, ++ .xml_path = "storage_format", ++ }, ++ { .prop_name = "state", ++ .type = OVIRT_TYPE_STORAGE_DOMAIN_STATE, ++ .xml_path = "status/state", ++ }, ++ { NULL , } + }; + + return ovirt_resource_parse_xml(OVIRT_RESOURCE(domain), node, storage_domain_elements); diff --git a/SOURCES/0008-storage-domain-Move-out-ovirt_resource_parse_xml-to-.patch b/SOURCES/0008-storage-domain-Move-out-ovirt_resource_parse_xml-to-.patch new file mode 100644 index 0000000..448aecb --- /dev/null +++ b/SOURCES/0008-storage-domain-Move-out-ovirt_resource_parse_xml-to-.patch @@ -0,0 +1,325 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Thu, 22 Jun 2017 13:06:53 -0300 +Subject: [PATCH] storage-domain: Move out ovirt_resource_parse_xml() to + ovirt-utils + +There were a couple of tweaks to the function: + +1) Renamed to ovirt_rest_xml_node_parse() + More suited to the task performed. + +2) Validates GObject instead of OvirtResource + This removes the restriction of usage by a OvirtResource, and in the + future it can also be used by OvirtVmDisplay to parse the elements. + It also makes it more coherent to its purpose, as the function only + sets properties of a GObject and does not really require a + OvirtResource. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-storage-domain.c | 152 +++++++--------------------------- + govirt/ovirt-utils.c | 71 +++++++++++++++- + govirt/ovirt-utils.h | 13 ++- + 3 files changed, 113 insertions(+), 123 deletions(-) + +diff --git a/govirt/ovirt-storage-domain.c b/govirt/ovirt-storage-domain.c +index 07c0ef0..0582203 100644 +--- a/govirt/ovirt-storage-domain.c ++++ b/govirt/ovirt-storage-domain.c +@@ -53,10 +53,6 @@ enum { + PROP_STATE + }; + +-static gboolean +-ovirt_storage_domain_refresh_from_xml(OvirtStorageDomain *domain, +- RestXmlNode *node); +- + static void ovirt_storage_domain_get_property(GObject *object, + guint prop_id, + GValue *value, +@@ -145,10 +141,39 @@ static gboolean ovirt_storage_domain_init_from_xml(OvirtResource *resource, + { + gboolean parsed_ok; + OvirtResourceClass *parent_class; +- OvirtStorageDomain *domain; ++ OvirtXmlElement storage_domain_elements[] = { ++ { .prop_name = "type", ++ .type = OVIRT_TYPE_STORAGE_DOMAIN_TYPE, ++ .xml_path = "type", ++ }, ++ { .prop_name = "master", ++ .type = G_TYPE_BOOLEAN, ++ .xml_path = "master", ++ }, ++ { .prop_name = "available", ++ .type = G_TYPE_UINT64, ++ .xml_path = "available", ++ }, ++ { .prop_name = "used", ++ .type = G_TYPE_UINT64, ++ .xml_path = "used", ++ }, ++ { .prop_name = "committed", ++ .type = G_TYPE_UINT64, ++ .xml_path = "committed", ++ }, ++ { .prop_name = "version", ++ .type = OVIRT_TYPE_STORAGE_DOMAIN_FORMAT_VERSION, ++ .xml_path = "storage_format", ++ }, ++ { .prop_name = "state", ++ .type = OVIRT_TYPE_STORAGE_DOMAIN_STATE, ++ .xml_path = "status/state", ++ }, ++ { NULL , } ++ }; + +- domain = OVIRT_STORAGE_DOMAIN(resource); +- parsed_ok = ovirt_storage_domain_refresh_from_xml(domain, node); ++ parsed_ok = ovirt_rest_xml_node_parse(node, G_OBJECT(resource), storage_domain_elements); + if (!parsed_ok) { + return FALSE; + } +@@ -277,119 +302,6 @@ OvirtStorageDomain *ovirt_storage_domain_new(void) + return OVIRT_STORAGE_DOMAIN(domain); + } + +-static gboolean +-_set_property_value_from_type(GValue *value, +- GType type, +- const char *value_str, +- RestXmlNode *node) +-{ +- gboolean ret = TRUE; +- +- if (g_type_is_a(type, OVIRT_TYPE_RESOURCE)) { +- GObject *resource_value = g_initable_new(type, NULL, NULL, "xml-node", node, NULL); +- g_value_set_object(value, resource_value); +- goto end; +- } +- +- /* All other types require valid value_str */ +- if (value_str == NULL) +- return FALSE; +- +- if (G_TYPE_IS_ENUM(type)) { +- int enum_value = ovirt_utils_genum_get_value(type, value_str, 0); +- g_value_set_enum(value, enum_value); +- goto end; +- } +- +- switch(type) { +- case G_TYPE_BOOLEAN: { +- gboolean bool_value = ovirt_utils_boolean_from_string(value_str); +- g_value_set_boolean(value, bool_value); +- break; +- } +- case G_TYPE_UINT64: { +- guint64 int64_value = g_ascii_strtoull(value_str, NULL, 0); +- g_value_set_uint64(value, int64_value); +- break; +- } +- default: { +- g_warning("Unexpected type '%s' with value '%s'", g_type_name(type), value_str); +- ret = FALSE; +- } +- } +- +-end: +- return ret; +-} +- +-typedef struct { +- const char *prop_name; +- GType type; +- const char *xml_path; +-} OvirtXmlElement; +- +-static gboolean +-ovirt_resource_parse_xml(OvirtResource *resource, +- RestXmlNode *node, +- OvirtXmlElement *elements) +-{ +- g_return_val_if_fail(OVIRT_IS_RESOURCE(resource), FALSE); +- g_return_val_if_fail(elements != NULL, FALSE); +- +- for (;elements->xml_path != NULL; elements++) { +- const char *value_str; +- GValue value = { 0, }; +- +- value_str = ovirt_rest_xml_node_get_content_from_path(node, elements->xml_path); +- +- g_value_init(&value, elements->type); +- if (_set_property_value_from_type(&value, elements->type, value_str, node)) +- g_object_set_property(G_OBJECT(resource), elements->prop_name, &value); +- g_value_unset(&value); +- } +- +- return TRUE; +-} +- +-static gboolean +-ovirt_storage_domain_refresh_from_xml(OvirtStorageDomain *domain, +- RestXmlNode *node) +-{ +- OvirtXmlElement storage_domain_elements[] = { +- { .prop_name = "type", +- .type = OVIRT_TYPE_STORAGE_DOMAIN_TYPE, +- .xml_path = "type", +- }, +- { .prop_name = "master", +- .type = G_TYPE_BOOLEAN, +- .xml_path = "master", +- }, +- { .prop_name = "available", +- .type = G_TYPE_UINT64, +- .xml_path = "available", +- }, +- { .prop_name = "used", +- .type = G_TYPE_UINT64, +- .xml_path = "used", +- }, +- { .prop_name = "committed", +- .type = G_TYPE_UINT64, +- .xml_path = "committed", +- }, +- { .prop_name = "version", +- .type = OVIRT_TYPE_STORAGE_DOMAIN_FORMAT_VERSION, +- .xml_path = "storage_format", +- }, +- { .prop_name = "state", +- .type = OVIRT_TYPE_STORAGE_DOMAIN_STATE, +- .xml_path = "status/state", +- }, +- { NULL , } +- }; +- +- return ovirt_resource_parse_xml(OVIRT_RESOURCE(domain), node, storage_domain_elements); +-} +- + + /** + * ovirt_storage_domain_get_files: +diff --git a/govirt/ovirt-utils.c b/govirt/ovirt-utils.c +index 0e0134c..44ea7da 100644 +--- a/govirt/ovirt-utils.c ++++ b/govirt/ovirt-utils.c +@@ -31,6 +31,7 @@ + #include "ovirt-utils.h" + + #include "ovirt-error.h" ++#include "ovirt-resource.h" + + RestXmlNode * + ovirt_rest_xml_node_from_call(RestProxyCall *call) +@@ -77,7 +78,7 @@ ovirt_rest_xml_node_get_content_va(RestXmlNode *node, + return node->content; + } + +-G_GNUC_INTERNAL const char * ++static const char * + ovirt_rest_xml_node_get_content_from_path(RestXmlNode *node, const char *path) + { + GStrv pathv; +@@ -109,6 +110,74 @@ ovirt_rest_xml_node_get_content(RestXmlNode *node, ...) + return content; + } + ++static gboolean ++_set_property_value_from_type(GValue *value, ++ GType type, ++ const char *value_str, ++ RestXmlNode *node) ++{ ++ gboolean ret = TRUE; ++ ++ if (g_type_is_a(type, OVIRT_TYPE_RESOURCE)) { ++ GObject *resource_value = g_initable_new(type, NULL, NULL, "xml-node", node, NULL); ++ g_value_set_object(value, resource_value); ++ goto end; ++ } ++ ++ /* All other types require valid value_str */ ++ if (value_str == NULL) ++ return FALSE; ++ ++ if (G_TYPE_IS_ENUM(type)) { ++ int enum_value = ovirt_utils_genum_get_value(type, value_str, 0); ++ g_value_set_enum(value, enum_value); ++ goto end; ++ } ++ ++ switch(type) { ++ case G_TYPE_BOOLEAN: { ++ gboolean bool_value = ovirt_utils_boolean_from_string(value_str); ++ g_value_set_boolean(value, bool_value); ++ break; ++ } ++ case G_TYPE_UINT64: { ++ guint64 int64_value = g_ascii_strtoull(value_str, NULL, 0); ++ g_value_set_uint64(value, int64_value); ++ break; ++ } ++ default: { ++ g_warning("Unexpected type '%s' with value '%s'", g_type_name(type), value_str); ++ ret = FALSE; ++ } ++ } ++ ++end: ++ return ret; ++} ++ ++gboolean ++ovirt_rest_xml_node_parse(RestXmlNode *node, ++ GObject *object, ++ OvirtXmlElement *elements) ++{ ++ g_return_val_if_fail(G_IS_OBJECT(object), FALSE); ++ g_return_val_if_fail(elements != NULL, FALSE); ++ ++ for (;elements->xml_path != NULL; elements++) { ++ const char *value_str; ++ GValue value = { 0, }; ++ ++ value_str = ovirt_rest_xml_node_get_content_from_path(node, elements->xml_path); ++ ++ g_value_init(&value, elements->type); ++ if (_set_property_value_from_type(&value, elements->type, value_str, node)) ++ g_object_set_property(object, elements->prop_name, &value); ++ g_value_unset(&value); ++ } ++ ++ return TRUE; ++} ++ + + /* These 2 functions come from + * libvirt-glib/libvirt-gconfig/libvirt-gconfig-helpers.c +diff --git a/govirt/ovirt-utils.h b/govirt/ovirt-utils.h +index 3f43fc9..4fd4164 100644 +--- a/govirt/ovirt-utils.h ++++ b/govirt/ovirt-utils.h +@@ -27,10 +27,19 @@ + + G_BEGIN_DECLS + ++typedef struct _OvirtXmlElement OvirtXmlElement; ++struct _OvirtXmlElement ++{ ++ const char *prop_name; ++ GType type; ++ const char *xml_path; ++}; ++ + RestXmlNode *ovirt_rest_xml_node_from_call(RestProxyCall *call); + const char *ovirt_rest_xml_node_get_content(RestXmlNode *node, ...); +-const char *ovirt_rest_xml_node_get_content_from_path(RestXmlNode *node, +- const char *path); ++gboolean ovirt_rest_xml_node_parse(RestXmlNode *node, ++ GObject *object, ++ OvirtXmlElement *elements); + gboolean ovirt_utils_gerror_from_xml_fault(RestXmlNode *root, GError **error); + gboolean g_object_set_guint_property_from_xml(GObject *g_object, + RestXmlNode *node, diff --git a/SOURCES/0009-utils-Remove-unused-function-ovirt_rest_xml_node_get.patch b/SOURCES/0009-utils-Remove-unused-function-ovirt_rest_xml_node_get.patch new file mode 100644 index 0000000..cf2cb18 --- /dev/null +++ b/SOURCES/0009-utils-Remove-unused-function-ovirt_rest_xml_node_get.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Fri, 28 Apr 2017 17:16:31 -0300 +Subject: [PATCH] utils: Remove unused function + ovirt_rest_xml_node_get_content() + +Most uses were removed in dbf8dd85 "Add generic resource parser" and the +last use in 18d7c005 "storage-domain: Parse storage domain status" + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-utils.c | 19 ------------------- + govirt/ovirt-utils.h | 1 - + 2 files changed, 20 deletions(-) + +diff --git a/govirt/ovirt-utils.c b/govirt/ovirt-utils.c +index 44ea7da..951c693 100644 +--- a/govirt/ovirt-utils.c ++++ b/govirt/ovirt-utils.c +@@ -91,25 +91,6 @@ ovirt_rest_xml_node_get_content_from_path(RestXmlNode *node, const char *path) + return content; + } + +-G_GNUC_INTERNAL const char * +-ovirt_rest_xml_node_get_content(RestXmlNode *node, ...) +-{ +- va_list args; +- const char *content; +- +- g_return_val_if_fail(node != NULL, NULL); +- +- va_start(args, node); +- +- content = ovirt_rest_xml_node_get_content_va(node, &args, NULL); +- +- va_end(args); +- +- g_warn_if_fail(node != NULL); +- +- return content; +-} +- + static gboolean + _set_property_value_from_type(GValue *value, + GType type, +diff --git a/govirt/ovirt-utils.h b/govirt/ovirt-utils.h +index 4fd4164..e786311 100644 +--- a/govirt/ovirt-utils.h ++++ b/govirt/ovirt-utils.h +@@ -36,7 +36,6 @@ struct _OvirtXmlElement + }; + + RestXmlNode *ovirt_rest_xml_node_from_call(RestProxyCall *call); +-const char *ovirt_rest_xml_node_get_content(RestXmlNode *node, ...); + gboolean ovirt_rest_xml_node_parse(RestXmlNode *node, + GObject *object, + OvirtXmlElement *elements); diff --git a/SOURCES/0010-utils-Rename-ovirt_rest_xml_node_get_content_va-to-o.patch b/SOURCES/0010-utils-Rename-ovirt_rest_xml_node_get_content_va-to-o.patch new file mode 100644 index 0000000..54518f0 --- /dev/null +++ b/SOURCES/0010-utils-Rename-ovirt_rest_xml_node_get_content_va-to-o.patch @@ -0,0 +1,91 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Fri, 19 May 2017 00:31:46 -0300 +Subject: [PATCH] utils: Rename ovirt_rest_xml_node_get_content_va() to + ovirt_rest_xml_node_find() + +It is more useful to make this function retrieve a sub node and let the +caller do what it wants with that node, instead of returning the content +directly. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-utils.c | 59 +++++++++++++++++++------------------------- + 1 file changed, 26 insertions(+), 33 deletions(-) + +diff --git a/govirt/ovirt-utils.c b/govirt/ovirt-utils.c +index 951c693..c0541e9 100644 +--- a/govirt/ovirt-utils.c ++++ b/govirt/ovirt-utils.c +@@ -50,45 +50,38 @@ ovirt_rest_xml_node_from_call(RestProxyCall *call) + return node; + } + +-static const char * +-ovirt_rest_xml_node_get_content_va(RestXmlNode *node, +- va_list *args, +- GStrv str_array) +-{ +- g_return_val_if_fail((args != NULL) || (str_array != NULL), NULL); +- +- while (TRUE) { +- const char *node_name; +- +- if (args != NULL) { +- node_name = va_arg(*args, const char *); +- } else { +- node_name = *str_array; +- str_array++; +- } +- if (node_name == NULL) +- break; +- node = rest_xml_node_find(node, node_name); +- if (node == NULL) { +- g_debug("could not find XML node '%s'", node_name); +- return NULL; +- } +- } +- +- return node->content; +-} +- +-static const char * +-ovirt_rest_xml_node_get_content_from_path(RestXmlNode *node, const char *path) ++static RestXmlNode * ++ovirt_rest_xml_node_find(RestXmlNode *node, const char *path) + { ++ guint i; + GStrv pathv; +- const char *content; ++ ++ g_return_val_if_fail((path != NULL), NULL); + + pathv = g_strsplit(path, "/", -1); +- content = ovirt_rest_xml_node_get_content_va(node, NULL, pathv); ++ ++ for (i = 0; i < g_strv_length(pathv); ++i) { ++ node = rest_xml_node_find(node, pathv[i]); ++ if (node == NULL) { ++ g_debug("could not find XML node '%s'", pathv[i]); ++ break; ++ } ++ } ++ + g_strfreev(pathv); + +- return content; ++ return node; ++} ++ ++static const char * ++ovirt_rest_xml_node_get_content_from_path(RestXmlNode *node, const char *path) ++{ ++ node = ovirt_rest_xml_node_find(node, path); ++ ++ if (node == NULL) ++ return NULL; ++ ++ return node->content; + } + + static gboolean diff --git a/SOURCES/0011-utils-Retrieve-node-attributes-in-ovirt_resource_par.patch b/SOURCES/0011-utils-Retrieve-node-attributes-in-ovirt_resource_par.patch new file mode 100644 index 0000000..335d0ea --- /dev/null +++ b/SOURCES/0011-utils-Retrieve-node-attributes-in-ovirt_resource_par.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Thu, 18 May 2017 17:53:33 -0300 +Subject: [PATCH] utils: Retrieve node attributes in ovirt_resource_parse_xml() + +This commit adds a new field to the OvirtXmlElement struct, which is +used to retrieve an attribute from the xml node. It is optional, meaning +that, if not informed, the function will still retrieve the node +contents instead. + +We also introduce ovirt_rest_xml_node_get_attr_from_path() function, +to retrieve the given attribute value from the path below the node, much +similar to ovirt_rest_xml_node_get_content_from_path(). + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-utils.c | 15 ++++++++++++++- + govirt/ovirt-utils.h | 1 + + 2 files changed, 15 insertions(+), 1 deletion(-) + +diff --git a/govirt/ovirt-utils.c b/govirt/ovirt-utils.c +index c0541e9..b9b7c15 100644 +--- a/govirt/ovirt-utils.c ++++ b/govirt/ovirt-utils.c +@@ -84,6 +84,16 @@ ovirt_rest_xml_node_get_content_from_path(RestXmlNode *node, const char *path) + return node->content; + } + ++static const char * ++ovirt_rest_xml_node_get_attr_from_path(RestXmlNode *node, const char *path, const char *attr) ++{ ++ node = ovirt_rest_xml_node_find(node, path); ++ if (node == NULL) ++ return NULL; ++ ++ return rest_xml_node_get_attr(node, attr); ++} ++ + static gboolean + _set_property_value_from_type(GValue *value, + GType type, +@@ -141,7 +151,10 @@ ovirt_rest_xml_node_parse(RestXmlNode *node, + const char *value_str; + GValue value = { 0, }; + +- value_str = ovirt_rest_xml_node_get_content_from_path(node, elements->xml_path); ++ if (elements->xml_attr != NULL) ++ value_str = ovirt_rest_xml_node_get_attr_from_path(node, elements->xml_path, elements->xml_attr); ++ else ++ value_str = ovirt_rest_xml_node_get_content_from_path(node, elements->xml_path); + + g_value_init(&value, elements->type); + if (_set_property_value_from_type(&value, elements->type, value_str, node)) +diff --git a/govirt/ovirt-utils.h b/govirt/ovirt-utils.h +index e786311..545847a 100644 +--- a/govirt/ovirt-utils.h ++++ b/govirt/ovirt-utils.h +@@ -33,6 +33,7 @@ struct _OvirtXmlElement + const char *prop_name; + GType type; + const char *xml_path; ++ const char *xml_attr; /* if NULL, retrieve node content instead of attribute */ + }; + + RestXmlNode *ovirt_rest_xml_node_from_call(RestProxyCall *call); diff --git a/SOURCES/0012-utils-Support-G_TYPE_STRING-in-_set_property_value_f.patch b/SOURCES/0012-utils-Support-G_TYPE_STRING-in-_set_property_value_f.patch new file mode 100644 index 0000000..82a58ea --- /dev/null +++ b/SOURCES/0012-utils-Support-G_TYPE_STRING-in-_set_property_value_f.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Wed, 10 May 2017 15:46:27 -0300 +Subject: [PATCH] utils: Support G_TYPE_STRING in + _set_property_value_from_type() + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-utils.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/govirt/ovirt-utils.c b/govirt/ovirt-utils.c +index b9b7c15..fafb9ec 100644 +--- a/govirt/ovirt-utils.c ++++ b/govirt/ovirt-utils.c +@@ -124,6 +124,10 @@ _set_property_value_from_type(GValue *value, + g_value_set_boolean(value, bool_value); + break; + } ++ case G_TYPE_STRING: { ++ g_value_set_string(value, value_str); ++ break; ++ } + case G_TYPE_UINT64: { + guint64 int64_value = g_ascii_strtoull(value_str, NULL, 0); + g_value_set_uint64(value, int64_value); diff --git a/SOURCES/0013-utils-Support-G_TYPE_STRV-in-_set_property_value_fro.patch b/SOURCES/0013-utils-Support-G_TYPE_STRV-in-_set_property_value_fro.patch new file mode 100644 index 0000000..b3f50db --- /dev/null +++ b/SOURCES/0013-utils-Support-G_TYPE_STRV-in-_set_property_value_fro.patch @@ -0,0 +1,111 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Thu, 11 May 2017 17:31:43 -0300 +Subject: [PATCH] utils: Support G_TYPE_STRV in _set_property_value_from_type() + +Because user can require either the attribute or the node content, it +was necessary to change the function signature to receive both +parameters. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-utils.c | 63 ++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 55 insertions(+), 8 deletions(-) + +diff --git a/govirt/ovirt-utils.c b/govirt/ovirt-utils.c +index fafb9ec..a200e48 100644 +--- a/govirt/ovirt-utils.c ++++ b/govirt/ovirt-utils.c +@@ -94,20 +94,73 @@ ovirt_rest_xml_node_get_attr_from_path(RestXmlNode *node, const char *path, cons + return rest_xml_node_get_attr(node, attr); + } + ++static GStrv ++ovirt_rest_xml_node_get_str_array_from_path(RestXmlNode *node, const char *path, const char *attr) ++{ ++ GArray *array; ++ GHashTableIter iter; ++ gpointer sub_node; ++ ++ node = ovirt_rest_xml_node_find(node, path); ++ if (node == NULL) ++ return NULL; ++ ++ array = g_array_new(TRUE, FALSE, sizeof(gchar *)); ++ ++ g_hash_table_iter_init(&iter, node->children); ++ while (g_hash_table_iter_next(&iter, NULL, &sub_node)) { ++ const char *value; ++ char *array_value; ++ ++ node = (RestXmlNode *) sub_node; ++ ++ if (attr != NULL) ++ value = rest_xml_node_get_attr(node, attr); ++ else ++ value = node->content; ++ ++ if (value == NULL) { ++ g_warning("node %s%s is NULL", attr ? "attribute:" : "content", attr ? attr : "" ); ++ continue; ++ } ++ ++ array_value = g_strdup(value); ++ g_array_append_val(array, array_value); ++ } ++ ++ return (GStrv) g_array_free(array, FALSE); ++} ++ + static gboolean + _set_property_value_from_type(GValue *value, + GType type, +- const char *value_str, ++ const char *path, ++ const char *attr, + RestXmlNode *node) + { + gboolean ret = TRUE; ++ const char *value_str; + + if (g_type_is_a(type, OVIRT_TYPE_RESOURCE)) { + GObject *resource_value = g_initable_new(type, NULL, NULL, "xml-node", node, NULL); + g_value_set_object(value, resource_value); + goto end; ++ } else if (g_type_is_a(type, G_TYPE_STRV)) { ++ GStrv strv_value = ovirt_rest_xml_node_get_str_array_from_path(node, path, attr); ++ if (strv_value == NULL) { ++ ret = FALSE; ++ goto end; ++ } ++ ++ g_value_take_boxed(value, strv_value); ++ goto end; + } + ++ if (attr != NULL) ++ value_str = ovirt_rest_xml_node_get_attr_from_path(node, path, attr); ++ else ++ value_str = ovirt_rest_xml_node_get_content_from_path(node, path); ++ + /* All other types require valid value_str */ + if (value_str == NULL) + return FALSE; +@@ -152,16 +205,10 @@ ovirt_rest_xml_node_parse(RestXmlNode *node, + g_return_val_if_fail(elements != NULL, FALSE); + + for (;elements->xml_path != NULL; elements++) { +- const char *value_str; + GValue value = { 0, }; + +- if (elements->xml_attr != NULL) +- value_str = ovirt_rest_xml_node_get_attr_from_path(node, elements->xml_path, elements->xml_attr); +- else +- value_str = ovirt_rest_xml_node_get_content_from_path(node, elements->xml_path); +- + g_value_init(&value, elements->type); +- if (_set_property_value_from_type(&value, elements->type, value_str, node)) ++ if (_set_property_value_from_type(&value, elements->type, elements->xml_path, elements->xml_attr, node)) + g_object_set_property(object, elements->prop_name, &value); + g_value_unset(&value); + } diff --git a/SOURCES/0014-Introduce-auxiliary-function-ovirt_sub_collection_ne.patch b/SOURCES/0014-Introduce-auxiliary-function-ovirt_sub_collection_ne.patch new file mode 100644 index 0000000..d6d3363 --- /dev/null +++ b/SOURCES/0014-Introduce-auxiliary-function-ovirt_sub_collection_ne.patch @@ -0,0 +1,203 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Thu, 18 May 2017 16:45:37 -0300 +Subject: [PATCH] Introduce auxiliary function + ovirt_sub_collection_new_from_resource() + +This function eliminates duplication of code used to create a +subcollection from a resource. Users are updated accordingly. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-api.c | 50 +++++++++++-------------------- + govirt/ovirt-collection-private.h | 5 ++++ + govirt/ovirt-collection.c | 15 ++++++++++ + govirt/ovirt-storage-domain.c | 18 ++++------- + govirt/ovirt-vm.c | 18 ++++------- + 5 files changed, 50 insertions(+), 56 deletions(-) + +diff --git a/govirt/ovirt-api.c b/govirt/ovirt-api.c +index 001ee42..37c0935 100644 +--- a/govirt/ovirt-api.c ++++ b/govirt/ovirt-api.c +@@ -123,18 +123,14 @@ OvirtApi *ovirt_api_new(void) + */ + OvirtCollection *ovirt_api_get_vms(OvirtApi *api) + { +- const char *href; +- + g_return_val_if_fail(OVIRT_IS_API(api), NULL); + +- if (api->priv->vms != NULL) +- return api->priv->vms; +- +- href = ovirt_resource_get_sub_collection(OVIRT_RESOURCE(api), "vms"); +- if (href == NULL) +- return NULL; +- +- api->priv->vms = ovirt_collection_new(href, "vms", OVIRT_TYPE_VM, "vm"); ++ if (api->priv->vms == NULL) ++ api->priv->vms = ovirt_sub_collection_new_from_resource(OVIRT_RESOURCE(api), ++ "vms", ++ "vms", ++ OVIRT_TYPE_VM, ++ "vm"); + + return api->priv->vms; + } +@@ -151,18 +147,14 @@ OvirtCollection *ovirt_api_get_vms(OvirtApi *api) + */ + OvirtCollection *ovirt_api_get_vm_pools(OvirtApi *api) + { +- const char *href; +- + g_return_val_if_fail(OVIRT_IS_API(api), NULL); + +- if (api->priv->vm_pools != NULL) +- return api->priv->vm_pools; +- +- href = ovirt_resource_get_sub_collection(OVIRT_RESOURCE(api), "vmpools"); +- if (href == NULL) +- return NULL; +- +- api->priv->vm_pools = ovirt_collection_new(href, "vmpools", OVIRT_TYPE_VM_POOL, "vmpool"); ++ if (api->priv->vm_pools == NULL) ++ api->priv->vm_pools = ovirt_sub_collection_new_from_resource(OVIRT_RESOURCE(api), ++ "vmpools", ++ "vmpools", ++ OVIRT_TYPE_VM_POOL, ++ "vmpool"); + + return api->priv->vm_pools; + } +@@ -180,20 +172,14 @@ OvirtCollection *ovirt_api_get_vm_pools(OvirtApi *api) + */ + OvirtCollection *ovirt_api_get_storage_domains(OvirtApi *api) + { +- const char *href; +- + g_return_val_if_fail(OVIRT_IS_API(api), NULL); + +- if (api->priv->storage_domains != NULL) +- return api->priv->storage_domains; +- +- href = ovirt_resource_get_sub_collection(OVIRT_RESOURCE(api), "storagedomains"); +- if (href == NULL) +- return NULL; +- +- api->priv->storage_domains = ovirt_collection_new(href, "storage_domains", +- OVIRT_TYPE_STORAGE_DOMAIN, +- "storage_domain"); ++ if (api->priv->storage_domains == NULL) ++ api->priv->storage_domains = ovirt_sub_collection_new_from_resource(OVIRT_RESOURCE(api), ++ "storagedomains", ++ "storage_domains", ++ OVIRT_TYPE_STORAGE_DOMAIN, ++ "storage_domain"); + + return api->priv->storage_domains; + } +diff --git a/govirt/ovirt-collection-private.h b/govirt/ovirt-collection-private.h +index 5bc294f..d955fc6 100644 +--- a/govirt/ovirt-collection-private.h ++++ b/govirt/ovirt-collection-private.h +@@ -41,6 +41,11 @@ OvirtCollection *ovirt_collection_new_from_xml(RestXmlNode *root_node, + GType resource_type, + const char *resource_name, + GError **error); ++OvirtCollection *ovirt_sub_collection_new_from_resource(OvirtResource *resource, ++ const char *href, ++ const char *collection_name, ++ GType resource_type, ++ const char *resource_name); + + G_END_DECLS + +diff --git a/govirt/ovirt-collection.c b/govirt/ovirt-collection.c +index a3b0f3f..6ec1c6e 100644 +--- a/govirt/ovirt-collection.c ++++ b/govirt/ovirt-collection.c +@@ -344,6 +344,21 @@ OvirtCollection *ovirt_collection_new_from_xml(RestXmlNode *root_node, + } + + ++OvirtCollection *ovirt_sub_collection_new_from_resource(OvirtResource *resource, ++ const char *href, ++ const char *collection_name, ++ GType resource_type, ++ const char *resource_name) ++{ ++ const char *link = ovirt_resource_get_sub_collection(resource, href); ++ ++ if (link == NULL) ++ return NULL; ++ ++ return ovirt_collection_new(link, collection_name, resource_type, resource_name); ++} ++ ++ + /** + * ovirt_collection_fetch: + * @collection: a #OvirtCollection +diff --git a/govirt/ovirt-storage-domain.c b/govirt/ovirt-storage-domain.c +index 0582203..38c4a62 100644 +--- a/govirt/ovirt-storage-domain.c ++++ b/govirt/ovirt-storage-domain.c +@@ -317,20 +317,14 @@ OvirtStorageDomain *ovirt_storage_domain_new(void) + */ + OvirtCollection *ovirt_storage_domain_get_files(OvirtStorageDomain *domain) + { +- const char *href; +- + g_return_val_if_fail(OVIRT_IS_STORAGE_DOMAIN(domain), NULL); + +- if (domain->priv->files != NULL) +- return domain->priv->files; +- +- href = ovirt_resource_get_sub_collection(OVIRT_RESOURCE(domain), "files"); +- if (href == NULL) +- return NULL; +- +- domain->priv->files = ovirt_collection_new(href, "files", +- OVIRT_TYPE_RESOURCE, +- "file"); ++ if (domain->priv->files == NULL) ++ domain->priv->files = ovirt_sub_collection_new_from_resource(OVIRT_RESOURCE(domain), ++ "files", ++ "files", ++ OVIRT_TYPE_RESOURCE, ++ "file"); + + return domain->priv->files; + } +diff --git a/govirt/ovirt-vm.c b/govirt/ovirt-vm.c +index 9a07c2f..3d64649 100644 +--- a/govirt/ovirt-vm.c ++++ b/govirt/ovirt-vm.c +@@ -329,20 +329,14 @@ gboolean ovirt_vm_refresh_finish(OvirtVm *vm, + */ + OvirtCollection *ovirt_vm_get_cdroms(OvirtVm *vm) + { +- const char *href; +- + g_return_val_if_fail(OVIRT_IS_VM(vm), NULL); + +- if (vm->priv->cdroms != NULL) +- return vm->priv->cdroms; +- +- href = ovirt_resource_get_sub_collection(OVIRT_RESOURCE(vm), "cdroms"); +- if (href == NULL) +- return NULL; +- +- vm->priv->cdroms = ovirt_collection_new(href, "cdroms", +- OVIRT_TYPE_CDROM, +- "cdrom"); ++ if (vm->priv->cdroms == NULL) ++ vm->priv->cdroms = ovirt_sub_collection_new_from_resource(OVIRT_RESOURCE(vm), ++ "cdroms", ++ "cdroms", ++ OVIRT_TYPE_CDROM, ++ "cdrom"); + + return vm->priv->cdroms; + } diff --git a/SOURCES/0015-New-API-functions-to-enable-search-queries-of-collec.patch b/SOURCES/0015-New-API-functions-to-enable-search-queries-of-collec.patch new file mode 100644 index 0000000..be369a2 --- /dev/null +++ b/SOURCES/0015-New-API-functions-to-enable-search-queries-of-collec.patch @@ -0,0 +1,199 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Fri, 7 Apr 2017 16:25:46 -0300 +Subject: [PATCH] New API functions to enable search queries of collections + +Currently it is not possible to specify search query to optimize the +collections returned by the REST API. It is necessary to retrieve and +parse the full results and then iterate over the data to find what you +are really looking for. + +This patch introduces the search functionality for the APIs that are +currently supported, improving bandwidth usage and also the need to +iterate over the results. + +Like the previous patch, this patch also introduces an auxiliary +function in ovirt-collection to retrieve a sub-collection with a search +query. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/govirt.sym | 4 +++ + govirt/ovirt-api.c | 60 +++++++++++++++++++++++++++++++ + govirt/ovirt-api.h | 3 ++ + govirt/ovirt-collection-private.h | 6 ++++ + govirt/ovirt-collection.c | 31 ++++++++++++++++ + 5 files changed, 104 insertions(+) + +diff --git a/govirt/govirt.sym b/govirt/govirt.sym +index 8371779..d02e77f 100644 +--- a/govirt/govirt.sym ++++ b/govirt/govirt.sym +@@ -105,6 +105,10 @@ GOVIRT_0.3.2 { + ovirt_resource_delete; + ovirt_resource_delete_async; + ovirt_resource_delete_finish; ++ ++ ovirt_api_search_storage_domains; ++ ovirt_api_search_vms; ++ ovirt_api_search_vm_pools; + } GOVIRT_0.3.1; + + GOVIRT_0.3.4 { +diff --git a/govirt/ovirt-api.c b/govirt/ovirt-api.c +index 37c0935..ca3fdcf 100644 +--- a/govirt/ovirt-api.c ++++ b/govirt/ovirt-api.c +@@ -135,6 +135,26 @@ OvirtCollection *ovirt_api_get_vms(OvirtApi *api) + return api->priv->vms; + } + ++/** ++ * ovirt_api_search_vms: ++ * @api: a #OvirtApi ++ * @query: search query ++ * ++ * Return value: (transfer full): ++ */ ++OvirtCollection *ovirt_api_search_vms(OvirtApi *api, const char *query) ++{ ++ g_return_val_if_fail(OVIRT_IS_API(api), NULL); ++ ++ return ovirt_sub_collection_new_from_resource_search(OVIRT_RESOURCE(api), ++ "vms/search", ++ "vms", ++ OVIRT_TYPE_VM, ++ "vm", ++ query); ++} ++ ++ + /** + * ovirt_api_get_vm_pools: + * @api: a #OvirtApi +@@ -160,6 +180,26 @@ OvirtCollection *ovirt_api_get_vm_pools(OvirtApi *api) + } + + ++/** ++ * ovirt_api_search_vm_pools: ++ * @api: a #OvirtApi ++ * @query: search query ++ * ++ * Return value: (transfer full): ++ */ ++OvirtCollection *ovirt_api_search_vm_pools(OvirtApi *api, const char *query) ++{ ++ g_return_val_if_fail(OVIRT_IS_API(api), NULL); ++ ++ return ovirt_sub_collection_new_from_resource_search(OVIRT_RESOURCE(api), ++ "vmpools/search", ++ "vmpools", ++ OVIRT_TYPE_VM_POOL, ++ "vmpool", ++ query); ++} ++ ++ + /** + * ovirt_api_get_storage_domains: + * @api: a #OvirtApi +@@ -183,3 +223,23 @@ OvirtCollection *ovirt_api_get_storage_domains(OvirtApi *api) + + return api->priv->storage_domains; + } ++ ++ ++/** ++ * ovirt_api_search_storage_domains: ++ * @api: a #OvirtApi ++ * @query: search query ++ * ++ * Return value: (transfer full): ++ */ ++OvirtCollection *ovirt_api_search_storage_domains(OvirtApi *api, const char *query) ++{ ++ g_return_val_if_fail(OVIRT_IS_API(api), NULL); ++ ++ return ovirt_sub_collection_new_from_resource_search(OVIRT_RESOURCE(api), ++ "storagedomains/search", ++ "storage_domains", ++ OVIRT_TYPE_STORAGE_DOMAIN, ++ "storage_domain", ++ query); ++} +diff --git a/govirt/ovirt-api.h b/govirt/ovirt-api.h +index 5f0d4e9..1bf6c02 100644 +--- a/govirt/ovirt-api.h ++++ b/govirt/ovirt-api.h +@@ -62,8 +62,11 @@ GType ovirt_api_get_type(void); + OvirtApi *ovirt_api_new(void); + + OvirtCollection *ovirt_api_get_storage_domains(OvirtApi *api); ++OvirtCollection *ovirt_api_search_storage_domains(OvirtApi *api, const char *query); + OvirtCollection *ovirt_api_get_vms(OvirtApi *api); ++OvirtCollection *ovirt_api_search_vms(OvirtApi *api, const char *query); + OvirtCollection *ovirt_api_get_vm_pools(OvirtApi *api); ++OvirtCollection *ovirt_api_search_vm_pools(OvirtApi *api, const char *query); + + G_END_DECLS + +diff --git a/govirt/ovirt-collection-private.h b/govirt/ovirt-collection-private.h +index d955fc6..cf7e603 100644 +--- a/govirt/ovirt-collection-private.h ++++ b/govirt/ovirt-collection-private.h +@@ -46,6 +46,12 @@ OvirtCollection *ovirt_sub_collection_new_from_resource(OvirtResource *resource, + const char *collection_name, + GType resource_type, + const char *resource_name); ++OvirtCollection *ovirt_sub_collection_new_from_resource_search(OvirtResource *resource, ++ const char *href, ++ const char *collection_name, ++ GType resource_type, ++ const char *resource_name, ++ const char *query); + + G_END_DECLS + +diff --git a/govirt/ovirt-collection.c b/govirt/ovirt-collection.c +index 6ec1c6e..d36d750 100644 +--- a/govirt/ovirt-collection.c ++++ b/govirt/ovirt-collection.c +@@ -358,6 +358,37 @@ OvirtCollection *ovirt_sub_collection_new_from_resource(OvirtResource *resource, + return ovirt_collection_new(link, collection_name, resource_type, resource_name); + } + ++OvirtCollection *ovirt_sub_collection_new_from_resource_search(OvirtResource *resource, ++ const char *href, ++ const char *collection_name, ++ GType resource_type, ++ const char *resource_name, ++ const char *query) ++{ ++ const char *link; ++ char *substr; ++ gchar *link_query, *escaped_query; ++ OvirtCollection *collection; ++ ++ link = ovirt_resource_get_sub_collection(resource, href); ++ if (link == NULL) ++ return NULL; ++ ++ /* link is will be something like "/ovirt-engine/api/vms?search={query}", so ++ * we need to strip out {query} substring. ++ */ ++ substr = g_strrstr(link, "{query}"); ++ if (substr != NULL) ++ *substr = '\0'; ++ ++ escaped_query = g_uri_escape_string(query, NULL, FALSE); ++ link_query = g_strconcat(link, escaped_query, NULL); ++ collection = ovirt_collection_new(link_query, collection_name, resource_type, resource_name); ++ g_free(escaped_query); ++ g_free(link_query); ++ ++ return collection; ++} + + /** + * ovirt_collection_fetch: diff --git a/SOURCES/0016-Introduce-ovirt_resource_new-functions.patch b/SOURCES/0016-Introduce-ovirt_resource_new-functions.patch new file mode 100644 index 0000000..6f945b8 --- /dev/null +++ b/SOURCES/0016-Introduce-ovirt_resource_new-functions.patch @@ -0,0 +1,85 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Thu, 13 Jul 2017 16:56:34 -0300 +Subject: [PATCH] Introduce ovirt_resource_new*() functions + +These functions should be used to replace usage of g_initable_new() +around the codebase, as it avoids code duplication by combining all +different ways of creating a resource in a single function. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-resource-private.h | 4 +++ + govirt/ovirt-resource.c | 47 +++++++++++++++++++++++++++++++++ + 2 files changed, 51 insertions(+) + +diff --git a/govirt/ovirt-resource-private.h b/govirt/ovirt-resource-private.h +index ff4e705..ef47557 100644 +--- a/govirt/ovirt-resource-private.h ++++ b/govirt/ovirt-resource-private.h +@@ -27,6 +27,10 @@ + + G_BEGIN_DECLS + ++OvirtResource *ovirt_resource_new(GType type); ++OvirtResource *ovirt_resource_new_from_id(GType type, const char *id, const char *href); ++OvirtResource *ovirt_resource_new_from_xml(GType type, RestXmlNode *node, GError **error); ++ + const char *ovirt_resource_get_action(OvirtResource *resource, + const char *action); + char *ovirt_resource_to_xml(OvirtResource *resource); +diff --git a/govirt/ovirt-resource.c b/govirt/ovirt-resource.c +index 7f79ab7..1413a77 100644 +--- a/govirt/ovirt-resource.c ++++ b/govirt/ovirt-resource.c +@@ -1065,3 +1065,50 @@ gboolean ovirt_resource_delete_finish(OvirtResource *resource, + + return ovirt_rest_call_finish(result, err); + } ++ ++ ++static OvirtResource *ovirt_resource_new_valist(GType type, GError **error, const char *prop_name, ...) ++{ ++ gpointer resource; ++ va_list var_args; ++ GError *local_error = NULL; ++ ++ g_return_val_if_fail(g_type_is_a(type, OVIRT_TYPE_RESOURCE), NULL); ++ ++ va_start(var_args, prop_name); ++ resource = g_initable_new_valist(type, prop_name, var_args, NULL, &local_error); ++ va_end(var_args); ++ ++ if (local_error != NULL) { ++ g_warning("Failed to create resource of type %s: %s", g_type_name(type), local_error->message); ++ g_propagate_error(error, local_error); ++ } ++ ++ return OVIRT_RESOURCE(resource); ++} ++ ++ ++G_GNUC_INTERNAL ++OvirtResource *ovirt_resource_new(GType type) ++{ ++ return ovirt_resource_new_valist(type, NULL, NULL); ++} ++ ++ ++G_GNUC_INTERNAL ++OvirtResource *ovirt_resource_new_from_id(GType type, const char *id, const char *href) ++{ ++ g_return_val_if_fail(id != NULL, NULL); ++ g_return_val_if_fail(href != NULL, NULL); ++ ++ return ovirt_resource_new_valist(type, NULL, "guid", id, "href", href, NULL); ++} ++ ++ ++G_GNUC_INTERNAL ++OvirtResource *ovirt_resource_new_from_xml(GType type, RestXmlNode *node, GError **error) ++{ ++ g_return_val_if_fail(node != NULL, NULL); ++ ++ return ovirt_resource_new_valist(type, error, "xml-node", node, NULL); ++} diff --git a/SOURCES/0017-Use-ovirt_resource_new-functions-instead-of-g_initab.patch b/SOURCES/0017-Use-ovirt_resource_new-functions-instead-of-g_initab.patch new file mode 100644 index 0000000..6b90155 --- /dev/null +++ b/SOURCES/0017-Use-ovirt_resource_new-functions-instead-of-g_initab.patch @@ -0,0 +1,144 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Thu, 13 Jul 2017 16:58:28 -0300 +Subject: [PATCH] Use ovirt_resource_new* functions instead of g_initable_new + +This patch also fix some functions that were supposed to be tagged as +G_GNUC_INTERNAL. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-api.c | 8 +++++--- + govirt/ovirt-collection.c | 4 +--- + govirt/ovirt-storage-domain.c | 11 ++--------- + govirt/ovirt-utils.c | 3 ++- + govirt/ovirt-vm-pool.c | 3 ++- + govirt/ovirt-vm.c | 8 +++++--- + 6 files changed, 17 insertions(+), 20 deletions(-) + +diff --git a/govirt/ovirt-api.c b/govirt/ovirt-api.c +index ca3fdcf..93dc3d5 100644 +--- a/govirt/ovirt-api.c ++++ b/govirt/ovirt-api.c +@@ -98,16 +98,18 @@ static void ovirt_api_init(G_GNUC_UNUSED OvirtApi *api) + api->priv = OVIRT_API_GET_PRIVATE(api); + } + ++G_GNUC_INTERNAL + OvirtApi *ovirt_api_new_from_xml(RestXmlNode *node, GError **error) + { +- return OVIRT_API(g_initable_new(OVIRT_TYPE_API, NULL, error, +- "xml-node", node, NULL)); ++ OvirtResource *api = ovirt_resource_new_from_xml(OVIRT_TYPE_API, node, error); ++ return OVIRT_API(api); + } + + + OvirtApi *ovirt_api_new(void) + { +- return OVIRT_API(g_initable_new(OVIRT_TYPE_API, NULL, NULL, NULL)); ++ OvirtResource *api = ovirt_resource_new(OVIRT_TYPE_API); ++ return OVIRT_API(api); + } + + +diff --git a/govirt/ovirt-collection.c b/govirt/ovirt-collection.c +index d36d750..8008903 100644 +--- a/govirt/ovirt-collection.c ++++ b/govirt/ovirt-collection.c +@@ -235,9 +235,7 @@ ovirt_collection_new_resource_from_xml(OvirtCollection *collection, + RestXmlNode *node, + GError **error) + { +- return OVIRT_RESOURCE(g_initable_new(collection->priv->resource_type, +- NULL, error, +- "xml-node", node , NULL)); ++ return ovirt_resource_new_from_xml(collection->priv->resource_type, node, error); + } + + +diff --git a/govirt/ovirt-storage-domain.c b/govirt/ovirt-storage-domain.c +index 38c4a62..e255565 100644 +--- a/govirt/ovirt-storage-domain.c ++++ b/govirt/ovirt-storage-domain.c +@@ -285,20 +285,13 @@ G_GNUC_INTERNAL + OvirtStorageDomain *ovirt_storage_domain_new_from_xml(RestXmlNode *node, + GError **error) + { +- GObject *domain; +- +- domain = g_initable_new(OVIRT_TYPE_STORAGE_DOMAIN, NULL, error, +- "xml-node", node, NULL); +- ++ OvirtResource *domain = ovirt_resource_new_from_xml(OVIRT_TYPE_STORAGE_DOMAIN, node, error); + return OVIRT_STORAGE_DOMAIN(domain); + } + + OvirtStorageDomain *ovirt_storage_domain_new(void) + { +- GObject *domain; +- +- domain = g_initable_new(OVIRT_TYPE_STORAGE_DOMAIN, NULL, NULL, NULL); +- ++ OvirtResource *domain = ovirt_resource_new(OVIRT_TYPE_STORAGE_DOMAIN); + return OVIRT_STORAGE_DOMAIN(domain); + } + +diff --git a/govirt/ovirt-utils.c b/govirt/ovirt-utils.c +index a200e48..1898862 100644 +--- a/govirt/ovirt-utils.c ++++ b/govirt/ovirt-utils.c +@@ -32,6 +32,7 @@ + + #include "ovirt-error.h" + #include "ovirt-resource.h" ++#include "ovirt-resource-private.h" + + RestXmlNode * + ovirt_rest_xml_node_from_call(RestProxyCall *call) +@@ -142,7 +143,7 @@ _set_property_value_from_type(GValue *value, + const char *value_str; + + if (g_type_is_a(type, OVIRT_TYPE_RESOURCE)) { +- GObject *resource_value = g_initable_new(type, NULL, NULL, "xml-node", node, NULL); ++ OvirtResource *resource_value = ovirt_resource_new_from_xml(type, node, NULL); + g_value_set_object(value, resource_value); + goto end; + } else if (g_type_is_a(type, G_TYPE_STRV)) { +diff --git a/govirt/ovirt-vm-pool.c b/govirt/ovirt-vm-pool.c +index 3187a8c..9d0d742 100644 +--- a/govirt/ovirt-vm-pool.c ++++ b/govirt/ovirt-vm-pool.c +@@ -168,7 +168,8 @@ static void ovirt_vm_pool_init(G_GNUC_UNUSED OvirtVmPool *vm_pool) + + OvirtVmPool *ovirt_vm_pool_new(void) + { +- return OVIRT_VM_POOL(g_initable_new(OVIRT_TYPE_VM_POOL, NULL, NULL, NULL)); ++ OvirtResource *vm_pool = ovirt_resource_new(OVIRT_TYPE_VM_POOL); ++ return OVIRT_VM_POOL(vm_pool); + } + + +diff --git a/govirt/ovirt-vm.c b/govirt/ovirt-vm.c +index 3d64649..806b5f3 100644 +--- a/govirt/ovirt-vm.c ++++ b/govirt/ovirt-vm.c +@@ -163,15 +163,17 @@ static void ovirt_vm_init(G_GNUC_UNUSED OvirtVm *vm) + vm->priv = OVIRT_VM_GET_PRIVATE(vm); + } + ++G_GNUC_INTERNAL + OvirtVm *ovirt_vm_new_from_xml(RestXmlNode *node, GError **error) + { +- return OVIRT_VM(g_initable_new(OVIRT_TYPE_VM, NULL, error, +- "xml-node", node, NULL)); ++ OvirtResource *vm = ovirt_resource_new_from_xml(OVIRT_TYPE_VM, node, error); ++ return OVIRT_VM(vm); + } + + OvirtVm *ovirt_vm_new(void) + { +- return OVIRT_VM(g_initable_new(OVIRT_TYPE_VM, NULL, NULL, NULL)); ++ OvirtResource *vm = ovirt_resource_new(OVIRT_TYPE_VM); ++ return OVIRT_VM(vm); + } diff --git a/SOURCES/0018-Move-resource-type-definitions-to-ovirt-types.h.patch b/SOURCES/0018-Move-resource-type-definitions-to-ovirt-types.h.patch new file mode 100644 index 0000000..f7be60b --- /dev/null +++ b/SOURCES/0018-Move-resource-type-definitions-to-ovirt-types.h.patch @@ -0,0 +1,135 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Thu, 13 Jul 2017 16:43:53 -0300 +Subject: [PATCH] Move resource type definitions to ovirt-types.h + +With recently added ovirt_resource_new* functions, it is now possible to +create any type of resource, being only necessary to pass the type as +argument. + +In order to avoid interdependencies between objects, we need a common +place for definition of the resource types. For instance, it should be +possible to access a OvirtHost from a OvirtVm and vice-versa. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-api.h | 1 - + govirt/ovirt-cdrom.h | 1 - + govirt/ovirt-collection.h | 1 - + govirt/ovirt-storage-domain.h | 1 - + govirt/ovirt-types.h | 7 +++++++ + govirt/ovirt-vm-display.h | 2 +- + govirt/ovirt-vm-pool.h | 1 - + govirt/ovirt-vm.h | 1 - + 8 files changed, 8 insertions(+), 7 deletions(-) + +diff --git a/govirt/ovirt-api.h b/govirt/ovirt-api.h +index 1bf6c02..d511d70 100644 +--- a/govirt/ovirt-api.h ++++ b/govirt/ovirt-api.h +@@ -37,7 +37,6 @@ G_BEGIN_DECLS + #define OVIRT_IS_API_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OVIRT_TYPE_API)) + #define OVIRT_API_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OVIRT_TYPE_API, OvirtApiClass)) + +-typedef struct _OvirtApi OvirtApi; + typedef struct _OvirtApiPrivate OvirtApiPrivate; + typedef struct _OvirtApiClass OvirtApiClass; + +diff --git a/govirt/ovirt-cdrom.h b/govirt/ovirt-cdrom.h +index a268d01..a43d85d 100644 +--- a/govirt/ovirt-cdrom.h ++++ b/govirt/ovirt-cdrom.h +@@ -36,7 +36,6 @@ G_BEGIN_DECLS + #define OVIRT_IS_CDROM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OVIRT_TYPE_CDROM)) + #define OVIRT_CDROM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OVIRT_TYPE_CDROM, OvirtCdromClass)) + +-typedef struct _OvirtCdrom OvirtCdrom; + typedef struct _OvirtCdromPrivate OvirtCdromPrivate; + typedef struct _OvirtCdromClass OvirtCdromClass; + +diff --git a/govirt/ovirt-collection.h b/govirt/ovirt-collection.h +index b41d269..af630e1 100644 +--- a/govirt/ovirt-collection.h ++++ b/govirt/ovirt-collection.h +@@ -36,7 +36,6 @@ G_BEGIN_DECLS + #define OVIRT_IS_COLLECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OVIRT_TYPE_COLLECTION)) + #define OVIRT_COLLECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OVIRT_TYPE_COLLECTION, OvirtCollectionClass)) + +-typedef struct _OvirtCollection OvirtCollection; + typedef struct _OvirtCollectionPrivate OvirtCollectionPrivate; + typedef struct _OvirtCollectionClass OvirtCollectionClass; + +diff --git a/govirt/ovirt-storage-domain.h b/govirt/ovirt-storage-domain.h +index 79f1741..dd7b593 100644 +--- a/govirt/ovirt-storage-domain.h ++++ b/govirt/ovirt-storage-domain.h +@@ -61,7 +61,6 @@ typedef enum { + OVIRT_STORAGE_DOMAIN_TYPE_IMAGE, + } OvirtStorageDomainType; + +-typedef struct _OvirtStorageDomain OvirtStorageDomain; + typedef struct _OvirtStorageDomainPrivate OvirtStorageDomainPrivate; + typedef struct _OvirtStorageDomainClass OvirtStorageDomainClass; + +diff --git a/govirt/ovirt-types.h b/govirt/ovirt-types.h +index 6e83368..c89521b 100644 +--- a/govirt/ovirt-types.h ++++ b/govirt/ovirt-types.h +@@ -25,7 +25,14 @@ + + G_BEGIN_DECLS + ++typedef struct _OvirtApi OvirtApi; ++typedef struct _OvirtCdrom OvirtCdrom; ++typedef struct _OvirtCollection OvirtCollection; + typedef struct _OvirtProxy OvirtProxy; ++typedef struct _OvirtStorageDomain OvirtStorageDomain; ++typedef struct _OvirtVmDisplay OvirtVmDisplay; ++typedef struct _OvirtVmPool OvirtVmPool; ++typedef struct _OvirtVm OvirtVm; + + G_END_DECLS + +diff --git a/govirt/ovirt-vm-display.h b/govirt/ovirt-vm-display.h +index 2b8a86d..f7eb310 100644 +--- a/govirt/ovirt-vm-display.h ++++ b/govirt/ovirt-vm-display.h +@@ -23,6 +23,7 @@ + #define __OVIRT_VM_DISPLAY_H__ + + #include ++#include + + G_BEGIN_DECLS + +@@ -33,7 +34,6 @@ G_BEGIN_DECLS + #define OVIRT_IS_VM_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OVIRT_TYPE_VM_DISPLAY)) + #define OVIRT_VM_DISPLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OVIRT_TYPE_VM_DISPLAY, OvirtVmDisplayClass)) + +-typedef struct _OvirtVmDisplay OvirtVmDisplay; + typedef struct _OvirtVmDisplayPrivate OvirtVmDisplayPrivate; + typedef struct _OvirtVmDisplayClass OvirtVmDisplayClass; + +diff --git a/govirt/ovirt-vm-pool.h b/govirt/ovirt-vm-pool.h +index ee2f55c..10e7be7 100644 +--- a/govirt/ovirt-vm-pool.h ++++ b/govirt/ovirt-vm-pool.h +@@ -35,7 +35,6 @@ G_BEGIN_DECLS + #define OVIRT_IS_VM_POOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OVIRT_TYPE_VM_POOL)) + #define OVIRT_VM_POOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OVIRT_TYPE_VM_POOL, OvirtVmPoolClass)) + +-typedef struct _OvirtVmPool OvirtVmPool; + typedef struct _OvirtVmPoolPrivate OvirtVmPoolPrivate; + typedef struct _OvirtVmPoolClass OvirtVmPoolClass; + +diff --git a/govirt/ovirt-vm.h b/govirt/ovirt-vm.h +index 10910e3..1e6c7ad 100644 +--- a/govirt/ovirt-vm.h ++++ b/govirt/ovirt-vm.h +@@ -41,7 +41,6 @@ G_BEGIN_DECLS + #define OVIRT_IS_VM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OVIRT_TYPE_VM)) + #define OVIRT_VM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OVIRT_TYPE_VM, OvirtVmClass)) + +-typedef struct _OvirtVm OvirtVm; + typedef struct _OvirtVmPrivate OvirtVmPrivate; + typedef struct _OvirtVmClass OvirtVmClass; diff --git a/SOURCES/0019-Initial-support-for-hosts.patch b/SOURCES/0019-Initial-support-for-hosts.patch new file mode 100644 index 0000000..31c4375 --- /dev/null +++ b/SOURCES/0019-Initial-support-for-hosts.patch @@ -0,0 +1,515 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Tue, 11 Apr 2017 21:47:44 -0300 +Subject: [PATCH] Initial support for hosts + +At the moment, we only care about the information about the cluster the +host is part of, and the list of the vms associated with it. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/Makefile.am | 3 + + govirt/govirt-private.h | 1 + + govirt/govirt.sym | 11 ++ + govirt/ovirt-api.c | 47 ++++++++ + govirt/ovirt-api.h | 2 + + govirt/ovirt-host-private.h | 37 +++++++ + govirt/ovirt-host.c | 214 ++++++++++++++++++++++++++++++++++++ + govirt/ovirt-host.h | 66 +++++++++++ + govirt/ovirt-types.h | 1 + + 9 files changed, 382 insertions(+) + create mode 100644 govirt/ovirt-host-private.h + create mode 100644 govirt/ovirt-host.c + create mode 100644 govirt/ovirt-host.h + +diff --git a/govirt/Makefile.am b/govirt/Makefile.am +index e905f1f..c62a1d6 100644 +--- a/govirt/Makefile.am ++++ b/govirt/Makefile.am +@@ -21,6 +21,7 @@ libgovirt_la_HEADERS = \ + ovirt-cdrom.h \ + ovirt-collection.h \ + ovirt-error.h \ ++ ovirt-host.h \ + ovirt-options.h \ + ovirt-proxy.h \ + ovirt-resource.h \ +@@ -38,6 +39,7 @@ noinst_HEADERS = \ + ovirt-action-rest-call.h \ + ovirt-api-private.h \ + ovirt-collection-private.h \ ++ ovirt-host-private.h \ + ovirt-proxy-private.h \ + ovirt-resource-private.h \ + ovirt-rest-call.h \ +@@ -54,6 +56,7 @@ libgovirt_la_SOURCES = \ + ovirt-cdrom.c \ + ovirt-collection.c \ + ovirt-error.c \ ++ ovirt-host.c \ + ovirt-options.c \ + ovirt-proxy.c \ + ovirt-proxy-deprecated.c \ +diff --git a/govirt/govirt-private.h b/govirt/govirt-private.h +index 972ebac..b51feb3 100644 +--- a/govirt/govirt-private.h ++++ b/govirt/govirt-private.h +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + #include + #include +diff --git a/govirt/govirt.sym b/govirt/govirt.sym +index d02e77f..6dc8159 100644 +--- a/govirt/govirt.sym ++++ b/govirt/govirt.sym +@@ -109,6 +109,17 @@ GOVIRT_0.3.2 { + ovirt_api_search_storage_domains; + ovirt_api_search_vms; + ovirt_api_search_vm_pools; ++ ++ ovirt_api_get_hosts; ++ ++ ovirt_api_search_hosts; ++ ovirt_api_search_storage_domains; ++ ovirt_api_search_vms; ++ ovirt_api_search_vm_pools; ++ ++ ovirt_host_get_type; ++ ovirt_host_get_vms; ++ ovirt_host_new; + } GOVIRT_0.3.1; + + GOVIRT_0.3.4 { +diff --git a/govirt/ovirt-api.c b/govirt/ovirt-api.c +index 93dc3d5..fef04ba 100644 +--- a/govirt/ovirt-api.c ++++ b/govirt/ovirt-api.c +@@ -41,6 +41,7 @@ + + + struct _OvirtApiPrivate { ++ OvirtCollection *hosts; + OvirtCollection *storage_domains; + OvirtCollection *vms; + OvirtCollection *vm_pools; +@@ -73,6 +74,7 @@ static void ovirt_api_dispose(GObject *object) + { + OvirtApi *api = OVIRT_API(object); + ++ g_clear_object(&api->priv->hosts); + g_clear_object(&api->priv->storage_domains); + g_clear_object(&api->priv->vms); + g_clear_object(&api->priv->vm_pools); +@@ -245,3 +247,48 @@ OvirtCollection *ovirt_api_search_storage_domains(OvirtApi *api, const char *que + "storage_domain", + query); + } ++ ++ ++/** ++ * ovirt_api_get_hosts: ++ * @api: a #OvirtApi ++ * ++ * This method does not initiate any network activity, the collection ++ * must be fetched with ovirt_collection_fetch() before having up-to-date ++ * content. ++ * ++ * Return value: (transfer none): ++ */ ++OvirtCollection *ovirt_api_get_hosts(OvirtApi *api) ++{ ++ g_return_val_if_fail(OVIRT_IS_API(api), NULL); ++ ++ if (api->priv->hosts == NULL) ++ api->priv->hosts = ovirt_sub_collection_new_from_resource(OVIRT_RESOURCE(api), ++ "hosts", ++ "hosts", ++ OVIRT_TYPE_HOST, ++ "host"); ++ ++ return api->priv->hosts; ++} ++ ++ ++/** ++ * ovirt_api_search_hosts: ++ * @api: a #OvirtApi ++ * @query: search query ++ * ++ * Return value: (transfer none): ++ */ ++OvirtCollection *ovirt_api_search_hosts(OvirtApi *api, const char *query) ++{ ++ g_return_val_if_fail(OVIRT_IS_API(api), NULL); ++ ++ return ovirt_sub_collection_new_from_resource_search(OVIRT_RESOURCE(api), ++ "hosts", ++ "hosts", ++ OVIRT_TYPE_HOST, ++ "host", ++ query); ++} +diff --git a/govirt/ovirt-api.h b/govirt/ovirt-api.h +index d511d70..c46e934 100644 +--- a/govirt/ovirt-api.h ++++ b/govirt/ovirt-api.h +@@ -60,6 +60,8 @@ struct _OvirtApiClass + GType ovirt_api_get_type(void); + OvirtApi *ovirt_api_new(void); + ++OvirtCollection *ovirt_api_get_hosts(OvirtApi *api); ++OvirtCollection *ovirt_api_search_hosts(OvirtApi *api, const char *query); + OvirtCollection *ovirt_api_get_storage_domains(OvirtApi *api); + OvirtCollection *ovirt_api_search_storage_domains(OvirtApi *api, const char *query); + OvirtCollection *ovirt_api_get_vms(OvirtApi *api); +diff --git a/govirt/ovirt-host-private.h b/govirt/ovirt-host-private.h +new file mode 100644 +index 0000000..26587ea +--- /dev/null ++++ b/govirt/ovirt-host-private.h +@@ -0,0 +1,37 @@ ++/* ++ * ovirt-host-private.h: oVirt host resource ++ * ++ * Copyright (C) 2017 Red Hat, Inc. ++ * ++ * 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, see ++ * . ++ * ++ * Author: Eduardo Lima (Etrunko) ++ */ ++#ifndef __OVIRT_HOST_PRIVATE_H__ ++#define __OVIRT_HOST_PRIVATE_H__ ++ ++#include ++#include ++ ++G_BEGIN_DECLS ++ ++OvirtHost *ovirt_host_new_from_id(const char *id, ++ const char *href); ++OvirtHost *ovirt_host_new_from_xml(RestXmlNode *node, ++ GError **error); ++ ++G_END_DECLS ++ ++#endif /* __OVIRT_HOST_PRIVATE_H__ */ +diff --git a/govirt/ovirt-host.c b/govirt/ovirt-host.c +new file mode 100644 +index 0000000..2df2a64 +--- /dev/null ++++ b/govirt/ovirt-host.c +@@ -0,0 +1,214 @@ ++/* ++ * ovirt-host.c: oVirt host handling ++ * ++ * Copyright (C) 2017 Red Hat, Inc. ++ * ++ * 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, see ++ * . ++ * ++ * Author: Eduardo Lima (Etrunko) ++ */ ++ ++#include ++#include "ovirt-enum-types.h" ++#include "ovirt-host.h" ++#include "govirt-private.h" ++ ++#define OVIRT_HOST_GET_PRIVATE(obj) \ ++ (G_TYPE_INSTANCE_GET_PRIVATE((obj), OVIRT_TYPE_HOST, OvirtHostPrivate)) ++ ++struct _OvirtHostPrivate { ++ gchar *cluster_href; ++ gchar *cluster_id; ++ OvirtCollection *vms; ++}; ++ ++G_DEFINE_TYPE(OvirtHost, ovirt_host, OVIRT_TYPE_RESOURCE); ++ ++enum { ++ PROP_0, ++ PROP_CLUSTER_HREF, ++ PROP_CLUSTER_ID, ++}; ++ ++static void ovirt_host_get_property(GObject *object, ++ guint prop_id, ++ GValue *value, ++ GParamSpec *pspec) ++{ ++ OvirtHost *host = OVIRT_HOST(object); ++ ++ switch (prop_id) { ++ case PROP_CLUSTER_HREF: ++ g_value_set_string(value, host->priv->cluster_href); ++ break; ++ case PROP_CLUSTER_ID: ++ g_value_set_string(value, host->priv->cluster_id); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); ++ } ++} ++ ++static void ovirt_host_set_property(GObject *object, ++ guint prop_id, ++ const GValue *value, ++ GParamSpec *pspec) ++{ ++ OvirtHost *host = OVIRT_HOST(object); ++ ++ switch (prop_id) { ++ case PROP_CLUSTER_HREF: ++ g_free(host->priv->cluster_href); ++ host->priv->cluster_href = g_value_dup_string(value); ++ break; ++ case PROP_CLUSTER_ID: ++ g_free(host->priv->cluster_id); ++ host->priv->cluster_id = g_value_dup_string(value); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); ++ } ++} ++ ++ ++static void ++ovirt_host_dispose(GObject *obj) ++{ ++ OvirtHost *host = OVIRT_HOST(obj); ++ ++ g_clear_pointer(&host->priv->cluster_href, g_free); ++ g_clear_pointer(&host->priv->cluster_id, g_free); ++ g_clear_object(&host->priv->vms); ++ ++ G_OBJECT_CLASS(ovirt_host_parent_class)->dispose(obj); ++} ++ ++ ++static gboolean ovirt_host_init_from_xml(OvirtResource *resource, ++ RestXmlNode *node, ++ GError **error) ++{ ++ OvirtResourceClass *parent_class; ++ OvirtXmlElement host_elements[] = { ++ { .prop_name = "cluster-href", ++ .type = G_TYPE_STRING, ++ .xml_path = "cluster", ++ .xml_attr = "href", ++ }, ++ { .prop_name = "cluster-id", ++ .type = G_TYPE_STRING, ++ .xml_path = "cluster", ++ .xml_attr = "id", ++ }, ++ { NULL , }, ++ }; ++ ++ if (!ovirt_rest_xml_node_parse(node, G_OBJECT(resource), host_elements)) ++ return FALSE; ++ ++ parent_class = OVIRT_RESOURCE_CLASS(ovirt_host_parent_class); ++ return parent_class->init_from_xml(resource, node, error); ++} ++ ++ ++static void ovirt_host_class_init(OvirtHostClass *klass) ++{ ++ GObjectClass *object_class = G_OBJECT_CLASS(klass); ++ OvirtResourceClass *resource_class = OVIRT_RESOURCE_CLASS(klass); ++ GParamSpec *param_spec; ++ ++ g_type_class_add_private(klass, sizeof(OvirtHostPrivate)); ++ ++ resource_class->init_from_xml = ovirt_host_init_from_xml; ++ object_class->dispose = ovirt_host_dispose; ++ object_class->get_property = ovirt_host_get_property; ++ object_class->set_property = ovirt_host_set_property; ++ ++ param_spec = g_param_spec_string("cluster-href", ++ "Cluster href", ++ "Cluster href for the Host", ++ NULL, ++ G_PARAM_READWRITE | ++ G_PARAM_STATIC_STRINGS); ++ g_object_class_install_property(object_class, ++ PROP_CLUSTER_HREF, ++ param_spec); ++ ++ param_spec = g_param_spec_string("cluster-id", ++ "Cluster Id", ++ "Cluster Id for the Host", ++ NULL, ++ G_PARAM_READWRITE | ++ G_PARAM_STATIC_STRINGS); ++ g_object_class_install_property(object_class, ++ PROP_CLUSTER_ID, ++ param_spec); ++} ++ ++static void ovirt_host_init(OvirtHost *host) ++{ ++ host->priv = OVIRT_HOST_GET_PRIVATE(host); ++} ++ ++G_GNUC_INTERNAL ++OvirtHost *ovirt_host_new_from_id(const char *id, ++ const char *href) ++{ ++ OvirtResource *host = ovirt_resource_new_from_id(OVIRT_TYPE_HOST, id, href); ++ return OVIRT_HOST(host); ++} ++ ++G_GNUC_INTERNAL ++OvirtHost *ovirt_host_new_from_xml(RestXmlNode *node, ++ GError **error) ++{ ++ OvirtResource *host = ovirt_resource_new_from_xml(OVIRT_TYPE_HOST, node, error); ++ return OVIRT_HOST(host); ++} ++ ++OvirtHost *ovirt_host_new(void) ++{ ++ OvirtResource *host = ovirt_resource_new(OVIRT_TYPE_HOST); ++ return OVIRT_HOST(host); ++} ++ ++/** ++ * ovirt_host_get_vms: ++ * @host: a #OvirtHost ++ * ++ * Gets a #OvirtCollection representing the list of remote vms from a ++ * host object. This method does not initiate any network ++ * activity, the remote vm list must be then be fetched using ++ * ovirt_collection_fetch() or ovirt_collection_fetch_async(). ++ * ++ * Return value: (transfer none): a #OvirtCollection representing the list ++ * of vms associated with @host. ++ */ ++OvirtCollection *ovirt_host_get_vms(OvirtHost *host) ++{ ++ g_return_val_if_fail(OVIRT_IS_HOST(host), NULL); ++ ++ if (host->priv->vms == NULL) { ++ OvirtCollection *collection; ++ collection = ovirt_sub_collection_new_from_resource(OVIRT_RESOURCE(host), ++ "vms", ++ "vms", ++ OVIRT_TYPE_VM, ++ "vm"); ++ host->priv->vms = collection; ++ } ++ ++ return host->priv->vms; ++} +diff --git a/govirt/ovirt-host.h b/govirt/ovirt-host.h +new file mode 100644 +index 0000000..91441f6 +--- /dev/null ++++ b/govirt/ovirt-host.h +@@ -0,0 +1,66 @@ ++/* ++ * ovirt-host.h: oVirt host resource ++ * ++ * Copyright (C) 2017 Red Hat, Inc. ++ * ++ * 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, see ++ * . ++ * ++ * Author: Eduardo Lima (Etrunko) ++ */ ++#ifndef __OVIRT_HOST_H__ ++#define __OVIRT_HOST_H__ ++ ++#include ++#include ++#include ++#include ++#include ++ ++G_BEGIN_DECLS ++ ++#define OVIRT_TYPE_HOST (ovirt_host_get_type ()) ++#define OVIRT_HOST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), OVIRT_TYPE_HOST, OvirtHost)) ++#define OVIRT_HOST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), OVIRT_TYPE_HOST, OvirtHostClass)) ++#define OVIRT_IS_HOST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OVIRT_TYPE_HOST)) ++#define OVIRT_IS_HOST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OVIRT_TYPE_HOST)) ++#define OVIRT_HOST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OVIRT_TYPE_HOST, OvirtHostClass)) ++ ++typedef struct _OvirtHostPrivate OvirtHostPrivate; ++typedef struct _OvirtHostClass OvirtHostClass; ++ ++struct _OvirtHost ++{ ++ OvirtResource parent; ++ ++ OvirtHostPrivate *priv; ++ ++ /* Do not add fields to this struct */ ++}; ++ ++struct _OvirtHostClass ++{ ++ OvirtResourceClass parent_class; ++ ++ gpointer padding[20]; ++}; ++ ++GType ovirt_host_get_type(void); ++ ++OvirtHost *ovirt_host_new(void); ++OvirtCollection *ovirt_host_get_vms(OvirtHost *host); ++ ++G_END_DECLS ++ ++#endif /* __OVIRT_HOST_H__ */ +diff --git a/govirt/ovirt-types.h b/govirt/ovirt-types.h +index c89521b..42fc004 100644 +--- a/govirt/ovirt-types.h ++++ b/govirt/ovirt-types.h +@@ -28,6 +28,7 @@ G_BEGIN_DECLS + typedef struct _OvirtApi OvirtApi; + typedef struct _OvirtCdrom OvirtCdrom; + typedef struct _OvirtCollection OvirtCollection; ++typedef struct _OvirtHost OvirtHost; + typedef struct _OvirtProxy OvirtProxy; + typedef struct _OvirtStorageDomain OvirtStorageDomain; + typedef struct _OvirtVmDisplay OvirtVmDisplay; diff --git a/SOURCES/0020-Initial-support-for-clusters.patch b/SOURCES/0020-Initial-support-for-clusters.patch new file mode 100644 index 0000000..0909f48 --- /dev/null +++ b/SOURCES/0020-Initial-support-for-clusters.patch @@ -0,0 +1,519 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Tue, 11 Apr 2017 21:51:14 -0300 +Subject: [PATCH] Initial support for clusters + +Like the previous commit, at the moment, we only care about the +information of the data center the cluster is part of, and the list of +the hosts associated with it. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/Makefile.am | 3 + + govirt/govirt-private.h | 1 + + govirt/govirt.sym | 6 + + govirt/ovirt-api.c | 47 +++++++ + govirt/ovirt-api.h | 2 + + govirt/ovirt-cluster-private.h | 37 ++++++ + govirt/ovirt-cluster.c | 215 +++++++++++++++++++++++++++++++++ + govirt/ovirt-cluster.h | 66 ++++++++++ + govirt/ovirt-types.h | 1 + + 9 files changed, 378 insertions(+) + create mode 100644 govirt/ovirt-cluster-private.h + create mode 100644 govirt/ovirt-cluster.c + create mode 100644 govirt/ovirt-cluster.h + +diff --git a/govirt/Makefile.am b/govirt/Makefile.am +index c62a1d6..cf6b858 100644 +--- a/govirt/Makefile.am ++++ b/govirt/Makefile.am +@@ -19,6 +19,7 @@ libgovirt_la_HEADERS = \ + govirt.h \ + ovirt-api.h \ + ovirt-cdrom.h \ ++ ovirt-cluster.h \ + ovirt-collection.h \ + ovirt-error.h \ + ovirt-host.h \ +@@ -38,6 +39,7 @@ noinst_HEADERS = \ + govirt-private.h \ + ovirt-action-rest-call.h \ + ovirt-api-private.h \ ++ ovirt-cluster-private.h \ + ovirt-collection-private.h \ + ovirt-host-private.h \ + ovirt-proxy-private.h \ +@@ -54,6 +56,7 @@ libgovirt_la_SOURCES = \ + ovirt-action-rest-call.c \ + ovirt-api.c \ + ovirt-cdrom.c \ ++ ovirt-cluster.c \ + ovirt-collection.c \ + ovirt-error.c \ + ovirt-host.c \ +diff --git a/govirt/govirt-private.h b/govirt/govirt-private.h +index b51feb3..d466f7a 100644 +--- a/govirt/govirt-private.h ++++ b/govirt/govirt-private.h +@@ -24,6 +24,7 @@ + + #include + #include ++#include + #include + #include + #include +diff --git a/govirt/govirt.sym b/govirt/govirt.sym +index 6dc8159..56e1d66 100644 +--- a/govirt/govirt.sym ++++ b/govirt/govirt.sym +@@ -110,13 +110,19 @@ GOVIRT_0.3.2 { + ovirt_api_search_vms; + ovirt_api_search_vm_pools; + ++ ovirt_api_get_clusters; + ovirt_api_get_hosts; + ++ ovirt_api_search_clusters; + ovirt_api_search_hosts; + ovirt_api_search_storage_domains; + ovirt_api_search_vms; + ovirt_api_search_vm_pools; + ++ ovirt_cluster_get_type; ++ ovirt_cluster_get_hosts; ++ ovirt_cluster_new; ++ + ovirt_host_get_type; + ovirt_host_get_vms; + ovirt_host_new; +diff --git a/govirt/ovirt-api.c b/govirt/ovirt-api.c +index fef04ba..14c6c5a 100644 +--- a/govirt/ovirt-api.c ++++ b/govirt/ovirt-api.c +@@ -41,6 +41,7 @@ + + + struct _OvirtApiPrivate { ++ OvirtCollection *clusters; + OvirtCollection *hosts; + OvirtCollection *storage_domains; + OvirtCollection *vms; +@@ -74,6 +75,7 @@ static void ovirt_api_dispose(GObject *object) + { + OvirtApi *api = OVIRT_API(object); + ++ g_clear_object(&api->priv->clusters); + g_clear_object(&api->priv->hosts); + g_clear_object(&api->priv->storage_domains); + g_clear_object(&api->priv->vms); +@@ -292,3 +294,48 @@ OvirtCollection *ovirt_api_search_hosts(OvirtApi *api, const char *query) + "host", + query); + } ++ ++ ++/** ++ * ovirt_api_get_clusters: ++ * @api: a #OvirtApi ++ * ++ * This method does not initiate any network activity, the collection ++ * must be fetched with ovirt_collection_fetch() before having up-to-date ++ * content. ++ * ++ * Return value: (transfer none): ++ */ ++OvirtCollection *ovirt_api_get_clusters(OvirtApi *api) ++{ ++ g_return_val_if_fail(OVIRT_IS_API(api), NULL); ++ ++ if (api->priv->clusters == NULL) ++ api->priv->clusters = ovirt_sub_collection_new_from_resource(OVIRT_RESOURCE(api), ++ "clusters", ++ "clusters", ++ OVIRT_TYPE_CLUSTER, ++ "cluster"); ++ ++ return api->priv->clusters; ++} ++ ++ ++/** ++ * ovirt_api_search_clusters: ++ * @api: a #OvirtApi ++ * @query: search query ++ * ++ * Return value: (transfer none): ++ */ ++OvirtCollection *ovirt_api_search_clusters(OvirtApi *api, const char *query) ++{ ++ g_return_val_if_fail(OVIRT_IS_API(api), NULL); ++ ++ return ovirt_sub_collection_new_from_resource_search(OVIRT_RESOURCE(api), ++ "clusters/search", ++ "clusters", ++ OVIRT_TYPE_CLUSTER, ++ "cluster", ++ query); ++} +diff --git a/govirt/ovirt-api.h b/govirt/ovirt-api.h +index c46e934..1b60f35 100644 +--- a/govirt/ovirt-api.h ++++ b/govirt/ovirt-api.h +@@ -60,6 +60,8 @@ struct _OvirtApiClass + GType ovirt_api_get_type(void); + OvirtApi *ovirt_api_new(void); + ++OvirtCollection *ovirt_api_get_clusters(OvirtApi *api); ++OvirtCollection *ovirt_api_search_clusters(OvirtApi *api, const char *query); + OvirtCollection *ovirt_api_get_hosts(OvirtApi *api); + OvirtCollection *ovirt_api_search_hosts(OvirtApi *api, const char *query); + OvirtCollection *ovirt_api_get_storage_domains(OvirtApi *api); +diff --git a/govirt/ovirt-cluster-private.h b/govirt/ovirt-cluster-private.h +new file mode 100644 +index 0000000..1a1817d +--- /dev/null ++++ b/govirt/ovirt-cluster-private.h +@@ -0,0 +1,37 @@ ++/* ++ * ovirt-cluster-private.h: oVirt cluster resource ++ * ++ * Copyright (C) 2017 Red Hat, Inc. ++ * ++ * 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, see ++ * . ++ * ++ * Author: Eduardo Lima (Etrunko) ++ */ ++#ifndef __OVIRT_CLUSTER_PRIVATE_H__ ++#define __OVIRT_CLUSTER_PRIVATE_H__ ++ ++#include ++#include ++ ++G_BEGIN_DECLS ++ ++OvirtCluster *ovirt_cluster_new_from_id(const char *id, ++ const char *href); ++OvirtCluster *ovirt_cluster_new_from_xml(RestXmlNode *node, ++ GError **error); ++ ++G_END_DECLS ++ ++#endif /* __OVIRT_CLUSTER_PRIVATE_H__ */ +diff --git a/govirt/ovirt-cluster.c b/govirt/ovirt-cluster.c +new file mode 100644 +index 0000000..83b0fa1 +--- /dev/null ++++ b/govirt/ovirt-cluster.c +@@ -0,0 +1,215 @@ ++/* ++ * ovirt-cluster.c: oVirt cluster handling ++ * ++ * Copyright (C) 2017 Red Hat, Inc. ++ * ++ * 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, see ++ * . ++ * ++ * Author: Eduardo Lima (Etrunko) ++ */ ++ ++#include ++#include "ovirt-enum-types.h" ++#include "ovirt-cluster.h" ++#include "govirt-private.h" ++ ++#define OVIRT_CLUSTER_GET_PRIVATE(obj) \ ++ (G_TYPE_INSTANCE_GET_PRIVATE((obj), OVIRT_TYPE_CLUSTER, OvirtClusterPrivate)) ++ ++struct _OvirtClusterPrivate { ++ gchar *data_center_href; ++ gchar *data_center_id; ++ OvirtCollection *hosts; ++}; ++ ++G_DEFINE_TYPE(OvirtCluster, ovirt_cluster, OVIRT_TYPE_RESOURCE); ++ ++enum { ++ PROP_0, ++ PROP_DATA_CENTER_HREF, ++ PROP_DATA_CENTER_ID, ++}; ++ ++static void ovirt_cluster_get_property(GObject *object, ++ guint prop_id, ++ GValue *value, ++ GParamSpec *pspec) ++{ ++ OvirtCluster *cluster = OVIRT_CLUSTER(object); ++ ++ switch (prop_id) { ++ case PROP_DATA_CENTER_HREF: ++ g_value_set_string(value, cluster->priv->data_center_href); ++ break; ++ case PROP_DATA_CENTER_ID: ++ g_value_set_string(value, cluster->priv->data_center_id); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); ++ } ++} ++ ++static void ovirt_cluster_set_property(GObject *object, ++ guint prop_id, ++ const GValue *value, ++ GParamSpec *pspec) ++{ ++ OvirtCluster *cluster = OVIRT_CLUSTER(object); ++ ++ switch (prop_id) { ++ case PROP_DATA_CENTER_HREF: ++ g_free(cluster->priv->data_center_href); ++ cluster->priv->data_center_href = g_value_dup_string(value); ++ break; ++ case PROP_DATA_CENTER_ID: ++ g_free(cluster->priv->data_center_id); ++ cluster->priv->data_center_id = g_value_dup_string(value); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); ++ } ++} ++ ++ ++static void ++ovirt_cluster_dispose(GObject *obj) ++{ ++ OvirtCluster *cluster = OVIRT_CLUSTER(obj); ++ ++ g_clear_pointer(&cluster->priv->data_center_href, g_free); ++ g_clear_pointer(&cluster->priv->data_center_id, g_free); ++ g_clear_object(&cluster->priv->hosts); ++ ++ G_OBJECT_CLASS(ovirt_cluster_parent_class)->dispose(obj); ++} ++ ++ ++static gboolean ovirt_cluster_init_from_xml(OvirtResource *resource, ++ RestXmlNode *node, ++ GError **error) ++{ ++ OvirtResourceClass *parent_class; ++ OvirtXmlElement cluster_elements[] = { ++ { .prop_name = "data-center-href", ++ .type = G_TYPE_STRING, ++ .xml_path = "data_center", ++ .xml_attr = "href", ++ }, ++ { .prop_name = "data-center-id", ++ .type = G_TYPE_STRING, ++ .xml_path = "data_center", ++ .xml_attr = "id", ++ }, ++ { NULL , }, ++ }; ++ ++ if (!ovirt_rest_xml_node_parse(node, G_OBJECT(resource), cluster_elements)) ++ return FALSE; ++ ++ parent_class = OVIRT_RESOURCE_CLASS(ovirt_cluster_parent_class); ++ return parent_class->init_from_xml(resource, node, error); ++} ++ ++ ++static void ovirt_cluster_class_init(OvirtClusterClass *klass) ++{ ++ GObjectClass *object_class = G_OBJECT_CLASS(klass); ++ OvirtResourceClass *resource_class = OVIRT_RESOURCE_CLASS(klass); ++ GParamSpec *param_spec; ++ ++ g_type_class_add_private(klass, sizeof(OvirtClusterPrivate)); ++ ++ resource_class->init_from_xml = ovirt_cluster_init_from_xml; ++ object_class->dispose = ovirt_cluster_dispose; ++ object_class->get_property = ovirt_cluster_get_property; ++ object_class->set_property = ovirt_cluster_set_property; ++ ++ param_spec = g_param_spec_string("data-center-href", ++ "Data Center href", ++ "Data Center href for the Cluster", ++ NULL, ++ G_PARAM_READWRITE | ++ G_PARAM_STATIC_STRINGS); ++ g_object_class_install_property(object_class, ++ PROP_DATA_CENTER_HREF, ++ param_spec); ++ ++ param_spec = g_param_spec_string("data-center-id", ++ "Data Center Id", ++ "Data Center Id for the Cluster", ++ NULL, ++ G_PARAM_READWRITE | ++ G_PARAM_STATIC_STRINGS); ++ g_object_class_install_property(object_class, ++ PROP_DATA_CENTER_ID, ++ param_spec); ++} ++ ++static void ovirt_cluster_init(OvirtCluster *cluster) ++{ ++ cluster->priv = OVIRT_CLUSTER_GET_PRIVATE(cluster); ++} ++ ++G_GNUC_INTERNAL ++OvirtCluster *ovirt_cluster_new_from_id(const char *id, ++ const char *href) ++{ ++ OvirtResource *cluster = ovirt_resource_new_from_id(OVIRT_TYPE_CLUSTER, id, href); ++ return OVIRT_CLUSTER(cluster); ++} ++ ++G_GNUC_INTERNAL ++OvirtCluster *ovirt_cluster_new_from_xml(RestXmlNode *node, ++ GError **error) ++{ ++ OvirtResource *cluster = ovirt_resource_new_from_xml(OVIRT_TYPE_CLUSTER, node, error); ++ return OVIRT_CLUSTER(cluster); ++} ++ ++OvirtCluster *ovirt_cluster_new(void) ++{ ++ OvirtResource *cluster = ovirt_resource_new(OVIRT_TYPE_CLUSTER); ++ return OVIRT_CLUSTER(cluster); ++} ++ ++/** ++ * ovirt_cluster_get_hosts: ++ * @cluster: a #OvirtCluster ++ * ++ * Gets a #OvirtCollection representing the list of remote hosts from a ++ * cluster object. This method does not initiate any network ++ * activity, the remote host list must be then be fetched using ++ * ovirt_collection_fetch() or ovirt_collection_fetch_async(). ++ * ++ * Return value: (transfer none): a #OvirtCollection representing the list ++ * of hosts associated with @cluster. ++ */ ++OvirtCollection *ovirt_cluster_get_hosts(OvirtCluster *cluster) ++{ ++ g_return_val_if_fail(OVIRT_IS_CLUSTER(cluster), NULL); ++ ++ if (cluster->priv->hosts == NULL) { ++ OvirtCollection *collection; ++ collection = ovirt_sub_collection_new_from_resource(OVIRT_RESOURCE(cluster), ++ "hosts", ++ "hosts", ++ OVIRT_TYPE_HOST, ++ "host"); ++ cluster->priv->hosts = collection; ++ } ++ ++ return cluster->priv->hosts; ++} ++ +diff --git a/govirt/ovirt-cluster.h b/govirt/ovirt-cluster.h +new file mode 100644 +index 0000000..9505e8c +--- /dev/null ++++ b/govirt/ovirt-cluster.h +@@ -0,0 +1,66 @@ ++/* ++ * ovirt-cluster.h: oVirt cluster resource ++ * ++ * Copyright (C) 2017 Red Hat, Inc. ++ * ++ * 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, see ++ * . ++ * ++ * Author: Eduardo Lima (Etrunko) ++ */ ++#ifndef __OVIRT_CLUSTER_H__ ++#define __OVIRT_CLUSTER_H__ ++ ++#include ++#include ++#include ++#include ++#include ++ ++G_BEGIN_DECLS ++ ++#define OVIRT_TYPE_CLUSTER (ovirt_cluster_get_type ()) ++#define OVIRT_CLUSTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), OVIRT_TYPE_CLUSTER, OvirtCluster)) ++#define OVIRT_CLUSTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), OVIRT_TYPE_CLUSTER, OvirtClusterClass)) ++#define OVIRT_IS_CLUSTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OVIRT_TYPE_CLUSTER)) ++#define OVIRT_IS_CLUSTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OVIRT_TYPE_CLUSTER)) ++#define OVIRT_CLUSTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OVIRT_TYPE_CLUSTER, OvirtClusterClass)) ++ ++typedef struct _OvirtClusterPrivate OvirtClusterPrivate; ++typedef struct _OvirtClusterClass OvirtClusterClass; ++ ++struct _OvirtCluster ++{ ++ OvirtResource parent; ++ ++ OvirtClusterPrivate *priv; ++ ++ /* Do not add fields to this struct */ ++}; ++ ++struct _OvirtClusterClass ++{ ++ OvirtResourceClass parent_class; ++ ++ gpointer padding[20]; ++}; ++ ++GType ovirt_cluster_get_type(void); ++ ++OvirtCluster *ovirt_cluster_new(void); ++OvirtCollection *ovirt_cluster_get_hosts(OvirtCluster *cluster); ++ ++G_END_DECLS ++ ++#endif /* __OVIRT_CLUSTER_H__ */ +diff --git a/govirt/ovirt-types.h b/govirt/ovirt-types.h +index 42fc004..e2f196e 100644 +--- a/govirt/ovirt-types.h ++++ b/govirt/ovirt-types.h +@@ -27,6 +27,7 @@ G_BEGIN_DECLS + + typedef struct _OvirtApi OvirtApi; + typedef struct _OvirtCdrom OvirtCdrom; ++typedef struct _OvirtCluster OvirtCluster; + typedef struct _OvirtCollection OvirtCollection; + typedef struct _OvirtHost OvirtHost; + typedef struct _OvirtProxy OvirtProxy; diff --git a/SOURCES/0021-Initial-support-for-data-centers.patch b/SOURCES/0021-Initial-support-for-data-centers.patch new file mode 100644 index 0000000..09642f3 --- /dev/null +++ b/SOURCES/0021-Initial-support-for-data-centers.patch @@ -0,0 +1,452 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Tue, 11 Apr 2017 21:53:26 -0300 +Subject: [PATCH] Initial support for data centers + +For this higher level object, the list of clusters and storage domains +associated with it are stored. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/Makefile.am | 3 + + govirt/govirt-private.h | 1 + + govirt/govirt.sym | 7 ++ + govirt/ovirt-api.c | 47 ++++++++++ + govirt/ovirt-api.h | 2 + + govirt/ovirt-data-center-private.h | 37 ++++++++ + govirt/ovirt-data-center.c | 144 +++++++++++++++++++++++++++++ + govirt/ovirt-data-center.h | 67 ++++++++++++++ + govirt/ovirt-types.h | 1 + + 9 files changed, 309 insertions(+) + create mode 100644 govirt/ovirt-data-center-private.h + create mode 100644 govirt/ovirt-data-center.c + create mode 100644 govirt/ovirt-data-center.h + +diff --git a/govirt/Makefile.am b/govirt/Makefile.am +index cf6b858..9bf0eba 100644 +--- a/govirt/Makefile.am ++++ b/govirt/Makefile.am +@@ -21,6 +21,7 @@ libgovirt_la_HEADERS = \ + ovirt-cdrom.h \ + ovirt-cluster.h \ + ovirt-collection.h \ ++ ovirt-data-center.h \ + ovirt-error.h \ + ovirt-host.h \ + ovirt-options.h \ +@@ -41,6 +42,7 @@ noinst_HEADERS = \ + ovirt-api-private.h \ + ovirt-cluster-private.h \ + ovirt-collection-private.h \ ++ ovirt-data-center-private.h \ + ovirt-host-private.h \ + ovirt-proxy-private.h \ + ovirt-resource-private.h \ +@@ -58,6 +60,7 @@ libgovirt_la_SOURCES = \ + ovirt-cdrom.c \ + ovirt-cluster.c \ + ovirt-collection.c \ ++ ovirt-data-center.c \ + ovirt-error.c \ + ovirt-host.c \ + ovirt-options.c \ +diff --git a/govirt/govirt-private.h b/govirt/govirt-private.h +index d466f7a..cd98b5b 100644 +--- a/govirt/govirt-private.h ++++ b/govirt/govirt-private.h +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + #include + #include +diff --git a/govirt/govirt.sym b/govirt/govirt.sym +index 56e1d66..b22af76 100644 +--- a/govirt/govirt.sym ++++ b/govirt/govirt.sym +@@ -111,9 +111,11 @@ GOVIRT_0.3.2 { + ovirt_api_search_vm_pools; + + ovirt_api_get_clusters; ++ ovirt_api_get_data_centers; + ovirt_api_get_hosts; + + ovirt_api_search_clusters; ++ ovirt_api_search_data_centers; + ovirt_api_search_hosts; + ovirt_api_search_storage_domains; + ovirt_api_search_vms; +@@ -123,6 +125,11 @@ GOVIRT_0.3.2 { + ovirt_cluster_get_hosts; + ovirt_cluster_new; + ++ ovirt_data_center_get_clusters; ++ ovirt_data_center_get_storage_domains; ++ ovirt_data_center_get_type; ++ ovirt_data_center_new; ++ + ovirt_host_get_type; + ovirt_host_get_vms; + ovirt_host_new; +diff --git a/govirt/ovirt-api.c b/govirt/ovirt-api.c +index 14c6c5a..d78ba7e 100644 +--- a/govirt/ovirt-api.c ++++ b/govirt/ovirt-api.c +@@ -42,6 +42,7 @@ + + struct _OvirtApiPrivate { + OvirtCollection *clusters; ++ OvirtCollection *data_centers; + OvirtCollection *hosts; + OvirtCollection *storage_domains; + OvirtCollection *vms; +@@ -76,6 +77,7 @@ static void ovirt_api_dispose(GObject *object) + OvirtApi *api = OVIRT_API(object); + + g_clear_object(&api->priv->clusters); ++ g_clear_object(&api->priv->data_centers); + g_clear_object(&api->priv->hosts); + g_clear_object(&api->priv->storage_domains); + g_clear_object(&api->priv->vms); +@@ -339,3 +341,48 @@ OvirtCollection *ovirt_api_search_clusters(OvirtApi *api, const char *query) + "cluster", + query); + } ++ ++ ++/** ++ * ovirt_api_get_data_centers: ++ * @api: a #OvirtApi ++ * ++ * This method does not initiate any network activity, the collection ++ * must be fetched with ovirt_collection_fetch() before having up-to-date ++ * content. ++ * ++ * Return value: (transfer none): ++ */ ++OvirtCollection *ovirt_api_get_data_centers(OvirtApi *api) ++{ ++ g_return_val_if_fail(OVIRT_IS_API(api), NULL); ++ ++ if (api->priv->data_centers == NULL) ++ api->priv->data_centers = ovirt_sub_collection_new_from_resource(OVIRT_RESOURCE(api), ++ "datacenters", ++ "data_centers", ++ OVIRT_TYPE_DATA_CENTER, ++ "data_center"); ++ ++ return api->priv->data_centers; ++} ++ ++ ++/** ++ * ovirt_api_search_data_centers: ++ * @api: a #OvirtApi ++ * @query: search query ++ * ++ * Return value: (transfer none): ++ */ ++OvirtCollection *ovirt_api_search_data_centers(OvirtApi *api, const char *query) ++{ ++ g_return_val_if_fail(OVIRT_IS_API(api), NULL); ++ ++ return ovirt_sub_collection_new_from_resource_search(OVIRT_RESOURCE(api), ++ "datacenters/search", ++ "data_centers", ++ OVIRT_TYPE_DATA_CENTER, ++ "data_center", ++ query); ++} +diff --git a/govirt/ovirt-api.h b/govirt/ovirt-api.h +index 1b60f35..1448296 100644 +--- a/govirt/ovirt-api.h ++++ b/govirt/ovirt-api.h +@@ -62,6 +62,8 @@ OvirtApi *ovirt_api_new(void); + + OvirtCollection *ovirt_api_get_clusters(OvirtApi *api); + OvirtCollection *ovirt_api_search_clusters(OvirtApi *api, const char *query); ++OvirtCollection *ovirt_api_get_data_centers(OvirtApi *api); ++OvirtCollection *ovirt_api_search_data_centers(OvirtApi *api, const char *query); + OvirtCollection *ovirt_api_get_hosts(OvirtApi *api); + OvirtCollection *ovirt_api_search_hosts(OvirtApi *api, const char *query); + OvirtCollection *ovirt_api_get_storage_domains(OvirtApi *api); +diff --git a/govirt/ovirt-data-center-private.h b/govirt/ovirt-data-center-private.h +new file mode 100644 +index 0000000..5839755 +--- /dev/null ++++ b/govirt/ovirt-data-center-private.h +@@ -0,0 +1,37 @@ ++/* ++ * ovirt-data_center-private.h: oVirt data center resource ++ * ++ * Copyright (C) 2017 Red Hat, Inc. ++ * ++ * 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, see ++ * . ++ * ++ * Author: Eduardo Lima (Etrunko) ++ */ ++#ifndef __OVIRT_DATA_CENTER_PRIVATE_H__ ++#define __OVIRT_DATA_CENTER_PRIVATE_H__ ++ ++#include ++#include ++ ++G_BEGIN_DECLS ++ ++OvirtDataCenter *ovirt_data_center_new_from_id(const char *id, ++ const char *href); ++OvirtDataCenter *ovirt_data_center_new_from_xml(RestXmlNode *node, ++ GError **error); ++ ++G_END_DECLS ++ ++#endif /* __OVIRT_DATA_CENTER_PRIVATE_H__ */ +diff --git a/govirt/ovirt-data-center.c b/govirt/ovirt-data-center.c +new file mode 100644 +index 0000000..577a31f +--- /dev/null ++++ b/govirt/ovirt-data-center.c +@@ -0,0 +1,144 @@ ++/* ++ * ovirt-data_center.c: oVirt data center handling ++ * ++ * Copyright (C) 2017 Red Hat, Inc. ++ * ++ * 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, see ++ * . ++ * ++ * Author: Eduardo Lima (Etrunko) ++ */ ++ ++#include ++#include "ovirt-enum-types.h" ++#include "ovirt-data-center.h" ++#include "govirt-private.h" ++ ++#define OVIRT_DATA_CENTER_GET_PRIVATE(obj) \ ++ (G_TYPE_INSTANCE_GET_PRIVATE((obj), OVIRT_TYPE_DATA_CENTER, OvirtDataCenterPrivate)) ++ ++struct _OvirtDataCenterPrivate { ++ OvirtCollection *clusters; ++ OvirtCollection *storage_domains; ++}; ++ ++G_DEFINE_TYPE(OvirtDataCenter, ovirt_data_center, OVIRT_TYPE_RESOURCE); ++ ++static void ++ovirt_data_center_dispose(GObject *obj) ++{ ++ OvirtDataCenter *data_center = OVIRT_DATA_CENTER(obj); ++ ++ g_clear_object(&data_center->priv->clusters); ++ g_clear_object(&data_center->priv->storage_domains); ++ ++ G_OBJECT_CLASS(ovirt_data_center_parent_class)->dispose(obj); ++} ++ ++static void ovirt_data_center_class_init(OvirtDataCenterClass *klass) ++{ ++ GObjectClass *object_class = G_OBJECT_CLASS(klass); ++ ++ g_type_class_add_private(klass, sizeof(OvirtDataCenterPrivate)); ++ ++ object_class->dispose = ovirt_data_center_dispose; ++} ++ ++ ++static void ovirt_data_center_init(OvirtDataCenter *data_center) ++{ ++ data_center->priv = OVIRT_DATA_CENTER_GET_PRIVATE(data_center); ++} ++ ++G_GNUC_INTERNAL ++OvirtDataCenter *ovirt_data_center_new_from_id(const char *id, ++ const char *href) ++{ ++ OvirtResource *data_center = ovirt_resource_new_from_id(OVIRT_TYPE_DATA_CENTER, id, href); ++ return OVIRT_DATA_CENTER(data_center); ++} ++ ++G_GNUC_INTERNAL ++OvirtDataCenter *ovirt_data_center_new_from_xml(RestXmlNode *node, ++ GError **error) ++{ ++ OvirtResource *data_center = ovirt_resource_new_from_xml(OVIRT_TYPE_DATA_CENTER, node, error); ++ return OVIRT_DATA_CENTER(data_center); ++} ++ ++OvirtDataCenter *ovirt_data_center_new(void) ++{ ++ OvirtResource *data_center = ovirt_resource_new(OVIRT_TYPE_DATA_CENTER); ++ return OVIRT_DATA_CENTER(data_center); ++} ++ ++ ++/** ++ * ovirt_data_center_get_clusters: ++ * @data_center: a #OvirtDataCenter ++ * ++ * Gets a #OvirtCollection representing the list of remote clusters from a ++ * data center object. This method does not initiate any network ++ * activity, the remote cluster list must be then be fetched using ++ * ovirt_collection_fetch() or ovirt_collection_fetch_async(). ++ * ++ * Return value: (transfer none): a #OvirtCollection representing the list ++ * of clusters associated with @data_center. ++ */ ++OvirtCollection *ovirt_data_center_get_clusters(OvirtDataCenter *data_center) ++{ ++ g_return_val_if_fail(OVIRT_IS_DATA_CENTER(data_center), NULL); ++ ++ if (data_center->priv->clusters == NULL) { ++ OvirtCollection *collection; ++ collection = ovirt_sub_collection_new_from_resource(OVIRT_RESOURCE(data_center), ++ "clusters", ++ "clusters", ++ OVIRT_TYPE_CLUSTER, ++ "cluster"); ++ data_center->priv->clusters = collection; ++ } ++ ++ return data_center->priv->clusters; ++} ++ ++ ++/** ++ * ovirt_data_center_get_storage_domains: ++ * @data_center: a #OvirtDataCenter ++ * ++ * Gets a #OvirtCollection representing the list of remote storage domains from a ++ * data center object. This method does not initiate any network ++ * activity, the remote storage domain list must be then be fetched using ++ * ovirt_collection_fetch() or ovirt_collection_fetch_async(). ++ * ++ * Return value: (transfer none): a #OvirtCollection representing the list ++ * of storage_domains associated with @data_center. ++ */ ++OvirtCollection *ovirt_data_center_get_storage_domains(OvirtDataCenter *data_center) ++{ ++ g_return_val_if_fail(OVIRT_IS_DATA_CENTER(data_center), NULL); ++ ++ if (data_center->priv->storage_domains == NULL) { ++ OvirtCollection *collection; ++ collection = ovirt_sub_collection_new_from_resource(OVIRT_RESOURCE(data_center), ++ "storagedomains", ++ "storage_domains", ++ OVIRT_TYPE_STORAGE_DOMAIN, ++ "storage_domain"); ++ data_center->priv->storage_domains = collection; ++ } ++ ++ return data_center->priv->storage_domains; ++} +diff --git a/govirt/ovirt-data-center.h b/govirt/ovirt-data-center.h +new file mode 100644 +index 0000000..1bad06f +--- /dev/null ++++ b/govirt/ovirt-data-center.h +@@ -0,0 +1,67 @@ ++/* ++ * ovirt-data_center.h: oVirt data center resource ++ * ++ * Copyright (C) 2017 Red Hat, Inc. ++ * ++ * 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, see ++ * . ++ * ++ * Author: Eduardo Lima (Etrunko) ++ */ ++#ifndef __OVIRT_DATA_CENTER_H__ ++#define __OVIRT_DATA_CENTER_H__ ++ ++#include ++#include ++#include ++#include ++#include ++ ++G_BEGIN_DECLS ++ ++#define OVIRT_TYPE_DATA_CENTER (ovirt_data_center_get_type ()) ++#define OVIRT_DATA_CENTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), OVIRT_TYPE_DATA_CENTER, OvirtDataCenter)) ++#define OVIRT_DATA_CENTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), OVIRT_TYPE_DATA_CENTER, OvirtDataCenterClass)) ++#define OVIRT_IS_DATA_CENTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OVIRT_TYPE_DATA_CENTER)) ++#define OVIRT_IS_DATA_CENTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OVIRT_TYPE_DATA_CENTER)) ++#define OVIRT_DATA_CENTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OVIRT_TYPE_DATA_CENTER, OvirtDataCenterClass)) ++ ++typedef struct _OvirtDataCenterPrivate OvirtDataCenterPrivate; ++typedef struct _OvirtDataCenterClass OvirtDataCenterClass; ++ ++struct _OvirtDataCenter ++{ ++ OvirtResource parent; ++ ++ OvirtDataCenterPrivate *priv; ++ ++ /* Do not add fields to this struct */ ++}; ++ ++struct _OvirtDataCenterClass ++{ ++ OvirtResourceClass parent_class; ++ ++ gpointer padding[20]; ++}; ++ ++GType ovirt_data_center_get_type(void); ++ ++OvirtDataCenter *ovirt_data_center_new(void); ++OvirtCollection *ovirt_data_center_get_clusters(OvirtDataCenter *data_center); ++OvirtCollection *ovirt_data_center_get_storage_domains(OvirtDataCenter *data_center); ++ ++G_END_DECLS ++ ++#endif /* __OVIRT_DATA_CENTER_H__ */ +diff --git a/govirt/ovirt-types.h b/govirt/ovirt-types.h +index e2f196e..eb85fd6 100644 +--- a/govirt/ovirt-types.h ++++ b/govirt/ovirt-types.h +@@ -29,6 +29,7 @@ typedef struct _OvirtApi OvirtApi; + typedef struct _OvirtCdrom OvirtCdrom; + typedef struct _OvirtCluster OvirtCluster; + typedef struct _OvirtCollection OvirtCollection; ++typedef struct _OvirtDataCenter OvirtDataCenter; + typedef struct _OvirtHost OvirtHost; + typedef struct _OvirtProxy OvirtProxy; + typedef struct _OvirtStorageDomain OvirtStorageDomain; diff --git a/SOURCES/0022-vm-Introduce-ovirt_vm_get_host.patch b/SOURCES/0022-vm-Introduce-ovirt_vm_get_host.patch new file mode 100644 index 0000000..dfcbe58 --- /dev/null +++ b/SOURCES/0022-vm-Introduce-ovirt_vm_get_host.patch @@ -0,0 +1,195 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Thu, 13 Jul 2017 18:02:49 -0300 +Subject: [PATCH] vm: Introduce ovirt_vm_get_host() + +With initial support for hosts implemented, this new function can be +used to retrieve the host the virtual machine belongs to. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/govirt.sym | 2 ++ + govirt/ovirt-vm.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++- + govirt/ovirt-vm.h | 1 + + 3 files changed, 94 insertions(+), 1 deletion(-) + +diff --git a/govirt/govirt.sym b/govirt/govirt.sym +index b22af76..039c88b 100644 +--- a/govirt/govirt.sym ++++ b/govirt/govirt.sym +@@ -133,6 +133,8 @@ GOVIRT_0.3.2 { + ovirt_host_get_type; + ovirt_host_get_vms; + ovirt_host_new; ++ ++ ovirt_vm_get_host; + } GOVIRT_0.3.1; + + GOVIRT_0.3.4 { +diff --git a/govirt/ovirt-vm.c b/govirt/ovirt-vm.c +index 806b5f3..6016c77 100644 +--- a/govirt/ovirt-vm.c ++++ b/govirt/ovirt-vm.c +@@ -42,6 +42,8 @@ struct _OvirtVmPrivate { + + OvirtVmState state; + OvirtVmDisplay *display; ++ gchar *host_href; ++ gchar *host_id; + } ; + G_DEFINE_TYPE(OvirtVm, ovirt_vm, OVIRT_TYPE_RESOURCE); + +@@ -56,9 +58,28 @@ enum OvirtResponseStatus { + enum { + PROP_0, + PROP_STATE, +- PROP_DISPLAY ++ PROP_DISPLAY, ++ PROP_HOST_HREF, ++ PROP_HOST_ID, + }; + ++static char *ensure_href_from_id(const char *id, ++ const char *path) ++{ ++ if (id == NULL) ++ return NULL; ++ ++ return g_strdup_printf("%s/%s", path, id); ++} ++ ++static const char *get_host_href(OvirtVm *vm) ++{ ++ if (vm->priv->host_href == NULL) ++ vm->priv->host_href = ensure_href_from_id(vm->priv->host_id, "/ovirt-engine/api/hosts"); ++ ++ return vm->priv->host_href; ++} ++ + static void ovirt_vm_get_property(GObject *object, + guint prop_id, + GValue *value, +@@ -73,6 +94,12 @@ static void ovirt_vm_get_property(GObject *object, + case PROP_DISPLAY: + g_value_set_object(value, vm->priv->display); + break; ++ case PROP_HOST_HREF: ++ g_value_set_string(value, get_host_href(vm)); ++ break; ++ case PROP_HOST_ID: ++ g_value_set_string(value, vm->priv->host_id); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + } +@@ -94,6 +121,14 @@ static void ovirt_vm_set_property(GObject *object, + g_object_unref(vm->priv->display); + vm->priv->display = g_value_dup_object(value); + break; ++ case PROP_HOST_HREF: ++ g_free(vm->priv->host_href); ++ vm->priv->host_href = g_value_dup_string(value); ++ break; ++ case PROP_HOST_ID: ++ g_free(vm->priv->host_id); ++ vm->priv->host_id = g_value_dup_string(value); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + } +@@ -106,6 +141,8 @@ static void ovirt_vm_dispose(GObject *object) + + g_clear_object(&vm->priv->cdroms); + g_clear_object(&vm->priv->display); ++ g_clear_pointer(&vm->priv->host_href, g_free); ++ g_clear_pointer(&vm->priv->host_id, g_free); + + G_OBJECT_CLASS(ovirt_vm_parent_class)->dispose(object); + } +@@ -117,11 +154,28 @@ static gboolean ovirt_vm_init_from_xml(OvirtResource *resource, + { + gboolean parsed_ok; + OvirtResourceClass *parent_class; ++ OvirtXmlElement vm_elements[] = { ++ { .prop_name = "host-href", ++ .type = G_TYPE_STRING, ++ .xml_path = "host", ++ .xml_attr = "href", ++ }, ++ { .prop_name = "host-id", ++ .type = G_TYPE_STRING, ++ .xml_path = "host", ++ .xml_attr = "id", ++ }, ++ { NULL, }, ++ }; + + parsed_ok = ovirt_vm_refresh_from_xml(OVIRT_VM(resource), node); + if (!parsed_ok) { + return FALSE; + } ++ ++ if (!ovirt_rest_xml_node_parse(node, G_OBJECT(resource), vm_elements)) ++ return FALSE; ++ + parent_class = OVIRT_RESOURCE_CLASS(ovirt_vm_parent_class); + + return parent_class->init_from_xml(resource, node, error); +@@ -156,6 +210,22 @@ static void ovirt_vm_class_init(OvirtVmClass *klass) + OVIRT_TYPE_VM_DISPLAY, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); ++ g_object_class_install_property(object_class, ++ PROP_HOST_HREF, ++ g_param_spec_string("host-href", ++ "Host href", ++ "Host href for the Virtual Machine", ++ NULL, ++ G_PARAM_READWRITE | ++ G_PARAM_STATIC_STRINGS)); ++ g_object_class_install_property(object_class, ++ PROP_HOST_ID, ++ g_param_spec_string("host-id", ++ "Host Id", ++ "Host Id for the Virtual Machine", ++ NULL, ++ G_PARAM_READWRITE | ++ G_PARAM_STATIC_STRINGS)); + } + + static void ovirt_vm_init(G_GNUC_UNUSED OvirtVm *vm) +@@ -342,3 +412,23 @@ OvirtCollection *ovirt_vm_get_cdroms(OvirtVm *vm) + + return vm->priv->cdroms; + } ++ ++ ++/** ++ * ovirt_vm_get_host: ++ * @vm: a #OvirtVm ++ * ++ * Gets a #OvirtHost representing the host the virtual machine belongs to. ++ * This method does not initiate any network activity, the remote host must be ++ * then be fetched using ovirt_resource_refresh() or ++ * ovirt_resource_refresh_async(). ++ * ++ * Return value: (transfer full): a #OvirtHost representing host the @vm ++ * belongs to. ++ */ ++OvirtHost *ovirt_vm_get_host(OvirtVm *vm) ++{ ++ g_return_val_if_fail(OVIRT_IS_VM(vm), NULL); ++ g_return_val_if_fail(vm->priv->host_id != NULL, NULL); ++ return ovirt_host_new_from_id(vm->priv->host_id, get_host_href(vm)); ++} +diff --git a/govirt/ovirt-vm.h b/govirt/ovirt-vm.h +index 1e6c7ad..e230ebb 100644 +--- a/govirt/ovirt-vm.h ++++ b/govirt/ovirt-vm.h +@@ -120,6 +120,7 @@ gboolean ovirt_vm_refresh_finish(OvirtVm *vm, + GError **err); + + OvirtCollection *ovirt_vm_get_cdroms(OvirtVm *vm); ++OvirtHost *ovirt_vm_get_host(OvirtVm *vm); + + G_END_DECLS diff --git a/SOURCES/0023-vm-Introduce-ovirt_vm_get_cluster.patch b/SOURCES/0023-vm-Introduce-ovirt_vm_get_cluster.patch new file mode 100644 index 0000000..acc287b --- /dev/null +++ b/SOURCES/0023-vm-Introduce-ovirt_vm_get_cluster.patch @@ -0,0 +1,176 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Thu, 13 Jul 2017 18:03:11 -0300 +Subject: [PATCH] vm: Introduce ovirt_vm_get_cluster() + +Similar to previous commit, this new function can be used to retrieve +the cluster the virtual machine belongs to. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/govirt.sym | 1 + + govirt/ovirt-vm.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++ + govirt/ovirt-vm.h | 1 + + 3 files changed, 76 insertions(+) + +diff --git a/govirt/govirt.sym b/govirt/govirt.sym +index 039c88b..bbfbd79 100644 +--- a/govirt/govirt.sym ++++ b/govirt/govirt.sym +@@ -135,6 +135,7 @@ GOVIRT_0.3.2 { + ovirt_host_new; + + ovirt_vm_get_host; ++ ovirt_vm_get_cluster; + } GOVIRT_0.3.1; + + GOVIRT_0.3.4 { +diff --git a/govirt/ovirt-vm.c b/govirt/ovirt-vm.c +index 6016c77..70b6f3a 100644 +--- a/govirt/ovirt-vm.c ++++ b/govirt/ovirt-vm.c +@@ -44,6 +44,8 @@ struct _OvirtVmPrivate { + OvirtVmDisplay *display; + gchar *host_href; + gchar *host_id; ++ gchar *cluster_href; ++ gchar *cluster_id; + } ; + G_DEFINE_TYPE(OvirtVm, ovirt_vm, OVIRT_TYPE_RESOURCE); + +@@ -61,6 +63,8 @@ enum { + PROP_DISPLAY, + PROP_HOST_HREF, + PROP_HOST_ID, ++ PROP_CLUSTER_HREF, ++ PROP_CLUSTER_ID, + }; + + static char *ensure_href_from_id(const char *id, +@@ -80,6 +84,14 @@ static const char *get_host_href(OvirtVm *vm) + return vm->priv->host_href; + } + ++static const char *get_cluster_href(OvirtVm *vm) ++{ ++ if (vm->priv->cluster_href == NULL) ++ vm->priv->cluster_href = ensure_href_from_id(vm->priv->cluster_id, "/ovirt-engine/api/clusters"); ++ ++ return vm->priv->cluster_href; ++} ++ + static void ovirt_vm_get_property(GObject *object, + guint prop_id, + GValue *value, +@@ -100,6 +112,12 @@ static void ovirt_vm_get_property(GObject *object, + case PROP_HOST_ID: + g_value_set_string(value, vm->priv->host_id); + break; ++ case PROP_CLUSTER_HREF: ++ g_value_set_string(value, get_cluster_href(vm)); ++ break; ++ case PROP_CLUSTER_ID: ++ g_value_set_string(value, vm->priv->cluster_id); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + } +@@ -129,6 +147,14 @@ static void ovirt_vm_set_property(GObject *object, + g_free(vm->priv->host_id); + vm->priv->host_id = g_value_dup_string(value); + break; ++ case PROP_CLUSTER_HREF: ++ g_free(vm->priv->cluster_href); ++ vm->priv->cluster_href = g_value_dup_string(value); ++ break; ++ case PROP_CLUSTER_ID: ++ g_free(vm->priv->cluster_id); ++ vm->priv->cluster_id = g_value_dup_string(value); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + } +@@ -143,6 +169,8 @@ static void ovirt_vm_dispose(GObject *object) + g_clear_object(&vm->priv->display); + g_clear_pointer(&vm->priv->host_href, g_free); + g_clear_pointer(&vm->priv->host_id, g_free); ++ g_clear_pointer(&vm->priv->cluster_href, g_free); ++ g_clear_pointer(&vm->priv->cluster_id, g_free); + + G_OBJECT_CLASS(ovirt_vm_parent_class)->dispose(object); + } +@@ -165,6 +193,16 @@ static gboolean ovirt_vm_init_from_xml(OvirtResource *resource, + .xml_path = "host", + .xml_attr = "id", + }, ++ { .prop_name = "cluster-href", ++ .type = G_TYPE_STRING, ++ .xml_path = "cluster", ++ .xml_attr = "href", ++ }, ++ { .prop_name = "cluster-id", ++ .type = G_TYPE_STRING, ++ .xml_path = "cluster", ++ .xml_attr = "id", ++ }, + { NULL, }, + }; + +@@ -226,6 +264,22 @@ static void ovirt_vm_class_init(OvirtVmClass *klass) + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); ++ g_object_class_install_property(object_class, ++ PROP_CLUSTER_HREF, ++ g_param_spec_string("cluster-href", ++ "Cluster href", ++ "Cluster href for the Virtual Machine", ++ NULL, ++ G_PARAM_READWRITE | ++ G_PARAM_STATIC_STRINGS)); ++ g_object_class_install_property(object_class, ++ PROP_CLUSTER_ID, ++ g_param_spec_string("cluster-id", ++ "Cluster Id", ++ "Cluster Id for the Virtual Machine", ++ NULL, ++ G_PARAM_READWRITE | ++ G_PARAM_STATIC_STRINGS)); + } + + static void ovirt_vm_init(G_GNUC_UNUSED OvirtVm *vm) +@@ -432,3 +486,23 @@ OvirtHost *ovirt_vm_get_host(OvirtVm *vm) + g_return_val_if_fail(vm->priv->host_id != NULL, NULL); + return ovirt_host_new_from_id(vm->priv->host_id, get_host_href(vm)); + } ++ ++ ++/** ++ * ovirt_vm_get_cluster: ++ * @vm: a #OvirtVm ++ * ++ * Gets a #OvirtCluster representing the cluster the virtual machine belongs ++ * to. This method does not initiate any network activity, the remote host must ++ * be then be fetched using ovirt_resource_refresh() or ++ * ovirt_resource_refresh_async(). ++ * ++ * Return value: (transfer full): a #OvirtCluster representing cluster the @vm ++ * belongs to. ++ */ ++OvirtCluster *ovirt_vm_get_cluster(OvirtVm *vm) ++{ ++ g_return_val_if_fail(OVIRT_IS_VM(vm), NULL); ++ g_return_val_if_fail(vm->priv->cluster_id != NULL, NULL); ++ return ovirt_cluster_new_from_id(vm->priv->cluster_id, get_cluster_href(vm)); ++} +diff --git a/govirt/ovirt-vm.h b/govirt/ovirt-vm.h +index e230ebb..bef4289 100644 +--- a/govirt/ovirt-vm.h ++++ b/govirt/ovirt-vm.h +@@ -121,6 +121,7 @@ gboolean ovirt_vm_refresh_finish(OvirtVm *vm, + + OvirtCollection *ovirt_vm_get_cdroms(OvirtVm *vm); + OvirtHost *ovirt_vm_get_host(OvirtVm *vm); ++OvirtCluster *ovirt_vm_get_cluster(OvirtVm *vm); + + G_END_DECLS diff --git a/SOURCES/0024-host-Introduce-ovirt_host_get_cluster.patch b/SOURCES/0024-host-Introduce-ovirt_host_get_cluster.patch new file mode 100644 index 0000000..6950857 --- /dev/null +++ b/SOURCES/0024-host-Introduce-ovirt_host_get_cluster.patch @@ -0,0 +1,95 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Thu, 13 Jul 2017 17:44:13 -0300 +Subject: [PATCH] host: Introduce ovirt_host_get_cluster() + +Following the same principle as previous commits, this functions can be +used to retrieve the cluster that includes this host. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/govirt.sym | 1 + + govirt/ovirt-host.c | 35 ++++++++++++++++++++++++++++++++++- + govirt/ovirt-host.h | 1 + + 3 files changed, 36 insertions(+), 1 deletion(-) + +diff --git a/govirt/govirt.sym b/govirt/govirt.sym +index bbfbd79..243ce0b 100644 +--- a/govirt/govirt.sym ++++ b/govirt/govirt.sym +@@ -130,6 +130,7 @@ GOVIRT_0.3.2 { + ovirt_data_center_get_type; + ovirt_data_center_new; + ++ ovirt_host_get_cluster; + ovirt_host_get_type; + ovirt_host_get_vms; + ovirt_host_new; +diff --git a/govirt/ovirt-host.c b/govirt/ovirt-host.c +index 2df2a64..191b360 100644 +--- a/govirt/ovirt-host.c ++++ b/govirt/ovirt-host.c +@@ -42,6 +42,19 @@ enum { + PROP_CLUSTER_ID, + }; + ++ ++static const char *get_cluster_href(OvirtHost *host) ++{ ++ if (host->priv->cluster_href == NULL && ++ host->priv->cluster_id != NULL) { ++ host->priv->cluster_href = g_strdup_printf("%s/%s", ++ "/ovirt-engine/api/clusters", ++ host->priv->cluster_id); ++ } ++ ++ return host->priv->cluster_href; ++} ++ + static void ovirt_host_get_property(GObject *object, + guint prop_id, + GValue *value, +@@ -51,7 +64,7 @@ static void ovirt_host_get_property(GObject *object, + + switch (prop_id) { + case PROP_CLUSTER_HREF: +- g_value_set_string(value, host->priv->cluster_href); ++ g_value_set_string(value, get_cluster_href(host)); + break; + case PROP_CLUSTER_ID: + g_value_set_string(value, host->priv->cluster_id); +@@ -212,3 +225,23 @@ OvirtCollection *ovirt_host_get_vms(OvirtHost *host) + + return host->priv->vms; + } ++ ++ ++/** ++ * ovirt_host_get_cluster: ++ * @host: a #OvirtHost ++ * ++ * Gets a #OvirtCluster representing the cluster the host belongs ++ * to. This method does not initiate any network activity, the remote host must ++ * be then be fetched using ovirt_resource_refresh() or ++ * ovirt_resource_refresh_async(). ++ * ++ * Return value: (transfer full): a #OvirtCluster representing cluster the @host ++ * belongs to. ++ */ ++OvirtCluster *ovirt_host_get_cluster(OvirtHost *host) ++{ ++ g_return_val_if_fail(OVIRT_IS_HOST(host), NULL); ++ g_return_val_if_fail(host->priv->cluster_id != NULL, NULL); ++ return ovirt_cluster_new_from_id(host->priv->cluster_id, get_cluster_href(host)); ++} +diff --git a/govirt/ovirt-host.h b/govirt/ovirt-host.h +index 91441f6..cdf702c 100644 +--- a/govirt/ovirt-host.h ++++ b/govirt/ovirt-host.h +@@ -60,6 +60,7 @@ GType ovirt_host_get_type(void); + + OvirtHost *ovirt_host_new(void); + OvirtCollection *ovirt_host_get_vms(OvirtHost *host); ++OvirtCluster *ovirt_host_get_cluster(OvirtHost *host); + + G_END_DECLS diff --git a/SOURCES/0025-cluster-Introduce-ovirt_cluster_get_data_center.patch b/SOURCES/0025-cluster-Introduce-ovirt_cluster_get_data_center.patch new file mode 100644 index 0000000..d62f95e --- /dev/null +++ b/SOURCES/0025-cluster-Introduce-ovirt_cluster_get_data_center.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Thu, 13 Jul 2017 17:49:36 -0300 +Subject: [PATCH] cluster: Introduce ovirt_cluster_get_data_center() + +This function can be used to retrieve the data center associated with +the cluster. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/govirt.sym | 1 + + govirt/ovirt-cluster.c | 33 ++++++++++++++++++++++++++++++++- + govirt/ovirt-cluster.h | 1 + + 3 files changed, 34 insertions(+), 1 deletion(-) + +diff --git a/govirt/govirt.sym b/govirt/govirt.sym +index 243ce0b..9806033 100644 +--- a/govirt/govirt.sym ++++ b/govirt/govirt.sym +@@ -121,6 +121,7 @@ GOVIRT_0.3.2 { + ovirt_api_search_vms; + ovirt_api_search_vm_pools; + ++ ovirt_cluster_get_data_center; + ovirt_cluster_get_type; + ovirt_cluster_get_hosts; + ovirt_cluster_new; +diff --git a/govirt/ovirt-cluster.c b/govirt/ovirt-cluster.c +index 83b0fa1..4aaf6b1 100644 +--- a/govirt/ovirt-cluster.c ++++ b/govirt/ovirt-cluster.c +@@ -42,6 +42,18 @@ enum { + PROP_DATA_CENTER_ID, + }; + ++static const char *get_data_center_href(OvirtCluster *cluster) ++{ ++ if (cluster->priv->data_center_href == NULL && ++ cluster->priv->data_center_id != NULL) { ++ cluster->priv->data_center_href = g_strdup_printf("%s/%s", ++ "/ovirt-engine/api/data_centers", ++ cluster->priv->data_center_id); ++ } ++ ++ return cluster->priv->data_center_href; ++} ++ + static void ovirt_cluster_get_property(GObject *object, + guint prop_id, + GValue *value, +@@ -51,7 +63,7 @@ static void ovirt_cluster_get_property(GObject *object, + + switch (prop_id) { + case PROP_DATA_CENTER_HREF: +- g_value_set_string(value, cluster->priv->data_center_href); ++ g_value_set_string(value, get_data_center_href(cluster)); + break; + case PROP_DATA_CENTER_ID: + g_value_set_string(value, cluster->priv->data_center_id); +@@ -213,3 +225,22 @@ OvirtCollection *ovirt_cluster_get_hosts(OvirtCluster *cluster) + return cluster->priv->hosts; + } + ++ ++/** ++ * ovirt_cluster_get_data_center: ++ * @cluster: a #OvirtCluster ++ * ++ * Gets a #OvirtCluster representing the data center the cluster belongs ++ * to. This method does not initiate any network activity, the remote data center must ++ * be then be fetched using ovirt_resource_refresh() or ++ * ovirt_resource_refresh_async(). ++ * ++ * Return value: (transfer full): a #OvirtDataCenter representing data center ++ * the @host belongs to. ++ */ ++OvirtDataCenter *ovirt_cluster_get_data_center(OvirtCluster *cluster) ++{ ++ g_return_val_if_fail(OVIRT_IS_CLUSTER(cluster), NULL); ++ g_return_val_if_fail(cluster->priv->data_center_id != NULL, NULL); ++ return ovirt_data_center_new_from_id(cluster->priv->data_center_id, get_data_center_href(cluster)); ++} +diff --git a/govirt/ovirt-cluster.h b/govirt/ovirt-cluster.h +index 9505e8c..cdd54b7 100644 +--- a/govirt/ovirt-cluster.h ++++ b/govirt/ovirt-cluster.h +@@ -60,6 +60,7 @@ GType ovirt_cluster_get_type(void); + + OvirtCluster *ovirt_cluster_new(void); + OvirtCollection *ovirt_cluster_get_hosts(OvirtCluster *cluster); ++OvirtDataCenter *ovirt_cluster_get_data_center(OvirtCluster *cluster); + + G_END_DECLS diff --git a/SOURCES/0026-storage-domain-Retrieve-data-center-ids.patch b/SOURCES/0026-storage-domain-Retrieve-data-center-ids.patch new file mode 100644 index 0000000..50716e9 --- /dev/null +++ b/SOURCES/0026-storage-domain-Retrieve-data-center-ids.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Thu, 13 Apr 2017 15:26:41 -0300 +Subject: [PATCH] storage-domain: Retrieve data center ids + +Storage domains can be part of one or more data centers, so we use a +GStrv to store each id. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-storage-domain.c | 27 ++++++++++++++++++++++++++- + 1 file changed, 26 insertions(+), 1 deletion(-) + +diff --git a/govirt/ovirt-storage-domain.c b/govirt/ovirt-storage-domain.c +index e255565..718c1d2 100644 +--- a/govirt/ovirt-storage-domain.c ++++ b/govirt/ovirt-storage-domain.c +@@ -30,6 +30,7 @@ + + struct _OvirtStorageDomainPrivate { + OvirtCollection *files; ++ GStrv data_center_ids; + + OvirtStorageDomainType type; + gboolean is_master; +@@ -50,7 +51,8 @@ enum { + PROP_USED, + PROP_COMMITTED, + PROP_VERSION, +- PROP_STATE ++ PROP_STATE, ++ PROP_DATA_CENTER_IDS, + }; + + static void ovirt_storage_domain_get_property(GObject *object, +@@ -82,6 +84,9 @@ static void ovirt_storage_domain_get_property(GObject *object, + case PROP_STATE: + g_value_set_enum(value, domain->priv->state); + break; ++ case PROP_DATA_CENTER_IDS: ++ g_value_set_boxed(value, domain->priv->data_center_ids); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; +@@ -117,6 +122,10 @@ static void ovirt_storage_domain_set_property(GObject *object, + case PROP_STATE: + domain->priv->state = g_value_get_enum(value); + break; ++ case PROP_DATA_CENTER_IDS: ++ g_strfreev(domain->priv->data_center_ids); ++ domain->priv->data_center_ids = g_value_dup_boxed(value); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; +@@ -130,6 +139,7 @@ ovirt_storage_domain_dispose(GObject *obj) + OvirtStorageDomain *domain = OVIRT_STORAGE_DOMAIN(obj); + + g_clear_object(&domain->priv->files); ++ g_clear_pointer(&domain->priv->data_center_ids, g_strfreev); + + G_OBJECT_CLASS(ovirt_storage_domain_parent_class)->dispose(obj); + } +@@ -170,6 +180,11 @@ static gboolean ovirt_storage_domain_init_from_xml(OvirtResource *resource, + .type = OVIRT_TYPE_STORAGE_DOMAIN_STATE, + .xml_path = "status/state", + }, ++ { .prop_name = "data-center-ids", ++ .type = G_TYPE_STRV, ++ .xml_path = "data_centers", ++ .xml_attr = "id", ++ }, + { NULL , } + }; + +@@ -274,6 +289,16 @@ static void ovirt_storage_domain_class_init(OvirtStorageDomainClass *klass) + g_object_class_install_property(object_class, + PROP_STATE, + param_spec); ++ ++ param_spec = g_param_spec_boxed("data-center-ids", ++ "Data Center Ids", ++ "Ids of Data Centers for this Storage Domain", ++ G_TYPE_STRV, ++ G_PARAM_READWRITE | ++ G_PARAM_STATIC_STRINGS); ++ g_object_class_install_property(object_class, ++ PROP_DATA_CENTER_IDS, ++ param_spec); + } + + static void ovirt_storage_domain_init(OvirtStorageDomain *domain) diff --git a/SOURCES/0027-Add-missing-include-in-govirt.h.patch b/SOURCES/0027-Add-missing-include-in-govirt.h.patch new file mode 100644 index 0000000..a6b0118 --- /dev/null +++ b/SOURCES/0027-Add-missing-include-in-govirt.h.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Thu, 3 Aug 2017 16:53:09 -0300 +Subject: [PATCH] Add missing #include in govirt.h + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/govirt.h | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/govirt/govirt.h b/govirt/govirt.h +index fb7756f..9c92318 100644 +--- a/govirt/govirt.h ++++ b/govirt/govirt.h +@@ -25,8 +25,11 @@ + #include + #include + #include ++#include + #include ++#include + #include ++#include + #include + #include + #include diff --git a/SOURCES/0028-resource-Fix-ovirt_resource_rest_call_sync-return-va.patch b/SOURCES/0028-resource-Fix-ovirt_resource_rest_call_sync-return-va.patch new file mode 100644 index 0000000..7f71feb --- /dev/null +++ b/SOURCES/0028-resource-Fix-ovirt_resource_rest_call_sync-return-va.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Christophe Fergeau +Date: Tue, 25 Jul 2017 17:34:31 +0200 +Subject: [PATCH] resource: Fix ovirt_resource_rest_call_sync return value + +Upon success, ovirt_resource_rest_call_sync() was always returning +NULL, which is not what is expected. This, among other things, made +ovirt_resource_refresh() non-functional. +--- + govirt/ovirt-resource.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/govirt/ovirt-resource.c b/govirt/ovirt-resource.c +index 1413a77..0c750ac 100644 +--- a/govirt/ovirt-resource.c ++++ b/govirt/ovirt-resource.c +@@ -499,7 +499,7 @@ G_GNUC_INTERNAL RestXmlNode *ovirt_resource_rest_call_sync(OvirtRestCall *call, + return NULL; + } + +- return root; ++ return ovirt_rest_xml_node_from_call(REST_PROXY_CALL(call)); + } diff --git a/SOURCES/0029-resource-Fix-ovirt_resource_rest_call_sync-crash-on-.patch b/SOURCES/0029-resource-Fix-ovirt_resource_rest_call_sync-crash-on-.patch new file mode 100644 index 0000000..bc23782 --- /dev/null +++ b/SOURCES/0029-resource-Fix-ovirt_resource_rest_call_sync-crash-on-.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Christophe Fergeau +Date: Tue, 25 Jul 2017 17:36:05 +0200 +Subject: [PATCH] resource: Fix ovirt_resource_rest_call_sync() crash on 404 + +When the REST call fails, we do not always get an XML answer from oVirt +describing the failure in more details. In particular, this is the case +when we hit a 404. In such situations, we'd be crashing because we'd +attempt to dereference a NULL pointer. +--- + govirt/ovirt-resource.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/govirt/ovirt-resource.c b/govirt/ovirt-resource.c +index 0c750ac..0f4a129 100644 +--- a/govirt/ovirt-resource.c ++++ b/govirt/ovirt-resource.c +@@ -485,16 +485,17 @@ G_GNUC_INTERNAL RestXmlNode *ovirt_resource_rest_call_sync(OvirtRestCall *call, + GError *local_error = NULL; + + root = ovirt_rest_xml_node_from_call(REST_PROXY_CALL(call)); +- ovirt_utils_gerror_from_xml_fault(root, &local_error); ++ if (root != NULL) { ++ ovirt_utils_gerror_from_xml_fault(root, &local_error); ++ rest_xml_node_unref(root); ++ } + if (local_error != NULL) { + g_clear_error(error); + g_warning("Error while updating resource"); + g_warning("message: %s", local_error->message); + g_propagate_error(error, local_error); + } +- if (root != NULL) { +- rest_xml_node_unref(root); +- } ++ g_warn_if_fail(error == NULL || *error != NULL); + + return NULL; + } diff --git a/SOURCES/0030-resource-Fix-ovirt_resource_init_from_xml_real-preco.patch b/SOURCES/0030-resource-Fix-ovirt_resource_init_from_xml_real-preco.patch new file mode 100644 index 0000000..631f689 --- /dev/null +++ b/SOURCES/0030-resource-Fix-ovirt_resource_init_from_xml_real-preco.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Christophe Fergeau +Date: Mon, 11 Sep 2017 15:01:59 +0200 +Subject: [PATCH] resource: Fix ovirt_resource_init_from_xml_real precondition + +When ovirt_resource_init_from_xml_real is called, the current value of +OvirtResource::xml-node is not very relevant, what matters is whether +the passed in xml node is NULL or not. + +This updates the test-govirt test case to call +ovirt_resource_refresh(ovirt_vm_get_cluster()) as this triggers this +precondition failure. +--- + govirt/ovirt-resource.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/govirt/ovirt-resource.c b/govirt/ovirt-resource.c +index 0f4a129..ad5e8ca 100644 +--- a/govirt/ovirt-resource.c ++++ b/govirt/ovirt-resource.c +@@ -422,7 +422,7 @@ static gboolean ovirt_resource_init_from_xml_real(OvirtResource *resource, + */ + is_api = OVIRT_IS_API(resource); + +- g_return_val_if_fail(resource->priv->xml != NULL, FALSE); ++ g_return_val_if_fail(node != NULL, FALSE); + + guid = rest_xml_node_get_attr(node, "id"); + if ((guid == NULL) && !is_api) { diff --git a/SOURCES/0031-resource-Update-xml-node-in-ovirt_resource_init_from.patch b/SOURCES/0031-resource-Update-xml-node-in-ovirt_resource_init_from.patch new file mode 100644 index 0000000..8a3fe41 --- /dev/null +++ b/SOURCES/0031-resource-Update-xml-node-in-ovirt_resource_init_from.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Christophe Fergeau +Date: Mon, 11 Sep 2017 14:59:08 +0200 +Subject: [PATCH] resource: Update xml node in + ovirt_resource_init_from_xml_real + +ovirt_resource_init_from_xml_real is called indirectly when +ovirt_resource_refresh() is used. For some reason, it updates +the various OvirtResource properties with the new XML node content, but +OvirtResource::xml-node is not set to be the new node. +This commit fixes this inconsistent state by making sure +OvirtResource::xml-node is changed to point to the new node. +--- + govirt/ovirt-resource.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +diff --git a/govirt/ovirt-resource.c b/govirt/ovirt-resource.c +index ad5e8ca..1984b1d 100644 +--- a/govirt/ovirt-resource.c ++++ b/govirt/ovirt-resource.c +@@ -97,6 +97,15 @@ static void ovirt_resource_get_property(GObject *object, + } + } + ++static void ovirt_resource_set_xml_node(OvirtResource *resource, ++ RestXmlNode *node) ++{ ++ g_clear_pointer(&resource->priv->xml, &rest_xml_node_unref); ++ if (node != NULL) { ++ resource->priv->xml = rest_xml_node_ref(node); ++ } ++} ++ + static void ovirt_resource_set_property(GObject *object, + guint prop_id, + const GValue *value, +@@ -121,13 +130,10 @@ static void ovirt_resource_set_property(GObject *object, + g_free(resource->priv->description); + resource->priv->description = g_value_dup_string(value); + break; +- case PROP_XML_NODE: { +- if (resource->priv->xml != NULL) { +- g_boxed_free(REST_TYPE_XML_NODE, resource->priv->xml); +- } +- resource->priv->xml = g_value_dup_boxed(value); ++ case PROP_XML_NODE: ++ ovirt_resource_set_xml_node(OVIRT_RESOURCE(object), ++ g_value_get_boxed(value)); + break; +- } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + } +@@ -438,6 +444,7 @@ static gboolean ovirt_resource_init_from_xml_real(OvirtResource *resource, + return FALSE; + } + ++ ovirt_resource_set_xml_node(resource, node); + g_object_set(G_OBJECT(resource), "guid", guid, "href", href, NULL); + + ovirt_resource_set_name_from_xml(resource, node); diff --git a/SOURCES/0032-utils-Drop-type-member-from-OvirtXmlElement-struct.patch b/SOURCES/0032-utils-Drop-type-member-from-OvirtXmlElement-struct.patch new file mode 100644 index 0000000..a7448b6 --- /dev/null +++ b/SOURCES/0032-utils-Drop-type-member-from-OvirtXmlElement-struct.patch @@ -0,0 +1,151 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Thu, 18 May 2017 17:21:10 -0300 +Subject: [PATCH] utils: Drop 'type' member from OvirtXmlElement struct + +Instead of passing the type, it is possible to get it using by calling +g_object_class_find_property(). All users have been updated accordingly. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-cluster.c | 2 -- + govirt/ovirt-host.c | 2 -- + govirt/ovirt-storage-domain.c | 8 -------- + govirt/ovirt-utils.c | 8 ++++++-- + govirt/ovirt-utils.h | 1 - + govirt/ovirt-vm.c | 4 ---- + 6 files changed, 6 insertions(+), 19 deletions(-) + +diff --git a/govirt/ovirt-cluster.c b/govirt/ovirt-cluster.c +index 4aaf6b1..ae25d63 100644 +--- a/govirt/ovirt-cluster.c ++++ b/govirt/ovirt-cluster.c +@@ -115,12 +115,10 @@ static gboolean ovirt_cluster_init_from_xml(OvirtResource *resource, + OvirtResourceClass *parent_class; + OvirtXmlElement cluster_elements[] = { + { .prop_name = "data-center-href", +- .type = G_TYPE_STRING, + .xml_path = "data_center", + .xml_attr = "href", + }, + { .prop_name = "data-center-id", +- .type = G_TYPE_STRING, + .xml_path = "data_center", + .xml_attr = "id", + }, +diff --git a/govirt/ovirt-host.c b/govirt/ovirt-host.c +index 191b360..1570cba 100644 +--- a/govirt/ovirt-host.c ++++ b/govirt/ovirt-host.c +@@ -116,12 +116,10 @@ static gboolean ovirt_host_init_from_xml(OvirtResource *resource, + OvirtResourceClass *parent_class; + OvirtXmlElement host_elements[] = { + { .prop_name = "cluster-href", +- .type = G_TYPE_STRING, + .xml_path = "cluster", + .xml_attr = "href", + }, + { .prop_name = "cluster-id", +- .type = G_TYPE_STRING, + .xml_path = "cluster", + .xml_attr = "id", + }, +diff --git a/govirt/ovirt-storage-domain.c b/govirt/ovirt-storage-domain.c +index 718c1d2..a9078f4 100644 +--- a/govirt/ovirt-storage-domain.c ++++ b/govirt/ovirt-storage-domain.c +@@ -153,35 +153,27 @@ static gboolean ovirt_storage_domain_init_from_xml(OvirtResource *resource, + OvirtResourceClass *parent_class; + OvirtXmlElement storage_domain_elements[] = { + { .prop_name = "type", +- .type = OVIRT_TYPE_STORAGE_DOMAIN_TYPE, + .xml_path = "type", + }, + { .prop_name = "master", +- .type = G_TYPE_BOOLEAN, + .xml_path = "master", + }, + { .prop_name = "available", +- .type = G_TYPE_UINT64, + .xml_path = "available", + }, + { .prop_name = "used", +- .type = G_TYPE_UINT64, + .xml_path = "used", + }, + { .prop_name = "committed", +- .type = G_TYPE_UINT64, + .xml_path = "committed", + }, + { .prop_name = "version", +- .type = OVIRT_TYPE_STORAGE_DOMAIN_FORMAT_VERSION, + .xml_path = "storage_format", + }, + { .prop_name = "state", +- .type = OVIRT_TYPE_STORAGE_DOMAIN_STATE, + .xml_path = "status/state", + }, + { .prop_name = "data-center-ids", +- .type = G_TYPE_STRV, + .xml_path = "data_centers", + .xml_attr = "id", + }, +diff --git a/govirt/ovirt-utils.c b/govirt/ovirt-utils.c +index 1898862..501acb9 100644 +--- a/govirt/ovirt-utils.c ++++ b/govirt/ovirt-utils.c +@@ -207,9 +207,13 @@ ovirt_rest_xml_node_parse(RestXmlNode *node, + + for (;elements->xml_path != NULL; elements++) { + GValue value = { 0, }; ++ GParamSpec *prop; + +- g_value_init(&value, elements->type); +- if (_set_property_value_from_type(&value, elements->type, elements->xml_path, elements->xml_attr, node)) ++ prop = g_object_class_find_property(G_OBJECT_GET_CLASS(object), elements->prop_name); ++ g_return_val_if_fail(prop != NULL, FALSE); ++ ++ g_value_init(&value, prop->value_type); ++ if (_set_property_value_from_type(&value, prop->value_type, elements->xml_path, elements->xml_attr, node)) + g_object_set_property(object, elements->prop_name, &value); + g_value_unset(&value); + } +diff --git a/govirt/ovirt-utils.h b/govirt/ovirt-utils.h +index 545847a..e03f453 100644 +--- a/govirt/ovirt-utils.h ++++ b/govirt/ovirt-utils.h +@@ -31,7 +31,6 @@ typedef struct _OvirtXmlElement OvirtXmlElement; + struct _OvirtXmlElement + { + const char *prop_name; +- GType type; + const char *xml_path; + const char *xml_attr; /* if NULL, retrieve node content instead of attribute */ + }; +diff --git a/govirt/ovirt-vm.c b/govirt/ovirt-vm.c +index 70b6f3a..36ffd35 100644 +--- a/govirt/ovirt-vm.c ++++ b/govirt/ovirt-vm.c +@@ -184,22 +184,18 @@ static gboolean ovirt_vm_init_from_xml(OvirtResource *resource, + OvirtResourceClass *parent_class; + OvirtXmlElement vm_elements[] = { + { .prop_name = "host-href", +- .type = G_TYPE_STRING, + .xml_path = "host", + .xml_attr = "href", + }, + { .prop_name = "host-id", +- .type = G_TYPE_STRING, + .xml_path = "host", + .xml_attr = "id", + }, + { .prop_name = "cluster-href", +- .type = G_TYPE_STRING, + .xml_path = "cluster", + .xml_attr = "href", + }, + { .prop_name = "cluster-id", +- .type = G_TYPE_STRING, + .xml_path = "cluster", + .xml_attr = "id", + }, diff --git a/SOURCES/0033-utils-Support-G_TYPE_UINT-in-_set_property_value_fro.patch b/SOURCES/0033-utils-Support-G_TYPE_UINT-in-_set_property_value_fro.patch new file mode 100644 index 0000000..49acbeb --- /dev/null +++ b/SOURCES/0033-utils-Support-G_TYPE_UINT-in-_set_property_value_fro.patch @@ -0,0 +1,39 @@ +From 7eae90f67d00bf36c0a9c56cf3c9e4fdc7d02494 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Wed, 10 May 2017 15:53:12 -0300 +Subject: [PATCH] utils: Support G_TYPE_UINT in _set_property_value_from_type() + +This type will mostly be used to parse the XML elements for +OvirtVmDisplay. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-utils.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/govirt/ovirt-utils.c b/govirt/ovirt-utils.c +index 501acb9..af1dfc6 100644 +--- a/govirt/ovirt-utils.c ++++ b/govirt/ovirt-utils.c +@@ -23,6 +23,7 @@ + #include + + #include ++#include + #include + + #include +@@ -182,6 +183,11 @@ _set_property_value_from_type(GValue *value, + g_value_set_string(value, value_str); + break; + } ++ case G_TYPE_UINT: { ++ guint uint_value = strtoul(value_str, NULL, 0); ++ g_value_set_uint(value, uint_value); ++ break; ++ } + case G_TYPE_UINT64: { + guint64 int64_value = g_ascii_strtoull(value_str, NULL, 0); + g_value_set_uint64(value, int64_value); +-- +2.14.4 diff --git a/SOURCES/0034-utils-Improve-log-message-when-subnode-is-not-found.patch b/SOURCES/0034-utils-Improve-log-message-when-subnode-is-not-found.patch new file mode 100644 index 0000000..0b7eda9 --- /dev/null +++ b/SOURCES/0034-utils-Improve-log-message-when-subnode-is-not-found.patch @@ -0,0 +1,28 @@ +From 5a41846ba6e0d88a0a641caa214703336e2b2820 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Mon, 18 Sep 2017 10:47:13 -0300 +Subject: [PATCH] utils: Improve log message when subnode is not found + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-utils.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/govirt/ovirt-utils.c b/govirt/ovirt-utils.c +index af1dfc6..a60c754 100644 +--- a/govirt/ovirt-utils.c ++++ b/govirt/ovirt-utils.c +@@ -63,9 +63,10 @@ ovirt_rest_xml_node_find(RestXmlNode *node, const char *path) + pathv = g_strsplit(path, "/", -1); + + for (i = 0; i < g_strv_length(pathv); ++i) { ++ gchar *name = node->name; + node = rest_xml_node_find(node, pathv[i]); + if (node == NULL) { +- g_debug("could not find XML node '%s'", pathv[i]); ++ g_debug("could not find subnode '%s' of XML node '%s' (search: %s)", pathv[i], name, path); + break; + } + } +-- +2.14.4 diff --git a/SOURCES/0035-utils-Factor-out-basic-value-type-setting-from-_set_.patch b/SOURCES/0035-utils-Factor-out-basic-value-type-setting-from-_set_.patch new file mode 100644 index 0000000..fbd2db6 --- /dev/null +++ b/SOURCES/0035-utils-Factor-out-basic-value-type-setting-from-_set_.patch @@ -0,0 +1,92 @@ +From 1bff3d3ca4101639e659c8649731020e7a5c9c10 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Tue, 3 Oct 2017 17:32:03 -0300 +Subject: [PATCH] utils: Factor out basic value type setting from + _set_property_value_from_type() + +A simple cosmetic enhancement with the hope to improve code readability. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-utils.c | 59 ++++++++++++++++++++++++++++++---------------------- + 1 file changed, 34 insertions(+), 25 deletions(-) + +diff --git a/govirt/ovirt-utils.c b/govirt/ovirt-utils.c +index a60c754..a0146fd 100644 +--- a/govirt/ovirt-utils.c ++++ b/govirt/ovirt-utils.c +@@ -134,6 +134,39 @@ ovirt_rest_xml_node_get_str_array_from_path(RestXmlNode *node, const char *path, + return (GStrv) g_array_free(array, FALSE); + } + ++static gboolean ++_set_property_value_from_basic_type(GValue *value, ++ GType type, ++ const char *value_str) ++{ ++ switch(type) { ++ case G_TYPE_BOOLEAN: { ++ gboolean bool_value = ovirt_utils_boolean_from_string(value_str); ++ g_value_set_boolean(value, bool_value); ++ return TRUE; ++ } ++ case G_TYPE_STRING: { ++ g_value_set_string(value, value_str); ++ return TRUE; ++ } ++ case G_TYPE_UINT: { ++ guint uint_value = strtoul(value_str, NULL, 0); ++ g_value_set_uint(value, uint_value); ++ return TRUE; ++ } ++ case G_TYPE_UINT64: { ++ guint64 int64_value = g_ascii_strtoull(value_str, NULL, 0); ++ g_value_set_uint64(value, int64_value); ++ return TRUE; ++ } ++ default: { ++ g_warning("Unexpected type '%s' with value '%s'", g_type_name(type), value_str); ++ } ++ } ++ ++ return FALSE; ++} ++ + static gboolean + _set_property_value_from_type(GValue *value, + GType type, +@@ -174,31 +207,7 @@ _set_property_value_from_type(GValue *value, + goto end; + } + +- switch(type) { +- case G_TYPE_BOOLEAN: { +- gboolean bool_value = ovirt_utils_boolean_from_string(value_str); +- g_value_set_boolean(value, bool_value); +- break; +- } +- case G_TYPE_STRING: { +- g_value_set_string(value, value_str); +- break; +- } +- case G_TYPE_UINT: { +- guint uint_value = strtoul(value_str, NULL, 0); +- g_value_set_uint(value, uint_value); +- break; +- } +- case G_TYPE_UINT64: { +- guint64 int64_value = g_ascii_strtoull(value_str, NULL, 0); +- g_value_set_uint64(value, int64_value); +- break; +- } +- default: { +- g_warning("Unexpected type '%s' with value '%s'", g_type_name(type), value_str); +- ret = FALSE; +- } +- } ++ ret = _set_property_value_from_basic_type(value, type, value_str); + + end: + return ret; +-- +2.14.4 diff --git a/SOURCES/0036-utils-Get-enum-default-value-from-GParamSpec.patch b/SOURCES/0036-utils-Get-enum-default-value-from-GParamSpec.patch new file mode 100644 index 0000000..57f433d --- /dev/null +++ b/SOURCES/0036-utils-Get-enum-default-value-from-GParamSpec.patch @@ -0,0 +1,54 @@ +From 290692dcf6d572e86a2a90ff87f666ea148eb602 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Tue, 3 Oct 2017 17:51:41 -0300 +Subject: [PATCH] utils: Get enum default value from GParamSpec + +Instead of assuming 0 as the default value, use the one specified during +property creation time with g_param_spec_enum(). + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-utils.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/govirt/ovirt-utils.c b/govirt/ovirt-utils.c +index a0146fd..dfaf09d 100644 +--- a/govirt/ovirt-utils.c ++++ b/govirt/ovirt-utils.c +@@ -169,13 +169,14 @@ _set_property_value_from_basic_type(GValue *value, + + static gboolean + _set_property_value_from_type(GValue *value, +- GType type, ++ GParamSpec *prop, + const char *path, + const char *attr, + RestXmlNode *node) + { + gboolean ret = TRUE; + const char *value_str; ++ GType type = prop->value_type; + + if (g_type_is_a(type, OVIRT_TYPE_RESOURCE)) { + OvirtResource *resource_value = ovirt_resource_new_from_xml(type, node, NULL); +@@ -202,7 +203,8 @@ _set_property_value_from_type(GValue *value, + return FALSE; + + if (G_TYPE_IS_ENUM(type)) { +- int enum_value = ovirt_utils_genum_get_value(type, value_str, 0); ++ GParamSpecEnum *enum_prop = G_PARAM_SPEC_ENUM(prop); ++ int enum_value = ovirt_utils_genum_get_value(type, value_str, enum_prop->default_value); + g_value_set_enum(value, enum_value); + goto end; + } +@@ -229,7 +231,7 @@ ovirt_rest_xml_node_parse(RestXmlNode *node, + g_return_val_if_fail(prop != NULL, FALSE); + + g_value_init(&value, prop->value_type); +- if (_set_property_value_from_type(&value, prop->value_type, elements->xml_path, elements->xml_attr, node)) ++ if (_set_property_value_from_type(&value, prop, elements->xml_path, elements->xml_attr, node)) + g_object_set_property(object, elements->prop_name, &value); + g_value_unset(&value); + } +-- +2.14.4 diff --git a/SOURCES/0037-vm-Set-vm-state-property-using-OvirtXmlElement-struc.patch b/SOURCES/0037-vm-Set-vm-state-property-using-OvirtXmlElement-struc.patch new file mode 100644 index 0000000..67111ff --- /dev/null +++ b/SOURCES/0037-vm-Set-vm-state-property-using-OvirtXmlElement-struc.patch @@ -0,0 +1,81 @@ +From 039c8d8bc0aa49ea3bd34fc190afc844d68a6e41 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Thu, 4 May 2017 18:23:39 -0300 +Subject: [PATCH] vm: Set vm state property using OvirtXmlElement struct + +It was required to change the default value of the enum property to +OVIRT_VM_STATE_UNKNOWN, so that it will be set by +ovirt_rest_xml_node_parse() function in case of error. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-vm-xml.c | 30 +----------------------------- + govirt/ovirt-vm.c | 5 ++++- + 2 files changed, 5 insertions(+), 30 deletions(-) + +diff --git a/govirt/ovirt-vm-xml.c b/govirt/ovirt-vm-xml.c +index 9990262..25f50f3 100644 +--- a/govirt/ovirt-vm-xml.c ++++ b/govirt/ovirt-vm-xml.c +@@ -138,35 +138,7 @@ static gboolean vm_set_display_from_xml(OvirtVm *vm, + return TRUE; + } + +-static gboolean vm_set_state_from_xml(OvirtVm *vm, RestXmlNode *node) +-{ +- RestXmlNode *state_node; +- +- state_node = rest_xml_node_find(node, "status"); +- if (state_node == NULL) { +- g_debug("Could not find 'status' node"); +- return FALSE; +- } +- state_node = rest_xml_node_find(state_node, "state"); +- if (state_node != NULL) { +- int state; +- +- g_return_val_if_fail(state_node->content != NULL, FALSE); +- state = ovirt_utils_genum_get_value(OVIRT_TYPE_VM_STATE, +- state_node->content, +- OVIRT_VM_STATE_UNKNOWN); +- g_object_set(G_OBJECT(vm), "state", state, NULL); +- +- return TRUE; +- } +- +- return FALSE; +-} +- + G_GNUC_INTERNAL gboolean ovirt_vm_refresh_from_xml(OvirtVm *vm, RestXmlNode *node) + { +- vm_set_state_from_xml(vm, node); +- vm_set_display_from_xml(vm, node); +- +- return TRUE; ++ return vm_set_display_from_xml(vm, node); + } +diff --git a/govirt/ovirt-vm.c b/govirt/ovirt-vm.c +index 36ffd35..f30022d 100644 +--- a/govirt/ovirt-vm.c ++++ b/govirt/ovirt-vm.c +@@ -199,6 +199,9 @@ static gboolean ovirt_vm_init_from_xml(OvirtResource *resource, + .xml_path = "cluster", + .xml_attr = "id", + }, ++ { .prop_name = "state", ++ .xml_path = "status/state", ++ }, + { NULL, }, + }; + +@@ -233,7 +236,7 @@ static void ovirt_vm_class_init(OvirtVmClass *klass) + "State", + "Virtual Machine State", + OVIRT_TYPE_VM_STATE, +- OVIRT_VM_STATE_DOWN, ++ OVIRT_VM_STATE_UNKNOWN, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property(object_class, +-- +2.14.4 diff --git a/SOURCES/0038-vm-Set-values-of-OvirtVmDisplay-using-OvirtXmlElemen.patch b/SOURCES/0038-vm-Set-values-of-OvirtVmDisplay-using-OvirtXmlElemen.patch new file mode 100644 index 0000000..2aae0d0 --- /dev/null +++ b/SOURCES/0038-vm-Set-values-of-OvirtVmDisplay-using-OvirtXmlElemen.patch @@ -0,0 +1,189 @@ +From b8b0d03e43bee40ad15fa4c3aa6ca8b07ca98e31 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Wed, 10 May 2017 15:48:09 -0300 +Subject: [PATCH] vm: Set values of OvirtVmDisplay using OvirtXmlElement struct + +This required the addition of OVIRT_VM_DISPLAY_INVALID to the +OvirtVmDisplayType enum as the default value. + +The value of the 'type' property of OvirtVmDisplay is tested after the +parsing is done, to ensure it is either vnc or spice. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-vm-display.c | 2 +- + govirt/ovirt-vm-display.h | 3 +- + govirt/ovirt-vm-xml.c | 118 ++++++++++++++-------------------------------- + 3 files changed, 38 insertions(+), 85 deletions(-) + +diff --git a/govirt/ovirt-vm-display.c b/govirt/ovirt-vm-display.c +index 37e042a..b03c303 100644 +--- a/govirt/ovirt-vm-display.c ++++ b/govirt/ovirt-vm-display.c +@@ -197,7 +197,7 @@ static void ovirt_vm_display_class_init(OvirtVmDisplayClass *klass) + "Type", + "Display Type", + OVIRT_TYPE_VM_DISPLAY_TYPE, +- OVIRT_VM_DISPLAY_SPICE, ++ OVIRT_VM_DISPLAY_INVALID, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property(object_class, +diff --git a/govirt/ovirt-vm-display.h b/govirt/ovirt-vm-display.h +index f7eb310..38ef9b7 100644 +--- a/govirt/ovirt-vm-display.h ++++ b/govirt/ovirt-vm-display.h +@@ -55,7 +55,8 @@ struct _OvirtVmDisplayClass + + typedef enum { + OVIRT_VM_DISPLAY_SPICE, +- OVIRT_VM_DISPLAY_VNC ++ OVIRT_VM_DISPLAY_VNC, ++ OVIRT_VM_DISPLAY_INVALID, + } OvirtVmDisplayType; + + GType ovirt_vm_display_get_type(void); +diff --git a/govirt/ovirt-vm-xml.c b/govirt/ovirt-vm-xml.c +index 25f50f3..0603427 100644 +--- a/govirt/ovirt-vm-xml.c ++++ b/govirt/ovirt-vm-xml.c +@@ -33,102 +33,54 @@ + static gboolean vm_set_display_from_xml(OvirtVm *vm, + RestXmlNode *root) + { +- RestXmlNode *node; + OvirtVmDisplay *display; +- const char *display_key = g_intern_string("display"); +- const char *type_key = g_intern_string("type"); +- const char *address_key = g_intern_string("address"); +- const char *port_key = g_intern_string("port"); +- const char *secure_port_key = g_intern_string("secure_port"); +- const char *monitors_key = g_intern_string("monitors"); +- const char *certificate_key = g_intern_string("certificate"); +- const char *smartcard_key = g_intern_string("smartcard_enabled"); +- const char *allow_override_key = g_intern_string("allow_override"); +- const char *proxy_key = g_intern_string("proxy"); ++ OvirtVmDisplayType type; ++ OvirtXmlElement display_elements[] = { ++ { .prop_name = "type", ++ .xml_path = "type", ++ }, ++ { .prop_name = "address", ++ .xml_path = "address", ++ }, ++ { .prop_name = "port", ++ .xml_path = "port", ++ }, ++ { .prop_name = "secure-port", ++ .xml_path = "secure_port", ++ }, ++ { .prop_name = "monitor-count", ++ .xml_path = "monitors", ++ }, ++ { .prop_name = "smartcard", ++ .xml_path = "smartcard_enabled", ++ }, ++ { .prop_name = "allow-override", ++ .xml_path = "allow_override", ++ }, ++ { .prop_name = "host-subject", ++ .xml_path = "certificate/subject", ++ }, ++ { .prop_name = "proxy-url", ++ .xml_path = "proxy", ++ }, ++ { NULL, }, ++ }; + + if (root == NULL) { + return FALSE; + } +- root = g_hash_table_lookup(root->children, display_key); ++ root = rest_xml_node_find(root, "display"); + if (root == NULL) { + g_debug("Could not find 'display' node"); + return FALSE; + } + display = ovirt_vm_display_new(); +- +- node = g_hash_table_lookup(root->children, type_key); +- g_return_val_if_fail(node != NULL, FALSE); +- if (g_strcmp0(node->content, "spice") == 0) { +- g_object_set(G_OBJECT(display), "type", OVIRT_VM_DISPLAY_SPICE, NULL); +- } else if (g_strcmp0(node->content, "vnc") == 0) { +- g_object_set(G_OBJECT(display), "type", OVIRT_VM_DISPLAY_VNC, NULL); +- } else { +- g_warning("Unknown display type: %s", node->content); ++ ovirt_rest_xml_node_parse(root, G_OBJECT(display), display_elements); ++ g_object_get(G_OBJECT(display), "type", &type, NULL); ++ if (type == OVIRT_VM_DISPLAY_INVALID) { + return FALSE; + } + +- node = g_hash_table_lookup(root->children, monitors_key); +- g_return_val_if_fail(node != NULL, FALSE); +- g_object_set(G_OBJECT(display), +- "monitor-count", strtoul(node->content, NULL, 0), +- NULL); +- +- /* on non started VMs, these 2 values will not be available */ +- node = g_hash_table_lookup(root->children, address_key); +- if (node != NULL) { +- g_object_set(G_OBJECT(display), "address", node->content, NULL); +- } +- +- node = g_hash_table_lookup(root->children, port_key); +- if (node != NULL) { +- g_object_set(G_OBJECT(display), +- "port", strtoul(node->content, NULL, 0), +- NULL); +- } +- +- node = g_hash_table_lookup(root->children, secure_port_key); +- if (node != NULL) { +- g_object_set(G_OBJECT(display), +- "secure-port", strtoul(node->content, NULL, 0), +- NULL); +- } +- +- node = g_hash_table_lookup(root->children, smartcard_key); +- if (node != NULL) { +- gboolean smartcard; +- +- smartcard = (g_strcmp0(node->content, "true") == 0); +- g_object_set(G_OBJECT(display), +- "smartcard", smartcard, +- NULL); +- } +- +- node = g_hash_table_lookup(root->children, allow_override_key); +- if (node != NULL) { +- gboolean allow_override; +- +- allow_override = (g_strcmp0(node->content, "true") == 0); +- g_object_set(G_OBJECT(display), +- "allow-override", allow_override, +- NULL); +- } +- +- node = g_hash_table_lookup(root->children, certificate_key); +- if (node != NULL) { +- const char *subject_key = g_intern_string("subject"); +- node = g_hash_table_lookup(node->children, subject_key); +- if (node != NULL) { +- g_object_set(G_OBJECT(display), +- "host-subject", node->content, +- NULL); +- } +- } +- +- node = g_hash_table_lookup(root->children, proxy_key); +- if (node != NULL) { +- g_object_set(G_OBJECT(display), "proxy-url", node->content, NULL); +- } +- + /* FIXME: this overrides the ticket/expiry which may + * already be set + */ +-- +2.14.4 diff --git a/SOURCES/0039-vm-display-Move-XML-parsing-from-ovirt-vm-xml.c-file.patch b/SOURCES/0039-vm-display-Move-XML-parsing-from-ovirt-vm-xml.c-file.patch new file mode 100644 index 0000000..8c25902 --- /dev/null +++ b/SOURCES/0039-vm-display-Move-XML-parsing-from-ovirt-vm-xml.c-file.patch @@ -0,0 +1,265 @@ +From c81f18b9dd4888145ac979addb4ef5d73585a176 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Tue, 19 Sep 2017 12:02:32 -0300 +Subject: [PATCH] vm-display: Move XML parsing from ovirt-vm-xml.c file + +Following the model of other resources, the code for parsing the XML +elements for the OvirtVmDisplay object where it really belongs to. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/Makefile.am | 1 - + govirt/ovirt-vm-display.c | 60 +++++++++++++++++++++++++++++ + govirt/ovirt-vm-display.h | 2 + + govirt/ovirt-vm-xml.c | 96 ----------------------------------------------- + govirt/ovirt-vm.c | 15 ++++++-- + 5 files changed, 74 insertions(+), 100 deletions(-) + delete mode 100644 govirt/ovirt-vm-xml.c + +diff --git a/govirt/Makefile.am b/govirt/Makefile.am +index 9bf0eba..1a59f2c 100644 +--- a/govirt/Makefile.am ++++ b/govirt/Makefile.am +@@ -73,7 +73,6 @@ libgovirt_la_SOURCES = \ + ovirt-utils.c \ + ovirt-vm.c \ + ovirt-vm-display.c \ +- ovirt-vm-xml.c \ + ovirt-vm-pool.c \ + $(NULL) + +diff --git a/govirt/ovirt-vm-display.c b/govirt/ovirt-vm-display.c +index b03c303..ebb04c2 100644 +--- a/govirt/ovirt-vm-display.c ++++ b/govirt/ovirt-vm-display.c +@@ -24,6 +24,7 @@ + + #include "ovirt-enum-types.h" + #include "ovirt-vm-display.h" ++#include "ovirt-utils.h" + + #define OVIRT_VM_DISPLAY_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), OVIRT_TYPE_VM_DISPLAY, OvirtVmDisplayPrivate)) +@@ -303,3 +304,62 @@ OvirtVmDisplay *ovirt_vm_display_new(void) + { + return OVIRT_VM_DISPLAY(g_object_new(OVIRT_TYPE_VM_DISPLAY, NULL)); + } ++ ++static gboolean ovirt_vm_display_set_from_xml(OvirtVmDisplay *display, RestXmlNode *node) ++{ ++ OvirtVmDisplayType type; ++ OvirtXmlElement display_elements[] = { ++ { .prop_name = "type", ++ .xml_path = "type", ++ }, ++ { .prop_name = "address", ++ .xml_path = "address", ++ }, ++ { .prop_name = "port", ++ .xml_path = "port", ++ }, ++ { .prop_name = "secure-port", ++ .xml_path = "secure_port", ++ }, ++ { .prop_name = "monitor-count", ++ .xml_path = "monitors", ++ }, ++ { .prop_name = "smartcard", ++ .xml_path = "smartcard_enabled", ++ }, ++ { .prop_name = "allow-override", ++ .xml_path = "allow_override", ++ }, ++ { .prop_name = "host-subject", ++ .xml_path = "certificate/subject", ++ }, ++ { .prop_name = "proxy-url", ++ .xml_path = "proxy", ++ }, ++ { NULL, }, ++ }; ++ ++ ovirt_rest_xml_node_parse(node, G_OBJECT(display), display_elements); ++ g_object_get(G_OBJECT(display), "type", &type, NULL); ++ if (type == OVIRT_VM_DISPLAY_INVALID) { ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++OvirtVmDisplay *ovirt_vm_display_new_from_xml(RestXmlNode *node) ++{ ++ OvirtVmDisplay *display; ++ ++ g_return_val_if_fail(node != NULL, NULL); ++ ++ display = ovirt_vm_display_new(); ++ ++ if (!ovirt_vm_display_set_from_xml(display, node)) { ++ g_object_unref(display); ++ return NULL; ++ } ++ ++ return display; ++} +diff --git a/govirt/ovirt-vm-display.h b/govirt/ovirt-vm-display.h +index 38ef9b7..11a5074 100644 +--- a/govirt/ovirt-vm-display.h ++++ b/govirt/ovirt-vm-display.h +@@ -24,6 +24,7 @@ + + #include + #include ++#include + + G_BEGIN_DECLS + +@@ -61,6 +62,7 @@ typedef enum { + + GType ovirt_vm_display_get_type(void); + OvirtVmDisplay *ovirt_vm_display_new(void); ++OvirtVmDisplay *ovirt_vm_display_new_from_xml(RestXmlNode *node); + + G_END_DECLS + +diff --git a/govirt/ovirt-vm-xml.c b/govirt/ovirt-vm-xml.c +deleted file mode 100644 +index 0603427..0000000 +--- a/govirt/ovirt-vm-xml.c ++++ /dev/null +@@ -1,96 +0,0 @@ +-/* +- * ovirt-vm-xml.c +- * +- * Copyright (C) 2011, 2013 Red Hat, Inc. +- * +- * 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, see +- * . +- * +- * Author: Christophe Fergeau +- */ +-#include +- +-#include +-#include +- +-#include "ovirt-enum-types.h" +-#include "ovirt-utils.h" +-#include "ovirt-vm.h" +-#include "ovirt-vm-display.h" +-#include "ovirt-vm-private.h" +- +-static gboolean vm_set_display_from_xml(OvirtVm *vm, +- RestXmlNode *root) +-{ +- OvirtVmDisplay *display; +- OvirtVmDisplayType type; +- OvirtXmlElement display_elements[] = { +- { .prop_name = "type", +- .xml_path = "type", +- }, +- { .prop_name = "address", +- .xml_path = "address", +- }, +- { .prop_name = "port", +- .xml_path = "port", +- }, +- { .prop_name = "secure-port", +- .xml_path = "secure_port", +- }, +- { .prop_name = "monitor-count", +- .xml_path = "monitors", +- }, +- { .prop_name = "smartcard", +- .xml_path = "smartcard_enabled", +- }, +- { .prop_name = "allow-override", +- .xml_path = "allow_override", +- }, +- { .prop_name = "host-subject", +- .xml_path = "certificate/subject", +- }, +- { .prop_name = "proxy-url", +- .xml_path = "proxy", +- }, +- { NULL, }, +- }; +- +- if (root == NULL) { +- return FALSE; +- } +- root = rest_xml_node_find(root, "display"); +- if (root == NULL) { +- g_debug("Could not find 'display' node"); +- return FALSE; +- } +- display = ovirt_vm_display_new(); +- ovirt_rest_xml_node_parse(root, G_OBJECT(display), display_elements); +- g_object_get(G_OBJECT(display), "type", &type, NULL); +- if (type == OVIRT_VM_DISPLAY_INVALID) { +- return FALSE; +- } +- +- /* FIXME: this overrides the ticket/expiry which may +- * already be set +- */ +- g_object_set(G_OBJECT(vm), "display", display, NULL); +- g_object_unref(G_OBJECT(display)); +- +- return TRUE; +-} +- +-G_GNUC_INTERNAL gboolean ovirt_vm_refresh_from_xml(OvirtVm *vm, RestXmlNode *node) +-{ +- return vm_set_display_from_xml(vm, node); +-} +diff --git a/govirt/ovirt-vm.c b/govirt/ovirt-vm.c +index f30022d..95c1e4d 100644 +--- a/govirt/ovirt-vm.c ++++ b/govirt/ovirt-vm.c +@@ -180,7 +180,8 @@ static gboolean ovirt_vm_init_from_xml(OvirtResource *resource, + RestXmlNode *node, + GError **error) + { +- gboolean parsed_ok; ++ OvirtVmDisplay *display; ++ RestXmlNode *display_node; + OvirtResourceClass *parent_class; + OvirtXmlElement vm_elements[] = { + { .prop_name = "host-href", +@@ -205,11 +206,19 @@ static gboolean ovirt_vm_init_from_xml(OvirtResource *resource, + { NULL, }, + }; + +- parsed_ok = ovirt_vm_refresh_from_xml(OVIRT_VM(resource), node); +- if (!parsed_ok) { ++ display_node = rest_xml_node_find(node, "display"); ++ if (display_node == NULL) { ++ g_debug("Could not find 'display' node"); + return FALSE; + } + ++ display = ovirt_vm_display_new_from_xml(display_node); ++ if (display == NULL) ++ return FALSE; ++ ++ g_object_set(G_OBJECT(resource), "display", display, NULL); ++ g_object_unref(G_OBJECT(display)); ++ + if (!ovirt_rest_xml_node_parse(node, G_OBJECT(resource), vm_elements)) + return FALSE; + +-- +2.14.4 diff --git a/SOURCES/0040-vm-Set-ticket-expiry-using-OvirtXmlElement-struct.patch b/SOURCES/0040-vm-Set-ticket-expiry-using-OvirtXmlElement-struct.patch new file mode 100644 index 0000000..e6a08e0 --- /dev/null +++ b/SOURCES/0040-vm-Set-ticket-expiry-using-OvirtXmlElement-struct.patch @@ -0,0 +1,97 @@ +From 3a92d61ba92b85c0d31aa836713344085dab813e Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Wed, 10 May 2017 15:16:27 -0300 +Subject: [PATCH] vm: Set 'ticket/expiry' using OvirtXmlElement struct + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-vm.c | 56 +++++++++++++++++++++++++++++++------------------------ + 1 file changed, 32 insertions(+), 24 deletions(-) + +diff --git a/govirt/ovirt-vm.c b/govirt/ovirt-vm.c +index 95c1e4d..8cd482b 100644 +--- a/govirt/ovirt-vm.c ++++ b/govirt/ovirt-vm.c +@@ -381,48 +381,56 @@ gboolean ovirt_vm_stop(OvirtVm *vm, OvirtProxy *proxy, GError **error) + + static gboolean parse_ticket_status(RestXmlNode *root, OvirtResource *resource, GError **error) + { +- OvirtVm *vm; +- RestXmlNode *node; +- const char *ticket_key = g_intern_string("ticket"); +- const char *value_key = g_intern_string("value"); +- const char *expiry_key = g_intern_string("expiry"); + OvirtVmDisplay *display; ++ gchar *ticket = NULL; ++ guint expiry = 0; ++ gboolean ret = FALSE; ++ OvirtXmlElement ticket_elements[] = { ++ { .prop_name = "ticket", ++ .xml_path = "value", ++ }, ++ { .prop_name = "expiry", ++ .xml_path = "expiry", ++ }, ++ { NULL, }, ++ }; + + g_return_val_if_fail(root != NULL, FALSE); + g_return_val_if_fail(OVIRT_IS_VM(resource), FALSE); + g_return_val_if_fail(error == NULL || *error == NULL, FALSE); + +- vm = OVIRT_VM(resource); +- root = g_hash_table_lookup(root->children, ticket_key); ++ g_object_get(G_OBJECT(resource), "display", &display, NULL); ++ g_return_val_if_fail(display != NULL, FALSE); ++ ++ root = rest_xml_node_find(root, "ticket"); + if (root == NULL) { + g_set_error(error, OVIRT_ERROR, OVIRT_ERROR_PARSING_FAILED, + _("Could not find 'ticket' node")); +- g_return_val_if_reached(FALSE); ++ goto end; + } +- node = g_hash_table_lookup(root->children, value_key); +- if (node == NULL) { ++ ++ ovirt_rest_xml_node_parse(root, G_OBJECT(display), ticket_elements); ++ ++ g_object_get(G_OBJECT(display), "ticket", &ticket, "expiry", &expiry, NULL); ++ ++ if (ticket == NULL) { + g_set_error(error, OVIRT_ERROR, OVIRT_ERROR_PARSING_FAILED, + _("Could not find 'value' node")); +- g_return_val_if_reached(FALSE); ++ goto end; + } ++ g_free(ticket); + +- g_object_get(G_OBJECT(vm), "display", &display, NULL); +- g_return_val_if_fail(display != NULL, FALSE); +- g_object_set(G_OBJECT(display), "ticket", node->content, NULL); +- +- node = g_hash_table_lookup(root->children, expiry_key); +- if (node == NULL) { ++ if (expiry == 0) { + g_set_error(error, OVIRT_ERROR, OVIRT_ERROR_PARSING_FAILED, + _("Could not find 'expiry' node")); +- g_object_unref(G_OBJECT(display)); +- g_return_val_if_reached(FALSE); ++ goto end; + } +- g_object_set(G_OBJECT(display), +- "expiry", strtoul(node->content, NULL, 0), +- NULL); ++ ++ ret = TRUE; ++ ++end: + g_object_unref(G_OBJECT(display)); +- +- return TRUE; ++ return ret; + } + + +-- +2.14.4 diff --git a/SOURCES/0041-test-govirt-Add-display-node-to-vm-XMLs.patch b/SOURCES/0041-test-govirt-Add-display-node-to-vm-XMLs.patch new file mode 100644 index 0000000..ae0d7ff --- /dev/null +++ b/SOURCES/0041-test-govirt-Add-display-node-to-vm-XMLs.patch @@ -0,0 +1,38 @@ +From a2abf332bf99baf1d6b6a96d9153b44efdedf384 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Fri, 22 Jun 2018 18:18:53 -0300 +Subject: [PATCH] test-govirt: Add 'display' node to vm XMLs + +Makes 'make distcheck' pass again. Test-govirt was failing since commit +039c8d8, because the 'display' node is mandatory, but the return value +of the function vm_set_display_from_xml() had been ignored. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + tests/test-govirt.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/tests/test-govirt.c b/tests/test-govirt.c +index 247a27a..7f2cd57 100644 +--- a/tests/test-govirt.c ++++ b/tests/test-govirt.c +@@ -194,9 +194,17 @@ static void test_govirt_list_duplicate_vms(void) + const char *vms_body = " \ + \ + vm0 \ ++ \ ++ spice \ ++ 1 \ ++ \ + \ + \ + vm0 \ ++ \ ++ spice \ ++ 1 \ ++ \ + \ + "; + +-- +2.14.4 diff --git a/SOURCES/0042-proxy-Set-detailed-error-message-for-async-call.patch b/SOURCES/0042-proxy-Set-detailed-error-message-for-async-call.patch new file mode 100644 index 0000000..53bb6a1 --- /dev/null +++ b/SOURCES/0042-proxy-Set-detailed-error-message-for-async-call.patch @@ -0,0 +1,65 @@ +From 01563a00550dd001f080aeddd8c6bbc35c676991 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Wed, 11 Jul 2018 15:42:16 -0300 +Subject: [PATCH] proxy: Set detailed error message for async call + +The rest API returns more detailed error messages with the result, not +only the literal corresponding to the value. If this is the case, we set +a new error message and return it. + +For example, before this change, virt-viewer showed a dialog with a +vague 'Bad Request' message, and now a much more detailed 'Operation +Failed: query execution failed due to insufficient permissions.' + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-proxy.c | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +diff --git a/govirt/ovirt-proxy.c b/govirt/ovirt-proxy.c +index 921e22e..f8e629e 100644 +--- a/govirt/ovirt-proxy.c ++++ b/govirt/ovirt-proxy.c +@@ -240,6 +240,22 @@ call_async_cancelled_cb (G_GNUC_UNUSED GCancellable *cancellable, + } + + ++static void rest_call_async_set_error(RestProxyCall *call, GSimpleAsyncResult *result, const GError *error) ++{ ++ GError *local_error = NULL; ++ RestXmlNode *root = ovirt_rest_xml_node_from_call(call); ++ ++ if (root != NULL && ovirt_utils_gerror_from_xml_fault(root, &local_error)) { ++ g_debug("ovirt_rest_call_async(): %s", local_error->message); ++ g_simple_async_result_set_from_error(result, local_error); ++ g_clear_error(&local_error); ++ } else { ++ g_simple_async_result_set_from_error(result, error); ++ } ++ ++ rest_xml_node_unref(root); ++} ++ + static void + call_async_cb(RestProxyCall *call, const GError *error, + G_GNUC_UNUSED GObject *weak_object, +@@ -249,7 +265,7 @@ call_async_cb(RestProxyCall *call, const GError *error, + GSimpleAsyncResult *result = data->result; + + if (error != NULL) { +- g_simple_async_result_set_from_error(result, error); ++ rest_call_async_set_error(call, result, error); + } else { + GError *call_error = NULL; + gboolean callback_result = TRUE; +@@ -259,7 +275,7 @@ call_async_cb(RestProxyCall *call, const GError *error, + data->call_user_data, + &call_error); + if (call_error != NULL) { +- g_simple_async_result_set_from_error(result, call_error); ++ rest_call_async_set_error(call, result, call_error); + } + } + +-- +2.20.1 diff --git a/SOURCES/0043-cdrom-Set-file-property-using-OvirtXmlElement-struct.patch b/SOURCES/0043-cdrom-Set-file-property-using-OvirtXmlElement-struct.patch new file mode 100644 index 0000000..abc291f --- /dev/null +++ b/SOURCES/0043-cdrom-Set-file-property-using-OvirtXmlElement-struct.patch @@ -0,0 +1,107 @@ +From 53fb63d610503679bd3f4e2780989076544ddb14 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Thu, 4 May 2017 15:54:02 -0300 +Subject: [PATCH] cdrom: Set file property using OvirtXmlElement struct + +This was the last place left to move to the new automatic parsing +scheme. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-cdrom.c | 57 +++++++++++++++++--------------------------- + 1 file changed, 22 insertions(+), 35 deletions(-) + +diff --git a/govirt/ovirt-cdrom.c b/govirt/ovirt-cdrom.c +index d852403..5bab7d3 100644 +--- a/govirt/ovirt-cdrom.c ++++ b/govirt/ovirt-cdrom.c +@@ -28,6 +28,7 @@ + #include "ovirt-proxy-private.h" + #include "ovirt-resource-private.h" + #include "ovirt-resource-rest-call.h" ++#include "ovirt-utils.h" + + #define OVIRT_CDROM_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), OVIRT_TYPE_CDROM, OvirtCdromPrivate)) +@@ -95,25 +96,29 @@ static void ovirt_cdrom_finalize(GObject *object) + } + + +-static gboolean ovirt_cdrom_refresh_from_xml(OvirtCdrom *cdrom, +- RestXmlNode *node) ++static gboolean ovirt_cdrom_init_from_xml(OvirtResource *resource, ++ RestXmlNode *node, ++ GError **error) + { +- RestXmlNode *file_node; +- const char *file; +- const char *file_key = g_intern_string("file"); ++ gboolean ret = FALSE; + char *name; ++ OvirtResourceClass *parent_class; ++ OvirtXmlElement cdrom_elements[] = { ++ { .prop_name = "file", ++ .xml_path = "file", ++ .xml_attr = "id", ++ }, ++ { NULL , }, ++ }; + +- file_node = g_hash_table_lookup(node->children, file_key); +- if (file_node != NULL) { +- file = rest_xml_node_get_attr(file_node, "id"); +- if (g_strcmp0(file, cdrom->priv->file) != 0) { +- g_free(cdrom->priv->file); +- cdrom->priv->file = g_strdup(file); +- g_object_notify(G_OBJECT(cdrom), "file"); +- } +- } ++ parent_class = OVIRT_RESOURCE_CLASS(ovirt_cdrom_parent_class); ++ ++ if (!parent_class->init_from_xml(resource, node, error)) ++ return FALSE; + +- g_object_get(G_OBJECT(cdrom), "name", &name, NULL); ++ ovirt_rest_xml_node_parse(node, G_OBJECT(resource), cdrom_elements); ++ ++ g_object_get(G_OBJECT(resource), "name", &name, NULL); + if (name == NULL) { + /* Build up fake name as ovirt_collection_refresh_from_xml() + * expects it to be set (it uses it as a hash table key), but +@@ -122,32 +127,14 @@ static gboolean ovirt_cdrom_refresh_from_xml(OvirtCdrom *cdrom, + * enough for now + */ + g_debug("Setting fake 'name' for cdrom resource"); +- g_object_set(G_OBJECT(cdrom), "name", "cdrom0", NULL); +- } else { +- g_free(name); ++ g_object_set(G_OBJECT(resource), "name", "cdrom0", NULL); + } + ++ g_free(name); + return TRUE; + } + + +-static gboolean ovirt_cdrom_init_from_xml(OvirtResource *resource, +- RestXmlNode *node, +- GError **error) +-{ +- gboolean parsed_ok; +- OvirtResourceClass *parent_class; +- +- parsed_ok = ovirt_cdrom_refresh_from_xml(OVIRT_CDROM(resource), node); +- if (!parsed_ok) { +- return FALSE; +- } +- parent_class = OVIRT_RESOURCE_CLASS(ovirt_cdrom_parent_class); +- +- return parent_class->init_from_xml(resource, node, error); +-} +- +- + static char *ovirt_cdrom_to_xml(OvirtResource *resource) + { + OvirtCdrom *cdrom; +-- +2.20.1 diff --git a/SOURCES/0044-proxy-Don-t-try-to-unref-NULL-root-node.patch b/SOURCES/0044-proxy-Don-t-try-to-unref-NULL-root-node.patch new file mode 100644 index 0000000..5fac578 --- /dev/null +++ b/SOURCES/0044-proxy-Don-t-try-to-unref-NULL-root-node.patch @@ -0,0 +1,30 @@ +From 8032575cbe274c9e70ec2a0efb0b536f13dbc6cd Mon Sep 17 00:00:00 2001 +From: Christophe Fergeau +Date: Fri, 21 Dec 2018 13:15:16 +0100 +Subject: [PATCH] proxy: Don't try to unref NULL root node + +When an error occurs, we may have failed to get any data, so 'root' may +be NULL. Trying to unref it triggers a critical. This happens for +example when trying to connect to a remote host with an invalid +certificate. +--- + govirt/ovirt-proxy.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/govirt/ovirt-proxy.c b/govirt/ovirt-proxy.c +index f8e629e..920ef21 100644 +--- a/govirt/ovirt-proxy.c ++++ b/govirt/ovirt-proxy.c +@@ -253,7 +253,9 @@ static void rest_call_async_set_error(RestProxyCall *call, GSimpleAsyncResult *r + g_simple_async_result_set_from_error(result, error); + } + +- rest_xml_node_unref(root); ++ if (root != NULL) { ++ rest_xml_node_unref(root); ++ } + } + + static void +-- +2.20.1 diff --git a/SOURCES/0045-utils-Check-for-valid-data-before-calling-rest_xml_p.patch b/SOURCES/0045-utils-Check-for-valid-data-before-calling-rest_xml_p.patch new file mode 100644 index 0000000..c68fd78 --- /dev/null +++ b/SOURCES/0045-utils-Check-for-valid-data-before-calling-rest_xml_p.patch @@ -0,0 +1,97 @@ +From d6ddeff795ce3f132f1e266fc813e0a4917f8bf7 Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Mon, 4 Feb 2019 15:58:40 -0200 +Subject: [PATCH] utils: Check for valid data before calling + rest_xml_parser_parse_from_data() + +In the case of HTTP errors, such as a invalid TLS certificate, the +returned data is NULL, and the code in librest does not check for the +pointer being valid, causing a segfault. + +The users of this function have been updated to check for NULL return +value. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + govirt/ovirt-proxy.c | 6 ++++++ + govirt/ovirt-resource.c | 9 ++++++++- + govirt/ovirt-utils.c | 7 +++++-- + 3 files changed, 19 insertions(+), 3 deletions(-) + +diff --git a/govirt/ovirt-proxy.c b/govirt/ovirt-proxy.c +index 920ef21..9cdd211 100644 +--- a/govirt/ovirt-proxy.c ++++ b/govirt/ovirt-proxy.c +@@ -365,6 +365,11 @@ static gboolean get_collection_xml_async_cb(OvirtProxy* proxy, + data = (OvirtProxyGetCollectionAsyncData *)user_data; + + root = ovirt_rest_xml_node_from_call(call); ++ if (root == NULL) { ++ g_set_error_literal(error, OVIRT_ERROR, OVIRT_ERROR_PARSING_FAILED, ++ _("Failed to parse response from collection")); ++ goto end; ++ } + + /* Do the parsing */ + g_warn_if_fail(data->parser != NULL); +@@ -374,6 +379,7 @@ static gboolean get_collection_xml_async_cb(OvirtProxy* proxy, + + rest_xml_node_unref(root); + ++end: + return parsed; + } + +diff --git a/govirt/ovirt-resource.c b/govirt/ovirt-resource.c +index 1984b1d..936e912 100644 +--- a/govirt/ovirt-resource.c ++++ b/govirt/ovirt-resource.c +@@ -868,17 +868,24 @@ static gboolean ovirt_resource_refresh_async_cb(OvirtProxy *proxy, + { + OvirtResource *resource; + RestXmlNode *root; +- gboolean refreshed; ++ gboolean refreshed = FALSE; + + g_return_val_if_fail(REST_IS_PROXY_CALL(call), FALSE); + g_return_val_if_fail(OVIRT_IS_RESOURCE(user_data), FALSE); + + root = ovirt_rest_xml_node_from_call(call); ++ if (root == NULL) { ++ g_set_error_literal(error, OVIRT_ERROR, OVIRT_ERROR_PARSING_FAILED, ++ _("Failed to parse response from resource")); ++ goto end; ++ } ++ + resource = OVIRT_RESOURCE(user_data); + refreshed = ovirt_resource_init_from_xml(resource, root, error); + + rest_xml_node_unref(root); + ++end: + return refreshed; + } + +diff --git a/govirt/ovirt-utils.c b/govirt/ovirt-utils.c +index dfaf09d..56ce2e1 100644 +--- a/govirt/ovirt-utils.c ++++ b/govirt/ovirt-utils.c +@@ -40,11 +40,14 @@ ovirt_rest_xml_node_from_call(RestProxyCall *call) + { + RestXmlParser *parser; + RestXmlNode *node; ++ const char * data = rest_proxy_call_get_payload (call); ++ ++ if (data == NULL) ++ return NULL; + + parser = rest_xml_parser_new (); + +- node = rest_xml_parser_parse_from_data (parser, +- rest_proxy_call_get_payload (call), ++ node = rest_xml_parser_parse_from_data (parser, data, + rest_proxy_call_get_payload_length (call)); + + g_object_unref(G_OBJECT(parser)); +-- +2.20.1 diff --git a/SOURCES/0046-Update-tests-certificates.patch b/SOURCES/0046-Update-tests-certificates.patch new file mode 100644 index 0000000..4562fbf --- /dev/null +++ b/SOURCES/0046-Update-tests-certificates.patch @@ -0,0 +1,146 @@ +From d8b4c483d8e31525b1290115fbded054b4e8c3ab Mon Sep 17 00:00:00 2001 +From: "Eduardo Lima (Etrunko)" +Date: Tue, 21 May 2019 14:30:50 -0300 +Subject: [PATCH] Update tests certificates + +As reference, use https://www.spice-space.org/spice-user-manual.html#_generating_self_signed_certificates +in order to create new certificates. This procedure should not be +necessary anymore, current date of expiration is set to Dec 31st 9999. + +Signed-off-by: Eduardo Lima (Etrunko) +--- + tests/https-cert/ca-cert.pem | 60 ++++++++++++++++---------------- + tests/https-cert/server-cert.pem | 54 ++++++++++++++-------------- + 2 files changed, 57 insertions(+), 57 deletions(-) + +diff --git a/tests/https-cert/ca-cert.pem b/tests/https-cert/ca-cert.pem +index 1f37f35..b904a2d 100644 +--- a/tests/https-cert/ca-cert.pem ++++ b/tests/https-cert/ca-cert.pem +@@ -1,32 +1,32 @@ + -----BEGIN CERTIFICATE----- +-MIIFfzCCA2egAwIBAgIJAJe68wcZuCytMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV +-BAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0RlZmF1bHQg +-Q29tcGFueSBMdGQxEjAQBgNVBAMMCWdvdmlydCBDQTAeFw0xNjA0MTIxNTEyNDFa +-Fw0xOTA0MTIxNTEyNDFaMFYxCzAJBgNVBAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0 +-IENpdHkxHDAaBgNVBAoME0RlZmF1bHQgQ29tcGFueSBMdGQxEjAQBgNVBAMMCWdv +-dmlydCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALj2s6YqG9CE +-O7ZxudxjGRSN3rUsnc++p0I+Exo32lsPMD3AXGJ9EwGnXhoRvGnuF2piICZ3CLl2 +-nOH/7Ta8Sb/RuHj67XpJyOhgamM9HULff7ZFXyOrSVyf7YhetCqtx6QhwGfeJ88A +-MsClJmLZ0AkC1rqtIze9r7HCHZCQxkZZHKV0EhF8RaK0oBxjt6MFIru/kzQCXvWT +-t9/RaaxhOdboCtTEmu5oTBQfmKUzl4KT3byYVhdm70MEu/PES1XcgnI2RiHcggrI +-jJ7IknDZTZVK6r0uYLwhBLYA7WsHjRuinTC45dfGcZo0ZTn3khO2Get1negU6wuq +-kkxyc/Su+tU+eH74haW58Xa3DRXlRNHu91ll81W1Wtpi2osDlImIbM/a+FTSTenl +-/bIpPOSqbncvi0yfOoZJhH/u8jgQl3hKVgcA8wYdBj/zcHknldnjeS/k0zI84jOd +-ZrSWL/U7CRGiqJJgRpEKMlggf8Zyh+Lu5Hs6DJrSMG36nbLuukioNCzk7mzMJtOk +-kcE2576RA/1qkYdno06ZHCR7AnOlwvOKusS8ApIti/quQy1COanBYKaiXOJOemZ2 +-n5D3cDsqRk1s/Wj53Ci9KurhGoQOoquRXHv7Z3vzBtZdqZBdwLH3r0pM85a//M6c +-HkDwEDsZNUPlvteDahhMPt2qjJNI1ucVAgMBAAGjUDBOMB0GA1UdDgQWBBTxTMG0 +-4azCV/NN7/DhFI5tVp9t3TAfBgNVHSMEGDAWgBTxTMG04azCV/NN7/DhFI5tVp9t +-3TAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQA0OOkImczWNwgz/CaB +-mEx6odCM0Kv2ozZ6d8ttsj4w9S3tn0HSR1xM62F/GmO1NfxQXKWTR3xYMou0fQVA +-RskWy/I9WVN/BTD2QSPD9b3fqZvXgi5eMXVeT/1zO2LywV/APLzVl+jbB3WT9J+9 +-1CHyiMNQUUbkIULmE3Z4FPYL30TGbAj4QSIIAbJlHAxRsrTbLXqRXnqw/NxdKdBk +-v1AOvCenu1HcbtWwDnwrIJGt8/igPB5KqsBzHVfcVmvpXUDC1oLf8w8v7nUB55hs +-ZMFyaeEcmc+W2B/JM26npbfTCjST9D6kxBXUhIeu9oJDimfiUqYUaZOuybUM6ZEy +-76vsO8qB06AuA+KhbvBgz8VHveMCnL516VIB8gxThvBgGIe7AQJuDHCy3+oRJ1+k +-kQm04t2k+Gg03ZpgtzbKaOCL6zRFyy5XE8h59/92KyUh804WTiS5MQZLTnqONqS1 +-49BWXgTZgL+PvMr2xzE5ECs3lkcNpO3TvQJB6eSg0X6NQEscQRbTI1qrmszfAov3 +-teQQlwZZHwzXhJxDNAW9u4oaCWbhRsVbYIoDDdvgIeeLozNaQgJkVzQOrSDOcbrk +-4cclYBgxgSAp1wvlje6iUFGGz6Q37GLBhqBTONjIL2ArlizqznGvBbQ/0CO1bij4 +-mePFkPdR8OZWT1+FN6HavKYtPg== ++MIIFjzCCA3egAwIBAgIUI09vQ7noXtQvCMMLivExKvahRI8wDQYJKoZIhvcNAQEL ++BQAwVjELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UE ++CgwTRGVmYXVsdCBDb21wYW55IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MCAXDTE5 ++MDUyMTE3MjUwN1oYDzk5OTkxMjMxMTcyNTA3WjBWMQswCQYDVQQGEwJYWDEVMBMG ++A1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQKDBNEZWZhdWx0IENvbXBhbnkgTHRk ++MRIwEAYDVQQDDAlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK ++AoICAQC49rOmKhvQhDu2cbncYxkUjd61LJ3PvqdCPhMaN9pbDzA9wFxifRMBp14a ++Ebxp7hdqYiAmdwi5dpzh/+02vEm/0bh4+u16ScjoYGpjPR1C33+2RV8jq0lcn+2I ++XrQqrcekIcBn3ifPADLApSZi2dAJAta6rSM3va+xwh2QkMZGWRyldBIRfEWitKAc ++Y7ejBSK7v5M0Al71k7ff0WmsYTnW6ArUxJruaEwUH5ilM5eCk928mFYXZu9DBLvz ++xEtV3IJyNkYh3IIKyIyeyJJw2U2VSuq9LmC8IQS2AO1rB40bop0wuOXXxnGaNGU5 ++95ITthnrdZ3oFOsLqpJMcnP0rvrVPnh++IWlufF2tw0V5UTR7vdZZfNVtVraYtqL ++A5SJiGzP2vhU0k3p5f2yKTzkqm53L4tMnzqGSYR/7vI4EJd4SlYHAPMGHQY/83B5 ++J5XZ43kv5NMyPOIznWa0li/1OwkRoqiSYEaRCjJYIH/Gcofi7uR7Ogya0jBt+p2y ++7rpIqDQs5O5szCbTpJHBNue+kQP9apGHZ6NOmRwkewJzpcLzirrEvAKSLYv6rkMt ++QjmpwWCmolziTnpmdp+Q93A7KkZNbP1o+dwovSrq4RqEDqKrkVx7+2d78wbWXamQ ++XcCx969KTPOWv/zOnB5A8BA7GTVD5b7Xg2oYTD7dqoyTSNbnFQIDAQABo1MwUTAd ++BgNVHQ4EFgQU8UzBtOGswlfzTe/w4RSObVafbd0wHwYDVR0jBBgwFoAU8UzBtOGs ++wlfzTe/w4RSObVafbd0wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC ++AgEAUFRLaj6YtYRLG+PAT9ic+VEqX2qxttBO2/LpjFwpsBPuNs6/kHF6VNPOhV6K ++6SM4yfWM+y37IqQATTCe4eMiMEun+4DMzhkKX4Lbz+FR/n7xyibwNALZH/M0P6gt ++nXIciyLcG7hmFkgQCGBCVyavrh6q7HcE14MYZlCCt+0rRyJu+PEd4sbcnwo+Ia9p ++4tEeTK8cU5Ek4kJh/AkdlabgGQ/Cq24Y0+Tfix/0i3tRPM1jWgaukKlD2wPh/Idp ++KjtPqx1PM0MSgCoalNxcCAOHPh1h/8NJt+yIDwurOd+XEbG+tBnLE8y0upyO5w1U ++SU9XCBqv7fQnSPOBgvQ/5OwribIHLuvjCVF0BkI3u+NeNVSzFtGreFHNWJ6foA6o ++Um50pw/hCgLptOfhXYkCx2uP7XxOhjlpJOc+1I05Y44vai5YmpqwvvEWkcV2Dlw3 ++ihIHWca6wxVql61LqIzqoiVxNhGiOGTPWbyGMBWA+8cbxVqG0zBKl3A4vox0cGRX ++QPBIiUFjhx4Z5pYZuJ5ndQHiclnYtEfC6+UppL08yrDdIzyLMxIpDqkUAw03TKKC ++TzCsa3DL10LTIulDJurC5SHgY+SrBrWAGuSy97Lmp0cogSBgU9VFqESKaB1lgtET ++c8dkOFwHdOIXu3iI9uKGcwkUfrjGsUdYOUJaAJ5t36WCw/Q= + -----END CERTIFICATE----- +diff --git a/tests/https-cert/server-cert.pem b/tests/https-cert/server-cert.pem +index 709369f..9ca912d 100644 +--- a/tests/https-cert/server-cert.pem ++++ b/tests/https-cert/server-cert.pem +@@ -1,30 +1,30 @@ + -----BEGIN CERTIFICATE----- +-MIIFIDCCAwgCAQEwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCWFgxFTATBgNV ++MIIFIjCCAwoCAQEwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCWFgxFTATBgNV + BAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UECgwTRGVmYXVsdCBDb21wYW55IEx0ZDES +-MBAGA1UEAwwJZ292aXJ0IENBMB4XDTE2MDQxMjE1MTMzNVoXDTE5MDQxMjE1MTMz +-NVowVjELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UE +-CgwTRGVmYXVsdCBDb21wYW55IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjAN +-BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAt6OkS5HhwwFLJWDmuRSOYCXwQP6v +-OlToc7rHvK0+shkspUb1KYks3iEw9djLQdxf1E5k+oDlifDKAMgd/AxkJn8kZ4f1 +-i3183gFdad+UlMFwCliReb3opdtalR6Bef1CDE91+wsN1S4OLXYlVY/EO/sV4Ydh +-khReJiSQzUS+s1T9Nxa57YiuhJ6KYhS5SKkoFDQ7OmyvXM4cSnqOy7h4xBg8fBv9 +-jxI24DNsF1qPg3XVQg3FDmHLEdRTlOWzq39qxzHPrTcFCboS1EaKHIX5DwlNR/L+ +-x/JVqP99t2d/7lp2u8rveHsV0sLCoGK6ehbL6CHMXZQmmRQaVL/xueVIUvUhpwCS +-BXdxRNHpSizPkM4P7/0isgvJ8okElwKv2G46rJjt/AuQTOXVJDEfajHe/703E5r3 +-iJkkG4Jd3uVeZIEigic9PEyervYk2VrWXIIZltfgaCUZYiJNRQ6xbG6RrKLYgSfV +-fpr8urFWFKs+j8dZHc8/GPi1tjTtaaYG0kXg3CGEh3Ww3ym0xjxrt2Qr62nMD+lH +-0loK8wdJbzsHgmLOGnURUWN55XKFpWcrP9rYHSl0d70u6YioMpIM2UClfRPQnLvX +-+/H3yBshAPQldBgseXJ9zlG1ho5fXaIg5u4mtNg+GccerNOFypdJJc97IdYFmyhm +-ww/6LcpMKk+e6wECAwEAATANBgkqhkiG9w0BAQsFAAOCAgEADePSnvlNHaO54TRl +-FZxfxNf/Ft3s+HP2ya6SC+tu1X7FgjbHQL4nm0Xf+pboAZoeUMujgUVGuYQ3ytkt +-irbSONYBbr439zZ4cPqWXqgzySTEiKwWR8REHXRPHJaupE09g+uEWo4E2u7423+k +-j3tbSkPZlObmsXkpdtQEw347yHcmZb8ujloxBopRK5KHchg/mXjiVGrkt9E8tzgX +-V8eG7CkCiEujnLpdjZ+7+AwmJoIuzB7xs2rXMe/zC7/4l2ViCFgjJKZra2oZLzqc +-FVBZXW8dAmWT4iIsZP4xXyzrKA8exzKgsdtXTMYNzgUsXH6Zcou0GhTR5jZvWbvZ +-Z0uPIXFnDRBqvK8nbRab0ok7iJRoLJhFih6q2tQwrpg05zPV39d9GLNwXKEKCo6/ +-dqnqUhQcD5CpXoLhANbSgZZo7xdTM4Onxlm+h+3D/UxbciOQ8nRmNKUC+xX79+Xw +-zPLRULRs32brrfObOuOJuiA4tL81n9ghAdnbVhiZZvhxpJ/QvZWl4CH1UdR2/bO4 +-+lkEAJDfLTP2uvWe0zYFS2E1WeJUOBjt6mU4sFNxqf5Vt+6PMWBGKvUg/JW+2kCP +-S5h1pRFDf8XOGWJ5UvzwlxP/VXrDo70xeY7Pdgk+TPr+TroJsNjorIi9Y0JXKZJ6 +-dux12jowA6uKxtF7dmtA5szUKSU= ++MBAGA1UEAwwJbG9jYWxob3N0MCAXDTE5MDUyMTE3MjUzMloYDzk5OTkxMjMxMTcy ++NTMyWjBWMQswCQYDVQQGEwJYWDEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYD ++VQQKDBNEZWZhdWx0IENvbXBhbnkgTHRkMRIwEAYDVQQDDAlsb2NhbGhvc3QwggIi ++MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC3o6RLkeHDAUslYOa5FI5gJfBA ++/q86VOhzuse8rT6yGSylRvUpiSzeITD12MtB3F/UTmT6gOWJ8MoAyB38DGQmfyRn ++h/WLfXzeAV1p35SUwXAKWJF5veil21qVHoF5/UIMT3X7Cw3VLg4tdiVVj8Q7+xXh ++h2GSFF4mJJDNRL6zVP03FrntiK6EnopiFLlIqSgUNDs6bK9czhxKeo7LuHjEGDx8 ++G/2PEjbgM2wXWo+DddVCDcUOYcsR1FOU5bOrf2rHMc+tNwUJuhLURoochfkPCU1H ++8v7H8lWo/323Z3/uWna7yu94exXSwsKgYrp6FsvoIcxdlCaZFBpUv/G55UhS9SGn ++AJIFd3FE0elKLM+Qzg/v/SKyC8nyiQSXAq/YbjqsmO38C5BM5dUkMR9qMd7/vTcT ++mveImSQbgl3e5V5kgSKCJz08TJ6u9iTZWtZcghmW1+BoJRliIk1FDrFsbpGsotiB ++J9V+mvy6sVYUqz6Px1kdzz8Y+LW2NO1ppgbSReDcIYSHdbDfKbTGPGu3ZCvracwP ++6UfSWgrzB0lvOweCYs4adRFRY3nlcoWlZys/2tgdKXR3vS7piKgykgzZQKV9E9Cc ++u9f78ffIGyEA9CV0GCx5cn3OUbWGjl9doiDm7ia02D4Zxx6s04XKl0klz3sh1gWb ++KGbDD/otykwqT57rAQIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQCdarzrfXWzSL1k ++MZ+D25teNSgZglXw7cpc/WVx2zQ26Wd7csig8Gac1vW/bQMk9XBbwZoI9tuHk62l ++6+9eXGgIgN5qUCchlqcO41IVSk4sWrvNPXiU7kbLrjmrh8txQM8D/YLKm8S8Muf7 ++F4r/RhRkQY+85eOS2GEyj5AMnUlmi1g7wBkIiRipY4fMLowwX8ouQiJCvQE/LJYS ++rQlPDnvCwcVmOxEKUjQoZ0vKrD6zNrnWzEe3LXxQQI3OnnAqgVGHH7bQsY482apn ++2e+WRJouBSwOKEb27/DWMQoXaiVhNBh2wWt5xgKKupJB+PIyW0H2w0Gw1Jr2JY+I ++Lh5fXJXCB/BF3qsbJhi2mnNYWhPP4oOoLN/pT6m1FV/bbTEXlsxxczfE/zT4JRsi ++DhQRZ/FWhbpT9Z7I5kd76KjpKkRFi3Nkb9ezAW35xuo6Ex5x7EWNJM8FJuktNgIK ++Z7JxnqeC0DVEDSWhtxo6HTlx0HgpVTjRPKCVEt1d4itPRBMKueygul1se1jLlMw8 +++8sRpCxdYU9KX18c+p4wANTke94vH5mrm2msK/oXmM77VDIGriEtr8tMIYZbGwKQ ++dhUKsH9eaReKHwoLqihQotpEi28DSng4EXSu9crZV/Yu7crL1+JBSF+N5OK7cf0q ++8K2k/Y/pshicpfHaEKDJmLp5vfULNw== + -----END CERTIFICATE----- +-- +2.21.0 diff --git a/SPECS/libgovirt.spec b/SPECS/libgovirt.spec new file mode 100644 index 0000000..988e912 --- /dev/null +++ b/SPECS/libgovirt.spec @@ -0,0 +1,229 @@ +# -*- rpm-spec -*- + +%global with_gir 0 + +# Default to skipping autoreconf. Distros can change just this one line +# (or provide a command-line override) if they backport any patches that +# touch configure.ac or Makefile.am. + +# Force running autoreconf because data center patches touch Makefile.am. +# To disable autoreconf, change the value to 0. +%{!?enable_autotools:%global enable_autotools 1} + +%if 0%{?fedora} >= 15 || 0%{?rhel} >= 7 +%global with_gir 1 +%endif + +Summary: A GObject library for interacting with oVirt REST API +Name: libgovirt +Version: 0.3.4 +Release: 3%{?dist}%{?extra_release} +License: LGPLv2+ +Group: Development/Libraries +Source: http://ftp.gnome.org/pub/GNOME/sources/libgovirt/0.3/%{name}-%{version}.tar.xz +URL: http://people.freedesktop.org/~teuf/govirt/ +Patch01: 0001-proxy-Fix-persistent-session-with-oVirt-3.6.patch +Patch02: 0002-Force-use-of-v3-REST-API.patch +Patch03: 0003-New-storage-format-added-in-oVirt-4.1.patch +Patch04: 0004-proxy-Hold-reference-to-cancellable-object.patch +Patch05: 0005-proxy-Check-if-operation-is-cancelled-before-disconn.patch +Patch06: 0006-storage-domain-Factor-out-property-value-setting-fro.patch +Patch07: 0007-storage-domain-use-explicit-initialization-of-struct.patch +Patch08: 0008-storage-domain-Move-out-ovirt_resource_parse_xml-to-.patch +Patch09: 0009-utils-Remove-unused-function-ovirt_rest_xml_node_get.patch +Patch10: 0010-utils-Rename-ovirt_rest_xml_node_get_content_va-to-o.patch +Patch11: 0011-utils-Retrieve-node-attributes-in-ovirt_resource_par.patch +Patch12: 0012-utils-Support-G_TYPE_STRING-in-_set_property_value_f.patch +Patch13: 0013-utils-Support-G_TYPE_STRV-in-_set_property_value_fro.patch +Patch14: 0014-Introduce-auxiliary-function-ovirt_sub_collection_ne.patch +Patch15: 0015-New-API-functions-to-enable-search-queries-of-collec.patch +Patch16: 0016-Introduce-ovirt_resource_new-functions.patch +Patch17: 0017-Use-ovirt_resource_new-functions-instead-of-g_initab.patch +Patch18: 0018-Move-resource-type-definitions-to-ovirt-types.h.patch +Patch19: 0019-Initial-support-for-hosts.patch +Patch20: 0020-Initial-support-for-clusters.patch +Patch21: 0021-Initial-support-for-data-centers.patch +Patch22: 0022-vm-Introduce-ovirt_vm_get_host.patch +Patch23: 0023-vm-Introduce-ovirt_vm_get_cluster.patch +Patch24: 0024-host-Introduce-ovirt_host_get_cluster.patch +Patch25: 0025-cluster-Introduce-ovirt_cluster_get_data_center.patch +Patch26: 0026-storage-domain-Retrieve-data-center-ids.patch +Patch27: 0027-Add-missing-include-in-govirt.h.patch +Patch28: 0028-resource-Fix-ovirt_resource_rest_call_sync-return-va.patch +Patch29: 0029-resource-Fix-ovirt_resource_rest_call_sync-crash-on-.patch +Patch30: 0030-resource-Fix-ovirt_resource_init_from_xml_real-preco.patch +Patch31: 0031-resource-Update-xml-node-in-ovirt_resource_init_from.patch +Patch32: 0032-utils-Drop-type-member-from-OvirtXmlElement-struct.patch +Patch33: 0033-utils-Support-G_TYPE_UINT-in-_set_property_value_fro.patch +Patch34: 0034-utils-Improve-log-message-when-subnode-is-not-found.patch +Patch35: 0035-utils-Factor-out-basic-value-type-setting-from-_set_.patch +Patch36: 0036-utils-Get-enum-default-value-from-GParamSpec.patch +Patch37: 0037-vm-Set-vm-state-property-using-OvirtXmlElement-struc.patch +Patch38: 0038-vm-Set-values-of-OvirtVmDisplay-using-OvirtXmlElemen.patch +Patch39: 0039-vm-display-Move-XML-parsing-from-ovirt-vm-xml.c-file.patch +Patch40: 0040-vm-Set-ticket-expiry-using-OvirtXmlElement-struct.patch +Patch41: 0041-test-govirt-Add-display-node-to-vm-XMLs.patch +Patch42: 0042-proxy-Set-detailed-error-message-for-async-call.patch +Patch43: 0043-cdrom-Set-file-property-using-OvirtXmlElement-struct.patch +Patch44: 0044-proxy-Don-t-try-to-unref-NULL-root-node.patch +Patch45: 0045-utils-Check-for-valid-data-before-calling-rest_xml_p.patch +Patch46: 0046-Update-tests-certificates.patch + +%if 0%{?enable_autotools} +BuildRequires: autoconf +BuildRequires: automake +BuildRequires: gettext-devel +BuildRequires: libtool +%endif + +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: rest-devel >= 0.7.92 +# needed for make check to complete successfully +BuildRequires: dconf + +BuildRequires: intltool +%if %{with_gir} +BuildRequires: gobject-introspection-devel +%endif + +%description +libgovirt is a library that allows applications to use oVirt REST API +to list VMs managed by an oVirt instance, and to get the connection +parameters needed to make a SPICE/VNC connection to them. + +%package devel +Summary: Libraries, includes, etc. to compile with the libgovirt library +Group: Development/Libraries +Requires: %{name}%{?_isa} = %{version}-%{release} +Requires: pkgconfig +Requires: glib2-devel + +%description devel +libgovirt is a library that allows applications to use oVirt REST API +to list VMs managed by an oVirt instance, and to get the connection +parameters needed to make a SPICE/VNC connection to them. + +Libraries, includes, etc. to compile with the libgovirt library + +%prep +%autosetup -S git_am + +%build +%if 0%{?enable_autotools} +autoreconf -if +%endif + +%if %{with_gir} +%global gir_arg --enable-introspection=yes +%else +%global gir_arg --enable-introspection=no +%endif + +%configure %{gir_arg} +%__make %{?_smp_mflags} V=1 + +%install +%__make install DESTDIR=%{buildroot} +rm -f %{buildroot}%{_libdir}/*.a +rm -f %{buildroot}%{_libdir}/*.la +%find_lang %{name} --with-gnome + +%check +make check + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%files -f %{name}.lang +%doc AUTHORS COPYING MAINTAINERS README +%{_libdir}/%{name}.so.2* +%if %{with_gir} +%{_libdir}/girepository-1.0/GoVirt-1.0.typelib +%endif + +%files devel +%{_libdir}/%{name}.so +%dir %{_includedir}/govirt-1.0/ +%dir %{_includedir}/govirt-1.0/govirt/ +%{_includedir}/govirt-1.0/govirt/*.h +%{_libdir}/pkgconfig/govirt-1.0.pc +%if %{with_gir} +%{_datadir}/gir-1.0/GoVirt-1.0.gir +%endif + +%changelog +* Tue Apr 09 2019 Eduardo Lima (Etrunko) - 0.3.4-2 +- Parse XML nodes automatically + Related: rhbz#1427467 +- Set detailed error message for async call + Related: rhbz#1427467 + +* Fri Jun 08 2018 Christophe Fergeau - 0.3.4-1 +- Rebase to latest 0.3.4 upstream release. Still quite a few patches as + there was no 0.3.5 release yet + Resolves: rhbz#1584266 + +* Mon Oct 02 2017 Eduardo Lima (Etrunko) - 0.3.3-6 +- Add support for Hosts, Clusters and Data Centers + Resolves: rhbz#1428401 + +* Mon Mar 13 2017 Eduardo Lima (Etrunko) - 0.3.3-5 +- New storage format added in oVirt 4.1 + Resolves: rhbz#1346215 +- Check if operation was cancelled before disconnecting signal + Resolves: rhbz#1431275 + +* Fri Jul 01 2016 Christophe Fergeau - 0.3.3-4 +- Add upstream patch forcing use of the older v3 REST API as we don't support + yet the v4 API + Resolves: rhbz#1346215 + +* Tue Jun 14 2016 Christophe Fergeau - 0.3.3-3 +- Add upstream patch fixing unwanted authentication dialog for foreign menu + when using remote-viewer ovirt:// + Resolves: rhbz#1346256 + +* Mon Jan 04 2016 Fabiano FidĂȘncio 0.3.3-2 +- Fix crash when VM has several ISO domains + Resolves: rhbz#1274356 +- Add OvirtProxy::sso-token support for oVirt 4.0 + Resolves: rhbz#1324457 + +* Tue May 12 2015 Christophe Fergeau 0.3.3-1 +- Rebase to 0.3.3 + Resolves: rhbz#1214234 + +* Fri Oct 10 2014 Christophe Fergeau 0.3.1-3 +- Add upstream patch allowing to remove CD images from an OvirtCdrom + Resolves: rhbz#1151171 + +* Tue Sep 30 2014 Christophe Fergeau 0.3.1-2 +- Requires a new enough librest as we use symbols not available in older + librest + Related: rhbz#1116844 + +* Mon Sep 08 2014 Christophe Fergeau 0.3.1-1 +- Rebase to libgovirt 0.3.1. + Resolves: rhbz#1116844 + +* Mon Jul 7 2014 Marc-Andre Lureau - 0.3.0-1 +- Rebase to libgovirt 0.3.0. + Resolves: rhbz#1116844 + +* Fri Jan 24 2014 Daniel Mach - 0.1.0-3 +- Mass rebuild 2014-01-24 + +* Fri Dec 27 2013 Daniel Mach - 0.1.0-2 +- Mass rebuild 2013-12-27 + +* Tue Jun 11 2013 Christophe Fergeau 0.1.0-1 +- Update to upstream release 0.1.0 + +* Mon Mar 11 2013 Christophe Fergeau 0.0.3-2 +- Removed definition of BuildRoot and cleanup of BuildRoot in %clean +- Added missing arch to versioned Requires: %%{name} in the -devel package +- Don't include empty NEWS and ChangeLog in built RPM + +* Wed Feb 20 2013 Christophe Fergeau 0.0.3-1 +- Initial import of libgovirt 0.0.3