1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-01-11 05:17:41 +03:00

Feature #4215: Attach nic action updates the context cdrom

This commit is contained in:
Carlos Martín 2016-01-25 16:20:12 +01:00
parent d66fe153e5
commit 3cee54afc9
13 changed files with 489 additions and 31 deletions

View File

@ -74,6 +74,8 @@ public:
ATTACH_NIC_FAILURE,/**< Sent by the VMM when an attach nic action fails */
DETACH_NIC_SUCCESS,/**< Sent by the VMM when a detach nic action succeeds */
DETACH_NIC_FAILURE,/**< Sent by the VMM when a detach nic action fails */
UPDATE_CONTEXT_SUCCESS,/**< Sent by the VMM when an update context action succeeds */
UPDATE_CONTEXT_FAILURE,/**< Sent by the VMM when an update context action fails */
CLEANUP_SUCCESS, /**< Sent by the VMM when a cleanup action succeeds */
CLEANUP_FAILURE, /**< Sent by the VMM when a cleanup action fails */
SAVEAS_SUCCESS, /**< Sent by the VMM when saveas succeeds */
@ -271,6 +273,10 @@ private:
void detach_nic_failure_action(int vid);
void update_context_success_action(int vid);
void update_context_failure_action(int vid);
void cleanup_callback_action(int vid);
void snapshot_create_success(int vid);

View File

@ -123,6 +123,26 @@ public:
ostream& xfr,
ostringstream& error);
/**
* Inserts a context command in the xfs stream
*
* @param vm The VM
* @param token_password Owner user's token password
* @param system_tm_mad The Transfer Manager for the system datastore
* @param opennebula_hostname The front-end hostname
* @param xfr Stream where the transfer command will be written
* @param error Error reason, if any
*
* @return 0 on success
*/
int prolog_context_command(
VirtualMachine * vm,
const string& token_password,
string& system_tm_mad,
string& opennebula_hostname,
ostream& xfr,
ostringstream& error);
/**
* Inserts a transfer command in the xfs stream
*

View File

@ -166,7 +166,9 @@ public:
DISK_SNAPSHOT_DELETE_SUSPENDED = 56,
DISK_SNAPSHOT = 57,
DISK_SNAPSHOT_REVERT = 58,
DISK_SNAPSHOT_DELETE = 59
DISK_SNAPSHOT_DELETE = 59,
HOTPLUG_CONTEXT = 60,
HOTPLUG_CONTEXT_FAILURE = 61
};
static int lcm_state_from_str(string& st, LcmState& state)
@ -231,6 +233,8 @@ public:
else if ( st == "DISK_SNAPSHOT") { state = DISK_SNAPSHOT; }
else if ( st == "DISK_SNAPSHOT_REVERT") { state = DISK_SNAPSHOT_REVERT; }
else if ( st == "DISK_SNAPSHOT_DELETE") { state = DISK_SNAPSHOT_DELETE; }
else if ( st == "HOTPLUG_CONTEXT") { state = HOTPLUG_CONTEXT; }
else if ( st == "HOTPLUG_CONTEXT_FAILURE") { state = HOTPLUG_CONTEXT_FAILURE; }
else {return -1;}
return 0;
@ -298,6 +302,8 @@ public:
case DISK_SNAPSHOT: st = "DISK_SNAPSHOT"; break;
case DISK_SNAPSHOT_REVERT: st = "DISK_SNAPSHOT_REVERT"; break;
case DISK_SNAPSHOT_DELETE: st = "DISK_SNAPSHOT_DELETE"; break;
case HOTPLUG_CONTEXT: st = "HOTPLUG_CONTEXT"; break;
case HOTPLUG_CONTEXT_FAILURE: st = "HOTPLUG_CONTEXT_FAILURE"; break;
}
return st;
@ -1318,6 +1324,8 @@ public:
*/
const VectorAttribute* get_disk(int disk_id) const;
const VectorAttribute* get_context_disk() const;
const VectorAttribute* get_nic(int nic_id) const;
// ------------------------------------------------------------------------
@ -1354,7 +1362,7 @@ public:
* @param token_password Password to encrypt the token, if it is set
* @return -1 in case of error, 0 if the VM has no context, 1 on success
*/
int generate_context(string &files, int &disk_id, string& token_password);
int generate_context(string &files, int &disk_id, const string& token_password);
int replace_context_attribute(const string& name, const string& value);
@ -1605,6 +1613,13 @@ public:
*/
int set_attach_nic(int nic_id);
/**
* Updates the network part of the context
* @param error_str Returns the error reason, if any
* @return 0 on success
*/
int update_context(string& error_str);
// ------------------------------------------------------------------------
// Snapshot related functions
// ------------------------------------------------------------------------

