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