Skip to content

Commit

Permalink
F #6029: Prevent backup removal VM is in BACKUP
Browse files Browse the repository at this point in the history
Some backup drivers may not allow delete (forget) operations while an
active backup is being performed. This commits fails the
one.image.delete API call in that case.

A new configuration attribute to describe the related driver behavior has been
added CONCURRENT_FORGET for DS_MAD_CONF.

(cherry picked from commit 940c1d7)
  • Loading branch information
rsmontero committed Feb 9, 2023
1 parent b82ca03 commit c68c81a
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 32 deletions.
9 changes: 7 additions & 2 deletions include/Datastore.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,11 +240,16 @@ class Datastore : public PoolObjectSQL, public Clusterable
};

/**
* Returns true if the DS_MAD_CONF has PERSISTENT_ONLY = "YES" flag
* @return true if persistent only
* @return true if the DS_MAD_CONF has PERSISTENT_ONLY = "YES" flag
*/
bool is_persistent_only() const;

/**
* (only relevant for backup datastores)
* @return true if the DS_MAD_CONF has CONCURRENT_FORGET = "YES" flag
*/
bool is_concurrent_forget() const;

/**
* Enable or disable the DS. Only for System DS.
* @param enable true to enable
Expand Down
79 changes: 49 additions & 30 deletions src/datastore/Datastore.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1110,58 +1110,77 @@ bool Datastore::get_avail_mb(long long &avail) const
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

bool Datastore::is_persistent_only() const
template <typename T>
static T ds_conf_value(const string& mad, const string& name, const T& defval)
{
int rc;
bool persistent_only = false;

const VectorAttribute* vatt;

rc = Nebula::instance().get_ds_conf_attribute(ds_mad, vatt);
int rc = Nebula::instance().get_ds_conf_attribute(mad, vatt);

if ( rc != 0 )
{
// No DS_MAD_CONF is available for this DS_MAD.
// Assuming this DS is not PERSISTENT_ONLY
return false;
return defval;
}

vatt->vector_value("PERSISTENT_ONLY", persistent_only);
T value;

return persistent_only;
};
rc = vatt->vector_value(name, value);

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
if ( rc != 0 )
{
// Attribute missing in DS_MAD_CONF
return defval;
}

return value;
}

/* -------------------------------------------------------------------------- */

bool Datastore::is_persistent_only() const
{
return ds_conf_value(ds_mad, "PERSISTENT_ONLY", false);
}

bool Datastore::is_concurrent_forget() const
{
return ds_conf_value(ds_mad, "CONCURRENT_FORGET", false);
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

int Datastore::get_tm_mad_targets(const string &tm_mad, string& ln_target,
string& clone_target, string& disk_type) const
{
if (!tm_mad.empty())
if (tm_mad.empty())
{
string tm_mad_t = one_util::trim(tm_mad);
one_util::toupper(tm_mad_t);
return 0;
}

get_template_attribute("CLONE_TARGET_" + tm_mad_t, clone_target);
string tm_mad_t = one_util::trim(tm_mad);
one_util::toupper(tm_mad_t);

if (clone_target.empty())
{
return -1;
}
get_template_attribute("CLONE_TARGET_" + tm_mad_t, clone_target);

get_template_attribute("LN_TARGET_" + tm_mad_t, ln_target);
if (clone_target.empty())
{
return -1;
}

if (ln_target.empty())
{
return -1;
}
get_template_attribute("LN_TARGET_" + tm_mad_t, ln_target);

get_template_attribute("DISK_TYPE_" + tm_mad_t, disk_type);
if (ln_target.empty())
{
return -1;
}

if (disk_type.empty())
{
return -1;
}
get_template_attribute("DISK_TYPE_" + tm_mad_t, disk_type);

if (disk_type.empty())
{
return -1;
}

return 0;
Expand Down
32 changes: 32 additions & 0 deletions src/image/ImageManagerActions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,8 @@ int ImageManager::delete_image(int iid, string& error_str)
int cloning_id = -1;
int vm_saving_id = -1;

bool cforget;

ostringstream oss;

if (auto img = ipool->get_ro(iid))
Expand All @@ -479,6 +481,8 @@ int ImageManager::delete_image(int iid, string& error_str)
ds->decrypt();

ds->to_xml(ds_data);

cforget = ds->is_concurrent_forget();
}
else
{
Expand All @@ -494,6 +498,34 @@ int ImageManager::delete_image(int iid, string& error_str)
return -1;
}

// Check associted VM state for backups. Note VM can no longer exist
// Fai if VM is in BACKUP and INCREMENT mode or FULL with no CONCURRENT_FORGET
if ( img->get_type() == Image::BACKUP )
{
auto ids = img->get_running_ids();
auto first = ids.cbegin();

if (first != ids.cend())
{
VirtualMachinePool* vmpool = Nebula::instance().get_vmpool();

if (auto vm = vmpool->get_ro(*first))
{
auto lstate = vm->get_lcm_state();
auto bmode = vm->backups().mode();

if ((lstate == VirtualMachine::BACKUP ||
lstate == VirtualMachine::BACKUP_POWEROFF) &&
(bmode == Backups::INCREMENT || !cforget))
{
error_str = "Active backup on the associated VM. Wait till "
"it finish to delete the backup Image";
return -1;
}
}
}
}

switch (img->get_state())
{
case Image::READY:
Expand Down

0 comments on commit c68c81a

Please sign in to comment.