~ubuntu-branches/ubuntu/vivid/neutron/vivid-updates

« back to all changes in this revision

Viewing changes to neutron/plugins/nec/packet_filter.py

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2015-03-30 11:17:19 UTC
  • mfrom: (1.1.21)
  • Revision ID: package-import@ubuntu.com-20150330111719-h0gx7233p4jkkgfh
Tags: 1:2015.1~b3-0ubuntu1
* New upstream milestone release:
  - d/control: Align version requirements with upstream.
  - d/control: Add new dependency on oslo-log.
  - d/p/*: Rebase.
  - d/control,d/neutron-plugin-hyperv*: Dropped, decomposed into
    separate project upstream.
  - d/control,d/neutron-plugin-openflow*: Dropped, decomposed into
    separate project upstream.
  - d/neutron-common.install: Add neutron-rootwrap-daemon and 
    neutron-keepalived-state-change binaries.
  - d/rules: Ignore neutron-hyperv-agent when installing; only for Windows.
  - d/neutron-plugin-cisco.install: Drop neutron-cisco-cfg-agent as
    decomposed into separate project upstream.
  - d/neutron-plugin-vmware.install: Drop neutron-check-nsx-config and
    neutron-nsx-manage as decomposed into separate project upstream.
  - d/control: Add dependency on python-neutron-fwaas to neutron-l3-agent.
* d/pydist-overrides: Add overrides for oslo packages.
* d/control: Fixup type in package description (LP: #1263539).
* d/p/fixup-driver-test-execution.patch: Cherry pick fix from upstream VCS
  to support unit test exection in out-of-tree vendor drivers.
* d/neutron-common.postinst: Allow general access to /etc/neutron but limit
  access to root/neutron to /etc/neutron/neutron.conf to support execution
  of unit tests in decomposed vendor drivers.
* d/control: Add dependency on python-neutron-fwaas to neutron-l3-agent
  package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright 2012-2013 NEC Corporation.  All rights reserved.
2
 
#
3
 
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
4
 
#    not use this file except in compliance with the License. You may obtain
5
 
#    a copy of the License at
6
 
#
7
 
#         http://www.apache.org/licenses/LICENSE-2.0
8
 
#
9
 
#    Unless required by applicable law or agreed to in writing, software
10
 
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
 
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
 
#    License for the specific language governing permissions and limitations
13
 
#    under the License.
14
 
 
15
 
from oslo.utils import excutils
16
 
 
17
 
from neutron.i18n import _LE
18
 
from neutron.openstack.common import log as logging
19
 
from neutron.plugins.nec.common import config
20
 
from neutron.plugins.nec.common import exceptions as nexc
21
 
from neutron.plugins.nec.db import packetfilter as pf_db
22
 
 
23
 
 
24
 
LOG = logging.getLogger(__name__)
25
 
 
26
 
 
27
 
class PacketFilterMixin(pf_db.PacketFilterDbMixin):
28
 
    """Mixin class to add packet filter to NECPluginV2."""
29
 
 
30
 
    @property
31
 
    def packet_filter_enabled(self):
32
 
        if not hasattr(self, '_packet_filter_enabled'):
33
 
            self._packet_filter_enabled = (
34
 
                config.OFC.enable_packet_filter and
35
 
                self.ofc.driver.filter_supported())
36
 
        return self._packet_filter_enabled
37
 
 
38
 
    def remove_packet_filter_extension_if_disabled(self, aliases):
39
 
        if not self.packet_filter_enabled:
40
 
            LOG.debug('Disabled packet-filter extension.')
41
 
            aliases.remove('packet-filter')
42
 
 
43
 
    def create_packet_filter(self, context, packet_filter):
44
 
        """Create a new packet_filter entry on DB, then try to activate it."""
45
 
        LOG.debug("create_packet_filter() called, packet_filter=%s .",
46
 
                  packet_filter)
47
 
 
48
 
        if hasattr(self.ofc.driver, 'validate_filter_create'):
49
 
            pf = packet_filter['packet_filter']
50
 
            self.ofc.driver.validate_filter_create(context, pf)
51
 
        pf = super(PacketFilterMixin, self).create_packet_filter(
52
 
            context, packet_filter)
53
 
 
54
 
        return self.activate_packet_filter_if_ready(context, pf)
55
 
 
56
 
    def update_packet_filter(self, context, id, packet_filter):
57
 
        """Update packet_filter entry on DB, and recreate it if changed.
58
 
 
59
 
        If any rule of the packet_filter was changed, recreate it on OFC.
60
 
        """
61
 
        LOG.debug("update_packet_filter() called, "
62
 
                  "id=%(id)s packet_filter=%(packet_filter)s .",
63
 
                  {'id': id, 'packet_filter': packet_filter})
64
 
 
65
 
        pf_data = packet_filter['packet_filter']
66
 
        if hasattr(self.ofc.driver, 'validate_filter_update'):
67
 
            self.ofc.driver.validate_filter_update(context, pf_data)
68
 
 
69
 
        # validate ownership
70
 
        pf_old = self.get_packet_filter(context, id)
71
 
 
72
 
        pf = super(PacketFilterMixin, self).update_packet_filter(
73
 
            context, id, packet_filter)
74
 
 
75
 
        def _packet_filter_changed(old_pf, new_pf):
76
 
            LOG.debug('old_pf=%(old_pf)s, new_pf=%(new_pf)s',
77
 
                      {'old_pf': old_pf, 'new_pf': new_pf})
78
 
            # When the status is ERROR, force sync to OFC.
79
 
            if old_pf['status'] == pf_db.PF_STATUS_ERROR:
80
 
                LOG.debug('update_packet_filter: Force filter update '
81
 
                          'because the previous status is ERROR.')
82
 
                return True
83
 
            for key in new_pf:
84
 
                if key in ('id', 'name', 'tenant_id', 'network_id',
85
 
                           'in_port', 'status'):
86
 
                    continue
87
 
                if old_pf[key] != new_pf[key]:
88
 
                    return True
89
 
            return False
90
 
 
91
 
        if _packet_filter_changed(pf_old, pf):
92
 
            if hasattr(self.ofc.driver, 'update_filter'):
93
 
                # admin_state is changed
94
 
                if pf_old['admin_state_up'] != pf['admin_state_up']:
95
 
                    LOG.debug('update_packet_filter: admin_state '
96
 
                              'is changed to %s', pf['admin_state_up'])
97
 
                    if pf['admin_state_up']:
98
 
                        self.activate_packet_filter_if_ready(context, pf)
99
 
                    else:
100
 
                        self.deactivate_packet_filter(context, pf)
101
 
                elif pf['admin_state_up']:
102
 
                    LOG.debug('update_packet_filter: admin_state is '
103
 
                              'unchanged (True)')
104
 
                    if self.ofc.exists_ofc_packet_filter(context, id):
105
 
                        pf = self._update_packet_filter(context, pf, pf_data)
106
 
                    else:
107
 
                        pf = self.activate_packet_filter_if_ready(context, pf)
108
 
                else:
109
 
                    LOG.debug('update_packet_filter: admin_state is unchanged '
110
 
                              '(False). No need to update OFC filter.')
111
 
            else:
112
 
                pf = self.deactivate_packet_filter(context, pf)
113
 
                pf = self.activate_packet_filter_if_ready(context, pf)
114
 
 
115
 
        return pf
116
 
 
117
 
    def _update_packet_filter(self, context, new_pf, pf_data):
118
 
        pf_id = new_pf['id']
119
 
        prev_status = new_pf['status']
120
 
        try:
121
 
            # If previous status is ERROR, try to sync all attributes.
122
 
            pf = new_pf if prev_status == pf_db.PF_STATUS_ERROR else pf_data
123
 
            self.ofc.update_ofc_packet_filter(context, pf_id, pf)
124
 
            new_status = pf_db.PF_STATUS_ACTIVE
125
 
            if new_status != prev_status:
126
 
                self._update_resource_status(context, "packet_filter",
127
 
                                             pf_id, new_status)
128
 
                new_pf['status'] = new_status
129
 
            return new_pf
130
 
        except Exception as exc:
131
 
            with excutils.save_and_reraise_exception():
132
 
                if (isinstance(exc, nexc.OFCException) or
133
 
                    isinstance(exc, nexc.OFCConsistencyBroken)):
134
 
                    LOG.error(_LE("Failed to create packet_filter id=%(id)s "
135
 
                                  "on OFC: %(exc)s"),
136
 
                              {'id': pf_id, 'exc': exc})
137
 
                new_status = pf_db.PF_STATUS_ERROR
138
 
                if new_status != prev_status:
139
 
                    self._update_resource_status(context, "packet_filter",
140
 
                                                 pf_id, new_status)
141
 
 
142
 
    def delete_packet_filter(self, context, id):
143
 
        """Deactivate and delete packet_filter."""
144
 
        LOG.debug("delete_packet_filter() called, id=%s .", id)
145
 
 
146
 
        # validate ownership
147
 
        pf = self.get_packet_filter(context, id)
148
 
 
149
 
        # deactivate_packet_filter() raises an exception
150
 
        # if an error occurs during processing.
151
 
        pf = self.deactivate_packet_filter(context, pf)
152
 
 
153
 
        super(PacketFilterMixin, self).delete_packet_filter(context, id)
154
 
 
155
 
    def activate_packet_filter_if_ready(self, context, packet_filter):
156
 
        """Activate packet_filter by creating filter on OFC if ready.
157
 
 
158
 
        Conditions to create packet_filter on OFC are:
159
 
            * packet_filter admin_state is UP
160
 
            * (if 'in_port' is specified) portinfo is available
161
 
        """
162
 
        LOG.debug("activate_packet_filter_if_ready() called, "
163
 
                  "packet_filter=%s.", packet_filter)
164
 
 
165
 
        pf_id = packet_filter['id']
166
 
        current = packet_filter['status']
167
 
 
168
 
        pf_status = current
169
 
        if not packet_filter['admin_state_up']:
170
 
            LOG.debug("activate_packet_filter_if_ready(): skip pf_id=%s, "
171
 
                      "packet_filter.admin_state_up is False.", pf_id)
172
 
        elif self.ofc.exists_ofc_packet_filter(context, packet_filter['id']):
173
 
            LOG.debug("_activate_packet_filter_if_ready(): skip, "
174
 
                      "ofc_packet_filter already exists.")
175
 
        else:
176
 
            LOG.debug("activate_packet_filter_if_ready(): create "
177
 
                      "packet_filter id=%s on OFC.", pf_id)
178
 
            try:
179
 
                self.ofc.create_ofc_packet_filter(context, pf_id,
180
 
                                                  packet_filter)
181
 
                pf_status = pf_db.PF_STATUS_ACTIVE
182
 
            except nexc.PortInfoNotFound:
183
 
                LOG.debug("Skipped to create a packet filter pf_id=%s "
184
 
                          "on OFC, no portinfo for the in_port.", pf_id)
185
 
            except (nexc.OFCException, nexc.OFCMappingNotFound) as exc:
186
 
                LOG.error(_LE("Failed to create packet_filter id=%(id)s on "
187
 
                              "OFC: %(exc)s"), {'id': pf_id, 'exc': exc})
188
 
                pf_status = pf_db.PF_STATUS_ERROR
189
 
 
190
 
        if pf_status != current:
191
 
            self._update_resource_status(context, "packet_filter", pf_id,
192
 
                                         pf_status)
193
 
            packet_filter.update({'status': pf_status})
194
 
 
195
 
        return packet_filter
196
 
 
197
 
    def deactivate_packet_filter(self, context, packet_filter):
198
 
        """Deactivate packet_filter by deleting filter from OFC if exixts."""
199
 
        LOG.debug("deactivate_packet_filter_if_ready() called, "
200
 
                  "packet_filter=%s.", packet_filter)
201
 
        pf_id = packet_filter['id']
202
 
 
203
 
        if not self.ofc.exists_ofc_packet_filter(context, pf_id):
204
 
            LOG.debug("deactivate_packet_filter(): skip, "
205
 
                      "Not found OFC Mapping for packet_filter id=%s.",
206
 
                      pf_id)
207
 
            return packet_filter
208
 
 
209
 
        LOG.debug("deactivate_packet_filter(): "
210
 
                  "deleting packet_filter id=%s from OFC.", pf_id)
211
 
        try:
212
 
            self.ofc.delete_ofc_packet_filter(context, pf_id)
213
 
            self._update_resource_status_if_changed(
214
 
                context, "packet_filter", packet_filter, pf_db.PF_STATUS_DOWN)
215
 
            return packet_filter
216
 
        except (nexc.OFCException, nexc.OFCMappingNotFound) as exc:
217
 
            with excutils.save_and_reraise_exception():
218
 
                LOG.error(_LE("Failed to delete packet_filter id=%(id)s "
219
 
                              "from OFC: %(exc)s"),
220
 
                          {'id': pf_id, 'exc': exc})
221
 
                self._update_resource_status_if_changed(
222
 
                    context, "packet_filter", packet_filter,
223
 
                    pf_db.PF_STATUS_ERROR)
224
 
 
225
 
    def activate_packet_filters_by_port(self, context, port_id):
226
 
        if not self.packet_filter_enabled:
227
 
            return
228
 
 
229
 
        filters = {'in_port': [port_id], 'admin_state_up': [True],
230
 
                   'status': [pf_db.PF_STATUS_DOWN]}
231
 
        pfs = self.get_packet_filters(context, filters=filters)
232
 
        for pf in pfs:
233
 
            self.activate_packet_filter_if_ready(context, pf)
234
 
 
235
 
    def deactivate_packet_filters_by_port(self, context, port_id,
236
 
                                          raise_exc=True):
237
 
        if not self.packet_filter_enabled:
238
 
            return
239
 
 
240
 
        filters = {'in_port': [port_id], 'status': [pf_db.PF_STATUS_ACTIVE]}
241
 
        pfs = self.get_packet_filters(context, filters=filters)
242
 
        error = False
243
 
        for pf in pfs:
244
 
            try:
245
 
                self.deactivate_packet_filter(context, pf)
246
 
            except (nexc.OFCException, nexc.OFCMappingNotFound):
247
 
                error = True
248
 
        if raise_exc and error:
249
 
            raise nexc.OFCException(_('Error occurred while disabling packet '
250
 
                                      'filter(s) for port %s'), port_id)
251
 
 
252
 
    def get_packet_filters_for_port(self, context, port):
253
 
        if self.packet_filter_enabled:
254
 
            return super(PacketFilterMixin,
255
 
                         self).get_packet_filters_for_port(context, port)