rbvmomi2 3.0.0 → 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +11 -25
- data/exe/rbvmomish +50 -48
- data/lib/rbvmomi/basic_types.rb +318 -294
- data/lib/rbvmomi/connection.rb +221 -216
- data/lib/rbvmomi/deserialization.rb +201 -205
- data/lib/rbvmomi/fault.rb +10 -9
- data/lib/rbvmomi/optimist.rb +51 -50
- data/lib/rbvmomi/pbm.rb +52 -50
- data/lib/rbvmomi/sms/SmsStorageManager.rb +2 -1
- data/lib/rbvmomi/sms.rb +48 -46
- data/lib/rbvmomi/sso.rb +13 -18
- data/lib/rbvmomi/trivial_soap.rb +9 -8
- data/lib/rbvmomi/type_loader.rb +100 -101
- data/lib/rbvmomi/utils/admission_control.rb +90 -106
- data/lib/rbvmomi/utils/deploy.rb +77 -85
- data/lib/rbvmomi/utils/leases.rb +31 -33
- data/lib/rbvmomi/utils/perfdump.rb +177 -207
- data/lib/rbvmomi/version.rb +2 -1
- data/lib/rbvmomi/vim/ComputeResource.rb +17 -15
- data/lib/rbvmomi/vim/Datacenter.rb +1 -0
- data/lib/rbvmomi/vim/Datastore.rb +18 -15
- data/lib/rbvmomi/vim/DynamicTypeMgrAllTypeInfo.rb +7 -6
- data/lib/rbvmomi/vim/DynamicTypeMgrDataTypeInfo.rb +3 -2
- data/lib/rbvmomi/vim/DynamicTypeMgrManagedTypeInfo.rb +7 -6
- data/lib/rbvmomi/vim/Folder.rb +37 -33
- data/lib/rbvmomi/vim/HostSystem.rb +139 -136
- data/lib/rbvmomi/vim/ManagedEntity.rb +15 -14
- data/lib/rbvmomi/vim/ManagedObject.rb +11 -10
- data/lib/rbvmomi/vim/ObjectContent.rb +3 -1
- data/lib/rbvmomi/vim/ObjectUpdate.rb +3 -1
- data/lib/rbvmomi/vim/OvfManager.rb +50 -57
- data/lib/rbvmomi/vim/PerfCounterInfo.rb +4 -3
- data/lib/rbvmomi/vim/PerformanceManager.rb +28 -31
- data/lib/rbvmomi/vim/PropertyCollector.rb +8 -7
- data/lib/rbvmomi/vim/ReflectManagedMethodExecuter.rb +22 -21
- data/lib/rbvmomi/vim/ResourcePool.rb +19 -18
- data/lib/rbvmomi/vim/ServiceInstance.rb +8 -7
- data/lib/rbvmomi/vim/Task.rb +6 -5
- data/lib/rbvmomi/vim/VirtualMachine.rb +8 -7
- data/lib/rbvmomi/vim.rb +112 -129
- data/lib/rbvmomi.rb +1 -0
- metadata +54 -10
@@ -1,177 +1,180 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# Copyright (c) 2011-2017 VMware, Inc. All Rights Reserved.
|
2
3
|
# SPDX-License-Identifier: MIT
|
3
4
|
|
4
5
|
module RbVmomi
|
5
6
|
|
6
|
-
class VIM::HostSystem
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
class VIM::HostSystem
|
8
|
+
def esxcli
|
9
|
+
@cached_esxcli ||= VIM::EsxcliNamespace.root(self)
|
10
|
+
end
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
def dtm
|
13
|
+
@cached_dtm ||= begin
|
14
|
+
RetrieveDynamicTypeManager()
|
15
|
+
rescue VIM::MethodNotFound
|
16
|
+
if summary.config.product.version >= '4.1.0'
|
17
|
+
if summary.config.product.version < '5.0.0' and direct?
|
18
|
+
VIM::InternalDynamicTypeManager(_connection, 'ha-dynamic-type-manager')
|
19
|
+
else
|
20
|
+
raise 'esxcli not supported through VC before 5.0.0'
|
21
|
+
end
|
18
22
|
else
|
19
|
-
raise
|
23
|
+
raise 'esxcli not supported before 4.1.0'
|
20
24
|
end
|
21
|
-
else
|
22
|
-
raise "esxcli not supported before 4.1.0"
|
23
25
|
end
|
24
|
-
|
25
|
-
end
|
26
|
+
end
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
28
|
+
def dti
|
29
|
+
@cached_dti ||= dtm.DynamicTypeMgrQueryTypeInfo
|
30
|
+
end
|
30
31
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
def create_dynamic_managed_object inst
|
33
|
+
wsdlName = dti.managedTypeInfo.find { |x| x.name == inst.moType }.wsdlName
|
34
|
+
_connection.type(wsdlName).new(_connection, inst.id)
|
35
|
+
end
|
35
36
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
inst = dtm.DynamicTypeMgrQueryMoInstances.find { |x| x.moType == 'vim.CLIInfo' }
|
40
|
-
@cached_cli_info_fetcher = create_dynamic_managed_object inst
|
41
|
-
end
|
37
|
+
def cli_info_fetcher
|
38
|
+
# XXX there can be more than one
|
39
|
+
return @cached_cli_info_fetcher if @cached_cli_info_fetcher
|
42
40
|
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
inst = dtm.DynamicTypeMgrQueryMoInstances.find { |x| x.moType == 'vim.CLIInfo' }
|
42
|
+
@cached_cli_info_fetcher = create_dynamic_managed_object inst
|
43
|
+
end
|
46
44
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
end
|
45
|
+
def mme
|
46
|
+
@cached_mme ||= RetrieveManagedMethodExecuter()
|
47
|
+
end
|
51
48
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
attr_reader :name, :parent, :host, :type, :instance, :type_info, :namespaces, :commands
|
56
|
-
|
57
|
-
def self.root host
|
58
|
-
type_hash = host.dti.toRbvmomiTypeHash
|
59
|
-
VIM.loader.add_types type_hash
|
60
|
-
all_instances = host.dtm.DynamicTypeMgrQueryMoInstances
|
61
|
-
instances = Hash[all_instances.select { |x| x.moType.start_with? ESXCLI_PREFIX }.
|
62
|
-
map { |x| [x.moType,x.id] }]
|
63
|
-
type_infos = Hash[host.dti.managedTypeInfo.map { |x| [x.name,x] }]
|
64
|
-
new('root', nil, host).tap do |root|
|
65
|
-
instances.each do |type,instance|
|
66
|
-
path = type.split('.')[2..-1]
|
67
|
-
ns = path.inject(root) { |b,v| b.namespaces[v] }
|
68
|
-
ns.realize type, instance, type_infos[type]
|
69
|
-
end
|
49
|
+
def direct?
|
50
|
+
@ref == 'ha-host'
|
70
51
|
end
|
71
52
|
end
|
72
53
|
|
73
|
-
|
74
|
-
|
75
|
-
@parent = parent
|
76
|
-
@host = host
|
77
|
-
@type = nil
|
78
|
-
@instance = nil
|
79
|
-
@type_info = nil
|
80
|
-
@namespaces = Hash.new { |h,k| h[k] = self.class.new k, self, host }
|
81
|
-
@commands = {}
|
82
|
-
@cached_cli_info = nil
|
83
|
-
end
|
54
|
+
class VIM::EsxcliNamespace
|
55
|
+
ESXCLI_PREFIX = 'vim.EsxCLI.'
|
84
56
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
57
|
+
attr_reader :name, :parent, :host, :type, :instance, :type_info, :namespaces, :commands
|
58
|
+
|
59
|
+
def self.root host
|
60
|
+
type_hash = host.dti.toRbvmomiTypeHash
|
61
|
+
VIM.loader.add_types type_hash
|
62
|
+
all_instances = host.dtm.DynamicTypeMgrQueryMoInstances
|
63
|
+
instances = Hash[all_instances.select { |x| x.moType.start_with? ESXCLI_PREFIX }.
|
64
|
+
map { |x| [x.moType, x.id] }]
|
65
|
+
type_infos = Hash[host.dti.managedTypeInfo.map { |x| [x.name, x] }]
|
66
|
+
new('root', nil, host).tap do |root|
|
67
|
+
instances.each do |type, instance|
|
68
|
+
path = type.split('.')[2..-1]
|
69
|
+
ns = path.inject(root) { |b, v| b.namespaces[v] }
|
70
|
+
ns.realize type, instance, type_infos[type]
|
71
|
+
end
|
72
|
+
end
|
93
73
|
end
|
94
|
-
end
|
95
74
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
75
|
+
def initialize name, parent, host
|
76
|
+
@name = name
|
77
|
+
@parent = parent
|
78
|
+
@host = host
|
79
|
+
@type = nil
|
80
|
+
@instance = nil
|
81
|
+
@type_info = nil
|
82
|
+
@namespaces = Hash.new { |h, k| h[k] = self.class.new k, self, host }
|
83
|
+
@commands = {}
|
84
|
+
@cached_cli_info = nil
|
100
85
|
end
|
101
|
-
end
|
102
86
|
|
103
|
-
|
104
|
-
|
105
|
-
if @host.direct?
|
106
|
-
@host.cli_info_fetcher.VimCLIInfoFetchCLIInfo(:typeName => type_name)
|
107
|
-
else
|
108
|
-
@host.mme.execute(@host.cli_info_fetcher._ref,
|
109
|
-
"vim.CLIInfo.FetchCLIInfo", :typeName => type_name)
|
110
|
-
end
|
111
|
-
end
|
87
|
+
def realize type, instance, type_info
|
88
|
+
raise if @type or @instance
|
112
89
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
90
|
+
@type = type
|
91
|
+
@instance = instance
|
92
|
+
@type_info = type_info
|
93
|
+
@type_info.method.each do |method_type_info|
|
94
|
+
name = method_type_info.name
|
95
|
+
@commands[name] = VIM::EsxcliCommand.new self, method_type_info
|
96
|
+
end
|
97
|
+
end
|
117
98
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
@commands[name].call(*args)
|
124
|
-
else
|
125
|
-
raise NoMethodError
|
99
|
+
def type_name
|
100
|
+
if @type then @type
|
101
|
+
elsif @parent then "#{@parent.type_name}.#{@name}"
|
102
|
+
else 'vim.EsxCLI'
|
103
|
+
end
|
126
104
|
end
|
127
|
-
end
|
128
105
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
q.text '{'
|
134
|
-
q.breakable
|
135
|
-
items = (@namespaces.values+@commands.values).sort_by(&:name)
|
136
|
-
q.seplist items, nil, :each do |v|
|
137
|
-
if v.is_a? VIM::EsxcliNamespace
|
138
|
-
q.pp v
|
106
|
+
def cli_info
|
107
|
+
@cached_cli_info ||=
|
108
|
+
if @host.direct?
|
109
|
+
@host.cli_info_fetcher.VimCLIInfoFetchCLIInfo(typeName: type_name)
|
139
110
|
else
|
140
|
-
|
111
|
+
@host.mme.execute(@host.cli_info_fetcher._ref,
|
112
|
+
'vim.CLIInfo.FetchCLIInfo', typeName: type_name)
|
141
113
|
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def obj
|
117
|
+
conn = @host._connection
|
118
|
+
conn.type(@type_info.wsdlName).new(conn, @instance)
|
119
|
+
end
|
120
|
+
|
121
|
+
def method_missing(name, *args)
|
122
|
+
name = name.to_s
|
123
|
+
if @namespaces.member? name and args.empty?
|
124
|
+
@namespaces[name]
|
125
|
+
elsif @commands.member? name
|
126
|
+
@commands[name].call(*args)
|
127
|
+
else
|
128
|
+
raise NoMethodError
|
142
129
|
end
|
143
130
|
end
|
144
|
-
|
145
|
-
q
|
131
|
+
|
132
|
+
def pretty_print q
|
133
|
+
q.text @name
|
134
|
+
q.text ' '
|
135
|
+
q.group 2 do
|
136
|
+
q.text '{'
|
137
|
+
q.breakable
|
138
|
+
items = (@namespaces.values+@commands.values).sort_by(&:name)
|
139
|
+
q.seplist items, nil, :each do |v|
|
140
|
+
if v.is_a? VIM::EsxcliNamespace
|
141
|
+
q.pp v
|
142
|
+
else
|
143
|
+
q.text v.name
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
q.breakable
|
148
|
+
q.text '}'
|
149
|
+
end
|
146
150
|
end
|
147
|
-
end
|
148
151
|
|
149
|
-
class VIM::EsxcliCommand
|
150
|
-
|
152
|
+
class VIM::EsxcliCommand
|
153
|
+
attr_reader :ns, :type_info, :cli_info
|
151
154
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
155
|
+
def initialize ns, type_info
|
156
|
+
@ns = ns
|
157
|
+
@type_info = type_info
|
158
|
+
@cached_cli_info = nil
|
159
|
+
end
|
157
160
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
+
def name
|
162
|
+
@type_info.name
|
163
|
+
end
|
161
164
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
+
def cli_info
|
166
|
+
@cached_cli_info ||= @ns.cli_info.method.find { |x| x.name == @type_info.name }
|
167
|
+
end
|
165
168
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
169
|
+
def call args={}
|
170
|
+
if @ns.host.direct?
|
171
|
+
@ns.obj._call @type_info.wsdlName, args
|
172
|
+
else
|
173
|
+
real_args = Set.new(type_info.paramTypeInfo.map(&:name))
|
174
|
+
args = args.reject { |k, v| !real_args.member?(k.to_s) }
|
175
|
+
@ns.host.mme.execute(@ns.obj._ref, "#{@ns.type_name}.#{@type_info.name}", args)
|
176
|
+
end
|
173
177
|
end
|
174
178
|
end
|
175
|
-
end
|
176
179
|
|
177
180
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# Copyright (c) 2011-2017 VMware, Inc. All Rights Reserved.
|
2
3
|
# SPDX-License-Identifier: MIT
|
3
4
|
|
@@ -7,35 +8,35 @@ class RbVmomi::VIM::ManagedEntity
|
|
7
8
|
def path
|
8
9
|
self.class.paths([self])[self]
|
9
10
|
end
|
10
|
-
|
11
|
+
|
11
12
|
# Retrieve the ancestors of a list of entries.
|
12
13
|
# @return [Hash] Object-indexed hash of ancestors of entities, starting with the root.
|
13
14
|
def self.paths objs
|
14
15
|
filterSpec = RbVmomi::VIM.PropertyFilterSpec(
|
15
|
-
:
|
16
|
+
objectSet: objs.map do |obj|
|
16
17
|
RbVmomi::VIM.ObjectSpec(
|
17
|
-
:
|
18
|
-
:
|
18
|
+
obj: obj,
|
19
|
+
selectSet: [
|
19
20
|
RbVmomi::VIM.TraversalSpec(
|
20
|
-
:
|
21
|
-
:
|
22
|
-
:
|
23
|
-
:
|
24
|
-
:
|
25
|
-
RbVmomi::VIM.SelectionSpec(:
|
21
|
+
name: 'tsME',
|
22
|
+
type: 'ManagedEntity',
|
23
|
+
path: 'parent',
|
24
|
+
skip: false,
|
25
|
+
selectSet: [
|
26
|
+
RbVmomi::VIM.SelectionSpec(name: 'tsME')
|
26
27
|
]
|
27
28
|
)
|
28
29
|
]
|
29
30
|
)
|
30
31
|
end,
|
31
|
-
:
|
32
|
-
:
|
33
|
-
:
|
32
|
+
propSet: [{
|
33
|
+
pathSet: %w(name parent),
|
34
|
+
type: 'ManagedEntity'
|
34
35
|
}]
|
35
36
|
)
|
36
37
|
|
37
38
|
propCollector = objs.first._connection.propertyCollector
|
38
|
-
result = propCollector.RetrieveProperties(:
|
39
|
+
result = propCollector.RetrieveProperties(specSet: [filterSpec])
|
39
40
|
|
40
41
|
Hash[objs.map do |obj|
|
41
42
|
tree = {}
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# Copyright (c) 2011-2017 VMware, Inc. All Rights Reserved.
|
2
3
|
# SPDX-License-Identifier: MIT
|
3
4
|
|
@@ -11,13 +12,13 @@ class RbVmomi::VIM::ManagedObject
|
|
11
12
|
# @todo Pass the current property values to the block.
|
12
13
|
def wait_until *pathSet, &b
|
13
14
|
all = pathSet.empty?
|
14
|
-
filter = _connection.propertyCollector.CreateFilter :
|
15
|
-
:
|
16
|
-
:
|
17
|
-
}, :
|
15
|
+
filter = _connection.propertyCollector.CreateFilter spec: {
|
16
|
+
propSet: [{ type: self.class.wsdl_name, all: all, pathSet: pathSet }],
|
17
|
+
objectSet: [{ obj: self }],
|
18
|
+
}, partialUpdates: false
|
18
19
|
ver = ''
|
19
20
|
loop do
|
20
|
-
result = _connection.propertyCollector.WaitForUpdates(:
|
21
|
+
result = _connection.propertyCollector.WaitForUpdates(version: ver)
|
21
22
|
ver = result.version
|
22
23
|
if x = b.call
|
23
24
|
return x
|
@@ -32,13 +33,13 @@ class RbVmomi::VIM::ManagedObject
|
|
32
33
|
# @return [Hash] Hash from property paths to values.
|
33
34
|
def collect! *pathSet
|
34
35
|
spec = {
|
35
|
-
:
|
36
|
-
:
|
37
|
-
:
|
38
|
-
:
|
36
|
+
objectSet: [{ obj: self }],
|
37
|
+
propSet: [{
|
38
|
+
pathSet: pathSet,
|
39
|
+
type: self.class.wsdl_name
|
39
40
|
}]
|
40
41
|
}
|
41
|
-
ret = _connection.propertyCollector.RetrieveProperties(:
|
42
|
+
ret = _connection.propertyCollector.RetrieveProperties(specSet: [spec])
|
42
43
|
if ret && ret.length > 0
|
43
44
|
ret[0].to_hash
|
44
45
|
else
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# Copyright (c) 2011-2017 VMware, Inc. All Rights Reserved.
|
2
3
|
# SPDX-License-Identifier: MIT
|
3
4
|
|
@@ -18,7 +19,8 @@ class RbVmomi::VIM::ObjectContent
|
|
18
19
|
def to_hash_uncached
|
19
20
|
h = {}
|
20
21
|
propSet.each do |x|
|
21
|
-
|
22
|
+
raise if h.member? x.name
|
23
|
+
|
22
24
|
h[x.name] = x.val
|
23
25
|
end
|
24
26
|
h
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# Copyright (c) 2011-2017 VMware, Inc. All Rights Reserved.
|
2
3
|
# SPDX-License-Identifier: MIT
|
3
4
|
|
@@ -18,7 +19,8 @@ class RbVmomi::VIM::ObjectUpdate
|
|
18
19
|
def to_hash_uncached
|
19
20
|
h = {}
|
20
21
|
changeSet.each do |x|
|
21
|
-
|
22
|
+
raise if h.member? x.name
|
23
|
+
|
22
24
|
h[x.name] = x.val
|
23
25
|
end
|
24
26
|
h
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# Copyright (c) 2011-2017 VMware, Inc. All Rights Reserved.
|
2
3
|
# SPDX-License-Identifier: MIT
|
3
4
|
|
@@ -5,7 +6,7 @@
|
|
5
6
|
# then set the +CURL+ environment variable to point to it.
|
6
7
|
# @todo Use an HTTP library instead of executing +curl+.
|
7
8
|
class RbVmomi::VIM::OvfManager
|
8
|
-
CURLBIN = ENV['CURL'] ||
|
9
|
+
CURLBIN = ENV['CURL'] || 'curl' #@private
|
9
10
|
|
10
11
|
# Deploy an OVF.
|
11
12
|
#
|
@@ -21,36 +22,34 @@ class RbVmomi::VIM::OvfManager
|
|
21
22
|
# @option opts [Hash] :propertyMappings Property mappings.
|
22
23
|
# @option opts [String] :deploymentOption Deployment option key.
|
23
24
|
def deployOVF opts
|
24
|
-
opts = { :
|
25
|
-
:
|
26
|
-
:
|
25
|
+
opts = { networkMappings: {},
|
26
|
+
propertyMappings: {},
|
27
|
+
diskProvisioning: :thin }.merge opts
|
27
28
|
|
28
29
|
%w(uri vmName vmFolder host resourcePool datastore).each do |k|
|
29
|
-
|
30
|
+
raise "parameter #{k} required" unless opts[k.to_sym]
|
30
31
|
end
|
31
32
|
|
32
33
|
ovfImportSpec = RbVmomi::VIM::OvfCreateImportSpecParams(
|
33
|
-
:
|
34
|
-
:
|
35
|
-
:
|
36
|
-
:
|
37
|
-
:
|
38
|
-
:
|
39
|
-
:
|
34
|
+
hostSystem: opts[:host],
|
35
|
+
locale: 'US',
|
36
|
+
entityName: opts[:vmName],
|
37
|
+
deploymentOption: opts[:deploymentOption] || '',
|
38
|
+
networkMapping: opts[:networkMappings].map{ |from, to| RbVmomi::VIM::OvfNetworkMapping(name: from, network: to) },
|
39
|
+
propertyMapping: opts[:propertyMappings].to_a,
|
40
|
+
diskProvisioning: opts[:diskProvisioning]
|
40
41
|
)
|
41
42
|
|
42
43
|
result = CreateImportSpec(
|
43
|
-
:
|
44
|
-
:
|
45
|
-
:
|
46
|
-
:
|
44
|
+
ovfDescriptor: open(opts[:uri]).read,
|
45
|
+
resourcePool: opts[:resourcePool],
|
46
|
+
datastore: opts[:datastore],
|
47
|
+
cisp: ovfImportSpec
|
47
48
|
)
|
48
49
|
|
49
50
|
raise result.error[0].localizedMessage if result.error && !result.error.empty?
|
50
51
|
|
51
|
-
if result.warning
|
52
|
-
result.warning.each{|x| puts "OVF Warning: #{x.localizedMessage.chomp}" }
|
53
|
-
end
|
52
|
+
result.warning.each{ |x| puts "OVF Warning: #{x.localizedMessage.chomp}" } if result.warning
|
54
53
|
|
55
54
|
importSpec = result.importSpec
|
56
55
|
if importSpec && importSpec.instantiationOst && importSpec.instantiationOst.child
|
@@ -60,20 +59,19 @@ class RbVmomi::VIM::OvfManager
|
|
60
59
|
end
|
61
60
|
end
|
62
61
|
end
|
63
|
-
|
64
|
-
nfcLease = opts[:resourcePool].ImportVApp(:spec => importSpec,
|
65
|
-
:folder => opts[:vmFolder],
|
66
|
-
:host => opts[:host])
|
67
62
|
|
68
|
-
nfcLease.
|
69
|
-
|
63
|
+
nfcLease = opts[:resourcePool].ImportVApp(spec: importSpec,
|
64
|
+
folder: opts[:vmFolder],
|
65
|
+
host: opts[:host])
|
66
|
+
|
67
|
+
nfcLease.wait_until(:state) { nfcLease.state != 'initializing' }
|
68
|
+
raise nfcLease.error if nfcLease.state == 'error'
|
69
|
+
|
70
70
|
begin
|
71
|
-
nfcLease.HttpNfcLeaseProgress(:
|
71
|
+
nfcLease.HttpNfcLeaseProgress(percent: 5)
|
72
72
|
timeout, = nfcLease.collect 'info.leaseTimeout'
|
73
73
|
puts "DEBUG: Timeout: #{timeout}"
|
74
|
-
if timeout < 4 * 60
|
75
|
-
puts "WARNING: OVF upload NFC lease timeout less than 4 minutes"
|
76
|
-
end
|
74
|
+
puts 'WARNING: OVF upload NFC lease timeout less than 4 minutes' if timeout < 4 * 60
|
77
75
|
progress = 5.0
|
78
76
|
result.fileItem.each do |fileItem|
|
79
77
|
leaseInfo, leaseState, leaseError = nfcLease.collect 'info', 'state', 'error'
|
@@ -88,33 +86,26 @@ class RbVmomi::VIM::OvfManager
|
|
88
86
|
leaseInfo, leaseState, leaseError = nfcLease.collect 'info', 'state', 'error'
|
89
87
|
i += 1
|
90
88
|
end
|
91
|
-
if leaseState !=
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
end
|
97
|
-
deviceUrl = leaseInfo.deviceUrl.find{|x| x.importKey == fileItem.deviceId}
|
98
|
-
if !deviceUrl
|
99
|
-
raise "Couldn't find deviceURL for device '#{fileItem.deviceId}'"
|
100
|
-
end
|
89
|
+
raise "NFC lease is no longer ready: #{leaseState}: #{leaseError}" if leaseState != 'ready'
|
90
|
+
raise 'NFC lease disappeared?' if leaseInfo == nil
|
91
|
+
|
92
|
+
deviceUrl = leaseInfo.deviceUrl.find{ |x| x.importKey == fileItem.deviceId }
|
93
|
+
raise "Couldn't find deviceURL for device '#{fileItem.deviceId}'" if !deviceUrl
|
101
94
|
|
102
95
|
ovfFilename = opts[:uri].to_s
|
103
96
|
tmp = ovfFilename.split(/\//)
|
104
97
|
tmp.pop
|
105
98
|
tmp << fileItem.path
|
106
|
-
filename = tmp.join(
|
99
|
+
filename = tmp.join('/')
|
107
100
|
|
108
101
|
# If filename doesn't have a URI scheme, we're considering it a local file
|
109
|
-
if URI(filename).scheme.nil?
|
110
|
-
filename = "file://" + filename
|
111
|
-
end
|
102
|
+
filename = 'file://' + filename if URI(filename).scheme.nil?
|
112
103
|
|
113
|
-
method = fileItem.create ?
|
104
|
+
method = fileItem.create ? 'PUT' : 'POST'
|
114
105
|
|
115
106
|
keepAliveThread = Thread.new do
|
116
107
|
while true
|
117
|
-
nfcLease.HttpNfcLeaseProgress(:
|
108
|
+
nfcLease.HttpNfcLeaseProgress(percent: progress.to_i)
|
118
109
|
sleep 1 * 60
|
119
110
|
end
|
120
111
|
end
|
@@ -132,24 +123,26 @@ class RbVmomi::VIM::OvfManager
|
|
132
123
|
i += 1
|
133
124
|
end while i <= 5 && !ip
|
134
125
|
raise "Couldn't get host's IP address" unless ip
|
135
|
-
|
126
|
+
|
127
|
+
href = deviceUrl.url.gsub('*', ip)
|
136
128
|
downloadCmd = "#{CURLBIN} -L '#{URI::escape(filename)}'"
|
137
129
|
uploadCmd = "#{CURLBIN} -Ss -X #{method} --insecure -T - -H 'Content-Type: application/x-vnd.vmware-streamVmdk' '#{URI::escape(href)}'"
|
138
130
|
# Previously we used to append "-H 'Content-Length: #{fileItem.size}'"
|
139
|
-
# to the uploadCmd. It is not clear to me why, but that leads to
|
131
|
+
# to the uploadCmd. It is not clear to me why, but that leads to
|
140
132
|
# trucation of the uploaded disk. Without this option curl can't tell
|
141
133
|
# the progress, but who cares
|
142
|
-
system("#{downloadCmd} | #{uploadCmd}", :
|
143
|
-
|
134
|
+
system("#{downloadCmd} | #{uploadCmd}", out: '/dev/null')
|
135
|
+
|
144
136
|
keepAliveThread.kill
|
145
137
|
keepAliveThread.join
|
146
|
-
|
138
|
+
|
147
139
|
progress += (90.0 / result.fileItem.length)
|
148
|
-
nfcLease.HttpNfcLeaseProgress(:
|
140
|
+
nfcLease.HttpNfcLeaseProgress(percent: progress.to_i)
|
149
141
|
end
|
150
142
|
|
151
|
-
nfcLease.HttpNfcLeaseProgress(:
|
152
|
-
raise nfcLease.error if nfcLease.state ==
|
143
|
+
nfcLease.HttpNfcLeaseProgress(percent: 100)
|
144
|
+
raise nfcLease.error if nfcLease.state == 'error'
|
145
|
+
|
153
146
|
i = 1
|
154
147
|
vm = nil
|
155
148
|
begin
|
@@ -173,14 +166,14 @@ class RbVmomi::VIM::OvfManager
|
|
173
166
|
i = 0
|
174
167
|
begin
|
175
168
|
nfcLease.HttpNfcLeaseComplete
|
176
|
-
puts
|
169
|
+
puts 'HttpNfcLeaseComplete succeeded'
|
177
170
|
rescue RbVmomi::VIM::InvalidState
|
178
|
-
puts
|
171
|
+
puts 'HttpNfcLeaseComplete already finished..'
|
179
172
|
rescue Exception => e
|
180
173
|
puts "HttpNfcLeaseComplete failed at iteration #{i} with exception: #{e}"
|
181
174
|
i += 1
|
182
175
|
retry if i < 3
|
183
|
-
puts
|
176
|
+
puts 'Giving up HttpNfcLeaseComplete..'
|
184
177
|
end
|
185
178
|
vm
|
186
179
|
end
|
@@ -188,7 +181,7 @@ class RbVmomi::VIM::OvfManager
|
|
188
181
|
(nfcLease.HttpNfcLeaseAbort rescue nil) if nfcLease
|
189
182
|
raise
|
190
183
|
end
|
191
|
-
|
184
|
+
|
192
185
|
def _handle_ost ost, opts = {}
|
193
186
|
ost = Nokogiri::XML(ost)
|
194
187
|
if opts[:vservice] == ['com.vmware.vim.vsm:extension_vservice']
|
@@ -1,17 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# Copyright (c) 2012-2017 VMware, Inc. All Rights Reserved.
|
2
3
|
# SPDX-License-Identifier: MIT
|
3
4
|
|
4
|
-
#
|
5
|
+
#
|
5
6
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
7
|
# of this software and associated documentation files (the "Software"), to deal
|
7
8
|
# in the Software without restriction, including without limitation the rights
|
8
9
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
10
|
# copies of the Software, and to permit persons to whom the Software is
|
10
11
|
# furnished to do so, subject to the following conditions:
|
11
|
-
#
|
12
|
+
#
|
12
13
|
# The above copyright notice and this permission notice shall be included in
|
13
14
|
# all copies or substantial portions of the Software.
|
14
|
-
#
|
15
|
+
#
|
15
16
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
17
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
18
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|