SMI-S plugin: Refactor, add smis_common.py, utils.py, dmtf.py files

 * The SMI-S provider of HP 3PAR and LSI/Avago MegaRAID is using
   'root/PG_Interop' namespace for profile register. Adding
   'root/PG_Interop' into check list for profile register namespace.
 * Move _merge_list() to separate file utils.py
 * Move smis._merge_list() to utils.merge_list().
 * Makefile and rpm spec updated.
 * Moving SNIA class constants into SmisCommon class.
 * SmisCommon class will handle WBEM connection which need __init__(),
   so we create a SmisCommon class instead of using smis_common namespace.
 * Makefile and RPM spec file updated.
 * Move these constants into DMTF as they are defined in DMTF DSP1033:
    Smis.DMTF_INTEROP_NAMESPACES => DMTF.INTEROP_NAMESPACES
    Smis.SMIS_DEFAULT_NAMESPACE => DMTF.DEFAULT_NAMESPACE
 * Move WBEM connection to SmisCommon. This allow use to move to other
   WBEM client library in the future(like lmiwbem) with limited changes.
 * In Smis class, the 'self._c' was a object of pywbem.WBEMConnection, now
   a object of SmisCommon.
 * To limit the changes of Smis class, wrap used method of WBEMConnection
   in SmisCommon:
    EnumerateInstances()
    EnumerateInstanceNames()
    InvokeMethod()
    GetInstance()
    References()
    DeleteInstance()
    Associators()
    AssociatorNames()
   These method names is defined by DMTF DSP0200, so I keep these CaMel method
   name.

 * EnumerateInstances() and EnumerateInstanceNames() will enumerate in vendor
   name space instead of interop namespace. The vendor namespace was checked
   by SmisCommon._vendor_namespace(self) via CIM_ElementConformsToProfile
   association.

 * New profile register in SmisCommon.__init__():
    1. Only store highest version of certain profile.
       Support status will be stored as SmisCommon._profile_dict in this
       format:
        {
            SmisCommon.SNIA_DISK_LITE_PROFILE: \
                SmisCommon.SMIS_SPEC_VER_1_4,

        }
       The SmisCommon._profile_dict will be used by
       SmisCommon.profile_check().
    2. Store root CIM_RegisteredProfile as SmisCommon.root_blk_cim_rp.
       It will be used by Smis._root_cim_syss() method. (In other patch)
    3. New profile support status check SmisCommon.profile_check().
    4. Skip MegaRAID profile register check as they only support 1.2 'Array'
       profile.

 * Replace Smis._profile_is_supported() with SmisCommon.profile_check().
 * Smis.cim_root_profile_dict is not needed anymore as
   Smis._profile_is_supported() is replaced.

 * Replace Smis._enumerate() with SmisCommon.EnumerateInstances() as
   SmisCommon will handle the vendor namespace issue now.

 * Replace Smis._enumerate() in disk capability check with
   EnumerateInstanceNames() to save some time.[1]

 * New method SmisCommon.is_megaraid(). It could be used to determine
   the vendor specific code.

 * Update Smis._root_cim_syss() to use SmisCommon.root_blk_cim_rp for
   CIM_ElementConformsToProfile association.

 * LSI/Avago MegaRAID has vendor specific code as it skip the profile
   check[2]. It just enumerate all CIM_ComputerSystem as MegaRAID does not
   support 'Multiple Computer System' profile.

 [1] EnumerateInstanceNames() only return CIMInstanceName which contains
    less data than a CIMInstance. For capability check, we just want to
    find whether CIM_DiskDrive is supported or not. CIMInstanceName is enough
    for this.

 [2] If profile check skiped, SmisCommon.root_blk_cim_rp will be None.

Signed-off-by: Gris Ge <fge@redhat.com>
SMI-S plugin: Refactor, remove eseries.py, smisproxy.py files

 * Remove fallback mode as no array really need them.
   All SMI-S provider I have access support DMTF profile register and support
   SMI-S 1.4 'Array' profile[1].
 * New method: SmisCommon.is_netappe() for NetApp-E vendor code check.
 * Simply move eseries.py codes into smis.py using SmisCommon.is_netappe()
   check.
 * Remove eseries.py file.
 * Makefile and RPM spec file updated.
 * SmisProxy is not needed any more after eseries.py got removed.
 * Vendor specific code will be stored in smis.py or future sub
   module/namespace of smis.py.
 * Makefile and RPM spec file updated.

