Discussion:
[Libstoragemgmt-devel] [PATCH 00/14] Tony and Gris patches.
Gris Ge
2014-08-04 14:41:26 UTC
Permalink
I combined tony's patches with my V2 patches.

This patch set contains:
1. Fix bugs found by OBS compile.
2. Change rpm spec and etc to support OBS build.
3. Access Group WWPN form.
4. Clean up AccessGroup.
5. Fix bugs of SMI-S plugin about access group.

Tested by 'make check' by OBS:
https://build.opensuse.org/project/monitor/home:cathay4t:libstoragemgmt-test

Gris Ge (11):
rpm spec: fix for OBS build
test: allowing runtest to show log of lsmd
test: empty expected_absent capabilities check
lsmcli: use python-ordereddict for python <= 2.6
Remove INIT_TYPE_WWNN and etc unused initiator type
Python API: standardize the WWPN
C API: Rename LSM_ERR_INVALID_IQN to LSM_ERR_INVALID_INIT
lsmcli: Remove --init-type argument
ontap plugin: Rename INVALID_IQN to INVALID_INIT
SMI-S plugin: standardize the WWPN
SMI-S plugin: Fix access group bugs

Tony Asleson(3):
Remove v7k plugin
cmdline.py: Check before reference
C API: Simplify lsm_capability_set_n


c_binding/include/libstoragemgmt/libstoragemgmt.h | 4 +-
.../libstoragemgmt/libstoragemgmt_capabilities.h | 2 +
.../include/libstoragemgmt/libstoragemgmt_error.h | 3 +-
.../libstoragemgmt/libstoragemgmt_plug_interface.h | 25 +-
.../include/libstoragemgmt/libstoragemgmt_types.h | 15 +-
c_binding/lsm_datatypes.cpp | 28 +-
c_binding/lsm_datatypes.hpp | 12 -
c_binding/lsm_mgmt.cpp | 6 +-
c_binding/lsm_plugin_ipc.cpp | 6 +-
configure.ac | 15 -
daemon/lsm_daemon.c | 1 +
doc/man/lsmcli.1.in | 12 +-
packaging/libstoragemgmt.spec.in | 88 ++---
plugin/Makefile.am | 9 -
plugin/ontap/ontap.py | 2 +-
plugin/sim/simarray.py | 9 +-
plugin/simc/simc_lsmplugin.c | 11 +-
plugin/smispy/smis.py | 222 +++++++------
plugin/v7k/__init__.py | 0
plugin/v7k/ibmv7k.py | 364 ---------------------
plugin/v7k/v7k_lsmplugin | 36 --
python_binding/lsm/_client.py | 4 +
python_binding/lsm/_common.py | 2 +-
python_binding/lsm/_data.py | 99 +++++-
test/cmdtest.py | 7 +-
test/runtests.sh | 73 +++--
test/tester.c | 86 ++---
tools/lsmcli/cmdline.py | 61 ++--
tools/lsmcli/data_display.py | 11 +-
29 files changed, 388 insertions(+), 825 deletions(-)
delete mode 100644 plugin/v7k/__init__.py
delete mode 100644 plugin/v7k/ibmv7k.py
delete mode 100755 plugin/v7k/v7k_lsmplugin
--
1.8.3.1
Gris Ge
2014-08-04 14:41:27 UTC
Permalink
This plugin is being removed for the following reasons:

1. No hardware to test it on
2. Plugin is not feature complete
3. SMI-S plugin at this point should offer a better experience
for the user

We can certainly bring it back if needed.

Signed-off-by: Tony Asleson <***@redhat.com>
---
configure.ac | 15 --
packaging/libstoragemgmt.spec.in | 41 -----
plugin/Makefile.am | 9 -
plugin/v7k/__init__.py | 0
plugin/v7k/ibmv7k.py | 364 ---------------------------------------
plugin/v7k/v7k_lsmplugin | 36 ----
6 files changed, 465 deletions(-)
delete mode 100644 plugin/v7k/__init__.py
delete mode 100644 plugin/v7k/ibmv7k.py
delete mode 100755 plugin/v7k/v7k_lsmplugin

diff --git a/configure.ac b/configure.ac
index b200078..cbf668b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -136,16 +136,6 @@ fi
AM_CONDITIONAL([BUILD_C_UNIT], [test "x${want_c_unit}" = "xyes"])

dnl ==========================================================================
-dnl Check to see if user wants to exclude code that depends on python-paramiko
-dnl ==========================================================================
-
-AC_ARG_WITH([paramiko],
- [AS_HELP_STRING([--without-paramiko], [Remove paramiko requirement and disables code which uses it, eg. IBM7K Plugin])],
- [], [with_paramiko="yes"])
-
-AM_CONDITIONAL([HAVE_PARAMIKO], [test "x${with_paramiko}" = "xyes"])
-
-dnl ==========================================================================
dnl Check for python as it is needed for the base cmd line function
dnl ==========================================================================

@@ -154,11 +144,6 @@ AC_PYTHON_MODULE([pywbem], [Required])
AC_PYTHON_MODULE([M2Crypto], [Required])
AC_PYTHON_MODULE([argparse], [Required])

-
-if test "x${with_paramiko}" = "xyes"; then
- AC_PYTHON_MODULE([paramiko], [Required])
-fi
-
dnl ==========================================================================
dnl Check for libmicrohttpd and json-c as it is needed for REST API daemon
dnl ==========================================================================
diff --git a/packaging/libstoragemgmt.spec.in b/packaging/libstoragemgmt.spec.in
index 2048da8..eaf9352 100644
--- a/packaging/libstoragemgmt.spec.in
+++ b/packaging/libstoragemgmt.spec.in
@@ -1,5 +1,4 @@
%bcond_without rest_api
-%bcond_without ibm_v7k

%if 0%{?rhel} <= 6
%global with_rest_api 0
@@ -9,22 +8,12 @@
# rpmbuild -ba libstoragemgmt.spec --with rest_api
%endif

-%if 0%{?rhel} >= 7
-%global with_ibm_v7k 0
-%endif
-
%{?_with_rest_api:
%global with_rest_api 1
}
%{?_without_rest_api:
%global with_rest_api 0
}
-%{?_with_ibm_v7k:
-%global with_ibm_v7k 1
-}
-%{?_without_ibm_v7k:
-%global with_ibm_v7k 0
-}

Name: libstoragemgmt
Version: @VERSION@
@@ -44,9 +33,6 @@ BuildRequires: gcc-c++
# These buggy extra conditional BuildRequires is for OBS only,
# Please refer to OBS bug:
# https://bugzilla.novell.com/show_bug.cgi?id=864323
-%if 0%{?fedora} || 0%{?rhel} <= 6
-BuildRequires: python-paramiko
-%endif
%if 0%{?fedora} || 0%{?rhel} >= 7
BuildRequires: libmicrohttpd-devel json-c-devel
%endif
@@ -129,21 +115,6 @@ The %{name}-targetd-plugin package contains plug-in for targetd array
support.


-%if 0%{?with_ibm_v7k}
-%package ibm-v7k-plugin
-Summary: Files for IBM v7k array support for %{name}
-Group: System Environment/Libraries
-Requires: python-paramiko %{name}-python
-Requires: libstoragemgmt-python = %{version}-%{release}
-BuildRequires: python-paramiko
-BuildArch: noarch
-
-%description ibm-v7k-plugin
-The %{name}-ibm-v7k-plugin package contains plug-in for IBM v7k array
-support.
-%endif
-
-
%package nstor-plugin
Summary: Files for NexentaStor array support for %{name}
Group: System Environment/Libraries
@@ -183,9 +154,6 @@ the %{name}-rest package contains the http daemon for %{name} rest api.

#Tell the install program to preserve file date/timestamps
%configure \
-%if 0%{?with_ibm_v7k} != 1
- --without-paramiko \
-%endif
%if 0%{?with_rest_api} != 1
--without-rest-api \
%endif
@@ -362,15 +330,6 @@ fi
%{python_sitelib}/lsm/plugin/targetd/targetd.*
%{_bindir}/targetd_lsmplugin

-
-%if 0%{?with_ibm_v7k}
-%files ibm-v7k-plugin
-%defattr(-,root,root,-)
-%{python_sitelib}/lsm/plugin/v7k/__init__.*
-%{python_sitelib}/lsm/plugin/v7k/ibmv7k.*
-%{_bindir}/v7k_lsmplugin
-%endif
-
%files nstor-plugin
%defattr(-,root,root,-)
%{python_sitelib}/lsm/plugin/nstor/__init__.*
diff --git a/plugin/Makefile.am b/plugin/Makefile.am
index a8f43da..96a243a 100644
--- a/plugin/Makefile.am
+++ b/plugin/Makefile.am
@@ -39,12 +39,3 @@ dist_bin_SCRIPTS= \
nstor/nstor_lsmplugin \
ontap/ontap_lsmplugin \
targetd/targetd_lsmplugin
-
-if HAVE_PARAMIKO
-v7kdir = $(plugindir)/v7k
-v7k_PYTHON = \
- v7k/__init__.py \
- v7k/ibmv7k.py
-
-dist_bin_SCRIPTS += v7k/v7k_lsmplugin
-endif
diff --git a/plugin/v7k/__init__.py b/plugin/v7k/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/plugin/v7k/ibmv7k.py b/plugin/v7k/ibmv7k.py
deleted file mode 100644
index 7a0c2d6..0000000
--- a/plugin/v7k/ibmv7k.py
+++ /dev/null
@@ -1,364 +0,0 @@
-# Copyright (C) 2013 IBM Corporation
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-#
-# Author: Deepak C Shetty (***@linux.vnet.ibm.com)
-
-import paramiko
-
-from lsm import (Capabilities, ErrorNumber, IStorageAreaNetwork,
- LsmError, Pool, System, VERSION, Volume, uri_parse,
- search_property, AccessGroup)
-
-
-def handle_ssh_errors(method):
- def ssh_wrapper(*args, **kwargs):
- try:
- return method(*args, **kwargs)
- except paramiko.SSHException as sshe:
- raise LsmError(ErrorNumber.TRANSPORT_COMMUNICATION, str(sshe))
-
- return ssh_wrapper
-
-
-class V7kError(Exception):
- """
- Class represents a v7k cli bad return code
- """
-
- def __init__(self, errno, reason, *args, **kwargs):
- Exception.__init__(self, *args, **kwargs)
- self.errno = errno
- self.reason = reason
-
-
-# NOTE: v7k cli doc doesn't list the possible error codes per cli.
-# Thus do very generic and basic error handling for now.
-# Just pass the error msg & code returned by the array back to lsm.
-def handle_v7k_errors(method):
- def v7k_wrapper(*args, **kwargs):
- try:
- return method(*args, **kwargs)
- except V7kError as ve:
- msg = ve.reason + " (vendor error code= " + str(ve.errno) + ")"
- raise LsmError(ErrorNumber.PLUGIN_ERROR, msg)
-
- return v7k_wrapper
-
-
-# A lite weight sshclient
-class SSHClient():
-
- @handle_ssh_errors
- def __init__(self, hostname, login, passwd, conn_timeout=30):
- self.ssh = paramiko.SSHClient()
- self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
-
- try:
- self.ssh.connect(hostname, username=login, password=passwd,
- timeout=conn_timeout)
- except Exception as e:
- msg = "Error while connecting via ssh to host %s : %s" % \
- (hostname, e)
- raise paramiko.SSHException(msg)
-
- @handle_v7k_errors
- def execute(self, command, check_exit_code=True):
- stdin_strm, stdout_strm, stderr_strm = self.ssh.exec_command(command)
-
- stdin_strm.close()
-
- stdout_channel = stdout_strm.channel
- exit_code = stdout_channel.recv_exit_status()
- stdout_channel.close()
-
- stdout = stdout_strm.read()
- stdout_strm.close()
-
- stderr = stderr_strm.read()
- stderr_strm.close()
-
- if check_exit_code and exit_code != 0:
- error_list = stderr.split(' ', 1)
-
- if exit_code == 127:
- # command not found error
- errno = exit_code
- else:
- # other errors
- errno = error_list[0]
-
- reason = error_list[1]
-
- raise V7kError(errno, reason)
-
- return exit_code, stdout, stderr
-
- @handle_ssh_errors
- def close(self):
- self.ssh.close()
-
-
-# IBM V7000 storage lsm plugin
-
-# *** lsm -- IBM V7000 terminology mapping ***
-# volume -- v7k volume (aka vdisk)
-# initiator -- host
-# access group -- NA
-# NA -- I/O group
-# pool -- mdisk group
-# volume-child dep -- ~fcmap and other maps if any
-# job -- cli that can be invoked in async mode
-
-class IbmV7k(IStorageAreaNetwork):
-
- def __init__(self):
- self.sys_info = None
- self.ssh = None
- self.tmo = 0
- self.password = None
- self.up = None
-
- def _execute_command(self, ssh_cmd):
- exit_code, stdout, stderr = self.ssh.execute(ssh_cmd)
- return exit_code, stdout, stderr
-
- def _execute_command_and_parse_detailed(self, ssh_cmd):
- exit_code, stdout, stderr = self.ssh.execute(ssh_cmd)
-
- cmd_output = {}
- if not len(stdout.strip()):
- return cmd_output
-
- output_lines = stdout.split('\n')
- if not len(output_lines):
- return cmd_output
-
- for line in output_lines:
- name, foo, value = line.partition('!')
- if name is not None and len(name.strip()):
- cmd_output[name] = value
-
- return cmd_output
-
- def _execute_command_and_parse_concise(self, ssh_cmd):
- # This assume -nohdr is *not* present in ssh_cmd
- exit_code, stdout, stderr = self.ssh.execute(ssh_cmd)
-
- cmd_output = {}
- if not len(stdout.strip()):
- return cmd_output
-
- output_lines = stdout.split('\n')
- if not len(output_lines):
- return cmd_output
-
- header_line = output_lines[0]
- keylist = header_line.split('!')
-
- # For some reason, concise output gives one extra blank line at the end
- attrib_lines = output_lines[1:-1]
- lineindex = 0
-
- for attrib_line in attrib_lines:
- valuelist = attrib_line.split('!')
- attributes = {}
- valueindex = 0
- for key in keylist:
- attributes[key] = valuelist[valueindex]
- valueindex += 1
-
- cmd_output[lineindex] = attributes
- lineindex += 1
-
- return cmd_output
-
- def _get_system_info(self):
- ssh_cmd = 'lssystem -delim !'
- return self._execute_command_and_parse_detailed(ssh_cmd)
-
- def _get_pools(self):
- ssh_cmd = 'lsmdiskgrp -bytes -delim !'
- return self._execute_command_and_parse_concise(ssh_cmd)
-
- def _pool(self, p):
- return Pool(p['id'], p['name'], Pool.ELEMENT_TYPE_VOLUME,
- int(p['capacity']),
- int(p['free_capacity']), Pool.STATUS_UNKNOWN, '',
- self.sys_info.id)
-
- def _get_volumes(self):
- ssh_cmd = 'lsvdisk -bytes -delim !'
- return self._execute_command_and_parse_concise(ssh_cmd)
-
- def _get_volume(self, volume):
- ssh_cmd = 'lsvdisk -bytes -delim ! %s' % volume
- return self._execute_command_and_parse_detailed(ssh_cmd)
-
- def _volume(self, v):
- # v7k support 512 bytes/sec only, as the phy drive bs.
- # Its a bit complicated to reverse map v7k volume to
- # phy drive using the cli, so for now hardcode it as
- # thats the only supported bs at the drive level.
- bs = 512
-
- if v['status'] == 'online':
- vol_status = Volume.STATUS_OK
- elif v['status'] == 'offline':
- vol_status = Volume.STATUS_DORMANT
- else:
- vol_status = Volume.STATUS_ERR
-
- return Volume(v['id'], v['name'], v['vdisk_UID'], bs,
- (float(v['capacity']) / bs), vol_status,
- self.sys_info.id, v['mdisk_grp_id'])
-
- def _create_volume(self, pool, vol_name, size_bytes, prov):
- ssh_cmd = ('mkvdisk -name %s -mdiskgrp %s -iogrp 0 -size %s'
- ' -unit b') % (vol_name, pool, size_bytes)
-
- if prov == Volume.PROVISION_THIN:
- # Defaults for thinp
- rsize = 5
- warning = 0
- autoex = '-autoexpand'
-
- ssh_cmd += ' -rsize %d%% -warning %d %s' % \
- (rsize, warning, autoex)
-
- exit_code, stdout, stderr = self.ssh.execute(ssh_cmd)
-
- def _delete_volume(self, volume, force):
- # NOTE: volume can be id or name
- ssh_cmd = 'rmvdisk %s %s' % ('-force' if force else '', volume)
- exit_code, stdout, stderr = self.ssh.execute(ssh_cmd)
-
- def _get_initiators(self):
- ssh_cmd = 'lshost -delim !'
- return self._execute_command_and_parse_concise(ssh_cmd)
-
- def _get_initiator(self, init):
- ssh_cmd = 'lshost -delim ! %s' % init
- return self._execute_command_and_parse_detailed(ssh_cmd)
-
- def plugin_register(self, uri, password, timeout, flags=0):
- self.password = password
- self.tmo = timeout
- self.up = uri_parse(uri)
-
- self.ssh = SSHClient(self.up['host'], self.up['username'],
- self.password, self.tmo)
-
- si = self._get_system_info()
- self.sys_info = System(si['id'], si['name'], System.STATUS_OK, '')
-
- def time_out_set(self, ms, flags=0):
- self.tmo = ms
- self.ssh.close()
- self.ssh = SSHClient(self.up['host'], self.up['username'],
- self.password, self.tmo)
-
- def time_out_get(self, flags=0):
- return self.tmo
-
- def plugin_unregister(self, flags=0):
- self.ssh.close()
- return
-
- def job_status(self, job_id, flags=0):
- raise LsmError(ErrorNumber.NOT_IMPLEMENTED,
- "API not implemented at this time")
-
- def job_free(self, job_id, flags=0):
- raise LsmError(ErrorNumber.NOT_IMPLEMENTED,
- "API not implemented at this time")
-
- # NOTE: Add more capabilities as more cli's are supported
- def capabilities(self, system, flags=0):
- cap = Capabilities()
- cap.set(Capabilities.VOLUMES)
- cap.set(Capabilities.VOLUME_CREATE)
- cap.set(Capabilities.VOLUME_DELETE)
- cap.set(Capabilities.VOLUME_THIN)
- cap.set(Capabilities.ACCESS_GROUPS)
- return cap
-
- def plugin_info(self, flags=0):
- return "IBM V7000 lsm plugin", VERSION
-
- def pools(self, search_key=None, search_value=None, flags=0):
- gp = self._get_pools()
- return search_property(
- [self._pool(p) for p in gp.itervalues()],
- search_key, search_value)
-
- def systems(self, flags=0):
- return [self.sys_info]
-
- def volumes(self, search_key=None, search_value=None, flags=0):
- gv = self._get_volumes()
- return search_property(
- [self._volume(v) for v in gv.itervalues()],
- search_key, search_value)
-
- @staticmethod
- def _v7k_init_to_lsm_ag(v7k_init, system_id):
- lsm_init_id = None
- lsm_init_type = AccessGroup.INIT_TYPE_UNKNOWN
- if 'WWPN' in v7k_init:
- lsm_init_type = AccessGroup.INIT_TYPE_WWPN
- # TODO: Add support for > 1 wwpn case.
- # v7k cli is not parse friendly for > 1 case.
- lsm_init_id = v7k_init['WWPN']
- elif 'iscsi_name' in v7k_init:
- lsm_init_type = AccessGroup.INIT_TYPE_ISCSI_IQN
- # TODO: Add support for > 1 iscsiname case.
- # v7k cli is not parse friendly for > 1 case.
- lsm_init_id = v7k_init['iscsi_name']
- elif 'SAS_WWPN' in v7k_init:
- # TODO: Add support for > 1 SAS_WWPN case.
- # v7k cli is not parse friendly for > 1 case.
- lsm_init_type = AccessGroup.INIT_TYPE_SAS
- lsm_init_id = v7k_init['SAS_WWPN']
- else:
- # Since lshost worked, support it as other type.
- lsm_init_type = AccessGroup.INIT_TYPE_OTHER
- lsm_init_id = v7k_init['id']
-
- ag_name = 'N/A'
- if 'name' in v7k_init:
- ag_name = v7k_init['name']
-
- return AccessGroup(lsm_init_id, ag_name, [lsm_init_id], lsm_init_type,
- system_id)
-
- def access_groups(self, search_key=None, search_value=None, flags=0):
- lsm_ags = []
- v7k_inits_dict = self._get_initiators()
- for v7k_init_dict in v7k_inits_dict.itervalues():
- v7k_init = self._get_initiator(v7k_init_dict['id'])
- lsm_ags.extend(
- [IbmV7k._v7k_init_to_lsm_ag(v7k_init, self.sys_info.id)])
- return lsm_ags
-
- def volume_create(self, pool, volume_name, size_bytes, provisioning,
- flags=0):
- self._create_volume(pool.id, volume_name, size_bytes, provisioning)
- new_vol = self._get_volume(volume_name)
- return None, self._volume(new_vol)
-
- def volume_delete(self, volume, flags=0):
- # TODO: How to pass -force param ? For now, assume -force
- self._delete_volume(volume.id, force=True)
- return None
diff --git a/plugin/v7k/v7k_lsmplugin b/plugin/v7k/v7k_lsmplugin
deleted file mode 100755
index 35908a4..0000000
--- a/plugin/v7k/v7k_lsmplugin
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (C) 2013 IBM Corporation
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-#
-# Author: Deepak C Shetty (***@linux.vnet.ibm.com)
-import sys
-import syslog
-import traceback
-
-try:
- from lsm import PluginRunner
- from lsm.plugin.v7k.ibmv7k import IbmV7k
-
- if __name__ == '__main__':
- PluginRunner(IbmV7k, sys.argv).run()
-except Exception:
- #This should be quite rare, but when it does happen this is pretty
- #key in understanding what happened, especially when it happens when
- #running from the daemon.
- msg = str(traceback.format_exc())
- syslog.syslog(syslog.LOG_ERR, msg)
- sys.stderr.write(msg)
- sys.exit(1)
\ No newline at end of file
--
1.8.3.1
Tony Asleson
2014-08-04 23:47:10 UTC
Permalink
Got them all to apply clean, haven't done a complete code review.
However, I did see:

smis.py line 4906 & 4935, cim_init_mg_pros not defined
smis.py line 4916, out_init_id not defined

_data.py: Missing "from lsm import LsmError"

I will try to reproduce the failure you saw and see what I can find.

