Пример #1
0
def create_private():
    data = request.get_json()
    pod, _, version = _get_instances(**data)

    ncore, nshare = pod.get_core_allocation(float(data['ncore']))
    ports = data.get('ports', [])
    args = data.get('args', [])
    strategy = data.get('strategy', 'average')

    callback_url = data.get('callback_url', '')
    if callback_url and not is_strict_url(callback_url):
        abort(400, 'callback_url must start with http:// or https://')

    ncontainer = int(data['ncontainer'])
    if not ncontainer:
        abort(400, 'ncontainer must be > 0')

    networks = [ipam.get_pool(n) for n in data.get('networks', [])]
    spec_ips = data.get('spec_ips', [])
    appconfig = version.appconfig

    entrypoint = data['entrypoint']
    if entrypoint not in appconfig.entrypoints:
        abort(400, 'Entrypoint %s not in app.yaml' % entrypoint)

    hostname = data.get('hostname', '')
    host = hostname and Host.get_by_name(hostname) or None

    task_ids, watch_keys = [], []
    host_cores = _get_strategy(strategy)(pod, ncontainer, ncore, nshare, host)
    if not host_cores:
        abort(400, 'Not enough core resources')

    for (host, container_count), cores in host_cores.iteritems():
        t = _create_task(
            version,
            host,
            container_count,
            cores,
            nshare,
            networks,
            ports,
            args,
            spec_ips,
            entrypoint,
            data['env'],
            image=data.get('image', ''),
            callback_url=callback_url,
        )
        if not t:
            continue

        host.occupy_cores(cores, nshare)
        task_ids.append(t.id)
        watch_keys.append(t.result_key)

    return {'tasks': task_ids, 'watch_keys': watch_keys}
Пример #2
0
def check_addr(addr):
    """addr is like 10.20.0.1/16 or 10.100.3.12/24"""
    try:
        interface = IPNetwork(addr)
    except AddrFormatError:
        abort(400, 'Not valid interface')
    net = ipam.get_pool(str(interface.cidr))
    if not net:
        abort(400, 'Interface not found')
    return {'available': interface.ip in net}
Пример #3
0
def create_public():
    data = request.get_json()
    pod, _, version = _get_instances(**data)

    ports = data.get('ports', [])
    args = data.get('args', [])

    callback_url = data.get('callback_url', '')
    if callback_url and not is_strict_url(callback_url):
        abort(400, 'callback_url must starts with http:// or https://')

    networks = [ipam.get_pool(n) for n in data.get('networks', [])]
    spec_ips = data.get('spec_ips', [])
    appconfig = version.appconfig

    ncontainer = int(data['ncontainer'])
    if not ncontainer:
        abort(400, 'ncontainer must be > 0')

    entrypoint = data['entrypoint']
    if entrypoint not in appconfig.entrypoints:
        abort(400, 'Entrypoint %s not in app.yaml' % entrypoint)

    task_ids, watch_keys = [], []
    hosts = pod.get_free_public_hosts(ncontainer)
    for host in itertools.islice(itertools.cycle(hosts), ncontainer):
        t = _create_task(
            version,
            host,
            1,
            {},
            0,
            networks,
            ports,
            args,
            spec_ips,
            data['entrypoint'],
            data['env'],
            image=data.get('image', ''),
            callback_url=callback_url,
        )
        if not t:
            continue
        task_ids.append(t.id)
        watch_keys.append(t.result_key)

    return {'tasks': task_ids, 'watch_keys': watch_keys}
Пример #4
0
def macvlan(id_or_name):
    host = _get_host(id_or_name)
    if request.method == 'GET':
        return host.list_vlans(g.start, g.limit)

    data = request.get_json()
    netname = data.get('network', '')
    network = ipam.get_pool(netname)
    if not network:
        abort(404, 'Network not found')

    vg = VLanGateway.get_by_host_and_network(host.id, network.id)
    if request.method == 'POST':
        return vg or network.acquire_gateway_ip(host)
    elif request.method == 'DELETE':
        if vg:
            vg.release()
        return DEFAULT_RETURN_VALUE
Пример #5
0
def bind_network(id_or_cid):
    c = _get_container(id_or_cid)

    data = request.get_json()
    appname = data['appname']

    if not c.is_alive:
        abort(404, 'Container %s not alive' % c.container_id)
    if c.appname != appname:
        abort(404, 'Container does not belong to app')
    if c.network_mode == 'host':
        abort(400, 'Container use host network mode')

    network_names = data.get('networks', [])
    networks = [ipam.get_pool(n) for n in network_names]
    if not networks:
        abort(400, 'network empty')

    cidrs = [n.cidr for n in networks if n]

    bind_container_ip(c, cidrs)
    return {'cidrs': cidrs}
Пример #6
0
def bind_network(id_or_cid):
    c = _get_container(id_or_cid)

    data = request.get_json()
    appname = data['appname']

    if not c.is_alive:
        abort(404, 'Container %s not alive' % c.container_id)
    if c.appname != appname:
        abort(404, 'Container does not belong to app')
    if c.network_mode == 'host':
        abort(400, 'Container use host network mode')

    network_names = data.get('networks', [])
    networks = [ipam.get_pool(n) for n in network_names]
    if not networks:
        abort(400, 'network empty')

    cidrs = [n.cidr for n in networks if n]

    bind_container_ip(c, cidrs)
    return {'cidrs': cidrs}
