This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

TLB bugfixes (#135)

* Don't colorize logs when logging to a file

* VNCEnv configure.required=True

Avoids obscure crash if user forgets to configure

* Fix merge

* Better errors for invalid remotes

Fixes #114

* Support local remotes from inside a container

* Fix formatting

* Fix formatting

* Fix formatting
  • Loading branch information...
nottombrown committed Feb 1, 2017
1 parent 1ca7c58 commit a5ea649ddcda587ad84e67c38a1228e6f193aada
View
@@ -24,19 +24,19 @@ run ``docker ps`` and get something like this:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
How to start a remote
=====================
There are currently three ways to start a remote:
- Create an **automatic local remote** using ``env.configure(remotes=1)``.
In this case, ``universe`` automatically creates a remote locally by spinning
up a docker container for you.
- Create a **manual remote** by spinning up your own Docker container,
locally or on a server you control.
- Create a **starter cluster** in AWS, which will automatically provide you
with cloud-hosted remotes.
@@ -64,6 +64,25 @@ container and start 1 copy of it locally.
env.render()
Agents inside Docker
~~~~~~~~~~~~~~~~~~~~
If you're running your agent inside a Docker container, it can still create automatic remotes by connecting
to the docker daemon on the host. To do this, mount the docker binary and socket inside the agent container like this:
.. code:: shell
$ docker run --privileged \
-v /usr/bin/docker:/usr/bin/docker \
-v /root/.docker:/root/.docker \
-v /var/run/docker.sock:/var/run/docker.sock \
-e DOCKER_NET_HOST=172.17.0.1 \
... \
my/agent:latest
The Universe remote will use ``$DOCKER_NET_HOST`` when connecting to the VNC and rewarder ports.
Manual remotes
--------------
@@ -109,21 +128,21 @@ VNC compression settings
-----------------------------------------------
The VNC connection supports multiple compression settings that control the tradeoff
between a fast but highly compressed, low quality data stream and slow, uncompressed
data stream. These can be configured by using the ``vnc_kwargs`` argument to
between a fast but highly compressed, low quality data stream and slow, uncompressed
data stream. These can be configured by using the ``vnc_kwargs`` argument to
``env.configure``. The default arguments are:
.. code:: python
env.configure(vnc_kwargs={'encoding':'tight', 'fine_quality_level':50, 'subsample_level':2})
Here, ``tight`` is a lossy encoding that uses JPEG for compression. We also support ``zrle`` instead, which is lossless.
The ``fine_quality_level`` controls the compression strength from high compression / low quality (0) to low compression / high quality (100).
The ``fine_quality_level`` controls the compression strength from high compression / low quality (0) to low compression / high quality (100).
For ``subsample_level``, 0 is highest quality, 2 is low quality and 3 is greyscale. You can investigate the effects
of many of these options on the visual fidelity by connecting to an environment using TurboVNC, which allows you to
of many of these options on the visual fidelity by connecting to an environment using TurboVNC, which allows you to
tune these settings in the user interface.
Note that the codecs always operate on deltas of the screen, so if large portions of your screen are not changing then
Note that the codecs always operate on deltas of the screen, so if large portions of your screen are not changing then
you might be able to afford higher quality settings. Conversely, if you're playing a racing game that takes up a large
portion of the screen you should be more worried about bandwidth. The call to ``step`` is asynchronous with respect to
new frames arriving, so if the connection is too slow the environments will lag.
@@ -146,7 +165,7 @@ Once your stack on AWS is ready, run `starter-cluster` to start your environment
or example, the follow will start two flashgames remotes:
.. code:: shell
$ pip install -r bin/starter-cluster-requirements.txt
$ bin/starter-cluster -v start -s OpenAI-Universe -i my-ec2-key.pem -r flashgames -n 2
Creating network "flashgames_default" with the default driver
@@ -164,13 +183,13 @@ Now you can pass the IP address and ports for your remotes to your agent,
as was described in the previous section on manual remotes. For example:
.. code:: shell
$ python bin/random_agent.py -e flashgames.DuskDrive-v0 -r vnc://54.245.154.123:5013+5015,54.245.154.123:5006+5008
Running ``bin/starter-cluster start`` again will restart your remotes. To stop them, run:
.. code:: shell
$ bin/starter-cluster stop -s OpenAI-Universe -i my-ec2-key.pem -r flashgames
Stopping flashgames_flashgames-1_1 ... done
Stopping flashgames_flashgames-0_1 ... done
@@ -194,7 +213,7 @@ Scaling Up
If you encounter the following
.. code:: shell
$ bin/starter-cluster -v start -s OpenAI-Universe -i my-ec2-key.pem -r flashgames -n 2
Creating network "flashgames_default" with the default driver
Pulling flashgames-0 (quay.io/openai/universe.flashgames:0.19.36)...
@@ -244,5 +263,3 @@ The configuration for the runtimes is defined in
and the specific version number tags for the corresponding Docker
images are specified in
`runtimes.yml <https://github.com/openai/universe/blob/master/universe/runtimes.yml>`__.
View
@@ -105,6 +105,7 @@ class VNCEnv(vectorized.Env):
'semantics.autoreset': True,
'video.frames_per_second' : 60,
'runtime.vectorized': True,
'configure.required': True,
}
def __init__(self, fps=None, probe_key=None):
@@ -3,6 +3,7 @@
from __future__ import unicode_literals
import sys
import os
import threading
from collections import namedtuple
@@ -18,7 +19,8 @@
from universe.remotes.compose.utils import split_buffer
def build(containers, service_names, **kwargs):
presenters = build_log_presenters(service_names, False)
monochrome = not os.isatty(1)
presenters = build_log_presenters(service_names, monochrome)
printer = LogPrinter(containers, presenters, **kwargs)
printer.start()
@@ -110,15 +110,27 @@ def healthcheck(self, instances):
)
def get_client():
"""
Set DOCKER_HOST (and probably DOCKER_TLS_VERIFY and DOCKER_CERT_PATH) to connect to a docker instance through TCP.
Leave DOCKER_HOST unset and it will use the default, typically unix:/var/run/docker.sock
It also needs to know how to connect to ports on the docker container after creating it.
Set DOCKER_NET_HOST to provide an IP address to connect to the VNC ports on
otherwise if DOCKER_HOST has a hostname, it will connect to the VNC ports using that name.
otherwise it connects using localhost
"""
info = {}
host = os.environ.get('DOCKER_HOST')
net_host = os.environ.get('DOCKER_NET_HOST')
client_api_version = os.environ.get('DOCKER_API_VERSION')
if not client_api_version:
client_api_version = "auto"
# IP to use for started containers
if host:
if net_host:
info['host'] = net_host
elif host:
info['host'] = urlparse.urlparse(host).netloc.split(':')[0]
else:
info['host'] = 'localhost'
@@ -107,6 +107,8 @@ def parse_remotes(remotes):
all_vnc = True
remote, rewarder_port = remote.split('+')
if not re.match(r'^[0-9]+$', rewarder_port):
raise error.Error('Rewarder port must be an integer, not `{}`: {}'.format(rewarder_port, remotes))
rewarder_port = int(rewarder_port)
else:
if all_vnc == True:
@@ -121,6 +123,8 @@ def parse_remotes(remotes):
all_rewarder = True
remote, vnc_port = remote.split(':')
if not re.match(r'^[0-9]+$', vnc_port):
raise error.Error('VNC port must be an integer, not `{}`: {}'.format(vnc_port, remotes))
vnc_port = int(vnc_port)
else:
if all_rewarder == True:
@@ -131,6 +135,8 @@ def parse_remotes(remotes):
all_rewarder = False
host = remote
if not re.match(r'^[-a-zA-Z0-9\.\_]+$', host):
raise error.Error('Invalid hostname for remote: {}'.format(remotes))
if rewarder_port is not None:
rewarder_address = '{}:{}'.format(host, rewarder_port)

0 comments on commit a5ea649

Please sign in to comment.