filter "updated_at" and "revision_number" in _gateway_ports_equal

When the HA attribute of the router changes, the code determines
whether the gateway in memory is consistent with the gateway
in the database to decide whether it needs to be reconfigured.
But there are problems with the judging conditions.

After the HA attribute of the router changes, the relevant parameters
of gateway port will be updated by ML2 agent,
including "binding:host_id"、"updated_at" and "revison_number".
Method "_gateway_ports_equal" removes
only the "binding:host_id" property of the port,
resulting in unequal results for each decision

Change-Id: I19e024ff360611d191da2bd3bff1b86abe1a8ea1
Closes-Bug: 1797298
This commit is contained in:
hujin 2018-10-11 13:28:11 +08:00
parent 14c940333c
commit 6541304d5e
2 changed files with 33 additions and 1 deletions

View File

@ -28,6 +28,8 @@ from neutron.agent.linux import external_process
from neutron.agent.linux import ip_lib
from neutron.agent.linux import keepalived
from neutron.common import utils as common_utils
from neutron.extensions import revisions
from neutron.extensions import timestamp
LOG = logging.getLogger(__name__)
HA_DEV_PREFIX = 'ha-'
@ -408,7 +410,8 @@ class HaRouter(router.RouterInfo):
def _get_filtered_dict(d, ignore):
return {k: v for k, v in d.items() if k not in ignore}
keys_to_ignore = set([portbindings.HOST_ID])
keys_to_ignore = set([portbindings.HOST_ID, timestamp.UPDATED,
revisions.REVISION])
port1_filtered = _get_filtered_dict(port1, keys_to_ignore)
port2_filtered = _get_filtered_dict(port2, keys_to_ignore)
return port1_filtered == port2_filtered

View File

@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import copy
import signal
import mock
@ -20,12 +21,18 @@ from oslo_utils import uuidutils
from neutron.agent.l3 import ha_router
from neutron.agent.l3 import router_info
from neutron.tests import base
from neutron.tests.common import l3_test_common
from neutron.tests import tools
_uuid = uuidutils.generate_uuid
class TestBasicRouterOperations(base.BaseTestCase):
def setUp(self):
super(TestBasicRouterOperations, self).setUp()
self.device_exists_p = mock.patch(
'neutron.agent.linux.ip_lib.device_exists')
self.device_exists = self.device_exists_p.start()
def _create_router(self, router=None, **kwargs):
if not router:
@ -141,3 +148,25 @@ class TestBasicRouterOperations(base.BaseTestCase):
'ha_state')
self.mock_open = IOError
self.assertEqual('unknown', ri.ha_state)
def test_gateway_ports_equal(self):
ri = self._create_router(mock.MagicMock())
ri.driver = mock.MagicMock()
subnet_id, qos_policy_id = _uuid(), _uuid()
_, old_gw_port = l3_test_common.prepare_ext_gw_test(
self, ri, True)
old_gw_port['qos_policy_id'] = qos_policy_id
new_gw_port = copy.deepcopy(old_gw_port)
new_gw_port.update({'binding:host_id': 'node02',
'updated_at': '2018-11-02T14:07:00',
'revision_number': 101,
'qos_policy_id': qos_policy_id})
self.assertTrue(ri._gateway_ports_equal(old_gw_port, new_gw_port))
fixed_ip = {'ip_address': '10.10.10.3', 'subnet_id': subnet_id}
new_gw_port['fixed_ips'].append(fixed_ip)
self.assertFalse(ri._gateway_ports_equal(old_gw_port, new_gw_port))
new_gw_port['fixed_ips'].remove(fixed_ip)
new_gw_port['qos_policy_id'] = _uuid()
self.assertFalse(ri._gateway_ports_equal(old_gw_port, new_gw_port))