1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-22 18:50:08 +03:00

B #5131: Track VNC allocation across migration

This commit is contained in:
Ruben S. Montero 2020-10-16 12:33:20 +02:00
parent 2879ebe17a
commit dd6a7f4cd6
No known key found for this signature in database
GPG Key ID: A0CEA6FA880A1D87
6 changed files with 138 additions and 4 deletions

View File

@ -459,8 +459,8 @@ public:
void replace(const string& name, const string& value);
/**
* Removes given the vector attribute
* @param name of the vector attribute
* Removes the given attribute from the vector
* @param name of the attribute
*/
void remove(const string& name);

View File

@ -847,6 +847,19 @@ public:
previous_history->req_id = rid;
};
/**
* Release the previous VNC port when a VM is migrated to another cluster
* (GRAPHICS/PREVIOUS_PORT present)
*/
void release_previous_vnc_port();
/**
* Frees current PORT from **current** cluster and sets it to PREVIOUS_PORT
* (which is allocated in previous cluster). This function is called when
* the migration fails.
*/
void rollback_previous_vnc_port();
// ------------------------------------------------------------------------
// Template & Object Representation
// ------------------------------------------------------------------------

View File

@ -334,6 +334,8 @@ void LifeCycleManager::migrate_action(const LCMAction& la)
if ( vm->get_hid() != vm->get_previous_hid() )
{
hpool->del_capacity(vm->get_previous_hid(), sr);
vm->release_previous_vnc_port();
}
vm->set_stime(the_time);

View File

@ -54,6 +54,8 @@ void LifeCycleManager::start_prolog_migrate(VirtualMachine* vm)
if ( vm->get_hid() != vm->get_previous_hid() )
{
hpool->del_capacity(vm->get_previous_hid(), sr);
vm->release_previous_vnc_port();
}
vmpool->update(vm);
@ -84,6 +86,8 @@ void LifeCycleManager::revert_migrate_after_failure(VirtualMachine* vm)
if ( vm->get_hid() != vm->get_previous_hid() )
{
hpool->del_capacity(vm->get_hid(), sr);
vm->rollback_previous_vnc_port();
}
vm->set_previous_etime(the_time);
@ -261,6 +265,8 @@ void LifeCycleManager::deploy_success_action(int vid)
hpool->del_capacity(vm->get_previous_hid(), sr);
vm->release_previous_vnc_port();
vm->set_state(VirtualMachine::RUNNING);
if ( !vmm->is_keep_snapshots(vm->get_vmm_mad()) )
@ -349,6 +355,8 @@ void LifeCycleManager::deploy_failure_action(int vid)
hpool->del_capacity(vm->get_hid(), sr);
vm->rollback_previous_vnc_port();
// --- Add new record by copying the previous one
vm->cp_previous_history();

View File

@ -746,6 +746,52 @@ int set_vnc_port(VirtualMachine *vm, int cluster_id, RequestAttributes& att)
return rc;
}
static int set_migrate_vnc_port(VirtualMachine *vm, int cluster_id, bool keep)
{
ClusterPool * cpool = Nebula::instance().get_clpool();
VectorAttribute * graphics = vm->get_template_attribute("GRAPHICS");
unsigned int previous_port;
unsigned int port;
int rc;
// Do not update VM if no GRAPHICS or GRAPHICS/PORT defined
if (graphics == nullptr)
{
return 0;
}
if (graphics->vector_value("PORT", previous_port) != 0)
{
return 0;
}
//live migrations need to keep VNC port
if (keep)
{
rc = cpool->set_vnc_port(cluster_id, previous_port);
port = previous_port;
}
else
{
rc = cpool->get_vnc_port(cluster_id, vm->get_oid(), port);
}
if ( rc != 0 )
{
return -1;
}
graphics->replace("PREVIOUS_PORT", previous_port);
graphics->replace("PORT", port);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
@ -1067,6 +1113,7 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
PoolObjectAuth * auth_ds_perms;
int c_hid;
int c_cluster_id;
int c_ds_id;
string c_tm_mad, tm_mad;
bool c_is_public_cloud;
@ -1286,6 +1333,7 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
}
c_is_public_cloud = host->is_public_cloud();
c_cluster_id = host->get_cluster_id();
host->unlock();
@ -1384,7 +1432,8 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
{
ostringstream oss;
oss << "Cannot migrate VM [" << id << "] to host [" << hid << "] and system datastore [" << ds_id << "]. Host is in cluster ["
oss << "Cannot migrate VM [" << id << "] to host [" << hid
<< "] and system datastore [" << ds_id << "]. Host is in cluster ["
<< cluster_id << "], and the datastore is in cluster ["
<< one_util::join(ds_cluster_ids, ',') << "]";
@ -1396,6 +1445,22 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
return;
}
// -------------------------------------------------------------------------
// Request a new VNC port in the new cluster
// -------------------------------------------------------------------------
if ( c_cluster_id != cluster_id )
{
if ( set_migrate_vnc_port(vm, cluster_id, live) == -1 )
{
att.resp_msg = "No free VNC port available in the new cluster";
failure_response(ACTION, att);
vm->unlock();
return;
}
}
// ------------------------------------------------------------------------
// Add a new history record and update volatile DISK attributes
// ------------------------------------------------------------------------
@ -1420,7 +1485,7 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
// Migrate the VM
// ------------------------------------------------------------------------
if (live == true && vm->get_lcm_state() == VirtualMachine::RUNNING )
if (live && vm->get_lcm_state() == VirtualMachine::RUNNING )
{
dm->live_migrate(vm, att);
}

View File

@ -3657,3 +3657,49 @@ void VirtualMachine::get_quota_template(VirtualMachineTemplate& quota_tmpl,
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachine::release_previous_vnc_port()
{
ClusterPool * cpool = Nebula::instance().get_clpool();
VectorAttribute * graphics = get_template_attribute("GRAPHICS");
unsigned int previous_port;
if (graphics == nullptr ||
graphics->vector_value("PREVIOUS_PORT", previous_port) != 0)
{
return;
}
cpool->release_vnc_port(previous_history->cid, previous_port);
graphics->remove("PREVIOUS_PORT");
};
/* -------------------------------------------------------------------------- */
void VirtualMachine::rollback_previous_vnc_port()
{
ClusterPool * cpool = Nebula::instance().get_clpool();
VectorAttribute * graphics = get_template_attribute("GRAPHICS");
unsigned int previous_port;
unsigned int port;
if (graphics == nullptr ||
graphics->vector_value("PREVIOUS_PORT", previous_port) != 0)
{
return;
}
if ( graphics->vector_value("PORT", port) == 0 )
{
cpool->release_vnc_port(history->cid, port);
}
graphics->replace("PORT", previous_port);
graphics->remove("PREVIOUS_PORT");
};