1
0
Fork 0
mirror of https://github.com/fog/fog.git synced 2022-11-09 13:51:43 -05:00

* [xenserver|compute] initial release

This commit is contained in:
Sergio Rubio 2012-04-02 13:25:03 +02:00
parent e27c195dd6
commit 3131e7b9fb
71 changed files with 2415 additions and 0 deletions

View file

@ -82,4 +82,5 @@ require 'fog/bin/virtual_box'
require 'fog/bin/vmfusion'
require 'fog/bin/vsphere'
require 'fog/bin/voxel'
require 'fog/bin/xenserver'
require 'fog/bin/zerigo'

31
lib/fog/bin/xenserver.rb Normal file
View file

@ -0,0 +1,31 @@
class XenServer < Fog::Bin
class << self
def class_for(key)
case key
when :compute
Fog::Compute::XenServer
else
raise ArgumentError, "Unrecognized service: #{key}"
end
end
def [](service)
@@connections ||= Hash.new do |hash, key|
hash[key] = case key
when :compute
Fog::Logger.warning("XenServer[:compute] is not recommended, use Compute[:xenserver] for portability")
Fog::Compute.new(:provider => 'XenServer')
else
raise ArgumentError, "Unrecognized service: #{key.inspect}"
end
end
@@connections[service]
end
def services
Fog::XenServer.services
end
end
end

View file

@ -85,6 +85,9 @@ module Fog
when :vsphere
require 'fog/vsphere/compute'
Fog::Compute::Vsphere.new(attributes)
when :xenserver
require 'fog/xenserver/compute'
Fog::Compute::XenServer.new(attributes)
else
raise ArgumentError.new("#{provider} is not a recognized compute provider")
end

View file

@ -27,4 +27,5 @@ require 'fog/virtual_box'
require 'fog/vmfusion'
require 'fog/vsphere'
require 'fog/voxel'
require 'fog/xenserver'
require 'fog/zerigo'

52
lib/fog/xenserver.rb Normal file
View file

@ -0,0 +1,52 @@
module Fog
module XenServer
extend Fog::Provider
service(:compute, 'xenserver/compute', 'Compute')
class Connection
require 'xmlrpc/client'
def initialize(host)
@factory = XMLRPC::Client.new(host, '/')
@factory.set_parser(XMLRPC::XMLParser::REXMLStreamParser.new)
end
def authenticate( username, password )
begin
response = @factory.call('session.login_with_password', username, password )
raise Fog::XenServer::InvalidLogin unless response["Status"] =~ /Success/
end
@credentials = response["Value"]
end
def request(options, *params)
begin
parser = options.delete(:parser)
method = options.delete(:method)
if params.empty?
response = @factory.call(method, @credentials)
else
if params.length.eql?(1) and params.first.is_a?(Hash)
response = @factory.call(method, @credentials, params.first)
else
response = eval("@factory.call('#{method}', '#{@credentials}', #{params.map {|p| p.is_a?(String) ? "'#{p}'" : p}.join(',')})")
end
end
#puts "RESPONSE: #{response}"
if parser
parser.parse( response["Value"] )
response = parser.response
end
response
end
end
end
end
end

View file

@ -0,0 +1,124 @@
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'xenserver'))
require 'fog/compute'
module Fog
module Compute
class XenServer < Fog::Service
require 'fog/xenserver/utilities'
require 'fog/xenserver/parser'
requires :xenserver_username
requires :xenserver_password
requires :xenserver_url
recognizes :xenserver_defaults
model_path 'fog/xenserver/models/compute'
model :server
collection :servers
model :host
collection :hosts
collection :vifs
model :vif
collection :storage_repositories
model :storage_repository
collection :pools
model :pool
collection :vbds
model :vbd
collection :vdis
model :vdi
collection :networks
model :network
collection :pifs
model :pif
collection :pbds
model :pbd
request_path 'fog/xenserver/requests/compute'
request :create_server
request :create_vif
request :create_vm
request :destroy_server
request :destroy_vbd
request :destroy_vdi
request :shutdown_server
request :get_hosts
request :get_network
request :get_networks
request :get_storage_repository
request :get_storage_repositories
request :get_vifs
request :get_vms
request :get_vm
request :start_vm
request :start_server
request :get_pool
request :get_pools
request :get_record
request :get_records
request :set_affinity
request :reboot_server
class Real
attr_accessor :default_template
def initialize(options={})
@host = options[:xenserver_url]
@username = options[:xenserver_username]
@password = options[:xenserver_password]
@defaults = options[:xenserver_defaults] || {}
@connection = Fog::XenServer::Connection.new(@host)
@connection.authenticate(@username, @password)
end
def reload
@connection.authenticate(@username, @password)
end
def default_template=(name)
@defaults[:template] = name
end
def default_template
return nil if @defaults[:template].nil?
data = get_vm( @defaults[:template] )
return nil if data[:reference].nil?
servers.get data[:reference]
end
def default_network
Fog::XenServer::Network.new( get_network( @defaults[:network] ) ) if @defaults[:network]
end
end
class Mock
def self.data
@data ||= Hash.new do |hash, key|
hash[key] = {}
end
end
def self.reset_data(keys=data.keys)
for key in [*keys]
data.delete(key)
end
end
def initialize(options={})
@host = options[:xenserver_pool_master]
@username = options[:xenserver_username]
@password = options[:xenserver_password]
@connection = Fog::Connection.new(@host)
@connection.authenticate(@username, @password)
end
end
end
end
end

View file

@ -0,0 +1,46 @@
require 'fog/core/model'
module Fog
module Compute
class XenServer
class Host < Fog::Model
# API Reference here:
# http://docs.vmd.citrix.com/XenServer/5.6.0/1.0/en_gb/api/?c=host
identity :reference
attribute :name, :aliases => :name_label
attribute :uuid
attribute :address
attribute :allowed_operations
attribute :enabled
attribute :hostname
attribute :metrics
attribute :name_description
attribute :other_config
attribute :__pbds, :aliases => :PBDs
attribute :__pifs, :aliases => :PIFs
attribute :__resident_vms, :aliases => :resident_VMs
def pifs
__pifs.collect { |pif| connection.pifs.get pif }
end
def pbds
__pbds.collect { |pbd| connection.pbds.get pbd }
end
def resident_servers
__resident_vms.collect { |ref| connection.servers.get ref }
end
def resident_vms
resident_servers
end
end
end
end
end

View file

