Blame nvmetcli

Packit 01965a
#!/usr/bin/python
Packit 01965a
Packit 01965a
'''
Packit 01965a
Frontend to access to the NVMe target configfs hierarchy
Packit 01965a
Packit 01965a
Copyright (c) 2016 by HGST, a Western Digital Company.
Packit 01965a
Packit 01965a
Licensed under the Apache License, Version 2.0 (the "License"); you may
Packit 01965a
not use this file except in compliance with the License. You may obtain
Packit 01965a
a copy of the License at
Packit 01965a
Packit 01965a
    http://www.apache.org/licenses/LICENSE-2.0
Packit 01965a
Packit 01965a
Unless required by applicable law or agreed to in writing, software
Packit 01965a
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
Packit 01965a
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
Packit 01965a
License for the specific language governing permissions and limitations
Packit 01965a
under the License.
Packit 01965a
'''
Packit 01965a
Packit 01965a
from __future__ import print_function
Packit 01965a
Packit 01965a
import os
Packit 01965a
import sys
Packit 01965a
import configshell_fb as configshell
Packit 01965a
import nvmet as nvme
Packit 01965a
from string import hexdigits
Packit 01965a
import uuid
Packit 01965a
Packit 01965a
def ngiud_set(nguid):
Packit 01965a
    return any(c in hexdigits and c != '0' for c in nguid)
Packit 01965a
Packit 01965a
class UINode(configshell.node.ConfigNode):
Packit 01965a
    def __init__(self, name, parent=None, cfnode=None, shell=None):
Packit 01965a
        configshell.node.ConfigNode.__init__(self, name, parent, shell)
Packit 01965a
        self.cfnode = cfnode
Packit 01965a
        if self.cfnode:
Packit 01965a
            if self.cfnode.attr_groups:
Packit 01965a
                for group in self.cfnode.attr_groups:
Packit 01965a
                    self._init_group(group)
Packit 01965a
        self.refresh()
Packit 01965a
Packit 01965a
    def _init_group(self, group):
Packit 01965a
        setattr(self.__class__, "ui_getgroup_%s" % group,
Packit 01965a
                lambda self, attr:
Packit 01965a
                    self.cfnode.get_attr(group, attr))
Packit 01965a
        setattr(self.__class__, "ui_setgroup_%s" % group,
Packit 01965a
                lambda self, attr, value:
Packit 01965a
                    self.cfnode.set_attr(group, attr, value))
Packit 01965a
Packit 01965a
        attrs = self.cfnode.list_attrs(group)
Packit 01965a
        attrs_ro = self.cfnode.list_attrs(group, writable=False)
Packit 01965a
        for attr in attrs:
Packit 01965a
            writable = attr not in attrs_ro
Packit 01965a
Packit 01965a
            name = "ui_desc_%s" % group
Packit 01965a
            t, d = getattr(self.__class__, name, {}).get(attr, ('string', ''))
Packit 01965a
            self.define_config_group_param(group, attr, t, d, writable)
Packit 01965a
Packit 01965a
    def refresh(self):
Packit 01965a
        self._children = set([])
Packit 01965a
Packit 01965a
    def status(self):
Packit 01965a
        return "None"
Packit 01965a
Packit 01965a
    def ui_command_refresh(self):
Packit 01965a
        '''
Packit 01965a
        Refreshes and updates the objects tree from the current path.
Packit 01965a
        '''
Packit 01965a
        self.refresh()
Packit 01965a
Packit 01965a
    def ui_command_status(self):
Packit 01965a
        '''
Packit 01965a
        Displays the current node's status summary.
Packit 01965a
Packit 01965a
        SEE ALSO
Packit 01965a
        ========
Packit 01965a
        B{ls}
Packit 01965a
        '''
Packit 01965a
        self.shell.log.info("Status for %s: %s" % (self.path, self.status()))
Packit 01965a
Packit 01965a
    def ui_command_saveconfig(self, savefile=None):
