Discussion:
[Libstoragemgmt-devel] [PATCH 05/14] nstor.py: Get plugin_test.py to pass
Tony Asleson
2014-09-07 05:45:39 UTC
Permalink
Fixed a number of issue with the nstor plugin.

Signed-off-by: Tony Asleson <***@redhat.com>
---
plugin/nstor/nstor.py | 51 +++++++++++++++++++++++++++++++++++++++------------
1 file changed, 39 insertions(+), 12 deletions(-)

diff --git a/plugin/nstor/nstor.py b/plugin/nstor/nstor.py
index 005d567..b4e5759 100644
--- a/plugin/nstor/nstor.py
+++ b/plugin/nstor/nstor.py
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2013 Nexenta Systems, Inc.
+# Copyright (C) 2013-2014 Nexenta Systems, Inc.
# All rights reserved.
#
# This library is free software; you can redistribute it and/or
@@ -83,6 +83,16 @@ class NexentaStor(INfs, IStorageAreaNetwork):
resp_json = response.read()
resp = json.loads(resp_json)
if resp['error']:
+
+ if 'message' in resp['error']:
+ msg = resp['error']['message']
+ # Check to see if there is a better way to do this...
+ if 'dataset already exists' in msg:
+ raise LsmError(ErrorNumber.NAME_CONFLICT, msg)
+
+ if 'Unable to destroy hostgroup' in msg:
+ raise LsmError(ErrorNumber.IS_MASKED, msg)
+
raise LsmError(ErrorNumber.PLUGIN_BUG, resp['error'])
return resp['result']

@@ -174,7 +184,7 @@ class NexentaStor(INfs, IStorageAreaNetwork):
if name.startswith(pool.name + '/'):
chunks = name.split('/')[1:]
name = '/'.join(chunks)
- fs_name = self._request("create", "folder", [pool.name, name])
+ fs_name = self._request("create", "folder", [pool.name, name])[0]
filesystem = FileSystem(fs_name, fs_name, pool.total_space,
pool.free_space, pool.id, fs_name)
return None, filesystem
@@ -456,7 +466,7 @@ class NexentaStor(INfs, IStorageAreaNetwork):
try:
lu_props = self._request("get_lu_props", "scsidisk", [lu])
except:
- lu_props = {'guid': 'N/A', 'state': 'N/A'}
+ lu_props = {'guid': '', 'state': 'N/A'}

zvol_props = self._request("get_child_props", "zvol", [lu, ""])

@@ -505,12 +515,8 @@ class NexentaStor(INfs, IStorageAreaNetwork):
[name, 'logbias', 'throughput'])

self._request("create_lu", "scsidisk", [name, []])
-
- new_volume = Volume(name, name, '', 8192, size_bytes / 8192,
- Volume.ADMIN_STATE_ENABLED, '',
- pool.id) # FIXhttp://192.168.0.1/st_wlan.phpME
- # replace with list request
- return None, new_volume
+ vols = self.volumes('id', name)
+ return None, vols[0]

@handle_nstor_errors
def volume_delete(self, volume, flags=0):
@@ -519,6 +525,12 @@ class NexentaStor(INfs, IStorageAreaNetwork):