Thanks,
Tony
Post by Gris Ge
1. No hardware to test it on
2. Plugin is not feature complete
3. SMI-S plugin at this point should offer a better experience
for the user
We can certainly bring it back if needed.
---
configure.ac | 15 --
packaging/libstoragemgmt.spec.in | 41 -----
plugin/Makefile.am | 9 -
plugin/v7k/__init__.py | 0
plugin/v7k/ibmv7k.py | 364 ---------------------------------------
plugin/v7k/v7k_lsmplugin | 36 ----
6 files changed, 465 deletions(-)
delete mode 100644 plugin/v7k/__init__.py
delete mode 100644 plugin/v7k/ibmv7k.py
delete mode 100755 plugin/v7k/v7k_lsmplugin
diff --git a/configure.ac b/configure.ac
index b200078..cbf668b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -136,16 +136,6 @@ fi
AM_CONDITIONAL([BUILD_C_UNIT], [test "x${want_c_unit}" = "xyes"])
dnl ==========================================================================
-dnl Check to see if user wants to exclude code that depends on python-paramiko
-dnl ==========================================================================
-
-AC_ARG_WITH([paramiko],
- [AS_HELP_STRING([--without-paramiko], [Remove paramiko requirement and disables code which uses it, eg. IBM7K Plugin])],
- [], [with_paramiko="yes"])
-
-AM_CONDITIONAL([HAVE_PARAMIKO], [test "x${with_paramiko}" = "xyes"])
-
-dnl ==========================================================================
dnl Check for python as it is needed for the base cmd line function
dnl ==========================================================================
@@ -154,11 +144,6 @@ AC_PYTHON_MODULE([pywbem], [Required])
AC_PYTHON_MODULE([M2Crypto], [Required])
AC_PYTHON_MODULE([argparse], [Required])
-
-if test "x${with_paramiko}" = "xyes"; then
- AC_PYTHON_MODULE([paramiko], [Required])
-fi
-
dnl ==========================================================================
dnl Check for libmicrohttpd and json-c as it is needed for REST API daemon
dnl ==========================================================================
diff --git a/packaging/libstoragemgmt.spec.in b/packaging/libstoragemgmt.spec.in
index 2048da8..eaf9352 100644
--- a/packaging/libstoragemgmt.spec.in
+++ b/packaging/libstoragemgmt.spec.in
@@ -1,5 +1,4 @@
%bcond_without rest_api
-%bcond_without ibm_v7k
%if 0%{?rhel} <= 6
%global with_rest_api 0
@@ -9,22 +8,12 @@
# rpmbuild -ba libstoragemgmt.spec --with rest_api
%endif
-%if 0%{?rhel} >= 7
-%global with_ibm_v7k 0
-%endif
-
%global with_rest_api 1
}
%global with_rest_api 0
}
-%global with_ibm_v7k 1
-}
-%global with_ibm_v7k 0
-}
Name: libstoragemgmt
@@ -44,9 +33,6 @@ BuildRequires: gcc-c++
# These buggy extra conditional BuildRequires is for OBS only,
# https://bugzilla.novell.com/show_bug.cgi?id=864323
-%if 0%{?fedora} || 0%{?rhel} <= 6
-BuildRequires: python-paramiko
-%endif
%if 0%{?fedora} || 0%{?rhel} >= 7
BuildRequires: libmicrohttpd-devel json-c-devel
%endif
@@ -129,21 +115,6 @@ The %{name}-targetd-plugin package contains plug-in for targetd array
support.
-%if 0%{?with_ibm_v7k}
-%package ibm-v7k-plugin
-Summary: Files for IBM v7k array support for %{name}
-Group: System Environment/Libraries
-Requires: python-paramiko %{name}-python
-Requires: libstoragemgmt-python = %{version}-%{release}
-BuildRequires: python-paramiko
-BuildArch: noarch
-
-%description ibm-v7k-plugin
-The %{name}-ibm-v7k-plugin package contains plug-in for IBM v7k array
-support.
-%endif
-
-
%package nstor-plugin
Summary: Files for NexentaStor array support for %{name}
Group: System Environment/Libraries
@@ -183,9 +154,6 @@ the %{name}-rest package contains the http daemon for %{name} rest api.
#Tell the install program to preserve file date/timestamps
%configure \
-%if 0%{?with_ibm_v7k} != 1
- --without-paramiko \
-%endif
%if 0%{?with_rest_api} != 1
--without-rest-api \
%endif
@@ -362,15 +330,6 @@ fi
%{python_sitelib}/lsm/plugin/targetd/targetd.*
%{_bindir}/targetd_lsmplugin
-
-%if 0%{?with_ibm_v7k}
-%files ibm-v7k-plugin
-%defattr(-,root,root,-)
-%{python_sitelib}/lsm/plugin/v7k/__init__.*
-%{python_sitelib}/lsm/plugin/v7k/ibmv7k.*
-%{_bindir}/v7k_lsmplugin
-%endif
-
%files nstor-plugin
%defattr(-,root,root,-)
%{python_sitelib}/lsm/plugin/nstor/__init__.*
diff --git a/plugin/Makefile.am b/plugin/Makefile.am
index a8f43da..96a243a 100644
--- a/plugin/Makefile.am
+++ b/plugin/Makefile.am
@@ -39,12 +39,3 @@ dist_bin_SCRIPTS= \
nstor/nstor_lsmplugin \
ontap/ontap_lsmplugin \
targetd/targetd_lsmplugin
-
-if HAVE_PARAMIKO
-v7kdir = $(plugindir)/v7k
-v7k_PYTHON = \
- v7k/__init__.py \
- v7k/ibmv7k.py
-
-dist_bin_SCRIPTS += v7k/v7k_lsmplugin
-endif
diff --git a/plugin/v7k/__init__.py b/plugin/v7k/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/plugin/v7k/ibmv7k.py b/plugin/v7k/ibmv7k.py
deleted file mode 100644
index 7a0c2d6..0000000
--- a/plugin/v7k/ibmv7k.py
+++ /dev/null
@@ -1,364 +0,0 @@
-# Copyright (C) 2013 IBM Corporation
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-#
-
-import paramiko
-
-from lsm import (Capabilities, ErrorNumber, IStorageAreaNetwork,
- LsmError, Pool, System, VERSION, Volume, uri_parse,
- search_property, AccessGroup)
-
-
- return method(*args, **kwargs)
- raise LsmError(ErrorNumber.TRANSPORT_COMMUNICATION, str(sshe))
-
- return ssh_wrapper
-
-
- """
- Class represents a v7k cli bad return code
- """
-
- Exception.__init__(self, *args, **kwargs)
- self.errno = errno
- self.reason = reason
-
-
-# NOTE: v7k cli doc doesn't list the possible error codes per cli.
-# Thus do very generic and basic error handling for now.
-# Just pass the error msg & code returned by the array back to lsm.
- return method(*args, **kwargs)
- msg = ve.reason + " (vendor error code= " + str(ve.errno) + ")"
- raise LsmError(ErrorNumber.PLUGIN_ERROR, msg)
-
- return v7k_wrapper
-
-
-# A lite weight sshclient
-
- self.ssh = paramiko.SSHClient()
- self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
-
- self.ssh.connect(hostname, username=login, password=passwd,
- timeout=conn_timeout)
- msg = "Error while connecting via ssh to host %s : %s" % \
- (hostname, e)
- raise paramiko.SSHException(msg)
-
- stdin_strm, stdout_strm, stderr_strm = self.ssh.exec_command(command)
-
- stdin_strm.close()
-
- stdout_channel = stdout_strm.channel
- exit_code = stdout_channel.recv_exit_status()
- stdout_channel.close()
-
- stdout = stdout_strm.read()
- stdout_strm.close()
-
- stderr = stderr_strm.read()
- stderr_strm.close()
-
- error_list = stderr.split(' ', 1)
-
- # command not found error
- errno = exit_code
- # other errors
- errno = error_list[0]
-
- reason = error_list[1]
-
- raise V7kError(errno, reason)
-
- return exit_code, stdout, stderr
-
- self.ssh.close()
-
-
-# IBM V7000 storage lsm plugin
-
-# *** lsm -- IBM V7000 terminology mapping ***
-# volume -- v7k volume (aka vdisk)
-# initiator -- host
-# access group -- NA
-# NA -- I/O group
-# pool -- mdisk group
-# volume-child dep -- ~fcmap and other maps if any
-# job -- cli that can be invoked in async mode
-
-
- self.sys_info = None
- self.ssh = None
- self.tmo = 0
- self.password = None
- self.up = None
-
- exit_code, stdout, stderr = self.ssh.execute(ssh_cmd)
- return exit_code, stdout, stderr
-
- exit_code, stdout, stderr = self.ssh.execute(ssh_cmd)
-
- cmd_output = {}
- return cmd_output
-
- output_lines = stdout.split('\n')
- return cmd_output
-
- name, foo, value = line.partition('!')
- cmd_output[name] = value
-
- return cmd_output
-
- # This assume -nohdr is *not* present in ssh_cmd
- exit_code, stdout, stderr = self.ssh.execute(ssh_cmd)
-
- cmd_output = {}
- return cmd_output
-
- output_lines = stdout.split('\n')
- return cmd_output
-
- header_line = output_lines[0]
- keylist = header_line.split('!')
-
- # For some reason, concise output gives one extra blank line at the end
- attrib_lines = output_lines[1:-1]
- lineindex = 0
-
- valuelist = attrib_line.split('!')
- attributes = {}
- valueindex = 0
- attributes[key] = valuelist[valueindex]
- valueindex += 1
-
- cmd_output[lineindex] = attributes
- lineindex += 1
-
- return cmd_output
-
- ssh_cmd = 'lssystem -delim !'
- return self._execute_command_and_parse_detailed(ssh_cmd)
-
- ssh_cmd = 'lsmdiskgrp -bytes -delim !'
- return self._execute_command_and_parse_concise(ssh_cmd)
-
- return Pool(p['id'], p['name'], Pool.ELEMENT_TYPE_VOLUME,
- int(p['capacity']),
- int(p['free_capacity']), Pool.STATUS_UNKNOWN, '',
- self.sys_info.id)
-
- ssh_cmd = 'lsvdisk -bytes -delim !'
- return self._execute_command_and_parse_concise(ssh_cmd)
-
- ssh_cmd = 'lsvdisk -bytes -delim ! %s' % volume
- return self._execute_command_and_parse_detailed(ssh_cmd)
-
- # v7k support 512 bytes/sec only, as the phy drive bs.
- # Its a bit complicated to reverse map v7k volume to
- # phy drive using the cli, so for now hardcode it as
- # thats the only supported bs at the drive level.
- bs = 512
-
- vol_status = Volume.STATUS_OK
- vol_status = Volume.STATUS_DORMANT
- vol_status = Volume.STATUS_ERR
-
- return Volume(v['id'], v['name'], v['vdisk_UID'], bs,
- (float(v['capacity']) / bs), vol_status,
- self.sys_info.id, v['mdisk_grp_id'])
-
- ssh_cmd = ('mkvdisk -name %s -mdiskgrp %s -iogrp 0 -size %s'
- ' -unit b') % (vol_name, pool, size_bytes)
-
- # Defaults for thinp
- rsize = 5
- warning = 0
- autoex = '-autoexpand'
-
- ssh_cmd += ' -rsize %d%% -warning %d %s' % \
- (rsize, warning, autoex)
-
- exit_code, stdout, stderr = self.ssh.execute(ssh_cmd)
-
- # NOTE: volume can be id or name
- ssh_cmd = 'rmvdisk %s %s' % ('-force' if force else '', volume)
- exit_code, stdout, stderr = self.ssh.execute(ssh_cmd)
-
- ssh_cmd = 'lshost -delim !'
- return self._execute_command_and_parse_concise(ssh_cmd)
-
- ssh_cmd = 'lshost -delim ! %s' % init
- return self._execute_command_and_parse_detailed(ssh_cmd)
-
- self.password = password
- self.tmo = timeout
- self.up = uri_parse(uri)
-
- self.ssh = SSHClient(self.up['host'], self.up['username'],
- self.password, self.tmo)
-
- si = self._get_system_info()
- self.sys_info = System(si['id'], si['name'], System.STATUS_OK, '')
-
- self.tmo = ms
- self.ssh.close()
- self.ssh = SSHClient(self.up['host'], self.up['username'],
- self.password, self.tmo)
-
- return self.tmo
-
- self.ssh.close()
- return
-
- raise LsmError(ErrorNumber.NOT_IMPLEMENTED,
- "API not implemented at this time")
-
- raise LsmError(ErrorNumber.NOT_IMPLEMENTED,
- "API not implemented at this time")
-
- # NOTE: Add more capabilities as more cli's are supported
- cap = Capabilities()
- cap.set(Capabilities.VOLUMES)
- cap.set(Capabilities.VOLUME_CREATE)
- cap.set(Capabilities.VOLUME_DELETE)
- cap.set(Capabilities.VOLUME_THIN)
- cap.set(Capabilities.ACCESS_GROUPS)
- return cap
-
- return "IBM V7000 lsm plugin", VERSION
-
- gp = self._get_pools()
- return search_property(
- [self._pool(p) for p in gp.itervalues()],
- search_key, search_value)
-
- return [self.sys_info]
-
- gv = self._get_volumes()
- return search_property(
- [self._volume(v) for v in gv.itervalues()],
- search_key, search_value)
-
- lsm_init_id = None
- lsm_init_type = AccessGroup.INIT_TYPE_UNKNOWN
- lsm_init_type = AccessGroup.INIT_TYPE_WWPN
- # TODO: Add support for > 1 wwpn case.
- # v7k cli is not parse friendly for > 1 case.
- lsm_init_id = v7k_init['WWPN']
- lsm_init_type = AccessGroup.INIT_TYPE_ISCSI_IQN
- # TODO: Add support for > 1 iscsiname case.
- # v7k cli is not parse friendly for > 1 case.
- lsm_init_id = v7k_init['iscsi_name']
- # TODO: Add support for > 1 SAS_WWPN case.
- # v7k cli is not parse friendly for > 1 case.
- lsm_init_type = AccessGroup.INIT_TYPE_SAS
- lsm_init_id = v7k_init['SAS_WWPN']
- # Since lshost worked, support it as other type.
- lsm_init_type = AccessGroup.INIT_TYPE_OTHER
- lsm_init_id = v7k_init['id']
-
- ag_name = 'N/A'
- ag_name = v7k_init['name']
-
- return AccessGroup(lsm_init_id, ag_name, [lsm_init_id], lsm_init_type,
- system_id)
-
- lsm_ags = []
- v7k_inits_dict = self._get_initiators()
- v7k_init = self._get_initiator(v7k_init_dict['id'])
- lsm_ags.extend(
- [IbmV7k._v7k_init_to_lsm_ag(v7k_init, self.sys_info.id)])
- return lsm_ags
-
- def volume_create(self, pool, volume_name, size_bytes, provisioning,
- self._create_volume(pool.id, volume_name, size_bytes, provisioning)
- new_vol = self._get_volume(volume_name)
- return None, self._volume(new_vol)
-
- # TODO: How to pass -force param ? For now, assume -force
- self._delete_volume(volume.id, force=True)
- return None
diff --git a/plugin/v7k/v7k_lsmplugin b/plugin/v7k/v7k_lsmplugin
deleted file mode 100755
index 35908a4..0000000
--- a/plugin/v7k/v7k_lsmplugin
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (C) 2013 IBM Corporation
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-#
-import sys
-import syslog
-import traceback
-
- from lsm import PluginRunner
- from lsm.plugin.v7k.ibmv7k import IbmV7k
-
- PluginRunner(IbmV7k, sys.argv).run()
- #This should be quite rare, but when it does happen this is pretty
- #key in understanding what happened, especially when it happens when
- #running from the daemon.
- msg = str(traceback.format_exc())
- syslog.syslog(syslog.LOG_ERR, msg)
- sys.stderr.write(msg)
- sys.exit(1)
\ No newline at end of file
Gris Ge
2014-08-05 02:48:42 UTC
Permalink
I combined tony's patches with my V2 patches.

This patch set contains:
1. Fix bugs found by OBS compile.
2. Change rpm spec and etc to support OBS build.
3. Access Group WWPN form.
4. Clean up AccessGroup.
5. Fix bugs of SMI-S plugin about access group.

Tested by 'make check' by OBS:
https://build.opensuse.org/project/monitor/home:cathay4t:libstoragemgmt-test

Changes in V2:
1. _data.py: Missing "from lsm import LsmError"
2. smis.py line 4906 & 4935, cim_init_mg_pros not defined
smis.py line 4916, out_init_id not defined
3. Tested access group create, add init, del init on EMC VMAX.

Gris Ge (11):
Remove v7k plugin
rpm spec: fix for OBS build
test: allowing runtest to show log of lsmd
cmdline.py: Check before reference
C API V2: Simplify lsm_capability_set_n
test: empty expected_absent capabilities check
lsmcli: use python-ordereddict for python <= 2.6
Remove INIT_TYPE_WWNN and etc unused initiator type
V2: Python API: standardize the WWPN
C API: Rename LSM_ERR_INVALID_IQN to LSM_ERR_INVALID_INIT
lsmcli: Remove --init-type argument
ontap plugin: Rename INVALID_IQN to INVALID_INIT
SMI-S plugin: standardize the WWPN
V2: SMI-S plugin: Fix access group bugs

Tony Asleson(3):
Remove v7k plugin
cmdline.py: Check before reference
C API: Simplify lsm_capability_set_n

c_binding/include/libstoragemgmt/libstoragemgmt.h | 4 +-
.../libstoragemgmt/libstoragemgmt_capabilities.h | 2 +
.../include/libstoragemgmt/libstoragemgmt_error.h | 3 +-
.../libstoragemgmt/libstoragemgmt_plug_interface.h | 25 +-
.../include/libstoragemgmt/libstoragemgmt_types.h | 15 +-
c_binding/lsm_datatypes.cpp | 28 +-
c_binding/lsm_datatypes.hpp | 12 -
c_binding/lsm_mgmt.cpp | 6 +-
c_binding/lsm_plugin_ipc.cpp | 6 +-
configure.ac | 15 -
daemon/lsm_daemon.c | 1 +
doc/man/lsmcli.1.in | 12 +-
packaging/libstoragemgmt.spec.in | 88 ++---
plugin/Makefile.am | 9 -
plugin/ontap/ontap.py | 2 +-
plugin/sim/simarray.py | 9 +-
plugin/simc/simc_lsmplugin.c | 11 +-
plugin/smispy/smis.py | 225 +++++++------
plugin/v7k/__init__.py | 0
plugin/v7k/ibmv7k.py | 364 ---------------------
plugin/v7k/v7k_lsmplugin | 36 --
python_binding/lsm/_client.py | 4 +
python_binding/lsm/_common.py | 2 +-
python_binding/lsm/_data.py | 99 +++++-
test/cmdtest.py | 7 +-
test/runtests.sh | 73 +++--
test/tester.c | 86 ++---
tools/lsmcli/cmdline.py | 61 ++--
tools/lsmcli/data_display.py | 11 +-
29 files changed, 391 insertions(+), 825 deletions(-)
delete mode 100644 plugin/v7k/__init__.py
delete mode 100644 plugin/v7k/ibmv7k.py
delete mode 100755 plugin/v7k/v7k_lsmplugin
--
1.8.3.1
Gris Ge
2014-08-05 02:48:43 UTC
Permalink
This plugin is being removed for the following reasons:

1. No hardware to test it on
2. Plugin is not feature complete
3. SMI-S plugin at this point should offer a better experience
for the user

We can certainly bring it back if needed.

Signed-off-by: Tony Asleson <***@redhat.com>
Signed-off-by: Gris Ge <***@redhat.com>
---
configure.ac | 15 --
packaging/libstoragemgmt.spec.in | 41 -----
plugin/Makefile.am | 9 -
plugin/v7k/__init__.py | 0
plugin/v7k/ibmv7k.py | 364 ---------------------------------------
plugin/v7k/v7k_lsmplugin | 36 ----
6 files changed, 465 deletions(-)
delete mode 100644 plugin/v7k/__init__.py
delete mode 100644 plugin/v7k/ibmv7k.py
delete mode 100755 plugin/v7k/v7k_lsmplugin

diff --git a/configure.ac b/configure.ac
index b200078..cbf668b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -136,16 +136,6 @@ fi
AM_CONDITIONAL([BUILD_C_UNIT], [test "x${want_c_unit}" = "xyes"])

dnl ==========================================================================
-dnl Check to see if user wants to exclude code that depends on python-paramiko
-dnl ==========================================================================
-
-AC_ARG_WITH([paramiko],
- [AS_HELP_STRING([--without-paramiko], [Remove paramiko requirement and disables code which uses it, eg. IBM7K Plugin])],
- [], [with_paramiko="yes"])
-
-AM_CONDITIONAL([HAVE_PARAMIKO], [test "x${with_paramiko}" = "xyes"])
-
-dnl ==========================================================================
dnl Check for python as it is needed for the base cmd line function
dnl ==========================================================================

@@ -154,11 +144,6 @@ AC_PYTHON_MODULE([pywbem], [Required])
AC_PYTHON_MODULE([M2Crypto], [Required])
AC_PYTHON_MODULE([argparse], [Required])

-
-if test "x${with_paramiko}" = "xyes"; then
- AC_PYTHON_MODULE([paramiko], [Required])
-fi
-
dnl ==========================================================================
dnl Check for libmicrohttpd and json-c as it is needed for REST API daemon
dnl ==========================================================================
diff --git a/packaging/libstoragemgmt.spec.in b/packaging/libstoragemgmt.spec.in
index 2048da8..eaf9352 100644
--- a/packaging/libstoragemgmt.spec.in
+++ b/packaging/libstoragemgmt.spec.in
@@ -1,5 +1,4 @@
%bcond_without rest_api
-%bcond_without ibm_v7k

%if 0%{?rhel} <= 6
%global with_rest_api 0
@@ -9,22 +8,12 @@
# rpmbuild -ba libstoragemgmt.spec --with rest_api
%endif

-%if 0%{?rhel} >= 7
-%global with_ibm_v7k 0
-%endif
-
%{?_with_rest_api:
%global with_rest_api 1
}
%{?_without_rest_api:
%global with_rest_api 0
}
-%{?_with_ibm_v7k:
-%global with_ibm_v7k 1
-}
-%{?_without_ibm_v7k:
-%global with_ibm_v7k 0
-}

Name: libstoragemgmt
Version: @VERSION@
@@ -44,9 +33,6 @@ BuildRequires: gcc-c++
# These buggy extra conditional BuildRequires is for OBS only,
# Please refer to OBS bug:
# https://bugzilla.novell.com/show_bug.cgi?id=864323
-%if 0%{?fedora} || 0%{?rhel} <= 6
-BuildRequires: python-paramiko
-%endif
%if 0%{?fedora} || 0%{?rhel} >= 7
BuildRequires: libmicrohttpd-devel json-c-devel
%endif
@@ -129,21 +115,6 @@ The %{name}-targetd-plugin package contains plug-in for targetd array
support.


-%if 0%{?with_ibm_v7k}
-%package ibm-v7k-plugin
-Summary: Files for IBM v7k array support for %{name}
-Group: System Environment/Libraries
-Requires: python-paramiko %{name}-python
-Requires: libstoragemgmt-python = %{version}-%{release}
-BuildRequires: python-paramiko
-BuildArch: noarch
-
-%description ibm-v7k-plugin
-The %{name}-ibm-v7k-plugin package contains plug-in for IBM v7k array
-support.
-%endif
-
-
%package nstor-plugin
Summary: Files for NexentaStor array support for %{name}
Group: System Environment/Libraries
@@ -183,9 +154,6 @@ the %{name}-rest package contains the http daemon for %{name} rest api.

#Tell the install program to preserve file date/timestamps
%configure \
-%if 0%{?with_ibm_v7k} != 1
- --without-paramiko \
-%endif
%if 0%{?with_rest_api} != 1
--without-rest-api \
%endif
@@ -362,15 +330,6 @@ fi
%{python_sitelib}/lsm/plugin/targetd/targetd.*
%{_bindir}/targetd_lsmplugin

-
-%if 0%{?with_ibm_v7k}
-%files ibm-v7k-plugin
-%defattr(-,root,root,-)
-%{python_sitelib}/lsm/plugin/v7k/__init__.*
-%{python_sitelib}/lsm/plugin/v7k/ibmv7k.*
-%{_bindir}/v7k_lsmplugin
-%endif
-
%files nstor-plugin
%defattr(-,root,root,-)
%{python_sitelib}/lsm/plugin/nstor/__init__.*
diff --git a/plugin/Makefile.am b/plugin/Makefile.am
index a8f43da..96a243a 100644
--- a/plugin/Makefile.am
+++ b/plugin/Makefile.am
@@ -39,12 +39,3 @@ dist_bin_SCRIPTS= \
nstor/nstor_lsmplugin \
ontap/ontap_lsmplugin \
targetd/targetd_lsmplugin
-
-if HAVE_PARAMIKO
-v7kdir = $(plugindir)/v7k
-v7k_PYTHON = \
- v7k/__init__.py \
- v7k/ibmv7k.py
-
-dist_bin_SCRIPTS += v7k/v7k_lsmplugin
-endif
diff --git a/plugin/v7k/__init__.py b/plugin/v7k/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/plugin/v7k/ibmv7k.py b/plugin/v7k/ibmv7k.py
deleted file mode 100644
index 7a0c2d6..0000000
--- a/plugin/v7k/ibmv7k.py
+++ /dev/null
@@ -1,364 +0,0 @@
-# Copyright (C) 2013 IBM Corporation
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-#
-# Author: Deepak C Shetty (***@linux.vnet.ibm.com)
-
-import paramiko
-
-from lsm import (Capabilities, ErrorNumber, IStorageAreaNetwork,
- LsmError, Pool, System, VERSION, Volume, uri_parse,
- search_property, AccessGroup)
-
-
-def handle_ssh_errors(method):
- def ssh_wrapper(*args, **kwargs):
- try:
- return method(*args, **kwargs)
- except paramiko.SSHException as sshe:
- raise LsmError(ErrorNumber.TRANSPORT_COMMUNICATION, str(sshe))
-
- return ssh_wrapper
-
-
-class V7kError(Exception):
- """
- Class represents a v7k cli bad return code
- """
-
- def __init__(self, errno, reason, *args, **kwargs):
- Exception.__init__(self, *args, **kwargs)
- self.errno = errno
- self.reason = reason
-
-
-# NOTE: v7k cli doc doesn't list the possible error codes per cli.
-# Thus do very generic and basic error handling for now.
-# Just pass the error msg & code returned by the array back to lsm.
-def handle_v7k_errors(method):
- def v7k_wrapper(*args, **kwargs):
- try:
- return method(*args, **kwargs)
- except V7kError as ve:
- msg = ve.reason + " (vendor error code= " + str(ve.errno) + ")"
- raise LsmError(ErrorNumber.PLUGIN_ERROR, msg)
-
- return v7k_wrapper
-
-
-# A lite weight sshclient
-class SSHClient():
-
- @handle_ssh_errors
- def __init__(self, hostname, login, passwd, conn_timeout=30):
- self.ssh = paramiko.SSHClient()
- self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
-
- try:
- self.ssh.connect(hostname, username=login, password=passwd,
- timeout=conn_timeout)
- except Exception as e:
- msg = "Error while connecting via ssh to host %s : %s" % \
- (hostname, e)
- raise paramiko.SSHException(msg)
-
- @handle_v7k_errors
- def execute(self, command, check_exit_code=True):
- stdin_strm, stdout_strm, stderr_strm = self.ssh.exec_command(command)
-
- stdin_strm.close()
-
- stdout_channel = stdout_strm.channel
- exit_code = stdout_channel.recv_exit_status()
- stdout_channel.close()
-
- stdout = stdout_strm.read()
- stdout_strm.close()
-
- stderr = stderr_strm.read()
- stderr_strm.close()
-
- if check_exit_code and exit_code != 0:
- error_list = stderr.split(' ', 1)
-
- if exit_code == 127:
- # command not found error
- errno = exit_code
- else:
- # other errors
- errno = error_list[0]
-
- reason = error_list[1]
-
- raise V7kError(errno, reason)
-
- return exit_code, stdout, stderr
-
- @handle_ssh_errors
- def close(self):
- self.ssh.close()
-
-
-# IBM V7000 storage lsm plugin
-
-# *** lsm -- IBM V7000 terminology mapping ***
-# volume -- v7k volume (aka vdisk)
-# initiator -- host
-# access group -- NA
-# NA -- I/O group
-# pool -- mdisk group
-# volume-child dep -- ~fcmap and other maps if any
-# job -- cli that can be invoked in async mode
-
-class IbmV7k(IStorageAreaNetwork):
-
- def __init__(self):
- self.sys_info = None
- self.ssh = None
- self.tmo = 0
- self.password = None
- self.up = None
-
- def _execute_command(self, ssh_cmd):
- exit_code, stdout, stderr = self.ssh.execute(ssh_cmd)
- return exit_code, stdout, stderr
-
- def _execute_command_and_parse_detailed(self, ssh_cmd):
- exit_code, stdout, stderr = self.ssh.execute(ssh_cmd)
-
- cmd_output = {}
- if not len(stdout.strip()):
- return cmd_output
-
- output_lines = stdout.split('\n')
- if not len(output_lines):
- return cmd_output
-
- for line in output_lines:
- name, foo, value = line.partition('!')
- if name is not None and len(name.strip()):
- cmd_output[name] = value
-
- return cmd_output
-
- def _execute_command_and_parse_concise(self, ssh_cmd):
- # This assume -nohdr is *not* present in ssh_cmd
- exit_code, stdout, stderr = self.ssh.execute(ssh_cmd)
-
- cmd_output = {}
- if not len(stdout.strip()):
- return cmd_output
-
- output_lines = stdout.split('\n')
- if not len(output_lines):
- return cmd_output
-
- header_line = output_lines[0]
- keylist = header_line.split('!')
-
- # For some reason, concise output gives one extra blank line at the end
- attrib_lines = output_lines[1:-1]
- lineindex = 0
-
- for attrib_line in attrib_lines:
- valuelist = attrib_line.split('!')
- attributes = {}
- valueindex = 0
- for key in keylist:
- attributes[key] = valuelist[valueindex]
- valueindex += 1
-
- cmd_output[lineindex] = attributes
- lineindex += 1
-
- return cmd_output
-
- def _get_system_info(self):
- ssh_cmd = 'lssystem -delim !'
- return self._execute_command_and_parse_detailed(ssh_cmd)
-
- def _get_pools(self):
- ssh_cmd = 'lsmdiskgrp -bytes -delim !'
- return self._execute_command_and_parse_concise(ssh_cmd)
-
- def _pool(self, p):
- return Pool(p['id'], p['name'], Pool.ELEMENT_TYPE_VOLUME,
- int(p['capacity']),
- int(p['free_capacity']), Pool.STATUS_UNKNOWN, '',
- self.sys_info.id)
-
- def _get_volumes(self):
- ssh_cmd = 'lsvdisk -bytes -delim !'
- return self._execute_command_and_parse_concise(ssh_cmd)
-
- def _get_volume(self, volume):
- ssh_cmd = 'lsvdisk -bytes -delim ! %s' % volume
- return self._execute_command_and_parse_detailed(ssh_cmd)
-
- def _volume(self, v):
- # v7k support 512 bytes/sec only, as the phy drive bs.
- # Its a bit complicated to reverse map v7k volume to
- # phy drive using the cli, so for now hardcode it as
- # thats the only supported bs at the drive level.
- bs = 512
-
- if v['status'] == 'online':
- vol_status = Volume.STATUS_OK
- elif v['status'] == 'offline':
- vol_status = Volume.STATUS_DORMANT
- else:
- vol_status = Volume.STATUS_ERR
-
- return Volume(v['id'], v['name'], v['vdisk_UID'], bs,
- (float(v['capacity']) / bs), vol_status,
- self.sys_info.id, v['mdisk_grp_id'])
-
- def _create_volume(self, pool, vol_name, size_bytes, prov):
- ssh_cmd = ('mkvdisk -name %s -mdiskgrp %s -iogrp 0 -size %s'
- ' -unit b') % (vol_name, pool, size_bytes)
-
- if prov == Volume.PROVISION_THIN:
- # Defaults for thinp
- rsize = 5
- warning = 0
- autoex = '-autoexpand'
-
- ssh_cmd += ' -rsize %d%% -warning %d %s' % \
- (rsize, warning, autoex)
-
- exit_code, stdout, stderr = self.ssh.execute(ssh_cmd)
-
- def _delete_volume(self, volume, force):
- # NOTE: volume can be id or name
- ssh_cmd = 'rmvdisk %s %s' % ('-force' if force else '', volume)
- exit_code, stdout, stderr = self.ssh.execute(ssh_cmd)
-
- def _get_initiators(self):
- ssh_cmd = 'lshost -delim !'
- return self._execute_command_and_parse_concise(ssh_cmd)
-
- def _get_initiator(self, init):
- ssh_cmd = 'lshost -delim ! %s' % init
- return self._execute_command_and_parse_detailed(ssh_cmd)
-
- def plugin_register(self, uri, password, timeout, flags=0):
- self.password = password
- self.tmo = timeout
- self.up = uri_parse(uri)
-
- self.ssh = SSHClient(self.up['host'], self.up['username'],
- self.password, self.tmo)
-
- si = self._get_system_info()
- self.sys_info = System(si['id'], si['name'], System.STATUS_OK, '')
-
- def time_out_set(self, ms, flags=0):
- self.tmo = ms
- self.ssh.close()
- self.ssh = SSHClient(self.up['host'], self.up['username'],
- self.password, self.tmo)
-
- def time_out_get(self, flags=0):
- return self.tmo
-
- def plugin_unregister(self, flags=0):
- self.ssh.close()
- return
-
- def job_status(self, job_id, flags=0):
- raise LsmError(ErrorNumber.NOT_IMPLEMENTED,
- "API not implemented at this time")
-
- def job_free(self, job_id, flags=0):
- raise LsmError(ErrorNumber.NOT_IMPLEMENTED,
- "API not implemented at this time")
-
- # NOTE: Add more capabilities as more cli's are supported
- def capabilities(self, system, flags=0):
- cap = Capabilities()
- cap.set(Capabilities.VOLUMES)
- cap.set(Capabilities.VOLUME_CREATE)
- cap.set(Capabilities.VOLUME_DELETE)
- cap.set(Capabilities.VOLUME_THIN)
- cap.set(Capabilities.ACCESS_GROUPS)
- return cap
-
- def plugin_info(self, flags=0):
- return "IBM V7000 lsm plugin", VERSION
-
- def pools(self, search_key=None, search_value=None, flags=0):
- gp = self._get_pools()
- return search_property(
- [self._pool(p) for p in gp.itervalues()],
- search_key, search_value)
-
- def systems(self, flags=0):
- return [self.sys_info]
-
- def volumes(self, search_key=None, search_value=None, flags=0):
- gv = self._get_volumes()
- return search_property(
- [self._volume(v) for v in gv.itervalues()],
- search_key, search_value)
-
- @staticmethod
- def _v7k_init_to_lsm_ag(v7k_init, system_id):
- lsm_init_id = None
- lsm_init_type = AccessGroup.INIT_TYPE_UNKNOWN
- if 'WWPN' in v7k_init:
- lsm_init_type = AccessGroup.INIT_TYPE_WWPN
- # TODO: Add support for > 1 wwpn case.
- # v7k cli is not parse friendly for > 1 case.
- lsm_init_id = v7k_init['WWPN']
- elif 'iscsi_name' in v7k_init:
- lsm_init_type = AccessGroup.INIT_TYPE_ISCSI_IQN
- # TODO: Add support for > 1 iscsiname case.
- # v7k cli is not parse friendly for > 1 case.
- lsm_init_id = v7k_init['iscsi_name']
- elif 'SAS_WWPN' in v7k_init:
- # TODO: Add support for > 1 SAS_WWPN case.
- # v7k cli is not parse friendly for > 1 case.
- lsm_init_type = AccessGroup.INIT_TYPE_SAS
- lsm_init_id = v7k_init['SAS_WWPN']
- else:
- # Since lshost worked, support it as other type.
- lsm_init_type = AccessGroup.INIT_TYPE_OTHER
- lsm_init_id = v7k_init['id']
-
- ag_name = 'N/A'
- if 'name' in v7k_init:
- ag_name = v7k_init['name']
-
- return AccessGroup(lsm_init_id, ag_name, [lsm_init_id], lsm_init_type,
- system_id)
-
- def access_groups(self, search_key=None, search_value=None, flags=0):
- lsm_ags = []
- v7k_inits_dict = self._get_initiators()
- for v7k_init_dict in v7k_inits_dict.itervalues():
- v7k_init = self._get_initiator(v7k_init_dict['id'])
- lsm_ags.extend(
- [IbmV7k._v7k_init_to_lsm_ag(v7k_init, self.sys_info.id)])
- return lsm_ags
-
- def volume_create(self, pool, volume_name, size_bytes, provisioning,
- flags=0):
- self._create_volume(pool.id, volume_name, size_bytes, provisioning)
- new_vol = self._get_volume(volume_name)
- return None, self._volume(new_vol)
-
- def volume_delete(self, volume, flags=0):
- # TODO: How to pass -force param ? For now, assume -force
- self._delete_volume(volume.id, force=True)
- return None
diff --git a/plugin/v7k/v7k_lsmplugin b/plugin/v7k/v7k_lsmplugin
deleted file mode 100755
index 35908a4..0000000
--- a/plugin/v7k/v7k_lsmplugin
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (C) 2013 IBM Corporation
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-#
-# Author: Deepak C Shetty (***@linux.vnet.ibm.com)
-import sys
-import syslog
-import traceback
-
-try:
- from lsm import PluginRunner
- from lsm.plugin.v7k.ibmv7k import IbmV7k
-
- if __name__ == '__main__':
- PluginRunner(IbmV7k, sys.argv).run()
-except Exception:
- #This should be quite rare, but when it does happen this is pretty
- #key in understanding what happened, especially when it happens when
- #running from the daemon.
- msg = str(traceback.format_exc())
- syslog.syslog(syslog.LOG_ERR, msg)
- sys.stderr.write(msg)
- sys.exit(1)
\ No newline at end of file
--
1.8.3.1
Gris Ge
2014-08-05 02:48:45 UTC
Permalink
1. Plush STDOUT on every logger call of lsmd daemon.
2. Change lsmd to systemd mode and save output to a tmp log file.
Useful to deubg daemon error and plugin error in OBS build where no way
to check syslog.
3. Fix a trivial typo:
export CK_export CK_FORK=no
4. Removed the 'tab' from runtest.sh which is mixing 'tab' and 'space'

Signed-off-by: Gris Ge <***@redhat.com>
---
daemon/lsm_daemon.c | 1 +
test/runtests.sh | 73 ++++++++++++++++++++++++++++-------------------------
2 files changed, 40 insertions(+), 34 deletions(-)

diff --git a/daemon/lsm_daemon.c b/daemon/lsm_daemon.c
index 923b66e..80e0064 100644
--- a/daemon/lsm_daemon.c
+++ b/daemon/lsm_daemon.c
@@ -107,6 +107,7 @@ void logger(int severity, const char *fmt, ...)
syslog(LOG_ERR, "%s", buf);
} else {
fprintf(stdout, "%s", buf);
+ fflush(stdout);
}

if( LOG_ERR == severity) {
diff --git a/test/runtests.sh b/test/runtests.sh
index 8faebb4..93b584e 100755
--- a/test/runtests.sh
+++ b/test/runtests.sh
@@ -23,7 +23,7 @@
export G_SLICE=always-malloc
export G_DEBUG=gc-friendly
export CK_DEFAULT_TIMEOUT=600
-export CK_export CK_FORK=no
+export CK_FORK=no

rundir=$RANDOM
base=/tmp/$rundir
@@ -33,35 +33,38 @@ LSMD_PID=65535
export LSM_TEST_RUNDIR=$rundir
export LSM_UDS_PATH=$base/lsm/ipc/

+LSMD_TMP_LOG_FILE="$base/lsmd.log"
+
cleanup() {
- #Clean up the daemon if it is running
- if [ $LSMD_PID -ne 65535 ]
- then
- kill -s INT $LSMD_PID
- fi
-
- if [ -e $LSM_UDS_PATH ]
- then
- rm -rf $base
- fi
-
- if [ -e $rootdir/_build ]
- then
- rm $lsm_py_folder/lsm/plugin
- rm $lsm_py_folder/lsm/lsmcli
- chmod -w $lsm_py_folder/lsm
- fi
+ #Clean up the daemon if it is running
+ if [ $LSMD_PID -ne 65535 ]
+ then
+ kill -s KILL $LSMD_PID
+ fi
+
+ cat $LSMD_TMP_LOG_FILE
+ if [ -e $LSM_UDS_PATH ]
+ then
+ rm -rf $base
+ fi
+
+ if [ -e $rootdir/_build ]
+ then
+ rm $lsm_py_folder/lsm/plugin
+ rm $lsm_py_folder/lsm/lsmcli
+ chmod -w $lsm_py_folder/lsm
+ fi
}

good() {
- echo "executing: $1"
- eval $1
- ec=$?
- if [ $ec -ne 0 ]; then
- echo "Fail exit[$ec]: $1"
- cleanup
- exit 1
- fi
+ echo "executing: $1"
+ eval $1
+ ec=$?
+ if [ $ec -ne 0 ]; then
+ echo "Fail exit[$ec]: $1"
+ cleanup
+ exit 1
+ fi
}

# Add a signal handler to clean-up
@@ -85,10 +88,10 @@ lsmcli_py_folder=$rootdir/tools/lsmcli

if [ -e $rootdir/_build ]
then
- c_unit=$rootdir/_build/test/tester
- LSMD_DAEMON=$rootdir/_build/daemon/lsmd
- shared_libs=$rootdir/_build/c_binding/.libs/
- bin_plugin=$rootdir/_build/plugin/simc/.libs/
+ c_unit=$rootdir/_build/test/tester
+ LSMD_DAEMON=$rootdir/_build/daemon/lsmd
+ shared_libs=$rootdir/_build/c_binding/.libs/
+ bin_plugin=$rootdir/_build/plugin/simc/.libs/
# In distcheck, all folder is read only(except _build and _inst).
# which prevent us from linking plugin and lsmcli into python/lsm folder.
chmod +w $rootdir/python_binding/lsm
@@ -133,17 +136,19 @@ good "find $rootdir/ \( ! -regex '.*/\..*' \) -type f -name \*_lsmplugin -exec c
good "cp $bin_plugin/*_lsmplugin $plugins"
good "ls -lh $plugins"

-
#Start daemon
-good "$LSMD_DAEMON --plugindir $plugins --socketdir $LSM_UDS_PATH" -v
+$LSMD_DAEMON \
+ --plugindir $plugins \
+ --socketdir $LSM_UDS_PATH \
+ -d >$LSMD_TMP_LOG_FILE &

LSMD_PID=$(ps aux | grep $LSM_UDS_PATH | grep -v grep | awk '{print $2}')

#Run C unit test
if [ -z "$LSM_VALGRIND" ]; then
- good "$c_unit"
+ good "$c_unit"
else
- good "valgrind --leak-check=full --show-reachable=no --log-file=/tmp/leaking_client $rootdir/test/.libs/tester"
+ good "valgrind --leak-check=full --show-reachable=no --log-file=/tmp/leaking_client $rootdir/test/.libs/tester"
fi

#Run cmdline against the simulator if we are not checking for leaks
--
1.8.3.1
Gris Ge
2014-08-05 02:48:44 UTC
Permalink
Enable OBS build:
1. Workaround for OBS bug 864323 by using one-line macro.
2. Move BuildRequires:python-argparse of libstoragemgmt-python to top
package. Required by OBS.
3. Show check log - test-suite.log if failed. Important when facing OBS
build failure. Thanks to Jiri Denemark from libvirt:
http://www.redhat.com/archives/libvir-list/2013-July/msg01834.html

Signed-off-by: Gris Ge <***@redhat.com>
---
packaging/libstoragemgmt.spec.in | 47 ++++++++++++++++++++--------------------
1 file changed, 23 insertions(+), 24 deletions(-)

diff --git a/packaging/libstoragemgmt.spec.in b/packaging/libstoragemgmt.spec.in
index eaf9352..37398f1 100644
--- a/packaging/libstoragemgmt.spec.in
+++ b/packaging/libstoragemgmt.spec.in
@@ -1,19 +1,9 @@
%bcond_without rest_api

-%if 0%{?rhel} <= 6
-%global with_rest_api 0
-# RHEL 6 does not have libmicrohttpd in main repo, but in EPEL repo
-# Hence we disable REST API daemon compiling.
-# If EPEL6 is enabled, please use:
-# rpmbuild -ba libstoragemgmt.spec --with rest_api
-%endif
-
-%{?_with_rest_api:
-%global with_rest_api 1
-}
-%{?_without_rest_api:
-%global with_rest_api 0
-}
+# Use one-line macro for OBS workaround:
+# https://bugzilla.novell.com/show_bug.cgi?id=864323
+%{?_with_rest_api: %global with_rest_api 1 }
+%{?_without_rest_api: %global with_rest_api 0 }

Name: libstoragemgmt
Version: @VERSION@
@@ -25,19 +15,22 @@ URL: http://sourceforge.net/projects/libstoragemgmt/
Source0: http://sourceforge.net/projects/libstoragemgmt/files/libstoragemgmt-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
Requires: %{name}-python
-BuildRequires: autoconf automake libtool yajl-devel libxml2-devel check-devel openssl-devel
+BuildRequires: autoconf automake libtool yajl-devel libxml2-devel check-devel
+BuildRequires: openssl-devel
+BuildRequires: python-argparse
BuildRequires: glib2-devel
# Explicitly require gcc-c++ is for OBS
BuildRequires: gcc-c++

-# These buggy extra conditional BuildRequires is for OBS only,
-# Please refer to OBS bug:
-# https://bugzilla.novell.com/show_bug.cgi?id=864323
-%if 0%{?fedora} || 0%{?rhel} >= 7
-BuildRequires: libmicrohttpd-devel json-c-devel
+# For OBS only. OBS is still using RHEL/Centos 6.2 which does not have
+# OrderedDict from python collection. Use EPEL6 python-ordereddict.
+# These line is only for OBS SPEC parser, not for rpmbuild.
+%if 0%{?centos_version} == 600 || 0%{?rhel_version} == 600
+BuildRequires: python-ordereddict
+# redhat-release was not included in OBS. It provides %{rhel} macro.
+BuildRequires: redhat-release
%endif

-
%if 0%{?fedora} >= 15 || 0%{?rhel} >= 7
BuildRequires: systemd-units
Requires: initscripts
@@ -67,9 +60,11 @@ Summary: Python client libraries and plug-in support for %{name}
Group: System Environment/Libraries
Requires: %{name} = %{version}-%{release}
BuildArch: noarch
-%if 0%{?rhel} <= 6
Requires: python-argparse
-BuildRequires: python-argparse
+%if 0%{?rhel} == 6
+# No way to detect 6.2 yet. Just forcing all RHEL 6 to install
+# python-ordereddict just in case.
+Requires: python-ordereddict
%endif

%description python
@@ -195,7 +190,11 @@ install -m 755 tools/udev/scan-scsi-target \
rm -rf %{buildroot}

%check
-make check
+if ! make check
+then
+ cat test/test-suite.log || true
+ exit 1
+fi

%pre
getent group libstoragemgmt >/dev/null || groupadd -r libstoragemgmt
--
1.8.3.1
Gris Ge
2014-08-05 02:48:46 UTC
Permalink
If we aren't doing the comand 'list', then self.args.type
is not present and we will throw an exception. Check
before use.

This was found when trying to run plugin-info without a uri
set.

Signed-off-by: Tony Asleson <***@redhat.com>
Signed-off-by: Gris Ge <***@redhat.com>
---
tools/lsmcli/cmdline.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/lsmcli/cmdline.py b/tools/lsmcli/cmdline.py
index 3f68d05..41bccda 100644
--- a/tools/lsmcli/cmdline.py
+++ b/tools/lsmcli/cmdline.py
@@ -1483,7 +1483,7 @@ class CmdLine:
# the same in all cases, even though it isn't technically
# required for the client library (static method)
# TODO: Make this not necessary.
- if (self.args.type == "PLUGINS"):
+ if ('type' in self.args and self.args.type == "PLUGINS"):
self.uri = "sim://"
self.password = None
else:
--
1.8.3.1
Gris Ge
2014-08-05 02:48:47 UTC
Permalink
More than once the call to lsm_capability_set_n has been done incorrectly
when adding or removing capabilities. Christophe offered this good suggestion:

"
Gris Ge
2014-08-05 02:48:48 UTC
Permalink
The 'simc://' and 'sim://' plugins are not sharing the same list of
UNSUPPORTED capabilities.

Before sync the behaviour of these two plugins, I would like to make test pass
by empty expected_absent capabilities check

Signed-off-by: Gris Ge <***@redhat.com>
---
test/tester.c | 20 --------------------
1 file changed, 20 deletions(-)

diff --git a/test/tester.c b/test/tester.c
index ac250c6..a910489 100644
--- a/test/tester.c
+++ b/test/tester.c
@@ -2097,26 +2097,6 @@ START_TEST(test_capability)
LSM_CAP_EXPORT_REMOVE};

