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

« back to all changes in this revision

Viewing changes to neutron/plugins/nuage/plugin.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:
12
12
#    License for the specific language governing permissions and limitations
13
13
#    under the License.
14
14
 
15
 
import copy
16
 
import re
17
 
 
18
 
import netaddr
19
 
from oslo.config import cfg
20
 
from oslo.utils import excutils
21
 
from oslo.utils import importutils
22
 
from oslo_concurrency import lockutils
23
 
from sqlalchemy.orm import exc
24
 
 
25
 
from neutron.api import extensions as neutron_extensions
26
 
from neutron.api.v2 import attributes
27
 
from neutron.common import constants as os_constants
28
 
from neutron.common import exceptions as n_exc
29
 
from neutron.common import utils
30
 
from neutron.db import api as db
31
 
from neutron.db import db_base_plugin_v2
32
 
from neutron.db import external_net_db
33
 
from neutron.db import extraroute_db
34
 
from neutron.db import l3_db
35
 
from neutron.db import quota_db  # noqa
36
 
from neutron.db import securitygroups_db as sg_db
37
 
from neutron.extensions import external_net
38
 
from neutron.extensions import l3
39
 
from neutron.extensions import portbindings
40
 
from neutron.extensions import providernet as pnet
41
 
from neutron.extensions import securitygroup as ext_sg
42
 
from neutron.openstack.common import log as logging
43
 
from neutron.openstack.common import loopingcall
44
 
from neutron.plugins.nuage.common import config
45
 
from neutron.plugins.nuage.common import constants
46
 
from neutron.plugins.nuage.common import exceptions as nuage_exc
47
 
from neutron.plugins.nuage import extensions
48
 
from neutron.plugins.nuage.extensions import netpartition
49
 
from neutron.plugins.nuage import nuagedb
50
 
from neutron.plugins.nuage import syncmanager
51
 
from neutron import policy
52
 
 
53
 
LOG = logging.getLogger(__name__)
54
 
 
55
 
 
56
 
class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2,
57
 
                  external_net_db.External_net_db_mixin,
58
 
                  extraroute_db.ExtraRoute_db_mixin,
59
 
                  l3_db.L3_NAT_db_mixin,
60
 
                  netpartition.NetPartitionPluginBase,
61
 
                  sg_db.SecurityGroupDbMixin):
62
 
    """Class that implements Nuage Networks' plugin functionality."""
 
15
from nuage_neutron.plugins.nuage import plugin
 
16
 
 
17
 
 
18
class NuagePlugin(plugin.NuagePlugin):
 
19
 
 
20
    vendor_extensions = plugin.NuagePlugin.vendor_extensions
63
21
    supported_extension_aliases = ["router", "binding", "external-net",
64
 
                                   "net-partition", "nuage-router",
65
 
                                   "nuage-subnet", "quotas", "provider",
66
 
                                   "extraroute", "security-group"]
67
 
 
68
 
    binding_view = "extension:port_binding:view"
 
22
                                   "quotas", "provider", "extraroute",
 
23
                                   "security-group"] + vendor_extensions
69
24
 
70
25
    def __init__(self):
71
26
        super(NuagePlugin, self).__init__()
72
 
        neutron_extensions.append_api_extensions_path(extensions.__path__)
73
 
        config.nuage_register_cfg_opts()
74
 
        self.nuageclient_init()
75
 
        net_partition = cfg.CONF.RESTPROXY.default_net_partition_name
76
 
        self._create_default_net_partition(net_partition)
77
 
        if cfg.CONF.SYNCMANAGER.enable_sync:
78
 
            self.syncmanager = syncmanager.SyncManager(self.nuageclient)
79
 
            self._synchronization_thread()
80
 
 
81
 
    db_base_plugin_v2.NeutronDbPluginV2.register_dict_extend_funcs(
82
 
        attributes.NETWORKS, ['_extend_network_dict_provider_nuage'])
83
 
 
84
 
    def nuageclient_init(self):
85
 
        server = cfg.CONF.RESTPROXY.server
86
 
        serverauth = cfg.CONF.RESTPROXY.serverauth
87
 
        serverssl = cfg.CONF.RESTPROXY.serverssl
88
 
        base_uri = cfg.CONF.RESTPROXY.base_uri
89
 
        auth_resource = cfg.CONF.RESTPROXY.auth_resource
90
 
        organization = cfg.CONF.RESTPROXY.organization
91
 
        nuageclient = importutils.import_module('nuagenetlib.nuageclient')
92
 
        self.nuageclient = nuageclient.NuageClient(server, base_uri,
93
 
                                                   serverssl, serverauth,
94
 
                                                   auth_resource,
95
 
                                                   organization)
96
 
 
97
 
    def _synchronization_thread(self):
98
 
        sync_interval = cfg.CONF.SYNCMANAGER.sync_interval
99
 
        fip_quota = str(cfg.CONF.RESTPROXY.default_floatingip_quota)
100
 
        if sync_interval > 0:
101
 
            sync_loop = loopingcall.FixedIntervalLoopingCall(
102
 
                self.syncmanager.synchronize, fip_quota)
103
 
            sync_loop.start(interval=sync_interval)
104
 
        else:
105
 
            self.syncmanager.synchronize(fip_quota)
106
 
 
107
 
    def _resource_finder(self, context, for_resource, resource, user_req):
108
 
        match = re.match(attributes.UUID_PATTERN, user_req[resource])
109
 
        if match:
110
 
            obj_lister = getattr(self, "get_%s" % resource)
111
 
            found_resource = obj_lister(context, user_req[resource])
112
 
            if not found_resource:
113
 
                msg = (_("%(resource)s with id %(resource_id)s does not "
114
 
                         "exist") % {'resource': resource,
115
 
                                     'resource_id': user_req[resource]})
116
 
                raise n_exc.BadRequest(resource=for_resource, msg=msg)
117
 
        else:
118
 
            filter = {'name': [user_req[resource]]}
119
 
            obj_lister = getattr(self, "get_%ss" % resource)
120
 
            found_resource = obj_lister(context, filters=filter)
121
 
            if not found_resource:
122
 
                msg = (_("Either %(resource)s %(req_resource)s not found "
123
 
                         "or you dont have credential to access it")
124
 
                       % {'resource': resource,
125
 
                          'req_resource': user_req[resource]})
126
 
                raise n_exc.BadRequest(resource=for_resource, msg=msg)
127
 
            if len(found_resource) > 1:
128
 
                msg = (_("More than one entry found for %(resource)s "
129
 
                         "%(req_resource)s. Use id instead")
130
 
                       % {'resource': resource,
131
 
                          'req_resource': user_req[resource]})
132
 
                raise n_exc.BadRequest(resource=for_resource, msg=msg)
133
 
            found_resource = found_resource[0]
134
 
        return found_resource
135
 
 
136
 
    def _create_update_port(self, context, port, np_name):
137
 
        filters = {'device_id': [port['device_id']]}
138
 
        ports = self.get_ports(context, filters)
139
 
        params = {
140
 
            'port_id': port['id'],
141
 
            'id': port['device_id'],
142
 
            'mac': port['mac_address'],
143
 
            'netpart_name': np_name,
144
 
            'ip': port['fixed_ips'][0]['ip_address'],
145
 
            'no_of_ports': len(ports),
146
 
            'tenant': port['tenant_id'],
147
 
            'neutron_id': port['fixed_ips'][0]['subnet_id']
148
 
        }
149
 
        self.nuageclient.create_vms(params)
150
 
 
151
 
    def _get_router_by_subnet(self, context, subnet_id):
152
 
        filters = {
153
 
            'fixed_ips': {'subnet_id': [subnet_id]},
154
 
            'device_owner': [os_constants.DEVICE_OWNER_ROUTER_INTF]
155
 
        }
156
 
        router_port = self.get_ports(context, filters=filters)
157
 
        if not router_port:
158
 
            msg = (_("Router for subnet %s not found ") % subnet_id)
159
 
            raise n_exc.BadRequest(resource='port', msg=msg)
160
 
        return router_port[0]['device_id']
161
 
 
162
 
    def _process_port_create_security_group(self, context, port,
163
 
                                            sec_group):
164
 
        if not attributes.is_attr_set(sec_group):
165
 
            port[ext_sg.SECURITYGROUPS] = []
