foreman/app/models/compute_resources/foreman/model/vmware.rb @ acfbc458
d4e8938a | Ohad Levy | require 'fog_extensions/vsphere/mini_servers'
|
|
617ee75f | Amos Benari | require 'foreman/exception'
|
|
d4e8938a | Ohad Levy | ||
4213d2be | Ohad Levy | module Foreman::Model
|
|
class Vmware < ComputeResource
|
|||
f2c78d4a | Joseph Magen | validates :user, :password, :server, :datacenter, :presence => true
|
|
3da587a3 | Ohad Levy | before_create :update_public_key
|
|
4213d2be | Ohad Levy | ||
def self.model_name
|
|||
ComputeResource.model_name
|
|||
end
|
|||
dd42df0a | Ohad Levy | def capabilities
|
|
1c9af75a | Ohad Levy | [:build]
|
|
dd42df0a | Ohad Levy | end
|
|
d4e8938a | Ohad Levy | def vms(opts = {})
|
|
if opts[:eager_loading] == true
|
|||
super()
|
|||
else
|
|||
#VMWare server loading is very slow
|
|||
#not using FOG models directly to save the time
|
|||
#and minimize the amount of time required (as we don't require all attributes by default when listing)
|
|||
FogExtensions::Vsphere::MiniServers.new(client, datacenter)
|
|||
end
|
|||
end
|
|||
1c9af75a | Ohad Levy | def provided_attributes
|
|
super.merge({ :mac => :mac })
|
|||
end
|
|||
def max_cpu_count (cluster = nil)
|
|||
return 8 unless cluster
|
|||
cluster.num_cpu_cores
|
|||
4213d2be | Ohad Levy | end
|
|
def max_memory
|
|||
16*1024*1024*1024
|
|||
end
|
|||
def datacenters
|
|||
1c9af75a | Ohad Levy | client.datacenters.all
|
|
end
|
|||
def clusters
|
|||
dc.clusters
|
|||
end
|
|||
def folders
|
|||
dc.vm_folders.sort_by{|f| f.path}
|
|||
end
|
|||
def networks
|
|||
dc.networks.all(:accessible => true)
|
|||
end
|
|||
c75be21b | Martin Matuska | def nictypes
|
|
{
|
|||
29769a4e | Martin Matuska | "VirtualE1000" => "E1000",
|
|
f2c78d4a | Joseph Magen | "VirtualVmxnet3" => "VMXNET 3"
|
|
c75be21b | Martin Matuska | }
|
|
f2c78d4a | Joseph Magen | end
|
|
c75be21b | Martin Matuska | ||
41ee835f | Martin Matuska | def scsi_controller_types
|
|
{
|
|||
"VirtualLsiLogicController" => "LSI Logic Parallel",
|
|||
"VirtualLsiLogicSASController" => "LSI Logic SAS",
|
|||
"VirtualBusLogicController" => "Bus Logic Parallel",
|
|||
"ParaVirtualSCSIController" => "VMware Paravirtual"
|
|||
}
|
|||
end
|
|||
def scsi_controller_default_type
|
|||
"VirtualLsiLogicController"
|
|||
end
|
|||
1c9af75a | Ohad Levy | def datastores
|
|
dc.datastores.all(:accessible => true)
|
|||
4213d2be | Ohad Levy | end
|
|
617ee75f | Amos Benari | def test_connection options = {}
|
|
4213d2be | Ohad Levy | super
|
|
95be0963 | Amos Benari | if errors[:server].empty? and errors[:user].empty? and errors[:password].empty?
|
|
617ee75f | Amos Benari | update_public_key options
|
|
95be0963 | Amos Benari | datacenters
|
|
end
|
|||
4213d2be | Ohad Levy | rescue => e
|
|
errors[:base] << e.message
|
|||
end
|
|||
1c9af75a | Ohad Levy | def new_vm attr={ }
|
|
95be0963 | Amos Benari | test_connection
|
|
return unless errors.empty?
|
|||
1c9af75a | Ohad Levy | opts = vm_instance_defaults.merge(attr.to_hash).symbolize_keys
|
|
# convert rails nested_attributes into a plain hash
|
|||
[:interfaces, :volumes].each do |collection|
|
|||
nested_attrs = opts.delete("#{collection}_attributes".to_sym)
|
|||
opts[collection] = nested_attributes_for(collection, nested_attrs) if nested_attrs
|
|||
end
|
|||
opts.reject! { |k, v| v.nil? }
|
|||
client.servers.new opts
|
|||
end
|
|||
def create_vm args = { }
|
|||
29769a4e | Martin Matuska | dc_networks = networks
|
|
c75be21b | Martin Matuska | args["interfaces_attributes"].each do |key, interface|
|
|
29769a4e | Martin Matuska | # Convert network id into name
|
|
net = dc_networks.find { |n| n.id == interface["network"] }
|
|||
raise "Unknown Network ID: #{interface["network"]}" if net.nil?
|
|||
interface["network"] = net.name
|
|||
c75be21b | Martin Matuska | end
|
|
1c9af75a | Ohad Levy | ||
c75be21b | Martin Matuska | vm = new_vm(args)
|
|
1c9af75a | Ohad Levy | vm.save
|
|
rescue Fog::Errors::Error => e
|
|||
logger.debug e.backtrace
|
|||
errors.add(:base, e.to_s)
|
|||
false
|
|||
end
|
|||
4213d2be | Ohad Levy | def server
|
|
url
|
|||
end
|
|||
def server= value
|
|||
self.url = value
|
|||
end
|
|||
1c9af75a | Ohad Levy | def datacenter
|
|
uuid
|
|||
end
|
|||
def datacenter= value
|
|||
self.uuid = value
|
|||
end
|
|||
4213d2be | Ohad Levy | def console uuid
|
|
vm = find_vm_by_uuid(uuid)
|
|||
raise "VM is not running!" unless vm.ready?
|
|||
#TOOD port, password
|
|||
#NOTE this requires the following port to be open on your ESXi FW
|
|||
1c9af75a | Ohad Levy | values = { :port => unused_vnc_port(vm.hypervisor), :password => random_password, :enabled => true }
|
|
4213d2be | Ohad Levy | vm.config_vnc(values)
|
|
8ffd9aee | Ohad Levy | WsProxy.start(:host => vm.hypervisor, :host_port => values[:port], :password => values[:password]).merge(:type => 'vnc')
|
|
4213d2be | Ohad Levy | end
|
|
1c9af75a | Ohad Levy | def new_interface attr = { }
|
|
client.interfaces.new attr
|
|||
end
|
|||
def new_volume attr = { }
|
|||
client.volumes.new attr.merge(:size_gb => 10)
|
|||
end
|
|||
617ee75f | Amos Benari | def pubkey_hash
|
|
attrs[:pubkey_hash]
|
|||
end
|
|||
def pubkey_hash= key
|
|||
attrs[:pubkey_hash] = key
|
|||
end
|
|||
805358df | Jason Montleon | def associated_host(vm)
|
|
acfbc458 | Marek Hulan | Host.authorized(:view_hosts, Host).where(:mac => vm.mac).first
|
|
805358df | Jason Montleon | end
|
|
2ebd2f22 | Joseph Magen | def provider_friendly_name
|
|
"VMWare"
|
|||
end
|
|||
4213d2be | Ohad Levy | private
|
|
1c9af75a | Ohad Levy | def dc
|
|
client.datacenters.get(datacenter)
|
|||
end
|
|||
617ee75f | Amos Benari | def update_public_key options ={}
|
|
return unless pubkey_hash.blank? || options[:force]
|
|||
3da587a3 | Ohad Levy | client
|
|
617ee75f | Amos Benari | rescue Foreman::FingerprintException => e
|
|
self.pubkey_hash = e.fingerprint
|
|||
3da587a3 | Ohad Levy | end
|
|
4213d2be | Ohad Levy | def client
|
|
@client ||= ::Fog::Compute.new(
|
|||
:provider => "vsphere",
|
|||
:vsphere_username => user,
|
|||
:vsphere_password => password,
|
|||
3da587a3 | Ohad Levy | :vsphere_server => server,
|
|
:vsphere_expected_pubkey_hash => pubkey_hash
|
|||
4213d2be | Ohad Levy | )
|
|
617ee75f | Amos Benari | rescue => e
|
|
if e.message =~ /The remote system presented a public key with hash (\w+) but we're expecting a hash of/
|
|||
raise Foreman::FingerprintException.new(
|
|||
N_("The remote system presented a public key with hash %s but we're expecting a different hash. If you are sure the remote system is authentic, go to the compute resource edit page, press the 'Test Connection' or 'Load Datacenters' button and submit"), $1)
|
|||
else
|
|||
raise e
|
|||
end
|
|||
4213d2be | Ohad Levy | end
|
|
def unused_vnc_port ip
|
|||
10.times do
|
|||
1c9af75a | Ohad Levy | port = 5901 + rand(64)
|
|
4213d2be | Ohad Levy | unused = (TCPSocket.connect(ip, port).close rescue true)
|
|
return port if unused
|
|||
end
|
|||
raise "no unused port found"
|
|||
end
|
|||
1c9af75a | Ohad Levy | def vm_instance_defaults
|
|
557b8543 | Joseph Mitchell Magen | super.merge(
|
|
1c9af75a | Ohad Levy | :memory_mb => 768,
|
|
:interfaces => [new_interface],
|
|||
:volumes => [new_volume],
|
|||
41ee835f | Martin Matuska | :scsi_controller => { :type => scsi_controller_default_type },
|
|
557b8543 | Joseph Mitchell Magen | :datacenter => datacenter
|
|
)
|
|||
1c9af75a | Ohad Levy | end
|
|
4213d2be | Ohad Levy | end
|
|
end
|