vcloud-rest 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/CHANGELOG.md +22 -0
  2. data/lib/vcloud-rest/connection.rb +145 -13
  3. metadata +2 -2
data/CHANGELOG.md CHANGED
@@ -1,13 +1,35 @@
1
1
  Changes
2
2
  ==
3
+ 2012-12-21 (0.2.0)
4
+ --
5
+
6
+ FEATURES:
7
+
8
+ * Allow Task tracking for vApp startup & shutdown
9
+ * Improve error message for operations on vApp not running
10
+ * Improve error message for access forbidden
11
+ * Extend vApp status codes handling
12
+ * Add method to show VM's details
13
+ * Basic vApp network configuration
14
+ * Basic VM network configuration
15
+ * Basic Guest Customization configuration
16
+
17
+ FIXES:
18
+
19
+ * Show catalog item: fix ID parsing
20
+
3
21
  2012-12-19 (0.1.1)
4
22
  --
5
23
 
24
+ FIXES:
25
+
6
26
  * Fix gemspec URL
7
27
 
8
28
  2012-12-19 (0.1.0)
9
29
  --
10
30
 
31
+ FEATURES:
32
+
11
33
  * Add support for main operations:
12
34
  * login/logout
13
35
  * organization _list/show_
@@ -184,7 +184,7 @@ module VCloudClient
184
184
 
185
185
  items = {}
186
186
  response.css("Entity[type='application/vnd.vmware.vcloud.vAppTemplate+xml']").each do |item|
187
- items[item['name']] = item['href'].gsub("#{@api_url}/vAppTemplate/", "")
187
+ items[item['name']] = item['href'].gsub("#{@api_url}/vAppTemplate/vappTemplate-", "")
188
188
  end
189
189
 
190
190
  [description, items]
@@ -211,7 +211,7 @@ module VCloudClient
211
211
  vapp_node = response.css('VApp').first
212
212
  if vapp_node
213
213
  name = vapp_node['name']
214
- status = convert_status(vapp_node['status'])
214
+ status = convert_vapp_status(vapp_node['status'])
215
215
  end
216
216
 
217
217
  description = response.css("Description").first
@@ -225,7 +225,7 @@ module VCloudClient
225
225
  vms.each do |vm|
226
226
  addresses = vm.css('rasd|Connection').collect{|n| n['ipAddress']}
227
227
  vms_hash[vm['name']] = {:addresses => addresses,
228
- :status => convert_status(vm['status']),
228
+ :status => convert_vapp_status(vm['status']),
229
229
  :id => vm['href'].gsub("#{@api_url}/vApp/vm-", '')
230
230
  }
231
231
  end
@@ -265,8 +265,8 @@ module VCloudClient
265
265
 
266
266
  response, headers = send_request(params, builder.to_xml,
267
267
  "application/vnd.vmware.vcloud.undeployVAppParams+xml")
268
-
269
- response
268
+ task_id = headers[:location].gsub("#{@api_url}/task/", "")
269
+ task_id
270
270
  end
271
271
 
272
272
  ##
@@ -278,8 +278,8 @@ module VCloudClient
278
278
  }
279
279
 
280
280
  response, headers = send_request(params)
281
- # TODO: track Task using headers[:location]
282
- [response, headers]
281
+ task_id = headers[:location].gsub("#{@api_url}/task/", "")
282
+ task_id
283
283
  end
284
284
 
285
285
  ##
@@ -290,7 +290,7 @@ module VCloudClient
290
290
  # - vapp_name: name of the target vapp
291
291
  # - vapp_description: description of the target vapp
292
292
  # - vapp_templateid: ID of the vapp template
293
- def create_vapp_from_template(vdc, vapp_name, vapp_description, vapp_templateid)
293
+ def create_vapp_from_template(vdc, vapp_name, vapp_description, vapp_templateid, poweron=false)
294
294
  builder = Nokogiri::XML::Builder.new do |xml|
