mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-22 18:50:08 +03:00
Feature #1483: Scheduler executes scheduled actions
Syntax inside VM/USER_TEMPLATE: SCHED_ACTION = [ ACTION = "resume/stop/shutdown...", TIME=12345 ]
This commit is contained in:
parent
047a3d4e26
commit
f9b7f820c6
@ -133,6 +133,9 @@ protected:
|
||||
*/
|
||||
virtual int set_up_pools();
|
||||
|
||||
|
||||
virtual int scheduled_actions();
|
||||
|
||||
private:
|
||||
Scheduler(Scheduler const&){};
|
||||
|
||||
|
@ -43,6 +43,15 @@ public:
|
||||
*/
|
||||
int set_up();
|
||||
|
||||
/**
|
||||
* Retrieves the VMs with scheduled actions
|
||||
*
|
||||
* @return 0 on success
|
||||
* -1 on error
|
||||
* -2 if no VMs need to be scheduled
|
||||
*/
|
||||
int set_up_actions();
|
||||
|
||||
/**
|
||||
* Gets an object from the pool
|
||||
* @param oid the object unique identifier
|
||||
@ -66,12 +75,16 @@ public:
|
||||
* Update the VM template
|
||||
* @param vid the VM id
|
||||
* @param st the template string
|
||||
*
|
||||
* @return 0 on success, -1 otherwise
|
||||
*/
|
||||
int update(int vid, const string &st) const;
|
||||
|
||||
/**
|
||||
* Update the VM template
|
||||
* @param the VM
|
||||
*
|
||||
* @return 0 on success, -1 otherwise
|
||||
*/
|
||||
int update(VirtualMachineXML * vm) const
|
||||
{
|
||||
@ -80,20 +93,35 @@ public:
|
||||
return update(vm->get_oid(), vm->get_template(xml));
|
||||
};
|
||||
|
||||
/**
|
||||
* Calls one.vm.action
|
||||
*
|
||||
* @param vid The VM id
|
||||
* @param action Action argument (shutdown, hold, release...)
|
||||
* @param error_msg Error reason, if any
|
||||
*
|
||||
* @return 0 on success, -1 otherwise
|
||||
*/
|
||||
int action(int vid, const string &action, string &error_msg) const;
|
||||
|
||||
protected:
|
||||
|
||||
int get_suitable_nodes(vector<xmlNodePtr>& content)
|
||||
{
|
||||
return get_nodes("/VM_POOL/VM[STATE=1 or (LCM_STATE=3 and RESCHED=1)]",
|
||||
content);
|
||||
};
|
||||
int get_suitable_nodes(vector<xmlNodePtr>& content);
|
||||
|
||||
virtual void add_object(xmlNodePtr node);
|
||||
|
||||
virtual int load_info(xmlrpc_c::value &result);
|
||||
|
||||
/* Do live migrations to resched VMs*/
|
||||
/**
|
||||
* Do live migrations to resched VMs
|
||||
*/
|
||||
bool live_resched;
|
||||
|
||||
/**
|
||||
* True to retrieve pending/resched VMs, false to get VMs with scheduled
|
||||
* actions
|
||||
*/
|
||||
bool retrieve_pending;
|
||||
};
|
||||
|
||||
#endif /* VM_POOL_XML_H_ */
|
||||
|
@ -124,6 +124,16 @@ public:
|
||||
return xml_str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a the VM Template
|
||||
*
|
||||
* @return A pointer to the VM Template (not to a copy)
|
||||
*/
|
||||
VirtualMachineTemplate* get_template()
|
||||
{
|
||||
return vm_template;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function to write a Virtual Machine in an output stream
|
||||
*/
|
||||
|
@ -22,6 +22,8 @@ int VirtualMachinePoolXML::set_up()
|
||||
ostringstream oss;
|
||||
int rc;
|
||||
|
||||
retrieve_pending = true;
|
||||
|
||||
rc = PoolXML::set_up();
|
||||
|
||||
if ( rc == 0 )
|
||||
@ -50,6 +52,63 @@ int VirtualMachinePoolXML::set_up()
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachinePoolXML::set_up_actions()
|
||||
{
|
||||
ostringstream oss;
|
||||
int rc;
|
||||
|
||||
retrieve_pending = false;
|
||||
|
||||
rc = PoolXML::set_up();
|
||||
|
||||
if ( rc == 0 )
|
||||
{
|
||||
if (objects.empty())
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
|
||||
oss.str("");
|
||||
oss << "VMs with scheduled actions:" << endl;
|
||||
|
||||
map<int,ObjectXML*>::iterator it;
|
||||
|
||||
for (it=objects.begin();it!=objects.end();it++)
|
||||
{
|
||||
oss << " " << it->first;
|
||||
}
|
||||
|
||||
NebulaLog::log("VM",Log::DEBUG,oss);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachinePoolXML::get_suitable_nodes(vector<xmlNodePtr>& content)
|
||||
{
|
||||
if (retrieve_pending)
|
||||
{
|
||||
return get_nodes(
|
||||
"/VM_POOL/VM[STATE=1 or (LCM_STATE=3 and RESCHED=1)]",
|
||||
content);
|
||||
}
|
||||
|
||||
ostringstream oss;
|
||||
|
||||
oss << "/VM_POOL/VM/USER_TEMPLATE/SCHED_ACTION[TIME < " << time(0)
|
||||
<< " and not(DONE > 0)]/../..";
|
||||
|
||||
return get_nodes(
|
||||
oss.str().c_str(),
|
||||
content);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void VirtualMachinePoolXML::add_object(xmlNodePtr node)
|
||||
{
|
||||
if ( node == 0 || node->children == 0 || node->children->next==0 )
|
||||
@ -209,3 +268,45 @@ int VirtualMachinePoolXML::update(int vid, const string &st) const
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachinePoolXML::action(
|
||||
int vid,
|
||||
const string& action,
|
||||
string& error_msg) const
|
||||
{
|
||||
xmlrpc_c::value result;
|
||||
bool success;
|
||||
|
||||
try
|
||||
{
|
||||
client->call( client->get_endpoint(), // serverUrl
|
||||
"one.vm.action", // methodName
|
||||
"ssi", // arguments format
|
||||
&result, // resultP
|
||||
client->get_oneauth().c_str(), // session
|
||||
action.c_str(), // action
|
||||
vid // VM ID
|
||||
);
|
||||
}
|
||||
catch (exception const& e)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
vector<xmlrpc_c::value> values =
|
||||
xmlrpc_c::value_array(result).vectorValueValue();
|
||||
|
||||
success = xmlrpc_c::value_boolean(values[0]);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
error_msg = xmlrpc_c::value_string( values[1] );
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -623,12 +623,150 @@ void Scheduler::dispatch()
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int Scheduler::scheduled_actions()
|
||||
{
|
||||
int rc = vmpool->set_up_actions();
|
||||
|
||||
if ( rc != 0 )
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
VirtualMachineXML* vm;
|
||||
VirtualMachineTemplate* vm_template;
|
||||
|
||||
vector<string> v_st;
|
||||
|
||||
map<int, ObjectXML*>::const_iterator vm_it;
|
||||
|
||||
vector<Attribute *> attributes;
|
||||
vector<Attribute *>::iterator it;
|
||||
|
||||
VectorAttribute* vatt;
|
||||
|
||||
time_t the_time = time(0);
|
||||
|
||||
int action_time, done_time, has_time, has_done;
|
||||
string action_st, error_msg;
|
||||
|
||||
// TODO: Move the time string creation to a common place
|
||||
|
||||
char time_str[26];
|
||||
|
||||
ostringstream oss;
|
||||
ostringstream oss_aux;
|
||||
|
||||
#ifdef SOLARIS
|
||||
ctime_r(&(the_time),time_str,sizeof(char)*26);
|
||||
#else
|
||||
ctime_r(&(the_time),time_str);
|
||||
#endif
|
||||
|
||||
time_str[24] = '\0'; // Get rid of final enter character
|
||||
|
||||
|
||||
const map<int, ObjectXML*> vms = vmpool->get_objects();
|
||||
|
||||
for (vm_it=vms.begin(); vm_it != vms.end(); vm_it++)
|
||||
{
|
||||
vm = static_cast<VirtualMachineXML*>(vm_it->second);
|
||||
vm_template = vm->get_template();
|
||||
|
||||
attributes.clear();
|
||||
vm_template->remove("SCHED_ACTION", attributes);
|
||||
|
||||
// TODO: Sort actions by TIME
|
||||
|
||||
for (it=attributes.begin(); it != attributes.end(); it++)
|
||||
{
|
||||
vatt = dynamic_cast<VectorAttribute*>(*it);
|
||||
|
||||
if (vatt == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
has_time = vatt->vector_value("TIME", action_time);
|
||||
has_done = vatt->vector_value("DONE", done_time);
|
||||
|
||||
// TODO: Transform to lower case
|
||||
action_st = vatt->vector_value("ACTION");
|
||||
|
||||
if (has_time == 0 && has_done == -1 && action_time < the_time)
|
||||
{
|
||||
oss.str("");
|
||||
|
||||
// onevm delete command uses the xml-rpc finalize action
|
||||
if (action_st == "delete")
|
||||
{
|
||||
action_st = "finalize";
|
||||
}
|
||||
|
||||
oss << "Executing action '" << action_st << "' for VM "
|
||||
<< vm->get_oid() << " : ";
|
||||
|
||||
if ( action_st != "shutdown"
|
||||
&& action_st != "hold"
|
||||
&& action_st != "release"
|
||||
&& action_st != "stop"
|
||||
&& action_st != "cancel"
|
||||
&& action_st != "suspend"
|
||||
&& action_st != "resume"
|
||||
&& action_st != "restart"
|
||||
&& action_st != "resubmit"
|
||||
&& action_st != "reboot"
|
||||
&& action_st != "reset"
|
||||
&& action_st != "poweroff"
|
||||
&& action_st != "finalize")
|
||||
{
|
||||
error_msg = "This action is not supported.";
|
||||
rc = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = vmpool->action(vm->get_oid(), action_st, error_msg);
|
||||
}
|
||||
|
||||
if (rc == 0)
|
||||
{
|
||||
vatt->remove("MESSAGE");
|
||||
vatt->replace("DONE", static_cast<int>(the_time));
|
||||
|
||||
oss << "Success.";
|
||||
}
|
||||
else
|
||||
{
|
||||
oss_aux.str("");
|
||||
oss_aux << time_str << " : " << error_msg;
|
||||
|
||||
vatt->replace("MESSAGE", oss_aux.str());
|
||||
|
||||
oss << "Failure. " << error_msg;
|
||||
}
|
||||
|
||||
NebulaLog::log("VM",Log::INFO,oss);
|
||||
}
|
||||
|
||||
vm_template->set(vatt);
|
||||
}
|
||||
|
||||
vmpool->update(vm);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void Scheduler::do_action(const string &name, void *args)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (name == ACTION_TIMER)
|
||||
{
|
||||
scheduled_actions();
|
||||
|
||||
rc = set_up_pools();
|
||||
|
||||
if ( rc != 0 )
|
||||
|
Loading…
x
Reference in New Issue
Block a user