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

feature #1288: Better interface for Quotas

This commit is contained in:
Ruben S. Montero 2012-06-04 00:45:56 +02:00
parent ce3609c28c
commit e73c78869b
6 changed files with 130 additions and 197 deletions

View File

@ -35,7 +35,7 @@ public:
* @param error describe the error in case of error
* @return 0 on success -1 otherwise
*/
int set(const string& quota_str, string& error);
int set(vector<VectorAttribute*> * quotas, string& error);
/**
* Check if the resource allocation will exceed the quota limits. If not
@ -44,19 +44,14 @@ public:
* @param error string
* @return true if the operation can be performed
*/
virtual bool check_add(Template* tmpl, string& error)
{
return false;
}
virtual bool check(Template* tmpl, string& error) = 0;
/**
* Decrement usage counters when deallocating image
* @param tmpl template for the resource
*/
virtual void del(Template* tmpl)
{
return;
}
virtual void del(Template* tmpl) = 0;
protected:
@ -70,10 +65,8 @@ protected:
* @param va attribute with the new limits
* @return 0 on success or -1 if wrong limits
*/
virtual int update_limits(Attribute* quota, const Attribute* va)
{
return -1;
};
virtual int update_limits(VectorAttribute* quota,
const VectorAttribute* va) = 0;
/**
* Creates an empty quota based on the given attribute. The attribute va
@ -81,29 +74,21 @@ protected:
* @param va limits for the new quota if 0 limits will be 0
* @return a new attribute representing the quota
*/
virtual Attribute * new_quota(Attribute* va)
{
return 0;
}
/**
* Gets a quota for a given resource. The resource is specified as a
* Template attribute. Derived class should return a quota that matches the
* resource.
* @param base_attribute describing the quota with the new limits
* @return pointer to the quota on success or 0 otherwise
*/
virtual Attribute * get_quota(const Attribute* base_attribute)
{
return 0;
};
virtual VectorAttribute * new_quota(VectorAttribute* va) = 0;
/**
* Adds a given value to the current quota (single)
* @param attr the quota with a numeric value
* @param num value to add to the current quota
* Gets a quota identified by its ID.
* @param id of the quota
* @return a pointer to the quota or 0 if not found
*/
void add_to_quota(SingleAttribute * attr, float num);
virtual VectorAttribute * get_quota(const string& id);
/**
* Adds a new quota, it also updates an internal index for fast accessing
* the quotas
* @param quota is the new quota, allocated in the HEAP
*/
virtual void add(VectorAttribute * quota);
/**
* Adds a given value to the current quota (vector)

View File

@ -22,7 +22,7 @@
/**
* DataStore Quotas, defined as:
* DATASTORE = [
* NAME = <Name of the datastore>
* ID = <ID of the datastore>
* IMAGES = <Max. number of images allowed in the datastore>
* SIZE = <Max. number of MB used in the datastore>
* IMAGES_USED = Current number of images in the datastore
@ -47,7 +47,7 @@ public:
* @param error string
* @return true if the operation can be performed
*/
bool check_add(Template* tmpl, string& error);
bool check(Template* tmpl, string& error);
/**
* Decrement usage counters when deallocating image
@ -63,7 +63,8 @@ protected:
* @param va attribute with the new limits
* @return 0 on success or -1 if wrong limits
*/
int update_limits(Attribute * quota, Attribute * va);
int update_limits(VectorAttribute* quota,
const VectorAttribute* va);
/**
* Creates an empty quota based on the given attribute. The attribute va
@ -71,34 +72,23 @@ protected:
* @param va limits for the new quota if 0 limits will be 0
* @return a new attribute representing the quota
*/
Attribute * new_quota(Attribute * va);
VectorAttribute * new_quota(VectorAttribute * va);
private:
/**
* Return the limits for image and size stored in the a given quota.
* @param va_ptr the attribute that stores the quota
* @param ds the name of the DATASTORE quota
* @param images the limit for the number of images
* @param ds the id of the DATASTORE quota
* @param imgs the limit for the number of images
* @param size the limit for the total storage size
*
* @return -1 if the limits are wrong 0 otherwise
*/
int get_limits(Attribute* va_ptr, string& ds, string& images, string& size);
/**
* Return the attribute with the datastore quotas
* @param ds_name name of the datastore
* @return pointer to the datastore quota or 0 if not found
*/
VectorAttribute * get_datastore_quota(const string& ds_name);
/**
* Return the attribute with the datastore quotas
* @param resource attribute describing a datastore quota
* @return pointer to the datastore quota or 0 if not found
*/
Attribute * get_quota(Attribute * resource);
int get_limits(const VectorAttribute* va,
string& ds,
string& imgs,
string& size);
};
#endif /*QUOTA_DATASTORE_H_*/

View File

