Beispiel #1
0
def container_log(cid):
    stderr = request.args.get('stderr', type=int, default=0)
    stdout = request.args.get('stdout', type=int, default=0)
    tail = request.args.get('tail', type=int, default=10)

    # docker client's argument
    if tail == 0:
        tail = 'all'

    ws = request.environ['wsgi.websocket']
    container = Container.get_by_container_id(cid)
    if not container:
        ws.close()
        _log.info('Container %s not found, close websocket' % cid)
        return 'websocket closed'
    try:
        client = get_docker_client(container.host.addr)
        for line in client.logs(cid,
                                stream=True,
                                stderr=bool(stderr),
                                stdout=bool(stdout),
                                tail=tail):
            ws.send(line)
    except geventwebsocket.WebSocketError, e:
        _log.exception(e)
Beispiel #2
0
def create_host():
    """为了文件, 只好不用json了"""
    addr = request.form.get('addr', default='')
    ip = addr.split(':', 1)[0]
    podname = request.form.get('podname', default='')
    is_public = request.form.get('is_public', default=False, type=bool)
    if not (addr and podname):
        abort(400, 'Bad addr or podname: addr="{}", podname="{}"'.format(addr, podname))

    pod = Pod.get_by_name(podname)
    if not pod:
        abort(400, 'Pod {} not found'.format(podname))

    # 存证书, 没有就算了
    certs = ['ca', 'cert', 'key']
    if all(k in request.files for k in certs):
        certs_contents = tuple(request.files[f].read() for f in certs)
        save_docker_certs(ip, *certs_contents)

    try:
        client = get_docker_client(addr, force_flush=True)
        info = client.info()
    except Exception as e:
        abort(400, 'Docker daemon error on host %s, error: %s' % (addr, e.message))

    if not Host.create(pod, addr, info['Name'], info['ID'], info['NCPU'],
                       info['MemTotal'], is_public=is_public):
        abort(400, 'Error while creating host')

    return 201, DEFAULT_RETURN_VALUE
Beispiel #3
0
def clean_image():
    for host in Host.query.all():
        try:
            client = get_docker_client(host.addr)
        except:
            print 'can not connect, maybe tls problem.'
            continue

        try:
            client.ping()
        except:
            print 'client not connected, skipped.'
            continue

        for c in client.containers(all=True):
            if need_to_delete_container(c['Image'], c['Names'][0]):
                try:
                    client.remove_container(c['Id'])
                    print 'container %s cleaned.' % c['Names'][0]
                except:
                    print 'container %s still running.' % c['Names'][0]

        for i in client.images():
            try:
                client.remove_image(i['Id'])
                print 'image %s cleaned.' % i['RepoTags'][0]
            except:
                print 'conflict, image %s is still being used.' % i['RepoTags'][0]

        print 'host %s cleaned.' % host.ip
Beispiel #4
0
def push_image(host, version):
    client = get_docker_client(host.addr)
    appname = version.app.name
    repo = '{0}/eru/{1}'.format(config.DOCKER_REGISTRY, appname)
    rev = version.short_sha
    return client.push(repo,
                       tag=rev,
                       stream=True,
                       insecure_registry=config.DOCKER_REGISTRY_INSECURE)
Beispiel #5
0
def remove_container_by_cid(cids, host):
    client = get_docker_client(host.addr)
    for cid in cids:
        try:
            __stop_container(client, cid)
            client.remove_container(cid)
        except docker.errors.APIError as e:
            if 'no such id' in str(e).lower():
                _log.info('%s not found, just delete it' % cid)
                continue
            raise
Beispiel #6
0
def remove_container_by_cid(cids, host):
    client = get_docker_client(host.addr)
    for cid in cids:
        try:
            __stop_container(client, cid)
            client.remove_container(cid)
        except docker.errors.APIError as e:
            if 'no such id' in str(e).lower():
                _log.info('%s not found, just delete it' % cid)
                continue
            raise
Beispiel #7
0
def build_image(host, version, base, file_path=None):
    """
    用 host 机器, 以 base 为基础镜像, 为 version 构建
    一个稍后可以运行的镜像.
    """
    client = get_docker_client(host.addr)
    appname = version.app.name
    repo = '{0}/{1}'.format(config.DOCKER_REGISTRY, appname)
    tag = '{0}:{1}'.format(repo, version.short_sha)

    with build_image_environment(version, base, file_path) as build_path:
        return client.build(path=build_path, rm=True, forcerm=True, tag=tag)
