1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-04-02 10:50:07 +03:00

featue #1739: Move Host and VM update functions to each class.

This commit is contained in:
Ruben S. Montero 2013-02-16 02:55:17 +01:00
parent fd73ebf919
commit 701f33ca5f
11 changed files with 422 additions and 317 deletions

View File

@ -80,27 +80,6 @@ public:
return ((state == MONITORING_ERROR) || (state==MONITORING_MONITORED));
}
/**
* Updates the Host's last_monitored time stamp.
* @param success if the monitored action was successfully performed
*/
void touch(bool success)
{
last_monitored = time(0);
if ( state != DISABLED) //Don't change the state is host is disabled
{
if (success == true)
{
state = MONITORED;
}
else
{
state = ERROR;
}
}
};
/**
* Disables the current host, it will not be monitored nor used by the
* scheduler
@ -119,11 +98,27 @@ public:
state = INIT;
};
/** Update host counters and update the whole host on the DB
/**
* Update host after a successful monitor. It modifies counters, state
* and template attributes
* @param parse_str string with values to be parsed
* @param with_vm_info if monitoring contains VM information
* @param lost set of VMs that should be in the host and were not found
* @param found VMs running in the host (as expected) and info.
* @return 0 on success
**/
int update_info(string &parse_str);
int update_info(string &parse_str,
bool &with_vm_info,
set<int> &lost,
map<int,string> &found);
/**
* Update host after a failed monitor. It state
* and template attributes
* @param message from the driver
* @param vm_ids running on the host
*/
void error_info(const string& message, set<int> &vm_ids);
/**
* Inserts the last monitoring, and deletes old monitoring entries.
@ -419,6 +414,31 @@ private:
virtual ~Host();
// *************************************************************************
// Host Management
// *************************************************************************
/**
* Updates the Host's last_monitored time stamp.
* @param success if the monitored action was successfully performed
*/
void touch(bool success)
{
last_monitored = time(0);
if ( state != DISABLED) //Don't change the state is host is disabled
{
if (success == true)
{
state = MONITORED;
}
else
{
state = ERROR;
}
}
};
// *************************************************************************
// DataBase implementation (Private)
// *************************************************************************

View File

@ -408,12 +408,24 @@ public:
void clear_template_error_message();
/**
* Sets a message with timestamp in the template
* Adds a string attribute
* @param att_name Name for the attribute
* @param message Message string
* @return 0 on success
* @param att_val Message string
*/
void set_template_message(const string& att_name, const string& message);
void add_template_attribute(const string& name, const string& value)
{
obj_template->add(name, value);
}
/**
* Adds an int attribute
* @param att_name Name for the attribute
* @param att_val integer
*/
void add_template_attribute(const string& name, int value)
{
obj_template->add(name, value);
}
/**
* Factory method for templates, it should be implemented

View File

@ -171,7 +171,7 @@ public:
};
/**
* Updates VM dynamic information (usage counters).
* Updates VM dynamic information (usage counters), and updates last_poll
* @param _memory Kilobytes used by the VM (total)
* @param _cpu used by the VM (rate)
* @param _net_tx transmitted bytes (total)
@ -181,28 +181,8 @@ public:
const int _memory,
const int _cpu,
const long long _net_tx,
const long long _net_rx)
{
if (_memory != -1)
{
memory = _memory;
}
if (_cpu != -1)
{
cpu = _cpu;
}
if (_net_tx != -1)
{
net_tx = _net_tx;
}
if (_net_rx != -1)
{
net_rx = _net_rx;
}
};
const long long _net_rx,
const map<string, string> &custom);
/**
* Returns the deployment ID
@ -778,15 +758,6 @@ public:
return last_poll;
};
/**
* Sets time of last information polling.
* @param poll time in epoch, normally time(0)
*/
void set_last_poll(time_t poll)
{
last_poll = poll;
};
/**
* Get the VM physical requirements for the host.
* @param cpu

View File

@ -121,11 +121,6 @@ private:
*/
time_t timer_period;
/**
* Time when the VMM was started
*/
time_t timer_start;
/**
* Virtual Machine polling interval
*/

