1
0
mirror of https://github.com/OpenNebula/one.git synced 2024-12-23 17:33:56 +03:00

Merge branch 'feature-1791'

This commit is contained in:
Jaime Melis 2013-03-08 16:13:00 +01:00
commit 89f6fb6380
35 changed files with 1267 additions and 159 deletions

View File

@ -348,6 +348,17 @@ public:
return it->is_saving();
}
/**
* Check if the image is a hot snapshot
* @return true if image is a hot snapshot
*/
bool isHot()
{
ImageTemplate * it = static_cast<ImageTemplate *>(obj_template);
return it->is_saving_hot();
}
/**
* Set permissions for the Image. Extends the PoolSQLObject method
* by checking the persistent state of the image.

View File

@ -52,6 +52,15 @@ public:
return (saving.empty() == false);
}
bool is_saving_hot()
{
string save_as_hot;
get(saving_hot_attribute, save_as_hot);
return (save_as_hot.empty() == false);
}
void set_saving()
{
SingleAttribute * attr= new SingleAttribute(saving_attribute, "YES");
@ -61,6 +70,15 @@ public:
set(attr);
}
void set_saving_hot()
{
SingleAttribute * attr = new SingleAttribute(saving_hot_attribute,"YES");
erase(saving_hot_attribute);
set(attr);
}
void unset_saving()
{
erase(saving_attribute);
@ -72,6 +90,7 @@ private:
static vector<string> restricted_attributes;
static string saving_attribute;
static string saving_hot_attribute;
/**
* Stores the attributes as restricted, these attributes will be used in
@ -83,7 +102,7 @@ private:
Template::set_restricted_attributes(rattrs, restricted_attributes);
};
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -68,6 +68,8 @@ public:
DETACH_NIC_FAILURE,/**< Sent by the VMM when a detach nic 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_HOT_SUCCESS,/**< Sent by the VMM when hot saveas succeeds */
SAVEAS_HOT_FAILURE,/**< Sent by the VMM when hot saveas fails */
SNAPSHOT_CREATE_SUCCESS, /**< Sent by the VMM on snap. create success */
SNAPSHOT_CREATE_FAILURE, /**< Sent by the VMM on snap. create failure */
SNAPSHOT_REVERT_SUCCESS, /**< Sent by the VMM on snap. revert success */
@ -197,6 +199,10 @@ private:
void detach_failure_action(int vid);
void saveas_hot_success_action(int vid);
void saveas_hot_failure_action(int vid);
void attach_nic_success_action(int vid);
void attach_nic_failure_action(int vid);

View File

@ -152,7 +152,7 @@ public:
VirtualMachineSaveDisk():
RequestManagerVirtualMachine("VirtualMachineSaveDisk",
"Saves a disk from virtual machine as a new image",
"A:siiss"){};
"A:siissb"){};
~VirtualMachineSaveDisk(){};

View File

@ -57,6 +57,7 @@ public:
EPILOG_DELETE_BOTH,
CHECKPOINT,
DRIVER_CANCEL,
SAVEAS_HOT,
FINALIZE
};
@ -307,6 +308,11 @@ private:
* This function cancels the operation being performed by the driver
*/
void driver_cancel_action(int vid);
/**
* This function starts the saveas of the given disk
*/
void saveas_hot_action(int vid);
};
#endif /*TRANSFER_MANAGER_H*/

View File