Changes in V2:

 * Fixed a NetApp-E bug:
        Old:
            self._vendor_namespace = SmisCommon._PRODUCT_NETAPP_E

            def is_netappe(self):
                return self._vendor_product == SmisCommon._PRODUCT_MEGARAID

        New:
            self._vendor_product = SmisCommon._PRODUCT_NETAPP_E

            def is_netappe(self):
                return self._vendor_product == SmisCommon._PRODUCT_NETAPP_E

[1] LSI/Avago MegaRAID is using 1.2 and using vendor specific code in this
    plugin.

Signed-off-by: Gris Ge <fge@redhat.com>
SMI-S plugin: Refactor, add smis_cap.py, smis_constants.py files

Moving handle_cim_error, hex_string_format to utils.py

Move smis class constants to smis_constants.py, move remaining
DMTF constants to dmtf.py file.

There is quite a bit of code which is used to determine
what capabilities an array supports.  Move this into
a separate file of related functionality.

To make this work we needed to move:

- get_class_instance
- get_cim_service_path

To smis_common.py

I also moved the MASK_* constants to the new file too.

Updated:
- Rename file to smis_cap.py
- Change from class to functions instead

Signed-off-by: Tony Asleson <tasleson@redhat.com>
SMI-S Plugin: Refactor, add smis_sys.py

 * Just empty smis_sys.py file with license only.
 * Makefile and RPM spec file updated.
 * Replace Smis._property_list_of_id(self, "System") with
   smis_sys.cim_sys_id_pros()
 * Replace Smis._sys_id(self, cim_sys) with
   smis_sys.sys_id_of_cim_sys(cim_sys)
 * Move Smis.system_list to SmisCommon.system_list to allow
   other smis_sys.py to do system filtering.
 * Replaced Smis._root_cim_syss(self) with smis_sys.root_cim_sys(smis_common)
 * Replace Smis._cim_sys_pros(self) with smis_sys.cim_sys_pros()
 * Make DMTF._dmtf_op_status_list_conv() public as
   DMTF.dmtf_op_status_list_conv().
 * Move DMTF.cim_sys_status_of() to smis_sys._sys_status_of_cim_sys().
   # Only used in smis_sys internally, hence hide from public.
 * Move Smis._cim_sys_to_lsm() to smis_sys.cim_sys_to_lsm_sys()
 * Add DMTF.OP_STATUS_UNKNOWN -> System.STATUS_UNKNOWN map.
   Found EMC SMI-S provider will use 0(Unknown) for outdated system.
 * Including smis_sys._sys_status_of_cim_sys() and
   smis_sys.cim_sys_to_lsm_sys() changes in one patch as
   _sys_status_of_cim_sys() is only used by smis_sys.cim_sys_to_lsm_sys().
 * Replace Smis._get_cim_instance_by_id("System") with
   smis_sys.cim_sys_of_sys_id()
 * Fix the bug when query filtered system.
   Example:

    URI: smispy://admin@emc-smi?systems=CLARiiON+APM00041704073
    CMD: lsmcli capabilities --sys CLARiiON+FCN00122500421

    Expected result:
        lsmcli should report system not found as URI already filter that
        requested system out.

    Actual result:
        lsmcli got capabilities of filtered system.

    Fix:
        Replace EnumerateInstances("CIM_ComputerSystem") with
        smis_sys.root_cim_sys() which implemented the system filter.

