示例#1
0
 def test_bump_revision(self):
     db_rev.create_initial_revision(self.net['id'], constants.TYPE_NETWORKS,
                                    self.session)
     self.net['revision_number'] = 123
     db_rev.bump_revision(self.net, constants.TYPE_NETWORKS)
     row = self.get_revision_row(self.net['id'])
     self.assertEqual(123, row.revision_number)
示例#2
0
 def test_bump_revision_row_not_found(self, mock_log):
     self.net['revision_number'] = 123
     db_rev.bump_revision(self.net, constants.TYPE_NETWORKS)
     # Assert the revision number wasn't bumped
     row = self.get_revision_row(self.net['id'])
     self.assertEqual(123, row.revision_number)
     self.assertIn('No revision row found for', mock_log.call_args[0][0])
示例#3
0
    def remove_router_interface(self, context, router_id, interface_info):
        router_interface_info = \
            super(OVNL3RouterPlugin, self).remove_router_interface(
                context, router_id, interface_info)
        router = self.get_router(context, router_id)
        port_id = router_interface_info['port_id']
        multi_prefix = False
        port_removed = False
        try:
            port = self._plugin.get_port(context, port_id)
            # The router interface port still exists, call ovn to update it.
            self._ovn_client.update_router_port(port, bump_db_rev=False)
            multi_prefix = True
        except n_exc.PortNotFound:
            # The router interface port doesn't exist any more,
            # we will call ovn to delete it once we remove the snat
            # rules in the router itself if we have to
            port_removed = True

        if not router.get(l3.EXTERNAL_GW_INFO):
            if port_removed:
                self._ovn_client.delete_router_port(port_id, router_id)
            return router_interface_info

        try:
            cidr = None
            if multi_prefix:
                subnet = self._plugin.get_subnet(context,
                                                 interface_info['subnet_id'])
                if subnet['ip_version'] == 4:
                    cidr = subnet['cidr']
            else:
                subnet_ids = router_interface_info.get('subnet_ids')
                for subnet_id in subnet_ids:
                    subnet = self._plugin.get_subnet(context, subnet_id)
                    if subnet['ip_version'] == 4:
                        cidr = subnet['cidr']
                        break

            if utils.is_snat_enabled(router) and cidr:
                self._ovn_client.update_nat_rules(router,
                                                  networks=[cidr],
                                                  enable_snat=False)
        except Exception:
            with excutils.save_and_reraise_exception():
                super(OVNL3RouterPlugin,
                      self).add_router_interface(context, router_id,
                                                 interface_info)
                LOG.error('Error is deleting snat')

        # NOTE(mangelajo): If the port doesn't exist anymore, we delete the
        # router port as the last operation and update the revision database
        # to ensure consistency
        if port_removed:
            self._ovn_client.delete_router_port(port_id, router_id)
        else:
            # otherwise, we just update the revision database
            db_rev.bump_revision(port, ovn_const.TYPE_ROUTER_PORTS)

        return router_interface_info
 def test_bump_older_revision(self):
     db_rev.create_initial_revision(self.net['id'], constants.TYPE_NETWORKS,
                                    self.session, revision_number=123)
     self.net['revision_number'] = 1
     db_rev.bump_revision(self.net, constants.TYPE_NETWORKS)
     # Assert the revision number wasn't bumped
     row = db_rev.get_revision_row(self.net['id'])
     self.assertEqual(123, row.revision_number)