@ -91,7 +91,10 @@ public:
BOOT_STOPPED = 22,
CLEANUP_DELETE = 23,
HOTPLUG_SNAPSHOT = 24,
HOTPLUG_NIC = 25
HOTPLUG_NIC = 25,
HOTPLUG_SAVEAS = 26,
HOTPLUG_SAVEAS_POWEROFF = 27,
HOTPLUG_SAVEAS_SUSPENDED = 28
};
// -------------------------------------------------------------------------
@ -845,20 +848,49 @@ public:
*/
int generate_context(string &files, int &disk_id);
// ------------------------------------------------------------------------
// -------------------------------------------------------------------------
// Datastore related functions
// ------------------------------------------------------------------------
// -------------------------------------------------------------------------
/**
* Gest the associated image to the given disk_id
* @param disk_id of the VM
* @param hot is this a save_as hot operation
* @param err_str describing the error
* @return -1 if the image cannot saveas
*/
int get_image_from_disk(int disk_id, bool hot, string& err_str);
/**
* Sets the corresponding SAVE_AS state.
* @return 0 if the VM can be saved as
*/
int set_saveas_state();
/**
* Clears the SAVE_AS state, moving the VM to the original state.
* @return 0 if the VM was in a SAVE_AS state
*/
int clear_saveas_state();
/**
* Set the SAVE_AS attribute for the "disk_id"th disk.
* @param disk_id Index of the disk to save
* @param source to save the disk (SAVE_AS_SOURCE)
* @param img_id ID of the image this disk will be saved to (SAVE_AS).
* @return 0 if success
*/
int save_disk(const string& disk_id,
const string& source,
int img_id);
/**
* Set the SAVE_AS attribute for the "disk_id"th disk.
* @param disk_id Index of the disk to save
* @param source to save the disk (SAVE_AS_SOURCE)
* @param img_id ID of the image this disk will be saved to (SAVE_AS).
*/
int save_disk_hot(const string& disk_id,
const string& source,
int img_id);
/**
* Get the original image id of the disk. It also checks that the disk can
* be saved_as.
@ -866,7 +898,12 @@ public:
* @param error_str describes the error
* @return -1 if failure
*/
int get_image_from_disk(int disk_id, string& error_str);
int get_saveas_disk_hot(int& disk_id, string& source, int& image_id);
/**
* Cleans the HOTPLUG_SAVEAS = YES attribute from the disks
*/
void clear_saveas_disk_hot();
// ------------------------------------------------------------------------
// Authorization related functions
@ -882,10 +919,9 @@ public:
AuthRequest& ar,
VirtualMachineTemplate *tmpl);
// ------------------------------------------------------------------------
// Disk Hotplug related functions
// ------------------------------------------------------------------------
// -------------------------------------------------------------------------
// Hotplug related functions
// -------------------------------------------------------------------------
/**
* Collects information about VM DISKS
* @param max_disk_id of the VM
@ -893,6 +929,14 @@ public:
*/
void get_disk_info(int& max_disk_id, set<string>& used_targets);
/**
* Get the IMAGE_ID of the image that's being saved as hot
* @param disk_id of the DISK
* @param image_id id of the image being saved
* @return IMAGE_ID on success, -1 otherwise
*/
int get_disk_hot_info(int& image_id, int& disk_id, string& source);
/**
* Generate a DISK attribute to be attached to the VM.
* @param tmpl Template containing a single DISK vector attribute.

View File

@ -935,7 +935,8 @@ TM_SHARED_FILES="src/tm_mad/shared/clone \
src/tm_mad/shared/context \
src/tm_mad/shared/premigrate \
src/tm_mad/shared/postmigrate \
src/tm_mad/shared/mvds"
src/tm_mad/shared/mvds \
src/tm_mad/shared/cpds"
TM_QCOW2_FILES="src/tm_mad/qcow2/clone \
src/tm_mad/qcow2/delete \
@ -946,7 +947,8 @@ TM_QCOW2_FILES="src/tm_mad/qcow2/clone \
src/tm_mad/qcow2/context \
src/tm_mad/qcow2/premigrate \
src/tm_mad/qcow2/postmigrate \
src/tm_mad/qcow2/mvds"
src/tm_mad/qcow2/mvds \
src/tm_mad/qcow2/cpds"
TM_SSH_FILES="src/tm_mad/ssh/clone \
src/tm_mad/ssh/delete \
@ -957,7 +959,8 @@ TM_SSH_FILES="src/tm_mad/ssh/clone \
src/tm_mad/ssh/context \
src/tm_mad/ssh/premigrate \
src/tm_mad/ssh/postmigrate \
src/tm_mad/ssh/mvds"
src/tm_mad/ssh/mvds \
src/tm_mad/ssh/cpds"
TM_DUMMY_FILES="src/tm_mad/dummy/clone \
src/tm_mad/dummy/delete \
@ -968,7 +971,8 @@ TM_DUMMY_FILES="src/tm_mad/dummy/clone \
src/tm_mad/dummy/context \
src/tm_mad/dummy/premigrate \
src/tm_mad/dummy/postmigrate \
src/tm_mad/dummy/mvds"
src/tm_mad/dummy/mvds \
src/tm_mad/dummy/cpds"
TM_VMFS_FILES="src/tm_mad/vmfs/clone \
src/tm_mad/vmfs/delete
@ -978,6 +982,7 @@ TM_VMFS_FILES="src/tm_mad/vmfs/clone \
src/tm_mad/vmfs/mv \
src/tm_mad/vmfs/context \
src/tm_mad/vmfs/mvds \
src/tm_mad/vmfs/cpds \
src/tm_mad/vmfs/postmigrate \
src/tm_mad/vmfs/premigrate"
@ -985,6 +990,7 @@ TM_ISCSI_FILES="src/tm_mad/iscsi/clone \
src/tm_mad/iscsi/ln \
src/tm_mad/iscsi/mv \
src/tm_mad/iscsi/mvds \
src/tm_mad/iscsi/cpds \
src/tm_mad/iscsi/premigrate \
src/tm_mad/iscsi/postmigrate \
src/tm_mad/iscsi/delete"
@ -993,6 +999,7 @@ TM_LVM_FILES="src/tm_mad/lvm/clone \
src/tm_mad/lvm/ln \
src/tm_mad/lvm/mv \
src/tm_mad/lvm/mvds \
src/tm_mad/lvm/cpds \
src/tm_mad/lvm/premigrate \
src/tm_mad/lvm/postmigrate \
src/tm_mad/lvm/delete"
@ -1001,6 +1008,7 @@ TM_CEPH_FILES="src/tm_mad/ceph/clone \
src/tm_mad/ceph/ln \
src/tm_mad/ceph/mv \
src/tm_mad/ceph/mvds \
src/tm_mad/ceph/cpds \
src/tm_mad/ceph/premigrate \
src/tm_mad/ceph/postmigrate \
src/tm_mad/ceph/delete"

View File

@ -108,7 +108,10 @@
BOOT_STOPPED = 22,
CLEANUP_DELETE = 23,
HOTPLUG_SNAPSHOT = 24,
HOTPLUG_NIC = 25
HOTPLUG_NIC = 25,
HOTPLUG_SAVEAS = 26,
HOTPLUG_SAVEAS_POWEROFF = 27,
HOTPLUG_SAVEAS_SUSPENDED = 28
-->
<xs:element name="LCM_STATE" type="xs:integer"/>
<xs:element name="RESCHED" type="xs:integer"/>

View File

@ -70,7 +70,10 @@
BOOT_STOPPED = 22,
CLEANUP_DELETE = 23,
HOTPLUG_SNAPSHOT = 24,
HOTPLUG_NIC = 25
HOTPLUG_NIC = 25,
HOTPLUG_SAVEAS = 26,
HOTPLUG_SAVEAS_POWEROFF = 27,
HOTPLUG_SAVEAS_SUSPENDED = 28
-->
<xs:element name="LCM_STATE" type="xs:integer"/>
<xs:element name="RESCHED" type="xs:integer"/>

View File

@ -82,6 +82,12 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
:description => "Show all template data"
}
HOT = {
:name =>"hot",
:large => "--hot",
:description => "The Image will be saved immediately"
}
def self.rname
"VM"
end

View File

@ -261,12 +261,19 @@ cmd=CommandParser::CmdParser.new(ARGV) do
created immediately, but the contents are saved only if the VM is
shut down gracefully (i.e., using 'onevm shutdown' and not
'onevm delete')
Sets the specified VM disk to be saved in a new Image.
The Image is created immediately, but the contents are saved only if the
VM is shut down gracefully (i.e., using 'onevm shutdown' and not 'onevm
delete')
If '--hot' is specified, the Image will be saved immediately.
States: ANY
EOT
command :saveas, saveas_desc, :vmid, :diskid, :img_name,
:options=>[TYPE] do
:options=>[TYPE, OneVMHelper::HOT] do
disk_id = args[1].to_i
image_name = args[2]
image_type = options[:type] || ""
@ -275,7 +282,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do
"the image #{image_name}"
helper.perform_action(args[0],options,verbose) do |vm|
res = vm.save_as(disk_id, image_name, image_type)
res = vm.save_as(disk_id, image_name, image_type, options[:hot])
if !OpenNebula.is_error?(res)
puts "Image ID: #{res}"

View File

@ -79,7 +79,7 @@ int Document::insert(SqlDB *db, string& error_str)
// Check default attributes
// ---------------------------------------------------------------------
get_template_attribute("NAME", name);
erase_template_attribute("NAME", name);
if ( name.empty() == true )
{
@ -199,8 +199,8 @@ string& Document::to_xml(string& xml) const
<< "<ID>" << oid << "</ID>"
<< "<UID>" << uid << "</UID>"
<< "<GID>" << gid << "</GID>"
<< "<UNAME>" << uname << "</UNAME>"
<< "<GNAME>" << gname << "</GNAME>"
<< "<UNAME>" << uname << "</UNAME>"
<< "<GNAME>" << gname << "</GNAME>"
<< "<NAME>" << name << "</NAME>"
<< "<TYPE>" << type << "</TYPE>"
<< perms_to_xml(perm_str)

View File

@ -26,7 +26,7 @@
/* Driver ASCII Protocol Implementation */
/* ************************************************************************** */
void ImageManagerDriver::cp(int oid,
void ImageManagerDriver::cp(int oid,
const string& drv_msg) const
{
ostringstream os;
@ -38,7 +38,7 @@ void ImageManagerDriver::cp(int oid,
/* -------------------------------------------------------------------------- */
void ImageManagerDriver::clone(int oid,
void ImageManagerDriver::clone(int oid,
const string& drv_msg) const
{
ostringstream os;
@ -49,7 +49,7 @@ void ImageManagerDriver::clone(int oid,
}
/* -------------------------------------------------------------------------- */
void ImageManagerDriver::stat(int oid,
void ImageManagerDriver::stat(int oid,
const string& drv_msg) const
{
ostringstream os;
@ -61,13 +61,13 @@ void ImageManagerDriver::stat(int oid,
/* -------------------------------------------------------------------------- */
void ImageManagerDriver::mkfs(int oid,
void ImageManagerDriver::mkfs(int oid,
const string& drv_msg) const
{
ostringstream os;
os << "MKFS " << oid << " " << drv_msg << endl;
write(os);
}
@ -121,9 +121,9 @@ static void stat_action(istringstream& is, int id, const string& result)
/* -------------------------------------------------------------------------- */
static void cp_action(istringstream& is,
ImagePool* ipool,
int id,
static void cp_action(istringstream& is,
ImagePool* ipool,
int id,
const string& result)
{
string source;
@ -143,7 +143,7 @@ static void cp_action(istringstream& is,
if ( is.good())
{
is >> source >> ws;
is >> source >> ws;
}
if (!source.empty())
@ -151,7 +151,7 @@ static void cp_action(istringstream& is,
oss << "CP operation succeeded but image no longer exists."
<< " Source image: " << source << ", may be left in datastore";
NebulaLog::log("ImM", Log::ERROR, oss);
NebulaLog::log("ImM", Log::ERROR, oss);
}
}
@ -160,7 +160,7 @@ static void cp_action(istringstream& is,
if ( result == "FAILURE" )
{
goto error;
goto error;
}
if ( is.good() )
@ -172,7 +172,7 @@ static void cp_action(istringstream& is,
{
goto error;
}
image->set_source(source);
image->set_state(Image::READY);
@ -194,7 +194,7 @@ error:
{
oss << ": " << info;
}
NebulaLog::log("ImM", Log::ERROR, oss);
image->set_template_error_message(oss.str());
@ -209,9 +209,9 @@ error:
/* -------------------------------------------------------------------------- */
static void clone_action(istringstream& is,
ImagePool* ipool,
int id,
static void clone_action(istringstream& is,
ImagePool* ipool,
int id,
const string& result)
{
int cloning_id;
@ -235,7 +235,7 @@ static void clone_action(istringstream& is,
if ( is.good())
{
is >> source >> ws;
is >> source >> ws;
}
if (!source.empty())
@ -243,7 +243,7 @@ static void clone_action(istringstream& is,
oss << "CLONE operation succeeded but image no longer exists."
<< " Source image: " << source << ", may be left in datastore";
NebulaLog::log("ImM", Log::ERROR, oss);
NebulaLog::log("ImM", Log::ERROR, oss);
}
}
@ -254,7 +254,7 @@ static void clone_action(istringstream& is,
if ( result == "FAILURE" )
{
goto error;
goto error;
}
if ( is.good() )
@ -266,7 +266,7 @@ static void clone_action(istringstream& is,
{
goto error;
}
image->set_source(source);
image->set_state(Image::READY);
@ -292,7 +292,7 @@ error:
{
oss << ": " << info;
}
NebulaLog::log("ImM", Log::ERROR, oss);
image->set_template_error_message(oss.str());
@ -311,25 +311,28 @@ error:
/* -------------------------------------------------------------------------- */
static void mkfs_action(istringstream& is,
ImagePool* ipool,
int id,
static void mkfs_action(istringstream& is,
ImagePool* ipool,
int id,
const string& result)
{
string source;
Image * image;
bool is_saving;
bool is_saving = false;
bool is_hot = false;
string disk_id;
string vm_id;
string info;
int rc;
int vm_id = -1;
string disk_id;
VirtualMachine * vm;
ostringstream oss;
Nebula& nd = Nebula::instance();
VirtualMachinePool * vmpool = nd.get_vmpool();
TransferManager * tm = nd.get_tm();
image = ipool->get(id, true);
@ -341,7 +344,7 @@ static void mkfs_action(istringstream& is,
if ( is.good())
{
is >> source >> ws;
is >> source >> ws;
}
if (!source.empty())
@ -349,55 +352,54 @@ static void mkfs_action(istringstream& is,
oss << "MkFS operation succeeded but image no longer exists."
<< " Source image: " << source << ", may be left in datastore";
NebulaLog::log("ImM", Log::ERROR, oss);
NebulaLog::log("ImM", Log::ERROR, oss);
}
}
return;
}
is_saving = image->isSaving();
is_hot = image->isHot();
if ( is_saving )
{
image->get_template_attribute("SAVED_VM_ID", vm_id);
image->get_template_attribute("SAVED_DISK_ID", disk_id);
}
if ( result == "FAILURE" )
{
goto error_img;
goto error_img;
}
if ( is.good() )
if ( !is.fail() )
{
is >> source >> ws;
}
if ( is.fail() )
else
{
goto error_img;
}
is_saving = image->isSaving();
image->set_source(source);
if (is_saving)
{
image->get_template_attribute("SAVED_DISK_ID", disk_id);
image->get_template_attribute("SAVED_VM_ID", vm_id);
}
else
if (!is_saving)
{
image->set_state(Image::READY);
NebulaLog::log("ImM", Log::INFO, "Image created and ready to use");
}
NebulaLog::log("ImM", Log::INFO, "Image created and ready to use");
ipool->update(image);
image->unlock();
if ( ! is_saving )
if ( !is_saving )
{
return;
}
/* ---------------- Set up information for the Saved Image -------------- */
vm = vmpool->get(vm_id, true);
if ( vm == 0 )
@ -405,11 +407,27 @@ static void mkfs_action(istringstream& is,
goto error_save_get;
}
rc = vm->save_disk(disk_id, source, id);
if ( rc == -1 )
if ( is_hot ) //Saveas hot, trigger disk copy
{
goto error_save_state;
rc = vm->save_disk_hot(disk_id, source, id);
if ( rc == -1 )
{
goto error_save_state;
}
tm->trigger(TransferManager::SAVEAS_HOT, vm_id);
}
else //setup disk information
{
rc = vm->save_disk(disk_id, source, id);
if ( rc == -1 )
{
goto error_save_state;
}
vm->clear_saveas_state();
}
vmpool->update(vm);
@ -446,7 +464,7 @@ error:
{
oss << ": " << info;
}
NebulaLog::log("ImM", Log::ERROR, oss);
image->set_template_error_message(oss.str());
@ -456,14 +474,25 @@ error:
image->unlock();
if (is_saving && vm_id != -1)
{
if ((vm = vmpool->get(vm_id, true)) != 0)
{
vm->clear_saveas_state();
vmpool->update(vm);
vm->unlock();
}
}
return ;
}
/* -------------------------------------------------------------------------- */
static void rm_action(istringstream& is,
ImagePool* ipool,
int id,
static void rm_action(istringstream& is,
ImagePool* ipool,
int id,
const string& result)
{
int rc;
@ -489,7 +518,7 @@ static void rm_action(istringstream& is,
if ( result == "FAILURE" )
{
goto error;
goto error;
}
else if ( rc < 0 )
{
@ -501,7 +530,7 @@ static void rm_action(istringstream& is,
return;
error_drop:
oss << "Error removing image from DB: " << tmp_error
oss << "Error removing image from DB: " << tmp_error
<< ". Remove image source " << source << " to completely delete image.";
NebulaLog::log("ImM", Log::ERROR, oss);
@ -517,7 +546,7 @@ error:
{
oss << ": " << info;
}
NebulaLog::log("ImM", Log::ERROR, oss);
return;
@ -535,9 +564,9 @@ void ImageManagerDriver::protocol(
string action;
string result;
string source;
string info;
string info;
int id;
oss << "Message received: " << message;
NebulaLog::log("ImG", Log::DEBUG, oss);
@ -584,7 +613,7 @@ void ImageManagerDriver::protocol(
else if ( action == "CLONE" )
{
clone_action(is, ipool, id, result);
}
}
else if ( action == "MKFS" )
{
mkfs_action(is, ipool, id, result);

View File

@ -21,7 +21,8 @@
vector<string> ImageTemplate::restricted_attributes;
string ImageTemplate::saving_attribute = "SAVE_AS";
string ImageTemplate::saving_attribute = "SAVE_AS";
string ImageTemplate::saving_hot_attribute = "SAVE_AS_HOT";
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -550,8 +550,6 @@ void LifeCycleManager::restart_action(int vid)
vm->log("LCM", Log::INFO, "New VM state is BOOT_POWEROFF");
}
//----------------------------------------------------
vmm->trigger(VirtualMachineManager::DEPLOY,vid);
}
else
@ -738,6 +736,9 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose)
case VirtualMachine::SHUTDOWN_POWEROFF:
case VirtualMachine::CANCEL:
case VirtualMachine::HOTPLUG:
case VirtualMachine::HOTPLUG_SAVEAS:
case VirtualMachine::HOTPLUG_SAVEAS_POWEROFF:
case VirtualMachine::HOTPLUG_SAVEAS_SUSPENDED:
case VirtualMachine::HOTPLUG_SNAPSHOT:
case VirtualMachine::HOTPLUG_NIC:
vm->set_running_etime(the_time);

View File

@ -145,6 +145,14 @@ void LifeCycleManager::trigger(Actions action, int _vid)
aname = "DETACH_FAILURE";
break;
case SAVEAS_HOT_SUCCESS:
aname = "SAVEAS_HOT_SUCCESS";
break;
case SAVEAS_HOT_FAILURE:
aname = "SAVEAS_HOT_FAILURE";
break;
case ATTACH_NIC_SUCCESS:
aname = "ATTACH_NIC_SUCCESS";
break;
@ -345,6 +353,14 @@ void LifeCycleManager::do_action(const string &action, void * arg)
{
detach_failure_action(vid);
}
else if (action == "SAVEAS_HOT_SUCCESS")
{
saveas_hot_success_action(vid);
}
else if (action == "SAVEAS_HOT_FAILURE")
{
saveas_hot_failure_action(vid);
}
else if (action == "ATTACH_NIC_SUCCESS")
{
attach_nic_success_action(vid);

View File

@ -1478,3 +1478,117 @@ void LifeCycleManager::detach_nic_failure_action(int vid)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void LifeCycleManager::saveas_hot_success_action(int vid)
{
Nebula& nd = Nebula::instance();
ImagePool * ipool = nd.get_ipool();
VirtualMachine * vm;
Image * image;
int image_id;
int disk_id;
string source;
vm = vmpool->get(vid,true);
if ( vm == 0 )
{
return;
}
if (vm->clear_saveas_state() == -1)
{
vm->log("LCM", Log::ERROR, "saveas_hot_success_action, VM in a wrong state");
vm->unlock();
return;
}
int rc = vm->get_saveas_disk_hot(disk_id, source, image_id);
vm->clear_saveas_disk_hot();
vmpool->update(vm);
vm->unlock();
if ( rc != 0 )
{
return;
}
image = ipool->get(image_id, true);
if ( image == 0 )
{
return;
}
image->set_state(Image::READY);
ipool->update(image);
image->unlock();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void LifeCycleManager::saveas_hot_failure_action(int vid)
{
Nebula& nd = Nebula::instance();
ImagePool * ipool = nd.get_ipool();
VirtualMachine * vm;
Image * image;
int image_id;
int disk_id;
string source;
vm = vmpool->get(vid,true);
if ( vm == 0 )
{
return;
}
if (vm->clear_saveas_state() == -1)
{
vm->log("LCM", Log::ERROR, "saveas_hot_success_action, VM in a wrong state");
vm->unlock();
return;
}
int rc = vm->get_saveas_disk_hot(disk_id, source, image_id);
vm->clear_saveas_disk_hot();
vmpool->update(vm);
vm->unlock();
if ( rc != 0 )
{
return;
}
image = ipool->get(image_id, true);
if ( image == 0 )
{
return;
}
image->set_state(Image::ERROR);
ipool->update(image);
image->unlock();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -96,7 +96,10 @@ public class VirtualMachine extends PoolElement{
"BOOT_STOPPED",
"CLEANUP_DELETE",
"HOTPLUG_SNAPSHOT",
"HOTPLUG_NIC" };
"HOTPLUG_NIC",
"HOTPLUG_SAVEAS",
"HOTPLUG_SAVEAS_POWEROFF",
"HOTPLUG_SAVEAS_SUSPENDED" };
private static final String[] SHORT_LCM_STATES =
{
@ -124,7 +127,11 @@ public class VirtualMachine extends PoolElement{
"boot",
"boot",
"clea",
"snap" };
"snap",
"hotp",
"hotp",
"hotp",
"hotp" };
/**
* Creates a new VM representation.
@ -468,9 +475,9 @@ public class VirtualMachine extends PoolElement{
* @param imageName Name of the new Image that will be created.
* @return If an error occurs the error message contains the reason.
*/
public OneResponse savedisk(int diskId, String imageName)
public OneResponse savedisk(int diskId, String imageName, boolean hot = false)
{
return savedisk(diskId, imageName, "");
return savedisk(diskId, imageName, "", hot);
}
/**
@ -481,11 +488,13 @@ public class VirtualMachine extends PoolElement{
* @param imageName Name of the new Image that will be created.
* @param imageType Type of the new image. Set to empty string to use
* the default type
* @param hot do not defer saveas operation
* @return If an error occurs the error message contains the reason.
*/
public OneResponse savedisk(int diskId, String imageName, String imageType)
public OneResponse savedisk(int diskId, String imageName, String imageType,
boolean hot)
{
return client.call(SAVEDISK, id ,diskId, imageName, imageType);
return client.call(SAVEDISK, id ,diskId, imageName, imageType, hot);
}
/**

View File

@ -52,7 +52,8 @@ module OpenNebula
SAVE_MIGRATE PROLOG_MIGRATE PROLOG_RESUME EPILOG_STOP EPILOG
SHUTDOWN CANCEL FAILURE CLEANUP_RESUBMIT UNKNOWN HOTPLUG SHUTDOWN_POWEROFF
BOOT_UNKNOWN BOOT_POWEROFF BOOT_SUSPENDED BOOT_STOPPED CLEANUP_DELETE
HOTPLUG_SNAPSHOT HOTPLUG_NIC}
HOTPLUG_SNAPSHOT HOTPLUG_NIC HOTPLUG_SAVEAS HOTPLUG_SAVEAS_POWEROFF
HOTPLUG_SAVEAS_SUSPENDED}
SHORT_VM_STATES={
"INIT" => "init",
@ -91,7 +92,10 @@ module OpenNebula
"BOOT_STOPPED" => "boot",
"CLEANUP_DELETE" => "clea",
"HOTPLUG_SNAPSHOT" => "snap",
"HOTPLUG_NIC" => "hotp"
"HOTPLUG_NIC" => "hotp",
"HOTPLUG_SAVEAS" => "hotp",
"HOTPLUG_SAVEAS_POWEROFF" => "hotp",
"HOTPLUG_SAVEAS_SUSPENDED" => "hotp"
}
MIGRATE_REASON=%w{NONE ERROR STOP_RESUME USER CANCEL}
@ -350,14 +354,15 @@ module OpenNebula
#
# @return [Integer, OpenNebula::Error] the new Image ID in case of
# success, error otherwise
def save_as(disk_id, image_name, image_type="")
def save_as(disk_id, image_name, image_type="", hot=false)
return Error.new('ID not defined') if !@pe_id
rc = @client.call(VM_METHODS[:savedisk],
@pe_id,
disk_id,
image_name,
image_type)
image_type,
hot)
return rc
end

View File

@ -104,7 +104,10 @@ var oZones = {
"BOOT_STOPPED",
"CLEANUP_DELETE",
"HOTPLUG_SNAPSHOT",
"HOTPLUG_NIC"][value]);
"HOTPLUG_NIC",
"HOTPLUG_SAVEAS",
"HOTPLUG_SAVEAS_POWEROFF",
"HOTPLUG_SAVEAS_SUSPENDED"][value]);
break;
case "IMAGE":
case "image":

View File

@ -682,47 +682,62 @@ void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramLis
{
Nebula& nd = Nebula::instance();
ImagePool * ipool = nd.get_ipool();
DatastorePool * dspool = nd.get_dspool();
UserPool * upool = nd.get_upool();
ImagePool * ipool = nd.get_ipool();
DatastorePool * dspool = nd.get_dspool();
UserPool * upool = nd.get_upool();
int id = xmlrpc_c::value_int(paramList.getInt(1));
int disk_id = xmlrpc_c::value_int(paramList.getInt(2));
string img_name = xmlrpc_c::value_string(paramList.getString(3));
string img_type = xmlrpc_c::value_string(paramList.getString(4));
bool is_hot = false; //Optional XML-RPC argument
if ( paramList.size() > 5 )
{
is_hot = xmlrpc_c::value_boolean(paramList.getBoolean(5));
}
VirtualMachinePool * vmpool = static_cast<VirtualMachinePool *>(pool);
VirtualMachine * vm;
Datastore * ds;
int iid;
int iid_orig;
Image * img;
Datastore * ds;
User * user;
Image::DiskType ds_disk_type;
int umask;
int rc;
string error_str;
string error_str;
string driver;
string target;
string dev_prefix;
// -------------------------------------------------------------------------
// Prepare and check the VM/DISK to be saved_as
// Get user's umask
// -------------------------------------------------------------------------
User * user = upool->get(att.uid, true);
if ( (vm = get_vm(id, att)) == 0 )
if ( user == 0 )
{
failure_response(NO_EXISTS,
get_error(object_name(PoolObjectSQL::VM), id),
att);
get_error(object_name(PoolObjectSQL::USER), att.uid),
att);
return;
}
iid_orig = vm->get_image_from_disk(disk_id, error_str);
int umask = user->get_umask();
pool->update(vm);
user->unlock();
// -------------------------------------------------------------------------
// Prepare and check the VM/DISK to be saved_as
// -------------------------------------------------------------------------
if ((vm = get_vm(id, att)) == 0)
{
return;
}
int rc = vm->set_saveas_state();
int iid_orig = vm->get_image_from_disk(disk_id, is_hot, error_str);
vmpool->update(vm);
vm->unlock();
@ -734,36 +749,32 @@ void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramLis
return;
}
// -------------------------------------------------------------------------
// Get user's umask
// -------------------------------------------------------------------------
user = upool->get(att.uid, true);
if ( user == 0 )
if ( rc != 0 )
{
failure_response(NO_EXISTS,
get_error(object_name(PoolObjectSQL::USER), att.uid),
att);
failure_response(INTERNAL,
request_error("VM has to be RUNNING, POWEROFF or"
" SUSPENDED to saveas disks.",""), att);
return;
}
umask = user->get_umask();
user->unlock();
// -------------------------------------------------------------------------
// Get the data of the Image to be saved
// -------------------------------------------------------------------------
img = ipool->get(iid_orig, true);
Image * img = ipool->get(iid_orig, true);
if ( img == 0 )
{
failure_response(NO_EXISTS,
get_error(object_name(PoolObjectSQL::IMAGE), iid_orig),
att);
if ((vm = vmpool->get(id, true)) != 0)
{
vm->clear_saveas_state();
vmpool->update(vm);
vm->unlock();
}
return;
}
@ -779,11 +790,22 @@ void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramLis
img->unlock();
// -------------------------------------------------------------------------
// Get the data of the DataStore for the new image
// -------------------------------------------------------------------------
if ((ds = dspool->get(ds_id, true)) == 0 )
{
failure_response(NO_EXISTS,
get_error(object_name(PoolObjectSQL::DATASTORE), ds_id),
att);
if ((vm = vmpool->get(id, true)) != 0)
{
vm->clear_saveas_state();
vmpool->update(vm);
vm->unlock();
}
return;
}
@ -798,21 +820,18 @@ void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramLis
case Image::RAMDISK:
case Image::CONTEXT:
failure_response(INTERNAL,
request_error("Cannot save_as image of type " + Image::type_to_str(type), ""),
att);
request_error("Cannot save_as image of type " +
Image::type_to_str(type), ""), att);
return;
}
// -------------------------------------------------------------------------
// Get the data of the DataStore for the new image
// -------------------------------------------------------------------------
string ds_data;
PoolObjectAuth ds_perms;
ds->get_permissions(ds_perms);
ds->to_xml(ds_data);
ds_disk_type = ds->get_disk_type();
Image::DiskType ds_disk_type = ds->get_disk_type();
ds->unlock();
@ -829,6 +848,13 @@ void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramLis
itemplate->add("SAVED_DISK_ID",disk_id);
itemplate->add("SAVED_VM_ID", id);
itemplate->set_saving();
if ( is_hot )
{
itemplate->set_saving_hot();
}
if ( img_type.empty() )
{
itemplate->add("TYPE", Image::type_to_str(type));
@ -853,31 +879,36 @@ void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramLis
itemplate->add("DEV_PREFIX", dev_prefix);
}
itemplate->set_saving();
img_usage.add("SIZE", size);
img_usage.add("DATASTORE", ds_id);
// -------------------------------------------------------------------------
// Authorize the operation & check quotas
// -------------------------------------------------------------------------
bool rc_auth = vm_authorization(id, itemplate, 0, att, 0,&ds_perms,auth_op);
if ( vm_authorization(id, itemplate, 0, att, 0, &ds_perms, auth_op) == false )
if ( rc_auth == true )
{
delete itemplate;
return;
rc_auth = quota_authorization(&img_usage, Quotas::DATASTORE, att);
}
if ( quota_authorization(&img_usage, Quotas::DATASTORE, att) == false )
if ( rc_auth == false)
{
delete itemplate;
if ((vm = vmpool->get(id, true)) != 0)
{
vm->clear_saveas_state();
vmpool->update(vm);
vm->unlock();
}
return;
}
// -------------------------------------------------------------------------
// Create the image
// -------------------------------------------------------------------------
rc = ipool->allocate(att.uid,
att.gid,
att.uname,
@ -896,6 +927,13 @@ void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramLis
{
quota_rollback(&img_usage, Quotas::DATASTORE, att);
if ((vm = vmpool->get(id, true)) != 0)
{
vm->clear_saveas_state();
vmpool->update(vm);
vm->unlock();
}
failure_response(INTERNAL,
allocate_error(PoolObjectSQL::IMAGE, error_str), att);
return;

View File

@ -112,7 +112,10 @@ var OpenNebula = {
"BOOT_STOPPED",
"CLEANUP_DELETE",
"HOTPLUG_SNAPSHOT",
"HOTPLUG_NIC"][value]);
"HOTPLUG_NIC",
"HOTPLUG_SAVEAS",
"HOTPLUG_SAVEAS_POWEROFF",
"HOTPLUG_SAVEAS_SUSPENDED"][value]);
break;
case "IMAGE":
case "image":

View File

@ -49,8 +49,7 @@ var vm_graphs = [
}
];
var VNCstates=["RUNNING","SHUTDOWN","SHUTDOWN_POWEROFF","UNKNOWN","HOTPLUG","CANCEL","MIGRATE", "HOTPLUG_SNAPSHOT", "HOTPLUG_NIC"];
var VNCstates=["RUNNING","SHUTDOWN","SHUTDOWN_POWEROFF","UNKNOWN","HOTPLUG","CANCEL","MIGRATE", "HOTPLUG_SNAPSHOT", "HOTPLUG_NIC", "HOTPLUG_SAVEAS", "HOTPLUG_SAVEAS_POWEROFF", "HOTPLUG_SAVEAS_SUSPENDED"];
//Permanent storage for last value of aggregated network usage
//Used to calculate bandwidth

View File

@ -123,6 +123,10 @@ void TransferManager::trigger(Actions action, int _vid)
aname = "CHECKPOINT";
break;
case SAVEAS_HOT:
aname = "SAVEAS_HOT";
break;
case DRIVER_CANCEL:
aname = "DRIVER_CANCEL";
break;
@ -195,6 +199,10 @@ void TransferManager::do_action(const string &action, void * arg)
{
checkpoint_action(vid);
}
else if (action == "SAVEAS_HOT")
{
saveas_hot_action(vid);
}
else if (action == "DRIVER_CANCEL")
{
driver_cancel_action(vid);
@ -1625,6 +1633,145 @@ void TransferManager::checkpoint_action(int vid)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void TransferManager::saveas_hot_action(int vid)
{
int disk_id;
int image_id;
string save_source;
string save;
string tm_mad;
string ds_id;
int num;
int disk_id_iter;
ostringstream os;
ofstream xfr;
string xfr_name;
string source;
const VectorAttribute * disk;
vector<const Attribute *> attrs;
VirtualMachine * vm;
Nebula& nd = Nebula::instance();
const TransferManagerDriver * tm_md;
// ------------------------------------------------------------------------
// Setup & Transfer script
// ------------------------------------------------------------------------
vm = vmpool->get(vid,true);
if (vm == 0)
{
vm->log("TM", Log::ERROR, "Could not obtain the VM");
goto error_common;
}
if (!vm->hasHistory())
{
vm->log("TM", Log::ERROR, "The VM has no history");
goto error_common;
}
if (vm->get_saveas_disk_hot(disk_id, save_source, image_id) == -1)
{
vm->log("TM", Log::ERROR, "Could not get disk information to saveas it");
goto error_common;
}
tm_md = get();
if (tm_md == 0)
{
goto error_driver;
}
num = vm->get_template_attribute("DISK",attrs);
for (int i=0 ; i < num ; i++)
{
disk = dynamic_cast<const VectorAttribute *>(attrs[i]);
if ( disk == 0 )
{
continue;
}
disk->vector_value("DISK_ID", disk_id_iter);
if (disk_id == disk_id_iter)
{
tm_mad = disk->vector_value("TM_MAD");
ds_id = disk->vector_value("DATASTORE_ID");
break;
}
}
if ( ds_id.empty() || tm_mad.empty() )
{
vm->log("TM", Log::ERROR, "No DS_ID or TM_MAD to save disk image");
goto error_common;
}
if (save_source.empty())
{
vm->log("TM", Log::ERROR, "No SOURCE to save disk image");
goto error_common;
}
xfr_name = vm->get_transfer_file() + ".saveas_hot";
xfr.open(xfr_name.c_str(),ios::out | ios::trunc);
if (xfr.fail() == true)
{
goto error_file;
}
//MVDS tm_mad hostname:remote_system_dir/disk.0 <fe:SOURCE|SOURCE> vmid dsid
xfr << "CPDS "
<< tm_mad << " "
<< vm->get_hostname() << ":"
<< vm->get_remote_system_dir() << "/disk." << disk_id << " "
<< save_source << " "
<< vm->get_oid() << " "
<< ds_id
<< endl;
xfr.close();
tm_md->transfer(vid, xfr_name);
vm->unlock();
return;
error_driver:
os << "saveas_hot_transfer, error getting TM driver.";
goto error_common;
error_file:
os << "saveas_hot_transfer, could not open file: " << xfr_name;
os << ". You may need to manually clean hosts (previous & current)";
goto error_common;
error_common:
vm->log("TM", Log::ERROR, os);
(nd.get_lcm())->trigger(LifeCycleManager::SAVEAS_HOT_FAILURE, vid);
vm->unlock();
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void TransferManager::migrate_transfer_command(
VirtualMachine * vm,
ostream& xfr)

View File

@ -131,6 +131,12 @@ void TransferManagerDriver::protocol(
lcm_action = LifeCycleManager::EPILOG_SUCCESS;
break;
case VirtualMachine::HOTPLUG_SAVEAS:
case VirtualMachine::HOTPLUG_SAVEAS_POWEROFF:
case VirtualMachine::HOTPLUG_SAVEAS_SUSPENDED:
lcm_action = LifeCycleManager::SAVEAS_HOT_SUCCESS;
break;
default:
goto error_state;
}
@ -168,6 +174,12 @@ void TransferManagerDriver::protocol(
lcm_action = LifeCycleManager::EPILOG_FAILURE;
break;
case VirtualMachine::HOTPLUG_SAVEAS:
case VirtualMachine::HOTPLUG_SAVEAS_POWEROFF:
case VirtualMachine::HOTPLUG_SAVEAS_SUSPENDED:
lcm_action = LifeCycleManager::SAVEAS_HOT_FAILURE;
break;
default:
goto error_state;
}

76
src/tm_mad/ceph/cpds Executable file
View File

@ -0,0 +1,76 @@
#!/bin/bash
# -------------------------------------------------------------------------- #
# Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs #
# #
# 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. #
#--------------------------------------------------------------------------- #
# mvds host:remote_system_ds/disk.i fe:SOURCE
# - fe is the front-end hostname
# - SOURCE is the path of the disk image in the form DS_BASE_PATH/disk
# - host is the target host to deploy the VM
# - remote_system_ds is the path for the system datastore in the host
SRC=$1
DST=$2
VM_ID=$3
DS_ID=$4
if [ -z "${ONE_LOCATION}" ]; then
TMCOMMON=/var/lib/one/remotes/tm/tm_common.sh
else
TMCOMMON=$ONE_LOCATION/var/remotes/tm/tm_common.sh
fi
DRIVER_PATH=$(dirname $0)
source $TMCOMMON
source ${DRIVER_PATH}/../../datastore/ceph/ceph.conf
#-------------------------------------------------------------------------------
# Set dst path and dir
#-------------------------------------------------------------------------------
SRC_HOST=`arg_host $SRC`
SRC_PATH=`arg_path $SRC`
#-------------------------------------------------------------------------------
# Get Image information
#-------------------------------------------------------------------------------
DISK_ID=$(echo "$SRC_PATH" | $AWK -F. '{print $NF}')
XPATH="${DRIVER_PATH}/../../datastore/xpath.rb --stdin"
unset i j XPATH_ELEMENTS
while IFS= read -r -d '' element; do
XPATH_ELEMENTS[i++]="$element"
done < <(onevm show -x $VM_ID| $XPATH \
/VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/SOURCE \
/VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/PERSISTENT)
RBD_SRC="${XPATH_ELEMENTS[j++]}"
PERSISTENT="${XPATH_ELEMENTS[j++]}"
if [ "$PERSISTENT" = "YES" ]; then
RBD_DST="${RBD_SRC}"
else
RBD_DST="${RBD_SRC}-${VM_ID}-${DISK_ID}"
fi
ssh_exec_and_log "$SRC_HOST" "$RBD copy $RBD_DST $DST" \
"Error cloning $RBD_DST to $DST in $DST_HOST"
exit 0

1
src/tm_mad/dummy/cpds Symbolic link
View File

@ -0,0 +1 @@
../common/dummy.sh

92
src/tm_mad/iscsi/cpds Executable file
View File

@ -0,0 +1,92 @@
#!/bin/bash
# -------------------------------------------------------------------------- #
# Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs #
# #
# 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. #
#--------------------------------------------------------------------------- #
# mvds host:remote_system_ds/disk.i fe:SOURCE
# - fe is the front-end hostname
# - SOURCE is the path of the disk image in the form DS_BASE_PATH/disk
# - host is the target host to deploy the VM
# - remote_system_ds is the path for the system datastore in the host
# - vmid is the id of the VM
# - dsid is the target datastore (0 is the system datastore)
SRC=$1
DST=$2
VMID=$3
DSID=$4
if [ -z "${ONE_LOCATION}" ]; then
TMCOMMON=/var/lib/one/remotes/tm/tm_common.sh
else
TMCOMMON=$ONE_LOCATION/var/remotes/tm/tm_common.sh
fi
DRIVER_PATH=$(dirname $0)
. $TMCOMMON
source ${DRIVER_PATH}/../../datastore/iscsi/iscsi.conf
SRC_HOST=`arg_host $SRC`
NEW_IQN="$DST"
DISK_ID=$(echo $SRC|awk -F. '{print $NF}')
#-------------------------------------------------------------------------------
# Get image information
#-------------------------------------------------------------------------------
XPATH="${DRIVER_PATH}/../../datastore/xpath.rb --stdin"
unset i XPATH_ELEMENTS
while IFS= read -r -d '' element; do
XPATH_ELEMENTS[i++]="$element"
done < <(onevm show -x $VMID| $XPATH \
/VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/SOURCE \
/VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/SAVE_AS \
/VM/TEMPLATE/DISK[DISK_ID=$DISK_ID]/PERSISTENT)
IQN="${XPATH_ELEMENTS[0]}"
SAVE_AS="${XPATH_ELEMENTS[1]}"
PERSISTENT="${XPATH_ELEMENTS[2]}"
if [ -z "$PERSISTENT" ]; then
IQN=$IQN-$VMID
fi
#-------------------------------------------------------------------------------
# IQN and TARGETs
#-------------------------------------------------------------------------------
LV_NAME=`echo $IQN|$AWK -F. '{print $(NF)}'`
VG_NAME=`echo $IQN|$AWK -F. '{print $(NF-1)}'`
SOURCE_DEV="/dev/$VG_NAME/$LV_NAME"
TARGET=`arg_path $IQN`
TARGET_LV_NAME=`echo $NEW_IQN|$AWK -F. '{print $(NF)}'`
TARGET_DEV="/dev/$VG_NAME/$TARGET_LV_NAME"
TARGET_HOST="${TARGET%.$VG_NAME.$LV_NAME}"
CLONE_CMD=$(cat <<EOF
$SUDO $DD if=$SOURCE_DEV of=$TARGET_DEV bs=2M
EOF
)
ssh_exec_and_log "$TARGET_HOST" "$CLONE_CMD" \
"Error cloning $DST_HOST:$TARGET_DEV"

70
src/tm_mad/lvm/cpds Executable file
View File

@ -0,0 +1,70 @@
#!/bin/bash
# -------------------------------------------------------------------------- #
# Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs #
# #
# 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. #
#--------------------------------------------------------------------------- #
# mvds host:remote_system_ds/disk.i fe:SOURCE
# - fe is the front-end hostname
# - SOURCE is the path of the disk image in the form DS_BASE_PATH/disk
# - host is the target host to deploy the VM
# - remote_system_ds is the path for the system datastore in the host
SRC=$1
DST=$2
VM_ID=$3
DS_ID=$4
if [ -z "${ONE_LOCATION}" ]; then
TMCOMMON=/var/lib/one/remotes/tm/tm_common.sh
else
TMCOMMON=$ONE_LOCATION/var/remotes/tm/tm_common.sh
fi
DRIVER_PATH=$(dirname $0)
source $TMCOMMON
source ${DRIVER_PATH}/../../datastore/lvm/lvm.conf
#-------------------------------------------------------------------------------
# Set dst path and dir
#-------------------------------------------------------------------------------
SRC_PATH=`arg_path $SRC`
SRC_HOST=`arg_host $SRC`
DST_PATH=`arg_path $DST`
DST_HOST=`arg_host $DST`
VG_NAME=$(echo $DST_PATH|cut -d. -f1)
LV_NAME=$(echo $DST_PATH|cut -d. -f2)
TARGET_DEV=/dev/$VG_NAME/$LV_NAME
DUMP_CMD=$(cat <<EOF
DEV=\$(readlink $SRC_PATH)
SIZE=\$($SUDO $LVS \$DEV --noheadings --nosuffix --units m -o lv_size \
| tr -d ' ')
$SUDO $LVCREATE -L\${SIZE}M ${VG_NAME} -n ${LV_NAME}
$SUDO $DD if="\${DEV}" of="${TARGET_DEV}"
EOF
)
#-------------------------------------------------------------------------------
# Move the image back to the datastore
#-------------------------------------------------------------------------------
log "Dumping $SRC to $DST"
ssh_exec_and_log "$SRC_HOST" "$DUMP_CMD" "Error dumping $SRC to $DST"
exit 0

75
src/tm_mad/qcow2/cpds Executable file
View File

@ -0,0 +1,75 @@
#!/bin/bash
# -------------------------------------------------------------------------- #
# Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs #
# #
# 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. #
#--------------------------------------------------------------------------- #
# mvds host:remote_system_ds/disk.i fe:SOURCE vmid dsid
# - fe is the front-end hostname
# - SOURCE is the path of the disk image in the form DS_BASE_PATH/disk
# - host is the target host to deploy the VM
# - remote_system_ds is the path for the system datastore in the host
# - vmid is the id of the VM
# - dsid is the target datastore (0 is the system datastore)
SRC=$1
DST=$2
VMID=$3
DSID=$4
if [ -z "${ONE_LOCATION}" ]; then
TMCOMMON=/var/lib/one/remotes/tm/tm_common.sh
else
TMCOMMON=$ONE_LOCATION/var/remotes/tm/tm_common.sh
fi
. $TMCOMMON
#-------------------------------------------------------------------------------
# Set dst path and dir
#-------------------------------------------------------------------------------
SRC_PATH=`arg_path $SRC`
SRC_HOST=`arg_host $SRC`
SRC_DIR=`dirname $SRC_PATH`
DST_ARG_PATH=`arg_path $DST`
SRC_DS_PATH="$(dirname $(dirname $(dirname $SRC_PATH)))"
DST_DS_PATH="$(dirname $(dirname $DST_ARG_PATH))"
DST_PATH="${SRC_DS_PATH}${DST_ARG_PATH##$DST_DS_PATH}"
#-------------------------------------------------------------------------------
# Move the image back to the datastore
#-------------------------------------------------------------------------------
CPSCRIPT=$(cat <<EOF
umask 0007
SRC_READLN=\$($READLINK -f $SRC_PATH)
DST_READLN=\$($READLINK -f $DST_PATH)
if [ \( -L $SRC_PATH \) -a \( "\$SRC_READLN" = "\$DST_READLN" \) ] ; then
echo "Not moving files to image repo, they are the same"
else
qemu-img convert $SRC_PATH -O qcow2 $DST_PATH
fi
EOF
)
log "Copying $SRC_PATH to datastore as $DST_PATH"
ssh_exec_and_log $SRC_HOST "$CPSCRIPT" "Could not move image $DST_PATH"
exit 0

83
src/tm_mad/shared/cpds Executable file
View File

@ -0,0 +1,83 @@
#!/bin/bash
# -------------------------------------------------------------------------- #
# Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs #
# #
# 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. #
#--------------------------------------------------------------------------- #
# mvds host:remote_system_ds/disk.i fe:SOURCE vmid dsid
# - fe is the front-end hostname
# - SOURCE is the path of the disk image in the form DS_BASE_PATH/disk
# - host is the target host to deploy the VM
# - remote_system_ds is the path for the system datastore in the host
# - vmid is the id of the VM
# - dsid is the target datastore (0 is the system datastore)
SRC=$1
DST=$2
VMID=$3
DSID=$4
if [ -z "${ONE_LOCATION}" ]; then
TMCOMMON=/var/lib/one/remotes/tm/tm_common.sh
else
TMCOMMON=$ONE_LOCATION/var/remotes/tm/tm_common.sh
fi
. $TMCOMMON
#-------------------------------------------------------------------------------
# Set dst path and dir
#-------------------------------------------------------------------------------
SRC_PATH=`arg_path $SRC`
SRC_HOST=`arg_host $SRC`
SRC_DIR=`dirname $SRC_PATH`
DST_ARG_PATH=`arg_path $DST`
SRC_DS_PATH="$(dirname $(dirname $(dirname $SRC_PATH)))"
DST_DS_PATH="$(dirname $(dirname $DST_ARG_PATH))"
DST_PATH="${SRC_DS_PATH}${DST_ARG_PATH##$DST_DS_PATH}"
#-------------------------------------------------------------------------------
# Move the image back to the datastore
#-------------------------------------------------------------------------------
CPSCRIPT=$(cat <<EOF
umask 0007
SRC_READLN=\$($READLINK -f $SRC_PATH)
DST_READLN=\$($READLINK -f $DST_PATH)
if [ -d $SRC_PATH ] ; then
if [ \( -L $SRC_PATH \) -a \( "\$SRC_READLN" = "\$DST_READLN" \) ] ; then
echo "Not moving files to image repo, they are the same"
elif [ -f $SRC_PATH/.is_persistent ]; then
echo "Not moving files to image repo, they are the same"
else
cp -rf $SRC_PATH/* $DST_PATH
fi
elif [ \( -L $SRC_PATH \) -a \( "\$SRC_READLN" = "\$DST_READLN" \) ] ; then
echo "Not copying files to image repo, they are the same"
else
cp -f $SRC_PATH $DST_PATH
fi
EOF
)
log "Copying $SRC_PATH to datastore as $DST_PATH"
ssh_exec_and_log $SRC_HOST "$CPSCRIPT" "Could not copy image $DST_PATH"
exit 0

47
src/tm_mad/ssh/cpds Executable file
View File

@ -0,0 +1,47 @@
#!/bin/bash
# -------------------------------------------------------------------------- #
# Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs #
# #
# 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. #
#--------------------------------------------------------------------------- #
# cpds host:remote_system_ds/disk.i fe:SOURCE vmid dsid
# - fe is the front-end hostname
# - SOURCE is the path of the disk image in the form DS_BASE_PATH/disk
# - host is the target host to deploy the VM
# - remote_system_ds is the path for the system datastore in the host
# - vmid is the id of the VM
# - dsid is the target datastore (0 is the system datastore)
SRC=$1
DST=$2
VMID=$3
DSID=$4
if [ -z "${ONE_LOCATION}" ]; then
TMCOMMON=/var/lib/one/remotes/tm/tm_common.sh
else
TMCOMMON=$ONE_LOCATION/var/remotes/tm/tm_common.sh
fi
. $TMCOMMON
#-------------------------------------------------------------------------------
# Move the image back to the datastore
#-------------------------------------------------------------------------------
log "Moving $SRC to datastore as $DST"
exec_and_log "$SCP -r $SRC $DST" "Error copying $SRC to $DST"
exit 0

1
src/tm_mad/vmfs/cpds Symbolic link
View File

@ -0,0 +1 @@
mvds

View File

@ -2431,7 +2431,7 @@ int VirtualMachine::generate_context(string &files, int &disk_id)
/* -------------------------------------------------------------------------- */
int VirtualMachine::get_image_from_disk(int disk_id, string& error_str)
int VirtualMachine::get_image_from_disk(int disk_id, bool hot, string& err_str)
{
int num_disks;
int tid;
@ -2473,7 +2473,7 @@ int VirtualMachine::get_image_from_disk(int disk_id, string& error_str)
goto error_saved;
}
if(!((disk->vector_value("PERSISTENT")).empty()))
if(!(disk->vector_value("PERSISTENT").empty()) && !hot)
{
goto error_persistent;
}
@ -2511,7 +2511,7 @@ error_not_found:
oss << "The DISK " << disk_id << " does not exist for VM " << oid << ".";
error_common:
error_str = oss.str();
err_str = oss.str();
return -1;
}
@ -2519,6 +2519,65 @@ error_common:
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachine::set_saveas_state()
{
switch (state)
{
case ACTIVE:
switch (lcm_state)
{
case RUNNING:
lcm_state = HOTPLUG_SAVEAS;
return 0;
default:
return -1;
}
break;
case POWEROFF:
state = ACTIVE;
lcm_state = HOTPLUG_SAVEAS_POWEROFF;
return 0;
case SUSPENDED:
state = ACTIVE;
lcm_state = HOTPLUG_SAVEAS_SUSPENDED;
return 0;
default:
return -1;
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachine::clear_saveas_state()
{
switch (lcm_state)
{
case HOTPLUG_SAVEAS:
lcm_state = RUNNING;
return 0;
case HOTPLUG_SAVEAS_POWEROFF:
state = POWEROFF;
lcm_state = LCM_INIT;
return 0;
case HOTPLUG_SAVEAS_SUSPENDED:
state = SUSPENDED;
lcm_state = LCM_INIT;
return 0;
default:
return -1;
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachine::save_disk(const string& disk_id,
const string& source,
int img_id)
@ -2526,18 +2585,16 @@ int VirtualMachine::save_disk(const string& disk_id,
vector<Attribute * > disks;
VectorAttribute * disk;
int num_disks;
string tdisk_id;
ostringstream oss;
int num_disks = obj_template->get("DISK",disks);
if ( state == DONE || state == FAILED )
if (lcm_state != HOTPLUG_SAVEAS && lcm_state != HOTPLUG_SAVEAS_SUSPENDED
&& lcm_state != HOTPLUG_SAVEAS_POWEROFF )
{
return -1;
}
num_disks = obj_template->get("DISK",disks);
for(int i=0; i<num_disks; i++)
{
disk = dynamic_cast<VectorAttribute * >(disks[i]);
@ -2553,8 +2610,7 @@ int VirtualMachine::save_disk(const string& disk_id,
{
disk->replace("SAVE_AS_SOURCE", source);
oss << (img_id);
disk->replace("SAVE_AS", oss.str());
disk->replace("SAVE_AS", img_id);
disk->replace("SAVE", "YES");
@ -2568,6 +2624,123 @@ int VirtualMachine::save_disk(const string& disk_id,
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachine::save_disk_hot(const string& disk_id,
const string& source,
int img_id)
{
int num_disks;
string tdisk_id;
vector<Attribute *> disks;
VectorAttribute * disk;
num_disks = obj_template->get("DISK", disks);
if (lcm_state != HOTPLUG_SAVEAS && lcm_state != HOTPLUG_SAVEAS_SUSPENDED
&& lcm_state != HOTPLUG_SAVEAS_POWEROFF )
{
return -1;
}
for(int i=0; i<num_disks; i++)
{
disk = dynamic_cast<VectorAttribute * >(disks[i]);
if ( disk == 0 )
{
continue;
}
tdisk_id = disk->vector_value("DISK_ID");
if ( tdisk_id == disk_id )
{
disk->replace("HOTPLUG_SAVEAS", "YES");
disk->replace("HOTPLUG_SAVEAS_IMAGE_ID", img_id);
disk->replace("HOTPLUG_SAVEAS_SOURCE", source);
break;
}
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachine::get_saveas_disk_hot(int& disk_id, string& source, int& image_id)
{
vector<Attribute *> disks;
VectorAttribute * disk;
int rc;
int num_disks;
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("HOTPLUG_SAVEAS") == "YES" )
{
source = disk->vector_value("HOTPLUG_SAVEAS_SOURCE");
rc = disk->vector_value("HOTPLUG_SAVEAS_IMAGE_ID", image_id);
rc += disk->vector_value("DISK_ID", disk_id);
if ( rc != 0 || source.empty() )
{
return -1;
}
return 0;
}
}
return -1;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachine::clear_saveas_disk_hot()
{
int num_disks;
vector<Attribute *> disks;
VectorAttribute * disk;
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("HOTPLUG_SAVEAS") == "YES" )
{
disk->remove("HOTPLUG_SAVEAS");
disk->remove("HOTPLUG_SAVEAS_IMAGE_ID");
disk->remove("HOTPLUG_SAVEAS_SOURCE");
return;
}
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachine::set_auth_request(int uid,
AuthRequest& ar,
VirtualMachineTemplate *tmpl)

View File

@ -81,7 +81,7 @@ int VMTemplate::insert(SqlDB *db, string& error_str)
// Check default attributes
// ---------------------------------------------------------------------
get_template_attribute("NAME", name);
erase_template_attribute("NAME", name);
if ( name.empty() == true )
{