@ -0,0 +1,29 @@
require 'fog/core/collection'
require 'fog/xenserver/models/compute/host'
module Fog
module Compute
class XenServer
class Hosts < Fog::Collection
model Fog::Compute::XenServer::Host
def all
data = connection.get_hosts
load(data)
end
def get( host_ref )
if host_ref && host = connection.get_record( host_ref, 'host' )
new(host)
else
nil
end
end
end
end
end
end

View file

@ -0,0 +1,58 @@
require 'fog/core/model'
module Fog
module Compute
class XenServer
class Network < Fog::Model
# API Reference here:
# http://docs.vmd.citrix.com/XenServer/5.6.0/1.0/en_gb/api/?c=network
identity :reference
attribute :uuid
attribute :__vifs, :aliases => :VIFs
attribute :tags
attribute :mtu, :aliases => :MTU
attribute :bridge
attribute :description, :aliases => :name_description
attribute :name, :aliases => :name_label
attribute :other_config
attribute :__pifs, :aliases => :PIFs
attribute :allowed_operations
attribute :current_operations
attribute :blobs
def refresh
data = connection.get_record( reference, 'network' )
merge_attributes( data )
true
end
#
# Return the list of network related PIFs
#
def pifs
p = []
__pifs.each do |pif|
p << connection.pifs.get(pif)
end
p
end
#
# Return the list of network related VIFs
#
def vifs
v = []
__vifs.each do |vif|
v << connection.vifs.get(vif)
end
v
end
end
end
end
end

View file

@ -0,0 +1,33 @@
require 'fog/core/collection'
require 'fog/xenserver/models/compute/network'
module Fog
module Compute
class XenServer
class Networks < Fog::Collection
model Fog::Compute::XenServer::Network
def initialize(attributes)
super
end
def all(options = {})
data = connection.get_records 'network'
load(data)
end
def get( ref )
if ref && obj = connection.get_record( ref, 'network' )
new(obj)
end
rescue Fog::XenServer::NotFound
nil
end
end
end
end
end

View file

@ -0,0 +1,33 @@
require 'fog/core/model'
module Fog
module Compute
class XenServer
class PBD < Fog::Model
# API Reference here:
# http://docs.vmd.citrix.com/XenServer/5.6.0/1.0/en_gb/api/?c=PBD
identity :reference
attribute :uuid
attribute :__host, :aliases => :host
attribute :__sr, :aliases => :SR
def sr
connection.storage_repositories.get __sr
end
def storage_repository
sr
end
def host
connection.hosts.get __host
end
end
end
end
end

View file

@ -0,0 +1,33 @@
require 'fog/core/collection'
require 'fog/xenserver/models/compute/pbd'
module Fog
module Compute
class XenServer
class Pbds < Fog::Collection
model Fog::Compute::XenServer::PBD
def initialize(attributes)
super
end
def all(options = {})
data = connection.get_records 'PBD'
load(data)
end
def get( ref )
if ref && obj = connection.get_record( ref, 'PBD' )
new(obj)
else
nil
end
end
end
end
end
end

View file

@ -0,0 +1,46 @@
require 'fog/core/model'
module Fog
module Compute
class XenServer
class PIF < Fog::Model
# API Reference here:
# http://docs.vmd.citrix.com/XenServer/5.6.0/1.0/en_gb/api/?c=PIF
identity :reference
attribute :uuid
attribute :physical
attribute :mac, :aliases => :MAC
attribute :currently_attached
attribute :device
attribute :device_name
attribute :metrics
attribute :dns, :aliases => :DNS
attribute :gateway
attribute :ip, :aliases => :IP
attribute :ip_configuration_mode
attribute :mtu, :aliases => :MTU
attribute :__network, :aliases => :network
attribute :netmask
attribute :status_code
attribute :status_detail
attribute :management
attribute :vlan, :aliases => :VLAN
attribute :other_config
attribute :__host, :aliases => :host
def network
connection.networks.get __network
end
def host
connection.hosts.get __host
end
end
end
end
end

View file

@ -0,0 +1,33 @@
require 'fog/core/collection'
require 'fog/xenserver/models/compute/pif'
module Fog
module Compute
class XenServer
class Pifs < Fog::Collection
model Fog::Compute::XenServer::PIF
def initialize(attributes)
super
end
def all(options = {})
data = connection.get_records 'PIF'
load(data)
end
def get( ref )
if ref && obj = connection.get_record( ref, 'PIF' )
new(obj)
end
rescue Fog::XenServer::NotFound
nil
end
end
end
end
end

View file

@ -0,0 +1,34 @@
require 'fog/core/model'
module Fog
module Compute
class XenServer
class Pool < Fog::Model
# API Reference here:
# http://docs.vmd.citrix.com/XenServer/5.6.0/1.0/en_gb/api/?c=pool
identity :reference
attribute :name_label
attribute :uuid
attribute :__default_sr, :aliases => :default_SR
def initialize(attributes={})
@uuid ||= 0
super
end
def default_sr
connection.get_storage_repository_by_ref __default_sr
end
def default_storage_repository
connection.get_storage_repository_by_ref __default_sr
end
end
end
end
end

View file

@ -0,0 +1,33 @@
require 'fog/core/collection'
require 'fog/xenserver/models/compute/pool'
module Fog
module Compute
class XenServer
class Pools < Fog::Collection
model Fog::Compute::XenServer::Pool
def initialize(attributes)
super
end
def all(options = {})
data = connection.get_pools
load(data)
end
def get( pool_ref )
if pool_ref && pool = connection.get_pool_by_ref( pool_ref )
new(pool)
end
rescue Fog::XenServer::NotFound
nil
end
end
end
end
end

View file

