You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aurora.apache.org by js...@apache.org on 2016/09/02 18:51:50 UTC
aurora git commit: Allow E_NAME_IN_USE in useradd/groupadd.
Repository: aurora
Updated Branches:
refs/heads/master bd11b1c51 -> 80cf585a0
Allow E_NAME_IN_USE in useradd/groupadd.
Bugs closed: AURORA-1761
Reviewed at https://reviews.apache.org/r/51564/
Project: http://git-wip-us.apache.org/repos/asf/aurora/repo
Commit: http://git-wip-us.apache.org/repos/asf/aurora/commit/80cf585a
Tree: http://git-wip-us.apache.org/repos/asf/aurora/tree/80cf585a
Diff: http://git-wip-us.apache.org/repos/asf/aurora/diff/80cf585a
Branch: refs/heads/master
Commit: 80cf585a00003388bc6501e40d2db05eca19d3cb
Parents: bd11b1c
Author: Zhitao Li <zh...@gmail.com>
Authored: Fri Sep 2 12:51:46 2016 -0600
Committer: John Sirois <jo...@gmail.com>
Committed: Fri Sep 2 12:51:46 2016 -0600
----------------------------------------------------------------------
.../apache/aurora/executor/common/sandbox.py | 41 +++++-
.../aurora/executor/common/test_sandbox.py | 124 +++++++++++++++++--
2 files changed, 154 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/aurora/blob/80cf585a/src/main/python/apache/aurora/executor/common/sandbox.py
----------------------------------------------------------------------
diff --git a/src/main/python/apache/aurora/executor/common/sandbox.py b/src/main/python/apache/aurora/executor/common/sandbox.py
index a172691..4a0f3b5 100644
--- a/src/main/python/apache/aurora/executor/common/sandbox.py
+++ b/src/main/python/apache/aurora/executor/common/sandbox.py
@@ -190,6 +190,10 @@ class FileSystemImageSandbox(DirectorySandbox):
# returncode from a `useradd` or `groupadd` call indicating that the uid/gid already exists.
_USER_OR_GROUP_ID_EXISTS = 4
+ # returncode from a `useradd` or `groupadd` call indicating that the user/group name
+ # already exists.
+ _USER_OR_GROUP_NAME_EXISTS = 9
+
def __init__(self, root, **kwargs):
self._task_fs_root = os.path.join(
os.environ[DefaultSandboxProvider.MESOS_DIRECTORY_ENV_VARIABLE],
@@ -205,6 +209,36 @@ class FileSystemImageSandbox(DirectorySandbox):
super(FileSystemImageSandbox, self).__init__(root, **kwargs)
+ def _verify_group_match_in_taskfs(self, group_id, group_name):
+ try:
+ result = subprocess.check_output(
+ ['chroot', self._task_fs_root, 'getent', 'group', group_name])
+ except subprocess.CalledProcessError as e:
+ raise self.CreationError(
+ 'Error when getting group id for name %s in task image: %s' % (
+ group_name, e))
+ splitted = result.split(':')
+ if (len(splitted) < 3 or splitted[0] != '%s' % group_name or
+ splitted[2] != '%s' % group_id):
+ raise self.CreationError(
+ 'Group id result %s from image does not match name %s and id %s' % (
+ result, group_name, group_id))
+
+ def _verify_user_match_in_taskfs(self, user_id, user_name, group_id, group_name):
+ try:
+ result = subprocess.check_output(
+ ['chroot', self._task_fs_root, 'id', '%s' % user_name])
+ except subprocess.CalledProcessError as e:
+ raise self.CreationError(
+ 'Error when getting user id for name %s in task image: %s' % (
+ user_name, e))
+
+ expected_prefix = "uid=%s(%s) gid=%s(%s) groups=" % (user_id, user_name, group_id, group_name)
+ if not result.startswith(expected_prefix):
+ raise self.CreationError(
+ 'User group result %s from task image does not start with expected prefix %s' % (
+ result, expected_prefix))
+
def _create_user_and_group_in_taskfs(self):
if self._user:
pwent, grent = self.get_user_and_group()
@@ -214,7 +248,8 @@ class FileSystemImageSandbox(DirectorySandbox):
['groupadd', '-R', self._task_fs_root, '-g', '%s' % grent.gr_gid, grent.gr_name])
except subprocess.CalledProcessError as e:
# If the failure was due to the group existing, we're ok to continue, otherwise bail out.
- if e.returncode == self._USER_OR_GROUP_ID_EXISTS:
+ if e.returncode in [self._USER_OR_GROUP_ID_EXISTS, self._USER_OR_GROUP_NAME_EXISTS]:
+ self._verify_group_match_in_taskfs(grent.gr_gid, grent.gr_name)
log.info(
'Group %s(%s) already exists in the task''s filesystem, no need to create.' % (
grent.gr_name, grent.gr_gid))
@@ -232,7 +267,9 @@ class FileSystemImageSandbox(DirectorySandbox):
pwent.pw_name])
except subprocess.CalledProcessError as e:
# If the failure was due to the user existing, we're ok to continue, otherwise bail out.
- if e.returncode == self._USER_OR_GROUP_ID_EXISTS:
+ if e.returncode in [self._USER_OR_GROUP_ID_EXISTS, self._USER_OR_GROUP_NAME_EXISTS]:
+ self._verify_user_match_in_taskfs(
+ pwent.pw_uid, pwent.pw_name, pwent.pw_gid, grent.gr_name)
log.info(
'User %s (%s) already exists in the task''s filesystem, no need to create.' % (
self._user, pwent.pw_uid))
http://git-wip-us.apache.org/repos/asf/aurora/blob/80cf585a/src/test/python/apache/aurora/executor/common/test_sandbox.py
----------------------------------------------------------------------
diff --git a/src/test/python/apache/aurora/executor/common/test_sandbox.py b/src/test/python/apache/aurora/executor/common/test_sandbox.py
index 57ab39e..41ee884 100644
--- a/src/test/python/apache/aurora/executor/common/test_sandbox.py
+++ b/src/test/python/apache/aurora/executor/common/test_sandbox.py
@@ -141,7 +141,89 @@ def test_destroy_ioerror():
ds.destroy()
-def assert_create_user_and_group(mock_check_call, gid_exists, uid_exists):
+MOCK_MESOS_DIRECTORY = '/some/path'
+
+
+@mock.patch('subprocess.check_output')
+@mock.patch.dict(os.environ, {'MESOS_DIRECTORY': MOCK_MESOS_DIRECTORY})
+def test_verify_group_match(mock_check_output):
+ with temporary_dir() as d:
+ sandbox = FileSystemImageSandbox(
+ os.path.join(d, 'sandbox'),
+ user='someuser',
+ sandbox_mount_point='/some/path')
+
+ mock_check_output.return_value = 'test-group:x:2:'
+
+ # valid case
+ sandbox._verify_group_match_in_taskfs(2, 'test-group')
+ mock_check_output.assert_called_with(
+ ['chroot', sandbox._task_fs_root, 'getent', 'group', 'test-group'])
+
+ # invalid group id
+ with pytest.raises(FileSystemImageSandbox.CreationError):
+ sandbox._verify_group_match_in_taskfs(3, 'test-group')
+
+ # invalid group name
+ with pytest.raises(FileSystemImageSandbox.CreationError):
+ sandbox._verify_group_match_in_taskfs(2, 'invalid-group')
+
+ # exception case
+ exception = subprocess.CalledProcessError(
+ returncode=1,
+ cmd='some command',
+ output=None)
+ mock_check_output.side_effect = exception
+ with pytest.raises(FileSystemImageSandbox.CreationError):
+ sandbox._verify_group_match_in_taskfs(2, 'test-group')
+
+
+@mock.patch('subprocess.check_output')
+@mock.patch.dict(os.environ, {'MESOS_DIRECTORY': MOCK_MESOS_DIRECTORY})
+def test_verify_user_match(mock_check_output):
+ with temporary_dir() as d:
+ sandbox = FileSystemImageSandbox(
+ os.path.join(d, 'sandbox'),
+ user='someuser',
+ sandbox_mount_point='/some/path')
+
+ mock_check_output.return_value = 'uid=1(test-user) gid=2(test-group) groups=2(test-group)'
+ # valid case
+ sandbox._verify_user_match_in_taskfs(1, 'test-user', 2, 'test-group')
+ mock_check_output.assert_called_with(['chroot', sandbox._task_fs_root, 'id', 'test-user'])
+
+ # invalid user id
+ with pytest.raises(FileSystemImageSandbox.CreationError):
+ sandbox._verify_user_match_in_taskfs(0, 'test-user', 2, 'test-group')
+
+ # invalid user name
+ with pytest.raises(FileSystemImageSandbox.CreationError):
+ sandbox._verify_user_match_in_taskfs(1, 'invalid-user', 2, 'test-group')
+
+ # invalid group id
+ with pytest.raises(FileSystemImageSandbox.CreationError):
+ sandbox._verify_user_match_in_taskfs(1, 'test-user', 0, 'test-group')
+
+ # invalid group name
+ with pytest.raises(FileSystemImageSandbox.CreationError):
+ sandbox._verify_user_match_in_taskfs(1, 'test-user', 2, 'invalid-group')
+
+ # exception case
+ exception = subprocess.CalledProcessError(
+ returncode=1,
+ cmd='some command',
+ output=None)
+ mock_check_output.side_effect = exception
+ with pytest.raises(FileSystemImageSandbox.CreationError):
+ sandbox._verify_user_match_in_taskfs(1, "test-user", 2, "test-group")
+
+
+def assert_create_user_and_group(mock_check_call,
+ mock_verify,
+ gid_exists,
+ uid_exists,
+ group_name_exists,
+ user_name_exists):
mock_pwent = pwd.struct_passwd((
'someuser', # login name
'hunter2', # password
@@ -157,14 +239,20 @@ def assert_create_user_and_group(mock_check_call, gid_exists, uid_exists):
835, # gid
['someuser'])) # members
+ returncode = 0
+ if gid_exists or uid_exists:
+ returncode = FileSystemImageSandbox._USER_OR_GROUP_ID_EXISTS
+ elif group_name_exists or user_name_exists:
+ returncode = FileSystemImageSandbox._USER_OR_GROUP_NAME_EXISTS
+
exception = subprocess.CalledProcessError(
- returncode=FileSystemImageSandbox._USER_OR_GROUP_ID_EXISTS,
+ returncode=returncode,
cmd='some command',
output=None)
mock_check_call.side_effect = [
- None if gid_exists else exception,
- None if uid_exists else exception]
+ exception if gid_exists or group_name_exists else None,
+ exception if uid_exists or user_name_exists else None]
with temporary_dir() as d:
with mock.patch.object(
@@ -179,21 +267,39 @@ def assert_create_user_and_group(mock_check_call, gid_exists, uid_exists):
sandbox._create_user_and_group_in_taskfs()
assert len(mock_check_call.mock_calls) == 2
+ assert len(mock_verify.mock_calls) == 1
-MOCK_MESOS_DIRECTORY = '/some/path'
+@mock.patch('apache.aurora.executor.common.sandbox.' +
+ 'FileSystemImageSandbox._verify_user_match_in_taskfs')
+@mock.patch('subprocess.check_call')
+@mock.patch.dict(os.environ, {'MESOS_DIRECTORY': MOCK_MESOS_DIRECTORY})
+def test_uid_exists(mock_check_call, mock_verify):
+ assert_create_user_and_group(mock_check_call, mock_verify, False, True, False, False)
+
+
+@mock.patch('apache.aurora.executor.common.sandbox.' +
+ 'FileSystemImageSandbox._verify_group_match_in_taskfs')
+@mock.patch('subprocess.check_call')
+@mock.patch.dict(os.environ, {'MESOS_DIRECTORY': MOCK_MESOS_DIRECTORY})
+def test_gid_exists(mock_check_call, mock_verify):
+ assert_create_user_and_group(mock_check_call, mock_verify, True, False, False, False)
+@mock.patch('apache.aurora.executor.common.sandbox.' +
+ 'FileSystemImageSandbox._verify_user_match_in_taskfs')
@mock.patch('subprocess.check_call')
@mock.patch.dict(os.environ, {'MESOS_DIRECTORY': MOCK_MESOS_DIRECTORY})
-def test_uid_exists(mock_check_call):
- assert_create_user_and_group(mock_check_call, False, True)
+def test_user_name_exists(mock_check_call, mock_verify):
+ assert_create_user_and_group(mock_check_call, mock_verify, False, False, False, True)
+@mock.patch('apache.aurora.executor.common.sandbox.' +
+ 'FileSystemImageSandbox._verify_group_match_in_taskfs')
@mock.patch('subprocess.check_call')
@mock.patch.dict(os.environ, {'MESOS_DIRECTORY': MOCK_MESOS_DIRECTORY})
-def test_gid_exists(mock_check_call):
- assert_create_user_and_group(mock_check_call, True, False)
+def test_group_name_exists(mock_check_call, mock_verify):
+ assert_create_user_and_group(mock_check_call, mock_verify, True, False, True, False)
@mock.patch('subprocess.check_call')