From f84f7522a8cda2b8f7e9e2396084e8d6c29d37d4 Mon Sep 17 00:00:00 2001 From: Alejandro Huertas Date: Tue, 16 Jun 2020 16:59:29 +0200 Subject: [PATCH] F OpenNebula/one#4552: VM Charters CLI support --- src/cli/one_helper/onevm_helper.rb | 116 +++++++++++++++++++++++++---- src/cli/onevm | 80 ++++++++++++++++++++ 2 files changed, 181 insertions(+), 15 deletions(-) diff --git a/src/cli/one_helper/onevm_helper.rb b/src/cli/one_helper/onevm_helper.rb index 77507f5c04..f1b56897af 100644 --- a/src/cli/one_helper/onevm_helper.rb +++ b/src/cli/one_helper/onevm_helper.rb @@ -402,7 +402,7 @@ class OneVMHelper < OpenNebulaHelper::OneHelper table end - def schedule_actions(ids, options, action) + def schedule_actions(ids, options, action, warning = nil) # Verbose by default options[:verbose] = true @@ -453,18 +453,69 @@ class OneVMHelper < OpenNebulaHelper::OneHelper id = ids.max + 1 end + unless options[:schedule].include?('+') + options[:schedule] = options[:schedule].to_i + end + tmp_str = vm.user_template_str tmp_str << "\nSCHED_ACTION = " tmp_str << "[ID = #{id}, ACTION = #{action}, " + tmp_str << "WARNING = #{warning}," if warning tmp_str << "ARGS = \"#{options[:args]}\"," if options[:args] - tmp_str << "TIME = #{options[:schedule].to_i}" + tmp_str << "TIME = #{options[:schedule]}" tmp_str << str_periodic << ']' vm.update(tmp_str) end end + # Update schedule action + # + # @param vm_id [Integer] Virtual Machine ID + # @param action_id [Integer] Sched action ID + # @param file [String] File path with update content + def update_schedule_action(vm_id, action_id, file) + perform_action(vm_id, {}, 'Sched action updated') do |vm| + rc = vm.info + + if OpenNebula.is_error?(rc) + STDERR.puts "Error #{rc.message}" + exit(-1) + end + + xpath = "USER_TEMPLATE/SCHED_ACTION[ID=#{action_id}]" + + unless vm.retrieve_elements(xpath) + STDERR.puts "Sched action #{action_id} not found" + exit(-1) + end + + # Get user information + if file + str = File.read(file) + else + str = OpenNebulaHelper.update_template(vm_id, vm, nil, xpath) + end + + # Delete the current sched action + vm.delete_element(xpath) + + # Add the modified sched action + tmp_str = vm.user_template_str + tmp_str << "\nSCHED_ACTION = [" + tmp_str << str.split("\n").join(',') + tmp_str << ']' + + rc = vm.update(tmp_str) + + if OpenNebula.is_error?(rc) + STDERR.puts "Error updating: #{rc.message}" + exit(-1) + end + end + end + RECOVER_RETRY_STEPS = { :PROLOG_MIGRATE_FAILURE => :migrate, :PROLOG_MIGRATE_POWEROFF_FAILURE => :migrate, @@ -602,6 +653,16 @@ class OneVMHelper < OpenNebulaHelper::OneHelper end end + # Get charters configuration + # + # @return [Array] + # - action + # - time + # - warning + def get_charters + YAML.load_file(self.class.table_conf)[:charters] + end + private def factory(id = nil) @@ -1144,24 +1205,24 @@ class OneVMHelper < OpenNebulaHelper::OneHelper CLIHelper.print_header(str_h1 % 'SCHEDULED ACTIONS', false) CLIHelper::ShowTable.new(nil, self) do - column :ID, '', :size => 2 do |d| + column :ID, '', :adjust => true do |d| d['ID'] unless d.nil? end - column :ACTION, '', :left, :size => 15 do |d| + column :ACTION, '', :adjust => true do |d| d['ACTION'] unless d.nil? end - column :ARGS, '', :left, :size => 15 do |d| + column :ARGS, '', :adjust => true do |d| d['ARGS'] ? d['ARGS'] : '-' end - column :SCHEDULED, '', :size => 12 do |d| + column :SCHEDULED, '', :adjust => true do |d| OpenNebulaHelper.time_to_str(d['TIME'], false) \ unless d.nil? end - column :REPEAT, '', :size => 20 do |d| + column :REPEAT, '', :adjust => true do |d| str_rep = '' if !d.nil? && d.key?('REPEAT') if d['REPEAT'] == '0' @@ -1180,7 +1241,7 @@ class OneVMHelper < OpenNebulaHelper::OneHelper str_rep unless d.nil? end - column :END, '', :size => 20 do |d| + column :END, '', :adjust => true do |d| str_end = '' if !d.nil? && d.key?('END_TYPE') if d['END_TYPE'] == '0' @@ -1197,25 +1258,50 @@ class OneVMHelper < OpenNebulaHelper::OneHelper str_end unless d.nil? end - column :DONE, '', :size => 12 do |d| + column :DONE, '', :adjust => true do |d| OpenNebulaHelper.time_to_str(d['DONE'], false) \ unless d.nil? end - column :MESSAGE, '', :left, :adjust, :size => 35 do |d| - d['MESSAGE'] unless d.nil? + column :MESSAGE, '', :size => 35 do |d| + d['MESSAGE'] ? d['MESSAGE'] : '-' + end + + column :CHARTER, '', :left, :adjust, :size => 15 do |d| + t1 = Time.now + t2 = Time.at(vm['STIME'].to_i + d['TIME'].to_i) + + days = ((t2 - t1) / (24 * 3600)).round(2) + hours = ((t2 - t1) / 3600).round(2) + minutes = ((t2 - t1) / 60).round(2) + + if days > 1 + show = "In #{days} days" + elsif days < 1 && hours > 1 + show = "In #{hours} hours" + elsif minutes > 0 + show = "In #{minutes} minutes" + else + show = 'Already done' + end + + if (t1 - vm['STIME'].to_i).to_i > d['WARNING'].to_i + "#{show} *" + else + show + end end end.show([vm_hash['VM']['USER_TEMPLATE']['SCHED_ACTION']].flatten, {}) end + if !options[:all] + vm.delete_element('/VM/USER_TEMPLATE/SCHED_ACTION') + end + if vm.has_elements?('/VM/USER_TEMPLATE') puts - if !options[:all] - vm.delete_element('/VM/USER_TEMPLATE/SCHED_ACTION') - end - CLIHelper.print_header(str_h1 % 'USER TEMPLATE', false) puts vm.template_like_str('USER_TEMPLATE') end diff --git a/src/cli/onevm b/src/cli/onevm index 2455bbf045..a13a6ce492 100755 --- a/src/cli/onevm +++ b/src/cli/onevm @@ -1297,6 +1297,86 @@ CommandParser::CmdParser.new(ARGV) do end end + ########################### Charters Management ############################ + + create_chart_desc = <<-EOT.unindent + Adds a charter to the VM, these are some consecutive scheduled actions + + You can configure the actions in /etc/one/cli/onevm.yaml + EOT + + command :'create-chart', create_chart_desc, [:range, :vmid_list] do + charters = helper.get_charters + + if charters.nil? + STDERR.puts 'No charters found on configuration file' + exit(-1) + end + + acc_t = 0 + acc_w = 0 + + charters.each do |action, time| + sched = "+#{time[:time].to_i + acc_t}" + + helper.schedule_actions(args[0], + { :schedule => sched }, + action.to_s, + time[:warning][:time] + acc_w) + + acc_t += time[:time].to_i + acc_w += time[:warning][:time].to_i + end + + 0 + end + + delete_chart_desc = <<-EOT.unindent + Deletes a charter from the VM + EOT + + command :'delete-chart', delete_chart_desc, :vmid, :sched_id do + helper.perform_action(args[0], {}, 'Charter deleted') do |vm| + rc = vm.info + + if OpenNebula.is_error?(rc) + STDERR.puts "Error #{rc.message}" + exit(-1) + end + + xpath = "USER_TEMPLATE/SCHED_ACTION[ID=#{args[1]}]" + + unless vm.retrieve_elements(xpath) + STDERR.puts "Sched action #{args[1]} not found" + exit(-1) + end + + vm.delete_element(xpath) + rc = vm.update(vm.user_template_str) + + if OpenNebula.is_error?(rc) + STDERR.puts "Error deleting: #{rc.message}" + exit(-1) + end + end + + 0 + end + + update_chart_desc = <<-EOT.unindent + Updates a charter from a VM + EOT + + command :'update-chart', + update_chart_desc, + :vmid, + :sched_id, + [:file, nil] do + helper.update_schedule_action(args[0], args[1], args[2]) + + 0 + end + # Deprecated commands deprecated_command(:shutdown, 'terminate')