Пример #7
0
def create_containers(task_id, ncontainer, nshare, cores, network_ids, spec_ips=None):
    """
    执行task_id的任务. 部署ncontainer个容器, 占用*_core_ids这些核, 绑定到networks这些子网
    """
    _log.info('Task<id=%s>: Started', task_id)
    task = Task.get(task_id)
    if not task:
        _log.error('Task (id=%s) not found, quit', task_id)
        return

    if spec_ips is None:
        spec_ips = []

    need_network = bool(network_ids)
    networks = [ipam.get_pool(n) for n in network_ids]

    notifier = TaskNotifier(task)
    host = task.host
    version = task.version
    entrypoint = task.props['entrypoint']
    env = task.props['env']
    ports = task.props['ports']
    args = task.props['args']
    # use raw
    image = task.props['image']
    callback_url = task.props['callback_url']
    cpu_shares = int(float(nshare) / host.pod.core_share * 1024) if nshare else 1024

    cids = []
    backends = []
    entry = version.appconfig.entrypoints[entrypoint]

    for fcores, pcores in _iter_cores(cores, ncontainer):
        cores_for_one_container = {'full': fcores, 'part': pcores}
        # 在宿主机上创建容器
        try:
            cid, cname = dockerjob.create_one_container(host,
                                                        version,
                                                        entrypoint,
                                                        env,
                                                        fcores + pcores,
                                                        ports=ports, args=args,
                                                        cpu_shares=cpu_shares,
                                                        image=image,
                                                        need_network=need_network)
        except Exception as e:
            # 写给celery日志看
            _log.exception(e)
            host.release_cores(cores_for_one_container, nshare)
            continue

        # 容器记录下来
        c = Container.create(cid, host, version, cname, entrypoint, cores_for_one_container, env, nshare, callback_url)

        # 为容器创建网络栈
        # 同时把各种信息都记录下来
        # 如果失败, 清除掉所有记录和宿主机上的容器
        # 循环下一次尝试
        cidrs = [n.netspace for n in networks]
        if not ipam.allocate_ips(cidrs, cid, spec_ips):
            _clean_failed_containers(cid)
            continue

        notifier.notify_agent(c)
        add_container_for_agent(host, c)
        add_container_backends(c)
        cids.append(cid)
        backends.extend(c.get_backends())

        c.callback_report(status='start')

    health_check = entry.get('health_check', '')
    if health_check and backends:
        urls = [b + health_check for b in backends]
        if not wait_health_check(urls):
            # TODO 这里要么回滚要么报警
            _log.info('Task<id=%s>: Done, but something went error', task_id)
            return

    publish_to_service_discovery(version.name)
    task.finish(consts.TASK_SUCCESS)
    task.reason = 'ok'
    task.container_ids = cids
    notifier.pub_success()

    _log.info('Task<id=%s>: Done', task_id)
Пример #8
0
def create_containers(task_id,
                      ncontainer,
                      nshare,
                      cores,
                      network_ids,
                      spec_ips=None):
    """
    执行task_id的任务. 部署ncontainer个容器, 占用*_core_ids这些核, 绑定到networks这些子网
    """
    _log.info('Task<id=%s>: Started', task_id)
    task = Task.get(task_id)
    if not task:
        _log.error('Task (id=%s) not found, quit', task_id)
        return

    if spec_ips is None:
        spec_ips = []

    need_network = bool(network_ids)
    networks = [ipam.get_pool(n) for n in network_ids]

    notifier = TaskNotifier(task)
    host = task.host
    version = task.version
    entrypoint = task.props['entrypoint']
    env = task.props['env']
    ports = task.props['ports']
    args = task.props['args']
    # use raw
    image = task.props['image']
    callback_url = task.props['callback_url']
    cpu_shares = int(float(nshare) / host.pod.core_share *
                     1024) if nshare else 1024

    cids = []
    backends = []
    entry = version.appconfig.entrypoints[entrypoint]

    for fcores, pcores in _iter_cores(cores, ncontainer):
        cores_for_one_container = {'full': fcores, 'part': pcores}
        # 在宿主机上创建容器
        try:
            cid, cname = dockerjob.create_one_container(
                host,
                version,
                entrypoint,
                env,
                fcores + pcores,
                ports=ports,
                args=args,
                cpu_shares=cpu_shares,
                image=image,
                need_network=need_network)
        except Exception as e:
            # 写给celery日志看
            _log.exception(e)
            host.release_cores(cores_for_one_container, nshare)
            continue

        # 容器记录下来
        c = Container.create(cid, host, version, cname, entrypoint,
                             cores_for_one_container, env, nshare,
                             callback_url)

        # 为容器创建网络栈
        # 同时把各种信息都记录下来
        # 如果失败, 清除掉所有记录和宿主机上的容器
        # 循环下一次尝试
        cidrs = [n.netspace for n in networks]
        if not ipam.allocate_ips(cidrs, cid, spec_ips):
            _clean_failed_containers(cid)
            continue

        notifier.notify_agent(c)
        add_container_for_agent(host, c)
        add_container_backends(c)
        cids.append(cid)
        backends.extend(c.get_backends())

        c.callback_report(status='start')

    health_check = entry.get('health_check', '')
    if health_check and backends:
        urls = [b + health_check for b in backends]
        if not wait_health_check(urls):
            # TODO 这里要么回滚要么报警
            _log.info('Task<id=%s>: Done, but something went error', task_id)
            return

    publish_to_service_discovery(version.name)
    task.finish(consts.TASK_SUCCESS)
    task.reason = 'ok'
    task.container_ids = cids
    notifier.pub_success()

    _log.info('Task<id=%s>: Done', task_id)
Пример #9
0
def get_network(id_or_name):
    n = ipam.get_pool(id_or_name)
    if not n:
        abort(404, 'Network %s not found' % id_or_name)
    return n