def __init__(self, parent): HttpHandler.__init__(self, parent.scheduler, False, parent.vhostbind) self._parent = parent self._logger = parent._logger self._macbase = uint64.create( create_binary(mac_addr_bytes(self._parent.mactemplate), 8)) cidrrange = parent.cidrrange try: subnet, mask = parse_ip4_network(cidrrange) if not (0 <= mask <= 24): raise ValueError except Exception: self._logger.warning( 'Invalid CIDR range: %r. Using default 10.0.0.0/8', cidrrange) subnet = ip4_addr('10.0.0.0') mask = 8 self.cidrrange_subnet = subnet self.cidrrange_mask = mask self.cidrrange_end = (1 << (24 - mask)) self.pooltimeout = parent.pooltimeout self.iptimeout = parent.iptimeout self._reqid = 0
def createendpoint(self, env, params): lognet_id = 'docker-' + params['NetworkID'] + '-lognet' subnet_id = 'docker-' + params['NetworkID'] + '-subnet' logport_id = 'docker-' + params['EndpointID'] logport_params = {} if 'Options' in params: logport_params.update(params['Options']) logport_params['id'] = logport_id logport_params['logicalnetwork'] = lognet_id logport_params['subnet'] = subnet_id mac_address = None if 'Interface' in params: interface = params['Interface'] if 'Address' in interface and interface['Address']: ip, f, prefix = interface['Address'].partition('/') logport_params['ip_address'] = ip else: ip = None if 'MacAddress' in interface and interface['MacAddress']: logport_params['mac_address'] = interface['MacAddress'] mac_address = interface['MacAddress'] if mac_address is None: # Generate a MAC address if ip: # Generate MAC address based on IP address mac_num = self._macbase mac_num ^= ((hash(subnet_id) & 0xffffffff) << 8) mac_num ^= ip4_addr(ip) else: # Generate MAC address based on Port ID and random number mac_num = self._macbase mac_num ^= ((hash(logport_id) & 0xffffffff) << 8) mac_num ^= randint(0, 0xffffffff) mac_address = mac_addr_bytes.formatter(create_binary(mac_num, 6)) logport_params['mac_address'] = mac_address try: for m in callAPI(self, 'viperflow', 'createlogicalport', logport_params): yield m except Exception as exc: # There is an issue that docker daemon may not delete an endpoint correctly # If autoremoveports is enabled, we remove the logical port automatically # Note that created veth and Openvswitch ports are not cleared because they # may not on this server, so you must clean them yourself with vlcp_docker.cleanup if self._parent.autoremoveports: for m in callAPI(self, 'viperflow', 'listlogicalports', { 'logicalnetwork': lognet_id, 'ip_address': ip }): yield m if self.retvalue: if self.retvalue[0]['id'].startswith('docker-'): dup_pid = self.retvalue[0]['id'] self._logger.warning( 'Duplicated ports detected: %s (%s). Will remove it.', dup_pid, self.retvalue[0]['ip_address']) for m in callAPI(self, 'viperflow', 'deletelogicalport', {'id': dup_pid}): yield m # Retry create logical port for m in callAPI(self, 'viperflow', 'createlogicalport', logport_params): yield m else: self._logger.warning( 'Duplicated with a non-docker port') raise exc else: raise exc else: raise exc ip_address = self.retvalue[0]['ip_address'] subnet_cidr = self.retvalue[0]['subnet']['cidr'] mtu = self.retvalue[0]['network'].get('mtu', self._parent.mtu) _, _, prefix = subnet_cidr.partition('/') if 'docker_ipam_poolid' in self.retvalue[0]['subnet']: docker_ipam_poolid = self.retvalue[0]['subnet'][ 'docker_ipam_poolid'] def _remove_ip_reservation(): try: # The reservation is completed, remove the temporary reservation def _ipam_updater(keys, values, timestamp): pool = values[0] self._remove_staled_ips(pool, timestamp) if ip_address in pool.reserved_ips: del pool.reserved_ips[ip_address] return ((keys[0], ), (pool, )) for m in callAPI( self, 'objectdb', 'transact', { 'keys': (IPAMReserve.default_key(docker_ipam_poolid), ), 'updater': _ipam_updater, 'withtime': True }): yield m except Exception: self._logger.warning( 'Unexpected exception while removing reservation of IP address %r, will ignore and continue', ip_address, exc_info=True) self.subroutine(_remove_ip_reservation()) port_created = False try: for m in self._parent.taskpool.runTask( self, lambda: _create_veth(self._parent.ipcommand, self._parent. vethprefix, mac_address, mtu)): yield m port_created = True device_name, _ = self.retvalue info = DockerInfo.create_instance(logport_id) info.docker_port = device_name @updater def _updater(dockerinfo): dockerinfo = set_new(dockerinfo, info) return (dockerinfo, ) for m in callAPI(self, 'objectdb', 'transact', { 'keys': (info.getkey(), ), 'updater': _updater }): yield m for m in self._parent.taskpool.runTask( self, lambda: _plug_ovs(self._parent.ovscommand, self._parent. ovsbridge, device_name, logport_id)): yield m result = {'Interface': {'MacAddress': mac_address}} if 'Address' not in interface: result['Interface']['Address'] = ip_address + '/' + prefix env.outputjson(result) except Exception as exc: try: if port_created: for m in self._parent.taskpool.runTask( self, lambda: _delete_veth(self._parent.ipcommand, device_name)): yield m except Exception: pass try: for m in callAPI(self, 'viperflow', 'deletelogicalport', {'id': logport_id}): yield m except Exception: pass raise exc
def createendpoint(self, env, params): lognet_id = 'docker-' + params['NetworkID'] + '-lognet' subnet_id = 'docker-' + params['NetworkID'] + '-subnet' logport_id = 'docker-' + params['EndpointID'] logport_params = {} if 'Options' in params: logport_params.update(params['Options']) logport_params['id'] = logport_id logport_params['logicalnetwork'] = lognet_id logport_params['subnet'] = subnet_id mac_address = None if 'Interface' in params: interface = params['Interface'] if 'Address' in interface and interface['Address']: ip, f, prefix = interface['Address'].rpartition('/') logport_params['ip_address'] = ip else: ip = None if 'MacAddress' in interface and interface['MacAddress']: logport_params['mac_address'] = interface['MacAddress'] mac_address = interface['MacAddress'] if mac_address is None: # Generate a MAC address if ip: # Generate MAC address based on IP address mac_num = self._macbase mac_num ^= ((hash(subnet_id) & 0xffffffff) << 8) mac_num ^= ip4_addr(ip) else: # Generate MAC address based on Port ID and random number mac_num = self._macbase mac_num ^= ((hash(logport_id) & 0xffffffff) << 8) mac_num ^= randint(0, 0xffffffff) mac_address = mac_addr_bytes.formatter(create_binary(mac_num, 6)) logport_params['mac_address'] = mac_address for m in callAPI(self, 'viperflow', 'createlogicalport', logport_params): yield m ip_address = self.retvalue[0]['ip_address'] subnet_cidr = self.retvalue[0]['subnet']['cidr'] mtu = self.retvalue[0]['network'].get('mtu', self._parent.mtu) _, _, prefix = subnet_cidr.partition('/') port_created = False try: for m in self._parent.taskpool.runTask( self, lambda: _create_veth(self._parent.ipcommand, self._parent. vethprefix, mac_address, mtu)): yield m port_created = True device_name, _ = self.retvalue info = DockerInfo.create_instance(logport_id) info.docker_port = device_name @updater def _updater(dockerinfo): dockerinfo = set_new(dockerinfo, info) return (dockerinfo, ) for m in callAPI(self, 'objectdb', 'transact', { 'keys': (info.getkey(), ), 'updater': _updater }): yield m for m in self._parent.taskpool.runTask( self, lambda: _plug_ovs(self._parent.ovscommand, self._parent. ovsbridge, device_name, logport_id)): yield m result = {'Interface': {'MacAddress': mac_address}} if 'Address' not in interface: result['Interface']['Address'] = ip_address + '/' + prefix env.outputjson(result) except Exception as exc: try: if port_created: for m in self._parent.taskpool.runTask( self, lambda: _delete_veth(self._parent.ipcommand, device_name)): yield m except Exception: pass try: for m in callAPI(self, 'viperflow', 'deletelogicalport', {'id': logport_id}): yield m except Exception: pass raise exc
def __init__(self, parent): HttpHandler.__init__(self, parent.scheduler, False, parent.vhostbind) self._parent = parent self._logger = parent._logger self._macbase = uint64.create( create_binary(mac_addr_bytes(self._parent.mactemplate), 8))