{
+ "hosts": [],
"ports": [
{
"addr": {
"trsvcid": "1023",
"trtype": "rdma"
},
- "enable": 1,
- "portid": 2
+ "portid": 2,
+ "subsystems": [
+ "nqn.2014-08.org.nvmexpress:NVMf:uuid:77dca664-0d3e-4f67-b8b2-04c70e3f991d"
+ ]
}
],
"subsystems": [
{
+ "allowed_hosts": [],
+ "attr": {
+ "allow_any_host": "1"
+ },
"namespaces": [
- {
- "device": {
- "nguid": "8a6a2e57-1a2d-2b41-8938-bc409c4ebb6c",
- "path": "/dev/ram0"
- },
- "enable": 0,
- "nsid": 2
- },
{
"device": {
"nguid": "289ae029-c396-3143-87e8-aec0d7a4b1a8",
},
"enable": 1,
"nsid": 1
+ },
+ {
+ "device": {
+ "nguid": "8a6a2e57-1a2d-2b41-8938-bc409c4ebb6c",
+ "path": "/dev/ram0"
+ },
+ "enable": 0,
+ "nsid": 2
}
],
"nqn": "nqn.2014-08.org.nvmexpress:NVMf:uuid:77dca664-0d3e-4f67-b8b2-04c70e3f991d"
Remove entire current configuration.
'''
- for s in self.subsystems:
- s.delete()
for p in self.ports:
p.delete()
+ for s in self.subsystems:
+ s.delete()
for h in self.hosts:
h.delete()
portid = property(_get_portid,
doc="Get the Port ID as an int.")
+ def _list_subsystems(self):
+ return [os.path.basename(name)
+ for name in os.listdir("%s/subsystems/" % self._path)]
+
+ subsystems = property(_list_subsystems,
+ doc="Get the list of Subsystem for this Port.")
+
+ def add_subsystem(self, nqn):
+ '''
+ Enable access to the Subsystem identified by I{nqn} through this Port.
+ '''
+ try:
+ os.symlink("%s/subsystems/%s" % (self.configfs_dir, nqn),
+ "%s/subsystems/%s" % (self._path, nqn))
+ except Exception as e:
+ raise CFSError("Could not symlink %s in configFS: %s" % (nqn, e))
+
+ def remove_subsystem(self, nqn):
+ '''
+ Disable access to the Subsystem identified by I{nqn} through this Port.
+ '''
+ try:
+ os.unlink("%s/subsystems/%s" % (self._path, nqn))
+ except Exception as e:
+ raise CFSError("Could not unlink %s in configFS: %s" % (nqn, e))
+
+ def delete(self):
+ '''
+ Recursively deletes a Port object.
+ '''
+ self._check_self()
+ for s in self.subsystems:
+ self.remove_subsystem(s);
+ super(Port, self).delete()
+
@classmethod
def setup(cls, root, n, err_func):
'''
return
port._setup_attrs(n, err_func)
+ for s in n.get('subsystems', []):
+ port.add_subsystem(s)
def dump(self):
d = super(Port, self).dump()
d['portid'] = self.portid
+ d['subsystems'] = self.subsystems
return d
root = nvme.Root()
root.clear_existing()
+ s = nvme.Subsystem(nqn='testnqn', mode='create')
p = nvme.Port(root, portid=0, mode='create')
- self.assertFalse(p.get_enable())
+ # subsystem doesn't exists, should fail
+ self.assertRaises(nvme.CFSError, p.add_subsystem, 'invalidnqn')
+
self.assertTrue('addr' in p.attr_groups)
# no trtype set yet, should fail
- self.assertRaises(nvme.CFSError, p.set_enable, 1)
+ self.assertRaises(nvme.CFSError, p.add_subsystem, 'testnqn')
# now set trtype to loop and other attrs and enable
p.set_attr('addr', 'trtype', 'loop')
p.set_attr('addr', 'traddr', '192.168.0.1')
p.set_attr('addr', 'treq', 'not required')
p.set_attr('addr', 'trsvcid', '1023')
- p.set_enable(1)
- self.assertTrue(p.get_enable())
+ p.add_subsystem('testnqn')
- # test double enable
- p.set_enable(1)
+ # test double add
+ self.assertRaises(nvme.CFSError, p.add_subsystem, 'testnqn')
# test that we can't write to attrs while enabled
self.assertRaises(nvme.CFSError, p.set_attr, 'addr', 'trtype',
self.assertRaises(nvme.CFSError, p.set_attr, 'addr', 'trsvcid',
'21')
- # disable: once and twice
- p.set_enable(0)
- p.set_enable(0)
+ # remove: once and twice
+ p.remove_subsystem('testnqn')
+ self.assertRaises(nvme.CFSError, p.remove_subsystem, 'testnqn')
# check that the attrs haven't been tampered with
self.assertEqual(p.get_attr('addr', 'trtype'), 'loop')
self.assertEqual(p.get_attr('addr', 'treq'), 'not required')
self.assertEqual(p.get_attr('addr', 'trsvcid'), '1023')
- # enable again, and remove while enabled
- p.set_enable(1)
+ # add again, and try to remove while enabled
+ p.add_subsystem('testnqn')
p.delete()
def test_host(self):
p.set_attr('addr', 'traddr', '192.168.0.1')
p.set_attr('addr', 'treq', 'not required')
p.set_attr('addr', 'trsvcid', '1023')
- p.set_enable(1)
+ p.add_subsystem('testnqn')
# save, clear, and restore
root.save_to_file('test.json')
self.assertEqual(p.get_attr('addr', 'traddr'), '192.168.0.1')
self.assertEqual(p.get_attr('addr', 'treq'), 'not required')
self.assertEqual(p.get_attr('addr', 'trsvcid'), '1023')
+ self.assertIn('testnqn', p.subsystems)
+ self.assertNotIn('testtnqn2', p.subsystems)
class UIPortNode(UINode):
def __init__(self, parent, cfnode):
UINode.__init__(self, str(cfnode.portid), parent, cfnode)
+ UIPortSubsystemsNode(self)
def status(self):
if self.cfnode.get_enable():
return "enabled"
return "disabled"
- def ui_command_enable(self):
+
+class UIPortSubsystemsNode(UINode):
+ def __init__(self, parent):
+ UINode.__init__(self, 'subsystems', parent)
+
+ def refresh(self):
+ self._children = set([])
+ for host in self.parent.cfnode.subsystems:
+ UIPortSubsystemNode(self, host)
+
+ def ui_command_create(self, nqn):
'''
- Enables the current Port.
+ Grants access to the subsystem specified by I{nqn} through the
+ parent port.
SEE ALSO
========
- B{disable}
+ B{delete}
'''
- if self.cfnode.get_enable():
- self.shell.log.info("The Port is already enabled.")
+ self.parent.cfnode.add_subsystem(nqn)
+ UIPortSubsystemNode(self, nqn)
+
+ def ui_complete_create(self, parameters, text, current_param):
+ completions = []
+ if current_param == 'nqn':
+ for subsys in self.get_node('/subsystems').children:
+ completions.append(subsys.cfnode.nqn)
+
+ if len(completions) == 1:
+ return [completions[0] + ' ']
else:
- try:
- self.cfnode.set_enable(1)
- self.shell.log.info("The Port has been enabled.")
- except Exception as e:
- raise configshell.ExecutionError(
- "The Port could not be enabled.")
+ return completions
- def ui_command_disable(self):
+ def ui_command_delete(self, nqn):
'''
- Disables the current Port.
+ Removes access to the subsystem specified by I{nqn} through the
+ parent port.
SEE ALSO
========
- B{enable}
+ B{create}
'''
- if not self.cfnode.get_enable():
- self.shell.log.info("The Port is already disabled.")
+ self.parent.cfnode.remove_subsystem(nqn)
+ self.refresh()
+
+ def ui_complete_delete(self, parameters, text, current_param):
+ completions = []
+ if current_param == 'nqn':
+ for nqn in self.parent.cfnode.subsystems:
+ completions.append(nqn)
+
+ if len(completions) == 1:
+ return [completions[0] + ' ']
else:
- try:
- self.cfnode.set_enable(0)
- self.shell.log.info("The Port has been disabled.")
- except Exception as e:
- raise configshell.ExecutionError(
- "The Port could not be disabled.")
+ return completions
+
+
+class UIPortSubsystemNode(UINode):
+ def __init__(self, parent, nqn):
+ UINode.__init__(self, nqn, parent)
class UIHostsNode(UINode):