mirror of
https://github.com/OpenNebula/one.git
synced 2024-12-22 13:33:52 +03:00
Co-authored-by: Ruben S. Montero <rsmontero@opennebula.org>
This commit is contained in:
parent
c4c6cc9998
commit
7ba1bbe633
@ -142,6 +142,9 @@ public:
|
||||
void trigger_update_conf_success(int vid);
|
||||
void trigger_update_conf_failure(int vid);
|
||||
|
||||
void trigger_resize_success(int vid);
|
||||
void trigger_resize_failure(int vid);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// External Actions, triggered by user requests
|
||||
// -------------------------------------------------------------------------
|
||||
|
@ -170,6 +170,7 @@ enum class VMManagerMessages : unsigned short int
|
||||
UPDATESG,
|
||||
DRIVER_CANCEL,
|
||||
LOG,
|
||||
RESIZE,
|
||||
ENUM_MAX
|
||||
};
|
||||
|
||||
|
@ -135,7 +135,8 @@ public:
|
||||
DISK_RESIZE = 62,
|
||||
DISK_RESIZE_POWEROFF = 63,
|
||||
DISK_RESIZE_UNDEPLOYED = 64,
|
||||
HOTPLUG_NIC_POWEROFF = 65
|
||||
HOTPLUG_NIC_POWEROFF = 65,
|
||||
HOTPLUG_RESIZE = 66
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1018,7 +1019,20 @@ public:
|
||||
* @param memory
|
||||
* @param vcpu
|
||||
*/
|
||||
int resize(float cpu, long int memory, unsigned int vcpu, std::string& error);
|
||||
int resize(float cpu, long int memory, unsigned int vcpu, std::string& error);
|
||||
|
||||
/**
|
||||
* Store old values of resize parameters, to be able to revert in case of failure
|
||||
* @param cpu - old cpu value
|
||||
* @param memory - old memory value
|
||||
* @param vcpu - old vcpu value
|
||||
*/
|
||||
void store_resize(float cpu, long int memory, unsigned int vcpu);
|
||||
|
||||
/**
|
||||
* Clear resize parameters
|
||||
*/
|
||||
void reset_resize();
|
||||
|
||||
/**
|
||||
* Parse TOPOLOGY and NUMA_NODE
|
||||
|
@ -111,6 +111,21 @@ public:
|
||||
return vmd->is_cold_nic_attach();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get live_resize capability from driver
|
||||
*/
|
||||
bool is_live_resize(const std::string& name)
|
||||
{
|
||||
const VirtualMachineManagerDriver * vmd = get(name);
|
||||
|
||||
if ( vmd == nullptr )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return vmd->is_live_resize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to a Virtual Machine Manager driver. The driver is
|
||||
* searched by its name.
|
||||
@ -269,6 +284,11 @@ private:
|
||||
*/
|
||||
void _driver_cancel(std::unique_ptr<vm_msg_t> msg);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void _resize(std::unique_ptr<vm_msg_t> msg);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ -495,6 +515,13 @@ public:
|
||||
* @param vid the id of the VM.
|
||||
*/
|
||||
void trigger_update_conf(int vid);
|
||||
|
||||
/**
|
||||
* Update VM context
|
||||
*
|
||||
* @param vid the id of the VM.
|
||||
*/
|
||||
void trigger_resize(int vid);
|
||||
};
|
||||
|
||||
#endif /*VIRTUAL_MACHINE_MANAGER_H*/
|
||||
|
@ -99,6 +99,14 @@ public:
|
||||
return cold_nic_attach;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if hotplug vcpu and memory supported
|
||||
*/
|
||||
bool is_live_resize() const
|
||||
{
|
||||
return live_resize;
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Gets a configuration attr from driver configuration file (single
|
||||
@ -263,6 +271,11 @@ private:
|
||||
*/
|
||||
bool cold_nic_attach;
|
||||
|
||||
/**
|
||||
* Set to true if hypervisor supports hotplug vcpu and memory
|
||||
*/
|
||||
bool live_resize;
|
||||
|
||||
/**
|
||||
* Sends a deploy request to the MAD: "DEPLOY ID XML_DRV_MSG"
|
||||
* @param oid the virtual machine id.
|
||||
|
@ -1116,6 +1116,7 @@ VMM_EXEC_KVM_SCRIPTS="src/vmm_mad/remotes/kvm/cancel \
|
||||
src/vmm_mad/remotes/kvm/shutdown \
|
||||
src/vmm_mad/remotes/kvm/reconfigure \
|
||||
src/vmm_mad/remotes/kvm/prereconfigure \
|
||||
src/vmm_mad/remotes/kvm/resize \
|
||||
src/vmm_mad/remotes/kvm/resize_disk"
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
@ -162,6 +162,7 @@ VM_MAD = [
|
||||
DEFAULT = \"vmm_exec/vmm_exec_kvm.conf\",
|
||||
TYPE = \"kvm\",
|
||||
KEEP_SNAPSHOTS = \"no\",
|
||||
LIVE_RESIZE = \"no\",
|
||||
IMPORTED_VMS_ACTIONS = \"terminate, terminate-hard, hold, release, suspend,
|
||||
resume, delete, reboot, reboot-hard, resched, unresched, disk-attach,
|
||||
disk-detach, nic-attach, nic-detach, snapshot-create, snapshot-delete\"
|
||||
|
@ -345,6 +345,14 @@
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
<xs:element name="LIVE_RESIZE" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:pattern value="[yY][eE][sS]" />
|
||||
<xs:pattern value="[nN][oO]" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
@ -389,6 +389,8 @@ IM_MAD = [
|
||||
# keep_snapshots: do not remove snapshots on power on/off cycles and live
|
||||
# migrations if the hypervisor supports that.
|
||||
#
|
||||
# live_resize: [yes|no] Hypervisor supports hotplug VCPU and memory
|
||||
#
|
||||
# imported_vms_actions : comma-separated list of actions supported
|
||||
# for imported vms. The available actions are:
|
||||
# migrate
|
||||
@ -443,6 +445,7 @@ VM_MAD = [
|
||||
DEFAULT = "vmm_exec/vmm_exec_kvm.conf",
|
||||
TYPE = "kvm",
|
||||
KEEP_SNAPSHOTS = "yes",
|
||||
LIVE_RESIZE = "yes",
|
||||
IMPORTED_VMS_ACTIONS = "terminate, terminate-hard, hold, release, suspend,
|
||||
resume, delete, reboot, reboot-hard, resched, unresched, disk-attach,
|
||||
disk-detach, nic-attach, nic-detach, snapshot-create, snapshot-delete"
|
||||
|
@ -221,6 +221,7 @@ module OneGate
|
||||
DISK_RESIZE_POWEROFF
|
||||
DISK_RESIZE_UNDEPLOYED
|
||||
HOTPLUG_NIC_POWEROFF
|
||||
HOTPLUG_RESIZE
|
||||
}
|
||||
|
||||
SHORT_VM_STATES={
|
||||
@ -302,7 +303,8 @@ module OneGate
|
||||
"DISK_RESIZE" => "drsz",
|
||||
"DISK_RESIZE_POWEROFF" => "drsz",
|
||||
"DISK_RESIZE_UNDEPLOYED" => "drsz",
|
||||
"HOTPLUG_NIC_POWEROFF" => "hotp"
|
||||
"HOTPLUG_NIC_POWEROFF" => "hotp",
|
||||
"HOTPLUG_RESIZE" => "hotp"
|
||||
}
|
||||
|
||||
def self.state_to_str(id, lcm_id)
|
||||
|
@ -596,7 +596,8 @@ func (d *Driver) GetState() (state.State, error) {
|
||||
"HOTPLUG_NIC",
|
||||
"HOTPLUG_SAVEAS",
|
||||
"DISK_SNAPSHOT",
|
||||
"DISK_SNAPSHOT_DELETE":
|
||||
"DISK_SNAPSHOT_DELETE",
|
||||
"HOTPLUG_RESIZE":
|
||||
|
||||
return state.Running, nil
|
||||
|
||||
|
@ -1102,6 +1102,15 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose,
|
||||
tm->trigger_epilog_delete(vm);
|
||||
break;
|
||||
|
||||
case VirtualMachine::HOTPLUG_RESIZE:
|
||||
vm->reset_resize();
|
||||
|
||||
vm->set_running_etime(the_time);
|
||||
|
||||
vmm->trigger_driver_cancel(vid);
|
||||
vmm->trigger_cleanup(vid, false);
|
||||
break;
|
||||
|
||||
case VirtualMachine::DISK_SNAPSHOT_POWEROFF:
|
||||
case VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF:
|
||||
case VirtualMachine::DISK_SNAPSHOT_DELETE_POWEROFF:
|
||||
@ -1446,6 +1455,17 @@ void LifeCycleManager::recover(VirtualMachine * vm, bool success,
|
||||
}
|
||||
break;
|
||||
|
||||
case VirtualMachine::HOTPLUG_RESIZE:
|
||||
if (success)
|
||||
{
|
||||
trigger_resize_success(vim);
|
||||
}
|
||||
else
|
||||
{
|
||||
trigger_resize_failure(vim);
|
||||
}
|
||||
break;
|
||||
|
||||
case VirtualMachine::DISK_SNAPSHOT_POWEROFF:
|
||||
case VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF:
|
||||
case VirtualMachine::DISK_SNAPSHOT_DELETE_POWEROFF:
|
||||
@ -1681,6 +1701,7 @@ void LifeCycleManager::retry(VirtualMachine * vm)
|
||||
case VirtualMachine::HOTPLUG_SAVEAS_SUSPENDED:
|
||||
case VirtualMachine::HOTPLUG_PROLOG_POWEROFF:
|
||||
case VirtualMachine::HOTPLUG_EPILOG_POWEROFF:
|
||||
case VirtualMachine::HOTPLUG_RESIZE:
|
||||
case VirtualMachine::DISK_SNAPSHOT_POWEROFF:
|
||||
case VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF:
|
||||
case VirtualMachine::DISK_SNAPSHOT_DELETE_POWEROFF:
|
||||
@ -1817,6 +1838,7 @@ void LifeCycleManager::trigger_updatesg(int sgid)
|
||||
case VirtualMachine::HOTPLUG:
|
||||
case VirtualMachine::HOTPLUG_SNAPSHOT:
|
||||
case VirtualMachine::HOTPLUG_SAVEAS:
|
||||
case VirtualMachine::HOTPLUG_RESIZE:
|
||||
case VirtualMachine::DISK_SNAPSHOT:
|
||||
case VirtualMachine::DISK_SNAPSHOT_DELETE:
|
||||
case VirtualMachine::DISK_RESIZE:
|
||||
|
@ -2387,3 +2387,118 @@ void LifeCycleManager::trigger_update_conf_failure(int vid)
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void LifeCycleManager::trigger_resize_success(int vid)
|
||||
{
|
||||
trigger([this, vid] {
|
||||
if ( auto vm = vmpool->get(vid) )
|
||||
{
|
||||
VirtualMachine::LcmState state = vm->get_lcm_state();
|
||||
|
||||
if (state == VirtualMachine::HOTPLUG_RESIZE)
|
||||
{
|
||||
vm->set_state(VirtualMachine::RUNNING);
|
||||
vm->log("LCM", Log::INFO, "VM resize operation completed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
vm->log("LCM", Log::ERROR, "hotplug_resize_success, VM in a wrong state");
|
||||
return;
|
||||
}
|
||||
|
||||
vm->reset_resize();
|
||||
|
||||
vmpool->update(vm.get());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void LifeCycleManager::trigger_resize_failure(int vid)
|
||||
{
|
||||
trigger([this, vid] {
|
||||
Template deltas;
|
||||
HostShareCapacity sr, sr_orig;
|
||||
int vm_uid, vm_gid, hid;
|
||||
|
||||
if ( auto vm = vmpool->get(vid) )
|
||||
{
|
||||
VirtualMachine::LcmState state = vm->get_lcm_state();
|
||||
|
||||
if (state == VirtualMachine::HOTPLUG_RESIZE)
|
||||
{
|
||||
vm->set_state(VirtualMachine::RUNNING);
|
||||
vm->log("LCM", Log::INFO,
|
||||
"VM hotplug resize operation fails");
|
||||
}
|
||||
else
|
||||
{
|
||||
vm->log("LCM", Log::ERROR,
|
||||
"hotplug resize fails, VM in a wrong state");
|
||||
return;
|
||||
}
|
||||
|
||||
hid = vm->get_hid();
|
||||
|
||||
vm->get_capacity(sr);
|
||||
|
||||
auto vattr = vm->get_template_attribute("RESIZE");
|
||||
|
||||
if (vattr)
|
||||
{
|
||||
vm_uid = vm->get_uid();
|
||||
vm_gid = vm->get_gid();
|
||||
|
||||
string error;
|
||||
float ocpu, ncpu;
|
||||
long omem, nmem;
|
||||
unsigned int ovcpu, nvcpu;
|
||||
|
||||
vm->get_template_attribute("MEMORY", nmem);
|
||||
vm->get_template_attribute("CPU", ncpu);
|
||||
vm->get_template_attribute("VCPU", nvcpu);
|
||||
|
||||
vattr->vector_value("CPU", ocpu);
|
||||
vattr->vector_value("VCPU", ovcpu);
|
||||
vattr->vector_value("MEMORY", omem);
|
||||
|
||||
deltas.add("MEMORY", nmem - omem);
|
||||
deltas.add("CPU", ncpu - ocpu);
|
||||
deltas.add("VMS", 0);
|
||||
|
||||
vm->resize(ocpu, omem, ovcpu, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
NebulaLog::error("LCM",
|
||||
"HOTPLUG_RESIZE failure, unable to revert VM and quotas");
|
||||
}
|
||||
|
||||
vm->get_capacity(sr_orig);
|
||||
|
||||
vm->reset_resize();
|
||||
|
||||
vmpool->update(vm.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Revert host capacity
|
||||
if (auto host = hpool->get(hid))
|
||||
{
|
||||
host->del_capacity(sr);
|
||||
|
||||
host->add_capacity(sr_orig);
|
||||
|
||||
hpool->update(host.get());
|
||||
}
|
||||
|
||||
// Quota rollback
|
||||
Quotas::quota_del(Quotas::VM, vm_uid, vm_gid, &deltas);
|
||||
});
|
||||
}
|
||||
|
@ -52,7 +52,8 @@ class VirtualMachineDriver < OpenNebulaDriver
|
||||
:disk_snapshot_create => "DISKSNAPSHOTCREATE",
|
||||
:resize_disk => "RESIZEDISK",
|
||||
:update_sg => "UPDATESG",
|
||||
:update_conf => "UPDATECONF"
|
||||
:update_conf => "UPDATECONF",
|
||||
:resize => "RESIZE"
|
||||
}
|
||||
|
||||
POLL_ATTRIBUTE = OpenNebula::VirtualMachine::Driver::POLL_ATTRIBUTE
|
||||
@ -98,6 +99,7 @@ class VirtualMachineDriver < OpenNebulaDriver
|
||||
register_action(ACTION[:resize_disk].to_sym, method("resize_disk"))
|
||||
register_action(ACTION[:update_sg].to_sym, method("update_sg"))
|
||||
register_action(ACTION[:update_conf].to_sym, method("update_conf"))
|
||||
register_action(ACTION[:resize].to_sym, method("resize"))
|
||||
end
|
||||
|
||||
# Decodes the encoded XML driver message received from the core
|
||||
@ -227,6 +229,11 @@ class VirtualMachineDriver < OpenNebulaDriver
|
||||
send_message(ACTION[:update_conf],RESULT[:failure],id,error)
|
||||
end
|
||||
|
||||
def resize(id, drv_message)
|
||||
error = "Action not implemented by driver #{self.class}"
|
||||
send_message(ACTION[:resize],RESULT[:failure],id,error)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Interface to handle the pending events from the ActionManager Interface
|
||||
|
@ -154,7 +154,8 @@ public class VirtualMachine extends PoolElement{
|
||||
"DISK_RESIZE",
|
||||
"DISK_RESIZE_POWEROFF",
|
||||
"DISK_RESIZE_UNDEPLOYED",
|
||||
"HOTPLUG_NIC_POWEROFF"
|
||||
"HOTPLUG_NIC_POWEROFF",
|
||||
"HOTPLUG_RESIZE"
|
||||
};
|
||||
|
||||
private static final String[] SHORT_LCM_STATES =
|
||||
@ -224,7 +225,8 @@ public class VirtualMachine extends PoolElement{
|
||||
"drsz", // DISK_RESIZE
|
||||
"drsz", // DISK_RESIZE_POWEROFF
|
||||
"drsz", // DISK_RESIZE_UNDEPLOYED
|
||||
"hotp" // HOTPLUG_NIC_POWEROFF
|
||||
"hotp", // HOTPLUG_NIC_POWEROFF
|
||||
"hotp" // HOTPLUG_RESIZE
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -154,7 +154,8 @@ LCM_STATE = IntEnum('LCM_STATE', '''
|
||||
DISK_RESIZE
|
||||
DISK_RESIZE_POWEROFF
|
||||
DISK_RESIZE_UNDEPLOYED
|
||||
HOTPLUG_NIC_POWEROFF''', start=0)
|
||||
HOTPLUG_NIC_POWEROFF
|
||||
HOTPLUG_RESIZE''', start=0)
|
||||
|
||||
MARKETPLACEAPP_STATES = IntEnum('MARKETPLACEAPP_STATES', '''INIT READY LOCKED
|
||||
ERROR DISABLED''', start=0)
|
||||
|
@ -124,6 +124,7 @@ module OpenNebula
|
||||
DISK_RESIZE_POWEROFF
|
||||
DISK_RESIZE_UNDEPLOYED
|
||||
HOTPLUG_NIC_POWEROFF
|
||||
HOTPLUG_RESIZE
|
||||
}
|
||||
|
||||
SHORT_VM_STATES={
|
||||
@ -205,7 +206,8 @@ module OpenNebula
|
||||
"DISK_RESIZE" => "drsz",
|
||||
"DISK_RESIZE_POWEROFF" => "drsz",
|
||||
"DISK_RESIZE_UNDEPLOYED" => "drsz",
|
||||
"HOTPLUG_NIC_POWEROFF" => "hotp"
|
||||
"HOTPLUG_NIC_POWEROFF" => "hotp",
|
||||
"HOTPLUG_RESIZE" => "hotp"
|
||||
}
|
||||
|
||||
HISTORY_ACTION=%w{none migrate live-migrate shutdown shutdown-hard
|
||||
|
@ -139,6 +139,7 @@ const EString<VMManagerMessages> vm_msg_t::_type_str({
|
||||
{"UPDATESG", VMManagerMessages::UPDATESG},
|
||||
{"DRIVER_CANCEL", VMManagerMessages::DRIVER_CANCEL},
|
||||
{"LOG", VMManagerMessages::LOG},
|
||||
{"RESIZE", VMManagerMessages::RESIZE},
|
||||
});
|
||||
|
||||
template<>
|
||||
|
@ -1927,7 +1927,9 @@ static int test_set_capacity(VirtualMachine * vm, float cpu, long mem, int vcpu,
|
||||
|
||||
int rc;
|
||||
|
||||
if ( vm->get_state() == VirtualMachine::POWEROFF )
|
||||
if ( vm->get_state() == VirtualMachine::POWEROFF ||
|
||||
(vm->get_state() == VirtualMachine::ACTIVE &&
|
||||
vm->get_lcm_state() == VirtualMachine::RUNNING))
|
||||
{
|
||||
HostShareCapacity sr;
|
||||
|
||||
@ -2130,10 +2132,59 @@ void VirtualMachineResize::request_execute(xmlrpc_c::paramList const& paramList,
|
||||
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);
|
||||
|
||||
auto vmm = Nebula::instance().get_vmm();
|
||||
|
||||
vmm->trigger_resize(id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case VirtualMachine::STOPPED:
|
||||
case VirtualMachine::DONE:
|
||||
case VirtualMachine::SUSPENDED:
|
||||
case VirtualMachine::ACTIVE:
|
||||
rc = -1;
|
||||
att.resp_msg = "Cannot resize a VM in state " + vm->state_str();
|
||||
break;
|
||||
|
@ -98,6 +98,7 @@ VNC_STATES = [
|
||||
#63, #DISK_RESIZE_POWEROFF
|
||||
#64 #DISK_RESIZE_UNDEPLOYED
|
||||
#65 #HOTPLUG_NIC_POWEROFF
|
||||
#66 #HOTPLUG_RESIZE
|
||||
]
|
||||
|
||||
class OpenNebulaVNC
|
||||
|
@ -137,7 +137,8 @@ define(function(require) {
|
||||
"DISK_RESIZE",
|
||||
"DISK_RESIZE_POWEROFF",
|
||||
"DISK_RESIZE_UNDEPLOYED",
|
||||
"HOTPLUG_NIC_POWEROFF"
|
||||
"HOTPLUG_NIC_POWEROFF",
|
||||
"HOTPLUG_RESIZE"
|
||||
];
|
||||
|
||||
var LCM_STATES_CLASSES = [
|
||||
@ -275,7 +276,8 @@ define(function(require) {
|
||||
DISK_RESIZE : 62,
|
||||
DISK_RESIZE_POWEROFF : 63,
|
||||
DISK_RESIZE_UNDEPLOYED : 64,
|
||||
HOTPLUG_NIC_POWEROFF : 65
|
||||
HOTPLUG_NIC_POWEROFF : 65,
|
||||
HOTPLUG_RESIZE : 66
|
||||
};
|
||||
|
||||
var SHORT_LCM_STATES_STR = [
|
||||
@ -344,7 +346,8 @@ define(function(require) {
|
||||
Locale.tr("DISK_RSZ"), // DISK_RESIZE
|
||||
Locale.tr("DISK_RSZ"), // DISK_RESIZE_POWEROFF
|
||||
Locale.tr("DISK_RSZ"), // DISK_RESIZE_UNDEPLOYED
|
||||
Locale.tr("HOTPLUG") // HOTPLUG_NIC_POWEROFF
|
||||
Locale.tr("HOTPLUG"), // HOTPLUG_NIC_POWEROFF
|
||||
Locale.tr("HOTPLUG") // HOTPLUG_RESIZE
|
||||
];
|
||||
|
||||
var VNC_STATES = [
|
||||
|
@ -908,6 +908,7 @@ define(function(require) {
|
||||
case OpenNebulaVM.LCM_STATES.DISK_RESIZE:
|
||||
case OpenNebulaVM.LCM_STATES.DISK_RESIZE_POWEROFF:
|
||||
case OpenNebulaVM.LCM_STATES.DISK_RESIZE_UNDEPLOYED:
|
||||
case OpenNebulaVM.LCM_STATES.HOTPLUG_RESIZE:
|
||||
state_color = "running";
|
||||
state_str = Locale.tr("RUNNING");
|
||||
break;
|
||||
|
@ -124,6 +124,7 @@ define(function(require) {
|
||||
LCM_STATE_ACTIONS[ OpenNebulaVM.LCM_STATES.DISK_RESIZE ] = [];
|
||||
LCM_STATE_ACTIONS[ OpenNebulaVM.LCM_STATES.DISK_RESIZE_POWEROFF ] = [];
|
||||
LCM_STATE_ACTIONS[ OpenNebulaVM.LCM_STATES.DISK_RESIZE_UNDEPLOYED ] = [];
|
||||
LCM_STATE_ACTIONS[ OpenNebulaVM.LCM_STATES.HOTPLUG_RESIZE ] = [];
|
||||
|
||||
return {
|
||||
'disableAllStateActions': disableAllStateActions,
|
||||
|
@ -290,6 +290,8 @@ int VirtualMachine::lcm_state_from_str(string& st, LcmState& state)
|
||||
state = DISK_RESIZE_UNDEPLOYED;
|
||||
} else if ( st == "HOTPLUG_NIC_POWEROFF" ) {
|
||||
state = HOTPLUG_NIC_POWEROFF;
|
||||
} else if ( st == "HOTPLUG_RESIZE" ) {
|
||||
state = HOTPLUG_RESIZE;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
@ -429,6 +431,8 @@ string& VirtualMachine::lcm_state_to_str(string& st, LcmState state)
|
||||
st = "DISK_RESIZE_UNDEPLOYED"; break;
|
||||
case HOTPLUG_NIC_POWEROFF:
|
||||
st = "HOTPLUG_NIC_POWEROFF"; break;
|
||||
case HOTPLUG_RESIZE:
|
||||
st = "HOTPLUG_RESIZE"; break;
|
||||
}
|
||||
|
||||
return st;
|
||||
@ -740,6 +744,7 @@ int VirtualMachine::insert(SqlDB * db, string& error_str)
|
||||
|
||||
string value;
|
||||
long int ivalue;
|
||||
long int memory;
|
||||
float fvalue;
|
||||
set<int> cluster_ids;
|
||||
set<int> datastore_ids;
|
||||
@ -812,13 +817,26 @@ int VirtualMachine::insert(SqlDB * db, string& error_str)
|
||||
// ------------------------------------------------------------------------
|
||||
// Check for CPU, VCPU, MEMORY and TOPOLOGY attributes
|
||||
// ------------------------------------------------------------------------
|
||||
if ( user_obj_template->get("MEMORY", ivalue) == false || ivalue <= 0 )
|
||||
if ( user_obj_template->get("MEMORY", memory) == false || memory <= 0 )
|
||||
{
|
||||
goto error_memory;
|
||||
}
|
||||
|
||||
user_obj_template->erase("MEMORY");
|
||||
obj_template->add("MEMORY", ivalue);
|
||||
obj_template->add("MEMORY", memory);
|
||||
|
||||
// Check optional MEMORY_MAX and MEMORY_SLOTS attribute
|
||||
if ( user_obj_template->get("MEMORY_MAX", ivalue) && ivalue > 0 )
|
||||
{
|
||||
user_obj_template->erase("MEMORY_MAX");
|
||||
obj_template->add("MEMORY_MAX", ivalue);
|
||||
}
|
||||
|
||||
if ( user_obj_template->get("MEMORY_SLOTS", ivalue) && ivalue > 0 )
|
||||
{
|
||||
user_obj_template->erase("MEMORY_SLOTS");
|
||||
obj_template->add("MEMORY_SLOTS", ivalue);
|
||||
}
|
||||
|
||||
if ( user_obj_template->get("CPU", fvalue) == false || fvalue <= 0 )
|
||||
{
|
||||
@ -843,6 +861,13 @@ int VirtualMachine::insert(SqlDB * db, string& error_str)
|
||||
obj_template->add("VCPU", ivalue);
|
||||
}
|
||||
|
||||
// Check optional VCPU_MAX attribute
|
||||
if ( user_obj_template->get("VCPU_MAX", ivalue) && ivalue > 0 )
|
||||
{
|
||||
user_obj_template->erase("VCPU_MAX");
|
||||
obj_template->add("VCPU_MAX", ivalue);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Check the cost attributes
|
||||
// ------------------------------------------------------------------------
|
||||
@ -1989,6 +2014,28 @@ int VirtualMachine::resize(float cpu, long int memory, unsigned int vcpu,
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void VirtualMachine::store_resize(float cpu, long int memory, unsigned int vcpu)
|
||||
{
|
||||
auto vattr = new VectorAttribute("RESIZE");
|
||||
vattr->replace("CPU", cpu);
|
||||
vattr->replace("VCPU", vcpu);
|
||||
vattr->replace("MEMORY", memory);
|
||||
|
||||
obj_template->erase("RESIZE");
|
||||
obj_template->set(vattr);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void VirtualMachine::reset_resize()
|
||||
{
|
||||
obj_template->erase("RESIZE");
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
bool VirtualMachine::is_imported() const
|
||||
{
|
||||
bool imported = false;
|
||||
|
@ -413,8 +413,10 @@ int LibVirtDriver::deployment_description_kvm(
|
||||
int num;
|
||||
|
||||
string vcpu;
|
||||
string vcpu_max;
|
||||
float cpu;
|
||||
int memory;
|
||||
int memory_max;
|
||||
|
||||
string emulator_path = "";
|
||||
|
||||
@ -617,8 +619,19 @@ int LibVirtDriver::deployment_description_kvm(
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
get_attribute(vm, host, cluster, "VCPU", vcpu);
|
||||
get_attribute(vm, host, cluster, "VCPU_MAX", vcpu_max);
|
||||
|
||||
if (!vcpu.empty())
|
||||
if (vcpu.empty())
|
||||
{
|
||||
vcpu = vcpu_max;
|
||||
}
|
||||
|
||||
if (!vcpu_max.empty())
|
||||
{
|
||||
file << "\t<vcpu current=" << one_util::escape_xml_attr(vcpu) << ">"
|
||||
<< one_util::escape_xml(vcpu_max) << "</vcpu>" << endl;
|
||||
}
|
||||
else if (!vcpu.empty())
|
||||
{
|
||||
file << "\t<vcpu>" << one_util::escape_xml(vcpu) << "</vcpu>" << endl;
|
||||
}
|
||||
@ -648,6 +661,18 @@ int LibVirtDriver::deployment_description_kvm(
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool has_memory_max = vm->get_template_attribute("MEMORY_MAX", memory_max);
|
||||
has_memory_max = has_memory_max && memory < memory_max;
|
||||
|
||||
if (!topology && has_memory_max)
|
||||
{
|
||||
int slots = 0;
|
||||
get_attribute(vm, host, cluster, "MEMORY_SLOTS", slots);
|
||||
|
||||
file << "\t<maxMemory slots='" << slots
|
||||
<< "'>" << memory_max * 1024 << "</maxMemory>" << endl;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// OS and boot options
|
||||
// ------------------------------------------------------------------------
|
||||
@ -722,7 +747,7 @@ int LibVirtDriver::deployment_description_kvm(
|
||||
cpu_mode = "custom";
|
||||
}
|
||||
|
||||
if ( !cpu_model.empty() || topology != 0 )
|
||||
if ( !cpu_model.empty() || topology != 0 || has_memory_max )
|
||||
{
|
||||
file << "\t<cpu";
|
||||
|
||||
@ -741,6 +766,19 @@ int LibVirtDriver::deployment_description_kvm(
|
||||
file << ">\n";
|
||||
}
|
||||
|
||||
if (nodes.empty() && has_memory_max)
|
||||
{
|
||||
int cpus = to_i(vcpu) - 1;
|
||||
if (cpus < 0)
|
||||
{
|
||||
cpus = 0;
|
||||
}
|
||||
|
||||
file << "\t\t<numa>\n\t\t\t<cell id='0' cpus='0-" << cpus
|
||||
<< "' memory=" << one_util::escape_xml_attr(memory * 1024)
|
||||
<< " unit='KiB'/>\n\t\t</numa>" << endl;
|
||||
}
|
||||
|
||||
vtopol(file, topology, nodes, numa_tune, mbacking);
|
||||
|
||||
file << "\t</cpu>\n";
|
||||
|
@ -27,8 +27,6 @@
|
||||
|
||||
#include "Nebula.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/* ************************************************************************** */
|
||||
@ -121,6 +119,9 @@ int VirtualMachineManager::start()
|
||||
register_action(VMManagerMessages::DRIVER_CANCEL,
|
||||
bind(&VirtualMachineManager::_driver_cancel, this, _1));
|
||||
|
||||
register_action(VMManagerMessages::RESIZE,
|
||||
bind(&VirtualMachineManager::_resize, this, _1));
|
||||
|
||||
register_action(VMManagerMessages::LOG,
|
||||
&VirtualMachineManager::_log);
|
||||
|
||||
@ -2330,6 +2331,71 @@ int VirtualMachineManager::updatesg(VirtualMachine * vm, int sgid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void VirtualMachineManager::trigger_resize(int vid)
|
||||
{
|
||||
trigger([this, vid] {
|
||||
const VirtualMachineManagerDriver * vmd;
|
||||
|
||||
string vm_tmpl;
|
||||
string drv_msg;
|
||||
ostringstream os;
|
||||
|
||||
// Get the VM from the pool
|
||||
auto vm = vmpool->get(vid);
|
||||
|
||||
if (vm == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!vm->hasHistory())
|
||||
{
|
||||
goto error_history;
|
||||
}
|
||||
|
||||
// Get the driver for this VM
|
||||
vmd = get(vm->get_vmm_mad());
|
||||
|
||||
if ( vmd == nullptr )
|
||||
{
|
||||
goto error_driver;
|
||||
}
|
||||
|
||||
// Invoke driver method
|
||||
drv_msg = format_message(
|
||||
vm->get_hostname(),
|
||||
"",
|
||||
vm->get_deploy_id(),
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
vm->to_xml(vm_tmpl),
|
||||
vm->get_ds_id(),
|
||||
-1);
|
||||
|
||||
vmd->write_drv(VMManagerMessages::RESIZE, vid, drv_msg);
|
||||
|
||||
return;
|
||||
|
||||
error_history:
|
||||
os << "trigger_resize, VM has no history";
|
||||
goto error_common;
|
||||
|
||||
error_driver:
|
||||
os << "trigger_resize, error getting driver " << vm->get_vmm_mad();
|
||||
|
||||
error_common:
|
||||
vm->log("VMM", Log::ERROR, os);
|
||||
return;
|
||||
});
|
||||
}
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* MAD Loading */
|
||||
/* ************************************************************************** */
|
||||
|
@ -42,7 +42,8 @@ VirtualMachineManagerDriver::VirtualMachineManagerDriver(
|
||||
driver_conf(true),
|
||||
keep_snapshots(false),
|
||||
ds_live_migration(false),
|
||||
cold_nic_attach(false)
|
||||
cold_nic_attach(false),
|
||||
live_resize(false)
|
||||
{
|
||||
char * error_msg = nullptr;
|
||||
const char * cfile;
|
||||
@ -111,6 +112,8 @@ VirtualMachineManagerDriver::VirtualMachineManagerDriver(
|
||||
// -------------------------------------------------------------------------
|
||||
driver_conf.get("COLD_NIC_ATTACH", cold_nic_attach);
|
||||
|
||||
driver_conf.get("LIVE_RESIZE", live_resize);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Parse IMPORTED_VMS_ACTIONS string and init the action set
|
||||
// -------------------------------------------------------------------------
|
||||
|
@ -807,6 +807,37 @@ void VirtualMachineManager::_driver_cancel(unique_ptr<vm_msg_t> msg)
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void VirtualMachineManager::_resize(unique_ptr<vm_msg_t> msg)
|
||||
{
|
||||
log_message(msg.get());
|
||||
|
||||
int id = msg->oid();
|
||||
auto lcm = Nebula::instance().get_lcm();
|
||||
|
||||
if (!check_vm_state(id, msg.get()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg->status() == "SUCCESS" )
|
||||
{
|
||||
if ( auto vm = vmpool->get_ro(id) )
|
||||
{
|
||||
vm->log("VMM", Log::INFO, "VM hotplug resize successful");
|
||||
|
||||
lcm->trigger_resize_success(id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error(id, msg->payload(), "Error resizing VM");
|
||||
|
||||
lcm->trigger_resize_failure(id);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void VirtualMachineManager::_log(unique_ptr<vm_msg_t> msg)
|
||||
{
|
||||
NebulaLog::log("VMM", log_type(msg->status()[0]), msg->payload());
|
||||
|
@ -199,6 +199,12 @@ class DummyDriver < VirtualMachineDriver
|
||||
send_message(ACTION[:resize_disk], result, id)
|
||||
end
|
||||
|
||||
def resize(id, drv_message)
|
||||
result = retrieve_result("resize")
|
||||
|
||||
send_message(ACTION[:resize], result, id)
|
||||
end
|
||||
|
||||
def poll(id, drv_message)
|
||||
result = retrieve_result("poll")
|
||||
|
||||
|
@ -1261,6 +1261,23 @@ class ExecDriver < VirtualMachineDriver
|
||||
action.run(steps, sg_id)
|
||||
end
|
||||
|
||||
#
|
||||
# RESIZE action
|
||||
#
|
||||
def resize(id, drv_message)
|
||||
xml_data = decode(drv_message)
|
||||
|
||||
host = xml_data.elements['HOST'].text
|
||||
deploy_id = xml_data.elements['DEPLOY_ID'].text
|
||||
|
||||
do_action("#{deploy_id}",
|
||||
id,
|
||||
host,
|
||||
ACTION[:resize],
|
||||
:script_name => 'resize',
|
||||
:stdin => xml_data.to_s)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ensure_xpath(xml_data, id, action, xpath)
|
||||
|
@ -20,6 +20,7 @@
|
||||
# - emulator
|
||||
# - os [kernel,initrd,boot,root,kernel_cmd,arch,machine,sd_disk_bus]
|
||||
# - vcpu
|
||||
# - memory_slots: number of memory slots for hotplug memory
|
||||
# - features [acpi, pae, apic, hyperv, localtime, guest_agent, virtio_scsi_queues]
|
||||
# - cpu_model [model]
|
||||
# - disk [driver, cache, io, discard, total_bytes_sec, total_iops_sec, read_bytes_sec, write_bytes_sec, read_iops_sec, write_iops_sec]
|
||||
@ -43,6 +44,8 @@ DISK = [ driver = "raw" , cache = "none"]
|
||||
|
||||
HYPERV_OPTIONS="<relaxed state='on'/><vapic state='on'/><spinlocks state='on' retries='4096'/>"
|
||||
|
||||
MEMORY_SLOTS = 16
|
||||
|
||||
SPICE_OPTIONS="
|
||||
<video>
|
||||
<model type='vga' heads='1'/>
|
||||
|
84
src/vmm_mad/remotes/kvm/resize
Executable file
84
src/vmm_mad/remotes/kvm/resize
Executable file
@ -0,0 +1,84 @@
|
||||
#!/bin/bash
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# 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. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
DRIVER_PATH=$(dirname $0)
|
||||
DOMAIN=$1
|
||||
|
||||
# Exit if no stdin data is available
|
||||
if [ -t 0 ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Read data from stdin data. Extracting the VCPU and MEMORY
|
||||
XPATH="${DRIVER_PATH}/../../datastore/xpath.rb --stdin"
|
||||
|
||||
unset i XPATH_ELEMENTS
|
||||
|
||||
while IFS= read -r -d '' element; do
|
||||
XPATH_ELEMENTS[i++]="$element"
|
||||
done < <($XPATH /VMM_DRIVER_ACTION_DATA/VM/TEMPLATE/VCPU \
|
||||
/VMM_DRIVER_ACTION_DATA/VM/TEMPLATE/MEMORY \
|
||||
/VMM_DRIVER_ACTION_DATA/VM/TEMPLATE/RESIZE/VCPU \
|
||||
/VMM_DRIVER_ACTION_DATA/VM/TEMPLATE/RESIZE/MEMORY)
|
||||
|
||||
unset i
|
||||
|
||||
VCPU="${XPATH_ELEMENTS[i++]}"
|
||||
MEM="${XPATH_ELEMENTS[i++]}"
|
||||
VCPU_OLD="${XPATH_ELEMENTS[i++]}"
|
||||
MEM_OLD="${XPATH_ELEMENTS[i++]}"
|
||||
|
||||
source $(dirname $0)/../../etc/vmm/kvm/kvmrc
|
||||
source $(dirname $0)/../../scripts_common.sh
|
||||
|
||||
# Resize mem
|
||||
if [ ! -z "$MEM" -a "$MEM" -ne "$MEM_OLD" ]; then
|
||||
# Extract node id from virsh dumpxml
|
||||
XML_INFO=$(virsh --connect ${LIBVIRT_URI} dumpxml ${DOMAIN})
|
||||
IFS= read -r -d '' NODE_ID < <(echo "$XML_INFO" | $XPATH --subtree /domain/cpu/numa/cell/@id)
|
||||
|
||||
MEM_DIFF=$(expr $MEM - $MEM_OLD)
|
||||
|
||||
case $MEM_DIFF in
|
||||
-*)
|
||||
ACTION="detach-device"
|
||||
MEM_DIFF=${MEM_DIFF#-}
|
||||
;;
|
||||
*)
|
||||
ACTION="attach-device"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Create tmp file with memory device specification
|
||||
TMPFILE=$(mktemp /tmp/resize.XXXXXX)
|
||||
echo -e "<memory model='dimm'>\n\t<target>\n\
|
||||
<size unit='MiB'>$MEM_DIFF</size>\n\
|
||||
<node>$NODE_ID</node>\n\t</target>\n</memory>" >$TMPFILE
|
||||
|
||||
# Add memory to VM
|
||||
exec_and_log "virsh --connect ${LIBVIRT_URI} ${ACTION} ${DOMAIN} ${TMPFILE} --live"
|
||||
|
||||
# Cleanup
|
||||
rm $TMPFILE
|
||||
fi
|
||||
|
||||
# Resize VCPU
|
||||
if [ ! -z "$VCPU" -a "$VCPU" -ne "$VCPU_OLD" ]; then
|
||||
exec_and_log "virsh --connect ${LIBVIRT_URI} setvcpus ${DOMAIN} ${VCPU} --live --hotpluggable" \
|
||||
"Failed to resize VCPU to ${VCPU} on ${DOMAIN}"
|
||||
fi
|
Loading…
Reference in New Issue
Block a user