@ -177,7 +177,7 @@ public:
*/
bool datastore_quota_check(Template * tmpl, string& reason)
{
return datastore_quota.check_add(tmpl, reason);
return datastore_quota.check(tmpl, reason);
}
/**

View File

@ -402,7 +402,7 @@ void ImageAllocate::request_execute(xmlrpc_c::paramList const& params,
string tmpl_str;
// ------------------ Check permissions and ACLs ----------------------
tmpl->add("DATASTORE", ds_name);
tmpl->add("DATASTORE", ds_id);
tmpl->to_xml(tmpl_str);
@ -446,7 +446,7 @@ void ImageAllocate::request_execute(xmlrpc_c::paramList const& params,
{
Template img_usage;
img_usage.add("DATASTORE", ds_name);
img_usage.add("DATASTORE", ds_id);
img_usage.add("SIZE", size_str);
quota_rollback(&img_usage, att);

View File

@ -19,73 +19,44 @@
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Quota::set(const string& quota_str, string& error)
VectorAttribute * Quota::get_quota(const string& id)
{
Quota tmp("GENERIC_QUOTA");
map<string, Attribute *>::iterator it;
VectorAttribute * q;
if ( tmp.parse_str_or_xml(quota_str, error) != 0 )
if ( id.empty() )
{
return -1;
return 0;
}
multimap<string, Attribute *>::iterator it;
pair<multimap<string, Attribute *>::iterator,
multimap<string, Attribute *>::iterator> actual;
Attribute * quota;
for ( it = tmp.attributes.begin(); it != tmp.attributes.end(); it++)
for ( it = attributes.begin(); it != attributes.end(); it++)
{
quota = get_quota(it->second);
q = static_cast<VectorAttribute *>(it->second);
if ( quota == 0 ) //Quota not set yet.
if (q->vector_value("ID") == id)
{
Attribute * nq;
if ((nq = new_quota(it->second)) == 0)
{
goto error_limits;
}
attributes.insert(make_pair(nq->name(),nq));
}
else
{
if (update_limits(quota, it->second))
{
goto error_limits;
}
return q;
}
}
error_limits:
ostringstream oss;
oss << "Negative limits or bad format in quota " << it->first
<< " = " << it->second->marshall();
error = oss.str();
return -1;
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void Quota::add_to_quota(SingleAttribute * attr, float num)
void Quota::add(VectorAttribute * nq)
{
istringstream iss;
ostringstream oss;
float total;
string id;
iss.str(attr->value());
id = nq->vector_value("ID");
iss >> total;
if ( id.empty() )
{
return;
}
total += num;
oss << total;
attr->replace(oss.str());
attributes.insert(make_pair(nq->name(), nq));
}
/* -------------------------------------------------------------------------- */
@ -107,3 +78,52 @@ void Quota::add_to_quota(VectorAttribute * attr, const string& va_name, int num)
attr->replace(va_name, oss.str());
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Quota::set(vector<VectorAttribute*> * new_quotas, string& error)
{
vector<VectorAttribute *>::iterator it;
VectorAttribute * tq;
string id;
for ( it = new_quotas->begin(); it != new_quotas->end(); it++)
{
id = (*it)->vector_value("ID");
tq = get_quota(id);
if ( tq == 0 )
{
VectorAttribute * nq;
if ((nq = new_quota(*it)) == 0)
{
goto error_limits;
}
add(nq);
}
else
{
if (update_limits(tq, *it))
{
goto error_limits;
}
}
}
return 0;
error_limits:
ostringstream oss;
oss << "Negative limits or bad format in quota " << (*it)->marshall();
error = oss.str();
return -1;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -16,58 +16,10 @@
#include "QuotaDatastore.h"
VectorAttribute * QuotaDatastore::get_datastore_quota(const string& ds_name)
{
vector<Attribute *> vquota;
VectorAttribute * ds_quota = 0;
int num = get("DATASTORE", vquota);
for (int i = 0; i< num ; i++)
{
ds_quota = dynamic_cast<VectorAttribute *>(vquota[i]);
if (ds_quota == 0)
{
continue;
}
if ( ds_quota->vector_value("NAME") == ds_name )
{
return ds_quota;
}
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
Attribute * QuotaDatastore::get_quota(Attribute * resource)
{
VectorAttribute * vresource = dynamic_cast<VectorAttribute *>(resource);
string ds_name;
if (vresource == 0)
{
return 0;
}
ds_name = vresource->vector_value("NAME");
if (ds_name.empty())
{
return 0;
}
return get_datastore_quota(ds_name);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
bool QuotaDatastore::check_add(Template * tmpl, string& error)
bool QuotaDatastore::check(Template * tmpl, string& error)
{
VectorAttribute * ds_quota;
@ -79,14 +31,14 @@ bool QuotaDatastore::check_add(Template * tmpl, string& error)
bool img_ok;
bool size_ok;
string ds_name;
string ds_id;
int size;
// --------------------- Get data from the Template --------------------
tmpl->get("DATASTORE", ds_name);
tmpl->get("DATASTORE", ds_id);
if ( ds_name.empty() )
if ( ds_id.empty() )
{
error = "Datastore not defined for image";
return false;
@ -100,25 +52,22 @@ bool QuotaDatastore::check_add(Template * tmpl, string& error)
// ------ There are no quotas for this datastore, create a new one ------
ds_quota = get_datastore_quota(ds_name);
ds_quota = get_quota(ds_id);
if ( ds_quota == 0 )
{
map<string,string> ds_quota;
VectorAttribute * attr;
ostringstream size_str;
size_str << size;
ds_quota.insert(make_pair("NAME", ds_name));
ds_quota.insert(make_pair("ID", ds_id));
ds_quota.insert(make_pair("IMAGES", "0"));
ds_quota.insert(make_pair("SIZE", "0"));
ds_quota.insert(make_pair("IMAGES_USED", "1"));
ds_quota.insert(make_pair("SIZE_USED", size_str.str()));
attr = new VectorAttribute("DATASTORE", ds_quota);
attributes.insert(make_pair("DATASTORE", attr));
add(new VectorAttribute("DATASTORE", ds_quota));
return true;
}
@ -144,7 +93,7 @@ bool QuotaDatastore::check_add(Template * tmpl, string& error)
ostringstream oss;
oss << "Maximum number of images limit (" << img_limit << ")"
<< " reached for datastore " << ds_name;
<< " reached for datastore " << ds_id;
error = oss.str();
}
@ -153,7 +102,7 @@ bool QuotaDatastore::check_add(Template * tmpl, string& error)
ostringstream oss;
oss << "Maximum storage capacity limit (" << size_limit << ")"
<< " reached for datastore " << ds_name;
<< " reached for datastore " << ds_id;
error = oss.str();
}
@ -168,12 +117,12 @@ void QuotaDatastore::del(Template * tmpl)
{
VectorAttribute * ds_quota;
string ds_name;
string ds_id;
int size;
tmpl->get("DATASTORE", ds_name);
tmpl->get("DATASTORE", ds_id);
if ( ds_name.empty() )
if ( ds_id.empty() )
{
return;
}
@ -183,7 +132,7 @@ void QuotaDatastore::del(Template * tmpl)
return;
}
ds_quota = get_datastore_quota(ds_name);
ds_quota = get_quota(ds_id);
if ( ds_quota == 0 )
{
@ -197,22 +146,20 @@ void QuotaDatastore::del(Template * tmpl)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int QuotaDatastore::update_limits(Attribute * quota, Attribute * va)
int QuotaDatastore::update_limits(VectorAttribute * quota,
const VectorAttribute * va)
{
string images_limit;
string size_limit;
string ds;
string ds_id;
VectorAttribute * vquota = dynamic_cast<VectorAttribute *>(quota);
int rc = get_limits(va, ds, images_limit, size_limit);
if ( vquota == 0 || rc != 0 )
if ( get_limits(va, ds_id, images_limit, size_limit) != 0 )
{
return -1;
}
vquota->replace("IMAGES", images_limit);
vquota->replace("SIZE", size_limit);
quota->replace("IMAGES", images_limit);
quota->replace("SIZE", size_limit);
return 0;
}
@ -220,22 +167,20 @@ int QuotaDatastore::update_limits(Attribute * quota, Attribute * va)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
Attribute * QuotaDatastore::new_quota(Attribute * va)
VectorAttribute * QuotaDatastore::new_quota(VectorAttribute * va)
{
string images_limit = "0";
string size_limit = "0";
string ds_name;
string ds_id;
int rc = get_limits(va, ds_name, images_limit, size_limit);
if ( rc != 0 || ds_name.empty())
if ( get_limits(va, ds_id, images_limit, size_limit) != 0 )
{
return 0;
}
map<string,string> limits;
limits.insert(make_pair("NAME", ds_name));
limits.insert(make_pair("ID", ds_id));
limits.insert(make_pair("IMAGES", images_limit));
limits.insert(make_pair("SIZE", size_limit));
@ -249,26 +194,19 @@ Attribute * QuotaDatastore::new_quota(Attribute * va)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int QuotaDatastore::get_limits(Attribute * va_ptr,
string& ds_name,
string& images,
string& size)
int QuotaDatastore::get_limits(const VectorAttribute * va,
string& ds_id,
string& images,
string& size)
{
int images_limit = 0;
int size_limit = 0;
VectorAttribute * va = dynamic_cast<VectorAttribute *>(va_ptr);
images = va->vector_value("IMAGES", images_limit);
size = va->vector_value("SIZE", size_limit);
ds_id = va->vector_value("ID");
if ( va == 0 )
{
return -1;
}
images = va->vector_value("IMAGES", images_limit);
size = va->vector_value("SIZE", size_limit);
ds_name = va->vector_value("NAME");
if ( images_limit < 0 || size_limit < 0 )
if ( images_limit < 0 || size_limit < 0 || ds_id.empty())
{
return -1;
}