Skip to content

Instantly share code, notes, and snippets.

@smothiki
Created May 13, 2015 15:22
Show Gist options
  • Save smothiki/8a6e002da1c0e459f9a9 to your computer and use it in GitHub Desktop.
Save smothiki/8a6e002da1c0e459f9a9 to your computer and use it in GitHub Desktop.
import re
import time
import logging
import os
from django.conf import settings
from docker import Client
from .states import JobState
logger = logging.getLogger(__name__)
def log_event(msg, level=logging.INFO):
# controller needs to know which app this log comes from
logger.log(level, "{}: {}".format("swarm", msg))
with open(os.path.join(settings.DEIS_LOG_DIR, "swarm" + '.log'), 'a') as f:
msg = "{} deis[api]: {}\n".format(time.strftime(settings.DEIS_DATETIME_FORMAT),msg)
f.write(msg.encode('utf-8'))
MATCH = re.compile(
r'(?P<app>[a-z0-9-]+)_?(?P<version>v[0-9]+)?\.?(?P<c_type>[a-z-_]+)?.(?P<c_num>[0-9]+)')
class SwarmClient(object):
def __init__(self, target, auth, options, pkey):
self.target = settings.SWARM_HOST
# single global connection
self.registry = settings.REGISTRY_HOST + ':' + settings.REGISTRY_PORT
self.docker_cli = Client("tcp://{}:2395".format(self.target),
timeout=1200, version='1.17')
def create(self, name, image, command='', template=None, **kwargs):
"""Create a container"""
cimage = self.registry + '/' + image
affinity = "affinity:container!=~/{}*/".format(re.split(r'_v\d.', name)[0])
l = locals().copy()
l.update(re.match(MATCH, name).groupdict())
mem = kwargs.get('memory', {}).get(l['c_type'])
if mem:
mem = mem.lower()
if mem[-2:-1].isalpha() and mem[-1].isalpha():
mem = mem[:-1]
cpu = kwargs.get('cpu', {}).get(l['c_type'])
try :
self.docker_cli.create_container(image=cimage, name=name,
command=command.encode('utf-8'), mem_limit=mem,
cpu_shares=cpu,
environment=[affinity],
host_config={'PublishAllPorts': True})
except Exception as err:
log_event(str(err.message)+" "+str(err.explanation), logging.ERROR)
def start(self, name):
"""
Start a container
"""
self.docker_cli.start(name)
def stop(self, name):
"""
Stop a container
"""
self.docker_cli.stop(name)
def destroy(self, name):
"""
Destroy a container
"""
self.stop(name)
self.docker_cli.remove_container(name)
def run(self, name, image, entrypoint, command):
"""
Run a one-off command
"""
cimage = self.registry + '/' + image
# use affinity for nodes that already have the image
affinity = "affinity:image==~{}".format(cimage)
self.docker_cli.create_container(image=cimage, name=name,
command=command.encode('utf-8'),
environment=[affinity],
entrypoint=[entrypoint])
time.sleep(2)
self.start(name)
rc = 0
while (True):
if self._get_container_state(name) == JobState.created:
break
time.sleep(1)
try:
output = self.docker_cli.logs(name)
return rc, output
except:
rc = 1
return rc, output
def _get_container_state(self, name):
try:
if self.docker_cli.inspect_container(name)['State']['Running']:
return JobState.up
else:
return JobState.created
except:
return JobState.destroyed
def state(self, name):
try:
for _ in range(30):
return self._get_container_state(name)
time.sleep(1)
# FIXME (smothiki): should be able to send JobState.crashed
except KeyError:
return JobState.error
except RuntimeError:
return JobState.destroyed
def attach(self, name):
"""
Attach to a job's stdin, stdout and stderr
"""
raise NotImplementedError
def _get_hostname(self, application_name):
hostname = settings.UNIT_HOSTNAME
if hostname == 'default':
return ''
elif hostname == 'application':
# replace underscore with dots, since underscore is not valid in DNS hostnames
dns_name = application_name.replace('_', '.')
return dns_name
elif hostname == 'server':
raise NotImplementedError
else:
raise RuntimeError('Unsupported hostname: ' + hostname)
def _get_portbindings(self, image):
dictports = self.docker_cli.inspect_image(image)['ContainerConfig']['ExposedPorts']
for port, mapping in dictports.items():
dictports[port] = None
return dictports
def _get_ports(self, image):
dictports = self.docker_cli.inspect_image(image)['ContainerConfig']['ExposedPorts']
return [int(port.split('/')[0]) for port in dictports.iterkeys()]
SchedulerClient = SwarmClient
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment