Skip to content

Commit

Permalink
Separate x11 from nvidia extension for use on non-nvidia platforms
Browse files Browse the repository at this point in the history
  • Loading branch information
tfoote committed Feb 25, 2019
1 parent ac3afc5 commit cea0680
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 30 deletions.
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
'pulse = rocker.extensions:PulseAudio',
'home = rocker.extensions:HomeDir',
'user = rocker.extensions:User',
'x11 = rocker.nvidia_extension:X11',
]
},
'author': 'Tully Foote',
Expand Down
68 changes: 41 additions & 27 deletions src/rocker/nvidia_extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,46 @@
from .core import RockerExtension


class X11(RockerExtension):
@staticmethod
def get_name():
return 'x11'

def __init__(self):
self.name = X11.get_name()
self._env_subs = None
self.xauth = '/tmp/.docker.xauth'

def get_docker_args(self, cliargs):
xauth = self.xauth
return " -e DISPLAY -e TERM \
-e QT_X11_NO_MITSHM=1 \
-e XAUTHORITY=%(xauth)s -v %(xauth)s:%(xauth)s \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-v /etc/localtime:/etc/localtime:ro" % locals()

def precondition_environment(self, cliargs):
xauth = self.xauth
display = os.getenv('DISPLAY')
# Make sure processes in the container can connect to the x server
# Necessary so gazebo can create a context for OpenGL rendering (even headless)
if not os.path.exists(self.xauth): #if [ ! -f $XAUTH ]
Path(self.xauth).touch()
# print("touched %s" % xauth)
cmd = 'xauth nlist %(display)s | sed -e \'s/^..../ffff/\' | xauth -f %(xauth)s nmerge -' % locals()
# print("runnning %s" % cmd)
try:
subprocess.check_call(cmd, shell=True)
except subprocess.CalledProcessError as ex:
print("Failed setting up XAuthority with command %s" % cmd)
raise ex

@staticmethod
def register_arguments(parser):
parser.add_argument(name_to_argument(X11.get_name()),
action='store_true',
help="Enable x11")


class Nvidia(RockerExtension):
@staticmethod
Expand All @@ -37,7 +77,6 @@ def get_name():
def __init__(self):
self._env_subs = None
self.name = Nvidia.get_name()
self.xauth = '/tmp/.docker.xauth'
self.supported_distros = ['Ubuntu']
self.supported_versions = ['16.04', '18.04']

Expand All @@ -47,7 +86,6 @@ def get_environment_subs(self, cliargs={}):
self._env_subs = {}
self._env_subs['user_id'] = os.getuid()
self._env_subs['username'] = getpass.getuser()
self._env_subs['DISPLAY'] = os.getenv('DISPLAY')

# non static elements test every time
build_detector_image()
Expand All @@ -73,33 +111,9 @@ def get_snippet(self, cliargs):
return em.expand(snippet, self.get_environment_subs(cliargs))

def get_docker_args(self, cliargs):
xauth = self.xauth
return " -e DISPLAY -e TERM \
-e QT_X11_NO_MITSHM=1 \
-e XAUTHORITY=%(xauth)s -v %(xauth)s:%(xauth)s \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-v /etc/localtime:/etc/localtime:ro \
--runtime=nvidia \
return " --runtime=nvidia \
--security-opt seccomp=unconfined" % locals()

def precondition_environment(self, cliargs):
xauth = self.xauth
display = os.getenv('DISPLAY')
# Make sure processes in the container can connect to the x server
# Necessary so gazebo can create a context for OpenGL rendering (even headless)
if not os.path.exists(self.xauth): #if [ ! -f $XAUTH ]
Path(self.xauth).touch()
# print("touched %s" % xauth)
cmd = 'xauth nlist %(display)s | sed -e \'s/^..../ffff/\' | xauth -f %(xauth)s nmerge -' % locals()
# print("runnning %s" % cmd)
try:
subprocess.check_call(cmd, shell=True)
except subprocess.CalledProcessError as ex:
print("Failed setting up XAuthority with command %s" % cmd)
raise ex
# import stat
# Path(xauth).chmod(stat.S_IROTH)

@staticmethod
def register_arguments(parser):
parser.add_argument(name_to_argument(Nvidia.get_name()),
Expand Down
62 changes: 59 additions & 3 deletions test/test_nvidia.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,62 @@
from rocker.core import get_docker_client
from test_extension import plugin_load_parser_correctly


class X11Test(unittest.TestCase):
@classmethod
def setUpClass(self):
client = get_docker_client()
self.dockerfile_tags = []
for distro_version in ['xenial', 'bionic']:
dockerfile = """
FROM ubuntu:%(distro_version)s
RUN apt-get update && apt-get install x11-utils -y && apt-get clean
CMD xdpyinfo
"""
dockerfile_tag = 'testfixture_%s_x11_validatw' % distro_version
iof = StringIO((dockerfile % locals()).encode())
im = client.build(fileobj = iof, tag=dockerfile_tag)
for e in im:
pass
#print(e)
self.dockerfile_tags.append(dockerfile_tag)

def setUp(self):
# Work around interference between empy Interpreter
# stdout proxy and test runner. empy installs a proxy on stdout
# to be able to capture the information.
# And the test runner creates a new stdout object for each test.
# This breaks empy as it assumes that the proxy has persistent
# between instances of the Interpreter class
# empy will error with the exception
# "em.Error: interpreter stdout proxy lost"
em.Interpreter._wasProxyInstalled = False

def test_nvidia_extension_basic(self):
plugins = list_plugins()
active_plugin = plugins['x11']
self.assertEqual(active_plugin.get_name(), 'x11')
self.assertTrue(plugin_load_parser_correctly(active_plugin))


def test_no_x11_xpdyinfo(self):
for tag in self.dockerfile_tags:
dig = DockerImageGenerator([], {}, tag)
self.assertEqual(dig.build(), 0)
self.assertNotEqual(dig.run(), 0)

def test_x11_xpdyinfo(self):
plugins = list_plugins()
desired_plugins = ['x11']
active_extensions = [e() for e in plugins.values() if e.get_name() in desired_plugins]
for tag in self.dockerfile_tags:
dig = DockerImageGenerator(active_extensions, {}, tag)
self.assertEqual(dig.build(), 0)
self.assertEqual(dig.run(), 0)


class NvidiaTest(unittest.TestCase):
@classmethod
def setUpClass(self):
Expand Down Expand Up @@ -63,10 +119,10 @@ def setUp(self):
def test_nvidia_extension_basic(self):
plugins = list_plugins()
nvidia_plugin = plugins['nvidia']
self.assertEqual(nvidia_plugin.get_name(), 'nvidia')
self.assertEqual(nvidia_plugin.get_name(), 'nvidia')
self.assertTrue(plugin_load_parser_correctly(nvidia_plugin))


def test_no_nvidia_glmark2(self):
for tag in self.dockerfile_tags:
dig = DockerImageGenerator([], {}, tag)
Expand All @@ -75,7 +131,7 @@ def test_no_nvidia_glmark2(self):

def test_nvidia_glmark2(self):
plugins = list_plugins()
desired_plugins = ['nvidia', 'user']
desired_plugins = ['x11', 'nvidia', 'user'] #TODO(Tfoote) encode the x11 dependency into the plugin and remove from test here
active_extensions = [e() for e in plugins.values() if e.get_name() in desired_plugins]
for tag in self.dockerfile_tags:
dig = DockerImageGenerator(active_extensions, {}, tag)
Expand Down

0 comments on commit cea0680

Please sign in to comment.