"default_availability_zones" need to be considered when validate az

If not set availability_zone_hits when create router, should use
configuration parameter default_availability_zones.
At present, only the creation parameters are validate, and the default
availability zones not validate.
Creating a network is the same as creating a route.

Closes-bug: #1938261

Change-Id: I1c7f50b69a31d725b762e3061f09a0bd5b077a58
This commit is contained in:
zhouhenglc 2021-07-28 15:25:39 +08:00 committed by ZhouHeng
parent b6bb4c0941
commit 7988ab5df0
9 changed files with 55 additions and 21 deletions

View File

@ -16,7 +16,6 @@ import os
import re
import netaddr
from neutron_lib.api.definitions import availability_zone as az_def
from neutron_lib.api.definitions import external_net
from neutron_lib.api.definitions import extra_dhcp_opt as edo_ext
from neutron_lib.api.definitions import l3
@ -513,11 +512,6 @@ def get_port_id_from_gwc_row(row):
return constants.RE_PORT_FROM_GWC.search(row.name).group(2)
def get_az_hints(resource):
"""Return the availability zone hints from a given resource."""
return (resource.get(az_def.AZ_HINTS) or CONF.default_availability_zones)
def get_chassis_availability_zones(chassis):
"""Return a list of availability zones from a given OVN Chassis."""
azs = []

View File

@ -34,6 +34,7 @@ import uuid
import eventlet
from eventlet.green import subprocess
import netaddr
from neutron_lib.api.definitions import availability_zone as az_def
from neutron_lib import constants as n_const
from neutron_lib.db import api as db_api
from neutron_lib.services.trunk import constants as trunk_constants
@ -982,3 +983,9 @@ def get_sql_random_method(sql_dialect_name):
# https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html
elif sql_dialect_name == mysql_dialect.name:
return sql_func.rand
def get_az_hints(resource):
"""Return the availability zone hints from a given resource."""
return (resource.get(az_def.AZ_HINTS) or
cfg.CONF.default_availability_zones)

View File

@ -21,6 +21,7 @@ from neutron_lib.db import resource_extend
from neutron_lib.plugins import constants
from neutron_lib.plugins import directory
from neutron.common import utils
from neutron.db import l3_attrs_db
@ -44,8 +45,9 @@ class RouterAvailabilityZoneMixin(l3_attrs_db.ExtraAttributesMixin):
context = payload.context
router = payload.latest_state
router_db = payload.metadata['router_db']
if az_def.AZ_HINTS in router:
az_hints = utils.get_az_hints(router)
if az_hints:
self.validate_availability_zones(context, 'router',
router[az_def.AZ_HINTS])
az_hints)
self.set_extra_attr_value(context, router_db, az_def.AZ_HINTS,
router[az_def.AZ_HINTS])
az_hints)

View File

@ -39,6 +39,7 @@ from ovsdbapp.backend.ovs_idl import idlutils
from neutron.common.ovn import acl as ovn_acl
from neutron.common.ovn import constants as ovn_const
from neutron.common.ovn import utils
from neutron.common import utils as common_utils
from neutron.conf.plugins.ml2.drivers.ovn import ovn_conf
from neutron.db import ovn_revision_numbers_db as db_rev
from neutron.db import segments_db
@ -1147,7 +1148,7 @@ class OVNClient(object):
ovn_const.OVN_REV_NUM_EXT_ID_KEY: str(utils.get_revision_number(
router, ovn_const.TYPE_ROUTERS)),
ovn_const.OVN_ROUTER_AZ_HINTS_EXT_ID_KEY:
','.join(utils.get_az_hints(router))}
','.join(common_utils.get_az_hints(router))}
def create_router(self, context, router, add_external_gateway=True):
"""Create a logical router."""
@ -1369,7 +1370,8 @@ class OVNClient(object):
port['network_id'])
physnet = self._get_physnet(port_net)
candidates = self.get_candidates_for_scheduling(
physnet, availability_zone_hints=utils.get_az_hints(router))
physnet, availability_zone_hints=common_utils.get_az_hints(
router))
selected_chassis = self._ovn_scheduler.select(
self._nb_idl, self._sb_idl, lrouter_port_name,
candidates=candidates)

View File

@ -1075,12 +1075,10 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
vlt = vlan_apidef.get_vlan_transparent(net_data)
net_db['vlan_transparent'] = vlt
result['vlan_transparent'] = vlt
if az_def.AZ_HINTS in net_data:
self.validate_availability_zones(context, 'network',
net_data[az_def.AZ_HINTS])
az_hints = az_validator.convert_az_list_to_string(
net_data[az_def.AZ_HINTS])
az_hints = utils.get_az_hints(net_data)
if az_hints:
self.validate_availability_zones(context, 'network', az_hints)
az_hints = az_validator.convert_az_list_to_string(az_hints)
net_db[az_def.AZ_HINTS] = az_hints
result[az_def.AZ_HINTS] = az_hints
registry.publish(resources.NETWORK, events.PRECOMMIT_CREATE, self,

View File

@ -19,7 +19,6 @@ import functools
import itertools
import random
from neutron_lib.api.definitions import availability_zone as az_def
from neutron_lib import constants as lib_const
from neutron_lib.db import api as lib_db_api
from neutron_lib.exceptions import l3 as l3_exc
@ -367,8 +366,7 @@ class AZLeastRoutersScheduler(LeastRoutersScheduler):
according to router's az_hints.
"""
def _get_az_hints(self, router):
return (router.get(az_def.AZ_HINTS) or
cfg.CONF.default_availability_zones)
return utils.get_az_hints(router)
def _get_routers_can_schedule(self, plugin, context, routers, l3_agent):
"""Overwrite L3Scheduler's method to filter by availability zone."""

View File

@ -31,6 +31,7 @@ from oslo_utils import excutils
from neutron.common.ovn import constants as ovn_const
from neutron.common.ovn import extensions
from neutron.common.ovn import utils
from neutron.common import utils as common_utils
from neutron.db.availability_zone import router as router_az_db
from neutron.db import dns_db
from neutron.db import extraroute_db
@ -360,7 +361,7 @@ class OVNL3RouterPlugin(service_base.ServicePluginBase,
lrp = self._ovn.get_lrouter_port(lrp_name)
router = self.get_router(
context, lrp.external_ids[ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY])
az_hints = utils.get_az_hints(router)
az_hints = common_utils.get_az_hints(router)
return az_hints
def schedule_unhosted_gateways(self, event_from_chassis=None):

View File

@ -16,6 +16,7 @@ from neutron_lib.api.definitions import availability_zone as az_def
from neutron_lib.api.definitions import availability_zone_filter as azf_def
from neutron_lib import context
from neutron_lib.exceptions import availability_zone as az_exc
from oslo_config import cfg
from neutron.db import agents_db
from neutron.db import db_base_plugin_v2
@ -170,3 +171,18 @@ class TestAZNetworkCase(AZTestCommon):
res = self._create_network(self.fmt, 'net', True,
availability_zone_hints=['nova3'])
self.assertEqual(404, res.status_int)
def test_create_network_with_default_azs_not_existing(self):
self._register_azs()
cfg.CONF.set_default('default_availability_zones', ['nova4'])
res = self._create_network(self.fmt, 'net', True)
self.assertEqual(404, res.status_int)
def test_create_network_with_default_azs_existing_az(self):
self._register_azs()
az_hints = ['nova1', 'nova2']
cfg.CONF.set_default('default_availability_zones', az_hints)
with self.network() as net:
res = self._show('networks', net['network']['id'])
self.assertCountEqual(az_hints,
res['network']['availability_zone_hints'])

View File

@ -15,6 +15,7 @@ from neutron_lib.api.definitions import l3 as l3_apidef
from neutron_lib.api.definitions import router_availability_zone
from neutron_lib import constants as lib_const
from neutron_lib.plugins import constants
from oslo_config import cfg
from neutron.db.availability_zone import router as router_az_db
from neutron.db import l3_agentschedulers_db
@ -88,3 +89,18 @@ class TestAZRouterCase(test_az.AZTestCommon, test_l3.L3NatTestCaseMixin):
res = self._create_router(self.fmt, 'tenant_id',
availability_zone_hints=['nova4'])
self.assertEqual(404, res.status_int)
def test_create_router_with_default_azs_not_existing(self):
self._register_azs()
cfg.CONF.set_default('default_availability_zones', ['nova4'])
res = self._create_router(self.fmt, 'tenant_id')
self.assertEqual(404, res.status_int)
def test_create_router_with_default_azs_existing_az(self):
self._register_azs()
az_hints = ['nova2', 'nova3']
cfg.CONF.set_default('default_availability_zones', az_hints)
with self.router() as router:
res = self._show('routers', router['router']['id'])
self.assertCountEqual(az_hints,
res['router']['availability_zone_hints'])