Esempio n. 1
0
/* 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;
}