From b7234a4c370e31869939d11aacc025780157d62d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Tue, 15 Oct 2013 13:45:16 +0200 Subject: [PATCH] Feature #1612: Add volatile disk quotas for attach/detach operations --- include/RequestManagerVirtualMachine.h | 10 ++ include/VirtualMachine.h | 5 + src/lcm/LifeCycleStates.cc | 13 +- src/rm/RequestManagerVirtualMachine.cc | 225 +++++++++++++++++-------- src/um/QuotaVirtualMachine.cc | 4 +- src/vm/VirtualMachine.cc | 27 +++ 6 files changed, 208 insertions(+), 76 deletions(-) diff --git a/include/RequestManagerVirtualMachine.h b/include/RequestManagerVirtualMachine.h index 789a0aebb7..cf845f2468 100644 --- a/include/RequestManagerVirtualMachine.h +++ b/include/RequestManagerVirtualMachine.h @@ -56,6 +56,16 @@ protected: PoolObjectAuth * ds_perm, AuthRequest::Operation op); + bool quota_resize_authorization( + Template * deltas, + RequestAttributes& att, + PoolObjectAuth& vm_perms); + + bool quota_resize_authorization( + int oid, + Template * deltas, + RequestAttributes& att); + int get_host_information( int hid, string& name, diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index 9ea3e36d1c..0b9f50e714 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -1073,6 +1073,11 @@ public: */ static bool isVolatile(const VectorAttribute * disk); + /** + * Check if the template contains a volatile disk + */ + static bool isVolatile(const Template * tmpl); + /** * Return the total SIZE of volatile disks */ diff --git a/src/lcm/LifeCycleStates.cc b/src/lcm/LifeCycleStates.cc index 612caca169..5991d36541 100644 --- a/src/lcm/LifeCycleStates.cc +++ b/src/lcm/LifeCycleStates.cc @@ -1346,12 +1346,21 @@ void LifeCycleManager::attach_failure_action(int vid) tmpl.set(disk); - Quotas::quota_del(Quotas::IMAGE, uid, gid, &tmpl); - if ( disk->vector_value("IMAGE_ID", image_id) == 0 ) { + // Disk using an Image + Quotas::quota_del(Quotas::IMAGE, uid, gid, &tmpl); + imagem->release_image(oid, image_id, false); } + else // Volatile disk + { + // It is an update of the volatile counter without + // shutting destroying a VM + tmpl.add("VMS", 0); + + Quotas::quota_del(Quotas::VM, uid, gid, &tmpl); + } } } else diff --git a/src/rm/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc index 9688b42370..f53bf7171b 100644 --- a/src/rm/RequestManagerVirtualMachine.cc +++ b/src/rm/RequestManagerVirtualMachine.cc @@ -96,6 +96,120 @@ bool RequestManagerVirtualMachine::vm_authorization( /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +bool RequestManagerVirtualMachine::quota_resize_authorization( + int oid, + Template * deltas, + RequestAttributes& att) +{ + PoolObjectAuth vm_perms; + VirtualMachine * vm = Nebula::instance().get_vmpool()->get(oid, true); + + if (vm == 0) + { + failure_response(NO_EXISTS, + get_error(object_name(PoolObjectSQL::VM),oid), + att); + + return false; + } + + vm->get_permissions(vm_perms); + + vm->unlock(); + + return quota_resize_authorization(deltas, att, vm_perms); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +bool RequestManagerVirtualMachine::quota_resize_authorization( + Template * deltas, + RequestAttributes& att, + PoolObjectAuth& vm_perms) +{ + int rc; + + string error_str; + + Nebula& nd = Nebula::instance(); + UserPool* upool = nd.get_upool(); + GroupPool* gpool = nd.get_gpool(); + + Quotas user_dquotas = nd.get_default_user_quota(); + Quotas group_dquotas = nd.get_default_group_quota(); + + if (vm_perms.uid != UserPool::ONEADMIN_ID) + { + User * user = upool->get(vm_perms.uid, true); + + if ( user != 0 ) + { + rc = user->quota.quota_update(Quotas::VM, deltas, user_dquotas, error_str); + + if (rc == false) + { + ostringstream oss; + + oss << object_name(PoolObjectSQL::USER) + << " [" << vm_perms.uid << "] " + << error_str; + + failure_response(AUTHORIZATION, + request_error(oss.str(), ""), + att); + + user->unlock(); + + return false; + } + + upool->update(user); + + user->unlock(); + } + } + + if (vm_perms.gid != GroupPool::ONEADMIN_ID) + { + Group * group = gpool->get(vm_perms.gid, true); + + if ( group != 0 ) + { + rc = group->quota.quota_update(Quotas::VM, deltas, group_dquotas, error_str); + + if (rc == false) + { + ostringstream oss; + RequestAttributes att_tmp(vm_perms.uid, -1, att); + + oss << object_name(PoolObjectSQL::GROUP) + << " [" << vm_perms.gid << "] " + << error_str; + + failure_response(AUTHORIZATION, + request_error(oss.str(), ""), + att); + + group->unlock(); + + quota_rollback(deltas, Quotas::VM, att_tmp); + + return false; + } + + gpool->update(group); + + group->unlock(); + } + } + + return true; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + int RequestManagerVirtualMachine::get_default_ds_information( int cluster_id, int& ds_id, @@ -1226,10 +1340,13 @@ void VirtualMachineAttach::request_execute(xmlrpc_c::paramList const& paramList, DispatchManager * dm = nd.get_dm(); VirtualMachineTemplate * tmpl = new VirtualMachineTemplate(); + VirtualMachineTemplate * deltas = 0; PoolObjectAuth host_perms; + PoolObjectAuth vm_perms; int rc; string error_str; + bool volatile_disk; int id = xmlrpc_c::value_int(paramList.getInt(1)); string str_tmpl = xmlrpc_c::value_string(paramList.getString(2)); @@ -1258,17 +1375,43 @@ void VirtualMachineAttach::request_execute(xmlrpc_c::paramList const& paramList, return; } - if ( quota_authorization(tmpl, Quotas::IMAGE, att) == false ) + volatile_disk = VirtualMachine::isVolatile(tmpl); + + if ( volatile_disk ) { - delete tmpl; - return; + deltas = new VirtualMachineTemplate(*tmpl); + + deltas->add("VMS", 0); + + if (quota_resize_authorization(id, deltas, att) == false) + { + delete tmpl; + delete deltas; + + return; + } + } + else + { + if ( quota_authorization(tmpl, Quotas::IMAGE, att) == false ) + { + delete tmpl; + return; + } } rc = dm->attach(id, tmpl, error_str); if ( rc != 0 ) { - quota_rollback(tmpl, Quotas::IMAGE, att); + if ( volatile_disk ) + { + quota_rollback(deltas, Quotas::VM, att); + } + else + { + quota_rollback(tmpl, Quotas::IMAGE, att); + } failure_response(ACTION, request_error(error_str, ""), @@ -1280,6 +1423,8 @@ void VirtualMachineAttach::request_execute(xmlrpc_c::paramList const& paramList, } delete tmpl; + delete deltas; + return; } @@ -1338,14 +1483,8 @@ void VirtualMachineResize::request_execute(xmlrpc_c::paramList const& paramList, int nvcpu, ovcpu; Nebula& nd = Nebula::instance(); - UserPool* upool = nd.get_upool(); - GroupPool* gpool = nd.get_gpool(); HostPool * hpool = nd.get_hpool(); - - Quotas user_dquotas = nd.get_default_user_quota(); - Quotas group_dquotas = nd.get_default_group_quota(); - - Host * host; + Host * host; Template deltas; string error_str; @@ -1494,69 +1633,9 @@ void VirtualMachineResize::request_execute(xmlrpc_c::paramList const& paramList, /* Check quotas */ /* ---------------------------------------------------------------------- */ - if (vm_perms.uid != UserPool::ONEADMIN_ID) + if (quota_resize_authorization(&deltas, att, vm_perms) == false) { - User * user = upool->get(vm_perms.uid, true); - - if ( user != 0 ) - { - rc = user->quota.quota_update(Quotas::VM, &deltas, user_dquotas, error_str); - - if (rc == false) - { - ostringstream oss; - - oss << object_name(PoolObjectSQL::USER) - << " [" << vm_perms.uid << "] " - << error_str; - - failure_response(AUTHORIZATION, - request_error(oss.str(), ""), - att); - - user->unlock(); - - return; - } - - upool->update(user); - - user->unlock(); - } - } - - if (vm_perms.gid != GroupPool::ONEADMIN_ID) - { - Group * group = gpool->get(vm_perms.gid, true); - - if ( group != 0 ) - { - rc = group->quota.quota_update(Quotas::VM, &deltas, group_dquotas, error_str); - - if (rc == false) - { - ostringstream oss; - RequestAttributes att_tmp(vm_perms.uid, -1, att); - - oss << object_name(PoolObjectSQL::GROUP) - << " [" << vm_perms.gid << "] " - << error_str; - - failure_response(AUTHORIZATION, - request_error(oss.str(), ""), - att); - - group->unlock(); - - quota_rollback(&deltas, Quotas::VM, att_tmp); - - return; - } - - gpool->update(group); - - group->unlock(); - } + return; } /* ---------------------------------------------------------------------- */ diff --git a/src/um/QuotaVirtualMachine.cc b/src/um/QuotaVirtualMachine.cc index 55eea64d81..7da8cb5101 100644 --- a/src/um/QuotaVirtualMachine.cc +++ b/src/um/QuotaVirtualMachine.cc @@ -150,7 +150,9 @@ bool QuotaVirtualMachine::update(Template * tmpl, vm_request.insert(make_pair("CPU", delta_cpu)); } - if ( tmpl->get("VOLATILE_SIZE", delta_size) == true ) + delta_size = VirtualMachine::get_volatile_disk_size(tmpl); + + if ( delta_size != 0 ) { vm_request.insert(make_pair("VOLATILE_SIZE", delta_size)); } diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index ed31b37327..85b8bf1bb0 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -2018,6 +2018,7 @@ VectorAttribute * VirtualMachine::delete_attach_disk() return 0; } + /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -2033,6 +2034,32 @@ bool VirtualMachine::isVolatile(const VectorAttribute * disk) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +bool VirtualMachine::isVolatile(const Template * tmpl) +{ + vector disks; + int num_disks = tmpl->get("DISK", disks); + + for (int i = 0 ; i < num_disks ; i++) + { + const VectorAttribute * disk = dynamic_cast(disks[i]); + + if (disk == 0) + { + continue; + } + + if (VirtualMachine::isVolatile(disk)) + { + return true; + } + } + + return false; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + float VirtualMachine::get_volatile_disk_size(Template * tmpl) { float size = 0;