opennebula 5.12.10 → 5.13.80.pre

Sign up to get free protection for your applications and to get access to all the features.
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 +1258 -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/role.rb +1126 -0
  17. data/lib/models/service.rb +709 -0
  18. data/lib/models.rb +32 -0
  19. data/lib/network.rb +635 -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/acl.rb +1 -1
  38. data/lib/opennebula/acl_pool.rb +1 -1
  39. data/lib/opennebula/client.rb +1 -1
  40. data/lib/opennebula/cluster.rb +1 -1
  41. data/lib/opennebula/cluster_pool.rb +1 -1
  42. data/lib/opennebula/datastore.rb +1 -1
  43. data/lib/opennebula/datastore_pool.rb +1 -1
  44. data/lib/opennebula/document.rb +8 -29
  45. data/lib/opennebula/document_json.rb +42 -12
  46. data/lib/opennebula/document_pool.rb +1 -1
  47. data/lib/opennebula/document_pool_json.rb +1 -1
  48. data/lib/opennebula/error.rb +4 -1
  49. data/lib/opennebula/flow/grammar.rb +1195 -0
  50. data/lib/opennebula/flow/service_pool.rb +190 -0
  51. data/lib/opennebula/flow/service_template.rb +572 -0
  52. data/lib/opennebula/flow/service_template_ext.rb +84 -0
  53. data/lib/opennebula/flow/service_template_pool.rb +32 -0
  54. data/lib/opennebula/flow/validator.rb +499 -0
  55. data/lib/opennebula/flow.rb +23 -0
  56. data/lib/opennebula/group.rb +1 -1
  57. data/lib/opennebula/group_pool.rb +1 -1
  58. data/lib/opennebula/hook.rb +5 -12
  59. data/lib/opennebula/hook_log.rb +1 -1
  60. data/lib/opennebula/hook_pool.rb +1 -1
  61. data/lib/opennebula/host.rb +1 -1
  62. data/lib/opennebula/host_pool.rb +1 -1
  63. data/lib/opennebula/image.rb +17 -14
  64. data/lib/opennebula/image_pool.rb +1 -1
  65. data/lib/opennebula/ldap_auth.rb +1 -1
  66. data/lib/opennebula/ldap_auth_spec.rb +1 -1
  67. data/lib/opennebula/lockable_ext.rb +163 -0
  68. data/lib/opennebula/marketplace.rb +1 -1
  69. data/lib/opennebula/marketplace_pool.rb +1 -1
  70. data/lib/opennebula/marketplaceapp.rb +9 -119
  71. data/lib/opennebula/marketplaceapp_ext.rb +522 -0
  72. data/lib/opennebula/marketplaceapp_pool.rb +1 -1
  73. data/lib/opennebula/oneflow_client.rb +4 -3
  74. data/lib/opennebula/pool.rb +4 -3
  75. data/lib/opennebula/pool_element.rb +1 -1
  76. data/lib/opennebula/security_group.rb +1 -1
  77. data/lib/opennebula/security_group_pool.rb +1 -1
  78. data/lib/opennebula/server_cipher_auth.rb +1 -1
  79. data/lib/opennebula/server_x509_auth.rb +1 -1
  80. data/lib/opennebula/ssh_auth.rb +1 -1
  81. data/lib/opennebula/system.rb +1 -1
  82. data/lib/opennebula/template.rb +4 -13
  83. data/lib/opennebula/template_ext.rb +325 -0
  84. data/lib/opennebula/template_pool.rb +1 -1
  85. data/lib/opennebula/user.rb +26 -2
  86. data/lib/opennebula/user_pool.rb +1 -1
  87. data/lib/opennebula/utils.rb +1 -1
  88. data/lib/opennebula/vdc.rb +1 -1
  89. data/lib/opennebula/vdc_pool.rb +1 -1
  90. data/lib/opennebula/virtual_machine.rb +25 -207
  91. data/lib/opennebula/virtual_machine_ext.rb +469 -0
  92. data/lib/opennebula/virtual_machine_pool.rb +1 -1
  93. data/lib/opennebula/virtual_network.rb +4 -10
  94. data/lib/opennebula/virtual_network_pool.rb +1 -1
  95. data/lib/opennebula/virtual_router.rb +4 -12
  96. data/lib/opennebula/virtual_router_pool.rb +1 -1
  97. data/lib/opennebula/vm_group.rb +4 -11
  98. data/lib/opennebula/vm_group_pool.rb +1 -1
  99. data/lib/opennebula/vntemplate.rb +4 -13
  100. data/lib/opennebula/vntemplate_pool.rb +1 -1
  101. data/lib/opennebula/wait_ext.rb +222 -0
  102. data/lib/opennebula/x509_auth.rb +1 -1
  103. data/lib/opennebula/xml_element.rb +1 -1
  104. data/lib/opennebula/xml_pool.rb +1 -1
  105. data/lib/opennebula/xml_utils.rb +1 -1
  106. data/lib/opennebula/zone.rb +1 -1
  107. data/lib/opennebula/zone_pool.rb +1 -1
  108. data/lib/opennebula.rb +5 -2
  109. data/lib/rest_client.rb +201 -0
  110. data/lib/scripts_common.rb +180 -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 +312 -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 +1961 -0
  125. data/lib/vmm_importer.rb +121 -0
  126. metadata +142 -29
@@ -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