fog-vsphere 3.3.1 → 3.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +0 -4
- data/CHANGELOG.md +14 -0
- data/CONTRIBUTORS.md +3 -1
- data/lib/fog/vsphere/compute.rb +13 -1
- data/lib/fog/vsphere/models/compute/clusters.rb +0 -2
- data/lib/fog/vsphere/models/compute/customfields.rb +0 -2
- data/lib/fog/vsphere/models/compute/customvalues.rb +0 -2
- data/lib/fog/vsphere/models/compute/datacenters.rb +0 -2
- data/lib/fog/vsphere/models/compute/datastores.rb +0 -2
- data/lib/fog/vsphere/models/compute/folders.rb +0 -2
- data/lib/fog/vsphere/models/compute/interfaces.rb +0 -2
- data/lib/fog/vsphere/models/compute/interfacetypes.rb +0 -2
- data/lib/fog/vsphere/models/compute/network.rb +1 -0
- data/lib/fog/vsphere/models/compute/networks.rb +0 -2
- data/lib/fog/vsphere/models/compute/resource_pools.rb +0 -2
- data/lib/fog/vsphere/models/compute/rules.rb +0 -2
- data/lib/fog/vsphere/models/compute/server.rb +3 -1
- data/lib/fog/vsphere/models/compute/servers.rb +0 -2
- data/lib/fog/vsphere/models/compute/servertypes.rb +0 -2
- data/lib/fog/vsphere/models/compute/templates.rb +0 -2
- data/lib/fog/vsphere/models/compute/tickets.rb +0 -2
- data/lib/fog/vsphere/models/compute/volumes.rb +0 -2
- data/lib/fog/vsphere/requests/compute/create_resource_pool.rb +51 -0
- data/lib/fog/vsphere/requests/compute/destroy_resource_pool.rb +15 -0
- data/lib/fog/vsphere/requests/compute/get_network.rb +3 -3
- data/lib/fog/vsphere/requests/compute/list_networks.rb +6 -8
- data/lib/fog/vsphere/requests/compute/list_resource_pools.rb +2 -2
- data/lib/fog/vsphere/requests/compute/update_resource_pool.rb +31 -0
- data/lib/fog/vsphere/requests/compute/vm_clone.rb +12 -6
- data/lib/fog/vsphere/requests/compute/vm_take_snapshot.rb +10 -6
- data/lib/fog/vsphere/version.rb +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a217d08496a46e7dac6d2d8dc64deb846a3c10bd46ab68bdb23a2eacad4e5e72
|
4
|
+
data.tar.gz: 8bfb514ee9c268109026c9dc71cca9b68eaa5f9b875d6b900ed0d0d82755b126
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 66e404157f86b584f7032b1bf30ccbf6dd7286d5864afd458f16d01dce6da6d6d88131612e1d2112da9c8405c26770a7da0e1b28ac596844953f7594cde6b89e
|
7
|
+
data.tar.gz: d696ad6d363c8e85322330d03c7f3b6709108274faa394b750187dc4af85203d040e0c283dbfafd5706c2387e4a6ec9aa9c8d8bdf77ab10e44a5a2a79b1f46f1
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## v3.5.1
|
2
|
+
* Creating ESX compute resource on vcenter 7.x fails with InvalidArgument: A specified parameter was not correct: deviceChange[1].device.key (#272)
|
3
|
+
|
4
|
+
## v3.5.0
|
5
|
+
* Clone vm from different datacenter (#263)
|
6
|
+
* Fix autoload issues (#267)
|
7
|
+
* Add extra_config attribute to server (#268)
|
8
|
+
* Expose `_ref` from Compute::Network (#265)
|
9
|
+
|
10
|
+
## v3.4.0
|
11
|
+
* list_resource_pools returns incorrect resource pool name (#256)
|
12
|
+
* Add ability to create update and delete Resource Pools (#253)
|
13
|
+
* Check datastore for existence prior vm_clone
|
14
|
+
|
1
15
|
## v3.3.1
|
2
16
|
Fixes eager zero flag (#251, #252)
|
3
17
|
|
data/CONTRIBUTORS.md
CHANGED
@@ -53,12 +53,14 @@
|
|
53
53
|
* Ohad Levy <ohadlevy@redhat.com>
|
54
54
|
* Ondrej Prazak <oprazak@redhat.com>
|
55
55
|
* Oscar Elfving <sofam84@gmail.com>
|
56
|
+
* Pablo Hess <phess@redhat.com>
|
56
57
|
* Paul Thornthwaite <paul@brightbox.co.uk>
|
57
58
|
* Paul Thornthwaite <tokengeek@gmail.com>
|
58
59
|
* Paulo Henrique Lopes Ribeiro <plribeiro3000@gmail.com>
|
59
|
-
* Rohan Arora <roarora@redhat.com>
|
60
60
|
* Rich Daley <rdaley@williamhill.co.uk>
|
61
61
|
* Rich Lane <rlane@club.cc.cmu.edu>
|
62
|
+
* Rohan Arora <roarora@redhat.com>
|
63
|
+
* Roman Lazoryshchak <lazoryshchak@gmail.com>
|
62
64
|
* Samuel Keeley <samuel@dropbox.com>
|
63
65
|
* Sergio Cambra <sergio@programatica.es>
|
64
66
|
* Shlomi Zadok <shlomi@ben-hanna.com>
|
data/lib/fog/vsphere/compute.rb
CHANGED
@@ -71,6 +71,9 @@ module Fog
|
|
71
71
|
request :get_cluster
|
72
72
|
request :list_resource_pools
|
73
73
|
request :get_resource_pool
|
74
|
+
request :create_resource_pool
|
75
|
+
request :update_resource_pool
|
76
|
+
request :destroy_resource_pool
|
74
77
|
request :list_networks
|
75
78
|
request :get_network
|
76
79
|
request :list_datastores
|
@@ -165,7 +168,8 @@ module Fog
|
|
165
168
|
memoryHotAddEnabled: 'config.memoryHotAddEnabled',
|
166
169
|
firmware: 'config.firmware',
|
167
170
|
boot_order: 'config.bootOptions.bootOrder',
|
168
|
-
annotation: 'config.annotation'
|
171
|
+
annotation: 'config.annotation',
|
172
|
+
extra_config: 'config.extraConfig'
|
169
173
|
}.freeze
|
170
174
|
|
171
175
|
def convert_vm_view_to_attr_hash(vms)
|
@@ -247,6 +251,8 @@ module Fog
|
|
247
251
|
nil
|
248
252
|
end
|
249
253
|
}
|
254
|
+
|
255
|
+
attrs['extra_config'] = parse_extra_config(attrs['extra_config'])
|
250
256
|
end
|
251
257
|
# This inline rescue catches any standard error. While a VM is
|
252
258
|
# cloning, a call to the macs method will throw and NoMethodError
|
@@ -305,6 +311,12 @@ module Fog
|
|
305
311
|
end.compact.uniq
|
306
312
|
end
|
307
313
|
|
314
|
+
# Flattens Array of RbVmomi::VIM::OptionValue to simple hash
|
315
|
+
def parse_extra_config(vm_extra_config)
|
316
|
+
return unless vm_extra_config.is_a?(Array)
|
317
|
+
vm_extra_config.map { |entry| [entry[:key], entry[:value]] }.to_h
|
318
|
+
end
|
319
|
+
|
308
320
|
# returns vmware managed obj id string
|
309
321
|
def managed_obj_id(obj)
|
310
322
|
obj.to_s.match(/\("([^"]+)"\)/)[1]
|
@@ -52,6 +52,7 @@ module Fog
|
|
52
52
|
attribute :firmware
|
53
53
|
attribute :boot_order
|
54
54
|
attribute :annotation
|
55
|
+
attribute :extra_config
|
55
56
|
|
56
57
|
def initialize(attributes = {})
|
57
58
|
super defaults.merge(attributes)
|
@@ -157,7 +158,8 @@ module Fog
|
|
157
158
|
|
158
159
|
# Give our path to the request
|
159
160
|
req_options['template_path'] = "#{relative_path}/#{name}"
|
160
|
-
req_options['
|
161
|
+
req_options['template_datacenter'] = datacenter.to_s
|
162
|
+
req_options['datacenter'] ||= datacenter.to_s
|
161
163
|
|
162
164
|
# Perform the actual clone
|
163
165
|
clone_results = service.vm_clone(req_options)
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Fog
|
2
|
+
module Vsphere
|
3
|
+
class Compute
|
4
|
+
class Real
|
5
|
+
def create_resource_pool(attributes = {})
|
6
|
+
cluster = get_raw_cluster(attributes[:cluster], attributes[:datacenter])
|
7
|
+
|
8
|
+
root_resource_pool = if attributes[:root_resource_pool_name]
|
9
|
+
cluster.resourcePool.find attributes[:root_resource_pool_name].gsub('/', '%2f')
|
10
|
+
else
|
11
|
+
cluster.resourcePool
|
12
|
+
end
|
13
|
+
|
14
|
+
raise ArgumentError, 'Root resource pool could not be found' if root_resource_pool.nil?
|
15
|
+
|
16
|
+
resource_pool = root_resource_pool.CreateResourcePool(
|
17
|
+
name: attributes[:name],
|
18
|
+
spec: get_resource_pool_spec(attributes)
|
19
|
+
)
|
20
|
+
|
21
|
+
resource_pool_attributes(resource_pool, attributes[:cluster], attributes[:datacenter])
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def get_resource_pool_spec(attributes = {})
|
27
|
+
RbVmomi::VIM.ResourceConfigSpec(
|
28
|
+
cpuAllocation: get_resource_pool_allocation_spec(attributes.fetch(:cpu, {})),
|
29
|
+
memoryAllocation: get_resource_pool_allocation_spec(attributes.fetch(:memory, {}))
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_resource_pool_allocation_spec(attributes = {})
|
34
|
+
RbVmomi::VIM.ResourceAllocationInfo(
|
35
|
+
reservation: attributes.fetch(:reservation, 0),
|
36
|
+
limit: attributes.fetch(:limit, -1),
|
37
|
+
expandableReservation: attributes.fetch(:expandable_reservation, false),
|
38
|
+
shares: RbVmomi::VIM.SharesInfo(
|
39
|
+
level: RbVmomi::VIM.SharesLevel(attributes.fetch(:shares_level, 'normal')),
|
40
|
+
shares: attributes.fetch(:shares, 0)
|
41
|
+
)
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class Mock
|
47
|
+
def create_resource_pool(attributes = {}); end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Fog
|
2
|
+
module Vsphere
|
3
|
+
class Compute
|
4
|
+
class Real
|
5
|
+
def destroy_resource_pool(attributes = {})
|
6
|
+
get_raw_resource_pool_by_ref(attributes).Destroy_Task().wait_for_completion
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Mock
|
11
|
+
def destroy_resource_pool(attributes = {}); end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -38,7 +38,7 @@ module Fog
|
|
38
38
|
# only the one will do
|
39
39
|
proc do |n|
|
40
40
|
n._ref == ref_or_name || (
|
41
|
-
n.is_a?(RbVmomi::VIM::DistributedVirtualPortgroup) && (n.name == ref_or_name
|
41
|
+
n.is_a?(RbVmomi::VIM::DistributedVirtualPortgroup) && (n.name == ref_or_name) &&
|
42
42
|
(n.config.distributedVirtualSwitch.name == distributedswitch)
|
43
43
|
)
|
44
44
|
end
|
@@ -46,12 +46,12 @@ module Fog
|
|
46
46
|
# the first distributed virtual switch will do - selected by network - gives control to vsphere
|
47
47
|
proc do |n|
|
48
48
|
n._ref == ref_or_name || (
|
49
|
-
n.is_a?(RbVmomi::VIM::DistributedVirtualPortgroup) && (n.name == ref_or_name
|
49
|
+
n.is_a?(RbVmomi::VIM::DistributedVirtualPortgroup) && (n.name == ref_or_name)
|
50
50
|
)
|
51
51
|
end
|
52
52
|
else
|
53
53
|
# the first matching network will do, seems like the non-distributed networks come first
|
54
|
-
proc { |n| n._ref == ref_or_name || n.name == ref_or_name
|
54
|
+
proc { |n| n._ref == ref_or_name || n.name == ref_or_name }
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
@@ -30,17 +30,15 @@ module Fog
|
|
30
30
|
virtualswitch: dvswitches[network['config.distributedVirtualSwitch']._ref]
|
31
31
|
)
|
32
32
|
elsif network.obj.is_a?(RbVmomi::VIM::OpaqueNetwork)
|
33
|
-
map_attrs_to_hash(network,
|
34
|
-
id: network.obj._ref,
|
33
|
+
map_attrs_to_hash(network, network_attribute_mapping).merge(
|
35
34
|
opaqueNetworkId: network.obj.summary.opaqueNetworkId
|
36
35
|
)
|
37
36
|
else
|
38
|
-
map_attrs_to_hash(network, network_attribute_mapping)
|
39
|
-
id: network.obj._ref
|
40
|
-
)
|
37
|
+
map_attrs_to_hash(network, network_attribute_mapping)
|
41
38
|
end.merge(
|
42
|
-
|
43
|
-
|
39
|
+
_ref: network.obj._ref,
|
40
|
+
id: managed_obj_id(network.obj),
|
41
|
+
datacenter: datacenter_name
|
44
42
|
)
|
45
43
|
end.compact
|
46
44
|
end
|
@@ -56,7 +54,7 @@ module Fog
|
|
56
54
|
|
57
55
|
def network_dvportgroup_attribute_mapping
|
58
56
|
network_attribute_mapping.merge(
|
59
|
-
|
57
|
+
dvp_uuid: 'config.key'
|
60
58
|
)
|
61
59
|
end
|
62
60
|
|
@@ -36,8 +36,8 @@ module Fog
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def resource_pool_attributes(resource_pool, cluster, datacenter)
|
39
|
-
|
40
|
-
name = 'Resources'
|
39
|
+
folder_path(resource_pool) =~ /(?<=Resources\/)(.+)/
|
40
|
+
name = Regexp.last_match(1) || 'Resources'
|
41
41
|
{
|
42
42
|
id: managed_obj_id(resource_pool),
|
43
43
|
name: name,
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Fog
|
2
|
+
module Vsphere
|
3
|
+
class Compute
|
4
|
+
class Real
|
5
|
+
def update_resource_pool(attributes = {})
|
6
|
+
raw_resource_pool = get_raw_resource_pool_by_ref(attributes)
|
7
|
+
|
8
|
+
raw_resource_pool.UpdateConfig(
|
9
|
+
name: attributes[:name],
|
10
|
+
config: get_resource_pool_spec(attributes)
|
11
|
+
)
|
12
|
+
|
13
|
+
resource_pool_attributes(raw_resource_pool, attributes[:cluster], attributes[:datacenter])
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def get_raw_resource_pool_by_ref(attributes = {})
|
19
|
+
dc = find_raw_datacenter(attributes[:datacenter])
|
20
|
+
cluster = dc.find_compute_resource(attributes[:cluster])
|
21
|
+
|
22
|
+
list_raw_resource_pools(cluster).detect { |rp| rp._ref == attributes[:ref] }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Mock
|
27
|
+
def update_resource_pool(attributes = {}); end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -21,9 +21,15 @@ module Fog
|
|
21
21
|
end
|
22
22
|
raise ArgumentError, 'cluster option is required' unless options['resource_pool'][0]
|
23
23
|
raise Fog::Vsphere::Compute::NotFound, "Datacenter #{options['datacenter']} Doesn't Exist!" unless get_datacenter(options['datacenter'])
|
24
|
-
|
24
|
+
if options['template_datacenter'] && !get_datacenter(options['template_datacenter'])
|
25
|
+
raise Fog::Vsphere::Compute::NotFound, "Datacenter #{options['template_datacenter']} Doesn't Exist!"
|
26
|
+
end
|
27
|
+
raise Fog::Vsphere::Compute::NotFound, "Template #{options['template_path']} Doesn't Exist!" unless get_virtual_machine(options['template_path'], options['template_datacenter'] || options['datacenter'])
|
25
28
|
raise Fog::Vsphere::Compute::NotFound, "Cluster #{options['resource_pool'][0]} Doesn't Exist in the DC!" unless get_raw_cluster(options["resource_pool"][0], options['datacenter'])
|
26
29
|
raise ArgumentError, 'path option is required' unless options.fetch('dest_folder', '/')
|
30
|
+
if options.key?('datastore') && !options['datastore'].nil? && !get_raw_datastore(options['datastore'], options['datacenter'])
|
31
|
+
raise Fog::Vsphere::Compute::NotFound, "Datastore #{options['datastore']} Doesn't Exist!"
|
32
|
+
end
|
27
33
|
if options.key?('storage_pod') && !options['storage_pod'].nil? && !get_raw_storage_pod(options['storage_pod'], options['datacenter'])
|
28
34
|
raise Fog::Vsphere::Compute::NotFound, "Storage Pod #{options['storage_pod']} Doesn't Exist!"
|
29
35
|
end
|
@@ -47,6 +53,9 @@ module Fog
|
|
47
53
|
# want to clone FROM. Relative to Datacenter (Example:
|
48
54
|
# "FolderNameHere/VMNameHere")
|
49
55
|
# * 'name'<~String> - *REQUIRED* The VMName of the Destination
|
56
|
+
# * 'template_datacenter'<~String> - Datacenter name where template
|
57
|
+
# is. Make sure this datacenter exists, should if you're using
|
58
|
+
# the clone function in server.rb model.
|
50
59
|
# * 'dest_folder'<~String> - Destination Folder of where 'name' will
|
51
60
|
# be placed on your cluster. Relative Path to Datacenter E.G.
|
52
61
|
# "FolderPlaceHere/anotherSub Folder/onemore"
|
@@ -101,14 +110,11 @@ module Fog
|
|
101
110
|
# Option handling
|
102
111
|
options = vm_clone_check_options(options)
|
103
112
|
|
104
|
-
# Added for people still using options['path']
|
105
|
-
template_path = options['path'] || options['template_path']
|
106
|
-
|
107
113
|
# Options['template_path']<~String>
|
108
114
|
# Added for people still using options['path']
|
109
115
|
template_path = options['path'] || options['template_path']
|
110
116
|
# Now find the template itself using the efficient find method
|
111
|
-
vm_mob_ref = get_vm_ref(template_path, options['datacenter'])
|
117
|
+
vm_mob_ref = get_vm_ref(template_path, options['template_datacenter'] || options['datacenter'])
|
112
118
|
|
113
119
|
# Options['dest_folder']<~String>
|
114
120
|
# Grab the destination folder object if it exists else use cloned mach
|
@@ -806,7 +812,7 @@ module Fog
|
|
806
812
|
end
|
807
813
|
|
808
814
|
new_nics.each do |interface|
|
809
|
-
specs << create_interface(interface,
|
815
|
+
specs << create_interface(interface, -rand(25000..29999), :add, datacenter: datacenter)
|
810
816
|
end
|
811
817
|
|
812
818
|
specs
|
@@ -5,13 +5,17 @@ module Fog
|
|
5
5
|
def vm_take_snapshot(options = {})
|
6
6
|
raise ArgumentError, 'instance_uuid is a required parameter' unless options.key? 'instance_uuid'
|
7
7
|
raise ArgumentError, 'name is a required parameter' unless options.key? 'name'
|
8
|
+
defaults = {
|
9
|
+
description: '',
|
10
|
+
memory: true,
|
11
|
+
quiesce: false
|
12
|
+
}
|
13
|
+
opts = options.clone
|
14
|
+
defaults.each do |k, v|
|
15
|
+
opts[k] = v unless opts.key?(k) || opts.key?(k.to_s)
|
16
|
+
end
|
8
17
|
vm = get_vm_ref(options['instance_uuid'])
|
9
|
-
task = vm.CreateSnapshot_Task(
|
10
|
-
name: options['name'],
|
11
|
-
description: options['description'] || '',
|
12
|
-
memory: options['memory'] || true,
|
13
|
-
quiesce: options['quiesce'] || false
|
14
|
-
)
|
18
|
+
task = vm.CreateSnapshot_Task(opts)
|
15
19
|
|
16
20
|
task.wait_for_completion
|
17
21
|
|
data/lib/fog/vsphere/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fog-vsphere
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- J.R. Garcia
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-05-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fog-core
|
@@ -240,10 +240,12 @@ files:
|
|
240
240
|
- lib/fog/vsphere/requests/compute/cloudinit_to_customspec.rb
|
241
241
|
- lib/fog/vsphere/requests/compute/create_folder.rb
|
242
242
|
- lib/fog/vsphere/requests/compute/create_group.rb
|
243
|
+
- lib/fog/vsphere/requests/compute/create_resource_pool.rb
|
243
244
|
- lib/fog/vsphere/requests/compute/create_rule.rb
|
244
245
|
- lib/fog/vsphere/requests/compute/create_vm.rb
|
245
246
|
- lib/fog/vsphere/requests/compute/current_time.rb
|
246
247
|
- lib/fog/vsphere/requests/compute/destroy_group.rb
|
248
|
+
- lib/fog/vsphere/requests/compute/destroy_resource_pool.rb
|
247
249
|
- lib/fog/vsphere/requests/compute/destroy_rule.rb
|
248
250
|
- lib/fog/vsphere/requests/compute/folder_destroy.rb
|
249
251
|
- lib/fog/vsphere/requests/compute/get_cluster.rb
|
@@ -293,6 +295,7 @@ files:
|
|
293
295
|
- lib/fog/vsphere/requests/compute/modify_vm_volume.rb
|
294
296
|
- lib/fog/vsphere/requests/compute/revert_to_snapshot.rb
|
295
297
|
- lib/fog/vsphere/requests/compute/set_vm_customvalue.rb
|
298
|
+
- lib/fog/vsphere/requests/compute/update_resource_pool.rb
|
296
299
|
- lib/fog/vsphere/requests/compute/update_vm.rb
|
297
300
|
- lib/fog/vsphere/requests/compute/upload_iso.rb
|
298
301
|
- lib/fog/vsphere/requests/compute/vm_acquire_ticket.rb
|
@@ -335,7 +338,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
335
338
|
- !ruby/object:Gem::Version
|
336
339
|
version: '0'
|
337
340
|
requirements: []
|
338
|
-
rubygems_version: 3.
|
341
|
+
rubygems_version: 3.1.4
|
339
342
|
signing_key:
|
340
343
|
specification_version: 4
|
341
344
|
summary: Module for the 'fog' gem to support VMware vSphere.
|