def test_create_network_with_same_name(self): """Create docker network with same name Create two docker networks with same name, delete them and see that neutron networks are deleted as well """ res = self.docker_client.create_network(name='fakenet', driver='kuryr') net_id1 = res['Id'] res = self.docker_client.create_network(name='fakenet', driver='kuryr') net_id2 = res['Id'] network = self.neutron_client.list_networks( tags=utils.make_net_tags(net_id1)) self.assertEqual(1, len(network['networks'])) network = self.neutron_client.list_networks( tags=utils.make_net_tags(net_id2)) self.assertEqual(1, len(network['networks'])) self.docker_client.remove_network(net_id1) self.docker_client.remove_network(net_id2) network = self.neutron_client.list_networks( tags=utils.make_net_tags(net_id1)) self.assertEqual(0, len(network['networks'])) network = self.neutron_client.list_networks( tags=utils.make_net_tags(net_id2)) self.assertEqual(0, len(network['networks']))
def _mock_out_network(self, neutron_network_id, docker_network_id, check_existing=False): no_networks_response = {"networks": []} fake_list_response = { "networks": [{ "status": "ACTIVE", "subnets": [], "admin_state_up": True, "tenant_id": "9bacb3c5d39d41a79512987f338cf177", "router:external": False, "segments": [], "shared": False, "id": neutron_network_id }] } self.mox.StubOutWithMock(app.neutron, 'list_networks') t = utils.make_net_tags(docker_network_id) if check_existing: te = t + ',' + const.KURYR_EXISTING_NEUTRON_NET app.neutron.list_networks(tags=te).AndReturn(no_networks_response) app.neutron.list_networks(tags=t).AndReturn(fake_list_response) self.mox.ReplayAll() return neutron_network_id
def setUp(self): super(ContainerTest, self).setUp() self.docker_client.pull(repository='busybox', tag='1') fake_ipam = { "Driver": "kuryr", "Options": {}, "Config": [ { "Subnet": "10.3.0.0/16", "IPRange": "10.3.0.0/24", "Gateway": "10.3.0.1" } ] } net_name = utils.get_random_string(8) res = self.docker_client.create_network(name=net_name, driver='kuryr', ipam=fake_ipam) self.net_id = res.get('Id') networks = self.neutron_client.list_networks( tags=utils.make_net_tags(self.net_id)) self.assertEqual(1, len(networks['networks'])) self.neutron_net_id = networks['networks'][0]['id']
def _mock_out_network(self, neutron_network_id, docker_network_id, check_existing=False): no_networks_response = {"networks": []} fake_list_response = { "networks": [ { "status": "ACTIVE", "subnets": [], "admin_state_up": True, "tenant_id": "9bacb3c5d39d41a79512987f338cf177", "router:external": False, "segments": [], "shared": False, "id": neutron_network_id, } ] } self.mox.StubOutWithMock(app.neutron, "list_networks") t = utils.make_net_tags(docker_network_id) if check_existing: te = t + "," + const.KURYR_EXISTING_NEUTRON_NET app.neutron.list_networks(tags=te).AndReturn(no_networks_response) app.neutron.list_networks(tags=t).AndReturn(fake_list_response) self.mox.ReplayAll() return neutron_network_id
def test_delete_network_pre_existing(self): docker_network_id, fake_neutron_net_id, fake_response = self._ids() self.mox.StubOutWithMock(app.neutron, 'list_networks') t = utils.make_net_tags(docker_network_id) te = t + ',' + const.KURYR_EXISTING_NEUTRON_NET app.neutron.list_networks(tags=te).AndReturn( fake_response) self.mox.StubOutWithMock(app.neutron, "remove_tag") tags = utils.create_net_tags(docker_network_id) for tag in tags: app.neutron.remove_tag('networks', fake_neutron_net_id, tag) app.neutron.remove_tag('networks', fake_neutron_net_id, const.KURYR_EXISTING_NEUTRON_NET) self.mox.ReplayAll() data = {'NetworkID': docker_network_id} response = self.app.post('/NetworkDriver.DeleteNetwork', content_type='application/json', data=jsonutils.dumps(data)) self.assertEqual(200, response.status_code) decoded_json = jsonutils.loads(response.data) self.assertEqual(const.SCHEMA['SUCCESS'], decoded_json)
def test_create_delete_network_with_kuryr_driver(self): """Create and Delete docker network with Kuryr This method creates a docker network with Kuryr driver and tests it was created in Neutron. It then deletes the docker network and tests that it was deleted from Neutron. """ res = self.docker_client.create_network(name='fakenet', driver='kuryr') net_id = res['Id'] network = self.neutron_client.list_networks( tags=utils.make_net_tags(net_id)) self.assertEqual(1, len(network['networks'])) self.docker_client.remove_network(net_id) network = self.neutron_client.list_networks( tags=utils.make_net_tags(net_id)) self.assertEqual(0, len(network['networks']))
def _delete_network_with_exception(self, network_id, ex): fake_neutron_network_id = "4e8e5957-649f-477b-9e5b-f1f75b21c03c" no_networks_response = {"networks": []} if ex == exceptions.NotFound: fake_networks_response = no_networks_response else: fake_networks_response = { "networks": [{ "status": "ACTIVE", "subnets": [], "name": network_id, "admin_state_up": True, "tenant_id": "9bacb3c5d39d41a79512987f338cf177", "router:external": False, "segments": [], "shared": False, "id": fake_neutron_network_id }] } self.mox.StubOutWithMock(app.neutron, 'list_networks') t = utils.make_net_tags(network_id) te = t + ',' + const.KURYR_EXISTING_NEUTRON_NET app.neutron.list_networks(tags=te).AndReturn(no_networks_response) app.neutron.list_networks(tags=t).AndReturn(fake_networks_response) subnet_v4_id = "9436e561-47bf-436a-b1f1-fe23a926e031" subnet_v6_id = "64dd4a98-3d7a-4bfd-acf4-91137a8d2f51" docker_network_id = hashlib.sha256(utils.getrandbits(256)).hexdigest() docker_endpoint_id = hashlib.sha256(utils.getrandbits(256)).hexdigest() fake_v4_subnet = self._get_fake_v4_subnet(docker_network_id, docker_endpoint_id, subnet_v4_id) fake_v6_subnet = self._get_fake_v6_subnet(docker_network_id, docker_endpoint_id, subnet_v6_id) fake_subnets_response = { "subnets": [fake_v4_subnet['subnet'], fake_v6_subnet['subnet']] } self.mox.StubOutWithMock(app.neutron, 'list_subnets') app.neutron.list_subnets(network_id=fake_neutron_network_id).AndReturn( fake_subnets_response) self.mox.StubOutWithMock(app.neutron, 'list_subnetpools') fake_subnetpools_response = {"subnetpools": []} app.neutron.list_subnetpools( name='kuryr').AndReturn(fake_subnetpools_response) app.neutron.list_subnetpools( name='kuryr6').AndReturn(fake_subnetpools_response) self.mox.StubOutWithMock(app.neutron, 'delete_subnet') app.neutron.delete_subnet(subnet_v4_id).AndReturn(None) app.neutron.delete_subnet(subnet_v6_id).AndReturn(None) self.mox.StubOutWithMock(app.neutron, 'delete_network') app.neutron.delete_network(fake_neutron_network_id).AndRaise(ex) self.mox.ReplayAll()
def _delete_network_with_subnet_exception(self, network_id, ex): fake_neutron_network_id = "4e8e5957-649f-477b-9e5b-f1f75b21c03c" no_networks_response = { "networks": [] } fake_networks_response = { "networks": [{ "status": "ACTIVE", "subnets": [], "name": network_id, "admin_state_up": True, "tenant_id": "9bacb3c5d39d41a79512987f338cf177", "router:external": False, "segments": [], "shared": False, "id": fake_neutron_network_id }] } self.mox.StubOutWithMock(app.neutron, 'list_networks') t = utils.make_net_tags(network_id) te = t + ',' + const.KURYR_EXISTING_NEUTRON_NET app.neutron.list_networks(tags=te).AndReturn(no_networks_response) app.neutron.list_networks(tags=t).AndReturn(fake_networks_response) subnet_v4_id = "9436e561-47bf-436a-b1f1-fe23a926e031" subnet_v6_id = "64dd4a98-3d7a-4bfd-acf4-91137a8d2f51" docker_network_id = hashlib.sha256( utils.getrandbits(256)).hexdigest() docker_endpoint_id = hashlib.sha256( utils.getrandbits(256)).hexdigest() fake_v4_subnet = self._get_fake_v4_subnet( docker_network_id, docker_endpoint_id, subnet_v4_id) fake_v6_subnet = self._get_fake_v6_subnet( docker_network_id, docker_endpoint_id, subnet_v6_id) fake_subnets_response = { "subnets": [ fake_v4_subnet['subnet'], fake_v6_subnet['subnet'] ] } self.mox.StubOutWithMock(app.neutron, 'list_subnets') app.neutron.list_subnets(network_id=fake_neutron_network_id).AndReturn( fake_subnets_response) self.mox.StubOutWithMock(app.neutron, 'list_subnetpools') fake_subnetpools_response = {"subnetpools": []} app.neutron.list_subnetpools(name='kuryr').AndReturn( fake_subnetpools_response) app.neutron.list_subnetpools(name='kuryr6').AndReturn( fake_subnetpools_response) self.mox.StubOutWithMock(app.neutron, 'delete_subnet') app.neutron.delete_subnet(subnet_v4_id).AndRaise(ex) self.mox.ReplayAll()
def network_driver_leave(): """Unbinds a Neutron Port to a network interface attached to a container. This function takes the following JSON data and delete the veth pair corresponding to the given info. :: { "NetworkID": string, "EndpointID": string } """ json_data = flask.request.get_json(force=True) app.logger.debug("Received JSON data {0} for" " /NetworkDriver.DeleteEndpoint".format(json_data)) jsonschema.validate(json_data, schemata.LEAVE_SCHEMA) neutron_network_tags = utils.make_net_tags(json_data['NetworkID']) endpoint_id = json_data['EndpointID'] filtered_networks = _get_networks_by_attrs(tags=neutron_network_tags) if not filtered_networks: return flask.jsonify({ 'Err': "Neutron network associated with tags {0} doesn't exit.".format( neutron_network_tags) }) else: neutron_port_name = utils.get_neutron_port_name(endpoint_id) filtered_ports = _get_ports_by_attrs(name=neutron_port_name) if not filtered_ports: raise exceptions.NoResourceException( "The port doesn't exist for the name {0}".format( neutron_port_name)) neutron_port = filtered_ports[0] try: stdout, stderr = binding.port_unbind(endpoint_id, neutron_port) app.logger.debug(stdout) if stderr: app.logger.error(stderr) except processutils.ProcessExecutionError: with excutils.save_and_reraise_exception(): app.logger.error( _LE('Could not unbind the Neutron port from the veth ' 'endpoint.')) except exceptions.VethDeletionFailure: with excutils.save_and_reraise_exception(): app.logger.error(_LE('Cleaning the veth pair up was failed.')) return flask.jsonify(const.SCHEMA['SUCCESS'])
def network_driver_leave(): """Unbinds a Neutron Port to a network interface attached to a container. This function takes the following JSON data and delete the veth pair corresponding to the given info. :: { "NetworkID": string, "EndpointID": string } """ json_data = flask.request.get_json(force=True) app.logger.debug("Received JSON data {0} for" " /NetworkDriver.DeleteEndpoint" .format(json_data)) jsonschema.validate(json_data, schemata.LEAVE_SCHEMA) neutron_network_tags = utils.make_net_tags(json_data['NetworkID']) endpoint_id = json_data['EndpointID'] filtered_networks = _get_networks_by_attrs(tags=neutron_network_tags) if not filtered_networks: return flask.jsonify({ 'Err': "Neutron network associated with tags {0} doesn't exit." .format(neutron_network_tags) }) else: neutron_port_name = utils.get_neutron_port_name(endpoint_id) filtered_ports = _get_ports_by_attrs(name=neutron_port_name) if not filtered_ports: raise exceptions.NoResourceException( "The port doesn't exist for the name {0}" .format(neutron_port_name)) neutron_port = filtered_ports[0] try: stdout, stderr = binding.port_unbind(endpoint_id, neutron_port) app.logger.debug(stdout) if stderr: app.logger.error(stderr) except processutils.ProcessExecutionError: with excutils.save_and_reraise_exception(): app.logger.error(_LE( 'Could not unbind the Neutron port from the veth ' 'endpoint.')) except exceptions.VethDeletionFailure: with excutils.save_and_reraise_exception(): app.logger.error(_LE('Cleaning the veth pair up was failed.')) return flask.jsonify(const.SCHEMA['SUCCESS'])
def test_create_delete_network_without_kuryr_driver(self): """Create and Delete docker network without Kuryr This method create a docker network with the default docker driver, It tests that it was created correctly, but not added to Neutron """ res = self.docker_client.create_network(name='fakenet') net_id = res['Id'] network = self.neutron_client.list_networks( tags=utils.make_net_tags(net_id)) self.assertEqual(0, len(network['networks'])) docker_networks = self.docker_client.networks() network_found = False for docker_net in docker_networks: if docker_net['Id'] == net_id: network_found = True self.assertTrue(network_found) self.docker_client.remove_network(net_id)
def network_driver_join(): """Binds a Neutron Port to a network interface attached to a container. This function takes the following JSON data, creates a veth pair, put one end inside of the container and binds another end to the Neutron Port specified in the request. :: { "NetworkID": string, "EndpointID": string, "SandboxKey": string, "Options": { ... } } If the binding is succeeded, the following JSON response is returned.:: { "InterfaceName": { SrcName: string, DstPrefix: string }, "Gateway": string, "GatewayIPv6": string, "StaticRoutes": [{ "Destination": string, "RouteType": int, "NextHop": string, }, ...] } See the following link for more details about the spec: https://github.com/docker/libnetwork/blob/master/docs/remote.md#join # noqa """ json_data = flask.request.get_json(force=True) app.logger.debug( "Received JSON data {0} for /NetworkDriver.Join".format(json_data)) jsonschema.validate(json_data, schemata.JOIN_SCHEMA) neutron_network_tags = utils.make_net_tags(json_data['NetworkID']) endpoint_id = json_data['EndpointID'] filtered_networks = _get_networks_by_attrs(tags=neutron_network_tags) if not filtered_networks: return flask.jsonify({ 'Err': "Neutron network associated with tags {0} doesn't exit.".format( neutron_network_tags) }) else: neutron_network_id = filtered_networks[0]['id'] neutron_port_name = utils.get_neutron_port_name(endpoint_id) filtered_ports = _get_ports_by_attrs(name=neutron_port_name) if not filtered_ports: raise exceptions.NoResourceException( "The port doesn't exist for the name {0}".format( neutron_port_name)) neutron_port = filtered_ports[0] all_subnets = _get_subnets_by_attrs(network_id=neutron_network_id) try: ifname, peer_name, (stdout, stderr) = binding.port_bind( endpoint_id, neutron_port, all_subnets) app.logger.debug(stdout) if stderr: app.logger.error(stderr) except exceptions.VethCreationFailure as ex: with excutils.save_and_reraise_exception(): app.logger.error( _LE('Preparing the veth ' 'pair was failed: {0}.').format(ex)) except processutils.ProcessExecutionError: with excutils.save_and_reraise_exception(): app.logger.error( _LE('Could not bind the Neutron port to the veth endpoint.' )) join_response = { "InterfaceName": { "SrcName": peer_name, "DstPrefix": config.CONF.binding.veth_dst_prefix }, "StaticRoutes": [] } for subnet in all_subnets: if subnet['ip_version'] == 4: join_response['Gateway'] = subnet.get('gateway_ip', '') else: join_response['GatewayIPv6'] = subnet.get('gateway_ip', '') host_routes = subnet.get('host_routes', []) for host_route in host_routes: static_route = {'Destination': host_route['destination']} if host_route.get('nexthop', None): static_route['RouteType'] = const.TYPES['NEXTHOP'] static_route['NextHop'] = host_route['nexthop'] else: static_route['RouteType'] = const.TYPES['CONNECTED'] join_response['StaticRoutes'].append(static_route) return flask.jsonify(join_response)
def network_driver_create_endpoint(): """Creates new Neutron Subnets and a Port with the given EndpointID. This function takes the following JSON data and delegates the actual endpoint creation to the Neutron client mapping it into Subnet and Port. :: { "NetworkID": string, "EndpointID": string, "Options": { ... }, "Interface": { "Address": string, "AddressIPv6": string, "MacAddress": string } } Then the following JSON response is returned. :: { "Interface": { "Address": string, "AddressIPv6": string, "MacAddress": string } } See the following link for more details about the spec: https://github.com/docker/libnetwork/blob/master/docs/remote.md#create-endpoint # noqa """ json_data = flask.request.get_json(force=True) app.logger.debug("Received JSON data {0} for " "/NetworkDriver.CreateEndpoint".format(json_data)) jsonschema.validate(json_data, schemata.ENDPOINT_CREATE_SCHEMA) neutron_network_tags = utils.make_net_tags(json_data['NetworkID']) endpoint_id = json_data['EndpointID'] filtered_networks = _get_networks_by_attrs(tags=neutron_network_tags) if not filtered_networks: return flask.jsonify({ 'Err': "Neutron network associated with tags {0} doesn't exist.".format( neutron_network_tags) }) else: neutron_network_id = filtered_networks[0]['id'] interface = json_data['Interface'] or {} # Workaround for null interface_cidrv4 = interface.get('Address', '') interface_cidrv6 = interface.get('AddressIPv6', '') interface_mac = interface.get('MacAddress', '') if not interface_cidrv4 and not interface_cidrv6: return flask.jsonify( {'Err': "Interface address v4 or v6 not provided."}) response_interface = _create_or_update_port(neutron_network_id, endpoint_id, interface_cidrv4, interface_cidrv6, interface_mac) return flask.jsonify({'Interface': response_interface})
def network_driver_delete_network(): """Delete the Neutron Network with name as the given NetworkID. This function takes the following JSON data and delegates the actual network deletion to the Neutron client. :: { "NetworkID": string } See the following link for more details about the spec: https://github.com/docker/libnetwork/blob/master/docs/remote.md#delete-network # noqa """ json_data = flask.request.get_json(force=True) app.logger.debug("Received JSON data {0} for" " /NetworkDriver.DeleteNetwork".format(json_data)) jsonschema.validate(json_data, schemata.NETWORK_DELETE_SCHEMA) container_net_id = json_data['NetworkID'] neutron_network_tags = utils.make_net_tags(container_net_id) existing_network_tags = neutron_network_tags + ',' existing_network_tags += const.KURYR_EXISTING_NEUTRON_NET try: existing_networks = _get_networks_by_attrs(tags=existing_network_tags) except n_exceptions.NeutronClientException as ex: app.logger.error( _LE("Error happened during listing " "Neutron networks: {0}").format(ex)) raise if existing_networks: app.logger.warn( _LW("Network is a pre existing Neutron network, " "not deleting in Neutron. removing tags: {0}").format( existing_network_tags)) neutron_net_id = existing_networks[0]['id'] _neutron_net_remove_tags(neutron_net_id, container_net_id) _neutron_net_remove_tag(neutron_net_id, const.KURYR_EXISTING_NEUTRON_NET) return flask.jsonify(const.SCHEMA['SUCCESS']) try: filtered_networks = _get_networks_by_attrs(tags=neutron_network_tags) except n_exceptions.NeutronClientException as ex: app.logger.error( _LE("Error happened during listing " "Neutron networks: {0}").format(ex)) raise if not filtered_networks: app.logger.warn( _LW("Network with tags {0} cannot be found").format( neutron_network_tags)) else: neutron_network_id = filtered_networks[0]['id'] filtered_subnets = _get_subnets_by_attrs(network_id=neutron_network_id) for subnet in filtered_subnets: try: subnetpool_id = subnet.get('subnetpool_id', None) _cache_default_subnetpool_ids(app) if subnetpool_id not in app.DEFAULT_POOL_IDS: # If the subnet to be deleted has any port, when some ports # are referring to the subnets in other words, # delete_subnet throws an exception, SubnetInUse that # extends Conflict. This can happen when the multiple # Docker endpoints are created with the same subnet CIDR # and it's totally the normal case. So we'd just log that # and continue to proceed. app.neutron.delete_subnet(subnet['id']) except n_exceptions.Conflict as ex: app.logger.error( _LE("Subnet, {0}, is in use. Network cant be deleted."). format(subnet['id'])) raise except n_exceptions.NeutronClientException as ex: app.logger.error( _LE("Error happened during deleting a " "Neutron subnets: {0}").format(ex)) raise try: app.neutron.delete_network(neutron_network_id) except n_exceptions.NeutronClientException as ex: app.logger.error( _LE("Error happened during deleting a " "Neutron network: {0}").format(ex)) raise app.logger.info( _LI("Deleted the network with ID {0} successfully").format( neutron_network_id)) return flask.jsonify(const.SCHEMA['SUCCESS'])
def tearDown(self): self.docker_client.remove_network(self.net_id) networks = self.neutron_client.list_networks( tags=utils.make_net_tags(self.net_id)) self.assertEqual(0, len(networks['networks'])) super(ContainerTest, self).tearDown()
def _make_net_identifier(network_id, tags=True): if tags: return utils.make_net_tags(network_id) return network_id
def network_driver_delete_network(): """Delete the Neutron Network with name as the given NetworkID. This function takes the following JSON data and delegates the actual network deletion to the Neutron client. :: { "NetworkID": string } See the following link for more details about the spec: https://github.com/docker/libnetwork/blob/master/docs/remote.md#delete-network # noqa """ json_data = flask.request.get_json(force=True) app.logger.debug("Received JSON data {0} for" " /NetworkDriver.DeleteNetwork".format(json_data)) jsonschema.validate(json_data, schemata.NETWORK_DELETE_SCHEMA) container_net_id = json_data['NetworkID'] neutron_network_tags = utils.make_net_tags(container_net_id) existing_network_tags = neutron_network_tags + ',' existing_network_tags += const.KURYR_EXISTING_NEUTRON_NET try: existing_networks = _get_networks_by_attrs(tags=existing_network_tags) except n_exceptions.NeutronClientException as ex: app.logger.error(_LE("Error happened during listing " "Neutron networks: {0}").format(ex)) raise if existing_networks: app.logger.warn(_LW("Network is a pre existing Neutron network, " "not deleting in Neutron. removing tags: {0}") .format(existing_network_tags)) neutron_net_id = existing_networks[0]['id'] _neutron_net_remove_tags(neutron_net_id, container_net_id) _neutron_net_remove_tag(neutron_net_id, const.KURYR_EXISTING_NEUTRON_NET) return flask.jsonify(const.SCHEMA['SUCCESS']) try: filtered_networks = _get_networks_by_attrs(tags=neutron_network_tags) except n_exceptions.NeutronClientException as ex: app.logger.error(_LE("Error happened during listing " "Neutron networks: {0}").format(ex)) raise if not filtered_networks: app.logger.warn(_LW("Network with tags {0} cannot be found") .format(neutron_network_tags)) else: neutron_network_id = filtered_networks[0]['id'] filtered_subnets = _get_subnets_by_attrs( network_id=neutron_network_id) for subnet in filtered_subnets: try: subnetpool_id = subnet.get('subnetpool_id', None) _cache_default_subnetpool_ids(app) if subnetpool_id not in app.DEFAULT_POOL_IDS: # If the subnet to be deleted has any port, when some ports # are referring to the subnets in other words, # delete_subnet throws an exception, SubnetInUse that # extends Conflict. This can happen when the multiple # Docker endpoints are created with the same subnet CIDR # and it's totally the normal case. So we'd just log that # and continue to proceed. app.neutron.delete_subnet(subnet['id']) except n_exceptions.Conflict as ex: app.logger.error(_LE( "Subnet, {0}, is in use. Network cant be deleted.").format( subnet['id'])) raise except n_exceptions.NeutronClientException as ex: app.logger.error(_LE("Error happened during deleting a " "Neutron subnets: {0}").format(ex)) raise try: app.neutron.delete_network(neutron_network_id) except n_exceptions.NeutronClientException as ex: app.logger.error(_LE("Error happened during deleting a " "Neutron network: {0}").format(ex)) raise app.logger.info(_LI("Deleted the network with ID {0} successfully") .format(neutron_network_id)) return flask.jsonify(const.SCHEMA['SUCCESS'])
def network_driver_create_endpoint(): """Creates new Neutron Subnets and a Port with the given EndpointID. This function takes the following JSON data and delegates the actual endpoint creation to the Neutron client mapping it into Subnet and Port. :: { "NetworkID": string, "EndpointID": string, "Options": { ... }, "Interface": { "Address": string, "AddressIPv6": string, "MacAddress": string } } Then the following JSON response is returned. :: { "Interface": { "Address": string, "AddressIPv6": string, "MacAddress": string } } See the following link for more details about the spec: https://github.com/docker/libnetwork/blob/master/docs/remote.md#create-endpoint # noqa """ json_data = flask.request.get_json(force=True) app.logger.debug("Received JSON data {0} for " "/NetworkDriver.CreateEndpoint" .format(json_data)) jsonschema.validate(json_data, schemata.ENDPOINT_CREATE_SCHEMA) neutron_network_tags = utils.make_net_tags(json_data['NetworkID']) endpoint_id = json_data['EndpointID'] filtered_networks = _get_networks_by_attrs(tags=neutron_network_tags) if not filtered_networks: return flask.jsonify({ 'Err': "Neutron network associated with tags {0} doesn't exist." .format(neutron_network_tags) }) else: neutron_network_id = filtered_networks[0]['id'] interface = json_data['Interface'] or {} # Workaround for null interface_cidrv4 = interface.get('Address', '') interface_cidrv6 = interface.get('AddressIPv6', '') interface_mac = interface.get('MacAddress', '') if not interface_cidrv4 and not interface_cidrv6: return flask.jsonify({ 'Err': "Interface address v4 or v6 not provided." }) response_interface = _create_or_update_port( neutron_network_id, endpoint_id, interface_cidrv4, interface_cidrv6, interface_mac) return flask.jsonify({'Interface': response_interface})
def network_driver_join(): """Binds a Neutron Port to a network interface attached to a container. This function takes the following JSON data, creates a veth pair, put one end inside of the container and binds another end to the Neutron Port specified in the request. :: { "NetworkID": string, "EndpointID": string, "SandboxKey": string, "Options": { ... } } If the binding is succeeded, the following JSON response is returned.:: { "InterfaceName": { SrcName: string, DstPrefix: string }, "Gateway": string, "GatewayIPv6": string, "StaticRoutes": [{ "Destination": string, "RouteType": int, "NextHop": string, }, ...] } See the following link for more details about the spec: https://github.com/docker/libnetwork/blob/master/docs/remote.md#join # noqa """ json_data = flask.request.get_json(force=True) app.logger.debug("Received JSON data {0} for /NetworkDriver.Join" .format(json_data)) jsonschema.validate(json_data, schemata.JOIN_SCHEMA) neutron_network_tags = utils.make_net_tags(json_data['NetworkID']) endpoint_id = json_data['EndpointID'] filtered_networks = _get_networks_by_attrs(tags=neutron_network_tags) if not filtered_networks: return flask.jsonify({ 'Err': "Neutron network associated with tags {0} doesn't exit." .format(neutron_network_tags) }) else: neutron_network_id = filtered_networks[0]['id'] neutron_port_name = utils.get_neutron_port_name(endpoint_id) filtered_ports = _get_ports_by_attrs(name=neutron_port_name) if not filtered_ports: raise exceptions.NoResourceException( "The port doesn't exist for the name {0}" .format(neutron_port_name)) neutron_port = filtered_ports[0] all_subnets = _get_subnets_by_attrs(network_id=neutron_network_id) try: ifname, peer_name, (stdout, stderr) = binding.port_bind( endpoint_id, neutron_port, all_subnets) app.logger.debug(stdout) if stderr: app.logger.error(stderr) except exceptions.VethCreationFailure as ex: with excutils.save_and_reraise_exception(): app.logger.error(_LE('Preparing the veth ' 'pair was failed: {0}.') .format(ex)) except processutils.ProcessExecutionError: with excutils.save_and_reraise_exception(): app.logger.error(_LE( 'Could not bind the Neutron port to the veth endpoint.')) join_response = { "InterfaceName": { "SrcName": peer_name, "DstPrefix": config.CONF.binding.veth_dst_prefix }, "StaticRoutes": [] } for subnet in all_subnets: if subnet['ip_version'] == 4: join_response['Gateway'] = subnet.get('gateway_ip', '') else: join_response['GatewayIPv6'] = subnet.get('gateway_ip', '') host_routes = subnet.get('host_routes', []) for host_route in host_routes: static_route = { 'Destination': host_route['destination'] } if host_route.get('nexthop', None): static_route['RouteType'] = const.TYPES['NEXTHOP'] static_route['NextHop'] = host_route['nexthop'] else: static_route['RouteType'] = const.TYPES['CONNECTED'] join_response['StaticRoutes'].append(static_route) return flask.jsonify(join_response)