# Copyright 2015 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. """ NSX-V3 Plugin router module """ import random from neutron.common import exceptions as n_exc from neutron.i18n import _LW from oslo_log import log from vmware_nsx.common import exceptions as nsx_exc from vmware_nsx.nsxlib import v3 as nsxlib LOG = log.getLogger(__name__) # TODO(berlin): Remove this when we merges the edge node auto # placement feature. MIN_EDGE_NODE_NUM = 1 TIER0_ROUTER_LINK_PORT_NAME = "TIER0-RouterLinkPort" TIER1_ROUTER_LINK_PORT_NAME = "TIER1-RouterLinkPort" ROUTER_INTF_PORT_NAME = "Tier1-RouterDownLinkPort" FIP_NAT_PRI = 900 GW_NAT_PRI = 1000 def validate_tier0(tier0_groups_dict, tier0_uuid): if tier0_uuid in tier0_groups_dict: return err_msg = None try: lrouter = nsxlib.get_logical_router(tier0_uuid) except nsx_exc.ResourceNotFound: err_msg = _("Failed to validate tier0 router %s since it is " "not found at the backend") % tier0_uuid else: edge_cluster_uuid = lrouter.get('edge_cluster_id') if not edge_cluster_uuid: err_msg = _("Failed to get edge cluster uuid from tier0 " "router %s at the backend") % lrouter else: edge_cluster = nsxlib.get_edge_cluster(edge_cluster_uuid) member_index_list = [member['member_index'] for member in edge_cluster['members']] if len(member_index_list) < MIN_EDGE_NODE_NUM: err_msg = _("%(act_num)s edge members found in " "edge_cluster %(cluster_id)s, however we " "require at least %(exp_num)s edge nodes " "in edge cluster for HA use.") % { 'act_num': len(member_index_list), 'exp_num': MIN_EDGE_NODE_NUM, 'cluster_id': edge_cluster_uuid} if err_msg: raise n_exc.InvalidInput(error_message=err_msg) else: tier0_groups_dict[tier0_uuid] = { 'edge_cluster_uuid': edge_cluster_uuid, 'member_index_list': member_index_list} def add_router_link_port(tier1_uuid, tier0_uuid, edge_members): # Create Tier0 logical router link port tier0_link_port = nsxlib.create_logical_router_port( tier0_uuid, display_name=TIER0_ROUTER_LINK_PORT_NAME, resource_type=nsxlib.LROUTERPORT_LINK, logical_port_id=None, address_groups=None) linked_logical_port_id = tier0_link_port['id'] edge_cluster_member_index = random.sample( edge_members, MIN_EDGE_NODE_NUM) # Create Tier1 logical router link port nsxlib.create_logical_router_port( tier1_uuid, display_name=TIER1_ROUTER_LINK_PORT_NAME, resource_type=nsxlib.LROUTERPORT_LINK, logical_port_id=linked_logical_port_id, address_groups=None, edge_cluster_member_index=edge_cluster_member_index) def remove_router_link_port(tier1_uuid, tier0_uuid): try: tier1_link_port = nsxlib.get_tier1_logical_router_link_port( tier1_uuid) except nsx_exc.ResourceNotFound: LOG.warning(_LW("Logical router link port for tier1 router: %s " "not found at the backend"), tier1_uuid) return tier1_link_port_id = tier1_link_port['id'] tier0_link_port_id = tier1_link_port['linked_logical_router_port_id'] nsxlib.delete_logical_router_port(tier1_link_port_id) nsxlib.delete_logical_router_port(tier0_link_port_id) def update_advertisement(logical_router_id, advertise_route_nat, advertise_route_connected): return nsxlib.update_logical_router_advertisement( logical_router_id, advertise_nat_routes=advertise_route_nat, advertise_connected_routes=advertise_route_connected) def delete_gw_snat_rule(logical_router_id, gw_ip): return nsxlib.delete_nat_rule_by_values(logical_router_id, translated_network=gw_ip) def add_gw_snat_rule(logical_router_id, gw_ip): return nsxlib.add_nat_rule(logical_router_id, action="SNAT", translated_network=gw_ip, rule_priority=GW_NAT_PRI) def update_router_edge_cluster(nsx_router_id, edge_cluster_uuid): return nsxlib.update_logical_router(nsx_router_id, edge_cluster_id=edge_cluster_uuid) def create_logical_router_intf_port_by_ls_id(logical_router_id, ls_id, logical_switch_port_id, address_groups): try: port = nsxlib.get_logical_router_port_by_ls_id(ls_id) except nsx_exc.ResourceNotFound: return nsxlib.create_logical_router_port(logical_router_id, ROUTER_INTF_PORT_NAME, nsxlib.LROUTERPORT_DOWNLINK, logical_switch_port_id, address_groups) else: return nsxlib.update_logical_router_port( port['id'], subnets=address_groups) def add_fip_nat_rules(logical_router_id, ext_ip, int_ip): nsxlib.add_nat_rule(logical_router_id, action="SNAT", translated_network=ext_ip, source_net=int_ip, rule_priority=FIP_NAT_PRI) nsxlib.add_nat_rule(logical_router_id, action="DNAT", translated_network=int_ip, dest_net=ext_ip, rule_priority=FIP_NAT_PRI) def delete_fip_nat_rules(logical_router_id, ext_ip, int_ip): nsxlib.delete_nat_rule_by_values(logical_router_id, action="SNAT", translated_network=ext_ip, match_source_network=int_ip) nsxlib.delete_nat_rule_by_values(logical_router_id, action="DNAT", translated_network=int_ip, match_destination_network=ext_ip) def add_static_routes(nsx_router_id, route): return nsxlib.add_static_route(nsx_router_id, route['destination'], route['nexthop']) def delete_static_routes(nsx_router_id, route): return nsxlib.delete_static_route_by_values( nsx_router_id, dest_cidr=route['destination'], nexthop=route['nexthop'])