1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-08 20:58:17 +03:00

feature #1233: Added quotas.Refactor Attach methods

This commit is contained in:
Ruben S. Montero 2012-06-15 12:28:20 +02:00
parent 554321c73b
commit 1dbeaa1719
14 changed files with 571 additions and 493 deletions

View File

@ -232,6 +232,7 @@ public:
* Set the re-scheduling flag for the VM (must be in RUNNING state) * Set the re-scheduling flag for the VM (must be in RUNNING state)
* @param vid VirtualMachine identification * @param vid VirtualMachine identification
* @param do_resched set or unset the flag * @param do_resched set or unset the flag
*
* @return 0 on success, -1 if the VM does not exits or -2 if the VM is * @return 0 on success, -1 if the VM does not exits or -2 if the VM is
* in a wrong a state * in a wrong a state
*/ */
@ -240,19 +241,14 @@ public:
bool do_resched); bool do_resched);
/** /**
* Starts the attach disk action. * Starts the attach disk action.
* @param vid VirtualMachine identification
* @param tmpl Template containing the new DISK attribute.
* @param error_str Error reason, if any
* *
* @param vm pointer to a VirtualMachine with its mutex locked. It will be * @return 0 on success, -1 otherwise
* unlocked
* @param tmpl Template containing the new DISK attribute.
* It will be deleted
* @param error_str Error reason, if any
* @return 0 on success, -1 action error, -2 if the VM is in a wrong a state
*/ */
int attach( int attach(int vid, VirtualMachineTemplate * tmpl, string & error_str);
VirtualMachine * vm,
VirtualMachineTemplate * tmpl,
string & error_str);
private: private:
/** /**

View File

@ -22,6 +22,8 @@
#include "QuotaVirtualMachine.h" #include "QuotaVirtualMachine.h"
#include "QuotaImage.h" #include "QuotaImage.h"
class ObjectXML;
class Quotas class Quotas
{ {
public: public:
@ -44,52 +46,7 @@ public:
* *
* @return 0 on success, -1 otherwise * @return 0 on success, -1 otherwise
*/ */
int set(Template *tmpl, string& error) int set(Template *tmpl, string& error);
{
vector<Attribute *> vquotas;
if ( tmpl->get(datastore_quota.get_quota_name(), vquotas) > 0 )
{
if ( datastore_quota.set(&vquotas, error) != 0 )
{
return -1;
}
vquotas.clear();
}
if ( tmpl->get(network_quota.get_quota_name(), vquotas) > 0 )
{
if ( network_quota.set(&vquotas, error) != 0 )
{
return -1;
}
vquotas.clear();
}
if ( tmpl->get(image_quota.get_quota_name(), vquotas) > 0 )
{
if ( image_quota.set(&vquotas, error) != 0 )
{
return -1;
}
vquotas.clear();
}
if ( tmpl->get(vm_quota.get_quota_name(), vquotas) > 0 )
{
if ( vm_quota.set(&vquotas, error) != 0 )
{
return -1;
}
vquotas.clear();
}
return 0;
}
/** /**
* Check Datastore quotas, it updates usage counters if quotas are not * Check Datastore quotas, it updates usage counters if quotas are not
@ -159,76 +116,32 @@ public:
* @param xml the string to store the XML * @param xml the string to store the XML
* @return the same xml string to use it in << compounds * @return the same xml string to use it in << compounds
*/ */
string& to_xml(string& xml) const string& to_xml(string& xml) const;
{
ostringstream oss;
string ds_quota_xml;
string net_quota_xml;
string vm_quota_xml;
string image_quota_xml;
oss << datastore_quota.to_xml(ds_quota_xml)
<< network_quota.to_xml(net_quota_xml)
<< vm_quota.to_xml(vm_quota_xml)
<< image_quota.to_xml(image_quota_xml);
xml = oss.str();
return xml;
}
/** /**
* Builds quota object from an ObjectXML * Builds quota object from an ObjectXML
* @param object_xml pointer to the ObjectXML * @param object_xml pointer to the ObjectXML
* @return 0 if success * @return 0 if success
*/ */
int from_xml(ObjectXML * object_xml) int from_xml(ObjectXML * object_xml);
{
vector<xmlNodePtr> content;
int rc = 0;
object_xml->get_nodes(ds_xpath, content); /**
* Delete VM related usage (network, image and compute) from quota counters.
* for the given user and group
* @param uid of the user
* @param gid of the group
* @param tmpl template for the image, with usage
*/
static void vm_del(int uid, int gid, Template * tmpl);
if (!content.empty()) /**
{ * Delete Datastore related usage from quota counters.
rc += datastore_quota.from_xml_node(content[0]); * for the given user and group
} * @param uid of the user
* @param gid of the group
object_xml->free_nodes(content); * @param tmpl template for the image, with usage
content.clear(); */
static void ds_del(int uid, int gid, Template * tmpl);
object_xml->get_nodes(net_xpath, content);
if (!content.empty())
{
rc += network_quota.from_xml_node(content[0]);
}
object_xml->free_nodes(content);
content.clear();
object_xml->get_nodes(vm_xpath, content);
if (!content.empty())
{
rc += vm_quota.from_xml_node(content[0]);
}
object_xml->free_nodes(content);
content.clear();
object_xml->get_nodes(img_xpath, content);
if (!content.empty())
{
rc += image_quota.from_xml_node(content[0]);
}
object_xml->free_nodes(content);
return rc;
}
private: private:
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@ -238,17 +151,17 @@ private:
/** /**
* Datastore Quotas * Datastore Quotas
*/ */
QuotaDatastore datastore_quota; QuotaDatastore datastore_quota;
/** /**
* Network Quotas * Network Quotas
*/ */
QuotaNetwork network_quota; QuotaNetwork network_quota;
/** /**
* Image Quotas * Image Quotas
*/ */
QuotaImage image_quota; QuotaImage image_quota;
/** /**
* Virtual Machine Quotas * Virtual Machine Quotas

View File

@ -49,11 +49,12 @@ protected:
RequestAttributes& att) = 0; RequestAttributes& att) = 0;
bool vm_authorization(int id, bool vm_authorization(int id,
ImageTemplate * tmpl, ImageTemplate * tmpl,
RequestAttributes& att, VirtualMachineTemplate* vtmpl,
PoolObjectAuth * host_perms, RequestAttributes& att,
PoolObjectAuth * ds_perm, PoolObjectAuth * host_perms,
AuthRequest::Operation op); PoolObjectAuth * ds_perm,
AuthRequest::Operation op);
int get_host_information(int hid, string& name, string& vmm, string& vnm, int get_host_information(int hid, string& name, string& vmm, string& vnm,
RequestAttributes& att, PoolObjectAuth& host_perms); RequestAttributes& att, PoolObjectAuth& host_perms);

View File

@ -169,6 +169,15 @@ public:
const string& name, const string& name,
vector<Attribute *>& values); vector<Attribute *>& values);
/**
* Removes an attribute from the template, but it DOES NOT free the
* attribute.
* @param att Attribute to remove. It will be deleted
* @return pointer to the removed attribute or 0 if non attribute was
* removed
*/
virtual Attribute * remove(Attribute * att);
/** /**
* Removes an attribute from the template, and frees the attributes. * Removes an attribute from the template, and frees the attributes.
* @param name of the attribute * @param name of the attribute

View File

@ -24,6 +24,7 @@
#include "NebulaLog.h" #include "NebulaLog.h"
#include <time.h> #include <time.h>
#include <set>
#include <sstream> #include <sstream>
using namespace std; using namespace std;
@ -744,17 +745,31 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** /**
* Attaches a new disk. It will acquire the Image used, if any, and add the * Collects information about VM DISKS
* disk to the VM template. The VM must be updated in the DB afterwards. * @param num_disks of the VM
* * @param used_targets by the DISKS of the VM
* @param tmpl Template containing a single DISK vector attribute. The
* caller must delete this template
* @param error_str Returns the error reason, if any
*
* @return 0 on success
*/ */
int attach_disk(VirtualMachineTemplate * tmpl, string& error_str); void get_disk_info(int& num_disks, set<string>& used_targets);
/**
* Generate a DISK attributed to be attached to the VM.
* @param tmpl Template containing a single DISK vector attribute.
* @param used_targets targets in use by current DISKS
* @param num_disks of the VM
* @param uid of the VM owner
* @param image_id returns the id of the aquired image
* @param error_str describes the error
*
* @return a new vectorattribute with the DISK (should be freed if not
* added to the template), 0 in case of error;
*/
static VectorAttribute * set_up_attach_disk(
VirtualMachineTemplate * tmpl,
set<string>& used_targets,
int num_disks,
int uid,
int& image_id,
string& error_str);
/** /**
* Returns the disk that is waiting for an attachment action * Returns the disk that is waiting for an attachment action
* *
@ -764,18 +779,27 @@ public:
/** /**
* Cleans the ATTACH = YES attribute from the disks * Cleans the ATTACH = YES attribute from the disks
*
* @return 0 on success, -1 otherwise
*/ */
int attach_success(); void clear_attach_disk();
/** /**
* Deletes the DISK that was in the process of being attached, and releases * Deletes the DISK that was in the process of being attached
* the image, if any
* *
* @return 0 on success, -1 otherwise * @return the DISK or 0 if no disk was deleted
*/ */
int attach_failure(); VectorAttribute * delete_attach_disk();
/**
* Adds a new disk to the virtual machine template. The disk should be
* generated by the build_attach_disk
* @param new_disk must be allocated in the heap
*/
void attach_disk(VectorAttribute * new_disk)
{
new_disk->replace("ATTACH", "YES");
obj_template->set(new_disk);
}
private: private:

