Esempio n. 1
0
//!
//! Destroy the backing store for a given instance
//!
//! @param[in] instance the instance identifier for which we will destroy the backing store
//! @param[in] do_destroy_files set to TRUE if we need to destroy the content otherwise set to FALSE.
//!
//! @return EUCA_OK on success
//!
//! @pre The instance parameter must not be NULL and do_destroy_files must be a valid boolean.
//!
//! @note
//!
int destroy_instance_backing(ncInstance * instance, boolean do_destroy_files)
{
    int i = 0;
    int ret = EUCA_OK;
    char path[EUCA_MAX_PATH] = "";
    char work_regex[1024] = "";        // {userId}/{instanceId}/.*
    char scURL[512] = "";

    if (get_localhost_sc_url(scURL) != EUCA_OK || strlen(scURL) == 0) {
        LOGWARN("[%s] could not obtain SC URL (is SC enabled?)\n", instance->instanceId);
        scURL[0] = '\0';
    }
    // find and detach iSCSI targets, if any
    for (i = 0; i < EUCA_MAX_VOLUMES; ++i) {
        ncVolume *volume = &instance->volumes[i];
        if (!is_volume_used(volume))
            continue;

        if (disconnect_ebs_volume
            (scURL, localhost_config.use_ws_sec, localhost_config.ws_sec_policy_file, volume->attachmentToken, volume->connectionString, localhost_config.ip,
             localhost_config.iqn) != 0) {
            LOGERROR("[%s][%s] failed to disconnect volume\n", instance->instanceId, volume->volumeId);
        }
    }

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

    if (do_destroy_files) {
        set_id2(instance, "/.*", work_regex, sizeof(work_regex));

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

        for (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);
        }

        // delete all non-blob files in the directory
        if (blobstore_delete_nonblobs(work_bs, instance->instancePath) < 0) {
            LOGERROR("[%s] failed to delete some non-blob files under %s\n", instance->instanceId, instance->instancePath);
        }
    }
    // 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) {
        LOGERROR("[%s] failed to remove backing directory %s\n", instance->instanceId, path);
    }

    return (ret);
}
//!
//! Destroy the backing store for a given instance
//!
//! @param[in] instance the instance identifier for which we will destroy the backing store
//! @param[in] do_destroy_files set to TRUE if we need to destroy the content otherwise set to FALSE.
//!
//! @return EUCA_OK on success
//!
//! @pre The instance parameter must not be NULL and do_destroy_files must be a valid boolean.
//!
//! @note
//!
int destroy_instance_backing(ncInstance * instance, boolean do_destroy_files)
{
    int i = 0;
    int ret = EUCA_OK;
    char path[EUCA_MAX_PATH] = "";
    char work_regex[1024] = "";        // {userId}/{instanceId}/.*
    char scURL[512] = "";
    ncVolume *volume = NULL;
    virtualMachine *vm = &(instance->params);
    virtualBootRecord *vbr = NULL;

    if (get_localhost_sc_url(scURL) != EUCA_OK || strlen(scURL) == 0) {
        LOGWARN("[%s] could not obtain SC URL (is SC enabled?)\n", instance->instanceId);
        scURL[0] = '\0';
    }
    // find and detach iSCSI targets, if any
    for (i = 0; ((i < EUCA_MAX_VBRS) && (i < vm->virtualBootRecordLen)); i++) {
        vbr = &(vm->virtualBootRecord[i]);
        if (vbr->locationType == NC_LOCATION_SC) {
            if (disconnect_ebs_volume
                (scURL, localhost_config.use_ws_sec, localhost_config.ws_sec_policy_file, vbr->resourceLocation, vbr->preparedResourceLocation, localhost_config.ip,
                 localhost_config.iqn) != 0) {
                LOGERROR("[%s] failed to disconnect volume attached to '%s'\n", instance->instanceId, vbr->backingPath);
            }
        }
    }
    // there may be iSCSI targets for volumes if instance disappeared or was migrated
    for (i = 0; i < EUCA_MAX_VOLUMES; ++i) {
        ncVolume *volume = &instance->volumes[i];
        if (!is_volume_used(volume))
            continue;

        if (disconnect_ebs_volume
            (scURL, localhost_config.use_ws_sec, localhost_config.ws_sec_policy_file, volume->attachmentToken, volume->connectionString, localhost_config.ip,
             localhost_config.iqn) != 0) {
            LOGERROR("[%s][%s] failed to disconnect volume\n", instance->instanceId, volume->volumeId);
        }
    }

    // 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)
    {
        DIR *dir = NULL;
        if ((dir = opendir(path)) == NULL) {
            return (-1);
        }

        struct dirent *dir_entry;
        while ((dir_entry = readdir(dir)) != NULL) {
            char *entry_name = dir_entry->d_name;

            if (!strcmp(".", entry_name) || !strcmp("..", entry_name))
                continue;

            // get the path of the directory item
            char entry_path[BLOBSTORE_MAX_PATH];
            snprintf(entry_path, sizeof(entry_path), "%s/%s", path, entry_name);

            if (diskutil_ch(entry_path, EUCALYPTUS_ADMIN, NULL, BACKING_FILE_PERM)) {
                LOGWARN("[%s] failed to chown files before cleanup\n", instance->instanceId);
            }
        }
        closedir(dir);
    }

    if (do_destroy_files) {
        set_id2(instance, "/.*", work_regex, sizeof(work_regex));

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

        for (i = 0; i < EUCA_MAX_VOLUMES; ++i) {
            volume = &instance->volumes[i];
            snprintf(path, sizeof(path), EUCALYPTUS_VOLUME_XML_PATH_FORMAT, instance->instancePath, volume->volumeId);
            unlink(path);
        }

        // delete all non-blob files in the directory
        if (blobstore_delete_nonblobs(work_bs, instance->instancePath) < 0) {
            LOGWARN("[%s] failed to delete some non-blob files under %s\n", instance->instanceId, instance->instancePath);
        }
    }
    // 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) {
        LOGWARN("[%s] failed to remove backing directory %s\n", instance->instanceId, path);
    }

    return (ret);
}
Esempio n. 3
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 Always return 0 or exit(1) on failure
//!
int main(int argc, char **argv)
{
    char *sc_hostport = NULL;
    char *command = NULL;
    char *ip = NULL;
    char *instance_id = NULL;
    char *iqn = NULL;
    int ch = 0;

    log_file_set(NULL, NULL);
    log_params_set(EUCA_LOG_ALL, 0, 1);

    while ((ch = getopt(argc, argv, "hn:h:s:i:")) != -1) {
        switch (ch) {
        case 's':
            sc_hostport = optarg;
            break;
        case 'i':
            instance_id = optarg;
            break;
        case 'h':
            usage();                   // will exit
            break;
        case '?':
        default:
            fprintf(stderr, "ERROR: unknown parameter (try -h)\n");
            exit(1);
        }
    }
    argc -= optind;
    argv += optind;

    if (argc > 0) {
        command = argv[0];
        if (argc > 1) {
            fprintf(stderr, "WARNING: too many parameters (%d), using first one as command\n", argc);
            for (int i = 0; i <= argc; i++) {
                if (argv[i])
                    fprintf(stderr, "%d = %s\n", i, argv[i]);
            }
        }
    } else {
        fprintf(stderr, "ERROR: command not specified (try -h)\n");
        exit(1);
    }

    char configFile[BUFSIZE], policyFile[BUFSIZE];
    char *euca_home;
    char sc_url[BUFSIZE];

    euca_home = getenv("EUCALYPTUS");
    if (!euca_home) {
        euca_home = "";
    }

    snprintf(configFile, BUFSIZE, EUCALYPTUS_CONF_LOCATION, euca_home);
    snprintf(policyFile, BUFSIZE, EUCALYPTUS_POLICIES_DIR "/sc-client-policy.xml", euca_home);
    snprintf(sc_url, BUFSIZE, "http://%s/services/Storage", sc_hostport);

    char *instances_path;
    int rc;

    rc = get_conf_var(configFile, INSTANCE_PATH, &instances_path);

    char *instance_path = find_instance_path(instances_path, instance_id);
    eucaVolume volumes[EUCA_MAX_VOLUMES];
    char instance_xml[BUFSIZE];
    snprintf(instance_xml, BUFSIZE, "%s/instance.xml", instance_path);

    loop_through_volumes(instance_xml, volumes);

    ip = find_ip_addr();
    iqn = find_local_iqn();

    printf("Found local iqn=%s and local ip=%s\n", iqn, ip);

    for(int i = 0; i < EUCA_MAX_VOLUMES; i++){
        if(strlen(volumes[i].state) == 0 || strcmp(volumes[i].state, VOL_STATE_ATTACHED)) continue;

        printf("Performing operation on volume %d\nid=%s\ntoken=%s\ndevice=%s\nconnectionstring=%s\nbus=%s\nserial=%s\n", 
               i, volumes[i].id, volumes[i].attachment_token, volumes[i].device, volumes[i].connection_string, volumes[i].bus, volumes[i].serial);
        /***********************************************************/
        if (!strcmp(command, "ConnectVolumes")) {
            CHECK_PARAM(ip, "ip");
            CHECK_PARAM(iqn, "iqn");
            CHECK_PARAM(sc_hostport, "sc host and port");

            setup_iscsi(euca_home, configFile);
            euca_init_cert();

            char *libvirt_xml = NULL;
            ebs_volume_data *vol_data = NULL;

            if (connect_ebs_volume(volumes[i].id, volumes[i].serial, volumes[i].bus, sc_url, volumes[i].attachment_token, 1, policyFile, ip, iqn, &libvirt_xml, &vol_data) != EUCA_OK) {
                fprintf(stderr, "Error connecting ebs volume %s\n", volumes[i].id);
                exit(1);
            }

            /***********************************************************/
        } else if (!strcmp(command, "DisconnectVolumes")) {
            CHECK_PARAM(ip, "ip");
            CHECK_PARAM(iqn, "iqn");
            CHECK_PARAM(sc_hostport, "sc host and port");

            setup_iscsi(euca_home, configFile);
            euca_init_cert();

            if (disconnect_ebs_volume(sc_url, 1, policyFile, volumes[i].attachment_token, volumes[i].connection_string, ip, iqn) != EUCA_OK) {
                fprintf(stderr, "Error disconnecting ebs volume %s.\n", volumes[i].id);
                exit(1);
            }

            /***********************************************************/
        } else {
            fprintf(stderr, "ERROR: command %s unknown (try -h)\n", command);
            exit(1);
        }
    }

    _exit(0);
}