From e88f1e6fd5f0f649b4ec0f181038d67c860b85fb Mon Sep 17 00:00:00 2001 From: Boden R Date: Fri, 20 Oct 2017 10:04:09 -0600 Subject: [PATCH] use availability zone api def from lib Commit I1d4ded9959c05c65b04b118b1c31b8e6db652e67 rehomed the availability zone extension's API definition into neutron-lib. This patch consumes it, removing the rehomed logic in neutron and switching over to lib's version of it. NeutronLibImpact Change-Id: I761381de0d6e26a0380386700e7921b824991669 --- neutron/db/agents_db.py | 3 +- neutron/db/availability_zone/network.py | 9 +- neutron/db/availability_zone/router.py | 10 +- neutron/db/l3_attrs_db.py | 6 +- neutron/extensions/availability_zone.py | 95 ++----------------- .../extensions/network_availability_zone.py | 11 +-- .../extensions/router_availability_zone.py | 11 +-- neutron/objects/network.py | 17 ++-- neutron/objects/router.py | 17 ++-- neutron/plugins/ml2/plugin.py | 15 +-- neutron/scheduler/dhcp_agent_scheduler.py | 6 +- neutron/scheduler/l3_agent_scheduler.py | 4 +- .../unit/extensions/test_availability_zone.py | 6 +- neutron/tests/unit/plugins/ml2/test_plugin.py | 13 ++- 14 files changed, 75 insertions(+), 148 deletions(-) diff --git a/neutron/db/agents_db.py b/neutron/db/agents_db.py index fa1e68a92df..732bd0408ab 100644 --- a/neutron/db/agents_db.py +++ b/neutron/db/agents_db.py @@ -23,6 +23,7 @@ from neutron_lib.callbacks import registry from neutron_lib.callbacks import resources from neutron_lib import constants from neutron_lib import context +from neutron_lib.exceptions import availability_zone as az_exc from neutron_lib.plugins import directory from oslo_config import cfg from oslo_log import log as logging @@ -135,7 +136,7 @@ class AgentAvailabilityZoneMixin(az_ext.AvailabilityZonePluginBase): azs = [item[0] for item in query] diff = set(availability_zones) - set(azs) if diff: - raise az_ext.AvailabilityZoneNotFound(availability_zone=diff.pop()) + raise az_exc.AvailabilityZoneNotFound(availability_zone=diff.pop()) class AgentDbMixin(ext_agent.AgentPluginBase, AgentAvailabilityZoneMixin): diff --git a/neutron/db/availability_zone/network.py b/neutron/db/availability_zone/network.py index 2e0c3ecf234..1473bcb8d92 100644 --- a/neutron/db/availability_zone/network.py +++ b/neutron/db/availability_zone/network.py @@ -11,11 +11,12 @@ # License for the specific language governing permissions and limitations # under the License. +from neutron_lib.api.definitions import availability_zone as az_def from neutron_lib.api.definitions import network as net_def +from neutron_lib.api.validators import availability_zone as az_validator from neutron_lib.plugins import directory from neutron.db import _resource_extend as resource_extend -from neutron.extensions import availability_zone as az_ext from neutron.extensions import network_availability_zone as net_az @@ -26,8 +27,8 @@ class NetworkAvailabilityZoneMixin(net_az.NetworkAvailabilityZonePluginBase): @staticmethod @resource_extend.extends([net_def.COLLECTION_NAME]) def _extend_availability_zone(net_res, net_db): - net_res[az_ext.AZ_HINTS] = az_ext.convert_az_string_to_list( - net_db[az_ext.AZ_HINTS]) + net_res[az_def.AZ_HINTS] = az_validator.convert_az_string_to_list( + net_db[az_def.AZ_HINTS]) plugin = directory.get_plugin() - net_res[az_ext.AVAILABILITY_ZONES] = ( + net_res[az_def.COLLECTION_NAME] = ( plugin.get_network_availability_zones(net_db)) diff --git a/neutron/db/availability_zone/router.py b/neutron/db/availability_zone/router.py index 7a95e9d6efe..5978f380349 100644 --- a/neutron/db/availability_zone/router.py +++ b/neutron/db/availability_zone/router.py @@ -11,6 +11,7 @@ # License for the specific language governing permissions and limitations # under the License. +from neutron_lib.api.definitions import availability_zone as az_def from neutron_lib.callbacks import events from neutron_lib.callbacks import registry from neutron_lib.callbacks import resources @@ -20,7 +21,6 @@ from neutron_lib.plugins import directory from neutron.common import utils from neutron.db import _resource_extend as resource_extend from neutron.db import l3_attrs_db -from neutron.extensions import availability_zone as az_ext from neutron.extensions import l3 @@ -42,8 +42,8 @@ class RouterAvailabilityZoneMixin(l3_attrs_db.ExtraAttributesMixin): @registry.receives(resources.ROUTER, [events.PRECOMMIT_CREATE]) def _process_az_request(self, resource, event, trigger, context, router, router_db, **kwargs): - if az_ext.AZ_HINTS in router: + if az_def.AZ_HINTS in router: self.validate_availability_zones(context, 'router', - router[az_ext.AZ_HINTS]) - self.set_extra_attr_value(context, router_db, az_ext.AZ_HINTS, - router[az_ext.AZ_HINTS]) + router[az_def.AZ_HINTS]) + self.set_extra_attr_value(context, router_db, az_def.AZ_HINTS, + router[az_def.AZ_HINTS]) diff --git a/neutron/db/l3_attrs_db.py b/neutron/db/l3_attrs_db.py index ec3bae78eef..d26c6ce9804 100644 --- a/neutron/db/l3_attrs_db.py +++ b/neutron/db/l3_attrs_db.py @@ -12,12 +12,12 @@ # License for the specific language governing permissions and limitations # under the License. +from neutron_lib.api.validators import availability_zone as az_validator from oslo_config import cfg from neutron._i18n import _ from neutron.db import _resource_extend as resource_extend from neutron.db.models import l3_attrs -from neutron.extensions import availability_zone as az from neutron.extensions import l3 @@ -28,8 +28,8 @@ def get_attr_info(): 'ha_vr_id': {'default': 0}, 'availability_zone_hints': { 'default': '[]', - 'transform_to_db': az.convert_az_list_to_string, - 'transform_from_db': az.convert_az_string_to_list} + 'transform_to_db': az_validator.convert_az_list_to_string, + 'transform_from_db': az_validator.convert_az_string_to_list} } diff --git a/neutron/extensions/availability_zone.py b/neutron/extensions/availability_zone.py index 8ec6c42e87b..db681537323 100644 --- a/neutron/extensions/availability_zone.py +++ b/neutron/extensions/availability_zone.py @@ -14,112 +14,31 @@ import abc +from neutron_lib.api.definitions import availability_zone as az_def from neutron_lib.api import extensions as api_extensions -from neutron_lib.api import validators -from neutron_lib import exceptions from neutron_lib.plugins import directory -from oslo_serialization import jsonutils import six -from neutron._i18n import _ from neutron.api import extensions from neutron.api.v2 import base -AZ_HINTS_DB_LEN = 255 - - -# resource independent common methods -def convert_az_list_to_string(az_list): - return jsonutils.dumps(az_list) - - -def convert_az_string_to_list(az_string): - return jsonutils.loads(az_string) if az_string else [] - - -def _validate_availability_zone_hints(data, valid_value=None): - # syntax check only here. existence of az will be checked later. - msg = validators.validate_list_of_unique_strings(data) - if msg: - return msg - az_string = convert_az_list_to_string(data) - if len(az_string) > AZ_HINTS_DB_LEN: - msg = _("Too many availability_zone_hints specified") - raise exceptions.InvalidInput(error_message=msg) - -validators.add_validator('availability_zone_hints', - _validate_availability_zone_hints) - -# Attribute Map -RESOURCE_NAME = 'availability_zone' -AVAILABILITY_ZONES = 'availability_zones' -AZ_HINTS = 'availability_zone_hints' -# name: name of availability zone (string) -# resource: type of resource: 'network' or 'router' -# state: state of availability zone: 'available' or 'unavailable' -# It means whether users can use the availability zone. -RESOURCE_ATTRIBUTE_MAP = { - AVAILABILITY_ZONES: { - 'name': {'is_visible': True}, - 'resource': {'is_visible': True}, - 'state': {'is_visible': True} - } -} - -EXTENDED_ATTRIBUTES_2_0 = { - 'agents': { - RESOURCE_NAME: {'allow_post': False, 'allow_put': False, - 'is_visible': True} - } -} - - -class AvailabilityZoneNotFound(exceptions.NotFound): - message = _("AvailabilityZone %(availability_zone)s could not be found.") - - -class Availability_zone(api_extensions.ExtensionDescriptor): +class Availability_zone(api_extensions.APIExtensionDescriptor): """Availability zone extension.""" - - @classmethod - def get_name(cls): - return "Availability Zone" - - @classmethod - def get_alias(cls): - return "availability_zone" - - @classmethod - def get_description(cls): - return "The availability zone extension." - - @classmethod - def get_updated(cls): - return "2015-01-01T10:00:00-00:00" - - def get_required_extensions(self): - return ["agent"] + api_definition = az_def @classmethod def get_resources(cls): """Returns Ext Resources.""" plugin = directory.get_plugin() - params = RESOURCE_ATTRIBUTE_MAP.get(AVAILABILITY_ZONES) - controller = base.create_resource(AVAILABILITY_ZONES, - RESOURCE_NAME, plugin, params) + params = az_def.RESOURCE_ATTRIBUTE_MAP.get(az_def.COLLECTION_NAME) + controller = base.create_resource(az_def.COLLECTION_NAME, + az_def.RESOURCE_NAME, plugin, params) - ex = extensions.ResourceExtension(AVAILABILITY_ZONES, controller) + ex = extensions.ResourceExtension(az_def.COLLECTION_NAME, controller) return [ex] - def get_extended_resources(self, version): - if version == "2.0": - return dict(list(EXTENDED_ATTRIBUTES_2_0.items()) + - list(RESOURCE_ATTRIBUTE_MAP.items())) - else: - return {} - @six.add_metaclass(abc.ABCMeta) class AvailabilityZonePluginBase(object): diff --git a/neutron/extensions/network_availability_zone.py b/neutron/extensions/network_availability_zone.py index 3beb0e1c9c0..98998f2c19b 100644 --- a/neutron/extensions/network_availability_zone.py +++ b/neutron/extensions/network_availability_zone.py @@ -14,19 +14,18 @@ import abc +from neutron_lib.api.definitions import availability_zone as az_def from neutron_lib.api import extensions import six -from neutron.extensions import availability_zone as az_ext - EXTENDED_ATTRIBUTES_2_0 = { 'networks': { - az_ext.AVAILABILITY_ZONES: {'allow_post': False, 'allow_put': False, - 'is_visible': True}, - az_ext.AZ_HINTS: { + az_def.COLLECTION_NAME: {'allow_post': False, 'allow_put': False, + 'is_visible': True}, + az_def.AZ_HINTS: { 'allow_post': True, 'allow_put': False, 'is_visible': True, - 'validate': {'type:availability_zone_hints': None}, + 'validate': {'type:availability_zone_hint_list': None}, 'default': []}}, } diff --git a/neutron/extensions/router_availability_zone.py b/neutron/extensions/router_availability_zone.py index 053eb791b5f..3cd718c8bf8 100644 --- a/neutron/extensions/router_availability_zone.py +++ b/neutron/extensions/router_availability_zone.py @@ -14,19 +14,18 @@ import abc +from neutron_lib.api.definitions import availability_zone as az_def from neutron_lib.api import extensions import six -from neutron.extensions import availability_zone as az_ext - EXTENDED_ATTRIBUTES_2_0 = { 'routers': { - az_ext.AVAILABILITY_ZONES: {'allow_post': False, 'allow_put': False, - 'is_visible': True}, - az_ext.AZ_HINTS: { + az_def.COLLECTION_NAME: {'allow_post': False, 'allow_put': False, + 'is_visible': True}, + az_def.AZ_HINTS: { 'allow_post': True, 'allow_put': False, 'is_visible': True, - 'validate': {'type:availability_zone_hints': None}, + 'validate': {'type:availability_zone_hint_list': None}, 'default': []}} } diff --git a/neutron/objects/network.py b/neutron/objects/network.py index 39a9de17d12..7af9973e7d8 100644 --- a/neutron/objects/network.py +++ b/neutron/objects/network.py @@ -12,6 +12,8 @@ # License for the specific language governing permissions and limitations # under the License. +from neutron_lib.api.definitions import availability_zone as az_def +from neutron_lib.api.validators import availability_zone as az_validator from oslo_versionedobjects import base as obj_base from oslo_versionedobjects import fields as obj_fields @@ -23,7 +25,6 @@ from neutron.db import models_v2 from neutron.db.network_dhcp_agent_binding import models as ndab_models from neutron.db.port_security import models as ps_models from neutron.db import rbac_db_models -from neutron.extensions import availability_zone as az_ext from neutron.objects import agent as agent_obj from neutron.objects import base from neutron.objects import common_types @@ -263,17 +264,19 @@ class Network(rbac_db.NeutronRbacObject): @classmethod def modify_fields_from_db(cls, db_obj): result = super(Network, cls).modify_fields_from_db(db_obj) - if az_ext.AZ_HINTS in result: - result[az_ext.AZ_HINTS] = ( - az_ext.convert_az_string_to_list(result[az_ext.AZ_HINTS])) + if az_def.AZ_HINTS in result: + result[az_def.AZ_HINTS] = ( + az_validator.convert_az_string_to_list( + result[az_def.AZ_HINTS])) return result @classmethod def modify_fields_to_db(cls, fields): result = super(Network, cls).modify_fields_to_db(fields) - if az_ext.AZ_HINTS in result: - result[az_ext.AZ_HINTS] = ( - az_ext.convert_az_list_to_string(result[az_ext.AZ_HINTS])) + if az_def.AZ_HINTS in result: + result[az_def.AZ_HINTS] = ( + az_validator.convert_az_list_to_string( + result[az_def.AZ_HINTS])) return result def from_db_object(self, *objs): diff --git a/neutron/objects/router.py b/neutron/objects/router.py index bbceb56b4c5..814ce1dbc35 100644 --- a/neutron/objects/router.py +++ b/neutron/objects/router.py @@ -12,6 +12,8 @@ import netaddr +from neutron_lib.api.definitions import availability_zone as az_def +from neutron_lib.api.validators import availability_zone as az_validator from oslo_versionedobjects import base as obj_base from oslo_versionedobjects import fields as obj_fields from sqlalchemy import func @@ -23,7 +25,6 @@ from neutron.db.models import l3 from neutron.db.models import l3_attrs from neutron.db.models import l3agent as rb_model from neutron.db import models_v2 -from neutron.extensions import availability_zone as az_ext from neutron.objects import base from neutron.objects import common_types @@ -88,17 +89,19 @@ class RouterExtraAttributes(base.NeutronDbObject): def modify_fields_from_db(cls, db_obj): result = super(RouterExtraAttributes, cls).modify_fields_from_db( db_obj) - if az_ext.AZ_HINTS in result: - result[az_ext.AZ_HINTS] = ( - az_ext.convert_az_string_to_list(result[az_ext.AZ_HINTS])) + if az_def.AZ_HINTS in result: + result[az_def.AZ_HINTS] = ( + az_validator.convert_az_string_to_list( + result[az_def.AZ_HINTS])) return result @classmethod def modify_fields_to_db(cls, fields): result = super(RouterExtraAttributes, cls).modify_fields_to_db(fields) - if az_ext.AZ_HINTS in result: - result[az_ext.AZ_HINTS] = ( - az_ext.convert_az_list_to_string(result[az_ext.AZ_HINTS])) + if az_def.AZ_HINTS in result: + result[az_def.AZ_HINTS] = ( + az_validator.convert_az_list_to_string( + result[az_def.AZ_HINTS])) return result @classmethod diff --git a/neutron/plugins/ml2/plugin.py b/neutron/plugins/ml2/plugin.py index e9a88e0bc39..3970eb153c2 100644 --- a/neutron/plugins/ml2/plugin.py +++ b/neutron/plugins/ml2/plugin.py @@ -14,6 +14,7 @@ # under the License. from eventlet import greenthread +from neutron_lib.api.definitions import availability_zone as az_def from neutron_lib.api.definitions import extra_dhcp_opt as edo_ext from neutron_lib.api.definitions import network as net_def from neutron_lib.api.definitions import port as port_def @@ -21,6 +22,7 @@ from neutron_lib.api.definitions import port_security as psec from neutron_lib.api.definitions import portbindings from neutron_lib.api.definitions import subnet as subnet_def from neutron_lib.api import validators +from neutron_lib.api.validators import availability_zone as az_validator from neutron_lib.callbacks import events from neutron_lib.callbacks import exceptions from neutron_lib.callbacks import registry @@ -75,7 +77,6 @@ from neutron.db import segments_db from neutron.db import subnet_service_type_db_models as service_type_db from neutron.db import vlantransparent_db from neutron.extensions import allowedaddresspairs as addr_pair -from neutron.extensions import availability_zone as az_ext from neutron.extensions import netmtu_writable as mtu_ext from neutron.extensions import providernet as provider from neutron.extensions import vlantransparent @@ -810,13 +811,13 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, net_db['vlan_transparent'] = vlt result['vlan_transparent'] = vlt - if az_ext.AZ_HINTS in net_data: + if az_def.AZ_HINTS in net_data: self.validate_availability_zones(context, 'network', - net_data[az_ext.AZ_HINTS]) - az_hints = az_ext.convert_az_list_to_string( - net_data[az_ext.AZ_HINTS]) - net_db[az_ext.AZ_HINTS] = az_hints - result[az_ext.AZ_HINTS] = az_hints + net_data[az_def.AZ_HINTS]) + az_hints = az_validator.convert_az_list_to_string( + net_data[az_def.AZ_HINTS]) + net_db[az_def.AZ_HINTS] = az_hints + result[az_def.AZ_HINTS] = az_hints registry.notify(resources.NETWORK, events.PRECOMMIT_CREATE, self, context=context, request=net_data, network=result) diff --git a/neutron/scheduler/dhcp_agent_scheduler.py b/neutron/scheduler/dhcp_agent_scheduler.py index b1f859c31a4..0a625de1904 100644 --- a/neutron/scheduler/dhcp_agent_scheduler.py +++ b/neutron/scheduler/dhcp_agent_scheduler.py @@ -17,6 +17,7 @@ import collections from operator import itemgetter +from neutron_lib.api.definitions import availability_zone as az_def from neutron_lib import constants from neutron_lib.objects import exceptions from oslo_config import cfg @@ -25,7 +26,6 @@ from sqlalchemy import sql from neutron.agent.common import utils as agent_utils from neutron.db.models import agent as agent_model -from neutron.extensions import availability_zone as az_ext from neutron.objects import network from neutron.scheduler import base_resource_filter from neutron.scheduler import base_scheduler @@ -86,7 +86,7 @@ class AutoScheduler(object): if any(dhcp_agent.id == agent.id for agent in agents): continue net = plugin.get_network(context, net_id) - az_hints = (net.get(az_ext.AZ_HINTS) or + az_hints = (net.get(az_def.AZ_HINTS) or cfg.CONF.default_availability_zones) if (az_hints and dhcp_agent['availability_zone'] not in az_hints): @@ -263,7 +263,7 @@ class DhcpFilter(base_resource_filter.BaseResourceFilter): if hosted_agents is None: return {'n_agents': 0, 'hostable_agents': [], 'hosted_agents': []} n_agents = cfg.CONF.dhcp_agents_per_network - len(hosted_agents) - az_hints = (network.get(az_ext.AZ_HINTS) or + az_hints = (network.get(az_def.AZ_HINTS) or cfg.CONF.default_availability_zones) active_dhcp_agents = self._get_active_agents(plugin, context, az_hints) hosted_agent_ids = [agent['id'] for agent in hosted_agents] diff --git a/neutron/scheduler/l3_agent_scheduler.py b/neutron/scheduler/l3_agent_scheduler.py index 4f62cf970ec..96f1ce66bc7 100644 --- a/neutron/scheduler/l3_agent_scheduler.py +++ b/neutron/scheduler/l3_agent_scheduler.py @@ -19,6 +19,7 @@ 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 oslo_config import cfg from oslo_db import exception as db_exc @@ -30,7 +31,6 @@ from neutron.common import utils from neutron.db import api as db_api from neutron.db import l3_hamode_db from neutron.db.models import l3agent as rb_model -from neutron.extensions import availability_zone as az_ext from neutron.extensions import l3 from neutron.objects import l3agent as rb_obj @@ -374,7 +374,7 @@ class AZLeastRoutersScheduler(LeastRoutersScheduler): according to router's az_hints. """ def _get_az_hints(self, router): - return (router.get(az_ext.AZ_HINTS) or + return (router.get(az_def.AZ_HINTS) or cfg.CONF.default_availability_zones) def _get_routers_can_schedule(self, plugin, context, routers, l3_agent): diff --git a/neutron/tests/unit/extensions/test_availability_zone.py b/neutron/tests/unit/extensions/test_availability_zone.py index 96e156478d0..9b5ce9ed23f 100644 --- a/neutron/tests/unit/extensions/test_availability_zone.py +++ b/neutron/tests/unit/extensions/test_availability_zone.py @@ -13,7 +13,9 @@ import copy +from neutron_lib.api.definitions import availability_zone as az_def from neutron_lib import context +from neutron_lib.exceptions import availability_zone as az_exc from neutron.db import agents_db from neutron.db import db_base_plugin_v2 @@ -26,7 +28,7 @@ from neutron.tests.unit.db import test_db_base_plugin_v2 class AZExtensionManager(object): def get_resources(self): - agent.Agent().update_attributes_map(az_ext.EXTENDED_ATTRIBUTES_2_0) + agent.Agent().update_attributes_map(az_def.RESOURCE_ATTRIBUTE_MAP) return (az_ext.Availability_zone.get_resources() + agent.Agent.get_resources()) @@ -94,7 +96,7 @@ class TestAZAgentCase(AZTestCommon): ['nova1', 'nova2']) self.plugin.validate_availability_zones(ctx, 'router', ['nova2', 'nova3']) - self.assertRaises(az_ext.AvailabilityZoneNotFound, + self.assertRaises(az_exc.AvailabilityZoneNotFound, self.plugin.validate_availability_zones, ctx, 'router', ['nova1']) diff --git a/neutron/tests/unit/plugins/ml2/test_plugin.py b/neutron/tests/unit/plugins/ml2/test_plugin.py index 95bed3ce2bb..6de80c185f8 100644 --- a/neutron/tests/unit/plugins/ml2/test_plugin.py +++ b/neutron/tests/unit/plugins/ml2/test_plugin.py @@ -17,10 +17,7 @@ import functools import fixtures import mock -from oslo_config import cfg -import testtools -import webob - +from neutron_lib.api.definitions import availability_zone as az_def from neutron_lib.api.definitions import portbindings from neutron_lib.api.definitions import provider_net as pnet from neutron_lib.callbacks import events @@ -33,8 +30,11 @@ from neutron_lib import exceptions as exc from neutron_lib.plugins import constants as plugin_constants from neutron_lib.plugins import directory from neutron_lib.plugins.ml2 import api as driver_api +from oslo_config import cfg from oslo_db import exception as db_exc from oslo_utils import uuidutils +import testtools +import webob from neutron._i18n import _ from neutron.common import utils @@ -43,7 +43,6 @@ from neutron.db import api as db_api from neutron.db import models_v2 from neutron.db import provisioning_blocks from neutron.db import segments_db -from neutron.extensions import availability_zone as az_ext from neutron.extensions import external_net from neutron.extensions import multiprovidernet as mpnet from neutron.objects import base as base_obj @@ -480,7 +479,7 @@ class TestMl2NetworksWithAvailabilityZone(TestMl2NetworksV2): def test_create_network_availability_zone(self): az_hints = ['az1', 'az2'] data = {'network': {'name': 'net1', - az_ext.AZ_HINTS: az_hints, + az_def.AZ_HINTS: az_hints, 'tenant_id': 'tenant_one'}} with mock.patch.object(agents_db.AgentAvailabilityZoneMixin, 'validate_availability_zones'): @@ -488,7 +487,7 @@ class TestMl2NetworksWithAvailabilityZone(TestMl2NetworksV2): res = network_req.get_response(self.api) self.assertEqual(201, res.status_int) network = self.deserialize(self.fmt, res)['network'] - self.assertEqual(az_hints, network[az_ext.AZ_HINTS]) + self.assertEqual(az_hints, network[az_def.AZ_HINTS]) class TestMl2SubnetsV2(test_plugin.TestSubnetsV2,