[Libvirt-cim] [PATCH 2 of 2] Make migration spawn an asynchronous job

Dan Smith danms at us.ibm.com
Mon Dec 10 18:26:50 UTC 2007


# HG changeset patch
# User Dan Smith <danms at us.ibm.com>
# Date 1197314773 28800
# Node ID 9a8027256eec1641b901477a63f7787c73edd1ee
# Parent  3515a63e76897dec28f1543f9ce7172e5bae567d
Make migration spawn an asynchronous job

Signed-off-by: Dan Smith <danms at us.ibm.com>

diff -r 3515a63e7689 -r 9a8027256eec src/Virt_VSMigrationService.c
--- a/src/Virt_VSMigrationService.c	Mon Dec 10 10:28:54 2007 -0800
+++ b/src/Virt_VSMigrationService.c	Mon Dec 10 11:26:13 2007 -0800
@@ -22,6 +22,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <uuid/uuid.h>
+
 #include <libvirt/libvirt.h>
 
 #include <cmpidt.h>
@@ -35,6 +37,10 @@
 
 #include "Virt_VSMigrationService.h"
 
+#define CIM_JOBSTATE_STARTING 3
+#define CIM_JOBSTATE_RUNNING 4
+#define CIM_JOBSTATE_COMPLETE 7
+
 #define METHOD_RETURN(r, v) do {                                        \
                 uint32_t rc = v;                                        \
                 CMReturnData(r, (CMPIValue *)&rc, CMPI_uint32);         \
@@ -42,12 +48,17 @@
 
 const static CMPIBroker *_BROKER;
 
