class PortInfoNotFound(qexc.NotFound):
message = _("PortInfo %(id)s could not be found")
-
-
-class PacketFilterNotFound(qexc.NotFound):
- message = _("PacketFilter %(id)s could not be found")
port_no = sa.Column(sa.Integer, nullable=False)
vlan_id = sa.Column(sa.Integer, nullable=False)
mac = sa.Column(sa.String(32), nullable=False)
-
-
-class PacketFilter(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
- """Represents a packet filter."""
- name = sa.Column(sa.String(255))
- network_id = sa.Column(sa.String(36),
- sa.ForeignKey('networks.id', ondelete="CASCADE"),
- nullable=False)
- priority = sa.Column(sa.Integer, nullable=False)
- action = sa.Column(sa.String(16), nullable=False)
- # condition
- in_port = sa.Column(sa.String(36), nullable=False)
- src_mac = sa.Column(sa.String(32), nullable=False)
- dst_mac = sa.Column(sa.String(32), nullable=False)
- eth_type = sa.Column(sa.Integer, nullable=False)
- src_cidr = sa.Column(sa.String(64), nullable=False)
- dst_cidr = sa.Column(sa.String(64), nullable=False)
- protocol = sa.Column(sa.String(16), nullable=False)
- src_port = sa.Column(sa.Integer, nullable=False)
- dst_port = sa.Column(sa.Integer, nullable=False)
- # status
- admin_state_up = sa.Column(sa.Boolean(), nullable=False)
- status = sa.Column(sa.String(16), nullable=False)
+++ /dev/null
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2012 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.
-# @author: Ryota MIBU
-
-from sqlalchemy.orm import exc
-
-from neutron.api.v2 import attributes
-from neutron.db import db_base_plugin_v2
-from neutron.openstack.common import log as logging
-from neutron.openstack.common import uuidutils
-from neutron.plugins.nec.common import exceptions as q_exc
-from neutron.plugins.nec.db import models as nmodels
-
-
-LOG = logging.getLogger(__name__)
-
-
-class NECPluginV2Base(db_base_plugin_v2.NeutronDbPluginV2):
-
- """Base class of plugins that handle packet filters."""
-
- def _make_packet_filter_dict(self, packet_filter, fields=None):
- res = {'id': packet_filter['id'],
- 'name': packet_filter['name'],
- 'tenant_id': packet_filter['tenant_id'],
- 'network_id': packet_filter['network_id'],
- 'action': packet_filter['action'],
- 'priority': packet_filter['priority'],
- 'in_port': packet_filter['in_port'],
- 'src_mac': packet_filter['src_mac'],
- 'dst_mac': packet_filter['dst_mac'],
- 'eth_type': packet_filter['eth_type'],
- 'src_cidr': packet_filter['src_cidr'],
- 'dst_cidr': packet_filter['dst_cidr'],
- 'protocol': packet_filter['protocol'],
- 'src_port': packet_filter['src_port'],
- 'dst_port': packet_filter['dst_port'],
- 'admin_state_up': packet_filter['admin_state_up'],
- 'status': packet_filter['status']}
- return self._fields(res, fields)
-
- def _get_packet_filter(self, context, id):
- try:
- packet_filter = self._get_by_id(context, nmodels.PacketFilter, id)
- except exc.NoResultFound:
- raise q_exc.PacketFilterNotFound(id=id)
- return packet_filter
-
- def get_packet_filter(self, context, id, fields=None):
- packet_filter = self._get_packet_filter(context, id)
- return self._make_packet_filter_dict(packet_filter, fields)
-
- def get_packet_filters(self, context, filters=None, fields=None):
- return self._get_collection(context,
- nmodels.PacketFilter,
- self._make_packet_filter_dict,
- filters=filters,
- fields=fields)
-
- def create_packet_filter(self, context, packet_filter):
- pf = packet_filter['packet_filter']
- tenant_id = self._get_tenant_id_for_create(context, pf)
-
- # validate network ownership
- super(NECPluginV2Base, self).get_network(context, pf['network_id'])
- if pf.get('in_port') is not attributes.ATTR_NOT_SPECIFIED:
- # validate port ownership
- super(NECPluginV2Base, self).get_port(context, pf['in_port'])
-
- params = {'tenant_id': tenant_id,
- 'id': pf.get('id') or uuidutils.generate_uuid(),
- 'name': pf['name'],
- 'network_id': pf['network_id'],
- 'priority': pf['priority'],
- 'action': pf['action'],
- 'admin_state_up': pf.get('admin_state_up', True),
- 'status': "ACTIVE"}
- conditions = {'in_port': '',
- 'src_mac': '',
- 'dst_mac': '',
- 'eth_type': 0,
- 'src_cidr': '',
- 'dst_cidr': '',
- 'src_port': 0,
- 'dst_port': 0,
- 'protocol': ''}
- for key, default in conditions.items():
- if pf.get(key) is attributes.ATTR_NOT_SPECIFIED:
- params.update({key: default})
- else:
- params.update({key: pf.get(key)})
-
- with context.session.begin(subtransactions=True):
- pf_entry = nmodels.PacketFilter(**params)
- context.session.add(pf_entry)
- return self._make_packet_filter_dict(pf_entry)
-
- def update_packet_filter(self, context, id, packet_filter):
- pf = packet_filter['packet_filter']
- with context.session.begin(subtransactions=True):
- pf_entry = self._get_packet_filter(context, id)
- pf_entry.update(pf)
- return self._make_packet_filter_dict(pf_entry)
-
- def delete_packet_filter(self, context, id):
- with context.session.begin(subtransactions=True):
- packet_filter = self._get_packet_filter(context, id)
- context.session.delete(packet_filter)
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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.
+# @author: Ryota MIBU
+
+import sqlalchemy as sa
+from sqlalchemy.orm import exc as sa_exc
+
+from neutron.api.v2 import attributes
+from neutron.common import exceptions
+from neutron.db import model_base
+from neutron.db import models_v2
+from neutron.openstack.common import uuidutils
+
+
+PF_STATUS_ACTIVE = 'ACTIVE'
+PF_STATUS_DOWN = 'DOWN'
+PF_STATUS_ERROR = 'ERROR'
+
+
+class PacketFilterNotFound(exceptions.NotFound):
+ message = _("PacketFilter %(id)s could not be found")
+
+
+class PacketFilter(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
+ """Represents a packet filter."""
+ name = sa.Column(sa.String(255))
+ network_id = sa.Column(sa.String(36),
+ sa.ForeignKey('networks.id', ondelete="CASCADE"),
+ nullable=False)
+ priority = sa.Column(sa.Integer, nullable=False)
+ action = sa.Column(sa.String(16), nullable=False)
+ # condition
+ in_port = sa.Column(sa.String(36), nullable=False)
+ src_mac = sa.Column(sa.String(32), nullable=False)
+ dst_mac = sa.Column(sa.String(32), nullable=False)
+ eth_type = sa.Column(sa.Integer, nullable=False)
+ src_cidr = sa.Column(sa.String(64), nullable=False)
+ dst_cidr = sa.Column(sa.String(64), nullable=False)
+ protocol = sa.Column(sa.String(16), nullable=False)
+ src_port = sa.Column(sa.Integer, nullable=False)
+ dst_port = sa.Column(sa.Integer, nullable=False)
+ # status
+ admin_state_up = sa.Column(sa.Boolean(), nullable=False)
+ status = sa.Column(sa.String(16), nullable=False)
+
+
+class PacketFilterDbMixin(object):
+
+ def _make_packet_filter_dict(self, pf_entry, fields=None):
+ res = {'id': pf_entry['id'],
+ 'name': pf_entry['name'],
+ 'tenant_id': pf_entry['tenant_id'],
+ 'network_id': pf_entry['network_id'],
+ 'action': pf_entry['action'],
+ 'priority': pf_entry['priority'],
+ 'in_port': pf_entry['in_port'],
+ 'src_mac': pf_entry['src_mac'],
+ 'dst_mac': pf_entry['dst_mac'],
+ 'eth_type': pf_entry['eth_type'],
+ 'src_cidr': pf_entry['src_cidr'],
+ 'dst_cidr': pf_entry['dst_cidr'],
+ 'protocol': pf_entry['protocol'],
+ 'src_port': pf_entry['src_port'],
+ 'dst_port': pf_entry['dst_port'],
+ 'admin_state_up': pf_entry['admin_state_up'],
+ 'status': pf_entry['status']}
+ return self._fields(res, fields)
+
+ def _get_packet_filter(self, context, id):
+ try:
+ pf_entry = self._get_by_id(context, PacketFilter, id)
+ except sa_exc.NoResultFound:
+ raise PacketFilterNotFound(id=id)
+ return pf_entry
+
+ def get_packet_filter(self, context, id, fields=None):
+ pf_entry = self._get_packet_filter(context, id)
+ return self._make_packet_filter_dict(pf_entry, fields)
+
+ def get_packet_filters(self, context, filters=None, fields=None):
+ return self._get_collection(context,
+ PacketFilter,
+ self._make_packet_filter_dict,
+ filters=filters,
+ fields=fields)
+
+ def create_packet_filter(self, context, packet_filter):
+ pf_dict = packet_filter['packet_filter']
+ tenant_id = self._get_tenant_id_for_create(context, pf_dict)
+
+ if pf_dict['in_port'] == attributes.ATTR_NOT_SPECIFIED:
+ # validate network ownership
+ self.get_network(context, pf_dict['network_id'])
+ else:
+ # validate port ownership
+ self.get_port(context, pf_dict['in_port'])
+
+ params = {'tenant_id': tenant_id,
+ 'id': pf_dict.get('id') or uuidutils.generate_uuid(),
+ 'name': pf_dict['name'],
+ 'network_id': pf_dict['network_id'],
+ 'priority': pf_dict['priority'],
+ 'action': pf_dict['action'],
+ 'admin_state_up': pf_dict.get('admin_state_up', True),
+ 'status': PF_STATUS_DOWN,
+ 'in_port': pf_dict['in_port'],
+ 'src_mac': pf_dict['src_mac'],
+ 'dst_mac': pf_dict['dst_mac'],
+ 'eth_type': pf_dict['eth_type'],
+ 'src_cidr': pf_dict['src_cidr'],
+ 'dst_cidr': pf_dict['dst_cidr'],
+ 'src_port': pf_dict['src_port'],
+ 'dst_port': pf_dict['dst_port'],
+ 'protocol': pf_dict['protocol']}
+ for key, default in params.items():
+ if params[key] == attributes.ATTR_NOT_SPECIFIED:
+ params.update({key: ''})
+
+ with context.session.begin(subtransactions=True):
+ pf_entry = PacketFilter(**params)
+ context.session.add(pf_entry)
+
+ return self._make_packet_filter_dict(pf_entry)
+
+ def update_packet_filter(self, context, id, packet_filter):
+ pf = packet_filter['packet_filter']
+ with context.session.begin(subtransactions=True):
+ pf_entry = self._get_packet_filter(context, id)
+ pf_entry.update(pf)
+ return self._make_packet_filter_dict(pf_entry)
+
+ def delete_packet_filter(self, context, id):
+ with context.session.begin(subtransactions=True):
+ pf_entry = self._get_packet_filter(context, id)
+ context.session.delete(pf_entry)
# vim: tabstop=4 shiftwidth=4 softtabstop=4
-# Copyright 2012 NEC Corporation.
+# Copyright 2012-2013 NEC Corporation.
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
from neutron.api import extensions
from neutron.api.v2 import attributes
from neutron.api.v2 import base
+from neutron.common import exceptions
from neutron.manager import NeutronManager
from neutron import quota
help=_("Number of packet_filters allowed per tenant, "
"-1 for unlimited"))
]
-# Register the configuration options
cfg.CONF.register_opts(quota_packet_filter_opts, 'QUOTAS')
-PACKET_FILTER_ACTION_REGEX = "(?i)^(allow|accept|drop|deny)$"
-PACKET_FILTER_NUMBER_REGEX = "(?i)^(0x[0-9a-fA-F]+|[0-9]+)$"
-PACKET_FILTER_PROTOCOL_REGEX = "(?i)^(icmp|tcp|udp|arp|0x[0-9a-fA-F]+|[0-9]+)$"
-PACKET_FILTER_ATTR_MAP = {
+def convert_to_int(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)
+
+
+ALIAS = 'packet-filter'
+RESOURCE = 'packet_filter'
+COLLECTION = 'packet_filters'
+PACKET_FILTER_ACTION_REGEX = '(?i)^(allow|accept|drop|deny)$'
+PACKET_FILTER_PROTOCOL_REGEX = (
+ '(?i)^(icmp|tcp|udp|arp|0x[0-9a-fA-F]+|[0-9]+|)$')
+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': None},
'is_visible': True},
'tenant_id': {'allow_post': True, 'allow_put': False,
+ 'validate': {'type:string': None},
'required_by_policy': True,
'is_visible': True},
'network_id': {'allow_post': True, 'allow_put': False,
'validate': {'type:regex': PACKET_FILTER_ACTION_REGEX},
'is_visible': True},
'priority': {'allow_post': True, 'allow_put': True,
- 'validate': {'type:regex': PACKET_FILTER_NUMBER_REGEX},
+ 'convert_to': convert_to_int,
'is_visible': True},
- 'in_port': {'allow_post': True, 'allow_put': True,
+ 'in_port': {'allow_post': True, 'allow_put': False,
'default': attributes.ATTR_NOT_SPECIFIED,
'validate': {'type:uuid': None},
'is_visible': True},
'is_visible': True},
'eth_type': {'allow_post': True, 'allow_put': True,
'default': attributes.ATTR_NOT_SPECIFIED,
- 'validate': {'type:regex': PACKET_FILTER_NUMBER_REGEX},
+ 'convert_to': convert_to_int,
'is_visible': True},
'src_cidr': {'allow_post': True, 'allow_put': True,
'default': attributes.ATTR_NOT_SPECIFIED,
'is_visible': True},
'src_port': {'allow_post': True, 'allow_put': True,
'default': attributes.ATTR_NOT_SPECIFIED,
- 'validate': {'type:regex': PACKET_FILTER_NUMBER_REGEX},
+ 'convert_to': convert_to_int,
'is_visible': True},
'dst_port': {'allow_post': True, 'allow_put': True,
'default': attributes.ATTR_NOT_SPECIFIED,
- 'validate': {'type:regex': PACKET_FILTER_NUMBER_REGEX},
+ 'convert_to': convert_to_int,
'is_visible': True},
}
+PACKET_FILTER_ATTR_MAP = {COLLECTION: PACKET_FILTER_ATTR_PARAMS}
class Packetfilter(extensions.ExtensionDescriptor):
- def get_name(self):
- return "PacketFilters"
+ @classmethod
+ def get_name(cls):
+ return ALIAS
- def get_alias(self):
- return "PacketFilters"
+ @classmethod
+ def get_alias(cls):
+ return ALIAS
- def get_description(self):
- return "PacketFilters"
+ @classmethod
+ def get_description(cls):
+ return "PacketFilters on OFC"
- def get_namespace(self):
+ @classmethod
+ def get_namespace(cls):
return "http://www.nec.co.jp/api/ext/packet_filter/v2.0"
- def get_updated(self):
- return "2012-07-24T00:00:00+09:00"
+ @classmethod
+ def get_updated(cls):
+ return "2013-07-16T00:00:00+09:00"
- def get_resources(self):
- resource = base.create_resource('packet_filters', 'packet_filter',
- NeutronManager.get_plugin(),
- PACKET_FILTER_ATTR_MAP)
- qresource = quota.CountableResource('packet_filter',
+ @classmethod
+ def get_resources(cls):
+ qresource = quota.CountableResource(RESOURCE,
quota._count_resource,
- 'quota_packet_filter')
+ 'quota_%s' % RESOURCE)
quota.QUOTAS.register_resource(qresource)
- return [extensions.ResourceExtension('packet_filters',
- resource,
- attr_map=PACKET_FILTER_ATTR_MAP)]
+
+ resource = base.create_resource(COLLECTION, RESOURCE,
+ NeutronManager.get_plugin(),
+ PACKET_FILTER_ATTR_PARAMS)
+ pf_ext = extensions.ResourceExtension(
+ COLLECTION, resource, attr_map=PACKET_FILTER_ATTR_PARAMS)
+ return [pf_ext]
+
+ def update_attributes_map(self, attributes):
+ super(Packetfilter, self).update_attributes_map(
+ attributes, extension_attrs_map=PACKET_FILTER_ATTR_MAP)
+
+ def get_extended_resources(self, version):
+ if version == "2.0":
+ return PACKET_FILTER_ATTR_MAP
+ else:
+ return {}
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
-# Copyright 2012 NEC Corporation. All rights reserved.
+# 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
from neutron.plugins.nec.common import config
from neutron.plugins.nec.common import exceptions as nexc
from neutron.plugins.nec.db import api as ndb
-from neutron.plugins.nec.db import nec_plugin_base
+from neutron.plugins.nec.db import packetfilter as pf_db
from neutron.plugins.nec import ofc_manager
+from neutron.plugins.nec import packet_filter
LOG = logging.getLogger(__name__)
ERROR = "ERROR"
-class NECPluginV2(nec_plugin_base.NECPluginV2Base,
+class NECPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
extraroute_db.ExtraRoute_db_mixin,
l3_gwmode_db.L3_NAT_db_mixin,
sg_db_rpc.SecurityGroupServerRpcMixin,
agentschedulers_db.L3AgentSchedulerDbMixin,
- agentschedulers_db.DhcpAgentSchedulerDbMixin):
+ agentschedulers_db.DhcpAgentSchedulerDbMixin,
+ packet_filter.PacketFilterMixin):
"""NECPluginV2 controls an OpenFlow Controller.
The Neutron NECPluginV2 maps L2 logical networks to L2 virtualized networks
"binding", "security-group",
"extraroute", "agent",
"l3_agent_scheduler",
- "dhcp_agent_scheduler"]
+ "dhcp_agent_scheduler",
+ "packet-filter"]
@property
def supported_extension_aliases(self):
if not hasattr(self, '_aliases'):
aliases = self._supported_extension_aliases[:]
sg_rpc.disable_security_group_extension_if_noop_driver(aliases)
+ self.remove_packet_filter_extension_if_disabled(aliases)
self._aliases = aliases
return self._aliases
ndb.initialize()
self.ofc = ofc_manager.OFCManager()
- self.packet_filter_enabled = (config.OFC.enable_packet_filter and
- self.ofc.driver.filter_supported())
- if self.packet_filter_enabled:
- self.supported_extension_aliases.append("PacketFilters")
-
# Set the plugin default extension path
# if no api_extensions_path is specified.
if not config.CONF.api_extensions_path:
if self.packet_filter_enabled:
if port_status is OperationalStatus.ACTIVE:
filters = dict(in_port=[port['id']],
- status=[OperationalStatus.DOWN],
+ status=[pf_db.PF_STATUS_DOWN],
admin_state_up=[True])
- pfs = (super(NECPluginV2, self).
- get_packet_filters(context, filters=filters))
+ pfs = self.get_packet_filters(context, filters=filters)
for pf in pfs:
- self._activate_packet_filter_if_ready(context, pf,
- network=network,
- in_port=port)
+ self.activate_packet_filter_if_ready(context, pf)
if port_status in [OperationalStatus.ACTIVE]:
if self.ofc.exists_ofc_port(context, port['id']):
# deactivate packet_filters after the port has deleted from OFC.
if self.packet_filter_enabled:
filters = dict(in_port=[port['id']],
- status=[OperationalStatus.ACTIVE])
- pfs = super(NECPluginV2, self).get_packet_filters(context,
- filters=filters)
+ status=[pf_db.PF_STATUS_ACTIVE])
+ pfs = self.get_packet_filters(context, filters=filters)
for pf in pfs:
- self._deactivate_packet_filter(context, pf)
+ self.deactivate_packet_filter(context, pf)
# Quantm Plugin Basic methods
if changed and not new_net['admin_state_up']:
self._update_resource_status(context, "network", id,
OperationalStatus.DOWN)
- # disable all active ports and packet_filters of the network
+ # disable all active ports of the network
filters = dict(network_id=[id], status=[OperationalStatus.ACTIVE])
ports = super(NECPluginV2, self).get_ports(context,
filters=filters)
for port in ports:
self.deactivate_port(context, port)
- if self.packet_filter_enabled:
- pfs = (super(NECPluginV2, self).
- get_packet_filters(context, filters=filters))
- for pf in pfs:
- self._deactivate_packet_filter(context, pf)
elif changed and new_net['admin_state_up']:
self._update_resource_status(context, "network", id,
OperationalStatus.ACTIVE)
- # enable ports and packet_filters of the network
+ # enable ports of the network
filters = dict(network_id=[id], status=[OperationalStatus.DOWN],
admin_state_up=[True])
ports = super(NECPluginV2, self).get_ports(context,
filters=filters)
for port in ports:
self.activate_port_if_ready(context, port, new_net)
- if self.packet_filter_enabled:
- pfs = (super(NECPluginV2, self).
- get_packet_filters(context, filters=filters))
- for pf in pfs:
- self._activate_packet_filter_if_ready(context, pf, new_net)
return new_net
' from OFC: %s'), port)
self.deactivate_port(context, port)
- # get packet_filters associated with the network
+ # delete all packet_filters of the network
if self.packet_filter_enabled:
filters = dict(network_id=[id])
- pfs = (super(NECPluginV2, self).
- get_packet_filters(context, filters=filters))
+ pfs = self.get_packet_filters(context, filters=filters)
+ for pf in pfs:
+ self.delete_packet_filter(context, pf['id'])
super(NECPluginV2, self).delete_network(context, id)
try:
# resources, so this plugin just warns.
LOG.warn(reason)
- # delete all packet_filters of the network
- if self.packet_filter_enabled:
- for pf in pfs:
- self.delete_packet_filter(context, pf['id'])
-
# delete unnessary ofc_tenant
filters = dict(tenant_id=[tenant_id])
nets = super(NECPluginV2, self).get_networks(context, filters=filters)
# delete all packet_filters of the port
if self.packet_filter_enabled:
filters = dict(port_id=[id])
- pfs = (super(NECPluginV2, self).
- get_packet_filters(context, filters=filters))
+ pfs = self.get_packet_filters(context, filters=filters)
for packet_filter in pfs:
self.delete_packet_filter(context, packet_filter['id'])
self._extend_port_dict_binding(context, port)
return [self._fields(port, fields) for port in ports]
- # For PacketFilter Extension
-
- def _activate_packet_filter_if_ready(self, context, packet_filter,
- network=None, in_port=None):
- """Activate packet_filter by creating filter on OFC if ready.
-
- Conditions to create packet_filter on OFC are:
- * packet_filter admin_state is UP
- * network admin_state is UP
- * (if 'in_port' is specified) portinfo is available
- """
- net_id = packet_filter['network_id']
- if not network:
- network = super(NECPluginV2, self).get_network(context, net_id)
- in_port_id = packet_filter.get("in_port")
- if in_port_id and not in_port:
- in_port = super(NECPluginV2, self).get_port(context, in_port_id)
-
- pf_status = OperationalStatus.ACTIVE
- if not packet_filter['admin_state_up']:
- LOG.debug(_("_activate_packet_filter_if_ready(): skip, "
- "packet_filter.admin_state_up is False."))
- pf_status = OperationalStatus.DOWN
- elif not network['admin_state_up']:
- LOG.debug(_("_activate_packet_filter_if_ready(): skip, "
- "network.admin_state_up is False."))
- pf_status = OperationalStatus.DOWN
- elif in_port_id and in_port_id is in_port.get('id'):
- LOG.debug(_("_activate_packet_filter_if_ready(): skip, "
- "invalid in_port_id."))
- pf_status = OperationalStatus.DOWN
- elif in_port_id and not ndb.get_portinfo(context.session, in_port_id):
- LOG.debug(_("_activate_packet_filter_if_ready(): skip, "
- "no portinfo for in_port."))
- pf_status = OperationalStatus.DOWN
-
- if pf_status in [OperationalStatus.ACTIVE]:
- if self.ofc.exists_ofc_packet_filter(context, packet_filter['id']):
- LOG.debug(_("_activate_packet_filter_if_ready(): skip, "
- "ofc_packet_filter already exists."))
- else:
- try:
- (self.ofc.
- create_ofc_packet_filter(context,
- packet_filter['id'],
- packet_filter))
- except (nexc.OFCException, nexc.OFCConsistencyBroken) as exc:
- reason = _("create_ofc_packet_filter() failed due to "
- "%s") % exc
- LOG.error(reason)
- pf_status = OperationalStatus.ERROR
-
- if pf_status is not packet_filter['status']:
- self._update_resource_status(context, "packet_filter",
- packet_filter['id'], pf_status)
-
- def _deactivate_packet_filter(self, context, packet_filter):
- """Deactivate packet_filter by deleting filter from OFC if exixts."""
- pf_status = OperationalStatus.DOWN
- if not self.ofc.exists_ofc_packet_filter(context, packet_filter['id']):
- LOG.debug(_("_deactivate_packet_filter(): skip, "
- "ofc_packet_filter does not exist."))
- else:
- try:
- self.ofc.delete_ofc_packet_filter(context, packet_filter['id'])
- except (nexc.OFCException, nexc.OFCConsistencyBroken) as exc:
- reason = _("delete_ofc_packet_filter() failed due to "
- "%s") % exc
- LOG.error(reason)
- pf_status = OperationalStatus.ERROR
-
- if pf_status is not packet_filter['status']:
- self._update_resource_status(context, "packet_filter",
- packet_filter['id'], pf_status)
-
- def create_packet_filter(self, context, packet_filter):
- """Create a new packet_filter entry on DB, then try to activate it."""
- LOG.debug(_("NECPluginV2.create_packet_filter() called, "
- "packet_filter=%s ."), packet_filter)
- new_pf = super(NECPluginV2, self).create_packet_filter(context,
- packet_filter)
- self._update_resource_status(context, "packet_filter", new_pf['id'],
- OperationalStatus.BUILD)
-
- self._activate_packet_filter_if_ready(context, new_pf)
-
- return new_pf
-
- def update_packet_filter(self, context, id, packet_filter):
- """Update packet_filter entry on DB, and recreate it if changed.
-
- If any rule of the packet_filter was changed, recreate it on OFC.
- """
- LOG.debug(_("NECPluginV2.update_packet_filter() called, "
- "id=%(id)s packet_filter=%(packet_filter)s ."),
- {'id': id, 'packet_filter': packet_filter})
- with context.session.begin(subtransactions=True):
- old_pf = super(NECPluginV2, self).get_packet_filter(context, id)
- new_pf = super(NECPluginV2, self).update_packet_filter(
- context, id, packet_filter)
-
- changed = False
- exclude_items = ["id", "name", "tenant_id", "network_id", "status"]
- for key in new_pf['packet_filter'].keys():
- if key not in exclude_items:
- if old_pf[key] is not new_pf[key]:
- changed = True
- break
-
- if changed:
- self._deactivate_packet_filter(context, old_pf)
- self._activate_packet_filter_if_ready(context, new_pf)
-
- return new_pf
-
- def delete_packet_filter(self, context, id):
- """Deactivate and delete packet_filter."""
- LOG.debug(_("NECPluginV2.delete_packet_filter() called, id=%s ."), id)
- pf = super(NECPluginV2, self).get_packet_filter(context, id)
- self._deactivate_packet_filter(context, pf)
-
- super(NECPluginV2, self).delete_packet_filter(context, id)
-
class NECPluginV2AgentNotifierApi(proxy.RpcProxy,
sg_rpc.SecurityGroupAgentRpcApiMixin):
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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.
+# @author: Ryota MIBU
+
+from neutron.openstack.common import log as logging
+from neutron.plugins.nec.common import config
+from neutron.plugins.nec.common import exceptions as nexc
+from neutron.plugins.nec.db import api as ndb
+from neutron.plugins.nec.db import packetfilter as pf_db
+
+
+LOG = logging.getLogger(__name__)
+
+
+class PacketFilterMixin(pf_db.PacketFilterDbMixin):
+ """Mixin class to add packet filter to NECPluginV2."""
+
+ @property
+ def packet_filter_enabled(self):
+ if not hasattr(self, '_packet_filter_enabled'):
+ self._packet_filter_enabled = (
+ config.OFC.enable_packet_filter and
+ self.ofc.driver.filter_supported())
+ return self._packet_filter_enabled
+
+ def remove_packet_filter_extension_if_disabled(self, aliases):
+ if not self.packet_filter_enabled:
+ LOG.debug(_('Disabled packet-filter extension.'))
+ aliases.remove('packet-filter')
+
+ def create_packet_filter(self, context, packet_filter):
+ """Create a new packet_filter entry on DB, then try to activate it."""
+ LOG.debug(_("create_packet_filter() called, packet_filter=%s ."),
+ packet_filter)
+
+ pf = super(PacketFilterMixin, self).create_packet_filter(
+ context, packet_filter)
+
+ return self.activate_packet_filter_if_ready(context, pf)
+
+ def update_packet_filter(self, context, id, packet_filter):
+ """Update packet_filter entry on DB, and recreate it if changed.
+
+ If any rule of the packet_filter was changed, recreate it on OFC.
+ """
+ LOG.debug(_("update_packet_filter() called, "
+ "id=%(id)s packet_filter=%(packet_filter)s ."),
+ {'id': id, 'packet_filter': packet_filter})
+
+ # validate ownership
+ pf_old = self.get_packet_filter(context, id)
+
+ pf = super(PacketFilterMixin, self).update_packet_filter(
+ context, id, packet_filter)
+
+ def _packet_filter_changed(old_pf, new_pf):
+ for key in new_pf:
+ if key not in ('id', 'name', 'tenant_id', 'network_id',
+ 'in_port', 'status'):
+ if old_pf[key] != new_pf[key]:
+ return True
+ return False
+
+ if _packet_filter_changed(pf_old, pf):
+ pf = self.deactivate_packet_filter(context, pf)
+ pf = self.activate_packet_filter_if_ready(context, pf)
+
+ return pf
+
+ def delete_packet_filter(self, context, id):
+ """Deactivate and delete packet_filter."""
+ LOG.debug(_("delete_packet_filter() called, id=%s ."), id)
+
+ # validate ownership
+ pf = self.get_packet_filter(context, id)
+
+ pf = self.deactivate_packet_filter(context, pf)
+ if pf['status'] == pf_db.PF_STATUS_ERROR:
+ msg = _("failed to delete packet_filter id=%s which remains in "
+ "error status.") % id
+ LOG.error(msg)
+ raise nexc.OFCException(reason=msg)
+
+ super(PacketFilterMixin, self).delete_packet_filter(context, id)
+
+ def activate_packet_filter_if_ready(self, context, packet_filter):
+ """Activate packet_filter by creating filter on OFC if ready.
+
+ Conditions to create packet_filter on OFC are:
+ * packet_filter admin_state is UP
+ * (if 'in_port' is specified) portinfo is available
+ """
+ LOG.debug(_("activate_packet_filter_if_ready() called, "
+ "packet_filter=%s."), packet_filter)
+
+ pf_id = packet_filter['id']
+ in_port_id = packet_filter.get('in_port')
+ current = packet_filter['status']
+
+ pf_status = current
+ if not packet_filter['admin_state_up']:
+ LOG.debug(_("activate_packet_filter_if_ready(): skip pf_id=%s, "
+ "packet_filter.admin_state_up is False."), pf_id)
+ elif in_port_id and not ndb.get_portinfo(context.session, in_port_id):
+ LOG.debug(_("activate_packet_filter_if_ready(): skip "
+ "pf_id=%s, no portinfo for the in_port."), pf_id)
+ elif self.ofc.exists_ofc_packet_filter(context, packet_filter['id']):
+ LOG.debug(_("_activate_packet_filter_if_ready(): skip, "
+ "ofc_packet_filter already exists."))
+ else:
+ LOG.debug(_("activate_packet_filter_if_ready(): create "
+ "packet_filter id=%s on OFC."), pf_id)
+ try:
+ self.ofc.create_ofc_packet_filter(context, pf_id,
+ packet_filter)
+ pf_status = pf_db.PF_STATUS_ACTIVE
+ except (nexc.OFCException, nexc.OFCConsistencyBroken) as exc:
+ LOG.error(_("failed to create packet_filter id=%(id)s on "
+ "OFC: %(exc)s"), {'id': pf_id, 'exc': str(exc)})
+ pf_status = pf_db.PF_STATUS_ERROR
+
+ if pf_status != current:
+ self._update_resource_status(context, "packet_filter", pf_id,
+ pf_status)
+ packet_filter.update({'status': pf_status})
+
+ return packet_filter
+
+ def deactivate_packet_filter(self, context, packet_filter):
+ """Deactivate packet_filter by deleting filter from OFC if exixts."""
+ LOG.debug(_("deactivate_packet_filter_if_ready() called, "
+ "packet_filter=%s."), packet_filter)
+ pf_id = packet_filter['id']
+ current = packet_filter['status']
+
+ pf_status = current
+ if self.ofc.exists_ofc_packet_filter(context, pf_id):
+ LOG.debug(_("deactivate_packet_filter(): "
+ "deleting packet_filter id=%s from OFC."), pf_id)
+ try:
+ self.ofc.delete_ofc_packet_filter(context, pf_id)
+ pf_status = pf_db.PF_STATUS_DOWN
+ except (nexc.OFCException, nexc.OFCConsistencyBroken) as exc:
+ LOG.error(_("failed to delete packet_filter id=%(id)s from "
+ "OFC: %(exc)s"), {'id': pf_id, 'exc': str(exc)})
+ pf_status = pf_db.PF_STATUS_ERROR
+ else:
+ LOG.debug(_("deactivate_packet_filter(): skip, "
+ "Not found OFC Mapping for packet_filter id=%s."),
+ pf_id)
+
+ if pf_status != current:
+ self._update_resource_status(context, "packet_filter", pf_id,
+ pf_status)
+ packet_filter.update({'status': pf_status})
+
+ return packet_filter
from neutron.api.v2 import attributes
from neutron.common.test_lib import test_config
from neutron import context
+from neutron.plugins.nec.common import exceptions as nexc
from neutron.plugins.nec.extensions import packetfilter
+from neutron.tests.unit.nec import test_nec_plugin
from neutron.tests.unit import test_db_plugin as test_plugin
-PLUGIN_NAME = 'neutron.plugins.nec.nec_plugin.NECPluginV2'
-OFC_MANAGER = 'neutron.plugins.nec.nec_plugin.ofc_manager.OFCManager'
+NEC_PLUGIN_PF_INI = """
+[DEFAULT]
+api_extensions_path = neutron/plugins/nec/extensions
+[OFC]
+driver = neutron.tests.unit.nec.stub_ofc_driver.StubOFCDriver
+enable_packet_filter = True
+"""
class PacketfilterExtensionManager(packetfilter.Packetfilter):
- def get_resources(self):
+ @classmethod
+ def get_resources(cls):
# Add the resources to the global attribute map
# This is done here as the setup process won't
# initialize the main API router which extends
# the global attribute map
attributes.RESOURCE_ATTRIBUTE_MAP.update(
{'packet_filters': packetfilter.PACKET_FILTER_ATTR_MAP})
- return super(PacketfilterExtensionManager, self).get_resources()
+ return super(PacketfilterExtensionManager, cls).get_resources()
-class TestNecPluginPacketFilter(test_plugin.NeutronDbPluginV2TestCase):
+class TestNecPluginPacketFilter(test_nec_plugin.NecPluginV2TestCase):
+
+ _nec_ini = NEC_PLUGIN_PF_INI
def setUp(self):
- self.addCleanup(mock.patch.stopall)
- ofc_manager_cls = mock.patch(OFC_MANAGER).start()
- ofc_driver = ofc_manager_cls.return_value.driver
- ofc_driver.filter_supported.return_value = True
test_config['extension_manager'] = PacketfilterExtensionManager()
- super(TestNecPluginPacketFilter, self).setUp(PLUGIN_NAME)
+ super(TestNecPluginPacketFilter, self).setUp()
def _create_packet_filter(self, fmt, net_id, expected_res_status=None,
arg_list=None, **kwargs):
if do_delete:
self._delete('packet_filters', pf['packet_filter']['id'])
+ @contextlib.contextmanager
+ def packet_filter_on_port(self, port=None, fmt=None, do_delete=True,
+ set_portinfo=True, **kwargs):
+ with test_plugin.optional_ctx(port, self.port) as port_to_use:
+ net_id = port_to_use['port']['network_id']
+ port_id = port_to_use['port']['id']
+
+ if set_portinfo:
+ portinfo = {'id': port_id,
+ 'port_no': kwargs.get('port_no', 123)}
+ kw = {'added': [portinfo]}
+ if 'datapath_id' in kwargs:
+ kw['datapath_id'] = kwargs['datapath_id']
+ self.rpcapi_update_ports(**kw)
+
+ kwargs['in_port'] = port_id
+ pf = self._make_packet_filter(fmt or self.fmt, net_id, **kwargs)
+ self.assertEqual(port_id, pf['packet_filter']['in_port'])
+ try:
+ yield pf
+ finally:
+ if do_delete:
+ self._delete('packet_filters', pf['packet_filter']['id'])
+
+ def test_list_packet_filters(self):
+ self._list('packet_filters')
+
+ def test_create_pf_on_network_no_ofc_creation(self):
+ with self.packet_filter_on_network(admin_state_up=False) as pf:
+ self.assertEqual(pf['packet_filter']['status'], 'DOWN')
+
+ self.assertFalse(self.ofc.create_ofc_packet_filter.called)
+ self.assertFalse(self.ofc.delete_ofc_packet_filter.called)
+
+ def test_create_pf_on_port_no_ofc_creation(self):
+ with self.packet_filter_on_port(admin_state_up=False,
+ set_portinfo=False) as pf:
+ self.assertEqual(pf['packet_filter']['status'], 'DOWN')
+
+ self.assertFalse(self.ofc.create_ofc_packet_filter.called)
+ self.assertFalse(self.ofc.delete_ofc_packet_filter.called)
+
+ def test_create_pf_on_network_with_ofc_creation(self):
+ with self.packet_filter_on_network() as pf:
+ pf_id = pf['packet_filter']['id']
+ self.assertEqual(pf['packet_filter']['status'], 'ACTIVE')
+
+ ctx = mock.ANY
+ pf_dict = mock.ANY
+ expected = [
+ mock.call.exists_ofc_packet_filter(ctx, pf_id),
+ mock.call.create_ofc_packet_filter(ctx, pf_id, pf_dict),
+ mock.call.exists_ofc_packet_filter(ctx, pf_id),
+ mock.call.delete_ofc_packet_filter(ctx, pf_id),
+ ]
+ self.ofc.assert_has_calls(expected)
+ self.assertEqual(self.ofc.create_ofc_packet_filter.call_count, 1)
+ self.assertEqual(self.ofc.delete_ofc_packet_filter.call_count, 1)
+
+ def test_create_pf_on_port_with_ofc_creation(self):
+ with self.packet_filter_on_port() as pf:
+ pf_id = pf['packet_filter']['id']
+ self.assertEqual(pf['packet_filter']['status'], 'ACTIVE')
+
+ ctx = mock.ANY
+ pf_dict = mock.ANY
+ expected = [
+ mock.call.exists_ofc_packet_filter(ctx, pf_id),
+ mock.call.create_ofc_packet_filter(ctx, pf_id, pf_dict),
+ mock.call.exists_ofc_packet_filter(ctx, pf_id),
+ mock.call.delete_ofc_packet_filter(ctx, pf_id),
+ ]
+ self.ofc.assert_has_calls(expected)
+ self.assertEqual(self.ofc.create_ofc_packet_filter.call_count, 1)
+ self.assertEqual(self.ofc.delete_ofc_packet_filter.call_count, 1)
+
+ def test_create_pf_with_invalid_priority(self):
+ with self.network() as net:
+ net_id = net['network']['id']
+ kwargs = {'priority': 'high'}
+ self._create_packet_filter(self.fmt, net_id,
+ webob.exc.HTTPBadRequest.code,
+ **kwargs)
+
+ self.assertFalse(self.ofc.create_ofc_packet_filter.called)
+
+ def test_create_pf_with_ofc_creation_failure(self):
+ self.ofc.set_raise_exc('create_ofc_packet_filter',
+ nexc.OFCException(reason='hoge'))
+
+ with self.packet_filter_on_network() as pf:
+ pf_id = pf['packet_filter']['id']
+ pf_ref = self._show('packet_filters', pf_id)
+ self.assertEqual(pf_ref['packet_filter']['status'], 'ERROR')
+
+ self.ofc.set_raise_exc('create_ofc_packet_filter', None)
+
+ # Retry deactivate packet_filter.
+ data = {'packet_filter': {'priority': 1000}}
+ self._update('packet_filters', pf_id, data)
+
+ pf_ref = self._show('packet_filters', pf_id)
+ self.assertEqual(pf_ref['packet_filter']['status'], 'ACTIVE')
+
+ ctx = mock.ANY
+ pf_dict = mock.ANY
+ expected = [
+ mock.call.exists_ofc_packet_filter(ctx, pf_id),
+ mock.call.create_ofc_packet_filter(ctx, pf_id, pf_dict),
+
+ mock.call.exists_ofc_packet_filter(ctx, pf_id),
+
+ mock.call.exists_ofc_packet_filter(ctx, pf_id),
+ mock.call.create_ofc_packet_filter(ctx, pf_id, pf_dict),
+ ]
+ self.ofc.assert_has_calls(expected)
+ self.assertEqual(self.ofc.create_ofc_packet_filter.call_count, 2)
+
def test_show_pf_on_network(self):
kwargs = {
'name': 'test-pf-net',
self.assertEqual(pf_id, pf_ref['packet_filter']['id'])
for key in kwargs:
self.assertEqual(kwargs[key], pf_ref['packet_filter'][key])
+
+ def test_show_pf_on_port(self):
+ kwargs = {
+ 'name': 'test-pf-port',
+ 'admin_state_up': False,
+ 'action': 'DENY',
+ 'priority': '0o147',
+ 'src_mac': '00:11:22:33:44:55',
+ 'dst_mac': '66:77:88:99:aa:bb',
+ 'eth_type': 2048,
+ 'src_cidr': '192.168.1.0/24',
+ 'dst_cidr': '192.168.2.0/24',
+ 'protocol': 'TCP',
+ 'dst_port': '0x50'
+ }
+
+ with self.packet_filter_on_port(**kwargs) as pf:
+ pf_id = pf['packet_filter']['id']
+ pf_ref = self._show('packet_filters', pf_id)
+
+ # convert string to int.
+ kwargs.update({'priority': 103, 'eth_type': 2048,
+ 'src_port': u'', 'dst_port': 80})
+
+ self.assertEqual(pf_id, pf_ref['packet_filter']['id'])
+ for key in kwargs:
+ self.assertEqual(kwargs[key], pf_ref['packet_filter'][key])
+
+ def test_show_pf_not_found(self):
+ pf_id = '00000000-ffff-ffff-ffff-000000000000'
+
+ self._show('packet_filters', pf_id,
+ expected_code=webob.exc.HTTPNotFound.code)
+
+ def test_update_pf_on_network(self):
+ ctx = mock.ANY
+ pf_dict = mock.ANY
+ with self.packet_filter_on_network(admin_state_up=False) as pf:
+ pf_id = pf['packet_filter']['id']
+
+ self.assertFalse(self.ofc.create_ofc_packet_filter.called)
+ data = {'packet_filter': {'admin_state_up': True}}
+ self._update('packet_filters', pf_id, data)
+ self.ofc.create_ofc_packet_filter.assert_called_once_with(
+ ctx, pf_id, pf_dict)
+
+ self.assertFalse(self.ofc.delete_ofc_packet_filter.called)
+ data = {'packet_filter': {'admin_state_up': False}}
+ self._update('packet_filters', pf_id, data)
+ self.ofc.delete_ofc_packet_filter.assert_called_once_with(
+ ctx, pf_id)
+
+ def test_update_pf_on_port(self):
+ ctx = mock.ANY
+ pf_dict = mock.ANY
+ with self.packet_filter_on_port(admin_state_up=False) as pf:
+ pf_id = pf['packet_filter']['id']
+
+ self.assertFalse(self.ofc.create_ofc_packet_filter.called)
+ data = {'packet_filter': {'admin_state_up': True}}
+ self._update('packet_filters', pf_id, data)
+ self.ofc.create_ofc_packet_filter.assert_called_once_with(
+ ctx, pf_id, pf_dict)
+
+ self.assertFalse(self.ofc.delete_ofc_packet_filter.called)
+ data = {'packet_filter': {'admin_state_up': False}}
+ self._update('packet_filters', pf_id, data)
+ self.ofc.delete_ofc_packet_filter.assert_called_once_with(
+ ctx, pf_id)
+
+ def test_activate_pf_on_port_triggered_by_update_port(self):
+ ctx = mock.ANY
+ pf_dict = mock.ANY
+ with self.packet_filter_on_port(set_portinfo=False) as pf:
+ pf_id = pf['packet_filter']['id']
+ in_port_id = pf['packet_filter']['in_port']
+
+ self.assertFalse(self.ofc.create_ofc_packet_filter.called)
+ portinfo = {'id': in_port_id, 'port_no': 123}
+ kw = {'added': [portinfo]}
+ self.rpcapi_update_ports(**kw)
+ self.ofc.create_ofc_packet_filter.assert_called_once_with(
+ ctx, pf_id, pf_dict)
+
+ self.assertFalse(self.ofc.delete_ofc_packet_filter.called)
+ kw = {'removed': [in_port_id]}
+ self.rpcapi_update_ports(**kw)
+ self.ofc.delete_ofc_packet_filter.assert_called_once_with(
+ ctx, pf_id)
+
+ # Ensure pf was created before in_port has activated.
+ ctx = mock.ANY
+ pf_dict = mock.ANY
+ port_dict = mock.ANY
+ expected = [
+ mock.call.exists_ofc_packet_filter(ctx, pf_id),
+ mock.call.create_ofc_packet_filter(ctx, pf_id, pf_dict),
+ mock.call.exists_ofc_port(ctx, in_port_id),
+ mock.call.create_ofc_port(ctx, in_port_id, port_dict),
+
+ mock.call.exists_ofc_port(ctx, in_port_id),
+ mock.call.delete_ofc_port(ctx, in_port_id, port_dict),
+ mock.call.exists_ofc_packet_filter(ctx, pf_id),
+ mock.call.delete_ofc_packet_filter(ctx, pf_id),
+ ]
+ self.ofc.assert_has_calls(expected)
+ self.assertEqual(self.ofc.create_ofc_packet_filter.call_count, 1)
+ self.assertEqual(self.ofc.delete_ofc_packet_filter.call_count, 1)
+
+ def test_activate_pf_while_exists_on_ofc(self):
+ ctx = mock.ANY
+ with self.packet_filter_on_network() as pf:
+ pf_id = pf['packet_filter']['id']
+
+ self.ofc.set_raise_exc('delete_ofc_packet_filter',
+ nexc.OFCException(reason='hoge'))
+
+ # This update request will make plugin reactivate pf.
+ data = {'packet_filter': {'priority': 1000}}
+ self._update('packet_filters', pf_id, data)
+
+ self.ofc.set_raise_exc('delete_ofc_packet_filter', None)
+
+ ctx = mock.ANY
+ pf_dict = mock.ANY
+ expected = [
+ mock.call.exists_ofc_packet_filter(ctx, pf_id),
+ mock.call.create_ofc_packet_filter(ctx, pf_id, pf_dict),
+
+ mock.call.exists_ofc_packet_filter(ctx, pf_id),
+ mock.call.delete_ofc_packet_filter(ctx, pf_id),
+
+ mock.call.exists_ofc_packet_filter(ctx, pf_id),
+
+ mock.call.exists_ofc_packet_filter(ctx, pf_id),
+ ]
+ self.ofc.assert_has_calls(expected)
+ self.assertEqual(self.ofc.delete_ofc_packet_filter.call_count, 2)
+
+ def test_deactivate_pf_with_ofc_deletion_failure(self):
+ ctx = mock.ANY
+ with self.packet_filter_on_network() as pf:
+ pf_id = pf['packet_filter']['id']
+
+ self.ofc.set_raise_exc('delete_ofc_packet_filter',
+ nexc.OFCException(reason='hoge'))
+
+ data = {'packet_filter': {'admin_state_up': False}}
+ self._update('packet_filters', pf_id, data)
+
+ pf_ref = self._show('packet_filters', pf_id)
+ self.assertEqual(pf_ref['packet_filter']['status'], 'ERROR')
+
+ self.ofc.set_raise_exc('delete_ofc_packet_filter', None)
+
+ data = {'packet_filter': {'priority': 1000}}
+ self._update('packet_filters', pf_id, data)
+
+ pf_ref = self._show('packet_filters', pf_id)
+ self.assertEqual(pf_ref['packet_filter']['status'], 'DOWN')
+
+ ctx = mock.ANY
+ pf_dict = mock.ANY
+ expected = [
+ mock.call.exists_ofc_packet_filter(ctx, pf_id),
+ mock.call.create_ofc_packet_filter(ctx, pf_id, pf_dict),
+
+ mock.call.exists_ofc_packet_filter(ctx, pf_id),
+ mock.call.delete_ofc_packet_filter(ctx, pf_id),
+
+ mock.call.exists_ofc_packet_filter(ctx, pf_id),
+ mock.call.delete_ofc_packet_filter(ctx, pf_id),
+
+ mock.call.exists_ofc_packet_filter(ctx, pf_id),
+ ]
+ self.ofc.assert_has_calls(expected)
+ self.assertEqual(self.ofc.delete_ofc_packet_filter.call_count, 2)
+
+ def test_delete_pf_with_ofc_deletion_failure(self):
+ self.ofc.set_raise_exc('delete_ofc_packet_filter',
+ nexc.OFCException(reason='hoge'))
+
+ with self.packet_filter_on_network() as pf:
+ pf_id = pf['packet_filter']['id']
+
+ self._delete('packet_filters', pf_id,
+ expected_code=webob.exc.HTTPInternalServerError.code)
+
+ pf_ref = self._show('packet_filters', pf_id)
+ self.assertEqual(pf_ref['packet_filter']['status'], 'ERROR')
+
+ self.ofc.set_raise_exc('delete_ofc_packet_filter', None)
+ # Then, self._delete('packet_filters', pf_id) will success.
+
+ ctx = mock.ANY
+ pf_dict = mock.ANY
+ expected = [
+ mock.call.exists_ofc_packet_filter(ctx, pf_id),
+ mock.call.create_ofc_packet_filter(ctx, pf_id, pf_dict),
+
+ mock.call.exists_ofc_packet_filter(ctx, pf_id),
+ mock.call.delete_ofc_packet_filter(ctx, pf_id),
+
+ mock.call.exists_ofc_packet_filter(ctx, pf_id),
+ mock.call.delete_ofc_packet_filter(ctx, pf_id),
+ ]
+ self.ofc.assert_has_calls(expected)
+ self.assertEqual(self.ofc.delete_ofc_packet_filter.call_count, 2)
+
+ def test_auto_delete_pf_in_network_deletion(self):
+ with self.packet_filter_on_network(admin_state_up=False,
+ do_delete=False) as pf:
+ pf_id = pf['packet_filter']['id']
+
+ self._show('packet_filters', pf_id,
+ expected_code=webob.exc.HTTPNotFound.code)