def _create_port_with_exception(self, neutron_network_id, docker_endpoint_id, neutron_subnetv4_id, neutron_subnetv6_id, ex): self.mox.StubOutWithMock(app.neutron, 'create_port') fake_port_request = { 'port': { 'name': utils.get_neutron_port_name(docker_endpoint_id), 'admin_state_up': True, "binding:host_id": utils.get_hostname(), 'device_owner': constants.DEVICE_OWNER, 'device_id': docker_endpoint_id, 'fixed_ips': [{ 'subnet_id': neutron_subnetv4_id, 'ip_address': '192.168.1.2' }, { 'subnet_id': neutron_subnetv6_id, 'ip_address': 'fe80::f816:3eff:fe20:57c4' }], 'mac_address': "fa:16:3e:20:57:c3", 'network_id': neutron_network_id } } # The following fake response is retrieved from the Neutron doc: # http://developer.openstack.org/api-ref-networking-v2.html#createPort # noqa fake_port = { "port": { "status": "DOWN", "name": utils.get_neutron_port_name(docker_endpoint_id), "allowed_address_pairs": [], "admin_state_up": True, "binding:host_id": utils.get_hostname(), "network_id": neutron_network_id, "tenant_id": "d6700c0c9ffa4f1cb322cd4a1f3906fa", "device_owner": constants.DEVICE_OWNER, 'device_id': docker_endpoint_id, "mac_address": "fa:16:3e:20:57:c3", 'fixed_ips': [{ 'subnet_id': neutron_subnetv4_id, 'ip_address': '192.168.1.2' }, { 'subnet_id': neutron_subnetv6_id, 'ip_address': 'fe80::f816:3eff:fe20:57c4' }], "id": "65c0ee9f-d634-4522-8954-51021b570b0d", "security_groups": [], "device_id": "" } } if ex: app.neutron.create_port(fake_port_request).AndRaise(ex) else: app.neutron.create_port(fake_port_request).AndReturn(fake_port) self.mox.ReplayAll()
def test_network_driver_leave(self): fake_docker_net_id = utils.get_hash() fake_docker_endpoint_id = utils.get_hash() fake_neutron_net_id = str(uuid.uuid4()) self._mock_out_network(fake_neutron_net_id, fake_docker_net_id) fake_neutron_port_id = str(uuid.uuid4()) self.mox.StubOutWithMock(app.neutron, 'list_ports') neutron_port_name = utils.get_neutron_port_name( fake_docker_endpoint_id) fake_neutron_v4_subnet_id = str(uuid.uuid4()) fake_neutron_v6_subnet_id = str(uuid.uuid4()) fake_neutron_ports_response = self._get_fake_ports( fake_docker_endpoint_id, fake_neutron_net_id, fake_neutron_port_id, constants.PORT_STATUS_ACTIVE, fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id) app.neutron.list_ports(name=neutron_port_name).AndReturn( fake_neutron_ports_response) fake_neutron_port = fake_neutron_ports_response['ports'][0] self._mock_out_unbinding(fake_docker_endpoint_id, fake_neutron_port) leave_request = { 'NetworkID': fake_docker_net_id, 'EndpointID': fake_docker_endpoint_id, } response = self.app.post('/NetworkDriver.Leave', content_type='application/json', data=jsonutils.dumps(leave_request)) self.mox.ReplayAll() self.assertEqual(200, response.status_code) decoded_json = jsonutils.loads(response.data) self.assertEqual(constants.SCHEMA['SUCCESS'], decoded_json)
def test_network_driver_leave(self): fake_docker_net_id = hashlib.sha256(utils.getrandbits(256)).hexdigest() fake_docker_endpoint_id = hashlib.sha256( utils.getrandbits(256)).hexdigest() fake_neutron_net_id = str(uuid.uuid4()) self._mock_out_network(fake_neutron_net_id, fake_docker_net_id) fake_neutron_port_id = str(uuid.uuid4()) self.mox.StubOutWithMock(app.neutron, 'list_ports') neutron_port_name = utils.get_neutron_port_name( fake_docker_endpoint_id) fake_neutron_v4_subnet_id = str(uuid.uuid4()) fake_neutron_v6_subnet_id = str(uuid.uuid4()) fake_neutron_ports_response = self._get_fake_ports( fake_docker_endpoint_id, fake_neutron_net_id, fake_neutron_port_id, fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id) app.neutron.list_ports( name=neutron_port_name).AndReturn(fake_neutron_ports_response) fake_neutron_port = fake_neutron_ports_response['ports'][0] self._mock_out_unbinding(fake_docker_endpoint_id, fake_neutron_port) leave_request = { 'NetworkID': fake_docker_net_id, 'EndpointID': fake_docker_endpoint_id, } response = self.app.post('/NetworkDriver.Leave', content_type='application/json', data=jsonutils.dumps(leave_request)) self.assertEqual(200, response.status_code) decoded_json = jsonutils.loads(response.data) self.assertEqual(constants.SCHEMA['SUCCESS'], decoded_json)
def test_get_port_name(self): fake_docker_endpoint_id = hashlib.sha256( utils.getrandbits(256)).hexdigest() generated_neutron_port_name = utils.get_neutron_port_name( fake_docker_endpoint_id) self.assertIn(utils.PORT_POSTFIX, generated_neutron_port_name) self.assertIn(fake_docker_endpoint_id, generated_neutron_port_name)
def test_leave_unbinding_failure(self, GivenException): fake_docker_network_id = hashlib.sha256(str(random.getrandbits(256))).hexdigest() fake_docker_endpoint_id = hashlib.sha256(str(random.getrandbits(256))).hexdigest() fake_neutron_network_id = str(uuid.uuid4()) self._mock_out_network(fake_neutron_network_id, fake_docker_network_id) fake_neutron_port_id = str(uuid.uuid4()) self.mox.StubOutWithMock(app.neutron, "list_ports") neutron_port_name = utils.get_neutron_port_name(fake_docker_endpoint_id) fake_neutron_v4_subnet_id = str(uuid.uuid4()) fake_neutron_v6_subnet_id = str(uuid.uuid4()) fake_neutron_ports_response = self._get_fake_ports( fake_docker_endpoint_id, fake_neutron_network_id, fake_neutron_port_id, fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id, ) app.neutron.list_ports(name=neutron_port_name).AndReturn(fake_neutron_ports_response) fake_neutron_port = fake_neutron_ports_response["ports"][0] fake_message = "fake message" fake_exception = GivenException(fake_message) self._port_unbind_with_exception(fake_docker_endpoint_id, fake_neutron_port, fake_exception) response = self._invoke_leave_request(fake_docker_network_id, fake_docker_endpoint_id) self.assertEqual(w_exceptions.InternalServerError.code, response.status_code) decoded_json = jsonutils.loads(response.data) self.assertTrue("Err" in decoded_json) self.assertTrue(fake_message in decoded_json["Err"])
def test_leave_unbinding_failure(self, GivenException): fake_docker_network_id = hashlib.sha256( utils.getrandbits(256)).hexdigest() fake_docker_endpoint_id = hashlib.sha256( utils.getrandbits(256)).hexdigest() fake_neutron_network_id = str(uuid.uuid4()) self._mock_out_network(fake_neutron_network_id, fake_docker_network_id) fake_neutron_port_id = str(uuid.uuid4()) self.mox.StubOutWithMock(app.neutron, 'list_ports') neutron_port_name = utils.get_neutron_port_name( fake_docker_endpoint_id) fake_neutron_v4_subnet_id = str(uuid.uuid4()) fake_neutron_v6_subnet_id = str(uuid.uuid4()) fake_neutron_ports_response = self._get_fake_ports( fake_docker_endpoint_id, fake_neutron_network_id, fake_neutron_port_id, fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id) app.neutron.list_ports(name=neutron_port_name).AndReturn( fake_neutron_ports_response) fake_neutron_port = fake_neutron_ports_response['ports'][0] fake_message = "fake message" fake_exception = GivenException(fake_message) self._port_unbind_with_exception( fake_docker_endpoint_id, fake_neutron_port, fake_exception) response = self._invoke_leave_request( fake_docker_network_id, fake_docker_endpoint_id) self.assertEqual( w_exceptions.InternalServerError.code, response.status_code) decoded_json = jsonutils.loads(response.data) self.assertIn('Err', decoded_json) self.assertIn(fake_message, decoded_json['Err'])
def test_get_port_name(self): fake_docker_endpoint_id = hashlib.sha256(str( random.getrandbits(256))).hexdigest() generated_neutron_port_name = utils.get_neutron_port_name( fake_docker_endpoint_id) self.assertTrue(utils.PORT_POSTFIX in generated_neutron_port_name) self.assertTrue(fake_docker_endpoint_id in generated_neutron_port_name)
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_identifier = _make_net_identifier(json_data['NetworkID'], tags=app.tag) endpoint_id = json_data['EndpointID'] filtered_networks = _get_networks_by_identifier(neutron_network_identifier) if not filtered_networks: return flask.jsonify({ 'Err': "Neutron net associated with identifier {0} doesn't exit." .format(neutron_network_identifier) }) 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 _update_port(port, endpoint_id): port['name'] = utils.get_neutron_port_name(endpoint_id) try: response_port = app.neutron.update_port( port['id'], {'port': { 'name': port['name'], 'device_owner': const.DEVICE_OWNER, 'device_id': endpoint_id}}) except n_exceptions.NeutronClientException as ex: app.logger.error(_LE("Error happend during creating a " "Neutron port: {0}").format(ex)) raise return response_port['port']
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_name = json_data['NetworkID'] endpoint_id = json_data['EndpointID'] filtered_networks = _get_networks_by_attrs(name=neutron_network_name) if not filtered_networks: return flask.jsonify({ 'Err': "Neutron network associated with ID {0} doesn't exit.".format( neutron_network_name) }) 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( 'Could not unbind the Neutron port from the veth ' 'endpoint.') except exceptions.VethDeletionFailure: with excutils.save_and_reraise_exception(): app.logger.error('Cleaning the veth pair up was failed.') return flask.jsonify(constants.SCHEMA['SUCCESS'])
def _update_port(port, endpoint_id): port['name'] = utils.get_neutron_port_name(endpoint_id) try: response_port = app.neutron.update_port( port['id'], { 'port': { 'name': port['name'], 'device_owner': constants.DEVICE_OWNER, 'device_id': endpoint_id } }) except n_exceptions.NeutronClientException as ex: app.logger.error("Error happened during creating a " "Neutron port: {0}".format(ex)) raise return response_port['port']
def test_join_veth_failures(self, GivenException): fake_docker_network_id = hashlib.sha256( str(random.getrandbits(256))).hexdigest() fake_docker_endpoint_id = hashlib.sha256( str(random.getrandbits(256))).hexdigest() fake_container_id = hashlib.sha256( str(random.getrandbits(256))).hexdigest() fake_neutron_network_id = str(uuid.uuid4()) self._mock_out_network(fake_neutron_network_id, fake_docker_network_id) fake_neutron_port_id = str(uuid.uuid4()) self.mox.StubOutWithMock(app.neutron, 'list_ports') neutron_port_name = utils.get_neutron_port_name( fake_docker_endpoint_id) fake_neutron_v4_subnet_id = str(uuid.uuid4()) fake_neutron_v6_subnet_id = str(uuid.uuid4()) fake_neutron_ports_response = self._get_fake_ports( fake_docker_endpoint_id, fake_neutron_network_id, fake_neutron_port_id, fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id) app.neutron.list_ports(name=neutron_port_name).AndReturn( fake_neutron_ports_response) self.mox.StubOutWithMock(app.neutron, 'list_subnets') fake_neutron_subnets_response = self._get_fake_subnets( fake_docker_endpoint_id, fake_neutron_network_id, fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id) app.neutron.list_subnets(network_id=fake_neutron_network_id).AndReturn( fake_neutron_subnets_response) fake_neutron_port = fake_neutron_ports_response['ports'][0] fake_neutron_subnets = fake_neutron_subnets_response['subnets'] fake_message = "fake message" fake_exception = GivenException(fake_message) self._port_bind_with_exeption( fake_docker_endpoint_id, fake_neutron_port, fake_neutron_subnets, fake_exception) self.mox.ReplayAll() response = self._invoke_join_request( fake_docker_network_id, fake_docker_endpoint_id, fake_container_id) self.assertEqual( w_exceptions.InternalServerError.code, response.status_code) decoded_json = jsonutils.loads(response.data) self.assertTrue('Err' in decoded_json) self.assertTrue(fake_message in decoded_json['Err'])
def _create_port(endpoint_id, neutron_network_id, interface_mac, fixed_ips): port = { 'name': utils.get_neutron_port_name(endpoint_id), 'admin_state_up': True, 'network_id': neutron_network_id, 'device_owner': constants.DEVICE_OWNER, 'device_id': endpoint_id, 'binding:host_id': utils.get_hostname(), 'fixed_ips': fixed_ips } if interface_mac: port['mac_address'] = interface_mac try: rcvd_port = app.neutron.create_port({'port': port}) except n_exceptions.NeutronClientException as ex: app.logger.error("Error happened during creating a " "Neutron port: {0}".format(ex)) raise return rcvd_port['port']
def _create_port(endpoint_id, neutron_network_id, interface_mac, fixed_ips): port = { 'name': utils.get_neutron_port_name(endpoint_id), 'admin_state_up': True, 'network_id': neutron_network_id, 'device_owner': const.DEVICE_OWNER, 'device_id': endpoint_id, 'binding:host_id': utils.get_hostname(), 'fixed_ips': fixed_ips } if interface_mac: port['mac_address'] = interface_mac try: rcvd_port = app.neutron.create_port({'port': port}) except n_exceptions.NeutronClientException as ex: app.logger.error(_LE("Error happend during creating a" " Neutron port: {0}").format(ex)) raise return rcvd_port['port']
def _get_fake_port(docker_endpoint_id, neutron_network_id, neutron_port_id, neutron_subnet_v4_id=None, neutron_subnet_v6_id=None, neutron_subnet_v4_address="192.168.1.2", neutron_subnet_v6_address="fe80::f816:3eff:fe20:57c4"): # The following fake response is retrieved from the Neutron doc: # http://developer.openstack.org/api-ref-networking-v2.html#createPort # noqa fake_port = { 'port': { "status": "DOWN", "name": utils.get_neutron_port_name(docker_endpoint_id), "allowed_address_pairs": [], "admin_state_up": True, "network_id": neutron_network_id, "tenant_id": "d6700c0c9ffa4f1cb322cd4a1f3906fa", "device_owner": "", "mac_address": "fa:16:3e:20:57:c3", "fixed_ips": [], "id": neutron_port_id, "security_groups": [], "device_id": "" } } if neutron_subnet_v4_id: fake_port['port']['fixed_ips'].append({ "subnet_id": neutron_subnet_v4_id, "ip_address": neutron_subnet_v4_address }) if neutron_subnet_v6_id: fake_port['port']['fixed_ips'].append({ "subnet_id": neutron_subnet_v6_id, "ip_address": neutron_subnet_v6_address }) return fake_port
def _get_fake_port( docker_endpoint_id, neutron_network_id, neutron_port_id, neutron_subnet_v4_id=None, neutron_subnet_v6_id=None, neutron_subnet_v4_address="192.168.1.2", neutron_subnet_v6_address="fe80::f816:3eff:fe20:57c4", ): # The following fake response is retrieved from the Neutron doc: # http://developer.openstack.org/api-ref-networking-v2.html#createPort # noqa fake_port = { "port": { "status": "DOWN", "name": utils.get_neutron_port_name(docker_endpoint_id), "allowed_address_pairs": [], "admin_state_up": True, "network_id": neutron_network_id, "tenant_id": "d6700c0c9ffa4f1cb322cd4a1f3906fa", "device_owner": "", "mac_address": "fa:16:3e:20:57:c3", "fixed_ips": [], "id": neutron_port_id, "security_groups": [], "device_id": "", } } if neutron_subnet_v4_id: fake_port["port"]["fixed_ips"].append( {"subnet_id": neutron_subnet_v4_id, "ip_address": neutron_subnet_v4_address} ) if neutron_subnet_v6_id: fake_port["port"]["fixed_ips"].append( {"subnet_id": neutron_subnet_v6_id, "ip_address": neutron_subnet_v6_address} ) return fake_port
def test_network_driver_create_endpoint_with_v4_subnetpool(self): docker_network_id = hashlib.sha256( str(random.getrandbits(256))).hexdigest() docker_endpoint_id = hashlib.sha256( str(random.getrandbits(256))).hexdigest() fake_neutron_network_id = str(uuid.uuid4()) self._mock_out_network(fake_neutron_network_id, docker_network_id) self.mox.StubOutWithMock(app.neutron, 'list_subnetpools') fake_kuryr_subnetpool_id = str(uuid.uuid4()) kuryr_subnetpools = self._get_fake_v4_subnetpools( fake_kuryr_subnetpool_id) app.neutron.list_subnetpools(name='kuryr').AndReturn(kuryr_subnetpools) app.neutron.list_subnetpools( name='kuryr6').AndReturn({'subnetpools': []}) self.mox.StubOutWithMock(app.neutron, 'list_subnets') fake_existing_subnets_response = { "subnets": [] } fake_cidr_v4 = '192.168.1.0/24' app.neutron.list_subnets( network_id=fake_neutron_network_id, cidr=fake_cidr_v4).AndReturn(fake_existing_subnets_response) self.mox.StubOutWithMock(app.neutron, 'create_subnet') fake_subnet_request = { "subnets": [{ 'name': '-'.join([docker_endpoint_id, '192.168.1.0']), 'network_id': fake_neutron_network_id, 'ip_version': 4, 'subnetpool_id': fake_kuryr_subnetpool_id, 'enable_dhcp': 'False' }] } subnet_v4_id = str(uuid.uuid4()) fake_v4_subnet = self._get_fake_v4_subnet( docker_network_id, docker_endpoint_id, subnet_v4_id, subnetpool_id=fake_kuryr_subnetpool_id) fake_subnet_response = { 'subnets': [ fake_v4_subnet['subnet'] ] } app.neutron.create_subnet( fake_subnet_request).AndReturn(fake_subnet_response) self.mox.StubOutWithMock(app.neutron, 'create_port') fake_mac_address = 'fa:16:3e:20:57:c3' fake_neutron_port_id = str(uuid.uuid4()) fake_port_request = { 'port': { 'name': utils.get_neutron_port_name(docker_endpoint_id), 'admin_state_up': True, "binding:host_id": utils.get_hostname(), 'mac_address': fake_mac_address, 'network_id': fake_neutron_network_id, 'device_owner': constants.DEVICE_OWNER, 'device_id': docker_endpoint_id, 'fixed_ips': [{'subnet_id': subnet_v4_id}] } } fake_port_response = self._get_fake_port( docker_endpoint_id, fake_neutron_network_id, fake_neutron_port_id, neutron_subnet_v4_id=subnet_v4_id, neutron_subnet_v4_address='192.168.1.2') app.neutron.create_port( fake_port_request).AndReturn(fake_port_response) self.mox.ReplayAll() request = { 'NetworkID': docker_network_id, 'EndpointID': docker_endpoint_id, 'Options': {}, 'Interface': { 'MacAddress': "fa:16:3e:20:57:c3" } } response = self.app.post('/NetworkDriver.CreateEndpoint', content_type='application/json', data=jsonutils.dumps(request)) self.assertEqual(200, response.status_code) decoded_json = jsonutils.loads(response.data) expected = {'Interface': request['Interface']} # Address and AddressIPv6, allocated by Neutron's IPAM automatically # should be contained in the response. self.assertNotEqual(expected, decoded_json) app.logger.debug(decoded_json) self.assertIn('Address', decoded_json['Interface'])
def _create_subnets_and_or_port(interface, neutron_network_id, endpoint_id): response_interface = {} existing_subnets = [] created_subnets_response = {'subnets': []} # v4 and v6 Subnets for bulk creation. new_subnets = [] interface_cidrv4 = interface.get('Address', '') interface_cidrv6 = interface.get('AddressIPv6', '') interface_mac = interface.get('MacAddress', '') if interface_cidrv4 or interface_cidrv6: created_subnets_response = _handle_explicit_allocation( neutron_network_id, endpoint_id, interface_cidrv4, interface_cidrv6, new_subnets, existing_subnets) else: app.logger.info("Retrieving or creating subnets with the default " "subnetpool because Address and AddressIPv6 are " "not given.") created_subnets_response = _handle_allocation_from_pools( neutron_network_id, endpoint_id, new_subnets, existing_subnets) try: port = { 'name': utils.get_neutron_port_name(endpoint_id), 'admin_state_up': True, "binding:host_id": utils.get_hostname(), 'network_id': neutron_network_id, 'device_owner': constants.DEVICE_OWNER, 'device_id': endpoint_id, } if interface_mac: port['mac_address'] = interface_mac created_subnets = created_subnets_response.get('subnets', []) all_subnets = created_subnets + existing_subnets fixed_ips = port['fixed_ips'] = [] for subnet in all_subnets: fixed_ip = {'subnet_id': subnet['id']} if interface_cidrv4 or interface_cidrv6: if subnet['ip_version'] == 4 and interface_cidrv4: cidr = netaddr.IPNetwork(interface_cidrv4) elif subnet['ip_version'] == 6 and interface_cidrv6: cidr = netaddr.IPNetwork(interface_cidrv6) subnet_cidr = '/'.join([str(cidr.network), str(cidr.prefixlen)]) if subnet['cidr'] != subnet_cidr: continue fixed_ip['ip_address'] = str(cidr.ip) fixed_ips.append(fixed_ip) created_port = app.neutron.create_port({'port': port}) created_port = created_port['port'] created_fixed_ips = created_port['fixed_ips'] subnets_dict_by_id = {subnet['id']: subnet for subnet in all_subnets} if not interface_mac: response_interface['MacAddress'] = created_port['mac_address'] if not (interface_cidrv4 or interface_cidrv6): if 'ip_address' in created_port: _process_interface_address( created_port, subnets_dict_by_id, response_interface) for fixed_ip in created_fixed_ips: _process_interface_address( fixed_ip, subnets_dict_by_id, response_interface) except n_exceptions.NeutronClientException as ex: app.logger.error("Error happened during creating a " "Neutron port: {0}".format(ex)) # Rollback the subnets creation for subnet in created_subnets: app.neutron.delete_subnet(subnet['id']) raise return response_interface
def test_network_driver_join(self): fake_docker_net_id = hashlib.sha256(utils.getrandbits(256)).hexdigest() fake_docker_endpoint_id = hashlib.sha256( utils.getrandbits(256)).hexdigest() fake_container_id = hashlib.sha256(utils.getrandbits(256)).hexdigest() fake_neutron_net_id = str(uuid.uuid4()) self._mock_out_network(fake_neutron_net_id, fake_docker_net_id) fake_neutron_port_id = str(uuid.uuid4()) self.mox.StubOutWithMock(app.neutron, 'list_ports') neutron_port_name = utils.get_neutron_port_name( fake_docker_endpoint_id) fake_neutron_v4_subnet_id = str(uuid.uuid4()) fake_neutron_v6_subnet_id = str(uuid.uuid4()) fake_neutron_ports_response = self._get_fake_ports( fake_docker_endpoint_id, fake_neutron_net_id, fake_neutron_port_id, fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id) app.neutron.list_ports( name=neutron_port_name).AndReturn(fake_neutron_ports_response) self.mox.StubOutWithMock(app.neutron, 'list_subnets') fake_neutron_subnets_response = self._get_fake_subnets( fake_docker_endpoint_id, fake_neutron_net_id, fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id) app.neutron.list_subnets(network_id=fake_neutron_net_id).AndReturn( fake_neutron_subnets_response) fake_neutron_port = fake_neutron_ports_response['ports'][0] fake_neutron_subnets = fake_neutron_subnets_response['subnets'] _, fake_peer_name, _ = self._mock_out_binding(fake_docker_endpoint_id, fake_neutron_port, fake_neutron_subnets) self.mox.ReplayAll() fake_subnets_dict_by_id = { subnet['id']: subnet for subnet in fake_neutron_subnets } join_request = { 'NetworkID': fake_docker_net_id, 'EndpointID': fake_docker_endpoint_id, 'SandboxKey': utils.get_sandbox_key(fake_container_id), 'Options': {}, } response = self.app.post('/NetworkDriver.Join', content_type='application/json', data=jsonutils.dumps(join_request)) self.assertEqual(200, response.status_code) decoded_json = jsonutils.loads(response.data) fake_neutron_v4_subnet = fake_subnets_dict_by_id[ fake_neutron_v4_subnet_id] fake_neutron_v6_subnet = fake_subnets_dict_by_id[ fake_neutron_v6_subnet_id] expected_response = { 'Gateway': fake_neutron_v4_subnet['gateway_ip'], 'GatewayIPv6': fake_neutron_v6_subnet['gateway_ip'], 'InterfaceName': { 'DstPrefix': config.CONF.binding.veth_dst_prefix, 'SrcName': fake_peer_name, }, 'StaticRoutes': [] } self.assertEqual(expected_response, decoded_json)
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_name = json_data['NetworkID'] endpoint_id = json_data['EndpointID'] filtered_networks = _get_networks_by_attrs(name=neutron_network_name) if not filtered_networks: return flask.jsonify({ 'Err': "Neutron network associated with ID {0} doesn't exit." .format(neutron_network_name) }) 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('Preparing the veth pair was failed: {0}.' .format(ex)) except processutils.ProcessExecutionError: with excutils.save_and_reraise_exception(): app.logger.error( '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'] = constants.TYPES['NEXTHOP'] static_route['NextHop'] = host_route['nexthop'] else: static_route['RouteType'] = constants.TYPES['CONNECTED'] join_response['StaticRoutes'].append(static_route) return flask.jsonify(join_response)
def test_network_driver_create_endpoint(self): docker_network_id = hashlib.sha256( str(random.getrandbits(256))).hexdigest() docker_endpoint_id = hashlib.sha256( str(random.getrandbits(256))).hexdigest() fake_neutron_network_id = str(uuid.uuid4()) self._mock_out_network(fake_neutron_network_id, docker_network_id) self.mox.StubOutWithMock(app.neutron, 'list_subnets') fake_existing_subnets_response = { "subnets": [] } fake_cidr_v4 = '192.168.1.0/24' app.neutron.list_subnets( network_id=fake_neutron_network_id, cidr=fake_cidr_v4).AndReturn(fake_existing_subnets_response) fake_cidr_v6 = 'fe80::/64' app.neutron.list_subnets( network_id=fake_neutron_network_id, cidr=fake_cidr_v6).AndReturn(fake_existing_subnets_response) self.mox.StubOutWithMock(app.neutron, 'create_subnet') fake_subnet_request = { "subnets": [{ 'name': '-'.join([docker_endpoint_id, '192.168.1.0']), 'network_id': fake_neutron_network_id, 'ip_version': 4, "cidr": '192.168.1.0/24', 'enable_dhcp': 'False' }, { 'name': '-'.join([docker_endpoint_id, 'fe80::']), 'network_id': fake_neutron_network_id, 'ip_version': 6, "cidr": 'fe80::/64', 'enable_dhcp': 'False' }] } # The following fake response is retrieved from the Neutron doc: # http://developer.openstack.org/api-ref-networking-v2.html#createSubnet # noqa subnet_v4_id = "9436e561-47bf-436a-b1f1-fe23a926e031" subnet_v6_id = "64dd4a98-3d7a-4bfd-acf4-91137a8d2f51" 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_subnet_response = { "subnets": [ fake_v4_subnet['subnet'], fake_v6_subnet['subnet'] ] } app.neutron.create_subnet( fake_subnet_request).AndReturn(fake_subnet_response) fake_ipv4cidr = '192.168.1.2/24' fake_ipv6cidr = 'fe80::f816:3eff:fe20:57c4/64' subnet_v4_address = fake_ipv4cidr.split('/')[0] subnet_v6_address = fake_ipv6cidr.split('/')[0] self.mox.StubOutWithMock(app.neutron, 'create_port') fake_port_request = { 'port': { 'name': utils.get_neutron_port_name(docker_endpoint_id), 'admin_state_up': True, "binding:host_id": utils.get_hostname(), 'device_owner': constants.DEVICE_OWNER, 'device_id': docker_endpoint_id, 'mac_address': "fa:16:3e:20:57:c3", 'network_id': fake_neutron_network_id, 'fixed_ips': [{ 'subnet_id': subnet_v4_id, 'ip_address': subnet_v4_address }, { 'subnet_id': subnet_v6_id, 'ip_address': subnet_v6_address }] } } fake_port_id = str(uuid.uuid4()) fake_port = self._get_fake_port( docker_endpoint_id, fake_neutron_network_id, fake_port_id, subnet_v4_id, subnet_v6_id) app.neutron.create_port(fake_port_request).AndReturn(fake_port) self.mox.ReplayAll() data = { 'NetworkID': docker_network_id, 'EndpointID': docker_endpoint_id, 'Options': {}, 'Interface': { 'Address': fake_ipv4cidr, 'AddressIPv6': fake_ipv6cidr, 'MacAddress': "fa:16:3e:20:57:c3" } } response = self.app.post('/NetworkDriver.CreateEndpoint', content_type='application/json', data=jsonutils.dumps(data)) self.assertEqual(200, response.status_code) decoded_json = jsonutils.loads(response.data) expected = {'Interface': {}} self.assertEqual(expected, decoded_json)
def test_network_driver_join(self, vif_plug_is_fatal): if vif_plug_is_fatal: self.mox.StubOutWithMock(app, "vif_plug_is_fatal") app.vif_plug_is_fatal = True fake_docker_net_id = utils.get_hash() fake_docker_endpoint_id = utils.get_hash() fake_container_id = utils.get_hash() fake_neutron_net_id = str(uuid.uuid4()) self._mock_out_network(fake_neutron_net_id, fake_docker_net_id) fake_neutron_port_id = str(uuid.uuid4()) self.mox.StubOutWithMock(app.neutron, 'list_ports') neutron_port_name = utils.get_neutron_port_name( fake_docker_endpoint_id) fake_neutron_v4_subnet_id = str(uuid.uuid4()) fake_neutron_v6_subnet_id = str(uuid.uuid4()) fake_neutron_ports_response = self._get_fake_ports( fake_docker_endpoint_id, fake_neutron_net_id, fake_neutron_port_id, constants.PORT_STATUS_DOWN, fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id) app.neutron.list_ports(name=neutron_port_name).AndReturn( fake_neutron_ports_response) self.mox.StubOutWithMock(app.neutron, 'list_subnets') fake_neutron_subnets_response = self._get_fake_subnets( fake_docker_endpoint_id, fake_neutron_net_id, fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id) app.neutron.list_subnets(network_id=fake_neutron_net_id).AndReturn( fake_neutron_subnets_response) fake_neutron_port = fake_neutron_ports_response['ports'][0] fake_neutron_subnets = fake_neutron_subnets_response['subnets'] _, fake_peer_name, _ = self._mock_out_binding( fake_docker_endpoint_id, fake_neutron_port, fake_neutron_subnets) if vif_plug_is_fatal: self.mox.StubOutWithMock(app.neutron, 'show_port') fake_neutron_ports_response_2 = self._get_fake_port( fake_docker_endpoint_id, fake_neutron_net_id, fake_neutron_port_id, constants.PORT_STATUS_ACTIVE, fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id) app.neutron.show_port(fake_neutron_port_id).AndReturn( fake_neutron_ports_response_2) self.mox.ReplayAll() fake_subnets_dict_by_id = {subnet['id']: subnet for subnet in fake_neutron_subnets} join_request = { 'NetworkID': fake_docker_net_id, 'EndpointID': fake_docker_endpoint_id, 'SandboxKey': utils.get_sandbox_key(fake_container_id), 'Options': {}, } response = self.app.post('/NetworkDriver.Join', content_type='application/json', data=jsonutils.dumps(join_request)) self.assertEqual(200, response.status_code) decoded_json = jsonutils.loads(response.data) fake_neutron_v4_subnet = fake_subnets_dict_by_id[ fake_neutron_v4_subnet_id] fake_neutron_v6_subnet = fake_subnets_dict_by_id[ fake_neutron_v6_subnet_id] expected_response = { 'Gateway': fake_neutron_v4_subnet['gateway_ip'], 'GatewayIPv6': fake_neutron_v6_subnet['gateway_ip'], 'InterfaceName': { 'DstPrefix': config.CONF.binding.veth_dst_prefix, 'SrcName': fake_peer_name, }, 'StaticRoutes': [] } self.assertEqual(expected_response, decoded_json)
def test_network_driver_create_endpoint_with_subnetpools(self): docker_network_id = hashlib.sha256( str(random.getrandbits(256))).hexdigest() docker_endpoint_id = hashlib.sha256( str(random.getrandbits(256))).hexdigest() fake_neutron_network_id = str(uuid.uuid4()) self._mock_out_network(fake_neutron_network_id, docker_network_id) self.mox.StubOutWithMock(app.neutron, 'list_subnetpools') fake_kuryr_subnetpool_id = str(uuid.uuid4()) kuryr_subnetpools = self._get_fake_v4_subnetpools( fake_kuryr_subnetpool_id) app.neutron.list_subnetpools(name='kuryr').AndReturn(kuryr_subnetpools) fake_kuryr6_subnetpool_id = str(uuid.uuid4()) kuryr6_subnetpools = self._get_fake_v6_subnetpools( fake_kuryr6_subnetpool_id) app.neutron.list_subnetpools( name='kuryr6').AndReturn(kuryr6_subnetpools) self.mox.StubOutWithMock(app.neutron, 'list_subnets') fake_existing_subnets_response = { "subnets": [] } fake_cidr_v4 = '192.168.1.0/24' app.neutron.list_subnets( network_id=fake_neutron_network_id, cidr=fake_cidr_v4).AndReturn(fake_existing_subnets_response) fake_cidr_v6 = 'fe80::/64' app.neutron.list_subnets( network_id=fake_neutron_network_id, cidr=fake_cidr_v6).AndReturn(fake_existing_subnets_response) self.mox.StubOutWithMock(app.neutron, 'create_subnet') fake_subnet_request = { "subnets": [{ 'name': '-'.join([docker_endpoint_id, '192.168.1.0']), 'network_id': fake_neutron_network_id, 'ip_version': 4, 'subnetpool_id': fake_kuryr_subnetpool_id, 'enable_dhcp': 'False' }, { 'name': '-'.join([docker_endpoint_id, 'fe80::']), 'network_id': fake_neutron_network_id, 'ip_version': 6, 'subnetpool_id': fake_kuryr6_subnetpool_id, 'enable_dhcp': 'False' }] } # The following fake response is retrieved from the Neutron doc: # http://developer.openstack.org/api-ref-networking-v2.html#createSubnet # noqa subnet_v4_id = "9436e561-47bf-436a-b1f1-fe23a926e031" subnet_v6_id = "64dd4a98-3d7a-4bfd-acf4-91137a8d2f51" fake_subnet_response = super(self.__class__, self)._get_fake_subnets( docker_endpoint_id, fake_neutron_network_id, subnet_v4_id, subnet_v6_id) app.neutron.create_subnet( fake_subnet_request).AndReturn(fake_subnet_response) self.mox.StubOutWithMock(app.neutron, 'create_port') fake_mac_address = 'fa:16:3e:20:57:c3' fake_neutron_port_id = str(uuid.uuid4()) fake_port_request = { 'port': { 'name': utils.get_neutron_port_name(docker_endpoint_id), 'admin_state_up': True, "binding:host_id": utils.get_hostname(), 'mac_address': fake_mac_address, 'network_id': fake_neutron_network_id, 'device_owner': constants.DEVICE_OWNER, 'device_id': docker_endpoint_id, 'fixed_ips': [ {'subnet_id': subnet_v4_id}, {'subnet_id': subnet_v6_id}, ] } } fake_port_response = self._get_fake_port( docker_endpoint_id, fake_neutron_network_id, fake_neutron_port_id, neutron_subnet_v4_id=subnet_v4_id, neutron_subnet_v6_id=subnet_v6_id, neutron_subnet_v4_address='192.168.1.2', neutron_subnet_v6_address="fe80::f816:3eff:fe20:57c4") app.neutron.create_port( fake_port_request).AndReturn(fake_port_response) self.mox.ReplayAll() request = { 'NetworkID': docker_network_id, 'EndpointID': docker_endpoint_id, 'Options': {}, 'Interface': { 'MacAddress': "fa:16:3e:20:57:c3" } } response = self.app.post('/NetworkDriver.CreateEndpoint', content_type='application/json', data=jsonutils.dumps(request)) self.assertEqual(200, response.status_code) decoded_json = jsonutils.loads(response.data) expected = {'Interface': request['Interface']} # Address and AddressIPv6, allocated by Neutron's IPAM automatically # should be contained in the response. self.assertNotEqual(expected, decoded_json) self.assertIn('Address', decoded_json['Interface']) self.assertIn('AddressIPv6', decoded_json['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)
def test_get_port_name(self): fake_docker_endpoint_id = utils.get_hash() generated_neutron_port_name = utils.get_neutron_port_name( fake_docker_endpoint_id) self.assertIn(utils.PORT_POSTFIX, generated_neutron_port_name) self.assertIn(fake_docker_endpoint_id, generated_neutron_port_name)