Skip to content

Commit

Permalink
Add new NVMe grain to display storage initiator
Browse files Browse the repository at this point in the history
  • Loading branch information
sdodsley committed Jan 7, 2019
1 parent 4527bac commit b629739
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 0 deletions.
14 changes: 14 additions & 0 deletions doc/ref/configuration/minion.rst
Expand Up @@ -929,6 +929,20 @@ minion. Since this grain is expensive, it is disabled by default.
iscsi_grains: True
.. conf_minion:: nvme_grains

``nvme_grains``
------------------------

Default: ``False``

The ``nvme_grains`` setting will enable the ``nvme_nqn`` grain on the
minion. Since this grain is expensive, it is disabled by default.

.. code-block:: yaml
nvme_grains: True
.. conf_minion:: mine_enabled

``mine_enabled``
Expand Down
64 changes: 64 additions & 0 deletions salt/grains/nvme.py
@@ -0,0 +1,64 @@
# -*- coding: utf-8 -*-
'''
Grains for NVMe Qualified Names (NQN).
.. versionadded:: Flourine
To enable these grains set `nvme_grains: True`.
.. code-block:: yaml
nvme_grains: True
'''
# Import Python libs
from __future__ import absolute_import, print_function, unicode_literals

import errno
import logging

# Import Salt libs
import salt.utils.files
import salt.utils.path
import salt.utils.platform

__virtualname__ = 'nvme'

# Get logging started
log = logging.getLogger(__name__)


def __virtual__():
if __opts__.get('nvme_grains', False) is False:
return False
return __virtualname__


def nvme_nqn():
'''
Return NVMe NQN
'''
grains = {}
grains['nvme_nqn'] = False
if salt.utils.platform.is_linux():
grains['nvme_nqn'] = _linux_nqn()
return grains


def _linux_nqn():
'''
Return NVMe NQN from a Linux host.
'''
ret = []

initiator = '/etc/nvme/hostnqn'
try:
with salt.utils.files.fopen(initiator, 'r') as _nvme:
for line in _nvme:
line = line.strip()
if line.startswith('nqn.'):
ret.append(line)
except IOError as ex:
if ex.errno != errno.ENOENT:
log.debug("Error while accessing '%s': %s", initiator, ex)

return ret
67 changes: 67 additions & 0 deletions tests/unit/grains/test_nvme.py
@@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-
'''
:codeauthor: :email:`Simon Dodsley <simon@purestorage.com>`
'''
# Import Python libs
from __future__ import absolute_import, print_function, unicode_literals
import errno
import textwrap

# Import Salt Testing Libs
from tests.support.unit import TestCase, skipIf
from tests.support.mock import (
patch,
mock_open,
MagicMock,
NO_MOCK,
NO_MOCK_REASON
)

# Import Salt Libs
import salt.grains.nvme as nvme


@skipIf(NO_MOCK, NO_MOCK_REASON)
class NvmeGrainsTestCase(TestCase):
'''
Test cases for nvme grains
'''

def test_linux_nvme_nqn_grains(self):
_nvme_file = textwrap.dedent('''\
nqn.2014-08.org.nvmexpress:fc_lif:uuid:2cd61a74-17f9-4c22-b350-3020020c458d
''')

with patch('salt.utils.files.fopen', mock_open(read_data=_nvme_file)):
nqn = nvme._linux_nqn()

assert isinstance(nqn, list)
assert len(nqn) == 1
assert nqn == ['nqn.2014-08.org.nvmexpress:fc_lif:uuid:2cd61a74-17f9-4c22-b350-3020020c458d']

@patch('salt.utils.files.fopen', MagicMock(side_effect=IOError(errno.EPERM,
'The cables are not the same length.')))
@patch('salt.grains.nvme.log', MagicMock())
def test_linux_nqn_non_root(self):
'''
Test if linux_nqn is running on salt-master as non-root
and handling access denial properly.
:return:
'''
assert nvme._linux_nqn() == []
nvme.log.debug.assert_called()
assert 'Error while accessing' in nvme.log.debug.call_args[0][0]
assert 'cables are not the same' in nvme.log.debug.call_args[0][2].strerror
assert nvme.log.debug.call_args[0][2].errno == errno.EPERM
assert nvme.log.debug.call_args[0][1] == '/etc/nvme/hostnqn'

@patch('salt.utils.files.fopen', MagicMock(side_effect=IOError(errno.ENOENT, '')))
@patch('salt.grains.nvme.log', MagicMock())
def test_linux_nqn_no_nvme_initiator(self):
'''
Test if linux_nqn is running on salt-master as root.
nvme initiator is not there accessible or is not supported.
:return:
'''
assert nvme._linux_nqn() == []
nvme.log.debug.assert_not_called()

0 comments on commit b629739

Please sign in to comment.