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

« back to all changes in this revision

Viewing changes to neutron/plugins/vmware/dhcp_meta/lsnmanager.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 2014 VMware, Inc.
2
 
#
3
 
# All Rights Reserved
4
 
#
5
 
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
6
 
#    not use this file except in compliance with the License. You may obtain
7
 
#    a copy of the License at
8
 
#
9
 
#         http://www.apache.org/licenses/LICENSE-2.0
10
 
#
11
 
#    Unless required by applicable law or agreed to in writing, software
12
 
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
 
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
 
#    License for the specific language governing permissions and limitations
15
 
#    under the License.
16
 
#
17
 
 
18
 
from oslo.config import cfg
19
 
from oslo.db import exception as db_exc
20
 
from oslo.utils import excutils
21
 
 
22
 
from neutron.common import exceptions as n_exc
23
 
from neutron.i18n import _LE, _LW
24
 
from neutron.openstack.common import log as logging
25
 
from neutron.plugins.vmware.api_client import exception as api_exc
26
 
from neutron.plugins.vmware.common import exceptions as p_exc
27
 
from neutron.plugins.vmware.common import nsx_utils
28
 
from neutron.plugins.vmware.dbexts import lsn_db
29
 
from neutron.plugins.vmware.dhcp_meta import constants as const
30
 
from neutron.plugins.vmware.nsxlib import lsn as lsn_api
31
 
from neutron.plugins.vmware.nsxlib import switch as switch_api
32
 
 
33
 
LOG = logging.getLogger(__name__)
34
 
 
35
 
META_CONF = 'metadata-proxy'
36
 
DHCP_CONF = 'dhcp'
37
 
 
38
 
 
39
 
lsn_opts = [
40
 
    cfg.BoolOpt('sync_on_missing_data', default=False,
41
 
                help=_('Pull LSN information from NSX in case it is missing '
42
 
                       'from the local data store. This is useful to rebuild '
43
 
                       'the local store in case of server recovery.'))
44
 
]
45
 
 
46
 
 
47
 
def register_lsn_opts(config):
48
 
    config.CONF.register_opts(lsn_opts, "NSX_LSN")
49
 
 
50
 
 
51
 
class LsnManager(object):
52
 
    """Manage LSN entities associated with networks."""
53
 
 
54
 
    def __init__(self, plugin):
55
 
        self.plugin = plugin
56
 
 
57
 
    @property
58
 
    def cluster(self):
59
 
        return self.plugin.cluster
60
 
 
61
 
    def lsn_exists(self, context, network_id):
62
 
        """Return True if a Logical Service Node exists for the network."""
63
 
        return self.lsn_get(
64
 
            context, network_id, raise_on_err=False) is not None
65
 
 
66
 
    def lsn_get(self, context, network_id, raise_on_err=True):
67
 
        """Retrieve the LSN id associated to the network."""
68
 
        try:
69
 
            return lsn_api.lsn_for_network_get(self.cluster, network_id)
70
 
        except (n_exc.NotFound, api_exc.NsxApiException):
71
 
            if raise_on_err:
72
 
                LOG.error(_LE('Unable to find Logical Service Node for '
73
 
                              'network %s.'),
74
 
                          network_id)
75
 
                raise p_exc.LsnNotFound(entity='network',
76
 
                                        entity_id=network_id)
77
 
            else:
78
 
                LOG.warn(_LW('Unable to find Logical Service Node for '
79
 
                             'the requested network %s.'),
80
 
                         network_id)
81
 
 
82
 
    def lsn_create(self, context, network_id):
83
 
        """Create a LSN associated to the network."""
84
 
        try:
85
 
            return lsn_api.lsn_for_network_create(self.cluster, network_id)
86
 
        except api_exc.NsxApiException:
87
 
            err_msg = _('Unable to create LSN for network %s') % network_id
88
 
            raise p_exc.NsxPluginException(err_msg=err_msg)
89
 
 
90
 
    def lsn_delete(self, context, lsn_id):
91
 
        """Delete a LSN given its id."""
92
 
        try:
93
 
            lsn_api.lsn_delete(self.cluster, lsn_id)
94
 
        except (n_exc.NotFound, api_exc.NsxApiException):
95
 
            LOG.warn(_LW('Unable to delete Logical Service Node %s'), lsn_id)
96
 
 
97
 
    def lsn_delete_by_network(self, context, network_id):
98
 
        """Delete a LSN associated to the network."""
