podman: get cpus allowed list only when isolcpus in cmdline

When building the podman command, only get cpus allowed list when there
is isolcpus in the /proc/cmdline otherwise skip the argument.

Note: re-working the Mocks for cpu affinity so we can properly test the
/proc/cmdline reads.

Change-Id: I270c90d3adc8824991896443c6074f8f7357c942
Related-Bug: #1884765
Co-Authored-By: Alex Schultz <aschultz@redhat.com>
This commit is contained in:
Emilien Macchi 2020-06-23 08:51:03 -04:00
parent 2729221477
commit 7ea9455221
5 changed files with 38 additions and 37 deletions

View File

@ -91,7 +91,10 @@ class ComposeV1Builder(base.BaseBuilder):
if cconfig['cpuset_cpus'] != 'all': if cconfig['cpuset_cpus'] != 'all':
cmd.append('--cpuset-cpus=%s' % cconfig['cpuset_cpus']) cmd.append('--cpuset-cpus=%s' % cconfig['cpuset_cpus'])
else: else:
cmd.append('--cpuset-cpus=%s' % common.get_cpus_allowed_list()) with open('/proc/cmdline') as cmdline:
if 'isolcpus' in cmdline.read():
cmd.append('--cpuset-cpus=%s' %
common.get_cpus_allowed_list())
self.string_arg(cconfig, cmd, self.string_arg(cconfig, cmd,
'stop_grace_period', '--stop-timeout', 'stop_grace_period', '--stop-timeout',

View File

@ -100,7 +100,10 @@ class PodmanBuilder(base.BaseBuilder):
if cconfig['cpuset_cpus'] != 'all': if cconfig['cpuset_cpus'] != 'all':
cmd.append('--cpuset-cpus=%s' % cconfig['cpuset_cpus']) cmd.append('--cpuset-cpus=%s' % cconfig['cpuset_cpus'])
else: else:
cmd.append('--cpuset-cpus=%s' % common.get_cpus_allowed_list()) with open('/proc/cmdline') as cmdline:
if 'isolcpus' in cmdline.read():
cmd.append('--cpuset-cpus=%s' %
common.get_cpus_allowed_list())
self.string_arg(cconfig, cmd, self.string_arg(cconfig, cmd,
'stop_grace_period', '--stop-timeout', 'stop_grace_period', '--stop-timeout',

View File

@ -26,10 +26,20 @@ from paunch.tests import base
class TestBaseBuilder(base.TestCase): class TestBaseBuilder(base.TestCase):
@mock.patch("psutil.Process.cpu_affinity", return_value=[0, 1, 2, 3]) def setUp(self):
super(TestBaseBuilder, self).setUp()
mock_cpu_obj = mock.MagicMock()
mock_cpu_aff = mock.MagicMock()
mock_cpu_aff.return_value = [0, 1, 2, 3]
mock_cpu_obj.cpu_affinity = mock_cpu_aff
self.psutil_mock = mock.patch('psutil.Process',
return_value=mock_cpu_obj)
self.psutil_mock.start()
self.addCleanup(self.psutil_mock.stop)
@mock.patch("paunch.builder.base.BaseBuilder.delete_updated", @mock.patch("paunch.builder.base.BaseBuilder.delete_updated",
return_value=False) return_value=False)
def test_apply(self, mock_delete_updated, mock_cpu): def test_apply(self, mock_delete_updated):
orig_call = tenacity.wait.wait_random_exponential.__call__ orig_call = tenacity.wait.wait_random_exponential.__call__
orig_argspec = inspect.getargspec(orig_call) orig_argspec = inspect.getargspec(orig_call)
config = { config = {
@ -168,7 +178,7 @@ three-12345678 three''', '', 0),
'--label', 'container_name=one', '--label', 'container_name=one',
'--label', 'managed_by=tester', '--label', 'managed_by=tester',
'--label', 'config_data=%s' % json.dumps(config['one']), '--label', 'config_data=%s' % json.dumps(config['one']),
'--detach=true', '--cpuset-cpus=0,1,2,3', '--detach=true',
'centos:7'], mock.ANY 'centos:7'], mock.ANY
), ),
# run two # run two
@ -178,7 +188,7 @@ three-12345678 three''', '', 0),
'--label', 'container_name=two', '--label', 'container_name=two',
'--label', 'managed_by=tester', '--label', 'managed_by=tester',
'--label', 'config_data=%s' % json.dumps(config['two']), '--label', 'config_data=%s' % json.dumps(config['two']),
'--detach=true', '--cpuset-cpus=0,1,2,3', '--detach=true',
'centos:7'], mock.ANY 'centos:7'], mock.ANY
), ),
# run four # run four
@ -188,7 +198,7 @@ three-12345678 three''', '', 0),
'--label', 'container_name=four', '--label', 'container_name=four',
'--label', 'managed_by=tester', '--label', 'managed_by=tester',
'--label', 'config_data=%s' % json.dumps(config['four']), '--label', 'config_data=%s' % json.dumps(config['four']),
'--detach=true', '--cpuset-cpus=0,1,2,3', '--detach=true',
'centos:7'], mock.ANY 'centos:7'], mock.ANY
), ),
# execute within four # execute within four
@ -198,11 +208,10 @@ three-12345678 three''', '', 0),
), ),
]) ])
@mock.patch("psutil.Process.cpu_affinity", return_value=[0, 1, 2, 3])
@mock.patch("paunch.runner.BaseRunner.container_names") @mock.patch("paunch.runner.BaseRunner.container_names")
@mock.patch("paunch.runner.BaseRunner.discover_container_name", @mock.patch("paunch.runner.BaseRunner.discover_container_name",
return_value='one') return_value='one')
def test_apply_idempotency(self, mock_dname, mock_cnames, mock_cpu): def test_apply_idempotency_with_isolcpus(self, mock_dname, mock_cnames):
config = { config = {
# running with the same config and given an ephemeral name # running with the same config and given an ephemeral name
'one': { 'one': {
@ -270,7 +279,9 @@ three-12345678 three''', '', 0),
r.execute = exe r.execute = exe
builder = compose1.ComposeV1Builder('foo', config, r) builder = compose1.ComposeV1Builder('foo', config, r)
stdout, stderr, deploy_status_code = builder.apply() with mock.patch("builtins.open",
mock.mock_open(read_data="isolcpus")):
stdout, stderr, deploy_status_code = builder.apply()
self.assertEqual(0, deploy_status_code) self.assertEqual(0, deploy_status_code)
self.assertEqual([ self.assertEqual([
'Created two-12345678', 'Created two-12345678',
@ -470,8 +481,7 @@ three-12345678 three''', '', 0),
self.assertIn(arg, cmd) self.assertIn(arg, cmd)
@mock.patch('paunch.runner.DockerRunner', autospec=True) @mock.patch('paunch.runner.DockerRunner', autospec=True)
@mock.patch("psutil.Process.cpu_affinity", return_value=[0, 1, 2, 3]) def test_container_run_args_lists(self, runner):
def test_container_run_args_lists(self, mock_cpu, runner):
config = { config = {
'one': { 'one': {
'image': 'centos:7', 'image': 'centos:7',
@ -503,7 +513,6 @@ three-12345678 three''', '', 0),
'--group-add=docker', '--group-add=zuul', '--group-add=docker', '--group-add=zuul',
'--volume=/foo:/foo:rw', '--volume=/bar:/bar:ro', '--volume=/foo:/foo:rw', '--volume=/bar:/bar:ro',
'--volumes-from=two', '--volumes-from=three', '--volumes-from=two', '--volumes-from=three',
'--cpuset-cpus=0,1,2,3',
'--cap-add=SYS_ADMIN', '--cap-add=SETUID', '--cap-drop=NET_RAW', '--cap-add=SYS_ADMIN', '--cap-add=SETUID', '--cap-drop=NET_RAW',
'centos:7', 'ls', '-l', '/foo'], 'centos:7', 'ls', '-l', '/foo'],
cmd cmd

View File

@ -20,8 +20,7 @@ from paunch.tests import test_builder_base as tbb
class TestComposeV1Builder(tbb.TestBaseBuilder): class TestComposeV1Builder(tbb.TestBaseBuilder):
@mock.patch('paunch.runner.DockerRunner', autospec=True) @mock.patch('paunch.runner.DockerRunner', autospec=True)
@mock.patch("psutil.Process.cpu_affinity", return_value=[0, 1, 2, 3]) def test_cont_run_args(self, runner):
def test_cont_run_args(self, mock_cpu, runner):
config = { config = {
'one': { 'one': {
'image': 'centos:7', 'image': 'centos:7',
@ -84,8 +83,7 @@ class TestComposeV1Builder(tbb.TestBaseBuilder):
) )
@mock.patch('paunch.runner.DockerRunner', autospec=True) @mock.patch('paunch.runner.DockerRunner', autospec=True)
@mock.patch("psutil.Process.cpu_affinity", return_value=[0, 1, 2, 3]) def test_cont_run_args_validation_true(self, runner):
def test_cont_run_args_validation_true(self, mock_cpu, runner):
config = { config = {
'one': { 'one': {
'image': 'foo', 'image': 'foo',
@ -99,15 +97,12 @@ class TestComposeV1Builder(tbb.TestBaseBuilder):
self.assertTrue(builder.container_run_args(cmd, 'one')) self.assertTrue(builder.container_run_args(cmd, 'one'))
self.assertEqual( self.assertEqual(
['docker', '--detach=true', ['docker', '--detach=true',
'--volume=/foo:/foo:rw', '--volume=/bar:/bar:ro', '--volume=/foo:/foo:rw', '--volume=/bar:/bar:ro', 'foo'],
'--cpuset-cpus=0,1,2,3',
'foo'],
cmd cmd
) )
@mock.patch('paunch.runner.DockerRunner', autospec=True) @mock.patch('paunch.runner.DockerRunner', autospec=True)
@mock.patch("psutil.Process.cpu_affinity", return_value=[0, 1, 2, 3]) def test_cont_run_args_validation_false(self, runner):
def test_cont_run_args_validation_false(self, mock_cpu, runner):
config = { config = {
'one': { 'one': {
'image': 'foo', 'image': 'foo',
@ -121,7 +116,6 @@ class TestComposeV1Builder(tbb.TestBaseBuilder):
self.assertFalse(builder.container_run_args(cmd, 'one')) self.assertFalse(builder.container_run_args(cmd, 'one'))
self.assertEqual( self.assertEqual(
['docker', '--detach=true', ['docker', '--detach=true',
'--volume=/foo:/foo:rw', '--volume=/bar:/bar:ro', '--volume=/foo:/foo:rw', '--volume=/bar:/bar:ro', 'foo'],
'--cpuset-cpus=0,1,2,3', 'foo'],
cmd cmd
) )

View File

@ -20,8 +20,7 @@ from paunch.tests import test_builder_base as base
class TestPodmanBuilder(base.TestBaseBuilder): class TestPodmanBuilder(base.TestBaseBuilder):
@mock.patch("psutil.Process.cpu_affinity", return_value=[0, 1, 2, 3]) def test_cont_run_args(self):
def test_cont_run_args(self, mock_cpu):
config = { config = {
'one': { 'one': {
'image': 'centos:7', 'image': 'centos:7',
@ -67,16 +66,13 @@ class TestPodmanBuilder(base.TestBaseBuilder):
'--hostname=foohostname', '--hostname=foohostname',
'--add-host=foohost:127.0.0.1', '--add-host=foohost:127.0.0.1',
'--add-host=barhost:127.0.0.2', '--add-host=barhost:127.0.0.2',
'--cpuset-cpus=0,1,2,3',
'--cap-add=SYS_ADMIN', '--cap-add=SETUID', '--cap-drop=NET_RAW', '--cap-add=SYS_ADMIN', '--cap-add=SETUID', '--cap-drop=NET_RAW',
'centos:7'], 'centos:7'],
cmd cmd
) )
@mock.patch("psutil.Process.cpu_affinity",
return_value=[0, 1, 2, 3, 4, 5, 6, 7])
@mock.patch('paunch.runner.PodmanRunner', autospec=True) @mock.patch('paunch.runner.PodmanRunner', autospec=True)
def test_cont_run_args_validation_true(self, runner, mock_cpu): def test_cont_run_args_validation_true(self, runner):
config = { config = {
'one': { 'one': {
'image': 'foo', 'image': 'foo',
@ -90,15 +86,12 @@ class TestPodmanBuilder(base.TestBaseBuilder):
self.assertTrue(builder.container_run_args(cmd, 'one')) self.assertTrue(builder.container_run_args(cmd, 'one'))
self.assertEqual( self.assertEqual(
['podman', '--conmon-pidfile=/var/run/one.pid', '--detach=true', ['podman', '--conmon-pidfile=/var/run/one.pid', '--detach=true',
'--volume=/foo:/foo:rw', '--volume=/bar:/bar:ro', '--volume=/foo:/foo:rw', '--volume=/bar:/bar:ro', 'foo'],
'--cpuset-cpus=0,1,2,3,4,5,6,7', 'foo'],
cmd cmd
) )
@mock.patch("psutil.Process.cpu_affinity",
return_value=[0, 1, 2, 3, 4, 5, 6, 7])
@mock.patch('paunch.runner.PodmanRunner', autospec=True) @mock.patch('paunch.runner.PodmanRunner', autospec=True)
def test_cont_run_args_validation_false(self, runner, mock_cpu): def test_cont_run_args_validation_false(self, runner):
config = { config = {
'one': { 'one': {
'image': 'foo', 'image': 'foo',
@ -112,7 +105,6 @@ class TestPodmanBuilder(base.TestBaseBuilder):
self.assertFalse(builder.container_run_args(cmd, 'one')) self.assertFalse(builder.container_run_args(cmd, 'one'))
self.assertEqual( self.assertEqual(
['podman', '--conmon-pidfile=/var/run/one.pid', '--detach=true', ['podman', '--conmon-pidfile=/var/run/one.pid', '--detach=true',
'--volume=/foo:/foo:rw', '--volume=/bar:/bar:ro', '--volume=/foo:/foo:rw', '--volume=/bar:/bar:ro', 'foo'],
'--cpuset-cpus=0,1,2,3,4,5,6,7', 'foo'],
cmd cmd
) )