diff --git a/include/Image.h b/include/Image.h index 1ff370ea52..b12f7eac9e 100644 --- a/include/Image.h +++ b/include/Image.h @@ -97,16 +97,16 @@ public: { switch (ob) { - case FILE: return "FILE" ; break; - case CD_ROM: return "CDROM" ; break; - case BLOCK: return "BLOCK" ; break; - case RBD: return "RBD" ; break; - case RBD_CDROM: return "RBD_CDROM" ; break; - case GLUSTER: return "GLUSTER" ; break; - case GLUSTER_CDROM: return "GLUSTER_CDROM" ; break; - case SHEEPDOG: return "SHEEPDOG" ; break; - case SHEEPDOG_CDROM: return "SHEEPDOG_CDROM" ; break; - default: return ""; + case FILE: return "FILE" ; break; + case CD_ROM: return "CDROM" ; break; + case BLOCK: return "BLOCK" ; break; + case RBD: return "RBD" ; break; + case RBD_CDROM: return "RBD_CDROM" ; break; + case GLUSTER: return "GLUSTER" ; break; + case GLUSTER_CDROM: return "GLUSTER_CDROM" ; break; + case SHEEPDOG: return "SHEEPDOG" ; break; + case SHEEPDOG_CDROM: return "SHEEPDOG_CDROM" ; break; + default: return ""; } }; @@ -178,7 +178,7 @@ public: * Returns true if the image is persistent * @return true if the image is persistent */ - bool isPersistent() const + bool is_persistent() const { return (persistent_img == 1); }; @@ -348,35 +348,13 @@ public: */ int set_type(string& _type, string& error); - /** - * Check if the image can be used by other users - * @return true if group or others can access the image - */ - bool isPublic() - { - return (group_u == 1 || other_u == 1); - } - /** * Check if the image is used for saving_as a current one * @return true if the image will be used to save an existing image. */ - bool isSaving() + bool is_saving() { - ImageTemplate * it = static_cast(obj_template); - - return it->is_saving(); - } - - /** - * Check if the image is a hot snapshot - * @return true if image is a hot snapshot - */ - bool isHot() - { - ImageTemplate * it = static_cast(obj_template); - - return it->is_saving_hot(); + return (static_cast(obj_template))->is_saving(); } /** diff --git a/include/ImageTemplate.h b/include/ImageTemplate.h index fc117061b3..6391161c67 100644 --- a/include/ImageTemplate.h +++ b/include/ImageTemplate.h @@ -61,43 +61,16 @@ public: bool is_saving() { - string saving; + bool save_as_hot; - get(saving_attribute, saving); + get("SAVE_AS_HOT", save_as_hot); - return (saving.empty() == false); - } - - bool is_saving_hot() - { - string save_as_hot; - - get(saving_hot_attribute, save_as_hot); - - return (save_as_hot.empty() == false); + return save_as_hot; } void set_saving() { - SingleAttribute * attr= new SingleAttribute(saving_attribute, "YES"); - - erase(saving_attribute); - - set(attr); - } - - void set_saving_hot() - { - SingleAttribute * attr = new SingleAttribute(saving_hot_attribute,"YES"); - - erase(saving_hot_attribute); - - set(attr); - } - - void unset_saving() - { - erase(saving_attribute); + replace("SAVE_AS_HOT", "YES"); } private: @@ -105,9 +78,6 @@ private: static vector restricted_attributes; - static string saving_attribute; - static string saving_hot_attribute; - bool has_restricted() { return restricted_attributes.size() > 0; diff --git a/include/LifeCycleManager.h b/include/LifeCycleManager.h index 24d12bf1dd..a98f925986 100644 --- a/include/LifeCycleManager.h +++ b/include/LifeCycleManager.h @@ -75,8 +75,8 @@ public: DETACH_NIC_FAILURE,/**< Sent by the VMM when a detach nic action fails */ CLEANUP_SUCCESS, /**< Sent by the VMM when a cleanup action succeeds */ CLEANUP_FAILURE, /**< Sent by the VMM when a cleanup action fails */ - SAVEAS_HOT_SUCCESS,/**< Sent by the VMM when hot saveas succeeds */ - SAVEAS_HOT_FAILURE,/**< Sent by the VMM when hot saveas fails */ + SAVEAS_SUCCESS, /**< Sent by the VMM when saveas succeeds */ + SAVEAS_FAILURE, /**< Sent by the VMM when saveas fails */ SNAPSHOT_CREATE_SUCCESS, /**< Sent by the VMM on snap. create success */ SNAPSHOT_CREATE_FAILURE, /**< Sent by the VMM on snap. create failure */ SNAPSHOT_REVERT_SUCCESS, /**< Sent by the VMM on snap. revert success */ @@ -252,9 +252,9 @@ private: void detach_failure_action(int vid); - void saveas_hot_success_action(int vid); + void saveas_success_action(int vid); - void saveas_hot_failure_action(int vid); + void saveas_failure_action(int vid); void attach_nic_success_action(int vid); diff --git a/include/RequestManagerVirtualMachine.h b/include/RequestManagerVirtualMachine.h index 9a3eb46f06..44c6b974e6 100644 --- a/include/RequestManagerVirtualMachine.h +++ b/include/RequestManagerVirtualMachine.h @@ -170,32 +170,15 @@ public: /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ -class VirtualMachineSaveDisk : public RequestManagerVirtualMachine +class VirtualMachineDiskSaveas : public RequestManagerVirtualMachine { public: - VirtualMachineSaveDisk(): - RequestManagerVirtualMachine("VirtualMachineSaveDisk", - "Saves a disk from virtual machine as a new image", - "A:siissb"){}; + VirtualMachineDiskSaveas(): + RequestManagerVirtualMachine("VirtualMachineDiskSaveas", + "Save a disk from virtual machine as a new image", + "A:siissi"){}; - ~VirtualMachineSaveDisk(){}; - - void request_execute(xmlrpc_c::paramList const& _paramList, - RequestAttributes& att); -}; - -/* ------------------------------------------------------------------------- */ -/* ------------------------------------------------------------------------- */ - -class VirtualMachineSaveDiskCancel : public RequestManagerVirtualMachine -{ -public: - VirtualMachineSaveDiskCancel(): - RequestManagerVirtualMachine("VirtualMachineSaveDiskCancel", - "Cancels a disk snapshot set by VirtualMachineSaveDisk", - "A:sii"){}; - - ~VirtualMachineSaveDiskCancel(){}; + ~VirtualMachineDiskSaveas(){}; void request_execute(xmlrpc_c::paramList const& _paramList, RequestAttributes& att); diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index 15bb959915..2ca85bfa57 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -1270,82 +1270,56 @@ public: int generate_context(string &files, int &disk_id, string& token_password); // ------------------------------------------------------------------------- - // Datastore related functions + // "Save as" Disk related functions (save_as hot) // ------------------------------------------------------------------------- /** - * Gest the associated image to the given disk_id + * Mark the disk that is going to be "save as" * @param disk_id of the VM - * @param hot is this a save_as hot operation + * @param snap_id of the disk to save, -1 to select the active snapshot * @param err_str describing the error - * @return -1 if the image cannot saveas + * @return -1 if the image cannot saveas or image_id of current disk */ - int get_image_from_disk(int disk_id, bool hot, string& err_str); + int set_saveas_disk(int disk_id, int snap_id, string& err_str); /** - * Sets the corresponding SAVE_AS state. + * Set save attributes for the disk * @param disk_id Index of the disk to save - * @param hot is this a save_as hot operation - * @return 0 if the VM can be saved as + * @param source to save the disk + * @param img_id ID of the image this disk will be saved to */ - int set_saveas_state(int disk_id, bool hot); + int set_saveas_disk(int disk_id, const string& source, int img_id); /** - * Clears the SAVE_AS state, moving the VM to the original state. - * @param disk_id Index of the disk to save - * @param hot is this a save_as hot operation - * @return 0 if the VM was in a SAVE_AS state + * Sets the corresponding state to save the disk. + * @return 0 if the VM can be saved */ - int clear_saveas_state(int disk_id, bool hot); + int set_saveas_state(); /** - * Set the SAVE_AS attribute for the "disk_id"th disk. - * @param disk_id Index of the disk to save - * @param source to save the disk (SAVE_AS_SOURCE) - * @param img_id ID of the image this disk will be saved to (SAVE_AS). + * Clears the save state, moving the VM to the original state. + * @return 0 if the VM was in an saveas state */ - int save_disk(int disk_id, - const string& source, - int img_id); - /** - * Clears the SAVE_AS attribute for the "disk_id"th disk. - * @param disk_id Index of the disk to save - * @return 0 on success, -1 if the disk does not exist - */ - int clear_save_disk(int disk_id); + int clear_saveas_state(); /** - * Returns the image ID to be saved-as. - * @param disk_id Index of the disk to save - * @return The image ID, or -1 if the disk is not going to be saved-as + * Clears the SAVE_AS_* attributes of the disk being saved as + * @return the ID of the image this disk will be saved to or -1 if it + * is not found. */ - int get_save_disk_image(int disk_id); + int clear_saveas_disk(); - /** - * Set the SAVE_AS attribute for the "disk_id"th disk. - * @param disk_id Index of the disk to save - * @param source to save the disk (SAVE_AS_SOURCE) - * @param img_id ID of the image this disk will be saved to (SAVE_AS). - */ - int save_disk_hot(int disk_id, - const string& source, - int img_id); /** * Get the original image id of the disk. It also checks that the disk can * be saved_as. * @param disk_id Index of the disk to save - * @param error_str describes the error + * @param source of the image to save the disk to + * @param image_id of the image to save the disk to + * @param tm_mad in use by the disk + * @param ds_id of the datastore in use by the disk * @return -1 if failure */ - int get_saveas_disk_hot(int& disk_id, string& source, int& image_id); - - /** - * Clears the save_as attributes of the disk being (hot) saved as - * - * @param img_id ID of the image this disk will be saved to. Can be - * -1 if it is not found - * @return 0 if a disk with (HOTPLUG_)SAVE_AS was cleaned - */ - int cancel_saveas_disk(int& image_id); + int get_saveas_disk(int& disk_id, string& source, int& image_id, + string& snap_id, string& tm_mad, string& ds_id); // ------------------------------------------------------------------------ // Authorization related functions diff --git a/include/VirtualMachinePool.h b/include/VirtualMachinePool.h index 5b260a3424..a819020292 100644 --- a/include/VirtualMachinePool.h +++ b/include/VirtualMachinePool.h @@ -344,10 +344,8 @@ public: * Images and updates usage quotas * * @param vid VM id - * @param release_save_as true to release non-persistent images - * in the detach event */ - void delete_attach_disk(int vid, bool release_save_as); + void delete_attach_disk(int vid); /** * Deletes the NIC that was in the process of being attached diff --git a/src/cli/one_helper/onevm_helper.rb b/src/cli/one_helper/onevm_helper.rb index b2d080305b..22e4d6e3da 100644 --- a/src/cli/one_helper/onevm_helper.rb +++ b/src/cli/one_helper/onevm_helper.rb @@ -601,13 +601,8 @@ class OneVMHelper < OpenNebulaHelper::OneHelper d["CLONE"] end - column :"SAVE_AS", "", :size=>7 do |d| - d["SAVE_AS"] || "-" - end - - default :ID, :TARGET, :IMAGE, :TYPE, - :SAVE, :SAVE_AS + :SAVE end.show(vm_disks, {}) while vm.has_elements?("/VM/TEMPLATE/DISK") diff --git a/src/cli/onevm b/src/cli/onevm index 4ae4f74cb6..7a8e380577 100755 --- a/src/cli/onevm +++ b/src/cli/onevm @@ -104,6 +104,14 @@ cmd=CommandParser::CmdParser.new(ARGV) do " the --retry option." } + SNAP={ + :name => "snapshot", + :short => "-s snapshot", + :large => "--snapshot snapshot", + :format => String, + :description => "ID of the Snapshot to save." + } + ######################################################################## # Global Options ######################################################################## @@ -298,29 +306,36 @@ cmd=CommandParser::CmdParser.new(ARGV) do end end - disk_snapshot_desc = <<-EOT.unindent - Sets the specified VM disk to be saved in a new Image. The Image is - created immediately, but the contents are saved only after the VM is - shut down gracefully (i.e., using 'onevm shutdown' and not - 'onevm delete') - - If '--live' is specified, the Image will be saved immediately. + disk_saveas_desc = <<-EOT.unindent + Saves the specified VM disk as a new Image. The Image is + created immediately, and the contents of the VM disk will be saved to + it. States: ANY EOT - command :"disk-snapshot", disk_snapshot_desc, :vmid, :diskid, :img_name, - :options=>[TYPE, OneVMHelper::LIVE] do - disk_id = args[1].to_i - image_name = args[2] - image_type = options[:type] || "" + command :"disk-saveas", disk_saveas_desc, :vmid, :diskid, :img_name, + :options=>[TYPE, SNAP] do - verbose = "disk #{disk_id} prepared to be saved in " << - "the image #{image_name}" + disk_id = args[1].to_i + image_name = args[2] + image_type = options[:type] || "" + snapshot_id = options[:snapshot] + + if snapshot_id.nil? || snapshot_id.empty? + snapshot_id = -1 + + verbose = "disk #{disk_id} prepared to be saved in " << + "the image #{image_name}" + else + snapshot_id = snapshot_id.to_i + + verbose = "disk #{disk_id} snapshot #{snapshot_id} prepared to " << + "be saved in the image #{image_name}" + end helper.perform_action(args[0],options,verbose) do |vm| - res = vm.disk_snapshot(disk_id, image_name, image_type, - options[:live]==true) + res = vm.disk_saveas(disk_id, image_name, image_type, snapshot_id) if !OpenNebula.is_error?(res) puts "Image ID: #{res}" @@ -330,19 +345,6 @@ cmd=CommandParser::CmdParser.new(ARGV) do end end - disk_snapshot_cancel_desc = <<-EOT.unindent - Cancels a deferred disk snapshot that has been set by disk-snapshot. - The target image is also deleted. - - States: ANY - EOT - - command :"disk-snapshot-cancel", disk_snapshot_cancel_desc, :vmid, :diskid do - helper.perform_action(args[0],options,"disk snapshot canceled") do |vm| - vm.disk_snapshot_cancel(args[1].to_i) - end - end - shutdown_desc = <<-EOT.unindent Shuts down the given VM. The VM life cycle will end. diff --git a/src/cloud/ec2/lib/EC2QueryServer.rb b/src/cloud/ec2/lib/EC2QueryServer.rb index c5c5ed0519..37b58bd15a 100644 --- a/src/cloud/ec2/lib/EC2QueryServer.rb +++ b/src/cloud/ec2/lib/EC2QueryServer.rb @@ -218,10 +218,9 @@ class EC2QueryServer < CloudServer return rc end - image_id = vm.disk_snapshot(1, - params["Name"], - OpenNebula::Image::IMAGE_TYPES[0], - true) + image_id = vm.disk_saveas(1, + params["Name"], + OpenNebula::Image::IMAGE_TYPES[0]) # TODO Add AMI Tags # TODO A new persistent image should be created for each instance diff --git a/src/cloud/ec2/lib/ebs.rb b/src/cloud/ec2/lib/ebs.rb index c09e7ccc5c..eff3b3575e 100644 --- a/src/cloud/ec2/lib/ebs.rb +++ b/src/cloud/ec2/lib/ebs.rb @@ -302,10 +302,9 @@ module EBS disk_id = vm["TEMPLATE/DISK[IMAGE_ID=#{image_id}]/DISK_ID"] if !disk_id.nil? - snapshot_id = vm.disk_snapshot(disk_id.to_i, + snapshot_id = vm.disk_saveas(disk_id.to_i, params["Description"]||ImageEC2.generate_uuid, - OpenNebula::Image::IMAGE_TYPES[image["TYPE"].to_i], - true) + OpenNebula::Image::IMAGE_TYPES[image["TYPE"].to_i]) if OpenNebula::is_error?(snapshot_id) return snapshot_id diff --git a/src/image/Image.cc b/src/image/Image.cc index 80f1562490..2ff499e3b1 100644 --- a/src/image/Image.cc +++ b/src/image/Image.cc @@ -183,7 +183,7 @@ int Image::insert(SqlDB *db, string& error_str) erase_template_attribute("PATH", path); erase_template_attribute("SOURCE", source); - if (!isSaving()) //Not a saving image + if (!is_saving()) //Not a saving image { if ( source.empty() && path.empty() ) { @@ -624,9 +624,9 @@ int Image::disk_attribute( VectorAttribute * disk, new_disk_type = RBD_CDROM; break; - case SHEEPDOG: - new_disk_type = SHEEPDOG_CDROM; - break; + case SHEEPDOG: + new_disk_type = SHEEPDOG_CDROM; + break; case GLUSTER: new_disk_type = GLUSTER_CDROM; @@ -730,7 +730,7 @@ ImageTemplate * Image::clone_template(const string& new_name) const tmpl->replace("FSTYPE", fs_type); tmpl->replace("SIZE", size_mb); - if ( isPersistent() ) + if ( is_persistent() ) { tmpl->replace("PERSISTENT", "YES"); } diff --git a/src/image/ImageManagerActions.cc b/src/image/ImageManagerActions.cc index 0fabd69811..6846353ac8 100644 --- a/src/image/ImageManagerActions.cc +++ b/src/image/ImageManagerActions.cc @@ -113,7 +113,7 @@ int ImageManager::acquire_image(int vm_id, Image *img, string& error) case Image::READY: img->inc_running(vm_id); - if ( img->isPersistent() ) + if ( img->is_persistent() ) { img->set_state(Image::USED_PERS); } @@ -160,11 +160,9 @@ int ImageManager::acquire_image(int vm_id, Image *img, string& error) void ImageManager::release_image(int vm_id, int iid, bool failed) { - Image * img; + ostringstream oss; - ostringstream disk_file; - - img = ipool->get(iid,true); + Image * img = ipool->get(iid,true); if ( img == 0 ) { @@ -218,27 +216,10 @@ void ImageManager::release_image(int vm_id, int iid, bool failed) break; case Image::LOCKED: - if ( img->isSaving() ) //SAVE_AS images are LOCKED till released - { - if (failed == true) - { - img->set_state(Image::ERROR); - } - else - { - img->set_state(Image::READY); - } + oss << "Releasing image in wrong state: " + << Image::state_to_str(img->get_state()); - ipool->update(img); - } - else - { - stringstream oss; - oss << "Releasing image in wrong state: " - << Image::state_to_str(img->get_state()); - - NebulaLog::log("ImM", Log::ERROR, oss.str()); - } + NebulaLog::log("ImM", Log::ERROR, oss.str()); img->unlock(); break; @@ -249,7 +230,6 @@ void ImageManager::release_image(int vm_id, int iid, bool failed) case Image::DISABLED: case Image::READY: case Image::ERROR: - ostringstream oss; oss << "Releasing image in wrong state: " << Image::state_to_str(img->get_state()); @@ -265,11 +245,7 @@ void ImageManager::release_image(int vm_id, int iid, bool failed) void ImageManager::release_cloning_image(int iid, int clone_img_id) { - Image * img; - - ostringstream disk_file; - - img = ipool->get(iid,true); + Image * img = ipool->get(iid,true); if ( img == 0 ) { @@ -296,15 +272,13 @@ void ImageManager::release_cloning_image(int iid, int clone_img_id) { case Image::USED: case Image::CLONE: - if (img->dec_cloning(clone_img_id) == 0 && img->get_running() == 0) { img->set_state(Image::READY); } ipool->update(img); - - break; + break; case Image::DELETE: case Image::INIT: @@ -313,14 +287,13 @@ void ImageManager::release_cloning_image(int iid, int clone_img_id) case Image::ERROR: case Image::USED_PERS: case Image::LOCKED: + ostringstream oss; - ostringstream oss; - oss << "Releasing image in wrong state: " - << Image::state_to_str(img->get_state()); + oss << "Releasing image in wrong state: " + << Image::state_to_str(img->get_state()); - NebulaLog::log("ImM", Log::ERROR, oss.str()); - - break; + NebulaLog::log("ImM", Log::ERROR, oss.str()); + break; } img->unlock(); @@ -639,7 +612,7 @@ int ImageManager::clone_image(int new_id, case Image::READY: img->inc_cloning(new_id); - if (img->isPersistent()) + if (img->is_persistent()) { img->set_state(Image::CLONE); } @@ -738,12 +711,11 @@ int ImageManager::register_image(int iid, const string& ds_data, string& error) { string source = img->get_source(); - if ( img->isSaving() || img->get_type() == Image::DATABLOCK ) + if ( img->is_saving() || img->get_type() == Image::DATABLOCK ) { imd->mkfs(img->get_oid(), *drv_msg); - oss << "Creating disk at " << source - << " of "<< img->get_size() + oss << "Creating disk at " << source << " of "<< img->get_size() << "Mb (type: " << img->get_fstype() << ")"; } else if ( !source.empty() ) //Source in Template diff --git a/src/image/ImageManagerDriver.cc b/src/image/ImageManagerDriver.cc index cb83c6566b..6bb6fa1aac 100644 --- a/src/image/ImageManagerDriver.cc +++ b/src/image/ImageManagerDriver.cc @@ -369,15 +369,12 @@ static int mkfs_action(istringstream& is, string source; Image * image; bool is_saving = false; - bool is_hot = false; string info; - int rc; - int vm_id = -1; - int ds_id = -1; - - int disk_id; + int vm_id = -1; + int ds_id = -1; + int disk_id = -1; VirtualMachine * vm; ostringstream oss; @@ -411,14 +408,13 @@ static int mkfs_action(istringstream& is, return ds_id; } - is_saving = image->isSaving(); - is_hot = image->isHot(); + is_saving = image->is_saving(); ds_id = image->get_ds_id(); if ( is_saving ) { - image->get_template_attribute("SAVED_VM_ID", vm_id); image->get_template_attribute("SAVED_DISK_ID", disk_id); + image->get_template_attribute("SAVED_VM_ID", vm_id); } if ( result == "FAILURE" ) @@ -459,28 +455,12 @@ static int mkfs_action(istringstream& is, goto error_save_get; } - if ( is_hot ) //Saveas hot, trigger disk copy + if ( vm->set_saveas_disk(disk_id, source, id) == -1 ) { - rc = vm->save_disk_hot(disk_id, source, id); - - if ( rc == -1 ) - { - goto error_save_state; - } - - tm->trigger(TransferManager::SAVEAS_HOT, vm_id); + goto error_save_state; } - else //setup disk information - { - rc = vm->save_disk(disk_id, source, id); - if ( rc == -1 ) - { - goto error_save_state; - } - - vm->clear_saveas_state(disk_id, is_hot); - } + tm->trigger(TransferManager::SAVEAS_HOT, vm_id); vmpool->update(vm); @@ -493,12 +473,12 @@ error_img: goto error; error_save_get: - oss << "Image created for SAVE_AS, but the associated VM does not exist."; + oss << "Image created to save as a disk but VM does not exist."; goto error_save; error_save_state: vm->unlock(); - oss << "Image created for SAVE_AS, but VM is no longer running"; + oss << "Image created to save as disk but VM is no longer running"; error_save: image = ipool->get(id, true); @@ -530,7 +510,10 @@ error: { if ((vm = vmpool->get(vm_id, true)) != 0) { - vm->clear_saveas_state(disk_id, is_hot); + vm->clear_saveas_state(); + + vm->clear_saveas_disk(); + vmpool->update(vm); vm->unlock(); diff --git a/src/image/ImageTemplate.cc b/src/image/ImageTemplate.cc index 9db95e66fc..599cfd4c78 100644 --- a/src/image/ImageTemplate.cc +++ b/src/image/ImageTemplate.cc @@ -21,8 +21,5 @@ vector ImageTemplate::restricted_attributes; -string ImageTemplate::saving_attribute = "SAVE_AS"; -string ImageTemplate::saving_hot_attribute = "SAVE_AS_HOT"; - /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ diff --git a/src/lcm/LifeCycleActions.cc b/src/lcm/LifeCycleActions.cc index ae844cfa8e..81a3ec4e08 100644 --- a/src/lcm/LifeCycleActions.cc +++ b/src/lcm/LifeCycleActions.cc @@ -938,7 +938,7 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose, int& imag break; case VirtualMachine::HOTPLUG_SAVEAS: - vm->cancel_saveas_disk(image_id); + image_id = vm->clear_saveas_disk(); vmpool->update(vm); vm->set_running_etime(the_time); @@ -952,7 +952,7 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose, int& imag case VirtualMachine::HOTPLUG_SAVEAS_SUSPENDED: tm->trigger(TransferManager::DRIVER_CANCEL, vid); - vm->cancel_saveas_disk(image_id); + image_id = vm->clear_saveas_disk(); vmpool->update(vm); vm->set_running_etime(the_time); @@ -1129,11 +1129,11 @@ void LifeCycleManager::recover(VirtualMachine * vm, bool success) case VirtualMachine::HOTPLUG_SAVEAS_SUSPENDED: if (success) { - lcm_action = LifeCycleManager::SAVEAS_HOT_SUCCESS; + lcm_action = LifeCycleManager::SAVEAS_SUCCESS; } else { - lcm_action = LifeCycleManager::SAVEAS_HOT_FAILURE; + lcm_action = LifeCycleManager::SAVEAS_FAILURE; } break; diff --git a/src/lcm/LifeCycleManager.cc b/src/lcm/LifeCycleManager.cc index 84b61b5246..1f98cb806f 100644 --- a/src/lcm/LifeCycleManager.cc +++ b/src/lcm/LifeCycleManager.cc @@ -166,12 +166,12 @@ void LifeCycleManager::trigger(Actions action, int _vid) aname = "DETACH_FAILURE"; break; - case SAVEAS_HOT_SUCCESS: - aname = "SAVEAS_HOT_SUCCESS"; + case SAVEAS_SUCCESS: + aname = "SAVEAS_SUCCESS"; break; - case SAVEAS_HOT_FAILURE: - aname = "SAVEAS_HOT_FAILURE"; + case SAVEAS_FAILURE: + aname = "SAVEAS_FAILURE"; break; case ATTACH_NIC_SUCCESS: @@ -399,13 +399,13 @@ void LifeCycleManager::do_action(const string &action, void * arg) { detach_failure_action(vid); } - else if (action == "SAVEAS_HOT_SUCCESS") + else if (action == "SAVEAS_SUCCESS") { - saveas_hot_success_action(vid); + saveas_success_action(vid); } - else if (action == "SAVEAS_HOT_FAILURE") + else if (action == "SAVEAS_FAILURE") { - saveas_hot_failure_action(vid); + saveas_failure_action(vid); } else if (action == "ATTACH_NIC_SUCCESS") { diff --git a/src/lcm/LifeCycleStates.cc b/src/lcm/LifeCycleStates.cc index e8cbe040da..76954ab173 100644 --- a/src/lcm/LifeCycleStates.cc +++ b/src/lcm/LifeCycleStates.cc @@ -1232,7 +1232,7 @@ void LifeCycleManager::attach_failure_action(int vid) { vm->unlock(); - vmpool->delete_attach_disk(vid, false); + vmpool->delete_attach_disk(vid); vm = vmpool->get(vid,true); @@ -1282,7 +1282,7 @@ void LifeCycleManager::detach_success_action(int vid) { vm->unlock(); - vmpool->delete_attach_disk(vid, true); + vmpool->delete_attach_disk(vid); vm = vmpool->get(vid,true); @@ -1604,27 +1604,32 @@ void LifeCycleManager::detach_nic_failure_action(int vid) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -void LifeCycleManager::saveas_hot_success_action(int vid) +void LifeCycleManager::saveas_success_action(int vid) { - VirtualMachine * vm; - Image * image; - int image_id; int disk_id; - string source; + string tm_mad; + string snap; + string ds_id; + string src; - vm = vmpool->get(vid,true); + VirtualMachine * vm = vmpool->get(vid,true); if ( vm == 0 ) { return; } - int rc = vm->get_saveas_disk_hot(disk_id, source, image_id); + int rc = vm->get_saveas_disk(disk_id, src, image_id, snap, tm_mad, ds_id); - if (vm->clear_saveas_state(disk_id, true) == -1) + vm->clear_saveas_disk(); + + if (vm->clear_saveas_state() == -1) { - vm->log("LCM", Log::ERROR, "saveas_hot_success_action, VM in a wrong state"); + vm->log("LCM",Log::ERROR, "saveas_success_action, VM in a wrong state"); + + vmpool->update(vm); + vm->unlock(); return; @@ -1634,14 +1639,14 @@ void LifeCycleManager::saveas_hot_success_action(int vid) vm->unlock(); - if ( rc != 0 ) + if (rc != 0) { return; } - image = ipool->get(image_id, true); + Image * image = ipool->get(image_id, true); - if ( image == 0 ) + if (image == 0) { return; } @@ -1656,27 +1661,32 @@ void LifeCycleManager::saveas_hot_success_action(int vid) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -void LifeCycleManager::saveas_hot_failure_action(int vid) +void LifeCycleManager::saveas_failure_action(int vid) { - VirtualMachine * vm; - Image * image; - int image_id; int disk_id; - string source; + string tm_mad; + string snap; + string ds_id; + string src; - vm = vmpool->get(vid,true); + VirtualMachine * vm = vmpool->get(vid,true); if ( vm == 0 ) { return; } - int rc = vm->get_saveas_disk_hot(disk_id, source, image_id); + int rc = vm->get_saveas_disk(disk_id, src, image_id, snap, tm_mad, ds_id); - if (vm->clear_saveas_state(disk_id, true) == -1) + vm->clear_saveas_disk(); + + if (vm->clear_saveas_state() == -1) { - vm->log("LCM", Log::ERROR, "saveas_hot_success_action, VM in a wrong state"); + vm->log("LCM",Log::ERROR, "saveas_failure_action, VM in a wrong state"); + + vmpool->update(vm); + vm->unlock(); return; @@ -1686,14 +1696,14 @@ void LifeCycleManager::saveas_hot_failure_action(int vid) vm->unlock(); - if ( rc != 0 ) + if (rc != 0) { return; } - image = ipool->get(image_id, true); + Image * image = ipool->get(image_id, true); - if ( image == 0 ) + if (image == 0) { return; } diff --git a/src/oca/ruby/opennebula/virtual_machine.rb b/src/oca/ruby/opennebula/virtual_machine.rb index 0b1d91a839..cb686f1f4e 100644 --- a/src/oca/ruby/opennebula/virtual_machine.rb +++ b/src/oca/ruby/opennebula/virtual_machine.rb @@ -29,8 +29,6 @@ module OpenNebula :action => "vm.action", :migrate => "vm.migrate", :deploy => "vm.deploy", - :savedisk => "vm.savedisk", - :savediskcancel => "vm.savediskcancel", :chown => "vm.chown", :chmod => "vm.chmod", :monitoring => "vm.monitoring", @@ -45,6 +43,7 @@ module OpenNebula :attachnic => "vm.attachnic", :detachnic => "vm.detachnic", :recover => "vm.recover", + :disksaveas => "vm.disksaveas", :disksnapshotcreate => "vm.disksnapshotcreate", :disksnapshotrevert => "vm.disksnapshotrevert", :disksnapshotdelete => "vm.disksnapshotdelete" @@ -460,7 +459,7 @@ module OpenNebula migrate(host_id, true, enforce) end - # Set the specified vm's disk to be saved in a new image + # Set the specified vm's disk to be saved as a new image # when the VirtualMachine shutdowns # # @param disk_id [Integer] ID of the disk to be saved @@ -468,36 +467,23 @@ module OpenNebula # disk will be saved # @param image_type [String] Type of the new image. Set to empty string # to use the default type - # @param hot [true|false] True to save the disk immediately, false will - # perform the operation when the VM shuts down + # @param snap_id [Integer] ID of the snapshot to save, -1 to use the + # current disk image state # # @return [Integer, OpenNebula::Error] the new Image ID in case of # success, error otherwise - def disk_snapshot(disk_id, image_name, image_type="", hot=false) + def disk_saveas(disk_id, image_name, image_type="", snap_id=-1) return Error.new('ID not defined') if !@pe_id - rc = @client.call(VM_METHODS[:savedisk], + rc = @client.call(VM_METHODS[:disksaveas], @pe_id, disk_id, image_name, image_type, - hot) + snap_id) return rc end - # @deprecated use {#disk_snapshot} - def save_as(disk_id, image_name, image_type="", hot=false) - return disk_snapshot(disk_id, image_name, image_type, hot) - end - - # Cancels a deferred snapshot that has been set by disk_snapshot. - # The target image is also deleted. - def disk_snapshot_cancel(disk_id) - return call(VM_METHODS[:savediskcancel], - @pe_id, - disk_id) - end - # Resize the VM # # @param capacity_template [String] Template containing the new capacity @@ -784,8 +770,7 @@ module OpenNebula image_id = disk["IMAGE_ID"] if !image_id.nil? && !image_id.empty? - rc = disk_snapshot(disk_id.to_i, "#{name}-disk-#{disk_id}", - "", true) + rc = disk_saveas(disk_id.to_i,"#{name}-disk-#{disk_id}","",-1) return rc if OpenNebula.is_error?(rc) diff --git a/src/rm/RequestManager.cc b/src/rm/RequestManager.cc index a390631b72..78ed77a113 100644 --- a/src/rm/RequestManager.cc +++ b/src/rm/RequestManager.cc @@ -293,8 +293,6 @@ void RequestManager::register_xml_methods() xmlrpc_c::methodPtr vm_deploy(new VirtualMachineDeploy()); xmlrpc_c::methodPtr vm_migrate(new VirtualMachineMigrate()); xmlrpc_c::methodPtr vm_action(new VirtualMachineAction()); - xmlrpc_c::methodPtr vm_savedisk(new VirtualMachineSaveDisk()); - xmlrpc_c::methodPtr vm_savedisk_cancel(new VirtualMachineSaveDiskCancel()); xmlrpc_c::methodPtr vm_monitoring(new VirtualMachineMonitoring()); xmlrpc_c::methodPtr vm_attach(new VirtualMachineAttach()); xmlrpc_c::methodPtr vm_detach(new VirtualMachineDetach()); @@ -304,6 +302,7 @@ void RequestManager::register_xml_methods() xmlrpc_c::methodPtr vm_snap_create(new VirtualMachineSnapshotCreate()); xmlrpc_c::methodPtr vm_snap_revert(new VirtualMachineSnapshotRevert()); xmlrpc_c::methodPtr vm_snap_delete(new VirtualMachineSnapshotDelete()); + xmlrpc_c::methodPtr vm_dsaveas(new VirtualMachineDiskSaveas()); xmlrpc_c::methodPtr vm_dsnap_create(new VirtualMachineDiskSnapshotCreate()); xmlrpc_c::methodPtr vm_dsnap_revert(new VirtualMachineDiskSnapshotRevert()); xmlrpc_c::methodPtr vm_dsnap_delete(new VirtualMachineDiskSnapshotDelete()); @@ -449,8 +448,6 @@ void RequestManager::register_xml_methods() RequestManagerRegistry.addMethod("one.vm.deploy", vm_deploy); RequestManagerRegistry.addMethod("one.vm.action", vm_action); RequestManagerRegistry.addMethod("one.vm.migrate", vm_migrate); - RequestManagerRegistry.addMethod("one.vm.savedisk", vm_savedisk); - RequestManagerRegistry.addMethod("one.vm.savediskcancel", vm_savedisk_cancel); RequestManagerRegistry.addMethod("one.vm.allocate", vm_allocate); RequestManagerRegistry.addMethod("one.vm.info", vm_info); RequestManagerRegistry.addMethod("one.vm.chown", vm_chown); @@ -466,6 +463,7 @@ void RequestManager::register_xml_methods() RequestManagerRegistry.addMethod("one.vm.snapshotcreate", vm_snap_create); RequestManagerRegistry.addMethod("one.vm.snapshotrevert", vm_snap_revert); RequestManagerRegistry.addMethod("one.vm.snapshotdelete", vm_snap_delete); + RequestManagerRegistry.addMethod("one.vm.disksaveas", vm_dsaveas); RequestManagerRegistry.addMethod("one.vm.disksnapshotcreate", vm_dsnap_create); RequestManagerRegistry.addMethod("one.vm.disksnapshotrevert", vm_dsnap_revert); RequestManagerRegistry.addMethod("one.vm.disksnapshotdelete", vm_dsnap_delete); diff --git a/src/rm/RequestManagerDelete.cc b/src/rm/RequestManagerDelete.cc index 5c193e19c7..f9e81085eb 100644 --- a/src/rm/RequestManagerDelete.cc +++ b/src/rm/RequestManagerDelete.cc @@ -179,55 +179,12 @@ int HostDelete::drop(int oid, PoolObjectSQL * object, string& error_msg) int ImageDelete::drop(int oid, PoolObjectSQL * object, string& error_msg) { - Nebula& nd = Nebula::instance(); - ImageManager * imagem = nd.get_imagem(); - VirtualMachinePool * vmpool = nd.get_vmpool(); - - VirtualMachine * vm; - - bool save_as; - int rc, img_id, vm_id, disk_id; - - object->get_template_attribute("SAVE_AS", save_as); - - save_as &= object->get_template_attribute("SAVED_VM_ID", vm_id) & - object->get_template_attribute("SAVED_DISK_ID", disk_id); + Nebula& nd = Nebula::instance(); + ImageManager * imagem = nd.get_imagem(); object->unlock(); - rc = imagem->delete_image(oid, error_msg); - - // ------------------------------------------------------------------------- - // Cancel the disk snapshot - // ------------------------------------------------------------------------- - - if (rc == 0 && save_as) - { - vm = vmpool->get(vm_id, true); - - if (vm == 0) - { - return rc; - } - - if (vm->get_state() == VirtualMachine::DONE) - { - vm->unlock(); - return rc; - } - - img_id = vm->get_save_disk_image(disk_id); - - if ( img_id == oid ) - { - vm->clear_save_disk(disk_id); - vmpool->update(vm); - } - - vm->unlock(); - } - - return rc; + return imagem->delete_image(oid, error_msg); } /* ------------------------------------------------------------------------- */ diff --git a/src/rm/RequestManagerImage.cc b/src/rm/RequestManagerImage.cc index f13dc45170..958804f420 100644 --- a/src/rm/RequestManagerImage.cc +++ b/src/rm/RequestManagerImage.cc @@ -495,7 +495,7 @@ void ImageSnapshotDelete::request_execute(xmlrpc_c::paramList const& paramList, return; } - success_response(id, att); + success_response(snap_id, att); } /* ------------------------------------------------------------------------- */ @@ -524,7 +524,7 @@ void ImageSnapshotRevert::request_execute(xmlrpc_c::paramList const& paramList, return; } - success_response(id, att); + success_response(snap_id, att); } /* ------------------------------------------------------------------------- */ @@ -553,6 +553,6 @@ void ImageSnapshotFlatten::request_execute(xmlrpc_c::paramList const& paramList, return; } - success_response(id, att); + success_response(snap_id, att); } diff --git a/src/rm/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc index afa1c4a743..b29f0f13f5 100644 --- a/src/rm/RequestManagerVirtualMachine.cc +++ b/src/rm/RequestManagerVirtualMachine.cc @@ -1176,66 +1176,72 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramList, - RequestAttributes& att) +void VirtualMachineDiskSaveas::request_execute( + xmlrpc_c::paramList const& paramList, RequestAttributes& att) { - Nebula& nd = Nebula::instance(); + Nebula& nd = Nebula::instance(); ImagePool * ipool = nd.get_ipool(); DatastorePool * dspool = nd.get_dspool(); - int id = xmlrpc_c::value_int(paramList.getInt(1)); - int disk_id = xmlrpc_c::value_int(paramList.getInt(2)); - string img_name = xmlrpc_c::value_string(paramList.getString(3)); - string img_type = xmlrpc_c::value_string(paramList.getString(4)); - bool is_hot = false; //Optional XML-RPC argument - - if ( paramList.size() > 5 ) - { - is_hot = xmlrpc_c::value_boolean(paramList.getBoolean(5)); - } + int id = xmlrpc_c::value_int(paramList.getInt(1)); + int disk_id = xmlrpc_c::value_int(paramList.getInt(2)); + string img_name = xmlrpc_c::value_string(paramList.getString(3)); + string img_type = xmlrpc_c::value_string(paramList.getString(4)); + int snap_id = xmlrpc_c::value_int(paramList.getInt(5)); VirtualMachinePool * vmpool = static_cast(pool); + VirtualMachine * vm; Datastore * ds; - int iid; + Image * img; + int iid; + int iid_orig; - string error_str; + string ds_data; + PoolObjectAuth ds_perms; + long long avail; + bool ds_check; string driver; string target; string dev_prefix; + int ds_id; + string ds_name; + long long size; + + string iname_orig; + string iuname_orig; + + Image::ImageType type; + Image::DiskType ds_disk_type; + + ImageTemplate * itemplate; + Template img_usage; + + int rc; + bool rc_auth; + string error; + // ------------------------------------------------------------------------- - // Prepare and check the VM/DISK to be saved_as + // Prepare and check the VM/DISK to be saved as // ------------------------------------------------------------------------- if ((vm = get_vm(id, att)) == 0) { return; } - if ( vm->set_saveas_state(disk_id, is_hot) != 0 ) + if (vm->set_saveas_state() != 0) { - vm->unlock(); - - failure_response(INTERNAL, - request_error("VM has to be RUNNING, POWEROFF or" - " SUSPENDED to snapshot disks.",""), att); - return; + goto error_state; } - int iid_orig = vm->get_image_from_disk(disk_id, is_hot, error_str); + iid_orig = vm->set_saveas_disk(disk_id, snap_id, error); - if ( iid_orig == -1 ) + if (iid_orig == -1) { - vm->clear_saveas_state(disk_id, is_hot); - - vm->unlock(); - - failure_response(INTERNAL, - request_error("Cannot use selected DISK", error_str), - att); - return; + goto error_disk; } vmpool->update(vm); @@ -1245,32 +1251,21 @@ void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramLis // ------------------------------------------------------------------------- // Get the data of the Image to be saved // ------------------------------------------------------------------------- - Image * img = ipool->get(iid_orig, true); + img = ipool->get(iid_orig, true); if ( img == 0 ) { - failure_response(NO_EXISTS, - get_error(object_name(PoolObjectSQL::IMAGE), iid_orig), - att); - - if ((vm = vmpool->get(id, true)) != 0) - { - vm->clear_saveas_state(disk_id, is_hot); - - vmpool->update(vm); - vm->unlock(); - } - - return; + goto error_image; } - int ds_id = img->get_ds_id(); - string ds_name = img->get_ds_name(); - long long size = img->get_size(); + ds_id = img->get_ds_id(); + ds_name = img->get_ds_name(); - string iname_orig = img->get_name(); - string iuname_orig = img->get_uname(); - Image::ImageType type = img->get_type(); + size = img->get_size(); + type = img->get_type(); + + iname_orig = img->get_name(); + iuname_orig = img->get_uname(); img->get_template_attribute("DRIVER", driver); img->get_template_attribute("TARGET", target); @@ -1283,74 +1278,39 @@ void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramLis case Image::OS: case Image::DATABLOCK: case Image::CDROM: - break; + break; case Image::KERNEL: case Image::RAMDISK: case Image::CONTEXT: - failure_response(INTERNAL, - request_error("Cannot save_as image of type " + - Image::type_to_str(type), ""), att); - return; + goto error_image_type; } // ------------------------------------------------------------------------- - // Get the data of the DataStore for the new image + // Get the data of the DataStore for the new image & size // ------------------------------------------------------------------------- if ((ds = dspool->get(ds_id, true)) == 0 ) { - failure_response(NO_EXISTS, - get_error(object_name(PoolObjectSQL::DATASTORE), ds_id), - att); - - if ((vm = vmpool->get(id, true)) != 0) - { - vm->clear_saveas_state(disk_id, is_hot); - - vmpool->update(vm); - vm->unlock(); - } - - return; + goto error_ds; } - string ds_data; - PoolObjectAuth ds_perms; - long long avail; - bool ds_check; - ds->get_permissions(ds_perms); ds->to_xml(ds_data); - ds_check = ds->get_avail_mb(avail); - - Image::DiskType ds_disk_type = ds->get_disk_type(); + ds_check = ds->get_avail_mb(avail); + ds_disk_type = ds->get_disk_type(); ds->unlock(); - // ------------------------------------------------------------------------- - // Check Datastore Capacity - // ------------------------------------------------------------------------- if (ds_check && (size > avail)) { - failure_response(ACTION, "Not enough space in datastore", att); - - if ((vm = vmpool->get(id, true)) != 0) - { - vm->clear_saveas_state(disk_id, is_hot); - - vmpool->update(vm); - vm->unlock(); - } - - return; + goto error_size; } // ------------------------------------------------------------------------- // Create a template for the new Image // ------------------------------------------------------------------------- - ImageTemplate * itemplate = new ImageTemplate; - Template img_usage; + itemplate = new ImageTemplate; itemplate->add("NAME", img_name); itemplate->add("SIZE", size); @@ -1358,15 +1318,9 @@ void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramLis itemplate->add("SAVED_IMAGE_ID",iid_orig); itemplate->add("SAVED_DISK_ID",disk_id); itemplate->add("SAVED_VM_ID", id); - itemplate->set_saving(); - if ( is_hot ) - { - itemplate->set_saving_hot(); - } - - if ( img_type.empty() ) + if (img_type.empty()) { itemplate->add("TYPE", Image::type_to_str(type)); } @@ -1375,17 +1329,17 @@ void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramLis itemplate->add("TYPE", img_type); } - if ( driver.empty() == false ) + if (!driver.empty()) { itemplate->add("DRIVER", driver); } - if ( target.empty() == false ) + if (!target.empty()) { itemplate->add("TARGET", target); } - if ( dev_prefix.empty() == false ) + if (!dev_prefix.empty()) { itemplate->add("DEV_PREFIX", dev_prefix); } @@ -1396,7 +1350,7 @@ void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramLis // ------------------------------------------------------------------------- // Authorize the operation & check quotas // ------------------------------------------------------------------------- - bool rc_auth = vm_authorization(id, itemplate, 0, att, 0,&ds_perms,auth_op); + rc_auth = vm_authorization(id, itemplate, 0, att, 0,&ds_perms,auth_op); if ( rc_auth == true ) { @@ -1405,216 +1359,111 @@ void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramLis if ( rc_auth == false) { - delete itemplate; - - if ((vm = vmpool->get(id, true)) != 0) - { - vm->clear_saveas_state(disk_id, is_hot); - - vmpool->update(vm); - vm->unlock(); - } - - return; + goto error_auth; } // ------------------------------------------------------------------------- // Create the image // ------------------------------------------------------------------------- - int rc = ipool->allocate(att.uid, - att.gid, - att.uname, - att.gname, - att.umask, - itemplate, - ds_id, - ds_name, - ds_disk_type, - ds_data, - Datastore::IMAGE_DS, - -1, - &iid, - error_str); + rc = ipool->allocate(att.uid, + att.gid, + att.uname, + att.gname, + att.umask, + itemplate, + ds_id, + ds_name, + ds_disk_type, + ds_data, + Datastore::IMAGE_DS, + -1, + &iid, + error); if (rc < 0) { - quota_rollback(&img_usage, Quotas::DATASTORE, att); - - if ((vm = vmpool->get(id, true)) != 0) - { - vm->clear_saveas_state(disk_id, is_hot); - - vmpool->update(vm); - vm->unlock(); - } - - failure_response(INTERNAL, - allocate_error(PoolObjectSQL::IMAGE, error_str), att); - return; + goto error_allocate; } ds = dspool->get(ds_id, true); - if ( ds != 0 ) // TODO: error otherwise or leave image in ERROR? + if (ds == 0) { - ds->add_image(iid); - - dspool->update(ds); - - ds->unlock(); + goto error_ds_removed; } + ds->add_image(iid); + + dspool->update(ds); + + ds->unlock(); + success_response(iid, att); -} -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ + return; -void VirtualMachineSaveDiskCancel::request_execute( - xmlrpc_c::paramList const& paramList, - RequestAttributes& att) -{ - Nebula& nd = Nebula::instance(); +error_state: + vm->unlock(); - AclManager * aclm = nd.get_aclm(); - ImageManager * imagem = nd.get_imagem(); - ImagePool * ipool = nd.get_ipool(); - Image * img; - int img_id; + failure_response(INTERNAL,request_error("VM has to be RUNNING, POWEROFF or " + "SUSPENDED to save disks.",""), att); + return; - VirtualMachinePool * vmpool = static_cast(pool); - VirtualMachine * vm; +error_disk: + vm->clear_saveas_state(); - string error_str; - - int id = xmlrpc_c::value_int(paramList.getInt(1)); - int disk_id = xmlrpc_c::value_int(paramList.getInt(2)); - - // ------------------------------------------------------------------------- - // Authorize the VM operation - // ------------------------------------------------------------------------- - - if (att.uid != UserPool::ONEADMIN_ID) - { - PoolObjectAuth vm_perms; - PoolObjectAuth img_perms; - - if ((vm = get_vm(id, att)) == 0) - { - return; - } - - vm->get_permissions(vm_perms); - - img_id = vm->get_save_disk_image(disk_id); - - vm->unlock(); - - AuthRequest ar(att.uid, att.group_ids); - - ar.add_auth(auth_op, vm_perms); // MANAGE VM - - img = ipool->get(img_id, true); - - if ( img != 0 ) - { - img->get_permissions(img_perms); - - img->unlock(); - - ar.add_auth(AuthRequest::MANAGE, img_perms); // MANAGE IMAGE - } - - if (UserPool::authorize(ar) == -1) - { - failure_response(AUTHORIZATION, - authorization_error(ar.message, att), - att); - - return; - } - } - - // ------------------------------------------------------------------------- - // Check the VM state - // ------------------------------------------------------------------------- - - if ((vm = get_vm(id, att)) == 0) - { - return; - } - - if ((vm->get_state() != VirtualMachine::ACTIVE || - (vm->get_lcm_state() != VirtualMachine::RUNNING && - vm->get_lcm_state() != VirtualMachine::UNKNOWN) ) && - vm->get_state() != VirtualMachine::POWEROFF && - vm->get_state() != VirtualMachine::SUSPENDED) - { - failure_response(ACTION, - request_error("Wrong state to perform action",""), - att); - - vm->unlock(); - return; - } - - // ------------------------------------------------------------------------- - // Cancel the disk snapshot - // ------------------------------------------------------------------------- - - img_id = vm->get_save_disk_image(disk_id); - - if ( img_id == -1 ) - { - ostringstream oss; - oss << "Disk with ID [" << disk_id << "] is not going to be saved"; - - failure_response(ACTION, - request_error(oss.str(), ""), - att); - - vm->unlock(); - - return; - } - - vm->clear_save_disk(disk_id); - - vmpool->update(vm); + vm->clear_saveas_disk(); vm->unlock(); - // ------------------------------------------------------------------------- - // Delete the target Image - // ------------------------------------------------------------------------- + failure_response(INTERNAL,request_error("Cannot use DISK", error), att); + return; - img = ipool->get(img_id, true); +error_image: + failure_response(NO_EXISTS, get_error(object_name(PoolObjectSQL::IMAGE), + iid_orig), att); + goto error_common; - if ( img != 0 ) +error_image_type: + failure_response(INTERNAL, request_error("Cannot save_as image of type " + + Image::type_to_str(type), ""), att); + goto error_common; + +error_ds: + failure_response(NO_EXISTS, get_error(object_name(PoolObjectSQL::DATASTORE), + ds_id), att); + goto error_common; + +error_size: + failure_response(ACTION, "Not enough space in datastore", att); + goto error_common; + +error_auth: + delete itemplate; + goto error_common; + +error_allocate: + quota_rollback(&img_usage, Quotas::DATASTORE, att); + failure_response(INTERNAL, allocate_error(PoolObjectSQL::IMAGE, error),att); + goto error_common; + +error_ds_removed: + failure_response(NO_EXISTS,get_error(object_name(PoolObjectSQL::DATASTORE), + ds_id), att); + goto error_common; + +error_common: + if ((vm = vmpool->get(id, true)) != 0) { - img->unlock(); + vm->clear_saveas_state(); - int rc = imagem->delete_image(img_id, error_str); + vm->clear_saveas_disk(); - if (rc != 0) - { - ostringstream oss; - oss << "The snapshot was canceled, but " - << object_name(PoolObjectSQL::IMAGE) << " [" << img_id - << "] could not be deleted: " << error_str; + vmpool->update(vm); - failure_response(INTERNAL, - request_error(oss.str(), ""), - att); - - return; - } - - aclm->del_resource_rules(img_id, PoolObjectSQL::IMAGE); + vm->unlock(); } - // TODO: Delete the cloned template - - success_response(id, att); + return; } /* -------------------------------------------------------------------------- */ @@ -2555,7 +2404,7 @@ void VirtualMachineDiskSnapshotRevert::request_execute( } else { - success_response(id, att); + success_response(snap_id, att); } return; @@ -2594,7 +2443,7 @@ void VirtualMachineDiskSnapshotDelete::request_execute( } else { - success_response(id, att); + success_response(snap_id, att); } return; diff --git a/src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb b/src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb index 987d780f78..295b10e1ca 100644 --- a/src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb +++ b/src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb @@ -55,7 +55,6 @@ module OpenNebulaJSON when "suspend" then self.suspend when "reset" then self.reset when "saveas" then self.save_as(action_hash['params']) - when "disk_snapshot_cancel" then self.disk_snapshot_cancel(action_hash['params']) when "snapshot_create" then self.snapshot_create(action_hash['params']) when "snapshot_revert" then self.snapshot_revert(action_hash['params']) when "snapshot_delete" then self.snapshot_delete(action_hash['params']) @@ -105,14 +104,7 @@ module OpenNebulaJSON end def save_as(params=Hash.new) - clone = params['clonetemplate'] - clone = false if clone.nil? - - disk_snapshot(params['disk_id'].to_i, params['image_name'], params['type'], params['hot'], clone) - end - - def disk_snapshot_cancel(params=Hash.new) - super(params['disk_id'].to_i) + disk_saveas(params['disk_id'].to_i, params['image_name'], params['type']) end def snapshot_create(params=Hash.new) diff --git a/src/tm/TransferManager.cc b/src/tm/TransferManager.cc index 84be34350d..c4d95f34fd 100644 --- a/src/tm/TransferManager.cc +++ b/src/tm/TransferManager.cc @@ -1233,27 +1233,20 @@ void TransferManager::epilog_transfer_command( const VectorAttribute * disk, ostream& xfr) { - string save; - string tm_mad; int disk_id; - disk->vector_value("DISK_ID", disk_id); - save = disk->vector_value("SAVE"); + string save = disk->vector_value("SAVE"); + + disk->vector_value("DISK_ID", disk_id); transform(save.begin(),save.end(),save.begin(),(int(*)(int))toupper); if ( save == "YES" ) { - string source; - string save_source; - string ds_id; - - source = disk->vector_value("SOURCE"); - save_source = disk->vector_value("SAVE_AS_SOURCE"); - - tm_mad = disk->vector_value("TM_MAD"); - ds_id = disk->vector_value("DATASTORE_ID"); + string source = disk->vector_value("SOURCE"); + string tm_mad = disk->vector_value("TM_MAD"); + string ds_id = disk->vector_value("DATASTORE_ID"); if ( ds_id.empty() || tm_mad.empty() ) { @@ -1261,17 +1254,12 @@ void TransferManager::epilog_transfer_command( return; } - if (source.empty() && save_source.empty()) + if (source.empty()) { vm->log("TM", Log::ERROR, "No SOURCE to save disk image"); return; } - if (!save_source.empty())//Use the save_as_source instead - { - source = save_source; - } - //MVDS tm_mad hostname:remote_system_dir/disk.0 vmid dsid xfr << "MVDS " << tm_mad << " " @@ -1284,6 +1272,8 @@ void TransferManager::epilog_transfer_command( } else //No saving disk { + string tm_mad; + int ds_id_i; int vv_rc = 0; @@ -2063,30 +2053,21 @@ void TransferManager::saveas_hot_action(int vid) { int disk_id; int image_id; - string save_source; - - string save; + string src; + string snap_id; string tm_mad; string ds_id; - int num; - int disk_id_iter; - ostringstream os; ofstream xfr; string xfr_name; - string source; - - const VectorAttribute * disk; - vector attrs; - VirtualMachine * vm; - Nebula& nd = Nebula::instance(); - const TransferManagerDriver * tm_md; + Nebula& nd = Nebula::instance(); + // ------------------------------------------------------------------------ // Setup & Transfer script // ------------------------------------------------------------------------ @@ -2104,9 +2085,9 @@ void TransferManager::saveas_hot_action(int vid) goto error_common; } - if (vm->get_saveas_disk_hot(disk_id, save_source, image_id) == -1) + if (vm->get_saveas_disk(disk_id, src, image_id, snap_id, tm_mad, ds_id)!= 0) { - vm->log("TM", Log::ERROR,"Could not get disk information to saveas it"); + vm->log("TM", Log::ERROR,"Could not get disk information to export it"); goto error_common; } @@ -2117,41 +2098,7 @@ void TransferManager::saveas_hot_action(int vid) goto error_driver; } - num = vm->get_template_attribute("DISK",attrs); - - for (int i=0 ; i < num ; i++) - { - disk = dynamic_cast(attrs[i]); - - if ( disk == 0 ) - { - continue; - } - - disk->vector_value("DISK_ID", disk_id_iter); - - if (disk_id == disk_id_iter) - { - tm_mad = disk->vector_value("TM_MAD"); - ds_id = disk->vector_value("DATASTORE_ID"); - - break; - } - } - - if ( ds_id.empty() || tm_mad.empty() ) - { - vm->log("TM", Log::ERROR, "No DS_ID or TM_MAD to save disk image"); - goto error_common; - } - - if (save_source.empty()) - { - vm->log("TM", Log::ERROR, "No SOURCE to save disk image"); - goto error_common; - } - - xfr_name = vm->get_transfer_file() + ".saveas_hot"; + xfr_name = vm->get_transfer_file() + ".disk_saveas"; xfr.open(xfr_name.c_str(),ios::out | ios::trunc); if (xfr.fail() == true) @@ -2159,12 +2106,13 @@ void TransferManager::saveas_hot_action(int vid) goto error_file; } - //MVDS tm_mad hostname:remote_system_dir/disk.0 vmid dsid + //CPDS tm_mad hostname:remote_system_dir/disk.0 source snapid vmid dsid xfr << "CPDS " << tm_mad << " " << vm->get_hostname() << ":" << vm->get_remote_system_dir() << "/disk." << disk_id << " " - << save_source << " " + << src << " " + << snap_id << " " << vm->get_oid() << " " << ds_id << endl; @@ -2189,7 +2137,7 @@ error_file: error_common: vm->log("TM", Log::ERROR, os); - (nd.get_lcm())->trigger(LifeCycleManager::SAVEAS_HOT_FAILURE, vid); + (nd.get_lcm())->trigger(LifeCycleManager::SAVEAS_FAILURE, vid); vm->unlock(); return; diff --git a/src/tm/TransferManagerDriver.cc b/src/tm/TransferManagerDriver.cc index d7c6b16b19..79ae4a7556 100644 --- a/src/tm/TransferManagerDriver.cc +++ b/src/tm/TransferManagerDriver.cc @@ -136,7 +136,7 @@ void TransferManagerDriver::protocol(const string& message) const case VirtualMachine::HOTPLUG_SAVEAS: case VirtualMachine::HOTPLUG_SAVEAS_POWEROFF: case VirtualMachine::HOTPLUG_SAVEAS_SUSPENDED: - lcm_action = LifeCycleManager::SAVEAS_HOT_SUCCESS; + lcm_action = LifeCycleManager::SAVEAS_SUCCESS; break; case VirtualMachine::HOTPLUG_PROLOG_POWEROFF: @@ -197,7 +197,7 @@ void TransferManagerDriver::protocol(const string& message) const case VirtualMachine::HOTPLUG_SAVEAS: case VirtualMachine::HOTPLUG_SAVEAS_POWEROFF: case VirtualMachine::HOTPLUG_SAVEAS_SUSPENDED: - lcm_action = LifeCycleManager::SAVEAS_HOT_FAILURE; + lcm_action = LifeCycleManager::SAVEAS_FAILURE; break; case VirtualMachine::HOTPLUG_PROLOG_POWEROFF: diff --git a/src/tm_mad/ceph/cpds b/src/tm_mad/ceph/cpds index b4deda72b9..32c8b5146c 100755 --- a/src/tm_mad/ceph/cpds +++ b/src/tm_mad/ceph/cpds @@ -16,16 +16,18 @@ # limitations under the License. # #--------------------------------------------------------------------------- # -# mvds host:remote_system_ds/disk.i fe:SOURCE +# cpds host:remote_system_ds/disk.i fe:SOURCE snapid vmid dsid # - fe is the front-end hostname # - SOURCE is the path of the disk image in the form DS_BASE_PATH/disk # - host is the target host to deploy the VM # - remote_system_ds is the path for the system datastore in the host +# - snapid is the snapshot id. "-1" for none SRC=$1 DST=$2 -VM_ID=$3 -DS_ID=$4 +SNAP_ID=$3 +VM_ID=$4 +DS_ID=$5 if [ -z "${ONE_LOCATION}" ]; then TMCOMMON=/var/lib/one/remotes/tm/tm_common.sh @@ -43,13 +45,13 @@ source ${DRIVER_PATH}/../../datastore/ceph/ceph.conf #------------------------------------------------------------------------------- SRC_HOST=`arg_host $SRC` -SRC_PATH=`arg_path $SRC` +RBD_SRC=`arg_path $SRC` #------------------------------------------------------------------------------- # Get Image information #------------------------------------------------------------------------------- -DISK_ID=$(echo "$SRC_PATH" | $AWK -F. '{print $NF}') +DISK_ID=$(echo "$RBD_SRC" | $AWK -F. '{print $NF}') XPATH="${DRIVER_PATH}/../../datastore/xpath.rb --stdin" @@ -76,7 +78,7 @@ else RBD_DST="${RBD_SRC}-${VM_ID}-${DISK_ID}" fi -if [ -n "$SNAP_ID" ]; then +if [ "$SNAP_ID" != "-1" ]; then RBD_DST="${RBD_DST}-${SNAP_ID}@${SNAP_ID}" fi diff --git a/src/tm_mad/ceph/mvds b/src/tm_mad/ceph/mvds index f64234933d..8c976fe703 100755 --- a/src/tm_mad/ceph/mvds +++ b/src/tm_mad/ceph/mvds @@ -16,91 +16,4 @@ # limitations under the License. # #--------------------------------------------------------------------------- # -# mvds host:remote_system_ds/disk.i fe:SOURCE -# - fe is the front-end hostname -# - SOURCE is the path of the disk image in the form DS_BASE_PATH/disk -# - host is the target host to deploy the VM -# - remote_system_ds is the path for the system datastore in the host - -SRC=$1 -DST=$2 -VM_ID=$3 -DS_ID=$4 - -if [ -z "${ONE_LOCATION}" ]; then - TMCOMMON=/var/lib/one/remotes/tm/tm_common.sh -else - TMCOMMON=$ONE_LOCATION/var/remotes/tm/tm_common.sh -fi - -DRIVER_PATH=$(dirname $0) - -source $TMCOMMON -source ${DRIVER_PATH}/../../datastore/ceph/ceph.conf - -#------------------------------------------------------------------------------- -# Set dst path and dir -#------------------------------------------------------------------------------- - -SRC_HOST=`arg_host $SRC` -SRC_PATH=`arg_path $SRC` - -#------------------------------------------------------------------------------- -# Get Image information -#------------------------------------------------------------------------------- - -DISK_ID=$(echo "$SRC_PATH" | $AWK -F. '{print $NF}') - -XPATH="${DRIVER_PATH}/../../datastore/xpath.rb --stdin" - -unset i j XPATH_ELEMENTS - -while IFS= read -r -d '' element; do - XPATH_ELEMENTS[i++]="$element" -done < <(onevm show -x $VM_ID| $XPATH \ - /VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/SOURCE \ - /VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/CLONE \ - /VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/CEPH_USER) - -RBD_SRC="${XPATH_ELEMENTS[j++]}" -CLONE="${XPATH_ELEMENTS[j++]}" -CEPH_USER="${XPATH_ELEMENTS[j++]}" - -# No need to copy back to datastore no cloned images -if [ "$CLONE" = "NO" ]; then - exit 0 -fi - -if [ -n "$CEPH_USER" ]; then - RBD="$RBD --id ${CEPH_USER}" -fi - -# cloned, so the name will be "/one---" -RBD_DST="${RBD_SRC}-${VM_ID}-${DISK_ID}" -RBD_SNAP="${VM_ID}-${DISK_ID}" - -#------------------------------------------------------------------------------- -# Move the image back to the datastore -#------------------------------------------------------------------------------- - -log "Dumping $RBD_DST to $DST" - -DUMP_CMD=$(cat <release_image(oid, iid, img_error); } - - if ( disk->vector_value("SAVE_AS", save_as_id) == 0 ) - { - imagem->release_image(oid, save_as_id, img_error); - } - } } @@ -3180,162 +3173,6 @@ int VirtualMachine::generate_context(string &files, int &disk_id, return 1; } -/* -------------------------------------------------------------------------- */ - -int VirtualMachine::get_image_from_disk(int disk_id, bool hot, string& err_str) -{ - int iid = -1; - int rc; - - VectorAttribute * disk; - - ostringstream oss; - - disk = get_disk(disk_id); - - if ( disk == 0 ) - { - goto error_not_found; - } - - if(!((disk->vector_value("SAVE_AS")).empty())) - { - goto error_saved; - } - - if(!(disk->vector_value("PERSISTENT").empty()) && !hot) - { - goto error_persistent; - } - - rc = disk->vector_value("IMAGE_ID", iid); - - if ( rc != 0 ) - { - goto error_image_id; - } - - return iid; - -error_persistent: - oss << "Source image for DISK " << disk_id << " is persistent."; - goto error_common; - -error_saved: - oss << "The DISK " << disk_id << " is already going to be saved."; - goto error_common; - -error_image_id: - oss << "The DISK " << disk_id << " does not have a valid IMAGE_ID."; - goto error_common; - -error_not_found: - oss << "The DISK " << disk_id << " does not exist for VM " << oid << "."; - -error_common: - err_str = oss.str(); - - return -1; -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int VirtualMachine::set_saveas_state(int disk_id, bool hot) -{ - VectorAttribute* disk; - - switch (state) - { - case ACTIVE: - switch (lcm_state) - { - case RUNNING: - lcm_state = HOTPLUG_SAVEAS; - break; - - default: - return -1; - } - break; - - case POWEROFF: - state = ACTIVE; - lcm_state = HOTPLUG_SAVEAS_POWEROFF; - break; - - case SUSPENDED: - state = ACTIVE; - lcm_state = HOTPLUG_SAVEAS_SUSPENDED; - break; - - default: - return -1; - } - - disk = get_disk(disk_id); - - if ( disk != 0 ) - { - if (hot) - { - disk->replace("HOTPLUG_SAVE_AS_ACTIVE", "YES"); - } - else - { - disk->replace("SAVE_AS_ACTIVE", "YES"); - } - } - - return 0; -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int VirtualMachine::clear_saveas_state(int disk_id, bool hot) -{ - VectorAttribute * disk; - - disk = get_disk(disk_id); - - if (disk != 0) - { - if (hot) - { - disk->remove("HOTPLUG_SAVE_AS_ACTIVE"); - disk->remove("HOTPLUG_SAVE_AS"); - disk->remove("HOTPLUG_SAVE_AS_SOURCE"); - } - else - { - disk->remove("SAVE_AS_ACTIVE"); - } - } - - switch (lcm_state) - { - case HOTPLUG_SAVEAS: - lcm_state = RUNNING; - break; - - case HOTPLUG_SAVEAS_POWEROFF: - state = POWEROFF; - lcm_state = LCM_INIT; - break; - - case HOTPLUG_SAVEAS_SUSPENDED: - state = SUSPENDED; - lcm_state = LCM_INIT; - break; - - default: - return -1; - } - - return 0; -} - /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -3372,27 +3209,130 @@ const VectorAttribute* VirtualMachine::get_disk(int disk_id) const /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int VirtualMachine::save_disk(int disk_id, - const string& source, - int img_id) +int VirtualMachine::set_saveas_disk(int disk_id, int snap_id, string& err_str) { - VectorAttribute * disk; + int iid = -1; + VectorAttribute * disk = get_disk(disk_id); + + if (disk == 0) + { + err_str = "DISK does not exist."; + return -1; + } + + if (disk->vector_value("IMAGE_ID", iid) != 0) + { + err_str = "DISK does not have a valid IMAGE_ID."; + return -1; + } + + const Snapshots * snaps = get_disk_snapshots(disk_id, err_str); + + if (snap_id != -1) + { + if (snaps == 0 || !snaps->exists(snap_id)) + { + err_str = "Snapshot does not exist."; + return -1; + } + } + + disk->replace("HOTPLUG_SAVE_AS_ACTIVE", "YES"); + disk->replace("HOTPLUG_SAVE_AS_SNAPSHOT_ID", snap_id); + + return iid; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int VirtualMachine::set_saveas_disk(int disk_id, const string& source, int iid) +{ if (lcm_state != HOTPLUG_SAVEAS && lcm_state != HOTPLUG_SAVEAS_SUSPENDED && lcm_state != HOTPLUG_SAVEAS_POWEROFF ) { return -1; } - disk = get_disk(disk_id); + VectorAttribute * disk = get_disk(disk_id); - if ( disk != 0 ) + if ( disk == 0 ) { - disk->replace("SAVE_AS_SOURCE", source); + return -1; + } - disk->replace("SAVE_AS", img_id); + disk->replace("HOTPLUG_SAVE_AS", iid); + disk->replace("HOTPLUG_SAVE_AS_SOURCE", source); - disk->replace("SAVE", "YES"); + return 0; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int VirtualMachine::set_saveas_state() +{ + string s; + + switch (state) + { + case ACTIVE: + if (lcm_state != RUNNING) + { + return -1; + } + + lcm_state = HOTPLUG_SAVEAS; + break; + + case POWEROFF: + state = ACTIVE; + lcm_state = HOTPLUG_SAVEAS_POWEROFF; + break; + + case SUSPENDED: + state = ACTIVE; + lcm_state = HOTPLUG_SAVEAS_SUSPENDED; + break; + + default: + return -1; + } + + log("VM", Log::INFO, "New state is " + lcm_state_to_str(s,lcm_state)); + + return 0; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int VirtualMachine::clear_saveas_state() +{ + string s; + + switch (lcm_state) + { + case HOTPLUG_SAVEAS: + lcm_state = RUNNING; + log("VM", Log::INFO, "New state is "+lcm_state_to_str(s,lcm_state)); + break; + + case HOTPLUG_SAVEAS_POWEROFF: + state = POWEROFF; + lcm_state = LCM_INIT; + log("VM", Log::INFO, "New state is " + vm_state_to_str(s,state)); + break; + + case HOTPLUG_SAVEAS_SUSPENDED: + state = SUSPENDED; + lcm_state = LCM_INIT; + log("VM", Log::INFO, "New state is " + vm_state_to_str(s,state)); + break; + + default: + return -1; } return 0; @@ -3401,79 +3341,49 @@ int VirtualMachine::save_disk(int disk_id, /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int VirtualMachine::clear_save_disk(int disk_id) +int VirtualMachine::clear_saveas_disk() { - VectorAttribute * disk; + vector disks; + VectorAttribute * disk; - disk = get_disk(disk_id); + int num_disks, image_id; + bool active; - if ( disk != 0 ) + num_disks = obj_template->get("DISK", disks); + + for(int i=0; iremove("SAVE_AS_SOURCE"); - disk->remove("SAVE_AS"); - disk->replace("SAVE", "NO"); + disk = dynamic_cast(disks[i]); - return 0; + if ( disk == 0 ) + { + continue; + } + + disk->vector_value("HOTPLUG_SAVE_AS_ACTIVE", active); + + if (active) + { + disk->vector_value("HOTPLUG_SAVE_AS", image_id); + + disk->remove("HOTPLUG_SAVE_AS_ACTIVE"); + disk->remove("HOTPLUG_SAVE_AS"); + disk->remove("HOTPLUG_SAVE_AS_SOURCE"); + disk->remove("HOTPLUG_SAVE_AS_SNAPSHOT_ID"); + + return image_id; + } } return -1; } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int VirtualMachine::get_save_disk_image(int disk_id) -{ - VectorAttribute * disk; - bool save; - int img_id = -1; - - disk = get_disk(disk_id); - - if ( disk != 0 ) - { - disk->vector_value("SAVE", save); - - if (save) - { - disk->vector_value("SAVE_AS", img_id); - } - } - - return img_id; -} /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int VirtualMachine::save_disk_hot(int disk_id, - const string& source, - int img_id) -{ - VectorAttribute * disk; - - if (lcm_state != HOTPLUG_SAVEAS && lcm_state != HOTPLUG_SAVEAS_SUSPENDED - && lcm_state != HOTPLUG_SAVEAS_POWEROFF ) - { - return -1; - } - - disk = get_disk(disk_id); - - if ( disk != 0 ) - { - disk->replace("HOTPLUG_SAVE_AS", img_id); - disk->replace("HOTPLUG_SAVE_AS_SOURCE", source); - } - - return 0; -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int VirtualMachine::get_saveas_disk_hot(int& disk_id, string& source, - int& image_id) +int VirtualMachine::get_saveas_disk(int& disk_id, string& source, + int& image_id, string& snap_id, string& tm_mad, string& ds_id) { vector disks; VectorAttribute * disk; @@ -3494,78 +3404,20 @@ int VirtualMachine::get_saveas_disk_hot(int& disk_id, string& source, if ( disk->vector_value("HOTPLUG_SAVE_AS_ACTIVE") == "YES" ) { - source = disk->vector_value("HOTPLUG_SAVE_AS_SOURCE"); - - rc = disk->vector_value("HOTPLUG_SAVE_AS", image_id); + rc = disk->vector_value("HOTPLUG_SAVE_AS_SOURCE", source); + rc += disk->vector_value("HOTPLUG_SAVE_AS", image_id); + rc += disk->vector_value("HOTPLUG_SAVE_AS_SNAPSHOT_ID", snap_id); rc += disk->vector_value("DISK_ID", disk_id); + rc += disk->vector_value("DATASTORE_ID", ds_id); + rc += disk->vector_value("TM_MAD", tm_mad); - if ( rc != 0 || source.empty() ) - { - return -1; - } - - return 0; + return rc; } } return -1; } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int VirtualMachine::cancel_saveas_disk(int& image_id) -{ - vector disks; - VectorAttribute * disk; - - int num_disks; - - num_disks = obj_template->get("DISK", disks); - - bool active, hot_active; - - image_id = -1; - - for(int i=0; i(disks[i]); - - if ( disk == 0 ) - { - continue; - } - - disk->vector_value("SAVE_AS_ACTIVE", active); - disk->vector_value("HOTPLUG_SAVE_AS_ACTIVE", hot_active); - - if (active) - { - disk->vector_value("SAVE_AS", image_id); - - disk->remove("SAVE_AS_ACTIVE"); - disk->remove("SAVE_AS_SOURCE"); - disk->remove("SAVE_AS"); - - disk->replace("SAVE", "NO"); - - return 0; - } - - if (hot_active) - { - disk->vector_value("HOTPLUG_SAVE_AS", image_id); - - disk->remove("HOTPLUG_SAVE_AS_ACTIVE"); - disk->remove("HOTPLUG_SAVE_AS"); - disk->remove("HOTPLUG_SAVE_AS_SOURCE"); - - return 0; - } - } - - return -1; -} /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -4434,5 +4286,14 @@ void VirtualMachine::delete_disk_snapshot(int did, int snap_id) } it->second->delete_snapshot(snap_id); + + if (it->second->size() == 0) + { + Snapshots * tmp = it->second; + + snapshots.erase(it); + + delete tmp; + } } diff --git a/src/vm/VirtualMachinePool.cc b/src/vm/VirtualMachinePool.cc index 7b413f9db2..43f83fd109 100644 --- a/src/vm/VirtualMachinePool.cc +++ b/src/vm/VirtualMachinePool.cc @@ -1028,7 +1028,7 @@ int VirtualMachinePool::calculate_showback( /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -void VirtualMachinePool::delete_attach_disk(int vid, bool release_save_as) +void VirtualMachinePool::delete_attach_disk(int vid) { VirtualMachine * vm; VectorAttribute * disk; @@ -1076,17 +1076,6 @@ void VirtualMachinePool::delete_attach_disk(int vid, bool release_save_as) } imagem->release_image(oid, image_id, false); - - // Release non-persistent images in the detach event - if (release_save_as) - { - int save_as_id; - - if ( disk->vector_value("SAVE_AS", save_as_id) == 0 ) - { - imagem->release_image(oid, save_as_id, false); - } - } } else // Volatile disk {