295
295
  xml.InstantiateVAppTemplateParams(
296
296
  "xmlns" => "http://www.vmware.com/vcloud/v1.5",
@@ -298,7 +298,7 @@ module VCloudClient
298
298
  "xmlns:ovf" => "http://schemas.dmtf.org/ovf/envelope/1",
299
299
  "name" => vapp_name,
300
300
  "deploy" => "true",
301
- "powerOn" => "true") {
301
+ "powerOn" => poweron) {
302
302
  xml.Description vapp_description
303
303
  xml.Source("href" => "#{@api_url}/vAppTemplate/#{vapp_templateid}")
304
304
  }
@@ -355,6 +355,128 @@ module VCloudClient
355
355
  [status, errormsg, start_time, end_time]
356
356
  end
357
357
 
358
+ ##
359
+ # Set vApp Network Config
360
+ def set_vapp_network_config(vappid, network_name, config={})
361
+ builder = Nokogiri::XML::Builder.new do |xml|
362
+ xml.NetworkConfigSection(
363
+ "xmlns" => "http://www.vmware.com/vcloud/v1.5",
364
+ "xmlns:ovf" => "http://schemas.dmtf.org/ovf/envelope/1") {
365
+ xml['ovf'].Info "Network configuration"
366
+ xml.NetworkConfig("networkName" => network_name) {
367
+ xml.Configuration {
368
+ xml.FenceMode (config[:fence_mode] || 'isolated')
369
+ xml.RetainNetInfoAcrossDeployments (config[:retain_net] || true)
370
+ }
371
+ }
372
+ }
373
+ end
374
+
375
+ params = {
376
+ 'method' => :put,
377
+ 'command' => "/vApp/vapp-#{vappid}/networkConfigSection"
378
+ }
379
+
380
+ response, headers = send_request(params, builder.to_xml, "application/vnd.vmware.vcloud.networkConfigSection+xml")
381
+
382
+ task_id = headers[:location].gsub("#{@api_url}/task/", "")
383
+ task_id
384
+ end
385
+
386
+ ##
387
+ # Set VM Network Config
388
+ def set_vm_network_config(vmid, network_name, config={})
389
+ builder = Nokogiri::XML::Builder.new do |xml|
390
+ xml.NetworkConnectionSection(
391
+ "xmlns" => "http://www.vmware.com/vcloud/v1.5",
392
+ "xmlns:ovf" => "http://schemas.dmtf.org/ovf/envelope/1") {
393
+ xml['ovf'].Info "VM Network configuration"
394
+ xml.PrimaryNetworkConnectionIndex (config[:primary_index] || 0)
395
+ xml.NetworkConnection("network" => network_name, "needsCustomization" => true) {
396
+ xml.NetworkConnectionIndex (config[:network_index] || 0)
397
+ xml.IpAddress config[:ip] if config[:ip]
398
+ xml.IsConnected (config[:is_connected] || true)
399
+ xml.IpAddressAllocationMode config[:ip_allocation_mode] if config[:ip_allocation_mode]
400
+ }
401
+ }
402
+ end
403
+
404
+ params = {
405
+ 'method' => :put,
406
+ 'command' => "/vApp/vm-#{vmid}/networkConnectionSection"
407
+ }
408
+
409
+ response, headers = send_request(params, builder.to_xml, "application/vnd.vmware.vcloud.networkConnectionSection+xml")
410
+
411
+ task_id = headers[:location].gsub("#{@api_url}/task/", "")
412
+ task_id
413
+ end
414
+
415
+
416
+ ##
417
+ # Set VM Guest Customization Config
418
+ def set_vm_guest_customization(vmid, computer_name, config={})
419
+ builder = Nokogiri::XML::Builder.new do |xml|
420
+ xml.GuestCustomizationSection(
421
+ "xmlns" => "http://www.vmware.com/vcloud/v1.5",
422
+ "xmlns:ovf" => "http://schemas.dmtf.org/ovf/envelope/1") {
423
+ xml['ovf'].Info "VM Guest Customization configuration"
424
+ xml.Enabled config[:enabled] if config[:enabled]
425
+ xml.AdminPasswordEnabled config[:admin_passwd_enabled] if config[:admin_passwd_enabled]
426
+ xml.AdminPassword config[:admin_passwd] if config[:admin_passwd]
427
+ xml.ComputerName computer_name
428
+ }
429
+ end
430
+
431
+ params = {
432
+ 'method' => :put,
433
+ 'command' => "/vApp/vm-#{vmid}/guestCustomizationSection"
434
+ }
435
+
436
+ response, headers = send_request(params, builder.to_xml, "application/vnd.vmware.vcloud.guestCustomizationSection+xml")
437
+
438
+ task_id = headers[:location].gsub("#{@api_url}/task/", "")
439
+ task_id
440
+ end
441
+
442
+ ##
443
+ # Show details about a given VM
444
+ def show_vm(vmId)
445
+ params = {
446
+ 'method' => :get,
447
+ 'command' => "/vApp/vm-#{vmId}"
448
+ }
449
+
450
+ response, headers = send_request(params)
451
+
452
+ os_desc = response.css('ovf|OperatingSystemSection ovf|Description').first.text
453
+
454
+ networks = {}
455
+ response.css('NetworkConnection').each do |network|
456
+ ip = network.css('IpAddress').first
457
+ ip = ip.text if ip
458
+
459
+ networks[network['network']] = {
460
+ :index => network.css('NetworkConnectionIndex').first.text,
461
+ :ip => ip,
462
+ :is_connected => network.css('IsConnected').first.text,
463
+ :mac_address => network.css('MACAddress').first.text,
464
+ :ip_allocation_mode => network.css('IpAddressAllocationMode').first.text
465
+ }
466
+ end
467
+
468
+ guest_customizations = {
469
+ :enabled => response.css('GuestCustomizationSection Enabled').first.text,
470
+ :admin_passwd_enabled => response.css('GuestCustomizationSection AdminPasswordEnabled').first.text,
471
+ :admin_passwd_auto => response.css('GuestCustomizationSection AdminPasswordAuto').first.text,
472
+ :admin_passwd => response.css('GuestCustomizationSection AdminPassword').first.text,
473
+ :reset_passwd_required => response.css('GuestCustomizationSection ResetPasswordRequired').first.text,
474
+ :computer_name => response.css('GuestCustomizationSection ComputerName').first.text
475
+ }
476
+
477
+ [os_desc, networks, guest_customizations]
478
+ end
479
+
358
480
  private
