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

F #4393: More work on resize

This commit is contained in:
Ruben S. Montero 2016-12-15 21:12:33 +01:00
parent 178489ef11
commit c1c3d0479d
8 changed files with 516 additions and 29 deletions

View File

@ -347,6 +347,7 @@ public:
int id,
int nic_id,
string& error_str);
/**
* Starts the snapshot create action
*
@ -441,6 +442,21 @@ public:
int snap_id,
string& error_str);
/**
* Starts the disk resize create action
*
* @param vid VirtualMachine identification
* @param did DISK identification
* @param size new size for the disk
* @param error_str Error reason, if any
*
* @return 0 on success, -1 otherwise
*/
int disk_resize(
int vid,
int did,
long long new_size,
string& error_str);
private:
/**

View File

@ -483,4 +483,26 @@ public:
RequestAttributes& att);
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
class VirtualMachineDiskResize : public RequestManagerVirtualMachine
{
public:
VirtualMachineDiskResize():
RequestManagerVirtualMachine("VirtualMachineDiskResize",
"Resizes a disk from a virtual machine",
"A:siis"){
Nebula& nd = Nebula::instance();
ipool = nd.get_ipool();
};
~VirtualMachineDiskResize(){};
void request_execute(xmlrpc_c::paramList const& _paramList,
RequestAttributes& att);
private:
ImagePool* ipool;
};
#endif

View File

@ -412,6 +412,14 @@ public:
*/
virtual bool has_restricted();
/**
* @return true if template is empty
*/
bool empty()
{
return attributes.empty();
}
protected:
/**
* The template attributes

View File

@ -232,6 +232,32 @@ public:
*/
void delete_snapshot(int snap_id, Template **ds_quota, Template **vm_quota);
/* ---------------------------------------------------------------------- */
/* Disk space usage functions */
/* ---------------------------------------------------------------------- */
/**
* @return the space required by this disk in the system datastore
*/
long long system_ds_size();
/**
* Calculate the quotas for a resize operation on the disk
* @param new_size of disk
* @param dsdeltas increment in datastore usage
* @param vmdelta increment in system datastore usage
*/
void resize_quotas(long long new_size, Template& dsdelta, Template& vmdelta);
/**
* Compute the storage needed by the disk in the system and/or image
* datastore
* @param ds_id of the datastore
* @param img_sz size in image datastore needed
* @param sys_sz size in system datastore needed
*/
void datastore_sizes(int& ds_id, long long& img_sz, long long& sys_sz);
private:
Snapshots * snapshots;

View File