View File

@ -685,9 +685,6 @@ int DispatchManager::finalize(
VirtualMachine * vm; VirtualMachine * vm;
ostringstream oss; ostringstream oss;
Template * tmpl; Template * tmpl;
User * user;
Group * group;
int uid; int uid;
int gid; int gid;
@ -709,8 +706,6 @@ int DispatchManager::finalize(
Nebula& nd = Nebula::instance(); Nebula& nd = Nebula::instance();
TransferManager * tm = nd.get_tm(); TransferManager * tm = nd.get_tm();
LifeCycleManager * lcm = nd.get_lcm(); LifeCycleManager * lcm = nd.get_lcm();
UserPool * upool = nd.get_upool();
GroupPool * gpool = nd.get_gpool();
switch (state) switch (state)
{ {
@ -739,34 +734,7 @@ int DispatchManager::finalize(
vm->unlock(); vm->unlock();
if ( uid != UserPool::ONEADMIN_ID ) Quotas::vm_del(uid, gid, tmpl);
{
user = upool->get(uid, true);
if ( user != 0 )
{
user->quota.vm_del(tmpl);
upool->update(user);
user->unlock();
}
}
if ( gid != GroupPool::ONEADMIN_ID )
{
group = gpool->get(gid, true);
if ( group != 0 )
{
group->quota.vm_del(tmpl);
gpool->update(group);
group->unlock();
}
}
delete tmpl; delete tmpl;
break; break;
@ -845,59 +813,96 @@ int DispatchManager::resubmit(int vid)
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
int DispatchManager::attach(
VirtualMachine * vm, int DispatchManager::attach(int vid,
VirtualMachineTemplate * tmpl, VirtualMachineTemplate * tmpl,
string & error_str) string & error_str)
{ {
ostringstream oss; ostringstream oss;
int rc;
int vid = vm->get_oid();
Nebula& nd = Nebula::instance(); int num_disks;
VirtualMachineManager * vmm = nd.get_vmm(); int uid;
int image_id;
oss << "Attaching a new disk to VM " << vid; set<string> used_targets;
NebulaLog::log("DiM",Log::DEBUG,oss); VectorAttribute * disk;
Nebula& nd = Nebula::instance();
VirtualMachineManager* vmm = nd.get_vmm();
VirtualMachine * vm = vmpool->get(vid, true);
if ( vm == 0 )
{
oss << "VirtualMachine " << vid << " no longer exists";
return -1;
}
if ( vm->get_state() != VirtualMachine::ACTIVE || if ( vm->get_state() != VirtualMachine::ACTIVE ||
vm->get_lcm_state() != VirtualMachine::RUNNING ) vm->get_lcm_state() != VirtualMachine::RUNNING )
{ {
goto error_state; oss << "Could not attach a new disk to VM " << vid << ", wrong state.";
} error_str = oss.str();
rc = vm->attach_disk(tmpl, error_str); NebulaLog::log("DiM", Log::ERROR, error_str);
if ( rc != 0 ) vm->unlock();
{ return -1;
goto error;
} }
vm->get_disk_info(num_disks, used_targets);
vm->set_state(VirtualMachine::HOTPLUG); vm->set_state(VirtualMachine::HOTPLUG);
vm->set_resched(false);
uid = vm->get_uid();
vmpool->update(vm); vmpool->update(vm);
vm->unlock(); vm->unlock();
delete tmpl;
vmm->trigger(VirtualMachineManager::ATTACH,vid); disk = VirtualMachine::set_up_attach_disk(tmpl,
used_targets,
num_disks,
uid,
image_id,
error_str);
vm = vmpool->get(vid, true);
if ( vm == 0 )
{
Nebula& nd = Nebula::instance();
ImageManager* imagem = nd.get_imagem();
if ( image_id != -1 )
{
imagem->release_image(image_id, false);
}
return -1;
}
if ( disk == 0 )
{
vm->set_state(VirtualMachine::RUNNING);
vmpool->update(vm);
vm->unlock();
return -1;
}
else
{
vm->attach_disk(disk);
}
vmpool->update(vm);
vm->unlock();
vmm->trigger(VirtualMachineManager::ATTACH,vid);
return 0; return 0;
error:
vm->unlock();
delete tmpl;
return -1;
error_state:
oss.str("");
oss << "Could not attach a new disk to VM " << vid << ", wrong state.";
error_str = oss.str();
NebulaLog::log("DiM", Log::ERROR, error_str);
vm->unlock();
delete tmpl;
return -2;
} }

View File

@ -108,13 +108,6 @@ void DispatchManager::done_action(int vid)
VirtualMachine::LcmState lcm_state; VirtualMachine::LcmState lcm_state;
VirtualMachine::VmState dm_state; VirtualMachine::VmState dm_state;
Nebula& nd = Nebula::instance();
UserPool * upool = nd.get_upool();
GroupPool* gpool = nd.get_gpool();
User * user;
Group * group;
vm = vmpool->get(vid,true); vm = vmpool->get(vid,true);
if ( vm == 0 ) if ( vm == 0 )
@ -150,35 +143,7 @@ void DispatchManager::done_action(int vid)
vm->unlock(); vm->unlock();
/* ---------------- Update Group & User quota counters -------------- */ Quotas::vm_del(uid, gid, tmpl);
if ( uid != UserPool::ONEADMIN_ID )
{
user = upool->get(uid, true);
if ( user != 0 )
{
user->quota.vm_del(tmpl);
upool->update(user);
user->unlock();
}
}
if ( gid != GroupPool::ONEADMIN_ID )
{
group = gpool->get(gid, true);
if ( group != 0 )
{
group->quota.vm_del(tmpl);
gpool->update(group);
group->unlock();
}
}
delete tmpl; delete tmpl;
} }

View File

@ -274,13 +274,7 @@ int ImageManager::delete_image(int iid, const string& ds_data)
int uid; int uid;
int gid; int gid;
Group* group;
User * user;
Nebula& nd = Nebula::instance();
UserPool * upool = nd.get_upool();
GroupPool* gpool = nd.get_gpool();
img = ipool->get(iid,true); img = ipool->get(iid,true);
if ( img == 0 ) if ( img == 0 )
@ -354,33 +348,7 @@ int ImageManager::delete_image(int iid, const string& ds_data)
img_usage.add("DATASTORE", ds_id); img_usage.add("DATASTORE", ds_id);
img_usage.add("SIZE", size); img_usage.add("SIZE", size);
if ( uid != UserPool::ONEADMIN_ID ) Quotas::ds_del(uid, gid, &img_usage);
{
user = upool->get(uid, true);
if ( user != 0 )
{
user->quota.ds_del(&img_usage);
upool->update(user);
user->unlock();
}
}
if ( gid != GroupPool::ONEADMIN_ID )
{
group = gpool->get(gid, true);
if ( group != 0 )
{
group->quota.ds_del(&img_usage);
gpool->update(group);
group->unlock();
}
}
return 0; return 0;
} }

View File

@ -846,7 +846,7 @@ void LifeCycleManager::attach_success_action(int vid)
return; return;
} }
vm->attach_success(); vm->clear_attach_disk();
vm->set_state(VirtualMachine::RUNNING); vm->set_state(VirtualMachine::RUNNING);
@ -860,7 +860,11 @@ void LifeCycleManager::attach_success_action(int vid)
void LifeCycleManager::attach_failure_action(int vid) void LifeCycleManager::attach_failure_action(int vid)
{ {
VirtualMachine * vm; VirtualMachine * vm;
VectorAttribute * disk;
int uid;
int gid;
vm = vmpool->get(vid,true); vm = vmpool->get(vid,true);
@ -869,7 +873,9 @@ void LifeCycleManager::attach_failure_action(int vid)
return; return;
} }
vm->attach_failure(); disk = vm->delete_attach_disk();
uid = vm->get_uid();
gid = vm->get_gid();
vm->set_state(VirtualMachine::RUNNING); vm->set_state(VirtualMachine::RUNNING);
@ -877,7 +883,14 @@ void LifeCycleManager::attach_failure_action(int vid)
vm->unlock(); vm->unlock();
// TODO: update quotas, here or in VirtualMachine::attach_failure if ( disk != 0 )
{
Template tmpl;
tmpl.set(disk);
Quotas::vm_del(uid, gid, &tmpl);
}
} }
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */

