1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-11 04:58:16 +03:00

B #6387: Fix accounting after onevm resize (#2866)

* Fix accounting after onevm resize
* Fix crash in VM resize if VM has no history

(cherry picked from commit ca934bbde0c6db9cfc4f776d0bcd1f8c7608a3de)
This commit is contained in:
Pavel Czerný 2024-01-03 13:01:18 +01:00 committed by Ruben S. Montero
parent 0949062589
commit e2f2782195
No known key found for this signature in database
GPG Key ID: A0CEA6FA880A1D87
4 changed files with 185 additions and 145 deletions

View File

@ -513,6 +513,21 @@ public:
*/
int backup_cancel(int vid, const RequestAttributes& ra, std::string& error_str);
/**
* Resize cpu and memory
*
* @param vid the VM id
* @param cpu new CPU value
* @param vcpu new VCPU value
* @param memory new memory value
* @param ra information about the API call request
* @param error_str Error reason, if any
*
* @return 0 on success, -1 otherwise
*/
int resize(int vid, float cpu, int vcpu, long memory,
const RequestAttributes& ra, std::string& error_str);
//--------------------------------------------------------------------------
// DM Actions associated with a VM state transition
//--------------------------------------------------------------------------

View File

@ -2852,3 +2852,163 @@ int DispatchManager::backup_cancel(int vid,
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
static int test_set_capacity(VirtualMachine * vm, float cpu, long mem, int vcpu,
string& error)
{
HostPool * hpool = Nebula::instance().get_hpool();
int rc;
if ( vm->get_state() == VirtualMachine::POWEROFF ||
(vm->get_state() == VirtualMachine::ACTIVE &&
vm->get_lcm_state() == VirtualMachine::RUNNING))
{
HostShareCapacity sr;
auto host = hpool->get(vm->get_hid());
if ( host == nullptr )
{
error = "Could not update host";
return -1;
}
vm->get_capacity(sr);
host->del_capacity(sr);
rc = vm->resize(cpu, mem, vcpu, error);
if ( rc == -1 )
{
return -1;
}
vm->get_capacity(sr);
if (!host->test_capacity(sr, error))
{
return -1;
}
host->add_capacity(sr);
hpool->update(host.get());
}
else
{
rc = vm->resize(cpu, mem, vcpu, error);
}
return rc;
}
int DispatchManager::resize(int vid, float cpu, int vcpu, long memory,
const RequestAttributes& ra, string& error_str)
{
/* ---------------------------------------------------------------------- */
/* Check & update VM & host capacity */
/* ---------------------------------------------------------------------- */
auto vm = vmpool->get(vid);
if (vm == nullptr)
{
error_str = "Virtual machine does not exist";
return -1;
}
int rc;
switch (vm->get_state())
{
case VirtualMachine::POWEROFF: //Only check host capacity in POWEROFF
case VirtualMachine::INIT:
case VirtualMachine::PENDING:
case VirtualMachine::HOLD:
case VirtualMachine::UNDEPLOYED:
case VirtualMachine::CLONING:
case VirtualMachine::CLONING_FAILURE:
rc = test_set_capacity(vm.get(), cpu, memory, vcpu, error_str);
break;
case VirtualMachine::ACTIVE:
{
if (vm->get_lcm_state() != VirtualMachine::RUNNING)
{
rc = -1;
error_str = "Cannot resize a VM in state " + vm->state_str();
break;
}
if (vm->is_pinned())
{
rc = -1;
error_str = "Cannot resize a pinned VM";
break;
}
auto vmm = Nebula::instance().get_vmm();
if (!vmm->is_live_resize(vm->get_vmm_mad()))
{
rc = -1;
error_str = "Hotplug resize not supported by driver "
+ vm->get_vmm_mad();
break;
}
long omemory;
float ocpu;
int ovcpu;
vm->get_template_attribute("MEMORY", omemory);
vm->get_template_attribute("CPU", ocpu);
vm->get_template_attribute("VCPU", ovcpu);
if (ocpu == cpu && omemory == memory && ovcpu == vcpu)
{
rc = 0;
error_str = "Nothing to resize";
break;
}
rc = test_set_capacity(vm.get(), cpu, memory, vcpu, error_str);
if (rc == 0)
{
vm->set_state(VirtualMachine::HOTPLUG_RESIZE);
vm->store_resize(ocpu, omemory, ovcpu);
vm->set_resched(false);
vmm->trigger_resize(vid);
}
break;
}
case VirtualMachine::STOPPED:
case VirtualMachine::DONE:
case VirtualMachine::SUSPENDED:
rc = -1;
error_str = "Cannot resize a VM in state " + vm->state_str();
break;
}
if (rc == 0)
{
if (vm->hasHistory())
{
close_cp_history(vmpool, vm.get(), VMActions::RESIZE_ACTION, ra);
}
vmpool->update(vm.get());
}
return rc;
}

View File

@ -2594,7 +2594,7 @@ void LifeCycleManager::trigger_resize_failure(int vid)
else
{
vm->log("LCM", Log::ERROR,
"hotplug resize fails, VM in a wrong state");
"hotplug resize fails, VM in a wrong state: " + vm->state_str());
return;
}
@ -2646,6 +2646,10 @@ void LifeCycleManager::trigger_resize_failure(int vid)
vm->reset_resize();
vm->set_vm_info();
vmpool->update_history(vm.get());
vmpool->update(vm.get());
// Revert host capacity