166
 
            return
167
 
        port_id = port['id']
168
 
        with context.session.begin(subtransactions=True):
169
 
            for sg_id in sec_group:
170
 
                super(NuagePlugin,
171
 
                      self)._create_port_security_group_binding(context,
172
 
                                                                port_id,
173
 
                                                                sg_id)
174
 
        try:
175
 
            vptag_vport_list = []
176
 
            for sg_id in sec_group:
177
 
                params = {
178
 
                    'neutron_port_id': port_id
179
 
                }
180
 
                nuage_port = self.nuageclient.get_nuage_port_by_id(params)
181
 
                if nuage_port and nuage_port.get('nuage_vport_id'):
182
 
                    nuage_vport_id = nuage_port['nuage_vport_id']
183
 
                    sg = self._get_security_group(context, sg_id)
184
 
                    sg_rules = self.get_security_group_rules(
185
 
                                        context,
186
 
                                        {'security_group_id': [sg_id]})
187
 
                    sg_params = {
188
 
                        'nuage_port': nuage_port,
189
 
                        'sg': sg,
190
 
                        'sg_rules': sg_rules
191
 
                    }
192
 
                    nuage_vptag_id = (
193
 
                        self.nuageclient.process_port_create_security_group(
194
 
                                                                    sg_params))
195
 
                    vptag_vport = {
196
 
                        'nuage_vporttag_id': nuage_vptag_id
197
 
                    }
198
 
                    vptag_vport_list.append(vptag_vport)
199
 
 
200
 
            if vptag_vport_list:
201
 
                params = {
202
 
                    'vptag_vport_list': vptag_vport_list,
203
 
                    'nuage_vport_id': nuage_vport_id
204
 
                }
205
 
                self.nuageclient.update_nuage_vport(params)
206
 
        except Exception:
207
 
            with excutils.save_and_reraise_exception():
208
 
                for sg_id in sec_group:
209
 
                    super(NuagePlugin,
210
 
                          self)._delete_port_security_group_bindings(context,
211
 
                                                                 port_id)
212
 
        # Convert to list as a set might be passed here and
213
 
        # this has to be serialized
214
 
        port[ext_sg.SECURITYGROUPS] = (list(sec_group) if sec_group else [])
215
 
 
216
 
    def _delete_port_security_group_bindings(self, context, port_id):
217
 
        super(NuagePlugin,
218
 
              self)._delete_port_security_group_bindings(context, port_id)
219
 
        self.nuageclient.delete_port_security_group_bindings(port_id)
220
 
 
221
 
    @lockutils.synchronized('create_port', 'nuage-port', external=True)
222
 
    def create_port(self, context, port):
223
 
        session = context.session
224
 
        with session.begin(subtransactions=True):
225
 
            p = port['port']
226
 
            self._ensure_default_security_group_on_port(context, port)
227
 
            port = super(NuagePlugin, self).create_port(context, port)
228
 
            device_owner = port.get('device_owner', None)
229
 
            if device_owner not in constants.AUTO_CREATE_PORT_OWNERS:
230
 
                if 'fixed_ips' not in port or len(port['fixed_ips']) == 0:
231
 
                    return self._extend_port_dict_binding(context, port)
232
 
                subnet_id = port['fixed_ips'][0]['subnet_id']
233
 
                subnet_mapping = nuagedb.get_subnet_l2dom_by_id(session,
234
 
                                                                subnet_id)
235
 
                if subnet_mapping:
236
 
                    port_prefix = constants.NOVA_PORT_OWNER_PREF
237
 
                    if port['device_owner'].startswith(port_prefix):
238
 
                        #This request is coming from nova
239
 
                        try:
240
 
                            net_partition = nuagedb.get_net_partition_by_id(
241
 
                                session,
242
 
                                subnet_mapping['net_partition_id'])
243
 
                            self._create_update_port(
244
 
                                context,
245
 
                                port,
246
 
                                net_partition['name'])
247
 
                        except Exception:
248
 
                            with excutils.save_and_reraise_exception():
249
 
                                super(NuagePlugin, self).delete_port(
250
 
                                    context,
251
 
                                    port['id'])
252
 
                    if ext_sg.SECURITYGROUPS in p:
253
 
                        self._process_port_create_security_group(
254
 
                            context,
255
 
                            port,
256
 
                            p[ext_sg.SECURITYGROUPS])
257
 
        return self._extend_port_dict_binding(context, port)
258
 
 
259
 
    def update_port(self, context, id, port):
260
 
        p = port['port']
261
 
        sg_groups = None
262
 
        if p.get('device_owner', '').startswith(
263
 
            constants.NOVA_PORT_OWNER_PREF):
264
 
            session = context.session
265
 
            with session.begin(subtransactions=True):
266
 
                port = self._get_port(context, id)
267
 
                port.update(p)
268
 
                if not port.get('fixed_ips'):
269
 
                    return self._make_port_dict(port)
270
 
                subnet_id = port['fixed_ips'][0]['subnet_id']
271
 
 
272
 
                subnet_mapping = nuagedb.get_subnet_l2dom_by_id(session,
273
 
                                                                subnet_id)
274
 
                if not subnet_mapping:
275
 
                    msg = (_("Subnet %s not found on VSD") % subnet_id)
276
 
                    raise n_exc.BadRequest(resource='port', msg=msg)
277
 
 
278
 
                params = {
279
 
                    'neutron_port_id': id,
280
 
                }
281
 
                nuage_port = self.nuageclient.get_nuage_port_by_id(params)
282
 
                if not nuage_port or not nuage_port.get('nuage_vport_id'):
283
 
                    net_partition = nuagedb.get_net_partition_by_id(
284
 
                        session, subnet_mapping['net_partition_id'])
285
 
                    self._create_update_port(context, port,
286
 
                                             net_partition['name'])
287
 
                self._check_floatingip_update(context, port)
288
 
                updated_port = self._make_port_dict(port)
289
 
                sg_port = self._extend_port_dict_security_group(
290
 
                    updated_port,
291
 
                    port
292
 
                )
293
 
                sg_groups = sg_port[ext_sg.SECURITYGROUPS]
294
 
        else:
295
 
            updated_port = super(NuagePlugin, self).update_port(context, id,
296
 
                                                                port)
297
 
            if not updated_port.get('fixed_ips'):
298
 
                return updated_port
299
 
            subnet_id = updated_port['fixed_ips'][0]['subnet_id']
300
 
            subnet_mapping = nuagedb.get_subnet_l2dom_by_id(context.session,
301
 
                                                            subnet_id)
302
 
        if subnet_mapping:
303
 
            if sg_groups:
304
 
                self._delete_port_security_group_bindings(context,
305
 
                                                          updated_port['id'])
306
 
                self._process_port_create_security_group(context,
307
 
                                                         updated_port,
308
 
                                                         sg_groups)
309
 
            elif ext_sg.SECURITYGROUPS in p:
310
 
                self._delete_port_security_group_bindings(context,
311
 
                                                          updated_port['id'])
312
 
                self._process_port_create_security_group(
313
 
                    context,
314
 
                    updated_port,
315
 
                    p[ext_sg.SECURITYGROUPS]
316
 
                )
317
 
        return updated_port
318
 
 
319
 
    def _delete_nuage_vport(self, context, port, np_name):
320
 
        nuage_vif_id = None
321
 
        params = {
322
 
            'neutron_port_id': port['id'],
323
 
        }
324
 
        nuage_port = self.nuageclient.get_nuage_port_by_id(params)
325
 
 
326
 
        if constants.NOVA_PORT_OWNER_PREF in port['device_owner']:
327
 
            # This was a VM Port
328
 
            if nuage_port:
329
 
                nuage_vif_id = nuage_port['nuage_vif_id']
330
 
            filters = {'device_id': [port['device_id']]}
331
 
            ports = self.get_ports(context, filters)
332
 
            params = {
333
 
                'no_of_ports': len(ports),
334
 
                'netpart_name': np_name,
335
 
                'tenant': port['tenant_id'],
336
 
                'mac': port['mac_address'],
337
 
                'nuage_vif_id': nuage_vif_id,
338
 
                'id': port['device_id']
339
 
            }
340
 
            self.nuageclient.delete_vms(params)