Packit 01965a
        '''
Packit 01965a
        Saves the current configuration to a file so that it can be restored
Packit 01965a
        on next boot.
Packit 01965a
        '''
Packit 01965a
        node = self
Packit 01965a
        while node.parent is not None:
Packit 01965a
            node = node.parent
Packit 01965a
        node.cfnode.save_to_file(savefile)
Packit 01965a
Packit 01965a
Packit 01965a
class UIRootNode(UINode):
Packit 01965a
    def __init__(self, shell):
Packit 01965a
        UINode.__init__(self, '/', parent=None, cfnode=nvme.Root(),
Packit 01965a
                        shell=shell)
Packit 01965a
Packit 01965a
    def refresh(self):
Packit 01965a
        self._children = set([])
Packit 01965a
        UISubsystemsNode(self)
Packit 01965a
        UIPortsNode(self)
Packit 01965a
        UIHostsNode(self)
Packit 01965a
Packit 01965a
    def ui_command_restoreconfig(self, savefile=None, clear_existing=False):
Packit 01965a
        '''
Packit 01965a
        Restores configuration from a file.
Packit 01965a
        '''
Packit 01965a
        errors = self.cfnode.restore_from_file(savefile, clear_existing)
Packit 01965a
        self.refresh()
Packit 01965a
Packit 01965a
        if errors:
Packit 01965a
            raise configshell.ExecutionError(
Packit 01965a
                "Configuration restored, %d errors:\n%s" %
Packit 01965a
                (len(errors), "\n".join(errors)))
Packit 01965a
Packit 01965a
Packit 01965a
class UISubsystemsNode(UINode):
Packit 01965a
    def __init__(self, parent):
Packit 01965a
        UINode.__init__(self, 'subsystems', parent)
Packit 01965a
Packit 01965a
    def refresh(self):
Packit 01965a
        self._children = set([])
Packit 01965a
        for subsys in self.parent.cfnode.subsystems:
Packit 01965a
            UISubsystemNode(self, subsys)
Packit 01965a
Packit 01965a
    def ui_command_create(self, nqn=None):
Packit 01965a
        '''
Packit 01965a
        Creates a new target. If I{nqn} is ommited, then the new Subsystem
Packit 01965a
        will be created using a randomly generated NQN.
Packit 01965a
Packit 01965a
        SEE ALSO
Packit 01965a
        ========
Packit 01965a
        B{delete}
Packit 01965a
        '''
Packit 01965a
        subsystem = nvme.Subsystem(nqn, mode='create')
Packit 01965a
        UISubsystemNode(self, subsystem)
Packit 01965a
Packit 01965a
    def ui_command_delete(self, nqn):
Packit 01965a
        '''
Packit 01965a
        Recursively deletes the subsystem with the specified I{nqn}, and all
Packit 01965a
        objects hanging under it.
Packit 01965a
Packit 01965a
        SEE ALSO
Packit 01965a
        ========
Packit 01965a
        B{create}
Packit 01965a
        '''
Packit 01965a
        subsystem = nvme.Subsystem(nqn, mode='lookup')
Packit 01965a
        subsystem.delete()
Packit 01965a
        self.refresh()
Packit 01965a
Packit 01965a
Packit 01965a
class UISubsystemNode(UINode):
Packit 01965a
    ui_desc_attr = {
Packit 01965a
        'allow_any_host': ('string', 'Allow access by any host if set to 1'),
Packit 01965a
        'serial': ('string', 'Export serial number to hosts'),
Packit 01965a
        'version': ('string', 'Export version number to hosts'),
Packit 01965a
    }
Packit 01965a
Packit 01965a
    def __init__(self, parent, cfnode):
Packit 01965a
        UINode.__init__(self, cfnode.nqn, parent, cfnode)
Packit 01965a
Packit 01965a
    def refresh(self):
Packit 01965a
        self._children = set([])
