opennebula-cli 6.6.3 → 6.7.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.
@@ -312,15 +312,9 @@ module CommandParser
312
312
  end
313
313
 
314
314
  def deprecated_command(name, new_command)
315
- cmd = Hash.new
316
- cmd[:desc] = "Deprecated, use #{new_command} instead"
317
- cmd[:arity] = 0
318
- cmd[:options] = []
319
- cmd[:args_format] = [[:string, nil]] * 20
315
+ cmd = @commands[name.to_sym] || Hash.new
316
+ cmd[:desc] += "\nDeprecated, use #{new_command} instead"
320
317
  cmd[:deprecated] = new_command
321
- cmd[:proc] = lambda do
322
- print_deprecated(new_command)
323
- end
324
318
 
325
319
  @commands[name.to_sym] = cmd
326
320
  end
@@ -800,7 +794,6 @@ module CommandParser
800
794
  def print_deprecated(new_command)
801
795
  puts "This command is deprecated, use instead:"
802
796
  puts " $ #{File.basename $0} #{new_command}"
803
- exit(-1)
804
797
  end
805
798
 
806
799
  def word_wrap(size, text, first_size=nil)
@@ -34,7 +34,7 @@ class OneAclHelper < OpenNebulaHelper::OneHelper
34
34
  def self.resource_mask(str)
35
35
  resource_type=str.split('/')[0]
36
36
 
37
- mask = '------------------'
37
+ mask = '-------------------'
38
38
 
39
39
  resource_type.split('+').each do |type|
40
40
  case type
@@ -74,6 +74,8 @@ class OneAclHelper < OpenNebulaHelper::OneHelper
74
74
  mask[16] = 'P'
75
75
  when 'VNTEMPLATE'
76
76
  mask[17] = 't'
77
+ when 'BACKUPJOB'
78
+ mask[18] = 'B'
77
79
  end
78
80
  end
79
81
  mask
@@ -128,9 +130,9 @@ class OneAclHelper < OpenNebulaHelper::OneHelper
128
130
  d['STRING'].split(' ')[0]
129
131
  end
130
132
 
131
- column :RES_VHNIUTGDCOZSvRMAPt,
133
+ column :RES_VHNIUTGDCOZSvRMAPtB,
132
134
  'Resource to which the rule applies',
133
- :size => 22 do |d|
135
+ :size => 23 do |d|
134
136
  OneAclHelper.resource_mask d['STRING'].split(' ')[1]
135
137
  end
136
138
 
@@ -155,7 +157,7 @@ class OneAclHelper < OpenNebulaHelper::OneHelper
155
157
  d['STRING']
156
158
  end
157
159
 
158
- default :ID, :USER, :RES_VHNIUTGDCOZSvRMAPt, :RID, :OPE_UMAC, :ZONE
160
+ default :ID, :USER, :RES_VHNIUTGDCOZSvRMAPtB, :RID, :OPE_UMAC, :ZONE
159
161
  end
160
162
  end
161
163
  # rubocop:enable Lint/IneffectiveAccessModifier
