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@xxxxxxxxx> 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@xxxxxxxxxxxxx> * * 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@xxxxxxxxxxxxx> + * + * 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@xxxxxxxxxxxxx> + * + * 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
Attachment:
pgp1a4vz3KJaF.pgp
Description: PGP signature
_______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel