def notify_add_biport(self, node, biport): """ Get notified that a new biport was added to this engine node. :param node: The specification node that spawn this engine node. :type node: pynml.nml.Node :param biport: The specification bidirectional port added. :type biport: pynml.nml.BidirectionalPort :rtype: str :return: The assigned interface name of the port. """ network_config = self._get_network_config() category = biport.metadata.get('category', network_config['default_category']) category_config = network_config['mapping'][category] if category_config['managed_by'] is 'docker': netname = category_config.get( 'connect_to', '{}_{}'.format(self._container_name, category)) return get_iface_name(self, netname) else: return biport.metadata.get('label', biport.identifier)
def create_docker_network(enode, category, config): """ Create a Docker managed network with given configuration (netns, prefix) to be used with Topology framework. :param enode: The platform (a.k.a "engine") node to configure. :param str category: Name of the panel category. :param dict config: Configuration for the network. A dictionary like: :: { 'netns': 'mynetns', 'managed_by': 'docker', 'connect_to': 'somedockernetwork', 'prefix': '' } This dictionary is taken from the ``node._get_network_config()`` result. """ # Let's find out which networks exist already dockernets = enode._client.networks() # Let's figure out what docker network we should connect to netname = config.get( 'connect_to', '{}_{}'.format(enode._container_name, category) ) # Create docker network if it doesn't exist already if not any(d['Name'] == netname for d in dockernets): enode._client.create_network( name=netname, driver='bridge' ) # Disconnect from 'none' to be able to connect to other # networks (https://github.com/docker/docker/issues/21132) networks = enode._client.inspect_container( enode.container_id )['NetworkSettings']['Networks'] if 'none' in networks: enode._client.disconnect_container_from_network( container=enode._container_id, net_id='none' ) # Connect container to the docker network enode._client.connect_container_to_network( container=enode._container_id, net_id=netname ) # Check if this category has a defined netns netns = config.get('netns', None) if netns is None: return # Create this network's namespace inside the container # https://imgflip.com/i/16621d enode._docker_exec('ip netns add {}'.format(netns)) netns_exec = 'ip netns exec {}'.format(netns) # lo should always be up enode._docker_exec('{} ip link set dev lo up'.format(netns_exec)) # Find out the name Docker gave to this interface name iface = get_iface_name(enode, netname) # Prefix interface prefixed_iface = '{}{}'.format(config['prefix'], iface) # Move this network's interface to its netns enode._docker_exec( 'ip link set dev {iface} netns {netns} name {prefixed_iface}'.format( **locals() ) ) # Reset the interface to original config # This is required because after moving the iface from netns it lost its # ip and other config. enode._docker_exec( '{netns_exec} ' 'ip address add {docker_netconf[IPAddress]}/' '{docker_netconf[IPPrefixLen]} ' 'dev {prefixed_iface}'.format( **locals() ) ) enode._docker_exec( '{netns_exec} ip link set dev {prefixed_iface} up'.format( **locals() ) )