Tony Asleson
2014-08-25 22:26:24 UTC
Ensure we get an IS_MASKED error if we try to delete an access group
that has a masked volume.
Tested against sim & simc
Signed-off-by: Tony Asleson <***@redhat.com>
---
plugin/simc/simc_lsmplugin.c | 37 +++++++++++++++++++++------
test/plugin_test.py | 61 +++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 89 insertions(+), 9 deletions(-)
diff --git a/plugin/simc/simc_lsmplugin.c b/plugin/simc/simc_lsmplugin.c
index 145a499..618613b 100644
--- a/plugin/simc/simc_lsmplugin.c
+++ b/plugin/simc/simc_lsmplugin.c
@@ -327,6 +327,11 @@ static int tmo_get(lsm_plugin_ptr c, uint32_t *timeout, lsm_flag flags)
return LSM_ERR_INVALID_ARGUMENT;
}
+static int vol_accessible_by_ag(lsm_plugin_ptr c,
+ lsm_access_group *group,
+ lsm_volume **volumes[],
+ uint32_t *count, lsm_flag flags);
+
static int cap(lsm_plugin_ptr c, lsm_system *system,
lsm_storage_capabilities **cap, lsm_flag flags)
{
@@ -1050,21 +1055,37 @@ static int access_group_delete( lsm_plugin_ptr c,
lsm_flag flags)
{
int rc = LSM_ERR_OK;
+ lsm_volume **volumes = NULL;
+ uint32_t count = 0;
struct plugin_data *pd = (struct plugin_data*)lsm_private_data_get(c);
const char *id = lsm_access_group_id_get(group);
- gboolean r = g_hash_table_remove(pd->access_groups, (gpointer)id);
+ rc = vol_accessible_by_ag(c, group, &volumes, &count, LSM_FLAG_RSVD);
- if( !r ) {
- rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_ACCESS_GROUP,
- "access group not found");
- } else {
- g_hash_table_remove(pd->group_grant, id);
+ if( rc == LSM_ERR_OK && count ) {
+ lsm_volume_record_array_free(volumes, count);
}
- if( !g_hash_table_size(pd->access_groups) ) {
- assert( g_hash_table_size(pd->group_grant ) == 0);
+ if( LSM_ERR_OK == rc ) {
+
+ if( count ) {
+ rc = lsm_log_error_basic(c, LSM_ERR_IS_MASKED,
+ "access group has masked volumes!");
+ } else {
+ gboolean r = g_hash_table_remove(pd->access_groups, (gpointer)id);
+
+ if( !r ) {
+ rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_ACCESS_GROUP,
+ "access group not found");
+ } else {
+ g_hash_table_remove(pd->group_grant, id);
+ }
+
+ if( !g_hash_table_size(pd->access_groups) ) {
+ assert( g_hash_table_size(pd->group_grant ) == 0);
+ }
+ }
}
return rc;
diff --git a/test/plugin_test.py b/test/plugin_test.py
index 4c7cd28..10d0c26 100755
--- a/test/plugin_test.py
+++ b/test/plugin_test.py
@@ -74,7 +74,7 @@ def rs(component, l=4):
rp = ''.join(random.choice(string.ascii_uppercase) for x in range(l))
if component is not None:
- return 'lsm_%s_' % component + rp
+ return 'lsm_%s_' % (component + rp)
return rp
@@ -657,6 +657,7 @@ class TestPlugin(unittest.TestCase):
def test_mask_unmask(self):
for s in self.systems:
+ ag = None
cap = self.c.capabilities(s)
if supported(cap, [lsm.Capabilities.ACCESS_GROUPS,
@@ -665,6 +666,14 @@ class TestPlugin(unittest.TestCase):
lsm.Capabilities.VOLUME_CREATE,
lsm.Capabilities.VOLUME_DELETE]):
+ if supported(cap, [lsm.Capabilities.ACCESS_GROUP_CREATE_WWPN]):
+ ag_name = rs("ag")
+ ag_iqn = 'iqn.1994-05.com.domain:01.' + rs(None, 6)
+
+ ag = self.c.access_group_create(
+ ag_name, ag_iqn, lsm.AccessGroup.INIT_TYPE_ISCSI_IQN,
+ s)
+
# Make sure we have an access group to test with, many
# smi-s providers don't provide functionality to create them!
ag_list = self.c.access_groups('system_id', s.id)
@@ -689,6 +698,10 @@ class TestPlugin(unittest.TestCase):
if vol:
self._volume_delete(vol)
+ if ag:
+ self.c.access_group_delete(ag)
+ ag = None
+
def _create_access_group(self, cap, name, s, init_type):
ag_created = None
@@ -901,6 +914,52 @@ class TestPlugin(unittest.TestCase):
self._delete_access_group(ag_created)
+ def test_ag_delete_with_vol_masked(self):
+ for s in self.systems:
+ cap = self.c.capabilities(s)
+ if supported(cap, [lsm.Capabilities.ACCESS_GROUPS,
+ lsm.Capabilities.ACCESS_GROUP_CREATE_ISCSI_IQN,
+ lsm.Capabilities.ACCESS_GROUP_DELETE,
+ lsm.Capabilities.VOLUME_UNMASK,
+ lsm.Capabilities.VOLUME_CREATE,
+ lsm.Capabilities.VOLUME_DELETE,
+ lsm.Capabilities.VOLUME_MASK,
+ lsm.Capabilities.VOLUME_UNMASK]):
+
+ ag_name = rs("ag")
+ ag_iqn = 'iqn.1994-05.com.domain:01.' + rs(None, 6)
+
+ ag = self.c.access_group_create(
+ ag_name, ag_iqn, lsm.AccessGroup.INIT_TYPE_ISCSI_IQN, s)
+
+ pool = self._get_pool_by_usage(s.id,
+ lsm.Pool.ELEMENT_TYPE_VOLUME)
+ if ag and pool:
+ vol_size = self._object_size(pool)
+
+ vol = self.c.volume_create(
+ pool, rs('v'), vol_size,
+ lsm.Volume.PROVISION_DEFAULT)[1]
+
+ if vol:
+ got_exception = False
+ self.c.volume_mask(ag, vol)
+
+ try:
+ self.c.access_group_delete(ag)
+ except LsmError as le:
+ if le.code == lsm.ErrorNumber.IS_MASKED:
+ got_exception = True
+ self.assertTrue(le.code ==
+ lsm.ErrorNumber.IS_MASKED)
+
+ self.assertTrue(got_exception)
+ self.c.volume_unmask(ag, vol)
+ self.c.volume_delete(vol)
+
+ self.c.access_group_delete(ag)
+
+
def dump_results():
"""
that has a masked volume.
Tested against sim & simc
Signed-off-by: Tony Asleson <***@redhat.com>
---
plugin/simc/simc_lsmplugin.c | 37 +++++++++++++++++++++------
test/plugin_test.py | 61 +++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 89 insertions(+), 9 deletions(-)
diff --git a/plugin/simc/simc_lsmplugin.c b/plugin/simc/simc_lsmplugin.c
index 145a499..618613b 100644
--- a/plugin/simc/simc_lsmplugin.c
+++ b/plugin/simc/simc_lsmplugin.c
@@ -327,6 +327,11 @@ static int tmo_get(lsm_plugin_ptr c, uint32_t *timeout, lsm_flag flags)
return LSM_ERR_INVALID_ARGUMENT;
}
+static int vol_accessible_by_ag(lsm_plugin_ptr c,
+ lsm_access_group *group,
+ lsm_volume **volumes[],
+ uint32_t *count, lsm_flag flags);
+
static int cap(lsm_plugin_ptr c, lsm_system *system,
lsm_storage_capabilities **cap, lsm_flag flags)
{
@@ -1050,21 +1055,37 @@ static int access_group_delete( lsm_plugin_ptr c,
lsm_flag flags)
{
int rc = LSM_ERR_OK;
+ lsm_volume **volumes = NULL;
+ uint32_t count = 0;
struct plugin_data *pd = (struct plugin_data*)lsm_private_data_get(c);
const char *id = lsm_access_group_id_get(group);
- gboolean r = g_hash_table_remove(pd->access_groups, (gpointer)id);
+ rc = vol_accessible_by_ag(c, group, &volumes, &count, LSM_FLAG_RSVD);
- if( !r ) {
- rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_ACCESS_GROUP,
- "access group not found");
- } else {
- g_hash_table_remove(pd->group_grant, id);
+ if( rc == LSM_ERR_OK && count ) {
+ lsm_volume_record_array_free(volumes, count);
}
- if( !g_hash_table_size(pd->access_groups) ) {
- assert( g_hash_table_size(pd->group_grant ) == 0);
+ if( LSM_ERR_OK == rc ) {
+
+ if( count ) {
+ rc = lsm_log_error_basic(c, LSM_ERR_IS_MASKED,
+ "access group has masked volumes!");
+ } else {
+ gboolean r = g_hash_table_remove(pd->access_groups, (gpointer)id);
+
+ if( !r ) {
+ rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_ACCESS_GROUP,
+ "access group not found");
+ } else {
+ g_hash_table_remove(pd->group_grant, id);
+ }
+
+ if( !g_hash_table_size(pd->access_groups) ) {
+ assert( g_hash_table_size(pd->group_grant ) == 0);
+ }
+ }
}
return rc;
diff --git a/test/plugin_test.py b/test/plugin_test.py
index 4c7cd28..10d0c26 100755
--- a/test/plugin_test.py
+++ b/test/plugin_test.py
@@ -74,7 +74,7 @@ def rs(component, l=4):
rp = ''.join(random.choice(string.ascii_uppercase) for x in range(l))
if component is not None:
- return 'lsm_%s_' % component + rp
+ return 'lsm_%s_' % (component + rp)
return rp
@@ -657,6 +657,7 @@ class TestPlugin(unittest.TestCase):
def test_mask_unmask(self):
for s in self.systems:
+ ag = None
cap = self.c.capabilities(s)
if supported(cap, [lsm.Capabilities.ACCESS_GROUPS,
@@ -665,6 +666,14 @@ class TestPlugin(unittest.TestCase):
lsm.Capabilities.VOLUME_CREATE,
lsm.Capabilities.VOLUME_DELETE]):
+ if supported(cap, [lsm.Capabilities.ACCESS_GROUP_CREATE_WWPN]):
+ ag_name = rs("ag")
+ ag_iqn = 'iqn.1994-05.com.domain:01.' + rs(None, 6)
+
+ ag = self.c.access_group_create(
+ ag_name, ag_iqn, lsm.AccessGroup.INIT_TYPE_ISCSI_IQN,
+ s)
+
# Make sure we have an access group to test with, many
# smi-s providers don't provide functionality to create them!
ag_list = self.c.access_groups('system_id', s.id)
@@ -689,6 +698,10 @@ class TestPlugin(unittest.TestCase):
if vol:
self._volume_delete(vol)
+ if ag:
+ self.c.access_group_delete(ag)
+ ag = None
+
def _create_access_group(self, cap, name, s, init_type):
ag_created = None
@@ -901,6 +914,52 @@ class TestPlugin(unittest.TestCase):
self._delete_access_group(ag_created)
+ def test_ag_delete_with_vol_masked(self):
+ for s in self.systems:
+ cap = self.c.capabilities(s)
+ if supported(cap, [lsm.Capabilities.ACCESS_GROUPS,
+ lsm.Capabilities.ACCESS_GROUP_CREATE_ISCSI_IQN,
+ lsm.Capabilities.ACCESS_GROUP_DELETE,
+ lsm.Capabilities.VOLUME_UNMASK,
+ lsm.Capabilities.VOLUME_CREATE,
+ lsm.Capabilities.VOLUME_DELETE,
+ lsm.Capabilities.VOLUME_MASK,
+ lsm.Capabilities.VOLUME_UNMASK]):
+
+ ag_name = rs("ag")
+ ag_iqn = 'iqn.1994-05.com.domain:01.' + rs(None, 6)
+
+ ag = self.c.access_group_create(
+ ag_name, ag_iqn, lsm.AccessGroup.INIT_TYPE_ISCSI_IQN, s)
+
+ pool = self._get_pool_by_usage(s.id,
+ lsm.Pool.ELEMENT_TYPE_VOLUME)
+ if ag and pool:
+ vol_size = self._object_size(pool)
+
+ vol = self.c.volume_create(
+ pool, rs('v'), vol_size,
+ lsm.Volume.PROVISION_DEFAULT)[1]
+
+ if vol:
+ got_exception = False
+ self.c.volume_mask(ag, vol)
+
+ try:
+ self.c.access_group_delete(ag)
+ except LsmError as le:
+ if le.code == lsm.ErrorNumber.IS_MASKED:
+ got_exception = True
+ self.assertTrue(le.code ==
+ lsm.ErrorNumber.IS_MASKED)
+
+ self.assertTrue(got_exception)
+ self.c.volume_unmask(ag, vol)
+ self.c.volume_delete(vol)
+
+ self.c.access_group_delete(ag)
+
+
def dump_results():
"""
--
1.8.2.1
1.8.2.1