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

Feature #4400: Allow VMs to use Images in the locked state

This commit is contained in:
Carlos Martín 2016-04-18 17:44:47 +02:00
parent 9a440e558c
commit 7855ebd22d
21 changed files with 498 additions and 43 deletions

View File

@ -132,7 +132,9 @@ public:
ERROR = 5, /** < Error state the operation FAILED*/
CLONE = 6, /** < Image is being cloned */
DELETE = 7, /** < DS is deleting the image */
USED_PERS = 8 /** < Image is in use and persistent */
USED_PERS = 8, /** < Image is in use and persistent */
LOCKED_USED = 9, /** < FS operation in progress, VMs waiting */
LOCKED_USED_PERS = 10 /** < FS operation in progress, VMs waiting. Persistent */
};
/**
@ -144,16 +146,18 @@ public:
{
switch(state)
{
case INIT: return "INIT"; break;
case READY: return "READY"; break;
case USED: return "USED"; break;
case DISABLED: return "DISABLED"; break;
case LOCKED: return "LOCKED"; break;
case ERROR: return "ERROR"; break;
case CLONE: return "CLONE"; break;
case DELETE: return "DELETE"; break;
case USED_PERS: return "USED"; break;
default: return "";
case INIT: return "INIT"; break;
case READY: return "READY"; break;
case USED: return "USED"; break;
case DISABLED: return "DISABLED"; break;
case LOCKED: return "LOCKED"; break;
case ERROR: return "ERROR"; break;
case CLONE: return "CLONE"; break;
case DELETE: return "DELETE"; break;
case USED_PERS: return "USED"; break;
case LOCKED_USED: return "LOCKED_USED"; break;
case LOCKED_USED_PERS: return "LOCKED_USED"; break;
default: return "";
}
};
@ -259,10 +263,12 @@ public:
* Sets the image state
* @param state of image
*/
void set_state(ImageState _state)
{
state = _state;
}
void set_state(ImageState _state);
/**
* Moves the image from the locked* states to ready, used, used_persistent
*/
void set_state_unlock();
/**
* Return the ID of the image we are cloning this one from (if any)
@ -317,6 +323,11 @@ public:
return running_vms;
}
set<int> get_running_ids() const
{
return vm_collection.clone();
}
int get_cloning() const
{
return cloning_ops;
@ -403,6 +414,8 @@ public:
case USED:
case CLONE:
case USED_PERS:
case LOCKED_USED:
case LOCKED_USED_PERS:
oss << "Image cannot be in state " << state_to_str(state) <<".";
error_str = oss.str();
return -1;

View File

@ -105,7 +105,9 @@ public:
DELETE, /**< Sent by the DM to delete a VM */
CLEAN, /**< Sent by the DM to cleanup a VM for resubmission*/
FINALIZE,
UPDATESG /**< Sent by RM/VMM to trigger the secgroup update */
UPDATESG, /**< Sent by RM/VMM to trigger the secgroup update */
DISK_LOCK_SUCCESS, /**< Sent by IM when an image moves from locked to ready */
DISK_LOCK_FAILURE, /**< Sent by IM when an image moves from locked to error */
};
/**
@ -303,6 +305,10 @@ private:
void disk_snapshot_failure(int vid);
void disk_lock_success(int vid);
void disk_lock_failure(int vid);
void deploy_action(int vid);
void suspend_action(int vid);

View File

@ -220,6 +220,8 @@ public:
int replace(const string& name, const string& value);
int replace(const string& name, const bool& value);
/**
* Adds a new single attribute to the template. It will replace an existing
* one if replace_mode was set to true

View File

@ -63,7 +63,8 @@ public:
DONE = 6,
//FAILED = 7,
POWEROFF = 8,
UNDEPLOYED = 9
UNDEPLOYED = 9,
CLONING = 10
};
static int vm_state_from_str(string& st, VmState& state)
@ -79,6 +80,7 @@ public:
else if ( st == "DONE" ) { state = DONE; }
else if ( st == "POWEROFF" ) { state = POWEROFF; }
else if ( st == "UNDEPLOYED" ) { state = UNDEPLOYED; }
else if ( st == "CLONING" ) { state = CLONING; }
else {return -1;}
return 0;
@ -97,6 +99,7 @@ public:
case DONE : st = "DONE"; break;
case POWEROFF : st = "POWEROFF"; break;
case UNDEPLOYED: st = "UNDEPLOYED"; break;
case CLONING : st = "CLONING"; break;
}
return st;
@ -1616,6 +1619,27 @@ public:
*/
void delete_snapshots();
// ------------------------------------------------------------------------
// Cloning state related functions
// ------------------------------------------------------------------------
/**
* Returns true if any of the disks is waiting for an image in LOCKED state
* @return true if cloning
*/
bool has_cloning_disks();
/**
* Returns the image IDs for the disks waiting for the LOCKED state to finish
* @return image IDs
*/
set<int> get_cloning_image_ids();
/**
* Clears the flag for the disks waiting for the given image
*/
void clear_cloning_image_id(int image_id);
private:
// -------------------------------------------------------------------------