Packit 01965a
        UINamespacesNode(self)
Packit 01965a
        UIAllowedHostsNode(self)
Packit 01965a
Packit 01965a
    def summary(self):
Packit 01965a
        info = []
Packit 01965a
        info.append("version=" + self.cfnode.get_attr("attr","version"))
Packit 01965a
        info.append("allow_any=" + self.cfnode.get_attr("attr","allow_any_host"))
Packit 01965a
        info.append("serial=" + self.cfnode.get_attr("attr","serial"))
Packit 01965a
        return (", ".join(info), True)
Packit 01965a
Packit 01965a
Packit 01965a
class UINamespacesNode(UINode):
Packit 01965a
    def __init__(self, parent):
Packit 01965a
        UINode.__init__(self, 'namespaces', parent)
Packit 01965a
Packit 01965a
    def refresh(self):
Packit 01965a
        self._children = set([])
Packit 01965a
        for ns in self.parent.cfnode.namespaces:
Packit 01965a
            UINamespaceNode(self, ns)
Packit 01965a
Packit 01965a
    def ui_command_create(self, nsid=None):
Packit 01965a
        '''
Packit 01965a
        Creates a new namespace. If I{nsid} is ommited, then the next
Packit 01965a
        available namespace id will be used.
Packit 01965a
Packit 01965a
        SEE ALSO
Packit 01965a
        ========
Packit 01965a
        B{delete}
Packit 01965a
        '''
Packit 01965a
        namespace = nvme.Namespace(self.parent.cfnode, nsid, mode='create')
Packit 01965a
        UINamespaceNode(self, namespace)
Packit 01965a
Packit 01965a
    def ui_command_delete(self, nsid):
Packit 01965a
        '''
Packit 01965a
        Recursively deletes the namespace with the specified I{nsid}, and all
Packit 01965a
        objects hanging under it.
Packit 01965a
Packit 01965a
        SEE ALSO
Packit 01965a
        ========
Packit 01965a
        B{create}
Packit 01965a
        '''
Packit 01965a
        namespace = nvme.Namespace(self.parent.cfnode, nsid, mode='lookup')
Packit 01965a
        namespace.delete()
Packit 01965a
        self.refresh()
Packit 01965a
Packit 01965a
Packit 01965a
class UINamespaceNode(UINode):
Packit 01965a
    ui_desc_device = {
Packit 01965a
        'path': ('string', 'Backing device path.'),
Packit 01965a
        'nguid': ('string', 'Namspace Global Unique Identifier.'),
Packit 01965a
        'uuid': ('string', 'Namespace Universally Unique Identifier.'),
Packit 01965a
    }
Packit 01965a
Packit 01965a
    def __init__(self, parent, cfnode):
Packit 01965a
        UINode.__init__(self, str(cfnode.nsid), parent, cfnode)
Packit 01965a
Packit 01965a
    def status(self):
Packit 01965a
        if self.cfnode.get_enable():
Packit 01965a
            return "enabled"
Packit 01965a
        return "disabled"
Packit 01965a
Packit 01965a
    def ui_command_enable(self):
Packit 01965a
        '''
Packit 01965a
        Enables the current Namespace.
Packit 01965a
Packit 01965a
        SEE ALSO
Packit 01965a
        ========
Packit 01965a
        B{disable}
Packit 01965a
        '''
Packit 01965a
        if self.cfnode.get_enable():
Packit 01965a
            self.shell.log.info("The Namespace is already enabled.")
Packit 01965a
        else:
Packit 01965a
            try:
Packit 01965a
                self.cfnode.set_enable(1)
Packit 01965a
                self.shell.log.info("The Namespace has been enabled.")
Packit 01965a
            except Exception as e:
Packit 01965a
                raise configshell.ExecutionError(
Packit 01965a
                    "The Namespace could not be enabled.")
Packit 01965a
Packit 01965a
    def ui_command_disable(self):
