[Spice-devel] VM pools and libgovirt

Christophe Fergeau cfergeau at redhat.com
Tue Dec 3 09:21:22 PST 2013


On Tue, Dec 03, 2013 at 11:46:40AM -0500, i iordanov wrote:
> Would you like me to generate a patch with all the suggested changes and a
> better log entry?

I've been doing that actually, with various changes:
- renamed allocatevm to allocate_vm
- renamed _vmpool_ to _vm_pool
- moved ovirt_vm_pool_xml.c to ovirt_vm_pool.c as it was not that big
- used guint for the various VmPool properties
- detect parsing errors when parsing numbers
- fixed the copyright headers (the new files should be (C) 2013 yourself,
  not (C) 2013 Red Hat Inc)

I still have these changes roughly split up if you don't like some of them
and want me to drop them.

Christophe


From 436eb3fd47ee1cc28dd9a2c68e3bf4c2c7827f60 Mon Sep 17 00:00:00 2001
From: Iordan Iordanov <iiordanov at gmail.com>
Date: Tue, 3 Dec 2013 03:07:09 -0500
Subject: [PATCH] Added initial support for VM pools.

The library is now able to allocate VMs from the pool synchronously.
The attributes size, prestarted_vms, and max_user_vms are parsed.
---
 govirt/Makefile.am      |   2 +
 govirt/govirt.h         |   1 +
 govirt/govirt.sym       |   7 +
 govirt/ovirt-api.c      |  28 ++++
 govirt/ovirt-api.h      |   1 +
 govirt/ovirt-resource.c |   1 +
 govirt/ovirt-utils.c    |  45 ++++++
 govirt/ovirt-utils.h    |   2 +
 govirt/ovirt-vm-pool.c  | 368 ++++++++++++++++++++++++++++++++++++++++++++++++
 govirt/ovirt-vm-pool.h  |  65 +++++++++
 10 files changed, 520 insertions(+)
 create mode 100644 govirt/ovirt-vm-pool.c
 create mode 100644 govirt/ovirt-vm-pool.h

diff --git a/govirt/Makefile.am b/govirt/Makefile.am
index d9e70a5..645545d 100644
--- a/govirt/Makefile.am
+++ b/govirt/Makefile.am
@@ -26,6 +26,7 @@ libgovirt_la_HEADERS =						\
 	ovirt-storage-domain.h					\
 	ovirt-types.h						\
 	ovirt-vm.h						\
+	ovirt-vm-pool.h						\
 	ovirt-vm-display.h					\
 	$(NULL)
 
@@ -62,6 +63,7 @@ libgovirt_la_SOURCES =						\
 	ovirt-vm.c						\
 	ovirt-vm-display.c					\
 	ovirt-vm-xml.c						\
+	ovirt-vm-pool.c						\
 	$(NULL)
 
 nodist_libgovirt_la_HEADERS =					\
diff --git a/govirt/govirt.h b/govirt/govirt.h
index 69f878b..fb7756f 100644
--- a/govirt/govirt.h
+++ b/govirt/govirt.h
@@ -34,5 +34,6 @@
 #include <govirt/ovirt-storage-domain.h>
 #include <govirt/ovirt-vm.h>
 #include <govirt/ovirt-vm-display.h>
+#include <govirt/ovirt-vm-pool.h>
 
 #endif /* __OVIRT_H__ */
diff --git a/govirt/govirt.sym b/govirt/govirt.sym
index bc53901..49636d5 100644
--- a/govirt/govirt.sym
+++ b/govirt/govirt.sym
@@ -87,5 +87,12 @@ GOVIRT_0.2.1 {
         ovirt_vm_get_cdroms;
 } GOVIRT_0.2.0;
 
+GOVIRT_0.3.1 {
+        ovirt_api_get_vm_pools;
+
+        ovirt_vm_pool_get_type;
+        ovirt_vm_pool_new;
+        ovirt_vm_pool_allocate_vm;
+} GOVIRT_0.2.1;
 
 # .... define new API here using predicted next version number ....
diff --git a/govirt/ovirt-api.c b/govirt/ovirt-api.c
index ddb2300..4b6d141 100644
--- a/govirt/ovirt-api.c
+++ b/govirt/ovirt-api.c
@@ -2,6 +2,7 @@
  * ovirt-api.c: oVirt API entry point
  *
  * Copyright (C) 2012, 2013 Red Hat, Inc.