@@ -0,0 +1,284 @@
1
+ # -------------------------------------------------------------------------- #
2
+ # Copyright 2002-2023, 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
+ require 'one_helper'
18
+
19
+ # Helper for onebackupjob command
20
+ class OneBackupJobHelper < OpenNebulaHelper::OneHelper
21
+
22
+ def self.rname
23
+ 'BACKUPJOB'
24
+ end
25
+
26
+ def self.conf_file
27
+ 'onebackupjob.yaml'
28
+ end
29
+
30
+ TEMPLATE_OPTIONS = [
31
+ {
32
+ :name => 'name',
33
+ :large => '--name name',
34
+ :format => String,
35
+ :description => 'Name of the new backup job'
36
+ },
37
+ {
38
+ :name => 'description',
39
+ :large => '--description description',
40
+ :format => String,
41
+ :description => 'Description for the new Image'
42
+ },
43
+ {
44
+ :name => 'backup_vms',
45
+ :large => '--vms "vm_id1,vm_id2..."',
46
+ :format => String,
47
+ :description => 'List of VM IDs to backup'
48
+ },
49
+ {
50
+ :name => 'keep_last',
51
+ :large => '--keep N',
52
+ :format => String,
53
+ :description => 'Keep N backups for the VMs in this backup job'
54
+ },
55
+ {
56
+ :name => 'mode',
57
+ :large => '--mode <increment|full>',
58
+ :format => String,
59
+ :description => 'Backup mode'
60
+ }
61
+ ]
62
+
63
+ def format_pool(options)
64
+ config_file = self.class.table_conf
65
+
66
+ CLIHelper::ShowTable.new(config_file, self) do
67
+ column :ID, 'ONE identifier for the Backup Job', :size=>4 do |d|
68
+ d['ID']
69
+ end
70
+
71
+ column :USER, 'Username of the Backup Job owner', :left,
72
+ :size=>15 do |d|
73
+ helper.user_name(d, options)
74
+ end
75
+
76
+ column :GROUP, 'Group of the Backup Job', :left, :size=>15 do |d|
77
+ helper.group_name(d, options)
78
+ end
79
+
80
+ column :PRIO, 'Priority of the Backup Job', :left, :size=>4 do |d|
81
+ d['PRIORITY'].to_i
82
+ end
83
+
84
+ column :NAME, 'Date for the last backup operation', :left, :size=>15 do |d|
85
+ d['NAME']
86
+ end
87
+
88
+ column :LAST, 'Date for the last backup operation', :size => 15 do |d|
89
+ begin
90
+ btime = d['LAST_BACKUP_TIME'].to_i
91
+ rescue StandardError
92
+ btime = 0
93
+ end
94
+ OpenNebulaHelper.time_to_str(btime, false, true, true)
95
+ end
96
+
97
+ column :VMS, 'VM IDs part of this backup job', :size => 15 do |d|
98
+ begin
99
+ vm = d['TEMPLATE']['BACKUP_VMS']
100
+ vm[12..-1]='...' if vm.size > 15
101
+ vm
102
+ rescue StandardError
103
+ '-'
104
+ end
105
+ end
106
+
107
+ default :ID, :USER, :GROUP, :PRIO, :NAME, :LAST, :VMS
108
+ end
109
+ end
110
+
111
+ def schedule_actions(ids, options, warning = nil)
112
+ # Verbose by default
113
+ options[:verbose] = true
114
+
115
+ message = if options[:schedule].class == Integer
116
+ "backup scheduled at #{Time.at(options[:schedule])}"
117
+ else
118
+ "backup scheduled after #{options[:schedule]}s"
119
+ end
120
+
121
+ tmp_str = OpenNebulaHelper.schedule_action_tmpl(options, nil, warning)
122
+
123
+ perform_actions(ids, options, message) do |bj|
124
+ rc = bj.sched_action_add(tmp_str)
125
+
126
+ if OpenNebula.is_error?(rc)
127
+ STDERR.puts rc.message
128
+ exit(-1)
129
+ end
130
+ end
131
+ end
132
+
133
+ # Update schedule action
134
+ #
135
+ # @param id [Integer] BackupJob ID
136
+ # @param action_id [Integer] Sched action ID
137
+ # @param file [String] File path with update content
138
+ # @param options
139
+ def update_schedule_action(id, action_id, file, options)
140
+ perform_action(id, options, 'Sched action updated') do |bj|
141
+ rc = bj.info
142
+
143
+ if OpenNebula.is_error?(rc)
144
+ STDERR.puts "Error #{rc.message}"
145
+ exit(-1)
146
+ end
147
+
148
+ xpath = "TEMPLATE/SCHED_ACTION[ID=#{action_id}]"
149
+
150
+ unless bj.retrieve_elements(xpath)
151
+ STDERR.puts "Sched action #{action_id} not found"
152
+ exit(-1)
153
+ end
154
+
155
+ # Get user information
156
+ if file
157
+ str = File.read(file)
158
+ else
159
+ str = OpenNebulaHelper.update_template(id, bj, nil, xpath)
160
+ end
161
+
162
+ # Add the modified sched action
163
+ tmp_str = "\nSCHED_ACTION = ["
164
+ tmp_str << str.split("\n").join(',')
165
+ tmp_str << ']'
166
+
167
+ rc = bj.sched_action_update(action_id, tmp_str)
168
+
169
+ if OpenNebula.is_error?(rc)
170
+ STDERR.puts "Error updating: #{rc.message}"
171
+ exit(-1)
172
+ end
173
+ end
174
+ end
175
+
176
+ def self.create_backupjob_template(options)
177
+ template_options = TEMPLATE_OPTIONS.map do |o|
178
+ o[:name].to_sym
179
+ end
180
+
181
+ template_options << :name
182
+
183
+ t = ''
184
+ template_options.each do |n|
185
+ t << "#{n.to_s.upcase}=\"#{options[n]}\"\n" if options[n]
186
+ end
187
+
188
+ t
189
+ end
190
+
191
+ private
192
+
193
+ def factory(id = nil)
194
+ if id
195
+ OpenNebula::BackupJob.new_with_id(id, @client)
196
+ else
197
+ xml=OpenNebula::BackupJob.build_xml
198
+ OpenNebula::BackupJob.new(xml, @client)
199
+ end
200
+ end
201
+
202
+ def factory_pool(user_flag = -2)
203
+ OpenNebula::BackupJobPool.new(@client, user_flag)
204
+ end
205
+
206
+ def format_resource(bj, options = {})
207
+ bj_hash = bj.to_hash
208
+
209
+ str='%-15s: %-20s'
210
+ str_h1='%-80s'
211
+
212
+ # ----------------------------------------------------------------------
213
+ CLIHelper.print_header(
214
+ str_h1 % "BACKUP JOB #{bj['ID']} INFORMATION"
215
+ )
216
+ # ----------------------------------------------------------------------
217
+ puts format(str, 'ID', bj.id.to_s)
218
+ puts format(str, 'NAME', bj.name)
219
+ puts format(str, 'USER', bj['UNAME'])
220
+ puts format(str, 'GROUP', bj['GNAME'])
221
+ puts format(str, 'LOCK', OpenNebulaHelper.level_lock_to_str(bj['LOCK/LOCKED']))
222
+
223
+ CLIHelper.print_header(str_h1 % 'PERMISSIONS', false)
224
+
225
+ ['OWNER', 'GROUP', 'OTHER'].each do |e|
226
+ mask = '---'
227
+ mask[0] = 'u' if bj["PERMISSIONS/#{e}_U"] == '1'
228
+ mask[1] = 'm' if bj["PERMISSIONS/#{e}_M"] == '1'
229
+ mask[2] = 'a' if bj["PERMISSIONS/#{e}_A"] == '1'
230
+
231
+ puts format(str, e, mask)
232
+ end
233
+ puts
234
+
235
+ # ----------------------------------------------------------------------
236
+ CLIHelper.print_header(
237
+ str_h1 % 'LAST BACKUP JOB EXECUTION INFORMATION'
238
+ )
239
+ # ----------------------------------------------------------------------
240
+ puts format(str, 'TIME', OpenNebulaHelper.time_to_str(bj['LAST_BACKUP_TIME']))
241
+ puts format(str, 'DURATION', OpenNebulaHelper.period_to_str(bj['LAST_BACKUP_DURATION']))
242
+ puts
243
+
244
+ # ----------------------------------------------------------------------
245
+ CLIHelper.print_header(
246
+ str_h1 % 'VIRTUAL MACHINE BACKUP STATUS'
247
+ )
248
+ # ----------------------------------------------------------------------
249
+ up = bj.retrieve_elements('UPDATED_VMS/ID')
250
+ out = bj.retrieve_elements('OUTDATED_VMS/ID')
251
+ act = bj.retrieve_elements('BACKING_UP_VMS/ID')
252
+ err = bj.retrieve_elements('ERROR_VMS/ID')
253
+
254
+ up = [] if up.nil?
255
+ out = [] if out.nil?
256
+ act = [] if act.nil?
257
+ err = [] if err.nil?
258
+
259
+ puts format(str, 'UPDATED', up.join(','))
260
+ puts format(str, 'OUTDATED', out.join(','))
261
+ puts format(str, 'ONGOING', act.join(','))
262
+ puts format(str, 'ERROR', err.join(','))
263
+
264
+ if bj.has_elements?('/BACKUPJOB/TEMPLATE/SCHED_ACTION')
265
+ puts
266
+ CLIHelper.print_header(str_h1 % 'SCHEDULED ACTIONS', false)
267
+
268
+ table = OpenNebulaHelper.scheduled_action_table(self)
269
+ table.show([bj_hash['BACKUPJOB']['TEMPLATE']['SCHED_ACTION']].flatten, {})
270
+ end
271
+
272
+ if !options[:all]
273
+ bj.delete_element('/BACKUPJOB/TEMPLATE/SCHED_ACTION')
274
+ end
275
+
276
+ puts
277
+
278
+ # ----------------------------------------------------------------------
279
+ CLIHelper.print_header(str_h1 % 'TEMPLATE CONTENTS', false)
280
+ # ----------------------------------------------------------------------
281
+ puts bj.template_str
282
+ end
283
+
284
+ end
@@ -112,72 +112,6 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
112
112
  :description => 'Creates the new VM on hold state instead of pending'
