[Libvirt-cim] [PATCH 2/3] ComputerSystem: Make Shutdown state change a job

Sharad Mishra snmishra at linux.vnet.ibm.com
Wed Mar 7 17:50:39 UTC 2012


Visual code inspection looks good.
Need to apply and test the patch.

-Sharad

On Tue, 2012-03-06 at 14:55 -0300, Eduardo Lima (Etrunko) wrote:
> From: "Eduardo Lima (Etrunko)" <eblima at br.ibm.com>
> 
> For Shutdown, the RequestStateChange method returns immediately with
> return code 0 (successful) even though the state change is still not completed.
> 
> According to the DMTF specification DSP1052 (Computer System Profile) the
> RequestStateChange() method should return 0x1000 and a corresponding job
> reference in the return parameters which can be polled for completion.
> 
> Signed-off-by: Eduardo Lima (Etrunko) <eblima at br.ibm.com>
> ---
>  schema/ComputerSystem.mof |    9 ++
>  src/Virt_ComputerSystem.c |  236 +++++++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 238 insertions(+), 7 deletions(-)
> 
> diff --git a/schema/ComputerSystem.mof b/schema/ComputerSystem.mof
> index 10cb8c4..886c085 100644
> --- a/schema/ComputerSystem.mof
> +++ b/schema/ComputerSystem.mof
> @@ -1,5 +1,14 @@
>  // Copyright IBM Corp. 2007
> 
> +class Xen_ComputerSystemStateChangeJob : CIM_ConcreteJob {
> +};
> +
> +class KVM_ComputerSystemStateChangeJob : CIM_ConcreteJob {
> +};
> +
> +class LXC_ComputerSystemStateChangeJob : CIM_ConcreteJob {
> +};
> +
>  [Description (
>  	"A class derived from CIM_ComputerSystem to represent "
>  	"the Xen virtual machines/domains running on the system."),
> diff --git a/src/Virt_ComputerSystem.c b/src/Virt_ComputerSystem.c
> index e6c7e55..778809d 100644
> --- a/src/Virt_ComputerSystem.c
> +++ b/src/Virt_ComputerSystem.c
> @@ -30,23 +30,37 @@
>  #include <cmpift.h>
>  #include <cmpimacs.h>
> 
> +#include <uuid.h>
>  #include <libvirt/libvirt.h>
> 
> -#include "cs_util.h"
>  #include <libcmpiutil/libcmpiutil.h>
> -#include "misc_util.h"
> -#include "infostore.h"
> -#include "device_parsing.h"
>  #include <libcmpiutil/std_invokemethod.h>
>  #include <libcmpiutil/std_instance.h>
>  #include <libcmpiutil/std_indication.h>
> 
> +#include "cs_util.h"
> +#include "misc_util.h"
> +#include "infostore.h"
> +#include "device_parsing.h"
> +#include "svpc_types.h"
> +
>  #include "Virt_ComputerSystem.h"
>  #include "Virt_HostSystem.h"
>  #include "Virt_VirtualSystemSnapshotService.h"
> 
> +
>  const static CMPIBroker *_BROKER;
> 
> +typedef struct _state_change_job state_change_job_t;
> +struct _state_change_job {
> +        char uuid[VIR_UUID_STRING_BUFLEN];
> +        CMPIContext *context;
> +        CMPIObjectPath *obj_path;
> +        char *dom_name;
> +        uint16_t dom_state;
> +        uint16_t status; /* job status */
> +};
> +
>  /* Set the "Name" property of an instance from a domain */
>  static int set_name_from_dom(virDomainPtr dom, CMPIInstance *instance)
>  {
> @@ -1190,7 +1204,7 @@ static CMPIStatus __state_change(const char *name,
>          else if (state == CIM_STATE_DISABLED)
>                  s = state_change_disable(dom, &info);
>          else if (state == CIM_STATE_SHUTDOWN)
> -                s = state_change_shutdown(dom, &info);
> +                s.rc = CIM_SVPC_RETURN_JOB_STARTED;
>          else if (state == CIM_STATE_PAUSED)
>                  s = state_change_pause(dom, &info);
>          else if (state == CIM_STATE_REBOOT)
> @@ -1202,6 +1216,9 @@ static CMPIStatus __state_change(const char *name,
>                             CMPI_RC_ERR_NOT_SUPPORTED,
>                             "State not supported");
> 
> +        if (s.rc != CMPI_RC_OK && s.rc != CIM_SVPC_RETURN_JOB_STARTED)
> +                goto out;
> +
>          infostore = infostore_open(dom);
>          if (infostore != NULL) {
>                  infostore_set_u64(infostore, "reqstate", (uint64_t)state);
> @@ -1215,6 +1232,191 @@ static CMPIStatus __state_change(const char *name,
>          return s;
>  }
> 
> +static CMPIStatus create_state_change_job(const CMPIObjectPath *ref,
> +                                          const CMPIContext *context,
> +                                          state_change_job_t **job,
> +                                          uint16_t state)
> +{
> +        CMPIStatus s = {CMPI_RC_OK, NULL};
> +        CMPIInstance *job_inst;
> +        CMPIDateTime *start;
> +        CMPIBoolean autodelete = true;
> +        CMPIObjectPath *obj_path;
> +        uuid_t uuid;
> +        char *type = NULL, *cn = NULL, *ns = NULL;
> +
> +        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;
> +        }
> +
> +        cn = strdup(CLASSNAME(ref));
> +        type = get_typed_class(cn, "ComputerSystemStateChangeJob");
> +
> +        obj_path = CMNewObjectPath(_BROKER, ns, type, &s);
> +        if ((s.rc != CMPI_RC_OK) || (CMIsNullObject(obj_path))) {
> +                cu_statusf(_BROKER, &s,
> +                           CMPI_RC_ERR_FAILED,
> +                           "Failed to get new object path");
> +                goto out;
> +        }
> +
> +        job_inst = CMNewInstance(_BROKER, obj_path, &s);
> +        if ((s.rc != CMPI_RC_OK) || (CMIsNullObject(job_inst))) {
> +                cu_statusf(_BROKER, &s,
> +                           CMPI_RC_ERR_FAILED,
> +                           "Failed to get new instance object");
> +                goto out;
> +        }
> +
> +        /* Alloc job struct */
> +        *job = calloc(1, sizeof(**job));
> +        if (*job == NULL) {
> +                cu_statusf(_BROKER, &s,
> +                           CMPI_RC_ERR_FAILED,
> +                           "Failed to allocate memory for job structure");
> +                goto out;
> +        }
> +
> +        (*job)->dom_state = state;
> +        (*job)->status = CIM_JOB_STATE_STARTING;
> +
> +        uuid_generate(uuid);
> +        uuid_unparse(uuid, (*job)->uuid);
> +
> +        /* Set Properties */
> +        CMSetProperty(job_inst, "InstanceID",
> +                      (CMPIValue *)(*job)->uuid, CMPI_chars);
> +        CMSetProperty(job_inst, "Name",
> +                      (CMPIValue *) "ComputerSystemStateChange", CMPI_chars);
> +        CMSetProperty(job_inst, "StartTime",
> +                      (CMPIValue *)&start, CMPI_dateTime);
> +        CMSetProperty(job_inst, "JobState",
> +                      (CMPIValue *)&((*job)->status), CMPI_uint16);
> +        CMSetProperty(job_inst, "Status",
> +                      (CMPIValue *) "Starting", CMPI_chars);
> +        CMSetProperty(job_inst, "DeleteOnCompletion",
> +                      (CMPIValue *)&autodelete, CMPI_boolean);
> +
> +        obj_path = CMGetObjectPath(job_inst, &s);
> +        if ((obj_path == NULL) || (s.rc != CMPI_RC_OK)) {
> +                cu_statusf(_BROKER, &s,
> +                           CMPI_RC_ERR_FAILED,
> +                           "Failed to get path for ComputerSystemStateChangeJob instance");
> +                goto out;
> +        }
> +
> +        CMSetNameSpace(obj_path, ns);
> +
> +        CU_DEBUG("Creating ComputerSystemStateChangeJob instance: %s",
> +                 CMGetCharPtr(CMObjectPathToString(obj_path, NULL)));
> +
> +        obj_path = CBCreateInstance(_BROKER, context, obj_path, job_inst, &s);
> +        if ((s.rc != CMPI_RC_OK) || (CMIsNullObject(obj_path))) {
> +                CU_DEBUG("Failed to create ComputerSystemStateChangeJob instance: %i", s.rc);
> +                goto out;
> +        }
> +
> +        ns = strdup(NAMESPACE(ref));
> +        CMSetNameSpace(obj_path, ns);
> +
> +        (*job)->obj_path = obj_path;
> +        (*job)->context = CBPrepareAttachThread(_BROKER, context);
> +
> + out:
> +        free(type);
> +        free(cn);
> +        free(ns);
> +        return s;
> +}
> +
> +static CMPI_THREAD_RETURN state_change_thread(void *data)
> +{
> +        CMPIStatus s;
> +        CMPIInstance *inst = NULL;
> +        state_change_job_t *job = (state_change_job_t *) data;
> +        virConnectPtr conn = NULL;
> +        virDomainPtr dom = NULL;
> +        virDomainInfo info;
> +
> +        if (job->dom_state != CIM_STATE_SHUTDOWN) {
> +                CU_DEBUG("Unrecognized state '%d'", job->dom_state);
> +                goto end;
> +        }
> +
> +        /* Set job state */
> +        CBAttachThread(_BROKER, job->context);
> +        CU_DEBUG("State change job %s started", job->uuid);
> +        job->status = CIM_JOB_STATE_RUNNING;
> +
> +        inst = CBGetInstance(_BROKER, job->context, job->obj_path, NULL, &s);
> +        if ((inst == NULL) || (s.rc != CMPI_RC_OK)) {
> +                CU_DEBUG("Failed to get job instance (%i)", s.rc);
> +                return NULL;
> +        }
> +
> +        CMSetProperty(inst, "JobState",
> +                      (CMPIValue *)&(job->status), CMPI_uint16);
> +        CMSetProperty(inst, "Status",
> +                      (CMPIValue *) "Running", CMPI_chars);
> +
> +        /* Connect to domain event callback */
> +        conn = connect_by_classname(_BROKER, CLASSNAME(job->obj_path), &s);
> +        if (conn == NULL) {
> +                CU_DEBUG("Unable to connect to '%s' hypervisor",
> +                         CLASSNAME(job->obj_path));
> +                goto out;
> +        }
> +
> +        dom = virDomainLookupByName(conn, job->dom_name);
> +        if (dom == NULL) {
> +                CU_DEBUG("Unable to get domain '%s'", job->dom_name);
> +                goto out;
> +        }
> +
> +        if (virDomainGetInfo(dom, &info) != 0) {
> +                CU_DEBUG("Unable to get domain info for '%s'", job->dom_name);
> +                goto out;
> +        }
> +
> +        s = state_change_shutdown(dom, &info);
> +        if (s.rc != CMPI_RC_OK) {
> +                CU_DEBUG("Unable to trigger domain shutdown: '%s'",
> +                         CMGetCharPtr(s.msg));
> +                goto out;
> +        }
> +
> +        /* Wait for operation (shutdown/reboot) to complete */
> +        while (info.state != VIR_DOMAIN_SHUTOFF) {
> +                usleep(100 * 1000);
> +                virDomainGetInfo(dom, &info);
> +        }
> +
> +        CU_DEBUG("Job completed");
> +
> +        /* Set job state */
> +        if (job->status == CIM_JOB_STATE_COMPLETED) {
> +                CMSetProperty(inst, "JobState",
> +                              (CMPIValue *)&(job->status), CMPI_uint16);
> +                CMSetProperty(inst, "Status",
> +                              (CMPIValue *) "Completed", CMPI_chars);
> +        }
> +
> + out:
> +        virDomainFree(dom);
> +        virConnectClose(conn);
> +
> +        CBDetachThread(_BROKER, job->context);
> +        free(job->dom_name);
> +        free(job);
> +
> + end:
> +        return NULL;
> +}
> +
>  static CMPIStatus state_change(CMPIMethodMI *self,
>                                 const CMPIContext *context,
>                                 const CMPIResult *results,
> @@ -1244,7 +1446,8 @@ static CMPIStatus state_change(CMPIMethodMI *self,
>                  goto out;
>          }
> 
> -        /* Retain original instance of the guest to use for the PreviousInstance           attribute when generating an indication. */
> +        /* Retain original instance of the guest to use for the PreviousInstance
> +           attribute when generating an indication. */
>          s = get_domain_by_name(_BROKER, reference, name, &prev_inst);
>          if (s.rc != CMPI_RC_OK || prev_inst == NULL) {
>                  cu_statusf(_BROKER, &s,
> @@ -1256,8 +1459,27 @@ static CMPIStatus state_change(CMPIMethodMI *self,
> 
>          s = __state_change(name, state, reference);
> 
> -        if (s.rc == CMPI_RC_OK)
> +        if (s.rc == CMPI_RC_OK) {
>                  rc = 0;
> +                goto out;
> +        }
> +
> +        if (s.rc == CIM_SVPC_RETURN_JOB_STARTED) {
> +                state_change_job_t *job = NULL;
> +                s = create_state_change_job(reference, context, &job, state);
> +                if (s.rc != CMPI_RC_OK) {
> +                        free(job);
> +                        goto out;
> +                }
> +
> +                job->dom_name = strdup(name);
> +
> +                _BROKER->xft->newThread(state_change_thread, job, 0);
> +
> +                CMAddArg(argsout, "Job", (CMPIValue *)&(job->obj_path),
> +                         CMPI_ref);
> +                rc = s.rc;
> +        }
> 
>   out:
>          CMReturnData(results, &rc, CMPI_uint32);





More information about the Libvirt-cim mailing list