Signed-off-by: Gris Ge <fge@redhat.com>
SMI-S Plugin: Refactor, add smis_pool.py file

 * Empty smis_pool.py with license only.
 * Makefile and RPM spec file updated.
 * Replace Smis._cim_pools_of() with smis_pool.cim_pools_of_cim_sys_path()
 * Merge the pool filtering(remove spare pool and other unused pool) into
   smis_pool.cim_pools_of_cim_sys_path().
   With this, it save some WBEM calls[1] in volumes().
   Performance changes for volumes()(lsmcli list --type volumes):
    EMC VNX with 95 volumes:
        Old: 13.37s
        New:  8.97s

 * Replace Smis._pool_id() with smis_pool.pool_id_of_cim_pool()
 * Replace Smis._property_list_of_id(self, 'Pool') with
   smis_pool.cim_pool_id_pros()
 * Replaced Smis._new_pool_cim_pool_pros(self) with
   smis_pool.cim_pool_pros()
 * Remove smis_constants.JOB_RETRIEVE_POOL
 * Remove Smis._new_pool_from_name() and Smis._new_pool_from_job()
 * Move DMTF.cim_pool_status_of() to
   smis_pool._pool_status_of_cim_pool().
   # This method is for smis_pool internal use only now.
 * Move Smis._pool_element_type() to
   smis_pool._pool_element_type()
   # This method is for smis_pool internal use only now.
 * Removed Smis._sys_id_of_cim_pool() as no method require it.
 * Add MegaRAID workaround for smis_pool._pool_element_type()
   to improve performance by returning (Pool.ELEMENT_TYPE_VOLUME, 0)
   directly. Tested on a remote MegaRAID card with two pools:
    Old: 10.10s     # With all pending patches but this one.
    New:  4.61s
 * Move Smis._new_pool() to smis_pool.cim_pool_to_lsm_pool()
 * Including three changes in patch as _pool_status_of_cim_pool() and
   _pool_element_type() are internal methods for
   smis_pool.cim_pool_to_lsm_pool() now.
 * Using json to save the CIMInstanceName of CIM_StoragePool into
   lsm.Pool.plugin_data and convert it back when needed:
    * Save:
        Pool.plugin_data = json.dumps({
            'classname': cim_path.classname,
            'keybindings': dict(cim_path.keybindings),
            'host': cim_path.host,
            'namespace': cim_path.namespace,
        })

    * Load:
        CIMInstanceName(**json.loads(Pool.plugin_data))

 * Replace Smis._get_cim_instance_by_id(self, 'Pool', pool.id) with
   smis_pool.lsm_pool_to_cim_pool_path(smis_common, pool)
 * Replace Smis._get_pool_from_vol() with smis_pool.pool_id_of_cim_vol()

Changes in V2:
 * Fix the error message formatter.
 * Use json instead of cPickle for security concern[2].

[1] Old codes will try to find volumes on spare pool or other unused pool
    which is waster of time.
[2] __reduce__() will be called by cPickle.loads() which might be
    use to excute any command remoted.

Signed-off-by: Gris Ge <fge@redhat.com>
SMI-S Plugin: Refactor, add smis_disk.py file.

 * Empty smis_disk.py with license file only.
 * Makefile and RPM spec file updated.
 * Remove as no method is using EMC_DISK_STATUS_REMOVED constants.
 * Replace DMTF.cim_disk_status_of() with smis_disk.disk_status_of_cim_disk()
 * Replace dmtf.dmtf_disk_type_2_lsm_disk_type() with
   smis_disk.dmtf_disk_type_2_lsm_disk_type()
 * Remove unused method Smis._cim_disk_of_pri_ext()
 * Replace Smis._disk_id() with smis_disk.disk_id_of_cim_disk()
 * Replace Smis._new_disk_cim_disk_pros() with
   smis_disk.cim_disk_pros()
 * Replace Smis._sys_id_child(cim_disk) with
   smis_disk.sys_id_of_cim_disk(cim_disk)
 * Replace Smis._new_disk() with smis_disk.cim_disk_to_lsm_disk()
 * Moved Smis._pri_cim_ext_of_cim_disk() into smis_disk.
 * Merged Smis._new_disk_cim_ext_pros() into smis_disk.cim_disk_to_lsm_disk()
   as no need to has a method for storing a non-shared list.
 * Combining these changes in one patch as they are internal actions for
   smis_disk.cim_disk_to_lsm_disk().
 * Hide these internal methods of smis_disk:
    smis_disk.disk_id_of_cim_disk()
        -> smis_disk._disk_id_of_cim_disk()
    smis_disk.dmtf_disk_type_2_lsm_disk_type()
        -> smis_disk._dmtf_disk_type_2_lsm_disk_type()
    smis_disk.disk_status_of_cim_disk()
        -> smis_disk._disk_status_of_cim_disk()