lsm_capability_type expected_absent[] = {
- LSM_CAP_EXPORT_CUSTOM_PATH,
- LSM_CAP_POOL_CREATE,
- LSM_CAP_POOL_CREATE_FROM_DISKS,
- LSM_CAP_POOL_CREATE_FROM_POOL,
-
- LSM_CAP_POOL_CREATE_DISK_RAID_0,
- LSM_CAP_POOL_CREATE_DISK_RAID_1,
- LSM_CAP_POOL_CREATE_DISK_RAID_JBOD,
- LSM_CAP_POOL_CREATE_DISK_RAID_3,
- LSM_CAP_POOL_CREATE_DISK_RAID_4,
- LSM_CAP_POOL_CREATE_DISK_RAID_5,
- LSM_CAP_POOL_CREATE_DISK_RAID_6,
- LSM_CAP_POOL_CREATE_DISK_RAID_10,
- LSM_CAP_POOL_CREATE_DISK_RAID_50,
- LSM_CAP_POOL_CREATE_DISK_RAID_51,
- LSM_CAP_POOL_CREATE_DISK_RAID_60,
- LSM_CAP_POOL_CREATE_DISK_RAID_61,
- LSM_CAP_POOL_CREATE_DISK_RAID_15,
- LSM_CAP_POOL_CREATE_DISK_RAID_16,
- LSM_CAP_POOL_CREATE_DISK_RAID_NOT_APPLICABLE
};
--
1.8.3.1
Gris Ge
2014-08-05 02:48:49 UTC
Permalink
OrderedDict is only available in python 2.7.[1]
We use it from python-ordereddict package which is a backport version.

Tested on RHEL 6.2 which does not port OrderedDict from 2.7 yet.

Signed-off-by: Gris Ge <***@redhat.com>
---
tools/lsmcli/cmdline.py | 7 ++++++-
tools/lsmcli/data_display.py | 8 +++++++-
2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/tools/lsmcli/cmdline.py b/tools/lsmcli/cmdline.py
index 41bccda..04f2a3b 100644
--- a/tools/lsmcli/cmdline.py
+++ b/tools/lsmcli/cmdline.py
@@ -22,7 +22,12 @@ import getpass
import time
import tty
import termios
-from collections import OrderedDict
+
+try:
+ from collections import OrderedDict
+except ImportError:
+ # python 2.6 or earlier, use backport
+ from ordereddict import OrderedDict

from argparse import ArgumentParser
from argparse import RawTextHelpFormatter
diff --git a/tools/lsmcli/data_display.py b/tools/lsmcli/data_display.py
index a4d9629..e87186b 100644
--- a/tools/lsmcli/data_display.py
+++ b/tools/lsmcli/data_display.py
@@ -16,7 +16,13 @@
#
# Author: Gris Ge <***@redhat.com>
import sys
-from collections import OrderedDict
+
+try:
+ from collections import OrderedDict
+except ImportError:
+ # python 2.6 or earlier, use backport
+ from ordereddict import OrderedDict
+
from datetime import datetime

