from neutron.plugins.nicira.extensions import nvp_networkgw as networkgw
from neutron.plugins.nicira.extensions import nvp_qos as ext_qos
from neutron.plugins.nicira.nsxlib import queue as queuelib
+from neutron.plugins.nicira.nsxlib import router as routerlib
from neutron.plugins.nicira import NvpApiClient
from neutron.plugins.nicira import nvplib
port_data['fixed_ips'],
subnet_ids))
try:
- lrouter_port = nvplib.create_router_lport(
+ lrouter_port = routerlib.create_router_lport(
cluster, nsx_router_id, port_data.get('tenant_id', 'fake'),
port_data.get('id', 'fake'), port_data.get('name', 'fake'),
port_data.get('admin_state_up', True), ip_addresses,
# Be safe and concede NAT rules might not exist.
# Therefore use min_num_expected=0
for cidr in cidrs:
- nvplib.delete_nat_rules_by_match(
+ routerlib.delete_nat_rules_by_match(
self.cluster, nsx_router_id, "SourceNatRule",
max_num_expected=1, min_num_expected=0,
source_ip_addresses=cidr)
# Set the SNAT rule for each subnet (only first IP)
for cidr in cidrs:
cidr_prefix = int(cidr.split('/')[1])
- nvplib.create_lrouter_snat_rule(
+ routerlib.create_lrouter_snat_rule(
self.cluster, nsx_router_id,
ip_addresses[0].split('/')[0],
ip_addresses[0].split('/')[0],
def _update_router_port_attachment(self, cluster, context,
nsx_router_id, port_data,
- nvp_router_port_id,
+ nsx_router_port_id,
attachment_type,
attachment,
attachment_vlan=None):
- if not nvp_router_port_id:
- nvp_router_port_id = self._find_router_gw_port(context, port_data)
+ if not nsx_router_port_id:
+ nsx_router_port_id = self._find_router_gw_port(context, port_data)
try:
- nvplib.plug_router_port_attachment(cluster, nsx_router_id,
- nvp_router_port_id,
- attachment,
- attachment_type,
- attachment_vlan)
+ routerlib.plug_router_port_attachment(cluster, nsx_router_id,
+ nsx_router_port_id,
+ attachment,
+ attachment_type,
+ attachment_vlan)
LOG.debug(_("Attached %(att)s to NVP router port %(port)s"),
- {'att': attachment, 'port': nvp_router_port_id})
+ {'att': attachment, 'port': nsx_router_port_id})
except NvpApiClient.NvpApiException:
# Must remove NVP logical port
- nvplib.delete_router_lport(cluster, nsx_router_id,
- nvp_router_port_id)
+ routerlib.delete_router_lport(cluster, nsx_router_id,
+ nsx_router_port_id)
LOG.exception(_("Unable to plug attachment in NVP logical "
"router port %(r_port_id)s, associated with "
"Neutron %(q_port_id)s"),
- {'r_port_id': nvp_router_port_id,
+ {'r_port_id': nsx_router_port_id,
'q_port_id': port_data.get('id')})
raise nvp_exc.NvpPluginException(
err_msg=(_("Unable to plug attachment in router port "
"%(r_port_id)s for neutron port id %(q_port_id)s "
"on router %(router_id)s") %
- {'r_port_id': nvp_router_port_id,
+ {'r_port_id': nsx_router_port_id,
'q_port_id': port_data.get('id'),
'router_id': nsx_router_id}))
# Delete logical router port
nsx_router_id = nsx_utils.get_nsx_router_id(
context.session, self.cluster, port_data['device_id'])
- nvp_switch_id, nvp_port_id = nsx_utils.get_nsx_switch_and_port_id(
+ nsx_switch_id, nsx_port_id = nsx_utils.get_nsx_switch_and_port_id(
context.session, self.cluster, port_data['id'])
- if not nvp_port_id:
+ if not nsx_port_id:
LOG.warn(_("Neutron port %(port_id)s not found on NVP backend. "
"Terminating delete operation. A dangling router port "
"might have been left on router %(router_id)s"),
'router_id': nsx_router_id})
return
try:
- nvplib.delete_peer_router_lport(self.cluster,
- nsx_router_id,
- nvp_switch_id,
- nvp_port_id)
+ routerlib.delete_peer_router_lport(self.cluster,
+ nsx_router_id,
+ nsx_switch_id,
+ nsx_port_id)
except NvpApiClient.NvpApiException:
# Do not raise because the issue might as well be that the
# router has already been deleted, so there would be nothing
# to do here
LOG.exception(_("Ignoring exception as this means the peer "
"for port '%s' has already been deleted."),
- nvp_port_id)
+ nsx_port_id)
# Delete logical switch port
self._nvp_delete_port(context, port_data)
port_data['network_id'])
nsx_router_id = nsx_utils.get_nsx_router_id(
context.session, self.cluster, router_id)
- lr_port = nvplib.find_router_gw_port(context, self.cluster,
- nsx_router_id)
+ lr_port = routerlib.find_router_gw_port(context, self.cluster,
+ nsx_router_id)
if not lr_port:
raise nvp_exc.NvpPluginException(
err_msg=(_("The gateway port for the NSX router %s "
# regardless of what the user specifies in neutron
nsx_router_id = nsx_utils.get_nsx_router_id(
context.session, self.cluster, port_data['device_id'])
- nvplib.update_router_lport(self.cluster,
- nsx_router_id,
- lr_port['uuid'],
- port_data['tenant_id'],
- port_data['id'],
- port_data['name'],
- True,
- ip_addresses)
+ routerlib.update_router_lport(self.cluster,
+ nsx_router_id,
+ lr_port['uuid'],
+ port_data['tenant_id'],
+ port_data['id'],
+ port_data['name'],
+ True,
+ ip_addresses)
ext_network = self.get_network(context, port_data['network_id'])
if ext_network.get(pnet.NETWORK_TYPE) == NetworkTypes.L3_EXT:
# Update attachment
router_id = port_data['device_id']
nsx_router_id = nsx_utils.get_nsx_router_id(
context.session, self.cluster, router_id)
- nvplib.update_router_lport(self.cluster,
- nsx_router_id,
- lr_port['uuid'],
- port_data['tenant_id'],
- port_data['id'],
- port_data['name'],
- True,
- ['0.0.0.0/31'])
+ routerlib.update_router_lport(self.cluster,
+ nsx_router_id,
+ lr_port['uuid'],
+ port_data['tenant_id'],
+ port_data['id'],
+ port_data['name'],
+ True,
+ ['0.0.0.0/31'])
# Reset attachment
self._update_router_port_attachment(
self.cluster, context, nsx_router_id, port_data,
'device_owner': ['network:router_interface']}
router_iface_ports = self.get_ports(context, filters=port_filter)
for port in router_iface_ports:
- nvp_switch_id, nvp_port_id = nsx_utils.get_nsx_switch_and_port_id(
+ nsx_switch_id, nsx_port_id = nsx_utils.get_nsx_switch_and_port_id(
context.session, self.cluster, id)
# Before removing entry from Neutron DB, retrieve NSX switch
# identifiers for removing them from backend
# clean up network owned ports
for port in router_iface_ports:
try:
- if nvp_port_id:
+ if nsx_port_id:
nsx_router_id = nsx_utils.get_nsx_router_id(
context.session, self.cluster, port['device_id'])
- nvplib.delete_peer_router_lport(self.cluster,
- nsx_router_id,
- nvp_switch_id,
- nvp_port_id)
+ routerlib.delete_peer_router_lport(self.cluster,
+ nsx_router_id,
+ nsx_switch_id,
+ nsx_port_id)
else:
LOG.warning(_("A nvp lport identifier was not found for "
"neutron port '%s'. Unable to remove "
# to do here
LOG.warning(_("Ignoring exception as this means the peer for "
"port '%s' has already been deleted."),
- nvp_port_id)
+ nsx_port_id)
# Do not go to NVP for external networks
if not external:
tenant_id = self._get_tenant_id_for_create(context, router)
distributed = router.get('distributed')
try:
- lrouter = nvplib.create_lrouter(
+ lrouter = routerlib.create_lrouter(
self.cluster, router['id'],
tenant_id, router['name'], nexthop,
distributed=attr.is_attr_set(distributed) and distributed)
'def_l3_gw_svc':
self.cluster.default_l3_gw_service_uuid})
# Try and remove logical router from NVP
- nvplib.delete_lrouter(self.cluster, lrouter['uuid'])
+ routerlib.delete_lrouter(self.cluster, lrouter['uuid'])
# Return user a 500 with an apter message
raise nvp_exc.NvpPluginException(
err_msg=(_("Unable to create router %s on NSX backend") %
def _update_lrouter(self, context, router_id, name, nexthop, routes=None):
nsx_router_id = nsx_utils.get_nsx_router_id(
context.session, self.cluster, router_id)
- return nvplib.update_lrouter(
+ return routerlib.update_lrouter(
self.cluster, nsx_router_id, name,
nexthop, routes=routes)
def _update_lrouter_routes(self, context, router_id, routes):
nsx_router_id = nsx_utils.get_nsx_router_id(
context.session, self.cluster, router_id)
- nvplib.update_explicit_routes_lrouter(
+ routerlib.update_explicit_routes_lrouter(
self.cluster, nsx_router_id, routes)
def update_router(self, context, router_id, router):
def _delete_lrouter(self, context, router_id, nsx_router_id):
# The neutron router id (router_id) is ignored in this routine,
# but used in plugins deriving from this one
- nvplib.delete_lrouter(self.cluster, nsx_router_id)
+ routerlib.delete_lrouter(self.cluster, nsx_router_id)
def delete_router(self, context, router_id):
with context.session.begin(subtransactions=True):
cidr_prefix = int(subnet['cidr'].split('/')[1])
nsx_router_id = nsx_utils.get_nsx_router_id(
context.session, self.cluster, router['id'])
- nvplib.create_lrouter_snat_rule(
+ routerlib.create_lrouter_snat_rule(
self.cluster, nsx_router_id, snat_ip, snat_ip,
order=NVP_EXTGW_NAT_RULES_ORDER - cidr_prefix,
match_criteria={'source_ip_addresses': subnet['cidr']})
if router.gw_port:
nsx_router_id = nsx_utils.get_nsx_router_id(
context.session, self.cluster, router['id'])
- nvplib.delete_nat_rules_by_match(
+ routerlib.delete_nat_rules_by_match(
self.cluster, nsx_router_id, "SourceNatRule",
max_num_expected=1, min_num_expected=1,
source_ip_addresses=subnet['cidr'])
# Fetch router from DB
router = self._get_router(context, router_id)
self._add_subnet_snat_rule(context, router, subnet)
- nvplib.create_lrouter_nosnat_rule(
+ routerlib.create_lrouter_nosnat_rule(
self.cluster, nsx_router_id,
order=NVP_NOSNAT_RULES_ORDER,
match_criteria={'destination_ip_addresses': subnet['cidr']})
# do not exist in 2.x deployments
nsx_router_id = nsx_utils.get_nsx_router_id(
context.session, self.cluster, router_id)
- nvplib.delete_nat_rules_by_match(
+ routerlib.delete_nat_rules_by_match(
self.cluster, nsx_router_id, "NoSourceNatRule",
max_num_expected=1, min_num_expected=0,
destination_ip_addresses=subnet['cidr'])
# but used by derived classes
try:
# Remove DNAT rule for the floating IP
- nvplib.delete_nat_rules_by_match(
+ routerlib.delete_nat_rules_by_match(
self.cluster, nsx_router_id, "DestinationNatRule",
max_num_expected=1,
min_num_expected=min_num_rules_expected,
destination_ip_addresses=floating_ip_address)
# Remove SNAT rules for the floating IP
- nvplib.delete_nat_rules_by_match(
+ routerlib.delete_nat_rules_by_match(
self.cluster, nsx_router_id, "SourceNatRule",
max_num_expected=1,
min_num_expected=min_num_rules_expected,
source_ip_addresses=internal_ip)
- nvplib.delete_nat_rules_by_match(
+ routerlib.delete_nat_rules_by_match(
self.cluster, nsx_router_id, "SourceNatRule",
max_num_expected=1,
min_num_expected=min_num_rules_expected,
router_id = fip_db.router_id
nsx_router_id = nsx_utils.get_nsx_router_id(
context.session, self.cluster, router_id)
- nvp_gw_port_id = nvplib.find_router_gw_port(
+ nsx_gw_port_id = routerlib.find_router_gw_port(
context, self.cluster, nsx_router_id)['uuid']
ext_neutron_port_db = self._get_port(context.elevated(),
fip_db.floating_port_id)
- nvp_floating_ips = self._build_ip_address_list(
+ nsx_floating_ips = self._build_ip_address_list(
context.elevated(), ext_neutron_port_db['fixed_ips'])
- nvplib.update_lrouter_port_ips(self.cluster,
- nsx_router_id,
- nvp_gw_port_id,
- ips_to_add=[],
- ips_to_remove=nvp_floating_ips)
+ routerlib.update_lrouter_port_ips(self.cluster,
+ nsx_router_id,
+ nsx_gw_port_id,
+ ips_to_add=[],
+ ips_to_remove=nsx_floating_ips)
def _get_fip_assoc_data(self, context, fip, floatingip_db):
if (('fixed_ip_address' in fip and fip['fixed_ip_address']) and
'port_id': floatingip_db.fixed_port_id,
'fixed_ip_address': floatingip_db.fixed_ip_address,
'tenant_id': floatingip_db.tenant_id})
- nvp_gw_port_id = nvplib.find_router_gw_port(
+ nsx_gw_port_id = routerlib.find_router_gw_port(
context, self.cluster, nsx_old_router_id)['uuid']
self._retrieve_and_delete_nat_rules(
context, floating_ip, old_internal_ip, nsx_old_router_id)
- nvplib.update_lrouter_port_ips(
- self.cluster, nsx_old_router_id, nvp_gw_port_id,
+ routerlib.update_lrouter_port_ips(
+ self.cluster, nsx_old_router_id, nsx_gw_port_id,
ips_to_add=[], ips_to_remove=nvp_floating_ips)
if router_id:
- nvp_gw_port_id = nvplib.find_router_gw_port(
+ nsx_gw_port_id = routerlib.find_router_gw_port(
context, self.cluster, nsx_router_id)['uuid']
# Re-create NAT rules only if a port id is specified
if fip.get('port_id'):
try:
# Setup DNAT rules for the floating IP
- nvplib.create_lrouter_dnat_rule(
+ routerlib.create_lrouter_dnat_rule(
self.cluster, nsx_router_id, internal_ip,
order=NVP_FLOATINGIP_NAT_RULES_ORDER,
match_criteria={'destination_ip_addresses':
internal_subnet_cidr = self._build_ip_address_list(
context, internal_port['fixed_ips'],
subnet_ids=subnet_ids)[0]
- nvplib.create_lrouter_snat_rule(
+ routerlib.create_lrouter_snat_rule(
self.cluster, nsx_router_id, floating_ip, floating_ip,
order=NVP_NOSNAT_RULES_ORDER - 1,
match_criteria={'source_ip_addresses':
internal_ip})
# setup snat rule such that src ip of a IP packet when
# using floating is the floating ip itself.
- nvplib.create_lrouter_snat_rule(
+ routerlib.create_lrouter_snat_rule(
self.cluster, nsx_router_id, floating_ip, floating_ip,
order=NVP_FLOATINGIP_NAT_RULES_ORDER,
match_criteria={'source_ip_addresses': internal_ip})
# Add Floating IP address to router_port
- nvplib.update_lrouter_port_ips(self.cluster,
- nsx_router_id,
- nvp_gw_port_id,
- ips_to_add=nvp_floating_ips,
- ips_to_remove=[])
+ routerlib.update_lrouter_port_ips(
+ self.cluster, nsx_router_id, nsx_gw_port_id,
+ ips_to_add=nvp_floating_ips, ips_to_remove=[])
except NvpApiClient.NvpApiException:
LOG.exception(_("An error occurred while creating NAT "
"rules on the NVP platform for floating "
from neutron.plugins.nicira.dbexts import vcns_models
from neutron.plugins.nicira.extensions import servicerouter as sr
from neutron.plugins.nicira import NeutronPlugin
+from neutron.plugins.nicira.nsxlib import router as routerlib
from neutron.plugins.nicira import NvpApiClient
from neutron.plugins.nicira import nvplib
from neutron.plugins.nicira.vshield.common import (
neutron_port_id = ''
pname = name[:36] + '-lp'
admin_status_enabled = True
- lr_port = nvplib.create_router_lport(
+ lr_port = routerlib.create_router_lport(
self.cluster, lrouter['uuid'], tenant_id,
neutron_port_id, pname, admin_status_enabled,
[vcns_const.INTEGRATION_LR_IPADDRESS])
msg = _("Unable to create integration logic switch "
"for router %s") % name
LOG.exception(msg)
- nvplib.delete_lrouter(self.cluster, lrouter['uuid'])
+ routerlib.delete_lrouter(self.cluster, lrouter['uuid'])
raise q_exc.NeutronException(message=msg)
try:
msg = _("Unable to add router interface to integration lswitch "
"for router %s") % name
LOG.exception(msg)
- nvplib.delete_lrouter(self.cluster, lrouter['uuid'])
+ routerlib.delete_lrouter(self.cluster, lrouter['uuid'])
raise q_exc.NeutronException(message=msg)
try:
msg = (_("Unable to create advance service router for %s") % name)
LOG.exception(msg)
self.vcns_driver.delete_lswitch(lswitch('uuid'))
- nvplib.delete_lrouter(self.cluster, lrouter['uuid'])
+ routerlib.delete_lrouter(self.cluster, lrouter['uuid'])
raise q_exc.NeutronException(message=msg)
lrouter['status'] = service_constants.PENDING_CREATE
self.vcns_driver.delete_edge(router_id, edge_id, jobdata=jobdata)
# delete NSX logical router
- nvplib.delete_lrouter(self.cluster, nsx_router_id)
+ routerlib.delete_lrouter(self.cluster, nsx_router_id)
if id in self._router_type:
del self._router_type[router_id]
def _get_nvp_lrouter_status(self, id):
try:
- lrouter = nvplib.get_lrouter(self.cluster, id)
+ lrouter = routerlib.get_lrouter(self.cluster, id)
lr_status = lrouter["_relations"]["LogicalRouterStatus"]
if lr_status["fabric_status"]:
nvp_status = RouterStatus.ROUTER_STATUS_ACTIVE
def _get_all_nvp_lrouters_statuses(self, tenant_id, fields):
# get nvp lrouters status
- nvp_lrouters = nvplib.get_lrouters(self.cluster,
- tenant_id,
- fields)
+ nvp_lrouters = routerlib.get_lrouters(self.cluster,
+ tenant_id,
+ fields)
nvp_status = {}
for nvp_lrouter in nvp_lrouters:
from neutron.openstack.common import log
from neutron.plugins.nicira.dbexts import nicira_db
from neutron.plugins.nicira import nsx_cluster
+from neutron.plugins.nicira.nsxlib import router as routerlib
from neutron.plugins.nicira import NvpApiClient
from neutron.plugins.nicira import nvplib
# Find logical router from backend.
# This is a rather expensive query, but it won't be executed
# more than once for each router in Neutron's lifetime
- nsx_routers = nvplib.query_lrouters(
+ nsx_routers = routerlib.query_lrouters(
cluster, '*',
filters={'tag': neutron_router_id,
'tag_scope': 'q_router_id'})
from neutron.openstack.common import timeutils
from neutron.plugins.nicira.common import exceptions as nvp_exc
from neutron.plugins.nicira.common import nsx_utils
+from neutron.plugins.nicira.nsxlib import router as routerlib
from neutron.plugins.nicira import NvpApiClient
from neutron.plugins.nicira import nvplib
nvplib.LSWITCH_RESOURCE, fields='uuid,tags,fabric_status',
relations='LogicalSwitchStatus')
LR_URI = nvplib._build_uri_path(
- nvplib.LROUTER_RESOURCE, fields='uuid,tags,fabric_status',
+ routerlib.LROUTER_RESOURCE, fields='uuid,tags,fabric_status',
relations='LogicalRouterStatus')
LP_URI = nvplib._build_uri_path(
nvplib.LSWITCHPORT_RESOURCE,
# This query will return the logical router status too
nsx_router_id = nsx_utils.get_nsx_router_id(
context.session, self._cluster, neutron_router_data['id'])
- lrouter = nvplib.get_lrouter(
+ lrouter = routerlib.get_lrouter(
self._cluster, nsx_router_id)
except exceptions.NotFound:
# NOTE(salv-orlando): We should be catching
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2013 VMware, Inc.
-# All Rights Reserved
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
--- /dev/null
+# Copyright 2014 VMware, Inc.
+# All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from neutron.common import exceptions as exception
+from neutron.openstack.common import excutils
+from neutron.openstack.common import jsonutils
+from neutron.openstack.common import log
+from neutron.plugins.nicira.common import exceptions as nvp_exc
+from neutron.plugins.nicira.common import utils
+from neutron.plugins.nicira.nsxlib.versioning import DEFAULT_VERSION
+from neutron.plugins.nicira.nsxlib.versioning import versioned
+from neutron.plugins.nicira import NvpApiClient
+from neutron.plugins.nicira.nvplib import _build_uri_path
+from neutron.plugins.nicira.nvplib import do_request
+from neutron.plugins.nicira.nvplib import get_all_query_pages
+from neutron.plugins.nicira.nvplib import get_port
+
+HTTP_GET = "GET"
+HTTP_POST = "POST"
+HTTP_DELETE = "DELETE"
+HTTP_PUT = "PUT"
+
+LROUTER_RESOURCE = "lrouter"
+LROUTER_RESOURCE = "lrouter"
+LROUTERPORT_RESOURCE = "lport/%s" % LROUTER_RESOURCE
+LROUTERRIB_RESOURCE = "rib/%s" % LROUTER_RESOURCE
+LROUTERNAT_RESOURCE = "nat/lrouter"
+# Constants for NAT rules
+MATCH_KEYS = ["destination_ip_addresses", "destination_port_max",
+ "destination_port_min", "source_ip_addresses",
+ "source_port_max", "source_port_min", "protocol"]
+
+LOG = log.getLogger(__name__)
+
+
+def _prepare_lrouter_body(name, neutron_router_id, tenant_id,
+ router_type, distributed=None, **kwargs):
+ body = {
+ "display_name": utils.check_and_truncate(name),
+ "tags": utils.get_tags(os_tid=tenant_id,
+ q_router_id=neutron_router_id),
+ "routing_config": {
+ "type": router_type
+ },
+ "type": "LogicalRouterConfig"
+ }
+ # add the distributed key only if not None (ie: True or False)
+ if distributed is not None:
+ body['distributed'] = distributed
+ if kwargs:
+ body["routing_config"].update(kwargs)
+ return body
+
+
+def _create_implicit_routing_lrouter(cluster, neutron_router_id, tenant_id,
+ display_name, nexthop, distributed=None):
+ implicit_routing_config = {
+ "default_route_next_hop": {
+ "gateway_ip_address": nexthop,
+ "type": "RouterNextHop"
+ },
+ }
+ lrouter_obj = _prepare_lrouter_body(
+ display_name, neutron_router_id, tenant_id,
+ "SingleDefaultRouteImplicitRoutingConfig",
+ distributed=distributed,
+ **implicit_routing_config)
+ return do_request(HTTP_POST, _build_uri_path(LROUTER_RESOURCE),
+ jsonutils.dumps(lrouter_obj), cluster=cluster)
+
+
+def create_implicit_routing_lrouter(cluster, neutron_router_id, tenant_id,
+ display_name, nexthop):
+ """Create a NSX logical router on the specified cluster.
+
+ :param cluster: The target NSX cluster
+ :param tenant_id: Identifier of the Openstack tenant for which
+ the logical router is being created
+ :param display_name: Descriptive name of this logical router
+ :param nexthop: External gateway IP address for the logical router
+ :raise NvpApiException: if there is a problem while communicating
+ with the NSX controller
+ """
+ return _create_implicit_routing_lrouter(
+ cluster, neutron_router_id, tenant_id, display_name, nexthop)
+
+
+def create_implicit_routing_lrouter_with_distribution(
+ cluster, neutron_router_id, tenant_id, display_name,
+ nexthop, distributed=None):
+ """Create a NSX logical router on the specified cluster.
+
+ This function also allows for creating distributed lrouters
+ :param cluster: The target NSX cluster
+ :param tenant_id: Identifier of the Openstack tenant for which
+ the logical router is being created
+ :param display_name: Descriptive name of this logical router
+ :param nexthop: External gateway IP address for the logical router
+ :param distributed: True for distributed logical routers
+ :raise NvpApiException: if there is a problem while communicating
+ with the NSX controller
+ """
+ return _create_implicit_routing_lrouter(
+ cluster, neutron_router_id, tenant_id,
+ display_name, nexthop, distributed)
+
+
+def create_explicit_routing_lrouter(cluster, neutron_router_id, tenant_id,
+ display_name, nexthop, distributed=None):
+ lrouter_obj = _prepare_lrouter_body(
+ display_name, neutron_router_id, tenant_id,
+ "RoutingTableRoutingConfig", distributed=distributed)
+ router = do_request(HTTP_POST, _build_uri_path(LROUTER_RESOURCE),
+ jsonutils.dumps(lrouter_obj), cluster=cluster)
+ default_gw = {'prefix': '0.0.0.0/0', 'next_hop_ip': nexthop}
+ create_explicit_route_lrouter(cluster, router['uuid'], default_gw)
+ return router
+
+
+def delete_lrouter(cluster, lrouter_id):
+ do_request(HTTP_DELETE, _build_uri_path(LROUTER_RESOURCE,
+ resource_id=lrouter_id),
+ cluster=cluster)
+
+
+def get_lrouter(cluster, lrouter_id):
+ return do_request(HTTP_GET,
+ _build_uri_path(LROUTER_RESOURCE,
+ resource_id=lrouter_id,
+ relations='LogicalRouterStatus'),
+ cluster=cluster)
+
+
+def query_lrouters(cluster, fields=None, filters=None):
+ return get_all_query_pages(
+ _build_uri_path(LROUTER_RESOURCE,
+ fields=fields,
+ relations='LogicalRouterStatus',
+ filters=filters),
+ cluster)
+
+
+def get_lrouters(cluster, tenant_id, fields=None, filters=None):
+ # FIXME(salv-orlando): Fields parameter is ignored in this routine
+ actual_filters = {}
+ if filters:
+ actual_filters.update(filters)
+ if tenant_id:
+ actual_filters['tag'] = tenant_id
+ actual_filters['tag_scope'] = 'os_tid'
+ lrouter_fields = "uuid,display_name,fabric_status,tags"
+ return query_lrouters(cluster, lrouter_fields, actual_filters)
+
+
+def update_implicit_routing_lrouter(cluster, r_id, display_name, nexthop):
+ lrouter_obj = get_lrouter(cluster, r_id)
+ if not display_name and not nexthop:
+ # Nothing to update
+ return lrouter_obj
+ # It seems that this is faster than the doing an if on display_name
+ lrouter_obj["display_name"] = (utils.check_and_truncate(display_name) or
+ lrouter_obj["display_name"])
+ if nexthop:
+ nh_element = lrouter_obj["routing_config"].get(
+ "default_route_next_hop")
+ if nh_element:
+ nh_element["gateway_ip_address"] = nexthop
+ return do_request(HTTP_PUT, _build_uri_path(LROUTER_RESOURCE,
+ resource_id=r_id),
+ jsonutils.dumps(lrouter_obj),
+ cluster=cluster)
+
+
+def get_explicit_routes_lrouter(cluster, router_id, protocol_type='static'):
+ static_filter = {'protocol': protocol_type}
+ existing_routes = do_request(
+ HTTP_GET,
+ _build_uri_path(LROUTERRIB_RESOURCE,
+ filters=static_filter,
+ fields="*",
+ parent_resource_id=router_id),
+ cluster=cluster)['results']
+ return existing_routes
+
+
+def delete_explicit_route_lrouter(cluster, router_id, route_id):
+ do_request(HTTP_DELETE,
+ _build_uri_path(LROUTERRIB_RESOURCE,
+ resource_id=route_id,
+ parent_resource_id=router_id),
+ cluster=cluster)
+
+
+def create_explicit_route_lrouter(cluster, router_id, route):
+ next_hop_ip = route.get("nexthop") or route.get("next_hop_ip")
+ prefix = route.get("destination") or route.get("prefix")
+ uuid = do_request(
+ HTTP_POST,
+ _build_uri_path(LROUTERRIB_RESOURCE,
+ parent_resource_id=router_id),
+ jsonutils.dumps({
+ "action": "accept",
+ "next_hop_ip": next_hop_ip,
+ "prefix": prefix,
+ "protocol": "static"
+ }),
+ cluster=cluster)['uuid']
+ return uuid
+
+
+def update_explicit_routes_lrouter(cluster, router_id, routes):
+ # Update in bulk: delete them all, and add the ones specified
+ # but keep track of what is been modified to allow roll-backs
+ # in case of failures
+ nsx_routes = get_explicit_routes_lrouter(cluster, router_id)
+ try:
+ deleted_routes = []
+ added_routes = []
+ # omit the default route (0.0.0.0/0) from the processing;
+ # this must be handled through the nexthop for the router
+ for route in nsx_routes:
+ prefix = route.get("destination") or route.get("prefix")
+ if prefix != '0.0.0.0/0':
+ delete_explicit_route_lrouter(cluster,
+ router_id,
+ route['uuid'])
+ deleted_routes.append(route)
+ for route in routes:
+ prefix = route.get("destination") or route.get("prefix")
+ if prefix != '0.0.0.0/0':
+ uuid = create_explicit_route_lrouter(cluster,
+ router_id, route)
+ added_routes.append(uuid)
+ except NvpApiClient.NvpApiException:
+ LOG.exception(_('Cannot update NSX routes %(routes)s for '
+ 'router %(router_id)s'),
+ {'routes': routes, 'router_id': router_id})
+ # Roll back to keep NSX in consistent state
+ with excutils.save_and_reraise_exception():
+ if nsx_routes:
+ if deleted_routes:
+ for route in deleted_routes:
+ create_explicit_route_lrouter(cluster,
+ router_id, route)
+ if added_routes:
+ for route_id in added_routes:
+ delete_explicit_route_lrouter(cluster,
+ router_id, route_id)
+ return nsx_routes
+
+
+def get_default_route_explicit_routing_lrouter_v33(cluster, router_id):
+ static_filter = {"protocol": "static",
+ "prefix": "0.0.0.0/0"}
+ default_route = do_request(
+ HTTP_GET,
+ _build_uri_path(LROUTERRIB_RESOURCE,
+ filters=static_filter,
+ fields="*",
+ parent_resource_id=router_id),
+ cluster=cluster)["results"][0]
+ return default_route
+
+
+def get_default_route_explicit_routing_lrouter_v32(cluster, router_id):
+ # Scan all routes because 3.2 does not support query by prefix
+ all_routes = get_explicit_routes_lrouter(cluster, router_id)
+ for route in all_routes:
+ if route['prefix'] == '0.0.0.0/0':
+ return route
+
+
+def update_default_gw_explicit_routing_lrouter(cluster, router_id, next_hop):
+ default_route = get_default_route_explicit_routing_lrouter(cluster,
+ router_id)
+ if next_hop != default_route["next_hop_ip"]:
+ new_default_route = {"action": "accept",
+ "next_hop_ip": next_hop,
+ "prefix": "0.0.0.0/0",
+ "protocol": "static"}
+ do_request(HTTP_PUT,
+ _build_uri_path(LROUTERRIB_RESOURCE,
+ resource_id=default_route['uuid'],
+ parent_resource_id=router_id),
+ jsonutils.dumps(new_default_route),
+ cluster=cluster)
+
+
+def update_explicit_routing_lrouter(cluster, router_id,
+ display_name, next_hop, routes=None):
+ update_implicit_routing_lrouter(cluster, router_id, display_name, next_hop)
+ if next_hop:
+ update_default_gw_explicit_routing_lrouter(cluster,
+ router_id, next_hop)
+ if routes is not None:
+ return update_explicit_routes_lrouter(cluster, router_id, routes)
+
+
+def query_lrouter_lports(cluster, lr_uuid, fields="*",
+ filters=None, relations=None):
+ uri = _build_uri_path(LROUTERPORT_RESOURCE, parent_resource_id=lr_uuid,
+ fields=fields, filters=filters, relations=relations)
+ return do_request(HTTP_GET, uri, cluster=cluster)['results']
+
+
+def create_router_lport(cluster, lrouter_uuid, tenant_id, neutron_port_id,
+ display_name, admin_status_enabled, ip_addresses,
+ mac_address=None):
+ """Creates a logical port on the assigned logical router."""
+ lport_obj = dict(
+ admin_status_enabled=admin_status_enabled,
+ display_name=display_name,
+ tags=utils.get_tags(os_tid=tenant_id, q_port_id=neutron_port_id),
+ ip_addresses=ip_addresses,
+ type="LogicalRouterPortConfig"
+ )
+ # Only add the mac_address to lport_obj if present. This is because
+ # when creating the fake_ext_gw there is no mac_address present.
+ if mac_address:
+ lport_obj['mac_address'] = mac_address
+ path = _build_uri_path(LROUTERPORT_RESOURCE,
+ parent_resource_id=lrouter_uuid)
+ result = do_request(HTTP_POST, path, jsonutils.dumps(lport_obj),
+ cluster=cluster)
+
+ LOG.debug(_("Created logical port %(lport_uuid)s on "
+ "logical router %(lrouter_uuid)s"),
+ {'lport_uuid': result['uuid'],
+ 'lrouter_uuid': lrouter_uuid})
+ return result
+
+
+def update_router_lport(cluster, lrouter_uuid, lrouter_port_uuid,
+ tenant_id, neutron_port_id, display_name,
+ admin_status_enabled, ip_addresses):
+ """Updates a logical port on the assigned logical router."""
+ lport_obj = dict(
+ admin_status_enabled=admin_status_enabled,
+ display_name=display_name,
+ tags=utils.get_tags(os_tid=tenant_id, q_port_id=neutron_port_id),
+ ip_addresses=ip_addresses,
+ type="LogicalRouterPortConfig"
+ )
+ # Do not pass null items to NSX
+ for key in lport_obj.keys():
+ if lport_obj[key] is None:
+ del lport_obj[key]
+ path = _build_uri_path(LROUTERPORT_RESOURCE,
+ lrouter_port_uuid,
+ parent_resource_id=lrouter_uuid)
+ result = do_request(HTTP_PUT, path,
+ jsonutils.dumps(lport_obj),
+ cluster=cluster)
+ LOG.debug(_("Updated logical port %(lport_uuid)s on "
+ "logical router %(lrouter_uuid)s"),
+ {'lport_uuid': lrouter_port_uuid, 'lrouter_uuid': lrouter_uuid})
+ return result
+
+
+def delete_router_lport(cluster, lrouter_uuid, lport_uuid):
+ """Creates a logical port on the assigned logical router."""
+ path = _build_uri_path(LROUTERPORT_RESOURCE, lport_uuid, lrouter_uuid)
+ do_request(HTTP_DELETE, path, cluster=cluster)
+ LOG.debug(_("Delete logical router port %(lport_uuid)s on "
+ "logical router %(lrouter_uuid)s"),
+ {'lport_uuid': lport_uuid,
+ 'lrouter_uuid': lrouter_uuid})
+
+
+def delete_peer_router_lport(cluster, lr_uuid, ls_uuid, lp_uuid):
+ nsx_port = get_port(cluster, ls_uuid, lp_uuid,
+ relations="LogicalPortAttachment")
+ relations = nsx_port.get('_relations')
+ if relations:
+ att_data = relations.get('LogicalPortAttachment')
+ if att_data:
+ lrp_uuid = att_data.get('peer_port_uuid')
+ if lrp_uuid:
+ delete_router_lport(cluster, lr_uuid, lrp_uuid)
+
+
+def find_router_gw_port(context, cluster, router_id):
+ """Retrieves the external gateway port for a NSX logical router."""
+
+ # Find the uuid of nsx ext gw logical router port
+ # TODO(salvatore-orlando): Consider storing it in Neutron DB
+ results = query_lrouter_lports(
+ cluster, router_id,
+ relations="LogicalPortAttachment")
+ for lport in results:
+ if '_relations' in lport:
+ attachment = lport['_relations'].get('LogicalPortAttachment')
+ if attachment and attachment.get('type') == 'L3GatewayAttachment':
+ return lport
+
+
+def plug_router_port_attachment(cluster, router_id, port_id,
+ attachment_uuid, nsx_attachment_type,
+ attachment_vlan=None):
+ """Attach a router port to the given attachment.
+
+ Current attachment types:
+ - PatchAttachment [-> logical switch port uuid]
+ - L3GatewayAttachment [-> L3GatewayService uuid]
+ For the latter attachment type a VLAN ID can be specified as well.
+ """
+ uri = _build_uri_path(LROUTERPORT_RESOURCE, port_id, router_id,
+ is_attachment=True)
+ attach_obj = {}
+ attach_obj["type"] = nsx_attachment_type
+ if nsx_attachment_type == "PatchAttachment":
+ attach_obj["peer_port_uuid"] = attachment_uuid
+ elif nsx_attachment_type == "L3GatewayAttachment":
+ attach_obj["l3_gateway_service_uuid"] = attachment_uuid
+ if attachment_vlan:
+ attach_obj['vlan_id'] = attachment_vlan
+ else:
+ raise nvp_exc.NvpInvalidAttachmentType(
+ attachment_type=nsx_attachment_type)
+ return do_request(
+ HTTP_PUT, uri, jsonutils.dumps(attach_obj), cluster=cluster)
+
+
+def _create_nat_match_obj(**kwargs):
+ nat_match_obj = {'ethertype': 'IPv4'}
+ delta = set(kwargs.keys()) - set(MATCH_KEYS)
+ if delta:
+ raise Exception(_("Invalid keys for NAT match: %s"), delta)
+ nat_match_obj.update(kwargs)
+ return nat_match_obj
+
+
+def _create_lrouter_nat_rule(cluster, router_id, nat_rule_obj):
+ LOG.debug(_("Creating NAT rule: %s"), nat_rule_obj)
+ uri = _build_uri_path(LROUTERNAT_RESOURCE, parent_resource_id=router_id)
+ return do_request(HTTP_POST, uri, jsonutils.dumps(nat_rule_obj),
+ cluster=cluster)
+
+
+def _build_snat_rule_obj(min_src_ip, max_src_ip, nat_match_obj):
+ return {"to_source_ip_address_min": min_src_ip,
+ "to_source_ip_address_max": max_src_ip,
+ "type": "SourceNatRule",
+ "match": nat_match_obj}
+
+
+def create_lrouter_nosnat_rule_v2(cluster, _router_id, _match_criteria=None):
+ LOG.info(_("No SNAT rules cannot be applied as they are not available in "
+ "this version of the NSX platform"))
+
+
+def create_lrouter_nodnat_rule_v2(cluster, _router_id, _match_criteria=None):
+ LOG.info(_("No DNAT rules cannot be applied as they are not available in "
+ "this version of the NSX platform"))
+
+
+def create_lrouter_snat_rule_v2(cluster, router_id,
+ min_src_ip, max_src_ip, match_criteria=None):
+
+ nat_match_obj = _create_nat_match_obj(**match_criteria)
+ nat_rule_obj = _build_snat_rule_obj(min_src_ip, max_src_ip, nat_match_obj)
+ return _create_lrouter_nat_rule(cluster, router_id, nat_rule_obj)
+
+
+def create_lrouter_dnat_rule_v2(cluster, router_id, dst_ip,
+ to_dst_port=None, match_criteria=None):
+
+ nat_match_obj = _create_nat_match_obj(**match_criteria)
+ nat_rule_obj = {
+ "to_destination_ip_address_min": dst_ip,
+ "to_destination_ip_address_max": dst_ip,
+ "type": "DestinationNatRule",
+ "match": nat_match_obj
+ }
+ if to_dst_port:
+ nat_rule_obj['to_destination_port'] = to_dst_port
+ return _create_lrouter_nat_rule(cluster, router_id, nat_rule_obj)
+
+
+def create_lrouter_nosnat_rule_v3(cluster, router_id, order=None,
+ match_criteria=None):
+ nat_match_obj = _create_nat_match_obj(**match_criteria)
+ nat_rule_obj = {
+ "type": "NoSourceNatRule",
+ "match": nat_match_obj
+ }
+ if order:
+ nat_rule_obj['order'] = order
+ return _create_lrouter_nat_rule(cluster, router_id, nat_rule_obj)
+
+
+def create_lrouter_nodnat_rule_v3(cluster, router_id, order=None,
+ match_criteria=None):
+ nat_match_obj = _create_nat_match_obj(**match_criteria)
+ nat_rule_obj = {
+ "type": "NoDestinationNatRule",
+ "match": nat_match_obj
+ }
+ if order:
+ nat_rule_obj['order'] = order
+ return _create_lrouter_nat_rule(cluster, router_id, nat_rule_obj)
+
+
+def create_lrouter_snat_rule_v3(cluster, router_id, min_src_ip, max_src_ip,
+ order=None, match_criteria=None):
+ nat_match_obj = _create_nat_match_obj(**match_criteria)
+ nat_rule_obj = _build_snat_rule_obj(min_src_ip, max_src_ip, nat_match_obj)
+ if order:
+ nat_rule_obj['order'] = order
+ return _create_lrouter_nat_rule(cluster, router_id, nat_rule_obj)
+
+
+def create_lrouter_dnat_rule_v3(cluster, router_id, dst_ip, to_dst_port=None,
+ order=None, match_criteria=None):
+
+ nat_match_obj = _create_nat_match_obj(**match_criteria)
+ nat_rule_obj = {
+ "to_destination_ip_address": dst_ip,
+ "type": "DestinationNatRule",
+ "match": nat_match_obj
+ }
+ if to_dst_port:
+ nat_rule_obj['to_destination_port'] = to_dst_port
+ if order:
+ nat_rule_obj['order'] = order
+ return _create_lrouter_nat_rule(cluster, router_id, nat_rule_obj)
+
+
+def delete_nat_rules_by_match(cluster, router_id, rule_type,
+ max_num_expected,
+ min_num_expected=0,
+ **kwargs):
+ # remove nat rules
+ nat_rules = query_nat_rules(cluster, router_id)
+ to_delete_ids = []
+ for r in nat_rules:
+ if (r['type'] != rule_type):
+ continue
+
+ for key, value in kwargs.iteritems():
+ if not (key in r['match'] and r['match'][key] == value):
+ break
+ else:
+ to_delete_ids.append(r['uuid'])
+ if not (len(to_delete_ids) in
+ range(min_num_expected, max_num_expected + 1)):
+ raise nvp_exc.NvpNatRuleMismatch(actual_rules=len(to_delete_ids),
+ min_rules=min_num_expected,
+ max_rules=max_num_expected)
+
+ for rule_id in to_delete_ids:
+ delete_router_nat_rule(cluster, router_id, rule_id)
+
+
+def delete_router_nat_rule(cluster, router_id, rule_id):
+ uri = _build_uri_path(LROUTERNAT_RESOURCE, rule_id, router_id)
+ do_request(HTTP_DELETE, uri, cluster=cluster)
+
+
+def query_nat_rules(cluster, router_id, fields="*", filters=None):
+ uri = _build_uri_path(LROUTERNAT_RESOURCE, parent_resource_id=router_id,
+ fields=fields, filters=filters)
+ return get_all_query_pages(uri, cluster)
+
+
+# NOTE(salvatore-orlando): The following FIXME applies in general to
+# each operation on list attributes.
+# FIXME(salvatore-orlando): need a lock around the list of IPs on an iface
+def update_lrouter_port_ips(cluster, lrouter_id, lport_id,
+ ips_to_add, ips_to_remove):
+ uri = _build_uri_path(LROUTERPORT_RESOURCE, lport_id, lrouter_id)
+ try:
+ port = do_request(HTTP_GET, uri, cluster=cluster)
+ # TODO(salvatore-orlando): Enforce ips_to_add intersection with
+ # ips_to_remove is empty
+ ip_address_set = set(port['ip_addresses'])
+ ip_address_set = ip_address_set - set(ips_to_remove)
+ ip_address_set = ip_address_set | set(ips_to_add)
+ # Set is not JSON serializable - convert to list
+ port['ip_addresses'] = list(ip_address_set)
+ do_request(HTTP_PUT, uri, jsonutils.dumps(port), cluster=cluster)
+ except exception.NotFound as e:
+ # FIXME(salv-orlando):avoid raising different exception
+ data = {'lport_id': lport_id, 'lrouter_id': lrouter_id}
+ msg = (_("Router Port %(lport_id)s not found on router "
+ "%(lrouter_id)s") % data)
+ LOG.exception(msg)
+ raise nvp_exc.NvpPluginException(err_msg=msg)
+ except NvpApiClient.NvpApiException as e:
+ msg = _("An exception occurred while updating IP addresses on a "
+ "router logical port:%s") % str(e)
+ LOG.exception(msg)
+ raise nvp_exc.NvpPluginException(err_msg=msg)
+
+
+ROUTER_FUNC_DICT = {
+ 'create_lrouter': {
+ 2: {DEFAULT_VERSION: create_implicit_routing_lrouter, },
+ 3: {DEFAULT_VERSION: create_implicit_routing_lrouter,
+ 1: create_implicit_routing_lrouter_with_distribution,
+ 2: create_explicit_routing_lrouter, }, },
+ 'update_lrouter': {
+ 2: {DEFAULT_VERSION: update_implicit_routing_lrouter, },
+ 3: {DEFAULT_VERSION: update_implicit_routing_lrouter,
+ 2: update_explicit_routing_lrouter, }, },
+ 'create_lrouter_dnat_rule': {
+ 2: {DEFAULT_VERSION: create_lrouter_dnat_rule_v2, },
+ 3: {DEFAULT_VERSION: create_lrouter_dnat_rule_v3, }, },
+ 'create_lrouter_snat_rule': {
+ 2: {DEFAULT_VERSION: create_lrouter_snat_rule_v2, },
+ 3: {DEFAULT_VERSION: create_lrouter_snat_rule_v3, }, },
+ 'create_lrouter_nosnat_rule': {
+ 2: {DEFAULT_VERSION: create_lrouter_nosnat_rule_v2, },
+ 3: {DEFAULT_VERSION: create_lrouter_nosnat_rule_v3, }, },
+ 'create_lrouter_nodnat_rule': {
+ 2: {DEFAULT_VERSION: create_lrouter_nodnat_rule_v2, },
+ 3: {DEFAULT_VERSION: create_lrouter_nodnat_rule_v3, }, },
+ 'get_default_route_explicit_routing_lrouter': {
+ 3: {DEFAULT_VERSION: get_default_route_explicit_routing_lrouter_v32,
+ 2: get_default_route_explicit_routing_lrouter_v32, }, },
+}
+
+
+@versioned(ROUTER_FUNC_DICT)
+def create_lrouter(cluster, *args, **kwargs):
+ if kwargs.get('distributed', None):
+ v = cluster.api_client.get_nvp_version()
+ if (v.major, v.minor) < (3, 1):
+ raise nvp_exc.NvpInvalidVersion(version=v)
+ return v
+
+
+@versioned(ROUTER_FUNC_DICT)
+def get_default_route_explicit_routing_lrouter(cluster, *args, **kwargs):
+ pass
+
+
+@versioned(ROUTER_FUNC_DICT)
+def update_lrouter(cluster, *args, **kwargs):
+ if kwargs.get('routes', None):
+ v = cluster.api_client.get_nvp_version()
+ if (v.major, v.minor) < (3, 2):
+ raise nvp_exc.NvpInvalidVersion(version=v)
+ return v
+
+
+@versioned(ROUTER_FUNC_DICT)
+def create_lrouter_dnat_rule(cluster, *args, **kwargs):
+ pass
+
+
+@versioned(ROUTER_FUNC_DICT)
+def create_lrouter_snat_rule(cluster, *args, **kwargs):
+ pass
+
+
+@versioned(ROUTER_FUNC_DICT)
+def create_lrouter_nosnat_rule(cluster, *args, **kwargs):
+ pass
+
+
+@versioned(ROUTER_FUNC_DICT)
+def create_lrouter_nodnat_rule(cluster, *args, **kwargs):
+ pass
--- /dev/null
+# Copyright 2014 VMware, Inc.
+# All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import inspect
+
+from neutron.plugins.nicira import NvpApiClient
+
+DEFAULT_VERSION = -1
+
+
+def versioned(func_table):
+
+ def versioned_function(wrapped_func):
+ func_name = wrapped_func.__name__
+
+ def dispatch_versioned_function(cluster, *args, **kwargs):
+ # Call the wrapper function, in case we need to
+ # run validation checks regarding versions. It
+ # should return the NVP version
+ v = (wrapped_func(cluster, *args, **kwargs) or
+ cluster.api_client.get_nvp_version())
+ func = get_function_by_version(func_table, func_name, v)
+ func_kwargs = kwargs
+ arg_spec = inspect.getargspec(func)
+ if not arg_spec.keywords and not arg_spec.varargs:
+ # drop args unknown to function from func_args
+ arg_set = set(func_kwargs.keys())
+ for arg in arg_set - set(arg_spec.args):
+ del func_kwargs[arg]
+ # NOTE(salvatore-orlando): shall we fail here if a required
+ # argument is not passed, or let the called function raise?
+ return func(cluster, *args, **func_kwargs)
+
+ return dispatch_versioned_function
+ return versioned_function
+
+
+def get_function_by_version(func_table, func_name, ver):
+ if ver:
+ if ver.major not in func_table[func_name]:
+ major = max(func_table[func_name].keys())
+ minor = max(func_table[func_name][major].keys())
+ if major > ver.major:
+ raise NotImplementedError(_("Operation may not be supported"))
+ else:
+ major = ver.major
+ minor = ver.minor
+ if ver.minor not in func_table[func_name][major]:
+ minor = DEFAULT_VERSION
+ return func_table[func_name][major][minor]
+ else:
+ msg = _('NSX version is not set. Unable to complete request '
+ 'correctly. Check log for NSX communication errors.')
+ raise NvpApiClient.ServiceUnavailable(message=msg)
import hashlib
-import inspect
import json
#FIXME(danwent): I'd like this file to get to the point where it has
# no neutron-specific logic in it
from neutron.common import constants
from neutron.common import exceptions as exception
-from neutron.openstack.common import excutils
from neutron.openstack.common import log
from neutron.plugins.nicira.common import exceptions as nvp_exc
from neutron.plugins.nicira.common import utils
# Resources exposed by NVP API
LSWITCH_RESOURCE = "lswitch"
LSWITCHPORT_RESOURCE = "lport/%s" % LSWITCH_RESOURCE
-LROUTER_RESOURCE = "lrouter"
-LROUTERPORT_RESOURCE = "lport/%s" % LROUTER_RESOURCE
-LROUTERRIB_RESOURCE = "rib/%s" % LROUTER_RESOURCE
-LROUTERNAT_RESOURCE = "nat/lrouter"
-LQUEUE_RESOURCE = "lqueue"
GWSERVICE_RESOURCE = "gateway-service"
# Current neutron version
NEUTRON_VERSION = version_info.release_string()
-# Constants for NAT rules
-MATCH_KEYS = ["destination_ip_addresses", "destination_port_max",
- "destination_port_min", "source_ip_addresses",
- "source_port_max", "source_port_min", "protocol"]
-SNAT_KEYS = ["to_src_port_min", "to_src_port_max", "to_src_ip_min",
- "to_src_ip_max"]
-
-DNAT_KEYS = ["to_dst_port", "to_dst_ip_min", "to_dst_ip_max"]
# Maximum page size for a single request
# NOTE(salv-orlando): This might become a version-dependent map should the
# limit be raised in future versions
return device_id
-def version_dependent(wrapped_func):
- func_name = wrapped_func.__name__
-
- def dispatch_version_dependent_function(cluster, *args, **kwargs):
- # Call the wrapper function, in case we need to
- # run validation checks regarding versions. It
- # should return the NVP version
- v = (wrapped_func(cluster, *args, **kwargs) or
- cluster.api_client.get_nvp_version())
- func = get_function_by_version(func_name, v)
- func_kwargs = kwargs
- arg_spec = inspect.getargspec(func)
- if not arg_spec.keywords and not arg_spec.varargs:
- # drop args unknown to function from func_args
- arg_set = set(func_kwargs.keys())
- for arg in arg_set - set(arg_spec.args):
- del func_kwargs[arg]
- # NOTE(salvatore-orlando): shall we fail here if a required
- # argument is not passed, or let the called function raise?
- return func(cluster, *args, **func_kwargs)
-
- return dispatch_version_dependent_function
-
-
def _build_uri_path(resource,
resource_id=None,
parent_resource_id=None,
json.dumps(gwservice_obj), cluster=cluster)
-def _prepare_lrouter_body(name, neutron_router_id, tenant_id, router_type,
- distributed=None, **kwargs):
- body = {
- "display_name": utils.check_and_truncate(name),
- "tags": [{"tag": tenant_id, "scope": "os_tid"},
- {"tag": neutron_router_id, "scope": "q_router_id"},
- {"tag": NEUTRON_VERSION, "scope": "quantum"}],
- "routing_config": {
- "type": router_type
- },
- "type": "LogicalRouterConfig"
- }
- # add the distributed key only if not None (ie: True or False)
- if distributed is not None:
- body['distributed'] = distributed
- if kwargs:
- body["routing_config"].update(kwargs)
- return body
-
-
-def _create_implicit_routing_lrouter(cluster, neutron_router_id, tenant_id,
- display_name, nexthop, distributed=None):
- implicit_routing_config = {
- "default_route_next_hop": {
- "gateway_ip_address": nexthop,
- "type": "RouterNextHop"
- },
- }
- lrouter_obj = _prepare_lrouter_body(
- display_name, neutron_router_id, tenant_id,
- "SingleDefaultRouteImplicitRoutingConfig",
- distributed=distributed,
- **implicit_routing_config)
- return do_request(HTTP_POST, _build_uri_path(LROUTER_RESOURCE),
- json.dumps(lrouter_obj), cluster=cluster)
-
-
-def create_implicit_routing_lrouter(cluster, neutron_router_id, tenant_id,
- display_name, nexthop):
- """Create a NVP logical router on the specified cluster.
-
- :param cluster: The target NVP cluster
- :param tenant_id: Identifier of the Openstack tenant for which
- the logical router is being created
- :param display_name: Descriptive name of this logical router
- :param nexthop: External gateway IP address for the logical router
- :raise NvpApiException: if there is a problem while communicating
- with the NVP controller
- """
- return _create_implicit_routing_lrouter(
- cluster, neutron_router_id, tenant_id, display_name, nexthop)
-
-
-def create_implicit_routing_lrouter_with_distribution(
- cluster, neutron_router_id, tenant_id,
- display_name, nexthop, distributed=None):
- """Create a NVP logical router on the specified cluster.
-
- This function also allows for creating distributed lrouters
- :param cluster: The target NVP cluster
- :param tenant_id: Identifier of the Openstack tenant for which
- the logical router is being created
- :param display_name: Descriptive name of this logical router
- :param nexthop: External gateway IP address for the logical router
- :param distributed: True for distributed logical routers
- :raise NvpApiException: if there is a problem while communicating
- with the NVP controller
- """
- return _create_implicit_routing_lrouter(
- cluster, neutron_router_id, tenant_id,
- display_name, nexthop, distributed)
-
-
-def create_explicit_routing_lrouter(cluster, neutron_router_id, tenant_id,
- display_name, nexthop,
- distributed=None):
- lrouter_obj = _prepare_lrouter_body(
- display_name, neutron_router_id,
- tenant_id, "RoutingTableRoutingConfig",
- distributed=distributed)
- router = do_request(HTTP_POST, _build_uri_path(LROUTER_RESOURCE),
- json.dumps(lrouter_obj), cluster=cluster)
- default_gw = {'prefix': '0.0.0.0/0', 'next_hop_ip': nexthop}
- create_explicit_route_lrouter(cluster, router['uuid'], default_gw)
- return router
-
-
-@version_dependent
-def create_lrouter(cluster, *args, **kwargs):
- if kwargs.get('distributed', None):
- v = cluster.api_client.get_nvp_version()
- if (v.major, v.minor) < (3, 1):
- raise nvp_exc.NvpInvalidVersion(version=v)
- return v
-
-
-def delete_lrouter(cluster, lrouter_id):
- do_request(HTTP_DELETE, _build_uri_path(LROUTER_RESOURCE,
- resource_id=lrouter_id),
- cluster=cluster)
-
-
def delete_l2_gw_service(cluster, gateway_id):
do_request("DELETE", _build_uri_path(GWSERVICE_RESOURCE,
resource_id=gateway_id),
cluster=cluster)
-def get_lrouter(cluster, lrouter_id):
- return do_request(HTTP_GET,
- _build_uri_path(LROUTER_RESOURCE,
- resource_id=lrouter_id,
- relations='LogicalRouterStatus'),
- cluster=cluster)
-
-
def get_l2_gw_service(cluster, gateway_id):
return do_request(
"GET", _build_uri_path(GWSERVICE_RESOURCE,
cluster=cluster)
-def query_lrouters(cluster, fields=None, filters=None):
- return get_all_query_pages(
- _build_uri_path(LROUTER_RESOURCE,
- fields=fields,
- relations='LogicalRouterStatus',
- filters=filters),
- cluster)
-
-
-def get_lrouters(cluster, tenant_id, fields=None, filters=None):
- # FIXME(salv-orlando): Fields parameter is ignored in this routine
- actual_filters = {}
- if filters:
- actual_filters.update(filters)
- if tenant_id:
- actual_filters['tag'] = tenant_id
- actual_filters['tag_scope'] = 'os_tid'
- lrouter_fields = "uuid,display_name,fabric_status,tags"
- return query_lrouters(cluster, lrouter_fields, actual_filters)
-
-
def get_l2_gw_services(cluster, tenant_id=None,
fields=None, filters=None):
actual_filters = dict(filters or {})
json.dumps(gwservice_obj), cluster=cluster)
-def update_implicit_routing_lrouter(cluster, r_id, display_name, nexthop):
- lrouter_obj = get_lrouter(cluster, r_id)
- if not display_name and not nexthop:
- # Nothing to update
- return lrouter_obj
- # It seems that this is faster than the doing an if on display_name
- lrouter_obj["display_name"] = (utils.check_and_truncate(display_name) or
- lrouter_obj["display_name"])
- if nexthop:
- nh_element = lrouter_obj["routing_config"].get(
- "default_route_next_hop")
- if nh_element:
- nh_element["gateway_ip_address"] = nexthop
- return do_request(HTTP_PUT, _build_uri_path(LROUTER_RESOURCE,
- resource_id=r_id),
- json.dumps(lrouter_obj),
- cluster=cluster)
-
-
-def get_explicit_routes_lrouter(cluster, router_id, protocol_type='static'):
- static_filter = {'protocol': protocol_type}
- existing_routes = do_request(
- HTTP_GET,
- _build_uri_path(LROUTERRIB_RESOURCE,
- filters=static_filter,
- fields="*",
- parent_resource_id=router_id),
- cluster=cluster)['results']
- return existing_routes
-
-
-def delete_explicit_route_lrouter(cluster, router_id, route_id):
- do_request(HTTP_DELETE,
- _build_uri_path(LROUTERRIB_RESOURCE,
- resource_id=route_id,
- parent_resource_id=router_id),
- cluster=cluster)
-
-
-def create_explicit_route_lrouter(cluster, router_id, route):
- next_hop_ip = route.get("nexthop") or route.get("next_hop_ip")
- prefix = route.get("destination") or route.get("prefix")
- uuid = do_request(
- HTTP_POST,
- _build_uri_path(LROUTERRIB_RESOURCE,
- parent_resource_id=router_id),
- json.dumps({
- "action": "accept",
- "next_hop_ip": next_hop_ip,
- "prefix": prefix,
- "protocol": "static"
- }),
- cluster=cluster)['uuid']
- return uuid
-
-
-def update_explicit_routes_lrouter(cluster, router_id, routes):
- # Update in bulk: delete them all, and add the ones specified
- # but keep track of what is been modified to allow roll-backs
- # in case of failures
- nvp_routes = get_explicit_routes_lrouter(cluster, router_id)
- try:
- deleted_routes = []
- added_routes = []
- # omit the default route (0.0.0.0/0) from the processing;
- # this must be handled through the nexthop for the router
- for route in nvp_routes:
- prefix = route.get("destination") or route.get("prefix")
- if prefix != '0.0.0.0/0':
- delete_explicit_route_lrouter(cluster,
- router_id,
- route['uuid'])
- deleted_routes.append(route)
- for route in routes:
- prefix = route.get("destination") or route.get("prefix")
- if prefix != '0.0.0.0/0':
- uuid = create_explicit_route_lrouter(cluster,
- router_id, route)
- added_routes.append(uuid)
- except NvpApiClient.NvpApiException:
- LOG.exception(_('Cannot update NVP routes %(routes)s for '
- 'router %(router_id)s'),
- {'routes': routes, 'router_id': router_id})
- # Roll back to keep NVP in consistent state
- with excutils.save_and_reraise_exception():
- if nvp_routes:
- if deleted_routes:
- for route in deleted_routes:
- create_explicit_route_lrouter(cluster,
- router_id, route)
- if added_routes:
- for route_id in added_routes:
- delete_explicit_route_lrouter(cluster,
- router_id, route_id)
- return nvp_routes
-
-
-@version_dependent
-def get_default_route_explicit_routing_lrouter(cluster, *args, **kwargs):
- pass
-
-
-def get_default_route_explicit_routing_lrouter_v33(cluster, router_id):
- static_filter = {"protocol": "static",
- "prefix": "0.0.0.0/0"}
- default_route = do_request(
- HTTP_GET,
- _build_uri_path(LROUTERRIB_RESOURCE,
- filters=static_filter,
- fields="*",
- parent_resource_id=router_id),
- cluster=cluster)["results"][0]
- return default_route
-
-
-def get_default_route_explicit_routing_lrouter_v32(cluster, router_id):
- # Scan all routes because 3.2 does not support query by prefix
- all_routes = get_explicit_routes_lrouter(cluster, router_id)
- for route in all_routes:
- if route['prefix'] == '0.0.0.0/0':
- return route
-
-
-def update_default_gw_explicit_routing_lrouter(cluster, router_id, next_hop):
- default_route = get_default_route_explicit_routing_lrouter(cluster,
- router_id)
- if next_hop != default_route["next_hop_ip"]:
- new_default_route = {"action": "accept",
- "next_hop_ip": next_hop,
- "prefix": "0.0.0.0/0",
- "protocol": "static"}
- do_request(HTTP_PUT,
- _build_uri_path(LROUTERRIB_RESOURCE,
- resource_id=default_route['uuid'],
- parent_resource_id=router_id),
- json.dumps(new_default_route),
- cluster=cluster)
-
-
-def update_explicit_routing_lrouter(cluster, router_id,
- display_name, next_hop, routes=None):
- update_implicit_routing_lrouter(cluster, router_id, display_name, next_hop)
- if next_hop:
- update_default_gw_explicit_routing_lrouter(cluster,
- router_id, next_hop)
- if routes is not None:
- return update_explicit_routes_lrouter(cluster, router_id, routes)
-
-
-@version_dependent
-def update_lrouter(cluster, *args, **kwargs):
- if kwargs.get('routes', None):
- v = cluster.api_client.get_nvp_version()
- if (v.major, v.minor) < (3, 2):
- raise nvp_exc.NvpInvalidVersion(version=v)
- return v
-
-
def delete_network(cluster, net_id, lswitch_id):
delete_networks(cluster, net_id, [lswitch_id])
return do_request(HTTP_GET, uri, cluster=cluster)['results']
-def query_lrouter_lports(cluster, lr_uuid, fields="*",
- filters=None, relations=None):
- uri = _build_uri_path(LROUTERPORT_RESOURCE, parent_resource_id=lr_uuid,
- fields=fields, filters=filters, relations=relations)
- return do_request(HTTP_GET, uri, cluster=cluster)['results']
-
-
def delete_port(cluster, switch, port):
uri = "/ws.v1/lswitch/" + switch + "/lport/" + port
try:
return result
-def create_router_lport(cluster, lrouter_uuid, tenant_id, neutron_port_id,
- display_name, admin_status_enabled, ip_addresses,
- mac_address=None):
- """Creates a logical port on the assigned logical router."""
- tags = [dict(scope='os_tid', tag=tenant_id),
- dict(scope='q_port_id', tag=neutron_port_id),
- dict(scope='quantum', tag=NEUTRON_VERSION)]
-
- lport_obj = dict(
- admin_status_enabled=admin_status_enabled,
- display_name=display_name,
- tags=tags,
- ip_addresses=ip_addresses,
- type="LogicalRouterPortConfig"
- )
- # Only add the mac_address to lport_obj if present. This is because
- # when creating the fake_ext_gw there is no mac_address present.
- if mac_address:
- lport_obj['mac_address'] = mac_address
- path = _build_uri_path(LROUTERPORT_RESOURCE,
- parent_resource_id=lrouter_uuid)
- result = do_request(HTTP_POST, path, json.dumps(lport_obj),
- cluster=cluster)
-
- LOG.debug(_("Created logical port %(lport_uuid)s on "
- "logical router %(lrouter_uuid)s"),
- {'lport_uuid': result['uuid'],
- 'lrouter_uuid': lrouter_uuid})
- return result
-
-
-def update_router_lport(cluster, lrouter_uuid, lrouter_port_uuid,
- tenant_id, neutron_port_id, display_name,
- admin_status_enabled, ip_addresses):
- """Updates a logical port on the assigned logical router."""
- lport_obj = dict(
- admin_status_enabled=admin_status_enabled,
- display_name=display_name,
- tags=[dict(scope='os_tid', tag=tenant_id),
- dict(scope='q_port_id', tag=neutron_port_id),
- dict(scope='quantum', tag=NEUTRON_VERSION)],
- ip_addresses=ip_addresses,
- type="LogicalRouterPortConfig"
- )
- # Do not pass null items to NVP
- for key in lport_obj.keys():
- if lport_obj[key] is None:
- del lport_obj[key]
- path = _build_uri_path(LROUTERPORT_RESOURCE,
- lrouter_port_uuid,
- parent_resource_id=lrouter_uuid)
- result = do_request(HTTP_PUT, path,
- json.dumps(lport_obj),
- cluster=cluster)
- LOG.debug(_("Updated logical port %(lport_uuid)s on "
- "logical router %(lrouter_uuid)s"),
- {'lport_uuid': lrouter_port_uuid, 'lrouter_uuid': lrouter_uuid})
- return result
-
-
-def delete_router_lport(cluster, lrouter_uuid, lport_uuid):
- """Creates a logical port on the assigned logical router."""
- path = _build_uri_path(LROUTERPORT_RESOURCE, lport_uuid, lrouter_uuid)
- do_request(HTTP_DELETE, path, cluster=cluster)
- LOG.debug(_("Delete logical router port %(lport_uuid)s on "
- "logical router %(lrouter_uuid)s"),
- {'lport_uuid': lport_uuid,
- 'lrouter_uuid': lrouter_uuid})
-
-
-def delete_peer_router_lport(cluster, lr_uuid, ls_uuid, lp_uuid):
- nvp_port = get_port(cluster, ls_uuid, lp_uuid,
- relations="LogicalPortAttachment")
- relations = nvp_port.get('_relations')
- if relations:
- att_data = relations.get('LogicalPortAttachment')
- if att_data:
- lrp_uuid = att_data.get('peer_port_uuid')
- if lrp_uuid:
- delete_router_lport(cluster, lr_uuid, lrp_uuid)
-
-
-def find_router_gw_port(context, cluster, router_id):
- """Retrieves the external gateway port for a NVP logical router."""
-
- # Find the uuid of nvp ext gw logical router port
- # TODO(salvatore-orlando): Consider storing it in Neutron DB
- results = query_lrouter_lports(
- cluster, router_id,
- relations="LogicalPortAttachment")
- for lport in results:
- if '_relations' in lport:
- attachment = lport['_relations'].get('LogicalPortAttachment')
- if attachment and attachment.get('type') == 'L3GatewayAttachment':
- return lport
-
-
-def plug_router_port_attachment(cluster, router_id, port_id,
- attachment_uuid, nvp_attachment_type,
- attachment_vlan=None):
- """Attach a router port to the given attachment.
-
- Current attachment types:
- - PatchAttachment [-> logical switch port uuid]
- - L3GatewayAttachment [-> L3GatewayService uuid]
- For the latter attachment type a VLAN ID can be specified as well.
- """
- uri = _build_uri_path(LROUTERPORT_RESOURCE, port_id, router_id,
- is_attachment=True)
- attach_obj = {}
- attach_obj["type"] = nvp_attachment_type
- if nvp_attachment_type == "PatchAttachment":
- attach_obj["peer_port_uuid"] = attachment_uuid
- elif nvp_attachment_type == "L3GatewayAttachment":
- attach_obj["l3_gateway_service_uuid"] = attachment_uuid
- if attachment_vlan:
- attach_obj['vlan_id'] = attachment_vlan
- else:
- raise nvp_exc.NvpInvalidAttachmentType(
- attachment_type=nvp_attachment_type)
- return do_request(HTTP_PUT, uri, json.dumps(attach_obj), cluster=cluster)
-
-
def get_port_status(cluster, lswitch_id, port_id):
"""Retrieve the operational status of the port."""
try:
LOG.warn(_("Unable to find security profile %s on NSX backend"),
spid)
raise
-
-
-def _create_nat_match_obj(**kwargs):
- nat_match_obj = {'ethertype': 'IPv4'}
- delta = set(kwargs.keys()) - set(MATCH_KEYS)
- if delta:
- raise Exception(_("Invalid keys for NAT match: %s"), delta)
- nat_match_obj.update(kwargs)
- return nat_match_obj
-
-
-def _create_lrouter_nat_rule(cluster, router_id, nat_rule_obj):
- LOG.debug(_("Creating NAT rule: %s"), nat_rule_obj)
- uri = _build_uri_path(LROUTERNAT_RESOURCE, parent_resource_id=router_id)
- return do_request(HTTP_POST, uri, json.dumps(nat_rule_obj),
- cluster=cluster)
-
-
-def _build_snat_rule_obj(min_src_ip, max_src_ip, nat_match_obj):
- return {"to_source_ip_address_min": min_src_ip,
- "to_source_ip_address_max": max_src_ip,
- "type": "SourceNatRule",
- "match": nat_match_obj}
-
-
-def create_lrouter_nosnat_rule_v2(cluster, _router_id, _match_criteria=None):
- LOG.info(_("No SNAT rules cannot be applied as they are not available in "
- "this version of the NVP platform"))
-
-
-def create_lrouter_nodnat_rule_v2(cluster, _router_id, _match_criteria=None):
- LOG.info(_("No DNAT rules cannot be applied as they are not available in "
- "this version of the NVP platform"))
-
-
-def create_lrouter_snat_rule_v2(cluster, router_id,
- min_src_ip, max_src_ip, match_criteria=None):
-
- nat_match_obj = _create_nat_match_obj(**match_criteria)
- nat_rule_obj = _build_snat_rule_obj(min_src_ip, max_src_ip, nat_match_obj)
- return _create_lrouter_nat_rule(cluster, router_id, nat_rule_obj)
-
-
-def create_lrouter_dnat_rule_v2(cluster, router_id, dst_ip,
- to_dst_port=None, match_criteria=None):
-
- nat_match_obj = _create_nat_match_obj(**match_criteria)
- nat_rule_obj = {
- "to_destination_ip_address_min": dst_ip,
- "to_destination_ip_address_max": dst_ip,
- "type": "DestinationNatRule",
- "match": nat_match_obj
- }
- if to_dst_port:
- nat_rule_obj['to_destination_port'] = to_dst_port
- return _create_lrouter_nat_rule(cluster, router_id, nat_rule_obj)
-
-
-def create_lrouter_nosnat_rule_v3(cluster, router_id, order=None,
- match_criteria=None):
- nat_match_obj = _create_nat_match_obj(**match_criteria)
- nat_rule_obj = {
- "type": "NoSourceNatRule",
- "match": nat_match_obj
- }
- if order:
- nat_rule_obj['order'] = order
- return _create_lrouter_nat_rule(cluster, router_id, nat_rule_obj)
-
-
-def create_lrouter_nodnat_rule_v3(cluster, router_id, order=None,
- match_criteria=None):
- nat_match_obj = _create_nat_match_obj(**match_criteria)
- nat_rule_obj = {
- "type": "NoDestinationNatRule",
- "match": nat_match_obj
- }
- if order:
- nat_rule_obj['order'] = order
- return _create_lrouter_nat_rule(cluster, router_id, nat_rule_obj)
-
-
-def create_lrouter_snat_rule_v3(cluster, router_id, min_src_ip, max_src_ip,
- order=None, match_criteria=None):
- nat_match_obj = _create_nat_match_obj(**match_criteria)
- nat_rule_obj = _build_snat_rule_obj(min_src_ip, max_src_ip, nat_match_obj)
- if order:
- nat_rule_obj['order'] = order
- return _create_lrouter_nat_rule(cluster, router_id, nat_rule_obj)
-
-
-def create_lrouter_dnat_rule_v3(cluster, router_id, dst_ip, to_dst_port=None,
- order=None, match_criteria=None):
-
- nat_match_obj = _create_nat_match_obj(**match_criteria)
- nat_rule_obj = {
- "to_destination_ip_address": dst_ip,
- "type": "DestinationNatRule",
- "match": nat_match_obj
- }
- if to_dst_port:
- nat_rule_obj['to_destination_port'] = to_dst_port
- if order:
- nat_rule_obj['order'] = order
- return _create_lrouter_nat_rule(cluster, router_id, nat_rule_obj)
-
-
-@version_dependent
-def create_lrouter_dnat_rule(cluster, *args, **kwargs):
- pass
-
-
-@version_dependent
-def create_lrouter_snat_rule(cluster, *args, **kwargs):
- pass
-
-
-@version_dependent
-def create_lrouter_nosnat_rule(cluster, *args, **kwargs):
- pass
-
-
-@version_dependent
-def create_lrouter_nodnat_rule(cluster, *args, **kwargs):
- pass
-
-
-def delete_nat_rules_by_match(cluster, router_id, rule_type,
- max_num_expected,
- min_num_expected=0,
- **kwargs):
- # remove nat rules
- nat_rules = query_nat_rules(cluster, router_id)
- to_delete_ids = []
- for r in nat_rules:
- if (r['type'] != rule_type):
- continue
-
- for key, value in kwargs.iteritems():
- if not (key in r['match'] and r['match'][key] == value):
- break
- else:
- to_delete_ids.append(r['uuid'])
- if not (len(to_delete_ids) in
- range(min_num_expected, max_num_expected + 1)):
- raise nvp_exc.NvpNatRuleMismatch(actual_rules=len(to_delete_ids),
- min_rules=min_num_expected,
- max_rules=max_num_expected)
-
- for rule_id in to_delete_ids:
- delete_router_nat_rule(cluster, router_id, rule_id)
-
-
-def delete_router_nat_rule(cluster, router_id, rule_id):
- uri = _build_uri_path(LROUTERNAT_RESOURCE, rule_id, router_id)
- do_request(HTTP_DELETE, uri, cluster=cluster)
-
-
-def query_nat_rules(cluster, router_id, fields="*", filters=None):
- uri = _build_uri_path(LROUTERNAT_RESOURCE, parent_resource_id=router_id,
- fields=fields, filters=filters)
- return get_all_query_pages(uri, cluster)
-
-
-# NOTE(salvatore-orlando): The following FIXME applies in general to
-# each operation on list attributes.
-# FIXME(salvatore-orlando): need a lock around the list of IPs on an iface
-def update_lrouter_port_ips(cluster, lrouter_id, lport_id,
- ips_to_add, ips_to_remove):
- uri = _build_uri_path(LROUTERPORT_RESOURCE, lport_id, lrouter_id)
- try:
- port = do_request(HTTP_GET, uri, cluster=cluster)
- # TODO(salvatore-orlando): Enforce ips_to_add intersection with
- # ips_to_remove is empty
- ip_address_set = set(port['ip_addresses'])
- ip_address_set = ip_address_set - set(ips_to_remove)
- ip_address_set = ip_address_set | set(ips_to_add)
- # Set is not JSON serializable - convert to list
- port['ip_addresses'] = list(ip_address_set)
- do_request(HTTP_PUT, uri, json.dumps(port), cluster=cluster)
- except exception.NotFound as e:
- # FIXME(salv-orlando):avoid raising different exception
- data = {'lport_id': lport_id, 'lrouter_id': lrouter_id}
- msg = (_("Router Port %(lport_id)s not found on router "
- "%(lrouter_id)s") % data)
- LOG.exception(msg)
- raise nvp_exc.NvpPluginException(err_msg=msg)
- except NvpApiClient.NvpApiException as e:
- msg = _("An exception occurred while updating IP addresses on a "
- "router logical port:%s") % str(e)
- LOG.exception(msg)
- raise nvp_exc.NvpPluginException(err_msg=msg)
-
-
-DEFAULT = -1
-NVPLIB_FUNC_DICT = {
- 'create_lrouter': {
- 2: {DEFAULT: create_implicit_routing_lrouter, },
- 3: {DEFAULT: create_implicit_routing_lrouter,
- 1: create_implicit_routing_lrouter_with_distribution,
- 2: create_explicit_routing_lrouter, }, },
- 'update_lrouter': {
- 2: {DEFAULT: update_implicit_routing_lrouter, },
- 3: {DEFAULT: update_implicit_routing_lrouter,
- 2: update_explicit_routing_lrouter, }, },
- 'create_lrouter_dnat_rule': {
- 2: {DEFAULT: create_lrouter_dnat_rule_v2, },
- 3: {DEFAULT: create_lrouter_dnat_rule_v3, }, },
- 'create_lrouter_snat_rule': {
- 2: {DEFAULT: create_lrouter_snat_rule_v2, },
- 3: {DEFAULT: create_lrouter_snat_rule_v3, }, },
- 'create_lrouter_nosnat_rule': {
- 2: {DEFAULT: create_lrouter_nosnat_rule_v2, },
- 3: {DEFAULT: create_lrouter_nosnat_rule_v3, }, },
- 'create_lrouter_nodnat_rule': {
- 2: {DEFAULT: create_lrouter_nodnat_rule_v2, },
- 3: {DEFAULT: create_lrouter_nodnat_rule_v3, }, },
- 'get_default_route_explicit_routing_lrouter': {
- 3: {DEFAULT: get_default_route_explicit_routing_lrouter_v32,
- 2: get_default_route_explicit_routing_lrouter_v32, }, },
-}
-
-
-def get_function_by_version(func_name, nvp_ver):
- if nvp_ver:
- if nvp_ver.major not in NVPLIB_FUNC_DICT[func_name]:
- major = max(NVPLIB_FUNC_DICT[func_name].keys())
- minor = max(NVPLIB_FUNC_DICT[func_name][major].keys())
- if major > nvp_ver.major:
- raise NotImplementedError(_("Operation may not be supported"))
- else:
- major = nvp_ver.major
- minor = nvp_ver.minor
- if nvp_ver.minor not in NVPLIB_FUNC_DICT[func_name][major]:
- minor = DEFAULT
- return NVPLIB_FUNC_DICT[func_name][major][minor]
- else:
- msg = _('NVP version is not set. Unable to complete request '
- 'correctly. Check log for NVP communication errors.')
- raise NvpApiClient.ServiceUnavailable(message=msg)
--- /dev/null
+# Copyright (c) 2014 VMware, 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 mock
+
+from neutron.common import exceptions
+from neutron.openstack.common import uuidutils
+from neutron.plugins.nicira.common import exceptions as nvp_exc
+from neutron.plugins.nicira.nsxlib import router as routerlib
+from neutron.plugins.nicira import NvpApiClient
+from neutron.plugins.nicira import nvplib
+from neutron.tests.unit.nicira.test_nvplib import NsxlibNegativeBaseTestCase
+from neutron.tests.unit.nicira.test_nvplib import NvplibTestCase
+from neutron.tests.unit import test_api_v2
+
+_uuid = test_api_v2._uuid
+
+
+class TestNatRules(NvplibTestCase):
+
+ def _test_create_lrouter_dnat_rule(self, version):
+ with mock.patch.object(self.fake_cluster.api_client,
+ 'get_nvp_version',
+ new=lambda: NvpApiClient.NVPVersion(version)):
+ tenant_id = 'pippo'
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ uuidutils.generate_uuid(),
+ tenant_id,
+ 'fake_router',
+ '192.168.0.1')
+ nat_rule = routerlib.create_lrouter_dnat_rule(
+ self.fake_cluster, lrouter['uuid'], '10.0.0.99',
+ match_criteria={'destination_ip_addresses':
+ '192.168.0.5'})
+ uri = nvplib._build_uri_path(routerlib.LROUTERNAT_RESOURCE,
+ nat_rule['uuid'],
+ lrouter['uuid'])
+ resp_obj = nvplib.do_request("GET", uri, cluster=self.fake_cluster)
+ self.assertEqual('DestinationNatRule', resp_obj['type'])
+ self.assertEqual('192.168.0.5',
+ resp_obj['match']['destination_ip_addresses'])
+
+ def test_create_lrouter_dnat_rule_v2(self):
+ self._test_create_lrouter_dnat_rule('2.9')
+
+ def test_create_lrouter_dnat_rule_v31(self):
+ self._test_create_lrouter_dnat_rule('3.1')
+
+
+class TestExplicitLRouters(NvplibTestCase):
+
+ def setUp(self):
+ self.fake_version = '3.2'
+ super(TestExplicitLRouters, self).setUp()
+
+ def _get_lrouter(self, tenant_id, router_name, router_id, relations=None):
+ schema = '/ws.v1/schema/RoutingTableRoutingConfig'
+
+ router = {'display_name': router_name,
+ 'uuid': router_id,
+ 'tags': [{'scope': 'quantum', 'tag': nvplib.NEUTRON_VERSION},
+ {'scope': 'os_tid', 'tag': '%s' % tenant_id}],
+ 'distributed': False,
+ 'routing_config': {'type': 'RoutingTableRoutingConfig',
+ '_schema': schema},
+ '_schema': schema,
+ 'nat_synchronization_enabled': True,
+ 'replication_mode': 'service',
+ 'type': 'LogicalRouterConfig',
+ '_href': '/ws.v1/lrouter/%s' % router_id, }
+ if relations:
+ router['_relations'] = relations
+ return router
+
+ def _get_single_route(self, router_id, route_id='fake_route_id_0',
+ prefix='0.0.0.0/0', next_hop_ip='1.1.1.1'):
+ return {'protocol': 'static',
+ '_href': '/ws.v1/lrouter/%s/rib/%s' % (router_id, route_id),
+ 'prefix': prefix,
+ '_schema': '/ws.v1/schema/RoutingTableEntry',
+ 'next_hop_ip': next_hop_ip,
+ 'action': 'accept',
+ 'uuid': route_id}
+
+ def test_prepare_body_with_implicit_routing_config(self):
+ router_name = 'fake_router_name'
+ tenant_id = 'fake_tenant_id'
+ neutron_router_id = 'pipita_higuain'
+ router_type = 'SingleDefaultRouteImplicitRoutingConfig'
+ route_config = {
+ 'default_route_next_hop': {'gateway_ip_address': 'fake_address',
+ 'type': 'RouterNextHop'}, }
+ body = routerlib._prepare_lrouter_body(router_name, neutron_router_id,
+ tenant_id, router_type,
+ **route_config)
+ expected = {'display_name': 'fake_router_name',
+ 'routing_config': {
+ 'default_route_next_hop':
+ {'gateway_ip_address': 'fake_address',
+ 'type': 'RouterNextHop'},
+ 'type': 'SingleDefaultRouteImplicitRoutingConfig'},
+ 'tags': [{'scope': 'os_tid', 'tag': 'fake_tenant_id'},
+ {'scope': 'q_router_id', 'tag': 'pipita_higuain'},
+ {'scope': 'quantum',
+ 'tag': nvplib.NEUTRON_VERSION}],
+ 'type': 'LogicalRouterConfig'}
+ self.assertEqual(expected, body)
+
+ def test_prepare_body_without_routing_config(self):
+ router_name = 'fake_router_name'
+ tenant_id = 'fake_tenant_id'
+ neutron_router_id = 'marekiaro_hamsik'
+ router_type = 'RoutingTableRoutingConfig'
+ body = routerlib._prepare_lrouter_body(router_name, neutron_router_id,
+ tenant_id, router_type)
+ expected = {'display_name': 'fake_router_name',
+ 'routing_config': {'type': 'RoutingTableRoutingConfig'},
+ 'tags': [{'scope': 'os_tid', 'tag': 'fake_tenant_id'},
+ {'scope': 'q_router_id',
+ 'tag': 'marekiaro_hamsik'},
+ {'scope': 'quantum',
+ 'tag': nvplib.NEUTRON_VERSION}],
+ 'type': 'LogicalRouterConfig'}
+ self.assertEqual(expected, body)
+
+ def test_get_lrouter(self):
+ tenant_id = 'fake_tenant_id'
+ router_name = 'fake_router_name'
+ router_id = 'fake_router_id'
+ relations = {
+ 'LogicalRouterStatus':
+ {'_href': '/ws.v1/lrouter/%s/status' % router_id,
+ 'lport_admin_up_count': 1,
+ '_schema': '/ws.v1/schema/LogicalRouterStatus',
+ 'lport_count': 1,
+ 'fabric_status': True,
+ 'type': 'LogicalRouterStatus',
+ 'lport_link_up_count': 0, }, }
+
+ with mock.patch.object(routerlib, 'do_request',
+ return_value=self._get_lrouter(tenant_id,
+ router_name,
+ router_id,
+ relations)):
+ lrouter = routerlib.get_lrouter(self.fake_cluster, router_id)
+ self.assertTrue(
+ lrouter['_relations']['LogicalRouterStatus']['fabric_status'])
+
+ def test_create_lrouter(self):
+ tenant_id = 'fake_tenant_id'
+ router_name = 'fake_router_name'
+ router_id = 'fake_router_id'
+ nexthop_ip = '10.0.0.1'
+ with mock.patch.object(
+ routerlib, 'do_request',
+ return_value=self._get_lrouter(tenant_id,
+ router_name,
+ router_id)):
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ uuidutils.generate_uuid(),
+ tenant_id,
+ router_name, nexthop_ip)
+ self.assertEqual(lrouter['routing_config']['type'],
+ 'RoutingTableRoutingConfig')
+ self.assertNotIn('default_route_next_hop',
+ lrouter['routing_config'])
+
+ def test_update_lrouter_with_no_routes(self):
+ router_id = 'fake_router_id'
+ new_routes = [{"nexthop": "10.0.0.2",
+ "destination": "169.254.169.0/30"}, ]
+
+ nvp_routes = [self._get_single_route(router_id)]
+ with mock.patch.object(routerlib, 'get_explicit_routes_lrouter',
+ return_value=nvp_routes):
+ with mock.patch.object(routerlib, 'create_explicit_route_lrouter',
+ return_value='fake_uuid'):
+ old_routes = routerlib.update_explicit_routes_lrouter(
+ self.fake_cluster, router_id, new_routes)
+ self.assertEqual(old_routes, nvp_routes)
+
+ def test_update_lrouter_with_no_routes_raise_nsx_exception(self):
+ router_id = 'fake_router_id'
+ new_routes = [{"nexthop": "10.0.0.2",
+ "destination": "169.254.169.0/30"}, ]
+
+ nsx_routes = [self._get_single_route(router_id)]
+ with mock.patch.object(routerlib, 'get_explicit_routes_lrouter',
+ return_value=nsx_routes):
+ with mock.patch.object(routerlib, 'create_explicit_route_lrouter',
+ side_effect=NvpApiClient.NvpApiException):
+ self.assertRaises(NvpApiClient.NvpApiException,
+ routerlib.update_explicit_routes_lrouter,
+ self.fake_cluster, router_id, new_routes)
+
+ def test_update_lrouter_with_routes(self):
+ router_id = 'fake_router_id'
+ new_routes = [{"next_hop_ip": "10.0.0.2",
+ "prefix": "169.254.169.0/30"}, ]
+
+ nsx_routes = [self._get_single_route(router_id),
+ self._get_single_route(router_id, 'fake_route_id_1',
+ '0.0.0.1/24', '10.0.0.3'),
+ self._get_single_route(router_id, 'fake_route_id_2',
+ '0.0.0.2/24', '10.0.0.4'), ]
+
+ with mock.patch.object(routerlib, 'get_explicit_routes_lrouter',
+ return_value=nsx_routes):
+ with mock.patch.object(routerlib, 'delete_explicit_route_lrouter',
+ return_value=None):
+ with mock.patch.object(routerlib,
+ 'create_explicit_route_lrouter',
+ return_value='fake_uuid'):
+ old_routes = routerlib.update_explicit_routes_lrouter(
+ self.fake_cluster, router_id, new_routes)
+ self.assertEqual(old_routes, nsx_routes)
+
+ def test_update_lrouter_with_routes_raises_nsx_expception(self):
+ router_id = 'fake_router_id'
+ new_routes = [{"nexthop": "10.0.0.2",
+ "destination": "169.254.169.0/30"}, ]
+
+ nsx_routes = [self._get_single_route(router_id),
+ self._get_single_route(router_id, 'fake_route_id_1',
+ '0.0.0.1/24', '10.0.0.3'),
+ self._get_single_route(router_id, 'fake_route_id_2',
+ '0.0.0.2/24', '10.0.0.4'), ]
+
+ with mock.patch.object(routerlib, 'get_explicit_routes_lrouter',
+ return_value=nsx_routes):
+ with mock.patch.object(routerlib, 'delete_explicit_route_lrouter',
+ side_effect=NvpApiClient.NvpApiException):
+ with mock.patch.object(
+ routerlib, 'create_explicit_route_lrouter',
+ return_value='fake_uuid'):
+ self.assertRaises(
+ NvpApiClient.NvpApiException,
+ routerlib.update_explicit_routes_lrouter,
+ self.fake_cluster, router_id, new_routes)
+
+
+class RouterNegativeTestCase(NsxlibNegativeBaseTestCase):
+
+ def test_create_lrouter_on_failure(self):
+ self.assertRaises(nvplib.NvpApiClient.NvpApiException,
+ routerlib.create_lrouter,
+ self.fake_cluster,
+ uuidutils.generate_uuid(),
+ 'pluto',
+ 'fake_router',
+ 'my_hop')
+
+ def test_delete_lrouter_on_failure(self):
+ self.assertRaises(nvplib.NvpApiClient.NvpApiException,
+ routerlib.delete_lrouter,
+ self.fake_cluster,
+ 'fake_router')
+
+ def test_get_lrouter_on_failure(self):
+ self.assertRaises(nvplib.NvpApiClient.NvpApiException,
+ routerlib.get_lrouter,
+ self.fake_cluster,
+ 'fake_router')
+
+ def test_update_lrouter_on_failure(self):
+ self.assertRaises(nvplib.NvpApiClient.NvpApiException,
+ routerlib.update_lrouter,
+ self.fake_cluster,
+ 'fake_router',
+ 'pluto',
+ 'new_hop')
+
+
+class TestLogicalRouters(NvplibTestCase):
+
+ def _verify_lrouter(self, res_lrouter,
+ expected_uuid,
+ expected_display_name,
+ expected_nexthop,
+ expected_tenant_id,
+ expected_neutron_id=None,
+ expected_distributed=None):
+ self.assertEqual(res_lrouter['uuid'], expected_uuid)
+ nexthop = (res_lrouter['routing_config']
+ ['default_route_next_hop']['gateway_ip_address'])
+ self.assertEqual(nexthop, expected_nexthop)
+ router_tags = self._build_tag_dict(res_lrouter['tags'])
+ self.assertIn('os_tid', router_tags)
+ self.assertEqual(res_lrouter['display_name'], expected_display_name)
+ self.assertEqual(expected_tenant_id, router_tags['os_tid'])
+ if expected_distributed is not None:
+ self.assertEqual(expected_distributed,
+ res_lrouter['distributed'])
+ if expected_neutron_id:
+ self.assertIn('q_router_id', router_tags)
+ self.assertEqual(expected_neutron_id, router_tags['q_router_id'])
+
+ def test_get_lrouters(self):
+ lrouter_uuids = [routerlib.create_lrouter(
+ self.fake_cluster, 'whatever', 'pippo', 'fake-lrouter-%s' % k,
+ '10.0.0.1')['uuid'] for k in range(3)]
+ routers = routerlib.get_lrouters(self.fake_cluster, 'pippo')
+ for router in routers:
+ self.assertIn(router['uuid'], lrouter_uuids)
+
+ def _create_lrouter(self, version, neutron_id=None, distributed=None):
+ with mock.patch.object(
+ self.fake_cluster.api_client, 'get_nvp_version',
+ return_value=NvpApiClient.NVPVersion(version)):
+ if not neutron_id:
+ neutron_id = uuidutils.generate_uuid()
+ lrouter = routerlib.create_lrouter(
+ self.fake_cluster, neutron_id, 'pippo',
+ 'fake-lrouter', '10.0.0.1', distributed=distributed)
+ return routerlib.get_lrouter(self.fake_cluster,
+ lrouter['uuid'])
+
+ def test_create_and_get_lrouter_v30(self):
+ neutron_id = uuidutils.generate_uuid()
+ res_lrouter = self._create_lrouter('3.0', neutron_id=neutron_id)
+ self._verify_lrouter(res_lrouter, res_lrouter['uuid'],
+ 'fake-lrouter', '10.0.0.1', 'pippo',
+ expected_neutron_id=neutron_id)
+
+ def test_create_and_get_lrouter_v31_centralized(self):
+ neutron_id = uuidutils.generate_uuid()
+ res_lrouter = self._create_lrouter('3.1', neutron_id=neutron_id,
+ distributed=False)
+ self._verify_lrouter(res_lrouter, res_lrouter['uuid'],
+ 'fake-lrouter', '10.0.0.1', 'pippo',
+ expected_neutron_id=neutron_id,
+ expected_distributed=False)
+
+ def test_create_and_get_lrouter_v31_distributed(self):
+ neutron_id = uuidutils.generate_uuid()
+ res_lrouter = self._create_lrouter('3.1', neutron_id=neutron_id,
+ distributed=True)
+ self._verify_lrouter(res_lrouter, res_lrouter['uuid'],
+ 'fake-lrouter', '10.0.0.1', 'pippo',
+ expected_neutron_id=neutron_id,
+ expected_distributed=True)
+
+ def test_create_and_get_lrouter_name_exceeds_40chars(self):
+ neutron_id = uuidutils.generate_uuid()
+ display_name = '*' * 50
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ neutron_id,
+ 'pippo',
+ display_name,
+ '10.0.0.1')
+ res_lrouter = routerlib.get_lrouter(self.fake_cluster,
+ lrouter['uuid'])
+ self._verify_lrouter(res_lrouter, lrouter['uuid'],
+ '*' * 40, '10.0.0.1', 'pippo',
+ expected_neutron_id=neutron_id)
+
+ def _test_version_dependent_update_lrouter(self, version):
+ def foo(*args, **kwargs):
+ return version
+
+ foo_func_dict = {
+ 'update_lrouter': {
+ 2: {-1: foo},
+ 3: {-1: foo, 2: foo}
+ }
+ }
+
+ with mock.patch.object(self.fake_cluster.api_client,
+ 'get_nvp_version',
+ return_value=NvpApiClient.NVPVersion(version)):
+ with mock.patch.dict(routerlib.ROUTER_FUNC_DICT,
+ foo_func_dict, clear=True):
+ return routerlib.update_lrouter(
+ self.fake_cluster, 'foo_router_id', 'foo_router_name',
+ 'foo_nexthop', routes={'foo_destination': 'foo_address'})
+
+ def test_version_dependent_update_lrouter_old_versions(self):
+ self.assertRaises(nvp_exc.NvpInvalidVersion,
+ self._test_version_dependent_update_lrouter,
+ "2.9")
+ self.assertRaises(nvp_exc.NvpInvalidVersion,
+ self._test_version_dependent_update_lrouter,
+ "3.0")
+ self.assertRaises(nvp_exc.NvpInvalidVersion,
+ self._test_version_dependent_update_lrouter,
+ "3.1")
+
+ def test_version_dependent_update_lrouter_new_versions(self):
+ self.assertEqual("3.2",
+ self._test_version_dependent_update_lrouter("3.2"))
+ self.assertEqual("4.0",
+ self._test_version_dependent_update_lrouter("4.0"))
+ self.assertEqual("4.1",
+ self._test_version_dependent_update_lrouter("4.1"))
+
+ def test_update_lrouter_no_nexthop(self):
+ neutron_id = uuidutils.generate_uuid()
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ neutron_id,
+ 'pippo',
+ 'fake-lrouter',
+ '10.0.0.1')
+ lrouter = routerlib.update_lrouter(self.fake_cluster,
+ lrouter['uuid'],
+ 'new_name',
+ None)
+ res_lrouter = routerlib.get_lrouter(self.fake_cluster,
+ lrouter['uuid'])
+ self._verify_lrouter(res_lrouter, lrouter['uuid'],
+ 'new_name', '10.0.0.1', 'pippo',
+ expected_neutron_id=neutron_id)
+
+ def test_update_lrouter(self):
+ neutron_id = uuidutils.generate_uuid()
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ neutron_id,
+ 'pippo',
+ 'fake-lrouter',
+ '10.0.0.1')
+ lrouter = routerlib.update_lrouter(self.fake_cluster,
+ lrouter['uuid'],
+ 'new_name',
+ '192.168.0.1')
+ res_lrouter = routerlib.get_lrouter(self.fake_cluster,
+ lrouter['uuid'])
+ self._verify_lrouter(res_lrouter, lrouter['uuid'],
+ 'new_name', '192.168.0.1', 'pippo',
+ expected_neutron_id=neutron_id)
+
+ def test_update_nonexistent_lrouter_raises(self):
+ self.assertRaises(exceptions.NotFound,
+ routerlib.update_lrouter,
+ self.fake_cluster,
+ 'whatever',
+ 'foo', '9.9.9.9')
+
+ def test_delete_lrouter(self):
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ uuidutils.generate_uuid(),
+ 'pippo',
+ 'fake-lrouter',
+ '10.0.0.1')
+ routerlib.delete_lrouter(self.fake_cluster, lrouter['uuid'])
+ self.assertRaises(exceptions.NotFound,
+ routerlib.get_lrouter,
+ self.fake_cluster,
+ lrouter['uuid'])
+
+ def test_query_lrouter_ports(self):
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ uuidutils.generate_uuid(),
+ 'pippo',
+ 'fake-lrouter',
+ '10.0.0.1')
+ router_port_uuids = [routerlib.create_router_lport(
+ self.fake_cluster, lrouter['uuid'], 'pippo',
+ 'qp_id_%s' % k, 'port-%s' % k, True,
+ ['192.168.0.%s' % k], '00:11:22:33:44:55')['uuid']
+ for k in range(3)]
+ ports = routerlib.query_lrouter_lports(
+ self.fake_cluster, lrouter['uuid'])
+ self.assertEqual(len(ports), 3)
+ for res_port in ports:
+ self.assertIn(res_port['uuid'], router_port_uuids)
+
+ def test_query_lrouter_lports_nonexistent_lrouter_raises(self):
+ self.assertRaises(
+ exceptions.NotFound, routerlib.create_router_lport,
+ self.fake_cluster, 'booo', 'pippo', 'neutron_port_id',
+ 'name', True, ['192.168.0.1'], '00:11:22:33:44:55')
+
+ def test_create_and_get_lrouter_port(self):
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ uuidutils.generate_uuid(),
+ 'pippo',
+ 'fake-lrouter',
+ '10.0.0.1')
+ routerlib.create_router_lport(
+ self.fake_cluster, lrouter['uuid'], 'pippo', 'neutron_port_id',
+ 'name', True, ['192.168.0.1'], '00:11:22:33:44:55')
+ ports = routerlib.query_lrouter_lports(
+ self.fake_cluster, lrouter['uuid'])
+ self.assertEqual(len(ports), 1)
+ res_port = ports[0]
+ port_tags = self._build_tag_dict(res_port['tags'])
+ self.assertEqual(['192.168.0.1'], res_port['ip_addresses'])
+ self.assertIn('os_tid', port_tags)
+ self.assertIn('q_port_id', port_tags)
+ self.assertEqual('pippo', port_tags['os_tid'])
+ self.assertEqual('neutron_port_id', port_tags['q_port_id'])
+
+ def test_create_lrouter_port_nonexistent_router_raises(self):
+ self.assertRaises(
+ exceptions.NotFound, routerlib.create_router_lport,
+ self.fake_cluster, 'booo', 'pippo', 'neutron_port_id',
+ 'name', True, ['192.168.0.1'], '00:11:22:33:44:55')
+
+ def test_update_lrouter_port(self):
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ uuidutils.generate_uuid(),
+ 'pippo',
+ 'fake-lrouter',
+ '10.0.0.1')
+ lrouter_port = routerlib.create_router_lport(
+ self.fake_cluster, lrouter['uuid'], 'pippo', 'neutron_port_id',
+ 'name', True, ['192.168.0.1'], '00:11:22:33:44:55')
+ routerlib.update_router_lport(
+ self.fake_cluster, lrouter['uuid'], lrouter_port['uuid'],
+ 'pippo', 'another_port_id', 'name', False,
+ ['192.168.0.1', '10.10.10.254'])
+
+ ports = routerlib.query_lrouter_lports(
+ self.fake_cluster, lrouter['uuid'])
+ self.assertEqual(len(ports), 1)
+ res_port = ports[0]
+ port_tags = self._build_tag_dict(res_port['tags'])
+ self.assertEqual(['192.168.0.1', '10.10.10.254'],
+ res_port['ip_addresses'])
+ self.assertEqual('False', res_port['admin_status_enabled'])
+ self.assertIn('os_tid', port_tags)
+ self.assertIn('q_port_id', port_tags)
+ self.assertEqual('pippo', port_tags['os_tid'])
+ self.assertEqual('another_port_id', port_tags['q_port_id'])
+
+ def test_update_lrouter_port_nonexistent_router_raises(self):
+ self.assertRaises(
+ exceptions.NotFound, routerlib.update_router_lport,
+ self.fake_cluster, 'boo-router', 'boo-port', 'pippo',
+ 'neutron_port_id', 'name', True, ['192.168.0.1'])
+
+ def test_update_lrouter_port_nonexistent_port_raises(self):
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ uuidutils.generate_uuid(),
+ 'pippo',
+ 'fake-lrouter',
+ '10.0.0.1')
+ self.assertRaises(
+ exceptions.NotFound, routerlib.update_router_lport,
+ self.fake_cluster, lrouter['uuid'], 'boo-port', 'pippo',
+ 'neutron_port_id', 'name', True, ['192.168.0.1'])
+
+ def test_delete_lrouter_port(self):
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ uuidutils.generate_uuid(),
+ 'pippo',
+ 'fake-lrouter',
+ '10.0.0.1')
+ lrouter_port = routerlib.create_router_lport(
+ self.fake_cluster, lrouter['uuid'], 'pippo', 'x', 'y', True, [],
+ '00:11:22:33:44:55')
+ ports = routerlib.query_lrouter_lports(
+ self.fake_cluster, lrouter['uuid'])
+ self.assertEqual(len(ports), 1)
+ routerlib.delete_router_lport(self.fake_cluster, lrouter['uuid'],
+ lrouter_port['uuid'])
+ ports = routerlib.query_lrouter_lports(
+ self.fake_cluster, lrouter['uuid'])
+ self.assertFalse(len(ports))
+
+ def test_delete_lrouter_port_nonexistent_router_raises(self):
+ self.assertRaises(exceptions.NotFound,
+ routerlib.delete_router_lport,
+ self.fake_cluster, 'xyz', 'abc')
+
+ def test_delete_lrouter_port_nonexistent_port_raises(self):
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ uuidutils.generate_uuid(),
+ 'pippo',
+ 'fake-lrouter',
+ '10.0.0.1')
+ self.assertRaises(exceptions.NotFound,
+ routerlib.delete_router_lport,
+ self.fake_cluster, lrouter['uuid'], 'abc')
+
+ def test_delete_peer_lrouter_port(self):
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ uuidutils.generate_uuid(),
+ 'pippo',
+ 'fake-lrouter',
+ '10.0.0.1')
+ lrouter_port = routerlib.create_router_lport(
+ self.fake_cluster, lrouter['uuid'], 'pippo', 'x', 'y', True, [],
+ '00:11:22:33:44:55')
+
+ def fakegetport(*args, **kwargs):
+ return {'_relations': {'LogicalPortAttachment':
+ {'peer_port_uuid': lrouter_port['uuid']}}}
+ # mock get_port
+ with mock.patch.object(routerlib, 'get_port', new=fakegetport):
+ routerlib.delete_peer_router_lport(self.fake_cluster,
+ lrouter_port['uuid'],
+ 'whatwever', 'whatever')
+
+ def test_update_lrouter_port_ips_add_only(self):
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ uuidutils.generate_uuid(),
+ 'pippo',
+ 'fake-lrouter',
+ '10.0.0.1')
+ lrouter_port = routerlib.create_router_lport(
+ self.fake_cluster, lrouter['uuid'], 'pippo', 'neutron_port_id',
+ 'name', True, ['192.168.0.1'], '00:11:22:33:44:55')
+ routerlib.update_lrouter_port_ips(
+ self.fake_cluster, lrouter['uuid'], lrouter_port['uuid'],
+ ['10.10.10.254'], [])
+ ports = routerlib.query_lrouter_lports(
+ self.fake_cluster, lrouter['uuid'])
+ self.assertEqual(len(ports), 1)
+ res_port = ports[0]
+ self.assertEqual(['10.10.10.254', '192.168.0.1'],
+ res_port['ip_addresses'])
+
+ def test_update_lrouter_port_ips_remove_only(self):
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ uuidutils.generate_uuid(),
+ 'pippo',
+ 'fake-lrouter',
+ '10.0.0.1')
+ lrouter_port = routerlib.create_router_lport(
+ self.fake_cluster, lrouter['uuid'], 'pippo', 'neutron_port_id',
+ 'name', True, ['192.168.0.1', '10.10.10.254'],
+ '00:11:22:33:44:55')
+ routerlib.update_lrouter_port_ips(
+ self.fake_cluster, lrouter['uuid'], lrouter_port['uuid'],
+ [], ['10.10.10.254'])
+ ports = routerlib.query_lrouter_lports(
+ self.fake_cluster, lrouter['uuid'])
+ self.assertEqual(len(ports), 1)
+ res_port = ports[0]
+ self.assertEqual(['192.168.0.1'], res_port['ip_addresses'])
+
+ def test_update_lrouter_port_ips_add_and_remove(self):
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ uuidutils.generate_uuid(),
+ 'pippo',
+ 'fake-lrouter',
+ '10.0.0.1')
+ lrouter_port = routerlib.create_router_lport(
+ self.fake_cluster, lrouter['uuid'], 'pippo', 'neutron_port_id',
+ 'name', True, ['192.168.0.1'], '00:11:22:33:44:55')
+ routerlib.update_lrouter_port_ips(
+ self.fake_cluster, lrouter['uuid'], lrouter_port['uuid'],
+ ['10.10.10.254'], ['192.168.0.1'])
+ ports = routerlib.query_lrouter_lports(
+ self.fake_cluster, lrouter['uuid'])
+ self.assertEqual(len(ports), 1)
+ res_port = ports[0]
+ self.assertEqual(['10.10.10.254'], res_port['ip_addresses'])
+
+ def test_update_lrouter_port_ips_nonexistent_router_raises(self):
+ self.assertRaises(
+ nvp_exc.NvpPluginException, routerlib.update_lrouter_port_ips,
+ self.fake_cluster, 'boo-router', 'boo-port', [], [])
+
+ def test_update_lrouter_port_ips_nsx_exception_raises(self):
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ uuidutils.generate_uuid(),
+ 'pippo',
+ 'fake-lrouter',
+ '10.0.0.1')
+ lrouter_port = routerlib.create_router_lport(
+ self.fake_cluster, lrouter['uuid'], 'pippo', 'neutron_port_id',
+ 'name', True, ['192.168.0.1'], '00:11:22:33:44:55')
+
+ def raise_nsx_exc(*args, **kwargs):
+ raise NvpApiClient.NvpApiException()
+
+ with mock.patch.object(routerlib, 'do_request', new=raise_nsx_exc):
+ self.assertRaises(
+ nvp_exc.NvpPluginException, routerlib.update_lrouter_port_ips,
+ self.fake_cluster, lrouter['uuid'],
+ lrouter_port['uuid'], [], [])
+
+ def test_plug_lrouter_port_patch_attachment(self):
+ tenant_id = 'pippo'
+ transport_zones_config = [{'zone_uuid': _uuid(),
+ 'transport_type': 'stt'}]
+ lswitch = nvplib.create_lswitch(self.fake_cluster,
+ _uuid(),
+ tenant_id, 'fake-switch',
+ transport_zones_config)
+ lport = nvplib.create_lport(self.fake_cluster, lswitch['uuid'],
+ tenant_id, 'xyz',
+ 'name', 'device_id', True)
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ uuidutils.generate_uuid(),
+ tenant_id,
+ 'fake-lrouter',
+ '10.0.0.1')
+ lrouter_port = routerlib.create_router_lport(
+ self.fake_cluster, lrouter['uuid'], 'pippo', 'neutron_port_id',
+ 'name', True, ['192.168.0.1'], '00:11:22:33:44:55:66')
+ result = routerlib.plug_router_port_attachment(
+ self.fake_cluster, lrouter['uuid'],
+ lrouter_port['uuid'],
+ lport['uuid'], 'PatchAttachment')
+ self.assertEqual(lport['uuid'],
+ result['LogicalPortAttachment']['peer_port_uuid'])
+
+ def test_plug_lrouter_port_l3_gw_attachment(self):
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ uuidutils.generate_uuid(),
+ 'pippo',
+ 'fake-lrouter',
+ '10.0.0.1')
+ lrouter_port = routerlib.create_router_lport(
+ self.fake_cluster, lrouter['uuid'], 'pippo', 'neutron_port_id',
+ 'name', True, ['192.168.0.1'], '00:11:22:33:44:55:66')
+ result = routerlib.plug_router_port_attachment(
+ self.fake_cluster, lrouter['uuid'],
+ lrouter_port['uuid'],
+ 'gw_att', 'L3GatewayAttachment')
+ self.assertEqual(
+ 'gw_att',
+ result['LogicalPortAttachment']['l3_gateway_service_uuid'])
+
+ def test_plug_lrouter_port_l3_gw_attachment_with_vlan(self):
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ uuidutils.generate_uuid(),
+ 'pippo',
+ 'fake-lrouter',
+ '10.0.0.1')
+ lrouter_port = routerlib.create_router_lport(
+ self.fake_cluster, lrouter['uuid'], 'pippo', 'neutron_port_id',
+ 'name', True, ['192.168.0.1'], '00:11:22:33:44:55')
+ result = routerlib.plug_router_port_attachment(
+ self.fake_cluster, lrouter['uuid'],
+ lrouter_port['uuid'],
+ 'gw_att', 'L3GatewayAttachment', 123)
+ self.assertEqual(
+ 'gw_att',
+ result['LogicalPortAttachment']['l3_gateway_service_uuid'])
+ self.assertEqual(
+ '123',
+ result['LogicalPortAttachment']['vlan_id'])
+
+ def test_plug_lrouter_port_invalid_attachment_type_raises(self):
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ uuidutils.generate_uuid(),
+ 'pippo',
+ 'fake-lrouter',
+ '10.0.0.1')
+ lrouter_port = routerlib.create_router_lport(
+ self.fake_cluster, lrouter['uuid'], 'pippo', 'neutron_port_id',
+ 'name', True, ['192.168.0.1'], '00:11:22:33:44:55')
+ self.assertRaises(nvp_exc.NvpInvalidAttachmentType,
+ routerlib.plug_router_port_attachment,
+ self.fake_cluster, lrouter['uuid'],
+ lrouter_port['uuid'], 'gw_att', 'BadType')
+
+ def _test_create_router_snat_rule(self, version):
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ uuidutils.generate_uuid(),
+ 'pippo',
+ 'fake-lrouter',
+ '10.0.0.1')
+ with mock.patch.object(self.fake_cluster.api_client,
+ 'get_nvp_version',
+ new=lambda: NvpApiClient.NVPVersion(version)):
+ routerlib.create_lrouter_snat_rule(
+ self.fake_cluster, lrouter['uuid'],
+ '10.0.0.2', '10.0.0.2', order=200,
+ match_criteria={'source_ip_addresses': '192.168.0.24'})
+ rules = routerlib.query_nat_rules(
+ self.fake_cluster, lrouter['uuid'])
+ self.assertEqual(len(rules), 1)
+
+ def test_create_router_snat_rule_v3(self):
+ self._test_create_router_snat_rule('3.0')
+
+ def test_create_router_snat_rule_v2(self):
+ self._test_create_router_snat_rule('2.0')
+
+ def _test_create_router_dnat_rule(self, version, dest_port=None):
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ uuidutils.generate_uuid(),
+ 'pippo',
+ 'fake-lrouter',
+ '10.0.0.1')
+ with mock.patch.object(self.fake_cluster.api_client,
+ 'get_nvp_version',
+ return_value=NvpApiClient.NVPVersion(version)):
+ routerlib.create_lrouter_dnat_rule(
+ self.fake_cluster, lrouter['uuid'], '192.168.0.2', order=200,
+ dest_port=dest_port,
+ match_criteria={'destination_ip_addresses': '10.0.0.3'})
+ rules = routerlib.query_nat_rules(
+ self.fake_cluster, lrouter['uuid'])
+ self.assertEqual(len(rules), 1)
+
+ def test_create_router_dnat_rule_v3(self):
+ self._test_create_router_dnat_rule('3.0')
+
+ def test_create_router_dnat_rule_v2(self):
+ self._test_create_router_dnat_rule('2.0')
+
+ def test_create_router_dnat_rule_v2_with_destination_port(self):
+ self._test_create_router_dnat_rule('2.0', 8080)
+
+ def test_create_router_dnat_rule_v3_with_destination_port(self):
+ self._test_create_router_dnat_rule('3.0', 8080)
+
+ def test_create_router_snat_rule_invalid_match_keys_raises(self):
+ # In this case the version does not make a difference
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ uuidutils.generate_uuid(),
+ 'pippo',
+ 'fake-lrouter',
+ '10.0.0.1')
+
+ with mock.patch.object(self.fake_cluster.api_client,
+ 'get_nvp_version',
+ new=lambda: '2.0'):
+ self.assertRaises(AttributeError,
+ routerlib.create_lrouter_snat_rule,
+ self.fake_cluster, lrouter['uuid'],
+ '10.0.0.2', '10.0.0.2', order=200,
+ match_criteria={'foo': 'bar'})
+
+ def _test_create_router_nosnat_rule(self, version, expected=1):
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ uuidutils.generate_uuid(),
+ 'pippo',
+ 'fake-lrouter',
+ '10.0.0.1')
+ with mock.patch.object(self.fake_cluster.api_client,
+ 'get_nvp_version',
+ new=lambda: NvpApiClient.NVPVersion(version)):
+ routerlib.create_lrouter_nosnat_rule(
+ self.fake_cluster, lrouter['uuid'],
+ order=100,
+ match_criteria={'destination_ip_addresses': '192.168.0.0/24'})
+ rules = routerlib.query_nat_rules(
+ self.fake_cluster, lrouter['uuid'])
+ # NoSNAT rules do not exist in V2
+ self.assertEqual(len(rules), expected)
+
+ def test_create_router_nosnat_rule_v2(self):
+ self._test_create_router_nosnat_rule('2.0', expected=0)
+
+ def test_create_router_nosnat_rule_v3(self):
+ self._test_create_router_nosnat_rule('3.0')
+
+ def _prepare_nat_rules_for_delete_tests(self):
+ lrouter = routerlib.create_lrouter(self.fake_cluster,
+ uuidutils.generate_uuid(),
+ 'pippo',
+ 'fake-lrouter',
+ '10.0.0.1')
+ # v2 or v3 makes no difference for this test
+ with mock.patch.object(self.fake_cluster.api_client,
+ 'get_nvp_version',
+ new=lambda: NvpApiClient.NVPVersion('2.0')):
+ routerlib.create_lrouter_snat_rule(
+ self.fake_cluster, lrouter['uuid'],
+ '10.0.0.2', '10.0.0.2', order=220,
+ match_criteria={'source_ip_addresses': '192.168.0.0/24'})
+ routerlib.create_lrouter_snat_rule(
+ self.fake_cluster, lrouter['uuid'],
+ '10.0.0.3', '10.0.0.3', order=200,
+ match_criteria={'source_ip_addresses': '192.168.0.2/32'})
+ routerlib.create_lrouter_dnat_rule(
+ self.fake_cluster, lrouter['uuid'], '192.168.0.2', order=200,
+ match_criteria={'destination_ip_addresses': '10.0.0.3'})
+ return lrouter
+
+ def test_delete_router_nat_rules_by_match_on_destination_ip(self):
+ lrouter = self._prepare_nat_rules_for_delete_tests()
+ rules = routerlib.query_nat_rules(self.fake_cluster, lrouter['uuid'])
+ self.assertEqual(len(rules), 3)
+ routerlib.delete_nat_rules_by_match(
+ self.fake_cluster, lrouter['uuid'], 'DestinationNatRule', 1, 1,
+ destination_ip_addresses='10.0.0.3')
+ rules = routerlib.query_nat_rules(self.fake_cluster, lrouter['uuid'])
+ self.assertEqual(len(rules), 2)
+
+ def test_delete_router_nat_rules_by_match_on_source_ip(self):
+ lrouter = self._prepare_nat_rules_for_delete_tests()
+ rules = routerlib.query_nat_rules(self.fake_cluster, lrouter['uuid'])
+ self.assertEqual(len(rules), 3)
+ routerlib.delete_nat_rules_by_match(
+ self.fake_cluster, lrouter['uuid'], 'SourceNatRule', 1, 1,
+ source_ip_addresses='192.168.0.2/32')
+ rules = routerlib.query_nat_rules(self.fake_cluster, lrouter['uuid'])
+ self.assertEqual(len(rules), 2)
+
+ def test_delete_router_nat_rules_by_match_no_match_expected(self):
+ lrouter = self._prepare_nat_rules_for_delete_tests()
+ rules = routerlib.query_nat_rules(self.fake_cluster, lrouter['uuid'])
+ self.assertEqual(len(rules), 3)
+ routerlib.delete_nat_rules_by_match(
+ self.fake_cluster, lrouter['uuid'], 'SomeWeirdType', 0)
+ rules = routerlib.query_nat_rules(self.fake_cluster, lrouter['uuid'])
+ self.assertEqual(len(rules), 3)
+ routerlib.delete_nat_rules_by_match(
+ self.fake_cluster, lrouter['uuid'], 'DestinationNatRule', 0,
+ destination_ip_addresses='99.99.99.99')
+ rules = routerlib.query_nat_rules(self.fake_cluster, lrouter['uuid'])
+ self.assertEqual(len(rules), 3)
+
+ def test_delete_router_nat_rules_by_match_no_match_raises(self):
+ lrouter = self._prepare_nat_rules_for_delete_tests()
+ rules = routerlib.query_nat_rules(self.fake_cluster, lrouter['uuid'])
+ self.assertEqual(len(rules), 3)
+ self.assertRaises(
+ nvp_exc.NvpNatRuleMismatch,
+ routerlib.delete_nat_rules_by_match,
+ self.fake_cluster, lrouter['uuid'],
+ 'SomeWeirdType', 1, 1)
--- /dev/null
+# Copyright (c) 2014 VMware, 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.
+#
+
+from neutron.plugins.nicira.nsxlib import router as routerlib
+from neutron.plugins.nicira.nsxlib import versioning
+from neutron.plugins.nicira import NvpApiClient
+from neutron.tests import base
+
+
+class TestVersioning(base.BaseTestCase):
+
+ def test_function_handling_missing_minor(self):
+ version = NvpApiClient.NVPVersion('2.0')
+ function = versioning.get_function_by_version(
+ routerlib.ROUTER_FUNC_DICT, 'create_lrouter', version)
+ self.assertEqual(routerlib.create_implicit_routing_lrouter,
+ function)
+
+ def test_function_handling_with_both_major_and_minor(self):
+ version = NvpApiClient.NVPVersion('3.2')
+ function = versioning.get_function_by_version(
+ routerlib.ROUTER_FUNC_DICT, 'create_lrouter', version)
+ self.assertEqual(routerlib.create_explicit_routing_lrouter,
+ function)
+
+ def test_function_handling_with_newer_major(self):
+ version = NvpApiClient.NVPVersion('5.2')
+ function = versioning.get_function_by_version(
+ routerlib.ROUTER_FUNC_DICT, 'create_lrouter', version)
+ self.assertEqual(routerlib.create_explicit_routing_lrouter,
+ function)
+
+ def test_function_handling_with_obsolete_major(self):
+ version = NvpApiClient.NVPVersion('1.2')
+ self.assertRaises(NotImplementedError,
+ versioning.get_function_by_version,
+ routerlib.ROUTER_FUNC_DICT,
+ 'create_lrouter', version)
+
+ def test_function_handling_with_unknown_version(self):
+ self.assertRaises(NvpApiClient.ServiceUnavailable,
+ versioning.get_function_by_version,
+ routerlib.ROUTER_FUNC_DICT,
+ 'create_lrouter', None)
self._test_router_create_with_distributed(True, True)
def test_router_create_distributed_with_new_nvp_versions(self):
- with mock.patch.object(nvplib, 'create_explicit_route_lrouter'):
+ with mock.patch.object(nsxlib.router, 'create_explicit_route_lrouter'):
self._test_router_create_with_distributed(True, True, '3.2')
self._test_router_create_with_distributed(True, True, '4.0')
self._test_router_create_with_distributed(True, True, '4.1')
def test_router_create_on_obsolete_platform(self):
def obsolete_response(*args, **kwargs):
- response = nvplib._create_implicit_routing_lrouter(*args, **kwargs)
+ response = (nsxlib.router.
+ _create_implicit_routing_lrouter(*args, **kwargs))
response.pop('distributed')
return response
with mock.patch.object(
- nvplib, 'create_lrouter', new=obsolete_response):
+ nsxlib.router, 'create_lrouter', new=obsolete_response):
self._test_router_create_with_distributed(None, False, '2.2')
def _create_router_with_gw_info_for_test(self, subnet):
return router_req.get_response(self.ext_api)
def test_router_create_nvp_error_returns_500(self, vlan_id=None):
- with mock.patch.object(nvplib,
+ with mock.patch.object(nsxlib.router,
'create_router_lport',
side_effect=NvpApiClient.NvpApiException):
with self._create_l3_ext_network(vlan_id) as net:
with self._create_l3_ext_network() as net:
with self.subnet(network=net) as s:
with mock.patch.object(
- nvplib,
+ nsxlib.router,
'do_request',
side_effect=nvp_exc.MaintenanceInProgress):
data = {'router': {'tenant_id': 'whatever'}}
# found for a given port identifier
exp_lr_uuid = uuidutils.generate_uuid()
self._mock_router_mapping_db_calls(None)
- with mock.patch(nicira_method('query_lrouters'),
+ with mock.patch(nicira_method('query_lrouters',
+ module_name='nsxlib.router'),
return_value=[{'uuid': exp_lr_uuid}]):
self._verify_get_nsx_router_id(exp_lr_uuid)
# This test verifies that the function returns None if the mapping
# are not found both in the db and in the backend
self._mock_router_mapping_db_calls(None)
- with mock.patch(nicira_method('query_lrouters'),
+ with mock.patch(nicira_method('query_lrouters',
+ module_name='nsxlib.router'),
return_value=[]):
self._verify_get_nsx_router_id(None)
from neutron.common import constants
from neutron.common import exceptions
-from neutron.openstack.common import uuidutils
from neutron.plugins.nicira.common import config # noqa
from neutron.plugins.nicira.common import exceptions as nvp_exc
from neutron.plugins.nicira.common import utils
from neutron.plugins.nicira import nvplib
from neutron.tests import base
from neutron.tests.unit.nicira import fake_nvpapiclient
-from neutron.tests.unit.nicira import nicira_method
from neutron.tests.unit.nicira import NVPAPI_NAME
from neutron.tests.unit.nicira import STUBS_PATH
from neutron.tests.unit import test_api_v2
return dict((t['scope'], t['tag']) for t in tags)
-class TestNvplibNatRules(NvplibTestCase):
-
- def _test_create_lrouter_dnat_rule(self, version):
- with mock.patch.object(self.fake_cluster.api_client,
- 'get_nvp_version',
- new=lambda: NvpApiClient.NVPVersion(version)):
- tenant_id = 'pippo'
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- uuidutils.generate_uuid(),
- tenant_id,
- 'fake_router',
- '192.168.0.1')
- nat_rule = nvplib.create_lrouter_dnat_rule(
- self.fake_cluster, lrouter['uuid'], '10.0.0.99',
- match_criteria={'destination_ip_addresses':
- '192.168.0.5'})
- uri = nvplib._build_uri_path(nvplib.LROUTERNAT_RESOURCE,
- nat_rule['uuid'],
- lrouter['uuid'])
- resp_obj = nvplib.do_request("GET", uri, cluster=self.fake_cluster)
- self.assertEqual('DestinationNatRule', resp_obj['type'])
- self.assertEqual('192.168.0.5',
- resp_obj['match']['destination_ip_addresses'])
-
- def test_create_lrouter_dnat_rule_v2(self):
- self._test_create_lrouter_dnat_rule('2.9')
-
- def test_create_lrouter_dnat_rule_v31(self):
- self._test_create_lrouter_dnat_rule('3.1')
-
-
-class NvplibNegativeTests(base.BaseTestCase):
+class NsxlibNegativeBaseTestCase(base.BaseTestCase):
def setUp(self):
# mock nvp api client
self.fake_cluster.req_timeout, self.fake_cluster.http_timeout,
self.fake_cluster.retries, self.fake_cluster.redirects)
- super(NvplibNegativeTests, self).setUp()
+ super(NsxlibNegativeBaseTestCase, self).setUp()
self.addCleanup(self.fc.reset_all)
self.addCleanup(self.mock_nvpapi.stop)
+
+class L2GatewayNegativeTestCase(NsxlibNegativeBaseTestCase):
+
def test_create_l2_gw_service_on_failure(self):
self.assertRaises(nvplib.NvpApiClient.NvpApiException,
nvplib.create_l2_gw_service,
'fake-gateway',
'pluto')
- def test_create_lrouter_on_failure(self):
- self.assertRaises(nvplib.NvpApiClient.NvpApiException,
- nvplib.create_lrouter,
- self.fake_cluster,
- uuidutils.generate_uuid(),
- 'pluto',
- 'fake_router',
- 'my_hop')
-
- def test_delete_lrouter_on_failure(self):
- self.assertRaises(nvplib.NvpApiClient.NvpApiException,
- nvplib.delete_lrouter,
- self.fake_cluster,
- 'fake_router')
-
- def test_get_lrouter_on_failure(self):
- self.assertRaises(nvplib.NvpApiClient.NvpApiException,
- nvplib.get_lrouter,
- self.fake_cluster,
- 'fake_router')
-
- def test_update_lrouter_on_failure(self):
- self.assertRaises(nvplib.NvpApiClient.NvpApiException,
- nvplib.update_lrouter,
- self.fake_cluster,
- 'fake_router',
- 'pluto',
- 'new_hop')
-
class TestNvplibL2Gateway(NvplibTestCase):
self.fake_cluster, 'whatever', ['whatever'])
-class TestNvplibExplicitLRouters(NvplibTestCase):
-
- def setUp(self):
- self.fake_version = '3.2'
- super(TestNvplibExplicitLRouters, self).setUp()
-
- def _get_lrouter(self, tenant_id, router_name, router_id, relations=None):
- schema = '/ws.v1/schema/RoutingTableRoutingConfig'
-
- router = {'display_name': router_name,
- 'uuid': router_id,
- 'tags': [{'scope': 'quantum', 'tag': nvplib.NEUTRON_VERSION},
- {'scope': 'os_tid', 'tag': '%s' % tenant_id}],
- 'distributed': False,
- 'routing_config': {'type': 'RoutingTableRoutingConfig',
- '_schema': schema},
- '_schema': schema,
- 'nat_synchronization_enabled': True,
- 'replication_mode': 'service',
- 'type': 'LogicalRouterConfig',
- '_href': '/ws.v1/lrouter/%s' % router_id, }
- if relations:
- router['_relations'] = relations
- return router
-
- def _get_single_route(self, router_id, route_id='fake_route_id_0',
- prefix='0.0.0.0/0', next_hop_ip='1.1.1.1'):
- return {'protocol': 'static',
- '_href': '/ws.v1/lrouter/%s/rib/%s' % (router_id, route_id),
- 'prefix': prefix,
- '_schema': '/ws.v1/schema/RoutingTableEntry',
- 'next_hop_ip': next_hop_ip,
- 'action': 'accept',
- 'uuid': route_id}
-
- def test_prepare_body_with_implicit_routing_config(self):
- router_name = 'fake_router_name'
- tenant_id = 'fake_tenant_id'
- neutron_router_id = 'pipita_higuain'
- router_type = 'SingleDefaultRouteImplicitRoutingConfig'
- route_config = {
- 'default_route_next_hop': {'gateway_ip_address': 'fake_address',
- 'type': 'RouterNextHop'}, }
- body = nvplib._prepare_lrouter_body(router_name, neutron_router_id,
- tenant_id, router_type,
- **route_config)
- expected = {'display_name': 'fake_router_name',
- 'routing_config': {
- 'default_route_next_hop':
- {'gateway_ip_address': 'fake_address',
- 'type': 'RouterNextHop'},
- 'type': 'SingleDefaultRouteImplicitRoutingConfig'},
- 'tags': [{'scope': 'os_tid', 'tag': 'fake_tenant_id'},
- {'scope': 'q_router_id', 'tag': 'pipita_higuain'},
- {'scope': 'quantum',
- 'tag': nvplib.NEUTRON_VERSION}],
- 'type': 'LogicalRouterConfig'}
- self.assertEqual(expected, body)
-
- def test_prepare_body_without_routing_config(self):
- router_name = 'fake_router_name'
- tenant_id = 'fake_tenant_id'
- router_type = 'RoutingTableRoutingConfig'
- neutron_router_id = 'marekiaro_hamsik'
- body = nvplib._prepare_lrouter_body(router_name, neutron_router_id,
- tenant_id, router_type)
- expected = {'display_name': 'fake_router_name',
- 'routing_config': {'type': 'RoutingTableRoutingConfig'},
- 'tags': [{'scope': 'os_tid', 'tag': 'fake_tenant_id'},
- {'scope': 'q_router_id',
- 'tag': 'marekiaro_hamsik'},
- {'scope': 'quantum',
- 'tag': nvplib.NEUTRON_VERSION}],
- 'type': 'LogicalRouterConfig'}
- self.assertEqual(expected, body)
-
- def test_get_lrouter(self):
- tenant_id = 'fake_tenant_id'
- router_name = 'fake_router_name'
- router_id = 'fake_router_id'
- relations = {
- 'LogicalRouterStatus':
- {'_href': '/ws.v1/lrouter/%s/status' % router_id,
- 'lport_admin_up_count': 1,
- '_schema': '/ws.v1/schema/LogicalRouterStatus',
- 'lport_count': 1,
- 'fabric_status': True,
- 'type': 'LogicalRouterStatus',
- 'lport_link_up_count': 0, }, }
-
- with mock.patch(nicira_method('do_request'),
- return_value=self._get_lrouter(tenant_id,
- router_name,
- router_id,
- relations)):
- lrouter = nvplib.get_lrouter(self.fake_cluster, router_id)
- self.assertTrue(
- lrouter['_relations']['LogicalRouterStatus']['fabric_status'])
-
- def test_create_lrouter(self):
- tenant_id = 'fake_tenant_id'
- router_name = 'fake_router_name'
- router_id = 'fake_router_id'
- nexthop_ip = '10.0.0.1'
- with mock.patch(nicira_method('do_request'),
- return_value=self._get_lrouter(tenant_id,
- router_name,
- router_id)):
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- uuidutils.generate_uuid(),
- tenant_id,
- router_name, nexthop_ip)
- self.assertEqual(lrouter['routing_config']['type'],
- 'RoutingTableRoutingConfig')
- self.assertNotIn('default_route_next_hop',
- lrouter['routing_config'])
-
- def test_update_lrouter_nvp_with_no_routes(self):
- router_id = 'fake_router_id'
- new_routes = [{"nexthop": "10.0.0.2",
- "destination": "169.254.169.0/30"}, ]
-
- nvp_routes = [self._get_single_route(router_id)]
- with mock.patch(nicira_method('get_explicit_routes_lrouter'),
- return_value=nvp_routes):
- with mock.patch(nicira_method('create_explicit_route_lrouter'),
- return_value='fake_uuid'):
- old_routes = nvplib.update_explicit_routes_lrouter(
- self.fake_cluster, router_id, new_routes)
- self.assertEqual(old_routes, nvp_routes)
-
- def test_update_lrouter_nvp_with_no_routes_raise_nvp_exception(self):
- router_id = 'fake_router_id'
- new_routes = [{"nexthop": "10.0.0.2",
- "destination": "169.254.169.0/30"}, ]
-
- nvp_routes = [self._get_single_route(router_id)]
- with mock.patch(nicira_method('get_explicit_routes_lrouter'),
- return_value=nvp_routes):
- with mock.patch(nicira_method('create_explicit_route_lrouter'),
- side_effect=NvpApiClient.NvpApiException):
- self.assertRaises(NvpApiClient.NvpApiException,
- nvplib.update_explicit_routes_lrouter,
- self.fake_cluster, router_id, new_routes)
-
- def test_update_lrouter_with_routes(self):
- router_id = 'fake_router_id'
- new_routes = [{"next_hop_ip": "10.0.0.2",
- "prefix": "169.254.169.0/30"}, ]
-
- nvp_routes = [self._get_single_route(router_id),
- self._get_single_route(router_id, 'fake_route_id_1',
- '0.0.0.1/24', '10.0.0.3'),
- self._get_single_route(router_id, 'fake_route_id_2',
- '0.0.0.2/24', '10.0.0.4'), ]
-
- with mock.patch(nicira_method('get_explicit_routes_lrouter'),
- return_value=nvp_routes):
- with mock.patch(nicira_method('delete_explicit_route_lrouter'),
- return_value=None):
- with mock.patch(nicira_method(
- 'create_explicit_route_lrouter'),
- return_value='fake_uuid'):
- old_routes = nvplib.update_explicit_routes_lrouter(
- self.fake_cluster, router_id, new_routes)
- self.assertEqual(old_routes, nvp_routes)
-
- def test_update_lrouter_with_routes_raises_nvp_expception(self):
- router_id = 'fake_router_id'
- new_routes = [{"nexthop": "10.0.0.2",
- "destination": "169.254.169.0/30"}, ]
-
- nvp_routes = [self._get_single_route(router_id),
- self._get_single_route(router_id, 'fake_route_id_1',
- '0.0.0.1/24', '10.0.0.3'),
- self._get_single_route(router_id, 'fake_route_id_2',
- '0.0.0.2/24', '10.0.0.4'), ]
-
- with mock.patch(nicira_method('get_explicit_routes_lrouter'),
- return_value=nvp_routes):
- with mock.patch(nicira_method('delete_explicit_route_lrouter'),
- side_effect=NvpApiClient.NvpApiException):
- with mock.patch(
- nicira_method('create_explicit_route_lrouter'),
- return_value='fake_uuid'):
- self.assertRaises(
- NvpApiClient.NvpApiException,
- nvplib.update_explicit_routes_lrouter,
- self.fake_cluster, router_id, new_routes)
-
-
-class TestNvplibLogicalRouters(NvplibTestCase):
-
- def _verify_lrouter(self, res_lrouter,
- expected_uuid,
- expected_display_name,
- expected_nexthop,
- expected_tenant_id,
- expected_neutron_id=None,
- expected_distributed=None):
- self.assertEqual(res_lrouter['uuid'], expected_uuid)
- nexthop = (res_lrouter['routing_config']
- ['default_route_next_hop']['gateway_ip_address'])
- self.assertEqual(nexthop, expected_nexthop)
- router_tags = self._build_tag_dict(res_lrouter['tags'])
- self.assertIn('os_tid', router_tags)
- self.assertEqual(res_lrouter['display_name'], expected_display_name)
- self.assertEqual(expected_tenant_id, router_tags['os_tid'])
- if expected_distributed is not None:
- self.assertEqual(expected_distributed,
- res_lrouter['distributed'])
- if expected_neutron_id:
- self.assertIn('q_router_id', router_tags)
- self.assertEqual(expected_neutron_id, router_tags['q_router_id'])
-
- def test_get_lrouters(self):
- lrouter_uuids = [nvplib.create_lrouter(
- self.fake_cluster, 'whatever', 'pippo', 'fake-lrouter-%s' % k,
- '10.0.0.1')['uuid'] for k in range(3)]
- routers = nvplib.get_lrouters(self.fake_cluster, 'pippo')
- for router in routers:
- self.assertIn(router['uuid'], lrouter_uuids)
-
- def _create_lrouter(self, version, neutron_id=None, distributed=None):
- with mock.patch.object(
- self.fake_cluster.api_client, 'get_nvp_version',
- return_value=NvpApiClient.NVPVersion(version)):
- if not neutron_id:
- neutron_id = uuidutils.generate_uuid()
- lrouter = nvplib.create_lrouter(
- self.fake_cluster, neutron_id, 'pippo',
- 'fake-lrouter', '10.0.0.1', distributed=distributed)
- return nvplib.get_lrouter(self.fake_cluster,
- lrouter['uuid'])
-
- def test_create_and_get_lrouter_v30(self):
- neutron_id = uuidutils.generate_uuid()
- res_lrouter = self._create_lrouter('3.0', neutron_id=neutron_id)
- self._verify_lrouter(res_lrouter, res_lrouter['uuid'],
- 'fake-lrouter', '10.0.0.1', 'pippo',
- neutron_id)
-
- def test_create_and_get_lrouter_v31_centralized(self):
- neutron_id = uuidutils.generate_uuid()
- res_lrouter = self._create_lrouter('3.1', neutron_id=neutron_id,
- distributed=False)
- self._verify_lrouter(res_lrouter, res_lrouter['uuid'],
- 'fake-lrouter', '10.0.0.1', 'pippo',
- expected_neutron_id=neutron_id,
- expected_distributed=False)
-
- def test_create_and_get_lrouter_v31_distributed(self):
- neutron_id = uuidutils.generate_uuid()
- res_lrouter = self._create_lrouter('3.1', neutron_id=neutron_id,
- distributed=True)
- self._verify_lrouter(res_lrouter, res_lrouter['uuid'],
- 'fake-lrouter', '10.0.0.1', 'pippo',
- expected_neutron_id=neutron_id,
- expected_distributed=True)
-
- def test_create_and_get_lrouter_name_exceeds_40chars(self):
- neutron_id = uuidutils.generate_uuid()
- display_name = '*' * 50
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- neutron_id,
- 'pippo',
- display_name,
- '10.0.0.1')
- res_lrouter = nvplib.get_lrouter(self.fake_cluster,
- lrouter['uuid'])
- self._verify_lrouter(res_lrouter, lrouter['uuid'],
- '*' * 40, '10.0.0.1', 'pippo',
- expected_neutron_id=neutron_id)
-
- def _test_version_dependent_update_lrouter(self, version):
- def foo(*args, **kwargs):
- return version
-
- foo_func_dict = {
- 'update_lrouter': {
- 2: {-1: foo},
- 3: {-1: foo, 2: foo}
- }
- }
-
- with mock.patch.object(self.fake_cluster.api_client,
- 'get_nvp_version',
- return_value=NvpApiClient.NVPVersion(version)):
- with mock.patch.dict(nvplib.NVPLIB_FUNC_DICT,
- foo_func_dict, clear=True):
- return nvplib.update_lrouter(
- self.fake_cluster, 'foo_router_id', 'foo_router_name',
- 'foo_nexthop', routes={'foo_destination': 'foo_address'})
-
- def test_version_dependent_update_lrouter_old_versions(self):
- self.assertRaises(nvp_exc.NvpInvalidVersion,
- self._test_version_dependent_update_lrouter,
- "2.9")
- self.assertRaises(nvp_exc.NvpInvalidVersion,
- self._test_version_dependent_update_lrouter,
- "3.0")
- self.assertRaises(nvp_exc.NvpInvalidVersion,
- self._test_version_dependent_update_lrouter,
- "3.1")
-
- def test_version_dependent_update_lrouter_new_versions(self):
- self.assertEqual("3.2",
- self._test_version_dependent_update_lrouter("3.2"))
- self.assertEqual("4.0",
- self._test_version_dependent_update_lrouter("4.0"))
- self.assertEqual("4.1",
- self._test_version_dependent_update_lrouter("4.1"))
-
- def test_update_lrouter_no_nexthop(self):
- neutron_id = uuidutils.generate_uuid()
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- neutron_id,
- 'pippo',
- 'fake-lrouter',
- '10.0.0.1')
- lrouter = nvplib.update_lrouter(self.fake_cluster,
- lrouter['uuid'],
- 'new_name',
- None)
- res_lrouter = nvplib.get_lrouter(self.fake_cluster,
- lrouter['uuid'])
- self._verify_lrouter(res_lrouter, lrouter['uuid'],
- 'new_name', '10.0.0.1', 'pippo',
- expected_neutron_id=neutron_id)
-
- def test_update_lrouter(self):
- neutron_id = uuidutils.generate_uuid()
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- neutron_id,
- 'pippo',
- 'fake-lrouter',
- '10.0.0.1')
- lrouter = nvplib.update_lrouter(self.fake_cluster,
- lrouter['uuid'],
- 'new_name',
- '192.168.0.1')
- res_lrouter = nvplib.get_lrouter(self.fake_cluster,
- lrouter['uuid'])
- self._verify_lrouter(res_lrouter, lrouter['uuid'],
- 'new_name', '192.168.0.1', 'pippo',
- expected_neutron_id=neutron_id)
-
- def test_update_nonexistent_lrouter_raises(self):
- self.assertRaises(exceptions.NotFound,
- nvplib.update_lrouter,
- self.fake_cluster,
- 'whatever',
- 'foo', '9.9.9.9')
-
- def test_delete_lrouter(self):
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- uuidutils.generate_uuid(),
- 'pippo',
- 'fake-lrouter',
- '10.0.0.1')
- nvplib.delete_lrouter(self.fake_cluster, lrouter['uuid'])
- self.assertRaises(exceptions.NotFound,
- nvplib.get_lrouter,
- self.fake_cluster,
- lrouter['uuid'])
-
- def test_query_lrouter_ports(self):
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- uuidutils.generate_uuid(),
- 'pippo',
- 'fake-lrouter',
- '10.0.0.1')
- router_port_uuids = [nvplib.create_router_lport(
- self.fake_cluster, lrouter['uuid'], 'pippo',
- 'qp_id_%s' % k, 'port-%s' % k, True,
- ['192.168.0.%s' % k], '00:11:22:33:44:55')['uuid']
- for k in range(3)]
- ports = nvplib.query_lrouter_lports(self.fake_cluster, lrouter['uuid'])
- self.assertEqual(len(ports), 3)
- for res_port in ports:
- self.assertIn(res_port['uuid'], router_port_uuids)
-
- def test_query_lrouter_lports_nonexistent_lrouter_raises(self):
- self.assertRaises(
- exceptions.NotFound, nvplib.create_router_lport,
- self.fake_cluster, 'booo', 'pippo', 'neutron_port_id',
- 'name', True, ['192.168.0.1'], '00:11:22:33:44:55')
-
- def test_create_and_get_lrouter_port(self):
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- uuidutils.generate_uuid(),
- 'pippo',
- 'fake-lrouter',
- '10.0.0.1')
- nvplib.create_router_lport(
- self.fake_cluster, lrouter['uuid'], 'pippo', 'neutron_port_id',
- 'name', True, ['192.168.0.1'], '00:11:22:33:44:55')
- ports = nvplib.query_lrouter_lports(self.fake_cluster, lrouter['uuid'])
- self.assertEqual(len(ports), 1)
- res_port = ports[0]
- port_tags = self._build_tag_dict(res_port['tags'])
- self.assertEqual(['192.168.0.1'], res_port['ip_addresses'])
- self.assertIn('os_tid', port_tags)
- self.assertIn('q_port_id', port_tags)
- self.assertEqual('pippo', port_tags['os_tid'])
- self.assertEqual('neutron_port_id', port_tags['q_port_id'])
-
- def test_create_lrouter_port_nonexistent_router_raises(self):
- self.assertRaises(
- exceptions.NotFound, nvplib.create_router_lport,
- self.fake_cluster, 'booo', 'pippo', 'neutron_port_id',
- 'name', True, ['192.168.0.1'], '00:11:22:33:44:55')
-
- def test_update_lrouter_port(self):
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- uuidutils.generate_uuid(),
- 'pippo',
- 'fake-lrouter',
- '10.0.0.1')
- lrouter_port = nvplib.create_router_lport(
- self.fake_cluster, lrouter['uuid'], 'pippo', 'neutron_port_id',
- 'name', True, ['192.168.0.1'], '00:11:22:33:44:55')
- nvplib.update_router_lport(
- self.fake_cluster, lrouter['uuid'], lrouter_port['uuid'],
- 'pippo', 'another_port_id', 'name', False,
- ['192.168.0.1', '10.10.10.254'])
-
- ports = nvplib.query_lrouter_lports(self.fake_cluster, lrouter['uuid'])
- self.assertEqual(len(ports), 1)
- res_port = ports[0]
- port_tags = self._build_tag_dict(res_port['tags'])
- self.assertEqual(['192.168.0.1', '10.10.10.254'],
- res_port['ip_addresses'])
- self.assertEqual('False', res_port['admin_status_enabled'])
- self.assertIn('os_tid', port_tags)
- self.assertIn('q_port_id', port_tags)
- self.assertEqual('pippo', port_tags['os_tid'])
- self.assertEqual('another_port_id', port_tags['q_port_id'])
-
- def test_update_lrouter_port_nonexistent_router_raises(self):
- self.assertRaises(
- exceptions.NotFound, nvplib.update_router_lport,
- self.fake_cluster, 'boo-router', 'boo-port', 'pippo',
- 'neutron_port_id', 'name', True, ['192.168.0.1'])
-
- def test_update_lrouter_port_nonexistent_port_raises(self):
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- uuidutils.generate_uuid(),
- 'pippo',
- 'fake-lrouter',
- '10.0.0.1')
- self.assertRaises(
- exceptions.NotFound, nvplib.update_router_lport,
- self.fake_cluster, lrouter['uuid'], 'boo-port', 'pippo',
- 'neutron_port_id', 'name', True, ['192.168.0.1'])
-
- def test_delete_lrouter_port(self):
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- uuidutils.generate_uuid(),
- 'pippo',
- 'fake-lrouter',
- '10.0.0.1')
- lrouter_port = nvplib.create_router_lport(
- self.fake_cluster, lrouter['uuid'], 'pippo', 'x', 'y', True, [],
- '00:11:22:33:44:55')
- ports = nvplib.query_lrouter_lports(self.fake_cluster, lrouter['uuid'])
- self.assertEqual(len(ports), 1)
- nvplib.delete_router_lport(self.fake_cluster, lrouter['uuid'],
- lrouter_port['uuid'])
- ports = nvplib.query_lrouter_lports(self.fake_cluster, lrouter['uuid'])
- self.assertFalse(len(ports))
-
- def test_delete_lrouter_port_nonexistent_router_raises(self):
- self.assertRaises(exceptions.NotFound,
- nvplib.delete_router_lport,
- self.fake_cluster, 'xyz', 'abc')
-
- def test_delete_lrouter_port_nonexistent_port_raises(self):
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- uuidutils.generate_uuid(),
- 'pippo',
- 'fake-lrouter',
- '10.0.0.1')
- self.assertRaises(exceptions.NotFound,
- nvplib.delete_router_lport,
- self.fake_cluster, lrouter['uuid'], 'abc')
-
- def test_delete_peer_lrouter_port(self):
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- uuidutils.generate_uuid(),
- 'pippo',
- 'fake-lrouter',
- '10.0.0.1')
- lrouter_port = nvplib.create_router_lport(
- self.fake_cluster, lrouter['uuid'], 'pippo', 'x', 'y', True, [],
- '00:11:22:33:44:55')
-
- def fakegetport(*args, **kwargs):
- return {'_relations': {'LogicalPortAttachment':
- {'peer_port_uuid': lrouter_port['uuid']}}}
- # mock get_port
- with mock.patch.object(nvplib, 'get_port', new=fakegetport):
- nvplib.delete_peer_router_lport(self.fake_cluster,
- lrouter_port['uuid'],
- 'whatwever', 'whatever')
-
- def test_update_lrouter_port_ips_add_only(self):
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- uuidutils.generate_uuid(),
- 'pippo',
- 'fake-lrouter',
- '10.0.0.1')
- lrouter_port = nvplib.create_router_lport(
- self.fake_cluster, lrouter['uuid'], 'pippo', 'neutron_port_id',
- 'name', True, ['192.168.0.1'], '00:11:22:33:44:55')
- nvplib.update_lrouter_port_ips(
- self.fake_cluster, lrouter['uuid'], lrouter_port['uuid'],
- ['10.10.10.254'], [])
- ports = nvplib.query_lrouter_lports(self.fake_cluster, lrouter['uuid'])
- self.assertEqual(len(ports), 1)
- res_port = ports[0]
- self.assertEqual(['10.10.10.254', '192.168.0.1'],
- res_port['ip_addresses'])
-
- def test_update_lrouter_port_ips_remove_only(self):
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- uuidutils.generate_uuid(),
- 'pippo',
- 'fake-lrouter',
- '10.0.0.1')
- lrouter_port = nvplib.create_router_lport(
- self.fake_cluster, lrouter['uuid'], 'pippo', 'neutron_port_id',
- 'name', True, ['192.168.0.1', '10.10.10.254'],
- '00:11:22:33:44:55')
- nvplib.update_lrouter_port_ips(
- self.fake_cluster, lrouter['uuid'], lrouter_port['uuid'],
- [], ['10.10.10.254'])
- ports = nvplib.query_lrouter_lports(self.fake_cluster, lrouter['uuid'])
- self.assertEqual(len(ports), 1)
- res_port = ports[0]
- self.assertEqual(['192.168.0.1'], res_port['ip_addresses'])
-
- def test_update_lrouter_port_ips_add_and_remove(self):
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- uuidutils.generate_uuid(),
- 'pippo',
- 'fake-lrouter',
- '10.0.0.1')
- lrouter_port = nvplib.create_router_lport(
- self.fake_cluster, lrouter['uuid'], 'pippo', 'neutron_port_id',
- 'name', True, ['192.168.0.1'], '00:11:22:33:44:55')
- nvplib.update_lrouter_port_ips(
- self.fake_cluster, lrouter['uuid'], lrouter_port['uuid'],
- ['10.10.10.254'], ['192.168.0.1'])
- ports = nvplib.query_lrouter_lports(self.fake_cluster, lrouter['uuid'])
- self.assertEqual(len(ports), 1)
- res_port = ports[0]
- self.assertEqual(['10.10.10.254'], res_port['ip_addresses'])
-
- def test_update_lrouter_port_ips_nonexistent_router_raises(self):
- self.assertRaises(
- nvp_exc.NvpPluginException, nvplib.update_lrouter_port_ips,
- self.fake_cluster, 'boo-router', 'boo-port', [], [])
-
- def test_update_lrouter_port_ips_nvp_exception_raises(self):
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- uuidutils.generate_uuid(),
- 'pippo',
- 'fake-lrouter',
- '10.0.0.1')
- lrouter_port = nvplib.create_router_lport(
- self.fake_cluster, lrouter['uuid'], 'pippo', 'neutron_port_id',
- 'name', True, ['192.168.0.1'], '00:11:22:33:44:55')
-
- def raise_nvp_exc(*args, **kwargs):
- raise NvpApiClient.NvpApiException()
-
- with mock.patch.object(nvplib, 'do_request', new=raise_nvp_exc):
- self.assertRaises(
- nvp_exc.NvpPluginException, nvplib.update_lrouter_port_ips,
- self.fake_cluster, lrouter['uuid'],
- lrouter_port['uuid'], [], [])
-
- def test_plug_lrouter_port_patch_attachment(self):
- tenant_id = 'pippo'
- transport_zones_config = [{'zone_uuid': _uuid(),
- 'transport_type': 'stt'}]
- lswitch = nvplib.create_lswitch(self.fake_cluster,
- _uuid(),
- tenant_id, 'fake-switch',
- transport_zones_config)
- lport = nvplib.create_lport(self.fake_cluster, lswitch['uuid'],
- tenant_id, 'xyz',
- 'name', 'device_id', True)
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- uuidutils.generate_uuid(),
- tenant_id,
- 'fake-lrouter',
- '10.0.0.1')
- lrouter_port = nvplib.create_router_lport(
- self.fake_cluster, lrouter['uuid'], 'pippo', 'neutron_port_id',
- 'name', True, ['192.168.0.1'], '00:11:22:33:44:55:66')
- result = nvplib.plug_router_port_attachment(
- self.fake_cluster, lrouter['uuid'],
- lrouter_port['uuid'],
- lport['uuid'], 'PatchAttachment')
- self.assertEqual(lport['uuid'],
- result['LogicalPortAttachment']['peer_port_uuid'])
-
- def test_plug_lrouter_port_l3_gw_attachment(self):
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- uuidutils.generate_uuid(),
- 'pippo',
- 'fake-lrouter',
- '10.0.0.1')
- lrouter_port = nvplib.create_router_lport(
- self.fake_cluster, lrouter['uuid'], 'pippo', 'neutron_port_id',
- 'name', True, ['192.168.0.1'], '00:11:22:33:44:55:66')
- result = nvplib.plug_router_port_attachment(
- self.fake_cluster, lrouter['uuid'],
- lrouter_port['uuid'],
- 'gw_att', 'L3GatewayAttachment')
- self.assertEqual(
- 'gw_att',
- result['LogicalPortAttachment']['l3_gateway_service_uuid'])
-
- def test_plug_lrouter_port_l3_gw_attachment_with_vlan(self):
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- uuidutils.generate_uuid(),
- 'pippo',
- 'fake-lrouter',
- '10.0.0.1')
- lrouter_port = nvplib.create_router_lport(
- self.fake_cluster, lrouter['uuid'], 'pippo', 'neutron_port_id',
- 'name', True, ['192.168.0.1'], '00:11:22:33:44:55')
- result = nvplib.plug_router_port_attachment(
- self.fake_cluster, lrouter['uuid'],
- lrouter_port['uuid'],
- 'gw_att', 'L3GatewayAttachment', 123)
- self.assertEqual(
- 'gw_att',
- result['LogicalPortAttachment']['l3_gateway_service_uuid'])
- self.assertEqual(
- '123',
- result['LogicalPortAttachment']['vlan_id'])
-
- def test_plug_lrouter_port_invalid_attachment_type_raises(self):
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- uuidutils.generate_uuid(),
- 'pippo',
- 'fake-lrouter',
- '10.0.0.1')
- lrouter_port = nvplib.create_router_lport(
- self.fake_cluster, lrouter['uuid'], 'pippo', 'neutron_port_id',
- 'name', True, ['192.168.0.1'], '00:11:22:33:44:55')
- self.assertRaises(nvp_exc.NvpInvalidAttachmentType,
- nvplib.plug_router_port_attachment,
- self.fake_cluster, lrouter['uuid'],
- lrouter_port['uuid'], 'gw_att', 'BadType')
-
- def _test_create_router_snat_rule(self, version):
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- uuidutils.generate_uuid(),
- 'pippo',
- 'fake-lrouter',
- '10.0.0.1')
- with mock.patch.object(self.fake_cluster.api_client,
- 'get_nvp_version',
- new=lambda: NvpApiClient.NVPVersion(version)):
- nvplib.create_lrouter_snat_rule(
- self.fake_cluster, lrouter['uuid'],
- '10.0.0.2', '10.0.0.2', order=200,
- match_criteria={'source_ip_addresses': '192.168.0.24'})
- rules = nvplib.query_nat_rules(self.fake_cluster, lrouter['uuid'])
- self.assertEqual(len(rules), 1)
-
- def test_create_router_snat_rule_v3(self):
- self._test_create_router_snat_rule('3.0')
-
- def test_create_router_snat_rule_v2(self):
- self._test_create_router_snat_rule('2.0')
-
- def _test_create_router_dnat_rule(self, version, dest_port=None):
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- uuidutils.generate_uuid(),
- 'pippo',
- 'fake-lrouter',
- '10.0.0.1')
- with mock.patch.object(self.fake_cluster.api_client,
- 'get_nvp_version',
- return_value=NvpApiClient.NVPVersion(version)):
- nvplib.create_lrouter_dnat_rule(
- self.fake_cluster, lrouter['uuid'], '192.168.0.2', order=200,
- dest_port=dest_port,
- match_criteria={'destination_ip_addresses': '10.0.0.3'})
- rules = nvplib.query_nat_rules(self.fake_cluster, lrouter['uuid'])
- self.assertEqual(len(rules), 1)
-
- def test_create_router_dnat_rule_v3(self):
- self._test_create_router_dnat_rule('3.0')
-
- def test_create_router_dnat_rule_v2(self):
- self._test_create_router_dnat_rule('2.0')
-
- def test_create_router_dnat_rule_v2_with_destination_port(self):
- self._test_create_router_dnat_rule('2.0', 8080)
-
- def test_create_router_dnat_rule_v3_with_destination_port(self):
- self._test_create_router_dnat_rule('3.0', 8080)
-
- def test_create_router_snat_rule_invalid_match_keys_raises(self):
- # In this case the version does not make a difference
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- uuidutils.generate_uuid(),
- 'pippo',
- 'fake-lrouter',
- '10.0.0.1')
-
- with mock.patch.object(self.fake_cluster.api_client,
- 'get_nvp_version',
- new=lambda: '2.0'):
- self.assertRaises(AttributeError,
- nvplib.create_lrouter_snat_rule,
- self.fake_cluster, lrouter['uuid'],
- '10.0.0.2', '10.0.0.2', order=200,
- match_criteria={'foo': 'bar'})
-
- def _test_create_router_nosnat_rule(self, version, expected=1):
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- uuidutils.generate_uuid(),
- 'pippo',
- 'fake-lrouter',
- '10.0.0.1')
- with mock.patch.object(self.fake_cluster.api_client,
- 'get_nvp_version',
- new=lambda: NvpApiClient.NVPVersion(version)):
- nvplib.create_lrouter_nosnat_rule(
- self.fake_cluster, lrouter['uuid'],
- order=100,
- match_criteria={'destination_ip_addresses': '192.168.0.0/24'})
- rules = nvplib.query_nat_rules(self.fake_cluster, lrouter['uuid'])
- # NoSNAT rules do not exist in V2
- self.assertEqual(len(rules), expected)
-
- def test_create_router_nosnat_rule_v2(self):
- self._test_create_router_nosnat_rule('2.0', expected=0)
-
- def test_create_router_nosnat_rule_v3(self):
- self._test_create_router_nosnat_rule('3.0')
-
- def _prepare_nat_rules_for_delete_tests(self):
- lrouter = nvplib.create_lrouter(self.fake_cluster,
- uuidutils.generate_uuid(),
- 'pippo',
- 'fake-lrouter',
- '10.0.0.1')
- # v2 or v3 makes no difference for this test
- with mock.patch.object(self.fake_cluster.api_client,
- 'get_nvp_version',
- new=lambda: NvpApiClient.NVPVersion('2.0')):
- nvplib.create_lrouter_snat_rule(
- self.fake_cluster, lrouter['uuid'],
- '10.0.0.2', '10.0.0.2', order=220,
- match_criteria={'source_ip_addresses': '192.168.0.0/24'})
- nvplib.create_lrouter_snat_rule(
- self.fake_cluster, lrouter['uuid'],
- '10.0.0.3', '10.0.0.3', order=200,
- match_criteria={'source_ip_addresses': '192.168.0.2/32'})
- nvplib.create_lrouter_dnat_rule(
- self.fake_cluster, lrouter['uuid'], '192.168.0.2', order=200,
- match_criteria={'destination_ip_addresses': '10.0.0.3'})
- return lrouter
-
- def test_delete_router_nat_rules_by_match_on_destination_ip(self):
- lrouter = self._prepare_nat_rules_for_delete_tests()
- rules = nvplib.query_nat_rules(self.fake_cluster, lrouter['uuid'])
- self.assertEqual(len(rules), 3)
- nvplib.delete_nat_rules_by_match(
- self.fake_cluster, lrouter['uuid'], 'DestinationNatRule', 1, 1,
- destination_ip_addresses='10.0.0.3')
- rules = nvplib.query_nat_rules(self.fake_cluster, lrouter['uuid'])
- self.assertEqual(len(rules), 2)
-
- def test_delete_router_nat_rules_by_match_on_source_ip(self):
- lrouter = self._prepare_nat_rules_for_delete_tests()
- rules = nvplib.query_nat_rules(self.fake_cluster, lrouter['uuid'])
- self.assertEqual(len(rules), 3)
- nvplib.delete_nat_rules_by_match(
- self.fake_cluster, lrouter['uuid'], 'SourceNatRule', 1, 1,
- source_ip_addresses='192.168.0.2/32')
- rules = nvplib.query_nat_rules(self.fake_cluster, lrouter['uuid'])
- self.assertEqual(len(rules), 2)
-
- def test_delete_router_nat_rules_by_match_no_match_expected(self):
- lrouter = self._prepare_nat_rules_for_delete_tests()
- rules = nvplib.query_nat_rules(self.fake_cluster, lrouter['uuid'])
- self.assertEqual(len(rules), 3)
- nvplib.delete_nat_rules_by_match(
- self.fake_cluster, lrouter['uuid'], 'SomeWeirdType', 0)
- rules = nvplib.query_nat_rules(self.fake_cluster, lrouter['uuid'])
- self.assertEqual(len(rules), 3)
- nvplib.delete_nat_rules_by_match(
- self.fake_cluster, lrouter['uuid'], 'DestinationNatRule', 0,
- destination_ip_addresses='99.99.99.99')
- rules = nvplib.query_nat_rules(self.fake_cluster, lrouter['uuid'])
- self.assertEqual(len(rules), 3)
-
- def test_delete_router_nat_rules_by_match_no_match_raises(self):
- lrouter = self._prepare_nat_rules_for_delete_tests()
- rules = nvplib.query_nat_rules(self.fake_cluster, lrouter['uuid'])
- self.assertEqual(len(rules), 3)
- self.assertRaises(
- nvp_exc.NvpNatRuleMismatch,
- nvplib.delete_nat_rules_by_match,
- self.fake_cluster, lrouter['uuid'],
- 'SomeWeirdType', 1, 1)
-
-
class TestNvplibSecurityProfile(NvplibTestCase):
def test_create_and_get_security_profile(self):
cluster=self.fake_cluster)
-class TestNvplibVersioning(base.BaseTestCase):
-
- def test_function_handling_missing_minor(self):
- version = NvpApiClient.NVPVersion('2.0')
- function = nvplib.get_function_by_version('create_lrouter', version)
- self.assertEqual(nvplib.create_implicit_routing_lrouter,
- function)
-
- def test_function_handling_with_both_major_and_minor(self):
- version = NvpApiClient.NVPVersion('3.2')
- function = nvplib.get_function_by_version('create_lrouter', version)
- self.assertEqual(nvplib.create_explicit_routing_lrouter,
- function)
-
- def test_function_handling_with_newer_major(self):
- version = NvpApiClient.NVPVersion('5.2')
- function = nvplib.get_function_by_version('create_lrouter', version)
- self.assertEqual(nvplib.create_explicit_routing_lrouter,
- function)
-
- def test_function_handling_with_obsolete_major(self):
- version = NvpApiClient.NVPVersion('1.2')
- self.assertRaises(NotImplementedError,
- nvplib.get_function_by_version,
- 'create_lrouter', version)
-
- def test_function_handling_with_unknown_version(self):
- self.assertRaises(NvpApiClient.ServiceUnavailable,
- nvplib.get_function_by_version,
- 'create_lrouter', None)
-
-
class NvplibMiscTestCase(base.BaseTestCase):
def test_check_and_truncate_name_with_none(self):
(nvplib.URI_PREFIX, parent_res,
par_id, child_res, res_id, 'doh'))
self.assertEqual(expected, result)
-
-
-def _nicira_method(method_name, module_name='nvplib'):
- return '%s.%s.%s' % ('neutron.plugins.nicira', module_name, method_name)