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

B #5131: Track VNC allocation across migration

(cherry picked from commit dd6a7f4cd6baad55d57c140c9d1ba057e5d1a9fe)
This commit is contained in:
Ruben S. Montero 2020-10-16 12:33:20 +02:00
parent e8da3aea37
commit 26498959bc
No known key found for this signature in database
GPG Key ID: A0CEA6FA880A1D87
6 changed files with 136 additions and 5 deletions

View File

@ -452,8 +452,8 @@ public:
void replace(const std::string& name, const std::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 std::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

@ -325,6 +325,8 @@ void LifeCycleManager::trigger_migrate(int vid, const RequestAttributes& ra,
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

@ -62,6 +62,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);
@ -95,6 +97,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);
@ -275,6 +279,8 @@ void LifeCycleManager::trigger_deploy_success(int vid)
vm->delete_snapshots();
}
vm->release_previous_vnc_port();
vmpool->update(vm.get());
}
else if ( vm->get_lcm_state() == VirtualMachine::BOOT ||
@ -353,6 +359,8 @@ void LifeCycleManager::trigger_deploy_failure(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

@ -705,6 +705,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;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
@ -1015,6 +1061,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;
@ -1211,6 +1258,7 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
if (auto host = nd.get_hpool()->get_ro(c_hid))
{
c_is_public_cloud = host->is_public_cloud();
c_cluster_id = host->get_cluster_id();
}
else
{
@ -1221,7 +1269,6 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
return;
}
if (!cluster_ids.empty() && cluster_ids.count(cluster_id) == 0)
{
ostringstream oss;
@ -1301,7 +1348,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, ',') << "]";
@ -1311,6 +1359,20 @@ 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.get(), cluster_id, live) == -1 )
{
att.resp_msg = "No free VNC port available in the new cluster";
failure_response(ACTION, att);
return;
}
}
// ------------------------------------------------------------------------
// Add a new history record and update volatile DISK attributes
// ------------------------------------------------------------------------
@ -1334,7 +1396,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.get(), att);
}

View File

@ -3623,3 +3623,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");
};