Packit 01965a
        '''
Packit 01965a
        Disables the current Namespace.
Packit 01965a
Packit 01965a
        SEE ALSO
Packit 01965a
        ========
Packit 01965a
        B{enable}
Packit 01965a
        '''
Packit 01965a
        if not self.cfnode.get_enable():
Packit 01965a
            self.shell.log.info("The Namespace is already disabled.")
Packit 01965a
        else:
Packit 01965a
            try:
Packit 01965a
                self.cfnode.set_enable(0)
Packit 01965a
                self.shell.log.info("The Namespace has been disabled.")
Packit 01965a
            except Exception as e:
Packit 01965a
                raise configshell.ExecutionError(
Packit 01965a
                    "The Namespace could not be disabled.")
Packit 01965a
Packit 01965a
    def summary(self):
Packit 01965a
        info = []
Packit 01965a
        info.append("path=" + self.cfnode.get_attr("device", "path"))
Packit 01965a
        ns_uuid = self.cfnode.get_attr("device", "uuid")
Packit 01965a
        if uuid.UUID(ns_uuid).int != 0:
Packit 01965a
            info.append("uuid=" + str(ns_uuid))
Packit 01965a
        ns_nguid = self.cfnode.get_attr("device", "nguid")
Packit 01965a
        if ngiud_set(ns_nguid):
Packit 01965a
            info.append("nguid=" + ns_nguid)
Packit 01965a
        info.append("enabled" if self.cfnode.get_enable() else "disabled")
Packit 01965a
        ns_enabled = self.cfnode.get_enable()
Packit 01965a
        return (", ".join(info), True if ns_enabled == 1 else ns_enabled)
Packit 01965a
Packit 01965a
Packit 01965a
class UIAllowedHostsNode(UINode):
Packit 01965a
    def __init__(self, parent):
Packit 01965a
        UINode.__init__(self, 'allowed_hosts', parent)
Packit 01965a
Packit 01965a
    def refresh(self):
Packit 01965a
        self._children = set([])
Packit 01965a
        for host in self.parent.cfnode.allowed_hosts:
Packit 01965a
            UIAllowedHostNode(self, host)
Packit 01965a
Packit 01965a
    def ui_command_create(self, nqn):
Packit 01965a
        '''
Packit 01965a
        Grants access to parent subsystems to the host specified by I{nqn}.
Packit 01965a
Packit 01965a
        SEE ALSO
Packit 01965a
        ========
Packit 01965a
        B{delete}
Packit 01965a
        '''
Packit 01965a
        self.parent.cfnode.add_allowed_host(nqn)
Packit 01965a
        UIAllowedHostNode(self, nqn)
Packit 01965a
Packit 01965a
    def ui_complete_create(self, parameters, text, current_param):
Packit 01965a
        completions = []
Packit 01965a
        if current_param == 'nqn':
Packit 01965a
            for host in self.get_node('/hosts').children:
Packit 01965a
                completions.append(host.cfnode.nqn)
Packit 01965a
Packit 01965a
        if len(completions) == 1:
Packit 01965a
            return [completions[0] + ' ']
Packit 01965a
        else:
Packit 01965a
            return completions
Packit 01965a
Packit 01965a
    def ui_command_delete(self, nqn):
Packit 01965a
        '''
Packit 01965a
        Recursively deletes the namespace with the specified I{nsid}, and all
Packit 01965a
        objects hanging under it.
Packit 01965a
Packit 01965a
        SEE ALSO
Packit 01965a
        ========
Packit 01965a
        B{create}
Packit 01965a
        '''
Packit 01965a
        self.parent.cfnode.remove_allowed_host(nqn)
Packit 01965a
        self.refresh()
Packit 01965a
Packit 01965a
    def ui_complete_delete(self, parameters, text, current_param):
Packit 01965a
        completions = []
Packit 01965a
        if current_param == 'nqn':
Packit 01965a
            for nqn in self.parent.cfnode.allowed_hosts:
Packit 01965a
                completions.append(nqn)
Packit 01965a
Packit 01965a
        if len(completions) == 1:
Packit 01965a
            return [completions[0] + ' ']
Packit 01965a
        else:
Packit 01965a
            return completions
Packit 01965a
Packit 01965a
Packit 01965a
class UIAllowedHostNode(UINode):
Packit 01965a
    def __init__(self, parent, nqn):
Packit 01965a
        UINode.__init__(self, nqn, parent)
Packit 01965a
Packit 01965a
Packit 01965a
class UIPortsNode(UINode):
Packit 01965a
    def __init__(self, parent):
Packit 01965a
        UINode.__init__(self, 'ports', parent)
Packit 01965a
Packit 01965a
    def refresh(self):
Packit 01965a
        self._children = set([])
Packit 01965a
        for port in self.parent.cfnode.ports:
Packit 01965a
            UIPortNode(self, port)
Packit 01965a
Packit 01965a
    def ui_command_create(self, portid=None):
Packit 01965a
        '''
Packit 01965a
        Creates a new NVMe port with portid I{portid}.
Packit 01965a
Packit 01965a
        SEE ALSO
Packit 01965a
        ========
Packit 01965a
        B{delete}
Packit 01965a
        '''
Packit 01965a
        port = nvme.Port(portid, mode='create')
Packit 01965a
        UIPortNode(self, port)
Packit 01965a
Packit 01965a
    def ui_command_delete(self, portid):
Packit 01965a
        '''
Packit 01965a
        Recursively deletes the NVMe Port with the specified I{port}, and all
Packit 01965a
        objects hanging under it.
Packit 01965a
Packit 01965a
        SEE ALSO
Packit 01965a
        ========
Packit 01965a
        B{create}
Packit 01965a
        '''
Packit 01965a
        port = nvme.Port(portid, mode='lookup')
Packit 01965a
        port.delete()
Packit 01965a
        self.refresh()
Packit 01965a
Packit 01965a
Packit 01965a
class UIPortNode(UINode):
Packit 01965a
    ui_desc_addr = {
Packit 01965a
        'adrfam': ('string', 'Address Family (e.g. ipv4 or fc)'),
Packit 01965a
        'treq': ('string', 'Transport Security Requirements'),
Packit 01965a
        'traddr': ('string', 'Transport Address (e.g. IP Address or FC wwnn:wwpn)'),
Packit 01965a
        'trsvcid': ('string', 'Transport Service ID (e.g. IP Port)'),
Packit 01965a
        'trtype': ('string', 'Transport Type (e.g. rdma or loop or fc)'),
Packit 01965a
    }
Packit 01965a
Packit 01965a
    def __init__(self, parent, cfnode):
Packit 01965a
        UINode.__init__(self, str(cfnode.portid), parent, cfnode)
Packit 01965a
        UIPortSubsystemsNode(self)
Packit 01965a
        UIReferralsNode(self)
Packit 01965a
Packit 01965a
    def summary(self):
Packit 01965a
        info = []
Packit 01965a
        info.append("trtype=" + self.cfnode.get_attr("addr", "trtype"))
Packit 01965a
        info.append("traddr=" + self.cfnode.get_attr("addr", "traddr"))
Packit 01965a
        trsvcid = self.cfnode.get_attr("addr", "trsvcid")
Packit 01965a
        if trsvcid != "none":
Packit 01965a
            info.append("trsvcid=%s" % trsvcid)
Packit 01965a
        enabled = not (not self.cfnode.subsystems and not list(self.cfnode.referrals))
Packit 01965a
        return (", ".join(info), True if enabled else 0)
Packit 01965a
Packit 01965a
class UIPortSubsystemsNode(UINode):
Packit 01965a
    def __init__(self, parent):
Packit 01965a
        UINode.__init__(self, 'subsystems', parent)
Packit 01965a
Packit 01965a
    def refresh(self):
