1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-02-26 09:57:23 +03:00

Feature #1223: New VMM attach action

This commit is contained in:
Carlos Martín 2012-06-13 18:42:42 +02:00
parent 73b6457d0e
commit cc13c07317
10 changed files with 543 additions and 1 deletions

View File

@ -317,6 +317,12 @@ public:
replace(name, oss.str());
}
/**
* Removes given the vector attribute
* @param name of the vector attribute
*/
void remove(const string& name);
/**
* Returns the attribute type
*/

View File

@ -58,6 +58,8 @@ public:
PROLOG_FAILURE, /**< Sent by the TM when the prolog phase fails */
EPILOG_SUCCESS, /**< Sent by the TM when the epilog phase succeeds */
EPILOG_FAILURE, /**< Sent by the TM when the epilog phase fails */
ATTACH_SUCCESS, /**< Sent by the VMM when an attach action succeeds */
ATTACH_FAILURE, /**< Sent by the VMM when an attach action fails */
DEPLOY, /**< Sent by the DM to deploy a VM on a host */
SUSPEND, /**< Sent by the DM to suspend an running VM */
RESTORE, /**< Sent by the DM to restore a suspended VM */

View File

@ -737,6 +737,37 @@ public:
static void set_auth_request(int uid,
AuthRequest& ar,
VirtualMachineTemplate *tmpl);
// ------------------------------------------------------------------------
// Hotplug related functions
// ------------------------------------------------------------------------
/**
* Attaches a new disk. It will acquire the Image used, if any, and add the
* disk to the VM template. The VM must be updated in the DB afterwards.
*
* @param tmpl Template containing a single DISK vector attribute. The
* caller must delete this template
* @param error_str Returns the error reason, if any
*
* @return 0 on success
*/
int attach_disk(VirtualMachineTemplate * tmpl, string& error_str);
/**
* Returns the disk that is waiting for an attachment action
*
* @return the disk waiting for an attachment action, or 0
*/
VectorAttribute* get_attach_disk();
/**
* Cleans the ATTACH = YES attribute from the disk
*
* @return 0 on success
*/
int end_attach_operation(int disk_id);
private:
// -------------------------------------------------------------------------

View File

@ -56,7 +56,8 @@ public:
POLL,
TIMER,
DRIVER_CANCEL,
FINALIZE
FINALIZE,
ATTACH
};
/**
@ -199,6 +200,9 @@ private:
* @param domain domain id as returned by the hypervisor
* @param dfile deployment file to boot the VM
* @param cfile checkpoint file to save the VM
* @param disk_id Disk to attach/detach, if any
* @param tm_command Transfer Manager command to attach/detach, if any
* @param disk_target_path Path of the disk to attach, if any
* @param tmpl the VM information in XML
*/
string * format_message(
@ -210,6 +214,9 @@ private:
const string& ldfile,
const string& rdfile,
const string& cfile,
int disk_id,
const string& tm_command,
const string& disk_target_path,
const string& tmpl);
/**
@ -290,6 +297,14 @@ private:
*/
void timer_action();
/**
* Attaches a new disk to a VM. The VM must have a disk with the
* attribute ATTACH = YES
* @param vid the id of the VM.
*/
void attach_action(
int vid);
/**
* This function cancels the current driver operation
*/

View File

@ -232,6 +232,18 @@ private:
}
/**
* Sends an attach request to the MAD: "ATTACH ID XML_DRV_MSG"
* @param oid the virtual machine id.
* @param drv_msg xml data for the mad operation
*/
void attach (
const int oid,
const string& drv_msg) const
{
write_drv("ATTACH", oid, drv_msg);
}
private:
void write_drv(const char * aname, const int oid, const string& msg) const

View File

