ruby_vcloud_sdk 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,7 @@
1
1
  require_relative "infrastructure"
2
2
  require_relative "powerable"
3
3
  require_relative "vm"
4
+ require_relative "network_config"
4
5
 
5
6
  module VCloudSdk
6
7
  class VApp
@@ -28,10 +29,10 @@ module VCloudSdk
28
29
  wait_for_running_tasks(vapp, "VApp #{vapp_name}")
29
30
 
30
31
  Config.logger.info "Deleting vApp #{vapp_name}."
31
- monitor_task(connection.delete(vapp.remove_link),
32
+ monitor_task(connection.delete(vapp.remove_link.href),
32
33
  @session.time_limit[:delete_vapp]) do |task|
33
34
  Config.logger.info "vApp #{vapp_name} deleted."
34
- return task
35
+ return
35
36
  end
36
37
 
37
38
  fail ApiRequestError,
@@ -66,6 +67,12 @@ module VCloudSdk
66
67
  end
67
68
  end
68
69
 
70
+ def vm_exists?(name)
71
+ entity_xml.vms.any? do |vm|
72
+ vm.name == name
73
+ end
74
+ end
75
+
69
76
  def find_vm_by_name(name)
70
77
  entity_xml.vms.each do |vm|
71
78
  return VCloudSdk::VM.new(@session, vm.href) if vm.name == name
@@ -113,10 +120,11 @@ module VCloudSdk
113
120
  payload,
114
121
  Xml::MEDIA_TYPE[:NETWORK_CONFIG_SECTION])
115
122
  monitor_task(task)
123
+ self
116
124
  end
117
125
 
118
126
  def delete_network_by_name(name)
119
- unless list_networks.any? { |network_name| network_name == name}
127
+ unless list_networks.any? { |network_name| network_name == name }
120
128
  fail ObjectNotFoundError,
121
129
  "Network '#{name}' is not found"
122
130
  end
@@ -134,7 +142,7 @@ module VCloudSdk
134
142
  payload,
135
143
  Xml::MEDIA_TYPE[:NETWORK_CONFIG_SECTION])
136
144
  monitor_task(task)
137
- nil
145
+ self
138
146
  end
139
147
 
140
148
  private
@@ -19,7 +19,7 @@ module VCloudSdk
19
19
  :name, :upload_link, :upload_media_link,
20
20
  :instantiate_vapp_template_link
21
21
 
22
- public :find_network_by_name
22
+ public :find_network_by_name, :network_exists?
23
23
 
24
24
  def initialize(session, link)
25
25
  @session = session
@@ -48,6 +48,12 @@ module VCloudSdk
48
48
  fail ObjectNotFoundError, "Storage profile '#{name}' is not found"
49
49
  end
50
50
 
51
+ def storage_profile_exists?(name)
52
+ storage_profile_records.any? do |storage_profile|
53
+ storage_profile.name == name
54
+ end
55
+ end
56
+
51
57
  def vapps
52
58
  entity_xml.vapps.map do |vapp_link|
53
59
  VCloudSdk::VApp.new(@session, vapp_link)
@@ -70,6 +76,12 @@ module VCloudSdk
70
76
  fail ObjectNotFoundError, "VApp '#{name}' is not found"
71
77
  end
72
78
 
79
+ def vapp_exists?(name)
80
+ entity_xml.vapps.any? do |vapp|
81
+ vapp.name == name
82
+ end
83
+ end
84
+
73
85
  def resources
74
86
  cpu = VCloudSdk::CPU.new(entity_xml.available_cpu_cores)
75
87
  memory = VCloudSdk::Memory.new(entity_xml.available_memory_mb)
@@ -123,8 +135,8 @@ module VCloudSdk
123
135
  end
124
136
 
125
137
  def disk_exists?(name)
126
- disks.any? do |disk|
127
- disk.name == name
138
+ list_disks.any? do |disk_name|
139
+ disk_name == name
128
140
  end
129
141
  end
130
142
 
@@ -165,7 +177,7 @@ module VCloudSdk
165
177
  "#{disks.size} disks with name #{name} were found" if disks.size > 1
166
178
 
167
179
  delete_single_disk(disks.first)
