opennebula-cli 6.6.3 → 6.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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)