1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-11 04:58:16 +03:00

F #5289: New api for sched actions

SchedActions are now a complete managed type. It is in in /TEMPLATE and
not /USER_TEMPLATE and includes dedicated API Calls to manage the
entries:

- one.vm.schedadd (add new sched_action)
- one.vm.schedupdate (update an exiting sched_action)
- one.vm.scheddelete (delete an action)

The scheduler now use this API. This will prevent race conditions
between update operations from different processes.

co-authored-by: Pavel Czerný <pczerny@opennebula.systems>
This commit is contained in:
Ruben S. Montero 2021-06-15 08:22:26 +00:00
parent bde16dcdcc
commit 3f171f3b5b
No known key found for this signature in database
GPG Key ID: A0CEA6FA880A1D87
18 changed files with 630 additions and 113 deletions

View File

@ -70,20 +70,6 @@ public:
va->merge(vattr, replace);
}
protected:
/**
* Creates the attribute with a reference to a VectorAttribute. The object
* is shared and WILL BE modified through this interface.
* @param va pointer to the VectorAttribute.
*/
ExtendedAttribute(VectorAttribute *_va):
Attribute(_va->name()) ,va(_va), id(-1) {};
ExtendedAttribute(VectorAttribute *_va, int _id):
Attribute(_va->name()) ,va(_va), id(_id) {};
virtual ~ExtendedAttribute(){};
/* ---------------------------------------------------------------------- */
/* Attribute Interface */
/* ---------------------------------------------------------------------- */
@ -107,6 +93,23 @@ protected:
return va->to_token(s);
};
protected:
/**
* Creates the attribute with a reference to a VectorAttribute. The object
* is shared and WILL BE modified through this interface.
* @param va pointer to the VectorAttribute.
*/
ExtendedAttribute(VectorAttribute *_va):
Attribute(_va->name()) ,va(_va), id(-1) {};
ExtendedAttribute(VectorAttribute *_va, int _id):
Attribute(_va->name()) ,va(_va), id(_id) {};
virtual ~ExtendedAttribute(){};
/* ---------------------------------------------------------------------- */
/* Attribute Interface */
/* ---------------------------------------------------------------------- */
void unmarshall(const std::string& sattr, const char * _sep = 0)
{
va->unmarshall(sattr, _sep);

View File

@ -0,0 +1,82 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2021, 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 REQUEST_MANAGER_SCHED_H_
#define REQUEST_MANAGER_SCHED_H_
#include "Request.h"
#include "Nebula.h"
#include "VirtualMachinePool.h"
class RequestManagerSchedAdd : public Request
{
public:
RequestManagerSchedAdd()
: Request("one.vm.schedadd", "A:is", "Add scheduled action")
{
auth_object = PoolObjectSQL::VM;
auth_op = AuthRequest::MANAGE;
Nebula& nd = Nebula::instance();
pool = nd.get_vmpool();
}
void request_execute(xmlrpc_c::paramList const& _paramList,
RequestAttributes& att) override;
};
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class RequestManagerSchedDelete : public Request
{
public:
RequestManagerSchedDelete()
: Request("one.vm.scheddelete", "A:ii", "Delete scheduled action")
{
auth_object = PoolObjectSQL::VM;
auth_op = AuthRequest::MANAGE;
Nebula& nd = Nebula::instance();
pool = nd.get_vmpool();
}
void request_execute(xmlrpc_c::paramList const& _paramList,
RequestAttributes& att) override;
};
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class RequestManagerSchedUpdate : public Request
{
public:
RequestManagerSchedUpdate()
: Request("one.vm.schedupdate", "A:iis", "Update scheduled action")
{
auth_object = PoolObjectSQL::VM;
auth_op = AuthRequest::MANAGE;
Nebula& nd = Nebula::instance();
pool = nd.get_vmpool();
}
void request_execute(xmlrpc_c::paramList const& _paramList,
RequestAttributes& att) override;
};
#endif

View File

@ -131,13 +131,11 @@ public:
tmpl->get("SCHED_ACTION", vas);
init_attribute_map("TIME", vas);
init_attribute_map("ID", vas);
};
virtual ~SchedActions(){};
/* ---------------------------------------------------------------------- */
/**
* Parse the ScheduleActions of a template
* @param error
@ -162,6 +160,39 @@ public:
return a_set.empty();
}
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
/* Raw VectorAttribute helpers */
/* ---------------------------------------------------------------------- */
/**
* Parse a set of scheduled actions and optionally assign them a valid id
* @param vas the vector of SCHED_ACTION
* @param err string in case of error
* @param clean remove DONE and MESSAGE attributes
* @param set_id to set ID for each action
*
* @return 0 on success -1 if error
*/
static int parse(std::vector<VectorAttribute *>& vas, std::string& err,
bool clean, bool set_id);
/**
* Adds a new SchedAction based on the provided VectorAttribute. The new
* attribute is check and parsed
* @param va VectorAttribute with the action
* @param err with description
*
* @return pointer to new attribute nullptr on error
*/
static VectorAttribute * new_action(
const std::vector<const VectorAttribute *>& vas,
VectorAttribute * va, std::string &err);
static VectorAttribute * get_action(
const std::vector<VectorAttribute *>& sched_actions, int id);
/* ---------------------------------------------------------------------- */
/* Iterators */
/* ---------------------------------------------------------------------- */

