in support/retro_contest/docker.py [0:0]
def run(game, state=None, entry=None, **kwargs):
client = docker.from_env()
remote_command = ['retro-contest-remote', 'run', game, *([state] if state else []), '-b', 'results/bk2', '-m', 'results']
remote_name = kwargs.get('remote_env', 'openai/retro-env')
agent_command = []
agent_name = kwargs.get('agent', 'agent')
datamount = {}
if kwargs.get('wallclock_limit') is not None:
remote_command.extend(['-W', str(kwargs['wallclock_limit'])])
if kwargs.get('timestep_limit') is not None:
remote_command.extend(['-T', str(kwargs['timestep_limit'])])
if kwargs.get('discrete_actions'):
remote_command.extend(['-D'])
if entry:
agent_command.append(entry)
if kwargs.get('entry_args'):
agent_command.extend(kwargs['entry_args'])
rand = ''.join(random.sample('abcdefghijklmnopqrstuvwxyz0123456789', 8))
volname = 'retro-contest-tmp%s' % rand
datamount = {}
agentmount = {}
if kwargs.get('resultsdir'):
results = os.path.realpath(kwargs['resultsdir'])
datamount[convert_path(results)] = {'bind': '/root/compo/results'}
os.makedirs(results, exist_ok=True)
else:
results = None
if kwargs.get('agentdir'):
agentdir = os.path.realpath(kwargs['agentdir'])
agentmount[convert_path(agentdir)] = {'bind': '/root/compo/out'}
os.makedirs(agentdir, exist_ok=True)
container_kwargs = {'detach': True, 'network_disabled': True}
remote_kwargs = dict(container_kwargs)
agent_kwargs = dict(container_kwargs)
if kwargs.get('agent_shm'):
agent_kwargs['shm_size'] = kwargs['agent_shm']
bridge = client.volumes.create(volname, driver='local', driver_opts={'type': 'tmpfs', 'device': 'tmpfs'})
if kwargs.get('use_host_data'):
remote_command = [remote_command[0], '--data-dir', '/root/data', *remote_command[1:]]
datamount[convert_path(data_path())] = {'bind': '/root/data', 'mode': 'ro'}
try:
remote = client.containers.run(remote_name, remote_command,
volumes={volname: {'bind': '/root/compo/tmp'},
**datamount},
**remote_kwargs)
except:
bridge.remove()
raise
try:
agent = client.containers.run(agent_name, agent_command,
volumes={volname: {'bind': '/root/compo/tmp'},
**agentmount},
runtime=kwargs.get('runtime', 'nvidia'),
**agent_kwargs)
except:
remote.kill()
remote.remove()
bridge.remove()
raise
a_exit = None
r_exit = None
if not kwargs.get('quiet'):
log_thread = LogThread(agent)
log_thread.start()
try:
while True:
try:
a_exit = agent.wait(timeout=5)
break
except requests.exceptions.RequestException:
pass
try:
r_exit = remote.wait(timeout=5)
break
except requests.exceptions.RequestException:
pass
if a_exit is None:
try:
a_exit = agent.wait(timeout=10)
except requests.exceptions.RequestException:
agent.kill()
if r_exit is None:
try:
r_exit = remote.wait(timeout=10)
except requests.exceptions.RequestException:
remote.kill()
except:
if a_exit is None:
try:
a_exit = agent.wait(timeout=1)
except:
try:
agent.kill()
except docker.errors.APIError:
pass
if r_exit is None:
try:
r_exit = remote.wait(timeout=1)
except:
try:
remote.kill()
except docker.errors.APIError:
pass
raise
finally:
if isinstance(a_exit, dict):
a_exit = a_exit.get('StatusCode')
if isinstance(r_exit, dict):
r_exit = r_exit.get('StatusCode')
if not kwargs.get('quiet'):
log_thread.exit()
logs = {
'remote': (r_exit, remote.logs(stdout=True, stderr=False), remote.logs(stdout=False, stderr=True)),
'agent': (a_exit, agent.logs(stdout=True, stderr=False), agent.logs(stdout=False, stderr=True))
}
if results:
with open(os.path.join(results, 'remote-stdout.txt'), 'w') as f:
f.write(logs['remote'][1].decode('utf-8'))
with open(os.path.join(results, 'remote-stderr.txt'), 'w') as f:
f.write(logs['remote'][2].decode('utf-8'))
with open(os.path.join(results, 'agent-stdout.txt'), 'w') as f:
f.write(logs['agent'][1].decode('utf-8'))
with open(os.path.join(results, 'agent-stderr.txt'), 'w') as f:
f.write(logs['agent'][2].decode('utf-8'))
remote.remove()
agent.remove()
bridge.remove()
return logs