Move the idmapshift binary into privsep.

I can't see any evidence that anyone else uses our nova-idmapshift
binary, and it adds a lot of complexity (flags we never call for
example). Move the code we do actually use into the privsep
directory and simplify our calls to it. Remove the extra binary
from our install and documentation.

Change-Id: Ibce28d20d166da154833376cf51f1877b829925e
blueprint: hurrah-for-privsep
This commit is contained in:
Michael Still 2017-09-27 06:56:34 +10:00
parent a067f8c646
commit 3f7995f586
10 changed files with 34 additions and 485 deletions

View File

@ -78,7 +78,6 @@ are documented for completeness and debugging if something goes wrong.
:maxdepth: 1
nova-rootwrap
nova-idmapshift
Deprecated Services
-------------------

View File

@ -1,92 +0,0 @@
===============
nova-idmapshift
===============
-----------------------------------------
Tool used by Nova libvirt-lxc virt driver
-----------------------------------------
:Author: openstack@lists.openstack.org
:Date: 2012-09-27
:Copyright: OpenStack Foundation
:Version: 2012.1
:Manual section: 1
:Manual group: cloud computing
SYNOPSIS
========
nova-idmapshift [options] path
DESCRIPTION
===========
nova-idmapshift is a tool that properly sets the ownership of a filesystem for use
with linux user namespaces. This tool can only be used with linux lxc containers.
When using user namespaces with linux lxc containers, the filesystem of the
container must be owned by the targeted user and group ids being applied
to that container. Otherwise, processes inside the container won't be able
to access the filesystem.
For example:
nova-idmapshift -i -u 0:10000:2000 -g 0:10000:2000 path
This command will idempotently shift `path` to proper ownership using
the provided uid and gid mappings.
When using the uid map string '0:10000:2000', this means that
user ids inside the container between 0 and 1999 will map to user ids on
the host between 10000 and 11999. Root (0) becomes 10000, user 1 becomes
10001, user 50 becomes 10050 and user 1999 becomes 11999. This means that
files that are owned by root need to actually be owned by user 10000, and
files owned by 50 need to be owned by 10050, and so on.
nova-idmapshift will take the uid and gid strings used for user namespaces and
properly set up the filesystem for use by those users. Uids and gids outside
of provided ranges will be mapped to nobody-id (default is max uid/gid)
so that they are inaccessible inside the container.
OPTIONS
=======
Positional arguments
~~~~~~~~~~~~~~~~~~~~
path Root path of the filesystem to be shifted
Optional arguments
~~~~~~~~~~~~~~~~~~
-h, --help Show this help message and exit.
-u USER_MAPS, --uid=USER_MAPS
User ID mappings, in the form:
[[guest-uid:host-uid:count],...]
-g GROUP_MAPS, --gid=GROUP_MAPS
Group ID mappings, in the form:
[[guest-gid:host-gid:count],...]
-n nobody-id, --nobody nobody-id
ID to map all unmapped uid and gids to.
Defaults to 65534.
-i, --idempotent Shift operation will only be performed if filesystem appears unshifted.
Defaults to false.
-c, --confirm Will perform check on the filesystem:
Returns 0 when filesystem appears shifted.
Returns 1 when filesystem appears unshifted.
Defaults to false.
-d, --dry-run Print chown operations, but won't perform them.
Defaults to false.
-v, --verbose Print chown operations while performing them.
Defaults to false.
SEE ALSO
========
* `OpenStack Nova <https://docs.openstack.org/nova/latest/>`__
BUGS
====
* Nova bugs are managed at Launchpad `Bugs : Nova <https://bugs.launchpad.net/nova>`__

View File

