fog-vsphere 2.1.1 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|