Returns None on success, else raises an LsmError
"""
+ ag = self.access_groups_granted_to_volume(volume)
+
+ if len(ag):
+ raise LsmError(ErrorNumber.IS_MASKED,
+ "Volume is masked to access group")
+
self._request("delete_lu", "scsidisk", [volume.id])
self._request("destroy", "zvol", [volume.id, ''])
return
@@ -538,7 +550,8 @@ class NexentaStor(INfs, IStorageAreaNetwork):
new_num_of_blocks = new_size_bytes / volume.block_size
return None, Volume(volume.id, volume.name, volume.vpd83,
volume.block_size, new_num_of_blocks,
- volume.status, volume.system_id, volume.pool_id)
+ volume.admin_state, volume.system_id,
+ volume.pool_id)

@handle_nstor_errors
def volume_replicate(self, pool, rep_type, volume_src, name, flags=0):
@@ -626,8 +639,13 @@ class NexentaStor(INfs, IStorageAreaNetwork):
return

def _get_views(self, volume_name):
- return self._request("list_lun_mapping_entries", "scsidisk",
- [volume_name])
+ results = []
+ try:
+ results = self._request("list_lun_mapping_entries", "scsidisk",
+ [volume_name])
+ except Exception:
+ pass
+ return results

def _volume_mask(self, group_name, volume_name):
self._request("add_lun_mapping_entry", "scsidisk",
@@ -694,6 +712,10 @@ class NexentaStor(INfs, IStorageAreaNetwork):
raise LsmError(ErrorNumber.EXISTS_INITIATOR,
"%s is already part of %s access group" %
(init_id, ag.name))
+
+ if name == ag.name:
+ raise LsmError(ErrorNumber.NAME_CONFLICT,
+ "Access group with name exists!")
self._request("create_hostgroup", "stmf", [name])
self._add_initiator(name, init_id)

@@ -704,6 +726,11 @@ class NexentaStor(INfs, IStorageAreaNetwork):
"""
Deletes an access group
"""
+ vols = self.volumes_accessible_by_access_group(access_group)
+ if len(vols):
+ raise LsmError(ErrorNumber.IS_MASKED,
+ "Access Group has volume(s) masked")
+
self._request("destroy_hostgroup", "stmf", [access_group.name])
return
--
1.8.2.1
Tony Asleson
2014-09-07 05:45:35 UTC
Permalink
No plugins/arrays we have support for support the ability to make
a read only point in time copy of a volume. We can add this back later
if this proves to be incorrect.

Signed-off-by: Tony Asleson <***@redhat.com>
---
c_binding/include/libstoragemgmt/libstoragemgmt_types.h | 1 -
plugin/nstor/nstor.py | 4 +---
plugin/smispy/smis.py | 3 +--
python_binding/lsm/_data.py | 1 -
test/tester.c | 6 +++---
tools/lsmcli/cmdline.py | 4 ++--
tools/lsmcli/data_display.py | 1 -
7 files changed, 7 insertions(+), 13 deletions(-)

diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt_types.h b/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
index c020641..238ef06 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
@@ -117,7 +117,6 @@ typedef struct _lsm_target_port lsm_target_port;
/**< \enum lsm_replication_type Different types of replications that can be created */
typedef enum {
LSM_VOLUME_REPLICATE_UNKNOWN = -1, /**< Unknown replicate */
- LSM_VOLUME_REPLICATE_SNAPSHOT = 1, /**< Space efficient read only copy*/
LSM_VOLUME_REPLICATE_CLONE = 2, /**< Space efficient copy */
LSM_VOLUME_REPLICATE_COPY = 3, /**< Full bitwise copy */
LSM_VOLUME_REPLICATE_MIRROR_SYNC = 4, /**< Mirrors always in sync */
diff --git a/plugin/nstor/nstor.py b/plugin/nstor/nstor.py
index bcb948f..005d567 100644
--- a/plugin/nstor/nstor.py
+++ b/plugin/nstor/nstor.py
@@ -553,9 +553,7 @@ class NexentaStor(INfs, IStorageAreaNetwork):
raise LsmError(ErrorNumber.NO_SUPPORT,
"volume_replicate not implemented")

- # if rep_type == Volume.REPLICATE_SNAPSHOT:
- # return
- # elif rep_type == Volume.REPLICATE_CLONE:
+ # if rep_type == Volume.REPLICATE_CLONE:
# return
# elif rep_type == Volume.REPLICATE_COPY:
# return
diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index 14f1ce9..ead15c8 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -1915,8 +1915,7 @@ class Smis(IStorageAreaNetwork):
rc[0] = Smis.SYNC_TYPE_MIRROR
rc[1] = Smis.CREATE_ELEMENT_REPLICA_MODE_SYNC

- elif rep_type == Volume.REPLICATE_CLONE \
- or rep_type == Volume.REPLICATE_SNAPSHOT:
+ elif rep_type == Volume.REPLICATE_CLONE:
if self.RepSvc.RepTypes.SYNC_CLONE_LOCAL in s_rt:
rc[0] = Smis.SYNC_TYPE_SNAPSHOT
rc[1] = Smis.CREATE_ELEMENT_REPLICA_MODE_SYNC
diff --git a/python_binding/lsm/_data.py b/python_binding/lsm/_data.py
index 2fb1d1f..74ed65e 100644
--- a/python_binding/lsm/_data.py
+++ b/python_binding/lsm/_data.py
@@ -244,7 +244,6 @@ class Volume(IData):

#Replication types
REPLICATE_UNKNOWN = -1
- REPLICATE_SNAPSHOT = 1
REPLICATE_CLONE = 2
REPLICATE_COPY = 3
REPLICATE_MIRROR_SYNC = 4
diff --git a/test/tester.c b/test/tester.c
index 4cf2f28..150c38b 100644
--- a/test/tester.c
+++ b/test/tester.c
@@ -585,10 +585,10 @@ START_TEST(test_smoke_test)

G(rc, lsm_volume_record_free, resized);

- //Lets create a snapshot of one.
+ //Lets create a clone of one.
int repRc = lsm_volume_replicate(c, NULL, //Pool is optional
- LSM_VOLUME_REPLICATE_SNAPSHOT,
- volumes[0], "SNAPSHOT1",
+ LSM_VOLUME_REPLICATE_CLONE,
+ volumes[0], "CLONE1",
&rep, &job, LSM_CLIENT_FLAG_RSVD);

fail_unless(repRc == LSM_ERR_OK || repRc == LSM_ERR_JOB_STARTED,
diff --git a/tools/lsmcli/cmdline.py b/tools/lsmcli/cmdline.py
index d24f8f3..a34fa30 100644
--- a/tools/lsmcli/cmdline.py
+++ b/tools/lsmcli/cmdline.py
@@ -125,7 +125,7 @@ list_choices = ['VOLUMES', 'POOLS', 'FS', 'SNAPSHOTS',
provision_types = ('DEFAULT', 'THIN', 'FULL')
provision_help = "provisioning type: " + ", ".join(provision_types)

-replicate_types = ('SNAPSHOT', 'CLONE', 'COPY', 'MIRROR_ASYNC', 'MIRROR_SYNC')
+replicate_types = ('CLONE', 'COPY', 'MIRROR_ASYNC', 'MIRROR_SYNC')
replicate_help = "replication type: " + ", ".join(replicate_types)

size_help = 'Can use B, KiB, MiB, GiB, TiB, PiB postfix (IEC sizing)'
@@ -276,7 +276,7 @@ cmds = (
'This is repeatable argument.',
action='append'),
dict(name="--dst-start", metavar='<DST_START_BLK>',
- help='destination volume start block number.\n'
+ help='Destination volume start block number.\n'
'This is repeatable argument.',
action='append'),
dict(name="--count", metavar='<BLK_COUNT>',
diff --git a/tools/lsmcli/data_display.py b/tools/lsmcli/data_display.py
index b122b8b..75dec6c 100644
--- a/tools/lsmcli/data_display.py
+++ b/tools/lsmcli/data_display.py
@@ -152,7 +152,6 @@ def vol_admin_state_to_str(vol_admin_state):


_VOL_REP_TYPE_CONV = {
- Volume.REPLICATE_SNAPSHOT: 'SNAPSHOT',
Volume.REPLICATE_CLONE: 'CLONE',
Volume.REPLICATE_COPY: 'COPY',
Volume.REPLICATE_MIRROR_SYNC: 'MIRROR_SYNC',
--
1.8.2.1
Tony Asleson
2014-09-07 05:45:36 UTC
Permalink
Signed-off-by: Tony Asleson <***@redhat.com>
---
doc/man/lsmcli.1.in | 193 ++++++++++++++++++++++++------------------------
tools/lsmcli/cmdline.py | 10 +--
2 files changed, 101 insertions(+), 102 deletions(-)

diff --git a/doc/man/lsmcli.1.in b/doc/man/lsmcli.1.in
index 7d96fb5..93b2b88 100644
--- a/doc/man/lsmcli.1.in
+++ b/doc/man/lsmcli.1.in
@@ -1,6 +1,6 @@
-.TH LSMCLI "1" "June 2014" "lsmcli @VERSION@" "libStorageMgmt"
+.TH LSMCLI "1" "September 2014" "lsmcli @VERSION@" "libStorageMgmt"
.SH NAME
-lsmcli - LibStorageMgmt command line interface
+lsmcli - libStorageMgmt command line interface

.SH SYNOPSIS
.B lsmcli \fIcommand\fR [\fIGLOBAL OPTIONS\fR]...[\fICOMMAND OPTIONS\fR]...
@@ -12,13 +12,12 @@ management of their storage.

.SH PREREQUISITES
.TP 8
-* libstoragemgmt daemon.
-The daemon '\fBlsmd\fR' is needed by every lsmcli command for socket initial
-communication.
+* libStorageMgmt daemon.
+The daemon '\fBlsmd\fR' is required by lsmcli.
.TP 8
* URI(Uniform Resource Identifier)
-URI is used to in deify which and how the plugin should communicate with
-storage array. The valid URI format is:
+URI is used to identify which plugin to use and how the plugin should
+communicate with the storage array. The valid URI format is:
.RS 12
.nf
\fBplugin://<username>@host:<port>?<query_string_parameters>\fR
@@ -27,7 +26,7 @@ storage array. The valid URI format is:
.fi
.RE 1
.RS 8
-Quick examples(please refer to "LibStorageMgmt User Guide" for detail):
+Examples, please refer to "LibStorageMgmt User Guide" for more details:
.RE 1
.RS 12
* Simulator:
@@ -44,15 +43,15 @@ Quick examples(please refer to "LibStorageMgmt User Guide" for detail):
\fBontap+ssl://***@host\fR
.RE 1
.RS 12
-* Storage Array support SMI-S(like, EMC CX/VNX, HDS AMS, IBM SVC/DS, LSI
-MegaRAID and etc):
+* SMI-S supported arrays (eg. EMC CX/VNX, HDS AMS, IBM SVC/DS, LSI
+MegaRAID and others):
.RS 4
\fBsmis://***@host:<port>?namespace=<namespace>\fR
.br
\fBsmis+ssl://***@host:<port>?namespace=<namespace>\fR
.RE 1
.RS 8
-You can pass URI to lsmcli via one of these ways:
+You can pass URI to lsmcli via one of these methods:
.RS 4
* Using '\fB-u\fR, \fB--uri\fR' argument.
.br
@@ -64,12 +63,12 @@ uri=\fI<URI>\fR
.RE 1
.TP 8
* Password
-All plugins require authentication(except simulator). You can pass it to
-lsmcli via one of these ways:
+For storage array password authentication you can pass it to
+lsmcli via one of the following methods:
.RS 12
-* Using '\fB-P\fR, \fB--prompt\fR' argument to prompt fro password.
+* '\fB-P\fR, \fB--prompt\fR' argument to prompt for password.
.br
-* Using '\fBLSMCLI_PASSWORD\fR' environment variable.
+* '\fBLSMCLI_PASSWORD\fR' environment variable.
.RE 1
.SH "GLOBAL OPTIONS"
.TP 15
@@ -77,8 +76,8 @@ lsmcli via one of these ways:
Show program's version number and exit
.TP 15
\fB-h\fR, \fB--help\fR
-Show this help message and exit. Will show help message of certain command if
-command defined.
+Show this help message and exit. Will show help message of specific command
+if specified.
.TP 15
\fB-u\fR \fI<URI>\fR, \fB--uri\fR \fI<URI>\fR
Uniform Resource Identifier (env LSMCLI_URI)
@@ -111,53 +110,51 @@ Run the command asynchronously instead of waiting for completion. The lsmcli
command will exit with exit code(7) and job id will be written to STDOUT when
a command is still executing on the storage array.
Use 'job-status --id \fI<job id>\fR' to inquire on the progress of the command.
-Some array or plugin might not support running asynchronous job, in that
-circumstance, \fb-b\fR will be effective, command will wait until finished.
+Some arrays or plugins might not support asynchronous operations, in those
+circumstances, \fb-b\fR will be ineffective. Command will wait until finished.
.TP 15
\fB-s\fR, \fB--script\fR
Displaying data in script friendly way.
.br
-Without this option, data is displayed in this manner:
+Without this option, data is displayed in this manner (default):
+
+ ID | Name | Element Type ...
+ ------------------------------------------ ...
+ aggr0 | aggr0 | FS,SYSTEM_RESERVED,POOL ...
+ iscsi | iscsi | FS,POOL ...

- ID | Name | Member IDs
- -----------------------------------------------------------
- 87720e90-3a83-11df-b8bf-00a0980ad71b | aggr0 | ID_A
- | | ID_B
- aa0ffc70-3dba-11df-b8cf-00a0980ad71b | aggr1 | ID_C
- | | ID_D

With this option, data is displayed in this manner.

- --------------------------------------------------
- ID | 87720e90-3a83-11df-b8bf-00a0980ad71b
- Name | aggr0
- Member IDs | ID_A
- | ID_B
- --------------------------------------------------
- ID | aa0ffc70-3dba-11df-b8cf-00a0980ad71b
- Name | aggr1
- Member IDs | ID_C
- | ID_D
- --------------------------------------------------
+ -----------------------------------------------
+ ID | aggr0
+ Name | aggr0
+ Element Type | FS,SYSTEM_RESERVED,POOL
+ ...
+ -----------------------------------------------
+ ID | iscsi
+ Name | iscsi
+ Element Type | FS,POOL
+ ...

Please note:
.br
-Due to console text width limitation(78), NOT all mandatory properties will be
-displayed in column way(default display way).
-But all mandatory properties will be displayed in script way.
+To reduce the width of output, NOT all properties will be displayed in default
+column display.

.SH COMMANDS
.SS list
List information on LSM objects
.TP 15
\fB--type\fR \fI<TYPE>\fR
-Required. Valid values are:
+Required. Valid values are (case insensitive):
.br
\fBVOLUMES\fR, \fBPOOLS\fR, \fBFS\fR, \fBSNAPSHOTS\fR,
-\fBEXPORTS\fR, \fBDISKS\fR,
+\fBEXPORTS\fR, \fBNFS_CLIENT_AUTH\fR,
.br
-\fBNFS_CLIENT_AUTH\fR, \fBACCESS_GROUPS\fR,
-\fBSYSTEMS\fR, \fBTARGET_PORTS\fR, \fBPLUGINS\fR.
+\fBACCESS_GROUPS\fR, \fBSYSTEMS\fR, \fBDISKS\fR, \fBPLUGINS\fR,
+\fBTARGET_PORTS\fR.
+
.TP
\fB--fs\fR \fI<FS_ID>\fR
Required for \fB--type\fR=\fBSNAPSHOTS\fR. List the snapshots of certain
@@ -204,27 +201,27 @@ Search resources from target port with target port ID. Only supported by these
types of resources: \fBTARGET_PORTS\fR.

.SS job-status
-Retrieve information about a job.
+Retrieve information about a job. Please see user guide on how to use.
.TP 15
\fB--job\fR \fI<JOB_ID>\fR

.SS capabilities
-Retrieves array capabilities
+Retrieves array capabilities.
.TP 15
\fB--sys\fR \fI<SYS_ID>\fR
-Required. ID of the system to query for capabilities
+Required. ID of the system to query for capabilities.

.SS plugin-info
Retrieves plugin description and version for current URI.

.SS volume-create
-Creates a volume (AKA, LUN or logical volume).
+Creates a volume (AKA., logical volume, virtual disk, LUN).
.TP 15
\fB--name\fR \fI<NAME>\fR
-Required. Volume name
+Required. Volume name.
.TP
\fB--size\fR \fI<SIZE>\fR
-Required. Volume size(See \fBSIZE OPTION\fR for allowed formats).
+Required. Volume size (See \fBSIZE OPTION\fR for allowed formats).
.TP
\fB--pool\fR \fI<POOL_ID>\fR
Required. ID of pool.
@@ -263,19 +260,18 @@ Required. The ID of volume to replicate.
\fB--name\fR \fI<NAME>\fR
Required. The name for new volume to hold replicated data.
.TP
-\fB--rep-type\fR \fI<REPL_TYPE>\fR
-Required. Valid types of replication are
+\fB--rep-type\fR \fI<REPL_TYPE>\fR (see \fBVOLUME REPLICATION TYPES)\fR
+Required. Valid types of replication are:
.br
-\fBSNAPSHOT\fR, \fBCLONE\fR, \fBCOPY\fR, \fBMIRROR_ASYNC\fR,
-\fBMIRROR_SYNC\fR. TODO: Explain every type here.
+\fBCLONE\fR, \fBCOPY\fR, \fBMIRROR_ASYNC\fR,
+\fBMIRROR_SYNC\fR.
.TP
\fB--pool\fR \fI<POOL_ID>\fR
-Optional. The ID of pool where the new volume should create in. If not define,
-replicate volume and source volume will be in the same pool.
+Optional. The ID of pool where the new volume should be created from. If not specified,
+plugin or array will choose appropriate pool.

.SS volume-replicate-range
-Replicates a portion of a volume, like only replicate the first 1024 block
-of certain volume to another volume.
+Replicates a portion of a volume to the same volume or to a different volume.
.TP 15
\fB--src-vol\fR \fI<SRC_VOL_ID>\fR
Required. The ID of replication source volume.
@@ -283,11 +279,10 @@ Required. The ID of replication source volume.
\fB--dst-vol\fR \fI<DST_VOL_ID>\fR
Required. The ID of replication destination volume.
.TP
-\fB--rep-type\fR \fI<REPL_TYPE>\fR
-Required. Valid types of replication are
+\fB--rep-type\fR \fI<REPL_TYPE>\fR (see \fBVOLUME REPLICATION TYPES)\fR
+Required. Appropriate types of replication are:
.br
-\fBSNAPSHOT\fR, \fBCLONE\fR, \fBCOPY\fR, \fBMIRROR_ASYNC\fR,
-\fBMIRROR_SYNC\fR. TODO: Explain every type here.
+\fBCLONE\fR, \fBCOPY\fR.
.TP
\fB--src-start\fR \fI<SRC_START_BLK>\fR
Required. Replication source volume start block number. Must in pair with
@@ -393,7 +388,7 @@ Lists the volumes that the access group has been granted access to.
Required. The ID of access group to query.

.SS iscsi-chap
-Configures ISCSI inbound/outbound CHAP authentication
+Configures ISCSI inbound/outbound CHAP authentication.
.TP 15
\fB--init\fR \fI<INIT_ID>\fR
Required. The ID of iSCSI initiator to configure.
@@ -402,16 +397,16 @@ Required. The ID of iSCSI initiator to configure.
Optional. Inbound CHAP user name.
.TP
\fB--in-pass\fR \fI<IN_PASS>\fR
-Optional. Inbound CHAP password
+Optional. Inbound CHAP password.
.TP
\fB--out-user\fR \fI<OUT_USER>\fR
Optional. Outbound CHAP user name.
.TP
\fB--out-pass\fR \fI<OUT_PASS>\fR
-Optional. Outbound CHAP password
+Optional. Outbound CHAP password.

.SS fs-create
-Creates a filesystem
+Creates a filesystem.
.TP 15
\fB--name\fR \fI<NAME>\fR
Required. Human friendly name for new filesystem.
@@ -423,13 +418,13 @@ Required. Volume size(See \fBSIZE OPTION\fR for allowed formats).
Required. ID of pool to hold the new filesystem.

.SS fs-delete
-Delete a filesystem
+Delete a filesystem.
.TP 15
\fB--fs\fR \fI<FS_ID>\fR
Required. ID of the filesystem to delete.

.SS fs-resize
-Resizes a filesystem
+Resizes a filesystem.
.TP 15
\fB--fs\fR \fI<FS_ID>\fR
Required. ID of the filesystem to resize.
@@ -470,14 +465,14 @@ Optional. The host/IP has read/write access. For two or more hosts/IPs:
'\fB--rw-host hostA --rw-host hostB\fR'.

.SS fs-unexport
-Delete an NFS export
+Remove an NFS export.
.TP 15
\fB--fs\fR \fI<FS_ID>\fR
Required. ID of the filesystem to unexport.

.SS fs-clone
Creates a file system clone. The 'clone' means point in time read writeable
-space efficient copy of data, aka read-writable snapshot.
+space efficient copy of data, AKA. read-writable snapshot.
.TP 15
\fB--src-fs\fR \fI<SRC_FS_ID>\fR
Required. The ID of the filesystem to clone.
@@ -486,25 +481,18 @@ Required. The ID of the filesystem to clone.
Required. The name for newly created destination file system.
.TP
\fB--backing-snapshot\fR \fI<BE_SS_ID>\fR
-Required. TODO: explain 'backing-snapshot' here.
+Optional. Make a FS clone using a previously created snapshot.

.SS fs-snap-create
-Creates a snapshot of certain filesystem. The snapshot means using
-copy-on-write technology to ensure the data will not be erased for future
-changes since snapshot creation time(PIT, point in time). The ordinal
-filesystem will still be read writable, the snapshot will be read only
-containing the data of PIT.
+Creates a snapshot of specified filesystem. A snapshot is defined as a read only
+space efficient point in time copy (PIT) of a filesystem. The source filesystem
+remains modifiable.
.TP 15
\fB--name\fR \fI<SNAP_NAME>\fR
Required. The human friendly name of new snapshot.
.TP
\fB--fs\fR \fI<FS_ID>\fR
Required. The ID of filesystem to create snapshot against.
-.TP
-\fB--file\fR \fI<FILE_PATH>\fR
-Optional. Repeatable. With this option defined, the snapshot will only
-containing the defined file/path. For two or more files/paths:
-'\fB--file fileA --file pathB\fR'.

.SS fs-snap-delete
Deletes a snapshot.
@@ -513,11 +501,11 @@ Deletes a snapshot.
Required. The ID of snapshot to delete.
.TP
\fB--fs\fR \fI<FS_ID>\fR
-Required. The ID of filesystem. TODO. No idea why we need fs_id.
+Required. The ID of filesystem.

.SS fs-snap-restore
Restores a FS or specified files to previous snapshot state. This will discard
-all the changes to filesystem since snapshot.
+all the changes to filesystem since snapshot if specific files are not specified in restore.
.TP 15
\fB--fs\fR \fI<FS_ID>\fR
Required. The ID of filesystem to restore.
@@ -527,23 +515,21 @@ Required. The ID of snapshot to restore.
.TP
\fB--file\fR \fI<FILE_PATH>\fR
Optional. Repeatable. With this option defined, will only restore the defined
-files. For two or more files/paths:
+file(s).
'\fB--file fileA --file pathB\fR'.
.TP
\fB--fileas\fR \fI<NEW_FILE_PATH>\fR
Optional. Repeatable. With this option defined, the restored file will be
-saved to defined path or filename. For two or more files/paths:
-'\fB--file fileA --file fileB --fileas old_fileA --fileas old_fileB\fR'.
+saved to specified path and filename, eg. '\fB--file fileA --fileas old_fileA \fR'.

.SS fs-dependants
-Returns True if a child dependency(snapshot or clone) exists.
+Returns True if a child dependency (snapshot or clone) exists.
.TP 15
\fB--fs\fR \fI<FS_ID>\fR
Required. The ID of filesystem to query.
.TP
\fB--file\fR \fI<FILE_PATH>\fR
-Optional. Repeatable. Only check defined files for snapshot or clone.
-For two or more files/paths: '\fB--file fileA --file pathB\fR'.
+Optional. Repeatable. Only check for dependencies on specific file(s), eg. '\fB--file fileA --file pathB\fR'.

.SS fs-dependants-rm
Removes filesystem dependencies(snapshot or clone).
@@ -552,20 +538,17 @@ Removes filesystem dependencies(snapshot or clone).
Required. The ID of filesystem to remove dependency.
.TP
\fB--file\fR \fI<FILE_PATH>\fR
-Optional. Repeatable. Only remove defined files for snapshot or clone.
-For two or more files/paths: '\fB--file fileA --file pathB\fR'.
+Optional. Repeatable. Only remove dependencies on specific file(s), eg. '\fB--file fileA --file pathB\fR'.

.SS file-clone
-Creates a clone of a file (thin provisioned).
+Creates a clone of a file (thin provisioned). Note: --src and --dst need to be paired
+ eg. '\fB--src fileA --src fileB --dst fileA_clone --dst fileB_clone\fR'.
.TP 15
\fB--src\fR \fI<SRC_FILE_PATH>\fR
Required. Repeatable. Source file to clone (relative path).
-For two or more files/paths: '\fB--src fileA --src fileB\fR'.
.TP
\fB--dst\fR \fI<DST_FILE_PATH>\fR
-Required. Repeatable. Destination file to clone (relative path).
-For two or more files/paths:
-'\fB--src fileA --src fileB --dst old_fileA --dst old_fileB\fR'.
+Required. Repeatable. Destination file for clone (relative path).

.IP
.SH ALIAS
@@ -679,10 +662,26 @@ The URI for the storage array in question.
LSMCLI_PASSWORD
The password to use for the array.

+.SH VOLUME REPLICATION TYPES
+.TP 17
+CLONE
+A point in time, read writeable, space efficent copy of data.
+.TP 17
+COPY
+A full bitwise copy of the data. It occupies the full space.
+.TP 17
+MIRROR_SYNC
+Continously updated, realtime with both copies having identical data.
+.TP 17
+MIRROR_ASYNC
+Continously updated, with a varying amount of delay and data delta
+between the source and target.
+
+
.SH NOTES
.TP 8
Plugin installation
-Plugins are installed individually except for the simulator which is always
+Plugins are installed individually except for the simulators which are always
included.

.TP 8
diff --git a/tools/lsmcli/cmdline.py b/tools/lsmcli/cmdline.py
index a34fa30..0a4e656 100644
--- a/tools/lsmcli/cmdline.py
+++ b/tools/lsmcli/cmdline.py
@@ -461,9 +461,9 @@ cmds = (
optional=[
dict(name="--exportpath", metavar='<EXPORT_PATH>',
help="NFS server export path. e.g. '/foo/bar'."),
- dict(name="--anonuid", metavar='<ANONY_UID>',
+ dict(name="--anonuid", metavar='<ANON_UID>',
help='UID(User ID) to map to anonymous user'),
- dict(name="--anongid", metavar='<ANONY_GID>',
+ dict(name="--anongid", metavar='<ANON_GID>',
help='GID(Group ID) to map to anonymous user'),
dict(name="--auth-type", metavar='<AUTH_TYPE>',
help='NFS client authentication type'),
@@ -485,7 +485,7 @@ cmds = (

dict(
name='fs-unexport',
- help='Delete an NFS export',
+ help='Remove an NFS export',
args=[
dict(export_id_opt),
],
@@ -584,8 +584,8 @@ cmds = (
help='source file to clone (relative path)\n'
"This is a repeatable argument.",),
dict(name="--dst", metavar="<DST_FILE_PATH>",
- help='destination file (relative path)'
- "This is a repeatable argument."),
+ help='Destination file (relative path)'
+ ", this is a repeatable argument."),
],
optional=[
dict(name="--backing-snapshot", help='backing snapshot id'),
--
1.8.2.1
Tony Asleson
2014-09-07 05:45:41 UTC
Permalink
Signed-off-by: Tony Asleson <***@redhat.com>
---
plugin/smispy/smis.py | 68 ++++++++++++++++++++++++++++++---------------------
1 file changed, 40 insertions(+), 28 deletions(-)

diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index ead15c8..5a51e93 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -1701,6 +1701,38 @@ class Smis(IStorageAreaNetwork):

return [Smis._cim_sys_to_lsm(s) for s in cim_syss]

+ def _check_for_dupe_vol(self, volume_name, original_exception):
+ """
+ Throw original exception or NAME_CONFLICT if volume name found
+ :param volume_name: Volume to check for
+ :original_exception Info grabbed from sys.exec_info
+ :return:
+ """
+ report_original = True
+
+ # Check to see if we already have a volume with this name. If we
+ # do we will assume that this is the cause of it. We will hide
+ # any errors that happen during this check and just report the
+ # original error if we can't determine if we have a duplicate
+ # name.
+
+ try:
+ # TODO: Add ability to search by volume name to 'volumes'
+ volumes = self.volumes()
+ for v in volumes:
+ if v.name == volume_name:
+ report_original = False
+ except Exception:
+ # Don't report anything here on a failing
+ pass
+
+ if report_original:
+ raise original_exception[1], None, original_exception[2]
+ else:
+ raise LsmError(ErrorNumber.NAME_CONFLICT,
+ "Volume with name '%s' already exists!" %
+ volume_name)
+
@handle_cim_errors
def volume_create(self, pool, volume_name, size_bytes, provisioning,
flags=0):
@@ -1727,31 +1759,7 @@ class Smis(IStorageAreaNetwork):
'CreateOrModifyElementFromStoragePool',
scs.path, **in_params)))
except CIMError:
- report_original = True
- # Save off exception so we can re-raise original if needed
- exception_info = sys.exc_info()
-
- # Check to see if we already have a volume with this name. If we
- # do we will assume that this is the cause of it. We will hide
- # any errors that happen during this check and just report the
- # original error if we can't determine if we have a duplicate
- # name.
- try:
- # TODO: Add ability to search by volume name to 'volumes'
- volumes = self.volumes()
- for v in volumes:
- if v.name == volume_name:
- report_original = False
- break
- except Exception:
- # Don't report anything here on a failing
- pass
-
- if report_original:
- raise exception_info[1], None, exception_info[2]
- else:
- raise LsmError(ErrorNumber.NAME_CONFLICT,
- "Volume with name exists!")
+ self._check_for_dupe_vol(volume_name, sys.exc_info())

def _poll(self, msg, job):
if job:
@@ -1989,9 +1997,13 @@ class Smis(IStorageAreaNetwork):
if cim_pool is not None:
in_params['TargetPool'] = cim_pool.path

- return self._pi("volume_replicate", Smis.JOB_RETRIEVE_VOLUME,
- *(self._c.InvokeMethod(method,
- rs.path, **in_params)))
+ try:
+
+ return self._pi("volume_replicate", Smis.JOB_RETRIEVE_VOLUME,
+ *(self._c.InvokeMethod(method,
+ rs.path, **in_params)))
+ except CIMError:
+ self._check_for_dupe_vol(name, sys.exc_info())

raise LsmError(ErrorNumber.NO_SUPPORT,
"volume-replicate not supported")
--
1.8.2.1
Tony Asleson
2014-09-07 05:45:40 UTC
Permalink
* Nstor want's things aligned to 8K boundaries.
* Check for disk capability before trying to list disks

Signed-off-by: Tony Asleson <***@redhat.com>
---
test/plugin_test.py | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/test/plugin_test.py b/test/plugin_test.py
index 79c41cd..8fd1437 100755
--- a/test/plugin_test.py
+++ b/test/plugin_test.py
@@ -337,8 +337,12 @@ class TestPlugin(unittest.TestCase):
self._volume_delete(vol)

def test_disks_list(self):
- disks = self.c.disks()
- self.assertTrue(len(disks) > 0, "We need at least 1 disk to test")
+ for s in self.systems:
+ cap = self.c.capabilities(s)
+ if supported(cap, [lsm.Capabilities.DISKS]):
+ disks = self.c.disks()
+ self.assertTrue(len(disks) > 0,
+ "We need at least 1 disk to test")

def _volume_create(self, system_id,
element_type=lsm.Pool.ELEMENT_TYPE_VOLUME):
@@ -441,7 +445,7 @@ class TestPlugin(unittest.TestCase):
lsm.Capabilities.VOLUME_RESIZE]):
vol = self._volume_create(s.id)[0]
vol_resize = self.c.volume_resize(
- vol, int(vol.size_bytes * 1.10))[1]
+ vol, vol.size_bytes + mb_in_bytes(16))[1]
self.assertTrue(vol.size_bytes < vol_resize.size_bytes)
self.assertTrue(vol.id == vol_resize.id,
"Expecting re-sized volume to refer to "
@@ -573,7 +577,7 @@ class TestPlugin(unittest.TestCase):

if fs is not None:
if supported(cap, [lsm.Capabilities.FS_RESIZE]):
- fs_size = fs.total_space * 1.10
+ fs_size = fs.total_space + mb_in_bytes(16)
fs_resized = self.c.fs_resize(fs, fs_size)[1]
self.assertTrue(fs_resized.total_space)
--
1.8.2.1
Tony Asleson
2014-09-07 05:45:45 UTC
Permalink
Signed-off-by: Tony Asleson <***@redhat.com>
---
plugin/smispy/smis.py | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index 5a294b7..870c6c1 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -681,10 +681,14 @@ class Smis(IStorageAreaNetwork):

element_types = cim_scs_cap['SupportedStorageElementTypes']
sup_actions = []
- if cim_scs_cap['SupportedSynchronousActions']:
- sup_actions.extend(cim_scs_cap['SupportedSynchronousActions'])
- if cim_scs_cap['SupportedAsynchronousActions']:
- sup_actions.extend(cim_scs_cap['SupportedAsynchronousActions'])
+
+ if 'SupportedSynchronousActions' in cim_scs_cap:
+ if cim_scs_cap['SupportedSynchronousActions']:
+ sup_actions.extend(cim_scs_cap['SupportedSynchronousActions'])
+
+ if 'SupportedAsynchronousActions' in cim_scs_cap:
+ if cim_scs_cap['SupportedAsynchronousActions']:
+ sup_actions.extend(cim_scs_cap['SupportedAsynchronousActions'])

if DMTF.SCS_CAP_SUP_ST_VOLUME in element_types or \
DMTF.SCS_CAP_SUP_THIN_ST_VOLUME in element_types:
--
1.8.2.1
Tony Asleson
2014-09-07 05:45:37 UTC
Permalink
Signed-off-by: Tony Asleson <***@redhat.com>
---
c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h | 2 --
c_binding/include/libstoragemgmt/libstoragemgmt_types.h | 2 +-
2 files changed, 1 insertion(+), 3 deletions(-)

diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h b/c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h
index 635fdef..5ebb93f 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h
@@ -864,8 +864,6 @@ int LSM_DLL_EXPORT lsm_plugin_error_log( lsm_plugin_ptr plug, lsm_error_ptr erro
/**
* Creates an error record.
* @param code
- * @param domain
- * @param level
* @param msg
* @param exception
* @param debug
diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt_types.h b/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
index 238ef06..746f397 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
@@ -123,7 +123,7 @@ typedef enum {
LSM_VOLUME_REPLICATE_MIRROR_ASYNC = 5 /**< Mirror partner updated with delay */
} lsm_replication_type;

-/**< \enum lsm_provision_type Different types of provisioning */
+/**< \enum lsm_volume_provision_type Different types of provisioning */
typedef enum {
LSM_VOLUME_PROVISION_UNKNOWN = -1, /**< Unknown */
LSM_VOLUME_PROVISION_THIN = 1, /**< Thin provisioning */
--
1.8.2.1
Tony Asleson
2014-09-07 05:45:44 UTC
Permalink
Signed-off-by: Tony Asleson <***@redhat.com>
---
plugin/ontap/ontap.py | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/plugin/ontap/ontap.py b/plugin/ontap/ontap.py
index e03f423..77a05fa 100644
--- a/plugin/ontap/ontap.py
+++ b/plugin/ontap/ontap.py
@@ -172,7 +172,6 @@ class Ontap(IStorageAreaNetwork, INfs):
if l['online'] == 'false':
admin_state = Volume.ADMIN_STATE_DISABLED

- #TODO: Need to retrieve actual volume status
return Volume(vol_id, vol_name,
Ontap._create_vpd(l['serial-number']), block_size,
num_blocks, admin_state, self.sys_info.id, pool_id)
@@ -707,7 +706,8 @@ class Ontap(IStorageAreaNetwork, INfs):

cur_init_ids = Ontap._initiators_in_group(igroups[0])
if len(cur_init_ids) == 0:
- raise LsmError(ErrorNumber.EMPTY_ACCESS_GROUP,
+ raise LsmError(
+ ErrorNumber.EMPTY_ACCESS_GROUP,
"Refuse to do volume masking against empty access group")
try:
self.f.lun_map(access_group.name, _lsm_vol_to_na_vol_path(volume))
@@ -834,7 +834,8 @@ class Ontap(IStorageAreaNetwork, INfs):
(init_id, access_group.name))

if len(cur_init_ids) == 1:
- raise LsmError(ErrorNumber.LAST_INIT_IN_ACCESS_GROUP,
+ raise LsmError(
+ ErrorNumber.LAST_INIT_IN_ACCESS_GROUP,
"Refuse to remove last initiator from access group")

self.f.igroup_del_initiator(access_group.name, init_id)
--
1.8.2.1
Tony Asleson
2014-09-07 05:45:46 UTC
Permalink
This was showing up as a public symbol in the SO which is not
wanted.

Signed-off-by: Tony Asleson <***@redhat.com>
---
c_binding/lsm_plugin_ipc.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/c_binding/lsm_plugin_ipc.cpp b/c_binding/lsm_plugin_ipc.cpp
index 0d3496f..2539d4a 100644
--- a/c_binding/lsm_plugin_ipc.cpp
+++ b/c_binding/lsm_plugin_ipc.cpp
@@ -2367,7 +2367,8 @@ static void name(void *i) \
method((method_type *)i); \
} \

-int filter(void *a[], size_t size, array_cmp cmp, void *cmp_data, free_item fo)
+static int filter(void *a[], size_t size, array_cmp cmp, void *cmp_data,
+ free_item fo)
{
int remaining = 0;
size_t i = 0;
--
1.8.2.1
Tony Asleson
2014-09-07 05:45:48 UTC
Permalink
Signed-off-by: Tony Asleson <***@redhat.com>
---
c_binding/lsm_convert.hpp | 64 +++++++++++++++++++++++---------------------
c_binding/lsm_datatypes.hpp | 10 +++----
c_binding/lsm_plugin_ipc.hpp | 3 ++-
3 files changed, 41 insertions(+), 36 deletions(-)

diff --git a/c_binding/lsm_convert.hpp b/c_binding/lsm_convert.hpp
index 0c495ae..fe1e91d 100644
--- a/c_binding/lsm_convert.hpp
+++ b/c_binding/lsm_convert.hpp
@@ -63,28 +63,28 @@ bool LSM_DLL_LOCAL is_expected_object(Value &obj, std::string class_name);
* @param list List represented as an vector of strings.
* @return lsm_string_list pointer, NULL on error.
*/
-lsm_string_list *value_to_string_list( Value &list);
+lsm_string_list LSM_DLL_LOCAL *value_to_string_list( Value &list);

/**
* Converts a lsm_string_list to a Value
* @param sl String list to convert
* @return Value
*/
-Value string_list_to_value( lsm_string_list *sl);
+Value LSM_DLL_LOCAL string_list_to_value( lsm_string_list *sl);

/**
* Converts a volume to a volume.
* @param vol Value to convert.
* @return lsm_volume *, else NULL on error
*/
-lsm_volume * value_to_volume(Value &vol);
+lsm_volume LSM_DLL_LOCAL *value_to_volume(Value &vol);

/**
* Converts a lsm_volume * to a Value
* @param vol lsm_volume to convert
* @return Value
*/
-Value volume_to_value(lsm_volume *vol);
+Value LSM_DLL_LOCAL volume_to_value(lsm_volume *vol);


/**
@@ -94,7 +94,7 @@ Value volume_to_value(lsm_volume *vol);
* @param count Number of volumes
* @return LSM_ERR_OK on success, else error reason
*/
-int value_array_to_volumes(Value &volume_values, lsm_volume **volumes[],
+int LSM_DLL_LOCAL value_array_to_volumes(Value &volume_values, lsm_volume **volumes[],
uint32_t *count);

/**
@@ -102,14 +102,14 @@ int value_array_to_volumes(Value &volume_values, lsm_volume **volumes[],
* @param disk Value representing a disk
* @return lsm_disk pointer, else NULL on error
*/
-lsm_disk *value_to_disk(Value &disk);
+lsm_disk LSM_DLL_LOCAL *value_to_disk(Value &disk);

/**
* Converts a lsm_disk to a value
* @param disk lsm_disk to convert to value
* @return Value
*/
-Value disk_to_value(lsm_disk *disk);
+Value LSM_DLL_LOCAL disk_to_value(lsm_disk *disk);

/**
* Converts a vector of disk values to an array.
@@ -118,7 +118,7 @@ Value disk_to_value(lsm_disk *disk);
* @param[out] count Number of disks
* @return LSM_ERR_OK on success, else error reason.
*/
-int value_array_to_disks(Value &disk_values, lsm_disk **disks[],
+int LSM_DLL_LOCAL value_array_to_disks(Value &disk_values, lsm_disk **disks[],
uint32_t *count);

/**
@@ -126,42 +126,42 @@ int value_array_to_disks(Value &disk_values, lsm_disk **disks[],
* @param pool To convert to lsm_pool *
* @return lsm_pool *, else NULL on error.
*/
-lsm_pool *value_to_pool(Value &pool);
+lsm_pool LSM_DLL_LOCAL *value_to_pool(Value &pool);

/**
* Converts a lsm_pool * to Value
* @param pool Pool pointer to convert
* @return Value
*/
-Value pool_to_value(lsm_pool *pool);
+Value LSM_DLL_LOCAL pool_to_value(lsm_pool *pool);

/**
* Converts a value to a system
* @param system to convert to lsm_system *
* @return lsm_system pointer, else NULL on error
*/
-lsm_system *value_to_system(Value &system);
+lsm_system LSM_DLL_LOCAL *value_to_system(Value &system);

/**
* Converts a lsm_system * to a Value
* @param system pointer to convert to Value
* @return Value
*/
-Value system_to_value(lsm_system *system);
+Value LSM_DLL_LOCAL system_to_value(lsm_system *system);

/**
* Converts a Value to a lsm_access_group
* @param group to convert to lsm_access_group*
* @return lsm_access_group *, NULL on error
*/
-lsm_access_group *value_to_access_group(Value &group);
+lsm_access_group LSM_DLL_LOCAL *value_to_access_group(Value &group);

/**
* Converts a lsm_access_group to a Value
* @param group Group to convert
* @return Value, null value type on error.
*/
-Value access_group_to_value(lsm_access_group *group);
+Value LSM_DLL_LOCAL access_group_to_value(lsm_access_group *group);

/**
* Converts an access group list to an array of access group pointers
@@ -170,7 +170,8 @@ Value access_group_to_value(lsm_access_group *group);
* @return NULL on memory allocation failure, else pointer to access group
* array.
*/
-lsm_access_group **value_to_access_group_list( Value &group, uint32_t *count );
+lsm_access_group LSM_DLL_LOCAL **value_to_access_group_list( Value &group,
+ uint32_t *count );

/**
* Converts an array of lsm_access_group to Value(s)
@@ -178,21 +179,22 @@ lsm_access_group **value_to_access_group_list( Value &group, uint32_t *count );
* @param count Number of items in array.
* @return std::vector of Values representing access groups
*/
-Value access_group_list_to_value( lsm_access_group **group, uint32_t count);
+Value LSM_DLL_LOCAL access_group_list_to_value( lsm_access_group **group,
+ uint32_t count);

/**
* Converts a Value to a lsm_block_range
* @param br Value representing a block range
* @return lsm_block_range *
*/
-lsm_block_range *value_to_block_range(Value &br);
+lsm_block_range LSM_DLL_LOCAL *value_to_block_range(Value &br);

/**
* Converts a lsm_block_range to a Value
* @param br lsm_block_range to convert
* @return Value, null value type on error
*/
-Value block_range_to_value(lsm_block_range *br);
+Value LSM_DLL_LOCAL block_range_to_value(lsm_block_range *br);

/**
* Converts a Value to an array of lsm_block_range
@@ -200,7 +202,8 @@ Value block_range_to_value(lsm_block_range *br);
* @param[out] count Number of items in the resulting array
* @return NULL on memory allocation failure, else array of lsm_block_range
*/
-lsm_block_range **value_to_block_range_list(Value &brl, uint32_t *count);
+lsm_block_range LSM_DLL_LOCAL **value_to_block_range_list(Value &brl,
+ uint32_t *count);

/**
* Converts an array of lsm_block_range to Value
@@ -208,76 +211,77 @@ lsm_block_range **value_to_block_range_list(Value &brl, uint32_t *count);
* @param count Number of items in input
* @return Value
*/
-Value block_range_list_to_value( lsm_block_range **brl, uint32_t count);
+Value LSM_DLL_LOCAL block_range_list_to_value( lsm_block_range **brl,
+ uint32_t count);

/**
* Converts a value to a lsm_fs *
* @param fs Value representing a FS to be converted
* @return lsm_fs pointer or NULL on error.
*/
-lsm_fs *value_to_fs(Value &fs);
+lsm_fs LSM_DLL_LOCAL *value_to_fs(Value &fs);

/**
* Converts a lsm_fs pointer to a Value
* @param fs File system pointer to convert
* @return Value
*/
-Value fs_to_value(lsm_fs *fs);
+Value LSM_DLL_LOCAL fs_to_value(lsm_fs *fs);

/**
* Converts a value to a lsm_ss *
* @param ss Value representing a snapshot to be converted
* @return lsm_ss pointer or NULL on error.
*/
-lsm_fs_ss *value_to_ss(Value &ss);
+lsm_fs_ss LSM_DLL_LOCAL *value_to_ss(Value &ss);

/**
* Converts a lsm_ss pointer to a Value
* @param ss Snapshot pointer to convert
* @return Value
*/
-Value ss_to_value(lsm_fs_ss *ss);
+Value LSM_DLL_LOCAL ss_to_value(lsm_fs_ss *ss);

/**
* Converts a value to a lsm_nfs_export *
* @param exp Value representing a nfs export to be converted
* @return lsm_nfs_export pointer or NULL on error.
*/
-lsm_nfs_export *value_to_nfs_export(Value &exp);
+lsm_nfs_export LSM_DLL_LOCAL *value_to_nfs_export(Value &exp);

/**
* Converts a lsm_nfs_export pointer to a Value
* @param exp NFS export pointer to convert
* @return Value
*/
-Value nfs_export_to_value(lsm_nfs_export *exp);
+Value LSM_DLL_LOCAL nfs_export_to_value(lsm_nfs_export *exp);

/**
* Converts a Value to a lsm_storage_capabilities
* @param exp Value representing a storage capabilities
* @return lsm_storage_capabilities pointer or NULL on error
*/
-lsm_storage_capabilities *value_to_capabilities(Value &exp);
+lsm_storage_capabilities LSM_DLL_LOCAL *value_to_capabilities(Value &exp);

/**
* Converts a lsm_storage_capabilities to a value
* @param cap lsm_storage_capabilities to convert to value
* @return Value
*/
-Value capabilities_to_value(lsm_storage_capabilities *cap);
+Value LSM_DLL_LOCAL capabilities_to_value(lsm_storage_capabilities *cap);

/**
* Convert a Value representation to lsm_target_port
* @param tp Value to convert to lsm_target_port
* @return lsm_target_port pointer or NULL on errors
*/
-lsm_target_port *value_to_target_port(Value &tp);
+lsm_target_port LSM_DLL_LOCAL *value_to_target_port(Value &tp);

/**
* Converts a lsm_target_port to a value
* @param tp lsm_target_port to convert to value
* @return Value
*/
-Value target_port_to_value(lsm_target_port *tp);
+Value LSM_DLL_LOCAL target_port_to_value(lsm_target_port *tp);

#endif
diff --git a/c_binding/lsm_datatypes.hpp b/c_binding/lsm_datatypes.hpp
index dbeaca1..aed6891 100644
--- a/c_binding/lsm_datatypes.hpp
+++ b/c_binding/lsm_datatypes.hpp
@@ -303,13 +303,13 @@ struct LSM_DLL_LOCAL _lsm_target_port {
* Returns a pointer to a newly created connection structure.
* @return NULL on memory exhaustion, else new connection.
*/
-LSM_DLL_LOCAL lsm_connect *connection_get();
+lsm_connect LSM_DLL_LOCAL *connection_get();

/**
* De-allocates the connection.
* @param c Connection to free.
*/
-LSM_DLL_LOCAL void connection_free(lsm_connect *c);
+void LSM_DLL_LOCAL connection_free(lsm_connect *c);

/**
* Loads the requester driver specified in the uri.
@@ -322,15 +322,15 @@ LSM_DLL_LOCAL void connection_free(lsm_connect *c);
* @param flags Reserved flag for future use
* @return LSM_ERR_OK on success, else error code.
*/
-LSM_DLL_LOCAL int driver_load(lsm_connect *c, const char *plugin,
+int LSM_DLL_LOCAL driver_load(lsm_connect *c, const char *plugin,
const char *password, uint32_t timeout,
lsm_error_ptr *e,
int startup,
lsm_flag flags);

-LSM_DLL_LOCAL char* capability_string(lsm_storage_capabilities *c);
+char LSM_DLL_LOCAL *capability_string(lsm_storage_capabilities *c);

-LSM_DLL_LOCAL const char *uds_path(void);
+const char LSM_DLL_LOCAL *uds_path(void);

/**
* Take a character string and tries to convert to a number.
diff --git a/c_binding/lsm_plugin_ipc.hpp b/c_binding/lsm_plugin_ipc.hpp
index 4065ed6..36f3220 100644
--- a/c_binding/lsm_plugin_ipc.hpp
+++ b/c_binding/lsm_plugin_ipc.hpp
@@ -21,9 +21,10 @@
#define LSM_PLUGIN_IPC_HPP

#include <map>
+#include "libstoragemgmt/libstoragemgmt_common.h"

template <typename K, typename V>
-class static_map
+class LSM_DLL_LOCAL static_map
{
private:
std::map<K, V> _m;
--
1.8.2.1
Tony Asleson
2014-09-07 05:45:42 UTC
Permalink
Signed-off-by: Tony Asleson <***@redhat.com>
---
test/plugin_test.py | 24 ++++++++++++++----------
1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/test/plugin_test.py b/test/plugin_test.py
index 8fd1437..84a426a 100755
--- a/test/plugin_test.py
+++ b/test/plugin_test.py
@@ -661,7 +661,7 @@ class TestPlugin(unittest.TestCase):

def test_mask_unmask(self):
for s in self.systems:
- ag = None
+ ag_created = None
cap = self.c.capabilities(s)

if supported(cap, [lsm.Capabilities.ACCESS_GROUPS,
@@ -674,7 +674,7 @@ class TestPlugin(unittest.TestCase):
ag_name = rs("ag")
ag_iqn = 'iqn.1994-05.com.domain:01.' + rs(None, 6)

- ag = self.c.access_group_create(
+ ag_created = self.c.access_group_create(
ag_name, ag_iqn, lsm.AccessGroup.INIT_TYPE_ISCSI_IQN,
s)

@@ -684,11 +684,15 @@ class TestPlugin(unittest.TestCase):
if len(ag_list):
vol = self._volume_create(s.id)[0]
self.assertTrue(vol is not None)
- chose_ag = None
- for ag in ag_list:
- if len(ag.init_ids) >= 1:
- chose_ag = ag
- break
+
+ chose_ag = ag_created
+
+ if chose_ag is None:
+ for ag in ag_list:
+ if len(ag.init_ids) >= 1:
+ chose_ag = ag
+ break
+
if chose_ag is None:
raise Exception("No access group with 1+ member "
"found, cannot do volume mask test")
@@ -702,9 +706,9 @@ class TestPlugin(unittest.TestCase):
if vol:
self._volume_delete(vol)

- if ag:
- self.c.access_group_delete(ag)
- ag = None
+ if ag_created:
+ self.c.access_group_delete(ag_created)
+ ag_created = None

def _create_access_group(self, cap, name, s, init_type):
ag_created = None
--
1.8.2.1
Tony Asleson
2014-09-07 05:45:47 UTC
Permalink
Signed-off-by: Tony Asleson <***@redhat.com>
---
c_binding/include/libstoragemgmt/libstoragemgmt_blockrange.h | 6 +++---
c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h | 4 ++--
c_binding/include/libstoragemgmt/libstoragemgmt_systems.h | 2 +-
3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt_blockrange.h b/c_binding/include/libstoragemgmt/libstoragemgmt_blockrange.h
index a91db79..a45a05e 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt_blockrange.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt_blockrange.h
@@ -75,21 +75,21 @@ int LSM_DLL_EXPORT lsm_block_range_record_array_free( lsm_block_range *br[],
* @param br Valid block range pointer
* @return value of source start.
*/
-uint64_t lsm_block_range_source_start_get(lsm_block_range *br);
+uint64_t LSM_DLL_EXPORT lsm_block_range_source_start_get(lsm_block_range *br);

/**
* Retrieves the dest block address.
* @param br Valid block range pointer
* @return value of dest start.
*/
-uint64_t lsm_block_range_dest_start_get(lsm_block_range *br);
+uint64_t LSM_DLL_EXPORT lsm_block_range_dest_start_get(lsm_block_range *br);

/**
* Retrieves the number of blocks to replicate.
* @param br Valid block range pointer
* @return value of number of blocks
*/
-uint64_t lsm_block_range_block_count_get(lsm_block_range *br);
+uint64_t LSM_DLL_EXPORT lsm_block_range_block_count_get(lsm_block_range *br);

#ifdef __cplusplus
}
diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h b/c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h
index 5ebb93f..dc42f23 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h
@@ -931,7 +931,7 @@ lsm_pool LSM_DLL_EXPORT *lsm_pool_record_alloc(const char *id, const char *name,
* @param p Pool to retrieve plugin private data for
* @return NULL if donesn't exists, else data.
*/
-const char *lsm_pool_plugin_data_get(lsm_pool *p);
+const char LSM_DLL_EXPORT *lsm_pool_plugin_data_get(lsm_pool *p);

/**
* Allocate the storage needed for and array of Volume records.
@@ -1086,7 +1086,7 @@ lsm_fs LSM_DLL_EXPORT **lsm_fs_record_array_alloc( uint32_t size );
* @param fs FS to retrieve plug-in private data for
* @return NULL if doesn't exist, else data.
*/
-const char *lsm_fs_plugin_data_get(lsm_fs *fs);
+const char LSM_DLL_EXPORT *lsm_fs_plugin_data_get(lsm_fs *fs);

/**
* Allocates the memory for single snap shot record.
diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt_systems.h b/c_binding/include/libstoragemgmt/libstoragemgmt_systems.h
index c2bca11..9c59062 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt_systems.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt_systems.h
@@ -31,7 +31,7 @@ extern "C" {
* @param s Record to duplicate
* @return NULL on memory allocation failure, else duplicated record.
*/
-lsm_system *lsm_system_record_copy(lsm_system *s);
+lsm_system LSM_DLL_EXPORT *lsm_system_record_copy(lsm_system *s);


/**
--
1.8.2.1
Tony Asleson
2014-09-07 05:45:38 UTC
Permalink
If we can create one then do so instead of mucking with existing
access groups.

Signed-off-by: Tony Asleson <***@redhat.com>
---
test/plugin_test.py | 52 +++++++++++++++++++++++++++-------------------------
1 file changed, 27 insertions(+), 25 deletions(-)

diff --git a/test/plugin_test.py b/test/plugin_test.py
index f84e2dd..79c41cd 100755
--- a/test/plugin_test.py
+++ b/test/plugin_test.py
@@ -809,7 +809,9 @@ class TestPlugin(unittest.TestCase):
if supported(cap, [lsm.Capabilities.ACCESS_GROUPS]):
ag_list = self.c.access_groups('system_id', s.id)

- if len(ag_list) == 0:
+ if supported(cap, [lsm.Capabilities.ACCESS_GROUP_CREATE_WWPN])\
+ or supported(cap, [lsm.Capabilities.ACCESS_GROUP_CREATE_ISCSI_IQN]):
+
if supported(
cap, [lsm.Capabilities.ACCESS_GROUP_CREATE_ISCSI_IQN,
lsm.Capabilities.ACCESS_GROUP_DELETE]):
@@ -824,34 +826,34 @@ class TestPlugin(unittest.TestCase):
cap, rs('ag'), s, lsm.AccessGroup.INIT_TYPE_WWPN)
ag_list = self.c.access_groups('system_id', s.id)

- if len(ag_list):
- # Try and find an initiator group that has a usable access
- # group type instead of unknown or other...
- ag = ag_list[0]
- for a_tmp in ag_list:
- if a_tmp.init_type in usable_ag_types:
- ag = a_tmp
- break
+ if ag_to_delete is not None:
+ self._delete_access_group(ag_to_delete)
+ else:
+ if len(ag_list):
+ # Try and find an initiator group that has a usable access
+ # group type instead of unknown or other...
+ ag = ag_list[0]
+ for a_tmp in ag_list:
+ if a_tmp.init_type in usable_ag_types:
+ ag = a_tmp
+ break

- if supported(cap, [lsm.Capabilities.
- ACCESS_GROUP_INITIATOR_ADD_WWPN]):
- init_id = self._ag_init_add(ag)
if supported(cap, [lsm.Capabilities.
- ACCESS_GROUP_INITIATOR_DELETE]):
- self._ag_init_delete(
- ag, init_id, lsm.AccessGroup.INIT_TYPE_WWPN)
+ ACCESS_GROUP_INITIATOR_ADD_WWPN]):
+ init_id = self._ag_init_add(ag)
+ if supported(cap, [lsm.Capabilities.
+ ACCESS_GROUP_INITIATOR_DELETE]):
+ self._ag_init_delete(
+ ag, init_id, lsm.AccessGroup.INIT_TYPE_WWPN)

- if supported(cap, [lsm.Capabilities.
- ACCESS_GROUP_INITIATOR_ADD_ISCSI_IQN]):
- init_id = self._ag_init_add(ag)
if supported(cap, [lsm.Capabilities.
- ACCESS_GROUP_INITIATOR_DELETE]):
- self._ag_init_delete(
- ag, init_id,
- lsm.AccessGroup.INIT_TYPE_ISCSI_IQN)
-
- if ag_to_delete is not None:
- self._delete_access_group(ag_to_delete)
+ ACCESS_GROUP_INITIATOR_ADD_ISCSI_IQN]):
+ init_id = self._ag_init_add(ag)
+ if supported(cap, [lsm.Capabilities.
+ ACCESS_GROUP_INITIATOR_DELETE]):
+ self._ag_init_delete(
+ ag, init_id,
+ lsm.AccessGroup.INIT_TYPE_ISCSI_IQN)

def test_duplicate_volume_name(self):
if self.pool_by_sys_id:
--
1.8.2.1
Tony Asleson
2014-09-07 05:45:43 UTC
Permalink
Signed-off-by: Tony Asleson <***@redhat.com>
---
plugin/smispy/smis.py | 53 ++++++++++++++++++++++++++-------------------------
1 file changed, 27 insertions(+), 26 deletions(-)

diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index 5a51e93..5a294b7 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -61,13 +61,13 @@ from dmtf import DMTF
# pool Object of LSM Pool
# vol Object of LSM Volume

-## Method Naming schme:
+## Method Naming scheme:
# _cim_xxx()
-# Return CIMInstance without any Associators() call.
+# Return CIMInstance without any Associations() call.
# _cim_xxx_of(cim_yyy)
# Return CIMInstance associated to cim_yyy
# _adj_cim_xxx()
-# Retrun CIMInstance with 'adj' only
+# Return CIMInstance with 'adj' only
# _cim_xxx_of_id(some_id)
# Return CIMInstance for given ID

@@ -167,7 +167,7 @@ def _lsm_tgt_port_type_of_cim_fc_tgt(cim_fc_tgt):
We are assuming we got CIM_FCPort. Caller should make sure of that.
Return TargetPool.PORT_TYPE_FC as fallback
"""
- # In SNIA SMI-S 1.6.1 public draft 2, 'PortDiscriminator' is mandatroy
+ # In SNIA SMI-S 1.6.1 public draft 2, 'PortDiscriminator' is mandatory
# for FCoE target port.
if 'PortDiscriminator' in cim_fc_tgt and \
cim_fc_tgt['PortDiscriminator'] and \
@@ -851,7 +851,7 @@ class Smis(IStorageAreaNetwork):
if self.fallback_mode:
flag_fc_support = True
flag_iscsi_support = True
- # CIM_FCPort is the contral class of FC Targets profile
+ # CIM_FCPort is the control class of FC Targets profile
try:
self._cim_fc_tgt_of(cim_sys_path)
except CIMError as e:
@@ -932,7 +932,7 @@ class Smis(IStorageAreaNetwork):
PropertyList=cim_gmm_cap_pros)[0]

