Discussion:
[Libstoragemgmt-devel] [PATCH 0/6] Add Thin Provisioning support to volume create.
Gris Ge
2014-10-15 14:31:31 UTC
Permalink
* This patchset is based on master tree plus:
'[PATCH 00/18] Pending patches' # 14 Oct 2014

* This patch set provide a way for creating thin provisioning or full
allocated volume:
Pool.element_type:
* Pool.ELEMENT_TYPE_VOLUME
# Can call volume_create() using
# provisioning=Volume.PROVISION_DEFAULT
# This is for back compatibility or user who don't care about
# Thin provisioning. Plugin or Array will use their default setting
# for new volume.
* Pool.ELEMENT_TYPE_VOLUME_THIN
# Can call volume_create() using
# provisioning=Volume.PROVISION_THIN
# Thin provisioned volume is required.
* Pool.ELEMENT_TYPE_VOLUME_FULL
# Can call volume_create() using
# provisioning=Volume.PROVISION_FULL
# Full allocated volume is required.

Gris Ge (6):
Library: Add new element_type to pool for thin provisioning.
lsmcli: Add new element types of lsm.Pool.
SMI-S Plugin: Indicate pool thin provisioning status in pool querying.
SMI-S Plugin: Allow provision parameter of volume_create()
ONTAP Plugin: Add thin provisioning support.
Nstor Plugin: Set VOLUME_THIN element type when querying pool.

.../include/libstoragemgmt/libstoragemgmt_types.h | 2 +
plugin/nstor/nstor.py | 4 +-
plugin/ontap/na.py | 6 ++-
plugin/ontap/ontap.py | 57 ++++++++++++++++++++--
plugin/smispy/dmtf.py | 4 +-
plugin/smispy/smis.py | 35 +++++++++++--
plugin/smispy/smis_pool.py | 9 +++-
python_binding/lsm/_data.py | 2 +
tools/lsmcli/data_display.py | 2 +
9 files changed, 106 insertions(+), 15 deletions(-)
--
1.8.3.1
Gris Ge
2014-10-15 14:31:32 UTC
Permalink
* Pool.ELEMENT_TYPE_VOLUME_THIN(Python) and
LSM_POOL_ELEMENT_TYPE_VOLUME_THIN(C) indicate current pool can
create thin provisioning volume via:

volume_create(provisioning=Volume.PROVISION_THIN)

* Pool.ELEMENT_TYPE_VOLUME_FULL(Python) and
LSM_POOL_ELEMENT_TYPE_VOLUME_FULL(C) indicate current pool can
create full allocated volume via:

volume_create(provisioning=Volume.PROVISION_FULL)

* To have back compatibility, Pool.ELEMENT_TYPE_VOLUME and
LSM_POOL_ELEMENT_TYPE_VOLUME indicate current pool can create
volume and allowing plugin or array to decide the provisioning type via:

volume_create(provisioning=Volume.PROVISION_DEFAULT)

Signed-off-by: Gris Ge <***@redhat.com>
---
c_binding/include/libstoragemgmt/libstoragemgmt_types.h | 2 ++
python_binding/lsm/_data.py | 2 ++
2 files changed, 4 insertions(+)

diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt_types.h b/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
index 746f397..309a5e8 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
@@ -213,6 +213,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_FULL 0x0000000000000020
+#define LSM_POOL_ELEMENT_TYPE_VOLUME_THIN 0x0000000000000040
#define LSM_POOL_ELEMENT_TYPE_SYS_RESERVED 0x0000000000000400

#define LSM_POOL_UNSUPPORTED_VOLUME_GROW 0x0000000000000001
diff --git a/python_binding/lsm/_data.py b/python_binding/lsm/_data.py
index 74ed65e..067c766 100644
--- a/python_binding/lsm/_data.py
+++ b/python_binding/lsm/_data.py
@@ -344,6 +344,8 @@ class Pool(IData):
ELEMENT_TYPE_VOLUME = 1 << 2
ELEMENT_TYPE_FS = 1 << 3
ELEMENT_TYPE_DELTA = 1 << 4
+ ELEMENT_TYPE_VOLUME_FULL = 1 << 5
+ ELEMENT_TYPE_VOLUME_THIN = 1 << 6
ELEMENT_TYPE_SYS_RESERVED = 1 << 10 # Reserved for system use

# Unsupported actions, what pool cannot be used for
--
1.8.3.1
Gris Ge
2014-10-15 14:31:35 UTC
Permalink
* Allow 'provision' parameter of volume_create() to be:
Volume.PROVISION_DEFAULT
Volume.PROVISION_FULL
Volume.PROVISION_THIN

* For Volume.PROVISION_DEFAULT, we create full allocated volume
unless only thin volume is supported. [1]

* For full allocated volume, we set 'ElementType' of
CreateOrModifyElementFromStoragePool() to dmtf.ELEMENT_THICK_VOLUME(2)

* For thin provisioning volume, we set 'ElementType' of
CreateOrModifyElementFromStoragePool() to dmtf.ELEMENT_THIN_VOLUME(5)

* This also fix a bug when running plugin_test.py against HDS AMS where
only dmtf.ELEMENT_THIN_VOLUME(5) is supported.

[1] HDS AMS Thin Pool only support ThinlyProvisionedStorageVolume.

