20803ea637
The following modules are removed: - excutils, - importutils, - network_utils, - strutils, - timeutils. Closes-Bug: #1385355 Change-Id: I1f34f17f5dbf37032584008f27e65d4dc4d475f4
1322 lines
61 KiB
Python
1322 lines
61 KiB
Python
# Copyright 2014 Alcatel-Lucent USA Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import copy
|
|
import re
|
|
|
|
import netaddr
|
|
from oslo.config import cfg
|
|
from oslo.utils import excutils
|
|
from oslo.utils import importutils
|
|
from sqlalchemy.orm import exc
|
|
|
|
from neutron.api import extensions as neutron_extensions
|
|
from neutron.api.v2 import attributes
|
|
from neutron.common import constants as os_constants
|
|
from neutron.common import exceptions as n_exc
|
|
from neutron.common import utils
|
|
from neutron.db import api as db
|
|
from neutron.db import db_base_plugin_v2
|
|
from neutron.db import external_net_db
|
|
from neutron.db import extraroute_db
|
|
from neutron.db import l3_db
|
|
from neutron.db import quota_db # noqa
|
|
from neutron.db import securitygroups_db as sg_db
|
|
from neutron.extensions import external_net
|
|
from neutron.extensions import l3
|
|
from neutron.extensions import portbindings
|
|
from neutron.extensions import providernet as pnet
|
|
from neutron.extensions import securitygroup as ext_sg
|
|
from neutron.openstack.common import lockutils
|
|
from neutron.openstack.common import log as logging
|
|
from neutron.openstack.common import loopingcall
|
|
from neutron.plugins.nuage.common import config
|
|
from neutron.plugins.nuage.common import constants
|
|
from neutron.plugins.nuage.common import exceptions as nuage_exc
|
|
from neutron.plugins.nuage import extensions
|
|
from neutron.plugins.nuage.extensions import netpartition
|
|
from neutron.plugins.nuage import nuagedb
|
|
from neutron.plugins.nuage import syncmanager
|
|
from neutron import policy
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|
external_net_db.External_net_db_mixin,
|
|
extraroute_db.ExtraRoute_db_mixin,
|
|
l3_db.L3_NAT_db_mixin,
|
|
netpartition.NetPartitionPluginBase,
|
|
sg_db.SecurityGroupDbMixin):
|
|
"""Class that implements Nuage Networks' plugin functionality."""
|
|
supported_extension_aliases = ["router", "binding", "external-net",
|
|
"net-partition", "nuage-router",
|
|
"nuage-subnet", "quotas", "provider",
|
|
"extraroute", "security-group"]
|
|
|
|
binding_view = "extension:port_binding:view"
|
|
|
|
def __init__(self):
|
|
super(NuagePlugin, self).__init__()
|
|
neutron_extensions.append_api_extensions_path(extensions.__path__)
|
|
config.nuage_register_cfg_opts()
|
|
self.nuageclient_init()
|
|
net_partition = cfg.CONF.RESTPROXY.default_net_partition_name
|
|
self._create_default_net_partition(net_partition)
|
|
if cfg.CONF.SYNCMANAGER.enable_sync:
|
|
self.syncmanager = syncmanager.SyncManager(self.nuageclient)
|
|
self._synchronization_thread()
|
|
|
|
db_base_plugin_v2.NeutronDbPluginV2.register_dict_extend_funcs(
|
|
attributes.NETWORKS, ['_extend_network_dict_provider_nuage'])
|
|
|
|
def nuageclient_init(self):
|
|
server = cfg.CONF.RESTPROXY.server
|
|
serverauth = cfg.CONF.RESTPROXY.serverauth
|
|
serverssl = cfg.CONF.RESTPROXY.serverssl
|
|
base_uri = cfg.CONF.RESTPROXY.base_uri
|
|
auth_resource = cfg.CONF.RESTPROXY.auth_resource
|
|
organization = cfg.CONF.RESTPROXY.organization
|
|
nuageclient = importutils.import_module('nuagenetlib.nuageclient')
|
|
self.nuageclient = nuageclient.NuageClient(server, base_uri,
|
|
serverssl, serverauth,
|
|
auth_resource,
|
|
organization)
|
|
|
|
def _synchronization_thread(self):
|
|
sync_interval = cfg.CONF.SYNCMANAGER.sync_interval
|
|
fip_quota = str(cfg.CONF.RESTPROXY.default_floatingip_quota)
|
|
if sync_interval > 0:
|
|
sync_loop = loopingcall.FixedIntervalLoopingCall(
|
|
self.syncmanager.synchronize, fip_quota)
|
|
sync_loop.start(interval=sync_interval)
|
|
else:
|
|
self.syncmanager.synchronize(fip_quota)
|
|
|
|
def _resource_finder(self, context, for_resource, resource, user_req):
|
|
match = re.match(attributes.UUID_PATTERN, user_req[resource])
|
|
if match:
|
|
obj_lister = getattr(self, "get_%s" % resource)
|
|
found_resource = obj_lister(context, user_req[resource])
|
|
if not found_resource:
|
|
msg = (_("%(resource)s with id %(resource_id)s does not "
|
|
"exist") % {'resource': resource,
|
|
'resource_id': user_req[resource]})
|
|
raise n_exc.BadRequest(resource=for_resource, msg=msg)
|
|
else:
|
|
filter = {'name': [user_req[resource]]}
|
|
obj_lister = getattr(self, "get_%ss" % resource)
|
|
found_resource = obj_lister(context, filters=filter)
|
|
if not found_resource:
|
|
msg = (_("Either %(resource)s %(req_resource)s not found "
|
|
"or you dont have credential to access it")
|
|
% {'resource': resource,
|
|
'req_resource': user_req[resource]})
|
|
raise n_exc.BadRequest(resource=for_resource, msg=msg)
|
|
if len(found_resource) > 1:
|
|
msg = (_("More than one entry found for %(resource)s "
|
|
"%(req_resource)s. Use id instead")
|
|
% {'resource': resource,
|
|
'req_resource': user_req[resource]})
|
|
raise n_exc.BadRequest(resource=for_resource, msg=msg)
|
|
found_resource = found_resource[0]
|
|
return found_resource
|
|
|
|
def _create_update_port(self, context, port, np_name):
|
|
filters = {'device_id': [port['device_id']]}
|
|
ports = self.get_ports(context, filters)
|
|
params = {
|
|
'port_id': port['id'],
|
|
'id': port['device_id'],
|
|
'mac': port['mac_address'],
|
|
'netpart_name': np_name,
|
|
'ip': port['fixed_ips'][0]['ip_address'],
|
|
'no_of_ports': len(ports),
|
|
'tenant': port['tenant_id'],
|
|
'neutron_id': port['fixed_ips'][0]['subnet_id']
|
|
}
|
|
self.nuageclient.create_vms(params)
|
|
|
|
def _get_router_by_subnet(self, context, subnet_id):
|
|
filters = {
|
|
'fixed_ips': {'subnet_id': [subnet_id]},
|
|
'device_owner': [os_constants.DEVICE_OWNER_ROUTER_INTF]
|
|
}
|
|
router_port = self.get_ports(context, filters=filters)
|
|
if not router_port:
|
|
msg = (_("Router for subnet %s not found ") % subnet_id)
|
|
raise n_exc.BadRequest(resource='port', msg=msg)
|
|
return router_port[0]['device_id']
|
|
|
|
def _process_port_create_security_group(self, context, port,
|
|
sec_group):
|
|
if not attributes.is_attr_set(sec_group):
|
|
port[ext_sg.SECURITYGROUPS] = []
|
|
return
|
|
port_id = port['id']
|
|
with context.session.begin(subtransactions=True):
|
|
for sg_id in sec_group:
|
|
super(NuagePlugin,
|
|
self)._create_port_security_group_binding(context,
|
|
port_id,
|
|
sg_id)
|
|
try:
|
|
vptag_vport_list = []
|
|
for sg_id in sec_group:
|
|
params = {
|
|
'neutron_port_id': port_id
|
|
}
|
|
nuage_port = self.nuageclient.get_nuage_port_by_id(params)
|
|
if nuage_port and nuage_port.get('nuage_vport_id'):
|
|
nuage_vport_id = nuage_port['nuage_vport_id']
|
|
sg = self._get_security_group(context, sg_id)
|
|
sg_rules = self.get_security_group_rules(
|
|
context,
|
|
{'security_group_id': [sg_id]})
|
|
sg_params = {
|
|
'nuage_port': nuage_port,
|
|
'sg': sg,
|
|
'sg_rules': sg_rules
|
|
}
|
|
nuage_vptag_id = (
|
|
self.nuageclient.process_port_create_security_group(
|
|
sg_params))
|
|
vptag_vport = {
|
|
'nuage_vporttag_id': nuage_vptag_id
|
|
}
|
|
vptag_vport_list.append(vptag_vport)
|
|
|
|
if vptag_vport_list:
|
|
params = {
|
|
'vptag_vport_list': vptag_vport_list,
|
|
'nuage_vport_id': nuage_vport_id
|
|
}
|
|
self.nuageclient.update_nuage_vport(params)
|
|
except Exception:
|
|
with excutils.save_and_reraise_exception():
|
|
for sg_id in sec_group:
|
|
super(NuagePlugin,
|
|
self)._delete_port_security_group_bindings(context,
|
|
port_id)
|
|
# Convert to list as a set might be passed here and
|
|
# this has to be serialized
|
|
port[ext_sg.SECURITYGROUPS] = (list(sec_group) if sec_group else [])
|
|
|
|
def _delete_port_security_group_bindings(self, context, port_id):
|
|
super(NuagePlugin,
|
|
self)._delete_port_security_group_bindings(context, port_id)
|
|
self.nuageclient.delete_port_security_group_bindings(port_id)
|
|
|
|
@lockutils.synchronized('create_port', 'nuage-port', external=True)
|
|
def create_port(self, context, port):
|
|
session = context.session
|
|
with session.begin(subtransactions=True):
|
|
p = port['port']
|
|
self._ensure_default_security_group_on_port(context, port)
|
|
port = super(NuagePlugin, self).create_port(context, port)
|
|
device_owner = port.get('device_owner', None)
|
|
if device_owner not in constants.AUTO_CREATE_PORT_OWNERS:
|
|
if 'fixed_ips' not in port or len(port['fixed_ips']) == 0:
|
|
return self._extend_port_dict_binding(context, port)
|
|
subnet_id = port['fixed_ips'][0]['subnet_id']
|
|
subnet_mapping = nuagedb.get_subnet_l2dom_by_id(session,
|
|
subnet_id)
|
|
if subnet_mapping:
|
|
port_prefix = constants.NOVA_PORT_OWNER_PREF
|
|
if port['device_owner'].startswith(port_prefix):
|
|
#This request is coming from nova
|
|
try:
|
|
net_partition = nuagedb.get_net_partition_by_id(
|
|
session,
|
|
subnet_mapping['net_partition_id'])
|
|
self._create_update_port(
|
|
context,
|
|
port,
|
|
net_partition['name'])
|
|
except Exception:
|
|
with excutils.save_and_reraise_exception():
|
|
super(NuagePlugin, self).delete_port(
|
|
context,
|
|
port['id'])
|
|
if ext_sg.SECURITYGROUPS in p:
|
|
self._process_port_create_security_group(
|
|
context,
|
|
port,
|
|
p[ext_sg.SECURITYGROUPS])
|
|
return self._extend_port_dict_binding(context, port)
|
|
|
|
def update_port(self, context, id, port):
|
|
p = port['port']
|
|
sg_groups = None
|
|
if p.get('device_owner', '').startswith(
|
|
constants.NOVA_PORT_OWNER_PREF):
|
|
session = context.session
|
|
with session.begin(subtransactions=True):
|
|
port = self._get_port(context, id)
|
|
port.update(p)
|
|
if not port.get('fixed_ips'):
|
|
return self._make_port_dict(port)
|
|
subnet_id = port['fixed_ips'][0]['subnet_id']
|
|
|
|
subnet_mapping = nuagedb.get_subnet_l2dom_by_id(session,
|
|
subnet_id)
|
|
if not subnet_mapping:
|
|
msg = (_("Subnet %s not found on VSD") % subnet_id)
|
|
raise n_exc.BadRequest(resource='port', msg=msg)
|
|
|
|
params = {
|
|
'neutron_port_id': id,
|
|
}
|
|
nuage_port = self.nuageclient.get_nuage_port_by_id(params)
|
|
if not nuage_port or not nuage_port.get('nuage_vport_id'):
|
|
net_partition = nuagedb.get_net_partition_by_id(
|
|
session, subnet_mapping['net_partition_id'])
|
|
self._create_update_port(context, port,
|
|
net_partition['name'])
|
|
self._check_floatingip_update(context, port)
|
|
updated_port = self._make_port_dict(port)
|
|
sg_port = self._extend_port_dict_security_group(
|
|
updated_port,
|
|
port
|
|
)
|
|
sg_groups = sg_port[ext_sg.SECURITYGROUPS]
|
|
else:
|
|
updated_port = super(NuagePlugin, self).update_port(context, id,
|
|
port)
|
|
if not updated_port.get('fixed_ips'):
|
|
return updated_port
|
|
subnet_id = updated_port['fixed_ips'][0]['subnet_id']
|
|
subnet_mapping = nuagedb.get_subnet_l2dom_by_id(context.session,
|
|
subnet_id)
|
|
if subnet_mapping:
|
|
if sg_groups:
|
|
self._delete_port_security_group_bindings(context,
|
|
updated_port['id'])
|
|
self._process_port_create_security_group(context,
|
|
updated_port,
|
|
sg_groups)
|
|
elif ext_sg.SECURITYGROUPS in p:
|
|
self._delete_port_security_group_bindings(context,
|
|
updated_port['id'])
|
|
self._process_port_create_security_group(
|
|
context,
|
|
updated_port,
|
|
p[ext_sg.SECURITYGROUPS]
|
|
)
|
|
return updated_port
|
|
|
|
def _delete_nuage_vport(self, context, port, np_name):
|
|
nuage_vif_id = None
|
|
params = {
|
|
'neutron_port_id': port['id'],
|
|
}
|
|
nuage_port = self.nuageclient.get_nuage_port_by_id(params)
|
|
|
|
if constants.NOVA_PORT_OWNER_PREF in port['device_owner']:
|
|
# This was a VM Port
|
|
if nuage_port:
|
|
nuage_vif_id = nuage_port['nuage_vif_id']
|
|
filters = {'device_id': [port['device_id']]}
|
|
ports = self.get_ports(context, filters)
|
|
params = {
|
|
'no_of_ports': len(ports),
|
|
'netpart_name': np_name,
|
|
'tenant': port['tenant_id'],
|
|
'mac': port['mac_address'],
|
|
'nuage_vif_id': nuage_vif_id,
|
|
'id': port['device_id']
|
|
}
|
|
self.nuageclient.delete_vms(params)
|
|
|
|
@lockutils.synchronized('delete-port', 'nuage-del', external=True)
|
|
def delete_port(self, context, id, l3_port_check=True):
|
|
if l3_port_check:
|
|
self.prevent_l3_port_deletion(context, id)
|
|
port = self._get_port(context, id)
|
|
# This is required for to pass ut test_floatingip_port_delete
|
|
self.disassociate_floatingips(context, id)
|
|
if not port['fixed_ips']:
|
|
return super(NuagePlugin, self).delete_port(context, id)
|
|
|
|
sub_id = port['fixed_ips'][0]['subnet_id']
|
|
|
|
subnet_mapping = nuagedb.get_subnet_l2dom_by_id(context.session,
|
|
sub_id)
|
|
if not subnet_mapping:
|
|
return super(NuagePlugin, self).delete_port(context, id)
|
|
|
|
# Need to call this explicitly to delete vport to vporttag binding
|
|
if ext_sg.SECURITYGROUPS in port:
|
|
self._delete_port_security_group_bindings(context, id)
|
|
|
|
netpart_id = subnet_mapping['net_partition_id']
|
|
net_partition = nuagedb.get_net_partition_by_id(context.session,
|
|
netpart_id)
|
|
self._delete_nuage_vport(context, port, net_partition['name'])
|
|
super(NuagePlugin, self).delete_port(context, id)
|
|
|
|
def _check_view_auth(self, context, resource, action):
|
|
return policy.check(context, action, resource)
|
|
|
|
def _extend_port_dict_binding(self, context, port):
|
|
if self._check_view_auth(context, port, self.binding_view):
|
|
port[portbindings.VIF_TYPE] = portbindings.VIF_TYPE_OVS
|
|
port[portbindings.VIF_DETAILS] = {
|
|
portbindings.CAP_PORT_FILTER: False
|
|
}
|
|
return port
|
|
|
|
def get_port(self, context, id, fields=None):
|
|
port = super(NuagePlugin, self).get_port(context, id, fields)
|
|
return self._fields(self._extend_port_dict_binding(context, port),
|
|
fields)
|
|
|
|
def get_ports(self, context, filters=None, fields=None):
|
|
ports = super(NuagePlugin, self).get_ports(context, filters, fields)
|
|
return [self._fields(self._extend_port_dict_binding(context, port),
|
|
fields) for port in ports]
|
|
|
|
def _check_router_subnet_for_tenant(self, context, tenant_id):
|
|
# Search router and subnet tables.
|
|
# If no entry left delete user and group from VSD
|
|
filters = {'tenant_id': [tenant_id]}
|
|
routers = self.get_routers(context, filters=filters)
|
|
subnets = self.get_subnets(context, filters=filters)
|
|
return bool(routers or subnets)
|
|
|
|
def _extend_network_dict_provider_nuage(self, network, net_db,
|
|
net_binding=None):
|
|
binding = net_db.pnetbinding if net_db else net_binding
|
|
if binding:
|
|
network[pnet.NETWORK_TYPE] = binding.network_type
|
|
network[pnet.PHYSICAL_NETWORK] = binding.physical_network
|
|
network[pnet.SEGMENTATION_ID] = binding.vlan_id
|
|
|
|
def _process_provider_create(self, context, attrs):
|
|
network_type = attrs.get(pnet.NETWORK_TYPE)
|
|
physical_network = attrs.get(pnet.PHYSICAL_NETWORK)
|
|
segmentation_id = attrs.get(pnet.SEGMENTATION_ID)
|
|
|
|
network_type_set = attributes.is_attr_set(network_type)
|
|
physical_network_set = attributes.is_attr_set(physical_network)
|
|
segmentation_id_set = attributes.is_attr_set(segmentation_id)
|
|
|
|
if not (network_type_set or physical_network_set or
|
|
segmentation_id_set):
|
|
return None, None, None
|
|
if not network_type_set:
|
|
msg = _("provider:network_type required")
|
|
raise n_exc.InvalidInput(error_message=msg)
|
|
elif network_type != 'vlan':
|
|
msg = (_("provider:network_type %s not supported in VSP")
|
|
% network_type)
|
|
raise nuage_exc.NuageBadRequest(msg=msg)
|
|
if not physical_network_set:
|
|
msg = _("provider:physical_network required")
|
|
raise nuage_exc.NuageBadRequest(msg=msg)
|
|
if not segmentation_id_set:
|
|
msg = _("provider:segmentation_id required")
|
|
raise nuage_exc.NuageBadRequest(msg=msg)
|
|
|
|
self.nuageclient.validate_provider_network(network_type,
|
|
physical_network,
|
|
segmentation_id)
|
|
|
|
return network_type, physical_network, segmentation_id
|
|
|
|
def create_network(self, context, network):
|
|
binding = None
|
|
(network_type, physical_network,
|
|
vlan_id) = self._process_provider_create(context,
|
|
network['network'])
|
|
with context.session.begin(subtransactions=True):
|
|
self._ensure_default_security_group(
|
|
context,
|
|
network['network']['tenant_id']
|
|
)
|
|
net = super(NuagePlugin, self).create_network(context,
|
|
network)
|
|
self._process_l3_create(context, net, network['network'])
|
|
if network_type == 'vlan':
|
|
binding = nuagedb.add_network_binding(context.session,
|
|
net['id'],
|
|
network_type,
|
|
physical_network, vlan_id)
|
|
self._extend_network_dict_provider_nuage(net, None, binding)
|
|
return net
|
|
|
|
def _validate_update_network(self, context, id, network):
|
|
req_data = network['network']
|
|
is_external_set = req_data.get(external_net.EXTERNAL)
|
|
if not attributes.is_attr_set(is_external_set):
|
|
return (None, None)
|
|
neutron_net = self.get_network(context, id)
|
|
if neutron_net.get(external_net.EXTERNAL) == is_external_set:
|
|
return (None, None)
|
|
subnet = self._validate_nuage_sharedresource(context, 'network', id)
|
|
if subnet and not is_external_set:
|
|
msg = _('External network with subnets can not be '
|
|
'changed to non-external network')
|
|
raise nuage_exc.OperationNotSupported(msg=msg)
|
|
if is_external_set:
|
|
# Check if there are vm ports attached to this network
|
|
# If there are, then updating the network is not allowed
|
|
ports = self.get_ports(context, filters={'network_id': [id]})
|
|
for p in ports:
|
|
if p['device_owner'].startswith(
|
|
constants.NOVA_PORT_OWNER_PREF):
|
|
raise n_exc.NetworkInUse(net_id=id)
|
|
return (is_external_set, subnet)
|
|
|
|
def update_network(self, context, id, network):
|
|
pnet._raise_if_updates_provider_attributes(network['network'])
|
|
with context.session.begin(subtransactions=True):
|
|
is_external_set, subnet = self._validate_update_network(context,
|
|
id,
|
|
network)
|
|
net = super(NuagePlugin, self).update_network(context, id,
|
|
network)
|
|
self._process_l3_update(context, net, network['network'])
|
|
if subnet and is_external_set:
|
|
subn = subnet[0]
|
|
subnet_l2dom = nuagedb.get_subnet_l2dom_by_id(context.session,
|
|
subn['id'])
|
|
if subnet_l2dom:
|
|
user_id = subnet_l2dom['nuage_user_id']
|
|
group_id = subnet_l2dom['nuage_group_id']
|
|
self.nuageclient.delete_subnet(subn['id'])
|
|
nuagedb.delete_subnetl2dom_mapping(context.session,
|
|
subnet_l2dom)
|
|
if not self._check_router_subnet_for_tenant(
|
|
context, subn['tenant_id']):
|
|
self.nuageclient.delete_user(user_id)
|
|
self.nuageclient.delete_group(group_id)
|
|
|
|
self._add_nuage_sharedresource(subnet[0],
|
|
id,
|
|
constants.SR_TYPE_FLOATING)
|
|
return net
|
|
|
|
def delete_network(self, context, id):
|
|
with context.session.begin(subtransactions=True):
|
|
self._process_l3_delete(context, id)
|
|
filter = {'network_id': [id]}
|
|
subnets = self.get_subnets(context, filters=filter)
|
|
for subnet in subnets:
|
|
self.delete_subnet(context, subnet['id'])
|
|
super(NuagePlugin, self).delete_network(context, id)
|
|
|
|
def _get_net_partition_for_subnet(self, context, subnet):
|
|
ent = subnet.get('net_partition', None)
|
|
if not ent:
|
|
def_net_part = cfg.CONF.RESTPROXY.default_net_partition_name
|
|
net_partition = nuagedb.get_net_partition_by_name(context.session,
|
|
def_net_part)
|
|
else:
|
|
net_partition = self._resource_finder(context, 'subnet',
|
|
'net_partition', subnet)
|
|
if not net_partition:
|
|
msg = _('Either net_partition is not provided with subnet OR '
|
|
'default net_partition is not created at the start')
|
|
raise n_exc.BadRequest(resource='subnet', msg=msg)
|
|
return net_partition
|
|
|
|
@staticmethod
|
|
def _validate_create_subnet(subnet):
|
|
if (attributes.is_attr_set(subnet['gateway_ip'])
|
|
and netaddr.IPAddress(subnet['gateway_ip'])
|
|
not in netaddr.IPNetwork(subnet['cidr'])):
|
|
msg = "Gateway IP outside of the subnet CIDR "
|
|
raise nuage_exc.NuageBadRequest(msg=msg)
|
|
|
|
def _validate_create_provider_subnet(self, context, net_id):
|
|
net_filter = {'network_id': [net_id]}
|
|
existing_subn = self.get_subnets(context, filters=net_filter)
|
|
if len(existing_subn) > 0:
|
|
msg = _('Only one subnet is allowed per '
|
|
'Provider network %s') % net_id
|
|
raise nuage_exc.OperationNotSupported(msg=msg)
|
|
|
|
def _delete_nuage_sharedresource(self, net_id):
|
|
self.nuageclient.delete_nuage_sharedresource(net_id)
|
|
|
|
def _validate_nuage_sharedresource(self, context, resource, net_id):
|
|
filter = {'network_id': [net_id]}
|
|
existing_subn = self.get_subnets(context, filters=filter)
|
|
if len(existing_subn) > 1:
|
|
msg = _('Only one subnet is allowed per '
|
|
'external network %s') % net_id
|
|
raise nuage_exc.OperationNotSupported(msg=msg)
|
|
return existing_subn
|
|
|
|
def _add_nuage_sharedresource(self, subnet, net_id, type):
|
|
net = netaddr.IPNetwork(subnet['cidr'])
|
|
params = {
|
|
'neutron_subnet': subnet,
|
|
'net': net,
|
|
'type': type,
|
|
'net_id': net_id
|
|
}
|
|
self.nuageclient.create_nuage_sharedresource(params)
|
|
|
|
def _create_nuage_sharedresource(self, context, subnet, type):
|
|
subn = subnet['subnet']
|
|
net_id = subn['network_id']
|
|
self._validate_nuage_sharedresource(context, 'subnet', net_id)
|
|
with context.session.begin(subtransactions=True):
|
|
subn = super(NuagePlugin, self).create_subnet(context, subnet)
|
|
self._add_nuage_sharedresource(subn, net_id, type)
|
|
return subn
|
|
|
|
def _create_port_gateway(self, context, subnet, gw_ip=None):
|
|
if gw_ip is not None:
|
|
fixed_ip = [{'ip_address': gw_ip, 'subnet_id': subnet['id']}]
|
|
else:
|
|
fixed_ip = [{'subnet_id': subnet['id']}]
|
|
|
|
port_dict = dict(port=dict(
|
|
name='',
|
|
device_id='',
|
|
admin_state_up=True,
|
|
network_id=subnet['network_id'],
|
|
tenant_id=subnet['tenant_id'],
|
|
fixed_ips=fixed_ip,
|
|
mac_address=attributes.ATTR_NOT_SPECIFIED,
|
|
device_owner=os_constants.DEVICE_OWNER_DHCP))
|
|
port = super(NuagePlugin, self).create_port(context, port_dict)
|
|
return port
|
|
|
|
def _delete_port_gateway(self, context, ports):
|
|
for port in ports:
|
|
super(NuagePlugin, self).delete_port(context, port['id'])
|
|
|
|
def _create_nuage_subnet(self, context, neutron_subnet, netpart_id,
|
|
l2dom_template_id, pnet_binding):
|
|
net = netaddr.IPNetwork(neutron_subnet['cidr'])
|
|
# list(net)[-1] is the broadcast
|
|
last_address = neutron_subnet['allocation_pools'][-1]['end']
|
|
gw_port = self._create_port_gateway(context, neutron_subnet,
|
|
last_address)
|
|
params = {
|
|
'netpart_id': netpart_id,
|
|
'tenant_id': neutron_subnet['tenant_id'],
|
|
'net': net,
|
|
'l2dom_tmplt_id': l2dom_template_id,
|
|
'pnet_binding': pnet_binding,
|
|
'dhcp_ip': gw_port['fixed_ips'][0]['ip_address']
|
|
}
|
|
try:
|
|
nuage_subnet = self.nuageclient.create_subnet(neutron_subnet,
|
|
params)
|
|
except Exception:
|
|
with excutils.save_and_reraise_exception():
|
|
self._delete_port_gateway(context, [gw_port])
|
|
super(NuagePlugin, self).delete_subnet(context,
|
|
neutron_subnet['id'])
|
|
|
|
if nuage_subnet:
|
|
l2dom_id = str(nuage_subnet['nuage_l2template_id'])
|
|
user_id = nuage_subnet['nuage_userid']
|
|
group_id = nuage_subnet['nuage_groupid']
|
|
id = nuage_subnet['nuage_l2domain_id']
|
|
with context.session.begin(subtransactions=True):
|
|
nuagedb.add_subnetl2dom_mapping(context.session,
|
|
neutron_subnet['id'],
|
|
id,
|
|
netpart_id,
|
|
l2dom_id=l2dom_id,
|
|
nuage_user_id=user_id,
|
|
nuage_group_id=group_id)
|
|
|
|
def create_subnet(self, context, subnet):
|
|
subn = subnet['subnet']
|
|
net_id = subn['network_id']
|
|
|
|
if self._network_is_external(context, net_id):
|
|
return self._create_nuage_sharedresource(
|
|
context, subnet, constants.SR_TYPE_FLOATING)
|
|
pnet_binding = nuagedb.get_network_binding(context.session, net_id)
|
|
if pnet_binding:
|
|
self._validate_create_provider_subnet(context, net_id)
|
|
|
|
self._validate_create_subnet(subn)
|
|
|
|
net_partition = self._get_net_partition_for_subnet(context, subn)
|
|
neutron_subnet = super(NuagePlugin, self).create_subnet(context,
|
|
subnet)
|
|
self._create_nuage_subnet(context, neutron_subnet, net_partition['id'],
|
|
subn['nuage_subnet_template'],
|
|
pnet_binding)
|
|
return neutron_subnet
|
|
|
|
def update_subnet(self, context, id, subnet):
|
|
subn = copy.deepcopy(subnet['subnet'])
|
|
subnet_l2dom = nuagedb.get_subnet_l2dom_by_id(context.session,
|
|
id)
|
|
params = {
|
|
'parent_id': subnet_l2dom['nuage_subnet_id'],
|
|
'type': subnet_l2dom['nuage_l2dom_tmplt_id']
|
|
}
|
|
with context.session.begin(subtransactions=True):
|
|
neutron_subnet = super(NuagePlugin, self).update_subnet(context,
|
|
id, subnet)
|
|
self.nuageclient.update_subnet(subn, params)
|
|
return neutron_subnet
|
|
|
|
def delete_subnet(self, context, id):
|
|
subnet = self.get_subnet(context, id)
|
|
if self._network_is_external(context, subnet['network_id']):
|
|
super(NuagePlugin, self).delete_subnet(context, id)
|
|
return self._delete_nuage_sharedresource(id)
|
|
|
|
filters = {'fixed_ips': {'subnet_id': [id]}}
|
|
ports = self.get_ports(context, filters)
|
|
for port in ports:
|
|
if port['device_owner'] != os_constants.DEVICE_OWNER_DHCP:
|
|
raise n_exc.SubnetInUse(subnet_id=id)
|
|
|
|
subnet_l2dom = nuagedb.get_subnet_l2dom_by_id(context.session, id)
|
|
if subnet_l2dom:
|
|
try:
|
|
self.nuageclient.delete_subnet(id)
|
|
except Exception:
|
|
msg = (_('Unable to complete operation on subnet %s.'
|
|
'One or more ports have an IP allocation '
|
|
'from this subnet.') % id)
|
|
raise n_exc.BadRequest(resource='subnet', msg=msg)
|
|
super(NuagePlugin, self).delete_subnet(context, id)
|
|
if subnet_l2dom and not self._check_router_subnet_for_tenant(
|
|
context, subnet['tenant_id']):
|
|
self.nuageclient.delete_user(subnet_l2dom['nuage_user_id'])
|
|
self.nuageclient.delete_group(subnet_l2dom['nuage_group_id'])
|
|
|
|
def add_router_interface(self, context, router_id, interface_info):
|
|
session = context.session
|
|
with session.begin(subtransactions=True):
|
|
rtr_if_info = super(NuagePlugin,
|
|
self).add_router_interface(context,
|
|
router_id,
|
|
interface_info)
|
|
subnet_id = rtr_if_info['subnet_id']
|
|
subn = self.get_subnet(context, subnet_id)
|
|
ent_rtr_mapping = nuagedb.get_ent_rtr_mapping_by_rtrid(session,
|
|
router_id)
|
|
nuage_zone = self.nuageclient.get_zone_by_routerid(router_id)
|
|
if not nuage_zone or not ent_rtr_mapping:
|
|
super(NuagePlugin,
|
|
self).remove_router_interface(context,
|
|
router_id,
|
|
interface_info)
|
|
msg = (_("Router %s does not hold default zone OR "
|
|
"domain in VSD. Router-IF add failed")
|
|
% router_id)
|
|
raise n_exc.BadRequest(resource='router', msg=msg)
|
|
|
|
subnet_l2dom = nuagedb.get_subnet_l2dom_by_id(session,
|
|
subnet_id)
|
|
if not subnet_l2dom:
|
|
super(NuagePlugin,
|
|
self).remove_router_interface(context,
|
|
router_id,
|
|
interface_info)
|
|
msg = (_("Subnet %s does not hold Nuage VSD reference. "
|
|
"Router-IF add failed") % subnet_id)
|
|
raise n_exc.BadRequest(resource='subnet', msg=msg)
|
|
|
|
if (subnet_l2dom['net_partition_id'] !=
|
|
ent_rtr_mapping['net_partition_id']):
|
|
super(NuagePlugin,
|
|
self).remove_router_interface(context,
|
|
router_id,
|
|
interface_info)
|
|
msg = (_("Subnet %(subnet)s and Router %(router)s belong to "
|
|
"different net_partition Router-IF add "
|
|
"not permitted") % {'subnet': subnet_id,
|
|
'router': router_id})
|
|
raise n_exc.BadRequest(resource='subnet', msg=msg)
|
|
nuage_subnet_id = subnet_l2dom['nuage_subnet_id']
|
|
if self.nuageclient.vms_on_l2domain(nuage_subnet_id):
|
|
super(NuagePlugin,
|
|
self).remove_router_interface(context,
|
|
router_id,
|
|
interface_info)
|
|
msg = (_("Subnet %s has one or more active VMs "
|
|
"Router-IF add not permitted") % subnet_id)
|
|
raise n_exc.BadRequest(resource='subnet', msg=msg)
|
|
self.nuageclient.delete_subnet(subnet_id)
|
|
net = netaddr.IPNetwork(subn['cidr'])
|
|
pnet_binding = nuagedb.get_network_binding(context.session,
|
|
subn['network_id'])
|
|
params = {
|
|
'net': net,
|
|
'zone_id': nuage_zone['nuage_zone_id'],
|
|
'neutron_subnet_id': subnet_id,
|
|
'pnet_binding': pnet_binding
|
|
}
|
|
if not attributes.is_attr_set(subn['gateway_ip']):
|
|
subn['gateway_ip'] = str(netaddr.IPAddress(net.first + 1))
|
|
|
|
try:
|
|
nuage_subnet = self.nuageclient.create_domain_subnet(subn,
|
|
params)
|
|
except Exception:
|
|
with excutils.save_and_reraise_exception():
|
|
super(NuagePlugin,
|
|
self).remove_router_interface(context,
|
|
router_id,
|
|
interface_info)
|
|
|
|
if nuage_subnet:
|
|
ns_dict = {}
|
|
ns_dict['nuage_subnet_id'] = nuage_subnet['nuage_subnetid']
|
|
ns_dict['nuage_l2dom_tmplt_id'] = None
|
|
nuagedb.update_subnetl2dom_mapping(subnet_l2dom,
|
|
ns_dict)
|
|
|
|
return rtr_if_info
|
|
|
|
def remove_router_interface(self, context, router_id, interface_info):
|
|
if 'subnet_id' in interface_info:
|
|
subnet_id = interface_info['subnet_id']
|
|
subnet = self.get_subnet(context, subnet_id)
|
|
found = False
|
|
try:
|
|
filters = {'device_id': [router_id],
|
|
'device_owner':
|
|
[os_constants.DEVICE_OWNER_ROUTER_INTF],
|
|
'network_id': [subnet['network_id']]}
|
|
ports = self.get_ports(context, filters)
|
|
|
|
for p in ports:
|
|
if p['fixed_ips'][0]['subnet_id'] == subnet_id:
|
|
found = True
|
|
break
|
|
except exc.NoResultFound:
|
|
msg = (_("No router interface found for Router %s. "
|
|
"Router-IF delete failed") % router_id)
|
|
raise n_exc.BadRequest(resource='router', msg=msg)
|
|
|
|
if not found:
|
|
msg = (_("No router interface found for Router %s. "
|
|
"Router-IF delete failed") % router_id)
|
|
raise n_exc.BadRequest(resource='router', msg=msg)
|
|
elif 'port_id' in interface_info:
|
|
port_db = self._get_port(context, interface_info['port_id'])
|
|
if not port_db:
|
|
msg = (_("No router interface found for Router %s. "
|
|
"Router-IF delete failed") % router_id)
|
|
raise n_exc.BadRequest(resource='router', msg=msg)
|
|
subnet_id = port_db['fixed_ips'][0]['subnet_id']
|
|
|
|
session = context.session
|
|
with session.begin(subtransactions=True):
|
|
subnet_l2dom = nuagedb.get_subnet_l2dom_by_id(session,
|
|
subnet_id)
|
|
if not subnet_l2dom:
|
|
return super(NuagePlugin,
|
|
self).remove_router_interface(context,
|
|
router_id,
|
|
interface_info)
|
|
nuage_subn_id = subnet_l2dom['nuage_subnet_id']
|
|
if self.nuageclient.vms_on_subnet(nuage_subn_id):
|
|
msg = (_("Subnet %s has one or more active VMs "
|
|
"Router-IF delete not permitted") % subnet_id)
|
|
raise n_exc.BadRequest(resource='subnet', msg=msg)
|
|
|
|
neutron_subnet = self.get_subnet(context, subnet_id)
|
|
ent_rtr_mapping = nuagedb.get_ent_rtr_mapping_by_rtrid(
|
|
context.session,
|
|
router_id)
|
|
if not ent_rtr_mapping:
|
|
msg = (_("Router %s does not hold net_partition "
|
|
"assoc on Nuage VSD. Router-IF delete failed")
|
|
% router_id)
|
|
raise n_exc.BadRequest(resource='router', msg=msg)
|
|
|
|
net = netaddr.IPNetwork(neutron_subnet['cidr'])
|
|
netpart_id = ent_rtr_mapping['net_partition_id']
|
|
pnet_binding = nuagedb.get_network_binding(
|
|
context.session, neutron_subnet['network_id'])
|
|
params = {
|
|
'tenant_id': neutron_subnet['tenant_id'],
|
|
'net': net,
|
|
'netpart_id': netpart_id,
|
|
'nuage_subn_id': nuage_subn_id,
|
|
'neutron_subnet': neutron_subnet,
|
|
'pnet_binding': pnet_binding
|
|
}
|
|
nuage_subnet = self.nuageclient.remove_router_interface(params)
|
|
info = super(NuagePlugin,
|
|
self).remove_router_interface(context, router_id,
|
|
interface_info)
|
|
|
|
if nuage_subnet:
|
|
tmplt_id = str(nuage_subnet['nuage_l2template_id'])
|
|
ns_dict = {}
|
|
ns_dict['nuage_subnet_id'] = nuage_subnet['nuage_l2domain_id']
|
|
ns_dict['nuage_l2dom_tmplt_id'] = tmplt_id
|
|
nuagedb.update_subnetl2dom_mapping(subnet_l2dom,
|
|
ns_dict)
|
|
return info
|
|
|
|
def _get_net_partition_for_router(self, context, rtr):
|
|
ent = rtr.get('net_partition', None)
|
|
if not ent:
|
|
def_net_part = cfg.CONF.RESTPROXY.default_net_partition_name
|
|
net_partition = nuagedb.get_net_partition_by_name(context.session,
|
|
def_net_part)
|
|
else:
|
|
net_partition = self._resource_finder(context, 'router',
|
|
'net_partition', rtr)
|
|
if not net_partition:
|
|
msg = _("Either net_partition is not provided with router OR "
|
|
"default net_partition is not created at the start")
|
|
raise n_exc.BadRequest(resource='router', msg=msg)
|
|
return net_partition
|
|
|
|
def create_router(self, context, router):
|
|
net_partition = self._get_net_partition_for_router(context, router)
|
|
neutron_router = super(NuagePlugin, self).create_router(context,
|
|
router)
|
|
params = {
|
|
'net_partition': net_partition,
|
|
'tenant_id': neutron_router['tenant_id']
|
|
}
|
|
try:
|
|
nuage_router = self.nuageclient.create_router(neutron_router,
|
|
router['router'],
|
|
params)
|
|
except Exception:
|
|
with excutils.save_and_reraise_exception():
|
|
super(NuagePlugin, self).delete_router(context,
|
|
neutron_router['id'])
|
|
|
|
if nuage_router:
|
|
with context.session.begin(subtransactions=True):
|
|
nuagedb.add_entrouter_mapping(context.session,
|
|
net_partition['id'],
|
|
neutron_router['id'],
|
|
nuage_router['nuage_domain_id'])
|
|
|
|
return neutron_router
|
|
|
|
def _validate_nuage_staticroutes(self, old_routes, added, removed):
|
|
cidrs = []
|
|
for old in old_routes:
|
|
if old not in removed:
|
|
ip = netaddr.IPNetwork(old['destination'])
|
|
cidrs.append(ip)
|
|
for route in added:
|
|
ip = netaddr.IPNetwork(route['destination'])
|
|
matching = netaddr.all_matching_cidrs(ip.ip, cidrs)
|
|
if matching:
|
|
msg = _('for same subnet, multiple static routes not allowed')
|
|
raise n_exc.BadRequest(resource='router', msg=msg)
|
|
cidrs.append(ip)
|
|
|
|
def update_router(self, context, id, router):
|
|
r = router['router']
|
|
with context.session.begin(subtransactions=True):
|
|
if 'routes' in r:
|
|
old_routes = self._get_extra_routes_by_router_id(context,
|
|
id)
|
|
added, removed = utils.diff_list_of_dict(old_routes,
|
|
r['routes'])
|
|
self._validate_nuage_staticroutes(old_routes, added, removed)
|
|
|
|
ent_rtr_mapping = nuagedb.get_ent_rtr_mapping_by_rtrid(
|
|
context.session, id)
|
|
if not ent_rtr_mapping:
|
|
msg = (_("Router %s does not hold net-partition "
|
|
"assoc on VSD. extra-route failed") % id)
|
|
raise n_exc.BadRequest(resource='router', msg=msg)
|
|
# Let it do internal checks first and verify it.
|
|
router_updated = super(NuagePlugin,
|
|
self).update_router(context,
|
|
id,
|
|
router)
|
|
for route in removed:
|
|
destaddr = route['destination']
|
|
cidr = destaddr.split('/')
|
|
params = {
|
|
"address": cidr[0],
|
|
"nexthop": route['nexthop'],
|
|
"nuage_domain_id": ent_rtr_mapping['nuage_router_id']
|
|
}
|
|
self.nuageclient.delete_nuage_staticroute(params)
|
|
|
|
for route in added:
|
|
params = {
|
|
'parent_id': ent_rtr_mapping['nuage_router_id'],
|
|
'net': netaddr.IPNetwork(route['destination']),
|
|
'nexthop': route['nexthop']
|
|
}
|
|
self.nuageclient.create_nuage_staticroute(
|
|
params)
|
|
else:
|
|
router_updated = super(NuagePlugin, self).update_router(
|
|
context, id, router)
|
|
return router_updated
|
|
|
|
def delete_router(self, context, id):
|
|
neutron_router = self.get_router(context, id)
|
|
session = context.session
|
|
ent_rtr_mapping = nuagedb.get_ent_rtr_mapping_by_rtrid(session,
|
|
id)
|
|
if ent_rtr_mapping:
|
|
filters = {
|
|
'device_id': [id],
|
|
'device_owner': [os_constants.DEVICE_OWNER_ROUTER_INTF]
|
|
}
|
|
ports = self.get_ports(context, filters)
|
|
if ports:
|
|
raise l3.RouterInUse(router_id=id)
|
|
nuage_domain_id = ent_rtr_mapping['nuage_router_id']
|
|
self.nuageclient.delete_router(nuage_domain_id)
|
|
|
|
super(NuagePlugin, self).delete_router(context, id)
|
|
|
|
if not self._check_router_subnet_for_tenant(
|
|
context, neutron_router['tenant_id']):
|
|
user_id, group_id = self.nuageclient.get_usergroup(
|
|
neutron_router['tenant_id'],
|
|
ent_rtr_mapping['net_partition_id'])
|
|
self.nuageclient.delete_user(user_id)
|
|
self.nuageclient.delete_group(group_id)
|
|
|
|
def _make_net_partition_dict(self, net_partition, fields=None):
|
|
res = {
|
|
'id': net_partition['id'],
|
|
'name': net_partition['name'],
|
|
'l3dom_tmplt_id': net_partition['l3dom_tmplt_id'],
|
|
'l2dom_tmplt_id': net_partition['l2dom_tmplt_id'],
|
|
}
|
|
return self._fields(res, fields)
|
|
|
|
def _create_net_partition(self, session, net_part_name):
|
|
fip_quota = cfg.CONF.RESTPROXY.default_floatingip_quota
|
|
params = {
|
|
"name": net_part_name,
|
|
"fp_quota": str(fip_quota)
|
|
}
|
|
nuage_net_partition = self.nuageclient.create_net_partition(params)
|
|
net_partitioninst = None
|
|
if nuage_net_partition:
|
|
nuage_entid = nuage_net_partition['nuage_entid']
|
|
l3dom_id = nuage_net_partition['l3dom_id']
|
|
l2dom_id = nuage_net_partition['l2dom_id']
|
|
with session.begin():
|
|
net_partitioninst = nuagedb.add_net_partition(session,
|
|
nuage_entid,
|
|
l3dom_id,
|
|
l2dom_id,
|
|
net_part_name)
|
|
if not net_partitioninst:
|
|
return {}
|
|
return self._make_net_partition_dict(net_partitioninst)
|
|
|
|
def _create_default_net_partition(self, default_net_part):
|
|
def_netpart = self.nuageclient.get_def_netpartition_data(
|
|
default_net_part)
|
|
session = db.get_session()
|
|
if def_netpart:
|
|
net_partition = nuagedb.get_net_partition_by_name(
|
|
session, default_net_part)
|
|
with session.begin(subtransactions=True):
|
|
if net_partition:
|
|
nuagedb.delete_net_partition(session, net_partition)
|
|
net_part = nuagedb.add_net_partition(session,
|
|
def_netpart['np_id'],
|
|
def_netpart['l3dom_tid'],
|
|
def_netpart['l2dom_tid'],
|
|
default_net_part)
|
|
return self._make_net_partition_dict(net_part)
|
|
else:
|
|
return self._create_net_partition(session, default_net_part)
|
|
|
|
def create_net_partition(self, context, net_partition):
|
|
ent = net_partition['net_partition']
|
|
session = context.session
|
|
return self._create_net_partition(session, ent["name"])
|
|
|
|
def delete_net_partition(self, context, id):
|
|
ent_rtr_mapping = nuagedb.get_ent_rtr_mapping_by_entid(context.session,
|
|
id)
|
|
if ent_rtr_mapping:
|
|
msg = (_("One or more router still attached to "
|
|
"net_partition %s.") % id)
|
|
raise n_exc.BadRequest(resource='net_partition', msg=msg)
|
|
net_partition = nuagedb.get_net_partition_by_id(context.session, id)
|
|
if not net_partition:
|
|
msg = (_("NetPartition with %s does not exist") % id)
|
|
raise n_exc.BadRequest(resource='net_partition', msg=msg)
|
|
l3dom_tmplt_id = net_partition['l3dom_tmplt_id']
|
|
l2dom_tmplt_id = net_partition['l2dom_tmplt_id']
|
|
self.nuageclient.delete_net_partition(net_partition['id'],
|
|
l3dom_id=l3dom_tmplt_id,
|
|
l2dom_id=l2dom_tmplt_id)
|
|
with context.session.begin(subtransactions=True):
|
|
nuagedb.delete_net_partition(context.session,
|
|
net_partition)
|
|
|
|
def get_net_partition(self, context, id, fields=None):
|
|
net_partition = nuagedb.get_net_partition_by_id(context.session,
|
|
id)
|
|
return self._make_net_partition_dict(net_partition)
|
|
|
|
def get_net_partitions(self, context, filters=None, fields=None):
|
|
net_partitions = nuagedb.get_net_partitions(context.session,
|
|
filters=filters,
|
|
fields=fields)
|
|
return [self._make_net_partition_dict(net_partition, fields)
|
|
for net_partition in net_partitions]
|
|
|
|
def _check_floatingip_update(self, context, port):
|
|
filter = {'fixed_port_id': [port['id']]}
|
|
local_fip = self.get_floatingips(context,
|
|
filters=filter)
|
|
if local_fip:
|
|
fip = local_fip[0]
|
|
self._create_update_floatingip(context,
|
|
fip, port['id'])
|
|
|
|
def _create_update_floatingip(self, context,
|
|
neutron_fip, port_id):
|
|
rtr_id = neutron_fip['router_id']
|
|
net_id = neutron_fip['floating_network_id']
|
|
subn = nuagedb.get_ipalloc_for_fip(context.session,
|
|
net_id,
|
|
neutron_fip['floating_ip_address'])
|
|
|
|
fip_pool = self.nuageclient.get_nuage_fip_pool_by_id(subn['subnet_id'])
|
|
if not fip_pool:
|
|
msg = _('sharedresource %s not found on VSD') % subn['subnet_id']
|
|
raise n_exc.BadRequest(resource='floatingip',
|
|
msg=msg)
|
|
|
|
ent_rtr_mapping = nuagedb.get_ent_rtr_mapping_by_rtrid(context.session,
|
|
rtr_id)
|
|
if not ent_rtr_mapping:
|
|
msg = _('router %s is not associated with '
|
|
'any net-partition') % rtr_id
|
|
raise n_exc.BadRequest(resource='floatingip',
|
|
msg=msg)
|
|
|
|
params = {
|
|
'router_id': ent_rtr_mapping['nuage_router_id'],
|
|
'fip_id': neutron_fip['id'],
|
|
'neutron_fip': neutron_fip
|
|
}
|
|
|
|
fip = self.nuageclient.get_nuage_fip_by_id(params)
|
|
if not fip:
|
|
params = {
|
|
'nuage_rtr_id': ent_rtr_mapping['nuage_router_id'],
|
|
'nuage_fippool_id': fip_pool['nuage_fip_pool_id'],
|
|
'neutron_fip_ip': neutron_fip['floating_ip_address'],
|
|
'neutron_fip_id': neutron_fip['id']
|
|
}
|
|
nuage_fip_id = self.nuageclient.create_nuage_floatingip(params)
|
|
else:
|
|
nuage_fip_id = fip['nuage_fip_id']
|
|
|
|
# Update VM if required
|
|
params = {
|
|
'neutron_port_id': port_id,
|
|
'nuage_fip_id': nuage_fip_id,
|
|
'nuage_rtr_id': ent_rtr_mapping['nuage_router_id']
|
|
}
|
|
nuage_port = self.nuageclient.get_nuage_port_by_id(params)
|
|
if nuage_port:
|
|
if (nuage_port['nuage_domain_id']) != (
|
|
ent_rtr_mapping['nuage_router_id']):
|
|
msg = _('Floating IP can not be associated to VM in '
|
|
'different router context')
|
|
raise nuage_exc.OperationNotSupported(msg=msg)
|
|
|
|
params = {
|
|
'nuage_vport_id': nuage_port['nuage_vport_id'],
|
|
'nuage_fip_id': nuage_fip_id
|
|
}
|
|
self.nuageclient.update_nuage_vm_vport(params)
|
|
|
|
def create_floatingip(self, context, floatingip):
|
|
fip = floatingip['floatingip']
|
|
with context.session.begin(subtransactions=True):
|
|
neutron_fip = super(NuagePlugin, self).create_floatingip(
|
|
context, floatingip)
|
|
if not neutron_fip['router_id']:
|
|
return neutron_fip
|
|
try:
|
|
self._create_update_floatingip(context, neutron_fip,
|
|
fip['port_id'])
|
|
except (nuage_exc.OperationNotSupported, n_exc.BadRequest):
|
|
with excutils.save_and_reraise_exception():
|
|
super(NuagePlugin, self).delete_floatingip(
|
|
context, neutron_fip['id'])
|
|
return neutron_fip
|
|
|
|
def disassociate_floatingips(self, context, port_id, do_notify=True):
|
|
router_ids = super(NuagePlugin, self).disassociate_floatingips(
|
|
context, port_id, do_notify=do_notify)
|
|
|
|
params = {
|
|
'neutron_port_id': port_id,
|
|
}
|
|
nuage_port = self.nuageclient.get_nuage_port_by_id(params)
|
|
if nuage_port:
|
|
params = {
|
|
'nuage_vport_id': nuage_port['nuage_vport_id'],
|
|
'nuage_fip_id': None
|
|
}
|
|
self.nuageclient.update_nuage_vm_vport(params)
|
|
|
|
return router_ids
|
|
|
|
def update_floatingip(self, context, id, floatingip):
|
|
fip = floatingip['floatingip']
|
|
orig_fip = self._get_floatingip(context, id)
|
|
port_id = orig_fip['fixed_port_id']
|
|
router_ids = []
|
|
with context.session.begin(subtransactions=True):
|
|
neutron_fip = super(NuagePlugin, self).update_floatingip(
|
|
context, id, floatingip)
|
|
if fip['port_id'] is not None:
|
|
if not neutron_fip['router_id']:
|
|
ret_msg = 'floating-ip is not associated yet'
|
|
raise n_exc.BadRequest(resource='floatingip',
|
|
msg=ret_msg)
|
|
|
|
try:
|
|
self._create_update_floatingip(context,
|
|
neutron_fip,
|
|
fip['port_id'])
|
|
except nuage_exc.OperationNotSupported:
|
|
with excutils.save_and_reraise_exception():
|
|
router_ids = super(
|
|
NuagePlugin, self).disassociate_floatingips(
|
|
context, fip['port_id'], do_notify=False)
|
|
except n_exc.BadRequest:
|
|
with excutils.save_and_reraise_exception():
|
|
super(NuagePlugin, self).delete_floatingip(context,
|
|
id)
|
|
else:
|
|
params = {
|
|
'neutron_port_id': port_id,
|
|
}
|
|
nuage_port = self.nuageclient.get_nuage_port_by_id(params)
|
|
if nuage_port:
|
|
params = {
|
|
'nuage_vport_id': nuage_port['nuage_vport_id'],
|
|
'nuage_fip_id': None
|
|
}
|
|
self.nuageclient.update_nuage_vm_vport(params)
|
|
|
|
# now that we've left db transaction, we are safe to notify
|
|
self.notify_routers_updated(context, router_ids)
|
|
|
|
return neutron_fip
|
|
|
|
def delete_floatingip(self, context, fip_id):
|
|
fip = self._get_floatingip(context, fip_id)
|
|
port_id = fip['fixed_port_id']
|
|
with context.session.begin(subtransactions=True):
|
|
if port_id:
|
|
params = {
|
|
'neutron_port_id': port_id,
|
|
}
|
|
nuage_port = self.nuageclient.get_nuage_port_by_id(params)
|
|
if (nuage_port and
|
|
nuage_port['nuage_vport_id'] is not None):
|
|
params = {
|
|
'nuage_vport_id': nuage_port['nuage_vport_id'],
|
|
'nuage_fip_id': None
|
|
}
|
|
self.nuageclient.update_nuage_vm_vport(params)
|
|
LOG.debug("Floating-ip %(fip)s is disassociated from "
|
|
"vport %(vport)s",
|
|
{'fip': fip_id,
|
|
'vport': nuage_port['nuage_vport_id']})
|
|
|
|
router_id = fip['router_id']
|
|
else:
|
|
router_id = fip['last_known_router_id']
|
|
|
|
if router_id:
|
|
ent_rtr_mapping = nuagedb.get_ent_rtr_mapping_by_rtrid(
|
|
context.session,
|
|
router_id)
|
|
if not ent_rtr_mapping:
|
|
msg = _('router %s is not associated with '
|
|
'any net-partition') % router_id
|
|
raise n_exc.BadRequest(resource='floatingip',
|
|
msg=msg)
|
|
params = {
|
|
'router_id': ent_rtr_mapping['nuage_router_id'],
|
|
'fip_id': fip_id
|
|
}
|
|
fip = self.nuageclient.get_nuage_fip_by_id(params)
|
|
if fip:
|
|
self.nuageclient.delete_nuage_floatingip(
|
|
fip['nuage_fip_id'])
|
|
LOG.debug('Floating-ip %s deleted from VSD', fip_id)
|
|
|
|
super(NuagePlugin, self).delete_floatingip(context, fip_id)
|
|
|
|
def delete_security_group(self, context, id):
|
|
filters = {'security_group_id': [id]}
|
|
ports = self._get_port_security_group_bindings(context,
|
|
filters)
|
|
if ports:
|
|
raise ext_sg.SecurityGroupInUse(id=id)
|
|
sg_rules = self.get_security_group_rules(context,
|
|
{'security_group_id': [id]})
|
|
|
|
if sg_rules:
|
|
self.nuageclient.delete_nuage_sgrule(sg_rules)
|
|
self.nuageclient.delete_nuage_secgroup(id)
|
|
|
|
super(NuagePlugin, self).delete_security_group(context, id)
|
|
|
|
def create_security_group_rule(self, context, security_group_rule):
|
|
sg_rule = security_group_rule['security_group_rule']
|
|
self.nuageclient.validate_nuage_sg_rule_definition(sg_rule)
|
|
sg_id = sg_rule['security_group_id']
|
|
|
|
local_sg_rule = super(NuagePlugin,
|
|
self).create_security_group_rule(
|
|
context, security_group_rule)
|
|
|
|
try:
|
|
nuage_vptag = self.nuageclient.get_sg_vptag_mapping(sg_id)
|
|
if nuage_vptag:
|
|
sg_params = {
|
|
'sg_id': sg_id,
|
|
'neutron_sg_rule': local_sg_rule,
|
|
'vptag': nuage_vptag
|
|
}
|
|
self.nuageclient.create_nuage_sgrule(sg_params)
|
|
except Exception:
|
|
with excutils.save_and_reraise_exception():
|
|
super(NuagePlugin,
|
|
self).delete_security_group_rule(context,
|
|
local_sg_rule['id'])
|
|
|
|
return local_sg_rule
|
|
|
|
def delete_security_group_rule(self, context, id):
|
|
local_sg_rule = self.get_security_group_rule(context, id)
|
|
super(NuagePlugin, self).delete_security_group_rule(context, id)
|
|
self.nuageclient.delete_nuage_sgrule([local_sg_rule])
|