vm_shepherd 3.5.0 → 3.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.rubocop.yml +1 -1
- data/.ruby-version +1 -1
- data/lib/vm_shepherd/aws_manager.rb +1 -1
- data/lib/vm_shepherd/shepherd.rb +18 -5
- data/lib/vm_shepherd/version.rb +1 -1
- data/lib/vm_shepherd/vsphere_manager.rb +43 -49
- data/spec/fixtures/ova_manager/default.ovf +136 -0
- data/spec/fixtures/ova_manager/without_public_ssh_key.ovf +132 -0
- data/spec/fixtures/shepherd/vsphere-one-vm-config.yml +35 -0
- data/spec/vm_shepherd/aws_manager_spec.rb +21 -0
- data/spec/vm_shepherd/shepherd_spec.rb +213 -0
- data/spec/vm_shepherd/vsphere_manager_spec.rb +31 -2
- data/vm_shepherd.gemspec +1 -0
- metadata +26 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f0c4eae538ba72ae93a1bc16e07b93153be92fb3730b0c1ee995c75aaa7bbec6
|
4
|
+
data.tar.gz: c46d2af2473fb238bfb1bec5e85f8ec13d19f9a0e32f5d7c88db23bd0ad3ac25
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c24318537ae944dc68ccd6c214baa05c1906ba78011ae2391a4a1e8b115c5fddc20813f1556a0634a95436dfcf6b73679570bccb35386ac77936e576cc76628e
|
7
|
+
data.tar.gz: 8db0afde7bfa78be5acaf6d0736cd0a4d0fb75cce46054777873125a5ead9f6c4a479834bbeb69ab765cba7ca4bc9189708ec9b4ae6119148e231189bc04dcbc
|
data/.rubocop.yml
CHANGED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.6.3
|
@@ -167,7 +167,7 @@ module VmShepherd
|
|
167
167
|
key_name: vm_config.fetch('key_name'),
|
168
168
|
security_group_ids: [env_config.fetch('outputs').fetch('security_group')],
|
169
169
|
subnet: env_config.fetch('outputs').fetch('public_subnet_id'),
|
170
|
-
instance_type: OPS_MANAGER_INSTANCE_TYPE
|
170
|
+
instance_type: vm_config.dig('instance_type') || OPS_MANAGER_INSTANCE_TYPE
|
171
171
|
}
|
172
172
|
|
173
173
|
if (instance_profile = env_config.fetch('outputs').fetch('instance_profile', nil))
|
data/lib/vm_shepherd/shepherd.rb
CHANGED
@@ -38,7 +38,7 @@ module VmShepherd
|
|
38
38
|
path,
|
39
39
|
vcloud_deploy_options(vm_shepherd_config),
|
40
40
|
)
|
41
|
-
|
41
|
+
when VmShepherd::VSPHERE_IAAS_TYPE then
|
42
42
|
VmShepherd::VsphereManager.new(
|
43
43
|
vm_shepherd_config.dig('vcenter_creds', 'ip'),
|
44
44
|
vm_shepherd_config.dig('vcenter_creds', 'username'),
|
@@ -164,6 +164,8 @@ module VmShepherd
|
|
164
164
|
datacenter_folders_to_clean: vm_shepherd_config.dig('cleanup', 'datacenter_folders_to_clean'),
|
165
165
|
datastores: vm_shepherd_config.dig('cleanup', 'datastores'),
|
166
166
|
datastore_folders_to_clean: vm_shepherd_config.dig('cleanup', 'datastore_folders_to_clean'),
|
167
|
+
cluster_name: vm_shepherd_config.dig('vsphere', 'cluster'),
|
168
|
+
resource_pool_name: vm_shepherd_config.dig('vsphere', 'resource_pool'),
|
167
169
|
)
|
168
170
|
end
|
169
171
|
when VmShepherd::AWS_IAAS_TYPE then
|
@@ -182,20 +184,31 @@ module VmShepherd
|
|
182
184
|
end
|
183
185
|
|
184
186
|
def vsphere_vm_options(input_config)
|
185
|
-
{
|
187
|
+
vsphere_vm_options = {
|
186
188
|
ip: input_config.dig('vm', 'ip'),
|
187
189
|
gateway: input_config.dig('vm', 'gateway'),
|
188
190
|
netmask: input_config.dig('vm', 'netmask'),
|
189
191
|
dns: input_config.dig('vm', 'dns'),
|
190
192
|
ntp_servers: input_config.dig('vm', 'ntp_servers'),
|
191
193
|
cpus: input_config.dig('vm', 'cpus'),
|
192
|
-
ram_mb: input_config.dig('vm', 'ram_mb')
|
193
|
-
vm_password: (input_config.dig('vm', 'vm_password') || 'tempest'),
|
194
|
-
public_ssh_key: read_assets_home(input_config.dig('vm', 'public_ssh_key')),
|
194
|
+
ram_mb: input_config.dig('vm', 'ram_mb')
|
195
195
|
}.tap do |result|
|
196
196
|
hostname = input_config.dig('vm', 'custom_hostname')
|
197
197
|
result[:custom_hostname] = hostname unless hostname.nil?
|
198
198
|
end
|
199
|
+
|
200
|
+
vsphere_vm_options.merge!(vm_password: get_vsphere_vm_password(input_config))
|
201
|
+
vsphere_vm_options.merge!(public_ssh_key: get_vsphere_vm_public_ssh_key(input_config))
|
202
|
+
|
203
|
+
vsphere_vm_options
|
204
|
+
end
|
205
|
+
|
206
|
+
def get_vsphere_vm_password(input_config)
|
207
|
+
ENV['PROVISION_WITH_PASSWORD'] == 'false' ? nil : (input_config.dig('vm', 'vm_password') || ENV['VSPHERE_VM_PASSWORD'] || 'tempest')
|
208
|
+
end
|
209
|
+
|
210
|
+
def get_vsphere_vm_public_ssh_key(input_config)
|
211
|
+
ENV['PROVISION_WITH_SSH_KEY'] == 'false' ? nil : (read_assets_home(input_config.dig('vm', 'public_ssh_key')))
|
199
212
|
end
|
200
213
|
|
201
214
|
def read_assets_home(path_or_value)
|
data/lib/vm_shepherd/version.rb
CHANGED
@@ -27,12 +27,12 @@ module VmShepherd
|
|
27
27
|
FileUtils.remove_entry_secure(ovf_file_path, force: true) unless ovf_file_path.nil?
|
28
28
|
end
|
29
29
|
|
30
|
-
def clean_environment(datacenter_folders_to_clean:, datastores:, datastore_folders_to_clean:)
|
30
|
+
def clean_environment(datacenter_folders_to_clean:, datastores:, datastore_folders_to_clean:, cluster_name: nil, resource_pool_name: nil)
|
31
31
|
return if datacenter_folders_to_clean.nil? || datastores.nil? || datacenter_folders_to_clean.nil?
|
32
32
|
|
33
33
|
datacenter_folders_to_clean.each do |folder_name|
|
34
34
|
validate_folder_name!(folder_name)
|
35
|
-
delete_folder_and_vms(folder_name)
|
35
|
+
delete_folder_and_vms(folder_name, cluster_name, resource_pool_name)
|
36
36
|
end
|
37
37
|
|
38
38
|
datastore_folders_to_clean.each do |folder_name|
|
@@ -105,18 +105,23 @@ module VmShepherd
|
|
105
105
|
end
|
106
106
|
|
107
107
|
def create_network_mappings(ovf_file_path, vsphere_config)
|
108
|
-
ovf =
|
109
|
-
ovf.remove_namespaces!
|
108
|
+
ovf = parse_ovf(ovf_file_path)
|
110
109
|
networks = ovf.xpath('//NetworkSection/Network').map { |x| x['name'] }
|
111
110
|
Hash[networks.map { |ovf_network| [ovf_network, network(vsphere_config)] }]
|
112
111
|
end
|
113
112
|
|
113
|
+
def parse_ovf(ovf_file_path)
|
114
|
+
ovf = Nokogiri::XML(File.read(ovf_file_path))
|
115
|
+
ovf.remove_namespaces!
|
116
|
+
ovf
|
117
|
+
end
|
118
|
+
|
114
119
|
def boot_vm(ovf_file_path, vm_config, vsphere_config)
|
115
120
|
ensure_folder_exists(vsphere_config[:folder])
|
116
121
|
template = deploy_ovf_template(ovf_file_path, vsphere_config)
|
117
122
|
vm = create_vm_from_template(template, vm_config, vsphere_config)
|
118
123
|
|
119
|
-
reconfigure_vm(vm, vm_config)
|
124
|
+
reconfigure_vm(vm, vm_config, ovf_file_path)
|
120
125
|
power_on_vm(vm)
|
121
126
|
end
|
122
127
|
|
@@ -124,12 +129,13 @@ module VmShepherd
|
|
124
129
|
datacenter.vmFolder.traverse(folder_name, RbVmomi::VIM::Folder, true)
|
125
130
|
end
|
126
131
|
|
127
|
-
def delete_folder_and_vms(folder_name)
|
132
|
+
def delete_folder_and_vms(folder_name, cluster_name = nil, resource_pool_name = nil)
|
128
133
|
3.times do |attempt|
|
129
134
|
break unless (folder = datacenter.vmFolder.traverse(folder_name))
|
130
135
|
|
131
136
|
find_vms(folder).each do |vm|
|
132
137
|
power_off_vm(vm)
|
138
|
+
convert_template_to_vm(vm, cluster_name, resource_pool_name)
|
133
139
|
end
|
134
140
|
|
135
141
|
begin
|
@@ -155,6 +161,7 @@ module VmShepherd
|
|
155
161
|
|
156
162
|
def power_off_vm(vm)
|
157
163
|
2.times do
|
164
|
+
# This will implicitly skip over VM templates, which always are in the "poweredOff" state
|
158
165
|
break if vm.runtime.powerState == 'poweredOff'
|
159
166
|
|
160
167
|
begin
|
@@ -168,6 +175,14 @@ module VmShepherd
|
|
168
175
|
end
|
169
176
|
end
|
170
177
|
|
178
|
+
def convert_template_to_vm(vm, cluster_name, resource_pool_name)
|
179
|
+
return unless vm.config.template
|
180
|
+
|
181
|
+
cluster = datacenter.find_compute_resource(cluster_name)
|
182
|
+
pool = cluster.resourcePool.resourcePool.find { |rp| rp.name == resource_pool_name }
|
183
|
+
vm.MarkAsVirtualMachine(pool: pool)
|
184
|
+
end
|
185
|
+
|
171
186
|
def deploy_ovf_template(ovf_file_path, vsphere_config)
|
172
187
|
template_name = [TEMPLATE_PREFIX, Time.new.strftime('%F-%H-%M'), cluster(vsphere_config).name].join('-')
|
173
188
|
logger.info("BEGIN deploy_ovf ovf_file=#{ovf_file_path} template_name=#{template_name}")
|
@@ -233,8 +248,8 @@ module VmShepherd
|
|
233
248
|
}
|
234
249
|
end
|
235
250
|
|
236
|
-
def reconfigure_vm(vm, vm_config)
|
237
|
-
virtual_machine_config_spec = create_virtual_machine_config_spec(vm_config)
|
251
|
+
def reconfigure_vm(vm, vm_config, ovf_file_path)
|
252
|
+
virtual_machine_config_spec = create_virtual_machine_config_spec(vm_config, ovf_file_path)
|
238
253
|
logger.info("BEGIN reconfigure_vm_task virtual_machine_config_spec=#{virtual_machine_config_spec.inspect}")
|
239
254
|
vm.ReconfigVM_Task(
|
240
255
|
spec: virtual_machine_config_spec
|
@@ -243,12 +258,12 @@ module VmShepherd
|
|
243
258
|
}
|
244
259
|
end
|
245
260
|
|
246
|
-
def create_virtual_machine_config_spec(vm_config)
|
261
|
+
def create_virtual_machine_config_spec(vm_config, ovf_file_path)
|
247
262
|
logger.info('BEGIN VmConfigSpec creation')
|
248
263
|
vm_config_spec =
|
249
264
|
RbVmomi::VIM::VmConfigSpec.new.tap do |vcs|
|
250
265
|
vcs.ovfEnvironmentTransport = ['com.vmware.guestInfo']
|
251
|
-
vcs.property = create_vapp_property_specs(vm_config)
|
266
|
+
vcs.property = create_vapp_property_specs(vm_config, ovf_file_path)
|
252
267
|
end
|
253
268
|
logger.info("END VmConfigSpec creation: #{vm_config_spec.inspect}")
|
254
269
|
|
@@ -259,57 +274,36 @@ module VmShepherd
|
|
259
274
|
end
|
260
275
|
end
|
261
276
|
|
262
|
-
def create_vapp_property_specs(vm_config)
|
263
|
-
|
264
|
-
'ip0'
|
265
|
-
'netmask0'
|
266
|
-
'gateway'
|
267
|
-
'DNS'
|
277
|
+
def create_vapp_property_specs(vm_config, ovf_file_path)
|
278
|
+
property_value_map = {
|
279
|
+
'ip0' => vm_config[:ip],
|
280
|
+
'netmask0' => vm_config[:netmask],
|
281
|
+
'gateway' => vm_config[:gateway],
|
282
|
+
'DNS' => vm_config[:dns],
|
268
283
|
'ntp_servers' => vm_config[:ntp_servers],
|
284
|
+
'admin_password' => vm_config[:vm_password],
|
285
|
+
'public_ssh_key' => vm_config[:public_ssh_key],
|
286
|
+
'custom_hostname' => vm_config[:custom_hostname],
|
269
287
|
}
|
270
288
|
|
271
289
|
vapp_property_specs = []
|
272
290
|
|
273
|
-
logger.info("BEGIN VAppPropertySpec creation configuration=#{
|
274
|
-
|
275
|
-
|
291
|
+
logger.info("BEGIN VAppPropertySpec creation configuration=#{property_value_map.inspect}")
|
292
|
+
|
293
|
+
# VAppPropertySpec order must match OVF template property order
|
294
|
+
ovf = parse_ovf(ovf_file_path)
|
295
|
+
ovf.xpath('//ProductSection/Property').each_with_index do |property, index|
|
296
|
+
label = property.attribute('key').value
|
276
297
|
vapp_property_specs << RbVmomi::VIM::VAppPropertySpec.new.tap do |spec|
|
277
298
|
spec.operation = 'edit'
|
278
299
|
spec.info = RbVmomi::VIM::VAppPropertyInfo.new.tap do |p|
|
279
|
-
p.key =
|
280
|
-
p.label =
|
281
|
-
p.value =
|
300
|
+
p.key = index
|
301
|
+
p.label = label
|
302
|
+
p.value = property_value_map[label]
|
282
303
|
end
|
283
304
|
end
|
284
305
|
end
|
285
306
|
|
286
|
-
vapp_property_specs << RbVmomi::VIM::VAppPropertySpec.new.tap do |spec|
|
287
|
-
spec.operation = 'edit'
|
288
|
-
spec.info = RbVmomi::VIM::VAppPropertyInfo.new.tap do |p|
|
289
|
-
p.key = 5 # this needs to be 5th to match the ovf template property order.
|
290
|
-
p.label = 'admin_password'
|
291
|
-
p.value = vm_config[:vm_password]
|
292
|
-
end
|
293
|
-
end
|
294
|
-
|
295
|
-
vapp_property_specs << RbVmomi::VIM::VAppPropertySpec.new.tap do |spec|
|
296
|
-
spec.operation = 'edit'
|
297
|
-
spec.info = RbVmomi::VIM::VAppPropertyInfo.new.tap do |p|
|
298
|
-
p.key = 6 # ditto. see above. it makes me sad, too.
|
299
|
-
p.label = 'public_ssh_key'
|
300
|
-
p.value = vm_config[:public_ssh_key]
|
301
|
-
end
|
302
|
-
end
|
303
|
-
|
304
|
-
vapp_property_specs << RbVmomi::VIM::VAppPropertySpec.new.tap do |spec|
|
305
|
-
spec.operation = 'edit'
|
306
|
-
spec.info = RbVmomi::VIM::VAppPropertyInfo.new.tap do |p|
|
307
|
-
p.key = 7 # ditto. see above. it makes me sad, too.
|
308
|
-
p.label = 'custom_hostname'
|
309
|
-
p.value = vm_config[:custom_hostname]
|
310
|
-
end
|
311
|
-
end unless vm_config[:custom_hostname].nil?
|
312
|
-
|
313
307
|
logger.info("END VAppPropertySpec creation vapp_property_specs=#{vapp_property_specs.inspect}")
|
314
308
|
vapp_property_specs
|
315
309
|
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<Envelope ovf:version="1.0"
|
3
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
4
|
+
xml:lang="en-US" xmlns="http://schemas.dmtf.org/ovf/envelope/1"
|
5
|
+
xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1"
|
6
|
+
xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData"
|
7
|
+
xmlns:vssd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData"
|
8
|
+
xmlns:vmw="http://www.vmware.com/schema/ovf">
|
9
|
+
|
10
|
+
<References>
|
11
|
+
<File ovf:href="pivotal-ops-manager-disk1.vmdk" ovf:size="4243996160" ovf:id="file1"/>
|
12
|
+
</References>
|
13
|
+
|
14
|
+
<DiskSection>
|
15
|
+
<Info>List of the virtual disks used in the package</Info>
|
16
|
+
<Disk ovf:capacity="171798603879"
|
17
|
+
ovf:diskId="vmdisk1"
|
18
|
+
ovf:fileRef="file1"
|
19
|
+
ovf:format="http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized"/>
|
20
|
+
</DiskSection>
|
21
|
+
|
22
|
+
<NetworkSection>
|
23
|
+
<Info>Logical networks used in the package</Info>
|
24
|
+
<Network ovf:name="Network 1">
|
25
|
+
<Description>Logical network used by this appliance.</Description>
|
26
|
+
</Network>
|
27
|
+
</NetworkSection>
|
28
|
+
|
29
|
+
<vmw:IpAssignmentSection ovf:required="false" vmw:protocols="IPv4" vmw:schemes="">
|
30
|
+
<Info>Supported IP assignment schemes</Info>
|
31
|
+
</vmw:IpAssignmentSection>
|
32
|
+
|
33
|
+
<VirtualSystem ovf:id="FAKE_FILENAME">
|
34
|
+
<Info>A virtual machine</Info>
|
35
|
+
|
36
|
+
<ProductSection>
|
37
|
+
<Info/>
|
38
|
+
<Product>Ops Manager</Product>
|
39
|
+
<Vendor>Pivotal</Vendor>
|
40
|
+
<Version>2.3-build.203</Version>
|
41
|
+
<Property ovf:key="ip0" ovf:userConfigurable="true" ovf:type="string">
|
42
|
+
<Label>IP Address</Label>
|
43
|
+
<Description>The IP address for the Ops Manager. Leave blank if DHCP is desired.</Description>
|
44
|
+
</Property>
|
45
|
+
<Property ovf:key="netmask0" ovf:userConfigurable="true" ovf:type="string">
|
46
|
+
<Label>Netmask</Label>
|
47
|
+
<Description>The netmask for the Ops Manager's network. Leave blank if DHCP is desired.</Description>
|
48
|
+
</Property>
|
49
|
+
<Property ovf:key="gateway" ovf:userConfigurable="true" ovf:type="string">
|
50
|
+
<Label>Default Gateway</Label>
|
51
|
+
<Description>The default gateway address for the Ops Manager's network. Leave blank if DHCP is desired.</Description>
|
52
|
+
</Property>
|
53
|
+
<Property ovf:key="DNS" ovf:userConfigurable="true" ovf:type="string">
|
54
|
+
<Label>DNS</Label>
|
55
|
+
<Description>The domain name servers for the Ops Manager (comma separated). Leave blank if DHCP is desired.</Description>
|
56
|
+
</Property>
|
57
|
+
<Property ovf:key="ntp_servers" ovf:userConfigurable="true" ovf:type="string">
|
58
|
+
<Label>NTP Servers</Label>
|
59
|
+
<Description>Comma-delimited list of NTP servers</Description>
|
60
|
+
</Property>
|
61
|
+
<Property ovf:key="admin_password" ovf:userConfigurable="true" ovf:type="password">
|
62
|
+
<Label>Admin Password</Label>
|
63
|
+
<Description>This password is used to SSH into the Ops Manager. The username is 'ubuntu'. One or both of Admin Password and SSH Key is required.</Description>
|
64
|
+
</Property>
|
65
|
+
<Property ovf:key="public_ssh_key" ovf:userConfigurable="true" ovf:type="string">
|
66
|
+
<Label>Public SSH Key</Label>
|
67
|
+
<Description>The Public SSH Key is used to allow SSHing into the Ops Manager with your private ssh key. The username is 'ubuntu'. One or both of Admin Password and SSH Key is required.</Description>
|
68
|
+
</Property>
|
69
|
+
<Property ovf:key="custom_hostname" ovf:userConfigurable="true" ovf:type="string">
|
70
|
+
<Label>Custom Hostname</Label>
|
71
|
+
<Description>This will be set as the hostname on the VM. Default: 'pivotal-ops-manager'.</Description>
|
72
|
+
</Property>
|
73
|
+
</ProductSection>
|
74
|
+
|
75
|
+
<AnnotationSection>
|
76
|
+
<Info/>
|
77
|
+
<Annotation>Ops Manager for Pivotal Cloud Foundry
|
78
|
+
installs and manages PCF products and services.</Annotation>
|
79
|
+
</AnnotationSection>
|
80
|
+
|
81
|
+
<VirtualHardwareSection ovf:required="false" ovf:transport="com.vmware.guestInfo">
|
82
|
+
<Info>Virtual hardware requirements for a virtual machine</Info>
|
83
|
+
<System>
|
84
|
+
<vssd:ElementName>Virtual Hardware Family</vssd:ElementName>
|
85
|
+
<vssd:InstanceID>0</vssd:InstanceID>
|
86
|
+
<vssd:VirtualSystemIdentifier>FAKE_FILENAME</vssd:VirtualSystemIdentifier>
|
87
|
+
<vssd:VirtualSystemType>vmx-09</vssd:VirtualSystemType>
|
88
|
+
</System>
|
89
|
+
<Item>
|
90
|
+
<rasd:Caption>1 virtual CPU</rasd:Caption>
|
91
|
+
<rasd:Description>Number of virtual CPUs</rasd:Description>
|
92
|
+
<rasd:ElementName>1 virtual CPU</rasd:ElementName>
|
93
|
+
<rasd:InstanceID>1</rasd:InstanceID>
|
94
|
+
<rasd:ResourceType>3</rasd:ResourceType>
|
95
|
+
<rasd:VirtualQuantity>1</rasd:VirtualQuantity>
|
96
|
+
</Item>
|
97
|
+
<Item>
|
98
|
+
<rasd:AllocationUnits>MegaBytes</rasd:AllocationUnits>
|
99
|
+
<rasd:Caption>8192 MB of memory</rasd:Caption>
|
100
|
+
<rasd:Description>Memory Size</rasd:Description>
|
101
|
+
<rasd:ElementName>8192 MB of memory</rasd:ElementName>
|
102
|
+
<rasd:InstanceID>2</rasd:InstanceID>
|
103
|
+
<rasd:ResourceType>4</rasd:ResourceType>
|
104
|
+
<rasd:VirtualQuantity>8192</rasd:VirtualQuantity>
|
105
|
+
</Item>
|
106
|
+
<Item>
|
107
|
+
<rasd:Address>0</rasd:Address>
|
108
|
+
<rasd:Caption>scsiController0</rasd:Caption>
|
109
|
+
<rasd:Description>SCSI Controller</rasd:Description>
|
110
|
+
<rasd:ElementName>scsiController0</rasd:ElementName>
|
111
|
+
<rasd:InstanceID>3</rasd:InstanceID>
|
112
|
+
<rasd:ResourceSubType>lsilogic</rasd:ResourceSubType>
|
113
|
+
<rasd:ResourceType>6</rasd:ResourceType>
|
114
|
+
</Item>
|
115
|
+
<Item>
|
116
|
+
<rasd:AutomaticAllocation>true</rasd:AutomaticAllocation>
|
117
|
+
<rasd:Caption>Ethernet adapter on 'Network 1'</rasd:Caption>
|
118
|
+
<rasd:Connection>Network 1</rasd:Connection>
|
119
|
+
<rasd:ElementName>Ethernet adapter on 'Network 1'</rasd:ElementName>
|
120
|
+
<rasd:InstanceID>4</rasd:InstanceID>
|
121
|
+
<rasd:ResourceSubType>E1000</rasd:ResourceSubType>
|
122
|
+
<rasd:ResourceType>10</rasd:ResourceType>
|
123
|
+
</Item>
|
124
|
+
<Item>
|
125
|
+
<rasd:AddressOnParent>0</rasd:AddressOnParent>
|
126
|
+
<rasd:Caption>disk1</rasd:Caption>
|
127
|
+
<rasd:Description>Disk Image</rasd:Description>
|
128
|
+
<rasd:ElementName>disk1</rasd:ElementName>
|
129
|
+
<rasd:HostResource>/disk/vmdisk1</rasd:HostResource>
|
130
|
+
<rasd:InstanceID>5</rasd:InstanceID>
|
131
|
+
<rasd:Parent>3</rasd:Parent>
|
132
|
+
<rasd:ResourceType>17</rasd:ResourceType>
|
133
|
+
</Item>
|
134
|
+
</VirtualHardwareSection>
|
135
|
+
</VirtualSystem>
|
136
|
+
</Envelope>
|
@@ -0,0 +1,132 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<Envelope ovf:version="1.0"
|
3
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
4
|
+
xml:lang="en-US" xmlns="http://schemas.dmtf.org/ovf/envelope/1"
|
5
|
+
xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1"
|
6
|
+
xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData"
|
7
|
+
xmlns:vssd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData"
|
8
|
+
xmlns:vmw="http://www.vmware.com/schema/ovf">
|
9
|
+
|
10
|
+
<References>
|
11
|
+
<File ovf:href="pivotal-ops-manager-disk1.vmdk" ovf:size="4223308288" ovf:id="file1"/>
|
12
|
+
</References>
|
13
|
+
|
14
|
+
<DiskSection>
|
15
|
+
<Info>List of the virtual disks used in the package</Info>
|
16
|
+
<Disk ovf:capacity="171798603879"
|
17
|
+
ovf:diskId="vmdisk1"
|
18
|
+
ovf:fileRef="file1"
|
19
|
+
ovf:format="http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized"/>
|
20
|
+
</DiskSection>
|
21
|
+
|
22
|
+
<NetworkSection>
|
23
|
+
<Info>Logical networks used in the package</Info>
|
24
|
+
<Network ovf:name="Network 1">
|
25
|
+
<Description>Logical network used by this appliance.</Description>
|
26
|
+
</Network>
|
27
|
+
</NetworkSection>
|
28
|
+
|
29
|
+
<vmw:IpAssignmentSection ovf:required="false" vmw:protocols="IPv4" vmw:schemes="">
|
30
|
+
<Info>Supported IP assignment schemes</Info>
|
31
|
+
</vmw:IpAssignmentSection>
|
32
|
+
|
33
|
+
<VirtualSystem ovf:id="FAKE_FILENAME">
|
34
|
+
<Info>A virtual machine</Info>
|
35
|
+
|
36
|
+
<ProductSection>
|
37
|
+
<Info/>
|
38
|
+
<Product>Ops Manager</Product>
|
39
|
+
<Vendor>Pivotal</Vendor>
|
40
|
+
<Version>2.2-build.365</Version>
|
41
|
+
<Property ovf:key="ip0" ovf:userConfigurable="true" ovf:type="string">
|
42
|
+
<Label>IP Address</Label>
|
43
|
+
<Description>The IP address for the Ops Manager. Leave blank if DHCP is desired.</Description>
|
44
|
+
</Property>
|
45
|
+
<Property ovf:key="netmask0" ovf:userConfigurable="true" ovf:type="string">
|
46
|
+
<Label>Netmask</Label>
|
47
|
+
<Description>The netmask for the Ops Manager's network. Leave blank if DHCP is desired.</Description>
|
48
|
+
</Property>
|
49
|
+
<Property ovf:key="gateway" ovf:userConfigurable="true" ovf:type="string">
|
50
|
+
<Label>Default Gateway</Label>
|
51
|
+
<Description>The default gateway address for the Ops Manager's network. Leave blank if DHCP is desired.</Description>
|
52
|
+
</Property>
|
53
|
+
<Property ovf:key="DNS" ovf:userConfigurable="true" ovf:type="string">
|
54
|
+
<Label>DNS</Label>
|
55
|
+
<Description>The domain name servers for the Ops Manager (comma separated). Leave blank if DHCP is desired.</Description>
|
56
|
+
</Property>
|
57
|
+
<Property ovf:key="ntp_servers" ovf:userConfigurable="true" ovf:type="string">
|
58
|
+
<Label>NTP Servers</Label>
|
59
|
+
<Description>Comma-delimited list of NTP servers</Description>
|
60
|
+
</Property>
|
61
|
+
<Property ovf:key="admin_password" ovf:required="true" ovf:userConfigurable="true" ovf:type="password">
|
62
|
+
<Label>Admin Password</Label>
|
63
|
+
<Description>This password is used to SSH into the Ops Manager. The username is 'ubuntu'.</Description>
|
64
|
+
</Property>
|
65
|
+
<Property ovf:key="custom_hostname" ovf:userConfigurable="true" ovf:type="string">
|
66
|
+
<Label>Custom Hostname</Label>
|
67
|
+
<Description>This will be set as the hostname on the VM. Default: 'pivotal-ops-manager'.</Description>
|
68
|
+
</Property>
|
69
|
+
</ProductSection>
|
70
|
+
|
71
|
+
<AnnotationSection>
|
72
|
+
<Info/>
|
73
|
+
<Annotation>Ops Manager for Pivotal Cloud Foundry
|
74
|
+
installs and manages PCF products and services.</Annotation>
|
75
|
+
</AnnotationSection>
|
76
|
+
|
77
|
+
<VirtualHardwareSection ovf:required="false" ovf:transport="com.vmware.guestInfo">
|
78
|
+
<Info>Virtual hardware requirements for a virtual machine</Info>
|
79
|
+
<System>
|
80
|
+
<vssd:ElementName>Virtual Hardware Family</vssd:ElementName>
|
81
|
+
<vssd:InstanceID>0</vssd:InstanceID>
|
82
|
+
<vssd:VirtualSystemIdentifier>FAKE_FILENAME</vssd:VirtualSystemIdentifier>
|
83
|
+
<vssd:VirtualSystemType>vmx-09</vssd:VirtualSystemType>
|
84
|
+
</System>
|
85
|
+
<Item>
|
86
|
+
<rasd:Caption>1 virtual CPU</rasd:Caption>
|
87
|
+
<rasd:Description>Number of virtual CPUs</rasd:Description>
|
88
|
+
<rasd:ElementName>1 virtual CPU</rasd:ElementName>
|
89
|
+
<rasd:InstanceID>1</rasd:InstanceID>
|
90
|
+
<rasd:ResourceType>3</rasd:ResourceType>
|
91
|
+
<rasd:VirtualQuantity>1</rasd:VirtualQuantity>
|
92
|
+
</Item>
|
93
|
+
<Item>
|
94
|
+
<rasd:AllocationUnits>MegaBytes</rasd:AllocationUnits>
|
95
|
+
<rasd:Caption>8192 MB of memory</rasd:Caption>
|
96
|
+
<rasd:Description>Memory Size</rasd:Description>
|
97
|
+
<rasd:ElementName>8192 MB of memory</rasd:ElementName>
|
98
|
+
<rasd:InstanceID>2</rasd:InstanceID>
|
99
|
+
<rasd:ResourceType>4</rasd:ResourceType>
|
100
|
+
<rasd:VirtualQuantity>8192</rasd:VirtualQuantity>
|
101
|
+
</Item>
|
102
|
+
<Item>
|
103
|
+
<rasd:Address>0</rasd:Address>
|
104
|
+
<rasd:Caption>scsiController0</rasd:Caption>
|
105
|
+
<rasd:Description>SCSI Controller</rasd:Description>
|
106
|
+
<rasd:ElementName>scsiController0</rasd:ElementName>
|
107
|
+
<rasd:InstanceID>3</rasd:InstanceID>
|
108
|
+
<rasd:ResourceSubType>lsilogic</rasd:ResourceSubType>
|
109
|
+
<rasd:ResourceType>6</rasd:ResourceType>
|
110
|
+
</Item>
|
111
|
+
<Item>
|
112
|
+
<rasd:AutomaticAllocation>true</rasd:AutomaticAllocation>
|
113
|
+
<rasd:Caption>Ethernet adapter on 'Network 1'</rasd:Caption>
|
114
|
+
<rasd:Connection>Network 1</rasd:Connection>
|
115
|
+
<rasd:ElementName>Ethernet adapter on 'Network 1'</rasd:ElementName>
|
116
|
+
<rasd:InstanceID>4</rasd:InstanceID>
|
117
|
+
<rasd:ResourceSubType>E1000</rasd:ResourceSubType>
|
118
|
+
<rasd:ResourceType>10</rasd:ResourceType>
|
119
|
+
</Item>
|
120
|
+
<Item>
|
121
|
+
<rasd:AddressOnParent>0</rasd:AddressOnParent>
|
122
|
+
<rasd:Caption>disk1</rasd:Caption>
|
123
|
+
<rasd:Description>Disk Image</rasd:Description>
|
124
|
+
<rasd:ElementName>disk1</rasd:ElementName>
|
125
|
+
<rasd:HostResource>/disk/vmdisk1</rasd:HostResource>
|
126
|
+
<rasd:InstanceID>5</rasd:InstanceID>
|
127
|
+
<rasd:Parent>3</rasd:Parent>
|
128
|
+
<rasd:ResourceType>17</rasd:ResourceType>
|
129
|
+
</Item>
|
130
|
+
</VirtualHardwareSection>
|
131
|
+
</VirtualSystem>
|
132
|
+
</Envelope>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
iaas_type: vsphere
|
2
|
+
vm_shepherd:
|
3
|
+
vm_configs:
|
4
|
+
- vcenter_creds:
|
5
|
+
ip: OVA_URL
|
6
|
+
username: OVA_ORGANIZATION
|
7
|
+
password: OVA_PASSWORD
|
8
|
+
vsphere:
|
9
|
+
datacenter: VSPHERE_DATACENTER
|
10
|
+
cluster: VSPHERE_CLUSTER
|
11
|
+
network: VSPHERE_NETWORK
|
12
|
+
resource_pool: VSPHERE_RESOURCE_POOL
|
13
|
+
datastore: VSPHERE_DATASTORE
|
14
|
+
folder: VSPHERE_FOLDER
|
15
|
+
vm:
|
16
|
+
ip: OVA_IP
|
17
|
+
gateway: OVA_GATEWAY
|
18
|
+
netmask: OVA_NETMASK
|
19
|
+
dns: OVA_DNS
|
20
|
+
ntp_servers: OVA_NTP
|
21
|
+
public_ssh_key: OVA_SSH_KEY
|
22
|
+
cpus: OVA_CPUS
|
23
|
+
ram_mb: OVA_RAM_MB
|
24
|
+
vm_password: not-tempest
|
25
|
+
custom_hostname: not-default-hostname
|
26
|
+
cleanup:
|
27
|
+
datacenter: VSPHERE_OTHER_DATACENTER
|
28
|
+
datastores:
|
29
|
+
- VSPHERE_DATASTORE_ONE
|
30
|
+
- VSPHERE_DATASTORE_TWO
|
31
|
+
datacenter_folders_to_clean:
|
32
|
+
- DC_FOLDER_ONE
|
33
|
+
- DC_FOLDER_TWO
|
34
|
+
datastore_folders_to_clean:
|
35
|
+
- DS_DISK_FOLDER
|
@@ -320,6 +320,27 @@ module VmShepherd
|
|
320
320
|
end
|
321
321
|
end
|
322
322
|
|
323
|
+
context 'when the instance type is specified in the vm config' do
|
324
|
+
let(:vm_config) do
|
325
|
+
{
|
326
|
+
'vm_name' => 'some-vm-name',
|
327
|
+
'key_name' => 'ssh-key-name',
|
328
|
+
'instance_type' => 't3.medium'
|
329
|
+
}
|
330
|
+
end
|
331
|
+
|
332
|
+
it 'creates an instance' do
|
333
|
+
expect(ec2).to receive_message_chain(:instances, :create).with(
|
334
|
+
image_id: ami_id,
|
335
|
+
key_name: 'ssh-key-name',
|
336
|
+
security_group_ids: ['security-group-id'],
|
337
|
+
subnet: 'public-subnet-id',
|
338
|
+
instance_type: 't3.medium').and_return(instance)
|
339
|
+
|
340
|
+
ami_manager.deploy(ami_file_path: ami_file_path, vm_config: vm_config)
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
323
344
|
context 'when the ip address is in use' do
|
324
345
|
it 'retries until the IP address is available' do
|
325
346
|
expect(instances).to receive(:create).and_raise(AWS::EC2::Errors::InvalidIPAddress::InUse).once
|
@@ -281,6 +281,215 @@ module VmShepherd
|
|
281
281
|
manager.deploy(paths: ['FIRST_FAKE_PATH', 'LAST_FAKE_PATH'])
|
282
282
|
end
|
283
283
|
end
|
284
|
+
|
285
|
+
context 'when provision environment variables are set' do
|
286
|
+
before do
|
287
|
+
allow(VsphereManager).to receive(:new).with(
|
288
|
+
first_config.dig('vcenter_creds', 'ip'),
|
289
|
+
first_config.dig('vcenter_creds', 'username'),
|
290
|
+
first_config.dig('vcenter_creds', 'password'),
|
291
|
+
first_config.dig('vsphere', 'datacenter'),
|
292
|
+
instance_of(Logger),
|
293
|
+
).and_return(first_ova_manager)
|
294
|
+
|
295
|
+
allow_any_instance_of(Shepherd).to receive(:read_assets_home).and_return('A PUBLIC KEY')
|
296
|
+
end
|
297
|
+
let(:settings_fixture_name) { 'vsphere-one-vm-config.yml' }
|
298
|
+
|
299
|
+
context 'when the PROVISION_WITH_PASSWORD environment variable is set' do
|
300
|
+
context 'and it is true' do
|
301
|
+
before { stub_const('ENV', {'PROVISION_WITH_PASSWORD' => 'true'}) }
|
302
|
+
|
303
|
+
context 'when the vm_password is set' do
|
304
|
+
before { stub_const('ENV', {'PROVISION_WITH_PASSWORD' => 'true', 'VSPHERE_VM_PASSWORD' => 'a-password'}) }
|
305
|
+
it 'deploys with the set vm password' do
|
306
|
+
expect(first_ova_manager).to receive(:deploy).with(
|
307
|
+
'FIRST_FAKE_PATH',
|
308
|
+
{
|
309
|
+
ip: first_config.dig('vm', 'ip'),
|
310
|
+
gateway: first_config.dig('vm', 'gateway'),
|
311
|
+
netmask: first_config.dig('vm', 'netmask'),
|
312
|
+
dns: first_config.dig('vm', 'dns'),
|
313
|
+
ntp_servers: first_config.dig('vm', 'ntp_servers'),
|
314
|
+
cpus: first_config.dig('vm', 'cpus'),
|
315
|
+
ram_mb: first_config.dig('vm', 'ram_mb'),
|
316
|
+
vm_password: first_config.dig('vm', 'vm_password'),
|
317
|
+
public_ssh_key: 'A PUBLIC KEY',
|
318
|
+
custom_hostname: first_config.dig('vm', 'custom_hostname')
|
319
|
+
},
|
320
|
+
{
|
321
|
+
cluster: first_config.dig('vsphere', 'cluster'),
|
322
|
+
resource_pool: first_config.dig('vsphere', 'resource_pool'),
|
323
|
+
datastore: first_config.dig('vsphere', 'datastore'),
|
324
|
+
network: first_config.dig('vsphere', 'network'),
|
325
|
+
folder: first_config.dig('vsphere', 'folder'),
|
326
|
+
},
|
327
|
+
)
|
328
|
+
|
329
|
+
manager.deploy(paths: ['FIRST_FAKE_PATH'])
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
context 'when the ENV vsphere VM password is set' do
|
334
|
+
before do
|
335
|
+
stub_const('ENV', { 'PROVISION_WITH_PASSWORD' => 'true', 'VSPHERE_VM_PASSWORD' => 'a-password' })
|
336
|
+
first_config['vm']['vm_password'] = nil
|
337
|
+
end
|
338
|
+
|
339
|
+
it 'deploys with the ENV vm password' do
|
340
|
+
expect(first_ova_manager).to receive(:deploy).with(
|
341
|
+
'FIRST_FAKE_PATH',
|
342
|
+
{
|
343
|
+
ip: first_config.dig('vm', 'ip'),
|
344
|
+
gateway: first_config.dig('vm', 'gateway'),
|
345
|
+
netmask: first_config.dig('vm', 'netmask'),
|
346
|
+
dns: first_config.dig('vm', 'dns'),
|
347
|
+
ntp_servers: first_config.dig('vm', 'ntp_servers'),
|
348
|
+
cpus: first_config.dig('vm', 'cpus'),
|
349
|
+
ram_mb: first_config.dig('vm', 'ram_mb'),
|
350
|
+
vm_password: 'a-password',
|
351
|
+
public_ssh_key: 'A PUBLIC KEY',
|
352
|
+
custom_hostname: first_config.dig('vm', 'custom_hostname')
|
353
|
+
},
|
354
|
+
{
|
355
|
+
cluster: first_config.dig('vsphere', 'cluster'),
|
356
|
+
resource_pool: first_config.dig('vsphere', 'resource_pool'),
|
357
|
+
datastore: first_config.dig('vsphere', 'datastore'),
|
358
|
+
network: first_config.dig('vsphere', 'network'),
|
359
|
+
folder: first_config.dig('vsphere', 'folder'),
|
360
|
+
},
|
361
|
+
)
|
362
|
+
|
363
|
+
manager.deploy(paths: ['FIRST_FAKE_PATH'])
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
context 'and neither vm password is set' do
|
368
|
+
before do
|
369
|
+
first_config['vm']['vm_password'] = nil
|
370
|
+
end
|
371
|
+
|
372
|
+
it 'deploys with the hardcoded vm password' do
|
373
|
+
expect(first_ova_manager).to receive(:deploy).with(
|
374
|
+
'FIRST_FAKE_PATH',
|
375
|
+
{
|
376
|
+
ip: first_config.dig('vm', 'ip'),
|
377
|
+
gateway: first_config.dig('vm', 'gateway'),
|
378
|
+
netmask: first_config.dig('vm', 'netmask'),
|
379
|
+
dns: first_config.dig('vm', 'dns'),
|
380
|
+
ntp_servers: first_config.dig('vm', 'ntp_servers'),
|
381
|
+
cpus: first_config.dig('vm', 'cpus'),
|
382
|
+
ram_mb: first_config.dig('vm', 'ram_mb'),
|
383
|
+
vm_password: 'tempest',
|
384
|
+
public_ssh_key: 'A PUBLIC KEY',
|
385
|
+
custom_hostname: first_config.dig('vm', 'custom_hostname')
|
386
|
+
},
|
387
|
+
{
|
388
|
+
cluster: first_config.dig('vsphere', 'cluster'),
|
389
|
+
resource_pool: first_config.dig('vsphere', 'resource_pool'),
|
390
|
+
datastore: first_config.dig('vsphere', 'datastore'),
|
391
|
+
network: first_config.dig('vsphere', 'network'),
|
392
|
+
folder: first_config.dig('vsphere', 'folder'),
|
393
|
+
},
|
394
|
+
)
|
395
|
+
manager.deploy(paths: ['FIRST_FAKE_PATH'])
|
396
|
+
end
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
context 'and it is false' do
|
401
|
+
before { stub_const('ENV', {'PROVISION_WITH_PASSWORD' => 'false'}) }
|
402
|
+
|
403
|
+
it 'deploys with a nil vm password' do
|
404
|
+
expect(first_ova_manager).to receive(:deploy).with(
|
405
|
+
'FIRST_FAKE_PATH',
|
406
|
+
{
|
407
|
+
ip: first_config.dig('vm', 'ip'),
|
408
|
+
gateway: first_config.dig('vm', 'gateway'),
|
409
|
+
netmask: first_config.dig('vm', 'netmask'),
|
410
|
+
dns: first_config.dig('vm', 'dns'),
|
411
|
+
ntp_servers: first_config.dig('vm', 'ntp_servers'),
|
412
|
+
cpus: first_config.dig('vm', 'cpus'),
|
413
|
+
ram_mb: first_config.dig('vm', 'ram_mb'),
|
414
|
+
vm_password: nil,
|
415
|
+
public_ssh_key: 'A PUBLIC KEY',
|
416
|
+
custom_hostname: first_config.dig('vm', 'custom_hostname')
|
417
|
+
},
|
418
|
+
{
|
419
|
+
cluster: first_config.dig('vsphere', 'cluster'),
|
420
|
+
resource_pool: first_config.dig('vsphere', 'resource_pool'),
|
421
|
+
datastore: first_config.dig('vsphere', 'datastore'),
|
422
|
+
network: first_config.dig('vsphere', 'network'),
|
423
|
+
folder: first_config.dig('vsphere', 'folder'),
|
424
|
+
},
|
425
|
+
)
|
426
|
+
manager.deploy(paths: ['FIRST_FAKE_PATH'])
|
427
|
+
end
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
context 'when the PROVISION_WITH_SSH_KEY environment variable is set' do
|
432
|
+
context 'and it is true' do
|
433
|
+
before { stub_const('ENV', {'PROVISION_WITH_SSH_KEY' => 'true'}) }
|
434
|
+
|
435
|
+
it 'deploys with the set public ssh key' do
|
436
|
+
expect(first_ova_manager).to receive(:deploy).with(
|
437
|
+
'FIRST_FAKE_PATH',
|
438
|
+
{
|
439
|
+
ip: first_config.dig('vm', 'ip'),
|
440
|
+
gateway: first_config.dig('vm', 'gateway'),
|
441
|
+
netmask: first_config.dig('vm', 'netmask'),
|
442
|
+
dns: first_config.dig('vm', 'dns'),
|
443
|
+
ntp_servers: first_config.dig('vm', 'ntp_servers'),
|
444
|
+
cpus: first_config.dig('vm', 'cpus'),
|
445
|
+
ram_mb: first_config.dig('vm', 'ram_mb'),
|
446
|
+
vm_password: first_config.dig('vm', 'vm_password'),
|
447
|
+
public_ssh_key: 'A PUBLIC KEY',
|
448
|
+
custom_hostname: first_config.dig('vm', 'custom_hostname')
|
449
|
+
},
|
450
|
+
{
|
451
|
+
cluster: first_config.dig('vsphere', 'cluster'),
|
452
|
+
resource_pool: first_config.dig('vsphere', 'resource_pool'),
|
453
|
+
datastore: first_config.dig('vsphere', 'datastore'),
|
454
|
+
network: first_config.dig('vsphere', 'network'),
|
455
|
+
folder: first_config.dig('vsphere', 'folder'),
|
456
|
+
},
|
457
|
+
)
|
458
|
+
manager.deploy(paths: ['FIRST_FAKE_PATH'])
|
459
|
+
end
|
460
|
+
end
|
461
|
+
|
462
|
+
context 'and it is false' do
|
463
|
+
before { stub_const('ENV', {'PROVISION_WITH_SSH_KEY' => 'false'}) }
|
464
|
+
|
465
|
+
it 'deploys with a nil public ssh key' do
|
466
|
+
expect(first_ova_manager).to receive(:deploy).with(
|
467
|
+
'FIRST_FAKE_PATH',
|
468
|
+
{
|
469
|
+
ip: first_config.dig('vm', 'ip'),
|
470
|
+
gateway: first_config.dig('vm', 'gateway'),
|
471
|
+
netmask: first_config.dig('vm', 'netmask'),
|
472
|
+
dns: first_config.dig('vm', 'dns'),
|
473
|
+
ntp_servers: first_config.dig('vm', 'ntp_servers'),
|
474
|
+
cpus: first_config.dig('vm', 'cpus'),
|
475
|
+
ram_mb: first_config.dig('vm', 'ram_mb'),
|
476
|
+
vm_password: first_config.dig('vm', 'vm_password'),
|
477
|
+
public_ssh_key: nil,
|
478
|
+
custom_hostname: first_config.dig('vm', 'custom_hostname')
|
479
|
+
},
|
480
|
+
{
|
481
|
+
cluster: first_config.dig('vsphere', 'cluster'),
|
482
|
+
resource_pool: first_config.dig('vsphere', 'resource_pool'),
|
483
|
+
datastore: first_config.dig('vsphere', 'datastore'),
|
484
|
+
network: first_config.dig('vsphere', 'network'),
|
485
|
+
folder: first_config.dig('vsphere', 'folder'),
|
486
|
+
},
|
487
|
+
)
|
488
|
+
manager.deploy(paths: ['FIRST_FAKE_PATH'])
|
489
|
+
end
|
490
|
+
end
|
491
|
+
end
|
492
|
+
end
|
284
493
|
end
|
285
494
|
|
286
495
|
context 'with AWS settings' do
|
@@ -616,6 +825,8 @@ module VmShepherd
|
|
616
825
|
datacenter_folders_to_clean: first_config.dig('cleanup', 'datacenter_folders_to_clean'),
|
617
826
|
datastores: first_config.dig('cleanup', 'datastores'),
|
618
827
|
datastore_folders_to_clean: first_config.dig('cleanup', 'datastore_folders_to_clean'),
|
828
|
+
cluster_name: first_config.dig('vsphere', 'cluster'),
|
829
|
+
resource_pool_name: first_config.dig('vsphere', 'resource_pool'),
|
619
830
|
}
|
620
831
|
end
|
621
832
|
let(:last_ova_manager) { instance_double(VsphereManager) }
|
@@ -624,6 +835,8 @@ module VmShepherd
|
|
624
835
|
datacenter_folders_to_clean: last_config.dig('cleanup', 'datacenter_folders_to_clean'),
|
625
836
|
datastores: last_config.dig('cleanup', 'datastores'),
|
626
837
|
datastore_folders_to_clean: last_config.dig('cleanup', 'datastore_folders_to_clean'),
|
838
|
+
cluster_name: last_config.dig('vsphere', 'cluster'),
|
839
|
+
resource_pool_name: last_config.dig('vsphere', 'resource_pool'),
|
627
840
|
}
|
628
841
|
end
|
629
842
|
|
@@ -48,18 +48,20 @@ module VmShepherd
|
|
48
48
|
let(:ovf_template) { instance_double(RbVmomi::VIM::VirtualMachine, name: 'vm_name', add_delta_disk_layer_on_all_disks: nil, MarkAsTemplate: nil) }
|
49
49
|
let(:vsphere_config) { { folder: folder_name, datastore: datastore_name } }
|
50
50
|
let(:vm_config) { {ip: '10.0.0.1'} }
|
51
|
+
let(:ovf_path) { 'spec/fixtures/ova_manager/default.ovf' }
|
51
52
|
|
52
53
|
before do
|
53
54
|
allow(vsphere_manager).to receive(:system).with("nc -z -w 1 #{vm_config[:ip]} 443").and_return(false)
|
54
55
|
allow(vsphere_manager).to receive(:system).with(/tar xfv/).and_return(true)
|
55
|
-
allow(Dir).to receive(:[]).and_return([
|
56
|
+
allow(Dir).to receive(:[]).and_return([ovf_path])
|
57
|
+
allow(FileUtils).to receive(:remove_entry_secure)
|
56
58
|
allow(vsphere_manager).to receive(:datacenter).and_return(datacenter)
|
57
59
|
allow(vsphere_manager).to receive(:connection).and_return(connection)
|
58
60
|
allow(ovf_manager).to receive(:deployOVF).and_return(ovf_template)
|
59
61
|
allow(vsphere_manager).to receive(:ovf_template_options).and_return({})
|
60
62
|
end
|
61
63
|
|
62
|
-
context 'When
|
64
|
+
context 'When a property value is not set' do
|
63
65
|
it 'verifies the value of custom hostname is nil' do
|
64
66
|
expect(vsphere_manager).to receive(:create_vm_from_template).and_return(vm1)
|
65
67
|
allow(subject).to receive(:power_on_vm)
|
@@ -69,7 +71,34 @@ module VmShepherd
|
|
69
71
|
custom_hostname_property = options[:spec].vAppConfig.property.find do |prop|
|
70
72
|
prop.instance_variable_get(:@props)[:info].instance_variable_get(:@props)[:label] == 'custom_hostname'
|
71
73
|
end
|
74
|
+
expect(custom_hostname_property.info.value).to be_nil
|
75
|
+
task
|
76
|
+
end
|
77
|
+
|
78
|
+
subject.deploy(ova_path, vm_config, vsphere_config)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'When the ovf does not contain a public_ssh_key property' do
|
83
|
+
let(:ovf_path) { 'spec/fixtures/ova_manager/without_public_ssh_key.ovf' }
|
84
|
+
let(:vm_config) { {ip: '10.0.0.1', custom_hostname: 'meow' } }
|
85
|
+
|
86
|
+
it 'does not create a property spec' do
|
87
|
+
expect(vsphere_manager).to receive(:create_vm_from_template).and_return(vm1)
|
88
|
+
allow(subject).to receive(:power_on_vm)
|
89
|
+
allow(task).to receive(:wait_for_completion)
|
90
|
+
|
91
|
+
expect(vm1).to receive(:ReconfigVM_Task) do |options|
|
92
|
+
custom_hostname_property = options[:spec].vAppConfig.property.find do |prop|
|
93
|
+
prop.instance_variable_get(:@props)[:info].instance_variable_get(:@props)[:label] == 'custom_hostname'
|
94
|
+
end
|
95
|
+
expect(custom_hostname_property.info.key).to eq(6)
|
96
|
+
|
97
|
+
custom_hostname_property = options[:spec].vAppConfig.property.find do |prop|
|
98
|
+
prop.instance_variable_get(:@props)[:info].instance_variable_get(:@props)[:label] == 'public_ssh_key'
|
99
|
+
end
|
72
100
|
expect(custom_hostname_property).to be_nil
|
101
|
+
|
73
102
|
task
|
74
103
|
end
|
75
104
|
|
data/vm_shepherd.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vm_shepherd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ops Manager Team
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-v1
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - '='
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 1.11.3
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: xmlrpc
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: bundler
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -167,12 +181,15 @@ files:
|
|
167
181
|
- lib/vm_shepherd/version.rb
|
168
182
|
- lib/vm_shepherd/vsphere_manager.rb
|
169
183
|
- spec/backport_refinements_spec.rb
|
184
|
+
- spec/fixtures/ova_manager/default.ovf
|
170
185
|
- spec/fixtures/ova_manager/foo.ova
|
186
|
+
- spec/fixtures/ova_manager/without_public_ssh_key.ovf
|
171
187
|
- spec/fixtures/shepherd/aws-no-elb.yml
|
172
188
|
- spec/fixtures/shepherd/aws.yml
|
173
189
|
- spec/fixtures/shepherd/openstack.yml
|
174
190
|
- spec/fixtures/shepherd/unknown.yml
|
175
191
|
- spec/fixtures/shepherd/vcloud.yml
|
192
|
+
- spec/fixtures/shepherd/vsphere-one-vm-config.yml
|
176
193
|
- spec/fixtures/shepherd/vsphere.yml
|
177
194
|
- spec/spec_helper.rb
|
178
195
|
- spec/support/patched_fog.rb
|
@@ -190,7 +207,7 @@ files:
|
|
190
207
|
homepage: ''
|
191
208
|
licenses: []
|
192
209
|
metadata: {}
|
193
|
-
post_install_message:
|
210
|
+
post_install_message:
|
194
211
|
rdoc_options: []
|
195
212
|
require_paths:
|
196
213
|
- lib
|
@@ -205,19 +222,21 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
205
222
|
- !ruby/object:Gem::Version
|
206
223
|
version: '0'
|
207
224
|
requirements: []
|
208
|
-
|
209
|
-
|
210
|
-
signing_key:
|
225
|
+
rubygems_version: 3.0.3
|
226
|
+
signing_key:
|
211
227
|
specification_version: 4
|
212
228
|
summary: A tool for booting and tearing down Ops Manager VMs on various Infrastructures.
|
213
229
|
test_files:
|
214
230
|
- spec/backport_refinements_spec.rb
|
231
|
+
- spec/fixtures/ova_manager/default.ovf
|
215
232
|
- spec/fixtures/ova_manager/foo.ova
|
233
|
+
- spec/fixtures/ova_manager/without_public_ssh_key.ovf
|
216
234
|
- spec/fixtures/shepherd/aws-no-elb.yml
|
217
235
|
- spec/fixtures/shepherd/aws.yml
|
218
236
|
- spec/fixtures/shepherd/openstack.yml
|
219
237
|
- spec/fixtures/shepherd/unknown.yml
|
220
238
|
- spec/fixtures/shepherd/vcloud.yml
|
239
|
+
- spec/fixtures/shepherd/vsphere-one-vm-config.yml
|
221
240
|
- spec/fixtures/shepherd/vsphere.yml
|
222
241
|
- spec/spec_helper.rb
|
223
242
|
- spec/support/patched_fog.rb
|