168
- nil
180
+ self
169
181
  end
170
182
 
171
183
  def delete_all_disks_by_name(name)
@@ -182,7 +194,7 @@ module VCloudSdk
182
194
 
183
195
  fail CloudError,
184
196
  "Failed to delete one or more of the disks with name '#{name}'. Check logs for details." unless success
185
- nil
197
+ self
186
198
  end
187
199
 
188
200
  def storage_profile_xml_node(name)
@@ -1,3 +1,3 @@
1
1
  module VCloudSdk
2
- VERSION = '0.5.0'
2
+ VERSION = '0.7.0'
3
3
  end
@@ -2,6 +2,7 @@ require "forwardable"
2
2
  require_relative "infrastructure"
3
3
  require_relative "powerable"
4
4
  require_relative "internal_disk"
5
+ require_relative "nic"
5
6
 
6
7
  module VCloudSdk
7
8
  class VM
@@ -92,6 +93,19 @@ module VCloudSdk
92
93
  .map { |network_connection| network_connection.network }
93
94
  end
94
95
 
96
+ def nics
97
+ primary_index = entity_xml
98
+ .network_connection_section
99
+ .primary_network_connection_index
100
+ entity_xml
101
+ .network_connection_section
102
+ .network_connections
103
+ .map do |network_connection|
104
+ VCloudSdk::NIC.new(network_connection,
105
+ network_connection.network_connection_index == primary_index)
106
+ end
107
+ end
108
+
95
109
  def independent_disks
96
110
  hardware_section = entity_xml.hardware_section
97
111
  disks = []
@@ -122,10 +136,10 @@ module VCloudSdk
122
136
  task = connection.post(entity_xml.attach_disk_link.href,
123
137
  disk_attach_or_detach_params(disk),
124
138
  Xml::MEDIA_TYPE[:DISK_ATTACH_DETACH_PARAMS])
125
- task = monitor_task(task)
139
+ monitor_task(task)
126
140
 
127
141
  Config.logger.info "Disk '#{disk.name}' is attached to VM '#{name}'"
128
- task
142
+ self
129
143
  end
130
144
 
131
145
  def detach_disk(disk)
@@ -143,10 +157,10 @@ module VCloudSdk
143
157
  task = connection.post(entity_xml.detach_disk_link.href,
144
158
  disk_attach_or_detach_params(disk),
145
159
  Xml::MEDIA_TYPE[:DISK_ATTACH_DETACH_PARAMS])
146
- task = monitor_task(task)
160
+ monitor_task(task)
147
161
 
148
162
  Config.logger.info "Disk '#{disk.name}' is detached from VM '#{name}'"
149
- task
163
+ self
150
164
  end
151
165
 
152
166
  def insert_media(catalog_name, media_file_name)
@@ -163,6 +177,7 @@ module VCloudSdk
163
177
  media_insert_or_eject_params(media),
164
178
  Xml::MEDIA_TYPE[:MEDIA_INSERT_EJECT_PARAMS])
165
179
  monitor_task(task)
180
+ self
166
181
  end
167
182
 
168
183
  def eject_media(catalog_name, media_file_name)
@@ -179,6 +194,7 @@ module VCloudSdk
179
194
  media_insert_or_eject_params(media),
180
195
  Xml::MEDIA_TYPE[:MEDIA_INSERT_EJECT_PARAMS])
181
196
  monitor_task(task)
197
+ self
182
198
  end
183
199
 