341
 
 
342
 
    @lockutils.synchronized('delete-port', 'nuage-del', external=True)
343
 
    def delete_port(self, context, id, l3_port_check=True):
344
 
        if l3_port_check:
345
 
            self.prevent_l3_port_deletion(context, id)
346
 
        port = self._get_port(context, id)
347
 
        # This is required for to pass ut test_floatingip_port_delete
348
 
        self.disassociate_floatingips(context, id)
349
 
        if not port['fixed_ips']:
350
 
            return super(NuagePlugin, self).delete_port(context, id)
351
 
 
352
 
        sub_id = port['fixed_ips'][0]['subnet_id']
353
 
 
354
 
        subnet_mapping = nuagedb.get_subnet_l2dom_by_id(context.session,
355
 
                                                        sub_id)
356
 
        if not subnet_mapping:
357
 
            return super(NuagePlugin, self).delete_port(context, id)
358
 
 
359
 
        # Need to call this explicitly to delete vport to vporttag binding
360
 
        if ext_sg.SECURITYGROUPS in port:
361
 
            self.nuageclient.delete_port_security_group_bindings(id)
362
 
 
363
 
        netpart_id = subnet_mapping['net_partition_id']
364
 
        net_partition = nuagedb.get_net_partition_by_id(context.session,
365
 
                                                        netpart_id)
366
 
        self._delete_nuage_vport(context, port, net_partition['name'])
367
 
        super(NuagePlugin, self).delete_port(context, id)
368
 
 
369
 
    def _check_view_auth(self, context, resource, action):
370
 
        return policy.check(context, action, resource)
371
 
 
372
 
    def _extend_port_dict_binding(self, context, port):
373
 
        if self._check_view_auth(context, port, self.binding_view):
374
 
            port[portbindings.VIF_TYPE] = portbindings.VIF_TYPE_OVS
375
 
            port[portbindings.VIF_DETAILS] = {
376
 
                portbindings.CAP_PORT_FILTER: False
377
 
            }
378
 
        return port
379
 
 
380
 
    def get_port(self, context, id, fields=None):
381
 
        port = super(NuagePlugin, self).get_port(context, id, fields)
382
 
        return self._fields(self._extend_port_dict_binding(context, port),
383
 
                            fields)
384
 
 
385
 
    def get_ports(self, context, filters=None, fields=None):
386
 
        ports = super(NuagePlugin, self).get_ports(context, filters, fields)
387
 
        return [self._fields(self._extend_port_dict_binding(context, port),
388
 
                             fields) for port in ports]
389
 
 
390
 
    def _check_router_subnet_for_tenant(self, context, tenant_id):
391
 
        # Search router and subnet tables.
392
 
        # If no entry left delete user and group from VSD
393
 
        filters = {'tenant_id': [tenant_id]}
394
 
        routers = self.get_routers(context, filters=filters)
395
 
        subnets = self.get_subnets(context, filters=filters)
396
 
        return bool(routers or subnets)
397
 
 
398
 
    def _extend_network_dict_provider_nuage(self, network, net_db,
399
 
                                            net_binding=None):
400
 
        binding = net_db.pnetbinding if net_db else net_binding
401
 
        if binding:
402
 
            network[pnet.NETWORK_TYPE] = binding.network_type
403
 
            network[pnet.PHYSICAL_NETWORK] = binding.physical_network
404
 
            network[pnet.SEGMENTATION_ID] = binding.vlan_id
405
 
 
406
 
    def _process_provider_create(self, context, attrs):
407
 
        network_type = attrs.get(pnet.NETWORK_TYPE)
408
 
        physical_network = attrs.get(pnet.PHYSICAL_NETWORK)
409
 
        segmentation_id = attrs.get(pnet.SEGMENTATION_ID)
410
 
 
411
 
        network_type_set = attributes.is_attr_set(network_type)
412
 
        physical_network_set = attributes.is_attr_set(physical_network)
413
 
        segmentation_id_set = attributes.is_attr_set(segmentation_id)
414
 
 
415
 
        if not (network_type_set or physical_network_set or
416
 
                segmentation_id_set):
417
 
            return None, None, None
418
 
        if not network_type_set:
419
 
            msg = _("provider:network_type required")
420
 
            raise n_exc.InvalidInput(error_message=msg)
421
 
        elif network_type != 'vlan':
422
 
            msg = (_("provider:network_type %s not supported in VSP")
423
 
                   % network_type)
424
 
            raise nuage_exc.NuageBadRequest(msg=msg)
425
 
        if not physical_network_set:
426
 
            msg = _("provider:physical_network required")
427
 
            raise nuage_exc.NuageBadRequest(msg=msg)
428
 
        if not segmentation_id_set:
429
 
            msg = _("provider:segmentation_id required")
430
 
            raise nuage_exc.NuageBadRequest(msg=msg)
431
 
 
432
 
        self.nuageclient.validate_provider_network(network_type,
433
 
                                                   physical_network,
434
 
                                                   segmentation_id)
435
 
 
436
 
        return network_type, physical_network, segmentation_id
437
 
 
438
 
    def create_network(self, context, network):
439
 
        binding = None
440
 
        (network_type, physical_network,
441
 
         vlan_id) = self._process_provider_create(context,
442
 
                                                  network['network'])
443
 
        with context.session.begin(subtransactions=True):
444
 
            self._ensure_default_security_group(
445
 
                context,
446
 
                network['network']['tenant_id']
447
 
            )
448
 
            net = super(NuagePlugin, self).create_network(context,
449
 
                                                          network)
450
 
            self._process_l3_create(context, net, network['network'])
451
 
            if network_type == 'vlan':
452
 
                binding = nuagedb.add_network_binding(context.session,
453
 
                                            net['id'],
454
 
                                            network_type,
455
 
                                            physical_network, vlan_id)
456
 
            self._extend_network_dict_provider_nuage(net, None, binding)
457
 
        return net
458
 
 
459
 
    def _validate_update_network(self, context, id, network):
460
 
        req_data = network['network']
461
 
        is_external_set = req_data.get(external_net.EXTERNAL)
462
 
        if not attributes.is_attr_set(is_external_set):
463
 
            return (None, None)
464
 
        neutron_net = self.get_network(context, id)
465
 
        if neutron_net.get(external_net.EXTERNAL) == is_external_set:
466
 
            return (None, None)
467
 
        subnet = self._validate_nuage_sharedresource(context, 'network', id)
468
 
        if subnet and not is_external_set:
469
 
            msg = _('External network with subnets can not be '
470
 
                    'changed to non-external network')
471
 
            raise nuage_exc.OperationNotSupported(msg=msg)
472
 
        if is_external_set:
473
 
            # Check if there are vm ports attached to this network
474
 
            # If there are, then updating the network is not allowed
475
 
            ports = self.get_ports(context, filters={'network_id': [id]})
476
 
            for p in ports:
477
 
                if p['device_owner'].startswith(
478
 
                        constants.NOVA_PORT_OWNER_PREF):
479
 
                    raise n_exc.NetworkInUse(net_id=id)
480
 
        return (is_external_set, subnet)
481
 
 
482
 
    def update_network(self, context, id, network):
483
 
        pnet._raise_if_updates_provider_attributes(network['network'])
484
 
        with context.session.begin(subtransactions=True):
485
 
            is_external_set, subnet = self._validate_update_network(context,
486
 
                                                                    id,
487
 
                                                                    network)
488
 
            net = super(NuagePlugin, self).update_network(context, id,
489
 
                                                          network)
490
 
            self._process_l3_update(context, net, network['network'])
491
 
            if subnet and is_external_set:
492
 
                subn = subnet[0]
493
 
                subnet_l2dom = nuagedb.get_subnet_l2dom_by_id(context.session,
494
 
                                                              subn['id'])
495
 
                if subnet_l2dom:
496
 
                    user_id = subnet_l2dom['nuage_user_id']
497
 
                    group_id = subnet_l2dom['nuage_group_id']
498
 
                    self.nuageclient.delete_subnet(subn['id'])
499
 
                    nuagedb.delete_subnetl2dom_mapping(context.session,
500
 
                                                       subnet_l2dom)
501
 
                    if not self._check_router_subnet_for_tenant(
502
 
                            context, subn['tenant_id']):
503
 
                        self.nuageclient.delete_user(user_id)
504
 
                        self.nuageclient.delete_group(group_id)
505
 
 
506
 
                    self._add_nuage_sharedresource(subnet[0],
507
 
                                                   id,
508
 
                                                   constants.SR_TYPE_FLOATING)
509
 
        return net
510
 
 
511
 
    def delete_network(self, context, id):
512
 
        with context.session.begin(subtransactions=True):
513
 
            self._process_l3_delete(context, id)
514
 
            filter = {'network_id': [id]}
515
 
            subnets = self.get_subnets(context, filters=filter)
516
 
            for subnet in subnets:
517
 
                self.delete_subnet(context, subnet['id'])
518
 
            super(NuagePlugin, self).delete_network(context, id)
519
 
 
520
 
    def _get_net_partition_for_subnet(self, context, subnet):
521
 
        ent = subnet.get('net_partition', None)
522
 
        if not ent:
523
 
            def_net_part = cfg.CONF.RESTPROXY.default_net_partition_name
524
 
            net_partition = nuagedb.get_net_partition_by_name(context.session,
525
 
                                                              def_net_part)
526
 
        else:
527
 
            net_partition = self._resource_finder(context, 'subnet',
528
 
                                                  'net_partition', subnet)
529
 
        if not net_partition:
530
 
            msg = _('Either net_partition is not provided with subnet OR '
531
 
                    'default net_partition is not created at the start')
532
 
            raise n_exc.BadRequest(resource='subnet', msg=msg)
533
 
        return net_partition
534
 
 
535
 
    @staticmethod
536
 
    def _validate_create_subnet(subnet):
537
 
        if (attributes.is_attr_set(subnet['gateway_ip'])
538
 
            and netaddr.IPAddress(subnet['gateway_ip'])
539
 
            not in netaddr.IPNetwork(subnet['cidr'])):
540
 
            msg = "Gateway IP outside of the subnet CIDR "
541
 
            raise nuage_exc.NuageBadRequest(msg=msg)
542
 
 
543
 
    def _validate_create_provider_subnet(self, context, net_id):
544
 
        net_filter = {'network_id': [net_id]}
545
 
        existing_subn = self.get_subnets(context, filters=net_filter)
546
 
        if len(existing_subn) > 0:
547
 
            msg = _('Only one subnet is allowed per '
548
 
                    'Provider network %s') % net_id
549
 
            raise nuage_exc.OperationNotSupported(msg=msg)
550
 
 
551
 
    def _delete_nuage_sharedresource(self, net_id):
552
 
        self.nuageclient.delete_nuage_sharedresource(net_id)
553
 
 
554
 
    def _validate_nuage_sharedresource(self, context, resource, net_id):
555
 
        filter = {'network_id': [net_id]}
556
 
        existing_subn = self.get_subnets(context, filters=filter)
557
 
        if len(existing_subn) > 1:
558
 
            msg = _('Only one subnet is allowed per '
559
 
                    'external network %s') % net_id
560
 
            raise nuage_exc.OperationNotSupported(msg=msg)
561
 
        return existing_subn
562
 
 
563
 
    def _add_nuage_sharedresource(self, subnet, net_id, type):
564
 
        net = netaddr.IPNetwork(subnet['cidr'])
565
 
        params = {
566
 
            'neutron_subnet': subnet,
567
 
            'net': net,
568
 
            'type': type,
569
 
            'net_id': net_id
570
 
        }
571
 
        self.nuageclient.create_nuage_sharedresource(params)
572
 
 
573
 
    def _create_nuage_sharedresource(self, context, subnet, type):
574
 
        subn = subnet['subnet']
575
 
        net_id = subn['network_id']
576
 
        self._validate_nuage_sharedresource(context, 'subnet', net_id)
577
 
        with context.session.begin(subtransactions=True):
578
 
            subn = super(NuagePlugin, self).create_subnet(context, subnet)
579
 
            self._add_nuage_sharedresource(subn, net_id, type)
580
 
            return subn
581
 
 
582
 
    def _create_port_gateway(self, context, subnet, gw_ip=None):
583
 
        if gw_ip is not None:
584
 
            fixed_ip = [{'ip_address': gw_ip, 'subnet_id': subnet['id']}]
585
 
        else:
586
 
            fixed_ip = [{'subnet_id': subnet['id']}]
587
 
 
588
 
        port_dict = dict(port=dict(
589
 
            name='',
590
 
            device_id='',
591
 
            admin_state_up=True,
592
 
            network_id=subnet['network_id'],
593
 
            tenant_id=subnet['tenant_id'],
594
 
            fixed_ips=fixed_ip,
595
 
            mac_address=attributes.ATTR_NOT_SPECIFIED,
596
 
            device_owner=os_constants.DEVICE_OWNER_DHCP))
597
 
        port = super(NuagePlugin, self).create_port(context, port_dict)
598
 
        return port
599
 
 
600
 
    def _delete_port_gateway(self, context, ports):
601
 
        for port in ports:
602
 
            super(NuagePlugin, self).delete_port(context, port['id'])
603
 
 
604
 
    def _create_nuage_subnet(self, context, neutron_subnet, netpart_id,
605
 
                             l2dom_template_id, pnet_binding):
606
 
        net = netaddr.IPNetwork(neutron_subnet['cidr'])
607
 
        # list(net)[-1] is the broadcast
608
 
        last_address = neutron_subnet['allocation_pools'][-1]['end']
609
 
        gw_port = self._create_port_gateway(context, neutron_subnet,
610
 
                                            last_address)
611
 
        params = {
612
 
            'netpart_id': netpart_id,
613
 
            'tenant_id': neutron_subnet['tenant_id'],
614
 
            'net': net,
615
 
            'l2dom_tmplt_id': l2dom_template_id,
616
 
            'pnet_binding': pnet_binding,
617
 
            'dhcp_ip': gw_port['fixed_ips'][0]['ip_address']
618
 
        }
619
 
        try:
620
 
            nuage_subnet = self.nuageclient.create_subnet(neutron_subnet,
621
 
                                                          params)
622
 
        except Exception:
623
 
            with excutils.save_and_reraise_exception():
624
 
                self._delete_port_gateway(context, [gw_port])
625
 
                super(NuagePlugin, self).delete_subnet(context,
626
 
                                                       neutron_subnet['id'])
627
 
 
628
 
        if nuage_subnet:
629
 
            l2dom_id = str(nuage_subnet['nuage_l2template_id'])
630
 
            user_id = nuage_subnet['nuage_userid']
631
 
            group_id = nuage_subnet['nuage_groupid']
632
 
            id = nuage_subnet['nuage_l2domain_id']
633
 
            with context.session.begin(subtransactions=True):
634
 
                nuagedb.add_subnetl2dom_mapping(context.session,
635
 
                                                neutron_subnet['id'],
636
 
                                                id,
637
 
                                                netpart_id,
638
 
                                                l2dom_id=l2dom_id,
639
 
                                                nuage_user_id=user_id,
640
 
                                                nuage_group_id=group_id)
641
 
 
642
 
    def create_subnet(self, context, subnet):
643
 
        subn = subnet['subnet']
644
 
        net_id = subn['network_id']
645
 
 
646
 
        if self._network_is_external(context, net_id):
647
 
            return self._create_nuage_sharedresource(
648
 
                context, subnet, constants.SR_TYPE_FLOATING)
649
 
        pnet_binding = nuagedb.get_network_binding(context.session, net_id)
650
 
        if pnet_binding:
651
 
            self._validate_create_provider_subnet(context, net_id)
652
 
 
653
 
        self._validate_create_subnet(subn)
654
 
 
655
 
        net_partition = self._get_net_partition_for_subnet(context, subn)
656
 
        neutron_subnet = super(NuagePlugin, self).create_subnet(context,
657
 
                                                                subnet)
658
 
        self._create_nuage_subnet(context, neutron_subnet, net_partition['id'],
659
 
                                  subn['nuage_subnet_template'],
660
 
                                  pnet_binding)
661
 
        return neutron_subnet
662
 
 
663
 
    def update_subnet(self, context, id, subnet):
664
 
        subn = copy.deepcopy(subnet['subnet'])
665
 
        subnet_l2dom = nuagedb.get_subnet_l2dom_by_id(context.session,
666
 
                                                      id)
