Ejemplo n.º 1
0
 def release_eip(self):
     if not self.eip:
         return
     agent = get_agent(self.host)
     agent.unpublish_container(self.eip, self)
     clean_eip_bound(self.eip)
     del self.eip
     return True
Ejemplo n.º 2
0
 def release_eip(self):
     if not self.eip:
         return
     agent = get_agent(self.host)
     agent.unpublish_container(self.eip, self)
     clean_eip_bound(self.eip)
     del self.eip
     return True
Ejemplo n.º 3
0
 def notify_agent(self, container):
     if not container:
         return
     if ERU_AGENT_API == 'pubsub':
         watcher_key = ERU_AGENT_WATCHERKEY % self.task.host.name
         message = '+|%s|%s' % (container.container_id, json.dumps(container.meta))
         rds.publish(watcher_key, message)
     elif ERU_AGENT_API == 'http':
         agent = get_agent(container.host)
         agent.add_container(container)
Ejemplo n.º 4
0
    def allocate_ips(self, cidrs, container_id, spec_ips=None):
        """
        allocate ips for container_id, one ip per one cidr.
        if spec_ips is given, then the ip will be in spec_ips.
        note, for history reasons cidrs should always be given.
        """
        from eru.models.container import Container

        def _release_ips(ips):
            for ip in ips:
                ip.release()

        if not (cidrs or spec_ips):
            return True

        container = Container.get_by_container_id(container_id)
        count = len(container.ips.all())
        nstart = count + 1 if count > 0 else 0
        nids = range(nstart, nstart + len(spec_ips or cidrs))

        networks = [Network.get_by_netspace(cidr) for cidr in cidrs]
        networks = [n for n in networks if n]

        if spec_ips:
            ips = [
                n.acquire_specific_ip(ip) for n, ip in zip(networks, spec_ips)
            ]
        else:
            ips = [n.acquire_ip() for n in networks]

        ips = [i for i in ips if i]
        ip_dict = {ip.vlan_address: ip for ip in ips}

        agent = get_agent(container.host)
        ip_list = [(nid, ip.vlan_address) for nid, ip in zip(nids, ips)]

        resp = agent.add_container_vlan(container_id, gen_salt(8), ip_list)
        if not resp or resp.status_code != 200:
            _release_ips(ips)
            return False

        rv = resp.json()
        if not all(r['succ'] for r in rv):
            _release_ips(ips)
            return False

        for r in rv:
            ip = ip_dict.get(r['ip'], None)
            if ip:
                ip.set_vethname(r['veth'])
                ip.assigned_to_container(container)
        return True
Ejemplo n.º 5
0
    def allocate_ips(self, cidrs, container_id, spec_ips=None):
        """
        allocate ips for container_id, one ip per one cidr.
        if spec_ips is given, then the ip will be in spec_ips.
        note, for history reasons cidrs should always be given.
        """
        from eru.models.container import Container

        def _release_ips(ips):
            for ip in ips:
                ip.release()

        if not (cidrs or spec_ips):
            return True

        container = Container.get_by_container_id(container_id)
        count = len(container.ips.all())
        nstart = count+1 if count > 0 else 0
        nids = range(nstart, nstart+len(spec_ips or cidrs))

        networks = [Network.get_by_netspace(cidr) for cidr in cidrs]
        networks = [n for n in networks if n]

        if spec_ips:
            ips = [n.acquire_specific_ip(ip) for n, ip in zip(networks, spec_ips)]
        else:
            ips = [n.acquire_ip() for n in networks]

        ips = [i for i in ips if i]
        ip_dict = {ip.vlan_address: ip for ip in ips}

        agent = get_agent(container.host)
        ip_list = [(nid, ip.vlan_address) for nid, ip in zip(nids, ips)]

        resp = agent.add_container_vlan(container_id, gen_salt(8), ip_list)
        if not resp or resp.status_code != 200:
            _release_ips(ips)
            return False

        rv = resp.json()
        if not all(r['succ'] for r in rv):
            _release_ips(ips)
            return False

        for r in rv:
            ip = ip_dict.get(r['ip'], None)
            if ip:
                ip.set_vethname(r['veth'])
                ip.assigned_to_container(container)
        return True