Packit 01965a
        self._children = set([])
Packit 01965a
        for host in self.parent.cfnode.subsystems:
Packit 01965a
            UIPortSubsystemNode(self, host)
Packit 01965a
Packit 01965a
    def ui_command_create(self, nqn):
Packit 01965a
        '''
Packit 01965a
        Grants access to the subsystem specified by I{nqn} through the
Packit 01965a
        parent port.
Packit 01965a
Packit 01965a
        SEE ALSO
Packit 01965a
        ========
Packit 01965a
        B{delete}
Packit 01965a
        '''
Packit 01965a
        self.parent.cfnode.add_subsystem(nqn)
Packit 01965a
        UIPortSubsystemNode(self, nqn)
Packit 01965a
Packit 01965a
    def ui_complete_create(self, parameters, text, current_param):
Packit 01965a
        completions = []
Packit 01965a
        if current_param == 'nqn':
Packit 01965a
            for subsys in self.get_node('/subsystems').children:
Packit 01965a
                completions.append(subsys.cfnode.nqn)
Packit 01965a
Packit 01965a
        if len(completions) == 1:
Packit 01965a
            return [completions[0] + ' ']
Packit 01965a
        else:
Packit 01965a
            return completions
Packit 01965a
Packit 01965a
    def ui_command_delete(self, nqn):
Packit 01965a
        '''
Packit 01965a
        Removes access to the subsystem specified by I{nqn} through the
Packit 01965a
        parent port.
Packit 01965a
Packit 01965a
        SEE ALSO
Packit 01965a
        ========
Packit 01965a
        B{create}
Packit 01965a
        '''
Packit 01965a
        self.parent.cfnode.remove_subsystem(nqn)
Packit 01965a
        self.refresh()
Packit 01965a
Packit 01965a
    def ui_complete_delete(self, parameters, text, current_param):
Packit 01965a
        completions = []
Packit 01965a
        if current_param == 'nqn':
Packit 01965a
            for nqn in self.parent.cfnode.subsystems:
Packit 01965a
                completions.append(nqn)
Packit 01965a
Packit 01965a
        if len(completions) == 1:
Packit 01965a
            return [completions[0] + ' ']
Packit 01965a
        else:
Packit 01965a
            return completions
Packit 01965a
Packit 01965a
Packit 01965a
class UIPortSubsystemNode(UINode):
Packit 01965a
    def __init__(self, parent, nqn):
Packit 01965a
        UINode.__init__(self, nqn, parent)
Packit 01965a
Packit 01965a
Packit 01965a
class UIReferralsNode(UINode):
Packit 01965a
    def __init__(self, parent):
Packit 01965a
        UINode.__init__(self, 'referrals', parent)
Packit 01965a
Packit 01965a
    def refresh(self):
Packit 01965a
        self._children = set([])
Packit 01965a
        for r in self.parent.cfnode.referrals:
Packit 01965a
            UIReferralNode(self, r)
Packit 01965a
Packit 01965a
    def ui_command_create(self, name):
Packit 01965a
        '''
Packit 01965a
        Creates a new referral.
Packit 01965a
Packit 01965a
        SEE ALSO
Packit 01965a
        ========
Packit 01965a
        B{delete}
Packit 01965a
        '''
Packit 01965a
        r = nvme.Referral(self.parent.cfnode, name, mode='create')
Packit 01965a
        UIReferralNode(self, r)
Packit 01965a
Packit 01965a
    def ui_command_delete(self, name):
Packit 01965a
        '''
Packit 01965a
        Deletes the referral with the specified I{name}.
Packit 01965a
Packit 01965a
        SEE ALSO
Packit 01965a
        ========
Packit 01965a
        B{create}
Packit 01965a
        '''
Packit 01965a
        r = nvme.Referral(self.parent.cfnode, name, mode='lookup')
Packit 01965a
        r.delete()
Packit 01965a
        self.refresh()