View File

@ -68,7 +68,8 @@ public:
SNAPSHOT_REVERT,
SNAPSHOT_DELETE,
DISK_SNAPSHOT_CREATE,
DISK_SNAPSHOT_REVERT
DISK_SNAPSHOT_REVERT,
UPDATE_CONTEXT
};
/**
@ -374,6 +375,13 @@ private:
void detach_action(
int vid);
/**
* Updates the context cdrom
* @param vid the id of the VM.
*/
void update_context_action(
int vid);
/**
* Attaches a new NIC to a VM. The VM must have a NIC with the
* attribute ATTACH = YES

View File

@ -314,6 +314,18 @@ private:
write_drv("DETACHDISK", oid, drv_msg);
}
/**
* Sends an update-context request to the MAD: "UPDATECONTEXT ID XML_DRV_MSG"
* @param oid the virtual machine id.
* @param drv_msg xml data for the mad operation
*/
void update_context (
const int oid,
const string& drv_msg) const
{
write_drv("UPDATECONTEXT", oid, drv_msg);
}
/**
* Sends an attach NIC request to the MAD: "ATTACHNIC ID XML_DRV_MSG"
* @param oid the virtual machine id.

View File

@ -1443,6 +1443,7 @@ int DispatchManager::attach_nic(
int uid;
int oid;
int rc;
string tmp_error;
set<int> vm_sgs;
@ -1579,6 +1580,8 @@ int DispatchManager::attach_nic(
vm->set_attach_nic(nic, sg_rules);
vm->update_context(tmp_error);
if (vm->get_lcm_state() == VirtualMachine::HOTPLUG_NIC)
{
time_t the_time = time(0);
@ -1631,6 +1634,7 @@ int DispatchManager::detach_nic(
string& error_str)
{
ostringstream oss;
string tmp_error;
VirtualMachine * vm = vmpool->get(vid, true);
@ -1682,6 +1686,8 @@ int DispatchManager::detach_nic(
return -1;
}
vm->update_context(tmp_error);
if (vm->get_state() == VirtualMachine::ACTIVE &&
vm->get_lcm_state() == VirtualMachine::RUNNING )
{
@ -1724,6 +1730,8 @@ int DispatchManager::detach_nic(
}
else
{
vmpool->update(vm);
vm->unlock();
vmpool->delete_attach_nic(vid);

View File

@ -937,6 +937,8 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose, int& imag
case VirtualMachine::SHUTDOWN_POWEROFF:
case VirtualMachine::SHUTDOWN_UNDEPLOY:
case VirtualMachine::HOTPLUG_SNAPSHOT:
case VirtualMachine::HOTPLUG_CONTEXT:
case VirtualMachine::HOTPLUG_CONTEXT_FAILURE:
vm->set_running_etime(the_time);
vmpool->update_history(vm);
@ -1284,6 +1286,18 @@ void LifeCycleManager::recover(VirtualMachine * vm, bool success)
}
break;
case VirtualMachine::HOTPLUG_CONTEXT:
case VirtualMachine::HOTPLUG_CONTEXT_FAILURE:
if (success)
{
lcm_action = LifeCycleManager::UPDATE_CONTEXT_SUCCESS;
}
else
{
lcm_action = LifeCycleManager::UPDATE_CONTEXT_FAILURE;
}
break;
//This is for all snapshot actions (create, delete & revert)
case VirtualMachine::HOTPLUG_SNAPSHOT:
lcm_action = LifeCycleManager::SNAPSHOT_CREATE_FAILURE;
@ -1496,6 +1510,18 @@ void LifeCycleManager::retry(VirtualMachine * vm)
tm->trigger(TransferManager::EPILOG_STOP,vid);
break;
case VirtualMachine::HOTPLUG_CONTEXT:
vmm->trigger(VirtualMachineManager::UPDATE_CONTEXT, vid);
break;
case VirtualMachine::HOTPLUG_CONTEXT_FAILURE:
vm->set_state(VirtualMachine::HOTPLUG_CONTEXT);
vmpool->update(vm);
vmm->trigger(VirtualMachineManager::UPDATE_CONTEXT, vid);
break;
case VirtualMachine::LCM_INIT:
case VirtualMachine::CLEANUP_RESUBMIT:
case VirtualMachine::CLEANUP_DELETE:

View File

@ -191,6 +191,14 @@ void LifeCycleManager::trigger(Actions action, int _vid)
aname = "DETACH_NIC_FAILURE";
break;
case UPDATE_CONTEXT_SUCCESS:
aname = "UPDATE_CONTEXT_SUCCESS";
break;
case UPDATE_CONTEXT_FAILURE:
aname = "UPDATE_CONTEXT_FAILURE";
break;
case CLEANUP_SUCCESS:
aname = "CLEANUP_SUCCESS";
break;
@ -424,6 +432,14 @@ void LifeCycleManager::do_action(const string &action, void * arg)
{
detach_nic_failure_action(vid);
}
else if (action == "UPDATE_CONTEXT_SUCCESS")
{
update_context_success_action(vid);
}
else if (action == "UPDATE_CONTEXT_FAILURE")
{
update_context_failure_action(vid);
}
else if (action == "CLEANUP_SUCCESS")
{
cleanup_callback_action(vid);

View File

@ -1615,6 +1615,64 @@ void LifeCycleManager::detach_nic_failure_action(int vid)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void LifeCycleManager::update_context_success_action(int vid)
{
VirtualMachine * vm;
vm = vmpool->get(vid,true);
if ( vm == 0 )
{
return;
}
if ( vm->get_lcm_state() == VirtualMachine::HOTPLUG_CONTEXT ||
vm->get_lcm_state() == VirtualMachine::HOTPLUG_CONTEXT_FAILURE ) //recover success
{
vm->set_state(VirtualMachine::RUNNING);
vmpool->update(vm);
}
else
{
vm->log("LCM",Log::ERROR,"update_context_success_action, VM in a wrong state");
}
vm->unlock();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void LifeCycleManager::update_context_failure_action(int vid)
{
VirtualMachine * vm;
vm = vmpool->get(vid,true);
if ( vm == 0 )
{
return;
}
if ( vm->get_lcm_state() == VirtualMachine::HOTPLUG_CONTEXT ||
vm->get_lcm_state() == VirtualMachine::HOTPLUG_CONTEXT_FAILURE ) //recover failure
{
vm->set_state(VirtualMachine::HOTPLUG_CONTEXT_FAILURE);
vmpool->update(vm);
}
else
{
vm->log("LCM",Log::ERROR,"update_context_failure_action, VM in a wrong state");
}
vm->unlock();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void LifeCycleManager::saveas_success_action(int vid)
{
int image_id;

View File

@ -607,6 +607,50 @@ static string prolog_os_transfer_commands(
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int TransferManager::prolog_context_command(
VirtualMachine * vm,
const string& token_password,
string& vm_tm_mad,
string& opennebula_hostname,
ostream& xfr,
ostringstream& os)
{
string files;
int context_result;
int disk_id;
context_result = vm->generate_context(files, disk_id, token_password);
if ( context_result == -1 )
{
return -1;
}
if ( context_result )
{
//CONTEXT tm_mad files hostname:remote_system_dir/disk.i vmid dsid(=0)
xfr << "CONTEXT "
<< vm_tm_mad << " "
<< vm->get_context_file() << " ";
if (!files.empty())
{
xfr << files << " ";
}
xfr << vm->get_hostname() << ":"
<< vm->get_remote_system_dir() << "/disk." << disk_id << " "
<< vm->get_oid() << " "
<< vm->get_ds_id()
<< endl;
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void TransferManager::prolog_action(int vid)
{
ofstream xfr;
@ -628,9 +672,6 @@ void TransferManager::prolog_action(int vid)
vector<const Attribute *> attrs;
int num;
int disk_id;
int context_result;
string token_password;
@ -771,32 +812,18 @@ void TransferManager::prolog_action(int vid)
// Generate context file
// -------------------------------------------------------------------------
context_result = vm->generate_context(files, disk_id, token_password);
rc = prolog_context_command( vm,
token_password,
vm_tm_mad,
opennebula_hostname,
xfr,
os);
if ( context_result == -1 )
if ( rc == -1 )
{
goto error_context;
}
if ( context_result )
{
//CONTEXT tm_mad files hostname:remote_system_dir/disk.i vmid dsid(=0)
xfr << "CONTEXT "
<< vm_tm_mad << " "
<< vm->get_context_file() << " ";
if (!files.empty())
{
xfr << files << " ";
}
xfr << vm->get_hostname() << ":"
<< vm->get_remote_system_dir() << "/disk." << disk_id << " "
<< vm->get_oid() << " "
<< vm->get_ds_id()
<< endl;
}
xfr.close();
tm_md->transfer(vid,xfr_name);

View File

@ -1136,6 +1136,16 @@ error_cleanup:
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachine::update_context(string& error_str)
{
// TODO: context update may need to be limited to network attributes,
// but for now the full context is parsed again
return parse_context(error_str);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachine::parse_pci(string& error_str)
{
VectorAttribute * pci;
@ -3308,7 +3318,7 @@ bool VirtualMachine::is_vrouter_action_supported(History::VMAction action)
/* -------------------------------------------------------------------------- */
int VirtualMachine::generate_context(string &files, int &disk_id,
string& token_password)
const string& token_password)
{
ofstream file;
string files_ds;
@ -3507,6 +3517,32 @@ const VectorAttribute* VirtualMachine::get_disk(int disk_id) const
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
const VectorAttribute* VirtualMachine::get_context_disk() const
{
vector<const Attribute *> array_context;
const VectorAttribute * context;
int num;
num = obj_template->get("CONTEXT", array_context);
if ( num != 1 )
{
return 0;
}
context = dynamic_cast<const VectorAttribute *>(array_context[0]);
if ( context == 0 )
{
return 0;
}
return context;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
const VectorAttribute* VirtualMachine::get_nic(int nic_id) const
{
int num_nics;

View File

@ -207,6 +207,10 @@ void VirtualMachineManager::trigger(Actions action, int _vid)
aname = "DISK_SNAPSHOT_REVERT";
break;
case UPDATE_CONTEXT:
aname = "UPDATE_CONTEXT";
break;
default:
delete vid;
return;
@ -330,6 +334,10 @@ void VirtualMachineManager::do_action(const string &action, void * arg)
{
disk_snapshot_revert_action(vid);
}
else if (action == "UPDATE_CONTEXT")
{
update_context_action(vid);
}
else if (action == ACTION_TIMER)
{
timer_action();
@ -1905,6 +1913,150 @@ error_common:
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineManager::update_context_action(
int vid)
{
VirtualMachine * vm;
const VirtualMachineManagerDriver * vmd;
ostringstream os, error_os;
string vm_tmpl;
string* drv_msg;
string vm_tm_mad;
string opennebula_hostname;
string prolog_cmd;
string epilog_cmd;
string disk_path;
const VectorAttribute * disk;
int disk_id;
int rc;
Nebula& nd = Nebula::instance();
TransferManager * tm = nd.get_tm();
// Get the VM from the pool
vm = vmpool->get(vid,true);
if (vm == 0)
{
return;
}
if (!vm->hasHistory())
{
goto error_history;
}
// Get the driver for this VM
vmd = get(vm->get_vmm_mad());
if ( vmd == 0 )
{
goto error_driver;
}
disk = vm->get_context_disk();
if ( disk == 0 )
{
goto error_disk;
}
vm_tm_mad = vm->get_tm_mad();
opennebula_hostname = nd.get_nebula_hostname();
rc = tm->prolog_context_command(
vm,
"", // TODO token_password
vm_tm_mad,
opennebula_hostname,
os,
error_os);
prolog_cmd = os.str();
if ( prolog_cmd.empty() || rc != 0 )
{
goto error_no_tm_command;
}
os.str("");
tm->epilog_transfer_command(vm, disk, os);
epilog_cmd = os.str();
os.str("");
disk->vector_value("DISK_ID", disk_id);
os << vm->get_remote_system_dir() << "/disk." << disk_id;
disk_path = os.str();
// Invoke driver method
drv_msg = format_message(
vm->get_hostname(),
vm->get_vnm_mad(),
"",
"",
vm->get_deploy_id(),
"",
"",
"",
prolog_cmd,
epilog_cmd,
disk_path,
vm->to_xml(vm_tmpl),
vm->get_ds_id());
vmd->update_context(vid, *drv_msg);
delete drv_msg;
vm->unlock();
return;
error_disk:
os.str("");
os << "update_context_action, could not find context disk";
goto error_common;
error_history:
os.str("");
os << "update_context_action, VM has no history";
goto error_common;
error_driver:
os.str("");
os << "update_context_action, error getting driver " << vm->get_vmm_mad();
goto error_common;
error_no_tm_command:
os.str("");
os << "Cannot set context disk to update it for VM: " << error_os.str();
goto error_common;
error_common:
Nebula &ne = Nebula::instance();
LifeCycleManager * lcm = ne.get_lcm();
lcm->trigger(LifeCycleManager::UPDATE_CONTEXT_FAILURE, vid);
vm->log("VMM", Log::ERROR, os);
vm->unlock();
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineManager::snapshot_create_action(int vid)
{
VirtualMachine * vm;
@ -2382,6 +2534,18 @@ void VirtualMachineManager::attach_nic_action(
string vm_tmpl;
string* drv_msg;
string vm_tm_mad;
string opennebula_hostname;
string prolog_cmd;
string epilog_cmd;
string disk_path;
const VectorAttribute * disk;
int disk_id;
int rc;
Nebula& nd = Nebula::instance();
TransferManager * tm = nd.get_tm();
// Get the VM from the pool
vm = vmpool->get(vid,true);
@ -2404,6 +2568,44 @@ void VirtualMachineManager::attach_nic_action(
goto error_driver;
}
disk = vm->get_context_disk();
if ( disk != 0 )
{
vm_tm_mad = vm->get_tm_mad();
opennebula_hostname = nd.get_nebula_hostname();
rc = tm->prolog_context_command(
vm,
"", // TODO token_password
vm_tm_mad,
opennebula_hostname,
os,
error_os);
prolog_cmd = os.str();
if ( prolog_cmd.empty() || rc != 0 )
{
goto error_no_tm_command;
}
os.str("");
tm->epilog_transfer_command(vm, disk, os);
epilog_cmd = os.str();
os.str("");
disk->vector_value("DISK_ID", disk_id);
os << vm->get_remote_system_dir() << "/disk." << disk_id;
disk_path = os.str();
}
// Invoke driver method
drv_msg = format_message(
vm->get_hostname(),
@ -2414,9 +2616,9 @@ void VirtualMachineManager::attach_nic_action(
"",
"",
"",
"",
"",
"",
prolog_cmd,
epilog_cmd,
disk_path,
vm->to_xml(vm_tmpl),
vm->get_ds_id());
@ -2438,6 +2640,11 @@ error_driver:
os << "attach_nic_action, error getting driver " << vm->get_vmm_mad();
goto error_common;
error_no_tm_command:
os.str("");
os << "Cannot set context disk to update it for VM: " << error_os.str();
goto error_common;
error_common:
Nebula &ne = Nebula::instance();
LifeCycleManager * lcm = ne.get_lcm();

View File

@ -524,6 +524,25 @@ void VirtualMachineManagerDriver::protocol(const string& message) const
lcm->trigger(LifeCycleManager::DETACH_NIC_FAILURE, id);
}
}
else if ( action == "UPDATECONTEXT" )
{
Nebula &ne = Nebula::instance();
LifeCycleManager *lcm = ne.get_lcm();
if ( result == "SUCCESS" )
{
vm->log("VMM", Log::INFO, "VM CONTEXT Successfully updated.");
lcm->trigger(LifeCycleManager::UPDATE_CONTEXT_SUCCESS, id);
}
else
{
log_error(vm, os, is, "Error updating VM CONTEXT");
vmpool->update(vm);
lcm->trigger(LifeCycleManager::UPDATE_CONTEXT_FAILURE, id);
}
}
else if ( action == "SNAPSHOTCREATE" )
{
Nebula &ne = Nebula::instance();