[libgovirt] Add ovirt_resource_action() method



commit 125c0f761b52ec689bcee6cf064337d45a5b5d0d
Author: Christophe Fergeau <cfergeau redhat com>
Date:   Tue Dec 3 19:44:40 2013 +0100

    Add ovirt_resource_action() method
    
    This will do a synchronous call to invoke an oVirt REST action. This is
    a generic version of ovirt_vm_action() which has been ported to it.

 govirt/ovirt-resource-private.h |    6 ++
 govirt/ovirt-resource.c         |  143 +++++++++++++++++++++++++++++++++++++++
 govirt/ovirt-vm.c               |   66 ++++--------------
 3 files changed, 162 insertions(+), 53 deletions(-)
---
diff --git a/govirt/ovirt-resource-private.h b/govirt/ovirt-resource-private.h
index c026014..0766049 100644
--- a/govirt/ovirt-resource-private.h
+++ b/govirt/ovirt-resource-private.h
@@ -32,6 +32,12 @@ const char *ovirt_resource_get_action(OvirtResource *resource,
 char *ovirt_resource_to_xml(OvirtResource *resource);
 gboolean ovirt_resource_rest_call_sync(OvirtRestCall *call, GError **error);
 
+typedef gboolean (*ActionResponseParser)(RestXmlNode *node, OvirtResource *resource, GError **error);
+gboolean ovirt_resource_action(OvirtResource *resource, OvirtProxy *proxy,
+                               const char *action,
+                               ActionResponseParser response_parser,
+                               GError **error);
+
 G_END_DECLS
 
 #endif /* __OVIRT_RESOURCE_PRIVATE_H__ */
diff --git a/govirt/ovirt-resource.c b/govirt/ovirt-resource.c
index fca06e8..a8cb13c 100644
--- a/govirt/ovirt-resource.c
+++ b/govirt/ovirt-resource.c
@@ -585,3 +585,146 @@ gboolean ovirt_resource_update_finish(OvirtResource *resource,
 
     return ovirt_rest_call_finish(result, err);
 }
+
+
+enum OvirtResponseStatus {
+    OVIRT_RESPONSE_UNKNOWN,
+    OVIRT_RESPONSE_FAILED,
+    OVIRT_RESPONSE_PENDING,
+    OVIRT_RESPONSE_IN_PROGRESS,
+    OVIRT_RESPONSE_COMPLETE
+};
+
+static gboolean parse_action_response(RestProxyCall *call, OvirtResource *resource,
+                                      ActionResponseParser response_parser,
+                                      GError **error);
+
+gboolean
+ovirt_resource_action(OvirtResource *resource, OvirtProxy *proxy,
+                      const char *action,
+                      ActionResponseParser response_parser,
+                      GError **error)
+{
+    RestProxyCall *call;
+    const char *function;
+
+    g_return_val_if_fail(OVIRT_IS_RESOURCE(resource), 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(resource), 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, resource);
+        /* Even in error cases we may have a response body describing
+         * the failure, try to parse that */
+        parse_action_response(call, resource, 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, resource, response_parser, error);
+
+    g_object_unref(G_OBJECT(call));
+
+    return TRUE;
+}
+
+
+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, OvirtResource *resource,
+                      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, resource, 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;
+}
diff --git a/govirt/ovirt-vm.c b/govirt/ovirt-vm.c
index 7f83384..be39eb7 100644
--- a/govirt/ovirt-vm.c
+++ b/govirt/ovirt-vm.c
@@ -30,11 +30,10 @@
 #include "govirt-private.h"
 
 
-typedef gboolean (*ActionResponseParser)(RestXmlNode *node, OvirtVm *vm, GError **error);
 static gboolean parse_action_response(RestProxyCall *call, OvirtVm *vm,
                                       ActionResponseParser response_parser,
                                       GError **error);
-static gboolean parse_ticket_status(RestXmlNode *root, OvirtVm *vm,
+static gboolean parse_ticket_status(RestXmlNode *root, OvirtResource *resource,
                                     GError **error);
 
 #define OVIRT_VM_GET_PRIVATE(obj)                         \
@@ -307,68 +306,28 @@ ovirt_vm_stop_finish(OvirtVm *vm, GAsyncResult *result, GError **err)
 }
 
 
-static gboolean
-ovirt_vm_action(OvirtVm *vm, OvirtProxy *proxy, const char *action,
-                ActionResponseParser response_parser, GError **error)
-{
-    RestProxyCall *call;
-    const char *function;
-
-    g_return_val_if_fail(OVIRT_IS_VM(vm), 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), 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);
-        /* Even in error cases we may have a response body describing
-         * the failure, try to parse that */
-        parse_action_response(call, vm, 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, response_parser, error);
-
-    g_object_unref(G_OBJECT(call));
-
-    return TRUE;
-}
-
 gboolean ovirt_vm_get_ticket(OvirtVm *vm, OvirtProxy *proxy, GError **error)
 {
-    return ovirt_vm_action(vm, proxy, "ticket",
-                           parse_ticket_status,
-                           error);
+    return ovirt_resource_action(OVIRT_RESOURCE(vm), proxy, "ticket",
+                                 parse_ticket_status,
+                                 error);
 }
 
 gboolean ovirt_vm_start(OvirtVm *vm, OvirtProxy *proxy, GError **error)
 {
-    return ovirt_vm_action(vm, proxy, "start", NULL, error);
+    return ovirt_resource_action(OVIRT_RESOURCE(vm), proxy, "start",
+                                 NULL, error);
 }
 
 gboolean ovirt_vm_stop(OvirtVm *vm, OvirtProxy *proxy, GError **error)
 {
-    return ovirt_vm_action(vm, proxy, "stop", NULL, error);
+    return ovirt_resource_action(OVIRT_RESOURCE(vm), proxy, "stop",
+                                 NULL, error);
 }
 
-static gboolean parse_ticket_status(RestXmlNode *root, OvirtVm *vm, GError **error)
+static gboolean parse_ticket_status(RestXmlNode *root, OvirtResource *resource, GError **error)
 {
+    OvirtVm *vm;
     RestXmlNode *node;
     const char *ticket_key = g_intern_string("ticket");
     const char *value_key = g_intern_string("value");
@@ -376,9 +335,10 @@ static gboolean parse_ticket_status(RestXmlNode *root, OvirtVm *vm, GError **err
     OvirtVmDisplay *display;
 
     g_return_val_if_fail(root != NULL, FALSE);
-    g_return_val_if_fail(vm != NULL, FALSE);
+    g_return_val_if_fail(OVIRT_IS_VM(resource), FALSE);
     g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
 
+    vm = OVIRT_VM(resource);
     root = g_hash_table_lookup(root->children, ticket_key);
     if (root == NULL) {
         g_set_error(error, OVIRT_ERROR, OVIRT_ERROR_PARSING_FAILED, "could not find 'ticket' node");
@@ -467,7 +427,7 @@ parse_action_response(RestProxyCall *call, OvirtVm *vm,
         status = parse_action_status(root, error);
         if (status  == OVIRT_RESPONSE_COMPLETE) {
             if (response_parser) {
-                result = response_parser(root, vm, error);
+                result = response_parser(root, OVIRT_RESOURCE(vm), error);
             } else {
                 result = TRUE;
             }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]