Revision 781a9928
src/tm_mad/vcenter/clone | ||
---|---|---|
1 |
../common/dummy.sh |
src/tm_mad/vcenter/clone | ||
---|---|---|
1 |
#!/usr/bin/env ruby |
|
2 |
|
|
3 |
# ---------------------------------------------------------------------------- # |
|
4 |
# Copyright 2002-2016, OpenNebula Project, OpenNebula Systems # |
|
5 |
# # |
|
6 |
# Licensed under the Apache License, Version 2.0 (the "License"); you may # |
|
7 |
# not use this file except in compliance with the License. You may obtain # |
|
8 |
# a copy of the License at # |
|
9 |
# # |
|
10 |
# http://www.apache.org/licenses/LICENSE-2.0 # |
|
11 |
# # |
|
12 |
# Unless required by applicable law or agreed to in writing, software # |
|
13 |
# distributed under the License is distributed on an "AS IS" BASIS, # |
|
14 |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # |
|
15 |
# See the License for the specific language governing permissions and # |
|
16 |
# limitations under the License. # |
|
17 |
# ---------------------------------------------------------------------------- # |
|
18 |
|
|
19 |
# clone fe:SOURCE host:remote_system_ds/disk.i vmid dsid |
|
20 |
# - fe is the front-end hostname |
|
21 |
# - SOURCE is the path of the disk image in the form DS_BASE_PATH/disk |
|
22 |
# - host is the target host to deploy the VM |
|
23 |
# - remote_system_ds is the path for the system datastore in the host |
|
24 |
# - vmid is the id of the VM |
|
25 |
# - dsid is the target datastore (0 is the system datastore) |
|
26 |
|
|
27 |
ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION) |
|
28 |
|
|
29 |
if !ONE_LOCATION |
|
30 |
RUBY_LIB_LOCATION="/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION) |
|
31 |
else |
|
32 |
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" if !defined?(RUBY_LIB_LOCATION) |
|
33 |
end |
|
34 |
|
|
35 |
$: << RUBY_LIB_LOCATION |
|
36 |
$: << File.dirname(__FILE__) |
|
37 |
|
|
38 |
require 'opennebula' |
|
39 |
require 'vcenter_driver' |
|
40 |
require 'digest' |
|
41 |
|
|
42 |
################################################################################ |
|
43 |
|
|
44 |
def check_valid(parameter, label) |
|
45 |
if parameter.nil? || parameter.empty? |
|
46 |
STDERR.puts "Not enough information to clone the image. " + |
|
47 |
"Missing '#{label}'." |
|
48 |
exit -1 |
|
49 |
end |
|
50 |
end |
|
51 |
|
|
52 |
################################################################################ |
|
53 |
|
|
54 |
src = ARGV[0] |
|
55 |
dst = ARGV[1] |
|
56 |
vm_id = ARGV[2] |
|
57 |
source_ds_id = ARGV[3] |
|
58 |
|
|
59 |
target_ds_id = dst.split("/")[-3] |
|
60 |
disk_id = dst.split(".")[-1] |
|
61 |
|
|
62 |
src_host, src_path = src.split ":" |
|
63 |
hostname, dst_path = dst.split ":" |
|
64 |
|
|
65 |
client = OpenNebula::Client.new |
|
66 |
ds_pool = OpenNebula::DatastorePool.new(client) |
|
67 |
|
|
68 |
rc = ds_pool.info |
|
69 |
if OpenNebula.is_error?(rc) |
|
70 |
puts rc.message |
|
71 |
exit -1 |
|
72 |
end |
|
73 |
|
|
74 |
xml = "/DATASTORE_POOL/DATASTORE[ID='#{source_ds_id}']/TEMPLATE/VCENTER_NAME" |
|
75 |
source_ds = ds_pool[xml] |
|
76 |
|
|
77 |
xml = "/DATASTORE_POOL/DATASTORE[ID='#{target_ds_id}']/TEMPLATE/VCENTER_NAME" |
|
78 |
target_ds = ds_pool[xml] |
|
79 |
|
|
80 |
################################################################################ |
|
81 |
|
|
82 |
# Generate target path |
|
83 |
target_path = "one_#{vm_id}_#{disk_id}.vmdk" |
|
84 |
|
|
85 |
################################################################################ |
|
86 |
|
|
87 |
# Check for errors |
|
88 |
check_valid source_ds, "source_ds" |
|
89 |
check_valid target_ds, "target_ds" |
|
90 |
check_valid hostname, "hostname" |
|
91 |
check_valid src_path, "src_path" |
|
92 |
|
|
93 |
################################################################################ |
|
94 |
|
|
95 |
begin |
|
96 |
host_id = VCenterDriver::VIClient.translate_hostname(hostname) |
|
97 |
vi_client = VCenterDriver::VIClient.new host_id |
|
98 |
|
|
99 |
vi_client.copy_virtual_disk(src_path, source_ds, target_path, target_ds) |
|
100 |
rescue Exception => e |
|
101 |
STDERR.puts "Error cloning img #{src_path} size. Reason: #{e.message}" |
|
102 |
exit -1 |
|
103 |
end |
src/tm_mad/vcenter/delete | ||
---|---|---|
22 | 22 |
# - vmid is the id of the VM |
23 | 23 |
# - dsid is the target datastore (0 is the system datastore) |
24 | 24 |
|
25 |
# Return if this has called for the whole directory, instead of for a specific |
|
26 |
# disk. |
|
27 |
|
|
28 |
if !ARGV[0].match(/disk\.\d+$/) |
|
29 |
exit(0) |
|
30 |
end |
|
31 |
|
|
32 |
# ---------------------------------------------------------------------------- # |
|
33 |
|
|
25 | 34 |
ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION) |
26 | 35 |
|
27 | 36 |
if !ONE_LOCATION |
... | ... | |
34 | 43 |
$: << File.dirname(__FILE__) |
35 | 44 |
|
36 | 45 |
require 'vcenter_driver' |
46 |
require 'opennebula' |
|
37 | 47 |
|
38 | 48 |
hostname, img_path = ARGV[0].split(":") |
39 | 49 |
vmid = ARGV[1] |
40 | 50 |
dsid = ARGV[2] |
41 | 51 |
|
52 |
client = OpenNebula::Client.new |
|
53 |
vm = OpenNebula::VirtualMachine.new_with_id(vmid, client) |
|
54 |
vm.info |
|
55 |
|
|
56 |
disk_id = img_path.split(".")[-1] |
|
57 |
|
|
58 |
persistent = vm["TEMPLATE/DISK[DISK_ID=#{disk_id}]/PERSISTENT"] |
|
59 |
|
|
60 |
if persistent != "YES" |
|
61 |
img_path = "one_#{vmid}_#{disk_id}.vmdk" |
|
62 |
end |
|
63 |
|
|
42 | 64 |
begin |
43 | 65 |
host_id = VCenterDriver::VIClient.translate_hostname(hostname) |
44 | 66 |
vi_client = VCenterDriver::VIClient.new host_id |
... | ... | |
47 | 69 |
vi_client.delete_virtual_disk(img_path, ds_name) |
48 | 70 |
rescue Exception => e |
49 | 71 |
STDERR.puts "Error delete virtual disk #{img_path} in datastore #{dsid}."\ |
50 |
" Reason: #{e.message}" |
|
72 |
" Reason: #{e.message}\n#{e.backtrace}"
|
|
51 | 73 |
exit -1 |
52 | 74 |
end |
src/vmm_mad/remotes/vcenter/vcenter_driver.rb | ||
---|---|---|
823 | 823 |
end |
824 | 824 |
|
825 | 825 |
def self.find_ds_name(ds_id) |
826 |
ds = OpenNebula::Datastore.new_with_id(ds_id) |
|
826 |
ds = OpenNebula::Datastore.new_with_id(ds_id, OpenNebula::Client.new)
|
|
827 | 827 |
rc = ds.info |
828 | 828 |
raise "Could not find datastore #{ds_id}" if OpenNebula.is_error?(rc) |
829 | 829 |
|
... | ... | |
1524 | 1524 |
reconfigure_vm(vm, xml, false, hostname) |
1525 | 1525 |
|
1526 | 1526 |
vm.PowerOnVM_Task.wait_for_completion |
1527 |
|
|
1527 | 1528 |
return vm.config.uuid |
1528 | 1529 |
end |
1529 | 1530 |
end |
... | ... | |
1537 | 1538 |
# @param disks VM attached disks |
1538 | 1539 |
############################################################################ |
1539 | 1540 |
def self.cancel(deploy_id, hostname, lcm_state, keep_disks, disks, to_template) |
1541 |
|
|
1540 | 1542 |
case lcm_state |
1541 | 1543 |
when "SHUTDOWN_POWEROFF", "SHUTDOWN_UNDEPLOY" |
1542 | 1544 |
shutdown(deploy_id, hostname, lcm_state, keep_disks, disks, to_template) |
1543 | 1545 |
when "CANCEL", "LCM_INIT", "CLEANUP_RESUBMIT", "SHUTDOWN", "CLEANUP_DELETE" |
1544 | 1546 |
hid = VIClient::translate_hostname(hostname) |
1545 | 1547 |
connection = VIClient.new(hid) |
1546 |
vm = connection.find_vm_template(deploy_id) |
|
1548 |
|
|
1549 |
vm = connection.find_vm_template(deploy_id) |
|
1547 | 1550 |
|
1548 | 1551 |
begin |
1549 | 1552 |
if vm.summary.runtime.powerState == "poweredOn" |
... | ... | |
1551 | 1554 |
end |
1552 | 1555 |
rescue |
1553 | 1556 |
end |
1557 |
|
|
1554 | 1558 |
if keep_disks |
1555 | 1559 |
detach_all_disks(vm) |
1556 | 1560 |
else |
... | ... | |
1661 | 1665 |
hid = VIClient::translate_hostname(hostname) |
1662 | 1666 |
connection = VIClient.new(hid) |
1663 | 1667 |
|
1664 |
vm = connection.find_vm_template(deploy_id) |
|
1668 |
vm = connection.find_vm_template(deploy_id) |
|
1669 |
vmid = get_vm_id |
|
1665 | 1670 |
|
1666 | 1671 |
case lcm_state |
1667 | 1672 |
when "SHUTDOWN" |
... | ... | |
2628 | 2633 |
|
2629 | 2634 |
end |
2630 | 2635 |
|
2631 |
|
|
2632 |
|
|
2633 | 2636 |
reconfigure_vm(vm, xml, true, hostname) |
2634 | 2637 |
|
2635 | 2638 |
# Power on the VM |
... | ... | |
2860 | 2863 |
hid = VIClient::translate_hostname(hostname) |
2861 | 2864 |
connection = VIClient.new(hid) |
2862 | 2865 |
disks.each{|disk| |
2863 |
ds_name = disk.elements["DATASTORE"].text |
|
2864 |
img_name = disk.elements["SOURCE"].text
|
|
2865 |
type_str = disk.elements["TYPE"].text |
|
2866 |
ds_name = disk.elements["DATASTORE"].text
|
|
2867 |
img_name = get_disk_img_path(disk, vmid)
|
|
2868 |
type_str = disk.elements["TYPE"].text
|
|
2866 | 2869 |
|
2867 |
disk_array += attach_disk("", "", ds_name, img_name, type_str, 0, vm, connection)[:deviceChange] |
|
2870 |
disk_array += attach_disk("", "", ds_name, img_name, type_str, 0, vm, connection)[:deviceChange]
|
|
2868 | 2871 |
} |
2869 | 2872 |
|
2870 | 2873 |
device_change += disk_array |
... | ... | |
2888 | 2891 |
end |
2889 | 2892 |
|
2890 | 2893 |
spec = RbVmomi::VIM.VirtualMachineConfigSpec(spec_hash) |
2894 |
|
|
2891 | 2895 |
vm.ReconfigVM_Task(:spec => spec).wait_for_completion |
2892 | 2896 |
end |
2893 | 2897 |
|
... | ... | |
2924 | 2928 |
end |
2925 | 2929 |
} |
2926 | 2930 |
|
2927 |
ds = datastores.select{|ds| ds.name == ds_name}[0]
|
|
2931 |
ds = datastores.select{|ds| ds.name == ds_name}[0] |
|
2928 | 2932 |
|
2929 | 2933 |
controller, new_number = find_free_controller(vm) |
2930 | 2934 |
|
... | ... | |
3165 | 3169 |
hid = VIClient::translate_hostname(hostname) |
3166 | 3170 |
connection = VIClient.new(hid) |
3167 | 3171 |
|
3172 |
vmid = vm.config.extraConfig.select do |val| |
|
3173 |
val[:key] == "opennebula.vm.id" |
|
3174 |
end.first.value |
|
3175 |
|
|
3168 | 3176 |
spec = { :deviceChange => [] } |
3169 | 3177 |
|
3170 | 3178 |
disks.each{ |disk| |
3171 |
ds_and_img_name = "[#{disk['DATASTORE']}] #{disk['SOURCE']}" |
|
3172 |
vcenter_disk = vm.config.hardware.device.select { |d| is_disk?(d) && |
|
3179 |
img_name = get_disk_img_path(disk, vmid) |
|
3180 |
ds_and_img_name = "[#{disk['DATASTORE']}] #{img_name}" |
|
3181 |
|
|
3182 |
vcenter_disk = vm.config.hardware.device.select { |d| is_disk?(d) && |
|
3173 | 3183 |
d.backing.respond_to?(:fileName) && |
3174 | 3184 |
d.backing.fileName == ds_and_img_name }[0] |
3175 |
spec[:deviceChange] << { |
|
3185 |
spec[:deviceChange] << {
|
|
3176 | 3186 |
:operation => :remove, |
3177 | 3187 |
:device => vcenter_disk |
3178 | 3188 |
} |
... | ... | |
3180 | 3190 |
|
3181 | 3191 |
vm.ReconfigVM_Task(:spec => spec).wait_for_completion |
3182 | 3192 |
end |
3193 |
|
|
3194 |
|
|
3195 |
############################################################################ |
|
3196 |
# Returns the source path of a disk. It will use the 'SOURCE' path if |
|
3197 |
# persistent and one-#{vm_id}-#{disk_id}.vmdk otherwise |
|
3198 |
# @param disks VM attached disks, either an REXML document, or a hash |
|
3199 |
# @param vmid The VM ID |
|
3200 |
############################################################################ |
|
3201 |
def self.get_disk_img_path(disk, vmid) |
|
3202 |
if disk.respond_to? :elements |
|
3203 |
# It's a REXML::Document, probably coming from self.reconfigure_vm |
|
3204 |
persistent = disk.elements["PERSISTENT"].text == "YES" rescue false |
|
3205 |
|
|
3206 |
if persistent |
|
3207 |
disk.elements["SOURCE"].text |
|
3208 |
else |
|
3209 |
disk_id = disk.elements["DISK_ID"].text |
|
3210 |
"one_#{vmid}_#{disk_id}.vmdk" |
|
3211 |
end |
|
3212 |
else |
|
3213 |
# It's a hash, probably coming from self.detach_attached_disks |
|
3214 |
persistent = disk["PERSISTENT"] == "YES" |
|
3215 |
|
|
3216 |
if persistent |
|
3217 |
disk["SOURCE"] |
|
3218 |
else |
|
3219 |
disk_id = disk["DISK_ID"] |
|
3220 |
"one_#{vmid}_#{disk_id}.vmdk" |
|
3221 |
end |
|
3222 |
end |
|
3223 |
end |
|
3224 |
|
|
3183 | 3225 |
end |
3184 | 3226 |
end |
Also available in: Unified diff