diff --git a/lib/fog/compute/models/vcloud/server.rb b/lib/fog/compute/models/vcloud/server.rb index 9d879708f..95cbdec9a 100644 --- a/lib/fog/compute/models/vcloud/server.rb +++ b/lib/fog/compute/models/vcloud/server.rb @@ -128,11 +128,14 @@ module Fog if @disk_change == :deleted raise RuntimeError, "Can't add a disk w/o saving changes or reloading" else - @disk_change = :added load_unless_loaded! - virtual_hardware[:Item] << { :ResourceType => '17', - :AddressOnParent => (disk_mess.map { |dm| dm[:AddressOnParent] }.sort.last.to_i + 1).to_s, - :VirtualQuantity => size.to_s } + @disk_change = :added + + @add_disk = { + :'rasd:HostResource' => {:vcloud_capacity => size}, + :'rasd:AddressOnParent' => (disk_mess.map { |dm| dm[:'rasd:AddressOnParent'] }.sort.last.to_i + 1).to_s, + :'rasd:ResourceType' => '17' + } end true end @@ -141,10 +144,10 @@ module Fog if @disk_change == :added raise RuntimeError, "Can't delete a disk w/o saving changes or reloading" else - @disk_change = :deleted load_unless_loaded! unless number == 0 - virtual_hardware[:Item].delete_if { |vh| vh[:ResourceType] == '17' && vh[:AddressOnParent].to_i == number } + @disk_change = :deleted + @remove_disk = number end end true @@ -169,6 +172,18 @@ module Fog memory_mess[:"rasd:VirtualQuantity"] = @update_memory_value.to_s connection.configure_vm_memory(memory_mess) end + if @disk_change == :deleted + data = disk_mess.delete_if do |vh| + vh[:'rasd:ResourceType'] == '17' && + vh[:'rasd:AddressOnParent'].to_s == @remove_disk.to_s + end + connection.configure_vm_disks(vm_href, data) + end + if @disk_change == :added + data = disk_mess + data << @add_disk + connection.configure_vm_disks(vm_href, data) + end #connection.configure_vapp( href, _compose_vapp_data ) end reset_tracking @@ -187,6 +202,14 @@ module Fog end alias :delete :destroy + def vm_href + load_unless_loaded! + #require 'pp' + #pp vm_data + #vm_data[0][:Link].select {|v| v[:rel] == 'edit'}[0][:href] + vm_data.kind_of?(Array)? vm_data[0][:href] : vm_data[:href] + end + private def reset_tracking diff --git a/lib/fog/compute/requests/vcloud/configure_vm.rb b/lib/fog/compute/requests/vcloud/configure_vm.rb new file mode 100644 index 000000000..9c1328a27 --- /dev/null +++ b/lib/fog/compute/requests/vcloud/configure_vm.rb @@ -0,0 +1,247 @@ +# -*- coding: utf-8 -*- +hardware_hash = {:xmlns_vcloud=>"http://www.vmware.com/vcloud/v1", + :vcloud_href=> + "https://vcd01.esx.dev.int.realestate.com.au/api/v1.0/vApp/vm-624535987/virtualHardwareSection/", + :vcloud_type=>"application/vnd.vmware.vcloud.virtualHardwareSection+xml", + :"ovf:Info"=>"Virtual hardware requirements", + :"ovf:System"=> + {:"vssd:ElementName"=>"Virtual Hardware Family", + :"vssd:InstanceID"=>"0", + :"vssd:VirtualSystemIdentifier"=>"centos", + :"vssd:VirtualSystemType"=>"vmx-07"}, + :"ovf:Item"=> + [{:"rasd:Address"=>"00:50:56:01:00:db", + :"rasd:AddressOnParent"=>"0", + :"rasd:AutomaticAllocation"=>"true", + :"rasd:Connection"=>"Gandalf_Dev_OrgNW_to_ExtNW_DirectConnect", + :"rasd:Description"=>"PCNet32 ethernet adapter", + :"rasd:ElementName"=>"Network adapter 0", + :"rasd:InstanceID"=>"1", + :"rasd:ResourceSubType"=>"PCNet32", + :"rasd:ResourceType"=>"10"}, + {:"rasd:Address"=>"0", + :"rasd:Description"=>"SCSI Controller", + :"rasd:ElementName"=>"SCSI Controller 0", + :"rasd:InstanceID"=>"2", + :"rasd:ResourceSubType"=>"lsilogic", + :"rasd:ResourceType"=>"6"}, + {:"rasd:AddressOnParent"=>"0", + :"rasd:Description"=>"Hard disk", + :"rasd:ElementName"=>"Hard disk 1", + :"rasd:HostResource"=> + {:vcloud_capacity=>"8192", + :vcloud_busType=>"6", + :vcloud_busSubType=>"lsilogic"}, + :"rasd:InstanceID"=>"2000", + :"rasd:Parent"=>"2", + :"rasd:ResourceType"=>"17"}, + {:"rasd:Address"=>"0", + :"rasd:Description"=>"IDE Controller", + :"rasd:ElementName"=>"IDE Controller 0", + :"rasd:InstanceID"=>"3", + :"rasd:ResourceType"=>"5"}, + {:"rasd:AddressOnParent"=>"0", + :"rasd:AutomaticAllocation"=>"false", + :"rasd:Description"=>"CD/DVD Drive", + :"rasd:ElementName"=>"CD/DVD Drive 1", + :"rasd:HostResource"=>"", + :"rasd:InstanceID"=>"3000", + :"rasd:Parent"=>"3", + :"rasd:ResourceType"=>"15"}, + {:"rasd:AddressOnParent"=>"0", + :"rasd:AutomaticAllocation"=>"false", + :"rasd:Description"=>"Floppy Drive", + :"rasd:ElementName"=>"Floppy Drive 1", + :"rasd:HostResource"=>"", + :"rasd:InstanceID"=>"8000", + :"rasd:ResourceType"=>"14"}, + {:vcloud_href=> + "https://vcd01.esx.dev.int.realestate.com.au/api/v1.0/vApp/vm-624535987/virtualHardwareSection/cpu", + :vcloud_type=>"application/vnd.vmware.vcloud.rasdItem+xml", + :"rasd:AllocationUnits"=>"hertz * 10^6", + :"rasd:Description"=>"Number of Virtual CPUs", + :"rasd:ElementName"=>"1 virtual CPU(s)", + :"rasd:InstanceID"=>"4", + :"rasd:Reservation"=>"0", + :"rasd:ResourceType"=>"3", + :"rasd:VirtualQuantity"=>"1", + :"rasd:Weight"=>"0", + :Link=> + {:rel=>"edit", + :type=>"application/vnd.vmware.vcloud.rasdItem+xml", + :href=> + "https://vcd01.esx.dev.int.realestate.com.au/api/v1.0/vApp/vm-624535987/virtualHardwareSection/cpu"}}, + {:vcloud_href=> + "https://vcd01.esx.dev.int.realestate.com.au/api/v1.0/vApp/vm-624535987/virtualHardwareSection/memory", + :vcloud_type=>"application/vnd.vmware.vcloud.rasdItem+xml", + :"rasd:AllocationUnits"=>"byte * 2^20", + :"rasd:Description"=>"Memory Size", + :"rasd:ElementName"=>"512 MB of memory", + :"rasd:InstanceID"=>"5", + :"rasd:Reservation"=>"0", + :"rasd:ResourceType"=>"4", + :"rasd:VirtualQuantity"=>"768", + :"rasd:Weight"=>"0", + :Link=> + {:rel=>"edit", + :type=>"application/vnd.vmware.vcloud.rasdItem+xml", + :href=> + "https://vcd01.esx.dev.int.realestate.com.au/api/v1.0/vApp/vm-624535987/virtualHardwareSection/memory"}}], + :Link=> + [{:rel=>"edit", + :type=>"application/vnd.vmware.vcloud.virtualHardwareSection+xml", + :href=> + "https://vcd01.esx.dev.int.realestate.com.au/api/v1.0/vApp/vm-624535987/virtualHardwareSection/"}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.rasdItem+xml", + :href=> + "https://vcd01.esx.dev.int.realestate.com.au/api/v1.0/vApp/vm-624535987/virtualHardwareSection/cpu"}, + {:rel=>"edit", + :type=>"application/vnd.vmware.vcloud.rasdItem+xml", + :href=> + "https://vcd01.esx.dev.int.realestate.com.au/api/v1.0/vApp/vm-624535987/virtualHardwareSection/cpu"}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.rasdItem+xml", + :href=> + "https://vcd01.esx.dev.int.realestate.com.au/api/v1.0/vApp/vm-624535987/virtualHardwareSection/memory"}, + {:rel=>"edit", + :type=>"application/vnd.vmware.vcloud.rasdItem+xml", + :href=> + "https://vcd01.esx.dev.int.realestate.com.au/api/v1.0/vApp/vm-624535987/virtualHardwareSection/memory"}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.rasdItemsList+xml", + :href=> + "https://vcd01.esx.dev.int.realestate.com.au/api/v1.0/vApp/vm-624535987/virtualHardwareSection/disks"}, + {:rel=>"edit", + :type=>"application/vnd.vmware.vcloud.rasdItemsList+xml", + :href=> + "https://vcd01.esx.dev.int.realestate.com.au/api/v1.0/vApp/vm-624535987/virtualHardwareSection/disks"}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.rasdItemsList+xml", + :href=> + "https://vcd01.esx.dev.int.realestate.com.au/api/v1.0/vApp/vm-624535987/virtualHardwareSection/media"}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.rasdItemsList+xml", + :href=> + "https://vcd01.esx.dev.int.realestate.com.au/api/v1.0/vApp/vm-624535987/virtualHardwareSection/networkCards"}, + {:rel=>"edit", + :type=>"application/vnd.vmware.vcloud.rasdItemsList+xml", + :href=> + "https://vcd01.esx.dev.int.realestate.com.au/api/v1.0/vApp/vm-624535987/virtualHardwareSection/networkCards"}]} + + +module Fog + module Vcloud + class Compute + module Shared + private + + def validate_vm_data(vm_data) + valid_opts = [:name, :cpus, :memory, :disks] + unless valid_opts.all? { |opt| vm_data.keys.include?(opt) } + raise ArgumentError.new("Required vm data missing: #{(valid_opts - vm_data.keys).map(&:inspect).join(", ")}") + end + end + end + + class Real + include Shared + + def generate_configure_vm_request(vm_data) + xmlns = 'http://schemas.dmtf.org/ovf/envelope/1' + xmlns_vcloud = 'http://www.vmware.com/vcloud/v1' + xmlns_rasd = 'http://schemas.dmtf.org/wbem/wscim/1/cim‐schema/2/CIM_ResourceAllocationSettingData' + xmlns_vssd = 'http://schemas.dmtf.org/wbem/wscim/1/cim‐schema/2/CIM_VirtualSystemSettingData' + + builder = Builder::XmlMarkup.new(:target=>STDOUT, :indent=>2) # TODO - remove params + builder.VirtualHardwareSection( + :"vcloud:href" => vm_data[:"vcloud_href"], + :"vcloud:type" => vm_data[:"vcloud_type"], + :name => vm_data[:name], + :status => 2, + :size => 0, + :xmlns => xmlns, + :"xmlns:vcloud" => xmlns_vcloud, + :"xmlns:rasd" => xmlns_rasd, + :"xmlns:vssd" => xmlns_vssd) { + #builder.VirtualHardwareSection(:xmlns => 'http://schemas.dmtf.org/ovf/envelope/1') { + + builder.Info(vm_data[:"ovf:Info"]) + if system = vm_data[:"ovf:System"] + builder.System { + builder.ElementName(system[:"vssd:ElementName"], :xmlns => xmlns_vssd) if system[:"vssd:ElementName"] + builder.InstanceID(system[:"vssd:InstanceID"], :xmlns => xmlns_vssd) if system[:"vssd:InstanceID"] + builder.VirtualSystemIdentifier(system[:"vssd:VirtualSystemIdentifier"], :xmlns => xmlns_vssd) if system[:"vssd:VirtualSystemIdentifier"] + builder.VirtualSystemType(system[:"vssd:VirtualSystemType"], :xmlns => xmlns_vssd) if system[:"vssd:VirtualSystemType"] + } + end + + vm_data[:'ovf:Item'].each do |oi| + builder.Item { + builder.Address(oi[:'rasd:Address'], :xmlns => xmlns_rasd) if oi[:'rasd:Address'] + builder.AddressOnParent(oi[:'rasd:AddressOnParent'], :xmlns => xmlns_rasd) if oi[:'rasd:AddressOnParent'] + builder.AutomaticAllocation(oi[:'rasd:AutomaticAllocation'], :xmlns => xmlns_rasd) if oi[:'rasd:AutomaticAllocation'] + builder.Connection(oi[:'rasd:Connection'], :xmlns => xmlns_rasd) if oi[:'rasd:Connection'] + builder.Description(oi[:'rasd:Description'], :xmlns => xmlns_rasd) if oi[:'rasd:Description'] + builder.ElementName(oi[:'rasd:ElementName'], :xmlns => xmlns_rasd) if oi[:'rasd:ElementName'] + builder.InstanceID(oi[:'rasd:InstanceID'], :xmlns => xmlns_rasd) if oi[:'rasd:InstanceID'] + builder.ResourceSubType(oi[:'rasd:ResourceSubType'], :xmlns => xmlns_rasd) if oi[:'rasd:ResourceSubType'] + builder.ResourceType(oi[:'rasd:ResourceType'], :xmlns => xmlns_rasd) if oi[:'rasd:ResourceType'] + if hr = oi[:'rasd:HostResource'] + attrs = {} + attrs[] + end + } + end + + + + # builder.Item(:xmlns => 'http://schemas.dmtf.org/ovf/envelope/1') { + # #builder.Item { + # builder.InstanceID(1, :xmlns => 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData') + # builder.ResourceType(3, :xmlns => 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData') + # builder.VirtualQuantity(vm_data[:cpus], :xmlns => 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData') + # } + # builder.Item(:xmlns => 'http://schemas.dmtf.org/ovf/envelope/1') { + # #builder.Item { + # builder.InstanceID(2, :xmlns => 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData') + # builder.ResourceType(4, :xmlns => 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData') + # builder.VirtualQuantity(vm_data[:memory], :xmlns => 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData') + # } + # vm_data[:disks].each do |disk_data| + # #builder.Item(:xmlns => 'http://schemas.dmtf.org/ovf/envelope/1') { + # builder.Item { + # builder.AddressOnParent(disk_data[:number], :xmlns => 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData') + # builder.HostResource(disk_data[:resource], :xmlns => 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData') + # builder.InstanceID(9, :xmlns => 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData') + # builder.ResourceType(17, :xmlns => 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData') + # builder.VirtualQuantity(disk_data[:size], :xmlns => 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData') + # } + # end + + } + end + + def configure_vm(vm_uri, vm_data) + validate_vm_data(vm_data) + + request( + :body => generate_configure_vm_request(vm_uri, vm_data), + :expects => 202, + :headers => {'Content-Type' => 'application/vnd.vmware.vcloud.vm+xml' }, + :method => 'PUT', + :uri => vm_uri, + :parse => true + ) + end + + end + end + end +end + +if $0 == __FILE__ + require 'builder' + i = Fog::Vcloud::Compute::Real.new + puts i.generate_configure_vm_request(hardware_hash) +end diff --git a/lib/fog/compute/requests/vcloud/configure_vm_disks.rb b/lib/fog/compute/requests/vcloud/configure_vm_disks.rb new file mode 100644 index 000000000..b61713bc0 --- /dev/null +++ b/lib/fog/compute/requests/vcloud/configure_vm_disks.rb @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- + +# +# +# +# 0 +# SCSI Controller +# SCSI Controller 0 +# 2 +# lsilogic +# 6 +# +# +# 0 +# Hard disk +# Hard disk 1 +# +# 2000 +# 2 +# 17 +# +# +# 0 +# IDE Controller +# IDE Controller 0 +# 3 +# 5 +# +# + + + + + +module Fog + module Vcloud + class Compute + class Real + + def generate_configure_vm_disks_request(href, disk_data) + xmlns = { + "xmlns:rasd" => "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData", + "xmlns" => "http://www.vmware.com/vcloud/v1" + } + # Get the XML from the API, parse it. + xml = Nokogiri::XML(request( :uri => href).body) + + #xml.root['name'] = vapp_data[:name] + + #disks + real_disks = xml.xpath("//rasd:ResourceType[ .='17']/..", xmlns) + real_disk_numbers = real_disks.map { |disk| disk.at('.//rasd:AddressOnParent', xmlns).content } + disk_numbers = disk_data.map { |vdisk| vdisk[:"rasd:AddressOnParent"].to_s } + + if disk_data.length < real_disks.length + #Assume we're removing a disk + remove_disk_numbers = real_disk_numbers - disk_numbers + remove_disk_numbers.each do |number| + if result = xml.at("//rasd:ResourceType[ .='17']/../rasd:AddressOnParent[.='#{number}']/..", xmlns) + result.remove + end + end + elsif disk_data.length > real_disks.length + add_disk_numbers = disk_numbers - real_disk_numbers + + add_disk_numbers.each do |number| + new_disk = real_disks.first.dup + new_disk.at('.//rasd:AddressOnParent', xmlns).content = number.to_i #-1 + new_disk.at('.//rasd:HostResource', xmlns)["vcloud:capacity"] = disk_data.detect { |disk| disk[:'rasd:AddressOnParent'].to_s == number.to_s }[:'rasd:HostResource'][:vcloud_capacity].to_s + # nokogiri bug? shouldn't need to add this explicitly. + new_disk.at('.//rasd:HostResource', xmlns)["xmlns:vcloud"] = xmlns['xmlns'] + new_disk.at('.//rasd:InstanceID', xmlns).content = (2000 + number.to_i).to_s + new_disk.at('.//rasd:ElementName', xmlns).content = "Hard disk #{number.to_i + 1}" + real_disks.first.parent << new_disk + end + + end + xml.to_s + end + + def configure_vm_disks(vm_href, disk_data) + disk_href = vm_href + '/virtualHardwareSection/disks' + + body = generate_configure_vm_disks_request(disk_href, disk_data) + + request( + :body => body, + :expects => 202, + :headers => {'Content-Type' => 'application/vnd.vmware.vcloud.rasdItem+xml' }, + :method => 'PUT', + :uri => disk_href, + :parse => true + ) + end + + end + + end + end +end diff --git a/lib/fog/compute/requests/vcloud/get_vm_disks.rb b/lib/fog/compute/requests/vcloud/get_vm_disks.rb new file mode 100644 index 000000000..9b56f186f --- /dev/null +++ b/lib/fog/compute/requests/vcloud/get_vm_disks.rb @@ -0,0 +1,16 @@ +module Fog + module Vcloud + class Compute + + class Real + def get_vm_disks(href) + request( + :expects => 200, + :uri => href, + :parse => true#false#true + ) + end + end + end + end +end diff --git a/lib/fog/compute/vcloud.rb b/lib/fog/compute/vcloud.rb index 150f6cac8..286f3d967 100644 --- a/lib/fog/compute/vcloud.rb +++ b/lib/fog/compute/vcloud.rb @@ -90,6 +90,7 @@ module Fog request :configure_network_ip request :configure_vapp request :configure_vm_memory + request :configure_vm_disks request :delete_vapp request :get_catalog request :get_catalog_item @@ -103,6 +104,7 @@ module Fog request :get_task_list request :get_vapp request :get_vapp_template + request :get_vm_disks request :get_vm_memory request :get_vdc request :instantiate_vapp_template diff --git a/tests/compute/models/vcloud/servers_tests.rb b/tests/compute/models/vcloud/servers_tests.rb index 2d28d5c22..be9e922ae 100644 --- a/tests/compute/models/vcloud/servers_tests.rb +++ b/tests/compute/models/vcloud/servers_tests.rb @@ -41,6 +41,40 @@ Shindo.tests("Vcloud::Compute | servers", ['vcloud']) do @svr.reload.memory[:amount] end + tests("#svr.add_disk(4096)").returns([2, "4096"]) do + pending if Fog.mocking? + raise 'Server template already has two disks' if @svr.disks.size == 2 + @svr.wait_for { ready? } + @svr.add_disk(4096) + @svr.save + @svr.wait_for { ready? } + # Can take a little while for the VM to know it has different ram, and not tied to a task.. + (1..20).each do |i| + break if @svr.reload.disks.size == 2 + sleep 1 + end + [ + @svr.disks.size, + @svr.disks[1][:resource][:vcloud_capacity] + ] + end + + tests("#svr.delete_disk(1)").returns(1) do + pending if Fog.mocking? + raise "Server doesn't have two disks - did previous step fail? " if @svr.disks.size != 2 + @svr.wait_for { ready? } + sleep 5 # otherwise complains about being busy + @svr.delete_disk 1 + @svr.save + @svr.wait_for { ready? } + # Can take a little while for the VM to know it has different ram, and not tied to a task.. + (1..20).each do |i| + break if @svr.reload.disks.size == 1 + sleep 1 + end + @svr.disks.size + end + tests("#svr.destroy").raises(Excon::Errors::Forbidden) do pending if Fog.mocking? @svr.destroy diff --git a/tests/compute/requests/vcloud/disk_configure_tests.rb b/tests/compute/requests/vcloud/disk_configure_tests.rb new file mode 100644 index 000000000..6c17251e5 --- /dev/null +++ b/tests/compute/requests/vcloud/disk_configure_tests.rb @@ -0,0 +1,107 @@ +require 'spec' +require 'spec/mocks' + +Shindo.tests("Vcloud::Compute | disk_requests", ['vcloud']) do + + @xmlns = { + "xmlns" => "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData", + "xmlns:vcloud" => "http://www.vmware.com/vcloud/v1" + } + + def disk_hash + [{:"rasd:AddressOnParent"=>"0", + :"rasd:Description"=>"Hard disk", + :"rasd:ElementName"=>"Hard disk 1", + :"rasd:HostResource"=> + {:vcloud_capacity=>"8192", + :vcloud_busType=>"6", + :vcloud_busSubType=>"lsilogic"}, + :"rasd:InstanceID"=>"2000", + :"rasd:Parent"=>"2", + :"rasd:ResourceType"=>"17"}] + end + + def nokogiri_load + Nokogiri::XML(MockDiskResponse.new.body) + end + + class MockDiskResponse + def body + < + + + 0 + SCSI Controller + SCSI Controller 0 + 2 + lsilogic + 6 + + + 0 + Hard disk + Hard disk 1 + + 2000 + 2 + 17 + + + 0 + IDE Controller + IDE Controller 0 + 3 + 5 + + +EOF + end + end + + Vcloud[:compute].stub!(:request).and_return(MockDiskResponse.new) + + tests("Call to generate config returns string").returns(true) do + Vcloud[:compute].generate_configure_vm_disks_request('http://blah', disk_hash).kind_of? String + end + + tests("Call to generate config with no changes returns input data").returns(true) do + Nokogiri::XML(Vcloud[:compute].generate_configure_vm_disks_request('http://blah', disk_hash)).to_s == + Nokogiri::XML(MockDiskResponse.new.body).to_s + end + + tests("Call to generate config with no disks removes disk").returns(true) do + xml = Vcloud[:compute].generate_configure_vm_disks_request('http://blah', []) + ng = Nokogiri::XML(xml) + # Should have 2 controllers, but no disks. + ng.xpath("//xmlns:ResourceType", @xmlns).size == 2 && + ng.xpath("//xmlns:ResourceType[ .='17']", @xmlns).size == 0 + end + + tests("Call to generate config adding a disk").returns(['4096', true, true]) do + disks = disk_hash + disks << { + :"rasd:AddressOnParent"=>"1", + :"rasd:Description"=>"Hard disk", + :"rasd:ElementName"=>"Hard disk 2", + :"rasd:HostResource"=> + {:vcloud_capacity=>"4096", + :vcloud_busType=>"6", + :vcloud_busSubType=>"lsilogic"}, + :"rasd:InstanceID"=>"2000", + :"rasd:Parent"=>"2", + :"rasd:ResourceType"=>"17"} + xml = Vcloud[:compute].generate_configure_vm_disks_request('http://blah', disks) + ng = Nokogiri::XML(xml) + [ + # should be 4096mb + ng.at("//xmlns:ResourceType[ .='17']/../xmlns:AddressOnParent[.='-1']/../xmlns:HostResource", @xmlns)["capacity"], + # Should have 2 controllers, and 2 disks + ng.xpath("//xmlns:ResourceType", @xmlns).size == 4, + ng.xpath("//xmlns:ResourceType[ .='17']", @xmlns).size == 2 + ] + end + + + Vcloud[:compute].unstub!(:request) +end