2011-08-30 15:25:28 -04:00
require 'digest/sha2'
2011-08-29 23:04:04 -04:00
module Fog
module Compute
class Vsphere < Fog :: Service
requires :vsphere_username , :vsphere_password , :vsphere_server
recognizes :vsphere_port , :vsphere_path , :vsphere_ns
2011-08-30 15:25:28 -04:00
recognizes :vsphere_rev , :vsphere_ssl , :vsphere_expected_pubkey_hash
2011-08-29 23:04:04 -04:00
2011-09-01 18:10:57 -04:00
model_path 'fog/vsphere/models/compute'
model :server
collection :servers
2011-08-30 16:44:31 -04:00
request_path 'fog/vsphere/requests/compute'
request :current_time
2011-09-10 16:27:52 -04:00
request :find_vm_by_ref
2011-09-01 18:10:57 -04:00
request :list_virtual_machines
2011-09-02 14:04:24 -04:00
request :vm_power_off
request :vm_power_on
request :vm_reboot
2011-09-06 19:46:42 -04:00
request :vm_clone
2011-09-06 19:41:37 -04:00
request :vm_destroy
2011-09-10 16:27:52 -04:00
module Shared
attr_reader :vsphere_is_vcenter
attr_reader :vsphere_rev
# Utility method to convert a VMware managed object into an attribute hash.
# This should only really be necessary for the real class.
# This method is expected to be called by the request methods
# in order to massage VMware Managed Object References into Attribute Hashes.
def convert_vm_mob_ref_to_attr_hash ( vm_mob_ref )
return nil unless vm_mob_ref
# A cloning VM doesn't have a configuration yet. Unfortuantely we just get
# a RunTime exception.
begin
is_ready = vm_mob_ref . config ? true : false
rescue RuntimeError
is_ready = nil
end
{
'id' = > is_ready ? vm_mob_ref . config . instanceUuid : vm_mob_ref . _ref ,
'mo_ref' = > vm_mob_ref . _ref ,
'name' = > vm_mob_ref . name ,
'uuid' = > is_ready ? vm_mob_ref . config . uuid : nil ,
'instance_uuid' = > is_ready ? vm_mob_ref . config . instanceUuid : nil ,
'hostname' = > vm_mob_ref . summary . guest . hostName ,
'operatingsystem' = > vm_mob_ref . summary . guest . guestFullName ,
'ipaddress' = > vm_mob_ref . summary . guest . ipAddress ,
'power_state' = > vm_mob_ref . runtime . powerState ,
'connection_state' = > vm_mob_ref . runtime . connectionState ,
'hypervisor' = > vm_mob_ref . runtime . host ? vm_mob_ref . runtime . host . name : nil ,
'tools_state' = > vm_mob_ref . summary . guest . toolsStatus ,
'tools_version' = > vm_mob_ref . summary . guest . toolsVersionStatus ,
'mac_addresses' = > is_ready ? vm_mob_ref . macs : nil ,
'is_a_template' = > is_ready ? vm_mob_ref . config . template : nil
}
end
end
2011-08-30 16:44:31 -04:00
2011-08-29 23:04:04 -04:00
class Mock
2011-09-10 16:27:52 -04:00
include Shared
2011-08-29 23:04:04 -04:00
def initialize ( options = { } )
2011-08-30 17:55:21 -04:00
require 'mocha'
@vsphere_username = options [ :vsphere_username ]
2011-09-10 16:27:52 -04:00
@vsphere_password = 'REDACTED'
2011-08-30 17:55:21 -04:00
@vsphere_server = options [ :vsphere_server ]
@vsphere_expected_pubkey_hash = options [ :vsphere_expected_pubkey_hash ]
2011-09-10 16:27:52 -04:00
@vsphere_is_vcenter = true
@vsphere_rev = '4.0'
2011-08-30 17:55:21 -04:00
@connection = Mocha :: Mock . new
2011-08-29 23:04:04 -04:00
end
end
class Real
2011-09-10 16:27:52 -04:00
include Shared
2011-08-30 15:25:28 -04:00
2011-08-29 23:04:04 -04:00
def initialize ( options = { } )
require 'rbvmomi'
@vsphere_username = options [ :vsphere_username ]
@vsphere_password = options [ :vsphere_password ]
@vsphere_server = options [ :vsphere_server ]
@vsphere_port = options [ :vsphere_port ] || 443
@vsphere_path = options [ :vsphere_path ] || '/sdk'
@vsphere_ns = options [ :vsphere_ns ] || 'urn:vim25'
@vsphere_rev = options [ :vsphere_rev ] || '4.0'
@vsphere_ssl = options [ :vsphere_ssl ] || true
2011-08-30 15:25:28 -04:00
@vsphere_expected_pubkey_hash = options [ :vsphere_expected_pubkey_hash ]
2011-08-29 23:04:04 -04:00
@vsphere_must_reauthenticate = false
2011-08-30 15:25:28 -04:00
@connection = nil
# This is a state variable to allow digest validation of the SSL cert
bad_cert = false
loop do
begin
@connection = RbVmomi :: VIM . new :host = > @vsphere_server ,
:port = > @vsphere_port ,
:path = > @vsphere_path ,
:ns = > @vsphere_ns ,
:rev = > @vsphere_rev ,
:ssl = > @vsphere_ssl ,
:insecure = > bad_cert
break
rescue OpenSSL :: SSL :: SSLError
raise if bad_cert
bad_cert = true
end
end
if bad_cert then
validate_ssl_connection
end
2011-08-29 23:04:04 -04:00
# Negotiate the API revision
if not options [ :vsphere_rev ]
rev = @connection . serviceContent . about . apiVersion
@connection . rev = [ rev , ENV [ 'FOG_VSPHERE_REV' ] || '4.1' ] . min
end
@vsphere_is_vcenter = @connection . serviceContent . about . apiType == " VirtualCenter "
authenticate
end
private
def authenticate
begin
@connection . serviceContent . sessionManager . Login :userName = > @vsphere_username ,
:password = > @vsphere_password
rescue RbVmomi :: VIM :: InvalidLogin = > e
raise Fog :: Vsphere :: Errors :: ServiceError , e . message
end
end
2011-08-30 15:25:28 -04:00
# Verify a SSL certificate based on the hashed public key
def validate_ssl_connection
pubkey = @connection . http . peer_cert . public_key
pubkey_hash = Digest :: SHA2 . hexdigest ( pubkey . to_s )
expected_pubkey_hash = @vsphere_expected_pubkey_hash
if pubkey_hash != expected_pubkey_hash then
raise Fog :: Vsphere :: Errors :: SecurityError , " The remote system presented a public key with hash #{ pubkey_hash } but we're expecting a hash of #{ expected_pubkey_hash || '<unset>' } . If you are sure the remote system is authentic set vsphere_expected_pubkey_hash: <the hash printed in this message> in ~/.fog "
end
end
2011-08-29 23:04:04 -04:00
end
end
end
end