vm_shepherd 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dd16c5dc4a8f8276b0c59927637e27a635005091
4
- data.tar.gz: a16f15c127599cdf280b3fc4fa21cecced662d8d
3
+ metadata.gz: a15179c8d68cb360d34b776f21f000a202c9f058
4
+ data.tar.gz: 279e17c6e5bc45225a888bd3fb70fe750c3e58fe
5
5
  SHA512:
6
- metadata.gz: 4ef0386504cbf50ec960bccf9e1eead05746441f7e4ff618249e43b0026da0fd6d1c9ffb17166a56ed203cc75b8726bd3a9214d5b0e27cfebc820e84b4e87899
7
- data.tar.gz: 58ebe55c5ced17018c1a8666a8e0ff26b502870179c2cba965735ce67117d2bbde06ef17ec286ba1455bb62efea40892d9043daf28a3c7051f630a467f541751
6
+ metadata.gz: 13ce9b1112ac673d7cc70030814ea929f62cbe9e572c9ba1f70471f7073bea4a0c95893677338048a95cb99de3c2c763737553fe67777efbebba00d6eaef63a9
7
+ data.tar.gz: d74268270051fe55e7fd6a14037afbbd413c35d2234c210f15deb8d1ff2cef903e47126bf46a6fd215dbba3676820cd29113b6ae2cd67a24772bf8e630d15d47
data/Gemfile CHANGED
@@ -1,5 +1,3 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'vsphere_clients', git: 'http://github.com/pivotal-cf-experimental/vsphere_clients'
4
-
5
3
  gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Pivotal CF
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # VmShepherd
2
2
 
3
- TODO: Write a gem description
3
+ Gem for deploying and destroying a VM on different IAASs such as AWS, vSphere, vCloud, and Openstack
4
4
 
5
5
  ## Installation
6
6
 
@@ -20,7 +20,20 @@ Or install it yourself as:
20
20
 
21
21
  ## Usage
22
22
 
23
- TODO: Write usage instructions here
23
+ ```ruby
24
+ require 'vm_shepherd'
25
+
26
+ settings = # An OpenStruct with the expected IaaS specific settings.
27
+ # => See YAML under spec/fixtures/shepherd/ for expected values
28
+
29
+ # create a new VM
30
+ shep = VmShepherd::Shepherd.new(settings: settings)
31
+ shep.deploy(path: 'path/to/vm.image')
32
+
33
+ # destroy an existing VM
34
+ shep = VmShepherd::Shepherd.new(settings: settings)
35
+ shep.destroy
36
+ ```
24
37
 
25
38
  ## Contributing
26
39
 
data/ci/run_specs.sh CHANGED
@@ -7,5 +7,10 @@ docker run \
7
7
  --rm=true \
8
8
  --volume=${PWD}:/vm_shepherd \
9
9
  --workdir=/vm_shepherd \
10
+ --env=VCENTER_IP=${VCENTER_IP} \
11
+ --env=USERNAME=${USERNAME} \
12
+ --env=PASSWORD=${PASSWORD} \
13
+ --env=DATACENTER_NAME=${DATACENTER_NAME} \
14
+ --env=DATASTORE_NAME=${DATASTORE_NAME} \
10
15
  ${DOCKER_REGISTRY}/${DOCKER_IMAGE_NAME} \
11
- /bin/sh -c 'bundle && bundle exec rspec --format documentation'
16
+ /bin/sh -c 'bundle && bundle exec rake -t'
@@ -0,0 +1,12 @@
1
+ require 'vm_shepherd/shepherd'
2
+ require 'vm_shepherd/aws_manager'
3
+ require 'vm_shepherd/openstack_manager'
4
+ require 'vm_shepherd/vcloud_manager'
5
+ require 'vm_shepherd/vsphere_manager'
6
+
7
+ module VmShepherd
8
+ AWS_IAAS_TYPE = 'aws'.freeze
9
+ OPENSTACK_IAAS_TYPE = 'openstack'.freeze
10
+ VCLOUD_IAAS_TYPE = 'vcloud'.freeze
11
+ VSPHERE_IAAS_TYPE = 'vsphere'.freeze
12
+ end
@@ -1,12 +1,11 @@
1
1
  require 'aws-sdk-v1'