View File

@ -865,6 +865,7 @@ int DispatchManager::finalize(
case VirtualMachine::INIT:
case VirtualMachine::PENDING:
case VirtualMachine::HOLD:
case VirtualMachine::CLONING:
finalize_cleanup(vm);
break;
@ -920,6 +921,7 @@ int DispatchManager::resubmit(
case VirtualMachine::INIT:
case VirtualMachine::PENDING:
case VirtualMachine::CLONING:
break;
case VirtualMachine::STOPPED:

View File

@ -28,6 +28,8 @@
#include "AuthManager.h"
#include "UserPool.h"
#include "NebulaUtil.h"
#include "LifeCycleManager.h"
#include "Nebula.h"
#define TO_UPPER(S) transform(S.begin(),S.end(),S.begin(),(int(*)(int))toupper)
@ -816,3 +818,79 @@ Image::DiskType Image::str_to_disk_type(string& s_disk_type)
return type;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
void Image::set_state(ImageState _state)
{
if (_state == ERROR && (state == LOCKED_USED || state == LOCKED_USED_PERS))
{
LifeCycleManager* lcm = Nebula::instance().get_lcm();
set<int>::iterator i;
for(i = vm_collection.get_collection().begin();
i != vm_collection.get_collection().end(); i++)
{
lcm->trigger(LifeCycleManager::DISK_LOCK_FAILURE, *i);
}
}
state = _state;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
void Image::set_state_unlock()
{
LifeCycleManager* lcm = Nebula::instance().get_lcm();
set<int> vms_notify;
switch (state) {
case LOCKED:
set_state(READY);
break;
case LOCKED_USED:
set_state(USED);
vms_notify = vm_collection.clone();
break;
case Image::LOCKED_USED_PERS:
set_state(USED_PERS);
vms_notify = vm_collection.clone();
break;
case Image::ERROR:
if (running_vms == 0)
{
set_state(READY);
}
else
{
if(is_persistent())
{
set_state(USED_PERS);
}
else
{
set_state(USED);
}
vms_notify = vm_collection.clone();
}
break;
default:
break;
}
for(set<int>::iterator i = vms_notify.begin(); i != vms_notify.end(); i++)
{
lcm->trigger(LifeCycleManager::DISK_LOCK_SUCCESS, *i);
}
}

View File

@ -125,7 +125,23 @@ int ImageManager::acquire_image(int vm_id, Image *img, string& error)
ipool->update(img);
break;
case Image::LOCKED:
img->inc_running(vm_id);
if ( img->is_persistent() )
{
img->set_state(Image::LOCKED_USED_PERS);
}
else
{
img->set_state(Image::LOCKED_USED);
}
ipool->update(img);
break;
case Image::USED_PERS:
case Image::LOCKED_USED_PERS:
oss << "Cannot acquire image " << img->get_oid()
<< ", it is persistent and already in use";
@ -134,13 +150,13 @@ int ImageManager::acquire_image(int vm_id, Image *img, string& error)
break;
case Image::USED:
case Image::LOCKED_USED:
img->inc_running(vm_id);
ipool->update(img);
break;
case Image::INIT:
case Image::DISABLED:
case Image::LOCKED:
case Image::ERROR:
case Image::DELETE:
case Image::CLONE:
@ -204,6 +220,23 @@ void ImageManager::release_image(int vm_id, int iid, bool failed)
img->unlock();
break;
case Image::LOCKED_USED_PERS:
img->dec_running(vm_id);
if (failed == true)
{
img->set_state(Image::ERROR);
}
else
{
img->set_state(Image::LOCKED);
}
ipool->update(img);
img->unlock();
break;
case Image::USED:
if ( img->dec_running(vm_id) == 0 && img->get_cloning() == 0 )
{
@ -215,6 +248,17 @@ void ImageManager::release_image(int vm_id, int iid, bool failed)
img->unlock();
break;
case Image::LOCKED_USED:
if ( img->dec_running(vm_id) == 0 && img->get_cloning() == 0 )
{
img->set_state(Image::LOCKED);
}
ipool->update(img);
img->unlock();
break;
case Image::LOCKED:
oss << "Releasing image in wrong state: "
<< Image::state_to_str(img->get_state());
@ -288,6 +332,8 @@ void ImageManager::release_cloning_resource(
case Image::ERROR:
case Image::USED_PERS:
case Image::LOCKED:
case Image::LOCKED_USED:
case Image::LOCKED_USED_PERS:
NebulaLog::log("ImM", Log::ERROR, "Release cloning image"
" in wrong state");
break;
@ -318,9 +364,13 @@ int ImageManager::enable_image(int iid, bool to_enable, string& error_str)
switch (img->get_state())
{
case Image::DISABLED:
case Image::ERROR:
img->set_state(Image::READY);
ipool->update(img);
break;
case Image::ERROR:
img->set_state_unlock();
ipool->update(img);
break;
case Image::READY:
break;
default:
@ -340,6 +390,7 @@ int ImageManager::enable_image(int iid, bool to_enable, string& error_str)
case Image::ERROR:
img->set_state(Image::DISABLED);
ipool->update(img);
break;
case Image::DISABLED:
break;
default:
@ -435,6 +486,8 @@ int ImageManager::delete_image(int iid, string& error_str)
case Image::USED:
case Image::USED_PERS:
case Image::LOCKED_USED:
case Image::LOCKED_USED_PERS:
oss << "There are " << img->get_running() << " VMs using it.";
error_str = oss.str();
@ -585,6 +638,8 @@ int ImageManager::can_clone_image(int cloning_id, ostringstream& oss_error)
case Image::ERROR:
case Image::DELETE:
case Image::LOCKED:
case Image::LOCKED_USED:
case Image::LOCKED_USED_PERS:
oss_error << "Cannot clone image in state: "
<< Image::state_to_str(state);
@ -644,6 +699,8 @@ int ImageManager::set_clone_state(
case Image::ERROR:
case Image::DELETE:
case Image::LOCKED:
case Image::LOCKED_USED:
case Image::LOCKED_USED_PERS:
error = "Cannot clone image in current state";
rc = -1;
break;
@ -760,7 +817,7 @@ int ImageManager::register_image(int iid,
}
else if ( !source.empty() ) //Source in Template
{
img->set_state(Image::READY);
img->set_state_unlock();
ipool->update(img);
oss << "Using source " << source

View File

@ -223,7 +223,7 @@ static int cp_action(istringstream& is,
image->set_source(source);
image->set_state(Image::READY);
image->set_state_unlock();
ipool->update(image);
@ -320,7 +320,7 @@ static int clone_action(istringstream& is,
image->set_source(source);
image->set_state(Image::READY);
image->set_state_unlock();
image->clear_cloning_id();
@ -444,7 +444,7 @@ static int mkfs_action(istringstream& is,
if (!is_saving)
{
image->set_state(Image::READY);
image->set_state_unlock();
}
ipool->update(image);
@ -711,7 +711,7 @@ static void snap_delete_action(istringstream& is,
return;
}
image->set_state(Image::READY);
image->set_state_unlock();
int snap_id = image->get_target_snapshot();
@ -787,7 +787,7 @@ static void snap_revert_action(istringstream& is,
int snap_id = image->get_target_snapshot();
image->set_state(Image::READY);
image->set_state_unlock();
if (snap_id == -1)
{
@ -871,7 +871,7 @@ static void snap_flatten_action(istringstream& is,
NebulaLog::log("ImM", Log::ERROR, oss);
}
image->set_state(Image::READY);
image->set_state_unlock();
image->clear_target_snapshot();

View File

@ -437,6 +437,11 @@ int ImagePool::acquire_disk(int vm_id,
(*snap)->set_disk_id(disk_id);
}
if (img->get_state() == Image::LOCKED_USED || img->get_state() == Image::LOCKED_USED_PERS)
{
disk->replace("CLONING", "YES");
}
img->unlock();
if ( ds_pool->disk_attribute(datastore_id, disk) == -1 )

View File

@ -301,6 +301,14 @@ void LifeCycleManager::trigger(Actions action, int _vid)
aname = "UPDATESG";
break;
case DISK_LOCK_SUCCESS:
aname = "DISK_LOCK_SUCCESS";
break;
case DISK_LOCK_FAILURE:
aname = "DISK_LOCK_FAILURE";
break;
default:
delete vid;
return;
@ -534,6 +542,14 @@ void LifeCycleManager::do_action(const string &action, void * arg)
{
updatesg_action(vid);
}
else if (action == "DISK_LOCK_SUCCESS")
{
disk_lock_success(vid);
}
else if (action == "DISK_LOCK_FAILURE")
{
disk_lock_failure(vid);
}
else if (action == ACTION_FINALIZE)
{
NebulaLog::log("LCM",Log::INFO,"Stopping Life-cycle Manager...");

View File

@ -1734,7 +1734,7 @@ void LifeCycleManager::saveas_success_action(int vid)
return;
}
image->set_state(Image::READY);
image->set_state_unlock();
ipool->update(image);
@ -2071,3 +2071,106 @@ void LifeCycleManager::disk_snapshot_failure(int vid)
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void LifeCycleManager::disk_lock_success(int vid)
{
VirtualMachine * vm = vmpool->get(vid,true);
Image * image;
if ( vm == 0 )
{
return;
}
if ( vm->get_state() != VirtualMachine::CLONING )
{
//vm->log("LCM",Log::ERROR,"disk_lock_success, VM in a wrong state");
vm->unlock();
return;
}
set<int> ids = vm->get_cloning_image_ids();
vm->unlock();
set<int> ready;
set<int> error;
for (set<int>::iterator id = ids.begin(); id != ids.end(); id++)
{
image = ipool->get(*id, true);
if (image != 0)
{
switch (image->get_state()) {
case Image::USED:
case Image::USED_PERS:
ready.insert(*id);
break;
case Image::ERROR:
error.insert(*id);
break;
case Image::INIT:
case Image::READY:
case Image::DISABLED:
case Image::LOCKED:
case Image::CLONE:
case Image::DELETE:
case Image::LOCKED_USED:
case Image::LOCKED_USED_PERS:
break;
}
image->unlock();
}
}
vm = vmpool->get(vid,true);
if (vm == 0)
{
return;
}
for (set<int>::iterator id = ready.begin(); id != ready.end(); id++)
{
vm->clear_cloning_image_id(*id);
}
if (ids.size() == ready.size())
{
bool on_hold = false;
vm->get_template_attribute("SUBMIT_ON_HOLD", on_hold);
if(on_hold)
{
vm->set_state(VirtualMachine::HOLD);
}
else
{
vm->set_state(VirtualMachine::PENDING);
}
}
else if (error.size() > 0)
{
// TODO
//vm->set_state(VirtualMachine::CLONING_FAILURE);
}
vmpool->update(vm);
vm->unlock();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void LifeCycleManager::disk_lock_failure(int vid)
{
disk_lock_success(vid);
}

View File

@ -45,10 +45,12 @@ public class Image extends PoolElement
private static final String[] IMAGE_STATES =
{"INIT", "READY", "USED", "DISABLED", "LOCKED",
"ERROR", "CLONE", "DELETE", "USED_PERS"};
"ERROR", "CLONE", "DELETE", "USED_PERS",
"LOCKED_USED", "LOCKED_USED_PERS"};
private static final String[] SHORT_IMAGE_STATES =
{"init", "rdy", "used", "disa", "lock", "err", "clon", "dele", "used"};
{"init", "rdy", "used", "disa", "lock", "err", "clon", "dele", "used",
"lock", "lock"};
private static final String[] IMAGE_TYPES =
{"OS", "CDROM", "DATABLOCK", "KERNEL", "RAMDISK", "CONTEXT"};

View File

@ -63,7 +63,8 @@ public class VirtualMachine extends PoolElement{
"DONE",
"FAILED",
"POWEROFF",
"UNDEPLOYED" };
"UNDEPLOYED",
"CLONING" };
private static final String[] SHORT_VM_STATES =
{
@ -76,7 +77,8 @@ public class VirtualMachine extends PoolElement{
"done",
"fail",
"poff",
"unde" };
"unde",
"clon" };
private static final String[] LCM_STATE =
{

View File

@ -41,7 +41,8 @@ module OpenNebula
:snapshotflatten=> "image.snapshotflatten"
}
IMAGE_STATES=%w{INIT READY USED DISABLED LOCKED ERROR CLONE DELETE USED_PERS}
IMAGE_STATES=%w{INIT READY USED DISABLED LOCKED ERROR CLONE DELETE
USED_PERS LOCKED_USED LOCKED_USED_PERS}
SHORT_IMAGE_STATES={
"INIT" => "init",
@ -52,7 +53,9 @@ module OpenNebula
"ERROR" => "err",
"CLONE" => "clon",
"DELETE" => "dele",
"USED_PERS" => "used"
"USED_PERS" => "used",
"LOCKED_USED" => "lock",
"LOCKED_USED_PERS" => "lock"
}
IMAGE_TYPES=%w{OS CDROM DATABLOCK KERNEL RAMDISK CONTEXT}

View File

@ -50,7 +50,7 @@ module OpenNebula
}
VM_STATE=%w{INIT PENDING HOLD ACTIVE STOPPED SUSPENDED DONE FAILED
POWEROFF UNDEPLOYED}
POWEROFF UNDEPLOYED CLONING}
LCM_STATE=%w{
LCM_INIT
@ -126,7 +126,8 @@ module OpenNebula
"DONE" => "done",
"FAILED" => "fail",
"POWEROFF" => "poff",
"UNDEPLOYED"=> "unde"
"UNDEPLOYED"=> "unde",
"CLONING" => "clon"
}
SHORT_LCM_STATES={

View File

@ -1930,6 +1930,7 @@ void VirtualMachineResize::request_execute(xmlrpc_c::paramList const& paramList,
case VirtualMachine::PENDING:
case VirtualMachine::HOLD:
case VirtualMachine::UNDEPLOYED:
case VirtualMachine::CLONING:
break;
case VirtualMachine::STOPPED:
@ -2049,6 +2050,7 @@ void VirtualMachineResize::request_execute(xmlrpc_c::paramList const& paramList,
case VirtualMachine::HOLD:
case VirtualMachine::POWEROFF:
case VirtualMachine::UNDEPLOYED:
case VirtualMachine::CLONING:
ret = vm->resize(ncpu, nmemory, nvcpu, att.resp_msg);
if (ret != 0)

View File

@ -32,7 +32,8 @@ define(function(require) {
"DONE",
"FAILED",
"POWEROFF",
"UNDEPLOYED"
"UNDEPLOYED",
"CLONING"
];
var STATES = {
@ -45,7 +46,8 @@ define(function(require) {
DONE : 6,
//FAILED : 7,
POWEROFF : 8,
UNDEPLOYED : 9
UNDEPLOYED : 9,
CLONING : 10
};
var LCM_STATES_STR = [

View File

@ -988,11 +988,15 @@ define(function(require) {
var state_str;
switch (state) {
case OpenNebulaVM.STATES.CLONING:
state_color = 'deploying';
state_str = Locale.tr("DEPLOYING") + " (1/4)";
break;
case OpenNebulaVM.STATES.INIT:
case OpenNebulaVM.STATES.PENDING:
case OpenNebulaVM.STATES.HOLD:
state_color = 'deploying';
state_str = Locale.tr("DEPLOYING") + " (1/3)";
state_str = Locale.tr("DEPLOYING") + " (2/4)";
break;
case OpenNebulaVM.STATES.ACTIVE:
var lcm_state = parseInt(data.LCM_STATE);
@ -1000,13 +1004,13 @@ define(function(require) {
switch (lcm_state) {
case OpenNebulaVM.LCM_STATES.LCM_INIT:
state_color = 'deploying';
state_str = Locale.tr("DEPLOYING") + " (1/3)";
state_str = Locale.tr("DEPLOYING") + " (2/4)";
break;
case OpenNebulaVM.LCM_STATES.PROLOG:
case OpenNebulaVM.LCM_STATES.PROLOG_RESUME:
case OpenNebulaVM.LCM_STATES.PROLOG_UNDEPLOY:
state_color = 'deploying';
state_str = Locale.tr("DEPLOYING") + " (2/3)";
state_str = Locale.tr("DEPLOYING") + " (3/4)";
break;
case OpenNebulaVM.LCM_STATES.BOOT:
case OpenNebulaVM.LCM_STATES.BOOT_UNKNOWN:
@ -1015,7 +1019,7 @@ define(function(require) {
case OpenNebulaVM.LCM_STATES.BOOT_STOPPED:
case OpenNebulaVM.LCM_STATES.BOOT_UNDEPLOY:
state_color = 'deploying';
state_str = Locale.tr("DEPLOYING") + " (3/3)";
state_str = Locale.tr("DEPLOYING") + " (4/4)";
break;
case OpenNebulaVM.LCM_STATES.RUNNING:
case OpenNebulaVM.LCM_STATES.HOTPLUG_SNAPSHOT:

View File

@ -264,6 +264,47 @@ int Template::replace(const string& name, const string& value)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Template::replace(const string& name, const bool& value)
{
string s_val;
pair<multimap<string, Attribute *>::iterator,
multimap<string, Attribute *>::iterator> index;
index = attributes.equal_range(name);
if (index.first != index.second )
{
multimap<string, Attribute *>::iterator i;
for ( i = index.first; i != index.second; i++)
{
Attribute * attr = i->second;
delete attr;
}
attributes.erase(index.first, index.second);
}
if (value)
{
s_val = "YES";
}
else
{
s_val = "NO";
}
SingleAttribute * sattr = new SingleAttribute(name, s_val);
attributes.insert(make_pair(sattr->name(), sattr));
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Template::erase(const string& name)
{
multimap<string, Attribute *>::iterator i;

View File

@ -472,6 +472,20 @@ int VirtualMachine::insert(SqlDB * db, string& error_str)
goto error_leases_rollback;
}
bool on_hold;
if (user_obj_template->get("SUBMIT_ON_HOLD", on_hold) == true)
{
user_obj_template->erase("SUBMIT_ON_HOLD");
obj_template->replace("SUBMIT_ON_HOLD", on_hold);
}
if ( has_cloning_disks())
{
state = VirtualMachine::CLONING;
}
// ------------------------------------------------------------------------
// PCI Devices
// ------------------------------------------------------------------------
@ -2082,6 +2096,83 @@ error_common:
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
bool VirtualMachine::has_cloning_disks()
{
bool cloning;
vector<VectorAttribute *> disks;
int num_disks = obj_template->get("DISK", disks);
for(int i=0; i < num_disks; i++)
{
disks[i]->vector_value("CLONING", cloning);
if (cloning)
{
return true;
}
}
return false;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
set<int> VirtualMachine::get_cloning_image_ids()
{
set<int> ids;
bool cloning;
int image_id;
vector<VectorAttribute *> disks;
int num_disks = obj_template->get("DISK", disks);
for(int i=0; i < num_disks; i++)
{
disks[i]->vector_value("CLONING", cloning);
if (cloning && (disks[i]->vector_value("IMAGE_ID", image_id) == 0) )
{
ids.insert(image_id);
}
}
return ids;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachine::clear_cloning_image_id(int image_id)
{
bool cloning;
int disk_image_id;
vector<VectorAttribute *> disks;
int num_disks = obj_template->get("DISK", disks);
for(int i=0; i < num_disks; i++)
{
disks[i]->vector_value("CLONING", cloning);
if (cloning &&
(disks[i]->vector_value("IMAGE_ID", disk_image_id) == 0) &&
disk_image_id == image_id)
{
disks[i]->remove("CLONING");
}
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachine::set_up_attach_disk(VirtualMachineTemplate * tmpl, string& err)
{
Nebula& nd = Nebula::instance();
@ -2737,7 +2828,7 @@ void VirtualMachine::release_disk_images()
for(int i=0; i<num_disks; i++)
{
img_error = (state == ACTIVE && lcm_state != EPILOG) &&
state != PENDING && state != HOLD;
state != PENDING && state != HOLD && state != CLONING;
if ( disks[i]->vector_value("IMAGE_ID", iid) == 0 )
{

View File

@ -284,6 +284,8 @@ int VirtualMachinePool::allocate (
if ( _submit_on_hold == true || on_hold )
{
vm->state = VirtualMachine::HOLD;
vm->user_obj_template->replace("SUBMIT_ON_HOLD", true);
}
else
{
@ -1146,4 +1148,3 @@ void VirtualMachinePool::delete_hotplug_nic(int vid, bool attach)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */