* Add support of these methods:
* volume_create_raid()
* volume_create_raid_cap_get()
* Add 'strip_size' property into pool.
* Add 'is_hw_raid_vol' property into volume.
If true, volume_delete() will also delete parent pool.
* Bumped data version to 3.4.
Changes in V3:
* Rebased to the pool_raid_info->pool_member_info changes.
Changes in V4:
* Method renamed to volume_raid_create().
Signed-off-by: Gris Ge <fge(a)redhat.com>
---
plugin/sim/simarray.py | 119 ++++++++++++++++++++++++++++++++++++++++++------
plugin/sim/simulator.py | 8 ++++
2 files changed, 113 insertions(+), 14 deletions(-)
diff --git a/plugin/sim/simarray.py b/plugin/sim/simarray.py
index a0809f6..3b4ec2a 100644
--- a/plugin/sim/simarray.py
+++ b/plugin/sim/simarray.py
@@ -123,7 +123,7 @@ def data_disk_count(raid_type, disk_count):
class BackStore(object):
- VERSION = "3.3"
+ VERSION = "3.4"
VERSION_SIGNATURE = 'LSM_SIMULATOR_DATA_%s_%s' % (VERSION, md5(VERSION))
JOB_DEFAULT_DURATION = 1
JOB_DATA_TYPE_VOL = 1
@@ -133,7 +133,7 @@ class BackStore(object):
SYS_ID = "sim-01"
SYS_NAME = "LSM simulated storage plug-in"
BLK_SIZE = 512
- STRIP_SIZE = 131072 # 128 KiB
+ DEFAULT_STRIP_SIZE = 128 * 1024 # 128 KiB
_LIST_SPLITTER = '#'
@@ -142,7 +142,8 @@ class BackStore(object):
POOL_KEY_LIST = [
'id', 'name', 'status', 'status_info',
'element_type', 'unsupported_actions', 'raid_type',
- 'member_type', 'parent_pool_id', 'total_space',
'free_space']
+ 'member_type', 'parent_pool_id', 'total_space',
'free_space',
+ 'strip_size']
DISK_KEY_LIST = [
'id', 'name', 'total_space', 'disk_type',
'status',
@@ -150,7 +151,7 @@ class BackStore(object):
VOL_KEY_LIST = [
'id', 'vpd83', 'name', 'total_space',
'consumed_size',
- 'pool_id', 'admin_state', 'thinp']
+ 'pool_id', 'admin_state', 'thinp',
'is_hw_raid_vol']
TGT_KEY_LIST = [
'id', 'port_type', 'service_address',
'network_address',
@@ -172,6 +173,16 @@ class BackStore(object):
'options', 'exp_root_hosts_str', 'exp_rw_hosts_str',
'exp_ro_hosts_str']
+ SUPPORTED_VCR_RAID_TYPES = [
+ Volume.RAID_TYPE_RAID0, Volume.RAID_TYPE_RAID1,
+ Volume.RAID_TYPE_RAID5, Volume.RAID_TYPE_RAID6,
+ Volume.RAID_TYPE_RAID10, Volume.RAID_TYPE_RAID50,
+ Volume.RAID_TYPE_RAID60]
+
+ SUPPORTED_VCR_STRIP_SIZES = [
+ 8 * 1024, 16 * 1024, 32 * 1024, 64 * 1024, 128 * 1024, 256 * 1024,
+ 512 * 1024, 1024 * 1024]
+
def __init__(self, statefile, timeout):
if not os.path.exists(statefile):
os.close(os.open(statefile, os.O_WRONLY | os.O_CREAT))
@@ -218,6 +229,7 @@ def __init__(self, statefile, timeout):
"parent_pool_id INTEGER, " # Indicate this pool is allocated from
# other pool
"member_type INTEGER, "
+ "strip_size INTEGER, "
"total_space LONG);\n") # total_space here is only for
# sub-pool (pool from pool)
@@ -244,6 +256,10 @@ def __init__(self, statefile, timeout):
# support.
"admin_state INTEGER, "
"thinp INTEGER NOT NULL, "
+ "is_hw_raid_vol INTEGER, " # Once its volume deleted, pool will
+ # be delete also. For HW RAID
+ # simulation only.
+
"pool_id INTEGER NOT NULL, "
"FOREIGN KEY(pool_id) "
"REFERENCES pools(id) ON DELETE CASCADE);\n")
@@ -362,6 +378,7 @@ def __init__(self, statefile, timeout):
pool0.raid_type,
pool0.member_type,
pool0.parent_pool_id,
+ pool0.strip_size,
pool1.total_space total_space,
pool1.total_space -
pool2.vol_consumed_size -
@@ -450,6 +467,7 @@ def __init__(self, statefile, timeout):
vol.pool_id,
vol.admin_state,
vol.thinp,
+ vol.is_hw_raid_vol,
vol_mask.ag_id ag_id
FROM
volumes vol
@@ -926,7 +944,11 @@ def sim_pool_of_id(self, sim_pool_id):
ErrorNumber.NOT_FOUND_POOL, "Pool")
def sim_pool_create_from_disk(self, name, sim_disk_ids, raid_type,
- element_type, unsupported_actions=0):
+ element_type, unsupported_actions=0,
+ strip_size=0):
+ if strip_size == 0:
+ strip_size = BackStore.DEFAULT_STRIP_SIZE
+
self._data_add(
'pools',
{
@@ -937,6 +959,7 @@ def sim_pool_create_from_disk(self, name, sim_disk_ids, raid_type,
'unsupported_actions': unsupported_actions,
'raid_type': raid_type,
'member_type': Pool.MEMBER_TYPE_DISK,
+ 'strip_size': strip_size,
})
data_disk_count = PoolRAID.data_disk_count(
@@ -1029,7 +1052,9 @@ def _block_rounding(size_bytes):
return (size_bytes + BackStore.BLK_SIZE - 1) / \
BackStore.BLK_SIZE * BackStore.BLK_SIZE
- def sim_vol_create(self, name, size_bytes, sim_pool_id, thinp):
+ def sim_vol_create(self, name, size_bytes, sim_pool_id, thinp,
+ is_hw_raid_vol=0):
+
size_bytes = BackStore._block_rounding(size_bytes)
self._check_pool_free_space(sim_pool_id, size_bytes)
sim_vol = dict()
@@ -1040,6 +1065,7 @@ def sim_vol_create(self, name, size_bytes, sim_pool_id, thinp):
sim_vol['total_space'] = size_bytes
sim_vol['consumed_size'] = size_bytes
sim_vol['admin_state'] = Volume.ADMIN_STATE_ENABLED
+ sim_vol['is_hw_raid_vol'] = is_hw_raid_vol
try:
self._data_add("volumes", sim_vol)
@@ -1055,7 +1081,7 @@ def sim_vol_delete(self, sim_vol_id):
This does not check whether volume exist or not.
"""
# Check existence.
- self.sim_vol_of_id(sim_vol_id)
+ sim_vol = self.sim_vol_of_id(sim_vol_id)
if self._sim_ag_ids_of_masked_vol(sim_vol_id):
raise LsmError(
@@ -1070,8 +1096,11 @@ def sim_vol_delete(self, sim_vol_id):
raise LsmError(
ErrorNumber.PLUGIN_BUG,
"Requested volume is a replication source")
-
- self._data_delete("volumes", 'id="%s"' % sim_vol_id)
+ if sim_vol['is_hw_raid_vol']:
+ # Delete the parent pool instead if found a HW RAID volume.
+ self._data_delete("pools", 'id="%s"' %
sim_vol['pool_id'])
+ else:
+ self._data_delete("volumes", 'id="%s"' %
sim_vol_id)
def sim_vol_mask(self, sim_vol_id, sim_ag_id):
self.sim_vol_of_id(sim_vol_id)
@@ -1759,7 +1788,7 @@ def disks(self):
@_handle_errors
def volume_create(self, pool_id, vol_name, size_bytes, thinp, flags=0,
- _internal_use=False):
+ _internal_use=False, _is_hw_raid_vol=0):
"""
The '_internal_use' parameter is only for SimArray internal use.
This method will return the new sim_vol id instead of job_id when
@@ -1769,7 +1798,8 @@ def volume_create(self, pool_id, vol_name, size_bytes, thinp,
flags=0,
self.bs_obj.trans_begin()
new_sim_vol_id = self.bs_obj.sim_vol_create(
- vol_name, size_bytes, SimArray._sim_pool_id_of(pool_id), thinp)
+ vol_name, size_bytes, SimArray._sim_pool_id_of(pool_id),
+ thinp, is_hw_raid_vol=_is_hw_raid_vol)
if _internal_use:
return new_sim_vol_id
@@ -2251,9 +2281,9 @@ def volume_raid_info(self, lsm_vol):
min_io_size = BackStore.BLK_SIZE
opt_io_size = BackStore.BLK_SIZE
else:
- strip_size = BackStore.STRIP_SIZE
- min_io_size = BackStore.STRIP_SIZE
- opt_io_size = int(data_disk_count * BackStore.STRIP_SIZE)
+ strip_size = sim_pool['strip_size']
+ min_io_size = strip_size
+ opt_io_size = int(data_disk_count * strip_size)
return [raid_type, strip_size, disk_count, min_io_size, opt_io_size]
@@ -2278,3 +2308,64 @@ def pool_member_info(self, lsm_pool):
member_type = Pool.MEMBER_TYPE_UNKNOWN
return sim_pool['raid_type'], member_type, member_ids
+
+ @_handle_errors
+ def volume_raid_create_cap_get(self, system):
+ if system.id != BackStore.SYS_ID:
+ raise LsmError(
+ ErrorNumber.NOT_FOUND_SYSTEM,
+ "System not found")
+ return (
+ BackStore.SUPPORTED_VCR_RAID_TYPES,
+ BackStore.SUPPORTED_VCR_STRIP_SIZES)
+
+ @_handle_errors
+ def volume_raid_create(self, name, raid_type, disks, strip_size):
+ if raid_type not in BackStore.SUPPORTED_VCR_RAID_TYPES:
+ raise LsmError(
+ ErrorNumber.NO_SUPPORT,
+ "Provided 'raid_type' is not supported")
+
+ if strip_size == Volume.VCR_STRIP_SIZE_DEFAULT:
+ strip_size = BackStore.DEFAULT_STRIP_SIZE
+ elif strip_size not in BackStore.SUPPORTED_VCR_STRIP_SIZES:
+ raise LsmError(
+ ErrorNumber.NO_SUPPORT,
+ "Provided 'strip_size' is not supported")
+
+ self.bs_obj.trans_begin()
+ pool_name = "Pool for volume %s" % name
+ sim_disk_ids = [
+ SimArray._lsm_id_to_sim_id(
+ d.id,
+ LsmError(ErrorNumber.NOT_FOUND_DISK, "Disk not found"))
+ for d in disks]
+
+ for disk in disks:
+ if not disk.status & Disk.STATUS_FREE:
+ raise LsmError(
+ ErrorNumber.DISK_NOT_FREE,
+ "Disk %s is not in DISK.STATUS_FREE mode" % disk.id)
+ try:
+ sim_pool_id = self.bs_obj.sim_pool_create_from_disk(
+ name=pool_name,
+ raid_type=raid_type,
+ sim_disk_ids=sim_disk_ids,
+ element_type=Pool.ELEMENT_TYPE_VOLUME,
+ unsupported_actions=Pool.UNSUPPORTED_VOLUME_GROW |
+ Pool.UNSUPPORTED_VOLUME_SHRINK,
+ strip_size=strip_size)
+ except sqlite3.IntegrityError as sql_error:
+ raise LsmError(
+ ErrorNumber.NAME_CONFLICT,
+ "Name '%s' is already in use by other volume" % name)
+
+
+ sim_pool = self.bs_obj.sim_pool_of_id(sim_pool_id)
+ sim_vol_id = self.volume_create(
+ SimArray._sim_id_to_lsm_id(sim_pool_id, 'POOL'), name,
+ sim_pool['free_space'], Volume.PROVISION_FULL,
+ _internal_use=True, _is_hw_raid_vol=1)
+ sim_vol = self.bs_obj.sim_vol_of_id(sim_vol_id)
+ self.bs_obj.trans_commit()
+ return SimArray._sim_vol_2_lsm(sim_vol)
diff --git a/plugin/sim/simulator.py b/plugin/sim/simulator.py
index 724574f..610ab81 100644
--- a/plugin/sim/simulator.py
+++ b/plugin/sim/simulator.py
@@ -295,3 +295,11 @@ def volume_raid_info(self, volume, flags=0):
def pool_member_info(self, pool, flags=0):
return self.sim_array.pool_member_info(pool)
+
+ def volume_raid_create_cap_get(self, system, flags=0):
+ return self.sim_array.volume_raid_create_cap_get(system)
+
+ def volume_raid_create(self, name, raid_type, disks, strip_size,
+ flags=0):
+ return self.sim_array.volume_raid_create(
+ name, raid_type, disks, strip_size)
--
1.8.3.1