Merge "Move lvm handling to privsep."

This commit is contained in:
Zuul 2017-10-20 16:44:25 +00:00 committed by Gerrit Code Review
commit 9058ed951f
5 changed files with 78 additions and 64 deletions

View File

@ -152,18 +152,6 @@ mkfs.ext3: CommandFilter, mkfs.ext3, root
mkfs.ext4: CommandFilter, mkfs.ext4, root
mkfs.ntfs: CommandFilter, mkfs.ntfs, root
# nova/virt/libvirt/driver.py:
lvremove: CommandFilter, lvremove, root
# nova/virt/libvirt/utils.py:
lvcreate: CommandFilter, lvcreate, root
# nova/virt/libvirt/utils.py:
lvs: CommandFilter, lvs, root
# nova/virt/libvirt/utils.py:
vgs: CommandFilter, vgs, root
# os-brick needed commands
read_initiator: ReadFileFilter, /etc/iscsi/initiatorname.iscsi
multipath: CommandFilter, multipath, root

View File

@ -36,3 +36,43 @@ def mount(fstype, device, mountpoint, options):
@nova.privsep.sys_admin_pctxt.entrypoint
def umount(mountpoint):
processutils.execute('umount', mountpoint, attempts=3, delay_on_retry=True)
@nova.privsep.sys_admin_pctxt.entrypoint
def lvcreate(size, lv, vg, preallocated=None):
cmd = ['lvcreate']
if not preallocated:
cmd.extend(['-L', '%db' % size])
else:
cmd.extend(['-L', '%db' % preallocated,
'--virtualsize', '%db' % size])
cmd.extend(['-n', lv, vg])
processutils.execute(*cmd, attempts=3)
@nova.privsep.sys_admin_pctxt.entrypoint
def vginfo(vg):
return processutils.execute('vgs', '--noheadings', '--nosuffix',
'--separator', '|', '--units', 'b',
'-o', 'vg_size,vg_free', vg)
@nova.privsep.sys_admin_pctxt.entrypoint
def lvlist(vg):
return processutils.execute('lvs', '--noheadings', '-o', 'lv_name', vg)
@nova.privsep.sys_admin_pctxt.entrypoint
def lvinfo(path):
return processutils.execute('lvs', '-o', 'vg_all,lv_all',
'--separator', '|', path)
@nova.privsep.sys_admin_pctxt.entrypoint
def lvremove(path):
processutils.execute('lvremove', '-f', path, attempts=3)
@nova.privsep.sys_admin_pctxt.entrypoint
def blockdev_size(path):
return processutils.execute('blockdev', '--getsize64', path)

View File

@ -19,44 +19,40 @@ from oslo_config import cfg
from nova import exception
from nova import test
from nova import utils
from nova.virt.libvirt.storage import lvm
CONF = cfg.CONF
class LvmTestCase(test.NoDBTestCase):
@mock.patch('nova.utils.execute')
def test_get_volume_size(self, mock_execute):
mock_execute.return_value = 123456789, None
@mock.patch('nova.privsep.fs.blockdev_size')
def test_get_volume_size(self, mock_blockdev_size):
mock_blockdev_size.return_value = '123456789', None
size = lvm.get_volume_size('/dev/foo')
mock_execute.assert_has_calls(
[mock.call('blockdev', '--getsize64', '/dev/foo',
run_as_root=True)])
self.assertEqual(123456789, size)
@mock.patch.object(utils, 'execute',
side_effect=processutils.ProcessExecutionError(
stderr=('blockdev: cannot open /dev/foo: '
'No such device or address')))
def test_get_volume_size_not_found(self, mock_execute):
@mock.patch('nova.privsep.fs.blockdev_size',
side_effect=processutils.ProcessExecutionError(
stderr=('blockdev: cannot open /dev/foo: '
'No such device or address')))
def test_get_volume_size_not_found(self, mock_blockdev_size):
self.assertRaises(exception.VolumeBDMPathNotFound,
lvm.get_volume_size, '/dev/foo')
@mock.patch.object(utils, 'execute',
side_effect=processutils.ProcessExecutionError(
stderr=('blockdev: cannot open /dev/foo: '
'No such file or directory')))
def test_get_volume_size_not_found_file(self, mock_execute):
@mock.patch('nova.privsep.fs.blockdev_size',
side_effect=processutils.ProcessExecutionError(
stderr=('blockdev: cannot open /dev/foo: '
'No such file or directory')))
def test_get_volume_size_not_found_file(self, mock_blockdev_size):
self.assertRaises(exception.VolumeBDMPathNotFound,
lvm.get_volume_size, '/dev/foo')
@mock.patch('os.path.exists', return_value=True)
@mock.patch.object(utils, 'execute',
side_effect=processutils.ProcessExecutionError(
stderr='blockdev: i am sad in other ways'))
def test_get_volume_size_unexpectd_error(self, mock_execute,
mock_path_exists):
@mock.patch('nova.privsep.fs.blockdev_size',
side_effect=processutils.ProcessExecutionError(
stderr='blockdev: i am sad in other ways'))
def test_get_volume_size_unexpected_error(self, mock_blockdev_size,
mock_path_exists):
self.assertRaises(processutils.ProcessExecutionError,
lvm.get_volume_size, '/dev/foo')
@ -117,18 +113,18 @@ class LvmTestCase(test.NoDBTestCase):
lvm.clear_volume('/dev/vc')
mock_execute.assert_not_called()
@mock.patch.object(utils, 'execute',
side_effect=processutils.ProcessExecutionError(
stderr=('blockdev: cannot open /dev/foo: '
'No such file or directory')))
def test_lvm_clear_ignore_lvm_not_found(self, mock_execute):
@mock.patch('nova.privsep.fs.blockdev_size',
side_effect=processutils.ProcessExecutionError(
stderr=('blockdev: cannot open /dev/foo: '
'No such file or directory')))
def test_lvm_clear_ignore_lvm_not_found(self, mock_blockdev_size):
lvm.clear_volume('/dev/foo')
@mock.patch.object(lvm, 'clear_volume')
@mock.patch.object(utils, 'execute',
side_effect=processutils.ProcessExecutionError('Error'))
def test_fail_remove_all_logical_volumes(self, mock_clear, mock_execute):
@mock.patch('nova.privsep.fs.lvremove',
side_effect=processutils.ProcessExecutionError('Error'))
def test_fail_remove_all_logical_volumes(self, mock_clear, mock_lvremove):
self.assertRaises(exception.VolumesNotRemoved,
lvm.remove_volumes,
['vol1', 'vol2', 'vol3'])
self.assertEqual(3, mock_execute.call_count)
self.assertEqual(3, mock_lvremove.call_count)