99
 
        lsn_id = self.lsn_get(context, network_id, raise_on_err=False)
100
 
        if lsn_id:
101
 
            self.lsn_delete(context, lsn_id)
102
 
 
103
 
    def lsn_port_get(self, context, network_id, subnet_id, raise_on_err=True):
104
 
        """Retrieve LSN and LSN port for the network and the subnet."""
105
 
        lsn_id = self.lsn_get(context, network_id, raise_on_err=raise_on_err)
106
 
        if lsn_id:
107
 
            try:
108
 
                lsn_port_id = lsn_api.lsn_port_by_subnet_get(
109
 
                    self.cluster, lsn_id, subnet_id)
110
 
            except (n_exc.NotFound, api_exc.NsxApiException):
111
 
                if raise_on_err:
112
 
                    LOG.error(_LE('Unable to find Logical Service Node Port '
113
 
                                  'for LSN %(lsn_id)s and subnet '
114
 
                                  '%(subnet_id)s'),
115
 
                              {'lsn_id': lsn_id, 'subnet_id': subnet_id})
116
 
                    raise p_exc.LsnPortNotFound(lsn_id=lsn_id,
117
 
                                                entity='subnet',
118
 
                                                entity_id=subnet_id)
119
 
                else:
120
 
                    LOG.warn(_LW('Unable to find Logical Service Node Port '
121
 
                                 'for LSN %(lsn_id)s and subnet '
122
 
                                 '%(subnet_id)s'),
123
 
                             {'lsn_id': lsn_id, 'subnet_id': subnet_id})
124
 
                return (lsn_id, None)
125
 
            else:
126
 
                return (lsn_id, lsn_port_id)
127
 
        else:
128
 
            return (None, None)
129
 
 
130
 
    def lsn_port_get_by_mac(self, context, network_id, mac, raise_on_err=True):
131
 
        """Retrieve LSN and LSN port given network and mac address."""
132
 
        lsn_id = self.lsn_get(context, network_id, raise_on_err=raise_on_err)
133
 
        if lsn_id:
134
 
            try:
135
 
                lsn_port_id = lsn_api.lsn_port_by_mac_get(
136
 
                    self.cluster, lsn_id, mac)
137
 
            except (n_exc.NotFound, api_exc.NsxApiException):
138
 
                if raise_on_err:
139
 
                    LOG.error(_LE('Unable to find Logical Service Node Port '
140
 
                                  'for LSN %(lsn_id)s and mac address '
141
 
                                  '%(mac)s'),
142
 
                              {'lsn_id': lsn_id, 'mac': mac})
143
 
                    raise p_exc.LsnPortNotFound(lsn_id=lsn_id,
144
 
                                                entity='MAC',
145
 
                                                entity_id=mac)
146
 
                else:
147
 
                    LOG.warn(_LW('Unable to find Logical Service Node '
148
 
                                 'Port for LSN %(lsn_id)s and mac address '
149
 
                                 '%(mac)s'),
150
 
                             {'lsn_id': lsn_id, 'mac': mac})
151
 
                return (lsn_id, None)
152
 
            else:
153
 
                return (lsn_id, lsn_port_id)
154
 
        else:
155
 
            return (None, None)
156
 
 
157
 
    def lsn_port_create(self, context, lsn_id, subnet_info):
158
 
        """Create and return LSN port for associated subnet."""
159
 
        try:
160
 
            return lsn_api.lsn_port_create(self.cluster, lsn_id, subnet_info)
161
 
        except n_exc.NotFound:
162
 
            raise p_exc.LsnNotFound(entity='', entity_id=lsn_id)
163
 
        except api_exc.NsxApiException:
164
 
            err_msg = _('Unable to create port for LSN  %s') % lsn_id
165
 
            raise p_exc.NsxPluginException(err_msg=err_msg)
166
 
 
167
 
    def lsn_port_delete(self, context, lsn_id, lsn_port_id):
168
 
        """Delete a LSN port from the Logical Service Node."""
169
 
        try:
170
 
            lsn_api.lsn_port_delete(self.cluster, lsn_id, lsn_port_id)
171
 
        except (n_exc.NotFound, api_exc.NsxApiException):
172
 
            LOG.warn(_LW('Unable to delete LSN Port %s'), lsn_port_id)
173
 
 
174
 
    def lsn_port_dispose(self, context, network_id, mac_address):
