Add support for processutils.execute
oslo.privsep should be used by default. We should be able to use processutils.execute when os-brick is used outside Nova or Cinder. E.g.: python-brick-cinderclient-ext should be used with sudo or run as root without any helpers like oslo.privsep or oslo.rootwrap. Depends-On: I489193c18ae6603f0bc750c7b63e1dd0b4a71e28 Change-Id: I5a10574cb91794f978eda2aa2e2e65dc92ca56b4
This commit is contained in:
parent
a2d38af095
commit
bce886ea7e
@ -18,20 +18,13 @@
|
|||||||
and root_helper settings, so this provides that hook.
|
and root_helper settings, so this provides that hook.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from oslo_concurrency import processutils as putils
|
|
||||||
|
|
||||||
from os_brick.privileged import rootwrap as priv_rootwrap
|
from os_brick.privileged import rootwrap as priv_rootwrap
|
||||||
|
|
||||||
|
|
||||||
class Executor(object):
|
class Executor(object):
|
||||||
def __init__(self, root_helper, execute=None,
|
def __init__(self, root_helper, execute=None,
|
||||||
*args, **kwargs):
|
*args, **kwargs):
|
||||||
# For backwards compatibility, `putils.execute` is interpreted
|
if execute is None:
|
||||||
# as a sentinel to mean "I want the os-brick default" :-/
|
|
||||||
# This can be burnt as soon as we update all the callsites (in
|
|
||||||
# nova+cinder) to the new default - and then we shall never
|
|
||||||
# speak of it again.
|
|
||||||
if execute is None or execute is putils.execute:
|
|
||||||
execute = priv_rootwrap.execute
|
execute = priv_rootwrap.execute
|
||||||
self.set_execute(execute)
|
self.set_execute(execute)
|
||||||
self.set_root_helper(root_helper)
|
self.set_root_helper(root_helper)
|
||||||
|
@ -108,7 +108,7 @@ connector_list = [
|
|||||||
|
|
||||||
|
|
||||||
def get_connector_properties(root_helper, my_ip, multipath, enforce_multipath,
|
def get_connector_properties(root_helper, my_ip, multipath, enforce_multipath,
|
||||||
host=None):
|
host=None, execute=None):
|
||||||
"""Get the connection properties for all protocols.
|
"""Get the connection properties for all protocols.
|
||||||
|
|
||||||
When the connector wants to use multipath, multipath=True should be
|
When the connector wants to use multipath, multipath=True should be
|
||||||
@ -129,6 +129,8 @@ def get_connector_properties(root_helper, my_ip, multipath, enforce_multipath,
|
|||||||
running? If the daemon isn't running then the
|
running? If the daemon isn't running then the
|
||||||
return dict will have multipath as False.
|
return dict will have multipath as False.
|
||||||
:type enforce_multipath: bool
|
:type enforce_multipath: bool
|
||||||
|
:param host: hostname.
|
||||||
|
:param execute: execute helper.
|
||||||
:returns: dict containing all of the collected initiator values.
|
:returns: dict containing all of the collected initiator values.
|
||||||
"""
|
"""
|
||||||
props = {}
|
props = {}
|
||||||
@ -148,7 +150,8 @@ def get_connector_properties(root_helper, my_ip, multipath, enforce_multipath,
|
|||||||
root_helper,
|
root_helper,
|
||||||
host=host,
|
host=host,
|
||||||
multipath=multipath,
|
multipath=multipath,
|
||||||
enforce_multipath=enforce_multipath))
|
enforce_multipath=enforce_multipath,
|
||||||
|
execute=execute))
|
||||||
|
|
||||||
return props
|
return props
|
||||||
|
|
||||||
@ -445,7 +448,8 @@ class BaseLinuxConnector(InitiatorConnector):
|
|||||||
|
|
||||||
props['multipath'] = (multipath and
|
props['multipath'] = (multipath and
|
||||||
linuxscsi.LinuxSCSI.is_multipath_running(
|
linuxscsi.LinuxSCSI.is_multipath_running(
|
||||||
enforce_multipath, root_helper))
|
enforce_multipath, root_helper,
|
||||||
|
execute=kwargs.get('execute')))
|
||||||
|
|
||||||
return props
|
return props
|
||||||
|
|
||||||
@ -566,7 +570,8 @@ class ISCSIConnector(BaseLinuxConnector):
|
|||||||
def get_connector_properties(root_helper, *args, **kwargs):
|
def get_connector_properties(root_helper, *args, **kwargs):
|
||||||
"""The iSCSI connector properties."""
|
"""The iSCSI connector properties."""
|
||||||
props = {}
|
props = {}
|
||||||
iscsi = ISCSIConnector(root_helper=root_helper)
|
iscsi = ISCSIConnector(root_helper=root_helper,
|
||||||
|
execute=kwargs.get('execute'))
|
||||||
initiator = iscsi.get_initiator()
|
initiator = iscsi.get_initiator()
|
||||||
if initiator:
|
if initiator:
|
||||||
props['initiator'] = initiator
|
props['initiator'] = initiator
|
||||||
@ -1380,7 +1385,8 @@ class FibreChannelConnector(BaseLinuxConnector):
|
|||||||
def get_connector_properties(root_helper, *args, **kwargs):
|
def get_connector_properties(root_helper, *args, **kwargs):
|
||||||
"""The Fibre Channel connector properties."""
|
"""The Fibre Channel connector properties."""
|
||||||
props = {}
|
props = {}
|
||||||
fc = linuxfc.LinuxFibreChannel(root_helper)
|
fc = linuxfc.LinuxFibreChannel(root_helper,
|
||||||
|
execute=kwargs.get('execute'))
|
||||||
|
|
||||||
wwpns = fc.get_fc_wwpns()
|
wwpns = fc.get_fc_wwpns()
|
||||||
if wwpns:
|
if wwpns:
|
||||||
|
@ -113,11 +113,12 @@ class LinuxSCSI(executor.Executor):
|
|||||||
return out.strip()
|
return out.strip()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_multipath_running(enforce_multipath, root_helper):
|
def is_multipath_running(enforce_multipath, root_helper, execute=None):
|
||||||
try:
|
try:
|
||||||
priv_rootwrap.execute('multipathd', 'show', 'status',
|
if execute is None:
|
||||||
run_as_root=True,
|
execute = priv_rootwrap.execute
|
||||||
root_helper=root_helper)
|
execute('multipathd', 'show', 'status',
|
||||||
|
run_as_root=True, root_helper=root_helper)
|
||||||
except putils.ProcessExecutionError as err:
|
except putils.ProcessExecutionError as err:
|
||||||
LOG.error(_LE('multipathd is not running: exit code %(err)s'),
|
LOG.error(_LE('multipathd is not running: exit code %(err)s'),
|
||||||
{'err': err.exit_code})
|
{'err': err.exit_code})
|
||||||
|
@ -657,3 +657,11 @@ loop0 0"""
|
|||||||
result = self.linuxscsi.process_lun_id(lun_id)
|
result = self.linuxscsi.process_lun_id(lun_id)
|
||||||
expected = 13
|
expected = 13
|
||||||
self.assertEqual(expected, result)
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
@mock.patch('os_brick.privileged.rootwrap')
|
||||||
|
def test_is_multipath_running_default_executor(self, mock_rootwrap):
|
||||||
|
self.assertTrue(
|
||||||
|
linuxscsi.LinuxSCSI.is_multipath_running(
|
||||||
|
False, None, mock_rootwrap.execute))
|
||||||
|
mock_rootwrap.execute.assert_called_once_with(
|
||||||
|
'multipathd', 'show', 'status', run_as_root=True, root_helper=None)
|
||||||
|
37
os_brick/tests/test_executor.py
Normal file
37
os_brick/tests/test_executor.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
# import time
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
|
from os_brick import executor as brick_executor
|
||||||
|
from os_brick.privileged import rootwrap
|
||||||
|
from os_brick.tests import base
|
||||||
|
|
||||||
|
|
||||||
|
class TestExecutor(base.TestCase):
|
||||||
|
def test_default_execute(self):
|
||||||
|
executor = brick_executor.Executor(root_helper=None)
|
||||||
|
self.assertEqual(rootwrap.execute, executor._execute)
|
||||||
|
|
||||||
|
def test_none_execute(self):
|
||||||
|
executor = brick_executor.Executor(root_helper=None, execute=None)
|
||||||
|
self.assertEqual(rootwrap.execute, executor._execute)
|
||||||
|
|
||||||
|
def test_fake_execute(self):
|
||||||
|
mock_execute = mock.Mock()
|
||||||
|
executor = brick_executor.Executor(root_helper=None,
|
||||||
|
execute=mock_execute)
|
||||||
|
self.assertEqual(mock_execute, executor._execute)
|
Loading…
Reference in New Issue
Block a user