from lsm import (size_bytes_2_size_human, LsmError, ErrorNumber,
--
1.8.3.1
Gris Ge
2014-08-05 02:48:50 UTC
Permalink
* Removed these initiator types as no plugin is using them:
INIT_TYPE_WWNN (Python)
INIT_TYPE_HOSTNAME (Python)
INIT_TYPE_SAS (Python)
LSM_ACCESS_GROUP_INIT_TYPE_WWNN (C)
LSM_ACCESS_GROUP_INIT_TYPE_HOSTNAME (C)
LSM_ACCESS_GROUP_INIT_TYPE_SAS (C)

* Update plugins for above changes.

* Renamed this type in C API:
INIT_TYPE_ISCSI_WWPN_MIXED to LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_WWPN_MIXED

* Removed old initiator class in C API:
1. Renamed lsm_initiator_type to lsm_access_group_init_type
2. Removed lsm_plug_initiator_grant() method
3. Removed _lsm_initiator class.

* Fix incorrect parameter of lsm_iscsi_chap_auth:
initiator -> init_id

* Enabled iscsi_chap_auth test.

Signed-off-by: Gris Ge <***@redhat.com>
---
c_binding/include/libstoragemgmt/libstoragemgmt.h | 4 +-
.../libstoragemgmt/libstoragemgmt_plug_interface.h | 18 +------
.../include/libstoragemgmt/libstoragemgmt_types.h | 15 +-----
c_binding/lsm_datatypes.hpp | 12 -----
c_binding/lsm_mgmt.cpp | 6 +--
c_binding/lsm_plugin_ipc.cpp | 6 +--
plugin/sim/simarray.py | 9 +---
plugin/simc/simc_lsmplugin.c | 6 +--
plugin/smispy/smis.py | 29 +++++-----
python_binding/lsm/_data.py | 3 --
test/tester.c | 61 ++++++++++------------
tools/lsmcli/cmdline.py | 2 +-
tools/lsmcli/data_display.py | 3 --
13 files changed, 55 insertions(+), 119 deletions(-)

diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt.h b/c_binding/include/libstoragemgmt/libstoragemgmt.h
index 5345017..968bfdd 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt.h
@@ -523,7 +523,7 @@ extern "C" {
int LSM_DLL_EXPORT lsm_access_group_create(lsm_connect *conn,
const char *name,
const char *init_id,
- lsm_initiator_type init_type,
+ lsm_access_group_init_type init_type,
lsm_system *system,
lsm_access_group **access_group,
lsm_flag flags);
@@ -552,7 +552,7 @@ extern "C" {
int LSM_DLL_EXPORT lsm_access_group_initiator_add(lsm_connect *conn,
lsm_access_group *access_group,
const char *init_id,
- lsm_initiator_type init_type,
+ lsm_access_group_init_type init_type,
lsm_access_group **updated_access_group,
lsm_flag flags);

diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h b/c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h
index 71a6579..77f2ecb 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h
@@ -417,22 +417,6 @@ typedef int (*lsm_plug_volume_offline)(lsm_plugin_ptr c, lsm_volume *v,
lsm_flag flags);

/**
- * Grants access to an initiator for a specified volume, callback function signature
- * @param[in] c Valid lsm plug-in pointer
- * @param[in] initiator_id Initiator ID
- * @param[in] initiator_type Type of initiator
- * @param[in] volume Volume of interest
- * @param[in] access Desired access to volume
- * @param[in] flags Reserved
- * @return LSM_ERR_OK, else error reason
- */
-typedef int (*lsm_plug_initiator_grant)(lsm_plugin_ptr c, const char *initiator_id,
- lsm_initiator_type initiator_type,
- lsm_volume *volume,
- lsm_access_type access,
- lsm_flag flags);
-
-/**
* Setup the cap authentication for the specified initiator, callback
* function signature
* @param[in] c Valid lsm plug-in pointer
@@ -509,7 +493,7 @@ typedef int (*lsm_plug_access_group_delete)(lsm_plugin_ptr c,
typedef int (*lsm_plug_access_group_initiator_add)(lsm_plugin_ptr c,
lsm_access_group *access_group,
const char *initiator_id,
- lsm_initiator_type id_type,
+ lsm_access_group_init_type id_type,
lsm_access_group **updated_access_group,
lsm_flag flags);

diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt_types.h b/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
index 5180441..4d3b6bd 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
@@ -172,25 +172,12 @@ typedef enum {
#define LSM_SYSTEM_STATUS_OTHER 0x00000200 /**< Vendor specific */


-/**< \enum lsm_initiator_type Different types of initiator IDs */
-typedef enum {
- LSM_INITIATOR_OTHER = 1, /**< Other or unspecified */
- LSM_INITIATOR_PORT_WWN = 2, /**< World wide port name */
- LSM_INITIATOR_NODE_WWN = 3, /**< World wide node name */
- LSM_INITIATOR_HOSTNAME = 4, /**< Host name */
- LSM_INITIATOR_ISCSI = 5, /**< iSCSI IQN */
- LSM_INITIATOR_SAS = 7 /**< SAS ID */
-} lsm_initiator_type;
-
typedef enum {
LSM_ACCESS_GROUP_INIT_TYPE_UNKNOWN = 0, /**< Unknown */
LSM_ACCESS_GROUP_INIT_TYPE_OTHER = 1, /**< Something not seen before */
LSM_ACCESS_GROUP_INIT_TYPE_WWPN = 2, /**< Port name */
- LSM_ACCESS_GROUP_INIT_TYPE_WWNN = 3, /**< Node name */
- LSM_ACCESS_GROUP_INIT_TYPE_HOSTNAME = 4, /**< Host name */
LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_IQN = 5, /**< ISCSI IQN */
- LSM_ACCESS_GROUP_INIT_TYPE_SAS = 6, /**< SAS */
- INIT_TYPE_ISCSI_WWPN_MIXED = 7 /**< More than 1 type */
+ LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_WWPN_MIXED = 7 /**< More than 1 type */
} lsm_access_group_init_type;


diff --git a/c_binding/lsm_datatypes.hpp b/c_binding/lsm_datatypes.hpp
index 40f2935..00e2111 100644
--- a/c_binding/lsm_datatypes.hpp
+++ b/c_binding/lsm_datatypes.hpp
@@ -90,18 +90,6 @@ struct LSM_DLL_LOCAL _lsm_pool {
};


-#define LSM_INIT_MAGIC 0xAA7A0002
-#define LSM_IS_INIT(obj) MAGIC_CHECK(obj, LSM_INIT_MAGIC)
-/**
- * Information about an initiator.
- */
-struct LSM_DLL_LOCAL _lsm_initiator {
- uint32_t magic; /**< Used for verification */
- lsm_initiator_type id_type; /**< Type of id */
- char *id; /**< Identifier */
- char *name; /**< Initiator name */
-};
-
#define LSM_ACCESS_GROUP_MAGIC 0xAA7A0003
#define LSM_IS_ACCESS_GROUP(obj) MAGIC_CHECK(obj, LSM_ACCESS_GROUP_MAGIC)

diff --git a/c_binding/lsm_mgmt.cpp b/c_binding/lsm_mgmt.cpp
index c75ffd5..7ca71c0 100644
--- a/c_binding/lsm_mgmt.cpp
+++ b/c_binding/lsm_mgmt.cpp
@@ -1361,7 +1361,7 @@ int lsm_iscsi_chap_auth(lsm_connect *c, const char *init_id,
}

std::map<std::string, Value> p;
- p["initiator"] = Value(init_id);
+ p["init_id"] = Value(init_id);
p["in_user"] = Value(username);
p["in_password"] = Value(password);
p["out_user"] = Value(out_user);
@@ -1436,7 +1436,7 @@ int lsm_access_group_list(lsm_connect *c, const char *search_key,
}

int lsm_access_group_create(lsm_connect *c, const char *name,
- const char *init_id, lsm_initiator_type init_type,
+ const char *init_id, lsm_access_group_init_type init_type,
lsm_system *system,
lsm_access_group **access_group, lsm_flag flags)
{
@@ -1499,7 +1499,7 @@ int lsm_access_group_delete(lsm_connect *c, lsm_access_group *access_group,
int lsm_access_group_initiator_add(lsm_connect *c,
lsm_access_group *access_group,
const char *init_id,
- lsm_initiator_type init_type,
+ lsm_access_group_init_type init_type,
lsm_access_group **updated_access_group,
lsm_flag flags)
{
diff --git a/c_binding/lsm_plugin_ipc.cpp b/c_binding/lsm_plugin_ipc.cpp
index 8058158..68cbf44 100644
--- a/c_binding/lsm_plugin_ipc.cpp
+++ b/c_binding/lsm_plugin_ipc.cpp
@@ -1236,8 +1236,8 @@ static int ag_initiator_add(lsm_plugin_ptr p, Value &params, Value &response)
if( ag ) {
lsm_access_group *updated_access_group = NULL;
const char *id = v_init_id.asC_str();
- lsm_initiator_type id_type = (lsm_initiator_type)
- v_init_type.asInt32_t();
+ lsm_access_group_init_type id_type =
+ (lsm_access_group_init_type) v_init_type.asInt32_t();

rc = p->san_ops->ag_add_initiator(p, ag, id, id_type,
&updated_access_group,
@@ -2222,7 +2222,7 @@ static int iscsi_chap(lsm_plugin_ptr p, Value &params, Value &response)
int rc = LSM_ERR_NO_SUPPORT;

if( p && p->san_ops && p->san_ops->iscsi_chap_auth ) {
- Value v_init = params["initiator"];
+ Value v_init = params["init_id"];
Value v_in_user = params["in_user"];
Value v_in_password = params["in_password"];
Value v_out_user = params["out_user"];
diff --git a/plugin/sim/simarray.py b/plugin/sim/simarray.py
index b399b03..d59a1b1 100644
--- a/plugin/sim/simarray.py
+++ b/plugin/sim/simarray.py
@@ -640,8 +640,6 @@ class SimData(object):

self.ag_dict = {
}
- self.init_dict = {
- }
# Create some volumes, fs and etc
self.volume_create(
'POO1', 'Volume 000', size_human_2_size_bytes('200GiB'),
@@ -1189,12 +1187,7 @@ class SimData(object):

def iscsi_chap_auth(self, init_id, in_user, in_pass, out_user, out_pass,
flags=0):
- # to_code
- if self.init_dict[init_id]['init_type'] != \
- AccessGroup.INIT_TYPE_ISCSI_IQN:
- raise LsmError(ErrorNumber.NO_SUPPORT,
- "Initiator %s is not an iSCSI IQN" % init_id)
- # No iscsi chap query API yet
+ # No iscsi chap query API yet, not need to setup anything
return None

def fs(self):
diff --git a/plugin/simc/simc_lsmplugin.c b/plugin/simc/simc_lsmplugin.c
index 3f2d056..5a295f6 100644
--- a/plugin/simc/simc_lsmplugin.c
+++ b/plugin/simc/simc_lsmplugin.c
@@ -113,7 +113,7 @@ struct allocated_fs {

struct allocated_ag {
lsm_access_group *ag;
- lsm_initiator_type ag_type;
+ lsm_access_group_init_type ag_type;
};

struct plugin_data {
@@ -189,7 +189,7 @@ void free_allocated_job(void *j)
}

struct allocated_ag *alloc_allocated_ag( lsm_access_group *ag,
- lsm_initiator_type i)
+ lsm_access_group_init_type i)
{
struct allocated_ag *aag =
(struct allocated_ag *)malloc(sizeof(struct allocated_ag));
@@ -1228,7 +1228,7 @@ static int access_group_delete( lsm_plugin_ptr c,
static int access_group_initiator_add( lsm_plugin_ptr c,
lsm_access_group *group,
const char *initiator_id,
- lsm_initiator_type id_type,
+ lsm_access_group_init_type id_type,
lsm_access_group **updated_access_group,
lsm_flag flags)
{
diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index 88ae335..6299d1c 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -141,11 +141,8 @@ class DMTF(object):
# CIM_StorageHardwareID['IDType']
ID_TYPE_OTHER = pywbem.Uint16(1)
ID_TYPE_WWPN = pywbem.Uint16(2)
- ID_TYPE_WWNN = pywbem.Uint16(3)
- ID_TYPE_HOSTNAME = pywbem.Uint16(4)
ID_TYPE_ISCSI = pywbem.Uint16(5)
- ID_TYPE_SW_WWN = pywbem.Uint16(6)
- ID_TYPE_SAS = pywbem.Uint16(7)
+
TGT_PORT_USAGE_FRONTEND_ONLY = pywbem.Uint16(2)
TGT_PORT_USAGE_UNRESTRICTED = pywbem.Uint16(4)
# CIM_FCPort['PortDiscriminator']
@@ -193,17 +190,16 @@ class DMTF(object):
_INIT_TYPE_CONV = {
DMTF.ID_TYPE_OTHER: AccessGroup.INIT_TYPE_OTHER,
DMTF.ID_TYPE_WWPN: AccessGroup.INIT_TYPE_WWPN,
- DMTF.ID_TYPE_WWNN: AccessGroup.INIT_TYPE_WWNN,
- DMTF.ID_TYPE_HOSTNAME: AccessGroup.INIT_TYPE_HOSTNAME,
DMTF.ID_TYPE_ISCSI: AccessGroup.INIT_TYPE_ISCSI_IQN,
- DMTF.ID_TYPE_SW_WWN: AccessGroup.INIT_TYPE_OTHER,
- DMTF.ID_TYPE_SAS: AccessGroup.INIT_TYPE_SAS,
}


def _dmtf_init_type_to_lsm(cim_init):
- if 'IDType' in cim_init and cim_init['IDType'] in _INIT_TYPE_CONV.keys():
- return _INIT_TYPE_CONV[cim_init['IDType']]
+ if 'IDType' in cim_init:
+ if cim_init['IDType'] == DMTF.ID_TYPE_WWPN:
+ return AccessGroup.INIT_TYPE_WWPN
+ elif cim_init['IDType'] == DMTF.ID_TYPE_ISCSI:
+ return AccessGroup.INIT_TYPE_ISCSI_IQN
return AccessGroup.INIT_TYPE_UNKNOWN


@@ -225,13 +221,12 @@ def _lsm_tgt_port_type_of_cim_fc_tgt(cim_fc_tgt):


def _lsm_init_type_to_dmtf(init_type):
- # Invert dict. Assumes values are unique.
- try:
- inv_dict = dict((v, k) for k, v in _INIT_TYPE_CONV.iteritems())
- return inv_dict[init_type]
- except KeyError:
- raise LsmError(ErrorNumber.NO_SUPPORT,
- "Does not support provided init_type: %d" % init_type)
+ if init_type == AccessGroup.INIT_TYPE_WWPN:
+ return DMTF.ID_TYPE_WWPN
+ if init_type == AccessGroup.INIT_TYPE_ISCSI_IQN:
+ return DMTF.ID_TYPE_ISCSI
+ raise LsmError(ErrorNumber.NO_SUPPORT,
+ "Does not support provided init_type: %d" % init_type)


class SNIA(object):
diff --git a/python_binding/lsm/_data.py b/python_binding/lsm/_data.py
index ff5065f..70ee4da 100644
--- a/python_binding/lsm/_data.py
+++ b/python_binding/lsm/_data.py
@@ -650,10 +650,7 @@ class AccessGroup(IData):
INIT_TYPE_UNKNOWN = 0
INIT_TYPE_OTHER = 1
INIT_TYPE_WWPN = 2
- INIT_TYPE_WWNN = 3
- INIT_TYPE_HOSTNAME = 4
INIT_TYPE_ISCSI_IQN = 5
- INIT_TYPE_SAS = 6
INIT_TYPE_ISCSI_WWPN_MIXED = 7

def __init__(self, _id, _name, _init_ids, _init_type, _system_id,
diff --git a/test/tester.c b/test/tester.c
index a910489..a034e04 100644
--- a/test/tester.c
+++ b/test/tester.c
@@ -613,7 +613,8 @@ START_TEST(test_access_groups)
fail_unless(groups == NULL);

G(rc, lsm_access_group_create, c, "test_access_groups",
- "iqn.1994-05.com.domain:01.89bd01", LSM_INITIATOR_ISCSI, system,
+ "iqn.1994-05.com.domain:01.89bd01",
+ LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_IQN, system,
&group, LSM_FLAG_RSVD);

if( LSM_ERR_OK == rc ) {
@@ -655,7 +656,9 @@ START_TEST(test_access_groups)
char *job = NULL;
lsm_access_group *updated = NULL;

- rc = lsm_access_group_initiator_add(c, group, "iqn.1994-05.com.domain:01.89bd02", LSM_INITIATOR_ISCSI, &updated, LSM_FLAG_RSVD);
+ rc = lsm_access_group_initiator_add(c, group, "iqn.1994-05.com.domain:01.89bd02",
+ LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_IQN,
+ &updated, LSM_FLAG_RSVD);
fail_unless(LSM_ERR_OK == rc, "Expected success on lsmAccessGroupInitiatorAdd %d %d", rc, which_plugin);

G(rc, lsm_access_group_list, c, NULL, NULL, &groups, &count, LSM_FLAG_RSVD);
@@ -744,9 +747,10 @@ START_TEST(test_access_groups_grant_revoke)
system = get_system(c);

G(rc, lsm_access_group_create, c, "test_access_groups_grant_revoke",
- ISCSI_HOST[0], LSM_INITIATOR_ISCSI,
- system,
- &group, LSM_FLAG_RSVD);
+ ISCSI_HOST[0],
+ LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_IQN,
+ system,
+ &group, LSM_FLAG_RSVD);


int vc = lsm_volume_create(c, pool, "volume_grant_test", 20000000,
@@ -1528,12 +1532,12 @@ START_TEST(test_invalid_input)
rc = lsm_access_group_create(c, NULL, NULL, 0, system, NULL, LSM_FLAG_RSVD);
fail_unless(rc == LSM_ERR_INVALID_ARGUMENT, "rc = %d", rc);

- rc = lsm_access_group_create(c, "my_group", ISCSI_HOST[0], LSM_INITIATOR_OTHER,
+ rc = lsm_access_group_create(c, "my_group", ISCSI_HOST[0], LSM_ACCESS_GROUP_INIT_TYPE_OTHER,
NULL, NULL, LSM_FLAG_RSVD);
fail_unless(rc == LSM_ERR_INVALID_SYSTEM, "rc = %d", rc);


- rc = lsm_access_group_create(c, "my_group", ISCSI_HOST[0], LSM_INITIATOR_OTHER,
+ rc = lsm_access_group_create(c, "my_group", ISCSI_HOST[0], LSM_ACCESS_GROUP_INIT_TYPE_OTHER,
system, &ag, LSM_FLAG_RSVD);
fail_unless(rc == LSM_ERR_OK, "rc = %d", rc);
fail_unless(ag != NULL);
@@ -1925,45 +1929,35 @@ START_TEST(test_iscsi_auth_in)
{
lsm_access_group *group = NULL;
lsm_system *system = NULL;
- //char *job = NULL;
- int rc;
+ int rc = 0;

system = get_system(c);
+ printf("get_system() OK\n");

G(rc, lsm_access_group_create, c, "ISCSI_AUTH", ISCSI_HOST[0],
- LSM_INITIATOR_ISCSI, system, &group, LSM_FLAG_RSVD);
+ LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_IQN, system, &group, LSM_FLAG_RSVD);
+ printf("lsm_access_group_create() OK\n");

- fail_unless(LSM_ERR_OK == rc, "rc = %d");
+ fail_unless(LSM_ERR_OK == rc, "rc = %d", rc);
G(rc, lsm_system_record_free, system);
+ printf("lsm_system_record_free() OK\n");
+
system = NULL;

if( LSM_ERR_OK == rc ) {
- /* TODO FIX THIS UP after we take out the C initiator support.
- lsm_initiator **inits = NULL;
- uint32_t init_count = 0;
-

- rc = lsm_initiator_list(c, &inits, &init_count, LSM_FLAG_RSVD );
- fail_unless(LSM_ERR_OK == rc );
+ rc = lsm_iscsi_chap_auth(
+ c, ISCSI_HOST[0], "username", "secret", NULL, NULL,
+ LSM_FLAG_RSVD);

- if( LSM_ERR_OK == rc && init_count ) {
- rc = lsm_iscsi_chap_auth(c, inits[0], "username", "secret",
- NULL, NULL, LSM_FLAG_RSVD);
+ fail_unless(LSM_ERR_OK == rc, "rc = %d", rc);

- fail_unless(LSM_ERR_OK == rc, "rc = %d", rc) ;
- }
+ rc = lsm_access_group_delete(c, group, LSM_FLAG_RSVD);

- rc = lsm_access_group_delete(c, group, LSM_FLAG_RSVD);
+ fail_unless(LSM_ERR_OK == rc );

- if(LSM_ERR_JOB_STARTED == rc ) {
- wait_for_job(c, &job);
- } else {
- fail_unless(LSM_ERR_OK == rc );
- }
- */
-
- lsm_access_group_record_free(group);
- group = NULL;
+ lsm_access_group_record_free(group);
+ group = NULL;
}
}
END_TEST
@@ -2666,7 +2660,8 @@ START_TEST(test_search_access_groups)
snprintf(ag_name, sizeof(ag_name), "test_access_group_%d", i);

G(rc, lsm_access_group_create, c, ag_name, ISCSI_HOST[i],
- LSM_INITIATOR_ISCSI, system, &group, LSM_FLAG_RSVD);
+ LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_IQN,
+ system, &group, LSM_FLAG_RSVD);

if( LSM_ERR_OK == rc ) {
G(rc, lsm_access_group_record_free, group);
diff --git a/tools/lsmcli/cmdline.py b/tools/lsmcli/cmdline.py
index 04f2a3b..96b3fbe 100644
--- a/tools/lsmcli/cmdline.py
+++ b/tools/lsmcli/cmdline.py
@@ -109,7 +109,7 @@ list_choices = ['VOLUMES', 'POOLS', 'FS', 'SNAPSHOTS',
'EXPORTS', "NFS_CLIENT_AUTH", 'ACCESS_GROUPS',
'SYSTEMS', 'DISKS', 'PLUGINS', 'TARGET_PORTS']

-init_types = ('WWPN', 'WWNN', 'ISCSI', 'HOSTNAME', 'SAS')
+init_types = ('WWPN', 'ISCSI')
init_id_help = "Access Group Initiator type: " + \
", ".join(init_types)

diff --git a/tools/lsmcli/data_display.py b/tools/lsmcli/data_display.py
index e87186b..9a18cd5 100644
--- a/tools/lsmcli/data_display.py
+++ b/tools/lsmcli/data_display.py
@@ -289,10 +289,7 @@ _AG_INIT_TYPE_CONV = {
AccessGroup.INIT_TYPE_UNKNOWN: 'Unknown',
AccessGroup.INIT_TYPE_OTHER: 'Other',
AccessGroup.INIT_TYPE_WWPN: 'WWPN',
- AccessGroup.INIT_TYPE_WWNN: 'WWNN',
- AccessGroup.INIT_TYPE_HOSTNAME: 'Hostname',
AccessGroup.INIT_TYPE_ISCSI_IQN: 'iSCSI',
- AccessGroup.INIT_TYPE_SAS: 'SAS',
AccessGroup.INIT_TYPE_ISCSI_WWPN_MIXED: 'iSCSI/WWPN Mixed',
}
--
1.8.3.1
Gris Ge
2014-08-05 02:48:51 UTC
Permalink
1. Forcing user to input WWPN in this format:
10:00:00:00:c9:95:2f:de

2. Add methods to lsm.AccessGroup:
AccessGroup.init_id_validate()
AccessGroup.wwpn_to_lsm_type()

3. Rename INVALID_IQN to INVALID_INIT

Signed-off-by: Gris Ge <***@redhat.com>
---
python_binding/lsm/_client.py | 4 ++
python_binding/lsm/_common.py | 2 +-
python_binding/lsm/_data.py | 96 ++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 99 insertions(+), 3 deletions(-)

diff --git a/python_binding/lsm/_client.py b/python_binding/lsm/_client.py
index 61a7aa2..00b9184 100644
--- a/python_binding/lsm/_client.py
+++ b/python_binding/lsm/_client.py
@@ -427,6 +427,8 @@ class Client(INetworkAttachedStorage):
Register a user/password for the specified initiator for CHAP
authentication.
"""
+ AccessGroup.init_id_validate(
+ init_id, AccessGroup.INIT_TYPE_ISCSI_IQN, raise_error=True)
return self._tp.rpc('iscsi_chap_auth', _del_self(locals()))

## Returns an array of volume objects
@@ -652,6 +654,7 @@ class Client(INetworkAttachedStorage):
Creates an access group and add the specified initiator id,
init_type and desired access.
"""
+ AccessGroup.init_id_validate(init_id, init_type, raise_error=True)
return self._tp.rpc('access_group_create', _del_self(locals()))

## Deletes an access group.
@@ -679,6 +682,7 @@ class Client(INetworkAttachedStorage):
"""
Adds an initiator to an access group
"""
+ AccessGroup.init_id_validate(init_id, init_type, raise_error=True)
return self._tp.rpc('access_group_initiator_add', _del_self(locals()))

## Deletes an initiator from an access group
diff --git a/python_binding/lsm/_common.py b/python_binding/lsm/_common.py
index fdd10ab..386d9a9 100644
--- a/python_binding/lsm/_common.py
+++ b/python_binding/lsm/_common.py
@@ -455,7 +455,7 @@ class ErrorNumber(object):
INVALID_VOLUME = 115
INVALID_CAPABILITY = 116
INVALID_SYSTEM = 117
- INVALID_IQN = 118
+ INVALID_INIT = 118
INVALID_DISK = 119
INVALID_BLOCK_RANGE = 121

diff --git a/python_binding/lsm/_data.py b/python_binding/lsm/_data.py
index 70ee4da..d6feed8 100644
--- a/python_binding/lsm/_data.py
+++ b/python_binding/lsm/_data.py
@@ -17,6 +17,7 @@
# Gris Ge <***@redhat.com>

from abc import ABCMeta as _ABCMeta
+import re

try:
import simplejson as json
@@ -24,7 +25,7 @@ except ImportError:
import json

from json.decoder import WHITESPACE
-from _common import get_class, default_property
+from _common import get_class, default_property, ErrorNumber, LsmError


class DataEncoder(json.JSONEncoder):
@@ -657,11 +658,102 @@ class AccessGroup(IData):
_plugin_data=None):
self._id = _id
self._name = _name # AccessGroup name
- self._init_ids = _init_ids # List of initiator IDs
+ self._init_ids = _init_ids # A list of Initiator ID strings.
self._init_type = _init_type
self._system_id = _system_id # System id this group belongs
self._plugin_data = _plugin_data

+ # Regex for LSM format of WWPN, example:
+ # 10:00:00:00:c9:95:2f:de
+ _regex_lsm_wwpn = re.compile(r"""
+ ^
+ (?:[0-9a-f]{2}:){7}
+ [0-9a-f]{2}
+ $
+ """, re.X)
+
+ _regex_iscsi_iqn = re.compile(r"""
+ ^
+ iqn # iqn
+ \. # .
+ [0-9]{4}-[0-9]{2} # 1995-02
+ \. # .
+ [A-Za-z](?:[A-Za-z0-9\-]*[A-Za-z0-9])? # com
+ \. # .
+ [A-Za-z](?:[A-Za-z0-9\-]*[A-Za-z0-9])? # redhat
+ : # :
+ [\.A-Za-z\-0-9]+ # gris-01
+ $
+ """, re.X)
+
+ @staticmethod
+ def init_id_validate(init_id, init_type, raise_error=True):
+ if init_type == AccessGroup.INIT_TYPE_ISCSI_IQN:
+ if AccessGroup._regex_iscsi_iqn.match(str(init_id)):
+ return True
+ if raise_error:
+ raise LsmError(ErrorNumber.INVALID_INIT,
+ "Invalid iSCSI IQN Initiator: %s" % init_id)
+ return False
+ elif init_type == AccessGroup.INIT_TYPE_WWPN:
+ if AccessGroup._regex_lsm_wwpn.match(str(init_id)):
+ return True
+ if raise_error:
+ raise LsmError(ErrorNumber.INVALID_INIT,
+ "Invalid WWPN Initiator: %s" % init_id)
+ return False
+ elif raise_error:
+ raise LsmError(ErrorNumber.NO_SUPPORT,
+ "Initiator type %d not supported" % init_type)
+ return False
+
+ _regex_wwpn = re.compile(r"""
+ ^
+ [0x|0X]{0,1}
+ (:?[0-9A-Fa-f]{2}
+ [\.\-:]{0,1}){7}
+ [0-9A-Fa-f]{2}
+ $
+ """, re.X)
+
+ @staticmethod
+ def wwpn_to_lsm_type(wwpn, raise_error=True):
+ """
+ Conver provided WWPN string into LSM standarded one:
+
+ LSM WWPN format:
+ ^(?:[0-9a-f]{2}:){7}[0-9a-f]{2}$
+ LSM WWPN Example:
+ 10:00:00:00:c9:95:2f:de
+
+ Acceptable WWPN format is:
+ ^[0x|0X]{0,1}(:?[0-9A-Fa-f]{2}[\.\-:]{0,1}){7}[0-9A-Fa-f]{2}$
+ Acceptable WWPN example:
+ 10:00:00:00:c9:95:2f:de
+ 10:00:00:00:C9:95:2F:DE
+ 10-00-00-00-C9-95-2F-DE
+ 10-00-00-00-c9-95-2f-de
+ 10.00.00.00.C9.95.2F.DE
+ 10.00.00.00.c9.95.2f.de
+ 0x10000000c9952fde
+ 0X10000000C9952FDE
+ 10000000c9952fde
+ 10000000C9952FDE
+ Return the LSM WWPN
+ Return None if raise_error is False and not a valid WWPN.
+ """
+ if AccessGroup._regex_wwpn.match(str(wwpn)):
+ s = str(wwpn)
+ s = s.lower()
+ s = re.sub(r'0x', '', s)
+ s = re.sub(r'[^0-9a-f]', '', s)
+ s = ":".join(re.findall(r'..', s))
+ return s
+ if raise_error:
+ raise LsmError(ErrorNumber.INVALID_INIT,
+ "Invalid WWPN Initiator: %s" % wwpn)
+ return None
+

@default_property('id', doc="Unique instance identifier")
@default_property('port_type', doc="Target port type")
--
1.8.3.1
Gris Ge
2014-08-05 02:48:52 UTC
Permalink
* Remove old LSM_ERR_INVALID_INIT which is not cleaned up by last initiator
class removal.

* Rename LSM_ERR_INVALID_IQN to LSM_ERR_INVALID_INIT.

Signed-off-by: Gris Ge <***@redhat.com>
---
c_binding/include/libstoragemgmt/libstoragemgmt_error.h | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt_error.h b/c_binding/include/libstoragemgmt/libstoragemgmt_error.h
index d03c29a..60f2362 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt_error.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt_error.h
@@ -66,7 +66,6 @@ typedef enum {
LSM_ERR_INVALID_CONN = 102, /**< Connection structure is invalid */
LSM_ERR_INVALID_ERR = 103, /**< Invalid error structure */
LSM_ERR_INVALID_FS = 104, /**< invalid fs */
- LSM_ERR_INVALID_INIT = 105, /**< Invalid initiator structure */
LSM_ERR_INVALID_JOB = 106, /**< Invalid job number */
LSM_ERR_INVALID_NAME = 107, /**< Name specified is invalid */
LSM_ERR_INVALID_NFS = 108, /**< invalid nfs export record */
@@ -79,7 +78,7 @@ typedef enum {
LSM_ERR_INVALID_VOL = 115, /**< Invalid volume pointer */
LSM_ERR_INVALID_CAPABILITY = 116, /**< Invalid capability pointer */
LSM_ERR_INVALID_SYSTEM = 117, /**< Invalid system pointer */
- LSM_ERR_INVALID_IQN = 118, /**< Invalid IQN */
+ LSM_ERR_INVALID_INIT = 118, /**< Invalid Initiator ID */
LSM_ERR_INVALID_DISK = 119, /**< Invalid disk */
LSM_ERR_INVALID_HASH = 120, /**< Invalid optional data */
LSM_ERR_INVALID_BLOCK_RANGE = 121, /**< Invalud block range */
--
1.8.3.1
Gris Ge
2014-08-05 02:48:53 UTC
Permalink
* Remove '--init-type' by auto detecting user input.
* Manpage updated.
* cmdtest.py updated.

Signed-off-by: Gris Ge <***@redhat.com>
---
doc/man/lsmcli.1.in | 12 ++----------
test/cmdtest.py | 7 ++-----
tools/lsmcli/cmdline.py | 52 ++++++++++++++++++++++++++-----------------------
3 files changed, 32 insertions(+), 39 deletions(-)

diff --git a/doc/man/lsmcli.1.in b/doc/man/lsmcli.1.in
index 1492847..d6337eb 100644
--- a/doc/man/lsmcli.1.in
+++ b/doc/man/lsmcli.1.in
@@ -357,11 +357,7 @@ Create an access group.
Required. The human friendly name for new access group.
.TP
\fB--init\fR \fI<INIT_ID>\fR
-Required. The first initiator ID of new access group.
-.TP
-\fB--init-type\fR \fI<INIT_TYPE>\fR
-Required. The initiator type. Valid values are: \fBWWPN\fR, \fBWWNN\fR,
-\fBISCSI\fR, \fBHOSTNAME\fR, \fBSAS\fR.
+Required. The first initiator ID of new access group. WWPN or iSCSI IQN.
.TP
\fB--sys\fR \fI<SYS_ID>\fR
Required. The ID of system where this access group should reside on.
@@ -373,11 +369,7 @@ Adds an initiator to an access group.
Required. ID of access group.
.TP
\fB--init\fR \fI<INIT_ID>\fR
-Required. ID of initiator to add.
-.TP
-\fB--init-type\fR \fI<INIT_TYPE>\fR
-Required. The initiator type. Valid values are: \fBWWPN\fR, \fBWWNN\fR,
-\fBISCSI\fR, \fBHOSTNAME\fR, \fBSAS\fR.
+Required. ID of initiator to add. WWPN or iSCSI IQN.

.SS access-group-remove
Removes an initiator from an access group.
diff --git a/test/cmdtest.py b/test/cmdtest.py
index 0dcd91c..408dc10 100755
--- a/test/cmdtest.py
+++ b/test/cmdtest.py
@@ -194,15 +194,13 @@ def delete_fs(fs_id):

def access_group_create(init_id, system_id):
out = call([cmd, '-t' + sep, 'access-group-create', '--name', rs(8),
- '--init', init_id, '--init-type', 'ISCSI',
- '--sys', system_id])[1]
+ '--init', init_id, '--sys', system_id])[1]
r = parse(out)
return r[0][ID]


def access_group_initiator_add(group, initiator):
- call([cmd, 'access-group-add', '--ag', group, '--init', initiator,
- '--init-type', 'ISCSI'])
+ call([cmd, 'access-group-add', '--ag', group, '--init', initiator])


def access_group_remove_init(group, initiator):
@@ -363,7 +361,6 @@ def initiator_grant(initiator_id, vol_id):
call([cmd,
'access-grant',
'--init', initiator_id,
- '--init-type', 'ISCSI',
'--vol', vol_id,
'--access', 'RW'])

diff --git a/tools/lsmcli/cmdline.py b/tools/lsmcli/cmdline.py
index 96b3fbe..3588597 100644
--- a/tools/lsmcli/cmdline.py
+++ b/tools/lsmcli/cmdline.py
@@ -77,6 +77,22 @@ def getch():
termios.tcsetattr(fd, termios.TCSADRAIN, prev)
return ch

+def parse_convert_init(init_id):
+ """
+ If init_id is a WWPN, convert it into LSM standard version:
+ (?:[0-9a-f]{2}:){7}[0-9a-f]{2}
+
+ Return (converted_init_id, lsm_init_type)
+ """
+ init_type = AccessGroup.INIT_TYPE_ISCSI_IQN
+ if AccessGroup.init_id_validate(init_id, init_type, raise_error=False):
+ return (init_id, init_type)
+
+ wwpn = AccessGroup.wwpn_to_lsm_type(init_id, raise_error=False)
+ if wwpn:
+ return (wwpn, AccessGroup.INIT_TYPE_WWPN)
+
+ raise ArgError("--init-id %s is not a valid WWPN or iSCSI IQN" % init_id)

## This class represents a command line argument error
class ArgError(Exception):
@@ -109,10 +125,6 @@ list_choices = ['VOLUMES', 'POOLS', 'FS', 'SNAPSHOTS',
'EXPORTS', "NFS_CLIENT_AUTH", 'ACCESS_GROUPS',
'SYSTEMS', 'DISKS', 'PLUGINS', 'TARGET_PORTS']

-init_types = ('WWPN', 'ISCSI')
-init_id_help = "Access Group Initiator type: " + \
- ", ".join(init_types)
-
provision_types = ('DEFAULT', 'THIN', 'FULL')
provision_help = "provisioning type: " + ", ".join(provision_types)

@@ -176,9 +188,6 @@ disk_id_filter_opt = dict(name='--disk', metavar='<DISK_ID>',

size_opt = dict(name='--size', metavar='<SIZE>', help=size_help)

-init_type_opt = dict(name="--init-type", help=init_id_help,
- metavar='<INIT_TYPE>', choices=init_types,
- type=str.upper)
tgt_id_opt = dict(name="--tgt", help="Search by target port ID",
metavar='<TGT_ID>')

@@ -348,10 +357,6 @@ cmds = (
dict(name='--init', metavar='<INIT_ID>', action='append',
help='Initiator ID, only used when access-group-create is '
'not supported'),
- dict(name="--init-type", type=str.upper,
- metavar='<INIT_TYPE>', choices=init_types,
- help="%s only used when access-group-create is not supported"
- % init_id_help),
],
),

@@ -373,7 +378,6 @@ cmds = (
# TODO: _client.py access_group_create should support multiple
# initiators when creating.
dict(init_id_opt),
- dict(init_type_opt),
dict(sys_id_opt),
],
),
@@ -384,7 +388,6 @@ cmds = (
args=[
dict(ag_id_opt),
dict(init_id_opt),
- dict(init_type_opt),
],
),
dict(
@@ -954,21 +957,21 @@ class CmdLine:

## Creates an access group.
def access_group_create(self, args):
- init_type = ag_init_type_str_to_lsm(args.init_type)
system = _get_item(self.c.systems(), args.sys, "system id")
- access_group = self.c.access_group_create(args.name, args.init,
+ (init_id, init_type) = parse_convert_init(args.init)
+ access_group = self.c.access_group_create(args.name, init_id,
init_type, system)
self.display_data([access_group])

def _add_rm_access_grp_init(self, args, op):
lsm_ag = _get_item(self.c.access_groups(), args.ag, "access group id")
+ (init_id, init_type) = parse_convert_init(args.init)

if op:
- init_type = ag_init_type_str_to_lsm(args.init_type)
- return self.c.access_group_initiator_add(lsm_ag, args.init,
+ return self.c.access_group_initiator_add(lsm_ag, init_id,
init_type)
else:
- return self.c.access_group_initiator_delete(lsm_ag, args.init)
+ return self.c.access_group_initiator_delete(lsm_ag, init_id)

## Adds an initiator from an access group
def access_group_add(self, args):
@@ -985,7 +988,11 @@ class CmdLine:
self.display_data(vols)

def iscsi_chap(self, args):
- self.c.iscsi_chap_auth(args.init, args.in_user,
+ (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)
+
+ self.c.iscsi_chap_auth(init_id, args.in_user,
self.args.in_pass,
self.args.out_user,
self.args.out_pass)
@@ -1266,9 +1273,6 @@ class CmdLine:
if not args.ag and not args.init:
raise ArgError('Neither --ag nor --init is defined. '
'Please specify at lease one')
- if args.init and not args.init_type:
- raise ArgError('In volume-mask command, --init and '
- '--init-type should be defined at the same time')
if args.ag and args.init:
raise ArgError('In volume-mask command, --init is '
'conflicting with --ag')
@@ -1278,8 +1282,8 @@ class CmdLine:
ag = _get_item(self.c.access_groups(), args.ag, 'Access Group ID')

if args.init:
- init_type = ag_init_type_str_to_lsm(args.init_type)
- ag = AccessGroup(0, '', args.init, init_type, vol.system_id)
+ (init_id, init_type) = parse_convert_init(args.init)
+ ag = AccessGroup(0, '', [init_id], init_type, vol.system_id)
self.c.volume_mask(ag, vol)

def volume_unmask(self, args):
--
1.8.3.1
Gris Ge
2014-08-05 02:48:54 UTC
Permalink
Rename ErrorNumber.INVALID_IQN to ErrorNumber.INVALID_INIT.

Signed-off-by: Gris Ge <***@redhat.com>
---
plugin/ontap/ontap.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/plugin/ontap/ontap.py b/plugin/ontap/ontap.py
index d33e230..6cf7ec0 100644
--- a/plugin/ontap/ontap.py
+++ b/plugin/ontap/ontap.py
@@ -44,7 +44,7 @@ e_map = {
na.Filer.ESERVICENOTLICENSED: ErrorNumber.NOT_LICENSED,
na.Filer.ECLONE_LICENSE_EXPIRED: ErrorNumber.NOT_LICENSED,
na.Filer.ECLONE_NOT_LICENSED: ErrorNumber.NOT_LICENSED,
- na.Filer.EINVALID_ISCSI_NAME: ErrorNumber.INVALID_IQN,
+ na.Filer.EINVALID_ISCSI_NAME: ErrorNumber.INVALID_INIT,
na.Filer.ETIMEOUT: ErrorNumber.PLUGIN_TIMEOUT,
na.Filer.EUNKNOWN: ErrorNumber.PLUGIN_ERROR
}
--
1.8.3.1
Gris Ge
2014-08-05 02:48:55 UTC
Permalink
* Convert SNIA format WWPN to LSM format before saving in AccessGroup.
* Convert LSM WWPN to SNIA format before sending to WBEM.

Signed-off-by: Gris Ge <***@redhat.com>
---
plugin/smispy/smis.py | 83 +++++++++++++++++++++++++++++----------------------
1 file changed, 47 insertions(+), 36 deletions(-)

diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index 6299d1c..a4122fc 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -137,6 +137,17 @@ def _hex_string_format(hex_str, length, every):
return ':'.join(hex_str[i:i + every] for i in range(0, length, every))


+def _lsm_init_id_to_snia(lsm_init_id):
+ """
+ If lsm_init_id is a WWPN, convert it to SNIA format:
+ [0-9A-F]{16}
+ If not, return directly.
+ """
+ if AccessGroup.init_id_validate(lsm_init_id,
+ AccessGroup.INIT_TYPE_WWPN):
+ return lsm_init_id.replace(':', '').upper()
+ return lsm_init_id
+
class DMTF(object):
# CIM_StorageHardwareID['IDType']
ID_TYPE_OTHER = pywbem.Uint16(1)
@@ -1549,23 +1560,35 @@ class Smis(IStorageAreaNetwork):
# filter out the mapping SPC.
return cim_spc_pros

- @staticmethod
- def _init_type_of_cim_inits(cim_inits):
- ag_init_types = [_dmtf_init_type_to_lsm(i) for i in cim_inits]
+ def _cim_inits_to_lsm(self, cim_inits):
+ """
+ Retrive AccessGroup.init_ids and AccessGroup.init_type from
+ a list of CIM_StorageHardwareID.
+ """
+ init_ids = []
init_type = AccessGroup.INIT_TYPE_UNKNOWN
- ag_init_type_dict = {}
- for ag_init_type in ag_init_types:
- ag_init_type_dict[ag_init_type] = 1
- if len(ag_init_type_dict) == 1:
- init_type = ag_init_types[0]
- elif (len(ag_init_type_dict) == 2 and
- AccessGroup.INIT_TYPE_ISCSI_IQN in ag_init_type_dict.keys() and
- AccessGroup.INIT_TYPE_WWPN in ag_init_type_dict.keys()):
+ init_types = []
+ for cim_init in cim_inits:
+ init_type = _dmtf_init_type_to_lsm(cim_init)
+ if init_type == AccessGroup.INIT_TYPE_WWPN:
+ init_ids.append(
+ AccessGroup.wwpn_to_lsm_type(self._init_id(cim_init)))
+ init_types.append(init_type)
+ elif init_type == AccessGroup.INIT_TYPE_ISCSI_IQN:
+ init_ids.append(self._init_id(cim_init))
+ init_types.append(init_type)
+ # Skip if not a iscsi initiator IQN or WWPN.
+ continue
+
+ init_type_dict = {}
+ for cur_init_type in init_types:
+ init_type_dict[cur_init_type] = 1
+
+ if len(init_type_dict) == 1:
+ init_type = init_types[0]
+ elif len(init_type_dict) == 2:
init_type = AccessGroup.INIT_TYPE_ISCSI_WWPN_MIXED
- else:
- # We have unknown mixed initiator type
- init_type = AccessGroup.INIT_TYPE_OTHER
- return init_type
+ return (init_ids, init_type)

def _cim_spc_to_lsm(self, cim_spc, system_id=None):
if system_id is None:
@@ -1576,24 +1599,9 @@ class Smis(IStorageAreaNetwork):
cim_init_pros = self._property_list_of_id('Initiator')
cim_init_pros.extend(['IDType'])
cim_inits = self._cim_init_of_spc(cim_spc.path, cim_init_pros)
- ag_init_ids = [self._init_id(i) for i in cim_inits]
- ag_init_types = [_dmtf_init_type_to_lsm(i) for i in cim_inits]
- init_type = AccessGroup.INIT_TYPE_UNKNOWN
- ag_init_type_dict = {}
- for ag_init_type in ag_init_types:
- ag_init_type_dict[ag_init_type] = 1
- if len(ag_init_type_dict) == 1:
- init_type = ag_init_types[0]
- elif (len(ag_init_type_dict) == 2 and
- AccessGroup.INIT_TYPE_ISCSI_IQN in ag_init_type_dict.keys() and
- AccessGroup.INIT_TYPE_WWPN in ag_init_type_dict.keys()):
- init_type = AccessGroup.INIT_TYPE_ISCSI_WWPN_MIXED
- else:
- # We have unknown mixed initiator type
- init_type = AccessGroup.INIT_TYPE_OTHER
-
+ (init_ids, init_type) = self._cim_inits_to_lsm(cim_inits)
sys_id = self._sys_id_child(cim_spc)
- return AccessGroup(ag_id, ag_name, ag_init_ids, init_type, sys_id)
+ return AccessGroup(ag_id, ag_name, init_ids, init_type, sys_id)

def _new_vol_from_job(self, job):
"""
@@ -2954,6 +2962,7 @@ class Smis(IStorageAreaNetwork):
@handle_cim_errors
def access_group_initiator_add(self, access_group, init_id, init_type,
flags=0):
+ init_id = _lsm_init_id_to_snia(init_id)
mask_type = self._mask_type(raise_error=True)

if mask_type == Smis.MASK_TYPE_GROUP:
@@ -3088,6 +3097,7 @@ class Smis(IStorageAreaNetwork):

@handle_cim_errors
def access_group_initiator_delete(self, access_group, init_id, flags=0):
+ init_id = _lsm_init_id_to_snia(init_id)
mask_type = self._mask_type(raise_error=True)

if mask_type == Smis.MASK_TYPE_GROUP:
@@ -4691,9 +4701,8 @@ class Smis(IStorageAreaNetwork):
cim_init_pros = self._property_list_of_id('Initiator')
cim_init_pros.extend(['IDType'])
cim_inits = self._cim_init_of_init_mg(cim_init_mg.path, cim_init_pros)
- ag_init_ids = [self._init_id(i) for i in cim_inits]
- init_type = Smis._init_type_of_cim_inits(cim_inits)
- return AccessGroup(ag_id, ag_name, ag_init_ids, init_type, system_id)
+ (init_ids, init_type) = self._cim_inits_to_lsm(cim_inits)
+ return AccessGroup(ag_id, ag_name, init_ids, init_type, system_id)

def _wait_invoke(self, rc, out, out_key=None, expect_class=None,
flag_out_array=False,):
@@ -4839,6 +4848,8 @@ class Smis(IStorageAreaNetwork):
confliction.
1. Create CIM_InitiatorMaskingGroup
"""
+ org_init_id = init_id
+ init_id = _lsm_init_id_to_snia(init_id)
if self.fallback_mode:
raise LsmError(ErrorNumber.NO_SUPPORT,
"access_group_create() is not supported in "
@@ -4900,7 +4911,7 @@ class Smis(IStorageAreaNetwork):
# Name does not match.
raise LsmError(ErrorNumber.EXISTS_INITIATOR,
"Initiator %s already exist in other access group "
- % init_id +
+ % org_init_id +
"with name %s and ID: %s" %
(exist_cim_init_mgs[0]['ElementName'],
md5(exist_cim_init_mgs[0]['DeviceID'])))
--
1.8.3.1
Gris Ge
2014-08-05 02:48:56 UTC
Permalink
* Fix these problems:
1. _cim_init_check_or_create() incorrect return CIMInstanceName when
creation needed.
# Now, method renamed to _cim_init_path_check_or_create().
# will return CIMInstanceName always.

2. The confliction error will be raise as CIMError in InvokeMethod()
command, not in _wait_invoke() method.
# Now, we do confliction check when error happened.
# Not check pre-excute, which can save some time for most legal use.

Changes in V2:
1. Thanks to Tony's detailed review, these issue fixed:
smis.py line 4906 & 4935, cim_init_mg_pros not defined
smis.py line 4916, out_init_id not defined

Signed-off-by: Gris Ge <***@redhat.com>
---
plugin/smispy/smis.py | 115 ++++++++++++++++++++++++++------------------------
1 file changed, 59 insertions(+), 56 deletions(-)

diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index a4122fc..c1ff5c3 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -148,6 +148,7 @@ def _lsm_init_id_to_snia(lsm_init_id):
return lsm_init_id.replace(':', '').upper()
return lsm_init_id

+
class DMTF(object):
# CIM_StorageHardwareID['IDType']
ID_TYPE_OTHER = pywbem.Uint16(1)
@@ -2865,23 +2866,15 @@ class Smis(IStorageAreaNetwork):

return search_property(rc, search_key, search_value)

- def _cim_init_check_or_create(self, cim_sys_path, init_id, init_type):
+ def _cim_init_path_check_or_create(self, cim_sys_path, init_id, init_type):
"""
Check whether CIM_StorageHardwareID exists, if not, create new one.
"""
cim_init = self._get_cim_instance_by_id(
- 'Initiator', init_id, raise_error=False, property_list=['IDType'])
+ 'Initiator', init_id, raise_error=False)

- # In rare chance, cim_init might holding different init_type
- # As ExposePaths is using init_id, hence we raise error instead of
- # creating new one
if cim_init:
- if _dmtf_init_type_to_lsm(cim_init) != init_type:
- raise LsmError(ErrorNumber.EXISTS_INITIATOR,
- "Another initiator exists with the same ID "
- "%s, but different init_type %d:" %
- (init_id, _dmtf_init_type_to_lsm(cim_init)))
- return cim_init
+ return cim_init.path

# Create new one
dmtf_id_type = _lsm_init_type_to_dmtf(init_type)
@@ -2890,14 +2883,13 @@ class Smis(IStorageAreaNetwork):
"SMI-S Plugin does not support init_type %d" %
init_type)

- cim_init = self._cim_init_create(
+ return self._cim_init_path_create(
cim_sys_path, init_id, dmtf_id_type)

- return cim_init
-
- def _cim_init_create(self, cim_sys_path, init_id, dmtf_id_type):
+ def _cim_init_path_create(self, cim_sys_path, init_id, dmtf_id_type):
"""
Create a CIM_StorageHardwareID.
+ Return CIMInstanceName
Raise error if failed. Return if pass.
"""
cim_hw_srv_path = self._get_cim_service_path(
@@ -2932,11 +2924,10 @@ class Smis(IStorageAreaNetwork):

# Check whether already added.
for exist_cim_init in exist_cim_inits:
- if self._init_id(exist_cim_init) == init_id and \
- _dmtf_init_type_to_lsm(exist_cim_init) == init_type:
- return copy.deepcopy(access_group)
+ if self._init_id(exist_cim_init) == init_id:
+ return copy.deepcopy(access_group)

- cim_init = self._cim_init_check_or_create(
+ cim_init_path = self._cim_init_path_check_or_create(
cim_sys.path, init_id, init_type)

cim_gmm_path = self._get_cim_service_path(
@@ -2944,7 +2935,7 @@ class Smis(IStorageAreaNetwork):

in_params = {
'MaskingGroup': cim_init_mg.path,
- 'Members': [cim_init.path],
+ 'Members': [cim_init_path],
}
(rc, out) = self._c.InvokeMethod('AddMembers',
cim_gmm_path, **in_params)
@@ -2991,19 +2982,12 @@ class Smis(IStorageAreaNetwork):

for exist_cim_init in exist_cim_inits:
if self._init_id(exist_cim_init) == init_id:
- if _dmtf_init_type_to_lsm(exist_cim_init) != init_type:
- raise LsmError(ErrorNumber.EXISTS_INITIATOR,
- "Another initiator exists with the same ID "
- "%s, but different init_type %d:" %
- (init_id,
- _dmtf_init_type_to_lsm(exist_cim_init)))
-
return copy.deepcopy(access_group)

# Check to see if we have this initiator already, if not we
# create it and then add to the view.

- self._cim_init_check_or_create(cim_sys.path, init_id, init_type)
+ self._cim_init_path_check_or_create(cim_sys.path, init_id, init_type)

cim_ccs_path = self._get_cim_service_path(
cim_sys.path, 'CIM_ControllerConfigurationService')
@@ -4892,44 +4876,63 @@ class Smis(IStorageAreaNetwork):
"iSCSI target port, which not allow creating "
"iSCSI IQN access group")

- cim_init = self._cim_init_check_or_create(
+ cim_init_path = self._cim_init_path_check_or_create(
cim_sys.path, init_id, init_type)

- cim_init_mg_pros = self._cim_init_mg_pros()
- exist_cim_init_mgs = self._c.Associators(
- cim_init.path,
- AssocClass='CIM_MemberOfCollection',
- ResultClass='CIM_InitiatorMaskingGroup',
- PropertyList=cim_init_mg_pros)
-
- if len(exist_cim_init_mgs) != 0:
- for exist_cim_init_mg in exist_cim_init_mgs:
- if exist_cim_init_mg['ElementName'] == name:
- return self._cim_init_mg_to_lsm(
- exist_cim_init_mg, system.id)
-
- # Name does not match.
- raise LsmError(ErrorNumber.EXISTS_INITIATOR,
- "Initiator %s already exist in other access group "
- % org_init_id +
- "with name %s and ID: %s" %
- (exist_cim_init_mgs[0]['ElementName'],
- md5(exist_cim_init_mgs[0]['DeviceID'])))
-
# Create CIM_InitiatorMaskingGroup
cim_gmm_path = self._get_cim_service_path(
cim_sys.path, 'CIM_GroupMaskingMappingService')

in_params = {'GroupName': name,
- 'Members': [cim_init.path],
+ 'Members': [cim_init_path],
'Type': DMTF.MASK_GROUP_TYPE_INIT}

- (rc, out) = self._c.InvokeMethod(
- 'CreateGroup', cim_gmm_path, **in_params)
+ cim_init_mg_pros = self._cim_init_mg_pros()

- cim_init_mg_path = self._wait_invoke(
- rc, out, out_key='MaskingGroup',
- expect_class='CIM_InitiatorMaskingGroup')
+ try:
+ (rc, out) = self._c.InvokeMethod(
+ 'CreateGroup', cim_gmm_path, **in_params)
+
+ cim_init_mg_path = self._wait_invoke(
+ rc, out, out_key='MaskingGroup',
+ expect_class='CIM_InitiatorMaskingGroup')
+
+ except (LsmError, CIMError):
+ # Check possible failure
+ # 1. Initiator already exist in other group.
+ # If that group hold the same name as requested.
+ # We consider as a duplicate call, return the exist one.
+ exist_cim_init_mgs = self._c.Associators(
+ cim_init_path,
+ AssocClass='CIM_MemberOfCollection',
+ ResultClass='CIM_InitiatorMaskingGroup',
+ PropertyList=cim_init_mg_pros)
+
+ if len(exist_cim_init_mgs) != 0:
+ for exist_cim_init_mg in exist_cim_init_mgs:
+ if exist_cim_init_mg['ElementName'] == name:
+ return self._cim_init_mg_to_lsm(
+ exist_cim_init_mg, system.id)
+
+ # Name does not match.
+ raise LsmError(ErrorNumber.EXISTS_INITIATOR,
+ "Initiator %s " % org_init_id +
+ "already exist in other access group "
+ "with name %s and ID: %s" %
+ (exist_cim_init_mgs[0]['ElementName'],
+ 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.
+ 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:
+ if exist_cim_init_mg['ElementName'] == name:
+ raise LsmError(ErrorNumber.EXISTS_ACCESS_GROUP,
+ "Requested name %s is used by " % name +
+ "another access group, but not containing "
+ "requested initiator %s" % org_init_id)
+ raise

cim_init_mg = self._c.GetInstance(
cim_init_mg_path, PropertyList=cim_init_mg_pros, LocalOnly=False)
--
1.8.3.1
Gris Ge
2014-08-04 14:41:28 UTC
Permalink
Enable OBS build:
1. Workaround for OBS bug 864323 by using one-line macro.
2. Move BuildRequires:python-argparse of libstoragemgmt-python to top
package. Required by OBS.
3. Show check log - test-suite.log if failed. Important when facing OBS
build failure. Thanks to libvirt:
http://www.redhat.com/archives/libvir-list/2013-July/msg01834.html

Signed-off-by: Gris Ge <***@redhat.com>
---
packaging/libstoragemgmt.spec.in | 47 ++++++++++++++++++++--------------------
1 file changed, 23 insertions(+), 24 deletions(-)

diff --git a/packaging/libstoragemgmt.spec.in b/packaging/libstoragemgmt.spec.in
index eaf9352..1693be9 100644
--- a/packaging/libstoragemgmt.spec.in
+++ b/packaging/libstoragemgmt.spec.in
@@ -1,19 +1,9 @@
%bcond_without rest_api

-%if 0%{?rhel} <= 6
-%global with_rest_api 0
-# RHEL 6 does not have libmicrohttpd in main repo, but in EPEL repo
-# Hence we disable REST API daemon compiling.
-# If EPEL6 is enabled, please use:
-# rpmbuild -ba libstoragemgmt.spec --with rest_api
-%endif
-
-%{?_with_rest_api:
-%global with_rest_api 1
-}
-%{?_without_rest_api:
-%global with_rest_api 0
-}
+# Use one-line macro for OBS workaround:
+# https://bugzilla.novell.com/show_bug.cgi?id=864323
+%{?_with_rest_api: %global with_rest_api 1 }
+%{?_without_rest_api: %global with_rest_api 0 }

Name: libstoragemgmt
Version: @VERSION@
@@ -25,19 +15,22 @@ URL: http://sourceforge.net/projects/libstoragemgmt/
Source0: http://sourceforge.net/projects/libstoragemgmt/files/libstoragemgmt-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
Requires: %{name}-python
-BuildRequires: autoconf automake libtool yajl-devel libxml2-devel check-devel openssl-devel
+BuildRequires: autoconf automake libtool yajl-devel libxml2-devel check-devel
+BuildRequires: openssl-devel
+BuildRequires: python-argparse
BuildRequires: glib2-devel
# Explicitly require gcc-c++ is for OBS
BuildRequires: gcc-c++

-# These buggy extra conditional BuildRequires is for OBS only,
-# Please refer to OBS bug:
-# https://bugzilla.novell.com/show_bug.cgi?id=864323
-%if 0%{?fedora} || 0%{?rhel} >= 7
-BuildRequires: libmicrohttpd-devel json-c-devel
+# For OBS only. OBS is still using RHEL/Centos 6.2 which does not have
+# OrderedDict from python collection. Use EPEL6 python-ordereddict.
+# These line is only for OBS SPEC parser, not for rpmbuild.
+%if 0%{?centos_version} == 600 || 0%{?rhel_version} == 600
+BuildRequires: python-ordereddict
+# redhat-release was not included in OBS. It provides %{rhel} macro.
+BuildRequires: redhat-release
%endif

-
%if 0%{?fedora} >= 15 || 0%{?rhel} >= 7
BuildRequires: systemd-units
Requires: initscripts
@@ -67,9 +60,11 @@ Summary: Python client libraries and plug-in support for %{name}
Group: System Environment/Libraries
Requires: %{name} = %{version}-%{release}
BuildArch: noarch
-%if 0%{?rhel} <= 6
Requires: python-argparse
-BuildRequires: python-argparse
+%if 0%{?rhel} == 6
+# No way to detect 6.2 yet. Just forcing all RHEL 6 to install
+# python-ordereddict just in case.
+Requires: python-ordereddict
%endif

%description python
@@ -195,7 +190,11 @@ install -m 755 tools/udev/scan-scsi-target \
rm -rf %{buildroot}

%check
-make check
+if ! make check
+then
+ cat test/test-suite.log || true
+ exit 1
+fi

%pre
getent group libstoragemgmt >/dev/null || groupadd -r libstoragemgmt
--
1.8.3.1
Gris Ge
2014-08-04 14:41:29 UTC
Permalink
1. Plush STDOUT on every logger call of lsmd daemon.
2. Change lsmd to systemd mode and save output to a tmp log file.
Useful to deubg daemon error and plugin error in OBS build where no way
to check syslog.
3. Fix a trivial typo:
export CK_export CK_FORK=no
4. Removed the 'tab' from runtest.sh which is mixing 'tab' and 'space'

Signed-off-by: Gris Ge <***@redhat.com>
---
daemon/lsm_daemon.c | 1 +
test/runtests.sh | 73 ++++++++++++++++++++++++++++-------------------------
2 files changed, 40 insertions(+), 34 deletions(-)

diff --git a/daemon/lsm_daemon.c b/daemon/lsm_daemon.c
index 923b66e..80e0064 100644
--- a/daemon/lsm_daemon.c
+++ b/daemon/lsm_daemon.c
@@ -107,6 +107,7 @@ void logger(int severity, const char *fmt, ...)
syslog(LOG_ERR, "%s", buf);
} else {
fprintf(stdout, "%s", buf);
+ fflush(stdout);
}

if( LOG_ERR == severity) {
diff --git a/test/runtests.sh b/test/runtests.sh
index 8faebb4..93b584e 100755
--- a/test/runtests.sh
+++ b/test/runtests.sh
@@ -23,7 +23,7 @@
export G_SLICE=always-malloc
export G_DEBUG=gc-friendly
export CK_DEFAULT_TIMEOUT=600
-export CK_export CK_FORK=no
+export CK_FORK=no

rundir=$RANDOM
base=/tmp/$rundir
@@ -33,35 +33,38 @@ LSMD_PID=65535
export LSM_TEST_RUNDIR=$rundir
export LSM_UDS_PATH=$base/lsm/ipc/

+LSMD_TMP_LOG_FILE="$base/lsmd.log"
+
cleanup() {
- #Clean up the daemon if it is running
- if [ $LSMD_PID -ne 65535 ]
- then
- kill -s INT $LSMD_PID
- fi
-
- if [ -e $LSM_UDS_PATH ]
- then
- rm -rf $base
- fi
-
- if [ -e $rootdir/_build ]
- then
- rm $lsm_py_folder/lsm/plugin
- rm $lsm_py_folder/lsm/lsmcli
- chmod -w $lsm_py_folder/lsm
- fi
+ #Clean up the daemon if it is running
+ if [ $LSMD_PID -ne 65535 ]
+ then
+ kill -s KILL $LSMD_PID
+ fi
+
+ cat $LSMD_TMP_LOG_FILE
+ if [ -e $LSM_UDS_PATH ]
+ then
+ rm -rf $base
+ fi
+
+ if [ -e $rootdir/_build ]
+ then
+ rm $lsm_py_folder/lsm/plugin
+ rm $lsm_py_folder/lsm/lsmcli
+ chmod -w $lsm_py_folder/lsm
+ fi
}

good() {
- echo "executing: $1"
- eval $1
- ec=$?
- if [ $ec -ne 0 ]; then
- echo "Fail exit[$ec]: $1"
- cleanup
- exit 1
- fi
+ echo "executing: $1"
+ eval $1
+ ec=$?
+ if [ $ec -ne 0 ]; then
+ echo "Fail exit[$ec]: $1"
+ cleanup
+ exit 1
+ fi
}

# Add a signal handler to clean-up
@@ -85,10 +88,10 @@ lsmcli_py_folder=$rootdir/tools/lsmcli

if [ -e $rootdir/_build ]
then
- c_unit=$rootdir/_build/test/tester
- LSMD_DAEMON=$rootdir/_build/daemon/lsmd
- shared_libs=$rootdir/_build/c_binding/.libs/
- bin_plugin=$rootdir/_build/plugin/simc/.libs/
+ c_unit=$rootdir/_build/test/tester
+ LSMD_DAEMON=$rootdir/_build/daemon/lsmd
+ shared_libs=$rootdir/_build/c_binding/.libs/
+ bin_plugin=$rootdir/_build/plugin/simc/.libs/
# In distcheck, all folder is read only(except _build and _inst).
# which prevent us from linking plugin and lsmcli into python/lsm folder.
chmod +w $rootdir/python_binding/lsm
@@ -133,17 +136,19 @@ good "find $rootdir/ \( ! -regex '.*/\..*' \) -type f -name \*_lsmplugin -exec c
good "cp $bin_plugin/*_lsmplugin $plugins"
good "ls -lh $plugins"

-
#Start daemon
-good "$LSMD_DAEMON --plugindir $plugins --socketdir $LSM_UDS_PATH" -v
+$LSMD_DAEMON \
+ --plugindir $plugins \
+ --socketdir $LSM_UDS_PATH \
+ -d >$LSMD_TMP_LOG_FILE &

LSMD_PID=$(ps aux | grep $LSM_UDS_PATH | grep -v grep | awk '{print $2}')

#Run C unit test
if [ -z "$LSM_VALGRIND" ]; then
- good "$c_unit"
+ good "$c_unit"
else
- good "valgrind --leak-check=full --show-reachable=no --log-file=/tmp/leaking_client $rootdir/test/.libs/tester"
+ good "valgrind --leak-check=full --show-reachable=no --log-file=/tmp/leaking_client $rootdir/test/.libs/tester"
fi

#Run cmdline against the simulator if we are not checking for leaks
--
1.8.3.1
Gris Ge
2014-08-04 14:41:30 UTC
Permalink
If we aren't doing the comand 'list', then self.args.type
is not present and we will throw an exception. Check
before use.

This was found when trying to run plugin-info without a uri
set.

Signed-off-by: Tony Asleson <***@redhat.com>
---
tools/lsmcli/cmdline.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/lsmcli/cmdline.py b/tools/lsmcli/cmdline.py
index 3f68d05..41bccda 100644
--- a/tools/lsmcli/cmdline.py
+++ b/tools/lsmcli/cmdline.py
@@ -1483,7 +1483,7 @@ class CmdLine:
# the same in all cases, even though it isn't technically
# required for the client library (static method)
# TODO: Make this not necessary.
- if (self.args.type == "PLUGINS"):
+ if ('type' in self.args and self.args.type == "PLUGINS"):
self.uri = "sim://"
self.password = None
else:
--
1.8.3.1
Gris Ge
2014-08-04 14:41:31 UTC
Permalink
More than once the call to lsm_capability_set_n has been done incorrectly
when adding or removing capabilities. Christophe offered this good suggestion:

"
Gris Ge
2014-08-04 14:41:32 UTC
Permalink
The 'simc://' and 'sim://' plugins are not sharing the same list of
UNSUPPORTED capabilities.

Before sync the behaviour of these two plugins, I would like to make test pass
by empty expected_absent capabilities check

Signed-off-by: Gris Ge <***@redhat.com>
---
test/tester.c | 20 --------------------
1 file changed, 20 deletions(-)

diff --git a/test/tester.c b/test/tester.c
index ac250c6..a910489 100644
--- a/test/tester.c
+++ b/test/tester.c
@@ -2097,26 +2097,6 @@ START_TEST(test_capability)
LSM_CAP_EXPORT_REMOVE};

lsm_capability_type expected_absent[] = {
- LSM_CAP_EXPORT_CUSTOM_PATH,
- LSM_CAP_POOL_CREATE,
- LSM_CAP_POOL_CREATE_FROM_DISKS,
- LSM_CAP_POOL_CREATE_FROM_POOL,
-
- LSM_CAP_POOL_CREATE_DISK_RAID_0,
- LSM_CAP_POOL_CREATE_DISK_RAID_1,
- LSM_CAP_POOL_CREATE_DISK_RAID_JBOD,
- LSM_CAP_POOL_CREATE_DISK_RAID_3,
- LSM_CAP_POOL_CREATE_DISK_RAID_4,
- LSM_CAP_POOL_CREATE_DISK_RAID_5,
- LSM_CAP_POOL_CREATE_DISK_RAID_6,
- LSM_CAP_POOL_CREATE_DISK_RAID_10,
- LSM_CAP_POOL_CREATE_DISK_RAID_50,
- LSM_CAP_POOL_CREATE_DISK_RAID_51,
- LSM_CAP_POOL_CREATE_DISK_RAID_60,
- LSM_CAP_POOL_CREATE_DISK_RAID_61,
- LSM_CAP_POOL_CREATE_DISK_RAID_15,
- LSM_CAP_POOL_CREATE_DISK_RAID_16,
- LSM_CAP_POOL_CREATE_DISK_RAID_NOT_APPLICABLE
};
--
1.8.3.1
Gris Ge
2014-08-04 14:41:33 UTC
Permalink
OrderedDict is only available in python 2.7.[1]
We use it from python-ordereddict package which is a backport version.

Tested on RHEL 6.2 which does not port OrderedDict from 2.7 yet.

Signed-off-by: Gris Ge <***@redhat.com>
---
tools/lsmcli/cmdline.py | 7 ++++++-
tools/lsmcli/data_display.py | 8 +++++++-
2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/tools/lsmcli/cmdline.py b/tools/lsmcli/cmdline.py
index 41bccda..04f2a3b 100644
--- a/tools/lsmcli/cmdline.py
+++ b/tools/lsmcli/cmdline.py
@@ -22,7 +22,12 @@ import getpass
import time
import tty
import termios
-from collections import OrderedDict
+
+try:
+ from collections import OrderedDict
+except ImportError:
+ # python 2.6 or earlier, use backport
+ from ordereddict import OrderedDict

from argparse import ArgumentParser
from argparse import RawTextHelpFormatter
diff --git a/tools/lsmcli/data_display.py b/tools/lsmcli/data_display.py
index a4d9629..e87186b 100644
--- a/tools/lsmcli/data_display.py
+++ b/tools/lsmcli/data_display.py
@@ -16,7 +16,13 @@
#
# Author: Gris Ge <***@redhat.com>
import sys
-from collections import OrderedDict
+
+try:
+ from collections import OrderedDict
+except ImportError:
+ # python 2.6 or earlier, use backport
+ from ordereddict import OrderedDict
+
from datetime import datetime

from lsm import (size_bytes_2_size_human, LsmError, ErrorNumber,
--
1.8.3.1
Gris Ge
2014-08-04 14:41:34 UTC
Permalink
* Removed these initiator types as no plugin is using them:
INIT_TYPE_WWNN (Python)
INIT_TYPE_HOSTNAME (Python)
INIT_TYPE_SAS (Python)
LSM_ACCESS_GROUP_INIT_TYPE_WWNN (C)
LSM_ACCESS_GROUP_INIT_TYPE_HOSTNAME (C)
LSM_ACCESS_GROUP_INIT_TYPE_SAS (C)

* Update plugins for above changes.

* Renamed this type in C API:
INIT_TYPE_ISCSI_WWPN_MIXED to LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_WWPN_MIXED

* Removed old initiator class in C API:
1. Renamed lsm_initiator_type to lsm_access_group_init_type
2. Removed lsm_plug_initiator_grant() method
3. Removed _lsm_initiator class.

* Fix incorrect parameter of lsm_iscsi_chap_auth:
initiator -> init_id

* Enabled iscsi_chap_auth test.

Signed-off-by: Gris Ge <***@redhat.com>
---
c_binding/include/libstoragemgmt/libstoragemgmt.h | 4 +-
.../libstoragemgmt/libstoragemgmt_plug_interface.h | 18 +------
.../include/libstoragemgmt/libstoragemgmt_types.h | 15 +-----
c_binding/lsm_datatypes.hpp | 12 -----
c_binding/lsm_mgmt.cpp | 6 +--
c_binding/lsm_plugin_ipc.cpp | 6 +--
plugin/sim/simarray.py | 9 +---
plugin/simc/simc_lsmplugin.c | 6 +--
plugin/smispy/smis.py | 29 +++++-----
python_binding/lsm/_data.py | 3 --
test/tester.c | 61 ++++++++++------------
tools/lsmcli/cmdline.py | 2 +-
tools/lsmcli/data_display.py | 3 --
13 files changed, 55 insertions(+), 119 deletions(-)

diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt.h b/c_binding/include/libstoragemgmt/libstoragemgmt.h
index 5345017..968bfdd 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt.h
@@ -523,7 +523,7 @@ extern "C" {
int LSM_DLL_EXPORT lsm_access_group_create(lsm_connect *conn,
const char *name,
const char *init_id,
- lsm_initiator_type init_type,
+ lsm_access_group_init_type init_type,
lsm_system *system,
lsm_access_group **access_group,
lsm_flag flags);
@@ -552,7 +552,7 @@ extern "C" {
int LSM_DLL_EXPORT lsm_access_group_initiator_add(lsm_connect *conn,
lsm_access_group *access_group,
const char *init_id,
- lsm_initiator_type init_type,
+ lsm_access_group_init_type init_type,
lsm_access_group **updated_access_group,
lsm_flag flags);

diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h b/c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h
index 71a6579..77f2ecb 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h
@@ -417,22 +417,6 @@ typedef int (*lsm_plug_volume_offline)(lsm_plugin_ptr c, lsm_volume *v,
lsm_flag flags);

/**
- * Grants access to an initiator for a specified volume, callback function signature
- * @param[in] c Valid lsm plug-in pointer
- * @param[in] initiator_id Initiator ID
- * @param[in] initiator_type Type of initiator
- * @param[in] volume Volume of interest
- * @param[in] access Desired access to volume
- * @param[in] flags Reserved
- * @return LSM_ERR_OK, else error reason
- */
-typedef int (*lsm_plug_initiator_grant)(lsm_plugin_ptr c, const char *initiator_id,
- lsm_initiator_type initiator_type,
- lsm_volume *volume,
- lsm_access_type access,
- lsm_flag flags);
-
-/**
* Setup the cap authentication for the specified initiator, callback
* function signature
* @param[in] c Valid lsm plug-in pointer
@@ -509,7 +493,7 @@ typedef int (*lsm_plug_access_group_delete)(lsm_plugin_ptr c,
typedef int (*lsm_plug_access_group_initiator_add)(lsm_plugin_ptr c,
lsm_access_group *access_group,
const char *initiator_id,
- lsm_initiator_type id_type,
+ lsm_access_group_init_type id_type,
lsm_access_group **updated_access_group,
lsm_flag flags);

diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt_types.h b/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
index 5180441..4d3b6bd 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
@@ -172,25 +172,12 @@ typedef enum {
#define LSM_SYSTEM_STATUS_OTHER 0x00000200 /**< Vendor specific */


-/**< \enum lsm_initiator_type Different types of initiator IDs */
-typedef enum {
- LSM_INITIATOR_OTHER = 1, /**< Other or unspecified */
- LSM_INITIATOR_PORT_WWN = 2, /**< World wide port name */
- LSM_INITIATOR_NODE_WWN = 3, /**< World wide node name */
- LSM_INITIATOR_HOSTNAME = 4, /**< Host name */
- LSM_INITIATOR_ISCSI = 5, /**< iSCSI IQN */
- LSM_INITIATOR_SAS = 7 /**< SAS ID */
-} lsm_initiator_type;
-
typedef enum {
LSM_ACCESS_GROUP_INIT_TYPE_UNKNOWN = 0, /**< Unknown */
LSM_ACCESS_GROUP_INIT_TYPE_OTHER = 1, /**< Something not seen before */
LSM_ACCESS_GROUP_INIT_TYPE_WWPN = 2, /**< Port name */
- LSM_ACCESS_GROUP_INIT_TYPE_WWNN = 3, /**< Node name */
- LSM_ACCESS_GROUP_INIT_TYPE_HOSTNAME = 4, /**< Host name */
LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_IQN = 5, /**< ISCSI IQN */
- LSM_ACCESS_GROUP_INIT_TYPE_SAS = 6, /**< SAS */
- INIT_TYPE_ISCSI_WWPN_MIXED = 7 /**< More than 1 type */
+ LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_WWPN_MIXED = 7 /**< More than 1 type */
} lsm_access_group_init_type;


diff --git a/c_binding/lsm_datatypes.hpp b/c_binding/lsm_datatypes.hpp
index 40f2935..00e2111 100644
--- a/c_binding/lsm_datatypes.hpp
+++ b/c_binding/lsm_datatypes.hpp
@@ -90,18 +90,6 @@ struct LSM_DLL_LOCAL _lsm_pool {
};


-#define LSM_INIT_MAGIC 0xAA7A0002
-#define LSM_IS_INIT(obj) MAGIC_CHECK(obj, LSM_INIT_MAGIC)
-/**
- * Information about an initiator.
- */
-struct LSM_DLL_LOCAL _lsm_initiator {
- uint32_t magic; /**< Used for verification */
- lsm_initiator_type id_type; /**< Type of id */
- char *id; /**< Identifier */
- char *name; /**< Initiator name */
-};
-
#define LSM_ACCESS_GROUP_MAGIC 0xAA7A0003
#define LSM_IS_ACCESS_GROUP(obj) MAGIC_CHECK(obj, LSM_ACCESS_GROUP_MAGIC)

diff --git a/c_binding/lsm_mgmt.cpp b/c_binding/lsm_mgmt.cpp
index c75ffd5..7ca71c0 100644
--- a/c_binding/lsm_mgmt.cpp
+++ b/c_binding/lsm_mgmt.cpp
@@ -1361,7 +1361,7 @@ int lsm_iscsi_chap_auth(lsm_connect *c, const char *init_id,
}

std::map<std::string, Value> p;
- p["initiator"] = Value(init_id);
+ p["init_id"] = Value(init_id);
p["in_user"] = Value(username);
p["in_password"] = Value(password);
p["out_user"] = Value(out_user);
@@ -1436,7 +1436,7 @@ int lsm_access_group_list(lsm_connect *c, const char *search_key,
}

int lsm_access_group_create(lsm_connect *c, const char *name,
- const char *init_id, lsm_initiator_type init_type,
+ const char *init_id, lsm_access_group_init_type init_type,
lsm_system *system,
lsm_access_group **access_group, lsm_flag flags)
{
@@ -1499,7 +1499,7 @@ int lsm_access_group_delete(lsm_connect *c, lsm_access_group *access_group,
int lsm_access_group_initiator_add(lsm_connect *c,
lsm_access_group *access_group,
const char *init_id,
- lsm_initiator_type init_type,
+ lsm_access_group_init_type init_type,
lsm_access_group **updated_access_group,
lsm_flag flags)
{
diff --git a/c_binding/lsm_plugin_ipc.cpp b/c_binding/lsm_plugin_ipc.cpp
index 8058158..68cbf44 100644
--- a/c_binding/lsm_plugin_ipc.cpp
+++ b/c_binding/lsm_plugin_ipc.cpp
@@ -1236,8 +1236,8 @@ static int ag_initiator_add(lsm_plugin_ptr p, Value &params, Value &response)
if( ag ) {
lsm_access_group *updated_access_group = NULL;
const char *id = v_init_id.asC_str();
- lsm_initiator_type id_type = (lsm_initiator_type)
- v_init_type.asInt32_t();
+ lsm_access_group_init_type id_type =
+ (lsm_access_group_init_type) v_init_type.asInt32_t();

rc = p->san_ops->ag_add_initiator(p, ag, id, id_type,
&updated_access_group,
@@ -2222,7 +2222,7 @@ static int iscsi_chap(lsm_plugin_ptr p, Value &params, Value &response)
int rc = LSM_ERR_NO_SUPPORT;

if( p && p->san_ops && p->san_ops->iscsi_chap_auth ) {
- Value v_init = params["initiator"];
+ Value v_init = params["init_id"];
Value v_in_user = params["in_user"];
Value v_in_password = params["in_password"];
Value v_out_user = params["out_user"];
diff --git a/plugin/sim/simarray.py b/plugin/sim/simarray.py
index b399b03..d59a1b1 100644
--- a/plugin/sim/simarray.py
+++ b/plugin/sim/simarray.py
@@ -640,8 +640,6 @@ class SimData(object):

self.ag_dict = {
}
- self.init_dict = {
- }
# Create some volumes, fs and etc
self.volume_create(
'POO1', 'Volume 000', size_human_2_size_bytes('200GiB'),
@@ -1189,12 +1187,7 @@ class SimData(object):

def iscsi_chap_auth(self, init_id, in_user, in_pass, out_user, out_pass,
flags=0):
- # to_code
- if self.init_dict[init_id]['init_type'] != \
- AccessGroup.INIT_TYPE_ISCSI_IQN:
- raise LsmError(ErrorNumber.NO_SUPPORT,
- "Initiator %s is not an iSCSI IQN" % init_id)
- # No iscsi chap query API yet
+ # No iscsi chap query API yet, not need to setup anything
return None

def fs(self):
diff --git a/plugin/simc/simc_lsmplugin.c b/plugin/simc/simc_lsmplugin.c
index 3f2d056..5a295f6 100644
--- a/plugin/simc/simc_lsmplugin.c
+++ b/plugin/simc/simc_lsmplugin.c
@@ -113,7 +113,7 @@ struct allocated_fs {

struct allocated_ag {
lsm_access_group *ag;
- lsm_initiator_type ag_type;
+ lsm_access_group_init_type ag_type;
};

struct plugin_data {
@@ -189,7 +189,7 @@ void free_allocated_job(void *j)
}

struct allocated_ag *alloc_allocated_ag( lsm_access_group *ag,
- lsm_initiator_type i)
+ lsm_access_group_init_type i)
{
struct allocated_ag *aag =
(struct allocated_ag *)malloc(sizeof(struct allocated_ag));
@@ -1228,7 +1228,7 @@ static int access_group_delete( lsm_plugin_ptr c,
static int access_group_initiator_add( lsm_plugin_ptr c,
lsm_access_group *group,
const char *initiator_id,
- lsm_initiator_type id_type,
+ lsm_access_group_init_type id_type,
lsm_access_group **updated_access_group,
lsm_flag flags)
{
diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index 88ae335..6299d1c 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -141,11 +141,8 @@ class DMTF(object):
# CIM_StorageHardwareID['IDType']
ID_TYPE_OTHER = pywbem.Uint16(1)
ID_TYPE_WWPN = pywbem.Uint16(2)
- ID_TYPE_WWNN = pywbem.Uint16(3)
- ID_TYPE_HOSTNAME = pywbem.Uint16(4)
ID_TYPE_ISCSI = pywbem.Uint16(5)
- ID_TYPE_SW_WWN = pywbem.Uint16(6)
- ID_TYPE_SAS = pywbem.Uint16(7)
+
TGT_PORT_USAGE_FRONTEND_ONLY = pywbem.Uint16(2)
TGT_PORT_USAGE_UNRESTRICTED = pywbem.Uint16(4)
# CIM_FCPort['PortDiscriminator']
@@ -193,17 +190,16 @@ class DMTF(object):
_INIT_TYPE_CONV = {
DMTF.ID_TYPE_OTHER: AccessGroup.INIT_TYPE_OTHER,
DMTF.ID_TYPE_WWPN: AccessGroup.INIT_TYPE_WWPN,
- DMTF.ID_TYPE_WWNN: AccessGroup.INIT_TYPE_WWNN,
- DMTF.ID_TYPE_HOSTNAME: AccessGroup.INIT_TYPE_HOSTNAME,
DMTF.ID_TYPE_ISCSI: AccessGroup.INIT_TYPE_ISCSI_IQN,
- DMTF.ID_TYPE_SW_WWN: AccessGroup.INIT_TYPE_OTHER,
- DMTF.ID_TYPE_SAS: AccessGroup.INIT_TYPE_SAS,
}


def _dmtf_init_type_to_lsm(cim_init):
- if 'IDType' in cim_init and cim_init['IDType'] in _INIT_TYPE_CONV.keys():
- return _INIT_TYPE_CONV[cim_init['IDType']]
+ if 'IDType' in cim_init:
+ if cim_init['IDType'] == DMTF.ID_TYPE_WWPN:
+ return AccessGroup.INIT_TYPE_WWPN
+ elif cim_init['IDType'] == DMTF.ID_TYPE_ISCSI:
+ return AccessGroup.INIT_TYPE_ISCSI_IQN
return AccessGroup.INIT_TYPE_UNKNOWN


@@ -225,13 +221,12 @@ def _lsm_tgt_port_type_of_cim_fc_tgt(cim_fc_tgt):


def _lsm_init_type_to_dmtf(init_type):
- # Invert dict. Assumes values are unique.
- try:
- inv_dict = dict((v, k) for k, v in _INIT_TYPE_CONV.iteritems())
- return inv_dict[init_type]
- except KeyError:
- raise LsmError(ErrorNumber.NO_SUPPORT,
- "Does not support provided init_type: %d" % init_type)
+ if init_type == AccessGroup.INIT_TYPE_WWPN:
+ return DMTF.ID_TYPE_WWPN
+ if init_type == AccessGroup.INIT_TYPE_ISCSI_IQN:
+ return DMTF.ID_TYPE_ISCSI
+ raise LsmError(ErrorNumber.NO_SUPPORT,
+ "Does not support provided init_type: %d" % init_type)


class SNIA(object):
diff --git a/python_binding/lsm/_data.py b/python_binding/lsm/_data.py
index ff5065f..70ee4da 100644
--- a/python_binding/lsm/_data.py
+++ b/python_binding/lsm/_data.py
@@ -650,10 +650,7 @@ class AccessGroup(IData):
INIT_TYPE_UNKNOWN = 0
INIT_TYPE_OTHER = 1
INIT_TYPE_WWPN = 2
- INIT_TYPE_WWNN = 3
- INIT_TYPE_HOSTNAME = 4
INIT_TYPE_ISCSI_IQN = 5
- INIT_TYPE_SAS = 6
INIT_TYPE_ISCSI_WWPN_MIXED = 7

def __init__(self, _id, _name, _init_ids, _init_type, _system_id,
diff --git a/test/tester.c b/test/tester.c
index a910489..a034e04 100644
--- a/test/tester.c
+++ b/test/tester.c
@@ -613,7 +613,8 @@ START_TEST(test_access_groups)
fail_unless(groups == NULL);

G(rc, lsm_access_group_create, c, "test_access_groups",
- "iqn.1994-05.com.domain:01.89bd01", LSM_INITIATOR_ISCSI, system,
+ "iqn.1994-05.com.domain:01.89bd01",
+ LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_IQN, system,
&group, LSM_FLAG_RSVD);

if( LSM_ERR_OK == rc ) {
@@ -655,7 +656,9 @@ START_TEST(test_access_groups)
char *job = NULL;
lsm_access_group *updated = NULL;

- rc = lsm_access_group_initiator_add(c, group, "iqn.1994-05.com.domain:01.89bd02", LSM_INITIATOR_ISCSI, &updated, LSM_FLAG_RSVD);
+ rc = lsm_access_group_initiator_add(c, group, "iqn.1994-05.com.domain:01.89bd02",
+ LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_IQN,
+ &updated, LSM_FLAG_RSVD);
fail_unless(LSM_ERR_OK == rc, "Expected success on lsmAccessGroupInitiatorAdd %d %d", rc, which_plugin);

G(rc, lsm_access_group_list, c, NULL, NULL, &groups, &count, LSM_FLAG_RSVD);
@@ -744,9 +747,10 @@ START_TEST(test_access_groups_grant_revoke)
system = get_system(c);

G(rc, lsm_access_group_create, c, "test_access_groups_grant_revoke",
- ISCSI_HOST[0], LSM_INITIATOR_ISCSI,
- system,
- &group, LSM_FLAG_RSVD);
+ ISCSI_HOST[0],
+ LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_IQN,
+ system,
+ &group, LSM_FLAG_RSVD);


int vc = lsm_volume_create(c, pool, "volume_grant_test", 20000000,
@@ -1528,12 +1532,12 @@ START_TEST(test_invalid_input)
rc = lsm_access_group_create(c, NULL, NULL, 0, system, NULL, LSM_FLAG_RSVD);
fail_unless(rc == LSM_ERR_INVALID_ARGUMENT, "rc = %d", rc);

- rc = lsm_access_group_create(c, "my_group", ISCSI_HOST[0], LSM_INITIATOR_OTHER,
+ rc = lsm_access_group_create(c, "my_group", ISCSI_HOST[0], LSM_ACCESS_GROUP_INIT_TYPE_OTHER,
NULL, NULL, LSM_FLAG_RSVD);
fail_unless(rc == LSM_ERR_INVALID_SYSTEM, "rc = %d", rc);


- rc = lsm_access_group_create(c, "my_group", ISCSI_HOST[0], LSM_INITIATOR_OTHER,
+ rc = lsm_access_group_create(c, "my_group", ISCSI_HOST[0], LSM_ACCESS_GROUP_INIT_TYPE_OTHER,
system, &ag, LSM_FLAG_RSVD);
fail_unless(rc == LSM_ERR_OK, "rc = %d", rc);
fail_unless(ag != NULL);
@@ -1925,45 +1929,35 @@ START_TEST(test_iscsi_auth_in)
{
lsm_access_group *group = NULL;
lsm_system *system = NULL;
- //char *job = NULL;
- int rc;
+ int rc = 0;

system = get_system(c);
+ printf("get_system() OK\n");

G(rc, lsm_access_group_create, c, "ISCSI_AUTH", ISCSI_HOST[0],
- LSM_INITIATOR_ISCSI, system, &group, LSM_FLAG_RSVD);
+ LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_IQN, system, &group, LSM_FLAG_RSVD);
+ printf("lsm_access_group_create() OK\n");

- fail_unless(LSM_ERR_OK == rc, "rc = %d");
+ fail_unless(LSM_ERR_OK == rc, "rc = %d", rc);
G(rc, lsm_system_record_free, system);
+ printf("lsm_system_record_free() OK\n");
+
system = NULL;

if( LSM_ERR_OK == rc ) {
- /* TODO FIX THIS UP after we take out the C initiator support.
- lsm_initiator **inits = NULL;
- uint32_t init_count = 0;
-

- rc = lsm_initiator_list(c, &inits, &init_count, LSM_FLAG_RSVD );
- fail_unless(LSM_ERR_OK == rc );
+ rc = lsm_iscsi_chap_auth(
+ c, ISCSI_HOST[0], "username", "secret", NULL, NULL,
+ LSM_FLAG_RSVD);

- if( LSM_ERR_OK == rc && init_count ) {
- rc = lsm_iscsi_chap_auth(c, inits[0], "username", "secret",
- NULL, NULL, LSM_FLAG_RSVD);
+ fail_unless(LSM_ERR_OK == rc, "rc = %d", rc);

- fail_unless(LSM_ERR_OK == rc, "rc = %d", rc) ;
- }
+ rc = lsm_access_group_delete(c, group, LSM_FLAG_RSVD);

- rc = lsm_access_group_delete(c, group, LSM_FLAG_RSVD);
+ fail_unless(LSM_ERR_OK == rc );

- if(LSM_ERR_JOB_STARTED == rc ) {
- wait_for_job(c, &job);
- } else {
- fail_unless(LSM_ERR_OK == rc );
- }
- */
-
- lsm_access_group_record_free(group);
- group = NULL;
+ lsm_access_group_record_free(group);
+ group = NULL;
}
}
END_TEST
@@ -2666,7 +2660,8 @@ START_TEST(test_search_access_groups)
snprintf(ag_name, sizeof(ag_name), "test_access_group_%d", i);

G(rc, lsm_access_group_create, c, ag_name, ISCSI_HOST[i],
- LSM_INITIATOR_ISCSI, system, &group, LSM_FLAG_RSVD);
+ LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_IQN,
+ system, &group, LSM_FLAG_RSVD);

if( LSM_ERR_OK == rc ) {
G(rc, lsm_access_group_record_free, group);
diff --git a/tools/lsmcli/cmdline.py b/tools/lsmcli/cmdline.py
index 04f2a3b..96b3fbe 100644
--- a/tools/lsmcli/cmdline.py
+++ b/tools/lsmcli/cmdline.py
@@ -109,7 +109,7 @@ list_choices = ['VOLUMES', 'POOLS', 'FS', 'SNAPSHOTS',
'EXPORTS', "NFS_CLIENT_AUTH", 'ACCESS_GROUPS',
'SYSTEMS', 'DISKS', 'PLUGINS', 'TARGET_PORTS']

-init_types = ('WWPN', 'WWNN', 'ISCSI', 'HOSTNAME', 'SAS')
+init_types = ('WWPN', 'ISCSI')
init_id_help = "Access Group Initiator type: " + \
", ".join(init_types)

diff --git a/tools/lsmcli/data_display.py b/tools/lsmcli/data_display.py
index e87186b..9a18cd5 100644
--- a/tools/lsmcli/data_display.py
+++ b/tools/lsmcli/data_display.py
@@ -289,10 +289,7 @@ _AG_INIT_TYPE_CONV = {
AccessGroup.INIT_TYPE_UNKNOWN: 'Unknown',
AccessGroup.INIT_TYPE_OTHER: 'Other',
AccessGroup.INIT_TYPE_WWPN: 'WWPN',
- AccessGroup.INIT_TYPE_WWNN: 'WWNN',
- AccessGroup.INIT_TYPE_HOSTNAME: 'Hostname',
AccessGroup.INIT_TYPE_ISCSI_IQN: 'iSCSI',
- AccessGroup.INIT_TYPE_SAS: 'SAS',
AccessGroup.INIT_TYPE_ISCSI_WWPN_MIXED: 'iSCSI/WWPN Mixed',
}
--
1.8.3.1
Gris Ge
2014-08-04 14:41:35 UTC
Permalink
1. Forcing user to input WWPN in this format:
10:00:00:00:c9:95:2f:de

2. Add methods to lsm.AccessGroup:
AccessGroup.init_id_validate()
AccessGroup.wwpn_to_lsm_type()

3. Rename INVALID_IQN to INVALID_INIT

Signed-off-by: Gris Ge <***@redhat.com>
---
python_binding/lsm/_client.py | 4 ++
python_binding/lsm/_common.py | 2 +-
python_binding/lsm/_data.py | 96 ++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 99 insertions(+), 3 deletions(-)

diff --git a/python_binding/lsm/_client.py b/python_binding/lsm/_client.py
index 61a7aa2..00b9184 100644
--- a/python_binding/lsm/_client.py
+++ b/python_binding/lsm/_client.py
@@ -427,6 +427,8 @@ class Client(INetworkAttachedStorage):
Register a user/password for the specified initiator for CHAP
authentication.
"""
+ AccessGroup.init_id_validate(
+ init_id, AccessGroup.INIT_TYPE_ISCSI_IQN, raise_error=True)
return self._tp.rpc('iscsi_chap_auth', _del_self(locals()))

## Returns an array of volume objects
@@ -652,6 +654,7 @@ class Client(INetworkAttachedStorage):
Creates an access group and add the specified initiator id,
init_type and desired access.
"""
+ AccessGroup.init_id_validate(init_id, init_type, raise_error=True)
return self._tp.rpc('access_group_create', _del_self(locals()))

## Deletes an access group.
@@ -679,6 +682,7 @@ class Client(INetworkAttachedStorage):
"""
Adds an initiator to an access group
"""
+ AccessGroup.init_id_validate(init_id, init_type, raise_error=True)
return self._tp.rpc('access_group_initiator_add', _del_self(locals()))

## Deletes an initiator from an access group
diff --git a/python_binding/lsm/_common.py b/python_binding/lsm/_common.py
index fdd10ab..386d9a9 100644
--- a/python_binding/lsm/_common.py
+++ b/python_binding/lsm/_common.py
@@ -455,7 +455,7 @@ class ErrorNumber(object):
INVALID_VOLUME = 115
INVALID_CAPABILITY = 116
INVALID_SYSTEM = 117
- INVALID_IQN = 118
+ INVALID_INIT = 118
INVALID_DISK = 119
INVALID_BLOCK_RANGE = 121

diff --git a/python_binding/lsm/_data.py b/python_binding/lsm/_data.py
index 70ee4da..8b70565 100644
--- a/python_binding/lsm/_data.py
+++ b/python_binding/lsm/_data.py
@@ -17,6 +17,7 @@
# Gris Ge <***@redhat.com>

from abc import ABCMeta as _ABCMeta
+import re

try:
import simplejson as json
@@ -24,7 +25,7 @@ except ImportError:
import json

from json.decoder import WHITESPACE
-from _common import get_class, default_property
+from _common import get_class, default_property, ErrorNumber


class DataEncoder(json.JSONEncoder):
@@ -657,11 +658,102 @@ class AccessGroup(IData):
_plugin_data=None):
self._id = _id
self._name = _name # AccessGroup name
- self._init_ids = _init_ids # List of initiator IDs
+ self._init_ids = _init_ids # A list of Initiator ID strings.
self._init_type = _init_type
self._system_id = _system_id # System id this group belongs
self._plugin_data = _plugin_data

+ # Regex for LSM format of WWPN, example:
+ # 10:00:00:00:c9:95:2f:de
+ _regex_lsm_wwpn = re.compile(r"""
+ ^
+ (?:[0-9a-f]{2}:){7}
+ [0-9a-f]{2}
+ $
+ """, re.X)
+
+ _regex_iscsi_iqn = re.compile(r"""
+ ^
+ iqn # iqn
+ \. # .
+ [0-9]{4}-[0-9]{2} # 1995-02
+ \. # .
+ [A-Za-z](?:[A-Za-z0-9\-]*[A-Za-z0-9])? # com
+ \. # .
+ [A-Za-z](?:[A-Za-z0-9\-]*[A-Za-z0-9])? # redhat
+ : # :
+ [\.A-Za-z\-0-9]+ # gris-01
+ $
+ """, re.X)
+
+ @staticmethod
+ def init_id_validate(init_id, init_type, raise_error=True):
+ if init_type == AccessGroup.INIT_TYPE_ISCSI_IQN:
+ if AccessGroup._regex_iscsi_iqn.match(str(init_id)):
+ return True
+ if raise_error:
+ raise LsmError(ErrorNumber.INVALID_INIT,
+ "Invalid iSCSI IQN Initiator: %s" % init_id)
+ return False
+ elif init_type == AccessGroup.INIT_TYPE_WWPN:
+ if AccessGroup._regex_lsm_wwpn.match(str(init_id)):
+ return True
+ if raise_error:
+ raise LsmError(ErrorNumber.INVALID_INIT,
+ "Invalid WWPN Initiator: %s" % init_id)
+ return False
+ elif raise_error:
+ raise LsmError(ErrorNumber.NO_SUPPORT,
+ "Initiator type %d not supported" % init_type)
+ return False
+
+ _regex_wwpn = re.compile(r"""
+ ^
+ [0x|0X]{0,1}
+ (:?[0-9A-Fa-f]{2}
+ [\.\-:]{0,1}){7}
+ [0-9A-Fa-f]{2}
+ $
+ """, re.X)
+
+ @staticmethod
+ def wwpn_to_lsm_type(wwpn, raise_error=True):
+ """
+ Conver provided WWPN string into LSM standarded one:
+
+ LSM WWPN format:
+ ^(?:[0-9a-f]{2}:){7}[0-9a-f]{2}$
+ LSM WWPN Example:
+ 10:00:00:00:c9:95:2f:de
+
+ Acceptable WWPN format is:
+ ^[0x|0X]{0,1}(:?[0-9A-Fa-f]{2}[\.\-:]{0,1}){7}[0-9A-Fa-f]{2}$
+ Acceptable WWPN example:
+ 10:00:00:00:c9:95:2f:de
+ 10:00:00:00:C9:95:2F:DE
+ 10-00-00-00-C9-95-2F-DE
+ 10-00-00-00-c9-95-2f-de
+ 10.00.00.00.C9.95.2F.DE
+ 10.00.00.00.c9.95.2f.de
+ 0x10000000c9952fde
+ 0X10000000C9952FDE
+ 10000000c9952fde
+ 10000000C9952FDE
+ Return the LSM WWPN
+ Return None if raise_error is False and not a valid WWPN.
+ """
+ if AccessGroup._regex_wwpn.match(str(wwpn)):
+ s = str(wwpn)
+ s = s.lower()
+ s = re.sub(r'0x', '', s)
+ s = re.sub(r'[^0-9a-f]', '', s)
+ s = ":".join(re.findall(r'..', s))
+ return s
+ if raise_error:
+ raise LsmError(ErrorNumber.INVALID_INIT,
+ "Invalid WWPN Initiator: %s" % wwpn)
+ return None
+

@default_property('id', doc="Unique instance identifier")
@default_property('port_type', doc="Target port type")
--
1.8.3.1
Tony Asleson
2014-08-04 20:35:30 UTC
Permalink
Gris,

Some parts of patch are missing. Please re-email the series.

Thanks,
Tony
Post by Gris Ge
I combined tony's patches with my V2 patches.
1. Fix bugs found by OBS compile.
2. Change rpm spec and etc to support OBS build.
3. Access Group WWPN form.
4. Clean up AccessGroup.
5. Fix bugs of SMI-S plugin about access group.
https://build.opensuse.org/project/monitor/home:cathay4t:libstoragemgmt-test
rpm spec: fix for OBS build
test: allowing runtest to show log of lsmd
test: empty expected_absent capabilities check
lsmcli: use python-ordereddict for python <= 2.6
Remove INIT_TYPE_WWNN and etc unused initiator type
Python API: standardize the WWPN
C API: Rename LSM_ERR_INVALID_IQN to LSM_ERR_INVALID_INIT
lsmcli: Remove --init-type argument
ontap plugin: Rename INVALID_IQN to INVALID_INIT
SMI-S plugin: standardize the WWPN
SMI-S plugin: Fix access group bugs
Remove v7k plugin
cmdline.py: Check before reference
C API: Simplify lsm_capability_set_n
c_binding/include/libstoragemgmt/libstoragemgmt.h | 4 +-
.../libstoragemgmt/libstoragemgmt_capabilities.h | 2 +
.../include/libstoragemgmt/libstoragemgmt_error.h | 3 +-
.../libstoragemgmt/libstoragemgmt_plug_interface.h | 25 +-
.../include/libstoragemgmt/libstoragemgmt_types.h | 15 +-
c_binding/lsm_datatypes.cpp | 28 +-
c_binding/lsm_datatypes.hpp | 12 -
c_binding/lsm_mgmt.cpp | 6 +-
c_binding/lsm_plugin_ipc.cpp | 6 +-
configure.ac | 15 -
daemon/lsm_daemon.c | 1 +
doc/man/lsmcli.1.in | 12 +-
packaging/libstoragemgmt.spec.in | 88 ++---
plugin/Makefile.am | 9 -
plugin/ontap/ontap.py | 2 +-
plugin/sim/simarray.py | 9 +-
plugin/simc/simc_lsmplugin.c | 11 +-
plugin/smispy/smis.py | 222 +++++++------
plugin/v7k/__init__.py | 0
plugin/v7k/ibmv7k.py | 364 ---------------------
plugin/v7k/v7k_lsmplugin | 36 --
python_binding/lsm/_client.py | 4 +
python_binding/lsm/_common.py | 2 +-
python_binding/lsm/_data.py | 99 +++++-
test/cmdtest.py | 7 +-
test/runtests.sh | 73 +++--
test/tester.c | 86 ++---
tools/lsmcli/cmdline.py | 61 ++--
tools/lsmcli/data_display.py | 11 +-
29 files changed, 388 insertions(+), 825 deletions(-)
delete mode 100644 plugin/v7k/__init__.py
delete mode 100644 plugin/v7k/ibmv7k.py
delete mode 100755 plugin/v7k/v7k_lsmplugin
Gris Ge
2014-08-04 22:54:55 UTC
Permalink
I combined tony's patches with my V2 patches.

This patch set contains:
1. Fix bugs found by OBS compile.
2. Change rpm spec and etc to support OBS build.
3. Access Group WWPN form.
4. Clean up AccessGroup.
5. Fix bugs of SMI-S plugin about access group.

Tested by 'make check' by OBS:
https://build.opensuse.org/project/monitor/home:cathay4t:libstoragemgmt-test

Gris Ge (11):
rpm spec: fix for OBS build
test: allowing runtest to show log of lsmd
test: empty expected_absent capabilities check
lsmcli: use python-ordereddict for python <= 2.6
Remove INIT_TYPE_WWNN and etc unused initiator type
Python API: standardize the WWPN
C API: Rename LSM_ERR_INVALID_IQN to LSM_ERR_INVALID_INIT
lsmcli: Remove --init-type argument
ontap plugin: Rename INVALID_IQN to INVALID_INIT
SMI-S plugin: standardize the WWPN
SMI-S plugin: Fix access group bugs

Tony Asleson(3):
Remove v7k plugin
cmdline.py: Check before reference
C API: Simplify lsm_capability_set_n


c_binding/include/libstoragemgmt/libstoragemgmt.h | 4 +-
.../libstoragemgmt/libstoragemgmt_capabilities.h | 2 +
.../include/libstoragemgmt/libstoragemgmt_error.h | 3 +-
.../libstoragemgmt/libstoragemgmt_plug_interface.h | 25 +-
.../include/libstoragemgmt/libstoragemgmt_types.h | 15 +-
c_binding/lsm_datatypes.cpp | 28 +-
c_binding/lsm_datatypes.hpp | 12 -
c_binding/lsm_mgmt.cpp | 6 +-
c_binding/lsm_plugin_ipc.cpp | 6 +-
configure.ac | 15 -
daemon/lsm_daemon.c | 1 +
doc/man/lsmcli.1.in | 12 +-
packaging/libstoragemgmt.spec.in | 88 ++---
plugin/Makefile.am | 9 -
plugin/ontap/ontap.py | 2 +-
plugin/sim/simarray.py | 9 +-
plugin/simc/simc_lsmplugin.c | 11 +-
plugin/smispy/smis.py | 222 +++++++------
plugin/v7k/__init__.py | 0
plugin/v7k/ibmv7k.py | 364 ---------------------
plugin/v7k/v7k_lsmplugin | 36 --
python_binding/lsm/_client.py | 4 +
python_binding/lsm/_common.py | 2 +-
python_binding/lsm/_data.py | 99 +++++-
test/cmdtest.py | 7 +-
test/runtests.sh | 73 +++--
test/tester.c | 86 ++---
tools/lsmcli/cmdline.py | 61 ++--
tools/lsmcli/data_display.py | 11 +-
29 files changed, 388 insertions(+), 825 deletions(-)
delete mode 100644 plugin/v7k/__init__.py
delete mode 100644 plugin/v7k/ibmv7k.py
delete mode 100755 plugin/v7k/v7k_lsmplugin
--
1.8.3.1
Gris Ge
2014-08-04 22:54:56 UTC
Permalink
This plugin is being removed for the following reasons:

1. No hardware to test it on
2. Plugin is not feature complete
3. SMI-S plugin at this point should offer a better experience
for the user

We can certainly bring it back if needed.

Signed-off-by: Tony Asleson <***@redhat.com>
---
configure.ac | 15 --
packaging/libstoragemgmt.spec.in | 41 -----
plugin/Makefile.am | 9 -
plugin/v7k/__init__.py | 0
plugin/v7k/ibmv7k.py | 364 ---------------------------------------
plugin/v7k/v7k_lsmplugin | 36 ----
6 files changed, 465 deletions(-)
delete mode 100644 plugin/v7k/__init__.py
delete mode 100644 plugin/v7k/ibmv7k.py
delete mode 100755 plugin/v7k/v7k_lsmplugin

diff --git a/configure.ac b/configure.ac
index b200078..cbf668b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -136,16 +136,6 @@ fi
AM_CONDITIONAL([BUILD_C_UNIT], [test "x${want_c_unit}" = "xyes"])

dnl ==========================================================================
-dnl Check to see if user wants to exclude code that depends on python-paramiko
-dnl ==========================================================================
-
-AC_ARG_WITH([paramiko],
- [AS_HELP_STRING([--without-paramiko], [Remove paramiko requirement and disables code which uses it, eg. IBM7K Plugin])],
- [], [with_paramiko="yes"])
-
-AM_CONDITIONAL([HAVE_PARAMIKO], [test "x${with_paramiko}" = "xyes"])
-
-dnl ==========================================================================
dnl Check for python as it is needed for the base cmd line function
dnl ==========================================================================

@@ -154,11 +144,6 @@ AC_PYTHON_MODULE([pywbem], [Required])
AC_PYTHON_MODULE([M2Crypto], [Required])
AC_PYTHON_MODULE([argparse], [Required])

-
-if test "x${with_paramiko}" = "xyes"; then
- AC_PYTHON_MODULE([paramiko], [Required])
-fi
-
dnl ==========================================================================
dnl Check for libmicrohttpd and json-c as it is needed for REST API daemon
dnl ==========================================================================
diff --git a/packaging/libstoragemgmt.spec.in b/packaging/libstoragemgmt.spec.in
index 2048da8..eaf9352 100644
--- a/packaging/libstoragemgmt.spec.in
+++ b/packaging/libstoragemgmt.spec.in
@@ -1,5 +1,4 @@
%bcond_without rest_api
-%bcond_without ibm_v7k

%if 0%{?rhel} <= 6
%global with_rest_api 0
@@ -9,22 +8,12 @@
# rpmbuild -ba libstoragemgmt.spec --with rest_api
%endif

-%if 0%{?rhel} >= 7
-%global with_ibm_v7k 0
-%endif
-
%{?_with_rest_api:
%global with_rest_api 1
}
%{?_without_rest_api:
%global with_rest_api 0
}
-%{?_with_ibm_v7k:
-%global with_ibm_v7k 1
-}
-%{?_without_ibm_v7k:
-%global with_ibm_v7k 0
-}

Name: libstoragemgmt
Version: @VERSION@
@@ -44,9 +33,6 @@ BuildRequires: gcc-c++
# These buggy extra conditional BuildRequires is for OBS only,
# Please refer to OBS bug:
# https://bugzilla.novell.com/show_bug.cgi?id=864323
-%if 0%{?fedora} || 0%{?rhel} <= 6
-BuildRequires: python-paramiko
-%endif
%if 0%{?fedora} || 0%{?rhel} >= 7
BuildRequires: libmicrohttpd-devel json-c-devel
%endif
@@ -129,21 +115,6 @@ The %{name}-targetd-plugin package contains plug-in for targetd array
support.


-%if 0%{?with_ibm_v7k}
-%package ibm-v7k-plugin
-Summary: Files for IBM v7k array support for %{name}
-Group: System Environment/Libraries
-Requires: python-paramiko %{name}-python
-Requires: libstoragemgmt-python = %{version}-%{release}
-BuildRequires: python-paramiko
-BuildArch: noarch
-
-%description ibm-v7k-plugin
-The %{name}-ibm-v7k-plugin package contains plug-in for IBM v7k array
-support.
-%endif
-
-
%package nstor-plugin
Summary: Files for NexentaStor array support for %{name}
Group: System Environment/Libraries
@@ -183,9 +154,6 @@ the %{name}-rest package contains the http daemon for %{name} rest api.

#Tell the install program to preserve file date/timestamps
%configure \
-%if 0%{?with_ibm_v7k} != 1
- --without-paramiko \
-%endif
%if 0%{?with_rest_api} != 1
--without-rest-api \
%endif
@@ -362,15 +330,6 @@ fi
%{python_sitelib}/lsm/plugin/targetd/targetd.*
%{_bindir}/targetd_lsmplugin

-
-%if 0%{?with_ibm_v7k}
-%files ibm-v7k-plugin
-%defattr(-,root,root,-)
-%{python_sitelib}/lsm/plugin/v7k/__init__.*
-%{python_sitelib}/lsm/plugin/v7k/ibmv7k.*
-%{_bindir}/v7k_lsmplugin
-%endif
-
%files nstor-plugin
%defattr(-,root,root,-)
%{python_sitelib}/lsm/plugin/nstor/__init__.*
diff --git a/plugin/Makefile.am b/plugin/Makefile.am
index a8f43da..96a243a 100644
--- a/plugin/Makefile.am
+++ b/plugin/Makefile.am
@@ -39,12 +39,3 @@ dist_bin_SCRIPTS= \
nstor/nstor_lsmplugin \
ontap/ontap_lsmplugin \
targetd/targetd_lsmplugin
-
-if HAVE_PARAMIKO
-v7kdir = $(plugindir)/v7k
-v7k_PYTHON = \
- v7k/__init__.py \
- v7k/ibmv7k.py
-
-dist_bin_SCRIPTS += v7k/v7k_lsmplugin
-endif
diff --git a/plugin/v7k/__init__.py b/plugin/v7k/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/plugin/v7k/ibmv7k.py b/plugin/v7k/ibmv7k.py
deleted file mode 100644
index 7a0c2d6..0000000
--- a/plugin/v7k/ibmv7k.py
+++ /dev/null
@@ -1,364 +0,0 @@
-# Copyright (C) 2013 IBM Corporation
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-#
-# Author: Deepak C Shetty (***@linux.vnet.ibm.com)
-
-import paramiko
-
-from lsm import (Capabilities, ErrorNumber, IStorageAreaNetwork,
- LsmError, Pool, System, VERSION, Volume, uri_parse,
- search_property, AccessGroup)
-
-
-def handle_ssh_errors(method):
- def ssh_wrapper(*args, **kwargs):
- try:
- return method(*args, **kwargs)
- except paramiko.SSHException as sshe:
- raise LsmError(ErrorNumber.TRANSPORT_COMMUNICATION, str(sshe))
-
- return ssh_wrapper
-
-
-class V7kError(Exception):
- """
- Class represents a v7k cli bad return code
- """
-
- def __init__(self, errno, reason, *args, **kwargs):
- Exception.__init__(self, *args, **kwargs)
- self.errno = errno
- self.reason = reason
-
-
-# NOTE: v7k cli doc doesn't list the possible error codes per cli.
-# Thus do very generic and basic error handling for now.
-# Just pass the error msg & code returned by the array back to lsm.
-def handle_v7k_errors(method):
- def v7k_wrapper(*args, **kwargs):
- try:
- return method(*args, **kwargs)
- except V7kError as ve:
- msg = ve.reason + " (vendor error code= " + str(ve.errno) + ")"
- raise LsmError(ErrorNumber.PLUGIN_ERROR, msg)
-
- return v7k_wrapper
-
-
-# A lite weight sshclient
-class SSHClient():
-
- @handle_ssh_errors
- def __init__(self, hostname, login, passwd, conn_timeout=30):
- self.ssh = paramiko.SSHClient()
- self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
-
- try:
- self.ssh.connect(hostname, username=login, password=passwd,
- timeout=conn_timeout)
- except Exception as e:
- msg = "Error while connecting via ssh to host %s : %s" % \
- (hostname, e)
- raise paramiko.SSHException(msg)
-
- @handle_v7k_errors
- def execute(self, command, check_exit_code=True):
- stdin_strm, stdout_strm, stderr_strm = self.ssh.exec_command(command)
-
- stdin_strm.close()
-
- stdout_channel = stdout_strm.channel
- exit_code = stdout_channel.recv_exit_status()
- stdout_channel.close()
-
- stdout = stdout_strm.read()
- stdout_strm.close()
-
- stderr = stderr_strm.read()
- stderr_strm.close()
-
- if check_exit_code and exit_code != 0:
- error_list = stderr.split(' ', 1)
-
- if exit_code == 127:
- # command not found error
- errno = exit_code
- else:
- # other errors
- errno = error_list[0]
-
- reason = error_list[1]
-
- raise V7kError(errno, reason)
-
- return exit_code, stdout, stderr
-
- @handle_ssh_errors
- def close(self):
- self.ssh.close()
-
-
-# IBM V7000 storage lsm plugin
-
-# *** lsm -- IBM V7000 terminology mapping ***
-# volume -- v7k volume (aka vdisk)
-# initiator -- host
-# access group -- NA
-# NA -- I/O group
-# pool -- mdisk group
-# volume-child dep -- ~fcmap and other maps if any
-# job -- cli that can be invoked in async mode
-
-class IbmV7k(IStorageAreaNetwork):
-
- def __init__(self):
- self.sys_info = None
- self.ssh = None
- self.tmo = 0
- self.password = None
- self.up = None
-
- def _execute_command(self, ssh_cmd):
- exit_code, stdout, stderr = self.ssh.execute(ssh_cmd)
- return exit_code, stdout, stderr
-
- def _execute_command_and_parse_detailed(self, ssh_cmd):
- exit_code, stdout, stderr = self.ssh.execute(ssh_cmd)
-
- cmd_output = {}
- if not len(stdout.strip()):
- return cmd_output
-
- output_lines = stdout.split('\n')
- if not len(output_lines):
- return cmd_output
-
- for line in output_lines:
- name, foo, value = line.partition('!')
- if name is not None and len(name.strip()):
- cmd_output[name] = value
-
- return cmd_output
-
- def _execute_command_and_parse_concise(self, ssh_cmd):
- # This assume -nohdr is *not* present in ssh_cmd
- exit_code, stdout, stderr = self.ssh.execute(ssh_cmd)
-
- cmd_output = {}
- if not len(stdout.strip()):
- return cmd_output
-
- output_lines = stdout.split('\n')
- if not len(output_lines):
- return cmd_output
-
- header_line = output_lines[0]
- keylist = header_line.split('!')
-
- # For some reason, concise output gives one extra blank line at the end
- attrib_lines = output_lines[1:-1]
- lineindex = 0
-
- for attrib_line in attrib_lines:
- valuelist = attrib_line.split('!')
- attributes = {}
- valueindex = 0
- for key in keylist:
- attributes[key] = valuelist[valueindex]
- valueindex += 1
-
- cmd_output[lineindex] = attributes
- lineindex += 1
-
- return cmd_output
-
- def _get_system_info(self):
- ssh_cmd = 'lssystem -delim !'
- return self._execute_command_and_parse_detailed(ssh_cmd)
-
- def _get_pools(self):
- ssh_cmd = 'lsmdiskgrp -bytes -delim !'
- return self._execute_command_and_parse_concise(ssh_cmd)
-
- def _pool(self, p):
- return Pool(p['id'], p['name'], Pool.ELEMENT_TYPE_VOLUME,
- int(p['capacity']),
- int(p['free_capacity']), Pool.STATUS_UNKNOWN, '',
- self.sys_info.id)
-
- def _get_volumes(self):
- ssh_cmd = 'lsvdisk -bytes -delim !'
- return self._execute_command_and_parse_concise(ssh_cmd)
-
- def _get_volume(self, volume):
- ssh_cmd = 'lsvdisk -bytes -delim ! %s' % volume
- return self._execute_command_and_parse_detailed(ssh_cmd)
-
- def _volume(self, v):
- # v7k support 512 bytes/sec only, as the phy drive bs.
- # Its a bit complicated to reverse map v7k volume to
- # phy drive using the cli, so for now hardcode it as
- # thats the only supported bs at the drive level.
- bs = 512
-
- if v['status'] == 'online':
- vol_status = Volume.STATUS_OK
- elif v['status'] == 'offline':
- vol_status = Volume.STATUS_DORMANT
- else:
- vol_status = Volume.STATUS_ERR
-
- return Volume(v['id'], v['name'], v['vdisk_UID'], bs,
- (float(v['capacity']) / bs), vol_status,
- self.sys_info.id, v['mdisk_grp_id'])
-
- def _create_volume(self, pool, vol_name, size_bytes, prov):
- ssh_cmd = ('mkvdisk -name %s -mdiskgrp %s -iogrp 0 -size %s'
- ' -unit b') % (vol_name, pool, size_bytes)
-
- if prov == Volume.PROVISION_THIN:
- # Defaults for thinp
- rsize = 5
- warning = 0
- autoex = '-autoexpand'
-
- ssh_cmd += ' -rsize %d%% -warning %d %s' % \
- (rsize, warning, autoex)
-
- exit_code, stdout, stderr = self.ssh.execute(ssh_cmd)
-
- def _delete_volume(self, volume, force):
- # NOTE: volume can be id or name
- ssh_cmd = 'rmvdisk %s %s' % ('-force' if force else '', volume)
- exit_code, stdout, stderr = self.ssh.execute(ssh_cmd)
-
- def _get_initiators(self):
- ssh_cmd = 'lshost -delim !'
- return self._execute_command_and_parse_concise(ssh_cmd)
-
- def _get_initiator(self, init):
- ssh_cmd = 'lshost -delim ! %s' % init
- return self._execute_command_and_parse_detailed(ssh_cmd)
-
- def plugin_register(self, uri, password, timeout, flags=0):
- self.password = password
- self.tmo = timeout
- self.up = uri_parse(uri)
-
- self.ssh = SSHClient(self.up['host'], self.up['username'],
- self.password, self.tmo)
-
- si = self._get_system_info()
- self.sys_info = System(si['id'], si['name'], System.STATUS_OK, '')
-
- def time_out_set(self, ms, flags=0):
- self.tmo = ms
- self.ssh.close()
- self.ssh = SSHClient(self.up['host'], self.up['username'],
- self.password, self.tmo)
-
- def time_out_get(self, flags=0):
- return self.tmo
-
- def plugin_unregister(self, flags=0):
- self.ssh.close()
- return
-
- def job_status(self, job_id, flags=0):
- raise LsmError(ErrorNumber.NOT_IMPLEMENTED,
- "API not implemented at this time")
-
- def job_free(self, job_id, flags=0):
- raise LsmError(ErrorNumber.NOT_IMPLEMENTED,
- "API not implemented at this time")
-
- # NOTE: Add more capabilities as more cli's are supported
- def capabilities(self, system, flags=0):
- cap = Capabilities()
- cap.set(Capabilities.VOLUMES)
- cap.set(Capabilities.VOLUME_CREATE)
- cap.set(Capabilities.VOLUME_DELETE)
- cap.set(Capabilities.VOLUME_THIN)
- cap.set(Capabilities.ACCESS_GROUPS)
- return cap
-
- def plugin_info(self, flags=0):
- return "IBM V7000 lsm plugin", VERSION
-
- def pools(self, search_key=None, search_value=None, flags=0):
- gp = self._get_pools()
- return search_property(
- [self._pool(p) for p in gp.itervalues()],
- search_key, search_value)
-
- def systems(self, flags=0):
- return [self.sys_info]
-
- def volumes(self, search_key=None, search_value=None, flags=0):
- gv = self._get_volumes()
- return search_property(
- [self._volume(v) for v in gv.itervalues()],
- search_key, search_value)
-
- @staticmethod
- def _v7k_init_to_lsm_ag(v7k_init, system_id):
- lsm_init_id = None
- lsm_init_type = AccessGroup.INIT_TYPE_UNKNOWN
- if 'WWPN' in v7k_init:
- lsm_init_type = AccessGroup.INIT_TYPE_WWPN
- # TODO: Add support for > 1 wwpn case.
- # v7k cli is not parse friendly for > 1 case.
- lsm_init_id = v7k_init['WWPN']
- elif 'iscsi_name' in v7k_init:
- lsm_init_type = AccessGroup.INIT_TYPE_ISCSI_IQN
- # TODO: Add support for > 1 iscsiname case.
- # v7k cli is not parse friendly for > 1 case.
- lsm_init_id = v7k_init['iscsi_name']
- elif 'SAS_WWPN' in v7k_init:
- # TODO: Add support for > 1 SAS_WWPN case.
- # v7k cli is not parse friendly for > 1 case.
- lsm_init_type = AccessGroup.INIT_TYPE_SAS
- lsm_init_id = v7k_init['SAS_WWPN']
- else:
- # Since lshost worked, support it as other type.
- lsm_init_type = AccessGroup.INIT_TYPE_OTHER
- lsm_init_id = v7k_init['id']
-
- ag_name = 'N/A'
- if 'name' in v7k_init:
- ag_name = v7k_init['name']
-
- return AccessGroup(lsm_init_id, ag_name, [lsm_init_id], lsm_init_type,
- system_id)
-
- def access_groups(self, search_key=None, search_value=None, flags=0):
- lsm_ags = []
- v7k_inits_dict = self._get_initiators()
- for v7k_init_dict in v7k_inits_dict.itervalues():
- v7k_init = self._get_initiator(v7k_init_dict['id'])
- lsm_ags.extend(
- [IbmV7k._v7k_init_to_lsm_ag(v7k_init, self.sys_info.id)])
- return lsm_ags
-
- def volume_create(self, pool, volume_name, size_bytes, provisioning,
- flags=0):
- self._create_volume(pool.id, volume_name, size_bytes, provisioning)
- new_vol = self._get_volume(volume_name)
- return None, self._volume(new_vol)
-
- def volume_delete(self, volume, flags=0):
- # TODO: How to pass -force param ? For now, assume -force
- self._delete_volume(volume.id, force=True)
- return None
diff --git a/plugin/v7k/v7k_lsmplugin b/plugin/v7k/v7k_lsmplugin
deleted file mode 100755
index 35908a4..0000000
--- a/plugin/v7k/v7k_lsmplugin
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (C) 2013 IBM Corporation
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-#
-# Author: Deepak C Shetty (***@linux.vnet.ibm.com)
-import sys
-import syslog
-import traceback
-
-try:
- from lsm import PluginRunner
- from lsm.plugin.v7k.ibmv7k import IbmV7k
-
- if __name__ == '__main__':
- PluginRunner(IbmV7k, sys.argv).run()
-except Exception:
- #This should be quite rare, but when it does happen this is pretty
- #key in understanding what happened, especially when it happens when
- #running from the daemon.
- msg = str(traceback.format_exc())
- syslog.syslog(syslog.LOG_ERR, msg)
- sys.stderr.write(msg)
- sys.exit(1)
\ No newline at end of file
--
1.8.3.1
Gris Ge
2014-08-04 22:54:57 UTC
Permalink
Enable OBS build:
1. Workaround for OBS bug 864323 by using one-line macro.
2. Move BuildRequires:python-argparse of libstoragemgmt-python to top
package. Required by OBS.
3. Show check log - test-suite.log if failed. Important when facing OBS
build failure. Thanks to libvirt:
http://www.redhat.com/archives/libvir-list/2013-July/msg01834.html

Signed-off-by: Gris Ge <***@redhat.com>
---
packaging/libstoragemgmt.spec.in | 47 ++++++++++++++++++++--------------------
1 file changed, 23 insertions(+), 24 deletions(-)

diff --git a/packaging/libstoragemgmt.spec.in b/packaging/libstoragemgmt.spec.in
index eaf9352..1693be9 100644
--- a/packaging/libstoragemgmt.spec.in
+++ b/packaging/libstoragemgmt.spec.in
@@ -1,19 +1,9 @@
%bcond_without rest_api

-%if 0%{?rhel} <= 6
-%global with_rest_api 0
-# RHEL 6 does not have libmicrohttpd in main repo, but in EPEL repo
-# Hence we disable REST API daemon compiling.
-# If EPEL6 is enabled, please use:
-# rpmbuild -ba libstoragemgmt.spec --with rest_api
-%endif
-
-%{?_with_rest_api:
-%global with_rest_api 1
-}
-%{?_without_rest_api:
-%global with_rest_api 0
-}
+# Use one-line macro for OBS workaround:
+# https://bugzilla.novell.com/show_bug.cgi?id=864323
+%{?_with_rest_api: %global with_rest_api 1 }
+%{?_without_rest_api: %global with_rest_api 0 }

Name: libstoragemgmt
Version: @VERSION@
@@ -25,19 +15,22 @@ URL: http://sourceforge.net/projects/libstoragemgmt/
Source0: http://sourceforge.net/projects/libstoragemgmt/files/libstoragemgmt-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
Requires: %{name}-python
-BuildRequires: autoconf automake libtool yajl-devel libxml2-devel check-devel openssl-devel
+BuildRequires: autoconf automake libtool yajl-devel libxml2-devel check-devel
+BuildRequires: openssl-devel
+BuildRequires: python-argparse
BuildRequires: glib2-devel
# Explicitly require gcc-c++ is for OBS
BuildRequires: gcc-c++

-# These buggy extra conditional BuildRequires is for OBS only,
-# Please refer to OBS bug:
-# https://bugzilla.novell.com/show_bug.cgi?id=864323
-%if 0%{?fedora} || 0%{?rhel} >= 7
-BuildRequires: libmicrohttpd-devel json-c-devel
+# For OBS only. OBS is still using RHEL/Centos 6.2 which does not have
+# OrderedDict from python collection. Use EPEL6 python-ordereddict.
+# These line is only for OBS SPEC parser, not for rpmbuild.
+%if 0%{?centos_version} == 600 || 0%{?rhel_version} == 600
+BuildRequires: python-ordereddict
+# redhat-release was not included in OBS. It provides %{rhel} macro.
+BuildRequires: redhat-release
%endif

-
%if 0%{?fedora} >= 15 || 0%{?rhel} >= 7
BuildRequires: systemd-units
Requires: initscripts
@@ -67,9 +60,11 @@ Summary: Python client libraries and plug-in support for %{name}
Group: System Environment/Libraries
Requires: %{name} = %{version}-%{release}
BuildArch: noarch
-%if 0%{?rhel} <= 6
Requires: python-argparse
-BuildRequires: python-argparse
+%if 0%{?rhel} == 6
+# No way to detect 6.2 yet. Just forcing all RHEL 6 to install
+# python-ordereddict just in case.
+Requires: python-ordereddict
%endif

%description python
@@ -195,7 +190,11 @@ install -m 755 tools/udev/scan-scsi-target \
rm -rf %{buildroot}

%check
-make check
+if ! make check
+then
+ cat test/test-suite.log || true
+ exit 1
+fi

%pre
getent group libstoragemgmt >/dev/null || groupadd -r libstoragemgmt
--
1.8.3.1
Gris Ge
2014-08-04 22:54:59 UTC
Permalink
If we aren't doing the comand 'list', then self.args.type
is not present and we will throw an exception. Check
before use.

This was found when trying to run plugin-info without a uri
set.

Signed-off-by: Tony Asleson <***@redhat.com>
---
tools/lsmcli/cmdline.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/lsmcli/cmdline.py b/tools/lsmcli/cmdline.py
index 3f68d05..41bccda 100644
--- a/tools/lsmcli/cmdline.py
+++ b/tools/lsmcli/cmdline.py
@@ -1483,7 +1483,7 @@ class CmdLine:
# the same in all cases, even though it isn't technically
# required for the client library (static method)
# TODO: Make this not necessary.
- if (self.args.type == "PLUGINS"):
+ if ('type' in self.args and self.args.type == "PLUGINS"):
self.uri = "sim://"
self.password = None
else:
--
1.8.3.1
Gris Ge
2014-08-04 22:54:58 UTC
Permalink
1. Plush STDOUT on every logger call of lsmd daemon.
2. Change lsmd to systemd mode and save output to a tmp log file.
Useful to deubg daemon error and plugin error in OBS build where no way
to check syslog.
3. Fix a trivial typo:
export CK_export CK_FORK=no
4. Removed the 'tab' from runtest.sh which is mixing 'tab' and 'space'

Signed-off-by: Gris Ge <***@redhat.com>
---
daemon/lsm_daemon.c | 1 +
test/runtests.sh | 73 ++++++++++++++++++++++++++++-------------------------
2 files changed, 40 insertions(+), 34 deletions(-)

diff --git a/daemon/lsm_daemon.c b/daemon/lsm_daemon.c
index 923b66e..80e0064 100644
--- a/daemon/lsm_daemon.c
+++ b/daemon/lsm_daemon.c
@@ -107,6 +107,7 @@ void logger(int severity, const char *fmt, ...)
syslog(LOG_ERR, "%s", buf);
} else {
fprintf(stdout, "%s", buf);
+ fflush(stdout);
}

if( LOG_ERR == severity) {
diff --git a/test/runtests.sh b/test/runtests.sh
index 8faebb4..93b584e 100755
--- a/test/runtests.sh
+++ b/test/runtests.sh
@@ -23,7 +23,7 @@
export G_SLICE=always-malloc
export G_DEBUG=gc-friendly
export CK_DEFAULT_TIMEOUT=600
-export CK_export CK_FORK=no
+export CK_FORK=no

rundir=$RANDOM
base=/tmp/$rundir
@@ -33,35 +33,38 @@ LSMD_PID=65535
export LSM_TEST_RUNDIR=$rundir
export LSM_UDS_PATH=$base/lsm/ipc/

+LSMD_TMP_LOG_FILE="$base/lsmd.log"
+
cleanup() {
- #Clean up the daemon if it is running
- if [ $LSMD_PID -ne 65535 ]
- then
- kill -s INT $LSMD_PID
- fi
-
- if [ -e $LSM_UDS_PATH ]
- then
- rm -rf $base
- fi
-
- if [ -e $rootdir/_build ]
- then
- rm $lsm_py_folder/lsm/plugin
- rm $lsm_py_folder/lsm/lsmcli
- chmod -w $lsm_py_folder/lsm
- fi
+ #Clean up the daemon if it is running
+ if [ $LSMD_PID -ne 65535 ]
+ then
+ kill -s KILL $LSMD_PID
+ fi
+
+ cat $LSMD_TMP_LOG_FILE
+ if [ -e $LSM_UDS_PATH ]
+ then
+ rm -rf $base
+ fi
+
+ if [ -e $rootdir/_build ]
+ then
+ rm $lsm_py_folder/lsm/plugin
+ rm $lsm_py_folder/lsm/lsmcli
+ chmod -w $lsm_py_folder/lsm
+ fi
}

good() {
- echo "executing: $1"
- eval $1
- ec=$?
- if [ $ec -ne 0 ]; then
- echo "Fail exit[$ec]: $1"
- cleanup
- exit 1
- fi
+ echo "executing: $1"
+ eval $1
+ ec=$?
+ if [ $ec -ne 0 ]; then
+ echo "Fail exit[$ec]: $1"
+ cleanup
+ exit 1
+ fi
}

# Add a signal handler to clean-up
@@ -85,10 +88,10 @@ lsmcli_py_folder=$rootdir/tools/lsmcli

if [ -e $rootdir/_build ]
then
- c_unit=$rootdir/_build/test/tester
- LSMD_DAEMON=$rootdir/_build/daemon/lsmd
- shared_libs=$rootdir/_build/c_binding/.libs/
- bin_plugin=$rootdir/_build/plugin/simc/.libs/
+ c_unit=$rootdir/_build/test/tester
+ LSMD_DAEMON=$rootdir/_build/daemon/lsmd
+ shared_libs=$rootdir/_build/c_binding/.libs/
+ bin_plugin=$rootdir/_build/plugin/simc/.libs/
# In distcheck, all folder is read only(except _build and _inst).
# which prevent us from linking plugin and lsmcli into python/lsm folder.
chmod +w $rootdir/python_binding/lsm
@@ -133,17 +136,19 @@ good "find $rootdir/ \( ! -regex '.*/\..*' \) -type f -name \*_lsmplugin -exec c
good "cp $bin_plugin/*_lsmplugin $plugins"
good "ls -lh $plugins"

-
#Start daemon
-good "$LSMD_DAEMON --plugindir $plugins --socketdir $LSM_UDS_PATH" -v
+$LSMD_DAEMON \
+ --plugindir $plugins \
+ --socketdir $LSM_UDS_PATH \
+ -d >$LSMD_TMP_LOG_FILE &

LSMD_PID=$(ps aux | grep $LSM_UDS_PATH | grep -v grep | awk '{print $2}')

#Run C unit test
if [ -z "$LSM_VALGRIND" ]; then
- good "$c_unit"
+ good "$c_unit"
else
- good "valgrind --leak-check=full --show-reachable=no --log-file=/tmp/leaking_client $rootdir/test/.libs/tester"
+ good "valgrind --leak-check=full --show-reachable=no --log-file=/tmp/leaking_client $rootdir/test/.libs/tester"
fi

#Run cmdline against the simulator if we are not checking for leaks
--
1.8.3.1
Gris Ge
2014-08-04 22:55:01 UTC
Permalink
The 'simc://' and 'sim://' plugins are not sharing the same list of
UNSUPPORTED capabilities.

Before sync the behaviour of these two plugins, I would like to make test pass
by empty expected_absent capabilities check

Signed-off-by: Gris Ge <***@redhat.com>
---
test/tester.c | 20 --------------------
1 file changed, 20 deletions(-)

diff --git a/test/tester.c b/test/tester.c
index ac250c6..a910489 100644
--- a/test/tester.c
+++ b/test/tester.c
@@ -2097,26 +2097,6 @@ START_TEST(test_capability)
LSM_CAP_EXPORT_REMOVE};

lsm_capability_type expected_absent[] = {
- LSM_CAP_EXPORT_CUSTOM_PATH,
- LSM_CAP_POOL_CREATE,
- LSM_CAP_POOL_CREATE_FROM_DISKS,
- LSM_CAP_POOL_CREATE_FROM_POOL,
-
- LSM_CAP_POOL_CREATE_DISK_RAID_0,
- LSM_CAP_POOL_CREATE_DISK_RAID_1,
- LSM_CAP_POOL_CREATE_DISK_RAID_JBOD,
- LSM_CAP_POOL_CREATE_DISK_RAID_3,
- LSM_CAP_POOL_CREATE_DISK_RAID_4,
- LSM_CAP_POOL_CREATE_DISK_RAID_5,
- LSM_CAP_POOL_CREATE_DISK_RAID_6,
- LSM_CAP_POOL_CREATE_DISK_RAID_10,
- LSM_CAP_POOL_CREATE_DISK_RAID_50,
- LSM_CAP_POOL_CREATE_DISK_RAID_51,
- LSM_CAP_POOL_CREATE_DISK_RAID_60,
- LSM_CAP_POOL_CREATE_DISK_RAID_61,
- LSM_CAP_POOL_CREATE_DISK_RAID_15,
- LSM_CAP_POOL_CREATE_DISK_RAID_16,
- LSM_CAP_POOL_CREATE_DISK_RAID_NOT_APPLICABLE
};
--
1.8.3.1
Gris Ge
2014-08-04 22:55:00 UTC
Permalink
More than once the call to lsm_capability_set_n has been done incorrectly
when adding or removing capabilities. Christophe offered this good suggestion:

"
Gris Ge
2014-08-04 22:55:02 UTC
Permalink
OrderedDict is only available in python 2.7.[1]
We use it from python-ordereddict package which is a backport version.

Tested on RHEL 6.2 which does not port OrderedDict from 2.7 yet.

Signed-off-by: Gris Ge <***@redhat.com>
---
tools/lsmcli/cmdline.py | 7 ++++++-
tools/lsmcli/data_display.py | 8 +++++++-
2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/tools/lsmcli/cmdline.py b/tools/lsmcli/cmdline.py
index 41bccda..04f2a3b 100644
--- a/tools/lsmcli/cmdline.py
+++ b/tools/lsmcli/cmdline.py
@@ -22,7 +22,12 @@ import getpass
import time
import tty
import termios
-from collections import OrderedDict
+
+try:
+ from collections import OrderedDict
+except ImportError:
+ # python 2.6 or earlier, use backport
+ from ordereddict import OrderedDict

from argparse import ArgumentParser
from argparse import RawTextHelpFormatter
diff --git a/tools/lsmcli/data_display.py b/tools/lsmcli/data_display.py
index a4d9629..e87186b 100644
--- a/tools/lsmcli/data_display.py
+++ b/tools/lsmcli/data_display.py
@@ -16,7 +16,13 @@
#
# Author: Gris Ge <***@redhat.com>
import sys
-from collections import OrderedDict
+
+try:
+ from collections import OrderedDict
+except ImportError:
+ # python 2.6 or earlier, use backport
+ from ordereddict import OrderedDict
+
from datetime import datetime

from lsm import (size_bytes_2_size_human, LsmError, ErrorNumber,
--
1.8.3.1
Gris Ge
2014-08-04 22:55:03 UTC
Permalink
* Removed these initiator types as no plugin is using them:
INIT_TYPE_WWNN (Python)
INIT_TYPE_HOSTNAME (Python)
INIT_TYPE_SAS (Python)
LSM_ACCESS_GROUP_INIT_TYPE_WWNN (C)
LSM_ACCESS_GROUP_INIT_TYPE_HOSTNAME (C)
LSM_ACCESS_GROUP_INIT_TYPE_SAS (C)

* Update plugins for above changes.

* Renamed this type in C API:
INIT_TYPE_ISCSI_WWPN_MIXED to LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_WWPN_MIXED

* Removed old initiator class in C API:
1. Renamed lsm_initiator_type to lsm_access_group_init_type
2. Removed lsm_plug_initiator_grant() method
3. Removed _lsm_initiator class.

* Fix incorrect parameter of lsm_iscsi_chap_auth:
initiator -> init_id

* Enabled iscsi_chap_auth test.

Signed-off-by: Gris Ge <***@redhat.com>
---
c_binding/include/libstoragemgmt/libstoragemgmt.h | 4 +-
.../libstoragemgmt/libstoragemgmt_plug_interface.h | 18 +------
.../include/libstoragemgmt/libstoragemgmt_types.h | 15 +-----
c_binding/lsm_datatypes.hpp | 12 -----
c_binding/lsm_mgmt.cpp | 6 +--
c_binding/lsm_plugin_ipc.cpp | 6 +--
plugin/sim/simarray.py | 9 +---
plugin/simc/simc_lsmplugin.c | 6 +--
plugin/smispy/smis.py | 29 +++++-----
python_binding/lsm/_data.py | 3 --
test/tester.c | 61 ++++++++++------------
tools/lsmcli/cmdline.py | 2 +-
tools/lsmcli/data_display.py | 3 --
13 files changed, 55 insertions(+), 119 deletions(-)

diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt.h b/c_binding/include/libstoragemgmt/libstoragemgmt.h
index 5345017..968bfdd 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt.h
@@ -523,7 +523,7 @@ extern "C" {
int LSM_DLL_EXPORT lsm_access_group_create(lsm_connect *conn,
const char *name,
const char *init_id,
- lsm_initiator_type init_type,
+ lsm_access_group_init_type init_type,
lsm_system *system,
lsm_access_group **access_group,
lsm_flag flags);
@@ -552,7 +552,7 @@ extern "C" {
int LSM_DLL_EXPORT lsm_access_group_initiator_add(lsm_connect *conn,
lsm_access_group *access_group,
const char *init_id,
- lsm_initiator_type init_type,
+ lsm_access_group_init_type init_type,
lsm_access_group **updated_access_group,
lsm_flag flags);

diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h b/c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h
index 71a6579..77f2ecb 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h
@@ -417,22 +417,6 @@ typedef int (*lsm_plug_volume_offline)(lsm_plugin_ptr c, lsm_volume *v,
lsm_flag flags);

/**
- * Grants access to an initiator for a specified volume, callback function signature
- * @param[in] c Valid lsm plug-in pointer
- * @param[in] initiator_id Initiator ID
- * @param[in] initiator_type Type of initiator
- * @param[in] volume Volume of interest
- * @param[in] access Desired access to volume
- * @param[in] flags Reserved
- * @return LSM_ERR_OK, else error reason
- */
-typedef int (*lsm_plug_initiator_grant)(lsm_plugin_ptr c, const char *initiator_id,
- lsm_initiator_type initiator_type,
- lsm_volume *volume,
- lsm_access_type access,
- lsm_flag flags);
-
-/**
* Setup the cap authentication for the specified initiator, callback
* function signature
* @param[in] c Valid lsm plug-in pointer
@@ -509,7 +493,7 @@ typedef int (*lsm_plug_access_group_delete)(lsm_plugin_ptr c,
typedef int (*lsm_plug_access_group_initiator_add)(lsm_plugin_ptr c,
lsm_access_group *access_group,
const char *initiator_id,
- lsm_initiator_type id_type,
+ lsm_access_group_init_type id_type,
lsm_access_group **updated_access_group,
lsm_flag flags);

diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt_types.h b/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
index 5180441..4d3b6bd 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
@@ -172,25 +172,12 @@ typedef enum {
#define LSM_SYSTEM_STATUS_OTHER 0x00000200 /**< Vendor specific */


-/**< \enum lsm_initiator_type Different types of initiator IDs */
-typedef enum {
- LSM_INITIATOR_OTHER = 1, /**< Other or unspecified */
- LSM_INITIATOR_PORT_WWN = 2, /**< World wide port name */
- LSM_INITIATOR_NODE_WWN = 3, /**< World wide node name */
- LSM_INITIATOR_HOSTNAME = 4, /**< Host name */
- LSM_INITIATOR_ISCSI = 5, /**< iSCSI IQN */
- LSM_INITIATOR_SAS = 7 /**< SAS ID */
-} lsm_initiator_type;
-
typedef enum {
LSM_ACCESS_GROUP_INIT_TYPE_UNKNOWN = 0, /**< Unknown */
LSM_ACCESS_GROUP_INIT_TYPE_OTHER = 1, /**< Something not seen before */
LSM_ACCESS_GROUP_INIT_TYPE_WWPN = 2, /**< Port name */
- LSM_ACCESS_GROUP_INIT_TYPE_WWNN = 3, /**< Node name */
- LSM_ACCESS_GROUP_INIT_TYPE_HOSTNAME = 4, /**< Host name */
LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_IQN = 5, /**< ISCSI IQN */
- LSM_ACCESS_GROUP_INIT_TYPE_SAS = 6, /**< SAS */
- INIT_TYPE_ISCSI_WWPN_MIXED = 7 /**< More than 1 type */
+ LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_WWPN_MIXED = 7 /**< More than 1 type */
} lsm_access_group_init_type;


diff --git a/c_binding/lsm_datatypes.hpp b/c_binding/lsm_datatypes.hpp
index 40f2935..00e2111 100644
--- a/c_binding/lsm_datatypes.hpp
+++ b/c_binding/lsm_datatypes.hpp
@@ -90,18 +90,6 @@ struct LSM_DLL_LOCAL _lsm_pool {
};


-#define LSM_INIT_MAGIC 0xAA7A0002
-#define LSM_IS_INIT(obj) MAGIC_CHECK(obj, LSM_INIT_MAGIC)
-/**
- * Information about an initiator.
- */
-struct LSM_DLL_LOCAL _lsm_initiator {
- uint32_t magic; /**< Used for verification */
- lsm_initiator_type id_type; /**< Type of id */
- char *id; /**< Identifier */
- char *name; /**< Initiator name */
-};
-
#define LSM_ACCESS_GROUP_MAGIC 0xAA7A0003
#define LSM_IS_ACCESS_GROUP(obj) MAGIC_CHECK(obj, LSM_ACCESS_GROUP_MAGIC)

diff --git a/c_binding/lsm_mgmt.cpp b/c_binding/lsm_mgmt.cpp
index c75ffd5..7ca71c0 100644
--- a/c_binding/lsm_mgmt.cpp
+++ b/c_binding/lsm_mgmt.cpp
@@ -1361,7 +1361,7 @@ int lsm_iscsi_chap_auth(lsm_connect *c, const char *init_id,
}

std::map<std::string, Value> p;
- p["initiator"] = Value(init_id);
+ p["init_id"] = Value(init_id);
p["in_user"] = Value(username);
p["in_password"] = Value(password);
p["out_user"] = Value(out_user);
@@ -1436,7 +1436,7 @@ int lsm_access_group_list(lsm_connect *c, const char *search_key,
}

int lsm_access_group_create(lsm_connect *c, const char *name,
- const char *init_id, lsm_initiator_type init_type,
+ const char *init_id, lsm_access_group_init_type init_type,
lsm_system *system,
lsm_access_group **access_group, lsm_flag flags)
{
@@ -1499,7 +1499,7 @@ int lsm_access_group_delete(lsm_connect *c, lsm_access_group *access_group,
int lsm_access_group_initiator_add(lsm_connect *c,
lsm_access_group *access_group,
const char *init_id,
- lsm_initiator_type init_type,
+ lsm_access_group_init_type init_type,
lsm_access_group **updated_access_group,
lsm_flag flags)
{
diff --git a/c_binding/lsm_plugin_ipc.cpp b/c_binding/lsm_plugin_ipc.cpp
index 8058158..68cbf44 100644
--- a/c_binding/lsm_plugin_ipc.cpp
+++ b/c_binding/lsm_plugin_ipc.cpp
@@ -1236,8 +1236,8 @@ static int ag_initiator_add(lsm_plugin_ptr p, Value &params, Value &response)
if( ag ) {
lsm_access_group *updated_access_group = NULL;
const char *id = v_init_id.asC_str();
- lsm_initiator_type id_type = (lsm_initiator_type)
- v_init_type.asInt32_t();
+ lsm_access_group_init_type id_type =
+ (lsm_access_group_init_type) v_init_type.asInt32_t();

rc = p->san_ops->ag_add_initiator(p, ag, id, id_type,
&updated_access_group,
@@ -2222,7 +2222,7 @@ static int iscsi_chap(lsm_plugin_ptr p, Value &params, Value &response)
int rc = LSM_ERR_NO_SUPPORT;

if( p && p->san_ops && p->san_ops->iscsi_chap_auth ) {
- Value v_init = params["initiator"];
+ Value v_init = params["init_id"];
Value v_in_user = params["in_user"];
Value v_in_password = params["in_password"];
Value v_out_user = params["out_user"];
diff --git a/plugin/sim/simarray.py b/plugin/sim/simarray.py
index b399b03..d59a1b1 100644
--- a/plugin/sim/simarray.py
+++ b/plugin/sim/simarray.py
@@ -640,8 +640,6 @@ class SimData(object):

self.ag_dict = {
}
- self.init_dict = {
- }
# Create some volumes, fs and etc
self.volume_create(
'POO1', 'Volume 000', size_human_2_size_bytes('200GiB'),
@@ -1189,12 +1187,7 @@ class SimData(object):

def iscsi_chap_auth(self, init_id, in_user, in_pass, out_user, out_pass,
flags=0):
- # to_code
- if self.init_dict[init_id]['init_type'] != \
- AccessGroup.INIT_TYPE_ISCSI_IQN:
- raise LsmError(ErrorNumber.NO_SUPPORT,
- "Initiator %s is not an iSCSI IQN" % init_id)
- # No iscsi chap query API yet
+ # No iscsi chap query API yet, not need to setup anything
return None

def fs(self):
diff --git a/plugin/simc/simc_lsmplugin.c b/plugin/simc/simc_lsmplugin.c
index 3f2d056..5a295f6 100644
--- a/plugin/simc/simc_lsmplugin.c
+++ b/plugin/simc/simc_lsmplugin.c
@@ -113,7 +113,7 @@ struct allocated_fs {

struct allocated_ag {
lsm_access_group *ag;
- lsm_initiator_type ag_type;
+ lsm_access_group_init_type ag_type;
};

struct plugin_data {
@@ -189,7 +189,7 @@ void free_allocated_job(void *j)
}

struct allocated_ag *alloc_allocated_ag( lsm_access_group *ag,
- lsm_initiator_type i)
+ lsm_access_group_init_type i)
{
struct allocated_ag *aag =
(struct allocated_ag *)malloc(sizeof(struct allocated_ag));
@@ -1228,7 +1228,7 @@ static int access_group_delete( lsm_plugin_ptr c,
static int access_group_initiator_add( lsm_plugin_ptr c,
lsm_access_group *group,
const char *initiator_id,
- lsm_initiator_type id_type,
+ lsm_access_group_init_type id_type,
lsm_access_group **updated_access_group,
lsm_flag flags)
{
diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index 88ae335..6299d1c 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -141,11 +141,8 @@ class DMTF(object):
# CIM_StorageHardwareID['IDType']
ID_TYPE_OTHER = pywbem.Uint16(1)
ID_TYPE_WWPN = pywbem.Uint16(2)
- ID_TYPE_WWNN = pywbem.Uint16(3)
- ID_TYPE_HOSTNAME = pywbem.Uint16(4)
ID_TYPE_ISCSI = pywbem.Uint16(5)
- ID_TYPE_SW_WWN = pywbem.Uint16(6)
- ID_TYPE_SAS = pywbem.Uint16(7)
+
TGT_PORT_USAGE_FRONTEND_ONLY = pywbem.Uint16(2)
TGT_PORT_USAGE_UNRESTRICTED = pywbem.Uint16(4)
# CIM_FCPort['PortDiscriminator']
@@ -193,17 +190,16 @@ class DMTF(object):
_INIT_TYPE_CONV = {
DMTF.ID_TYPE_OTHER: AccessGroup.INIT_TYPE_OTHER,
DMTF.ID_TYPE_WWPN: AccessGroup.INIT_TYPE_WWPN,
- DMTF.ID_TYPE_WWNN: AccessGroup.INIT_TYPE_WWNN,
- DMTF.ID_TYPE_HOSTNAME: AccessGroup.INIT_TYPE_HOSTNAME,
DMTF.ID_TYPE_ISCSI: AccessGroup.INIT_TYPE_ISCSI_IQN,
- DMTF.ID_TYPE_SW_WWN: AccessGroup.INIT_TYPE_OTHER,
- DMTF.ID_TYPE_SAS: AccessGroup.INIT_TYPE_SAS,
}


def _dmtf_init_type_to_lsm(cim_init):
- if 'IDType' in cim_init and cim_init['IDType'] in _INIT_TYPE_CONV.keys():
- return _INIT_TYPE_CONV[cim_init['IDType']]
+ if 'IDType' in cim_init:
+ if cim_init['IDType'] == DMTF.ID_TYPE_WWPN:
+ return AccessGroup.INIT_TYPE_WWPN
+ elif cim_init['IDType'] == DMTF.ID_TYPE_ISCSI:
+ return AccessGroup.INIT_TYPE_ISCSI_IQN
return AccessGroup.INIT_TYPE_UNKNOWN


@@ -225,13 +221,12 @@ def _lsm_tgt_port_type_of_cim_fc_tgt(cim_fc_tgt):


def _lsm_init_type_to_dmtf(init_type):
- # Invert dict. Assumes values are unique.
- try:
- inv_dict = dict((v, k) for k, v in _INIT_TYPE_CONV.iteritems())
- return inv_dict[init_type]
- except KeyError:
- raise LsmError(ErrorNumber.NO_SUPPORT,
- "Does not support provided init_type: %d" % init_type)
+ if init_type == AccessGroup.INIT_TYPE_WWPN:
+ return DMTF.ID_TYPE_WWPN
+ if init_type == AccessGroup.INIT_TYPE_ISCSI_IQN:
+ return DMTF.ID_TYPE_ISCSI
+ raise LsmError(ErrorNumber.NO_SUPPORT,
+ "Does not support provided init_type: %d" % init_type)


class SNIA(object):
diff --git a/python_binding/lsm/_data.py b/python_binding/lsm/_data.py
index ff5065f..70ee4da 100644
--- a/python_binding/lsm/_data.py
+++ b/python_binding/lsm/_data.py
@@ -650,10 +650,7 @@ class AccessGroup(IData):
INIT_TYPE_UNKNOWN = 0
INIT_TYPE_OTHER = 1
INIT_TYPE_WWPN = 2
- INIT_TYPE_WWNN = 3
- INIT_TYPE_HOSTNAME = 4
INIT_TYPE_ISCSI_IQN = 5
- INIT_TYPE_SAS = 6
INIT_TYPE_ISCSI_WWPN_MIXED = 7

def __init__(self, _id, _name, _init_ids, _init_type, _system_id,
diff --git a/test/tester.c b/test/tester.c
index a910489..a034e04 100644
--- a/test/tester.c
+++ b/test/tester.c
@@ -613,7 +613,8 @@ START_TEST(test_access_groups)
fail_unless(groups == NULL);

G(rc, lsm_access_group_create, c, "test_access_groups",
- "iqn.1994-05.com.domain:01.89bd01", LSM_INITIATOR_ISCSI, system,
+ "iqn.1994-05.com.domain:01.89bd01",
+ LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_IQN, system,
&group, LSM_FLAG_RSVD);

if( LSM_ERR_OK == rc ) {
@@ -655,7 +656,9 @@ START_TEST(test_access_groups)
char *job = NULL;
lsm_access_group *updated = NULL;

- rc = lsm_access_group_initiator_add(c, group, "iqn.1994-05.com.domain:01.89bd02", LSM_INITIATOR_ISCSI, &updated, LSM_FLAG_RSVD);
+ rc = lsm_access_group_initiator_add(c, group, "iqn.1994-05.com.domain:01.89bd02",
+ LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_IQN,
+ &updated, LSM_FLAG_RSVD);
fail_unless(LSM_ERR_OK == rc, "Expected success on lsmAccessGroupInitiatorAdd %d %d", rc, which_plugin);

G(rc, lsm_access_group_list, c, NULL, NULL, &groups, &count, LSM_FLAG_RSVD);
@@ -744,9 +747,10 @@ START_TEST(test_access_groups_grant_revoke)
system = get_system(c);

G(rc, lsm_access_group_create, c, "test_access_groups_grant_revoke",
- ISCSI_HOST[0], LSM_INITIATOR_ISCSI,
- system,
- &group, LSM_FLAG_RSVD);
+ ISCSI_HOST[0],
+ LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_IQN,
+ system,
+ &group, LSM_FLAG_RSVD);


int vc = lsm_volume_create(c, pool, "volume_grant_test", 20000000,
@@ -1528,12 +1532,12 @@ START_TEST(test_invalid_input)
rc = lsm_access_group_create(c, NULL, NULL, 0, system, NULL, LSM_FLAG_RSVD);
fail_unless(rc == LSM_ERR_INVALID_ARGUMENT, "rc = %d", rc);

- rc = lsm_access_group_create(c, "my_group", ISCSI_HOST[0], LSM_INITIATOR_OTHER,
+ rc = lsm_access_group_create(c, "my_group", ISCSI_HOST[0], LSM_ACCESS_GROUP_INIT_TYPE_OTHER,
NULL, NULL, LSM_FLAG_RSVD);
fail_unless(rc == LSM_ERR_INVALID_SYSTEM, "rc = %d", rc);


- rc = lsm_access_group_create(c, "my_group", ISCSI_HOST[0], LSM_INITIATOR_OTHER,
+ rc = lsm_access_group_create(c, "my_group", ISCSI_HOST[0], LSM_ACCESS_GROUP_INIT_TYPE_OTHER,
system, &ag, LSM_FLAG_RSVD);
fail_unless(rc == LSM_ERR_OK, "rc = %d", rc);
fail_unless(ag != NULL);
@@ -1925,45 +1929,35 @@ START_TEST(test_iscsi_auth_in)
{
lsm_access_group *group = NULL;
lsm_system *system = NULL;
- //char *job = NULL;
- int rc;
+ int rc = 0;

system = get_system(c);
+ printf("get_system() OK\n");

G(rc, lsm_access_group_create, c, "ISCSI_AUTH", ISCSI_HOST[0],
- LSM_INITIATOR_ISCSI, system, &group, LSM_FLAG_RSVD);
+ LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_IQN, system, &group, LSM_FLAG_RSVD);
+ printf("lsm_access_group_create() OK\n");

- fail_unless(LSM_ERR_OK == rc, "rc = %d");
+ fail_unless(LSM_ERR_OK == rc, "rc = %d", rc);
G(rc, lsm_system_record_free, system);
+ printf("lsm_system_record_free() OK\n");
+
system = NULL;

if( LSM_ERR_OK == rc ) {
- /* TODO FIX THIS UP after we take out the C initiator support.
- lsm_initiator **inits = NULL;
- uint32_t init_count = 0;
-

- rc = lsm_initiator_list(c, &inits, &init_count, LSM_FLAG_RSVD );
- fail_unless(LSM_ERR_OK == rc );
+ rc = lsm_iscsi_chap_auth(
+ c, ISCSI_HOST[0], "username", "secret", NULL, NULL,
+ LSM_FLAG_RSVD);

- if( LSM_ERR_OK == rc && init_count ) {
- rc = lsm_iscsi_chap_auth(c, inits[0], "username", "secret",
- NULL, NULL, LSM_FLAG_RSVD);
+ fail_unless(LSM_ERR_OK == rc, "rc = %d", rc);

- fail_unless(LSM_ERR_OK == rc, "rc = %d", rc) ;
- }
+ rc = lsm_access_group_delete(c, group, LSM_FLAG_RSVD);

- rc = lsm_access_group_delete(c, group, LSM_FLAG_RSVD);
+ fail_unless(LSM_ERR_OK == rc );

- if(LSM_ERR_JOB_STARTED == rc ) {
- wait_for_job(c, &job);
- } else {
- fail_unless(LSM_ERR_OK == rc );
- }
- */
-
- lsm_access_group_record_free(group);
- group = NULL;
+ lsm_access_group_record_free(group);
+ group = NULL;
}
}
END_TEST
@@ -2666,7 +2660,8 @@ START_TEST(test_search_access_groups)
snprintf(ag_name, sizeof(ag_name), "test_access_group_%d", i);

G(rc, lsm_access_group_create, c, ag_name, ISCSI_HOST[i],
- LSM_INITIATOR_ISCSI, system, &group, LSM_FLAG_RSVD);
+ LSM_ACCESS_GROUP_INIT_TYPE_ISCSI_IQN,
+ system, &group, LSM_FLAG_RSVD);

if( LSM_ERR_OK == rc ) {
G(rc, lsm_access_group_record_free, group);
diff --git a/tools/lsmcli/cmdline.py b/tools/lsmcli/cmdline.py
index 04f2a3b..96b3fbe 100644
--- a/tools/lsmcli/cmdline.py
+++ b/tools/lsmcli/cmdline.py
@@ -109,7 +109,7 @@ list_choices = ['VOLUMES', 'POOLS', 'FS', 'SNAPSHOTS',
'EXPORTS', "NFS_CLIENT_AUTH", 'ACCESS_GROUPS',
'SYSTEMS', 'DISKS', 'PLUGINS', 'TARGET_PORTS']

-init_types = ('WWPN', 'WWNN', 'ISCSI', 'HOSTNAME', 'SAS')
+init_types = ('WWPN', 'ISCSI')
init_id_help = "Access Group Initiator type: " + \
", ".join(init_types)

diff --git a/tools/lsmcli/data_display.py b/tools/lsmcli/data_display.py
index e87186b..9a18cd5 100644
--- a/tools/lsmcli/data_display.py
+++ b/tools/lsmcli/data_display.py
@@ -289,10 +289,7 @@ _AG_INIT_TYPE_CONV = {
AccessGroup.INIT_TYPE_UNKNOWN: 'Unknown',
AccessGroup.INIT_TYPE_OTHER: 'Other',
AccessGroup.INIT_TYPE_WWPN: 'WWPN',
- AccessGroup.INIT_TYPE_WWNN: 'WWNN',
- AccessGroup.INIT_TYPE_HOSTNAME: 'Hostname',
AccessGroup.INIT_TYPE_ISCSI_IQN: 'iSCSI',
- AccessGroup.INIT_TYPE_SAS: 'SAS',
AccessGroup.INIT_TYPE_ISCSI_WWPN_MIXED: 'iSCSI/WWPN Mixed',
}
--
1.8.3.1
Gris Ge
2014-08-04 22:55:04 UTC
Permalink
1. Forcing user to input WWPN in this format:
10:00:00:00:c9:95:2f:de

2. Add methods to lsm.AccessGroup:
AccessGroup.init_id_validate()
AccessGroup.wwpn_to_lsm_type()

3. Rename INVALID_IQN to INVALID_INIT

Signed-off-by: Gris Ge <***@redhat.com>
---
python_binding/lsm/_client.py | 4 ++
python_binding/lsm/_common.py | 2 +-
python_binding/lsm/_data.py | 96 ++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 99 insertions(+), 3 deletions(-)

diff --git a/python_binding/lsm/_client.py b/python_binding/lsm/_client.py
index 61a7aa2..00b9184 100644
--- a/python_binding/lsm/_client.py
+++ b/python_binding/lsm/_client.py
@@ -427,6 +427,8 @@ class Client(INetworkAttachedStorage):
Register a user/password for the specified initiator for CHAP
authentication.
"""
+ AccessGroup.init_id_validate(
+ init_id, AccessGroup.INIT_TYPE_ISCSI_IQN, raise_error=True)
return self._tp.rpc('iscsi_chap_auth', _del_self(locals()))

## Returns an array of volume objects
@@ -652,6 +654,7 @@ class Client(INetworkAttachedStorage):
Creates an access group and add the specified initiator id,
init_type and desired access.
"""
+ AccessGroup.init_id_validate(init_id, init_type, raise_error=True)
return self._tp.rpc('access_group_create', _del_self(locals()))

## Deletes an access group.
@@ -679,6 +682,7 @@ class Client(INetworkAttachedStorage):
"""
Adds an initiator to an access group
"""
+ AccessGroup.init_id_validate(init_id, init_type, raise_error=True)
return self._tp.rpc('access_group_initiator_add', _del_self(locals()))

## Deletes an initiator from an access group
diff --git a/python_binding/lsm/_common.py b/python_binding/lsm/_common.py
index fdd10ab..386d9a9 100644
--- a/python_binding/lsm/_common.py
+++ b/python_binding/lsm/_common.py
@@ -455,7 +455,7 @@ class ErrorNumber(object):
INVALID_VOLUME = 115
INVALID_CAPABILITY = 116
INVALID_SYSTEM = 117
- INVALID_IQN = 118
+ INVALID_INIT = 118
INVALID_DISK = 119
INVALID_BLOCK_RANGE = 121

diff --git a/python_binding/lsm/_data.py b/python_binding/lsm/_data.py
index 70ee4da..8b70565 100644
--- a/python_binding/lsm/_data.py
+++ b/python_binding/lsm/_data.py
@@ -17,6 +17,7 @@
# Gris Ge <***@redhat.com>

from abc import ABCMeta as _ABCMeta
+import re

try:
import simplejson as json
@@ -24,7 +25,7 @@ except ImportError:
import json

from json.decoder import WHITESPACE
-from _common import get_class, default_property
+from _common import get_class, default_property, ErrorNumber


class DataEncoder(json.JSONEncoder):
@@ -657,11 +658,102 @@ class AccessGroup(IData):
_plugin_data=None):
self._id = _id
self._name = _name # AccessGroup name
- self._init_ids = _init_ids # List of initiator IDs
+ self._init_ids = _init_ids # A list of Initiator ID strings.
self._init_type = _init_type
self._system_id = _system_id # System id this group belongs
self._plugin_data = _plugin_data

+ # Regex for LSM format of WWPN, example:
+ # 10:00:00:00:c9:95:2f:de
+ _regex_lsm_wwpn = re.compile(r"""
+ ^
+ (?:[0-9a-f]{2}:){7}
+ [0-9a-f]{2}
+ $
+ """, re.X)
+
+ _regex_iscsi_iqn = re.compile(r"""
+ ^
+ iqn # iqn
+ \. # .
+ [0-9]{4}-[0-9]{2} # 1995-02
+ \. # .
+ [A-Za-z](?:[A-Za-z0-9\-]*[A-Za-z0-9])? # com
+ \. # .
+ [A-Za-z](?:[A-Za-z0-9\-]*[A-Za-z0-9])? # redhat
+ : # :
+ [\.A-Za-z\-0-9]+ # gris-01
+ $
+ """, re.X)
+
+ @staticmethod
+ def init_id_validate(init_id, init_type, raise_error=True):
+ if init_type == AccessGroup.INIT_TYPE_ISCSI_IQN:
+ if AccessGroup._regex_iscsi_iqn.match(str(init_id)):
+ return True
+ if raise_error:
+ raise LsmError(ErrorNumber.INVALID_INIT,
+ "Invalid iSCSI IQN Initiator: %s" % init_id)
+ return False
+ elif init_type == AccessGroup.INIT_TYPE_WWPN:
+ if AccessGroup._regex_lsm_wwpn.match(str(init_id)):
+ return True
+ if raise_error:
+ raise LsmError(ErrorNumber.INVALID_INIT,
+ "Invalid WWPN Initiator: %s" % init_id)
+ return False
+ elif raise_error:
+ raise LsmError(ErrorNumber.NO_SUPPORT,
+ "Initiator type %d not supported" % init_type)
+ return False
+
+ _regex_wwpn = re.compile(r"""
+ ^
+ [0x|0X]{0,1}
+ (:?[0-9A-Fa-f]{2}
+ [\.\-:]{0,1}){7}
+ [0-9A-Fa-f]{2}
+ $
+ """, re.X)
+
+ @staticmethod
+ def wwpn_to_lsm_type(wwpn, raise_error=True):
+ """
+ Conver provided WWPN string into LSM standarded one:
+
+ LSM WWPN format:
+ ^(?:[0-9a-f]{2}:){7}[0-9a-f]{2}$
+ LSM WWPN Example:
+ 10:00:00:00:c9:95:2f:de
+
+ Acceptable WWPN format is:
+ ^[0x|0X]{0,1}(:?[0-9A-Fa-f]{2}[\.\-:]{0,1}){7}[0-9A-Fa-f]{2}$
+ Acceptable WWPN example:
+ 10:00:00:00:c9:95:2f:de
+ 10:00:00:00:C9:95:2F:DE
+ 10-00-00-00-C9-95-2F-DE
+ 10-00-00-00-c9-95-2f-de
+ 10.00.00.00.C9.95.2F.DE
+ 10.00.00.00.c9.95.2f.de
+ 0x10000000c9952fde
+ 0X10000000C9952FDE
+ 10000000c9952fde
+ 10000000C9952FDE
+ Return the LSM WWPN
+ Return None if raise_error is False and not a valid WWPN.
+ """
+ if AccessGroup._regex_wwpn.match(str(wwpn)):
+ s = str(wwpn)
+ s = s.lower()
+ s = re.sub(r'0x', '', s)
+ s = re.sub(r'[^0-9a-f]', '', s)
+ s = ":".join(re.findall(r'..', s))
+ return s
+ if raise_error:
+ raise LsmError(ErrorNumber.INVALID_INIT,
+ "Invalid WWPN Initiator: %s" % wwpn)
+ return None
+

@default_property('id', doc="Unique instance identifier")
@default_property('port_type', doc="Target port type")
--
1.8.3.1
Gris Ge
2014-08-04 22:55:05 UTC
Permalink
* Remove old LSM_ERR_INVALID_INIT which is not cleaned up by last initiator
class removal.

* Rename LSM_ERR_INVALID_IQN to LSM_ERR_INVALID_INIT.

Signed-off-by: Gris Ge <***@redhat.com>
---
c_binding/include/libstoragemgmt/libstoragemgmt_error.h | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt_error.h b/c_binding/include/libstoragemgmt/libstoragemgmt_error.h
index d03c29a..60f2362 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt_error.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt_error.h
@@ -66,7 +66,6 @@ typedef enum {
LSM_ERR_INVALID_CONN = 102, /**< Connection structure is invalid */
LSM_ERR_INVALID_ERR = 103, /**< Invalid error structure */
LSM_ERR_INVALID_FS = 104, /**< invalid fs */
- LSM_ERR_INVALID_INIT = 105, /**< Invalid initiator structure */
LSM_ERR_INVALID_JOB = 106, /**< Invalid job number */
LSM_ERR_INVALID_NAME = 107, /**< Name specified is invalid */
LSM_ERR_INVALID_NFS = 108, /**< invalid nfs export record */
@@ -79,7 +78,7 @@ typedef enum {
LSM_ERR_INVALID_VOL = 115, /**< Invalid volume pointer */
LSM_ERR_INVALID_CAPABILITY = 116, /**< Invalid capability pointer */
LSM_ERR_INVALID_SYSTEM = 117, /**< Invalid system pointer */
- LSM_ERR_INVALID_IQN = 118, /**< Invalid IQN */
+ LSM_ERR_INVALID_INIT = 118, /**< Invalid Initiator ID */
LSM_ERR_INVALID_DISK = 119, /**< Invalid disk */
LSM_ERR_INVALID_HASH = 120, /**< Invalid optional data */
LSM_ERR_INVALID_BLOCK_RANGE = 121, /**< Invalud block range */
--
1.8.3.1
Gris Ge
2014-08-04 22:55:06 UTC
Permalink
* Remove '--init-type' by auto detecting user input.
* Manpage updated.
* cmdtest.py updated.

Signed-off-by: Gris Ge <***@redhat.com>
---
doc/man/lsmcli.1.in | 12 ++----------
test/cmdtest.py | 7 ++-----
tools/lsmcli/cmdline.py | 52 ++++++++++++++++++++++++++-----------------------
3 files changed, 32 insertions(+), 39 deletions(-)

diff --git a/doc/man/lsmcli.1.in b/doc/man/lsmcli.1.in
index 1492847..d6337eb 100644
--- a/doc/man/lsmcli.1.in
+++ b/doc/man/lsmcli.1.in
@@ -357,11 +357,7 @@ Create an access group.
Required. The human friendly name for new access group.
.TP
\fB--init\fR \fI<INIT_ID>\fR
-Required. The first initiator ID of new access group.
-.TP
-\fB--init-type\fR \fI<INIT_TYPE>\fR
-Required. The initiator type. Valid values are: \fBWWPN\fR, \fBWWNN\fR,
-\fBISCSI\fR, \fBHOSTNAME\fR, \fBSAS\fR.
+Required. The first initiator ID of new access group. WWPN or iSCSI IQN.
.TP
\fB--sys\fR \fI<SYS_ID>\fR
Required. The ID of system where this access group should reside on.
@@ -373,11 +369,7 @@ Adds an initiator to an access group.
Required. ID of access group.
.TP
\fB--init\fR \fI<INIT_ID>\fR
-Required. ID of initiator to add.
-.TP
-\fB--init-type\fR \fI<INIT_TYPE>\fR
-Required. The initiator type. Valid values are: \fBWWPN\fR, \fBWWNN\fR,
-\fBISCSI\fR, \fBHOSTNAME\fR, \fBSAS\fR.
+Required. ID of initiator to add. WWPN or iSCSI IQN.

.SS access-group-remove
Removes an initiator from an access group.
diff --git a/test/cmdtest.py b/test/cmdtest.py
index 0dcd91c..408dc10 100755
--- a/test/cmdtest.py
+++ b/test/cmdtest.py
@@ -194,15 +194,13 @@ def delete_fs(fs_id):

def access_group_create(init_id, system_id):
out = call([cmd, '-t' + sep, 'access-group-create', '--name', rs(8),
- '--init', init_id, '--init-type', 'ISCSI',
- '--sys', system_id])[1]
+ '--init', init_id, '--sys', system_id])[1]
r = parse(out)
return r[0][ID]


def access_group_initiator_add(group, initiator):
- call([cmd, 'access-group-add', '--ag', group, '--init', initiator,
- '--init-type', 'ISCSI'])
+ call([cmd, 'access-group-add', '--ag', group, '--init', initiator])


def access_group_remove_init(group, initiator):
@@ -363,7 +361,6 @@ def initiator_grant(initiator_id, vol_id):
call([cmd,
'access-grant',
'--init', initiator_id,
- '--init-type', 'ISCSI',
'--vol', vol_id,
'--access', 'RW'])

diff --git a/tools/lsmcli/cmdline.py b/tools/lsmcli/cmdline.py
index 96b3fbe..3588597 100644
--- a/tools/lsmcli/cmdline.py
+++ b/tools/lsmcli/cmdline.py
@@ -77,6 +77,22 @@ def getch():
termios.tcsetattr(fd, termios.TCSADRAIN, prev)
return ch

+def parse_convert_init(init_id):
+ """
+ If init_id is a WWPN, convert it into LSM standard version:
+ (?:[0-9a-f]{2}:){7}[0-9a-f]{2}
+
+ Return (converted_init_id, lsm_init_type)
+ """
+ init_type = AccessGroup.INIT_TYPE_ISCSI_IQN
+ if AccessGroup.init_id_validate(init_id, init_type, raise_error=False):
+ return (init_id, init_type)
+
+ wwpn = AccessGroup.wwpn_to_lsm_type(init_id, raise_error=False)
+ if wwpn:
+ return (wwpn, AccessGroup.INIT_TYPE_WWPN)
+
+ raise ArgError("--init-id %s is not a valid WWPN or iSCSI IQN" % init_id)

## This class represents a command line argument error
class ArgError(Exception):
@@ -109,10 +125,6 @@ list_choices = ['VOLUMES', 'POOLS', 'FS', 'SNAPSHOTS',
'EXPORTS', "NFS_CLIENT_AUTH", 'ACCESS_GROUPS',
'SYSTEMS', 'DISKS', 'PLUGINS', 'TARGET_PORTS']

-init_types = ('WWPN', 'ISCSI')
-init_id_help = "Access Group Initiator type: " + \
- ", ".join(init_types)
-
provision_types = ('DEFAULT', 'THIN', 'FULL')
provision_help = "provisioning type: " + ", ".join(provision_types)

@@ -176,9 +188,6 @@ disk_id_filter_opt = dict(name='--disk', metavar='<DISK_ID>',

size_opt = dict(name='--size', metavar='<SIZE>', help=size_help)

-init_type_opt = dict(name="--init-type", help=init_id_help,
- metavar='<INIT_TYPE>', choices=init_types,
- type=str.upper)
tgt_id_opt = dict(name="--tgt", help="Search by target port ID",
metavar='<TGT_ID>')

@@ -348,10 +357,6 @@ cmds = (
dict(name='--init', metavar='<INIT_ID>', action='append',
help='Initiator ID, only used when access-group-create is '
'not supported'),
- dict(name="--init-type", type=str.upper,
- metavar='<INIT_TYPE>', choices=init_types,
- help="%s only used when access-group-create is not supported"
- % init_id_help),
],
),

@@ -373,7 +378,6 @@ cmds = (
# TODO: _client.py access_group_create should support multiple
# initiators when creating.
dict(init_id_opt),
- dict(init_type_opt),
dict(sys_id_opt),
],
),
@@ -384,7 +388,6 @@ cmds = (
args=[
dict(ag_id_opt),
dict(init_id_opt),
- dict(init_type_opt),
],
),
dict(
@@ -954,21 +957,21 @@ class CmdLine:

## Creates an access group.
def access_group_create(self, args):
- init_type = ag_init_type_str_to_lsm(args.init_type)
system = _get_item(self.c.systems(), args.sys, "system id")
- access_group = self.c.access_group_create(args.name, args.init,
+ (init_id, init_type) = parse_convert_init(args.init)
+ access_group = self.c.access_group_create(args.name, init_id,
init_type, system)
self.display_data([access_group])

def _add_rm_access_grp_init(self, args, op):
lsm_ag = _get_item(self.c.access_groups(), args.ag, "access group id")
+ (init_id, init_type) = parse_convert_init(args.init)

if op:
- init_type = ag_init_type_str_to_lsm(args.init_type)
- return self.c.access_group_initiator_add(lsm_ag, args.init,
+ return self.c.access_group_initiator_add(lsm_ag, init_id,
init_type)
else:
- return self.c.access_group_initiator_delete(lsm_ag, args.init)
+ return self.c.access_group_initiator_delete(lsm_ag, init_id)

## Adds an initiator from an access group
def access_group_add(self, args):
@@ -985,7 +988,11 @@ class CmdLine:
self.display_data(vols)

def iscsi_chap(self, args):
- self.c.iscsi_chap_auth(args.init, args.in_user,
+ (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)
+
+ self.c.iscsi_chap_auth(init_id, args.in_user,
self.args.in_pass,
self.args.out_user,
self.args.out_pass)
@@ -1266,9 +1273,6 @@ class CmdLine:
if not args.ag and not args.init:
raise ArgError('Neither --ag nor --init is defined. '
'Please specify at lease one')
- if args.init and not args.init_type:
- raise ArgError('In volume-mask command, --init and '
- '--init-type should be defined at the same time')
if args.ag and args.init:
raise ArgError('In volume-mask command, --init is '
'conflicting with --ag')
@@ -1278,8 +1282,8 @@ class CmdLine:
ag = _get_item(self.c.access_groups(), args.ag, 'Access Group ID')

if args.init:
- init_type = ag_init_type_str_to_lsm(args.init_type)
- ag = AccessGroup(0, '', args.init, init_type, vol.system_id)
+ (init_id, init_type) = parse_convert_init(args.init)
+ ag = AccessGroup(0, '', [init_id], init_type, vol.system_id)
self.c.volume_mask(ag, vol)

def volume_unmask(self, args):
--
1.8.3.1
Gris Ge
2014-08-04 22:55:07 UTC
Permalink
Rename ErrorNumber.INVALID_IQN to ErrorNumber.INVALID_INIT.

Signed-off-by: Gris Ge <***@redhat.com>
---
plugin/ontap/ontap.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/plugin/ontap/ontap.py b/plugin/ontap/ontap.py
index d33e230..6cf7ec0 100644
--- a/plugin/ontap/ontap.py
+++ b/plugin/ontap/ontap.py
@@ -44,7 +44,7 @@ e_map = {
na.Filer.ESERVICENOTLICENSED: ErrorNumber.NOT_LICENSED,
na.Filer.ECLONE_LICENSE_EXPIRED: ErrorNumber.NOT_LICENSED,
na.Filer.ECLONE_NOT_LICENSED: ErrorNumber.NOT_LICENSED,
- na.Filer.EINVALID_ISCSI_NAME: ErrorNumber.INVALID_IQN,
+ na.Filer.EINVALID_ISCSI_NAME: ErrorNumber.INVALID_INIT,
na.Filer.ETIMEOUT: ErrorNumber.PLUGIN_TIMEOUT,
na.Filer.EUNKNOWN: ErrorNumber.PLUGIN_ERROR
}
--
1.8.3.1
Gris Ge
2014-08-04 22:55:08 UTC
Permalink
* Convert SNIA format WWPN to LSM format before saving in AccessGroup.
* Convert LSM WWPN to SNIA format before sending to WBEM.

Signed-off-by: Gris Ge <***@redhat.com>
---
plugin/smispy/smis.py | 83 +++++++++++++++++++++++++++++----------------------
1 file changed, 47 insertions(+), 36 deletions(-)

diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index 6299d1c..a4122fc 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -137,6 +137,17 @@ def _hex_string_format(hex_str, length, every):
return ':'.join(hex_str[i:i + every] for i in range(0, length, every))


+def _lsm_init_id_to_snia(lsm_init_id):
+ """
+ If lsm_init_id is a WWPN, convert it to SNIA format:
+ [0-9A-F]{16}
+ If not, return directly.
+ """
+ if AccessGroup.init_id_validate(lsm_init_id,
+ AccessGroup.INIT_TYPE_WWPN):
+ return lsm_init_id.replace(':', '').upper()
+ return lsm_init_id
+
class DMTF(object):
# CIM_StorageHardwareID['IDType']
ID_TYPE_OTHER = pywbem.Uint16(1)
@@ -1549,23 +1560,35 @@ class Smis(IStorageAreaNetwork):
# filter out the mapping SPC.
return cim_spc_pros

- @staticmethod
- def _init_type_of_cim_inits(cim_inits):
- ag_init_types = [_dmtf_init_type_to_lsm(i) for i in cim_inits]
+ def _cim_inits_to_lsm(self, cim_inits):
+ """
+ Retrive AccessGroup.init_ids and AccessGroup.init_type from
+ a list of CIM_StorageHardwareID.
+ """
+ init_ids = []
init_type = AccessGroup.INIT_TYPE_UNKNOWN
- ag_init_type_dict = {}
- for ag_init_type in ag_init_types:
- ag_init_type_dict[ag_init_type] = 1
- if len(ag_init_type_dict) == 1:
- init_type = ag_init_types[0]
- elif (len(ag_init_type_dict) == 2 and
- AccessGroup.INIT_TYPE_ISCSI_IQN in ag_init_type_dict.keys() and
- AccessGroup.INIT_TYPE_WWPN in ag_init_type_dict.keys()):
+ init_types = []
+ for cim_init in cim_inits:
+ init_type = _dmtf_init_type_to_lsm(cim_init)
+ if init_type == AccessGroup.INIT_TYPE_WWPN:
+ init_ids.append(
+ AccessGroup.wwpn_to_lsm_type(self._init_id(cim_init)))
+ init_types.append(init_type)
+ elif init_type == AccessGroup.INIT_TYPE_ISCSI_IQN:
+ init_ids.append(self._init_id(cim_init))
+ init_types.append(init_type)
+ # Skip if not a iscsi initiator IQN or WWPN.
+ continue
+
+ init_type_dict = {}
+ for cur_init_type in init_types:
+ init_type_dict[cur_init_type] = 1
+
+ if len(init_type_dict) == 1:
+ init_type = init_types[0]
+ elif len(init_type_dict) == 2:
init_type = AccessGroup.INIT_TYPE_ISCSI_WWPN_MIXED
- else:
- # We have unknown mixed initiator type
- init_type = AccessGroup.INIT_TYPE_OTHER
- return init_type
+ return (init_ids, init_type)

def _cim_spc_to_lsm(self, cim_spc, system_id=None):
if system_id is None:
@@ -1576,24 +1599,9 @@ class Smis(IStorageAreaNetwork):
cim_init_pros = self._property_list_of_id('Initiator')
cim_init_pros.extend(['IDType'])
cim_inits = self._cim_init_of_spc(cim_spc.path, cim_init_pros)
- ag_init_ids = [self._init_id(i) for i in cim_inits]
- ag_init_types = [_dmtf_init_type_to_lsm(i) for i in cim_inits]
- init_type = AccessGroup.INIT_TYPE_UNKNOWN
- ag_init_type_dict = {}
- for ag_init_type in ag_init_types:
- ag_init_type_dict[ag_init_type] = 1
- if len(ag_init_type_dict) == 1:
- init_type = ag_init_types[0]
- elif (len(ag_init_type_dict) == 2 and
- AccessGroup.INIT_TYPE_ISCSI_IQN in ag_init_type_dict.keys() and
- AccessGroup.INIT_TYPE_WWPN in ag_init_type_dict.keys()):
- init_type = AccessGroup.INIT_TYPE_ISCSI_WWPN_MIXED
- else:
- # We have unknown mixed initiator type
- init_type = AccessGroup.INIT_TYPE_OTHER
-
+ (init_ids, init_type) = self._cim_inits_to_lsm(cim_inits)
sys_id = self._sys_id_child(cim_spc)
- return AccessGroup(ag_id, ag_name, ag_init_ids, init_type, sys_id)
+ return AccessGroup(ag_id, ag_name, init_ids, init_type, sys_id)

def _new_vol_from_job(self, job):
"""
@@ -2954,6 +2962,7 @@ class Smis(IStorageAreaNetwork):
@handle_cim_errors
def access_group_initiator_add(self, access_group, init_id, init_type,
flags=0):
+ init_id = _lsm_init_id_to_snia(init_id)
mask_type = self._mask_type(raise_error=True)

if mask_type == Smis.MASK_TYPE_GROUP:
@@ -3088,6 +3097,7 @@ class Smis(IStorageAreaNetwork):

@handle_cim_errors
def access_group_initiator_delete(self, access_group, init_id, flags=0):
+ init_id = _lsm_init_id_to_snia(init_id)
mask_type = self._mask_type(raise_error=True)

if mask_type == Smis.MASK_TYPE_GROUP:
@@ -4691,9 +4701,8 @@ class Smis(IStorageAreaNetwork):
cim_init_pros = self._property_list_of_id('Initiator')
cim_init_pros.extend(['IDType'])
cim_inits = self._cim_init_of_init_mg(cim_init_mg.path, cim_init_pros)
- ag_init_ids = [self._init_id(i) for i in cim_inits]
- init_type = Smis._init_type_of_cim_inits(cim_inits)
- return AccessGroup(ag_id, ag_name, ag_init_ids, init_type, system_id)
+ (init_ids, init_type) = self._cim_inits_to_lsm(cim_inits)
+ return AccessGroup(ag_id, ag_name, init_ids, init_type, system_id)

def _wait_invoke(self, rc, out, out_key=None, expect_class=None,
flag_out_array=False,):
@@ -4839,6 +4848,8 @@ class Smis(IStorageAreaNetwork):
confliction.
1. Create CIM_InitiatorMaskingGroup
"""
+ org_init_id = init_id
+ init_id = _lsm_init_id_to_snia(init_id)
if self.fallback_mode:
raise LsmError(ErrorNumber.NO_SUPPORT,
"access_group_create() is not supported in "
@@ -4900,7 +4911,7 @@ class Smis(IStorageAreaNetwork):
# Name does not match.
raise LsmError(ErrorNumber.EXISTS_INITIATOR,
"Initiator %s already exist in other access group "
- % init_id +
+ % org_init_id +
"with name %s and ID: %s" %
(exist_cim_init_mgs[0]['ElementName'],
md5(exist_cim_init_mgs[0]['DeviceID'])))
--
1.8.3.1
Gris Ge
2014-08-04 22:55:09 UTC
Permalink
* Fix these problems:
1. _cim_init_check_or_create() incorrect return CIMInstanceName when
creation needed.
# Now, method renamed to _cim_init_path_check_or_create().
# will return CIMInstanceName always.

2. The confliction error will be raise as CIMError in InvokeMethod()
command, not in _wait_invoke() method.
# Now, we do confliction check when error happened.
# Not check pre-excute, which can save some time for most legal use.

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

diff --git a/plugin/smispy/smis.py b/plugin/smispy/smis.py
index a4122fc..a9e517b 100644
--- a/plugin/smispy/smis.py
+++ b/plugin/smispy/smis.py
@@ -148,6 +148,7 @@ def _lsm_init_id_to_snia(lsm_init_id):
return lsm_init_id.replace(':', '').upper()
return lsm_init_id

+
class DMTF(object):
# CIM_StorageHardwareID['IDType']
ID_TYPE_OTHER = pywbem.Uint16(1)
@@ -2865,23 +2866,15 @@ class Smis(IStorageAreaNetwork):

return search_property(rc, search_key, search_value)

- def _cim_init_check_or_create(self, cim_sys_path, init_id, init_type):
+ def _cim_init_path_check_or_create(self, cim_sys_path, init_id, init_type):
"""
Check whether CIM_StorageHardwareID exists, if not, create new one.
"""
cim_init = self._get_cim_instance_by_id(
- 'Initiator', init_id, raise_error=False, property_list=['IDType'])
+ 'Initiator', init_id, raise_error=False)

- # In rare chance, cim_init might holding different init_type
- # As ExposePaths is using init_id, hence we raise error instead of
- # creating new one
if cim_init:
- if _dmtf_init_type_to_lsm(cim_init) != init_type:
- raise LsmError(ErrorNumber.EXISTS_INITIATOR,
- "Another initiator exists with the same ID "
- "%s, but different init_type %d:" %
- (init_id, _dmtf_init_type_to_lsm(cim_init)))
- return cim_init
+ return cim_init.path

# Create new one
dmtf_id_type = _lsm_init_type_to_dmtf(init_type)
@@ -2890,14 +2883,13 @@ class Smis(IStorageAreaNetwork):
"SMI-S Plugin does not support init_type %d" %
init_type)

- cim_init = self._cim_init_create(
+ return self._cim_init_path_create(
cim_sys_path, init_id, dmtf_id_type)

- return cim_init
-
- def _cim_init_create(self, cim_sys_path, init_id, dmtf_id_type):
+ def _cim_init_path_create(self, cim_sys_path, init_id, dmtf_id_type):
"""
Create a CIM_StorageHardwareID.
+ Return CIMInstanceName
Raise error if failed. Return if pass.
"""
cim_hw_srv_path = self._get_cim_service_path(
@@ -2932,11 +2924,10 @@ class Smis(IStorageAreaNetwork):

# Check whether already added.
for exist_cim_init in exist_cim_inits:
- if self._init_id(exist_cim_init) == init_id and \
- _dmtf_init_type_to_lsm(exist_cim_init) == init_type:
- return copy.deepcopy(access_group)
+ if self._init_id(exist_cim_init) == init_id:
+ return copy.deepcopy(access_group)

- cim_init = self._cim_init_check_or_create(
+ cim_init_path = self._cim_init_path_check_or_create(
cim_sys.path, init_id, init_type)

cim_gmm_path = self._get_cim_service_path(
@@ -2944,7 +2935,7 @@ class Smis(IStorageAreaNetwork):

in_params = {
'MaskingGroup': cim_init_mg.path,
- 'Members': [cim_init.path],
+ 'Members': [cim_init_path],
}
(rc, out) = self._c.InvokeMethod('AddMembers',
cim_gmm_path, **in_params)
@@ -2991,19 +2982,12 @@ class Smis(IStorageAreaNetwork):

for exist_cim_init in exist_cim_inits:
if self._init_id(exist_cim_init) == init_id:
- if _dmtf_init_type_to_lsm(exist_cim_init) != init_type:
- raise LsmError(ErrorNumber.EXISTS_INITIATOR,
- "Another initiator exists with the same ID "
- "%s, but different init_type %d:" %
- (init_id,
- _dmtf_init_type_to_lsm(exist_cim_init)))
-
return copy.deepcopy(access_group)

# Check to see if we have this initiator already, if not we
# create it and then add to the view.

- self._cim_init_check_or_create(cim_sys.path, init_id, init_type)
+ self._cim_init_path_check_or_create(cim_sys.path, init_id, init_type)

cim_ccs_path = self._get_cim_service_path(
cim_sys.path, 'CIM_ControllerConfigurationService')
@@ -4892,44 +4876,60 @@ class Smis(IStorageAreaNetwork):
"iSCSI target port, which not allow creating "
"iSCSI IQN access group")

- cim_init = self._cim_init_check_or_create(
+ cim_init_path = self._cim_init_path_check_or_create(
cim_sys.path, init_id, init_type)

- cim_init_mg_pros = self._cim_init_mg_pros()
- exist_cim_init_mgs = self._c.Associators(
- cim_init.path,
- AssocClass='CIM_MemberOfCollection',
- ResultClass='CIM_InitiatorMaskingGroup',
- PropertyList=cim_init_mg_pros)
-
- if len(exist_cim_init_mgs) != 0:
- for exist_cim_init_mg in exist_cim_init_mgs:
- if exist_cim_init_mg['ElementName'] == name:
- return self._cim_init_mg_to_lsm(
- exist_cim_init_mg, system.id)
-
- # Name does not match.
- raise LsmError(ErrorNumber.EXISTS_INITIATOR,
- "Initiator %s already exist in other access group "
- % org_init_id +
- "with name %s and ID: %s" %
- (exist_cim_init_mgs[0]['ElementName'],
- md5(exist_cim_init_mgs[0]['DeviceID'])))
-
# Create CIM_InitiatorMaskingGroup
cim_gmm_path = self._get_cim_service_path(
cim_sys.path, 'CIM_GroupMaskingMappingService')

in_params = {'GroupName': name,
- 'Members': [cim_init.path],
+ 'Members': [cim_init_path],
'Type': DMTF.MASK_GROUP_TYPE_INIT}
+ try:
+ (rc, out) = self._c.InvokeMethod(
+ 'CreateGroup', cim_gmm_path, **in_params)

- (rc, out) = self._c.InvokeMethod(
- 'CreateGroup', cim_gmm_path, **in_params)
+ cim_init_mg_path = self._wait_invoke(
+ rc, out, out_key='MaskingGroup',
+ expect_class='CIM_InitiatorMaskingGroup')
+
+ except (LsmError, CIMError):
+ # Check possible failure
+ # 1. Initiator already exist in other group.
+ # If that group hold the same name as requested.
+ # We consider as a duplicate call, return the exist one.
+ exist_cim_init_mgs = self._c.Associators(
+ cim_init_path,
+ AssocClass='CIM_MemberOfCollection',
+ ResultClass='CIM_InitiatorMaskingGroup',
+ PropertyList=cim_init_mg_pros)

- cim_init_mg_path = self._wait_invoke(
- rc, out, out_key='MaskingGroup',
- expect_class='CIM_InitiatorMaskingGroup')
+ if len(exist_cim_init_mgs) != 0:
+ for exist_cim_init_mg in exist_cim_init_mgs:
+ if exist_cim_init_mg['ElementName'] == name:
+ return self._cim_init_mg_to_lsm(
+ exist_cim_init_mg, system.id)
+
+ # Name does not match.
+ raise LsmError(ErrorNumber.EXISTS_INITIATOR,
+ "Initiator %s " % old_init_id +
+ "already exist in other access group "
+ "with name %s and ID: %s" %
+ (exist_cim_init_mgs[0]['ElementName'],
+ 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.
+ 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:
+ if exist_cim_init_mg['ElementName'] == name:
+ raise LsmError(ErrorNumber.EXISTS_ACCESS_GROUP,
+ "Requested name %s is used by " % name +
+ "another access group, but not containing "
+ "requested initiator %s" % old_init_id)
+ raise

cim_init_mg = self._c.GetInstance(
cim_init_mg_path, PropertyList=cim_init_mg_pros, LocalOnly=False)
--
1.8.3.1
Tony Asleson
2014-08-06 00:04:33 UTC
Permalink
Series committed.

Thanks,
Tony
Post by Gris Ge
I combined tony's patches with my V2 patches.
1. Fix bugs found by OBS compile.
2. Change rpm spec and etc to support OBS build.
3. Access Group WWPN form.
4. Clean up AccessGroup.
5. Fix bugs of SMI-S plugin about access group.
https://build.opensuse.org/project/monitor/home:cathay4t:libstoragemgmt-test
rpm spec: fix for OBS build
test: allowing runtest to show log of lsmd
test: empty expected_absent capabilities check
lsmcli: use python-ordereddict for python <= 2.6
Remove INIT_TYPE_WWNN and etc unused initiator type
Python API: standardize the WWPN
C API: Rename LSM_ERR_INVALID_IQN to LSM_ERR_INVALID_INIT
lsmcli: Remove --init-type argument
ontap plugin: Rename INVALID_IQN to INVALID_INIT
SMI-S plugin: standardize the WWPN
SMI-S plugin: Fix access group bugs
Remove v7k plugin
cmdline.py: Check before reference
C API: Simplify lsm_capability_set_n
c_binding/include/libstoragemgmt/libstoragemgmt.h | 4 +-
.../libstoragemgmt/libstoragemgmt_capabilities.h | 2 +
.../include/libstoragemgmt/libstoragemgmt_error.h | 3 +-
.../libstoragemgmt/libstoragemgmt_plug_interface.h | 25 +-
.../include/libstoragemgmt/libstoragemgmt_types.h | 15 +-
c_binding/lsm_datatypes.cpp | 28 +-
c_binding/lsm_datatypes.hpp | 12 -
c_binding/lsm_mgmt.cpp | 6 +-
c_binding/lsm_plugin_ipc.cpp | 6 +-
configure.ac | 15 -
daemon/lsm_daemon.c | 1 +
doc/man/lsmcli.1.in | 12 +-
packaging/libstoragemgmt.spec.in | 88 ++---
plugin/Makefile.am | 9 -
plugin/ontap/ontap.py | 2 +-
plugin/sim/simarray.py | 9 +-
plugin/simc/simc_lsmplugin.c | 11 +-
plugin/smispy/smis.py | 222 +++++++------
plugin/v7k/__init__.py | 0
plugin/v7k/ibmv7k.py | 364 ---------------------
plugin/v7k/v7k_lsmplugin | 36 --
python_binding/lsm/_client.py | 4 +
python_binding/lsm/_common.py | 2 +-
python_binding/lsm/_data.py | 99 +++++-
test/cmdtest.py | 7 +-
test/runtests.sh | 73 +++--
test/tester.c | 86 ++---
tools/lsmcli/cmdline.py | 61 ++--
tools/lsmcli/data_display.py | 11 +-
29 files changed, 388 insertions(+), 825 deletions(-)
delete mode 100644 plugin/v7k/__init__.py
delete mode 100644 plugin/v7k/ibmv7k.py
delete mode 100755 plugin/v7k/v7k_lsmplugin
Continue reading on narkive:
Loading...