184
200
  def add_nic(
@@ -203,7 +219,7 @@ module VCloudSdk
203
219
  fail CloudError,
204
220
  "VM #{name} is powered-on and cannot add NIC." if is_status?(payload, :POWERED_ON)
205
221
 
206
- nic_index = list_networks.size # nic index begins with 0
222
+ nic_index = add_nic_index
207
223
 
208
224
  Config.logger
209
225
  .info("Adding NIC #{nic_index}, network #{network_name} using mode '#{ip_addressing_mode}' #{ip.nil? ? "" : "IP: #{ip}"}")
@@ -230,6 +246,20 @@ module VCloudSdk
230
246
  payload,
231
247
  Xml::MEDIA_TYPE[:VM])
232
248
  monitor_task(task)
249
+ self
250
+ end
251
+
252
+ def delete_nics(*nics)
253
+ payload = entity_xml
254
+ fail CloudError,
255
+ "VM #{name} is powered-on and cannot delete NIC." if is_status?(payload, :POWERED_ON)
256
+
257
+ payload.delete_nics(*nics)
258
+ task = connection.post(payload.reconfigure_link.href,
259
+ payload,
260
+ Xml::MEDIA_TYPE[:VM])
261
+ monitor_task(task)
262
+ self
233
263
  end
234
264
 
235
265
  def product_section_properties
@@ -240,8 +270,8 @@ module VCloudSdk
240
270
  end
241
271
 
242
272
  def product_section_properties=(properties)
243
- Config.logger
244
- .info("Updating VM #{name} production sections with properties: #{properties.pretty_inspect}")
273
+ Config.logger.info(
274
+ "Updating VM #{name} production sections with properties: #{properties.inspect}")
245
275
  task = connection.put(entity_xml.product_sections_link.href,
246
276
  product_section_list_params(properties),
247
277
  Xml::MEDIA_TYPE[:PRODUCT_SECTIONS])
@@ -288,10 +318,35 @@ module VCloudSdk
288
318
  payload,
289
319
  Xml::MEDIA_TYPE[:VM])
290
320
  monitor_task(task)
321
+ self
322
+ end
323
+
324
+ def delete_internal_disk_by_name(name)
325
+ payload = entity_xml
326
+
327
+ unless payload.delete_hard_disk?(name)
328
+ fail ObjectNotFoundError, "Internal disk '#{name}' is not found"
329
+ end
330
+
331
+ task = connection.post(payload.reconfigure_link.href,
332
+ payload,
333
+ Xml::MEDIA_TYPE[:VM])
334
+ monitor_task(task)
335
+ self
291
336
  end
292
337
 
293
338
  private
294
339
 
340
+ def add_nic_index
341
+ # nic index begins with 0
342
+ i = 0
343
+ nic_indexes = nics.map { |n| n.nic_index }
344
+ while (nic_indexes.include?(i))
345
+ i += 1
346
+ end
347
+ i
348
+ end
349
+
295
350
  def disk_attach_or_detach_params(disk)
296
351
  Xml::WrapperFactory
297
352
  .create_instance("DiskAttachOrDetachParams")
@@ -42,24 +42,69 @@ module VCloudSdk
42
42
  @local_exists = true
43
43
 
44
44
  locality.each do |k,v|
45
- node_sp = create_child("SourcedVmInstantiationParams")
45
+ node_sp = create_child("SourcedVmInstantiationParams",
46
+ namespace.prefix,
47
+ namespace.href)
46
48
  is_source_delete.node.after(node_sp)
47
49
 
48
- node_sv = add_child("Source", nil, nil, node_sp)
50
+ node_sv = add_child("Source",
51
+ namespace.prefix,
52
+ namespace.href,
53
+ node_sp)
49
54
  node_sv["type"] = k.type
50
55
  node_sv["name"] = k.name
51
56
  node_sv["href"] = k.href
52
57
 
53
- node_lp = create_child("LocalityParams")
58
+ node_lp = create_child("LocalityParams",
59
+ namespace.prefix,
60
+ namespace.href)
54
61
  node_sv.after(node_lp)
55
62
 
56
- node_re = add_child("ResourceEntity", nil, nil, node_lp)
63
+ node_re = add_child("ResourceEntity",
64
+ namespace.prefix,
65
+ namespace.href,
66
+ node_lp)
57
67
  node_re["type"] = v.type
58
68
  node_re["name"] = v.name
59
69
  node_re["href"] = v.href
60
70
  end
61
71
  end
62
72
 