@ -0,0 +1,157 @@
require 'fog/compute/models/server'
module Fog
module Compute
class XenServer
class Server < Fog::Compute::Server
# API Reference here:
# http://docs.vmd.citrix.com/XenServer/5.6.0/1.0/en_gb/api/?c=VM
identity :reference
attribute :uuid
attribute :name, :aliases => :name_label
attribute :affinity
attribute :allowed_operations
attribute :consoles
attribute :domarch
attribute :domid
attribute :guest_metrics
attribute :is_a_snapshot
attribute :is_a_template
attribute :is_control_domain
attribute :memory_dynamic_max
attribute :memory_dynamic_min
attribute :memory_static_max
attribute :memory_static_min
attribute :memory_target
attribute :metrics
attribute :name_description
attribute :other_config
attribute :power_state
attribute :pv_args, :aliases => :PV_args
attribute :resident_on
# Virtual Block Devices
attribute :__vbds, :aliases => :VBDs
# Virtual CPUs
attribute :vcpus_at_startup, :aliases => :VCPUs_at_startup
attribute :vcpus_max, :aliases => :VCPUs_max
# Virtual Interfaces (NIC)
attribute :__vifs, :aliases => :VIFs
attribute :template_name
#ignore_attributes :HVM_boot_params, :HVM_boot_policy, :HVM_shadow_multiplier, :PCI_bus, :PV_bootloader,
# :PV_bootloader_args, :PV_kernel, :PV_legacy_args, :PV_ramdisk, :VCPUs_params, :VTPMs,
# :actions_after_crash, :actions_after_reboot, :actions_after_shutdown, :blobs,
# :blocked_operations, :crash_dumps, :current_operations, :ha_always_run, :ha_restart_priority,
# :last_boot_CPU_flags, :last_booted_record, :platform, :recommendations, :snapshot_time,
# :snapshots, :snapshot_of, :suspend_VDI, :tags, :transportable_snapshot_id, :user_version,
# :xenstore_data, :memory_overhead, :children, :bios_strings, :parent, :snapshot_metadata,
# :snapshot_info
def initialize(attributes={})
super
end
def vbds
__vbds.collect {|vbd| connection.vbds.get vbd }
end
def destroy
stop('hard') if running?
vbds.each do |vbd|
connection.destroy_vdi( vbd.vdi.reference ) if vbd.type == "Disk"
end
connection.destroy_server( reference )
true
end
def refresh
data = connection.get_record( reference, 'VM' )
merge_attributes( data )
true
end
def vifs
networks
end
# associations
def networks
__vifs.collect {|vif| Fog::Compute::XenServer::VIF.new(connection.get_record( vif, 'VIF' ))}
end
def running_on
Fog::Compute::XenServer::Host.new(connection.get_record( resident_on, 'host' ))
end
def home_hypervisor
connection.hosts.first
end
def mac_address
networks.first.MAC
end
def running?
power_state =~ /Running/
end
def halted?
power_state =~ /Halted/
end
# operations
def start
return false if running?
connection.start_server( reference )
true
end
def save(params = {})
requires :name
new_vm = connection.create_server( name, template_name, nil)
merge_attributes(new_vm.attributes)
true
end
def reboot(stype = 'clean')
connection.reboot_server(reference, stype)
true
end
def hard_reboot
reboot 'hard'
end
def clean_reboot
reboot 'clean'
end
def stop(stype = 'clean')
return false if !running?
connection.shutdown_server( reference, stype )
wait_for { !running? }
true
end
def hard_shutdown
stop 'hard'
end
def clean_shutdown
stop 'clean'
end
# def snapshot
# requires :reference, :name_label
# data = connection.snapshot_server(@reference, @name_label)
# merge_attributes(data.body)
# true
# end
end
end
end
end

View file