Beispiel #8
0
def build_image(host, version, base, file_path=None):
    """
    用 host 机器, 以 base 为基础镜像, 为 version 构建
    一个稍后可以运行的镜像.
    """
    client = get_docker_client(host.addr)
    appname = version.app.name
    repo = '{0}/{1}'.format(config.DOCKER_REGISTRY, appname)
    tag = '{0}:{1}'.format(repo, version.short_sha)

    with build_image_environment(version, base, file_path) as build_path:
        return client.build(path=build_path, rm=True, forcerm=True, tag=tag)
Beispiel #9
0
def remove_host_containers(containers, host):
    """删除这个host上的这些容器"""
    client = get_docker_client(host.addr)
    for c in containers:
        try:
            __stop_container(client, c.container_id)
            client.remove_container(c.container_id)
        except docker.errors.APIError as e:
            if 'no such id' in str(e).lower():
                _log.info('%s not found, just delete it' % c.container_id)
                continue
            raise
Beispiel #10
0
def remove_host_containers(containers, host):
    """删除这个host上的这些容器"""
    client = get_docker_client(host.addr)
    for c in containers:
        try:
            __stop_container(client, c.container_id)
            client.remove_container(c.container_id)
        except docker.errors.APIError as e:
            if 'no such id' in str(e).lower():
                _log.info('%s not found, just delete it' % c.container_id)
                continue
            raise
Beispiel #11
0
def remove_image(version, host):
    """在host上删除掉version的镜像"""
    client = get_docker_client(host.addr)
    appconfig = version.appconfig
    appname = appconfig.appname
    image = '{0}/{1}:{2}'.format(config.DOCKER_REGISTRY, appname, version.short_sha)
    try:
        client.remove_image(image)
    except docker.errors.APIError as e:
        if 'no such image' in str(e).lower():
            _log.info('%s not found, just delete it' % image)
        else:
            raise
Beispiel #12
0
def remove_image(version, host):
    """在host上删除掉version的镜像"""
    client = get_docker_client(host.addr)
    appconfig = version.appconfig
    appname = appconfig.appname
    image = '{0}/{1}:{2}'.format(config.DOCKER_REGISTRY, appname,
                                 version.short_sha)
    try:
        client.remove_image(image)
    except docker.errors.APIError as e:
        if 'no such image' in str(e).lower():
            _log.info('%s not found, just delete it' % image)
        else:
            raise
Beispiel #13
0
def container_log(cid):
    stderr = request.args.get('stderr', type=int, default=0)
    stdout = request.args.get('stdout', type=int, default=0)
    tail = request.args.get('tail', type=int, default=10)

    # docker client's argument
    if tail == 0:
        tail = 'all'

    ws = request.environ['wsgi.websocket']
    container = Container.get_by_container_id(cid)
    if not container:
        ws.close()
        _log.info('Container %s not found, close websocket' % cid)
        return 'websocket closed'
    try:
        client = get_docker_client(container.host.addr)
        for line in client.logs(cid, stream=True, stderr=bool(stderr), stdout=bool(stdout), tail=tail):
            ws.send(line)
    except geventwebsocket.WebSocketError, e:
        _log.exception(e)
Beispiel #14
0
def push_image(host, version):
    client = get_docker_client(host.addr)
    appname = version.app.name
    repo = '{0}/eru/{1}'.format(config.DOCKER_REGISTRY, appname)
    rev = version.short_sha
    return client.push(repo, tag=rev, stream=True, insecure_registry=config.DOCKER_REGISTRY_INSECURE)
Beispiel #15
0
def execute_container(host, container_id, cmd, stream=False):
    """在容器里跑一个命令, stream的话返回一个generator"""
    client = get_docker_client(host.addr)
    exec_id = client.exec_create(container_id, cmd, stream=stream)
    return client.exec_start(exec_id)