73
+ def set_network_config(vapp_network_name, vdc_netowrk_href, fence_mode)
74
+ instantiation_param = get_nodes("InstantiationParams").first
75
+
76
+ net_config_section = add_child("NetworkConfigSection",
77
+ namespace.prefix,
78
+ namespace.href,
79
+ instantiation_param.node)
80
+
81
+ ovf_info = add_child("Info", "ovf", OVF, net_config_section)
82
+ ovf_info.content = "Configuration parameters for logical networks"
83
+
84
+ network_config = create_child("NetworkConfig",
85
+ namespace.prefix,
86
+ namespace.href)
87
+ ovf_info.after(network_config)
88
+ network_config["networkName"] = vapp_network_name
89
+
90
+ configuration = add_child("Configuration",
91
+ namespace.prefix,
92
+ namespace.href,
93
+ network_config)
94
+
95
+ parent_network = add_child("ParentNetwork",
96
+ namespace.prefix,
97
+ namespace.href,
98
+ configuration)
99
+ parent_network["href"] = vdc_netowrk_href
100
+
101
+ fence_node = create_child("FenceMode",
102
+ namespace.prefix,
103
+ namespace.href)
104
+ parent_network.after(fence_node)
105
+ fence_node.content = fence_mode
106
+ end
107
+
63
108
  private
64
109
 
65
110
  def is_source_delete
@@ -1,6 +1,5 @@
1
1
  module VCloudSdk
2
2
  module Xml
3
-
4
3
  class NetworkConnection < Wrapper
5
4
  def network
6
5
  @root["network"]
@@ -16,15 +15,18 @@ module VCloudSdk
16
15
  end
17
16
 
18
17
  def network_connection_index=(value)
19
- unless get_nodes("NetworkConnectionIndex").first
18
+ index_node = get_nodes("NetworkConnectionIndex").first
19
+ if index_node.nil?
20
20
  index_node = create_child("NetworkConnectionIndex")
21
21
  add_child(index_node)
22
22
  end
23
- get_nodes("NetworkConnectionIndex").first.content = value
23
+ index_node.content = value
24
24
  end
25
25
 
26
26
  def ip_address
27
- get_nodes("IpAddress").first.content
27
+ ip_address_node = get_nodes("IpAddress").first
28
+ return if ip_address_node.nil?
29
+ ip_address_node.content
28
30
  end
29
31
 
30
32
  def ip_address=(value)
@@ -59,13 +61,13 @@ module VCloudSdk
59
61
  end
60
62
 
61
63
  def ip_address_allocation_mode=(value)
62
- if !IP_ADDRESSING_MODE.values.include?(value)
63
- raise ArgumentError, "Invalid IP addressing mode. Valid modes " +
64
- "are: #{IP_ADDRESSING_MODE.values.join(" ")}"
64
+ unless IP_ADDRESSING_MODE.values.include?(value)
65
+ fail ArgumentError,
66
+ "Invalid IP addressing mode. Valid modes " +
67
+ "are: #{IP_ADDRESSING_MODE.values.join(" ")}"
65
68
  end
66
69
  get_nodes("IpAddressAllocationMode").first.content = value
67
70
  end
68
71
  end
69
-
70
72
  end
71
73
  end
@@ -1,6 +1,5 @@
1
1
  module VCloudSdk
2
2
  module Xml
3
-
4
3
  class NetworkConnectionSection < Wrapper
5
4
  def add_item(item)
6
5
  link_node = get_nodes("Link").first
@@ -12,10 +11,11 @@ module VCloudSdk
12
11
  end
13
12
 
14
13
  def network_connection(index)
15
- net = network_connections.find {
16
- |n| n.network_connection_index == index.to_s }
14
+ net = network_connections.find do |n|
15
+ n.network_connection_index == index.to_s
16
+ end
17
17
  unless net
18
- raise ObjectNotFoundError, "Network connection #{index} does not exist."
18
+ fail ObjectNotFoundError, "Network connection #{index} does not exist."
19
19
  end
20
20
  net
21
21
  end
@@ -38,26 +38,27 @@ module VCloudSdk
38
38
  connection = network_connection(index)
39
39
  if connection
40
40
  connection.node.remove
41
- reconcile_primary_network()
41
+ reconcile_primary_network
42
42
  else
43
- raise ObjectNotFoundError,
44
- "Cannot remove network connection #{index}: does not exist."
43
+ fail ObjectNotFoundError,
44
+ "Cannot remove network connection #{index}: does not exist."
45
45
  end
46
46
  end