+ * Copyright (C) 2013 Iordan Iordanov <i at iiordanov.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -27,6 +28,7 @@
 #include "ovirt-proxy.h"
 #include "ovirt-rest-call.h"
 #include "ovirt-api.h"
+#include "ovirt-vm-pool.h"
 #include "govirt-private.h"
 
 #include <rest/rest-xml-node.h>
@@ -41,6 +43,7 @@
 struct _OvirtApiPrivate {
     OvirtCollection *storage_domains;
     OvirtCollection *vms;
+    OvirtCollection *vm_pools;
 };
 
 
@@ -72,6 +75,7 @@ static void ovirt_api_dispose(GObject *object)
 
     g_clear_object(&api->priv->storage_domains);
     g_clear_object(&api->priv->vms);
+    g_clear_object(&api->priv->vm_pools);
 
     G_OBJECT_CLASS(ovirt_api_parent_class)->dispose(object);
 }
@@ -131,6 +135,30 @@ OvirtCollection *ovirt_api_get_vms(OvirtApi *api)
     return api->priv->vms;
 }
 
+/**
+ * ovirt_api_get_vm_pools:
+ * @api: a #OvirtApi
+ *
+ * Return value: (transfer full):
+ */
+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");
+
+    return api->priv->vm_pools;
+}
+
 
 /**
  * ovirt_api_get_storage_domains:
diff --git a/govirt/ovirt-api.h b/govirt/ovirt-api.h
index d1de522..5f0d4e9 100644
--- a/govirt/ovirt-api.h
+++ b/govirt/ovirt-api.h
@@ -63,6 +63,7 @@ OvirtApi *ovirt_api_new(void);
 
 OvirtCollection *ovirt_api_get_storage_domains(OvirtApi *api);
 OvirtCollection *ovirt_api_get_vms(OvirtApi *api);
+OvirtCollection *ovirt_api_get_vm_pools(OvirtApi *api);
 
 G_END_DECLS
 
diff --git a/govirt/ovirt-resource.c b/govirt/ovirt-resource.c
index fca06e8..81241be 100644
--- a/govirt/ovirt-resource.c
+++ b/govirt/ovirt-resource.c
@@ -25,6 +25,7 @@
 #include <string.h>
 
 #include <rest/rest-xml-node.h>
+#include <rest/rest-xml-parser.h>
 
 #include "govirt-private.h"
 #include "ovirt-error.h"
diff --git a/govirt/ovirt-utils.c b/govirt/ovirt-utils.c
index 618992a..3b9593a 100644
--- a/govirt/ovirt-utils.c
+++ b/govirt/ovirt-utils.c
@@ -22,6 +22,7 @@
 
 #include <config.h>
 
+#include <errno.h>
 #include <string.h>
 
 #include <rest/rest-xml-parser.h>
@@ -126,6 +127,50 @@ ovirt_utils_boolean_from_string(const char *value)
     return (g_strcmp0(value, "true") == 0);
 }
 
+G_GNUC_INTERNAL gboolean
+ovirt_utils_guint64_from_string(const char *value_str, guint64 *value)
+{
+    char *end_ptr;
+    guint64 result;
+
+    g_return_val_if_fail(value_str != NULL, FALSE);
+
+    result = g_ascii_strtoull(value_str, &end_ptr, 10);
+    if ((result == G_MAXUINT64) && (errno == ERANGE)) {
+        /* overflow */
+        return FALSE;
+    }
+    if ((result == 0) && (errno == EINVAL)) {
+        /* should not happen, invalid base */
+        return FALSE;
+    }
+    if (*end_ptr != '\0') {
+        return FALSE;
+    }
+
+    *value = result;
+
+    return TRUE;
+}
+
+G_GNUC_INTERNAL gboolean
+ovirt_utils_guint_from_string(const char *value_str, guint *value)
+{
+    guint64 value64;
+    gboolean success;
+
+    success = ovirt_utils_guint64_from_string(value_str, &value64);
+    if (!success) {
+        return FALSE;
+    }
+    if (value64 > G_MAXUINT32) {
+        return FALSE;
+    }
+
+    *value = (guint)value64;
+
+    return TRUE;
+}
 
 G_GNUC_INTERNAL const char *ovirt_utils_strip_api_base_dir(const char *path)
 {
diff --git a/govirt/ovirt-utils.h b/govirt/ovirt-utils.h
index 935b029..f627c13 100644
--- a/govirt/ovirt-utils.h
+++ b/govirt/ovirt-utils.h
@@ -36,6 +36,8 @@ gboolean ovirt_utils_gerror_from_xml_fault(RestXmlNode *root, GError **error);
 const char *ovirt_utils_genum_get_nick (GType enum_type, gint value);
 int ovirt_utils_genum_get_value (GType enum_type, const char *nick,
                                  gint default_value);
+gboolean ovirt_utils_guint64_from_string(const char *value_str, guint64 *value);
+gboolean ovirt_utils_guint_from_string(const char *value_str, guint *value);
 gboolean ovirt_utils_boolean_from_string(const char *value);
 const char *ovirt_utils_strip_api_base_dir(const char *path);
 
diff --git a/govirt/ovirt-vm-pool.c b/govirt/ovirt-vm-pool.c
new file mode 100644
index 0000000..99a8444
--- /dev/null
+++ b/govirt/ovirt-vm-pool.c
@@ -0,0 +1,368 @@
+/*
+ * ovirt-vm-pool.c: oVirt virtual machine pool
+ *
+ * Copyright (C) 2013 Iordan Iordanov <i at iiordanov.com>
+ *
+ * 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/>.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <rest/rest-xml-node.h>
+#include <rest/rest-xml-parser.h>
+
+#include "govirt.h"
+#include "govirt-private.h"
+
+
+typedef gboolean (*ActionResponseParser)(RestXmlNode *node, OvirtVmPool *vm_pool, GError **error);
+static gboolean parse_action_response(RestProxyCall *call, OvirtVmPool *vm_pool,
+                                      ActionResponseParser response_parser,
+                                      GError **error);
+static gboolean ovirt_vm_pool_refresh_from_xml(OvirtVmPool *vm_pool, RestXmlNode *node);
+#define OVIRT_VM_POOL_GET_PRIVATE(obj)                         \
+        (G_TYPE_INSTANCE_GET_PRIVATE((obj), OVIRT_TYPE_VM_POOL, OvirtVmPoolPrivate))
+
+struct _OvirtVmPoolPrivate {
+        guint prestarted_vms;
+        guint max_user_vms;
+        guint size;
+};
+
+G_DEFINE_TYPE(OvirtVmPool, ovirt_vm_pool, OVIRT_TYPE_RESOURCE);
+
+enum OvirtResponseStatus {
+    OVIRT_RESPONSE_UNKNOWN,
+    OVIRT_RESPONSE_FAILED,
+    OVIRT_RESPONSE_PENDING,
+    OVIRT_RESPONSE_IN_PROGRESS,
+    OVIRT_RESPONSE_COMPLETE
+};
+
+enum {
+    PROP_0,
+    PROP_SIZE,
+    PROP_PRESTARTED_VMS,
+    PROP_MAX_USER_VMS
+};
+
+static void ovirt_vm_pool_get_property(GObject *object,
+                                       guint prop_id,
+                                       GValue *value,
+                                       GParamSpec *pspec)
+{
+    OvirtVmPool *vm_pool = OVIRT_VM_POOL(object);
+
+    switch (prop_id) {
+    case PROP_SIZE:
+        g_value_set_uint(value, vm_pool->priv->size);
+        break;
+    case PROP_PRESTARTED_VMS:
+        g_value_set_uint(value, vm_pool->priv->prestarted_vms);
+        break;
+    case PROP_MAX_USER_VMS:
+        g_value_set_uint(value, vm_pool->priv->max_user_vms);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+    }
+}
+
+static void ovirt_vm_pool_set_property(GObject *object,
+                                       guint prop_id,
+                                       const GValue *value,
+                                       GParamSpec *pspec)
+{
+    OvirtVmPool *vm_pool = OVIRT_VM_POOL(object);
+
+    switch (prop_id) {
+    case PROP_SIZE:
+        vm_pool->priv->size = g_value_get_uint(value);
+        break;
+    case PROP_PRESTARTED_VMS:
+        vm_pool->priv->prestarted_vms = g_value_get_uint(value);
+        break;
+    case PROP_MAX_USER_VMS:
+        vm_pool->priv->max_user_vms = g_value_get_uint(value);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+    }
+}
+
+static void ovirt_vm_pool_dispose(GObject *object)
+{
+    G_OBJECT_CLASS(ovirt_vm_pool_parent_class)->dispose(object);
+}
+
+static gboolean ovirt_vm_pool_init_from_xml(OvirtResource *resource,
+                                            RestXmlNode *node,
+                                            GError **error)
+{
+    gboolean parsed_ok;
+    OvirtResourceClass *parent_class;
+
+    parsed_ok = ovirt_vm_pool_refresh_from_xml(OVIRT_VM_POOL(resource), node);
+    if (!parsed_ok) {
+        return FALSE;
+    }
+    parent_class = OVIRT_RESOURCE_CLASS(ovirt_vm_pool_parent_class);
+
+    return parent_class->init_from_xml(resource, node, error);
+}
+
+static void ovirt_vm_pool_class_init(OvirtVmPoolClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS(klass);
+    OvirtResourceClass *resource_class = OVIRT_RESOURCE_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(OvirtVmPoolPrivate));
+
+    resource_class->init_from_xml = ovirt_vm_pool_init_from_xml;
+    object_class->dispose = ovirt_vm_pool_dispose;
+    object_class->get_property = ovirt_vm_pool_get_property;
+    object_class->set_property = ovirt_vm_pool_set_property;
+
+    g_object_class_install_property(object_class,
+                                    PROP_SIZE,
+                                    g_param_spec_uint("size",
+                                                      "Size of pool",
+                                                      "The number of VMs in the pool",
+                                                      0,
+                                                      G_MAXUINT,
+                                                      0,
+                                                      G_PARAM_READWRITE));
+    g_object_class_install_property(object_class,
+                                    PROP_PRESTARTED_VMS,
+                                    g_param_spec_uint("prestarted_vms",
+                                                      "Prestarted VMs",
+                                                      "The number of VMs prestarted in the pool",
+                                                      0,
+                                                      G_MAXUINT,
+                                                      0,
+                                                      G_PARAM_READWRITE));
+    g_object_class_install_property(object_class,
+                                    PROP_MAX_USER_VMS,
+                                    g_param_spec_uint("max_user_vms",
+                                                      "Max VMs per user",
+                                                      "The number of VMs a user can allocate from the pool",
+                                                      0,
+                                                      G_MAXUINT,
+                                                      0,
+                                                      G_PARAM_READWRITE));
+}
+
+static void ovirt_vm_pool_init(G_GNUC_UNUSED OvirtVmPool *vm_pool)
+{
+    vm_pool->priv = OVIRT_VM_POOL_GET_PRIVATE(vm_pool);
+}
+
+OvirtVmPool *ovirt_vm_pool_new(void)
+{
+    return OVIRT_VM_POOL(g_initable_new(OVIRT_TYPE_VM_POOL, NULL, NULL, NULL));
+}
+
+static gboolean
+ovirt_vm_pool_action(OvirtVmPool *vm_pool, OvirtProxy *proxy, const char *action,
+                     ActionResponseParser response_parser, GError **error)
+{
+    RestProxyCall *call;
+    const char *function;
+
+    g_return_val_if_fail(OVIRT_IS_VM_POOL(vm_pool), FALSE);
+    g_return_val_if_fail(action != NULL, FALSE);
+    g_return_val_if_fail(OVIRT_IS_PROXY(proxy), FALSE);
+    g_return_val_if_fail((error == NULL) || (*error == NULL), FALSE);
+
+    function = ovirt_resource_get_action(OVIRT_RESOURCE(vm_pool), action);
+    function = ovirt_utils_strip_api_base_dir(function);
+    g_return_val_if_fail(function != NULL, FALSE);
+
+    call = REST_PROXY_CALL(ovirt_action_rest_call_new(REST_PROXY(proxy)));
+    rest_proxy_call_set_method(call, "POST");
+    rest_proxy_call_set_function(call, function);
+    rest_proxy_call_add_param(call, "async", "false");
+
+    if (!rest_proxy_call_sync(call, error)) {
+        GError *call_error = NULL;
+        g_warning("Error while running %s on %p", action, vm_pool);
+        /* Even in error cases we may have a response body describing
+         * the failure, try to parse that */
+        parse_action_response(call, vm_pool, response_parser, &call_error);
+        if (call_error != NULL) {
+            g_clear_error(error);
+            g_propagate_error(error, call_error);
+        }
+
+        g_object_unref(G_OBJECT(call));
+        return FALSE;
+    }
+
+    parse_action_response(call, vm_pool, response_parser, error);
+
+    g_object_unref(G_OBJECT(call));
+
+    return TRUE;
+}
+
+gboolean ovirt_vm_pool_allocate_vm(OvirtVmPool *vm_pool, OvirtProxy *proxy, GError **error)
+{
+    return ovirt_vm_pool_action(vm_pool, proxy, "allocatevm", NULL, error);
+}
+
+static enum OvirtResponseStatus parse_action_status(RestXmlNode *root,
+                                                    GError **error)
+{
+    RestXmlNode *node;
+    const char *status_key = g_intern_string("status");
+    const char *state_key = g_intern_string("state");
+
+    g_return_val_if_fail(g_strcmp0(root->name, "action") == 0,
+                         OVIRT_RESPONSE_UNKNOWN);
+    g_return_val_if_fail(error == NULL || *error == NULL,
+                         OVIRT_RESPONSE_UNKNOWN);
+
+    node = g_hash_table_lookup(root->children, status_key);
+    if (node == NULL) {
+        g_set_error(error, OVIRT_ERROR, OVIRT_ERROR_PARSING_FAILED, "could not find 'status' node");
+        g_return_val_if_reached(OVIRT_RESPONSE_UNKNOWN);
+    }
+    node = g_hash_table_lookup(node->children, state_key);
+    if (node == NULL) {
+        g_set_error(error, OVIRT_ERROR, OVIRT_ERROR_PARSING_FAILED, "could not find 'state' node");
+        g_return_val_if_reached(OVIRT_RESPONSE_UNKNOWN);
+    }
+    g_debug("State: %s\n", node->content);
+    if (g_strcmp0(node->content, "complete") == 0) {
+        return OVIRT_RESPONSE_COMPLETE;
+    } else if (g_strcmp0(node->content, "pending") == 0) {
+        g_set_error(error, OVIRT_ERROR, OVIRT_ERROR_ACTION_FAILED, "action is pending");
+        return OVIRT_RESPONSE_PENDING;
+    } else if (g_strcmp0(node->content, "in_progress") == 0) {
+        g_set_error(error, OVIRT_ERROR, OVIRT_ERROR_ACTION_FAILED, "action is in progress");
+        return OVIRT_RESPONSE_IN_PROGRESS;
+    } else if (g_strcmp0(node->content, "failed") == 0) {
+        g_set_error(error, OVIRT_ERROR, OVIRT_ERROR_ACTION_FAILED, "action has failed");
+        return OVIRT_RESPONSE_FAILED;
+    }
+
+    g_set_error(error, OVIRT_ERROR, OVIRT_ERROR_PARSING_FAILED, "unknown action failure");
+    g_return_val_if_reached(OVIRT_RESPONSE_UNKNOWN);
+}
+
+
+static gboolean
+parse_action_response(RestProxyCall *call, OvirtVmPool *vm_pool,
+                      ActionResponseParser response_parser, GError **error)
+{
+    RestXmlNode *root;
+    gboolean result;
+
+    result = FALSE;
+    root = ovirt_rest_xml_node_from_call(call);
+
+    if (g_strcmp0(root->name, "action") == 0) {
+        enum OvirtResponseStatus status;
+
+        status = parse_action_status(root, error);
+        if (status  == OVIRT_RESPONSE_COMPLETE) {
+            if (response_parser) {
+                result = response_parser(root, vm_pool, error);
+            } else {
+                result = TRUE;
+            }
+        } if (status == OVIRT_RESPONSE_FAILED) {
+            const char *fault_key = g_intern_string("fault");
+            GError *fault_error = NULL;
+            RestXmlNode *fault_node = NULL;
+
+            fault_node = g_hash_table_lookup(root->children, fault_key);
+            if (fault_node != NULL) {
+                ovirt_utils_gerror_from_xml_fault(fault_node, &fault_error);
+                if (fault_error != NULL) {
+                    g_clear_error(error);
+                    g_propagate_error(error, fault_error);
+                }
+            }
+        }
+    } else {
+        g_warn_if_reached();
+    }
+
+    rest_xml_node_unref(root);
+
+    return result;
+}
+
+
+static gboolean vm_pool_set_size_from_xml(OvirtVmPool *vm_pool, RestXmlNode *node)
+{
+    RestXmlNode *size_node;
+    size_node = rest_xml_node_find(node, "size");
+    if (size_node != NULL) {
+        guint size;
+        g_return_val_if_fail(size_node->content != NULL, FALSE);
+        if (!ovirt_utils_guint_from_string(size_node->content, &size)) {
+            return FALSE;
+        }
+        g_object_set(G_OBJECT(vm_pool), "size", size, NULL);
+        return TRUE;
+    }
+    return FALSE;
+}
+
+
+static gboolean vm_pool_set_prestarted_vms_from_xml(OvirtVmPool *vm_pool, RestXmlNode *node)
+{
+    RestXmlNode *prestarted_vms_node;
+    prestarted_vms_node = rest_xml_node_find(node, "prestarted_vms");
+    if (prestarted_vms_node != NULL) {
+        guint prestarted_vms;
+        g_return_val_if_fail(prestarted_vms_node->content != NULL, FALSE);
+        if (!ovirt_utils_guint_from_string(prestarted_vms_node->content, &prestarted_vms)) {
+            return FALSE;
+        }
+        g_object_set(G_OBJECT(vm_pool), "prestarted_vms", prestarted_vms, NULL);
+        return TRUE;
+    }
+    return FALSE;
+}
+
+
+static gboolean vm_pool_set_max_user_vms_from_xml(OvirtVmPool *vm_pool, RestXmlNode *node)
+{
+    RestXmlNode *max_user_vms_node;
+    max_user_vms_node = rest_xml_node_find(node, "max_user_vms");
+    if (max_user_vms_node != NULL) {
+        guint max_user_vms;
+        g_return_val_if_fail(max_user_vms_node->content != NULL, FALSE);
+        if (!ovirt_utils_guint_from_string(max_user_vms_node->content, &max_user_vms)) {
+            return FALSE;
+        }
+        g_object_set(G_OBJECT(vm_pool), "max_user_vms", max_user_vms, NULL);
+        return TRUE;
+    }
+    return FALSE;
+}
+
+
+static gboolean ovirt_vm_pool_refresh_from_xml(OvirtVmPool *vm_pool, RestXmlNode *node)
+{
+    vm_pool_set_size_from_xml(vm_pool, node);
+    vm_pool_set_prestarted_vms_from_xml(vm_pool, node);
+    vm_pool_set_max_user_vms_from_xml(vm_pool, node);
+    return TRUE;
+}
diff --git a/govirt/ovirt-vm-pool.h b/govirt/ovirt-vm-pool.h
new file mode 100644
index 0000000..e4245cb
--- /dev/null
+++ b/govirt/ovirt-vm-pool.h
@@ -0,0 +1,65 @@
+/*
+ * ovirt-vm-pool.h: oVirt VM pool
+ *
+ * Copyright (C) 2013 Iordan Iordanov <i at iiordanov.com>
+ *
+ * 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/>.
+ */
+#ifndef __OVIRT_VM_POOL_H__
+#define __OVIRT_VM_POOL_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_VM_POOL            (ovirt_vm_pool_get_type ())
+#define OVIRT_VM_POOL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), OVIRT_TYPE_VM_POOL, OvirtVmPool))
+#define OVIRT_VM_POOL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), OVIRT_TYPE_VM_POOL, OvirtVmPoolClass))
+#define OVIRT_IS_VM_POOL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OVIRT_TYPE_VM_POOL))
+#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;
+
+struct _OvirtVmPool
+{
+    OvirtResource parent;
+
+    OvirtVmPoolPrivate *priv;
+
+    /* Do not add fields to this struct */
+};
+
+struct _OvirtVmPoolClass
+{
+    OvirtResourceClass parent_class;
+
+    gpointer padding[20];
+};
+
+GType ovirt_vm_pool_get_type(void);
+OvirtVmPool *ovirt_vm_pool_new(void);
+
+gboolean ovirt_vm_pool_allocate_vm(OvirtVmPool *vm_pool, OvirtProxy *proxy, GError **error);
+
+G_END_DECLS
+
+#endif /* __OVIRT_VM_POOL_H__ */
-- 
1.8.4.2

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/spice-devel/attachments/20131203/be349077/attachment-0001.pgp>


More information about the Spice-devel mailing list