diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f96b084
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+SOURCES/cfergeau-29AC6C82.keyring
+SOURCES/libgovirt-0.3.4.tar.xz
diff --git a/.libgovirt.metadata b/.libgovirt.metadata
new file mode 100644
index 0000000..563955b
--- /dev/null
+++ b/.libgovirt.metadata
@@ -0,0 +1,2 @@
+84d3abd436c6f4e194aa3f7a58be17ec9ced0a82 SOURCES/cfergeau-29AC6C82.keyring
+aa9d6f7f0c3f24e52117c1b93795df36cf882702 SOURCES/libgovirt-0.3.4.tar.xz
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..e8cd5f1
--- /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 <cfergeau@redhat.com>
+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..17144b5
--- /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 <cfergeau@redhat.com>
+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..649f2d9
--- /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)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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..e3cf6f6
--- /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)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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..20f43b8
--- /dev/null
+++ b/SOURCES/0006-storage-domain-Factor-out-property-value-setting-fro.patch
@@ -0,0 +1,108 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: "Eduardo Lima (Etrunko)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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..fcf4f1e
--- /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)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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..1f7881c
--- /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)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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..57253ac
--- /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)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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..8338a7b
--- /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)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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..16f4b57
--- /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)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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..1d59138
--- /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)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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..2d389a0
--- /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)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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..b662439
--- /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)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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..21f5bf1
--- /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)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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..767f15e
--- /dev/null
+++ b/SOURCES/0017-Use-ovirt_resource_new-functions-instead-of-g_initab.patch
@@ -0,0 +1,146 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: "Eduardo Lima (Etrunko)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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..d284dc9
--- /dev/null
+++ b/SOURCES/0018-Move-resource-type-definitions-to-ovirt-types.h.patch
@@ -0,0 +1,136 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: "Eduardo Lima (Etrunko)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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 <glib-object.h>
++#include <govirt/ovirt-types.h>
+ 
+ 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..fb9e602
--- /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)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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 <govirt/ovirt-api-private.h>
+ #include <govirt/ovirt-collection-private.h>
+ #include <govirt/ovirt-enum-types-private.h>
++#include <govirt/ovirt-host-private.h>
+ #include <govirt/ovirt-proxy-private.h>
+ #include <govirt/ovirt-resource-private.h>
+ #include <govirt/ovirt-resource-rest-call.h>
+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
++ * <http://www.gnu.org/licenses/>.
++ *
++ * Author: Eduardo Lima (Etrunko) <etrunko@redhat.com>
++ */
++#ifndef __OVIRT_HOST_PRIVATE_H__
++#define __OVIRT_HOST_PRIVATE_H__
++
++#include <ovirt-host.h>
++#include <rest/rest-xml-node.h>
++
++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
++ * <http://www.gnu.org/licenses/>.
++ *
++ * Author: Eduardo Lima (Etrunko) <etrunko@redhat.com>
++ */
++
++#include <config.h>
++#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
++ * <http://www.gnu.org/licenses/>.
++ *
++ * Author: Eduardo Lima (Etrunko) <etrunko@redhat.com>
++ */
++#ifndef __OVIRT_HOST_H__
++#define __OVIRT_HOST_H__
++
++#include <gio/gio.h>
++#include <glib-object.h>
++#include <govirt/ovirt-collection.h>
++#include <govirt/ovirt-resource.h>
++#include <govirt/ovirt-types.h>
++
++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..525c725
--- /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)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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 <govirt/ovirt-action-rest-call.h>
+ #include <govirt/ovirt-api-private.h>
++#include <govirt/ovirt-cluster-private.h>
+ #include <govirt/ovirt-collection-private.h>
+ #include <govirt/ovirt-enum-types-private.h>
+ #include <govirt/ovirt-host-private.h>
+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
++ * <http://www.gnu.org/licenses/>.
++ *
++ * Author: Eduardo Lima (Etrunko) <etrunko@redhat.com>
++ */
++#ifndef __OVIRT_CLUSTER_PRIVATE_H__
++#define __OVIRT_CLUSTER_PRIVATE_H__
++
++#include <ovirt-cluster.h>
++#include <rest/rest-xml-node.h>
++
++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
++ * <http://www.gnu.org/licenses/>.
++ *
++ * Author: Eduardo Lima (Etrunko) <etrunko@redhat.com>
++ */
++
++#include <config.h>
++#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
++ * <http://www.gnu.org/licenses/>.
++ *
++ * Author: Eduardo Lima (Etrunko) <etrunko@redhat.com>
++ */
++#ifndef __OVIRT_CLUSTER_H__
++#define __OVIRT_CLUSTER_H__
++
++#include <gio/gio.h>
++#include <glib-object.h>
++#include <govirt/ovirt-collection.h>
++#include <govirt/ovirt-resource.h>
++#include <govirt/ovirt-types.h>
++
++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..54f0323
--- /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)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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 <govirt/ovirt-api-private.h>
+ #include <govirt/ovirt-cluster-private.h>
+ #include <govirt/ovirt-collection-private.h>
++#include <govirt/ovirt-data-center-private.h>
+ #include <govirt/ovirt-enum-types-private.h>
+ #include <govirt/ovirt-host-private.h>
+ #include <govirt/ovirt-proxy-private.h>
+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
++ * <http://www.gnu.org/licenses/>.
++ *
++ * Author: Eduardo Lima (Etrunko) <etrunko@redhat.com>
++ */
++#ifndef __OVIRT_DATA_CENTER_PRIVATE_H__
++#define __OVIRT_DATA_CENTER_PRIVATE_H__
++
++#include <ovirt-data-center.h>
++#include <rest/rest-xml-node.h>
++
++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
++ * <http://www.gnu.org/licenses/>.
++ *
++ * Author: Eduardo Lima (Etrunko) <etrunko@redhat.com>
++ */
++
++#include <config.h>
++#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
++ * <http://www.gnu.org/licenses/>.
++ *
++ * Author: Eduardo Lima (Etrunko) <etrunko@redhat.com>
++ */
++#ifndef __OVIRT_DATA_CENTER_H__
++#define __OVIRT_DATA_CENTER_H__
++
++#include <gio/gio.h>
++#include <glib-object.h>
++#include <govirt/ovirt-collection.h>
++#include <govirt/ovirt-resource.h>
++#include <govirt/ovirt-types.h>
++
++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..1766cca
--- /dev/null
+++ b/SOURCES/0022-vm-Introduce-ovirt_vm_get_host.patch
@@ -0,0 +1,196 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: "Eduardo Lima (Etrunko)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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..03bab39
--- /dev/null
+++ b/SOURCES/0023-vm-Introduce-ovirt_vm_get_cluster.patch
@@ -0,0 +1,177 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: "Eduardo Lima (Etrunko)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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..8ea67f2
--- /dev/null
+++ b/SOURCES/0024-host-Introduce-ovirt_host_get_cluster.patch
@@ -0,0 +1,96 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: "Eduardo Lima (Etrunko)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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..1b3036a
--- /dev/null
+++ b/SOURCES/0025-cluster-Introduce-ovirt_cluster_get_data_center.patch
@@ -0,0 +1,94 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: "Eduardo Lima (Etrunko)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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..7f180ff
--- /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)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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)" <etrunko@redhat.com>
+Date: Thu, 3 Aug 2017 16:53:09 -0300
+Subject: [PATCH] Add missing #include in govirt.h
+
+Signed-off-by: Eduardo Lima (Etrunko) <etrunko@redhat.com>
+---
+ 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 <govirt/ovirt-enum-types.h>
+ #include <govirt/ovirt-api.h>
+ #include <govirt/ovirt-cdrom.h>
++#include <govirt/ovirt-cluster.h>
+ #include <govirt/ovirt-collection.h>
++#include <govirt/ovirt-data-center.h>
+ #include <govirt/ovirt-error.h>
++#include <govirt/ovirt-host.h>
+ #include <govirt/ovirt-options.h>
+ #include <govirt/ovirt-proxy.h>
+ #include <govirt/ovirt-resource.h>
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..faeba43
--- /dev/null
+++ b/SOURCES/0028-resource-Fix-ovirt_resource_rest_call_sync-return-va.patch
@@ -0,0 +1,25 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Christophe Fergeau <cfergeau@redhat.com>
+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..d77b6bb
--- /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 <cfergeau@redhat.com>
+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..68f67e3
--- /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 <cfergeau@redhat.com>
+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..43a0cb2
--- /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 <cfergeau@redhat.com>
+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..a436aed
--- /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)" <etrunko@redhat.com>
+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) <etrunko@redhat.com>
+---
+ 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/libgovirt-0.3.4.tar.xz.sign b/SOURCES/libgovirt-0.3.4.tar.xz.sign
new file mode 100644
index 0000000..c1a7d0d
--- /dev/null
+++ b/SOURCES/libgovirt-0.3.4.tar.xz.sign
@@ -0,0 +1,17 @@
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1
+
+iQIcBAABCAAGBQJXDmDvAAoJEKnYwhQprGyCgyYQALXgvc8Yj66gIHZ5xfj+m5b/
+rfz6ZS0q6g5ya+jSNpZjf2oonhuXa9RrfKsuJ9tQdnajbCDygnn3EITSXZyD56tJ
+RCNElJuycGMQADK7ng7dkrCuXNDyZLSI7V3VHw7YKgfU6Wu9meqOWI3N65SAhlIZ
+zSuRpCUhxZVfx02ogopdwZh5nCCExZjAPcCeEUKQvEtWLFSNI4eDlGB3aafYFnmV
+McM7NxLtdsZ9Y3Y6khtoFC7puMZq7Bl7l9ExTdTlZncLOuEVWtKL2zFts82oBPms
+ZTI8AxpK+EK4bIwl1qi5ovdrg5JHEUbeypbCKWj9DVVcTR6aacgXiQTeLBI1x4nk
+JlAxhMKnVQpVffOF1e27Xaa0AHJqHHtz2lYWKvpNWz+jDdqtAU8aspyuL6qG+EpK
+9cnHBiWou9EEoIYnwMdkZnPtoEI8KWz5ttpPoGbYUKaqlBUwJjr6HLK1U3utYKdT
+lOqy1zPRo88KX0EakZQ4BQaPfecBjQ7prHteFKyxunlEDu3fEHFhLeMKTto3wlWZ
+FZDn3YvWv5iXrRaH2LwojsN82G+oRwf4IUM0uUesNzpgs7E+kYVisWwDLLM8H3Xs
+d5o6KmU90nyAG4rCnV2rNH4/ing2+pYvcNyDcVEzxWXMktlekQqTWyr5LezGXTOK
+coKms31iehaDddKVI4UX
+=Kk6z
+-----END PGP SIGNATURE-----
diff --git a/SPECS/libgovirt.spec b/SPECS/libgovirt.spec
new file mode 100644
index 0000000..bcade89
--- /dev/null
+++ b/SPECS/libgovirt.spec
@@ -0,0 +1,219 @@
+# -*- 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: 8%{?dist}%{?extra_release}
+License: LGPLv2+
+Group: Development/Libraries
+Source0: http://ftp.gnome.org/pub/GNOME/sources/libgovirt/0.3/%{name}-%{version}.tar.xz
+Source1: http://ftp.gnome.org/pub/GNOME/sources/libgovirt/0.3/%{name}-%{version}.tar.xz.sign
+Source2: cfergeau-29AC6C82.keyring
+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
+
+%if 0%{?enable_autotools}
+BuildRequires: autoconf
+BuildRequires: automake
+BuildRequires: gettext-devel
+BuildRequires: libtool
+%endif
+BuildRequires: git-core
+
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: intltool
+BuildRequires: rest-devel >= 0.7.92
+%if %{with_gir}
+BuildRequires: gobject-introspection-devel
+%endif
+#needed for make check
+BuildRequires: glib-networking
+BuildRequires: dconf
+#needed for GPG signature checek
+BuildRequires: gnupg2
+
+%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
+gpgv2 --quiet --keyring %{SOURCE2} %{SOURCE1} %{SOURCE0}
+%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
+
+%ldconfig_scriptlets
+
+%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
+* Mon Jun 11 2018 Christophe Fergeau <cfergeau@redhat.com> - 0.3.4-8
+- Sync with the rhel 7.6 package
+  Resolves: rhbz#1584506
+
+* Fri Feb 09 2018 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 0.3.4-7
+- Escape macros in %%changelog
+
+* Wed Feb 07 2018 Fedora Release Engineering <releng@fedoraproject.org> - 0.3.4-6
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
+
+* Sat Feb 03 2018 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 0.3.4-5
+- Switch to %%ldconfig_scriptlets
+
+* Thu Aug 03 2017 Fedora Release Engineering <releng@fedoraproject.org> - 0.3.4-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild
+
+* Wed Jul 26 2017 Fedora Release Engineering <releng@fedoraproject.org> - 0.3.4-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
+
+* Fri Feb 10 2017 Fedora Release Engineering <releng@fedoraproject.org> - 0.3.4-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
+
+* Wed Apr 13 2016 Christophe Fergeau <cfergeau@redhat.com> 0.3.4-1
+- Update to libgovirt 0.3.4
+
+* Thu Feb 04 2016 Fedora Release Engineering <releng@fedoraproject.org> - 0.3.3-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild
+
+* Wed Jun 17 2015 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.3.3-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild
+
+* Wed Apr 08 2015 Christophe Fergeau <cfergeau@redhat.com> 0.3.3-1
+- Update to upstream release 0.3.3
+
+* Thu Oct 09 2014 Christophe Fergeau <cfergeau@redhat.com> 0.3.2-1
+- Update to upstream release 0.3.2
+
+* Wed Sep 03 2014 Christophe Fergeau <cfergeau@redhat.com> 0.3.1-1
+- Update to upstream release 0.3.1
+
+* Sun Aug 17 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.3.0-7
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild
+
+* Sat Aug 02 2014 Richard Jones <rjones@redhat.com> - 0.3.0-6
+- Force rebuild for aarch64.
+
+* Tue Jul 22 2014 Kalev Lember <kalevlember@gmail.com> - 0.3.0-5
+- Rebuilt for gobject-introspection 1.41.4
+
+* Sat Jun 07 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.3.0-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
+
+* Tue Nov 26 2013 Christophe Fergeau <cfergeau@redhat.com> 0.3.0-3
+- Actually apply Patch0 /o\
+
+* Tue Nov 26 2013 Christophe Fergeau <cfergeau@redhat.com> 0.3.0-2
+- Add patch to fix a memory corruption issue when librest does not have the
+  RestProxy::ssl-ca-file property (which is currently the case in Fedora)
+
+* Sat Aug 03 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.1.0-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild
+
+* Tue Jun 11 2013 Christophe Fergeau <cfergeau@redhat.com> 0.1.0-1
+- Update to upstream release 0.1.0
+
+* Mon Mar 11 2013 Christophe Fergeau <cfergeau@redhat.com> 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 <cfergeau@redhat.com> 0.0.3-1
+- Initial import of libgovirt 0.0.3
+
+