175
 
        """Delete a LSN port given the network and the mac address."""
176
 
        lsn_id, lsn_port_id = self.lsn_port_get_by_mac(
177
 
            context, network_id, mac_address, raise_on_err=False)
178
 
        if lsn_port_id:
179
 
            self.lsn_port_delete(context, lsn_id, lsn_port_id)
180
 
            if mac_address == const.METADATA_MAC:
181
 
                try:
182
 
                    lswitch_port_id = switch_api.get_port_by_neutron_tag(
183
 
                        self.cluster, network_id,
184
 
                        const.METADATA_PORT_ID)['uuid']
185
 
                    switch_api.delete_port(
186
 
                        self.cluster, network_id, lswitch_port_id)
187
 
                except (n_exc.PortNotFoundOnNetwork,
188
 
                        api_exc.NsxApiException):
189
 
                    LOG.warn(_LW("Metadata port not found while attempting "
190
 
                                 "to delete it from network %s"), network_id)
191
 
        else:
192
 
            LOG.warn(_LW("Unable to find Logical Services Node "
193
 
                         "Port with MAC %s"), mac_address)
194
 
 
195
 
    def lsn_port_dhcp_setup(
196
 
        self, context, network_id, port_id, port_data, subnet_config=None):
197
 
        """Connect network to LSN via specified port and port_data."""
198
 
        try:
199
 
            lsn_id = None
200
 
            switch_id = nsx_utils.get_nsx_switch_ids(
201
 
                context.session, self.cluster, network_id)[0]
202
 
            lswitch_port_id = switch_api.get_port_by_neutron_tag(
203
 
                self.cluster, switch_id, port_id)['uuid']
204
 
            lsn_id = self.lsn_get(context, network_id)
205
 
            lsn_port_id = self.lsn_port_create(context, lsn_id, port_data)
206
 
        except (n_exc.NotFound, p_exc.NsxPluginException):
207
 
            raise p_exc.PortConfigurationError(
208
 
                net_id=network_id, lsn_id=lsn_id, port_id=port_id)
209
 
        else:
210
 
            try:
211
 
                lsn_api.lsn_port_plug_network(
212
 
                    self.cluster, lsn_id, lsn_port_id, lswitch_port_id)
213
 
            except p_exc.LsnConfigurationConflict:
214
 
                self.lsn_port_delete(context, lsn_id, lsn_port_id)
215
 
                raise p_exc.PortConfigurationError(
216
 
                    net_id=network_id, lsn_id=lsn_id, port_id=port_id)
217
 
            if subnet_config:
218
 
                self.lsn_port_dhcp_configure(
219
 
                    context, lsn_id, lsn_port_id, subnet_config)
220
 
            else:
221
 
                return (lsn_id, lsn_port_id)
222
 
 
223
 
    def lsn_port_metadata_setup(self, context, lsn_id, subnet):
224
 
        """Connect subnet to specified LSN."""
225
 
        data = {
226
 
            "mac_address": const.METADATA_MAC,
227
 
            "ip_address": subnet['cidr'],
228
 
            "subnet_id": subnet['id']
229
 
        }
230
 
        network_id = subnet['network_id']
231
 
        tenant_id = subnet['tenant_id']
232
 
        lswitch_port_id = None
233
 
        try:
234
 
            switch_id = nsx_utils.get_nsx_switch_ids(
235
 
                context.session, self.cluster, network_id)[0]
236
 
            lswitch_port_id = switch_api.create_lport(
237
 
                self.cluster, switch_id, tenant_id,
238
 
                const.METADATA_PORT_ID, const.METADATA_PORT_NAME,
239
 
                const.METADATA_DEVICE_ID, True)['uuid']
240
 
            lsn_port_id = self.lsn_port_create(context, lsn_id, data)
241
 
        except (n_exc.NotFound, p_exc.NsxPluginException,
242
 
                api_exc.NsxApiException):
243
 
            raise p_exc.PortConfigurationError(
244
 
                net_id=network_id, lsn_id=lsn_id, port_id=lswitch_port_id)
245
 
        else:
246
 
            try:
247
 
                lsn_api.lsn_port_plug_network(
248
 
                    self.cluster, lsn_id, lsn_port_id, lswitch_port_id)
249
 
            except p_exc.LsnConfigurationConflict:
250
 
                self.lsn_port_delete(self.cluster, lsn_id, lsn_port_id)