Packit 01965a
Packit 01965a
Packit 01965a
class UIReferralNode(UINode):
Packit 01965a
    ui_desc_addr = {
Packit 01965a
        'adrfam': ('string', 'Address Family (e.g. ipv4 or fc)'),
Packit 01965a
        'treq': ('string', 'Transport Security Requirements'),
Packit 01965a
        'traddr': ('string', 'Transport Address (e.g. IP Address or FC wwnn:wwpn)'),
Packit 01965a
        'trsvcid': ('string', 'Transport Service ID (e.g. IP Port)'),
Packit 01965a
        'trtype': ('string', 'Transport Type (e.g. rdma or loop or fc)'),
Packit 01965a
        'portid': ('number', 'Port identifier'),
Packit 01965a
    }
Packit 01965a
Packit 01965a
    def __init__(self, parent, cfnode):
Packit 01965a
        UINode.__init__(self, cfnode.name, parent, cfnode)
Packit 01965a
Packit 01965a
    def status(self):
Packit 01965a
        if self.cfnode.get_enable():
Packit 01965a
            return "enabled"
Packit 01965a
        return "disabled"
Packit 01965a
Packit 01965a
    def ui_command_enable(self):
Packit 01965a
        '''
Packit 01965a
        Enables the current Referral.
Packit 01965a
Packit 01965a
        SEE ALSO
Packit 01965a
        ========
Packit 01965a
        B{disable}
Packit 01965a
        '''
Packit 01965a
        if self.cfnode.get_enable():
Packit 01965a
            self.shell.log.info("The Referral is already enabled.")
Packit 01965a
        else:
Packit 01965a
            try:
Packit 01965a
                self.cfnode.set_enable(1)
Packit 01965a
                self.shell.log.info("The Referral has been enabled.")
Packit 01965a
            except Exception as e:
Packit 01965a
                raise configshell.ExecutionError(
Packit 01965a
                    "The Referral could not be enabled.")
Packit 01965a
Packit 01965a
    def ui_command_disable(self):
Packit 01965a
        '''
Packit 01965a
        Disables the current Referral.
Packit 01965a
Packit 01965a
        SEE ALSO
Packit 01965a
        ========
Packit 01965a
        B{enable}
Packit 01965a
        '''
Packit 01965a
        if not self.cfnode.get_enable():
Packit 01965a
            self.shell.log.info("The Referral is already disabled.")
Packit 01965a
        else:
Packit 01965a
            try:
Packit 01965a
                self.cfnode.set_enable(0)
Packit 01965a
                self.shell.log.info("The Referral has been disabled.")
Packit 01965a
            except Exception as e:
Packit 01965a
                raise configshell.ExecutionError(
Packit 01965a
                    "The Referral could not be disabled.")
Packit 01965a
Packit 01965a
Packit 01965a
class UIHostsNode(UINode):
Packit 01965a
    def __init__(self, parent):
Packit 01965a
        UINode.__init__(self, 'hosts', parent)
Packit 01965a
Packit 01965a
    def refresh(self):
Packit 01965a
        self._children = set([])
Packit 01965a
        for host in self.parent.cfnode.hosts:
Packit 01965a
            UIHostNode(self, host)
Packit 01965a
Packit 01965a
    def ui_command_create(self, nqn):
Packit 01965a
        '''
Packit 01965a
        Creates a new NVMe host.
Packit 01965a
Packit 01965a
        SEE ALSO
Packit 01965a
        ========
Packit 01965a
        B{delete}
Packit 01965a
        '''
Packit 01965a
        host = nvme.Host(nqn, mode='create')
Packit 01965a
        UIHostNode(self, host)
Packit 01965a
Packit 01965a
    def ui_command_delete(self, nqn):
Packit 01965a
        '''
Packit 01965a
        Recursively deletes the NVMe Host with the specified I{nqn}, and all
Packit 01965a
        objects hanging under it.
Packit 01965a
Packit 01965a
        SEE ALSO
Packit 01965a
        ========
Packit 01965a
        B{create}
Packit 01965a
        '''
