Discussion:
[Libstoragemgmt-devel] [PATCH 1/2] plugin_test.py: Add test for IS_MASKED
Tony Asleson
2014-08-26 21:38:01 UTC
Permalink
Ensure we get an IS_MASKED error if we try to delete a volume
that is masked against an access group.

Tested against sim & simc

Signed-off-by: Tony Asleson <***@redhat.com>
---
plugin/simc/simc_lsmplugin.c | 27 +++++++++++++++++++++++++--
test/plugin_test.py | 18 +++++++++++++++++-
2 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/plugin/simc/simc_lsmplugin.c b/plugin/simc/simc_lsmplugin.c
index 618613b..b263adb 100644
--- a/plugin/simc/simc_lsmplugin.c
+++ b/plugin/simc/simc_lsmplugin.c
@@ -332,6 +332,11 @@ static int vol_accessible_by_ag(lsm_plugin_ptr c,
lsm_volume **volumes[],
uint32_t *count, lsm_flag flags);

+static int ag_granted_to_volume( lsm_plugin_ptr c,
+ lsm_volume *volume,
+ lsm_access_group **groups[],
+ uint32_t *count, lsm_flag flags);
+
static int cap(lsm_plugin_ptr c, lsm_system *system,
lsm_storage_capabilities **cap, lsm_flag flags)
{
@@ -923,11 +928,29 @@ static int _volume_delete(lsm_plugin_ptr c, const char *volume_id)
static int volume_delete(lsm_plugin_ptr c, lsm_volume *volume,
char **job, lsm_flag flags)
{
+ lsm_access_group **groups = NULL;
+ uint32_t count = 0;
+
struct plugin_data *pd = (struct plugin_data*)lsm_private_data_get(c);
- int rc = _volume_delete(c, lsm_volume_id_get(volume));
+
+ // Check to see if this volume is masked to any access groups, if it is we
+ // will return an IS_MASKED error code.
+ int rc = ag_granted_to_volume(c, volume, &groups, &count, LSM_FLAG_RSVD);

if( LSM_ERR_OK == rc ) {
- rc = create_job(pd, job, LSM_DATA_TYPE_NONE, NULL, NULL);
+ lsm_access_group_record_array_free(groups, count);
+ groups = NULL;
+
+ if( !count ) {
+
+ rc = _volume_delete(c, lsm_volume_id_get(volume));
+
+ if( LSM_ERR_OK == rc ) {
+ rc = create_job(pd, job, LSM_DATA_TYPE_NONE, NULL, NULL);
+ }
+ } else {
+ rc = lsm_log_error_basic(c, LSM_ERR_IS_MASKED, "Volume is masked!");
+ }
}
return rc;
}
diff --git a/test/plugin_test.py b/test/plugin_test.py
index 10d0c26..042835a 100755
--- a/test/plugin_test.py
+++ b/test/plugin_test.py
@@ -914,7 +914,7 @@ class TestPlugin(unittest.TestCase):

self._delete_access_group(ag_created)

- def test_ag_delete_with_vol_masked(self):
+ def test_ag_vol_delete_with_vol_masked(self):
for s in self.systems:
cap = self.c.capabilities(s)
if supported(cap, [lsm.Capabilities.ACCESS_GROUPS,
@@ -945,6 +945,8 @@ class TestPlugin(unittest.TestCase):
got_exception = False
self.c.volume_mask(ag, vol)

+ # Try to delete the access group
+
try:
self.c.access_group_delete(ag)
except LsmError as le:
@@ -954,6 +956,20 @@ class TestPlugin(unittest.TestCase):
lsm.ErrorNumber.IS_MASKED)

self.assertTrue(got_exception)
+
+ # Try to delete the volume
+ got_exception = False
+ try:
+ self.c.volume_delete(vol)
+ 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)
+
+ # Clean up
self.c.volume_unmask(ag, vol)
self.c.volume_delete(vol)
--
1.8.2.1
Tony Asleson
2014-08-26 21:38:02 UTC
Permalink
Some arrays have pools which don't allow Volumes created from them
to be re-sized. For SMI-S the array may report that re-size is
supported, but you have to check each individual pool to see if
it supports this functionality.

I added:

ELEMENT_TYPE_VOLUME_EXPAND
ELEMENT_TYPE_VOLUME_SHRINK

to pool. This seems a little hack'ish to me.

Gris and others, any suggestions on how to make this better? Other
than adding another field, this seemed like the obvious way.

Thanks,
Tony

Signed-off-by: Tony Asleson <***@redhat.com>
---
.../include/libstoragemgmt/libstoragemgmt_types.h | 2 ++
plugin/nstor/nstor.py | 3 +-
plugin/ontap/ontap.py | 4 ++-
plugin/sim/simarray.py | 8 ++++--
plugin/simc/simc_lsmplugin.c | 4 ++-
plugin/smispy/smis.py | 32 ++++++++++++++++------
plugin/targetd/targetd.py | 4 ++-
python_binding/lsm/_data.py | 5 +++-
test/plugin_test.py | 9 +++---
tools/lsmcli/data_display.py | 2 ++
10 files changed, 54 insertions(+), 19 deletions(-)

diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt_types.h b/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
index 053dec3..c46c93a 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
@@ -242,6 +242,8 @@ typedef enum {
#define LSM_POOL_ELEMENT_TYPE_VOLUME 0x0000000000000004
#define LSM_POOL_ELEMENT_TYPE_FS 0x0000000000000008
#define LSM_POOL_ELEMENT_TYPE_DELTA 0x0000000000000010
+#define LSM_POOL_ELEMENT_TYPE_VOLUME_EXPAND 0x0000000000000020
+#define LSM_POOL_ELEMENT_TYPE_VOLUME_SHRINK 0x0000000000000040
#define LSM_POOL_ELEMENT_TYPE_SYS_RESERVED 0x0000000000000400

typedef enum {
diff --git a/plugin/nstor/nstor.py b/plugin/nstor/nstor.py
index c5e3ef1..3908293 100644
--- a/plugin/nstor/nstor.py
+++ b/plugin/nstor/nstor.py
@@ -133,7 +133,8 @@ class NexentaStor(INfs, IStorageAreaNetwork):
[str(pool), ""])

pools.append(Pool(pool_info['name'], pool_info['name'],
- Pool.ELEMENT_TYPE_VOLUME | Pool.ELEMENT_TYPE_FS,
+ Pool.ELEMENT_TYPE_VOLUME | Pool.ELEMENT_TYPE_FS |
+ Pool.ELEMENT_TYPE_VOLUME_EXPAND,
NexentaStor._to_bytes(pool_info['size']),
NexentaStor._to_bytes(pool_info['free']),
Pool.STATUS_UNKNOWN, '', self.system.id))
diff --git a/plugin/ontap/ontap.py b/plugin/ontap/ontap.py
index c13caec..ba4b759 100644
--- a/plugin/ontap/ontap.py
+++ b/plugin/ontap/ontap.py
@@ -429,7 +429,9 @@ class Ontap(IStorageAreaNetwork, INfs):
return "%s/%s" % (Ontap.VOLUME_PREFIX, na_vol_name)

def _pool_from_na_vol(self, na_vol, na_aggrs, flags):
- element_type = Pool.ELEMENT_TYPE_VOLUME
+ element_type = (Pool.ELEMENT_TYPE_VOLUME |
+ Pool.ELEMENT_TYPE_VOLUME_EXPAND |
+ Pool.ELEMENT_TYPE_VOLUME_SHRINK)
pool_name = na_vol['name']
pool_id = self._pool_id_of_na_vol_name(na_vol['name'])
total_space = int(na_vol['size-total'])
diff --git a/plugin/sim/simarray.py b/plugin/sim/simarray.py
index 8d5ddf0..03d8905 100644
--- a/plugin/sim/simarray.py
+++ b/plugin/sim/simarray.py
@@ -222,7 +222,9 @@ class SimArray(object):
status_info = sim_pool['status_info']
sys_id = sim_pool['sys_id']
return Pool(pool_id, name,
- Pool.ELEMENT_TYPE_VOLUME | Pool.ELEMENT_TYPE_FS,
+ Pool.ELEMENT_TYPE_VOLUME | Pool.ELEMENT_TYPE_FS |
+ Pool.ELEMENT_TYPE_VOLUME_EXPAND |
+ Pool.ELEMENT_TYPE_VOLUME_SHRINK,
total_space, free_space, status,
status_info, sys_id)

@@ -550,7 +552,9 @@ class SimData(object):
SIM_DATA_POOL_STATUS_INFO = ''
SIM_DATA_POOL_ELEMENT_TYPE = Pool.ELEMENT_TYPE_FS \
| Pool.ELEMENT_TYPE_POOL \
- | Pool.ELEMENT_TYPE_VOLUME
+ | Pool.ELEMENT_TYPE_VOLUME \
+ | Pool.ELEMENT_TYPE_VOLUME_EXPAND \
+ | Pool.ELEMENT_TYPE_VOLUME_SHRINK

SIM_DATA_SYS_POOL_ELEMENT_TYPE = SIM_DATA_POOL_ELEMENT_TYPE \
| Pool.ELEMENT_TYPE_SYS_RESERVED
diff --git a/plugin/simc/simc_lsmplugin.c b/plugin/simc/simc_lsmplugin.c
index b263adb..091863c 100644
--- a/plugin/simc/simc_lsmplugin.c
+++ b/plugin/simc/simc_lsmplugin.c
@@ -2119,7 +2119,9 @@ int load( lsm_plugin_ptr c, const char *uri, const char *password,

p = lsm_pool_record_alloc("POOL_3", "lsm_test_aggr",
LSM_POOL_ELEMENT_TYPE_FS|
- LSM_POOL_ELEMENT_TYPE_VOLUME,
+ LSM_POOL_ELEMENT_TYPE_VOLUME |
+ LSM_POOL_ELEMENT_TYPE_VOLUME_EXPAND|
+ LSM_POOL_ELEMENT_TYPE_VOLUME_SHRINK,
UINT64_MAX, UINT64_MAX,
LSM_POOL_STATUS_OK, "",
sys_id, NULL);
diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index 41cf94e..db09fd1 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -255,12 +255,16 @@ class Smis(IStorageAreaNetwork):
JOB_RETRIEVE_POOL = 2

# DMTF CIM 2.37.0 experimental CIM_StoragePool['Usage']
- DMTF_POOL_USAGE_SPARE = 8
+ DMTF_POOL_USAGE_UNRESTRICTED = 2
+ DMTF_POOL_USAGE_RESERVED_FOR_SYSTEM = 3
DMTF_POOL_USAGE_DELTA = 4
+ DMTF_POOL_USAGE_SPARE = 8

# DMTF CIM 2.29.1 CIM_StorageConfigurationCapabilities
# ['SupportedStorageElementFeatures']
DMTF_SUPPORT_VOL_CREATE = 3
+ DMTF_SUPPORT_ELEMENT_EXPAND = 12
+ DMTF_SUPPORT_ELEMENT_REDUCE = 13

# DMTF CIM 2.37.0 experimental CIM_StorageConfigurationCapabilities
# ['SupportedStorageElementTypes']
@@ -3185,10 +3189,16 @@ class Smis(IStorageAreaNetwork):
# Manipulation, Figure 9 - Capabilities Specific to a StoragePool
if len(cim_sccs) == 1:
cim_scc = cim_sccs[0]
- if 'SupportedStorageElementFeatures' in cim_scc and \
- Smis.DMTF_SUPPORT_VOL_CREATE in \
- cim_scc['SupportedStorageElementFeatures']:
- element_type = Pool.ELEMENT_TYPE_VOLUME
+ if 'SupportedStorageElementFeatures' in cim_scc:
+ supported_features = cim_scc['SupportedStorageElementFeatures']
+
+ if Smis.DMTF_SUPPORT_VOL_CREATE in supported_features:
+ element_type |= Pool.ELEMENT_TYPE_VOLUME
+ if Smis.DMTF_SUPPORT_ELEMENT_EXPAND in supported_features:
+ element_type |= Pool.ELEMENT_TYPE_VOLUME_EXPAND
+ if Smis.DMTF_SUPPORT_ELEMENT_REDUCE in supported_features:
+ element_type |= Pool.ELEMENT_TYPE_VOLUME_SHRINK
+
else:
# IBM DS 8000 does not support StorageConfigurationCapabilities
# per pool yet. They has been informed. Before fix, use a quick
@@ -3205,10 +3215,16 @@ class Smis(IStorageAreaNetwork):
element_type = Pool.ELEMENT_TYPE_VOLUME

if 'Usage' in cim_pool:
- if cim_pool['Usage'] == Smis.DMTF_POOL_USAGE_DELTA:
+ usage = cim_pool['Usage']
+
+ if usage == Smis.DMTF_POOL_USAGE_UNRESTRICTED:
+ element_type |= Pool.ELEMENT_TYPE_VOLUME
+ if usage == Smis.DMTF_POOL_USAGE_RESERVED_FOR_SYSTEM or \
+ usage > Smis.DMTF_POOL_USAGE_DELTA:
+ element_type |= Pool.ELEMENT_TYPE_SYS_RESERVED
+ if usage == Smis.DMTF_POOL_USAGE_DELTA:
+ # We blitz all the other elements types for this designation
element_type = Pool.ELEMENT_TYPE_DELTA
- if cim_pool['Usage'] == 2:
- element_type = Pool.ELEMENT_TYPE_VOLUME

return element_type

diff --git a/plugin/targetd/targetd.py b/plugin/targetd/targetd.py
index 989dbf5..a3b479f 100644
--- a/plugin/targetd/targetd.py
+++ b/plugin/targetd/targetd.py
@@ -177,7 +177,9 @@ class TargetdStorage(IStorageAreaNetwork, INfs):
if pool['name'].startswith('/'):
et = Pool.ELEMENT_TYPE_FS
else:
- et = Pool.ELEMENT_TYPE_VOLUME
+ et = Pool.ELEMENT_TYPE_VOLUME | \
+ Pool.ELEMENT_TYPE_VOLUME_EXPAND | \
+ Pool.ELEMENT_TYPE_VOLUME_SHRINK

pools.append(Pool(pool['name'],
pool['name'], et, pool['size'],
diff --git a/python_binding/lsm/_data.py b/python_binding/lsm/_data.py
index ef2483d..d00a11e 100644
--- a/python_binding/lsm/_data.py
+++ b/python_binding/lsm/_data.py
@@ -312,7 +312,8 @@ class Pool(IData):
TOTAL_SPACE_NOT_FOUND = -1
FREE_SPACE_NOT_FOUND = -1

- # Element Type indicate what kind of element could this pool create:
+ # Element Type indicate what kind of element could this pool create or
+ # what features the pool supports.
# * Another Pool
# * Volume (aka, LUN)
# * System Reserved Pool.
@@ -321,6 +322,8 @@ class Pool(IData):
ELEMENT_TYPE_VOLUME = 1 << 2
ELEMENT_TYPE_FS = 1 << 3
ELEMENT_TYPE_DELTA = 1 << 4
+ ELEMENT_TYPE_VOLUME_EXPAND = 1 << 5
+ ELEMENT_TYPE_VOLUME_SHRINK = 1 << 6
ELEMENT_TYPE_SYS_RESERVED = 1 << 10 # Reserved for system use

# Pool status could be any combination of these status.
diff --git a/test/plugin_test.py b/test/plugin_test.py
index 042835a..2b15d7f 100755
--- a/test/plugin_test.py
+++ b/test/plugin_test.py
@@ -340,10 +340,10 @@ class TestPlugin(unittest.TestCase):
disks = self.c.disks()
self.assertTrue(len(disks) > 0, "We need at least 1 disk to test")

- def _volume_create(self, system_id):
+ def _volume_create(self, system_id,
+ element_type=lsm.Pool.ELEMENT_TYPE_VOLUME):
if system_id in self.pool_by_sys_id:
- p = self._get_pool_by_usage(system_id,
- lsm.Pool.ELEMENT_TYPE_VOLUME)
+ p = self._get_pool_by_usage(system_id, element_type)

self.assertTrue(p is not None, "Unable to find a suitable pool")

@@ -439,7 +439,8 @@ class TestPlugin(unittest.TestCase):
if supported(cap, [lsm.Capabilities.VOLUME_CREATE,
lsm.Capabilities.VOLUME_DELETE,
lsm.Capabilities.VOLUME_RESIZE]):
- vol = self._volume_create(s.id)[0]
+ vol = self._volume_create(
+ s.id, lsm.Pool.ELEMENT_TYPE_VOLUME_EXPAND)[0]
vol_resize = self.c.volume_resize(
vol, int(vol.size_bytes * 1.10))[1]
self.assertTrue(vol.size_bytes < vol_resize.size_bytes)
diff --git a/tools/lsmcli/data_display.py b/tools/lsmcli/data_display.py
index 7f4100e..f82f869 100644
--- a/tools/lsmcli/data_display.py
+++ b/tools/lsmcli/data_display.py
@@ -116,6 +116,8 @@ _POOL_ELEMENT_TYPE_CONV = {
Pool.ELEMENT_TYPE_FS: 'FILE_SYSTEM',
Pool.ELEMENT_TYPE_SYS_RESERVED: 'SYSTEM_RESERVED',
Pool.ELEMENT_TYPE_DELTA: "DELTA",
+ Pool.ELEMENT_TYPE_VOLUME_SHRINK: "VOLUME_SHRINK",
+ Pool.ELEMENT_TYPE_VOLUME_EXPAND: "VOLUME_EXPAND"
}
--
1.8.2.1
Loading...