Dan Smith wrote:
+++ b/src/Virt_VirtualSystemSnapshotService.c Tue Feb 26 11:19:56
2008 -0800
@@ -0,0 +1,521 @@
+/*
+ * Copyright IBM Corp. 2007
2008 ;)
+static void do_snapshot(struct snap_context *ctx,
+ virConnectPtr conn,
+ virDomainPtr dom)
+{
+ ...
+ if (ctx->restore) {
+ CU_DEBUG("Starting restore from %s", ctx->save_path);
+
+ ret = virDomainRestore(conn, ctx->save_path);
+ if (ret == -1) {
+ CU_DEBUG("Restore failed");
+ snap_job_set_status(ctx,
+ CIM_JOBSTATE_COMPLETE,
+ "Snapshot Failed (restore)");
+ return;
+ }
+
+ CU_DEBUG("Restore completed");
+ snap_job_set_status(ctx,
+ CIM_JOBSTATE_RUNNING,
+ "Restore finished");
Please can you explain why you set the status here and overwrite it
right afterwards ? I think the CIM_JOBSTATE is already COMPLETE here.
+ }
+
+ CU_DEBUG("Snapshot (%s/%s) completed",
+ ctx->save ? "Save" : "None",
+ ctx->restore ? "Restore" : "None");
+
+ snap_job_set_status(ctx,
+ CIM_JOBSTATE_COMPLETE,
+ "Snapshot complete");
+
+ return;
+}
+
+static CMPI_THREAD_RETURN snapshot_thread(struct snap_context *ctx)
+{...
+ conn = connect_by_classname(_BROKER, ctx->ref_cn, &s);
+ if (conn == NULL) {
+ CU_DEBUG("Failed to connect with classname `%s'",
ctx->ref_cn);
+ snap_job_set_status(ctx,
+ CIM_JOBSTATE_COMPLETE,
+ "Unable to connect to hypervisor");
+ goto out;
+ }
+
+ dom = virDomainLookupByName(conn, ctx->domain);
+ if (dom == NULL) {
+ CU_DEBUG("No such domain `%s'", ctx->domain);
+ snap_job_set_status(ctx,
+ CIM_JOBSTATE_COMPLETE,
+ "No such domain");
+ goto out;
+ }
+
+ do_snapshot(ctx, conn, dom);
+
+ out:
FYI - I encountered some problems with another provider, where I tried
virDomainFree() with a not initialized dom. This could also happen here
with the goto out from conn. Maybe virDomainFree() can not handle NULL ?
+ virDomainFree(dom);
+ virConnectClose(conn);
+
+ snap_job_free(ctx);
+
+ return NULL;
+}
+
+static CMPIStatus create_job(const CMPIContext *context,
+ const CMPIObjectPath *ref,
+ struct snap_context *ctx,
+ CMPIObjectPath **job)
+{
+ CMPIObjectPath *op;
+ CMPIInstance *inst;
+ CMPIStatus s;
+
+ op = CMNewObjectPath(_BROKER,
+ NAMESPACE(ref),
+ "CIM_ConcreteJob", /*FIXME*/
+ &s);
+ if ((s.rc != CMPI_RC_OK) || (op == NULL)) {
+ CU_DEBUG("Failed to create job path");
+ goto out;
+ }
+
+ CMSetNameSpace(op, NAMESPACE(ref));
This step is not necessary as NewObjectPath already sets the namespace.
+
+ inst = CMNewInstance(_BROKER, op, &s);
+ if ((s.rc != CMPI_RC_OK) || (inst == NULL)) {
+ CU_DEBUG("Failed to create job instance");
+ goto out;
+ }
+
+ CMSetProperty(inst, "InstanceID",
+ (CMPIValue *)ctx->uuid, CMPI_chars);
+
+ CMSetProperty(inst, "Name",
+ (CMPIValue *)"Snapshot", CMPI_chars);
+
+ CMSetProperty(inst, "Status",
+ (CMPIValue *)"Queued", CMPI_chars);
+
+ op = CMGetObjectPath(inst, &s);
+ if ((op == NULL) || (s.rc != CMPI_RC_OK)) {
+ CU_DEBUG("Failed to get path of job instance");
+ goto out;
+ }
+
+ CMSetNameSpace(op, NAMESPACE(ref));
This should also be not necessary. But as you debug the ref right
afterwards ... did you encounter some problems here ?
+
+ CU_DEBUG("ref was %s", CMGetCharPtr(CMObjectPathToString(op, NULL)));
+
+ *job = CBCreateInstance(_BROKER, context, op, inst, &s);
+ if ((*job == NULL) || (s.rc != CMPI_RC_OK)) {
+ CU_DEBUG("Failed to create job");
+ goto out;
+ }
+
+ ctx->ref_ns = strdup(NAMESPACE(ref));
+ ctx->ref_cn = strdup(CLASSNAME(ref));
+
+ ctx->context = CBPrepareAttachThread(_BROKER, context);
+
+ _BROKER->xft->newThread((void *)snapshot_thread, ctx, 0);
+
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_OK,
+ "");
Its more my personal view, but as you "goto out" each time the status
is
something else than CMPI_RC_OK, it should still be CMPI_RC_OK at this
point, if you initialize it right at the beginning of the function with
CMPIStatus s = {CMPI_RC_OK, NULL}; .
+ out:
+ return s;
+}
+
+char *vsss_get_save_path(const char *domname)
+{
+ int ret;
+ char *path = NULL;
You could use a CMPIString and return its char* to the caller. This
avoids missing frees.
+
+ ret = asprintf(&path,
+ "/var/lib/libvirt/%s.save", domname);
+ if (ret == -1)
+ return NULL;
+
+ return path;
+}
+ ...
+
+
+static CMPIStatus create_snapshot(CMPIMethodMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const CMPIArgs *argsin,
+ CMPIArgs *argsout)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIObjectPath *system;
+ CMPIInstance *sd;
+ uint16_t type;
+ uint32_t retcode = 0;
+ const char *name;
+
+ if (cu_get_u16_arg(argsin, "SnapshotType", &type) != CMPI_RC_OK)
{
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_INVALID_PARAMETER,
+ "Missing SnapshotType");
+ goto out;
+ }
+ ...
+
+ s = start_snapshot_job(reference, context, name, type);
+
+ CMReturnData(results, (CMPIValue *)&retcode, CMPI_uint32);
+ out:
+ CU_DEBUG("Returning: %i", s.rc);
You also need to do a CMReturnData for a failed request.
+ return s;
+}
+
+static CMPIStatus destroy_snapshot(CMPIMethodMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const CMPIArgs *argsin,
+ CMPIArgs *argsout)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIObjectPath *snap;
+ char *name = NULL;
+ char *path = NULL;
+ ...
+ out:
+ free(path);
+ free(name);
You need to return the uint32 status of this method. The same
for
apply_snapshot().
+ return s;
+}
+ ...
+
+STDIM_MethodMIStub(, Virt_VirtualSystemSnapshotService,
+ _BROKER, libvirt_cim_init(), handlers);
I miss the instance provider interface. Do you plan to add this ?
--
Regards
Heidi Eckhart
Software Engineer
IBM Linux Technology Center - Open Hypervisor