diff --git a/lib/fog/aws/storage.rb b/lib/fog/aws/storage.rb index 576fed37f..5d511d1f7 100644 --- a/lib/fog/aws/storage.rb +++ b/lib/fog/aws/storage.rb @@ -255,6 +255,7 @@ module Fog @scheme = endpoint.scheme else options[:region] ||= 'us-east-1' + @region = options[:region] @host = options[:host] || case options[:region] when 'us-east-1' 's3.amazonaws.com' diff --git a/lib/fog/vsphere/compute.rb b/lib/fog/vsphere/compute.rb index 92c3b630b..f75bab8b8 100644 --- a/lib/fog/vsphere/compute.rb +++ b/lib/fog/vsphere/compute.rb @@ -27,6 +27,7 @@ module Fog request :vm_reconfig_hardware request :vm_reconfig_memory request :vm_reconfig_cpus + request :vm_config_vnc module Shared @@ -49,6 +50,8 @@ module Fog :tools_state => 'guest.toolsStatus', :tools_version => 'guest.toolsVersionStatus', :is_a_template => 'config.template', + :memory_mb => 'config.hardware.memoryMB', + :cpus => 'config.hardware.numCPU', } # Utility method to convert a VMware managed object into an attribute hash. @@ -65,8 +68,8 @@ module Fog # API. The hypervisor name and mac_addresses attributes may not be available # so we need catch any exceptions thrown during lookup and set them to nil. # - # The use of the "tap" method here is a convience, it allows us to update the - # hash object without expliclty returning the hash at the end of the method. + # The use of the "tap" method here is a convenience, it allows us to update the + # hash object without explicitly returning the hash at the end of the method. Hash[ATTR_TO_PROP.map { |k,v| [k.to_s, props[v]] }].tap do |attrs| attrs['id'] ||= vm_mob_ref._ref attrs['mo_ref'] = vm_mob_ref._ref diff --git a/lib/fog/vsphere/models/compute/server.rb b/lib/fog/vsphere/models/compute/server.rb index fd0aeac5b..ddef26e21 100644 --- a/lib/fog/vsphere/models/compute/server.rb +++ b/lib/fog/vsphere/models/compute/server.rb @@ -34,26 +34,31 @@ module Fog attribute :connection_state attribute :mo_ref attribute :path + attribute :memory_mb + attribute :cpus def vm_reconfig_memory(options = {}) requires :instance_uuid, :memory connection.vm_reconfig_memory('instance_uuid' => instance_uuid, 'memory' => memory) end + def vm_reconfig_cpus(options = {}) requires :instance_uuid, :cpus connection.vm_reconfig_cpus('instance_uuid' => instance_uuid, 'cpus' => cpus) end + def vm_reconfig_hardware(options = {}) requires :instance_uuid, :hardware_spec connection.vm_reconfig_hardware('instance_uuid' => instance_uuid, 'hardware_spec' => hardware_spec) end + def start(options = {}) requires :instance_uuid connection.vm_power_on('instance_uuid' => instance_uuid) end def stop(options = {}) - options = { :force => false }.merge(options) + options = { :force => !tools_installed? }.merge(options) requires :instance_uuid connection.vm_power_off('instance_uuid' => instance_uuid, 'force' => options[:force]) end @@ -82,6 +87,7 @@ module Fog new_vm.connection = self.connection new_vm end + def clone(options = {}) requires :name, :path # Convert symbols to strings @@ -100,6 +106,30 @@ module Fog new_vm end + def ready? + power_state == "poweredOn" + end + + def tools_installed? + tools_state != "toolsNotInstalled" + end + + # defines VNC attributes on the hypervisor + def config_vnc(options = {}) + requires :instance_uuid + connection.vm_config_vnc(options.merge('instance_uuid' => instance_uuid)) + end + + # returns a hash of VNC attributes required for connection + def vnc + requires :instance_uuid + connection.vm_get_vnc(instance_uuid) + end + + def memory + memory_mb * 1024 * 1024 + end + end end diff --git a/lib/fog/vsphere/requests/compute/vm_config_vnc.rb b/lib/fog/vsphere/requests/compute/vm_config_vnc.rb new file mode 100644 index 000000000..8be88395c --- /dev/null +++ b/lib/fog/vsphere/requests/compute/vm_config_vnc.rb @@ -0,0 +1,47 @@ +module Fog + module Compute + class Vsphere + class Real + def vm_config_vnc(options = { }) + raise ArgumentError, "instance_uuid is a required parameter" unless options.has_key? 'instance_uuid' + + search_filter = { :uuid => options['instance_uuid'], 'vmSearch' => true, 'instanceUuid' => true } + vm_mob_ref = @connection.searchIndex.FindAllByUuid(search_filter).first + task = vm_mob_ref.ReconfigVM_Task(:spec => { + :extraConfig => [ + { :key => 'RemoteDisplay.vnc.enabled', :value => options[:enabled] ? 'true' : 'false' }, + { :key => 'RemoteDisplay.vnc.password', :value => options[:password].to_s }, + { :key => 'RemoteDisplay.vnc.port', :value => options[:port].to_s || '5910' } + ] + }) + task.wait_for_completion + { 'task_state' => task.info.state } + end + + # return a hash of VNC attributes required to view the console + def vm_get_vnc uuid + + search_filter = { :uuid => uuid, 'vmSearch' => true, 'instanceUuid' => true } + vm = @connection.searchIndex.FindAllByUuid(search_filter).first + Hash[vm.config.extraConfig.map do |config| + if config.key =~ /^RemoteDisplay\.vnc\.(\w+)$/ + [$1.to_sym, config.value] + end + end.compact] + end + + end + + class Mock + def vm_config_vnc(options = { }) + raise ArgumentError, "instance_uuid is a required parameter" unless options.has_key? 'instance_uuid' + { 'task_state' => 'success' } + end + + def vm_get_vnc uuid + {:password => 'secret', :port => '5900', :enabled => 'true'} + end + end + end + end +end diff --git a/tests/vsphere/requests/compute/vm_config_vnc_tests.rb b/tests/vsphere/requests/compute/vm_config_vnc_tests.rb new file mode 100644 index 000000000..9350d069d --- /dev/null +++ b/tests/vsphere/requests/compute/vm_config_vnc_tests.rb @@ -0,0 +1,19 @@ +Shindo.tests('Fog::Compute[:vsphere] | vm_config_vnc request', ['vsphere']) do + + compute = Fog::Compute[:vsphere] + + reconfig_target = '50137835-88a1-436e-768e-9b2677076e67' + vnc_spec = {:port => '5900', :password => 'ssaaa', :enabled => 'true'} + + tests('The response should') do + response = compute.vm_config_vnc('instance_uuid' => reconfig_target).merge(vnc_spec) + test('be a kind of Hash') { response.kind_of? Hash } + test('should have a task_state key') { response.has_key? 'task_state' } + end + + tests('VNC attrs response should') do + response = compute.vm_get_vnc(reconfig_target) + test('be a kind of Hash') { response.kind_of? Hash } + test('should have a port key') { response.has_key? :port } + end +end