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.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/lib/ActionManager.rb +1 -1
  3. data/lib/CommandManager.rb +1 -1
  4. data/lib/DriverExecHelper.rb +44 -28
  5. data/lib/OpenNebulaDriver.rb +8 -4
  6. data/lib/VirtualMachineDriver.rb +9 -2
  7. data/lib/cloud/CloudClient.rb +3 -3
  8. data/lib/datacenter.rb +1257 -0
  9. data/lib/datastore.rb +1025 -0
  10. data/lib/distributed_firewall.rb +280 -0
  11. data/lib/file_helper.rb +370 -0
  12. data/lib/host.rb +1517 -0
  13. data/lib/logical_port.rb +50 -0
  14. data/lib/logical_switch.rb +77 -0
  15. data/lib/memoize.rb +74 -0
  16. data/lib/models.rb +32 -0
  17. data/lib/models/role.rb +1126 -0
  18. data/lib/models/service.rb +709 -0
  19. data/lib/network.rb +699 -0
  20. data/lib/nsx_client.rb +144 -0
  21. data/lib/nsx_component.rb +28 -0
  22. data/lib/nsx_constants.rb +149 -0
  23. data/lib/nsx_driver.rb +78 -0
  24. data/lib/nsx_error.rb +77 -0
  25. data/lib/nsx_rule.rb +193 -0
  26. data/lib/nsxt_client.rb +176 -0
  27. data/lib/nsxt_dfw.rb +196 -0
  28. data/lib/nsxt_logical_port.rb +94 -0
  29. data/lib/nsxt_rule.rb +188 -0
  30. data/lib/nsxt_tz.rb +38 -0
  31. data/lib/nsxv_client.rb +176 -0
  32. data/lib/nsxv_dfw.rb +202 -0
  33. data/lib/nsxv_logical_port.rb +107 -0
  34. data/lib/nsxv_rule.rb +172 -0
  35. data/lib/nsxv_tz.rb +41 -0
  36. data/lib/opaque_network.rb +134 -0
  37. data/lib/opennebula.rb +5 -2
  38. data/lib/opennebula/acl.rb +1 -1
  39. data/lib/opennebula/acl_pool.rb +1 -1
  40. data/lib/opennebula/client.rb +10 -2
  41. data/lib/opennebula/cluster.rb +1 -1
  42. data/lib/opennebula/cluster_pool.rb +1 -1
  43. data/lib/opennebula/datastore.rb +1 -1
  44. data/lib/opennebula/datastore_pool.rb +1 -1
  45. data/lib/opennebula/document.rb +8 -29
  46. data/lib/opennebula/document_json.rb +42 -12
  47. data/lib/opennebula/document_pool.rb +1 -1
  48. data/lib/opennebula/document_pool_json.rb +1 -1
  49. data/lib/opennebula/error.rb +4 -1
  50. data/lib/opennebula/flow.rb +23 -0
  51. data/lib/opennebula/flow/grammar.rb +1195 -0
  52. data/lib/opennebula/flow/service_pool.rb +190 -0
  53. data/lib/opennebula/flow/service_template.rb +608 -0
  54. data/lib/opennebula/flow/service_template_ext.rb +84 -0
  55. data/lib/opennebula/flow/service_template_pool.rb +32 -0
  56. data/lib/opennebula/flow/validator.rb +499 -0
  57. data/lib/opennebula/group.rb +1 -1
  58. data/lib/opennebula/group_pool.rb +1 -1
  59. data/lib/opennebula/hook.rb +5 -12
  60. data/lib/opennebula/hook_log.rb +1 -1
  61. data/lib/opennebula/hook_pool.rb +1 -1
  62. data/lib/opennebula/host.rb +1 -1
  63. data/lib/opennebula/host_pool.rb +1 -1
  64. data/lib/opennebula/image.rb +19 -14
  65. data/lib/opennebula/image_pool.rb +1 -1
  66. data/lib/opennebula/ldap_auth.rb +1 -1
  67. data/lib/opennebula/ldap_auth_spec.rb +1 -1
  68. data/lib/opennebula/lockable_ext.rb +163 -0
  69. data/lib/opennebula/marketplace.rb +1 -1
  70. data/lib/opennebula/marketplace_pool.rb +1 -1
  71. data/lib/opennebula/marketplaceapp.rb +9 -119
  72. data/lib/opennebula/marketplaceapp_ext.rb +586 -0
  73. data/lib/opennebula/marketplaceapp_pool.rb +1 -1
  74. data/lib/opennebula/oneflow_client.rb +4 -3
  75. data/lib/opennebula/pool.rb +6 -3
  76. data/lib/opennebula/pool_element.rb +1 -1
  77. data/lib/opennebula/security_group.rb +1 -1
  78. data/lib/opennebula/security_group_pool.rb +1 -1
  79. data/lib/opennebula/server_cipher_auth.rb +1 -1
  80. data/lib/opennebula/server_x509_auth.rb +1 -1
  81. data/lib/opennebula/ssh_auth.rb +1 -1
  82. data/lib/opennebula/system.rb +1 -1
  83. data/lib/opennebula/template.rb +4 -13
  84. data/lib/opennebula/template_ext.rb +342 -0
  85. data/lib/opennebula/template_pool.rb +1 -1
  86. data/lib/opennebula/user.rb +26 -2
  87. data/lib/opennebula/user_pool.rb +1 -1
  88. data/lib/opennebula/utils.rb +1 -1
  89. data/lib/opennebula/vdc.rb +1 -1
  90. data/lib/opennebula/vdc_pool.rb +1 -1
  91. data/lib/opennebula/virtual_machine.rb +26 -206
  92. data/lib/opennebula/virtual_machine_ext.rb +469 -0
  93. data/lib/opennebula/virtual_machine_pool.rb +1 -1
  94. data/lib/opennebula/virtual_network.rb +4 -10
  95. data/lib/opennebula/virtual_network_pool.rb +1 -1
  96. data/lib/opennebula/virtual_router.rb +4 -12
  97. data/lib/opennebula/virtual_router_pool.rb +1 -1
  98. data/lib/opennebula/vm_group.rb +4 -11
  99. data/lib/opennebula/vm_group_pool.rb +1 -1
  100. data/lib/opennebula/vntemplate.rb +4 -13
  101. data/lib/opennebula/vntemplate_pool.rb +1 -1
  102. data/lib/opennebula/wait_ext.rb +257 -0
  103. data/lib/opennebula/x509_auth.rb +1 -1
  104. data/lib/opennebula/xml_element.rb +1 -1
  105. data/lib/opennebula/xml_pool.rb +1 -1
  106. data/lib/opennebula/xml_utils.rb +1 -1
  107. data/lib/opennebula/zone.rb +1 -1
  108. data/lib/opennebula/zone_pool.rb +1 -1
  109. data/lib/rest_client.rb +201 -0
  110. data/lib/scripts_common.rb +183 -0
  111. data/lib/transport_zone.rb +43 -0
  112. data/lib/vcenter_driver.rb +13 -12
  113. data/lib/vcenter_importer.rb +616 -0
  114. data/lib/vi_client.rb +281 -0
  115. data/lib/vi_helper.rb +313 -0
  116. data/lib/virtual_machine.rb +3477 -0
  117. data/lib/virtual_wire.rb +158 -0
  118. data/lib/vm_device.rb +80 -0
  119. data/lib/vm_disk.rb +202 -0
  120. data/lib/vm_folder.rb +69 -0
  121. data/lib/vm_helper.rb +30 -0
  122. data/lib/vm_monitor.rb +303 -0
  123. data/lib/vm_nic.rb +70 -0
  124. data/lib/vm_template.rb +1963 -0
  125. data/lib/vmm_importer.rb +121 -0
  126. metadata +140 -27
