示例#1
0
//!
//! Refactored logic for detaching a local iSCSI device and unexporting the volume. To be invoked only by other functions in this file after acquiring the necessary lock.
//!
//! @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] vol_data - The ebs_volume_data struct pointer
//! @param[in] connect_string - The connection string to use for local connection
//! @param[in] local_ip - The local host's external IP
//! @param[in] local_iqn - The local host's IQN
//! @param[in] do_rescan - Set to false to indicate no rescan should be done on disconnect, or true to use rescan
//!
//! @return EUCA_OK on success, EUCA_ERROR on failure
//!
//! @pre
//!
//! @post
//!
//! @note should be invoked only by functions in this file that acquired the necessary lock.
//!
static int cleanup_volume_attachment(char *sc_url, int use_ws_sec, char *ws_sec_policy_file, ebs_volume_data * vol_data, char *connect_string, char *local_ip, char *local_iqn,
                                     int do_rescan)
{
    int rc = 0;
    char *reencrypted_token = NULL;
    char *refreshedDev = NULL;

    if (vol_data == NULL || connect_string == NULL || local_ip == NULL || local_iqn == NULL) {
        LOGERROR("Cannot cleanup volume attachment. Got NULL input parameters.\n");
        return EUCA_ERROR;
    }

    LOGDEBUG("[%s] attempting to disconnect iscsi target\n", vol_data->volumeId);
    if (disconnect_iscsi_target(connect_string, do_rescan) != 0) {
        LOGERROR("[%s] failed to disconnect iscsi target\n", vol_data->volumeId);
        LOGDEBUG("Skipping SC Call due to previous errors\n");
        return EUCA_ERROR;
    }

    if (sc_url == NULL || strlen(sc_url) <= 0) {
        LOGERROR("[%s] Cannot invoke SC UnexportVolume, SC URL is invalid\n", vol_data->volumeId);
        return EUCA_ERROR;
    }

    rc = re_encrypt_token(vol_data->token, &reencrypted_token);
    if (rc != 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;
    } else {
        LOGTRACE("Re-encrypted token for %s is %s\n", vol_data->volumeId, reencrypted_token);
    }

    threadCorrelationId* corr_id = get_corrid();
    LOGTRACE("Calling scClientCall with url: %s and token %s\n", sc_url, vol_data->token);
    if (scClientCall( corr_id == NULL ? NULL : corr_id->correlation_id, NULL, use_ws_sec, ws_sec_policy_file, request_timeout_sec, sc_url, "UnexportVolume", vol_data->volumeId, reencrypted_token, local_ip, local_iqn) !=
        EUCA_OK) {
        EUCA_FREE(reencrypted_token);
        LOGERROR("ERROR unexporting volume %s\n", vol_data->volumeId);
        return EUCA_ERROR;
    } else {
        EUCA_FREE(reencrypted_token);
        //Ok, now refresh local session to be sure it's gone.
        //Should return error of not found.
        refreshedDev = get_iscsi_target(connect_string);
        if (refreshedDev) {
            //Failure, should have NULL.
            return EUCA_ERROR;
        } else {
            //We're good
            return EUCA_OK;
        }
    }
}
示例#2
0
int destroy_instance_backing (ncInstance * instance, int do_destroy_files)
{
    int ret = OK;
    int total_prereqs = 0;
    char path [MAX_PATH];
    virtualMachine * vm = &(instance->params);
    
    // find and detach iSCSI targets, if any
    for (int i=0; i<EUCA_MAX_VBRS && i<vm->virtualBootRecordLen; i++) {
        virtualBootRecord * vbr = &(vm->virtualBootRecord[i]);
        if (vbr->locationType==NC_LOCATION_IQN) {
            if (disconnect_iscsi_target (vbr->resourceLocation)) {
                logprintfl(EUCAERROR, "[%s] error: failed to disconnect iSCSI target attached to %s\n", instance->instanceId, vbr->backingPath);
            } 
        }
    }

    // see if instance directory is there (sometimes startup fails before it is created)
    set_path (path, sizeof (path), instance, NULL);
    if (check_path (path))
        return ret;

    // to ensure that we are able to delete all blobs, we chown files back to 'eucalyptus'
    // (e.g., libvirt on KVM on Maverick chowns them to libvirt-qemu while
    // VM is running and then chowns them to root after termination)
    set_path (path, sizeof (path), instance, "*");
    if (diskutil_ch (path, EUCALYPTUS_ADMIN, NULL, BACKING_FILE_PERM)) {
        logprintfl (EUCAWARN, "[%s] error: failed to chown files before cleanup\n", instance->instanceId);
    }

    if (do_destroy_files) {
        char work_regex [1024]; // {userId}/{instanceId}/.*
        set_id2 (instance, "/.*", work_regex, sizeof (work_regex));

        if (blobstore_delete_regex (work_bs, work_regex) == -1) {
            logprintfl (EUCAERROR, "[%s] error: failed to remove some artifacts in %s\n", instance->instanceId, path);
        }

        // remove the known leftover files
        unlink (instance->xmlFilePath);
        unlink (instance->libvirtFilePath);
        unlink (instance->consoleFilePath);
        if (strlen (instance->floppyFilePath)) {
            unlink (instance->floppyFilePath);
        }
        set_path (path, sizeof (path), instance, "instance.checkpoint");
        unlink (path);
        for (int i=0; i < EUCA_MAX_VOLUMES; ++i) {
            ncVolume * volume = &instance->volumes[i];
            snprintf (path, sizeof (path), EUCALYPTUS_VOLUME_XML_PATH_FORMAT, instance->instancePath, volume->volumeId);
            unlink (path);
        }
        // bundle instance will leave additional files
        // let's delete every file in the directory
        struct dirent **files;
        int n = scandir(instance->instancePath, &files, 0, alphasort);
        char toDelete[MAX_PATH];
        if (n>0){
            while (n--) {
               struct dirent *entry = files[n];
               if( entry !=NULL && strncmp(entry->d_name, ".",1)!=0 && strncmp(entry->d_name, "..", 2)!=0){
                    snprintf(toDelete, MAX_PATH, "%s/%s", instance->instancePath, entry->d_name);
                    unlink(toDelete);
                    free(entry);
               }
            }
            free(files);
        }
    }
   
    // Finally try to remove the directory.
    // If either the user or our code introduced
    // any new files, this last step will fail.
    set_path (path, sizeof (path), instance, NULL);
    if (rmdir (path) && do_destroy_files) {
        logprintfl (EUCAWARN, "[%s] warning: failed to remove backing directory %s\n", instance->instanceId, path);
    }
    
    return ret;
}