mirror of
https://github.com/OpenNebula/one.git
synced 2025-01-07 17:17:41 +03:00
Merge branch 'feature-1548'
Conflicts: src/sunstone/public/app/tabs/templates-tab/form-panels/instantiate.js
This commit is contained in:
commit
f9699aed19
203
include/ScheduledAction.h
Normal file
203
include/ScheduledAction.h
Normal file
@ -0,0 +1,203 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2018, OpenNebula Project, OpenNebula Systems */
|
||||
/* */
|
||||
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
|
||||
/* not use this file except in compliance with the License. You may obtain */
|
||||
/* a copy of the License at */
|
||||
/* */
|
||||
/* http://www.apache.org/licenses/LICENSE-2.0 */
|
||||
/* */
|
||||
/* Unless required by applicable law or agreed to in writing, software */
|
||||
/* distributed under the License is distributed on an "AS IS" BASIS, */
|
||||
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
|
||||
/* See the License for the specific language governing permissions and */
|
||||
/* limitations under the License. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef SCHED_ACTION_ATTRIBUTE_H_
|
||||
#define SCHED_ACTION_ATTRIBUTE_H_
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "VirtualMachineAttribute.h"
|
||||
|
||||
/**
|
||||
* The VirtualMachine SCHED_ACTION attribute
|
||||
*/
|
||||
class SchedAction: public VirtualMachineAttribute
|
||||
{
|
||||
public:
|
||||
enum Repeat
|
||||
{
|
||||
NONE = -1,
|
||||
WEEKLY = 0,
|
||||
MONTHLY = 1,
|
||||
YEARLY = 2,
|
||||
HOURLY = 3
|
||||
};
|
||||
|
||||
enum EndOn
|
||||
{
|
||||
NEVER = 0,
|
||||
TIMES = 1,
|
||||
DATE = 2
|
||||
};
|
||||
|
||||
SchedAction(VectorAttribute *va, int id):VirtualMachineAttribute(va, id){};
|
||||
|
||||
virtual ~SchedAction(){};
|
||||
|
||||
/**
|
||||
* Returns the REPEAT value of the SCHED_ACTION
|
||||
* @param r repeat WEEKLY, MONTHLY, YEARLY or HOURLY
|
||||
* @return -1 if REPEAT not found or in wrong format 0 on success
|
||||
*/
|
||||
int repeat(Repeat& r);
|
||||
|
||||
/**
|
||||
* Returns the END_TYPE value of the SCHED_ACTION
|
||||
* @param eo ends on TIMES WEEKLY, MONTHLY, YEARLY or HOURLY
|
||||
* @return -1 if REPEAT not found or in wrong format 0 on success
|
||||
*/
|
||||
int endon(EndOn& eo);
|
||||
|
||||
/**
|
||||
* Parse the DAYS attribute of the sched action
|
||||
* @param d set of days (unique)
|
||||
* @return -1 if not found (d will be empty) 0 otherwise
|
||||
*/
|
||||
int days(std::set<int>& _d);
|
||||
|
||||
/**
|
||||
* This function checks that the DAYS attributes are in range
|
||||
* according to the Repeat value:
|
||||
* @param r repeat type (hourly, weekly...)
|
||||
* @param error in case of error
|
||||
*
|
||||
* @return true if days are in range false (error) if not
|
||||
*/
|
||||
bool days_in_range(Repeat r, std::string& error);
|
||||
|
||||
/**
|
||||
* This function checks that END_VALUE is properly defined for the
|
||||
* associated END_TYPE
|
||||
* @param eo end type (date, times)
|
||||
* @param error in case of error
|
||||
*
|
||||
* @return true if days are in range false (error) if not
|
||||
*/
|
||||
bool ends_in_range(EndOn eo, std::string& error);
|
||||
|
||||
/**
|
||||
* This function parse and checks the sched action attributes: REPEAT, DAYS
|
||||
* , END_TYPE, END_DATE. It also removed DONE and MESSAGE.
|
||||
* @param error
|
||||
* @return 0 if success -1 otherwise
|
||||
*/
|
||||
int parse(std::string& error);
|
||||
|
||||
/**
|
||||
* @return true if the action needs to be executed.
|
||||
*/
|
||||
bool is_due();
|
||||
|
||||
/**
|
||||
* Compute the next action, updating the TIME attribute for this action
|
||||
* @return -1 if action ended 0 otherwise
|
||||
*/
|
||||
int next_action();
|
||||
};
|
||||
|
||||
/**
|
||||
* Set of VirtualMachine SCHED_ACTION attributes
|
||||
*/
|
||||
class SchedActions : public VirtualMachineAttributeSet
|
||||
{
|
||||
public:
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Constructor and Initialization functions */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/**
|
||||
* Creates the SchedAction set from a Template with SCHED_ACTION=[...]
|
||||
* attributes, id's are auto-assigned for internal use
|
||||
* @param tmpl template with DISK
|
||||
*/
|
||||
SchedActions(Template * tmpl): VirtualMachineAttributeSet(false)
|
||||
{
|
||||
std::vector<VectorAttribute *> vas;
|
||||
|
||||
tmpl->get("SCHED_ACTION", vas);
|
||||
|
||||
init_attribute_map("TIME", vas);
|
||||
};
|
||||
|
||||
virtual ~SchedActions(){};
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Parse the ScheduleActions of a template
|
||||
* @param error
|
||||
* @return -1 in case of error 0 otherwise
|
||||
*/
|
||||
int parse(std::string& error)
|
||||
{
|
||||
for ( schedaction_iterator action = begin(); action != end(); ++action)
|
||||
{
|
||||
if ( (*action)->parse(error) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool empty()
|
||||
{
|
||||
return a_set.empty();
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Iterators */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/**
|
||||
* Generic iterator for the SchedActions set.
|
||||
*/
|
||||
class SchedActionIterator : public AttributeIterator
|
||||
{
|
||||
public:
|
||||
SchedActionIterator():AttributeIterator(){};
|
||||
SchedActionIterator(const AttributeIterator& i):AttributeIterator(i){};
|
||||
virtual ~SchedActionIterator(){};
|
||||
|
||||
SchedAction * operator*() const
|
||||
{
|
||||
return static_cast<SchedAction *>(map_it->second);
|
||||
}
|
||||
};
|
||||
|
||||
SchedActionIterator begin()
|
||||
{
|
||||
SchedActionIterator it(ExtendedAttributeSet::begin());
|
||||
return it;
|
||||
}
|
||||
|
||||
SchedActionIterator end()
|
||||
{
|
||||
SchedActionIterator it(ExtendedAttributeSet::end());
|
||||
return it;
|
||||
}
|
||||
|
||||
typedef class SchedActionIterator schedaction_iterator;
|
||||
|
||||
protected:
|
||||
VirtualMachineAttribute * attribute_factory(VectorAttribute * va,
|
||||
int id) const
|
||||
{
|
||||
return new SchedAction(va, id);
|
||||
};
|
||||
};
|
||||
|
||||
#endif /*SCHED_ACTION_ATTRIBUTE_H_*/
|
||||
|
@ -170,7 +170,7 @@ private:
|
||||
/**
|
||||
* This method removes sched_action DONE/MESSAGE attributes
|
||||
*/
|
||||
void parse_sched_action();
|
||||
int parse_sched_action(string& error_str);
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -828,15 +828,31 @@ EOT
|
||||
end
|
||||
end
|
||||
|
||||
def OpenNebulaHelper.time_to_str(time, print_seconds=true)
|
||||
def OpenNebulaHelper.time_to_str(time, print_seconds=true, print_hours=true, print_years=false)
|
||||
value=time.to_i
|
||||
if value==0
|
||||
value='-'
|
||||
else
|
||||
if print_seconds
|
||||
value=Time.at(value).strftime("%m/%d %H:%M:%S")
|
||||
if print_hours
|
||||
if print_seconds
|
||||
if print_years
|
||||
value=Time.at(value).strftime("%m/%d/%y %H:%M:%S")
|
||||
else
|
||||
value=Time.at(value).strftime("%m/%d %H:%M:%S")
|
||||
end
|
||||
else
|
||||
if print_years
|
||||
value=Time.at(value).strftime("%m/%d/%y %H:%M")
|
||||
else
|
||||
value=Time.at(value).strftime("%m/%d %H:%M")
|
||||
end
|
||||
end
|
||||
else
|
||||
value=Time.at(value).strftime("%m/%d %H:%M")
|
||||
if print_years
|
||||
value=Time.at(value).strftime("%m/%d/%y")
|
||||
else
|
||||
value=Time.at(value).strftime("%m/%d")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -114,6 +114,45 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
|
||||
:format => Time
|
||||
}
|
||||
|
||||
WEEKLY = {
|
||||
:name => "weekly",
|
||||
:large => "--weekly days",
|
||||
:description => "Schedules this action to be executed after" \
|
||||
"the given time. For example: onevm resume 0 --schedule \"09/23 14:15\"",
|
||||
:format => String
|
||||
}
|
||||
|
||||
MONTHLY = {
|
||||
:name => "monthly",
|
||||
:large => "--monthly days",
|
||||
:description => "Schedules this action to be executed after" \
|
||||
"the given time. For example: onevm resume 0 --schedule \"09/23 14:15\"",
|
||||
:format => String
|
||||
}
|
||||
|
||||
YEARLY = {
|
||||
:name => "yearly",
|
||||
:large => "--yearly days",
|
||||
:description => "Schedules this action to be executed after" \
|
||||
"the given time. For example: onevm resume 0 --schedule \"09/23 14:15\"",
|
||||
:format => String
|
||||
}
|
||||
|
||||
HOURLY = {
|
||||
:name => "hourly",
|
||||
:large => "--hourly hour",
|
||||
:description => "Schedules this action to be executed after" \
|
||||
"the given time. For example: onevm resume 0 --schedule \"09/23 14:15\"",
|
||||
:format => Numeric
|
||||
}
|
||||
|
||||
END_TIME = {
|
||||
:name => "end",
|
||||
:large => "--end number|TIME",
|
||||
:description => "----",
|
||||
:format => String
|
||||
}
|
||||
|
||||
ALL_TEMPLATE = {
|
||||
:name => "all",
|
||||
:large => "--all",
|
||||
@ -314,6 +353,31 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
|
||||
ids, options,
|
||||
"#{action} scheduled at #{options[:schedule]}") do |vm|
|
||||
|
||||
str_periodic = ""
|
||||
|
||||
if options.key?(:weekly)
|
||||
str_periodic << ", REPEAT = 0, DAYS = \"#{options[:weekly]}\""
|
||||
elsif options.key?(:monthly)
|
||||
str_periodic << ", REPEAT = 1, DAYS = \"#{options[:monthly]}\""
|
||||
elsif options.key?(:yearly)
|
||||
str_periodic << ", REPEAT = 2, DAYS = \"#{options[:yearly]}\""
|
||||
elsif options.key?(:hourly)
|
||||
str_periodic << ", REPEAT = 3, DAYS = \"#{options[:hourly].to_s}\""
|
||||
end
|
||||
|
||||
if options.key?(:end)
|
||||
begin
|
||||
end_date = Date.parse(options[:end])
|
||||
str_periodic << ", END_TYPE = 2, END_VALUE = #{end_date.to_time.to_i}"
|
||||
rescue ArgumentError
|
||||
if options[:end].to_i > 0
|
||||
str_periodic << ", END_TYPE = 1, END_VALUE = #{options[:end].to_i}"
|
||||
end
|
||||
end
|
||||
elsif str_periodic != ""
|
||||
str_periodic << ", END_TYPE = 0"
|
||||
end
|
||||
|
||||
rc = vm.info
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
@ -331,7 +395,7 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
|
||||
|
||||
tmp_str = vm.user_template_str
|
||||
|
||||
tmp_str << "\nSCHED_ACTION = [ID = #{id}, ACTION = #{action}, TIME = #{options[:schedule].to_i}]"
|
||||
tmp_str << "\nSCHED_ACTION = [ID = #{id}, ACTION = #{action}, TIME = #{options[:schedule].to_i}" << str_periodic << "]"
|
||||
|
||||
vm.update(tmp_str)
|
||||
end
|
||||
@ -998,6 +1062,39 @@ in the frontend machine.
|
||||
OpenNebulaHelper.time_to_str(d["TIME"], false) if !d.nil?
|
||||
end
|
||||
|
||||
column :"REPEAT", "", :size=>20 do |d|
|
||||
str_rep = ""
|
||||
if !d.nil? && d.key?("REPEAT")
|
||||
if d["REPEAT"] == "0"
|
||||
str_rep << "Weekly "
|
||||
elsif d["REPEAT"] == "1"
|
||||
str_rep << "Monthly "
|
||||
elsif d["REPEAT"] == "2"
|
||||
str_rep << "Yearly "
|
||||
elsif d["REPEAT"] == "3"
|
||||
str_rep << "Each " << d['DAYS'] << " hours"
|
||||
end
|
||||
if d["REPEAT"] != "3"
|
||||
str_rep << d["DAYS"]
|
||||
end
|
||||
end
|
||||
str_rep if !d.nil?
|
||||
end
|
||||
|
||||
column :"END", "", :size=>20 do |d|
|
||||
str_end = ""
|
||||
if !d.nil? && d.key?("END_TYPE")
|
||||
if d["END_TYPE"] == "0"
|
||||
str_end << "None"
|
||||
elsif d["END_TYPE"] == "1"
|
||||
str_end << "After " << d["END_VALUE"] << " times"
|
||||
elsif d["END_TYPE"] == "2"
|
||||
str_end << "On " << OpenNebulaHelper.time_to_str(d["END_VALUE"], false, false, true)
|
||||
end
|
||||
end
|
||||
str_end if !d.nil?
|
||||
end
|
||||
|
||||
column :"DONE", "", :size=>12 do |d|
|
||||
OpenNebulaHelper.time_to_str(d["DONE"], false) if !d.nil?
|
||||
end
|
||||
|
@ -316,7 +316,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
EOT
|
||||
|
||||
command :hold, hold_desc, [:range,:vmid_list],
|
||||
:options => [OneVMHelper::SCHEDULE] do
|
||||
:options => [OneVMHelper::SCHEDULE, OneVMHelper::WEEKLY, OneVMHelper::MONTHLY, OneVMHelper::YEARLY, OneVMHelper::HOURLY, OneVMHelper::END_TIME] do
|
||||
if (!options[:schedule].nil?)
|
||||
helper.schedule_actions(args[0], options, @comm_name)
|
||||
else
|
||||
@ -333,7 +333,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
EOT
|
||||
|
||||
command :release, release_desc, [:range,:vmid_list],
|
||||
:options => [OneVMHelper::SCHEDULE] do
|
||||
:options => [OneVMHelper::SCHEDULE, OneVMHelper::WEEKLY, OneVMHelper::MONTHLY, OneVMHelper::YEARLY, OneVMHelper::HOURLY, OneVMHelper::END_TIME] do
|
||||
if (!options[:schedule].nil?)
|
||||
helper.schedule_actions(args[0], options, @comm_name)
|
||||
else
|
||||
@ -391,7 +391,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
EOT
|
||||
|
||||
command :terminate, terminate_desc, [:range,:vmid_list],
|
||||
:options => [OneVMHelper::SCHEDULE, OneVMHelper::HARD] do
|
||||
:options => [OneVMHelper::SCHEDULE, OneVMHelper::WEEKLY, OneVMHelper::MONTHLY, OneVMHelper::YEARLY, OneVMHelper::HOURLY, OneVMHelper::END_TIME, OneVMHelper::HARD] do
|
||||
|
||||
command_name='terminate'
|
||||
command_name<<'-hard' if options[:hard]
|
||||
@ -414,7 +414,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
EOT
|
||||
|
||||
command :undeploy, undeploy_desc, [:range,:vmid_list],
|
||||
:options => [OneVMHelper::SCHEDULE, OneVMHelper::HARD] do
|
||||
:options => [OneVMHelper::SCHEDULE, OneVMHelper::WEEKLY, OneVMHelper::MONTHLY, OneVMHelper::YEARLY, OneVMHelper::HOURLY, OneVMHelper::END_TIME, OneVMHelper::HARD] do
|
||||
|
||||
command_name='undeploy'
|
||||
command_name<<'-hard' if options[:hard]
|
||||
@ -436,7 +436,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
EOT
|
||||
|
||||
command :poweroff, poweroff_desc, [:range,:vmid_list],
|
||||
:options => [OneVMHelper::SCHEDULE, OneVMHelper::HARD] do
|
||||
:options => [OneVMHelper::SCHEDULE, OneVMHelper::WEEKLY, OneVMHelper::MONTHLY, OneVMHelper::YEARLY, OneVMHelper::HOURLY, OneVMHelper::END_TIME, OneVMHelper::HARD] do
|
||||
|
||||
command_name='poweroff'
|
||||
command_name<<'-hard' if options[:hard]
|
||||
@ -460,7 +460,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
EOT
|
||||
|
||||
command :reboot, reboot_desc, [:range,:vmid_list],
|
||||
:options => [OneVMHelper::SCHEDULE, OneVMHelper::HARD] do
|
||||
:options => [OneVMHelper::SCHEDULE, OneVMHelper::WEEKLY, OneVMHelper::MONTHLY, OneVMHelper::YEARLY, OneVMHelper::HOURLY, OneVMHelper::END_TIME, OneVMHelper::HARD] do
|
||||
|
||||
command_name='reboot'
|
||||
command_name<<'-hard' if options[:hard]
|
||||
@ -525,7 +525,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
EOT
|
||||
|
||||
command :stop, stop_desc, [:range,:vmid_list],
|
||||
:options => [OneVMHelper::SCHEDULE] do
|
||||
:options => [OneVMHelper::SCHEDULE, OneVMHelper::WEEKLY, OneVMHelper::MONTHLY, OneVMHelper::YEARLY, OneVMHelper::HOURLY, OneVMHelper::END_TIME] do
|
||||
if (!options[:schedule].nil?)
|
||||
helper.schedule_actions(args[0], options, @comm_name)
|
||||
else
|
||||
@ -545,7 +545,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
EOT
|
||||
|
||||
command :suspend, suspend_desc, [:range,:vmid_list],
|
||||
:options => [OneVMHelper::SCHEDULE] do
|
||||
:options => [OneVMHelper::SCHEDULE, OneVMHelper::WEEKLY, OneVMHelper::MONTHLY, OneVMHelper::YEARLY, OneVMHelper::HOURLY, OneVMHelper::END_TIME] do
|
||||
if (!options[:schedule].nil?)
|
||||
helper.schedule_actions(args[0], options, @comm_name)
|
||||
else
|
||||
@ -562,7 +562,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
EOT
|
||||
|
||||
command :resume, resume_desc, [:range,:vmid_list],
|
||||
:options => [OneVMHelper::SCHEDULE] do
|
||||
:options => [OneVMHelper::SCHEDULE, OneVMHelper::WEEKLY, OneVMHelper::MONTHLY, OneVMHelper::YEARLY, OneVMHelper::HOURLY, OneVMHelper::END_TIME] do
|
||||
if (!options[:schedule].nil?)
|
||||
helper.schedule_actions(args[0], options, @comm_name)
|
||||
else
|
||||
@ -804,7 +804,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
EOT
|
||||
|
||||
command :"snapshot-create", snapshot_create_desc, [:range,:vmid_list],
|
||||
[:name, nil], :options => [OneVMHelper::SCHEDULE] do
|
||||
[:name, nil], :options => [OneVMHelper::SCHEDULE, OneVMHelper::WEEKLY, OneVMHelper::MONTHLY, OneVMHelper::YEARLY, OneVMHelper::HOURLY, OneVMHelper::END_TIME] do
|
||||
|
||||
if (!options[:schedule].nil?)
|
||||
helper.schedule_actions(args[0], options, @comm_name)
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "Resource.h"
|
||||
|
||||
#include "VirtualMachineTemplate.h"
|
||||
#include "ScheduledAction.h"
|
||||
|
||||
class ImageDatastorePoolXML;
|
||||
|
||||
@ -325,11 +326,9 @@ public:
|
||||
*
|
||||
* @param attributes to hold the VM actions
|
||||
*/
|
||||
void get_actions(vector<Attribute *>& attributes) const
|
||||
SchedActions * get_actions()
|
||||
{
|
||||
attributes.clear();
|
||||
|
||||
user_template->remove("SCHED_ACTION", attributes);
|
||||
return new SchedActions(user_template);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "VirtualMachineXML.h"
|
||||
#include "ScheduledAction.h"
|
||||
#include "DatastoreXML.h"
|
||||
#include "DatastorePoolXML.h"
|
||||
#include "NebulaUtil.h"
|
||||
@ -507,3 +508,6 @@ bool VirtualMachineXML::is_only_public_cloud() const
|
||||
{
|
||||
return only_public_cloud;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -39,6 +39,7 @@ sched_env.Prepend(LIBS=[
|
||||
'nebula_common',
|
||||
'nebula_core',
|
||||
'nebula_template',
|
||||
'nebula_vmtemplate',
|
||||
'nebula_vm',
|
||||
'nebula_host',
|
||||
'nebula_parsers',
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "NebulaLog.h"
|
||||
#include "PoolObjectAuth.h"
|
||||
#include "NebulaUtil.h"
|
||||
#include "ScheduledAction.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -1381,86 +1382,74 @@ int Scheduler::do_scheduled_actions()
|
||||
const map<int, ObjectXML*> vms = vmapool->get_objects();
|
||||
map<int, ObjectXML*>::const_iterator vm_it;
|
||||
|
||||
vector<Attribute *> attributes;
|
||||
vector<Attribute *>::iterator it;
|
||||
|
||||
VectorAttribute* vatt;
|
||||
|
||||
int action_time;
|
||||
int done_time;
|
||||
int has_time;
|
||||
int has_done;
|
||||
|
||||
string action_st, error_msg;
|
||||
|
||||
time_t the_time = time(0);
|
||||
string time_str = one_util::log_time(the_time);
|
||||
string time_str = one_util::log_time(time(0));
|
||||
|
||||
for (vm_it=vms.begin(); vm_it != vms.end(); vm_it++)
|
||||
{
|
||||
vm = static_cast<VirtualMachineXML*>(vm_it->second);
|
||||
SchedActions::schedaction_iterator action;
|
||||
|
||||
vm->get_actions(attributes);
|
||||
vm = static_cast<VirtualMachineXML *>(vm_it->second);
|
||||
|
||||
// TODO: Sort actions by TIME
|
||||
for (it=attributes.begin(); it != attributes.end(); it++)
|
||||
SchedActions * sas = vm->get_actions();
|
||||
|
||||
for ( action = sas->begin(); action != sas->end(); ++action)
|
||||
{
|
||||
vatt = dynamic_cast<VectorAttribute*>(*it);
|
||||
ostringstream oss;
|
||||
|
||||
if (vatt == 0)
|
||||
if (!(*action)->is_due())
|
||||
{
|
||||
delete *it;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
has_time = vatt->vector_value("TIME", action_time);
|
||||
has_done = vatt->vector_value("DONE", done_time);
|
||||
action_st = vatt->vector_value("ACTION");
|
||||
action_st = (*action)->vector_value("ACTION");
|
||||
|
||||
if (has_time == 0 && has_done == -1 && action_time < the_time)
|
||||
int rc = VirtualMachineXML::parse_action_name(action_st);
|
||||
|
||||
oss << "Executing action '" << action_st << "' for VM "
|
||||
<< vm->get_oid() << " : ";
|
||||
|
||||
if ( rc != 0 )
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
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
|
||||
{
|
||||
rc = vmapool->action(vm->get_oid(), action_st, error_msg);
|
||||
}
|
||||
error_msg = "This action is not supported.";
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = vmapool->action(vm->get_oid(), action_st, error_msg);
|
||||
|
||||
if (rc == 0)
|
||||
{
|
||||
vatt->remove("MESSAGE");
|
||||
vatt->replace("DONE", static_cast<int>(the_time));
|
||||
(*action)->remove("MESSAGE");
|
||||
|
||||
(*action)->replace("DONE", time(0));
|
||||
|
||||
(*action)->next_action();
|
||||
|
||||
oss << "Success.";
|
||||
}
|
||||
else
|
||||
{
|
||||
ostringstream oss_aux;
|
||||
|
||||
oss_aux << time_str << " : " << error_msg;
|
||||
|
||||
vatt->replace("MESSAGE", oss_aux.str());
|
||||
|
||||
oss << "Failure. " << error_msg;
|
||||
}
|
||||
|
||||
NebulaLog::log("VM", Log::INFO, oss);
|
||||
}
|
||||
|
||||
vm->set_attribute(vatt);
|
||||
if ( rc != 0 )
|
||||
{
|
||||
ostringstream oss_aux;
|
||||
|
||||
oss_aux << time_str << " : " << error_msg;
|
||||
|
||||
(*action)->replace("MESSAGE", oss_aux.str());
|
||||
|
||||
oss << "Failure. " << error_msg;
|
||||
}
|
||||
|
||||
NebulaLog::log("VM", Log::INFO, oss);
|
||||
}
|
||||
|
||||
vmpool->update(vm);
|
||||
if ( sas->empty() != 0 ) //Do not update VMs without SCHED_ACTION
|
||||
{
|
||||
vmpool->update(vm);
|
||||
}
|
||||
|
||||
delete sas;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -20,6 +20,7 @@ define(function(require) {
|
||||
*/
|
||||
|
||||
var Config = require('sunstone-config');
|
||||
var ScheduleActions = require('utils/schedule_action');
|
||||
var Locale = require('utils/locale');
|
||||
var Tips = require('utils/tips');
|
||||
var WizardFields = require('utils/wizard-fields');
|
||||
@ -59,7 +60,9 @@ define(function(require) {
|
||||
return WizardTab;
|
||||
|
||||
function _html() {
|
||||
return TemplateHTML();
|
||||
return TemplateHTML({
|
||||
'table_sched_actions': ScheduleActions.htmlTable("temp")
|
||||
});
|
||||
}
|
||||
|
||||
function _onShow(context, panelForm) {
|
||||
@ -68,103 +71,39 @@ define(function(require) {
|
||||
function _setup(context) {
|
||||
var that = this;
|
||||
var actions = ["terminate", "terminate-hard", "hold", "release", "stop", "suspend", "resume", "reboot", "reboot-hard", "poweroff", "poweroff-hard", "undeploy", "undeploy-hard", "snapshot-create"];
|
||||
|
||||
context.off('click', '#add_scheduling_temp_action');
|
||||
context.on('click', '#add_scheduling_temp_action', function() {
|
||||
$("#add_scheduling_temp_action", context).attr("disabled", "disabled");
|
||||
var html = '<tr>\
|
||||
<td></td>\
|
||||
<td>\
|
||||
<select id="select_new_action" class="select_new_action" name="select_action">';
|
||||
$.each(actions, function(key, action){
|
||||
var actionAux = action.replace("-", "_");
|
||||
if (Config.isTabActionEnabled("vms-tab", "VM." + actionAux)){
|
||||
html += '<option value="' + action + '">' + Locale.tr(action) + '</option>';
|
||||
}
|
||||
});
|
||||
html += '</select>\
|
||||
</td>\
|
||||
<td>\
|
||||
<input id="date_input" type="date" placeholder="2013/12/30"/>\
|
||||
<input id="time_input" type="time" placeholder="12:30"/>\
|
||||
</td>\
|
||||
<td>\
|
||||
<button id="add_temp_action_json" class="button small secondary radius" >' + Locale.tr("Add") + '</button>\
|
||||
</td>\
|
||||
<td colspan=2></td>\
|
||||
</tr>';
|
||||
$("#scheduling_temp_actions_table").append(html);
|
||||
ScheduleActions.htmlNewAction(actions, context, "temp");
|
||||
ScheduleActions.setup(context)
|
||||
return false;
|
||||
});
|
||||
|
||||
context.off("click", "#add_temp_action_json");
|
||||
context.on("click" , "#add_temp_action_json", function(){
|
||||
var date_input_value = $("#date_input", context).val();
|
||||
var time_input_value = $("#time_input", context).val();
|
||||
|
||||
if (date_input_value == "" || time_input_value == ""){
|
||||
return false;
|
||||
var sched_action = ScheduleActions.retrieveNewAction(context);
|
||||
if (sched_action != false) {
|
||||
$("#sched_temp_actions_body").append(ScheduleActions.fromJSONtoActionsTable(sched_action));
|
||||
}
|
||||
|
||||
var time_value = date_input_value + ' ' + time_input_value;
|
||||
var epoch_str = new Date(time_value);
|
||||
var time = parseInt(epoch_str.getTime()) / 1000;
|
||||
|
||||
var new_action = $("#select_new_action", context).val();
|
||||
var sched_action = {};
|
||||
sched_action.ACTION = new_action;
|
||||
sched_action.TIME = time;
|
||||
|
||||
$(this).parents('tr').remove();
|
||||
$("#add_scheduling_temp_action", context).removeAttr("disabled");
|
||||
|
||||
$("#sched_temp_actions_body").append(Actions.fromJSONtoActionsTable(sched_action));
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
context.on("focusout" , "#time_input", function(){
|
||||
$("#time_input").removeAttr("data-invalid");
|
||||
$("#time_input").removeAttr("class");
|
||||
context.off("click", ".remove_action_x");
|
||||
context.on("click", ".remove_action_x", function () {
|
||||
$(this).parents('tr').remove();
|
||||
});
|
||||
|
||||
context.off("click", ".remove_action_x");
|
||||
context.on("click", ".remove_action_x", function(){
|
||||
$(this).parents('tr').remove();
|
||||
});
|
||||
}
|
||||
|
||||
function _retrieve(context) {
|
||||
var templateJSON = {};
|
||||
var actionsJSON = [];
|
||||
|
||||
$("#scheduling_temp_actions_table tbody tr").each(function(index){
|
||||
var first = $(this).children("td")[0];
|
||||
if(!$('select', first).html()){
|
||||
var actionJSON = {};
|
||||
actionJSON.ID = index;
|
||||
$(this).children("td").each(function(index2){
|
||||
if(index2 == 0)
|
||||
actionJSON.ACTION = $(this).text();
|
||||
else if (index2 == 1){
|
||||
var pretty_time = $(this).text();
|
||||
pretty_time = pretty_time.split(' ');
|
||||
var date = Actions.convertDate(pretty_time[1]);
|
||||
var time_value = date + ' ' + pretty_time[0];
|
||||
var epoch_str = new Date(time_value);
|
||||
var time = parseInt(epoch_str.getTime()) / 1000;
|
||||
actionJSON.TIME = time;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!$.isEmptyObject(actionJSON)) {actionsJSON.push(actionJSON)};
|
||||
});
|
||||
|
||||
templateJSON['SCHED_ACTION'] = actionsJSON;
|
||||
templateJSON['SCHED_ACTION'] = ScheduleActions.retrieve(context);
|
||||
return templateJSON;
|
||||
}
|
||||
|
||||
function _fill(context, templateJSON) {
|
||||
var actions = Actions.fromJSONtoActionsTable(templateJSON.SCHED_ACTION);
|
||||
var actions = ScheduleActions.fromJSONtoActionsTable(templateJSON.SCHED_ACTION);
|
||||
$("#sched_temp_actions_body").append(actions);
|
||||
delete templateJSON['SCHED_ACTION'];
|
||||
}
|
||||
|
@ -1,15 +1,5 @@
|
||||
<div class="row">
|
||||
<div class="large-12 columns">
|
||||
<table id="scheduling_temp_actions_table" class="info_table dataTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th> {{tr "Action"}} </th>
|
||||
<th> {{tr "Time"}} </th>
|
||||
<th colspan=""> {{tr "Actions"}} </th>
|
||||
<th><button id="add_scheduling_temp_action" class="button small success right radius"> {{tr "Add action"}} </button></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="sched_temp_actions_body"></tbody>
|
||||
</table>
|
||||
{{{table_sched_actions}}}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -43,7 +43,7 @@ define(function(require) {
|
||||
var Humanize = require("utils/humanize");
|
||||
var TemplateUtils = require("utils/template-utils");
|
||||
var UniqueId = require("utils/unique-id");
|
||||
var Actions = require("utils/actions");
|
||||
var ScheduleActions = require("utils/schedule_action");
|
||||
|
||||
/*
|
||||
CONSTANTS
|
||||
@ -128,54 +128,20 @@ define(function(require) {
|
||||
context.on("click", "#add_scheduling_inst_action", function() {
|
||||
var actions = ["terminate", "terminate-hard", "hold", "release", "stop", "suspend", "resume", "reboot", "reboot-hard", "poweroff", "poweroff-hard", "undeploy", "undeploy-hard", "snapshot-create"];
|
||||
$("#add_scheduling_inst_action", context).attr("disabled", "disabled");
|
||||
var html = "<tr>\
|
||||
<td></td>\
|
||||
<td>\
|
||||
<select id=\"select_new_action\" class=\"select_new_action\" name=\"select_action\">";
|
||||
$.each(actions, function(key, action){
|
||||
var actionAux = action.replace("-", "_");
|
||||
if (Config.isTabActionEnabled("vms-tab", "VM." + actionAux)){
|
||||
html += "<option value=\"" + action + "\">" + Locale.tr(action) + "</option>";
|
||||
}
|
||||
});
|
||||
html += "</select>\
|
||||
</td>\
|
||||
<td>\
|
||||
<input id=\"date_input\" type=\"date\" placeholder=\"2013/12/30\"/>\
|
||||
<input id=\"time_input\" type=\"time\" placeholder=\"12:30\"/>\
|
||||
</td>\
|
||||
<td>\
|
||||
<button id=\"add_inst_action_json\" class=\"button small secondary radius\" >" + Locale.tr("Add") + "</button>\
|
||||
</td>\
|
||||
<td colspan=2></td>\
|
||||
</tr>";
|
||||
$("#scheduling_inst_actions_table").append(html);
|
||||
|
||||
ScheduleActions.htmlNewAction(actions, context, "inst");
|
||||
ScheduleActions.setup(context)
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
context.off("click", "#add_inst_action_json");
|
||||
context.on("click" , "#add_inst_action_json", function(){
|
||||
var date_input_value = $("#date_input", context).val();
|
||||
var time_input_value = $("#time_input", context).val();
|
||||
|
||||
if (date_input_value == "" || time_input_value == ""){
|
||||
return false;
|
||||
var sched_action = ScheduleActions.retrieveNewAction(context);
|
||||
if (sched_action != false) {
|
||||
$("#sched_inst_actions_body").append(ScheduleActions.fromJSONtoActionsTable(sched_action));
|
||||
}
|
||||
|
||||
var time_value = date_input_value + " " + time_input_value;
|
||||
var epoch_str = new Date(time_value);
|
||||
var time = parseInt(epoch_str.getTime()) / 1000;
|
||||
|
||||
var new_action = $("#select_new_action", context).val();
|
||||
var sched_action = {};
|
||||
sched_action.ACTION = new_action;
|
||||
sched_action.TIME = time;
|
||||
|
||||
$(this).parents("tr").remove();
|
||||
$("#add_scheduling_inst_action", context).removeAttr("disabled");
|
||||
|
||||
$("#sched_inst_actions_body").append(Actions.fromJSONtoActionsTable(sched_action));
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
@ -338,32 +304,11 @@ define(function(require) {
|
||||
}
|
||||
}
|
||||
|
||||
var templateJSON = {};
|
||||
var actionsJSON = [];
|
||||
tmp_json['SCHED_ACTION'] = ScheduleActions.retrieve(context);
|
||||
|
||||
$("#scheduling_inst_actions_table tbody tr").each(function(index){
|
||||
var first = $(this).children("td")[0];
|
||||
if(!$("select", first).html()){
|
||||
var actionJSON = {};
|
||||
actionJSON.ID = index;
|
||||
$(this).children("td").each(function(index2){
|
||||
if(index2 == 0)
|
||||
actionJSON.ACTION = $(this).text();
|
||||
else if (index2 == 1){
|
||||
var pretty_time = $(this).text();
|
||||
pretty_time = pretty_time.split(" ");
|
||||
var date = Actions.convertDate(pretty_time[1]);
|
||||
var time_value = date + " " + pretty_time[0];
|
||||
var epoch_str = new Date(time_value);
|
||||
var time = parseInt(epoch_str.getTime()) / 1000;
|
||||
actionJSON.TIME = time;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!$.isEmptyObject(actionJSON)) {actionsJSON.push(actionJSON);};
|
||||
});
|
||||
|
||||
tmp_json["SCHED_ACTION"] = actionsJSON;
|
||||
if (tmp_json['SCHED_ACTION'].length == 0) {
|
||||
delete tmp_json['SCHED_ACTION'];
|
||||
}
|
||||
|
||||
capacityContext = $(".capacityContext" + template_id, context);
|
||||
$.extend(tmp_json, CapacityInputs.retrieveChanges(capacityContext));
|
||||
@ -442,7 +387,8 @@ define(function(require) {
|
||||
hostsDatatable: that.hostsTable.dataTableHTML,
|
||||
dsDatatable: that.datastoresTable.dataTableHTML,
|
||||
usersDatatable: that.usersTable.dataTableHTML,
|
||||
groupDatatable: that.groupTable.dataTableHTML
|
||||
groupDatatable: that.groupTable.dataTableHTML,
|
||||
table_sched_actions: ScheduleActions.htmlTable("inst")
|
||||
}) );
|
||||
|
||||
$(".provision_host_selector" + template_json.VMTEMPLATE.ID, context).data("hostsTable", that.hostsTable);
|
||||
@ -450,7 +396,7 @@ define(function(require) {
|
||||
$(".provision_uid_selector" + template_json.VMTEMPLATE.ID, context).data("usersTable", that.usersTable);
|
||||
$(".provision_gid_selector" + template_json.VMTEMPLATE.ID, context).data("groupTable", that.groupTable);
|
||||
|
||||
var actions = Actions.fromJSONtoActionsTable(template_json.VMTEMPLATE.TEMPLATE.SCHED_ACTION);
|
||||
var actions = ScheduleActions.fromJSONtoActionsTable(template_json.VMTEMPLATE.TEMPLATE.SCHED_ACTION);
|
||||
$("#sched_inst_actions_body").append(actions);
|
||||
|
||||
var selectOptions = {
|
||||
|
@ -137,17 +137,7 @@
|
||||
<legend>
|
||||
<i class="fas fa-calendar-alt"></i> {{tr "Schedule Actions for VM"}}
|
||||
</legend>
|
||||
<table id="scheduling_inst_actions_table" class="info_table dataTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th> {{tr "Action"}} </th>
|
||||
<th> {{tr "Time"}} </th>
|
||||
<th colspan=""> {{tr "Actions"}} </th>
|
||||
<th><button id="add_scheduling_inst_action" class="button small success right radius"> {{tr "Add action"}} </button></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="sched_inst_actions_body"></tbody>
|
||||
</table>
|
||||
{{{table_sched_actions}}}
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -24,6 +24,7 @@ define(function(require) {
|
||||
var Humanize = require('utils/humanize');
|
||||
var TemplateUtils = require('utils/template-utils');
|
||||
var Config = require('sunstone-config');
|
||||
var ScheduleActions = require('utils/schedule_action');
|
||||
|
||||
/*
|
||||
CONSTANTS
|
||||
@ -62,99 +63,59 @@ define(function(require) {
|
||||
var that = this;
|
||||
var html = '<div class="row">\
|
||||
<div class="large-12 columns">\
|
||||
<table id="scheduling_actions_table" class="info_table dataTable">\
|
||||
<table id="scheduling_vms_actions_table" class="info_table dataTable">\
|
||||
<thead>\
|
||||
<tr>\
|
||||
<th>' + Locale.tr("ID") + '</th>\
|
||||
<th>' + Locale.tr("Action") + '</th>\
|
||||
<th>' + Locale.tr("Time") + '</th>\
|
||||
<th>' + Locale.tr("Rep") + '</th>\
|
||||
<th>' + Locale.tr("End") + '</th>\
|
||||
<th>' + Locale.tr("Done") + '</th>\
|
||||
<th>' + Locale.tr("Message") + '</th>\
|
||||
<th colspan="">' + Locale.tr("Actions") + '</th>\
|
||||
<th><button id="add_scheduling_action" class="button small success right radius" >' + Locale.tr("Add action") + '</button></th>\
|
||||
<th><button id="add_scheduling_vms_action" class="button small success right radius" >' + Locale.tr("Add action") + '</button></th>\
|
||||
</tr>\
|
||||
</thead>' +
|
||||
fromJSONtoActionsTable(that.element.USER_TEMPLATE.SCHED_ACTION) +
|
||||
'</table>\
|
||||
</thead>\
|
||||
<tbody id="sched_vms_actions_body">'+
|
||||
vmsfromJSONtoActionsTable(that.element.USER_TEMPLATE.SCHED_ACTION) +
|
||||
'</tbody>\
|
||||
</table>\
|
||||
</div>\
|
||||
</div>';
|
||||
|
||||
ScheduleActions.htmlTable("vms") //only charge the resource attribute
|
||||
return html;
|
||||
}
|
||||
|
||||
function _setup(context) {
|
||||
var that = this;
|
||||
var actions = ["terminate", "terminate-hard", "hold", "release", "stop", "suspend", "resume", "reboot", "reboot-hard", "poweroff", "poweroff-hard", "undeploy", "undeploy-hard", "snapshot-create"];
|
||||
context.off('click', '#add_scheduling_action');
|
||||
context.on('click', '#add_scheduling_action', function() {
|
||||
$("#add_scheduling_action", context).attr("disabled", "disabled");
|
||||
var html = '<tr>\
|
||||
<td></td>\
|
||||
<td>\
|
||||
<select id="select_new_action" class="select_new_action" name="select_action">';
|
||||
$.each(actions, function(key, action){
|
||||
var actionAux = action.replace("-", "_");
|
||||
if (Config.isTabActionEnabled("vms-tab", "VM." + actionAux)){
|
||||
html += '<option value="' + action + '">' + Locale.tr(action) + '</option>';
|
||||
}
|
||||
});
|
||||
html += '</select>\
|
||||
</td>\
|
||||
<td>\
|
||||
<input id="date_input" type="date" placeholder="2013/12/30"/>\
|
||||
<input id="time_input" type="time" placeholder="12:30"/>\
|
||||
</td>\
|
||||
<td>\
|
||||
<button id="submit_scheduling_action" class="button small secondary radius" >' + Locale.tr("Add") + '</button>\
|
||||
</td>\
|
||||
<td colspan=2></td>\
|
||||
</tr>';
|
||||
$("#scheduling_actions_table").append(html);
|
||||
context.off('click', '#add_scheduling_vms_action');
|
||||
context.on('click', '#add_scheduling_vms_action', function() {
|
||||
$("#add_scheduling_vms_action", context).attr("disabled", "disabled");
|
||||
ScheduleActions.htmlNewAction(actions, context, "vms");
|
||||
ScheduleActions.setup(context)
|
||||
return false;
|
||||
});
|
||||
|
||||
context.off("click", "#submit_scheduling_action");
|
||||
context.on("click", "#submit_scheduling_action", function() {
|
||||
var date_input_value = $("#date_input", context).val();
|
||||
var time_input_value = $("#time_input", context).val();
|
||||
|
||||
if (date_input_value == "" || time_input_value == "")
|
||||
return false;
|
||||
|
||||
var time_value = date_input_value + ' ' + time_input_value
|
||||
|
||||
// Calculate MAX_ID
|
||||
var max_id = -1;
|
||||
|
||||
if (that.element.USER_TEMPLATE.SCHED_ACTION) {
|
||||
if (!that.element.USER_TEMPLATE.SCHED_ACTION.length) {
|
||||
var tmp_element = that.element.USER_TEMPLATE.SCHED_ACTION;
|
||||
that.element.USER_TEMPLATE.SCHED_ACTION = new Array();
|
||||
that.element.USER_TEMPLATE.SCHED_ACTION.push(tmp_element);
|
||||
}
|
||||
|
||||
$.each(that.element.USER_TEMPLATE.SCHED_ACTION, function(i, element) {
|
||||
if (max_id < element.ID)
|
||||
max_id = element.ID
|
||||
})
|
||||
context.off("click", "#add_vms_action_json");
|
||||
context.on("click" , "#add_vms_action_json", function(){
|
||||
var sched_action = ScheduleActions.retrieveNewAction(context);
|
||||
if (sched_action != false) {
|
||||
$("#no_actions_tr", context).remove();
|
||||
$("#sched_vms_actions_body").append(ScheduleActions.fromJSONtoActionsTable(sched_action));
|
||||
} else {
|
||||
that.element.USER_TEMPLATE.SCHED_ACTION = new Array();
|
||||
return false;
|
||||
}
|
||||
|
||||
var new_action = {};
|
||||
new_action.ID = parseInt(max_id) + 1;
|
||||
new_action.ACTION = $("#select_new_action", context).val();
|
||||
var epoch_str = new Date(time_value);
|
||||
|
||||
new_action.TIME = parseInt(epoch_str.getTime()) / 1000;
|
||||
|
||||
that.element.USER_TEMPLATE.SCHED_ACTION.push(new_action);
|
||||
that.element.USER_TEMPLATE.SCHED_ACTION = ScheduleActions.retrieve(context);
|
||||
|
||||
// Let OpenNebula know
|
||||
var template_str = TemplateUtils.templateToString(that.element.USER_TEMPLATE);
|
||||
Sunstone.runAction("VM.update_template", that.element.ID, template_str);
|
||||
|
||||
$("#add_scheduling_action", context).removeAttr("disabled");
|
||||
$("#add_scheduling_vms_action", context).removeAttr("disabled");
|
||||
return false;
|
||||
});
|
||||
|
||||
@ -179,7 +140,7 @@ define(function(require) {
|
||||
}
|
||||
|
||||
// Returns an HTML string with the json keys and values
|
||||
function fromJSONtoActionsTable(actions_array) {
|
||||
function vmsfromJSONtoActionsTable(actions_array) {
|
||||
var str = ""
|
||||
var empty = '\
|
||||
<tr id="no_actions_tr">\
|
||||
@ -201,24 +162,22 @@ define(function(require) {
|
||||
}
|
||||
|
||||
$.each(actions_array, function(index, scheduling_action) {
|
||||
str += fromJSONtoActionRow(scheduling_action);
|
||||
str += "<tr class='tr_action_"+scheduling_action.ID+"' data='" + JSON.stringify(scheduling_action) + "'>";
|
||||
str += '<td class="id_row">' + TemplateUtils.htmlEncode(scheduling_action.ID) + '</td>'
|
||||
var actions = ScheduleActions.fromJSONtoActionsTable([scheduling_action], scheduling_action.ID, true);
|
||||
str += actions;
|
||||
str += vmsfromJSONtoActionRow(scheduling_action);
|
||||
});
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
// Helper for fromJSONtoHTMLTable function
|
||||
function fromJSONtoActionRow(scheduling_action) {
|
||||
function vmsfromJSONtoActionRow(scheduling_action) {
|
||||
var done_str = scheduling_action.DONE ? (Humanize.prettyTime(scheduling_action.DONE)) : "";
|
||||
var message_str = scheduling_action.MESSAGE ? scheduling_action.MESSAGE : "";
|
||||
var time_str = Humanize.prettyTime(scheduling_action.TIME);
|
||||
|
||||
var str = "";
|
||||
str += '<tr class="tr_action_' + scheduling_action.ID + '">\
|
||||
<td class="id_row">' + TemplateUtils.htmlEncode(scheduling_action.ID) + '</td>\
|
||||
<td class="action_row">' + TemplateUtils.htmlEncode(scheduling_action.ACTION) + '</td>\
|
||||
<td nowrap class="time_row">' + time_str + '</td>\
|
||||
<td class="done_row">' + done_str + '</td>\
|
||||
var str = '<td class="done_row">' + done_str + '</td>\
|
||||
<td class="message_row">' + TemplateUtils.htmlEncode(message_str) + '</td>\
|
||||
<td>\
|
||||
<div>\
|
||||
|
@ -62,6 +62,8 @@ define(function(require) {
|
||||
}
|
||||
};
|
||||
|
||||
var week_days_str = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
||||
|
||||
/*
|
||||
CONSTRUCTOR
|
||||
*/
|
||||
@ -80,7 +82,8 @@ define(function(require) {
|
||||
'prettyTimeAgo': _format_date,
|
||||
'prettyTimeDatatable': _prettyTimeDatatable,
|
||||
'lock_to_str': _lock_to_str,
|
||||
'state_lock_to_color': _state_lock_to_color
|
||||
'state_lock_to_color': _state_lock_to_color,
|
||||
'week_days': _week_days
|
||||
}
|
||||
|
||||
/*
|
||||
@ -392,4 +395,13 @@ define(function(require) {
|
||||
|
||||
return '<span style="'+show_lock+' float:left; margin-right: 3px; width: 5px; height: 20px; background: '+color+';"></span>'
|
||||
}
|
||||
|
||||
function _week_days(days){
|
||||
var days = days.split(",");
|
||||
var str = "";
|
||||
days.forEach(function(day){
|
||||
str += week_days_str[day] + ",";
|
||||
});
|
||||
return str.slice(0, -1);
|
||||
}
|
||||
})
|
||||
|
342
src/sunstone/public/app/utils/schedule_action.js
Normal file
342
src/sunstone/public/app/utils/schedule_action.js
Normal file
@ -0,0 +1,342 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2018, OpenNebula Project, OpenNebula Systems */
|
||||
/* */
|
||||
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
|
||||
/* not use this file except in compliance with the License. You may obtain */
|
||||
/* a copy of the License at */
|
||||
/* */
|
||||
/* http://www.apache.org/licenses/LICENSE-2.0 */
|
||||
/* */
|
||||
/* Unless required by applicable law or agreed to in writing, software */
|
||||
/* distributed under the License is distributed on an "AS IS" BASIS, */
|
||||
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
|
||||
/* See the License for the specific language governing permissions and */
|
||||
/* limitations under the License. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
define(function (require) {
|
||||
var Config = require("sunstone-config");
|
||||
var Locale = require("utils/locale");
|
||||
var Humanize = require("utils/humanize");
|
||||
var TemplateUtils = require("utils/template-utils");
|
||||
var Tips = require('utils/tips');
|
||||
|
||||
var TemplateHTML = require("hbs!./schedule_action/html");
|
||||
var TemplateTableHTML = require("hbs!./schedule_action/table");
|
||||
|
||||
function _html(resource) {
|
||||
this.res = resource;
|
||||
return TemplateTableHTML({
|
||||
res: resource
|
||||
});
|
||||
}
|
||||
|
||||
function _htmlNewAction(actions, context, res) {
|
||||
var options = "";
|
||||
var that = this;
|
||||
$.each(actions, function (key, action) {
|
||||
var actionAux = action.replace("-", "_");
|
||||
if (Config.isTabActionEnabled("vms-tab", "VM." + actionAux)) {
|
||||
options += "<option value=\"" + action + "\">" + Locale.tr(action) + "</option>";
|
||||
}
|
||||
});
|
||||
$("#scheduling_" + res + "_actions_table tbody", context).append(TemplateHTML({
|
||||
"actions": options,
|
||||
"res": that.res
|
||||
}));
|
||||
|
||||
if (res === "vms"){
|
||||
$("#title", context).prop("colspan", "2");
|
||||
$("#td_days", context).prop("colspan", "5");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function _setup(context) {
|
||||
var today = new Date();
|
||||
var dd = today.getDate();
|
||||
var mm = today.getMonth() + 1;
|
||||
var yyyy = today.getFullYear();
|
||||
if (dd < 10) {
|
||||
dd = "0" + dd;
|
||||
}
|
||||
if (mm < 10) {
|
||||
mm = "0" + mm;
|
||||
}
|
||||
today = yyyy + "-" + mm + "-" + dd;
|
||||
$("#date_input", context).attr("min", today);
|
||||
$("#date_input", context).attr("value", today);
|
||||
|
||||
$(".periodic", context).hide();
|
||||
|
||||
$("input#schedule_type", context).on("change", function () {
|
||||
var periodic = $(this).prop("checked");
|
||||
|
||||
if (periodic) {
|
||||
$(".periodic", context).show();
|
||||
$(".non-periodic", context).hide();
|
||||
} else {
|
||||
$(".periodic", context).hide();
|
||||
$(".non-periodic", context).show();
|
||||
}
|
||||
});
|
||||
var that = this;
|
||||
this.rep = "week";
|
||||
this.end_type = "never";
|
||||
$("select[name='repeat']", context).change(function () {
|
||||
var value = $(this).val();
|
||||
that.repeat = value;
|
||||
var input_html = "";
|
||||
switch (value) {
|
||||
case "week":
|
||||
input_html = "<div id=\"days_week_value\" style=\"margin: 10px 0 10px 0;\">\
|
||||
<input type=\"checkbox\" id=\"mon\" name=\"days\" value=\"0\"><label for=\"mon\">" + Locale.tr("Mo") + "</label>\
|
||||
<input type=\"checkbox\" id=\"tue\" name=\"days\" value=\"1\"><label for=\"tue\">" + Locale.tr("Tu") + "</label>\
|
||||
<input type=\"checkbox\" id=\"wed\" name=\"days\" value=\"2\"><label for=\"wed\">" + Locale.tr("We") + "</label>\
|
||||
<input type=\"checkbox\" id=\"thu\" name=\"days\" value=\"3\"><label for=\"thu\">" + Locale.tr("Th") + "</label>\
|
||||
<input type=\"checkbox\" id=\"fri\" name=\"days\" value=\"4\"><label for=\"fri\">" + Locale.tr("Fr") + "</label>\
|
||||
<input type=\"checkbox\" id=\"sat\" name=\"days\" value=\"5\"><label for=\"sat\">" + Locale.tr("Sa") + "</label>\
|
||||
<input type=\"checkbox\" id=\"sun\" name=\"days\" value=\"6\"><label for=\"sun\">" + Locale.tr("Su") + "</label>\
|
||||
</div>";
|
||||
break;
|
||||
case "month":
|
||||
input_html = "<div style=\"display: -webkit-box;\"><input style=\"margin-right: 4px;\" id=\"days_month_value\" type=\"text\" placeholder=\"1,31\"/>\
|
||||
<span class=\"tip\">"+Locale.tr("Comma separated list of days of the month to repeat the action on. Ex: 1,15,25 repeats the action every first, 15th and 25th day of the month")+" </span></div>";
|
||||
break;
|
||||
case "year":
|
||||
input_html = "<div style=\"display: -webkit-box;\"><input style=\"margin-right: 4px;\" id=\"days_year_value\" type=\"text\" placeholder=\"0,365\"/>\
|
||||
<span class=\"tip\">"+Locale.tr("Comma separated list of days of the year to repeat the action on. Ex: 1,30,330 repeats the action every first, 30th and 330th day of the year")+" </span></div>";
|
||||
break;
|
||||
case "hour":
|
||||
input_html = "<div style=\"display: -webkit-box;\">\
|
||||
<label style=\"margin-right: 5px;\">"+ Locale.tr("Each")+"</label>\
|
||||
<input style=\"margin-right: 4px;\" id=\"days_hour_value\" min=\"0\" max=\"168\" type=\"number\" placeholder=\"5\"/>\
|
||||
<label> "+ Locale.tr("hours")+"</label>\
|
||||
</div>";
|
||||
break;
|
||||
}
|
||||
$("#td_days").html(input_html);
|
||||
Tips.setup(context);
|
||||
});
|
||||
|
||||
$("input[name='end_type']", context).change(function () {
|
||||
var value = $(this).val();
|
||||
that.end_type = value;
|
||||
var input_html = "";
|
||||
var min;
|
||||
$(".end_input", context).prop('disabled', true);
|
||||
switch (value) {
|
||||
case "n_rep":
|
||||
min = 1;
|
||||
break;
|
||||
case "date":
|
||||
var today = new Date();
|
||||
var dd = today.getDate();
|
||||
var mm = today.getMonth() + 1;
|
||||
var yyyy = today.getFullYear();
|
||||
if (dd < 10) {
|
||||
dd = "0" + dd
|
||||
}
|
||||
if (mm < 10) {
|
||||
mm = "0" + mm
|
||||
}
|
||||
min = yyyy + "-" + mm + "-" + dd;
|
||||
break;
|
||||
}
|
||||
$("#end_value_" + value, context).attr("min", min);
|
||||
$("#end_value_" + value, context).prop('disabled', false);
|
||||
});
|
||||
|
||||
context.on("focusout", "#time_input", function () {
|
||||
$("#time_input").removeAttr("data-invalid");
|
||||
$("#time_input").removeAttr("class");
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function _retrieve(context) {
|
||||
var actionsJSON = [];
|
||||
$("#scheduling_" + this.res + "_actions_table tbody tr").each(function (index) {
|
||||
var first = $(this).children("td")[0];
|
||||
if (!$("select", first).html()) {
|
||||
var actionJSON = {};
|
||||
actionJSON = JSON.parse($(this).attr("data"));
|
||||
actionJSON.ID = index;
|
||||
}
|
||||
if (!$.isEmptyObject(actionJSON)) { actionsJSON.push(actionJSON) };
|
||||
});
|
||||
return actionsJSON;
|
||||
}
|
||||
|
||||
function _retrieveNewAction(context) {
|
||||
var periodic = $("input#schedule_type", context).prop("checked");
|
||||
var time_input_value = $("#time_input", context).val();
|
||||
var date_input_value = $("#date_input", context).val();
|
||||
var new_action = $("#select_new_action", context).val();
|
||||
var rep = 0;
|
||||
var end_type = 1;
|
||||
var days = "";
|
||||
var end_value = 1;
|
||||
var sched_action = {};
|
||||
|
||||
if (time_input_value == "" || date_input_value == "") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (periodic) {
|
||||
|
||||
if (!this.repeat || !this.end_type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.repeat == "week") {
|
||||
$("input[name='days']:checked").each(function () {
|
||||
days = days + (this).value + ",";
|
||||
});
|
||||
days = days.slice(0, -1);
|
||||
} else if (this.repeat == "month") {
|
||||
rep = 1;
|
||||
days = $("#days_month_value", context).val();
|
||||
} else if (this.repeat == "year"){
|
||||
rep = 2;
|
||||
days = $("#days_year_value", context).val();
|
||||
} else {
|
||||
rep = 3;
|
||||
days = $("#days_hour_value", context).val();
|
||||
}
|
||||
|
||||
if (days == "") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.end_type == "never") {
|
||||
end_type = 0;
|
||||
} else if (this.end_type == "n_rep") {
|
||||
end_value = $("#end_value_n_rep", context).val();
|
||||
if (end_value == "") {
|
||||
return false;
|
||||
}
|
||||
} else if (this.end_type == "date") {
|
||||
end_type = 2;
|
||||
end_date = $("#end_value_date", context).val();
|
||||
var time_value = end_date + " " + time_input_value;
|
||||
var epoch_str = new Date(time_value);
|
||||
end_value = parseInt(epoch_str.getTime()) / 1000;
|
||||
if (end_value == "") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
sched_action.DAYS = days;
|
||||
sched_action.REPEAT = rep;
|
||||
sched_action.END_TYPE = end_type;
|
||||
sched_action.END_VALUE = end_value;
|
||||
}
|
||||
|
||||
var time_value = date_input_value + " " + time_input_value;
|
||||
var epoch_str = new Date(time_value);
|
||||
var time = parseInt(epoch_str.getTime()) / 1000;
|
||||
|
||||
sched_action.ACTION = new_action;
|
||||
sched_action.TIME = time;
|
||||
|
||||
$("#scheduling_" + this.res + "_actions_table .create", context).remove();
|
||||
$("#add_scheduling_" + this.res + "_action", context).removeAttr("disabled");
|
||||
|
||||
return sched_action;
|
||||
}
|
||||
|
||||
function _fromJSONtoActionsTable(actions_array, action_id, minus) {
|
||||
var str = "";
|
||||
|
||||
if (!actions_array) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (!$.isArray(actions_array)) {
|
||||
var tmp_array = new Array();
|
||||
tmp_array[0] = actions_array;
|
||||
actions_array = tmp_array;
|
||||
}
|
||||
|
||||
if (!actions_array.length) {
|
||||
return "";
|
||||
}
|
||||
|
||||
$.each(actions_array, function (index, scheduling_action) {
|
||||
str += _fromJSONtoActionRow(scheduling_action, action_id, minus);
|
||||
});
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
function _fromJSONtoActionRow(scheduling_action, action_id, minus) {
|
||||
var time_str = Humanize.prettyTime(scheduling_action.TIME);
|
||||
var rep_str = "";
|
||||
var end_str = "";
|
||||
|
||||
if (scheduling_action.REPEAT != undefined) {
|
||||
if (scheduling_action.REPEAT == 0) {
|
||||
rep_str = "Weekly ";
|
||||
} else if (scheduling_action.REPEAT == 1) {
|
||||
rep_str = "Monthly ";
|
||||
} else if (scheduling_action.REPEAT == 2) {
|
||||
rep_str = "Yearly ";
|
||||
} else if (scheduling_action.REPEAT == 3) {
|
||||
rep_str = "Each " + scheduling_action.DAYS + " hours";
|
||||
}
|
||||
|
||||
if (scheduling_action.REPEAT != 3) {
|
||||
if (scheduling_action.REPEAT != 0) {
|
||||
rep_str += scheduling_action.DAYS;
|
||||
} else {
|
||||
rep_str += Humanize.week_days(scheduling_action.DAYS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (scheduling_action.END_TYPE != undefined) {
|
||||
if (scheduling_action.END_TYPE == 0) {
|
||||
end_str = "None";
|
||||
} else if (scheduling_action.END_TYPE == 1) {
|
||||
end_str = "After " + scheduling_action.END_VALUE + " times";
|
||||
} else if (scheduling_action.END_TYPE == 2) {
|
||||
end_str = "on " + Humanize.prettyTime(scheduling_action.END_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
var str = "";
|
||||
if (action_id == undefined) {
|
||||
str += "<tr class='tr_action' data='" + JSON.stringify(scheduling_action) + "'>";
|
||||
}
|
||||
str += "<td class='action_row'>" + TemplateUtils.htmlEncode(scheduling_action.ACTION) + "</td>\
|
||||
<td nowrap class='time_row'>" + time_str + "</td>\
|
||||
<td nowrap class='rep_row'>" + rep_str + "</td>\
|
||||
<td nowrap class='end_row'>" + end_str + "</td>";
|
||||
if (minus == undefined) {
|
||||
str += "<td>\
|
||||
<div>\
|
||||
<a id='minus' class='remove_action_x' href='#'><i class='fa fa-trash-o'/></a>\
|
||||
</div>\
|
||||
</td>\
|
||||
</tr>";
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
function convertDate(date_string) {
|
||||
date_string = date_string.split("/");
|
||||
return date_string[2] + "-" + date_string[1] + "-" + date_string[0];
|
||||
}
|
||||
|
||||
return {
|
||||
"fromJSONtoActionRow": _fromJSONtoActionRow,
|
||||
"fromJSONtoActionsTable": _fromJSONtoActionsTable,
|
||||
"htmlNewAction": _htmlNewAction,
|
||||
"setup": _setup,
|
||||
"htmlTable": _html,
|
||||
"retrieveNewAction": _retrieveNewAction,
|
||||
"retrieve": _retrieve
|
||||
};
|
||||
});
|
98
src/sunstone/public/app/utils/schedule_action/html.hbs
Normal file
98
src/sunstone/public/app/utils/schedule_action/html.hbs
Normal file
@ -0,0 +1,98 @@
|
||||
{{! -------------------------------------------------------------------------- }} {{! Copyright 2002-2018, OpenNebula Project,
|
||||
OpenNebula Systems }} {{! }} {{! Licensed under the Apache License, Version 2.0 (the "License"); you may }} {{! not use this
|
||||
file except in compliance with the License. You may obtain }} {{! a copy of the License at }} {{! }} {{! http://www.apache.org/licenses/LICENSE-2.0
|
||||
}} {{! }} {{! Unless required by applicable law or agreed to in writing, software }} {{! distributed under the License is
|
||||
distributed on an "AS IS" BASIS, }} {{! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. }} {{! See
|
||||
the License for the specific language governing permissions and }} {{! limitations under the License. }} {{! --------------------------------------------------------------------------
|
||||
}}
|
||||
|
||||
<tr class="create">
|
||||
<td id="title">
|
||||
<h6 class="title_label">{{tr "New scheduled action"}}:</h6>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="tr_schedule_base" class="create">
|
||||
<td>
|
||||
<select style="width: 80%" id="select_new_action" class="select_new_action" name="select_action">{{{actions}}}</select>
|
||||
</td>
|
||||
<td>
|
||||
<input style="width: 80%" id="date_input" type="date" />
|
||||
</td>
|
||||
<td>
|
||||
<input style="width: 80%" id="time_input" type="time" placeholder="12:30" />
|
||||
</td>
|
||||
<td>
|
||||
<input id="schedule_type" type="checkbox">
|
||||
<label>{{tr "Periodic"}}</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="periodic create">
|
||||
<td>
|
||||
<label class="title_label">{{tr "Repeat"}}: </label>
|
||||
</td>
|
||||
<td>
|
||||
<select style="width: 75%" id="repeat" name="repeat">
|
||||
<option value="week">{{tr "Weekly"}}</option>
|
||||
<option value="month">{{tr "Monthly"}}</option>
|
||||
<option value="year">{{tr "Yearly"}}</option>
|
||||
<option value="hour">{{tr "Hourly"}}</option>
|
||||
</select>
|
||||
</td>
|
||||
<td id="td_days" colspan="3">
|
||||
<div id="days_week_value" style="margin: 10px 0 10px 0;">
|
||||
<input type="checkbox" id="mon" name="days" value="0">
|
||||
<label for="mon">{{tr "Mo"}}</label>
|
||||
<input type="checkbox" id="tue" name="days" value="1">
|
||||
<label for="tue">{{tr "Tu"}}</label>
|
||||
<input type="checkbox" id="wed" name="days" value="2">
|
||||
<label for="wed">{{tr "We"}}</label>
|
||||
<input type="checkbox" id="thu" name="days" value="3">
|
||||
<label for="thu">{{tr "Th"}}</label>
|
||||
<input type="checkbox" id="fri" name="days" value="4">
|
||||
<label for="fri">{{tr "Fr"}}</label>
|
||||
<input type="checkbox" id="sat" name="days" value="5">
|
||||
<label for="sat">{{tr "Sa"}}</label>
|
||||
<input type="checkbox" id="sun" name="days" value="6">
|
||||
<label for="sun">{{tr "Su"}}</label>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="periodic create">
|
||||
<td>
|
||||
<label class="title_label">{{tr "Ends"}}: </label>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="periodic create">
|
||||
<td>
|
||||
<input type="radio" name="end_type" id="end_type_ever" value="never" checked>
|
||||
<label for="end_type_ever">{{tr "Never"}}</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="periodic create">
|
||||
<td>
|
||||
<input type="radio" name="end_type" id="end_type_n_rep" value="date">
|
||||
<label for="end_type_date">{{tr "On"}}</label>
|
||||
</td>
|
||||
<td id="td_end_value_date">
|
||||
<input class="end_input" id="end_value_date" type="date" disabled/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="periodic create">
|
||||
<td>
|
||||
<input type="radio" name="end_type" id="end_type_n_rep" value="n_rep">
|
||||
<label for="end_type_n_rep">{{tr "After"}}</label>
|
||||
</td>
|
||||
<td id="td_end_value_nrep">
|
||||
<input class="end_input" id="end_value_n_rep" type="number" placeholder="1" disabled/>
|
||||
</td>
|
||||
<td>
|
||||
<label for="end_value_date">{{tr "times"}}</label>
|
||||
</td>
|
||||
</tr>
|
||||
<br>
|
||||
<tr class="create">
|
||||
<td>
|
||||
<button style="margin-top: 15px;" id="add_{{res}}_action_json" class="button small success secondary radius">{{tr "Add"}}</button>
|
||||
</td>
|
||||
</tr>
|
38
src/sunstone/public/app/utils/schedule_action/table.hbs
Normal file
38
src/sunstone/public/app/utils/schedule_action/table.hbs
Normal file
@ -0,0 +1,38 @@
|
||||
{{! -------------------------------------------------------------------------- }}
|
||||
{{! Copyright 2002-2018, OpenNebula Project, OpenNebula Systems }}
|
||||
{{! }}
|
||||
{{! Licensed under the Apache License, Version 2.0 (the "License"); you may }}
|
||||
{{! not use this file except in compliance with the License. You may obtain }}
|
||||
{{! a copy of the License at }}
|
||||
{{! }}
|
||||
{{! http://www.apache.org/licenses/LICENSE-2.0 }}
|
||||
{{! }}
|
||||
{{! Unless required by applicable law or agreed to in writing, software }}
|
||||
{{! distributed under the License is distributed on an "AS IS" BASIS, }}
|
||||
{{! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. }}
|
||||
{{! See the License for the specific language governing permissions and }}
|
||||
{{! limitations under the License. }}
|
||||
{{! -------------------------------------------------------------------------- }}
|
||||
|
||||
<style>
|
||||
.title_label{
|
||||
font-weight: bold;
|
||||
color:#555;
|
||||
}
|
||||
</style>
|
||||
|
||||
<table id="scheduling_{{res}}_actions_table" class="info_table dataTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th> {{tr "Action"}} </th>
|
||||
<th> {{tr "Time"}} </th>
|
||||
<th> {{tr "Rep"}} </th>
|
||||
<th> {{tr "Ends"}} </th>
|
||||
<th colspan=""> {{tr "Actions"}} </th>
|
||||
<th>
|
||||
<button id="add_scheduling_{{res}}_action" class="button small success right radius"> {{tr "Add action"}} </button>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="sched_{{res}}_actions_body"></tbody>
|
||||
</table>
|
@ -23,7 +23,8 @@ lib_name='nebula_vmtemplate'
|
||||
# Sources to generate the library
|
||||
source_files=[
|
||||
'VMTemplate.cc',
|
||||
'VMTemplatePool.cc'
|
||||
'VMTemplatePool.cc',
|
||||
'ScheduledAction.cc'
|
||||
]
|
||||
|
||||
# Build library
|
||||
|
422
src/vm_template/ScheduledAction.cc
Normal file
422
src/vm_template/ScheduledAction.cc
Normal file
@ -0,0 +1,422 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2018, OpenNebula Project, OpenNebula Systems */
|
||||
/* */
|
||||
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
|
||||
/* not use this file except in compliance with the License. You may obtain */
|
||||
/* a copy of the License at */
|
||||
/* */
|
||||
/* http://www.apache.org/licenses/LICENSE-2.0 */
|
||||
/* */
|
||||
/* Unless required by applicable law or agreed to in writing, software */
|
||||
/* distributed under the License is distributed on an "AS IS" BASIS, */
|
||||
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
|
||||
/* See the License for the specific language governing permissions and */
|
||||
/* limitations under the License. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#include "ScheduledAction.h"
|
||||
#include "NebulaUtil.h"
|
||||
|
||||
int SchedAction::repeat(Repeat& r)
|
||||
{
|
||||
r = NONE;
|
||||
|
||||
std::string rep_s = vector_value("REPEAT");
|
||||
|
||||
if ( rep_s.empty() )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::istringstream iss(rep_s);
|
||||
int v_r;
|
||||
|
||||
iss >> v_r;
|
||||
|
||||
if (iss.fail() || !iss.eof())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( v_r < WEEKLY || v_r > HOURLY )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = static_cast<Repeat>(v_r);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int SchedAction::endon(EndOn& eo)
|
||||
{
|
||||
eo = NEVER;
|
||||
|
||||
std::string et_s = vector_value("END_TYPE");
|
||||
|
||||
if ( et_s.empty() )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::istringstream iss(et_s);
|
||||
int v_eo;
|
||||
|
||||
iss >> v_eo;
|
||||
|
||||
if (iss.fail() || !iss.eof())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( v_eo < TIMES || v_eo > DATE )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
eo = static_cast<EndOn>(v_eo);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int SchedAction::days(std::set<int>& _d)
|
||||
{
|
||||
std::string st;
|
||||
|
||||
int rc = vector_value("DAYS", st);
|
||||
|
||||
if ( rc != 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
one_util::split_unique<int>(st, ',', _d);
|
||||
|
||||
if ( _d.empty() )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
bool SchedAction::days_in_range(Repeat r, std::string& error)
|
||||
{
|
||||
static const char * e[] = {
|
||||
"Days in a week have to be in [0,6] range", //WEEKLY - 0
|
||||
"Days in a month have to be in [0,31] range", // MONTHLY - 1
|
||||
"Days in a year have to be in [0,365] range", // YEARLY - 2
|
||||
"Hours have to be in [0,168] range" // HOURLY - 3
|
||||
};
|
||||
|
||||
static int fday[] = {0,1,0,1};
|
||||
static int lday[] = {7,32,366,168};
|
||||
|
||||
bool extra_check;
|
||||
|
||||
std::set<int> _d;
|
||||
|
||||
if ( days(_d) == -1 )
|
||||
{
|
||||
error = "Wrong format of DAYS attribute";
|
||||
return false;
|
||||
}
|
||||
else if ( _d.empty() )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int _fday = *(_d.begin());
|
||||
int _lday = *(_d.rbegin());
|
||||
|
||||
switch(r)
|
||||
{
|
||||
case WEEKLY:
|
||||
case MONTHLY:
|
||||
case YEARLY:
|
||||
extra_check = false;
|
||||
break;
|
||||
case HOURLY:
|
||||
extra_check = _d.size() != 1;
|
||||
break;
|
||||
case NONE:
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( _fday < fday[r] || _lday >= lday[r] || extra_check )
|
||||
{
|
||||
error = e[r];
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
bool SchedAction::ends_in_range(EndOn eo, std::string& error)
|
||||
{
|
||||
int end_value;
|
||||
int rc = vector_value("END_VALUE", end_value);
|
||||
|
||||
if ( rc == -1 )
|
||||
{
|
||||
error = "Missing END_VALUE";
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( eo == TIMES && end_value <= 0 )
|
||||
{
|
||||
error = "Error parsing END_VALUE, times has to be greater than 0";
|
||||
return false;
|
||||
}
|
||||
else if ( eo == DATE )
|
||||
{
|
||||
struct tm val_tm;
|
||||
|
||||
localtime_r((time_t *)&end_value, &val_tm);
|
||||
|
||||
time_t out = mktime(&val_tm);
|
||||
|
||||
if (out == -1)
|
||||
{
|
||||
error = "Error parsing END_VALUE, wrong format for date.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int SchedAction::parse(std::string& error)
|
||||
{
|
||||
Repeat r;
|
||||
EndOn eo;
|
||||
|
||||
if ( repeat(r) == -1 )
|
||||
{
|
||||
error = "Error parsing REPEAT attribute";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( endon(eo) == -1 )
|
||||
{
|
||||
error = "Error parsing END_TYPE attribute";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( !days_in_range(r, error) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( !ends_in_range(eo, error) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
remove("DONE");
|
||||
remove("MESSAGE");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static int days_in_period(SchedAction::Repeat& r, int month, int year)
|
||||
{
|
||||
static map<int, int> MONTHS_DAYS = {{0, 31}, {1, 28}, {2, 31}, {3, 30},
|
||||
{4, 31}, {5, 30}, {6, 31}, {7, 31}, {8, 30}, {9, 31}, {10, 30},
|
||||
{11, 31}};
|
||||
|
||||
int leap_year = 0;
|
||||
int leap_month = 0;
|
||||
|
||||
year += 1900;
|
||||
|
||||
if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
|
||||
{
|
||||
leap_year = 1;
|
||||
|
||||
if ( month == 1 )
|
||||
{
|
||||
leap_month = 1;
|
||||
}
|
||||
}
|
||||
|
||||
switch(r)
|
||||
{
|
||||
case SchedAction::WEEKLY:
|
||||
return 7;
|
||||
|
||||
//Return value for months assume month day starts in 0
|
||||
case SchedAction::MONTHLY:
|
||||
return MONTHS_DAYS[month] + leap_month;
|
||||
|
||||
case SchedAction::YEARLY:
|
||||
return 365 + leap_year;
|
||||
|
||||
case SchedAction::HOURLY:
|
||||
case SchedAction::NONE:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
bool SchedAction::is_due()
|
||||
{
|
||||
time_t action_time, done_time;
|
||||
|
||||
bool has_done = vector_value("DONE", done_time) == 0;
|
||||
|
||||
vector_value("TIME", action_time);
|
||||
|
||||
return ((!has_done || done_time < action_time) && action_time < time(0));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int SchedAction::next_action()
|
||||
{
|
||||
Repeat r;
|
||||
EndOn eo;
|
||||
|
||||
if ( repeat(r) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( endon(eo) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::set<int> _days;
|
||||
|
||||
if ( days(_days) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if ( _days.empty() )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Check if action is already finished */
|
||||
/* --------------------------------------------------------------------- */
|
||||
int end_value;
|
||||
int rc = vector_value("END_VALUE", end_value);
|
||||
|
||||
if ( rc == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( eo == TIMES )
|
||||
{
|
||||
if (end_value <= 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
replace("END_VALUE", end_value - 1);
|
||||
}
|
||||
else if ( eo == DATE )
|
||||
{
|
||||
if ( time(0) > end_value )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Compute next event for the action - HOURLY */
|
||||
/* --------------------------------------------------------------------- */
|
||||
time_t action_time;
|
||||
|
||||
vector_value("TIME", action_time);
|
||||
|
||||
if ( r == HOURLY )
|
||||
{
|
||||
action_time += *(_days.begin()) * 3600;
|
||||
|
||||
replace("TIME", action_time);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Compute next event for the action - WEEKLY, MONTHLY & YEARLY */
|
||||
/* --------------------------------------------------------------------- */
|
||||
time_t current = time(0);
|
||||
|
||||
struct tm current_tm;
|
||||
|
||||
int cday;
|
||||
|
||||
localtime_r(¤t, ¤t_tm);
|
||||
|
||||
switch(r)
|
||||
{
|
||||
case WEEKLY:
|
||||
cday = current_tm.tm_wday;
|
||||
break;
|
||||
|
||||
case MONTHLY:
|
||||
cday = current_tm.tm_mday;
|
||||
break;
|
||||
|
||||
case YEARLY:
|
||||
cday = current_tm.tm_yday;
|
||||
break;
|
||||
|
||||
case HOURLY:
|
||||
case NONE:
|
||||
break;
|
||||
}
|
||||
|
||||
std::set<int>::iterator it = _days.lower_bound(cday);
|
||||
|
||||
int delta = 0;
|
||||
|
||||
if (it == _days.end()) //after last day in range
|
||||
{
|
||||
int pdays = days_in_period(r, current_tm.tm_mon, current_tm.tm_year);
|
||||
|
||||
delta = pdays - cday + *(_days.begin()); //assume start day is 0
|
||||
}
|
||||
else if (cday < *(_days.begin())) //before first day in range
|
||||
{
|
||||
delta = *(_days.begin()) - cday;
|
||||
}
|
||||
else if (*it != cday ) //is not today
|
||||
{
|
||||
delta = *it - cday;
|
||||
}
|
||||
|
||||
action_time += delta * 24 * 3600;
|
||||
|
||||
replace("TIME", action_time);
|
||||
|
||||
return 0;
|
||||
}
|
@ -15,8 +15,7 @@
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#include "VMTemplate.h"
|
||||
|
||||
#define TO_UPPER(S) transform(S.begin(),S.end(),S.begin(),(int(*)(int))toupper)
|
||||
#include "ScheduledAction.h"
|
||||
|
||||
/* ************************************************************************ */
|
||||
/* VMTemplate :: Constructor/Destructor */
|
||||
@ -74,9 +73,14 @@ int VMTemplate::insert(SqlDB *db, string& error_str)
|
||||
erase_template_attribute("NAME", name);
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Remove DONE/MESSAGE from SCHED_ACTION
|
||||
// Remove DONE/MESSAGE from SCHED_ACTION and check rest attributes
|
||||
// ---------------------------------------------------------------------
|
||||
parse_sched_action();
|
||||
int rc = parse_sched_action(error_str);
|
||||
|
||||
if (rc == -1)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Insert the Template
|
||||
@ -167,18 +171,11 @@ error_common:
|
||||
return -1;
|
||||
}
|
||||
|
||||
void VMTemplate::parse_sched_action()
|
||||
int VMTemplate::parse_sched_action(string& error_str)
|
||||
{
|
||||
vector<VectorAttribute *> _sched_actions;
|
||||
vector<VectorAttribute *>::iterator i;
|
||||
SchedActions sactions(obj_template);
|
||||
|
||||
get_template_attribute("SCHED_ACTION", _sched_actions);
|
||||
|
||||
for ( i = _sched_actions.begin(); i != _sched_actions.end() ; ++i)
|
||||
{
|
||||
(*i)->remove("DONE");
|
||||
(*i)->remove("MESSAGE");
|
||||
}
|
||||
return sactions.parse(error_str);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
@ -186,7 +183,11 @@ void VMTemplate::parse_sched_action()
|
||||
|
||||
int VMTemplate::post_update_template(string& error)
|
||||
{
|
||||
parse_sched_action();
|
||||
int rc = parse_sched_action(error);
|
||||
if (rc == -1)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user