Skip Trilio dirs when setting ownership in /var/lib/nova
Trilio currently mounts an NFS export in /var/lib/nova to make it accessible
from within the nova_compute and nova_libvirt containers.
This can result in considerable delays when walking the directory tree to
ensure the ownership is correct.
This patch adds the ability to skip paths when recursively setting the
ownership and selinux context in /var/lib/nova. The list of paths to skip
can be set via te NovaStatedirOwnershipSkip heat parameter. This default to
the Trilio dir.
Change-Id: Ic6f053d56194613046ae0a4a908206ebb453fcf4
(cherry picked from commit c156534010
)
This commit is contained in:
parent
2a20b7582f
commit
fbc55f02f2
|
@ -137,7 +137,8 @@ class NovaStatedirOwnershipManager(object):
|
||||||
docker nova uid/gid is not known in this context).
|
docker nova uid/gid is not known in this context).
|
||||||
"""
|
"""
|
||||||
def __init__(self, statedir, upgrade_marker='upgrade_marker',
|
def __init__(self, statedir, upgrade_marker='upgrade_marker',
|
||||||
nova_user='nova', secontext_marker='../_nova_secontext'):
|
nova_user='nova', secontext_marker='../_nova_secontext',
|
||||||
|
exclude_paths=None):
|
||||||
self.statedir = statedir
|
self.statedir = statedir
|
||||||
self.nova_user = nova_user
|
self.nova_user = nova_user
|
||||||
|
|
||||||
|
@ -145,6 +146,13 @@ class NovaStatedirOwnershipManager(object):
|
||||||
self.secontext_marker_path = os.path.normpath(os.path.join(statedir, secontext_marker))
|
self.secontext_marker_path = os.path.normpath(os.path.join(statedir, secontext_marker))
|
||||||
self.upgrade = os.path.exists(self.upgrade_marker_path)
|
self.upgrade = os.path.exists(self.upgrade_marker_path)
|
||||||
|
|
||||||
|
self.exclude_paths = [self.upgrade_marker_path]
|
||||||
|
if exclude_paths is not None:
|
||||||
|
for p in exclude_paths:
|
||||||
|
if not p.startswith(os.path.sep):
|
||||||
|
p = os.path.join(self.statedir, p)
|
||||||
|
self.exclude_paths.append(p)
|
||||||
|
|
||||||
self.target_uid, self.target_gid = self._get_nova_ids()
|
self.target_uid, self.target_gid = self._get_nova_ids()
|
||||||
self.previous_uid, self.previous_gid = self._get_previous_nova_ids()
|
self.previous_uid, self.previous_gid = self._get_previous_nova_ids()
|
||||||
self.id_change = (self.target_uid, self.target_gid) != \
|
self.id_change = (self.target_uid, self.target_gid) != \
|
||||||
|
@ -172,7 +180,7 @@ class NovaStatedirOwnershipManager(object):
|
||||||
for f in os.listdir(top):
|
for f in os.listdir(top):
|
||||||
pathname = os.path.join(top, f)
|
pathname = os.path.join(top, f)
|
||||||
|
|
||||||
if pathname == self.upgrade_marker_path:
|
if pathname in self.exclude_paths:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -228,5 +236,12 @@ class NovaStatedirOwnershipManager(object):
|
||||||
LOG.info('Nova statedir ownership complete')
|
LOG.info('Nova statedir ownership complete')
|
||||||
|
|
||||||
|
|
||||||
|
def get_exclude_paths():
|
||||||
|
exclude_paths = os.environ.get('NOVA_STATEDIR_OWNERSHIP_SKIP')
|
||||||
|
if exclude_paths is not None:
|
||||||
|
exclude_paths = exclude_paths.split(os.pathsep)
|
||||||
|
return exclude_paths
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
NovaStatedirOwnershipManager('/var/lib/nova').run()
|
NovaStatedirOwnershipManager('/var/lib/nova', exclude_paths=get_exclude_paths())
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
import contextlib
|
import contextlib
|
||||||
|
import os
|
||||||
from os import stat as orig_stat
|
from os import stat as orig_stat
|
||||||
import six
|
import six
|
||||||
import stat
|
import stat
|
||||||
|
@ -36,6 +37,7 @@ class FakeSelinux(object):
|
||||||
|
|
||||||
sys.modules["selinux"] = FakeSelinux
|
sys.modules["selinux"] = FakeSelinux
|
||||||
|
|
||||||
|
from container_config_scripts.nova_statedir_ownership import get_exclude_paths # noqa: E402
|
||||||
from container_config_scripts.nova_statedir_ownership import \
|
from container_config_scripts.nova_statedir_ownership import \
|
||||||
NovaStatedirOwnershipManager # noqa: E402
|
NovaStatedirOwnershipManager # noqa: E402
|
||||||
from container_config_scripts.nova_statedir_ownership import PathManager # noqa: E402
|
from container_config_scripts.nova_statedir_ownership import PathManager # noqa: E402
|
||||||
|
@ -395,3 +397,31 @@ class NovaStatedirOwnershipManagerTestCase(base.BaseTestCase):
|
||||||
for fn, expected in six.iteritems(expected_changes):
|
for fn, expected in six.iteritems(expected_changes):
|
||||||
assert_ids(testtree, fn, expected[0], expected[1])
|
assert_ids(testtree, fn, expected[0], expected[1])
|
||||||
fake_unlink.assert_called_with('/var/lib/nova/upgrade_marker')
|
fake_unlink.assert_called_with('/var/lib/nova/upgrade_marker')
|
||||||
|
|
||||||
|
def test_exclude_path(self):
|
||||||
|
testtree = generate_testtree1(current_uid, current_gid)
|
||||||
|
|
||||||
|
with fake_testtree(testtree) as (
|
||||||
|
fake_chown, _, fake_listdir, fake_stat, _, _, _):
|
||||||
|
manager = NovaStatedirOwnershipManager(
|
||||||
|
'/var/lib/nova',
|
||||||
|
exclude_paths=['instances/foo/bar', '/var/lib/nova/instances/foo/removeddir']
|
||||||
|
)
|
||||||
|
manager.run()
|
||||||
|
self.assertIn('/var/lib/nova/instances/foo/bar', manager.exclude_paths)
|
||||||
|
self.assertIn('/var/lib/nova/instances/foo/removeddir', manager.exclude_paths)
|
||||||
|
self.assertNotIn(mock.call('/var/lib/nova/instances/foo/bar'), fake_stat.call_args_list)
|
||||||
|
self.assertNotIn(mock.call('/var/lib/nova/instances/foo/bar'), fake_chown.call_args_list)
|
||||||
|
self.assertNotIn(mock.call('/var/lib/nova/instances/foo/removeddir'), fake_stat.call_args_list)
|
||||||
|
self.assertNotIn(mock.call('/var/lib/nova/instances/foo/removeddir'), fake_chown.call_args_list)
|
||||||
|
self.assertNotIn(mock.call('/var/lib/nova/instances/foo/removeddir'), fake_listdir.call_args_list)
|
||||||
|
|
||||||
|
@mock.patch.dict(os.environ, {'NOVA_STATEDIR_OWNERSHIP_SKIP': 'foo:bar:foo/bar/baz'})
|
||||||
|
def test_get_exclude_paths(self):
|
||||||
|
expected = [
|
||||||
|
'foo',
|
||||||
|
'bar',
|
||||||
|
'foo/bar/baz'
|
||||||
|
]
|
||||||
|
exclude_paths = get_exclude_paths()
|
||||||
|
self.assertEqual(exclude_paths, expected)
|
||||||
|
|
|
@ -500,6 +500,13 @@ parameters:
|
||||||
default: false
|
default: false
|
||||||
tags:
|
tags:
|
||||||
- role_specific
|
- role_specific
|
||||||
|
NovaStatedirOwnershipSkip:
|
||||||
|
type: comma_delimited_list
|
||||||
|
description: >
|
||||||
|
List of paths relative to nova_statedir to ignore when recursively setting the
|
||||||
|
ownership and selinux context.
|
||||||
|
default:
|
||||||
|
- 'triliovault-mounts'
|
||||||
|
|
||||||
# DEPRECATED: the following options are deprecated and are currently maintained
|
# DEPRECATED: the following options are deprecated and are currently maintained
|
||||||
# for backwards compatibility. They will be removed in future release.
|
# for backwards compatibility. They will be removed in future release.
|
||||||
|
@ -917,6 +924,10 @@ outputs:
|
||||||
expression: str($.data.debug)
|
expression: str($.data.debug)
|
||||||
data:
|
data:
|
||||||
debug: {get_attr: [NovaBase, role_data, config_settings, 'nova::logging::debug']}
|
debug: {get_attr: [NovaBase, role_data, config_settings, 'nova::logging::debug']}
|
||||||
|
NOVA_STATEDIR_OWNERSHIP_SKIP:
|
||||||
|
list_join:
|
||||||
|
- ':'
|
||||||
|
- {get_param: NovaStatedirOwnershipSkip}
|
||||||
step_5:
|
step_5:
|
||||||
map_merge:
|
map_merge:
|
||||||
- nova_compute:
|
- nova_compute:
|
||||||
|
|
Loading…
Reference in New Issue