fog-vsphere 2.1.1 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +8 -0
- data/.rubocop_todo.yml +217 -0
- data/.travis.yml +1 -0
- data/CHANGELOG.md +4 -0
- data/Rakefile +10 -1
- data/fog-vsphere.gemspec +2 -2
- data/lib/fog/bin/vsphere.rb +1 -1
- data/lib/fog/vsphere/compute.rb +320 -301
- data/lib/fog/vsphere/models/compute/cdrom.rb +10 -10
- data/lib/fog/vsphere/models/compute/cdroms.rb +2 -2
- data/lib/fog/vsphere/models/compute/cluster.rb +20 -20
- data/lib/fog/vsphere/models/compute/clusters.rb +1 -1
- data/lib/fog/vsphere/models/compute/customfields.rb +4 -4
- data/lib/fog/vsphere/models/compute/customvalues.rb +8 -8
- data/lib/fog/vsphere/models/compute/datacenter.rb +16 -16
- data/lib/fog/vsphere/models/compute/datastores.rb +1 -1
- data/lib/fog/vsphere/models/compute/folder.rb +2 -2
- data/lib/fog/vsphere/models/compute/folders.rb +2 -2
- data/lib/fog/vsphere/models/compute/hosts.rb +4 -4
- data/lib/fog/vsphere/models/compute/interface.rb +12 -12
- data/lib/fog/vsphere/models/compute/interfaces.rb +14 -16
- data/lib/fog/vsphere/models/compute/interfacetype.rb +2 -2
- data/lib/fog/vsphere/models/compute/interfacetypes.rb +6 -8
- data/lib/fog/vsphere/models/compute/networks.rb +1 -1
- data/lib/fog/vsphere/models/compute/resource_pools.rb +1 -1
- data/lib/fog/vsphere/models/compute/rule.rb +8 -9
- data/lib/fog/vsphere/models/compute/rules.rb +9 -10
- data/lib/fog/vsphere/models/compute/scsicontroller.rb +1 -1
- data/lib/fog/vsphere/models/compute/server.rb +68 -80
- data/lib/fog/vsphere/models/compute/servers.rb +12 -13
- data/lib/fog/vsphere/models/compute/servertype.rb +6 -6
- data/lib/fog/vsphere/models/compute/servertypes.rb +2 -2
- data/lib/fog/vsphere/models/compute/snapshot.rb +5 -6
- data/lib/fog/vsphere/models/compute/snapshots.rb +1 -1
- data/lib/fog/vsphere/models/compute/ticket.rb +0 -1
- data/lib/fog/vsphere/models/compute/volume.rb +12 -14
- data/lib/fog/vsphere/models/compute/volumes.rb +10 -10
- data/lib/fog/vsphere/requests/compute/cloudinit_to_customspec.rb +8 -8
- data/lib/fog/vsphere/requests/compute/create_folder.rb +5 -5
- data/lib/fog/vsphere/requests/compute/create_group.rb +16 -16
- data/lib/fog/vsphere/requests/compute/create_rule.rb +13 -13
- data/lib/fog/vsphere/requests/compute/create_vm.rb +117 -119
- data/lib/fog/vsphere/requests/compute/destroy_group.rb +8 -8
- data/lib/fog/vsphere/requests/compute/destroy_rule.rb +8 -8
- data/lib/fog/vsphere/requests/compute/folder_destroy.rb +3 -3
- data/lib/fog/vsphere/requests/compute/get_cluster.rb +2 -2
- data/lib/fog/vsphere/requests/compute/get_compute_resource.rb +16 -16
- data/lib/fog/vsphere/requests/compute/get_datacenter.rb +7 -7
- data/lib/fog/vsphere/requests/compute/get_datastore.rb +1 -2
- data/lib/fog/vsphere/requests/compute/get_folder.rb +24 -24
- data/lib/fog/vsphere/requests/compute/get_host.rb +2 -3
- data/lib/fog/vsphere/requests/compute/get_interface_type.rb +6 -6
- data/lib/fog/vsphere/requests/compute/get_network.rb +7 -10
- data/lib/fog/vsphere/requests/compute/get_resource_pool.rb +1 -2
- data/lib/fog/vsphere/requests/compute/get_server_type.rb +14 -14
- data/lib/fog/vsphere/requests/compute/get_storage_pod.rb +2 -2
- data/lib/fog/vsphere/requests/compute/get_template.rb +1 -2
- data/lib/fog/vsphere/requests/compute/get_virtual_machine.rb +26 -26
- data/lib/fog/vsphere/requests/compute/get_vm_first_scsi_controller.rb +6 -7
- data/lib/fog/vsphere/requests/compute/host_finish_maintenance.rb +1 -1
- data/lib/fog/vsphere/requests/compute/host_shutdown.rb +1 -1
- data/lib/fog/vsphere/requests/compute/host_start_maintenance.rb +1 -1
- data/lib/fog/vsphere/requests/compute/list_child_snapshots.rb +37 -39
- data/lib/fog/vsphere/requests/compute/list_clusters.rb +8 -9
- data/lib/fog/vsphere/requests/compute/list_compute_resources.rb +57 -59
- data/lib/fog/vsphere/requests/compute/list_customfields.rb +5 -6
- data/lib/fog/vsphere/requests/compute/list_datacenters.rb +17 -17
- data/lib/fog/vsphere/requests/compute/list_datastores.rb +16 -15
- data/lib/fog/vsphere/requests/compute/list_folders.rb +4 -4
- data/lib/fog/vsphere/requests/compute/list_groups.rb +5 -5
- data/lib/fog/vsphere/requests/compute/list_hosts.rb +30 -14
- data/lib/fog/vsphere/requests/compute/list_interface_types.rb +7 -7
- data/lib/fog/vsphere/requests/compute/list_networks.rb +12 -16
- data/lib/fog/vsphere/requests/compute/list_processes.rb +14 -14
- data/lib/fog/vsphere/requests/compute/list_resource_pools.rb +13 -14
- data/lib/fog/vsphere/requests/compute/list_rules.rb +4 -4
- data/lib/fog/vsphere/requests/compute/list_server_types.rb +24 -26
- data/lib/fog/vsphere/requests/compute/list_storage_pods.rb +8 -8
- data/lib/fog/vsphere/requests/compute/list_templates.rb +4 -5
- data/lib/fog/vsphere/requests/compute/list_virtual_machines.rb +15 -15
- data/lib/fog/vsphere/requests/compute/list_vm_cdroms.rb +16 -12
- data/lib/fog/vsphere/requests/compute/list_vm_customvalues.rb +3 -4
- data/lib/fog/vsphere/requests/compute/list_vm_interfaces.rb +54 -56
- data/lib/fog/vsphere/requests/compute/list_vm_scsi_controllers.rb +7 -7
- data/lib/fog/vsphere/requests/compute/list_vm_snapshots.rb +36 -36
- data/lib/fog/vsphere/requests/compute/list_vm_volumes.rb +43 -36
- data/lib/fog/vsphere/requests/compute/modify_vm_cdrom.rb +4 -4
- data/lib/fog/vsphere/requests/compute/modify_vm_controller.rb +2 -2
- data/lib/fog/vsphere/requests/compute/modify_vm_interface.rb +26 -19
- data/lib/fog/vsphere/requests/compute/modify_vm_volume.rb +7 -7
- data/lib/fog/vsphere/requests/compute/revert_to_snapshot.rb +2 -2
- data/lib/fog/vsphere/requests/compute/set_vm_customvalue.rb +2 -2
- data/lib/fog/vsphere/requests/compute/update_vm.rb +111 -0
- data/lib/fog/vsphere/requests/compute/upload_iso.rb +10 -10
- data/lib/fog/vsphere/requests/compute/vm_acquire_ticket.rb +3 -3
- data/lib/fog/vsphere/requests/compute/vm_clone.rb +245 -247
- data/lib/fog/vsphere/requests/compute/vm_config_vnc.rb +15 -15
- data/lib/fog/vsphere/requests/compute/vm_destroy.rb +2 -2
- data/lib/fog/vsphere/requests/compute/vm_execute.rb +16 -16
- data/lib/fog/vsphere/requests/compute/vm_migrate.rb +11 -11
- data/lib/fog/vsphere/requests/compute/vm_power_off.rb +8 -8
- data/lib/fog/vsphere/requests/compute/vm_power_on.rb +2 -2
- data/lib/fog/vsphere/requests/compute/vm_reboot.rb +5 -5
- data/lib/fog/vsphere/requests/compute/vm_reconfig_cdrom.rb +11 -11
- data/lib/fog/vsphere/requests/compute/vm_reconfig_cpus.rb +8 -8
- data/lib/fog/vsphere/requests/compute/vm_reconfig_hardware.rb +6 -6
- data/lib/fog/vsphere/requests/compute/vm_reconfig_memory.rb +8 -8
- data/lib/fog/vsphere/requests/compute/vm_reconfig_volumes.rb +14 -16
- data/lib/fog/vsphere/requests/compute/vm_relocate.rb +8 -8
- data/lib/fog/vsphere/requests/compute/vm_remove_snapshot.rb +2 -2
- data/lib/fog/vsphere/requests/compute/vm_rename.rb +5 -5
- data/lib/fog/vsphere/requests/compute/vm_revert_snapshot.rb +1 -1
- data/lib/fog/vsphere/requests/compute/vm_take_snapshot.rb +8 -8
- data/lib/fog/vsphere/version.rb +1 -1
- data/tests/compute_tests.rb +16 -17
- data/tests/helpers/mock_helper.rb +3 -3
- data/tests/models/compute/cluster_tests.rb +4 -5
- data/tests/models/compute/hosts_tests.rb +2 -4
- data/tests/models/compute/rules_tests.rb +10 -16
- data/tests/models/compute/server_tests.rb +30 -31
- data/tests/models/compute/servers_tests.rb +2 -4
- data/tests/models/compute/ticket_tests.rb +4 -6
- data/tests/models/compute/tickets_tests.rb +1 -3
- data/tests/requests/compute/current_time_tests.rb +2 -4
- data/tests/requests/compute/folder_destroy_tests.rb +5 -7
- data/tests/requests/compute/get_network_tests.rb +20 -23
- data/tests/requests/compute/list_child_snapshots_tests.rb +1 -2
- data/tests/requests/compute/list_clusters_tests.rb +5 -6
- data/tests/requests/compute/list_datastores_tests.rb +6 -7
- data/tests/requests/compute/list_hosts_tests.rb +3 -4
- data/tests/requests/compute/list_networks_tests.rb +6 -7
- data/tests/requests/compute/list_storage_pods_test.rb +3 -4
- data/tests/requests/compute/list_virtual_machines_tests.rb +16 -20
- data/tests/requests/compute/list_vm_cdroms_tests.rb +1 -2
- data/tests/requests/compute/list_vm_snapshots_tests.rb +1 -2
- data/tests/requests/compute/modify_vm_cdrom_tests.rb +3 -4
- data/tests/requests/compute/revert_to_snapshot_tests.rb +2 -4
- data/tests/requests/compute/set_vm_customvalue_tests.rb +0 -2
- data/tests/requests/compute/update_vm_tests.rb +13 -0
- data/tests/requests/compute/vm_clone_tests.rb +20 -20
- data/tests/requests/compute/vm_config_vnc_tests.rb +3 -4
- data/tests/requests/compute/vm_destroy_tests.rb +1 -4
- data/tests/requests/compute/vm_migrate_tests.rb +1 -2
- data/tests/requests/compute/vm_power_off_tests.rb +2 -4
- data/tests/requests/compute/vm_power_on_tests.rb +1 -3
- data/tests/requests/compute/vm_reboot_tests.rb +2 -4
- data/tests/requests/compute/vm_reconfig_cdrom_tests.rb +2 -3
- data/tests/requests/compute/vm_reconfig_cpus_tests.rb +1 -3
- data/tests/requests/compute/vm_reconfig_hardware_tests.rb +2 -4
- data/tests/requests/compute/vm_reconfig_memory_tests.rb +1 -3
- data/tests/requests/compute/vm_take_snapshot_tests.rb +1 -3
- metadata +9 -4
@@ -3,21 +3,21 @@ module Fog
|
|
3
3
|
class Vsphere
|
4
4
|
class Real
|
5
5
|
def add_vm_cdrom(cdrom)
|
6
|
-
vm_reconfig_hardware('instance_uuid' => cdrom.server.instance_uuid, 'hardware_spec' => {'deviceChange'=>[create_cdrom(cdrom, cdrom.unit_number, :add)]})
|
6
|
+
vm_reconfig_hardware('instance_uuid' => cdrom.server.instance_uuid, 'hardware_spec' => { 'deviceChange' => [create_cdrom(cdrom, cdrom.unit_number, :add)] })
|
7
7
|
end
|
8
8
|
|
9
9
|
def destroy_vm_cdrom(cdrom)
|
10
|
-
vm_reconfig_hardware('instance_uuid' => cdrom.server.instance_uuid, 'hardware_spec' => {'deviceChange'=>[create_cdrom(cdrom, cdrom.unit_number, :remove)]})
|
10
|
+
vm_reconfig_hardware('instance_uuid' => cdrom.server.instance_uuid, 'hardware_spec' => { 'deviceChange' => [create_cdrom(cdrom, cdrom.unit_number, :remove)] })
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
14
|
class Mock
|
15
15
|
def add_vm_cdrom(cdrom)
|
16
|
-
vm_reconfig_hardware('instance_uuid' => cdrom.server.instance_uuid, 'hardware_spec' => {'deviceChange'=>[create_cdrom(cdrom, cdrom.unit_number, :add)]})
|
16
|
+
vm_reconfig_hardware('instance_uuid' => cdrom.server.instance_uuid, 'hardware_spec' => { 'deviceChange' => [create_cdrom(cdrom, cdrom.unit_number, :add)] })
|
17
17
|
end
|
18
18
|
|
19
19
|
def destroy_vm_cdrom(cdrom)
|
20
|
-
vm_reconfig_hardware('instance_uuid' => cdrom.server.instance_uuid, 'hardware_spec' => {'deviceChange'=>[create_cdrom(cdrom, cdrom.unit_number, :remove)]})
|
20
|
+
vm_reconfig_hardware('instance_uuid' => cdrom.server.instance_uuid, 'hardware_spec' => { 'deviceChange' => [create_cdrom(cdrom, cdrom.unit_number, :remove)] })
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
@@ -3,13 +3,13 @@ module Fog
|
|
3
3
|
class Vsphere
|
4
4
|
class Real
|
5
5
|
def add_vm_controller(controller)
|
6
|
-
vm_reconfig_hardware('instance_uuid' => controller.server_id, 'hardware_spec' => {'deviceChange'=>[create_controller(controller)]})
|
6
|
+
vm_reconfig_hardware('instance_uuid' => controller.server_id, 'hardware_spec' => { 'deviceChange' => [create_controller(controller)] })
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
10
|
class Mock
|
11
11
|
def add_vm_controller(controller)
|
12
|
-
vm_reconfig_hardware('instance_uuid' => controller.server_id, 'hardware_spec' => {'deviceChange'=>[create_controller(controller)]})
|
12
|
+
vm_reconfig_hardware('instance_uuid' => controller.server_id, 'hardware_spec' => { 'deviceChange' => [create_controller(controller)] })
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
@@ -3,52 +3,59 @@ module Fog
|
|
3
3
|
class Vsphere
|
4
4
|
class Real
|
5
5
|
def add_vm_interface(vmid, options = {})
|
6
|
-
raise ArgumentError,
|
6
|
+
raise ArgumentError, 'instance id is a required parameter' unless vmid
|
7
7
|
|
8
|
-
interface = get_interface_from_options(vmid, options.merge(:
|
9
|
-
vm_reconfig_hardware('instance_uuid' => vmid, 'hardware_spec' => {'deviceChange'=>[create_interface(interface, 0, :add, options)]})
|
8
|
+
interface = get_interface_from_options(vmid, options.merge(server_id: vmid))
|
9
|
+
vm_reconfig_hardware('instance_uuid' => vmid, 'hardware_spec' => { 'deviceChange' => [create_interface(interface, 0, :add, options)] })
|
10
10
|
end
|
11
11
|
|
12
12
|
def destroy_vm_interface(vmid, options = {})
|
13
|
-
raise ArgumentError,
|
13
|
+
raise ArgumentError, 'instance id is a required parameter' unless vmid
|
14
14
|
|
15
|
-
interface = get_interface_from_options(vmid, options.merge(:
|
16
|
-
vm_reconfig_hardware('instance_uuid' => vmid, 'hardware_spec' => {'deviceChange'=>[create_interface(interface, interface.key, :remove)]})
|
15
|
+
interface = get_interface_from_options(vmid, options.merge(server_id: vmid))
|
16
|
+
vm_reconfig_hardware('instance_uuid' => vmid, 'hardware_spec' => { 'deviceChange' => [create_interface(interface, interface.key, :remove)] })
|
17
17
|
end
|
18
18
|
|
19
19
|
def update_vm_interface(vmid, options = {})
|
20
|
-
raise ArgumentError,
|
20
|
+
raise ArgumentError, 'instance id is a required parameter' unless vmid
|
21
|
+
raise ArgumentError, "'datacenter' is a required key in options: #{options}" unless options.key?(:datacenter)
|
22
|
+
|
23
|
+
datacenter_name = options[:datacenter]
|
21
24
|
|
22
25
|
interface = get_interface_from_options(vmid, options)
|
23
|
-
raw_interface = get_raw_interface(vmid, key: interface.key)
|
26
|
+
raw_interface = get_raw_interface(vmid, key: interface.key, datacenter: datacenter_name)
|
27
|
+
|
24
28
|
if options[:network]
|
25
29
|
interface.network = options[:network]
|
26
|
-
backing = create_nic_backing(interface,
|
30
|
+
backing = create_nic_backing(interface, datacenter: datacenter_name)
|
27
31
|
raw_interface.backing = backing
|
28
32
|
end
|
33
|
+
|
29
34
|
apply_options_to_raw_interface(raw_interface, options)
|
35
|
+
|
30
36
|
spec = {
|
31
37
|
operation: :edit,
|
32
38
|
device: raw_interface
|
33
39
|
}
|
34
|
-
|
40
|
+
|
41
|
+
vm_reconfig_hardware('instance_uuid' => vmid, 'hardware_spec' => { 'deviceChange' => [spec] })
|
35
42
|
end
|
36
43
|
|
37
44
|
private
|
38
45
|
|
39
46
|
def get_interface_from_options(vmid, options)
|
40
|
-
if options
|
47
|
+
if options && options[:interface]
|
41
48
|
options[:interface]
|
42
49
|
|
43
|
-
elsif options[:key]
|
50
|
+
elsif options[:key] && (options[:key] > 0)
|
44
51
|
oldattributes = get_vm_interface(vmid, options)
|
45
52
|
Fog::Compute::Vsphere::Interface.new(oldattributes.merge(options))
|
46
53
|
|
47
|
-
elsif options[:type]
|
54
|
+
elsif options[:type] && options[:network]
|
48
55
|
Fog::Compute::Vsphere::Interface.new options
|
49
56
|
|
50
57
|
else
|
51
|
-
raise ArgumentError,
|
58
|
+
raise ArgumentError, 'interface is a required parameter or pass options with type and network'
|
52
59
|
end
|
53
60
|
end
|
54
61
|
|
@@ -64,18 +71,18 @@ module Fog
|
|
64
71
|
|
65
72
|
class Mock
|
66
73
|
def add_vm_interface(vmid, options = {})
|
67
|
-
raise ArgumentError,
|
68
|
-
raise ArgumentError,
|
74
|
+
raise ArgumentError, 'instance id is a required parameter' unless vmid
|
75
|
+
raise ArgumentError, 'interface is a required parameter' unless options && options[:interface]
|
69
76
|
true
|
70
77
|
end
|
71
78
|
|
72
79
|
def destroy_vm_interface(vmid, options = {})
|
73
|
-
raise ArgumentError,
|
74
|
-
raise ArgumentError,
|
80
|
+
raise ArgumentError, 'instance id is a required parameter' unless vmid
|
81
|
+
raise ArgumentError, 'interface is a required parameter' unless options && options[:interface]
|
75
82
|
true
|
76
83
|
end
|
77
84
|
|
78
|
-
def update_vm_interface(
|
85
|
+
def update_vm_interface(_vmid, options = {})
|
79
86
|
return unless options[:interface]
|
80
87
|
options[:interface].network = options[:network]
|
81
88
|
options[:interface].type = options[:type]
|
@@ -3,30 +3,30 @@ module Fog
|
|
3
3
|
class Vsphere
|
4
4
|
class Real
|
5
5
|
def add_vm_volume(volume)
|
6
|
-
vm_reconfig_hardware('instance_uuid' => volume.server_id, 'hardware_spec' => {'deviceChange'=>[create_disk(volume, :add)]})
|
6
|
+
vm_reconfig_hardware('instance_uuid' => volume.server_id, 'hardware_spec' => { 'deviceChange' => [create_disk(volume, :add)] })
|
7
7
|
end
|
8
8
|
|
9
9
|
def remove_vm_volume(volume)
|
10
|
-
vm_reconfig_hardware('instance_uuid' => volume.server_id, 'hardware_spec' => {'deviceChange'=>[create_disk(volume, :remove)]})
|
10
|
+
vm_reconfig_hardware('instance_uuid' => volume.server_id, 'hardware_spec' => { 'deviceChange' => [create_disk(volume, :remove)] })
|
11
11
|
end
|
12
12
|
|
13
13
|
def destroy_vm_volume(volume)
|
14
14
|
vm_reconfig_hardware('instance_uuid' => volume.server_id, 'hardware_spec' => {
|
15
|
-
|
16
|
-
|
15
|
+
'deviceChange' => [create_disk(volume, :remove, file_operation: :destroy)]
|
16
|
+
})
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
20
|
class Mock
|
21
21
|
def add_vm_volume(volume)
|
22
|
-
vm_reconfig_hardware('instance_uuid' => volume.server_id, 'hardware_spec' => {'deviceChange'=>[create_cdrom(volume, :add)]})
|
22
|
+
vm_reconfig_hardware('instance_uuid' => volume.server_id, 'hardware_spec' => { 'deviceChange' => [create_cdrom(volume, :add)] })
|
23
23
|
end
|
24
24
|
|
25
|
-
def remove_vm_volume(
|
25
|
+
def remove_vm_volume(_volume)
|
26
26
|
true
|
27
27
|
end
|
28
28
|
|
29
|
-
def destroy_vm_volume(
|
29
|
+
def destroy_vm_volume(_volume)
|
30
30
|
true
|
31
31
|
end
|
32
32
|
end
|
@@ -4,7 +4,7 @@ module Fog
|
|
4
4
|
class Real
|
5
5
|
def revert_to_snapshot(snapshot)
|
6
6
|
unless Snapshot === snapshot
|
7
|
-
|
7
|
+
raise ArgumentError, 'snapshot is a required parameter'
|
8
8
|
end
|
9
9
|
|
10
10
|
task = snapshot.mo_ref.RevertToSnapshot_Task
|
@@ -18,7 +18,7 @@ module Fog
|
|
18
18
|
|
19
19
|
class Mock
|
20
20
|
def revert_to_snapshot(snapshot)
|
21
|
-
|
21
|
+
raise ArgumentError, 'snapshot is a required parameter' if snapshot.nil?
|
22
22
|
|
23
23
|
{
|
24
24
|
'state' => 'success'
|
@@ -4,11 +4,11 @@ module Fog
|
|
4
4
|
class Real
|
5
5
|
def set_vm_customvalue(vm_id, key, value)
|
6
6
|
vm_ref = get_vm_ref(vm_id)
|
7
|
-
vm_ref.setCustomValue(:
|
7
|
+
vm_ref.setCustomValue(key: key, value: value)
|
8
8
|
end
|
9
9
|
end
|
10
10
|
class Mock
|
11
|
-
def set_vm_customvalue(
|
11
|
+
def set_vm_customvalue(_vm_id, _key, _value)
|
12
12
|
nil
|
13
13
|
end
|
14
14
|
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module Fog
|
2
|
+
module Compute
|
3
|
+
class Vsphere
|
4
|
+
class Real
|
5
|
+
def update_vm(server)
|
6
|
+
attributes = server.attributes
|
7
|
+
datacenter = attributes[:datacenter]
|
8
|
+
vm_mob_ref = get_vm_ref(attributes[:instance_uuid], datacenter)
|
9
|
+
|
10
|
+
device_change = []
|
11
|
+
spec = {}
|
12
|
+
|
13
|
+
# Name
|
14
|
+
spec[:name] = attributes[:name]
|
15
|
+
|
16
|
+
# CPUs
|
17
|
+
spec[:numCPUs] = attributes[:cpus]
|
18
|
+
spec[:numCoresPerSocket] = attributes[:corespersocket]
|
19
|
+
|
20
|
+
# Memory
|
21
|
+
spec[:memoryMB] = attributes[:memory_mb]
|
22
|
+
|
23
|
+
# Volumes
|
24
|
+
device_change.concat(update_vm_volumes_specs(vm_mob_ref, server.volumes))
|
25
|
+
|
26
|
+
# Networks
|
27
|
+
device_change.concat(update_vm_interfaces_specs(vm_mob_ref, server.interfaces, datacenter))
|
28
|
+
|
29
|
+
spec[:deviceChange] = device_change unless device_change.empty?
|
30
|
+
|
31
|
+
vm_reconfig_hardware('instance_uuid' => attributes[:instance_uuid], 'hardware_spec' => spec) unless spec.empty?
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def update_vm_interfaces_specs(vm_mob_ref, fog_interfaces, datacenter)
|
37
|
+
vm_nics = vm_mob_ref.config.hardware.device.grep(RbVmomi::VIM::VirtualEthernetCard)
|
38
|
+
modified_nics = fog_interfaces.to_a.take(vm_nics.size)
|
39
|
+
new_nics = fog_interfaces.to_a.drop(vm_nics.size)
|
40
|
+
|
41
|
+
specs = []
|
42
|
+
vm_nics.zip(modified_nics).each do |vm_nic, fog_nic|
|
43
|
+
if fog_nic
|
44
|
+
# Update the attributes on the existing nic
|
45
|
+
backing = create_nic_backing(fog_nic, datacenter: datacenter)
|
46
|
+
|
47
|
+
if nic_backing_different?(vm_nic.backing, backing)
|
48
|
+
vm_nic.backing = backing
|
49
|
+
specs << { operation: :edit, device: vm_nic }
|
50
|
+
end
|
51
|
+
else
|
52
|
+
specs << {
|
53
|
+
operation: :remove,
|
54
|
+
device: vm_nic
|
55
|
+
}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
specs.concat(new_nics.map { |nic| create_interface(nic, 0, :add, datacenter: datacenter) }) if new_nics.any?
|
60
|
+
|
61
|
+
specs
|
62
|
+
end
|
63
|
+
|
64
|
+
def update_vm_volumes_specs(vm_mob_ref, volumes)
|
65
|
+
vm_volumes = vm_mob_ref.config.hardware.device.grep(RbVmomi::VIM::VirtualDisk)
|
66
|
+
modified_volumes = volumes.to_a.take(vm_volumes.size)
|
67
|
+
new_volumes = volumes.to_a.drop(vm_volumes.size)
|
68
|
+
|
69
|
+
specs = []
|
70
|
+
vm_volumes.zip(modified_volumes).each do |vm_volume, fog_volume|
|
71
|
+
if fog_volume
|
72
|
+
update_volume_attributes(vm_volume, fog_volume)
|
73
|
+
|
74
|
+
specs << { operation: :edit, device: vm_volume }
|
75
|
+
next
|
76
|
+
end
|
77
|
+
|
78
|
+
specs << { operation: :remove, fileOperation: :destroy, device: vm_volume }
|
79
|
+
end
|
80
|
+
|
81
|
+
specs.concat(new_volumes.map { |volume| create_disk(volume) }) if new_volumes.any?
|
82
|
+
|
83
|
+
specs
|
84
|
+
end
|
85
|
+
|
86
|
+
def update_volume_attributes(vm_volume, fog_volume)
|
87
|
+
vm_volume.capacityInKB = fog_volume.size
|
88
|
+
vm_volume.backing.diskMode = fog_volume.mode
|
89
|
+
vm_volume.backing.thinProvisioned = fog_volume.thin
|
90
|
+
end
|
91
|
+
|
92
|
+
def nic_backing_different?(one, two)
|
93
|
+
return true if one.class != two.class
|
94
|
+
|
95
|
+
return true if one.is_a?(RbVmomi::VIM::VirtualEthernetCardDistributedVirtualPortBackingInfo) && (one.port.portgroupKey != two.port.portgroupKey || one.port.switchUuid != two.port.switchUuid)
|
96
|
+
|
97
|
+
return true if one.is_a?(RbVmomi::VIM::VirtualEthernetCardNetworkBackingInfo) && one.deviceName != two.deviceName && one.deviceType != twp.device
|
98
|
+
|
99
|
+
false
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
class Mock
|
104
|
+
def update_vm(_server)
|
105
|
+
# TODO: - currently useless and tests need to be re-though on a whole.
|
106
|
+
{ 'task_state' => 'success' }
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -4,15 +4,15 @@ module Fog
|
|
4
4
|
class Real
|
5
5
|
def upload_iso_check_options(options)
|
6
6
|
default_options = {
|
7
|
-
'upload_directory' => 'isos'
|
7
|
+
'upload_directory' => 'isos'
|
8
8
|
}
|
9
9
|
options = default_options.merge(options)
|
10
|
-
required_options = %w
|
10
|
+
required_options = %w[datacenter datastore local_path]
|
11
11
|
required_options.each do |param|
|
12
12
|
raise ArgumentError, "#{required_options.join(', ')} are required" unless options.key? param
|
13
13
|
end
|
14
|
-
raise Fog::Compute::Vsphere::NotFound, "Datacenter #{options[
|
15
|
-
raise Fog::Compute::Vsphere::NotFound, "Datastore #{options[
|
14
|
+
raise Fog::Compute::Vsphere::NotFound, "Datacenter #{options['datacenter']} Doesn't Exist!" unless get_datacenter(options['datacenter'])
|
15
|
+
raise Fog::Compute::Vsphere::NotFound, "Datastore #{options['datastore']} Doesn't Exist!" unless get_raw_datastore(options['datastore'], options['datacenter'])
|
16
16
|
options
|
17
17
|
end
|
18
18
|
|
@@ -21,13 +21,13 @@ module Fog
|
|
21
21
|
datastore = get_raw_datastore(options['datastore'], options['datacenter'])
|
22
22
|
datacenter = get_raw_datacenter(options['datacenter'])
|
23
23
|
filename = options['filename'] || File.basename(options['local_path'])
|
24
|
-
unless datastore.exists? options['upload_directory']+'/'
|
25
|
-
connection.serviceContent.fileManager.MakeDirectory :
|
26
|
-
|
27
|
-
|
24
|
+
unless datastore.exists? options['upload_directory'] + '/'
|
25
|
+
connection.serviceContent.fileManager.MakeDirectory name: "[#{options['datastore']}] #{options['upload_directory']}",
|
26
|
+
datacenter: datacenter,
|
27
|
+
createParentDirectories: false
|
28
28
|
end
|
29
|
-
datastore.upload options['upload_directory']+'/'+filename, options['local_path']
|
30
|
-
datastore.exists? options['upload_directory']+'/'+filename
|
29
|
+
datastore.upload options['upload_directory'] + '/' + filename, options['local_path']
|
30
|
+
datastore.exists? options['upload_directory'] + '/' + filename
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
@@ -3,12 +3,12 @@ module Fog
|
|
3
3
|
class Vsphere
|
4
4
|
class Real
|
5
5
|
def vm_acquire_ticket(options = {})
|
6
|
-
raise ArgumentError,
|
6
|
+
raise ArgumentError, 'instance_uuid is a required parameter' unless options.key?('instance_uuid')
|
7
7
|
ticket_type = options['ticket_type'] || 'webmks'
|
8
8
|
|
9
9
|
vm_mob_ref = get_vm_ref(options['instance_uuid'])
|
10
10
|
|
11
|
-
ticket = vm_mob_ref.AcquireTicket(:
|
11
|
+
ticket = vm_mob_ref.AcquireTicket(ticketType: ticket_type)
|
12
12
|
{
|
13
13
|
'ticket' => ticket.ticket,
|
14
14
|
'host' => ticket.host,
|
@@ -20,7 +20,7 @@ module Fog
|
|
20
20
|
|
21
21
|
class Mock
|
22
22
|
def vm_acquire_ticket(options = {})
|
23
|
-
raise ArgumentError,
|
23
|
+
raise ArgumentError, 'instance_uuid is a required parameter' unless options.key?('instance_uuid')
|
24
24
|
{
|
25
25
|
'ticket' => 'fdsfdsf',
|
26
26
|
'host' => 'esxi.example.com',
|
@@ -3,25 +3,26 @@ module Fog
|
|
3
3
|
class Vsphere
|
4
4
|
module Shared
|
5
5
|
private
|
6
|
+
|
6
7
|
def vm_clone_check_options(options)
|
7
8
|
default_options = {
|
8
9
|
'force' => false,
|
9
10
|
'linked_clone' => false,
|
10
|
-
'nic_type' => 'VirtualE1000'
|
11
|
+
'nic_type' => 'VirtualE1000'
|
11
12
|
}
|
12
13
|
options = default_options.merge(options)
|
13
|
-
options[
|
14
|
+
options['storage_pod'] = nil if options['storage_pod'] == ''
|
14
15
|
# Backwards compat for "path" option
|
15
|
-
options[
|
16
|
-
options[
|
17
|
-
required_options = %w
|
16
|
+
options['template_path'] ||= options['path']
|
17
|
+
options['path'] ||= options['template_path']
|
18
|
+
required_options = %w[datacenter template_path name]
|
18
19
|
required_options.each do |param|
|
19
20
|
raise ArgumentError, "#{required_options.join(', ')} are required" unless options.key? param
|
20
21
|
end
|
21
|
-
raise Fog::Compute::Vsphere::NotFound, "Datacenter #{options[
|
22
|
-
raise Fog::Compute::Vsphere::NotFound, "Template #{options[
|
22
|
+
raise Fog::Compute::Vsphere::NotFound, "Datacenter #{options['datacenter']} Doesn't Exist!" unless get_datacenter(options['datacenter'])
|
23
|
+
raise Fog::Compute::Vsphere::NotFound, "Template #{options['template_path']} Doesn't Exist!" unless get_virtual_machine(options['template_path'], options['datacenter'])
|
23
24
|
if options.key?('storage_pod') && !options['storage_pod'].nil? && !get_raw_storage_pod(options['storage_pod'], options['datacenter'])
|
24
|
-
raise Fog::Compute::Vsphere::NotFound, "Storage Pod #{options[
|
25
|
+
raise Fog::Compute::Vsphere::NotFound, "Storage Pod #{options['storage_pod']} Doesn't Exist!"
|
25
26
|
end
|
26
27
|
options
|
27
28
|
end
|
@@ -64,7 +65,7 @@ module Fog
|
|
64
65
|
# * 'numCoresPerSocket'<~Integer> - the number of cores per socket of the Destination VM
|
65
66
|
# * 'memoryMB'<~Integer> - the size of memory of the Destination VM in MB
|
66
67
|
# * customization_spec<~Hash>: Options are marked as required if you
|
67
|
-
# use this customization_spec.
|
68
|
+
# use this customization_spec.
|
68
69
|
# As defined https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Specification.html
|
69
70
|
# * encryptionKey <~array of bytes> Used to encrypt/decrypt password
|
70
71
|
# * globalIPSettings expects a hash, REQUIRED
|
@@ -72,7 +73,7 @@ module Fog
|
|
72
73
|
# * nicSettingMap expects an array
|
73
74
|
# * options expects a hash
|
74
75
|
# * All options can be parsed using a yaml template with cloudinit_to_customspec.rb
|
75
|
-
#
|
76
|
+
#
|
76
77
|
# OLD Values still supported:
|
77
78
|
# This only support cloning and setting DHCP on the first interface
|
78
79
|
# * 'domain'<~String> - *REQUIRED* This is put into
|
@@ -106,19 +107,19 @@ module Fog
|
|
106
107
|
|
107
108
|
# Options['dest_folder']<~String>
|
108
109
|
# Grab the destination folder object if it exists else use cloned mach
|
109
|
-
dest_folder_path = options.fetch('dest_folder','/') # default to root path ({dc_name}/vm/)
|
110
|
+
dest_folder_path = options.fetch('dest_folder', '/') # default to root path ({dc_name}/vm/)
|
110
111
|
dest_folder = get_raw_vmfolder(dest_folder_path, options['datacenter'])
|
111
112
|
|
112
113
|
# Options['resource_pool']<~Array>
|
113
114
|
# Now find _a_ resource pool to use for the clone if one is not specified
|
114
|
-
if
|
115
|
+
if options.key?('resource_pool') && options['resource_pool'].is_a?(Array) && options['resource_pool'].length == 2 && options['resource_pool'][1] != 'Resources'
|
115
116
|
cluster_name = options['resource_pool'][0]
|
116
117
|
pool_name = options['resource_pool'][1]
|
117
118
|
resource_pool = get_raw_resource_pool(pool_name, cluster_name, options['datacenter'])
|
118
|
-
elsif
|
119
|
+
elsif options.key?('resource_pool') && options['resource_pool'].is_a?(Array) && options['resource_pool'].length == 2 && options['resource_pool'][1] == 'Resources'
|
119
120
|
cluster_name = options['resource_pool'][0]
|
120
121
|
resource_pool = get_raw_resource_pool(nil, cluster_name, options['datacenter'])
|
121
|
-
elsif
|
122
|
+
elsif vm_mob_ref.resourcePool.nil?
|
122
123
|
# If the template is really a template then there is no associated resource pool,
|
123
124
|
# so we need to find one using the template's parent host or cluster
|
124
125
|
esx_host = vm_mob_ref.collect!('runtime.host')['runtime.host']
|
@@ -135,11 +136,9 @@ module Fog
|
|
135
136
|
|
136
137
|
# Options['host']<~String>
|
137
138
|
# The target host for the virtual machine. Optional.
|
138
|
-
if options.key?('host') && !options['host'].empty? && !cluster_name.nil?
|
139
|
-
|
140
|
-
|
141
|
-
host = nil
|
142
|
-
end
|
139
|
+
host = if options.key?('host') && !options['host'].empty? && !cluster_name.nil?
|
140
|
+
get_raw_host(options['host'], cluster_name, options['datacenter'])
|
141
|
+
end
|
143
142
|
|
144
143
|
# Options['datastore']<~String>
|
145
144
|
# Grab the datastore object if option is set
|
@@ -151,7 +150,7 @@ module Fog
|
|
151
150
|
device_change = []
|
152
151
|
# fully futured interfaces api: replace the current nics
|
153
152
|
# with the new based on the specification
|
154
|
-
if
|
153
|
+
if options.key?('interfaces')
|
155
154
|
if options.key?('network_label')
|
156
155
|
raise ArgumentError, "interfaces option can't be specified together with network_label"
|
157
156
|
end
|
@@ -168,34 +167,34 @@ module Fog
|
|
168
167
|
# https://github.com/rlane/rbvmomi/blob/master/test/test_serialization.rb
|
169
168
|
# http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.vm.ConfigSpec.html
|
170
169
|
# FIXME: pad this out with the rest of the useful things in VirtualMachineConfigSpec
|
171
|
-
virtual_machine_config_spec.numCPUs = options['numCPUs'] if
|
170
|
+
virtual_machine_config_spec.numCPUs = options['numCPUs'] if options.key?('numCPUs')
|
172
171
|
virtual_machine_config_spec.numCoresPerSocket = options['numCoresPerSocket'] if options.key?('numCoresPerSocket')
|
173
|
-
virtual_machine_config_spec.memoryMB = options['memoryMB'] if
|
174
|
-
virtual_machine_config_spec.cpuHotAddEnabled = options['cpuHotAddEnabled'] if
|
175
|
-
virtual_machine_config_spec.memoryHotAddEnabled = options['memoryHotAddEnabled'] if
|
176
|
-
virtual_machine_config_spec.firmware = options['firmware'] if
|
177
|
-
virtual_machine_config_spec.extraConfig = extra_config(extra_config: options['extraConfig']) if
|
172
|
+
virtual_machine_config_spec.memoryMB = options['memoryMB'] if options.key?('memoryMB')
|
173
|
+
virtual_machine_config_spec.cpuHotAddEnabled = options['cpuHotAddEnabled'] if options.key?('cpuHotAddEnabled')
|
174
|
+
virtual_machine_config_spec.memoryHotAddEnabled = options['memoryHotAddEnabled'] if options.key?('memoryHotAddEnabled')
|
175
|
+
virtual_machine_config_spec.firmware = options['firmware'] if options.key?('firmware')
|
176
|
+
virtual_machine_config_spec.extraConfig = extra_config(extra_config: options['extraConfig']) if options.key?('extraConfig')
|
178
177
|
if @vsphere_rev.to_f >= 5 && options.key?('boot_order')
|
179
178
|
boot_order = options['boot_order'].flat_map do |boot_device|
|
180
179
|
case boot_device.to_sym
|
181
180
|
when :network
|
182
181
|
interfaces = device_change.select do |change|
|
183
|
-
[
|
182
|
+
%i[edit add].include?(change[:operation]) &&
|
184
183
|
change[:device].class <= RbVmomi::VIM::VirtualEthernetCard
|
185
184
|
end.map { |change| change[:device] }
|
186
185
|
interfaces.map do |interface|
|
187
186
|
RbVmomi::VIM::VirtualMachineBootOptionsBootableEthernetDevice.new(
|
188
|
-
:
|
187
|
+
deviceKey: interface.key
|
189
188
|
)
|
190
189
|
end
|
191
190
|
when :disk
|
192
191
|
disks = device_change.select do |change|
|
193
|
-
[
|
192
|
+
%i[edit add].include?(change[:operation]) &&
|
194
193
|
change[:device].is_a?(RbVmomi::VIM::VirtualDisk)
|
195
194
|
end.map { |change| change[:device] }
|
196
195
|
disks.map do |disk|
|
197
196
|
RbVmomi::VIM::VirtualMachineBootOptionsBootableDiskDevice.new(
|
198
|
-
:
|
197
|
+
deviceKey: disk.key
|
199
198
|
)
|
200
199
|
end
|
201
200
|
when :cdrom
|
@@ -204,7 +203,7 @@ module Fog
|
|
204
203
|
RbVmomi::VIM::VirtualMachineBootOptionsBootableFloppyDevice.new
|
205
204
|
end
|
206
205
|
end
|
207
|
-
virtual_machine_config_spec.bootOptions = { :
|
206
|
+
virtual_machine_config_spec.bootOptions = { bootOrder: boot_order }
|
208
207
|
end
|
209
208
|
# Options['customization_spec']
|
210
209
|
# OLD Options still supported
|
@@ -234,10 +233,10 @@ module Fog
|
|
234
233
|
# * password: <~Hash> - REQUIRED, new administrator password for the machine
|
235
234
|
# * plainText: boolean - REQUIRED, specify whether or not the password is in plain text, rather than encrypted
|
236
235
|
# * value: <~String> - REQUIRED, password string
|
237
|
-
# * timeZone: <~int> - REQUIRED, (see here for values https://msdn.microsoft.com/en-us/library/ms912391(v=winembedded.11).aspx)
|
236
|
+
# * timeZone: <~int> - REQUIRED, (see here for values https://msdn.microsoft.com/en-us/library/ms912391(v=winembedded.11).aspx)
|
238
237
|
# * identification: <~Hash> - REQUIRED, representation of the sysprep Identification key
|
239
238
|
# * domainAdmin: <~String> - Optional, domain user account used for authentication if the virtual machine is joining a domain
|
240
|
-
# * domainAdminPassword: <~Hash> - Optional, password for the domain user account used for authentication
|
239
|
+
# * domainAdminPassword: <~Hash> - Optional, password for the domain user account used for authentication
|
241
240
|
# * plainText: boolean - REQUIRED, specify whether or not the password is in plain text, rather than encrypted
|
242
241
|
# * value: <~String> - REQUIRED, password string
|
243
242
|
# * joinDomain: <~String> - Optional, The domain that the virtual machine should join. If this value is supplied, then domainAdmin and domainAdminPassword must also be supplied
|
@@ -256,7 +255,7 @@ module Fog
|
|
256
255
|
# * hwClockUTC: <~Boolean> - Optional, Specifies whether the hardware clock is in UTC or local time
|
257
256
|
# * timeZone: <~String> - Optional, Case sensistive timezone, valid values can be found at https://pubs.vmware.com/vsphere-51/topic/com.vmware.wssdk.apiref.doc/timezone.html
|
258
257
|
# * SysprepText: <~Hash> - Optional, alternate way to specify the sysprep.inf answer file.
|
259
|
-
# * value: <~String> - REQUIRED, Text for the sysprep.inf answer file.
|
258
|
+
# * value: <~String> - REQUIRED, Text for the sysprep.inf answer file.
|
260
259
|
# * nicSettingMap: <~Array> - Optional, IP settings that are specific to a particular virtual network adapter
|
261
260
|
# * Each item in array:
|
262
261
|
# * adapter: <~Hash> - REQUIRED, IP settings for the associated virtual network adapter
|
@@ -277,7 +276,7 @@ module Fog
|
|
277
276
|
# * deleteAccounts: <~Boolean> - REQUIRED, If deleteAccounts is true, then all user accounts are removed from the system
|
278
277
|
# * reboot: <~String> - Optional, (defaults to reboot), Action to be taken after running sysprep, must be one of: 'noreboot', 'reboot', 'shutdown'
|
279
278
|
#
|
280
|
-
if
|
279
|
+
if options.key?('customization_spec')
|
281
280
|
custom_spec = options['customization_spec']
|
282
281
|
|
283
282
|
# backwards compatablity
|
@@ -295,44 +294,44 @@ module Fog
|
|
295
294
|
#
|
296
295
|
# we can assume old parameters being passed
|
297
296
|
cust_hostname = custom_spec['hostname'] || options['name']
|
298
|
-
custom_spec['identity'] =
|
299
|
-
custom_spec['identity']['LinuxPrep'] = {
|
300
|
-
|
297
|
+
custom_spec['identity'] = {} unless custom_spec.key?('identity')
|
298
|
+
custom_spec['identity']['LinuxPrep'] = { 'domain' => custom_spec['domain'], 'hostName' => cust_hostname, 'timeZone' => custom_spec['time_zone'] }
|
299
|
+
|
301
300
|
if custom_spec.key?('ipsettings')
|
302
|
-
custom_spec['globalIPSettings']=
|
301
|
+
custom_spec['globalIPSettings'] = {} unless custom_spec.key?('globalIPSettings')
|
303
302
|
custom_spec['globalIPSettings']['dnsServerList'] = custom_spec['ipsettings']['dnsServerList'] if custom_spec['ipsettings'].key?('dnsServerList')
|
304
|
-
custom_spec['globalIPSettings']['dnsSuffixList'] = custom_spec['dnsSuffixList'] || [custom_spec['domain']] if
|
305
|
-
if
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
end
|
303
|
+
custom_spec['globalIPSettings']['dnsSuffixList'] = custom_spec['dnsSuffixList'] || [custom_spec['domain']] if custom_spec['dnsSuffixList'] || custom_spec['domain']
|
304
|
+
if custom_spec['ipsettings'].key?('ip') || custom_spec['ipsettings'].key?('gateway') || custom_spec['ipsettings'].key?('subnetMask') || custom_spec['ipsettings'].key?('domain') || custom_spec['ipsettings'].key?('dnsServerList')
|
305
|
+
if custom_spec['ipsettings'].key?('ip') && !custom_spec['ipsettings'].key?('subnetMask')
|
306
|
+
raise ArgumentError, 'subnetMask is required for static ip'
|
307
|
+
end
|
308
|
+
custom_spec['nicSettingMap'] = [] unless custom_spec.key?('nicSettingMap')
|
309
|
+
custom_spec['nicSettingMap'][0] = {} if custom_spec['nicSettingMap'].empty?
|
310
|
+
custom_spec['nicSettingMap'][0]['adapter'] = {} unless custom_spec['nicSettingMap'][0].key?('adapter')
|
311
|
+
custom_spec['nicSettingMap'][0]['adapter']['ip'] = custom_spec['ipsettings']['ip'] if custom_spec['ipsettings'].key?('ip')
|
312
|
+
custom_spec['nicSettingMap'][0]['adapter']['gateway'] = custom_spec['ipsettings']['gateway'] if custom_spec['ipsettings'].key?('gateway')
|
313
|
+
custom_spec['nicSettingMap'][0]['adapter']['subnetMask'] = custom_spec['ipsettings']['subnetMask'] if custom_spec['ipsettings'].key?('subnetMask')
|
314
|
+
custom_spec['nicSettingMap'][0]['adapter']['dnsDomain'] = custom_spec['ipsettings']['domain'] if custom_spec['ipsettings'].key?('domain')
|
315
|
+
custom_spec['nicSettingMap'][0]['adapter']['dnsServerList'] = custom_spec['ipsettings']['dnsServerList'] if custom_spec['ipsettings'].key?('dnsServerList')
|
316
|
+
end
|
318
317
|
end
|
319
318
|
end
|
320
|
-
### End of backwards compatability
|
319
|
+
### End of backwards compatability
|
321
320
|
|
322
321
|
## requirements check here ##
|
323
|
-
raise ArgumentError,
|
324
|
-
raise ArgumentError,
|
325
|
-
|
322
|
+
raise ArgumentError, 'globalIPSettings are required when using Customization Spec' unless custom_spec.key?('globalIPSettings')
|
323
|
+
raise ArgumentError, 'identity is required when using Customization Spec' unless custom_spec.key?('identity')
|
324
|
+
|
326
325
|
# encryptionKey
|
327
326
|
custom_encryptionKey = custom_spec['encryptionKey'] if custom_spec.key?('encryptionKey')
|
328
327
|
custom_encryptionKey ||= nil
|
329
|
-
|
328
|
+
|
330
329
|
# globalIPSettings
|
331
330
|
# https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.GlobalIPSettings.html
|
332
|
-
custom_globalIPSettings = RbVmomi::VIM::CustomizationGlobalIPSettings.new
|
333
|
-
custom_globalIPSettings.dnsServerList = custom_spec['globalIPSettings']['dnsServerList'] if custom_spec['globalIPSettings'].key?(
|
334
|
-
custom_globalIPSettings.dnsSuffixList = custom_spec['globalIPSettings']['dnsSuffixList'] if custom_spec['globalIPSettings'].key?(
|
335
|
-
|
331
|
+
custom_globalIPSettings = RbVmomi::VIM::CustomizationGlobalIPSettings.new
|
332
|
+
custom_globalIPSettings.dnsServerList = custom_spec['globalIPSettings']['dnsServerList'] if custom_spec['globalIPSettings'].key?('dnsServerList')
|
333
|
+
custom_globalIPSettings.dnsSuffixList = custom_spec['globalIPSettings']['dnsSuffixList'] if custom_spec['globalIPSettings'].key?('dnsSuffixList')
|
334
|
+
|
336
335
|
# identity
|
337
336
|
# https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.IdentitySettings.html
|
338
337
|
# Accepts the 3 supported CustomizationIdentitySettings Types:
|
@@ -342,21 +341,21 @@ module Fog
|
|
342
341
|
# At least one of these is required
|
343
342
|
#
|
344
343
|
identity = custom_spec['identity']
|
345
|
-
if identity.key?(
|
344
|
+
if identity.key?('LinuxPrep')
|
346
345
|
# https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.LinuxPrep.html
|
347
346
|
# Fields:
|
348
347
|
# * domain: string **REQUIRED**
|
349
348
|
# * hostName: string (CustomizationName) **REQUIRED** Will use options['name'] if not provided.
|
350
349
|
# * hwClockUTC: boolean
|
351
|
-
# * timeZone: string (https://pubs.vmware.com/vsphere-55/topic/com.vmware.wssdk.apiref.doc/timezone.html)
|
352
|
-
raise ArgumentError,
|
353
|
-
custom_identity = RbVmomi::VIM::CustomizationLinuxPrep(:
|
354
|
-
cust_hostname = RbVmomi::VIM::CustomizationFixedName(:
|
355
|
-
cust_hostname ||= RbVmomi::VIM::CustomizationFixedName(:
|
350
|
+
# * timeZone: string (https://pubs.vmware.com/vsphere-55/topic/com.vmware.wssdk.apiref.doc/timezone.html)
|
351
|
+
raise ArgumentError, 'domain is required when using LinuxPrep identity' unless identity['LinuxPrep'].key?('domain')
|
352
|
+
custom_identity = RbVmomi::VIM::CustomizationLinuxPrep(domain: identity['LinuxPrep']['domain'])
|
353
|
+
cust_hostname = RbVmomi::VIM::CustomizationFixedName(name: identity['LinuxPrep']['hostName']) if identity['LinuxPrep'].key?('hostName')
|
354
|
+
cust_hostname ||= RbVmomi::VIM::CustomizationFixedName(name: options['name'])
|
356
355
|
custom_identity.hostName = cust_hostname
|
357
356
|
custom_identity.hwClockUTC = identity['LinuxPrep']['hwClockUTC'] if identity['LinuxPrep'].key?('hwClockUTC')
|
358
|
-
custom_identity.timeZone = identity['LinuxPrep']['timeZone'] if identity['LinuxPrep'].key?('timeZone')
|
359
|
-
elsif identity.key?(
|
357
|
+
custom_identity.timeZone = identity['LinuxPrep']['timeZone'] if identity['LinuxPrep'].key?('timeZone')
|
358
|
+
elsif identity.key?('Sysprep')
|
360
359
|
# https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Sysprep.html
|
361
360
|
# Fields:
|
362
361
|
# * guiRunOnce: CustomizationGuiRunOnce
|
@@ -364,42 +363,42 @@ module Fog
|
|
364
363
|
# * identification: CustomizationIdentification **REQUIRED**
|
365
364
|
# * licenseFilePrintData: CustomizationLicenseFilePrintData
|
366
365
|
# * userData: CustomizationUserData **REQUIRED**
|
367
|
-
#
|
368
|
-
raise ArgumentError,
|
369
|
-
raise ArgumentError,
|
370
|
-
raise ArgumentError,
|
366
|
+
#
|
367
|
+
raise ArgumentError, 'guiUnattended is required when using Sysprep identity' unless identity['Sysprep'].key?('guiUnattended')
|
368
|
+
raise ArgumentError, 'identification is required when using Sysprep identity' unless identity['Sysprep'].key?('identification')
|
369
|
+
raise ArgumentError, 'userData is required when using Sysprep identity' unless identity['Sysprep'].key?('userData')
|
371
370
|
if identity['Sysprep']['guiRunOnce']
|
372
371
|
# https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.GuiRunOnce.html
|
373
372
|
# Fields:
|
374
373
|
# * commandList: array of string **REQUIRED***
|
375
374
|
#
|
376
|
-
raise ArgumentError,
|
377
|
-
cust_guirunonce = RbVmomi::VIM.CustomizationGuiRunOnce(
|
375
|
+
raise ArgumentError, 'commandList is required when using Sysprep identity and guiRunOnce' unless identity['Sysprep']['guiRunOnce'].key?('commandList')
|
376
|
+
cust_guirunonce = RbVmomi::VIM.CustomizationGuiRunOnce(commandList: identity['Sysprep']['guiRunOnce']['commandList'])
|
378
377
|
end
|
379
378
|
# https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.GuiUnattended.html
|
380
379
|
# Fields:
|
381
380
|
# * autoLogin: boolean **REQUIRED**
|
382
381
|
# * autoLogonCount: int **REQUIRED**
|
383
382
|
# * timeZone: int (see here for values https://msdn.microsoft.com/en-us/library/ms912391(v=winembedded.11).aspx) **REQUIRED**
|
384
|
-
# * password: CustomizationPassword
|
385
|
-
raise ArgumentError,
|
386
|
-
raise ArgumentError,
|
387
|
-
raise ArgumentError,
|
383
|
+
# * password: CustomizationPassword
|
384
|
+
raise ArgumentError, 'guiUnattended->autoLogon is required when using Sysprep identity' unless identity['Sysprep']['guiUnattended'].key?('autoLogon')
|
385
|
+
raise ArgumentError, 'guiUnattended->autoLogonCount is required when using Sysprep identity' unless identity['Sysprep']['guiUnattended'].key?('autoLogonCount')
|
386
|
+
raise ArgumentError, 'guiUnattended->timeZone is required when using Sysprep identity' unless identity['Sysprep']['guiUnattended'].key?('timeZone')
|
388
387
|
custom_guiUnattended = RbVmomi::VIM.CustomizationGuiUnattended(
|
389
|
-
:
|
390
|
-
:
|
391
|
-
:
|
388
|
+
autoLogon: identity['Sysprep']['guiUnattended']['autoLogon'],
|
389
|
+
autoLogonCount: identity['Sysprep']['guiUnattended']['autoLogonCount'],
|
390
|
+
timeZone: identity['Sysprep']['guiUnattended']['timeZone']
|
392
391
|
)
|
393
392
|
if identity['Sysprep']['guiUnattended']['password']
|
394
393
|
# https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Password.html
|
395
394
|
# Fields:
|
396
395
|
# * plainText: boolean **REQUIRED**
|
397
396
|
# * value: string **REQUIRED**
|
398
|
-
raise ArgumentError,
|
399
|
-
raise ArgumentError,
|
397
|
+
raise ArgumentError, 'guiUnattended->password->plainText is required when using Sysprep identity and guiUnattended -> password' unless identity['Sysprep']['guiUnattended']['password'].key?('plainText')
|
398
|
+
raise ArgumentError, 'guiUnattended->password->value is required when using Sysprep identity and guiUnattended -> password' unless identity['Sysprep']['guiUnattended']['password'].key?('value')
|
400
399
|
custom_guiUnattended.password = RbVmomi::VIM.CustomizationPassword(
|
401
|
-
:
|
402
|
-
:
|
400
|
+
plainText: identity['Sysprep']['guiUnattended']['password']['plainText'],
|
401
|
+
value: identity['Sysprep']['guiUnattended']['password']['value']
|
403
402
|
)
|
404
403
|
end
|
405
404
|
# https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Identification.html
|
@@ -412,19 +411,19 @@ module Fog
|
|
412
411
|
if identity['Sysprep']['identification'].key?('joinWorkgroup')
|
413
412
|
custom_identification.joinWorkgroup = identity['Sysprep']['identification']['joinWorkgroup']
|
414
413
|
elsif identity['Sysprep']['identification'].key?('joinDomain')
|
415
|
-
raise ArgumentError,
|
416
|
-
raise ArgumentError,
|
417
|
-
raise ArgumentError,
|
418
|
-
raise ArgumentError,
|
414
|
+
raise ArgumentError, 'identification->domainAdmin is required when using Sysprep identity and identification -> joinDomain' unless identity['Sysprep']['identification'].key?('domainAdmin')
|
415
|
+
raise ArgumentError, 'identification->domainAdminPassword is required when using Sysprep identity and identification -> joinDomain' unless identity['Sysprep']['identification'].key?('domainAdmin')
|
416
|
+
raise ArgumentError, 'identification->domainAdminPassword->plainText is required when using Sysprep identity and identification -> joinDomain' unless identity['Sysprep']['identification']['domainAdminPassword'].key?('plainText')
|
417
|
+
raise ArgumentError, 'identification->domainAdminPassword->value is required when using Sysprep identity and identification -> joinDomain' unless identity['Sysprep']['identification']['domainAdminPassword'].key?('value')
|
419
418
|
custom_identification.joinDomain = identity['Sysprep']['identification']['joinDomain']
|
420
419
|
custom_identification.domainAdmin = identity['Sysprep']['identification']['domainAdmin']
|
421
420
|
# https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Password.html
|
422
421
|
# Fields:
|
423
422
|
# * plainText: boolean **REQUIRED**
|
424
423
|
# * value: string **REQUIRED**
|
425
|
-
custom_identification.domainAdminPassword = RbVmomi::VIM.CustomizationPassword(
|
426
|
-
:
|
427
|
-
:
|
424
|
+
custom_identification.domainAdminPassword = RbVmomi::VIM.CustomizationPassword(
|
425
|
+
plainText: identity['Sysprep']['identification']['domainAdminPassword']['plainText'],
|
426
|
+
value: identity['Sysprep']['identification']['domainAdminPassword']['value']
|
428
427
|
)
|
429
428
|
else
|
430
429
|
raise ArgumentError, "No valid Indentification found, valid values are 'joinWorkgroup' and 'joinDomain'"
|
@@ -434,13 +433,13 @@ module Fog
|
|
434
433
|
# Fields:
|
435
434
|
# * autoMode: string (CustomizationLicenseDataMode) ** REQUIRED **, valid strings are: 'perSeat' or 'perServer'
|
436
435
|
# * autoUsers: int (valid only if AutoMode = PerServer)
|
437
|
-
raise ArgumentError,
|
438
|
-
raise ArgumentError, "Unsupported autoMode, supported modes are : 'perSeat' or 'perServer'" unless [
|
436
|
+
raise ArgumentError, 'licenseFilePrintData->autoMode is required when using Sysprep identity and licenseFilePrintData' unless identity['Sysprep']['licenseFilePrintData'].key?('autoMode')
|
437
|
+
raise ArgumentError, "Unsupported autoMode, supported modes are : 'perSeat' or 'perServer'" unless %w[perSeat perServer].include? identity['Sysprep']['licenseFilePrintData']['autoMode']
|
439
438
|
custom_licenseFilePrintData = RbVmomi::VIM.CustomizationLicenseFilePrintData(
|
440
|
-
:
|
439
|
+
autoMode: RbVmomi::VIM.CustomizationLicenseDataMode(identity['Sysprep']['licenseFilePrintData']['autoMode'])
|
441
440
|
)
|
442
441
|
if identity['Sysprep']['licenseFilePrintData'].key?('autoUsers')
|
443
|
-
custom_licenseFilePrintData.autoUsers = identity['Sysprep']['licenseFilePrintData']['autoUsers'] if identity['Sysprep']['licenseFilePrintData']['autoMode'] ==
|
442
|
+
custom_licenseFilePrintData.autoUsers = identity['Sysprep']['licenseFilePrintData']['autoUsers'] if identity['Sysprep']['licenseFilePrintData']['autoMode'] == 'PerServer'
|
444
443
|
end
|
445
444
|
end
|
446
445
|
# https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.UserData.html
|
@@ -449,48 +448,48 @@ module Fog
|
|
449
448
|
# * fullName: string **REQUIRED**
|
450
449
|
# * orgName: string **REQUIRED**
|
451
450
|
# * productID: string **REQUIRED**
|
452
|
-
raise ArgumentError,
|
453
|
-
raise ArgumentError,
|
454
|
-
raise ArgumentError,
|
455
|
-
raise ArgumentError,
|
451
|
+
raise ArgumentError, 'userData->computerName is required when using Sysprep identity' unless identity['Sysprep']['userData'].key?('computerName')
|
452
|
+
raise ArgumentError, 'userData->fullName is required when using Sysprep identity' unless identity['Sysprep']['userData'].key?('fullName')
|
453
|
+
raise ArgumentError, 'userData->orgName is required when using Sysprep identity' unless identity['Sysprep']['userData'].key?('orgName')
|
454
|
+
raise ArgumentError, 'userData->productId is required when using Sysprep identity' unless identity['Sysprep']['userData'].key?('productId')
|
456
455
|
custom_userData = RbVmomi::VIM.CustomizationUserData(
|
457
|
-
:
|
458
|
-
:
|
459
|
-
:
|
460
|
-
:
|
456
|
+
fullName: identity['Sysprep']['userData']['fullName'],
|
457
|
+
orgName: identity['Sysprep']['userData']['orgName'],
|
458
|
+
productId: identity['Sysprep']['userData']['productId'],
|
459
|
+
computerName: RbVmomi::VIM.CustomizationFixedName(name: identity['Sysprep']['userData']['computerName'])
|
461
460
|
)
|
462
461
|
|
463
|
-
custom_identity = RbVmomi::VIM::CustomizationSysprep(
|
464
|
-
:
|
465
|
-
:
|
466
|
-
:
|
462
|
+
custom_identity = RbVmomi::VIM::CustomizationSysprep(
|
463
|
+
guiUnattended: custom_guiUnattended,
|
464
|
+
identification: custom_identification,
|
465
|
+
userData: custom_userData
|
467
466
|
)
|
468
467
|
custom_identity.guiRunOnce = cust_guirunonce if defined?(cust_guirunonce)
|
469
468
|
custom_identity.licenseFilePrintData = custom_licenseFilePrintData if defined?(custom_licenseFilePrintData)
|
470
|
-
elsif identity.key?(
|
469
|
+
elsif identity.key?('SysprepText')
|
471
470
|
# https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.SysprepText.html
|
472
471
|
# Fields:
|
473
472
|
# * value: string **REQUIRED**
|
474
|
-
raise ArgumentError,
|
475
|
-
custom_identity = RbVmomi::VIM::CustomizationSysprepText(:
|
473
|
+
raise ArgumentError, 'SysprepText -> value is required when using SysprepText identity' unless identity['SysprepText'].key?('value')
|
474
|
+
custom_identity = RbVmomi::VIM::CustomizationSysprepText(value: identity['SysprepText']['value'])
|
476
475
|
else
|
477
|
-
raise ArgumentError,
|
476
|
+
raise ArgumentError, 'At least one of the following valid identities must be supplied: LinuxPrep, Sysprep, SysprepText'
|
478
477
|
end
|
479
478
|
|
480
|
-
if custom_spec.key?(
|
479
|
+
if custom_spec.key?('nicSettingMap')
|
481
480
|
# custom_spec['nicSettingMap'] is an array of adapater mappings:
|
482
481
|
# custom_spec['nicSettingMap'][0]['macAddress']
|
483
482
|
# custom_spec['nicSettingMap'][0]['adapter']['ip']
|
484
|
-
#https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.AdapterMapping.html
|
483
|
+
# https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.AdapterMapping.html
|
485
484
|
# Fields:
|
486
485
|
# * adapter: CustomizationIPSettings **REQUIRED**
|
487
486
|
# * macAddress: string
|
488
|
-
raise ArgumentError,
|
489
|
-
raise ArgumentError,
|
490
|
-
|
491
|
-
custom_nicSettingMap = []
|
487
|
+
raise ArgumentError, 'At least one nicSettingMap is required when using nicSettingMap' if custom_spec['nicSettingMap'].empty?
|
488
|
+
raise ArgumentError, 'Adapter is required when using nicSettingMap' unless custom_spec['nicSettingMap'][0].key?('adapter')
|
489
|
+
|
490
|
+
custom_nicSettingMap = []
|
492
491
|
# need to go through array here for each apapter
|
493
|
-
custom_spec['nicSettingMap'].each do |
|
492
|
+
custom_spec['nicSettingMap'].each do |nic|
|
494
493
|
# https://pubs.vmware.com/vsphere-55/index.jsp?topic=%2Fcom.vmware.wssdk.apiref.doc%2Fvim.vm.customization.IPSettings.html
|
495
494
|
# Fields:
|
496
495
|
# * dnsDomain: string
|
@@ -502,12 +501,12 @@ module Fog
|
|
502
501
|
# * secondaryWINS: string
|
503
502
|
# * subnetMask: string - Required if assigning static IP
|
504
503
|
if nic['adapter'].key?('ip')
|
505
|
-
raise ArgumentError,
|
506
|
-
custom_ip = RbVmomi::VIM.CustomizationFixedIp(:
|
504
|
+
raise ArgumentError, 'SubnetMask is required when assigning static IP when using nicSettingMap -> Adapter' unless nic['adapter'].key?('subnetMask')
|
505
|
+
custom_ip = RbVmomi::VIM.CustomizationFixedIp(ipAddress: nic['adapter']['ip'])
|
507
506
|
else
|
508
|
-
custom_ip = RbVmomi::VIM::CustomizationDhcpIpGenerator.new
|
507
|
+
custom_ip = RbVmomi::VIM::CustomizationDhcpIpGenerator.new
|
509
508
|
end
|
510
|
-
custom_adapter = RbVmomi::VIM.CustomizationIPSettings(:
|
509
|
+
custom_adapter = RbVmomi::VIM.CustomizationIPSettings(ip: custom_ip)
|
511
510
|
custom_adapter.dnsDomain = nic['adapter']['dnsDomain'] if nic['adapter'].key?('dnsDomain')
|
512
511
|
custom_adapter.dnsServerList = nic['adapter']['dnsServerList'] if nic['adapter'].key?('dnsServerList')
|
513
512
|
custom_adapter.gateway = nic['adapter']['gateway'] if nic['adapter'].key?('gateway')
|
@@ -517,18 +516,18 @@ module Fog
|
|
517
516
|
# * gateway: array of string
|
518
517
|
# * ip: CustomizationIpV6Generator[] **Required if setting static IP **
|
519
518
|
if nic['adapter']['ipV6Spec'].key?('ipAddress')
|
520
|
-
raise ArgumentError,
|
519
|
+
raise ArgumentError, 'SubnetMask is required when assigning static IPv6 when using nicSettingMap -> Adapter -> ipV6Spec' unless nic['adapter']['ipV6Spec'].key?('subnetMask')
|
521
520
|
# https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.FixedIpV6.html
|
522
521
|
# * ipAddress: string **REQUIRED**
|
523
522
|
# * subnetMask: int **REQUIRED**
|
524
523
|
custom_ipv6 = RbVmomi::VIM.CustomizationFixedIpV6(
|
525
|
-
:
|
526
|
-
:
|
524
|
+
ipAddress: nic['adapter']['ipV6Spec']['ipAddress'],
|
525
|
+
subnetMask: nic['adapter']['ipV6Spec']['subnetMask']
|
527
526
|
)
|
528
527
|
else
|
529
|
-
custom_ipv6 = RbVmomi::VIM::CustomizationDhcpIpV6Generator.new
|
528
|
+
custom_ipv6 = RbVmomi::VIM::CustomizationDhcpIpV6Generator.new
|
530
529
|
end
|
531
|
-
custom_ipv6Spec = RbVmomi::VIM.CustomizationIPSettingsIpV6AddressSpec(:
|
530
|
+
custom_ipv6Spec = RbVmomi::VIM.CustomizationIPSettingsIpV6AddressSpec(ip: custom_ipv6)
|
532
531
|
custom_ipv6Spec.gateway = nic['adapter']['ipV6Spec']['gateway'] if nic['adapter']['ipV6Spec'].key?('gateway')
|
533
532
|
custom_adapter.ipV6Spec = custom_ipv6Spec
|
534
533
|
end
|
@@ -537,45 +536,45 @@ module Fog
|
|
537
536
|
# Fields:
|
538
537
|
# netBIOS: string matching: 'disableNetBIOS','enableNetBIOS' or 'enableNetBIOSViaDhcp' ** REQUIRED **
|
539
538
|
#
|
540
|
-
raise ArgumentError, "Unsupported NetBIOSMode, supported modes are : 'disableNetBIOS','enableNetBIOS' or 'enableNetBIOSViaDhcp'" unless [
|
539
|
+
raise ArgumentError, "Unsupported NetBIOSMode, supported modes are : 'disableNetBIOS','enableNetBIOS' or 'enableNetBIOSViaDhcp'" unless %w[disableNetBIOS enableNetBIOS enableNetBIOSViaDhcp].include? nic['adapter']['netBIOS']
|
541
540
|
custom_adapter.netBIOS = RbVmomi::VIM.CustomizationNetBIOSMode(nic['adapter']['netBIOS'])
|
542
541
|
end
|
543
542
|
custom_adapter.primaryWINS = nic['adapter']['primaryWINS'] if nic['adapter'].key?('primaryWINS')
|
544
543
|
custom_adapter.secondaryWINS = nic['adapter']['secondaryWINS'] if nic['adapter'].key?('secondaryWINS')
|
545
544
|
custom_adapter.subnetMask = nic['adapter']['subnetMask'] if nic['adapter'].key?('subnetMask')
|
546
545
|
|
547
|
-
custom_adapter_mapping = RbVmomi::VIM::CustomizationAdapterMapping(:
|
546
|
+
custom_adapter_mapping = RbVmomi::VIM::CustomizationAdapterMapping(adapter: custom_adapter)
|
548
547
|
custom_adapter_mapping.macAddress = nic['macAddress'] if nic.key?('macAddress')
|
549
|
-
|
548
|
+
|
550
549
|
# build the adapters array
|
551
550
|
custom_nicSettingMap << custom_adapter_mapping
|
552
551
|
end
|
553
|
-
end
|
554
|
-
|
555
|
-
if custom_spec.key?(
|
552
|
+
end
|
553
|
+
|
554
|
+
if custom_spec.key?('options')
|
556
555
|
# https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Options.html
|
557
556
|
# this currently doesn't have any Linux options, just windows
|
558
557
|
# Fields:
|
559
558
|
# * changeSID: boolean **REQUIRED**
|
560
559
|
# * deleteAccounts: boolean **REQUIRED** **note deleteAccounts is deprecated as of VI API 2.5 so can be ignored
|
561
560
|
# * reboot: CustomizationSysprepRebootOption: (string) one of following 'noreboot', reboot' or 'shutdown' (defaults to reboot)
|
562
|
-
raise ArgumentError,
|
563
|
-
raise ArgumentError,
|
561
|
+
raise ArgumentError, 'changeSID id required when using Windows Options' unless custom_spec['options'].key?('changeSID')
|
562
|
+
raise ArgumentError, 'deleteAccounts id required when using Windows Options' unless custom_spec['options'].key?('deleteAccounts')
|
564
563
|
custom_options = RbVmomi::VIM::CustomizationWinOptions(
|
565
|
-
:
|
566
|
-
:
|
564
|
+
changeSID: custom_spec['options']['changeSID'],
|
565
|
+
deleteAccounts: custom_spec['options']['deleteAccounts']
|
567
566
|
)
|
568
567
|
if custom_spec['options'].key?('reboot')
|
569
|
-
raise ArgumentError, "Unsupported reboot option, supported options are : 'noreboot', 'reboot' or 'shutdown'" unless [
|
568
|
+
raise ArgumentError, "Unsupported reboot option, supported options are : 'noreboot', 'reboot' or 'shutdown'" unless %w[noreboot reboot shutdown].include? custom_spec['options']['reboot']
|
570
569
|
custom_options.reboot = RBVmomi::VIM.CustomizationSysprepRebootOption(custom_spec['options']['reboot'])
|
571
570
|
end
|
572
571
|
end
|
573
|
-
custom_options ||=nil
|
574
|
-
|
572
|
+
custom_options ||= nil
|
573
|
+
|
575
574
|
# https://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/vim.vm.customization.Specification.html
|
576
575
|
customization_spec = RbVmomi::VIM::CustomizationSpec(
|
577
|
-
:
|
578
|
-
:
|
576
|
+
globalIPSettings: custom_globalIPSettings,
|
577
|
+
identity: custom_identity
|
579
578
|
)
|
580
579
|
customization_spec.encryptionKey = custom_encryptionKey if defined?(custom_encryptionKey)
|
581
580
|
customization_spec.nicSettingMap = custom_nicSettingMap if defined?(custom_nicSettingMap)
|
@@ -584,11 +583,11 @@ module Fog
|
|
584
583
|
end
|
585
584
|
customization_spec ||= nil
|
586
585
|
|
587
|
-
relocation_spec=nil
|
588
|
-
if
|
586
|
+
relocation_spec = nil
|
587
|
+
if options['linked_clone']
|
589
588
|
# Storage DRS does not support vSphere linked clones.
|
590
589
|
# http://www.vmware.com/files/pdf/techpaper/vsphere-storage-drs-interoperability.pdf
|
591
|
-
raise ArgumentError,
|
590
|
+
raise ArgumentError, 'linked clones are not supported on storage pods' unless options.key?('storage_pod')
|
592
591
|
# cribbed heavily from the rbvmomi clone_vm.rb
|
593
592
|
# this chunk of code reconfigures the disk of the clone source to be read only,
|
594
593
|
# and then creates a delta disk on top of that, this is required by the API in order to create
|
@@ -596,36 +595,36 @@ module Fog
|
|
596
595
|
disks = vm_mob_ref.config.hardware.device.select do |vm_device|
|
597
596
|
vm_device.class == RbVmomi::VIM::VirtualDisk
|
598
597
|
end
|
599
|
-
disks.select{|vm_device| vm_device.backing.parent
|
598
|
+
disks.select { |vm_device| vm_device.backing.parent.nil? }.each do |disk|
|
600
599
|
disk_spec = {
|
601
|
-
:
|
600
|
+
deviceChange: [
|
602
601
|
{
|
603
|
-
:
|
604
|
-
:
|
602
|
+
operation: :remove,
|
603
|
+
device: disk
|
605
604
|
},
|
606
605
|
{
|
607
|
-
:
|
608
|
-
:
|
609
|
-
:
|
610
|
-
disk_backing.backing = disk_backing.backing.dup
|
611
|
-
disk_backing.backing.fileName = "[#{disk.backing.datastore.name}]"
|
606
|
+
operation: :add,
|
607
|
+
fileOperation: :create,
|
608
|
+
device: disk.dup.tap do |disk_backing|
|
609
|
+
disk_backing.backing = disk_backing.backing.dup
|
610
|
+
disk_backing.backing.fileName = "[#{disk.backing.datastore.name}]"
|
612
611
|
disk_backing.backing.parent = disk.backing
|
613
|
-
|
612
|
+
end
|
614
613
|
}
|
615
614
|
]
|
616
615
|
}
|
617
|
-
vm_mob_ref.ReconfigVM_Task(:
|
616
|
+
vm_mob_ref.ReconfigVM_Task(spec: disk_spec).wait_for_completion
|
618
617
|
end
|
619
618
|
# Next, create a Relocation Spec instance
|
620
|
-
relocation_spec = RbVmomi::VIM.VirtualMachineRelocateSpec(:
|
621
|
-
:
|
622
|
-
:
|
623
|
-
:
|
619
|
+
relocation_spec = RbVmomi::VIM.VirtualMachineRelocateSpec(datastore: datastore_obj,
|
620
|
+
pool: resource_pool,
|
621
|
+
host: host,
|
622
|
+
diskMoveType: :moveChildMostDiskBacking)
|
624
623
|
else
|
625
|
-
relocation_spec = RbVmomi::VIM.VirtualMachineRelocateSpec(:
|
626
|
-
:
|
627
|
-
:
|
628
|
-
unless options.key?('storage_pod')
|
624
|
+
relocation_spec = RbVmomi::VIM.VirtualMachineRelocateSpec(pool: resource_pool,
|
625
|
+
host: host,
|
626
|
+
transform: options['transform'] || 'sparse')
|
627
|
+
unless options.key?('storage_pod') && datastore_obj.nil?
|
629
628
|
relocation_spec[:datastore] = datastore_obj
|
630
629
|
end
|
631
630
|
end
|
@@ -634,72 +633,72 @@ module Fog
|
|
634
633
|
relocation_spec[:disk] = relocate_template_volumes_specs(vm_mob_ref, options['volumes'], options['datacenter'])
|
635
634
|
end
|
636
635
|
# And the clone specification
|
637
|
-
clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(:
|
638
|
-
:
|
639
|
-
:
|
640
|
-
:
|
641
|
-
:
|
636
|
+
clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(location: relocation_spec,
|
637
|
+
config: virtual_machine_config_spec,
|
638
|
+
customization: customization_spec,
|
639
|
+
powerOn: options.key?('power_on') ? options['power_on'] : true,
|
640
|
+
template: false)
|
642
641
|
|
643
642
|
# Perform the actual Clone Task
|
644
643
|
# Clone VM on a storage pod
|
645
|
-
if options.key?('storage_pod')
|
646
|
-
raise ArgumentError,
|
647
|
-
pod_spec
|
648
|
-
:
|
644
|
+
if options.key?('storage_pod') && !options['storage_pod'].nil?
|
645
|
+
raise ArgumentError, 'need to use at least vsphere revision 5.0 or greater to use storage pods' unless @vsphere_rev.to_f >= 5
|
646
|
+
pod_spec = RbVmomi::VIM::StorageDrsPodSelectionSpec.new(
|
647
|
+
storagePod: get_raw_storage_pod(options['storage_pod'], options['datacenter'])
|
649
648
|
)
|
650
649
|
storage_spec = RbVmomi::VIM::StoragePlacementSpec.new(
|
651
|
-
:
|
652
|
-
:
|
653
|
-
:
|
654
|
-
:
|
655
|
-
:
|
656
|
-
:
|
657
|
-
:
|
650
|
+
type: 'clone',
|
651
|
+
folder: dest_folder,
|
652
|
+
resourcePool: resource_pool,
|
653
|
+
podSelectionSpec: pod_spec,
|
654
|
+
cloneSpec: clone_spec,
|
655
|
+
cloneName: options['name'],
|
656
|
+
vm: vm_mob_ref
|
658
657
|
)
|
659
658
|
srm = connection.serviceContent.storageResourceManager
|
660
|
-
result = srm.RecommendDatastores(:
|
659
|
+
result = srm.RecommendDatastores(storageSpec: storage_spec)
|
661
660
|
|
662
661
|
# if result array contains recommendation, we can apply it
|
663
662
|
if key = result.recommendations.first.key
|
664
|
-
task = srm.ApplyStorageDrsRecommendation_Task(:
|
665
|
-
if options.fetch('wait', true)
|
663
|
+
task = srm.ApplyStorageDrsRecommendation_Task(key: [key])
|
664
|
+
if options.fetch('wait', true)
|
666
665
|
result = task.wait_for_completion
|
667
666
|
new_vm = result.vm
|
668
667
|
else
|
669
668
|
new_vm = nil
|
670
|
-
Fog.wait_for(150, 15)
|
669
|
+
Fog.wait_for(150, 15) do
|
671
670
|
begin
|
672
|
-
new_vm = dest_folder.find(options['name'], RbVmomi::VIM::VirtualMachine)
|
671
|
+
(new_vm = dest_folder.find(options['name'], RbVmomi::VIM::VirtualMachine)) || raise(Fog::Vsphere::Errors::NotFound)
|
673
672
|
rescue Fog::Vsphere::Errors::NotFound
|
674
673
|
new_vm = nil
|
675
674
|
end
|
676
|
-
|
675
|
+
end
|
677
676
|
raise Fog::Vsphere::Errors::NotFound unless new_vm
|
678
677
|
end
|
679
678
|
end
|
680
679
|
else
|
681
|
-
task = vm_mob_ref.CloneVM_Task(:
|
682
|
-
|
683
|
-
|
680
|
+
task = vm_mob_ref.CloneVM_Task(folder: dest_folder,
|
681
|
+
name: options['name'],
|
682
|
+
spec: clone_spec)
|
684
683
|
# Waiting for the VM to complete allows us to get the VirtulMachine
|
685
684
|
# object of the new machine when it's done. It is HIGHLY recommended
|
686
685
|
# to set 'wait' => true if your app wants to wait. Otherwise, you're
|
687
686
|
# going to have to reload the server model over and over which
|
688
687
|
# generates a lot of time consuming API calls to vmware.
|
689
|
-
if options.fetch('wait', true)
|
688
|
+
if options.fetch('wait', true)
|
690
689
|
# REVISIT: It would be awesome to call a block passed to this
|
691
690
|
# request to notify the application how far along in the process we
|
692
691
|
# are. I'm thinking of updating a progress bar, etc...
|
693
692
|
new_vm = task.wait_for_completion
|
694
693
|
else
|
695
694
|
new_vm = nil
|
696
|
-
Fog.wait_for(150, 15)
|
695
|
+
Fog.wait_for(150, 15) do
|
697
696
|
begin
|
698
|
-
new_vm = dest_folder.find(options['name'], RbVmomi::VIM::VirtualMachine)
|
697
|
+
(new_vm = dest_folder.find(options['name'], RbVmomi::VIM::VirtualMachine)) || raise(Fog::Vsphere::Errors::NotFound)
|
699
698
|
rescue Fog::Vsphere::Errors::NotFound
|
700
699
|
new_vm = nil
|
701
700
|
end
|
702
|
-
|
701
|
+
end
|
703
702
|
raise Fog::Vsphere::Errors::NotFound unless new_vm
|
704
703
|
end
|
705
704
|
end
|
@@ -715,37 +714,38 @@ module Fog
|
|
715
714
|
# Build up the network config spec for simple case:
|
716
715
|
# simple case: apply just the network_label, nic_type and network_adapter_device_key
|
717
716
|
def modify_template_nics_simple_spec(network_label, nic_type, network_adapter_device_key, datacenter)
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
717
|
+
config_spec_operation = RbVmomi::VIM::VirtualDeviceConfigSpecOperation('edit')
|
718
|
+
# Get the portgroup and handle it from there.
|
719
|
+
network = get_raw_network(network_label, datacenter)
|
720
|
+
nic_backing_info = if network.is_a? RbVmomi::VIM::DistributedVirtualPortgroup
|
721
|
+
# Create the NIC backing for the distributed virtual portgroup
|
722
|
+
RbVmomi::VIM::VirtualEthernetCardDistributedVirtualPortBackingInfo(
|
723
|
+
port: RbVmomi::VIM::DistributedVirtualSwitchPortConnection(
|
724
|
+
portgroupKey: network.key,
|
725
|
+
switchUuid: network.config.distributedVirtualSwitch.uuid
|
726
|
+
)
|
727
|
+
)
|
728
|
+
else
|
729
|
+
# Otherwise it's a non distributed port group
|
730
|
+
RbVmomi::VIM::VirtualEthernetCardNetworkBackingInfo(deviceName: network_label)
|
731
|
+
end
|
732
|
+
connectable = RbVmomi::VIM::VirtualDeviceConnectInfo(
|
733
|
+
allowGuestControl: true,
|
734
|
+
connected: true,
|
735
|
+
startConnected: true
|
736
|
+
)
|
737
|
+
device = RbVmomi::VIM.public_send nic_type.to_s,
|
738
|
+
backing: nic_backing_info,
|
739
|
+
deviceInfo: RbVmomi::VIM::Description(label: 'Network adapter 1', summary: network_label),
|
740
|
+
key: network_adapter_device_key,
|
741
|
+
connectable: connectable
|
742
|
+
device_spec = RbVmomi::VIM::VirtualDeviceConfigSpec(
|
743
|
+
operation: config_spec_operation,
|
744
|
+
device: device
|
745
|
+
)
|
746
|
+
device_spec
|
746
747
|
end
|
747
748
|
|
748
|
-
|
749
749
|
def modify_template_nics_specs(vm_mob_ref, nics, datacenter)
|
750
750
|
specs = []
|
751
751
|
template_nics = vm_mob_ref.config.hardware.device.grep(RbVmomi::VIM::VirtualEthernetCard)
|
@@ -754,14 +754,14 @@ module Fog
|
|
754
754
|
|
755
755
|
template_nics.zip(modified_nics).each do |template_nic, new_nic|
|
756
756
|
if new_nic
|
757
|
-
backing = create_nic_backing(new_nic,
|
757
|
+
backing = create_nic_backing(new_nic, datacenter: datacenter)
|
758
758
|
template_nic.backing = backing
|
759
759
|
template_nic.addressType = 'generated'
|
760
760
|
template_nic.macAddress = nil
|
761
761
|
connectable = RbVmomi::VIM::VirtualDeviceConnectInfo(
|
762
|
-
:
|
763
|
-
:
|
764
|
-
:
|
762
|
+
allowGuestControl: true,
|
763
|
+
connected: true,
|
764
|
+
startConnected: true
|
765
765
|
)
|
766
766
|
template_nic.connectable = connectable
|
767
767
|
specs << {
|
@@ -770,12 +770,12 @@ module Fog
|
|
770
770
|
}
|
771
771
|
else
|
772
772
|
interface = Fog::Compute::Vsphere::Interface.new(raw_to_hash(template_nic))
|
773
|
-
specs << create_interface(interface, interface.key, :remove, :
|
773
|
+
specs << create_interface(interface, interface.key, :remove, datacenter: datacenter)
|
774
774
|
end
|
775
775
|
end
|
776
776
|
|
777
777
|
new_nics.each do |interface|
|
778
|
-
specs << create_interface(interface, 0, :add, :
|
778
|
+
specs << create_interface(interface, 0, :add, datacenter: datacenter)
|
779
779
|
end
|
780
780
|
|
781
781
|
specs
|
@@ -796,11 +796,11 @@ module Fog
|
|
796
796
|
end
|
797
797
|
template_volume.backing.diskMode = new_volume.mode
|
798
798
|
template_volume.backing.thinProvisioned = new_volume.thin
|
799
|
-
specs << { :
|
799
|
+
specs << { operation: :edit, device: template_volume }
|
800
800
|
else
|
801
|
-
specs << { :
|
802
|
-
:
|
803
|
-
:
|
801
|
+
specs << { operation: :remove,
|
802
|
+
fileOperation: :destroy,
|
803
|
+
device: template_volume }
|
804
804
|
end
|
805
805
|
end
|
806
806
|
specs.concat(new_volumes.map { |volume| create_disk(volume) })
|
@@ -814,7 +814,7 @@ module Fog
|
|
814
814
|
specs = []
|
815
815
|
template_volumes.zip(modified_volumes).each do |template_volume, new_volume|
|
816
816
|
if new_volume && new_volume.datastore && new_volume.datastore != template_volume.backing.datastore.name
|
817
|
-
specs << { :
|
817
|
+
specs << { diskId: template_volume.key, datastore: get_raw_datastore(new_volume.datastore, datacenter) }
|
818
818
|
end
|
819
819
|
end
|
820
820
|
specs
|
@@ -826,25 +826,23 @@ module Fog
|
|
826
826
|
def vm_clone(options = {})
|
827
827
|
# Option handling TODO Needs better method of checking
|
828
828
|
options = vm_clone_check_options(options)
|
829
|
-
notfound =
|
829
|
+
notfound = -> { raise Fog::Compute::Vsphere::NotFound, 'Could not find VM template' }
|
830
830
|
template = list_virtual_machines.find(notfound) do |vm|
|
831
|
-
vm['name'] == options['template_path'].split(
|
831
|
+
vm['name'] == options['template_path'].split('/')[-1]
|
832
832
|
end
|
833
833
|
|
834
834
|
# generate a random id
|
835
|
-
id = [8,4,4,4,12].map{|i| Fog::Mock.random_hex(i)}.join(
|
836
|
-
new_vm = template.clone.merge(
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
})
|
842
|
-
self.data[:servers][id] = new_vm
|
835
|
+
id = [8, 4, 4, 4, 12].map { |i| Fog::Mock.random_hex(i) }.join('-')
|
836
|
+
new_vm = template.clone.merge('name' => options['name'],
|
837
|
+
'id' => id,
|
838
|
+
'instance_uuid' => id,
|
839
|
+
'path' => "/Datacenters/#{options['datacenter']}/#{options['dest_folder'] ? options['dest_folder'] + '/' : ''}#{options['name']}")
|
840
|
+
data[:servers][id] = new_vm
|
843
841
|
|
844
842
|
{
|
845
843
|
'vm_ref' => "vm-#{Fog::Mock.random_numbers(3)}",
|
846
844
|
'new_vm' => new_vm,
|
847
|
-
'task_ref' => "task-#{Fog::Mock.random_numbers(4)}"
|
845
|
+
'task_ref' => "task-#{Fog::Mock.random_numbers(4)}"
|
848
846
|
}
|
849
847
|
end
|
850
848
|
end
|