diff --git a/include/ScheduledAction.h b/include/ScheduledAction.h index 2cff28598b..a6504d52aa 100644 --- a/include/ScheduledAction.h +++ b/include/ScheduledAction.h @@ -99,7 +99,13 @@ public: int parse(std::string& error, bool clean); /** - * @param stime time when the time was started for relative time specs + * @param stime time when the VM was started for relative time specs + * @return action execution time. Returns -1 on error + */ + time_t get_time(time_t stime); + + /** + * @param stime time when the VM was started for relative time specs * @return true if the action needs to be executed. */ bool is_due(time_t stime); diff --git a/src/scheduler/src/sched/Scheduler.cc b/src/scheduler/src/sched/Scheduler.cc index 4435b5a723..b85788b442 100644 --- a/src/scheduler/src/sched/Scheduler.cc +++ b/src/scheduler/src/sched/Scheduler.cc @@ -1693,80 +1693,96 @@ int Scheduler::do_scheduled_actions() const map vms = vmapool->get_objects(); - string action_st, args_st, error_msg; - - string time_str = one_util::log_time(time(0)); - for (auto vm_it=vms.begin(); vm_it != vms.end(); vm_it++) { vm = static_cast(vm_it->second); SchedActions sas = vm->get_actions(); - for ( auto action : sas) - { - ostringstream oss; + SchedAction* first_action = nullptr; - if (!action->is_due(vm->get_stime())) + for (auto action : sas) + { + auto stime = vm->get_stime(); + if (!action->is_due(stime)) { continue; } - action_st = action->vector_value("ACTION"); - args_st = action->vector_value("ARGS"); - - int rc = VirtualMachineXML::parse_action_name(action_st); - - oss << "Executing action '" << action_st << "' for VM " - << vm->get_oid() << " : "; - - if ( rc != 0 ) + if (!first_action || + first_action->get_time(stime) > action->get_time(stime)) { - error_msg = "This action is not supported."; + // Only first is_due action with lower time will be executed + first_action = action; } - else - { - rc = vmapool->action(vm->get_oid(), action_st, args_st, error_msg); - - if (rc == 0) - { - time_t done_time = time(0); - time_t next_time; - - action->remove("MESSAGE"); - - action->replace("DONE", done_time); - - do - { - next_time = action->next_action(); - } while ( next_time < done_time && next_time != -1 ); - - oss << "Success."; - } - } - - if ( rc != 0 ) - { - ostringstream oss_aux; - - oss_aux << time_str << " : " << error_msg; - - action->replace("MESSAGE", oss_aux.str()); - - oss << "Failure. " << error_msg; - } - - if (!vm->update_sched_action(action)) - { - ostringstream oss; - action->to_xml(oss); - NebulaLog::warn("SCHED", string("Unable to update sched action: ") - + oss.str()); - } - - NebulaLog::log("VM", Log::INFO, oss); } + + if (!first_action) + { + return 0; + } + + ostringstream oss; + + string error_msg; + + string action_st = first_action->vector_value("ACTION"); + + int rc = VirtualMachineXML::parse_action_name(action_st); + + oss << "Executing action '" << action_st << "' for VM " + << vm->get_oid() << " : "; + + if ( rc != 0 ) + { + error_msg = "This action is not supported."; + } + else + { + string args_st = first_action->vector_value("ARGS"); + + rc = vmapool->action(vm->get_oid(), action_st, args_st, error_msg); + + if (rc == 0) + { + time_t done_time = time(0); + time_t next_time; + + first_action->remove("MESSAGE"); + + first_action->replace("DONE", done_time); + + do + { + next_time = first_action->next_action(); + } while ( next_time < done_time && next_time != -1 ); + + oss << "Success."; + } + } + + if ( rc != 0 ) + { + ostringstream oss_aux; + + string time_str = one_util::log_time(time(0)); + + oss_aux << time_str << " : " << error_msg; + + first_action->replace("MESSAGE", oss_aux.str()); + + oss << "Failure. " << error_msg; + } + + if (!vm->update_sched_action(first_action)) + { + ostringstream oss; + first_action->to_xml(oss); + NebulaLog::warn("SCHED", string("Unable to update sched action: ") + + oss.str()); + } + + NebulaLog::log("VM", Log::INFO, oss); } return 0; diff --git a/src/vm_template/ScheduledAction.cc b/src/vm_template/ScheduledAction.cc index 36d6343022..61009a79fb 100644 --- a/src/vm_template/ScheduledAction.cc +++ b/src/vm_template/ScheduledAction.cc @@ -295,15 +295,12 @@ static int days_in_period(SchedAction::Repeat& r, int month, int year) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -bool SchedAction::is_due(time_t stime) +time_t SchedAction::get_time(time_t stime) { - time_t action_time, done_time, origin = 0; - int repeat; + time_t action_time, origin = 0; std::istringstream iss; - bool has_done = vector_value("DONE", done_time) == 0; - bool has_repeat = vector_value("REPEAT", repeat) == 0; std::string action_time_s = vector_value("TIME"); if ( action_time_s[0] == '+' ) @@ -318,13 +315,30 @@ bool SchedAction::is_due(time_t stime) if (iss.fail() || !iss.eof()) { - return false; + return -1; } action_time += origin; - return ((!has_done || done_time < action_time || has_repeat) - && action_time < time(0)); + return action_time; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +bool SchedAction::is_due(time_t stime) +{ + time_t action_time, done_time, origin = 0; + int repeat; + + bool has_done = vector_value("DONE", done_time) == 0; + bool has_repeat = vector_value("REPEAT", repeat) == 0; + + action_time = get_time(stime); + + return (action_time != -1) + && ((!has_done || done_time < action_time || has_repeat) + && action_time < time(0)); } /* -------------------------------------------------------------------------- */