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;