251
 
                switch_api.delete_port(
252
 
                    self.cluster, network_id, lswitch_port_id)
253
 
                raise p_exc.PortConfigurationError(
254
 
                    net_id=network_id, lsn_id=lsn_id, port_id=lsn_port_id)
255
 
 
256
 
    def lsn_port_dhcp_configure(self, context, lsn_id, lsn_port_id, subnet):
257
 
        """Enable/disable dhcp services with the given config options."""
258
 
        is_enabled = subnet["enable_dhcp"]
259
 
        dhcp_options = {
260
 
            "domain_name": cfg.CONF.NSX_DHCP.domain_name,
261
 
            "default_lease_time": cfg.CONF.NSX_DHCP.default_lease_time,
262
 
        }
263
 
        dns_servers = cfg.CONF.NSX_DHCP.extra_domain_name_servers or []
264
 
        dns_servers.extend(subnet["dns_nameservers"])
265
 
        if subnet['gateway_ip']:
266
 
            dhcp_options["routers"] = subnet["gateway_ip"]
267
 
        if dns_servers:
268
 
            dhcp_options["domain_name_servers"] = ",".join(dns_servers)
269
 
        if subnet["host_routes"]:
270
 
            dhcp_options["classless_static_routes"] = (
271
 
                ",".join(subnet["host_routes"])
272
 
            )
273
 
        try:
274
 
            lsn_api.lsn_port_dhcp_configure(
275
 
                self.cluster, lsn_id, lsn_port_id, is_enabled, dhcp_options)
276
 
        except (n_exc.NotFound, api_exc.NsxApiException):
277
 
            err_msg = (_('Unable to configure dhcp for Logical Service '
278
 
                         'Node %(lsn_id)s and port %(lsn_port_id)s')
279
 
                       % {'lsn_id': lsn_id, 'lsn_port_id': lsn_port_id})
280
 
            LOG.error(err_msg)
281
 
            raise p_exc.NsxPluginException(err_msg=err_msg)
282
 
 
283
 
    def lsn_metadata_configure(self, context, subnet_id, is_enabled):
284
 
        """Configure metadata service for the specified subnet."""
285
 
        subnet = self.plugin.get_subnet(context, subnet_id)
286
 
        network_id = subnet['network_id']
287
 
        meta_conf = cfg.CONF.NSX_METADATA
288
 
        metadata_options = {
289
 
            'metadata_server_ip': meta_conf.metadata_server_address,
290
 
            'metadata_server_port': meta_conf.metadata_server_port,
291
 
            'metadata_proxy_shared_secret': meta_conf.metadata_shared_secret
292
 
        }
293
 
        try:
294
 
            lsn_id = self.lsn_get(context, network_id)
295
 
            lsn_api.lsn_metadata_configure(
296
 
                self.cluster, lsn_id, is_enabled, metadata_options)
297
 
        except (p_exc.LsnNotFound, api_exc.NsxApiException):
298
 
            err_msg = (_('Unable to configure metadata '
299
 
                         'for subnet %s') % subnet_id)
300
 
            LOG.error(err_msg)
301
 
            raise p_exc.NsxPluginException(err_msg=err_msg)
302
 
        if is_enabled:
303
 
            try:
304
 
                # test that the lsn port exists
305
 
                self.lsn_port_get(context, network_id, subnet_id)
306
 
            except p_exc.LsnPortNotFound:
307
 
                # this might happen if subnet had dhcp off when created
308
 
                # so create one, and wire it
309
 
                self.lsn_port_metadata_setup(context, lsn_id, subnet)
310
 
        else:
311
 
            self.lsn_port_dispose(context, network_id, const.METADATA_MAC)
312
 
 
313
 
    def _lsn_port_host_conf(self, context, network_id, subnet_id, data, hdlr):
314
 
        lsn_id, lsn_port_id = self.lsn_port_get(
315
 
            context, network_id, subnet_id, raise_on_err=False)
316
 
        try:
317
 
            if lsn_id and lsn_port_id:
318
 
                hdlr(self.cluster, lsn_id, lsn_port_id, data)
319
 
        except (n_exc.NotFound, api_exc.NsxApiException):
320
 
            LOG.error(_LE('Error while configuring LSN '
321
 
                          'port %s'), lsn_port_id)
322
 
            raise p_exc.PortConfigurationError(
323
 
                net_id=network_id, lsn_id=lsn_id, port_id=lsn_port_id)
