/***************************************************************************** * 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; }
// 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); }
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; }
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; }