Hello community, here is the log from the commit of package python-rtslib-fb for openSUSE:Factory checked in at 2015-05-16 19:02:03 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-rtslib-fb (Old) and /work/SRC/openSUSE:Factory/.python-rtslib-fb.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-rtslib-fb" Changes: -------- --- /work/SRC/openSUSE:Factory/python-rtslib-fb/python-rtslib-fb.changes 2014-09-05 09:34:40.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.python-rtslib-fb.new/python-rtslib-fb.changes 2015-05-16 19:02:05.000000000 +0200 @@ -1,0 +2,6 @@ +Tue May 12 14:58:13 UTC 2015 - benoit.mo...@gmx.fr + +- update to version 2.1.51: + * no changelog available + +------------------------------------------------------------------- Old: ---- rtslib-fb-2.1.49.tar.gz New: ---- rtslib-fb-2.1.51.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-rtslib-fb.spec ++++++ --- /var/tmp/diff_new_pack.Uo6vj2/_old 2015-05-16 19:02:05.000000000 +0200 +++ /var/tmp/diff_new_pack.Uo6vj2/_new 2015-05-16 19:02:05.000000000 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-rtslib-fb # -# Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: python-rtslib-fb -Version: 2.1.49 +Version: 2.1.51 Release: 0 Summary: API for Linux kernel SCSI target (aka LIO) License: Apache-2.0 ++++++ rtslib-fb-2.1.49.tar.gz -> rtslib-fb-2.1.51.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rtslib-fb-2.1.49/PKG-INFO new/rtslib-fb-2.1.51/PKG-INFO --- old/rtslib-fb-2.1.49/PKG-INFO 2014-08-28 20:25:36.000000000 +0200 +++ new/rtslib-fb-2.1.51/PKG-INFO 2014-12-02 18:57:51.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: rtslib-fb -Version: 2.1.49 +Version: 2.1.51 Summary: API for Linux kernel SCSI target (aka LIO) Home-page: http://github.com/agrover/rtslib-fb Author: Andy Grover diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rtslib-fb-2.1.49/rtslib/__init__.py new/rtslib-fb-2.1.51/rtslib/__init__.py --- old/rtslib-fb-2.1.49/rtslib/__init__.py 2014-08-28 20:14:27.000000000 +0200 +++ new/rtslib-fb-2.1.51/rtslib/__init__.py 2014-12-02 18:29:22.000000000 +0100 @@ -24,7 +24,7 @@ from fabric import FabricModule from tcm import FileIOStorageObject, BlockStorageObject -from tcm import PSCSIStorageObject, RDMCPStorageObject +from tcm import PSCSIStorageObject, RDMCPStorageObject, UserBackedStorageObject from tcm import StorageObjectFactory __version__ = 'GIT_VERSION' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rtslib-fb-2.1.49/rtslib/fabric.py new/rtslib-fb-2.1.51/rtslib/fabric.py --- old/rtslib-fb-2.1.49/rtslib/fabric.py 2014-08-08 00:26:19.000000000 +0200 +++ new/rtslib-fb-2.1.51/rtslib/fabric.py 2014-12-02 18:29:22.000000000 +0100 @@ -176,7 +176,7 @@ if os.path.isfile(path): return fread(path) else: - raise RTSLibError("Can't find version for fabric module %s." + raise RTSLibError("Can't find version for fabric module %s" % self.name) else: return None @@ -214,8 +214,8 @@ def _assert_feature(self, feature): if not self.has_feature(feature): - raise RTSLibError("This fabric module does not implement " - + "the %s feature." % feature) + raise RTSLibError("Fabric module %s does not implement " + + "the %s feature" % (self.name, feature)) def clear_discovery_auth_settings(self): self._check_self() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rtslib-fb-2.1.49/rtslib/node.py new/rtslib-fb-2.1.51/rtslib/node.py --- old/rtslib-fb-2.1.49/rtslib/node.py 2014-08-08 00:26:19.000000000 +0200 +++ new/rtslib-fb-2.1.51/rtslib/node.py 2014-11-21 00:56:58.000000000 +0100 @@ -33,6 +33,12 @@ def __init__(self): self._path = self.configfs_dir + def __eq__(self, other): + return self._path == other._path + + def __ne__(self, other): + return self._path != other._path + def _get_path(self): return self._path @@ -47,17 +53,17 @@ if mode not in ['any', 'lookup', 'create']: raise RTSLibError("Invalid mode: %s" % mode) if self.exists and mode == 'create': - raise RTSLibError("This %s already exists in configFS." + raise RTSLibError("This %s already exists in configFS" % self.__class__.__name__) elif not self.exists and mode == 'lookup': - raise RTSLibNotInCFS("No such %s in configfs: %s." + raise RTSLibNotInCFS("No such %s in configfs: %s" % (self.__class__.__name__, self.path)) if not self.exists: try: os.mkdir(self.path) except: - raise RTSLibError("Could not create %s in configFS." + raise RTSLibError("Could not create %s in configFS" % self.__class__.__name__) def _exists(self): @@ -65,7 +71,7 @@ def _check_self(self): if not self.exists: - raise RTSLibNotInCFS("This %s does not exist in configFS." + raise RTSLibNotInCFS("This %s does not exist in configFS" % self.__class__.__name__) def _list_files(self, path, writable=None): @@ -134,7 +140,7 @@ self._check_self() path = "%s/attrib/%s" % (self.path, str(attribute)) if not os.path.isfile(path): - raise RTSLibError("Cannot find attribute: %s." + raise RTSLibError("Cannot find attribute: %s" % str(attribute)) else: try: @@ -150,8 +156,7 @@ self._check_self() path = "%s/attrib/%s" % (self.path, str(attribute)) if not os.path.isfile(path): - raise RTSLibError("Cannot find attribute: %s." - % str(attribute)) + raise RTSLibError("Cannot find attribute: %s" % attribute) else: return fread(path) @@ -167,8 +172,7 @@ self._check_self() path = "%s/param/%s" % (self.path, str(parameter)) if not os.path.isfile(path): - raise RTSLibError("Cannot find parameter: %s." - % str(parameter)) + raise RTSLibError("Cannot find parameter: %s" % parameter) else: try: fwrite(path, "%s\n" % str(value)) @@ -184,8 +188,7 @@ self._check_self() path = "%s/param/%s" % (self.path, str(parameter)) if not os.path.isfile(path): - raise RTSLibError("Cannot find RFC-3720 parameter: %s." - % str(parameter)) + raise RTSLibError("Cannot find RFC-3720 parameter: %s" % parameter) else: return fread(path) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rtslib-fb-2.1.49/rtslib/root.py new/rtslib-fb-2.1.51/rtslib/root.py --- old/rtslib-fb-2.1.49/rtslib/root.py 2014-08-08 00:26:19.000000000 +0200 +++ new/rtslib-fb-2.1.51/rtslib/root.py 2014-11-13 20:40:15.000000000 +0100 @@ -158,12 +158,13 @@ ''' Takes a dict generated by dump() and reconfigures the target to match. Returns list of non-fatal errors that were encountered. + Will refuse to restore over an existing configuration unless clear_existing + is True. ''' if clear_existing: self.clear_existing(confirm=True) - elif list(self.storage_objects) or list(self.targets): - raise RTSLibError("storageobjects or targets present, not restoring." + - " Set clear_existing=True?") + elif any(self.storage_objects) or any(self.targets): + raise RTSLibError("storageobjects or targets present, not restoring") errors = [] @@ -187,8 +188,8 @@ dict_remove(kwargs, ('exists', 'attributes', 'plugin', 'buffered_mode')) try: so_obj = so_cls(**kwargs) - except (TypeError, ValueError): - err_func("Could not create StorageObject %s" % so['name']) + except Exception as e: + err_func("Could not create StorageObject %s: %s" % (so['name'], e)) continue # Custom err func to include block name diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rtslib-fb-2.1.49/rtslib/target.py new/rtslib-fb-2.1.51/rtslib/target.py --- old/rtslib-fb-2.1.49/rtslib/target.py 2014-08-05 05:19:18.000000000 +0200 +++ new/rtslib-fb-2.1.51/rtslib/target.py 2014-12-02 18:29:22.000000000 +0100 @@ -32,6 +32,8 @@ import tcm from functools import partial +auth_params = ('userid', 'password', 'mutual_userid', 'mutual_password') + class Target(CFSNode): ''' This is an interface to Targets in configFS. @@ -175,17 +177,17 @@ tag = index break if tag is None: - raise RTSLibError("Cannot find an available TPG Tag.") + raise RTSLibError("Cannot find an available TPG Tag") else: tag = int(tag) if not tag > 0: - raise RTSLibError("The TPG Tag must be >0.") + raise RTSLibError("The TPG Tag must be >0") self._tag = tag if isinstance(parent_target, Target): self._parent_target = parent_target else: - raise RTSLibError("Invalid parent Target.") + raise RTSLibError("Invalid parent Target") self._path = "%s/tpgt_%d" % (self.parent_target.path, self.tag) @@ -195,7 +197,7 @@ if filename.startswith("tpgt_") \ and os.path.isdir("%s/%s" % (target_path, filename)) \ and filename != "tpgt_%d" % self.tag: - raise RTSLibError("Target cannot have multiple TPGs.") + raise RTSLibError("Target cannot have multiple TPGs") self._create_in_cfs_ine(mode) if self.has_feature('nexus') and not self._get_nexus(): @@ -263,9 +265,9 @@ self._check_self() if not self.has_feature('nexus'): - raise RTSLibError("The TPG does not use a nexus.") + raise RTSLibError("The TPG does not use a nexus") if self._get_nexus(): - raise RTSLibError("The TPG's nexus initiator WWN is already set.") + raise RTSLibError("The TPG's nexus initiator WWN is already set") fm = self.parent_target.fabric_module @@ -431,7 +433,7 @@ d['portals'] = [portal.dump() for portal in self.network_portals] d['node_acls'] = [acl.dump() for acl in self.node_acls] if self.has_feature("auth"): - for attr in ("userid", "password", "mutual_userid", "mutual_password"): + for attr in auth_params: val = getattr(self, "chap_" + attr, None) if val: d["chap_" + attr] = val @@ -480,7 +482,7 @@ if isinstance(parent_tpg, TPG): self._parent_tpg = parent_tpg else: - raise RTSLibError("Invalid parent TPG.") + raise RTSLibError("Invalid parent TPG") if lun is None: luns = [l.lun for l in self.parent_tpg.luns] @@ -501,7 +503,7 @@ if storage_object is None and alias is not None: raise RTSLibError("The alias parameter has no meaning " \ - + "without the storage_object parameter.") + + "without the storage_object parameter") if storage_object is not None: self._create_in_cfs_ine('create') @@ -527,7 +529,7 @@ if storage_object.exists: source = storage_object.path else: - raise RTSLibError("storage_object does not exist in configFS.") + raise RTSLibError("storage_object does not exist in configFS") os.symlink(source, destination) @@ -680,12 +682,12 @@ try: self._port = int(port) except ValueError: - raise RTSLibError("Invalid port.") + raise RTSLibError("Invalid port") if isinstance(parent_tpg, TPG): self._parent_tpg = parent_tpg else: - raise RTSLibError("Invalid parent TPG.") + raise RTSLibError("Invalid parent TPG") self._path = "%s/np/%s:%d" \ % (self.parent_tpg.path, self.ip_address, self.port) @@ -693,7 +695,7 @@ try: self._create_in_cfs_ine(mode) except OSError as msg: - raise RTSLibError(msg[1]) + raise RTSLibError(msg) def _get_ip_address(self): return self._ip_address @@ -791,7 +793,7 @@ if isinstance(parent_tpg, TPG): self._parent_tpg = parent_tpg else: - raise RTSLibError("Invalid parent TPG.") + raise RTSLibError("Invalid parent TPG") fm = self.parent_tpg.parent_target.fabric_module self._node_wwn, self.wwn_type = normalize_wwn(fm.wwn_types, node_wwn) @@ -966,7 +968,7 @@ if self.tag: d['tag'] = self.tag if self.has_feature("auth"): - for attr in ("userid", "password", "mutual_userid", "mutual_password"): + for attr in auth_params: val = getattr(self, "chap_" + attr, None) if val: d["chap_" + attr] = val @@ -1015,23 +1017,23 @@ if not isinstance(parent_nodeacl, NodeACL): raise RTSLibError("The parent_nodeacl parameter must be " \ - + "a NodeACL object.") + + "a NodeACL object") else: self._parent_nodeacl = parent_nodeacl if not parent_nodeacl.exists: - raise RTSLibError("The parent_nodeacl does not exist.") + raise RTSLibError("The parent_nodeacl does not exist") try: self._mapped_lun = int(mapped_lun) except ValueError: raise RTSLibError("The mapped_lun parameter must be an " \ - + "integer value.") + + "integer value") self._path = "%s/lun_%d" % (self.parent_nodeacl.path, self.mapped_lun) if tpg_lun is None and write_protect is not None: raise RTSLibError("The write_protect parameter has no " \ - + "meaning without the tpg_lun parameter.") + + "meaning without the tpg_lun parameter") if tpg_lun is not None: self._create_in_cfs_ine('create') @@ -1052,14 +1054,14 @@ tpg_lun = int(tpg_lun) except ValueError: raise RTSLibError("The tpg_lun must be either an " - + "integer or a LUN object.") + + "integer or a LUN object") # Check that the tpg_lun exists in the TPG for lun in self.parent_nodeacl.parent_tpg.luns: if lun.lun == tpg_lun: tpg_lun = lun break if not (isinstance(tpg_lun, LUN) and tpg_lun): - raise RTSLibError("LUN %s does not exist in this TPG." + raise RTSLibError("LUN %s does not exist in this TPG" % str(tpg_lun)) os.symlink(tpg_lun.path, "%s/%s" % (self.path, str(uuid.uuid4())[-10:])) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rtslib-fb-2.1.49/rtslib/tcm.py new/rtslib-fb-2.1.51/rtslib/tcm.py --- old/rtslib-fb-2.1.49/rtslib/tcm.py 2014-08-28 20:14:27.000000000 +0200 +++ new/rtslib-fb-2.1.51/rtslib/tcm.py 2014-12-02 18:29:22.000000000 +0100 @@ -44,7 +44,7 @@ super(StorageObject, self).__init__() if "/" in name or " " in name or "\t" in name or "\n" in name: raise RTSLibError("A storage object's name cannot contain " - " /, newline or spaces/tabs.") + " /, newline or spaces/tabs") else: self._name = name self._backstore = _Backstore(name, type(self), mode) @@ -119,7 +119,7 @@ return fread(path).partition(":")[2].strip() else: raise RTSLibError("Cannot read a T10 WWN Unit Serial from " - + "an unconfigured StorageObject.") + + "an unconfigured StorageObject") def _set_wwn(self, wwn): self._check_self() @@ -128,7 +128,7 @@ fwrite(path, "%s\n" % wwn) else: raise RTSLibError("Cannot write a T10 WWN Unit Serial to " - + "an unconfigured StorageObject.") + + "an unconfigured StorageObject") def _set_udev_path(self, udev_path): self._check_self() @@ -172,7 +172,7 @@ def _get_status(self): self._check_self() - return self._parse_info('Status') + return self._parse_info('Status').lower() def _gen_attached_luns(self): ''' @@ -326,14 +326,14 @@ raise RTSLibError("Cannot find SCSI device by " + "path, and dev " + "parameter not in H:C:T:L " - + "format: %s." % dev) + + "format: %s" % dev) else: udev_path = convert_scsi_hctl_to_path(hostid, channelid, targetid, lunid) if not udev_path: - raise RTSLibError("SCSI device does not exist.") + raise RTSLibError("SCSI device does not exist") else: udev_path = dev.strip() @@ -342,7 +342,7 @@ + "device %s (SCSI %d:%d:%d:%d) " % (udev_path, hostid, channelid, targetid, lunid) - + "is already in use.") + + "is already in use") self._control("scsi_host_id=%d," % hostid \ + "scsi_channel_id=%d," % channelid \ @@ -567,10 +567,10 @@ block_type = get_blockdev_type(dev) if block_type is None: # a file if os.path.exists(os.path.realpath(dev)) and not os.path.isfile(dev): - raise RTSLibError("Path not to a file or block device.") + raise RTSLibError("Path not to a file or block device") if size is None: - raise RTSLibError("Path is to a file, size needed.") + raise RTSLibError("Path is to a file, size needed") self._control("fd_dev_name=%s,fd_dev_size=%d" % (dev, size)) @@ -579,10 +579,10 @@ # dump() saves it and thus restore() will call us with it. if block_type != 0: - raise RTSLibError("Device is not a TYPE_DISK block device.") + raise RTSLibError("Device is not a TYPE_DISK block device") if is_dev_in_use(dev): - raise RTSLibError("Device %s is already in use." % dev) + raise RTSLibError("Device %s is already in use" % dev) self._control("fd_dev_name=%s" % dev) @@ -676,10 +676,10 @@ def _configure(self, dev, wwn, readonly): self._check_self() if get_blockdev_type(dev) != 0: - raise RTSLibError("Device is not a TYPE_DISK block device.") + raise RTSLibError("Device %s is not a TYPE_DISK block device" % dev) if is_dev_in_use(dev): raise RTSLibError("Cannot configure StorageObject because " - + "device %s is already in use." % dev) + + "device %s is already in use" % dev) self._set_udev_path(dev) self._control("udev_path=%s" % dev) self._control("readonly=%d" % readonly) @@ -733,6 +733,92 @@ return d +class UserBackedStorageObject(StorageObject): + ''' + An interface to configFS storage objects for userspace-backed backstore. + ''' + + def __init__(self, name, config=None, level=None, size=None, wwn=None): + ''' + @param name: The name of the UserBackedStorageObject. + @type name: string + @param dev: The path to the backend block device to be used. + - Example: I{dev="/dev/sda"}. + - The only device type that is accepted I{TYPE_DISK}. + For other device types, use pscsi. + @type dev: string + @param size: The size of the device to create, in bytes. + @type size: int + @param config: user-handler-specific config string. + - e.g. "rbd/machine1@snap4" + @type config: string + @param level: TCMU emulation level, 0 or 1. Level 0 will pass all SCSI + commands, 1 will just pass I/O commands, READ, WRITE, etc. + @type level: int + @return: A UserBackedStorageObject object. + ''' + + if size is not None: + if level is None or config is None: + raise RTSLibError("'size', 'level', and 'config' must be set when " + "creating a new UserBackedStorageObject") + if '/' not in config: + raise RTSLibError("'config' must contain a '/' separating subtype " + "from its configuration string") + super(UserBackedStorageObject, self).__init__(name, 'create') + try: + self._configure(config, level, size, wwn) + except: + self.delete() + raise + else: + super(UserBackedStorageObject, self).__init__(name, 'lookup') + + def _configure(self, config, level, size, wwn): + self._check_self() + + if ':' in config: + raise RTSLibError("':' not allowed in config string") + if level not in (0, 1): + raise RTSLibError("Current allowable levels are 0 or 1") + self._control("dev_config=%s" % config) + self._control("pass_level=%d" % level) + self._control("dev_size=%d" % size) + self._enable() + + super(UserBackedStorageObject, self)._configure(wwn) + + def _get_size(self): + self._check_self() + return int(self._parse_info('Size')) + + def _get_level(self): + self._check_self() + return int(self._parse_info('PassLevel')) + + def _get_config(self): + self._check_self() + val = self._parse_info('Config') + if val == "NULL": + return None + return val + + size = property(_get_size, + doc="Get the size in bytes.") + level = property(_get_level, + doc="Get the command emulation level.") + config = property(_get_config, + doc="Get the TCMU config.") + + def dump(self): + d = super(UserBackedStorageObject, self).dump() + d['wwn'] = self.wwn + d['size'] = self.size + d['level'] = self.level + d['config'] = self.config + return d + + class StorageObjectFactory(object): """ Create a storage object based on a given path. @@ -761,6 +847,7 @@ "fileio": FileIOStorageObject, "iblock": BlockStorageObject, "block": BlockStorageObject, + "user": UserBackedStorageObject, } @@ -769,6 +856,7 @@ RDMCPStorageObject: dict(name='ramdisk', alt_dirprefix='rd_mcp'), FileIOStorageObject: dict(name='fileio'), BlockStorageObject: dict(name='block', alt_dirprefix='iblock'), + UserBackedStorageObject: dict(name='user'), } bs_cache = {} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rtslib-fb-2.1.49/rtslib/utils.py new/rtslib-fb-2.1.51/rtslib/utils.py --- old/rtslib-fb-2.1.49/rtslib/utils.py 2014-08-08 00:26:19.000000000 +0200 +++ new/rtslib-fb-2.1.51/rtslib/utils.py 2014-12-02 18:40:04.000000000 +0100 @@ -128,7 +128,7 @@ return get_size("/sys/block/%s" % name) except IOError: # Maybe it's a partition? - m = re.search(r'^([a-z0-9_-!]+)(\d+)$', name) + m = re.search(r'^([a-z0-9_\-!]+)(\d+)$', name) if m: # If disk name ends with a digit, Linux sticks a 'p' between it and # the partition number in the blockdev name. @@ -245,7 +245,7 @@ lun = int(lun) except ValueError: raise RTSLibError( - "The host, controller, target and lun parameter must be integers.") + "The host, controller, target and lun parameter must be integers") for devname in os.listdir("/sys/block"): path = "/dev/%s" % devname @@ -281,11 +281,11 @@ # 5 = IEEE registered # 001405 = OpenIB OUI (they let us use it I guess?) # rest = random - return "naa.5001405" + uuid.uuid4().get_hex()[-9:] + return "naa.5001405" + uuid.uuid4().hex[-9:] elif wwn_type == 'eui': - return "eui.001405" + uuid.uuid4().get_hex()[-10:] + return "eui.001405" + uuid.uuid4().hex[-10:] else: - raise ValueError("Unknown WWN type: %s." % wwn_type) + raise ValueError("Unknown WWN type: %s" % wwn_type) def colonize(str): ''' @@ -378,7 +378,7 @@ stderr=subprocess.PIPE) (stdoutdata, stderrdata) = process.communicate() if process.returncode != 0: - raise RTSLibError("Cannot mount configfs.") + raise RTSLibError("Cannot mount configfs") def dict_remove(d, items): for item in items: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rtslib-fb-2.1.49/rtslib_fb.egg-info/PKG-INFO new/rtslib-fb-2.1.51/rtslib_fb.egg-info/PKG-INFO --- old/rtslib-fb-2.1.49/rtslib_fb.egg-info/PKG-INFO 2014-08-28 20:25:36.000000000 +0200 +++ new/rtslib-fb-2.1.51/rtslib_fb.egg-info/PKG-INFO 2014-12-02 18:57:51.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: rtslib-fb -Version: 2.1.49 +Version: 2.1.51 Summary: API for Linux kernel SCSI target (aka LIO) Home-page: http://github.com/agrover/rtslib-fb Author: Andy Grover diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rtslib-fb-2.1.49/setup.py new/rtslib-fb-2.1.51/setup.py --- old/rtslib-fb-2.1.49/setup.py 2014-08-28 20:20:25.000000000 +0200 +++ new/rtslib-fb-2.1.51/setup.py 2014-12-02 18:54:10.000000000 +0100 @@ -20,7 +20,7 @@ setup ( name = 'rtslib-fb', - version = '2.1.49', + version = '2.1.51', description = 'API for Linux kernel SCSI target (aka LIO)', license = 'Apache 2.0', maintainer = 'Andy Grover',