Gris Ge
2014-11-06 12:40:50 UTC
* Volume mask will fail with '--init' option[1].
* Update simulator plugin to support creating access group when volume mask.
* Add a test into cmdtest.py for this.
* Manpage updated to guide targetd user.
[1] It's the only way to mask volume to new WWPN/iSCSI IQN on targetd.
Signed-off-by: Gris Ge <***@redhat.com>
---
doc/man/lsmcli.1.in | 10 ++++++++--
plugin/sim/simulator.py | 21 ++++++++++++++++++++-
test/cmdtest.py | 27 +++++++++++++++++++++++++++
tools/lsmcli/cmdline.py | 10 +++++-----
4 files changed, 60 insertions(+), 8 deletions(-)
diff --git a/doc/man/lsmcli.1.in b/doc/man/lsmcli.1.in
index ec4e3eb..0315ca3 100644
--- a/doc/man/lsmcli.1.in
+++ b/doc/man/lsmcli.1.in
@@ -326,13 +326,19 @@ Required. The ID of volume to query access.
.SS volume-mask
.TP 15
Grant access group RW access to certain volume. Like LUN masking
-or NFS export.
+or NFS export. For targetd which does not support creating access group,
+\fB--init\fR could be used for masking volume to new WWPN or iSCSI IQN.
+Either \fB--ag\fR or \f--init\fR should be defined.
.TP
\fB--vol\fR \fI<VOL_ID>\fR
Required. The ID of volume to access.
.TP
\fB--ag\fR \fI<AG_ID>\fR
-Required. The ID of access group to grant.
+Optional. The ID of access group to grant. Conflict with \fB--init\fR option.
+.TP
+\fB--init\fR \fI<INIT_ID>\fR
+Optional. The initiator ID, WWPN or iSCSI IQN. Only used for masking volume
+to new iSCSI IQN or WWPN on targetd.
.SS volume-unmask
.TP 15
diff --git a/plugin/sim/simulator.py b/plugin/sim/simulator.py
index 79b6df5..b350233 100644
--- a/plugin/sim/simulator.py
+++ b/plugin/sim/simulator.py
@@ -17,7 +17,7 @@
# Gris Ge <***@redhat.com>
from lsm import (uri_parse, VERSION, Capabilities, INfs,
- IStorageAreaNetwork, search_property)
+ IStorageAreaNetwork, search_property, LsmError, ErrorNumber)
from simarray import SimArray
@@ -180,6 +180,25 @@ class SimPlugin(INfs, IStorageAreaNetwork):
return SimPlugin._sim_data_2_lsm(sim_ag)
def volume_mask(self, access_group, volume, flags=0):
+ if access_group.id == 0:
+ # access_group.id == 0 means user want to create new access group
+ # when doing volume masking. It's only for targetd.
+ # We support it here purely for testing lsmcli.
+ systems = self.sim_array.systems()
+ system = None
+ for tmp_system in systems:
+ if tmp_system.id == access_group.system_id:
+ system = tmp_system
+ break
+ if system is None:
+ raise LsmError(
+ ErrorNumber.NOT_FOUND_SYSTEM,
+ "System %s not found" % access_group.system_id)
+
+ access_group = self.sim_array.access_group_create(
+ access_group.init_ids[0], access_group.init_ids[0],
+ access_group.init_type, system)
+
return self.sim_array.volume_mask(
access_group.id, volume.id, flags)
diff --git a/test/cmdtest.py b/test/cmdtest.py
index 790fa39..91caa11 100755
--- a/test/cmdtest.py
+++ b/test/cmdtest.py
@@ -46,6 +46,10 @@ from optparse import OptionParser
(SYS_STATUS,) = (2,)
+# access group listing index
+AG_QUERY_ID_INDEX = 0
+AG_QUERY_INIT_IDS_INDEX = 2
+
iqn = ['iqn.1994-05.com.domain:01.89bd01', 'iqn.1994-05.com.domain:01.89bd02']
cmd = "lsmcli"
@@ -214,6 +218,8 @@ def access_group_delete(group_id):
def volume_mask(group, volume_id):
call([cmd, 'volume-mask', '--ag', group, '--vol', volume_id])
+def volume_mask_init(init_id, volume_id):
+ call([cmd, 'volume-mask', '--init', init_id, '--vol', volume_id])
def volume_unmask(group, volume_id):
call([cmd, 'volume-unmask', '--ag', group, '--vol', volume_id])
@@ -617,6 +623,26 @@ def test_mapping(cap, system_id):
if cap['ACCESS_GROUP_DELETE']:
access_group_delete(ag_id)
+def test_volume_mask_init(cap, system_id):
+ # Test volume mask using init id.
+ # Assuming we are testing against simulator
+ pool_id = name_to_id(OP_POOL, test_pool_name)
+ iqn1 = random_iqn()
+ vol_id = create_volume(pool_id)
+ volume_mask_init(iqn1, vol_id)
+ out = call([cmd, '-t' + sep, 'la', '--vol', vol_id])[1]
+ new_ag_id = None
+ for ag in parse(out):
+ if ag[AG_QUERY_INIT_IDS_INDEX] == iqn1:
+ new_ag_id = ag[AG_QUERY_ID_INDEX]
+ break
+ if new_ag_id is None:
+ raise Exception("Failed to find newly created access group by "
+ "volume-mask --init")
+
+ volume_unmask(new_ag_id, vol_id)
+ access_group_delete(new_ag_id)
+ volume_delete(vol_id)
def test_nfs_operations(cap, system_id):
pass
@@ -704,6 +730,7 @@ def run_all_tests(cap, system_id):
create_all(cap, system_id)
test_mapping(cap, system_id)
+ test_volume_mask_init(cap, system_id)
search_test(cap, system_id)
diff --git a/tools/lsmcli/cmdline.py b/tools/lsmcli/cmdline.py
index 66163b3..cd6ca8e 100644
--- a/tools/lsmcli/cmdline.py
+++ b/tools/lsmcli/cmdline.py
@@ -88,7 +88,7 @@ def parse_convert_init(init_id):
if valid:
return (init_id, init_type)
- raise ArgError("--init-id %s is not a valid WWPN or iSCSI IQN" % init_id)
+ raise ArgError("--init %s is not a valid WWPN or iSCSI IQN" % init_id)
## This class represents a command line argument error
@@ -327,9 +327,9 @@ cmds = (
],
optional=[
dict(ag_id_opt),
- dict(name='--init', metavar='<INIT_ID>', action='append',
- help='Initiator ID, only used when access-group-create is '
- 'not supported'),
+ dict(name='--init', metavar='<INIT_ID>',
+ help='Initiator ID, only used for masking new WWPN/iSCSI '
+ 'IQN on targetd not supported'),
],
),
@@ -959,7 +959,7 @@ class CmdLine:
def iscsi_chap(self, args):
(init_id, init_type) = parse_convert_init(args.init)
if init_type != AccessGroup.INIT_TYPE_ISCSI_IQN:
- raise ArgError("--init-id %s is not a valid iSCSI IQN" % args.init)
+ raise ArgError("--init %s is not a valid iSCSI IQN" % args.init)
self.c.iscsi_chap_auth(init_id, args.in_user,
self.args.in_pass,
* Update simulator plugin to support creating access group when volume mask.
* Add a test into cmdtest.py for this.
* Manpage updated to guide targetd user.
[1] It's the only way to mask volume to new WWPN/iSCSI IQN on targetd.
Signed-off-by: Gris Ge <***@redhat.com>
---
doc/man/lsmcli.1.in | 10 ++++++++--
plugin/sim/simulator.py | 21 ++++++++++++++++++++-
test/cmdtest.py | 27 +++++++++++++++++++++++++++
tools/lsmcli/cmdline.py | 10 +++++-----
4 files changed, 60 insertions(+), 8 deletions(-)
diff --git a/doc/man/lsmcli.1.in b/doc/man/lsmcli.1.in
index ec4e3eb..0315ca3 100644
--- a/doc/man/lsmcli.1.in
+++ b/doc/man/lsmcli.1.in
@@ -326,13 +326,19 @@ Required. The ID of volume to query access.
.SS volume-mask
.TP 15
Grant access group RW access to certain volume. Like LUN masking
-or NFS export.
+or NFS export. For targetd which does not support creating access group,
+\fB--init\fR could be used for masking volume to new WWPN or iSCSI IQN.
+Either \fB--ag\fR or \f--init\fR should be defined.
.TP
\fB--vol\fR \fI<VOL_ID>\fR
Required. The ID of volume to access.
.TP
\fB--ag\fR \fI<AG_ID>\fR
-Required. The ID of access group to grant.
+Optional. The ID of access group to grant. Conflict with \fB--init\fR option.
+.TP
+\fB--init\fR \fI<INIT_ID>\fR
+Optional. The initiator ID, WWPN or iSCSI IQN. Only used for masking volume
+to new iSCSI IQN or WWPN on targetd.
.SS volume-unmask
.TP 15
diff --git a/plugin/sim/simulator.py b/plugin/sim/simulator.py
index 79b6df5..b350233 100644
--- a/plugin/sim/simulator.py
+++ b/plugin/sim/simulator.py
@@ -17,7 +17,7 @@
# Gris Ge <***@redhat.com>
from lsm import (uri_parse, VERSION, Capabilities, INfs,
- IStorageAreaNetwork, search_property)
+ IStorageAreaNetwork, search_property, LsmError, ErrorNumber)
from simarray import SimArray
@@ -180,6 +180,25 @@ class SimPlugin(INfs, IStorageAreaNetwork):
return SimPlugin._sim_data_2_lsm(sim_ag)
def volume_mask(self, access_group, volume, flags=0):
+ if access_group.id == 0:
+ # access_group.id == 0 means user want to create new access group
+ # when doing volume masking. It's only for targetd.
+ # We support it here purely for testing lsmcli.
+ systems = self.sim_array.systems()
+ system = None
+ for tmp_system in systems:
+ if tmp_system.id == access_group.system_id:
+ system = tmp_system
+ break
+ if system is None:
+ raise LsmError(
+ ErrorNumber.NOT_FOUND_SYSTEM,
+ "System %s not found" % access_group.system_id)
+
+ access_group = self.sim_array.access_group_create(
+ access_group.init_ids[0], access_group.init_ids[0],
+ access_group.init_type, system)
+
return self.sim_array.volume_mask(
access_group.id, volume.id, flags)
diff --git a/test/cmdtest.py b/test/cmdtest.py
index 790fa39..91caa11 100755
--- a/test/cmdtest.py
+++ b/test/cmdtest.py
@@ -46,6 +46,10 @@ from optparse import OptionParser
(SYS_STATUS,) = (2,)
+# access group listing index
+AG_QUERY_ID_INDEX = 0
+AG_QUERY_INIT_IDS_INDEX = 2
+
iqn = ['iqn.1994-05.com.domain:01.89bd01', 'iqn.1994-05.com.domain:01.89bd02']
cmd = "lsmcli"
@@ -214,6 +218,8 @@ def access_group_delete(group_id):
def volume_mask(group, volume_id):
call([cmd, 'volume-mask', '--ag', group, '--vol', volume_id])
+def volume_mask_init(init_id, volume_id):
+ call([cmd, 'volume-mask', '--init', init_id, '--vol', volume_id])
def volume_unmask(group, volume_id):
call([cmd, 'volume-unmask', '--ag', group, '--vol', volume_id])
@@ -617,6 +623,26 @@ def test_mapping(cap, system_id):
if cap['ACCESS_GROUP_DELETE']:
access_group_delete(ag_id)
+def test_volume_mask_init(cap, system_id):
+ # Test volume mask using init id.
+ # Assuming we are testing against simulator
+ pool_id = name_to_id(OP_POOL, test_pool_name)
+ iqn1 = random_iqn()
+ vol_id = create_volume(pool_id)
+ volume_mask_init(iqn1, vol_id)
+ out = call([cmd, '-t' + sep, 'la', '--vol', vol_id])[1]
+ new_ag_id = None
+ for ag in parse(out):
+ if ag[AG_QUERY_INIT_IDS_INDEX] == iqn1:
+ new_ag_id = ag[AG_QUERY_ID_INDEX]
+ break
+ if new_ag_id is None:
+ raise Exception("Failed to find newly created access group by "
+ "volume-mask --init")
+
+ volume_unmask(new_ag_id, vol_id)
+ access_group_delete(new_ag_id)
+ volume_delete(vol_id)
def test_nfs_operations(cap, system_id):
pass
@@ -704,6 +730,7 @@ def run_all_tests(cap, system_id):
create_all(cap, system_id)
test_mapping(cap, system_id)
+ test_volume_mask_init(cap, system_id)
search_test(cap, system_id)
diff --git a/tools/lsmcli/cmdline.py b/tools/lsmcli/cmdline.py
index 66163b3..cd6ca8e 100644
--- a/tools/lsmcli/cmdline.py
+++ b/tools/lsmcli/cmdline.py
@@ -88,7 +88,7 @@ def parse_convert_init(init_id):
if valid:
return (init_id, init_type)
- raise ArgError("--init-id %s is not a valid WWPN or iSCSI IQN" % init_id)
+ raise ArgError("--init %s is not a valid WWPN or iSCSI IQN" % init_id)
## This class represents a command line argument error
@@ -327,9 +327,9 @@ cmds = (
],
optional=[
dict(ag_id_opt),
- dict(name='--init', metavar='<INIT_ID>', action='append',
- help='Initiator ID, only used when access-group-create is '
- 'not supported'),
+ dict(name='--init', metavar='<INIT_ID>',
+ help='Initiator ID, only used for masking new WWPN/iSCSI '
+ 'IQN on targetd not supported'),
],
),
@@ -959,7 +959,7 @@ class CmdLine:
def iscsi_chap(self, args):
(init_id, init_type) = parse_convert_init(args.init)
if init_type != AccessGroup.INIT_TYPE_ISCSI_IQN:
- raise ArgError("--init-id %s is not a valid iSCSI IQN" % args.init)
+ raise ArgError("--init %s is not a valid iSCSI IQN" % args.init)
self.c.iscsi_chap_auth(init_id, args.in_user,
self.args.in_pass,
--
1.8.3.1
------------------------------------------------------------------------------
1.8.3.1
------------------------------------------------------------------------------