/*****************************************************************************
 * Function to cleanup the resource
 *
 * @param - provider_resource to be freed
 * @return CMPIrc error codes
****************************************************************************/
static CMPIrc xen_resource_record_cleanup(
    provider_resource *prov_res
    )
{
    local_host_resource *ctx = prov_res->ctx;
    if (ctx) {
        if (ctx->host_rec)
            xen_host_record_free(ctx->host_rec);
        if (ctx->host)
            xen_host_free(ctx->host);
        free(ctx);
    }
    return CMPI_RC_OK;
}
Exemple #2
0
// automatically generated. Do not modify
static void testHosts(xen_session *session) {
	printf("\nGet all the  Host Records\n");

	xen_host_set *host_set;
	bool d = xen_host_get_all(session, &host_set);
	if (d) {
		size_t i = 0;
		for (; i < host_set->size; ++i) {
			xen_host_record *host_record;
			xen_host_get_record(session, &host_record, host_set->contents[i]);
			char *handle = (char*) host_record->handle;
			char *opaque = (char*) host_set->contents[i];
			if (strcmp(handle, opaque) == 0)
				printf("identical: %s\n", opaque);
			else
				printf("record->handle[%s] v.s. set->contents[%d][%s]\n",
						opaque, i, handle);
			xen_host_record_free(host_record);
		}
	} else {
		print_error(session);
	}

#if 0
	printf("== Get All ============================\n\n");

	xen_host_xen_host_record_map *result;
	bool ok = xen_host_get_all_records(session, &result);
	if(!ok) {
		print_error(session);
	}
	size_t i=0;
	for(;i<result->size;++i) {
		xen_host key = result->contents[i].key;
		struct xen_host_record *val = result->contents[i].val;
		if(strcmp((char*)key, (char*)val->handle)==0) {

		} else {
			printf("%s v.s. %s", (char*)key, (char*)val->handle);
		}
		xen_host_record_free(val);
		xen_host_free(key);
	}
	free(result);
#endif
	xen_host_set_free(host_set);

	printf("\n==============================================\n\n");
}
void
xen_host_xen_host_record_map_free(xen_host_xen_host_record_map *map)
{
    if (map == NULL)
    {
        return;
    }

    size_t n = map->size;
    for (size_t i = 0; i < n; i++)
    {
        xen_host_free(map->contents[i].key);
        xen_host_record_free(map->contents[i].val);
    }

    free(map);
}
Exemple #4
0
static CMPIrc processor_metric_set_properties(
    const CMPIBroker *broker,
    provider_resource *resource, 
    xen_host_record *host_rec,
    CMPIInstance *inst)
{
    char buf[MAX_INSTANCEID_LEN];
    xen_host_cpu_record *cpu_rec = (xen_host_cpu_record *)resource->ctx;
    _CMPICreateNewDeviceInstanceID(buf, MAX_INSTANCEID_LEN, host_rec->uuid, cpu_rec->uuid);
    CMSetProperty(inst, "InstanceID",(CMPIValue *)buf, CMPI_chars);

    // Is this the MetricsDefinitionID or the classname ?
    snprintf(buf, MAX_INSTANCEID_LEN, "%sDef", resource->classname);
    CMSetProperty(inst, "MetricDefinitionId",(CMPIValue *)buf, CMPI_chars);
    //CMSetProperty(inst, "BreakdownDimension",(CMPIValue *)<value>, CMPI_chars);
    //CMSetProperty(inst, "BreakdownValue",(CMPIValue *)<value>, CMPI_chars);
    CMSetProperty(inst, "Caption",(CMPIValue *)"Xen Host Processor Metrics", CMPI_chars);
    //CMPIDateTime *date_time = xen_utils_time_t_to_CMPIDateTime(_BROKER, &<time_value>);
    //CMSetProperty(inst, "Duration",(CMPIValue *)&date_time, CMPI_dateTime);
    //CMSetProperty(inst, "Generation",(CMPIValue *)&<value>, CMPI_uint64);
    CMSetProperty(inst, "ElementName",(CMPIValue *)host_rec->uuid, CMPI_chars);
    CMSetProperty(inst, "MeasuredElementName",(CMPIValue *)host_rec->name_label, CMPI_chars);

    xen_host host = NULL;
    double load_percentage = 0.0;
    xen_host_get_by_uuid(resource->session->xen, &host, host_rec->uuid);
    if(host) {

        snprintf(buf, MAX_INSTANCEID_LEN, "cpu%" PRId64, cpu_rec->number);
        xen_host_query_data_source(resource->session->xen, &load_percentage, host, buf);
        CMSetProperty(inst, "Description",(CMPIValue *)buf, CMPI_chars);
        xen_host_free(host);
    }
    snprintf(buf, MAX_INSTANCEID_LEN, "%f", (load_percentage*100));
    CMSetProperty(inst, "MetricValue",(CMPIValue *)buf, CMPI_chars);

    CMPIDateTime *date_time = xen_utils_CMPIDateTime_now(broker);
    CMSetProperty(inst, "TimeStamp",(CMPIValue *)&date_time, CMPI_dateTime);
    bool vol=true;
    CMSetProperty(inst, "Volatile",(CMPIValue *)&vol, CMPI_boolean);
    return CMPI_RC_OK;
}
Exemple #5
0
int main(int argc, char **argv)
{

    if (argc != 5)
    {
        usage();
    }

    url = argv[1];
    char *sr_name = argv[2];
    char *username = argv[3];
    char *password = argv[4];

    xmlInitParser();
    xmlKeepBlanksDefault(0);
    xen_init();
    curl_global_init(CURL_GLOBAL_ALL);

#define CLEANUP                                 \
    do {                                        \
        xen_session_logout(session);            \
        curl_global_cleanup();                  \
        xen_fini();                             \
        xmlCleanupParser();                     \
    } while(0)                                  \

    
    xen_session *session =
        xen_session_login_with_password(call_func, NULL, username, password,
                                        xen_api_latest_version);

    /* ---------------------------------------------------------------------
       Read host, capabilities and API vsn
       --------------------------------------------------------------------- */

    printf("\n\nQuerying host...\n");

    xen_host host;
    if (!xen_session_get_this_host(session, &host, session))
    {
        print_error(session);
        CLEANUP;
        return 1;
    }

    xen_string_string_map *versions;
    if (!xen_host_get_software_version(session, &versions, host))
    {
        print_error(session);
        xen_host_free(host);
        CLEANUP;
        return 1;
    }

    xen_string_set *supported_bootloaders;
    if (!xen_host_get_supported_bootloaders(session, &supported_bootloaders,
                                            host))
    {
        print_error(session);
        xen_string_string_map_free(versions);
        xen_host_free(host);
        CLEANUP;
        return 1;
    }

    xen_string_set *capabilities;
    if (!xen_host_get_capabilities(session, &capabilities, host))
    {
        print_error(session);
        xen_string_set_free(supported_bootloaders);
        xen_string_string_map_free(versions);
        xen_host_free(host);
        CLEANUP;
        return 1;
    }


    for (size_t i = 0; i < versions->size; i++)
    {
        printf("%s -> %s.\n", versions->contents[i].key,
               versions->contents[i].val);
    }

    printf("Host supports the following bootloaders:");
    for (size_t i = 0; i < supported_bootloaders->size; i++)
    {
        printf(" %s", supported_bootloaders->contents[i]);
    }
    printf("\n");

    printf("Host has the following capabilities:");
    for (size_t i = 0; i < capabilities->size; i++)
    {
        printf(" %s", capabilities->contents[i]);
    }
    printf("\n");

    xen_host_free(host);
    xen_string_string_map_free(versions);
    xen_string_set_free(supported_bootloaders);
    xen_string_set_free(capabilities);

    /* ---------------------------------------------------------------------
       Create a new VM with a blank disk:
       --------------------------------------------------------------------- */

    printf("\n\nCreating new HVM VM...\n");
    xen_vm hvm_vm = create_new_vm(session, "Other install media", sr_name, false);
    if (!session->ok)
    {
        /* Error has been logged, just clean up. */
        CLEANUP;
        return 1;
    }

    print_vm_power_state(session, hvm_vm);

    /* Blob handling used to crash when we tried to free the VM record:
     * CA-38872. */
    xen_blob blob;
    xen_blob_create(session, &blob, "hello", false);
    xen_vm_create_new_blob(session, &blob, hvm_vm, "test", "test", false);
    printf("\nBlob created.\n");
    xen_blob_record *blob_record;
    xen_blob_get_record(session, &blob_record, blob);
    printf("Blob record retrieved.\n");

    printf("\nGetting VM record...\n");
    xen_vm_record *vm_record;
    xen_vm_get_record(session, &vm_record, hvm_vm);
    printf("VM record: %s blob: %s\n",
           (char *)vm_record->handle,
           (char *)blob_record->handle);
    printf("Freeing VM record...\n");
    xen_vm_record_free(vm_record);
    printf("VM record freed.\n");
    printf("Freeing blob record...\n");
    xen_blob_record_free(blob_record);
    printf("Blob record freed.\n");
    
    if (!session->ok)
    {
        /* Error has been logged, just clean up. */
        xen_vm_free(hvm_vm);
        CLEANUP;
        return 1;
    }

    /*
       Test Enum parsing by setting actions after shutdown
     */

    xen_vm_set_actions_after_shutdown(session, hvm_vm, XEN_ON_NORMAL_EXIT_RESTART);

    /*
      Test getting a map and having a play
     */
    xen_string_string_map *hvm_boot_params;

    if (!xen_vm_get_hvm_boot_params(session, &hvm_boot_params, hvm_vm))
    {
        print_error(session);
        CLEANUP;
        return 1;
    }

    printf("HVM_boot_params contains:\n");

    for (size_t i = 0; i < hvm_boot_params->size; i++)
    {
        printf("%s -> %s.\n", hvm_boot_params->contents[i].key,
               hvm_boot_params->contents[i].val);
    }

    xen_string_string_map_free(hvm_boot_params);

    cycle_vm(session, hvm_vm);

    xen_vm_free(hvm_vm);

    /* TODO uncomment this when we test against real
            hosts, as SDK doesn't have debian template
    
    printf("\n\nCreating new PV VM...\n");
    xen_vm pv_vm = create_new_vm(session, "Debian Etch 4.0", sr_name, true);
    if (!session->ok)
    {
        CLEANUP;
        return 1;
    }

    if (!xen_vm_get_hvm_boot_params(session, &hvm_boot_params, pv_vm))
    {
        print_error(session);
        CLEANUP;
        return 1;
    }

    for (size_t i = 0; i < hvm_boot_params->size; i++)
    {
        printf("%s -> %s.\n", hvm_boot_params->contents[i].key,
               hvm_boot_params->contents[i].val);
    }

    cycle_vm(session, pv_vm);

    xen_vm_free(pv_vm);
    */

    CLEANUP;
}
/*
 * Async job worker that gets called on a separate thread (see Xen_Job.c)
*/
static void migrate_task(void *async_job)
{
    /* Perform the migration */
    Xen_job *job = (Xen_job *)async_job;
    xen_utils_session *session = job->session;
    int state = JobState_Exception;
    CMPIrc statusrc = CMPI_RC_ERR_FAILED;
    char *job_status_description = "ERROR: Migrate VM failed with unknown error";
    char *xen_error = NULL;
    migrate_job_context *job_context = (migrate_job_context *)job->job_context;
    bool kvpNeedsReenabling=false;
    bool error=false;
    char *uuid=NULL;
    xen_string_string_map *other_config=NULL;

    _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_INFO, ("Migration job started"));

    state = JobState_Running;
    job_change_state(job, session, state, 0, 0, STATE_MIGRATE_STARTED);
    sleep(1);

    if(!error && !xen_vm_get_uuid(session->xen, &uuid, job_context->vm)) {
        _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_ERROR, ("Could not get the UUID of the vm."));
        error=true;
    }

    if(!error && !xen_vm_get_other_config(session->xen, &other_config, job_context->vm)) {
        _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_ERROR, ("Could not get other_config of the VM"));
        error=true;
    }

    if(!error && xen_utils_get_from_string_string_map(other_config, "kvp_enabled")) {
        _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_INFO, ("KVP is enabled, disabling it to allow migration"));
        kvpNeedsReenabling=true;
        if(xen_utils_preparemigration_kvp_channel(session, uuid) != Xen_KVP_RC_OK) {
            error=true;
            _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_ERROR, ("Could not prepare KVP for migration"));
        }
    }

    if(!error) {
        _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_INFO, ("Doing the migration"));
        xen_string_string_map *options = xen_string_string_map_alloc(0);
        if(!xen_vm_pool_migrate(session->xen, job_context->vm, job_context->host, options)) {
            _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_ERROR, ("Could not do the migration"));
            error=true;
        }
        xen_string_string_map_free(options);
    }

    if(!error) {
        state = JobState_Completed;
        statusrc = CMPI_RC_OK;
        job_status_description = "Completed Successfully";
    }
    else {
        state = JobState_Exception;
        statusrc = CMPI_RC_ERR_FAILED;
        xen_error = xen_utils_get_xen_error(session->xen);
        job_status_description = xen_error;
    }

    // The reenabling of KVM is always done,  it is not depending on whether the migration was succesfull / an error occured
    if(kvpNeedsReenabling) {
        _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_INFO, ("Reenabling KVP"));
        if (xen_utils_finishmigration_kvp_channel(session, uuid) != Xen_KVP_RC_OK) {
            _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_ERROR, ("Could not reenable KVP"));
			state = JobState_Exception;
			statusrc = CMPI_RC_ERR_FAILED;
			job_status_description = "Error: Could not re-enable KVP channel";
        }
    }

    _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_INFO, ("Migration job status %d (%s)", statusrc, job_status_description));
    job_change_state(job, session, state, 100, statusrc, job_status_description);

    if(job_context->vm) 
        xen_vm_free(job_context->vm);
    if(job_context->host)
        xen_host_free(job_context->host);
    free(job_context);
    if(xen_error)
        free(xen_error);
    if(uuid)
        free(uuid);
    if(other_config)
        free(other_config);
}
/******************************************************************************
* checks for migratability or actually does the migration
******************************************************************************/
int MigrateVirtualSystem(
    const CMPIBroker *broker,   /* in - CMPI Broker that does most of the work */
    const CMPIContext *context, /* in - CMPI context for the caller */
    const CMPIArgs *argsin,     /* in - All the arguments for the method */
    const CMPIArgs *argsout,    /* out - All the output arguments for the method */
    xen_utils_session *session, /* in - Session for making xen calls */
    bool host_ip,               /* in - The host parameter is an IP address */
    bool migrate_check_only,    /* in -Check if migration is possible only, dont actually migrate */
    CMPIStatus *status)         /* out - Report CMPI status of method */
{
    char *hostid = NULL, *vm_uuid = NULL;
    CMPIData argdata;
    xen_vm vm = NULL;
    xen_host_set *host_set = NULL;
    CMPIInstance *msd = NULL;
    xen_host host = NULL;
    int rc = Xen_VirtualSystemMigrationService_MigrateVirtualSystemToSystem_Invalid_Parameter;
    CMPIrc statusrc = CMPI_RC_ERR_INVALID_PARAMETER;
    char *error_msg = "ERROR: Unknown error";
    xen_string_string_map *other_config=NULL;

    /* For now only Live migrations are supported */
    if(_GetArgument(broker, argsin, "MigrationSettingData", CMPI_chars, &argdata, status)) {
        /* Argument passed in as a MOF string, parse it */
        msd = xen_utils_parse_embedded_instance(broker, CMGetCharPtr(argdata.value.string));
        if (msd == NULL) { // parser returns zero for success, non-zero for error
            error_msg = "ERROR: Couldnt parse the 'MigrationSettingData' parameter";
            goto Exit;
        }
    }
    else
        /* Argument could have been passed in as an intance */
        if(_GetArgument(broker, argsin, "MigrationSettingData", CMPI_instance, &argdata, status))
            msd = argdata.value.inst;

    if(msd != NULL) {
        CMPIData data = CMGetProperty(msd, "MigrationType", status);
        if(data.value.uint16 != Xen_VirtualSystemMigrationSettingData_MigrationType_Live) {
            error_msg = "ERROR: 'MigrationSettingData' contains an invalid MigrationType (Live expected)";
            goto Exit;
        }
    }

    /* Host to migrate to */
    if(!host_ip) {
        /* required parameters */
        if(!_GetArgument(broker, argsin, "DestinationSystem", CMPI_ref, &argdata, status)){
            error_msg = "ERROR: 'DestionationSystem' parameter is missing";
            goto Exit;
        }
        else {
            /* This is the CIM reference to an existing Host object */
            CMPIData key;
            key = CMGetKey(argdata.value.ref, "Name", status);
            if(status->rc != CMPI_RC_OK || CMIsNullValue(key)) {
                error_msg = "ERROR: 'DestinationSystem' is missing the required 'Name' key";
                goto Exit;
            }
            hostid = CMGetCharPtr(key.value.string);
            if(!xen_host_get_by_uuid(session->xen, &host, hostid)) 
                goto Exit;
        }
    }
    else {
        if(!_GetArgument(broker, argsin, "DestinationHost", CMPI_string, &argdata, status)) {
            error_msg = "ERROR: 'DestinationHost' parameter is missing";
            goto Exit;
        }
        else {
            /* Determing Xen host based on IP address,. Cannot use inet_pton() and so on since DNS may not have been configured properly */
            hostid = CMGetCharPtr(argdata.value.string);
            _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_INFO, ("Trying to migrate to DestinationHost : %s", hostid));
            if(!xen_host_get_all(session->xen, &host_set))
                goto Exit;
            int i=0;
            for (i=0; i<host_set->size; i++) {
                xen_host_record *host_rec = NULL;
                if(!xen_host_get_record(session->xen, &host_rec, host_set->contents[i]))
                    goto Exit;
                /* DestinationHost could be an IP address or the hostname */
                if((host_rec->address &&  (strcmp(hostid, host_rec->address) == 0)) || 
                   (host_rec->hostname && (strcmp(hostid, host_rec->hostname) == 0)) ||
                   (host_rec->name_label && (strcmp(hostid, host_rec->name_label) == 0))) { 
                    xen_host_record_free(host_rec);
                    host = host_set->contents[i];
                    host_set->contents[i] = NULL; /* dont free this one */
                    break;
                }
                xen_host_record_free(host_rec);
            }
        }
    }

    /* VM to migrate - required parameter */
    if(!_GetArgument(broker, argsin, "ComputerSystem", CMPI_ref, &argdata, status)) {
        if(!_GetArgument(broker, argsin, "ComputerSystem", CMPI_string, &argdata, status)) {
            error_msg = "ERROR: Missing the required 'ComputerSystem' parameter";
            goto Exit;
        }
        else
            vm_uuid = CMGetCharPtr(argdata.value.string);
    } else {
        argdata = CMGetKey(argdata.value.ref, "Name", status);
        if(status->rc != CMPI_RC_OK || CMIsNullValue(argdata)) {
            error_msg = "ERROR: ComputerSystem is missing the required 'Name' key";
            goto Exit;
        }
        vm_uuid = CMGetCharPtr(argdata.value.string);
    }
    status->rc = CMPI_RC_ERR_FAILED;
    rc = Xen_VirtualSystemMigrationService_MigrateVirtualSystemToSystem_Failed;
    if(xen_vm_get_by_uuid(session->xen, &vm, vm_uuid)) {
        _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_ERROR, ("Migrating %s to %s", vm_uuid, hostid));
        if(migrate_check_only) {
            /* Check to see if migration is possible */
            statusrc = CMPI_RC_OK;
            rc = Xen_VirtualSystemMigrationService_MigrateVirtualSystemToSystem_Completed_with_No_Error;
            bool migratable = xen_vm_assert_can_boot_here(session->xen, vm, host);
            if(migratable == false || !session->xen->ok) {
                migratable = false;

                // Workaround for kvp migration
                if(session->xen->error_description_count==1) {
                    if(xen_vm_get_other_config(session->xen, &other_config, vm)) {
                         if(xen_utils_get_from_string_string_map(other_config, "kvp_enabled")) {
                            _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_INFO, ("Overwriting migratable to mark kvp vm as migratable, although its network"));
                            migratable=true;
                            RESET_XEN_ERROR(session->xen);
                         }
                         free(other_config);
                    } else {
                       _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_ERROR, ("Could not get other config."));
                    }
                }

                if(migratable == false && session->xen->error_description) {
                    /* This is not part of the MOF (and is not documented), but nice to have */
                    char *xen_error = xen_utils_get_xen_error(session->xen);
                    CMAddArg(argsout, "Reason", (CMPIValue *)xen_error, CMPI_chars);
                    free(xen_error);
                }
            }
            CMAddArg(argsout, "IsMigratable", (CMPIValue *)&migratable, CMPI_boolean);
        }
        else {
            /* Do the actual migration, this could take a few minutes */
            CMPIObjectPath* job_instance_op = NULL;
            migrate_job_context *job_context = calloc(1, sizeof(migrate_job_context));
            if(!job_context) {
                error_msg = "ERROR: Couldn't allocate memory for the migrate job.";
                goto Exit;
            }
            job_context->vm = vm;
            job_context->host = host;
            if(!job_create(broker, context, session, MIGRATE_VM_TASK_NAME, vm_uuid, 
                           migrate_task, job_context, &job_instance_op, status)) {
                error_msg = "ERROR: Couldn't prepare the Migrate job. Job wasnt started.";
                goto Exit;
            }
            statusrc = CMPI_RC_OK;
            rc = Xen_VirtualSystemMigrationService_MigrateVirtualSystemToHost_Method_Parameters_Checked___Job_Started;
            CMAddArg(argsout, "Job", (CMPIValue *)&job_instance_op, CMPI_ref);
            vm = NULL;      /* freed by async thread */
            host = NULL;    /* freed by async thread */
        }
    }

Exit:
    if(host)
        xen_host_free(host);
    if(vm)
        xen_vm_free(vm);
    if(host_set)
        xen_host_set_free(host_set);

    xen_utils_set_status(broker, status, statusrc, error_msg, session->xen);
    return rc;
}