667
 
        params = {
668
 
            'parent_id': subnet_l2dom['nuage_subnet_id'],
669
 
            'type': subnet_l2dom['nuage_l2dom_tmplt_id']
670
 
        }
671
 
        with context.session.begin(subtransactions=True):
672
 
            neutron_subnet = super(NuagePlugin, self).update_subnet(context,
673
 
                                                                    id, subnet)
674
 
            self.nuageclient.update_subnet(subn, params)
675
 
            return neutron_subnet
676
 
 
677
 
    def delete_subnet(self, context, id):
678
 
        subnet = self.get_subnet(context, id)
679
 
        if self._network_is_external(context, subnet['network_id']):
680
 
            super(NuagePlugin, self).delete_subnet(context, id)
681
 
            return self._delete_nuage_sharedresource(id)
682
 
 
683
 
        filters = {'fixed_ips': {'subnet_id': [id]}}
684
 
        ports = self.get_ports(context, filters)
685
 
        for port in ports:
686
 
            if port['device_owner'] != os_constants.DEVICE_OWNER_DHCP:
687
 
                raise n_exc.SubnetInUse(subnet_id=id)
688
 
 
689
 
        subnet_l2dom = nuagedb.get_subnet_l2dom_by_id(context.session, id)
690
 
        if subnet_l2dom:
691
 
            try:
692
 
                self.nuageclient.delete_subnet(id)
693
 
            except Exception:
694
 
                msg = (_('Unable to complete operation on subnet %s.'
695
 
                         'One or more ports have an IP allocation '
696
 
                         'from this subnet.') % id)
697
 
                raise n_exc.BadRequest(resource='subnet', msg=msg)
698
 
        super(NuagePlugin, self).delete_subnet(context, id)
699
 
        if subnet_l2dom and not self._check_router_subnet_for_tenant(
700
 
                context, subnet['tenant_id']):
701
 
            self.nuageclient.delete_user(subnet_l2dom['nuage_user_id'])
702
 
            self.nuageclient.delete_group(subnet_l2dom['nuage_group_id'])
703
 
 
704
 
    def add_router_interface(self, context, router_id, interface_info):
705
 
        session = context.session
706
 
        with session.begin(subtransactions=True):
707
 
            rtr_if_info = super(NuagePlugin,
708
 
                                self).add_router_interface(context,
709
 
                                                           router_id,
710
 
                                                           interface_info)
711
 
            subnet_id = rtr_if_info['subnet_id']
712
 
            subn = self.get_subnet(context, subnet_id)
713
 
            ent_rtr_mapping = nuagedb.get_ent_rtr_mapping_by_rtrid(session,
714
 
                                                                   router_id)
715
 
            nuage_zone = self.nuageclient.get_zone_by_routerid(router_id)
716
 
            if not nuage_zone or not ent_rtr_mapping:
717
 
                super(NuagePlugin,
718
 
                      self).remove_router_interface(context,
719
 
                                                    router_id,
720
 
                                                    interface_info)
721
 
                msg = (_("Router %s does not hold default zone OR "
722
 
                         "domain in VSD. Router-IF add failed")
723
 
                       % router_id)
724
 
                raise n_exc.BadRequest(resource='router', msg=msg)
725
 
 
726
 
            subnet_l2dom = nuagedb.get_subnet_l2dom_by_id(session,
727
 
                                                          subnet_id)
728
 
            if not subnet_l2dom:
729
 
                super(NuagePlugin,
730
 
                      self).remove_router_interface(context,
731
 
                                                    router_id,
732
 
                                                    interface_info)
733
 
                msg = (_("Subnet %s does not hold Nuage VSD reference. "
734
 
                         "Router-IF add failed") % subnet_id)
735
 
                raise n_exc.BadRequest(resource='subnet', msg=msg)
736
 
 
737
 
            if (subnet_l2dom['net_partition_id'] !=
738
 
                ent_rtr_mapping['net_partition_id']):
739
 
                super(NuagePlugin,
740
 
                      self).remove_router_interface(context,
741
 
                                                    router_id,
742
 
                                                    interface_info)
743
 
                msg = (_("Subnet %(subnet)s and Router %(router)s belong to "
744
 
                         "different net_partition Router-IF add "
745
 
                         "not permitted") % {'subnet': subnet_id,
746
 
                                             'router': router_id})
747
 
                raise n_exc.BadRequest(resource='subnet', msg=msg)
748
 
            nuage_subnet_id = subnet_l2dom['nuage_subnet_id']
749
 
            if self.nuageclient.vms_on_l2domain(nuage_subnet_id):
750
 
                super(NuagePlugin,
751
 
                      self).remove_router_interface(context,
752
 
                                                    router_id,
753
 
                                                    interface_info)
754
 
                msg = (_("Subnet %s has one or more active VMs "
755
 
                       "Router-IF add not permitted") % subnet_id)
756
 
                raise n_exc.BadRequest(resource='subnet', msg=msg)
757
 
            self.nuageclient.delete_subnet(subnet_id)
758
 
            net = netaddr.IPNetwork(subn['cidr'])
759
 
            pnet_binding = nuagedb.get_network_binding(context.session,
760
 
                                                       subn['network_id'])
761
 
            params = {
762
 
                'net': net,
763
 
                'zone_id': nuage_zone['nuage_zone_id'],
764
 
                'neutron_subnet_id': subnet_id,
765
 
                'pnet_binding': pnet_binding
766
 
            }
767
 
            if not attributes.is_attr_set(subn['gateway_ip']):
768
 
                subn['gateway_ip'] = str(netaddr.IPAddress(net.first + 1))
769
 
 
770
 
            try:
771
 
                nuage_subnet = self.nuageclient.create_domain_subnet(subn,
772
 
                                                                   params)
773
 
            except Exception:
774
 
                with excutils.save_and_reraise_exception():
775
 
                    super(NuagePlugin,
776
 
                          self).remove_router_interface(context,
777
 
                                                        router_id,
778
 
                                                        interface_info)
779
 
 
780
 
            if nuage_subnet:
781
 
                ns_dict = {}
782
 
                ns_dict['nuage_subnet_id'] = nuage_subnet['nuage_subnetid']
783
 
                ns_dict['nuage_l2dom_tmplt_id'] = None
784
 
                nuagedb.update_subnetl2dom_mapping(subnet_l2dom,
785
 
                                                   ns_dict)
786
 
 
787
 
        return rtr_if_info
788
 
 
789
 
    def remove_router_interface(self, context, router_id, interface_info):
790
 
        if 'subnet_id' in interface_info:
791
 
            subnet_id = interface_info['subnet_id']
792
 
            subnet = self.get_subnet(context, subnet_id)
793
 
            found = False
794
 
            try:
795
 
                filters = {'device_id': [router_id],
796
 
                           'device_owner':
797
 
                           [os_constants.DEVICE_OWNER_ROUTER_INTF],
798
 
                           'network_id': [subnet['network_id']]}
799
 
                ports = self.get_ports(context, filters)
800
 
 
801
 
                for p in ports:
802
 
                    if p['fixed_ips'][0]['subnet_id'] == subnet_id:
803
 
                        found = True
804
 
                        break
805
 
            except exc.NoResultFound:
806
 
                msg = (_("No router interface found for Router %s. "
807
 
                         "Router-IF delete failed") % router_id)
808
 
                raise n_exc.BadRequest(resource='router', msg=msg)
809
 
 
810
 
            if not found:
811
 
                msg = (_("No router interface found for Router %s. "
812
 
                         "Router-IF delete failed") % router_id)
813
 
                raise n_exc.BadRequest(resource='router', msg=msg)
814
 
        elif 'port_id' in interface_info:
815
 
            port_db = self._get_port(context, interface_info['port_id'])
816
 
            if not port_db:
817
 
                msg = (_("No router interface found for Router %s. "
818
 
                         "Router-IF delete failed") % router_id)
819
 
                raise n_exc.BadRequest(resource='router', msg=msg)
820
 
            subnet_id = port_db['fixed_ips'][0]['subnet_id']
821
 
 
822
 
        session = context.session
823
 
        with session.begin(subtransactions=True):
824
 
            subnet_l2dom = nuagedb.get_subnet_l2dom_by_id(session,
825
 
                                                          subnet_id)
826
 
            if not subnet_l2dom:
