neutron/neutron/plugins/nec/extensions/packetfilter.py

200 lines
7.5 KiB
Python

# 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 import quota
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.CountableResource(RESOURCE,
quota._count_resource,
'quota_%s' % RESOURCE)
quota.QUOTAS.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 {}