1
0
mirror of https://github.com/OpenNebula/one.git synced 2024-12-22 13:33:52 +03:00

B #6355: Fix VM quotas (#2861)

* Remove useless default values from VM quotas, adapt chown and chgrp to it
* Fix VM transition from poweroff, stopped, suspended, undeployed to done when quotas are tmp exceeded
* Fix VM transition from poweroff to undeployed
* Fix VM transition from suspended to stopped

(cherry picked from commit 1e25904148)
This commit is contained in:
Pavel Czerný 2023-12-12 16:19:20 +01:00 committed by Ruben S. Montero
parent c5f9292797
commit 725337ea5e
No known key found for this signature in database
GPG Key ID: A0CEA6FA880A1D87
14 changed files with 228 additions and 75 deletions

View File

@ -39,10 +39,11 @@ public:
virtual bool check(Template* tmpl, Quotas& default_quotas, std::string& error) = 0;
/**
* Decrement usage counters when deallocating image
* Decrement usage counters
* @param tmpl template for the resource
*/
virtual void del(Template* tmpl) = 0;
/**
* Set the quotas. If the quota previously exists its limit is updated.
* @param quota_str the quota template in ASCII or XML formats
@ -251,6 +252,14 @@ protected:
Quotas& default_quotas,
std::string& error);
/**
* Add usage for a given quota without checking the limits
* @param qid id that identifies the quota, to be used by get_quota
* @param usage_req usage for each metric
*/
void add_quota(const std::string& qid,
std::map<std::string, float>& usage_req);
/**
* Reduce usage from a given quota based on the current consumption
* @param qid id that identifies the quota, to be used by get_quota

View File

@ -75,6 +75,12 @@ public:
*/
bool update(Template * tmpl, Quotas& default_quotas, std::string& error) override;
/**
* Add usage counters. Use carefully this method does not care about exceeding the quota
* @param tmpl Template with the quota usage
*/
void add(Template* tmpl);
/**
* Decrement usage counters when deallocating image
* @param tmpl template for the resource

View File

@ -50,7 +50,7 @@ public:
/**
* Delete usage from quota counters.
* @param tmpl template for the image, with usage
* @param tmpl Template with the quota usage
*/
void ds_del(Template * tmpl)
{
@ -70,6 +70,15 @@ public:
return datastore_quota.get_quota(id, va);
}
/**
* Add VM quota usage, without checking limits
* @param tmpl Template with the quota usage
*/
void vm_add(Template * tmpl)
{
vm_quota.add(tmpl);
}
/**
* Gets a VM quota identified by its ID.
*
@ -157,6 +166,15 @@ public:
*/
int from_xml(ObjectXML * object_xml);
/**
* Add VM quota usage, without checking the limits
* @param uid of the user
* @param gid of the group
* @param tmpl template with quota usage
* @note Use carefully as this method may exceed quota limits
*/
static void vm_add(int uid, int gid, Template * tmpl);
/**
* Delete VM related usage (network, image and compute) from quota counters.
* for the given user and group
@ -244,7 +262,7 @@ public:
* @param type the quota to work with
* @param uid of the user
* @param gid of the group
* @param tmpl template for the image, with usage
* @param tmpl template with quota usage
*/
static void quota_del(QuotaType type, int uid, int gid, Template * tmpl);

View File

