diff --git a/src/vmm/VirtualMachineManager.cc b/src/vmm/VirtualMachineManager.cc index ad500b1aec..4dca140f69 100644 --- a/src/vmm/VirtualMachineManager.cc +++ b/src/vmm/VirtualMachineManager.cc @@ -2152,7 +2152,6 @@ void VirtualMachineManager::disk_snapshot_create_action(int vid) goto error_disk; } - rc = tm->snapshot_transfer_command( vm, "SNAP_CREATE", os); snap_cmd = os.str(); @@ -2174,7 +2173,6 @@ void VirtualMachineManager::disk_snapshot_create_action(int vid) disk_path = os.str(); - // Invoke driver method drv_msg = format_message( vm->get_hostname(), @@ -2192,10 +2190,10 @@ void VirtualMachineManager::disk_snapshot_create_action(int vid) vmd->disk_snapshot_create(vid, *drv_msg); - delete drv_msg; - vm->unlock(); + delete drv_msg; + return; error_disk: @@ -2230,6 +2228,112 @@ error_common: void VirtualMachineManager::disk_snapshot_revert_action(int vid) { + VirtualMachine * vm; + const VirtualMachineManagerDriver * vmd; + + ostringstream os; + + string vm_tmpl; + string* drv_msg; + + string vm_tm_mad; + string snap_cmd; + string disk_path; + + string ds_id, tm_mad, disk_id, snap_id; + + int rc; + + Nebula& nd = Nebula::instance(); + TransferManager * tm = nd.get_tm(); + + vm = vmpool->get(vid,true); + + if (vm == 0) + { + return; + } + + if (!vm->hasHistory()) + { + goto error_history; + } + + vmd = get(vm->get_vmm_mad()); + + if ( vmd == 0 ) + { + goto error_driver; + } + + if ( vm->get_snapshot_disk(ds_id, tm_mad, disk_id, snap_id) != 0 ) + { + goto error_disk; + } + + rc = tm->snapshot_transfer_command(vm, "SNAP_REVERT", os); + + snap_cmd = os.str(); + + os.str(""); + + if ( snap_cmd.empty() || rc != 0 ) + { + goto error_no_tm_command; + } + + os << vm->get_remote_system_dir() << "/disk." << disk_id; + + disk_path = os.str(); + + // Invoke driver method + drv_msg = format_message( + vm->get_hostname(), + vm->get_vnm_mad(), + "", + "", + vm->get_deploy_id(), + "", + "", + vm->get_checkpoint_file(), + snap_cmd, + "", + disk_path, + vm->to_xml(vm_tmpl)); + + vmd->disk_snapshot_revert(vid, *drv_msg); + + vm->unlock(); + + delete drv_msg; + + return; + +error_disk: + os << "disk_snapshot_revert, could not find disk to revert snapshot"; + goto error_common; + +error_history: + os << "disk_snapshot_revert, VM has no history"; + goto error_common; + +error_driver: + os << "disk_snapshot_revert, error getting driver " << vm->get_vmm_mad(); + goto error_common; + +error_no_tm_command: + os << "Cannot set disk for snapshot."; + goto error_common; + +error_common: + Nebula &ne = Nebula::instance(); + LifeCycleManager * lcm = ne.get_lcm(); + + lcm->trigger(LifeCycleManager::DISK_SNAPSHOT_FAILURE, vid); + + vm->log("VMM", Log::ERROR, os); + vm->unlock(); + return; } /* -------------------------------------------------------------------------- */ diff --git a/src/vmm_mad/exec/one_vmm_exec.rb b/src/vmm_mad/exec/one_vmm_exec.rb index 68140d0f99..408f0587fb 100755 --- a/src/vmm_mad/exec/one_vmm_exec.rb +++ b/src/vmm_mad/exec/one_vmm_exec.rb @@ -906,7 +906,7 @@ class ExecDriver < VirtualMachineDriver disk = xml_data.elements[target_xpath] attach = REXML::Element.new('ATTACH') attach.add_text('YES') - disk.add(attach) + disk.add(attach) drv_message = Base64.encode64(xml_data.to_s) @@ -973,6 +973,75 @@ class ExecDriver < VirtualMachineDriver action.run(steps) end + # + # DISKSNAPSHOTREVERT action, takes a snapshot of a disk + # + def disk_snapshot_revert(id, drv_message) + action = ACTION[:disk_snapshot_revert] + xml_data = decode(drv_message) + + tm_command = ensure_xpath(xml_data, id, action, 'TM_COMMAND') || return + + target_xpath = "VM/TEMPLATE/DISK[DISK_SNAPSHOT_ACTIVE='YES']/TARGET" + target = ensure_xpath(xml_data, id, action, target_xpath) || return + + target_index = target.downcase[-1..-1].unpack('c').first - 97 + + disk = xml_data.elements[target_xpath] + attach = REXML::Element.new('ATTACH') + attach.add_text('YES') + disk.add(attach) + + drv_message = Base64.encode64(xml_data.to_s) + + action = VmmAction.new(self, id, :disk_snapshot_revert, drv_message) + + steps = [ + # First detach the disk from the VM + #{ + # :driver => :vmm, + # :action => :detach_disk, + # :parameters => [ + # :deploy_id, + # :disk_target_path, + # target, + # target_index + # ] + #}, + # Save the Virtual Machine state + { + :driver => :vmm, + :action => :save, + :parameters => [:deploy_id, :checkpoint_file, :host] + }, + # Do the snapshot + { + :driver => :tm, + :action => :tm_snap_revert, + :parameters => tm_command.split + }, + # Restore the Virtual Machine from checkpoint + { + :driver => :vmm, + :action => :restore, + :parameters => [:checkpoint_file, :host, :deploy_id] + }, + # Attach the disk again + #{ + # :driver => :vmm, + # :action => :attach_disk, + # :parameters => [ + # :deploy_id, + # :disk_target_path, + # target, + # target_index, + # drv_message + # ] + #} + ] + + action.run(steps) + end private def ensure_xpath(xml_data, id, action, xpath)