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:
parent
e73c78869b
commit
e60efb1480
@ -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_*/
|
||||
|
@ -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
|
||||
|
205
src/um/Quota.cc
205
src/um/Quota.cc
@ -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;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -25,7 +25,7 @@ source_files=[
|
||||
'User.cc',
|
||||
'UserPool.cc',
|
||||
'Quota.cc',
|
||||
'QuotaDatastore.cc'
|
||||
# 'QuotaDatastore.cc'
|
||||
]
|
||||
|
||||
# Build library
|
||||
|
Loading…
x
Reference in New Issue
Block a user