Ejemplo n.º 6
0
    def release_eip(self, eip=None):
        if eip is not None:
            to_release = [IPAddress(eip)]
        else:
            to_release = self.eips

        eips = [ip for ip in self.eips if ip not in to_release]

        ip_list = [('%s/16' % e, e.value & 0xFFFF) for e in to_release]
        agent = get_agent(self)
        if not agent.unbind_eip(ip_list):
            return

        for eip in to_release:
            ipam.release_eip(eip)

        self.eips = [e.value for e in eips]
Ejemplo n.º 7
0
    def release_eip(self, eip=None):
        if eip is not None:
            to_release = [IPAddress(eip)]
        else:
            to_release = self.eips

        eips = [ip for ip in self.eips if ip not in to_release]

        ip_list = [('%s/16' % e, e.value & 0xFFFF) for e in to_release]
        agent = get_agent(self)
        if not agent.unbind_eip(ip_list):
            return

        for eip in to_release:
            ipam.release_eip(eip)

        self.eips = [e.value for e in eips]
Ejemplo n.º 8
0
    def bind_eip(self, eip=None):
        eip = ipam.get_eip(eip)
        if eip is None:
            return None

        mask = IPAddress(0xFFFF)
        ids = [eip.value & 0xFFFF]
        broadcasts = [str(eip | mask)]
        ip_list = ['%s/16' % eip]

        agent = get_agent(self)
        if not agent.bind_eip(zip(ip_list, ids, broadcasts)):
            ipam.release_eip(eip)
            return None

        eips = [ip.value for ip in self.eips] + [eip.value]
        self.eips = eips
        return eip
Ejemplo n.º 9
0
    def bind_eip(self, eip=None):
        if self.eip:
            return

        if eip is None:
            for e in self.host.eips:
                if not check_eip_bound(e):
                    eip = e
                    break

        if eip is None:
            return

        agent = get_agent(self.host)
        agent.publish_container(eip, self)
        self.eip = str(eip)
        set_eip_bound(eip, self.container_id)
        return True
Ejemplo n.º 10
0
    def bind_eip(self, eip=None):
        if self.eip:
            return

        if eip is None:
            for e in self.host.eips:
                if not check_eip_bound(e):
                    eip = e
                    break

        if eip is None:
            return

        agent = get_agent(self.host)
        agent.publish_container(eip, self)
        self.eip = str(eip)
        set_eip_bound(eip, self.container_id)
        return True
Ejemplo n.º 11
0
    def bind_eip(self, eip=None):
        eip = ipam.get_eip(eip)
        if eip is None:
            return None

        mask = IPAddress(0xFFFF)
        ids = [eip.value & 0xFFFF]
        broadcasts = [str(eip | mask)]
        ip_list = ['%s/16' % eip]

        agent = get_agent(self)
        if not agent.bind_eip(zip(ip_list, ids, broadcasts)):
            ipam.release_eip(eip)
            return None

        eips = [ip.value for ip in self.eips] + [eip.value]
        self.eips = eips
        return eip
Ejemplo n.º 12
0
def _bind_container_ip_http(task_id, container, ips, nid=None):
    agent = get_agent(container.host)
    feedback_key = 'eru:agent:%s:feedback' % task_id

    ip_list = [(nid or ip.vlan_seq_id, ip.vlan_address) for ip in ips]
    agent.add_container_vlan(container.container_id, str(task_id), ip_list)

    for _ in ips:
        rv = rds.blpop(feedback_key, 15)
        if rv is None:
            break
        succ = rv[1].split('|')[0]
        if succ == '0':
            break
    else:
        return True

    rds.delete(feedback_key)
    return False