113
113
  }
114
114
 
115
- SCHEDULE = {
116
- :name => 'schedule',
117
- :large => '--schedule TIME',
118
- :description => 'Schedules this action to be executed after' \
119
- 'the given time. For example: onevm resume 0 --schedule "09/23 14:15"',
120
- :format => String,
121
- :proc => lambda {|o, options|
122
- if o[0] == '+'
123
- options[:schedule] = o
124
- elsif o == 'now'
125
- options[:schedule] = Time.now.to_i
126
- else
127
- begin
128
- options[:schedule] = Time.parse(o).to_i
129
- rescue StandardError
130
- STDERR.puts "Error parsing time spec: #{o}"
131
- exit(-1)
132
- end
133
- end
134
- }
135
- }
136
-
137
- WEEKLY = {
138
- :name => 'weekly',
139
- :large => '--weekly days',
140
- :description => 'Repeats the schedule action the days of the week ' \
141
- 'specified, it can be a number between 0 (Sunday) to 6 (Saturday) ' \
142
- 'separated with commas. ' \
143
- 'For example: onevm resume 0 --schedule "09/23 14:15" --weekly 0,2,4',
144
- :format => String
145
- }
146
-
147
- MONTHLY = {
148
- :name => 'monthly',
149
- :large => '--monthly days',
150
- :description => 'Repeats the schedule action the days of the month ' \
151
- 'specified, it can be a number between 1,31 separated with commas. ' \
152
- 'For example: onevm resume 0 --schedule "09/23 14:15" --monthly 1,14',
153
- :format => String
154
- }
155
-
156
- YEARLY = {
157
- :name => 'yearly',
158
- :large => '--yearly days',
159
- :description => 'Repeats the schedule action the days of the year ' \
160
- 'specified, it can be a number between 0,365 separated with commas. ' \
161
- 'For example: onevm resume 0 --schedule "09/23 14:15" --yearly 30,60',
162
- :format => String
163
- }
164
-
165
- HOURLY = {
166
- :name => 'hourly',
167
- :large => '--hourly hour',
168
- :description => 'Repeats the schedule action each hours specified,' \
169
- 'it can be a number between 0,168 separated with commas. ' \
170
- 'For example: onevm resume 0 --schedule "09/23 14:15" --hourly 1,5',
171
- :format => Numeric
172
- }
173
-
174
- END_TIME = {
175
- :name => 'end',
176
- :large => '--end number|TIME',
177
- :description => '----',
178
- :format => String
179
- }
180
-
181
115
  ALL_TEMPLATE = {
182
116
  :name => 'all',
183
117
  :large => '--all',
@@ -426,41 +360,9 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
426
360
  "#{action} scheduled after #{options[:schedule]}s from start"
427
361
  end
428
362
 
429
- perform_actions(ids, options, message) do |vm|
430
- str_periodic = ''
431
-
432
- if options.key?(:weekly)
433
- str_periodic << ", REPEAT = 0, DAYS = \"#{options[:weekly]}\""
434
- elsif options.key?(:monthly)
435
- str_periodic << ", REPEAT = 1, DAYS = \"#{options[:monthly]}\""
436
- elsif options.key?(:yearly)
437
- str_periodic << ", REPEAT = 2, DAYS = \"#{options[:yearly]}\""
438
- elsif options.key?(:hourly)
439
- str_periodic << ", REPEAT = 3, DAYS = \"#{options[:hourly]}\""
440
- end
441
-
442
- if options.key?(:end)
443
- begin
444
- end_date = Date.parse(options[:end])
445
- str_periodic << ', END_TYPE = 2, ' \
446
- "END_VALUE = #{end_date.to_time.to_i}"
447
- rescue ArgumentError
448
- if options[:end].to_i > 0
449
- str_periodic << ', END_TYPE = 1, ' \
450
- "END_VALUE = #{options[:end].to_i}"
451
- end
452
- end
453
- elsif str_periodic != ''
454
- str_periodic << ', END_TYPE = 0'
455
- end
456
-
457
- tmp_str = 'SCHED_ACTION = ['
458
- tmp_str << "ACTION = #{action}, "
459
- tmp_str << "WARNING = #{warning}," if warning
460
- tmp_str << "ARGS = \"#{options[:args]}\"," if options[:args]
461
- tmp_str << "TIME = #{options[:schedule]}"
462
- tmp_str << str_periodic << ']'
363
+ tmp_str = OpenNebulaHelper.schedule_action_tmpl(options, action, warning)
463
364
 
365
+ perform_actions(ids, options, message) do |vm|
464
366
  rc = vm.sched_action_add(tmp_str)
465
367
 
466
368
  if OpenNebula.is_error?(rc)
@@ -475,8 +377,9 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
475
377
  # @param vm_id [Integer] Virtual Machine ID
476
378
  # @param action_id [Integer] Sched action ID
477
379
  # @param file [String] File path with update content
478
- def update_schedule_action(vm_id, action_id, file)
479
- perform_action(vm_id, {}, 'Sched action updated') do |vm|
380
+ # @param options
381
+ def update_schedule_action(vm_id, action_id, file, options)
382
+ perform_action(vm_id, options, 'Sched action updated') do |vm|
480
383
  rc = vm.info
481
384
 
482
385
  if OpenNebula.is_error?(rc)
@@ -1290,92 +1193,8 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
1290
1193
  puts
1291
1194
  CLIHelper.print_header(str_h1 % 'SCHEDULED ACTIONS', false)
1292
1195
 
1293
- CLIHelper::ShowTable.new(nil, self) do
1294
- column :ID, '', :adjust => true do |d|
1295
- d['ID'] unless d.nil?
1296
- end
1297
-
1298
- column :ACTION, '', :adjust => true do |d|
1299
- d['ACTION'] unless d.nil?
1300
- end
1301
-
1302
- column :ARGS, '', :adjust => true do |d|
1303
- d['ARGS'] ? d['ARGS'] : '-'
1304
- end
1305
-
1306
- column :SCHEDULED, '', :adjust => true do |d|
1307
- t2 = d['TIME'].to_i
1308
- t2 += vm['STIME'].to_i unless d['TIME'] =~ /^[0-9].*/
1309
-
1310
- OpenNebulaHelper.time_to_str(t2, false) \
1311
- unless d.nil?
1312
- end
1313
-
1314
- column :REPEAT, '', :adjust => true do |d|
1315
- str_rep = ''
1316
- if !d.nil? && d.key?('REPEAT')
1317
- case d['REPEAT']
1318
- when '0'
1319
- str_rep << 'Weekly '
1320
- when '1'
1321
- str_rep << 'Monthly '
1322
- when '2'
1323
- str_rep << 'Yearly '
1324
- when '3'
1325
- str_rep << 'Each ' << d['DAYS'] << ' hours'
1326
- end
1327
-
1328
- if d['REPEAT'] != '3'
1329
- str_rep << d['DAYS']
1330
- end
1331
- end
1332
- str_rep unless d.nil?
1333
- end
1334
-
1335
- column :END, '', :adjust => true do |d|
1336
- str_end = ''
1337
- if !d.nil? && d.key?('END_TYPE')
1338
- case d['END_TYPE']
1339
- when '0'
1340
- str_end << 'None'
1341
- when '1'
1342
- str_end << 'After ' << d['END_VALUE'] << ' times'
1343
- when '2'
1344
- str_end << 'On ' << \
1345
- OpenNebulaHelper.time_to_str(d['END_VALUE'], false, false, true)
1346
- end
1347
- end
1348
- str_end unless d.nil?
1349
- end
1350
- column :STATUS, '', :left, :size => 50 do |d|
1351
- if d['DONE'] && !d['REPEAT']
1352
- "Done on #{OpenNebulaHelper.time_to_str(d['DONE'], false)}"
1353
- elsif d['MESSAGE']
1354
- "Error! #{d['MESSAGE']}"
1355
- else
1356
- t1 = Time.now
1357
- t2 = d['TIME'].to_i
1358
- t2 += vm['STIME'].to_i unless d['TIME'] =~ /^[0-9].*/
1359
-
1360
- t2 = Time.at(t2)
1361
-
1362
- days = ((t2 - t1) / (24 * 3600)).round(2)
1363
- hours = ((t2 - t1) / 3600).round(2)
1364
- minutes = ((t2 - t1) / 60).round(2)
1365
-
1366
- if days > 1
1367
- "Next in #{days} days"
1368
- elsif days <= 1 && hours > 1
1369
- "Next in #{hours} hours"
1370
- elsif minutes > 0
1371
- "Next in #{minutes} minutes"
1372
- else
1373
- 'Overdue!'
1374
- end
1375
- end
1376
- end
1377
- end.show([vm_hash['VM']['TEMPLATE']['SCHED_ACTION']].flatten,
1378
- {})
1196
+ table = OpenNebulaHelper.scheduled_action_table(self)
1197
+ table.show([vm_hash['VM']['TEMPLATE']['SCHED_ACTION']].flatten, {})
1379
1198
  end
1380
1199
 
1381
1200
  if !options[:all]
@@ -81,6 +81,21 @@ class OneVMGroupHelper < OpenNebulaHelper::OneHelper
81
81
  table
82
82
  end
83
83
 
84
+ def retrieve_role_id(vmg_id, id)
85
+ return [0, id.to_i] if id =~ /\A\d+\z/
86
+
87
+ puts vmg_id
88
+ vmg = retrieve_resource(vmg_id)
89
+ vmg.info
90
+
91
+ ids = vmg.retrieve_elements("ROLES/ROLE[NAME='#{id}']/ID")
92
+
93
+ return [-1, "#{id} not found or duplicated"] \
94
+ if ids.nil? || ids.size > 1
95
+
96
+ [0, ids[0].to_i]
97
+ end
98
+
84
99
  private
85
100
 
86
101
  def factory(id=nil)