View File

@ -22,12 +22,13 @@
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
bool RequestManagerVirtualMachine::vm_authorization( bool RequestManagerVirtualMachine::vm_authorization(
int oid, int oid,
ImageTemplate * tmpl, ImageTemplate * tmpl,
RequestAttributes& att, VirtualMachineTemplate* vtmpl,
PoolObjectAuth * host_perm, RequestAttributes& att,
PoolObjectAuth * ds_perm, PoolObjectAuth * host_perm,
AuthRequest::Operation op) PoolObjectAuth * ds_perm,
AuthRequest::Operation op)
{ {
PoolObjectSQL * object; PoolObjectSQL * object;
PoolObjectAuth vm_perms; PoolObjectAuth vm_perms;
@ -69,6 +70,11 @@ bool RequestManagerVirtualMachine::vm_authorization(
ar.add_create_auth(PoolObjectSQL::IMAGE, tmpl->to_xml(t_xml)); ar.add_create_auth(PoolObjectSQL::IMAGE, tmpl->to_xml(t_xml));
} }
if ( vtmpl != 0 )
{
VirtualMachine::set_auth_request(att.uid, ar, vtmpl);
}
if ( ds_perm != 0 ) if ( ds_perm != 0 )
{ {
ar.add_auth(AuthRequest::USE, *ds_perm); ar.add_auth(AuthRequest::USE, *ds_perm);
@ -196,7 +202,7 @@ void VirtualMachineAction::request_execute(xmlrpc_c::paramList const& paramList,
op = AuthRequest::ADMIN; op = AuthRequest::ADMIN;
} }
if ( vm_authorization(id, 0, att, 0, 0, op) == false ) if ( vm_authorization(id, 0, 0, att, 0, 0, op) == false )
{ {
return; return;
} }
@ -313,7 +319,7 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList,
return; return;
} }
auth = vm_authorization(id, 0, att, &host_perms, 0, auth_op); auth = vm_authorization(id, 0, 0, att, &host_perms, 0, auth_op);
if ( auth == false ) if ( auth == false )
{ {
@ -375,7 +381,7 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
return; return;
} }
auth = vm_authorization(id, 0, att, &host_perms, 0, auth_op); auth = vm_authorization(id, 0, 0, att, &host_perms, 0, auth_op);
if ( auth == false ) if ( auth == false )
{ {
@ -546,7 +552,7 @@ void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramLis
// Authorize the operation & check quotas // Authorize the operation & check quotas
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
if ( vm_authorization(id, itemplate, att, 0, &ds_perms, auth_op) == false ) if ( vm_authorization(id, itemplate, 0, att, 0, &ds_perms, auth_op) == false )
{ {
delete itemplate; delete itemplate;
return; return;
@ -598,7 +604,7 @@ void VirtualMachineMonitoring::request_execute(
ostringstream oss; ostringstream oss;
bool auth = vm_authorization(id, 0, att, 0, 0, auth_op); bool auth = vm_authorization(id, 0, 0, att, 0, 0, auth_op);
if ( auth == false ) if ( auth == false )
{ {
@ -624,59 +630,66 @@ void VirtualMachineMonitoring::request_execute(
void VirtualMachineAttach::request_execute(xmlrpc_c::paramList const& paramList, void VirtualMachineAttach::request_execute(xmlrpc_c::paramList const& paramList,
RequestAttributes& att) RequestAttributes& att)
{ {
Nebula& nd = Nebula::instance(); Nebula& nd = Nebula::instance();
DispatchManager * dm = nd.get_dm(); DispatchManager * dm = nd.get_dm();
VirtualMachine * vm; VirtualMachine * vm;
VirtualMachineTemplate * tmpl; VirtualMachineTemplate * tmpl = new VirtualMachineTemplate();
PoolObjectAuth host_perms; PoolObjectAuth host_perms;
int rc; int rc;
string error_str; string error_str;
int id = xmlrpc_c::value_int(paramList.getInt(1)); int id = xmlrpc_c::value_int(paramList.getInt(1));
string str_tmpl = xmlrpc_c::value_string(paramList.getString(2)); string str_tmpl = xmlrpc_c::value_string(paramList.getString(2));
tmpl = new VirtualMachineTemplate(); // -------------------------------------------------------------------------
// Parse Disk template
// -------------------------------------------------------------------------
rc = tmpl->parse_str_or_xml(str_tmpl, error_str); rc = tmpl->parse_str_or_xml(str_tmpl, error_str);
if ( rc != 0 ) if ( rc != 0 )
{ {
failure_response(INTERNAL, "", att); // TODO: error message failure_response(INTERNAL, error_str, att);
delete tmpl; delete tmpl;
return; return;
} }
// TODO: auth & quotas // -------------------------------------------------------------------------
// Authorize the operation & check quotas
// TODO: set vm state HOTPLUG & vm->set_resched(false); // Cancel re-scheduling actions // -------------------------------------------------------------------------
vm = get_vm(id, att); if ( vm_authorization(id, 0, tmpl, att, 0, 0, auth_op) == false )
if ( vm == 0 )
{ {
failure_response(NO_EXISTS,
get_error(object_name(auth_object),id),
att);
delete tmpl; delete tmpl;
return; return;
} }
rc = dm->attach(vm, tmpl, error_str); if ( quota_authorization(tmpl, att) == false )
{
delete tmpl;
return;
}
rc = dm->attach(id, tmpl, error_str);
if ( rc != 0 ) if ( rc != 0 )
{ {
quota_rollback(tmpl, att);
failure_response(ACTION, failure_response(ACTION,
request_error(error_str, ""), request_error(error_str, ""),
att); att);
}
return; else
{
success_response(id, att);
} }
success_response(id, att); delete tmpl;
return;
} }
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */

View File

@ -309,6 +309,33 @@ int Template::erase(Attribute * att)
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
Attribute * Template::remove(Attribute * att)
{
multimap<string, Attribute *>::iterator i;
pair<
multimap<string, Attribute *>::iterator,
multimap<string, Attribute *>::iterator
> index;
index = attributes.equal_range( att->name() );
for ( i = index.first; i != index.second; i++ )
{
if ( i->second == att )
{
attributes.erase(i);
return att;
}
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Template::get( int Template::get(
const string& name, const string& name,
vector<const Attribute*>& values) const vector<const Attribute*>& values) const

222
src/um/Quotas.cc Normal file
View File

@ -0,0 +1,222 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "Quotas.h"
#include "Nebula.h"
#include "ObjectXML.h"
int Quotas::set(Template *tmpl, string& error)
{
vector<Attribute *> vquotas;
if ( tmpl->get(datastore_quota.get_quota_name(), vquotas) > 0 )
{
if ( datastore_quota.set(&vquotas, error) != 0 )
{
return -1;
}
vquotas.clear();
}
if ( tmpl->get(network_quota.get_quota_name(), vquotas) > 0 )
{
if ( network_quota.set(&vquotas, error) != 0 )
{
return -1;
}
vquotas.clear();
}
if ( tmpl->get(image_quota.get_quota_name(), vquotas) > 0 )
{
if ( image_quota.set(&vquotas, error) != 0 )
{
return -1;
}
vquotas.clear();
}
if ( tmpl->get(vm_quota.get_quota_name(), vquotas) > 0 )
{
if ( vm_quota.set(&vquotas, error) != 0 )
{
return -1;
}
vquotas.clear();
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string& Quotas::to_xml(string& xml) const
{
ostringstream oss;
string ds_quota_xml;
string net_quota_xml;
string vm_quota_xml;
string image_quota_xml;
oss << datastore_quota.to_xml(ds_quota_xml)
<< network_quota.to_xml(net_quota_xml)
<< vm_quota.to_xml(vm_quota_xml)
<< image_quota.to_xml(image_quota_xml);
xml = oss.str();
return xml;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Quotas::from_xml(ObjectXML * object_xml)
{
vector<xmlNodePtr> content;
int rc = 0;
object_xml->get_nodes(ds_xpath, content);
if (!content.empty())
{
rc += datastore_quota.from_xml_node(content[0]);
}
object_xml->free_nodes(content);
content.clear();
object_xml->get_nodes(net_xpath, content);
if (!content.empty())
{
rc += network_quota.from_xml_node(content[0]);
}
object_xml->free_nodes(content);
content.clear();
object_xml->get_nodes(vm_xpath, content);
if (!content.empty())
{
rc += vm_quota.from_xml_node(content[0]);
}
object_xml->free_nodes(content);
content.clear();
object_xml->get_nodes(img_xpath, content);
if (!content.empty())
{
rc += image_quota.from_xml_node(content[0]);
}
object_xml->free_nodes(content);
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void Quotas::vm_del(int uid, int gid, Template * tmpl)
{
Nebula& nd = Nebula::instance();
UserPool * upool = nd.get_upool();
GroupPool * gpool = nd.get_gpool();
User * user;
Group * group;
if ( uid != UserPool::ONEADMIN_ID )
{
user = upool->get(uid, true);
if ( user != 0 )
{
user->quota.vm_del(tmpl);
upool->update(user);
user->unlock();
}
}
if ( gid != GroupPool::ONEADMIN_ID )
{
group = gpool->get(gid, true);
if ( group != 0 )
{
group->quota.vm_del(tmpl);
gpool->update(group);
group->unlock();
}
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void Quotas::ds_del(int uid, int gid, Template * tmpl)
{
Nebula& nd = Nebula::instance();
UserPool * upool = nd.get_upool();
GroupPool * gpool = nd.get_gpool();
User * user;
Group * group;
if ( uid != UserPool::ONEADMIN_ID )
{
user = upool->get(uid, true);
if ( user != 0 )
{
user->quota.ds_del(tmpl);
upool->update(user);
user->unlock();
}
}
if ( gid != GroupPool::ONEADMIN_ID )
{
group = gpool->get(gid, true);
if ( group != 0 )
{
group->quota.ds_del(tmpl);
gpool->update(group);
group->unlock();
}
}
}

View File

@ -28,7 +28,8 @@ source_files=[
'QuotaDatastore.cc', 'QuotaDatastore.cc',
'QuotaNetwork.cc', 'QuotaNetwork.cc',
'QuotaVirtualMachine.cc', 'QuotaVirtualMachine.cc',
'QuotaImage.cc' 'QuotaImage.cc',
'Quotas.cc'
] ]
# Build library # Build library

View File

@ -1109,77 +1109,16 @@ error_common:
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
// TODO: this method requires the VM to be locked, and then it locks the Image void VirtualMachine::get_disk_info(int& num_disks,
// to acquire. Check if this can be troublesome set<string>& used_targets)
int VirtualMachine::attach_disk(VirtualMachineTemplate * tmpl, string& error_str)
{ {
int num_disks, rc;
vector<Attribute *> disks; vector<Attribute *> disks;
ImagePool * ipool;
VectorAttribute * disk; VectorAttribute * disk;
VectorAttribute * new_disk;
vector<int> acquired_images;
int new_disk_id; string target;
int image_id;
string dev_prefix;
string target;
queue<pair <string, VectorAttribute *> > disks_queue;
set<string> used_targets;
ostringstream oss;
Image::ImageType img_type;
Nebula& nd = Nebula::instance();
ipool = nd.get_ipool();
// -------------------------------------------------------------------------
// Get the DISK attribute from the template
// -------------------------------------------------------------------------
num_disks = tmpl->get("DISK", disks);
if ( num_disks != 1 )
{
goto error_no_disk;
}
new_disk = new VectorAttribute( *(dynamic_cast<VectorAttribute * >(disks[0])) );
// -------------------------------------------------------------------------
// See if there is a CONTEXT cdrom, and get the target it is using
// -------------------------------------------------------------------------
num_disks = obj_template->get("CONTEXT", disks);
if ( num_disks > 0 )
{
disk = dynamic_cast<VectorAttribute * >(disks[0]);
if ( disk != 0 )
{
target = disk->vector_value("TARGET");
if ( !target.empty() )
{
used_targets.insert(target);
}
}
}
// -------------------------------------------------------------------------
// Check the used targets
// -------------------------------------------------------------------------
disks.clear();
num_disks = obj_template->get("DISK", disks); num_disks = obj_template->get("DISK", disks);
if ( num_disks >= 20 )
{
goto error_max_disks;
}
for(int i=0; i<num_disks; i++) for(int i=0; i<num_disks; i++)
{ {
disk = dynamic_cast<VectorAttribute * >(disks[i]); disk = dynamic_cast<VectorAttribute * >(disks[i]);
@ -1197,79 +1136,101 @@ int VirtualMachine::attach_disk(VirtualMachineTemplate * tmpl, string& error_str
} }
} }
if ( obj_template->get("CONTEXT", disks) > 0 )
{
disk = dynamic_cast<VectorAttribute * >(disks[0]);
if ( disk != 0 )
{
target = disk->vector_value("TARGET");
if ( !target.empty() )
{
used_targets.insert(target);
}
}
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
VectorAttribute * VirtualMachine::set_up_attach_disk(
VirtualMachineTemplate * tmpl,
set<string>& used_targets,
int num_disks,
int uid,
int& image_id,
string& error_str)
{
vector<Attribute *> disks;
VectorAttribute * new_disk;
string target;
Nebula& nd = Nebula::instance();
ImagePool * ipool = nd.get_ipool();
ImageManager* imagem = nd.get_imagem();
string dev_prefix;
Image::ImageType img_type;
image_id = -1;
// -------------------------------------------------------------------------
// Get the DISK attribute from the template
// -------------------------------------------------------------------------
if ( tmpl->get("DISK", disks) != 1 )
{
error_str = "The template must contain one DISK attribute";
return 0;
}
new_disk = new VectorAttribute(*(dynamic_cast<VectorAttribute * >(disks[0])));
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Acquire the new disk image // Acquire the new disk image
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// num_disks +1 because the context is not a DISK, but it takes the int rc = ipool->disk_attribute(new_disk,
// ds/<vm_id>/disk.num_disks file num_disks + 1, //Preserv CONTEXT disk.i file
new_disk_id = num_disks + 1; img_type,
dev_prefix,
rc = ipool->disk_attribute(new_disk, uid,
new_disk_id, image_id,
img_type, error_str);
dev_prefix, if ( rc != 0 )
uid,
image_id,
error_str);
if ( rc == 0 )
{ {
acquired_images.push_back(image_id); return 0;
}
target = new_disk->vector_value("TARGET"); target = new_disk->vector_value("TARGET");
if ( !target.empty() ) if ( !target.empty() )
{
if ( used_targets.insert(target).second == false )
{ {
if ( used_targets.insert(target).second == false ) ostringstream oss;
{
goto error_duplicated_target; oss << "Target " << target << "is already in use.";
} error_str = oss.str();
}
else imagem->release_image(image_id, false);
{
disks_queue.push( make_pair(dev_prefix, new_disk) );
} }
return 0;
} }
else else
{ {
goto error_common; queue<pair <string, VectorAttribute *> > disks_queue;
disks_queue.push(make_pair(dev_prefix, new_disk));
assign_disk_targets(disks_queue, used_targets);
} }
assign_disk_targets(disks_queue, used_targets); return new_disk;
// -------------------------------------------------------------------------
// Add the disk to the VM template
// -------------------------------------------------------------------------
new_disk->replace("ATTACH", "YES");
obj_template->set(new_disk);
return 0;
error_no_disk:
error_str = "The template must contain one DISK attribute";
return -1;
error_max_disks:
error_str = "Exceeded the maximum number of disks (20)";
return -1;
error_duplicated_target:
oss << "Two disks have defined the same target " << target;
error_str = oss.str();
error_common:
ImageManager * imagem = nd.get_imagem();
vector<int>::iterator it;
for ( it=acquired_images.begin() ; it < acquired_images.end(); it++ )
{
imagem->release_image(*it, false);
}
return -1;
} }
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
@ -1281,11 +1242,6 @@ VectorAttribute* VirtualMachine::get_attach_disk()
vector<Attribute *> disks; vector<Attribute *> disks;
VectorAttribute * disk; VectorAttribute * disk;
ostringstream oss;
// -------------------------------------------------------------------------
// Set DISK attributes & Targets
// -------------------------------------------------------------------------
num_disks = obj_template->get("DISK", disks); num_disks = obj_template->get("DISK", disks);
for(int i=0; i<num_disks; i++) for(int i=0; i<num_disks; i++)
@ -1309,12 +1265,11 @@ VectorAttribute* VirtualMachine::get_attach_disk()
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
int VirtualMachine::attach_success() void VirtualMachine::clear_attach_disk()
{ {
int num_disks; int num_disks;
vector<Attribute *> disks; vector<Attribute *> disks;
VectorAttribute * disk; VectorAttribute * disk;
bool removed;
num_disks = obj_template->get("DISK", disks); num_disks = obj_template->get("DISK", disks);
@ -1330,46 +1285,25 @@ int VirtualMachine::attach_success()
if ( disk->vector_value("ATTACH") == "YES" ) if ( disk->vector_value("ATTACH") == "YES" )
{ {
disk->remove("ATTACH"); disk->remove("ATTACH");
removed = true; return;
} }
} }
if ( removed )
{
return 0;
}
return -1;
} }
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
// TODO: this method requires the VM to be locked, and then it locks the Image VectorAttribute * VirtualMachine::delete_attach_disk()
// to release. Check if this can be troublesome
int VirtualMachine::attach_failure()
{ {
int num_disks;
vector<Attribute *> disks; vector<Attribute *> disks;
VectorAttribute * disk; VectorAttribute * disk;
bool found = false;
bool uses_image = false;
int iid;
Nebula& nd = Nebula::instance(); int num_disks = obj_template->get("DISK", disks);
ImageManager * imagem = nd.get_imagem();
num_disks = obj_template->get("DISK", disks); for(int i=0; i<num_disks; i++)
int i = 0;
while( !found && i<num_disks )
{ {
disk = dynamic_cast<VectorAttribute * >(disks[i]); disk = dynamic_cast<VectorAttribute * >(disks[i]);
i++;
if ( disk == 0 ) if ( disk == 0 )
{ {
continue; continue;
@ -1377,23 +1311,10 @@ int VirtualMachine::attach_failure()
if ( disk->vector_value("ATTACH") == "YES" ) if ( disk->vector_value("ATTACH") == "YES" )
{ {
uses_image = ( disk->vector_value("IMAGE_ID", iid) != -1 ); return static_cast<VectorAttribute * >(obj_template->remove(disk));
obj_template->erase(disk);
found = true;
} }
} }
if ( !found )
{
return -1;
}
if ( uses_image )
{
imagem->release_image(iid, false);
}
return 0; return 0;
} }