Hello community, here is the log from the commit of package python-rtslib-fb for openSUSE:Factory checked in at 2014-09-05 09:34:19 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 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-01-23 15:54:44.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.python-rtslib-fb.new/python-rtslib-fb.changes 2014-09-05 09:34:40.000000000 +0200 @@ -1,0 +2,16 @@ +Wed Sep 3 12:01:09 UTC 2014 - [email protected] + +- update to 2.1.49: + * Improve error message when NetworkPortal restore fails + * Python 3.x porting fixes + * targetctl: A missing restore file is not an error + * Add a message if no configfile is found + * Add StorageObjectFactory + * Convert all exceptions in set_parameter/attribute to RTSLibError + * Change set_parameters/attributes to take an err_func + * Fix missing err_func parameter to set_attributes + * '!' allowed character in block and partition names + * Don't add to cache if cfs create fails + * Don't lower-case return values from _parse_info functions + +------------------------------------------------------------------- Old: ---- rtslib-fb-2.1.43.tar.gz New: ---- rtslib-fb-2.1.49.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-rtslib-fb.spec ++++++ --- /var/tmp/diff_new_pack.bkn1H1/_old 2014-09-05 09:34:41.000000000 +0200 +++ /var/tmp/diff_new_pack.bkn1H1/_new 2014-09-05 09:34:41.000000000 +0200 @@ -17,7 +17,7 @@ Name: python-rtslib-fb -Version: 2.1.43 +Version: 2.1.49 Release: 0 Summary: API for Linux kernel SCSI target (aka LIO) License: Apache-2.0 ++++++ rtslib-fb-2.1.43.tar.gz -> rtslib-fb-2.1.49.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rtslib-fb-2.1.43/PKG-INFO new/rtslib-fb-2.1.49/PKG-INFO --- old/rtslib-fb-2.1.43/PKG-INFO 2013-12-04 18:24:20.000000000 +0100 +++ new/rtslib-fb-2.1.49/PKG-INFO 2014-08-28 20:25:36.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: rtslib-fb -Version: 2.1.43 +Version: 2.1.49 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.43/rtslib/__init__.py new/rtslib-fb-2.1.49/rtslib/__init__.py --- old/rtslib-fb-2.1.43/rtslib/__init__.py 2013-11-08 01:21:56.000000000 +0100 +++ new/rtslib-fb-2.1.49/rtslib/__init__.py 2014-08-28 20:14:27.000000000 +0200 @@ -1,6 +1,7 @@ ''' This file is part of RTSLib. Copyright (c) 2011-2013 by Datera, Inc +Copyright (c) 2011-2014 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 @@ -24,6 +25,7 @@ from tcm import FileIOStorageObject, BlockStorageObject from tcm import PSCSIStorageObject, RDMCPStorageObject +from tcm import StorageObjectFactory __version__ = 'GIT_VERSION' __author__ = "Jerome Martin <[email protected]>" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rtslib-fb-2.1.43/rtslib/fabric.py new/rtslib-fb-2.1.49/rtslib/fabric.py --- old/rtslib-fb-2.1.43/rtslib/fabric.py 2013-11-20 20:39:46.000000000 +0100 +++ new/rtslib-fb-2.1.49/rtslib/fabric.py 2014-08-08 00:26:19.000000000 +0200 @@ -1,7 +1,7 @@ ''' This file is part of RTSLib. Copyright (c) 2011-2013 by Datera, Inc -Copyright (c) 2013 by Andy Grover +Copyright (c) 2011-2014 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 @@ -187,7 +187,7 @@ according to the spec, and returns a tuple of our preferred string representation of the wwn, and what type it turned out to be. ''' - return normalize_wwn(self.wwn_types, wwn, self.wwns) + return normalize_wwn(self.wwn_types, wwn) def to_fabric_wwn(self, wwn): ''' @@ -198,7 +198,10 @@ def from_fabric_wwn(self, wwn): ''' - see to_fabric_wwn. + Converts from WWN format used in this fabric's LIO configfs to canonical + format. + Note: Do not call from wwns(). There's no guarantee fabric wwn format is + the same as wherever wwns() is reading from. ''' return wwn @@ -347,10 +350,7 @@ for fname in glob("/sys/bus/firewire/devices/fw*/is_local"): if bool(int(fread(fname))): guid_path = os.path.dirname(fname) + "/guid" - tmp = fread(guid_path) - if tmp[0:2] == '0x': - tmp = tmp[2:] - yield self.from_fabric_wwn(tmp) + yield "eui." + fread(guid_path)[2:] break @@ -366,8 +366,6 @@ return colonize(wwn[4:]) def from_fabric_wwn(self, wwn): - if wwn.startswith("0x"): - wwn = wwn[2:] return "naa." + wwn.replace(":", "") @property @@ -375,7 +373,7 @@ for wwn_file in glob("/sys/class/fc_host/host*/port_name"): with ignored(IOError): if not fread(os.path.dirname(wwn_file)+"/symbolic_name").startswith("fcoe"): - yield self.from_fabric_wwn(fread(wwn_file)) + yield "naa." + fread(wwn_file)[2:] class SRPTFabricModule(_BaseFabricModule): @@ -390,14 +388,12 @@ return "0x" + wwn[3:] def from_fabric_wwn(self, wwn): - if wwn.startswith("0x"): - wwn = wwn[2:] - return "ib." + wwn.replace(":", "") + return "ib." + wwn[2:] @property def wwns(self): for wwn_file in glob("/sys/class/infiniband/*/ports/*/gids/0"): - yield self.from_fabric_wwn(fread(wwn_file)) + yield "ib." + fread(wwn_file).replace(":", "") class FCoEFabricModule(_BaseFabricModule): @@ -414,14 +410,14 @@ return colonize(wwn[4:]) def from_fabric_wwn(self, wwn): - return "naa." + wwn[2:] + return "naa." + wwn.replace(":", "") @property def wwns(self): for wwn_file in glob("/sys/class/fc_host/host*/port_name"): with ignored(IOError): if fread(os.path.dirname(wwn_file)+"/symbolic_name").startswith("fcoe"): - yield self.from_fabric_wwn(fread(wwn_file)) + yield "naa." + fread(wwn_file)[2:] class USBGadgetFabricModule(_BaseFabricModule): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rtslib-fb-2.1.43/rtslib/node.py new/rtslib-fb-2.1.49/rtslib/node.py --- old/rtslib-fb-2.1.43/rtslib/node.py 2013-11-08 01:21:56.000000000 +0100 +++ new/rtslib-fb-2.1.49/rtslib/node.py 2014-08-08 00:26:19.000000000 +0200 @@ -3,6 +3,7 @@ This file is part of RTSLib. Copyright (c) 2011-2013 by Datera, Inc +Copyright (c) 2011-2014 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 @@ -138,10 +139,8 @@ else: try: fwrite(path, "%s" % str(value)) - except IOError as msg: - msg = msg[1] - raise RTSLibError("Cannot set attribute %s: %s" - % (str(attribute), str(msg))) + except Exception as e: + raise RTSLibError("Cannot set attribute %s: %s" % (attribute, e)) def get_attribute(self, attribute): ''' @@ -173,10 +172,8 @@ else: try: fwrite(path, "%s\n" % str(value)) - except IOError as msg: - msg = msg[1] - raise RTSLibError("Cannot set parameter %s: %s" - % (str(parameter), str(msg))) + except Exception as e: + raise RTSLibError("Cannot set parameter %s: %s" % (parameter, e)) def get_parameter(self, parameter): ''' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rtslib-fb-2.1.43/rtslib/root.py new/rtslib-fb-2.1.49/rtslib/root.py --- old/rtslib-fb-2.1.43/rtslib/root.py 2013-11-20 20:39:46.000000000 +0100 +++ new/rtslib-fb-2.1.49/rtslib/root.py 2014-08-08 00:26:19.000000000 +0200 @@ -3,6 +3,7 @@ This file is part of RTSLib. Copyright (c) 2011-2013 by Datera, Inc +Copyright (c) 2011-2014 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 @@ -25,18 +26,10 @@ from node import CFSNode from target import Target from fabric import FabricModule -from tcm import (StorageObject, FileIOStorageObject, BlockStorageObject, - PSCSIStorageObject, RDMCPStorageObject) +from tcm import so_mapping, StorageObject from utils import RTSLibError, RTSLibBrokenLink, modprobe, mount_configfs from utils import dict_remove, set_attributes -storageobjects = dict( - fileio=FileIOStorageObject, - block=BlockStorageObject, - pscsi=PSCSIStorageObject, - ramdisk=RDMCPStorageObject, - ) - default_save_file = "/etc/target/saveconfig.json" class RTSRoot(CFSNode): @@ -98,6 +91,12 @@ for node_acl in t.node_acls: yield node_acl + def _list_mapped_luns(self): + self._check_self() + for na in self.node_acls: + for mlun in na.mapped_luns: + yield mlun + def _list_network_portals(self): self._check_self() for t in self.tpgs: @@ -180,7 +179,7 @@ err_func("'name' not defined in storage object %d" % index) continue try: - so_cls = storageobjects[so['plugin']] + so_cls = so_mapping[so['plugin']] except KeyError: err_func("'plugin' not defined or invalid in storageobject %s" % so['name']) continue @@ -191,10 +190,12 @@ except (TypeError, ValueError): err_func("Could not create StorageObject %s" % so['name']) continue - try: - set_attributes(so_obj, so.get('attributes', {})) - except RTSLibError: - err_func("Could not set an attribute for %s" % so['name']) + + # Custom err func to include block name + def so_err_func(x): + return err_func("Storage Object %s/%s: %s" % (so['plugin'], so['name'], x)) + + set_attributes(so_obj, so.get('attributes', {}), so_err_func) # Don't need to create fabric modules for index, fm in enumerate(config.get('fabric_modules', [])): @@ -259,6 +260,8 @@ doc="Get the list of all the existing TPG objects.") node_acls = property(_list_node_acls, doc="Get the list of all the existing NodeACL objects.") + mapped_luns = property(_list_mapped_luns, + doc="Get the list of all the existing MappedLUN objects.") sessions = property(_list_sessions, doc="Get the list of all the existing sessions.") network_portals = property(_list_network_portals, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rtslib-fb-2.1.43/rtslib/target.py new/rtslib-fb-2.1.49/rtslib/target.py --- old/rtslib-fb-2.1.43/rtslib/target.py 2013-12-04 02:17:37.000000000 +0100 +++ new/rtslib-fb-2.1.49/rtslib/target.py 2014-08-05 05:19:18.000000000 +0200 @@ -3,7 +3,7 @@ This file is part of RTSLib. Copyright (c) 2011-2013 by Datera, Inc. -Copyright (c) 2011-2013 by Red Hat, Inc. +Copyright (c) 2011-2014 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 @@ -122,8 +122,8 @@ try: t_obj = Target(fm_obj, t['wwn']) - except RTSLibError: - err_func("Could not create Target object") + except RTSLibError as e: + err_func("Could not create Target object: %s" % e) return for tpg in t.get('tpgs', []): @@ -267,17 +267,13 @@ if self._get_nexus(): raise RTSLibError("The TPG's nexus initiator WWN is already set.") - # Nexus wwn type should match parent target - wwn_type = self.parent_target.wwn_type + fm = self.parent_target.fabric_module + if nexus_wwn: - # Not using fabric-specific version of normalize_wwn, since we - # want to make sure wwn conforms to regexp, but don't check - # against target wwn_list, since we're setting the "initiator" here. - nexus_wwn = normalize_wwn((wwn_type,), nexus_wwn)[0] + nexus_wwn = fm.to_normalized_wwn(nexus_wwn)[0] else: - nexus_wwn = generate_wwn(wwn_type) - - fm = self.parent_target.fabric_module + # Nexus wwn type should match parent target + nexus_wwn = generate_wwn(self.parent_target.wwn_type) fwrite("%s/nexus" % self.path, fm.to_fabric_wwn(nexus_wwn)) @@ -404,8 +400,8 @@ @classmethod def setup(cls, t_obj, tpg, err_func): tpg_obj = cls(t_obj, tag=tpg.get("tag", None)) - set_attributes(tpg_obj, tpg.get('attributes', {})) - set_parameters(tpg_obj, tpg.get('parameters', {})) + set_attributes(tpg_obj, tpg.get('attributes', {}), err_func) + set_parameters(tpg_obj, tpg.get('parameters', {}), err_func) for lun in tpg.get('luns', []): LUN.setup(tpg_obj, lun, err_func) @@ -453,7 +449,7 @@ # LUN private stuff def __repr__(self): - return "<LUN %d (%s/%s)" % (self.lun, self.storage_object.plugin, + return "<LUN %d (%s/%s)>" % (self.lun, self.storage_object.plugin, self.storage_object.name) def __init__(self, parent_tpg, lun=None, storage_object=None, alias=None): @@ -658,7 +654,7 @@ # NetworkPortal private stuff def __repr__(self): - return "<NetworkPortal %s port %s" % (self.ip_address, self.port) + return "<NetworkPortal %s port %s>" % (self.ip_address, self.port) def __init__(self, parent_tpg, ip_address, port=3260, mode='any'): ''' @@ -751,9 +747,9 @@ try: np = cls(tpg_obj, p['ip_address'], p['port']) np.iser = p.get('iser', False) - except (RTSLibError, KeyError): - err_func("Creating NetworkPortal object %s:%s failed" % - (p['ip_address'], p['port'])) + except (RTSLibError, KeyError) as e: + err_func("Creating NetworkPortal object %s:%s failed: %s" % + (p['ip_address'], p['port'], e)) def dump(self): d = super(NetworkPortal, self).dump() @@ -945,11 +941,11 @@ return try: acl_obj = cls(tpg_obj, acl['node_wwn']) - except RTSLibError: - err_func("Error when creating NodeACL for %s" % acl['node_wwn']) + except RTSLibError as e: + err_func("Error when creating NodeACL for %s: %s" % (acl['node_wwn'], e)) return - set_attributes(acl_obj, acl.get('attributes', {})) + set_attributes(acl_obj, acl.get('attributes', {}), err_func) for mlun in acl.get('mapped_luns', []): MappedLUN.setup(tpg_obj, acl_obj, mlun, err_func) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rtslib-fb-2.1.43/rtslib/tcm.py new/rtslib-fb-2.1.49/rtslib/tcm.py --- old/rtslib-fb-2.1.43/rtslib/tcm.py 2013-12-04 02:17:37.000000000 +0100 +++ new/rtslib-fb-2.1.49/rtslib/tcm.py 2014-08-28 20:14:27.000000000 +0200 @@ -3,6 +3,7 @@ This file is part of RTSLib. Copyright (c) 2011-2013 by Datera, Inc +Copyright (c) 2011-2014 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 @@ -18,6 +19,7 @@ ''' import os +import stat import re import glob import resource @@ -106,15 +108,9 @@ ''' Build a StorageObject of the correct type from a configfs path. ''' - mapping = dict( - fileio=FileIOStorageObject, - pscsi=PSCSIStorageObject, - iblock=BlockStorageObject, - rd_mcp=RDMCPStorageObject, - ) so_name = os.path.basename(path) so_type = path.split("/")[-2].rsplit("_", 1)[0] - return mapping[so_type](so_name) + return so_mapping[so_type](so_name) def _get_wwn(self): self._check_self() @@ -172,7 +168,7 @@ self._check_self() info = fread("%s/info" % self.path) return re.search(".*%s: ([^: ]+).*" \ - % key, ' '.join(info.split())).group(1).lower() + % key, ' '.join(info.split())).group(1) def _get_status(self): self._check_self() @@ -670,14 +666,14 @@ if dev is not None: super(BlockStorageObject, self).__init__(name, 'create') try: - self._configure(dev, wwn, readonly, write_back) + self._configure(dev, wwn, readonly) except: self.delete() raise else: super(BlockStorageObject, self).__init__(name, 'lookup') - def _configure(self, dev, wwn, readonly, write_back): + 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.") @@ -689,9 +685,6 @@ self._control("readonly=%d" % readonly) self._enable() - if write_back: - self.set_attribute("emulate_write_cache", 1) - super(BlockStorageObject, self)._configure(wwn) def _get_major(self): @@ -740,6 +733,37 @@ return d +class StorageObjectFactory(object): + """ + Create a storage object based on a given path. + Only works for file & block. + """ + + def __new__(cls, path): + path = os.path.realpath(path) + name = path.strip("/").replace("/", "-") + if os.path.exists(path): + s = os.stat(path) + if stat.S_ISBLK(s.st_mode): + return BlockStorageObject(name=name, dev=path) + elif stat.S_ISREG(s.st_mode): + return FileIOStorageObject(name=name, dev=path, size=s.st_size) + + raise RTSLibError("Can't create storageobject from path: %s" % path) + + +# Used to convert either dirprefix or plugin to the SO. Instead of two +# almost-identical dicts we just have some duplicate entries. +so_mapping = { + "pscsi": PSCSIStorageObject, + "rd_mcp": RDMCPStorageObject, + "ramdisk": RDMCPStorageObject, + "fileio": FileIOStorageObject, + "iblock": BlockStorageObject, + "block": BlockStorageObject, +} + + bs_params = { PSCSIStorageObject: dict(name='pscsi'), RDMCPStorageObject: dict(name='ramdisk', alt_dirprefix='rd_mcp'), @@ -796,7 +820,11 @@ self._path = "%s/core/%s_%d" % (self.configfs_dir, dirp, self._index) - self._create_in_cfs_ine(mode) + try: + self._create_in_cfs_ine(mode) + except: + del bs_cache[self._lookup_key] + raise def delete(self): super(_Backstore, self).delete() @@ -809,7 +837,7 @@ self._check_self() info = fread("%s/hba_info" % self.path) return re.search(".*%s: ([^: ]+).*" \ - % key, ' '.join(info.split())).group(1).lower() + % key, ' '.join(info.split())).group(1) def _get_version(self): self._check_self() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rtslib-fb-2.1.43/rtslib/utils.py new/rtslib-fb-2.1.49/rtslib/utils.py --- old/rtslib-fb-2.1.43/rtslib/utils.py 2013-12-04 02:10:15.000000000 +0100 +++ new/rtslib-fb-2.1.49/rtslib/utils.py 2014-08-08 00:26:19.000000000 +0200 @@ -3,6 +3,7 @@ This file is part of RTSLib. Copyright (c) 2011-2013 by Datera, Inc +Copyright (c) 2011-2014 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 @@ -127,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. @@ -297,12 +298,13 @@ Some wwns may have alternate text representations. Adjust to our preferred representation. ''' - wwn = str(wwn.strip()) + wwn = str(wwn.strip()).lower() if wwn_type in ('naa', 'eui', 'ib'): if wwn.startswith("0x"): wwn = wwn[2:] - wwn = wwn.replace(":-", "") + wwn = wwn.replace("-", "") + wwn = wwn.replace(":", "") if not (wwn.startswith("naa.") or wwn.startswith("eui.") or \ wwn.startswith("ib.")): @@ -310,7 +312,7 @@ return wwn -def normalize_wwn(wwn_types, wwn, possible_wwns=None): +def normalize_wwn(wwn_types, wwn): ''' Take a WWN as given by the user and convert it to a standard text representation. If possible_wwns is not None, verify that @@ -339,9 +341,6 @@ else: raise RTSLibError("WWN not valid as: %s" % ", ".join(wwn_types)) - if possible_wwns is not None and clean_wwn not in possible_wwns: - raise RTSLibError("WWN not in possible WWNs") - return (clean_wwn, wwn_type) def list_loaded_kernel_modules(): @@ -435,17 +434,19 @@ if not ignore: raise -def set_attributes(obj, attr_dict): +def set_attributes(obj, attr_dict, err_func): for name, value in attr_dict.iteritems(): - # Setting some attributes may return an error, before kernel 3.3 - with ignored(RTSLibError): + try: obj.set_attribute(name, value) + except RTSLibError as e: + err_func(str(e)) -def set_parameters(obj, param_dict): +def set_parameters(obj, param_dict, err_func): for name, value in param_dict.iteritems(): - # Setting some parameters may return an error, before kernel 3.3 - with ignored(RTSLibError): + try: obj.set_parameter(name, value) + except RTSLibError as e: + err_func(str(e)) def _test(): '''Run the doctests''' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rtslib-fb-2.1.43/rtslib_fb.egg-info/PKG-INFO new/rtslib-fb-2.1.49/rtslib_fb.egg-info/PKG-INFO --- old/rtslib-fb-2.1.43/rtslib_fb.egg-info/PKG-INFO 2013-12-04 18:24:20.000000000 +0100 +++ new/rtslib-fb-2.1.49/rtslib_fb.egg-info/PKG-INFO 2014-08-28 20:25:36.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: rtslib-fb -Version: 2.1.43 +Version: 2.1.49 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.43/scripts/targetctl new/rtslib-fb-2.1.49/scripts/targetctl --- old/rtslib-fb-2.1.43/scripts/targetctl 2013-11-04 17:25:58.000000000 +0100 +++ new/rtslib-fb-2.1.49/scripts/targetctl 2014-08-05 05:19:18.000000000 +0200 @@ -42,15 +42,21 @@ RTSRoot().save_to_file(save_file=to_file) def restore(from_file): + + try: errors = RTSRoot().restore_from_file(restore_file=from_file) + except IOError: + # Not an error if the restore file is not present + print("No saved config file at %s, ok, exiting" % from_file) + sys.exit(0) - if errors: - print("Restore failed, %d errors:" % len(errors), file=err) + if errors: + print("Restore failed, %d errors:" % len(errors), file=err) - for error in errors: - print(error, file=err) + for error in errors: + print(error, file=err) - sys.exit(-1) + sys.exit(-1) def clear(unused): RTSRoot().clear_existing(confirm=True) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rtslib-fb-2.1.43/setup.py new/rtslib-fb-2.1.49/setup.py --- old/rtslib-fb-2.1.43/setup.py 2013-12-04 02:17:37.000000000 +0100 +++ new/rtslib-fb-2.1.49/setup.py 2014-08-28 20:20:25.000000000 +0200 @@ -20,7 +20,7 @@ setup ( name = 'rtslib-fb', - version = '2.1.43', + version = '2.1.49', description = 'API for Linux kernel SCSI target (aka LIO)', license = 'Apache 2.0', maintainer = 'Andy Grover', -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
