vm_shepherd 0.0.1 → 0.1.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.
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