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_leave_unbinding_failure(self, GivenException): fake_docker_network_id = utils.get_hash() fake_docker_endpoint_id = utils.get_hash() 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, const.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] 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 _get_fake_port_request(neutron_network_id, docker_endpoint_id, neutron_subnetv4_id, neutron_subnetv6_id): fake_port_request = { 'port': { 'name': utils.get_neutron_port_name(docker_endpoint_id), 'admin_state_up': True, "binding:host_id": lib_utils.get_hostname(), 'device_owner': lib_const.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 } } return fake_port_request
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 _get_fake_port_map( neutron_network_id, docker_endpoint_id, neutron_subnetv4_id, neutron_subnetv6_id): fake_port = { "port": { "status": "DOWN", "name": utils.get_neutron_port_name(docker_endpoint_id), "allowed_address_pairs": [], "admin_state_up": True, "binding:host_id": lib_utils.get_hostname(), "network_id": neutron_network_id, "tenant_id": "d6700c0c9ffa4f1cb322cd4a1f3906fa", 'device_owner': lib_const.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": [], } } return fake_port
def update_port(self, port, endpoint_id, interface_mac): """Updates port information and performs extra driver-specific actions. It returns the updated port dictionary after the required actions performed depending on the binding driver. :param port: a neutron port dictionary returned from python-neutronclient :param endpoint_id: the ID of the endpoint as string :param interface_mac: the MAC address of the endpoint :returns: the updated Neutron port id dictionary as returned by python-neutronclient """ port['name'] = libnet_utils.get_neutron_port_name(endpoint_id) try: updated_port = { 'name': port['name'], 'device_owner': lib_const.DEVICE_OWNER, 'binding:host_id': lib_utils.get_hostname(), } if not port.get('device_id'): updated_port['device_id'] = endpoint_id if interface_mac: updated_port['mac_address'] = interface_mac response_port = app.neutron.update_port(port['id'], {'port': updated_port}) except n_exceptions.NeutronClientException as ex: LOG.error("Error happened during updating a " "Neutron port: %s", ex) raise return response_port['port']
def _get_fake_port(docker_endpoint_id, neutron_network_id, neutron_port_id, neutron_port_status=lib_const.PORT_STATUS_DOWN, 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", neutron_mac_address="fa:16:3e:20:57:c3", device_owner=None, neutron_trunk_id=None, tags=None, name=None, binding_profile=None): # The following fake response is retrieved from the Neutron doc: # http://developer.openstack.org/api-ref-networking-v2.html#createPort # noqa if not name: name = utils.get_neutron_port_name(docker_endpoint_id) fake_port = { 'port': { "status": neutron_port_status, "name": name, "allowed_address_pairs": [], "admin_state_up": True, "network_id": neutron_network_id, "tenant_id": "d6700c0c9ffa4f1cb322cd4a1f3906fa", "device_owner": device_owner, "mac_address": neutron_mac_address, "fixed_ips": [], "id": neutron_port_id, "security_groups": [], "device_id": docker_endpoint_id, "tags": tags } } if binding_profile is not None: fake_port['port']['binding:profile'] = binding_profile 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 }) if neutron_trunk_id: fake_port['port']['trunk_details'] = {'trunk_id': neutron_trunk_id} return fake_port
def test_delete_endpoint_delete_host_iface_failure(self, GivenException, mock_list_networks, mock_list_ports, mock_delete_host_iface): fake_docker_network_id = lib_utils.get_hash() fake_docker_endpoint_id = lib_utils.get_hash() fake_neutron_network_id = uuidutils.generate_uuid() fake_neutron_port_id = uuidutils.generate_uuid() fake_neutron_v4_subnet_id = uuidutils.generate_uuid() fake_neutron_v6_subnet_id = uuidutils.generate_uuid() t = utils.make_net_tags(fake_docker_network_id) mock_list_networks.return_value = self._get_fake_list_network( fake_neutron_network_id) neutron_port_name = utils.get_neutron_port_name( fake_docker_endpoint_id) fake_neutron_ports_response = self._get_fake_ports( fake_docker_endpoint_id, fake_neutron_network_id, fake_neutron_port_id, lib_const.PORT_STATUS_ACTIVE, fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id) mock_list_ports.return_value = fake_neutron_ports_response fake_neutron_port = fake_neutron_ports_response['ports'][0] fake_message = "fake message" if GivenException == n_exceptions.NeutronClientException: fake_exception = GivenException(fake_message, status_code=500) else: fake_exception = GivenException(fake_message) mock_delete_host_iface.side_effect = fake_exception response = self._invoke_delete_request(fake_docker_network_id, fake_docker_endpoint_id) self.assertEqual(w_exceptions.InternalServerError.code, response.status_code) mock_list_networks.assert_called_with(tags=t) mock_list_ports.assert_called_with(name=neutron_port_name) mock_delete_host_iface.assert_called_with(fake_docker_endpoint_id, fake_neutron_port) decoded_json = jsonutils.loads(response.data) self.assertIn('Err', decoded_json) self.assertIn(fake_message, decoded_json['Err'])
def update_port(self, port, endpoint_id, interface_mac, tags=True): """Updates port information and performs extra driver-specific actions. It returns the updated port dictionary after the required actions performed depending on the binding driver. :param port: a neutron port dictionary returned from python-neutronclient :param endpoint_id: the ID of the endpoint as string :param interface_mac: the MAC address of the endpoint :returns: the updated Neutron port id dictionary as returned by python-neutronclient """ try: updated_port = {} hostname = lib_utils.get_hostname() if port['binding:host_id'] != hostname: updated_port['binding:host_id'] = hostname updated_port['device_owner'] = lib_const.DEVICE_OWNER if port['admin_state_up'] is not True: updated_port['admin_state_up'] = True if not tags: # rename the port if tagging is not supported updated_port['name'] = libnet_utils.get_neutron_port_name( endpoint_id) if not port.get('device_id'): updated_port['device_id'] = endpoint_id if interface_mac and port['mac_address'] != interface_mac: updated_port['mac_address'] = interface_mac if updated_port: port = app.neutron.update_port(port['id'], {'port': updated_port})['port'] except n_exceptions.NeutronClientException as ex: LOG.error("Error happened during updating a " "Neutron port: %s", ex) raise return port
def _get_fake_port(docker_endpoint_id, neutron_network_id, neutron_port_id, neutron_port_status=const.PORT_STATUS_DOWN, 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": neutron_port_status, "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 update_port(self, port, endpoint_id, interface_mac, tags=True): """Updates port information and performs extra driver-specific actions. It returns the updated port dictionary after the required actions performed depending on the binding driver. :param port: a neutron port dictionary returned from python-neutronclient :param endpoint_id: the ID of the endpoint as string :param interface_mac: the MAC address of the endpoint :returns: the updated Neutron port id dictionary as returned by python-neutronclient """ try: updated_port = {} hostname = lib_utils.get_hostname() if port['binding:host_id'] != hostname: updated_port['binding:host_id'] = hostname updated_port['device_owner'] = lib_const.DEVICE_OWNER if port['admin_state_up'] is not True: updated_port['admin_state_up'] = True if not tags: # rename the port if tagging is not supported updated_port['name'] = libnet_utils.get_neutron_port_name( endpoint_id) if not port.get('device_id'): updated_port['device_id'] = endpoint_id if interface_mac and port['mac_address'] != interface_mac: updated_port['mac_address'] = interface_mac if updated_port: port = app.neutron.update_port(port['id'], {'port': updated_port})['port'] except n_exceptions.NeutronClientException as ex: LOG.error("Error happened during updating a " "Neutron port: %s", ex) raise return port
def test_container_ipam_request_address_with_existing_port(self): # pre-created Neutron network and subnet and port neutron_net_name = lib_utils.get_random_string(8) neutron_network = self.neutron_client.create_network( {'network': {'name': neutron_net_name, "admin_state_up": True}}) neutron_subnet_name = lib_utils.get_random_string(8) subnet_param = [{ 'name': neutron_subnet_name, 'network_id': neutron_network['network']['id'], 'ip_version': 4, 'cidr': "10.14.0.0/24", }] neutron_subnet = self.neutron_client.create_subnet( {'subnets': subnet_param}) neutron_v6_subnet_name = lib_utils.get_random_string(8) v6_subnet_param = [{ 'name': neutron_v6_subnet_name, 'network_id': neutron_network['network']['id'], 'ip_version': 6, 'cidr': "fe81::/64", }] neutron_v6_subnet = self.neutron_client.create_subnet( {'subnets': v6_subnet_param}) existing_neutron_port = self.neutron_client.create_port( {'port': {'network_id': neutron_network['network']['id']}}) fixed_ips = {fip['subnet_id']: fip['ip_address'] for fip in existing_neutron_port['port']['fixed_ips']} ipv4_address = fixed_ips[neutron_subnet['subnets'][0]['id']] ipv6_address = fixed_ips[neutron_v6_subnet['subnets'][0]['id']] fake_ipam = { "Driver": "kuryr", "Options": {}, "Config": [ { "Subnet": "10.14.0.0/24", "Gateway": "10.14.0.1" }, { "Subnet": "fe81::/64", "Gateway": "fe81::1" }, ] } # Create docker network using existing Neutron network options = {'neutron.net.name': neutron_net_name} container_net_name = lib_utils.get_random_string(8) container_net = self.docker_client.create_network( name=container_net_name, driver='kuryr', enable_ipv6=True, options=options, ipam=fake_ipam) container_net_id = container_net.get('Id') try: networks = self.neutron_client.list_networks( tags=utils.make_net_tags(container_net_id)) except Exception as e: self.docker_client.remove_network(container_net_id) message = ("Failed to list neutron networks: %s") self.fail(message % e.args[0]) self.assertEqual(1, len(networks['networks'])) # Boot a container, and connect to the docker network. container_name = lib_utils.get_random_string(8) container = self.docker_client.create_container( image='kuryr/busybox', command='/bin/sleep 600', hostname='kuryr_test_container', name=container_name) warn_msg = container.get('Warning') container_id = container.get('Id') self.assertIsNone(warn_msg, 'Warn in creating container') self.assertIsNotNone(container_id, 'Create container id must not ' 'be None') self.docker_client.start(container=container_id) self.docker_client.connect_container_to_network( container_id, container_net_id, ipv4_address=ipv4_address, ipv6_address=ipv6_address) try: ports = self.neutron_client.list_ports( network_id=neutron_network['network']['id']) except Exception as e: self.docker_client.disconnect_container_from_network( container_id, container_net_id) message = ("Failed to list neutron ports: %s") self.fail(message % e.args[0]) # A dhcp port gets created as well; dhcp is enabled by default self.assertEqual(2, len(ports['ports'])) # Find the existing neutron port neutron_port_param = {"network_id": neutron_network['network']['id']} neutron_ports = self.neutron_client.list_ports( **neutron_port_param) neutron_port = [port for port in neutron_ports['ports'] if (const.KURYR_EXISTING_NEUTRON_PORT in port['tags'] or port['name'] == utils.get_neutron_port_name(port['device_id']))] self.assertEqual(1, len(neutron_port)) # Disconnect container from network. self.docker_client.disconnect_container_from_network(container_id, container_net_id) ports = self.neutron_client.list_ports( network_id=neutron_network['network']['id']) self.assertEqual(2, len(ports['ports'])) neutron_ports = self.neutron_client.list_ports( **neutron_port_param) neutron_port = [port for port in neutron_ports['ports'] if (const.KURYR_EXISTING_NEUTRON_PORT in port['tags'] or port['name'] == utils.get_neutron_port_name(port['device_id']))] self.assertEqual(0, len(neutron_port)) # Cleanup resources self.docker_client.stop(container=container_id) self.docker_client.remove_network(container_net_id) self.neutron_client.delete_port(existing_neutron_port['port']['id']) self.neutron_client.delete_subnet(neutron_subnet['subnets'][0]['id']) self.neutron_client.delete_subnet( neutron_v6_subnet['subnets'][0]['id']) self.neutron_client.delete_network(neutron_network['network']['id'])
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_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)
def test_create_host_iface_failures(self, GivenException, mock_list_networks, mock_list_ports, mock_list_subnets, mock_update_port, mock_create_host_iface): fake_docker_network_id = lib_utils.get_hash() fake_docker_endpoint_id = lib_utils.get_hash() fake_neutron_network_id = uuidutils.generate_uuid() fake_neutron_network = self._get_fake_list_network( fake_neutron_network_id) t = utils.make_net_tags(fake_docker_network_id) mock_list_networks.return_value = fake_neutron_network fake_neutron_v4_subnet_id = uuidutils.generate_uuid() fake_neutron_v6_subnet_id = uuidutils.generate_uuid() fake_v4_subnet = self._get_fake_v4_subnet(fake_docker_network_id, fake_docker_endpoint_id, fake_neutron_v4_subnet_id) fake_v6_subnet = self._get_fake_v6_subnet(fake_docker_network_id, fake_docker_endpoint_id, fake_neutron_v6_subnet_id) fake_v4_subnet_response = { "subnets": [ fake_v4_subnet['subnet'] ] } fake_v6_subnet_response = { "subnets": [ fake_v6_subnet['subnet'] ] } def fake_subnet_response(network_id, cidr): if cidr == '192.168.1.0/24': return fake_v4_subnet_response elif cidr == 'fe80::/64': return fake_v6_subnet_response else: return {'subnets': []} mock_list_subnets.side_effect = fake_subnet_response fake_neutron_port_id = uuidutils.generate_uuid() fake_fixed_ips = ['subnet_id=%s' % fake_neutron_v4_subnet_id, 'ip_address=192.168.1.2', 'subnet_id=%s' % fake_neutron_v6_subnet_id, 'ip_address=fe80::f816:3eff:fe20:57c4'] fake_port_response = self._get_fake_port( fake_docker_endpoint_id, fake_neutron_network_id, fake_neutron_port_id, lib_const.PORT_STATUS_ACTIVE, fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id) fake_ports_response = { "ports": [ fake_port_response['port'] ] } mock_list_ports.return_value = fake_ports_response fake_updated_port = fake_port_response['port'] fake_updated_port['name'] = utils.get_neutron_port_name( fake_docker_endpoint_id) mock_update_port.return_value = fake_port_response['port'] fake_neutron_subnets = [fake_v4_subnet['subnet'], fake_v6_subnet['subnet']] fake_message = "fake message" if GivenException == n_exceptions.NeutronClientException: fake_exception = GivenException(fake_message, status_code=500) else: fake_exception = GivenException(fake_message) mock_create_host_iface.side_effect = fake_exception response = self._invoke_create_request( fake_docker_network_id, fake_docker_endpoint_id) self.assertEqual( w_exceptions.InternalServerError.code, response.status_code) mock_list_networks.assert_called_with(tags=t) expect_calls = [mock.call(cidr='192.168.1.0/24', network_id=fake_neutron_network_id), mock.call(cidr='fe80::/64', network_id=fake_neutron_network_id)] mock_list_subnets.assert_has_calls(expect_calls, any_order=True) mock_list_ports.assert_called_with(fixed_ips=fake_fixed_ips) mock_update_port.assert_called_with(fake_port_response['port'], fake_docker_endpoint_id, "fa:16:3e:20:57:c3") mock_create_host_iface.assert_called_with( fake_docker_endpoint_id, fake_updated_port, fake_neutron_subnets, fake_neutron_network['networks'][0]) decoded_json = jsonutils.loads(response.data) self.assertIn('Err', decoded_json) self.assertIn(fake_message, decoded_json['Err'])
def test_network_driver_program_external_connectivity(self, existing_sg, num_ports): fake_docker_net_id = utils.get_hash() fake_docker_endpoint_id = utils.get_hash() fake_neutron_net_id = str(uuid.uuid4()) 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) if existing_sg: fake_neutron_existing_sec_group_id = str(uuid.uuid4()) fake_neutron_ports_response['ports'][0]['security_groups'] = [ fake_neutron_existing_sec_group_id] app.neutron.list_ports(name=neutron_port_name).AndReturn( fake_neutron_ports_response) sec_group = { 'name': utils.get_sg_expose_name(fake_neutron_port_id), 'description': 'Docker exposed ports created by Kuryr.' } self.mox.StubOutWithMock(app.neutron, 'create_security_group') fake_neutron_sec_group_id = utils.get_hash() fake_neutron_sec_group_response = {'security_group': {'id': fake_neutron_sec_group_id}} app.neutron.create_security_group({'security_group': sec_group}).AndReturn( fake_neutron_sec_group_response) self.mox.StubOutWithMock(app.neutron, 'create_security_group_rule') for i in range(num_ports): sec_group_rule = { 'security_group_id': fake_neutron_sec_group_id, 'direction': 'ingress', 'port_range_min': PORT + i, 'port_range_max': PORT + i, 'protocol': constants.PROTOCOLS[PROTOCOL] } app.neutron.create_security_group_rule({'security_group_rule': sec_group_rule}) sgs = [fake_neutron_sec_group_id] if existing_sg: sgs.append(fake_neutron_existing_sec_group_id) self.mox.StubOutWithMock(app.neutron, 'show_port') app.neutron.show_port(fake_neutron_port_id).AndReturn( {'port': fake_neutron_ports_response['ports'][0]}) self.mox.StubOutWithMock(app.neutron, 'update_port') app.neutron.update_port(fake_neutron_port_id, {'port': {'security_groups': sgs}}) self.mox.ReplayAll() port_opt = [] for i in range(num_ports): port_opt.append({u'Port': PORT + i, u'Proto': PROTOCOL}) options = {'com.docker.network.endpoint.exposedports': port_opt, 'com.docker.network.portmap': []} data = { 'NetworkID': fake_docker_net_id, 'EndpointID': fake_docker_endpoint_id, 'Options': options, } response = self.app.post('/NetworkDriver.ProgramExternalConnectivity', content_type='application/json', data=jsonutils.dumps(data)) self.assertEqual(200, response.status_code) decoded_json = jsonutils.loads(response.data) self.assertEqual(constants.SCHEMA['SUCCESS'], decoded_json)
def test_container_ipam_release_address_with_existing_network(self): # pre-created Neutron network and subnet neutron_net_name = lib_utils.get_random_string(8) neutron_network = self.neutron_client.create_network( {'network': { 'name': neutron_net_name, "admin_state_up": True }}) neutron_subnet_name = lib_utils.get_random_string(8) subnet_param = [{ 'name': neutron_subnet_name, 'network_id': neutron_network['network']['id'], 'ip_version': 4, 'cidr': "10.10.0.0/24", 'enable_dhcp': True, }] self.neutron_client.create_subnet({'subnets': subnet_param}) fake_ipam = { "Driver": "kuryr", "Options": {}, "Config": [{ "Subnet": "10.10.0.0/16", "IPRange": "10.10.0.0/24", "Gateway": "10.10.0.1" }] } # Create docker network using existing Neutron network options = {'neutron.net.name': neutron_net_name} container_net_name = lib_utils.get_random_string(8) container_net = self.docker_client.create_network( name=container_net_name, driver='kuryr', options=options, ipam=fake_ipam) container_net_id = container_net.get('Id') try: networks = self.neutron_client.list_networks( tags=utils.make_net_tags(container_net_id)) except Exception as e: self.docker_client.remove_network(container_net_id) message = ("Failed to list neutron networks: %s") self.fail(message % e.args[0]) self.assertEqual(1, len(networks['networks'])) # Boot a container, and connect to the docker network. container_name = lib_utils.get_random_string(8) container = self.docker_client.create_container( image='kuryr/busybox', command='/bin/sleep 600', hostname='kuryr_test_container', name=container_name) warn_msg = container.get('Warning') container_id = container.get('Id') self.assertIsNone(warn_msg, 'Warn in creating container') self.assertIsNotNone(container_id, 'Create container id must not ' 'be None') self.docker_client.start(container=container_id) self.docker_client.connect_container_to_network( container_id, container_net_id) try: ports = self.neutron_client.list_ports( network_id=neutron_network['network']['id']) except Exception as e: self.docker_client.disconnect_container_from_network( container_id, container_net_id) message = ("Failed to list neutron ports: %s") self.fail(message % e.args[0]) # A dhcp port gets created as well; dhcp is enabled by default self.assertEqual(2, len(ports['ports'])) # Find the kuryr port kuryr_port_param = {"network_id": neutron_network['network']['id']} kuryr_ports = self.neutron_client.list_ports(**kuryr_port_param) kuryr_port = [ port for port in kuryr_ports['ports'] if (lib_const.DEVICE_OWNER in port['tags'] or port['name'] == utils.get_neutron_port_name(port['device_id'])) ] self.assertEqual(1, len(kuryr_port)) # Disconnect container from network, this release ip address. self.docker_client.disconnect_container_from_network( container_id, container_net_id) ports = self.neutron_client.list_ports( network_id=neutron_network['network']['id']) self.assertEqual(1, len(ports['ports'])) kuryr_ports = self.neutron_client.list_ports(**kuryr_port_param) kuryr_port = [ port for port in kuryr_ports['ports'] if (lib_const.DEVICE_OWNER in port['tags'] or port['name'] == utils.get_neutron_port_name(port['device_id'])) ] self.assertEqual(0, len(kuryr_port)) # Cleanup resources self.docker_client.stop(container=container_id) self.docker_client.remove_network(container_net_id) self.neutron_client.delete_network(neutron_network['network']['id'])
def test_container_ipam_release_address_with_existing_network(self): # pre-created Neutron network and subnet neutron_net_name = lib_utils.get_random_string(8) neutron_network = self.neutron_client.create_network( {'network': {'name': neutron_net_name, "admin_state_up": True}}) neutron_subnet_name = lib_utils.get_random_string(8) subnet_param = [{ 'name': neutron_subnet_name, 'network_id': neutron_network['network']['id'], 'ip_version': 4, 'cidr': "10.10.0.0/24", 'enable_dhcp': True, }] self.neutron_client.create_subnet({'subnets': subnet_param}) fake_ipam = { "Driver": "kuryr", "Options": {}, "Config": [ { "Subnet": "10.10.0.0/16", "IPRange": "10.10.0.0/24", "Gateway": "10.10.0.1" } ] } # Create docker network using existing Neutron network options = {'neutron.net.name': neutron_net_name} container_net_name = lib_utils.get_random_string(8) container_net = self.docker_client.create_network( name=container_net_name, driver='kuryr', options=options, ipam=fake_ipam) container_net_id = container_net.get('Id') try: networks = self.neutron_client.list_networks( tags=utils.make_net_tags(container_net_id)) except Exception as e: self.docker_client.remove_network(container_net_id) message = ("Failed to list neutron networks: %s") self.fail(message % e.args[0]) self.assertEqual(1, len(networks['networks'])) # Boot a container, and connect to the docker network. container_name = lib_utils.get_random_string(8) container = self.docker_client.create_container( image='kuryr/busybox', command='/bin/sleep 600', hostname='kuryr_test_container', name=container_name) warn_msg = container.get('Warning') container_id = container.get('Id') self.assertIsNone(warn_msg, 'Warn in creating container') self.assertIsNotNone(container_id, 'Create container id must not ' 'be None') self.docker_client.start(container=container_id) self.docker_client.connect_container_to_network(container_id, container_net_id) try: ports = self.neutron_client.list_ports( network_id=neutron_network['network']['id']) except Exception as e: self.docker_client.disconnect_container_from_network( container_id, container_net_id) message = ("Failed to list neutron ports: %s") self.fail(message % e.args[0]) # A dhcp port gets created as well; dhcp is enabled by default self.assertEqual(2, len(ports['ports'])) # Find the kuryr port kuryr_port_param = {"network_id": neutron_network['network']['id']} kuryr_ports = self.neutron_client.list_ports( **kuryr_port_param) kuryr_port = [port for port in kuryr_ports['ports'] if (lib_const.DEVICE_OWNER in port['tags'] or port['name'] == utils.get_neutron_port_name(port['device_id']))] self.assertEqual(1, len(kuryr_port)) # Disconnect container from network, this release ip address. self.docker_client.disconnect_container_from_network(container_id, container_net_id) ports = self.neutron_client.list_ports( network_id=neutron_network['network']['id']) self.assertEqual(1, len(ports['ports'])) kuryr_ports = self.neutron_client.list_ports( **kuryr_port_param) kuryr_port = [port for port in kuryr_ports['ports'] if (lib_const.DEVICE_OWNER in port['tags'] or port['name'] == utils.get_neutron_port_name(port['device_id']))] self.assertEqual(0, len(kuryr_port)) # Cleanup resources self.docker_client.stop(container=container_id) self.docker_client.remove_network(container_net_id) self.neutron_client.delete_network(neutron_network['network']['id'])
def test_container_ipam_request_address(self): fake_ipam = { "Driver": "kuryr", "Options": {}, "Config": [{ "Subnet": "10.12.0.0/16", "IPRange": "10.12.0.0/24", "Gateway": "10.12.0.1" }] } container_net_name = lib_utils.get_random_string(8) container_net = self.docker_client.create_network( name=container_net_name, driver='kuryr', ipam=fake_ipam) container_net_id = container_net.get('Id') try: networks = self.neutron_client.list_networks( tags=utils.make_net_tags(container_net_id)) except Exception as e: self.docker_client.remove_network(container_net_id) message = ("Failed to list neutron networks: %s") self.fail(message % e.args[0]) # Currently we cannot get IPAM pool from docker client. pool_name = "kuryrPool-" + "10.12.0.0/24" subnetpools = self.neutron_client.list_subnetpools(name=pool_name) self.assertEqual(1, len(subnetpools['subnetpools'])) subnets = self.neutron_client.list_subnets( network_id=networks['networks'][0]['id'], cidr="10.12.0.0/24") self.assertEqual(1, len(subnets['subnets'])) # Boot a container, and connect to the docker network. container_name = lib_utils.get_random_string(8) container = self.docker_client.create_container( image='kuryr/busybox', command='/bin/sleep 600', hostname='kuryr_test_container', name=container_name) warn_msg = container.get('Warning') container_id = container.get('Id') self.assertIsNone(warn_msg, 'Warn in creating container') self.assertIsNotNone(container_id, 'Create container id must not ' 'be None') self.docker_client.start(container=container_id) self.docker_client.connect_container_to_network( container_id, container_net_id) try: ports = self.neutron_client.list_ports( network_id=networks['networks'][0]['id']) except Exception as e: self.docker_client.disconnect_container_from_network( container_id, container_net_id) message = ("Failed to list neutron ports: %s") self.fail(message % e.args[0]) # DHCP port and container endpoint self.assertEqual(2, len(ports['ports'])) # Find the kuryr port kuryr_port_param = {"network_id": networks['networks'][0]['id']} kuryr_ports = self.neutron_client.list_ports(**kuryr_port_param) kuryr_port = [ port for port in kuryr_ports['ports'] if (lib_const.DEVICE_OWNER in port['tags'] or port['name'] == utils.get_neutron_port_name(port['device_id'])) ] self.assertEqual(1, len(kuryr_port)) # Disconnect container from network, this release ip address. self.docker_client.disconnect_container_from_network( container_id, container_net_id) # Cleanup resources self.docker_client.stop(container=container_id) self.docker_client.remove_network(container_net_id)
def test_network_driver_revoke_external_connectivity(self, existing_sg, removing_sg, mock_list_ports, mock_list_security_groups, mock_delete_security_groups, mock_show_port, mock_update_port): config.CONF.set_override('process_external_connectivity', True) fake_docker_net_id = lib_utils.get_hash() fake_docker_endpoint_id = lib_utils.get_hash() fake_neutron_net_id = uuidutils.generate_uuid() fake_neutron_port_id = uuidutils.generate_uuid() fake_neutron_sec_group_id = lib_utils.get_hash() neutron_port_name = utils.get_neutron_port_name( fake_docker_endpoint_id) fake_neutron_v4_subnet_id = uuidutils.generate_uuid() fake_neutron_v6_subnet_id = uuidutils.generate_uuid() fake_neutron_ports_response = self._get_fake_ports( fake_docker_endpoint_id, fake_neutron_net_id, fake_neutron_port_id, lib_const.PORT_STATUS_ACTIVE, fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id) if existing_sg: fake_neutron_existing_sec_group_id = uuidutils.generate_uuid() fake_neutron_ports_response['ports'][0]['security_groups'] = [ fake_neutron_sec_group_id, fake_neutron_existing_sec_group_id] else: fake_neutron_ports_response['ports'][0]['security_groups'] = [ fake_neutron_sec_group_id] if removing_sg: fake_neutron_sec_group_response = { 'security_groups': [{'id': fake_neutron_sec_group_id}]} else: fake_neutron_sec_group_response = { 'security_groups': []} mock_list_ports.return_value = fake_neutron_ports_response mock_list_security_groups.return_value = ( fake_neutron_sec_group_response) mock_show_port.return_value = {'port': fake_neutron_ports_response['ports'][0]} if existing_sg: sgs = [fake_neutron_existing_sec_group_id] else: sgs = [] data = { 'NetworkID': fake_docker_net_id, 'EndpointID': fake_docker_endpoint_id, } response = self.app.post('/NetworkDriver.RevokeExternalConnectivity', content_type='application/json', data=jsonutils.dumps(data)) self.assertEqual(200, response.status_code) mock_list_ports.assert_called_with(name=neutron_port_name) if removing_sg: mock_list_security_groups.assert_called_with( name=utils.get_sg_expose_name(fake_neutron_port_id)) mock_delete_security_groups.assert_called_with( fake_neutron_sec_group_id) mock_show_port.assert_called_with(fake_neutron_port_id) mock_update_port.assert_called_with(fake_neutron_port_id, {'port': {'security_groups': sgs}}) else: mock_list_security_groups.assert_called_with( name=utils.get_sg_expose_name(fake_neutron_port_id)) mock_delete_security_groups.assert_not_called() mock_show_port.assert_not_called() mock_update_port.assert_not_called() decoded_json = jsonutils.loads(response.data) self.assertEqual(constants.SCHEMA['SUCCESS'], decoded_json)
def test_network_driver_revoke_external_connectivity( self, existing_sg, removing_sg, mock_list_ports, mock_list_security_groups, mock_delete_security_groups, mock_show_port, mock_update_port): fake_docker_net_id = lib_utils.get_hash() fake_docker_endpoint_id = lib_utils.get_hash() fake_neutron_net_id = uuidutils.generate_uuid() fake_neutron_port_id = uuidutils.generate_uuid() fake_neutron_sec_group_id = lib_utils.get_hash() neutron_port_name = utils.get_neutron_port_name( fake_docker_endpoint_id) fake_neutron_v4_subnet_id = uuidutils.generate_uuid() fake_neutron_v6_subnet_id = uuidutils.generate_uuid() fake_neutron_ports_response = self._get_fake_ports( fake_docker_endpoint_id, fake_neutron_net_id, fake_neutron_port_id, lib_const.PORT_STATUS_ACTIVE, fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id) if existing_sg: fake_neutron_existing_sec_group_id = uuidutils.generate_uuid() fake_neutron_ports_response['ports'][0]['security_groups'] = [ fake_neutron_sec_group_id, fake_neutron_existing_sec_group_id ] else: fake_neutron_ports_response['ports'][0]['security_groups'] = [ fake_neutron_sec_group_id ] if removing_sg: fake_neutron_sec_group_response = { 'security_groups': [{ 'id': fake_neutron_sec_group_id }] } else: fake_neutron_sec_group_response = {'security_groups': []} mock_list_ports.return_value = fake_neutron_ports_response mock_list_security_groups.return_value = ( fake_neutron_sec_group_response) mock_show_port.return_value = { 'port': fake_neutron_ports_response['ports'][0] } if existing_sg: sgs = [fake_neutron_existing_sec_group_id] else: sgs = [] data = { 'NetworkID': fake_docker_net_id, 'EndpointID': fake_docker_endpoint_id, } response = self.app.post('/NetworkDriver.RevokeExternalConnectivity', content_type='application/json', data=jsonutils.dumps(data)) self.assertEqual(200, response.status_code) mock_list_ports.assert_called_with(name=neutron_port_name) if removing_sg: mock_list_security_groups.assert_called_with( name=utils.get_sg_expose_name(fake_neutron_port_id)) mock_delete_security_groups.assert_called_with( fake_neutron_sec_group_id) mock_show_port.assert_called_with(fake_neutron_port_id) mock_update_port.assert_called_with( fake_neutron_port_id, {'port': { 'security_groups': sgs }}) else: mock_list_security_groups.assert_called_with( name=utils.get_sg_expose_name(fake_neutron_port_id)) mock_delete_security_groups.assert_not_called() mock_show_port.assert_not_called() mock_update_port.assert_not_called() decoded_json = jsonutils.loads(response.data) self.assertEqual(constants.SCHEMA['SUCCESS'], decoded_json)
def test_container_ipam_request_address(self): fake_ipam = { "Driver": "kuryr", "Options": {}, "Config": [ { "Subnet": "10.12.0.0/16", "IPRange": "10.12.0.0/24", "Gateway": "10.12.0.1" } ] } container_net_name = lib_utils.get_random_string(8) container_net = self.docker_client.create_network( name=container_net_name, driver='kuryr', ipam=fake_ipam) container_net_id = container_net.get('Id') try: networks = self.neutron_client.list_networks( tags=utils.make_net_tags(container_net_id)) except Exception as e: self.docker_client.remove_network(container_net_id) message = ("Failed to list neutron networks: %s") self.fail(message % e.args[0]) # Currently we cannot get IPAM pool from docker client. pool_name = "kuryrPool-" + "10.12.0.0/24" subnetpools = self.neutron_client.list_subnetpools(name=pool_name) self.assertEqual(1, len(subnetpools['subnetpools'])) subnets = self.neutron_client.list_subnets( network_id=networks['networks'][0]['id'], cidr="10.12.0.0/24") self.assertEqual(1, len(subnets['subnets'])) # Boot a container, and connect to the docker network. container_name = lib_utils.get_random_string(8) container = self.docker_client.create_container( image='kuryr/busybox', command='/bin/sleep 600', hostname='kuryr_test_container', name=container_name) warn_msg = container.get('Warning') container_id = container.get('Id') self.assertIsNone(warn_msg, 'Warn in creating container') self.assertIsNotNone(container_id, 'Create container id must not ' 'be None') self.docker_client.start(container=container_id) self.docker_client.connect_container_to_network(container_id, container_net_id) try: ports = self.neutron_client.list_ports( network_id=networks['networks'][0]['id']) except Exception as e: self.docker_client.disconnect_container_from_network( container_id, container_net_id) message = ("Failed to list neutron ports: %s") self.fail(message % e.args[0]) # DHCP port and container endpoint self.assertEqual(2, len(ports['ports'])) # Find the kuryr port kuryr_port_param = {"network_id": networks['networks'][0]['id']} kuryr_ports = self.neutron_client.list_ports( **kuryr_port_param) kuryr_port = [port for port in kuryr_ports['ports'] if (lib_const.DEVICE_OWNER in port['tags'] or port['name'] == utils.get_neutron_port_name(port['device_id']))] self.assertEqual(1, len(kuryr_port)) # Disconnect container from network, this release ip address. self.docker_client.disconnect_container_from_network(container_id, container_net_id) # Cleanup resources self.docker_client.stop(container=container_id) self.docker_client.remove_network(container_net_id)
def test_network_driver_program_external_connectivity( self, existing_sg, num_ports, mock_list_ports, mock_create_security_group, mock_create_security_group_rule, mock_show_port, mock_update_port): fake_docker_net_id = lib_utils.get_hash() fake_docker_endpoint_id = lib_utils.get_hash() fake_neutron_net_id = uuidutils.generate_uuid() fake_neutron_port_id = uuidutils.generate_uuid() neutron_port_name = utils.get_neutron_port_name( fake_docker_endpoint_id) fake_neutron_v4_subnet_id = uuidutils.generate_uuid() fake_neutron_v6_subnet_id = uuidutils.generate_uuid() fake_neutron_ports_response = self._get_fake_ports( fake_docker_endpoint_id, fake_neutron_net_id, fake_neutron_port_id, lib_const.PORT_STATUS_ACTIVE, fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id) if existing_sg: fake_neutron_existing_sec_group_id = uuidutils.generate_uuid() fake_neutron_ports_response['ports'][0]['security_groups'] = [ fake_neutron_existing_sec_group_id ] mock_list_ports.return_value = fake_neutron_ports_response sec_group = { 'name': utils.get_sg_expose_name(fake_neutron_port_id), 'description': 'Docker exposed ports created by Kuryr.' } fake_neutron_sec_group_id = lib_utils.get_hash() fake_neutron_sec_group_response = { 'security_group': { 'id': fake_neutron_sec_group_id } } mock_create_security_group.return_value = ( fake_neutron_sec_group_response) proto_port_dict = defaultdict(list) for i in range(num_ports): proto_port_dict[constants.PROTOCOLS[PROTOCOL_TCP]].append(PORT + i) proto_port_dict[constants.PROTOCOLS[PROTOCOL_UDP]].append(PORT + i) proto_port_dict[constants.PROTOCOLS[PROTOCOL_UDP]].append(SINGLE_PORT) for proto, port_list in proto_port_dict.items(): for key, group in groupby(enumerate(sorted(port_list)), lambda ix: ix[0] - ix[1]): port_range_list = list(map(itemgetter(1), group)) port_range_min = min(port_range_list) port_range_max = max(port_range_list) sec_group_rule = { 'security_group_id': fake_neutron_sec_group_id, 'direction': 'ingress', 'port_range_min': port_range_min, 'port_range_max': port_range_max, 'protocol': proto } sgs = [fake_neutron_sec_group_id] if existing_sg: sgs.append(fake_neutron_existing_sec_group_id) mock_show_port.return_value = { 'port': fake_neutron_ports_response['ports'][0] } port_opt = [] for i in range(num_ports): port_opt.append({u'Port': PORT + i, u'Proto': PROTOCOL_TCP}) port_opt.append({u'Port': PORT + i, u'Proto': PROTOCOL_UDP}) port_opt.append({u'Port': SINGLE_PORT, u'Proto': PROTOCOL_UDP}) options = { 'com.docker.network.endpoint.exposedports': port_opt, 'com.docker.network.portmap': [] } data = { 'NetworkID': fake_docker_net_id, 'EndpointID': fake_docker_endpoint_id, 'Options': options, } response = self.app.post('/NetworkDriver.ProgramExternalConnectivity', content_type='application/json', data=jsonutils.dumps(data)) self.assertEqual(200, response.status_code) mock_update_port.assert_called_with(fake_neutron_port_id, {'port': { 'security_groups': sgs }}) mock_show_port.assert_called_with(fake_neutron_port_id) mock_create_security_group_rule.assert_called_with( {'security_group_rule': sec_group_rule}) mock_create_security_group.assert_called_with( {'security_group': sec_group}) mock_list_ports.assert_called_with(name=neutron_port_name) decoded_json = jsonutils.loads(response.data) self.assertEqual(constants.SCHEMA['SUCCESS'], decoded_json)
def test_network_driver_revoke_external_connectivity(self, existing_sg): fake_docker_net_id = utils.get_hash() fake_docker_endpoint_id = utils.get_hash() fake_neutron_net_id = str(uuid.uuid4()) fake_neutron_port_id = str(uuid.uuid4()) fake_neutron_sec_group_id = utils.get_hash() 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) if existing_sg: fake_neutron_existing_sec_group_id = str(uuid.uuid4()) fake_neutron_ports_response['ports'][0]['security_groups'] = [ fake_neutron_sec_group_id, fake_neutron_existing_sec_group_id] else: fake_neutron_ports_response['ports'][0]['security_groups'] = [ fake_neutron_sec_group_id] app.neutron.list_ports(name=neutron_port_name).AndReturn( fake_neutron_ports_response) self.mox.StubOutWithMock(app.neutron, 'list_security_groups') fake_neutron_sec_group_response = {'security_groups': [{'id': fake_neutron_sec_group_id}]} app.neutron.list_security_groups( name=utils.get_sg_expose_name(fake_neutron_port_id)).AndReturn( fake_neutron_sec_group_response) if existing_sg: sgs = [fake_neutron_existing_sec_group_id] else: sgs = [] self.mox.StubOutWithMock(app.neutron, 'show_port') app.neutron.show_port(fake_neutron_port_id).AndReturn( {'port': fake_neutron_ports_response['ports'][0]}) self.mox.StubOutWithMock(app.neutron, 'update_port') app.neutron.update_port(fake_neutron_port_id, {'port': {'security_groups': sgs}}) self.mox.StubOutWithMock(app.neutron, 'delete_security_group') app.neutron.delete_security_group(fake_neutron_sec_group_id) self.mox.ReplayAll() data = { 'NetworkID': fake_docker_net_id, 'EndpointID': fake_docker_endpoint_id, } response = self.app.post('/NetworkDriver.RevokeExternalConnectivity', content_type='application/json', data=jsonutils.dumps(data)) self.assertEqual(200, response.status_code) decoded_json = jsonutils.loads(response.data) self.assertEqual(constants.SCHEMA['SUCCESS'], decoded_json)
def test_container_ipam_request_address_with_existing_port(self): # pre-created Neutron network and subnet and port neutron_net_name = lib_utils.get_random_string(8) neutron_network = self.neutron_client.create_network( {'network': { 'name': neutron_net_name, "admin_state_up": True }}) neutron_subnet_name = lib_utils.get_random_string(8) subnet_param = [{ 'name': neutron_subnet_name, 'network_id': neutron_network['network']['id'], 'ip_version': 4, 'cidr': "10.14.0.0/24", }] neutron_subnet = self.neutron_client.create_subnet( {'subnets': subnet_param}) neutron_v6_subnet_name = lib_utils.get_random_string(8) v6_subnet_param = [{ 'name': neutron_v6_subnet_name, 'network_id': neutron_network['network']['id'], 'ip_version': 6, 'cidr': "fe81::/64", }] neutron_v6_subnet = self.neutron_client.create_subnet( {'subnets': v6_subnet_param}) existing_neutron_port = self.neutron_client.create_port( {'port': { 'network_id': neutron_network['network']['id'] }}) fixed_ips = { fip['subnet_id']: fip['ip_address'] for fip in existing_neutron_port['port']['fixed_ips'] } ipv4_address = fixed_ips[neutron_subnet['subnets'][0]['id']] ipv6_address = fixed_ips[neutron_v6_subnet['subnets'][0]['id']] fake_ipam = { "Driver": "kuryr", "Options": {}, "Config": [ { "Subnet": "10.14.0.0/24", "Gateway": "10.14.0.1" }, { "Subnet": "fe81::/64", "Gateway": "fe81::1" }, ] } # Create docker network using existing Neutron network options = {'neutron.net.name': neutron_net_name} container_net_name = lib_utils.get_random_string(8) container_net = self.docker_client.create_network( name=container_net_name, driver='kuryr', enable_ipv6=True, options=options, ipam=fake_ipam) container_net_id = container_net.get('Id') try: networks = self.neutron_client.list_networks( tags=utils.make_net_tags(container_net_id)) except Exception as e: self.docker_client.remove_network(container_net_id) message = ("Failed to list neutron networks: %s") self.fail(message % e.args[0]) self.assertEqual(1, len(networks['networks'])) # Boot a container, and connect to the docker network. container_name = lib_utils.get_random_string(8) container = self.docker_client.create_container( image='kuryr/busybox', command='/bin/sleep 600', hostname='kuryr_test_container', name=container_name) warn_msg = container.get('Warning') container_id = container.get('Id') self.assertIsNone(warn_msg, 'Warn in creating container') self.assertIsNotNone(container_id, 'Create container id must not ' 'be None') self.docker_client.start(container=container_id) self.docker_client.connect_container_to_network( container_id, container_net_id, ipv4_address=ipv4_address, ipv6_address=ipv6_address) try: ports = self.neutron_client.list_ports( network_id=neutron_network['network']['id']) except Exception as e: self.docker_client.disconnect_container_from_network( container_id, container_net_id) message = ("Failed to list neutron ports: %s") self.fail(message % e.args[0]) # A dhcp port gets created as well; dhcp is enabled by default self.assertEqual(2, len(ports['ports'])) # Find the existing neutron port neutron_port_param = {"network_id": neutron_network['network']['id']} neutron_ports = self.neutron_client.list_ports(**neutron_port_param) neutron_port = [ port for port in neutron_ports['ports'] if (const.KURYR_EXISTING_NEUTRON_PORT in port['tags'] or port['name'] == utils.get_neutron_port_name(port['device_id'])) ] self.assertEqual(1, len(neutron_port)) # Disconnect container from network. self.docker_client.disconnect_container_from_network( container_id, container_net_id) ports = self.neutron_client.list_ports( network_id=neutron_network['network']['id']) self.assertEqual(2, len(ports['ports'])) neutron_ports = self.neutron_client.list_ports(**neutron_port_param) neutron_port = [ port for port in neutron_ports['ports'] if (const.KURYR_EXISTING_NEUTRON_PORT in port['tags'] or port['name'] == utils.get_neutron_port_name(port['device_id'])) ] self.assertEqual(0, len(neutron_port)) # Cleanup resources self.docker_client.stop(container=container_id) self.docker_client.remove_network(container_net_id) self.neutron_client.delete_port(existing_neutron_port['port']['id']) self.neutron_client.delete_subnet(neutron_subnet['subnets'][0]['id']) self.neutron_client.delete_subnet( neutron_v6_subnet['subnets'][0]['id']) self.neutron_client.delete_network(neutron_network['network']['id'])
def test_network_driver_program_external_connectivity(self, existing_sg, num_ports, mock_list_ports, mock_create_security_group, mock_create_security_group_rule, mock_show_port, mock_update_port): config.CONF.set_override('process_external_connectivity', True) fake_docker_net_id = lib_utils.get_hash() fake_docker_endpoint_id = lib_utils.get_hash() fake_neutron_net_id = uuidutils.generate_uuid() fake_neutron_port_id = uuidutils.generate_uuid() neutron_port_name = utils.get_neutron_port_name( fake_docker_endpoint_id) fake_neutron_v4_subnet_id = uuidutils.generate_uuid() fake_neutron_v6_subnet_id = uuidutils.generate_uuid() fake_neutron_ports_response = self._get_fake_ports( fake_docker_endpoint_id, fake_neutron_net_id, fake_neutron_port_id, lib_const.PORT_STATUS_ACTIVE, fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id) if existing_sg: fake_neutron_existing_sec_group_id = uuidutils.generate_uuid() fake_neutron_ports_response['ports'][0]['security_groups'] = [ fake_neutron_existing_sec_group_id] mock_list_ports.return_value = fake_neutron_ports_response sec_group = { 'name': utils.get_sg_expose_name(fake_neutron_port_id), 'description': 'Docker exposed ports created by Kuryr.' } fake_neutron_sec_group_id = lib_utils.get_hash() fake_neutron_sec_group_response = {'security_group': {'id': fake_neutron_sec_group_id}} mock_create_security_group.return_value = ( fake_neutron_sec_group_response) proto_port_dict = defaultdict(list) for i in range(num_ports): proto_port_dict[constants.PROTOCOLS[PROTOCOL_TCP]].append(PORT + i) proto_port_dict[constants.PROTOCOLS[PROTOCOL_UDP]].append(PORT + i) proto_port_dict[constants.PROTOCOLS[PROTOCOL_UDP]].append(SINGLE_PORT) for proto, port_list in proto_port_dict.items(): for key, group in groupby(enumerate(sorted(port_list)), lambda ix: ix[0] - ix[1]): port_range_list = list(map(itemgetter(1), group)) port_range_min = min(port_range_list) port_range_max = max(port_range_list) sec_group_rule = { 'security_group_id': fake_neutron_sec_group_id, 'direction': 'ingress', 'port_range_min': port_range_min, 'port_range_max': port_range_max, 'protocol': proto } sgs = [fake_neutron_sec_group_id] if existing_sg: sgs.append(fake_neutron_existing_sec_group_id) mock_show_port.return_value = {'port': fake_neutron_ports_response['ports'][0]} port_opt = [] for i in range(num_ports): port_opt.append({u'Port': PORT + i, u'Proto': PROTOCOL_TCP}) port_opt.append({u'Port': PORT + i, u'Proto': PROTOCOL_UDP}) port_opt.append({u'Port': SINGLE_PORT, u'Proto': PROTOCOL_UDP}) options = {'com.docker.network.endpoint.exposedports': port_opt, 'com.docker.network.portmap': []} data = { 'NetworkID': fake_docker_net_id, 'EndpointID': fake_docker_endpoint_id, 'Options': options, } response = self.app.post('/NetworkDriver.ProgramExternalConnectivity', content_type='application/json', data=jsonutils.dumps(data)) self.assertEqual(200, response.status_code) mock_update_port.assert_called_with(fake_neutron_port_id, {'port': {'security_groups': sgs}}) mock_show_port.assert_called_with(fake_neutron_port_id) mock_create_security_group_rule.assert_called_with( {'security_group_rule': sec_group_rule}) mock_create_security_group.assert_called_with( {'security_group': sec_group}) mock_list_ports.assert_called_with(name=neutron_port_name) decoded_json = jsonutils.loads(response.data) self.assertEqual(constants.SCHEMA['SUCCESS'], decoded_json)
def test_create_host_iface_failures(self, GivenException, mock_list_networks, mock_list_ports, mock_list_subnets, mock_update_port, mock_create_host_iface): fake_docker_network_id = lib_utils.get_hash() fake_docker_endpoint_id = lib_utils.get_hash() fake_neutron_network_id = uuidutils.generate_uuid() fake_neutron_network = self._get_fake_list_network( fake_neutron_network_id) t = utils.make_net_tags(fake_docker_network_id) mock_list_networks.return_value = fake_neutron_network fake_neutron_v4_subnet_id = uuidutils.generate_uuid() fake_neutron_v6_subnet_id = uuidutils.generate_uuid() fake_v4_subnet = self._get_fake_v4_subnet(fake_docker_network_id, fake_docker_endpoint_id, fake_neutron_v4_subnet_id) fake_v6_subnet = self._get_fake_v6_subnet(fake_docker_network_id, fake_docker_endpoint_id, fake_neutron_v6_subnet_id) fake_v4_subnet_response = { "subnets": [ fake_v4_subnet['subnet'] ] } fake_v6_subnet_response = { "subnets": [ fake_v6_subnet['subnet'] ] } def fake_subnet_response(network_id, cidr): if cidr == '192.168.1.0/24': return fake_v4_subnet_response elif cidr == 'fe80::/64': return fake_v6_subnet_response else: return {'subnets': []} mock_list_subnets.side_effect = fake_subnet_response fake_neutron_port_id = uuidutils.generate_uuid() fake_fixed_ips = ['subnet_id=%s' % fake_neutron_v4_subnet_id, 'ip_address=192.168.1.2', 'subnet_id=%s' % fake_neutron_v6_subnet_id, 'ip_address=fe80::f816:3eff:fe20:57c4'] fake_port_response = self._get_fake_port( fake_docker_endpoint_id, fake_neutron_network_id, fake_neutron_port_id, lib_const.PORT_STATUS_ACTIVE, fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id, tags=utils.create_port_tags(fake_docker_endpoint_id)) fake_ports_response = { "ports": [ fake_port_response['port'] ] } mock_list_ports.return_value = fake_ports_response fake_updated_port = fake_port_response['port'] fake_updated_port['name'] = utils.get_neutron_port_name( fake_docker_endpoint_id) mock_update_port.return_value = fake_port_response['port'] fake_neutron_subnets = [fake_v4_subnet['subnet'], fake_v6_subnet['subnet']] fake_message = "fake message" if GivenException == n_exceptions.NeutronClientException: fake_exception = GivenException(fake_message, status_code=500) else: fake_exception = GivenException(fake_message) mock_create_host_iface.side_effect = fake_exception response = self._invoke_create_request( fake_docker_network_id, fake_docker_endpoint_id) self.assertEqual( w_exceptions.InternalServerError.code, response.status_code) mock_list_networks.assert_called_with(tags=t) expect_calls = [mock.call(cidr='192.168.1.0/24', network_id=fake_neutron_network_id), mock.call(cidr='fe80::/64', network_id=fake_neutron_network_id)] mock_list_subnets.assert_has_calls(expect_calls, any_order=True) mock_list_ports.assert_called_with(fixed_ips=fake_fixed_ips) mock_update_port.assert_called_with(fake_port_response['port'], fake_docker_endpoint_id, "fa:16:3e:20:57:c3", tags=True) mock_create_host_iface.assert_called_with( fake_docker_endpoint_id, fake_updated_port, fake_neutron_subnets, fake_neutron_network['networks'][0]) 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 = lib_utils.get_hash() generated_neutron_port_name = utils.get_neutron_port_name( fake_docker_endpoint_id) self.assertIn(lib_utils.PORT_POSTFIX, generated_neutron_port_name) self.assertIn(fake_docker_endpoint_id, generated_neutron_port_name)