示例#5
0
    def add_router_interface(self, context, router_id, interface_info):
        router_interface_info = \
            super(OVNL3RouterPlugin, self).add_router_interface(
                context, router_id, interface_info)
        port = self._plugin.get_port(context, router_interface_info['port_id'])

        multi_prefix = False
        if (len(router_interface_info['subnet_ids']) == 1
                and len(port['fixed_ips']) > 1):
            # NOTE(lizk) It's adding a subnet onto an already existing router
            # interface port, try to update lrouter port 'networks' column.
            self._ovn_client.update_router_port(port, bump_db_rev=False)
            multi_prefix = True
        else:
            self._ovn_client.create_router_port(router_id, port)

        router = self.get_router(context, router_id)
        if not router.get(l3.EXTERNAL_GW_INFO):
            db_rev.bump_revision(port, ovn_const.TYPE_ROUTER_PORTS)
            return router_interface_info

        cidr = None
        for fixed_ip in port['fixed_ips']:
            subnet = self._plugin.get_subnet(context, fixed_ip['subnet_id'])
            if multi_prefix:
                if 'subnet_id' in interface_info:
                    if subnet['id'] is not interface_info['subnet_id']:
                        continue
            if subnet['ip_version'] == 4:
                cidr = subnet['cidr']

        if utils.is_snat_enabled(router) and cidr:
            try:
                self._ovn_client.update_nat_rules(router,
                                                  networks=[cidr],
                                                  enable_snat=True)
            except Exception:
                with excutils.save_and_reraise_exception():
                    self._ovn.delete_lrouter_port(
                        utils.ovn_lrouter_port_name(port['id']),
                        utils.ovn_name(router_id)).execute(check_error=True)
                    super(OVNL3RouterPlugin, self).remove_router_interface(
                        context, router_id, router_interface_info)
                    LOG.error(
                        'Error updating snat for subnet %(subnet)s in '
                        'router %(router)s', {
                            'subnet': router_interface_info['subnet_id'],
                            'router': router_id
                        })

        db_rev.bump_revision(port, ovn_const.TYPE_ROUTER_PORTS)
        return router_interface_info
示例#6
0
    def _fix_create_update(self, row):
        res_map = self._resources_func_map[row.resource_type]
        admin_context = n_context.get_admin_context()
        try:
            # Get the latest version of the resource in Neutron DB
            n_obj = res_map['neutron_get'](admin_context, row.resource_uuid)
        except n_exc.NotFound:
            LOG.warning(
                'Skip fixing resource %(res_uuid)s (type: '
                '%(res_type)s). Resource does not exist in Neutron '
                'database anymore', {
                    'res_uuid': row.resource_uuid,
                    'res_type': row.resource_type
                })
            return

        ovn_obj = res_map['ovn_get'](row.resource_uuid)

        if not ovn_obj:
            res_map['ovn_create'](n_obj)
        else:
            if row.resource_type == ovn_const.TYPE_SECURITY_GROUP_RULES:
                LOG.error(
                    "SG rule %s found with a revision number while "
                    "this resource doesn't support updates", row.resource_uuid)
            elif row.resource_type == ovn_const.TYPE_SECURITY_GROUPS:
                # In OVN, we don't care about updates to security groups,
                # so just bump the revision number to whatever it's
                # supposed to be.
                db_rev.bump_revision(n_obj, row.resource_type)
            else:
                ext_ids = getattr(ovn_obj, 'external_ids', {})
                ovn_revision = int(
                    ext_ids.get(ovn_const.OVN_REV_NUM_EXT_ID_KEY, -1))
                # If the resource exist in the OVN DB but the revision
                # number is different from Neutron DB, updated it.
                if ovn_revision != n_obj['revision_number']:
                    res_map['ovn_update'](n_obj)
                else:
                    # If the resource exist and the revision number
                    # is equal on both databases just bump the revision on
                    # the cache table.
                    db_rev.bump_revision(n_obj, row.resource_type)
示例#7
0
    def _fix_create_update_network(self, row):
        # Get the latest version of the resource in Neutron DB
        admin_context = n_context.get_admin_context()
        n_db_obj = self._ovn_client._plugin.get_network(
            admin_context, row.resource_uuid)
        ovn_net = self._nb_idl.get_lswitch(utils.ovn_name(row.resource_uuid))

        if not ovn_net:
            # If the resource doesn't exist in the OVN DB, create it.
            self._ovn_client.create_network(n_db_obj)
        else:
            ext_ids = getattr(ovn_net, 'external_ids', {})
            ovn_revision = int(
                ext_ids.get(ovn_const.OVN_REV_NUM_EXT_ID_KEY, -1))
            # If the resource exist in the OVN DB but the revision
            # number is different from Neutron DB, updated it.
            if ovn_revision != n_db_obj['revision_number']:
                self._ovn_client.update_network(n_db_obj)
            else:
                # If the resource exist and the revision number
                # is equal on both databases just bump the revision on
                # the cache table.
                db_rev.bump_revision(n_db_obj, ovn_const.TYPE_NETWORKS)
示例#8
0
 def _update_security_group(self, resource, event, trigger, security_group,
                            **kwargs):
     # OVN doesn't care about updates to security groups, only if they
     # exist or not. We are bumping the revision number here so it
     # doesn't show as inconsistent to the maintenance periodic task
     db_rev.bump_revision(security_group, ovn_const.TYPE_SECURITY_GROUPS)