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,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
|