diff --git a/nova/privsep/fs.py b/nova/privsep/fs.py index 459e9e8cedde..4707598c7e60 100644 --- a/nova/privsep/fs.py +++ b/nova/privsep/fs.py @@ -153,3 +153,45 @@ def unprivileged_resize2fs(image, check_exit_code): processutils.execute('resize2fs', image, check_exit_code=check_exit_code) + + +@nova.privsep.sys_admin_pctxt.entrypoint +def create_partition_table(device, style, check_exit_code=True): + processutils.execute('parted', '--script', device, 'mklabel', style, + check_exit_code=check_exit_code) + + +@nova.privsep.sys_admin_pctxt.entrypoint +def create_partition(device, style, start, end, check_exit_code=True): + processutils.execute('parted', '--script', device, '--', + 'mkpart', style, start, end, + check_exit_code=check_exit_code) + + +@nova.privsep.sys_admin_pctxt.entrypoint +def list_partitions(device): + return unprivileged_list_partitions(device) + + +# NOTE(mikal): this method is deliberately not wrapped in a privsep entrypoint +def unprivileged_list_partitions(device): + """Return partition information (num, size, type) for a device.""" + + out, _err = processutils.execute('parted', '--script', '--machine', + device, 'unit s', 'print') + lines = [line for line in out.split('\n') if line] + partitions = [] + + LOG.debug('Partitions:') + for line in lines[2:]: + line = line.rstrip(';') + num, start, end, size, fstype, name, flags = line.split(':') + num = int(num) + start = int(start.rstrip('s')) + end = int(end.rstrip('s')) + size = int(size.rstrip('s')) + LOG.debug(' %(num)s: %(fstype)s %(size)d sectors', + {'num': num, 'fstype': fstype, 'size': size}) + partitions.append((num, start, size, fstype, name, flags)) + + return partitions diff --git a/nova/tests/unit/privsep/test_fs.py b/nova/tests/unit/privsep/test_fs.py new file mode 100644 index 000000000000..babcbe5f292d --- /dev/null +++ b/nova/tests/unit/privsep/test_fs.py @@ -0,0 +1,34 @@ +# Copyright 2013 OpenStack Foundation +# All Rights Reserved. +# +# 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 mock + +import nova.privsep.fs +from nova import test + + +class PrivsepFilesystemHelpersTestCase(test.NoDBTestCase): + @mock.patch('oslo_concurrency.processutils.execute') + def test_list_partitions(self, mock_execute): + parted_return = "BYT;\n...\n" + parted_return += "1:2s:11s:10s:ext3::boot;\n" + parted_return += "2:20s:11s:10s::bob:;\n" + mock_execute.return_value = (parted_return, None) + + partitions = nova.privsep.fs.unprivileged_list_partitions("abc") + + self.assertEqual(2, len(partitions)) + self.assertEqual((1, 2, 10, "ext3", "", "boot"), partitions[0]) + self.assertEqual((2, 20, 10, "", "bob", ""), partitions[1]) diff --git a/nova/tests/unit/virt/xenapi/test_vm_utils.py b/nova/tests/unit/virt/xenapi/test_vm_utils.py index 05e356111bca..98cabf64052d 100644 --- a/nova/tests/unit/virt/xenapi/test_vm_utils.py +++ b/nova/tests/unit/virt/xenapi/test_vm_utils.py @@ -451,19 +451,6 @@ class ResizeHelpersTestCase(VMUtilsTestBase): def test_auto_config_disk_returns_early_on_zero_size(self): vm_utils.try_auto_configure_disk("bad_session", "bad_vdi_ref", 0) - @mock.patch.object(utils, "execute") - def test_get_partitions(self, mock_execute): - parted_return = "BYT;\n...\n" - parted_return += "1:2s:11s:10s:ext3::boot;\n" - parted_return += "2:20s:11s:10s::bob:;\n" - mock_execute.return_value = (parted_return, None) - - partitions = vm_utils._get_partitions("abc") - - self.assertEqual(2, len(partitions)) - self.assertEqual((1, 2, 10, "ext3", "", "boot"), partitions[0]) - self.assertEqual((2, 20, 10, "", "bob", ""), partitions[1]) - class CheckVDISizeTestCase(VMUtilsTestBase): def setUp(self): diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index ba8a4f45d569..ae8364fba852 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -973,16 +973,11 @@ def _make_partition(session, dev, partition_start, partition_end): # NOTE(bobball) If this runs in Dom0, parted will error trying # to re-read the partition table and return a generic error - utils.execute('parted', '--script', dev_path, - 'mklabel', 'msdos', run_as_root=True, - check_exit_code=not session.is_local_connection) - - utils.execute('parted', '--script', dev_path, '--', - 'mkpart', 'primary', - partition_start, - partition_end, - run_as_root=True, - check_exit_code=not session.is_local_connection) + nova.privsep.fs.create_partition_table( + dev_path, 'msdos', check_exit_code=not session.is_local_connection) + nova.privsep.fs.create_partition( + dev_path, 'primary', partition_start, partition_end, + check_exit_code=not session.is_local_connection) partition_path = utils.make_dev_path(dev, partition=1) if session.is_local_connection: @@ -2253,27 +2248,7 @@ def _get_this_vm_ref(session): def _get_partitions(dev): - """Return partition information (num, size, type) for a device.""" - dev_path = utils.make_dev_path(dev) - out, _err = utils.execute('parted', '--script', '--machine', - dev_path, 'unit s', 'print', - run_as_root=True) - lines = [line for line in out.split('\n') if line] - partitions = [] - - LOG.debug("Partitions:") - for line in lines[2:]: - line = line.rstrip(';') - num, start, end, size, fstype, name, flags = line.split(':') - num = int(num) - start = int(start.rstrip('s')) - end = int(end.rstrip('s')) - size = int(size.rstrip('s')) - LOG.debug(" %(num)s: %(fstype)s %(size)d sectors", - {'num': num, 'fstype': fstype, 'size': size}) - partitions.append((num, start, size, fstype, name, flags)) - - return partitions + return nova.privsep.fs.list_partitions(utils.make_dev_path(dev)) def _stream_disk(session, image_service_func, image_type, virtual_size, dev):