View File

@ -989,18 +989,6 @@ public:
*/
void clear_template_error_message() override;
/**
* Sets an error message with timestamp in the template (ERROR_MONITOR)
* @param message Message string
*/
void set_template_monitor_error(const std::string& message);
/**
* Deletes the error message from the template (ERROR_MONITOR)
* @param message Message string
*/
void clear_template_monitor_error();
// ------------------------------------------------------------------------
// Timers & Requirements
// ------------------------------------------------------------------------
@ -1694,6 +1682,35 @@ public:
*/
int check_shareable_disks(const std::string& vmm_mad, std::string& error);
/**
* Add scheduled actions
* @param sched_template Teplate with scheduled actions
* @param error Error string in case of failure
* @return 0 on success, -1 on failure
*/
int sched_action_add(const std::string& sched_template,
std::string& error);
/**
* Update one scheduled action
* @param sched_id ID of the scheduled action to delete
* @param error Error string in case of failure
* @return 0 on success, -1 on failure
*/
int sched_action_delete(int sched_id,
std::string& error);
/**
* Update one scheduled action
* @param sched_id ID of the scheduled action to update
* @param sched_template New value of scheduled action
* @param error Error string in case of failure
* @return 0 on success, -1 on failure
*/
int sched_action_update(int sched_id,
const std::string& sched_template,
std::string& error);
private:
// -------------------------------------------------------------------------
@ -2171,6 +2188,11 @@ private:
*/
int parse_sched_action(std::string& error_str);
/**
* Assign id to sched actions without id
*/
void assign_sched_ids();
/**
* Encrypt all secret attributes
*/

View File

@ -439,21 +439,6 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
str_periodic << ', END_TYPE = 0'
end
rc = vm.info
if OpenNebula.is_error?(rc)
puts rc.message
exit(-1)
end
ids = vm.retrieve_elements('USER_TEMPLATE/SCHED_ACTION/ID')
id = 0
if !ids.nil? && !ids.empty?
ids.map! {|e| e.to_i }
id = ids.max + 1
end
sched = options[:schedule]
# If the action is set to be executed from VM start to an specific
@ -463,16 +448,14 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
sched = sched.to_i
end
tmp_str = vm.user_template_str
tmp_str << "\nSCHED_ACTION = "
tmp_str << "[ID = #{id}, ACTION = #{action}, "
tmp_str = "SCHED_ACTION = ["
tmp_str << "ACTION = #{action}, "
tmp_str << "WARNING = #{warning}," if warning
tmp_str << "ARGS = \"#{options[:args]}\"," if options[:args]
tmp_str << "TIME = #{sched}"
tmp_str << str_periodic << ']'
vm.update(tmp_str)
vm.sched_action_add(tmp_str)
end
end
@ -490,7 +473,7 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
exit(-1)
end
xpath = "USER_TEMPLATE/SCHED_ACTION[ID=#{action_id}]"
xpath = "TEMPLATE/SCHED_ACTION[ID=#{action_id}]"
unless vm.retrieve_elements(xpath)
STDERR.puts "Sched action #{action_id} not found"
@ -508,12 +491,11 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
vm.delete_element(xpath)
# Add the modified sched action
tmp_str = vm.user_template_str
tmp_str << "\nSCHED_ACTION = ["
tmp_str = "\nSCHED_ACTION = ["
tmp_str << str.split("\n").join(',')
tmp_str << ']'
rc = vm.update(tmp_str)
rc = vm.sched_action_update(action_id, tmp_str)
if OpenNebula.is_error?(rc)
STDERR.puts "Error updating: #{rc.message}"
@ -1227,7 +1209,7 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
format_history(vm)
end
if vm.has_elements?('/VM/USER_TEMPLATE/SCHED_ACTION')
if vm.has_elements?('/VM/TEMPLATE/SCHED_ACTION')
puts
CLIHelper.print_header(str_h1 % 'SCHEDULED ACTIONS', false)
@ -1318,12 +1300,12 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
show
end
end
end.show([vm_hash['VM']['USER_TEMPLATE']['SCHED_ACTION']].flatten,
end.show([vm_hash['VM']['TEMPLATE']['SCHED_ACTION']].flatten,
{})
end
if !options[:all]
vm.delete_element('/VM/USER_TEMPLATE/SCHED_ACTION')
vm.delete_element('/VM/TEMPLATE/SCHED_ACTION')
end
if vm.has_elements?('/VM/USER_TEMPLATE')

View File

@ -1411,22 +1411,7 @@ CommandParser::CmdParser.new(ARGV) do
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)
rc = vm.sched_action_delete(args[1])
if OpenNebula.is_error?(rc)
STDERR.puts "Error deleting: #{rc.message}"