359
481
  ##
360
482
  # Sends a synchronous request to the vCloud API and returns the response as parsed XML + headers.
@@ -394,23 +516,33 @@ module VCloudClient
394
516
  when /validation error on field 'id': String value has invalid format or length/
395
517
  raise WrongItemIDError, "Invalid ID specified. Please verify that the item exists and correctly typed."
396
518
  when /The requested operation could not be executed on vApp "(.*)". Stop the vApp and try again/
397
- raise InvalidStateError, "Invalid request. Stop vApp '#{$1}' and try again."
519
+ raise InvalidStateError, "Invalid request because vApp is running. Stop vApp '#{$1}' and try again."
520
+ when /The requested operation could not be executed since vApp "(.*)" is not running/
521
+ raise InvalidStateError, "Invalid request because vApp is stopped. Start vApp '#{$1}' and try again."
398
522
  else
399
523
  raise UnhandledError, "BadRequest - unhandled error: #{message}.\nPlease report this issue."
400
524
  end
525
+ rescue RestClient::Forbidden => e
526
+ body = Nokogiri.parse(e.http_body)
527
+ message = body.css("Error").first["message"]
528
+ raise UnauthorizedAccess, "Operation not permitted: #{message}."
401
529
  end
402
530
  end
403
531
 
404
532
  ##
405
- # Convert status codes into human readable description
406
- def convert_status(status_code)
533
+ # Convert vApp status codes into human readable description
534
+ def convert_vapp_status(status_code)
407
535
  case status_code.to_i
408
- when 3
536
+ when 0
409
537
  'suspended'
538
+ when 3
539
+ 'paused'
410
540
  when 4
411
541
  'running'
412
542
  when 8
413
543
  'stopped'
544
+ when 10
545
+ 'mixed'
414
546
  else
415
547
  "Unknown #{status_code}"
416
548
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vcloud-rest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-19 00:00:00.000000000 Z
12
+ date: 2012-12-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri