ruby_vcloud_sdk 0.4.8 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +296 -0
- data/lib/ruby_vcloud_sdk.rb +0 -4
- data/lib/ruby_vcloud_sdk/catalog.rb +377 -0
- data/lib/ruby_vcloud_sdk/catalog_item.rb +26 -0
- data/lib/ruby_vcloud_sdk/client.rb +25 -882
- data/lib/ruby_vcloud_sdk/config.rb +1 -7
- data/lib/ruby_vcloud_sdk/connection/connection.rb +114 -54
- data/lib/ruby_vcloud_sdk/cpu.rb +11 -0
- data/lib/ruby_vcloud_sdk/disk.rb +55 -0
- data/lib/ruby_vcloud_sdk/edge_gateway.rb +32 -0
- data/lib/ruby_vcloud_sdk/infrastructure.rb +135 -0
- data/lib/ruby_vcloud_sdk/ip_ranges.rb +95 -0
- data/lib/ruby_vcloud_sdk/memory.rb +11 -0
- data/lib/ruby_vcloud_sdk/network.rb +32 -0
- data/lib/ruby_vcloud_sdk/powerable.rb +78 -0
- data/lib/ruby_vcloud_sdk/resources.rb +13 -0
- data/lib/ruby_vcloud_sdk/session.rb +46 -0
- data/lib/ruby_vcloud_sdk/vapp.rb +122 -0
- data/lib/ruby_vcloud_sdk/vdc.rb +210 -0
- data/lib/ruby_vcloud_sdk/vdc_storage_profile.rb +23 -0
- data/lib/ruby_vcloud_sdk/version.rb +1 -1
- data/lib/ruby_vcloud_sdk/vm.rb +132 -0
- data/lib/ruby_vcloud_sdk/xml/constants.rb +6 -4
- data/lib/ruby_vcloud_sdk/xml/wrapper.rb +109 -30
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes.rb +45 -2
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/admin_catalog.rb +13 -4
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/allocated_ip_addresses.rb +9 -0
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/catalog_item.rb +6 -14
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/disk.rb +24 -14
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/disk_attach_or_detach_params.rb +0 -2
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/disk_create_params.rb +1 -3
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/edge_gateway.rb +13 -0
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/gateway_interface.rb +22 -0
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/hard_disk_item_wrapper.rb +4 -4
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/ip_address.rb +10 -0
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/ip_range.rb +13 -0
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/ip_ranges.rb +9 -0
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/ip_scope.rb +6 -32
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/item.rb +1 -7
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/link.rb +14 -0
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/media.rb +4 -20
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/media_insert_or_eject_params.rb +1 -3
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/network_connection_section.rb +0 -4
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/nic_item_wrapper.rb +0 -2
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/org.rb +44 -0
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/org_vdc_network.rb +11 -3
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/query_result_records.rb +14 -0
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/recompose_vapp_params.rb +42 -0
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/session.rb +5 -5
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/supported_versions.rb +19 -0
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/task.rb +1 -1
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/upload_vapp_template_params.rb +2 -4
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/vapp.rb +13 -22
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/vapp_template.rb +0 -2
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/vcloud.rb +5 -3
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/vdc.rb +72 -15
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/virtual_hardware_section.rb +8 -6
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/vm.rb +29 -25
- data/lib/ruby_vcloud_sdk/xml/wrapper_classes/vms.rb +12 -0
- data/lib/ruby_vcloud_sdk/xml/xml_templates/AdminCatalog.xml +6 -1
- data/lib/ruby_vcloud_sdk/xml/xml_templates/RecomposeVAppParams.xml +16 -1
- metadata +116 -233
- data/README +0 -1
- data/Rakefile +0 -50
- data/lib/ruby_vcloud_sdk/util.rb +0 -21
- data/spec/assets/admin_org_response.xml +0 -75
- data/spec/assets/catalog_add_item_response.xml +0 -8
- data/spec/assets/catalog_add_vapp_request.xml +0 -5
- data/spec/assets/catalog_item_added_response.xml +0 -19
- data/spec/assets/catalog_response.xml +0 -19
- data/spec/assets/existing_media_busy_response.xml +0 -19
- data/spec/assets/existing_media_catalog_item.xml +0 -8
- data/spec/assets/existing_media_delete_task_done.xml +0 -6
- data/spec/assets/existing_media_done_response.xml +0 -11
- data/spec/assets/existing_vapp_resolver_response.xml +0 -3
- data/spec/assets/existing_vapp_template_catalog_resolver_response.xml +0 -3
- data/spec/assets/existing_vapp_template_instantiate_response.xml +0 -20
- data/spec/assets/existing_vapp_template_instantiate_task_error_response.xml +0 -7
- data/spec/assets/existing_vapp_template_instantiate_task_start_response.xml +0 -7
- data/spec/assets/existing_vapp_template_instantiate_task_success_response.xml +0 -7
- data/spec/assets/existing_vapp_template_item_response.xml +0 -8
- data/spec/assets/existing_vapp_template_ready_response.xml +0 -79
- data/spec/assets/finalize_upload_task_done_response.xml +0 -7
- data/spec/assets/finalize_upload_task_response.xml +0 -7
- data/spec/assets/indy_disk_attach_request.xml +0 -3
- data/spec/assets/indy_disk_attach_task.xml +0 -6
- data/spec/assets/indy_disk_attach_task_error.xml +0 -6
- data/spec/assets/indy_disk_create_error.xml +0 -1
- data/spec/assets/indy_disk_create_request.xml +0 -4
- data/spec/assets/indy_disk_create_response.xml +0 -19
- data/spec/assets/indy_disk_delete_task.xml +0 -6
- data/spec/assets/indy_disk_detach_request.xml +0 -3
- data/spec/assets/indy_disk_detach_task.xml +0 -6
- data/spec/assets/indy_disk_response.xml +0 -11
- data/spec/assets/instantiated_suspended_vapp_response.xml +0 -209
- data/spec/assets/instantiated_vapp_delelete_done_task.xml +0 -5
- data/spec/assets/instantiated_vapp_delelete_running_task.xml +0 -6
- data/spec/assets/instantiated_vapp_network_config_add_network_request.xml +0 -36
- data/spec/assets/instantiated_vapp_network_config_modify_network_task_success.xml +0 -6
- data/spec/assets/instantiated_vapp_network_config_remove_network_request.xml +0 -6
- data/spec/assets/instantiated_vapp_network_config_section_response.xml +0 -17
- data/spec/assets/instantiated_vapp_off_response.xml +0 -206
- data/spec/assets/instantiated_vapp_on_response.xml +0 -205
- data/spec/assets/instantiated_vapp_power_task_running.xml +0 -6
- data/spec/assets/instantiated_vapp_power_task_success.xml +0 -6
- data/spec/assets/instantiated_vapp_response.xml +0 -205
- data/spec/assets/instantiated_vm_change_task_running.xml +0 -6
- data/spec/assets/instantiated_vm_change_task_success.xml +0 -6
- data/spec/assets/instantiated_vm_cpu_response.xml +0 -11
- data/spec/assets/instantiated_vm_insert_media_task_done.xml +0 -6
- data/spec/assets/instantiated_vm_memory_response.xml +0 -11
- data/spec/assets/instantiated_vm_modify_task_running.xml +0 -6
- data/spec/assets/instantiated_vm_modify_task_success.xml +0 -5
- data/spec/assets/instantiated_vm_network_section_response.xml +0 -11
- data/spec/assets/instantiated_vm_response.xml +0 -149
- data/spec/assets/media_add_to_catalog_request.xml +0 -5
- data/spec/assets/media_add_to_catalog_response.xml +0 -8
- data/spec/assets/media_delete_task_done.xml +0 -6
- data/spec/assets/media_upload_pending_response.xml +0 -13
- data/spec/assets/media_upload_request.xml +0 -2
- data/spec/assets/metadata_set_request.xml +0 -3
- data/spec/assets/metadata_set_task_done.xml +0 -6
- data/spec/assets/org_network_response.xml +0 -22
- data/spec/assets/reconfigure_vm_request.xml +0 -133
- data/spec/assets/reconfigure_vm_task.xml +0 -8
- data/spec/assets/session.xml +0 -7
- data/spec/assets/test-config.yml +0 -38
- data/spec/assets/undeploy_params.xml +0 -1
- data/spec/assets/vapp_template_catalog_resolver_response.xml +0 -3
- data/spec/assets/vapp_template_delelete_done_task.xml +0 -5
- data/spec/assets/vapp_template_delelete_running_task.xml +0 -6
- data/spec/assets/vapp_template_instantiate_request.xml +0 -8
- data/spec/assets/vapp_template_instantiate_with_locality_request.xml +0 -14
- data/spec/assets/vapp_template_no_disk_response.xml +0 -27
- data/spec/assets/vapp_template_ready_response.xml +0 -79
- data/spec/assets/vapp_template_upload_complete.xml +0 -28
- data/spec/assets/vapp_template_upload_failed.xml +0 -28
- data/spec/assets/vapp_template_upload_request.xml +0 -4
- data/spec/assets/vapp_template_upload_response.xml +0 -25
- data/spec/assets/vcloud_response.xml +0 -56
- data/spec/assets/vdc_response.xml +0 -57
- data/spec/spec_helper.rb +0 -107
- data/spec/unit/client_response.rb +0 -700
- data/spec/unit/client_spec.rb +0 -1152
@@ -0,0 +1,95 @@
|
|
1
|
+
require "netaddr"
|
2
|
+
require "set"
|
3
|
+
|
4
|
+
module VCloudSdk
|
5
|
+
class IpRanges
|
6
|
+
attr_reader :ranges
|
7
|
+
|
8
|
+
def initialize(value = nil)
|
9
|
+
@ranges = Set.new
|
10
|
+
|
11
|
+
parse_ip_ranges(value) unless value.nil?
|
12
|
+
end
|
13
|
+
|
14
|
+
def add(ip_ranges)
|
15
|
+
ip_ranges = objectify ip_ranges
|
16
|
+
result = IpRanges.new
|
17
|
+
result.ranges.merge @ranges
|
18
|
+
result.ranges.merge ip_ranges.ranges
|
19
|
+
result
|
20
|
+
end
|
21
|
+
alias_method :+, :add
|
22
|
+
|
23
|
+
def subtract(ip_ranges)
|
24
|
+
ip_ranges = objectify ip_ranges
|
25
|
+
difference = IpRanges.new
|
26
|
+
difference.ranges.merge @ranges
|
27
|
+
difference.ranges.subtract ip_ranges.ranges
|
28
|
+
|
29
|
+
difference
|
30
|
+
end
|
31
|
+
alias_method :-, :subtract
|
32
|
+
|
33
|
+
def include?(ip_ranges)
|
34
|
+
ip_ranges = objectify ip_ranges
|
35
|
+
@ranges.superset? ip_ranges.ranges
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
attr_writer :ranges
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def parse_ip_ranges(ip_ranges_string)
|
45
|
+
fail "Parameter is not a string" unless ip_ranges_string.is_a? String
|
46
|
+
|
47
|
+
# remove white space
|
48
|
+
ip_ranges_string.gsub(/\s+/, "").split(",").map do |i|
|
49
|
+
parse_ip_range(i)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def parse_ip_range(ip_range_string)
|
54
|
+
case ip_range_string
|
55
|
+
when /-/
|
56
|
+
ips = ip_range_string.split("-")
|
57
|
+
unless ips.length == 2
|
58
|
+
fail "Invalid input: #{ips.length} field/fields separated by '-'"
|
59
|
+
end
|
60
|
+
|
61
|
+
ips ips[0], ips[1]
|
62
|
+
when /\//
|
63
|
+
ips = NetAddr::CIDR.create(ip_range_string)
|
64
|
+
ips ips.first, ips.last
|
65
|
+
else
|
66
|
+
# A single IP address such as "10.142.15.11"
|
67
|
+
ip = NetAddr::CIDR.create(ip_range_string)
|
68
|
+
fail "IPv6 is not supported" if ip.is_a?(NetAddr::CIDRv6)
|
69
|
+
@ranges.add ip.ip
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def ips(ip_start_string, ip_end_string)
|
74
|
+
ip_start = NetAddr::CIDR.create(ip_start_string)
|
75
|
+
ip_end = NetAddr::CIDR.create(ip_end_string)
|
76
|
+
if ip_start.is_a?(NetAddr::CIDRv6) || ip_end.is_a?(NetAddr::CIDRv6)
|
77
|
+
fail "IPv6 is not supported"
|
78
|
+
end
|
79
|
+
|
80
|
+
if ip_start > ip_end
|
81
|
+
fail "IP #{ip_start.ip} is bigger than IP #{ip_end.ip}"
|
82
|
+
end
|
83
|
+
|
84
|
+
@ranges.merge((ip_start..ip_end).map(&:ip))
|
85
|
+
end
|
86
|
+
|
87
|
+
def objectify(ip_ranges)
|
88
|
+
ip_ranges = IpRanges.new(ip_ranges) if ip_ranges.is_a? String
|
89
|
+
unless ip_ranges.is_a? IpRanges
|
90
|
+
fail "Unable to parse object that is not IpRange or string"
|
91
|
+
end
|
92
|
+
ip_ranges
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require_relative "infrastructure"
|
2
|
+
require_relative "ip_ranges"
|
3
|
+
|
4
|
+
module VCloudSdk
|
5
|
+
class Network
|
6
|
+
include Infrastructure
|
7
|
+
|
8
|
+
def initialize(session, link)
|
9
|
+
@session = session
|
10
|
+
@link = link
|
11
|
+
end
|
12
|
+
|
13
|
+
def name
|
14
|
+
entity_xml.name
|
15
|
+
end
|
16
|
+
|
17
|
+
def ip_ranges
|
18
|
+
entity_xml.ip_ranges
|
19
|
+
.ranges
|
20
|
+
.reduce(IpRanges.new) do |result, i|
|
21
|
+
result + IpRanges.new("#{i.start_address}-#{i.end_address}")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def allocated_ips
|
26
|
+
allocated_addresses = connection.get(entity_xml.allocated_addresses_link)
|
27
|
+
allocated_addresses.ip_addresses.map do |i|
|
28
|
+
i.ip_address
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module VCloudSdk
|
2
|
+
# Shared functions by classes VM and VApp
|
3
|
+
module Powerable
|
4
|
+
def status
|
5
|
+
status_code = entity_xml[:status].to_i
|
6
|
+
Xml::RESOURCE_ENTITY_STATUS.each_pair do |k, v|
|
7
|
+
return k.to_s if v == status_code
|
8
|
+
end
|
9
|
+
|
10
|
+
fail CloudError,
|
11
|
+
"Fail to find corresponding status for code '#{status_code}'"
|
12
|
+
end
|
13
|
+
|
14
|
+
# Power on VApp or VM
|
15
|
+
def power_on
|
16
|
+
target = entity_xml
|
17
|
+
class_name = self.class.name.split("::").last
|
18
|
+
Config.logger.debug "#{class_name} status: #{target[:status]}"
|
19
|
+
if is_status?(target, :POWERED_ON)
|
20
|
+
Config.logger.info "#{class_name} #{target.name} is already powered-on."
|
21
|
+
return
|
22
|
+
end
|
23
|
+
|
24
|
+
power_on_link = target.power_on_link
|
25
|
+
unless power_on_link
|
26
|
+
fail CloudError,
|
27
|
+
"#{class_name} #{target.name} not in a state able to power on."
|
28
|
+
end
|
29
|
+
|
30
|
+
Config.logger.info "Powering on #{class_name} #{target.name}."
|
31
|
+
task = connection.post(power_on_link, nil)
|
32
|
+
task = monitor_task task, @session.time_limit[:power_on]
|
33
|
+
Config.logger.info "#{class_name} #{target.name} is powered on."
|
34
|
+
task
|
35
|
+
end
|
36
|
+
|
37
|
+
# Power off VApp or VM
|
38
|
+
def power_off
|
39
|
+
target = entity_xml
|
40
|
+
class_name = self.class.name.split("::").last
|
41
|
+
Config.logger.debug "#{class_name} status: #{target[:status]}"
|
42
|
+
if is_status?(target, :SUSPENDED)
|
43
|
+
error_msg = "#{class_name} #{target.name} suspended, discard state before powering off."
|
44
|
+
fail class_name == "VApp" ? VappSuspendedError : VmSuspendedError,
|
45
|
+
error_msg
|
46
|
+
end
|
47
|
+
if is_status?(target, :POWERED_OFF)
|
48
|
+
Config.logger.info "#{class_name} #{target.name} is already powered off."
|
49
|
+
return
|
50
|
+
end
|
51
|
+
|
52
|
+
power_off_link = target.power_off_link
|
53
|
+
unless power_off_link
|
54
|
+
fail CloudError, "#{class_name} #{target.name} is not in a state that could be powered off."
|
55
|
+
end
|
56
|
+
|
57
|
+
task = connection.post(power_off_link, nil)
|
58
|
+
monitor_task task, @session.time_limit[:power_off]
|
59
|
+
Config.logger.info "#{class_name} #{target.name} is powered off."
|
60
|
+
|
61
|
+
undeploy(target, class_name)
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def is_status?(target, status)
|
67
|
+
target[:status] == Xml::RESOURCE_ENTITY_STATUS[status].to_s
|
68
|
+
end
|
69
|
+
|
70
|
+
def undeploy(target, class_name)
|
71
|
+
params = Xml::WrapperFactory.create_instance("UndeployVAppParams") # Even for VM it's called UndeployVappParams
|
72
|
+
task = connection.post(target.undeploy_link, params)
|
73
|
+
task = monitor_task(task, @session.time_limit[:undeploy])
|
74
|
+
Config.logger.info "#{class_name} #{target.name} is undeployed."
|
75
|
+
task
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module VCloudSdk
|
2
|
+
class Session
|
3
|
+
attr_reader :connection
|
4
|
+
attr_accessor :retries, :time_limit, :delay
|
5
|
+
|
6
|
+
RETRIES = {
|
7
|
+
default: 5,
|
8
|
+
upload_vapp_files: 7,
|
9
|
+
cpi: 1,
|
10
|
+
}
|
11
|
+
|
12
|
+
TIME_LIMIT_SEC = {
|
13
|
+
default: 120,
|
14
|
+
delete_vapp_template: 120,
|
15
|
+
delete_vapp: 120,
|
16
|
+
delete_media: 120,
|
17
|
+
instantiate_vapp_template: 300,
|
18
|
+
power_on: 600,
|
19
|
+
power_off: 600,
|
20
|
+
undeploy: 720,
|
21
|
+
process_descriptor_vapp_template: 300,
|
22
|
+
http_request: 240,
|
23
|
+
recompose_vapp: 200,
|
24
|
+
}
|
25
|
+
|
26
|
+
DELAY = 1
|
27
|
+
|
28
|
+
private_constant :RETRIES, :TIME_LIMIT_SEC, :DELAY
|
29
|
+
|
30
|
+
def initialize(url, username, password, options)
|
31
|
+
@time_limit = options[:time_limit_sec] || TIME_LIMIT_SEC
|
32
|
+
@retries = options[:retries] || RETRIES
|
33
|
+
@delay = options[:delay] || DELAY
|
34
|
+
@connection = Connection::Connection.new(
|
35
|
+
url,
|
36
|
+
@time_limit[:http_request])
|
37
|
+
@session_xml_obj = @connection.connect(username, password)
|
38
|
+
@org_link = @session_xml_obj.organization
|
39
|
+
end
|
40
|
+
|
41
|
+
def org
|
42
|
+
@connection.get(@org_link)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require_relative "infrastructure"
|
2
|
+
require_relative "powerable"
|
3
|
+
require_relative "vm"
|
4
|
+
|
5
|
+
module VCloudSdk
|
6
|
+
class VApp
|
7
|
+
include Infrastructure
|
8
|
+
include Powerable
|
9
|
+
|
10
|
+
def initialize(session, link)
|
11
|
+
@session = session
|
12
|
+
@link = link
|
13
|
+
end
|
14
|
+
|
15
|
+
def name
|
16
|
+
entity_xml.name
|
17
|
+
end
|
18
|
+
|
19
|
+
def delete
|
20
|
+
vapp = entity_xml
|
21
|
+
vapp_name = name
|
22
|
+
|
23
|
+
if is_status?(vapp, :POWERED_ON)
|
24
|
+
fail CloudError,
|
25
|
+
"vApp #{vapp_name} is powered on, power-off before deleting."
|
26
|
+
end
|
27
|
+
|
28
|
+
wait_for_running_tasks(vapp, "VApp #{vapp_name}")
|
29
|
+
|
30
|
+
Config.logger.info "Deleting vApp #{vapp_name}."
|
31
|
+
monitor_task(connection.delete(vapp.remove_link),
|
32
|
+
@session.time_limit[:delete_vapp]) do |task|
|
33
|
+
Config.logger.info "vApp #{vapp_name} deleted."
|
34
|
+
return task
|
35
|
+
end
|
36
|
+
|
37
|
+
fail ApiRequestError,
|
38
|
+
"Fail to delete vApp #{vapp_name}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def recompose_from_vapp_template(catalog_name, template_name)
|
42
|
+
recompose_vapp_link = get_recompose_vapp_link
|
43
|
+
|
44
|
+
Config.logger.info "Recomposing from template '#{template_name}' in catalog '#{catalog_name}'."
|
45
|
+
catalog = find_catalog_by_name catalog_name
|
46
|
+
|
47
|
+
template = catalog.find_vapp_template_by_name template_name
|
48
|
+
|
49
|
+
task = connection.post recompose_vapp_link.href,
|
50
|
+
recompose_from_vapp_template_param(template)
|
51
|
+
|
52
|
+
monitor_task task, @session.time_limit[:recompose_vapp]
|
53
|
+
Config.logger.info "vApp #{name} is recomposed."
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
def vms
|
58
|
+
entity_xml.vms.map do |vm|
|
59
|
+
VCloudSdk::VM.new(@session, vm.href)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def list_vms
|
64
|
+
entity_xml.vms.map do |vm|
|
65
|
+
vm.name
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def find_vm_by_name(name)
|
70
|
+
entity_xml.vms.each do |vm|
|
71
|
+
return VCloudSdk::VM.new(@session, vm.href) if vm.name == name
|
72
|
+
end
|
73
|
+
|
74
|
+
fail ObjectNotFoundError, "VM '#{name}' is not found"
|
75
|
+
end
|
76
|
+
|
77
|
+
def remove_vm_by_name(vm_name)
|
78
|
+
target_vm = find_vm_by_name vm_name
|
79
|
+
recompose_vapp_link = get_recompose_vapp_link
|
80
|
+
|
81
|
+
task = connection.post recompose_vapp_link.href,
|
82
|
+
remove_vm_param(target_vm)
|
83
|
+
|
84
|
+
monitor_task task, @session.time_limit[:recompose_vapp]
|
85
|
+
Config.logger.info "VM #{vm_name} is removed."
|
86
|
+
self
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def recompose_from_vapp_template_param(template)
|
92
|
+
Xml::WrapperFactory.create_instance("RecomposeVAppParams").tap do |params|
|
93
|
+
params.name = name
|
94
|
+
params.all_eulas_accepted = true
|
95
|
+
params.add_source_item template.href
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def get_recompose_vapp_link
|
100
|
+
recompose_vapp_link = connection
|
101
|
+
.get(@link)
|
102
|
+
.recompose_vapp_link
|
103
|
+
|
104
|
+
if recompose_vapp_link.nil?
|
105
|
+
# We are able to recompose vapp when it is suspended or powered off
|
106
|
+
# If vapp is powered on, throw exception
|
107
|
+
fail CloudError,
|
108
|
+
"VApp is in status of '#{status}' and can not be recomposed"
|
109
|
+
end
|
110
|
+
|
111
|
+
recompose_vapp_link
|
112
|
+
end
|
113
|
+
|
114
|
+
def remove_vm_param(vm)
|
115
|
+
Xml::WrapperFactory.create_instance("RecomposeVAppParams").tap do |params|
|
116
|
+
params.name = name
|
117
|
+
params.all_eulas_accepted = true
|
118
|
+
params.add_delete_item vm.href
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,210 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
require "uri"
|
3
|
+
require_relative "vdc_storage_profile"
|
4
|
+
require_relative "vapp"
|
5
|
+
require_relative "infrastructure"
|
6
|
+
require_relative "resources"
|
7
|
+
require_relative "cpu"
|
8
|
+
require_relative "disk"
|
9
|
+
require_relative "memory"
|
10
|
+
require_relative "network"
|
11
|
+
require_relative "edge_gateway"
|
12
|
+
|
13
|
+
module VCloudSdk
|
14
|
+
class VDC
|
15
|
+
include Infrastructure
|
16
|
+
|
17
|
+
extend Forwardable
|
18
|
+
def_delegators :@vdc_xml_obj,
|
19
|
+
:name, :upload_link, :upload_media_link,
|
20
|
+
:instantiate_vapp_template_link
|
21
|
+
|
22
|
+
BUS_TYPE = {
|
23
|
+
"scsi" => Xml::HARDWARE_TYPE[:SCSI_CONTROLLER]
|
24
|
+
}
|
25
|
+
|
26
|
+
BUS_SUB_TYPE = {
|
27
|
+
"lsilogic" => Xml::BUS_SUB_TYPE[:LSILOGIC]
|
28
|
+
}
|
29
|
+
|
30
|
+
private_constant :BUS_TYPE, :BUS_SUB_TYPE
|
31
|
+
|
32
|
+
def initialize(session, vdc_xml_obj)
|
33
|
+
@session = session
|
34
|
+
@vdc_xml_obj = vdc_xml_obj
|
35
|
+
end
|
36
|
+
|
37
|
+
def storage_profiles
|
38
|
+
storage_profile_records.map do |storage_profile|
|
39
|
+
VCloudSdk::VdcStorageProfile.new(storage_profile)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def list_storage_profiles
|
44
|
+
storage_profile_records.map do |storage_profile|
|
45
|
+
storage_profile.name
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def find_storage_profile_by_name(name)
|
50
|
+
storage_profile_records.each do |storage_profile|
|
51
|
+
if storage_profile.name == name
|
52
|
+
return VCloudSdk::VdcStorageProfile.new(storage_profile)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
fail ObjectNotFoundError, "Storage profile '#{name}' is not found"
|
57
|
+
end
|
58
|
+
|
59
|
+
def vapps
|
60
|
+
@vdc_xml_obj.vapps.map do |vapp_link|
|
61
|
+
VCloudSdk::VApp.new(@session, vapp_link)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def list_vapps
|
66
|
+
@vdc_xml_obj.vapps.map do |vapp_link|
|
67
|
+
vapp_link.name
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def find_vapp_by_name(name)
|
72
|
+
@vdc_xml_obj.vapps.each do |vapp_link|
|
73
|
+
if vapp_link.name == name
|
74
|
+
return VCloudSdk::VApp.new(@session, vapp_link)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
fail ObjectNotFoundError, "VApp '#{name}' is not found"
|
79
|
+
end
|
80
|
+
|
81
|
+
def resources
|
82
|
+
cpu = VCloudSdk::CPU.new(@vdc_xml_obj.available_cpu_cores)
|
83
|
+
memory = VCloudSdk::Memory.new(@vdc_xml_obj.available_memory_mb)
|
84
|
+
VCloudSdk::Resources.new(cpu, memory)
|
85
|
+
end
|
86
|
+
|
87
|
+
def networks
|
88
|
+
@session.org.networks.map do |network_link|
|
89
|
+
VCloudSdk::Network.new(@session, network_link)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def list_networks
|
94
|
+
@session.org.networks.map do |network_link|
|
95
|
+
network_link.name
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def find_network_by_name(name)
|
100
|
+
@session.org.networks.each do |network_link|
|
101
|
+
if network_link.name == name
|
102
|
+
return VCloudSdk::Network.new(@session, network_link)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
fail ObjectNotFoundError, "Network '#{name}' is not found"
|
107
|
+
end
|
108
|
+
|
109
|
+
def edge_gateways
|
110
|
+
connection
|
111
|
+
.get(@vdc_xml_obj.edge_gateways_link)
|
112
|
+
.edge_gateway_records
|
113
|
+
.map do |edge_gateway_link|
|
114
|
+
VCloudSdk::EdgeGateway.new(@session, edge_gateway_link.href)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def disks
|
119
|
+
@vdc_xml_obj.disks.map do |disk_link|
|
120
|
+
VCloudSdk::Disk.new(@session, disk_link)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def list_disks
|
125
|
+
@vdc_xml_obj.disks.map do |disk_link|
|
126
|
+
disk_link.name
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def find_disks_by_name(name)
|
131
|
+
disks = @vdc_xml_obj
|
132
|
+
.disks
|
133
|
+
.select { |disk_link| disk_link.name == name }
|
134
|
+
.map { |disk_link| VCloudSdk::Disk.new(@session, disk_link.href) }
|
135
|
+
|
136
|
+
if disks.empty?
|
137
|
+
fail ObjectNotFoundError, "Disk '#{name}' is not found"
|
138
|
+
end
|
139
|
+
|
140
|
+
disks
|
141
|
+
end
|
142
|
+
|
143
|
+
def disk_exists?(name)
|
144
|
+
disks.any? do |disk|
|
145
|
+
disk.name == name
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def create_disk(
|
150
|
+
name,
|
151
|
+
size_mb,
|
152
|
+
vm = nil,
|
153
|
+
bus_type = "scsi",
|
154
|
+
bus_sub_type = "lsilogic")
|
155
|
+
|
156
|
+
fail(CloudError,
|
157
|
+
"Invalid size in MB #{size_mb}") if size_mb <= 0
|
158
|
+
|
159
|
+
bus_type = BUS_TYPE[bus_type.downcase]
|
160
|
+
fail(CloudError,
|
161
|
+
"Invalid bus type!") unless bus_type
|
162
|
+
|
163
|
+
bus_sub_type = BUS_SUB_TYPE[bus_sub_type.downcase]
|
164
|
+
fail(CloudError,
|
165
|
+
"Invalid bus sub type!") unless bus_sub_type
|
166
|
+
|
167
|
+
Config
|
168
|
+
.logger
|
169
|
+
.info "Creating independent disk #{name} of #{size_mb}MB."
|
170
|
+
|
171
|
+
disk = connection.post(@vdc_xml_obj.add_disk_link,
|
172
|
+
disk_create_params(name, size_mb, bus_type, bus_sub_type, vm),
|
173
|
+
Xml::MEDIA_TYPE[:DISK_CREATE_PARAMS])
|
174
|
+
|
175
|
+
wait_for_running_tasks(disk, "Disk #{name}")
|
176
|
+
|
177
|
+
VCloudSdk::Disk.new(@session, disk.href)
|
178
|
+
end
|
179
|
+
|
180
|
+
def storage_profile_xml_node(name)
|
181
|
+
return nil if name.nil?
|
182
|
+
|
183
|
+
storage_profile = @vdc_xml_obj.storage_profile(name)
|
184
|
+
unless storage_profile
|
185
|
+
fail ObjectNotFoundError,
|
186
|
+
"Storage profile '#{name}' does not exist"
|
187
|
+
end
|
188
|
+
|
189
|
+
storage_profile
|
190
|
+
end
|
191
|
+
|
192
|
+
private
|
193
|
+
|
194
|
+
def storage_profile_records
|
195
|
+
connection
|
196
|
+
.get("/api/query?type=orgVdcStorageProfile&filter=vdcName==#{URI.encode(name)}")
|
197
|
+
.org_vdc_storage_profile_records
|
198
|
+
end
|
199
|
+
|
200
|
+
def disk_create_params(name, size_mb, bus_type, bus_sub_type, vm)
|
201
|
+
Xml::WrapperFactory.create_instance("DiskCreateParams").tap do |params|
|
202
|
+
params.name = name
|
203
|
+
params.size_bytes = size_mb * 1024 * 1024 # VCD expects bytes
|
204
|
+
params.bus_type = bus_type
|
205
|
+
params.bus_sub_type = bus_sub_type
|
206
|
+
params.add_locality(connection.get(vm.href)) if vm # Use xml form of vm
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|