324
 
 
325
 
    def lsn_port_dhcp_host_add(self, context, network_id, subnet_id, host):
326
 
        """Add dhcp host entry to LSN port configuration."""
327
 
        self._lsn_port_host_conf(context, network_id, subnet_id, host,
328
 
                                 lsn_api.lsn_port_dhcp_host_add)
329
 
 
330
 
    def lsn_port_dhcp_host_remove(self, context, network_id, subnet_id, host):
331
 
        """Remove dhcp host entry from LSN port configuration."""
332
 
        self._lsn_port_host_conf(context, network_id, subnet_id, host,
333
 
                                 lsn_api.lsn_port_dhcp_host_remove)
334
 
 
335
 
    def lsn_port_meta_host_add(self, context, network_id, subnet_id, host):
336
 
        """Add dhcp host entry to LSN port configuration."""
337
 
        self._lsn_port_host_conf(context, network_id, subnet_id, host,
338
 
                                 lsn_api.lsn_port_metadata_host_add)
339
 
 
340
 
    def lsn_port_meta_host_remove(self, context, network_id, subnet_id, host):
341
 
        """Remove dhcp host entry from LSN port configuration."""
342
 
        self._lsn_port_host_conf(context, network_id, subnet_id, host,
343
 
                                 lsn_api.lsn_port_metadata_host_remove)
344
 
 
345
 
    def lsn_port_update(
346
 
        self, context, network_id, subnet_id, dhcp=None, meta=None):
347
 
        """Update the specified configuration for the LSN port."""
348
 
        if not dhcp and not meta:
349
 
            return
350
 
        try:
351
 
            lsn_id, lsn_port_id = self.lsn_port_get(
352
 
                context, network_id, subnet_id, raise_on_err=False)
353
 
            if dhcp and lsn_id and lsn_port_id:
354
 
                lsn_api.lsn_port_host_entries_update(
355
 
                    self.cluster, lsn_id, lsn_port_id, DHCP_CONF, dhcp)
356
 
            if meta and lsn_id and lsn_port_id:
357
 
                lsn_api.lsn_port_host_entries_update(
358
 
                    self.cluster, lsn_id, lsn_port_id, META_CONF, meta)
359
 
        except api_exc.NsxApiException:
360
 
            raise p_exc.PortConfigurationError(
361
 
                net_id=network_id, lsn_id=lsn_id, port_id=lsn_port_id)
362
 
 
363
 
 
364
 
class PersistentLsnManager(LsnManager):
365
 
    """Add local persistent state to LSN Manager."""
366
 
 
367
 
    def __init__(self, plugin):
368
 
        super(PersistentLsnManager, self).__init__(plugin)
369
 
        self.sync_on_missing = cfg.CONF.NSX_LSN.sync_on_missing_data
370
 
 
371
 
    def lsn_get(self, context, network_id, raise_on_err=True):
372
 
        try:
373
 
            obj = lsn_db.lsn_get_for_network(
374
 
                context, network_id, raise_on_err=raise_on_err)
375
 
            return obj.lsn_id if obj else None
376
 
        except p_exc.LsnNotFound:
377
 
            with excutils.save_and_reraise_exception() as ctxt:
378
 
                ctxt.reraise = False
379
 
                if self.sync_on_missing:
380
 
                    lsn_id = super(PersistentLsnManager, self).lsn_get(
381
 
                        context, network_id, raise_on_err=raise_on_err)
382
 
                    self.lsn_save(context, network_id, lsn_id)
383
 
                    return lsn_id
384
 
                if raise_on_err:
385
 
                    ctxt.reraise = True
386
 
 
387
 
    def lsn_save(self, context, network_id, lsn_id):
388
 
        """Save LSN-Network mapping to the DB."""
389
 
        try:
390
 
            lsn_db.lsn_add(context, network_id, lsn_id)
391
 
        except db_exc.DBError:
392
 
            err_msg = _('Unable to save LSN for network %s') % network_id
393
 
            LOG.exception(err_msg)
394
 
            raise p_exc.NsxPluginException(err_msg=err_msg)
395
 
 
396
 
    def lsn_create(self, context, network_id):
397
 
        lsn_id = super(PersistentLsnManager,
398
 
                       self).lsn_create(context, network_id)
399
 
        try:
400
 
            self.lsn_save(context, network_id, lsn_id)
401
 
        except p_exc.NsxPluginException:
402
 
            with excutils.save_and_reraise_exception():