View File

@ -1971,57 +1971,6 @@ void VirtualMachineDetach::request_execute(xmlrpc_c::paramList const& paramList,
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
static int test_set_capacity(VirtualMachine * vm, float cpu, long mem, int vcpu,
string& error)
{
HostPool * hpool = Nebula::instance().get_hpool();
int rc;
if ( vm->get_state() == VirtualMachine::POWEROFF ||
(vm->get_state() == VirtualMachine::ACTIVE &&
vm->get_lcm_state() == VirtualMachine::RUNNING))
{
HostShareCapacity sr;
auto host = hpool->get(vm->get_hid());
if ( host == nullptr )
{
error = "Could not update host";
return -1;
}
vm->get_capacity(sr);
host->del_capacity(sr);
rc = vm->resize(cpu, mem, vcpu, error);
if ( rc == -1 )
{
return -1;
}
vm->get_capacity(sr);
if (!host->test_capacity(sr, error))
{
return -1;
}
host->add_capacity(sr);
hpool->update(host.get());
}
else
{
rc = vm->resize(cpu, mem, vcpu, error);
}
return rc;
}
void VirtualMachineResize::request_execute(xmlrpc_c::paramList const& paramList,
RequestAttributes& att)
{
@ -2044,9 +1993,7 @@ void VirtualMachineResize::request_execute(xmlrpc_c::paramList const& paramList,
// -------------------------------------------------------------------------
// Parse template
// -------------------------------------------------------------------------
int rc = tmpl.parse_str_or_xml(str_tmpl, att.resp_msg);
if ( rc != 0 )
if ( tmpl.parse_str_or_xml(str_tmpl, att.resp_msg) != 0 )
{
failure_response(INTERNAL, att);
return;
@ -2181,103 +2128,17 @@ void VirtualMachineResize::request_execute(xmlrpc_c::paramList const& paramList,
RequestAttributes att_rollback(vm_perms.uid, vm_perms.gid, att);
/* ---------------------------------------------------------------------- */
/* Check & update VM & host capacity */
/* ---------------------------------------------------------------------- */
auto vm = vmpool->get(id);
if (vm == nullptr)
if ( dm->resize(id, ncpu, nvcpu, nmemory, att, att.resp_msg) == -1 )
{
att.resp_msg = id;
failure_response(NO_EXISTS, att);
quota_rollback(&deltas, Quotas::VM, att_rollback);
return;
}
switch (vm->get_state())
{
case VirtualMachine::POWEROFF: //Only check host capacity in POWEROFF
case VirtualMachine::INIT:
case VirtualMachine::PENDING:
case VirtualMachine::HOLD:
case VirtualMachine::UNDEPLOYED:
case VirtualMachine::CLONING:
case VirtualMachine::CLONING_FAILURE:
rc = test_set_capacity(vm.get(), ncpu, nmemory, nvcpu, att.resp_msg);
break;
case VirtualMachine::ACTIVE:
{
if (vm->get_lcm_state() != VirtualMachine::RUNNING)
{
rc = -1;
att.resp_msg = "Cannot resize a VM in state " + vm->state_str();
break;
}
if (vm->is_pinned())
{
rc = -1;
att.resp_msg = "Cannot resize a pinned VM";
break;
}
auto vmm = Nebula::instance().get_vmm();
if (!vmm->is_live_resize(vm->get_vmm_mad()))
{
rc = -1;
att.resp_msg = "Hotplug resize not supported by driver "
+ vm->get_vmm_mad();
break;
}
if (ocpu == ncpu && omemory == nmemory && ovcpu == nvcpu)
{
rc = 0;
att.resp_msg = "Nothing to resize";
break;
}
rc = test_set_capacity(vm.get(), ncpu, nmemory, nvcpu, att.resp_msg);
if (rc == 0)
{
vm->set_state(VirtualMachine::HOTPLUG_RESIZE);
vm->store_resize(ocpu, omemory, ovcpu);
vm->set_resched(false);
vmm->trigger_resize(id);
}
break;
}
case VirtualMachine::STOPPED:
case VirtualMachine::DONE:
case VirtualMachine::SUSPENDED:
rc = -1;
att.resp_msg = "Cannot resize a VM in state " + vm->state_str();
break;
}
if ( rc == -1 )
{
vm.reset();
quota_rollback(&deltas, Quotas::VM, att_rollback);
failure_response(ACTION, att);
}
else
{
vmpool->update(vm.get());
success_response(id, att);
return;
}
success_response(id, att);
return;
}