-static const char *transport_from_ref(const CMPIObjectPath *ref)
-{
-        const char *cn;
-
-        cn = CLASSNAME(ref);
-
+struct migration_job {
+        CMPIContext *context;
+        char *domain;
+        char *host;
+        char *ref_cn;
+        char *ref_ns;
+        char uuid[33];
+};
+
+static const char *transport_from_class(const char *cn)
+{
         if (STARTS_WITH(cn, "Xen"))
                 return "xen+ssh";
         else if (STARTS_WITH(cn, "KVM"))
@@ -56,15 +67,15 @@ static const char *transport_from_ref(co
                 return NULL;
 }
 
-static char *dest_uri(const CMPIObjectPath *ref,
+static char *dest_uri(const char *cn,
                       const char *dest)
 {
         char *uri;
         const char *tport = NULL;
 
-        tport = transport_from_ref(ref);
+        tport = transport_from_class(cn);
         if (tport == NULL) {
-                CU_DEBUG("Failed to get transport for %s", CLASSNAME(ref));
+                CU_DEBUG("Failed to get transport for %s", cn);
                 return NULL;
         }
 
@@ -127,7 +138,7 @@ static CMPIStatus vs_migratable(const CM
         virConnectPtr dconn = NULL;
         uint32_t retcode = 1;
 
-        uri = dest_uri(ref, destination);
+        uri = dest_uri(CLASSNAME(ref), destination);
         if (uri == NULL) {
                 cu_statusf(_BROKER, &s,
                            CMPI_RC_ERR_FAILED,
@@ -230,10 +241,48 @@ static CMPIStatus vs_migratable_system(C
         return vs_migratable(ref, name, dname, results);
 }
 
-static CMPIStatus migrate_vs(const CMPIObjectPath *ref,
-                             const char *domain,
-                             const char *destination,
-                             const CMPIResult *results)
+static void migrate_job_set_state(struct migration_job *job,
+                                  uint16_t state,
+                                  const char *status)
+{
+        CMPIInstance *inst;
+        CMPIStatus s;
+        CMPIObjectPath *op;
+
+        op = CMNewObjectPath(_BROKER,
+                             job->ref_ns,
+                             "Virt_MigrationJob",
+                             &s);
+        if (s.rc != CMPI_RC_OK) {
+                CU_DEBUG("Failed to create job path for update");
+                return;
+        }
+
+        CMSetNameSpace(op, job->ref_ns);
+        CMAddKey(op, "InstanceID", (CMPIValue *)job->uuid, CMPI_chars);
+
+        CU_DEBUG("Getting job instance %s", job->uuid);
+        CU_DEBUG("  OP: %s", CMGetCharPtr(CMObjectPathToString(op, NULL)));
+        inst = CBGetInstance(_BROKER, job->context, op, NULL, &s);
+        if ((inst == NULL) || (s.rc != CMPI_RC_OK)) {
+                CU_DEBUG("Failed to get job instance for update (%i)", s.rc);
+                return;
+        }
+
+        CMSetProperty(inst, "JobState",
+                      (CMPIValue *)&state, CMPI_uint16);
+        CMSetProperty(inst, "Status",
+                      (CMPIValue *)status, CMPI_chars);
+
+        CU_DEBUG("Modifying job %s (%i:%s)", job->uuid, state, status);
+
+        s = CBModifyInstance(_BROKER, job->context, op, inst, NULL);
+        if (s.rc != CMPI_RC_OK)
+                CU_DEBUG("Failed to update job instance: %s",
+                         CMGetCharPtr(s.msg));
+}
+
+static CMPIStatus migrate_vs(struct migration_job *job)
 {
         CMPIStatus s;
         virConnectPtr conn = NULL;
@@ -241,9 +290,8 @@ static CMPIStatus migrate_vs(const CMPIO
         virDomainPtr dom = NULL;
         virDomainPtr ddom = NULL;
         char *uri = NULL;
-        uint32_t retcode = 1;
-
-        uri = dest_uri(ref, destination);
+
+        uri = dest_uri(job->ref_cn, job->host);
         if (uri == NULL) {
                 cu_statusf(_BROKER, &s,
                            CMPI_RC_ERR_FAILED,
@@ -251,16 +299,16 @@ static CMPIStatus migrate_vs(const CMPIO
                 goto out;
         }
 
-        conn = connect_by_classname(_BROKER, CLASSNAME(ref), &s);
+        conn = connect_by_classname(_BROKER, job->ref_cn, &s);
         if (conn == NULL)
                 goto out;
 
-        dom = virDomainLookupByName(conn, domain);
+        dom = virDomainLookupByName(conn, job->domain);
         if (dom == NULL) {
-                CU_DEBUG("Failed to lookup `%s'", domain);
-                cu_statusf(_BROKER, &s,
-                           CMPI_RC_ERR_FAILED,
-                           "Failed to lookup domain `%s'", domain);
+                CU_DEBUG("Failed to lookup `%s'", job->domain);
+                cu_statusf(_BROKER, &s,
+                           CMPI_RC_ERR_FAILED,
+                           "Failed to lookup domain `%s'", job->domain);
                 goto out;
         }
 
@@ -273,7 +321,7 @@ static CMPIStatus migrate_vs(const CMPIO
                 goto out;
         }
 
-        CU_DEBUG("Migrating %s -> %s", domain, uri);
+        CU_DEBUG("Migrating %s -> %s", job->domain, uri);
 
         ddom = virDomainMigrate(dom, dconn, VIR_MIGRATE_LIVE, NULL, NULL, 0);
         if (ddom == NULL) {
@@ -285,17 +333,194 @@ static CMPIStatus migrate_vs(const CMPIO
         }
 
         CU_DEBUG("Migration succeeded");
-        retcode = 0;
         CMSetStatus(&s, CMPI_RC_OK);
 
  out:
-        CMReturnData(results, (CMPIValue *)&retcode, CMPI_uint32);
-
         free(uri);
         virDomainFree(dom);
         virDomainFree(ddom);
         virConnectClose(conn);
         virConnectClose(dconn);
+
+        return s;
+}
+
+static CMPI_THREAD_RETURN migration_thread(struct migration_job *job)
+{
+        CMPIStatus s;
+
+        CBAttachThread(_BROKER, job->context);
+
+        CU_DEBUG("Migration Job %s started", job->uuid);
+        migrate_job_set_state(job, CIM_JOBSTATE_RUNNING, "Running");
+
+        s = migrate_vs(job);
+
+        CU_DEBUG("Migration Job %s finished: %i", job->uuid, s.rc);
+        if (s.rc != CMPI_RC_OK)
+                migrate_job_set_state(job,
+                                      CIM_JOBSTATE_COMPLETE,
+                                      CMGetCharPtr(s.msg));
+        else
+                migrate_job_set_state(job,
+                                      CIM_JOBSTATE_COMPLETE,
+                                      "Completed");
+
+        free(job->domain);
+        free(job->host);
+        free(job->ref_cn);
+        free(job->ref_ns);
+        free(job);
+
+        return NULL;
+}
+
+static CMPIInstance *_migrate_job_new_instance(const char *cn,
+                                               const char *ns)
+{
+        CMPIObjectPath *op;
+        CMPIInstance *inst;
+        CMPIStatus s;
+
+        op = CMNewObjectPath(_BROKER, ns, cn, &s);
+        if ((s.rc != CMPI_RC_OK) || (CMIsNullObject(op))) {
+                CU_DEBUG("Failed to create ref: %s:%s", ns, cn);
+                return NULL;
+        }
+
+        inst = CMNewInstance(_BROKER, op, &s);
+        if ((s.rc != CMPI_RC_OK) || (CMIsNullObject(op))) {
+                CU_DEBUG("Failed to create instance from ref: %s",
+                         CMGetCharPtr(CMObjectPathToString(op, NULL)));
+                return NULL;
+        }
+
+        return inst;
+}
+
+static CMPIStatus migrate_create_job_instance(const CMPIContext *context,
+                                              struct migration_job *job,
+                                              CMPIObjectPath **job_op)
+{
+        CMPIStatus s;
+        CMPIInstance *jobinst;
+        CMPIDateTime *start;
+        CMPIBoolean autodelete = true;
+        uint16_t state = CIM_JOBSTATE_STARTING;
+
+        start = CMNewDateTime(_BROKER, &s);
+        if ((s.rc != CMPI_RC_OK) || CMIsNullObject(start)) {
+                cu_statusf(_BROKER, &s,
+                           CMPI_RC_ERR_FAILED,
+                           "Failed to get job start time");
+                goto out;
+        }
+
+        jobinst = _migrate_job_new_instance("Virt_MigrationJob",
+                                            job->ref_ns);
+        if (jobinst == NULL) {
+                cu_statusf(_BROKER, &s,
+                           CMPI_RC_ERR_FAILED,
+                           "Unable to get instance of MigrationJob");
+                goto out;
+        }
+
+        CMSetProperty(jobinst, "InstanceID",
+                      (CMPIValue *)job->uuid, CMPI_chars);
+        CMSetProperty(jobinst, "Name",
+                      (CMPIValue *)"Migration", CMPI_chars);
+        CMSetProperty(jobinst, "StartTime",
+                      (CMPIValue *)&start, CMPI_dateTime);
+        CMSetProperty(jobinst, "JobState",
+                      (CMPIValue *)&state, CMPI_uint16);
+        CMSetProperty(jobinst, "Status",
+                      (CMPIValue *)"Queued", CMPI_chars);
+        CMSetProperty(jobinst, "DeleteOnCompletion",
+                      (CMPIValue *)&autodelete, CMPI_boolean);
+
+        *job_op = CMGetObjectPath(jobinst, &s);
+        if ((*job_op == NULL) || (s.rc != CMPI_RC_OK)) {
+                cu_statusf(_BROKER, &s,
+                           CMPI_RC_ERR_FAILED,
+                           "Failed to get path for job instance");
+                goto out;
+        }
+
+        CMSetNameSpace(*job_op, job->ref_ns);
+
+        CU_DEBUG("Creating instance: %s",
+                 CMGetCharPtr(CMObjectPathToString(*job_op, NULL)));
+
+        *job_op = CBCreateInstance(_BROKER, context, *job_op, jobinst, &s);
+        if ((s.rc != CMPI_RC_OK) || (CMIsNullObject(*job_op))) {
+                CU_DEBUG("Failed to create job instance: %i", s.rc);
+                goto out;
+        }
+
+ out:
+        return s;
+}
+
+static struct migration_job *migrate_job_prepare(const CMPIContext *context,
+                                                 const CMPIObjectPath *ref,
+                                                 const char *domain,
+                                                 const char *host)
+{
+        struct migration_job *job;
+        uuid_t uuid;
+
+        job = malloc(sizeof(*job));
+        if (job == NULL)
+                return NULL;
+
+        job->domain = strdup(domain);
+        job->host = strdup(host);
+        job->ref_cn = strdup(CLASSNAME(ref));
+        job->ref_ns = strdup(NAMESPACE(ref));
+
+        uuid_generate(uuid);
+        uuid_unparse(uuid, job->uuid);
+
+        job->context = CBPrepareAttachThread(_BROKER, context);
+
+        return job;
+}
+
+static CMPIStatus migrate_do(const CMPIObjectPath *ref,
+                             const CMPIContext *context,
+                             const char *domain,
+                             const char *host,
+                             const CMPIResult *results,
+                             CMPIArgs *argsout)
+{
+        CMPIStatus s;
+        CMPIObjectPath *job_op;
+        struct migration_job *job;
+        CMPI_THREAD_TYPE thread;
+        uint32_t retcode = 1;
+
+        job = migrate_job_prepare(context, ref, domain, host);
+        if (job == NULL) {
+                cu_statusf(_BROKER, &s,
+                           CMPI_RC_ERR_FAILED,
+                           "Unable to prepare migration job");
+                goto out;
+        }
+
+        CU_DEBUG("Prepared migration job %s", job->uuid);
+
+        s = migrate_create_job_instance(context, job, &job_op);
+        if (s.rc != CMPI_RC_OK)
+                goto out;
+
+        CMAddArg(argsout, "Job", (CMPIValue *)&job_op, CMPI_ref);
+
+        thread = _BROKER->xft->newThread((void*)migration_thread, job, 0);
+
+        retcode = 0;
+
+ out:
+        CMReturnData(results, (CMPIValue *)&retcode, CMPI_uint32);
 
         return s;
 }
@@ -323,15 +548,15 @@ static CMPIStatus migrate_vs_host(CMPIMe
                 return s;
         }
 
-        return migrate_vs(ref, name, dhost, results);
+        return migrate_do(ref, ctx, name, dhost, results, argsout);
 }
 
 static CMPIStatus migrate_vs_system(CMPIMethodMI *self,
-                                  const CMPIContext *ctx,
-                                  const CMPIResult *results,
-                                  const CMPIObjectPath *ref,
-                                  const CMPIArgs *argsin,
-                                  CMPIArgs *argsout)
+                                    const CMPIContext *ctx,
+                                    const CMPIResult *results,
+                                    const CMPIObjectPath *ref,
+                                    const CMPIArgs *argsin,
+                                    CMPIArgs *argsout)
 {
         CMPIStatus s;
         CMPIObjectPath *dsys;
@@ -358,7 +583,7 @@ static CMPIStatus migrate_vs_system(CMPI
                 return s;
         }
 
-        return migrate_vs(ref, name, dname, results);
+        return migrate_do(ref, ctx, name, dname, results, argsout);
 }
 
 static struct method_handler vsimth = {




More information about the Libvirt-cim mailing list