1
0
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:
Carlos Martín 2013-02-04 18:09:18 +01:00
parent 047a3d4e26
commit f9b7f820c6
5 changed files with 286 additions and 6 deletions

View File

@ -133,6 +133,9 @@ protected:
*/
virtual int set_up_pools();
virtual int scheduled_actions();
private:
Scheduler(Scheduler const&){};

View File

@ -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_ */

View File

@ -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
*/

View File

@ -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;
}

View File

@ -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 )