1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-02-02 09:47:00 +03:00

feature #1288: Generic Quota Management

This commit is contained in:
Ruben S. Montero 2012-06-05 01:58:37 +02:00
parent e73c78869b
commit e60efb1480
4 changed files with 254 additions and 25 deletions

View File

@ -59,14 +59,51 @@ protected:
virtual ~Quota(){};
/**
* Sets new limit values for the quota
* @param quota to be updated
* @param va attribute with the new limits
* @return 0 on success or -1 if wrong limits
/**
* Generic Quota Names
*
* template_name = [
* ID = "ID to identify the resource",
* metrics[0] = "Limit for the first metric"
* metrics[0]_USED = "Usage for metric"
* ]
*
* ID & counter fields are optional
*/
virtual int update_limits(VectorAttribute* quota,
const VectorAttribute* va) = 0;
/**
* Name of the quota used in the templates
*/
char * template_name;
/**
* The name of the quota metrics
*/
char ** metrics;
/**
* Length o
*/
int num_metrics;
/**
* Check a given quota for an usage request and update counters if the
* request does not exceed quota limits
* @param qid id that identifies the quota, to be used by get_quota
* @param usage_req usage for each metric
* @return true if the request does not exceed current limits
*/
bool check_quota(const string& qid,
map<string, int>& usage_req,
string& error);
/**
* Reduce usage from a given quota based on the current consumption
* @param qid id that identifies the quota, to be used by get_quota
* @param usage_req usage for each metric
*/
void del_quota(const string& qid,
map<string, int>& usage_req);
/**
* Creates an empty quota based on the given attribute. The attribute va
@ -81,7 +118,7 @@ protected:
* @param id of the quota
* @return a pointer to the quota or 0 if not found
*/
virtual VectorAttribute * get_quota(const string& id);
virtual int get_quota(const string& id, VectorAttribute **va);
/**
* Adds a new quota, it also updates an internal index for fast accessing
@ -97,6 +134,21 @@ protected:
* @param num value to add to the current quota;
*/
void add_to_quota(VectorAttribute * attr, const string& va_name, int num);
/**
* Sets new limit values for the quota
* @param quota to be updated
* @param va attribute with the new limits
* @return 0 on success or -1 if wrong limits
*/
int update_limits(VectorAttribute* quota, const VectorAttribute* va);
/**
* Extract the limits from a given attribute
* @param va the attribute with the limits
* @param
*/
int get_limits(const VectorAttribute * va, map<string, string>& limits);
};
#endif /*QUOTA_H_*/

View File

@ -63,8 +63,8 @@ protected:
* @param va attribute with the new limits
* @return 0 on success or -1 if wrong limits
*/
int update_limits(VectorAttribute* quota,
const VectorAttribute* va);
/*int update_limits(VectorAttribute* quota,
const VectorAttribute* va);*/
/**
* Creates an empty quota based on the given attribute. The attribute va

View File

@ -19,14 +19,16 @@
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
VectorAttribute * Quota::get_quota(const string& id)
int Quota::get_quota(const string& id, VectorAttribute ** va)
{
map<string, Attribute *>::iterator it;
VectorAttribute * q;
*va = 0;
if ( id.empty() )
{
return 0;
return -1;
}
for ( it = attributes.begin(); it != attributes.end(); it++)
@ -35,7 +37,8 @@ VectorAttribute * Quota::get_quota(const string& id)
if (q->vector_value("ID") == id)
{
return q;
*va = q;
return 0;
}
}
@ -47,15 +50,6 @@ VectorAttribute * Quota::get_quota(const string& id)
void Quota::add(VectorAttribute * nq)
{
string id;
id = nq->vector_value("ID");
if ( id.empty() )
{
return;
}
attributes.insert(make_pair(nq->name(), nq));
}
@ -93,7 +87,10 @@ int Quota::set(vector<VectorAttribute*> * new_quotas, string& error)
{
id = (*it)->vector_value("ID");
tq = get_quota(id);
if ( get_quota(id, &tq) == -1 )
{
goto error_limits;
}
if ( tq == 0 )
{
@ -111,7 +108,7 @@ int Quota::set(vector<VectorAttribute*> * new_quotas, string& error)
if (update_limits(tq, *it))
{
goto error_limits;
}
}
}
}
@ -127,3 +124,183 @@ error_limits:
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
bool Quota::check_quota(const string& qid,
map<string, int>& usage_req,
string& error)
{
VectorAttribute * q;
map<string, int>::iterator it;
bool check;
int limit;
int usage;
if ( get_quota(qid, &q) == -1 )
{
return false;
}
// -------------------------------------------------------------------------
// Quota does not exist, create a new one
// -------------------------------------------------------------------------
if ( q == 0 )
{
map<string, string> values;
for (int i=0; i < num_metrics; i++)
{
ostringstream usage_req_str;
string metrics_used = metrics[i];
metrics_used += "_USED";
it = usage_req.find(metrics[i]);
if (it == usage_req.end())
{
usage_req_str << "0";
}
else
{
usage_req_str << it->second;
}
values.insert(make_pair(metrics[i], "0"));
values.insert(make_pair(metrics_used, usage_req_str.str()));
}
if (!qid.empty())
{
values.insert(make_pair("ID", qid));
}
add(new VectorAttribute(template_name, values));
return true;
}
// -------------------------------------------------------------------------
// Check the quotas for each usage request
// -------------------------------------------------------------------------
for (int i=0; i < num_metrics; i++)
{
string metrics_used = metrics[i];
metrics_used += "_USED";
it = usage_req.find(metrics[i]);
if (it == usage_req.end())
{
continue;
}
q->vector_value(metrics[i], limit);
q->vector_value(metrics_used.c_str(), usage);
check = ( limit == 0 ) || ( ( usage + it->second ) <= limit );
if ( !check )
{
ostringstream oss;
oss << "Limit (" << limit << ") reached for " << metrics[i]
<< " in quota " << template_name;
if ( !qid.empty() )
{
oss << "with ID: " << qid;
}
error = oss.str();
return false;
}
}
// -------------------------------------------------------------------------
// Add resource usage to quotas
// -------------------------------------------------------------------------
for (int i=0; i < num_metrics; i++)
{
string metrics_used = metrics[i];
metrics_used += "_USED";
it = usage_req.find(metrics[i]);
if (it == usage_req.end())
{
continue;
}
add_to_quota(q, metrics_used, it->second);
}
return true;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void Quota::del_quota(const string& qid, map<string, int>& usage_req)
{
VectorAttribute * q;
map<string, int>::iterator it;
if ( get_quota(qid, &q) == -1)
{
return;
}
if ( q == 0 )
{
return;
}
for (int i=0; i < num_metrics; i++)
{
string metrics_used = metrics[i];
metrics_used += "_USED";
it = usage_req.find(metrics[i]);
if (it == usage_req.end())
{
continue;
}
add_to_quota(q, metrics_used, -it->second);
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Quota::update_limits(VectorAttribute * quota, const VectorAttribute * va)
{
string limit;
int limit_i;
for (int i=0; i < num_metrics; i++)
{
limit = va->vector_value(metrics[i], limit_i);
if ( !limit.empty() )
{
if ( limit_i < 0 )
{
return -1;
}
quota->replace(metrics[i], limit);
}
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -25,7 +25,7 @@ source_files=[
'User.cc',
'UserPool.cc',
'Quota.cc',
'QuotaDatastore.cc'
# 'QuotaDatastore.cc'
]
# Build library