47
47
 
48
48
  private
49
49
 
50
- def reconcile_primary_network()
50
+ def reconcile_primary_network
51
51
  new_primary = network_connections.first
52
52
  if new_primary
53
- self.primary_network_connection_index =
54
- new_primary.network_connection_index
53
+ primary_index = new_primary.network_connection_index
54
+ self.primary_network_connection_index = primary_index
55
+ primary_index
55
56
  else
56
57
  primary = get_nodes("PrimaryNetworkConnectionIndex").first
57
58
  primary.node.remove if primary
59
+ nil
58
60
  end
59
61
  end
60
62
  end
61
-
62
63
  end
63
64
  end
@@ -1,6 +1,12 @@
1
1
  module VCloudSdk
2
2
  module Xml
3
3
  class Org < Wrapper
4
+ def vdcs
5
+ get_nodes(XML_TYPE[:LINK],
6
+ { type: MEDIA_TYPE[:VDC] },
7
+ true)
8
+ end
9
+
4
10
  def vdc_link(name)
5
11
  get_nodes(XML_TYPE[:LINK],
6
12
  { type: MEDIA_TYPE[:VDC],
@@ -5,31 +5,56 @@ module VCloudSdk
5
5
  property_node = add_child("Property",
6
6
  ovf_namespace_prefix,
7
7
  OVF)
8
- property_node["#{ovf_namespace_prefix}:type"] = property["type"].nil? ? "string" : property["type"]
8
+ property_node["#{ovf_namespace_prefix}:type"] =
9
+ property["type"].nil? ? "string" : property["type"]
9
10
  property_node["#{ovf_namespace_prefix}:key"] = property["key"]
10
11
  property_node["#{ovf_namespace_prefix}:value"] = property["value"]
11
- property_node["#{ovf_namespace_prefix}:password"] = property["password"] if property["password"]
12
+ property_node["#{ovf_namespace_prefix}:password"] =
13
+ property["password"] if property["password"] # default to false
14
+ property_node["#{ovf_namespace_prefix}:userConfigurable"] =
15
+ property["userConfigurable"] if property["userConfigurable"] # default to false
12
16
 
13
- unless property["Label"].nil?
14
- label_node = add_child("Label", ovf_namespace_prefix, OVF, property_node)
15
- label_node.content = property["Label"]
17
+ %w[Label Description].each do |k|
18
+ add_child_node_property(property_node, property, k)
19
+ end
20
+
21
+ if property["value"].nil?
22
+ value_node = add_child("Value", ovf_namespace_prefix, OVF, property_node)
23
+ value_node.attribute("value").value = property["value"]
16
24
  end
17
25
  end
18
26
 
19
27
  def properties
20
28
  get_nodes("Property", nil, true, OVF).map do |property_node|
21
29
  property = {}
22
- property["type"] = property_node.attribute("type").content
23
- property["key"] = property_node.attribute("key").content
24
- property["value"] = property_node.attribute("value").content
25
- property["password"] = property_node.attribute("password").content
30
+ %w[type key value password userConfigurable].each do |k|
31
+ attr = property_node.attribute(k)
32
+ property[k] = attr.nil? ? "" : attr.content
33
+ end
26
34
 
27
- label_node = property_node.get_nodes("Label", nil, true, OVF).first
28
- property["Label"] = label_node.content unless label_node.nil?
35
+ %w[Label Description].each do |k|
36
+ read_child_node_property(property_node, property, k)
37
+ end
29
38
 
39
+ value_node = property_node.get_nodes("Value", nil, true, OVF).first
40
+ property["value"] = value_node.attribute("value").content unless value_node.nil?
30
41
  property
31
42
  end
32
43
  end
44
+
45
+ private
46
+
47
+ def add_child_node_property(property_node, property, key)
48
+ unless property[key].nil?
49
+ child_node = add_child(key, ovf_namespace_prefix, OVF, property_node)
50
+ child_node.content = property[key]
51
+ end
52
+ end
53
+
54
+ def read_child_node_property(property_node, property, key)
55
+ child_node = property_node.get_nodes(key, nil, true, OVF).first
56
+ property[key] = child_node.content unless child_node.nil?
57
+ end
33
58
  end
34
59
  end
35
60
  end
@@ -35,8 +35,9 @@ module VCloudSdk
35
35
  end
36
36
 
37
37
  def nics
38
- items = hardware.find_all {|h| h.get_rasd_content(
39
- RASD_TYPES[:RESOURCE_TYPE]) == HARDWARE_TYPE[:NIC] }
38
+ items = hardware.select do |h|
39
+ h.get_rasd_content(RASD_TYPES[:RESOURCE_TYPE]) == HARDWARE_TYPE[:NIC]
40
+ end
40
41
  items.map { |i| NicItemWrapper.new(i) }
41
42
  end
42
43
 
@@ -45,14 +46,29 @@ module VCloudSdk
45
46
  end
46
47
 
47
48
  def remove_hw(hw_type, index)
48
- item = hardware.find { |h|
49
+ index = index.to_s
50
+ item = hardware.find do |h|
49
51
  h.get_rasd_content(RASD_TYPES[:RESOURCE_TYPE]) == hw_type &&
50
- h.get_rasd_content(RASD_TYPES[:ADDRESS_ON_PARENT]) == index }
52
+ h.get_rasd_content(RASD_TYPES[:ADDRESS_ON_PARENT]) == index
53
+ end
51
54
  if item
52
55
  item.node.remove
53
56
  else
54
- raise ObjectNotFoundError,
55
- "Cannot remove hw item #{hw_type}:#{index}, does not exist."
57
+ fail ObjectNotFoundError,
58
+ "Cannot remove hw item #{hw_type}:#{index}, does not exist."
59
+ end
60
+ end
61
+
62
+ def reconcile_primary_network(primary_index)
63
+ primary_index = primary_index.to_s
64
+ hardware.select do |item|
65
+ item.get_rasd_content(RASD_TYPES[:RESOURCE_TYPE]) == HARDWARE_TYPE[:NIC]
66
+ end.each do |item|
67
+ if item.get_rasd_content(RASD_TYPES[:ADDRESS_ON_PARENT]) == primary_index
68
+ item.get_rasd(RASD_TYPES[:CONNECTION]).attribute("primaryNetworkConnection").value = "true"
69
+ else
70
+ item.get_rasd(RASD_TYPES[:CONNECTION]).attribute("primaryNetworkConnection").value = "false"
71
+ end
56
72
  end
57
73
  end
58
74
 
@@ -117,6 +117,17 @@ module VCloudSdk
117
117
  "busType", VCLOUD_NAMESPACE)] = bus_type