@ -185,6 +185,21 @@ void VectorAttribute::replace(const string& name, const string& value)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VectorAttribute::remove(const string& name)
{
map<string,string>::iterator it;
it = attribute_value.find(name);
if ( it != attribute_value.end() )
{
attribute_value.erase(it);
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string VectorAttribute::vector_value(const char *name) const
{
map<string,string>::const_iterator it;

View File

@ -129,6 +129,14 @@ void LifeCycleManager::trigger(Actions action, int _vid)
aname = "EPILOG_FAILURE";
break;
case ATTACH_SUCCESS:
aname = "ATTACH_SUCCESS";
break;
case ATTACH_FAILURE:
aname = "ATTACH_FAILURE";
break;
case DEPLOY:
aname = "DEPLOY";
break;
@ -262,6 +270,16 @@ void LifeCycleManager::do_action(const string &action, void * arg)
{
epilog_failure_action(vid);
}
else if (action == "ATTACH_SUCCESS")
{
// TODO
// attach_success_action(vid);
}
else if (action == "ATTACH_FAILURE")
{
// TODO
// attach_failure_action(vid);
}
else if (action == "DEPLOY")
{
deploy_action(vid);

View File

@ -922,6 +922,7 @@ void VirtualMachine::get_requirements (int& cpu, int& memory, int& disk)
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
@ -1108,6 +1109,241 @@ error_common:
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
// TODO: this method requires the VM to be locked, and then it locks the Image
// to acquire. Check if this can be troublesome
int VirtualMachine::attach_disk(VirtualMachineTemplate * tmpl, string& error_str)
{
int num_disks, rc;
vector<Attribute *> disks;
ImagePool * ipool;
VectorAttribute * disk;
VectorAttribute * new_disk;
vector<int> acquired_images;
int new_disk_id;
int image_id;
string dev_prefix;
string target;
queue<pair <string, VectorAttribute *> > disks_queue;
set<string> used_targets;
ostringstream oss;
Image::ImageType img_type;
Nebula& nd = Nebula::instance();
ipool = nd.get_ipool();
// -------------------------------------------------------------------------
// Get the DISK attribute from the template
// -------------------------------------------------------------------------
num_disks = obj_template->get("DISK", disks);
if ( num_disks != 1 )
{
goto error_no_disk;
}
new_disk = new VectorAttribute( *(dynamic_cast<VectorAttribute * >(disks[0])) );
// -------------------------------------------------------------------------
// See if there is a CONTEXT cdrom, and get the target it is using
// -------------------------------------------------------------------------
num_disks = obj_template->get("CONTEXT", disks);
if ( num_disks > 0 )
{
disk = dynamic_cast<VectorAttribute * >(disks[0]);
if ( disk != 0 )
{
target = disk->vector_value("TARGET");
if ( !target.empty() )
{
used_targets.insert(target);
}
}
}
// -------------------------------------------------------------------------
// Check the used targets
// -------------------------------------------------------------------------
disks.clear();
num_disks = obj_template->get("DISK", disks);
if ( num_disks >= 20 )
{
goto error_max_disks;
}
for(int i=0; i<num_disks; i++)
{
disk = dynamic_cast<VectorAttribute * >(disks[i]);
if ( disk == 0 )
{
continue;
}
target = disk->vector_value("TARGET");
if ( !target.empty() )
{
used_targets.insert(target);
}
}
// -------------------------------------------------------------------------
// Acquire the new disk image
// -------------------------------------------------------------------------
// num_disks +1 because the context is not a DISK, but it takes the
// ds/<vm_id>/disk.num_disks file
new_disk_id = num_disks + 1;
rc = ipool->disk_attribute(new_disk,
new_disk_id,
img_type,
dev_prefix,
uid,
image_id,
error_str);
if ( rc == 0 )
{
acquired_images.push_back(image_id);
target = new_disk->vector_value("TARGET");
if ( !target.empty() )
{
if ( used_targets.insert(target).second == false )
{
goto error_duplicated_target;
}
}
else
{
disks_queue.push( make_pair(dev_prefix, new_disk) );
}
}
else
{
goto error_common;
}
assign_disk_targets(disks_queue, used_targets);
// -------------------------------------------------------------------------
// Add the disk to the VM template
// -------------------------------------------------------------------------
new_disk->replace("ATTACH", "YES");
obj_template->set(new_disk);
return 0;
error_no_disk:
error_str = "The template must contain one DISK attribute";
return -1;
error_max_disks:
error_str = "Exceeded the maximum number of disks (20)";
return -1;
error_duplicated_target:
oss << "Two disks have defined the same target " << target;
error_str = oss.str();
error_common:
ImageManager * imagem = nd.get_imagem();
vector<int>::iterator it;
for ( it=acquired_images.begin() ; it < acquired_images.end(); it++ )
{
imagem->release_image(*it, false);
}
return -1;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
VectorAttribute* VirtualMachine::get_attach_disk()
{
int num_disks;
vector<Attribute *> disks;
VectorAttribute * disk;
ostringstream oss;
// -------------------------------------------------------------------------
// Set DISK attributes & Targets
// -------------------------------------------------------------------------
num_disks = obj_template->get("DISK", disks);
for(int i=0; i<num_disks; i++)
{
disk = dynamic_cast<VectorAttribute * >(disks[i]);
if ( disk == 0 )
{
continue;
}
if ( disk->vector_value("ATTACH") == "YES" )
{
return disk;
}
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachine::end_attach_operation(int disk_id)
{
int num_disks;
vector<Attribute *> disks;
VectorAttribute * disk;
int value;
ostringstream oss;
num_disks = obj_template->get("DISK", disks);
for(int i=0; i<num_disks; i++)
{
disk = dynamic_cast<VectorAttribute * >(disks[i]);
if ( disk == 0 )
{
continue;
}
disk->vector_value("DISK_ID", value);
if ( value == disk_id )
{
disk->remove("ATTACH");
return 0;
}
}
return -1;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachine::release_disk_images()
{
int iid;

View File

@ -162,6 +162,10 @@ void VirtualMachineManager::trigger(Actions action, int _vid)
aname = ACTION_FINALIZE;
break;
case ATTACH:
aname = "ATTACH";
break;
default:
delete vid;
return;
@ -238,6 +242,10 @@ void VirtualMachineManager::do_action(const string &action, void * arg)
{
driver_cancel_action(vid);
}
else if (action == "ATTACH")
{
attach_action(vid);
}
else if (action == ACTION_TIMER)
{
timer_action();
@ -270,6 +278,9 @@ string * VirtualMachineManager::format_message(
const string& ldfile,
const string& rdfile,
const string& cfile,
int disk_id,
const string& tm_command,
const string& disk_target_path,
const string& tmpl)
{
ostringstream oss;
@ -317,6 +328,19 @@ string * VirtualMachineManager::format_message(
oss << "<CHECKPOINT_FILE/>";
}
if ( !tm_command.empty() )
{
oss << "<TM_COMMAND>" << tm_command << "</TM_COMMAND>"
<< "<DISK_ID>" << disk_id << "</DISK_ID>"
<< "<DISK_TARGET_PATH>" << disk_target_path << "</DISK_TARGET_PATH>";
}
else
{
oss << "<TM_COMMAND/>"
<< "<DISK_ID/>"
<< "<DISK_TARGET_PATH/>";
}
oss << tmpl
<< "</VMM_DRIVER_ACTION_DATA>";
@ -380,6 +404,9 @@ void VirtualMachineManager::deploy_action(int vid)
vm->get_deployment_file(),
vm->get_remote_deployment_file(),
"",
0,
"",
"",
vm->to_xml(vm_tmpl));
vmd->deploy(vid, *drv_msg);
@ -477,6 +504,9 @@ void VirtualMachineManager::save_action(
"",
"",
vm->get_checkpoint_file(),
0,
"",
"",
vm->to_xml(vm_tmpl));
vmd->save(vid, *drv_msg);
@ -556,6 +586,9 @@ void VirtualMachineManager::shutdown_action(
"",
"",
"",
0,
"",
"",
vm->to_xml(vm_tmpl));
vmd->shutdown(vid, *drv_msg);
@ -630,6 +663,9 @@ void VirtualMachineManager::reboot_action(
"",
"",
"",
0,
"",
"",
vm->to_xml(vm_tmpl));
vmd->reboot(vid, *drv_msg);
@ -699,6 +735,9 @@ void VirtualMachineManager::reset_action(
"",
"",
"",
0,
"",
"",
vm->to_xml(vm_tmpl));
vmd->reset(vid, *drv_msg);
@ -769,6 +808,9 @@ void VirtualMachineManager::cancel_action(
"",
"",
"",
0,
"",
"",
vm->to_xml(vm_tmpl));
vmd->cancel(vid, *drv_msg);
@ -847,6 +889,9 @@ void VirtualMachineManager::cancel_previous_action(
"",
"",
"",
0,
"",
"",
vm->to_xml(vm_tmpl));
vmd->cancel(vid, *drv_msg);
@ -921,6 +966,9 @@ void VirtualMachineManager::migrate_action(
"",
"",
"",
0,
"",
"",
vm->to_xml(vm_tmpl));
vmd->migrate(vid, *drv_msg);
@ -1001,6 +1049,9 @@ void VirtualMachineManager::restore_action(
"",
"",
vm->get_checkpoint_file(),
0,
"",
"",
vm->to_xml(vm_tmpl));
vmd->restore(vid, *drv_msg);
@ -1076,6 +1127,9 @@ void VirtualMachineManager::poll_action(
"",
"",
"",
0,
"",
"",
vm->to_xml(vm_tmpl));
vmd->poll(vid, *drv_msg);
@ -1236,6 +1290,9 @@ void VirtualMachineManager::timer_action()
"",
"",
"",
0,
"",
"",
vm->to_xml(vm_tmpl));
vmd->poll(*it, *drv_msg);
@ -1248,6 +1305,125 @@ void VirtualMachineManager::timer_action()
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineManager::attach_action(
int vid)
{
VirtualMachine * vm;
const VirtualMachineManagerDriver * vmd;
ostringstream os;
string vm_tmpl;
string * drv_msg;
string tm_command;
string system_tm_mad;
string opennebula_hostname;
string prolog_cmd;
string disk_path;
string error_str;
const VectorAttribute * disk;
int disk_id;
Nebula& nd = Nebula::instance();
// 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_attach_disk();
if ( disk == 0 )
{
return;
}
system_tm_mad = nd.get_system_ds_tm_mad();
opennebula_hostname = nd.get_nebula_hostname();
disk_id = disk->vector_value("DISK_ID", disk_id);
Nebula::instance().get_tm()->prolog_transfer_command(
vm,
disk,
disk_id,
system_tm_mad,
opennebula_hostname,
os,
error_str);
prolog_cmd = os.str();
os.str("");
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(),
"",
"",
"",
disk_id,
prolog_cmd,
disk_path,
vm->to_xml(vm_tmpl));
vmd->attach(vid, *drv_msg);
delete drv_msg;
vm->unlock();
return;
error_history:
os.str("");
os << "attach_action, VM has no history";
goto error_common;
error_driver:
os.str("");
os << "attach_action, error getting driver " << vm->get_vmm_mad();
goto error_common;
error_common:
Nebula &ne = Nebula::instance();
LifeCycleManager * lcm = ne.get_lcm();
lcm->trigger(LifeCycleManager::ATTACH_FAILURE, vid);
vm->log("VMM", Log::ERROR, os);
vm->unlock();
return;
}
/* ************************************************************************** */
/* MAD Loading */
/* ************************************************************************** */

View File

@ -335,6 +335,37 @@ void VirtualMachineManagerDriver::protocol(
vmpool->update(vm);
}
}
else if ( action == "ATTACH" )
{
Nebula &ne = Nebula::instance();
LifeCycleManager *lcm = ne.get_lcm();
int disk_id;
istringstream tiss;
string disk_id_str = is.str();
tiss.clear();
tiss.str(disk_id_str);
tiss >> disk_id;
// TODO: check disk_id is correctly returned by the driver
if ( result == "SUCCESS" )
{
vm->log("VMM",Log::ERROR,"VM Disk Successfully attached.");
lcm->trigger(LifeCycleManager::ATTACH_SUCCESS, id);
}
else
{
log_error(vm,os,is,"Error attaching new VM Disk");
vmpool->update(vm);
lcm->trigger(LifeCycleManager::ATTACH_FAILURE, id);
}
}
else if ( action == "POLL" )
{
if (result == "SUCCESS")