# Copyright 2012-2013 NEC Corporation. # 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. from oslo_config import cfg from neutron.api import extensions from neutron.api.v2 import attributes from neutron.api.v2 import base from neutron.common import constants from neutron.common import exceptions from neutron import manager from neutron.quota import resource as quota_resource from neutron.quota import resource_registry quota_packet_filter_opts = [ cfg.IntOpt('quota_packet_filter', default=100, help=_("Number of packet_filters allowed per tenant, " "-1 for unlimited")) ] cfg.CONF.register_opts(quota_packet_filter_opts, 'QUOTAS') class PacketFilterNotFound(exceptions.NotFound): message = _("PacketFilter %(id)s could not be found") class PacketFilterIpVersionNonSupported(exceptions.BadRequest): message = _("IP version %(version)s is not supported for %(field)s " "(%(value)s is specified)") class PacketFilterInvalidPriority(exceptions.BadRequest): message = _("Packet Filter priority should be %(min)s-%(max)s (included)") class PacketFilterUpdateNotSupported(exceptions.BadRequest): message = _("%(field)s field cannot be updated") class PacketFilterDuplicatedPriority(exceptions.BadRequest): message = _("The backend does not support duplicated priority. " "Priority %(priority)s is in use") class PacketFilterEtherTypeProtocolMismatch(exceptions.Conflict): message = _("Ether Type '%(eth_type)s' conflicts with protocol " "'%(protocol)s'. Update or clear protocol before " "changing ether type.") def convert_to_int_dec_and_hex(data): try: return int(data, 0) except (ValueError, TypeError): pass try: return int(data) except (ValueError, TypeError): msg = _("'%s' is not a integer") % data raise exceptions.InvalidInput(error_message=msg) def convert_to_int_or_none(data): if data is None: return return convert_to_int_dec_and_hex(data) PROTO_NAME_ARP = 'arp' SUPPORTED_PROTOCOLS = [constants.PROTO_NAME_ICMP, constants.PROTO_NAME_TCP, constants.PROTO_NAME_UDP, PROTO_NAME_ARP] ALLOW_ACTIONS = ['allow', 'accept'] DROP_ACTIONS = ['drop', 'deny'] SUPPORTED_ACTIONS = ALLOW_ACTIONS + DROP_ACTIONS ALIAS = 'packet-filter' RESOURCE = 'packet_filter' COLLECTION = 'packet_filters' PACKET_FILTER_ACTION_REGEX = '(?i)^(%s)$' % '|'.join(SUPPORTED_ACTIONS) PACKET_FILTER_PROTOCOL_REGEX = ('(?i)^(%s|0x[0-9a-fA-F]+|[0-9]+|)$' % '|'.join(SUPPORTED_PROTOCOLS)) PACKET_FILTER_ATTR_PARAMS = { 'id': {'allow_post': False, 'allow_put': False, 'validate': {'type:uuid': None}, 'is_visible': True}, 'name': {'allow_post': True, 'allow_put': True, 'default': '', 'validate': {'type:string': attributes.NAME_MAX_LEN}, 'is_visible': True}, 'tenant_id': {'allow_post': True, 'allow_put': False, 'validate': {'type:string': attributes.TENANT_ID_MAX_LEN}, 'required_by_policy': True, 'is_visible': True}, 'network_id': {'allow_post': True, 'allow_put': False, 'validate': {'type:uuid': None}, 'is_visible': True}, 'admin_state_up': {'allow_post': True, 'allow_put': True, 'default': True, 'convert_to': attributes.convert_to_boolean, 'is_visible': True}, 'status': {'allow_post': False, 'allow_put': False, 'is_visible': True}, 'action': {'allow_post': True, 'allow_put': True, 'validate': {'type:regex': PACKET_FILTER_ACTION_REGEX}, 'is_visible': True}, 'priority': {'allow_post': True, 'allow_put': True, 'convert_to': convert_to_int_dec_and_hex, 'is_visible': True}, 'in_port': {'allow_post': True, 'allow_put': False, 'default': attributes.ATTR_NOT_SPECIFIED, 'validate': {'type:uuid': None}, 'is_visible': True}, 'src_mac': {'allow_post': True, 'allow_put': True, 'default': attributes.ATTR_NOT_SPECIFIED, 'validate': {'type:mac_address_or_none': None}, 'is_visible': True}, 'dst_mac': {'allow_post': True, 'allow_put': True, 'default': attributes.ATTR_NOT_SPECIFIED, 'validate': {'type:mac_address_or_none': None}, 'is_visible': True}, 'eth_type': {'allow_post': True, 'allow_put': True, 'default': attributes.ATTR_NOT_SPECIFIED, 'convert_to': convert_to_int_or_none, 'is_visible': True}, 'src_cidr': {'allow_post': True, 'allow_put': True, 'default': attributes.ATTR_NOT_SPECIFIED, 'validate': {'type:subnet_or_none': None}, 'is_visible': True}, 'dst_cidr': {'allow_post': True, 'allow_put': True, 'default': attributes.ATTR_NOT_SPECIFIED, 'validate': {'type:subnet_or_none': None}, 'is_visible': True}, 'protocol': {'allow_post': True, 'allow_put': True, 'default': attributes.ATTR_NOT_SPECIFIED, 'validate': {'type:regex_or_none': PACKET_FILTER_PROTOCOL_REGEX}, 'is_visible': True}, 'src_port': {'allow_post': True, 'allow_put': True, 'default': attributes.ATTR_NOT_SPECIFIED, 'convert_to': convert_to_int_or_none, 'is_visible': True}, 'dst_port': {'allow_post': True, 'allow_put': True, 'default': attributes.ATTR_NOT_SPECIFIED, 'convert_to': convert_to_int_or_none, 'is_visible': True}, } PACKET_FILTER_ATTR_MAP = {COLLECTION: PACKET_FILTER_ATTR_PARAMS} class Packetfilter(extensions.ExtensionDescriptor): @classmethod def get_name(cls): return ALIAS @classmethod def get_alias(cls): return ALIAS @classmethod def get_description(cls): return "PacketFilters on OFC" @classmethod def get_updated(cls): return "2013-07-16T00:00:00+09:00" @classmethod def get_resources(cls): qresource = quota_resource.CountableResource( RESOURCE, quota_resource._count_resource, 'quota_%s' % RESOURCE) resource_registry.register_resource(qresource) resource = base.create_resource(COLLECTION, RESOURCE, manager.NeutronManager.get_plugin(), PACKET_FILTER_ATTR_PARAMS) pf_ext = extensions.ResourceExtension( COLLECTION, resource, attr_map=PACKET_FILTER_ATTR_PARAMS) return [pf_ext] def get_extended_resources(self, version): if version == "2.0": return PACKET_FILTER_ATTR_MAP else: return {}