Пример #1
0
//!
//! Main entry point of the application
//!
//! @param[in] argc the number of parameter passed on the command line
//! @param[in] argv the list of arguments
//!
//! @return EUCA_OK on success or EUCA_ERROR on failure.
//!
int main(int argc, char **argv)
{
    //char *sc_url_prefix = "sc://";
    //char *sc_ur1 = "http://192.168.1.1:8773/services/Storage";
    //char *sc_ur1_slash = "http://192.168.1.1:8773/services/Storage/";

    //char *sc_hostname_url = "http://testhost.com:8773/services/Storage";
    //char *sc_hostname_ur1_slash = "http://testhost.com:8773/services/Storage/";

    char *serialized1 = "sc://vol-123ABCD,10aavaeosvas-sd-adsf-asdfa-vasdva";
    char *serialized2 = "sc://vol-123ABCD,10aavaeosvas-sd-adsf-asdfa-vasdva";

    ebs_volume_data test_struct1 = { "testtoken123", "vol-AB123DD" };
    ebs_volume_data test_struct2 = { "1aoivlna-adflnew-aavaa0an12zc", "vol-123ABCD" };

    char *output = NULL;
    ebs_volume_data *ebs_out = NULL;
    int result;

    printf("Testing serialization\n");
    result = serialize_volume(&test_struct1, &output);
    printf("Got serialized output: %s\n", output);
    EUCA_FREE(output);

    result = serialize_volume(&test_struct2, &output);
    printf("Got serialized output: %s\n", output);
    EUCA_FREE(output);

    printf("Testing de-serialization\n");
    result = deserialize_volume(serialized1, &ebs_out);
    printf("Input %s\n\tGot de-serialized: %s %s\n", serialized1, ebs_out->volumeId, ebs_out->token);
    EUCA_FREE(ebs_out);

    result = deserialize_volume(serialized2, &ebs_out);
    printf("Input %s\n\tGot de-serialized: %s %s\n", serialized2, ebs_out->volumeId, ebs_out->token);
    EUCA_FREE(ebs_out);

    //int replace_sc_url(const char * volume_string, const char * scUrl, char * restrict dest_string)
    /*printf("Testing url replacement\n");
       char url_out1[512];
       result = replace_sc_url(serialized1, "http://localhost.com:8773/services/Storage", url_out1);
       printf("Result string %s\n", url_out1);

       char url_out2[512];
       result = replace_sc_url(serialized2, "http://192.168.1.1:8773/services/Storage/", url_out2);
       printf("Result string %s\n", url_out2);

       char url_out3[512];
       result = replace_sc_url(serialized3, "http://localhost.com:8773/services/Storage", url_out3);
       printf("Result string %s\n", url_out3); */

    return (0);
}
Пример #2
0
//!
//! Detach a local device that is iSCSI and disconnect the session.
//!
//! @param[in] sc_url - The URL to reach the cluster's SC at.
//! @param[in] use_ws_sec - boolean to determine use of WS-SEC.
//! @param[in] ws_sec_policy_file - Policy file path for WS-SEC
//! @param[in] attachment_token - The volume/token string received in the request that will be used
//! @param[in] connect_string - The connect string used for attachment, to be re-used on disconnect
//! @param[in] local_ip - The local host's external IP
//! @param[in] local_iqn - The local host's IQN
//!
//! @return
//!
//! @pre
//!
//! @post
//!
//! @note should only be invoked after detachment from the guest
//!
int disconnect_ebs_volume(char *sc_url, int use_ws_sec, char *ws_sec_policy_file, char *attachment_token, char *connect_string, char *local_ip, char *local_iqn)
{
    int ret = EUCA_ERROR;
    int norescan = 0;                  //send a 0 to indicate no rescan requested
    ebs_volume_data *vol_data = NULL;

    if (attachment_token == NULL || connect_string == NULL || local_ip == NULL || local_iqn == NULL) {
        LOGERROR("Cannont disconnect ebs volume. Got NULL input parameters.\n");
        return EUCA_ERROR;
    }

    LOGTRACE("Disconnecting an EBS volume\n");

    if (deserialize_volume(attachment_token, &vol_data) != EUCA_OK) {
        LOGERROR("Could not deserialize attachment token string %s\n", attachment_token);
        return EUCA_ERROR;
    }

    LOGTRACE("Requesting volume lock\n");
    sem_p(vol_sem);
    {
        LOGTRACE("Got volume lock\n");
        ret = cleanup_volume_attachment(sc_url, use_ws_sec, ws_sec_policy_file, vol_data, connect_string, local_ip, local_iqn, norescan);
        LOGTRACE("cleanup_volume_attachment returned: %d\n", ret);
        LOGTRACE("Releasing volume lock\n");
    }
    sem_v(vol_sem);
    LOGTRACE("Released volume lock\n");

    EUCA_FREE(vol_data);
    return ret;
}
Пример #3
0
//!
//! Implement the backing store for a given instance
//!
//! @param[in] instance pointer to the instance
//! @param[in] is_migration_dest
//!
//! @return EUCA_OK on success or EUCA_ERROR on failure
//!
//! @pre The instance parameter must not be NULL.
//!
//! @post
//!
int create_instance_backing(ncInstance * instance, boolean is_migration_dest)
{
    int rc = 0;
    int ret = EUCA_ERROR;
    virtualMachine *vm = &(instance->params);
    artifact *sentinel = NULL;
    char work_prefix[1024] = { 0 };    // {userId}/{instanceId}
    char base_path[EUCA_MAX_PATH];
    char user_dir_path[EUCA_MAX_PATH];

    // set various instance-directory-relative paths in the instance struct
    set_instance_paths(instance);

    set_path(base_path, sizeof(base_path), NULL, NULL);
    snprintf(user_dir_path, sizeof(user_dir_path), "%s/%s", base_path, instance->userId);
    // create backing directory
    if ((check_path(user_dir_path) == 1) && (mkdir(user_dir_path, INSTANCE_DIRECTORY_PERM) == -1)) {
        LOGERROR("[%s] could not create backing directory %s\n", instance->instanceId, user_dir_path);
        goto out;
    }
    if (mkdir(instance->instancePath, INSTANCE_DIRECTORY_PERM) == -1) {
        LOGERROR("[%s] could not create backing directory %s\n", instance->instanceId, instance->instancePath);
        goto out;
    }

    if (strstr(instance->platform, "windows")) {
        // generate the floppy file for windows instances
        if (makeWindowsFloppy(nc_state.home, instance->instancePath, instance->keyName, instance->instanceId)) {
            LOGERROR("[%s] could not create windows bootup script floppy\n", instance->instanceId);
            goto out;
        } else {
            set_path(instance->floppyFilePath, sizeof(instance->floppyFilePath), instance, "floppy");
            instance->hasFloppy = TRUE;
        }
    } else if (instance->credential && strlen(instance->credential)) {
        LOGDEBUG("[%s] creating floppy for instance credential\n", instance->instanceId);
        if (make_credential_floppy(nc_state.home, instance->instancePath, instance->credential)) {
            LOGERROR("[%s] could not create credential floppy\n", instance->instanceId);
            goto out;
        } else {
            set_path(instance->floppyFilePath, sizeof(instance->floppyFilePath), instance, "floppy");
            instance->hasFloppy = TRUE;
        }
    } else if(instance->hasFloppy && is_migration_dest) {
        LOGDEBUG("[%s] creating blank instance credential floppy\n", instance->instanceId);
        char dest_path[1024] = "";
        int fd = 0;
        snprintf(dest_path, 1024, "%s/floppy", instance->instancePath);
        if ((fd = open(dest_path, O_CREAT | O_TRUNC | O_RDWR, 0700)) < 0) {
           LOGERROR("[%s] failed to create fake floppy\n", instance->instanceId);
           goto out;
        } else {
           lseek(fd, 1024*2048-1, SEEK_SET);
           write(fd, "\n", 1);
        }
        close(fd);
    } else {
        instance->hasFloppy = FALSE;
    }

    set_id(instance, NULL, work_prefix, sizeof(work_prefix));

    // compute tree of dependencies
    sentinel = vbr_alloc_tree(vm,      // the struct containing the VBR
                              TRUE,    // make working copy of runtime-modifiable files
                              is_migration_dest,    // tree of an instance on the migration destination
                              (instance->do_inject_key) ? (instance->keyName) : (NULL), // the SSH key
                              &(instance->bail_flag),   // flag indicating that provisioning should bail
                              instance->instanceId);    // ID is for logging
    if (sentinel == NULL) {
        LOGERROR("[%s] failed to prepare extended backing for instance\n", instance->instanceId);
        goto out;
    }

    sem_p(disk_sem);
    {
        // download/create/combine the dependencies
        rc = art_implement_tree(sentinel, work_bs, cache_bs, work_prefix, INSTANCE_PREP_TIMEOUT_USEC);
    }
    sem_v(disk_sem);

    if (rc != EUCA_OK) {
        LOGERROR("[%s] failed to implement backing for instance\n", instance->instanceId);
        goto out;
    }
    // copy EBS entries from VBR[] to volumes[]
    for (int i = 0; ((i < EUCA_MAX_VBRS) && (i < instance->params.virtualBootRecordLen)); i++) {
        virtualBootRecord *vbr = &(instance->params.virtualBootRecord[i]);
        if (vbr->locationType == NC_LOCATION_SC) {
            char *volumeId = vbr->id;  // id is 'emi-XXXX', replace it with 'vol-XXXX'
            ebs_volume_data *vol_data = NULL;
            if (deserialize_volume(vbr->resourceLocation, &vol_data) == 0) {
                volumeId = vol_data->volumeId;
            }
            if (save_volume(instance, volumeId, vbr->resourceLocation,  // attachmentToken
                            vbr->preparedResourceLocation,  // connect_string
                            vbr->guestDeviceName, VOL_STATE_ATTACHED, vbr->backingPath) == NULL) {  // the XML
                LOGERROR("[%s] failed to add record for volume %s\n", instance->instanceId, volumeId);
            }
            EUCA_FREE(vol_data);
        }
    }

    if (save_instance_struct(instance)) // update instance checkpoint now that the struct got updated
        goto out;

    ret = EUCA_OK;

out:
    if (sentinel)
        art_free(sentinel);
    return (ret);
}
Пример #4
0
//!
//! Connects an EBS volume to the local host as an ISCSI block device. The resulting device is placed in *result_device
//!
//! @param[in] sc_url - The URL to reach the cluster's SC at.
//! @param[in] attachment_token - The attachment token/volume string received in the attach request (or vbr)
//! @param[in] use_ws_sec - Boolean to use WS-SEC on SC call.
//! @param[in] ws_sec_policy_file - Policy file for WS-SEC on SC call.
//! @param[in] local_ip - External IP of the local host. Will be used to send to SC for authorization
//! @param[in] local_iqn - IQN of local host for sending to SC for authorization.
//! @param[out] result_device - The block device that is the EBS volume connected to local host, will be populated on success.
//! @param[out] vol_data - The populated ebs_volume_data struct that hold volume info (id, connect string, token, etc)
//!
//! @return EUCA_OK on success, EUCA_ERROR on failure.
//!
//! @pre
//!
//! @post
//!
//! @note
//!
int connect_ebs_volume(char *sc_url, char *attachment_token, int use_ws_sec, char *ws_sec_policy_file, char *local_ip, char *local_iqn, char **result_device,
                       ebs_volume_data ** vol_data)
{
    int ret = EUCA_OK;
    char *reencrypted_token = NULL;
    char *connect_string = NULL;
    char *dev = NULL;
    int do_rescan = 1;

    if (sc_url == NULL || strlen(sc_url) == 0 || attachment_token == NULL || local_ip == NULL || local_iqn == NULL) {
        LOGERROR("Cannont connect ebs volume. Got NULL input parameters.\n");
        return EUCA_ERROR;
    }

    if (deserialize_volume(attachment_token, vol_data) != EUCA_OK || *vol_data == NULL) {
        LOGERROR("Failed parsing volume string %s\n", attachment_token);
        ret = EUCA_ERROR;
        return ret;
    }

    if (strlen((*vol_data)->volumeId) == 0 || (*vol_data)->token == NULL || strlen((*vol_data)->token) == 0) {
        LOGERROR("After deserializing volume string, still found null or empty volumeId or token");
        ret = EUCA_ERROR;
        return ret;
    }

    LOGTRACE("Parsed volume info: volumeId=%s, encrypted token=%s\n", (*vol_data)->volumeId, (*vol_data)->token);
    if (re_encrypt_token((*vol_data)->token, &reencrypted_token) != EUCA_OK || reencrypted_token == NULL || strlen(reencrypted_token) <= 0) {
        LOGERROR("Failed on re-encryption of token for call to SC\n");
        if (reencrypted_token != NULL) {
            EUCA_FREE(reencrypted_token);
        }
        return EUCA_ERROR;
    }

    LOGTRACE("Requesting volume lock\n");
    sem_p(vol_sem);                    //Acquire the lock, after this, failure requires 'goto release' for release of lock
    LOGTRACE("Got volume lock\n");

    LOGTRACE("Calling ExportVolume on SC at %s\n", sc_url);
    threadCorrelationId* corr_id = get_corrid();
    if (scClientCall(corr_id!=NULL ? corr_id->correlation_id: NULL, NULL, use_ws_sec, ws_sec_policy_file, request_timeout_sec, sc_url, "ExportVolume", (*vol_data)->volumeId, reencrypted_token, local_ip, local_iqn,
                     &connect_string) != EUCA_OK) {
        LOGERROR("Failed to get connection information for volume %s from storage controller at: %s\n", (*vol_data)->volumeId, sc_url);
        ret = EUCA_ERROR;
        goto release;
    } else {
        if (euca_strncpy((*vol_data)->connect_string, connect_string, EBS_CONNECT_STRING_MAX_LENGTH) == NULL) {
            LOGERROR("Failed to copy connect string from SC response: %s\n", connect_string);
            ret = EUCA_ERROR;
            goto release;
        }
    }

    //copy the connection info from the SC return to the resourceLocation.
    dev = connect_iscsi_target((*vol_data)->connect_string);
    if (!dev || !strstr(dev, "/dev")) {
        LOGERROR("Failed to connect to iSCSI target: %s\n", (*vol_data)->connect_string);
        //disconnect the volume
        if (cleanup_volume_attachment(sc_url, use_ws_sec, ws_sec_policy_file, (*vol_data), (*vol_data)->connect_string, local_ip, local_iqn, do_rescan) != EUCA_OK) {
            LOGTRACE("cleanup_volume_attachment returned failure on cleanup from connection failure\n");
        }
        ret = EUCA_ERROR;
        goto release;
    }

    *result_device = dev;

release:
    LOGTRACE("Releasing volume lock\n");
    sem_v(vol_sem);
    LOGTRACE("Released volume lock\n");

    if (reencrypted_token != NULL) {
        EUCA_FREE(reencrypted_token);
    }

    if (ret != EUCA_OK && (*vol_data) != NULL) {
        //Free the vol data struct too
        EUCA_FREE(*vol_data);
    }

    return ret;
}