# if empty dev group in spc is allowed, RemoveMembers() is enough
- # to do volume_unamsk(). RemoveMembers() is mandatory.
+ # to do volume_unmask(). RemoveMembers() is mandatory.
if DMTF.GMM_CAP_DEV_MG_ALLOW_EMPTY_W_SPC in \
cim_gmm_cap['SupportedDeviceGroupFeatures']:
cap.set(Capabilities.VOLUME_UNMASK)
@@ -1157,7 +1157,7 @@ class Smis(IStorageAreaNetwork):

def _init_id(self, cim_init):
"""
- Retrive Initiator ID from CIM_StorageHardwareID
+ Retrieve Initiator ID from CIM_StorageHardwareID
"""
return self._id('Initiator', cim_init)

@@ -1241,7 +1241,7 @@ class Smis(IStorageAreaNetwork):

def _cim_vol_pros(self):
"""
- Retrun the PropertyList required for creating new LSM Volume.
+ Return the PropertyList required for creating new LSM Volume.
"""
props = ['ElementName', 'NameFormat',
'NameNamespace', 'BlockSize', 'NumberOfBlocks', 'Name',
@@ -1319,7 +1319,7 @@ class Smis(IStorageAreaNetwork):
name = cv['Name']
if not (nf and nn and name):
return None
- # SNIA might missly said VPD83Type3(1), it should be
+ # SNIA might have miss documented VPD83Type3(1), it should be
# VOL_NAME_FORMAT_OTHER(1) based on DMTF.
# Will remove the Smis.VOL_NAME_FORMAT_OTHER condition if confirmed as
# SNIA document fault.
@@ -1431,7 +1431,7 @@ class Smis(IStorageAreaNetwork):

def _cim_inits_to_lsm(self, cim_inits):
"""
- Retrive AccessGroup.init_ids and AccessGroup.init_type from
+ Retrieve AccessGroup.init_ids and AccessGroup.init_type from
a list of CIM_StorageHardwareID.
"""
init_ids = []
@@ -2087,7 +2087,7 @@ class Smis(IStorageAreaNetwork):
cim_iscsi_pgs = self._cim_iscsi_pg_of(cim_sys_path)
in_params['Members'] = [x.path for x in cim_iscsi_pgs]
else:
- # Already checked at the begining of this method
+ # Already checked at the beginning of this method
pass

cim_tgt_mg_path = None
@@ -2312,7 +2312,7 @@ class Smis(IStorageAreaNetwork):

flag_init_mg_found = False
cur_cim_init_mg = None
- # Seaching for CIM_DeviceMaskingGroup
+ # Searching for CIM_DeviceMaskingGroup
for cim_spc_path in cim_spcs_path:
cim_init_mgs = self._c.Associators(
cim_spc_path,
@@ -2920,12 +2920,13 @@ class Smis(IStorageAreaNetwork):

if cim_init is None:
raise LsmError(ErrorNumber.NO_STATE_CHANGE,
- "Initiator %s does not exist in defined access group %s" %
- (init_id, access_group.id))
+ "Initiator %s does not exist in defined "
+ "access group %s" %
+ (init_id, access_group.id))

if len(cur_cim_inits) == 1:
raise LsmError(ErrorNumber.LAST_INIT_IN_ACCESS_GROUP,
- "Refuse to remove last initiator from access group")
+ "Refuse to remove last initiator from access group")

