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