diff --git a/SOURCES/0007-alua-enable-alua-for-pscsi-tcmu-if-kernel-reports-su.patch b/SOURCES/0007-alua-enable-alua-for-pscsi-tcmu-if-kernel-reports-su.patch new file mode 100644 index 0000000..a7e9321 --- /dev/null +++ b/SOURCES/0007-alua-enable-alua-for-pscsi-tcmu-if-kernel-reports-su.patch @@ -0,0 +1,113 @@ +From 86fed9fdab8803fd8d321c8242097e7b4f952ada Mon Sep 17 00:00:00 2001 +From: Maurizio Lombardi +Date: Tue, 27 Mar 2018 14:50:09 +0200 +Subject: [PATCH] alua: enable alua for pscsi/tcmu if kernel reports support + +4.14 (it is currently the 4.13 feature window and I think we will +miss it) will add this patch + +https://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending.git/commit/?h=for-next&id=c17d5d5f51f72f24e0e17a4450ae5010bf6962d9 + +commit c17d5d5f51f72f24e0e17a4450ae5010bf6962d9 +Author: Mike Christie +Date: Mon Jul 10 14:53:31 2017 -0500 + + target: export lio pgr/alua support as device attr + +which has the lio device report if it supports lio based ALUA. +We can then check this configfs file and know if we are using +a modern kernel with support and not worry about possibly crashing +the system. + +Signed-off-by: Maurizio Lombardi +--- + rtslib/alua.py | 4 ---- + rtslib/tcm.py | 23 ++++++++++++++++++----- + 2 files changed, 18 insertions(+), 9 deletions(-) + +diff --git a/rtslib/alua.py b/rtslib/alua.py +index 390e74a..fadc225 100644 +--- a/rtslib/alua.py ++++ b/rtslib/alua.py +@@ -46,10 +46,6 @@ class ALUATargetPortGroup(CFSNode): + @param tag: target port group id. If not passed in, try to look + up existing ALUA TPG with the same name + """ +- # kernel partially sets up default_tg_pt_gp and will let you partially +- # setup ALUA groups for pscsi and user, but writing to some of the +- # files will crash the kernel. Just fail to even create groups until +- # the kernel is fixed. + if storage_object.alua_supported is False: + raise RTSLibALUANotSupported("Backend does not support ALUA setup") + +diff --git a/rtslib/tcm.py b/rtslib/tcm.py +index aa3530a..bf681fe 100644 +--- a/rtslib/tcm.py ++++ b/rtslib/tcm.py +@@ -32,6 +32,19 @@ from .utils import convert_scsi_path_to_hctl, convert_scsi_hctl_to_path + from .utils import is_dev_in_use, get_blockdev_type + from .utils import get_size_for_blk_dev, get_size_for_disk_name + ++def storage_object_get_alua_support_attr(so): ++ ''' ++ Helper function that can be called by passthrough type of backends. ++ ''' ++ try: ++ if int(so.get_attribute("alua_support")) == 1: ++ return True ++ except RTSLibError: ++ pass ++ # Default to false because older kernels will crash when ++ # reading/writing to some ALUA files when ALUA was not ++ # fully supported by pscsi and tcmu. ++ return False + + class StorageObject(CFSNode): + ''' +@@ -227,7 +240,7 @@ class StorageObject(CFSNode): + + def _get_alua_supported(self): + ''' +- Children should override and return false if ALUA setup is not supported. ++ Children should override if the backend did not always support ALUA + ''' + self._check_self() + return True +@@ -420,7 +433,7 @@ class PSCSIStorageObject(StorageObject): + + def _get_alua_supported(self): + self._check_self() +- return False ++ return storage_object_get_alua_support_attr(self) + + # PSCSIStorageObject public stuff + +@@ -442,7 +455,7 @@ class PSCSIStorageObject(StorageObject): + lun = property(_get_lun, + doc="Get the SCSI device LUN") + alua_supported = property(_get_alua_supported, +- doc="ALUA cannot be setup with rtslib, so False is returned."); ++ doc="Returns true if ALUA can be setup. False if not supported.") + + def dump(self): + d = super(PSCSIStorageObject, self).dump() +@@ -826,14 +839,14 @@ class UserBackedStorageObject(StorageObject): + + def _get_alua_supported(self): + self._check_self() +- return False ++ return storage_object_get_alua_support_attr(self) + + size = property(_get_size, + doc="Get the size in bytes.") + config = property(_get_config, + doc="Get the TCMU config.") + alua_supported = property(_get_alua_supported, +- doc="ALUA cannot be setup with rtslib, so False is returned."); ++ doc="Returns true if ALUA can be setup. False if not supported.") + + def dump(self): + d = super(UserBackedStorageObject, self).dump() +-- +1.8.3.1 + diff --git a/SOURCES/0008-save_to_file-support-saveconfig-at-storage-object-le.patch b/SOURCES/0008-save_to_file-support-saveconfig-at-storage-object-le.patch new file mode 100644 index 0000000..73f69da --- /dev/null +++ b/SOURCES/0008-save_to_file-support-saveconfig-at-storage-object-le.patch @@ -0,0 +1,143 @@ +From 7cc8531b03f5391f8c2fa1208c4f6b6e7b030b66 Mon Sep 17 00:00:00 2001 +From: Maurizio Lombardi +Date: Tue, 10 Apr 2018 15:18:37 +0200 +Subject: [PATCH] save_to_file: support saveconfig at storage object level + +Added an option to update configuration for single storage object at a time. +As of today changes done for one storage object needs the whole configuration +update. This option will enable us to save changes done to a give storage object. + +$ targetcli /backstores/user:glfs/block1 help +[...] +AVAILABLE COMMANDS +[...] + - saveconfig [savefile] + - set [group] [parameter=value...] + - status + - version + +$ targetcli /backstores/user:glfs/block1 saveconfig +Storage Object 'user:block1' config saved to /etc/target/saveconfig.json + +Signed-off-by: Prasanna Kumar Kalever +Signed-off-by: Maurizio Lombardi +--- + rtslib/root.py | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 84 insertions(+), 2 deletions(-) + +diff --git a/rtslib/root.py b/rtslib/root.py +index 99a25b7..c6697cf 100644 +--- a/rtslib/root.py ++++ b/rtslib/root.py +@@ -148,6 +148,83 @@ class RTSRoot(CFSNode): + def __str__(self): + return "rtslib" + ++ def _get_saveconf(self, so_path, save_file): ++ ''' ++ Fetch the configuration of all the blocks and return conf with ++ updated storageObject info and its related target configuraion of ++ given storage object path ++ ''' ++ current = self.dump() ++ ++ with open(save_file, "r") as f: ++ saveconf = json.loads(f.read()) ++ f.close() ++ ++ fetch_cur_so = False ++ fetch_cur_tg = False ++ # Get the given block current storageObj configuration ++ for sidx, sobj in enumerate(current.get('storage_objects', [])): ++ if '/backstores/' + sobj['plugin'] + '/' + sobj['name'] == so_path: ++ current_so = current['storage_objects'][sidx] ++ fetch_cur_so = True ++ break ++ ++ # Get the given block current target configuration ++ if fetch_cur_so: ++ for tidx, tobj in enumerate(current.get('targets', [])): ++ if fetch_cur_tg: ++ break ++ for luns in tobj.get('tpgs', []): ++ if fetch_cur_tg: ++ break ++ for lun in luns.get('luns', []): ++ if lun['storage_object'] == so_path: ++ current_tg = current['targets'][tidx] ++ fetch_cur_tg = True ++ break ++ ++ fetch_sav_so = False ++ fetch_sav_tg = False ++ # Get the given block storageObj from saved configuration ++ for sidx, sobj in enumerate(saveconf.get('storage_objects', [])): ++ if '/backstores/' + sobj['plugin'] + '/' + sobj['name'] == so_path: ++ # Merge StorageObj ++ if fetch_cur_so: ++ saveconf['storage_objects'][sidx] = current_so; ++ # Remove StorageObj ++ else: ++ saveconf['storage_objects'].remove(saveconf['storage_objects'][sidx]) ++ fetch_sav_so = True ++ break ++ ++ # Get the given block target from saved configuration ++ if fetch_sav_so: ++ for tidx, tobj in enumerate(saveconf.get('targets', [])): ++ if fetch_sav_tg: ++ break ++ for luns in tobj.get('tpgs', []): ++ if fetch_sav_tg: ++ break ++ for lun in luns.get('luns', []): ++ if lun['storage_object'] == so_path: ++ # Merge target ++ if fetch_cur_tg: ++ saveconf['targets'][tidx] = current_tg; ++ # Remove target ++ else: ++ saveconf['targets'].remove(saveconf['targets'][tidx]) ++ fetch_sav_tg = True ++ break ++ ++ # Insert storageObj ++ if fetch_cur_so and not fetch_sav_so: ++ saveconf['storage_objects'].append(current_so) ++ # Insert target ++ if fetch_cur_tg and not fetch_sav_tg: ++ saveconf['targets'].append(current_tg) ++ ++ return saveconf ++ + # RTSRoot public stuff + + def dump(self): +@@ -257,7 +334,7 @@ class RTSRoot(CFSNode): + + return errors + +- def save_to_file(self, save_file=None): ++ def save_to_file(self, save_file=None, so_path=None): + ''' + Write the configuration in json format to a file. + Save file defaults to '/etc/targets/saveconfig.json'. +@@ -265,9 +342,14 @@ class RTSRoot(CFSNode): + if not save_file: + save_file = default_save_file + ++ if so_path: ++ saveconf = self._get_saveconf(so_path, save_file) ++ else: ++ saveconf = self.dump() ++ + with open(save_file+".temp", "w+") as f: + os.fchmod(f.fileno(), stat.S_IRUSR | stat.S_IWUSR) +- f.write(json.dumps(self.dump(), sort_keys=True, indent=2)) ++ f.write(json.dumps(saveconf, sort_keys=True, indent=2)) + f.write("\n") + f.flush() + os.fsync(f.fileno()) +-- +1.8.3.1 + diff --git a/SOURCES/0009-restoreconfig-fix-alua-tpg-config-setup.patch b/SOURCES/0009-restoreconfig-fix-alua-tpg-config-setup.patch new file mode 100644 index 0000000..a07d1fc --- /dev/null +++ b/SOURCES/0009-restoreconfig-fix-alua-tpg-config-setup.patch @@ -0,0 +1,73 @@ +From 515e1b10bbdbeeca4a4f24aa2157beb1bcea3304 Mon Sep 17 00:00:00 2001 +From: Prasanna Kumar Kalever +Date: Wed, 4 Apr 2018 16:30:42 +0530 +Subject: [PATCH] restoreconfig: fix alua tpg config setup + +Problem: +--- +$ cat myconfig.json +{ + "storage_objects": [ + { + "alua_tpgs": [ + { + "alua_access_type": 0, + "name": "glfs_tg_pt_gp", + "tg_pt_gp_id": 1 + } + ], + "config": "glfs/test@192.168.124.227/block-store/2e189467-00ae-4388-bbd2-a8b4df154671", + "name": "blockX", + "plugin": "user", + "size": 1073741824 + } + ], + "targets": [] +} + +$ targetcli restoreconfig myconfig.json +All configuration cleared +'alua_access_state' + +And attributes won't be effected as per myconfig.json: +$ targetcli/backstores/user:glfs/blockX/alua/glfs_tg_pt_gp get alua alua_access_type +alua_access_type=3 + +Fix: +--- +This patch fix the problem by calling setattr for available attribs in the +configfile and rest all will be as per kernel defaults. + +Signed-off-by: Prasanna Kumar Kalever +--- + rtslib/alua.py | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/rtslib/alua.py b/rtslib/alua.py +index 8a4b30d..9a7af0d 100644 +--- a/rtslib/alua.py ++++ b/rtslib/alua.py +@@ -19,6 +19,7 @@ a copy of the License at + + from .node import CFSNode + from .utils import RTSLibError, RTSLibALUANotSupported, fread, fwrite ++import six + + alua_rw_params = ['alua_access_state', 'alua_access_status', + 'alua_write_metadata', 'alua_access_type', 'preferred', +@@ -393,5 +394,10 @@ class ALUATargetPortGroup(CFSNode): + 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]) ++ for param, value in six.iteritems(alua_tpg): ++ if param != 'name' and param != 'tg_pt_gp_id': ++ try: ++ setattr(alua_tpg_obj, param, value) ++ except: ++ raise RTSLibError("Could not set attribute '%s' for alua tpg '%s'" ++ % (param, alua_tpg['name'])) +-- +1.8.3.1 + diff --git a/SOURCES/0010-Support-tcmu-hw-max-sectors.patch b/SOURCES/0010-Support-tcmu-hw-max-sectors.patch new file mode 100644 index 0000000..8070b8e --- /dev/null +++ b/SOURCES/0010-Support-tcmu-hw-max-sectors.patch @@ -0,0 +1,77 @@ +diff --git a/rtslib/tcm.py b/rtslib/tcm.py +index bf681fe..cb52386 100644 +--- a/rtslib/tcm.py ++++ b/rtslib/tcm.py +@@ -785,7 +785,8 @@ class UserBackedStorageObject(StorageObject): + An interface to configFS storage objects for userspace-backed backstore. + ''' + +- def __init__(self, name, config=None, size=None, wwn=None): ++ def __init__(self, name, config=None, size=None, wwn=None, ++ hw_max_sectors=None): + ''' + @param name: The name of the UserBackedStorageObject. + @type name: string +@@ -796,6 +797,8 @@ class UserBackedStorageObject(StorageObject): + @type size: int + @param wwn: T10 WWN Unit Serial, will generate if None + @type wwn: string ++ @hw_max_sectors: Max sectors per command limit to export to initiators. ++ @type hw_max_sectors: int + @return: A UserBackedStorageObject object. + ''' + +@@ -808,20 +811,22 @@ class UserBackedStorageObject(StorageObject): + "from its configuration string") + super(UserBackedStorageObject, self).__init__(name, 'create') + try: +- self._configure(config, size, wwn) ++ self._configure(config, size, wwn, hw_max_sectors) + except: + self.delete() + raise + else: + super(UserBackedStorageObject, self).__init__(name, 'lookup') + +- def _configure(self, config, size, wwn): ++ def _configure(self, config, size, wwn, hw_max_sectors): + self._check_self() + + if ':' in config: + raise RTSLibError("':' not allowed in config string") + self._control("dev_config=%s" % config) + self._control("dev_size=%d" % size) ++ if hw_max_sectors is not None: ++ self._control("hw_max_sectors=%s" % hw_max_sectors) + self._enable() + + super(UserBackedStorageObject, self)._configure(wwn) +@@ -830,6 +835,10 @@ class UserBackedStorageObject(StorageObject): + self._check_self() + return int(self._parse_info('Size')) + ++ def _get_hw_max_sectors(self): ++ self._check_self() ++ return int(self._parse_info('HwMaxSectors')) ++ + def _get_config(self): + self._check_self() + val = self._parse_info('Config') +@@ -841,6 +850,8 @@ class UserBackedStorageObject(StorageObject): + self._check_self() + return storage_object_get_alua_support_attr(self) + ++ hw_max_sectors = property(_get_hw_max_sectors, ++ doc="Get the max sectors per command.") + size = property(_get_size, + doc="Get the size in bytes.") + config = property(_get_config, +@@ -853,6 +864,8 @@ class UserBackedStorageObject(StorageObject): + d['wwn'] = self.wwn + d['size'] = self.size + d['config'] = self.config ++ d['hw_max_sectors'] = self.hw_max_sectors ++ + return d + + diff --git a/SOURCES/0011-saveconfig-dump-control-string-containing-control-va.patch b/SOURCES/0011-saveconfig-dump-control-string-containing-control-va.patch new file mode 100644 index 0000000..f552042 --- /dev/null +++ b/SOURCES/0011-saveconfig-dump-control-string-containing-control-va.patch @@ -0,0 +1,93 @@ +From eff378068812503ee2394baffba37b5cadd9a0f7 Mon Sep 17 00:00:00 2001 +From: Prasanna Kumar Kalever +Date: Fri, 6 Apr 2018 13:03:28 +0530 +Subject: [PATCH] saveconfig: dump control string containing control=value + tuples + +Problem: +------- +$ targetcli /backstores/user:glfs create blockX1 1073741824 \ + test@192.168.124.227/block-store/e59309bb-d591-4121-a891-e98ff3416446,max_data_area_mb=32 + +$ targetcli / saveconfig + +$ cat /etc/target/saveconfig.json +{ + "storage_objects": [ + { + "alua_tpgs": [], + "attributes": { + ... + }, + "config": "glfs/test@192.168.124.227/block-store/e59309bb-d591-4121-a891-e98ff3416446", + "hw_max_sectors": 128, + "name": "blockX1", + "plugin": "user", + "size": 1073741824, + "wwn": "3aa072d6-a007-45a3-8eac-e85b53655515" + } + ], + "targets": [] +} + +Note max_data_area_mb is not dumped into the configfile and hence on restart of +target service or node reboot this storageObject property is lost. + +Fix: +---- +This patch make sure to dump control string containing control=value tuples, like: +$ cat /etc/target/saveconfig.json +{ + ... + "config": "glfs/test@192.168.124.227/block-store/e59309bb-d591-4121-a891-e98ff3416446", + "control": "max_data_area_mb=32", + ... +} + +Signed-off-by: Prasanna Kumar Kalever +--- + rtslib/tcm.py | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/rtslib/tcm.py b/rtslib/tcm.py +index efe685a..4feb738 100644 +--- a/rtslib/tcm.py ++++ b/rtslib/tcm.py +@@ -845,6 +845,17 @@ class UserBackedStorageObject(StorageObject): + self._check_self() + return int(self._parse_info('HwMaxSectors')) + ++ def _get_control_tuples(self): ++ self._check_self() ++ tuples = [] ++ # 1. max_data_area_mb ++ val = self._parse_info('MaxDataAreaMB') ++ if val != "NULL": ++ tuples.append("max_data_area_mb=%s" % val) ++ # 2. add next ... ++ ++ return ",".join(tuples) ++ + def _get_config(self): + self._check_self() + val = self._parse_info('Config') +@@ -858,6 +869,8 @@ class UserBackedStorageObject(StorageObject): + + hw_max_sectors = property(_get_hw_max_sectors, + doc="Get the max sectors per command.") ++ control_tuples = property(_get_control_tuples, ++ doc="Get the comma separated string containing control=value tuples.") + size = property(_get_size, + doc="Get the size in bytes.") + config = property(_get_config, +@@ -871,6 +884,7 @@ class UserBackedStorageObject(StorageObject): + d['size'] = self.size + d['config'] = self.config + d['hw_max_sectors'] = self.hw_max_sectors ++ d['control'] = self.control_tuples + + return d + +-- +1.8.3.1 + diff --git a/SOURCES/0012-tcmu-add-control-constructor-arg.patch b/SOURCES/0012-tcmu-add-control-constructor-arg.patch new file mode 100644 index 0000000..9b29897 --- /dev/null +++ b/SOURCES/0012-tcmu-add-control-constructor-arg.patch @@ -0,0 +1,65 @@ +From 9637223b9d8cee3abc527f58fc9e14a1bcbe4b29 Mon Sep 17 00:00:00 2001 +From: Mike Christie +Date: Wed, 7 Mar 2018 19:47:34 -0600 +Subject: [PATCH] tcmu: add control constructor arg + +Add format control constructor arg so user does not have to hack +in extra settings through the config option. + +Signed-off-by: Mike Christie +--- + rtslib/tcm.py | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/rtslib/tcm.py b/rtslib/tcm.py +index 1aeea23..efe685a 100644 +--- a/rtslib/tcm.py ++++ b/rtslib/tcm.py +@@ -787,7 +787,7 @@ class UserBackedStorageObject(StorageObject): + ''' + + def __init__(self, name, config=None, size=None, wwn=None, +- hw_max_sectors=None): ++ hw_max_sectors=None, control=None): + ''' + @param name: The name of the UserBackedStorageObject. + @type name: string +@@ -800,6 +800,9 @@ class UserBackedStorageObject(StorageObject): + @type wwn: string + @hw_max_sectors: Max sectors per command limit to export to initiators. + @type hw_max_sectors: int ++ @control: String of control=value tuples separate by a ',' that will ++ passed to the kernel control file. ++ @type: string + @return: A UserBackedStorageObject object. + ''' + +@@ -812,14 +815,14 @@ class UserBackedStorageObject(StorageObject): + "from its configuration string") + super(UserBackedStorageObject, self).__init__(name, 'create') + try: +- self._configure(config, size, wwn, hw_max_sectors) ++ self._configure(config, size, wwn, hw_max_sectors, control) + except: + self.delete() + raise + else: + super(UserBackedStorageObject, self).__init__(name, 'lookup') + +- def _configure(self, config, size, wwn, hw_max_sectors): ++ def _configure(self, config, size, wwn, hw_max_sectors, control): + self._check_self() + + if ':' in config: +@@ -828,6 +831,8 @@ class UserBackedStorageObject(StorageObject): + self._control("dev_size=%d" % size) + if hw_max_sectors is not None: + self._control("hw_max_sectors=%s" % hw_max_sectors) ++ if control is not None: ++ self._control(control) + self._enable() + + super(UserBackedStorageObject, self)._configure(wwn) +-- +1.8.3.1 + diff --git a/SOURCES/0013-saveconfig-fix-failure-in-absence-of-save-file.patch b/SOURCES/0013-saveconfig-fix-failure-in-absence-of-save-file.patch new file mode 100644 index 0000000..1674b47 --- /dev/null +++ b/SOURCES/0013-saveconfig-fix-failure-in-absence-of-save-file.patch @@ -0,0 +1,39 @@ +From 1dccdd8f1415c7fe63fb59044618435a09619e45 Mon Sep 17 00:00:00 2001 +From: Prasanna Kumar Kalever +Date: Tue, 24 Apr 2018 16:33:36 +0530 +Subject: [PATCH] saveconfig: fix failure in absence of save file + +$ ls /etc/target/ +backup + +$ targetcli /backstores/user:glfs/testX saveconfig +[Errno 2] No such file or directory: '/etc/target/saveconfig.json' + +Signed-off-by: Prasanna Kumar Kalever +--- + rtslib/root.py | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/rtslib/root.py b/rtslib/root.py +index 913d8ea..d5a6e43 100644 +--- a/rtslib/root.py ++++ b/rtslib/root.py +@@ -184,9 +184,12 @@ class RTSRoot(CFSNode): + ''' + current = self.dump() + +- with open(save_file, "r") as f: +- saveconf = json.loads(f.read()) +- f.close() ++ if not os.path.exists(save_file): ++ saveconf = {'storage_objects': [], 'targets': []} ++ else: ++ with open(save_file, "r") as f: ++ saveconf = json.loads(f.read()) ++ f.close() + + fetch_cur_so = False + fetch_cur_tg = False +-- +1.8.3.1 + diff --git a/SPECS/python-rtslib.spec b/SPECS/python-rtslib.spec index e025c20..c723deb 100644 --- a/SPECS/python-rtslib.spec +++ b/SPECS/python-rtslib.spec @@ -9,7 +9,7 @@ License: ASL 2.0 Group: System Environment/Libraries Summary: API for Linux kernel LIO SCSI target Version: 2.1.fb63 -Release: 5%{?dist} +Release: 11%{?dist} URL: https://fedorahosted.org/targetcli-fb/ Source: https://fedorahosted.org/released/targetcli-fb/%{oname}-%{version}.tar.gz Source1: target.service @@ -19,6 +19,13 @@ Patch2: 0003-Fix-exception-in-convert_scsi_hctl_to_path.patch Patch3: 0004-Support-Reconfiguration-of-device-path.patch Patch4: 0005-Remove-hba-only-directories-in-clear_existing.patch Patch5: 0006-create-remove-stale-hba-only-dir.patch +Patch6: 0007-alua-enable-alua-for-pscsi-tcmu-if-kernel-reports-su.patch +Patch7: 0008-save_to_file-support-saveconfig-at-storage-object-le.patch +Patch8: 0009-restoreconfig-fix-alua-tpg-config-setup.patch +Patch9: 0010-Support-tcmu-hw-max-sectors.patch +Patch10: 0011-saveconfig-dump-control-string-containing-control-va.patch +Patch11: 0012-tcmu-add-control-constructor-arg.patch +Patch12: 0013-saveconfig-fix-failure-in-absence-of-save-file.patch BuildArch: noarch BuildRequires: python-devel epydoc python-setuptools systemd-units python-six python-pyudev Requires: python-kmod python-six python-pyudev @@ -61,6 +68,13 @@ API for generic Linux SCSI kernel target. %patch3 -p1 %patch4 -p1 %patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 %if 0%{?with_python3} rm -rf %{py3dir} @@ -134,6 +148,25 @@ popd %doc doc/html %changelog +* Tue Apr 24 2018 Maurizio Lombardi - 2.1.fb63-11 +- Fix a failure in absence of save file + +* Thu Apr 19 2018 Maurizio Lombardi - 2.1.fb63-10 +- Add missing patch "tcmu: add control constructor arg" + +* Fri Apr 13 2018 Maurizio Lombardi - 2.1.fb63-9 +- Support tcmu hw max sectors +- saveconfig: dump control string containing control=value tuples + +* Wed Apr 11 2018 Maurizio Lombardi - 2.1.fb63-8 +- Fix ALUA tpg config setup + +* Tue Apr 10 2018 Maurizio Lombardi - 2.1.fb63-7 +- Introduce support to saveconfig at the storage object level + +* Tue Mar 27 2018 Maurizio Lombardi - 2.1.fb63-6 +- enable alua for pscsi/tcmu if kernel reports support + * Mon Feb 26 2018 Maurizio Lombardi - 2.1.fb63-5 - rtslib never creates hba directories without a storage object within it, but if under some circumstance these existed then we should remove them. @@ -141,7 +174,7 @@ popd * Wed Feb 21 2018 Maurizio Lombardi - 2.1.fb63-4 - Allow users to pass in a string into the attributes. -* Wed Nov 02 2017 Maurizio Lombardi - 2.1.fb63-3 +* Thu Nov 02 2017 Maurizio Lombardi - 2.1.fb63-3 - Enabled qla2xxx target support to fix #1327710 * Wed May 17 2017 Andy Grover - 2.1.fb63-2