NVMe-oF: Get system uuid in privsep
Move the _get_system_uuid method from the NVMeOFConnector connector to os_brick/privsep/nvmeof.py renaming it to get_system_uuid and running it as privileged. This allows us to read sys/class/dmi/id/product_uuid file in Python instead of running a subprocess to execute cat. It also allows the connector to have one less privsep calls if the file doesn't exist, because it can execute the dmidecode command directly without making another request to the privsep daemon. Change-Id: I8f2edef6fda97af0ff3f92e39c8b24a85b6c3402
This commit is contained in:
parent
b41b3c8814
commit
da4561165d
|
@ -34,6 +34,7 @@ try:
|
|||
from os_brick.initiator.connectors import nvmeof_agent
|
||||
except ImportError:
|
||||
nvmeof_agent = None
|
||||
from os_brick.privileged import nvmeof as priv_nvmeof
|
||||
from os_brick.privileged import rootwrap as priv_rootwrap
|
||||
from os_brick import utils
|
||||
|
||||
|
@ -767,7 +768,7 @@ class NVMeOFConnector(base.BaseLinuxConnector):
|
|||
|
||||
nqn = None
|
||||
uuid = nvmf._get_host_uuid()
|
||||
suuid = nvmf._get_system_uuid()
|
||||
suuid = priv_nvmeof.get_system_uuid()
|
||||
if cls.nvme_present():
|
||||
nqn = utils.get_host_nqn()
|
||||
if uuid:
|
||||
|
@ -795,31 +796,6 @@ class NVMeOFConnector(base.BaseLinuxConnector):
|
|||
"Process execution error in _get_host_uuid: %s", e)
|
||||
return None
|
||||
|
||||
def _get_system_uuid(self) -> str:
|
||||
"""Get the system's UUID from DMI
|
||||
|
||||
First try reading it from sysfs and if not possible use the dmidecode
|
||||
tool.
|
||||
"""
|
||||
# RSD requires system_uuid to let Cinder RSD Driver identify
|
||||
# Nova node for later RSD volume attachment.
|
||||
try:
|
||||
out, err = self._execute('cat', '/sys/class/dmi/id/product_uuid',
|
||||
root_helper=self._root_helper,
|
||||
run_as_root=True)
|
||||
except putils.ProcessExecutionError:
|
||||
try:
|
||||
out, err = self._execute('dmidecode', '-ssystem-uuid',
|
||||
root_helper=self._root_helper,
|
||||
run_as_root=True)
|
||||
if not out:
|
||||
LOG.warning('dmidecode returned empty system-uuid')
|
||||
except putils.ProcessExecutionError as e:
|
||||
LOG.debug("Unable to locate dmidecode. For Cinder RSD Backend,"
|
||||
" please make sure it is installed: %s", e)
|
||||
out = ""
|
||||
return out.strip()
|
||||
|
||||
@classmethod
|
||||
def _set_native_multipath_supported(cls):
|
||||
if cls.native_multipath_supported is None:
|
||||
|
|
|
@ -71,3 +71,25 @@ def create_hostnqn():
|
|||
LOG.warning("Could not generate host nqn: %s", e)
|
||||
|
||||
return host_nqn
|
||||
|
||||
|
||||
@os_brick.privileged.default.entrypoint
|
||||
def get_system_uuid() -> str:
|
||||
# RSD requires system_uuid to let Cinder RSD Driver identify
|
||||
# Nova node for later RSD volume attachment.
|
||||
try:
|
||||
with open('/sys/class/dmi/id/product_uuid', 'r') as f:
|
||||
return f.read().strip()
|
||||
except Exception:
|
||||
LOG.debug("Could not read dmi's 'product_uuid' on sysfs")
|
||||
|
||||
try:
|
||||
out, err = rootwrap.custom_execute('dmidecode', '-ssystem-uuid')
|
||||
if not out:
|
||||
LOG.warning('dmidecode returned empty system-uuid')
|
||||
except putils.ProcessExecutionError as e:
|
||||
LOG.debug("Unable to locate dmidecode. For Cinder RSD Backend,"
|
||||
" please make sure it is installed: %s", e)
|
||||
out = ""
|
||||
|
||||
return out.strip()
|
||||
|
|
|
@ -21,6 +21,7 @@ from oslo_concurrency import processutils as putils
|
|||
from os_brick import exception
|
||||
from os_brick import executor
|
||||
from os_brick.initiator.connectors import nvmeof
|
||||
from os_brick.privileged import nvmeof as priv_nvmeof
|
||||
from os_brick.privileged import rootwrap as priv_rootwrap
|
||||
from os_brick.tests import base as test_base
|
||||
from os_brick.tests.initiator import test_connector
|
||||
|
@ -920,7 +921,7 @@ class NVMeOFConnectorTestCase(test_connector.ConnectorTestCase):
|
|||
return_value=True)
|
||||
@mock.patch.object(utils, 'get_host_nqn',
|
||||
return_value='fakenqn')
|
||||
@mock.patch.object(nvmeof.NVMeOFConnector, '_get_system_uuid',
|
||||
@mock.patch.object(priv_nvmeof, 'get_system_uuid',
|
||||
return_value=None)
|
||||
@mock.patch.object(nvmeof.NVMeOFConnector, '_get_host_uuid',
|
||||
return_value=None)
|
||||
|
@ -937,7 +938,7 @@ class NVMeOFConnectorTestCase(test_connector.ConnectorTestCase):
|
|||
return_value=True)
|
||||
@mock.patch.object(nvmeof.NVMeOFConnector, 'nvme_present')
|
||||
@mock.patch.object(utils, 'get_host_nqn', autospec=True)
|
||||
@mock.patch.object(nvmeof.NVMeOFConnector, '_get_system_uuid',
|
||||
@mock.patch.object(priv_nvmeof, 'get_system_uuid',
|
||||
autospec=True)
|
||||
@mock.patch.object(nvmeof.NVMeOFConnector, '_get_host_uuid', autospec=True)
|
||||
def test_get_connector_properties_with_sysuuid(self, mock_host_uuid,
|
||||
|
|
|
@ -26,6 +26,7 @@ from os_brick.initiator.connectors import fake
|
|||
from os_brick.initiator.connectors import iscsi
|
||||
from os_brick.initiator.connectors import nvmeof
|
||||
from os_brick.initiator import linuxfc
|
||||
from os_brick.privileged import nvmeof as priv_nvmeof
|
||||
from os_brick.privileged import rootwrap as priv_rootwrap
|
||||
from os_brick.tests import base as test_base
|
||||
from os_brick import utils
|
||||
|
@ -45,7 +46,7 @@ class ConnectorUtilsTestCase(test_base.TestCase):
|
|||
@mock.patch.object(nvmeof.NVMeOFConnector,
|
||||
'_is_native_multipath_supported',
|
||||
return_value=False)
|
||||
@mock.patch.object(nvmeof.NVMeOFConnector, '_get_system_uuid',
|
||||
@mock.patch.object(priv_nvmeof, 'get_system_uuid',
|
||||
return_value=None)
|
||||
@mock.patch.object(nvmeof.NVMeOFConnector, '_get_host_uuid',
|
||||
return_value=None)
|
||||
|
|
|
@ -125,3 +125,44 @@ class PrivNVMeTestCase(base.TestCase):
|
|||
exist_ok=True)
|
||||
mock_exec.assert_called_once_with('nvme', 'show-hostnqn')
|
||||
self.assertEqual('', res)
|
||||
|
||||
@mock.patch.object(builtins, 'open', new_callable=mock.mock_open)
|
||||
def test_get_system_uuid_product_uuid(self, mock_open):
|
||||
uuid = 'dbc6ba60-36ae-4b96-9310-628832bdfc3d'
|
||||
mock_fd = mock_open.return_value.__enter__.return_value
|
||||
mock_fd.read.return_value = uuid
|
||||
res = privsep_nvme.get_system_uuid()
|
||||
self.assertEqual(uuid, res)
|
||||
mock_open.assert_called_once_with('/sys/class/dmi/id/product_uuid',
|
||||
'r')
|
||||
mock_fd.read.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(builtins, 'open', side_effect=Exception)
|
||||
@mock.patch.object(rootwrap, 'custom_execute')
|
||||
def test_get_system_uuid_dmidecode(self, mock_exec, mock_open):
|
||||
uuid = 'dbc6ba60-36ae-4b96-9310-628832bdfc3d'
|
||||
mock_exec.return_value = (f' {uuid} ', '')
|
||||
res = privsep_nvme.get_system_uuid()
|
||||
self.assertEqual(uuid, res)
|
||||
mock_open.assert_called_once_with('/sys/class/dmi/id/product_uuid',
|
||||
'r')
|
||||
mock_exec.assert_called_once_with('dmidecode', '-ssystem-uuid')
|
||||
|
||||
@mock.patch.object(builtins, 'open', side_effect=Exception)
|
||||
@mock.patch.object(rootwrap, 'custom_execute', return_value=('', ''))
|
||||
def test_get_system_uuid_dmidecode_empty(self, mock_exec, mock_open):
|
||||
res = privsep_nvme.get_system_uuid()
|
||||
self.assertEqual('', res)
|
||||
mock_open.assert_called_once_with('/sys/class/dmi/id/product_uuid',
|
||||
'r')
|
||||
mock_exec.assert_called_once_with('dmidecode', '-ssystem-uuid')
|
||||
|
||||
@mock.patch.object(builtins, 'open', side_effect=Exception)
|
||||
@mock.patch.object(rootwrap, 'custom_execute',
|
||||
side_effect=putils.ProcessExecutionError)
|
||||
def test_get_system_uuid_failure(self, mock_exec, mock_open):
|
||||
res = privsep_nvme.get_system_uuid()
|
||||
self.assertEqual('', res)
|
||||
mock_open.assert_called_once_with('/sys/class/dmi/id/product_uuid',
|
||||
'r')
|
||||
mock_exec.assert_called_once_with('dmidecode', '-ssystem-uuid')
|
||||
|
|
Loading…
Reference in New Issue