/* creates network intereface for VM */ int createVifNetwork (virConnectPtr conn, xen_vm vm, char *device, char *bridge, char *mac) { xen_session *session = ((struct _xenapiPrivate *)(conn->privateData))->session; xen_vm xvm = NULL; char *uuid = NULL; xen_vm_get_uuid(session, &uuid, vm); if (uuid) { if (!xen_vm_get_by_uuid(session, &xvm, uuid)) return -1; VIR_FREE(uuid); } xen_vm_record_opt *vm_opt = xen_vm_record_opt_alloc(); vm_opt->is_record = 0; vm_opt->u.handle = xvm; xen_network_set *net_set = NULL; xen_network_record *net_rec = NULL; int cnt = 0; if (xen_network_get_all(session, &net_set)) { for(cnt = 0; cnt < net_set->size; cnt++) { if (xen_network_get_record(session, &net_rec, net_set->contents[cnt])) { if (STREQ(net_rec->bridge, bridge)) { break; } else { xen_network_record_free(net_rec); } } } } if (cnt < net_set->size && net_rec) { xen_network network = NULL; xen_network_get_by_uuid(session, &network, net_rec->uuid); xen_network_record_opt *network_opt = xen_network_record_opt_alloc(); network_opt->is_record = 0; network_opt->u.handle = network; xen_vif_record *vif_record = xen_vif_record_alloc(); vif_record->mac = mac; vif_record->vm = vm_opt; vif_record->network = network_opt; xen_vif vif = NULL; vif_record->other_config = xen_string_string_map_alloc(0); vif_record->runtime_properties = xen_string_string_map_alloc(0); vif_record->qos_algorithm_params = xen_string_string_map_alloc(0); vif_record->device = strdup(device); xen_vif_create(session, &vif, vif_record); if (!vif) { xen_vif_free(vif); xen_vif_record_free(vif_record); xen_network_record_free(net_rec); xen_network_set_free(net_set); return 0; } xen_vif_record_free(vif_record); xen_network_record_free(net_rec); } if (net_set != NULL) xen_network_set_free(net_set); return -1; }
/****************************************************************************** * 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; }