Beispiel #16
0
def create_one_container(host, version, entrypoint, env='prod', cores=None,
                         ports=None, args=None, cpu_shares=1024, image='',
                         need_network=False):
    # raw方式有些设定不同
    is_raw = bool(image)

    if cores is None:
        cores = []
    if ports is None:
        ports = []
    if args is None:
        args = []

    client = get_docker_client(host.addr)
    local_images = {r['RepoTags'][0] for r in client.images()}

    appconfig = version.appconfig
    appname = appconfig.appname
    entry = appconfig.entrypoints[entrypoint]
    envconfig = version.get_resource_config(env)
    # replace $port1...
    cmd = replace_ports(entry['cmd'], ports)
    # add extend arguments
    cmd = cmd + ' '.join([''] + args)
    if not is_raw:
        starter = 'launcheroot' if entry.get('privileged', '') else 'launcher'
        network = 'network' if need_network else 'nonetwork'
        cmd = '/usr/local/bin/%s %s %s' % (starter, network, cmd)

    network_mode = entry.get('network_mode', config.DOCKER_NETWORK_MODE)
    mem_limit = entry.get('mem_limit', 0)
    restart_policy = {'MaximumRetryCount': 3, 'Name': entry.get('restart', 'no')}  # could be no/always/on-failure

    # raw 模式下可以选择暴露端口
    def get_ports(expose):
        inport, hostport = expose.split(':')
        return int(inport), int(hostport)

    exposes = [get_ports(expose) for expose in entry.get('exposes', [])]
    exposed_ports = None
    port_bindings = None
    if is_raw and exposes:
        exposed_ports = [p for p, _ in exposes]
        port_bindings = dict(exposes)

    if not image:
        image = '{0}/{1}:{2}'.format(config.DOCKER_REGISTRY, appname, version.short_sha)

    if image not in local_images:
        repo, tag = image.split(':', 1)
        for line in client.pull(repo, tag, stream=True, insecure_registry=config.DOCKER_REGISTRY_INSECURE):
            _log.info(line)

    env_dict = {
        'APP_NAME': appname,
        'ERU_RUNENV': env.upper(),
        'ERU_POD': host.pod.name,
        'ERU_HOST': host.name,
    }
    env_dict.update(envconfig.to_env_dict())

    volumes = ['/writable-proc/sys']
    volumes.extend(appconfig.get('volumes', []))

    binds = {'/proc/sys': {'bind': '/writable-proc/sys', 'ro': False}}
    binds.update(appconfig.get('binds', {}))

    if config.ERU_CONTAINER_PERMDIR and entry.get('permdir', ''):
        permdir = config.ERU_CONTAINER_PERMDIR % appname
        env_dict['ERU_PERMDIR'] = permdir
        volumes.append(permdir)
        binds[config.ERU_HOST_PERMDIR % appname] = {'bind': permdir, 'ro': False}

    extra_hosts = entry.get('hosts', None)

    # container name: {appname}_{entrypoint}_{ident_id}
    container_name = '_'.join([appname, entrypoint, gen_salt(6)])
    # cpuset: '0,1,2,3'
    cpuset = ','.join([c.label for c in cores])
    # host_config, include log_config
    host_config = client.create_host_config(
        binds=binds,
        network_mode=network_mode,
        log_config=LogConfig(type=config.DOCKER_LOG_DRIVER),
        ulimits=[Ulimit(name='nofile', soft=65535, hard=65535)],
        restart_policy=restart_policy,
        mem_limit=mem_limit,
        port_bindings=port_bindings,
        extra_hosts=extra_hosts,
    )
    container = client.create_container(
        image=image,
        command=cmd,
        environment=env_dict,
        name=container_name,
        cpuset=cpuset,
        working_dir=None if is_raw else '/%s' % appname,
        network_disabled=config.DOCKER_NETWORK_DISABLED,
        volumes=volumes,
        host_config=host_config,
        cpu_shares=cpu_shares,
        ports=exposed_ports,
    )
    container_id = container['Id']

    client.start(container=container_id)
    return container_id, container_name
Beispiel #17
0
def pull_image(host, repo, tag):
    client = get_docker_client(host.addr)
    return client.pull(repo, tag=tag, stream=True, insecure_registry=config.DOCKER_REGISTRY_INSECURE)
Beispiel #18
0
def pull_image(host, repo, tag):
    client = get_docker_client(host.addr)
    return client.pull(repo,
                       tag=tag,
                       stream=True,
                       insecure_registry=config.DOCKER_REGISTRY_INSECURE)
Beispiel #19
0
def stop_containers(containers, host):
    """停止这个host上的这些容器"""
    client = get_docker_client(host.addr)
    for c in containers:
        __stop_container(client, c.container_id)
Beispiel #20
0
def start_containers(containers, host):
    """启动这个host上的这些容器"""
    client = get_docker_client(host.addr)
    for c in containers:
        client.start(c.container_id)
Beispiel #21
0
def execute_container(host, container_id, cmd, stream=False):
    """在容器里跑一个命令, stream的话返回一个generator"""
    client = get_docker_client(host.addr)
    exec_id = client.exec_create(container_id, cmd, stream=stream)
    return client.exec_start(exec_id)
