Hello community, here is the log from the commit of package nvmetcli for openSUSE:Factory checked in at 2020-03-31 17:15:54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/nvmetcli (Old) and /work/SRC/openSUSE:Factory/.nvmetcli.new.3160 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "nvmetcli" Tue Mar 31 17:15:54 2020 rev:10 rq:790010 version:0.7 Changes: -------- --- /work/SRC/openSUSE:Factory/nvmetcli/nvmetcli.changes 2018-04-19 15:32:46.574952117 +0200 +++ /work/SRC/openSUSE:Factory/.nvmetcli.new.3160/nvmetcli.changes 2020-03-31 17:16:04.759659379 +0200 @@ -1,0 +2,18 @@ +Fri Mar 27 07:48:31 UTC 2020 - h...@suse.de + +- Update to version v0.7: + * bump version to v0.7 + * nvmetcli: ANA configuration support + * nvmetcli: simplify the enabled logic + * nvmetcli: pep8 fixes + * nvmetcli: support inline_data_size port parameter + * Revert "nvmetcli: expose nvmet port status and state" + * Support python3 dictionary access. + * nvmetcli: expose nvmet port status and state +- Remove patch merged with upstream + * nvmetcli-make-dict-access-python-version-independant.patch +- 'clear' command doesn't handle ANA groups correctly (bsc#1167644) + adding patch + - 0001-nvmetcli-don-t-remove-ANA-Group-1-on-clear.patch + +------------------------------------------------------------------- Old: ---- nvmetcli-make-dict-access-python-version-independant.patch nvmetcli-v0.6.tar.gz New: ---- 0001-nvmetcli-don-t-remove-ANA-Group-1-on-clear.patch nvmetcli-v0.7.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ nvmetcli.spec ++++++ --- /var/tmp/diff_new_pack.sw0Klo/_old 2020-03-31 17:16:05.591659908 +0200 +++ /var/tmp/diff_new_pack.sw0Klo/_new 2020-03-31 17:16:05.595659910 +0200 @@ -1,7 +1,7 @@ # # spec file for package nvmetcli # -# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2020 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: nvmetcli -Version: 0.6 +Version: 0.7 Release: 1%{?dist} Summary: Command line interface for the kernel NVMe nvmet License: Apache-2.0 @@ -25,7 +25,7 @@ Url: http://git.infradead.org/users/hch/nvmetcli.git Source: nvmetcli-v%{version}.tar.gz Patch1: %{name}-update-python-to-python3.patch -Patch2: %{name}-make-dict-access-python-version-independant.patch +Patch2: 0001-nvmetcli-don-t-remove-ANA-Group-1-on-clear.patch BuildRequires: python3-devel BuildRequires: python3-setuptools Requires: python3-configshell-fb ++++++ 0001-nvmetcli-don-t-remove-ANA-Group-1-on-clear.patch ++++++ >From 5e5e45f5e2800ff1f791e67f683891963f1583a4 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke <h...@suse.de> Date: Fri, 27 Mar 2020 07:55:34 +0100 Subject: [PATCH] nvmetcli: don't remove ANA Group 1 on clear The first ANA group is maintained by the kernel so it cannot be deleted. Signed-off-by: Hannes Reinecke <h...@suse.de> --- nvmet/nvme.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nvmet/nvme.py b/nvmet/nvme.py index 0647ddc..fdec4ff 100644 --- a/nvmet/nvme.py +++ b/nvmet/nvme.py @@ -845,6 +845,11 @@ class ANAGroup(CFSNode): a._setup_attrs(n, err_func) + def delete(self): + # ANA Group 1 is automatically created/deleted + if self.grpid != 1: + super(ANAGroup, self).delete() + def dump(self): d = super(ANAGroup, self).dump() d['grpid'] = self.grpid -- 2.16.4 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.sw0Klo/_old 2020-03-31 17:16:05.623659928 +0200 +++ /var/tmp/diff_new_pack.sw0Klo/_new 2020-03-31 17:16:05.623659928 +0200 @@ -4,8 +4,8 @@ <param name="scm">git</param> <param name="url">git://git.infradead.org/users/hch/nvmetcli.git</param> <param name="filename">nvmetcli</param> - <param name="version">v0.6</param> - <param name="revision">v0.6</param> + <param name="version">v0.7</param> + <param name="revision">v0.7</param> <param name="exclude">.git</param> <param name="changesgenerate">enable</param> </service> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.sw0Klo/_old 2020-03-31 17:16:05.635659935 +0200 +++ /var/tmp/diff_new_pack.sw0Klo/_new 2020-03-31 17:16:05.635659935 +0200 @@ -1,4 +1,4 @@ <servicedata> <service name="tar_scm"> <param name="url">git://git.infradead.org/users/hch/nvmetcli.git</param> - <param name="changesrevision">9d51ae651a1c39a83b0192fbbe1e400abf3a0409</param></service></servicedata> \ No newline at end of file + <param name="changesrevision">0a6b088db2dc2e5de11e6f23f1e890e4b54fee64</param></service></servicedata> \ No newline at end of file ++++++ nvmetcli-v0.6.tar.gz -> nvmetcli-v0.7.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvmetcli-v0.6/README new/nvmetcli-v0.7/README --- old/nvmetcli-v0.6/README 2018-01-22 19:45:05.000000000 +0100 +++ new/nvmetcli-v0.7/README 2019-04-28 14:47:14.000000000 +0200 @@ -14,9 +14,11 @@ Common Package Dependencies and Problems ----------------------------------------- -nvmetcli uses the 'python-six' and 'pyparsing' packages -(running nvmetcli without these packages may produce -hard-to-decipher errors). +Both python2 and python3 are supported via use of the 'python-six' +package. + +nvmetcli uses the 'pyparsing' package -- running nvmetcli without this +package may produce hard-to-decipher errors. Usage ----- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvmetcli-v0.6/nvmet/__init__.py new/nvmetcli-v0.7/nvmet/__init__.py --- old/nvmetcli-v0.6/nvmet/__init__.py 2018-01-22 19:45:05.000000000 +0100 +++ new/nvmetcli-v0.7/nvmet/__init__.py 2019-04-28 14:47:14.000000000 +0200 @@ -1 +1 @@ -from .nvme import Root, Subsystem, Namespace, Port, Host, Referral +from .nvme import Root, Subsystem, Namespace, Port, Host, Referral, ANAGroup diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvmetcli-v0.6/nvmet/nvme.py new/nvmetcli-v0.7/nvmet/nvme.py --- old/nvmetcli-v0.6/nvmet/nvme.py 2018-01-22 19:45:05.000000000 +0100 +++ new/nvmetcli-v0.7/nvmet/nvme.py 2019-04-28 14:47:14.000000000 +0200 @@ -23,6 +23,7 @@ import uuid import json from glob import iglob as glob +from six import iteritems DEFAULT_SAVE_FILE = '/etc/nvmet/config.json' @@ -219,7 +220,7 @@ def _setup_attrs(self, attr_dict, err_func): for group in self.attr_groups: - for name, value in attr_dict.get(group, {}).iteritems(): + for name, value in iteritems(attr_dict.get(group, {})): try: self.set_attr(group, name, value) except CFSError as e: @@ -565,6 +566,24 @@ def _get_nsid(self): return self._nsid + def _get_grpid(self): + self._check_self() + _grpid = 0 + path = "%s/ana_grpid" % self.path + if os.path.isfile(path): + with open(path, 'r') as file_fd: + _grpid = int(file_fd.read().strip()) + return _grpid + + def set_grpid(self, grpid): + self._check_self() + path = "%s/ana_grpid" % self.path + if os.path.isfile(path): + with open(path, 'w') as file_fd: + file_fd.write(str(grpid)) + + grpid = property(_get_grpid, doc="Get the ANA Group ID.") + subsystem = property(_get_subsystem, doc="Get the parent Subsystem object.") nsid = property(_get_nsid, doc="Get the NSID as an int.") @@ -588,10 +607,13 @@ return ns._setup_attrs(n, err_func) + if 'ana_grpid' in n: + ns.set_grpid(int(n['ana_grpid'])) def dump(self): d = super(Namespace, self).dump() d['nsid'] = self.nsid + d['ana_grpid'] = self.grpid return d @@ -608,7 +630,7 @@ def __init__(self, portid, mode='any'): super(Port, self).__init__() - self.attr_groups = ['addr'] + self.attr_groups = ['addr', 'param'] self._portid = int(portid) self._path = "%s/ports/%d" % (self.configfs_dir, self._portid) self._create_in_cfs(mode) @@ -651,6 +673,8 @@ self._check_self() for s in self.subsystems: self.remove_subsystem(s) + for a in self.ana_groups: + a.delete() for r in self.referrals: r.delete() super(Port, self).delete() @@ -663,10 +687,19 @@ referrals = property(_list_referrals, doc="Get the list of Referrals for this Port.") + def _list_ana_groups(self): + self._check_self() + if os.path.isdir("%s/ana_groups/" % self._path): + for d in os.listdir("%s/ana_groups/" % self._path): + yield ANAGroup(self, int(d), 'lookup') + + ana_groups = property(_list_ana_groups, + doc="Get the list of ANA Groups for this Port.") + @classmethod def setup(cls, root, n, err_func): ''' - Set up a Namespace object based upon n dict, from saved config. + Set up a Port object based upon n dict, from saved config. Guard against missing or bad dict items, but keep going. Call 'err_func' for each error. ''' @@ -684,6 +717,8 @@ port._setup_attrs(n, err_func) for s in n.get('subsystems', []): port.add_subsystem(s) + for a in n.get('ana_groups', []): + ANAGroup.setup(port, a, err_func) for r in n.get('referrals', []): Referral.setup(port, r, err_func) @@ -691,6 +726,7 @@ d = super(Port, self).dump() d['portid'] = self.portid d['subsystems'] = self.subsystems + d['ana_groups'] = [a.dump() for a in self.ana_groups] d['referrals'] = [r.dump() for r in self.referrals] return d @@ -746,6 +782,75 @@ return d +class ANAGroup(CFSNode): + ''' + This is an interface to a NVMe ANA Group in configFS. + ''' + + MAX_GRPID = 1024 + + def __repr__(self): + return "<ANA Group %d>" % self.grpid + + def __init__(self, port, grpid, mode='any'): + super(ANAGroup, self).__init__() + + if not os.path.isdir("%s/ana_groups" % port.path): + raise CFSError("ANA not supported") + + if grpid is None: + if mode == 'lookup': + raise CFSError("Need grpid for lookup") + + grpids = [n.grpid for n in port.ana_groups] + for index in xrange(2, self.MAX_GRPID + 1): + if index not in grpids: + grpid = index + break + if grpid is None: + raise CFSError("All ANA Group IDs 1-%d in use" % self.MAX_GRPID) + else: + grpid = int(grpid) + if grpid < 1 or grpid > self.MAX_GRPID: + raise CFSError("GRPID %d must be 1 to %d" % (grpid, self.MAX_GRPID)) + + self.attr_groups = ['ana'] + self._port = port + self._grpid = grpid + self._path = "%s/ana_groups/%d" % (self._port.path, self.grpid) + self._create_in_cfs(mode) + + def _get_grpid(self): + return self._grpid + + grpid = property(_get_grpid, doc="Get the ANA Group ID.") + + @classmethod + def setup(cls, port, n, err_func): + ''' + Set up an ANA Group object based upon n dict, from saved config. + Guard against missing or bad dict items, but keep going. + Call 'err_func' for each error. + ''' + + if 'grpid' not in n: + err_func("'grpid' not defined for ANA Group") + return + + try: + a = ANAGroup(port, n['grpid']) + except CFSError as e: + err_func("Could not create ANA Group object: %s" % e) + return + + a._setup_attrs(n, err_func) + + def dump(self): + d = super(ANAGroup, self).dump() + d['grpid'] = self.grpid + return d + + class Host(CFSNode): ''' This is an interface to a NVMe Host in configFS. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvmetcli-v0.6/nvmetcli new/nvmetcli-v0.7/nvmetcli --- old/nvmetcli-v0.6/nvmetcli 2018-01-22 19:45:05.000000000 +0100 +++ new/nvmetcli-v0.7/nvmetcli 2019-04-28 14:47:14.000000000 +0200 @@ -27,9 +27,11 @@ from string import hexdigits import uuid + def ngiud_set(nguid): return any(c in hexdigits and c != '0' for c in nguid) + class UINode(configshell.node.ConfigNode): def __init__(self, name, parent=None, cfnode=None, shell=None): configshell.node.ConfigNode.__init__(self, name, parent, shell) @@ -166,9 +168,10 @@ def summary(self): info = [] - info.append("version=" + self.cfnode.get_attr("attr","version")) - info.append("allow_any=" + self.cfnode.get_attr("attr","allow_any_host")) - info.append("serial=" + self.cfnode.get_attr("attr","serial")) + info.append("version=" + self.cfnode.get_attr("attr", "version")) + info.append("allow_any=" + + self.cfnode.get_attr("attr", "allow_any_host")) + info.append("serial=" + self.cfnode.get_attr("attr", "serial")) return (", ".join(info), True) @@ -258,6 +261,16 @@ raise configshell.ExecutionError( "The Namespace could not be disabled.") + def ui_command_grpid(self, grpid): + ''' + Sets the ANA Group ID of the current Namespace to I{grpid} + ''' + try: + self.cfnode.set_grpid(grpid) + except Exception as e: + raise configshell.ExecutionError( + "Failed to set ANA Group ID for this Namespace.") + def summary(self): info = [] info.append("path=" + self.cfnode.get_attr("device", "path")) @@ -267,6 +280,8 @@ ns_nguid = self.cfnode.get_attr("device", "nguid") if ngiud_set(ns_nguid): info.append("nguid=" + ns_nguid) + if self.cfnode.grpid != 0: + info.append("grpid=" + str(self.cfnode.grpid)) info.append("enabled" if self.cfnode.get_enable() else "disabled") ns_enabled = self.cfnode.get_enable() return (", ".join(info), True if ns_enabled == 1 else ns_enabled) @@ -370,14 +385,24 @@ ui_desc_addr = { 'adrfam': ('string', 'Address Family (e.g. ipv4 or fc)'), 'treq': ('string', 'Transport Security Requirements'), - 'traddr': ('string', 'Transport Address (e.g. IP Address or FC wwnn:wwpn)'), + 'traddr': ('string', + 'Transport Address (e.g. IP Address or FC wwnn:wwpn)'), 'trsvcid': ('string', 'Transport Service ID (e.g. IP Port)'), 'trtype': ('string', 'Transport Type (e.g. rdma or loop or fc)'), } + ui_desc_param = { + 'inline_data_size': ('string', 'Port inline data size in bytes'), + } def __init__(self, parent, cfnode): UINode.__init__(self, str(cfnode.portid), parent, cfnode) UIPortSubsystemsNode(self) + try: + next(cfnode.ana_groups) + except StopIteration: + pass + else: + UIANAGroupsNode(self) UIReferralsNode(self) def summary(self): @@ -387,9 +412,20 @@ trsvcid = self.cfnode.get_attr("addr", "trsvcid") if trsvcid != "none": info.append("trsvcid=%s" % trsvcid) - enabled = not (not self.cfnode.subsystems and not list(self.cfnode.referrals)) + + ''' + Support older target driver w/o the inline_data_size parameter + ''' + try: + inline_data_size = self.cfnode.get_attr("param", "inline_data_size") + except Exception as e: + inline_data_size = "n/a" + if inline_data_size != "n/a": + info.append("inline_data_size=" + inline_data_size) + enabled = self.cfnode.subsystems or list(self.cfnode.referrals) return (", ".join(info), True if enabled else 0) + class UIPortSubsystemsNode(UINode): def __init__(self, parent): UINode.__init__(self, 'subsystems', parent) @@ -488,7 +524,8 @@ ui_desc_addr = { 'adrfam': ('string', 'Address Family (e.g. ipv4 or fc)'), 'treq': ('string', 'Transport Security Requirements'), - 'traddr': ('string', 'Transport Address (e.g. IP Address or FC wwnn:wwpn)'), + 'traddr': ('string', + 'Transport Address (e.g. IP Address or FC wwnn:wwpn)'), 'trsvcid': ('string', 'Transport Service ID (e.g. IP Port)'), 'trtype': ('string', 'Transport Type (e.g. rdma or loop or fc)'), 'portid': ('number', 'Port identifier'), @@ -539,6 +576,52 @@ "The Referral could not be disabled.") +class UIANAGroupsNode(UINode): + def __init__(self, parent): + UINode.__init__(self, 'ana_groups', parent) + + def refresh(self): + self._children = set([]) + for a in self.parent.cfnode.ana_groups: + UIANAGroupNode(self, a) + + def ui_command_create(self, grpid): + ''' + Creates a new ANA Group. + + SEE ALSO + ======== + B{delete} + ''' + a = nvme.ANAGroup(self.parent.cfnode, grpid, mode='create') + UIANAGroupNode(self, a) + + def ui_command_delete(self, grpid): + ''' + Deletes the ANA Group with the specified I{name}. + + SEE ALSO + ======== + B{create} + ''' + a = nvme.ANAGroup(self.parent.cfnode, grpid, mode='lookup') + a.delete() + self.refresh() + + +class UIANAGroupNode(UINode): + ui_desc_ana = { + 'state' : ('string', 'ANA state'), + } + + def __init__(self, parent, cfnode): + UINode.__init__(self, str(cfnode.grpid), parent, cfnode) + + def summary(self): + info = [] + info.append("state=" + self.cfnode.get_attr("ana", "state")) + return (", ".join(info), True) + class UIHostsNode(UINode): def __init__(self, parent): UINode.__init__(self, 'hosts', parent) @@ -652,5 +735,6 @@ except Exception as msg: shell.log.error(str(msg)) + if __name__ == "__main__": main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvmetcli-v0.6/setup.py new/nvmetcli-v0.7/setup.py --- old/nvmetcli-v0.6/setup.py 2018-01-22 19:45:05.000000000 +0100 +++ new/nvmetcli-v0.7/setup.py 2019-04-28 14:47:14.000000000 +0200 @@ -20,7 +20,7 @@ setup( name = 'nvmetcli', - version = 0.6, + version = 0.7, description = 'NVMe target configuration tool', license = 'Apache 2.0', maintainer = 'Christoph Hellwig',