Signed-off-by: Gris Ge <fge@redhat.com>
SMI-S Plugin: Refactor dmtf.py

 * Move dmtf.DMTF.OP_STATUS_XXX to dmtf.DMTF_OP_STATUS_XXX.
 * Move dmtf.DMTF.dmtf_op_status_list_conv() to
   dmtf.dmtf_op_status_list_conv()
 * Move dmtf.DMTF.dmtf_op_status_to_str() to
   dmtf._dmtf_op_status_to_str()
 * Removed all dmtf.DMTF_STATUS_XXX constants as no method is
   using it.
 * Please use dmtf.DMTF_OP_STATUS_XXX instead if needed.
 * Remove DMTF class as no __init__() or methods any more.
 * All DMTF constants moved to dmtf.py file level.

Changes in V2:

 * Remove 'DMTF_' prefix of constants in dmtf.py.
 * Changed 'from dmtf import *' to 'import dmtf' in smis_xxx.py files.
 * Renamed dmtf.dmtf_op_status_list_conv() to dmtf.op_status_list_conv()

Signed-off-by: Gris Ge <fge@redhat.com>
SMI-S Plugin: Refactor, remove smis_constants.py

 * Move smis_constants.JS_XXX to dmtf.py:
    smis_constants.JS_NEW -> dmtf.JOB_STATE_NEW
    smis_constants.JS_STARTING -> dmtf.JOB_STATE_STARTING
    smis_constants.JS_RUNNING -> dmtf.JOB_STATE_RUNNING
    smis_constants.JS_COMPLETED -> dmtf.JOB_STATE_COMPLETED
 * Removed unused smis_constants.JS_XXX constatns:
    smis_constants.JS_SUSPENDED
    smis_constants.JS_SHUTTING_DOWN
    smis_constants.JS_TERMINATED
    smis_constants.JS_KILLED
    smis_constants.JS_EXCEPTION
 * Replace these constants:
    smis_constants.JOB_OK => dmtf.OP_STATUS_OK
    smis_constants.JOB_COMPLETE => dmtf.OP_STATUS_COMPLETED
 * Removed Unused constants:
    smis_constants.JOB_ERROR
    smis_constants.JOB_STOPPED
 * Move these InvokeMethod() return code to SmisCommon:
    smis_constants.INVOKE_OK => SmisCommon.SNIA_INVOKE_OK
    smis_constants.INVOKE_ASYNC => SmisCommon.SNIA_INVOKE_ASYNC
    smis_constants.INVOKE_NOT_SUPPORTED =>
        SmisCommon.SNIA_INVOKE_NOT_SUPPORTED
    smis_constants.INVOKE_FAILED => SmisCommon.SNIA_INVOKE_FAILED
 * Removed these InvokeMethod() return code as unused:
    smis_constants.INVOKE_TIMEOUT
    smis_constants.INVOKE_FAILED
    smis_constants.INVOKE_INVALID_PARAMETER
    smis_constants.INVOKE_IN_USE
    smis_constants.INVOKE_SIZE_NOT_SUPPORTED
 * Replaced these constants used by CreateElementReplica():
    smis_constants.SYNC_TYPE_MIRROR
        -> dmtf.SYNC_TYPE_MIRROR
    smis_constants.SYNC_TYPE_SNAPSHOT
        -> dmtf.SYNC_TYPE_SNAPSHOT
    smis_constants.SYNC_TYPE_CLONE
        -> dmtf.SYNC_TYPE_CLONE
    smis_constants.CREATE_ELEMENT_REPLICA_MODE_SYNC
        -> dmtf.REPLICA_MODE_SYNC
    smis_constants.CREATE_ELEMENT_REPLICA_MODE_ASYNC
        -> dmtf.REPLICA_MODE_ASYNC
 * Move these constants into dmtf.
    VOL_NAME_FORMAT_OTHER
    VOL_NAME_FORMAT_NNA
    VOL_NAME_FORMAT_EUI64
    VOL_NAME_FORMAT_T10VID

    VOL_NAME_SPACE_OTHER
    VOL_NAME_SPACE_VPD83_TYPE3
    VOL_NAME_SPACE_VPD83_TYPE2
    VOL_NAME_SPACE_VPD83_TYPE1
 * Removed these unused constants:
    VOL_NAME_FORMAT_VPD83_NNA6
    VOL_NAME_FORMAT_VPD83_NNA5
    VOL_NAME_FORMAT_VPD83_TYPE2
    VOL_NAME_FORMAT_VPD83_TYPE1
    VOL_NAME_FORMAT_VPD83_TYPE0
    VOL_NAME_FORMAT_SNVM
    VOL_NAME_FORMAT_NODE_WWN

    VOL_NAME_SPACE_OTHER
    VOL_NAME_SPACE_VPD80
    VOL_NAME_SPACE_NODE_WWN
    VOL_NAME_SPACE_SNVM
 * Move these constants to SmisCommon:
    smis_constants.JOB_RETRIEVE_NONE => SmisCommon.JOB_RETRIEVE_NONE
    smis_constants.JOB_RETRIEVE_VOLUME => SmisCommon.JOB_RETRIEVE_VOLUME
    # These two constants is just for plugin internal use, not a SNIA or DMTF
    # constant.
 * Move these constants into SmisCommon:
    smis_constants.IAAN_WBEM_HTTP_PORT => SmisCommon.IAAN_WBEM_HTTP_PORT
    smis_constants.IAAN_WBEM_HTTPS_PORT => SmisCommon.IAAN_WBEM_HTTPS_PORT
    # These two constant is defined by IETF IAAN. Store in SmisCommon class
    # which was supposed to hold non-dmtf constants.
 * Previously:
    incorrect use
    CIM_ReplicationServiceCapabilities['SupportedReplicationTypes'] --
    2(Synchronous Mirror Local) for Capabilities.VOLUME_REPLICATE
    capability.
   Now:
    Use CIM_ReplicationServiceCapabilities['SupportedSynchronousActions'] and
    ['SupportedAsynchronousActions'] -- 2(CreateElementReplica) for
    Capabilities.VOLUME_REPLICATE capability.
 * Remove smis_constants.RepSvc.Action class.
 * Add dmtf.REPLICA_CAP_ACTION_CREATE_ELEMENT for 2(CreateElementReplica)
   in CIM_ReplicationServiceCapabilities['SupportedSynchronousActions'] and
   ['SupportedAsynchronousActions'].
 * Replace smis_constants.RepSvc with these constants in dmtf.py:
    RepSvc.RepTypes.SYNC_SNAPSHOT_LOCAL
        -> dmtf.REPLICA_CAP_TYPE_SYNC_SNAPSHOT_LOCAL
    RepSvc.RepTypes.ASYNC_SNAPSHOT_LOCAL
        -> dmtf.REPLICA_CAP_TYPE_ASYNC_SNAPSHOT_LOCAL
    RepSvc.RepTypes.SYNC_CLONE_LOCAL
        -> dmtf.REPLICA_CAP_TYPE_SYNC_CLONE_LOCAL
    RepSvc.RepTypes.ASYNC_CLONE_LOCAL
        -> dmtf.REPLICA_CAP_TYPE_ASYNC_CLONE_LOCAL
    RepSvc.RepTypes.SYNC_MIRROR_LOCAL
        -> dmtf.REPLICA_CAP_TYPE_SYNC_MIRROR_LOCAL
    RepSvc.RepTypes.ASYNC_MIRROR_LOCAL
        -> dmtf.REPLICA_CAP_TYPE_ASYNC_MIRROR_LOCAL
 * Removed these unused constants:
    RepSvc.RepTypes.SYNC_MIRROR_REMOTE
    RepSvc.RepTypes.ASYNC_MIRROR_REMOTE
    RepSvc.RepTypes.SYNC_CLONE_REMOTE
    RepSvc.RepTypes.ASYNC_CLONE_REMOTE
 * Replace smis_constants.CopyStates with dmtf.py constants:
    smis_constants.CopyStates.SYNCHRONIZED
        -> dmtf.COPY_STATE_SYNC
 * Removed smis_constants.CopyStates unused constants:
    smis_constants.CopyStates.INITIALIZED
    smis_constants.CopyStates.UNSYNCHRONIZED
    smis_constants.CopyStates.INACTIVE
 * Remove smis_constants.CopyStates class.
 * Replaced smis_constants.CopyTypes by dmtf constants:
    smis_constants.CopyTypes.ASYNC
        -> dmtf.ST_CONF_CAP_COPY_TYPE_ASYNC
    smis_constants.CopyTypes.SYNC
        -> dmtf.ST_CONF_CAP_COPY_TYPE_SYNC
    smis_constants.CopyTypes.UNSYNCASSOC
        -> dmtf.ST_CONF_CAP_COPY_TYPE_UNSYNC_ASSOC
    smis_constants.CopyTypes.UNSYNCUNASSOC
        -> dmtf.ST_CONF_CAP_COPY_TYPE_UNSYNC_UNASSOC
 * Removed smis_constants.CopyTypes as all its constants moved out.
 * Replaced this constants by dmtf one:
    smis_constants.Synchronized.SyncState.SYNCHRONIZED
        -> dmtf.ST_SYNC_STATE_SYNCHRONIZED
 * Removed unused constants in smis_constants.py:
    smis_constants.Synchronized.SyncState.INITIALIZED
    smis_constants.Synchronized.SyncState.PREPAREINPROGRESS
    smis_constants.Synchronized.SyncState.PREPARED
    smis_constants.Synchronized.SyncState.RESYNCINPROGRESS
    smis_constants.Synchronized.SyncState.FRACTURE_IN_PROGRESS
    smis_constants.Synchronized.SyncState.QUIESCEINPROGRESS
    smis_constants.Synchronized.SyncState.QUIESCED
    smis_constants.Synchronized.SyncState.RESTORE_IN_PROGRESSS
    smis_constants.Synchronized.SyncState.IDLE
    smis_constants.Synchronized.SyncState.BROKEN
    smis_constants.Synchronized.SyncState.FRACTURED
    smis_constants.Synchronized.SyncState.FROZEN
    smis_constants.Synchronized.SyncState.COPY_IN_PROGRESS
 * Remove smis_constants.Synchronized class as all its constants moved out.
 * Removed these unused constants of smis_constants.py:
        CREATE_ELEMENT_REPLICA_MODE_SYNC
        CREATE_ELEMENT_REPLICA_MODE_ASYNC
        VOL_OP_STATUS_OK
        VOL_OP_STATUS_DEGRADED
        VOL_OP_STATUS_ERR
        VOL_OP_STATUS_STARTING
        VOL_OP_STATUS_DORMANT
        EXPOSE_PATHS_DA_READ_ONLY
 * Replace smis_constants.EXPOSE_PATHS_DA_READ_WRITE with
   dmtf.CTRL_CONF_SRV_DA_RW
 * Remove empty smis_constants.py file.
 * Makefile and rpm SPEC file updated