View File

@ -84,13 +84,6 @@ public:
*/
static void process_poll(VirtualMachine* vm, const string &monitor_str);
/**
* Updates the VM after a failed poll driver action
*
* @param id VM id
*/
static void process_failed_poll(int id);
protected:
/**
* Gets a configuration attr from driver configuration file (single
@ -291,8 +284,6 @@ private:
write_drv("DETACHDISK", oid, drv_msg);
}
private:
void write_drv(const char * aname, const int oid, const string& msg) const
{
ostringstream os;
@ -301,6 +292,32 @@ private:
write(os);
}
/**
* Gets VM information from the driver answer
* @param monitor_str from the driver
* @param memory Kilobytes used by the VM (total)
* @param cpu used by the VM (rate)
* @param net_tx transmitted bytes (total)
* @param net_rx received bytes (total)
* @param state of the vm
* @param custom monitor information
*/
static int parse_vm_info(
const string& monitor_str,
int &cpu,
int &memory,
long long &net_tx,
long long &net_rx,
char &state,
map<string,string> &custom);
/**
* Based on the monitoring state updates or trigger LCM actions
* @param vm virtual machine
* @param state from driver
*/
static void process_poll_state(VirtualMachine* vm, char state);
};
/* -------------------------------------------------------------------------- */

View File

