mirror of
https://github.com/OpenNebula/one.git
synced 2025-01-10 01:17:40 +03:00
feature #1112: Save_as functionality
This commit is contained in:
parent
950ef37b69
commit
92dd8d4c5e
@ -39,6 +39,22 @@ public:
|
||||
DATABLOCK = 2 /** < User persistent data device */
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the string representation of an ImageType
|
||||
* @param ob the type
|
||||
* @return the string
|
||||
*/
|
||||
static string type_to_str(ImageType ob)
|
||||
{
|
||||
switch (ob)
|
||||
{
|
||||
case OS: return "OS" ; break;
|
||||
case CDROM: return "CDROM" ; break;
|
||||
case DATABLOCK: return "DATABLOCK" ; break;
|
||||
default: return "";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Image State
|
||||
*/
|
||||
@ -199,6 +215,17 @@ public:
|
||||
return (group_u == 1 || other_u == 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the image is used for saving_as a current one
|
||||
* @return true if the image will be used to save an existing image.
|
||||
*/
|
||||
bool isSaving()
|
||||
{
|
||||
ImageTemplate * it = static_cast<ImageTemplate *>(obj_template);
|
||||
|
||||
return it->is_saving();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set permissions for the Image. Extends the PoolSQLObject method
|
||||
* by checking the persistent state of the image.
|
||||
@ -291,7 +318,7 @@ public:
|
||||
/**
|
||||
* Factory method for image templates
|
||||
*/
|
||||
Template * get_new_template()
|
||||
Template * get_new_template() const
|
||||
{
|
||||
return new ImageTemplate;
|
||||
}
|
||||
@ -299,11 +326,19 @@ public:
|
||||
/**
|
||||
* Returns the Datastore ID
|
||||
*/
|
||||
int get_ds_id()
|
||||
int get_ds_id() const
|
||||
{
|
||||
return ds_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the Datastore ID
|
||||
*/
|
||||
const string& get_ds_name() const
|
||||
{
|
||||
return ds_name;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
@ -99,14 +99,8 @@ public:
|
||||
/**
|
||||
* Releases an image and triggers any needed operations in the repo
|
||||
* @param iid image id of the image to be released
|
||||
* @param disk_path base path for disk location
|
||||
* @param disk number for this image in the VM
|
||||
* @param saveid id of image to save the current image
|
||||
*/
|
||||
void release_image(const string& iid,
|
||||
const string& disk_path,
|
||||
int disk_num,
|
||||
const string& saveid)
|
||||
void release_image(const string& iid)
|
||||
{
|
||||
int image_id;
|
||||
istringstream iss;
|
||||
@ -114,30 +108,14 @@ public:
|
||||
iss.str(iid);
|
||||
iss >> image_id;
|
||||
|
||||
release_image(image_id, disk_path, disk_num, saveid);
|
||||
release_image(image_id);
|
||||
};
|
||||
|
||||
/**
|
||||
* Releases an image and triggers any needed operations in the repo
|
||||
* @param iid image id of the image to be released
|
||||
* @param disk_path base path for disk location
|
||||
* @param disk number for this image in the VM
|
||||
* @param saveid id of image to save the current image
|
||||
*/
|
||||
void release_image(int iid,
|
||||
const string& disk_path,
|
||||
int disk_num,
|
||||
const string& saveid);
|
||||
|
||||
/**
|
||||
* Moves a VM disk to the Image Repository
|
||||
* @param disk_path base path for disk location
|
||||
* @param disk number for this image in the VM
|
||||
* @param saveid id of image to save the current image
|
||||
*/
|
||||
void disk_to_image(const string& disk_path,
|
||||
int disk_num,
|
||||
const string& save_id);
|
||||
void release_image(int iid);
|
||||
|
||||
/**
|
||||
* Enables the image
|
||||
@ -205,9 +183,7 @@ private:
|
||||
* @param action the name of the action
|
||||
* @param arg arguments for the action function
|
||||
*/
|
||||
void do_action(
|
||||
const string & action,
|
||||
void * arg);
|
||||
void do_action(const string& action, void * arg);
|
||||
|
||||
/**
|
||||
* Acquires an image updating its state.
|
||||
@ -230,9 +206,7 @@ private:
|
||||
* @param ds_data Datastore XML representation
|
||||
* @return the XML message
|
||||
*/
|
||||
string * format_message(
|
||||
const string& img_data,
|
||||
const string& ds_data);
|
||||
string * format_message(const string& img_data, const string& ds_data);
|
||||
};
|
||||
|
||||
#endif /*IMAGE_MANAGER_H*/
|
||||
|
@ -41,11 +41,36 @@ public:
|
||||
return Template::check(rs_attr, restricted_attributes);
|
||||
};
|
||||
|
||||
bool is_saving()
|
||||
{
|
||||
string saving;
|
||||
|
||||
get(saving_attribute, saving);
|
||||
|
||||
return (saving.empty() == false);
|
||||
}
|
||||
|
||||
void set_saving()
|
||||
{
|
||||
SingleAttribute * attr= new SingleAttribute(saving_attribute, "YES");
|
||||
|
||||
erase(saving_attribute);
|
||||
|
||||
set(attr);
|
||||
}
|
||||
|
||||
void unset_saving()
|
||||
{
|
||||
erase(saving_attribute);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class ImagePool;
|
||||
|
||||
static vector<string> restricted_attributes;
|
||||
|
||||
static string saving_attribute;
|
||||
|
||||
/**
|
||||
* Stores the attributes as restricted, these attributes will be used in
|
||||
* ImageTemplate::check
|
||||
|
@ -48,8 +48,11 @@ protected:
|
||||
virtual void request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
RequestAttributes& att) = 0;
|
||||
|
||||
bool vm_authorization(int id, ImageTemplate *tmpl,
|
||||
RequestAttributes& att, PoolObjectAuth* host_perms);
|
||||
bool vm_authorization(int id,
|
||||
ImageTemplate * tmpl,
|
||||
RequestAttributes& att,
|
||||
PoolObjectAuth * host_perms,
|
||||
PoolObjectAuth * ds_perm);
|
||||
|
||||
int get_host_information(int hid, string& name, string& vmm, string& vnm,
|
||||
RequestAttributes& att, PoolObjectAuth& host_perms);
|
||||
|
@ -653,15 +653,27 @@ public:
|
||||
int generate_context(string &files);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Image repository related functions
|
||||
// Datastore related functions
|
||||
// ------------------------------------------------------------------------
|
||||
/**
|
||||
* Set the SAVE_AS attribute for the "disk_id"th disk.
|
||||
* @param disk_id Index of the disk to save
|
||||
* @param img_id ID of the image this disk will be saved to.
|
||||
* @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(int disk_id, int img_id, string& error_str);
|
||||
int save_disk(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.
|
||||
* @param disk_id Index of the disk to save
|
||||
* @param error_str describes the error
|
||||
* @return -1 if failure
|
||||
*/
|
||||
int get_image_from_disk(int disk_id, string& error_str);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Authorization related functions
|
||||
|
@ -96,6 +96,7 @@ int Image::insert(SqlDB *db, string& error_str)
|
||||
string dev_prefix;
|
||||
string source_attr;
|
||||
string aname;
|
||||
string saved_id;
|
||||
|
||||
ostringstream oss;
|
||||
|
||||
@ -159,34 +160,36 @@ int Image::insert(SqlDB *db, string& error_str)
|
||||
erase_template_attribute("PATH", path);
|
||||
erase_template_attribute("SOURCE", source);
|
||||
|
||||
// The template should contain PATH or SOURCE
|
||||
if ( source.empty() && path.empty() )
|
||||
if (!isSaving()) //Not a saving image
|
||||
{
|
||||
string size_attr;
|
||||
istringstream iss;
|
||||
|
||||
erase_template_attribute("SIZE", size_attr);
|
||||
erase_template_attribute("FSTYPE", fs_type);
|
||||
|
||||
// DATABLOCK image needs SIZE and FSTYPE
|
||||
if (type != DATABLOCK || size_attr.empty() || fs_type.empty())
|
||||
if ( source.empty() && path.empty() )
|
||||
{
|
||||
goto error_no_path;
|
||||
string size_attr;
|
||||
istringstream iss;
|
||||
|
||||
erase_template_attribute("SIZE", size_attr);
|
||||
erase_template_attribute("FSTYPE", fs_type);
|
||||
|
||||
// DATABLOCK image needs SIZE and FSTYPE
|
||||
if (type != DATABLOCK || size_attr.empty() || fs_type.empty())
|
||||
{
|
||||
goto error_no_path;
|
||||
}
|
||||
|
||||
iss.str(size_attr);
|
||||
|
||||
iss >> size_mb;
|
||||
|
||||
if (iss.fail() == true)
|
||||
{
|
||||
goto error_size_format;
|
||||
}
|
||||
}
|
||||
|
||||
iss.str(size_attr);
|
||||
|
||||
iss >> size_mb;
|
||||
|
||||
if (iss.fail() == true)
|
||||
else if ( !source.empty() && !path.empty() )
|
||||
{
|
||||
goto error_size_format;
|
||||
goto error_path_and_source;
|
||||
}
|
||||
}
|
||||
else if ( !source.empty() && !path.empty() )
|
||||
{
|
||||
goto error_path_and_source;
|
||||
}
|
||||
|
||||
state = LOCKED; //LOCKED till the ImageManager copies it to the Repository
|
||||
|
||||
|
@ -128,84 +128,14 @@ int ImageManager::acquire_image(Image *img, string& error)
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void ImageManager::move_image(Image *img, const string& source)
|
||||
{
|
||||
const ImageManagerDriver* imd = get();
|
||||
ostringstream oss;
|
||||
|
||||
if ( imd == 0 )
|
||||
{
|
||||
NebulaLog::log("ImM",Log::ERROR,
|
||||
"Could not get driver to update repository");
|
||||
return;
|
||||
}
|
||||
|
||||
oss << "Moving disk " << source << " to repository image "
|
||||
<< img->get_oid();
|
||||
|
||||
imd->mv(img->get_oid(),source,img->get_source());
|
||||
|
||||
NebulaLog::log("ImM",Log::INFO,oss);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void ImageManager::disk_to_image(const string& disk_path,
|
||||
int disk_num,
|
||||
const string& save_id)
|
||||
{
|
||||
int sid;
|
||||
|
||||
istringstream iss;
|
||||
Image * img;
|
||||
|
||||
ostringstream disk_file;
|
||||
|
||||
iss.str(save_id);
|
||||
|
||||
iss >> sid;
|
||||
|
||||
img = ipool->get(sid,true);
|
||||
|
||||
if ( img == 0 )
|
||||
{
|
||||
NebulaLog::log("ImM",Log::ERROR,"Could not get image to saveas disk.");
|
||||
}
|
||||
else
|
||||
{
|
||||
disk_file << disk_path << "/disk." << disk_num;
|
||||
|
||||
move_image(img,disk_file.str());
|
||||
}
|
||||
|
||||
img->unlock();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void ImageManager::release_image(int iid,
|
||||
const string& disk_path,
|
||||
int disk_num,
|
||||
const string& save_id)
|
||||
void ImageManager::release_image(int iid)
|
||||
{
|
||||
int rvms;
|
||||
|
||||
int sid = -1;
|
||||
|
||||
istringstream iss;
|
||||
Image * img;
|
||||
Image * img;
|
||||
|
||||
ostringstream disk_file;
|
||||
|
||||
if ( save_id.empty() == false )
|
||||
{
|
||||
iss.str(save_id);
|
||||
|
||||
iss >> sid;
|
||||
}
|
||||
|
||||
img = ipool->get(iid,true);
|
||||
|
||||
if ( img == 0 )
|
||||
@ -218,48 +148,14 @@ void ImageManager::release_image(int iid,
|
||||
case Image::USED:
|
||||
rvms = img->dec_running();
|
||||
|
||||
if ( img->isPersistent() && !disk_path.empty() )
|
||||
if ( img->isPersistent() || rvms == 0 )
|
||||
{
|
||||
disk_file << disk_path << "/disk." << disk_num;
|
||||
|
||||
img->set_state(Image::LOCKED);
|
||||
|
||||
move_image(img,disk_file.str());
|
||||
img->set_state(Image::READY);
|
||||
|
||||
ipool->update(img);
|
||||
|
||||
img->unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( rvms == 0)
|
||||
{
|
||||
img->set_state(Image::READY);
|
||||
}
|
||||
|
||||
ipool->update(img);
|
||||
|
||||
img->unlock();
|
||||
|
||||
if ( sid != -1 )
|
||||
{
|
||||
img = ipool->get(sid,true);
|
||||
|
||||
if ( img == 0 )
|
||||
{
|
||||
NebulaLog::log("ImM",Log::ERROR,
|
||||
"Could not get image to saveas disk.");
|
||||
}
|
||||
else
|
||||
{
|
||||
disk_file << disk_path << "/disk." << disk_num;
|
||||
|
||||
move_image(img,disk_file.str());
|
||||
}
|
||||
|
||||
img->unlock();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Image::DISABLED:
|
||||
@ -372,8 +268,7 @@ int ImageManager::delete_image(int iid, const string& ds_data)
|
||||
}
|
||||
|
||||
drv_msg = format_message(img->to_xml(img_tmpl), ds_data);
|
||||
|
||||
source = img->get_source();
|
||||
source = img->get_source();
|
||||
|
||||
if (source.empty())
|
||||
{
|
||||
@ -431,30 +326,25 @@ int ImageManager::register_image(int iid, const string& ds_data)
|
||||
drv_msg = format_message(img->to_xml(img_tmpl), ds_data);
|
||||
path = img->get_path();
|
||||
|
||||
if ( path.empty() == true ) //NO PATH -> USE SOURCE OR MKFS FOR DATABLOCK
|
||||
if ( path.empty() == true ) //NO PATH
|
||||
{
|
||||
if ( img->get_type() == Image::DATABLOCK)
|
||||
{
|
||||
string fs = img->get_fstype();
|
||||
int size = img->get_size();
|
||||
string source = img->get_source();
|
||||
|
||||
if ( img->isSaving() || img->get_type() == Image::DATABLOCK )
|
||||
{
|
||||
imd->mkfs(img->get_oid(), *drv_msg);
|
||||
|
||||
oss << "Creating disk at " << img->get_source() << " of "
|
||||
<< size << "Mb with format " << fs;
|
||||
oss << "Creating disk at " << source
|
||||
<< " of "<< img->get_size()
|
||||
<< "Mb (type: " << img->get_fstype() << ")";
|
||||
}
|
||||
else
|
||||
else if ( !source.empty() ) //Source in Template
|
||||
{
|
||||
string source = img->get_source();
|
||||
img->set_state(Image::READY);
|
||||
ipool->update(img);
|
||||
|
||||
if (source != "-") //SAVE_AS IMAGE DO NOT ENABLE THE IMAGE
|
||||
{
|
||||
img->set_state(Image::READY);
|
||||
ipool->update(img);
|
||||
|
||||
oss << "Using source " << img->get_source()
|
||||
<< " from template for image " << img->get_name();
|
||||
}
|
||||
oss << "Using source " << source
|
||||
<< " from template for image " << img->get_name();
|
||||
}
|
||||
}
|
||||
else //PATH -> COPY TO REPOSITORY AS SOURCE
|
||||
|
@ -179,40 +179,69 @@ void ImageManagerDriver::protocol(
|
||||
goto error_cp;
|
||||
}
|
||||
}
|
||||
else if ( action == "MV" )
|
||||
{
|
||||
if ( result == "SUCCESS" )
|
||||
{
|
||||
if (image->get_source() == "-")
|
||||
{
|
||||
image->set_source(source);
|
||||
}
|
||||
|
||||
image->set_size(size_mb);
|
||||
|
||||
image->set_state(Image::READY);
|
||||
|
||||
ipool->update(image);
|
||||
|
||||
NebulaLog::log("ImM", Log::INFO, "Image saved and ready to use.");
|
||||
}
|
||||
else
|
||||
{
|
||||
goto error_mv;
|
||||
}
|
||||
}
|
||||
else if ( action == "MKFS" )
|
||||
{
|
||||
if ( result == "SUCCESS" )
|
||||
{
|
||||
image->set_source(source);
|
||||
image->set_size(size_mb);
|
||||
bool is_saving = image->isSaving();
|
||||
|
||||
image->set_state(Image::READY);
|
||||
string disk_id;
|
||||
string vm_id;
|
||||
int rc;
|
||||
|
||||
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
|
||||
{
|
||||
image->set_size(size_mb);
|
||||
|
||||
image->set_state(Image::READY);
|
||||
|
||||
NebulaLog::log("ImM", Log::INFO,
|
||||
"Image created and ready to use");
|
||||
}
|
||||
|
||||
ipool->update(image);
|
||||
|
||||
NebulaLog::log("ImM", Log::INFO, "Image created and ready to use");
|
||||
image->unlock();
|
||||
|
||||
if (is_saving)
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
|
||||
VirtualMachinePool * vmpool = nd.get_vmpool();
|
||||
|
||||
VirtualMachine * vm;
|
||||
istringstream iss(vm_id);
|
||||
|
||||
int vm_id_i;
|
||||
|
||||
iss >> vm_id_i;
|
||||
|
||||
vm = vmpool->get(vm_id_i, true);
|
||||
|
||||
if ( vm == 0 )
|
||||
{
|
||||
goto error_save_no_vm;
|
||||
}
|
||||
|
||||
rc = vm->save_disk(disk_id, source, id);
|
||||
|
||||
if ( rc == -1 )
|
||||
{
|
||||
vm->unlock();
|
||||
goto error_save_state_vm;
|
||||
}
|
||||
|
||||
vm->unlock();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -255,11 +284,6 @@ error_cp:
|
||||
os << "Error copying image in the repository";
|
||||
goto error_common;
|
||||
|
||||
error_mv:
|
||||
os.str("");
|
||||
os << "Error saving image to the repository";
|
||||
goto error_common;
|
||||
|
||||
error_mkfs:
|
||||
os.str("");
|
||||
os << "Error creating datablock";
|
||||
@ -280,9 +304,28 @@ error_rm:
|
||||
}
|
||||
|
||||
NebulaLog::log("ImM", Log::ERROR, os);
|
||||
|
||||
return;
|
||||
|
||||
error_save_no_vm:
|
||||
os.str("");
|
||||
os << "Image created for SAVE_AS, but the associated VM does not exist.";
|
||||
|
||||
goto error_save_common;
|
||||
|
||||
error_save_state_vm:
|
||||
os.str("");
|
||||
os << "Image created for SAVE_AS, but VM is no longer running";
|
||||
|
||||
goto error_save_common;
|
||||
|
||||
error_save_common:
|
||||
image = ipool->get(id, true);
|
||||
|
||||
if (image == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
error_common:
|
||||
getline(is,info);
|
||||
|
||||
|
@ -21,5 +21,7 @@
|
||||
|
||||
vector<string> ImageTemplate::restricted_attributes;
|
||||
|
||||
string ImageTemplate::saving_attribute = "SAVE_AS";
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -24,7 +24,8 @@
|
||||
bool RequestManagerVirtualMachine::vm_authorization(int oid,
|
||||
ImageTemplate * tmpl,
|
||||
RequestAttributes& att,
|
||||
PoolObjectAuth * host_perm)
|
||||
PoolObjectAuth * host_perm,
|
||||
PoolObjectAuth * ds_perm)
|
||||
{
|
||||
PoolObjectSQL * object;
|
||||
PoolObjectAuth vm_perms;
|
||||
@ -57,13 +58,19 @@ bool RequestManagerVirtualMachine::vm_authorization(int oid,
|
||||
{
|
||||
ar.add_auth(AuthRequest::MANAGE, *host_perm);
|
||||
}
|
||||
else if (tmpl != 0)
|
||||
|
||||
if (tmpl != 0)
|
||||
{
|
||||
string t_xml;
|
||||
|
||||
ar.add_create_auth(PoolObjectSQL::IMAGE, tmpl->to_xml(t_xml));
|
||||
}
|
||||
|
||||
if ( ds_perm != 0 )
|
||||
{
|
||||
ar.add_auth(AuthRequest::USE, *ds_perm);
|
||||
}
|
||||
|
||||
if (UserPool::authorize(ar) == -1)
|
||||
{
|
||||
failure_response(AUTHORIZATION,
|
||||
@ -177,7 +184,7 @@ void VirtualMachineAction::request_execute(xmlrpc_c::paramList const& paramList,
|
||||
Nebula& nd = Nebula::instance();
|
||||
DispatchManager * dm = nd.get_dm();
|
||||
|
||||
if ( vm_authorization(id,0,att,0) == false )
|
||||
if ( vm_authorization(id, 0, att, 0, 0) == false )
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -282,7 +289,7 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList,
|
||||
return;
|
||||
}
|
||||
|
||||
auth = vm_authorization(id,0,att,&host_perms);
|
||||
auth = vm_authorization(id, 0, att, &host_perms, 0);
|
||||
|
||||
if ( auth == false )
|
||||
{
|
||||
@ -344,7 +351,7 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
|
||||
return;
|
||||
}
|
||||
|
||||
auth = vm_authorization(id,0,att,&host_perms);
|
||||
auth = vm_authorization(id, 0, att, &host_perms, 0);
|
||||
|
||||
if ( auth == false )
|
||||
{
|
||||
@ -394,8 +401,10 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
|
||||
void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramList,
|
||||
RequestAttributes& att)
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
ImagePool * ipool = nd.get_ipool();
|
||||
Nebula& nd = Nebula::instance();
|
||||
|
||||
ImagePool * ipool = nd.get_ipool();
|
||||
DatastorePool * dspool = nd.get_dspool();
|
||||
|
||||
int id = xmlrpc_c::value_int(paramList.getInt(1));
|
||||
int disk_id = xmlrpc_c::value_int(paramList.getInt(2));
|
||||
@ -403,24 +412,100 @@ void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramLis
|
||||
string img_type = xmlrpc_c::value_string(paramList.getString(4));
|
||||
|
||||
VirtualMachine * vm;
|
||||
string vm_owner;
|
||||
|
||||
int iid;
|
||||
ImageTemplate * itemplate;
|
||||
int iid_orig;
|
||||
|
||||
Image * img;
|
||||
Datastore * ds;
|
||||
|
||||
int rc;
|
||||
ostringstream oss;
|
||||
string error_str;
|
||||
|
||||
// ------------------ Template for the new image ------------------
|
||||
// -------------------------------------------------------------------------
|
||||
// Prepare and check the VM/DISK to be saved_as
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
if ( (vm = get_vm(id, att)) == 0 )
|
||||
{
|
||||
failure_response(NO_EXISTS,
|
||||
get_error(object_name(PoolObjectSQL::VM), id),
|
||||
att);
|
||||
return;
|
||||
}
|
||||
|
||||
oss << "NAME= \"" << img_name << "\"" << endl;
|
||||
oss << "PUBLIC = NO " << endl;
|
||||
oss << "SOURCE = - " << endl;
|
||||
oss << "SAVED_DISK_ID = " << disk_id << endl;
|
||||
oss << "SAVED_VM_ID = " << id << endl;
|
||||
iid_orig = vm->get_image_from_disk(disk_id, error_str);
|
||||
|
||||
if ( img_type != "" )
|
||||
pool->update(vm);
|
||||
|
||||
vm->unlock();
|
||||
|
||||
if ( iid_orig == -1 )
|
||||
{
|
||||
failure_response(INTERNAL,
|
||||
request_error("Can not used selected DISK", error_str),
|
||||
att);
|
||||
return;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Get the data of the Image to be saved
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
if ( (img = ipool->get(iid_orig, true)) != 0 )
|
||||
{
|
||||
failure_response(NO_EXISTS,
|
||||
get_error(object_name(PoolObjectSQL::IMAGE), iid_orig),
|
||||
att);
|
||||
return;
|
||||
}
|
||||
|
||||
int ds_id = img->get_ds_id();
|
||||
string ds_name = img->get_ds_name();
|
||||
int size = img->get_size();
|
||||
|
||||
Image::ImageType type = img->get_type();
|
||||
|
||||
img->unlock();
|
||||
|
||||
if ((ds = dspool->get(ds_id, true)) == 0 )
|
||||
{
|
||||
failure_response(NO_EXISTS,
|
||||
get_error(object_name(PoolObjectSQL::DATASTORE), ds_id),
|
||||
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->unlock();
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Create a template for the new Image
|
||||
// -------------------------------------------------------------------------
|
||||
ImageTemplate * itemplate;
|
||||
ostringstream oss;
|
||||
|
||||
oss << "NAME = \"" << img_name << "\"" << endl;
|
||||
oss << "PUBLIC = NO" << endl;
|
||||
oss << "SIZE = " << size << endl;
|
||||
oss << "FS_TYPE = save_as" << endl;
|
||||
|
||||
oss << "SAVED_IMAGE_ID = " << iid_orig << endl;
|
||||
oss << "SAVED_DISK_ID = " << disk_id << endl;
|
||||
oss << "SAVED_VM_ID = " << id << endl;
|
||||
|
||||
if ( img_type.empty() )
|
||||
{
|
||||
oss << "TYPE = " << Image::type_to_str(type) << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
oss << "TYPE = " << img_type << endl;
|
||||
}
|
||||
@ -429,24 +514,32 @@ void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramLis
|
||||
|
||||
itemplate->parse_str_or_xml(oss.str(), error_str);
|
||||
|
||||
// ------------------ Authorize the operation ------------------
|
||||
itemplate->set_saving();
|
||||
|
||||
if ( vm_authorization(id,itemplate,att,0) == false )
|
||||
// -------------------------------------------------------------------------
|
||||
// Authorize the operation
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
if ( vm_authorization(id, itemplate, att, 0, &ds_perms) == false )
|
||||
{
|
||||
delete itemplate;
|
||||
return;
|
||||
}
|
||||
|
||||
// ------------------ Create the image ------------------
|
||||
|
||||
// TODO: get values from source image DS
|
||||
int ds_id = 0;
|
||||
string ds_name = "";
|
||||
string ds_data = "";
|
||||
|
||||
rc = ipool->allocate(att.uid, att.gid, att.uname, att.gname, itemplate,
|
||||
ds_id, ds_name, ds_data, &iid, error_str);
|
||||
// -------------------------------------------------------------------------
|
||||
// Create the image
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
rc = ipool->allocate(att.uid,
|
||||
att.gid,
|
||||
att.uname,
|
||||
att.gname,
|
||||
itemplate,
|
||||
ds_id,
|
||||
ds_name,
|
||||
ds_data,
|
||||
&iid,
|
||||
error_str);
|
||||
if (rc < 0)
|
||||
{
|
||||
failure_response(INTERNAL,
|
||||
@ -454,50 +547,6 @@ void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramLis
|
||||
return;
|
||||
}
|
||||
|
||||
// ------------------ Store image id to save the disk ------------------
|
||||
|
||||
if ( (vm = get_vm(id, att)) == 0 )
|
||||
{
|
||||
Image * img;
|
||||
|
||||
if ( (img = ipool->get(iid,true)) != 0 )
|
||||
{
|
||||
string tmp_error;
|
||||
|
||||
ipool->drop(img, tmp_error);
|
||||
img->unlock();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
rc = vm->save_disk(disk_id, iid, error_str);
|
||||
|
||||
if ( rc == 0 )
|
||||
{
|
||||
pool->update(vm);
|
||||
}
|
||||
|
||||
vm->unlock();
|
||||
|
||||
if ( rc == -1 )
|
||||
{
|
||||
Image * img;
|
||||
|
||||
if ( (img = ipool->get(iid,true)) != 0 )
|
||||
{
|
||||
string tmp_error;
|
||||
|
||||
ipool->drop(img, tmp_error);
|
||||
img->unlock();
|
||||
}
|
||||
|
||||
failure_response(INTERNAL,
|
||||
request_error("Can not save_as disk",error_str),
|
||||
att);
|
||||
return;
|
||||
}
|
||||
|
||||
// Return the new allocated Image ID
|
||||
success_response(iid, att);
|
||||
}
|
||||
|
@ -790,26 +790,23 @@ void TransferManager::epilog_action(int vid)
|
||||
|
||||
tm_mad = disk->vector_value("TM_MAD");
|
||||
|
||||
if ( save == "YES" )
|
||||
if ( save == "YES" ) //TODO SAVE_SOURCE
|
||||
{
|
||||
ostringstream tsource;
|
||||
string source;
|
||||
string save_source;
|
||||
|
||||
source = disk->vector_value("SOURCE");
|
||||
source = disk->vector_value("SOURCE");
|
||||
save_source = disk->vector_value("SAVE_AS_SOURCE");
|
||||
|
||||
if ( source.empty() )
|
||||
if ( source.empty() && save_source.empty() )
|
||||
{
|
||||
vm->log("TM", Log::ERROR, "No SOURCE to save disk image");
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( source.find(":") == string::npos ) //Regular file
|
||||
if (!save_source.empty()) //Use the save as source instead
|
||||
{
|
||||
tsource << nd.get_nebula_hostname() << ":" << source << " ";
|
||||
}
|
||||
else //TM Plugin specific protocol
|
||||
{
|
||||
tsource << source << " ";
|
||||
source = save_source;
|
||||
}
|
||||
|
||||
//MVDS tm_mad hostname:remote_system_dir/disk.0 <fe:SOURCE|SOURCE>
|
||||
@ -817,7 +814,7 @@ void TransferManager::epilog_action(int vid)
|
||||
<< tm_mad << " "
|
||||
<< vm->get_hostname() << ":"
|
||||
<< vm->get_remote_system_dir() << "/disk." << i << " "
|
||||
<< tsource.str() << endl;
|
||||
<< source << endl;
|
||||
}
|
||||
else if ( !tm_mad.empty() ) //No saving disk and no system_ds disk
|
||||
{
|
||||
|
@ -824,9 +824,7 @@ error_common:
|
||||
|
||||
for ( it=acquired_images.begin() ; it < acquired_images.end(); it++ )
|
||||
{
|
||||
// Set disk_path and save_id to empty string, this way the image manager
|
||||
// won't try to move any files
|
||||
imagem->release_image(*it,"",-1,"");
|
||||
imagem->release_image(*it);
|
||||
}
|
||||
|
||||
return -1;
|
||||
@ -849,14 +847,7 @@ void VirtualMachine::release_disk_images()
|
||||
Nebula& nd = Nebula::instance();
|
||||
imagem = nd.get_imagem();
|
||||
|
||||
num_disks = get_template_attribute("DISK",disks);
|
||||
|
||||
if (hasHistory() != 0)
|
||||
{
|
||||
/*
|
||||
disk_base_path = get_local_dir();
|
||||
*/
|
||||
}
|
||||
num_disks = get_template_attribute("DISK",disks);
|
||||
|
||||
for(int i=0; i<num_disks; i++)
|
||||
{
|
||||
@ -868,19 +859,11 @@ void VirtualMachine::release_disk_images()
|
||||
continue;
|
||||
}
|
||||
|
||||
iid = disk->vector_value("IMAGE_ID");
|
||||
saveas = disk->vector_value("SAVE_AS");
|
||||
iid = disk->vector_value("IMAGE_ID");
|
||||
|
||||
if ( iid.empty() )
|
||||
if ( !iid.empty() )
|
||||
{
|
||||
if (!saveas.empty())
|
||||
{
|
||||
imagem->disk_to_image(disk_base_path,i,saveas);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
imagem->release_image(iid,disk_base_path,i,saveas);
|
||||
imagem->release_image(iid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1037,26 +1020,45 @@ int VirtualMachine::generate_context(string &files)
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachine::save_disk(int disk_id, int img_id, string& error_str)
|
||||
static int id_from_attr (VectorAttribute * attr, const char *name)
|
||||
{
|
||||
int num_disks;
|
||||
int id;
|
||||
string id_str;
|
||||
|
||||
id_str = attr->vector_value(name);
|
||||
|
||||
if (id_str.empty())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
istringstream iss(id_str);
|
||||
iss >> id;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachine::get_image_from_disk(int disk_id, string& error_str)
|
||||
{
|
||||
int num_disks;
|
||||
int tid;
|
||||
int iid = -1;
|
||||
|
||||
vector<Attribute * > disks;
|
||||
VectorAttribute * disk;
|
||||
|
||||
string disk_id_str;
|
||||
int tmp_disk_id;
|
||||
|
||||
ostringstream oss;
|
||||
istringstream iss;
|
||||
|
||||
num_disks = obj_template->get("DISK",disks);
|
||||
|
||||
if ( state == DONE || state == FAILED )
|
||||
{
|
||||
goto error_state;
|
||||
}
|
||||
|
||||
num_disks = obj_template->get("DISK",disks);
|
||||
|
||||
for(int i=0; i<num_disks; i++, iss.clear())
|
||||
for(int i=0; i<num_disks; i++)
|
||||
{
|
||||
disk = dynamic_cast<VectorAttribute * >(disks[i]);
|
||||
|
||||
@ -1065,12 +1067,9 @@ int VirtualMachine::save_disk(int disk_id, int img_id, string& error_str)
|
||||
continue;
|
||||
}
|
||||
|
||||
disk_id_str = disk->vector_value("DISK_ID");
|
||||
tid = id_from_attr(disk,"DISK_ID");
|
||||
|
||||
iss.str(disk_id_str);
|
||||
iss >> tmp_disk_id;
|
||||
|
||||
if ( tmp_disk_id == disk_id )
|
||||
if ( disk_id == tid )
|
||||
{
|
||||
if(!((disk->vector_value("SAVE_AS")).empty()))
|
||||
{
|
||||
@ -1082,12 +1081,16 @@ int VirtualMachine::save_disk(int disk_id, int img_id, string& error_str)
|
||||
goto error_persistent;
|
||||
}
|
||||
|
||||
iid = id_from_attr(disk, "IMAGE_ID");
|
||||
|
||||
if (iid == -1)
|
||||
{
|
||||
goto error_image_id;
|
||||
}
|
||||
|
||||
disk->replace("SAVE", "YES");
|
||||
|
||||
oss << (img_id);
|
||||
disk->replace("SAVE_AS", oss.str());
|
||||
|
||||
return 0;
|
||||
return iid;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1105,6 +1108,10 @@ error_saved:
|
||||
oss << "The DISK " << disk_id << " is already going to be saved.";
|
||||
goto error_common;
|
||||
|
||||
error_image_id:
|
||||
oss << "The DISK " << disk_id << "does not have a valid IMAGE_ID.";
|
||||
goto error_common;
|
||||
|
||||
error_not_found:
|
||||
oss << "The DISK " << disk_id << " does not exist for VM " << oid << ".";
|
||||
|
||||
@ -1117,6 +1124,53 @@ error_common:
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachine::save_disk(const string& disk_id,
|
||||
const string& source,
|
||||
int img_id)
|
||||
{
|
||||
vector<Attribute * > disks;
|
||||
VectorAttribute * disk;
|
||||
|
||||
int num_disks;
|
||||
string tdisk_id;
|
||||
|
||||
ostringstream oss;
|
||||
|
||||
if ( state == DONE || state == FAILED )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
tdisk_id = disk->vector_value("DISK_ID");
|
||||
|
||||
if ( tdisk_id == disk_id )
|
||||
{
|
||||
disk->replace("SAVE_AS_SOURCE", source);
|
||||
|
||||
oss << (img_id);
|
||||
disk->replace("SAVE_AS", oss.str());
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void VirtualMachine::set_auth_request(int uid,
|
||||
AuthRequest& ar,
|
||||
VirtualMachineTemplate *tmpl)
|
||||
|
Loading…
Reference in New Issue
Block a user