118
118
  end
119
119
 
120
+ def delete_hard_disk?(disk_name)
121
+ hardware_section.hard_disks.each do |disk|
122
+ if disk.element_name == disk_name
123
+ disk.node.remove
124
+ return true
125
+ end
126
+ end
127
+
128
+ false
129
+ end
130
+
120
131
  def change_cpu_count(quantity)
121
132
  @logger.debug("Updating CPU count on vm #{name} to #{quantity} ")
122
133
  item = hardware_section.cpu
@@ -132,7 +143,7 @@ module VCloudSdk
132
143
  # Deletes NIC from VM. Accepts variable number of arguments for NICs.
133
144
  # To delete all NICs from VM use the splat operator
134
145
  # ex: delete_nic(vm, *vm.hardware_section.nics)
135
- def delete_nic(*nics)
146
+ def delete_nics(*nics)
136
147
  # Trying to remove a NIC without removing the network connection
137
148
  # first will cause an error. Removing the network connection of a NIC
138
149
  # in the NetworkConnectionSection will automatically delete the NIC.
@@ -141,8 +152,9 @@ module VCloudSdk
141
152
  nics.each do |nic|
142
153
  nic_index = nic.nic_index
143
154
  @logger.info("Removing NIC #{nic_index} from VM #{name}")
144
- net_conn_section.remove_network_connection(nic_index)
155
+ primary_index = net_conn_section.remove_network_connection(nic_index)
145
156
  vhw_section.remove_nic(nic_index)
157
+ vhw_section.reconcile_primary_network(primary_index) if primary_index
146
158
  end
147
159
  end
148
160