Signed-off-by: Gris Ge <***@redhat.com>
---
plugin/smispy/dmtf.py | 4 ++--
plugin/smispy/smis.py | 35 ++++++++++++++++++++++++++++++-----
2 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/plugin/smispy/dmtf.py b/plugin/smispy/dmtf.py
index 5e30bac..3113b73 100644
--- a/plugin/smispy/dmtf.py
+++ b/plugin/smispy/dmtf.py
@@ -93,8 +93,8 @@ SUPPORT_ELEMENT_REDUCE = 13

# DMTF CIM 2.37.0 experimental CIM_StorageConfigurationCapabilities
# ['SupportedStorageElementTypes']
-ELEMENT_THICK_VOLUME = 2
-ELEMENT_THIN_VOLUME = 5
+ELEMENT_THICK_VOLUME = Uint16(2)
+ELEMENT_THIN_VOLUME = Uint16(5)

# DMTF CIM 2.29.1 CIM_StorageConfigurationCapabilities
# ['SupportedStoragePoolFeatures']
diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index 80c503c..6a2d904 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -35,7 +35,7 @@ import smis_disk
import dmtf

from lsm import (IStorageAreaNetwork, uri_parse, LsmError, ErrorNumber,
- JobStatus, md5, Volume, AccessGroup,
+ JobStatus, md5, Volume, AccessGroup, Pool,
VERSION, TargetPort,
search_property)

@@ -879,9 +879,34 @@ class Smis(IStorageAreaNetwork):
"""
Create a volume.
"""
- if provisioning != Volume.PROVISION_DEFAULT:
- raise LsmError(ErrorNumber.INVALID_ARGUMENT,
- "Unsupported provisioning")
+ # Use user provide lsm.Pool.element_type to speed thing up.
+ if not Pool.ELEMENT_TYPE_VOLUME & pool.element_type:
+ raise LsmError(
+ ErrorNumber.NO_SUPPORT,
+ "Pool not suitable for creating volumes")
+
+ # Use THICK volume by default unless unsupported or user requested.
+ dmtf_element_type = dmtf.ELEMENT_THICK_VOLUME
+
+ if provisioning == Volume.PROVISION_DEFAULT:
+ # Prefer thick/full volume unless only thin volume supported.
+ # HDS AMS only support thin volume in their thin pool.
+ if not Pool.ELEMENT_TYPE_VOLUME_FULL & pool.element_type and \
+ Pool.ELEMENT_TYPE_VOLUME_THIN & pool.element_type:
+ dmtf_element_type = dmtf.ELEMENT_THIN_VOLUME
+ else:
+ # User is requesting certain type of volume
+ if provisioning == Volume.PROVISION_FULL and \
+ Pool.ELEMENT_TYPE_VOLUME_FULL & pool.element_type:
+ dmtf_element_type = dmtf.ELEMENT_THICK_VOLUME
+ elif provisioning == Volume.PROVISION_THIN and \
+ Pool.ELEMENT_TYPE_VOLUME_THIN & pool.element_type:
+ dmtf_element_type = dmtf.ELEMENT_THIN_VOLUME
+ else:
+ raise LsmError(
+ ErrorNumber.NO_SUPPORT,
+ "Pool not suitable for creating volume with "
+ "requested provisioning type")

# Get the Configuration service for the system we are interested in.
scs = self._c.get_class_instance('CIM_StorageConfigurationService',
@@ -890,7 +915,7 @@ class Smis(IStorageAreaNetwork):
self._c, pool)

in_params = {'ElementName': volume_name,
- 'ElementType': pywbem.Uint16(2),
+ 'ElementType': dmtf_element_type,
'InPool': cim_pool_path,
'Size': pywbem.Uint64(size_bytes)}
--
1.8.3.1
Gris Ge
2014-10-15 14:31:33 UTC
Permalink
* Add these new element types of lsm.Pool:
lsm.Pool.ELEMENT_TYPE_VOLUME_THIN
lsm.Pool.ELEMENT_TYPE_VOLUME_FULL

Signed-off-by: Gris Ge <***@redhat.com>
---
tools/lsmcli/data_display.py | 2 ++
1 file changed, 2 insertions(+)

