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:
commit
89f6fb6380
@ -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.
|
||||
|
@ -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);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
|
@ -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);
|
||||
|
@ -152,7 +152,7 @@ public:
|
||||
VirtualMachineSaveDisk():
|
||||
RequestManagerVirtualMachine("VirtualMachineSaveDisk",
|
||||
"Saves a disk from virtual machine as a new image",
|
||||
"A:siiss"){};
|
||||
"A:siissb"){};
|
||||
|
||||
~VirtualMachineSaveDisk(){};
|
||||
|
||||
|
@ -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*/
|
||||
|
@ -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.
|
||||
|
16
install.sh
16
install.sh
@ -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"
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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
|
||||
|
@ -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}"
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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";
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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":
|
||||
|
@ -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;
|
||||
|
@ -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":
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
76
src/tm_mad/ceph/cpds
Executable 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
1
src/tm_mad/dummy/cpds
Symbolic link
@ -0,0 +1 @@
|
||||
../common/dummy.sh
|
92
src/tm_mad/iscsi/cpds
Executable file
92
src/tm_mad/iscsi/cpds
Executable 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
70
src/tm_mad/lvm/cpds
Executable 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
75
src/tm_mad/qcow2/cpds
Executable 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
83
src/tm_mad/shared/cpds
Executable 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
47
src/tm_mad/ssh/cpds
Executable 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
1
src/tm_mad/vmfs/cpds
Symbolic link
@ -0,0 +1 @@
|
||||
mvds
|
@ -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)
|
||||
|
@ -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 )
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user