Signed-off-by: Gris Ge <fge@redhat.com>
SMI-S Plugin: Workaround for volume name duplication check after job creation.

Problem:
    EMC VNX SMI-S provider will create a CIM_ConcreteJob when volume_create()
    with exist volume name. It will mark CIM_ConcreteJob as failed for
    volume confliction.

Root Cause:
    Out SMI-S plugin only does error handling for duplicate volume name when
    job creation for volume_create(), not after a job_creation.

Fix:
    Run this duplication check in job_status() for volume_create:
        self._check_for_dupe_vol(volume_name, sys.exc_info())

Detail Fix:
    1. New constant SmisCommon.JOB_RETRIEVE_VOLUME_CREATE to indicate
       a job is generated by volume_create().
    2. Store method_data into job id:

        self._job_id(cim_job, retrieve_data, method_data)
        Smis._parse_job_id(job_id)
        self._pi(msg, retrieve_data, method_data, rc, out)
       # method_data could be used to store information(string) into job_id
       # for error handling in job_status()
    3. Run self._check_for_dupe_vol() in job_status() if cim_job failed.
    4. Change self._check_for_dupe_vol() to allow setting original_exception
       as None. In that case, it will not raise error when not NAME_CONFLICT.

Before fix:

    $ lsmcli vc --name gris_test_10 \
      --pool 'CLARiiON+FCN00122500421+U+Pool 0' --size 1B

    PLUGIN_BUG(2): C:ERROR_CLASS_SOFTWARE F:ERROR_FAMILY_FAILED R:1000006 An
    error from a sub-library call occurred : 2 : 20027 : "The specified LUN
    name is already in use."