2
2
 
3
3
  module VmShepherd
4
- class AmiManager
4
+ class AwsManager
5
5
  class RetryLimitExceeded < StandardError
6
6
  end
7
7
 
8
8
  AWS_REGION = 'us-east-1'
9
- OPS_MANAGER_PRIVATE_IP = '10.0.1.5'
10
9
  OPS_MANAGER_INSTANCE_TYPE = 'm3.medium'
11
10
  RETRY_LIMIT = 60
12
11
  RETRY_INTERVAL = 5
@@ -31,7 +30,6 @@ module VmShepherd
31
30
  key_name: aws_options.fetch(:ssh_key_name),
32
31
  security_group_ids: [aws_options.fetch(:security_group_id)],
33
32
  subnet: aws_options.fetch(:public_subnet_id),
34
- private_ip_address: OPS_MANAGER_PRIVATE_IP,
35
33
  instance_type: OPS_MANAGER_INSTANCE_TYPE
36
34
  )
37
35
  end
@@ -0,0 +1,102 @@
1
+ require 'fog'
2
+
3
+ module VmShepherd
4
+ class OpenstackManager
5
+ def initialize(auth_url:, username:, api_key:, tenant:)
6
+ @auth_url = auth_url
7
+ @username = username
8
+ @api_key = api_key
9
+ @tenant = tenant
10
+ end
11
+
12
+ def deploy(qcow2_file_path, vm_options)
13
+ say "Uploading the image #{qcow2_file_path}"
14
+ image = image_service.images.create(
15
+ name: vm_options[:name],
16
+ size: File.size(qcow2_file_path),
17
+ disk_format: 'qcow2',
18
+ container_format: 'bare',
19
+ location: qcow2_file_path,
20
+ )
21
+ say 'Finished uploading the image'
22
+
23
+ flavor = find_flavor(vm_options[:min_disk_size])
24
+ network = network_service.networks.find { |net| net.name == vm_options[:network_name] }
25
+ security_groups = vm_options[:security_group_names]
26
+
27
+ say('Launching an instance')
28
+ server = service.servers.create(
29
+ name: vm_options[:name],
30
+ flavor_ref: flavor.id,
31
+ image_ref: image.id,
32
+ key_name: vm_options[:key_name],
33
+ security_groups: security_groups,
34
+ nics: [
35
+ { net_id: network.id, v4_fixed_ip: vm_options[:private_ip] }
36
+ ],
37
+ )
38
+ server.wait_for { ready? }
39
+ say('Finished launching an instance')
40
+
41
+ say('Assigning a Public IP to the instance')
42
+ ip = service.addresses.find { |address| address.instance_id.nil? && address.ip == vm_options[:public_ip] }
43
+ ip.server = server
44
+ say('Finished assigning a Public IP to the instance')
45
+ end
46
+
47
+ def destroy(vm_options)
48
+ ip = service.addresses.find { |address| address.ip == vm_options[:public_ip] }
49
+ server = service.servers.get(ip.instance_id)
50
+ if server
51
+ image = image_service.images.get(server.image['id'])
52
+
53
+ server.destroy
54
+ image.destroy
55
+ end
56
+ end
57
+
58
+ def service
59
+ @service ||= Fog::Compute.new(
60
+ provider: 'openstack',
61
+ openstack_auth_url: auth_url,
62
+ openstack_username: username,
63
+ openstack_tenant: tenant,
64
+ openstack_api_key: api_key,
65
+ )
66
+ end
67
+
68
+ def image_service
69
+ @image_service ||= Fog::Image.new(
70
+ provider: 'openstack',
71
+ openstack_auth_url: auth_url,
72
+ openstack_username: username,
73
+ openstack_tenant: tenant,
74
+ openstack_api_key: api_key,
75
+ openstack_endpoint_type: 'publicURL',
76
+ )
77
+ end
78
+
79
+ def network_service
80
+ @network_service ||= Fog::Network.new(
81
+ provider: 'openstack',
82
+ openstack_auth_url: auth_url,
83
+ openstack_username: username,
84
+ openstack_tenant: tenant,
85
+ openstack_api_key: api_key,
86
+ openstack_endpoint_type: 'publicURL',
87
+ )
88
+ end
89
+
90
+ private
91
+
92
+ attr_reader :auth_url, :username, :api_key, :tenant
93
+
94
+ def say(message)
95
+ puts message
96
+ end
97
+
98
+ def find_flavor(min_disk)
99
+ service.flavors.find { |flavor| flavor.disk >= min_disk }
100
+ end
101
+ end
102
+ end
@@ -1,16 +1,5 @@
1
- require 'vm_shepherd/vapp_manager/deployer'
2
- require 'vm_shepherd/vapp_manager/destroyer'
3
- require 'vm_shepherd/ova_manager/deployer'
4
- require 'vm_shepherd/ova_manager/destroyer'
5
- require 'vm_shepherd/ami_manager'
6
-
7
1
  module VmShepherd