827
 
                return super(NuagePlugin,
828
 
                             self).remove_router_interface(context,
829
 
                                                           router_id,
830
 
                                                           interface_info)
831
 
            nuage_subn_id = subnet_l2dom['nuage_subnet_id']
832
 
            if self.nuageclient.vms_on_subnet(nuage_subn_id):
833
 
                msg = (_("Subnet %s has one or more active VMs "
834
 
                         "Router-IF delete not permitted") % subnet_id)
835
 
                raise n_exc.BadRequest(resource='subnet', msg=msg)
836
 
 
837
 
            neutron_subnet = self.get_subnet(context, subnet_id)
838
 
            ent_rtr_mapping = nuagedb.get_ent_rtr_mapping_by_rtrid(
839
 
                context.session,
840
 
                router_id)
841
 
            if not ent_rtr_mapping:
842
 
                msg = (_("Router %s does not hold net_partition "
843
 
                         "assoc on Nuage VSD. Router-IF delete failed")
844
 
                       % router_id)
845
 
                raise n_exc.BadRequest(resource='router', msg=msg)
846
 
 
847
 
            net = netaddr.IPNetwork(neutron_subnet['cidr'])
848
 
            netpart_id = ent_rtr_mapping['net_partition_id']
849
 
            pnet_binding = nuagedb.get_network_binding(
850
 
                context.session, neutron_subnet['network_id'])
851
 
            params = {
852
 
                'tenant_id': neutron_subnet['tenant_id'],
853
 
                'net': net,
854
 
                'netpart_id': netpart_id,
855
 
                'nuage_subn_id': nuage_subn_id,
856
 
                'neutron_subnet': neutron_subnet,
857
 
                'pnet_binding': pnet_binding
858
 
            }
859
 
            nuage_subnet = self.nuageclient.remove_router_interface(params)
860
 
            info = super(NuagePlugin,
861
 
                         self).remove_router_interface(context, router_id,
862
 
                                                       interface_info)
863
 
 
864
 
            if nuage_subnet:
865
 
                tmplt_id = str(nuage_subnet['nuage_l2template_id'])
866
 
                ns_dict = {}
867
 
                ns_dict['nuage_subnet_id'] = nuage_subnet['nuage_l2domain_id']
868
 
                ns_dict['nuage_l2dom_tmplt_id'] = tmplt_id
869
 
                nuagedb.update_subnetl2dom_mapping(subnet_l2dom,
870
 
                                                   ns_dict)
871
 
        return info
872
 
 
873
 
    def _get_net_partition_for_router(self, context, rtr):
874
 
        ent = rtr.get('net_partition', None)
875
 
        if not ent:
876
 
            def_net_part = cfg.CONF.RESTPROXY.default_net_partition_name
877
 
            net_partition = nuagedb.get_net_partition_by_name(context.session,
878
 
                                                              def_net_part)
879
 
        else:
880
 
            net_partition = self._resource_finder(context, 'router',
881
 
                                                  'net_partition', rtr)
882
 
        if not net_partition:
883
 
            msg = _("Either net_partition is not provided with router OR "
884
 
                    "default net_partition is not created at the start")
885
 
            raise n_exc.BadRequest(resource='router', msg=msg)
886
 
        return net_partition
887
 
 
888
 
    def create_router(self, context, router):
889
 
        net_partition = self._get_net_partition_for_router(context, router)
890
 
        neutron_router = super(NuagePlugin, self).create_router(context,
891
 
                                                                router)
892
 
        params = {
893
 
            'net_partition': net_partition,
894
 
            'tenant_id': neutron_router['tenant_id']
895
 
        }
896
 
        try:
897
 
            nuage_router = self.nuageclient.create_router(neutron_router,
898
 
                                                          router['router'],
899
 
                                                          params)
900
 
        except Exception:
901
 
            with excutils.save_and_reraise_exception():
902
 
                super(NuagePlugin, self).delete_router(context,
903
 
                                                       neutron_router['id'])
904
 
 
905
 
        if nuage_router:
906
 
            with context.session.begin(subtransactions=True):
907
 
                nuagedb.add_entrouter_mapping(context.session,
908
 
                                              net_partition['id'],
909
 
                                              neutron_router['id'],
910
 
                                              nuage_router['nuage_domain_id'])
911
 
 
912
 
        return neutron_router
913
 
 
914
 
    def _validate_nuage_staticroutes(self, old_routes, added, removed):
915
 
        cidrs = []
916
 
        for old in old_routes:
917
 
            if old not in removed:
918
 
                ip = netaddr.IPNetwork(old['destination'])
919
 
                cidrs.append(ip)
920
 
        for route in added:
921
 
            ip = netaddr.IPNetwork(route['destination'])
922
 
            matching = netaddr.all_matching_cidrs(ip.ip, cidrs)
923
 
            if matching:
924
 
                msg = _('for same subnet, multiple static routes not allowed')
925
 
                raise n_exc.BadRequest(resource='router', msg=msg)
926
 
            cidrs.append(ip)
927
 
 
928
 
    def update_router(self, context, id, router):
929
 
        r = router['router']
930
 
        with context.session.begin(subtransactions=True):
931
 
            if 'routes' in r:
932
 
                old_routes = self._get_extra_routes_by_router_id(context,
933
 
                                                                 id)
934
 
                added, removed = utils.diff_list_of_dict(old_routes,
935
 
                                                         r['routes'])
936
 
                self._validate_nuage_staticroutes(old_routes, added, removed)
937
 
 
938
 
                ent_rtr_mapping = nuagedb.get_ent_rtr_mapping_by_rtrid(
939
 
                    context.session, id)
940
 
                if not ent_rtr_mapping:
941
 
                    msg = (_("Router %s does not hold net-partition "
942
 
                             "assoc on VSD. extra-route failed") % id)
943
 
                    raise n_exc.BadRequest(resource='router', msg=msg)
944
 
                # Let it do internal checks first and verify it.
945
 
                router_updated = super(NuagePlugin,
946
 
                                       self).update_router(context,
947
 
                                                           id,
948
 
                                                           router)
949
 
                for route in removed:
950
 
                    destaddr = route['destination']
951
 
                    cidr = destaddr.split('/')
952
 
                    params = {
953
 
                        "address": cidr[0],
954
 
                        "nexthop": route['nexthop'],
955
 
                        "nuage_domain_id": ent_rtr_mapping['nuage_router_id']
956
 
                    }
957
 
                    self.nuageclient.delete_nuage_staticroute(params)
958
 
 
959
 
                for route in added:
960
 
                    params = {
961
 
                        'parent_id': ent_rtr_mapping['nuage_router_id'],
962
 
                        'net': netaddr.IPNetwork(route['destination']),
963
 
                        'nexthop': route['nexthop']
964
 
                    }
965
 
                    self.nuageclient.create_nuage_staticroute(
966
 
                        params)
967
 
            else:
968
 
                router_updated = super(NuagePlugin, self).update_router(
969
 
                    context, id, router)
970
 
        return router_updated
971
 
 
972
 
    def delete_router(self, context, id):
973
 
        neutron_router = self.get_router(context, id)
974
 
        session = context.session
975
 
        ent_rtr_mapping = nuagedb.get_ent_rtr_mapping_by_rtrid(session,
976
 
                                                               id)
977
 
        if ent_rtr_mapping:
978
 
            filters = {
979
 
                'device_id': [id],
980
 
                'device_owner': [os_constants.DEVICE_OWNER_ROUTER_INTF]
981
 
            }
982
 
            ports = self.get_ports(context, filters)
983
 
            if ports:
984
 
                raise l3.RouterInUse(router_id=id)
985
 
            nuage_domain_id = ent_rtr_mapping['nuage_router_id']
986
 
            self.nuageclient.delete_router(nuage_domain_id)
987
 
 
988
 
        super(NuagePlugin, self).delete_router(context, id)
989
 
 
990
 
        if not self._check_router_subnet_for_tenant(
991
 
                context, neutron_router['tenant_id']):
992
 
            user_id, group_id = self.nuageclient.get_usergroup(
993
 
                neutron_router['tenant_id'],
994
 
                ent_rtr_mapping['net_partition_id'])
995
 
            self.nuageclient.delete_user(user_id)
996
 
            self.nuageclient.delete_group(group_id)