View File

@ -583,7 +583,7 @@ module OpenNebula
@service.log_error(msg)
else
ids = vm.retrieve_elements('USER_TEMPLATE/SCHED_ACTION/ID')
ids = vm.retrieve_elements('TEMPLATE/SCHED_ACTION/ID')
id = 0
if !ids.nil? && !ids.empty?
@ -591,20 +591,18 @@ module OpenNebula
id = ids.max + 1
end
tmp_str = vm.user_template_str
if do_offset
offset = (index / vms_per_period.to_i).floor
time_offset = offset * period.to_i
end
tmp_str << "\nSCHED_ACTION = ["
tmp_str = "SCHED_ACTION = ["
tmp_str << "ID = #{id},"
tmp_str << "ACTION = #{action},"
tmp_str << "ARGS = \"#{args}\"," if args
tmp_str << "TIME = #{now + time_offset}]"
rc = vm.update(tmp_str)
rc = vm.sched_action_add(tmp_str)
if OpenNebula.is_error?(rc)
msg = "Role #{name} : VM #{vm_id} error scheduling "\
"action; #{rc.message}"

View File

@ -50,8 +50,11 @@ module OpenNebula
:disksnapshotrename => "vm.disksnapshotrename",
:diskresize => "vm.diskresize",
:updateconf => "vm.updateconf",
:lock => "vm.lock",
:unlock => "vm.unlock"
:lock => "vm.lock",
:unlock => "vm.unlock",
:schedadd => "vm.schedadd",
:scheddelete => "vm.scheddelete",
:schedupdate => "vm.schedupdate"
}
VM_STATE=%w{INIT PENDING HOLD ACTIVE STOPPED SUSPENDED DONE FAILED
@ -724,6 +727,35 @@ module OpenNebula
return call(VM_METHODS[:updateconf], @pe_id, new_conf)
end
# Add sched actions
#
# @param sched_template [String] Template with SCHED_ACTIONs
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def sched_action_add(sched_template)
return call(VM_METHODS[:schedadd], @pe_id, sched_template)
end
# Delete sched action
#
# @param sched_id [Int] id of the SCHED_ACTION
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def sched_action_delete(sched_id)
return call(VM_METHODS[:scheddelete], @pe_id, sched_id.to_i)
end
# Update sched_action
#
# @param sched_id [Int] id of the SCHED_ACTION
# @param sched_template [String] Template containing a SCHED_ACTION
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def sched_action_update(sched_id, sched_template)
return call(VM_METHODS[:schedupdate], @pe_id, sched_id.to_i,
sched_template)
end
########################################################################
# Helpers to get VirtualMachine information
########################################################################

View File

@ -53,6 +53,7 @@
#include "RequestManagerVNTemplate.h"
#include "RequestManagerHook.h"
#include "RequestManagerMarketPlace.h"
#include "RequestManagerSchedAction.h"
#include "RequestManagerSystem.h"
#include "RequestManagerProxy.h"
@ -339,6 +340,9 @@ void RequestManager::register_xml_methods()
xmlrpc_c::methodPtr vm_recover(new VirtualMachineRecover());
xmlrpc_c::methodPtr vm_updateconf(new VirtualMachineUpdateConf());
xmlrpc_c::methodPtr vm_disk_resize(new VirtualMachineDiskResize());
xmlrpc_c::methodPtr vm_sched_add(new RequestManagerSchedAdd());
xmlrpc_c::methodPtr vm_sched_delete(new RequestManagerSchedDelete());
xmlrpc_c::methodPtr vm_sched_update(new RequestManagerSchedUpdate());
xmlrpc_c::methodPtr vm_pool_acct(new VirtualMachinePoolAccounting());
xmlrpc_c::methodPtr vm_pool_monitoring(new VirtualMachinePoolMonitoring());
@ -570,6 +574,9 @@ void RequestManager::register_xml_methods()
RequestManagerRegistry.addMethod("one.vm.lock", vm_lock);
RequestManagerRegistry.addMethod("one.vm.unlock", vm_unlock);
RequestManagerRegistry.addMethod("one.vm.diskresize", vm_disk_resize);
RequestManagerRegistry.addMethod("one.vm.schedadd", vm_sched_add);
RequestManagerRegistry.addMethod("one.vm.scheddelete", vm_sched_delete);
RequestManagerRegistry.addMethod("one.vm.schedupdate", vm_sched_update);
RequestManagerRegistry.addMethod("one.vmpool.info", vm_pool_info);
RequestManagerRegistry.addMethod("one.vmpool.infoextended", vm_pool_info_extended);

View File

@ -0,0 +1,126 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2021, 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 "RequestManagerSchedAction.h"
using namespace std;
void RequestManagerSchedAdd::request_execute(xmlrpc_c::paramList const& paramList,
RequestAttributes& att)
{
int oid = paramList.getInt(1);
string template_str = paramList.getString(2);
if ( basic_authorization(oid, att) == false )
{
return;
}
auto vm = pool->get<VirtualMachine>(oid);
if ( !vm )
{
att.resp_id = oid;
failure_response(NO_EXISTS, att);
return;
}
if ( vm->sched_action_add(template_str, att.resp_msg) != 0 )
{
failure_response(INTERNAL, att);
return;
}
pool->update(vm.get());
success_response(oid, att);
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void RequestManagerSchedDelete::request_execute(xmlrpc_c::paramList const& paramList,
RequestAttributes& att)
{
int oid = paramList.getInt(1);
int sched_id = paramList.getInt(2);
if ( basic_authorization(oid, att) == false )
{
return;
}
auto vm = pool->get<VirtualMachine>(oid);
if ( !vm )
{
att.resp_id = oid;
failure_response(NO_EXISTS, att);
return;
}
if ( vm->sched_action_delete(sched_id, att.resp_msg) != 0 )
{
failure_response(INTERNAL, att);
return;
}
pool->update(vm.get());
success_response(oid, att);
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void RequestManagerSchedUpdate::request_execute(xmlrpc_c::paramList const& paramList,
RequestAttributes& att)
{
int oid = paramList.getInt(1);
int sched_id = paramList.getInt(2);
string template_str = paramList.getString(3);
if ( basic_authorization(oid, att) == false )
{
return;
}
auto vm = pool->get<VirtualMachine>(oid);
if ( !vm )
{
att.resp_id = oid;
failure_response(NO_EXISTS, att);
return;
}
if ( vm->sched_action_update(sched_id, template_str, att.resp_msg) != 0 )
{
failure_response(INTERNAL, att);
return;
}
pool->update(vm.get());
success_response(oid, att);
return;
}

View File

@ -53,7 +53,8 @@ source_files=[
'RequestManagerVirtualRouter.cc',
'RequestManagerSecurityGroup.cc',
'RequestManagerVNTemplate.cc',
'RequestManagerHook.cc'
'RequestManagerHook.cc',
'RequestManagerSchedAction.cc'
]
# Build library

View File

@ -82,6 +82,7 @@ public:
*
* @return 0 on success, -1 otherwise
*/
[[deprecated("This method may cause race condition issues")]]
int update(VirtualMachineXML * vm) const
{
std::string xml;
@ -175,7 +176,7 @@ protected:
{
std::ostringstream oss;
oss << "/VM_POOL/VM/USER_TEMPLATE/SCHED_ACTION[(TIME < " << time(0)
oss << "/VM_POOL/VM/TEMPLATE/SCHED_ACTION[(TIME < " << time(0)
<< " and (not(DONE > 0) or boolean(REPEAT))) or ( TIME[starts-with(text(),\"+\")] and not(DONE>0) ) ]/../..";
return get_nodes(oss.str().c_str(), content);

View File

@ -406,9 +406,16 @@ public:
*/
SchedActions get_actions() const
{
return SchedActions(user_template.get());
return SchedActions(vm_template.get());
}
/**
* Update scheduled action of the VM
*
* @param action sched action to update
*/
bool update_sched_action(SchedAction* action);
/**
* Sets an attribute in the VM Template, it must be allocated in the heap
*

View File

@ -681,6 +681,39 @@ int VirtualMachineXML::parse_action_name(string& action_st)
return 0;
};
//******************************************************************************
// Updates to oned
//******************************************************************************
bool VirtualMachineXML::update_sched_action(SchedAction* action)
{
xmlrpc_c::value result;
try
{
string action_id_str = action->vector_value("ID");
int action_id = std::stoi(action_id_str);
ostringstream oss;
oss << "<TEMPLATE>";
action->to_xml(oss);
oss << "</TEMPLATE>";
Client::client()->call("one.vm.schedupdate", "iis", &result, oid,
action_id,
oss.str().c_str());
}
catch (exception const& e)
{
return false;
}
vector<xmlrpc_c::value> values =
xmlrpc_c::value_array(result).vectorValueValue();
return xmlrpc_c::value_boolean(values[0]);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -1741,12 +1741,15 @@ int Scheduler::do_scheduled_actions()
oss << "Failure. " << error_msg;
}
NebulaLog::log("VM", Log::INFO, oss);
}
if (!vm->update_sched_action(action))
{
ostringstream oss;
action->to_xml(oss);
NebulaLog::warn("SCHED", string("Unable to update sched action: ")
+ oss.str());
}
if ( !sas.empty() ) //Do not update VMs without SCHED_ACTION
{
vmpool->update(vm);
NebulaLog::log("VM", Log::INFO, oss);
}
}

View File

@ -2604,17 +2604,6 @@ int VirtualMachine::replace_template(
return -1;
}
/* ---------------------------------------------------------------------- */
/* Parse attributes in USER_TEMPLATE: */
/* - SCHED_ACTION */
/* ---------------------------------------------------------------------- */
SchedActions sactions(new_tmpl.get());
if ( sactions.parse(error, false) == -1 )
{
return -1;
}
/* ---------------------------------------------------------------------- */
/* Replace new_tmpl to the current user_template */
/* ---------------------------------------------------------------------- */
@ -2674,17 +2663,6 @@ int VirtualMachine::append_template(
return -1;
}
/* ---------------------------------------------------------------------- */
/* Parse attributes in USER_TEMPLATE: */
/* - SCHED_ACTION */
/* ---------------------------------------------------------------------- */
SchedActions sactions(new_tmpl.get());
if ( sactions.parse(error, false) == -1 )
{
return -1;
}
/* ---------------------------------------------------------------------- */
/* Append new_tmpl to the current user_template */
/* ---------------------------------------------------------------------- */
@ -3556,9 +3534,18 @@ void VirtualMachine::release_vmgroup()
int VirtualMachine::parse_sched_action(string& error_str)
{
SchedActions sactions(user_obj_template.get());
vector<VectorAttribute*> vas;
return sactions.parse(error_str, false);
if (user_obj_template->remove("SCHED_ACTION", vas) == 0)
{
return 0;
}
int rc = SchedActions::parse(vas, error_str, true, true);
obj_template->set(vas);
return rc;
}
/* ------------------------------------------------------------------------ */
@ -3624,6 +3611,118 @@ int VirtualMachine::check_shareable_disks(const string& vmm_mad, string& error)
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int VirtualMachine::sched_action_add(const string& sched_template,
std::string& error)
{
// Read and verify SCHED_ACTION in incoming string
VirtualMachineTemplate new_tmpl(false, '=', "TEMPLATE");
if (new_tmpl.parse_str_or_xml(sched_template, error) != 0 )
{
return -1;
}
vector<VectorAttribute*> sa;
if (new_tmpl.remove("SCHED_ACTION", sa) == 0 || sa.empty())
{
error = "Cannot read SCHED_ACTION from the template: " + sched_template;
return -1;
}
vector<const VectorAttribute*> vm_sa;
obj_template->get("SCHED_ACTION", vm_sa);
VectorAttribute * new_sa = SchedActions::new_action(vm_sa, sa[0], error);
if (!new_sa)
{
return -1;
}
obj_template->set(new_sa);
return 0;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int VirtualMachine::sched_action_delete(int sched_id, std::string& error)
{
vector<VectorAttribute*> sched_actions;
obj_template->get("SCHED_ACTION", sched_actions);
VectorAttribute* sa = SchedActions::get_action(sched_actions, sched_id);
if (!sa)
{
error = "Sched action with id = " + to_string(sched_id) +
"doesn't exist";
return -1;
}
obj_template->remove(sa);
return 0;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int VirtualMachine::sched_action_update(int sched_id,
const string& sched_template,
std::string& error)
{
// Get SchedAction with ID = sched_id
vector<VectorAttribute*> sched_actions;
obj_template->get("SCHED_ACTION", sched_actions);
VectorAttribute* sa = SchedActions::get_action(sched_actions, sched_id);
if (!sa)
{
error = "Sched action with id = " + to_string(sched_id) +
"doesn't exist";
return -1;
}
// Read and verify SCHED_ACTION in incoming string
VirtualMachineTemplate new_tmpl(false, '=', "TEMPLATE");
if (new_tmpl.parse_str_or_xml(sched_template, error) != 0 )
{
return -1;
}
vector<VectorAttribute*> new_sa_v;
if (new_tmpl.remove("SCHED_ACTION", new_sa_v) == 0 || new_sa_v.empty())
{
error = "Cannot read SCHED_ACTION from the template: " + sched_template;
return -1;
}
SchedAction new_sa(new_sa_v[0], sched_id);
if ( new_sa.parse(error, false) == -1 )
{
return -1;
}
new_sa_v[0]->replace("ID", sched_id);
sa->replace(new_sa_v[0]->value());
return 0;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
void VirtualMachine::encrypt()
{
std::string one_key;

View File

@ -455,3 +455,99 @@ time_t SchedAction::next_action()
return action_time;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int SchedActions::parse(std::vector<VectorAttribute *>& vas,
std::string& error, bool clean, bool set_id)
{
unsigned int sched_id = 0;
std::string err;
int rc = 0;
for (auto it = vas.begin(); it != vas.end(); )
{
if ( (*it)->type() != Attribute::VECTOR )
{
delete *it;
it = vas.erase(it);
}
else
{
if (set_id)
{
(*it)->replace("ID", sched_id++);
}
SchedAction sa(*it, sched_id);
if ( sa.parse(err, clean) == -1 )
{
std::ostringstream oss;
oss << " SCHED_ACTION: " << sched_id << ". Parse error: "<< err;
error += oss.str();
rc = -1;
}
++it;
}
}
return rc;
}
/* -------------------------------------------------------------------------- */
VectorAttribute * SchedActions::new_action(
const std::vector<const VectorAttribute *>& vas,
VectorAttribute * va, std::string &err)
{
int max_id = -1;
for(auto const *_va : vas)
{
int id = -1;
if (_va->vector_value("ID", id) == 0)
{
max_id = std::max(max_id, id);
}
}
SchedAction sched_action(va, max_id + 1);
if (sched_action.parse(err, true) == -1)
{
return nullptr;
}
VectorAttribute * new_sa = new VectorAttribute(va);
new_sa->replace("ID", max_id + 1);
return new_sa;
}
/* -------------------------------------------------------------------------- */
VectorAttribute * SchedActions::get_action(
const std::vector<VectorAttribute *>& sched_actions, int id)
{
for (auto *va : sched_actions)
{
int _id;
if (va->vector_value("ID", _id) == 0 && _id == id)
{
return va;
}
}
return nullptr;
}

View File

@ -188,9 +188,18 @@ int VMTemplate::bootstrap(SqlDB * db)
int VMTemplate::parse_sched_action(string& error_str)
{
SchedActions sactions(obj_template.get());
vector<VectorAttribute*> vas;
return sactions.parse(error_str, true);
if (obj_template->remove("SCHED_ACTION", vas) == 0)
{
return 0;
}
int rc = SchedActions::parse(vas, error_str, true, false);
obj_template->set(vas);
return rc;
}
/* ------------------------------------------------------------------------ */