@ -0,0 +1,57 @@
require 'fog/core/collection'
require 'fog/xenserver/models/compute/server'
module Fog
module Compute
class XenServer
class Servers < Fog::Collection
model Fog::Compute::XenServer::Server
def initialize(attributes)
super
end
def all(options = {})
data = connection.get_vms
# Exclude templates
data.delete_if { |vm|
vm[:is_a_template] and (!options[:include_templates] and !options[:include_custom_templates])
}
data.delete_if { |vm|
# VM is a custom template
if vm[:is_a_template] and vm[:allowed_operations].include?("destroy")
!options[:include_custom_templates]
end
}
data.delete_if { |vm|
# VM is a built-in template
if vm[:is_a_template] and !vm[:allowed_operations].include?("destroy")
!options[:include_templates]
end
}
data.delete_if { |vm| vm[:is_control_domain] }
data.delete_if { |vm| vm[:is_a_snapshot] and !options[:include_snapshots] }
data.delete_if { |vm| options[:name_matches] and (vm[:name_label] !~ /#{Regexp.escape(options[:name_matches])}/i ) }
data.delete_if { |vm| options[:name_equals] and (vm[:name_label] != options[:name_equals] ) }
load(data)
end
def get_by_name( name )
all(:name_equals => name).first
end
def get( vm_ref )
if vm_ref && vm = connection.get_vm_by_ref( vm_ref )
new(vm)
end
rescue Fog::XenServer::NotFound
nil
end
end
end
end
end

View file

@ -0,0 +1,31 @@
require 'fog/core/collection'
require 'fog/xenserver/models/compute/storage_repository'
module Fog
module Compute
class XenServer
class StorageRepositories < Fog::Collection
model Fog::Compute::XenServer::StorageRepository
def all
data = connection.get_storage_repositories
#data.delete_if {|sr| sr[:shared].eql?(false)}
#data.delete_if {|sr| sr[:content_type].eql?('iso')}
load(data)
end
def get( sr_ref )
if sr_ref && sr = connection.get_record( sr_ref, 'SR' )
new(sr)
else
nil
end
end
end
end
end
end

View file

@ -0,0 +1,36 @@
require 'fog/core/model'
module Fog
module Compute
class XenServer
class StorageRepository < Fog::Model
# API Reference here:
# http://docs.vmd.citrix.com/XenServer/5.6.0/1.0/en_gb/api/?c=SR
identity :reference
attribute :name_label
attribute :uuid
attribute :allowed_operations
attribute :content_type
attribute :name_description
attribute :other_config
attribute :PBDs
attribute :shared
attribute :type
attribute :VDIs
ignore_attributes :blobs, :current_operations, :physical_size, :physical_utilisation, :sm_config, :tags,
:virtual_allocation
def initialize(attributes={})
@uuid ||= 0
super
end
end
end
end
end

View file

@ -0,0 +1,39 @@
require 'fog/core/model'
module Fog
module Compute
class XenServer
class VBD < Fog::Model
# API Reference here:
# http://docs.vmd.citrix.com/XenServer/5.6.0/1.0/en_gb/api/?c=VBD
identity :reference
attribute :uuid
attribute :currently_attached
attribute :reserved
attribute :__vdi, :aliases => :VDI
attribute :vm, :aliases => :VM
attribute :device
attribute :status_detail
attribute :type
attribute :userdevice
#ignore_attributes :current_operations, :qos_supported_algorithms, :qos_algorithm_params, :qos_algorithm_type, :other_config,
# :runtime_properties
def initialize(attributes={})
super
end
def vdi
#Fog::Compute::XenServer::VDI.new(connection.get_record( __vdi, 'VDI' ))
connection.vdis.get __vdi
end
end
end
end
end

View file

@ -0,0 +1,34 @@
require 'fog/core/collection'
require 'fog/xenserver/models/compute/vbd'
module Fog
module Compute
class XenServer
class Vbds < Fog::Collection
model Fog::Compute::XenServer::VBD
def initialize(attributes)
super
end
def all(options = {})
data = connection.get_records 'VBD'
#data.delete_if { |vm| vm[:is_a_template] and !options[:include_templates] }
load(data)
end
def get( vbd_ref )
if vbd_ref && vbd = connection.get_record( vbd_ref, 'VBD' )
new(vbd)
end
rescue Fog::XenServer::NotFound
nil
end
end
end
end
end

View file

@ -0,0 +1,33 @@
require 'fog/core/model'
module Fog
module Compute
class XenServer
class VDI < Fog::Model
# API Reference here:
# http://docs.vmd.citrix.com/XenServer/5.6.0/1.0/en_gb/api/?c=VDI
identity :reference
attribute :uuid
attribute :is_a_snapshot
attribute :name, :aliases => :name_label
attribute :description, :aliases => :name_description
attribute :__parent, :aliases => :parent
attribute :virtual_size, :aliases => :parent
attribute :__vbds, :aliases => :VBDs
attribute :__sr, :aliases => :SR
attribute :sharable
attribute :readonly
def initialize(attributes={})
@uuid ||= 0
super
end
end
end
end
end

View file

@ -0,0 +1,34 @@
require 'fog/core/collection'
require 'fog/xenserver/models/compute/vdi'
module Fog
module Compute
class XenServer
class Vdis < Fog::Collection
model Fog::Compute::XenServer::VDI
def initialize(attributes)
super
end
def all(options = {})
data = connection.get_records 'VDI'
#data.delete_if { |vm| vm[:is_a_template] and !options[:include_templates] }
load(data)
end
def get( vdi_ref )
if vdi_ref && vdi = connection.get_record( vdi_ref, 'VDI' )
new(vdi)
end
rescue Fog::XenServer::NotFound
nil
end
end
end
end
end

View file

@ -0,0 +1,37 @@
require 'fog/core/model'
module Fog
module Compute
class XenServer
class VIF < Fog::Model
# API Reference here:
# http://docs.vmd.citrix.com/XenServer/5.6.0/1.0/en_gb/api/?c=VIF
identity :reference
attribute :mac, :aliases => :MAC
attribute :uuid
attribute :allowed_operations
attribute :currently_attached
attribute :device
attribute :mac_autogenerated, :aliases => :MAC_autogenerated
attribute :metrics
attribute :mtu, :aliases => :MTU
attribute :network
attribute :status_code
attribute :status_detail
attribute :vm, :aliases => :VM
#ignore_attributes :current_operations, :qos_supported_algorithms, :qos_algorithm_params, :qos_algorithm_type, :other_config,
# :runtime_properties
def initialize(attributes={})
@uuid ||= 0
super
end
end
end
end
end

View file

@ -0,0 +1,29 @@
require 'fog/core/collection'
require 'fog/xenserver/models/compute/vif'
module Fog
module Compute
class XenServer
class Vifs < Fog::Collection
model Fog::Compute::XenServer::VIF
def all(options = {})
data = connection.get_records 'VIF'
load(data)
end
def get( ref )
if ref && obj = connection.get_record( ref, 'VIF' )
new(obj)
end
rescue Fog::XenServer::NotFound
nil
end
end
end
end
end

View file

@ -0,0 +1,29 @@
module Fog
module Parsers
module XenServer
class Base
attr_reader :response
def initialize
reset
end
def reset
@response = {}
end
def parse( data )
if data.is_a? Hash
@response = data.symbolize_keys!
elsif data.is_a? Array
@response = data.first
end
@response
end
end
end
end
end

View file

@ -0,0 +1,19 @@
module Fog
module Parsers
module XenServer
class GetHosts < Fog::Parsers::XenServer::Base
def reset
@response = []
end
def parse( data )
parser = Fog::Parsers::XenServer::Base.new
data.each_pair {|reference, host_hash| @response << parser.parse( host_hash ).merge(:reference => reference) }
end
end
end
end
end

View file

@ -0,0 +1,19 @@
module Fog
module Parsers
module XenServer
class GetNetworks < Fog::Parsers::XenServer::Base
def reset
@response = []
end
def parse( data )
parser = Fog::Parsers::XenServer::Base.new
data.each_pair {|reference, network_hash| @response << parser.parse( network_hash ).merge(:reference => reference) }
end
end
end
end
end

View file

@ -0,0 +1,19 @@
module Fog
module Parsers
module XenServer
class GetPools < Fog::Parsers::XenServer::Base
def reset
@response = []
end
def parse( data )
parser = Fog::Parsers::XenServer::Base.new
data.each_pair {|reference, pool_hash| @response << parser.parse( pool_hash ).merge(:reference => reference) }
end
end
end
end
end

View file

@ -0,0 +1,19 @@
module Fog
module Parsers
module XenServer
class GetRecords < Fog::Parsers::XenServer::Base
def reset
@response = []
end
def parse( data )
parser = Fog::Parsers::XenServer::Base.new
data.each_pair {|reference, hash| @response << parser.parse( hash ).merge(:reference => reference) }
end
end
end
end
end

View file

@ -0,0 +1,19 @@
module Fog
module Parsers
module XenServer
class GetStorageRepositories < Fog::Parsers::XenServer::Base
def reset
@response = []
end
def parse( data )
parser = Fog::Parsers::XenServer::Base.new
data.each_pair {|reference, sr_hash| @response << parser.parse( sr_hash ).merge(:reference => reference) }
end
end
end
end
end

View file

@ -0,0 +1,19 @@
module Fog
module Parsers
module XenServer
class GetVBDs < Fog::Parsers::XenServer::Base
def reset
@response = []
end
def parse( data )
parser = Fog::Parsers::XenServer::Base.new
data.each_pair {|reference, hash| @response << parser.parse( hash ).merge(:reference => reference) }
end
end
end
end
end

View file

@ -0,0 +1,19 @@
module Fog
module Parsers
module XenServer
class GetVIFs < Fog::Parsers::XenServer::Base
def reset
@response = []
end
def parse( data )
parser = Fog::Parsers::XenServer::Base.new
data.each_pair {|reference, vif_hash| @response << parser.parse( vif_hash ).merge(:reference => reference) }
end
end
end
end
end

View file

@ -0,0 +1,19 @@
module Fog
module Parsers
module XenServer
class GetVms < Fog::Parsers::XenServer::Base
def reset
@response = []
end
def parse( data )
parser = Fog::Parsers::XenServer::Base.new
data.each_pair {|reference, vm_hash| @response << parser.parse( vm_hash ).merge(:reference => reference) }
end
end
end
end
end

View file

@ -0,0 +1,22 @@
module Fog
module Compute
class XenServer
class Real
def create_server( name_label, template = nil, network = nil, extra_args = {})
create_vm( name_label, template, network, extra_args)
end
end
class Mock
def create_server()
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,36 @@
module Fog
module Compute
class XenServer
class Real
def create_vif( vm_ref, network_ref )
@connection.request({:parser => Fog::Parsers::XenServer::Base.new, :method => 'VIF.create'}, default_vif_config(vm_ref, network_ref) )
end
def default_vif_config( vm_ref, network_ref, device_number = '0' )
{
'MAC_autogenerated' => 'True',
'VM' => vm_ref,
'network' => network_ref,
'device' => device_number,
'MAC' => '',
'MTU' => '0',
'other_config' => {},
'qos_algorithm_type' => 'ratelimit',
'qos_algorithm_params' => {}
}
end
end
class Mock
def create_vm()
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,66 @@
module Fog
module Compute
class XenServer
class Real
def create_vm( name_label, template = nil, network = nil, extra_args = {})
template ||= default_template
network ||= default_network
if template.nil?
raise "Invalid template"
end
if template.kind_of? String
data = get_vm( template )
template_string = template
template = Fog::Compute::XenServer::Server.new(data)
end
begin
#FIXME: need to check that template exist actually
raise "Template #{template_string} does not exist" if template.allowed_operations.nil?
raise 'Clone Operation not Allowed' unless template.allowed_operations.include?('clone')
# Clone the VM template
@connection.request(
{:parser => Fog::Parsers::XenServer::Base.new, :method => 'VM.clone'},
template.reference, name_label
)
new_vm = Fog::Compute::XenServer::Server.new get_vm( name_label )
# Not required
#@connection.request(
# {:parser => Fog::Parsers::XenServer::Base.new, :method => 'VM.set_affinity'},
# new_vm.reference, hosts.all.first.reference
#)
#
# Create VIF
#create_vif( new_vm.reference, network.reference )
# raise Fog::XenServer::OperationFailed unless new_vm.allowed_operations.include?('provision')
@connection.request({:parser => Fog::Parsers::XenServer::Base.new, :method => 'VM.provision'}, new_vm.reference)
start_vm( new_vm.reference ) unless extra_args[:auto_start] == false
new_vm
rescue => e
puts e.message
puts e.backtrace
puts "ERROR"
end
end
end
class Mock
def create_vm()
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,22 @@
module Fog
module Compute
class XenServer
class Real
def destroy_server( vm_ref , extra_args = {})
@connection.request({:parser => Fog::Parsers::XenServer::Base.new, :method => 'VM.destroy'}, vm_ref)
end
end
class Mock
def destroy_server()
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,22 @@
module Fog
module Compute
class XenServer
class Real
def destroy_vbd( vbd_ref, extra_args = {})
@connection.request({:parser => Fog::Parsers::XenServer::Base.new, :method => 'VBD.destroy'}, vbd_ref)
end
end
class Mock
def destroy_vbd()
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,22 @@
module Fog
module Compute
class XenServer
class Real
def destroy_vdi( vdi_ref, extra_args = {})
@connection.request({:parser => Fog::Parsers::XenServer::Base.new, :method => 'VDI.destroy'}, vdi_ref)
end
end
class Mock
def destroy_vdi()
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,27 @@
module Fog
module Compute
class XenServer
class Real
require 'fog/xenserver/parsers/get_hosts'
def get_hosts( options = {} )
options[:sort] ||= 'name_label'
result = @connection.request(:parser => Fog::Parsers::XenServer::GetHosts.new, :method => 'host.get_all_records')
result.sort! {|a,b| a[ options[:sort].to_sym ] <=> b[ options[:sort].to_sym ]}
end
end
class Mock
def get_hosts
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,26 @@
module Fog
module XenServer
class Real
require 'fog/xenserver/parser'
def get_network( name_label )
network_ref = @connection.request({:parser => Fog::Parsers::XenServer::Base.new, :method => 'network.get_by_name_label'}, name_label)
get_network_by_ref( network_ref )
end
def get_network_by_ref( network_ref )
@connection.request({:parser => Fog::Parsers::XenServer::Base.new, :method => 'network.get_record'}, network_ref).merge(:reference => network_ref)
end
end
class Mock
def get_network( uuid )
Fog::Mock.not_implemented
end
end
end
end

View file

@ -0,0 +1,23 @@
module Fog
module XenServer
class Real
require 'fog/xenserver/parsers/get_networks'
def get_networks( options = {} )
options[:sort] ||= 'name_label'
result = @connection.request(:parser => Fog::Parsers::XenServer::GetNetworks.new, :method => 'network.get_all_records')
result.sort! {|a,b| a[ options[:sort].to_sym ] <=> b[ options[:sort].to_sym ]}
end
end
class Mock
def get_networks
Fog::Mock.not_implemented
end
end
end
end

View file

@ -0,0 +1,24 @@
module Fog
module Compute
class XenServer
class Real
require 'fog/xenserver/parser'
def get_pool_by_ref( pool_ref )
@connection.request({:parser => Fog::Parsers::XenServer::Base.new, :method => 'VM.get_record'}, pool_ref).merge(:reference => pool_ref)
end
end
class Mock
def get_pool( uuid )
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,27 @@
module Fog
module Compute
class XenServer
class Real
require 'fog/xenserver/parsers/get_pools'
def get_pools( options = {} )
options[:sort] ||= 'name_label'
result = @connection.request(:parser => Fog::Parsers::XenServer::GetPools.new, :method => 'pool.get_all_records')
result.sort! {|a,b| a[ options[:sort].to_sym ] <=> b[ options[:sort].to_sym ]}
end
end
class Mock
def get_pools
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,29 @@
module Fog
module Compute
class XenServer
class Real
require 'fog/xenserver/parser'
def get_record( ref, klass, options = {} )
get_record_by_ref ref, klass, options
end
def get_record_by_ref( ref, klass, options = {} )
@connection.request({:parser => Fog::Parsers::XenServer::Base.new, :method => "#{klass}.get_record"}, ref).merge(:reference => ref)
end
end
class Mock
def get_record_by_ref
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,25 @@
module Fog
module Compute
class XenServer
class Real
require 'fog/xenserver/parsers/get_records'
def get_records( klass, options = {} )
@connection.request(:parser => Fog::Parsers::XenServer::GetRecords.new, :method => "#{klass}.get_all_records")
end
end
class Mock
def get_vms
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,26 @@
module Fog
module Compute
class XenServer
class Real
require 'fog/xenserver/parsers/get_storage_repositories'
def get_storage_repositories( options = {} )
options[:sort] ||= 'name_label'
result = @connection.request(:parser => Fog::Parsers::XenServer::GetStorageRepositories.new, :method => 'SR.get_all_records')
result.sort! {|a,b| a[ options[:sort].to_sym ] <=> b[ options[:sort].to_sym ]}
end
end
class Mock
def get_storage_repositories
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,33 @@
module Fog
module Compute
class XenServer
class Real
require 'fog/xenserver/parser'
def get_storage_repository( name_label )
sr_ref = @connection.request({:parser => Fog::Parsers::XenServer::Base.new, :method => 'SR.get_by_name_label'}, name_label)
get_storage_repository_by_ref( sr_ref )
end
def get_storage_repository_by_ref( sr_ref )
@connection.request({:parser => Fog::Parsers::XenServer::Base.new, :method => 'SR.get_record'}, sr_ref).merge(:reference => sr_ref)
end
end
class Mock
def get_storage_repository( uuid )
Fog::Mock.not_implemented
end
def get_storage_repository_by_ref( sr_ref )
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,25 @@
module Fog
module Compute
class XenServer
class Real
require 'fog/xenserver/parsers/get_records'
def get_vbds( options = {} )
@connection.request(:parser => Fog::Parsers::XenServer::GetRecords.new, :method => 'VBD.get_all_records')
end
end
class Mock
def get_vbds
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,27 @@
module Fog
module Compute
class XenServer
class Real
require 'fog/xenserver/parsers/get_vifs'
def get_vifs( options = {} )
options[:sort] ||= 'name_label'
result = @connection.request(:parser => Fog::Parsers::XenServer::GetVIFs.new, :method => 'VIF.get_all_records')
result.sort! {|a,b| a[ options[:sort].to_sym ] <=> b[ options[:sort].to_sym ]}
end
end
class Mock
def get_vifs
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,29 @@
module Fog
module Compute
class XenServer
class Real
require 'fog/xenserver/parser'
def get_vm( name_label )
vm_ref = @connection.request({:parser => Fog::Parsers::XenServer::Base.new, :method => 'VM.get_by_name_label'}, name_label)
get_vm_by_ref( vm_ref )
end
def get_vm_by_ref( vm_ref )
@connection.request({:parser => Fog::Parsers::XenServer::Base.new, :method => 'VM.get_record'}, vm_ref).merge(:reference => vm_ref)
end
end
class Mock
def get_vm( uuid )
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,27 @@
module Fog
module Compute
class XenServer
class Real
require 'fog/xenserver/parsers/get_vms'
def get_vms( options = {} )
options[:sort] ||= 'name_label'
result = @connection.request(:parser => Fog::Parsers::XenServer::GetVms.new, :method => 'VM.get_all_records')
result.sort! {|a,b| a[ options[:sort].to_sym ] <=> b[ options[:sort].to_sym ]}
end
end
class Mock
def get_vms
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,23 @@
module Fog
module Compute
class XenServer
class Real
def reboot_server( ref, stype = 'clean' )
@connection.request({:parser => Fog::Parsers::XenServer::Base.new, :method => "VM.#{stype}_shutdown"}, ref)
end
end
class Mock
def reboot_server( ref, stype )
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,25 @@
module Fog
module Compute
class XenServer
class Real
require 'fog/xenserver/parser'
def set_affinity( host_ref )
@connection.request({:parser => Fog::Parsers::XenServer::Base.new, :method => 'VM.set_affinity'}, host_ref)
end
end
class Mock
def set_affinity( uuid )
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,23 @@
module Fog
module Compute
class XenServer
class Real
def shutdown_server( vm_ref, stype = 'clean' )
@connection.request({:parser => Fog::Parsers::XenServer::Base.new, :method => "VM.#{stype}_shutdown"}, vm_ref)
end
end
class Mock
def shutdown_server( vm_ref )
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,23 @@
module Fog
module Compute
class XenServer
class Real
def start_server( vm_ref )
start_vm( vm_ref )
end
end
class Mock
def start_server( vm_ref )
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,25 @@
module Fog
module Compute
class XenServer
class Real
# http://bit.ly/8ZPyCN
# VM.start( session, VM_ref, start_paused, force)
def start_vm( vm_ref )
@connection.request({:parser => Fog::Parsers::XenServer::Base.new, :method => 'VM.start'}, vm_ref, false, false)
end
end
class Mock
def start_vm( vm_ref )
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,8 @@
class Hash
def symbolize_keys!
keys.each do |key|
self[(key.to_sym rescue key)] = delete(key) if key.respond_to?(:to_sym) && !key.is_a?(Fixnum)
end
self
end
end

21
tests/xenserver/README Normal file
View file

@ -0,0 +1,21 @@
# Running the XenServer tests.
Tweak the helper.rb file in tests/xenserver/helper.rb to fit your needs.
Fog credentials in $HOME/.fog file are used to run the tests. In particular:
:default:
:xenserver_url: xenserver-test
:xenserver_username: root
:xenserver_password: secret
We need a working template named squeeze-test available in the XenServer
to perform the tests. Change the template name to fit your needs
or create a working template named squeeze-test.
The tests creates a few VMs during the flight. Make sure you have enough RAM and
Storage available in the hypervisor.
Run the XenServer provider tests issuing:
shindo tests/xenserver

View file

@ -0,0 +1,44 @@
Shindo.tests('Fog::Compute[:xenserver]', ['xenserver']) do
compute = Fog::Compute[:xenserver]
tests("Compute attributes") do
%w{ default_template }.each do |attr|
test("it should respond to #{attr}") { compute.respond_to? attr }
end
end
tests("Compute collections") do
%w{ pifs vifs hosts storage_repositories servers networks vbds vdis pools }.each do |collection|
test("it should respond to #{collection}") { compute.respond_to? collection }
test("it should respond to #{collection}.all") { eval("compute.#{collection}").respond_to? 'all' }
test("it should respond to #{collection}.get") { eval("compute.#{collection}").respond_to? 'get' }
end
# This will fail if there are no PIFs
# (not sure if that's gonna be a real scenario though)
tests("PIFs collection") do
test("should have at least one PIF") { compute.pifs.size >= 1 }
end
# This will fail if there are no VIFs
# (not sure if that's gonna be a real scenario though)
tests("VIFs collection") do
test("should have at least one VIF") { compute.vifs.size >= 1 }
end
# This will fail if there are no VIFs
# (not sure if that's gonna be a real scenario though)
tests("Networks collection") do
test("should have at least one Network") { compute.networks.size >= 1 }
end
end
tests "Default template" do
test("it should NOT have a default template") { compute.default_template.nil? }
# This template exists in our XenServer
compute.default_template = 'squeeze-test'
test("it should have a default template if template exists") { compute.default_template.name == 'squeeze-test' }
test("default template must be a Fog::Compute::XenServer::Server") { compute.default_template.is_a? Fog::Compute::XenServer::Server }
end
end

View file

@ -0,0 +1,8 @@
def test_template_name
'squeeze-test'
end
def test_ephemeral_vm_name
'fog-test-server-shindo'
end

View file

@ -0,0 +1,67 @@
Shindo.tests('Fog::Compute[:xenserver] | host model', ['xenserver']) do
hosts = Fog::Compute[:xenserver].hosts
host = hosts.first
tests('The host model should') do
tests('have the action') do
test('reload') { host.respond_to? 'reload' }
end
tests('have attributes') do
model_attribute_hash = host.attributes
attributes = [
:reference,
:uuid,
:name,
:address,
:allowed_operations,
:enabled,
:hostname,
:metrics,
:name_description,
:other_config,
:__pbds,
:__pifs,
:__resident_vms
]
tests("The host model should respond to") do
attributes.each do |attribute|
test("#{attribute}") { host.respond_to? attribute }
end
end
tests("The attributes hash should have key") do
attributes.each do |attribute|
test("#{attribute}") { model_attribute_hash.has_key? attribute }
end
end
end
test('be a kind of Fog::Compute::XenServer::Host') { host.kind_of? Fog::Compute::XenServer::Host }
end
tests("A real host should") do
tests("return valid PIFs") do
test("as an array") { host.pifs.kind_of? Array }
host.pifs.each { |i|
test("and each PIF should be a Fog::Compute::XenServer::PIF") { i.kind_of? Fog::Compute::XenServer::PIF}
}
end
tests("return valid PBDs") do
test("as an array") { host.pbds.kind_of? Array }
host.pbds.each { |i|
test("and each PBD should be a Fog::Compute::XenServer::PBD") { i.kind_of? Fog::Compute::XenServer::PBD}
}
end
tests("return valid resident servers") do
test("as an array") { host.resident_servers.kind_of? Array }
host.resident_servers.each { |i|
test("and each Server should be a Fog::Compute::XenServer::Server") { i.kind_of? Fog::Compute::XenServer::Server}
}
end
end
end

View file

@ -0,0 +1,22 @@
Shindo.tests('Fog::Compute[:xenserver] | hosts collection', ['xenserver']) do
conn = Fog::Compute[:xenserver]
tests('The hosts collection') do
hosts = conn.hosts.all
test('should not be empty') { !hosts.empty? }
test('should be a kind of Fog::Compute::XenServer::Hosts') { hosts.kind_of? Fog::Compute::XenServer::Hosts }
tests('should be able to reload itself').succeeds { hosts.reload }
tests('should be able to get a model') do
tests('by reference').succeeds {
hosts.get(hosts.first.reference).is_a? Fog::Compute::XenServer::Host
}
end
end
end

View file

@ -0,0 +1,67 @@
Shindo.tests('Fog::Compute[:network] | network model', ['network']) do
require 'pp'
networks = Fog::Compute[:xenserver].networks
network = networks.first
tests('The network model should') do
tests('have the action') do
test('reload') { network.respond_to? 'reload' }
#%w{ refresh stop clean_shutdown hard_shutdown start destroy reboot hard_reboot clean_reboot }.each do |action|
# test(action) { server.respond_to? action }
# #test("#{action} returns successfully") { server.send(action.to_sym) ? true : false }
#end
end
tests('have attributes') do
model_attribute_hash = network.attributes
attributes = [
:reference,
:uuid,
:__vifs,
:tags,
:mtu,
:bridge,
:name,
:other_config,
:__pifs,
:allowed_operations,
:current_operations,
:blobs
]
tests("The network model should respond to") do
attributes.each do |attribute|
test("#{attribute}") { network.respond_to? attribute }
end
end
tests("The attributes hash should have key") do
attributes.each do |attribute|
test("#{attribute}") { model_attribute_hash.has_key? attribute }
end
end
end
test('be a kind of Fog::Compute::XenServer::Network') { network.kind_of? Fog::Compute::XenServer::Network }
end
tests("A real network should") do
tests("return valid vifs") do
test("as an array") { network.vifs.kind_of? Array }
network.vifs.each { |i|
test("and each VIF should be a Fog::Compute::XenServer::VIF") { i.kind_of? Fog::Compute::XenServer::VIF }
}
end
tests("return valid PIFs") do
networks.each do |network|
test("as an array") { network.pifs.kind_of? Array }
network.pifs.each { |i|
test("and each PIF should be a Fog::Compute::XenServer::PIF") { i.kind_of? Fog::Compute::XenServer::PIF}
}
end
end
test("be able to refresh itself") { network.refresh }
end
end

View file

@ -0,0 +1,44 @@
Shindo.tests('Fog::Compute[:network] | network model', ['network']) do
pbds = Fog::Compute[:xenserver].pbds
pbd = pbds.first
tests('The PBD model should') do
tests('have the action') do
test('reload') { pbd.respond_to? 'reload' }
end
tests('have attributes') do
model_attribute_hash = pbd.attributes
attributes = [
:reference,
:uuid,
:__host,
:__sr
]
tests("The PBD model should respond to") do
attributes.each do |attribute|
test("#{attribute}") { pbd.respond_to? attribute }
end
end
tests("The attributes hash should have key") do
attributes.each do |attribute|
test("#{attribute}") { model_attribute_hash.has_key? attribute }
end
end
end
test('be a kind of Fog::Compute::XenServer::PBD') { pbd.kind_of? Fog::Compute::XenServer::PBD}
end
tests("A real PBD should") do
tests("return valid host") do
test("should be a Fog::Compute::XenServer::Host") { pbd.host.kind_of? Fog::Compute::XenServer::Host }
end
tests("return valid storage repository") do
test("should be a Fog::Compute::XenServer::StorageRepository") { pbd.storage_repository.kind_of? Fog::Compute::XenServer::StorageRepository }
end
end
end

View file

@ -0,0 +1,22 @@
Shindo.tests('Fog::Compute[:xenserver] | pbds collection', ['xenserver']) do
conn = Fog::Compute[:xenserver]
tests('The pbds collection') do
pbds = conn.pbds.all
test('should not be empty') { !pbds.empty? }
test('should be a kind of Fog::Compute::XenServer::Pbds') { pbds.kind_of? Fog::Compute::XenServer::Pbds }
tests('should be able to reload itself').succeeds { pbds.reload }
tests('should be able to get a model') do
tests('by reference').succeeds {
pbds.get(pbds.first.reference).is_a? Fog::Compute::XenServer::PBD
}
end
end
end

View file

@ -0,0 +1,58 @@
Shindo.tests('Fog::Compute[:network] | network model', ['network']) do
pifs = Fog::Compute[:xenserver].pifs
pif = pifs.first
tests('The PIF model should') do
tests('have the action') do
test('reload') { pif.respond_to? 'reload' }
end
tests('have attributes') do
model_attribute_hash = pif.attributes
attributes = [
:reference,
:uuid,
:physical,
:mac,
:currently_attached,
:device,
:metrics,
:dns,
:gateway,
:ip,
:ip_configuration_mode,
:mtu,
:__network,
:netmask,
:management,
:vlan,
:other_config,
:__host
]
tests("The PIF model should respond to") do
attributes.each do |attribute|
test("#{attribute}") { pif.respond_to? attribute }
end
end
tests("The attributes hash should have key") do
attributes.each do |attribute|
test("#{attribute}") { model_attribute_hash.has_key? attribute }
end
end
end
test('be a kind of Fog::Compute::XenServer::PIF') { pif.kind_of? Fog::Compute::XenServer::PIF}
end
tests("A real PIF should") do
tests("return a valid network") do
test("should be a Fog::Compute::XenServer::Network") { pif.network.kind_of? Fog::Compute::XenServer::Network }
end
tests("return valid host") do
test("should be a Fog::Compute::XenServer::Host") { pif.host.kind_of? Fog::Compute::XenServer::Host }
end
end
end

View file

@ -0,0 +1,109 @@
Shindo.tests('Fog::Compute[:xenserver] | server model', ['xenserver']) do
servers = Fog::Compute[:xenserver].servers
# pre-flight cleanup
(servers.all :name_matches => test_ephemeral_vm_name).each do |s|
s.destroy
end
server = Fog::Compute[:xenserver].servers.create(:name => test_ephemeral_vm_name,
:template_name => test_template_name)
tests('The server model should') do
tests('have the action') do
test('reload') { server.respond_to? 'reload' }
%w{ refresh stop clean_shutdown hard_shutdown start destroy reboot hard_reboot clean_reboot }.each do |action|
test(action) { server.respond_to? action }
#test("#{action} returns successfully") { server.send(action.to_sym) ? true : false }
end
end
tests('have attributes') do
model_attribute_hash = server.attributes
attributes = [
:reference,
:uuid,
:is_a_template,
:affinity,
:allowed_operations,
:consoles,
:domarch,
:domid,
:guest_metrics,
:is_a_snapshot,
:is_a_template,
:is_control_domain,
:memory_dynamic_max,
:memory_dynamic_min,
:memory_static_max,
:memory_static_min,
:memory_target,
:metrics,
:name_description,
:other_config,
:power_state,
:pv_args,
:resident_on,
:__vbds,
:vcpus_at_startup,
:vcpus_max,
:__vifs
]
tests("The server model should respond to") do
attributes.each do |attribute|
test("#{attribute}") { server.respond_to? attribute }
end
end
tests("The attributes hash should have key") do
attributes.each do |attribute|
test("#{attribute}") { model_attribute_hash.has_key? attribute }
end
end
end
test('be a kind of Fog::Compute::XenServer::Server') { server.kind_of? Fog::Compute::XenServer::Server }
end
tests("A real server should") do
tests("return valid vbds") do
test("as an array") { server.vbds.kind_of? Array }
server.vbds.each { |i|
test("and each VBD should be a Fog::Compute::XenServer::VBD") { i.kind_of? Fog::Compute::XenServer::VBD }
}
end
test("be able to refresh itself") { server.refresh }
test("always stop when I say stop('hard')") do
server.stop 'hard'
end
# shutdown is async apparently, we wait
test("not be running when it's stopped") do
server.wait_for { !server.running? }
true
end
test("do nothing when I say stop('hard') but it's not running") do
server.stop('hard') == false
end
test("always start when I say start") do
server.start
end
# start is async apparently, we wait
test("be running if I started the server") do
server.wait_for { server.running? }
true
end
test("be able to be destroyed!") do
server.destroy
servers.get_by_name('fog-test-server-shindo') == nil
end
end
end

View file

@ -0,0 +1,30 @@
Shindo.tests('Fog::Compute[:xenserver] | servers collection', ['xenserver']) do
#require 'pp'
conn = Fog::Compute[:xenserver]
# pre-flight cleanup
(conn.servers.all :name_matches => test_ephemeral_vm_name).each do |s|
s.destroy
end
# Create some test data
server = conn.servers.create(:name => test_ephemeral_vm_name,
:template_name => test_template_name)
server.wait_for { running? }
tests('The servers collection') do
servers = conn.servers.all
test('should not be empty') { !servers.empty? }
test('should be a kind of Fog::Compute::XenServer::Servers') { servers.kind_of? Fog::Compute::XenServer::Servers }
tests('should be able to reload itself').succeeds { servers.reload }
tests('should be able to get a model') do
tests('by name').succeeds { servers.get_by_name test_ephemeral_vm_name }
tests('by instance uuid').succeeds { servers.get(servers.get_by_name(test_ephemeral_vm_name).reference) }
end
end
end