8
2
  class Shepherd
9
- VCLOUD_IAAS_TYPE = 'vcloud'.freeze
10
- VSPHERE_IAAS_TYPE = 'vsphere'.freeze
11
- AWS_IAAS_TYPE = 'aws'.freeze
12
- VSPHERE_TEMPLATE_PREFIX = 'tpl'.freeze
13
-
14
3
  class InvalidIaas < StandardError
15
4
 
16
5
  end
@@ -21,19 +10,51 @@ module VmShepherd
21
10
 
22
11
  def deploy(path:)
23
12
  case settings.iaas_type
24
- when VCLOUD_IAAS_TYPE then
25
- vcloud_deployer.deploy(
13
+ when VmShepherd::VCLOUD_IAAS_TYPE then
14
+ VmShepherd::VcloudManager.new(
15
+ {
16
+ url: settings.vapp_deployer.creds.url,
17
+ organization: settings.vapp_deployer.creds.organization,
18
+ user: settings.vapp_deployer.creds.user,
19
+ password: settings.vapp_deployer.creds.password,
20
+ },
21
+ {
22
+ vdc: settings.vapp_deployer.vdc.name,
23
+ catalog: settings.vapp_deployer.vdc.catalog,
24
+ network: settings.vapp_deployer.vdc.network,
25
+ },
26
+ debug_logger
27
+ ).deploy(
26
28
  path,
27
29
  vcloud_deploy_options,
28
30
  )
29
- when VSPHERE_IAAS_TYPE then
30
- vsphere_deployer.deploy(
31
- VSPHERE_TEMPLATE_PREFIX,
31
+ when VmShepherd::VSPHERE_IAAS_TYPE then
32
+ VmShepherd::VsphereManager.new(
33
+ settings.vm_deployer.vcenter_creds.ip,
34
+ settings.vm_deployer.vcenter_creds.username,
35
+ settings.vm_deployer.vcenter_creds.password,
36
+ settings.vm_deployer.vsphere.datacenter,
37
+ ).deploy(
32
38
  path,
33
- vsphere_deploy_options,
39
+ {
40
+ ip: settings.vm_deployer.vm.ip,
41
+ gateway: settings.vm_deployer.vm.gateway,
42
+ netmask: settings.vm_deployer.vm.netmask,
43
+ dns: settings.vm_deployer.vm.dns,
44
+ ntp_servers: settings.vm_deployer.vm.ntp_servers,
45
+ },
46
+ {
47
+ cluster: settings.vm_deployer.vsphere.cluster,
48
+ resource_pool: settings.vm_deployer.vsphere.resource_pool,
49
+ datastore: settings.vm_deployer.vsphere.datastore,
50
+ network: settings.vm_deployer.vsphere.network,
51
+ folder: settings.vm_deployer.vsphere.folder,
52
+ }
34
53
  )
35
- when AWS_IAAS_TYPE then
54
+ when VmShepherd::AWS_IAAS_TYPE then
36
55
  ami_manager.deploy(path)
56
+ when VmShepherd::OPENSTACK_IAAS_TYPE then
57
+ openstack_vm_manager.deploy(path, openstack_vm_options)
37
58
  else
38
59
  fail(InvalidIaas, "Unknown IaaS type: #{settings.iaas_type.inspect}")
39
60
  end
@@ -41,8 +62,8 @@ module VmShepherd
41
62
 
42
63
  def destroy
43
64
  case settings.iaas_type
44
- when VCLOUD_IAAS_TYPE then
45
- VmShepherd::VappManager::Destroyer.new(
65
+ when VmShepherd::VCLOUD_IAAS_TYPE then
66
+ VmShepherd::VcloudManager.new(
46
67
  {
47
68
  url: settings.vapp_deployer.creds.url,
48
69
  organization: settings.vapp_deployer.creds.organization,
@@ -52,20 +73,21 @@ module VmShepherd
52
73
  {
53
74
  vdc: settings.vapp_deployer.vdc.name,
54
75
  catalog: settings.vapp_deployer.vdc.catalog,
76
+ network: settings.vapp_deployer.vdc.network,
55
77
  },
56
- Logger.new(STDOUT).tap { |l| l.level = Logger::Severity::ERROR }
78
+ logger
57
79
  ).destroy(settings.vapp_deployer.vapp.name)
58
- when VSPHERE_IAAS_TYPE then
59
- VmShepherd::OvaManager::Destroyer.new(
80
+ when VmShepherd::VSPHERE_IAAS_TYPE then
81
+ VmShepherd::VsphereManager.new(
82
+ settings.vm_deployer.vcenter_creds.ip,
83
+ settings.vm_deployer.vcenter_creds.username,
84
+ settings.vm_deployer.vcenter_creds.password,
60
85
  settings.vm_deployer.vsphere.datacenter,
61
- {
62
- host: settings.vm_deployer.vcenter_creds.ip,
63
- user: settings.vm_deployer.vcenter_creds.username,
64
- password: settings.vm_deployer.vcenter_creds.password,
65
- }
66
- ).clean_folder(settings.vm_deployer.vsphere.folder)
67
- when AWS_IAAS_TYPE then
86
+ ).destroy(settings.vm_deployer.vsphere.folder)
87
+ when VmShepherd::AWS_IAAS_TYPE then
68
88
  ami_manager.destroy
89
+ when VmShepherd::OPENSTACK_IAAS_TYPE then
90
+ openstack_vm_manager.destroy(openstack_vm_options)
69
91
  else
70
92
  fail(InvalidIaas, "Unknown IaaS type: #{settings.iaas_type.inspect}")
71
93
  end
@@ -87,25 +109,6 @@ module VmShepherd
87
109
  end
88
110
  end
89
111
 
90
- def vcloud_deployer
91
- creds = settings.vapp_deployer.creds
92
- vdc = settings.vapp_deployer.vdc
93
- VmShepherd::VappManager::Deployer.new(
94
- {
95
- url: creds.url,
96
- organization: creds.organization,
97
- user: creds.user,
98
- password: creds.password,
99
- },
100
- {
101
- vdc: vdc.name,
102
- catalog: vdc.catalog,
103
- network: vdc.network,
104
- },
105
- debug_logger
106
- )
107
- end
108
-
109
112
  def vcloud_deploy_options
110
113
  vm = settings.vapp_deployer.vapp
111
114
  {
@@ -118,40 +121,9 @@ module VmShepherd
118
121
  }
119
122
  end
120
123
 
121
- def vsphere_deployer
122
- vcenter_creds = settings.vm_deployer.vcenter_creds
123
- vsphere = settings.vm_deployer.vsphere
124
- VmShepherd::OvaManager::Deployer.new(
125
- {
126
- host: vcenter_creds.ip,
127
- user: vcenter_creds.username,
128
- password: vcenter_creds.password,
129
- },
130
- {
131
- datacenter: vsphere.datacenter,
132
- cluster: vsphere.cluster,
133
- resource_pool: vsphere.resource_pool,
134
- datastore: vsphere.datastore,
135
- network: vsphere.network,
136
- folder: vsphere.folder,
137
- }
138
- )
139
- end
140
-
141
- def vsphere_deploy_options
142
- vm = settings.vm_deployer.vm
143
- {
144
- ip: vm.ip,
145
- gateway: vm.gateway,
146
- netmask: vm.netmask,
147
- dns: vm.dns,
148
- ntp_servers: vm.ntp_servers,
149
- }
150
- end
151
-
152
124
  def ami_manager
153
125
  vm_deployer = settings.vm_deployer
154
- VmShepherd::AmiManager.new(
126
+ VmShepherd::AwsManager.new(
155
127
  aws_access_key: vm_deployer.aws_access_key,
156
128
  aws_secret_key: vm_deployer.aws_secret_key,
157
129
  ssh_key_name: vm_deployer.ssh_key_name,
@@ -162,5 +134,26 @@ module VmShepherd
162
134
  vm_name: vm_deployer.vm_name,
163
135
  )
164
136
  end
137
+
138
+ def openstack_vm_manager
139
+ OpenstackManager.new(
140
+ auth_url: settings.vm_deployer.creds.auth_url,
141
+ username: settings.vm_deployer.creds.username,
142
+ api_key: settings.vm_deployer.creds.api_key,
143
+ tenant: settings.vm_deployer.creds.tenant,
144
+ )
145
+ end
146
+
147
+ def openstack_vm_options
148
+ {
149
+ name: settings.vm_deployer.vm.name,
150
+ min_disk_size: settings.vm_deployer.vm.flavor_parameters.min_disk_size,
151
+ network_name: settings.vm_deployer.vm.network_name,
152
+ key_name: settings.vm_deployer.vm.key_name,
153
+ security_group_names: settings.vm_deployer.vm.security_group_names,
154
+ public_ip: settings.vm_deployer.vm.public_ip,
155
+ private_ip: settings.vm_deployer.vm.private_ip,
156
+ }
157
+ end
165
158
  end
166
159
  end
@@ -0,0 +1,170 @@
1
+ require 'tmpdir'
2
+ require 'fileutils'
3
+ require 'ruby_vcloud_sdk'
4
+
5
+ module VmShepherd
6
+ class VcloudManager
7
+ def initialize(login_info, location, logger)
8
+ @login_info = login_info
9
+ @location = location
10
+ @logger = logger
11
+ raise 'VDC must be set' unless @location[:vdc]
12
+ raise 'Catalog must be set' unless @location[:catalog]
13
+ raise 'Network must be set' unless @location[:network]
14
+ end
15
+
16
+ def deploy(vapp_template_tar_path, vapp_config)
17
+ tmpdir = Dir.mktmpdir
18
+
19
+ check_vapp_status(vapp_config)
20
+
21
+ untar_vapp_template_tar(File.expand_path(vapp_template_tar_path), tmpdir)
22
+
23
+ vapp = deploy_vapp(tmpdir, vapp_config)
24
+ reconfigure_vm(vapp, vapp_config)
25
+ vapp.power_on
26
+ ensure
27
+ FileUtils.remove_entry_secure(tmpdir, force: true)
28
+ end
29
+
30
+ def destroy(vapp_name)
31
+ delete_vapp(vapp_name)
32
+ delete_catalog
33
+ end
34
+
35
+ private
36
+
37
+ def check_vapp_status(vapp_config)
38
+ log('Checking for existing VM') do
39
+ ip = vapp_config[:ip]
40
+ raise "VM exists at #{ip}" if system("ping -c 5 #{ip}")
41
+ end
42
+ end
43
+
44
+ def untar_vapp_template_tar(vapp_template_tar_path, dir)
45
+ log("Untarring #{vapp_template_tar_path}") do
46
+ system_or_exit("cd #{dir} && tar xfv '#{vapp_template_tar_path}'")
47
+ end
48
+ end
49
+
50
+ def client
51
+ @client ||= VCloudSdk::Client.new(
52
+ @login_info[:url],
53
+ "#{@login_info[:user]}@#{@login_info[:organization]}",
54
+ @login_info[:password],
55
+ {},
56
+ @logger,
57
+ )
58
+ end
59
+
60
+ def deploy_vapp(ovf_dir, vapp_config)
61
+ # setup the catalog
62
+ client.delete_catalog_by_name(@location[:catalog]) if client.catalog_exists?(@location[:catalog])
63
+ catalog = client.create_catalog(@location[:catalog])
64
+
65
+ # upload template and instantiate vapp
66
+ catalog.upload_vapp_template(@location[:vdc], vapp_config[:name], ovf_dir)
67
+
68
+ # instantiate template
69
+ network_config = VCloudSdk::NetworkConfig.new(@location[:network], 'Network 1')
70
+ catalog.instantiate_vapp_template(
71
+ vapp_config[:name], @location[:vdc], vapp_config[:name], nil, nil, network_config)
72
+ rescue => e
73
+ @logger.error(e.http_body) if e.respond_to?(:http_body)
74
+ raise e
75
+ end
76
+
77
+ def reconfigure_vm(vapp, vapp_config)
78
+ vm = vapp.find_vm_by_name(vapp_config[:name])
79
+ vm.product_section_properties = build_properties(vapp_config)
80
+ vm
81
+ end
82
+
83
+ def build_properties(vapp_config)
84
+ [
85
+ {
86
+ 'type' => 'string',
87
+ 'key' => 'gateway',
88
+ 'value' => vapp_config[:gateway],
89
+ 'password' => 'false',
90
+ 'userConfigurable' => 'true',
91
+ 'Label' => 'Default Gateway',
92
+ 'Description' => 'The default gateway address for the VM network. Leave blank if DHCP is desired.'
93
+ },
94
+ {
95
+ 'type' => 'string',
96
+ 'key' => 'DNS',
97
+ 'value' => vapp_config[:dns],
98
+ 'password' => 'false',
99
+ 'userConfigurable' => 'true',
100
+ 'Label' => 'DNS',
101
+ 'Description' => 'The domain name servers for the VM (comma separated). Leave blank if DHCP is desired.',
102
+ },
103
+ {
104
+ 'type' => 'string',
105
+ 'key' => 'ntp_servers',
106
+ 'value' => vapp_config[:ntp],
107
+ 'password' => 'false',
108
+ 'userConfigurable' => 'true',
109
+ 'Label' => 'NTP Servers',
110
+ 'Description' => 'Comma-delimited list of NTP servers'
111
+ },
112
+ {
113
+ 'type' => 'string',
114
+ 'key' => 'admin_password',
115
+ 'value' => 'tempest',
116
+ 'password' => 'true',
117
+ 'userConfigurable' => 'true',
118
+ 'Label' => 'Admin Password',
119
+ 'Description' => 'This password is used to SSH into the VM. The username is "tempest".',
120
+ },
121
+ {
122
+ 'type' => 'string',
123
+ 'key' => 'ip0',
124
+ 'value' => vapp_config[:ip],
125
+ 'password' => 'false',
126
+ 'userConfigurable' => 'true',
127
+ 'Label' => 'IP Address',
128
+ 'Description' => 'The IP address for the VM. Leave blank if DHCP is desired.',
129
+ },
130
+ {
131
+ 'type' => 'string',
132
+ 'key' => 'netmask0',
133
+ 'value' => vapp_config[:netmask],
134
+ 'password' => 'false',
135
+ 'userConfigurable' => 'true',
136
+ 'Label' => 'Netmask',
137
+ 'Description' => 'The netmask for the VM network. Leave blank if DHCP is desired.'
138
+ }
139
+ ]
140
+ end
141
+
142
+ def log(title, &blk)
143
+ @logger.debug "--- Begin: #{title.inspect} @ #{DateTime.now}"
144
+ blk.call
145
+ @logger.debug "--- End: #{title.inspect} @ #{DateTime.now}"
146
+ end
147
+
148
+ def system_or_exit(command)
149
+ log(command) do
150
+ system(command) || raise("Error executing: #{command.inspect}")
151
+ end
152
+ end
153
+
154
+ def vdc
155
+ @vdc ||= client.find_vdc_by_name(@location[:vdc])
156
+ end
157
+
158
+ def delete_vapp(vapp_name)
159
+ vapp = vdc.find_vapp_by_name(vapp_name)
160
+ vapp.power_off
161
+ vapp.delete
162
+ rescue VCloudSdk::ObjectNotFoundError => e
163
+ @logger.debug "Could not delete vapp '#{vapp_name}': #{e.inspect}"
164
+ end
165
+
166
+ def delete_catalog
167
+ client.delete_catalog_by_name(@location[:catalog]) if client.catalog_exists?(@location[:catalog])
168
+ end
169
+ end
170
+ end