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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 266777cd8cbee1a5dd1a31a5a13be7cebb30ea31fb570f250e86879ba3bdbb0e
4
- data.tar.gz: 3a60b62aa8040d838ba5a838ee30e53ae3f120e63c9d348329e1ed01e82f982a
3
+ metadata.gz: 5cb427e39e8e2f581076e069b21c0da24b5e82dac56e29b0e7017c7e419b3a31
4
+ data.tar.gz: 59203c99872a0065565a336a0bc814f5f7f9acd15a79bcdf3e1df9c92f3b5209
5
5
  SHA512:
6
- metadata.gz: 5b62bafc5c642cef2ba2b3f9e10c656cefe8c65a2c4835f3b9aaceda2b5eec3fc40513abbd77ee592369e805d14a936a925d5168e380e2c94b7e7ec9f9d05d3a
7
- data.tar.gz: c10696616d94b1acaf6bc29912d92c331b7ff0f25d543312fbbec802dcfbe466616da36a74537e06f009315d25a762f375aa989910234ecc0bb879c4cb1b667c
6
+ metadata.gz: c20a43d2ade283e63fda2143c9fb8fc2d88f7191e81f75f17219d0d625c99f587f6aea2517dfde44d1dd65aea08c65fa349518045a58df2f912d3d7bc5afb197
7
+ data.tar.gz: 7e4f2365737cf9746b91834ff0af8cb01ff7dc198b5f143686d483f6c9aa927df6cbac4e4226682ce599c5afea85be716e2cb21dc2144986e288f8f2f33e5bbb
@@ -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
- attr_accessor :host
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
@@ -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
@@ -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 = Array.new
80
-
81
- register_action(ACTION[:deploy].to_sym, method("deploy"))
82
- register_action(ACTION[:shutdown].to_sym, method("shutdown"))
83
- register_action(ACTION[:reboot].to_sym, method("reboot"))
84
- register_action(ACTION[:reset].to_sym, method("reset"))
85
- register_action(ACTION[:cancel].to_sym, method("cancel"))
86
- register_action(ACTION[:save].to_sym, method("save"))
87
- register_action(ACTION[:restore].to_sym, method("restore"))
88
- register_action(ACTION[:migrate].to_sym, method("migrate"))
89
- register_action(ACTION[:poll].to_sym, method("poll"))
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, method("cleanup"))
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
@@ -51,7 +51,7 @@ end
51
51
  module CloudClient
52
52
 
53
53
  # OpenNebula version
54
- VERSION = '6.4.0'
54
+ VERSION = '6.5.80'
55
55
 
56
56
  # #########################################################################
57
57
  # Default location for the authentication file
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
@@ -361,7 +361,7 @@ module VCenterDriver
361
361
  .rm_rf(
362
362
  temp_folder
363
363
  )
364
- raise "Error \ removing tar for #{descriptor_name}")
364
+ raise "Error removing tar for #{descriptor_name}")
365
365
  end # rubocop:disable Style/Semicolon
366
366
  end
367
367
  end
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
@@ -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
- @cloud_auth.client
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, external_client = nil, &block)
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
- if external_client.nil?
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 = external_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?
@@ -26,20 +26,21 @@ module OpenNebula
26
26
  #######################################################################
27
27
 
28
28
  IMAGE_METHODS = {
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",
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
- super(IMAGE_METHODS[:delete])
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
- return call(IMAGE_METHODS[:rename], @pe_id, name)
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
- return call(IMAGE_METHODS[:snapshotdelete], @pe_id, snap_id)
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
- return call(IMAGE_METHODS[:snapshotrevert], @pe_id, snap_id)
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
- return call(IMAGE_METHODS[:snapshotflatten], @pe_id, snap_id)
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
  #######################################################################
@@ -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.include? @options[:group_admin_group_dn]
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
@@ -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 = "/etc/one"
32
+ ETC_LOCATION = "/etc/one"
33
33
  else
34
- ETC_LOCATION = ENV["ONE_LOCATION"] + "/etc"
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 failed + "Certificate not valid. Current time is " +
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 failed + signee.subject.to_s + " with issuer " +
191
- signee.issuer.to_s + " was not verified by " +
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 failed + "No certifcate authority directory was specified."
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 failed + signee.subject.to_s + " with issuer " +
211
- signee.issuer.to_s + " was not verified by " +
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 + "CRL file #{crl_path} does not exist"
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 + "CRL is not verified by its Signer"
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 + "#{signee.subject.to_s} is found in the "<<
254
- "CRL, i.e. it is revoked"
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
@@ -77,5 +77,5 @@ require 'opennebula/flow'
77
77
  module OpenNebula
78
78
 
79
79
  # OpenNebula version
80
- VERSION = '6.4.0'
80
+ VERSION = '6.5.80'
81
81
  end
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.1
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-07-12 00:00:00.000000000 Z
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: '0'
260
+ version: 1.3.1
261
261
  requirements: []
262
262
  rubygems_version: 3.1.2
263
263
  signing_key: