1
0
Fork 0
mirror of https://github.com/fog/fog.git synced 2022-11-09 13:51:43 -05:00
fog--fog/lib/fog/vcloud/models/compute/server.rb
2013-01-07 21:01:23 +00:00

305 lines
8.9 KiB
Ruby

require 'fog/vcloud/models/compute/helpers/status'
module Fog
module Vcloud
class Compute
class Server < Fog::Vcloud::Model
include Fog::Vcloud::Compute::Helpers::Status
identity :href, :aliases => :Href
attribute :links, :aliases => :Link, :type => :array
ignore_attributes :xmlns, :xmlns_i, :xmlns_xsi, :xmlns_xsd
attribute :type
attribute :name
attribute :status
attribute :deployed, :type => :boolean
attribute :description, :aliases => :Description
attribute :vapp_scoped_local_id, :aliases => :VAppScopedLocalId
attribute :network_connections, :aliases => :NetworkConnectionSection, :squash => :NetworkConnection
attribute :virtual_hardware, :aliases => :'ovf:VirtualHardwareSection', :squash => :'ovf:Item'
attribute :guest_customization, :aliases => :GuestCustomizationSection
attribute :operating_system, :aliases => :'ovf:OperatingSystemSection'
attribute :tasks, :aliases => :Tasks, :type => :array
has_up :vapp
def computer_name
load_unless_loaded!
self.guest_customization[:ComputerName]
end
def os_desc
load_unless_loaded!
self.operating_system[:'ovf:Description']
end
def os_type
load_unless_loaded!
self.operating_system[:vmw_osType]
end
def ip_addresses
load_unless_loaded!
[self.network_connections].flatten.collect{|n| n[:IpAddress] }
end
def ready?
reload_status # always ensure we have the correct status
running_tasks = self.tasks && self.tasks.flatten.any? {|ti| ti.kind_of?(Hash) && ti[:status] == 'running' }
status != '0' && !running_tasks # 0 is provisioning, and no running tasks
end
def power_on
power_operation( :power_on => :powerOn )
end
def power_off
power_operation( :power_off => :powerOff )
end
def shutdown
power_operation( :power_shutdown => :shutdown )
end
def power_reset
power_operation( :power_reset => :reset )
end
# This is the real power-off operation
def undeploy
service.undeploy href
end
def graceful_restart
requires :href
shutdown
wait_for { off? }
power_on
end
def name=(new_name)
attributes[:name] = new_name
@changed = true
end
def password
guest_customization[:AdminPassword]
end
def password=(password)
return if password.nil? or password.size == 0
@changed = true
@update_password = password
end
def cpus
if cpu_mess
{ :count => cpu_mess[:"rasd:VirtualQuantity"].to_i,
:units => cpu_mess[:"rasd:AllocationUnits"] }
end
end
def cpus=(qty)
return if qty.nil? or qty.size == 0
@changed = true
@update_cpu_value = qty
qty
end
def memory
if memory_mess
{ :amount => memory_mess[:"rasd:VirtualQuantity"].to_i,
:units => memory_mess[:"rasd:AllocationUnits"] }
end
end
def memory=(amount)
return if amount.nil? or amount.size == 0
@changed = true
@update_memory_value = amount
amount
end
def disks
disk_mess.map do |dm|
{ :number => dm[:"rasd:AddressOnParent"].to_i, :size => dm[:"rasd:HostResource"][:vcloud_capacity].to_i, :resource => dm[:"rasd:HostResource"], :disk_data => dm }
end
end
def add_disk(size)
if @disk_change == :deleted
raise RuntimeError, "Can't add a disk w/o saving changes or reloading"
else
load_unless_loaded!
@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
def delete_disk(number)
if @disk_change == :added
raise RuntimeError, "Can't delete a disk w/o saving changes or reloading"
else
load_unless_loaded!
unless number == 0
@disk_change = :deleted
@remove_disk = number
end
end
true
end
def description=(description)
@description_changed = true unless attributes[:description] == description || attributes[:description] == nil
attributes[:description] = description
end
def name=(name)
@name_changed = true unless attributes[:name] == name || attributes[:name] == nil
attributes[:name] = name
end
def reload
reset_tracking
super
end
def save
unless persisted?
#Lame ...
raise RuntimeError, "Should not be here"
else
if on?
if @changed
raise RuntimeError, "Can't save cpu, name or memory changes while the VM is on."
end
end
if @update_password
guest_customization[:AdminPassword] = @update_password.to_s
service.configure_vm_password(guest_customization)
wait_for { ready? }
end
if @update_cpu_value
cpu_mess[:"rasd:VirtualQuantity"] = @update_cpu_value.to_s
service.configure_vm_cpus(cpu_mess)
wait_for { ready? }
end
if @update_memory_value
memory_mess[:"rasd:VirtualQuantity"] = @update_memory_value.to_s
service.configure_vm_memory(memory_mess)
wait_for { ready? }
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
service.configure_vm_disks(self.href, data)
wait_for { ready? }
end
if @disk_change == :added
data = disk_mess
data << @add_disk
service.configure_vm_disks(self.href, data)
wait_for { ready? }
end
if @name_changed || @description_changed
edit_uri = links.select {|i| i[:rel] == 'edit'}
edit_uri = edit_uri.kind_of?(Array) ? edit_uri.flatten[0][:href] : edit_uri[:href]
service.configure_vm_name_description(edit_uri, self.name, self.description)
wait_for { ready? }
end
end
reset_tracking
true
end
def destroy
if on?
undeploy
wait_for { off? }
end
wait_for { off? } # be sure..
wait_for { ready? } # be doubly sure..
sleep 2 # API lies. need to give it some time to be happy.
service.delete_vapp(href).body[:status] == "running"
end
alias :delete :destroy
private
def reset_tracking
@disk_change = false
@changed = false
@update_password = nil
@update_cpu_value = nil
@update_memory_value = nil
@name_changed = false
@description_changed = nil
end
def _compose_vapp_data
{ :name => name,
:cpus => cpus[:count],
:memory => memory[:amount],
:disks => disks
}
end
def memory_mess
load_unless_loaded!
if virtual_hardware
virtual_hardware.detect { |item| item[:"rasd:ResourceType"] == "4" }
end
end
def cpu_mess
load_unless_loaded!
if virtual_hardware
virtual_hardware.detect { |item| item[:"rasd:ResourceType"] == "3" }
end
end
def disk_mess
load_unless_loaded!
if virtual_hardware
virtual_hardware.select { |item| item[:"rasd:ResourceType"] == "17" }
else
[]
end
end
def power_operation(op)
requires :href
begin
service.send(op.keys.first, href + "/power/action/#{op.values.first}" )
rescue Excon::Errors::InternalServerError => e
#Frankly we shouldn't get here ...
raise e unless e.to_s =~ /because it is already powered o(n|ff)/
end
true
end
def reload_status
server = service.get_server(href)
self.status = server.status
self.tasks = server.tasks
end
end
end
end
end