Packit 01965a
        host = nvme.Host(nqn, mode='lookup')
Packit 01965a
        host.delete()
Packit 01965a
        self.refresh()
Packit 01965a
Packit 01965a
Packit 01965a
class UIHostNode(UINode):
Packit 01965a
    def __init__(self, parent, cfnode):
Packit 01965a
        UINode.__init__(self, cfnode.nqn, parent, cfnode)
Packit 01965a
Packit 01965a
Packit 01965a
def usage():
Packit 01965a
    print("syntax: %s save [file_to_save_to]" % sys.argv[0])
Packit 01965a
    print("        %s restore [file_to_restore_from]" % sys.argv[0])
Packit 01965a
    print("        %s clear" % sys.argv[0])
Packit 01965a
    print("        %s ls" % sys.argv[0])
Packit 01965a
    sys.exit(-1)
Packit 01965a
Packit 01965a
Packit 01965a
def save(to_file):
Packit 01965a
    nvme.Root().save_to_file(to_file)
Packit 01965a
Packit 01965a
Packit 01965a
def restore(from_file):
Packit 01965a
    try:
Packit 01965a
        errors = nvme.Root().restore_from_file(from_file)
Packit 01965a
    except IOError:
Packit 01965a
        # Not an error if the restore file is not present
Packit 01965a
        print("No saved config file at %s, ok, exiting" % from_file)
Packit 01965a
    sys.exit(0)
Packit 01965a
Packit 01965a
    for error in errors:
Packit 01965a
        print(error)
Packit 01965a
Packit 01965a
Packit 01965a
def clear(unused):
Packit 01965a
    nvme.Root().clear_existing()
Packit 01965a
Packit 01965a
Packit 01965a
def ls(unused):
Packit 01965a
    shell = configshell.shell.ConfigShell('~/.nvmetcli')
Packit 01965a
    UIRootNode(shell)
Packit 01965a
    shell.run_cmdline("ls")
Packit 01965a
    sys.exit(0)
Packit 01965a
Packit 01965a
Packit 01965a
funcs = dict(save=save, restore=restore, clear=clear, ls=ls)
Packit 01965a
Packit 01965a
Packit 01965a
def main():
Packit 01965a
    if os.geteuid() != 0:
Packit 01965a
        print("%s: must run as root." % sys.argv[0], file=sys.stderr)
Packit 01965a
        sys.exit(-1)
Packit 01965a
Packit 01965a
    if len(sys.argv) > 3:
Packit 01965a
        usage()
Packit 01965a
Packit 01965a
    if len(sys.argv) == 2 or len(sys.argv) == 3:
Packit 01965a
        if sys.argv[1] == "--help":
Packit 01965a
            usage()
Packit 01965a
Packit 01965a
        if sys.argv[1] not in funcs.keys():
Packit 01965a
            usage()
Packit 01965a
Packit 01965a
        if len(sys.argv) == 3:
Packit 01965a
            savefile = sys.argv[2]
Packit 01965a
        else:
Packit 01965a
            savefile = None
Packit 01965a
Packit 01965a
        funcs[sys.argv[1]](savefile)
Packit 01965a
        return
Packit 01965a
Packit 01965a
    try:
Packit 01965a
        shell = configshell.shell.ConfigShell('~/.nvmetcli')
Packit 01965a
        UIRootNode(shell)
Packit 01965a
    except Exception as msg:
Packit 01965a
        shell.log.error(str(msg))
Packit 01965a
        return
Packit 01965a
Packit 01965a
    while not shell._exit:
Packit 01965a
        try:
Packit 01965a
            shell.run_interactive()
Packit 01965a
        except Exception as msg:
Packit 01965a
            shell.log.error(str(msg))
Packit 01965a
Packit 01965a
if __name__ == "__main__":
Packit 01965a
    main()