997
 
 
998
 
    def _make_net_partition_dict(self, net_partition, fields=None):
999
 
        res = {
1000
 
            'id': net_partition['id'],
1001
 
            'name': net_partition['name'],
1002
 
            'l3dom_tmplt_id': net_partition['l3dom_tmplt_id'],
1003
 
            'l2dom_tmplt_id': net_partition['l2dom_tmplt_id'],
1004
 
        }
1005
 
        return self._fields(res, fields)
1006
 
 
1007
 
    def _create_net_partition(self, session, net_part_name):
1008
 
        fip_quota = cfg.CONF.RESTPROXY.default_floatingip_quota
1009
 
        params = {
1010
 
            "name": net_part_name,
1011
 
            "fp_quota": str(fip_quota)
1012
 
        }
1013
 
        nuage_net_partition = self.nuageclient.create_net_partition(params)
1014
 
        net_partitioninst = None
1015
 
        if nuage_net_partition:
1016
 
            nuage_entid = nuage_net_partition['nuage_entid']
1017
 
            l3dom_id = nuage_net_partition['l3dom_id']
1018
 
            l2dom_id = nuage_net_partition['l2dom_id']
1019
 
            with session.begin():
1020
 
                net_partitioninst = nuagedb.add_net_partition(session,
1021
 
                                                              nuage_entid,
1022
 
                                                              l3dom_id,
1023
 
                                                              l2dom_id,
1024
 
                                                              net_part_name)
1025
 
        if not net_partitioninst:
1026
 
            return {}
1027
 
        return self._make_net_partition_dict(net_partitioninst)
1028
 
 
1029
 
    def _create_default_net_partition(self, default_net_part):
1030
 
        def_netpart = self.nuageclient.get_def_netpartition_data(
1031
 
            default_net_part)
1032
 
        session = db.get_session()
1033
 
        if def_netpart:
1034
 
            net_partition = nuagedb.get_net_partition_by_name(
1035
 
                session, default_net_part)
1036
 
            with session.begin(subtransactions=True):
1037
 
                if net_partition:
1038
 
                    nuagedb.delete_net_partition(session, net_partition)
1039
 
                net_part = nuagedb.add_net_partition(session,
1040
 
                                                     def_netpart['np_id'],
1041
 
                                                     def_netpart['l3dom_tid'],
1042
 
                                                     def_netpart['l2dom_tid'],
1043
 
                                                     default_net_part)
1044
 
                return self._make_net_partition_dict(net_part)
1045
 
        else:
1046
 
            return self._create_net_partition(session, default_net_part)
1047
 
 
1048
 
    def create_net_partition(self, context, net_partition):
1049
 
        ent = net_partition['net_partition']
1050
 
        session = context.session
1051
 
        return self._create_net_partition(session, ent["name"])
1052
 
 
1053
 
    def delete_net_partition(self, context, id):
1054
 
        ent_rtr_mapping = nuagedb.get_ent_rtr_mapping_by_entid(context.session,
1055
 
                                                               id)
1056
 
        if ent_rtr_mapping:
1057
 
            msg = (_("One or more router still attached to "
1058
 
                     "net_partition %s.") % id)
1059
 
            raise n_exc.BadRequest(resource='net_partition', msg=msg)
1060
 
        net_partition = nuagedb.get_net_partition_by_id(context.session, id)
1061
 
        if not net_partition:
1062
 
            msg = (_("NetPartition with %s does not exist") % id)
1063
 
            raise n_exc.BadRequest(resource='net_partition', msg=msg)
1064
 
        l3dom_tmplt_id = net_partition['l3dom_tmplt_id']
1065
 
        l2dom_tmplt_id = net_partition['l2dom_tmplt_id']
1066
 
        self.nuageclient.delete_net_partition(net_partition['id'],
1067
 
                                              l3dom_id=l3dom_tmplt_id,
1068
 
                                              l2dom_id=l2dom_tmplt_id)
1069
 
        with context.session.begin(subtransactions=True):
1070
 
            nuagedb.delete_net_partition(context.session,
1071
 
                                         net_partition)
1072
 
 
1073
 
    def get_net_partition(self, context, id, fields=None):
1074
 
        net_partition = nuagedb.get_net_partition_by_id(context.session,
1075
 
                                                        id)
1076
 
        return self._make_net_partition_dict(net_partition)
1077
 
 
1078
 
    def get_net_partitions(self, context, filters=None, fields=None):
1079
 
        net_partitions = nuagedb.get_net_partitions(context.session,
1080
 
                                                    filters=filters,
1081
 
                                                    fields=fields)
1082
 
        return [self._make_net_partition_dict(net_partition, fields)
1083
 
                for net_partition in net_partitions]
1084
 
 
1085
 
    def _check_floatingip_update(self, context, port):
1086
 
        filter = {'fixed_port_id': [port['id']]}
1087
 
        local_fip = self.get_floatingips(context,
1088
 
                                         filters=filter)
1089
 
        if local_fip:
1090
 
            fip = local_fip[0]
1091
 
            self._create_update_floatingip(context,
1092
 
                                           fip, port['id'])
1093
 
 
1094
 
    def _create_update_floatingip(self, context,
1095
 
                                  neutron_fip, port_id):
1096
 
        rtr_id = neutron_fip['router_id']
1097
 
        net_id = neutron_fip['floating_network_id']
1098
 
        subn = nuagedb.get_ipalloc_for_fip(context.session,
1099
 
                                           net_id,
1100
 
                                           neutron_fip['floating_ip_address'])
1101
 
 
1102
 
        fip_pool = self.nuageclient.get_nuage_fip_pool_by_id(subn['subnet_id'])
1103
 
        if not fip_pool:
1104
 
            msg = _('sharedresource %s not found on VSD') % subn['subnet_id']
1105
 
            raise n_exc.BadRequest(resource='floatingip',
1106
 
                                   msg=msg)
1107
 
 
1108
 
        ent_rtr_mapping = nuagedb.get_ent_rtr_mapping_by_rtrid(context.session,
1109
 
                                                               rtr_id)
1110
 
        if not ent_rtr_mapping:
1111
 
            msg = _('router %s is not associated with '
1112
 
                    'any net-partition') % rtr_id
1113
 
            raise n_exc.BadRequest(resource='floatingip',
1114
 
                                   msg=msg)
1115
 
 
1116
 
        params = {
1117
 
            'router_id': ent_rtr_mapping['nuage_router_id'],
1118
 
            'fip_id': neutron_fip['id'],
1119
 
            'neutron_fip': neutron_fip
1120
 
        }
1121
 
 
1122
 
        fip = self.nuageclient.get_nuage_fip_by_id(params)
1123
 
        if not fip:
1124
 
            params = {
1125
 
                'nuage_rtr_id': ent_rtr_mapping['nuage_router_id'],
1126
 
                'nuage_fippool_id': fip_pool['nuage_fip_pool_id'],
1127
 
                'neutron_fip_ip': neutron_fip['floating_ip_address'],
1128
 
                'neutron_fip_id': neutron_fip['id']
1129
 
            }
1130
 
            nuage_fip_id = self.nuageclient.create_nuage_floatingip(params)
1131
 
        else:
1132
 
            nuage_fip_id = fip['nuage_fip_id']
1133
 
 
1134
 
        # Update VM if required
1135
 
        params = {
1136
 
            'neutron_port_id': port_id,
1137
 
            'nuage_fip_id': nuage_fip_id,
1138
 
            'nuage_rtr_id': ent_rtr_mapping['nuage_router_id']
1139
 
        }
1140
 
        nuage_port = self.nuageclient.get_nuage_port_by_id(params)
1141
 
        if nuage_port:
1142
 
            if (nuage_port['nuage_domain_id']) != (
1143
 
                    ent_rtr_mapping['nuage_router_id']):
1144
 
                msg = _('Floating IP can not be associated to VM in '
1145
 
                        'different router context')
1146
 
                raise nuage_exc.OperationNotSupported(msg=msg)
1147
 
 
1148
 
            params = {
1149
 
                'nuage_vport_id': nuage_port['nuage_vport_id'],
1150
 
                'nuage_fip_id': nuage_fip_id
1151
 
            }
1152
 
            self.nuageclient.update_nuage_vm_vport(params)