@ -192,6 +192,20 @@ void LifeCycleManager::trigger_stop(int vid, const RequestAttributes& ra)
//----------------------------------------------------
// Bypass SAVE_STOP
//----------------------------------------------------
VirtualMachineTemplate quota_tmpl;
std::string memory, cpu;
int quota_uid = vm->get_uid();
int quota_gid = vm->get_gid();
vm->get_template_attribute("MEMORY", memory);
vm->get_template_attribute("CPU", cpu);
quota_tmpl.add("RUNNING_MEMORY", memory);
quota_tmpl.add("RUNNING_CPU", cpu);
quota_tmpl.add("RUNNING_VMS", 1);
vm->set_state(VirtualMachine::ACTIVE);
vm->set_state(VirtualMachine::EPILOG_STOP);
@ -206,6 +220,10 @@ void LifeCycleManager::trigger_stop(int vid, const RequestAttributes& ra)
//----------------------------------------------------
tm->trigger_epilog_stop(vm.get());
// Add running quota, it will be removed in DM::stop_success
vm.reset();
Quotas::vm_add(quota_uid, quota_gid, &quota_tmpl);
}
else
{
@ -428,7 +446,6 @@ void LifeCycleManager::trigger_shutdown(int vid, bool hard,
trigger([this, hard, vid, uid, gid, req_id] {
auto vm = vmpool->get(vid);
VirtualMachineTemplate quota_tmpl;
string error;
if ( vm == nullptr )
{
@ -451,10 +468,6 @@ void LifeCycleManager::trigger_shutdown(int vid, bool hard,
quota_tmpl.add("RUNNING_MEMORY", memory);
quota_tmpl.add("RUNNING_CPU", cpu);
quota_tmpl.add("RUNNING_VMS", 1);
quota_tmpl.add("MEMORY", 0);
quota_tmpl.add("CPU", 0);
quota_tmpl.add("VMS", 0);
}
auto lcm_state = vm->get_lcm_state();
@ -505,8 +518,6 @@ void LifeCycleManager::trigger_shutdown(int vid, bool hard,
vm->set_state(VirtualMachine::ACTIVE);
vm->set_state(VirtualMachine::EPILOG);
Quotas::vm_check(uid, gid, &quota_tmpl, error);
vm->set_action(VMActions::TERMINATE_ACTION, uid, gid, req_id);
vm->set_epilog_stime(time(0));
@ -518,6 +529,10 @@ void LifeCycleManager::trigger_shutdown(int vid, bool hard,
//----------------------------------------------------
tm->trigger_epilog(false, vm.get());
// Add running quota, it will be removed in DM::done
vm.reset();
Quotas::vm_add(uid, gid, &quota_tmpl);
}
else if (vm->get_state() == VirtualMachine::STOPPED ||
vm->get_state() == VirtualMachine::UNDEPLOYED)
@ -525,8 +540,6 @@ void LifeCycleManager::trigger_shutdown(int vid, bool hard,
vm->set_state(VirtualMachine::ACTIVE);
vm->set_state(VirtualMachine::EPILOG);
Quotas::vm_check(uid, gid, &quota_tmpl, error);
vm->set_action(VMActions::TERMINATE_ACTION, uid, gid, req_id);
vm->set_epilog_stime(time(0));
@ -538,6 +551,10 @@ void LifeCycleManager::trigger_shutdown(int vid, bool hard,
//----------------------------------------------------
tm->trigger_epilog(true, vm.get());
// Add running quota, it will be removed in DM::done
vm.reset();
Quotas::vm_add(uid, gid, &quota_tmpl);
}
else
{
@ -612,6 +629,20 @@ void LifeCycleManager::trigger_undeploy(int vid, bool hard,
// Bypass SHUTDOWN_UNDEPLOY
//----------------------------------------------------
VirtualMachineTemplate quota_tmpl;
std::string memory, cpu;
int quota_uid = vm->get_uid();
int quota_gid = vm->get_gid();
vm->get_template_attribute("MEMORY", memory);
vm->get_template_attribute("CPU", cpu);
quota_tmpl.add("RUNNING_MEMORY", memory);
quota_tmpl.add("RUNNING_CPU", cpu);
quota_tmpl.add("RUNNING_VMS", 1);
vm->set_state(VirtualMachine::ACTIVE);
vm->set_state(VirtualMachine::EPILOG_UNDEPLOY);
@ -626,6 +657,11 @@ void LifeCycleManager::trigger_undeploy(int vid, bool hard,
//----------------------------------------------------
tm->trigger_epilog_stop(vm.get());
vm.reset();
// Add running quota, it will be removed in DM:undeploy_success
Quotas::vm_add(quota_uid, quota_gid, &quota_tmpl);
}
else
{

View File

@ -1601,7 +1601,6 @@ void LifeCycleManager::trigger_snapshot_delete_success(int vid)
Template quota_tmpl;
quota_tmpl.set(snap);
quota_tmpl.replace("VMS", 0);
Quotas::quota_del(Quotas::VM, vm_uid, vm_gid, &quota_tmpl);
}

View File

@ -79,6 +79,8 @@ unique_ptr<PoolObjectSQL> RequestManagerChown::get_and_quota(
tmpl->add("RUNNING_VMS", 1);
}
tmpl->add("VMS", 1);
VirtualMachineDisks::image_ds_quotas(tmpl.get(), ds_quotas);
quota_map.insert(make_pair(Quotas::VIRTUALMACHINE, move(tmpl)));

View File

@ -525,10 +525,6 @@ Request::ErrorCode VirtualMachineAction::request_execute(RequestAttributes& att,
quota_tmpl.add("RUNNING_CPU", cpu);
quota_tmpl.add("RUNNING_VMS", 1);
quota_tmpl.add("VMS", 0);
quota_tmpl.add("MEMORY", 0);
quota_tmpl.add("CPU", 0);
att_aux.uid = vm->get_uid();
att_aux.gid = vm->get_gid();
@ -2170,7 +2166,6 @@ void VirtualMachineResize::request_execute(xmlrpc_c::paramList const& paramList,
deltas.add("MEMORY", dmemory);
deltas.add("CPU", dcpu);
deltas.add("VMS", 0);
if (update_running_quota)
{
@ -2347,8 +2342,6 @@ Request::ErrorCode VirtualMachineSnapshotCreate::request_execute(RequestAttribut
Template quota_tmpl;
quota_tmpl.set(snap);
quota_tmpl.add("MEMORY", 0);
quota_tmpl.add("CPU", 0);
quota_tmpl.add("VMS", 0);
RequestAttributes att_quota(vm_perms.uid, vm_perms.gid, att);

View File

@ -274,6 +274,40 @@ bool Quota::check_quota(const string& qid,
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void Quota::add_quota(const string& qid, map<string, float>& usage_req)
{
VectorAttribute * q;
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";
auto it = usage_req.find(metrics[i]);
if (it == usage_req.end())
{
continue;
}
add_to_quota(q, metrics_used, it->second);
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void Quota::del_quota(const string& qid, map<string, float>& usage_req)
{
VectorAttribute * q;

View File

@ -53,58 +53,53 @@ bool QuotaVirtualMachine::check(Template * tmpl,
float cpu, running_cpu;
long long size;
if ( tmpl->get("MEMORY", memory) == false || memory < 0 )
if ( tmpl->get("MEMORY", memory) )
{
error = "MEMORY attribute must be a positive integer value";
return false;
if ( memory < 0 )
{
error = "MEMORY attribute must be a positive integer value";
return false;
}
vm_request.insert(make_pair("MEMORY", memory));
}
if ( tmpl->get("CPU", cpu) == false || cpu < 0 )
if ( tmpl->get("CPU", cpu) )
{
error = "CPU attribute must be a positive float or integer value";
return false;
if ( cpu < 0 )
{
error = "CPU attribute must be a positive float or integer value";
return false;
}
vm_request.insert(make_pair("CPU", cpu));
}
size = VirtualMachineDisks::system_ds_size(tmpl, true);
size += VirtualMachine::get_snapshots_system_size(tmpl);
if ( tmpl->get("VMS", vms) == false )
vm_request.insert(make_pair("SYSTEM_DISK_SIZE", size));
if ( tmpl->get("VMS", vms) )
{
vms = 1;
vm_request.insert(make_pair("VMS", vms));
}
if ( tmpl->get("RUNNING_MEMORY", running_memory) )
{
vm_request.insert(make_pair("RUNNING_MEMORY", running_memory));
}
else
{
vm_request.insert(make_pair("RUNNING_MEMORY", 0));
}
if ( tmpl->get("RUNNING_CPU", running_cpu) )
{
vm_request.insert(make_pair("RUNNING_CPU", running_cpu));
}
else
{
vm_request.insert(make_pair("RUNNING_CPU", 0));
}
if ( tmpl->get("RUNNING_VMS", running_vms) )
{
vm_request.insert(make_pair("RUNNING_VMS", running_vms));
}
else
{
vm_request.insert(make_pair("RUNNING_VMS", 0));
}
vm_request.insert(make_pair("VMS", vms));
vm_request.insert(make_pair("MEMORY", memory));
vm_request.insert(make_pair("CPU", cpu));
vm_request.insert(make_pair("SYSTEM_DISK_SIZE", size));
return check_quota("", vm_request, default_quotas, error);
}
@ -112,6 +107,54 @@ bool QuotaVirtualMachine::check(Template * tmpl,
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void QuotaVirtualMachine::add(Template * tmpl)
{
map<string, float> vm_request;
float value;
if ( tmpl->get("MEMORY", value) )
{
vm_request.insert(make_pair("MEMORY", value));
}
if ( tmpl->get("CPU", value) )
{
vm_request.insert(make_pair("CPU", value));
}
if ( tmpl->get("VMS", value) )
{
vm_request.insert(make_pair("VMS", value));
}
if ( tmpl->get("RUNNING_MEMORY", value) )
{
vm_request.insert(make_pair("RUNNING_MEMORY", value));
}
if ( tmpl->get("RUNNING_CPU", value) )
{
vm_request.insert(make_pair("RUNNING_CPU", value));
}
if ( tmpl->get("RUNNING_VMS", value) )
{
vm_request.insert(make_pair("RUNNING_VMS", value));
}
long long size = VirtualMachineDisks::system_ds_size(tmpl, true);
size += VirtualMachine::get_snapshots_system_size(tmpl);
vm_request.insert(make_pair("SYSTEM_DISK_SIZE", size));
add_quota("", vm_request);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void QuotaVirtualMachine::del(Template * tmpl)
{
map<string, float> vm_request;
@ -120,46 +163,40 @@ void QuotaVirtualMachine::del(Template * tmpl)
float cpu, running_cpu;
long long size;
if ( tmpl->get("MEMORY", memory) == false )
if ( tmpl->get("MEMORY", memory) )
{
memory = 0;
vm_request.insert(make_pair("MEMORY", memory));
}
if ( tmpl->get("CPU", cpu) == false )
if ( tmpl->get("CPU", cpu) )
{
cpu = 0;
vm_request.insert(make_pair("CPU", cpu));
}
if ( tmpl->get("VMS", vms) == false )
if ( tmpl->get("VMS", vms) )
{
vms = 1;
vm_request.insert(make_pair("VMS", vms));
}
if ( tmpl->get("RUNNING_MEMORY", running_memory) == false )
if ( tmpl->get("RUNNING_MEMORY", running_memory) )
{
running_memory = 0;
vm_request.insert(make_pair("RUNNING_MEMORY", running_memory));
}
if ( tmpl->get("RUNNING_CPU", running_cpu) == false )
if ( tmpl->get("RUNNING_CPU", running_cpu) )
{
running_cpu = 0;
vm_request.insert(make_pair("RUNNING_CPU", running_cpu));
}
if ( tmpl->get("RUNNING_VMS", running_vms) == false )
if ( tmpl->get("RUNNING_VMS", running_vms) )
{
running_vms = 0;
vm_request.insert(make_pair("RUNNING_VMS", running_vms));
}
size = VirtualMachineDisks::system_ds_size(tmpl, true);
size += VirtualMachine::get_snapshots_system_size(tmpl);
vm_request.insert(make_pair("VMS", vms));
vm_request.insert(make_pair("MEMORY", memory));
vm_request.insert(make_pair("CPU", cpu));
vm_request.insert(make_pair("RUNNING_VMS", running_vms));
vm_request.insert(make_pair("RUNNING_MEMORY", running_memory));
vm_request.insert(make_pair("RUNNING_CPU", running_cpu));
vm_request.insert(make_pair("SYSTEM_DISK_SIZE", size));
del_quota("", vm_request);

View File

@ -141,6 +141,36 @@ int Quotas::from_xml(ObjectXML * object_xml)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void Quotas::vm_add(int uid, int gid, Template * tmpl)
{
Nebula& nd = Nebula::instance();
UserPool * upool = nd.get_upool();
GroupPool * gpool = nd.get_gpool();
if ( uid != UserPool::ONEADMIN_ID )
{
if ( auto user = upool->get(uid) )
{
user->quota.vm_add(tmpl);
upool->update_quotas(user.get());
}
}
if ( gid != GroupPool::ONEADMIN_ID )
{
if ( auto group = gpool->get(gid) )
{
group->quota.vm_add(tmpl);
gpool->update_quotas(group.get());
}
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void Quotas::quota_del(QuotaType type, Template *tmpl)
{
switch (type)
@ -195,7 +225,6 @@ bool Quotas::quota_check(QuotaType type,
case VM:
return vm_quota.check(tmpl, default_quotas, error_str);
case VIRTUALMACHINE:
if ( network_quota.check(tmpl, default_quotas, error_str) == false )
{

View File

@ -3980,13 +3980,7 @@ void VirtualMachine::get_quota_template(VirtualMachineTemplate& quota_tmpl,
quota_tmpl.add("RUNNING_CPU", cpu);
quota_tmpl.add("RUNNING_VMS", 1);
if (only_running)
{
quota_tmpl.add("MEMORY", 0);
quota_tmpl.add("CPU", 0);
quota_tmpl.add("VMS", 0);
}
else
if (!only_running)
{
quota_tmpl.add("MEMORY", memory);
quota_tmpl.add("CPU", cpu);

View File

@ -364,7 +364,6 @@ void VirtualMachineDisk::delete_snapshot(int snap_id, Template **ds_quotas,
delta_disk->replace("TYPE", "FS");
delta_disk->replace("SIZE", ssize);
(*vm_quotas)->add("VMS", 0);
(*vm_quotas)->set(delta_disk);
}
}
@ -1507,7 +1506,6 @@ void VirtualMachineDisks::delete_non_persistent_snapshots(Template &vm_quotas,
delta_disk->replace("TYPE", "FS");
delta_disk->replace("SIZE", system_disk);
vm_quotas.add("VMS", 0);
vm_quotas.set(delta_disk);
}
}

View File

@ -1037,7 +1037,6 @@ void VirtualMachinePool::delete_attach_disk(std::unique_ptr<VirtualMachine> vm)
Template tmpl;
tmpl.set(disk->vector_attribute());
tmpl.add("VMS", 0);
if (disk->is_volatile())
{

View File

@ -264,7 +264,6 @@ void VirtualMachine::delete_snapshots(Template& snapshots)
obj_template->remove("SNAPSHOT", attrs);
snapshots.set(attrs);
snapshots.add("VMS", 0);
}
/* -------------------------------------------------------------------------- */