diff --git a/include/Host.h b/include/Host.h index 03d082aad5..31cc4477d2 100644 --- a/include/Host.h +++ b/include/Host.h @@ -317,6 +317,19 @@ public: } }; + /** + * Updates the capacity used in a host when a VM is resized + * counters + * @param cpu increment of cpu requested by the VM + * @param mem increment of memory requested by the VM + * @param disk not used + * @return 0 on success + */ + void update_capacity(int cpu, int mem, int disk) + { + host_share.update(cpu,mem,disk); + }; + /** * Tests whether a new VM can be hosted by the host or not * @param cpu needed by the VM (percentage) @@ -326,7 +339,7 @@ public: */ bool test_capacity(int cpu, int mem, int disk) { - return host_share.test(cpu,mem,disk); + return host_share.test(cpu, mem, disk); } /** diff --git a/include/HostShare.h b/include/HostShare.h index c7321a3662..66c5acf536 100644 --- a/include/HostShare.h +++ b/include/HostShare.h @@ -54,6 +54,19 @@ public: running_vms++; } + /** + * Updates the capacity of VM in this share + * @param cpu increment + * @param mem increment + * @param disk increment + */ + void update(int cpu, int mem, int disk) + { + cpu_usage += cpu; + mem_usage += mem; + disk_usage += disk; + } + /** * Delete a VM from this share * @param cpu requested by the VM diff --git a/include/PoolObjectSQL.h b/include/PoolObjectSQL.h index 812a587157..beec7d8651 100644 --- a/include/PoolObjectSQL.h +++ b/include/PoolObjectSQL.h @@ -427,6 +427,16 @@ public: obj_template->add(name, value); } + /** + * Adds a float attribute + * @param att_name Name for the attribute + * @param att_val integer + */ + void add_template_attribute(const string& name, float value) + { + obj_template->add(name, value); + } + /** * Factory method for templates, it should be implemented * by classes that uses templates diff --git a/include/Quota.h b/include/Quota.h index 01eb24b885..ad99b047b8 100644 --- a/include/Quota.h +++ b/include/Quota.h @@ -51,13 +51,26 @@ public: */ virtual bool check(Template* tmpl, Quotas& default_quotas, string& error) = 0; + /** + * Check if a resource update in usage counters will exceed the + * quota limits. If not the usage counters are updated for that resource + * @param tmpl with increments in MEMORY and CPU + * @param default_quotas Quotas that contain the default limits + * @param error string + * @return true if the operation can be performed + */ + virtual bool update(Template * tmpl, Quotas& default_quotas, string& error) + { + error = "Update operation for quotas not supported."; + return false; + }; + /** * Decrement usage counters when deallocating image * @param tmpl template for the resource */ virtual void del(Template* tmpl) = 0; - /** * Returns the name that identifies the quota in a template */ diff --git a/include/QuotaVirtualMachine.h b/include/QuotaVirtualMachine.h index 622ea5c439..e46c47c0c3 100644 --- a/include/QuotaVirtualMachine.h +++ b/include/QuotaVirtualMachine.h @@ -57,6 +57,16 @@ public: */ bool check(Template* tmpl, Quotas& default_quotas, string& error); + /** + * Check if the resource update (change in MEMORY or CPU) will exceed the + * quota limits. If not the usage counters are updated + * @param tmpl with increments in MEMORY and CPU + * @param default_quotas Quotas that contain the default limits + * @param error string + * @return true if the operation can be performed + */ + bool update(Template * tmpl, Quotas& default_quotas, string& error); + /** * Decrement usage counters when deallocating image * @param tmpl template for the resource diff --git a/include/Quotas.h b/include/Quotas.h index f42761ab06..02a30e36d7 100644 --- a/include/Quotas.h +++ b/include/Quotas.h @@ -141,13 +141,27 @@ public: * @param tmpl template for the VirtualMachine * @param default_quotas Quotas that contain the default limits * @param error_str string describing the error - * @return true if VM can be allocated, false otherwise + * @return true if resource can be allocated, false otherwise */ bool quota_check(QuotaType type, Template *tmpl, Quotas& default_quotas, string& error_str); + /** + * Update usage of an existing quota (e.g. size of an image), it updates + * the usage counters if quotas are not exceeded. + * @param type the quota to work with + * @param tmpl template for the VirtualMachine + * @param default_quotas Quotas that contain the default limits + * @param error_str string describing the error + * @return true if resource can be updated, false otherwise + */ + bool quota_update(QuotaType type, + Template *tmpl, + Quotas& default_quotas, + string& error_str); + /** * Delete usage from the given quota counters. * @param type the quota to work with diff --git a/include/RequestManagerVirtualMachine.h b/include/RequestManagerVirtualMachine.h index 0393c22b99..b4bf5a9852 100644 --- a/include/RequestManagerVirtualMachine.h +++ b/include/RequestManagerVirtualMachine.h @@ -217,6 +217,21 @@ public: RequestAttributes& att); }; +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ + +class VirtualMachineResize : public RequestManagerVirtualMachine +{ +public: + VirtualMachineResize(): + RequestManagerVirtualMachine("VirtualMachineResize", + "Changes the capacity of the virtual machine", + "A:sidiib"){}; + ~VirtualMachineResize(){}; + + void request_execute(xmlrpc_c::paramList const& _paramList, + RequestAttributes& att); +}; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ diff --git a/include/Template.h b/include/Template.h index 400c60e5bd..21e3aed633 100644 --- a/include/Template.h +++ b/include/Template.h @@ -156,10 +156,10 @@ public: oss << value; - return replace(name, oss.str()); + return replace(name, oss.str()); } - /* + /* * Adds a new single attribute to the template. It will replace an existing * one if replace_mode was set to true * @param name of the attribute @@ -184,6 +184,20 @@ public: set(new SingleAttribute(name, oss.str())); } + /** + * Adds a new single attribute to the template. + * @param name of the attribute + * @param value of the attribute + */ + void add(const string& name, float value) + { + ostringstream oss; + + oss << value; + + set(new SingleAttribute(name, oss.str())); + } + /** * Removes an attribute from the template. The attributes are returned. The * attributes MUST be freed by the calling funtion @@ -196,10 +210,10 @@ public: vector& values); /** - * Removes an attribute from the template, but it DOES NOT free the + * 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 + * @return pointer to the removed attribute or 0 if non attribute was * removed */ virtual Attribute * remove(Attribute * att); diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index ec52350bed..99d4eca0a6 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -747,7 +747,7 @@ public: }; // ------------------------------------------------------------------------ - // Timers + // Timers & // ------------------------------------------------------------------------ /** * Gets time from last information polling. @@ -766,6 +766,28 @@ public: */ void get_requirements (int& cpu, int& memory, int& disk); + /** + * Checks if the resize parameters are valid + * @param cpu New CPU. 0 means unchanged. + * @param memory New MEMORY. 0 means unchanged. + * @param vcpu New VCPU. 0 means unchanged. + * @param error_str Error reason, if any + * + * @return 0 on success + */ + int check_resize (float cpu, int memory, int vcpu, string& error_str); + + /** + * Resize the VM capacity + * @param cpu + * @param memory + * @param vcpu + * @param error_str Error reason, if any + * + * @return 0 on success + */ + int resize (float cpu, int memory, int vcpu, string& error_str); + // ------------------------------------------------------------------------ // Network Leases & Disk Images // ------------------------------------------------------------------------ diff --git a/src/cli/one_helper.rb b/src/cli/one_helper.rb index f812bc0de6..d0dcbf83cb 100644 --- a/src/cli/one_helper.rb +++ b/src/cli/one_helper.rb @@ -103,6 +103,7 @@ EOT } ] + #NOTE: Other options defined using this array, add new options at the end TEMPLATE_OPTIONS=[ { :name => 'cpu', @@ -212,6 +213,8 @@ EOT TEMPLATE_OPTIONS_VM=[TEMPLATE_NAME_VM]+TEMPLATE_OPTIONS+[DRY] + CAPACITY_OPTIONS_VM=[TEMPLATE_OPTIONS[0],TEMPLATE_OPTIONS[1],TEMPLATE_OPTIONS[3]] + OPTIONS = XML, NUMERIC, KILOBYTES class OneHelper diff --git a/src/cli/onevm b/src/cli/onevm index f4e4a7cee2..3577adf771 100755 --- a/src/cli/onevm +++ b/src/cli/onevm @@ -662,4 +662,23 @@ cmd=CommandParser::CmdParser.new(ARGV) do :options=>CLIHelper::OPTIONS+OpenNebulaHelper::OPTIONS do helper.list_pool(options, true, args[0]) end + + resize_desc = <<-EOT.unindent + Resizes the capacity of a Virtual Machine (offline, the VM cannot be + RUNNING) + + EOT + + command :resize, resize_desc, :vmid, :options => + OpenNebulaHelper::CAPACITY_OPTIONS_VM + [ENFORCE] do + + cpu = options[:cpu] || 0.0 + memory = options[:memory] || 0 + vcpu = options[:vcpu] || 0 + enforce = options[:enforce] || false + + helper.perform_action(args[0], options, "Resizing VM") do |vm| + vm.resize(cpu, memory, vcpu, enforce) + end + end end diff --git a/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java b/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java index 0cc1260ec2..fbd9f39ed1 100644 --- a/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java +++ b/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java @@ -41,6 +41,7 @@ public class VirtualMachine extends PoolElement{ private static final String DETACH = METHOD_PREFIX + "detach"; private static final String RENAME = METHOD_PREFIX + "rename"; private static final String UPDATE = METHOD_PREFIX + "update"; + private static final String RESIZE = METHOD_PREFIX + "resize"; private static final String[] VM_STATES = { @@ -184,6 +185,25 @@ public class VirtualMachine extends PoolElement{ return client.call(UPDATE, id, new_template); } + /** + * Resizes the VM capacity + * + * @param client XML-RPC Client. + * @param id The id of the target vm. + * @param cpu the new CPU value + * @param memory the new MEMORY value + * @param vcpu the new VCPU value + * @param enforce If it is set to true, the host capacity + * will be checked. This will only affect oneadmin requests, regular users + * resize requests will always be enforced + * @return If an error occurs the error message contains the reason. + */ + public static OneResponse resize(Client client, int id, + double cpu, int memory, int vcpu, boolean enforce) + { + return client.call(RESIZE, id, cpu, memory, vcpu, enforce); + } + /** * Retrieves the information of the given VM. * @@ -571,6 +591,22 @@ public class VirtualMachine extends PoolElement{ return client.call(UPDATE, id, new_template); } + /** + * Resizes this VM's capacity + * + * @param cpu the new CPU value + * @param memory the new MEMORY value + * @param vcpu the new VCPU value + * @param enforce If it is set to true, the host capacity + * will be checked. This will only affect oneadmin requests, regular users + * resize requests will always be enforced + * @return If an error occurs the error message contains the reason. + */ + public OneResponse resize(double cpu, int memory, int vcpu, boolean enforce) + { + return client.call(RESIZE, id, cpu, memory, vcpu, enforce); + } + // ================================= // Helpers // ================================= diff --git a/src/oca/java/test/VirtualMachineTest.java b/src/oca/java/test/VirtualMachineTest.java index 02b0632f2e..5abcf065b6 100644 --- a/src/oca/java/test/VirtualMachineTest.java +++ b/src/oca/java/test/VirtualMachineTest.java @@ -341,4 +341,14 @@ public class VirtualMachineTest res = vm.info(); assertTrue( res.getErrorMessage(), !res.isError() ); } + + @Test + public void resize() + { + res = vm.resize(2.5, 512, 0, true); + assertTrue( res.getErrorMessage(), !res.isError() ); + + res = vm.resize(1, 128, 2, false); + assertTrue( res.getErrorMessage(), !res.isError() ); + } } diff --git a/src/oca/ruby/opennebula/virtual_machine.rb b/src/oca/ruby/opennebula/virtual_machine.rb index f794b5b8a5..7fe52979c0 100644 --- a/src/oca/ruby/opennebula/virtual_machine.rb +++ b/src/oca/ruby/opennebula/virtual_machine.rb @@ -37,7 +37,8 @@ module OpenNebula :attach => "vm.attach", :detach => "vm.detach", :rename => "vm.rename", - :update => "vm.update" + :update => "vm.update", + :resize => "vm.resize" } VM_STATE=%w{INIT PENDING HOLD ACTIVE STOPPED SUSPENDED DONE FAILED @@ -338,6 +339,21 @@ module OpenNebula return rc end + # Resize the VM + # + # @param cpu [Float] the new CPU value + # @param memory [Integer] the new MEMORY value + # @param vcpu [Integer] the new VCPU value + # @param enforce [true|false] If it is set to true, the host capacity + # will be checked. This will only affect oneadmin requests, regular users + # resize requests will always be enforced + # + # @return [nil, OpenNebula::Error] nil in case of success, Error + # otherwise + def resize(cpu, memory, vcpu, enforce) + return call(VM_METHODS[:resize], @pe_id, cpu, memory, vcpu, enforce) + end + # Changes the owner/group # uid:: _Integer_ the new owner id. Set to -1 to leave the current one # gid:: _Integer_ the new group id. Set to -1 to leave the current one diff --git a/src/rm/Request.cc b/src/rm/Request.cc index cb423626e8..231705d4d7 100644 --- a/src/rm/Request.cc +++ b/src/rm/Request.cc @@ -470,7 +470,7 @@ void Request::quota_rollback(Template * tmpl, if ( att.gid != GroupPool::ONEADMIN_ID && att.gid != -1 ) { - group_quota_rollback(tmpl, qtype, att);; + group_quota_rollback(tmpl, qtype, att); } } diff --git a/src/rm/RequestManager.cc b/src/rm/RequestManager.cc index d698e67197..4dad32ab5f 100644 --- a/src/rm/RequestManager.cc +++ b/src/rm/RequestManager.cc @@ -254,6 +254,7 @@ void RequestManager::register_xml_methods() xmlrpc_c::methodPtr vm_monitoring(new VirtualMachineMonitoring()); xmlrpc_c::methodPtr vm_attach(new VirtualMachineAttach()); xmlrpc_c::methodPtr vm_detach(new VirtualMachineDetach()); + xmlrpc_c::methodPtr vm_resize(new VirtualMachineResize()); xmlrpc_c::methodPtr vm_pool_acct(new VirtualMachinePoolAccounting()); xmlrpc_c::methodPtr vm_pool_monitoring(new VirtualMachinePoolMonitoring()); @@ -396,6 +397,7 @@ void RequestManager::register_xml_methods() RequestManagerRegistry.addMethod("one.vm.attach", vm_attach); RequestManagerRegistry.addMethod("one.vm.detach", vm_detach); RequestManagerRegistry.addMethod("one.vm.rename", vm_rename); + RequestManagerRegistry.addMethod("one.vm.resize", vm_resize); RequestManagerRegistry.addMethod("one.vm.update", vm_update); RequestManagerRegistry.addMethod("one.vmpool.info", vm_pool_info); diff --git a/src/rm/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc index b8baaff07f..51bf57b1b7 100644 --- a/src/rm/RequestManagerVirtualMachine.cc +++ b/src/rm/RequestManagerVirtualMachine.cc @@ -17,6 +17,7 @@ #include "RequestManagerVirtualMachine.h" #include "PoolObjectAuth.h" #include "Nebula.h" +#include "Quotas.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -1056,3 +1057,329 @@ void VirtualMachineDetach::request_execute(xmlrpc_c::paramList const& paramList, /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ + +void VirtualMachineResize::request_execute(xmlrpc_c::paramList const& paramList, + RequestAttributes& att) +{ + int id = xmlrpc_c::value_int(paramList.getInt(1)); + float ncpu = xmlrpc_c::value_double(paramList.getDouble(2)); + int nmemory = xmlrpc_c::value_int(paramList.getInt(3)); + int nvcpu = xmlrpc_c::value_int(paramList.getInt(4)); + bool enforce_param = xmlrpc_c::value_boolean(paramList.getBoolean(5)); + + float ocpu, dcpu; + int omemory, dmemory; + int ovcpu; + + Nebula& nd = Nebula::instance(); + UserPool* upool = nd.get_upool(); + GroupPool* gpool = nd.get_gpool(); + Quotas dquotas = nd.get_default_user_quota(); + HostPool * hpool = nd.get_hpool(); + + Host * host; + + Template deltas; + string error_str; + bool rc; + int ret; + int hid = -1; + + PoolObjectAuth vm_perms; + + VirtualMachinePool * vmpool = static_cast(pool); + VirtualMachine * vm; + + bool enforce = true; + + if (att.uid == UserPool::ONEADMIN_ID || att.gid == GroupPool::ONEADMIN_ID) + { + enforce = enforce_param; + } + + /* ---------------------------------------------------------------------- */ + /* Authorize the operation */ + /* ---------------------------------------------------------------------- */ + + if ( vm_authorization(id, 0, 0, att, 0, 0, auth_op) == false ) + { + return; + } + + /* ---------------------------------------------------------------------- */ + /* Get the resize values */ + /* ---------------------------------------------------------------------- */ + + vm = vmpool->get(id, true); + + if (vm == 0) + { + failure_response(NO_EXISTS, + get_error(object_name(PoolObjectSQL::VM),id), + att); + return; + } + + vm->get_permissions(vm_perms); + + vm->get_template_attribute("MEMORY", omemory); + vm->get_template_attribute("CPU", ocpu); + vm->get_template_attribute("VCPU", ovcpu); + + if (nmemory == 0) + { + nmemory = omemory; + } + + if (ncpu == 0) + { + ncpu = ocpu; + } + + if (nvcpu == 0) + { + nvcpu = ovcpu; + } + + dcpu = ncpu - ocpu; + dmemory = nmemory - omemory; + + deltas.add("MEMORY", dmemory); + deltas.add("CPU", dcpu); + + switch (vm->get_state()) + { + case VirtualMachine::POWEROFF: //Only check host capacity in POWEROFF + if (vm->hasHistory() == true) + { + hid = vm->get_hid(); + } + break; + + case VirtualMachine::INIT: + case VirtualMachine::PENDING: + case VirtualMachine::HOLD: + case VirtualMachine::FAILED: + break; + + case VirtualMachine::STOPPED: + case VirtualMachine::DONE: + case VirtualMachine::SUSPENDED: + case VirtualMachine::ACTIVE: + failure_response(ACTION, + request_error("Wrong state to perform action",""), + att); + + vm->unlock(); + return; + } + + ret = vm->check_resize(ncpu, nmemory, nvcpu, error_str); + + vm->unlock(); + + if (ret != 0) + { + failure_response(INTERNAL, + request_error("Could resize the VM", error_str), + att); + return; + } + + /* ---------------------------------------------------------------------- */ + /* Check quotas */ + /* ---------------------------------------------------------------------- */ + + 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, 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, 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(); + } + } + + /* ---------------------------------------------------------------------- */ + /* Check & update host capacity */ + /* ---------------------------------------------------------------------- */ + + if (hid != -1) + { + int dcpu_host = (int) (dcpu * 100);//now in 100% + int dmem_host = dmemory * 1024; //now in Kilobytes + + host = hpool->get(hid, true); + + if (host == 0) + { + failure_response(NO_EXISTS, + get_error(object_name(PoolObjectSQL::HOST),hid), + att); + + quota_rollback(&deltas, Quotas::VM, att); + + return; + } + + if ( enforce && host->test_capacity(dcpu_host, dmem_host, 0) == false) + { + ostringstream oss; + + oss << object_name(PoolObjectSQL::HOST) + << " " << hid << " does not have enough capacity."; + + failure_response(ACTION, request_error(oss.str(),""), att); + + host->unlock(); + + quota_rollback(&deltas, Quotas::VM, att); + + return; + } + + host->update_capacity(dcpu_host, dmem_host, 0); + + hpool->update(host); + + host->unlock(); + } + + /* ---------------------------------------------------------------------- */ + /* Resize the VM */ + /* ---------------------------------------------------------------------- */ + + vm = vmpool->get(id, true); + + if (vm == 0) + { + failure_response(NO_EXISTS, + get_error(object_name(PoolObjectSQL::VM),id), + att); + + quota_rollback(&deltas, Quotas::VM, att); + + if (hid != -1) + { + host = hpool->get(hid, true); + + if (host != 0) + { + host->update_capacity(-dcpu, -dmemory, 0); + hpool->update(host); + + host->unlock(); + } + } + return; + } + + //Check again state as the VM may transit to active (e.g. scheduled) + switch (vm->get_state()) + { + case VirtualMachine::INIT: + case VirtualMachine::PENDING: + case VirtualMachine::HOLD: + case VirtualMachine::FAILED: + case VirtualMachine::POWEROFF: + ret = vm->resize(ncpu, nmemory, nvcpu, error_str); + + if (ret != 0) + { + vm->unlock(); + + failure_response(INTERNAL, + request_error("Could not resize the VM", error_str), + att); + return; + } + + vmpool->update(vm); + break; + + case VirtualMachine::STOPPED: + case VirtualMachine::DONE: + case VirtualMachine::SUSPENDED: + case VirtualMachine::ACTIVE: + failure_response(ACTION, + request_error("Wrong state to perform action",""), + att); + + vm->unlock(); + + quota_rollback(&deltas, Quotas::VM, att); + + if (hid != -1) + { + host = hpool->get(hid, true); + + if (host != 0) + { + host->update_capacity(ocpu - ncpu, omemory - nmemory, 0); + hpool->update(host); + + host->unlock(); + } + } + return; + } + + vm->unlock(); + + success_response(id, att); +} diff --git a/src/um/QuotaVirtualMachine.cc b/src/um/QuotaVirtualMachine.cc index cacd7afed0..1df620dba7 100644 --- a/src/um/QuotaVirtualMachine.cc +++ b/src/um/QuotaVirtualMachine.cc @@ -117,3 +117,25 @@ int QuotaVirtualMachine::get_default_quota( /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ + +bool QuotaVirtualMachine::update(Template * tmpl, + Quotas& default_quotas, + string& error) +{ + map vm_request; + + int delta_memory; + float delta_cpu; + + if ( tmpl->get("MEMORY", delta_memory) == true ) + { + vm_request.insert(make_pair("MEMORY", delta_memory)); + } + + if ( tmpl->get("CPU", delta_cpu) == true ) + { + vm_request.insert(make_pair("CPU", delta_cpu)); + } + + return check_quota("", vm_request, default_quotas, error); +} diff --git a/src/um/Quotas.cc b/src/um/Quotas.cc index 3918471294..90bb22dbb4 100644 --- a/src/um/Quotas.cc +++ b/src/um/Quotas.cc @@ -29,7 +29,7 @@ int Quotas::set(Template *tmpl, string& error) { return -1; } - + vquotas.clear(); } @@ -39,7 +39,7 @@ int Quotas::set(Template *tmpl, string& error) { return -1; } - + vquotas.clear(); } @@ -49,7 +49,7 @@ int Quotas::set(Template *tmpl, string& error) { return -1; } - + vquotas.clear(); } @@ -59,7 +59,7 @@ int Quotas::set(Template *tmpl, string& error) { return -1; } - + vquotas.clear(); } @@ -219,6 +219,31 @@ bool Quotas::quota_check(QuotaType type, /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +bool Quotas::quota_update(QuotaType type, + Template *tmpl, + Quotas &default_quotas, + string &error_str) +{ + switch (type) + { + // This is an internal check, should never get in here. + case DATASTORE: + case NETWORK: + case IMAGE: + case VIRTUALMACHINE: + error_str = "Cannot update quota. Not implemented"; + return false; + + case VM: + return vm_quota.update(tmpl, default_quotas, error_str); + } + + return false; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + void Quotas::quota_del(QuotaType type, int uid, int gid, Template * tmpl) { Nebula& nd = Nebula::instance(); @@ -239,7 +264,7 @@ void Quotas::quota_del(QuotaType type, int uid, int gid, Template * tmpl) upool->update(user); user->unlock(); - } + } } if ( gid != GroupPool::ONEADMIN_ID ) @@ -253,6 +278,6 @@ void Quotas::quota_del(QuotaType type, int uid, int gid, Template * tmpl) gpool->update(group); group->unlock(); - } + } } } diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index c60f67d023..a1d1692214 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -1258,14 +1258,11 @@ void VirtualMachine::cp_previous_history() void VirtualMachine::get_requirements (int& cpu, int& memory, int& disk) { - string scpu; istringstream iss; float fcpu; - get_template_attribute("MEMORY",memory); - get_template_attribute("CPU",scpu); - - if ((memory == 0) || (scpu=="")) + if ((get_template_attribute("MEMORY",memory) == false) || + (get_template_attribute("CPU",fcpu) == false)) { cpu = 0; memory = 0; @@ -1274,9 +1271,6 @@ void VirtualMachine::get_requirements (int& cpu, int& memory, int& disk) return; } - iss.str(scpu); - iss >> fcpu; - cpu = (int) (fcpu * 100);//now in 100% memory = memory * 1024; //now in Kilobytes disk = 0; @@ -1287,6 +1281,70 @@ void VirtualMachine::get_requirements (int& cpu, int& memory, int& disk) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +int VirtualMachine::check_resize ( + float cpu, int memory, int vcpu, string& error_str) +{ + if (cpu < 0) + { + error_str = "CPU must be a positive float or integer value."; + return -1; + } + + if (memory < 0) + { + error_str = "MEMORY must be a positive integer value."; + return -1; + } + + if (vcpu < 0) + { + error_str = "VCPU must be a positive integer value."; + return -1; + } + + return 0; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int VirtualMachine::resize(float cpu, int memory, int vcpu, string& error_str) +{ + ostringstream oss; + + int rc = check_resize(cpu, memory, vcpu, error_str); + + if (rc != 0) + { + return rc; + } + + if (cpu > 0) + { + oss << cpu; + replace_template_attribute("CPU", oss.str()); + oss.str(""); + } + + if (memory > 0) + { + oss << memory; + replace_template_attribute("MEMORY", oss.str()); + oss.str(""); + } + + if (vcpu > 0) + { + oss << vcpu; + replace_template_attribute("VCPU", oss.str()); + } + + return 0; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + static void assign_disk_targets(queue >& _queue, set& used_targets) {