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