@ -123,7 +123,6 @@ _man_pages = [
('nova-console', u'Cloud controller fabric'),
('nova-consoleauth', u'Cloud controller fabric'),
('nova-dhcpbridge', u'Cloud controller fabric'),
('nova-idmapshift', u'Cloud controller fabric'),
('nova-manage', u'Cloud controller fabric'),
('nova-network', u'Cloud controller fabric'),
('nova-novncproxy', u'Cloud controller fabric'),

View File

@ -137,9 +137,6 @@ brctl: CommandFilter, brctl, root
# nova/virt/xenapi/vm_utils.py: 'mkswap'
mkswap: CommandFilter, mkswap, root
# nova/virt/libvirt/utils.py: 'nova-idmapshift'
nova-idmapshift: CommandFilter, nova-idmapshift, root
# nova/virt/xenapi/vm_utils.py: 'mkfs'
# nova/utils.py: 'mkfs', fs, path, label
mkfs: CommandFilter, mkfs, root

View File

@ -11,56 +11,12 @@
# 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.
"""
##########
IDMapShift
##########
IDMapShift is a tool that properly sets the ownership of a filesystem for use
with linux user namespaces.
=====
Usage
=====
nova-idmapshift -i -u 0:10000:2000 -g 0:10000:2000 path
This command will idempotently shift `path` to proper ownership using
the provided uid and gid mappings.
=========
Arguments
=========
nova-idmapshift -i -c -d -v
-u [[guest-uid:host-uid:count],...]
-g [[guest-gid:host-gid:count],...]
-n [nobody-id]
path
path: Root path of the filesystem to be shifted
-i, --idempotent: Shift operation will only be performed if filesystem
appears unshifted
-c, --confirm: Will perform check on filesystem
Returns 0 when filesystem appears shifted
Returns 1 when filesystem appears unshifted
-d, --dry-run: Print chown operations, but won't perform them
-v, --verbose: Print chown operations while performing them
-u, --uid: User ID mappings, maximum of 3 ranges
-g, --gid: Group ID mappings, maximum of 3 ranges
-n, --nobody: ID to map all unmapped uid and gids to.
=======
Purpose
=======
When using user namespaces with linux containers, the filesystem of the
container must be owned by the targeted user and group ids being applied
to that container. Otherwise, processes inside the container won't be able
@ -80,12 +36,13 @@ inaccessible inside the container.
"""
import argparse
import os
import sys
from nova.i18n import _
from oslo_log import log as logging
import nova.privsep
LOG = logging.getLogger(__name__)
NOBODY_ID = 65534
@ -102,30 +59,25 @@ def find_target_id(fsid, mappings, nobody, memo):
def print_chown(path, uid, gid, target_uid, target_gid):
print('%s %s:%s -> %s:%s' % (path, uid, gid, target_uid, target_gid))
LOG.debug('%s %s:%s -> %s:%s', path, uid, gid, target_uid, target_gid)
def shift_path(path, uid_mappings, gid_mappings, nobody, uid_memo, gid_memo,
dry_run=False, verbose=False):
def shift_path(path, uid_mappings, gid_mappings, nobody, uid_memo, gid_memo):
stat = os.lstat(path)
uid = stat.st_uid
gid = stat.st_gid
target_uid = find_target_id(uid, uid_mappings, nobody, uid_memo)
target_gid = find_target_id(gid, gid_mappings, nobody, gid_memo)
if verbose:
print_chown(path, uid, gid, target_uid, target_gid)
if not dry_run:
os.lchown(path, target_uid, target_gid)
print_chown(path, uid, gid, target_uid, target_gid)
os.lchown(path, target_uid, target_gid)
def shift_dir(fsdir, uid_mappings, gid_mappings, nobody,
dry_run=False, verbose=False):
def shift_dir(fsdir, uid_mappings, gid_mappings, nobody):
uid_memo = dict()
gid_memo = dict()
def shift_path_short(p):
shift_path(p, uid_mappings, gid_mappings, nobody,
dry_run=dry_run, verbose=verbose,
uid_memo=uid_memo, gid_memo=gid_memo)
shift_path_short(fsdir)
@ -182,51 +134,8 @@ def confirm_dir(fsdir, uid_mappings, gid_mappings, nobody):
return True
def id_map_type(val):
maps = val.split(',')
id_maps = []
for m in maps:
map_vals = m.split(':')
if len(map_vals) != 3:
msg = ('Invalid id map %s, correct syntax is '
'guest-id:host-id:count.')
raise argparse.ArgumentTypeError(msg % val)
try:
vals = [int(i) for i in map_vals]
except ValueError:
msg = 'Invalid id map %s, values must be integers' % val
raise argparse.ArgumentTypeError(msg)
id_maps.append(tuple(vals))
return id_maps
def main():
parser = argparse.ArgumentParser(
description=_('nova-idmapshift is a tool that properly '
'sets the ownership of a filesystem for '
'use with linux user namespaces. '
'This tool can only be used with linux '
'lxc containers. See the man page for '
'details.'))
parser.add_argument('path')
parser.add_argument('-u', '--uid', type=id_map_type, default=[])
parser.add_argument('-g', '--gid', type=id_map_type, default=[])
parser.add_argument('-n', '--nobody', default=NOBODY_ID, type=int)
parser.add_argument('-i', '--idempotent', action='store_true')
parser.add_argument('-c', '--confirm', action='store_true')
parser.add_argument('-d', '--dry-run', action='store_true')
parser.add_argument('-v', '--verbose', action='store_true')
args = parser.parse_args()
if args.idempotent or args.confirm:
if confirm_dir(args.path, args.uid, args.gid, args.nobody):
sys.exit(0)
else:
if args.confirm:
sys.exit(1)
shift_dir(args.path, args.uid, args.gid, args.nobody,
dry_run=args.dry_run, verbose=args.verbose)
@nova.privsep.sys_admin_pctxt.entrypoint
def shift(path, uid_map, gid_map):
if confirm_dir(uid_map, gid_map, path, NOBODY_ID):
return
shift_dir(path, uid_map, gid_map, NOBODY_ID)

View File

@ -12,13 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import argparse
import fixtures
import mock
from six.moves import StringIO
from nova.cmd import idmapshift
from nova.privsep import idmapshift
from nova import test
@ -111,32 +109,9 @@ class ShiftPathTestCase(BaseTestCase):
mock_lstat.assert_has_calls([mock.call('/test/path')])
mock_lchown.assert_has_calls([mock.call('/test/path', 10000, 10000)])
@mock.patch('os.lchown')
@mock.patch('os.lstat')
def test_shift_path_dry_run(self, mock_lstat, mock_lchown):
mock_lstat.return_value = FakeStat(0, 0)
idmapshift.shift_path('/test/path', self.uid_maps, self.gid_maps,
idmapshift.NOBODY_ID, dict(), dict(),
dry_run=True)
mock_lstat.assert_has_calls([mock.call('/test/path')])
self.assertEqual(0, len(mock_lchown.mock_calls))
@mock.patch('os.lchown')
@mock.patch('nova.cmd.idmapshift.print_chown')
@mock.patch('os.lstat')
def test_shift_path_verbose(self, mock_lstat, mock_print, mock_lchown):
mock_lstat.return_value = FakeStat(0, 0)
idmapshift.shift_path('/test/path', self.uid_maps, self.gid_maps,
idmapshift.NOBODY_ID, dict(), dict(),
verbose=True)
mock_lstat.assert_has_calls([mock.call('/test/path')])
mock_print_call = mock.call('/test/path', 0, 0, 10000, 10000)
mock_print.assert_has_calls([mock_print_call])
mock_lchown.assert_has_calls([mock.call('/test/path', 10000, 10000)])
class ShiftDirTestCase(BaseTestCase):
@mock.patch('nova.cmd.idmapshift.shift_path')
@mock.patch('nova.privsep.idmapshift.shift_path')
@mock.patch('os.path.join')
@mock.patch('os.walk')
def test_shift_dir(self, mock_walk, mock_join, mock_shift_path):
@ -152,32 +127,7 @@ class ShiftDirTestCase(BaseTestCase):
mock_join.assert_has_calls(mock_join_calls)
args = (self.uid_maps, self.gid_maps, idmapshift.NOBODY_ID)
kwargs = dict(dry_run=False, verbose=False,
uid_memo=dict(), gid_memo=dict())
shift_path_calls = [mock.call('/', *args, **kwargs)]
shift_path_calls += [mock.call('/' + x, *args, **kwargs)
for x in files]
mock_shift_path.assert_has_calls(shift_path_calls)
@mock.patch('nova.cmd.idmapshift.shift_path')
@mock.patch('os.path.join')
@mock.patch('os.walk')
def test_shift_dir_dry_run(self, mock_walk, mock_join, mock_shift_path):
mock_walk.return_value = [('/', ['a', 'b'], ['c', 'd'])]
mock_join.side_effect = join_side_effect
idmapshift.shift_dir('/', self.uid_maps, self.gid_maps,
idmapshift.NOBODY_ID, dry_run=True)
mock_walk.assert_has_calls([mock.call('/')])
files = ['a', 'b', 'c', 'd']
mock_join_calls = [mock.call('/', x) for x in files]
mock_join.assert_has_calls(mock_join_calls)
args = (self.uid_maps, self.gid_maps, idmapshift.NOBODY_ID)
kwargs = dict(dry_run=True, verbose=False,
uid_memo=dict(), gid_memo=dict())
kwargs = dict(uid_memo=dict(), gid_memo=dict())
shift_path_calls = [mock.call('/', *args, **kwargs)]
shift_path_calls += [mock.call('/' + x, *args, **kwargs)
for x in files]
@ -264,7 +214,7 @@ class ConfirmDirTestCase(BaseTestCase):
self.uid_map_ranges = idmapshift.get_ranges(self.uid_maps)
self.gid_map_ranges = idmapshift.get_ranges(self.gid_maps)
@mock.patch('nova.cmd.idmapshift.confirm_path')
@mock.patch('nova.privsep.idmapshift.confirm_path')
@mock.patch('os.path.join')
@mock.patch('os.walk')
def test_confirm_dir(self, mock_walk, mock_join, mock_confirm_path):
@ -286,7 +236,7 @@ class ConfirmDirTestCase(BaseTestCase):
for x in files]
mock_confirm_path.assert_has_calls(confirm_path_calls)
@mock.patch('nova.cmd.idmapshift.confirm_path')
@mock.patch('nova.privsep.idmapshift.confirm_path')
@mock.patch('os.path.join')
@mock.patch('os.walk')
def test_confirm_dir_short_circuit_root(self, mock_walk, mock_join,
@ -302,7 +252,7 @@ class ConfirmDirTestCase(BaseTestCase):
confirm_path_calls = [mock.call('/', *args)]
mock_confirm_path.assert_has_calls(confirm_path_calls)
@mock.patch('nova.cmd.idmapshift.confirm_path')
@mock.patch('nova.privsep.idmapshift.confirm_path')
@mock.patch('os.path.join')
@mock.patch('os.walk')
def test_confirm_dir_short_circuit_file(self, mock_walk, mock_join,
@ -328,7 +278,7 @@ class ConfirmDirTestCase(BaseTestCase):
mock.call('/' + 'a', *args)]
mock_confirm_path.assert_has_calls(confirm_path_calls)
@mock.patch('nova.cmd.idmapshift.confirm_path')
@mock.patch('nova.privsep.idmapshift.confirm_path')
@mock.patch('os.path.join')
@mock.patch('os.walk')
def test_confirm_dir_short_circuit_dir(self, mock_walk, mock_join,
@ -358,162 +308,6 @@ class ConfirmDirTestCase(BaseTestCase):
mock_confirm_path.assert_has_calls(confirm_path_calls)
class IDMapTypeTestCase(test.NoDBTestCase):
def test_id_map_type(self):
result = idmapshift.id_map_type("1:1:1,2:2:2")
self.assertEqual([(1, 1, 1), (2, 2, 2)], result)
def test_id_map_type_not_int(self):
self.assertRaises(argparse.ArgumentTypeError, idmapshift.id_map_type,
"a:1:1")
def test_id_map_type_not_proper_format(self):
self.assertRaises(argparse.ArgumentTypeError, idmapshift.id_map_type,
"1:1")
class MainTestCase(BaseTestCase):
@mock.patch('nova.cmd.idmapshift.shift_dir')
@mock.patch('argparse.ArgumentParser')
def test_main(self, mock_parser_class, mock_shift_dir):
mock_parser = mock.MagicMock()
mock_parser.parse_args.return_value = mock_parser
mock_parser.idempotent = False
mock_parser.confirm = False
mock_parser.path = '/test/path'
mock_parser.uid = self.uid_maps
mock_parser.gid = self.gid_maps
mock_parser.nobody = idmapshift.NOBODY_ID
mock_parser.dry_run = False
mock_parser.verbose = False
mock_parser_class.return_value = mock_parser
idmapshift.main()
mock_shift_dir_call = mock.call('/test/path', self.uid_maps,
self.gid_maps, idmapshift.NOBODY_ID,
dry_run=False, verbose=False)
mock_shift_dir.assert_has_calls([mock_shift_dir_call])
@mock.patch('nova.cmd.idmapshift.shift_dir')
@mock.patch('nova.cmd.idmapshift.confirm_dir')
@mock.patch('argparse.ArgumentParser')
def test_main_confirm_dir_idempotent_unshifted(self, mock_parser_class,
mock_confirm_dir,
mock_shift_dir):
mock_parser = mock.MagicMock()
mock_parser.parse_args.return_value = mock_parser
mock_parser.idempotent = True
mock_parser.confirm = False
mock_parser.path = '/test/path'
mock_parser.uid = self.uid_maps
mock_parser.gid = self.gid_maps
mock_parser.nobody = idmapshift.NOBODY_ID
mock_parser.dry_run = False
mock_parser.verbose = False
mock_parser_class.return_value = mock_parser
mock_confirm_dir.return_value = False
idmapshift.main()
mock_confirm_dir_call = mock.call('/test/path', self.uid_maps,
self.gid_maps, idmapshift.NOBODY_ID)
mock_confirm_dir.assert_has_calls([mock_confirm_dir_call])
mock_shift_dir_call = mock.call('/test/path', self.uid_maps,
self.gid_maps, idmapshift.NOBODY_ID,
dry_run=False, verbose=False)
mock_shift_dir.assert_has_calls([mock_shift_dir_call])
@mock.patch('nova.cmd.idmapshift.shift_dir')
@mock.patch('nova.cmd.idmapshift.confirm_dir')
@mock.patch('argparse.ArgumentParser')
def test_main_confirm_dir_idempotent_shifted(self, mock_parser_class,
mock_confirm_dir,
mock_shift_dir):
mock_parser = mock.MagicMock()
mock_parser.parse_args.return_value = mock_parser
mock_parser.idempotent = True
mock_parser.confirm = False
mock_parser.path = '/test/path'
mock_parser.uid = self.uid_maps
mock_parser.gid = self.gid_maps
mock_parser.nobody = idmapshift.NOBODY_ID
mock_parser.dry_run = False
mock_parser.verbose = False
mock_parser_class.return_value = mock_parser
mock_confirm_dir.return_value = True
try:
idmapshift.main()
except SystemExit as sys_exit:
self.assertEqual(sys_exit.code, 0)
mock_confirm_dir_call = mock.call('/test/path', self.uid_maps,
self.gid_maps, idmapshift.NOBODY_ID)
mock_confirm_dir.assert_has_calls([mock_confirm_dir_call])
mock_shift_dir.assert_has_calls([])
@mock.patch('nova.cmd.idmapshift.shift_dir')
@mock.patch('nova.cmd.idmapshift.confirm_dir')
@mock.patch('argparse.ArgumentParser')
def test_main_confirm_dir_confirm_unshifted(self, mock_parser_class,
mock_confirm_dir,
mock_shift_dir):
mock_parser = mock.MagicMock()
mock_parser.parse_args.return_value = mock_parser
mock_parser.idempotent = False
mock_parser.confirm = True
mock_parser.exit_on_fail = True
mock_parser.path = '/test/path'
mock_parser.uid = self.uid_maps
mock_parser.gid = self.gid_maps
mock_parser.nobody = idmapshift.NOBODY_ID
mock_parser.dry_run = False
mock_parser.verbose = False
mock_parser_class.return_value = mock_parser
mock_confirm_dir.return_value = False
try:
idmapshift.main()
except SystemExit as sys_exit:
self.assertEqual(sys_exit.code, 1)
mock_confirm_dir_call = mock.call('/test/path', self.uid_maps,
self.gid_maps, idmapshift.NOBODY_ID)
mock_confirm_dir.assert_has_calls([mock_confirm_dir_call])
mock_shift_dir.assert_has_calls([])
@mock.patch('nova.cmd.idmapshift.shift_dir')
@mock.patch('nova.cmd.idmapshift.confirm_dir')
@mock.patch('argparse.ArgumentParser')
def test_main_confirm_dir_confirm_shifted(self, mock_parser_class,
mock_confirm_dir,
mock_shift_dir):
mock_parser = mock.MagicMock()
mock_parser.parse_args.return_value = mock_parser
mock_parser.idempotent = False
mock_parser.confirm = True
mock_parser.exit_on_fail = True
mock_parser.path = '/test/path'
mock_parser.uid = self.uid_maps
mock_parser.gid = self.gid_maps
mock_parser.nobody = idmapshift.NOBODY_ID
mock_parser.dry_run = False
mock_parser.verbose = False
mock_parser_class.return_value = mock_parser
mock_confirm_dir.return_value = True
try:
idmapshift.main()
except SystemExit as sys_exit:
self.assertEqual(sys_exit.code, 0)
mock_confirm_dir_call = mock.call('/test/path', self.uid_maps,
self.gid_maps, idmapshift.NOBODY_ID)
mock_confirm_dir.assert_has_calls([mock_confirm_dir_call])
mock_shift_dir.assert_has_calls([])
class IntegrationTestCase(BaseTestCase):
@mock.patch('os.lchown')
@mock.patch('os.lstat')
@ -540,7 +334,7 @@ class IntegrationTestCase(BaseTestCase):
mock_lstat.side_effect = lstat
idmapshift.shift_dir('/tmp/test', self.uid_maps, self.gid_maps,
idmapshift.NOBODY_ID, verbose=True)
idmapshift.NOBODY_ID)
lchown_calls = [
mock.call('/tmp/test', 10000, 10000),
@ -554,35 +348,6 @@ class IntegrationTestCase(BaseTestCase):
]
mock_lchown.assert_has_calls(lchown_calls)
@mock.patch('os.lchown')
@mock.patch('os.lstat')
@mock.patch('os.path.join')
@mock.patch('os.walk')
def test_integrated_shift_dir_dry_run(self, mock_walk, mock_join,
mock_lstat, mock_lchown):
mock_walk.return_value = [('/tmp/test', ['a', 'b', 'c'], ['d']),
('/tmp/test/d', ['1', '2'], [])]
mock_join.side_effect = join_side_effect
def lstat(path):
stats = {
't': FakeStat(0, 0),
'a': FakeStat(0, 0),
'b': FakeStat(0, 2),
'c': FakeStat(30000, 30000),
'd': FakeStat(100, 100),
'1': FakeStat(0, 100),
'2': FakeStat(100, 100),
}
return stats[path[-1]]
mock_lstat.side_effect = lstat
idmapshift.shift_dir('/tmp/test', self.uid_maps, self.gid_maps,
idmapshift.NOBODY_ID, dry_run=True, verbose=True)
self.assertEqual(0, len(mock_lchown.mock_calls))
@mock.patch('os.lstat')
@mock.patch('os.path.join')
@mock.patch('os.walk')

View File

@ -35,7 +35,6 @@ from nova.tests import uuidsentinel as uuids
from nova import utils
from nova.virt.disk import api as disk
from nova.virt import images
from nova.virt.libvirt import config as vconfig
from nova.virt.libvirt import guest as libvirt_guest
from nova.virt.libvirt import utils as libvirt_utils
@ -518,29 +517,6 @@ disk size: 4.4M
finally:
os.unlink(dst_path)
@mock.patch.object(utils, 'execute')
def test_chown_for_id_maps(self, mock_execute):
id_maps = [vconfig.LibvirtConfigGuestUIDMap(),
vconfig.LibvirtConfigGuestUIDMap(),
vconfig.LibvirtConfigGuestGIDMap(),
vconfig.LibvirtConfigGuestGIDMap()]
id_maps[0].target = 10000
id_maps[0].count = 2000
id_maps[1].start = 2000
id_maps[1].target = 40000
id_maps[1].count = 2000
id_maps[2].target = 10000
id_maps[2].count = 2000
id_maps[3].start = 2000
id_maps[3].target = 40000
id_maps[3].count = 2000
libvirt_utils.chown_for_id_maps('/some/path', id_maps)
execute_args = ('nova-idmapshift', '-i',
'-u', '0:10000:2000,2000:40000:2000',
'-g', '0:10000:2000,2000:40000:2000',
'/some/path')
mock_execute.assert_called_once_with(*execute_args, run_as_root=True)
def _do_test_extract_snapshot(self, mock_execute, src_format='qcow2',
dest_format='raw', out_format='raw'):
libvirt_utils.extract_snapshot('/path/to/disk/image', src_format,

View File

@ -29,6 +29,7 @@ from oslo_utils import fileutils
import nova.conf
from nova.i18n import _
from nova.objects import fields as obj_fields
import nova.privsep.idmapshift
import nova.privsep.libvirt
from nova import utils
from nova.virt.disk import api as disk
@ -243,10 +244,6 @@ def write_to_file(path, contents, umask=None):
os.umask(saved_umask)
def _id_map_to_config(id_map):
return "%s:%s:%s" % (id_map.start, id_map.target, id_map.count)
def chown_for_id_maps(path, id_maps):
"""Change ownership of file or directory for an id mapped
environment
@ -254,14 +251,11 @@ def chown_for_id_maps(path, id_maps):
:param path: File or directory whose ownership to change
:param id_maps: List of type LibvirtConfigGuestIDMap
"""
uid_maps_str = ','.join([_id_map_to_config(id_map) for id_map in id_maps if
isinstance(id_map,
vconfig.LibvirtConfigGuestUIDMap)])
gid_maps_str = ','.join([_id_map_to_config(id_map) for id_map in id_maps if
isinstance(id_map,
vconfig.LibvirtConfigGuestGIDMap)])
utils.execute('nova-idmapshift', '-i', '-u', uid_maps_str,
'-g', gid_maps_str, path, run_as_root=True)
uid_maps = [id_map for id_map in id_maps if
isinstance(id_map, vconfig.LibvirtConfigGuestUIDMap)]
gid_maps = [id_map for id_map in id_maps if
isinstance(id_map, vconfig.LibvirtConfigGuestGIDMap)]
nova.privsep.idmapshift.shift(path, uid_maps, gid_maps)
def extract_snapshot(disk_path, source_fmt, out_path, dest_fmt):

View File

@ -5,8 +5,11 @@ upgrade:
rootwrap configuration.
- |
Calls to mount in the virt disk api no longer ignore the value of stderr.
- |
The nova-idmapshift binary has been removed. This has been replaced by
internal functionality using privsep.
- |
The following commands are no longer required to be listed in your rootwrap
configuration: cat; chown; cryptsetup; dd; lvcreate; lvremove; lvs; mkdir;
mount; ploop; prl_disk_tool; readlink; shred; tee; touch; umount; vgs;
and xend.
mount; nova-idmapshift; ploop; prl_disk_tool; readlink; shred; tee; touch;
umount; vgs; and xend.

View File

@ -61,7 +61,6 @@ console_scripts =
nova-console = nova.cmd.console:main
nova-consoleauth = nova.cmd.consoleauth:main
nova-dhcpbridge = nova.cmd.dhcpbridge:main
nova-idmapshift = nova.cmd.idmapshift:main
nova-manage = nova.cmd.manage:main
nova-network = nova.cmd.network:main
nova-novncproxy = nova.cmd.novncproxy:main