403
 
                super(PersistentLsnManager, self).lsn_delete(context, lsn_id)
404
 
        return lsn_id
405
 
 
406
 
    def lsn_delete(self, context, lsn_id):
407
 
        lsn_db.lsn_remove(context, lsn_id)
408
 
        super(PersistentLsnManager, self).lsn_delete(context, lsn_id)
409
 
 
410
 
    def lsn_port_get(self, context, network_id, subnet_id, raise_on_err=True):
411
 
        try:
412
 
            obj = lsn_db.lsn_port_get_for_subnet(
413
 
                context, subnet_id, raise_on_err=raise_on_err)
414
 
            return (obj.lsn_id, obj.lsn_port_id) if obj else (None, None)
415
 
        except p_exc.LsnPortNotFound:
416
 
            with excutils.save_and_reraise_exception() as ctxt:
417
 
                ctxt.reraise = False
418
 
                if self.sync_on_missing:
419
 
                    lsn_id, lsn_port_id = (
420
 
                        super(PersistentLsnManager, self).lsn_port_get(
421
 
                            context, network_id, subnet_id,
422
 
                            raise_on_err=raise_on_err))
423
 
                    mac_addr = lsn_api.lsn_port_info_get(
424
 
                        self.cluster, lsn_id, lsn_port_id)['mac_address']
425
 
                    self.lsn_port_save(
426
 
                        context, lsn_port_id, subnet_id, mac_addr, lsn_id)
427
 
                    return (lsn_id, lsn_port_id)
428
 
                if raise_on_err:
429
 
                    ctxt.reraise = True
430
 
 
431
 
    def lsn_port_get_by_mac(self, context, network_id, mac, raise_on_err=True):
432
 
        try:
433
 
            obj = lsn_db.lsn_port_get_for_mac(
434
 
                context, mac, raise_on_err=raise_on_err)
435
 
            return (obj.lsn_id, obj.lsn_port_id) if obj else (None, None)
436
 
        except p_exc.LsnPortNotFound:
437
 
            with excutils.save_and_reraise_exception() as ctxt:
438
 
                ctxt.reraise = False
439
 
                if self.sync_on_missing:
440
 
                    lsn_id, lsn_port_id = (
441
 
                        super(PersistentLsnManager, self).lsn_port_get_by_mac(
442
 
                            context, network_id, mac,
443
 
                            raise_on_err=raise_on_err))
444
 
                    subnet_id = lsn_api.lsn_port_info_get(
445
 
                        self.cluster, lsn_id, lsn_port_id).get('subnet_id')
446
 
                    self.lsn_port_save(
447
 
                        context, lsn_port_id, subnet_id, mac, lsn_id)
448
 
                    return (lsn_id, lsn_port_id)
449
 
                if raise_on_err:
450
 
                    ctxt.reraise = True
451
 
 
452
 
    def lsn_port_save(self, context, lsn_port_id, subnet_id, mac_addr, lsn_id):
453
 
        """Save LSN Port information to the DB."""
454
 
        try:
455
 
            lsn_db.lsn_port_add_for_lsn(
456
 
                context, lsn_port_id, subnet_id, mac_addr, lsn_id)
457
 
        except db_exc.DBError:
458
 
            err_msg = _('Unable to save LSN port for subnet %s') % subnet_id
459
 
            LOG.exception(err_msg)
460
 
            raise p_exc.NsxPluginException(err_msg=err_msg)
461
 
 
462
 
    def lsn_port_create(self, context, lsn_id, subnet_info):
463
 
        lsn_port_id = super(PersistentLsnManager,
464
 
                            self).lsn_port_create(context, lsn_id, subnet_info)
465
 
        try:
466
 
            self.lsn_port_save(context, lsn_port_id, subnet_info['subnet_id'],
467
 
                               subnet_info['mac_address'], lsn_id)
468
 
        except p_exc.NsxPluginException:
469
 
            with excutils.save_and_reraise_exception():
470
 
                super(PersistentLsnManager, self).lsn_port_delete(
471
 
                    context, lsn_id, lsn_port_id)
472
 
        return lsn_port_id
473
 
 
474
 
    def lsn_port_delete(self, context, lsn_id, lsn_port_id):
475
 
        lsn_db.lsn_port_remove(context, lsn_port_id)
476
 
        super(PersistentLsnManager, self).lsn_port_delete(
477
 
            context, lsn_id, lsn_port_id)