diff --git a/tools/lsmcli/data_display.py b/tools/lsmcli/data_display.py
index 75dec6c..1d8f61e 100644
--- a/tools/lsmcli/data_display.py
+++ b/tools/lsmcli/data_display.py
@@ -110,6 +110,8 @@ def pool_status_to_str(pool_status):
_POOL_ELEMENT_TYPE_CONV = {
Pool.ELEMENT_TYPE_POOL: 'POOL',
Pool.ELEMENT_TYPE_VOLUME: 'VOLUME',
+ Pool.ELEMENT_TYPE_VOLUME_THIN: 'VOLUME_THIN',
+ Pool.ELEMENT_TYPE_VOLUME_FULL: 'VOLUME_FULL',
Pool.ELEMENT_TYPE_FS: 'FS',
Pool.ELEMENT_TYPE_SYS_RESERVED: 'SYSTEM_RESERVED',
Pool.ELEMENT_TYPE_DELTA: "DELTA",
--
1.8.3.1
Gris Ge
2014-10-15 14:31:34 UTC
Permalink
* Add the ability to check whether cerntain pool can create
StorageVolume(3) or/and ThinlyProvisionedStorageVolume(5) via
CIM_StorageConfigurationCapabilities['SupportedStorageElementTypes']

Signed-off-by: Gris Ge <***@redhat.com>
---
plugin/smispy/smis_pool.py | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/plugin/smispy/smis_pool.py b/plugin/smispy/smis_pool.py
index fba8931..a978622 100644
--- a/plugin/smispy/smis_pool.py
+++ b/plugin/smispy/smis_pool.py
@@ -122,7 +122,7 @@ def _pool_element_type(smis_common, cim_pool):
For MegaRAID, just return (Pool.ELEMENT_TYPE_VOLUME, 0)
"""
if smis_common.is_megaraid():
- return Pool.ELEMENT_TYPE_VOLUME, 0
+ return Pool.ELEMENT_TYPE_VOLUME|Pool.ELEMENT_THIN_VOLUME_FULL, 0

element_type = 0
unsupported = 0
@@ -142,9 +142,14 @@ def _pool_element_type(smis_common, cim_pool):
cim_scc = cim_sccs[0]
if 'SupportedStorageElementFeatures' in cim_scc:
supported_features = cim_scc['SupportedStorageElementFeatures']
+ supported_types = cim_scc['SupportedStorageElementTypes']

if dmtf.SUPPORT_VOL_CREATE in supported_features:
- element_type |= Pool.ELEMENT_TYPE_VOLUME
+ element_type = Pool.ELEMENT_TYPE_VOLUME
+ if dmtf.ELEMENT_THIN_VOLUME in supported_types:
+ element_type |= Pool.ELEMENT_TYPE_VOLUME_THIN
+ if dmtf.ELEMENT_THICK_VOLUME in supported_types:
+ element_type |= Pool.ELEMENT_TYPE_VOLUME_FULL
if dmtf.SUPPORT_ELEMENT_EXPAND not in supported_features:
unsupported |= Pool.UNSUPPORTED_VOLUME_GROW
if dmtf.SUPPORT_ELEMENT_REDUCE not in supported_features:
--
1.8.3.1
Gris Ge
2014-10-15 14:31:36 UTC
Permalink
* The pool query will got more element_type:
Pool.ELEMENT_TYPE_VOLUME_THIN
Pool.ELEMENT_TYPE_VOLUME_FULL
indicating the thin provisioning setting of certain pool.
* To have a thin and full pool:
NetApp volume has to set 'guarantee' option to 'file'
* To have a thin only pool:
NetApp volume with 'guarantee' option as 'none' or
NetApp volume with 'guarantee' option as 'volume' with
'fractional_reserve' option less than 100.
* To have a full only pool:
NetApp volume has to set 'guarantee' as 'volume' and
'fractional_reserve' option equal to 100.

* Allow these 'provision' parameter of volume_create:
Volume.PROVISION_DEFAULT
Volume.PROVISION_FULL
Volume.PROVISION_THIN

* As NetApp ONTAP LUN has its own allocation setting[1], we allow user
to create THIN LUN on FULL only pool or FULL LUN on THIN only pool.
So that user can change pool(NetApp volume) setting to achieve their
expectation.

* For Volume.PROVISION_DEFAULT, we create FULL LUN.

[1] LUN could be marked as FULL while pool is a thin only pool.
In ONTAP CLI, it said:
'Space Reservation: enabled (not honored by containing Aggregate)'

Signed-off-by: Gris Ge <***@redhat.com>
---
plugin/ontap/na.py | 6 +++++-
plugin/ontap/ontap.py | 57 +++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 58 insertions(+), 5 deletions(-)

diff --git a/plugin/ontap/na.py b/plugin/ontap/na.py
index 2e00f92..5db7005 100644
--- a/plugin/ontap/na.py
+++ b/plugin/ontap/na.py
@@ -293,12 +293,16 @@ class Filer(object):
def lun_min_size(self):
return self._invoke('lun-get-minsize', {'type': 'image'})['min-size']

- def lun_create(self, full_path_name, size_bytes):
+ def lun_create(self, full_path_name, size_bytes, flag_thin=False):
"""
Creates a lun
+ If flag_thin set to True, will set 'space-reservation-enabled' as
+ 'false' which means "create a LUN without any space being reserved".
"""
params = {'path': full_path_name,
'size': size_bytes}
+ if flag_thin is True:
+ params['space-reservation-enabled'] = 'false'

self._invoke('lun-create-by-size', params)

diff --git a/plugin/ontap/ontap.py b/plugin/ontap/ontap.py
index 77a05fa..31e2366 100644
--- a/plugin/ontap/ontap.py
+++ b/plugin/ontap/ontap.py
@@ -428,6 +428,46 @@ class Ontap(IStorageAreaNetwork, INfs):

def _pool_from_na_vol(self, na_vol, na_aggrs, flags):
element_type = Pool.ELEMENT_TYPE_VOLUME
+ # Thin provisioning is controled by:
+ # 1. NetApp Volume level:
+ # 'guarantee' option and 'fractional_reserve' option.
+ # If 'guarantee' is 'file', 'fractional_reserve' is forced to
+ # be 100, we can create Thin LUN and full allocated LUN.
+ # If 'guarantee' is 'volume' and 'fractional_reserve' is 100, we
+ # can create full LUN.
+ # If 'guarantee' is 'volume' and 'fractional_reserve' is less
+ # than 100, we can only create thin LUN.
+ # If 'guarantee' is 'none', we can only create thin LUN.
+ # 2. NetApp LUN level:
+ # If option 'reservation' is enabled, it's a full allocated LUN
+ # when parent NetApp volume allowed.
+ # If option 'reservation' is disabled, it's a thin LUN if
+ # parent NetApp volume allowed.
+
+ if 'space-reserve' in na_vol and \
+ 'space-reserve-enabled' in na_vol and \
+ 'reserve' in na_vol and \
+ na_vol['space-reserve-enabled'] == 'true':
+ # 'space-reserve' and 'space-reserve-enabled' might not appear if
+ # the flexible volume is restricted or offline.
+ if na_vol['space-reserve'] == 'file':
+ # space-reserve: 'file' means only LUN or file marked as
+ # 'Space Reservation: enabled' will be reserve all space.
+ element_type |= Pool.ELEMENT_TYPE_VOLUME_THIN
+ element_type |= Pool.ELEMENT_TYPE_VOLUME_FULL
+ elif na_vol['space-reserve'] == 'volume':
+ # space-reserve: 'volume' means only LUN or file marked as
+ # 'Space Reservation: enabled' will be reserve all space.
+ if na_vol['reserve'] == na_vol['reserve-required']:
+ # When 'reserve' == 'reserve-required' it means option
+ # 'fractional_reserve' is set to 100, only with that we
+ # can create full alocated LUN.
+ element_type |= Pool.ELEMENT_TYPE_VOLUME_FULL
+ else:
+ element_type |= Pool.ELEMENT_TYPE_VOLUME_THIN
+ elif na_vol['space-reserve'] == 'none':
+ element_type |= Pool.ELEMENT_TYPE_VOLUME_THIN
+
pool_name = na_vol['name']
pool_id = self._pool_id_of_na_vol_name(na_vol['name'])
total_space = int(na_vol['size-total'])
@@ -538,20 +578,29 @@ class Ontap(IStorageAreaNetwork, INfs):
@handle_ontap_errors
def volume_create(self, pool, volume_name, size_bytes, provisioning,
flags=0):
- if provisioning != Volume.PROVISION_DEFAULT:
- raise LsmError(ErrorNumber.INVALID_ARGUMENT,
- "Unsupported provisioning")

if not pool.element_type & Pool.ELEMENT_TYPE_VOLUME:
raise LsmError(ErrorNumber.INVALID_ARGUMENT,
"Pool not suitable for creating volumes")

+ # Even pool is full or thin only pool, we still allow user to
+ # create full or thin LUN in case that's what they intend to do so.
+ # TODO: allow user to query provising status of certain LUN. We can
+ # use THIN(not effective) or FULL(not effective) to indicate
+ # pool setting not allow thin/full LUN yet, user can change pool
+ # setting.
+ # Wise user can check pool.element_type before creating full or thin
+ # volume.
+ flag_thin = False
+ if provisioning == Volume.PROVISION_THIN:
+ flag_thin = True
+
na_vol_name = pool.name

lun_name = self.f.lun_build_name(na_vol_name, volume_name)

try:
- self.f.lun_create(lun_name, size_bytes)
+ self.f.lun_create(lun_name, size_bytes, flag_thin)
except na.FilerError as fe:
if fe.errno == na.FilerError.EVDISK_ERROR_SIZE_TOO_LARGE:
raise LsmError(
--
1.8.3.1
Gris Ge
2014-10-15 14:31:37 UTC
Permalink
* Existing volume_create() of Nstor plugin code indicate Nstor 3.x
support Thin Provisioning, hence show Pool.ELEMENT_TYPE_VOLUME_THIN
when querying pool.

Signed-off-by: Gris Ge <***@redhat.com>
---
plugin/nstor/nstor.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/plugin/nstor/nstor.py b/plugin/nstor/nstor.py
index b4e5759..efa8734 100644
--- a/plugin/nstor/nstor.py
+++ b/plugin/nstor/nstor.py
@@ -143,7 +143,9 @@ 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_VOLUME_THIN | \
+ Pool.ELEMENT_TYPE_FS,
0,
NexentaStor._to_bytes(pool_info['size']),
NexentaStor._to_bytes(pool_info['free']),
--
1.8.3.1
Tony Asleson
2014-10-15 22:16:44 UTC
Permalink
Patch set looks good!

Tested:
- All arrays in snia lab (looking better)
- NetApp simulator
- Nexenta

Thanks,
Tony
Post by Gris Ge
'[PATCH 00/18] Pending patches' # 14 Oct 2014
* This patch set provide a way for creating thin provisioning or full
* Pool.ELEMENT_TYPE_VOLUME
# Can call volume_create() using
# provisioning=Volume.PROVISION_DEFAULT
# This is for back compatibility or user who don't care about
# Thin provisioning. Plugin or Array will use their default setting
# for new volume.
* Pool.ELEMENT_TYPE_VOLUME_THIN
# Can call volume_create() using
# provisioning=Volume.PROVISION_THIN
# Thin provisioned volume is required.
* Pool.ELEMENT_TYPE_VOLUME_FULL
# Can call volume_create() using
# provisioning=Volume.PROVISION_FULL
# Full allocated volume is required.
Library: Add new element_type to pool for thin provisioning.
lsmcli: Add new element types of lsm.Pool.
SMI-S Plugin: Indicate pool thin provisioning status in pool querying.
SMI-S Plugin: Allow provision parameter of volume_create()
ONTAP Plugin: Add thin provisioning support.
Nstor Plugin: Set VOLUME_THIN element type when querying pool.
.../include/libstoragemgmt/libstoragemgmt_types.h | 2 +
plugin/nstor/nstor.py | 4 +-
plugin/ontap/na.py | 6 ++-
plugin/ontap/ontap.py | 57 ++++++++++++++++++++--
plugin/smispy/dmtf.py | 4 +-
plugin/smispy/smis.py | 35 +++++++++++--
plugin/smispy/smis_pool.py | 9 +++-
python_binding/lsm/_data.py | 2 +
tools/lsmcli/data_display.py | 2 +
9 files changed, 106 insertions(+), 15 deletions(-)
Gris Ge
2014-10-16 12:27:36 UTC
Permalink
* This patchset is based on master tree plus:
'[PATCH 00/18] Pending patches' # 14 Oct 2014

* This patch set provide a way for creating thin provisioning or full
allocated volume:
Pool.element_type:
* Pool.ELEMENT_TYPE_VOLUME
# Can call volume_create() using
# provisioning=Volume.PROVISION_DEFAULT
# This is for back compatibility or user who don't care about
# Thin provisioning. Plugin or Array will use their default setting
# for new volume.
* Pool.ELEMENT_TYPE_VOLUME_THIN
# Can call volume_create() using
# provisioning=Volume.PROVISION_THIN
# Thin provisioned volume is required.
* Pool.ELEMENT_TYPE_VOLUME_FULL
# Can call volume_create() using
# provisioning=Volume.PROVISION_FULL
# Full allocated volume is required.

Changes in V2:
* Fix the type of constant used by LSI MegaRAID pool query in patch 3/6:
V1:
return Pool.ELEMENT_TYPE_VOLUME|Pool.ELEMENT_THIN_VOLUME_FULL, 0
^^^^
V2:
return Pool.ELEMENT_TYPE_VOLUME|Pool.ELEMENT_TYPE_VOLUME_FULL, 0
^^^^

Gris Ge (6):
Library: Add new element_type to pool for thin provisioning.
lsmcli: Add new element types of lsm.Pool.
SMI-S Plugin: Indicate pool thin provisioning status in pool querying.
SMI-S Plugin: Allow provision parameter of volume_create()
ONTAP Plugin: Add thin provisioning support.
Nstor Plugin: Set VOLUME_THIN element type when querying pool.

.../include/libstoragemgmt/libstoragemgmt_types.h | 2 +
plugin/nstor/nstor.py | 4 +-
plugin/ontap/na.py | 6 ++-
plugin/ontap/ontap.py | 57 ++++++++++++++++++++--
plugin/smispy/dmtf.py | 4 +-
plugin/smispy/smis.py | 35 +++++++++++--
plugin/smispy/smis_pool.py | 9 +++-
python_binding/lsm/_data.py | 2 +
tools/lsmcli/data_display.py | 2 +
9 files changed, 106 insertions(+), 15 deletions(-)
--
1.8.3.1
Gris Ge
2014-10-16 12:27:37 UTC
Permalink
* Pool.ELEMENT_TYPE_VOLUME_THIN(Python) and
LSM_POOL_ELEMENT_TYPE_VOLUME_THIN(C) indicate current pool can
create thin provisioning volume via:

volume_create(provisioning=Volume.PROVISION_THIN)

* Pool.ELEMENT_TYPE_VOLUME_FULL(Python) and
LSM_POOL_ELEMENT_TYPE_VOLUME_FULL(C) indicate current pool can
create full allocated volume via:

volume_create(provisioning=Volume.PROVISION_FULL)

* To have back compatibility, Pool.ELEMENT_TYPE_VOLUME and
LSM_POOL_ELEMENT_TYPE_VOLUME indicate current pool can create
volume and allowing plugin or array to decide the provisioning type via:

volume_create(provisioning=Volume.PROVISION_DEFAULT)

Signed-off-by: Gris Ge <***@redhat.com>
---
c_binding/include/libstoragemgmt/libstoragemgmt_types.h | 2 ++
python_binding/lsm/_data.py | 2 ++
2 files changed, 4 insertions(+)

diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt_types.h b/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
index 746f397..309a5e8 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
@@ -213,6 +213,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_FULL 0x0000000000000020
+#define LSM_POOL_ELEMENT_TYPE_VOLUME_THIN 0x0000000000000040
#define LSM_POOL_ELEMENT_TYPE_SYS_RESERVED 0x0000000000000400

#define LSM_POOL_UNSUPPORTED_VOLUME_GROW 0x0000000000000001
diff --git a/python_binding/lsm/_data.py b/python_binding/lsm/_data.py
index 74ed65e..067c766 100644
--- a/python_binding/lsm/_data.py
+++ b/python_binding/lsm/_data.py
@@ -344,6 +344,8 @@ class Pool(IData):
ELEMENT_TYPE_VOLUME = 1 << 2
ELEMENT_TYPE_FS = 1 << 3
ELEMENT_TYPE_DELTA = 1 << 4
+ ELEMENT_TYPE_VOLUME_FULL = 1 << 5
+ ELEMENT_TYPE_VOLUME_THIN = 1 << 6
ELEMENT_TYPE_SYS_RESERVED = 1 << 10 # Reserved for system use

# Unsupported actions, what pool cannot be used for
--
1.8.3.1
Gris Ge
2014-10-16 12:27:38 UTC
Permalink
* Add these new element types of lsm.Pool:
lsm.Pool.ELEMENT_TYPE_VOLUME_THIN
lsm.Pool.ELEMENT_TYPE_VOLUME_FULL

Signed-off-by: Gris Ge <***@redhat.com>
---
tools/lsmcli/data_display.py | 2 ++
1 file changed, 2 insertions(+)

diff --git a/tools/lsmcli/data_display.py b/tools/lsmcli/data_display.py
index 75dec6c..1d8f61e 100644
--- a/tools/lsmcli/data_display.py
+++ b/tools/lsmcli/data_display.py
@@ -110,6 +110,8 @@ def pool_status_to_str(pool_status):
_POOL_ELEMENT_TYPE_CONV = {
Pool.ELEMENT_TYPE_POOL: 'POOL',
Pool.ELEMENT_TYPE_VOLUME: 'VOLUME',
+ Pool.ELEMENT_TYPE_VOLUME_THIN: 'VOLUME_THIN',
+ Pool.ELEMENT_TYPE_VOLUME_FULL: 'VOLUME_FULL',
Pool.ELEMENT_TYPE_FS: 'FS',
Pool.ELEMENT_TYPE_SYS_RESERVED: 'SYSTEM_RESERVED',
Pool.ELEMENT_TYPE_DELTA: "DELTA",
--
1.8.3.1
Gris Ge
2014-10-16 12:27:39 UTC
Permalink
* Add the ability to check whether cerntain pool can create
StorageVolume(3) or/and ThinlyProvisionedStorageVolume(5) via
CIM_StorageConfigurationCapabilities['SupportedStorageElementTypes']

Signed-off-by: Gris Ge <***@redhat.com>
---
plugin/smispy/smis_pool.py | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/plugin/smispy/smis_pool.py b/plugin/smispy/smis_pool.py
index fba8931..ca0999e 100644
--- a/plugin/smispy/smis_pool.py
+++ b/plugin/smispy/smis_pool.py
@@ -122,7 +122,7 @@ def _pool_element_type(smis_common, cim_pool):
For MegaRAID, just return (Pool.ELEMENT_TYPE_VOLUME, 0)
"""
if smis_common.is_megaraid():
- return Pool.ELEMENT_TYPE_VOLUME, 0
+ return Pool.ELEMENT_TYPE_VOLUME|Pool.ELEMENT_TYPE_VOLUME_FULL, 0

element_type = 0
unsupported = 0
@@ -142,9 +142,14 @@ def _pool_element_type(smis_common, cim_pool):
cim_scc = cim_sccs[0]
if 'SupportedStorageElementFeatures' in cim_scc:
supported_features = cim_scc['SupportedStorageElementFeatures']
+ supported_types = cim_scc['SupportedStorageElementTypes']

if dmtf.SUPPORT_VOL_CREATE in supported_features:
- element_type |= Pool.ELEMENT_TYPE_VOLUME
+ element_type = Pool.ELEMENT_TYPE_VOLUME
+ if dmtf.ELEMENT_THIN_VOLUME in supported_types:
+ element_type |= Pool.ELEMENT_TYPE_VOLUME_THIN
+ if dmtf.ELEMENT_THICK_VOLUME in supported_types:
+ element_type |= Pool.ELEMENT_TYPE_VOLUME_FULL
if dmtf.SUPPORT_ELEMENT_EXPAND not in supported_features:
unsupported |= Pool.UNSUPPORTED_VOLUME_GROW
if dmtf.SUPPORT_ELEMENT_REDUCE not in supported_features:
--
1.8.3.1
Gris Ge
2014-10-16 12:27:40 UTC
Permalink
* Allow 'provision' parameter of volume_create() to be:
Volume.PROVISION_DEFAULT
Volume.PROVISION_FULL
Volume.PROVISION_THIN

* For Volume.PROVISION_DEFAULT, we create full allocated volume
unless only thin volume is supported. [1]

* For full allocated volume, we set 'ElementType' of
CreateOrModifyElementFromStoragePool() to dmtf.ELEMENT_THICK_VOLUME(2)

* For thin provisioning volume, we set 'ElementType' of
CreateOrModifyElementFromStoragePool() to dmtf.ELEMENT_THIN_VOLUME(5)

* This also fix a bug when running plugin_test.py against HDS AMS where
only dmtf.ELEMENT_THIN_VOLUME(5) is supported.

[1] HDS AMS Thin Pool only support ThinlyProvisionedStorageVolume.

Signed-off-by: Gris Ge <***@redhat.com>
---
plugin/smispy/dmtf.py | 4 ++--
plugin/smispy/smis.py | 35 ++++++++++++++++++++++++++++++-----
2 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/plugin/smispy/dmtf.py b/plugin/smispy/dmtf.py
index 5e30bac..3113b73 100644
--- a/plugin/smispy/dmtf.py
+++ b/plugin/smispy/dmtf.py
@@ -93,8 +93,8 @@ SUPPORT_ELEMENT_REDUCE = 13

# DMTF CIM 2.37.0 experimental CIM_StorageConfigurationCapabilities
# ['SupportedStorageElementTypes']
-ELEMENT_THICK_VOLUME = 2
-ELEMENT_THIN_VOLUME = 5
+ELEMENT_THICK_VOLUME = Uint16(2)
+ELEMENT_THIN_VOLUME = Uint16(5)

# DMTF CIM 2.29.1 CIM_StorageConfigurationCapabilities
# ['SupportedStoragePoolFeatures']
diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index 80c503c..6a2d904 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -35,7 +35,7 @@ import smis_disk
import dmtf

from lsm import (IStorageAreaNetwork, uri_parse, LsmError, ErrorNumber,
- JobStatus, md5, Volume, AccessGroup,
+ JobStatus, md5, Volume, AccessGroup, Pool,
VERSION, TargetPort,
search_property)

@@ -879,9 +879,34 @@ class Smis(IStorageAreaNetwork):
"""
Create a volume.
"""
- if provisioning != Volume.PROVISION_DEFAULT:
- raise LsmError(ErrorNumber.INVALID_ARGUMENT,
- "Unsupported provisioning")
+ # Use user provide lsm.Pool.element_type to speed thing up.
+ if not Pool.ELEMENT_TYPE_VOLUME & pool.element_type:
+ raise LsmError(
+ ErrorNumber.NO_SUPPORT,
+ "Pool not suitable for creating volumes")
+
+ # Use THICK volume by default unless unsupported or user requested.
+ dmtf_element_type = dmtf.ELEMENT_THICK_VOLUME
+
+ if provisioning == Volume.PROVISION_DEFAULT:
+ # Prefer thick/full volume unless only thin volume supported.
+ # HDS AMS only support thin volume in their thin pool.
+ if not Pool.ELEMENT_TYPE_VOLUME_FULL & pool.element_type and \
+ Pool.ELEMENT_TYPE_VOLUME_THIN & pool.element_type:
+ dmtf_element_type = dmtf.ELEMENT_THIN_VOLUME
+ else:
+ # User is requesting certain type of volume
+ if provisioning == Volume.PROVISION_FULL and \
+ Pool.ELEMENT_TYPE_VOLUME_FULL & pool.element_type:
+ dmtf_element_type = dmtf.ELEMENT_THICK_VOLUME
+ elif provisioning == Volume.PROVISION_THIN and \
+ Pool.ELEMENT_TYPE_VOLUME_THIN & pool.element_type:
+ dmtf_element_type = dmtf.ELEMENT_THIN_VOLUME
+ else:
+ raise LsmError(
+ ErrorNumber.NO_SUPPORT,
+ "Pool not suitable for creating volume with "
+ "requested provisioning type")

# Get the Configuration service for the system we are interested in.
scs = self._c.get_class_instance('CIM_StorageConfigurationService',
@@ -890,7 +915,7 @@ class Smis(IStorageAreaNetwork):
self._c, pool)

in_params = {'ElementName': volume_name,
- 'ElementType': pywbem.Uint16(2),
+ 'ElementType': dmtf_element_type,
'InPool': cim_pool_path,
'Size': pywbem.Uint64(size_bytes)}
--
1.8.3.1
Gris Ge
2014-10-16 12:27:41 UTC
Permalink
* The pool query will got more element_type:
Pool.ELEMENT_TYPE_VOLUME_THIN
Pool.ELEMENT_TYPE_VOLUME_FULL
indicating the thin provisioning setting of certain pool.
* To have a thin and full pool:
NetApp volume has to set 'guarantee' option to 'file'
* To have a thin only pool:
NetApp volume with 'guarantee' option as 'none' or
NetApp volume with 'guarantee' option as 'volume' with
'fractional_reserve' option less than 100.
* To have a full only pool:
NetApp volume has to set 'guarantee' as 'volume' and
'fractional_reserve' option equal to 100.

* Allow these 'provision' parameter of volume_create:
Volume.PROVISION_DEFAULT
Volume.PROVISION_FULL
Volume.PROVISION_THIN

* As NetApp ONTAP LUN has its own allocation setting[1], we allow user
to create THIN LUN on FULL only pool or FULL LUN on THIN only pool.
So that user can change pool(NetApp volume) setting to achieve their
expectation.

* For Volume.PROVISION_DEFAULT, we create FULL LUN.

[1] LUN could be marked as FULL while pool is a thin only pool.
In ONTAP CLI, it said:
'Space Reservation: enabled (not honored by containing Aggregate)'

Signed-off-by: Gris Ge <***@redhat.com>
---
plugin/ontap/na.py | 6 +++++-
plugin/ontap/ontap.py | 57 +++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 58 insertions(+), 5 deletions(-)

diff --git a/plugin/ontap/na.py b/plugin/ontap/na.py
index 2e00f92..5db7005 100644
--- a/plugin/ontap/na.py
+++ b/plugin/ontap/na.py
@@ -293,12 +293,16 @@ class Filer(object):
def lun_min_size(self):
return self._invoke('lun-get-minsize', {'type': 'image'})['min-size']

- def lun_create(self, full_path_name, size_bytes):
+ def lun_create(self, full_path_name, size_bytes, flag_thin=False):
"""
Creates a lun
+ If flag_thin set to True, will set 'space-reservation-enabled' as
+ 'false' which means "create a LUN without any space being reserved".
"""
params = {'path': full_path_name,
'size': size_bytes}
+ if flag_thin is True:
+ params['space-reservation-enabled'] = 'false'

self._invoke('lun-create-by-size', params)

diff --git a/plugin/ontap/ontap.py b/plugin/ontap/ontap.py
index 77a05fa..31e2366 100644
--- a/plugin/ontap/ontap.py
+++ b/plugin/ontap/ontap.py
@@ -428,6 +428,46 @@ class Ontap(IStorageAreaNetwork, INfs):

def _pool_from_na_vol(self, na_vol, na_aggrs, flags):
element_type = Pool.ELEMENT_TYPE_VOLUME
+ # Thin provisioning is controled by:
+ # 1. NetApp Volume level:
+ # 'guarantee' option and 'fractional_reserve' option.
+ # If 'guarantee' is 'file', 'fractional_reserve' is forced to
+ # be 100, we can create Thin LUN and full allocated LUN.
+ # If 'guarantee' is 'volume' and 'fractional_reserve' is 100, we
+ # can create full LUN.
+ # If 'guarantee' is 'volume' and 'fractional_reserve' is less
+ # than 100, we can only create thin LUN.
+ # If 'guarantee' is 'none', we can only create thin LUN.
+ # 2. NetApp LUN level:
+ # If option 'reservation' is enabled, it's a full allocated LUN
+ # when parent NetApp volume allowed.
+ # If option 'reservation' is disabled, it's a thin LUN if
+ # parent NetApp volume allowed.
+
+ if 'space-reserve' in na_vol and \
+ 'space-reserve-enabled' in na_vol and \
+ 'reserve' in na_vol and \
+ na_vol['space-reserve-enabled'] == 'true':
+ # 'space-reserve' and 'space-reserve-enabled' might not appear if
+ # the flexible volume is restricted or offline.
+ if na_vol['space-reserve'] == 'file':
+ # space-reserve: 'file' means only LUN or file marked as
+ # 'Space Reservation: enabled' will be reserve all space.
+ element_type |= Pool.ELEMENT_TYPE_VOLUME_THIN
+ element_type |= Pool.ELEMENT_TYPE_VOLUME_FULL
+ elif na_vol['space-reserve'] == 'volume':
+ # space-reserve: 'volume' means only LUN or file marked as
+ # 'Space Reservation: enabled' will be reserve all space.
+ if na_vol['reserve'] == na_vol['reserve-required']:
+ # When 'reserve' == 'reserve-required' it means option
+ # 'fractional_reserve' is set to 100, only with that we
+ # can create full alocated LUN.
+ element_type |= Pool.ELEMENT_TYPE_VOLUME_FULL
+ else:
+ element_type |= Pool.ELEMENT_TYPE_VOLUME_THIN
+ elif na_vol['space-reserve'] == 'none':
+ element_type |= Pool.ELEMENT_TYPE_VOLUME_THIN
+
pool_name = na_vol['name']
pool_id = self._pool_id_of_na_vol_name(na_vol['name'])
total_space = int(na_vol['size-total'])
@@ -538,20 +578,29 @@ class Ontap(IStorageAreaNetwork, INfs):
@handle_ontap_errors
def volume_create(self, pool, volume_name, size_bytes, provisioning,
flags=0):
- if provisioning != Volume.PROVISION_DEFAULT:
- raise LsmError(ErrorNumber.INVALID_ARGUMENT,
- "Unsupported provisioning")

if not pool.element_type & Pool.ELEMENT_TYPE_VOLUME:
raise LsmError(ErrorNumber.INVALID_ARGUMENT,
"Pool not suitable for creating volumes")

+ # Even pool is full or thin only pool, we still allow user to
+ # create full or thin LUN in case that's what they intend to do so.
+ # TODO: allow user to query provising status of certain LUN. We can
+ # use THIN(not effective) or FULL(not effective) to indicate
+ # pool setting not allow thin/full LUN yet, user can change pool
+ # setting.
+ # Wise user can check pool.element_type before creating full or thin
+ # volume.
+ flag_thin = False
+ if provisioning == Volume.PROVISION_THIN:
+ flag_thin = True
+
na_vol_name = pool.name

lun_name = self.f.lun_build_name(na_vol_name, volume_name)

try:
- self.f.lun_create(lun_name, size_bytes)
+ self.f.lun_create(lun_name, size_bytes, flag_thin)
except na.FilerError as fe:
if fe.errno == na.FilerError.EVDISK_ERROR_SIZE_TOO_LARGE:
raise LsmError(
--
1.8.3.1
Gris Ge
2014-10-16 12:27:42 UTC
Permalink
* Existing volume_create() of Nstor plugin code indicate Nstor 3.x
support Thin Provisioning, hence show Pool.ELEMENT_TYPE_VOLUME_THIN
when querying pool.

Signed-off-by: Gris Ge <***@redhat.com>
---
plugin/nstor/nstor.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/plugin/nstor/nstor.py b/plugin/nstor/nstor.py
index b4e5759..efa8734 100644
--- a/plugin/nstor/nstor.py
+++ b/plugin/nstor/nstor.py
@@ -143,7 +143,9 @@ 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_VOLUME_THIN | \
+ Pool.ELEMENT_TYPE_FS,
0,
NexentaStor._to_bytes(pool_info['size']),
NexentaStor._to_bytes(pool_info['free']),
--
1.8.3.1
Continue reading on narkive:
Loading...