1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-01-11 05:17:41 +03:00

F #5207: vCenter disks can be resized when VM in poweroff

This commit is contained in:
mcabrerizo 2017-06-28 14:43:38 +02:00
parent a5edba2a36
commit 00b7d8607a
3 changed files with 184 additions and 1 deletions

View File

@ -1031,6 +1031,7 @@ TM_VCENTER_FILES="src/tm_mad/vcenter/clone \
src/tm_mad/vcenter/cpds \
src/tm_mad/vcenter/premigrate \
src/tm_mad/vcenter/postmigrate \
src/tm_mad/vcenter/resize \
src/tm_mad/vcenter/snap_create \
src/tm_mad/vcenter/snap_create_live \
src/tm_mad/vcenter/snap_delete \

View File

@ -1 +0,0 @@
../common/not_supported.sh

89
src/tm_mad/vcenter/resize Executable file
View File

@ -0,0 +1,89 @@
#!/usr/bin/env ruby
# ---------------------------------------------------------------------------- #
# Copyright 2002-2017, OpenNebula Project, OpenNebula Systems #
# #
# 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. #
# ---------------------------------------------------------------------------- #
# resize image size vmid
ONE_LOCATION = ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION)
if !ONE_LOCATION
RUBY_LIB_LOCATION = "/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION)
else
RUBY_LIB_LOCATION = ONE_LOCATION + "/lib/ruby" if !defined?(RUBY_LIB_LOCATION)
end
$: << RUBY_LIB_LOCATION
$: << File.dirname(__FILE__)
require 'vcenter_driver'
src = ARGV[0]
new_size = ARGV[1]
vmid = ARGV[2]
check_valid src,"src"
check_valid new_size,"new_size"
check_valid vmid,"vmid"
disk_id = src.split(".")[-1]
hostname, = src.split ":"
# Get host ID
host = VCenterDriver::VIHelper.find_by_name(OpenNebula::HostPool, hostname)
host_id = host['ID']
# Get OpenNebula VM
one_vm = VCenterDriver::VIHelper.one_item(OpenNebula::VirtualMachine, vmid)
vm_ref = one_vm['DEPLOY_ID']
begin
# This action is only possible when VM in ACTIVE / DISK_RESIZE_POWEROFF
if one_vm['LCM_STATE'].to_i != 63
raise "'disk-resize' operation is not supported for vCenter running VMs."
end
vi_client = VCenterDriver::VIClient.new_from_host(host_id)
vm = VCenterDriver::VirtualMachine.new_from_ref(vm_ref, vi_client)
# Cannot resize if VM has snapshots
if vm.has_snapshots?
raise "'disk-resize' operation is not supported for VMs with system snapshots."
end
# Get disk element to be resized
disk = one_vm.retrieve_xmlelements("TEMPLATE/DISK[DISK_ID=#{disk_id}]").first
if disk["ORIGINAL_SIZE"].to_i >= new_size.to_i
raise "'disk-resize' cannot decrease the disk's size"
end
# Resize operation
if !disk["OPENNEBULA_MANAGED"] || disk["OPENNEBULA_MANAGED"].downcase != "no" &&
vm.resize_managed_disk(disk,new_size)
else
vm.resize_unmanaged_disk(disk, new_size)
end
rescue Exception => e
message = "Error resizing disk #{disk_id} for VM #{one_vm["NAME"]} "\
"Reason: #{e.message}\n#{e.backtrace}"
STDERR.puts error_message(message)
exit -1
ensure
vi_client.close_connection if vi_client
end

View File

@ -2111,6 +2111,100 @@ class VirtualMachine < Template
end
end
def resize_unmanaged_disk(disk, new_size)
resize_hash = {}
disks = []
found = false
unmanaged_keys = get_unmanaged_keys
vc_disks = get_vcenter_disks
vc_disks.each do |vcenter_disk|
if unmanaged_keys.key?("opennebula.disk.#{disk["DISK_ID"]}")
device_key = unmanaged_keys["opennebula.disk.#{disk["DISK_ID"]}"].to_i
if device_key == vcenter_disk[:key].to_i
if disk["SIZE"].to_i <= disk["ORIGINAL_SIZE"].to_i
raise "Disk size cannot be shrinked."
end
# Edit capacity setting new size in KB
d = vcenter_disk[:device]
d.capacityInKB = disk["SIZE"].to_i * 1024
disks << { :device => d, :operation => :edit }
found = true
break
end
end
end
raise "Unmanaged disk could not be found to apply resize operation." if !found
if !disks.empty?
resize_hash[:deviceChange] = disks
@item.ReconfigVM_Task(:spec => resize_hash).wait_for_completion
else
raise "Device was not found after attaching it to VM in poweroff."
end
end
def resize_managed_disk(disk, new_size)
resize_hash = {}
unmanaged_keys = get_unmanaged_keys
vc_disks = get_vcenter_disks
# Get vcenter device to be detached and remove if found
device = disk_attached_to_vm(disk, unmanaged_keys, vc_disks)
# If the disk is being attached in poweroff, reconfigure the VM
if !device
spec_hash = {}
device_change = []
# Get an array with disk paths in OpenNebula's vm template
disks_in_onevm_vector = disks_in_onevm(unmanaged_keys, vc_disks)
device_change_ds, device_change_spod, device_change_spod_ids = device_attach_disks(disks_in_onevm_vector, vc_disks)
device_change += device_change_ds
# Create volatile disks in StorageDRS if any
if !device_change_spod.empty?
spec_hash[:extraConfig] = create_storagedrs_disks(device_change_spod, device_change_spod_ids)
end
# Common reconfigure task
spec_hash[:deviceChange] = device_change
spec = RbVmomi::VIM.VirtualMachineConfigSpec(spec_hash)
@item.ReconfigVM_Task(:spec => spec).wait_for_completion
# Check again if device has now been attached
unmanaged_keys = get_unmanaged_keys
vc_disks = get_vcenter_disks
device = disk_attached_to_vm(disk, unmanaged_keys, vc_disks)
if !device
raise "Device was not found after attaching it to VM in poweroff."
end
end
# Resize disk now that we know that it's part of the VM
if device
vcenter_disk = device[:device]
vcenter_disk.capacityInKB = new_size.to_i * 1024
resize_hash[:deviceChange] = [{
:operation => :edit,
:device => vcenter_disk
}]
@item.ReconfigVM_Task(:spec => resize_hash).wait_for_completion
end
end
def has_snapshots?
self['rootSnapshot'] && !self['rootSnapshot'].empty?
end