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
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)
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
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
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]
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
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
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
def notify_agent(self, container): if not container: return agent = get_agent(container.host) agent.add_container(container)
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)
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
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