opennebula 5.12.9 → 6.0.0.1
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/lib/ActionManager.rb +1 -1
- data/lib/CommandManager.rb +1 -1
- data/lib/DriverExecHelper.rb +44 -28
- data/lib/OpenNebulaDriver.rb +8 -4
- data/lib/VirtualMachineDriver.rb +9 -2
- data/lib/cloud/CloudClient.rb +3 -3
- data/lib/datacenter.rb +1257 -0
- data/lib/datastore.rb +1025 -0
- data/lib/distributed_firewall.rb +280 -0
- data/lib/file_helper.rb +370 -0
- data/lib/host.rb +1517 -0
- data/lib/logical_port.rb +50 -0
- data/lib/logical_switch.rb +77 -0
- data/lib/memoize.rb +74 -0
- data/lib/models.rb +32 -0
- data/lib/models/role.rb +1126 -0
- data/lib/models/service.rb +709 -0
- data/lib/network.rb +699 -0
- data/lib/nsx_client.rb +144 -0
- data/lib/nsx_component.rb +28 -0
- data/lib/nsx_constants.rb +149 -0
- data/lib/nsx_driver.rb +78 -0
- data/lib/nsx_error.rb +77 -0
- data/lib/nsx_rule.rb +193 -0
- data/lib/nsxt_client.rb +176 -0
- data/lib/nsxt_dfw.rb +196 -0
- data/lib/nsxt_logical_port.rb +94 -0
- data/lib/nsxt_rule.rb +188 -0
- data/lib/nsxt_tz.rb +38 -0
- data/lib/nsxv_client.rb +176 -0
- data/lib/nsxv_dfw.rb +202 -0
- data/lib/nsxv_logical_port.rb +107 -0
- data/lib/nsxv_rule.rb +172 -0
- data/lib/nsxv_tz.rb +41 -0
- data/lib/opaque_network.rb +134 -0
- data/lib/opennebula.rb +5 -2
- data/lib/opennebula/acl.rb +1 -1
- data/lib/opennebula/acl_pool.rb +1 -1
- data/lib/opennebula/client.rb +10 -2
- data/lib/opennebula/cluster.rb +1 -1
- data/lib/opennebula/cluster_pool.rb +1 -1
- data/lib/opennebula/datastore.rb +1 -1
- data/lib/opennebula/datastore_pool.rb +1 -1
- data/lib/opennebula/document.rb +8 -29
- data/lib/opennebula/document_json.rb +42 -12
- data/lib/opennebula/document_pool.rb +1 -1
- data/lib/opennebula/document_pool_json.rb +1 -1
- data/lib/opennebula/error.rb +4 -1
- data/lib/opennebula/flow.rb +23 -0
- data/lib/opennebula/flow/grammar.rb +1195 -0
- data/lib/opennebula/flow/service_pool.rb +190 -0
- data/lib/opennebula/flow/service_template.rb +608 -0
- data/lib/opennebula/flow/service_template_ext.rb +84 -0
- data/lib/opennebula/flow/service_template_pool.rb +32 -0
- data/lib/opennebula/flow/validator.rb +499 -0
- data/lib/opennebula/group.rb +1 -1
- data/lib/opennebula/group_pool.rb +1 -1
- data/lib/opennebula/hook.rb +5 -12
- data/lib/opennebula/hook_log.rb +1 -1
- data/lib/opennebula/hook_pool.rb +1 -1
- data/lib/opennebula/host.rb +1 -1
- data/lib/opennebula/host_pool.rb +1 -1
- data/lib/opennebula/image.rb +19 -14
- data/lib/opennebula/image_pool.rb +1 -1
- data/lib/opennebula/ldap_auth.rb +1 -1
- data/lib/opennebula/ldap_auth_spec.rb +1 -1
- data/lib/opennebula/lockable_ext.rb +163 -0
- data/lib/opennebula/marketplace.rb +1 -1
- data/lib/opennebula/marketplace_pool.rb +1 -1
- data/lib/opennebula/marketplaceapp.rb +9 -119
- data/lib/opennebula/marketplaceapp_ext.rb +586 -0
- data/lib/opennebula/marketplaceapp_pool.rb +1 -1
- data/lib/opennebula/oneflow_client.rb +4 -3
- data/lib/opennebula/pool.rb +6 -3
- data/lib/opennebula/pool_element.rb +1 -1
- data/lib/opennebula/security_group.rb +1 -1
- data/lib/opennebula/security_group_pool.rb +1 -1
- data/lib/opennebula/server_cipher_auth.rb +1 -1
- data/lib/opennebula/server_x509_auth.rb +1 -1
- data/lib/opennebula/ssh_auth.rb +1 -1
- data/lib/opennebula/system.rb +1 -1
- data/lib/opennebula/template.rb +4 -13
- data/lib/opennebula/template_ext.rb +342 -0
- data/lib/opennebula/template_pool.rb +1 -1
- data/lib/opennebula/user.rb +26 -2
- data/lib/opennebula/user_pool.rb +1 -1
- data/lib/opennebula/utils.rb +1 -1
- data/lib/opennebula/vdc.rb +1 -1
- data/lib/opennebula/vdc_pool.rb +1 -1
- data/lib/opennebula/virtual_machine.rb +26 -206
- data/lib/opennebula/virtual_machine_ext.rb +469 -0
- data/lib/opennebula/virtual_machine_pool.rb +1 -1
- data/lib/opennebula/virtual_network.rb +4 -10
- data/lib/opennebula/virtual_network_pool.rb +1 -1
- data/lib/opennebula/virtual_router.rb +4 -12
- data/lib/opennebula/virtual_router_pool.rb +1 -1
- data/lib/opennebula/vm_group.rb +4 -11
- data/lib/opennebula/vm_group_pool.rb +1 -1
- data/lib/opennebula/vntemplate.rb +4 -13
- data/lib/opennebula/vntemplate_pool.rb +1 -1
- data/lib/opennebula/wait_ext.rb +257 -0
- data/lib/opennebula/x509_auth.rb +1 -1
- data/lib/opennebula/xml_element.rb +1 -1
- data/lib/opennebula/xml_pool.rb +1 -1
- data/lib/opennebula/xml_utils.rb +1 -1
- data/lib/opennebula/zone.rb +1 -1
- data/lib/opennebula/zone_pool.rb +1 -1
- data/lib/rest_client.rb +201 -0
- data/lib/scripts_common.rb +183 -0
- data/lib/transport_zone.rb +43 -0
- data/lib/vcenter_driver.rb +13 -12
- data/lib/vcenter_importer.rb +616 -0
- data/lib/vi_client.rb +281 -0
- data/lib/vi_helper.rb +313 -0
- data/lib/virtual_machine.rb +3477 -0
- data/lib/virtual_wire.rb +158 -0
- data/lib/vm_device.rb +80 -0
- data/lib/vm_disk.rb +202 -0
- data/lib/vm_folder.rb +69 -0
- data/lib/vm_helper.rb +30 -0
- data/lib/vm_monitor.rb +303 -0
- data/lib/vm_nic.rb +70 -0
- data/lib/vm_template.rb +1963 -0
- data/lib/vmm_importer.rb +121 -0
- metadata +140 -27
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------- #
|
|
2
|
+
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
|
|
3
|
+
# #
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
|
5
|
+
# not use this file except in compliance with the License. You may obtain #
|
|
6
|
+
# a copy of the License at #
|
|
7
|
+
# #
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0 #
|
|
9
|
+
# #
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software #
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS, #
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
|
13
|
+
# See the License for the specific language governing permissions and #
|
|
14
|
+
# limitations under the License. #
|
|
15
|
+
#--------------------------------------------------------------------------- #
|
|
16
|
+
|
|
17
|
+
# Module to decorate MarketApp class with additional helpers not directly
|
|
18
|
+
# exposed through the OpenNebula XMLRPC API. The extensions include
|
|
19
|
+
# - export helper that creates OpenNebula related objects from a given app.
|
|
20
|
+
#
|
|
21
|
+
# rubocop:disable Style/ClassAndModuleChildren
|
|
22
|
+
module OpenNebula::MarketPlaceAppExt
|
|
23
|
+
|
|
24
|
+
include OpenNebula
|
|
25
|
+
|
|
26
|
+
def self.extend_object(obj)
|
|
27
|
+
if !obj.is_a?(OpenNebula::MarketPlaceApp)
|
|
28
|
+
raise StandardError, "Cannot extended #{obj.class} " \
|
|
29
|
+
'with MarketPlaceAppExt'
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class << obj
|
|
33
|
+
|
|
34
|
+
####################################################################
|
|
35
|
+
# Public extended interface
|
|
36
|
+
####################################################################
|
|
37
|
+
# Exports this app to a suitable OpenNebula object
|
|
38
|
+
# @param appid [Integer] id of the marketplace app
|
|
39
|
+
# @param options [Hash] to control the export behavior
|
|
40
|
+
# dsid [Integer] datastore to save images
|
|
41
|
+
# f_dsid [Integer] file datastore to save kernels
|
|
42
|
+
# name [String] of the new object
|
|
43
|
+
# vmtemplate_name [String] name for the VM Template, if the App
|
|
44
|
+
# has one complex [Boolean] true to only create image
|
|
45
|
+
#
|
|
46
|
+
# @return [Hash, OpenNebula::Error] with the ID and type of
|
|
47
|
+
# the created objects. Instead of an ID, the array may
|
|
48
|
+
# contain OpenNebula::Error with specific object creation errors
|
|
49
|
+
# {
|
|
50
|
+
# :vm => [ vm ids/OpenNebula::Error ],
|
|
51
|
+
# :vmtemplate => [ vmtemplates ids/OpenNebula::Error ],
|
|
52
|
+
# :image => [ vm ids/OpenNebula::Error ]
|
|
53
|
+
# }
|
|
54
|
+
# rc_info = {
|
|
55
|
+
# :image => [],
|
|
56
|
+
# :image_type => nil,
|
|
57
|
+
# :vmtemplate => [],
|
|
58
|
+
# :service_template => []
|
|
59
|
+
# }
|
|
60
|
+
def export(options = {})
|
|
61
|
+
# Get App information and check for errors
|
|
62
|
+
rc = info
|
|
63
|
+
return rc if OpenNebula.is_error?(rc)
|
|
64
|
+
return Error.new('App is not READY') if state_str != 'READY'
|
|
65
|
+
|
|
66
|
+
if options[:dsid].nil?
|
|
67
|
+
return Error.new('Missing datastore id')
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
if options[:name].nil?
|
|
71
|
+
return Error.new('Missing name to export app')
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
case type_str
|
|
75
|
+
when 'IMAGE'
|
|
76
|
+
export_image(options)
|
|
77
|
+
when 'VMTEMPLATE'
|
|
78
|
+
options[:notemplate] = true
|
|
79
|
+
|
|
80
|
+
export_vm_template(options)
|
|
81
|
+
when 'SERVICE_TEMPLATE'
|
|
82
|
+
export_service_template(options)
|
|
83
|
+
else
|
|
84
|
+
Error.new("App type #{type_str} not supported")
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
####################################################################
|
|
89
|
+
# Private methods
|
|
90
|
+
####################################################################
|
|
91
|
+
private
|
|
92
|
+
|
|
93
|
+
# Exports an OpenNebula Image from this marketplace app
|
|
94
|
+
# @param options to export the image
|
|
95
|
+
# :vmtemplate_name [String] name of new image and template
|
|
96
|
+
# :url_args [String] optional URL arguments
|
|
97
|
+
# :dsid [String] Datastore id to create the image
|
|
98
|
+
# :f_dsid [String] Files Datastore id
|
|
99
|
+
# :notemplate [Bool] if true do not create vm_template (if any)
|
|
100
|
+
# :template [Integer] Template id to use with image
|
|
101
|
+
# :default_template [String] Default template id for vCenter
|
|
102
|
+
# @return [Hash]
|
|
103
|
+
# :image [Array] of the new image
|
|
104
|
+
# :image_type [String] of the new image (CONTEXT, KERNEL, CDROM)
|
|
105
|
+
# :vmtemplate [Array] of the associated vm_template (if any)
|
|
106
|
+
# :service_template [Array] empty []
|
|
107
|
+
def export_image(options)
|
|
108
|
+
rc_info = {
|
|
109
|
+
:image => [],
|
|
110
|
+
:image_type => nil,
|
|
111
|
+
:vmtemplate => [],
|
|
112
|
+
:service_template => []
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
#---------------------------------------------------------------
|
|
116
|
+
# Create the image template
|
|
117
|
+
#---------------------------------------------------------------
|
|
118
|
+
tmpl = ''
|
|
119
|
+
|
|
120
|
+
if self['APPTEMPLATE64']
|
|
121
|
+
tmpl = Base64.decode64(self['APPTEMPLATE64'])
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
tmpl << <<-EOT
|
|
125
|
+
NAME = "#{options[:name]}"
|
|
126
|
+
FROM_APP = "#{self['ID']}"
|
|
127
|
+
EOT
|
|
128
|
+
|
|
129
|
+
if options[:url_args]
|
|
130
|
+
tmpl << "URL_ARGS=\"#{options[:url_args]}\"\n"
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
#---------------------------------------------------------------
|
|
134
|
+
# Kernel or context images stored in a files datastore
|
|
135
|
+
#---------------------------------------------------------------
|
|
136
|
+
dsid = options[:dsid]
|
|
137
|
+
|
|
138
|
+
if tmpl.match(/^\s*TYPE\s*=\s*KERNEL|CONTEXT\s/i)
|
|
139
|
+
if options[:f_dsid]
|
|
140
|
+
dsid = options[:f_dsid]
|
|
141
|
+
else
|
|
142
|
+
dspool = DatastorePool.new(@client)
|
|
143
|
+
|
|
144
|
+
rc = dspool.info
|
|
145
|
+
return { :image => [rc] } if OpenNebula.is_error?(rc)
|
|
146
|
+
|
|
147
|
+
file_ds = dspool.select {|d| d['TYPE'].to_i == 2 }
|
|
148
|
+
dsid = file_ds.first['ID'].to_i
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
ds = OpenNebula::Datastore.new_with_id(dsid, @client)
|
|
153
|
+
rc = ds.info
|
|
154
|
+
|
|
155
|
+
is_vcenter = !OpenNebula.is_error?(rc) &&
|
|
156
|
+
(ds['TEMPLATE/DRIVER'] == 'vcenter')
|
|
157
|
+
|
|
158
|
+
if is_vcenter && options[:template].nil?
|
|
159
|
+
options = update_options_with_template(options)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
#---------------------------------------------------------------
|
|
163
|
+
# Allocate the image in OpenNebula
|
|
164
|
+
#---------------------------------------------------------------
|
|
165
|
+
image = Image.new(Image.build_xml, @client)
|
|
166
|
+
rc = image.allocate(tmpl, dsid)
|
|
167
|
+
|
|
168
|
+
if OpenNebula.is_error?(rc)
|
|
169
|
+
rc_info[:image] = [rc]
|
|
170
|
+
|
|
171
|
+
return rc_info
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
image.info
|
|
175
|
+
|
|
176
|
+
image.delete_element('TEMPLATE/FORMAT')
|
|
177
|
+
image.delete_element('TEMPLATE/DRIVER')
|
|
178
|
+
image.delete_element('TEMPLATE/DEV_PREFIX') if is_vcenter
|
|
179
|
+
|
|
180
|
+
image.update(image.template_xml)
|
|
181
|
+
|
|
182
|
+
rc_info[:image] = [image.id]
|
|
183
|
+
rc_info[:image_type] = image.type_str
|
|
184
|
+
|
|
185
|
+
#---------------------------------------------------------------
|
|
186
|
+
# Created an associated VMTemplate if needed
|
|
187
|
+
#---------------------------------------------------------------
|
|
188
|
+
if (self['TEMPLATE/VMTEMPLATE64'].nil? && !is_vcenter) ||
|
|
189
|
+
options[:notemplate] ||
|
|
190
|
+
options[:template] == -1
|
|
191
|
+
return rc_info
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
if !options[:template].nil?
|
|
195
|
+
template_id = options[:template]
|
|
196
|
+
|
|
197
|
+
if template_id < 0
|
|
198
|
+
raise 'Invalid option, template_id must be a valid ID'
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
template = Template.new_with_id(template_id, @client)
|
|
202
|
+
|
|
203
|
+
vmtpl_id = template.clone(
|
|
204
|
+
options[:vmtemplate_name] || options[:name]
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
tmpl << <<-EOT
|
|
208
|
+
|
|
209
|
+
NAME = "#{options[:vmtemplate_name] || options[:name]}"
|
|
210
|
+
DISK = [ IMAGE_ID = "#{image.id}" ]
|
|
211
|
+
EOT
|
|
212
|
+
|
|
213
|
+
template = Template.new_with_id(vmtpl_id, @client)
|
|
214
|
+
|
|
215
|
+
template.update(tmpl, true)
|
|
216
|
+
|
|
217
|
+
rc_info[:vmtemplate] = [vmtpl_id]
|
|
218
|
+
else
|
|
219
|
+
tmpl = Base64.decode64(self['TEMPLATE/VMTEMPLATE64'])
|
|
220
|
+
tmpl << <<-EOT
|
|
221
|
+
|
|
222
|
+
NAME = "#{options[:vmtemplate_name] || options[:name]}"
|
|
223
|
+
DISK = [ IMAGE_ID = "#{image.id}" ]
|
|
224
|
+
EOT
|
|
225
|
+
|
|
226
|
+
vmtpl = Template.new(Template.build_xml, @client)
|
|
227
|
+
|
|
228
|
+
rc = vmtpl.allocate(tmpl)
|
|
229
|
+
rc = vmtpl.id unless OpenNebula.is_error?(rc)
|
|
230
|
+
|
|
231
|
+
rc_info[:vmtemplate] = [rc]
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
rc_info
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# Export complex template from marketplace
|
|
238
|
+
#
|
|
239
|
+
# @param name [Hash] Export options
|
|
240
|
+
# @param ds_id [Integer] Datastore ID to export child apps
|
|
241
|
+
def export_vm_template(options)
|
|
242
|
+
rc = {
|
|
243
|
+
:image => [],
|
|
244
|
+
:image_type => nil,
|
|
245
|
+
:vmtemplate => [],
|
|
246
|
+
:service_template => []
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
vmtmpl = export_recursive('//DISK', options) do |disks|
|
|
250
|
+
create_vm_template(options, disks)
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
rc[:vmtemplate] = [vmtmpl[0]]
|
|
254
|
+
|
|
255
|
+
unless OpenNebula.is_error?(vmtmpl[0])
|
|
256
|
+
rc[:image] += vmtmpl[1]
|
|
257
|
+
rc[:vmtemplate] += vmtmpl[2] unless options[:notemplate]
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
rc
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
# Export service template from marketplace
|
|
264
|
+
#
|
|
265
|
+
# @param name [Hash] Export options
|
|
266
|
+
# @param ds_id [Integer] Datastore ID to export child apps
|
|
267
|
+
def export_service_template(options)
|
|
268
|
+
rc = {
|
|
269
|
+
:image => [],
|
|
270
|
+
:image_type => nil,
|
|
271
|
+
:vmtemplate => [],
|
|
272
|
+
:service_template => []
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
stmpl = export_recursive('//ROLE', options) do |roles|
|
|
276
|
+
create_service_template(options, roles)
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
rc[:service_template] = [stmpl[0]]
|
|
280
|
+
|
|
281
|
+
unless OpenNebula.is_error?(stmpl[0])
|
|
282
|
+
rc[:image] += stmpl[1]
|
|
283
|
+
rc[:vmtemplate] += stmpl[2]
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
rc
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
def update_options_with_template(options, _validate = false)
|
|
290
|
+
vcenterrc_path =
|
|
291
|
+
"#{VAR_LOCATION}/remotes/etc/vmm/vcenter/vcenterrc"
|
|
292
|
+
|
|
293
|
+
if File.file?(vcenterrc_path)
|
|
294
|
+
config_vcenter = YAML.load_file(vcenterrc_path)
|
|
295
|
+
|
|
296
|
+
if config_vcenter.key?(:default_template)
|
|
297
|
+
options[:template] =
|
|
298
|
+
config_vcenter[:default_template]
|
|
299
|
+
|
|
300
|
+
options
|
|
301
|
+
else
|
|
302
|
+
raise "Couldn't find default_template " \
|
|
303
|
+
'configuration in vcenterrc conf ' \
|
|
304
|
+
'file. Please use the --template ' \
|
|
305
|
+
'file to define a VM Template ID if ' \
|
|
306
|
+
'needed or add default_template to' \
|
|
307
|
+
' vcenterrc conf file'
|
|
308
|
+
end
|
|
309
|
+
else
|
|
310
|
+
raise "Couldn't find vcenterrc conf file. " \
|
|
311
|
+
' Please use the --template file to define' \
|
|
312
|
+
' a VM Template ID if needed.'
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
# Creates a VM template based on the APPTEMPLATE64 attribute
|
|
317
|
+
# @param [Hash] options
|
|
318
|
+
# :export_name [String] name of the vm template
|
|
319
|
+
# @param [Hash] disks exported disks from related apps.
|
|
320
|
+
# As returned by the export_image method
|
|
321
|
+
#
|
|
322
|
+
# @return [Integer, OpenNebula::Error] template id or error
|
|
323
|
+
def create_vm_template(options, disks)
|
|
324
|
+
dsid = options[:dsid]
|
|
325
|
+
ds = OpenNebula::Datastore.new_with_id(dsid, @client)
|
|
326
|
+
rc = ds.info
|
|
327
|
+
|
|
328
|
+
is_vcenter =
|
|
329
|
+
!OpenNebula.is_error?(rc) &&
|
|
330
|
+
(ds['TEMPLATE/DRIVER'] == 'vcenter')
|
|
331
|
+
|
|
332
|
+
if is_vcenter
|
|
333
|
+
if options[:template].nil?
|
|
334
|
+
options = update_options_with_template(options)
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
template_id = options[:template]
|
|
338
|
+
|
|
339
|
+
if template_id < 0
|
|
340
|
+
return
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
template = Template.new_with_id(template_id, @client)
|
|
344
|
+
|
|
345
|
+
vmtpl_id = template.clone(
|
|
346
|
+
options[:vmtemplate_name] || options[:name]
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
vmtpl = Template.new_with_id(vmtpl_id, @client)
|
|
350
|
+
rc = vmtpl.info
|
|
351
|
+
else
|
|
352
|
+
# ----------------------------------------------------------
|
|
353
|
+
# Allocate Template
|
|
354
|
+
# ----------------------------------------------------------
|
|
355
|
+
if self['TEMPLATE/APPTEMPLATE64'].nil?
|
|
356
|
+
return Error.new(
|
|
357
|
+
"Missing APPTEMPLATE64 for App #{id}"
|
|
358
|
+
)
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
tmpl = Base64.decode64(self['TEMPLATE/APPTEMPLATE64'])
|
|
362
|
+
|
|
363
|
+
tmpl << "\nNAME=\"#{options[:name]}\"\n"
|
|
364
|
+
|
|
365
|
+
vmtpl = Template.new(Template.build_xml, @client)
|
|
366
|
+
rc = vmtpl.allocate(tmpl)
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
return rc if OpenNebula.is_error?(rc)
|
|
370
|
+
|
|
371
|
+
# --------------------------------------------------------------
|
|
372
|
+
# Update disk information in template
|
|
373
|
+
# --------------------------------------------------------------
|
|
374
|
+
vmtpl.info
|
|
375
|
+
|
|
376
|
+
context = []
|
|
377
|
+
|
|
378
|
+
disks.each do |_app, disk|
|
|
379
|
+
id = disk[:image]
|
|
380
|
+
|
|
381
|
+
case disk[:image_type]
|
|
382
|
+
when 'IMAGE', 'OS', 'DATABLOCK', 'CDROM'
|
|
383
|
+
vmtpl.add_element('TEMPLATE',
|
|
384
|
+
'DISK' => { 'IMAGE_ID' => id.first })
|
|
385
|
+
when 'CONTEXT'
|
|
386
|
+
context << "$FILE[IMAGE_ID=\"#{id}\"]"
|
|
387
|
+
when 'KERNEL'
|
|
388
|
+
if !vmtpl.has_elements?('TEMPLATE/OS')
|
|
389
|
+
vmtpl.add_element('TEMPLATE', 'OS'=>{})
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
vmtpl.add_element(
|
|
393
|
+
'TEMPLATE/OS',
|
|
394
|
+
'KERNEL_DS' => "$FILE[IMAGE_ID=#{id}]"
|
|
395
|
+
)
|
|
396
|
+
end
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
if !context.empty?
|
|
400
|
+
if !vmtpl.has_elements?('TEMPLATE/CONTEXT')
|
|
401
|
+
vmtpl.add_element('TEMPLATE', 'CONTEXT' => {})
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
vmtpl.add_element('TEMPLATE/CONTEXT',
|
|
405
|
+
'FILES_DS' => context.join(' '))
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
# --------------------------------------------------------------
|
|
409
|
+
# Update template information in OpenNebula
|
|
410
|
+
# --------------------------------------------------------------
|
|
411
|
+
vmtpl.update(vmtpl.template_xml)
|
|
412
|
+
|
|
413
|
+
vmtpl.id
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
# Creates a Service template based on the VMTEMPLATE64 attribute
|
|
417
|
+
# @return [Integer, OpenNebula::Error] template id or error
|
|
418
|
+
def create_service_template(options, roles)
|
|
419
|
+
# --------------------------------------------------------------
|
|
420
|
+
# Allocate Template
|
|
421
|
+
# --------------------------------------------------------------
|
|
422
|
+
if self['TEMPLATE/APPTEMPLATE64'].nil?
|
|
423
|
+
return Error.new("Missing APPTEMPLATE64 for App #{id}")
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
tmpl = Base64.decode64(self['TEMPLATE/APPTEMPLATE64'])
|
|
427
|
+
tmpl = JSON.parse(tmpl)
|
|
428
|
+
|
|
429
|
+
tmpl['name'] = options[:name]
|
|
430
|
+
|
|
431
|
+
# --------------------------------------------------------------
|
|
432
|
+
# Append template IDs to each role information
|
|
433
|
+
# --------------------------------------------------------------
|
|
434
|
+
tmpl['roles'].each do |role|
|
|
435
|
+
t_id = roles.find {|_, v| v[:names].include?(role['name']) }
|
|
436
|
+
|
|
437
|
+
if t_id.nil? || t_id[1].nil? || t_id[1][:vmtemplate].nil?
|
|
438
|
+
next
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
role['vm_template'] = nil
|
|
442
|
+
role['vm_template'] = t_id[1][:vmtemplate][0]
|
|
443
|
+
end
|
|
444
|
+
|
|
445
|
+
# --------------------------------------------------------------
|
|
446
|
+
# Allocate Service template in OpenNebula
|
|
447
|
+
# --------------------------------------------------------------
|
|
448
|
+
stmpl = ServiceTemplate.new(ServiceTemplate.build_xml, @client)
|
|
449
|
+
|
|
450
|
+
rc = stmpl.allocate(tmpl.to_json)
|
|
451
|
+
rc = stmpl.id unless OpenNebula.is_error?(rc)
|
|
452
|
+
|
|
453
|
+
rc
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
# Export complex template from marketplace
|
|
457
|
+
#
|
|
458
|
+
# @param xpath [String] Xpath to search childs
|
|
459
|
+
# @param options [Hash] Export options
|
|
460
|
+
# @param ds_id [Integer] Datastore ID to export child apps
|
|
461
|
+
def export_recursive(xpath, options)
|
|
462
|
+
# Get marketplace apps pool to find roles apps
|
|
463
|
+
pool = OpenNebula::MarketPlaceAppPool.new(@client)
|
|
464
|
+
rc = pool.info
|
|
465
|
+
|
|
466
|
+
return rc if OpenNebula.is_error?(rc)
|
|
467
|
+
|
|
468
|
+
# Apps that have been already exported
|
|
469
|
+
#
|
|
470
|
+
# app_name =>
|
|
471
|
+
# :vmtempalte = exported template ID
|
|
472
|
+
# :image = exported image ID
|
|
473
|
+
# :image_type = type (KERNEL, CONTEXT...) of image
|
|
474
|
+
# :names = [name_a, name_b, ...]
|
|
475
|
+
exported = {}
|
|
476
|
+
idx = 0
|
|
477
|
+
|
|
478
|
+
# Store IDs of created resources
|
|
479
|
+
images = []
|
|
480
|
+
templates = []
|
|
481
|
+
|
|
482
|
+
# Iterate over all childs
|
|
483
|
+
rc = retrieve_xmlelements(xpath).each do |obj|
|
|
484
|
+
# Get name and app information
|
|
485
|
+
obj_name = obj['NAME']
|
|
486
|
+
app = obj['APP']
|
|
487
|
+
|
|
488
|
+
# If the app was already exported, do not export it again
|
|
489
|
+
if exported[app]
|
|
490
|
+
exported[app][:names] << obj_name
|
|
491
|
+
next
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
# Find app in pool
|
|
495
|
+
obj = pool.find {|p| p['NAME'] == app }
|
|
496
|
+
|
|
497
|
+
break Error.new("App `#{app}` not found") unless obj
|
|
498
|
+
|
|
499
|
+
obj.extend(MarketPlaceAppExt)
|
|
500
|
+
|
|
501
|
+
rc = obj.export(
|
|
502
|
+
:dsid => options[:dsid],
|
|
503
|
+
:name => "#{options[:name]}-#{idx}",
|
|
504
|
+
:notemplate => options[:notemplate]
|
|
505
|
+
)
|
|
506
|
+
|
|
507
|
+
image = rc[:image].first if rc[:image]
|
|
508
|
+
vmtemplate = rc[:vmtemplate].first if rc[:vmtemplate]
|
|
509
|
+
|
|
510
|
+
break image if OpenNebula.is_error?(image)
|
|
511
|
+
break vmtemplate if OpenNebula.is_error?(vmtemplate)
|
|
512
|
+
|
|
513
|
+
idx += 1
|
|
514
|
+
|
|
515
|
+
# Update exported hash with information
|
|
516
|
+
exported[app] = rc
|
|
517
|
+
exported[app][:names] = [obj_name]
|
|
518
|
+
|
|
519
|
+
# Add IDs to return object
|
|
520
|
+
images << image
|
|
521
|
+
templates << vmtemplate
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
if block_given? && !OpenNebula.is_error?(rc)
|
|
525
|
+
rc = yield(exported)
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
if OpenNebula.is_error?(rc)
|
|
529
|
+
rc_rbck = rollback_export(exported, xpath != '//DISK')
|
|
530
|
+
|
|
531
|
+
return rc_rbck if OpenNebula.is_error?(rc_rbck)
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
[rc, images, templates]
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
# Delete templates/images in case something went wrong
|
|
538
|
+
#
|
|
539
|
+
# @param exported [Hash] Exported apps information
|
|
540
|
+
# @param template [Boolean] True to delete VM Template
|
|
541
|
+
# False to delete images
|
|
542
|
+
#
|
|
543
|
+
# @return [nil | OpenNebula::Error]
|
|
544
|
+
def rollback_export(exported, is_template)
|
|
545
|
+
ret = ''
|
|
546
|
+
|
|
547
|
+
if is_template
|
|
548
|
+
obj_factory = lambda {|v|
|
|
549
|
+
id = v[:vmtemplate].first
|
|
550
|
+
[Template.new_with_id(id, @client),
|
|
551
|
+
"Error deleting template #{id}"]
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
delete_method = 'delete(true)'
|
|
555
|
+
else
|
|
556
|
+
obj_factory = lambda {|v|
|
|
557
|
+
id = v[:image].first
|
|
558
|
+
[Image.new_with_id(id, @client),
|
|
559
|
+
"Error deleting image #{id}"]
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
delete_method = 'delete'
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
exported.each do |_, v|
|
|
566
|
+
obj, err_msg = obj_factory.call(v)
|
|
567
|
+
|
|
568
|
+
next unless OpenNebula.is_error?(obj.send(delete_method))
|
|
569
|
+
|
|
570
|
+
ret << err_msg
|
|
571
|
+
end
|
|
572
|
+
|
|
573
|
+
if ret.empty?
|
|
574
|
+
nil
|
|
575
|
+
else
|
|
576
|
+
Error.new(ret) unless ret.empty?
|
|
577
|
+
end
|
|
578
|
+
end
|
|
579
|
+
|
|
580
|
+
end
|
|
581
|
+
|
|
582
|
+
super
|
|
583
|
+
end
|
|
584
|
+
|
|
585
|
+
end
|
|
586
|
+
# rubocop:enable Style/ClassAndModuleChildren
|