@ -2045,3 +2045,127 @@ int DispatchManager::disk_snapshot_delete(
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int DispatchManager::disk_resize(
int vid,
int did,
long long new_size,
string& error_str)
{
ostringstream oss;
time_t the_time;
VirtualMachine * vm = vmpool->get(vid, true);
if ( vm == 0 )
{
oss << "Could not resize disk for VM " << vid << ", VM does not exist" ;
error_str = oss.str();
NebulaLog::log("DiM", Log::ERROR, error_str);
return -1;
}
VirtualMachine::VmState state = vm->get_state();
VirtualMachine::LcmState lstate = vm->get_lcm_state();
if ((state !=VirtualMachine::POWEROFF || lstate !=VirtualMachine::LCM_INIT)&&
(state !=VirtualMachine::STOPPED || lstate !=VirtualMachine::LCM_INIT)&&
(state !=VirtualMachine::UNDEPLOYED || lstate !=VirtualMachine::LCM_INIT)&&
(state !=VirtualMachine::ACTIVE || lstate !=VirtualMachine::RUNNING))
{
oss << "Could not resize disk for VM " << vid << ", wrong state "
<< vm->state_str() << ".";
error_str = oss.str();
NebulaLog::log("DiM", Log::ERROR, error_str);
vm->unlock();
return -1;
}
// Set the VM info in the history before the disk is resized
vm->set_vm_info();
int rc = vm->set_up_resize_disk(did, new_size, error_str);
if (rc == -1)
{
vm->unlock();
return -1;
}
/*
switch(state)
{
case VirtualMachine::POWEROFF:
vm->set_state(VirtualMachine::ACTIVE);
vm->set_state(VirtualMachine::DISK_RESIZE_POWEROFF);
break;
case VirtualMachine::STOPPED:
vm->set_state(VirtualMachine::ACTIVE);
vm->set_state(VirtualMachine::DISK_RESIZE_STOPPED);
break;
case VirtualMachine::UNDEPLOYED:
vm->set_state(VirtualMachine::ACTIVE);
vm->set_state(VirtualMachine::DISK_RESIZE_UNDEPLOYED);
break;
case VirtualMachine::ACTIVE:
vm->set_state(VirtualMachine::ACTIVE);
vm->set_state(VirtualMachine::DISK_RESIZE);
break;
default: break;
}
vmpool->update(vm);
vm->unlock();
switch(state)
{
case VirtualMachine::POWEROFF:
case VirtualMachine::SUSPENDED:
tm->trigger(TransferManager::SNAPSHOT_CREATE,vid);
break;
case VirtualMachine::ACTIVE:
the_time = time(0);
// Close current history record
vm->set_running_etime(the_time);
vm->set_etime(the_time);
vm->set_action(History::DISK_SNAPSHOT_CREATE_ACTION);
vm->set_reason(History::USER);
vmpool->update_history(vm);
// Open a new history record
vm->cp_history();
vm->set_stime(the_time);
vm->set_running_stime(the_time);
vmpool->update_history(vm);
vmm->trigger(VirtualMachineManager::DISK_SNAPSHOT_CREATE, vid);
break;
default: break;
}
*/
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -1994,7 +1994,7 @@ void LifeCycleManager::disk_snapshot_success(int vid)
}
// Update image if it is persistent and ln mode does not clone it
if ( img_id != -1 && is_persistent && has_snaps && target != "SYSTEM" )
if ( img_id != -1 && is_persistent && has_snaps && target == "NONE" )
{
imagem->set_image_snapshots(img_id, snaps);
}

View File

@ -2888,3 +2888,188 @@ void VirtualMachineUpdateConf::request_execute(
vm->unlock();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineDiskResize::request_execute(
xmlrpc_c::paramList const& paramList,
RequestAttributes& att)
{
Nebula& nd = Nebula::instance();
DispatchManager * dm = nd.get_dm();
VirtualMachine * vm;
Template ds_deltas;
Template vm_deltas;
PoolObjectAuth vm_perms;
int id = xmlrpc_c::value_int(paramList.getInt(1));
int did = xmlrpc_c::value_int(paramList.getInt(2));
string size_s = xmlrpc_c::value_string(paramList.getString(3));
long long size , current_size;
// ------------------------------------------------------------------------
// Check request consistency (VM & disk exists, size, and no snapshots)
// ------------------------------------------------------------------------
istringstream iss(size_s);
iss >> size;
if (iss.fail() || !iss.eof())
{
att.resp_msg = "Disk SIZE is not a valid integer";
failure_response(ACTION, att);
return;
}
if ((vm = get_vm(id, att)) == 0)
{
return;
}
VirtualMachineDisk * disk =vm->get_disk(did);
if (disk == 0)
{
att.resp_msg = "VM disk does not exist";
failure_response(ACTION, att);
vm->unlock();
return;
}
disk->vector_value("SIZE", current_size);
if ( size <= current_size )
{
att.resp_msg = "New disk size has to be greater than current one";
failure_response(ACTION, att);
vm->unlock();
return;
}
if ( disk->has_snapshots() )
{
att.resp_msg = "Cannot resize a disk with snapshots";
failure_response(ACTION, att);
vm->unlock();
return;
}
/* ------------- Get information about the disk and image --------------- */
bool is_persistent = disk->is_persistent();
disk->resize_quotas(size, ds_deltas, vm_deltas);
int img_id = -1;
disk->vector_value("IMAGE_ID", img_id);
vm->get_permissions(vm_perms);
vm->unlock();
/* ---------------------------------------------------------------------- */
/* Authorize the request for VM and IMAGE for persistent disks */
/* ---------------------------------------------------------------------- */
RequestAttributes ds_att_quota;
RequestAttributes vm_att_quota;
if ( is_persistent )
{
PoolObjectAuth img_perms;
if ( img_id != -1 )
{
Image* img = ipool->get(img_id, true);
if (img == 0)
{
att.resp_obj = PoolObjectSQL::IMAGE;
att.resp_id = img_id;
failure_response(NO_EXISTS, att);
return;
}
img->get_permissions(img_perms);
img->unlock();
}
if (vm_authorization(id, 0, 0, att, 0, 0, &img_perms, auth_op) == false)
{
return;
}
ds_att_quota = RequestAttributes(img_perms.uid, img_perms.gid, att);
}
else
{
if ( vm_authorization(id, 0, 0, att, 0, 0, 0, auth_op) == false )
{
return;
}
ds_att_quota = RequestAttributes(vm_perms.uid, vm_perms.gid, att);
}
/* ---------------------------------------------------------------------- */
/* Check quotas for the new size in image/system datastoress */
/* ---------------------------------------------------------------------- */
if ( !ds_deltas.empty() )
{
if (!quota_authorization(&ds_deltas, Quotas::DATASTORE, ds_att_quota))
{
return;
}
}
if ( !vm_deltas.empty() )
{
if (!quota_resize_authorization(id, &vm_deltas, vm_att_quota))
{
if (!ds_deltas.empty())
{
quota_rollback(&ds_deltas, Quotas::DATASTORE, ds_att_quota);
}
return;
}
}
// ------------------------------------------------------------------------
// Do the snapshot
// ------------------------------------------------------------------------
int rc = dm->disk_resize(id, did, size, att.resp_msg);
if ( rc != 0 )
{
if ( !ds_deltas.empty() )
{
quota_rollback(&ds_deltas, Quotas::DATASTORE, ds_att_quota);
}
if ( !vm_deltas.empty() )
{
quota_rollback(&vm_deltas, Quotas::VM, vm_att_quota);
}
failure_response(ACTION, att);
}
else
{
success_response(did, att);
}
return;
}

View File

@ -316,6 +316,112 @@ void VirtualMachineDisk::delete_snapshot(int snap_id, Template **ds_quotas,
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
long long VirtualMachineDisk::system_ds_size()
{
long long disk_sz, snapshot_sz = 0;
if ( vector_value("SIZE", disk_sz) != 0 )
{
return 0;
}
//Volatile disks don't have snapshots
if (vector_value("DISK_SNAPSHOT_TOTAL_SIZE", snapshot_sz) == 0)
{
disk_sz += snapshot_sz;
}
if ( is_volatile() || get_tm_target() == "SYSTEM" )
{
return disk_sz;
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineDisk::resize_quotas(long long new_size, Template& ds_deltas,
Template& vm_deltas)
{
long long current_size, delta_size;
if ( vector_value("SIZE", current_size) != 0 )
{
return;
}
delta_size = new_size - current_size;
bool is_system = get_tm_target() == "SYSTEM";
string ds_id = vector_value("DATASTORE_ID");
if ( !is_volatile() && ( is_persistent() || !is_system ) )
{
ds_deltas.add("DATASTORE", ds_id);
ds_deltas.add("SIZE", delta_size);
ds_deltas.add("IMAGES", 0);
}
if ( is_volatile() || is_system )
{
VectorAttribute * delta_disk = new VectorAttribute("DISK");
delta_disk->replace("TYPE", "FS");
delta_disk->replace("SIZE", delta_size);
vm_deltas.add("VMS", 0);
vm_deltas.set(delta_disk);
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineDisk::datastore_sizes(int& ds_id, long long& image_sz,
long long& system_sz)
{
long long tmp_size, snapshot_size;
image_sz = 0;
system_sz = 0;
ds_id = -1;
if ( vector_value("SIZE", tmp_size) != 0 )
{
return;
}
if ( vector_value("DISK_SNAPSHOT_TOTAL_SIZE", snapshot_size) == 0 )
{
tmp_size += snapshot_size;
}
if ( is_volatile() )
{
system_sz = tmp_size;
return;
}
else
{
string target = get_tm_target();
if ( target == "SYSTEM" )
{
system_sz = tmp_size;
}
else if ( target == "SELF" )
{
vector_value("DATASTORE_ID", ds_id);
image_sz = tmp_size;
}// else if ( target == "NONE" )
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
@ -341,26 +447,7 @@ long long VirtualMachineDisks::system_ds_size()
for ( disk_iterator disk = begin() ; disk != end() ; ++disk )
{
long long tmp_size;
if ( (*disk)->vector_value("SIZE", tmp_size) != 0 )
{
continue;
}
if ( (*disk)->is_volatile() )
{
size += tmp_size;
}
else if ( (*disk)->get_tm_target() == "SYSTEM" )
{
size += tmp_size;
if ((*disk)->vector_value("DISK_SNAPSHOT_TOTAL_SIZE",tmp_size) == 0)
{
size += tmp_size;
}
}
size += (*disk)->system_ds_size();
}
return size;
@ -373,6 +460,33 @@ long long VirtualMachineDisks::system_ds_size(Template * ds_tmpl)
return disks.system_ds_size();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/*
void VirtualMachineDisks::image_ds_size(bool resize_snapshot, long long system,
std::map<int, long long>& ds_size) const
{
int ds_id;
long long system_sz, image_sz;
for ( disk_iterator disk = begin() ; disk != end() ; ++disk )
{
(*disk)->ds_size(resize_snapshot, ds_id, image_sz, system_sz);
system += system_sz;
if ( ds_id != -1 && image_sz > 0 )
{
if (ds_size.count(ds_id) == 0)
{
ds_size[ds_id] = 0;
}
ds_size[ds_id] += image_sz;
}
}
}
*/
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
@ -418,14 +532,6 @@ bool VirtualMachineDisks::volatile_info(int ds_id)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineDisks::image_ds_size(std::map<int, long long>& ds_size) const
{
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineDisks::get_image_ids(set<int>& ids, int uid)
{
int id;