Ejemplo n.º 13
0
 def notify_agent(self, container):
     if not container:
         return
     agent = get_agent(container.host)
     agent.add_container(container)
Ejemplo n.º 14
0
def create_containers_with_macvlan(task_id, ncontainer, nshare, cores, network_ids, spec_ips=None):
    """
    执行task_id的任务. 部署ncontainer个容器, 占用*_core_ids这些核, 绑定到networks这些子网
    """
    current_flask.logger.info('Task<id=%s>: Started', task_id)
    task = Task.get(task_id)
    if not task:
        current_flask.logger.error('Task (id=%s) not found, quit', task_id)
        return

    if spec_ips is None:
        spec_ips = []

    need_network = bool(network_ids)
    networks = Network.get_multi(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
    route = task.props['route']
    image = task.props['image']
    callback_url = task.props['callback_url']
    cpu_shares = int(float(nshare) / host.pod.core_share * 1024) if nshare else 1024

    pub_agent_vlan_key = 'eru:agent:%s:vlan' % host.name
    pub_agent_route_key = 'eru:agent:%s:route' % host.name
    feedback_key = 'eru:agent:%s:feedback' % task_id

    cids = []

    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日志看
            print e
            host.release_cores(cores_for_one_container, nshare)
            continue

        if spec_ips:
            ips = [n.acquire_specific_ip(ip) for n, ip in zip(networks, spec_ips)]
        else:
            ips = [n.acquire_ip() for n in networks]
        ips = [i for i in ips if i]
        ip_dict = {ip.vlan_address: ip for ip in ips}

        if ips:
            if ERU_AGENT_API == 'pubsub':
                values = [str(task_id), cid] + ['{0}:{1}'.format(ip.vlan_seq_id, ip.vlan_address) for ip in ips]
                rds.publish(pub_agent_vlan_key, '|'.join(values))
            elif ERU_AGENT_API == 'http':
                agent = get_agent(host)
                ip_list = [(ip.vlan_seq_id, ip.vlan_address) for ip in ips]
                agent.add_container_vlan(cid, str(task_id), ip_list)

        for _ in ips:
            # timeout 15s
            rv = rds.blpop(feedback_key, 15)
            if rv is None:
                break
            # rv is like (feedback_key, 'succ|container_id|vethname|ip')
            succ, _, vethname, vlan_address = rv[1].split('|')
            if succ == '0':
                break
            ip = ip_dict.get(vlan_address, None)
            if ip:
                ip.set_vethname(vethname)

            if route:
                rds.publish(pub_agent_route_key, '%s|%s' % (cid, route))

        else:
            current_flask.logger.info('Creating container (cid=%s, ips=%s)', cid, ips)
            c = Container.create(cid, host, version, cname, entrypoint,
                    cores_for_one_container, env, nshare, callback_url)
            for ip in ips:
                ip.assigned_to_container(c)
            notifier.notify_agent(c)
            add_container_for_agent(c)
            add_container_backends(c)
            cids.append(cid)
            # 略过清理工作
            continue

        # 清理掉失败的容器, 释放核, 释放ip
        current_flask.logger.info('Cleaning failed container (cid=%s)', cid)
        dockerjob.remove_container_by_cid([cid], host)
        host.release_cores(cores_for_one_container, nshare)
        [ip.release() for ip in ips]
        # 失败了就得清理掉这个key
        rds.delete(feedback_key)

    publish_to_service_discovery(version.name)
    task.finish_with_result(consts.TASK_SUCCESS, container_ids=cids)
    notifier.pub_success()

    # 有IO, 丢最后面算了
    falcon_all_graphs(version)
    falcon_all_alarms(version)

    current_flask.logger.info('Task<id=%s>: Done', task_id)
Ejemplo n.º 15
0
    def allocate_ips(self, cidrs, container_id, spec_ips=None):
        """
        Allocate IPs for container_id, all done by calicoctl.
        If spec_ips is given, cidrs will be ignored.
        Note: agent use calicoctl to assign IPs and it will do all the things related to calico,
            so here we only need to tell agent which ip to assign.
        Generally we give cidr to agent, and maybe IPs instead.
        """
        from eru.models.container import Container

        def _release_ips(ips):
            try:
                ips = set([IPAddress(i) for i in ips])
            except (AddrFormatError, ValueError):
                return
            _ipam.release_ips(set(ips))

        ip_list = spec_ips or cidrs
        if not ip_list:
            return True

        container = Container.get_by_container_id(container_id)
        agent = get_agent(container.host)

        pools = [self.get_pool(ip) for ip in ip_list]
        profiles = [p.name for p in pools]

        count = len(_get_container_ips(container.container_id))
        nstart = count + 1 if count > 0 else 0
        nids = range(nstart, nstart + len(ip_list))
        appends = [True for _ in nids]
        if count == 0:
            appends[0] = False

        # call agent to add network
        # and add container to profile
        resp = agent.add_container_calico(
            container_id, zip(nids, ip_list, profiles, appends))
        if not resp or resp.status_code != 200:
            _release_ips(ip_list)
            return False

        rv = resp.json()
        if not all(r['succ'] for r in rv):
            _release_ips(ip_list)
            return False

        # if it goes well
        # add inbound profile for ports
        # allow all IPs, if already exists, ignore

        # currently disabled
        # entry = container.get_entry()
        # if 'publish' in entry:
        #     ports = entry.get('ports', [])
        #     protocol_dict = {}
        #     for port in ports:
        #         p, protocol = port.split('/', 1)
        #         protocol_dict.setdefault(protocol, []).append(int(p))

        #     for profile_name in profiles:
        #         for protocol, ports in protocol_dict.iteritems():
        #             add_inbound(profile_name, protocol, ports)

        return True
Ejemplo n.º 16
0
 def notify_agent(self, container):
     if not container:
         return
     agent = get_agent(container.host)
     agent.add_container(container)
Ejemplo n.º 17
0
    def allocate_ips(self, cidrs, container_id, spec_ips=None):
        """
        Allocate IPs for container_id, all done by calicoctl.
        If spec_ips is given, cidrs will be ignored.
        Note: agent use calicoctl to assign IPs and it will do all the things related to calico,
            so here we only need to tell agent which ip to assign.
        Generally we give cidr to agent, and maybe IPs instead.
        """
        from eru.models.container import Container

        def _release_ips(ips):
            try:
                ips = set([IPAddress(i) for i in ips])
            except (AddrFormatError, ValueError):
                return
            _ipam.release_ips(set(ips))

        ip_list = spec_ips or cidrs
        if not ip_list:
            return True

        container = Container.get_by_container_id(container_id)
        agent = get_agent(container.host)

        pools = [self.get_pool(ip) for ip in ip_list]
        profiles = [p.name for p in pools]

        count = len(_get_container_ips(container.container_id))
        nstart = count+1 if count > 0 else 0
        nids = range(nstart, nstart+len(ip_list))
        appends = [True for _ in nids]
        if count == 0:
            appends[0] = False

        # call agent to add network
        # and add container to profile
        resp = agent.add_container_calico(container_id, zip(nids, ip_list, profiles, appends))
        if not resp or resp.status_code != 200:
            _release_ips(ip_list)
            return False

        rv = resp.json()
        if not all(r['succ'] for r in rv):
            _release_ips(ip_list)
            return False

        # if it goes well
        # add inbound profile for ports
        # allow all IPs, if already exists, ignore

        # currently disabled
        # entry = container.get_entry()
        # if 'publish' in entry:
        #     ports = entry.get('ports', [])
        #     protocol_dict = {}
        #     for port in ports:
        #         p, protocol = port.split('/', 1)
        #         protocol_dict.setdefault(protocol, []).append(int(p))

        #     for profile_name in profiles:
        #         for protocol, ports in protocol_dict.iteritems():
        #             add_inbound(profile_name, protocol, ports)

        return True