@ -170,22 +170,60 @@ error_common:
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int Host::update_info(string &parse_str)
int Host::update_info(string &parse_str,
bool &with_vm_info,
set<int> &lost,
map<int,string> &found)
{
char * error_msg;
int rc;
float fv;
char * error_msg;
Template* tmpl;
VectorAttribute* vatt;
vector<Attribute*>::iterator it;
vector<Attribute*> vm_att;
int rc;
int vmid;
float fv;
ostringstream zombie;
ostringstream wild;
int num_zombies = 0;
int num_wilds = 0;
//
// ---------------------------------------------------------------------- //
// Parse Template (twice because of repeated VM values) //
// ---------------------------------------------------------------------- //
rc = obj_template->parse(parse_str, &error_msg);
if ( rc != 0 )
{
NebulaLog::log("ONE", Log::ERROR, error_msg);
ostringstream ess;
ess << "Error parsing host information: " << error_msg
<< "Monitoring information: " << parse_str;
NebulaLog::log("ONE", Log::ERROR, ess);
touch(false);
set_template_error_message("Error parsing monitor information."
" Check oned.log for more details.");
free(error_msg);
return -1;
}
tmpl = new Template();
tmpl->parse(parse_str, &error_msg);
// ---------------------------------------------------------------------- //
// Extract share information //
// ---------------------------------------------------------------------- //
get_template_attribute("TOTALCPU", fv);
host_share.max_cpu = static_cast<int>(fv);
get_template_attribute("TOTALMEMORY", fv);
@ -201,12 +239,113 @@ int Host::update_info(string &parse_str)
get_template_attribute("USEDMEMORY", fv);
host_share.used_mem = static_cast<int>(fv);
// ---------------------------------------------------------------------- //
// Remove expired information //
// ---------------------------------------------------------------------- //
clear_template_error_message();
remove_template_attribute("ZOMBIES");
remove_template_attribute("TOTAL_ZOMBIES");
remove_template_attribute("WILDS");
remove_template_attribute("TOTAL_WILDS");
remove_template_attribute("VM");
get_template_attribute("VM_POLL", with_vm_info);
remove_template_attribute("VM_POLL");
// ---------------------------------------------------------------------- //
// Correlate VM information with the list of running VMs //
// ---------------------------------------------------------------------- //
tmpl->remove("VM", vm_att);
lost = get_running_vms();
for (it = vm_att.begin(); it != vm_att.end(); it++)
{
vatt = dynamic_cast<VectorAttribute*>(*it);
if (vatt == 0)
{
delete *it;
continue;
}
rc = vatt->vector_value("ID", vmid);
if (rc == 0 && vmid != -1)
{
if (lost.erase(vmid) == 1) //Good, known
{
found.insert(make_pair(vmid, vatt->vector_value("POLL")));
}
else //Bad, known but should not be here
{
if (num_zombies++ > 0)
{
zombie << ", ";
}
zombie << vatt->vector_value("DEPLOY_ID");
}
}
else if (rc == 0) //not ours
{
if (num_wilds++ > 0)
{
wild << ", ";
}
wild << vatt->vector_value("DEPLOY_ID");
}
delete *it;
}
if (num_wilds > 0)
{
add_template_attribute("TOTAL_WILDS", num_wilds);
add_template_attribute("WILDS", wild.str());
}
if (num_zombies > 0)
{
add_template_attribute("TOTAL_ZOMBIES", num_zombies);
add_template_attribute("ZOMBIES", zombie.str());
}
delete tmpl;
// Touch the host to update its last_monitored timestamp and state
touch(true);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void Host::error_info(const string& message, set<int> &vm_ids)
{
ostringstream oss;
vm_ids = vm_collection.get_collection_copy();
oss << "Error monitoring Host " << get_name() << " (" << get_oid() << ")"
<< ": " << message;
NebulaLog::log("ONE", Log::ERROR, oss);
touch(false);
set_template_error_message(oss.str());
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Host::update_monitoring(SqlDB * db)
{
ostringstream oss;

View File

@ -16,6 +16,7 @@
#include "InformationManagerDriver.h"
#include "NebulaLog.h"
#include "Nebula.h"
#include "Util.h"
#include "VirtualMachineManagerDriver.h"
#include <sstream>
@ -96,6 +97,11 @@ void InformationManagerDriver::protocol(
{
bool vm_poll;
set<int> lost;
map<int,string> found;
int rc;
host = hpool->get(id,true);
if ( host == 0 )
@ -103,167 +109,72 @@ void InformationManagerDriver::protocol(
goto error_host;
}
vm_ids = host->get_running_vms();
getline (is, hinfo64);
hinfo = one_util::base64_decode(hinfo64);
if (result != "SUCCESS")
{
goto error_driver_info;
set<int> vm_ids;
host->error_info(*hinfo, vm_ids);
for (set<int>::iterator it = vm_ids.begin(); it != vm_ids.end(); it++)
{
Nebula &ne = Nebula::instance();
LifeCycleManager *lcm = ne.get_lcm();
lcm->trigger(LifeCycleManager::MONITOR_DONE, *it);
}
delete hinfo;
hpool->update(host);
host->unlock();
return;
}
int rc;
ostringstream oss;
int vmid;
char * error_msg;
string monitor_str;
VectorAttribute* vatt;
vector<Attribute*> vm_att;
vector<Attribute*>::iterator it;
oss << "Host " << id << " successfully monitored.";
NebulaLog::log("InM", Log::DEBUG, oss);
rc = host->update_info(*hinfo);
rc = host->update_info(*hinfo, vm_poll, lost, found);
if (rc != 0)
{
ess << "Error parsing host information: " << *hinfo;
delete hinfo;
goto error_common_info;
hpool->update(host);
host->unlock();
return;
}
host->clear_template_error_message();
host->remove_template_attribute("INFO_MESSAGE");
// The hinfo string is parsed again because HostTemplate has
// replace_mode set to true, but we expect several VM vector attributes
Template* tmpl = new Template();
tmpl->parse(*hinfo, &error_msg);
tmpl->remove("VM", vm_att);
delete hinfo;
host->get_template_attribute("VM_POLL", vm_poll);
host->remove_template_attribute("VM_POLL");
host->remove_template_attribute("VM");
host->touch(true);
hpool->update(host);
hpool->update_monitoring(host);
ess << "Host " << host->get_name() << " (" << host->get_oid() << ")"
<< " successfully monitored.";
NebulaLog::log("InM", Log::DEBUG, ess);
host->unlock();
vector<string> external_vms;
map<int,string> rogue_vms;
for (it=vm_att.begin(); it != vm_att.end(); it++)
{
vatt = dynamic_cast<VectorAttribute*>(*it);
if (vatt == 0)
{
delete *it;
continue;
}
rc = vatt->vector_value("ID", vmid);
if (rc == 0 && vmid != -1)
{
if (vm_ids.erase(vmid) == 1)
{
monitor_str = vatt->vector_value("POLL");
VirtualMachineManagerDriver::process_poll(vmid, monitor_str);
}
else
{
rogue_vms[vmid] = vatt->vector_value("DEPLOY_ID");
}
}
else if (rc == 0)
{
external_vms.push_back( vatt->vector_value("DEPLOY_ID") );
}
delete *it;
}
if (vm_poll)
{
for (set<int>::iterator it = vm_ids.begin(); it != vm_ids.end(); it++)
set<int>::iterator its;
map<int,string>::iterator itm;
for (its = lost.begin(); its != lost.end(); its++)
{
// This VM should be running on this host, but it was not reported
Nebula &ne = Nebula::instance();
LifeCycleManager *lcm = ne.get_lcm();
VirtualMachineManagerDriver::process_failed_poll(*it);
}
}
bool log_error = false;
bool log_info = false;
if (!rogue_vms.empty())
{
log_error = true;
map<int,string>::iterator it;
ess.str("");
ess << "Manual intervention required, these VMs should"
<< " not be running on Host " << id << ":";
for(it = rogue_vms.begin(); it != rogue_vms.end(); it++)
{
ess << " VM " << it->first << " (hypervisor name '" << it->second << "')";
lcm->trigger(LifeCycleManager::MONITOR_DONE, *its);
}
NebulaLog::log("InM",Log::ERROR,ess);
}
if (!external_vms.empty())
{
log_info = true;
vector<string>::iterator it;
oss.str("");
oss << "External VMs found:";
for(it = external_vms.begin(); it != external_vms.end(); it++)
for (itm = found.begin(); itm != found.end(); itm++)
{
oss << " " << *it;
}
}
if (log_error || log_info)
{
host = hpool->get(id,true);
if ( host != 0 )
{
if (log_error)
{
host->set_template_error_message(ess.str());
}
if (log_info)
{
host->set_template_message("INFO_MESSAGE", oss.str());
}
hpool->update(host);
host->unlock();
VirtualMachineManagerDriver::process_poll(itm->first, itm->second);
}
}
}
@ -277,31 +188,6 @@ void InformationManagerDriver::protocol(
return;
error_driver_info:
ess << "Error monitoring host " << id << " : " << *hinfo;
delete hinfo;
for (set<int>::iterator it = vm_ids.begin(); it != vm_ids.end(); it++)
{
VirtualMachineManagerDriver::process_failed_poll(*it);
}
goto error_common_info;
error_common_info:
NebulaLog::log("InM",Log::ERROR,ess);
host->set_template_error_message(ess.str());
host->touch(false);
hpool->update(host);
host->unlock();
return;
error_host:
ess << "Could not get host " << id;
NebulaLog::log("InM",Log::ERROR,ess);
@ -309,7 +195,6 @@ error_host:
return;
error_parse:
ess << "Error while parsing driver message: " << message;
NebulaLog::log("InM",Log::ERROR,ess);

View File

@ -138,7 +138,17 @@ const char * PoolObjectSQL::error_attribute_name = "ERROR";
void PoolObjectSQL::set_template_error_message(const string& message)
{
set_template_message(error_attribute_name, message);
SingleAttribute * attr;
ostringstream error_value;
error_value << one_util::log_time() << " : " << message;
//Replace previous error message and insert the new one
attr = new SingleAttribute(error_attribute_name, error_value.str());
obj_template->erase(error_attribute_name);
obj_template->set(attr);
}
/* -------------------------------------------------------------------------- */
@ -152,26 +162,6 @@ void PoolObjectSQL::clear_template_error_message()
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void PoolObjectSQL::set_template_message(
const string& att_name,
const string& message)
{
SingleAttribute * attr;
ostringstream error_value;
error_value << one_util::log_time() << " : " << message;
//Replace previous error message and insert the new one
attr = new SingleAttribute(att_name, error_value.str());
obj_template->erase(att_name);
obj_template->set(attr);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int PoolObjectSQL::replace_template(const string& tmpl_str, string& error)
{
Template * new_tmpl = get_new_template();

View File

@ -2465,6 +2465,47 @@ string VirtualMachine::get_system_dir() const
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachine::update_info(
const int _memory,
const int _cpu,
const long long _net_tx,
const long long _net_rx,
const map<string, string> &custom)
{
map<string, string>::const_iterator it;
last_poll = time(0);
if (_memory != -1)
{
memory = _memory;
}
if (_cpu != -1)
{
cpu = _cpu;
}
if (_net_tx != -1)
{
net_tx = _net_tx;
}
if (_net_rx != -1)
{
net_rx = _net_rx;
}
for (it = custom.begin(); it != custom.end(); it++)
{
replace_template_attribute(it->first, it->second);
}
set_vm_info();
clear_template_error_message();
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -40,7 +40,6 @@ VirtualMachineManager::VirtualMachineManager(
vmpool(_vmpool),
hpool(_hpool),
timer_period(_timer_period),
timer_start(0),
poll_period(_poll_period),
vm_limit(_vm_limit)
{
@ -64,8 +63,6 @@ extern "C" void * vmm_action_loop(void *arg)
NebulaLog::log("VMM",Log::INFO,"Virtual Machine Manager started.");
vmm->timer_start = time(0);
if ( vmm->poll_period == 0 )
{
NebulaLog::log("VMM",Log::INFO,"VM monitoring is disabled.");
@ -1422,7 +1419,8 @@ error_common:
void VirtualMachineManager::timer_action()
{
static int mark = 0;
static int mark = 0;
static int timer_start = time(0);
VirtualMachine * vm;
vector<int> oids;

View File

@ -400,9 +400,12 @@ void VirtualMachineManagerDriver::protocol(
}
else
{
log_error(vm,os,is,"Error monitoring VM");
Nebula &ne = Nebula::instance();
LifeCycleManager* lcm = ne.get_lcm();
process_poll(vm, "STATE=d");
log_error(vm, os, is, "Error monitoring VM");
lcm->trigger(LifeCycleManager::MONITOR_DONE, vm->get_oid());
}
}
else if (action == "LOG")
@ -419,14 +422,6 @@ void VirtualMachineManagerDriver::protocol(
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineManagerDriver::process_failed_poll(int id)
{
process_poll(id, "STATE=d");
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineManagerDriver::process_poll(
int id,
const string &monitor_str)
@ -451,24 +446,76 @@ void VirtualMachineManagerDriver::process_poll(
VirtualMachine* vm,
const string& monitor_str)
{
size_t pos;
int rc;
int cpu;
int memory;
long long net_tx;
long long net_rx;
char state;
map<string, string> custom;
ostringstream oss;
VirtualMachinePool* vmpool = Nebula::instance().get_vmpool();
rc = parse_vm_info(monitor_str, cpu, memory, net_tx, net_rx, state, custom);
if (rc == -1)
{
vm->set_template_error_message("Error parsing monitoring information.");
vmpool->update(vm);
return;
}
oss << "VM " << vm->get_oid() << " successfully monitored: " << monitor_str;
NebulaLog::log("VMM", Log::INFO, oss);
vm->update_info(memory, cpu, net_tx, net_rx, custom);
vmpool->update(vm);
vmpool->update_history(vm);
vmpool->update_monitoring(vm);
process_poll_state(vm, state);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachineManagerDriver::parse_vm_info(
const string& monitor_str,
int &cpu,
int &memory,
long long &net_tx,
long long &net_rx,
char &state,
map<string,string> &custom)
{
istringstream is;
int parse_error = 0;
size_t pos;
string tmp;
string var;
string tmp;
string var;
ostringstream os;
istringstream tiss;
int cpu = -1;
int memory = -1;
long long net_tx = -1;
long long net_rx = -1;
char state = '-';
cpu = -1;
memory = -1;
net_tx = -1;
net_rx = -1;
state = '-';
bool parse_error = false;
custom.clear();
VirtualMachinePool * vmpool = Nebula::instance().get_vmpool();
istringstream is;
is.str(monitor_str);
while(is.good())
@ -479,7 +526,7 @@ void VirtualMachineManagerDriver::process_poll(
if ( pos == string::npos )
{
parse_error = true;
parse_error = -1;
continue;
}
@ -493,7 +540,7 @@ void VirtualMachineManagerDriver::process_poll(
if (!tiss.good())
{
parse_error = true;
parse_error = -1;
continue;
}
@ -523,61 +570,52 @@ void VirtualMachineManagerDriver::process_poll(
tiss >> val;
vm->replace_template_attribute(var,val);
custom.insert(make_pair(var, val));
}
}
if (parse_error)
return parse_error;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineManagerDriver::process_poll_state(
VirtualMachine* vm,
char state)
{
if (state == '-' ||
(vm->get_lcm_state() != VirtualMachine::RUNNING &&
vm->get_lcm_state() != VirtualMachine::UNKNOWN))
{
os.str("");
os << "Error parsing monitoring str:\"" << monitor_str <<"\"";
vm->log("VMM",Log::ERROR,os);
vm->set_template_error_message(os.str());
vmpool->update(vm);
return;
}
vm->set_last_poll(time(0));
Nebula &ne = Nebula::instance();
vm->update_info(memory,cpu,net_tx,net_rx);
vm->set_vm_info();
LifeCycleManager* lcm = ne.get_lcm();
VirtualMachinePool* vmpool = ne.get_vmpool();
vmpool->update(vm);
vmpool->update_history(vm);
vmpool->update_monitoring(vm);
if (state != '-' &&
(vm->get_lcm_state() == VirtualMachine::RUNNING ||
vm->get_lcm_state() == VirtualMachine::UNKNOWN))
switch (state)
{
Nebula &ne = Nebula::instance();
LifeCycleManager * lcm = ne.get_lcm();
switch (state)
{
case 'a': // Still active, good!
if ( vm->get_lcm_state() == VirtualMachine::UNKNOWN)
{
vm->log("VMM",Log::INFO,"VM was now found, new state is"
" RUNNING");
vm->log("VMM",Log::INFO,"VM found again, state is RUNNING");
vm->set_state(VirtualMachine::RUNNING);
vmpool->update(vm);
}
break;
case 'p': // It's paused
vm->log("VMM",Log::INFO,"VM running but new state "
"from monitor is PAUSED.");
vm->log("VMM",Log::INFO,"VM running but monitor state is PAUSED.");
lcm->trigger(LifeCycleManager::MONITOR_SUSPEND, vm->get_oid());
break;
case 'e': //Failed
vm->log("VMM",Log::INFO,"VM running but new state "
"from monitor is ERROR.");
vm->log("VMM",Log::INFO,"VM running but monitor state is ERROR.");
lcm->trigger(LifeCycleManager::MONITOR_FAILURE, vm->get_oid());
break;
@ -589,7 +627,6 @@ void VirtualMachineManagerDriver::process_poll(
lcm->trigger(LifeCycleManager::MONITOR_DONE, vm->get_oid());
break;
}
}
}