diff -Nru neutron-13.0.0/AUTHORS neutron-13.0.1/AUTHORS --- neutron-13.0.0/AUTHORS 2018-08-30 14:17:12.000000000 +0000 +++ neutron-13.0.1/AUTHORS 2018-09-10 05:09:29.000000000 +0000 @@ -143,6 +143,7 @@ Chang Bo Guo ChangBo Guo(gcb) Chengli XU +Chengqian Liu Chirag Shahani Christian Berendt Christoph Arnold @@ -797,6 +798,7 @@ Tim Miller Tim Rozet Tim Swanson +Tobias Urdin Tom Cammann Tom Fifield Tom Holtzen diff -Nru neutron-13.0.0/ChangeLog neutron-13.0.1/ChangeLog --- neutron-13.0.0/ChangeLog 2018-08-30 14:17:11.000000000 +0000 +++ neutron-13.0.1/ChangeLog 2018-09-10 05:09:28.000000000 +0000 @@ -1,6 +1,19 @@ CHANGES ======= +13.0.1 +------ + +* ovs fw: apply the NORMAL action on egress traffic in a single table +* doc: Additional fixes to the SR-IOV doc +* Remove deprecated RamFilter from admin guide +* Fix incorrect log resources querying +* DVR: Add IPv6 csnat port address correctly +* import zuul job settings from project-config +* Reduce qos rpc times on the ovs-agent side +* Remove fdb entries for ha router interfaces when going DOWN +* Fix neutron-openvswitch-agent Windows support + 13.0.0 ------ diff -Nru neutron-13.0.0/debian/changelog neutron-13.0.1/debian/changelog --- neutron-13.0.0/debian/changelog 2018-09-25 13:12:54.000000000 +0000 +++ neutron-13.0.1/debian/changelog 2018-10-02 21:18:19.000000000 +0000 @@ -1,3 +1,13 @@ +neutron (2:13.0.1-0ubuntu1) cosmic; urgency=medium + + * New stable point release for OpenStack Rocky. + * d/p/revert-dvr-add-error-handling.patch: Cherry-picked from upstream to + revert DVR regressions (LP: #1751396) + * d/p/revert-dvr-inter-tenant.patch: Cherry-picked from upstream to revert + DVR regression (LP: #1783654). + + -- Corey Bryant Tue, 02 Oct 2018 17:18:19 -0400 + neutron (2:13.0.0-0ubuntu4) cosmic; urgency=medium * d/control: Update min version of python(3)-pecan to rocky version diff -Nru neutron-13.0.0/debian/patches/revert-dvr-add-error-handling.patch neutron-13.0.1/debian/patches/revert-dvr-add-error-handling.patch --- neutron-13.0.0/debian/patches/revert-dvr-add-error-handling.patch 1970-01-01 00:00:00.000000000 +0000 +++ neutron-13.0.1/debian/patches/revert-dvr-add-error-handling.patch 2018-10-02 21:18:19.000000000 +0000 @@ -0,0 +1,261 @@ +From d1a0d630d22180cbe602d56cfb308732add453de Mon Sep 17 00:00:00 2001 +From: Swaminathan Vasudevan +Date: Thu, 23 Aug 2018 06:10:42 +0000 +Subject: [PATCH 1/2] Revert "DVR: Add error handling for + get_network_info_for_id rpc call" + +This reverts commit c331b898e19c8125d005c09d8a6e247805e506a8. +Related-Bug: #1751396 + +Change-Id: I2e348091b5bdd0f3ef056dd108342989ce57062f +(cherry picked from commit 267eea50fd9e9c74faa96d529a7ec2fd8aa8d51f) +--- + .../agent/ovs_dvr_neutron_agent.py | 21 +- + .../agent/test_ovs_neutron_agent.py | 192 ------------------ + 2 files changed, 6 insertions(+), 207 deletions(-) + +diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_dvr_neutron_agent.py b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_dvr_neutron_agent.py +index dbbe167c8..d3f77cb88 100644 +--- a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_dvr_neutron_agent.py ++++ b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_dvr_neutron_agent.py +@@ -417,21 +417,12 @@ class OVSDVRNeutronAgent(object): + br = self.tun_br + # TODO(vivek) remove the IPv6 related flows once SNAT is not + # used for IPv6 DVR. +- port_net_info = None +- net_shared_only = False +- try: +- port_net_info = ( +- self.plugin_rpc.get_network_info_for_id( +- self.context, subnet_info.get('network_id'))) +- except oslo_messaging.RemoteError as e: +- LOG.error('L2 agent could not get network_info_for_id ' +- 'due to RPC error. It happens when the server ' +- 'does not support this RPC API. Detailed message: ' +- '%s', e) +- if port_net_info: +- net_shared_only = ( +- port_net_info[0]['shared'] and +- not port_net_info[0]['router:external']) ++ port_net_info = ( ++ self.plugin_rpc.get_network_info_for_id( ++ self.context, subnet_info.get('network_id'))) ++ net_shared_only = ( ++ port_net_info[0]['shared'] and ++ not port_net_info[0]['router:external']) + if net_shared_only: + LOG.debug("Not applying DVR rules to tunnel bridge because %s " + "is a shared network", subnet_info.get('network_id')) +diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py +index 30f43afde..17882b315 100644 +--- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py ++++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py +@@ -2788,188 +2788,6 @@ class TestOvsDvrNeutronAgent(object): + self.assertEqual([], tun_br.mock_calls) + self.assertEqual([], phys_br.mock_calls) + +- def _test_port_bound_for_dvr_on_vlan_network_rpc_error( +- self, device_owner, ip_version=4): +- self._setup_for_dvr_test() +- if ip_version == 4: +- gateway_ip = '1.1.1.1' +- cidr = '1.1.1.0/24' +- else: +- gateway_ip = '2001:100::1' +- cidr = '2001:100::0/64' +- self._port.vif_mac = gateway_mac = 'aa:bb:cc:11:22:33' +- self._compute_port.vif_mac = '77:88:99:00:11:22' +- physical_network = self._physical_network +- segmentation_id = self._segmentation_id +- network_type = n_const.TYPE_VLAN +- int_br = mock.create_autospec(self.agent.int_br) +- tun_br = mock.create_autospec(self.agent.tun_br) +- phys_br = mock.create_autospec(self.br_phys_cls('br-phys')) +- int_br.set_db_attribute.return_value = True +- int_br.db_get_val.return_value = {} +- with mock.patch.object(self.agent.dvr_agent.plugin_rpc, +- 'get_subnet_for_dvr', +- return_value={'gateway_ip': gateway_ip, +- 'cidr': cidr, +- 'ip_version': ip_version, +- 'gateway_mac': gateway_mac, +- 'network_id': 'fake-id'}),\ +- mock.patch.object(self.agent.dvr_agent.plugin_rpc, +- 'get_network_info_for_id', +- side_effect=oslo_messaging.RemoteError),\ +- mock.patch.object(self.agent.dvr_agent.plugin_rpc, +- 'get_ports_on_host_by_subnet', +- return_value=[]),\ +- mock.patch.object(self.agent.dvr_agent.int_br, +- 'get_vif_port_by_id', +- return_value=self._port),\ +- mock.patch.object(self.agent, 'int_br', new=int_br),\ +- mock.patch.object(self.agent, 'tun_br', new=tun_br),\ +- mock.patch.dict(self.agent.phys_brs, +- {physical_network: phys_br}),\ +- mock.patch.object(self.agent.dvr_agent, 'int_br', new=int_br),\ +- mock.patch.object(self.agent.dvr_agent, 'tun_br', new=tun_br),\ +- mock.patch.dict(self.agent.dvr_agent.phys_brs, +- {physical_network: phys_br}): +- self.agent.port_bound( +- self._port, self._net_uuid, network_type, +- physical_network, segmentation_id, self._fixed_ips, +- n_const.DEVICE_OWNER_DVR_INTERFACE, False) +- phy_ofp = self.agent.dvr_agent.phys_ofports[physical_network] +- int_ofp = self.agent.dvr_agent.int_ofports[physical_network] +- lvid = self.agent.vlan_manager.get(self._net_uuid).vlan +- expected_on_phys_br = [ +- mock.call.provision_local_vlan( +- port=phy_ofp, +- lvid=lvid, +- segmentation_id=segmentation_id, +- distributed=True, +- ), +- ] + self._expected_install_dvr_process( +- port=self._port, +- lvid=lvid, +- ip_version=ip_version, +- gateway_ip=gateway_ip, +- gateway_mac=gateway_mac, +- shared=False) +- expected_on_int_br = [ +- mock.call.provision_local_vlan( +- port=int_ofp, +- lvid=lvid, +- segmentation_id=segmentation_id, +- ), +- ] + self._expected_port_bound(self._port, lvid) +- self.assertEqual(expected_on_int_br, int_br.mock_calls) +- self.assertEqual([], tun_br.mock_calls) +- self.assertEqual(expected_on_phys_br, phys_br.mock_calls) +- int_br.reset_mock() +- tun_br.reset_mock() +- phys_br.reset_mock() +- self.agent.port_bound(self._compute_port, self._net_uuid, +- network_type, physical_network, +- segmentation_id, +- self._compute_fixed_ips, +- device_owner, False) +- expected_on_int_br = [ +- mock.call.install_dvr_to_src_mac( +- network_type=network_type, +- gateway_mac=gateway_mac, +- dst_mac=self._compute_port.vif_mac, +- dst_port=self._compute_port.ofport, +- vlan_tag=segmentation_id, +- ), +- ] + self._expected_port_bound(self._compute_port, lvid, False) +- self.assertEqual(expected_on_int_br, int_br.mock_calls) +- self.assertFalse([], tun_br.mock_calls) +- self.assertFalse([], phys_br.mock_calls) +- +- def _test_port_bound_for_dvr_on_vxlan_network_rpc_error( +- self, device_owner, ip_version=4): +- self._setup_for_dvr_test() +- if ip_version == 4: +- gateway_ip = '1.1.1.1' +- cidr = '1.1.1.0/24' +- else: +- gateway_ip = '2001:100::1' +- cidr = '2001:100::0/64' +- network_type = n_const.TYPE_VXLAN +- self._port.vif_mac = gateway_mac = 'aa:bb:cc:11:22:33' +- self._compute_port.vif_mac = '77:88:99:00:11:22' +- physical_network = self._physical_network +- segmentation_id = self._segmentation_id +- int_br = mock.create_autospec(self.agent.int_br) +- tun_br = mock.create_autospec(self.agent.tun_br) +- phys_br = mock.create_autospec(self.br_phys_cls('br-phys')) +- int_br.set_db_attribute.return_value = True +- int_br.db_get_val.return_value = {} +- with mock.patch.object(self.agent.dvr_agent.plugin_rpc, +- 'get_subnet_for_dvr', +- return_value={'gateway_ip': gateway_ip, +- 'cidr': cidr, +- 'ip_version': ip_version, +- 'gateway_mac': gateway_mac, +- 'network_id': 'fake-id'}),\ +- mock.patch.object(self.agent.dvr_agent.plugin_rpc, +- 'get_network_info_for_id', +- side_effect=oslo_messaging.RemoteError),\ +- mock.patch.object(self.agent.dvr_agent.plugin_rpc, +- 'get_ports_on_host_by_subnet', +- return_value=[]),\ +- mock.patch.object(self.agent.dvr_agent.int_br, +- 'get_vif_port_by_id', +- return_value=self._port),\ +- mock.patch.object(self.agent, 'int_br', new=int_br),\ +- mock.patch.object(self.agent, 'tun_br', new=tun_br),\ +- mock.patch.dict(self.agent.phys_brs, +- {physical_network: phys_br}),\ +- mock.patch.object(self.agent.dvr_agent, 'int_br', new=int_br),\ +- mock.patch.object(self.agent.dvr_agent, 'tun_br', new=tun_br),\ +- mock.patch.dict(self.agent.dvr_agent.phys_brs, +- {physical_network: phys_br}): +- self.agent.port_bound( +- self._port, self._net_uuid, network_type, +- physical_network, segmentation_id, self._fixed_ips, +- n_const.DEVICE_OWNER_DVR_INTERFACE, False) +- lvid = self.agent.vlan_manager.get(self._net_uuid).vlan +- expected_on_int_br = self._expected_port_bound( +- self._port, lvid) +- expected_on_tun_br = [ +- mock.call.provision_local_vlan( +- network_type=network_type, +- segmentation_id=segmentation_id, +- lvid=lvid, +- distributed=True), +- ] + self._expected_install_dvr_process( +- port=self._port, +- lvid=lvid, +- ip_version=ip_version, +- gateway_ip=gateway_ip, +- gateway_mac=gateway_mac, +- shared=False) +- self.assertEqual(expected_on_int_br, int_br.mock_calls) +- self.assertEqual(expected_on_tun_br, tun_br.mock_calls) +- self.assertEqual([], phys_br.mock_calls) +- int_br.reset_mock() +- tun_br.reset_mock() +- phys_br.reset_mock() +- self.agent.port_bound(self._compute_port, self._net_uuid, +- network_type, physical_network, +- segmentation_id, +- self._compute_fixed_ips, +- device_owner, False) +- expected_on_int_br = [ +- mock.call.install_dvr_to_src_mac( +- network_type=network_type, +- gateway_mac=gateway_mac, +- dst_mac=self._compute_port.vif_mac, +- dst_port=self._compute_port.ofport, +- vlan_tag=lvid, +- ), +- ] + self._expected_port_bound(self._compute_port, lvid, False) +- self.assertEqual(expected_on_int_br, int_br.mock_calls) +- self.assertEqual([], tun_br.mock_calls) +- self.assertEqual([], phys_br.mock_calls) +- + def test_port_bound_for_dvr_with_compute_ports(self): + self._test_port_bound_for_dvr_on_vlan_network( + device_owner=DEVICE_OWNER_COMPUTE) +@@ -2990,16 +2808,6 @@ class TestOvsDvrNeutronAgent(object): + self._test_port_bound_for_dvr_on_vxlan_network( + device_owner=DEVICE_OWNER_COMPUTE, ip_version=6, shared=True) + +- def test_port_bound_for_dvr_with_compute_ports_rpc_error(self): +- self._test_port_bound_for_dvr_on_vlan_network_rpc_error( +- device_owner=DEVICE_OWNER_COMPUTE) +- self._test_port_bound_for_dvr_on_vlan_network_rpc_error( +- device_owner=DEVICE_OWNER_COMPUTE, ip_version=6) +- self._test_port_bound_for_dvr_on_vxlan_network_rpc_error( +- device_owner=DEVICE_OWNER_COMPUTE) +- self._test_port_bound_for_dvr_on_vxlan_network_rpc_error( +- device_owner=DEVICE_OWNER_COMPUTE, ip_version=6) +- + def test_port_bound_for_dvr_with_lbaas_vip_ports(self): + self._test_port_bound_for_dvr_on_vlan_network( + device_owner=n_const.DEVICE_OWNER_LOADBALANCER) +-- +2.17.1 + diff -Nru neutron-13.0.0/debian/patches/revert-dvr-inter-tenant.patch neutron-13.0.1/debian/patches/revert-dvr-inter-tenant.patch --- neutron-13.0.0/debian/patches/revert-dvr-inter-tenant.patch 1970-01-01 00:00:00.000000000 +0000 +++ neutron-13.0.1/debian/patches/revert-dvr-inter-tenant.patch 2018-10-02 21:18:19.000000000 +0000 @@ -0,0 +1,295 @@ +From 694d7757d745665f6e4ab05efa6feebf4e47304c Mon Sep 17 00:00:00 2001 +From: Swaminathan Vasudevan +Date: Thu, 23 Aug 2018 05:54:17 +0000 +Subject: [PATCH 2/2] Revert "DVR: Inter Tenant Traffic between networks not + possible with shared net" + +This reverts commit d019790fe436b72cb05b8d0ff1f3a62ebd9e9bee. + +Closes-Bug: #1783654 +Change-Id: I4fd2610e185fb60cae62693cd4032ab700209b5f +(cherry picked from commit fd72643a61f726145288b2a468b044e84d02c88e) +--- + neutron/api/rpc/handlers/dvr_rpc.py | 14 --- + .../agent/ovs_dvr_neutron_agent.py | 29 ++---- + .../unit/api/rpc/handlers/test_dvr_rpc.py | 7 -- + .../agent/test_ovs_neutron_agent.py | 97 ++++++------------- + 4 files changed, 36 insertions(+), 111 deletions(-) + +diff --git a/neutron/api/rpc/handlers/dvr_rpc.py b/neutron/api/rpc/handlers/dvr_rpc.py +index df29c4c45..c7b5dd102 100644 +--- a/neutron/api/rpc/handlers/dvr_rpc.py ++++ b/neutron/api/rpc/handlers/dvr_rpc.py +@@ -59,13 +59,6 @@ class DVRServerRpcApi(object): + return cctxt.call(context, 'get_ports_on_host_by_subnet', + host=host, subnet=subnet) + +- @log_helpers.log_method_call +- def get_network_info_for_id(self, context, network_id): +- """Get network info for DVR router ports.""" +- cctxt = self.client.prepare() +- return cctxt.call(context, 'get_network_info_for_id', +- network_id=network_id) +- + @log_helpers.log_method_call + def get_subnet_for_dvr(self, context, subnet, fixed_ips): + cctxt = self.client.prepare() +@@ -112,13 +105,6 @@ class DVRServerRpcCallback(object): + return self.plugin.get_ports_on_host_by_subnet(context, + host, subnet) + +- def get_network_info_for_id(self, context, **kwargs): +- """Get network info for DVR port.""" +- network_id = kwargs.get('network_id') +- LOG.debug("DVR Agent requests network info for id %s", network_id) +- net_filter = {'id': [network_id]} +- return self.plugin.get_networks(context, filters=net_filter) +- + def get_subnet_for_dvr(self, context, **kwargs): + fixed_ips = kwargs.get('fixed_ips') + subnet = kwargs.get('subnet') +diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_dvr_neutron_agent.py b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_dvr_neutron_agent.py +index d3f77cb88..1c73d5f7c 100644 +--- a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_dvr_neutron_agent.py ++++ b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_dvr_neutron_agent.py +@@ -417,27 +417,16 @@ class OVSDVRNeutronAgent(object): + br = self.tun_br + # TODO(vivek) remove the IPv6 related flows once SNAT is not + # used for IPv6 DVR. +- port_net_info = ( +- self.plugin_rpc.get_network_info_for_id( +- self.context, subnet_info.get('network_id'))) +- net_shared_only = ( +- port_net_info[0]['shared'] and +- not port_net_info[0]['router:external']) +- if net_shared_only: +- LOG.debug("Not applying DVR rules to tunnel bridge because %s " +- "is a shared network", subnet_info.get('network_id')) ++ if ip_version == 4: ++ if subnet_info['gateway_ip']: ++ br.install_dvr_process_ipv4( ++ vlan_tag=lvm.vlan, gateway_ip=subnet_info['gateway_ip']) + else: +- if ip_version == 4: +- if subnet_info['gateway_ip']: +- br.install_dvr_process_ipv4( +- vlan_tag=lvm.vlan, +- gateway_ip=subnet_info['gateway_ip']) +- else: +- br.install_dvr_process_ipv6( +- vlan_tag=lvm.vlan, gateway_mac=subnet_info['gateway_mac']) +- br.install_dvr_process( +- vlan_tag=lvm.vlan, vif_mac=port.vif_mac, +- dvr_mac_address=self.dvr_mac_address) ++ br.install_dvr_process_ipv6( ++ vlan_tag=lvm.vlan, gateway_mac=subnet_info['gateway_mac']) ++ br.install_dvr_process( ++ vlan_tag=lvm.vlan, vif_mac=port.vif_mac, ++ dvr_mac_address=self.dvr_mac_address) + + # the dvr router interface is itself a port, so capture it + # queue this subnet to that port. A subnet appears only once as +diff --git a/neutron/tests/unit/api/rpc/handlers/test_dvr_rpc.py b/neutron/tests/unit/api/rpc/handlers/test_dvr_rpc.py +index b8a3fb4b6..0931604db 100644 +--- a/neutron/tests/unit/api/rpc/handlers/test_dvr_rpc.py ++++ b/neutron/tests/unit/api/rpc/handlers/test_dvr_rpc.py +@@ -46,13 +46,6 @@ class DVRServerRpcApiTestCase(base.BaseTestCase): + self.ctxt, 'get_ports_on_host_by_subnet', + host='foo_host', subnet='foo_subnet') + +- def test_get_network_info_for_id(self): +- self.rpc.get_network_info_for_id( +- self.ctxt, 'fake-network-id') +- self.mock_cctxt.call.assert_called_with( +- self.ctxt, 'get_network_info_for_id', +- network_id='fake-network-id') +- + def test_get_subnet_for_dvr(self): + self.rpc.get_subnet_for_dvr( + self.ctxt, 'foo_subnet', fixed_ips='foo_fixed_ips') +diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py +index 17882b315..32fca28bc 100644 +--- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py ++++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py +@@ -2578,33 +2578,29 @@ class TestOvsDvrNeutronAgent(object): + return resp + + def _expected_install_dvr_process(self, lvid, port, ip_version, +- gateway_ip, gateway_mac, shared=False): +- if not shared: +- if ip_version == 4: +- ipvx_calls = [ +- mock.call.install_dvr_process_ipv4( +- vlan_tag=lvid, +- gateway_ip=gateway_ip), +- ] +- else: +- ipvx_calls = [ +- mock.call.install_dvr_process_ipv6( +- vlan_tag=lvid, +- gateway_mac=gateway_mac), +- ] +- return ipvx_calls + [ +- mock.call.install_dvr_process( ++ gateway_ip, gateway_mac): ++ if ip_version == 4: ++ ipvx_calls = [ ++ mock.call.install_dvr_process_ipv4( + vlan_tag=lvid, +- dvr_mac_address=self.agent.dvr_agent.dvr_mac_address, +- vif_mac=port.vif_mac, +- ), ++ gateway_ip=gateway_ip), + ] + else: +- return [] ++ ipvx_calls = [ ++ mock.call.install_dvr_process_ipv6( ++ vlan_tag=lvid, ++ gateway_mac=gateway_mac), ++ ] ++ return ipvx_calls + [ ++ mock.call.install_dvr_process( ++ vlan_tag=lvid, ++ dvr_mac_address=self.agent.dvr_agent.dvr_mac_address, ++ vif_mac=port.vif_mac, ++ ), ++ ] + + def _test_port_bound_for_dvr_on_vlan_network(self, device_owner, +- ip_version=4, +- shared=False): ++ ip_version=4): + self._setup_for_dvr_test() + if ip_version == 4: + gateway_ip = '1.1.1.1' +@@ -2627,12 +2623,7 @@ class TestOvsDvrNeutronAgent(object): + return_value={'gateway_ip': gateway_ip, + 'cidr': cidr, + 'ip_version': ip_version, +- 'gateway_mac': gateway_mac, +- 'network_id': 'fake-id'}),\ +- mock.patch.object(self.agent.dvr_agent.plugin_rpc, +- 'get_network_info_for_id', +- return_value=[{'shared': shared, +- 'router:external': False}]),\ ++ 'gateway_mac': gateway_mac}),\ + mock.patch.object(self.agent.dvr_agent.plugin_rpc, + 'get_ports_on_host_by_subnet', + return_value=[]),\ +@@ -2666,8 +2657,7 @@ class TestOvsDvrNeutronAgent(object): + lvid=lvid, + ip_version=ip_version, + gateway_ip=gateway_ip, +- gateway_mac=gateway_mac, +- shared=shared) ++ gateway_mac=gateway_mac) + expected_on_int_br = [ + mock.call.provision_local_vlan( + port=int_ofp, +@@ -2700,8 +2690,7 @@ class TestOvsDvrNeutronAgent(object): + self.assertFalse([], phys_br.mock_calls) + + def _test_port_bound_for_dvr_on_vxlan_network(self, device_owner, +- ip_version=4, +- shared=False): ++ ip_version=4): + self._setup_for_dvr_test() + if ip_version == 4: + gateway_ip = '1.1.1.1' +@@ -2724,12 +2713,7 @@ class TestOvsDvrNeutronAgent(object): + return_value={'gateway_ip': gateway_ip, + 'cidr': cidr, + 'ip_version': ip_version, +- 'gateway_mac': gateway_mac, +- 'network_id': 'fake-id'}),\ +- mock.patch.object(self.agent.dvr_agent.plugin_rpc, +- 'get_network_info_for_id', +- return_value=[{'shared': shared, +- 'router:external': False}]),\ ++ 'gateway_mac': gateway_mac}),\ + mock.patch.object(self.agent.dvr_agent.plugin_rpc, + 'get_ports_on_host_by_subnet', + return_value=[]),\ +@@ -2762,8 +2746,7 @@ class TestOvsDvrNeutronAgent(object): + lvid=lvid, + ip_version=ip_version, + gateway_ip=gateway_ip, +- gateway_mac=gateway_mac, +- shared=shared) ++ gateway_mac=gateway_mac) + self.assertEqual(expected_on_int_br, int_br.mock_calls) + self.assertEqual(expected_on_tun_br, tun_br.mock_calls) + self.assertEqual([], phys_br.mock_calls) +@@ -2798,16 +2781,6 @@ class TestOvsDvrNeutronAgent(object): + self._test_port_bound_for_dvr_on_vxlan_network( + device_owner=DEVICE_OWNER_COMPUTE, ip_version=6) + +- def test_port_bound_for_dvr_with_compute_ports_on_shared_network(self): +- self._test_port_bound_for_dvr_on_vlan_network( +- device_owner=DEVICE_OWNER_COMPUTE, shared=True) +- self._test_port_bound_for_dvr_on_vlan_network( +- device_owner=DEVICE_OWNER_COMPUTE, ip_version=6, shared=True) +- self._test_port_bound_for_dvr_on_vxlan_network( +- device_owner=DEVICE_OWNER_COMPUTE, shared=True) +- self._test_port_bound_for_dvr_on_vxlan_network( +- device_owner=DEVICE_OWNER_COMPUTE, ip_version=6, shared=True) +- + def test_port_bound_for_dvr_with_lbaas_vip_ports(self): + self._test_port_bound_for_dvr_on_vlan_network( + device_owner=n_const.DEVICE_OWNER_LOADBALANCER) +@@ -2927,8 +2900,7 @@ class TestOvsDvrNeutronAgent(object): + return_value={'gateway_ip': '1.1.1.1', + 'cidr': '1.1.1.0/24', + 'ip_version': 4, +- 'gateway_mac': 'aa:bb:cc:11:22:33', +- 'network_id': 'faked-id'}),\ ++ 'gateway_mac': 'aa:bb:cc:11:22:33'}),\ + mock.patch.object(self.agent.dvr_agent.plugin_rpc, + 'get_ports_on_host_by_subnet', + return_value=[]),\ +@@ -2992,12 +2964,7 @@ class TestOvsDvrNeutronAgent(object): + return_value={'gateway_ip': gateway_ip, + 'cidr': cidr, + 'ip_version': ip_version, +- 'gateway_mac': gateway_mac, +- 'network_id': 'fake-id'}),\ +- mock.patch.object(self.agent.dvr_agent.plugin_rpc, +- 'get_network_info_for_id', +- return_value=[{'shared': False, +- 'router:external': False}]),\ ++ 'gateway_mac': gateway_mac}),\ + mock.patch.object(self.agent.dvr_agent.plugin_rpc, + 'get_ports_on_host_by_subnet', + return_value=[]),\ +@@ -3102,12 +3069,7 @@ class TestOvsDvrNeutronAgent(object): + return_value={'gateway_ip': gateway_ip, + 'cidr': cidr, + 'ip_version': ip_version, +- 'gateway_mac': gateway_mac, +- 'network_id': 'faked-id'}),\ +- mock.patch.object(self.agent.dvr_agent.plugin_rpc, +- 'get_network_info_for_id', +- return_value=[{'shared': False, +- 'router:external': False}]),\ ++ 'gateway_mac': gateway_mac}),\ + mock.patch.object(self.agent.dvr_agent.plugin_rpc, + 'get_ports_on_host_by_subnet', + return_value=[]),\ +@@ -3222,12 +3184,7 @@ class TestOvsDvrNeutronAgent(object): + return_value={'gateway_ip': '1.1.1.1', + 'cidr': '1.1.1.0/24', + 'ip_version': 4, +- 'gateway_mac': gateway_mac, +- 'network_id': 'fake-id'}),\ +- mock.patch.object(self.agent.dvr_agent.plugin_rpc, +- 'get_network_info_for_id', +- return_value=[{'shared': False, +- 'router:external': False}]),\ ++ 'gateway_mac': gateway_mac}),\ + mock.patch.object(self.agent.dvr_agent.plugin_rpc, + 'get_ports_on_host_by_subnet', + return_value=[]),\ +-- +2.17.1 + diff -Nru neutron-13.0.0/debian/patches/series neutron-13.0.1/debian/patches/series --- neutron-13.0.0/debian/patches/series 2018-09-25 13:12:54.000000000 +0000 +++ neutron-13.0.1/debian/patches/series 2018-10-02 21:18:19.000000000 +0000 @@ -1,3 +1,5 @@ skip-iptest.patch flake8-legacy.patch metadata-use-requests-for-comms-with-nova-api.patch +revert-dvr-add-error-handling.patch +revert-dvr-inter-tenant.patch diff -Nru neutron-13.0.0/doc/source/admin/config-sriov.rst neutron-13.0.1/doc/source/admin/config-sriov.rst --- neutron-13.0.0/doc/source/admin/config-sriov.rst 2018-08-30 14:14:55.000000000 +0000 +++ neutron-13.0.1/doc/source/admin/config-sriov.rst 2018-09-10 05:07:20.000000000 +0000 @@ -132,7 +132,7 @@ modify the interfaces configuration file adding an ``ifup`` script command. - In Ubuntu, modifying the ``/etc/network/interfaces`` file: + On Ubuntu, modify the ``/etc/network/interfaces`` file: .. code-block:: ini @@ -140,8 +140,7 @@ iface eth3 inet dhcp pre-up echo '4' > /sys/class/net/eth3/device/sriov_numvfs - - In Red Hat, modifying the ``/sbin/ifup-local`` file: + On Red Hat, modify the ``/sbin/ifup-local`` file: .. code-block:: bash @@ -151,7 +150,6 @@ echo '4' > /sys/class/net/eth3/device/sriov_numvfs fi - .. warning:: Alternatively, you can create VFs by passing the ``max_vfs`` to the @@ -166,7 +164,7 @@ # cat /sys/class/net/eth3/device/sriov_totalvfs 63 -#. Verify that the VFs have been created and are in ``up`` state: +#. Verify that the VFs have been created and are in ``up`` state. For example: .. code-block:: console @@ -223,42 +221,46 @@ .. code-block:: ini - [default] - pci_passthrough_whitelist = { "devname": "eth3", "physical_network": "physnet2"} + [pci] + passthrough_whitelist = { "devname": "eth3", "physical_network": "physnet2"} This tells the Compute service that all VFs belonging to ``eth3`` are allowed to be passed through to instances and belong to the provider network ``physnet2``. - Alternatively the ``pci_passthrough_whitelist`` parameter also supports + Alternatively the ``[pci] passthrough_whitelist`` parameter also supports whitelisting by: - PCI address: The address uses the same syntax as in ``lspci`` and an - asterisk (*) can be used to match anything. + asterisk (``*``) can be used to match anything. .. code-block:: ini - pci_passthrough_whitelist = { "address": "[[[[]:]]:][][.[]]", "physical_network": "physnet2" } + [pci] + passthrough_whitelist = { "address": "[[[[]:]]:][][.[]]", "physical_network": "physnet2" } - For example, to match any domain, bus 0a, slot 00, and all functions: + For example, to match any domain, bus ``0a``, slot ``00``, and all + functions: .. code-block:: ini - pci_passthrough_whitelist = { "address": "*:0a:00.*", "physical_network": "physnet2" } + [pci] + passthrough_whitelist = { "address": "*:0a:00.*", "physical_network": "physnet2" } - PCI ``vendor_id`` and ``product_id`` as displayed by the Linux utility ``lspci``. .. code-block:: ini - pci_passthrough_whitelist = { "vendor_id": "", "product_id": "", "physical_network": "physnet2" } + [pci] + passthrough_whitelist = { "vendor_id": "", "product_id": "", "physical_network": "physnet2" } If the device defined by the PCI address or ``devname`` corresponds to an SR-IOV PF, all VFs under the PF will match the entry. Multiple - ``pci_passthrough_whitelist`` entries per host are supported. + ``[pci] passthrough_whitelist`` entries per host are supported. In order to enable SR-IOV to request "trusted mode", the - ``[pci]/pci_passthrough_whitelist`` parameter also supports a ``trusted`` + ``[pci] passthrough_whitelist`` parameter also supports a ``trusted`` tag. .. note:: @@ -297,8 +299,17 @@ .. code-block:: ini + [ml2] mechanism_drivers = openvswitch,sriovnicswitch +#. Ensure your physnet is configured for the chosen network type. Edit the + ``ml2_conf.ini`` file on each controller: + + .. code-block:: ini + + [ml2_type_vlan] + network_vlan_ranges = physnet2 + #. Add the ``plugin.ini`` file as a parameter to the ``neutron-server`` service. Edit the appropriate initialization script to configure the ``neutron-server`` service to load the plugin configuration file: @@ -314,24 +325,22 @@ ------------------------------------- #. On every controller node running the ``nova-scheduler`` service, add - ``PciPassthroughFilter`` to ``scheduler_default_filters`` to enable - ``PciPassthroughFilter`` by default. - Also ensure ``scheduler_available_filters`` parameter under the - ``[DEFAULT]`` section in ``nova.conf`` is set to ``all_filters`` - to enable all filters provided by the Compute service. + ``PciPassthroughFilter`` to ``[filter_scheduler] enabled_filters`` to enable + this filter. Ensure ``[filter_scheduler] available_filters`` is set to the + default of ``nova.scheduler.filters.all_filters``: .. code-block:: ini - [DEFAULT] - scheduler_default_filters = RetryFilter, AvailabilityZoneFilter, RamFilter, ComputeFilter, ComputeCapabilitiesFilter, ImagePropertiesFilter, ServerGroupAntiAffinityFilter, ServerGroupAffinityFilter, PciPassthroughFilter - scheduler_available_filters = nova.scheduler.filters.all_filters + [filter_scheduler] + enabled_filters = RetryFilter, AvailabilityZoneFilter, ComputeFilter, ComputeCapabilitiesFilter, ImagePropertiesFilter, ServerGroupAntiAffinityFilter, ServerGroupAffinityFilter, PciPassthroughFilter + available_filters = nova.scheduler.filters.all_filters #. Restart the ``nova-scheduler`` service. -Enable neutron sriov-agent (Compute) -------------------------------------- +Enable neutron-sriov-nic-agent (Compute) +---------------------------------------- -#. Install the SR-IOV agent. +#. Install the SR-IOV agent, if necessary. #. Edit the ``sriov_agent.ini`` file on each compute node. For example: @@ -360,7 +369,7 @@ exclude_devices = eth1:0000:07:00.2;0000:07:00.3,eth2:0000:05:00.1;0000:05:00.2 -#. Ensure the neutron sriov-agent runs successfully: +#. Ensure the SR-IOV agent runs successfully: .. code-block:: console @@ -368,7 +377,7 @@ --config-file /etc/neutron/neutron.conf \ --config-file /etc/neutron/plugins/ml2/sriov_agent.ini -#. Enable the neutron sriov-agent service. +#. Enable the neutron SR-IOV agent service. If installing from source, you must configure a daemon file for the init system manually. @@ -412,39 +421,66 @@ Once configuration is complete, you can launch instances with SR-IOV ports. +#. If it does not already exist, create a network and subnet for the chosen + physnet. This is the network to which SR-IOV ports will be attached. For + example: + + .. code-block:: console + + $ openstack network create --provider-physical-network physnet2 \ + --provider-network-type vlan --provider-segment 1000 \ + sriov-net + + $ openstack subnet create --network sriov-net \ + --subnet-pool shared-default-subnetpool-v4 \ + sriov-subnet + #. Get the ``id`` of the network where you want the SR-IOV port to be created: .. code-block:: console - $ net_id=`neutron net-show net04 | grep "\ id\ " | awk '{ print $4 }'` + $ net_id=$(openstack network show sriov-net -c id -f value) -#. Create the SR-IOV port. ``vnic_type=direct`` is used here, but other options +#. Create the SR-IOV port. ``vnic-type=direct`` is used here, but other options include ``normal``, ``direct-physical``, and ``macvtap``: .. code-block:: console - $ port_id=`neutron port-create $net_id --name sriov_port --binding:vnic_type direct | grep "\ id\ " | awk '{ print $4 }'` + $ openstack port create --network $net_id --vnic-type direct \ + sriov-port - To request that the SR-IOV port accept trusted capabilities, the - binding profile should be enhanced with the ``trusted`` tag. + Alternatively, to request that the SR-IOV port accept trusted capabilities, + the binding profile should be enhanced with the ``trusted`` tag. .. code-block:: console - $ port_id=`neutron port-create $net_id --name sriov_port --binding:vnic_type direct --binding:profile type=dict trusted=true | grep "\ id\ " | awk '{ print $4 }'` + $ openstack port create --network $net_id --vnic-type direct \ + --binding-profile trusted=true \ + sriov-port + +#. Get the ``id`` of the created port: + + .. code-block:: console + + $ port_id=$(openstack port show sriov-port -c id -f value) #. Create the instance. Specify the SR-IOV port created in step two for the NIC: .. code-block:: console - $ openstack server create --flavor m1.large --image ubuntu_14.04 --nic port-id=$port_id test-sriov + $ openstack server create --flavor m1.large --image ubuntu_18.04 \ + --nic port-id=$port_id \ + test-sriov .. note:: There are two ways to attach VFs to an instance. You can create an SR-IOV port or use the ``pci_alias`` in the Compute service. For more - information about using ``pci_alias``, refer to `nova-api configuration - `__. + information about using ``pci_alias``, refer to `nova-api + configuration`__. + + __ https://docs.openstack.org/nova/latest/admin/pci-passthrough.html#configure-nova-api-controller SR-IOV with InfiniBand ~~~~~~~~~~~~~~~~~~~~~~ diff -Nru neutron-13.0.0/doc/source/contributor/internals/openvswitch_firewall.rst neutron-13.0.1/doc/source/contributor/internals/openvswitch_firewall.rst --- neutron-13.0.0/doc/source/contributor/internals/openvswitch_firewall.rst 2018-08-30 14:14:55.000000000 +0000 +++ neutron-13.0.1/doc/source/contributor/internals/openvswitch_firewall.rst 2018-09-10 05:07:20.000000000 +0000 @@ -207,25 +207,25 @@ :: - table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=130 actions=NORMAL - table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=131 actions=NORMAL - table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=132 actions=NORMAL - table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=135 actions=NORMAL - table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=136 actions=NORMAL - table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=130 actions=NORMAL - table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=131 actions=NORMAL - table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=132 actions=NORMAL - table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=135 actions=NORMAL - table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=136 actions=NORMAL + table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=130 actions=resubmit(,94) + table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=131 actions=resubmit(,94) + table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=132 actions=resubmit(,94) + table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=135 actions=resubmit(,94) + table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=136 actions=resubmit(,94) + table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=130 actions=resubmit(,94) + table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=131 actions=resubmit(,94) + table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=132 actions=resubmit(,94) + table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=135 actions=resubmit(,94) + table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=136 actions=resubmit(,94) Following rules implement arp spoofing protection :: - table=71, priority=95,arp,reg5=0x1,in_port=1,dl_src=fa:16:3e:a4:22:10,arp_spa=192.168.0.1 actions=NORMAL - table=71, priority=95,arp,reg5=0x1,in_port=1,dl_src=fa:16:3e:8c:84:13,arp_spa=10.0.0.1 actions=NORMAL - table=71, priority=95,arp,reg5=0x2,in_port=2,dl_src=fa:16:3e:24:57:c7,arp_spa=192.168.0.2 actions=NORMAL - table=71, priority=95,arp,reg5=0x2,in_port=2,dl_src=fa:16:3e:8c:84:14,arp_spa=10.1.0.0/24 actions=NORMAL + table=71, priority=95,arp,reg5=0x1,in_port=1,dl_src=fa:16:3e:a4:22:10,arp_spa=192.168.0.1 actions=resubmit(,94) + table=71, priority=95,arp,reg5=0x1,in_port=1,dl_src=fa:16:3e:8c:84:13,arp_spa=10.0.0.1 actions=resubmit(,94) + table=71, priority=95,arp,reg5=0x2,in_port=2,dl_src=fa:16:3e:24:57:c7,arp_spa=192.168.0.2 actions=resubmit(,94) + table=71, priority=95,arp,reg5=0x2,in_port=2,dl_src=fa:16:3e:8c:84:14,arp_spa=10.1.0.0/24 actions=resubmit(,94) DHCP and DHCPv6 traffic is allowed to instance but DHCP servers are blocked on instances. @@ -288,10 +288,10 @@ :: - table=72, priority=50,ct_state=+est-rel+rpl,ct_zone=644,ct_mark=0,reg5=0x1 actions=NORMAL - table=72, priority=50,ct_state=+est-rel+rpl,ct_zone=644,ct_mark=0,reg5=0x2 actions=NORMAL - table=72, priority=50,ct_state=-new-est+rel-inv,ct_zone=644,ct_mark=0,reg5=0x1 actions=NORMAL - table=72, priority=50,ct_state=-new-est+rel-inv,ct_zone=644,ct_mark=0,reg5=0x2 actions=NORMAL + table=72, priority=50,ct_state=+est-rel+rpl,ct_zone=644,ct_mark=0,reg5=0x1 actions=resubmit(,94) + table=72, priority=50,ct_state=+est-rel+rpl,ct_zone=644,ct_mark=0,reg5=0x2 actions=resubmit(,94) + table=72, priority=50,ct_state=-new-est+rel-inv,ct_zone=644,ct_mark=0,reg5=0x1 actions=resubmit(,94) + table=72, priority=50,ct_state=-new-est+rel-inv,ct_zone=644,ct_mark=0,reg5=0x2 actions=resubmit(,94) In the following flows are marked established connections that weren't matched in the previous flows, which means they don't have accepting security group @@ -307,7 +307,8 @@ In following ``table 73`` are all detected ingress connections sent to ingress pipeline. Since the connection was already accepted by egress pipeline, all -remaining egress connections are sent to normal switching. +remaining egress connections are sent to normal flood'n'learn switching +(table 94). :: @@ -317,8 +318,8 @@ table=73, priority=100,reg6=0x284,dl_dst=fa:16:3e:8c:84:14 actions=load:0x2->NXM_NX_REG5[],resubmit(,81) table=73, priority=90,ct_state=+new-est,reg5=0x1 actions=ct(commit,zone=NXM_NX_REG6[0..15]),resubmit(,91) table=73, priority=90,ct_state=+new-est,reg5=0x2 actions=ct(commit,zone=NXM_NX_REG6[0..15]),resubmit(,91) - table=73, priority=80,reg5=0x1 actions=NORMAL - table=73, priority=80,reg5=0x2 actions=NORMAL + table=73, priority=80,reg5=0x1 actions=resubmit(,94) + table=73, priority=80,reg5=0x2 actions=resubmit(,94) table=73, priority=0 actions=drop ``table 81`` is similar to ``table 71``, allows basic ingress traffic for @@ -460,16 +461,24 @@ There are three tables where packets are sent once they get through the OVS firewall pipeline. The tables can be used by other mechanisms using OpenFlow that are supposed to work with the OVS firewall. Packets sent to ``table 91`` -are considered accepted by the egress pipeline and won't be processed further. -``NORMAL`` action is used by default in this table. Packets sent to -``table 92`` were processed by the ingress filtering pipeline. As packets from -the ingress filtering pipeline were injected to its destination, ``table 92`` -receives copies of those packets and therefore default action is ``drop``. -Finally, packets sent to ``table 93`` were filtered by the firewall and should -be dropped. Default action is ``drop`` in this table. - -In regard to the performance perspective, please note that only the first accepted -packet of each connection session will go to ``table 91`` and ``table 92``. +are considered accepted by the egress pipeline, and will be processed so that +they are forwarded to their destination by being submitted to a NORMAL action +that results in Ethernet flood/learn processing. Note that ``table 91`` merely +resubmits to ``table 94``that contains the actual NORMAL action; this allows +to have``table 91`` be a single places where the NORMAL action can be overriden +by other components (currently used by ``networking-bagpipe`` driver for +``networking-bgpvpn``). + +Packets sent to ``table 92`` were processed by the ingress filtering pipeline. +As packets from the ingress filtering pipeline were injected to its +destination, ``table 92`` receives copies of those packets and therefore +default action is ``drop``. Finally, packets sent to ``table 93`` were filtered +by the firewall and should be dropped. Default action is ``drop`` in this +table. + +In regard to the performance perspective, please note that only the first +accepted packet of each connection session will go to ``table 91`` and +``table 92``. Future work ----------- diff -Nru neutron-13.0.0/neutron/agent/common/ip_lib.py neutron-13.0.1/neutron/agent/common/ip_lib.py --- neutron-13.0.0/neutron/agent/common/ip_lib.py 2018-08-30 14:14:55.000000000 +0000 +++ neutron-13.0.1/neutron/agent/common/ip_lib.py 2018-09-10 05:07:08.000000000 +0000 @@ -27,3 +27,5 @@ IPWrapper = ip_lib.IPWrapper IPDevice = ip_lib.IPDevice + +add_namespace_to_cmd = ip_lib.add_namespace_to_cmd diff -Nru neutron-13.0.0/neutron/agent/common/utils.py neutron-13.0.1/neutron/agent/common/utils.py --- neutron-13.0.0/neutron/agent/common/utils.py 2018-08-30 14:14:55.000000000 +0000 +++ neutron-13.0.1/neutron/agent/common/utils.py 2018-09-10 05:07:08.000000000 +0000 @@ -37,7 +37,11 @@ INTERFACE_NAMESPACE = 'neutron.interface_drivers' +create_process = utils.create_process +kill_process = utils.kill_process execute = utils.execute +get_root_helper_child_pid = utils.get_root_helper_child_pid +pid_invoked_with_cmdline = utils.pid_invoked_with_cmdline def load_interface_driver(conf): diff -Nru neutron-13.0.0/neutron/agent/l2/extensions/qos.py neutron-13.0.1/neutron/agent/l2/extensions/qos.py --- neutron-13.0.0/neutron/agent/l2/extensions/qos.py 2018-08-30 14:14:55.000000000 +0000 +++ neutron-13.0.1/neutron/agent/l2/extensions/qos.py 2018-09-10 05:07:08.000000000 +0000 @@ -257,7 +257,8 @@ if not self.policy_map.has_policy_changed(port, qos_policy_id): return - qos_policy = self.resource_rpc.pull( + qos_policy = self.policy_map.get_policy( + qos_policy_id) or self.resource_rpc.pull( context, resources.QOS_POLICY, qos_policy_id) if qos_policy is None: LOG.info("QoS policy %(qos_policy_id)s applied to port " diff -Nru neutron-13.0.0/neutron/agent/linux/async_process.py neutron-13.0.1/neutron/agent/linux/async_process.py --- neutron-13.0.0/neutron/agent/linux/async_process.py 2018-08-30 14:14:55.000000000 +0000 +++ neutron-13.0.1/neutron/agent/linux/async_process.py 2018-09-10 05:07:20.000000000 +0000 @@ -21,8 +21,8 @@ from oslo_log import log as logging from neutron._i18n import _ -from neutron.agent.linux import ip_lib -from neutron.agent.linux import utils +from neutron.agent.common import ip_lib +from neutron.agent.common import utils from neutron.common import utils as common_utils @@ -117,7 +117,7 @@ if block: common_utils.wait_until_true(self.is_active) - def stop(self, block=False, kill_signal=signal.SIGKILL): + def stop(self, block=False, kill_signal=None): """Halt the process and watcher threads. :param block: Block until the process has stopped. @@ -126,6 +126,7 @@ :raises utils.WaitTimeout if blocking is True and the process did not stop in time. """ + kill_signal = kill_signal or getattr(signal, 'SIGKILL', signal.SIGTERM) if self._is_running: LOG.debug('Halting async process [%s].', self.cmd) self._kill(kill_signal) @@ -196,7 +197,7 @@ stderr = list(self.iter_stderr()) LOG.debug('Halting async process [%s] in response to an error. stdout:' ' [%s] - stderr: [%s]', self.cmd, stdout, stderr) - self._kill(signal.SIGKILL) + self._kill(getattr(signal, 'SIGKILL', signal.SIGTERM)) if self.respawn_interval is not None and self.respawn_interval >= 0: eventlet.sleep(self.respawn_interval) LOG.debug('Respawning async process [%s].', self.cmd) diff -Nru neutron-13.0.0/neutron/agent/linux/iptables_manager.py neutron-13.0.1/neutron/agent/linux/iptables_manager.py --- neutron-13.0.0/neutron/agent/linux/iptables_manager.py 2018-08-30 14:14:55.000000000 +0000 +++ neutron-13.0.1/neutron/agent/linux/iptables_manager.py 2018-09-10 05:07:08.000000000 +0000 @@ -495,7 +495,7 @@ return self._do_run_restore(args, commands, lock=True) err = self._do_run_restore(args, commands) - if (isinstance(err, linux_utils.ProcessExecutionError) and + if (isinstance(err, n_exc.ProcessExecutionError) and err.returncode == XTABLES_RESOURCE_PROBLEM_CODE): # maybe we run on a platform that includes iptables commit # 999eaa241212d3952ddff39a99d0d55a74e3639e (for example, latest diff -Nru neutron-13.0.0/neutron/agent/linux/openvswitch_firewall/firewall.py neutron-13.0.1/neutron/agent/linux/openvswitch_firewall/firewall.py --- neutron-13.0.0/neutron/agent/linux/openvswitch_firewall/firewall.py 2018-08-30 14:14:42.000000000 +0000 +++ neutron-13.0.1/neutron/agent/linux/openvswitch_firewall/firewall.py 2018-09-10 05:07:08.000000000 +0000 @@ -473,9 +473,15 @@ def _initialize_third_party_tables(self): self.int_br.br.add_flow( - table=ovs_consts.ACCEPTED_EGRESS_TRAFFIC_TABLE, + table=ovs_consts.ACCEPTED_EGRESS_TRAFFIC_NORMAL_TABLE, priority=1, actions='normal') + self.int_br.br.add_flow( + table=ovs_consts.ACCEPTED_EGRESS_TRAFFIC_TABLE, + priority=1, + actions='resubmit(,%d)' % ( + ovs_consts.ACCEPTED_EGRESS_TRAFFIC_NORMAL_TABLE) + ) for table in (ovs_consts.ACCEPTED_INGRESS_TRAFFIC_TABLE, ovs_consts.DROPPED_TRAFFIC_TABLE): self.int_br.br.add_flow( @@ -709,7 +715,8 @@ dl_type=constants.ETHERTYPE_IPV6, nw_proto=lib_const.PROTO_NUM_IPV6_ICMP, icmp_type=icmp_type, - actions='normal' + actions='resubmit(,%d)' % ( + ovs_consts.ACCEPTED_EGRESS_TRAFFIC_NORMAL_TABLE) ) def _initialize_egress_no_port_security(self, port_id): @@ -743,7 +750,8 @@ table=ovs_consts.ACCEPT_OR_INGRESS_TABLE, priority=80, reg_port=ovs_port.ofport, - actions='normal' + actions='resubmit(,%d)' % ( + ovs_consts.ACCEPTED_EGRESS_TRAFFIC_NORMAL_TABLE) ) def _remove_egress_no_port_security(self, port_id): @@ -778,7 +786,8 @@ dl_src=mac_addr, dl_type=constants.ETHERTYPE_ARP, arp_spa=ip_addr, - actions='normal' + actions='resubmit(,%d)' % ( + ovs_consts.ACCEPTED_EGRESS_TRAFFIC_NORMAL_TABLE) ) self._add_flow( table=ovs_consts.BASE_EGRESS_TABLE, @@ -893,7 +902,8 @@ table=ovs_consts.ACCEPT_OR_INGRESS_TABLE, priority=80, reg_port=port.ofport, - actions='normal' + actions='resubmit(,%d)' % ( + ovs_consts.ACCEPTED_EGRESS_TRAFFIC_NORMAL_TABLE) ) def _initialize_tracked_egress(self, port): @@ -924,7 +934,8 @@ ct_mark=ovsfw_consts.CT_MARK_NORMAL, reg_port=port.ofport, ct_zone=port.vlan_tag, - actions='normal' + actions='resubmit(,%d)' % ( + ovs_consts.ACCEPTED_EGRESS_TRAFFIC_NORMAL_TABLE) ) self._add_flow( table=ovs_consts.RULES_EGRESS_TABLE, diff -Nru neutron-13.0.0/neutron/agent/linux/utils.py neutron-13.0.1/neutron/agent/linux/utils.py --- neutron-13.0.0/neutron/agent/linux/utils.py 2018-08-30 14:14:55.000000000 +0000 +++ neutron-13.0.1/neutron/agent/linux/utils.py 2018-09-10 05:07:08.000000000 +0000 @@ -35,6 +35,7 @@ from neutron._i18n import _ from neutron.agent.linux import xenapi_root_helper +from neutron.common import exceptions from neutron.common import utils from neutron.conf.agent import common as config from neutron import wsgi @@ -43,12 +44,6 @@ LOG = logging.getLogger(__name__) -class ProcessExecutionError(RuntimeError): - def __init__(self, message, returncode): - super(ProcessExecutionError, self).__init__(message) - self.returncode = returncode - - class RootwrapDaemonHelper(object): __client = None __lock = threading.Lock() @@ -148,7 +143,8 @@ if log_fail_as_error: LOG.error(msg) if check_exit_code: - raise ProcessExecutionError(msg, returncode=returncode) + raise exceptions.ProcessExecutionError(msg, + returncode=returncode) finally: # NOTE(termie): this appears to be necessary to let the subprocess @@ -167,7 +163,7 @@ try: raw_pids = execute(['ps', '--ppid', pid, '-o', 'pid='], log_fail_as_error=False) - except ProcessExecutionError as e: + except exceptions.ProcessExecutionError as e: # Unexpected errors are the responsibility of the caller with excutils.save_and_reraise_exception() as ctxt: # Exception has already been logged by execute @@ -191,7 +187,7 @@ try: ppid = execute(['ps', '-o', 'ppid=', pid], log_fail_as_error=False) - except ProcessExecutionError as e: + except exceptions.ProcessExecutionError as e: # Unexpected errors are the responsibility of the caller with excutils.save_and_reraise_exception() as ctxt: # Exception has already been logged by execute @@ -221,7 +217,7 @@ """Kill the process with the given pid using the given signal.""" try: execute(['kill', '-%d' % signal, pid], run_as_root=run_as_root) - except ProcessExecutionError: + except exceptions.ProcessExecutionError: if process_is_running(pid): raise diff -Nru neutron-13.0.0/neutron/agent/windows/ip_lib.py neutron-13.0.1/neutron/agent/windows/ip_lib.py --- neutron-13.0.0/neutron/agent/windows/ip_lib.py 2018-08-30 14:14:55.000000000 +0000 +++ neutron-13.0.1/neutron/agent/windows/ip_lib.py 2018-09-10 05:07:08.000000000 +0000 @@ -79,3 +79,9 @@ return False return [eth_addr['addr'] for eth_addr in device_addresses.get(netifaces.AF_LINK, [])] + + +def add_namespace_to_cmd(cmd, namespace=None): + """Add an optional namespace to the command.""" + + return cmd diff -Nru neutron-13.0.0/neutron/agent/windows/utils.py neutron-13.0.1/neutron/agent/windows/utils.py --- neutron-13.0.0/neutron/agent/windows/utils.py 2018-08-30 14:14:55.000000000 +0000 +++ neutron-13.0.1/neutron/agent/windows/utils.py 2018-09-10 05:07:08.000000000 +0000 @@ -13,6 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. +import io import os import eventlet @@ -20,8 +21,13 @@ from neutron_lib.utils import helpers from oslo_log import log as logging from oslo_utils import encodeutils +import six from neutron._i18n import _ +from neutron.common import exceptions + +if os.name == 'nt': + import wmi LOG = logging.getLogger(__name__) @@ -32,7 +38,8 @@ subprocess.threading = eventlet.patcher.original('threading') -def create_process(cmd, addl_env=None): +def create_process(cmd, run_as_root=False, addl_env=None, + tpool_proxy=True): cmd = list(map(str, cmd)) LOG.debug("Running command: %s", cmd) @@ -48,10 +55,39 @@ env=env, preexec_fn=None, close_fds=False) + if tpool_proxy and eventlet.getcurrent().parent: + # If we intend to access the process streams, we need to wrap this + # in a tpool proxy object, avoding blocking other greenthreads. + # + # The 'file' type is not available on Python 3.x. + file_type = getattr(six.moves.builtins, 'file', io.IOBase) + obj = tpool.Proxy(obj, autowrap=(file_type, )) return obj, cmd +def _get_wmi_process(pid): + if not pid: + return None + + conn = wmi.WMI() + processes = conn.Win32_Process(ProcessId=pid) + if processes: + return processes[0] + return None + + +def kill_process(pid, signal, run_as_root=False): + """Kill the process with the given pid using the given signal.""" + process = _get_wmi_process(pid) + try: + if process: + process.Terminate() + except Exception: + if _get_wmi_process(pid): + raise + + def execute(cmd, process_input=None, addl_env=None, check_exit_code=True, return_stderr=False, log_fail_as_error=True, extra_ok_codes=None, run_as_root=False, do_decode=True): @@ -60,7 +96,7 @@ _process_input = encodeutils.to_utf8(process_input) else: _process_input = None - obj, cmd = create_process(cmd, addl_env=addl_env) + obj, cmd = create_process(cmd, addl_env=addl_env, tpool_proxy=False) _stdout, _stderr = avoid_blocking_call(obj.communicate, _process_input) obj.stdin.close() _stdout = helpers.safe_decode_utf8(_stdout) @@ -85,7 +121,7 @@ LOG.debug(log_msg) if obj.returncode and check_exit_code: - raise RuntimeError(m) + raise exceptions.ProcessExecutionError(m, returncode=obj.returncode) return (_stdout, _stderr) if return_stderr else _stdout @@ -107,3 +143,22 @@ return tpool.execute(f, *args, **kwargs) else: return f(*args, **kwargs) + + +def get_root_helper_child_pid(pid, expected_cmd, run_as_root=False): + # We don't use a root helper on Windows. + return str(pid) + + +def process_is_running(pid): + """Find if the given PID is running in the system.""" + return _get_wmi_process(pid) is not None + + +def pid_invoked_with_cmdline(pid, expected_cmd): + process = _get_wmi_process(pid) + if not process: + return False + + command = process.CommandLine + return command == " ".join(expected_cmd) diff -Nru neutron-13.0.0/neutron/common/exceptions.py neutron-13.0.1/neutron/common/exceptions.py --- neutron-13.0.0/neutron/common/exceptions.py 2018-08-30 14:14:55.000000000 +0000 +++ neutron-13.0.1/neutron/common/exceptions.py 2018-09-10 05:07:20.000000000 +0000 @@ -353,3 +353,9 @@ class PortBindingError(e.NeutronException): message = _("Binding for port %(port_id)s on host %(host)s could not be " "created or updated.") + + +class ProcessExecutionError(RuntimeError): + def __init__(self, message, returncode): + super(ProcessExecutionError, self).__init__(message) + self.returncode = returncode diff -Nru neutron-13.0.0/neutron/db/l3_dvr_db.py neutron-13.0.1/neutron/db/l3_dvr_db.py --- neutron-13.0.0/neutron/db/l3_dvr_db.py 2018-08-30 14:14:55.000000000 +0000 +++ neutron-13.0.1/neutron/db/l3_dvr_db.py 2018-09-10 05:07:08.000000000 +0000 @@ -204,11 +204,11 @@ return ports def _add_csnat_router_interface_port( - self, context, router, network_id, subnet_id, do_pop=True): + self, context, router, network_id, subnets, do_pop=True): """Add SNAT interface to the specified router and subnet.""" port_data = {'tenant_id': '', 'network_id': network_id, - 'fixed_ips': [{'subnet_id': subnet_id}], + 'fixed_ips': subnets, 'device_id': router.id, 'device_owner': const.DEVICE_OWNER_ROUTER_SNAT, 'admin_state_up': True, @@ -253,15 +253,31 @@ ) LOG.info('SNAT interface port list does not exist,' ' so create one: %s', port_list) + v6_subnets = [] + network = None for intf in int_ports: if intf.fixed_ips: # Passing the subnet for the port to make sure the IP's # are assigned on the right subnet if multiple subnet # exists - snat_port = self._add_csnat_router_interface_port( - context, router, intf['network_id'], - intf['fixed_ips'][0]['subnet_id'], do_pop=False) - port_list.append(snat_port) + for fixed_ip in intf['fixed_ips']: + ip_version = n_utils.get_ip_version( + fixed_ip.get('ip_address')) + if ip_version == const.IP_VERSION_4: + snat_port = self._add_csnat_router_interface_port( + context, router, intf['network_id'], + [{'subnet_id': fixed_ip['subnet_id']}], + do_pop=False) + port_list.append(snat_port) + else: + v6_subnets.append( + {"subnet_id": fixed_ip['subnet_id']}) + network = intf['network_id'] + if v6_subnets: + snat_port = self._add_csnat_router_interface_port( + context, router, network, + v6_subnets, do_pop=False) + port_list.append(snat_port) if port_list: self.l3plugin._populate_mtu_and_subnets_for_ports( context, port_list) @@ -397,7 +413,7 @@ admin_context = context.elevated() self._add_csnat_router_interface_port( admin_context, router_db, port['network_id'], - port['fixed_ips'][-1]['subnet_id']) + [{'subnet_id': port['fixed_ips'][-1]['subnet_id']}]) @registry.receives(resources.ROUTER_INTERFACE, [events.AFTER_CREATE]) @db_api.retry_if_session_inactive() diff -Nru neutron-13.0.0/neutron/plugins/ml2/drivers/l2pop/mech_driver.py neutron-13.0.1/neutron/plugins/ml2/drivers/l2pop/mech_driver.py --- neutron-13.0.0/neutron/plugins/ml2/drivers/l2pop/mech_driver.py 2018-08-30 14:14:55.000000000 +0000 +++ neutron-13.0.1/neutron/plugins/ml2/drivers/l2pop/mech_driver.py 2018-09-10 05:07:20.000000000 +0000 @@ -52,6 +52,14 @@ ip_address=ip['ip_address']) for ip in port['fixed_ips']] + def _remove_flooding(self, fdb_entries): + for network_fdb in fdb_entries.values(): + for agent_fdb in network_fdb.get('ports', {}).values(): + try: + agent_fdb.remove(const.FLOODING_ENTRY) + except ValueError: + pass + def check_vlan_transparency(self, context): """L2population driver vlan transparency support.""" return True @@ -255,11 +263,15 @@ l3plugin, "list_router_ids_on_host", None): admin_context = n_context.get_admin_context() port_context = context._plugin_context - if l3plugin.list_router_ids_on_host( - admin_context, agent_host, [port['device_id']]): - return fdb_entries = self._get_agent_fdb( - port_context, context.bottom_bound_segment, port, agent_host) + port_context, context.bottom_bound_segment, port, agent_host, + include_ha_router_ports=True) + if (fdb_entries and + l3plugin.list_router_ids_on_host( + admin_context, agent_host, [port['device_id']])): + # NOTE(slaweq): in case this is HA router, remove unicast + # entries to this port but don't remove flood entry + self._remove_flooding(fdb_entries) self.L2populationAgentNotify.remove_fdb_entries( self.rpc_ctx, fdb_entries) @@ -310,7 +322,8 @@ self.L2populationAgentNotify.add_fdb_entries(self.rpc_ctx, other_fdb_entries) - def _get_agent_fdb(self, context, segment, port, agent_host): + def _get_agent_fdb(self, context, segment, port, agent_host, + include_ha_router_ports=False): if not agent_host: return @@ -338,9 +351,10 @@ const.FLOODING_ENTRY) # Notify other agents to remove fdb rules for current port if (port['device_owner'] != const.DEVICE_OWNER_DVR_INTERFACE and + (include_ha_router_ports or not l3_hamode_db.is_ha_router_port(context, port['device_owner'], - port['device_id'])): + port['device_id']))): fdb_entries = self._get_port_fdb_entries(port) other_fdb_entries[network_id]['ports'][agent_ip] += fdb_entries diff -Nru neutron-13.0.0/neutron/plugins/ml2/drivers/openvswitch/agent/common/constants.py neutron-13.0.1/neutron/plugins/ml2/drivers/openvswitch/agent/common/constants.py --- neutron-13.0.0/neutron/plugins/ml2/drivers/openvswitch/agent/common/constants.py 2018-08-30 14:14:42.000000000 +0000 +++ neutron-13.0.1/neutron/plugins/ml2/drivers/openvswitch/agent/common/constants.py 2018-09-10 05:07:09.000000000 +0000 @@ -76,6 +76,8 @@ ACCEPTED_INGRESS_TRAFFIC_TABLE = 92 DROPPED_TRAFFIC_TABLE = 93 +ACCEPTED_EGRESS_TRAFFIC_NORMAL_TABLE = 94 + # --- Tunnel bridge (tun_br) # Various tables for tunneling flows diff -Nru neutron-13.0.0/neutron/services/logapi/common/db_api.py neutron-13.0.1/neutron/services/logapi/common/db_api.py --- neutron-13.0.0/neutron/services/logapi/common/db_api.py 2018-08-30 14:14:42.000000000 +0000 +++ neutron-13.0.1/neutron/services/logapi/common/db_api.py 2018-09-10 05:07:09.000000000 +0000 @@ -170,8 +170,10 @@ port = port_objects.Port.get_object(context, id=port_id) project_id = port['project_id'] - logs = log_object.Log.get_objects( - context, project_id=project_id, enabled=True) + logs = log_object.Log.get_objects(context, + project_id=project_id, + resource_type=constants.SECURITY_GROUP, + enabled=True) is_bound = lambda log: (log.resource_id in port.security_group_ids or log.target_id == port.id or (not log.target_id and not log.resource_id)) @@ -183,7 +185,11 @@ project_id = context.tenant_id log_objs = log_object.Log.get_objects( - context, project_id=project_id, enabled=True) + context, + project_id=project_id, + resource_type=constants.SECURITY_GROUP, + enabled=True) + log_resources = [] for log_obj in log_objs: if log_obj.resource_id == sg_id: diff -Nru neutron-13.0.0/neutron/services/logapi/drivers/openvswitch/ovs_firewall_log.py neutron-13.0.1/neutron/services/logapi/drivers/openvswitch/ovs_firewall_log.py --- neutron-13.0.0/neutron/services/logapi/drivers/openvswitch/ovs_firewall_log.py 2018-08-30 14:14:42.000000000 +0000 +++ neutron-13.0.1/neutron/services/logapi/drivers/openvswitch/ovs_firewall_log.py 2018-09-10 05:07:09.000000000 +0000 @@ -344,7 +344,8 @@ flow['actions'] = 'controller' # forward egress accepted packet and log if flow['table'] == ovs_consts.ACCEPTED_EGRESS_TRAFFIC_TABLE: - flow['actions'] = 'normal,controller' + flow['actions'] = 'resubmit(,%d),controller' % ( + ovs_consts.ACCEPTED_EGRESS_TRAFFIC_NORMAL_TABLE) self._add_flow(**flow) def _add_flow(self, **kwargs): diff -Nru neutron-13.0.0/neutron/tests/functional/services/logapi/test_logging.py neutron-13.0.1/neutron/tests/functional/services/logapi/test_logging.py --- neutron-13.0.0/neutron/tests/functional/services/logapi/test_logging.py 2018-08-30 14:14:42.000000000 +0000 +++ neutron-13.0.1/neutron/tests/functional/services/logapi/test_logging.py 2018-09-10 05:07:09.000000000 +0000 @@ -100,11 +100,10 @@ ip_cidr = '192.168.0.1/24' - def _is_log_flow_set(self, table): + def _is_log_flow_set(self, table, actions): flows = self.log_driver.int_br.br.dump_flows_for_table(table) pattern = re.compile( - r"^.* table=%s.* " - r"actions=(NORMAL,CONTROLLER:65535|CONTROLLER:65535)" % table + r"^.* table=%s.* actions=%s" % (table, actions) ) for flow in flows.splitlines(): if pattern.match(flow.strip()): @@ -113,19 +112,27 @@ def _assert_logging_flows_set(self): self.assertTrue(self._is_log_flow_set( - table=ovs_consts.ACCEPTED_EGRESS_TRAFFIC_TABLE)) + table=ovs_consts.ACCEPTED_EGRESS_TRAFFIC_TABLE, + actions=r"resubmit\(,%d\),CONTROLLER:65535" % ( + ovs_consts.ACCEPTED_EGRESS_TRAFFIC_NORMAL_TABLE))) self.assertTrue(self._is_log_flow_set( - table=ovs_consts.ACCEPTED_INGRESS_TRAFFIC_TABLE)) + table=ovs_consts.ACCEPTED_INGRESS_TRAFFIC_TABLE, + actions="CONTROLLER:65535")) self.assertTrue(self._is_log_flow_set( - table=ovs_consts.DROPPED_TRAFFIC_TABLE)) + table=ovs_consts.DROPPED_TRAFFIC_TABLE, + actions="CONTROLLER:65535")) def _assert_logging_flows_not_set(self): self.assertFalse(self._is_log_flow_set( - table=ovs_consts.ACCEPTED_EGRESS_TRAFFIC_TABLE)) + table=ovs_consts.ACCEPTED_EGRESS_TRAFFIC_TABLE, + actions=r"resubmit\(,%d\),CONTROLLER:65535" % ( + ovs_consts.ACCEPTED_EGRESS_TRAFFIC_NORMAL_TABLE))) self.assertFalse(self._is_log_flow_set( - table=ovs_consts.ACCEPTED_INGRESS_TRAFFIC_TABLE)) + table=ovs_consts.ACCEPTED_INGRESS_TRAFFIC_TABLE, + actions="CONTROLLER:65535")) self.assertFalse(self._is_log_flow_set( - table=ovs_consts.DROPPED_TRAFFIC_TABLE)) + table=ovs_consts.DROPPED_TRAFFIC_TABLE, + actions="CONTROLLER:65535")) def test_log_lifecycle(self): sg_rules = [{'ethertype': constants.IPv4, diff -Nru neutron-13.0.0/neutron/tests/unit/agent/l2/extensions/test_qos.py neutron-13.0.1/neutron/tests/unit/agent/l2/extensions/test_qos.py --- neutron-13.0.0/neutron/tests/unit/agent/l2/extensions/test_qos.py 2018-08-30 14:14:55.000000000 +0000 +++ neutron-13.0.1/neutron/tests/unit/agent/l2/extensions/test_qos.py 2018-09-10 05:07:09.000000000 +0000 @@ -291,6 +291,28 @@ self.context, resources.QOS_POLICY, port['qos_policy_id']) + def test_handle_diff_ports_same_policy_id(self): + port_obj1 = self._create_test_port_dict() + port_obj2 = self._create_test_port_dict() + + self.qos_ext.handle_port(self.context, port_obj1) + self.pull_mock.assert_called_once_with( + self.context, resources.QOS_POLICY, + port_obj1['qos_policy_id']) + self.assertIsNotNone( + self.qos_ext.policy_map.get_port_policy(port_obj1)) + self.assertIsNone( + self.qos_ext.policy_map.get_port_policy(port_obj2)) + + self.qos_ext.resource_rpc.pull.reset_mock() + self.qos_ext.handle_port(self.context, port_obj2) + self.assertFalse(self.pull_mock.called) + self.assertIsNotNone( + self.qos_ext.policy_map.get_port_policy(port_obj2)) + self.assertEqual( + self.qos_ext.policy_map.get_port_policy(port_obj1), + self.qos_ext.policy_map.get_port_policy(port_obj2)) + def test_delete_known_port(self): port = self._create_test_port_dict() self.qos_ext.handle_port(self.context, port) diff -Nru neutron-13.0.0/neutron/tests/unit/agent/linux/test_async_process.py neutron-13.0.1/neutron/tests/unit/agent/linux/test_async_process.py --- neutron-13.0.0/neutron/tests/unit/agent/linux/test_async_process.py 2018-08-30 14:14:55.000000000 +0000 +++ neutron-13.0.1/neutron/tests/unit/agent/linux/test_async_process.py 2018-09-10 05:07:20.000000000 +0000 @@ -19,8 +19,8 @@ import mock import testtools +from neutron.agent.common import utils from neutron.agent.linux import async_process -from neutron.agent.linux import utils from neutron.tests import base from neutron.tests.unit.agent.linux import failing_process diff -Nru neutron-13.0.0/neutron/tests/unit/agent/linux/test_iptables_manager.py neutron-13.0.1/neutron/tests/unit/agent/linux/test_iptables_manager.py --- neutron-13.0.0/neutron/tests/unit/agent/linux/test_iptables_manager.py 2018-08-30 14:14:55.000000000 +0000 +++ neutron-13.0.1/neutron/tests/unit/agent/linux/test_iptables_manager.py 2018-09-10 05:07:09.000000000 +0000 @@ -887,7 +887,7 @@ # pretend line 11 failed msg = ("Exit code: 1\nStdout: ''\n" "Stderr: 'iptables-restore: line 11 failed\n'") - raise linux_utils.ProcessExecutionError( + raise n_exc.ProcessExecutionError( msg, iptables_manager.XTABLES_RESOURCE_PROBLEM_CODE) return FILTER_DUMP self.execute.side_effect = iptables_restore_failer @@ -926,7 +926,7 @@ def test_iptables_use_table_lock(self): # Under normal operation, if we do call iptables-restore with a -w # and it succeeds, the next call will only use -w. - PE_error = linux_utils.ProcessExecutionError( + PE_error = n_exc.ProcessExecutionError( "", iptables_manager.XTABLES_RESOURCE_PROBLEM_CODE) num_calls = 3 diff -Nru neutron-13.0.0/neutron/tests/unit/agent/linux/test_utils.py neutron-13.0.1/neutron/tests/unit/agent/linux/test_utils.py --- neutron-13.0.0/neutron/tests/unit/agent/linux/test_utils.py 2018-08-30 14:14:55.000000000 +0000 +++ neutron-13.0.1/neutron/tests/unit/agent/linux/test_utils.py 2018-09-10 05:07:09.000000000 +0000 @@ -24,6 +24,7 @@ import oslo_i18n from neutron.agent.linux import utils +from neutron.common import exceptions as n_exc from neutron.tests import base from neutron.tests.common import helpers @@ -146,7 +147,7 @@ self.mock_popen.return_value = ('', '') self.process.return_value.returncode = 1 with mock.patch.object(utils, 'LOG') as log: - self.assertRaises(utils.ProcessExecutionError, utils.execute, + self.assertRaises(n_exc.ProcessExecutionError, utils.execute, ['ls'], log_fail_as_error=False) self.assertFalse(log.error.called) @@ -200,7 +201,7 @@ self.m_execute = mock.patch.object(utils, 'execute').start() def test_returns_none_for_no_valid_pid(self): - self.m_execute.side_effect = utils.ProcessExecutionError('', + self.m_execute.side_effect = n_exc.ProcessExecutionError('', returncode=1) self.assertIsNone(utils.find_parent_pid(-1)) @@ -209,9 +210,9 @@ self.assertEqual(utils.find_parent_pid(-1), '123') def test_raises_exception_returncode_0(self): - with testtools.ExpectedException(utils.ProcessExecutionError): + with testtools.ExpectedException(n_exc.ProcessExecutionError): self.m_execute.side_effect = \ - utils.ProcessExecutionError('', returncode=0) + n_exc.ProcessExecutionError('', returncode=0) utils.find_parent_pid(-1) def test_raises_unknown_exception(self): @@ -264,7 +265,7 @@ def _test_kill_process(self, pid, raise_exception=False, kill_signal=signal.SIGKILL, pid_killed=True): if raise_exception: - exc = utils.ProcessExecutionError('', returncode=0) + exc = n_exc.ProcessExecutionError('', returncode=0) else: exc = None with mock.patch.object(utils, 'execute', @@ -283,7 +284,7 @@ self._test_kill_process('1', raise_exception=True) def test_kill_process_raises_exception_for_execute_exception(self): - with testtools.ExpectedException(utils.ProcessExecutionError): + with testtools.ExpectedException(n_exc.ProcessExecutionError): # Simulate that the process is running after trying to kill due to # any reason such as, for example, Permission denied self._test_kill_process('1', raise_exception=True, @@ -297,7 +298,7 @@ def test_returns_empty_list_for_exit_code_1(self): with mock.patch.object(utils, 'execute', - side_effect=utils.ProcessExecutionError( + side_effect=n_exc.ProcessExecutionError( '', returncode=1)): self.assertEqual([], utils.find_child_pids(-1)) diff -Nru neutron-13.0.0/neutron/tests/unit/agent/windows/test_utils.py neutron-13.0.1/neutron/tests/unit/agent/windows/test_utils.py --- neutron-13.0.0/neutron/tests/unit/agent/windows/test_utils.py 1970-01-01 00:00:00.000000000 +0000 +++ neutron-13.0.1/neutron/tests/unit/agent/windows/test_utils.py 2018-09-10 05:07:09.000000000 +0000 @@ -0,0 +1,215 @@ +# Copyright 2018 Cloudbase Solutions. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import io + +import ddt +import eventlet +from eventlet import tpool +import mock +import six + +from neutron.agent.windows import utils +from neutron.common import exceptions +from neutron.tests import base + + +@ddt.ddt +class WindowsUtilsTestCase(base.BaseTestCase): + @mock.patch('os.environ', {mock.sentinel.key0: mock.sentinel.val0}) + @mock.patch.object(utils.subprocess, 'Popen') + @mock.patch.object(tpool, 'Proxy') + @mock.patch.object(eventlet, 'getcurrent') + def test_create_process(self, mock_get_current_gt, + mock_tpool_proxy, mock_popen): + cmd = ['fake_cmd'] + + popen_obj, ret_cmd = utils.create_process( + cmd, + run_as_root=mock.sentinel.run_as_root, + addl_env={mock.sentinel.key1: mock.sentinel.val1}, + tpool_proxy=True) + + exp_env = {mock.sentinel.key0: mock.sentinel.val0, + mock.sentinel.key1: mock.sentinel.val1} + + mock_popen.assert_called_once_with( + cmd, + shell=False, + stdin=utils.subprocess.PIPE, + stdout=utils.subprocess.PIPE, + stderr=utils.subprocess.PIPE, + env=exp_env, + preexec_fn=None, + close_fds=False) + + file_type = getattr(six.moves.builtins, 'file', io.IOBase) + mock_tpool_proxy.assert_called_once_with( + mock_popen.return_value, autowrap=(file_type, )) + + self.assertEqual(mock_tpool_proxy.return_value, popen_obj) + self.assertEqual(ret_cmd, cmd) + + @ddt.data({}, + {'pid': None}, + {'process_exists': True}) + @ddt.unpack + @mock.patch.object(utils, 'wmi', create=True) + def test_get_wmi_process(self, mock_wmi, + pid=mock.sentinel.pid, + process_exists=False): + mock_conn = mock_wmi.WMI.return_value + + if not pid: + exp_process = None + elif process_exists: + exp_process = mock.sentinel.wmi_obj + mock_conn.Win32_Process.return_value = [exp_process] + else: + exp_process = None + mock_conn.Win32_Process.return_value = [] + + wmi_obj = utils._get_wmi_process(pid) + self.assertEqual(exp_process, wmi_obj) + + if pid: + mock_conn.Win32_Process.assert_called_once_with(ProcessId=pid) + + @ddt.data(True, False) + @mock.patch.object(utils, '_get_wmi_process') + def test_kill_process(self, process_exists, mock_get_process): + if not process_exists: + mock_get_process.return_value = None + + utils.kill_process(mock.sentinel.pid, mock.sentinel.signal, + run_as_root=False) + + mock_get_process.assert_called_once_with(mock.sentinel.pid) + if process_exists: + mock_get_process.return_value.Terminate.assert_called_once_with() + + @ddt.data(True, False) + @mock.patch.object(utils, '_get_wmi_process') + def test_kill_process_exception(self, process_still_running, + mock_get_process): + mock_process = mock.Mock() + mock_process.Terminate.side_effect = OSError + + mock_get_process.side_effect = [ + mock_process, + mock_process if process_still_running else None] + + if process_still_running: + self.assertRaises(OSError, + utils.kill_process, + mock.sentinel.pid, + mock.sentinel.signal) + else: + utils.kill_process(mock.sentinel.pid, + mock.sentinel.signal) + + @ddt.data({'return_stder': True}, + {'returncode': 1, + 'check_exit_code': False, + 'log_fail_as_error': True}, + {'returncode': 1, + 'log_fail_as_error': True, + 'extra_ok_codes': [1]}, + {'returncode': 1, + 'log_fail_as_error': True, + 'exp_fail': True}) + @ddt.unpack + @mock.patch.object(utils, 'create_process') + @mock.patch.object(utils, 'avoid_blocking_call') + def test_execute(self, mock_avoid_blocking_call, mock_create_process, + returncode=0, check_exit_code=True, return_stder=True, + log_fail_as_error=True, extra_ok_codes=None, + exp_fail=False): + fake_stdin = 'fake_stdin' + fake_stdout = 'fake_stdout' + fake_stderr = 'fake_stderr' + + mock_popen = mock.Mock() + mock_popen.communicate.return_value = fake_stdout, fake_stderr + mock_popen.returncode = returncode + + mock_create_process.return_value = mock_popen, mock.sentinel.cmd + mock_avoid_blocking_call.side_effect = ( + lambda func, *args, **kwargs: func(*args, **kwargs)) + + args = (mock.sentinel.cmd, fake_stdin, mock.sentinel.env, + check_exit_code, return_stder, log_fail_as_error, + extra_ok_codes) + + if exp_fail: + self.assertRaises(exceptions.ProcessExecutionError, + utils.execute, + *args) + else: + ret_val = utils.execute(*args) + if return_stder: + exp_ret_val = (fake_stdout, fake_stderr) + else: + exp_ret_val = fake_stdout + + self.assertEqual(exp_ret_val, ret_val) + + mock_create_process.assert_called_once_with( + mock.sentinel.cmd, addl_env=mock.sentinel.env, + tpool_proxy=False) + mock_avoid_blocking_call.assert_called_once_with( + mock_popen.communicate, six.b(fake_stdin)) + mock_popen.communicate.assert_called_once_with(six.b(fake_stdin)) + mock_popen.stdin.close.assert_called_once_with() + + def test_get_root_helper_child_pid(self): + pid = utils.get_root_helper_child_pid( + mock.sentinel.pid, + mock.sentinel.exp_cmd, + run_as_root=False) + self.assertEqual(str(mock.sentinel.pid), pid) + + @ddt.data(True, False) + @mock.patch.object(utils, '_get_wmi_process') + def test_process_is_running(self, process_running, mock_get_process): + mock_get_process.return_value = ( + mock.sentinel.wmi_obj if process_running else None) + + self.assertEqual(process_running, + utils.process_is_running(mock.sentinel.pid)) + mock_get_process.assert_called_once_with(mock.sentinel.pid) + + @ddt.data({}, + {'process_running': False}, + {'command_matches': False}) + @ddt.unpack + @mock.patch.object(utils, '_get_wmi_process') + def test_pid_invoked_with_cmdline(self, mock_get_process, + process_running=True, + command_matches=False): + exp_cmd = 'exp_cmd' + mock_process = mock.Mock() + + mock_get_process.return_value = ( + mock_process if process_running else None) + mock_process.CommandLine = ( + exp_cmd if command_matches else 'unexpected_cmd') + + exp_result = process_running and command_matches + result = utils.pid_invoked_with_cmdline(mock.sentinel.pid, + [exp_cmd]) + + self.assertEqual(exp_result, result) + mock_get_process.assert_called_once_with(mock.sentinel.pid) diff -Nru neutron-13.0.0/neutron/tests/unit/db/test_l3_dvr_db.py neutron-13.0.1/neutron/tests/unit/db/test_l3_dvr_db.py --- neutron-13.0.0/neutron/tests/unit/db/test_l3_dvr_db.py 2018-08-30 14:14:55.000000000 +0000 +++ neutron-13.0.1/neutron/tests/unit/db/test_l3_dvr_db.py 2018-09-10 05:07:20.000000000 +0000 @@ -596,6 +596,72 @@ def test_distributed_to_ha_csnat_ports_removal(self): self._test_csnat_ports_removal(ha=True) + def test_update_router_gw_info_csnat_ports_add(self): + router_dict = {'name': 'test_router', + 'admin_state_up': True, + 'distributed': True} + router = self._create_router(router_dict) + with self.network() as net_ext,\ + self.network() as net_int,\ + self.subnet( + network=net_int, + cidr='2001:db8:1::/64', + gateway_ip='2001:db8:1::1', + ip_version=const.IP_VERSION_6) as v6_subnet1,\ + self.subnet( + network=net_int, + cidr='2001:db8:2::/64', + gateway_ip='2001:db8:2::1', + ip_version=const.IP_VERSION_6) as v6_subnet2,\ + self.subnet( + network=net_int, + cidr='10.10.10.0/24') as v4_subnet: + + self.core_plugin.update_network( + self.ctx, net_ext['network']['id'], + {'network': {'router:external': True}}) + + # Add router interface, then set router gateway + self.mixin.add_router_interface(self.ctx, router['id'], + {'subnet_id': v6_subnet1['subnet']['id']}) + self.mixin.add_router_interface(self.ctx, router['id'], + {'subnet_id': v6_subnet2['subnet']['id']}) + self.mixin.add_router_interface(self.ctx, router['id'], + {'subnet_id': v4_subnet['subnet']['id']}) + + dvr_filters = {'device_owner': + [const.DEVICE_OWNER_DVR_INTERFACE]} + dvr_ports = self.core_plugin.get_ports( + self.ctx, filters=dvr_filters) + # One for IPv4, one for two IPv6 subnets + self.assertEqual(2, len(dvr_ports)) + + self.mixin.update_router( + self.ctx, router['id'], + {'router': {'external_gateway_info': + {'network_id': net_ext['network']['id']}}}) + + csnat_filters = {'device_owner': + [const.DEVICE_OWNER_ROUTER_SNAT]} + csnat_ports = self.core_plugin.get_ports( + self.ctx, filters=csnat_filters) + # One for IPv4, one for two IPv6 subnets + self.assertEqual(2, len(csnat_ports)) + + # Remove v4 subnet interface from router + self.mixin.remove_router_interface( + self.ctx, router['id'], + {'subnet_id': v4_subnet['subnet']['id']}) + + dvr_ports = self.core_plugin.get_ports( + self.ctx, filters=dvr_filters) + self.assertEqual(1, len(dvr_ports)) + + csnat_ports = self.core_plugin.get_ports( + self.ctx, filters=csnat_filters) + self.assertEqual(1, len(csnat_ports)) + self.assertEqual(2, len(csnat_ports[0]['fixed_ips'])) + def test_remove_router_interface_csnat_ports_removal(self): router_dict = {'name': 'test_router', 'admin_state_up': True, 'distributed': True} diff -Nru neutron-13.0.0/neutron/tests/unit/plugins/ml2/drivers/l2pop/test_mech_driver.py neutron-13.0.1/neutron/tests/unit/plugins/ml2/drivers/l2pop/test_mech_driver.py --- neutron-13.0.0/neutron/tests/unit/plugins/ml2/drivers/l2pop/test_mech_driver.py 2018-08-30 14:14:55.000000000 +0000 +++ neutron-13.0.1/neutron/tests/unit/plugins/ml2/drivers/l2pop/test_mech_driver.py 2018-09-10 05:07:20.000000000 +0000 @@ -57,6 +57,7 @@ NOTIFIER = 'neutron.plugins.ml2.rpc.AgentNotifierApi' DEVICE_OWNER_COMPUTE = constants.DEVICE_OWNER_COMPUTE_PREFIX + 'fake' +DEVICE_OWNER_ROUTER_HA_INTF = constants.DEVICE_OWNER_ROUTER_HA_INTF + 'fake' class FakeL3PluginWithAgents(common_db_mixin.CommonDbMixin, @@ -858,6 +859,45 @@ self.mock_fanout.assert_called_with( mock.ANY, 'remove_fdb_entries', expected) + def test_update_port_down_ha_router_port(self): + router = self._create_ha_router() + directory.add_plugin(plugin_constants.L3, self.plugin) + with self.subnet(network=self._network, enable_dhcp=False) as snet: + subnet = snet['subnet'] + router_port = self._add_router_interface(subnet, router, HOST) + router_port_device = 'tap' + router_port['id'] + + host_arg = {portbindings.HOST_ID: HOST_4, 'admin_state_up': True} + with self.port(subnet=snet, + device_owner=DEVICE_OWNER_COMPUTE, + arg_list=(portbindings.HOST_ID,), + **host_arg) as port1: + p1 = port1['port'] + device1 = 'tap' + p1['id'] + + self.callbacks.update_device_up(self.adminContext, + agent_id=HOST, + device=device1) + self.mock_fanout.reset_mock() + self.callbacks.update_device_down(self.adminContext, + agent_id=HOST, + device=router_port_device, + host=HOST) + + router_port_ips = [ + p['ip_address'] for p in router_port['fixed_ips']] + expected = { + router_port['network_id']: { + 'ports': { + '20.0.0.1': [ + l2pop_rpc.PortInfo(router_port['mac_address'], + router_port_ips[0])]}, + 'network_type': 'vxlan', + 'segment_id': 1}} + + self.mock_fanout.assert_called_with( + mock.ANY, 'remove_fdb_entries', expected) + def test_delete_port(self): self._register_ml2_agents() diff -Nru neutron-13.0.0/neutron/tests/unit/services/logapi/common/test_db_api.py neutron-13.0.1/neutron/tests/unit/services/logapi/common/test_db_api.py --- neutron-13.0.0/neutron/tests/unit/services/logapi/common/test_db_api.py 2018-08-30 14:14:42.000000000 +0000 +++ neutron-13.0.1/neutron/tests/unit/services/logapi/common/test_db_api.py 2018-09-10 05:07:09.000000000 +0000 @@ -50,6 +50,7 @@ super(LoggingDBApiTestCase, self).setUp() self.context = context.get_admin_context() self.sg_id, self.port_id, self.tenant_id = self._create_sg_and_port() + self.context.tenant_id = self.tenant_id def _create_sg_and_port(self): with self.network() as network, \ @@ -72,6 +73,12 @@ self.assertEqual( [log], db_api.get_logs_bound_port(self.context, self.port_id)) + # Test get log objects with required resource type + calls = [mock.call(self.context, project_id=self.tenant_id, + resource_type=log_const.SECURITY_GROUP, + enabled=True)] + log_object.Log.get_objects.assert_has_calls(calls) + def test_get_logs_not_bound_port(self): fake_sg_id = uuidutils.generate_uuid() log = _create_log(resource_id=fake_sg_id, tenant_id=self.tenant_id) @@ -80,6 +87,12 @@ self.assertEqual( [], db_api.get_logs_bound_port(self.context, self.port_id)) + # Test get log objects with required resource type + calls = [mock.call(self.context, project_id=self.tenant_id, + resource_type=log_const.SECURITY_GROUP, + enabled=True)] + log_object.Log.get_objects.assert_has_calls(calls) + def test_get_logs_bound_sg(self): log = _create_log(resource_id=self.sg_id, tenant_id=self.tenant_id) with mock.patch.object(log_object.Log, 'get_objects', @@ -87,6 +100,12 @@ self.assertEqual( [log], db_api.get_logs_bound_sg(self.context, self.sg_id)) + # Test get log objects with required resource type + calls = [mock.call(self.context, project_id=self.tenant_id, + resource_type=log_const.SECURITY_GROUP, + enabled=True)] + log_object.Log.get_objects.assert_has_calls(calls) + def test_get_logs_not_bound_sg(self): with self.network() as network, \ self.subnet(network), \ @@ -102,6 +121,12 @@ self.assertEqual( [], db_api.get_logs_bound_sg(self.context, self.sg_id)) + # Test get log objects with required resource type + calls = [mock.call(self.context, project_id=self.tenant_id, + resource_type=log_const.SECURITY_GROUP, + enabled=True)] + log_object.Log.get_objects.assert_has_calls(calls) + def test__get_ports_being_logged(self): log1 = _create_log(target_id=self.port_id, tenant_id=self.tenant_id) diff -Nru neutron-13.0.0/neutron/tests/unit/services/logapi/drivers/openvswitch/test_ovs_firewall_log.py neutron-13.0.1/neutron/tests/unit/services/logapi/drivers/openvswitch/test_ovs_firewall_log.py --- neutron-13.0.0/neutron/tests/unit/services/logapi/drivers/openvswitch/test_ovs_firewall_log.py 2018-08-30 14:14:42.000000000 +0000 +++ neutron-13.0.1/neutron/tests/unit/services/logapi/drivers/openvswitch/test_ovs_firewall_log.py 2018-09-10 05:07:09.000000000 +0000 @@ -181,7 +181,8 @@ tcp_dst='0x007b'), # log egress tcp6 mock.call( - actions='normal,controller', + actions='resubmit(,%d),controller' % ( + ovs_consts.ACCEPTED_EGRESS_TRAFFIC_NORMAL_TABLE), cookie=accept_cookie.id, reg5=self.port_ofport, dl_type="0x{:04x}".format(n_const.ETHERTYPE_IPV6), @@ -190,7 +191,8 @@ table=ovs_consts.ACCEPTED_EGRESS_TRAFFIC_TABLE), # log egress udp mock.call( - actions='normal,controller', + actions='resubmit(,%d),controller' % ( + ovs_consts.ACCEPTED_EGRESS_TRAFFIC_NORMAL_TABLE), cookie=accept_cookie.id, reg5=self.port_ofport, dl_type="0x{:04x}".format(n_const.ETHERTYPE_IP), diff -Nru neutron-13.0.0/neutron.egg-info/pbr.json neutron-13.0.1/neutron.egg-info/pbr.json --- neutron-13.0.0/neutron.egg-info/pbr.json 2018-08-30 14:17:12.000000000 +0000 +++ neutron-13.0.1/neutron.egg-info/pbr.json 2018-09-10 05:09:29.000000000 +0000 @@ -1 +1 @@ -{"git_version": "b6314ea", "is_release": true} \ No newline at end of file +{"git_version": "d48b0c1", "is_release": true} \ No newline at end of file diff -Nru neutron-13.0.0/neutron.egg-info/PKG-INFO neutron-13.0.1/neutron.egg-info/PKG-INFO --- neutron-13.0.0/neutron.egg-info/PKG-INFO 2018-08-30 14:17:12.000000000 +0000 +++ neutron-13.0.1/neutron.egg-info/PKG-INFO 2018-09-10 05:09:29.000000000 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: neutron -Version: 13.0.0 +Version: 13.0.1 Summary: OpenStack Networking Home-page: https://docs.openstack.org/neutron/latest/ Author: OpenStack diff -Nru neutron-13.0.0/neutron.egg-info/SOURCES.txt neutron-13.0.1/neutron.egg-info/SOURCES.txt --- neutron-13.0.0/neutron.egg-info/SOURCES.txt 2018-08-30 14:17:14.000000000 +0000 +++ neutron-13.0.1/neutron.egg-info/SOURCES.txt 2018-09-10 05:09:30.000000000 +0000 @@ -1632,6 +1632,7 @@ neutron/tests/unit/agent/ovsdb/native/test_connection.py neutron/tests/unit/agent/windows/__init__.py neutron/tests/unit/agent/windows/test_ip_lib.py +neutron/tests/unit/agent/windows/test_utils.py neutron/tests/unit/api/__init__.py neutron/tests/unit/api/test_api_common.py neutron/tests/unit/api/test_extensions.py @@ -2133,6 +2134,7 @@ releasenotes/notes/fip-janitor-53f0d42a7471c5ed.yaml releasenotes/notes/fip-qos-52926bce81c3f8bb.yaml releasenotes/notes/firewall_driver_not_needed_on_server-4159669ad834dea6.yaml +releasenotes/notes/fix-co-existence-bug-between-sg-logging-and-fwg-logging-ef16077880d76449.yaml releasenotes/notes/fix-mtu-for-existing-networks-5a476cde9bc46a53.yaml releasenotes/notes/fix-ovsdb-ssl-connection-4058caf4fdcb33ab.yaml releasenotes/notes/fix-security-group-protocol-by-numbers-48afb97ede961716.yaml diff -Nru neutron-13.0.0/PKG-INFO neutron-13.0.1/PKG-INFO --- neutron-13.0.0/PKG-INFO 2018-08-30 14:17:27.000000000 +0000 +++ neutron-13.0.1/PKG-INFO 2018-09-10 05:09:44.000000000 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: neutron -Version: 13.0.0 +Version: 13.0.1 Summary: OpenStack Networking Home-page: https://docs.openstack.org/neutron/latest/ Author: OpenStack diff -Nru neutron-13.0.0/releasenotes/notes/fix-co-existence-bug-between-sg-logging-and-fwg-logging-ef16077880d76449.yaml neutron-13.0.1/releasenotes/notes/fix-co-existence-bug-between-sg-logging-and-fwg-logging-ef16077880d76449.yaml --- neutron-13.0.0/releasenotes/notes/fix-co-existence-bug-between-sg-logging-and-fwg-logging-ef16077880d76449.yaml 1970-01-01 00:00:00.000000000 +0000 +++ neutron-13.0.1/releasenotes/notes/fix-co-existence-bug-between-sg-logging-and-fwg-logging-ef16077880d76449.yaml 2018-09-10 05:07:09.000000000 +0000 @@ -0,0 +1,7 @@ +--- +fixes: + - | + Add ``resource_type`` into log object query to distinguish between security + group and firewall group log objects. + For more information see bug + `1787119 `_. diff -Nru neutron-13.0.0/releasenotes/notes/reno.cache neutron-13.0.1/releasenotes/notes/reno.cache --- neutron-13.0.0/releasenotes/notes/reno.cache 2018-08-30 14:17:27.000000000 +0000 +++ neutron-13.0.1/releasenotes/notes/reno.cache 2018-09-10 05:09:43.000000000 +0000 @@ -1,5 +1,15 @@ --- file-contents: + releasenotes/notes/fix-co-existence-bug-between-sg-logging-and-fwg-logging-ef16077880d76449.yaml: + fixes: ['Add ``resource_type`` into log object query to distinguish between security + + group and firewall group log objects. + + For more information see bug + + `1787119 `_. + + '] releasenotes/notes/metering-iptables-driver-load-interface-driver-ca397f1db40ec643.yaml: other: ['The metering agent iptables driver can now load its interface driver by @@ -13,6 +23,11 @@ '] notes: - files: + - - releasenotes/notes/fix-co-existence-bug-between-sg-logging-and-fwg-logging-ef16077880d76449.yaml + - !!binary | + M2U2ODM5ODMzNTc5NWQ0MjJkNThhNmUyMTEwZjIwMjU5MDdjNTg5Mg== + version: 13.0.1 +- files: - - releasenotes/notes/metering-iptables-driver-load-interface-driver-ca397f1db40ec643.yaml - !!binary | YWQyYzFiYzM3NGI2YzIxNDM5Y2RkYzkyZTk3ZDZmNmQ5NDFlMzUwNw== diff -Nru neutron-13.0.0/RELEASENOTES.rst neutron-13.0.1/RELEASENOTES.rst --- neutron-13.0.0/RELEASENOTES.rst 2018-08-30 14:17:27.000000000 +0000 +++ neutron-13.0.1/RELEASENOTES.rst 2018-09-10 05:09:43.000000000 +0000 @@ -2,6 +2,24 @@ neutron ======= +.. _neutron_13.0.1: + +13.0.1 +====== + +.. _neutron_13.0.1_Bug Fixes: + +Bug Fixes +--------- + +.. releasenotes/notes/fix-co-existence-bug-between-sg-logging-and-fwg-logging-ef16077880d76449.yaml @ b'3e68398335795d422d58a6e2110f2025907c5892' + +- Add ``resource_type`` into log object query to distinguish between security + group and firewall group log objects. + For more information see bug + `1787119 `_. + + .. _neutron_13.0.0: 13.0.0 diff -Nru neutron-13.0.0/.zuul.yaml neutron-13.0.1/.zuul.yaml --- neutron-13.0.0/.zuul.yaml 2018-08-30 14:14:55.000000000 +0000 +++ neutron-13.0.1/.zuul.yaml 2018-09-10 05:07:20.000000000 +0000 @@ -1,6 +1,14 @@ - project: templates: - neutron-tempest-plugin-jobs + - openstack-python-jobs + - openstack-python35-jobs + - publish-openstack-sphinx-docs + - periodic-stable-jobs + - check-requirements + - integrated-gate + - integrated-gate-py35 + - release-notes-jobs check: jobs: - neutron-functional @@ -29,6 +37,18 @@ - ^setup.cfg$ - ^tools/.*$ - ^tox.ini$ + - openstack-tox-cover + - tempest-full: + irrelevant-files: + - ^(test-|)requirements.txt$ + - ^.*\.rst$ + - ^doc/.*$ + - ^neutron/locale/.*$ + - ^neutron/tests/unit/.*$ + - ^releasenotes/.*$ + - ^setup.cfg$ + - ^tools/.*$ + - ^tox.ini$ gate: jobs: - neutron-functional @@ -40,6 +60,7 @@ - neutron-grenade-dvr-multinode - neutron-grenade - openstack-tox-lower-constraints + - openstack-tox-cover periodic: jobs: - neutron-functional @@ -52,6 +73,99 @@ - neutron-fullstack-with-uwsgi - neutron-tempest-with-uwsgi + - legacy-grenade-dsvm-neutron-linuxbridge-multinode: + irrelevant-files: + - ^(test-|)requirements.txt$ + - ^.*\.rst$ + - ^doc/.*$ + - ^neutron/locale/.*$ + - ^neutron/tests/unit/.*$ + - ^releasenotes/.*$ + - ^setup.cfg$ + - ^tools/.*$ + - ^tox.ini$ + - legacy-grenade-dsvm-neutron-forward: + irrelevant-files: + - ^(test-|)requirements.txt$ + - ^.*\.rst$ + - ^doc/.*$ + - ^neutron/locale/.*$ + - ^neutron/tests/unit/.*$ + - ^releasenotes/.*$ + - ^setup.cfg$ + - ^tools/.*$ + - ^tox.ini$ + - legacy-neutron-dsvm-api-pecan + - legacy-tempest-dsvm-neutron-pg-full: + irrelevant-files: + - ^(test-|)requirements.txt$ + - ^.*\.rst$ + - ^doc/.*$ + - ^neutron/locale/.*$ + - ^neutron/tests/unit/.*$ + - ^releasenotes/.*$ + - ^setup.cfg$ + - ^tools/.*$ + - ^tox.ini$ + - legacy-tempest-dsvm-neutron-pecan: + irrelevant-files: + - ^(test-|)requirements.txt$ + - ^.*\.rst$ + - ^doc/.*$ + - ^neutron/locale/.*$ + - ^neutron/tests/unit/.*$ + - ^releasenotes/.*$ + - ^setup.cfg$ + - ^tools/.*$ + - ^tox.ini$ + - legacy-tempest-dsvm-neutron-full-centos-7: + irrelevant-files: + - ^(test-|)requirements.txt$ + - ^.*\.rst$ + - ^doc/.*$ + - ^neutron/locale/.*$ + - ^neutron/tests/unit/.*$ + - ^releasenotes/.*$ + - ^setup.cfg$ + - ^tools/.*$ + - ^tox.ini$ + - legacy-tempest-dsvm-neutron-dvr-multinode-full: + irrelevant-files: + - ^(test-|)requirements.txt$ + - ^.*\.rst$ + - ^doc/.*$ + - ^neutron/locale/.*$ + - ^neutron/tests/unit/.*$ + - ^releasenotes/.*$ + - ^setup.cfg$ + - ^tools/.*$ + - ^tox.ini$ + - legacy-tempest-dsvm-neutron-with-ryu-master: + irrelevant-files: + - ^(test-|)requirements.txt$ + - ^.*\.rst$ + - ^doc/.*$ + - ^neutron/locale/.*$ + - ^neutron/tests/unit/.*$ + - ^releasenotes/.*$ + - ^setup.cfg$ + - ^tools/.*$ + - ^tox.ini$ + - legacy-tempest-dsvm-neutron-full-opensuse-423: + irrelevant-files: + - ^(test-|)requirements.txt$ + - ^.*\.rst$ + - ^doc/.*$ + - ^neutron/locale/.*$ + - ^neutron/tests/unit/.*$ + - ^releasenotes/.*$ + - ^setup.cfg$ + - ^tools/.*$ + - ^tox.ini$ + + post: + jobs: + - openstack-tox-cover - job: name: neutron-functional parent: legacy-dsvm-base @@ -377,7 +491,7 @@ vars: tox_envlist: full devstack_localrc: - NEUTRON_DEPLOY_MOD_WSGI: True + NEUTRON_DEPLOY_MOD_WSGI: true irrelevant-files: - ^(test-|)requirements.txt$ - ^.*\.rst$