After fix:

    $ lsmcli vc --name gris_test_10 \
      --pool 'CLARiiON+FCN00122500421+U+Pool 0' --size 1B

    NAME_CONFLICT(50): Volume with name 'gris_test_10' already exists!

Signed-off-by: Gris Ge <fge@redhat.com>
SMI-S Plugin: Check duplicate name in volume_replicate()

 * Some (EMC VMAX, Dot hill) SMI-S Providers allow duplicated
   ElementName when creating replication, we have to do a pre-check by
   enumerating all CIM_StroageVolume with 'ElementName' property only.

 * EMC VMAX passed the 'TestPlugin.test_volume_replication' test of
   plugin_test.py.

V2:
- We don't need to check for duplicate volume name in the exception
  handler if we already checked before trying to replicate
- Move quicker search code into method so it can be shared.
- rebased

Signed-off-by: Gris Ge <fge@redhat.com>
Signed-off-by: Tony Asleson <tasleson@redhat.com>
Plugin test: Fix incorrect NAME_CONFLICT check in test_volume_replication()

 * If certain plugin didn't raise LsmError on NAME_CONFLICT for
   volume_create(), plugin_test.py will incorrectly treat it as PASS.
   This patch fixed it by using a error_num variable to checking
   NAME_CONFLICT.