1153
 
 
1154
 
    def create_floatingip(self, context, floatingip):
1155
 
        fip = floatingip['floatingip']
1156
 
        with context.session.begin(subtransactions=True):
1157
 
            neutron_fip = super(NuagePlugin, self).create_floatingip(
1158
 
                context, floatingip)
1159
 
            if not neutron_fip['router_id']:
1160
 
                return neutron_fip
1161
 
            try:
1162
 
                self._create_update_floatingip(context, neutron_fip,
1163
 
                                               fip['port_id'])
1164
 
            except (nuage_exc.OperationNotSupported, n_exc.BadRequest):
1165
 
                with excutils.save_and_reraise_exception():
1166
 
                    super(NuagePlugin, self).delete_floatingip(
1167
 
                        context, neutron_fip['id'])
1168
 
            return neutron_fip
1169
 
 
1170
 
    def disassociate_floatingips(self, context, port_id, do_notify=True):
1171
 
        router_ids = super(NuagePlugin, self).disassociate_floatingips(
1172
 
            context, port_id, do_notify=do_notify)
1173
 
 
1174
 
        params = {
1175
 
            'neutron_port_id': port_id,
1176
 
        }
1177
 
        nuage_port = self.nuageclient.get_nuage_port_by_id(params)
1178
 
        if nuage_port:
1179
 
            params = {
1180
 
                'nuage_vport_id': nuage_port['nuage_vport_id'],
1181
 
                'nuage_fip_id': None
1182
 
            }
1183
 
            self.nuageclient.update_nuage_vm_vport(params)
1184
 
 
1185
 
        return router_ids
1186
 
 
1187
 
    def update_floatingip(self, context, id, floatingip):
1188
 
        fip = floatingip['floatingip']
1189
 
        orig_fip = self._get_floatingip(context, id)
1190
 
        port_id = orig_fip['fixed_port_id']
1191
 
        router_ids = []
1192
 
        with context.session.begin(subtransactions=True):
1193
 
            neutron_fip = super(NuagePlugin, self).update_floatingip(
1194
 
                context, id, floatingip)
1195
 
            if fip['port_id'] is not None:
1196
 
                if not neutron_fip['router_id']:
1197
 
                    ret_msg = 'floating-ip is not associated yet'
1198
 
                    raise n_exc.BadRequest(resource='floatingip',
1199
 
                                           msg=ret_msg)
1200
 
 
1201
 
                try:
1202
 
                    self._create_update_floatingip(context,
1203
 
                                                   neutron_fip,
1204
 
                                                   fip['port_id'])
1205
 
                except nuage_exc.OperationNotSupported:
1206
 
                    with excutils.save_and_reraise_exception():
1207
 
                        router_ids = super(
1208
 
                            NuagePlugin, self).disassociate_floatingips(
1209
 
                                context, fip['port_id'], do_notify=False)
1210
 
                except n_exc.BadRequest:
1211
 
                    with excutils.save_and_reraise_exception():
1212
 
                        super(NuagePlugin, self).delete_floatingip(context,
1213
 
                                                                   id)
1214
 
            else:
1215
 
                params = {
1216
 
                    'neutron_port_id': port_id,
1217
 
                }
1218
 
                nuage_port = self.nuageclient.get_nuage_port_by_id(params)
1219
 
                if nuage_port:
1220
 
                    params = {
1221
 
                        'nuage_vport_id': nuage_port['nuage_vport_id'],
1222
 
                        'nuage_fip_id': None
1223
 
                    }
1224
 
                    self.nuageclient.update_nuage_vm_vport(params)
1225
 
 
1226
 
        # now that we've left db transaction, we are safe to notify
1227
 
        self.notify_routers_updated(context, router_ids)
1228
 
 
1229
 
        return neutron_fip
1230
 
 
1231
 
    def delete_floatingip(self, context, fip_id):
1232
 
        fip = self._get_floatingip(context, fip_id)
1233
 
        port_id = fip['fixed_port_id']
1234
 
        with context.session.begin(subtransactions=True):
1235
 
            if port_id:
1236
 
                params = {
1237
 
                    'neutron_port_id': port_id,
1238
 
                }
1239
 
                nuage_port = self.nuageclient.get_nuage_port_by_id(params)
1240
 
                if (nuage_port and
1241
 
                    nuage_port['nuage_vport_id'] is not None):
1242
 
                    params = {
1243
 
                        'nuage_vport_id': nuage_port['nuage_vport_id'],
1244
 
                        'nuage_fip_id': None
1245
 
                    }
1246
 
                    self.nuageclient.update_nuage_vm_vport(params)
1247
 
                    LOG.debug("Floating-ip %(fip)s is disassociated from "
1248
 
                              "vport %(vport)s",
1249
 
                              {'fip': fip_id,
1250
 
                               'vport': nuage_port['nuage_vport_id']})
1251
 
 
1252
 
                router_id = fip['router_id']
1253
 
            else:
1254
 
                router_id = fip['last_known_router_id']
1255
 
 
1256
 
            if router_id:
1257
 
                ent_rtr_mapping = nuagedb.get_ent_rtr_mapping_by_rtrid(
1258
 
                    context.session,
1259
 
                    router_id)
1260
 
                if not ent_rtr_mapping:
1261
 
                    msg = _('router %s is not associated with '
1262
 
                            'any net-partition') % router_id
1263
 
                    raise n_exc.BadRequest(resource='floatingip',
1264
 
                                       msg=msg)
1265
 
                params = {
1266
 
                    'router_id': ent_rtr_mapping['nuage_router_id'],
1267
 
                    'fip_id': fip_id
1268
 
                }
1269
 
                fip = self.nuageclient.get_nuage_fip_by_id(params)
1270
 
                if fip:
1271
 
                    self.nuageclient.delete_nuage_floatingip(
1272
 
                        fip['nuage_fip_id'])
1273
 
                    LOG.debug('Floating-ip %s deleted from VSD', fip_id)
1274
 
 
1275
 
            super(NuagePlugin, self).delete_floatingip(context, fip_id)
1276
 
 
1277
 
    def delete_security_group(self, context, id):
1278
 
        filters = {'security_group_id': [id]}
1279
 
        ports = self._get_port_security_group_bindings(context,
1280
 
                                                       filters)
1281
 
        if ports:
1282
 
            raise ext_sg.SecurityGroupInUse(id=id)
1283
 
        sg_rules = self.get_security_group_rules(context,
1284
 
                                                 {'security_group_id': [id]})
1285
 
 
1286
 
        if sg_rules:
1287
 
            self.nuageclient.delete_nuage_sgrule(sg_rules)
1288
 
        self.nuageclient.delete_nuage_secgroup(id)
1289
 
 
1290
 
        super(NuagePlugin, self).delete_security_group(context, id)
1291
 
 
1292
 
    def create_security_group_rule(self, context, security_group_rule):
1293
 
        sg_rule = security_group_rule['security_group_rule']
1294
 
        self.nuageclient.validate_nuage_sg_rule_definition(sg_rule)
1295
 
        sg_id = sg_rule['security_group_id']
1296
 
 
1297
 
        local_sg_rule = super(NuagePlugin,
1298
 
                              self).create_security_group_rule(
1299
 
                                        context, security_group_rule)
1300
 
 
1301
 
        try:
1302
 
            nuage_vptag = self.nuageclient.get_sg_vptag_mapping(sg_id)
1303
 
            if nuage_vptag:
1304
 
                sg_params = {
1305
 
                    'sg_id': sg_id,
1306
 
                    'neutron_sg_rule': local_sg_rule,
1307
 
                    'vptag': nuage_vptag
1308
 
                }
1309
 
                self.nuageclient.create_nuage_sgrule(sg_params)
1310
 
        except Exception:
1311
 
            with excutils.save_and_reraise_exception():
1312
 
                super(NuagePlugin,
1313
 
                      self).delete_security_group_rule(context,
1314
 
                                                   local_sg_rule['id'])
1315
 
 
1316
 
        return local_sg_rule
1317
 
 
1318
 
    def delete_security_group_rule(self, context, id):
1319
 
        local_sg_rule = self.get_security_group_rule(context, id)
1320
 
        super(NuagePlugin, self).delete_security_group_rule(context, id)
1321
 
        self.nuageclient.delete_nuage_sgrule([local_sg_rule])