-
-
Notifications
You must be signed in to change notification settings - Fork 32k
gh-95023: Added os.setns and os.unshare to easily switch between namespaces on Linux #95046
New is 8000 sue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 35 commits
0bdd8bc
3685a27
8f22740
5115c8a
8845a86
d7bb582
987613a
4c91413
7d23963
b7abf20
af74db5
5181126
3a37ac2
1386833
ae4b661
57b2c84
b2df7f7
b4a68b6
dc51d01
5a3cff5
1d45196
84c4b8c
b9d3a34
51c60d4
225e06b
fb64bb7
01d4af4
15e6d8b
375165b
7e2b44c
3ae952c
432d274
afa9a00
54c7bce
01713ec
a6bb345
1c0fb83
dac402a
ff7f961
cc44f01
58bc8a6
b14396e
50c4809
de7dd3d
5c1bbdd
29129d9
94883a4
3e365d2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2172,6 +2172,58 @@ def test_utime(self): | |
os.utime("path", dir_fd=0) | ||
|
||
|
||
class NamespacesTests(unittest.TestCase): | ||
"""Tests for os.unshare() and os.setns().""" | ||
|
||
@support.requires_subprocess() | ||
def subprocess(self, code): | ||
import subprocess | ||
with subprocess.Popen((sys.executable, '-c', code), | ||
stdout=subprocess.PIPE, | ||
stderr=subprocess.PIPE, | ||
encoding="utf-8" | ||
) as p: | ||
p.wait() | ||
return ( | ||
p.returncode, | ||
tuple(p.stdout), | ||
tuple(p.stderr), | ||
) | ||
|
||
@unittest.skipUnless(hasattr(os, 'unshare'), 'needs os.unshare()') | ||
@unittest.skipUnless(hasattr(os, 'setns'), 'needs os.setns()') | ||
@unittest.skipUnless(os.path.exists('/proc/self/ns/uts'), 'need /proc/self/ns/uts') | ||
@support.requires_linux_version(3, 0, 0) | ||
def test_unshare_setns(self): | ||
rc, out, err = self.subprocess("""if 1: | ||
noamcohen97 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
import os | ||
import sys | ||
fd = os.open('/proc/self/ns/uts', os.O_RDONLY) | ||
try: | ||
print(os.readlink('/proc/self/ns/uts')) | ||
os.unshare(os.CLONE_NEWUTS) | ||
print(os.readlink('/proc/self/ns/uts')) | ||
os.setns(fd, os.CLONE_NEWUTS) | ||
print(os.readlink('/proc/self/ns/uts')) | ||
except OSError as e: | ||
sys.stderr.write(str(e.errno)) | ||
sys.exit(2) | ||
finally: | ||
os.close(fd) | ||
""") | ||
|
||
if rc == 2: | ||
e = int(err[0]) | ||
self.assertIn(e, (errno.EPERM, errno.EINVAL, errno.ENOSPC, errno.ENOSYS)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would prefer to move these checks inside the child process code. I don't think that skipping the test if unshare() or setns() fails matters. Just exit the child process early with a success (exit code 0, well, just exit) if you get one of these errors, no? If the child process must always succeed, you can use test.suppot.script_helper.assert_python_ok() which captures stdout and stderr and raises an exception with all data if the process fails. Maybe it would make sense to add a ENOSPC is expected on unshare() if we exceed some limits on namespaces? If it can only happen on unshare(), maybe add a try/except only on this function call? Why is EINVAL expected? Can it be raised if there is a bug in the test? Or can it be raised depending on the kernel configuration? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool! did not know about There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
self.skipTest(f"could not call os.unshare / os.setns [Errno {e}].") | ||
|
||
self.assertEqual(rc, 0) | ||
self.assertEqual(err, ()) | ||
original, new, back = out | ||
self.assertNotEqual(original, new) | ||
self.assertEqual(original, back) | ||
noamcohen97 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
def tearDownModule(): | ||
support.reap_children() | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Implement :func:`os.setns` and :func:`os.unshare` for Linux. Patch by Noam Cohen. |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Uh oh!
There was an error while loading. Please reload this page.