cim_gmm_path = self._get_cim_service_path(
cim_sys.path, 'CIM_GroupMaskingMappingService')
@@ -2988,7 +2989,7 @@ class Smis(IStorageAreaNetwork):

def _enumerate(self, class_name, property_list=None):
"""
- Please do the filter of "sytems=" in URI by yourself.
+ Please do the filter of "systems=" in URI by yourself.
"""
if len(self.all_vendor_namespaces) == 0:
# We need to find out the vendor spaces.
@@ -3018,10 +3019,10 @@ class Smis(IStorageAreaNetwork):
CIM_PhysicalPackage
CIM_DiskDrive
CIM_StorageExtent (Primordial)
- Due to 'Multiple Computer System' profile, disks might assocated to
- sub ComputerSystem. To improve profromance of listing disks, we will
+ Due to 'Multiple Computer System' profile, disks might associated to
+ sub ComputerSystem. To improve performance of listing disks, we will
use EnumerateInstances(). Which means we have to filter the results
- by ourself in case URI contain 'system=xxx'.
+ by ourselves in case URI contain 'system=xxx'.
"""
rc = []
if not self.fallback_mode:
@@ -3433,7 +3434,7 @@ class Smis(IStorageAreaNetwork):
Return True if FC Target Port 1.4+ profile is supported.
For fallback_mode, we call self._cim_iscsi_pg_of() and do try-except
For fallback_mode:
- Even CIM_EthernetPort is the contral class of iSCSI Target
+ Even CIM_EthernetPort is the control class of iSCSI Target
Ports profile, but that class is optional. :(
We use CIM_iSCSIProtocolEndpoint as it's a start point we are
using in our code of target_ports().
@@ -3515,7 +3516,7 @@ class Smis(IStorageAreaNetwork):
"""
port_id = md5(cim_fc_tgt['DeviceID'])
port_type = _lsm_tgt_port_type_of_cim_fc_tgt(cim_fc_tgt)
- # SNIA define WWPN string as upper, no spliter, 16 digits.
+ # SNIA define WWPN string as upper, no splitter, 16 digits.
# No need to check.
wwpn = _hex_string_format(cim_fc_tgt['PermanentAddress'], 16, 2)
port_name = cim_fc_tgt['ElementName']
@@ -3672,7 +3673,7 @@ class Smis(IStorageAreaNetwork):
nics = []
# NetApp ONTAP cluster-mode show one IP bonded to multiple
# ethernet,
- # Not suer it's their BUG or real ethernet channel bonding.
+ # Not sure it's their BUG or real ethernet channel bonding.
# Waiting reply.
if len(cim_eths) == 0:
nics = [('', '')]
@@ -3832,7 +3833,7 @@ class Smis(IStorageAreaNetwork):
"""
Return out[out_key] if found rc == INVOKE_OK.
For rc == INVOKE_ASYNC, we check every Smis.INVOKE_CHECK_INTERVAL
- seconds until done. Then return assocition via CIM_AffectedJobElement
+ seconds until done. Then return association via CIM_AffectedJobElement
Return CIM_InstanceName
Assuming only one CIM_InstanceName will get.
"""
@@ -3880,7 +3881,7 @@ class Smis(IStorageAreaNetwork):
"%d: %s" % (job_state, cim_job.items()))
if len(cim_xxxs_path) != 1:
raise LsmError(ErrorNumber.PLUGIN_BUG,
- "_wait_invoke(): got unexpect(not 1) "
+ "_wait_invoke(): got unexpected(not 1) "
"return from CIM_AffectedJobElement: "
"%s, out: %s, job: %s" %
(cim_xxxs_path, out.items(),
@@ -3968,7 +3969,7 @@ class Smis(IStorageAreaNetwork):
Actually, only EMC VMAX/DMX support this now(July 2014).
Steps:
0. Check exist SPC of init_id for duplication call and
- confliction.
+ conflict.
1. Create CIM_InitiatorMaskingGroup
"""
org_init_id = init_id
@@ -4062,7 +4063,7 @@ class Smis(IStorageAreaNetwork):
md5(exist_cim_init_mgs[0]['InstanceID'])))
# 2. Requested name used by other group.
# Since 1) already checked whether any group containing
- # requested init_id, now, it's surelly a confliction.
+ # requested init_id, now, it's surly a conflict.
exist_cim_init_mgs = self._cim_init_mg_of(
cim_sys.path, property_list=['ElementName'])
for exist_cim_init_mg in exist_cim_init_mgs:
--
1.8.2.1
Loading...