@@ -0,0 +1,709 @@
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 OpenNebula
18
+
19
+ # Service class as wrapper of DocumentJSON
20
+ class Service < DocumentJSON
21
+
22
+ attr_reader :roles, :client
23
+
24
+ DOCUMENT_TYPE = 100
25
+
26
+ STATE = {
27
+ 'PENDING' => 0,
28
+ 'DEPLOYING' => 1,
29
+ 'RUNNING' => 2,
30
+ 'UNDEPLOYING' => 3,
31
+ 'WARNING' => 4,
32
+ 'DONE' => 5,
33
+ 'FAILED_UNDEPLOYING' => 6,
34
+ 'FAILED_DEPLOYING' => 7,
35
+ 'SCALING' => 8,
36
+ 'FAILED_SCALING' => 9,
37
+ 'COOLDOWN' => 10
38
+ }
39
+
40
+ STATE_STR = %w[
41
+ PENDING
42
+ DEPLOYING
43
+ RUNNING
44
+ UNDEPLOYING
45
+ WARNING
46
+ DONE
47
+ FAILED_UNDEPLOYING
48
+ FAILED_DEPLOYING
49
+ SCALING
50
+ FAILED_SCALING
51
+ COOLDOWN
52
+ ]
53
+
54
+ TRANSIENT_STATES = %w[
55
+ DEPLOYING
56
+ UNDEPLOYING
57
+ SCALING
58
+ COOLDOWN
59
+ ]
60
+
61
+ FAILED_STATES = %w[
62
+ FAILED_DEPLOYING
63
+ FAILED_UNDEPLOYING
64
+ FAILED_SCALING
65
+ ]
66
+
67
+ RECOVER_DEPLOY_STATES = %w[
68
+ FAILED_DEPLOYING
69
+ DEPLOYING
70
+ PENDING
71
+ ]
72
+
73
+ RECOVER_UNDEPLOY_STATES = %w[
74
+ FAILED_UNDEPLOYING
75
+ UNDEPLOYING
76
+ ]
77
+
78
+ RECOVER_SCALE_STATES = %w[
79
+ FAILED_SCALING
80
+ SCALING
81
+ ]
82
+
83
+ # List of attributes that can't be changed in update operation
84
+ #
85
+ # custom_attrs: it only has sense when deploying, not in running
86
+ # custom_attrs_values: it only has sense when deploying, not in running
87
+ # deployment: changing this, changes the undeploy operation
88
+ # log: this is just internal information, no sense to change it
89
+ # name: this has to be changed using rename operation
90
+ # networks: it only has sense when deploying, not in running
91
+ # networks_values: it only has sense when deploying, not in running
92
+ # ready_status_gate: it only has sense when deploying, not in running
93
+ # state: this is internal information managed by OneFlow server
94
+ # start_time: this is internal information managed by OneFlow server
95
+ IMMUTABLE_ATTRS = %w[
96
+ custom_attrs
97
+ custom_attrs_values
98
+ deployment
99
+ log
100
+ name
101
+ networks
102
+ networks_values
103
+ ready_status_gate
104
+ state
105
+ start_time
106
+ ]
107
+
108
+ LOG_COMP = 'SER'
109
+
110
+ # Returns the service state
111
+ # @return [Integer] the service state
112
+ def state
113
+ @body['state'].to_i
114
+ end
115
+
116
+ # Returns the service strategy
117
+ # @return [String] the service strategy
118
+ def strategy
119
+ @body['deployment']
120
+ end
121
+
122
+ # Returns the string representation of the service state
123
+ # @return the state string
124
+ def state_str
125
+ STATE_STR[state]
126
+ end
127
+
128
+ # Returns true if the service is in transient state
129
+ # @return true if the service is in transient state, false otherwise
130
+ def transient_state?
131
+ TRANSIENT_STATES.include? STATE_STR[state]
132
+ end
133
+
134
+ # Return true if the service is in failed state
135
+ # @return true if the service is in failed state, false otherwise
136
+ def failed_state?
137
+ FAILED_STATES.include? STATE_STR[state]
138
+ end
139
+
140
+ # Return true if the service can be undeployed
141
+ # @return true if the service can be undeployed, false otherwise
142
+ def can_undeploy?
143
+ if (transient_state? && state != Service::STATE['UNDEPLOYING']) ||
144
+ state == Service::STATE['DONE'] || failed_state?
145
+ false
146
+ else
147
+ true
148
+ end
149
+ end
150
+
151
+ # Return true if the service can be updated
152
+ # @return true if the service can be updated, false otherwise
153
+ def can_update?
154
+ !transient_state? && !failed_state?
155
+ end
156
+
157
+ def can_recover_deploy?
158
+ RECOVER_DEPLOY_STATES.include? STATE_STR[state]
159
+ end
160
+
161
+ def can_recover_undeploy?
162
+ RECOVER_UNDEPLOY_STATES.include? STATE_STR[state]
163
+ end
164
+
165
+ def can_recover_scale?
166
+ RECOVER_SCALE_STATES.include? STATE_STR[state]
167
+ end
168
+
169
+ # Returns the running_status_vm option
170
+ # @return [true, false] true if the running_status_vm option is enabled
171
+ def report_ready?
172
+ @body['ready_status_gate']
173
+ end
174
+
175
+ def uname
176
+ self['UNAME']
177
+ end
178
+
179
+ def gid
180
+ self['GID'].to_i
181
+ end
182
+
183
+ # Replaces this object's client with a new one
184
+ # @param [OpenNebula::Client] owner_client the new client
185
+ def replace_client(owner_client)
186
+ @client = owner_client
187
+ end
188
+
189
+ # Sets a new state
190
+ # @param [Integer] the new state
191
+ # @return [true, false] true if the value was changed
192
+ # rubocop:disable Naming/AccessorMethodName
193
+ def set_state(state)
194
+ # rubocop:enable Naming/AccessorMethodName
195
+ if state < 0 || state > STATE_STR.size
196
+ return false
197
+ end
198
+
199
+ @body['state'] = state.to_i
200
+
201
+ msg = "New state: #{STATE_STR[state]}"
202
+ Log.info LOG_COMP, msg, id
203
+ log_info(msg)
204
+
205
+ true
206
+ end
207
+
208
+ # Returns true if all the nodes are correctly deployed
209
+ # @return [true, false] true if all the nodes are correctly deployed
210
+ def all_roles_running?
211
+ @roles.each do |_name, role|
212
+ if role.state != Role::STATE['RUNNING']
213
+ return false
214
+ end
215
+ end
216
+
217
+ true
218
+ end
219
+
220
+ # Returns true if all the nodes are in done state
221
+ # @return [true, false] true if all the nodes are correctly deployed
222
+ def all_roles_done?
223
+ @roles.each do |_name, role|
224
+ if role.state != Role::STATE['DONE']
225
+ return false
226
+ end
227
+ end
228
+
229
+ true
230
+ end
231
+
232
+ # Create a new service based on the template provided
233
+ # @param [String] template_json
234
+ # @return [nil, OpenNebula::Error] nil in case of success, Error
235
+ # otherwise
236
+ def allocate(template_json)
237
+ template = JSON.parse(template_json)
238
+ template['state'] = STATE['PENDING']
239
+
240
+ if template['roles']
241
+ template['roles'].each do |elem|
242
+ elem['state'] ||= Role::STATE['PENDING']
243
+ end
244
+ end
245
+
246
+ template['start_time'] = Integer(Time.now)
247
+
248
+ super(template.to_json, template['name'])
249
+ end
250
+
251
+ # Recover a failed service.
252
+ # @return [nil, OpenNebula::Error] nil in case of success, Error
253
+ # otherwise
254
+ def recover
255
+ if [Service::STATE['FAILED_DEPLOYING']].include?(state)
256
+ @roles.each do |_name, role|
257
+ if role.state == Role::STATE['FAILED_DEPLOYING']
258
+ role.set_state(Role::STATE['PENDING'])
259
+ end
260
+ end
261
+
262
+ set_state(Service::STATE['DEPLOYING'])
263
+
264
+ elsif state == Service::STATE['FAILED_SCALING']
265
+ @roles.each do |_name, role|
266
+ if role.state == Role::STATE['FAILED_SCALING']
267
+ role.set_state(Role::STATE['SCALING'])
268
+ end
269
+ end
270
+
271
+ set_state(Service::STATE['SCALING'])
272
+
273
+ elsif state == Service::STATE['FAILED_UNDEPLOYING']
274
+ @roles.each do |_name, role|
275
+ if role.state == Role::STATE['FAILED_UNDEPLOYING']
276
+ role.set_state(Role::STATE['RUNNING'])
277
+ end
278
+ end
279
+
280
+ set_state(Service::STATE['UNDEPLOYING'])
281
+
282
+ elsif state == Service::STATE['COOLDOWN']
283
+ @roles.each do |_name, role|
284
+ if role.state == Role::STATE['COOLDOWN']
285
+ role.set_state(Role::STATE['RUNNING'])
286
+ end
287
+ end
288
+
289
+ set_state(Service::STATE['RUNNING'])
290
+
291
+ elsif state == Service::STATE['WARNING']
292
+ @roles.each do |_name, role|
293
+ if role.state == Role::STATE['WARNING']
294
+ role.recover_warning
295
+ end
296
+ end
297
+ else
298
+ OpenNebula::Error.new('Action recover: Wrong state' \
299
+ " #{state_str}")
300
+ end
301
+ end
302
+
303
+ # Retrieves the information of the Service and all its Nodes.
304
+ #
305
+ # @return [nil, OpenNebula::Error] nil in case of success, Error
306
+ # otherwise
307
+ def info
308
+ rc = super
309
+ if OpenNebula.is_error?(rc)
310
+ return rc
311
+ end
312
+
313
+ @roles = {}
314
+
315
+ if @body['roles']
316
+ @body['roles'].each do |elem|
317
+ elem['state'] ||= Role::STATE['PENDING']
318
+ role = Role.new(elem, self)
319
+ @roles[role.name] = role
320
+ end
321
+ end
322
+
323
+ nil
324
+ end
325
+
326
+ # Retrieves the information of the Service and all its Nodes.
327
+ #
328
+ # @return [nil, OpenNebula::Error] nil in case of success, Error
329
+ # otherwise
330
+ def info_roles
331
+ @roles = {}
332
+
333
+ if @body['roles']
334
+ @body['roles'].each do |elem|
335
+ elem['state'] ||= Role::STATE['PENDING']
336
+ role = Role.new(elem, self)
337
+ @roles[role.name] = role
338
+ end
339
+ end
340
+
341
+ nil
342
+ end
343
+
344
+ # Add an info message in the service information that will be stored
345
+ # in OpenNebula
346
+ # @param [String] message
347
+ def log_info(message)
348
+ add_log(Logger::INFO, message)
349
+ end
350
+
351
+ # Add an error message in the service information that will be stored
352
+ # in OpenNebula
353
+ # @param [String] message
354
+ def log_error(message)
355
+ add_log(Logger::ERROR, message)
356
+ end
357
+
358
+ # Changes the owner/group
359
+ #
360
+ # @param [Integer] uid the new owner id. Use -1 to leave the current one
361
+ # @param [Integer] gid the new group id. Use -1 to leave the current one
362
+ #
363
+ # @return [nil, OpenNebula::Error] nil in case of success, Error
364
+ # otherwise
365
+ def chown(uid, gid)
366
+ old_uid = self['UID'].to_i
367
+ old_gid = self['GID'].to_i
368
+
369
+ rc = super(uid, gid)
370
+
371
+ if OpenNebula.is_error?(rc)
372
+ return rc
373
+ end
374
+
375
+ @roles.each do |_name, role|
376
+ rc = role.chown(uid, gid)
377
+
378
+ break if rc[0] == false
379
+ end
380
+
381
+ if rc[0] == false
382
+ log_error('Chown operation failed, will try to rollback ' \
383
+ 'all VMs to the old user and group')
384
+
385
+ update
386
+
387
+ super(old_uid, old_gid)
388
+
389
+ @roles.each do |_name, role|
390
+ role.chown(old_uid, old_gid)
391
+ end
392
+
393
+ return OpenNebula::Error.new(rc[1])
394
+ end
395
+
396
+ nil
397
+ end
398
+
399
+ # Updates a role
400
+ # @param [String] role_name
401
+ # @param [String] template_json
402
+ # @return [nil, OpenNebula::Error] nil in case of success, Error
403
+ # otherwise
404
+ def update_role(role_name, template_json)
405
+ if ![Service::STATE['RUNNING'], Service::STATE['WARNING']]
406
+ .include?(state)
407
+
408
+ return OpenNebula::Error.new('Update role: Wrong state' \
409
+ " #{state_str}")
410
+ end
411
+
412
+ template = JSON.parse(template_json)
413
+
414
+ # TODO: Validate template?
415
+
416
+ role = @roles[role_name]
417
+
418
+ if role.nil?
419
+ return OpenNebula::Error.new("ROLE \"#{role_name}\" " \
420
+ 'does not exist')
421
+ end
422
+
423
+ rc = role.update(template)
424
+
425
+ if OpenNebula.is_error?(rc)
426
+ return rc
427
+ end
428
+
429
+ # TODO: The update may not change the cardinality, only
430
+ # the max and min vms...
431
+
432
+ role.set_state(Role::STATE['SCALING'])
433
+
434
+ role.set_default_cooldown_duration
435
+
436
+ set_state(Service::STATE['SCALING'])
437
+
438
+ update
439
+ end
440
+
441
+ def shutdown_action
442
+ @body['shutdown_action']
443
+ end
444
+
445
+ # Replaces the template contents
446
+ #
447
+ # @param template_json [String] New template contents
448
+ # @param append [true, false] True to append new attributes instead of
449
+ # replace the whole template
450
+ #
451
+ # @return [nil, OpenNebula::Error] nil in case of success, Error
452
+ # otherwise
453
+ def update(template_json = nil, append = false)
454
+ if template_json
455
+ template = JSON.parse(template_json)
456
+
457
+ if append
458
+ rc = info
459
+
460
+ if OpenNebula.is_error? rc
461
+ return rc
462
+ end
463
+
464
+ template = @body.merge(template)
465
+ end
466
+
467
+ template_json = template.to_json
468
+ end
469
+
470
+ super(template_json, append)
471
+ end
472
+
473
+ # Replaces the raw template contents
474
+ #
475
+ # @param template [String] New template contents, in the form KEY = VAL
476
+ # @param append [true, false] True to append new attributes instead of
477
+ # replace the whole template
478
+ #
479
+ # @return [nil, OpenNebula::Error] nil in case of success, Error
480
+ # otherwise
481
+ def update_raw(template_raw, append = false)
482
+ super(template_raw, append)
483
+ end
484
+
485
+ # Check that changes values are correct
486
+ #
487
+ # @param template_json [String] New template
488
+ #
489
+ # @return [Boolean, String] True, nil if everything is correct
490
+ # False, attr if attr was changed
491
+ def check_new_template(template_json)
492
+ template = JSON.parse(template_json)
493
+
494
+ if template['roles'].size != @roles.size
495
+ return [false, 'service/roles size']
496
+ end
497
+
498
+ IMMUTABLE_ATTRS.each do |attr|
499
+ next if template[attr] == @body[attr]
500
+
501
+ return [false, "service/#{attr}"]
502
+ end
503
+
504
+ template['roles'].each do |role|
505
+ # Role name can't be changed, if it is changed some problems
506
+ # may appear, as name is used to reference roles
507
+ return [false, 'name'] unless @roles[role['name']]
508
+
509
+ rc = @roles[role['name']].check_new_template(role)
510
+
511
+ return rc unless rc[0]
512
+ end
513
+
514
+ [true, nil]
515
+ end
516
+
517
+ def deploy_networks
518
+ body = JSON.parse(self['TEMPLATE/BODY'])
519
+
520
+ return if body['networks_values'].nil?
521
+
522
+ body['networks_values'].each do |net|
523
+ rc = create_vnet(net) if net[net.keys[0]].key?('template_id')
524
+
525
+ if OpenNebula.is_error?(rc)
526
+ return rc
527
+ end
528
+
529
+ rc = reserve(net) if net[net.keys[0]].key?('reserve_from')
530
+
531
+ if OpenNebula.is_error?(rc)
532
+ return rc
533
+ end
534
+ end
535
+
536
+ # Replace $attibute by the corresponding value
537
+ resolve_attributes(body)
538
+
539
+ # @body = template.to_hash
540
+
541
+ update_body(body)
542
+ end
543
+
544
+ def delete_networks
545
+ vnets = @body['networks_values']
546
+ vnets_failed = []
547
+
548
+ return if vnets.nil?
549
+
550
+ vnets.each do |vnet|
551
+ next unless vnet[vnet.keys[0]].key?('template_id') ||
552
+ vnet[vnet.keys[0]].key?('reserve_from')
553
+
554
+ vnet_id = vnet[vnet.keys[0]]['id'].to_i
555
+
556
+ rc = OpenNebula::VirtualNetwork
557
+ .new_with_id(vnet_id, @client).delete
558
+
559
+ if OpenNebula.is_error?(rc)
560
+ vnets_failed << vnet_id
561
+ end
562
+ end
563
+
564
+ vnets_failed
565
+ end
566
+
567
+ def can_scale?
568
+ state == Service::STATE['RUNNING']
569
+ end
570
+
571
+ # Check if role is terminated or not
572
+ #
573
+ # @param role [OpenNebula::Role] Role information
574
+ #
575
+ # @return [Boolean]
576
+ # True if the service should be undeployed
577
+ # False otherwise
578
+ def check_role(role)
579
+ return unless @body['automatic_deletion']
580
+
581
+ return unless role.nodes.empty?
582
+
583
+ ret = true
584
+
585
+ @body['roles'].each {|r| ret &= r['nodes'].empty? }
586
+
587
+ ret
588
+ end
589
+
590
+ private
591
+
592
+ # Maximum number of log entries per service
593
+ # TODO: Make this value configurable
594
+ MAX_LOG = 50
595
+
596
+ def update_body(body)
597
+ @body = body
598
+
599
+ # Update @roles attribute with the new @body content
600
+ @roles = {}
601
+ if @body['roles']
602
+ @body['roles'].each do |elem|
603
+ elem['state'] ||= Role::STATE['PENDING']
604
+ role = Role.new(elem, self)
605
+ @roles[role.name] = role
606
+ end
607
+ end
608
+
609
+ # Update @xml attribute with the new body content
610
+ @xml.at_xpath('/DOCUMENT/TEMPLATE/BODY').children[0].content = @body
611
+ end
612
+
613
+ # @param [Logger::Severity] severity
614
+ # @param [String] message
615
+ def add_log(severity, message)
616
+ severity_str = Logger::SEV_LABEL[severity][0..0]
617
+
618
+ @body['log'] ||= []
619
+ @body['log'] << {
620
+ :timestamp => Time.now.to_i,
621
+ :severity => severity_str,
622
+ :message => message
623
+ }
624
+
625
+ # Truncate the number of log entries
626
+ @body['log'] = @body['log'].last(MAX_LOG)
627
+ end
628
+
629
+ def create_vnet(net)
630
+ extra = ''
631
+
632
+ extra = net[net.keys[0]]['extra'] if net[net.keys[0]].key? 'extra'
633
+
634
+ vntmpl_id = OpenNebula::VNTemplate
635
+ .new_with_id(net[net.keys[0]]['template_id']
636
+ .to_i, @client).instantiate(get_vnet_name(net), extra)
637
+
638
+ # TODO, check which error should be returned
639
+ return vntmpl_id if OpenNebula.is_error?(vntmpl_id)
640
+
641
+ net[net.keys[0]]['id'] = vntmpl_id
642
+
643
+ true
644
+ end
645
+
646
+ def reserve(net)
647
+ get_vnet_name(net)
648
+ extra = net[net.keys[0]]['extra'] if net[net.keys[0]].key? 'extra'
649
+
650
+ return false if !extra || extra.empty?
651
+
652
+ extra.concat("\nNAME=\"#{get_vnet_name(net)}\"\n")
653
+
654
+ reserve_id = OpenNebula::VirtualNetwork
655
+ .new_with_id(net[net.keys[0]]['reserve_from']
656
+ .to_i, @client).reserve_with_extra(extra)
657
+
658
+ return reserve_id if OpenNebula.is_error?(reserve_id)
659
+
660
+ net[net.keys[0]]['id'] = reserve_id
661
+
662
+ true
663
+ end
664
+
665
+ def get_vnet_name(net)
666
+ "#{net.keys[0]}-#{id}"
667
+ end
668
+
669
+ def resolve_attributes(template)
670
+ template['roles'].each do |role|
671
+ if role['vm_template_contents']
672
+ # $CUSTOM1_VAR Any word character
673
+ # (letter, number, underscore)
674
+ role['vm_template_contents'].scan(/\$(\w+)/).each do |key|
675
+ # Check if $ var value is in custom_attrs_values
676
+ if !template['custom_attrs_values'].nil? &&
677
+ template['custom_attrs_values'].key?(key[0])
678
+ role['vm_template_contents'].gsub!(
679
+ '$'+key[0],
680
+ template['custom_attrs_values'][key[0]]
681
+ )
682
+ next
683
+ end
684
+
685
+ # Check if $ var value is in networks
686
+ net = template['networks_values']
687
+ .find {|att| att.key? key[0] }
688
+
689
+ next if net.nil?
690
+
691
+ role['vm_template_contents'].gsub!(
692
+ '$'+key[0],
693
+ net[net.keys[0]]['id'].to_s
694
+ )
695
+ end
696
+ end
697
+
698
+ next unless role['user_inputs_values']
699
+
700
+ role['vm_template_contents'] ||= ''
701
+ role['user_inputs_values'].each do |key, value|
702
+ role['vm_template_contents'] += "\n#{key}=\"#{value}\""
703
+ end
704
+ end
705
+ end
706
+
707
+ end
708
+
709
+ end