From 020436595ad63e659c8287036b7a86388a3fd479 Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Mon, 28 Oct 2013 17:57:55 -0400 Subject: [PATCH] [vsphere|compute] Added the ability to create and destroy new volumes. --- lib/fog/vsphere/compute.rb | 1 + lib/fog/vsphere/models/compute/server.rb | 4 +- lib/fog/vsphere/models/compute/volume.rb | 40 +++++++++++++++++-- lib/fog/vsphere/models/compute/volumes.rb | 29 ++++++++++---- lib/fog/vsphere/requests/compute/create_vm.rb | 12 ++++-- .../requests/compute/list_vm_volumes.rb | 4 +- .../requests/compute/modify_vm_volume.rb | 26 ++++++++++++ 7 files changed, 99 insertions(+), 17 deletions(-) create mode 100644 lib/fog/vsphere/requests/compute/modify_vm_volume.rb diff --git a/lib/fog/vsphere/compute.rb b/lib/fog/vsphere/compute.rb index 5004667da..bf8f42b22 100644 --- a/lib/fog/vsphere/compute.rb +++ b/lib/fog/vsphere/compute.rb @@ -64,6 +64,7 @@ module Fog request :create_vm request :list_vm_interfaces request :modify_vm_interface + request :modify_vm_volume request :list_vm_volumes request :get_virtual_machine request :vm_reconfig_hardware diff --git a/lib/fog/vsphere/models/compute/server.rb b/lib/fog/vsphere/models/compute/server.rb index 6127cf968..e4c41ffaa 100644 --- a/lib/fog/vsphere/models/compute/server.rb +++ b/lib/fog/vsphere/models/compute/server.rb @@ -201,9 +201,9 @@ module Fog end def volumes - attributes[:volumes] ||= id.nil? ? [] : service.volumes( :vm => self ) + attributes[:volumes] ||= id.nil? ? [] : service.volumes(:server => self) end - + def customvalues attributes[:customvalues] ||= id.nil? ? [] : service.customvalues( :vm => self ) end diff --git a/lib/fog/vsphere/models/compute/volume.rb b/lib/fog/vsphere/models/compute/volume.rb index 42019da66..42c87b451 100644 --- a/lib/fog/vsphere/models/compute/volume.rb +++ b/lib/fog/vsphere/models/compute/volume.rb @@ -10,11 +10,18 @@ module Fog attribute :mode attribute :size attribute :thin + attribute :eager_zero attribute :name attribute :filename attribute :size_gb + attribute :key + attribute :unit_number + attribute :server_id def initialize(attributes={} ) + # Assign server first to prevent race condition with persisted? + self.server_id = attributes.delete(:server_id) + super defaults.merge(attributes) end @@ -30,13 +37,38 @@ module Fog name end - private + def destroy + requires :server_id, :key, :unit_number + + service.destroy_vm_volume(self) + true + end + + def save + raise Fog::Errors::Error.new('Resaving an existing object may create a duplicate') if persisted? + requires :server_id, :size, :datastore + + if unit_number.nil? + self.unit_number = server.volumes.size + end + + service.add_vm_volume(self) + + true + end + + def server + requires :server_id + service.servers.get(server_id) + end + + private def defaults { - :thin=>true, - :name=>"Hard disk", - :mode=>"persistent" + :thin => true, + :name => "Hard disk", + :mode => "persistent" } end end diff --git a/lib/fog/vsphere/models/compute/volumes.rb b/lib/fog/vsphere/models/compute/volumes.rb index c3740dec2..f3f3ae1e4 100644 --- a/lib/fog/vsphere/models/compute/volumes.rb +++ b/lib/fog/vsphere/models/compute/volumes.rb @@ -7,26 +7,41 @@ module Fog class Volumes < Fog::Collection + attribute :server + model Fog::Compute::Vsphere::Volume - attr_accessor :vm - def all(filters = {}) - requires :vm - case vm + requires :server + + case server when Fog::Compute::Vsphere::Server - load service.list_vm_volumes(vm.id) + load service.list_vm_volumes(server.id) when Fog::Compute::Vsphere::Template - load service.list_template_volumes(vm.id) + load service.list_template_volumes(server.id) else raise 'volumes should have vm or template' - end + end + + self.each { |volume| volume.server_id = server.id } + self end def get(id) new service.get_volume(id) end + def new(attributes = {}) + if server + # Default to the root volume datastore if one is not configured. + datastore = ! attributes.has_key?(:datastore) && self.any? ? self.first.datastore : nil + + super({ :server_id => server.id, :datastore => datastore }.merge!(attributes)) + else + super + end + end + end end end diff --git a/lib/fog/vsphere/requests/compute/create_vm.rb b/lib/fog/vsphere/requests/compute/create_vm.rb index 11b8f5621..abc28d696 100644 --- a/lib/fog/vsphere/requests/compute/create_vm.rb +++ b/lib/fog/vsphere/requests/compute/create_vm.rb @@ -92,11 +92,11 @@ module Fog end def create_disk disk, index = 0, operation = :add, controller_key = 1000 - { + payload = { :operation => operation, - :fileOperation => :create, + :fileOperation => operation == :add ? :create : :destroy, :device => RbVmomi::VIM.VirtualDisk( - :key => index, + :key => disk.key || index, :backing => RbVmomi::VIM.VirtualDiskFlatVer2BackingInfo( :fileName => "[#{disk.datastore}]", :diskMode => disk.mode.to_sym, @@ -107,6 +107,12 @@ module Fog :capacityInKB => disk.size ) } + + if operation == :add && disk.thin == false && disk.eager_zero + payload[:device][:backing][:eagerlyScrub] = disk.eager_zero + end + + payload end def extra_config attributes diff --git a/lib/fog/vsphere/requests/compute/list_vm_volumes.rb b/lib/fog/vsphere/requests/compute/list_vm_volumes.rb index 365b84341..699c3a553 100644 --- a/lib/fog/vsphere/requests/compute/list_vm_volumes.rb +++ b/lib/fog/vsphere/requests/compute/list_vm_volumes.rb @@ -36,7 +36,9 @@ module Fog :filename => vol.backing.fileName, :datastore => (vol.backing.datastore.name rescue(nil)), :size => vol.capacityInKB, - :name => vol.deviceInfo.label + :name => vol.deviceInfo.label, + :key => vol.key, + :unit_number => vol.unitNumber } end end diff --git a/lib/fog/vsphere/requests/compute/modify_vm_volume.rb b/lib/fog/vsphere/requests/compute/modify_vm_volume.rb new file mode 100644 index 000000000..7086f3fda --- /dev/null +++ b/lib/fog/vsphere/requests/compute/modify_vm_volume.rb @@ -0,0 +1,26 @@ +module Fog + module Compute + class Vsphere + class Real + + def add_vm_volume(volume) + vm_reconfig_hardware('instance_uuid' => volume.server_id, 'hardware_spec' => {'deviceChange'=>[create_disk(volume, volume.unit_number, :add)]}) + end + + def destroy_vm_volume(volume) + vm_reconfig_hardware('instance_uuid' => volume.server_id, 'hardware_spec' => {'deviceChange'=>[create_disk(volume, volume.unit_number, :remove)]}) + end + end + + class Mock + def add_vm_volume(volume) + true + end + + def destroy_vm_volume(volume) + true + end + end + end + end +end \ No newline at end of file