Signed-off-by: Gris Ge <fge@redhat.com>
simarray.py: Lock state file

There is a possiblity of an older exiting simulator plugin writing
its state out while a new client is reading state from the file.
Ensure this cannot happen with a lock on the state file to ensure
that only one plugin can be mucking with the state file at one time.

This is only a theory as I'm unable to reproduce a failure I was
seeing while building packages, but it would be good to prevent
concurrent access to the state file regardless.

The file is opened and locked and kept open until the plugin is
closed.

Signed-off-by: Tony Asleson <tasleson@redhat.com>
Fix mem leaks in lsm_daemon.c, simc_lsmplugin.c

Not likely to happen in normal operation.

Signed-off-by: Tony Asleson <tasleson@redhat.com>
rpm spec: Use correct tmpfiles.d dir

Signed-off-by: Tony Asleson <tasleson@redhat.com>
rpm spec: Move command line python files to python package

We cannot have files that have a py extension in packages that are
not in noarch rpm.  This is to prevent a user from installing both
32bit and 64bit packages on the same system from having signature
conflicts for the compiled python files (pyc).

Signed-off-by: Tony Asleson <tasleson@redhat.com>
rpm spec: udev files to /usr/lib dir instead of /lib

Later versions of Fedora and EL linux moved /lib to /usr/lib.

Signed-off-by: Tony Asleson <tasleson@redhat.com>
lsmcli: new alias lt = lsmcli list --type target_ports

 * Create new alias 'lsmcli lt' for this command:
    lsmcli list --type target_ports

Signed-off-by: Gris Ge <fge@redhat.com>
lsmenv: Integrate with plugin_test.py

 * Update plugin_test.py to read LSM_TEST_URI and LSM_TEST_PASSWORD
   if command line arguments didn't provided URI and password.

 * Update lsmenv to set LSM_TEST_URI and LSM_TEST_PASSWORD for given device
   alias.

 * Create a shortcut in lsmenv for plugin_test.py. Example:
    lsmenv vnx plugin_test

 * This patch just save my time of typing uri and password for plugin_test.

Signed-off-by: Gris Ge <fge@redhat.com>
Library: Add new element_type to pool for thin provisioning.

 * 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 <fge@redhat.com>
lsmcli: Add new element types of lsm.Pool.

 * 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 <fge@redhat.com>