From 67e524f2b0dcc28a3689c8aeea500c37a8cfc8c4 Mon Sep 17 00:00:00 2001 From: david karapetyan Date: Tue, 12 May 2015 14:10:23 -0700 Subject: [PATCH 01/83] rstrip! the endpoint as well I kept getting bad URI error when loading the endpoint from a file because there was a trailing newline. This fixes that problem. --- src/oca/ruby/opennebula/client.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/oca/ruby/opennebula/client.rb b/src/oca/ruby/opennebula/client.rb index d649f36e8f..3f730d0bab 100644 --- a/src/oca/ruby/opennebula/client.rb +++ b/src/oca/ruby/opennebula/client.rb @@ -143,6 +143,8 @@ module OpenNebula else @one_endpoint = "http://localhost:2633/RPC2" end + + @one_endpoint.rstrip! @async = !options[:sync] From 676bfcc1dbdfd007bc766e6bbfe75c71a08d2e72 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Thu, 14 May 2015 19:43:31 +0200 Subject: [PATCH 02/83] feature #3782: Initial class for Snapshot list --- include/Snapshot.h | 85 +++++++++++++++++++ src/vm/SConstruct | 3 +- src/vm/Snapshots.cc | 195 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 282 insertions(+), 1 deletion(-) create mode 100644 include/Snapshot.h create mode 100644 src/vm/Snapshots.cc diff --git a/include/Snapshot.h b/include/Snapshot.h new file mode 100644 index 0000000000..2817b28b22 --- /dev/null +++ b/include/Snapshot.h @@ -0,0 +1,85 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); you may */ +/* not use this file except in compliance with the License. You may obtain */ +/* a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ +/* -------------------------------------------------------------------------- */ + +#ifndef SNAPSHOT_POOL_H_ +#define SNAPSHOT_POOL_H_ + +#include +#include +#include + +#include + +#include "Template.h" + +using namespace std; + +class VectorAttribute; + +/** + * This class represents the List of Snapshots associated to an image or Virtual + * Machine Disk + */ +class Snapshots +{ +public: + Snapshots(int _disk_id); + + virtual ~Snapshots(); + + // ************************************************************************* + // Inititalization functions + // ************************************************************************* + + /** + * Builds the snapshot list from its XML representation. This function + * is used when importing it from the DB. + * @param node xmlNode for the template + * @return 0 on success + */ + int from_xml_node(const xmlNodePtr node); + + int create_snapshot(unsigned int p_id, const string& tag, string& error); + + int delete_snapshot(unsigned int id); + + /** + * Set the given snapshot as active. Updates the values of the current + * snapshot + */ + int active_snapshot(unsigned int id); + +private: + + /** + * Get a snapshot from the pool + * @param id of the snapshot + * @return pointer to the snapshot (VectorAttribute) or null + */ + VectorAttribute * get_snapshot(unsigned int id); + + Template snapshot_template; + + unsigned int next_snapshot; + + unsigned int disk_id; + + map snapshot_pool; + + unsigned int active; +}; + +#endif /*SNAPSHOT_H_*/ diff --git a/src/vm/SConstruct b/src/vm/SConstruct index 957aaa163a..1c29aa6180 100644 --- a/src/vm/SConstruct +++ b/src/vm/SConstruct @@ -47,7 +47,8 @@ source_files=[ 'vm_file_var_syntax.cc', 'VirtualMachinePool.cc', 'VirtualMachineHook.cc', - 'VirtualMachineTemplate.cc' + 'VirtualMachineTemplate.cc', + 'Snapshots.cc' ] # Build library diff --git a/src/vm/Snapshots.cc b/src/vm/Snapshots.cc new file mode 100644 index 0000000000..803da7c6e7 --- /dev/null +++ b/src/vm/Snapshots.cc @@ -0,0 +1,195 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); you may */ +/* not use this file except in compliance with the License. You may obtain */ +/* a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ +/* -------------------------------------------------------------------------- */ + +#include "Snapshot.h" + +Snapshots::Snapshots(int _disk_id): + snapshot_template(false,'=',"SNAPSHOTS"), + next_snapshot(0), + disk_id(_disk_id), + active(-1) +{ + snapshot_template.add("DISK_ID",_disk_id); +}; + +Snapshots::~Snapshots(){}; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int Snapshots::from_xml_node(const xmlNodePtr node) +{ + int rc = snapshot_template.from_xml_node(node); + + if (rc != 0) + { + return -1; + } + + vector vsnap; + + unsigned int id; + bool current; + + int num_snap = snapshot_template.get("SNAPSHOT", vsnap); + + for (int i=0; i < num_snap; i++) + { + VectorAttribute * snap = static_cast(vsnap[i]); + + snap->vector_value("ID", id); + + snap->vector_value("ACTIVE", current); + + if (current) + { + active = id; + } + + if (id >= next_snapshot) + { + next_snapshot = id + 1; + } + + snapshot_pool.insert(pair(id, snap)); + } + + int did; + + if (snapshot_template.get("DISK_ID", did)) + { + disk_id = id; + } + + return 0; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int Snapshots::create_snapshot(unsigned int p_id, const string& tag, + string& error) +{ + VectorAttribute * parent = get_snapshot(p_id); + + if (parent == 0) + { + error = "Parent snapshot not found."; + return -1; + } + + string psource = parent->vector_value("SOURCE"); + + if (psource.empty()) + { + error = "Parent snapshot has no source."; + return -1; + } + + VectorAttribute * snapshot = new VectorAttribute("SNAPSHOT"); + + if (!tag.empty()) + { + snapshot->replace("TAG",tag); + } + + snapshot->replace("ID", next_snapshot++); + + snapshot->replace("DATE", static_cast(time(0))); + + snapshot->replace("PARENT", psource); + + snapshot_template.set(snapshot); + + snapshot_pool.insert(pair(next_snapshot, snapshot)); + + return next_snapshot; +}; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int Snapshots::delete_snapshot(unsigned int id) +{ + VectorAttribute * snapshot = get_snapshot(id); + + if (snapshot == 0) + { + return -1; + } + + bool current; + + snapshot->vector_value("ACTIVE", current); + + if (current) + { + return -1; + } + + snapshot_template.remove(snapshot); + + delete snapshot; + + snapshot_pool.erase(id); + + return 0; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int Snapshots::active_snapshot(unsigned int id) +{ + VectorAttribute * snapshot = get_snapshot(id); + + if (snapshot == 0) + { + return -1; + } + + snapshot->replace("ACTIVE", true); + + snapshot = get_snapshot(active); + + if (snapshot != 0) + { + snapshot->remove("ACTIVE"); + } + + active = id; + + return 0; +} + + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +VectorAttribute * Snapshots::get_snapshot(unsigned int id) +{ + map::iterator it; + + it = snapshot_pool.find(id); + + if (it == snapshot_pool.end()) + { + return 0; + } + + return it->second; +}; + From 86c86610b9164b400ec450ab54919247201fccd5 Mon Sep 17 00:00:00 2001 From: Tino Vazquez Date: Mon, 18 May 2015 19:25:07 +0200 Subject: [PATCH 03/83] Feature #3802: iDeprecate onevcenter vms with the new onehost import functionality --- src/cli/onevcenter | 78 ++-------------------------------- src/sunstone/routes/vcenter.rb | 20 --------- 2 files changed, 4 insertions(+), 94 deletions(-) diff --git a/src/cli/onevcenter b/src/cli/onevcenter index 87f11bc617..00bbc98944 100755 --- a/src/cli/onevcenter +++ b/src/cli/onevcenter @@ -216,84 +216,14 @@ cmd=CommandParser::CmdParser.new(ARGV) do end vms_desc = <<-EOT.unindent - Import vCenter running Virtual Machines into OpenNebula + Deprecated action in onevcenter, please use onehost importvm instead EOT command :vms, vms_desc, :options=>[ VCENTER, USER, PASS ] do - if options[:vuser].nil? || - options[:vpass].nil? || - options[:vcenter].nil? - STDERR.puts "vCenter connection parameters are mandatory to import"\ - " VM templates:\n"\ - "\t --vcenter vCenter hostname\n"\ - "\t --vuser username to login in vcenter\n"\ - "\t --vpass password for the user" - exit -1 - end + STDERR.puts "Deprecated action in onevcenter, please use onehost "\ + "importvm instead" - begin - STDOUT.print "\nConnecting to vCenter: #{options[:vcenter]}..." - - vc = VCenterDriver::VIClient.new_connection( - :user => options[:vuser], - :password => options[:vpass], - :host => options[:vcenter]) - - STDOUT.print "done!\n\n" - - STDOUT.print "Looking for running Virtual Machines..." - - rs = vc.running_vms - - STDOUT.print "done!\n" - - rs.each {|dc, tmps| - STDOUT.print "\nDo you want to process datacenter #{dc} [y/n]? " - - next if STDIN.gets.strip.downcase != 'y' - - if tmps.empty? - STDOUT.print " No new running Virtual Machines found in"\ - " #{dc}...\n\n" - next - end - - tmps.each{ |v| - STDOUT.print "\n * Running Virtual Machine found:\n"\ - " - Name : #{v[:name]}\n"\ - " - UUID : #{v[:uuid]}\n"\ - " - Cluster: #{v[:host]}\n"\ - " Import this Virtual Machine [y/n]? " - - next if STDIN.gets.strip.downcase != 'y' - - one_v = ::OpenNebula::VirtualMachine.new( - ::OpenNebula::VirtualMachine.build_xml, vc.one) - - rc = one_v.allocate(v[:one]) - - if ::OpenNebula.is_error?(rc) - STDOUT.puts " Error creating Virtual Machine: "\ - "#{rc.message}\n" - end - - rc = one_v.deploy v[:host_id] - - if ::OpenNebula.is_error?(rc) - STDOUT.puts " Error creating Virtual Machine: "\ - "#{rc.message}\n" - else - STDOUT.puts " OpenNebula VM #{one_v.id} "\ - "created!\n" - end - } - } - rescue Exception => e - STDOUT.puts "error: #{e.message}" - exit -1 - end - - exit 0 + exit -1 end network_desc = <<-EOT.unindent diff --git a/src/sunstone/routes/vcenter.rb b/src/sunstone/routes/vcenter.rb index 74d09b03bb..ac7c125e18 100644 --- a/src/sunstone/routes/vcenter.rb +++ b/src/sunstone/routes/vcenter.rb @@ -87,26 +87,6 @@ get '/vcenter/templates' do end end - -get '/vcenter/vms' do - begin - vms = vcenter_client.running_vms( - $cloud_auth.client(session[:user], session[:active_zone_endpoint])) - if vms.nil? - msg = "No datacenter found" - logger.error("[vCenter] " + msg) - error = Error.new(msg) - error 404, error.to_json - end - - [200, vms.to_json] - rescue Exception => e - logger.error("[vCenter] " + e.message) - error = Error.new(e.message) - error 403, error.to_json - end -end - get '/vcenter/networks' do begin networks = vcenter_client.vcenter_networks( From aaf77b9dd1d96865ab0f6e01ea32df30951b89e8 Mon Sep 17 00:00:00 2001 From: Cherdancev Evgeni Date: Tue, 19 May 2015 14:02:21 +0600 Subject: [PATCH 04/83] add enp2 interface AND refactor mem&cpu for using /proc --- src/im_mad/remotes/kvm-probes.d/kvm.rb | 43 ++++++++++++-------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/src/im_mad/remotes/kvm-probes.d/kvm.rb b/src/im_mad/remotes/kvm-probes.d/kvm.rb index 7209dd67b5..c8b84cd34f 100755 --- a/src/im_mad/remotes/kvm-probes.d/kvm.rb +++ b/src/im_mad/remotes/kvm-probes.d/kvm.rb @@ -26,7 +26,7 @@ end # TODO : use virsh freecell when available ###### -nodeinfo_text = `virsh -c qemu:///system nodeinfo` +nodeinfo_text = `LANG=C virsh -c qemu:///system nodeinfo` exit(-1) if $?.exitstatus != 0 nodeinfo_text.split(/\n/).each{|line| @@ -43,33 +43,30 @@ nodeinfo_text.split(/\n/).each{|line| # for everything else, top & proc ##### -NETINTERFACE = "eth|bond|em|p[0-9]+p[0-9]+" +NETINTERFACE = "eth|bond|em|enp2|p[0-9]+p[0-9]+" -top_text=`top -bin2` -exit(-1) if $?.exitstatus != 0 +stat = `cat /proc/stat` -top_text.gsub!(/^top.*^top.*?$/m, "") # Strip first top output +stat.each_line do |line| + if /\Acpu (.*)\Z/.match(line) + stat_cpu = Regexp.last_match[1].to_s.split + stat_total_cpu = stat_cpu.inject(0) {|s,sum| sum.to_i+s.to_i}.to_i + $free_cpu = $total_cpu * stat_cpu[3].to_f / stat_total_cpu + $used_cpu = $total_cpu - $free_cpu + end +end -top_text.split(/\n/).each{|line| - if line.match('^%?Cpu') - line[7..-1].split(",").each{|elemento| - temp = elemento.strip.split(/[% ]/) - if temp[1]=="id" - idle = temp[0] - $free_cpu = idle.to_f * $total_cpu.to_f / 100 - $used_cpu = $total_cpu.to_f - $free_cpu - break - end +memory = `cat /proc/meminfo` +meminfo = Hash.new() +memory.each_line do |line| + key, value = line.split(':') + meminfo[key] = /\d+/.match(value)[0].to_i +end - } - end -} +$total_memory = meminfo['MemTotal'] -$total_memory = `free -k|grep "Mem:" | awk '{print $2}'` -tmp=`free -k|grep "buffers\/cache"|awk '{print $3 " " $4}'`.split - -$used_memory=tmp[0] -$free_memory=tmp[1] +$used_memory = meminfo['MemTotal'] - meminfo['MemFree'] - meminfo['Buffers'] - meminfo['Cached'] +$free_memory = $total_memory - $used_memory net_text=`cat /proc/net/dev` exit(-1) if $?.exitstatus != 0 From 0728ea0bacd1da8918a59c9ac937fe65e5c06e71 Mon Sep 17 00:00:00 2001 From: Cherdancev Evgeni Date: Tue, 19 May 2015 14:10:23 +0600 Subject: [PATCH 05/83] change enp2 to enp interfaces --- src/im_mad/remotes/kvm-probes.d/kvm.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/im_mad/remotes/kvm-probes.d/kvm.rb b/src/im_mad/remotes/kvm-probes.d/kvm.rb index c8b84cd34f..946934827c 100755 --- a/src/im_mad/remotes/kvm-probes.d/kvm.rb +++ b/src/im_mad/remotes/kvm-probes.d/kvm.rb @@ -43,7 +43,7 @@ nodeinfo_text.split(/\n/).each{|line| # for everything else, top & proc ##### -NETINTERFACE = "eth|bond|em|enp2|p[0-9]+p[0-9]+" +NETINTERFACE = "eth|bond|em|enp|p[0-9]+p[0-9]+" stat = `cat /proc/stat` From bc3b4a53880de6aeaf71ca5db43cc0ad5e7a116b Mon Sep 17 00:00:00 2001 From: Cherdancev Evgeni Date: Tue, 19 May 2015 14:28:55 +0600 Subject: [PATCH 06/83] inject swap arguments --- src/im_mad/remotes/kvm-probes.d/kvm.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/im_mad/remotes/kvm-probes.d/kvm.rb b/src/im_mad/remotes/kvm-probes.d/kvm.rb index 946934827c..9dad514323 100755 --- a/src/im_mad/remotes/kvm-probes.d/kvm.rb +++ b/src/im_mad/remotes/kvm-probes.d/kvm.rb @@ -50,7 +50,7 @@ stat = `cat /proc/stat` stat.each_line do |line| if /\Acpu (.*)\Z/.match(line) stat_cpu = Regexp.last_match[1].to_s.split - stat_total_cpu = stat_cpu.inject(0) {|s,sum| sum.to_i+s.to_i}.to_i + stat_total_cpu = stat_cpu.inject(0) {|sum,s| sum.to_i+s.to_i}.to_i $free_cpu = $total_cpu * stat_cpu[3].to_f / stat_total_cpu $used_cpu = $total_cpu - $free_cpu end From df4cbea89be201332535679ded256916984a13de Mon Sep 17 00:00:00 2001 From: Cherdancev Evgeni Date: Tue, 19 May 2015 17:42:23 +0600 Subject: [PATCH 07/83] use vmstat instead of /proc/stat for cpu --- src/im_mad/remotes/kvm-probes.d/kvm.rb | 28 ++++++++++++-------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/im_mad/remotes/kvm-probes.d/kvm.rb b/src/im_mad/remotes/kvm-probes.d/kvm.rb index 9dad514323..77b4dbac54 100755 --- a/src/im_mad/remotes/kvm-probes.d/kvm.rb +++ b/src/im_mad/remotes/kvm-probes.d/kvm.rb @@ -40,22 +40,15 @@ nodeinfo_text.split(/\n/).each{|line| } ###### -# for everything else, top & proc -##### - -NETINTERFACE = "eth|bond|em|enp|p[0-9]+p[0-9]+" - -stat = `cat /proc/stat` - -stat.each_line do |line| - if /\Acpu (.*)\Z/.match(line) - stat_cpu = Regexp.last_match[1].to_s.split - stat_total_cpu = stat_cpu.inject(0) {|sum,s| sum.to_i+s.to_i}.to_i - $free_cpu = $total_cpu * stat_cpu[3].to_f / stat_total_cpu - $used_cpu = $total_cpu - $free_cpu - end -end +# CPU +###### +vmstat = `vmstat 1 2` +$free_cpu = $total_cpu * ((vmstat.split("\n").to_a.last.split)[14].to_i)/100 +$used_cpu = $total_cpu - $free_cpu +###### +# MEMORY +###### memory = `cat /proc/meminfo` meminfo = Hash.new() memory.each_line do |line| @@ -68,6 +61,11 @@ $total_memory = meminfo['MemTotal'] $used_memory = meminfo['MemTotal'] - meminfo['MemFree'] - meminfo['Buffers'] - meminfo['Cached'] $free_memory = $total_memory - $used_memory +###### +# INTERFACE +###### +NETINTERFACE = "eth|bond|em|enp|p[0-9]+p[0-9]+" + net_text=`cat /proc/net/dev` exit(-1) if $?.exitstatus != 0 From d880cc6c6b644465967771ec322ffada62c26bec Mon Sep 17 00:00:00 2001 From: Cherdancev Evgeni Date: Tue, 19 May 2015 20:32:09 +0600 Subject: [PATCH 08/83] fix LANG=C --- src/im_mad/remotes/kvm-probes.d/kvm.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/im_mad/remotes/kvm-probes.d/kvm.rb b/src/im_mad/remotes/kvm-probes.d/kvm.rb index 77b4dbac54..32db20488f 100755 --- a/src/im_mad/remotes/kvm-probes.d/kvm.rb +++ b/src/im_mad/remotes/kvm-probes.d/kvm.rb @@ -26,7 +26,9 @@ end # TODO : use virsh freecell when available ###### -nodeinfo_text = `LANG=C virsh -c qemu:///system nodeinfo` +ENV['LANG'] = 'C' + +nodeinfo_text = `virsh -c qemu:///system nodeinfo` exit(-1) if $?.exitstatus != 0 nodeinfo_text.split(/\n/).each{|line| From 98f76cf3fe3154a3c5fdde9c32a5547190d2b31e Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Tue, 19 May 2015 18:41:23 +0200 Subject: [PATCH 09/83] feature #3782: Create and Revert operations for Disk Snapshots. Core and OCA levels --- include/DispatchManager.h | 33 ++++++ include/RequestManagerVirtualMachine.h | 31 +++++ include/{Snapshot.h => Snapshots.h} | 70 ++++++++++-- include/VirtualMachine.h | 46 ++++++-- src/cli/onevm | 28 +++++ src/dm/DispatchManagerActions.cc | 122 +++++++++++++++++++- src/oca/ruby/opennebula/virtual_machine.rb | 25 +++- src/rm/RequestManager.cc | 4 + src/rm/RequestManagerVirtualMachine.cc | 79 +++++++++++++ src/vm/Snapshots.cc | 67 ++++++----- src/vm/VirtualMachine.cc | 127 ++++++++++++++++++++- 11 files changed, 576 insertions(+), 56 deletions(-) rename include/{Snapshot.h => Snapshots.h} (58%) diff --git a/include/DispatchManager.h b/include/DispatchManager.h index 482c89cffd..02558f3eae 100644 --- a/include/DispatchManager.h +++ b/include/DispatchManager.h @@ -363,6 +363,39 @@ public: int snap_id, string& error_str); + /** + * Starts the disk snapshot create action + * + * @param vid VirtualMachine identification + * @param did DISK identification + * @param tag Description for the new snapshot + * @param snap_id Will contain the new snapshot ID + * @param error_str Error reason, if any + * + * @return 0 on success, -1 otherwise + */ + int disk_snapshot_create( + int vid, + int did, + const string& tag, + int& snap_id, + string& error_str); + + /** + * Reverts the disk state to a previous snapshot + * + * @param vid VirtualMachine identification + * @param did DISK identification + * @param snap_id Snapshot to be restored + * @param error_str Error reason, if any + * + * @return 0 on success, -1 otherwise + */ + int disk_snapshot_revert( + int vid, + int did, + int snap_id, + string& error_str); private: /** * Thread id for the Dispatch Manager diff --git a/include/RequestManagerVirtualMachine.h b/include/RequestManagerVirtualMachine.h index 6cd874ca23..ac7fc030a6 100644 --- a/include/RequestManagerVirtualMachine.h +++ b/include/RequestManagerVirtualMachine.h @@ -405,4 +405,35 @@ public: /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +class VirtualMachineDiskSnapshotCreate: public RequestManagerVirtualMachine +{ +public: + VirtualMachineDiskSnapshotCreate(): + RequestManagerVirtualMachine("VirtualMachineDiskSnapshotCreate", + "Creates a new virtual machine disk snapshot", + "A:siis"){}; + + ~VirtualMachineDiskSnapshotCreate(){}; + + void request_execute(xmlrpc_c::paramList const& _paramList, + RequestAttributes& att); +}; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +class VirtualMachineDiskSnapshotRevert: public RequestManagerVirtualMachine +{ +public: + VirtualMachineDiskSnapshotRevert(): + RequestManagerVirtualMachine("VirtualMachineDiskSnapshotRevert", + "Reverts disk state to a snapshot", + "A:siii"){}; + + ~VirtualMachineDiskSnapshotRevert(){}; + + void request_execute(xmlrpc_c::paramList const& _paramList, + RequestAttributes& att); +}; + #endif diff --git a/include/Snapshot.h b/include/Snapshots.h similarity index 58% rename from include/Snapshot.h rename to include/Snapshots.h index 2817b28b22..bf755fedd9 100644 --- a/include/Snapshot.h +++ b/include/Snapshots.h @@ -14,8 +14,8 @@ /* limitations under the License. */ /* -------------------------------------------------------------------------- */ -#ifndef SNAPSHOT_POOL_H_ -#define SNAPSHOT_POOL_H_ +#ifndef SNAPSHOTS_H_ +#define SNAPSHOTS_H_ #include #include @@ -30,8 +30,18 @@ using namespace std; class VectorAttribute; /** - * This class represents the List of Snapshots associated to an image or Virtual - * Machine Disk + * This class represents a list of Snapshots associated to an image or Virtual + * Machine Disk. The list is in the form: + * + * : of the disk the snapshots are taken from (the initial backing) + * : the current snapshot in use by the VM. 0 for the original DISK + * + * + * : Description + * : the snapshot was taken + * : backing for this snapshot, 0 for the original image + * : Opaque (driver specific) string representing the parent + * : Opaque (driver specific) string representing the snapshot */ class Snapshots { @@ -52,15 +62,41 @@ public: */ int from_xml_node(const xmlNodePtr node); - int create_snapshot(unsigned int p_id, const string& tag, string& error); + /** + * XML Representation of the Snapshots + */ + string& to_xml(string& xml) const + { + return snapshot_template.to_xml(xml); + }; + /** + * Creates a new (empty) snapshot of the active disk + * @param src source of disk image (inital backing file) + * @param tag description of this snapshot (optional) + * @return id of the new snapshot + */ + int create_snapshot(const string& src, const string& tag); + + /** + * Removes the snapshot from the list + * @param id of the snapshot + */ int delete_snapshot(unsigned int id); /** * Set the given snapshot as active. Updates the values of the current * snapshot */ - int active_snapshot(unsigned int id); + int active_snapshot(unsigned int id, string& error); + + /** + * Return the disk_id of the snapshot list + */ + int get_disk_id() + { + return disk_id; + } private: @@ -71,15 +107,31 @@ private: */ VectorAttribute * get_snapshot(unsigned int id); + /** + * Text representation of the snapshot pool. To be stored as part of the + * VM or Image Templates + */ Template snapshot_template; + /** + * Next id + */ unsigned int next_snapshot; + /** + * Id of the active (current) snapshot, 0 represents the base image + */ + unsigned int active; + + /** + * Id of the disk associated with this snapshot list + */ unsigned int disk_id; + /** + * Snapshot pointer map + */ map snapshot_pool; - - unsigned int active; }; -#endif /*SNAPSHOT_H_*/ +#endif /*SNAPSHOTS_H_*/ diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index 37ece6f3cc..7119250f81 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -32,6 +32,7 @@ using namespace std; class AuthRequest; +class Snapshots; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -1495,6 +1496,28 @@ public: */ int set_attach_nic(int nic_id); + // ------------------------------------------------------------------------ + // Snapshot related functions + // ------------------------------------------------------------------------ + + /** + * Creates a new snapshot of the given disk + * @param disk_id of the disk + * @param tag a description for this snapshot + * @param error if any + * @return the id of the new snapshot or -1 if error + */ + int new_disk_snapshot(int disk_id, const string& tag, string& error); + + /** + * Sets the snap_id as active, the VM will boot from it next time + * @param disk_id of the disk + * @param snap_id of the snapshot. It can be 0 to revert to the original + * disk + * @param error if any + * @return -1 if error + */ + int revert_disk_snapshot(int disk_id, int snap_id, string& error); // ------------------------------------------------------------------------ // Snapshot related functions @@ -1651,6 +1674,11 @@ private: */ vector history_records; + /** + * Snapshots for each disk + */ + map snapshots; + // ------------------------------------------------------------------------- // Logging & Dirs // ------------------------------------------------------------------------- @@ -1797,12 +1825,12 @@ private: */ int parse_defaults(string& error_str); - /** + /** * Known attributes for network contextualization rendered as: * ETH__ = $NETWORK[context[1], vnet_name] * - * The context[1] values in the map are searched in the NIC and - * if not found in the AR and VNET. They can be also set in the + * The context[1] values in the map are searched in the NIC and + * if not found in the AR and VNET. They can be also set in the * CONTEXT section it self using full name (ETH_). * * IPv4 context variables: @@ -1924,6 +1952,13 @@ private: */ int get_disk_images(string &error_str); + /** + * Return the VectorAttribute representation of a disk + * @param disk_id of the disk + * @return pointer to the VectorAttribute + */ + VectorAttribute* get_disk(int disk_id); + protected: //************************************************************************** @@ -1998,11 +2033,6 @@ protected: return -1; } - // ************************************************************************* - // Helpers - // ************************************************************************* - - VectorAttribute* get_disk(int disk_id); }; #endif /*VIRTUAL_MACHINE_H_*/ diff --git a/src/cli/onevm b/src/cli/onevm index 714a1d8d10..927e92bfea 100755 --- a/src/cli/onevm +++ b/src/cli/onevm @@ -785,6 +785,34 @@ cmd=CommandParser::CmdParser.new(ARGV) do end end + disk_snapshot_create_desc = <<-EOT.unindent + Takes a new snapshot of the given disk. This operation needs support + from the Datastore drivers: QCOW2 or Ceph. + + States: POWEROFF + EOT + + command :"disk-snapshot-create", disk_snapshot_create_desc, + :vmid, :diskid, :tag do + helper.perform_action(args[0],options,"disk snapshot created") do |o| + o.disk_snapshot_create(args[1].to_i, args[2]) + end + end + + disk_snapshot_revert_desc = <<-EOT.unindent + Reverts disk state to a previously taken snapshot. To revert + disk state to the base disk image use 0 as snapshot id + + States: POWEROFF + EOT + + command :"disk-snapshot-revert", disk_snapshot_revert_desc, + :vmid, :diskid, :snapshot_id do + helper.perform_action(args[0],options,"disk snapshot reverted") do |o| + o.disk_snapshot_revert(args[1].to_i, args[2].to_i) + end + end + list_desc = <<-EOT.unindent Lists VMs in the pool EOT diff --git a/src/dm/DispatchManagerActions.cc b/src/dm/DispatchManagerActions.cc index 6899515335..963ca1048e 100644 --- a/src/dm/DispatchManagerActions.cc +++ b/src/dm/DispatchManagerActions.cc @@ -1146,10 +1146,10 @@ int DispatchManager::detach( /* -------------------------------------------------------------------------- */ int DispatchManager::snapshot_create( - int vid, - string& name, - int& snap_id, - string& error_str) + int vid, + string& name, + int& snap_id, + string& error_str) { ostringstream oss; @@ -1606,3 +1606,117 @@ int DispatchManager::detach_nic( /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ + +int DispatchManager::disk_snapshot_create( + int vid, + int did, + const string& tag, + int& snap_id, + string& error_str) +{ + ostringstream oss; + + VirtualMachine * vm = vmpool->get(vid, true); + + if ( vm == 0 ) + { + oss << "Could not create a new disk snapshot for VM " << vid + << ", VM does not exist" ; + error_str = oss.str(); + + NebulaLog::log("DiM", Log::ERROR, error_str); + + return -1; + } + + if ( vm->get_state() != VirtualMachine::POWEROFF || + vm->get_lcm_state() != VirtualMachine::LCM_INIT ) + { + oss << "Could not create a new snapshot for VM " << vid + << ", wrong state " << vm->state_str() << "."; + error_str = oss.str(); + + NebulaLog::log("DiM", Log::ERROR, error_str); + + vm->unlock(); + + return -1; + } + + //TODO set state (reuse HOTPLUG_SNAPSHOT?) + //vm->set_state(VirtualMachine::HOTPLUG_SNAPSHOT); + + snap_id = vm->new_disk_snapshot(did, tag, error_str); + + if (snap_id == -1) + { + vm->unlock(); + return -1; + } + + vm->unlock(); + + vmpool->update(vm); + + //TODO Trigger snapshot action on the TM + //vmm->trigger(VirtualMachineManager::SNAPSHOT_CREATE,vid); + + return 0; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int DispatchManager::disk_snapshot_revert( + int vid, + int did, + int snap_id, + string& error_str) +{ + ostringstream oss; + + VirtualMachine * vm = vmpool->get(vid, true); + + if ( vm == 0 ) + { + oss << "Could not revert to disk snapshot for VM " << vid + << ", VM does not exist" ; + error_str = oss.str(); + + NebulaLog::log("DiM", Log::ERROR, error_str); + + return -1; + } + + if ( vm->get_state() != VirtualMachine::POWEROFF || + vm->get_lcm_state() != VirtualMachine::LCM_INIT ) + { + oss << "Could not revert to disk snapshot for VM " << vid + << ", wrong state " << vm->state_str() << "."; + error_str = oss.str(); + + NebulaLog::log("DiM", Log::ERROR, error_str); + + vm->unlock(); + + return -1; + } + + //TODO set state (reuse HOTPLUG_SNAPSHOT?) + //vm->set_state(VirtualMachine::HOTPLUG_SNAPSHOT); + + if (vm->revert_disk_snapshot(did, snap_id, error_str) == -1) + { + vm->unlock(); + return -1; + } + + vm->unlock(); + + vmpool->update(vm); + + //TODO Regenerate Deployment FILE (and send it to host?) + //vmm->trigger(VirtualMachineManager::SNAPSHOT_CREATE,vid); + + return 0; +} diff --git a/src/oca/ruby/opennebula/virtual_machine.rb b/src/oca/ruby/opennebula/virtual_machine.rb index e9612749f5..fb0e14d5ec 100644 --- a/src/oca/ruby/opennebula/virtual_machine.rb +++ b/src/oca/ruby/opennebula/virtual_machine.rb @@ -44,7 +44,9 @@ module OpenNebula :snapshotdelete => "vm.snapshotdelete", :attachnic => "vm.attachnic", :detachnic => "vm.detachnic", - :recover => "vm.recover" + :recover => "vm.recover", + :disksnapshotcreate => "vm.disksnapshotcreate", + :disksnapshotrevert => "vm.disksnapshotrevert" } VM_STATE=%w{INIT PENDING HOLD ACTIVE STOPPED SUSPENDED DONE FAILED @@ -610,6 +612,27 @@ module OpenNebula return call(VM_METHODS[:snapshotdelete], @pe_id, snap_id) end + # Takes a new snapshot of a disk + # + # @param disk_id [Integer] Id of the disk + # @param tag [String] description for the snapshot + # + # @return [Integer, OpenNebula::Error] The new snapshot ID or error + def disk_snapshot_create(disk_id, tag) + return call(VM_METHODS[:disksnapshotcreate], @pe_id, disk_id, tag) + end + + # Reverts disk state to a previously taken snapshot + # + # @param disk_id [Integer] Id of the disk + # @param snap_id [Integer] Id of the snapshot + # + # @return [nil, OpenNebula::Error] nil in case of success, Error + # otherwise + def disk_snapshot_revert(disk_id, snap_id) + return call(VM_METHODS[:disksnapshotrevert], @pe_id, disk_id, snap_id) + end + # Recovers an ACTIVE VM # # @param result [Integer] Recover with failure (0), success (1) or diff --git a/src/rm/RequestManager.cc b/src/rm/RequestManager.cc index c2fb8892a2..5465383a20 100644 --- a/src/rm/RequestManager.cc +++ b/src/rm/RequestManager.cc @@ -304,6 +304,8 @@ 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_dsnap_create(new VirtualMachineDiskSnapshotCreate()); + xmlrpc_c::methodPtr vm_dsnap_revert(new VirtualMachineDiskSnapshotRevert()); xmlrpc_c::methodPtr vm_recover(new VirtualMachineRecover()); xmlrpc_c::methodPtr vm_pool_acct(new VirtualMachinePoolAccounting()); @@ -460,6 +462,8 @@ 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.disksnapshotcreate", vm_dsnap_create); + RequestManagerRegistry.addMethod("one.vm.disksnapshotrevert", vm_dsnap_revert); RequestManagerRegistry.addMethod("one.vm.recover", vm_recover); RequestManagerRegistry.addMethod("one.vmpool.info", vm_pool_info); diff --git a/src/rm/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc index bb96166dde..ec106800c2 100644 --- a/src/rm/RequestManagerVirtualMachine.cc +++ b/src/rm/RequestManagerVirtualMachine.cc @@ -2483,3 +2483,82 @@ void VirtualMachinePoolCalculateShowback::request_execute( return; } + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void VirtualMachineDiskSnapshotCreate::request_execute( + xmlrpc_c::paramList const& paramList, + RequestAttributes& att) +{ + Nebula& nd = Nebula::instance(); + DispatchManager * dm = nd.get_dm(); + + int rc; + int snap_id; + string error_str; + + int id = xmlrpc_c::value_int(paramList.getInt(1)); + int did = xmlrpc_c::value_int(paramList.getInt(2)); + string tag = xmlrpc_c::value_string(paramList.getString(3)); + + if ( vm_authorization(id, 0, 0, att, 0, 0, auth_op) == false ) + { + return; + } + + rc = dm->disk_snapshot_create(id, did, tag, snap_id, error_str); + + if ( rc != 0 ) + { + failure_response(ACTION, + request_error(error_str, ""), + att); + } + else + { + success_response(snap_id, att); + } + + return; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void VirtualMachineDiskSnapshotRevert::request_execute( + xmlrpc_c::paramList const& paramList, + RequestAttributes& att) +{ + Nebula& nd = Nebula::instance(); + DispatchManager * dm = nd.get_dm(); + + int rc; + string error_str; + + int id = xmlrpc_c::value_int(paramList.getInt(1)); + int did = xmlrpc_c::value_int(paramList.getInt(2)); + int snap_id = xmlrpc_c::value_int(paramList.getInt(3)); + + if ( vm_authorization(id, 0, 0, att, 0, 0, auth_op) == false ) + { + return; + } + + rc = dm->disk_snapshot_revert(id, did, snap_id, error_str); + + if ( rc != 0 ) + { + failure_response(ACTION, + request_error(error_str, ""), + att); + } + else + { + success_response(id, att); + } + + return; +} +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ diff --git a/src/vm/Snapshots.cc b/src/vm/Snapshots.cc index 803da7c6e7..becf641c84 100644 --- a/src/vm/Snapshots.cc +++ b/src/vm/Snapshots.cc @@ -14,13 +14,13 @@ /* limitations under the License. */ /* -------------------------------------------------------------------------- */ -#include "Snapshot.h" +#include "Snapshots.h" Snapshots::Snapshots(int _disk_id): snapshot_template(false,'=',"SNAPSHOTS"), - next_snapshot(0), - disk_id(_disk_id), - active(-1) + next_snapshot(1), + active(0), + disk_id(_disk_id) { snapshot_template.add("DISK_ID",_disk_id); }; @@ -71,7 +71,7 @@ int Snapshots::from_xml_node(const xmlNodePtr node) if (snapshot_template.get("DISK_ID", did)) { - disk_id = id; + disk_id = did; } return 0; @@ -80,23 +80,22 @@ int Snapshots::from_xml_node(const xmlNodePtr node) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int Snapshots::create_snapshot(unsigned int p_id, const string& tag, - string& error) +int Snapshots::create_snapshot(const string& disk_src, const string& tag) { - VectorAttribute * parent = get_snapshot(p_id); + string source; + int parent_id; - if (parent == 0) + if ( active > 0 ) { - error = "Parent snapshot not found."; - return -1; + VectorAttribute * parent = get_snapshot(active); + + source = parent->vector_value("SOURCE"); + parent_id = active; } - - string psource = parent->vector_value("SOURCE"); - - if (psource.empty()) + else { - error = "Parent snapshot has no source."; - return -1; + source = disk_src; + parent_id = 0; } VectorAttribute * snapshot = new VectorAttribute("SNAPSHOT"); @@ -106,17 +105,17 @@ int Snapshots::create_snapshot(unsigned int p_id, const string& tag, snapshot->replace("TAG",tag); } - snapshot->replace("ID", next_snapshot++); - + snapshot->replace("ID", next_snapshot); snapshot->replace("DATE", static_cast(time(0))); - - snapshot->replace("PARENT", psource); + snapshot->replace("PARENT_ID", parent_id); + snapshot->replace("PARENT", source); snapshot_template.set(snapshot); - snapshot_pool.insert(pair(next_snapshot, snapshot)); + snapshot_pool.insert( + pair(next_snapshot, snapshot)); - return next_snapshot; + return next_snapshot++; }; /* -------------------------------------------------------------------------- */ @@ -152,16 +151,27 @@ int Snapshots::delete_snapshot(unsigned int id) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int Snapshots::active_snapshot(unsigned int id) +int Snapshots::active_snapshot(unsigned int id, string& error) { - VectorAttribute * snapshot = get_snapshot(id); + VectorAttribute * snapshot; - if (snapshot == 0) + if ( id == active ) { - return -1; + return 0; } - snapshot->replace("ACTIVE", true); + if ( id != 0 ) + { + snapshot = get_snapshot(id); + + if (snapshot == 0) + { + error = "Snapshot does not exists"; + return -1; + } + + snapshot->replace("ACTIVE", true); + } snapshot = get_snapshot(active); @@ -175,7 +185,6 @@ int Snapshots::active_snapshot(unsigned int id) return 0; } - /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index bc5526fa37..b4942b5b6f 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -30,6 +30,7 @@ #include "ImagePool.h" #include "NebulaLog.h" #include "NebulaUtil.h" +#include "Snapshots.h" #include "Nebula.h" @@ -89,6 +90,12 @@ VirtualMachine::~VirtualMachine() delete history_records[i]; } + for (map::const_iterator it = snapshots.begin(); + it != snapshots.end() ; it++) + { + delete it->second; + } + delete _log; delete obj_template; delete user_obj_template; @@ -883,12 +890,12 @@ int VirtualMachine::parse_context(string& error_str) continue; } - parse_context_network(NETWORK_CONTEXT, NUM_NETWORK_CONTEXT, + parse_context_network(NETWORK_CONTEXT, NUM_NETWORK_CONTEXT, context, vatt); if (!vatt->vector_value("IP6_GLOBAL").empty()) { - parse_context_network(NETWORK6_CONTEXT, NUM_NETWORK6_CONTEXT, + parse_context_network(NETWORK6_CONTEXT, NUM_NETWORK6_CONTEXT, context, vatt); } } @@ -2987,7 +2994,8 @@ void VirtualMachine::release_security_groups(int id, VectorAttribute const * nic /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int VirtualMachine::generate_context(string &files, int &disk_id, string& token_password) +int VirtualMachine::generate_context(string &files, int &disk_id, + string& token_password) { ofstream file; string files_ds; @@ -3418,7 +3426,8 @@ int VirtualMachine::save_disk_hot(int disk_id, /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int VirtualMachine::get_saveas_disk_hot(int& disk_id, string& source, int& image_id) +int VirtualMachine::get_saveas_disk_hot(int& disk_id, string& source, + int& image_id) { vector disks; VectorAttribute * disk; @@ -3731,6 +3740,8 @@ string& VirtualMachine::to_xml_extended(string& xml, int n_history) const string user_template_xml; string history_xml; string perm_xml; + string snap_xml; + ostringstream oss; oss << "" @@ -3780,6 +3791,12 @@ string& VirtualMachine::to_xml_extended(string& xml, int n_history) const oss << ""; } + for (map::const_iterator it = snapshots.begin(); + it != snapshots.end() ; it++) + { + oss << it->second->to_xml(snap_xml); + } + oss << ""; xml = oss.str(); @@ -3878,6 +3895,32 @@ int VirtualMachine::from_xml(const string &xml_str) history_records[history->seq] = history; ObjectXML::free_nodes(content); + content.clear(); + } + + // Virtual Machine user template + + ObjectXML::get_nodes("/VM/SNAPSHOTS", content); + + for (vector::iterator it=content.begin();it!=content.end();it++) + { + Snapshots * snap = new Snapshots(-1); + + rc += snap->from_xml_node(*it); + + if ( rc != 0) + { + delete snap; + break; + } + + snapshots.insert(pair(snap->get_disk_id(), snap)); + } + + if (!content.empty()) + { + ObjectXML::free_nodes(content); + content.clear(); } if (rc != 0) @@ -4078,7 +4121,8 @@ void VirtualMachine::clear_template_monitor_error() /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int VirtualMachine::get_public_cloud_hypervisors(vector &public_cloud_hypervisors) const +int VirtualMachine::get_public_cloud_hypervisors( + vector &public_cloud_hypervisors) const { vector attrs; vector::const_iterator it; @@ -4116,3 +4160,76 @@ int VirtualMachine::get_public_cloud_hypervisors(vector &public_cloud_hy return public_cloud_hypervisors.size(); } + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int VirtualMachine::new_disk_snapshot(int did, const string& tag, string& error) +{ + map::iterator it; + int snap_id; + + VectorAttribute * disk; + string source; + + disk = get_disk(did); + + if ( disk == 0 ) + { + error = "DISK does not exists"; + return -1; + } + + source = disk->vector_value("SOURCE"); + + it = snapshots.find(did); + + if ( it == snapshots.end() ) + { + Snapshots * snap = new Snapshots(did); + + snap_id = snap->create_snapshot(source, tag); + + snapshots.insert(pair(did, snap)); + } + else + { + snap_id = it->second->create_snapshot(source, tag); + } + + return snap_id; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int VirtualMachine::revert_disk_snapshot(int did, int snap_id, string& error) +{ + map::iterator it; + int rc; + + VectorAttribute * disk; + string source; + + disk = get_disk(did); + + if ( disk == 0 ) + { + error = "DISK does not exists"; + return -1; + } + + it = snapshots.find(did); + + if ( it == snapshots.end() && snap_id != 0 ) + { + error = "Snapshot does not exists"; + return -1; + } + else if ( it != snapshots.end() ) + { + rc = it->second->active_snapshot(snap_id, error); + } + + return rc; +} From e3066807298a3470aface3bbc4c6a94f2f862bc3 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Wed, 20 May 2015 00:21:26 +0200 Subject: [PATCH 10/83] feature #3782: Add DISK_SNAPSHOT_POWEROFF state --- include/VirtualMachine.h | 5 ++- share/doc/xsd/acct.xsd | 3 +- share/doc/xsd/vm.xsd | 3 +- src/lcm/LifeCycleActions.cc | 38 ++++++++++++++++--- .../opennebula/client/vm/VirtualMachine.java | 6 ++- src/oca/ruby/opennebula/virtual_machine.rb | 4 +- src/sunstone/OpenNebulaVNC.rb | 1 + 7 files changed, 48 insertions(+), 12 deletions(-) diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index 7119250f81..12f6d008bd 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -155,7 +155,8 @@ public: BOOT_UNDEPLOY_FAILURE = 47, BOOT_STOPPED_FAILURE = 48, PROLOG_RESUME_FAILURE = 49, - PROLOG_UNDEPLOY_FAILURE = 50 + PROLOG_UNDEPLOY_FAILURE = 50, + DISK_SNAPSHOT_POWEROFF = 51 }; static int lcm_state_from_str(string& st, LcmState& state) @@ -211,6 +212,7 @@ public: else if ( st == "BOOT_UNDEPLOY_FAILURE") { state = BOOT_UNDEPLOY_FAILURE; } else if ( st == "PROLOG_RESUME_FAILURE") { state = PROLOG_RESUME_FAILURE; } else if ( st == "PROLOG_UNDEPLOY_FAILURE") { state = PROLOG_UNDEPLOY_FAILURE; } + else if ( st == "DISK_SNAPSHOT_POWEROFF") { state = DISK_SNAPSHOT_POWEROFF; } else {return -1;} return 0; @@ -269,6 +271,7 @@ public: case BOOT_UNDEPLOY_FAILURE: st = "BOOT_UNDEPLOY_FAILURE"; break; case PROLOG_RESUME_FAILURE: st = "PROLOG_RESUME_FAILURE"; break; case PROLOG_UNDEPLOY_FAILURE: st = "PROLOG_UNDEPLOY_FAILURE"; break; + case DISK_SNAPSHOT_POWEROFF: st = "DISK_SNAPSHOT_POWEROFF"; break; } return st; diff --git a/share/doc/xsd/acct.xsd b/share/doc/xsd/acct.xsd index 3df22ebf4a..7042c73510 100644 --- a/share/doc/xsd/acct.xsd +++ b/share/doc/xsd/acct.xsd @@ -163,7 +163,8 @@ BOOT_UNDEPLOY_FAILURE = 47, BOOT_STOPPED_FAILURE = 48, PROLOG_RESUME_FAILURE = 49, - PROLOG_UNDEPLOY_FAILURE = 50 + PROLOG_UNDEPLOY_FAILURE = 50, + DISK_SNAPSHOT_POWEROFF = 51 --> diff --git a/share/doc/xsd/vm.xsd b/share/doc/xsd/vm.xsd index f201a1e7ea..06c8b3d975 100644 --- a/share/doc/xsd/vm.xsd +++ b/share/doc/xsd/vm.xsd @@ -96,7 +96,8 @@ BOOT_UNDEPLOY_FAILURE = 47, BOOT_STOPPED_FAILURE = 48, PROLOG_RESUME_FAILURE = 49, - PROLOG_UNDEPLOY_FAILURE = 50 + PROLOG_UNDEPLOY_FAILURE = 50, + DISK_SNAPSHOT_POWEROFF = 51 --> diff --git a/src/lcm/LifeCycleActions.cc b/src/lcm/LifeCycleActions.cc index a24c1c77e3..939f78ff5f 100644 --- a/src/lcm/LifeCycleActions.cc +++ b/src/lcm/LifeCycleActions.cc @@ -917,6 +917,7 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose, int& imag case VirtualMachine::HOTPLUG: vm->clear_attach_disk(); + vmpool->update(vm); vm->set_running_etime(the_time); vmpool->update_history(vm); @@ -927,6 +928,7 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose, int& imag case VirtualMachine::HOTPLUG_NIC: vm->clear_attach_nic(); + vmpool->update(vm); vm->set_running_etime(the_time); vmpool->update_history(vm); @@ -936,11 +938,8 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose, int& imag break; case VirtualMachine::HOTPLUG_SAVEAS: - case VirtualMachine::HOTPLUG_SAVEAS_POWEROFF: - case VirtualMachine::HOTPLUG_SAVEAS_SUSPENDED: - tm->trigger(TransferManager::DRIVER_CANCEL, vid); - vm->cancel_saveas_disk(image_id); + vmpool->update(vm); vm->set_running_etime(the_time); vmpool->update_history(vm); @@ -949,14 +948,34 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose, int& imag vmm->trigger(VirtualMachineManager::CLEANUP,vid); break; + case VirtualMachine::HOTPLUG_SAVEAS_POWEROFF: + case VirtualMachine::HOTPLUG_SAVEAS_SUSPENDED: + tm->trigger(TransferManager::DRIVER_CANCEL, vid); + + vm->cancel_saveas_disk(image_id); + vmpool->update(vm); + + vm->set_running_etime(the_time); + vmpool->update_history(vm); + break; + case VirtualMachine::HOTPLUG_PROLOG_POWEROFF: case VirtualMachine::HOTPLUG_EPILOG_POWEROFF: vm->clear_attach_disk(); + vmpool->update(vm); tm->trigger(TransferManager::DRIVER_CANCEL,vid); tm->trigger(TransferManager::EPILOG_DELETE,vid); break; + case VirtualMachine::DISK_SNAPSHOT_POWEROFF: + //TODO CLEAR CURRENT SNAPSHOT + //vmpool->update(vm); + + tm->trigger(TransferManager::DRIVER_CANCEL, vid); + tm->trigger(TransferManager::EPILOG_DELETE,vid); + break; + case VirtualMachine::MIGRATE: vm->set_running_etime(the_time); vmpool->update_history(vm); @@ -967,7 +986,8 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose, int& imag vm->set_previous_reason(History::USER); vmpool->update_previous_history(vm); - hpool->del_capacity(vm->get_previous_hid(), vm->get_oid(), cpu, mem, disk); + hpool->del_capacity(vm->get_previous_hid(), vm->get_oid(), cpu, + mem, disk); vmm->trigger(VirtualMachineManager::DRIVER_CANCEL,vid); vmm->trigger(VirtualMachineManager::CLEANUP_BOTH,vid); @@ -992,7 +1012,8 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose, int& imag vm->set_previous_reason(History::USER); vmpool->update_previous_history(vm); - hpool->del_capacity(vm->get_previous_hid(), vm->get_oid(), cpu, mem, disk); + hpool->del_capacity(vm->get_previous_hid(), vm->get_oid(), cpu, + mem, disk); vmm->trigger(VirtualMachineManager::DRIVER_CANCEL,vid); vmm->trigger(VirtualMachineManager::CLEANUP_PREVIOUS,vid); @@ -1220,6 +1241,10 @@ void LifeCycleManager::recover(VirtualMachine * vm, bool success) case VirtualMachine::HOTPLUG_SNAPSHOT: lcm_action = LifeCycleManager::SNAPSHOT_CREATE_FAILURE; break; + + case VirtualMachine::DISK_SNAPSHOT_POWEROFF: + //TODO trigger lcm action + break; } if (lcm_action != LifeCycleManager::FINALIZE) @@ -1420,6 +1445,7 @@ void LifeCycleManager::retry(VirtualMachine * vm) case VirtualMachine::HOTPLUG_SAVEAS_SUSPENDED: case VirtualMachine::HOTPLUG_PROLOG_POWEROFF: case VirtualMachine::HOTPLUG_EPILOG_POWEROFF: + case VirtualMachine::DISK_SNAPSHOT_POWEROFF: case VirtualMachine::RUNNING: case VirtualMachine::UNKNOWN: break; diff --git a/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java b/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java index c26c02cd66..5e8b99e56c 100644 --- a/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java +++ b/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java @@ -127,7 +127,8 @@ public class VirtualMachine extends PoolElement{ "BOOT_UNDEPLOY_FAILURE", "BOOT_STOPPED_FAILURE", "PROLOG_RESUME_FAILURE", - "PROLOG_UNDEPLOY_FAILURE" + "PROLOG_UNDEPLOY_FAILURE", + "DISK_SNAPSHOT_POWEROFF" }; private static final String[] SHORT_LCM_STATES = @@ -182,7 +183,8 @@ public class VirtualMachine extends PoolElement{ "fail", // BOOT_UNDEPLOY_FAILURE "fail", // BOOT_STOPPED_FAILURE "fail", // PROLOG_RESUME_FAILURE - "fail" // PROLOG_UNDEPLOY_FAILURE + "fail", // PROLOG_UNDEPLOY_FAILURE + "snap" // DISK_SNAPSHOT_POWEROFF }; /** diff --git a/src/oca/ruby/opennebula/virtual_machine.rb b/src/oca/ruby/opennebula/virtual_machine.rb index fb0e14d5ec..f3b87a550f 100644 --- a/src/oca/ruby/opennebula/virtual_machine.rb +++ b/src/oca/ruby/opennebula/virtual_machine.rb @@ -104,6 +104,7 @@ module OpenNebula BOOT_STOPPED_FAILURE PROLOG_RESUME_FAILURE PROLOG_UNDEPLOY_FAILURE + DISK_SNAPSHOT_POWEROFF } SHORT_VM_STATES={ @@ -169,7 +170,8 @@ module OpenNebula "BOOT_UNDEPLOY_FAILURE" => "fail", "BOOT_STOPPED_FAILURE" => "fail", "PROLOG_RESUME_FAILURE" => "fail", - "PROLOG_UNDEPLOY_FAILURE" => "fail" + "PROLOG_UNDEPLOY_FAILURE" => "fail", + "DISK_SNAPSHOT_POWEROFF" => "snap" } MIGRATE_REASON=%w{NONE ERROR USER} diff --git a/src/sunstone/OpenNebulaVNC.rb b/src/sunstone/OpenNebulaVNC.rb index 077976f553..9481df6ea4 100644 --- a/src/sunstone/OpenNebulaVNC.rb +++ b/src/sunstone/OpenNebulaVNC.rb @@ -83,6 +83,7 @@ VNC_STATES = [ #48, #BOOT_STOPPED_FAILURE #49, #PROLOG_RESUME_FAILURE #50, #PROLOG_UNDEPLOY_FAILURE + #51, #DISK_SNAPSHOT_POWEROFF ] class OpenNebulaVNC From 986cf14c6bda32befbfed06b8735ce97f0f68287 Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Wed, 20 May 2015 17:18:26 +0200 Subject: [PATCH 11/83] feature #3782: add snapshots to onevm show --- src/cli/one_helper/onevm_helper.rb | 57 ++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/cli/one_helper/onevm_helper.rb b/src/cli/one_helper/onevm_helper.rb index 81c8d1c58f..19fdb61103 100644 --- a/src/cli/one_helper/onevm_helper.rb +++ b/src/cli/one_helper/onevm_helper.rb @@ -615,6 +615,12 @@ class OneVMHelper < OpenNebulaHelper::OneHelper end if !options[:all] end + if vm.has_elements?("/VM/SNAPSHOTS") + puts + CLIHelper.print_header(str_h1 % "VM DISK SNAPSHOTS",false) + format_snapshots(vm) + end + sg_nics = [] if (vm.has_elements?("/VM/TEMPLATE/NIC/SECURITY_GROUPS")) @@ -941,4 +947,55 @@ class OneVMHelper < OpenNebulaHelper::OneHelper table.show(history) end + + def format_snapshots(vm) + table=CLIHelper::ShowTable.new(nil, self) do + column :AC , "Is active", :left, :size => 2 do |d| + if d["ACTIVE"] == "YES" + "=>" + else + "" + end + end + column :ID, "Snapshot ID", :size=>3 do |d| + d["ID"] + end + + column :DISK, "Disk ID", :size=>4 do |d| + d["DISK_ID"] + end + + column :PARENT, "Snapshot Parent ID", :size=>6 do |d| + d["PARENT_ID"] + end + + column :TAG, "Snapshot Tag", :left, :size=>45 do |d| + d["TAG"] + end + + column :DATE, "Snapshot creation date", :size=>15 do |d| + OpenNebulaHelper.time_to_str(d["DATE"]) + end + + default :AC, :ID, :DISK, :PARENT, :DATE, :TAG + end + + # Convert snapshot data to an array + vm_hash = vm.to_hash + vm_snapshots = [vm_hash['VM']['SNAPSHOTS']].flatten + + snapshots = [] + + vm_snapshots.each do |disk| + disk_id = disk['DISK_ID'] + + sshots = [disk['SNAPSHOT']].flatten + sshots.each do |snapshot| + data = snapshot.merge({ 'DISK_ID' => disk_id }) + snapshots << data + end + end + + table.show(snapshots) + end end From 20fac744a7a6d47a495043efc8dda6fb65d0f224 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Wed, 20 May 2015 17:48:27 +0200 Subject: [PATCH 12/83] feature #3782: Generate snapshot files for TransferManager --- include/Snapshots.h | 9 +++ include/TransferManager.h | 12 ++++ include/VirtualMachine.h | 10 +++ src/dm/DispatchManagerActions.cc | 11 ++- src/tm/TransferManager.cc | 117 ++++++++++++++++++++++++++++++- src/vm/Snapshots.cc | 18 +++++ src/vm/VirtualMachine.cc | 63 +++++++++++++++++ 7 files changed, 233 insertions(+), 7 deletions(-) diff --git a/include/Snapshots.h b/include/Snapshots.h index bf755fedd9..927162db6c 100644 --- a/include/Snapshots.h +++ b/include/Snapshots.h @@ -98,6 +98,15 @@ public: return disk_id; } + /** + * Get Attribute from the given snapshot + * @param id of the snapshot + * @param name of the attribute + * + * @return value or empty if not found + */ + string get_snapshot_attribute(unsigned int id, const char* name); + private: /** diff --git a/include/TransferManager.h b/include/TransferManager.h index 7fbf7a3ffd..448340d59f 100644 --- a/include/TransferManager.h +++ b/include/TransferManager.h @@ -60,6 +60,8 @@ public: CHECKPOINT, DRIVER_CANCEL, SAVEAS_HOT, + SNAPSHOT_CREATE, + SNAPSHOT_DELETE, FINALIZE }; @@ -325,6 +327,16 @@ private: * This function starts the saveas of the given disk */ void saveas_hot_action(int vid); + + /** + * This function takes an snapshot of a disk + */ + void snapshot_create_action(int vid); + + /** + * This function deletes an snapshot of a disk + */ + void snapshot_delete_action(int vid); }; #endif /*TRANSFER_MANAGER_H*/ diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index 12f6d008bd..0208d037c0 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -1522,6 +1522,16 @@ public: */ int revert_disk_snapshot(int disk_id, int snap_id, string& error); + /** + * Get information about the disk to take the snapshot from + * @param ds_id id of the datastore + * @param tm_mad used by the datastore + * @param parent to take the snapshot from + * @param snap_id of the snapshot + */ + int get_snapshot_disk(string& ds_id, string& tm_mad, string& parent, + string& snap_id); + // ------------------------------------------------------------------------ // Snapshot related functions // ------------------------------------------------------------------------ diff --git a/src/dm/DispatchManagerActions.cc b/src/dm/DispatchManagerActions.cc index 963ca1048e..908e0c95f9 100644 --- a/src/dm/DispatchManagerActions.cc +++ b/src/dm/DispatchManagerActions.cc @@ -1643,8 +1643,8 @@ int DispatchManager::disk_snapshot_create( return -1; } - //TODO set state (reuse HOTPLUG_SNAPSHOT?) - //vm->set_state(VirtualMachine::HOTPLUG_SNAPSHOT); + vm->set_state(VirtualMachine::ACTIVE); + vm->set_state(VirtualMachine::DISK_SNAPSHOT_POWEROFF); snap_id = vm->new_disk_snapshot(did, tag, error_str); @@ -1658,8 +1658,7 @@ int DispatchManager::disk_snapshot_create( vmpool->update(vm); - //TODO Trigger snapshot action on the TM - //vmm->trigger(VirtualMachineManager::SNAPSHOT_CREATE,vid); + tm->trigger(TransferManager::SNAPSHOT_CREATE,vid); return 0; } @@ -1702,8 +1701,8 @@ int DispatchManager::disk_snapshot_revert( return -1; } - //TODO set state (reuse HOTPLUG_SNAPSHOT?) - //vm->set_state(VirtualMachine::HOTPLUG_SNAPSHOT); + vm->set_state(VirtualMachine::ACTIVE); + vm->set_state(VirtualMachine::DISK_SNAPSHOT_POWEROFF); if (vm->revert_disk_snapshot(did, snap_id, error_str) == -1) { diff --git a/src/tm/TransferManager.cc b/src/tm/TransferManager.cc index f9e6d0cfb8..6f89d02bdc 100644 --- a/src/tm/TransferManager.cc +++ b/src/tm/TransferManager.cc @@ -139,6 +139,14 @@ void TransferManager::trigger(Actions action, int _vid) aname = "DRIVER_CANCEL"; break; + case SNAPSHOT_CREATE: + aname = "SNAPSHOT_CREATE"; + break; + + case SNAPSHOT_DELETE: + aname = "SNAPSHOT_DELETE"; + break; + case FINALIZE: aname = ACTION_FINALIZE; break; @@ -378,6 +386,14 @@ void TransferManager::do_action(const string &action, void * arg) { driver_cancel_action(vid); } + else if (action == "SNAPSHOT_CREATE") + { + snapshot_create_action(vid); + } + else if (action == "SNAPSHOT_DELETE") + { + snapshot_delete_action(vid); + } else { ostringstream oss; @@ -2082,7 +2098,7 @@ void TransferManager::saveas_hot_action(int vid) if (vm->get_saveas_disk_hot(disk_id, save_source, image_id) == -1) { - vm->log("TM", Log::ERROR, "Could not get disk information to saveas it"); + vm->log("TM", Log::ERROR,"Could not get disk information to saveas it"); goto error_common; } @@ -2190,6 +2206,105 @@ void TransferManager::migrate_transfer_command( << endl; } +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void TransferManager::snapshot_create_action(int vid) +{ + string tm_mad; + string ds_id; + string parent; + string snap_id; + + ostringstream os; + + ofstream xfr; + string xfr_name; + + VirtualMachine * vm; + + const TransferManagerDriver * tm_md; + + // ------------------------------------------------------------------------ + // Setup & Transfer script + // ------------------------------------------------------------------------ + vm = vmpool->get(vid,true); + + if (vm == 0) + { + vm->log("TM", Log::ERROR, "Could not obtain the VM"); + goto error_common; + } + + if (!vm->hasHistory()) + { + vm->log("TM", Log::ERROR, "The VM has no history"); + goto error_common; + } + + if (vm->get_snapshot_disk(ds_id, tm_mad, parent, snap_id) == -1) + { + vm->log("TM", Log::ERROR, "Could not get disk information to" + "take snapshot"); + goto error_common; + } + + tm_md = get(); + + if (tm_md == 0) + { + goto error_driver; + } + + xfr_name = vm->get_transfer_file() + ".disk_snapshot"; + xfr.open(xfr_name.c_str(),ios::out | ios::trunc); + + if (xfr.fail() == true) + { + goto error_file; + } + + //SNAP_CREATE tm_mad hostname:parent_path vmid dsid + xfr << "SNAP_CREATE " + << tm_mad << " " + << vm->get_hostname() << ":" + << parent << " " + << snap_id << " " + << vm->get_oid() << " " + << ds_id + << endl; + + xfr.close(); + + tm_md->transfer(vid, xfr_name); + + vm->unlock(); + + return; + +error_driver: + os << "saveas_hot_transfer, error getting TM driver."; + goto error_common; + +error_file: + os << "disk_snapshot_create, could not open file: " << xfr_name; + os << ". You may need to manually clean hosts (previous & current)"; + goto error_common; + +error_common: + vm->log("TM", Log::ERROR, os); + +//TODO (nd.get_lcm())->trigger(LifeCycleManager::SAVEAS_HOT_FAILURE, vid); + + vm->unlock(); + return; +}; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void TransferManager::snapshot_delete_action(int vid){}; + /* ************************************************************************** */ /* MAD Loading */ /* ************************************************************************** */ diff --git a/src/vm/Snapshots.cc b/src/vm/Snapshots.cc index becf641c84..663617c72c 100644 --- a/src/vm/Snapshots.cc +++ b/src/vm/Snapshots.cc @@ -202,3 +202,21 @@ VectorAttribute * Snapshots::get_snapshot(unsigned int id) return it->second; }; +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +string Snapshots::get_snapshot_attribute(unsigned int id, const char * name) +{ + VectorAttribute * snapshot = get_snapshot(id); + + if (snapshot == 0) + { + return ""; + } + + return snapshot->vector_value(name); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index b4942b5b6f..a49b51a277 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -4161,6 +4161,66 @@ int VirtualMachine::get_public_cloud_hypervisors( return public_cloud_hypervisors.size(); } +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ +//TODO SNAPSHOT clear_snapshot_disk (deletes) +int VirtualMachine::get_snapshot_disk(string& ds_id, string& tm_mad, + string& parent, string& snap_id) +{ + vector disks; + VectorAttribute * disk; + + int num_disks; + + num_disks = obj_template->get("DISK", disks); + + for(int i=0; i(disks[i]); + + if ( disk == 0 ) + { + continue; + } + + if ( disk->vector_value("DISK_SNAPSHOT_ACTIVE") == "YES" ) + { + map::iterator it; + int did; + + if (disk->vector_value("DISK_ID", did) == -1) + { + return -1; + } + + it = snapshots.find(did); + + if (it == snapshots.end()) + { + return -1; + } + + tm_mad = disk->vector_value("TM_MAD"); + ds_id = disk->vector_value("DATASTORE_ID"); + snap_id = disk->vector_value("DISK_SNAPSHOT_ID"); + + int isnap_id = strtol(snap_id.c_str(),NULL,0); + + parent = it->second->get_snapshot_attribute(isnap_id, "PARENT"); + + if (parent.empty() || snap_id.empty() || tm_mad.empty() + || ds_id.empty()) + { + return -1; + } + + return 0; + } + } + + return -1; +} + /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -4197,6 +4257,9 @@ int VirtualMachine::new_disk_snapshot(int did, const string& tag, string& error) snap_id = it->second->create_snapshot(source, tag); } + disk->replace("DISK_SNAPSHOT_ACTIVE", "YES"); + disk->replace("DISK_SNAPSHOT_ID", snap_id); + return snap_id; } From 904b3248e9bf9d3ed6555c23372d778fd88749a5 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Thu, 21 May 2015 14:12:35 +0200 Subject: [PATCH 13/83] feature #3782: Remove SOURCE and PARENT from snapshots. Drivers MUST generate internal snapshot references from snapshot_id, parent_id --- include/LifeCycleManager.h | 2 ++ include/Snapshots.h | 3 +- include/VirtualMachine.h | 11 +++++-- src/lcm/LifeCycleActions.cc | 4 +-- src/tm/TransferManager.cc | 10 +++--- src/tm/TransferManagerDriver.cc | 4 +++ src/vm/Snapshots.cc | 21 ++----------- src/vm/VirtualMachine.cc | 55 ++++++++++++++++++++++++--------- 8 files changed, 66 insertions(+), 44 deletions(-) diff --git a/include/LifeCycleManager.h b/include/LifeCycleManager.h index a310a598c4..7c4e04e0e3 100644 --- a/include/LifeCycleManager.h +++ b/include/LifeCycleManager.h @@ -83,6 +83,8 @@ public: SNAPSHOT_REVERT_FAILURE, /**< Sent by the VMM on snap. revert failure */ SNAPSHOT_DELETE_SUCCESS, /**< Sent by the VMM on snap. revert success */ SNAPSHOT_DELETE_FAILURE, /**< Sent by the VMM on snap. revert failure */ + DISK_SNAPSHOT_SUCCESS, /**update(vm); + vm->clear_snapshot_disk(); + vmpool->update(vm); tm->trigger(TransferManager::DRIVER_CANCEL, vid); tm->trigger(TransferManager::EPILOG_DELETE,vid); diff --git a/src/tm/TransferManager.cc b/src/tm/TransferManager.cc index 6f89d02bdc..9a07a96953 100644 --- a/src/tm/TransferManager.cc +++ b/src/tm/TransferManager.cc @@ -2213,7 +2213,8 @@ void TransferManager::snapshot_create_action(int vid) { string tm_mad; string ds_id; - string parent; + string disk_id; + string parent_id; string snap_id; ostringstream os; @@ -2242,7 +2243,7 @@ void TransferManager::snapshot_create_action(int vid) goto error_common; } - if (vm->get_snapshot_disk(ds_id, tm_mad, parent, snap_id) == -1) + if (vm->get_snapshot_disk(ds_id, tm_mad, disk_id, parent_id, snap_id) == -1) { vm->log("TM", Log::ERROR, "Could not get disk information to" "take snapshot"); @@ -2264,11 +2265,12 @@ void TransferManager::snapshot_create_action(int vid) goto error_file; } - //SNAP_CREATE tm_mad hostname:parent_path vmid dsid + //SNAP_CREATE tm_mad host:remote_system_dir/disk.0 parentid snapid vmid dsid xfr << "SNAP_CREATE " << tm_mad << " " << vm->get_hostname() << ":" - << parent << " " + << vm->get_remote_system_dir() << "/disk." << disk_id << " " + << parent_id << " " << snap_id << " " << vm->get_oid() << " " << ds_id diff --git a/src/tm/TransferManagerDriver.cc b/src/tm/TransferManagerDriver.cc index 9ab120ca64..487e9801ff 100644 --- a/src/tm/TransferManagerDriver.cc +++ b/src/tm/TransferManagerDriver.cc @@ -147,6 +147,10 @@ void TransferManagerDriver::protocol(const string& message) const lcm_action = LifeCycleManager::DETACH_SUCCESS; break; + case VirtualMachine::DISK_SNAPSHOT_POWEROFF: + lcm_action = LifeCycleManager::DISK_SNAPSHOT_SUCCESS; + break; + default: goto error_state; } diff --git a/src/vm/Snapshots.cc b/src/vm/Snapshots.cc index 663617c72c..ae1ba811e8 100644 --- a/src/vm/Snapshots.cc +++ b/src/vm/Snapshots.cc @@ -80,24 +80,8 @@ int Snapshots::from_xml_node(const xmlNodePtr node) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int Snapshots::create_snapshot(const string& disk_src, const string& tag) +int Snapshots::create_snapshot(const string& tag) { - string source; - int parent_id; - - if ( active > 0 ) - { - VectorAttribute * parent = get_snapshot(active); - - source = parent->vector_value("SOURCE"); - parent_id = active; - } - else - { - source = disk_src; - parent_id = 0; - } - VectorAttribute * snapshot = new VectorAttribute("SNAPSHOT"); if (!tag.empty()) @@ -107,8 +91,7 @@ int Snapshots::create_snapshot(const string& disk_src, const string& tag) snapshot->replace("ID", next_snapshot); snapshot->replace("DATE", static_cast(time(0))); - snapshot->replace("PARENT_ID", parent_id); - snapshot->replace("PARENT", source); + snapshot->replace("PARENT_ID", active); snapshot_template.set(snapshot); diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index a49b51a277..1641b304e2 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -4163,9 +4163,37 @@ int VirtualMachine::get_public_cloud_hypervisors( /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -//TODO SNAPSHOT clear_snapshot_disk (deletes) + +void VirtualMachine::clear_snapshot_disk() +{ + int num_disks; + vector disks; + VectorAttribute * disk; + + num_disks = obj_template->get("DISK", disks); + + for(int i=0; i(disks[i]); + + if ( disk == 0 ) + { + continue; + } + + if ( disk->vector_value("DISK_SNAPSHOT_ACTIVE") == "YES" ) + { + disk->remove("DISK_SNAPSHOT_ACTIVE"); + disk->remove("DISK_SNAPSHOT_ID"); + return; + } + } +} + +/* -------------------------------------------------------------------------- */ + int VirtualMachine::get_snapshot_disk(string& ds_id, string& tm_mad, - string& parent, string& snap_id) + string& disk_id, string& parent_id, string& snap_id) { vector disks; VectorAttribute * disk; @@ -4200,16 +4228,17 @@ int VirtualMachine::get_snapshot_disk(string& ds_id, string& tm_mad, return -1; } - tm_mad = disk->vector_value("TM_MAD"); - ds_id = disk->vector_value("DATASTORE_ID"); - snap_id = disk->vector_value("DISK_SNAPSHOT_ID"); + tm_mad = disk->vector_value("TM_MAD"); + ds_id = disk->vector_value("DATASTORE_ID"); + disk_id = disk->vector_value("DISK_ID"); + snap_id = disk->vector_value("DISK_SNAPSHOT_ID"); int isnap_id = strtol(snap_id.c_str(),NULL,0); - parent = it->second->get_snapshot_attribute(isnap_id, "PARENT"); + parent_id =it->second->get_snapshot_attribute(isnap_id,"PARENT_ID"); - if (parent.empty() || snap_id.empty() || tm_mad.empty() - || ds_id.empty()) + if (parent_id.empty() || snap_id.empty() || tm_mad.empty() + || ds_id.empty() || disk_id.empty()) { return -1; } @@ -4230,7 +4259,6 @@ int VirtualMachine::new_disk_snapshot(int did, const string& tag, string& error) int snap_id; VectorAttribute * disk; - string source; disk = get_disk(did); @@ -4240,21 +4268,20 @@ int VirtualMachine::new_disk_snapshot(int did, const string& tag, string& error) return -1; } - source = disk->vector_value("SOURCE"); it = snapshots.find(did); if ( it == snapshots.end() ) { - Snapshots * snap = new Snapshots(did); + Snapshots * snap = new Snapshots(did); - snap_id = snap->create_snapshot(source, tag); + snap_id = snap->create_snapshot(tag); - snapshots.insert(pair(did, snap)); + snapshots.insert(pair(did, snap)); } else { - snap_id = it->second->create_snapshot(source, tag); + snap_id = it->second->create_snapshot(tag); } disk->replace("DISK_SNAPSHOT_ACTIVE", "YES"); From 9bb5770f8649f6ea0ca2a779e7c7334c05566906 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Thu, 21 May 2015 14:52:36 +0200 Subject: [PATCH 14/83] feature #3782: Snapshot event triggers --- include/LifeCycleManager.h | 4 ++++ src/dm/DispatchManagerActions.cc | 7 ------- src/dm/DispatchManagerStates.cc | 1 + src/lcm/LifeCycleActions.cc | 2 +- src/lcm/LifeCycleManager.cc | 16 ++++++++++++++ src/lcm/LifeCycleStates.cc | 36 ++++++++++++++++++++++++++++++++ src/tm/TransferManagerDriver.cc | 4 ++++ 7 files changed, 62 insertions(+), 8 deletions(-) diff --git a/include/LifeCycleManager.h b/include/LifeCycleManager.h index 7c4e04e0e3..24d12bf1dd 100644 --- a/include/LifeCycleManager.h +++ b/include/LifeCycleManager.h @@ -278,6 +278,10 @@ private: void snapshot_delete_failure(int vid); + void disk_snapshot_success(int vid); + + void disk_snapshot_failure(int vid); + void deploy_action(int vid); void suspend_action(int vid); diff --git a/src/dm/DispatchManagerActions.cc b/src/dm/DispatchManagerActions.cc index 908e0c95f9..d678bd6f53 100644 --- a/src/dm/DispatchManagerActions.cc +++ b/src/dm/DispatchManagerActions.cc @@ -1697,13 +1697,9 @@ int DispatchManager::disk_snapshot_revert( NebulaLog::log("DiM", Log::ERROR, error_str); vm->unlock(); - return -1; } - vm->set_state(VirtualMachine::ACTIVE); - vm->set_state(VirtualMachine::DISK_SNAPSHOT_POWEROFF); - if (vm->revert_disk_snapshot(did, snap_id, error_str) == -1) { vm->unlock(); @@ -1714,8 +1710,5 @@ int DispatchManager::disk_snapshot_revert( vmpool->update(vm); - //TODO Regenerate Deployment FILE (and send it to host?) - //vmm->trigger(VirtualMachineManager::SNAPSHOT_CREATE,vid); - return 0; } diff --git a/src/dm/DispatchManagerStates.cc b/src/dm/DispatchManagerStates.cc index b58add4521..2fe21d9747 100644 --- a/src/dm/DispatchManagerStates.cc +++ b/src/dm/DispatchManagerStates.cc @@ -166,6 +166,7 @@ void DispatchManager::poweroff_success_action(int vid) vm->get_lcm_state() == VirtualMachine::HOTPLUG_PROLOG_POWEROFF || vm->get_lcm_state() == VirtualMachine::HOTPLUG_EPILOG_POWEROFF || vm->get_lcm_state() == VirtualMachine::PROLOG_MIGRATE_POWEROFF || + vm->get_lcm_state() == VirtualMachine::DISK_SNAPSHOT_POWEROFF || vm->get_lcm_state() == VirtualMachine::PROLOG_MIGRATE_POWEROFF_FAILURE)) { vm->set_state(VirtualMachine::POWEROFF); diff --git a/src/lcm/LifeCycleActions.cc b/src/lcm/LifeCycleActions.cc index bb8642812b..44d6fb3ed9 100644 --- a/src/lcm/LifeCycleActions.cc +++ b/src/lcm/LifeCycleActions.cc @@ -1243,7 +1243,7 @@ void LifeCycleManager::recover(VirtualMachine * vm, bool success) break; case VirtualMachine::DISK_SNAPSHOT_POWEROFF: - //TODO trigger lcm action + lcm_action = LifeCycleManager::DISK_SNAPSHOT_FAILURE; break; } diff --git a/src/lcm/LifeCycleManager.cc b/src/lcm/LifeCycleManager.cc index 0604f7f58a..84b61b5246 100644 --- a/src/lcm/LifeCycleManager.cc +++ b/src/lcm/LifeCycleManager.cc @@ -222,6 +222,14 @@ void LifeCycleManager::trigger(Actions action, int _vid) aname = "SNAPSHOT_DELETE_FAILURE"; break; + case DISK_SNAPSHOT_SUCCESS: + aname = "DISK_SNAPSHOT_SUCCESS"; + break; + + case DISK_SNAPSHOT_FAILURE: + aname = "DISK_SNAPSHOT_FAILURE"; + break; + case DEPLOY: aname = "DEPLOY"; break; @@ -447,6 +455,14 @@ void LifeCycleManager::do_action(const string &action, void * arg) { snapshot_delete_failure(vid); } + else if (action == "DISK_SNAPSHOT_SUCCESS") + { + disk_snapshot_success(vid); + } + else if (action == "DISK_SNAPSHOT_FAILURE") + { + disk_snapshot_failure(vid); + } else if (action == "DEPLOY") { deploy_action(vid); diff --git a/src/lcm/LifeCycleStates.cc b/src/lcm/LifeCycleStates.cc index 952b01113d..af13a58f19 100644 --- a/src/lcm/LifeCycleStates.cc +++ b/src/lcm/LifeCycleStates.cc @@ -1707,3 +1707,39 @@ void LifeCycleManager::saveas_hot_failure_action(int vid) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ + +void LifeCycleManager::disk_snapshot_success(int vid) +{ + VirtualMachine * vm; + + vm = vmpool->get(vid,true); + + if ( vm == 0 ) + { + return; + } + + if ( vm->get_lcm_state() == VirtualMachine::DISK_SNAPSHOT_POWEROFF ) + { + vm->log("LCM", Log::INFO, "VM Disk snapshot successfully taken."); + + vm->clear_snapshot_disk(); + + vmpool->update(vm); + + dm->trigger(DispatchManager::POWEROFF_SUCCESS,vid); + } + else + { + vm->log("LCM",Log::ERROR,"disk_snapshot_success, VM in a wrong state"); + } + + vm->unlock(); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void LifeCycleManager::disk_snapshot_failure(int vid) +{ +}; diff --git a/src/tm/TransferManagerDriver.cc b/src/tm/TransferManagerDriver.cc index 487e9801ff..877c4d7cdd 100644 --- a/src/tm/TransferManagerDriver.cc +++ b/src/tm/TransferManagerDriver.cc @@ -206,6 +206,10 @@ void TransferManagerDriver::protocol(const string& message) const lcm_action = LifeCycleManager::DETACH_FAILURE; break; + case VirtualMachine::DISK_SNAPSHOT_POWEROFF: + lcm_action = LifeCycleManager::DISK_SNAPSHOT_FAILURE; + break; + default: goto error_state; } From a5c04b47e69c919a9438592c4bc393a5b56bd7db Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Tue, 26 May 2015 11:24:34 +0200 Subject: [PATCH 15/83] feature #3782: Re-design of revert operation. New action for drivers, and new state. --- include/Snapshots.h | 4 +- include/TransferManager.h | 11 +++ include/VirtualMachine.h | 31 +++++-- share/doc/xsd/acct.xsd | 3 +- share/doc/xsd/vm.xsd | 3 +- src/dm/DispatchManagerActions.cc | 15 ++-- src/dm/DispatchManagerStates.cc | 1 + src/lcm/LifeCycleActions.cc | 3 + src/lcm/LifeCycleStates.cc | 86 ++++++++++++++++++- .../opennebula/client/vm/VirtualMachine.java | 6 +- src/oca/ruby/opennebula/virtual_machine.rb | 4 +- src/sunstone/OpenNebulaVNC.rb | 1 + src/tm/TransferManager.cc | 38 +++++--- src/tm/TransferManagerDriver.cc | 2 + src/vm/Snapshots.cc | 8 +- src/vm/VirtualMachine.cc | 76 +++++++++++++--- 16 files changed, 246 insertions(+), 46 deletions(-) diff --git a/include/Snapshots.h b/include/Snapshots.h index 7e27f58d25..054ca380b4 100644 --- a/include/Snapshots.h +++ b/include/Snapshots.h @@ -80,8 +80,10 @@ public: /** * Removes the snapshot from the list * @param id of the snapshot + * @param error if any + * @return 0 on success -1 otherwise */ - int delete_snapshot(unsigned int id); + int delete_snapshot(unsigned int id, string& error); /** * Set the given snapshot as active. Updates the values of the current diff --git a/include/TransferManager.h b/include/TransferManager.h index 448340d59f..aa3255f6ce 100644 --- a/include/TransferManager.h +++ b/include/TransferManager.h @@ -61,6 +61,7 @@ public: DRIVER_CANCEL, SAVEAS_HOT, SNAPSHOT_CREATE, + SNAPSHOT_REVERT, SNAPSHOT_DELETE, FINALIZE }; @@ -328,11 +329,21 @@ private: */ void saveas_hot_action(int vid); + /** + * This function performs a generic snapshot action + */ + void do_snapshot_action(int vid, const char * action); + /** * This function takes an snapshot of a disk */ void snapshot_create_action(int vid); + /** + * This function takes an snapshot of a disk + */ + void snapshot_revert_action(int vid); + /** * This function deletes an snapshot of a disk */ diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index 3b804e1896..c8669b2c91 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -156,7 +156,8 @@ public: BOOT_STOPPED_FAILURE = 48, PROLOG_RESUME_FAILURE = 49, PROLOG_UNDEPLOY_FAILURE = 50, - DISK_SNAPSHOT_POWEROFF = 51 + DISK_SNAPSHOT_POWEROFF = 51, + DISK_SNAPSHOT_REVERT_POWEROFF = 52 }; static int lcm_state_from_str(string& st, LcmState& state) @@ -213,6 +214,7 @@ public: else if ( st == "PROLOG_RESUME_FAILURE") { state = PROLOG_RESUME_FAILURE; } else if ( st == "PROLOG_UNDEPLOY_FAILURE") { state = PROLOG_UNDEPLOY_FAILURE; } else if ( st == "DISK_SNAPSHOT_POWEROFF") { state = DISK_SNAPSHOT_POWEROFF; } + else if ( st == "DISK_SNAPSHOT_REVERT_POWEROFF") { state = DISK_SNAPSHOT_REVERT_POWEROFF; } else {return -1;} return 0; @@ -272,6 +274,7 @@ public: case PROLOG_RESUME_FAILURE: st = "PROLOG_RESUME_FAILURE"; break; case PROLOG_UNDEPLOY_FAILURE: st = "PROLOG_UNDEPLOY_FAILURE"; break; case DISK_SNAPSHOT_POWEROFF: st = "DISK_SNAPSHOT_POWEROFF"; break; + case DISK_SNAPSHOT_REVERT_POWEROFF: st = "DISK_SNAPSHOT_REVERT_POWEROFF"; break; } return st; @@ -1522,21 +1525,37 @@ public: */ int revert_disk_snapshot(int disk_id, int snap_id, string& error); + /** + * Deletes the snap_id, the snapshot cannot be the current (active) one + * @param disk_id of the disk + * @param snap_id of the snapshot. It can be 0 to revert to the original + * disk + * @param error if any + * @return -1 if error + */ + int delete_disk_snapshot(int disk_id, int snap_id, string& error); + /** * Get information about the disk to take the snapshot from * @param ds_id id of the datastore * @param tm_mad used by the datastore * @param disk_id of the disk - * @param parent_id to take the snapshot from * @param snap_id of the snapshot */ - int get_snapshot_disk(string& ds_id, string& tm_mad, - string& disk_id, string& parent_id, string& snap_id); + int get_snapshot_disk(string& ds_id, string& tm_mad, string& disk_id, + string& snap_id); + /** + * Unset the current disk being snapshotted (reverted...) + */ + void clear_snapshot_disk(); /** - * Unset the current disk being snapshotted + * Set the disk as being snapshotted (reverted...) + * @param disk_id of the disk + * @param snap_id of the target snap_id */ - void clear_snapshot_disk(); + int set_snapshot_disk(int disk_id, int snap_id); + // ------------------------------------------------------------------------ // Snapshot related functions // ------------------------------------------------------------------------ diff --git a/share/doc/xsd/acct.xsd b/share/doc/xsd/acct.xsd index 7042c73510..c09c26bdb5 100644 --- a/share/doc/xsd/acct.xsd +++ b/share/doc/xsd/acct.xsd @@ -164,7 +164,8 @@ BOOT_STOPPED_FAILURE = 48, PROLOG_RESUME_FAILURE = 49, PROLOG_UNDEPLOY_FAILURE = 50, - DISK_SNAPSHOT_POWEROFF = 51 + DISK_SNAPSHOT_POWEROFF = 51, + DISK_SNAPSHOT_REVERT_POWEROFF = 52 --> diff --git a/share/doc/xsd/vm.xsd b/share/doc/xsd/vm.xsd index 06c8b3d975..493683cb5f 100644 --- a/share/doc/xsd/vm.xsd +++ b/share/doc/xsd/vm.xsd @@ -97,7 +97,8 @@ BOOT_STOPPED_FAILURE = 48, PROLOG_RESUME_FAILURE = 49, PROLOG_UNDEPLOY_FAILURE = 50, - DISK_SNAPSHOT_POWEROFF = 51 + DISK_SNAPSHOT_POWEROFF = 51, + DISK_SNAPSHOT_REVERT_POWEROFF = 52 --> diff --git a/src/dm/DispatchManagerActions.cc b/src/dm/DispatchManagerActions.cc index d678bd6f53..8128b9ae44 100644 --- a/src/dm/DispatchManagerActions.cc +++ b/src/dm/DispatchManagerActions.cc @@ -1643,9 +1643,6 @@ int DispatchManager::disk_snapshot_create( return -1; } - vm->set_state(VirtualMachine::ACTIVE); - vm->set_state(VirtualMachine::DISK_SNAPSHOT_POWEROFF); - snap_id = vm->new_disk_snapshot(did, tag, error_str); if (snap_id == -1) @@ -1654,6 +1651,9 @@ int DispatchManager::disk_snapshot_create( return -1; } + vm->set_state(VirtualMachine::ACTIVE); + vm->set_state(VirtualMachine::DISK_SNAPSHOT_POWEROFF); + vm->unlock(); vmpool->update(vm); @@ -1700,15 +1700,20 @@ int DispatchManager::disk_snapshot_revert( return -1; } - if (vm->revert_disk_snapshot(did, snap_id, error_str) == -1) + if (vm->set_snapshot_disk(did, snap_id) == -1) { vm->unlock(); return -1; } - vm->unlock(); + vm->set_state(VirtualMachine::ACTIVE); + vm->set_state(VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF); vmpool->update(vm); + vm->unlock(); + + tm->trigger(TransferManager::SNAPSHOT_REVERT, vid); + return 0; } diff --git a/src/dm/DispatchManagerStates.cc b/src/dm/DispatchManagerStates.cc index 2fe21d9747..47528b4ad4 100644 --- a/src/dm/DispatchManagerStates.cc +++ b/src/dm/DispatchManagerStates.cc @@ -167,6 +167,7 @@ void DispatchManager::poweroff_success_action(int vid) vm->get_lcm_state() == VirtualMachine::HOTPLUG_EPILOG_POWEROFF || vm->get_lcm_state() == VirtualMachine::PROLOG_MIGRATE_POWEROFF || vm->get_lcm_state() == VirtualMachine::DISK_SNAPSHOT_POWEROFF || + vm->get_lcm_state() == VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF || vm->get_lcm_state() == VirtualMachine::PROLOG_MIGRATE_POWEROFF_FAILURE)) { vm->set_state(VirtualMachine::POWEROFF); diff --git a/src/lcm/LifeCycleActions.cc b/src/lcm/LifeCycleActions.cc index 44d6fb3ed9..05d8b20f0a 100644 --- a/src/lcm/LifeCycleActions.cc +++ b/src/lcm/LifeCycleActions.cc @@ -969,6 +969,7 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose, int& imag break; case VirtualMachine::DISK_SNAPSHOT_POWEROFF: + case VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF: vm->clear_snapshot_disk(); vmpool->update(vm); @@ -1243,6 +1244,7 @@ void LifeCycleManager::recover(VirtualMachine * vm, bool success) break; case VirtualMachine::DISK_SNAPSHOT_POWEROFF: + case VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF: lcm_action = LifeCycleManager::DISK_SNAPSHOT_FAILURE; break; } @@ -1446,6 +1448,7 @@ void LifeCycleManager::retry(VirtualMachine * vm) case VirtualMachine::HOTPLUG_PROLOG_POWEROFF: case VirtualMachine::HOTPLUG_EPILOG_POWEROFF: case VirtualMachine::DISK_SNAPSHOT_POWEROFF: + case VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF: case VirtualMachine::RUNNING: case VirtualMachine::UNKNOWN: break; diff --git a/src/lcm/LifeCycleStates.cc b/src/lcm/LifeCycleStates.cc index af13a58f19..fdb131ac39 100644 --- a/src/lcm/LifeCycleStates.cc +++ b/src/lcm/LifeCycleStates.cc @@ -1721,13 +1721,40 @@ void LifeCycleManager::disk_snapshot_success(int vid) if ( vm->get_lcm_state() == VirtualMachine::DISK_SNAPSHOT_POWEROFF ) { - vm->log("LCM", Log::INFO, "VM Disk snapshot successfully taken."); + vm->log("LCM", Log::INFO, "VM disk snapshot successfully taken."); vm->clear_snapshot_disk(); vmpool->update(vm); - dm->trigger(DispatchManager::POWEROFF_SUCCESS,vid); + dm->trigger(DispatchManager::POWEROFF_SUCCESS, vid); + } + else if (vm->get_lcm_state()==VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF) + { + string disk_id, tm_mad, ds_id, snap_id, err; + + if (vm->get_snapshot_disk(ds_id, tm_mad, disk_id, snap_id) == -1) + { + vm->log("LCM", Log::INFO, "Active disk snapshot not found."); + } + else + { + int isnap_id = strtol(snap_id.c_str(),NULL,0); + int idisk_id = strtol(disk_id.c_str(),NULL,0); + + if (vm->revert_disk_snapshot(idisk_id, isnap_id, err)==-1) + { + vm->log("LCM", Log::INFO, "Error activating snapshot: " + err); + } + } + + vm->log("LCM", Log::INFO, "VM disk snapshot successfully reverted."); + + vm->clear_snapshot_disk(); + + vmpool->update(vm); + + dm->trigger(DispatchManager::POWEROFF_SUCCESS, vid); } else { @@ -1742,4 +1769,59 @@ void LifeCycleManager::disk_snapshot_success(int vid) void LifeCycleManager::disk_snapshot_failure(int vid) { + VirtualMachine * vm; + + vm = vmpool->get(vid,true); + + if ( vm == 0 ) + { + return; + } + + if ( vm->get_lcm_state() == VirtualMachine::DISK_SNAPSHOT_POWEROFF ) + { + string disk_id, tm_mad, ds_id, snap_id, err; + + vm->log("LCM",Log::ERROR,"Error taking disk snapshot"); + + if (vm->get_snapshot_disk(ds_id, tm_mad, disk_id, snap_id) == -1) + { + vm->log("LCM", Log::INFO, "Active disk snapshot not found." + " Remove failed snapshot manually."); + } + else + { + int isnap_id = strtol(snap_id.c_str(),NULL,0); + int idisk_id = strtol(disk_id.c_str(),NULL,0); + + if (vm->delete_disk_snapshot(idisk_id, isnap_id, err) == -1) + { + vm->log("LCM", Log::INFO, "Error deleting snapshot: " + err + + " Remove failed snapshot manually."); + } + } + + vm->clear_snapshot_disk(); + + vmpool->update(vm); + + dm->trigger(DispatchManager::POWEROFF_SUCCESS, vid); + } + else if (vm->get_lcm_state()==VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF) + { + vm->log("LCM",Log::ERROR,"Could not revert to disk snapshot."); + + vm->clear_snapshot_disk(); + + vmpool->update(vm); + + dm->trigger(DispatchManager::POWEROFF_SUCCESS, vid); + } + else + { + vm->log("LCM",Log::ERROR,"disk_snapshot_success, VM in a wrong state."); + } + + vm->unlock(); }; + diff --git a/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java b/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java index 5e8b99e56c..126fb96c97 100644 --- a/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java +++ b/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java @@ -128,7 +128,8 @@ public class VirtualMachine extends PoolElement{ "BOOT_STOPPED_FAILURE", "PROLOG_RESUME_FAILURE", "PROLOG_UNDEPLOY_FAILURE", - "DISK_SNAPSHOT_POWEROFF" + "DISK_SNAPSHOT_POWEROFF", + "DISK_SNAPSHOT_REVERT_POWEROFF" }; private static final String[] SHORT_LCM_STATES = @@ -184,7 +185,8 @@ public class VirtualMachine extends PoolElement{ "fail", // BOOT_STOPPED_FAILURE "fail", // PROLOG_RESUME_FAILURE "fail", // PROLOG_UNDEPLOY_FAILURE - "snap" // DISK_SNAPSHOT_POWEROFF + "snap", // DISK_SNAPSHOT_POWEROFF + "snap" // DISK_SNAPSHOT_REVERT_POWEROFF }; /** diff --git a/src/oca/ruby/opennebula/virtual_machine.rb b/src/oca/ruby/opennebula/virtual_machine.rb index f3b87a550f..2568e7f05d 100644 --- a/src/oca/ruby/opennebula/virtual_machine.rb +++ b/src/oca/ruby/opennebula/virtual_machine.rb @@ -105,6 +105,7 @@ module OpenNebula PROLOG_RESUME_FAILURE PROLOG_UNDEPLOY_FAILURE DISK_SNAPSHOT_POWEROFF + DISK_SNAPSHOT_REVERT_POWEROFF } SHORT_VM_STATES={ @@ -171,7 +172,8 @@ module OpenNebula "BOOT_STOPPED_FAILURE" => "fail", "PROLOG_RESUME_FAILURE" => "fail", "PROLOG_UNDEPLOY_FAILURE" => "fail", - "DISK_SNAPSHOT_POWEROFF" => "snap" + "DISK_SNAPSHOT_POWEROFF" => "snap", + "DISK_SNAPSHOT_REVERT_POWEROFF" => "snap" } MIGRATE_REASON=%w{NONE ERROR USER} diff --git a/src/sunstone/OpenNebulaVNC.rb b/src/sunstone/OpenNebulaVNC.rb index 9481df6ea4..377ef88797 100644 --- a/src/sunstone/OpenNebulaVNC.rb +++ b/src/sunstone/OpenNebulaVNC.rb @@ -84,6 +84,7 @@ VNC_STATES = [ #49, #PROLOG_RESUME_FAILURE #50, #PROLOG_UNDEPLOY_FAILURE #51, #DISK_SNAPSHOT_POWEROFF + #52, #DISK_SNAPSHOT_REVERT_POWEROFF ] class OpenNebulaVNC diff --git a/src/tm/TransferManager.cc b/src/tm/TransferManager.cc index 9a07a96953..84be34350d 100644 --- a/src/tm/TransferManager.cc +++ b/src/tm/TransferManager.cc @@ -143,6 +143,10 @@ void TransferManager::trigger(Actions action, int _vid) aname = "SNAPSHOT_CREATE"; break; + case SNAPSHOT_REVERT: + aname = "SNAPSHOT_REVERT"; + break; + case SNAPSHOT_DELETE: aname = "SNAPSHOT_DELETE"; break; @@ -390,6 +394,10 @@ void TransferManager::do_action(const string &action, void * arg) { snapshot_create_action(vid); } + else if (action == "SNAPSHOT_REVERT") + { + snapshot_revert_action(vid); + } else if (action == "SNAPSHOT_DELETE") { snapshot_delete_action(vid); @@ -2209,7 +2217,7 @@ void TransferManager::migrate_transfer_command( /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -void TransferManager::snapshot_create_action(int vid) +void TransferManager::do_snapshot_action(int vid, const char * snap_action) { string tm_mad; string ds_id; @@ -2226,6 +2234,8 @@ void TransferManager::snapshot_create_action(int vid) const TransferManagerDriver * tm_md; + Nebula& nd = Nebula::instance(); + // ------------------------------------------------------------------------ // Setup & Transfer script // ------------------------------------------------------------------------ @@ -2243,7 +2253,7 @@ void TransferManager::snapshot_create_action(int vid) goto error_common; } - if (vm->get_snapshot_disk(ds_id, tm_mad, disk_id, parent_id, snap_id) == -1) + if (vm->get_snapshot_disk(ds_id, tm_mad, disk_id, snap_id) == -1) { vm->log("TM", Log::ERROR, "Could not get disk information to" "take snapshot"); @@ -2265,12 +2275,11 @@ void TransferManager::snapshot_create_action(int vid) goto error_file; } - //SNAP_CREATE tm_mad host:remote_system_dir/disk.0 parentid snapid vmid dsid - xfr << "SNAP_CREATE " + //SNAP_CREATE tm_mad host:remote_system_dir/disk.0 snapid vmid dsid + xfr << snap_action << " " << tm_mad << " " << vm->get_hostname() << ":" << vm->get_remote_system_dir() << "/disk." << disk_id << " " - << parent_id << " " << snap_id << " " << vm->get_oid() << " " << ds_id @@ -2290,22 +2299,31 @@ error_driver: error_file: os << "disk_snapshot_create, could not open file: " << xfr_name; - os << ". You may need to manually clean hosts (previous & current)"; goto error_common; error_common: vm->log("TM", Log::ERROR, os); -//TODO (nd.get_lcm())->trigger(LifeCycleManager::SAVEAS_HOT_FAILURE, vid); + (nd.get_lcm())->trigger(LifeCycleManager::DISK_SNAPSHOT_FAILURE, vid); vm->unlock(); return; +} + +void TransferManager::snapshot_create_action(int vid) +{ + return do_snapshot_action(vid, "SNAP_CREATE"); }; -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +void TransferManager::snapshot_revert_action(int vid) +{ + return do_snapshot_action(vid, "SNAP_REVERT"); +}; -void TransferManager::snapshot_delete_action(int vid){}; +void TransferManager::snapshot_delete_action(int vid) +{ + return do_snapshot_action(vid, "SNAP_DELETE"); +}; /* ************************************************************************** */ /* MAD Loading */ diff --git a/src/tm/TransferManagerDriver.cc b/src/tm/TransferManagerDriver.cc index 877c4d7cdd..2c94cfac9f 100644 --- a/src/tm/TransferManagerDriver.cc +++ b/src/tm/TransferManagerDriver.cc @@ -148,6 +148,7 @@ void TransferManagerDriver::protocol(const string& message) const break; case VirtualMachine::DISK_SNAPSHOT_POWEROFF: + case VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF: lcm_action = LifeCycleManager::DISK_SNAPSHOT_SUCCESS; break; @@ -207,6 +208,7 @@ void TransferManagerDriver::protocol(const string& message) const break; case VirtualMachine::DISK_SNAPSHOT_POWEROFF: + case VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF: lcm_action = LifeCycleManager::DISK_SNAPSHOT_FAILURE; break; diff --git a/src/vm/Snapshots.cc b/src/vm/Snapshots.cc index ae1ba811e8..75c370aea1 100644 --- a/src/vm/Snapshots.cc +++ b/src/vm/Snapshots.cc @@ -18,8 +18,8 @@ Snapshots::Snapshots(int _disk_id): snapshot_template(false,'=',"SNAPSHOTS"), - next_snapshot(1), - active(0), + next_snapshot(0), + active(-1), disk_id(_disk_id) { snapshot_template.add("DISK_ID",_disk_id); @@ -104,12 +104,13 @@ int Snapshots::create_snapshot(const string& tag) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int Snapshots::delete_snapshot(unsigned int id) +int Snapshots::delete_snapshot(unsigned int id, string& error) { VectorAttribute * snapshot = get_snapshot(id); if (snapshot == 0) { + error = "Snapshot does not exists"; return -1; } @@ -119,6 +120,7 @@ int Snapshots::delete_snapshot(unsigned int id) if (current) { + error = "Cannot delete the active snapshot"; return -1; } diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index 1641b304e2..12fa284754 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -4164,6 +4164,25 @@ int VirtualMachine::get_public_cloud_hypervisors( /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +int VirtualMachine::set_snapshot_disk(int did, int snap_id) +{ + VectorAttribute * disk; + + disk = get_disk(did); + + if ( disk == 0 ) + { + return -1; + } + + disk->replace("DISK_SNAPSHOT_ACTIVE", "YES"); + disk->replace("DISK_SNAPSHOT_ID", snap_id); + + return 0; +} + +/* -------------------------------------------------------------------------- */ + void VirtualMachine::clear_snapshot_disk() { int num_disks; @@ -4193,7 +4212,7 @@ void VirtualMachine::clear_snapshot_disk() /* -------------------------------------------------------------------------- */ int VirtualMachine::get_snapshot_disk(string& ds_id, string& tm_mad, - string& disk_id, string& parent_id, string& snap_id) + string& disk_id, string& snap_id) { vector disks; VectorAttribute * disk; @@ -4228,17 +4247,12 @@ int VirtualMachine::get_snapshot_disk(string& ds_id, string& tm_mad, return -1; } - tm_mad = disk->vector_value("TM_MAD"); - ds_id = disk->vector_value("DATASTORE_ID"); - disk_id = disk->vector_value("DISK_ID"); - snap_id = disk->vector_value("DISK_SNAPSHOT_ID"); + tm_mad = disk->vector_value("TM_MAD"); + ds_id = disk->vector_value("DATASTORE_ID"); + disk_id = disk->vector_value("DISK_ID"); + snap_id = disk->vector_value("DISK_SNAPSHOT_ID"); - int isnap_id = strtol(snap_id.c_str(),NULL,0); - - parent_id =it->second->get_snapshot_attribute(isnap_id,"PARENT_ID"); - - if (parent_id.empty() || snap_id.empty() || tm_mad.empty() - || ds_id.empty() || disk_id.empty()) + if (snap_id.empty()||tm_mad.empty()||ds_id.empty()||disk_id.empty()) { return -1; } @@ -4268,7 +4282,6 @@ int VirtualMachine::new_disk_snapshot(int did, const string& tag, string& error) return -1; } - it = snapshots.find(did); if ( it == snapshots.end() ) @@ -4311,15 +4324,50 @@ int VirtualMachine::revert_disk_snapshot(int did, int snap_id, string& error) it = snapshots.find(did); - if ( it == snapshots.end() && snap_id != 0 ) + if (it == snapshots.end()) { error = "Snapshot does not exists"; return -1; } - else if ( it != snapshots.end() ) + else { rc = it->second->active_snapshot(snap_id, error); } return rc; } + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int VirtualMachine::delete_disk_snapshot(int did, int snap_id, string& error) +{ + map::iterator it; + int rc; + + VectorAttribute * disk; + string source; + + disk = get_disk(did); + + if ( disk == 0 ) + { + error = "DISK does not exists"; + return -1; + } + + it = snapshots.find(did); + + if (it == snapshots.end()) + { + error = "Snapshot does not exists"; + return -1; + } + else + { + rc = it->second->delete_snapshot(snap_id, error); + } + + return rc; +} + From b27d12e48de81e0f869356d8f188c0b42d12a1b3 Mon Sep 17 00:00:00 2001 From: Jaime Melis Date: Tue, 26 May 2015 12:02:43 +0200 Subject: [PATCH 16/83] Feature #3021: disallow root to run onehost sync --- src/cli/one_helper/onehost_helper.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cli/one_helper/onehost_helper.rb b/src/cli/one_helper/onehost_helper.rb index a9ed75ea51..44f262daa4 100644 --- a/src/cli/one_helper/onehost_helper.rb +++ b/src/cli/one_helper/onehost_helper.rb @@ -167,6 +167,11 @@ class OneHostHelper < OpenNebulaHelper::OneHelper NUM_THREADS = 15 def sync(host_ids, options) + if `id -u`.to_i == 0 || `id -G`.split.collect{|e| e.to_i}.include?(0) + STDERR.puts("Cannot run 'onehost sync' as root") + exit -1 + end + begin current_version = File.read(REMOTES_LOCATION+'/VERSION').strip rescue From 4f473093e61845fcf5d8f5f658ffd89145edcd72 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Tue, 26 May 2015 12:52:55 +0200 Subject: [PATCH 17/83] feature #3782: Deal with snapshot id=0 --- include/Snapshots.h | 2 +- src/vm/Snapshots.cc | 17 +++++++---------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/include/Snapshots.h b/include/Snapshots.h index 054ca380b4..9b4198b9e8 100644 --- a/include/Snapshots.h +++ b/include/Snapshots.h @@ -131,7 +131,7 @@ private: /** * Id of the active (current) snapshot, 0 represents the base image */ - unsigned int active; + int active; /** * Id of the disk associated with this snapshot list diff --git a/src/vm/Snapshots.cc b/src/vm/Snapshots.cc index 75c370aea1..cdad2ef2ba 100644 --- a/src/vm/Snapshots.cc +++ b/src/vm/Snapshots.cc @@ -145,19 +145,16 @@ int Snapshots::active_snapshot(unsigned int id, string& error) return 0; } - if ( id != 0 ) + snapshot = get_snapshot(id); + + if (snapshot == 0) { - snapshot = get_snapshot(id); - - if (snapshot == 0) - { - error = "Snapshot does not exists"; - return -1; - } - - snapshot->replace("ACTIVE", true); + error = "Snapshot does not exists"; + return -1; } + snapshot->replace("ACTIVE", true); + snapshot = get_snapshot(active); if (snapshot != 0) From 036862b1ad65350984dbec6515bf0e4294df3ed1 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Tue, 26 May 2015 13:52:40 +0200 Subject: [PATCH 18/83] feature #3782: Add children list. Rename PARENT_ID to PARENT --- include/Snapshots.h | 5 +-- src/cli/one_helper/onevm_helper.rb | 8 +++- src/dm/DispatchManagerActions.cc | 4 +- src/vm/Snapshots.cc | 67 ++++++++++++++++++++++++++++-- src/vm/VirtualMachine.cc | 16 +++++-- 5 files changed, 86 insertions(+), 14 deletions(-) diff --git a/include/Snapshots.h b/include/Snapshots.h index 9b4198b9e8..30149b2910 100644 --- a/include/Snapshots.h +++ b/include/Snapshots.h @@ -39,9 +39,8 @@ class VectorAttribute; * * : Description * : the snapshot was taken - * : backing for this snapshot, 0 for the original image - * : Opaque (driver specific) string representing the parent - * : Opaque (driver specific) string representing the snapshot + * : backing for this snapshot, -1 for the original image + * : comma separated list of children snapshots */ class Snapshots { diff --git a/src/cli/one_helper/onevm_helper.rb b/src/cli/one_helper/onevm_helper.rb index 19fdb61103..b2d080305b 100644 --- a/src/cli/one_helper/onevm_helper.rb +++ b/src/cli/one_helper/onevm_helper.rb @@ -966,7 +966,11 @@ class OneVMHelper < OpenNebulaHelper::OneHelper end column :PARENT, "Snapshot Parent ID", :size=>6 do |d| - d["PARENT_ID"] + d["PARENT"] + end + + column :CHILDREN, "Snapshot Children IDs", :size=>10 do |d| + d["CHILDREN"] end column :TAG, "Snapshot Tag", :left, :size=>45 do |d| @@ -977,7 +981,7 @@ class OneVMHelper < OpenNebulaHelper::OneHelper OpenNebulaHelper.time_to_str(d["DATE"]) end - default :AC, :ID, :DISK, :PARENT, :DATE, :TAG + default :AC, :ID, :DISK, :PARENT, :DATE, :CHILDREN, :TAG end # Convert snapshot data to an array diff --git a/src/dm/DispatchManagerActions.cc b/src/dm/DispatchManagerActions.cc index 8128b9ae44..063a7b7b50 100644 --- a/src/dm/DispatchManagerActions.cc +++ b/src/dm/DispatchManagerActions.cc @@ -1654,10 +1654,10 @@ int DispatchManager::disk_snapshot_create( vm->set_state(VirtualMachine::ACTIVE); vm->set_state(VirtualMachine::DISK_SNAPSHOT_POWEROFF); - vm->unlock(); - vmpool->update(vm); + vm->unlock(); + tm->trigger(TransferManager::SNAPSHOT_CREATE,vid); return 0; diff --git a/src/vm/Snapshots.cc b/src/vm/Snapshots.cc index cdad2ef2ba..4bacf92d94 100644 --- a/src/vm/Snapshots.cc +++ b/src/vm/Snapshots.cc @@ -15,6 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "Snapshots.h" +#include "NebulaUtil.h" Snapshots::Snapshots(int _disk_id): snapshot_template(false,'=',"SNAPSHOTS"), @@ -91,7 +92,33 @@ int Snapshots::create_snapshot(const string& tag) snapshot->replace("ID", next_snapshot); snapshot->replace("DATE", static_cast(time(0))); - snapshot->replace("PARENT_ID", active); + snapshot->replace("PARENT", active); + + if (active != -1) + { + VectorAttribute * parent = get_snapshot(active); + + if (parent == 0) + { + delete snapshot; + return -1; + } + + string children = parent->vector_value("CHILDREN"); + + if (children.empty()) + { + parent->replace("CHILDREN", next_snapshot); + } + else + { + ostringstream oss; + + oss << children << "," << next_snapshot; + + parent->replace("CHILDREN", oss.str()); + } + } snapshot_template.set(snapshot); @@ -106,6 +133,10 @@ int Snapshots::create_snapshot(const string& tag) int Snapshots::delete_snapshot(unsigned int id, string& error) { + int parent_id; + bool current; + string children; + VectorAttribute * snapshot = get_snapshot(id); if (snapshot == 0) @@ -114,8 +145,6 @@ int Snapshots::delete_snapshot(unsigned int id, string& error) return -1; } - bool current; - snapshot->vector_value("ACTIVE", current); if (current) @@ -124,6 +153,36 @@ int Snapshots::delete_snapshot(unsigned int id, string& error) return -1; } + snapshot->vector_value("CHILDREN", children); + + if (!children.empty()) + { + error = "Cannot delete snapshot with children"; + return -1; + } + + snapshot->vector_value("PARENT", parent_id); + + if (parent_id != -1) + { + set child_set; + + VectorAttribute * parent = get_snapshot(parent_id); + + if (parent != 0) + { + children = parent->vector_value("CHILDREN"); + + one_util::split_unique(children, ',', child_set); + + child_set.erase(id); + + children = one_util::join(child_set.begin(), child_set.end(), ','); + + parent->replace("CHILDREN", children); + } + } + snapshot_template.remove(snapshot); delete snapshot; @@ -140,7 +199,7 @@ int Snapshots::active_snapshot(unsigned int id, string& error) { VectorAttribute * snapshot; - if ( id == active ) + if (static_cast(id) == active) { return 0; } diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index 12fa284754..ca33cc3096 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -4290,15 +4290,25 @@ int VirtualMachine::new_disk_snapshot(int did, const string& tag, string& error) snap_id = snap->create_snapshot(tag); - snapshots.insert(pair(did, snap)); + if (snap_id != -1) + { + snapshots.insert(pair(did, snap)); + } + else + { + delete snap; + } } else { snap_id = it->second->create_snapshot(tag); } - disk->replace("DISK_SNAPSHOT_ACTIVE", "YES"); - disk->replace("DISK_SNAPSHOT_ID", snap_id); + if (snap_id != -1) + { + disk->replace("DISK_SNAPSHOT_ACTIVE", "YES"); + disk->replace("DISK_SNAPSHOT_ID", snap_id); + } return snap_id; } From aa4347023370a042178f63ec8da3ac2fc1b56496 Mon Sep 17 00:00:00 2001 From: Jaime Melis Date: Tue, 26 May 2015 15:11:49 +0200 Subject: [PATCH 19/83] Feature #3650: Specify the default auth driver in oned.conf --- include/UserPool.h | 5 ----- share/etc/oned.conf | 9 +++++++++ src/um/UserPool.cc | 13 ++++++++++--- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/include/UserPool.h b/include/UserPool.h index b94682c336..484f030b3d 100644 --- a/include/UserPool.h +++ b/include/UserPool.h @@ -187,11 +187,6 @@ public: */ static const char * PUBLIC_AUTH; - /** - * Name for the default auth driver to be used for not registered users - */ - static const char * DEFAULT_AUTH; - /** * Name for the default Sunstone server user */ diff --git a/share/etc/oned.conf b/share/etc/oned.conf index d32b5578a8..05b8647cac 100644 --- a/share/etc/oned.conf +++ b/share/etc/oned.conf @@ -703,6 +703,13 @@ HM_MAD = [ # defined all the modules available will be enabled # authz : list of authentication modules separated by commas # +# DEFAULT_AUTH: The default authentication driver to use when OpenNebula +# does not know the user and needs to authenticate it externally. The default +# value is "default", however as no "default" auth driver exists, there should +# be a symbolic link pointig to the actual authentication driver, example: +# 'default -> ldap', or simply use DEFAULT_AUTH = "ldap" and no symlink is +# required. +# # SESSION_EXPIRATION_TIME: Time in seconds to keep an authenticated token as # valid. During this time, the driver is not used. Use 0 to disable session # caching @@ -721,6 +728,8 @@ AUTH_MAD = [ authn = "ssh,x509,ldap,server_cipher,server_x509" ] +#DEFAULT_AUTH = "default" + SESSION_EXPIRATION_TIME = 900 #ENABLE_OTHER_PERMISSIONS = "YES" diff --git a/src/um/UserPool.cc b/src/um/UserPool.cc index fc50c7dee1..1400b66690 100644 --- a/src/um/UserPool.cc +++ b/src/um/UserPool.cc @@ -36,7 +36,6 @@ const char * UserPool::CORE_AUTH = "core"; const char * UserPool::SERVER_AUTH = "server*"; const char * UserPool::PUBLIC_AUTH = "public"; -const char * UserPool::DEFAULT_AUTH = "default"; const char * UserPool::SERVER_NAME = "serveradmin"; @@ -248,7 +247,7 @@ error_no_open: erro_exists: oss << "Password file " << filenames[i] << " already exists " - << "but OpenNebula is boostraping the database. Check your " + << "but OpenNebula is boostraping the database. Check your " << "database configuration in oned.conf."; goto error_common; @@ -713,6 +712,7 @@ bool UserPool::authenticate_external(const string& username, string mad_pass; string error_str; string tmp_str; + string default_auth; Nebula& nd = Nebula::instance(); AuthManager * authm = nd.get_authm(); @@ -734,7 +734,14 @@ bool UserPool::authenticate_external(const string& username, } //Initialize authentication request and call the driver - ar.add_authenticate(UserPool::DEFAULT_AUTH, username,"-",token); + nd.get_configuration_attribute("DEFAULT_AUTH",default_auth); + + if (default_auth.empty()) + { + default_auth = "default"; + } + + ar.add_authenticate(default_auth, username,"-",token); authm->trigger(AuthManager::AUTHENTICATE, &ar); ar.wait(); From d89ba1692aba4329773ec437f642b19480532c59 Mon Sep 17 00:00:00 2001 From: Jaime Melis Date: Tue, 26 May 2015 15:25:51 +0200 Subject: [PATCH 20/83] Feature #3650: Use NebulaTemplate to set the default value of DEFAULT_AUTH --- src/nebula/NebulaTemplate.cc | 7 +++++++ src/um/UserPool.cc | 5 ----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/nebula/NebulaTemplate.cc b/src/nebula/NebulaTemplate.cc index 1741404ae2..876310daf0 100644 --- a/src/nebula/NebulaTemplate.cc +++ b/src/nebula/NebulaTemplate.cc @@ -356,11 +356,18 @@ void OpenNebulaTemplate::set_conf_default() #******************************************************************************* # Auth Manager Configuration #******************************************************************************* +# DEFAULT_AUTH # SESSION_EXPIRATION_TIME # ENABLE_OTHER_PERMISSIONS # DEFAULT_UMASK #******************************************************************************* */ + // DEFAULT_AUTH + value = "default"; + + attribute = new SingleAttribute("DEFAULT_AUTH",value); + conf_default.insert(make_pair(attribute->name(),attribute)); + // SESSION_EXPIRATION_TIME value = "0"; diff --git a/src/um/UserPool.cc b/src/um/UserPool.cc index 1400b66690..808d8c829b 100644 --- a/src/um/UserPool.cc +++ b/src/um/UserPool.cc @@ -736,11 +736,6 @@ bool UserPool::authenticate_external(const string& username, //Initialize authentication request and call the driver nd.get_configuration_attribute("DEFAULT_AUTH",default_auth); - if (default_auth.empty()) - { - default_auth = "default"; - } - ar.add_authenticate(default_auth, username,"-",token); authm->trigger(AuthManager::AUTHENTICATE, &ar); From 4eb305b72166127d5cba95e61d87dbd10a41bf7a Mon Sep 17 00:00:00 2001 From: Jaime Melis Date: Tue, 26 May 2015 15:52:24 +0200 Subject: [PATCH 21/83] Feature #3650: Clarify documenation in oned.conf for DEFAULT_AUTH --- share/etc/oned.conf | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/share/etc/oned.conf b/share/etc/oned.conf index 05b8647cac..b942dc390d 100644 --- a/share/etc/oned.conf +++ b/share/etc/oned.conf @@ -703,12 +703,12 @@ HM_MAD = [ # defined all the modules available will be enabled # authz : list of authentication modules separated by commas # -# DEFAULT_AUTH: The default authentication driver to use when OpenNebula -# does not know the user and needs to authenticate it externally. The default -# value is "default", however as no "default" auth driver exists, there should -# be a symbolic link pointig to the actual authentication driver, example: -# 'default -> ldap', or simply use DEFAULT_AUTH = "ldap" and no symlink is -# required. +# DEFAULT_AUTH: The default authentication driver to use when OpenNebula does +# not know the user and needs to authenticate it externally. If you want to +# use "default" (not recommended, but supported for backwards compatibility +# reasons) make sure you create a symlink pointing to the actual authentication +# driver in /var/lib/one/remotes/auth, and add "default" to the 'auth' +# parameter in the 'AUTH_MAD' section. # # SESSION_EXPIRATION_TIME: Time in seconds to keep an authenticated token as # valid. During this time, the driver is not used. Use 0 to disable session From d3feae9b03d5c0e493a7ea4bf96787ccdc3d5084 Mon Sep 17 00:00:00 2001 From: Tino Vazquez Date: Tue, 26 May 2015 17:15:20 +0200 Subject: [PATCH 22/83] Bug #3818: Fix wrong polling in shutdown --- src/vmm_mad/remotes/vmware/shutdown | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vmm_mad/remotes/vmware/shutdown b/src/vmm_mad/remotes/vmware/shutdown index fbaac03238..50041948de 100755 --- a/src/vmm_mad/remotes/vmware/shutdown +++ b/src/vmm_mad/remotes/vmware/shutdown @@ -28,6 +28,7 @@ $: << RUBY_LIB_LOCATION $: << File.dirname(__FILE__) require 'vmware_driver' +require 'vi_driver' #------------------------------------------------------------------------------ # Wait the VM to shutdown TIMEOUT (xPOLL_INTERVAL) seconds. @@ -39,12 +40,14 @@ TIMEOUT=300 deploy_id = ARGV[0] host = ARGV[1] +VIDriver::initialize(host) + vmware_drv = VMwareDriver.new(host) vmware_drv.shutdown(deploy_id) count=0 -while (vmware_drv.poll(deploy_id).match(/STATE=(.*)/)[1] != "d") do +while (VIDriver::poll_vm(deploy_id).match(/STATE=(.*)/)[1] != "d") do sleep POLL_INTERVAL if count > TIMEOUT then OpenNebula.log_debug("Timeout reached and VM #{deploy_id} is still alive.") From dc318dd06467f41f478d1cd027cdb0b4279fc48b Mon Sep 17 00:00:00 2001 From: Jaime Melis Date: Tue, 26 May 2015 19:01:08 +0200 Subject: [PATCH 23/83] Bug #3807: Remove only rules for ATTACH=YES nics when doing a detach (deactivate method) --- src/vnm_mad/remotes/ebtables/Ebtables.rb | 7 +++++++ src/vnm_mad/remotes/lib/fw_driver.rb | 13 ++++++++++--- src/vnm_mad/remotes/lib/sg_driver.rb | 12 +++++++++--- src/vnm_mad/remotes/ovswitch/OpenvSwitch.rb | 6 ++++++ 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/vnm_mad/remotes/ebtables/Ebtables.rb b/src/vnm_mad/remotes/ebtables/Ebtables.rb index 931bd23308..cf1f29b788 100644 --- a/src/vnm_mad/remotes/ebtables/Ebtables.rb +++ b/src/vnm_mad/remotes/ebtables/Ebtables.rb @@ -62,8 +62,15 @@ class EbtablesVLAN < VNMMAD::VNMDriver def deactivate lock + attach_nic_id = @vm['TEMPLATE/NIC[ATTACH="YES"]/NIC_ID'] + process do |nic| + if attach_nic_id && attach_nic_id != nic[:nic_id] + next + end + mac = nic[:mac] + # remove 0-padding mac = mac.split(":").collect{|e| e.hex.to_s(16)}.join(":") diff --git a/src/vnm_mad/remotes/lib/fw_driver.rb b/src/vnm_mad/remotes/lib/fw_driver.rb index 513f7980ed..592b3f7f44 100644 --- a/src/vnm_mad/remotes/lib/fw_driver.rb +++ b/src/vnm_mad/remotes/lib/fw_driver.rb @@ -40,7 +40,7 @@ module VNMMAD lock vm_id = @vm['ID'] - + process do |nic| #:white_ports_tcp => iptables_range #:white_ports_udp => iptables_range @@ -93,8 +93,15 @@ module VNMMAD def deactivate lock - vm_id = @vm['ID'] + vm_id = @vm['ID'] + + attach_nic_id = @vm['TEMPLATE/NIC[ATTACH="YES"]/NIC_ID'] + process do |nic| + if attach_nic_id && attach_nic_id != nic[:nic_id] + next + end + chain = "one-#{vm_id}-#{nic[:network_id]}" iptables_out = `#{command(:iptables)} -n -v --line-numbers -L FORWARD` if m = iptables_out.match(/.*#{chain}.*/) @@ -196,4 +203,4 @@ module VNMMAD "#{command(:iptables)} #{rule}" end end -end \ No newline at end of file +end diff --git a/src/vnm_mad/remotes/lib/sg_driver.rb b/src/vnm_mad/remotes/lib/sg_driver.rb index bf2efea5f4..9a87b0ccbb 100644 --- a/src/vnm_mad/remotes/lib/sg_driver.rb +++ b/src/vnm_mad/remotes/lib/sg_driver.rb @@ -23,7 +23,7 @@ module VNMMAD DRIVER = "sg" XPATH_FILTER = "TEMPLATE/NIC" - + # Creates a new SG driver and scans SG Rules def initialize(vm, deploy_id = nil, hypervisor = nil) super(vm, XPATH_FILTER, deploy_id, hypervisor) @@ -48,7 +48,7 @@ module VNMMAD @security_group_rules = rules end - # Activate the rules, bootstrap iptables chains and set filter rules for + # Activate the rules, bootstrap iptables chains and set filter rules for # each VM NIC def activate deactivate @@ -68,7 +68,7 @@ module VNMMAD sg_ids.each do |sg_id| rules = @security_group_rules[sg_id] - sg = SGIPTables::SecurityGroupIPTables.new(@vm, nic, sg_id, + sg = SGIPTables::SecurityGroupIPTables.new(@vm, nic, sg_id, rules) begin @@ -92,7 +92,13 @@ module VNMMAD lock begin + attach_nic_id = @vm['TEMPLATE/NIC[ATTACH="YES"]/NIC_ID'] + @vm.nics.each do |nic| + if attach_nic_id && attach_nic_id != nic[:nic_id] + next + end + SGIPTables.nic_deactivate(@vm, nic) end rescue Exception => e diff --git a/src/vnm_mad/remotes/ovswitch/OpenvSwitch.rb b/src/vnm_mad/remotes/ovswitch/OpenvSwitch.rb index 8a1bd5e848..adb9e74a44 100644 --- a/src/vnm_mad/remotes/ovswitch/OpenvSwitch.rb +++ b/src/vnm_mad/remotes/ovswitch/OpenvSwitch.rb @@ -72,7 +72,13 @@ class OpenvSwitchVLAN < VNMMAD::VNMDriver def deactivate lock + attach_nic_id = @vm['TEMPLATE/NIC[ATTACH="YES"]/NIC_ID'] + process do |nic| + if attach_nic_id && attach_nic_id != nic[:nic_id] + next + end + @nic = nic # Remove flows From 83ac6188de4b77b31e8935ba4e6369482ff00fac Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Wed, 27 May 2015 16:29:41 +0200 Subject: [PATCH 24/83] feature #3782: New state to delete snapshots. Delete action OCA (Ruby), core and CLI --- include/DispatchManager.h | 17 +++ include/RequestManagerVirtualMachine.h | 17 +++ include/VirtualMachine.h | 5 +- share/doc/xsd/acct.xsd | 3 +- share/doc/xsd/vm.xsd | 3 +- src/cli/onevm | 15 ++- src/dm/DispatchManagerActions.cc | 62 +++++++++ src/dm/DispatchManagerStates.cc | 1 + src/lcm/LifeCycleActions.cc | 3 + src/lcm/LifeCycleStates.cc | 126 ++++++++---------- .../opennebula/client/vm/VirtualMachine.java | 6 +- src/oca/ruby/opennebula/virtual_machine.rb | 22 ++- src/rm/RequestManager.cc | 2 + src/rm/RequestManagerVirtualMachine.cc | 38 ++++++ src/sunstone/OpenNebulaVNC.rb | 1 + src/tm/TransferManagerDriver.cc | 2 + src/vm/Snapshots.cc | 9 +- src/vm/VirtualMachine.cc | 6 +- 18 files changed, 251 insertions(+), 87 deletions(-) diff --git a/include/DispatchManager.h b/include/DispatchManager.h index 02558f3eae..35df649ab4 100644 --- a/include/DispatchManager.h +++ b/include/DispatchManager.h @@ -396,6 +396,23 @@ public: int did, int snap_id, string& error_str); + + /** + * Deletes a disk snapshot + * + * @param vid VirtualMachine identification + * @param did DISK identification + * @param snap_id Snapshot to be restored + * @param error_str Error reason, if any + * + * @return 0 on success, -1 otherwise + */ + int disk_snapshot_delete( + int vid, + int did, + int snap_id, + string& error_str); + private: /** * Thread id for the Dispatch Manager diff --git a/include/RequestManagerVirtualMachine.h b/include/RequestManagerVirtualMachine.h index ac7fc030a6..9a3eb46f06 100644 --- a/include/RequestManagerVirtualMachine.h +++ b/include/RequestManagerVirtualMachine.h @@ -436,4 +436,21 @@ public: RequestAttributes& att); }; +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +class VirtualMachineDiskSnapshotDelete: public RequestManagerVirtualMachine +{ +public: + VirtualMachineDiskSnapshotDelete(): + RequestManagerVirtualMachine("VirtualMachineDiskSnapshotDelete", + "Deletes a disk snapshot", + "A:siii"){}; + + ~VirtualMachineDiskSnapshotDelete(){}; + + void request_execute(xmlrpc_c::paramList const& _paramList, + RequestAttributes& att); +}; + #endif diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index c8669b2c91..de7b6467b1 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -157,7 +157,8 @@ public: PROLOG_RESUME_FAILURE = 49, PROLOG_UNDEPLOY_FAILURE = 50, DISK_SNAPSHOT_POWEROFF = 51, - DISK_SNAPSHOT_REVERT_POWEROFF = 52 + DISK_SNAPSHOT_REVERT_POWEROFF = 52, + DISK_SNAPSHOT_DELETE_POWEROFF = 53 }; static int lcm_state_from_str(string& st, LcmState& state) @@ -215,6 +216,7 @@ public: else if ( st == "PROLOG_UNDEPLOY_FAILURE") { state = PROLOG_UNDEPLOY_FAILURE; } else if ( st == "DISK_SNAPSHOT_POWEROFF") { state = DISK_SNAPSHOT_POWEROFF; } else if ( st == "DISK_SNAPSHOT_REVERT_POWEROFF") { state = DISK_SNAPSHOT_REVERT_POWEROFF; } + else if ( st == "DISK_SNAPSHOT_DELETE_POWEROFF") { state = DISK_SNAPSHOT_DELETE_POWEROFF; } else {return -1;} return 0; @@ -275,6 +277,7 @@ public: case PROLOG_UNDEPLOY_FAILURE: st = "PROLOG_UNDEPLOY_FAILURE"; break; case DISK_SNAPSHOT_POWEROFF: st = "DISK_SNAPSHOT_POWEROFF"; break; case DISK_SNAPSHOT_REVERT_POWEROFF: st = "DISK_SNAPSHOT_REVERT_POWEROFF"; break; + case DISK_SNAPSHOT_DELETE_POWEROFF: st = "DISK_SNAPSHOT_DELETE_POWEROFF"; break; } return st; diff --git a/share/doc/xsd/acct.xsd b/share/doc/xsd/acct.xsd index c09c26bdb5..9b1b9d1870 100644 --- a/share/doc/xsd/acct.xsd +++ b/share/doc/xsd/acct.xsd @@ -165,7 +165,8 @@ PROLOG_RESUME_FAILURE = 49, PROLOG_UNDEPLOY_FAILURE = 50, DISK_SNAPSHOT_POWEROFF = 51, - DISK_SNAPSHOT_REVERT_POWEROFF = 52 + DISK_SNAPSHOT_REVERT_POWEROFF = 52, + DISK_SNAPSHOT_DELETE_POWEROFF = 53 --> diff --git a/share/doc/xsd/vm.xsd b/share/doc/xsd/vm.xsd index 493683cb5f..fb37186bf9 100644 --- a/share/doc/xsd/vm.xsd +++ b/share/doc/xsd/vm.xsd @@ -98,7 +98,8 @@ PROLOG_RESUME_FAILURE = 49, PROLOG_UNDEPLOY_FAILURE = 50, DISK_SNAPSHOT_POWEROFF = 51, - DISK_SNAPSHOT_REVERT_POWEROFF = 52 + DISK_SNAPSHOT_REVERT_POWEROFF = 52, + DISK_SNAPSHOT_DELETE_POWEROFF = 53 --> diff --git a/src/cli/onevm b/src/cli/onevm index 927e92bfea..4ae4f74cb6 100755 --- a/src/cli/onevm +++ b/src/cli/onevm @@ -800,8 +800,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do end disk_snapshot_revert_desc = <<-EOT.unindent - Reverts disk state to a previously taken snapshot. To revert - disk state to the base disk image use 0 as snapshot id + Reverts disk state to a previously taken snapshot. States: POWEROFF EOT @@ -813,6 +812,18 @@ cmd=CommandParser::CmdParser.new(ARGV) do end end + disk_snapshot_delete_desc = <<-EOT.unindent + Deletes a disk snapshot. + + States: POWEROFF + EOT + command :"disk-snapshot-delete", disk_snapshot_delete_desc, + :vmid, :diskid, :snapshot_id do + helper.perform_action(args[0],options,"disk snapshot deleted") do |o| + o.disk_snapshot_delete(args[1].to_i, args[2].to_i) + end + end + list_desc = <<-EOT.unindent Lists VMs in the pool EOT diff --git a/src/dm/DispatchManagerActions.cc b/src/dm/DispatchManagerActions.cc index 063a7b7b50..a80ff9c543 100644 --- a/src/dm/DispatchManagerActions.cc +++ b/src/dm/DispatchManagerActions.cc @@ -1717,3 +1717,65 @@ int DispatchManager::disk_snapshot_revert( return 0; } + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int DispatchManager::disk_snapshot_delete( + int vid, + int did, + int snap_id, + string& error_str) +{ + ostringstream oss; + + VirtualMachine * vm = vmpool->get(vid, true); + + if ( vm == 0 ) + { + oss << "Could not delete disk snapshot from VM " << vid + << ", VM does not exist" ; + error_str = oss.str(); + + NebulaLog::log("DiM", Log::ERROR, error_str); + + return -1; + } + + if ( vm->get_state() != VirtualMachine::POWEROFF || + vm->get_lcm_state() != VirtualMachine::LCM_INIT ) + { + oss << "Could not delete disk snapshot from VM " << vid + << ", wrong state " << vm->state_str() << "."; + error_str = oss.str(); + + NebulaLog::log("DiM", Log::ERROR, error_str); + + vm->unlock(); + return -1; + } + + if (vm->delete_disk_snapshot(did, snap_id, error_str) == -1) + { + vm->unlock(); + return -1; + } + + if (vm->set_snapshot_disk(did, snap_id) == -1) + { + vm->unlock(); + return -1; + } + + vm->set_state(VirtualMachine::ACTIVE); + vm->set_state(VirtualMachine::DISK_SNAPSHOT_DELETE_POWEROFF); + + vmpool->update(vm); + + vm->unlock(); + + tm->trigger(TransferManager::SNAPSHOT_DELETE, vid); + + return 0; +} + diff --git a/src/dm/DispatchManagerStates.cc b/src/dm/DispatchManagerStates.cc index 47528b4ad4..a7728b2490 100644 --- a/src/dm/DispatchManagerStates.cc +++ b/src/dm/DispatchManagerStates.cc @@ -168,6 +168,7 @@ void DispatchManager::poweroff_success_action(int vid) vm->get_lcm_state() == VirtualMachine::PROLOG_MIGRATE_POWEROFF || vm->get_lcm_state() == VirtualMachine::DISK_SNAPSHOT_POWEROFF || vm->get_lcm_state() == VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF || + vm->get_lcm_state() == VirtualMachine::DISK_SNAPSHOT_DELETE_POWEROFF || vm->get_lcm_state() == VirtualMachine::PROLOG_MIGRATE_POWEROFF_FAILURE)) { vm->set_state(VirtualMachine::POWEROFF); diff --git a/src/lcm/LifeCycleActions.cc b/src/lcm/LifeCycleActions.cc index 05d8b20f0a..ae844cfa8e 100644 --- a/src/lcm/LifeCycleActions.cc +++ b/src/lcm/LifeCycleActions.cc @@ -970,6 +970,7 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose, int& imag case VirtualMachine::DISK_SNAPSHOT_POWEROFF: case VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF: + case VirtualMachine::DISK_SNAPSHOT_DELETE_POWEROFF: vm->clear_snapshot_disk(); vmpool->update(vm); @@ -1245,6 +1246,7 @@ void LifeCycleManager::recover(VirtualMachine * vm, bool success) case VirtualMachine::DISK_SNAPSHOT_POWEROFF: case VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF: + case VirtualMachine::DISK_SNAPSHOT_DELETE_POWEROFF: lcm_action = LifeCycleManager::DISK_SNAPSHOT_FAILURE; break; } @@ -1449,6 +1451,7 @@ void LifeCycleManager::retry(VirtualMachine * vm) case VirtualMachine::HOTPLUG_EPILOG_POWEROFF: case VirtualMachine::DISK_SNAPSHOT_POWEROFF: case VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF: + case VirtualMachine::DISK_SNAPSHOT_DELETE_POWEROFF: case VirtualMachine::RUNNING: case VirtualMachine::UNKNOWN: break; diff --git a/src/lcm/LifeCycleStates.cc b/src/lcm/LifeCycleStates.cc index fdb131ac39..c45ca8284a 100644 --- a/src/lcm/LifeCycleStates.cc +++ b/src/lcm/LifeCycleStates.cc @@ -1710,58 +1710,50 @@ void LifeCycleManager::saveas_hot_failure_action(int vid) void LifeCycleManager::disk_snapshot_success(int vid) { - VirtualMachine * vm; + string disk_id, tm_mad, ds_id, snap_id, err; + int isnap_id, idisk_id; - vm = vmpool->get(vid,true); + VirtualMachine * vm = vmpool->get(vid,true); if ( vm == 0 ) { return; } - if ( vm->get_lcm_state() == VirtualMachine::DISK_SNAPSHOT_POWEROFF ) + switch (vm->get_lcm_state()) { - vm->log("LCM", Log::INFO, "VM disk snapshot successfully taken."); + case VirtualMachine::DISK_SNAPSHOT_POWEROFF: + case VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF: + vm->log("LCM", Log::INFO, "VM disk snapshot operation completed."); - vm->clear_snapshot_disk(); - - vmpool->update(vm); - - dm->trigger(DispatchManager::POWEROFF_SUCCESS, vid); - } - else if (vm->get_lcm_state()==VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF) - { - string disk_id, tm_mad, ds_id, snap_id, err; - - if (vm->get_snapshot_disk(ds_id, tm_mad, disk_id, snap_id) == -1) - { - vm->log("LCM", Log::INFO, "Active disk snapshot not found."); - } - else - { - int isnap_id = strtol(snap_id.c_str(),NULL,0); - int idisk_id = strtol(disk_id.c_str(),NULL,0); - - if (vm->revert_disk_snapshot(idisk_id, isnap_id, err)==-1) + if (vm->get_snapshot_disk(ds_id, tm_mad, disk_id, snap_id) != -1) { - vm->log("LCM", Log::INFO, "Error activating snapshot: " + err); + isnap_id = strtol(snap_id.c_str(),NULL,0); + idisk_id = strtol(disk_id.c_str(),NULL,0); + + vm->revert_disk_snapshot(idisk_id, isnap_id, err); } - } + break; - vm->log("LCM", Log::INFO, "VM disk snapshot successfully reverted."); + case VirtualMachine::DISK_SNAPSHOT_DELETE_POWEROFF: + vm->log("LCM", Log::INFO, "VM disk snapshot deleted."); + break; - vm->clear_snapshot_disk(); - - vmpool->update(vm); - - dm->trigger(DispatchManager::POWEROFF_SUCCESS, vid); - } - else - { - vm->log("LCM",Log::ERROR,"disk_snapshot_success, VM in a wrong state"); + default: + vm->log("LCM",Log::ERROR,"disk_snapshot_success, VM in a wrong state"); + vm->unlock(); + return; } + vm->clear_snapshot_disk(); + + vmpool->update(vm); + + dm->trigger(DispatchManager::POWEROFF_SUCCESS, vid); + vm->unlock(); + + return; } /* -------------------------------------------------------------------------- */ @@ -1769,59 +1761,49 @@ void LifeCycleManager::disk_snapshot_success(int vid) void LifeCycleManager::disk_snapshot_failure(int vid) { - VirtualMachine * vm; + string disk_id, tm_mad, ds_id, snap_id, err; + int isnap_id, idisk_id; - vm = vmpool->get(vid,true); + VirtualMachine * vm = vmpool->get(vid,true); if ( vm == 0 ) { return; } - if ( vm->get_lcm_state() == VirtualMachine::DISK_SNAPSHOT_POWEROFF ) + switch (vm->get_lcm_state()) { - string disk_id, tm_mad, ds_id, snap_id, err; + case VirtualMachine::DISK_SNAPSHOT_POWEROFF: + case VirtualMachine::DISK_SNAPSHOT_DELETE_POWEROFF: + vm->log("LCM", Log::ERROR, "VM disk snapshot operation failed."); - vm->log("LCM",Log::ERROR,"Error taking disk snapshot"); - - if (vm->get_snapshot_disk(ds_id, tm_mad, disk_id, snap_id) == -1) - { - vm->log("LCM", Log::INFO, "Active disk snapshot not found." - " Remove failed snapshot manually."); - } - else - { - int isnap_id = strtol(snap_id.c_str(),NULL,0); - int idisk_id = strtol(disk_id.c_str(),NULL,0); - - if (vm->delete_disk_snapshot(idisk_id, isnap_id, err) == -1) + if (vm->get_snapshot_disk(ds_id, tm_mad, disk_id, snap_id) != -1) { - vm->log("LCM", Log::INFO, "Error deleting snapshot: " + err - + " Remove failed snapshot manually."); + isnap_id = strtol(snap_id.c_str(),NULL,0); + idisk_id = strtol(disk_id.c_str(),NULL,0); + + vm->delete_disk_snapshot(idisk_id, isnap_id, err); } - } + break; - vm->clear_snapshot_disk(); + case VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF: + vm->log("LCM", Log::ERROR, "Could not revert to disk snapshot."); + break; - vmpool->update(vm); - - dm->trigger(DispatchManager::POWEROFF_SUCCESS, vid); + default: + vm->log("LCM",Log::ERROR,"disk_snapshot_failure, VM in a wrong state"); + vm->unlock(); + return; } - else if (vm->get_lcm_state()==VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF) - { - vm->log("LCM",Log::ERROR,"Could not revert to disk snapshot."); - vm->clear_snapshot_disk(); + vm->clear_snapshot_disk(); - vmpool->update(vm); + vmpool->update(vm); - dm->trigger(DispatchManager::POWEROFF_SUCCESS, vid); - } - else - { - vm->log("LCM",Log::ERROR,"disk_snapshot_success, VM in a wrong state."); - } + dm->trigger(DispatchManager::POWEROFF_SUCCESS, vid); vm->unlock(); -}; + + return; +} diff --git a/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java b/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java index 126fb96c97..d7e70bea57 100644 --- a/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java +++ b/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java @@ -129,7 +129,8 @@ public class VirtualMachine extends PoolElement{ "PROLOG_RESUME_FAILURE", "PROLOG_UNDEPLOY_FAILURE", "DISK_SNAPSHOT_POWEROFF", - "DISK_SNAPSHOT_REVERT_POWEROFF" + "DISK_SNAPSHOT_REVERT_POWEROFF", + "DISK_SNAPSHOT_DELETE_POWEROFF" }; private static final String[] SHORT_LCM_STATES = @@ -186,7 +187,8 @@ public class VirtualMachine extends PoolElement{ "fail", // PROLOG_RESUME_FAILURE "fail", // PROLOG_UNDEPLOY_FAILURE "snap", // DISK_SNAPSHOT_POWEROFF - "snap" // DISK_SNAPSHOT_REVERT_POWEROFF + "snap", // DISK_SNAPSHOT_REVERT_POWEROFF + "snap" // DISK_SNAPSHOT_DELETE_POWEROFF }; /** diff --git a/src/oca/ruby/opennebula/virtual_machine.rb b/src/oca/ruby/opennebula/virtual_machine.rb index 2568e7f05d..0b1d91a839 100644 --- a/src/oca/ruby/opennebula/virtual_machine.rb +++ b/src/oca/ruby/opennebula/virtual_machine.rb @@ -46,7 +46,8 @@ module OpenNebula :detachnic => "vm.detachnic", :recover => "vm.recover", :disksnapshotcreate => "vm.disksnapshotcreate", - :disksnapshotrevert => "vm.disksnapshotrevert" + :disksnapshotrevert => "vm.disksnapshotrevert", + :disksnapshotdelete => "vm.disksnapshotdelete" } VM_STATE=%w{INIT PENDING HOLD ACTIVE STOPPED SUSPENDED DONE FAILED @@ -106,6 +107,7 @@ module OpenNebula PROLOG_UNDEPLOY_FAILURE DISK_SNAPSHOT_POWEROFF DISK_SNAPSHOT_REVERT_POWEROFF + DISK_SNAPSHOT_DELETE_POWEROFF } SHORT_VM_STATES={ @@ -173,7 +175,8 @@ module OpenNebula "PROLOG_RESUME_FAILURE" => "fail", "PROLOG_UNDEPLOY_FAILURE" => "fail", "DISK_SNAPSHOT_POWEROFF" => "snap", - "DISK_SNAPSHOT_REVERT_POWEROFF" => "snap" + "DISK_SNAPSHOT_REVERT_POWEROFF" => "snap", + "DISK_SNAPSHOT_DELETE_POWEROFF" => "snap" } MIGRATE_REASON=%w{NONE ERROR USER} @@ -617,7 +620,7 @@ module OpenNebula end # Takes a new snapshot of a disk - # + # # @param disk_id [Integer] Id of the disk # @param tag [String] description for the snapshot # @@ -627,7 +630,7 @@ module OpenNebula end # Reverts disk state to a previously taken snapshot - # + # # @param disk_id [Integer] Id of the disk # @param snap_id [Integer] Id of the snapshot # @@ -637,6 +640,17 @@ module OpenNebula return call(VM_METHODS[:disksnapshotrevert], @pe_id, disk_id, snap_id) end + # Deletes a disk snapshot + # + # @param disk_id [Integer] Id of the disk + # @param snap_id [Integer] Id of the snapshot + # + # @return [nil, OpenNebula::Error] nil in case of success, Error + # otherwise + def disk_snapshot_delete(disk_id, snap_id) + return call(VM_METHODS[:disksnapshotdelete], @pe_id, disk_id, snap_id) + end + # Recovers an ACTIVE VM # # @param result [Integer] Recover with failure (0), success (1) or diff --git a/src/rm/RequestManager.cc b/src/rm/RequestManager.cc index 5465383a20..9d00465815 100644 --- a/src/rm/RequestManager.cc +++ b/src/rm/RequestManager.cc @@ -306,6 +306,7 @@ void RequestManager::register_xml_methods() xmlrpc_c::methodPtr vm_snap_delete(new VirtualMachineSnapshotDelete()); xmlrpc_c::methodPtr vm_dsnap_create(new VirtualMachineDiskSnapshotCreate()); xmlrpc_c::methodPtr vm_dsnap_revert(new VirtualMachineDiskSnapshotRevert()); + xmlrpc_c::methodPtr vm_dsnap_delete(new VirtualMachineDiskSnapshotDelete()); xmlrpc_c::methodPtr vm_recover(new VirtualMachineRecover()); xmlrpc_c::methodPtr vm_pool_acct(new VirtualMachinePoolAccounting()); @@ -464,6 +465,7 @@ void RequestManager::register_xml_methods() RequestManagerRegistry.addMethod("one.vm.snapshotdelete", vm_snap_delete); RequestManagerRegistry.addMethod("one.vm.disksnapshotcreate", vm_dsnap_create); RequestManagerRegistry.addMethod("one.vm.disksnapshotrevert", vm_dsnap_revert); + RequestManagerRegistry.addMethod("one.vm.disksnapshotdelete", vm_dsnap_delete); RequestManagerRegistry.addMethod("one.vm.recover", vm_recover); RequestManagerRegistry.addMethod("one.vmpool.info", vm_pool_info); diff --git a/src/rm/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc index ec106800c2..5e1051a409 100644 --- a/src/rm/RequestManagerVirtualMachine.cc +++ b/src/rm/RequestManagerVirtualMachine.cc @@ -2560,5 +2560,43 @@ void VirtualMachineDiskSnapshotRevert::request_execute( return; } + /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ + + +void VirtualMachineDiskSnapshotDelete::request_execute( + xmlrpc_c::paramList const& paramList, + RequestAttributes& att) +{ + Nebula& nd = Nebula::instance(); + DispatchManager * dm = nd.get_dm(); + + int rc; + string error_str; + + int id = xmlrpc_c::value_int(paramList.getInt(1)); + int did = xmlrpc_c::value_int(paramList.getInt(2)); + int snap_id = xmlrpc_c::value_int(paramList.getInt(3)); + + if ( vm_authorization(id, 0, 0, att, 0, 0, auth_op) == false ) + { + return; + } + + rc = dm->disk_snapshot_delete(id, did, snap_id, error_str); + + if ( rc != 0 ) + { + failure_response(ACTION, + request_error(error_str, ""), + att); + } + else + { + success_response(id, att); + } + + return; +} + diff --git a/src/sunstone/OpenNebulaVNC.rb b/src/sunstone/OpenNebulaVNC.rb index 377ef88797..457d7a0609 100644 --- a/src/sunstone/OpenNebulaVNC.rb +++ b/src/sunstone/OpenNebulaVNC.rb @@ -85,6 +85,7 @@ VNC_STATES = [ #50, #PROLOG_UNDEPLOY_FAILURE #51, #DISK_SNAPSHOT_POWEROFF #52, #DISK_SNAPSHOT_REVERT_POWEROFF + #53, #DISK_SNAPSHOT_DELETE_POWEROFF ] class OpenNebulaVNC diff --git a/src/tm/TransferManagerDriver.cc b/src/tm/TransferManagerDriver.cc index 2c94cfac9f..d7c6b16b19 100644 --- a/src/tm/TransferManagerDriver.cc +++ b/src/tm/TransferManagerDriver.cc @@ -149,6 +149,7 @@ void TransferManagerDriver::protocol(const string& message) const case VirtualMachine::DISK_SNAPSHOT_POWEROFF: case VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF: + case VirtualMachine::DISK_SNAPSHOT_DELETE_POWEROFF: lcm_action = LifeCycleManager::DISK_SNAPSHOT_SUCCESS; break; @@ -209,6 +210,7 @@ void TransferManagerDriver::protocol(const string& message) const case VirtualMachine::DISK_SNAPSHOT_POWEROFF: case VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF: + case VirtualMachine::DISK_SNAPSHOT_DELETE_POWEROFF: lcm_action = LifeCycleManager::DISK_SNAPSHOT_FAILURE; break; diff --git a/src/vm/Snapshots.cc b/src/vm/Snapshots.cc index 4bacf92d94..af055a615e 100644 --- a/src/vm/Snapshots.cc +++ b/src/vm/Snapshots.cc @@ -179,7 +179,14 @@ int Snapshots::delete_snapshot(unsigned int id, string& error) children = one_util::join(child_set.begin(), child_set.end(), ','); - parent->replace("CHILDREN", children); + if (children.empty()) + { + parent->remove("CHILDREN"); + } + else + { + parent->replace("CHILDREN", children); + } } } diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index ca33cc3096..9124a8f312 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -4278,7 +4278,7 @@ int VirtualMachine::new_disk_snapshot(int did, const string& tag, string& error) if ( disk == 0 ) { - error = "DISK does not exists"; + error = "VM disk does not exists"; return -1; } @@ -4328,7 +4328,7 @@ int VirtualMachine::revert_disk_snapshot(int did, int snap_id, string& error) if ( disk == 0 ) { - error = "DISK does not exists"; + error = "VM disk does not exists"; return -1; } @@ -4362,7 +4362,7 @@ int VirtualMachine::delete_disk_snapshot(int did, int snap_id, string& error) if ( disk == 0 ) { - error = "DISK does not exists"; + error = "VM disk does not exists"; return -1; } From f503bcbffee6865a05283cda85fa6f65262bc669 Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Thu, 28 May 2015 16:09:00 +0200 Subject: [PATCH 25/83] bug #3743: add Debian8 directory and fix ipset path in Debian 7 --- share/pkgs/{Debian => Debian7}/opennebula | 0 .../pkgs/{Debian => Debian7}/opennebula-econe | 0 .../pkgs/{Debian => Debian7}/opennebula-flow | 0 .../pkgs/{Debian => Debian7}/opennebula-gate | 0 .../pkgs/{Debian => Debian7}/opennebula-novnc | 0 .../{Debian => Debian7}/opennebula-sunstone | 0 share/pkgs/Debian7/opennebula.sudoers | 11 ++ share/pkgs/Debian8/opennebula | 128 ++++++++++++++++++ share/pkgs/Debian8/opennebula-econe | 106 +++++++++++++++ share/pkgs/Debian8/opennebula-flow | 94 +++++++++++++ share/pkgs/Debian8/opennebula-gate | 94 +++++++++++++ share/pkgs/Debian8/opennebula-novnc | 105 ++++++++++++++ share/pkgs/Debian8/opennebula-sunstone | 108 +++++++++++++++ .../{Debian => Debian8}/opennebula.sudoers | 0 14 files changed, 646 insertions(+) rename share/pkgs/{Debian => Debian7}/opennebula (100%) rename share/pkgs/{Debian => Debian7}/opennebula-econe (100%) rename share/pkgs/{Debian => Debian7}/opennebula-flow (100%) rename share/pkgs/{Debian => Debian7}/opennebula-gate (100%) rename share/pkgs/{Debian => Debian7}/opennebula-novnc (100%) rename share/pkgs/{Debian => Debian7}/opennebula-sunstone (100%) create mode 100644 share/pkgs/Debian7/opennebula.sudoers create mode 100755 share/pkgs/Debian8/opennebula create mode 100755 share/pkgs/Debian8/opennebula-econe create mode 100755 share/pkgs/Debian8/opennebula-flow create mode 100755 share/pkgs/Debian8/opennebula-gate create mode 100755 share/pkgs/Debian8/opennebula-novnc create mode 100755 share/pkgs/Debian8/opennebula-sunstone rename share/pkgs/{Debian => Debian8}/opennebula.sudoers (100%) diff --git a/share/pkgs/Debian/opennebula b/share/pkgs/Debian7/opennebula similarity index 100% rename from share/pkgs/Debian/opennebula rename to share/pkgs/Debian7/opennebula diff --git a/share/pkgs/Debian/opennebula-econe b/share/pkgs/Debian7/opennebula-econe similarity index 100% rename from share/pkgs/Debian/opennebula-econe rename to share/pkgs/Debian7/opennebula-econe diff --git a/share/pkgs/Debian/opennebula-flow b/share/pkgs/Debian7/opennebula-flow similarity index 100% rename from share/pkgs/Debian/opennebula-flow rename to share/pkgs/Debian7/opennebula-flow diff --git a/share/pkgs/Debian/opennebula-gate b/share/pkgs/Debian7/opennebula-gate similarity index 100% rename from share/pkgs/Debian/opennebula-gate rename to share/pkgs/Debian7/opennebula-gate diff --git a/share/pkgs/Debian/opennebula-novnc b/share/pkgs/Debian7/opennebula-novnc similarity index 100% rename from share/pkgs/Debian/opennebula-novnc rename to share/pkgs/Debian7/opennebula-novnc diff --git a/share/pkgs/Debian/opennebula-sunstone b/share/pkgs/Debian7/opennebula-sunstone similarity index 100% rename from share/pkgs/Debian/opennebula-sunstone rename to share/pkgs/Debian7/opennebula-sunstone diff --git a/share/pkgs/Debian7/opennebula.sudoers b/share/pkgs/Debian7/opennebula.sudoers new file mode 100644 index 0000000000..4f75c3eec7 --- /dev/null +++ b/share/pkgs/Debian7/opennebula.sudoers @@ -0,0 +1,11 @@ +Defaults:oneadmin !requiretty +Defaults:oneadmin secure_path = /sbin:/bin:/usr/sbin:/usr/bin + +Cmnd_Alias ONE_MISC = /bin/dd, /sbin/mkfs, /bin/sync +Cmnd_Alias ONE_NET = /sbin/brctl, /sbin/ebtables, /sbin/iptables, /sbin/ip, /usr/sbin/ipset +Cmnd_Alias ONE_LVM = /sbin/lvcreate, /sbin/lvremove, /sbin/lvrename, /sbin/lvs, /sbin/vgdisplay +Cmnd_Alias ONE_ISCSI = /usr/bin/iscsiadm, /usr/sbin/tgt-admin, /usr/sbin/tgtadm +Cmnd_Alias ONE_OVS = /usr/bin/ovs-ofctl, /usr/bin/ovs-vsctl +Cmnd_Alias ONE_XEN = /usr/sbin/xentop, /usr/sbin/xl, /usr/sbin/xm + +oneadmin ALL=(ALL) NOPASSWD: ONE_MISC, ONE_NET, ONE_LVM, ONE_ISCSI, ONE_OVS, ONE_XEN diff --git a/share/pkgs/Debian8/opennebula b/share/pkgs/Debian8/opennebula new file mode 100755 index 0000000000..9d923565b4 --- /dev/null +++ b/share/pkgs/Debian8/opennebula @@ -0,0 +1,128 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: opennebula +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Should-Start: mysql +# Should-Stop: mysql +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: OpenNebula init script +# Description: OpenNebula cloud initialisation script +### END INIT INFO + +# Author: Soren Hansen + +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="OpenNebula cloud" +NAME=one +DAEMON=/usr/bin/$NAME +DAEMON_ARGS="" +PIDFILE=/var/run/$NAME.pid +SCRIPTNAME=/etc/init.d/$NAME + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Load the VERBOSE setting and other rcS variables +. /lib/init/vars.sh + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.0-6) to ensure that this file is present. +. /lib/lsb/init-functions + +# +# Function that starts the daemon/service +# +do_start() +{ + mkdir -p /var/run/one /var/lock/one + chown oneadmin /var/run/one /var/lock/one + su oneadmin -s /bin/sh -c 'one start' +} + +# +# Function that stops the daemon/service +# +do_stop() +{ + su oneadmin -s /bin/sh -c 'one stop' +} + +do_start_sched() +{ + su oneadmin -s /bin/sh -c 'one start-sched' +} + +do_stop_sched() +{ + su oneadmin -s /bin/sh -c 'one stop-sched' +} + +case "$1" in + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + status) + status_of_proc "oned" "$NAME" && exit 0 || exit $? + ;; + restart|force-reload) + # + # If the "reload" option is implemented then remove the + # 'force-reload' alias + # + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + restart-sched) + log_daemon_msg "Restarting scheduler" + do_stop_sched + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + *) + echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload|status}" >&2 + exit 3 + ;; +esac + +: diff --git a/share/pkgs/Debian8/opennebula-econe b/share/pkgs/Debian8/opennebula-econe new file mode 100755 index 0000000000..31003b2b0d --- /dev/null +++ b/share/pkgs/Debian8/opennebula-econe @@ -0,0 +1,106 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: opennebula-econe +# Required-Start: $remote_fs +# Required-Stop: $remote_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: ECONE Server init script +# Description: OpenNebula ECONE service initialisation script +### END INIT INFO + +# Author: Tino Vázquez + +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="ECONE Service" +NAME=econe-server +DAEMON=/usr/bin/$NAME +DAEMON_ARGS="" +SCRIPTNAME=/etc/init.d/$NAME +PID_FILE=/var/run/one/econe-server.pid + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Load the VERBOSE setting and other rcS variables +. /lib/init/vars.sh + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.0-6) to ensure that this file is present. +. /lib/lsb/init-functions + +# +# Function that starts the daemon/service +# +do_start() +{ + mkdir -p /var/run/one /var/lock/one /var/log/one + chown oneadmin /var/run/one /var/lock/one /var/log/one + su oneadmin -s /bin/sh -c "$DAEMON start" +} + +# +# Function that stops the daemon/service +# +do_stop() +{ + su oneadmin -s /bin/sh -c "$DAEMON stop" +} + +case "$1" in + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + status) + ECONE_PID=`cat $PID_FILE` + kill -0 $ECONE_PID > /dev/null 2>&1 + if [ "$?" -eq "0" ]; then + log_daemon_msg "$NAME is running" + log_end_msg 0 + else + log_daemon_msg "$NAME is not running" + log_end_msg 1 + fi + ;; + restart|force-reload) + # + # If the "reload" option is implemented then remove the + # 'force-reload' alias + # + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + *) + echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 + exit 3 + ;; +esac + +: diff --git a/share/pkgs/Debian8/opennebula-flow b/share/pkgs/Debian8/opennebula-flow new file mode 100755 index 0000000000..6467dd9476 --- /dev/null +++ b/share/pkgs/Debian8/opennebula-flow @@ -0,0 +1,94 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: opennebula-flow +# Required-Start: $remote_fs +# Required-Stop: $remote_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: OneFlow init script +# Description: OpenNebula OneFlow service initialisation script +### END INIT INFO + +# Author: Tino Vázquez + +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="OneFlow Service" +NAME=oneflow-server +DAEMON=/usr/bin/$NAME +DAEMON_ARGS="" +SCRIPTNAME=/etc/init.d/$NAME + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Load the VERBOSE setting and other rcS variables +. /lib/init/vars.sh + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.0-6) to ensure that this file is present. +. /lib/lsb/init-functions + +# +# Function that starts the daemon/service +# +do_start() +{ + mkdir -p /var/run/one /var/lock/one /var/log/one + chown oneadmin /var/run/one /var/lock/one /var/log/one + su oneadmin -s /bin/sh -c "$DAEMON start" +} + +# +# Function that stops the daemon/service +# +do_stop() +{ + su oneadmin -s /bin/sh -c "$DAEMON stop" +} + +case "$1" in + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + restart|force-reload) + # + # If the "reload" option is implemented then remove the + # 'force-reload' alias + # + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + *) + echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2 + exit 3 + ;; +esac + +: diff --git a/share/pkgs/Debian8/opennebula-gate b/share/pkgs/Debian8/opennebula-gate new file mode 100755 index 0000000000..613f2614ef --- /dev/null +++ b/share/pkgs/Debian8/opennebula-gate @@ -0,0 +1,94 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: opennebula-gate +# Required-Start: $remote_fs +# Required-Stop: $remote_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: OneGate init script +# Description: OpenNebula OneGate service initialisation script +### END INIT INFO + +# Author: Tino Vázquez + +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="OneGate Service" +NAME=onegate-server +DAEMON=/usr/bin/$NAME +DAEMON_ARGS="" +SCRIPTNAME=/etc/init.d/$NAME + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Load the VERBOSE setting and other rcS variables +. /lib/init/vars.sh + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.0-6) to ensure that this file is present. +. /lib/lsb/init-functions + +# +# Function that starts the daemon/service +# +do_start() +{ + mkdir -p /var/run/one /var/lock/one /var/log/one + chown oneadmin /var/run/one /var/lock/one /var/log/one + su oneadmin -s /bin/sh -c "$DAEMON start" +} + +# +# Function that stops the daemon/service +# +do_stop() +{ + su oneadmin -s /bin/sh -c "$DAEMON stop" +} + +case "$1" in + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + restart|force-reload) + # + # If the "reload" option is implemented then remove the + # 'force-reload' alias + # + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + *) + echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2 + exit 3 + ;; +esac + +: diff --git a/share/pkgs/Debian8/opennebula-novnc b/share/pkgs/Debian8/opennebula-novnc new file mode 100755 index 0000000000..f583a5fe1c --- /dev/null +++ b/share/pkgs/Debian8/opennebula-novnc @@ -0,0 +1,105 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: opennebula-novnc +# Required-Start: $remote_fs +# Required-Stop: $remote_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: novnc init script +# Description: OpenNebula novnc server +### END INIT INFO + +# Author: Arnold Bechtoldt + +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="OpenNebula novnc server" +NAME=novnc-server +DAEMON=/usr/bin/$NAME +DAEMON_ARGS="" +SCRIPTNAME=/etc/init.d/opennebula-novnc + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Load the VERBOSE setting and other rcS variables +. /lib/init/vars.sh + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.0-6) to ensure that this file is present. +. /lib/lsb/init-functions + +# +# Function that starts the daemon/service +# +do_start() +{ + mkdir -p /var/lock/one /var/log/one + chown oneadmin /var/lock/one /var/log/one + su oneadmin -s /bin/sh -c "$DAEMON start" +} + +# +# Function that retrives the status of the daemon/service +# +do_status() +{ + su oneadmin -s /bin/sh -c "$DAEMON status" +} + +# +# Function that stops the daemon/service +# +do_stop() +{ + su oneadmin -s /bin/sh -c "$DAEMON stop" +} + +case "$1" in + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + status) + do_status && exit 0 || exit $? + ;; + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + restart|force-reload) + # + # If the "reload" option is implemented then remove the + # 'force-reload' alias + # + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + *) + echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 + exit 3 + ;; +esac + +: diff --git a/share/pkgs/Debian8/opennebula-sunstone b/share/pkgs/Debian8/opennebula-sunstone new file mode 100755 index 0000000000..34e9e1fbfb --- /dev/null +++ b/share/pkgs/Debian8/opennebula-sunstone @@ -0,0 +1,108 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: opennebula-sunstone +# Required-Start: $remote_fs +# Required-Stop: $remote_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Sunstone init script +# Description: OpenNebula Sunstone web interface cloud initialisation script +### END INIT INFO + +# Author: Jaime Melis + +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="Sunstone Web interface" +NAME=sunstone-server +DAEMON=/usr/bin/$NAME +DAEMON_ARGS="" +SCRIPTNAME=/etc/init.d/opennebula-sunstone +PID_FILE=/var/run/one/sunstone.pid + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Load the VERBOSE setting and other rcS variables +. /lib/init/vars.sh + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.0-6) to ensure that this file is present. +. /lib/lsb/init-functions + +# +# Function that starts the daemon/service +# +do_start() +{ + service opennebula-novnc start + mkdir -p /var/run/one /var/lock/one /var/log/one + chown oneadmin /var/run/one /var/lock/one /var/log/one + su oneadmin -s /bin/sh -c "$DAEMON start-sunstone" +} + +# +# Function that stops the daemon/service +# +do_stop() +{ + su oneadmin -s /bin/sh -c "$DAEMON stop-sunstone" + service opennebula-novnc stop +} + +case "$1" in + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + status) + SUNSTONE_PID=`cat $PID_FILE` + kill -0 $SUNSTONE_PID > /dev/null 2>&1 + if [ "$?" -eq "0" ]; then + log_daemon_msg "$NAME is running" + log_end_msg 0 + else + log_daemon_msg "$NAME is not running" + log_end_msg 1 + fi + ;; + restart|force-reload) + # + # If the "reload" option is implemented then remove the + # 'force-reload' alias + # + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + *) + echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 + exit 3 + ;; +esac + +: diff --git a/share/pkgs/Debian/opennebula.sudoers b/share/pkgs/Debian8/opennebula.sudoers similarity index 100% rename from share/pkgs/Debian/opennebula.sudoers rename to share/pkgs/Debian8/opennebula.sudoers From b0f72d5ad4ebe7e16098685c1287b093fa7a8a5a Mon Sep 17 00:00:00 2001 From: Jaime Melis Date: Thu, 28 May 2015 17:19:48 +0200 Subject: [PATCH 26/83] Feature #3782: Add ceph disk snapshot actions --- install.sh | 3 ++ src/tm_mad/ceph/delete | 36 +++++++++++++- src/tm_mad/ceph/snap_create | 99 +++++++++++++++++++++++++++++++++++++ src/tm_mad/ceph/snap_delete | 98 ++++++++++++++++++++++++++++++++++++ src/tm_mad/ceph/snap_revert | 97 ++++++++++++++++++++++++++++++++++++ 5 files changed, 331 insertions(+), 2 deletions(-) create mode 100755 src/tm_mad/ceph/snap_create create mode 100755 src/tm_mad/ceph/snap_delete create mode 100755 src/tm_mad/ceph/snap_revert diff --git a/install.sh b/install.sh index d29e734f5f..f8c64d2968 100755 --- a/install.sh +++ b/install.sh @@ -1094,6 +1094,9 @@ TM_CEPH_FILES="src/tm_mad/ceph/clone \ src/tm_mad/ceph/cpds \ src/tm_mad/ceph/premigrate \ src/tm_mad/ceph/postmigrate \ + src/tm_mad/ceph/snap_create \ + src/tm_mad/ceph/snap_delete \ + src/tm_mad/ceph/snap_revert \ src/tm_mad/ceph/delete" TM_DEV_FILES="src/tm_mad/dev/clone \ diff --git a/src/tm_mad/ceph/delete b/src/tm_mad/ceph/delete index ea0c7b1b99..3ac6b54a43 100755 --- a/src/tm_mad/ceph/delete +++ b/src/tm_mad/ceph/delete @@ -97,11 +97,43 @@ log "Deleting $DST_PATH" # drivers, is executed in the worker node and not in the CEPH frontend. DELETE_CMD=$(cat </dev/null) + + for child in \$CHILDREN; do + snap_id=\${child##*-} + child=\$child@\$snap_id + rm_children \$child + done + + $RBD snap unprotect \$rbd_snap + $RBD snap rm \$rbd_snap + fi + + $RBD rm \$rbd + } RBD_FORMAT=\$($RBD info $RBD_SRC | sed -n 's/.*format: // p') - $RBD rm $RBD_SRC + if [ "\$RBD_FORMAT" = "2" ]; then + has_snap_shots=\$($RBD info $RBD_SRC-0@0 2>/dev/null) + + if [ -n "\$has_snap_shots" ]; then + rm_children $RBD_SRC-0@0 + else + $RBD rm $RBD_SRC + fi + else + $RBD rm $RBD_SRC + fi if [ "\$RBD_FORMAT" = "2" ]; then $RBD snap unprotect $SRC@$RBD_SNAP diff --git a/src/tm_mad/ceph/snap_create b/src/tm_mad/ceph/snap_create new file mode 100755 index 0000000000..3bf3865f7d --- /dev/null +++ b/src/tm_mad/ceph/snap_create @@ -0,0 +1,99 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +# snap_create host:parent_image snap_id vmid ds_id + +SRC=$1 +SNAP_ID=$2 +VM_ID=$3 +DS_ID=$4 + +# Example +# SRC=ceph0:/var/lib/one//datastores/0/76/disk.0 +# SNAP_ID=1 +# VM_ID=76 +# DS_ID=100 + +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]/CEPH_USER) + +RBD_SRC="${XPATH_ELEMENTS[j++]}" +CEPH_USER="${XPATH_ELEMENTS[j++]}" + +RBD_DST="${RBD_SRC}-${VM_ID}-${DISK_ID}" + +#------------------------------------------------------------------------------- +# Create snapshots +#------------------------------------------------------------------------------- + +if [ -n "$CEPH_USER" ]; then + RBD="$RBD --id ${CEPH_USER}" +fi + +SNAP_CREATE_CMD=$(cat <&2 + exit 1 + fi + + $RBD snap create $RBD_DST@$SNAP_ID + $RBD snap protect $RBD_DST@$SNAP_ID + $RBD rename $RBD_DST $RBD_DST-$SNAP_ID + $RBD clone $RBD_DST-$SNAP_ID@$SNAP_ID $RBD_DST +EOF +) + +ssh_exec_and_log "$SRC_HOST" "$SNAP_CREATE_CMD" \ + "Error creating snapshot $RBD_DST@$SNAP_ID" + +exit 0 diff --git a/src/tm_mad/ceph/snap_delete b/src/tm_mad/ceph/snap_delete new file mode 100755 index 0000000000..bbc47db236 --- /dev/null +++ b/src/tm_mad/ceph/snap_delete @@ -0,0 +1,98 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +# snap_delete host:parent_image snap_id vmid ds_id + +SRC=$1 +SNAP_ID=$2 +VM_ID=$3 +DS_ID=$4 + +# Example +# SRC=ceph0:/var/lib/one//datastores/0/76/disk.0 +# SNAP_ID=1 +# VM_ID=76 +# DS_ID=100 + +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]/CEPH_USER) + +RBD_SRC="${XPATH_ELEMENTS[j++]}" +CEPH_USER="${XPATH_ELEMENTS[j++]}" + +RBD_DST="${RBD_SRC}-${VM_ID}-${DISK_ID}" + +#------------------------------------------------------------------------------- +# Create snapshots +#------------------------------------------------------------------------------- + +if [ -n "$CEPH_USER" ]; then + RBD="$RBD --id ${CEPH_USER}" +fi + +SNAP_DELETE_CMD=$(cat <&2 + exit 1 + fi + + $RBD snap unprotect $RBD_DST-$SNAP_ID@$SNAP_ID + $RBD snap rm $RBD_DST-$SNAP_ID@$SNAP_ID + $RBD rm $RBD_DST-$SNAP_ID +EOF +) + +ssh_exec_and_log "$SRC_HOST" "$SNAP_DELETE_CMD" \ + "Error deleting snapshot $RBD_DST-$SNAP_ID@$SNAP_ID" + +exit 0 diff --git a/src/tm_mad/ceph/snap_revert b/src/tm_mad/ceph/snap_revert new file mode 100755 index 0000000000..efba90ae25 --- /dev/null +++ b/src/tm_mad/ceph/snap_revert @@ -0,0 +1,97 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +# snap_revert host:parent_image snap_id vmid ds_id + +SRC=$1 +SNAP_ID=$2 +VM_ID=$3 +DS_ID=$4 + +# Example +# SRC=ceph0:/var/lib/one//datastores/0/76/disk.0 +# SNAP_ID=1 +# VM_ID=76 +# DS_ID=100 + +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]/CEPH_USER) + +RBD_SRC="${XPATH_ELEMENTS[j++]}" +CEPH_USER="${XPATH_ELEMENTS[j++]}" + +RBD_DST="${RBD_SRC}-${VM_ID}-${DISK_ID}" + +#------------------------------------------------------------------------------- +# Create snapshots +#------------------------------------------------------------------------------- + +if [ -n "$CEPH_USER" ]; then + RBD="$RBD --id ${CEPH_USER}" +fi + +SNAP_REVERT_CMD=$(cat <&2 + exit 1 + fi + + $RBD rm $RBD_DST + $RBD clone $RBD_DST-$SNAP_ID@$SNAP_ID $RBD_DST +EOF +) + +ssh_exec_and_log "$SRC_HOST" "$SNAP_REVERT_CMD" \ + "Error reverting snapshot $RBD_DST-$SNAP_ID@$SNAP_ID" + +exit 0 From f3c70ff374d0476fba1e0575bbd720f0fdf7724a Mon Sep 17 00:00:00 2001 From: Jaime Melis Date: Thu, 28 May 2015 17:30:01 +0200 Subject: [PATCH 27/83] Feature #3782: remove debug info --- src/tm_mad/ceph/snap_create | 6 ------ src/tm_mad/ceph/snap_delete | 6 ------ src/tm_mad/ceph/snap_revert | 6 ------ 3 files changed, 18 deletions(-) diff --git a/src/tm_mad/ceph/snap_create b/src/tm_mad/ceph/snap_create index 3bf3865f7d..2ee456d010 100755 --- a/src/tm_mad/ceph/snap_create +++ b/src/tm_mad/ceph/snap_create @@ -23,12 +23,6 @@ SNAP_ID=$2 VM_ID=$3 DS_ID=$4 -# Example -# SRC=ceph0:/var/lib/one//datastores/0/76/disk.0 -# SNAP_ID=1 -# VM_ID=76 -# DS_ID=100 - if [ -z "${ONE_LOCATION}" ]; then TMCOMMON=/var/lib/one/remotes/tm/tm_common.sh else diff --git a/src/tm_mad/ceph/snap_delete b/src/tm_mad/ceph/snap_delete index bbc47db236..e27810c8c3 100755 --- a/src/tm_mad/ceph/snap_delete +++ b/src/tm_mad/ceph/snap_delete @@ -23,12 +23,6 @@ SNAP_ID=$2 VM_ID=$3 DS_ID=$4 -# Example -# SRC=ceph0:/var/lib/one//datastores/0/76/disk.0 -# SNAP_ID=1 -# VM_ID=76 -# DS_ID=100 - if [ -z "${ONE_LOCATION}" ]; then TMCOMMON=/var/lib/one/remotes/tm/tm_common.sh else diff --git a/src/tm_mad/ceph/snap_revert b/src/tm_mad/ceph/snap_revert index efba90ae25..7b72c48c02 100755 --- a/src/tm_mad/ceph/snap_revert +++ b/src/tm_mad/ceph/snap_revert @@ -23,12 +23,6 @@ SNAP_ID=$2 VM_ID=$3 DS_ID=$4 -# Example -# SRC=ceph0:/var/lib/one//datastores/0/76/disk.0 -# SNAP_ID=1 -# VM_ID=76 -# DS_ID=100 - if [ -z "${ONE_LOCATION}" ]; then TMCOMMON=/var/lib/one/remotes/tm/tm_common.sh else From 4929b50b2b573d59b21d323b0682e1769ca845f1 Mon Sep 17 00:00:00 2001 From: Jaime Melis Date: Fri, 29 May 2015 14:02:51 +0200 Subject: [PATCH 28/83] Feature #3782: add support for snapshots of persistent images in ceph --- src/tm_mad/ceph/cpds | 5 ++++- src/tm_mad/ceph/snap_create | 8 +++++++- src/tm_mad/ceph/snap_delete | 10 ++++++++-- src/tm_mad/ceph/snap_revert | 8 +++++++- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/tm_mad/ceph/cpds b/src/tm_mad/ceph/cpds index ba800ec6bd..b4deda72b9 100755 --- a/src/tm_mad/ceph/cpds +++ b/src/tm_mad/ceph/cpds @@ -76,11 +76,14 @@ else RBD_DST="${RBD_SRC}-${VM_ID}-${DISK_ID}" fi +if [ -n "$SNAP_ID" ]; then + RBD_DST="${RBD_DST}-${SNAP_ID}@${SNAP_ID}" +fi + if [ -n "$CEPH_USER" ]; then RBD="$RBD --id ${CEPH_USER}" fi - ssh_exec_and_log "$SRC_HOST" "$RBD copy $RBD_DST $DST" \ "Error cloning $RBD_DST to $DST in $SRC_HOST" diff --git a/src/tm_mad/ceph/snap_create b/src/tm_mad/ceph/snap_create index 2ee456d010..8fc9242b7c 100755 --- a/src/tm_mad/ceph/snap_create +++ b/src/tm_mad/ceph/snap_create @@ -55,12 +55,18 @@ 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++]}" -RBD_DST="${RBD_SRC}-${VM_ID}-${DISK_ID}" +if [ "$CLONE" = "NO" ]; then + RBD_DST="${RBD_SRC}" +else + RBD_DST="${RBD_SRC}-${VM_ID}-${DISK_ID}" +fi #------------------------------------------------------------------------------- # Create snapshots diff --git a/src/tm_mad/ceph/snap_delete b/src/tm_mad/ceph/snap_delete index e27810c8c3..60f4c27f39 100755 --- a/src/tm_mad/ceph/snap_delete +++ b/src/tm_mad/ceph/snap_delete @@ -55,15 +55,21 @@ 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++]}" -RBD_DST="${RBD_SRC}-${VM_ID}-${DISK_ID}" +if [ "$CLONE" = "NO" ]; then + RBD_DST="${RBD_SRC}" +else + RBD_DST="${RBD_SRC}-${VM_ID}-${DISK_ID}" +fi #------------------------------------------------------------------------------- -# Create snapshots +# Delete snapshots #------------------------------------------------------------------------------- if [ -n "$CEPH_USER" ]; then diff --git a/src/tm_mad/ceph/snap_revert b/src/tm_mad/ceph/snap_revert index 7b72c48c02..63f8366563 100755 --- a/src/tm_mad/ceph/snap_revert +++ b/src/tm_mad/ceph/snap_revert @@ -55,12 +55,18 @@ 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++]}" -RBD_DST="${RBD_SRC}-${VM_ID}-${DISK_ID}" +if [ "$CLONE" = "NO" ]; then + RBD_DST="${RBD_SRC}" +else + RBD_DST="${RBD_SRC}-${VM_ID}-${DISK_ID}" +fi #------------------------------------------------------------------------------- # Create snapshots From b96c2e635ef4ac6e9918d8fc7744d4eb69f0d646 Mon Sep 17 00:00:00 2001 From: Jaime Melis Date: Fri, 29 May 2015 14:59:03 +0200 Subject: [PATCH 29/83] Bug #3732: The FILES datastores should use NO_DECOMPRESS = yes --- src/datastore_mad/remotes/fs/cp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/datastore_mad/remotes/fs/cp b/src/datastore_mad/remotes/fs/cp index e65991a68e..cfd9560d8c 100755 --- a/src/datastore_mad/remotes/fs/cp +++ b/src/datastore_mad/remotes/fs/cp @@ -52,6 +52,7 @@ done < <($XPATH /DS_DRIVER_ACTION_DATA/DATASTORE/BASE_PATH \ /DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/SAFE_DIRS \ /DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/BRIDGE_LIST \ /DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/STAGING_DIR \ + /DS_DRIVER_ACTION_DATA/DATASTORE/TYPE \ /DS_DRIVER_ACTION_DATA/IMAGE/PATH \ /DS_DRIVER_ACTION_DATA/IMAGE/TEMPLATE/MD5 \ /DS_DRIVER_ACTION_DATA/IMAGE/TEMPLATE/SHA1 \ @@ -65,6 +66,7 @@ RESTRICTED_DIRS="${XPATH_ELEMENTS[i++]}" SAFE_DIRS="${XPATH_ELEMENTS[i++]}" BRIDGE_LIST="${XPATH_ELEMENTS[i++]}" STAGING_DIR="${XPATH_ELEMENTS[i++]:-/var/tmp}" +TYPE="${XPATH_ELEMENTS[i++]}" SRC="${XPATH_ELEMENTS[i++]}" MD5="${XPATH_ELEMENTS[i++]}" SHA1="${XPATH_ELEMENTS[i++]}" @@ -76,6 +78,11 @@ IMAGE_HASH=`basename $DST` set_up_datastore "$BASE_PATH" "$RESTRICTED_DIRS" "$SAFE_DIRS" +# Disable auto-decompress for the 'files' datastores (type 2) +if [ "$TYPE" = "2" ]; then + NO_DECOMPRESS="${NO_DECOMPRESS:-yes}" +fi + if [ -n "$BRIDGE_LIST" ]; then DOWNLOADER_ARGS=`set_downloader_args "$MD5" "$SHA1" "$NO_DECOMPRESS" "$LIMIT_TRANSFER_BW" "$SRC" -` else From 0c3bee9ec36141cf1bac720894a19978373d7a0f Mon Sep 17 00:00:00 2001 From: Tino Vazquez Date: Fri, 29 May 2015 18:51:02 +0200 Subject: [PATCH 30/83] Feature #3767: Add support for resource pool confinment in vCenter drivers --- src/vmm_mad/remotes/vcenter/vcenter_driver.rb | 47 ++++++++++++++++++- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/src/vmm_mad/remotes/vcenter/vcenter_driver.rb b/src/vmm_mad/remotes/vcenter/vcenter_driver.rb index c65ae733da..9d7366db11 100644 --- a/src/vmm_mad/remotes/vcenter/vcenter_driver.rb +++ b/src/vmm_mad/remotes/vcenter/vcenter_driver.rb @@ -146,7 +146,50 @@ class VIClient # The associated resource pool for this connection ######################################################################## def resource_pool - return @cluster.resourcePool + rp_name = @one_host["TEMPLATE/VCENTER_RESOURCE_POOL"] + + if rp_name.nil? + @cluster.resourcePool + else + find_resource_pool(rp_name) + end + end + + ######################################################################## + # Searches the desired ResourcePool of the DataCenter for the current + # connection. Returns a RbVmomi::VIM::ResourcePool or the default pool + # if not found + # @param rpool [String] the ResourcePool name + ######################################################################## + def find_resource_pool(poolName) + baseEntity = @cluster + entityArray = poolName.split('/') + entityArray.each do |entityArrItem| + if entityArrItem != '' + if baseEntity.is_a? RbVmomi::VIM::Folder + baseEntity = baseEntity.childEntity.find { |f| + f.name == entityArrItem + } or return @cluster.resourcePool + elsif baseEntity.is_a? RbVmomi::VIM::ClusterComputeResource + baseEntity = baseEntity.resourcePool.resourcePool.find { |f| + f.name == entityArrItem + } or return @cluster.resourcePool + elsif baseEntity.is_a? RbVmomi::VIM::ResourcePool + baseEntity = baseEntity.resourcePool.find { |f| + f.name == entityArrItem + } or return @cluster.resourcePool + else + return @cluster.resourcePool + end + end + end + + if !baseEntity.is_a?(RbVmomi::VIM::ResourcePool) and + baseEntity.respond_to?(:resourcePool) + baseEntity = baseEntity.resourcePool + end + + baseEntity end ######################################################################## @@ -1083,7 +1126,7 @@ class VCenterVm " TYPE =\"vnc\",\n"\ " LISTEN =\"0.0.0.0\",\n"\ " PORT =\"#{vp[0][:value]}\"\n" - str << " ,KEYMAP =\"#{keymap[0][:value]}\"\n" if keymap[0] + str << " KEYMAP =\"#{keymap[0][:value]}\"\n" if keymap str << "]\n" end From 14557d9cd2ea579beb2d83ea5d857b66c951a81c Mon Sep 17 00:00:00 2001 From: Tino Vazquez Date: Sat, 30 May 2015 00:40:16 +0200 Subject: [PATCH 31/83] Fix lamely introduced bug --- src/vmm_mad/remotes/vcenter/vcenter_driver.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vmm_mad/remotes/vcenter/vcenter_driver.rb b/src/vmm_mad/remotes/vcenter/vcenter_driver.rb index 9d7366db11..6559f26cbf 100644 --- a/src/vmm_mad/remotes/vcenter/vcenter_driver.rb +++ b/src/vmm_mad/remotes/vcenter/vcenter_driver.rb @@ -1125,7 +1125,7 @@ class VCenterVm str << "GRAPHICS = [\n"\ " TYPE =\"vnc\",\n"\ " LISTEN =\"0.0.0.0\",\n"\ - " PORT =\"#{vp[0][:value]}\"\n" + " PORT =\"#{vp[0][:value]},\"\n" str << " KEYMAP =\"#{keymap[0][:value]}\"\n" if keymap str << "]\n" end From 3f54b6f611b76d7d0a73a958728192b12160cd65 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Sat, 30 May 2015 13:29:27 +0200 Subject: [PATCH 32/83] feature #3782: Update copy constructor for Template. It should purge before copying. Adds a generic clear() method, and use it in class implementation --- include/Template.h | 7 ++++++ src/template/Template.cc | 48 +++++++++++++++++++++------------------- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/include/Template.h b/include/Template.h index d368d41fcf..04d752c761 100644 --- a/include/Template.h +++ b/include/Template.h @@ -55,6 +55,8 @@ public: separator = t.separator; xml_root = t.xml_root; + attributes.clear(); + for (it = t.attributes.begin() ; it != t.attributes.end() ; it++) { attributes.insert(make_pair(it->first,(it->second)->clone())); @@ -127,6 +129,11 @@ public: */ string& to_str(string& str) const; + /** + * Clears all the attributes from the template + */ + void clear(); + /** * Sets a new attribute, the attribute MUST BE ALLOCATED IN THE HEAP, and * will be freed when the template destructor is called. diff --git a/src/template/Template.cc b/src/template/Template.cc index afab0f1f98..27c5d7f22a 100644 --- a/src/template/Template.cc +++ b/src/template/Template.cc @@ -16,14 +16,13 @@ #include "Template.h" #include "template_syntax.h" +#include "NebulaUtil.h" #include #include #include #include -#define TO_UPPER(S) transform(S.begin(),S.end(),S.begin(),(int(*)(int))toupper) - /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -524,7 +523,7 @@ bool Template::get( return false; } - TO_UPPER(sval); + one_util::toupper(sval); if ( sval == "YES" ) { @@ -747,18 +746,7 @@ void Template::rebuild_attributes(const xmlNode * root_element) Attribute * attr; - //Clear the template if not empty - if (!attributes.empty()) - { - multimap::iterator it; - - for ( it = attributes.begin(); it != attributes.end(); it++) - { - delete it->second; - } - - attributes.clear(); - } + clear(); // Get the root's children and try to build attributes. for (cur_node = root_element->children; @@ -976,17 +964,31 @@ void Template::remove_all_except_restricted(const vector &restricted_att remove(*res_it); } - multimap::iterator att_it; - - for ( att_it = attributes.begin(); att_it != attributes.end(); att_it++) - { - delete att_it->second; - } - - attributes.clear(); + clear(); for (res_it = restricted.begin(); res_it != restricted.end(); res_it++) { set(*res_it); } } + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void Template::clear() +{ + if (attributes.empty()) + { + return; + } + + multimap::iterator it; + + for ( it = attributes.begin(); it != attributes.end(); it++) + { + delete it->second; + } + + attributes.clear(); +} + From c2bf13fe00340e499846ce1ca92cc5e9b1c80b51 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Sat, 30 May 2015 13:31:25 +0200 Subject: [PATCH 33/83] feature #3782: Copy constructor for Snapshots. Used to transfer the snapshot lisk from VM disk to Image objects --- include/Snapshots.h | 17 +++++++++++++++++ src/vm/Snapshots.cc | 26 +++++++++++++++++++++++--- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/include/Snapshots.h b/include/Snapshots.h index 30149b2910..f6acd03441 100644 --- a/include/Snapshots.h +++ b/include/Snapshots.h @@ -47,6 +47,8 @@ class Snapshots public: Snapshots(int _disk_id); + Snapshots(const Snapshots& s); + virtual ~Snapshots(); // ************************************************************************* @@ -98,6 +100,15 @@ public: return disk_id; } + /** + * Removes the DISK_ID attribute to link the list to an Image + */ + void clear_disk_id() + { + disk_id = -1; + snapshot_template.erase("DISK_ID"); + }; + /** * Get Attribute from the given snapshot * @param id of the snapshot @@ -116,6 +127,12 @@ private: */ VectorAttribute * get_snapshot(unsigned int id); + /** + * Build the object internal representation from an initialized + * template + */ + void init(); + /** * Text representation of the snapshot pool. To be stored as part of the * VM or Image Templates diff --git a/src/vm/Snapshots.cc b/src/vm/Snapshots.cc index af055a615e..e2b0af92b7 100644 --- a/src/vm/Snapshots.cc +++ b/src/vm/Snapshots.cc @@ -17,15 +17,28 @@ #include "Snapshots.h" #include "NebulaUtil.h" +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + Snapshots::Snapshots(int _disk_id): snapshot_template(false,'=',"SNAPSHOTS"), next_snapshot(0), active(-1), disk_id(_disk_id) { - snapshot_template.add("DISK_ID",_disk_id); + if (_disk_id != -1) + { + snapshot_template.add("DISK_ID",_disk_id); + } }; +Snapshots::Snapshots(const Snapshots& s) +{ + snapshot_template = s.snapshot_template; + + init(); +} + Snapshots::~Snapshots(){}; /* -------------------------------------------------------------------------- */ @@ -40,6 +53,15 @@ int Snapshots::from_xml_node(const xmlNodePtr node) return -1; } + init(); + + return 0; +} + +/* -------------------------------------------------------------------------- */ + +void Snapshots::init() +{ vector vsnap; unsigned int id; @@ -74,8 +96,6 @@ int Snapshots::from_xml_node(const xmlNodePtr node) { disk_id = did; } - - return 0; } /* -------------------------------------------------------------------------- */ From 9e30da08c117d4eec48b49c21d87045d16efdb45 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Sat, 30 May 2015 13:33:06 +0200 Subject: [PATCH 34/83] feature #3782: Add snapshots to Image object. Transfer them back from VM disk --- include/Image.h | 16 +++++++++++ include/ImageManager.h | 10 +++++++ src/image/Image.cc | 26 +++++++++++++----- src/image/ImageManagerActions.cc | 46 ++++++++++++++++++++++++++++++++ src/vm/VirtualMachine.cc | 17 +++++++++--- 5 files changed, 106 insertions(+), 9 deletions(-) diff --git a/include/Image.h b/include/Image.h index 6fb6b977b2..4505eb247d 100644 --- a/include/Image.h +++ b/include/Image.h @@ -21,6 +21,7 @@ #include "ImageTemplate.h" #include "NebulaLog.h" #include "ObjectCollection.h" +#include "Snapshots.h" using namespace std; @@ -486,6 +487,16 @@ public: */ ImageTemplate * clone_template(const string& new_name) const; + /** + * Set the snapshots for this image + * @param snapshot list + */ + void set_snapshots(const Snapshots& s) + { + snapshots = s; + snapshots.clear_disk_id(); + } + private: // ------------------------------------------------------------------------- @@ -579,6 +590,11 @@ private: */ ObjectCollection img_clone_collection; + /** + * Snapshot list for this image + */ + Snapshots snapshots; + // ************************************************************************* // DataBase implementation (Private) // ************************************************************************* diff --git a/include/ImageManager.h b/include/ImageManager.h index 57d4c27060..0dd421c76e 100644 --- a/include/ImageManager.h +++ b/include/ImageManager.h @@ -26,6 +26,7 @@ using namespace std; extern "C" void * image_action_loop(void *arg); class Image; +class Snapshots; class Template; class ImageManager : public MadManager, public ActionListener @@ -189,6 +190,15 @@ public: */ void monitor_datastore(int ds_id); + /** + * Set the snapshots for the given image. The image MUST be persistent + * and of type OS or DATABLOCK. + * @param iid id of image + * @param s snapshot list + * @param failed the associated VM releasing the images is FAILED + */ + void set_image_snapshots(int iid, const Snapshots& s, bool failed); + private: /** * Generic name for the Image driver diff --git a/src/image/Image.cc b/src/image/Image.cc index de2c9fd543..521a64fb46 100644 --- a/src/image/Image.cc +++ b/src/image/Image.cc @@ -56,7 +56,8 @@ Image::Image(int _uid, ds_id(-1), ds_name(""), vm_collection("VMS"), - img_clone_collection("CLONES") + img_clone_collection("CLONES"), + snapshots(-1) { if (_image_template != 0) { @@ -334,11 +335,12 @@ error_common: string& Image::to_xml(string& xml) const { - string template_xml; - string perms_xml; - ostringstream oss; - string vm_collection_xml; - string clone_collection_xml; + string template_xml; + string perms_xml; + ostringstream oss; + string vm_collection_xml; + string clone_collection_xml; + string snapshots_xml; oss << "" << @@ -366,6 +368,7 @@ string& Image::to_xml(string& xml) const vm_collection.to_xml(vm_collection_xml) << img_clone_collection.to_xml(clone_collection_xml) << obj_template->to_xml(template_xml) << + snapshots.to_xml(snapshots_xml) << ""; xml = oss.str(); @@ -462,6 +465,17 @@ int Image::from_xml(const string& xml) ObjectXML::free_nodes(content); + content.clear(); + + ObjectXML::get_nodes("/IMAGE/SNAPSHOTS", content); + + if (!content.empty()) + { + rc += snapshots.from_xml_node(content[0]); + + ObjectXML::free_nodes(content); + content.clear(); + } if (rc != 0) { diff --git a/src/image/ImageManagerActions.cc b/src/image/ImageManagerActions.cc index a4651ab0af..e72de0f4dc 100644 --- a/src/image/ImageManagerActions.cc +++ b/src/image/ImageManagerActions.cc @@ -895,3 +895,49 @@ string * ImageManager::format_message( /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +void ImageManager::set_image_snapshots(int iid, const Snapshots& s, bool failed) +{ + Image * img = ipool->get(iid,true); + + if ( img == 0 ) + { + return; + } + + switch(img->get_type()) + { + case Image::OS: + case Image::DATABLOCK: + break; + + case Image::KERNEL: + case Image::RAMDISK: + case Image::CONTEXT: + case Image::CDROM: + img->unlock(); + return; + } + + switch (img->get_state()) + { + case Image::USED_PERS: + break; + + case Image::USED: + case Image::LOCKED: + case Image::CLONE: + case Image::DELETE: + case Image::INIT: + case Image::DISABLED: + case Image::READY: + case Image::ERROR: + img->unlock(); + return; + } + + img->set_snapshots(s); + + ipool->update(img); + + img->unlock(); +} diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index 9124a8f312..ec05c81029 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -2495,9 +2495,10 @@ int VirtualMachine::set_attach_nic(int nic_id) void VirtualMachine::release_disk_images() { - int iid; - int save_as_id; - int num_disks; + int iid; + int save_as_id; + int num_disks; + int did = -1; bool img_error; @@ -2523,6 +2524,15 @@ void VirtualMachine::release_disk_images() img_error = state != ACTIVE || lcm_state != EPILOG; + disk->vector_value("DISK_ID", did); + + map::iterator it = snapshots.find(did); + + if (it != snapshots.end()) + { + imagem->set_image_snapshots(iid, *(it->second), img_error); + } + if ( disk->vector_value("IMAGE_ID", iid) == 0 ) { imagem->release_image(oid, iid, img_error); @@ -2532,6 +2542,7 @@ void VirtualMachine::release_disk_images() { imagem->release_image(oid, save_as_id, img_error); } + } } From 82eac63f124d8206574dfab257069708660da7ca Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Mon, 1 Jun 2015 19:25:02 +0200 Subject: [PATCH 35/83] feature #3782: Assignment copy constructor for Snapshots. Clear disk_id --- include/Snapshots.h | 20 ++++++++++++++++++++ src/vm/Snapshots.cc | 27 ++++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/include/Snapshots.h b/include/Snapshots.h index f6acd03441..0f88ca875d 100644 --- a/include/Snapshots.h +++ b/include/Snapshots.h @@ -49,6 +49,8 @@ public: Snapshots(const Snapshots& s); + Snapshots& operator= (const Snapshots& s); + virtual ~Snapshots(); // ************************************************************************* @@ -109,6 +111,24 @@ public: snapshot_template.erase("DISK_ID"); }; + /** + * Sets the disk id for this snapshot list + * @param did the id + */ + void set_disk_id(int did) + { + disk_id = did; + snapshot_template.replace("DISK_ID", did); + } + + /** + * @return number of snapshots in the list + */ + unsigned int size() + { + return snapshot_pool.size(); + } + /** * Get Attribute from the given snapshot * @param id of the snapshot diff --git a/src/vm/Snapshots.cc b/src/vm/Snapshots.cc index e2b0af92b7..a7876af3e8 100644 --- a/src/vm/Snapshots.cc +++ b/src/vm/Snapshots.cc @@ -32,13 +32,34 @@ Snapshots::Snapshots(int _disk_id): } }; -Snapshots::Snapshots(const Snapshots& s) +Snapshots::Snapshots(const Snapshots& s): + snapshot_template(s.snapshot_template), + next_snapshot(0), + active(-1), + disk_id(-1) { - snapshot_template = s.snapshot_template; - init(); } + +Snapshots& Snapshots::operator= (const Snapshots& s) +{ + if (this != &s) + { + next_snapshot = s.next_snapshot; + active = s.active; + disk_id = s.disk_id; + + snapshot_template = s.snapshot_template; + + snapshot_pool.clear(); + + init(); + } + + return *this; +} + Snapshots::~Snapshots(){}; /* -------------------------------------------------------------------------- */ From a841b12e944bf63c958366abad0269d366709bb1 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Mon, 1 Jun 2015 19:26:03 +0200 Subject: [PATCH 36/83] feature #3782: Copy assignment operator for Templates --- include/Template.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/include/Template.h b/include/Template.h index 04d752c761..ae07a846b2 100644 --- a/include/Template.h +++ b/include/Template.h @@ -63,6 +63,27 @@ public: } } + Template& operator=(const Template& t) + { + multimap::const_iterator it; + + if (this != &t) + { + replace_mode = t.replace_mode; + separator = t.separator; + xml_root = t.xml_root; + + attributes.clear(); + + for (it = t.attributes.begin() ; it != t.attributes.end() ; it++) + { + attributes.insert(make_pair(it->first,(it->second)->clone())); + } + } + + return *this; + } + /** * The class destructor frees all the attributes conforming the template */ From e599187ad578bdc97e0bc192e8227f968e0b9913 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Mon, 1 Jun 2015 19:28:37 +0200 Subject: [PATCH 37/83] feature #3782: Copy snapshots from Image to VM disks, and back. Still needs to do the same on attach dettach operations --- include/ImagePool.h | 3 +++ include/VirtualMachine.h | 1 + src/dm/DispatchManagerActions.cc | 2 ++ src/image/ImagePool.cc | 10 +++++++++ src/vm/VirtualMachine.cc | 36 +++++++++++++++++++++++++------- 5 files changed, 44 insertions(+), 8 deletions(-) diff --git a/include/ImagePool.h b/include/ImagePool.h index 52d932d86b..5c35b0842d 100644 --- a/include/ImagePool.h +++ b/include/ImagePool.h @@ -29,6 +29,7 @@ #include class AuthRequest; +class Snapshots; using namespace std; @@ -158,6 +159,7 @@ public: * or the default one * @param uid of VM owner (to look for the image id within its images) * @param image_id on success returns the acquired image id + * @param snaps list of snapshots associated to this image * @param error_str string describing the error * * @return 0 on success, -1 otherwise @@ -169,6 +171,7 @@ public: string& dev_prefix, int uid, int& image_id, + Snapshots ** snaps, string& error_str); /** * Generates an Authorization token for the DISK attribute diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index de7b6467b1..2c72fe6abe 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -1398,6 +1398,7 @@ public: int max_disk_id, int uid, int& image_id, + Snapshots ** snap, string& error_str); /** * Returns the disk that is waiting for an attachment action diff --git a/src/dm/DispatchManagerActions.cc b/src/dm/DispatchManagerActions.cc index a80ff9c543..0b91429051 100644 --- a/src/dm/DispatchManagerActions.cc +++ b/src/dm/DispatchManagerActions.cc @@ -905,6 +905,7 @@ int DispatchManager::attach(int vid, set used_targets; VectorAttribute * disk; + Snapshots * snap; VirtualMachine * vm = vmpool->get(vid, true); @@ -958,6 +959,7 @@ int DispatchManager::attach(int vid, max_disk_id, uid, image_id, + &snap, error_str); vm = vmpool->get(vid, true); diff --git a/src/image/ImagePool.cc b/src/image/ImagePool.cc index 9a174d3d91..76fbbb1b92 100644 --- a/src/image/ImagePool.cc +++ b/src/image/ImagePool.cc @@ -19,6 +19,7 @@ /* ************************************************************************** */ #include "ImagePool.h" +#include "Snapshots.h" #include "AuthManager.h" #include "Nebula.h" #include "PoolObjectAuth.h" @@ -313,6 +314,7 @@ int ImagePool::disk_attribute(int vm_id, string& dev_prefix, int uid, int& image_id, + Snapshots ** snap, string& error_str) { string source; @@ -326,6 +328,8 @@ int ImagePool::disk_attribute(int vm_id, Nebula& nd = Nebula::instance(); ImageManager * imagem = nd.get_imagem(); + *snap = 0; + if (!(source = disk->vector_value("IMAGE")).empty()) { int uiid = get_disk_uid(disk,uid); @@ -412,6 +416,12 @@ int ImagePool::disk_attribute(int vm_id, image_id = img->get_oid(); datastore_id = img->get_ds_id(); + if (img->snapshots.size() > 0) + { + *snap = new Snapshots(img->snapshots); + (*snap)->set_disk_id(disk_id); + } + img->unlock(); if (rc == -1) diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index ec05c81029..74f29dd17f 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -1798,6 +1798,8 @@ int VirtualMachine::get_disk_images(string& error_str) // ------------------------------------------------------------------------- for(int i=0; i(disks[i]); if ( disk == 0 ) @@ -1812,9 +1814,22 @@ int VirtualMachine::get_disk_images(string& error_str) dev_prefix, uid, image_id, + &snap, error_str); if (rc == 0 ) { + if (snap != 0) + { + if (img_type == Image::OS || img_type == Image::DATABLOCK) + { + snapshots.insert(pair(i, snap)); + } + else + { + delete snap; + } + } + acquired_images.push_back(image_id); target = disk->vector_value("TARGET"); @@ -2004,6 +2019,7 @@ VectorAttribute * VirtualMachine::set_up_attach_disk( int max_disk_id, int uid, int& image_id, + Snapshots ** snap, string& error_str) { vector disks; @@ -2051,6 +2067,7 @@ VectorAttribute * VirtualMachine::set_up_attach_disk( dev_prefix, uid, image_id, + snap, error_str); if ( rc != 0 ) { @@ -2071,7 +2088,9 @@ VectorAttribute * VirtualMachine::set_up_attach_disk( imagem->release_image(vm_id, image_id, false); + delete snap; delete new_disk; + return 0; } } @@ -2524,17 +2543,18 @@ void VirtualMachine::release_disk_images() img_error = state != ACTIVE || lcm_state != EPILOG; - disk->vector_value("DISK_ID", did); - - map::iterator it = snapshots.find(did); - - if (it != snapshots.end()) - { - imagem->set_image_snapshots(iid, *(it->second), img_error); - } if ( disk->vector_value("IMAGE_ID", iid) == 0 ) { + disk->vector_value("DISK_ID", did); + + map::iterator it = snapshots.find(did); + + if (it != snapshots.end()) + { + imagem->set_image_snapshots(iid, *(it->second), img_error); + } + imagem->release_image(oid, iid, img_error); } From da79447688fd55d55f671ef34f597d57186dcd8e Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Tue, 2 Jun 2015 01:50:28 +0200 Subject: [PATCH 38/83] feature #3782: Transfer snapshot list from/to attach disks --- include/VirtualMachine.h | 13 +++++++++++-- src/dm/DispatchManagerActions.cc | 5 ++++- src/image/ImagePool.cc | 6 ++++++ src/vm/VirtualMachine.cc | 19 +++++++++++++++++-- src/vm/VirtualMachinePool.cc | 19 +++++++++++++------ 5 files changed, 51 insertions(+), 11 deletions(-) diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index 2c72fe6abe..688cb67f0c 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -1417,18 +1417,27 @@ public: * * @return the DISK or 0 if no disk was deleted */ - VectorAttribute * delete_attach_disk(); + VectorAttribute * delete_attach_disk(Snapshots **snap); /** * Adds a new disk to the virtual machine template. The disk should be * generated by the build_attach_disk * @param new_disk must be allocated in the heap + * @param snap list of snapshots associated to the disk */ - void set_attach_disk(VectorAttribute * new_disk) + void set_attach_disk(VectorAttribute * new_disk, Snapshots * snap) { new_disk->replace("ATTACH", "YES"); obj_template->set(new_disk); + + if (snap != 0) + { + int disk_id; + + new_disk->vector_value("DISK_ID", disk_id); + snapshots.insert(pair(disk_id, snap)); + } } /** diff --git a/src/dm/DispatchManagerActions.cc b/src/dm/DispatchManagerActions.cc index 0b91429051..9be157e6c8 100644 --- a/src/dm/DispatchManagerActions.cc +++ b/src/dm/DispatchManagerActions.cc @@ -970,6 +970,9 @@ int DispatchManager::attach(int vid, imagem->release_image(oid, image_id, false); } + delete snap; + delete disk; + oss << "Could not attach a new disk to VM " << vid << ", VM does not exist after setting its state to HOTPLUG." ; error_str = oss.str(); @@ -1003,7 +1006,7 @@ int DispatchManager::attach(int vid, // VM template vm->set_vm_info(); - vm->set_attach_disk(disk); + vm->set_attach_disk(disk, snap); if ( vm->get_lcm_state() == VirtualMachine::HOTPLUG ) { diff --git a/src/image/ImagePool.cc b/src/image/ImagePool.cc index 76fbbb1b92..0f897e539e 100644 --- a/src/image/ImagePool.cc +++ b/src/image/ImagePool.cc @@ -429,6 +429,9 @@ int ImagePool::disk_attribute(int vm_id, imagem->release_image(vm_id, iid, false); error_str = "Unknown internal error"; + delete *snap; + *snap = 0; + return -1; } @@ -439,6 +442,9 @@ int ImagePool::disk_attribute(int vm_id, imagem->release_image(vm_id, iid, false); error_str = "Associated datastore for the image does not exist"; + delete *snap; + *snap = 0; + return -1; } diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index 74f29dd17f..e5dac101a5 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -2035,6 +2035,7 @@ VectorAttribute * VirtualMachine::set_up_attach_disk( Image::ImageType img_type; image_id = -1; + *snap = 0; // ------------------------------------------------------------------------- // Get the DISK attribute from the template @@ -2088,8 +2089,8 @@ VectorAttribute * VirtualMachine::set_up_attach_disk( imagem->release_image(vm_id, image_id, false); - delete snap; delete new_disk; + delete snap; return 0; } @@ -2184,13 +2185,15 @@ void VirtualMachine::clear_attach_disk() /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -VectorAttribute * VirtualMachine::delete_attach_disk() +VectorAttribute * VirtualMachine::delete_attach_disk(Snapshots **snap) { vector disks; VectorAttribute * disk; int num_disks = obj_template->get("DISK", disks); + *snap = 0; + for(int i=0; i(disks[i]); @@ -2202,6 +2205,18 @@ VectorAttribute * VirtualMachine::delete_attach_disk() if ( disk->vector_value("ATTACH") == "YES" ) { + int disk_id; + + disk->vector_value("DISK_ID", disk_id); + + map::iterator it = snapshots.find(disk_id); + + if (it != snapshots.end()) + { + *snap = it->second; + snapshots.erase(it); + } + return static_cast(obj_template->remove(disk)); } } diff --git a/src/vm/VirtualMachinePool.cc b/src/vm/VirtualMachinePool.cc index fdb9455f02..7b413f9db2 100644 --- a/src/vm/VirtualMachinePool.cc +++ b/src/vm/VirtualMachinePool.cc @@ -222,7 +222,7 @@ VirtualMachinePool::VirtualMachinePool( /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int VirtualMachinePool::insert_index(const string& deploy_id, int vmid, +int VirtualMachinePool::insert_index(const string& deploy_id, int vmid, bool replace) { ostringstream oss; @@ -262,7 +262,7 @@ void VirtualMachinePool::drop_index(const string& deploy_id) return; } - oss << "DELETE FROM " << import_table << " WHERE deploy_id='" + oss << "DELETE FROM " << import_table << " WHERE deploy_id='" << deploy_name << "'"; db->exec(oss); @@ -541,13 +541,13 @@ int VirtualMachinePool::db_int_cb(void * _int_output, int num, char **values, ch int VirtualMachinePool::get_vmid (const string& deploy_id) { int rc; - int vmid = -1; + int vmid = -1; ostringstream oss; set_callback(static_cast(&VirtualMachinePool::db_int_cb), static_cast(&vmid)); - oss << "SELECT vmid FROM " << import_table + oss << "SELECT vmid FROM " << import_table << " WHERE deploy_id = '" << db->escape_str(deploy_id.c_str()) << "'"; rc = db->exec(oss, this); @@ -634,7 +634,7 @@ int VirtualMachinePool::calculate_showback( vector showback_slots; vector::iterator slot_it; - + map > vm_cost; map >::iterator vm_it; @@ -1032,6 +1032,7 @@ void VirtualMachinePool::delete_attach_disk(int vid, bool release_save_as) { VirtualMachine * vm; VectorAttribute * disk; + Snapshots * snap; int uid; int gid; @@ -1044,7 +1045,7 @@ void VirtualMachinePool::delete_attach_disk(int vid, bool release_save_as) return; } - disk = vm->delete_attach_disk(); + disk = vm->delete_attach_disk(&snap); uid = vm->get_uid(); gid = vm->get_gid(); oid = vm->get_oid(); @@ -1068,6 +1069,12 @@ void VirtualMachinePool::delete_attach_disk(int vid, bool release_save_as) // Disk using an Image Quotas::quota_del(Quotas::IMAGE, uid, gid, &tmpl); + if (snap != 0) + { + imagem->set_image_snapshots(image_id, *snap, false); + delete snap; + } + imagem->release_image(oid, image_id, false); // Release non-persistent images in the detach event From 71d4bdd0ec790b2a4980b2f64c85cf0e411318f6 Mon Sep 17 00:00:00 2001 From: Tino Vazquez Date: Tue, 2 Jun 2015 11:55:14 +0200 Subject: [PATCH 39/83] Fix wrongly generated GRAPHICS section --- src/vmm_mad/remotes/vcenter/vcenter_driver.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vmm_mad/remotes/vcenter/vcenter_driver.rb b/src/vmm_mad/remotes/vcenter/vcenter_driver.rb index 6559f26cbf..f16fb7bf54 100644 --- a/src/vmm_mad/remotes/vcenter/vcenter_driver.rb +++ b/src/vmm_mad/remotes/vcenter/vcenter_driver.rb @@ -1125,8 +1125,8 @@ class VCenterVm str << "GRAPHICS = [\n"\ " TYPE =\"vnc\",\n"\ " LISTEN =\"0.0.0.0\",\n"\ - " PORT =\"#{vp[0][:value]},\"\n" - str << " KEYMAP =\"#{keymap[0][:value]}\"\n" if keymap + " PORT =\"#{vp[0][:value]}\"\n" + str << " ,KEYMAP =\"#{keymap[0][:value]}\"\n" if keymap str << "]\n" end From 14da3131b96f53026941817b5e78a2c8e0dbf3a4 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Tue, 2 Jun 2015 20:45:42 +0200 Subject: [PATCH 40/83] feature #3782: Image with snapshots cannot be made non-persistent --- include/Image.h | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/include/Image.h b/include/Image.h index 4505eb247d..cbce3cdc37 100644 --- a/include/Image.h +++ b/include/Image.h @@ -389,13 +389,20 @@ public: { ostringstream oss; + if ((snapshots.size() > 0) && !persis) + { + error_str = "Image has snapshots."; + return -1; + } + switch(state) { case USED: case CLONE: case USED_PERS: - goto error_state; - break; + oss << "Image cannot be in state " << state_to_str(state) <<"."; + error_str = oss.str(); + return -1; case INIT: case READY: @@ -416,16 +423,6 @@ public: } return 0; - - error_state: - oss << "Image cannot be in state " << state_to_str(state) << "."; - error_str = oss.str(); - - goto error_common; - - error_common: - return -1; - } /** From 43be9c663e79308be9476fee7e8741c985ed3309 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Tue, 2 Jun 2015 23:12:42 +0200 Subject: [PATCH 41/83] feature #3782: Image with snapshots can be only of type OS or DATABLOCK --- include/Image.h | 2 +- src/image/Image.cc | 17 ++++++++++------- src/rm/RequestManagerImage.cc | 4 +--- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/include/Image.h b/include/Image.h index cbce3cdc37..a3b281563c 100644 --- a/include/Image.h +++ b/include/Image.h @@ -345,7 +345,7 @@ public: * @param _type the new type. It will be transformed to upper case * @return 0 on success, -1 otherwise */ - int set_type(string& _type); + int set_type(string& _type, string& error); /** * Check if the image can be used by other users diff --git a/src/image/Image.cc b/src/image/Image.cc index 521a64fb46..7b0e0eb460 100644 --- a/src/image/Image.cc +++ b/src/image/Image.cc @@ -125,9 +125,9 @@ int Image::insert(SqlDB *db, string& error_str) type_att = ImagePool::default_type(); } - if (set_type(type_att) != 0) + if (set_type(type_att, error_str) != 0) { - goto error_type; + goto error_common; } // ------------ PERSISTENT & PREFIX -------------------- @@ -219,10 +219,6 @@ int Image::insert(SqlDB *db, string& error_str) return rc; -error_type: - error_str = "Incorrect TYPE in template."; - goto error_common; - error_no_path: error_str = "No PATH in template."; goto error_common; @@ -670,12 +666,18 @@ int Image::disk_attribute( VectorAttribute * disk, /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ -int Image::set_type(string& _type) +int Image::set_type(string& _type, string& error) { int rc = 0; TO_UPPER(_type); + if ((_type != "OS" && _type != "DATABLOCK") && (snapshots.size() > 0)) + { + error = "Image with snapshots can be only of type OS or DATABLOCK"; + return -1; + } + if ( _type == "OS" ) { type = OS; @@ -702,6 +704,7 @@ int Image::set_type(string& _type) } else { + error = "Unknown type " + type; rc = -1; } diff --git a/src/rm/RequestManagerImage.cc b/src/rm/RequestManagerImage.cc index 9a044fdcae..c0562e3de3 100644 --- a/src/rm/RequestManagerImage.cc +++ b/src/rm/RequestManagerImage.cc @@ -200,12 +200,10 @@ void ImageChangeType::request_execute(xmlrpc_c::paramList const& paramList, break; } - rc = image->set_type(type); + rc = image->set_type(type, err_msg); if ( rc != 0 ) { - err_msg = "Unknown type " + type; - failure_response(INTERNAL,request_error(err_msg,""), att); image->unlock(); From 023c853b6ed23fdfdda519bc1991cbb949213f09 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Tue, 2 Jun 2015 23:42:19 +0200 Subject: [PATCH 42/83] feature #3782: Cannot clone images with snapshots --- include/Image.h | 8 ++++++++ src/rm/RequestManagerImage.cc | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/include/Image.h b/include/Image.h index a3b281563c..fe9bdcd980 100644 --- a/include/Image.h +++ b/include/Image.h @@ -219,6 +219,14 @@ public: return size_mb; } + /** + * Return the number of snapshots + */ + unsigned int get_snapshots_size() + { + return snapshots.size(); + } + /** * Sets the source path of the image */ diff --git a/src/rm/RequestManagerImage.cc b/src/rm/RequestManagerImage.cc index c0562e3de3..1e934ba6c6 100644 --- a/src/rm/RequestManagerImage.cc +++ b/src/rm/RequestManagerImage.cc @@ -280,6 +280,14 @@ void ImageClone::request_execute( return; } + if (img->get_snapshots_size () > 0) + { + failure_response(ACTION, + request_error("Cannot clone images with snapshots",""), att); + img->unlock(); + return; + } + tmpl = img->clone_template(name); img->get_permissions(perms); From 8978f56c90c7da1ffdd2092ab6e076fb3ade26a9 Mon Sep 17 00:00:00 2001 From: Jaime Melis Date: Wed, 3 Jun 2015 14:36:59 +0200 Subject: [PATCH 43/83] feature #3782: Display snapshots in oneimage show --- src/cli/one_helper/oneimage_helper.rb | 45 +++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/cli/one_helper/oneimage_helper.rb b/src/cli/one_helper/oneimage_helper.rb index 068a417a85..72799b8d50 100644 --- a/src/cli/one_helper/oneimage_helper.rb +++ b/src/cli/one_helper/oneimage_helper.rb @@ -292,6 +292,13 @@ class OneImageHelper < OpenNebulaHelper::OneHelper puts str % [e, mask] } + + if image.has_elements?("/IMAGE/SNAPSHOTS") + puts + CLIHelper.print_header(str_h1 % "IMAGE SNAPSHOTS",false) + format_snapshots(image) + end + puts CLIHelper.print_header(str_h1 % "IMAGE TEMPLATE",false) @@ -311,6 +318,44 @@ class OneImageHelper < OpenNebulaHelper::OneHelper end end + def format_snapshots(image) + table=CLIHelper::ShowTable.new(nil, self) do + column :AC , "Is active", :left, :size => 2 do |d| + if d["ACTIVE"] == "YES" + "=>" + else + "" + end + end + column :ID, "Snapshot ID", :size=>3 do |d| + d["ID"] + end + + column :PARENT, "Snapshot Parent ID", :size=>6 do |d| + d["PARENT"] + end + + column :CHILDREN, "Snapshot Children IDs", :size=>10 do |d| + d["CHILDREN"] + end + + column :TAG, "Snapshot Tag", :left, :size=>45 do |d| + d["TAG"] + end + + column :DATE, "Snapshot creation date", :size=>15 do |d| + OpenNebulaHelper.time_to_str(d["DATE"]) + end + + default :AC, :ID, :PARENT, :DATE, :CHILDREN, :TAG + end + + # Convert snapshot data to an array + image_hash = image.to_hash + image_snapshots = [image_hash['IMAGE']['SNAPSHOTS']].flatten.first + table.show(image_snapshots) + end + def self.create_image_variables(options, name) if Array===name names=name From bdd231bf517bd61d0ca656ec59c011ef37fc2b13 Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Wed, 3 Jun 2015 18:17:52 -0400 Subject: [PATCH 44/83] bug #3768: add tm/failmigrate call on error --- src/vmm_mad/exec/one_vmm_exec.rb | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/vmm_mad/exec/one_vmm_exec.rb b/src/vmm_mad/exec/one_vmm_exec.rb index 4e4ffaa7b2..3f45fb4560 100755 --- a/src/vmm_mad/exec/one_vmm_exec.rb +++ b/src/vmm_mad/exec/one_vmm_exec.rb @@ -478,9 +478,11 @@ class ExecDriver < VirtualMachineDriver action = VmmAction.new(self, id, :migrate, drv_message) pre = "PRE" post = "POST" + failed = "FAIL" pre << action.data[:tm_command] << " " << action.data[:vm] post << action.data[:tm_command] << " " << action.data[:vm] + failed << action.data[:tm_command] << " " << action.data[:vm] steps=[ # Execute a pre-migrate TM setup @@ -499,7 +501,15 @@ class ExecDriver < VirtualMachineDriver { :driver => :vmm, :action => :migrate, - :parameters => [:deploy_id, :dest_host, :host] + :parameters => [:deploy_id, :dest_host, :host], + :fail_actions => [ + { + :driver => :tm, + :action => :tm_failmigrate, + :parameters => failed.split, + :no_fail => true + } + ] }, # Execute networking clean up operations # NOTE: VM is now in the new host. If we fail from now on, oned will From 94105537f4674591a531dec9b5b1538879fa51f5 Mon Sep 17 00:00:00 2001 From: Tino Vazquez Date: Thu, 4 Jun 2015 18:46:33 +0200 Subject: [PATCH 45/83] Add capacity resizing and honoring capacity changes in VM templates in the VM drivers (cherry picked from commit d2f7e7bb28468451f1b73ab1eb0c30a1b692a8f9) --- src/vmm_mad/remotes/vcenter/vcenter_driver.rb | 64 +++++++++++++------ 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/src/vmm_mad/remotes/vcenter/vcenter_driver.rb b/src/vmm_mad/remotes/vcenter/vcenter_driver.rb index f16fb7bf54..5c52d9b232 100644 --- a/src/vmm_mad/remotes/vcenter/vcenter_driver.rb +++ b/src/vmm_mad/remotes/vcenter/vcenter_driver.rb @@ -734,6 +734,19 @@ class VCenterVm hid = VIClient::translate_hostname(hostname) connection = VIClient.new(hid) vm = connection.find_vm_template(deploy_id) + + # Find out if we need to reconfigure capacity + expected_cpu, expected_memory = get_cpu_and_memory(xml_text) + current_cpu = vm.config.hardware.numCPU + current_memory = vm.config.hardware.memoryMB + + if current_cpu != expected_cpu or current_memory != expected_memory + capacity_hash = {:numCPUs => expected_cpu.to_i, + :memoryMB => expected_memory } + spec = RbVmomi::VIM.VirtualMachineConfigSpec(capacity_hash) + vm.ReconfigVM_Task(:spec => spec).wait_for_completion + end + vm.PowerOnVM_Task.wait_for_completion return vm.config.uuid end @@ -1237,13 +1250,21 @@ private } end + def self.get_cpu_and_memory(xml_text) + xml = REXML::Document.new xml_text + + cpu = xml.root.elements["//TEMPLATE/CPU"].text + memory = xml.root.elements["//TEMPLATE/MEMORY"].text + + return cpu, memory + end + ######################################################################## # Clone a vCenter VM Template and leaves it powered on ######################################################################## def self.clone_vm(xml_text) xml = REXML::Document.new xml_text - pcs = xml.root.get_elements("//USER_TEMPLATE/PUBLIC_CLOUD") raise "Cannot find VCenter element in VM template." if pcs.nil? @@ -1260,33 +1281,29 @@ private raise "Cannot find VM_TEMPLATE in VCenter element." if uuid.nil? uuid = uuid.text - vmid = xml.root.elements["/VM/ID"].text - hid = xml.root.elements["//HISTORY_RECORDS/HISTORY/HID"] raise "Cannot find host id in deployment file history." if hid.nil? context = xml.root.elements["//TEMPLATE/CONTEXT"] - connection = VIClient.new(hid) - vc_template = connection.find_vm_template(uuid) relocate_spec = RbVmomi::VIM.VirtualMachineRelocateSpec( - :diskMoveType => :moveChildMostDiskBacking, - :pool => connection.resource_pool) + :diskMoveType => :moveChildMostDiskBacking, + :pool => connection.resource_pool) clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec( - :location => relocate_spec, - :powerOn => false, - :template => false) + :location => relocate_spec, + :powerOn => false, + :template => false) begin vm = vc_template.CloneVM_Task( - :folder => vc_template.parent, - :name => "one-#{vmid}", - :spec => clone_spec).wait_for_completion + :folder => vc_template.parent, + :name => "one-#{vmid}", + :spec => clone_spec).wait_for_completion rescue Exception => e if !e.message.start_with?('DuplicateName') @@ -1297,8 +1314,7 @@ private raise "Cannot clone VM Template" if vm.nil? - vm.Destroy_Task.wait_for_completion - + vm.Destroy_Task.wait_for_completion vm = vc_template.CloneVM_Task( :folder => vc_template.parent, :name => "one-#{vmid}", @@ -1352,6 +1368,7 @@ private end # NIC section, build the reconfig hash + nics = xml.root.get_elements("//TEMPLATE/NIC") nic_spec = {} @@ -1367,12 +1384,19 @@ private nic_spec = {:deviceChange => nic_array} end - if !context_vnc_spec.empty? or !nic_spec.empty? - spec_hash = context_vnc_spec.merge(nic_spec) - spec = RbVmomi::VIM.VirtualMachineConfigSpec(spec_hash) - vm.ReconfigVM_Task(:spec => spec).wait_for_completion - end + # Capacity section + cpu = xml.root.elements["//TEMPLATE/CPU"].text + memory = xml.root.elements["//TEMPLATE/MEMORY"].text + capacity_spec = {:numCPUs => cpu.to_i, + :memoryMB => memory } + + # Perform the VM reconfiguration + spec_hash = context_vnc_spec.merge(nic_spec).merge(capacity_spec) + spec = RbVmomi::VIM.VirtualMachineConfigSpec(spec_hash) + vm.ReconfigVM_Task(:spec => spec).wait_for_completion + + # Power on the VM vm.PowerOnVM_Task.wait_for_completion return vm_uuid From 5510b56bd54b9a06a42bb35f06dfde83cc3803d5 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Thu, 4 Jun 2015 19:46:46 +0200 Subject: [PATCH 46/83] feature #3782: Delete operations are now two-phase. More checks on disk-snapshots actions. Improve const-ness of Snapshot class --- include/Snapshots.h | 38 +++++++++++++---- include/VirtualMachine.h | 31 +++++++++----- src/dm/DispatchManagerActions.cc | 23 +++++++++- src/lcm/LifeCycleStates.cc | 59 ++++++++++++++++---------- src/vm/Snapshots.cc | 72 ++++++++++++++++++-------------- src/vm/VirtualMachine.cc | 71 ++++++++++++++++--------------- 6 files changed, 184 insertions(+), 110 deletions(-) diff --git a/include/Snapshots.h b/include/Snapshots.h index 0f88ca875d..098110eced 100644 --- a/include/Snapshots.h +++ b/include/Snapshots.h @@ -81,27 +81,41 @@ public: int create_snapshot(const string& tag); /** - * Removes the snapshot from the list + * Check if an snapshot can be deleted (no children, no active) * @param id of the snapshot * @param error if any - * @return 0 on success -1 otherwise + * @return true if can be deleted, false otherwise */ - int delete_snapshot(unsigned int id, string& error); + bool test_delete(unsigned int id, string& error) const; + + /** + * Removes the snapshot from the list + * @param id of the snapshot + */ + void delete_snapshot(unsigned int id); /** * Set the given snapshot as active. Updates the values of the current * snapshot */ - int active_snapshot(unsigned int id, string& error); + int active_snapshot(unsigned int id); /** * Return the disk_id of the snapshot list */ - int get_disk_id() + int get_disk_id() const { return disk_id; } + /** + * Return the active snapshot id + */ + int get_active_id() const + { + return active; + } + /** * Removes the DISK_ID attribute to link the list to an Image */ @@ -119,15 +133,15 @@ public: { disk_id = did; snapshot_template.replace("DISK_ID", did); - } + }; /** * @return number of snapshots in the list */ - unsigned int size() + unsigned int size() const { return snapshot_pool.size(); - } + }; /** * Get Attribute from the given snapshot @@ -145,7 +159,13 @@ private: * @param id of the snapshot * @return pointer to the snapshot (VectorAttribute) or null */ - VectorAttribute * get_snapshot(unsigned int id); + const VectorAttribute * get_snapshot(unsigned int id) const; + + VectorAttribute * get_snapshot(unsigned int id) + { + return const_cast( + static_cast(*this).get_snapshot(id)); + }; /** * Build the object internal representation from an initialized diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index 688cb67f0c..15bb959915 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -1519,6 +1519,14 @@ public: // Snapshot related functions // ------------------------------------------------------------------------ + /** + * Return the snapshot list for the disk + * @param disk_id of the disk + * @param error if any + * @return pointer to Snapshots or 0 if not found + */ + const Snapshots * get_disk_snapshots(int did, string& err) const; + /** * Creates a new snapshot of the given disk * @param disk_id of the disk @@ -1531,22 +1539,19 @@ public: /** * Sets the snap_id as active, the VM will boot from it next time * @param disk_id of the disk - * @param snap_id of the snapshot. It can be 0 to revert to the original - * disk + * @param snap_id of the snapshot * @param error if any * @return -1 if error */ - int revert_disk_snapshot(int disk_id, int snap_id, string& error); + int revert_disk_snapshot(int disk_id, int snap_id); /** - * Deletes the snap_id, the snapshot cannot be the current (active) one + * Deletes the snap_id from the list, test_delete_disk_snapshot *MUST* be + * called before actually deleting the snapshot. * @param disk_id of the disk - * @param snap_id of the snapshot. It can be 0 to revert to the original - * disk - * @param error if any - * @return -1 if error + * @param snap_id of the snapshot */ - int delete_disk_snapshot(int disk_id, int snap_id, string& error); + void delete_disk_snapshot(int disk_id, int snap_id); /** * Get information about the disk to take the snapshot from @@ -2007,7 +2012,13 @@ private: * @param disk_id of the disk * @return pointer to the VectorAttribute */ - VectorAttribute* get_disk(int disk_id); + VectorAttribute* get_disk(int disk_id) + { + return const_cast( + static_cast(*this).get_disk(disk_id)); + }; + + const VectorAttribute* get_disk(int disk_id) const; protected: diff --git a/src/dm/DispatchManagerActions.cc b/src/dm/DispatchManagerActions.cc index 9be157e6c8..ba1b61ce64 100644 --- a/src/dm/DispatchManagerActions.cc +++ b/src/dm/DispatchManagerActions.cc @@ -1705,6 +1705,19 @@ int DispatchManager::disk_snapshot_revert( return -1; } + const Snapshots * snaps = vm->get_disk_snapshots(did, error_str); + + if (snaps == 0) + { + return -1; + } + + if (snaps->get_active_id() == snap_id) + { + error_str = "Snapshot is already the active one"; + return -1; + } + if (vm->set_snapshot_disk(did, snap_id) == -1) { vm->unlock(); @@ -1760,9 +1773,15 @@ int DispatchManager::disk_snapshot_delete( return -1; } - if (vm->delete_disk_snapshot(did, snap_id, error_str) == -1) + const Snapshots * snaps = vm->get_disk_snapshots(did, error_str); + + if (snaps == 0) + { + return -1; + } + + if (!snaps->test_delete(snap_id, error_str)) { - vm->unlock(); return -1; } diff --git a/src/lcm/LifeCycleStates.cc b/src/lcm/LifeCycleStates.cc index c45ca8284a..e8cbe040da 100644 --- a/src/lcm/LifeCycleStates.cc +++ b/src/lcm/LifeCycleStates.cc @@ -1710,8 +1710,7 @@ void LifeCycleManager::saveas_hot_failure_action(int vid) void LifeCycleManager::disk_snapshot_success(int vid) { - string disk_id, tm_mad, ds_id, snap_id, err; - int isnap_id, idisk_id; + string disk_id, tm_mad, ds_id, snap_id; VirtualMachine * vm = vmpool->get(vid,true); @@ -1720,23 +1719,31 @@ void LifeCycleManager::disk_snapshot_success(int vid) return; } + if (vm->get_snapshot_disk(ds_id, tm_mad, disk_id, snap_id) == -1) + { + vm->log("LCM", Log::ERROR, "Snapshot DISK could not be found"); + + dm->trigger(DispatchManager::POWEROFF_SUCCESS, vid); + + vm->unlock(); + + return; + } + + int isnap_id = strtol(snap_id.c_str(),NULL,0); + int idisk_id = strtol(disk_id.c_str(),NULL,0); + switch (vm->get_lcm_state()) { case VirtualMachine::DISK_SNAPSHOT_POWEROFF: case VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF: vm->log("LCM", Log::INFO, "VM disk snapshot operation completed."); - - if (vm->get_snapshot_disk(ds_id, tm_mad, disk_id, snap_id) != -1) - { - isnap_id = strtol(snap_id.c_str(),NULL,0); - idisk_id = strtol(disk_id.c_str(),NULL,0); - - vm->revert_disk_snapshot(idisk_id, isnap_id, err); - } + vm->revert_disk_snapshot(idisk_id, isnap_id); break; case VirtualMachine::DISK_SNAPSHOT_DELETE_POWEROFF: vm->log("LCM", Log::INFO, "VM disk snapshot deleted."); + vm->delete_disk_snapshot(idisk_id, isnap_id); break; default: @@ -1761,8 +1768,7 @@ void LifeCycleManager::disk_snapshot_success(int vid) void LifeCycleManager::disk_snapshot_failure(int vid) { - string disk_id, tm_mad, ds_id, snap_id, err; - int isnap_id, idisk_id; + string disk_id, tm_mad, ds_id, snap_id; VirtualMachine * vm = vmpool->get(vid,true); @@ -1771,23 +1777,30 @@ void LifeCycleManager::disk_snapshot_failure(int vid) return; } + if (vm->get_snapshot_disk(ds_id, tm_mad, disk_id, snap_id) == -1) + { + vm->log("LCM", Log::ERROR, "Snapshot DISK could not be found"); + + dm->trigger(DispatchManager::POWEROFF_SUCCESS, vid); + + vm->unlock(); + + return; + } + + int isnap_id = strtol(snap_id.c_str(),NULL,0); + int idisk_id = strtol(disk_id.c_str(),NULL,0); + switch (vm->get_lcm_state()) { case VirtualMachine::DISK_SNAPSHOT_POWEROFF: - case VirtualMachine::DISK_SNAPSHOT_DELETE_POWEROFF: - vm->log("LCM", Log::ERROR, "VM disk snapshot operation failed."); - - if (vm->get_snapshot_disk(ds_id, tm_mad, disk_id, snap_id) != -1) - { - isnap_id = strtol(snap_id.c_str(),NULL,0); - idisk_id = strtol(disk_id.c_str(),NULL,0); - - vm->delete_disk_snapshot(idisk_id, isnap_id, err); - } + vm->log("LCM", Log::ERROR, "Could not take disk snapshot."); + vm->delete_disk_snapshot(idisk_id, isnap_id); break; + case VirtualMachine::DISK_SNAPSHOT_DELETE_POWEROFF: case VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF: - vm->log("LCM", Log::ERROR, "Could not revert to disk snapshot."); + vm->log("LCM", Log::ERROR, "VM disk snapshot operation failed."); break; default: diff --git a/src/vm/Snapshots.cc b/src/vm/Snapshots.cc index a7876af3e8..2cee81882b 100644 --- a/src/vm/Snapshots.cc +++ b/src/vm/Snapshots.cc @@ -172,34 +172,15 @@ int Snapshots::create_snapshot(const string& tag) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int Snapshots::delete_snapshot(unsigned int id, string& error) +void Snapshots::delete_snapshot(unsigned int id) { - int parent_id; - bool current; - string children; + int parent_id; VectorAttribute * snapshot = get_snapshot(id); if (snapshot == 0) { - error = "Snapshot does not exists"; - return -1; - } - - snapshot->vector_value("ACTIVE", current); - - if (current) - { - error = "Cannot delete the active snapshot"; - return -1; - } - - snapshot->vector_value("CHILDREN", children); - - if (!children.empty()) - { - error = "Cannot delete snapshot with children"; - return -1; + return; } snapshot->vector_value("PARENT", parent_id); @@ -212,7 +193,7 @@ int Snapshots::delete_snapshot(unsigned int id, string& error) if (parent != 0) { - children = parent->vector_value("CHILDREN"); + string children = parent->vector_value("CHILDREN"); one_util::split_unique(children, ',', child_set); @@ -236,27 +217,22 @@ int Snapshots::delete_snapshot(unsigned int id, string& error) delete snapshot; snapshot_pool.erase(id); - - return 0; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int Snapshots::active_snapshot(unsigned int id, string& error) +int Snapshots::active_snapshot(unsigned int id) { - VectorAttribute * snapshot; - if (static_cast(id) == active) { return 0; } - snapshot = get_snapshot(id); + VectorAttribute * snapshot = get_snapshot(id); if (snapshot == 0) { - error = "Snapshot does not exists"; return -1; } @@ -277,9 +253,9 @@ int Snapshots::active_snapshot(unsigned int id, string& error) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -VectorAttribute * Snapshots::get_snapshot(unsigned int id) +const VectorAttribute * Snapshots::get_snapshot(unsigned int id) const { - map::iterator it; + map::const_iterator it; it = snapshot_pool.find(id); @@ -309,3 +285,35 @@ string Snapshots::get_snapshot_attribute(unsigned int id, const char * name) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +bool Snapshots::test_delete(unsigned int id, string& error) const +{ + bool current; + string children; + + const VectorAttribute * snapshot = get_snapshot(id); + + if (snapshot == 0) + { + error = "Snapshot does not exists"; + return false; + } + + snapshot->vector_value("ACTIVE", current); + + if (current) + { + error = "Cannot delete the active snapshot"; + return false; + } + + snapshot->vector_value("CHILDREN", children); + + if (!children.empty()) + { + error = "Cannot delete snapshot with children"; + return false; + } + + return true; +} + diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index e5dac101a5..bff395fde8 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -3339,19 +3339,19 @@ int VirtualMachine::clear_saveas_state(int disk_id, bool hot) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -VectorAttribute* VirtualMachine::get_disk(int disk_id) +const VectorAttribute* VirtualMachine::get_disk(int disk_id) const { int num_disks; int tdisk_id; - vector disks; - VectorAttribute * disk; + vector disks; + const VectorAttribute * disk; num_disks = obj_template->get("DISK", disks); for(int i=0; i(disks[i]); + disk = dynamic_cast(disks[i]); if ( disk == 0 ) { @@ -4362,19 +4362,38 @@ int VirtualMachine::new_disk_snapshot(int did, const string& tag, string& error) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int VirtualMachine::revert_disk_snapshot(int did, int snap_id, string& error) +const Snapshots * VirtualMachine::get_disk_snapshots(int did, string& error) const { - map::iterator it; - int rc; - - VectorAttribute * disk; - string source; - - disk = get_disk(did); + const VectorAttribute * disk = get_disk(did); if ( disk == 0 ) { error = "VM disk does not exists"; + return 0; + } + + map::const_iterator it = snapshots.find(did); + + if (it == snapshots.end()) + { + error = "Snapshot does not exists"; + return 0; + } + + return it->second; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int VirtualMachine::revert_disk_snapshot(int did, int snap_id) +{ + map::iterator it; + + VectorAttribute * disk = get_disk(did); + + if ( disk == 0 ) + { return -1; } @@ -4382,48 +4401,32 @@ int VirtualMachine::revert_disk_snapshot(int did, int snap_id, string& error) if (it == snapshots.end()) { - error = "Snapshot does not exists"; return -1; } - else - { - rc = it->second->active_snapshot(snap_id, error); - } - return rc; + return it->second->active_snapshot(snap_id); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int VirtualMachine::delete_disk_snapshot(int did, int snap_id, string& error) +void VirtualMachine::delete_disk_snapshot(int did, int snap_id) { map::iterator it; - int rc; - - VectorAttribute * disk; - string source; - - disk = get_disk(did); + VectorAttribute * disk = get_disk(did); if ( disk == 0 ) { - error = "VM disk does not exists"; - return -1; + return; } it = snapshots.find(did); if (it == snapshots.end()) { - error = "Snapshot does not exists"; - return -1; - } - else - { - rc = it->second->delete_snapshot(snap_id, error); + return; } - return rc; + it->second->delete_snapshot(snap_id); } From 480ad9178da6e9951a0fc1aac1cac96dab10e511 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Thu, 4 Jun 2015 20:04:10 +0200 Subject: [PATCH 47/83] feature #3782: Add missing unlocks to failure exits --- src/dm/DispatchManagerActions.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/dm/DispatchManagerActions.cc b/src/dm/DispatchManagerActions.cc index ba1b61ce64..ad4a3b7bf7 100644 --- a/src/dm/DispatchManagerActions.cc +++ b/src/dm/DispatchManagerActions.cc @@ -1709,12 +1709,15 @@ int DispatchManager::disk_snapshot_revert( if (snaps == 0) { + vm->unlock(); return -1; } if (snaps->get_active_id() == snap_id) { error_str = "Snapshot is already the active one"; + + vm->unlock(); return -1; } @@ -1777,11 +1780,13 @@ int DispatchManager::disk_snapshot_delete( if (snaps == 0) { + vm->unlock(); return -1; } if (!snaps->test_delete(snap_id, error_str)) { + vm->unlock(); return -1; } From adc3e0e4e711149ff86bbfd273a74c0df520c625 Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Thu, 4 Jun 2015 15:43:32 -0400 Subject: [PATCH 48/83] bug #3768: add placeholder failmigrate script --- install.sh | 9 +++++++++ src/tm_mad/ceph/failmigrate | 1 + src/tm_mad/common/failmigrate | 29 +++++++++++++++++++++++++++++ src/tm_mad/dev/failmigrate | 1 + src/tm_mad/dummy/failmigrate | 1 + src/tm_mad/fs_lvm/failmigrate | 1 + src/tm_mad/lvm/failmigrate | 1 + src/tm_mad/qcow2/failmigrate | 1 + src/tm_mad/shared/failmigrate | 1 + src/tm_mad/ssh/failmigrate | 1 + src/tm_mad/vmfs/failmigrate | 1 + 11 files changed, 47 insertions(+) create mode 120000 src/tm_mad/ceph/failmigrate create mode 100755 src/tm_mad/common/failmigrate create mode 120000 src/tm_mad/dev/failmigrate create mode 120000 src/tm_mad/dummy/failmigrate create mode 120000 src/tm_mad/fs_lvm/failmigrate create mode 120000 src/tm_mad/lvm/failmigrate create mode 120000 src/tm_mad/qcow2/failmigrate create mode 120000 src/tm_mad/shared/failmigrate create mode 120000 src/tm_mad/ssh/failmigrate create mode 120000 src/tm_mad/vmfs/failmigrate diff --git a/install.sh b/install.sh index d29e734f5f..075d381737 100755 --- a/install.sh +++ b/install.sh @@ -1018,6 +1018,7 @@ TM_SHARED_FILES="src/tm_mad/shared/clone \ src/tm_mad/shared/context \ src/tm_mad/shared/premigrate \ src/tm_mad/shared/postmigrate \ + src/tm_mad/shared/failmigrate \ src/tm_mad/shared/mvds \ src/tm_mad/shared/cpds" @@ -1028,6 +1029,7 @@ TM_FS_LVM_FILES="src/tm_mad/fs_lvm/clone \ src/tm_mad/fs_lvm/cpds \ src/tm_mad/fs_lvm/premigrate \ src/tm_mad/fs_lvm/postmigrate \ + src/tm_mad/fs_lvm/failmigrate \ src/tm_mad/fs_lvm/delete" TM_QCOW2_FILES="src/tm_mad/qcow2/clone \ @@ -1039,6 +1041,7 @@ TM_QCOW2_FILES="src/tm_mad/qcow2/clone \ src/tm_mad/qcow2/context \ src/tm_mad/qcow2/premigrate \ src/tm_mad/qcow2/postmigrate \ + src/tm_mad/qcow2/failmigrate \ src/tm_mad/qcow2/mvds \ src/tm_mad/qcow2/cpds" @@ -1051,6 +1054,7 @@ TM_SSH_FILES="src/tm_mad/ssh/clone \ src/tm_mad/ssh/context \ src/tm_mad/ssh/premigrate \ src/tm_mad/ssh/postmigrate \ + src/tm_mad/ssh/failmigrate \ src/tm_mad/ssh/mvds \ src/tm_mad/ssh/cpds" @@ -1063,6 +1067,7 @@ TM_DUMMY_FILES="src/tm_mad/dummy/clone \ src/tm_mad/dummy/context \ src/tm_mad/dummy/premigrate \ src/tm_mad/dummy/postmigrate \ + src/tm_mad/dummy/failmigrate \ src/tm_mad/dummy/mvds \ src/tm_mad/dummy/cpds" @@ -1076,6 +1081,7 @@ TM_VMFS_FILES="src/tm_mad/vmfs/clone \ src/tm_mad/vmfs/mvds \ src/tm_mad/vmfs/cpds \ src/tm_mad/vmfs/postmigrate \ + src/tm_mad/vmfs/failmigrate \ src/tm_mad/vmfs/premigrate" TM_LVM_FILES="src/tm_mad/lvm/clone \ @@ -1085,6 +1091,7 @@ TM_LVM_FILES="src/tm_mad/lvm/clone \ src/tm_mad/lvm/cpds \ src/tm_mad/lvm/premigrate \ src/tm_mad/lvm/postmigrate \ + src/tm_mad/lvm/failmigrate \ src/tm_mad/lvm/delete" TM_CEPH_FILES="src/tm_mad/ceph/clone \ @@ -1094,6 +1101,7 @@ TM_CEPH_FILES="src/tm_mad/ceph/clone \ src/tm_mad/ceph/cpds \ src/tm_mad/ceph/premigrate \ src/tm_mad/ceph/postmigrate \ + src/tm_mad/ceph/failmigrate \ src/tm_mad/ceph/delete" TM_DEV_FILES="src/tm_mad/dev/clone \ @@ -1103,6 +1111,7 @@ TM_DEV_FILES="src/tm_mad/dev/clone \ src/tm_mad/dev/cpds \ src/tm_mad/dev/premigrate \ src/tm_mad/dev/postmigrate \ + src/tm_mad/dev/failmigrate \ src/tm_mad/dev/delete" #------------------------------------------------------------------------------- diff --git a/src/tm_mad/ceph/failmigrate b/src/tm_mad/ceph/failmigrate new file mode 120000 index 0000000000..5928a42794 --- /dev/null +++ b/src/tm_mad/ceph/failmigrate @@ -0,0 +1 @@ +../common/failmigrate \ No newline at end of file diff --git a/src/tm_mad/common/failmigrate b/src/tm_mad/common/failmigrate new file mode 100755 index 0000000000..49ab4a881d --- /dev/null +++ b/src/tm_mad/common/failmigrate @@ -0,0 +1,29 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # +# FAILMIGRATE SOURCE DST remote_system_dir vmid dsid template +# - SOURCE is the host where the VM is running +# - DST is the host where the VM failed to be migrated +# - remote_system_dir is the path for the VM home in the system datastore +# - vmid is the id of the VM +# - dsid is the target datastore +# - template is the template of the VM in XML and base64 encoded + +# To access the vm_template you can use the xpath.rb utility. Check the +# datastore drivers for an example. + +exit 0 diff --git a/src/tm_mad/dev/failmigrate b/src/tm_mad/dev/failmigrate new file mode 120000 index 0000000000..5928a42794 --- /dev/null +++ b/src/tm_mad/dev/failmigrate @@ -0,0 +1 @@ +../common/failmigrate \ No newline at end of file diff --git a/src/tm_mad/dummy/failmigrate b/src/tm_mad/dummy/failmigrate new file mode 120000 index 0000000000..5928a42794 --- /dev/null +++ b/src/tm_mad/dummy/failmigrate @@ -0,0 +1 @@ +../common/failmigrate \ No newline at end of file diff --git a/src/tm_mad/fs_lvm/failmigrate b/src/tm_mad/fs_lvm/failmigrate new file mode 120000 index 0000000000..5928a42794 --- /dev/null +++ b/src/tm_mad/fs_lvm/failmigrate @@ -0,0 +1 @@ +../common/failmigrate \ No newline at end of file diff --git a/src/tm_mad/lvm/failmigrate b/src/tm_mad/lvm/failmigrate new file mode 120000 index 0000000000..5928a42794 --- /dev/null +++ b/src/tm_mad/lvm/failmigrate @@ -0,0 +1 @@ +../common/failmigrate \ No newline at end of file diff --git a/src/tm_mad/qcow2/failmigrate b/src/tm_mad/qcow2/failmigrate new file mode 120000 index 0000000000..5928a42794 --- /dev/null +++ b/src/tm_mad/qcow2/failmigrate @@ -0,0 +1 @@ +../common/failmigrate \ No newline at end of file diff --git a/src/tm_mad/shared/failmigrate b/src/tm_mad/shared/failmigrate new file mode 120000 index 0000000000..5928a42794 --- /dev/null +++ b/src/tm_mad/shared/failmigrate @@ -0,0 +1 @@ +../common/failmigrate \ No newline at end of file diff --git a/src/tm_mad/ssh/failmigrate b/src/tm_mad/ssh/failmigrate new file mode 120000 index 0000000000..5928a42794 --- /dev/null +++ b/src/tm_mad/ssh/failmigrate @@ -0,0 +1 @@ +../common/failmigrate \ No newline at end of file diff --git a/src/tm_mad/vmfs/failmigrate b/src/tm_mad/vmfs/failmigrate new file mode 120000 index 0000000000..5928a42794 --- /dev/null +++ b/src/tm_mad/vmfs/failmigrate @@ -0,0 +1 @@ +../common/failmigrate \ No newline at end of file From 28d3dcb82d5d05170341f315954ca7862b7a80fd Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Fri, 5 Jun 2015 03:15:39 +0200 Subject: [PATCH 49/83] feature #3782: Snapshot operations for Image class. Add target_snapshot to Image class to identify operation on progress --- include/Image.h | 50 ++++++++++++++++++++++++++++++++++++++-------- src/image/Image.cc | 6 +++++- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/include/Image.h b/include/Image.h index fe9bdcd980..f3687dede2 100644 --- a/include/Image.h +++ b/include/Image.h @@ -219,13 +219,6 @@ public: return size_mb; } - /** - * Return the number of snapshots - */ - unsigned int get_snapshots_size() - { - return snapshots.size(); - } /** * Sets the source path of the image @@ -492,6 +485,17 @@ public: */ ImageTemplate * clone_template(const string& new_name) const; + /* ---------------------------------------------------------------------- */ + /* Snapshots functions */ + /* ---------------------------------------------------------------------- */ + /** + * Return the snapshot list of this image + */ + const Snapshots& get_snapshots() const + { + return snapshots; + }; + /** * Set the snapshots for this image * @param snapshot list @@ -500,7 +504,32 @@ public: { snapshots = s; snapshots.clear_disk_id(); - } + }; + + void delete_snapshot(int snap_id) + { + snapshots.delete_snapshot(snap_id); + }; + + void revert_snapshot(int snap_id) + { + snapshots.active_snapshot(snap_id); + }; + + void set_target_snapshot(int snap_id) + { + target_snapshot = snap_id; + }; + + int get_target_snapshot() + { + return target_snapshot; + }; + + void clear_target_snapshot() + { + target_snapshot = -1; + }; private: @@ -600,6 +629,11 @@ private: */ Snapshots snapshots; + /** + * ID of the snapshot being processed (if any) + */ + int target_snapshot; + // ************************************************************************* // DataBase implementation (Private) // ************************************************************************* diff --git a/src/image/Image.cc b/src/image/Image.cc index 7b0e0eb460..80f1562490 100644 --- a/src/image/Image.cc +++ b/src/image/Image.cc @@ -57,7 +57,8 @@ Image::Image(int _uid, ds_name(""), vm_collection("VMS"), img_clone_collection("CLONES"), - snapshots(-1) + snapshots(-1), + target_snapshot(-1) { if (_image_template != 0) { @@ -359,6 +360,7 @@ string& Image::to_xml(string& xml) const "" << running_vms << "" << "" << cloning_ops << "" << "" << cloning_id << "" << + ""<< target_snapshot << ""<< "" << ds_id << ""<< "" << ds_name << "" << vm_collection.to_xml(vm_collection_xml) << @@ -409,6 +411,8 @@ int Image::from_xml(const string& xml) rc += xpath(cloning_ops, "/IMAGE/CLONING_OPS", -1); rc += xpath(cloning_id, "/IMAGE/CLONING_ID", -1); + xpath(target_snapshot, "/IMAGE/TARGET_SNAPSHOT", -1); + rc += xpath(ds_id, "/IMAGE/DATASTORE_ID", -1); rc += xpath(ds_name, "/IMAGE/DATASTORE", "not_found"); From 1bd6ffe60a45b8e5c84023689615c6810ff86bb2 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Fri, 5 Jun 2015 03:18:40 +0200 Subject: [PATCH 50/83] feature #3782: Delete operations for image snapshots. Core image manager and driver functions --- include/ImageManager.h | 9 +++ include/ImageManagerDriver.h | 21 +++++++ src/image/ImageManagerActions.cc | 75 ++++++++++++++++++++++ src/image/ImageManagerDriver.cc | 103 +++++++++++++++++++++++++++++-- 4 files changed, 202 insertions(+), 6 deletions(-) diff --git a/include/ImageManager.h b/include/ImageManager.h index 0dd421c76e..04f87f2ede 100644 --- a/include/ImageManager.h +++ b/include/ImageManager.h @@ -199,6 +199,15 @@ public: */ void set_image_snapshots(int iid, const Snapshots& s, bool failed); + /** + * Deletes the snapshot of an image + * @param iid id of image + * @param sid id of the snapshot + * @param error_str Error reason, if any + * @return 0 on success + */ + int delete_snapshot(int iid, int sid, string& error); + private: /** * Generic name for the Image driver diff --git a/include/ImageManagerDriver.h b/include/ImageManagerDriver.h index b1cd750741..2e00397cbf 100644 --- a/include/ImageManagerDriver.h +++ b/include/ImageManagerDriver.h @@ -114,6 +114,27 @@ private: * @param drv_msg xml data for the mad operation. */ void monitor(int oid, const string& drv_msg) const; + + /** + * Sends a delete snapshot command: "SNAP_DELETE DS_ID DS_XML" + * @param oid the datastore id. + * @param drv_msg xml data for the mad operation. + */ + void snapshot_delete(int oid, const string& drv_msg) const; + + /** + * Sends a revert snapshot command: "SNAP_REVERT DS_ID DS_XML" + * @param oid the datastore id. + * @param drv_msg xml data for the mad operation. + */ + void snapshot_revert(int oid, const string& drv_msg) const; + + /** + * Sends a flatten snapshot command: "SNAP_FLATTEN DS_ID DS_XML" + * @param oid the datastore id. + * @param drv_msg xml data for the mad operation. + */ + void snapshot_flatten(int oid, const string& drv_msg) const; }; /* -------------------------------------------------------------------------- */ diff --git a/src/image/ImageManagerActions.cc b/src/image/ImageManagerActions.cc index e72de0f4dc..4ec609d343 100644 --- a/src/image/ImageManagerActions.cc +++ b/src/image/ImageManagerActions.cc @@ -941,3 +941,78 @@ void ImageManager::set_image_snapshots(int iid, const Snapshots& s, bool failed) img->unlock(); } + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int ImageManager::delete_snapshot(int iid, int sid, string& error) +{ + const ImageManagerDriver* imd = get(); + + if ( imd == 0 ) + { + error = "Could not get datastore driver"; + NebulaLog::log("ImM",Log::ERROR, error); + + return -1; + } + + Image * img = ipool->get(iid,true); + + if ( img == 0 ) + { + error = "Image does not exist"; + return -1; + } + + const Snapshots& snaps = img->get_snapshots(); + + if (!snaps.test_delete(sid, error)) + { + img->unlock(); + return -1; + } + + int ds_id = img->get_ds_id(); + + img->unlock(); + + string ds_data; + + Datastore * ds = dspool->get(ds_id, true); + + if ( ds == 0 ) + { + error = "Datastore no longer exists"; + return -1; + } + + ds->to_xml(ds_data); + + ds->unlock(); + + img = ipool->get(iid,true); + + if ( img == 0 ) + { + error = "Image does not exist"; + return -1; + } + + img->set_target_snapshot(sid); + + string img_tmpl; + string * drv_msg = format_message(img->to_xml(img_tmpl), ds_data); + + imd->snapshot_delete(iid, *drv_msg); + + ipool->update(img); + + img->unlock(); + + delete drv_msg; + + return 0; +} + + diff --git a/src/image/ImageManagerDriver.cc b/src/image/ImageManagerDriver.cc index 407c7efae0..7d55444baa 100644 --- a/src/image/ImageManagerDriver.cc +++ b/src/image/ImageManagerDriver.cc @@ -93,6 +93,39 @@ void ImageManagerDriver::monitor(int oid, const string& drv_msg) const write(os); } +/* -------------------------------------------------------------------------- */ + +void ImageManagerDriver::snapshot_delete(int oid, const string& drv_msg) const +{ + ostringstream os; + + os << "SNAP_DELETE " << oid << " " << drv_msg << endl; + + write(os); +} + +/* -------------------------------------------------------------------------- */ + +void ImageManagerDriver::snapshot_revert(int oid, const string& drv_msg) const +{ + ostringstream os; + + os << "SNAP_REVERT " << oid << " " << drv_msg << endl; + + write(os); +} + +/* -------------------------------------------------------------------------- */ + +void ImageManagerDriver::snapshot_flatten(int oid, const string& drv_msg) const +{ + ostringstream os; + + os << "SNAP_FLATTEN " << oid << " " << drv_msg << endl; + + write(os); +} + /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -666,6 +699,60 @@ static void monitor_action(istringstream& is, return; } +/* -------------------------------------------------------------------------- */ + +static void snap_delete_action(istringstream& is, + ImagePool* ipool, + int id, + const string& result) +{ + ostringstream oss; + string info; + + Image * image = ipool->get(id, true); + + if ( image == 0 ) + { + return; + } + + int snap_id = image->get_target_snapshot(); + + if (snap_id == -1) + { + NebulaLog::log("ImM", Log::ERROR, "No target snapshot in callback"); + + image->unlock(); + return; + } + + if ( result == "SUCCESS") + { + image->delete_snapshot(snap_id); + } + else + { + oss << "Error removing snapshot " << snap_id << " from image " << id; + + getline(is, info); + + if (!info.empty() && (info[0] != '-')) + { + oss << ": " << info; + } + + image->set_template_error_message(oss.str()); + + NebulaLog::log("ImM", Log::ERROR, oss); + } + + image->clear_target_snapshot(); + + ipool->update(image); + + image->unlock(); +} + /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -717,30 +804,34 @@ void ImageManagerDriver::protocol(const string& message) const else return; - if ( action == "STAT" ) + if (action == "STAT") { stat_action(is, id, result); } - else if ( action == "CP" ) + else if (action == "CP") { ds_id = cp_action(is, ipool, id, result); } - else if ( action == "CLONE" ) + else if (action == "CLONE") { ds_id = clone_action(is, ipool, id, result); } - else if ( action == "MKFS" ) + else if (action == "MKFS") { ds_id = mkfs_action(is, ipool, id, result); } - else if ( action == "RM" ) + else if (action == "RM") { ds_id = rm_action(is, ipool, id, result); } - else if ( action == "MONITOR" ) + else if (action == "MONITOR") { monitor_action(is, dspool, id, result); } + else if (action == "SNAP_DELETE") + { + snap_delete_action(is, ipool, id, result); + } else if (action == "LOG") { getline(is,info); From 62a98c550d20e049e9aea270db68fb9b1efe0e62 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Fri, 5 Jun 2015 03:24:46 +0200 Subject: [PATCH 51/83] feature #3782: Image XML-RPC methods for snapshot delete --- include/RequestManagerImage.h | 52 +++++++++++++++++++++++++- src/rm/RequestManager.cc | 2 + src/rm/RequestManagerImage.cc | 32 +++++++++++++++- src/rm/RequestManagerVirtualMachine.cc | 12 +++--- 4 files changed, 90 insertions(+), 8 deletions(-) diff --git a/include/RequestManagerImage.h b/include/RequestManagerImage.h index c8e5135a9f..4bc4d9ae26 100644 --- a/include/RequestManagerImage.h +++ b/include/RequestManagerImage.h @@ -119,7 +119,57 @@ public: RequestAttributes& att); }; -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ + +class ImageSnapshotRevert : public RequestManagerImage +{ +public: + ImageSnapshotRevert(): + RequestManagerImage("ImageSnapshotRevert", + "Reverts image state to a previous snapshot", + "A:sis"){}; + + ~ImageSnapshotRevert(){}; + + void request_execute(xmlrpc_c::paramList const& _paramList, + RequestAttributes& att); +}; + +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ + +class ImageSnapshotFlatten : public RequestManagerImage +{ +public: + ImageSnapshotFlatten(): + RequestManagerImage("ImageSnapshotFlatten", + "Flattens the selected image snapshot", + "A:sii"){}; + + ~ImageSnapshotFlatten(){}; + + void request_execute(xmlrpc_c::paramList const& _paramList, + RequestAttributes& att); +}; + +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ + +class ImageSnapshotDelete : public RequestManagerImage +{ +public: + ImageSnapshotDelete(): + RequestManagerImage("ImageSnapshotDelete", + "Deletes a snapshot from image", + "A:sii"){}; + + ~ImageSnapshotDelete(){}; + + void request_execute(xmlrpc_c::paramList const& _paramList, + RequestAttributes& att); +}; + /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ diff --git a/src/rm/RequestManager.cc b/src/rm/RequestManager.cc index 9d00465815..c5f1362690 100644 --- a/src/rm/RequestManager.cc +++ b/src/rm/RequestManager.cc @@ -397,6 +397,7 @@ void RequestManager::register_xml_methods() xmlrpc_c::methodPtr image_enable(new ImageEnable()); xmlrpc_c::methodPtr image_chtype(new ImageChangeType()); xmlrpc_c::methodPtr image_clone(new ImageClone()); + xmlrpc_c::methodPtr image_snap_delete(new ImageSnapshotDelete()); // Datastore Methods xmlrpc_c::methodPtr datastore_enable(new DatastoreEnable()); @@ -653,6 +654,7 @@ void RequestManager::register_xml_methods() RequestManagerRegistry.addMethod("one.image.chtype", image_chtype); RequestManagerRegistry.addMethod("one.image.clone", image_clone); RequestManagerRegistry.addMethod("one.image.rename", image_rename); + RequestManagerRegistry.addMethod("one.image.snapshotdelete", image_snap_delete); RequestManagerRegistry.addMethod("one.imagepool.info", imagepool_info); diff --git a/src/rm/RequestManagerImage.cc b/src/rm/RequestManagerImage.cc index 1e934ba6c6..1b7dd73db9 100644 --- a/src/rm/RequestManagerImage.cc +++ b/src/rm/RequestManagerImage.cc @@ -280,7 +280,9 @@ void ImageClone::request_execute( return; } - if (img->get_snapshots_size () > 0) + const Snapshots& snaps = img->get_snapshots(); + + if (snaps.size () > 0) { failure_response(ACTION, request_error("Cannot clone images with snapshots",""), att); @@ -467,4 +469,32 @@ void ImageClone::request_execute( success_response(new_id, att); } +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ + +void ImageSnapshotDelete::request_execute(xmlrpc_c::paramList const& paramList, + RequestAttributes& att) +{ + int id = xmlrpc_c::value_int(paramList.getInt(1)); + int snap_id = xmlrpc_c::value_int(paramList.getInt(2)); + + Nebula& nd = Nebula::instance(); + ImageManager * imagem = nd.get_imagem(); + + if ( basic_authorization(id, att) == false ) + { + return; + } + + string err_msg; + int rc = imagem->delete_snapshot(id, snap_id, err_msg); + + if ( rc < 0 ) + { + failure_response(ACTION, request_error(err_msg, ""), att); + return; + } + + success_response(id, att); +} diff --git a/src/rm/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc index 5e1051a409..afa1c4a743 100644 --- a/src/rm/RequestManagerVirtualMachine.cc +++ b/src/rm/RequestManagerVirtualMachine.cc @@ -2494,13 +2494,13 @@ void VirtualMachineDiskSnapshotCreate::request_execute( Nebula& nd = Nebula::instance(); DispatchManager * dm = nd.get_dm(); - int rc; - int snap_id; - string error_str; + int rc; + int snap_id; + string error_str; - int id = xmlrpc_c::value_int(paramList.getInt(1)); - int did = xmlrpc_c::value_int(paramList.getInt(2)); - string tag = xmlrpc_c::value_string(paramList.getString(3)); + int id = xmlrpc_c::value_int(paramList.getInt(1)); + int did = xmlrpc_c::value_int(paramList.getInt(2)); + string tag = xmlrpc_c::value_string(paramList.getString(3)); if ( vm_authorization(id, 0, 0, att, 0, 0, auth_op) == false ) { From 78c7bdbd5d890b63aaea447b85a7d2fa7a0f8bc4 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Fri, 5 Jun 2015 03:27:51 +0200 Subject: [PATCH 52/83] feature #3782: Ruby OCA method for snapshot-delete, cli command. Datastore driver action for snapshot delete --- src/cli/oneimage | 10 ++++++++++ src/datastore_mad/one_datastore.rb | 12 ++++++++++-- src/oca/ruby/opennebula/image.rb | 12 +++++++++++- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/cli/oneimage b/src/cli/oneimage index b0ce67d352..c754442a85 100755 --- a/src/cli/oneimage +++ b/src/cli/oneimage @@ -301,6 +301,16 @@ cmd=CommandParser::CmdParser.new(ARGV) do end end + snapshot_delete_desc = <<-EOT.unindent + Deletes a snapshot from the image + EOT + + command :"snapshot-delete", snapshot_delete_desc, :imageid, :snapshot_id do + helper.perform_action(args[0], options, "snapshot deleted") do |o| + o.snapshot_delete(args[1].to_i) + end + end + list_desc = <<-EOT.unindent Lists Images in the pool EOT diff --git a/src/datastore_mad/one_datastore.rb b/src/datastore_mad/one_datastore.rb index eeaceb4bd5..5f00080bdd 100755 --- a/src/datastore_mad/one_datastore.rb +++ b/src/datastore_mad/one_datastore.rb @@ -50,7 +50,8 @@ class DatastoreDriver < OpenNebulaDriver :log => "LOG", :stat => "STAT", :clone => "CLONE", - :monitor => "MONITOR" + :monitor => "MONITOR", + :snap_delete => "SNAP_DELETE" } # Register default actions for the protocol @@ -65,7 +66,8 @@ class DatastoreDriver < OpenNebulaDriver ACTION[:rm] => nil, ACTION[:mkfs] => nil, ACTION[:clone] => nil, - ACTION[:monitor] => nil + ACTION[:monitor] => nil, + ACTION[:snap_delete] => nil } }.merge!(options) @@ -87,6 +89,7 @@ class DatastoreDriver < OpenNebulaDriver register_action(ACTION[:stat].to_sym, method("stat")) register_action(ACTION[:clone].to_sym, method("clone")) register_action(ACTION[:monitor].to_sym, method("monitor")) + register_action(ACTION[:snap_delete].to_sym, method("snap_delete")) end ############################################################################ @@ -123,6 +126,11 @@ class DatastoreDriver < OpenNebulaDriver do_image_action(id, ds, :monitor, "#{drv_message} #{id}", true) end + def snap_delete(id, drv_message) + ds = get_ds_type(drv_message) + do_image_action(id, ds, :snap_delete, "#{drv_message} #{id}") + end + private def is_available?(ds, id, action) diff --git a/src/oca/ruby/opennebula/image.rb b/src/oca/ruby/opennebula/image.rb index c090a865c6..a1024cdf35 100644 --- a/src/oca/ruby/opennebula/image.rb +++ b/src/oca/ruby/opennebula/image.rb @@ -36,7 +36,8 @@ module OpenNebula :chmod => "image.chmod", :chtype => "image.chtype", :clone => "image.clone", - :rename => "image.rename" + :rename => "image.rename", + :snapshotdelete => "image.snapshotdelete" } IMAGE_STATES=%w{INIT READY USED DISABLED LOCKED ERROR CLONE DELETE USED_PERS} @@ -224,6 +225,15 @@ module OpenNebula return call(IMAGE_METHODS[:rename], @pe_id, name) end + # Deletes Image from snapshot + # + # @param snap_id [Integet] ID of the snapshot to delete + # + # @return [nil, OpenNebula::Error] nil in case of success or Error + def snapshot_delete(snap_id) + return call(IMAGE_METHODS[:snapshotdelete], @pe_id, snap_id) + end + ####################################################################### # Helpers to get Image information ####################################################################### From 9348a0d455955ce923ad9d32dbb258152d985ddb Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Fri, 5 Jun 2015 04:45:20 +0200 Subject: [PATCH 53/83] feature #3782: Revert action for images --- include/ImageManager.h | 17 +++++-- include/RequestManagerImage.h | 2 +- src/cli/oneimage | 10 ++++ src/datastore_mad/one_datastore.rb | 12 ++++- src/image/ImageManagerActions.cc | 74 ++++++++++++++++++++++++++++++ src/image/ImageManagerDriver.cc | 58 +++++++++++++++++++++++ src/oca/ruby/opennebula/image.rb | 13 +++++- src/rm/RequestManager.cc | 2 + src/rm/RequestManagerImage.cc | 30 ++++++++++++ 9 files changed, 209 insertions(+), 9 deletions(-) diff --git a/include/ImageManager.h b/include/ImageManager.h index 04f87f2ede..8be735fbf1 100644 --- a/include/ImageManager.h +++ b/include/ImageManager.h @@ -201,13 +201,22 @@ public: /** * Deletes the snapshot of an image - * @param iid id of image - * @param sid id of the snapshot - * @param error_str Error reason, if any - * @return 0 on success + * @param iid id of image + * @param sid id of the snapshot + * @param error_str Error reason, if any + * @return 0 on success */ int delete_snapshot(int iid, int sid, string& error); + /** + * Reverts image state to a previous snapshot + * @param iid id of image + * @param sid id of the snapshot + * @param error_str Error reason, if any + * @return 0 on success + */ + int revert_snapshot(int iid, int sid, string& error); + private: /** * Generic name for the Image driver diff --git a/include/RequestManagerImage.h b/include/RequestManagerImage.h index 4bc4d9ae26..e56b8a4f9b 100644 --- a/include/RequestManagerImage.h +++ b/include/RequestManagerImage.h @@ -128,7 +128,7 @@ public: ImageSnapshotRevert(): RequestManagerImage("ImageSnapshotRevert", "Reverts image state to a previous snapshot", - "A:sis"){}; + "A:sii"){}; ~ImageSnapshotRevert(){}; diff --git a/src/cli/oneimage b/src/cli/oneimage index c754442a85..19f23a4fa0 100755 --- a/src/cli/oneimage +++ b/src/cli/oneimage @@ -311,6 +311,16 @@ cmd=CommandParser::CmdParser.new(ARGV) do end end + snapshot_revert_desc = <<-EOT.unindent + Reverts image state to a snapshot + EOT + + command :"snapshot-revert", snapshot_revert_desc, :imageid, :snapshot_id do + helper.perform_action(args[0], options, "image state reverted") do |o| + o.snapshot_revert(args[1].to_i) + end + end + list_desc = <<-EOT.unindent Lists Images in the pool EOT diff --git a/src/datastore_mad/one_datastore.rb b/src/datastore_mad/one_datastore.rb index 5f00080bdd..9c791c114f 100755 --- a/src/datastore_mad/one_datastore.rb +++ b/src/datastore_mad/one_datastore.rb @@ -51,7 +51,8 @@ class DatastoreDriver < OpenNebulaDriver :stat => "STAT", :clone => "CLONE", :monitor => "MONITOR", - :snap_delete => "SNAP_DELETE" + :snap_delete => "SNAP_DELETE", + :snap_revert => "SNAP_REVERT" } # Register default actions for the protocol @@ -67,7 +68,8 @@ class DatastoreDriver < OpenNebulaDriver ACTION[:mkfs] => nil, ACTION[:clone] => nil, ACTION[:monitor] => nil, - ACTION[:snap_delete] => nil + ACTION[:snap_delete] => nil, + ACTION[:snap_revert] => nil } }.merge!(options) @@ -90,6 +92,7 @@ class DatastoreDriver < OpenNebulaDriver register_action(ACTION[:clone].to_sym, method("clone")) register_action(ACTION[:monitor].to_sym, method("monitor")) register_action(ACTION[:snap_delete].to_sym, method("snap_delete")) + register_action(ACTION[:snap_revert].to_sym, method("snap_revert")) end ############################################################################ @@ -131,6 +134,11 @@ class DatastoreDriver < OpenNebulaDriver do_image_action(id, ds, :snap_delete, "#{drv_message} #{id}") end + def snap_revert(id, drv_message) + ds = get_ds_type(drv_message) + do_image_action(id, ds, :snap_revert, "#{drv_message} #{id}") + end + private def is_available?(ds, id, action) diff --git a/src/image/ImageManagerActions.cc b/src/image/ImageManagerActions.cc index 4ec609d343..aa5f5c5930 100644 --- a/src/image/ImageManagerActions.cc +++ b/src/image/ImageManagerActions.cc @@ -1015,4 +1015,78 @@ int ImageManager::delete_snapshot(int iid, int sid, string& error) return 0; } +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int ImageManager::revert_snapshot(int iid, int sid, string& error) +{ + const ImageManagerDriver* imd = get(); + + if ( imd == 0 ) + { + error = "Could not get datastore driver"; + NebulaLog::log("ImM",Log::ERROR, error); + + return -1; + } + + Image * img = ipool->get(iid,true); + + if ( img == 0 ) + { + error = "Image does not exist"; + return -1; + } + + const Snapshots& snaps = img->get_snapshots(); + + if (snaps.get_active_id() == sid) + { + error = "Snapshot is already the active one"; + + img->unlock(); + return -1; + } + + int ds_id = img->get_ds_id(); + + img->unlock(); + + string ds_data; + + Datastore * ds = dspool->get(ds_id, true); + + if ( ds == 0 ) + { + error = "Datastore no longer exists"; + return -1; + } + + ds->to_xml(ds_data); + + ds->unlock(); + + img = ipool->get(iid,true); + + if ( img == 0 ) + { + error = "Image does not exist"; + return -1; + } + + img->set_target_snapshot(sid); + + string img_tmpl; + string * drv_msg = format_message(img->to_xml(img_tmpl), ds_data); + + imd->snapshot_revert(iid, *drv_msg); + + ipool->update(img); + + img->unlock(); + + delete drv_msg; + + return 0; +} diff --git a/src/image/ImageManagerDriver.cc b/src/image/ImageManagerDriver.cc index 7d55444baa..9ca04e24e3 100644 --- a/src/image/ImageManagerDriver.cc +++ b/src/image/ImageManagerDriver.cc @@ -753,6 +753,60 @@ static void snap_delete_action(istringstream& is, image->unlock(); } +/* -------------------------------------------------------------------------- */ + +static void snap_revert_action(istringstream& is, + ImagePool* ipool, + int id, + const string& result) +{ + ostringstream oss; + string info; + + Image * image = ipool->get(id, true); + + if ( image == 0 ) + { + return; + } + + int snap_id = image->get_target_snapshot(); + + if (snap_id == -1) + { + NebulaLog::log("ImM", Log::ERROR, "No target snapshot in callback"); + + image->unlock(); + return; + } + + if ( result == "SUCCESS") + { + image->revert_snapshot(snap_id); + } + else + { + oss << "Error reverting image " << id << " to snapshot " << snap_id; + + getline(is, info); + + if (!info.empty() && (info[0] != '-')) + { + oss << ": " << info; + } + + image->set_template_error_message(oss.str()); + + NebulaLog::log("ImM", Log::ERROR, oss); + } + + image->clear_target_snapshot(); + + ipool->update(image); + + image->unlock(); +} + /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -832,6 +886,10 @@ void ImageManagerDriver::protocol(const string& message) const { snap_delete_action(is, ipool, id, result); } + else if (action == "SNAP_REVERT") + { + snap_revert_action(is, ipool, id, result); + } else if (action == "LOG") { getline(is,info); diff --git a/src/oca/ruby/opennebula/image.rb b/src/oca/ruby/opennebula/image.rb index a1024cdf35..c5d9f61837 100644 --- a/src/oca/ruby/opennebula/image.rb +++ b/src/oca/ruby/opennebula/image.rb @@ -24,7 +24,6 @@ module OpenNebula # Constants and Class Methods ####################################################################### - IMAGE_METHODS = { :info => "image.info", :allocate => "image.allocate", @@ -37,7 +36,8 @@ module OpenNebula :chtype => "image.chtype", :clone => "image.clone", :rename => "image.rename", - :snapshotdelete => "image.snapshotdelete" + :snapshotdelete => "image.snapshotdelete", + :snapshotrevert => "image.snapshotrevert" } IMAGE_STATES=%w{INIT READY USED DISABLED LOCKED ERROR CLONE DELETE USED_PERS} @@ -234,6 +234,15 @@ module OpenNebula return call(IMAGE_METHODS[:snapshotdelete], @pe_id, snap_id) end + # Reverts Image state to a previous snapshot + # + # @param snap_id [Integet] ID of the snapshot to delete + # + # @return [nil, OpenNebula::Error] nil in case of success or Error + def snapshot_revert(snap_id) + return call(IMAGE_METHODS[:snapshotrevert], @pe_id, snap_id) + end + ####################################################################### # Helpers to get Image information ####################################################################### diff --git a/src/rm/RequestManager.cc b/src/rm/RequestManager.cc index c5f1362690..15616dd1d7 100644 --- a/src/rm/RequestManager.cc +++ b/src/rm/RequestManager.cc @@ -398,6 +398,7 @@ void RequestManager::register_xml_methods() xmlrpc_c::methodPtr image_chtype(new ImageChangeType()); xmlrpc_c::methodPtr image_clone(new ImageClone()); xmlrpc_c::methodPtr image_snap_delete(new ImageSnapshotDelete()); + xmlrpc_c::methodPtr image_snap_revert(new ImageSnapshotRevert()); // Datastore Methods xmlrpc_c::methodPtr datastore_enable(new DatastoreEnable()); @@ -655,6 +656,7 @@ void RequestManager::register_xml_methods() RequestManagerRegistry.addMethod("one.image.clone", image_clone); RequestManagerRegistry.addMethod("one.image.rename", image_rename); RequestManagerRegistry.addMethod("one.image.snapshotdelete", image_snap_delete); + RequestManagerRegistry.addMethod("one.image.snapshotrevert", image_snap_revert); RequestManagerRegistry.addMethod("one.imagepool.info", imagepool_info); diff --git a/src/rm/RequestManagerImage.cc b/src/rm/RequestManagerImage.cc index 1b7dd73db9..5a7768da7c 100644 --- a/src/rm/RequestManagerImage.cc +++ b/src/rm/RequestManagerImage.cc @@ -498,3 +498,33 @@ void ImageSnapshotDelete::request_execute(xmlrpc_c::paramList const& paramList, success_response(id, att); } + +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ + +void ImageSnapshotRevert::request_execute(xmlrpc_c::paramList const& paramList, + RequestAttributes& att) +{ + int id = xmlrpc_c::value_int(paramList.getInt(1)); + int snap_id = xmlrpc_c::value_int(paramList.getInt(2)); + + Nebula& nd = Nebula::instance(); + ImageManager * imagem = nd.get_imagem(); + + if ( basic_authorization(id, att) == false ) + { + return; + } + + string err_msg; + int rc = imagem->revert_snapshot(id, snap_id, err_msg); + + if ( rc < 0 ) + { + failure_response(ACTION, request_error(err_msg, ""), att); + return; + } + + success_response(id, att); +} + From 0bbb99a2405604deff0cea4ef99112abe4a51fce Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Fri, 5 Jun 2015 13:32:00 +0200 Subject: [PATCH 54/83] feature #3782: Image are in LOCKED state while performing snapshot operations --- include/Snapshots.h | 12 ++++++ src/image/ImageManagerActions.cc | 69 +++++++++++++++++++++++++------- src/image/ImageManagerDriver.cc | 8 ++++ 3 files changed, 74 insertions(+), 15 deletions(-) diff --git a/include/Snapshots.h b/include/Snapshots.h index 098110eced..eba353bf01 100644 --- a/include/Snapshots.h +++ b/include/Snapshots.h @@ -143,6 +143,18 @@ public: return snapshot_pool.size(); }; + /** + * Check if snapshot exists + * @param snap_id of the snapshot + * @return true if the snapshot with snap_id exisits + */ + bool exists(int snap_id) const + { + const VectorAttribute * snap = get_snapshot(snap_id); + + return (snap != 0); + } + /** * Get Attribute from the given snapshot * @param id of the snapshot diff --git a/src/image/ImageManagerActions.cc b/src/image/ImageManagerActions.cc index aa5f5c5930..3cf9c5c5f4 100644 --- a/src/image/ImageManagerActions.cc +++ b/src/image/ImageManagerActions.cc @@ -918,21 +918,10 @@ void ImageManager::set_image_snapshots(int iid, const Snapshots& s, bool failed) return; } - switch (img->get_state()) + if (img->get_state() != Image::USED_PERS) { - case Image::USED_PERS: - break; - - case Image::USED: - case Image::LOCKED: - case Image::CLONE: - case Image::DELETE: - case Image::INIT: - case Image::DISABLED: - case Image::READY: - case Image::ERROR: - img->unlock(); - return; + img->unlock(); + return; } img->set_snapshots(s); @@ -957,6 +946,11 @@ int ImageManager::delete_snapshot(int iid, int sid, string& error) return -1; } + /* ---------------------------------------------------------------------- */ + /* Check action consistency: */ + /* state is READY */ + /* snapshot can be deleted (not active, no childs, exists) */ + /* ---------------------------------------------------------------------- */ Image * img = ipool->get(iid,true); if ( img == 0 ) @@ -965,6 +959,13 @@ int ImageManager::delete_snapshot(int iid, int sid, string& error) return -1; } + if (img->get_state() != Image::READY) + { + error = "Cannot delete snapshot in state " + Image::state_to_str(img->get_state()); + img->unlock(); + return -1; + } + const Snapshots& snaps = img->get_snapshots(); if (!snaps.test_delete(sid, error)) @@ -973,6 +974,9 @@ int ImageManager::delete_snapshot(int iid, int sid, string& error) return -1; } + /* ---------------------------------------------------------------------- */ + /* Get DS data for driver */ + /* ---------------------------------------------------------------------- */ int ds_id = img->get_ds_id(); img->unlock(); @@ -993,6 +997,9 @@ int ImageManager::delete_snapshot(int iid, int sid, string& error) img = ipool->get(iid,true); + /* ---------------------------------------------------------------------- */ + /* Format message and send action to driver */ + /* ---------------------------------------------------------------------- */ if ( img == 0 ) { error = "Image does not exist"; @@ -1006,6 +1013,8 @@ int ImageManager::delete_snapshot(int iid, int sid, string& error) imd->snapshot_delete(iid, *drv_msg); + img->set_state(Image::LOCKED); + ipool->update(img); img->unlock(); @@ -1030,6 +1039,13 @@ int ImageManager::revert_snapshot(int iid, int sid, string& error) return -1; } + /* ---------------------------------------------------------------------- */ + /* Check action consistency: */ + /* state is READY */ + /* snapshot exists */ + /* snapshot is not the active one */ + /* ---------------------------------------------------------------------- */ + Image * img = ipool->get(iid,true); if ( img == 0 ) @@ -1038,8 +1054,23 @@ int ImageManager::revert_snapshot(int iid, int sid, string& error) return -1; } + if (img->get_state() != Image::READY) + { + error = "Cannot revert to snapshot in state " + Image::state_to_str(img->get_state()); + img->unlock(); + return -1; + } + const Snapshots& snaps = img->get_snapshots(); + if (!snaps.exists(sid)) + { + error = "Snapshot does not exist"; + + img->unlock(); + return -1; + } + if (snaps.get_active_id() == sid) { error = "Snapshot is already the active one"; @@ -1048,6 +1079,9 @@ int ImageManager::revert_snapshot(int iid, int sid, string& error) return -1; } + /* ---------------------------------------------------------------------- */ + /* Get DS data for driver */ + /* ---------------------------------------------------------------------- */ int ds_id = img->get_ds_id(); img->unlock(); @@ -1066,6 +1100,9 @@ int ImageManager::revert_snapshot(int iid, int sid, string& error) ds->unlock(); + /* ---------------------------------------------------------------------- */ + /* Format message and send action to driver */ + /* ---------------------------------------------------------------------- */ img = ipool->get(iid,true); if ( img == 0 ) @@ -1076,11 +1113,13 @@ int ImageManager::revert_snapshot(int iid, int sid, string& error) img->set_target_snapshot(sid); - string img_tmpl; + string img_tmpl; string * drv_msg = format_message(img->to_xml(img_tmpl), ds_data); imd->snapshot_revert(iid, *drv_msg); + img->set_state(Image::LOCKED); + ipool->update(img); img->unlock(); diff --git a/src/image/ImageManagerDriver.cc b/src/image/ImageManagerDriver.cc index 9ca04e24e3..fa6dec4442 100644 --- a/src/image/ImageManagerDriver.cc +++ b/src/image/ImageManagerDriver.cc @@ -716,12 +716,16 @@ static void snap_delete_action(istringstream& is, return; } + image->set_state(Image::READY); + int snap_id = image->get_target_snapshot(); if (snap_id == -1) { NebulaLog::log("ImM", Log::ERROR, "No target snapshot in callback"); + ipool->update(image); + image->unlock(); return; } @@ -772,10 +776,14 @@ static void snap_revert_action(istringstream& is, int snap_id = image->get_target_snapshot(); + image->set_state(Image::READY); + if (snap_id == -1) { NebulaLog::log("ImM", Log::ERROR, "No target snapshot in callback"); + ipool->update(image); + image->unlock(); return; } From 08356ed8c311b1f97c4cfa538854427857e7dcab Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Fri, 5 Jun 2015 16:01:06 +0200 Subject: [PATCH 55/83] feature #3782: Flatten action for Images --- include/Image.h | 8 +++ include/ImageManager.h | 9 +++ include/Snapshots.h | 13 ++++ src/cli/oneimage | 10 ++++ src/datastore_mad/one_datastore.rb | 12 +++- src/image/ImageManagerActions.cc | 96 ++++++++++++++++++++++++++++++ src/image/ImageManagerDriver.cc | 50 ++++++++++++++++ src/oca/ruby/opennebula/image.rb | 11 +++- src/rm/RequestManager.cc | 2 + src/rm/RequestManagerImage.cc | 30 +++++++++- 10 files changed, 237 insertions(+), 4 deletions(-) diff --git a/include/Image.h b/include/Image.h index f3687dede2..1ff370ea52 100644 --- a/include/Image.h +++ b/include/Image.h @@ -496,6 +496,14 @@ public: return snapshots; }; + /** + * Clear all the snapshots in the list + */ + void clear_snapshots() + { + snapshots.clear(); + } + /** * Set the snapshots for this image * @param snapshot list diff --git a/include/ImageManager.h b/include/ImageManager.h index 8be735fbf1..a12ece2ed1 100644 --- a/include/ImageManager.h +++ b/include/ImageManager.h @@ -217,6 +217,15 @@ public: */ int revert_snapshot(int iid, int sid, string& error); + /** + * Flattens ths snapshot by commiting changes to base image. + * @param iid id of image + * @param sid id of the snapshot + * @param error_str Error reason, if any + * @return 0 on success + */ + int flatten_snapshot(int iid, int sid, string& error); + private: /** * Generic name for the Image driver diff --git a/include/Snapshots.h b/include/Snapshots.h index eba353bf01..adbfea9a8c 100644 --- a/include/Snapshots.h +++ b/include/Snapshots.h @@ -100,6 +100,19 @@ public: */ int active_snapshot(unsigned int id); + /** + * Clear all the snapshots in the list + */ + void clear() + { + next_snapshot = 0; + active = -1; + disk_id = -1; + + snapshot_template.clear(); + snapshot_pool.clear(); + } + /** * Return the disk_id of the snapshot list */ diff --git a/src/cli/oneimage b/src/cli/oneimage index 19f23a4fa0..431f764a1b 100755 --- a/src/cli/oneimage +++ b/src/cli/oneimage @@ -321,6 +321,16 @@ cmd=CommandParser::CmdParser.new(ARGV) do end end + snapshot_flatten_desc = <<-EOT.unindent + Flattens the snapshot and removes all other snapshots in the image + EOT + + command :"snapshot-flatten", snapshot_flatten_desc, :imageid, :snapshot_id do + helper.perform_action(args[0], options, "snapshot flattened") do |o| + o.snapshot_flatten(args[1].to_i) + end + end + list_desc = <<-EOT.unindent Lists Images in the pool EOT diff --git a/src/datastore_mad/one_datastore.rb b/src/datastore_mad/one_datastore.rb index 9c791c114f..a0680c01db 100755 --- a/src/datastore_mad/one_datastore.rb +++ b/src/datastore_mad/one_datastore.rb @@ -52,7 +52,8 @@ class DatastoreDriver < OpenNebulaDriver :clone => "CLONE", :monitor => "MONITOR", :snap_delete => "SNAP_DELETE", - :snap_revert => "SNAP_REVERT" + :snap_revert => "SNAP_REVERT", + :snap_flatten=> "SNAP_FLATTEN" } # Register default actions for the protocol @@ -69,7 +70,8 @@ class DatastoreDriver < OpenNebulaDriver ACTION[:clone] => nil, ACTION[:monitor] => nil, ACTION[:snap_delete] => nil, - ACTION[:snap_revert] => nil + ACTION[:snap_revert] => nil, + ACTION[:snap_flatten] => nil } }.merge!(options) @@ -93,6 +95,7 @@ class DatastoreDriver < OpenNebulaDriver register_action(ACTION[:monitor].to_sym, method("monitor")) register_action(ACTION[:snap_delete].to_sym, method("snap_delete")) register_action(ACTION[:snap_revert].to_sym, method("snap_revert")) + register_action(ACTION[:snap_flatten].to_sym, method("snap_flatten")) end ############################################################################ @@ -139,6 +142,11 @@ class DatastoreDriver < OpenNebulaDriver do_image_action(id, ds, :snap_revert, "#{drv_message} #{id}") end + def snap_flatten(id, drv_message) + ds = get_ds_type(drv_message) + do_image_action(id, ds, :snap_flatten, "#{drv_message} #{id}") + end + private def is_available?(ds, id, action) diff --git a/src/image/ImageManagerActions.cc b/src/image/ImageManagerActions.cc index 3cf9c5c5f4..0fabd69811 100644 --- a/src/image/ImageManagerActions.cc +++ b/src/image/ImageManagerActions.cc @@ -1129,3 +1129,99 @@ int ImageManager::revert_snapshot(int iid, int sid, string& error) return 0; } +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int ImageManager::flatten_snapshot(int iid, int sid, string& error) +{ + const ImageManagerDriver* imd = get(); + + if ( imd == 0 ) + { + error = "Could not get datastore driver"; + NebulaLog::log("ImM",Log::ERROR, error); + + return -1; + } + + /* ---------------------------------------------------------------------- */ + /* Check action consistency: */ + /* state is READY */ + /* snapshot exists */ + /* ---------------------------------------------------------------------- */ + + Image * img = ipool->get(iid,true); + + if ( img == 0 ) + { + error = "Image does not exist"; + return -1; + } + + if (img->get_state() != Image::READY) + { + error = "Cannot flatten snapshot in state " + Image::state_to_str(img->get_state()); + img->unlock(); + return -1; + } + + const Snapshots& snaps = img->get_snapshots(); + + if (!snaps.exists(sid)) + { + error = "Snapshot does not exist"; + + img->unlock(); + return -1; + } + + /* ---------------------------------------------------------------------- */ + /* Get DS data for driver */ + /* ---------------------------------------------------------------------- */ + int ds_id = img->get_ds_id(); + + img->unlock(); + + string ds_data; + + Datastore * ds = dspool->get(ds_id, true); + + if ( ds == 0 ) + { + error = "Datastore no longer exists"; + return -1; + } + + ds->to_xml(ds_data); + + ds->unlock(); + + /* ---------------------------------------------------------------------- */ + /* Format message and send action to driver */ + /* ---------------------------------------------------------------------- */ + img = ipool->get(iid,true); + + if ( img == 0 ) + { + error = "Image does not exist"; + return -1; + } + + img->set_target_snapshot(sid); + + string img_tmpl; + string * drv_msg = format_message(img->to_xml(img_tmpl), ds_data); + + imd->snapshot_flatten(iid, *drv_msg); + + img->set_state(Image::LOCKED); + + ipool->update(img); + + img->unlock(); + + delete drv_msg; + + return 0; +} + diff --git a/src/image/ImageManagerDriver.cc b/src/image/ImageManagerDriver.cc index fa6dec4442..cb83c6566b 100644 --- a/src/image/ImageManagerDriver.cc +++ b/src/image/ImageManagerDriver.cc @@ -815,6 +815,52 @@ static void snap_revert_action(istringstream& is, image->unlock(); } +/* -------------------------------------------------------------------------- */ + +static void snap_flatten_action(istringstream& is, + ImagePool* ipool, + int id, + const string& result) +{ + ostringstream oss; + string info; + + Image * image = ipool->get(id, true); + + if ( image == 0 ) + { + return; + } + + if ( result == "SUCCESS") + { + image->clear_snapshots(); + } + else + { + oss << "Error flattening image snapshot"; + + getline(is, info); + + if (!info.empty() && (info[0] != '-')) + { + oss << ": " << info; + } + + image->set_template_error_message(oss.str()); + + NebulaLog::log("ImM", Log::ERROR, oss); + } + + image->set_state(Image::READY); + + image->clear_target_snapshot(); + + ipool->update(image); + + image->unlock(); +} + /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -898,6 +944,10 @@ void ImageManagerDriver::protocol(const string& message) const { snap_revert_action(is, ipool, id, result); } + else if (action == "SNAP_FLATTEN") + { + snap_flatten_action(is, ipool, id, result); + } else if (action == "LOG") { getline(is,info); diff --git a/src/oca/ruby/opennebula/image.rb b/src/oca/ruby/opennebula/image.rb index c5d9f61837..3940989487 100644 --- a/src/oca/ruby/opennebula/image.rb +++ b/src/oca/ruby/opennebula/image.rb @@ -37,7 +37,8 @@ module OpenNebula :clone => "image.clone", :rename => "image.rename", :snapshotdelete => "image.snapshotdelete", - :snapshotrevert => "image.snapshotrevert" + :snapshotrevert => "image.snapshotrevert", + :snapshotflatten=> "image.snapshotflatten" } IMAGE_STATES=%w{INIT READY USED DISABLED LOCKED ERROR CLONE DELETE USED_PERS} @@ -243,6 +244,14 @@ module OpenNebula return call(IMAGE_METHODS[:snapshotrevert], @pe_id, snap_id) end + # Flattens an image snapshot + # + # @param snap_id [Integet] ID of the snapshot to flatten + # + # @return [nil, OpenNebula::Error] nil in case of success or Error + def snapshot_flatten(snap_id) + return call(IMAGE_METHODS[:snapshotflatten], @pe_id, snap_id) + end ####################################################################### # Helpers to get Image information ####################################################################### diff --git a/src/rm/RequestManager.cc b/src/rm/RequestManager.cc index 15616dd1d7..a390631b72 100644 --- a/src/rm/RequestManager.cc +++ b/src/rm/RequestManager.cc @@ -399,6 +399,7 @@ void RequestManager::register_xml_methods() xmlrpc_c::methodPtr image_clone(new ImageClone()); xmlrpc_c::methodPtr image_snap_delete(new ImageSnapshotDelete()); xmlrpc_c::methodPtr image_snap_revert(new ImageSnapshotRevert()); + xmlrpc_c::methodPtr image_snap_flatten(new ImageSnapshotFlatten()); // Datastore Methods xmlrpc_c::methodPtr datastore_enable(new DatastoreEnable()); @@ -657,6 +658,7 @@ void RequestManager::register_xml_methods() RequestManagerRegistry.addMethod("one.image.rename", image_rename); RequestManagerRegistry.addMethod("one.image.snapshotdelete", image_snap_delete); RequestManagerRegistry.addMethod("one.image.snapshotrevert", image_snap_revert); + RequestManagerRegistry.addMethod("one.image.snapshotflatten", image_snap_flatten); RequestManagerRegistry.addMethod("one.imagepool.info", imagepool_info); diff --git a/src/rm/RequestManagerImage.cc b/src/rm/RequestManagerImage.cc index 5a7768da7c..f13dc45170 100644 --- a/src/rm/RequestManagerImage.cc +++ b/src/rm/RequestManagerImage.cc @@ -498,7 +498,6 @@ void ImageSnapshotDelete::request_execute(xmlrpc_c::paramList const& paramList, success_response(id, att); } - /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ @@ -528,3 +527,32 @@ void ImageSnapshotRevert::request_execute(xmlrpc_c::paramList const& paramList, success_response(id, att); } +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ + +void ImageSnapshotFlatten::request_execute(xmlrpc_c::paramList const& paramList, + RequestAttributes& att) +{ + int id = xmlrpc_c::value_int(paramList.getInt(1)); + int snap_id = xmlrpc_c::value_int(paramList.getInt(2)); + + Nebula& nd = Nebula::instance(); + ImageManager * imagem = nd.get_imagem(); + + if ( basic_authorization(id, att) == false ) + { + return; + } + + string err_msg; + int rc = imagem->flatten_snapshot(id, snap_id, err_msg); + + if ( rc < 0 ) + { + failure_response(ACTION, request_error(err_msg, ""), att); + return; + } + + success_response(id, att); +} + From ce6f465b9546dfc3ec0faaa0ea606257790e54d6 Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Fri, 5 Jun 2015 11:06:11 -0400 Subject: [PATCH 56/83] Only create predefined set of filesystems --- src/mad/sh/scripts_common.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/mad/sh/scripts_common.sh b/src/mad/sh/scripts_common.sh index 343e869186..43317bce2f 100644 --- a/src/mad/sh/scripts_common.sh +++ b/src/mad/sh/scripts_common.sh @@ -320,7 +320,7 @@ function mkfs_command { OPTS="-F" ;; - "reiserfs") + "reiserfs"|"xfs") OPTS="-f -q" ;; @@ -355,7 +355,9 @@ function mkfs_command { return 0 ;; *) - OPTS="" + echo "" + echo "Filesystem '$FSTYPE' not valid." 1>&2 + return 1 ;; esac From ced1a29bfb3f3d1991ea88e658ea9462071fe4b8 Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Fri, 5 Jun 2015 11:31:30 -0400 Subject: [PATCH 57/83] Copy ONE_AUTH and ONE_XMLRPC before stripping The strings that come from the environment are frozen and cannot be modified. --- src/oca/ruby/opennebula/client.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/oca/ruby/opennebula/client.rb b/src/oca/ruby/opennebula/client.rb index 3f730d0bab..a733dd5269 100644 --- a/src/oca/ruby/opennebula/client.rb +++ b/src/oca/ruby/opennebula/client.rb @@ -130,7 +130,7 @@ module OpenNebula raise "ONE_AUTH file not present" end - @one_auth.rstrip! + @one_auth = @one_auth.rstrip if endpoint @one_endpoint = endpoint @@ -143,8 +143,8 @@ module OpenNebula else @one_endpoint = "http://localhost:2633/RPC2" end - - @one_endpoint.rstrip! + + @one_endpoint= @one_endpoint.rstrip @async = !options[:sync] From 85a5e5f85909a27e904867105d709a7931fc7a66 Mon Sep 17 00:00:00 2001 From: Jaime Melis Date: Fri, 5 Jun 2015 17:42:11 +0200 Subject: [PATCH 58/83] Handle snap_revert, snap_delete TM_MAD/delete and DS_MAD/rm for persistent Ceph images with snapshots --- src/datastore_mad/remotes/ceph/rm | 51 ++++++++++-- src/datastore_mad/remotes/ceph/snap_delete | 90 ++++++++++++++++++++++ src/datastore_mad/remotes/ceph/snap_revert | 89 +++++++++++++++++++++ src/tm_mad/ceph/delete | 1 + 4 files changed, 226 insertions(+), 5 deletions(-) create mode 100755 src/datastore_mad/remotes/ceph/snap_delete create mode 100755 src/datastore_mad/remotes/ceph/snap_revert diff --git a/src/datastore_mad/remotes/ceph/rm b/src/datastore_mad/remotes/ceph/rm index 6300c4dd2b..324d6f7ca1 100755 --- a/src/datastore_mad/remotes/ceph/rm +++ b/src/datastore_mad/remotes/ceph/rm @@ -17,7 +17,7 @@ #--------------------------------------------------------------------------- # ############################################################################### -# This script is used to remove a VM image (SRC) from the image repository +# This script is used to remove a VM image (RBD_SRC) from the image repository ############################################################################### # ------------ Set up the environment to source common tools ------------ @@ -48,7 +48,7 @@ done < <($XPATH /DS_DRIVER_ACTION_DATA/IMAGE/SOURCE \ /DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/BRIDGE_LIST \ /DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/CEPH_USER) -SRC="${XPATH_ELEMENTS[j++]}" +RBD_SRC="${XPATH_ELEMENTS[j++]}" BRIDGE_LIST="${XPATH_ELEMENTS[j++]}" CEPH_USER="${XPATH_ELEMENTS[j++]}" @@ -63,11 +63,52 @@ if [ -n "$CEPH_USER" ]; then RBD="$RBD --id ${CEPH_USER}" fi - # -------- Remove Image from Datastore ------------ -log "Removing $SRC from the rbd image repository in $DST_HOST" +log "Removing $RBD_SRC from the rbd image repository in $DST_HOST" -ssh_exec_and_log "$DST_HOST" "$RBD rm $SRC" "Error removing $SRC in $DST_HOST" +DELETE_CMD=$(cat </dev/null) + + for child in \$CHILDREN; do + snap_id=\${child##*-} + child=\$child@\$snap_id + rm_children \$child + done + + $RBD snap unprotect \$rbd_snap + $RBD snap rm \$rbd_snap + fi + + $RBD rm \$rbd + } + + RBD_FORMAT=\$($RBD info $RBD_SRC | sed -n 's/.*format: // p') + + if [ "\$RBD_FORMAT" = "2" ]; then + has_snap_shots=\$($RBD info $RBD_SRC-0@0 2>/dev/null) + + if [ -n "\$has_snap_shots" ]; then + rm_children $RBD_SRC-0@0 + else + $RBD rm $RBD_SRC + fi + else + $RBD rm $RBD_SRC + fi +EOF +) + +ssh_exec_and_log "$DST_HOST" "$DELETE_CMD" \ + "Error deleting $RBD_SRC in $DST_HOST" exit 0 diff --git a/src/datastore_mad/remotes/ceph/snap_delete b/src/datastore_mad/remotes/ceph/snap_delete new file mode 100755 index 0000000000..57724fc6ed --- /dev/null +++ b/src/datastore_mad/remotes/ceph/snap_delete @@ -0,0 +1,90 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +############################################################################### +# This script is used to delete a snapshot of an image +############################################################################### + +# -------- Set up the environment to source common tools & conf ------------ + +if [ -z "${ONE_LOCATION}" ]; then + LIB_LOCATION=/usr/lib/one +else + LIB_LOCATION=$ONE_LOCATION/lib +fi + +. $LIB_LOCATION/sh/scripts_common.sh + +DRIVER_PATH=$(dirname $0) +source ${DRIVER_PATH}/../libfs.sh +source ${DRIVER_PATH}/ceph.conf + +# -------- Get image and datastore arguments from OpenNebula core ------------ + +DRV_ACTION=$1 +ID=$2 + +XPATH="${DRIVER_PATH}/../xpath.rb -b $DRV_ACTION" + +unset i XPATH_ELEMENTS + +while IFS= read -r -d '' element; do + XPATH_ELEMENTS[i++]="$element" +done < <($XPATH /DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/BRIDGE_LIST \ + /DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/POOL_NAME \ + /DS_DRIVER_ACTION_DATA/IMAGE/SOURCE \ + /DS_DRIVER_ACTION_DATA/IMAGE/TARGET_SNAPSHOT \ + /DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/CEPH_USER) + +unset i + +BRIDGE_LIST="${XPATH_ELEMENTS[i++]}" +POOL_NAME="${XPATH_ELEMENTS[i++]:-$POOL_NAME}" +RBD_SRC="${XPATH_ELEMENTS[i++]}" +SNAP_ID="${XPATH_ELEMENTS[i++]}" +CEPH_USER="${XPATH_ELEMENTS[i++]}" + +DST_HOST=`get_destination_host $ID` + +if [ -z "$DST_HOST" ]; then + error_message "Datastore template missing 'BRIDGE_LIST' attribute." + exit -1 +fi + +if [ -n "$CEPH_USER" ]; then + RBD="$RBD --id ${CEPH_USER}" +fi + +SNAP_DELETE_CMD=$(cat <&2 + exit 1 + fi + + $RBD snap unprotect $RBD_SRC-$SNAP_ID@$SNAP_ID + $RBD snap rm $RBD_SRC-$SNAP_ID@$SNAP_ID + $RBD rm $RBD_SRC-$SNAP_ID +EOF +) + +ssh_exec_and_log "$DST_HOST" "$SNAP_DELETE_CMD" \ + "Error deleting snapshot $RBD_SRC-$SNAP_ID@$SNAP_ID" diff --git a/src/datastore_mad/remotes/ceph/snap_revert b/src/datastore_mad/remotes/ceph/snap_revert new file mode 100755 index 0000000000..1a552c7191 --- /dev/null +++ b/src/datastore_mad/remotes/ceph/snap_revert @@ -0,0 +1,89 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +############################################################################### +# This script is used to revert a snapshot of an image +############################################################################### + +# -------- Set up the environment to source common tools & conf ------------ + +if [ -z "${ONE_LOCATION}" ]; then + LIB_LOCATION=/usr/lib/one +else + LIB_LOCATION=$ONE_LOCATION/lib +fi + +. $LIB_LOCATION/sh/scripts_common.sh + +DRIVER_PATH=$(dirname $0) +source ${DRIVER_PATH}/../libfs.sh +source ${DRIVER_PATH}/ceph.conf + +# -------- Get image and datastore arguments from OpenNebula core ------------ + +DRV_ACTION=$1 +ID=$2 + +XPATH="${DRIVER_PATH}/../xpath.rb -b $DRV_ACTION" + +unset i XPATH_ELEMENTS + +while IFS= read -r -d '' element; do + XPATH_ELEMENTS[i++]="$element" +done < <($XPATH /DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/BRIDGE_LIST \ + /DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/POOL_NAME \ + /DS_DRIVER_ACTION_DATA/IMAGE/SOURCE \ + /DS_DRIVER_ACTION_DATA/IMAGE/TARGET_SNAPSHOT \ + /DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/CEPH_USER) + +unset i + +BRIDGE_LIST="${XPATH_ELEMENTS[i++]}" +POOL_NAME="${XPATH_ELEMENTS[i++]:-$POOL_NAME}" +RBD_SRC="${XPATH_ELEMENTS[i++]}" +SNAP_ID="${XPATH_ELEMENTS[i++]}" +CEPH_USER="${XPATH_ELEMENTS[i++]}" + +DST_HOST=`get_destination_host $ID` + +if [ -z "$DST_HOST" ]; then + error_message "Datastore template missing 'BRIDGE_LIST' attribute." + exit -1 +fi + +if [ -n "$CEPH_USER" ]; then + RBD="$RBD --id ${CEPH_USER}" +fi + +SNAP_REVERT_CMD=$(cat <&2 + exit 1 + fi + + $RBD rm $RBD_SRC + $RBD clone $RBD_SRC-$SNAP_ID@$SNAP_ID $RBD_SRC +EOF +) + +ssh_exec_and_log "$DST_HOST" "$SNAP_REVERT_CMD" \ + "Error reverting snapshot $RBD_SRC-$SNAP_ID@$SNAP_ID" diff --git a/src/tm_mad/ceph/delete b/src/tm_mad/ceph/delete index 3ac6b54a43..5be934284f 100755 --- a/src/tm_mad/ceph/delete +++ b/src/tm_mad/ceph/delete @@ -135,6 +135,7 @@ DELETE_CMD=$(cat < Date: Mon, 8 Jun 2015 12:04:23 +0200 Subject: [PATCH 59/83] Feature #3782: Action for Ceph snapshot flatten --- src/datastore_mad/remotes/ceph/snap_flatten | 115 ++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100755 src/datastore_mad/remotes/ceph/snap_flatten diff --git a/src/datastore_mad/remotes/ceph/snap_flatten b/src/datastore_mad/remotes/ceph/snap_flatten new file mode 100755 index 0000000000..3b6a7fb2d4 --- /dev/null +++ b/src/datastore_mad/remotes/ceph/snap_flatten @@ -0,0 +1,115 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +############################################################################### +# This script is used to flatten a snapshot of a persistent image +############################################################################### + +# -------- Set up the environment to source common tools & conf ------------ + +if [ -z "${ONE_LOCATION}" ]; then + LIB_LOCATION=/usr/lib/one +else + LIB_LOCATION=$ONE_LOCATION/lib +fi + +. $LIB_LOCATION/sh/scripts_common.sh + +DRIVER_PATH=$(dirname $0) +source ${DRIVER_PATH}/../libfs.sh +source ${DRIVER_PATH}/ceph.conf + +# -------- Get image and datastore arguments from OpenNebula core ------------ + +DRV_ACTION=$1 +ID=$2 + +XPATH="${DRIVER_PATH}/../xpath.rb -b $DRV_ACTION" + +unset i XPATH_ELEMENTS + +while IFS= read -r -d '' element; do + XPATH_ELEMENTS[i++]="$element" +done < <($XPATH /DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/BRIDGE_LIST \ + /DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/POOL_NAME \ + /DS_DRIVER_ACTION_DATA/IMAGE/SOURCE \ + /DS_DRIVER_ACTION_DATA/IMAGE/TARGET_SNAPSHOT \ + /DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/CEPH_USER) + +unset i + +BRIDGE_LIST="${XPATH_ELEMENTS[i++]}" +POOL_NAME="${XPATH_ELEMENTS[i++]:-$POOL_NAME}" +RBD_SRC="${XPATH_ELEMENTS[i++]}" +SNAP_ID="${XPATH_ELEMENTS[i++]}" +CEPH_USER="${XPATH_ELEMENTS[i++]}" + +DST_HOST=`get_destination_host $ID` + +if [ -z "$DST_HOST" ]; then + error_message "Datastore template missing 'BRIDGE_LIST' attribute." + exit -1 +fi + +if [ -n "$CEPH_USER" ]; then + RBD="$RBD --id ${CEPH_USER}" +fi + +SNAP_FLATTEN_CMD=$(cat </dev/null) + + for child in \$CHILDREN; do + snap_id=\${child##*-} + child=\$child@\$snap_id + rm_children \$child + done + + $RBD snap unprotect \$rbd_snap + $RBD snap rm \$rbd_snap + fi + + $RBD rm \$rbd + } + + RBD_FORMAT=\$($RBD info $RBD_SRC | sed -n 's/.*format: // p') + + if [ "\${RBD_FORMAT}" != "2" ]; then + echo "Only RBD Format 2 is supported for this operation" >&2 + exit 1 + fi + + $RBD clone $RBD_SRC-$SNAP_ID@$SNAP_ID $RBD_SRC.flatten + $RBD flatten $RBD_SRC.flatten + + rm_children $RBD_SRC-0@0 + + $RBD rename $RBD_SRC.flatten $RBD_SRC +EOF +) + +ssh_exec_and_log "$DST_HOST" "$SNAP_FLATTEN_CMD" \ + "Error flattening snapshot $RBD_SRC-$SNAP_ID@$SNAP_ID" From 56af55f57fc566f0e6bb99c52ba8034c79e68131 Mon Sep 17 00:00:00 2001 From: Tino Vazquez Date: Mon, 8 Jun 2015 12:42:42 +0200 Subject: [PATCH 60/83] Small refactor to have a self-contained deploy action in vCenter --- src/vmm_mad/remotes/vcenter/vcenter_driver.rb | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/vmm_mad/remotes/vcenter/vcenter_driver.rb b/src/vmm_mad/remotes/vcenter/vcenter_driver.rb index 5c52d9b232..e86d9cde30 100644 --- a/src/vmm_mad/remotes/vcenter/vcenter_driver.rb +++ b/src/vmm_mad/remotes/vcenter/vcenter_driver.rb @@ -736,9 +736,12 @@ class VCenterVm vm = connection.find_vm_template(deploy_id) # Find out if we need to reconfigure capacity - expected_cpu, expected_memory = get_cpu_and_memory(xml_text) - current_cpu = vm.config.hardware.numCPU - current_memory = vm.config.hardware.memoryMB + xml = REXML::Document.new xml_text + + expected_cpu = xml.root.elements["//TEMPLATE/CPU"].text + expected_memory = xml.root.elements["//TEMPLATE/MEMORY"].text + current_cpu = vm.config.hardware.numCPU + current_memory = vm.config.hardware.memoryMB if current_cpu != expected_cpu or current_memory != expected_memory capacity_hash = {:numCPUs => expected_cpu.to_i, @@ -1250,15 +1253,6 @@ private } end - def self.get_cpu_and_memory(xml_text) - xml = REXML::Document.new xml_text - - cpu = xml.root.elements["//TEMPLATE/CPU"].text - memory = xml.root.elements["//TEMPLATE/MEMORY"].text - - return cpu, memory - end - ######################################################################## # Clone a vCenter VM Template and leaves it powered on ######################################################################## From c3621e3327832803e7283584c992e7c29b8bcb73 Mon Sep 17 00:00:00 2001 From: Jaime Melis Date: Mon, 8 Jun 2015 12:45:16 +0200 Subject: [PATCH 61/83] Feature #3782: Update install.sh and remotes with ds snap actions --- install.sh | 18 ++++++++++++++++++ src/datastore_mad/remotes/dev/snap_delete | 1 + src/datastore_mad/remotes/dev/snap_flatten | 1 + src/datastore_mad/remotes/dev/snap_revert | 1 + src/datastore_mad/remotes/dummy/snap_delete | 19 +++++++++++++++++++ src/datastore_mad/remotes/dummy/snap_flatten | 19 +++++++++++++++++++ src/datastore_mad/remotes/dummy/snap_revert | 19 +++++++++++++++++++ src/datastore_mad/remotes/fs/snap_delete | 1 + src/datastore_mad/remotes/fs/snap_flatten | 1 + src/datastore_mad/remotes/fs/snap_revert | 1 + src/datastore_mad/remotes/lvm/snap_delete | 1 + src/datastore_mad/remotes/lvm/snap_flatten | 1 + src/datastore_mad/remotes/lvm/snap_revert | 1 + src/datastore_mad/remotes/vmfs/snap_delete | 1 + src/datastore_mad/remotes/vmfs/snap_flatten | 1 + src/datastore_mad/remotes/vmfs/snap_revert | 1 + 16 files changed, 87 insertions(+) create mode 120000 src/datastore_mad/remotes/dev/snap_delete create mode 120000 src/datastore_mad/remotes/dev/snap_flatten create mode 120000 src/datastore_mad/remotes/dev/snap_revert create mode 100755 src/datastore_mad/remotes/dummy/snap_delete create mode 100755 src/datastore_mad/remotes/dummy/snap_flatten create mode 100755 src/datastore_mad/remotes/dummy/snap_revert create mode 120000 src/datastore_mad/remotes/fs/snap_delete create mode 120000 src/datastore_mad/remotes/fs/snap_flatten create mode 120000 src/datastore_mad/remotes/fs/snap_revert create mode 120000 src/datastore_mad/remotes/lvm/snap_delete create mode 120000 src/datastore_mad/remotes/lvm/snap_flatten create mode 120000 src/datastore_mad/remotes/lvm/snap_revert create mode 120000 src/datastore_mad/remotes/vmfs/snap_delete create mode 120000 src/datastore_mad/remotes/vmfs/snap_flatten create mode 120000 src/datastore_mad/remotes/vmfs/snap_revert diff --git a/install.sh b/install.sh index f8c64d2968..7ea90cb94e 100755 --- a/install.sh +++ b/install.sh @@ -1125,6 +1125,9 @@ DATASTORE_DRIVER_DUMMY_SCRIPTS="src/datastore_mad/remotes/dummy/cp \ src/datastore_mad/remotes/dummy/stat \ src/datastore_mad/remotes/dummy/clone \ src/datastore_mad/remotes/dummy/monitor \ + src/datastore_mad/remotes/dummy/snap_delete \ + src/datastore_mad/remotes/dummy/snap_revert \ + src/datastore_mad/remotes/dummy/snap_flatten \ src/datastore_mad/remotes/dummy/rm" DATASTORE_DRIVER_FS_SCRIPTS="src/datastore_mad/remotes/fs/cp \ @@ -1132,6 +1135,9 @@ DATASTORE_DRIVER_FS_SCRIPTS="src/datastore_mad/remotes/fs/cp \ src/datastore_mad/remotes/fs/stat \ src/datastore_mad/remotes/fs/clone \ src/datastore_mad/remotes/fs/monitor \ + src/datastore_mad/remotes/fs/snap_delete \ + src/datastore_mad/remotes/fs/snap_revert \ + src/datastore_mad/remotes/fs/snap_flatten \ src/datastore_mad/remotes/fs/rm" DATASTORE_DRIVER_VMFS_SCRIPTS="src/datastore_mad/remotes/vmfs/cp \ @@ -1140,6 +1146,9 @@ DATASTORE_DRIVER_VMFS_SCRIPTS="src/datastore_mad/remotes/vmfs/cp \ src/datastore_mad/remotes/vmfs/clone \ src/datastore_mad/remotes/vmfs/monitor \ src/datastore_mad/remotes/vmfs/rm \ + src/datastore_mad/remotes/vmfs/snap_delete \ + src/datastore_mad/remotes/vmfs/snap_revert \ + src/datastore_mad/remotes/vmfs/snap_flatten \ src/datastore_mad/remotes/vmfs/vmfs.conf" DATASTORE_DRIVER_LVM_SCRIPTS="src/datastore_mad/remotes/lvm/cp \ @@ -1148,6 +1157,9 @@ DATASTORE_DRIVER_LVM_SCRIPTS="src/datastore_mad/remotes/lvm/cp \ src/datastore_mad/remotes/lvm/rm \ src/datastore_mad/remotes/lvm/monitor \ src/datastore_mad/remotes/lvm/clone \ + src/datastore_mad/remotes/lvm/snap_delete \ + src/datastore_mad/remotes/lvm/snap_revert \ + src/datastore_mad/remotes/lvm/snap_flatten \ src/datastore_mad/remotes/lvm/lvm.conf" DATASTORE_DRIVER_CEPH_SCRIPTS="src/datastore_mad/remotes/ceph/cp \ @@ -1156,6 +1168,9 @@ DATASTORE_DRIVER_CEPH_SCRIPTS="src/datastore_mad/remotes/ceph/cp \ src/datastore_mad/remotes/ceph/rm \ src/datastore_mad/remotes/ceph/monitor \ src/datastore_mad/remotes/ceph/clone \ + src/datastore_mad/remotes/ceph/snap_delete \ + src/datastore_mad/remotes/ceph/snap_revert \ + src/datastore_mad/remotes/ceph/snap_flatten \ src/datastore_mad/remotes/ceph/ceph.conf" DATASTORE_DRIVER_DEV_SCRIPTS="src/datastore_mad/remotes/dev/cp \ @@ -1163,6 +1178,9 @@ DATASTORE_DRIVER_DEV_SCRIPTS="src/datastore_mad/remotes/dev/cp \ src/datastore_mad/remotes/dev/stat \ src/datastore_mad/remotes/dev/rm \ src/datastore_mad/remotes/dev/monitor \ + src/datastore_mad/remotes/dev/snap_delete \ + src/datastore_mad/remotes/dev/snap_revert \ + src/datastore_mad/remotes/dev/snap_flatten \ src/datastore_mad/remotes/dev/clone" #------------------------------------------------------------------------------- diff --git a/src/datastore_mad/remotes/dev/snap_delete b/src/datastore_mad/remotes/dev/snap_delete new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/datastore_mad/remotes/dev/snap_delete @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/datastore_mad/remotes/dev/snap_flatten b/src/datastore_mad/remotes/dev/snap_flatten new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/datastore_mad/remotes/dev/snap_flatten @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/datastore_mad/remotes/dev/snap_revert b/src/datastore_mad/remotes/dev/snap_revert new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/datastore_mad/remotes/dev/snap_revert @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/datastore_mad/remotes/dummy/snap_delete b/src/datastore_mad/remotes/dummy/snap_delete new file mode 100755 index 0000000000..49b0cbefb2 --- /dev/null +++ b/src/datastore_mad/remotes/dummy/snap_delete @@ -0,0 +1,19 @@ +#!/bin/sh + +# -------------------------------------------------------------------------- # +# Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +exit 0 diff --git a/src/datastore_mad/remotes/dummy/snap_flatten b/src/datastore_mad/remotes/dummy/snap_flatten new file mode 100755 index 0000000000..49b0cbefb2 --- /dev/null +++ b/src/datastore_mad/remotes/dummy/snap_flatten @@ -0,0 +1,19 @@ +#!/bin/sh + +# -------------------------------------------------------------------------- # +# Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +exit 0 diff --git a/src/datastore_mad/remotes/dummy/snap_revert b/src/datastore_mad/remotes/dummy/snap_revert new file mode 100755 index 0000000000..49b0cbefb2 --- /dev/null +++ b/src/datastore_mad/remotes/dummy/snap_revert @@ -0,0 +1,19 @@ +#!/bin/sh + +# -------------------------------------------------------------------------- # +# Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +exit 0 diff --git a/src/datastore_mad/remotes/fs/snap_delete b/src/datastore_mad/remotes/fs/snap_delete new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/datastore_mad/remotes/fs/snap_delete @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/datastore_mad/remotes/fs/snap_flatten b/src/datastore_mad/remotes/fs/snap_flatten new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/datastore_mad/remotes/fs/snap_flatten @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/datastore_mad/remotes/fs/snap_revert b/src/datastore_mad/remotes/fs/snap_revert new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/datastore_mad/remotes/fs/snap_revert @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/datastore_mad/remotes/lvm/snap_delete b/src/datastore_mad/remotes/lvm/snap_delete new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/datastore_mad/remotes/lvm/snap_delete @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/datastore_mad/remotes/lvm/snap_flatten b/src/datastore_mad/remotes/lvm/snap_flatten new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/datastore_mad/remotes/lvm/snap_flatten @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/datastore_mad/remotes/lvm/snap_revert b/src/datastore_mad/remotes/lvm/snap_revert new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/datastore_mad/remotes/lvm/snap_revert @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/datastore_mad/remotes/vmfs/snap_delete b/src/datastore_mad/remotes/vmfs/snap_delete new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/datastore_mad/remotes/vmfs/snap_delete @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/datastore_mad/remotes/vmfs/snap_flatten b/src/datastore_mad/remotes/vmfs/snap_flatten new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/datastore_mad/remotes/vmfs/snap_flatten @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/datastore_mad/remotes/vmfs/snap_revert b/src/datastore_mad/remotes/vmfs/snap_revert new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/datastore_mad/remotes/vmfs/snap_revert @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file From 58a260f96fe7aedbd94235565dcecf88233c2f4c Mon Sep 17 00:00:00 2001 From: Jaime Melis Date: Mon, 8 Jun 2015 15:00:32 +0200 Subject: [PATCH 62/83] Feature #3782: Add dummy snapshot_* placeholders for all the TM drivers but Ceph --- install.sh | 24 ++++++++++++++++++++++++ src/tm_mad/dev/snap_create | 1 + src/tm_mad/dev/snap_delete | 1 + src/tm_mad/dev/snap_revert | 1 + src/tm_mad/dummy/snap_create | 1 + src/tm_mad/dummy/snap_delete | 1 + src/tm_mad/dummy/snap_revert | 1 + src/tm_mad/fs_lvm/snap_create | 1 + src/tm_mad/fs_lvm/snap_delete | 1 + src/tm_mad/fs_lvm/snap_revert | 1 + src/tm_mad/lvm/snap_create | 1 + src/tm_mad/lvm/snap_delete | 1 + src/tm_mad/lvm/snap_revert | 1 + src/tm_mad/qcow2/snap_create | 1 + src/tm_mad/qcow2/snap_delete | 1 + src/tm_mad/qcow2/snap_revert | 1 + src/tm_mad/shared/snap_create | 1 + src/tm_mad/shared/snap_delete | 1 + src/tm_mad/shared/snap_revert | 1 + src/tm_mad/ssh/snap_create | 1 + src/tm_mad/ssh/snap_delete | 1 + src/tm_mad/ssh/snap_revert | 1 + src/tm_mad/vmfs/snap_create | 1 + src/tm_mad/vmfs/snap_delete | 1 + src/tm_mad/vmfs/snap_revert | 1 + 25 files changed, 48 insertions(+) create mode 120000 src/tm_mad/dev/snap_create create mode 120000 src/tm_mad/dev/snap_delete create mode 120000 src/tm_mad/dev/snap_revert create mode 120000 src/tm_mad/dummy/snap_create create mode 120000 src/tm_mad/dummy/snap_delete create mode 120000 src/tm_mad/dummy/snap_revert create mode 120000 src/tm_mad/fs_lvm/snap_create create mode 120000 src/tm_mad/fs_lvm/snap_delete create mode 120000 src/tm_mad/fs_lvm/snap_revert create mode 120000 src/tm_mad/lvm/snap_create create mode 120000 src/tm_mad/lvm/snap_delete create mode 120000 src/tm_mad/lvm/snap_revert create mode 120000 src/tm_mad/qcow2/snap_create create mode 120000 src/tm_mad/qcow2/snap_delete create mode 120000 src/tm_mad/qcow2/snap_revert create mode 120000 src/tm_mad/shared/snap_create create mode 120000 src/tm_mad/shared/snap_delete create mode 120000 src/tm_mad/shared/snap_revert create mode 120000 src/tm_mad/ssh/snap_create create mode 120000 src/tm_mad/ssh/snap_delete create mode 120000 src/tm_mad/ssh/snap_revert create mode 120000 src/tm_mad/vmfs/snap_create create mode 120000 src/tm_mad/vmfs/snap_delete create mode 120000 src/tm_mad/vmfs/snap_revert diff --git a/install.sh b/install.sh index 7ea90cb94e..c244ae0369 100755 --- a/install.sh +++ b/install.sh @@ -1019,6 +1019,9 @@ TM_SHARED_FILES="src/tm_mad/shared/clone \ src/tm_mad/shared/premigrate \ src/tm_mad/shared/postmigrate \ src/tm_mad/shared/mvds \ + src/tm_mad/shared/snap_create \ + src/tm_mad/shared/snap_delete \ + src/tm_mad/shared/snap_revert \ src/tm_mad/shared/cpds" TM_FS_LVM_FILES="src/tm_mad/fs_lvm/clone \ @@ -1028,6 +1031,9 @@ TM_FS_LVM_FILES="src/tm_mad/fs_lvm/clone \ src/tm_mad/fs_lvm/cpds \ src/tm_mad/fs_lvm/premigrate \ src/tm_mad/fs_lvm/postmigrate \ + src/tm_mad/fs_lvm/snap_create \ + src/tm_mad/fs_lvm/snap_delete \ + src/tm_mad/fs_lvm/snap_revert \ src/tm_mad/fs_lvm/delete" TM_QCOW2_FILES="src/tm_mad/qcow2/clone \ @@ -1040,6 +1046,9 @@ TM_QCOW2_FILES="src/tm_mad/qcow2/clone \ src/tm_mad/qcow2/premigrate \ src/tm_mad/qcow2/postmigrate \ src/tm_mad/qcow2/mvds \ + src/tm_mad/qcow2/snap_create \ + src/tm_mad/qcow2/snap_delete \ + src/tm_mad/qcow2/snap_revert \ src/tm_mad/qcow2/cpds" TM_SSH_FILES="src/tm_mad/ssh/clone \ @@ -1052,6 +1061,9 @@ TM_SSH_FILES="src/tm_mad/ssh/clone \ src/tm_mad/ssh/premigrate \ src/tm_mad/ssh/postmigrate \ src/tm_mad/ssh/mvds \ + src/tm_mad/ssh/snap_create \ + src/tm_mad/ssh/snap_delete \ + src/tm_mad/ssh/snap_revert \ src/tm_mad/ssh/cpds" TM_DUMMY_FILES="src/tm_mad/dummy/clone \ @@ -1064,6 +1076,9 @@ TM_DUMMY_FILES="src/tm_mad/dummy/clone \ src/tm_mad/dummy/premigrate \ src/tm_mad/dummy/postmigrate \ src/tm_mad/dummy/mvds \ + src/tm_mad/dummy/snap_create \ + src/tm_mad/dummy/snap_delete \ + src/tm_mad/dummy/snap_revert \ src/tm_mad/dummy/cpds" TM_VMFS_FILES="src/tm_mad/vmfs/clone \ @@ -1076,6 +1091,9 @@ TM_VMFS_FILES="src/tm_mad/vmfs/clone \ src/tm_mad/vmfs/mvds \ src/tm_mad/vmfs/cpds \ src/tm_mad/vmfs/postmigrate \ + src/tm_mad/vmfs/snap_create \ + src/tm_mad/vmfs/snap_delete \ + src/tm_mad/vmfs/snap_revert \ src/tm_mad/vmfs/premigrate" TM_LVM_FILES="src/tm_mad/lvm/clone \ @@ -1085,6 +1103,9 @@ TM_LVM_FILES="src/tm_mad/lvm/clone \ src/tm_mad/lvm/cpds \ src/tm_mad/lvm/premigrate \ src/tm_mad/lvm/postmigrate \ + src/tm_mad/lvm/snap_create \ + src/tm_mad/lvm/snap_delete \ + src/tm_mad/lvm/snap_revert \ src/tm_mad/lvm/delete" TM_CEPH_FILES="src/tm_mad/ceph/clone \ @@ -1106,6 +1127,9 @@ TM_DEV_FILES="src/tm_mad/dev/clone \ src/tm_mad/dev/cpds \ src/tm_mad/dev/premigrate \ src/tm_mad/dev/postmigrate \ + src/tm_mad/dev/snap_create \ + src/tm_mad/dev/snap_delete \ + src/tm_mad/dev/snap_revert \ src/tm_mad/dev/delete" #------------------------------------------------------------------------------- diff --git a/src/tm_mad/dev/snap_create b/src/tm_mad/dev/snap_create new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/tm_mad/dev/snap_create @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/dev/snap_delete b/src/tm_mad/dev/snap_delete new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/tm_mad/dev/snap_delete @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/dev/snap_revert b/src/tm_mad/dev/snap_revert new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/tm_mad/dev/snap_revert @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/dummy/snap_create b/src/tm_mad/dummy/snap_create new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/tm_mad/dummy/snap_create @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/dummy/snap_delete b/src/tm_mad/dummy/snap_delete new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/tm_mad/dummy/snap_delete @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/dummy/snap_revert b/src/tm_mad/dummy/snap_revert new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/tm_mad/dummy/snap_revert @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/fs_lvm/snap_create b/src/tm_mad/fs_lvm/snap_create new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/tm_mad/fs_lvm/snap_create @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/fs_lvm/snap_delete b/src/tm_mad/fs_lvm/snap_delete new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/tm_mad/fs_lvm/snap_delete @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/fs_lvm/snap_revert b/src/tm_mad/fs_lvm/snap_revert new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/tm_mad/fs_lvm/snap_revert @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/lvm/snap_create b/src/tm_mad/lvm/snap_create new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/tm_mad/lvm/snap_create @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/lvm/snap_delete b/src/tm_mad/lvm/snap_delete new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/tm_mad/lvm/snap_delete @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/lvm/snap_revert b/src/tm_mad/lvm/snap_revert new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/tm_mad/lvm/snap_revert @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/qcow2/snap_create b/src/tm_mad/qcow2/snap_create new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/tm_mad/qcow2/snap_create @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/qcow2/snap_delete b/src/tm_mad/qcow2/snap_delete new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/tm_mad/qcow2/snap_delete @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/qcow2/snap_revert b/src/tm_mad/qcow2/snap_revert new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/tm_mad/qcow2/snap_revert @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/shared/snap_create b/src/tm_mad/shared/snap_create new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/tm_mad/shared/snap_create @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/shared/snap_delete b/src/tm_mad/shared/snap_delete new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/tm_mad/shared/snap_delete @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/shared/snap_revert b/src/tm_mad/shared/snap_revert new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/tm_mad/shared/snap_revert @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/ssh/snap_create b/src/tm_mad/ssh/snap_create new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/tm_mad/ssh/snap_create @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/ssh/snap_delete b/src/tm_mad/ssh/snap_delete new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/tm_mad/ssh/snap_delete @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/ssh/snap_revert b/src/tm_mad/ssh/snap_revert new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/tm_mad/ssh/snap_revert @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/vmfs/snap_create b/src/tm_mad/vmfs/snap_create new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/tm_mad/vmfs/snap_create @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/vmfs/snap_delete b/src/tm_mad/vmfs/snap_delete new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/tm_mad/vmfs/snap_delete @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/vmfs/snap_revert b/src/tm_mad/vmfs/snap_revert new file mode 120000 index 0000000000..9c454e8cd4 --- /dev/null +++ b/src/tm_mad/vmfs/snap_revert @@ -0,0 +1 @@ +../common/not_supported.sh \ No newline at end of file From ee1fb2c637cdc02042dc58371a2a33e6f0f4549c Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Mon, 8 Jun 2015 19:59:17 +0200 Subject: [PATCH 63/83] feature #3782: Do not snapshot volatile disks --- src/vm/VirtualMachine.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index bff395fde8..1e43d1add7 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -4328,6 +4328,12 @@ int VirtualMachine::new_disk_snapshot(int did, const string& tag, string& error) return -1; } + if (isVolatile(disk)) + { + error = "Cannot make snapshots on volatile disks"; + return -1; + } + it = snapshots.find(did); if ( it == snapshots.end() ) From c3741e4fa16328be578c451baebbf7dafc9e2230 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Tue, 9 Jun 2015 00:21:29 +0200 Subject: [PATCH 64/83] feature #3782: Remove snapshot list if empty --- src/vm/VirtualMachine.cc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index 1e43d1add7..72042516d7 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -4434,5 +4434,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; + } } From b7a862bed07a0b9405487bd30d609660566b784c Mon Sep 17 00:00:00 2001 From: Tino Vazquez Date: Tue, 9 Jun 2015 18:28:03 +0200 Subject: [PATCH 65/83] Better check for keymap VNC information present in vCenter VMs (cherry picked from commit db3a97335557ed7097ab5d599095942cdec3effc) --- src/vmm_mad/remotes/vcenter/vcenter_driver.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vmm_mad/remotes/vcenter/vcenter_driver.rb b/src/vmm_mad/remotes/vcenter/vcenter_driver.rb index e86d9cde30..6c2518542d 100644 --- a/src/vmm_mad/remotes/vcenter/vcenter_driver.rb +++ b/src/vmm_mad/remotes/vcenter/vcenter_driver.rb @@ -1142,7 +1142,7 @@ class VCenterVm " TYPE =\"vnc\",\n"\ " LISTEN =\"0.0.0.0\",\n"\ " PORT =\"#{vp[0][:value]}\"\n" - str << " ,KEYMAP =\"#{keymap[0][:value]}\"\n" if keymap + str << " ,KEYMAP =\"#{keymap[0][:value]}\"\n" if keymap[0] str << "]\n" end From 9d20167c1cec126ab73e31b45a6baef18bd512b1 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Tue, 9 Jun 2015 23:25:10 +0200 Subject: [PATCH 66/83] feautre #3782: Remove SAVE_AS from core --- include/Image.h | 48 +-- include/ImageTemplate.h | 38 +-- include/RequestManagerVirtualMachine.h | 17 - include/VirtualMachine.h | 60 +--- include/VirtualMachinePool.h | 4 +- src/image/Image.cc | 10 +- src/image/ImageManagerActions.cc | 39 +-- src/image/ImageManagerDriver.cc | 41 +-- src/image/ImageTemplate.cc | 3 - src/lcm/LifeCycleActions.cc | 4 +- src/lcm/LifeCycleStates.cc | 46 +-- src/rm/RequestManager.cc | 2 - src/rm/RequestManagerDelete.cc | 49 +-- src/rm/RequestManagerVirtualMachine.cc | 418 ++++++++----------------- src/tm/TransferManager.cc | 82 +---- src/vm/VirtualMachine.cc | 357 ++++++--------------- src/vm/VirtualMachinePool.cc | 13 +- 17 files changed, 333 insertions(+), 898 deletions(-) diff --git a/include/Image.h b/include/Image.h index 1ff370ea52..ee1be2757c 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_hot(); } /** diff --git a/include/ImageTemplate.h b/include/ImageTemplate.h index fc117061b3..45348abe1b 100644 --- a/include/ImageTemplate.h +++ b/include/ImageTemplate.h @@ -59,45 +59,18 @@ public: Template::remove_all_except_restricted(restricted_attributes); }; - bool is_saving() - { - string saving; - - get(saving_attribute, saving); - - return (saving.empty() == false); - } - bool is_saving_hot() { - string save_as_hot; + bool save_as_hot; - get(saving_hot_attribute, save_as_hot); + get("SAVE_AS_HOT", save_as_hot); - return (save_as_hot.empty() == false); - } - - void set_saving() - { - SingleAttribute * attr= new SingleAttribute(saving_attribute, "YES"); - - erase(saving_attribute); - - set(attr); + return save_as_hot; } 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/RequestManagerVirtualMachine.h b/include/RequestManagerVirtualMachine.h index 9a3eb46f06..bb1e849090 100644 --- a/include/RequestManagerVirtualMachine.h +++ b/include/RequestManagerVirtualMachine.h @@ -187,23 +187,6 @@ public: /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ -class VirtualMachineSaveDiskCancel : public RequestManagerVirtualMachine -{ -public: - VirtualMachineSaveDiskCancel(): - RequestManagerVirtualMachine("VirtualMachineSaveDiskCancel", - "Cancels a disk snapshot set by VirtualMachineSaveDisk", - "A:sii"){}; - - ~VirtualMachineSaveDiskCancel(){}; - - void request_execute(xmlrpc_c::paramList const& _paramList, - RequestAttributes& att); -}; - -/* ------------------------------------------------------------------------- */ -/* ------------------------------------------------------------------------- */ - class VirtualMachineMonitoring : public RequestManagerVirtualMachine { public: diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index 15bb959915..3c3b08d352 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -1270,55 +1270,34 @@ public: int generate_context(string &files, int &disk_id, string& token_password); // ------------------------------------------------------------------------- - // Datastore related functions + // Export Disk related functions (save_as hot) // ------------------------------------------------------------------------- /** - * Gest the associated image to the given disk_id + * Mark the disk that is going to be exported (saved_as) * @param disk_id of the VM - * @param hot is this a save_as hot operation * @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, string& err_str); /** - * Sets the corresponding SAVE_AS state. - * @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 + * Sets the corresponding state to export the disk. + * @return 0 if the VM can be exported */ - int set_saveas_state(int disk_id, bool hot); + int set_saveas_state(); /** - * 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 + * Clears the export state, moving the VM to the original state. + * @return 0 if the VM was in an export state */ - int clear_saveas_state(int disk_id, bool hot); + int clear_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 export 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 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); - - /** - * 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 - */ - int get_save_disk_image(int disk_id); + int clear_saveas_disk(); /** * Set the SAVE_AS attribute for the "disk_id"th disk. @@ -1336,16 +1315,9 @@ public: * @param error_str describes the error * @return -1 if failure */ - int get_saveas_disk_hot(int& disk_id, string& source, int& image_id); + int get_saveas_disk_hot(int& disk_id, string& source, int& image_id, + string& tm_mad, string& ds_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); // ------------------------------------------------------------------------ // 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/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..eefc7f52fc 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 disk_file, 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()); @@ -639,7 +619,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 +718,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..e97fb47889 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->save_disk_hot(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); @@ -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..5599c8f4ce 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); diff --git a/src/lcm/LifeCycleStates.cc b/src/lcm/LifeCycleStates.cc index e8cbe040da..5b958b1f11 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); @@ -1606,32 +1606,33 @@ void LifeCycleManager::detach_nic_failure_action(int vid) void LifeCycleManager::saveas_hot_success_action(int vid) { - VirtualMachine * vm; - Image * image; - int image_id; int disk_id; + string tm_mad; + string ds_id; string source; - 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_hot(disk_id, source, image_id, tm_mad, ds_id); - if (vm->clear_saveas_state(disk_id, true) == -1) + vm->clear_saveas_disk(); + + vmpool->update(vm); + + 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"); vm->unlock(); return; } - vmpool->update(vm); - vm->unlock(); if ( rc != 0 ) @@ -1639,7 +1640,7 @@ void LifeCycleManager::saveas_hot_success_action(int vid) return; } - image = ipool->get(image_id, true); + Image * image = ipool->get(image_id, true); if ( image == 0 ) { @@ -1658,32 +1659,33 @@ void LifeCycleManager::saveas_hot_success_action(int vid) void LifeCycleManager::saveas_hot_failure_action(int vid) { - VirtualMachine * vm; - Image * image; - int image_id; int disk_id; + string tm_mad; + string ds_id; string source; - 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_hot(disk_id, source, image_id, tm_mad, ds_id); - if (vm->clear_saveas_state(disk_id, true) == -1) + vm->clear_saveas_disk(); + + vmpool->update(vm); + + 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"); vm->unlock(); return; } - vmpool->update(vm); - vm->unlock(); if ( rc != 0 ) @@ -1691,7 +1693,7 @@ void LifeCycleManager::saveas_hot_failure_action(int vid) return; } - image = ipool->get(image_id, true); + Image * image = ipool->get(image_id, true); if ( image == 0 ) { diff --git a/src/rm/RequestManager.cc b/src/rm/RequestManager.cc index a390631b72..91dc6fe9df 100644 --- a/src/rm/RequestManager.cc +++ b/src/rm/RequestManager.cc @@ -294,7 +294,6 @@ void RequestManager::register_xml_methods() 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()); @@ -450,7 +449,6 @@ void RequestManager::register_xml_methods() 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); 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/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc index afa1c4a743..c812424844 100644 --- a/src/rm/RequestManagerVirtualMachine.cc +++ b/src/rm/RequestManagerVirtualMachine.cc @@ -1179,63 +1179,68 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList void VirtualMachineSaveDisk::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)); 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 export // ------------------------------------------------------------------------- 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, 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 +1250,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 +1277,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 +1317,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_hot(); - 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 +1328,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 +1349,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 +1358,109 @@ 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); -} -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +error_state: + vm->unlock(); -void VirtualMachineSaveDiskCancel::request_execute( - xmlrpc_c::paramList const& paramList, - RequestAttributes& att) -{ - Nebula& nd = Nebula::instance(); + failure_response(INTERNAL,request_error("VM has to be RUNNING, POWEROFF or " + "SUSPENDED to export disks.",""), att); + return; - AclManager * aclm = nd.get_aclm(); - ImageManager * imagem = nd.get_imagem(); - ImagePool * ipool = nd.get_ipool(); - Image * img; - int img_id; +error_disk: + vm->clear_saveas_state(); - VirtualMachinePool * vmpool = static_cast(pool); - VirtualMachine * vm; - - 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; } /* -------------------------------------------------------------------------- */ diff --git a/src/tm/TransferManager.cc b/src/tm/TransferManager.cc index 84be34350d..e670c82ce5 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,20 @@ void TransferManager::saveas_hot_action(int vid) { int disk_id; int image_id; - string save_source; - - string save; + string source; 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,7 +2084,7 @@ 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_hot(disk_id, source, image_id, tm_mad, ds_id) != 0) { vm->log("TM", Log::ERROR,"Could not get disk information to saveas it"); goto error_common; @@ -2117,40 +2097,6 @@ 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.open(xfr_name.c_str(),ios::out | ios::trunc); @@ -2164,7 +2110,7 @@ void TransferManager::saveas_hot_action(int vid) << tm_mad << " " << vm->get_hostname() << ":" << vm->get_remote_system_dir() << "/disk." << disk_id << " " - << save_source << " " + << source << " " << vm->get_oid() << " " << ds_id << endl; diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index 72042516d7..6c08419a36 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -3180,162 +3180,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 +3216,57 @@ 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, string& err_str) { - VectorAttribute * disk; + int iid = -1; - if (lcm_state != HOTPLUG_SAVEAS && lcm_state != HOTPLUG_SAVEAS_SUSPENDED - && lcm_state != HOTPLUG_SAVEAS_POWEROFF ) + VectorAttribute * disk = get_disk(disk_id); + + if ( disk == 0 ) { + err_str = "DISK does not exist."; return -1; } - disk = get_disk(disk_id); - - if ( disk != 0 ) + if ( disk->vector_value("IMAGE_ID", iid) != 0 ) { - disk->replace("SAVE_AS_SOURCE", source); + err_str = "DISK does not have a valid IMAGE_ID."; + return -1; + } - disk->replace("SAVE_AS", img_id); + disk->replace("HOTPLUG_SAVE_AS_ACTIVE", "YES"); - disk->replace("SAVE", "YES"); + return iid; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int VirtualMachine::set_saveas_state() +{ + 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; } return 0; @@ -3401,46 +3275,68 @@ int VirtualMachine::save_disk(int disk_id, /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int VirtualMachine::clear_save_disk(int disk_id) +int VirtualMachine::clear_saveas_state() { - VectorAttribute * disk; - - disk = get_disk(disk_id); - - if ( disk != 0 ) + switch (lcm_state) { - disk->remove("SAVE_AS_SOURCE"); - disk->remove("SAVE_AS"); - disk->replace("SAVE", "NO"); + case HOTPLUG_SAVEAS: + lcm_state = RUNNING; + break; - return 0; + 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 -1; + return 0; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int VirtualMachine::get_save_disk_image(int disk_id) +int VirtualMachine::clear_saveas_disk() { - VectorAttribute * disk; - bool save; - int img_id = -1; + 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; ivector_value("SAVE", save); + disk = dynamic_cast(disks[i]); - if (save) + if ( disk == 0 ) { - disk->vector_value("SAVE_AS", img_id); + 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"); + + return image_id; } } - return img_id; + return -1; } /* -------------------------------------------------------------------------- */ @@ -3450,22 +3346,22 @@ 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); + VectorAttribute * disk = get_disk(disk_id); - if ( disk != 0 ) + if ( disk == 0 ) { - disk->replace("HOTPLUG_SAVE_AS", img_id); - disk->replace("HOTPLUG_SAVE_AS_SOURCE", source); + return -1; } + disk->replace("HOTPLUG_SAVE_AS", img_id); + disk->replace("HOTPLUG_SAVE_AS_SOURCE", source); + return 0; } @@ -3473,7 +3369,7 @@ int VirtualMachine::save_disk_hot(int disk_id, /* -------------------------------------------------------------------------- */ int VirtualMachine::get_saveas_disk_hot(int& disk_id, string& source, - int& image_id) + int& image_id, string& tm_mad, string& ds_id) { vector disks; VectorAttribute * disk; @@ -3494,78 +3390,19 @@ 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("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; -} /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ 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 { From ce85188042d04d23b5ff2a138750080eec9117be Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Wed, 10 Jun 2015 01:30:22 +0200 Subject: [PATCH 67/83] feature #3782: Changes in OCA (Ruby) and CLI. Updated direct references to OCA methods --- include/RequestManagerVirtualMachine.h | 12 +++---- src/cli/onevm | 31 +++++-------------- src/cloud/ec2/lib/EC2QueryServer.rb | 7 ++--- src/cloud/ec2/lib/ebs.rb | 5 ++- src/image/ImageManagerActions.cc | 23 +++++--------- src/lcm/LifeCycleStates.cc | 14 ++++++--- src/oca/ruby/opennebula/virtual_machine.rb | 28 +++-------------- src/rm/RequestManager.cc | 4 +-- src/rm/RequestManagerVirtualMachine.cc | 4 ++- .../OpenNebulaJSON/VirtualMachineJSON.rb | 10 +----- 10 files changed, 47 insertions(+), 91 deletions(-) diff --git a/include/RequestManagerVirtualMachine.h b/include/RequestManagerVirtualMachine.h index bb1e849090..33f606d50e 100644 --- a/include/RequestManagerVirtualMachine.h +++ b/include/RequestManagerVirtualMachine.h @@ -170,15 +170,15 @@ public: /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ -class VirtualMachineSaveDisk : public RequestManagerVirtualMachine +class VirtualMachineDiskExport : public RequestManagerVirtualMachine { public: - VirtualMachineSaveDisk(): - RequestManagerVirtualMachine("VirtualMachineSaveDisk", - "Saves a disk from virtual machine as a new image", - "A:siissb"){}; + VirtualMachineDiskExport(): + RequestManagerVirtualMachine("VirtualMachineDiskExport", + "Exports a disk from virtual machine as a new image", + "A:siiss"){}; - ~VirtualMachineSaveDisk(){}; + ~VirtualMachineDiskExport(){}; void request_execute(xmlrpc_c::paramList const& _paramList, RequestAttributes& att); diff --git a/src/cli/onevm b/src/cli/onevm index 4ae4f74cb6..e97023ea3b 100755 --- a/src/cli/onevm +++ b/src/cli/onevm @@ -298,19 +298,16 @@ 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_export_desc = <<-EOT.unindent + Exports the specified VM disk to 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 + command :"disk-export", disk_export_desc, :vmid, :diskid, :img_name, + :options=>[TYPE] do disk_id = args[1].to_i image_name = args[2] image_type = options[:type] || "" @@ -319,8 +316,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do "the image #{image_name}" 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_export(disk_id, image_name, image_type) if !OpenNebula.is_error?(res) puts "Image ID: #{res}" @@ -330,19 +326,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..5381e4443c 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_export(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..9f6807ff87 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_export(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/ImageManagerActions.cc b/src/image/ImageManagerActions.cc index eefc7f52fc..6846353ac8 100644 --- a/src/image/ImageManagerActions.cc +++ b/src/image/ImageManagerActions.cc @@ -160,7 +160,7 @@ int ImageManager::acquire_image(int vm_id, Image *img, string& error) void ImageManager::release_image(int vm_id, int iid, bool failed) { - ostringstream disk_file, oss; + ostringstream oss; Image * img = ipool->get(iid,true); @@ -245,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 ) { @@ -276,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: @@ -293,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(); diff --git a/src/lcm/LifeCycleStates.cc b/src/lcm/LifeCycleStates.cc index 5b958b1f11..7c350351d2 100644 --- a/src/lcm/LifeCycleStates.cc +++ b/src/lcm/LifeCycleStates.cc @@ -1623,16 +1623,19 @@ void LifeCycleManager::saveas_hot_success_action(int vid) vm->clear_saveas_disk(); - vmpool->update(vm); - if (vm->clear_saveas_state() == -1) { vm->log("LCM",Log::ERROR, "saveas_success_action, VM in a wrong state"); + + vmpool->update(vm); + vm->unlock(); return; } + vmpool->update(vm); + vm->unlock(); if ( rc != 0 ) @@ -1676,16 +1679,19 @@ void LifeCycleManager::saveas_hot_failure_action(int vid) vm->clear_saveas_disk(); - vmpool->update(vm); - if (vm->clear_saveas_state() == -1) { vm->log("LCM",Log::ERROR, "saveas_failure_action, VM in a wrong state"); + + vmpool->update(vm); + vm->unlock(); return; } + vmpool->update(vm); + vm->unlock(); if ( rc != 0 ) diff --git a/src/oca/ruby/opennebula/virtual_machine.rb b/src/oca/ruby/opennebula/virtual_machine.rb index 0b1d91a839..71dfda1ca7 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", + :diskexport => "vm.diskexport", :disksnapshotcreate => "vm.disksnapshotcreate", :disksnapshotrevert => "vm.disksnapshotrevert", :disksnapshotdelete => "vm.disksnapshotdelete" @@ -468,36 +467,20 @@ 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 # # @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_export(disk_id, image_name, image_type="") return Error.new('ID not defined') if !@pe_id - rc = @client.call(VM_METHODS[:savedisk], + rc = @client.call(VM_METHODS[:diskexport], @pe_id, disk_id, image_name, - image_type, - hot) + image_type) 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 +767,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_export(disk_id.to_i,"#{name}-disk-#{disk_id}","") return rc if OpenNebula.is_error?(rc) diff --git a/src/rm/RequestManager.cc b/src/rm/RequestManager.cc index 91dc6fe9df..72a29c3d91 100644 --- a/src/rm/RequestManager.cc +++ b/src/rm/RequestManager.cc @@ -293,7 +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_monitoring(new VirtualMachineMonitoring()); xmlrpc_c::methodPtr vm_attach(new VirtualMachineAttach()); xmlrpc_c::methodPtr vm_detach(new VirtualMachineDetach()); @@ -303,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_dexport(new VirtualMachineDiskExport()); xmlrpc_c::methodPtr vm_dsnap_create(new VirtualMachineDiskSnapshotCreate()); xmlrpc_c::methodPtr vm_dsnap_revert(new VirtualMachineDiskSnapshotRevert()); xmlrpc_c::methodPtr vm_dsnap_delete(new VirtualMachineDiskSnapshotDelete()); @@ -448,7 +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.allocate", vm_allocate); RequestManagerRegistry.addMethod("one.vm.info", vm_info); RequestManagerRegistry.addMethod("one.vm.chown", vm_chown); @@ -464,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.diskexport", vm_dexport); 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/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc index c812424844..6bb1d5cc3b 100644 --- a/src/rm/RequestManagerVirtualMachine.cc +++ b/src/rm/RequestManagerVirtualMachine.cc @@ -1176,7 +1176,7 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramList, +void VirtualMachineDiskExport::request_execute(xmlrpc_c::paramList const& paramList, RequestAttributes& att) { Nebula& nd = Nebula::instance(); @@ -1398,6 +1398,8 @@ void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramLis success_response(iid, att); + return; + error_state: vm->unlock(); diff --git a/src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb b/src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb index 987d780f78..b181f4ddd3 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_export(params['disk_id'].to_i, params['image_name'], params['type']) end def snapshot_create(params=Hash.new) From 630e0360053de10ff4748089361f570ed354ad95 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Wed, 10 Jun 2015 12:53:55 +0200 Subject: [PATCH 68/83] feature #3782: Removed _hot from saveas functions --- include/LifeCycleManager.h | 8 +++--- include/VirtualMachine.h | 25 ++++++++-------- src/image/ImageManagerDriver.cc | 2 +- src/lcm/LifeCycleActions.cc | 4 +-- src/lcm/LifeCycleManager.cc | 16 +++++------ src/lcm/LifeCycleStates.cc | 16 +++++------ src/tm/TransferManager.cc | 6 ++-- src/tm/TransferManagerDriver.cc | 4 +-- src/vm/VirtualMachine.cc | 51 ++++++++++++++++----------------- 9 files changed, 66 insertions(+), 66 deletions(-) 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/VirtualMachine.h b/include/VirtualMachine.h index 3c3b08d352..b0b9701002 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -1280,6 +1280,14 @@ public: */ int set_saveas_disk(int disk_id, string& err_str); + /** + * Set export attributes for the disk + * @param disk_id Index of the disk to export + * @param source to save the disk + * @param img_id ID of the image this disk will be saved to + */ + int set_saveas_disk(int disk_id, const string& source, int img_id); + /** * Sets the corresponding state to export the disk. * @return 0 if the VM can be exported @@ -1299,26 +1307,19 @@ public: */ 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, + int get_saveas_disk(int& disk_id, string& source, int& image_id, string& tm_mad, string& ds_id); - // ------------------------------------------------------------------------ // Authorization related functions // ------------------------------------------------------------------------ diff --git a/src/image/ImageManagerDriver.cc b/src/image/ImageManagerDriver.cc index e97fb47889..d2cda36e9d 100644 --- a/src/image/ImageManagerDriver.cc +++ b/src/image/ImageManagerDriver.cc @@ -455,7 +455,7 @@ static int mkfs_action(istringstream& is, goto error_save_get; } - if ( vm->save_disk_hot(disk_id, source, id) == -1 ) + if ( vm->set_saveas_disk(disk_id, source, id) == -1 ) { goto error_save_state; } diff --git a/src/lcm/LifeCycleActions.cc b/src/lcm/LifeCycleActions.cc index 5599c8f4ce..81a3ec4e08 100644 --- a/src/lcm/LifeCycleActions.cc +++ b/src/lcm/LifeCycleActions.cc @@ -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 7c350351d2..2a36ead8f8 100644 --- a/src/lcm/LifeCycleStates.cc +++ b/src/lcm/LifeCycleStates.cc @@ -1604,7 +1604,7 @@ void LifeCycleManager::detach_nic_failure_action(int vid) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -void LifeCycleManager::saveas_hot_success_action(int vid) +void LifeCycleManager::saveas_success_action(int vid) { int image_id; int disk_id; @@ -1619,7 +1619,7 @@ void LifeCycleManager::saveas_hot_success_action(int vid) return; } - int rc = vm->get_saveas_disk_hot(disk_id, source, image_id, tm_mad, ds_id); + int rc = vm->get_saveas_disk(disk_id, source, image_id, tm_mad, ds_id); vm->clear_saveas_disk(); @@ -1638,14 +1638,14 @@ void LifeCycleManager::saveas_hot_success_action(int vid) vm->unlock(); - if ( rc != 0 ) + if (rc != 0) { return; } Image * image = ipool->get(image_id, true); - if ( image == 0 ) + if (image == 0) { return; } @@ -1660,7 +1660,7 @@ void LifeCycleManager::saveas_hot_success_action(int vid) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -void LifeCycleManager::saveas_hot_failure_action(int vid) +void LifeCycleManager::saveas_failure_action(int vid) { int image_id; int disk_id; @@ -1675,7 +1675,7 @@ void LifeCycleManager::saveas_hot_failure_action(int vid) return; } - int rc = vm->get_saveas_disk_hot(disk_id, source, image_id, tm_mad, ds_id); + int rc = vm->get_saveas_disk(disk_id, source, image_id, tm_mad, ds_id); vm->clear_saveas_disk(); @@ -1694,14 +1694,14 @@ void LifeCycleManager::saveas_hot_failure_action(int vid) vm->unlock(); - if ( rc != 0 ) + if (rc != 0) { return; } Image * image = ipool->get(image_id, true); - if ( image == 0 ) + if (image == 0) { return; } diff --git a/src/tm/TransferManager.cc b/src/tm/TransferManager.cc index e670c82ce5..a3dcbaea7d 100644 --- a/src/tm/TransferManager.cc +++ b/src/tm/TransferManager.cc @@ -2084,9 +2084,9 @@ void TransferManager::saveas_hot_action(int vid) goto error_common; } - if (vm->get_saveas_disk_hot(disk_id, source, image_id, tm_mad, ds_id) != 0) + if (vm->get_saveas_disk(disk_id, source, image_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; } @@ -2135,7 +2135,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/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index 6c08419a36..848232838c 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -3242,6 +3242,30 @@ int VirtualMachine::set_saveas_disk(int disk_id, string& err_str) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +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; + } + + VectorAttribute * disk = get_disk(disk_id); + + if ( disk == 0 ) + { + return -1; + } + + disk->replace("HOTPLUG_SAVE_AS", iid); + disk->replace("HOTPLUG_SAVE_AS_SOURCE", source); + + return 0; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + int VirtualMachine::set_saveas_state() { switch (state) @@ -3339,36 +3363,11 @@ int VirtualMachine::clear_saveas_disk() return -1; } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int VirtualMachine::save_disk_hot(int disk_id, - const string& source, - int img_id) -{ - if (lcm_state != HOTPLUG_SAVEAS && lcm_state != HOTPLUG_SAVEAS_SUSPENDED - && lcm_state != HOTPLUG_SAVEAS_POWEROFF ) - { - return -1; - } - - VectorAttribute * disk = get_disk(disk_id); - - if ( disk == 0 ) - { - return -1; - } - - 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 VirtualMachine::get_saveas_disk(int& disk_id, string& source, int& image_id, string& tm_mad, string& ds_id) { vector disks; From dd12b9f0413c117414a7ac9fd4a69f2bc3aec641 Mon Sep 17 00:00:00 2001 From: Tino Vazquez Date: Wed, 10 Jun 2015 15:08:12 +0200 Subject: [PATCH 69/83] vCenter capacity presented to VMs based on VCPU and CPU --- src/vmm_mad/remotes/vcenter/vcenter_driver.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vmm_mad/remotes/vcenter/vcenter_driver.rb b/src/vmm_mad/remotes/vcenter/vcenter_driver.rb index 6c2518542d..7990750c15 100644 --- a/src/vmm_mad/remotes/vcenter/vcenter_driver.rb +++ b/src/vmm_mad/remotes/vcenter/vcenter_driver.rb @@ -738,7 +738,7 @@ class VCenterVm # Find out if we need to reconfigure capacity xml = REXML::Document.new xml_text - expected_cpu = xml.root.elements["//TEMPLATE/CPU"].text + expected_cpu = xml.root.elements["//TEMPLATE/VCPU"].text expected_memory = xml.root.elements["//TEMPLATE/MEMORY"].text current_cpu = vm.config.hardware.numCPU current_memory = vm.config.hardware.memoryMB @@ -1380,7 +1380,7 @@ private # Capacity section - cpu = xml.root.elements["//TEMPLATE/CPU"].text + cpu = xml.root.elements["//TEMPLATE/VCPU"].text memory = xml.root.elements["//TEMPLATE/MEMORY"].text capacity_spec = {:numCPUs => cpu.to_i, :memoryMB => memory } From 80c06dca381f616b3776c0db9cd6148ee7c25977 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Wed, 10 Jun 2015 19:56:35 +0200 Subject: [PATCH 70/83] feature #3782: renamed method to disksaveas, cli and Ruby OCA. Added snap id to save as disks --- include/Image.h | 2 +- include/ImageTemplate.h | 4 +- include/RequestManagerVirtualMachine.h | 12 ++-- include/VirtualMachine.h | 23 ++++---- src/cli/one_helper/onevm_helper.rb | 7 +-- src/cli/onevm | 8 +-- src/cloud/ec2/lib/EC2QueryServer.rb | 2 +- src/cloud/ec2/lib/ebs.rb | 2 +- src/image/ImageManagerDriver.cc | 4 +- src/lcm/LifeCycleStates.cc | 10 ++-- src/oca/ruby/opennebula/virtual_machine.rb | 15 +++-- src/rm/RequestManager.cc | 4 +- src/rm/RequestManagerVirtualMachine.cc | 13 +++-- .../OpenNebulaJSON/VirtualMachineJSON.rb | 2 +- src/tm/TransferManager.cc | 12 ++-- src/vm/VirtualMachine.cc | 56 ++++++++++++++----- 16 files changed, 104 insertions(+), 72 deletions(-) diff --git a/include/Image.h b/include/Image.h index ee1be2757c..b12f7eac9e 100644 --- a/include/Image.h +++ b/include/Image.h @@ -354,7 +354,7 @@ public: */ bool is_saving() { - return (static_cast(obj_template))->is_saving_hot(); + return (static_cast(obj_template))->is_saving(); } /** diff --git a/include/ImageTemplate.h b/include/ImageTemplate.h index 45348abe1b..6391161c67 100644 --- a/include/ImageTemplate.h +++ b/include/ImageTemplate.h @@ -59,7 +59,7 @@ public: Template::remove_all_except_restricted(restricted_attributes); }; - bool is_saving_hot() + bool is_saving() { bool save_as_hot; @@ -68,7 +68,7 @@ public: return save_as_hot; } - void set_saving_hot() + void set_saving() { replace("SAVE_AS_HOT", "YES"); } diff --git a/include/RequestManagerVirtualMachine.h b/include/RequestManagerVirtualMachine.h index 33f606d50e..44c6b974e6 100644 --- a/include/RequestManagerVirtualMachine.h +++ b/include/RequestManagerVirtualMachine.h @@ -170,15 +170,15 @@ public: /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ -class VirtualMachineDiskExport : public RequestManagerVirtualMachine +class VirtualMachineDiskSaveas : public RequestManagerVirtualMachine { public: - VirtualMachineDiskExport(): - RequestManagerVirtualMachine("VirtualMachineDiskExport", - "Exports a disk from virtual machine as a new image", - "A:siiss"){}; + VirtualMachineDiskSaveas(): + RequestManagerVirtualMachine("VirtualMachineDiskSaveas", + "Save a disk from virtual machine as a new image", + "A:siissi"){}; - ~VirtualMachineDiskExport(){}; + ~VirtualMachineDiskSaveas(){}; void request_execute(xmlrpc_c::paramList const& _paramList, RequestAttributes& att); diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index b0b9701002..2ca85bfa57 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -1270,38 +1270,39 @@ public: int generate_context(string &files, int &disk_id, string& token_password); // ------------------------------------------------------------------------- - // Export Disk related functions (save_as hot) + // "Save as" Disk related functions (save_as hot) // ------------------------------------------------------------------------- /** - * Mark the disk that is going to be exported (saved_as) + * Mark the disk that is going to be "save as" * @param disk_id of the VM + * @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 or image_id of current disk */ - int set_saveas_disk(int disk_id, string& err_str); + int set_saveas_disk(int disk_id, int snap_id, string& err_str); /** - * Set export attributes for the disk - * @param disk_id Index of the disk to export + * Set save attributes for the disk + * @param disk_id Index of the disk to save * @param source to save the disk * @param img_id ID of the image this disk will be saved to */ int set_saveas_disk(int disk_id, const string& source, int img_id); /** - * Sets the corresponding state to export the disk. - * @return 0 if the VM can be exported + * Sets the corresponding state to save the disk. + * @return 0 if the VM can be saved */ int set_saveas_state(); /** - * Clears the export state, moving the VM to the original state. - * @return 0 if the VM was in an export state + * Clears the save state, moving the VM to the original state. + * @return 0 if the VM was in an saveas state */ int clear_saveas_state(); /** - * Clears the export attributes of the disk being 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. */ @@ -1318,7 +1319,7 @@ public: * @return -1 if failure */ int get_saveas_disk(int& disk_id, string& source, int& image_id, - string& tm_mad, string& ds_id); + string& snap_id, string& tm_mad, string& ds_id); // ------------------------------------------------------------------------ // Authorization related functions 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 e97023ea3b..42f0d093ae 100755 --- a/src/cli/onevm +++ b/src/cli/onevm @@ -298,15 +298,15 @@ cmd=CommandParser::CmdParser.new(ARGV) do end end - disk_export_desc = <<-EOT.unindent - Exports the specified VM disk to a new Image. The Image is + 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-export", disk_export_desc, :vmid, :diskid, :img_name, + command :"disk-saveas", disk_saveas_desc, :vmid, :diskid, :img_name, :options=>[TYPE] do disk_id = args[1].to_i image_name = args[2] @@ -316,7 +316,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do "the image #{image_name}" helper.perform_action(args[0],options,verbose) do |vm| - res = vm.disk_export(disk_id, image_name, image_type) + res = vm.disk_saveas(disk_id, image_name, image_type,-1) if !OpenNebula.is_error?(res) puts "Image ID: #{res}" diff --git a/src/cloud/ec2/lib/EC2QueryServer.rb b/src/cloud/ec2/lib/EC2QueryServer.rb index 5381e4443c..37b58bd15a 100644 --- a/src/cloud/ec2/lib/EC2QueryServer.rb +++ b/src/cloud/ec2/lib/EC2QueryServer.rb @@ -218,7 +218,7 @@ class EC2QueryServer < CloudServer return rc end - image_id = vm.disk_export(1, + image_id = vm.disk_saveas(1, params["Name"], OpenNebula::Image::IMAGE_TYPES[0]) diff --git a/src/cloud/ec2/lib/ebs.rb b/src/cloud/ec2/lib/ebs.rb index 9f6807ff87..eff3b3575e 100644 --- a/src/cloud/ec2/lib/ebs.rb +++ b/src/cloud/ec2/lib/ebs.rb @@ -302,7 +302,7 @@ module EBS disk_id = vm["TEMPLATE/DISK[IMAGE_ID=#{image_id}]/DISK_ID"] if !disk_id.nil? - snapshot_id = vm.disk_export(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]) diff --git a/src/image/ImageManagerDriver.cc b/src/image/ImageManagerDriver.cc index d2cda36e9d..6bb6fa1aac 100644 --- a/src/image/ImageManagerDriver.cc +++ b/src/image/ImageManagerDriver.cc @@ -473,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); diff --git a/src/lcm/LifeCycleStates.cc b/src/lcm/LifeCycleStates.cc index 2a36ead8f8..76954ab173 100644 --- a/src/lcm/LifeCycleStates.cc +++ b/src/lcm/LifeCycleStates.cc @@ -1609,8 +1609,9 @@ void LifeCycleManager::saveas_success_action(int vid) int image_id; int disk_id; string tm_mad; + string snap; string ds_id; - string source; + string src; VirtualMachine * vm = vmpool->get(vid,true); @@ -1619,7 +1620,7 @@ void LifeCycleManager::saveas_success_action(int vid) return; } - int rc = vm->get_saveas_disk(disk_id, source, image_id, tm_mad, ds_id); + int rc = vm->get_saveas_disk(disk_id, src, image_id, snap, tm_mad, ds_id); vm->clear_saveas_disk(); @@ -1665,8 +1666,9 @@ void LifeCycleManager::saveas_failure_action(int vid) int image_id; int disk_id; string tm_mad; + string snap; string ds_id; - string source; + string src; VirtualMachine * vm = vmpool->get(vid,true); @@ -1675,7 +1677,7 @@ void LifeCycleManager::saveas_failure_action(int vid) return; } - int rc = vm->get_saveas_disk(disk_id, source, image_id, tm_mad, ds_id); + int rc = vm->get_saveas_disk(disk_id, src, image_id, snap, tm_mad, ds_id); vm->clear_saveas_disk(); diff --git a/src/oca/ruby/opennebula/virtual_machine.rb b/src/oca/ruby/opennebula/virtual_machine.rb index 71dfda1ca7..cb686f1f4e 100644 --- a/src/oca/ruby/opennebula/virtual_machine.rb +++ b/src/oca/ruby/opennebula/virtual_machine.rb @@ -43,7 +43,7 @@ module OpenNebula :attachnic => "vm.attachnic", :detachnic => "vm.detachnic", :recover => "vm.recover", - :diskexport => "vm.diskexport", + :disksaveas => "vm.disksaveas", :disksnapshotcreate => "vm.disksnapshotcreate", :disksnapshotrevert => "vm.disksnapshotrevert", :disksnapshotdelete => "vm.disksnapshotdelete" @@ -459,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 @@ -467,17 +467,20 @@ 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 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_export(disk_id, image_name, image_type="") + 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[:diskexport], + rc = @client.call(VM_METHODS[:disksaveas], @pe_id, disk_id, image_name, - image_type) + image_type, + snap_id) return rc end @@ -767,7 +770,7 @@ module OpenNebula image_id = disk["IMAGE_ID"] if !image_id.nil? && !image_id.empty? - rc = disk_export(disk_id.to_i,"#{name}-disk-#{disk_id}","") + 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 72a29c3d91..78ed77a113 100644 --- a/src/rm/RequestManager.cc +++ b/src/rm/RequestManager.cc @@ -302,7 +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_dexport(new VirtualMachineDiskExport()); + 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()); @@ -463,7 +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.diskexport", vm_dexport); + 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/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc index 6bb1d5cc3b..a2390fd4dc 100644 --- a/src/rm/RequestManagerVirtualMachine.cc +++ b/src/rm/RequestManagerVirtualMachine.cc @@ -1176,8 +1176,8 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -void VirtualMachineDiskExport::request_execute(xmlrpc_c::paramList const& paramList, - RequestAttributes& att) +void VirtualMachineDiskSaveas::request_execute( + xmlrpc_c::paramList const& paramList, RequestAttributes& att) { Nebula& nd = Nebula::instance(); @@ -1188,6 +1188,7 @@ void VirtualMachineDiskExport::request_execute(xmlrpc_c::paramList const& paramL 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); @@ -1224,7 +1225,7 @@ void VirtualMachineDiskExport::request_execute(xmlrpc_c::paramList const& paramL string error; // ------------------------------------------------------------------------- - // Prepare and check the VM/DISK to be export + // Prepare and check the VM/DISK to be saved as // ------------------------------------------------------------------------- if ((vm = get_vm(id, att)) == 0) { @@ -1236,7 +1237,7 @@ void VirtualMachineDiskExport::request_execute(xmlrpc_c::paramList const& paramL goto error_state; } - iid_orig = vm->set_saveas_disk(disk_id, error); + iid_orig = vm->set_saveas_disk(disk_id, snap_id, error); if (iid_orig == -1) { @@ -1317,7 +1318,7 @@ void VirtualMachineDiskExport::request_execute(xmlrpc_c::paramList const& paramL itemplate->add("SAVED_IMAGE_ID",iid_orig); itemplate->add("SAVED_DISK_ID",disk_id); itemplate->add("SAVED_VM_ID", id); - itemplate->set_saving_hot(); + itemplate->set_saving(); if (img_type.empty()) { @@ -1404,7 +1405,7 @@ error_state: vm->unlock(); failure_response(INTERNAL,request_error("VM has to be RUNNING, POWEROFF or " - "SUSPENDED to export disks.",""), att); + "SUSPENDED to save disks.",""), att); return; error_disk: diff --git a/src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb b/src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb index b181f4ddd3..295b10e1ca 100644 --- a/src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb +++ b/src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb @@ -104,7 +104,7 @@ module OpenNebulaJSON end def save_as(params=Hash.new) - disk_export(params['disk_id'].to_i, params['image_name'], params['type']) + 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 a3dcbaea7d..80f479fbc1 100644 --- a/src/tm/TransferManager.cc +++ b/src/tm/TransferManager.cc @@ -2053,7 +2053,8 @@ void TransferManager::saveas_hot_action(int vid) { int disk_id; int image_id; - string source; + string src; + string snap_id; string tm_mad; string ds_id; @@ -2084,7 +2085,7 @@ void TransferManager::saveas_hot_action(int vid) goto error_common; } - if (vm->get_saveas_disk(disk_id, source, image_id, tm_mad, ds_id) != 0) + 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 export it"); goto error_common; @@ -2097,7 +2098,7 @@ void TransferManager::saveas_hot_action(int vid) goto error_driver; } - 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) @@ -2105,12 +2106,13 @@ void TransferManager::saveas_hot_action(int vid) goto error_file; } - //MVDS tm_mad hostname:remote_system_dir/disk.0 vmid dsid + //MVDS 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 << " " - << source << " " + << src << " " + << snap_id << " " << vm->get_oid() << " " << ds_id << endl; diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index 848232838c..884600358d 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -2530,7 +2530,6 @@ int VirtualMachine::set_attach_nic(int nic_id) void VirtualMachine::release_disk_images() { int iid; - int save_as_id; int num_disks; int did = -1; @@ -2572,12 +2571,6 @@ void VirtualMachine::release_disk_images() imagem->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); - } - } } @@ -3216,25 +3209,49 @@ const VectorAttribute* VirtualMachine::get_disk(int disk_id) const /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int VirtualMachine::set_saveas_disk(int disk_id, string& err_str) +int VirtualMachine::set_saveas_disk(int disk_id, int snap_id, string& err_str) { int iid = -1; VectorAttribute * disk = get_disk(disk_id); - if ( disk == 0 ) + if (disk == 0) { err_str = "DISK does not exist."; return -1; } - if ( disk->vector_value("IMAGE_ID", iid) != 0 ) + 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 (snaps == 0) + { + if (snap_id != -1) + { + err_str = "Snapshot does not exists."; + return -1; + } + } + else + { + if (snap_id == -1) + { + snap_id = snaps->get_active_id(); + } + else if (!snaps->exists(snap_id)) + { + err_str = "Snapshot does not exists."; + return -1; + } + } + disk->replace("HOTPLUG_SAVE_AS_ACTIVE", "YES"); + disk->replace("HOTPLUG_SAVE_AS_SNAPSHOT_ID", snap_id); return iid; } @@ -3268,6 +3285,8 @@ int VirtualMachine::set_saveas_disk(int disk_id, const string& source, int iid) int VirtualMachine::set_saveas_state() { + string s; + switch (state) { case ACTIVE: @@ -3277,22 +3296,24 @@ int VirtualMachine::set_saveas_state() } lcm_state = HOTPLUG_SAVEAS; - break; + break; case POWEROFF: state = ACTIVE; lcm_state = HOTPLUG_SAVEAS_POWEROFF; - break; + break; case SUSPENDED: state = ACTIVE; lcm_state = HOTPLUG_SAVEAS_SUSPENDED; - break; + break; default: return -1; } + log("VM", Log::INFO, "New state is " + lcm_state_to_str(s,lcm_state)); + return 0; } @@ -3301,20 +3322,25 @@ int VirtualMachine::set_saveas_state() 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: @@ -3355,6 +3381,7 @@ int VirtualMachine::clear_saveas_disk() 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; } @@ -3368,7 +3395,7 @@ int VirtualMachine::clear_saveas_disk() /* -------------------------------------------------------------------------- */ int VirtualMachine::get_saveas_disk(int& disk_id, string& source, - int& image_id, string& tm_mad, string& ds_id) + int& image_id, string& snap_id, string& tm_mad, string& ds_id) { vector disks; VectorAttribute * disk; @@ -3391,6 +3418,7 @@ int VirtualMachine::get_saveas_disk(int& disk_id, string& source, { 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); From 943e0e5292d439fbc29ad3addb7e185d93862fc9 Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Wed, 10 Jun 2015 18:44:03 -0400 Subject: [PATCH 71/83] feature #3782: add qcow2 tm/snap_{create,revert} --- src/tm_mad/qcow2/snap_create | 75 +++++++++++++++++++++++++++++++++++- src/tm_mad/qcow2/snap_revert | 50 +++++++++++++++++++++++- 2 files changed, 123 insertions(+), 2 deletions(-) mode change 120000 => 100755 src/tm_mad/qcow2/snap_create mode change 120000 => 100755 src/tm_mad/qcow2/snap_revert diff --git a/src/tm_mad/qcow2/snap_create b/src/tm_mad/qcow2/snap_create deleted file mode 120000 index 9c454e8cd4..0000000000 --- a/src/tm_mad/qcow2/snap_create +++ /dev/null @@ -1 +0,0 @@ -../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/qcow2/snap_create b/src/tm_mad/qcow2/snap_create new file mode 100755 index 0000000000..f91356d7d1 --- /dev/null +++ b/src/tm_mad/qcow2/snap_create @@ -0,0 +1,74 @@ +#!/bin/bash -x + +# -------------------------------------------------------------------------- # +# Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +# snap_create host:parent_image snap_id vmid ds_id + +SRC=$1 +SNAP_ID=$2 +VMID=$3 +DSID=$4 + +if [ -z "${ONE_LOCATION}" ]; then + TMCOMMON=/var/lib/one/remotes/tm/tm_common.sh + DATASTORES=/var/lib/one/datastores +else + TMCOMMON=$ONE_LOCATION/var/remotes/tm/tm_common.sh + DATASTORES=$ONE_LOCATION/var/datastores +fi + +. $TMCOMMON + +SRC_PATH=`arg_path $SRC` + +SYSTEM_DS_PATH=$(dirname ${SRC_PATH}) + +DISK_ID=$(basename ${SRC} | cut -d. -f2) +DISK_PATH="${SYSTEM_DS_PATH}/disk.${DISK_ID}" +SNAP_DIR="${DISK_PATH}.snap" +SNAP_PATH="${SNAP_DIR}/${SNAP_ID}" +SNAP_PATH_RELATIVE=$(basename ${SNAP_PATH}) +CURRENT_PATH=${DISK_PATH} + +if [ ! -d ${SNAP_PATH} ]; then + mkdir ${SNAP_DIR} +fi + +# Move save current snapshot and create a new one. The snapshot uses +# absolute path name as the qemu-img has problems with relative backing +# file paths and symlinks +mv ${CURRENT_PATH} ${SNAP_PATH} +qemu-img create -f qcow2 -b ${SNAP_PATH} ${CURRENT_PATH} + +# TODO: Check that the new snapshot can be created. Roll back in case +# of error + +# Convert backing file absolute path to relative path so it works outside +# the system directory. Do not do this for snapshot one as: +# * It could be a non backed file (persistent) +# * The backing file is in images directory, is not relative +if [ "$SNAP_ID" != "0" ]; then + BACKING_FILE=$(qemu-img info ${SNAP_PATH} | grep '^backing file:' | \ + cut -d: -f2 | sed 's/^ //') + + if [ -n "$BACKING_FILE" ]; then + RELATIVE_BACKING_FILE=$(basename ${BACKING_FILE}) + + qemu-img rebase -u -b ${RELATIVE_BACKING_FILE} ${SNAP_PATH} + fi +fi + diff --git a/src/tm_mad/qcow2/snap_revert b/src/tm_mad/qcow2/snap_revert deleted file mode 120000 index 9c454e8cd4..0000000000 --- a/src/tm_mad/qcow2/snap_revert +++ /dev/null @@ -1 +0,0 @@ -../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/qcow2/snap_revert b/src/tm_mad/qcow2/snap_revert new file mode 100755 index 0000000000..38ac9ae954 --- /dev/null +++ b/src/tm_mad/qcow2/snap_revert @@ -0,0 +1,49 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +# snap_create host:parent_image snap_id vmid ds_id + +SRC=$1 +SNAP_ID=$2 +VMID=$3 +DSID=$4 + +if [ -z "${ONE_LOCATION}" ]; then + TMCOMMON=/var/lib/one/remotes/tm/tm_common.sh + DATASTORES=/var/lib/one/datastores +else + TMCOMMON=$ONE_LOCATION/var/remotes/tm/tm_common.sh + DATASTORES=$ONE_LOCATION/var/datastores +fi + +. $TMCOMMON + +SRC_PATH=`arg_path $SRC` + +SYSTEM_DS_PATH=$(dirname ${SRC_PATH}) + +DISK_ID=$(basename ${SRC} | cut -d. -f2) +DISK_PATH="${SYSTEM_DS_PATH}/disk.${DISK_ID}" +SNAP_DIR="${DISK_PATH}.snap" +SNAP_PATH="${SNAP_DIR}/${SNAP_ID}" +SNAP_PATH_RELATIVE=$(basename ${SNAP_PATH}) +CURRENT_PATH=${DISK_PATH} + +rm ${CURRENT_PATH} +qemu-img create -f qcow2 -b ${SNAP_PATH} ${CURRENT_PATH} + From e5bcaea18de84b1aa4c4b626b0a962ada41e607d Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Wed, 10 Jun 2015 18:49:38 -0400 Subject: [PATCH 72/83] feature #3782: add qcow2 tm/snap_delete --- src/tm_mad/qcow2/snap_delete | 49 +++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) mode change 120000 => 100755 src/tm_mad/qcow2/snap_delete diff --git a/src/tm_mad/qcow2/snap_delete b/src/tm_mad/qcow2/snap_delete deleted file mode 120000 index 9c454e8cd4..0000000000 --- a/src/tm_mad/qcow2/snap_delete +++ /dev/null @@ -1 +0,0 @@ -../common/not_supported.sh \ No newline at end of file diff --git a/src/tm_mad/qcow2/snap_delete b/src/tm_mad/qcow2/snap_delete new file mode 100755 index 0000000000..d8d3c4d452 --- /dev/null +++ b/src/tm_mad/qcow2/snap_delete @@ -0,0 +1,48 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +# snap_delete host:parent_image snap_id vmid ds_id + +SRC=$1 +SNAP_ID=$2 +VMID=$3 +DSID=$4 + +if [ -z "${ONE_LOCATION}" ]; then + TMCOMMON=/var/lib/one/remotes/tm/tm_common.sh + DATASTORES=/var/lib/one/datastores +else + TMCOMMON=$ONE_LOCATION/var/remotes/tm/tm_common.sh + DATASTORES=$ONE_LOCATION/var/datastores +fi + +. $TMCOMMON + +SRC_PATH=`arg_path $SRC` + +SYSTEM_DS_PATH=$(dirname ${SRC_PATH}) + +DISK_ID=$(basename ${SRC} | cut -d. -f2) +DISK_PATH="${SYSTEM_DS_PATH}/disk.${DISK_ID}" +SNAP_DIR="${DISK_PATH}.snap" +SNAP_PATH="${SNAP_DIR}/${SNAP_ID}" +SNAP_PATH_RELATIVE=$(basename ${SNAP_PATH}) +CURRENT_PATH=${DISK_PATH} + +rm ${SNAP_PATH} + From 996ee89dc1fc3682cf81322f094b9c1790dba1fb Mon Sep 17 00:00:00 2001 From: Jaime Melis Date: Thu, 11 Jun 2015 18:09:41 +0200 Subject: [PATCH 73/83] feature #3782: allow disk-saveas operations on the currently running disk --- src/vm/VirtualMachine.cc | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index 884600358d..a87af5db8f 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -3229,23 +3229,11 @@ int VirtualMachine::set_saveas_disk(int disk_id, int snap_id, string& err_str) const Snapshots * snaps = get_disk_snapshots(disk_id, err_str); - if (snaps == 0) + if (snap_id != -1) { - if (snap_id != -1) + if (snaps == 0 || !snaps->exists(snap_id)) { - err_str = "Snapshot does not exists."; - return -1; - } - } - else - { - if (snap_id == -1) - { - snap_id = snaps->get_active_id(); - } - else if (!snaps->exists(snap_id)) - { - err_str = "Snapshot does not exists."; + err_str = "Snapshot does not exist."; return -1; } } From ae33c915f2db946a69b9170d4fd01682024e8e69 Mon Sep 17 00:00:00 2001 From: Jaime Melis Date: Thu, 11 Jun 2015 18:10:23 +0200 Subject: [PATCH 74/83] feature #3782: Add snapshot id to the onevm disk-saveas command --- src/cli/onevm | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/src/cli/onevm b/src/cli/onevm index 42f0d093ae..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 ######################################################################## @@ -307,16 +315,27 @@ cmd=CommandParser::CmdParser.new(ARGV) do EOT command :"disk-saveas", disk_saveas_desc, :vmid, :diskid, :img_name, - :options=>[TYPE] do - disk_id = args[1].to_i - image_name = args[2] - image_type = options[:type] || "" + :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_saveas(disk_id, image_name, image_type,-1) + res = vm.disk_saveas(disk_id, image_name, image_type, snapshot_id) if !OpenNebula.is_error?(res) puts "Image ID: #{res}" From d8c15a1394ebafcbe2f49884fa9f841931300bb4 Mon Sep 17 00:00:00 2001 From: Jaime Melis Date: Thu, 11 Jun 2015 18:11:08 +0200 Subject: [PATCH 75/83] feature #3782: Update ceph cpds and mvds scripts to handle snaps --- src/tm_mad/ceph/cpds | 14 +++++--- src/tm_mad/ceph/mvds | 81 -------------------------------------------- 2 files changed, 9 insertions(+), 86 deletions(-) diff --git a/src/tm_mad/ceph/cpds b/src/tm_mad/ceph/cpds index b4deda72b9..c194032aec 100755 --- a/src/tm_mad/ceph/cpds +++ b/src/tm_mad/ceph/cpds @@ -17,15 +17,18 @@ #--------------------------------------------------------------------------- # # 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 +46,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 +79,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 @@ -84,6 +87,7 @@ if [ -n "$CEPH_USER" ]; then RBD="$RBD --id ${CEPH_USER}" fi +echo "$RBD copy $RBD_DST $DST" > /tmp/k ssh_exec_and_log "$SRC_HOST" "$RBD copy $RBD_DST $DST" \ "Error cloning $RBD_DST to $DST in $SRC_HOST" diff --git a/src/tm_mad/ceph/mvds b/src/tm_mad/ceph/mvds index f64234933d..55e35ec3a4 100755 --- a/src/tm_mad/ceph/mvds +++ b/src/tm_mad/ceph/mvds @@ -22,85 +22,4 @@ # - 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 < Date: Thu, 11 Jun 2015 18:22:08 +0200 Subject: [PATCH 76/83] feature #3782: Update all cpds to include the SNAP_ID parameter --- src/tm_mad/ceph/cpds | 1 - src/tm_mad/fs_lvm/cpds | 8 +++++--- src/tm_mad/lvm/cpds | 8 +++++--- src/tm_mad/shared/cpds | 11 +++++------ src/tm_mad/ssh/cpds | 11 +++++------ src/tm_mad/vmfs/mvds | 11 +++++------ 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/tm_mad/ceph/cpds b/src/tm_mad/ceph/cpds index c194032aec..a811614c58 100755 --- a/src/tm_mad/ceph/cpds +++ b/src/tm_mad/ceph/cpds @@ -16,7 +16,6 @@ # 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 diff --git a/src/tm_mad/fs_lvm/cpds b/src/tm_mad/fs_lvm/cpds index f4df668072..6e88b772da 100755 --- a/src/tm_mad/fs_lvm/cpds +++ b/src/tm_mad/fs_lvm/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 diff --git a/src/tm_mad/lvm/cpds b/src/tm_mad/lvm/cpds index 8532363507..c97379f250 100755 --- a/src/tm_mad/lvm/cpds +++ b/src/tm_mad/lvm/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 diff --git a/src/tm_mad/shared/cpds b/src/tm_mad/shared/cpds index 1a898ad2ba..fae3b52e8b 100755 --- a/src/tm_mad/shared/cpds +++ b/src/tm_mad/shared/cpds @@ -16,19 +16,18 @@ # limitations under the License. # #--------------------------------------------------------------------------- # -# mvds host:remote_system_ds/disk.i fe:SOURCE vmid dsid +# 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 -# - vmid is the id of the VM -# - dsid is the target datastore (0 is the system datastore) +# - snapid is the snapshot id. "-1" for none SRC=$1 DST=$2 - -VMID=$3 -DSID=$4 +SNAP_ID=$3 +VMID=$4 +DSID=$5 if [ -z "${ONE_LOCATION}" ]; then TMCOMMON=/var/lib/one/remotes/tm/tm_common.sh diff --git a/src/tm_mad/ssh/cpds b/src/tm_mad/ssh/cpds index e42b11feb7..2a7d64f691 100755 --- a/src/tm_mad/ssh/cpds +++ b/src/tm_mad/ssh/cpds @@ -16,19 +16,18 @@ # limitations under the License. # #--------------------------------------------------------------------------- # -# cpds host:remote_system_ds/disk.i fe:SOURCE vmid dsid +# 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 -# - vmid is the id of the VM -# - dsid is the target datastore (0 is the system datastore) +# - snapid is the snapshot id. "-1" for none SRC=$1 DST=$2 - -VMID=$3 -DSID=$4 +SNAP_ID=$3 +VMID=$4 +DSID=$5 if [ -z "${ONE_LOCATION}" ]; then TMCOMMON=/var/lib/one/remotes/tm/tm_common.sh diff --git a/src/tm_mad/vmfs/mvds b/src/tm_mad/vmfs/mvds index 59815c0869..824c08ac62 100755 --- a/src/tm_mad/vmfs/mvds +++ b/src/tm_mad/vmfs/mvds @@ -16,19 +16,18 @@ # limitations under the License. # #--------------------------------------------------------------------------- # -# mvds host:remote_system_ds/disk.i fe:SOURCE vmid dsid +# 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 -# - vmid is the id of the VM -# - dsid is the target datastore (0 is the system datastore) +# - snapid is the snapshot id. "-1" for none SRC=$1 DST=$2 - -VMID=$3 -DSID=$4 +SNAP_ID=$3 +VMID=$4 +DSID=$5 if [ -z "${ONE_LOCATION}" ]; then TMCOMMON=/var/lib/one/remotes/tm/tm_common.sh From 28e3791365d2810a9d2eafd94c4370e296801fcc Mon Sep 17 00:00:00 2001 From: Tino Vazquez Date: Fri, 12 Jun 2015 17:29:53 +0200 Subject: [PATCH 77/83] Extra check on vCenter template import (cherry picked from commit 31216f7d98d0892e4e48201ff86dfa8458c29292) --- src/vmm_mad/remotes/vcenter/vcenter_driver.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vmm_mad/remotes/vcenter/vcenter_driver.rb b/src/vmm_mad/remotes/vcenter/vcenter_driver.rb index 7990750c15..a85ff1fbc6 100644 --- a/src/vmm_mad/remotes/vcenter/vcenter_driver.rb +++ b/src/vmm_mad/remotes/vcenter/vcenter_driver.rb @@ -264,7 +264,7 @@ class VIClient datacenters.each { |dc| vms = get_entities(dc.vmFolder, 'VirtualMachine') - tmp = vms.select { |v| v.config.template == true } + tmp = vms.select { |v| v.config && (v.config.template == true) } one_tmp = [] From b5136a152ffdb15e30dc5e3accfa83581319fc24 Mon Sep 17 00:00:00 2001 From: Jaime Melis Date: Fri, 12 Jun 2015 17:50:09 +0200 Subject: [PATCH 78/83] Feature #3782: Remove debugging data --- src/tm_mad/ceph/cpds | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tm_mad/ceph/cpds b/src/tm_mad/ceph/cpds index a811614c58..32c8b5146c 100755 --- a/src/tm_mad/ceph/cpds +++ b/src/tm_mad/ceph/cpds @@ -86,7 +86,6 @@ if [ -n "$CEPH_USER" ]; then RBD="$RBD --id ${CEPH_USER}" fi -echo "$RBD copy $RBD_DST $DST" > /tmp/k ssh_exec_and_log "$SRC_HOST" "$RBD copy $RBD_DST $DST" \ "Error cloning $RBD_DST to $DST in $SRC_HOST" From 1b531f82ff39d8cd4fa350ebe996f48603865d6f Mon Sep 17 00:00:00 2001 From: Jaime Melis Date: Fri, 12 Jun 2015 17:50:28 +0200 Subject: [PATCH 79/83] Feature #3782: Simplify all TM/mvds action as now they don't handle deferred saveas --- src/tm_mad/ceph/mvds | 6 ---- src/tm_mad/lvm/mvds | 48 ---------------------------- src/tm_mad/qcow2/mvds | 56 -------------------------------- src/tm_mad/shared/mvds | 56 -------------------------------- src/tm_mad/vmfs/mvds | 72 ------------------------------------------ 5 files changed, 238 deletions(-) diff --git a/src/tm_mad/ceph/mvds b/src/tm_mad/ceph/mvds index 55e35ec3a4..8c976fe703 100755 --- a/src/tm_mad/ceph/mvds +++ b/src/tm_mad/ceph/mvds @@ -16,10 +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 - exit 0 diff --git a/src/tm_mad/lvm/mvds b/src/tm_mad/lvm/mvds index 1d80718a1b..55e35ec3a4 100755 --- a/src/tm_mad/lvm/mvds +++ b/src/tm_mad/lvm/mvds @@ -22,52 +22,4 @@ # - 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/lvm/lvm.conf - -#------------------------------------------------------------------------------- -# Set dst path and dir -#------------------------------------------------------------------------------- -SRC_PATH=`arg_path $SRC` -SRC_HOST=`arg_host $SRC` - -DST_PATH=`arg_path $DST` -DST_HOST=`arg_host $DST` - -VG_NAME=$(echo $DST_PATH|cut -d. -f1) -LV_NAME=$(echo $DST_PATH|cut -d. -f2) - -TARGET_DEV=/dev/$VG_NAME/$LV_NAME - -DUMP_CMD=$(cat < Date: Mon, 15 Jun 2015 23:28:38 +0200 Subject: [PATCH 80/83] feature #3782: Fix comment --- src/tm/TransferManager.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tm/TransferManager.cc b/src/tm/TransferManager.cc index 80f479fbc1..c4d95f34fd 100644 --- a/src/tm/TransferManager.cc +++ b/src/tm/TransferManager.cc @@ -2106,7 +2106,7 @@ void TransferManager::saveas_hot_action(int vid) goto error_file; } - //MVDS tm_mad hostname:remote_system_dir/disk.0 source snapid vmid dsid + //CPDS tm_mad hostname:remote_system_dir/disk.0 source snapid vmid dsid xfr << "CPDS " << tm_mad << " " << vm->get_hostname() << ":" From 32832269e5c1e97c35c885706280e49ded0ecad2 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Tue, 16 Jun 2015 01:59:24 +0200 Subject: [PATCH 81/83] feature #3782: Fix return codes --- src/rm/RequestManagerImage.cc | 6 +++--- src/rm/RequestManagerVirtualMachine.cc | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) 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 a2390fd4dc..b29f0f13f5 100644 --- a/src/rm/RequestManagerVirtualMachine.cc +++ b/src/rm/RequestManagerVirtualMachine.cc @@ -2404,7 +2404,7 @@ void VirtualMachineDiskSnapshotRevert::request_execute( } else { - success_response(id, att); + success_response(snap_id, att); } return; @@ -2443,7 +2443,7 @@ void VirtualMachineDiskSnapshotDelete::request_execute( } else { - success_response(id, att); + success_response(snap_id, att); } return; From 4e267311fcd96cf8349bd4a691fdccc869fd2223 Mon Sep 17 00:00:00 2001 From: gschmidt Date: Wed, 17 Jun 2015 04:15:12 +0200 Subject: [PATCH 82/83] added missing delete --- src/pool/PoolObjectSQL.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pool/PoolObjectSQL.cc b/src/pool/PoolObjectSQL.cc index f7c6d5715a..c00a95bd4e 100644 --- a/src/pool/PoolObjectSQL.cc +++ b/src/pool/PoolObjectSQL.cc @@ -280,6 +280,8 @@ int PoolObjectSQL::append_template( return -1; } + delete old_tmpl; + return 0; } From c41e9355c15074e5b2507e1a46d4e92048c1d8cf Mon Sep 17 00:00:00 2001 From: gschmidt Date: Wed, 17 Jun 2015 04:34:17 +0200 Subject: [PATCH 83/83] added second missing delete (this one is for replacement) --- src/pool/PoolObjectSQL.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pool/PoolObjectSQL.cc b/src/pool/PoolObjectSQL.cc index c00a95bd4e..da46973739 100644 --- a/src/pool/PoolObjectSQL.cc +++ b/src/pool/PoolObjectSQL.cc @@ -223,6 +223,8 @@ int PoolObjectSQL::replace_template( return -1; } + delete old_tmpl; + return 0; }