summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rtslib/__init__.py2
-rw-r--r--rtslib/alua.py385
2 files changed, 387 insertions, 0 deletions
diff --git a/rtslib/__init__.py b/rtslib/__init__.py
index c4b3cb6..48aab2a 100644
--- a/rtslib/__init__.py
+++ b/rtslib/__init__.py
@@ -33,6 +33,8 @@ from .tcm import FileIOStorageObject, BlockStorageObject
from .tcm import PSCSIStorageObject, RDMCPStorageObject, UserBackedStorageObject
from .tcm import StorageObjectFactory
+from .alua import ALUATargetPortGroup
+
__version__ = 'GIT_VERSION'
__author__ = "Jerome Martin <jxm@risingtidesystems.com>"
__url__ = "http://www.risingtidesystems.com"
diff --git a/rtslib/alua.py b/rtslib/alua.py
new file mode 100644
index 0000000..86a4dd3
--- /dev/null
+++ b/rtslib/alua.py
@@ -0,0 +1,385 @@
+'''
+Implements the RTS ALUA Target Port Group class.
+
+This file is part of RTSLib.
+Copyright (c) 2016 by Red Hat, Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may
+not use this file except in compliance with the License. You may obtain
+a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ License for the specific language governing permissions and limitations
+ under the License.
+'''
+
+from .node import CFSNode
+from .utils import RTSLibError, fread, fwrite
+
+alua_rw_params = ['alua_access_state', 'alua_access_status',
+ 'alua_write_metadata', 'alua_access_type', 'preferred',
+ 'nonop_delay_msecs', 'trans_delay_msecs',
+ 'implicit_trans_secs', 'alua_support_offline',
+ 'alua_support_standby', 'alua_support_transitioning',
+ 'alua_support_active_nonoptimized',
+ 'alua_support_unavailable', 'alua_support_active_optimized']
+alua_ro_params = ['tg_pt_gp_id', 'members', 'alua_support_lba_dependent']
+alua_types = ['None', 'Implicit', 'Explicit', 'Implicit and Explicit']
+alua_statuses = ['None', 'Altered by Explicit STPG', 'Altered by Implicit ALUA']
+
+class ALUATargetPortGroup(CFSNode):
+ """
+ ALUA Target Port Group interface
+ """
+
+ def __repr__(self):
+ return "<ALUA TPG %s>" % self.name
+
+ def __init__(self, storage_object, name, tag=None):
+ """
+ @param storage_object: backstore storage object to create ALUA group for
+ @param name: name of ALUA group
+ @param tag: target port group id. If not passed in, try to look
+ up existing ALUA TPG with the same name
+ """
+
+ # default_tg_pt_gp takes tag 1
+ if tag is not None and (tag > 65535 or tag < 1):
+ raise RTSLibError("The TPG Tag must be between 1 and 65535")
+
+ super(ALUATargetPortGroup, self).__init__()
+ self.name = name
+ self.storage_object = storage_object
+
+ self._path = "%s/alua/%s" % (storage_object.path, name)
+
+ if tag is not None:
+ try:
+ self._create_in_cfs_ine('create')
+ except OSError as msg:
+ raise RTSLibError(msg)
+
+ try:
+ fwrite("%s/tg_pt_gp_id" % self._path, tag)
+ except IOError as msg:
+ self.delete()
+ raise RTSLibError("Cannot set id to %d: %s" % (tag, str(msg)))
+ else:
+ try:
+ self._create_in_cfs_ine('lookup')
+ except OSError as msg:
+ raise RTSLibError(msg)
+
+ # Public
+
+ def delete(self):
+ """
+ Delete ALUA TPG and unmap from LUNs
+ """
+ self._check_self()
+
+ # default_tg_pt_gp created by the kernel and cannot be deleted
+ if self.name == "default_tg_pt_gp":
+ raise RTSLibError("Can not delete default_tg_pt_gp")
+
+ # This will reset the ALUA tpg to default_tg_pt_gp
+ super(ALUATargetPortGroup, self).delete()
+
+ def _get_alua_access_state(self):
+ self._check_self()
+ path = "%s/alua_access_state" % self.path
+ return int(fread(path))
+
+ def _set_alua_access_state(self, newstate):
+ self._check_self()
+ path = "%s/alua_access_state" % self.path
+ try:
+ fwrite(path, str(int(newstate)))
+ except IOError as e:
+ raise RTSLibError("Cannot change ALUA state: %s" % e)
+
+ def _get_alua_access_status(self):
+ self._check_self()
+ path = "%s/alua_access_status" % self.path
+ status = fread(path)
+ return alua_statuses.index(status)
+
+ def _set_alua_access_status(self, newstatus):
+ self._check_self()
+ path = "%s/alua_access_status" % self.path
+ try:
+ fwrite(path, str(int(newstatus)))
+ except IOError as e:
+ raise RTSLibError("Cannot change ALUA status: %s" % e)
+
+ def _get_alua_access_type(self):
+ self._check_self()
+ path = "%s/alua_access_type" % self.path
+ alua_type = fread(path)
+ return alua_types.index(alua_type)
+
+ def _set_alua_access_type(self, access_type):
+ self._check_self()
+ path = "%s/alua_access_type" % self.path
+ try:
+ fwrite(path, str(int(access_type)))
+ except IOError as e:
+ raise RTSLibError("Cannot change ALUA access type: %s" % e)
+
+ def _get_preferred(self):
+ self._check_self()
+ path = "%s/preferred" % self.path
+ return int(fread(path))
+
+ def _set_preferred(self, pref):
+ self._check_self()
+ path = "%s/preferred" % self.path
+ try:
+ fwrite(path, str(int(pref)))
+ except IOError as e:
+ raise RTSLibError("Cannot set preferred: %s" % e)
+
+ def _get_alua_write_metadata(self):
+ self._check_self()
+ path = "%s/alua_write_metadata" % self.path
+ return int(fread(path))
+
+ def _set_alua_write_metadata(self, pref):
+ self._check_self()
+ path = "%s/alua_write_metadata" % self.path
+ try:
+ fwrite(path, str(int(pref)))
+ except IOError as e:
+ raise RTSLibError("Cannot set alua_write_metadata: %s" % e)
+
+ def _get_alua_support_active_nonoptimized(self):
+ self._check_self()
+ path = "%s/alua_support_active_nonoptimized" % self.path
+ return int(fread(path))
+
+ def _set_alua_support_active_nonoptimized(self, enabled):
+ self._check_self()
+ path = "%s/alua_support_active_nonoptimized" % self.path
+ try:
+ fwrite(path, str(int(enabled)))
+ except IOError as e:
+ raise RTSLibError("Cannot set alua_support_active_nonoptimized: %s" % e)
+
+ def _get_alua_support_active_optimized(self):
+ self._check_self()
+ path = "%s/alua_support_active_optimized" % self.path
+ return int(fread(path))
+
+ def _set_alua_support_active_optimized(self, enabled):
+ self._check_self()
+ path = "%s/alua_support_active_optimized" % self.path
+ try:
+ fwrite(path, str(int(enabled)))
+ except IOError as e:
+ raise RTSLibError("Cannot set alua_support_active_optimized: %s" % e)
+
+ def _get_alua_support_offline(self):
+ self._check_self()
+ path = "%s/alua_support_offline" % self.path
+ return int(fread(path))
+
+ def _set_alua_support_offline(self, enabled):
+ self._check_self()
+ path = "%s/alua_support_offline" % self.path
+ try:
+ fwrite(path, str(int(enabled)))
+ except IOError as e:
+ raise RTSLibError("Cannot set alua_support_offline: %s" % e)
+
+ def _get_alua_support_unavailable(self):
+ self._check_self()
+ path = "%s/alua_support_unavailable" % self.path
+ return int(fread(path))
+
+ def _set_alua_support_unavailable(self, enabled):
+ self._check_self()
+ path = "%s/alua_support_unavailable" % self.path
+ try:
+ fwrite(path, str(int(enabled)))
+ except IOError as e:
+ raise RTSLibError("Cannot set alua_support_unavailable: %s" % e)
+
+ def _get_alua_support_standby(self):
+ self._check_self()
+ path = "%s/alua_support_standby" % self.path
+ return int(fread(path))
+
+ def _set_alua_support_standby(self, enabled):
+ self._check_self()
+ path = "%s/alua_support_standby" % self.path
+ try:
+ fwrite(path, str(int(enabled)))
+ except IOError as e:
+ raise RTSLibError("Cannot set alua_support_standby: %s" % e)
+
+ def _get_alua_support_transitioning(self):
+ self._check_self()
+ path = "%s/alua_support_transitioning" % self.path
+ return int(fread(path))
+
+ def _set_alua_support_transitioning(self, enabled):
+ self._check_self()
+ path = "%s/alua_support_transitioning" % self.path
+ try:
+ fwrite(path, str(int(enabled)))
+ except IOError as e:
+ raise RTSLibError("Cannot set alua_support_transitioning: %s" % e)
+
+ def _get_alua_support_lba_dependent(self):
+ self._check_self()
+ path = "%s/alua_support_lba_dependent" % self.path
+ return int(fread(path))
+
+ def _get_members(self):
+ self._check_self()
+ path = "%s/members" % self.path
+ return fread(path)
+
+ def _get_tg_pt_gp_id(self):
+ self._check_self()
+ path = "%s/tg_pt_gp_id" % self.path
+ return int(fread(path))
+
+ def _get_trans_delay_msecs(self):
+ self._check_self()
+ path = "%s/trans_delay_msecs" % self.path
+ return int(fread(path))
+
+ def _set_trans_delay_msecs(self, secs):
+ self._check_self()
+ path = "%s/trans_delay_msecs" % self.path
+ try:
+ fwrite(path, str(int(secs)))
+ except IOError as e:
+ raise RTSLibError("Cannot set trans_delay_msecs: %s" % e)
+
+ def _get_implicit_trans_secs(self):
+ self._check_self()
+ path = "%s/implicit_trans_secs" % self.path
+ return int(fread(path))
+
+ def _set_implicit_trans_secs(self, secs):
+ self._check_self()
+ path = "%s/implicit_trans_secs" % self.path
+ try:
+ fwrite(path, str(int(secs)))
+ except IOError as e:
+ raise RTSLibError("Cannot set implicit_trans_secs: %s" % e)
+
+ def _get_nonop_delay_msecs(self):
+ self._check_self()
+ path = "%s/nonop_delay_msecs" % self.path
+ return int(fread(path))
+
+ def _set_nonop_delay_msecs(self, delay):
+ self._check_self()
+ path = "%s/nonop_delay_msecs" % self.path
+ try:
+ fwrite(path, str(int(delay)))
+ except IOError as e:
+ raise RTSLibError("Cannot set nonop_delay_msecs: %s" % e)
+
+ def dump(self):
+ d = super(ALUATargetPortGroup, self).dump()
+ d['name'] = self.name
+ d['tg_pt_gp_id'] = self.tg_pt_gp_id
+ for param in alua_rw_params:
+ d[param] = getattr(self, param, None)
+ return d
+
+ alua_access_state = property(_get_alua_access_state, _set_alua_access_state,
+ doc="Get or set ALUA state. "
+ "0 = Active/optimized, "
+ "1 = Active/non-optimized, "
+ "2 = Standby, "
+ "3 = Unavailable, "
+ "4 = LBA Dependent, "
+ "14 = Offline, "
+ "15 = Transitioning")
+
+ alua_access_type = property(_get_alua_access_type, _set_alua_access_type,
+ doc="Get or set ALUA access type. "
+ "1 = Implicit, 2 = Explicit, 3 = Both")
+
+ alua_access_status = property(_get_alua_access_status,
+ _set_alua_access_status,
+ doc="Get or set ALUA access status. "
+ "0 = None, "
+ "1 = Altered by Explicit STPG, "
+ "2 = Altered by Implicit ALUA")
+
+ preferred = property(_get_preferred, _set_preferred,
+ doc="Get or set preferred bit. 1 = Pref, 0 Not-Pre")
+
+ alua_write_metadata = property(_get_alua_write_metadata,
+ _set_alua_write_metadata,
+ doc="Get or set alua_write_metadata flag. "
+ "enable (1) or disable (0)")
+
+ tg_pt_gp_id = property(_get_tg_pt_gp_id, doc="Get ALUA Target Port Group ID")
+
+ members = property(_get_members, doc="Get LUNs in Target Port Group")
+
+ alua_support_active_nonoptimized = property(_get_alua_support_active_nonoptimized,
+ _set_alua_support_active_nonoptimized,
+ doc="Enable (1) or disable (0) "
+ "Active/non-optimized support")
+
+ alua_support_active_optimized = property(_get_alua_support_active_optimized,
+ _set_alua_support_active_optimized,
+ doc="Enable (1) or disable (0) "
+ "Active/optimized support")
+
+ alua_support_offline = property(_get_alua_support_offline,
+ _set_alua_support_offline,
+ doc="Enable (1) or disable (0) "
+ "offline support")
+
+ alua_support_unavailable = property(_get_alua_support_unavailable,
+ _set_alua_support_unavailable,
+ doc="enable (1) or disable (0) "
+ "unavailable support")
+
+ alua_support_standby = property(_get_alua_support_standby,
+ _set_alua_support_standby,
+ doc="enable (1) or disable (0) "
+ "standby support")
+
+ alua_support_lba_dependent = property(_get_alua_support_lba_dependent,
+ doc="show lba_dependent support "
+ "enabled (1) or disabled (0)")
+
+ alua_support_transitioning = property(_get_alua_support_transitioning,
+ _set_alua_support_transitioning,
+ doc="enable (1) or disable (0) "
+ "transitioning support")
+
+ trans_delay_msecs = property(_get_trans_delay_msecs,
+ _set_trans_delay_msecs,
+ doc="msecs to delay state transition")
+
+ implicit_trans_secs = property(_get_implicit_trans_secs,
+ _set_implicit_trans_secs,
+ doc="implicit transition time limit")
+
+ nonop_delay_msecs = property(_get_nonop_delay_msecs, _set_nonop_delay_msecs,
+ doc="msecs to delay IO when non-optimized")
+
+ @classmethod
+ def setup(cls, storage_obj, alua_tpg, err_func):
+ name = alua_tpg['name']
+ if name == 'default_tg_pt_gp':
+ return
+
+ alua_tpg_obj = cls(storage_obj, name, alua_tpg['tg_pt_gp_id'])
+ for param in alua_rw_params:
+ setattr(alua_tpg_obj, param, alua_tpg[param])