Beispiel #22
0
def stop_containers(containers, host):
    """停止这个host上的这些容器"""
    client = get_docker_client(host.addr)
    for c in containers:
        __stop_container(client, c.container_id)
Beispiel #23
0
def create_one_container(host,
                         version,
                         entrypoint,
                         env='prod',
                         cores=None,
                         ports=None,
                         args=None,
                         cpu_shares=1024,
                         image='',
                         need_network=False):
    # raw方式有些设定不同
    is_raw = bool(image)

    if cores is None:
        cores = []
    if ports is None:
        ports = []
    if args is None:
        args = []

    client = get_docker_client(host.addr)
    local_images = {r['RepoTags'][0] for r in client.images()}

    appconfig = version.appconfig
    appname = appconfig.appname
    entry = appconfig.entrypoints[entrypoint]
    envconfig = version.get_resource_config(env)
    # replace $port1...
    cmd = replace_ports(entry['cmd'], ports)
    # add extend arguments
    cmd = cmd + ' '.join([''] + args)
    if not is_raw:
        starter = 'launcheroot' if entry.get('privileged', '') else 'launcher'
        network = 'network' if need_network else 'nonetwork'
        cmd = '/usr/local/bin/%s %s %s' % (starter, network, cmd)

    network_mode = entry.get('network_mode', config.DOCKER_NETWORK_MODE)
    mem_limit = entry.get('mem_limit', 0)
    restart_policy = {
        'MaximumRetryCount': 3,
        'Name': entry.get('restart', 'no')
    }  # could be no/always/on-failure

    # raw 模式下可以选择暴露端口
    def get_ports(expose):
        inport, hostport = expose.split(':')
        return int(inport), int(hostport)

    exposes = [get_ports(expose) for expose in entry.get('exposes', [])]
    exposed_ports = None
    port_bindings = None
    if is_raw and exposes:
        exposed_ports = [p for p, _ in exposes]
        port_bindings = dict(exposes)

    if not image:
        image = '{0}/{1}:{2}'.format(config.DOCKER_REGISTRY, appname,
                                     version.short_sha)

    if image not in local_images:
        repo, tag = image.split(':', 1)
        for line in client.pull(
                repo,
                tag,
                stream=True,
                insecure_registry=config.DOCKER_REGISTRY_INSECURE):
            _log.info(line)

    env_dict = {
        'APP_NAME': appname,
        'ERU_RUNENV': env.upper(),
        'ERU_POD': host.pod.name,
        'ERU_HOST': host.name,
    }
    env_dict.update(envconfig.to_env_dict())

    volumes = ['/writable-proc/sys']
    volumes.extend(appconfig.get('volumes', []))

    binds = {'/proc/sys': {'bind': '/writable-proc/sys', 'ro': False}}
    binds.update(appconfig.get('binds', {}))

    if config.ERU_CONTAINER_PERMDIR and entry.get('permdir', ''):
        permdir = config.ERU_CONTAINER_PERMDIR % appname
        env_dict['ERU_PERMDIR'] = permdir
        volumes.append(permdir)
        binds[config.ERU_HOST_PERMDIR % appname] = {
            'bind': permdir,
            'ro': False
        }

    extra_hosts = entry.get('hosts', None)

    # container name: {appname}_{entrypoint}_{ident_id}
    container_name = '_'.join([appname, entrypoint, gen_salt(6)])
    # cpuset: '0,1,2,3'
    cpuset = ','.join([c.label for c in cores])
    # host_config, include log_config
    host_config = client.create_host_config(
        binds=binds,
        network_mode=network_mode,
        log_config=LogConfig(type=config.DOCKER_LOG_DRIVER),
        ulimits=[Ulimit(name='nofile', soft=65535, hard=65535)],
        restart_policy=restart_policy,
        mem_limit=mem_limit,
        port_bindings=port_bindings,
        extra_hosts=extra_hosts,
    )
    container = client.create_container(
        image=image,
        command=cmd,
        environment=env_dict,
        name=container_name,
        cpuset=cpuset,
        working_dir=None if is_raw else '/%s' % appname,
        network_disabled=config.DOCKER_NETWORK_DISABLED,
        volumes=volumes,
        host_config=host_config,
        cpu_shares=cpu_shares,
        ports=exposed_ports,
    )
    container_id = container['Id']

    client.start(container=container_id)
    return container_id, container_name
Beispiel #24
0
def start_containers(containers, host):
    """启动这个host上的这些容器"""
    client = get_docker_client(host.addr)
    for c in containers:
        client.start(c.container_id)