View File

@ -29,6 +29,7 @@ import six
import nova.conf
from nova import exception
from nova.i18n import _
import nova.privsep.fs
from nova import utils
CONF = nova.conf.CONF
@ -72,13 +73,11 @@ def create_volume(vg, lv, size, sparse=False):
'free_space': free_space,
'size': size,
'lv': lv})
cmd = ('lvcreate', '-L', '%db' % preallocated_space,
'--virtualsize', '%db' % size, '-n', lv, vg)
nova.privsep.fs.lvcreate(size, lv, vg,
preallocated=preallocated_space)
else:
check_size(vg, lv, size)
cmd = ('lvcreate', '-L', '%db' % size, '-n', lv, vg)
utils.execute(*cmd, run_as_root=True, attempts=3)
nova.privsep.fs.lvcreate(size, lv, vg)
def get_volume_group_info(vg):
@ -91,10 +90,7 @@ def get_volume_group_info(vg):
:used: How much space is used (in bytes)
"""
out, err = utils.execute('vgs', '--noheadings', '--nosuffix',
'--separator', '|',
'--units', 'b', '-o', 'vg_size,vg_free', vg,
run_as_root=True)
out, err = nova.privsep.fs.vginfo(vg)
info = out.split('|')
if len(info) != 2:
@ -113,9 +109,7 @@ def list_volumes(vg):
: Data format example
: ['volume-aaa', 'volume-bbb', 'volume-ccc']
"""
out, err = utils.execute('lvs', '--noheadings', '-o', 'lv_name', vg,
run_as_root=True)
out, err = nova.privsep.fs.lvlist(vg)
return [line.strip() for line in out.splitlines()]
@ -135,9 +129,7 @@ def volume_info(path):
: ...
: 'LSize': '1.00g', '#PV': '1', '#VMdaCps': 'unmanaged'}
"""
out, err = utils.execute('lvs', '-o', 'vg_all,lv_all',
'--separator', '|', path, run_as_root=True)
out, err = nova.privsep.fs.lvinfo(path)
info = [line.split('|') for line in out.splitlines()]
if len(info) != 2:
@ -155,8 +147,7 @@ def get_volume_size(path):
:raises: exception.VolumeBDMPathNotFound if the volume path does not exist.
"""
try:
out, _err = utils.execute('blockdev', '--getsize64', path,
run_as_root=True)
out, _err = nova.privsep.fs.blockdev_size(path)
except processutils.ProcessExecutionError:
if not os.path.exists(path):
raise exception.VolumeBDMPathNotFound(path=path)
@ -201,9 +192,8 @@ def remove_volumes(paths):
errors = []
for path in paths:
clear_volume(path)
lvremove = ('lvremove', '-f', path)
try:
utils.execute(*lvremove, attempts=3, run_as_root=True)
nova.privsep.fs.lvremove(path)
except processutils.ProcessExecutionError as exp:
errors.append(six.text_type(exp))
if errors:

View File

@ -7,5 +7,5 @@ upgrade:
Calls to mount in the virt disk api no longer ignore the value of stderr.
- |
The following commands are no longer required to be listed in your rootwrap
configuration: cat; chown; cryptsetup; dd; mkdir; mount; ploop;
prl_disk_tool; readlink; tee; touch; and umount.
configuration: cat; chown; cryptsetup; dd; lvcreate; lvremove; lvs; mkdir;
mount; ploop; prl_disk_tool; readlink; tee; touch; umount; and vgs.