opennebula 6.4.1 → 6.5.80.pre
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/CommandManager.rb +9 -6
- data/lib/OpenNebulaDriver.rb +1 -1
- data/lib/VirtualMachineDriver.rb +27 -13
- data/lib/cloud/CloudClient.rb +1 -1
- data/lib/datastore.rb +13 -0
- data/lib/file_helper.rb +1 -1
- data/lib/models/role.rb +46 -0
- data/lib/opennebula/datastore.rb +3 -2
- data/lib/opennebula/flow/service_pool.rb +13 -6
- data/lib/opennebula/flow/service_template.rb +1 -2
- data/lib/opennebula/image.rb +32 -22
- data/lib/opennebula/ldap_auth.rb +3 -1
- data/lib/opennebula/template_ext.rb +1 -3
- data/lib/opennebula/virtual_machine.rb +30 -2
- data/lib/opennebula/virtual_machine_ext.rb +0 -206
- data/lib/opennebula/virtual_network.rb +32 -3
- data/lib/opennebula/x509_auth.rb +13 -15
- data/lib/opennebula.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5cb427e39e8e2f581076e069b21c0da24b5e82dac56e29b0e7017c7e419b3a31
|
4
|
+
data.tar.gz: 59203c99872a0065565a336a0bc814f5f7f9acd15a79bcdf3e1df9c92f3b5209
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c20a43d2ade283e63fda2143c9fb8fc2d88f7191e81f75f17219d0d625c99f587f6aea2517dfde44d1dd65aea08c65fa349518045a58df2f912d3d7bc5afb197
|
7
|
+
data.tar.gz: 7e4f2365737cf9746b91834ff0af8cb01ff7dc198b5f143686d483f6c9aa927df6cbac4e4226682ce599c5afea85be716e2cb21dc2144986e288f8f2f33e5bbb
|
data/lib/CommandManager.rb
CHANGED
@@ -212,19 +212,22 @@ end
|
|
212
212
|
# Executes commands in a remote machine ussing ssh. See documentation
|
213
213
|
# for GenericCommand
|
214
214
|
class SSHCommand < GenericCommand
|
215
|
-
|
215
|
+
|
216
|
+
attr_accessor :host, :ssh_opts
|
216
217
|
|
217
218
|
# Creates a command and runs it
|
218
|
-
def self.run(command, host, logger=nil, stdin=nil, timeout=nil)
|
219
|
-
cmd=self.new(command, host, logger, stdin, timeout)
|
219
|
+
def self.run(command, host, logger=nil, stdin=nil, timeout=nil, ssh_opts='')
|
220
|
+
cmd=self.new(command, host, logger, stdin, timeout, ssh_opts)
|
220
221
|
cmd.run
|
221
222
|
cmd
|
222
223
|
end
|
223
224
|
|
224
225
|
# This one takes another parameter. +host+ is the machine
|
225
226
|
# where the command is going to be executed
|
226
|
-
def initialize(command, host, logger=nil, stdin=nil, timeout=nil)
|
227
|
+
def initialize(command, host, logger=nil, stdin=nil, timeout=nil, ssh_opts='')
|
227
228
|
@host=host
|
229
|
+
@ssh_opts = ssh_opts
|
230
|
+
|
228
231
|
super(command, logger, stdin, timeout)
|
229
232
|
end
|
230
233
|
|
@@ -232,10 +235,10 @@ private
|
|
232
235
|
|
233
236
|
def execute
|
234
237
|
if @stdin
|
235
|
-
capture3_timeout("ssh #{@host} #{@command}",
|
238
|
+
capture3_timeout("ssh #{@ssh_opts} #{@host} #{@command}",
|
236
239
|
:pgroup => true, :stdin_data => @stdin)
|
237
240
|
else
|
238
|
-
capture3_timeout("ssh -n #{@host} #{@command}",
|
241
|
+
capture3_timeout("ssh -n #{@ssh_opts} #{@host} #{@command}",
|
239
242
|
:pgroup => true)
|
240
243
|
end
|
241
244
|
end
|
data/lib/OpenNebulaDriver.rb
CHANGED
@@ -108,7 +108,7 @@ class OpenNebulaDriver < ActionManager
|
|
108
108
|
@timeout)
|
109
109
|
elsif options[:ssh_stream]
|
110
110
|
if options[:stdin]
|
111
|
-
cmdin = "cat << EOT | #{command}"
|
111
|
+
cmdin = "cat << 'EOT' | #{command}"
|
112
112
|
stdin = "#{options[:stdin]}\nEOT\n"
|
113
113
|
else
|
114
114
|
cmdin = command
|
data/lib/VirtualMachineDriver.rb
CHANGED
@@ -53,7 +53,9 @@ class VirtualMachineDriver < OpenNebulaDriver
|
|
53
53
|
:resize_disk => "RESIZEDISK",
|
54
54
|
:update_sg => "UPDATESG",
|
55
55
|
:update_conf => "UPDATECONF",
|
56
|
-
:resize => "RESIZE"
|
56
|
+
:resize => "RESIZE",
|
57
|
+
:backup => "BACKUP",
|
58
|
+
:update_nic => "UPDATENIC"
|
57
59
|
}
|
58
60
|
|
59
61
|
POLL_ATTRIBUTE = OpenNebula::VirtualMachine::Driver::POLL_ATTRIBUTE
|
@@ -76,23 +78,23 @@ class VirtualMachineDriver < OpenNebulaDriver
|
|
76
78
|
|
77
79
|
super(directory, @options)
|
78
80
|
|
79
|
-
@hosts
|
80
|
-
|
81
|
-
register_action(ACTION[:deploy].to_sym,
|
82
|
-
register_action(ACTION[:shutdown].to_sym,
|
83
|
-
register_action(ACTION[:reboot].to_sym,
|
84
|
-
register_action(ACTION[:reset].to_sym,
|
85
|
-
register_action(ACTION[:cancel].to_sym,
|
86
|
-
register_action(ACTION[:save].to_sym,
|
87
|
-
register_action(ACTION[:restore].to_sym,
|
88
|
-
register_action(ACTION[:migrate].to_sym,
|
89
|
-
register_action(ACTION[:poll].to_sym,
|
81
|
+
@hosts = Array.new
|
82
|
+
|
83
|
+
register_action(ACTION[:deploy].to_sym, method("deploy"))
|
84
|
+
register_action(ACTION[:shutdown].to_sym, method("shutdown"))
|
85
|
+
register_action(ACTION[:reboot].to_sym, method("reboot"))
|
86
|
+
register_action(ACTION[:reset].to_sym, method("reset"))
|
87
|
+
register_action(ACTION[:cancel].to_sym, method("cancel"))
|
88
|
+
register_action(ACTION[:save].to_sym, method("save"))
|
89
|
+
register_action(ACTION[:restore].to_sym, method("restore"))
|
90
|
+
register_action(ACTION[:migrate].to_sym, method("migrate"))
|
91
|
+
register_action(ACTION[:poll].to_sym, method("poll"))
|
90
92
|
register_action(ACTION[:attach_disk].to_sym, method("attach_disk"))
|
91
93
|
register_action(ACTION[:detach_disk].to_sym, method("detach_disk"))
|
92
94
|
register_action(ACTION[:snapshot_create].to_sym, method("snapshot_create"))
|
93
95
|
register_action(ACTION[:snapshot_revert].to_sym, method("snapshot_revert"))
|
94
96
|
register_action(ACTION[:snapshot_delete].to_sym, method("snapshot_delete"))
|
95
|
-
register_action(ACTION[:cleanup].to_sym,
|
97
|
+
register_action(ACTION[:cleanup].to_sym, method("cleanup"))
|
96
98
|
register_action(ACTION[:attach_nic].to_sym, method("attach_nic"))
|
97
99
|
register_action(ACTION[:detach_nic].to_sym, method("detach_nic"))
|
98
100
|
register_action(ACTION[:disk_snapshot_create].to_sym, method("disk_snapshot_create"))
|
@@ -100,6 +102,8 @@ class VirtualMachineDriver < OpenNebulaDriver
|
|
100
102
|
register_action(ACTION[:update_sg].to_sym, method("update_sg"))
|
101
103
|
register_action(ACTION[:update_conf].to_sym, method("update_conf"))
|
102
104
|
register_action(ACTION[:resize].to_sym, method("resize"))
|
105
|
+
register_action(ACTION[:backup].to_sym, method("backup"))
|
106
|
+
register_action(ACTION[:update_nic].to_sym, method("update_nic"))
|
103
107
|
end
|
104
108
|
|
105
109
|
# Decodes the encoded XML driver message received from the core
|
@@ -234,6 +238,16 @@ class VirtualMachineDriver < OpenNebulaDriver
|
|
234
238
|
send_message(ACTION[:resize],RESULT[:failure],id,error)
|
235
239
|
end
|
236
240
|
|
241
|
+
def backup(id, drv_message)
|
242
|
+
error = "Action not implemented by driver #{self.class}"
|
243
|
+
send_message(ACTION[:backup],RESULT[:failure],id,error)
|
244
|
+
end
|
245
|
+
|
246
|
+
def update_nic(id, drv_message)
|
247
|
+
error = "Action not implemented by driver #{self.class}"
|
248
|
+
send_message(ACTION[:update_nic],RESULT[:failure],id,error)
|
249
|
+
end
|
250
|
+
|
237
251
|
private
|
238
252
|
|
239
253
|
# Interface to handle the pending events from the ActionManager Interface
|
data/lib/cloud/CloudClient.rb
CHANGED
data/lib/datastore.rb
CHANGED
@@ -14,6 +14,19 @@
|
|
14
14
|
# limitations under the License. #
|
15
15
|
#--------------------------------------------------------------------------- #
|
16
16
|
|
17
|
+
# Ruby 3.x+ deprecated URI.escape, however rbvmomi still relies on it
|
18
|
+
|
19
|
+
if RUBY_VERSION.split('.')[0].to_i >= 3
|
20
|
+
# Monkey patch the escape functionality
|
21
|
+
module URI
|
22
|
+
|
23
|
+
def self.escape(url)
|
24
|
+
URI::Parser.new.escape url
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
17
30
|
##############################################################################
|
18
31
|
# Module VCenterDriver
|
19
32
|
##############################################################################
|
data/lib/file_helper.rb
CHANGED
data/lib/models/role.rb
CHANGED
@@ -455,6 +455,9 @@ module OpenNebula
|
|
455
455
|
extra_template << "\nSERVICE_ID = #{@service.id}"
|
456
456
|
extra_template << "\nROLE_NAME = \"#{@body['name']}\""
|
457
457
|
|
458
|
+
# Evaluate attributes with parent roles
|
459
|
+
evaluate(extra_template)
|
460
|
+
|
458
461
|
n_nodes.times do
|
459
462
|
vm_name = @@vm_name_template
|
460
463
|
.gsub('$SERVICE_ID', @service.id.to_s)
|
@@ -1168,6 +1171,49 @@ module OpenNebula
|
|
1168
1171
|
new_cardinality
|
1169
1172
|
end
|
1170
1173
|
|
1174
|
+
# Evaluate rules that references to parent roles
|
1175
|
+
#
|
1176
|
+
# @param template [String] Role template with $ to replace
|
1177
|
+
def evaluate(template)
|
1178
|
+
client = service.client
|
1179
|
+
|
1180
|
+
template.scan(/\$\{(.*?)\}/).flatten.each do |value|
|
1181
|
+
s_value = value.split('.') # 0 -> parent, 1..N -> XPATH
|
1182
|
+
|
1183
|
+
# If parent not found, instead of error, replace it by blank
|
1184
|
+
unless parents.include?(s_value[0])
|
1185
|
+
template.gsub!("${#{value}}", '')
|
1186
|
+
next
|
1187
|
+
end
|
1188
|
+
|
1189
|
+
found = false
|
1190
|
+
p_nodes = service.roles[s_value[0]].nodes
|
1191
|
+
xpath = "//#{s_value[1..-1].join('/').upcase}"
|
1192
|
+
|
1193
|
+
# Iterate over parent nodes to find the XPATH on their template
|
1194
|
+
p_nodes.each do |node|
|
1195
|
+
id = node['deploy_id']
|
1196
|
+
vm = OpenNebula::VirtualMachine.new_with_id(id, client)
|
1197
|
+
|
1198
|
+
# If error continue searching in other nodes
|
1199
|
+
next if OpenNebula.is_error?(vm.info)
|
1200
|
+
|
1201
|
+
next unless vm[xpath]
|
1202
|
+
|
1203
|
+
template.gsub!("${#{value}}", vm[xpath])
|
1204
|
+
|
1205
|
+
# If found, continue with next expression
|
1206
|
+
found = true
|
1207
|
+
break
|
1208
|
+
end
|
1209
|
+
|
1210
|
+
next if found
|
1211
|
+
|
1212
|
+
# If value not found, replace it by blank to avoid issues
|
1213
|
+
template.gsub!("${#{value}}", '')
|
1214
|
+
end
|
1215
|
+
end
|
1216
|
+
|
1171
1217
|
end
|
1172
1218
|
|
1173
1219
|
end
|
data/lib/opennebula/datastore.rb
CHANGED
@@ -34,12 +34,13 @@ module OpenNebula
|
|
34
34
|
:enable => "datastore.enable"
|
35
35
|
}
|
36
36
|
|
37
|
-
DATASTORE_TYPES=%w{IMAGE SYSTEM FILE}
|
37
|
+
DATASTORE_TYPES=%w{IMAGE SYSTEM FILE BACKUP}
|
38
38
|
|
39
39
|
SHORT_DATASTORE_TYPES = {
|
40
40
|
"IMAGE" => "img",
|
41
41
|
"SYSTEM"=> "sys",
|
42
|
-
"FILE" => "fil"
|
42
|
+
"FILE" => "fil",
|
43
|
+
"BACKUP"=> "bck"
|
43
44
|
}
|
44
45
|
|
45
46
|
DATASTORE_STATES=%w{READY DISABLED}
|
@@ -66,12 +66,16 @@ module OpenNebula
|
|
66
66
|
super('DOCUMENT_POOL', 'DOCUMENT', @client)
|
67
67
|
end
|
68
68
|
|
69
|
-
def client
|
69
|
+
def client(user_name = nil)
|
70
70
|
# If there's a client defined use it
|
71
71
|
return @client unless @client.nil?
|
72
72
|
|
73
73
|
# If not, get one via cloud_auth
|
74
|
-
|
74
|
+
if user_name.nil?
|
75
|
+
@cloud_auth.client
|
76
|
+
else
|
77
|
+
@cloud_auth.client(user_name)
|
78
|
+
end
|
75
79
|
end
|
76
80
|
|
77
81
|
def info
|
@@ -129,14 +133,17 @@ module OpenNebula
|
|
129
133
|
# The mutex will be unlocked after the block execution.
|
130
134
|
#
|
131
135
|
# @return [Service, OpenNebula::Error] The Service in case of success
|
132
|
-
def get(service_id,
|
136
|
+
def get(service_id, external_user = nil, &block)
|
133
137
|
service_id = service_id.to_i if service_id
|
134
138
|
aux_client = nil
|
135
139
|
|
136
|
-
|
140
|
+
# WARNING!!!
|
141
|
+
# No validation will be performed for external_user, the credentials
|
142
|
+
# for this user must be validated previously.
|
143
|
+
if external_user.nil?
|
137
144
|
aux_client = client
|
138
145
|
else
|
139
|
-
aux_client =
|
146
|
+
aux_client = client(external_user)
|
140
147
|
end
|
141
148
|
|
142
149
|
service = Service.new_with_id(service_id, aux_client)
|
@@ -172,7 +179,7 @@ module OpenNebula
|
|
172
179
|
return rc
|
173
180
|
end
|
174
181
|
|
175
|
-
block.call(service)
|
182
|
+
block.call(service, client)
|
176
183
|
end
|
177
184
|
|
178
185
|
@@mutex.synchronize do
|
@@ -549,8 +549,7 @@ module OpenNebula
|
|
549
549
|
end
|
550
550
|
|
551
551
|
if role['elasticity_policies']
|
552
|
-
role['elasticity_policies'].each_with_index do |policy,
|
553
|
-
index|
|
552
|
+
role['elasticity_policies'].each_with_index do |policy, index|
|
554
553
|
exp = policy['expression']
|
555
554
|
|
556
555
|
if exp.empty?
|
data/lib/opennebula/image.rb
CHANGED
@@ -26,20 +26,21 @@ module OpenNebula
|
|
26
26
|
#######################################################################
|
27
27
|
|
28
28
|
IMAGE_METHODS = {
|
29
|
-
:info
|
30
|
-
:allocate
|
31
|
-
:update
|
32
|
-
:enable
|
33
|
-
:persistent
|
34
|
-
:delete
|
35
|
-
:chown
|
36
|
-
:chmod
|
37
|
-
:chtype
|
38
|
-
:clone
|
39
|
-
:rename
|
40
|
-
:snapshotdelete
|
41
|
-
:snapshotrevert
|
42
|
-
:snapshotflatten=> "image.snapshotflatten",
|
29
|
+
:info => "image.info",
|
30
|
+
:allocate => "image.allocate",
|
31
|
+
:update => "image.update",
|
32
|
+
:enable => "image.enable",
|
33
|
+
:persistent => "image.persistent",
|
34
|
+
:delete => "image.delete",
|
35
|
+
:chown => "image.chown",
|
36
|
+
:chmod => "image.chmod",
|
37
|
+
:chtype => "image.chtype",
|
38
|
+
:clone => "image.clone",
|
39
|
+
:rename => "image.rename",
|
40
|
+
:snapshotdelete => "image.snapshotdelete",
|
41
|
+
:snapshotrevert => "image.snapshotrevert",
|
42
|
+
:snapshotflatten => "image.snapshotflatten",
|
43
|
+
:restore => "image.restore",
|
43
44
|
:lock => "image.lock",
|
44
45
|
:unlock => "image.unlock"
|
45
46
|
}
|
@@ -61,7 +62,7 @@ module OpenNebula
|
|
61
62
|
"LOCKED_USED_PERS" => "lock"
|
62
63
|
}
|
63
64
|
|
64
|
-
IMAGE_TYPES=%w{OS CDROM DATABLOCK KERNEL RAMDISK CONTEXT}
|
65
|
+
IMAGE_TYPES=%w{OS CDROM DATABLOCK KERNEL RAMDISK CONTEXT BACKUP}
|
65
66
|
|
66
67
|
SHORT_IMAGE_TYPES={
|
67
68
|
"OS" => "OS",
|
@@ -69,7 +70,8 @@ module OpenNebula
|
|
69
70
|
"DATABLOCK" => "DB",
|
70
71
|
"KERNEL" => "KL",
|
71
72
|
"RAMDISK" => "RD",
|
72
|
-
"CONTEXT" => "CX"
|
73
|
+
"CONTEXT" => "CX",
|
74
|
+
"BACKUP" => "BK"
|
73
75
|
}
|
74
76
|
|
75
77
|
DISK_TYPES=%w{FILE CD_ROM BLOCK RBD}
|
@@ -163,8 +165,8 @@ module OpenNebula
|
|
163
165
|
end
|
164
166
|
|
165
167
|
# Deletes the Image
|
166
|
-
def delete()
|
167
|
-
|
168
|
+
def delete(force=false)
|
169
|
+
call(IMAGE_METHODS[:delete], @pe_id, force)
|
168
170
|
end
|
169
171
|
|
170
172
|
# Changes the owner/group
|
@@ -229,7 +231,7 @@ module OpenNebula
|
|
229
231
|
# @return [nil, OpenNebula::Error] nil in case of success, Error
|
230
232
|
# otherwise
|
231
233
|
def rename(name)
|
232
|
-
|
234
|
+
call(IMAGE_METHODS[:rename], @pe_id, name)
|
233
235
|
end
|
234
236
|
|
235
237
|
# Deletes Image from snapshot
|
@@ -238,7 +240,7 @@ module OpenNebula
|
|
238
240
|
#
|
239
241
|
# @return [nil, OpenNebula::Error] nil in case of success or Error
|
240
242
|
def snapshot_delete(snap_id)
|
241
|
-
|
243
|
+
call(IMAGE_METHODS[:snapshotdelete], @pe_id, snap_id)
|
242
244
|
end
|
243
245
|
|
244
246
|
# Reverts Image state to a previous snapshot
|
@@ -247,7 +249,7 @@ module OpenNebula
|
|
247
249
|
#
|
248
250
|
# @return [nil, OpenNebula::Error] nil in case of success or Error
|
249
251
|
def snapshot_revert(snap_id)
|
250
|
-
|
252
|
+
call(IMAGE_METHODS[:snapshotrevert], @pe_id, snap_id)
|
251
253
|
end
|
252
254
|
|
253
255
|
# Flattens an image snapshot
|
@@ -256,7 +258,15 @@ module OpenNebula
|
|
256
258
|
#
|
257
259
|
# @return [nil, OpenNebula::Error] nil in case of success or Error
|
258
260
|
def snapshot_flatten(snap_id)
|
259
|
-
|
261
|
+
call(IMAGE_METHODS[:snapshotflatten], @pe_id, snap_id)
|
262
|
+
end
|
263
|
+
|
264
|
+
# Restore the VM backup stored by the image
|
265
|
+
#
|
266
|
+
# @param dst_id [Integer] Datastore destination ID
|
267
|
+
# @param restore_opts [String] Template with additional restore options
|
268
|
+
def restore(dst_id, restore_opts)
|
269
|
+
@client.call(IMAGE_METHODS[:restore], @pe_id, dst_id, restore_opts)
|
260
270
|
end
|
261
271
|
|
262
272
|
#######################################################################
|
data/lib/opennebula/ldap_auth.rb
CHANGED
@@ -213,7 +213,9 @@ class OpenNebula::LdapAuth
|
|
213
213
|
groups = []
|
214
214
|
ldap_groups.each do |group|
|
215
215
|
if (g = in_hash_ignore_case?(@mapping, group))
|
216
|
-
if ldap_groups.
|
216
|
+
if ldap_groups.any? {
|
217
|
+
|s| s.casecmp(@options[:group_admin_group_dn])==0
|
218
|
+
}
|
217
219
|
groups << "*#{@mapping[g]}"
|
218
220
|
else
|
219
221
|
groups << @mapping[g]
|
@@ -63,9 +63,7 @@ module OpenNebula::TemplateExt
|
|
63
63
|
#---------------------------------------------------------------
|
64
64
|
logger.info 'Processing VM disks' if logger
|
65
65
|
|
66
|
-
retrieve_xmlelements('TEMPLATE/DISK').each_with_index do
|
67
|
-
|disk, idx|
|
68
|
-
|
66
|
+
retrieve_xmlelements('TEMPLATE/DISK').each_with_index do |disk, idx|
|
69
67
|
image = image_lookup(disk)
|
70
68
|
|
71
69
|
next unless image
|
@@ -56,7 +56,9 @@ module OpenNebula
|
|
56
56
|
:scheddelete => "vm.scheddelete",
|
57
57
|
:schedupdate => "vm.schedupdate",
|
58
58
|
:attachsg => "vm.attachsg",
|
59
|
-
:detachsg => "vm.detachsg"
|
59
|
+
:detachsg => "vm.detachsg",
|
60
|
+
:backup => "vm.backup",
|
61
|
+
:updatenic => "vm.updatenic"
|
60
62
|
}
|
61
63
|
|
62
64
|
VM_STATE=%w{INIT PENDING HOLD ACTIVE STOPPED SUSPENDED DONE FAILED
|
@@ -132,6 +134,8 @@ module OpenNebula
|
|
132
134
|
HOTPLUG_RESIZE
|
133
135
|
HOTPLUG_SAVEAS_UNDEPLOYED
|
134
136
|
HOTPLUG_SAVEAS_STOPPED
|
137
|
+
BACKUP
|
138
|
+
BACKUP_POWEROFF
|
135
139
|
}
|
136
140
|
|
137
141
|
SHORT_VM_STATES={
|
@@ -216,7 +220,9 @@ module OpenNebula
|
|
216
220
|
"HOTPLUG_NIC_POWEROFF" => "hotp",
|
217
221
|
"HOTPLUG_RESIZE" => "hotp",
|
218
222
|
"HOTPLUG_SAVEAS_UNDEPLOYED" => "hotp",
|
219
|
-
"HOTPLUG_SAVEAS_STOPPED" => "hotp"
|
223
|
+
"HOTPLUG_SAVEAS_STOPPED" => "hotp",
|
224
|
+
"BACKUP" => "back",
|
225
|
+
"BACKUP_POWEROFF" => "back",
|
220
226
|
}
|
221
227
|
|
222
228
|
HISTORY_ACTION=%w{none migrate live-migrate shutdown shutdown-hard
|
@@ -228,6 +234,7 @@ module OpenNebula
|
|
228
234
|
snapshot-resize snapshot-delete snapshot-revert disk-saveas
|
229
235
|
disk-snapshot-revert recover retry monitor disk-snapshot-rename
|
230
236
|
alias-attach alias-detach poweroff-migrate poweroff-hard-migrate
|
237
|
+
backup nic-update
|
231
238
|
}
|
232
239
|
|
233
240
|
EXTERNAL_IP_ATTRS = [
|
@@ -462,6 +469,18 @@ module OpenNebula
|
|
462
469
|
return call(VM_METHODS[:detachnic], @pe_id, nic_id)
|
463
470
|
end
|
464
471
|
|
472
|
+
# Updates a NIC for a running VM
|
473
|
+
#
|
474
|
+
# @param nic_id [Integer] Id of the NIC to be updated
|
475
|
+
# @param nic_template [String] Template with updated attributes
|
476
|
+
# @param append [true|false] True to append new attributes instead of
|
477
|
+
# replace the whole template
|
478
|
+
# @return [nil, OpenNebula::Error] nil in case of success, Error
|
479
|
+
# otherwise
|
480
|
+
def nic_update(nic_id, nic_template, append = false)
|
481
|
+
return call(VM_METHODS[:updatenic], @pe_id, nic_id, nic_template, append ? 1 : 0)
|
482
|
+
end
|
483
|
+
|
465
484
|
# Attaches a Security Groupt to a running VM
|
466
485
|
#
|
467
486
|
# @param nic_id [Integer] Id of the NIC, where to attach SG
|
@@ -779,6 +798,15 @@ module OpenNebula
|
|
779
798
|
sched_template)
|
780
799
|
end
|
781
800
|
|
801
|
+
# Generate a backup for the VM (backup config must be set)
|
802
|
+
#
|
803
|
+
# @param ds_id [Integer] Id of the datastore to save the backup
|
804
|
+
# @return [Integer, OpenNebula::Error] ID of the resulting BACKUP image
|
805
|
+
# in case of success, Error otherwise.
|
806
|
+
def backup(ds_id, reset = false)
|
807
|
+
return @client.call(VM_METHODS[:backup], @pe_id, ds_id, reset)
|
808
|
+
end
|
809
|
+
|
782
810
|
########################################################################
|
783
811
|
# Helpers to get VirtualMachine information
|
784
812
|
########################################################################
|
@@ -286,160 +286,6 @@ module OpenNebula::VirtualMachineExt
|
|
286
286
|
raise
|
287
287
|
end
|
288
288
|
|
289
|
-
#-------------------------------------------------------------------
|
290
|
-
# Backups a VM. TODO Add final description
|
291
|
-
# @param keep [Bool]
|
292
|
-
# @param logger[Logger]
|
293
|
-
# @param binfo[Hash] Oneshot
|
294
|
-
#-------------------------------------------------------------------
|
295
|
-
def backup(keep = false, logger = nil, binfo = nil)
|
296
|
-
# --------------------------------------------------------------
|
297
|
-
# Check backup consistency
|
298
|
-
# --------------------------------------------------------------
|
299
|
-
rc = info
|
300
|
-
|
301
|
-
raise rc.message if OpenNebula.is_error?(rc)
|
302
|
-
|
303
|
-
binfo.merge!(backup_info) do |_key, old_val, new_val|
|
304
|
-
new_val.nil? ? old_val : new_val
|
305
|
-
end
|
306
|
-
|
307
|
-
raise 'No backup information' if binfo.nil?
|
308
|
-
|
309
|
-
raise 'No frequency defined' unless valid?(binfo[:freq])
|
310
|
-
|
311
|
-
raise 'No marketplace defined' unless valid?(binfo[:market])
|
312
|
-
|
313
|
-
return if Time.now.to_i - binfo[:last].to_i < binfo[:freq].to_i
|
314
|
-
|
315
|
-
# --------------------------------------------------------------
|
316
|
-
# Save VM as new template
|
317
|
-
# --------------------------------------------------------------
|
318
|
-
logger.info 'Saving VM as template' if logger
|
319
|
-
|
320
|
-
tid = save_as_template(
|
321
|
-
binfo[:name], '', :poweroff => true, :logger => logger
|
322
|
-
)
|
323
|
-
|
324
|
-
tmp = OpenNebula::Template.new_with_id(tid, @client)
|
325
|
-
rc = tmp.info
|
326
|
-
|
327
|
-
raise rc.message if OpenNebula.is_error?(rc)
|
328
|
-
|
329
|
-
# --------------------------------------------------------------
|
330
|
-
# Import template into Marketplace & update VM info
|
331
|
-
# --------------------------------------------------------------
|
332
|
-
logger.info "Importing template #{tmp.id} to marketplace "\
|
333
|
-
"#{binfo[:market]}" if logger
|
334
|
-
|
335
|
-
tmp.extend(OpenNebula::TemplateExt)
|
336
|
-
|
337
|
-
rc, ids = tmp.mp_import(binfo[:market], true, binfo[:name],
|
338
|
-
:wait => true, :logger => logger)
|
339
|
-
|
340
|
-
raise rc.message if OpenNebula.is_error?(rc)
|
341
|
-
|
342
|
-
logger.info "Imported app ids: #{ids.join(',')}" if logger
|
343
|
-
|
344
|
-
rc = update(backup_attr(binfo, ids), true)
|
345
|
-
|
346
|
-
if OpenNebula.is_error?(rc)
|
347
|
-
raise 'Could not update the backup reference: ' \
|
348
|
-
" #{rc.message}. New backup ids are #{ids.join(',')}."
|
349
|
-
end
|
350
|
-
|
351
|
-
# --------------------------------------------------------------
|
352
|
-
# Cleanup
|
353
|
-
# --------------------------------------------------------------
|
354
|
-
backup_cleanup(keep, logger, binfo, tmp)
|
355
|
-
rescue Error, StandardError => e
|
356
|
-
backup_cleanup(keep, logger, binfo, tmp)
|
357
|
-
|
358
|
-
logger.fatal(e.inspect) if logger
|
359
|
-
|
360
|
-
raise
|
361
|
-
end
|
362
|
-
|
363
|
-
#-------------------------------------------------------------------
|
364
|
-
# Restores VM information from previous backup
|
365
|
-
#
|
366
|
-
# @param datastore [Integer] Datastore ID to import app backup
|
367
|
-
# @param logger [Logger] Logger instance to print debug info
|
368
|
-
#
|
369
|
-
# @return [Integer] VM ID
|
370
|
-
#-------------------------------------------------------------------
|
371
|
-
def restore(datastore, logger = nil)
|
372
|
-
rc = info
|
373
|
-
|
374
|
-
if OpenNebula.is_error?(rc)
|
375
|
-
raise "Error getting VM: #{rc.message}"
|
376
|
-
end
|
377
|
-
|
378
|
-
logger.info 'Reading backup information' if logger
|
379
|
-
|
380
|
-
backup_ids = backup_info[:apps]
|
381
|
-
|
382
|
-
# highest (=last) of the app ids is the template id
|
383
|
-
app_id = backup_ids.last
|
384
|
-
|
385
|
-
app = OpenNebula::MarketPlaceApp.new_with_id(app_id, @client)
|
386
|
-
rc = app.info
|
387
|
-
|
388
|
-
if OpenNebula.is_error?(rc)
|
389
|
-
raise "Can not find appliance #{app_id}: #{rc.message}."
|
390
|
-
end
|
391
|
-
|
392
|
-
if logger
|
393
|
-
logger.info "Restoring VM #{self['ID']} from " \
|
394
|
-
"saved appliance #{app_id}"
|
395
|
-
end
|
396
|
-
|
397
|
-
app.extend(OpenNebula::MarketPlaceAppExt)
|
398
|
-
|
399
|
-
exp = app.export(:dsid => Integer(datastore),
|
400
|
-
:name => "#{self['NAME']} - RESTORED")
|
401
|
-
|
402
|
-
if OpenNebula.is_error?(exp)
|
403
|
-
raise "Can not restore app: #{exp.message}."
|
404
|
-
end
|
405
|
-
|
406
|
-
# Check possible errors when exporting apps
|
407
|
-
exp[:image].each do |image|
|
408
|
-
next unless OpenNebula.is_error?(image)
|
409
|
-
|
410
|
-
raise "Error restoring image: #{image.message}."
|
411
|
-
end
|
412
|
-
|
413
|
-
template = exp[:vmtemplate].first
|
414
|
-
|
415
|
-
if OpenNebula.is_error?(template)
|
416
|
-
raise "Error restoring template: #{template.message}."
|
417
|
-
end
|
418
|
-
|
419
|
-
if logger
|
420
|
-
logger.info(
|
421
|
-
"Backup restored, VM template: #{exp[:vmtemplate]}, " \
|
422
|
-
"images: #{exp[:image]}"
|
423
|
-
)
|
424
|
-
|
425
|
-
logger.info(
|
426
|
-
"Instantiating the template #{exp[:vmtemplate]}"
|
427
|
-
)
|
428
|
-
end
|
429
|
-
|
430
|
-
tmpl = OpenNebula::Template.new_with_id(template, @client)
|
431
|
-
rc = tmpl.instantiate
|
432
|
-
|
433
|
-
if OpenNebula.is_error?(rc)
|
434
|
-
raise "Can not instantiate the template: #{rc.message}."
|
435
|
-
end
|
436
|
-
|
437
|
-
rc
|
438
|
-
rescue Error, StandardError => e
|
439
|
-
logger.fatal(e.inspect) if logger
|
440
|
-
raise
|
441
|
-
end
|
442
|
-
|
443
289
|
####################################################################
|
444
290
|
# Private extended interface
|
445
291
|
####################################################################
|
@@ -457,58 +303,6 @@ module OpenNebula::VirtualMachineExt
|
|
457
303
|
!att.nil?
|
458
304
|
end
|
459
305
|
|
460
|
-
#-------------------------------------------------------------------
|
461
|
-
# Get backup information from the VM
|
462
|
-
#-------------------------------------------------------------------
|
463
|
-
def backup_info
|
464
|
-
base = '//USER_TEMPLATE/BACKUP'
|
465
|
-
binfo = {}
|
466
|
-
|
467
|
-
app_ids = self["#{base}/MARKETPLACE_APP_IDS"] || ''
|
468
|
-
|
469
|
-
binfo[:name] = "#{self['NAME']} - BACKUP " \
|
470
|
-
" - #{Time.now.strftime('%Y%m%d_%k%M')}"
|
471
|
-
|
472
|
-
binfo[:freq] = self["#{base}/FREQUENCY_SECONDS"]
|
473
|
-
binfo[:last] = self["#{base}/LAST_BACKUP_TIME"]
|
474
|
-
binfo[:market] = Integer(self["#{base}/MARKETPLACE_ID"])
|
475
|
-
binfo[:apps] = app_ids.split(',')
|
476
|
-
|
477
|
-
binfo
|
478
|
-
rescue StandardError
|
479
|
-
binfo
|
480
|
-
end
|
481
|
-
|
482
|
-
#-------------------------------------------------------------------
|
483
|
-
# Generate backup information string
|
484
|
-
#-------------------------------------------------------------------
|
485
|
-
def backup_attr(binfo, ids)
|
486
|
-
'BACKUP=[' \
|
487
|
-
" MARKETPLACE_APP_IDS = \"#{ids.join(',')}\"," \
|
488
|
-
" FREQUENCY_SECONDS = \"#{binfo[:freq]}\"," \
|
489
|
-
" LAST_BACKUP_TIME = \"#{Time.now.to_i}\"," \
|
490
|
-
" MARKETPLACE_ID = \"#{binfo[:market]}\" ]"
|
491
|
-
end
|
492
|
-
|
493
|
-
#-------------------------------------------------------------------
|
494
|
-
# Cleanup backup leftovers in case of failure
|
495
|
-
#-------------------------------------------------------------------
|
496
|
-
def backup_cleanup(keep, logger, binfo, template)
|
497
|
-
if template
|
498
|
-
logger.info "Deleting template #{template.id}" if logger
|
499
|
-
|
500
|
-
template.delete(true)
|
501
|
-
end
|
502
|
-
|
503
|
-
binfo[:apps].each do |id|
|
504
|
-
logger.info "Deleting appliance #{id}" if logger
|
505
|
-
|
506
|
-
papp = OpenNebula::MarketPlaceApp.new_with_id(id, @client)
|
507
|
-
|
508
|
-
papp.delete
|
509
|
-
end if !keep && binfo[:apps]
|
510
|
-
end
|
511
|
-
|
512
306
|
end
|
513
307
|
end
|
514
308
|
|
@@ -44,7 +44,7 @@ module OpenNebula
|
|
44
44
|
:recover => "vn.recover"
|
45
45
|
}
|
46
46
|
|
47
|
-
VN_STATES=%w{INIT READY LOCK_CREATE LOCK_DELETE DONE ERROR}
|
47
|
+
VN_STATES=%w{INIT READY LOCK_CREATE LOCK_DELETE DONE ERROR UPDATE_FAILURE}
|
48
48
|
|
49
49
|
SHORT_VN_STATES={
|
50
50
|
"INIT" => "init",
|
@@ -52,7 +52,8 @@ module OpenNebula
|
|
52
52
|
"LOCK_CREATE" => "lock",
|
53
53
|
"LOCK_DELETE" => "lock",
|
54
54
|
"DONE" => "done",
|
55
|
-
"ERROR" => "err"
|
55
|
+
"ERROR" => "err",
|
56
|
+
"UPDATE_FAILURE"=> "fail"
|
56
57
|
}
|
57
58
|
|
58
59
|
# Creates a VirtualNetwork description with just its identifier
|
@@ -326,7 +327,7 @@ module OpenNebula
|
|
326
327
|
# Recovers an stuck Virtual Network
|
327
328
|
#
|
328
329
|
# @param result [Integer] Recover with failure (0), success (1),
|
329
|
-
# delete (2)
|
330
|
+
# delete (2), retry (3)
|
330
331
|
# @return [nil, OpenNebula::Error] nil in case of success, Error
|
331
332
|
# otherwise
|
332
333
|
def recover(result)
|
@@ -377,6 +378,34 @@ module OpenNebula
|
|
377
378
|
SHORT_VN_STATES[state_str]
|
378
379
|
end
|
379
380
|
|
381
|
+
# Returns three arrays with the numeric VM IDs for VMs updated,
|
382
|
+
# outdated (include updating) and error
|
383
|
+
def vm_ids
|
384
|
+
updated = Array.new
|
385
|
+
|
386
|
+
self.each('UPDATED_VMS/ID') do |id|
|
387
|
+
updated << id.text.to_i
|
388
|
+
end
|
389
|
+
|
390
|
+
outdated = Array.new
|
391
|
+
|
392
|
+
self.each('OUTDATED_VMS/ID') do |id|
|
393
|
+
outdated << id.text.to_i
|
394
|
+
end
|
395
|
+
|
396
|
+
self.each('UPDATING_VMS/ID') do |id|
|
397
|
+
outdated << id.text.to_i
|
398
|
+
end
|
399
|
+
|
400
|
+
error = Array.new
|
401
|
+
|
402
|
+
self.each('ERROR_VMS/ID') do |id|
|
403
|
+
error << id.text.to_i
|
404
|
+
end
|
405
|
+
|
406
|
+
[updated, outdated, error]
|
407
|
+
end
|
408
|
+
|
380
409
|
private
|
381
410
|
def set_publish(published)
|
382
411
|
group_u = published ? 1 : 0
|
data/lib/opennebula/x509_auth.rb
CHANGED
@@ -29,9 +29,9 @@ class OpenNebula::X509Auth
|
|
29
29
|
#Constants with paths to relevant files and defaults
|
30
30
|
###########################################################################
|
31
31
|
if !ENV["ONE_LOCATION"]
|
32
|
-
ETC_LOCATION
|
32
|
+
ETC_LOCATION = "/etc/one"
|
33
33
|
else
|
34
|
-
ETC_LOCATION
|
34
|
+
ETC_LOCATION = ENV["ONE_LOCATION"] + "/etc"
|
35
35
|
end
|
36
36
|
|
37
37
|
X509_AUTH_CONF_PATH = ETC_LOCATION + "/auth/x509_auth.conf"
|
@@ -173,8 +173,7 @@ private
|
|
173
173
|
# Check start time and end time of certificates
|
174
174
|
@cert_chain.each do |cert|
|
175
175
|
if cert.not_before > now || cert.not_after < now
|
176
|
-
raise
|
177
|
-
now.localtime.to_s + "."
|
176
|
+
raise "Certificate not valid. Current time is #{now.localtime}"
|
178
177
|
end
|
179
178
|
end
|
180
179
|
|
@@ -187,16 +186,16 @@ private
|
|
187
186
|
@cert_chain[1..-1].each do |cert|
|
188
187
|
if !((signee.issuer.to_s == cert.subject.to_s) &&
|
189
188
|
(signee.verify(cert.public_key)))
|
190
|
-
raise
|
191
|
-
|
192
|
-
cert.subject.to_s + "."
|
189
|
+
raise "#{signee.subject} with issuer #{signee.issuer} " \
|
190
|
+
"was not verified by #{cert.subject}"
|
193
191
|
end
|
192
|
+
|
194
193
|
signee = cert
|
195
194
|
end
|
196
195
|
|
197
196
|
# Validate the End Entity certificate
|
198
197
|
if !@options[:ca_dir]
|
199
|
-
raise
|
198
|
+
raise "No certifcate authority directory was specified."
|
200
199
|
end
|
201
200
|
|
202
201
|
begin
|
@@ -207,9 +206,8 @@ private
|
|
207
206
|
|
208
207
|
if !((signee.issuer.to_s == ca_cert.subject.to_s) &&
|
209
208
|
(signee.verify(ca_cert.public_key)))
|
210
|
-
raise
|
211
|
-
|
212
|
-
ca_cert.subject.to_s + "."
|
209
|
+
raise "#{signee.subject} with issuer #{signee.issuer} " \
|
210
|
+
"was not verified by #{ca_cert.subject}"
|
213
211
|
end
|
214
212
|
|
215
213
|
signee = ca_cert
|
@@ -229,7 +227,7 @@ private
|
|
229
227
|
|
230
228
|
if !File.exist?(crl_path)
|
231
229
|
if @options[:check_crl]
|
232
|
-
raise failed
|
230
|
+
raise "#{failed} CRL file #{crl_path} does not exist"
|
233
231
|
else
|
234
232
|
return
|
235
233
|
end
|
@@ -240,7 +238,7 @@ private
|
|
240
238
|
|
241
239
|
# First verify the CRL itself with its signer
|
242
240
|
unless crl_cert.verify( ca_cert.public_key ) then
|
243
|
-
raise failed
|
241
|
+
raise "#{failed} CRL is not verified by its Signer"
|
244
242
|
end
|
245
243
|
|
246
244
|
# Extract the list of revoked certificates from the CRL
|
@@ -250,8 +248,8 @@ private
|
|
250
248
|
# certificate
|
251
249
|
rc_array.each do |e|
|
252
250
|
if e.serial.eql?(signee.serial) then
|
253
|
-
raise failed
|
254
|
-
|
251
|
+
raise "#{failed} #{signee.subject} is found in the " \
|
252
|
+
"CRL, i.e. it is revoked"
|
255
253
|
end
|
256
254
|
end
|
257
255
|
end
|
data/lib/opennebula.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opennebula
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.
|
4
|
+
version: 6.5.80.pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- OpenNebula
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-12-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -255,9 +255,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
255
255
|
version: '0'
|
256
256
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
257
257
|
requirements:
|
258
|
-
- - "
|
258
|
+
- - ">"
|
259
259
|
- !ruby/object:Gem::Version
|
260
|
-
version:
|
260
|
+
version: 1.3.1
|
261
261
|
requirements: []
|
262
262
|
rubygems_version: 3.1.2
|
263
263
|
signing_key:
|