Convert ext filesystem resizes to privsep.
This patch introduces the first code in the privsep directory which _does_not_ run with escalated premissions. This is a requirement because the privsep code has a restricted python path when executing. This pattern will be used for other methods which are only sometimes escalated. Change-Id: Ie09e40d6476dcabda2d599e96701d419e3e8bdf0 blueprint: hurrah-for-privsep
This commit is contained in:
parent
3cec0cb584
commit
cc33bdb239
|
@ -18,10 +18,14 @@ Helpers for filesystem related routines.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from oslo_concurrency import processutils
|
from oslo_concurrency import processutils
|
||||||
|
from oslo_log import log as logging
|
||||||
|
|
||||||
import nova.privsep
|
import nova.privsep
|
||||||
|
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@nova.privsep.sys_admin_pctxt.entrypoint
|
@nova.privsep.sys_admin_pctxt.entrypoint
|
||||||
def mount(fstype, device, mountpoint, options):
|
def mount(fstype, device, mountpoint, options):
|
||||||
mount_cmd = ['mount']
|
mount_cmd = ['mount']
|
||||||
|
@ -123,3 +127,24 @@ def remove_device_maps(device):
|
||||||
def get_filesystem_type(device):
|
def get_filesystem_type(device):
|
||||||
return processutils.execute('blkid', '-o', 'value', '-s', 'TYPE', device,
|
return processutils.execute('blkid', '-o', 'value', '-s', 'TYPE', device,
|
||||||
check_exit_code=[0, 2])
|
check_exit_code=[0, 2])
|
||||||
|
|
||||||
|
|
||||||
|
@nova.privsep.sys_admin_pctxt.entrypoint
|
||||||
|
def resize2fs(image, check_exit_code):
|
||||||
|
unprivileged_resize2fs(image, check_exit_code)
|
||||||
|
|
||||||
|
|
||||||
|
# NOTE(mikal): this method is deliberately not wrapped in a privsep entrypoint
|
||||||
|
def unprivileged_resize2fs(image, check_exit_code):
|
||||||
|
try:
|
||||||
|
processutils.execute('e2fsck',
|
||||||
|
'-fp',
|
||||||
|
image,
|
||||||
|
check_exit_code=[0, 1, 2])
|
||||||
|
except processutils.ProcessExecutionError as exc:
|
||||||
|
LOG.debug("Checking the file system with e2fsck has failed, "
|
||||||
|
"the resize will be aborted. (%s)", exc)
|
||||||
|
else:
|
||||||
|
processutils.execute('resize2fs',
|
||||||
|
image,
|
||||||
|
check_exit_code=check_exit_code)
|
||||||
|
|
|
@ -59,7 +59,7 @@ class APITestCase(test.NoDBTestCase):
|
||||||
self.assertTrue(api.is_image_extendable(image))
|
self.assertTrue(api.is_image_extendable(image))
|
||||||
mock_exec.assert_called_once_with('e2label', imgfile)
|
mock_exec.assert_called_once_with('e2label', imgfile)
|
||||||
|
|
||||||
@mock.patch.object(utils, 'execute', autospec=True)
|
@mock.patch('oslo_concurrency.processutils.execute', autospec=True)
|
||||||
def test_resize2fs_success(self, mock_exec):
|
def test_resize2fs_success(self, mock_exec):
|
||||||
imgfile = tempfile.NamedTemporaryFile()
|
imgfile = tempfile.NamedTemporaryFile()
|
||||||
self.addCleanup(imgfile.close)
|
self.addCleanup(imgfile.close)
|
||||||
|
@ -70,16 +70,24 @@ class APITestCase(test.NoDBTestCase):
|
||||||
[mock.call('e2fsck',
|
[mock.call('e2fsck',
|
||||||
'-fp',
|
'-fp',
|
||||||
imgfile,
|
imgfile,
|
||||||
check_exit_code=[0, 1, 2],
|
check_exit_code=[0, 1, 2]),
|
||||||
run_as_root=False),
|
|
||||||
mock.call('resize2fs',
|
mock.call('resize2fs',
|
||||||
imgfile,
|
imgfile,
|
||||||
check_exit_code=False,
|
check_exit_code=False)])
|
||||||
run_as_root=False)])
|
|
||||||
|
|
||||||
@mock.patch.object(utils, 'execute', autospec=True,
|
@mock.patch('oslo_concurrency.processutils.execute')
|
||||||
side_effect=processutils.ProcessExecutionError(
|
@mock.patch('nova.privsep.fs.resize2fs')
|
||||||
"fs error"))
|
def test_resize2fs_success_as_root(self, mock_resize, mock_exec):
|
||||||
|
imgfile = tempfile.NamedTemporaryFile()
|
||||||
|
self.addCleanup(imgfile.close)
|
||||||
|
|
||||||
|
api.resize2fs(imgfile, run_as_root=True)
|
||||||
|
|
||||||
|
mock_exec.assert_not_called()
|
||||||
|
mock_resize.assert_called()
|
||||||
|
|
||||||
|
@mock.patch('oslo_concurrency.processutils.execute', autospec=True,
|
||||||
|
side_effect=processutils.ProcessExecutionError("fs error"))
|
||||||
def test_resize2fs_e2fsck_fails(self, mock_exec):
|
def test_resize2fs_e2fsck_fails(self, mock_exec):
|
||||||
imgfile = tempfile.NamedTemporaryFile()
|
imgfile = tempfile.NamedTemporaryFile()
|
||||||
self.addCleanup(imgfile.close)
|
self.addCleanup(imgfile.close)
|
||||||
|
@ -88,8 +96,7 @@ class APITestCase(test.NoDBTestCase):
|
||||||
mock_exec.assert_called_once_with('e2fsck',
|
mock_exec.assert_called_once_with('e2fsck',
|
||||||
'-fp',
|
'-fp',
|
||||||
imgfile,
|
imgfile,
|
||||||
check_exit_code=[0, 1, 2],
|
check_exit_code=[0, 1, 2])
|
||||||
run_as_root=False)
|
|
||||||
|
|
||||||
@mock.patch.object(api, 'can_resize_image', autospec=True,
|
@mock.patch.object(api, 'can_resize_image', autospec=True,
|
||||||
return_value=True)
|
return_value=True)
|
||||||
|
|
|
@ -121,20 +121,10 @@ def mkfs(os_type, fs_label, target, run_as_root=True, specified_fs=None):
|
||||||
|
|
||||||
|
|
||||||
def resize2fs(image, check_exit_code=False, run_as_root=False):
|
def resize2fs(image, check_exit_code=False, run_as_root=False):
|
||||||
try:
|
if run_as_root:
|
||||||
utils.execute('e2fsck',
|
nova.privsep.fs.resize2fs(image, check_exit_code)
|
||||||
'-fp',
|
|
||||||
image,
|
|
||||||
check_exit_code=[0, 1, 2],
|
|
||||||
run_as_root=run_as_root)
|
|
||||||
except processutils.ProcessExecutionError as exc:
|
|
||||||
LOG.debug("Checking the file system with e2fsck has failed, "
|
|
||||||
"the resize will be aborted. (%s)", exc)
|
|
||||||
else:
|
else:
|
||||||
utils.execute('resize2fs',
|
nova.privsep.fs.unprivileged_resize2fs(image, check_exit_code)
|
||||||
image,
|
|
||||||
check_exit_code=check_exit_code,
|
|
||||||
run_as_root=run_as_root)
|
|
||||||
|
|
||||||
|
|
||||||
def get_disk_size(path):
|
def get_disk_size(path):
|
||||||
|
|
Loading…
Reference in New Issue