nsx v3 router refactor

Change-Id: I8ffb28b8656d39161da438b5a174e6d25c35f1e2
This commit is contained in:
Shih-Hao Li 2015-10-13 14:22:34 -07:00
parent 0e5c1f4ac6
commit f04849f031
8 changed files with 414 additions and 280 deletions

View File

@ -39,6 +39,16 @@ ROUTER_TYPE_TIER1 = "TIER1"
ROUTER_TYPES = [ROUTER_TYPE_TIER0, ROUTER_TYPE_TIER1]
LROUTERPORT_UPLINK = "LogicalRouterUplinkPort"
LROUTERPORT_DOWNLINK = "LogicalRouterDownLinkPort"
LROUTERPORT_LINKONTIER0 = "LogicalRouterLinkPortOnTIER0"
LROUTERPORT_LINKONTIER1 = "LogicalRouterLinkPortOnTIER1"
LROUTER_TYPES = [LROUTERPORT_UPLINK,
LROUTERPORT_DOWNLINK,
LROUTERPORT_LINKONTIER0,
LROUTERPORT_LINKONTIER1]
# L2 agent vif type
VIF_TYPE_DVS = 'dvs'

View File

@ -25,18 +25,6 @@ from vmware_nsx.nsxlib.v3 import client
LOG = log.getLogger(__name__)
# TODO(berlin): move them to nsx_constants file
# Router logical port types
LROUTERPORT_UPLINK = "LogicalRouterUplinkPort"
LROUTERPORT_DOWNLINK = "LogicalRouterDownLinkPort"
LROUTERPORT_LINKONTIER0 = "LogicalRouterLinkPortOnTIER0"
LROUTERPORT_LINKONTIER1 = "LogicalRouterLinkPortOnTIER1"
LROUTER_TYPES = [LROUTERPORT_UPLINK,
LROUTERPORT_DOWNLINK,
LROUTERPORT_LINKONTIER0,
LROUTERPORT_LINKONTIER1]
def get_edge_cluster(edge_cluster_uuid):
resource = "edge-clusters/%s" % edge_cluster_uuid
@ -129,122 +117,6 @@ def update_logical_switch(lswitch_id, name=None, admin_state=None):
return client.update_resource(resource, lswitch)
def create_logical_router(display_name, tags,
edge_cluster_uuid=None, tier_0=False):
# TODO(salv-orlando): If possible do not manage edge clusters in the main
# plugin logic.
router_type = (nsx_constants.ROUTER_TYPE_TIER0 if tier_0 else
nsx_constants.ROUTER_TYPE_TIER1)
resource = 'logical-routers'
body = {'display_name': display_name,
'router_type': router_type,
'tags': tags}
if edge_cluster_uuid:
body['edge_cluster_id'] = edge_cluster_uuid
return client.create_resource(resource, body)
def get_logical_router(lrouter_id):
resource = 'logical-routers/%s' % lrouter_id
return client.get_resource(resource)
def update_logical_router(lrouter_id, **kwargs):
resource = 'logical-routers/%s' % lrouter_id
return update_resource_with_retry(resource, kwargs)
def delete_logical_router(lrouter_id):
# TODO(berlin): need to verify whether cascade prefix is valid to delete
# router link port and its relative nat rules
resource = 'logical-routers/%s/' % lrouter_id
# TODO(salv-orlando): Must handle connection exceptions
return client.delete_resource(resource)
def get_logical_router_port_by_ls_id(logical_switch_id):
resource = 'logical-router-ports?logical_switch_id=%s' % logical_switch_id
router_ports = client.get_resource(resource)
if int(router_ports['result_count']) >= 2:
raise nsx_exc.NsxPluginException(
err_msg=_("Can't support more than one logical router ports "
"on same logical switch %s ") % logical_switch_id)
elif int(router_ports['result_count']) == 1:
return router_ports['results'][0]
else:
err_msg = (_("Logical router link port not found on logical "
"switch %s") % logical_switch_id)
raise nsx_exc.ResourceNotFound(manager=client._get_manager_ip(),
operation=err_msg)
def create_logical_router_port(logical_router_id,
display_name,
resource_type,
logical_port_id,
address_groups,
edge_cluster_member_index=None):
resource = 'logical-router-ports'
body = {'display_name': display_name,
'resource_type': resource_type,
'logical_router_id': logical_router_id}
if address_groups:
body['subnets'] = address_groups
if resource_type in [LROUTERPORT_UPLINK,
LROUTERPORT_DOWNLINK]:
body['linked_logical_switch_port_id'] = {
'target_id': logical_port_id}
elif resource_type == LROUTERPORT_LINKONTIER1:
body['linked_logical_router_port_id'] = {
'target_id': logical_port_id}
elif logical_port_id:
body['linked_logical_router_port_id'] = logical_port_id
if edge_cluster_member_index:
body['edge_cluster_member_index'] = edge_cluster_member_index
return client.create_resource(resource, body)
def update_logical_router_port_by_ls_id(logical_router_id, ls_id,
**payload):
port = get_logical_router_port_by_ls_id(ls_id)
return update_logical_router_port(port['id'], **payload)
def update_logical_router_port(logical_port_id, **kwargs):
resource = 'logical-router-ports/%s?detach=true' % logical_port_id
return update_resource_with_retry(resource, kwargs)
def delete_logical_router_port_by_ls_id(ls_id):
port = get_logical_router_port_by_ls_id(ls_id)
delete_logical_router_port(port['id'])
def delete_logical_router_port(logical_port_id):
resource = 'logical-router-ports/%s?detach=true' % logical_port_id
client.delete_resource(resource)
def get_logical_router_ports_by_router_id(logical_router_id):
resource = 'logical-router-ports'
logical_router_ports = client.get_resource(
resource, logical_router_id=logical_router_id)
return logical_router_ports['results']
def get_tier1_logical_router_link_port(logical_router_id):
logical_router_ports = get_logical_router_ports_by_router_id(
logical_router_id)
for port in logical_router_ports:
if port['resource_type'] == LROUTERPORT_LINKONTIER1:
return port
raise nsx_exc.ResourceNotFound(
manager=client._get_manager_ip(),
operation="get router link port")
def add_nat_rule(logical_router_id, action, translated_network,
source_net=None, dest_net=None,
enabled=True, rule_priority=None):

View File

@ -21,6 +21,7 @@ from oslo_config import cfg
from vmware_nsx.common import exceptions as nsx_exc
from vmware_nsx.common import nsx_constants
from vmware_nsx.common import utils
from vmware_nsx.nsxlib.v3 import client
SwitchingProfileTypeId = collections.namedtuple(
@ -238,3 +239,126 @@ class LogicalPort(AbstractRESTResource):
# re-fetch, patch the response and send it again with the
# new revision_id
return self._client.update(lport_id, body=lport)
class LogicalRouter(AbstractRESTResource):
@property
def uri_segment(self):
return 'logical-routers'
def create(self, display_name, tags, edge_cluster_uuid=None, tier_0=False):
# TODO(salv-orlando): If possible do not manage edge clusters
# in the main plugin logic.
router_type = (nsx_constants.ROUTER_TYPE_TIER0 if tier_0 else
nsx_constants.ROUTER_TYPE_TIER1)
body = {'display_name': display_name,
'router_type': router_type,
'tags': tags}
if edge_cluster_uuid:
body['edge_cluster_id'] = edge_cluster_uuid
return self._client.create(body=body)
def delete(self, lrouter_id):
return self._client.url_delete(lrouter_id)
@utils.retry_upon_exception_nsxv3(
nsx_exc.StaleRevision,
max_attempts=cfg.CONF.nsx_v3.retries)
def update(self, lrouter_id, *args, **kwargs):
lrouter = self.get(lrouter_id)
for k in kwargs:
lrouter[k] = kwargs[k]
# If revision_id of the payload that we send is older than what NSX has
# then we will get a 412: Precondition Failed. In that case we need to
# re-fetch, patch the response and send it again with the
# new revision_id
return self._client.update(lrouter_id, body=lrouter)
class LogicalRouterPort(AbstractRESTResource):
@property
def uri_segment(self):
return 'logical-router-ports'
def create(self, logical_router_id,
display_name,
resource_type,
logical_port_id,
address_groups,
edge_cluster_member_index=None):
body = {'display_name': display_name,
'resource_type': resource_type,
'logical_router_id': logical_router_id}
if address_groups:
body['subnets'] = address_groups
if resource_type in [nsx_constants.LROUTERPORT_UPLINK,
nsx_constants.LROUTERPORT_DOWNLINK]:
body['linked_logical_switch_port_id'] = {
'target_id': logical_port_id}
elif resource_type == nsx_constants.LROUTERPORT_LINKONTIER1:
body['linked_logical_router_port_id'] = {
'target_id': logical_port_id}
elif logical_port_id:
body['linked_logical_router_port_id'] = logical_port_id
if edge_cluster_member_index:
body['edge_cluster_member_index'] = edge_cluster_member_index
return self._client.create(body)
@utils.retry_upon_exception_nsxv3(
nsx_exc.StaleRevision,
max_attempts=cfg.CONF.nsx_v3.retries)
def update(self, logical_port_id, **kwargs):
resource = '%s?detach=true' % logical_port_id
logical_router_port = self.get(logical_port_id)
for k in kwargs:
logical_router_port[k] = kwargs[k]
# If revision_id of the payload that we send is older than what NSX has
# then we will get a 412: Precondition Failed. In that case we need to
# re-fetch, patch the response and send it again with the
# new revision_id
return self._client.update(resource, body=logical_router_port)
def delete(self, logical_port_id):
return self._client.url_delete(logical_port_id)
def get_by_lswitch_id(self, logical_switch_id):
resource = ('logical-router-ports?logical_switch_id=%s' %
logical_switch_id)
router_ports = self._client.url_get(resource)
if int(router_ports['result_count']) >= 2:
raise nsx_exc.NsxPluginException(
err_msg=_("Can't support more than one logical router ports "
"on same logical switch %s ") % logical_switch_id)
elif int(router_ports['result_count']) == 1:
return router_ports['results'][0]
else:
err_msg = (_("Logical router link port not found on logical "
"switch %s") % logical_switch_id)
raise nsx_exc.ResourceNotFound(manager=client._get_manager_ip(),
operation=err_msg)
def update_by_lswitch_id(self, logical_router_id, ls_id, **payload):
port = self.get_by_lswitch_id(ls_id)
return self.update(port['id'], **payload)
def delete_by_lswitch_id(self, ls_id):
port = self.get_by_lswitch_id(ls_id)
self.delete(port['id'])
def get_by_router_id(self, logical_router_id):
resource = ('logical-router-ports/?logical_router_id=%s' %
logical_router_id)
logical_router_ports = self._client.url_get(resource)
return logical_router_ports['results']
def get_tier1_link_port(self, logical_router_id):
logical_router_ports = self.get_by_router_id(logical_router_id)
for port in logical_router_ports:
if port['resource_type'] == nsx_constants.LROUTERPORT_LINKONTIER1:
return port
raise nsx_exc.ResourceNotFound(
manager=client._get_manager_ip(),
operation="get router link port")

View File

@ -24,6 +24,7 @@ from neutron.i18n import _LW
from oslo_log import log
from vmware_nsx.common import exceptions as nsx_exc
from vmware_nsx.common import nsx_constants
from vmware_nsx.nsxlib import v3 as nsxlib
LOG = log.getLogger(__name__)
@ -40,144 +41,140 @@ 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
class RouterLib(object):
def __init__(self, router_client, router_port_client):
self._router_client = router_client
self._router_port_client = router_port_client
def validate_tier0(self, tier0_groups_dict, tier0_uuid):
if tier0_uuid in tier0_groups_dict:
return
err_msg = None
try:
resource = 'logical-routers/%s' % tier0_uuid
lrouter = self._router_client.get(resource)
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 = 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}
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(self, tier1_uuid, tier0_uuid, edge_members):
# Create Tier0 logical router link port
tier0_link_port = self._router_port_client.create(
tier0_uuid, display_name=TIER0_ROUTER_LINK_PORT_NAME,
resource_type=nsx_constants.LROUTERPORT_LINKONTIER0,
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
self._router_port_client.create(
tier1_uuid, display_name=TIER1_ROUTER_LINK_PORT_NAME,
resource_type=nsx_constants.LROUTERPORT_LINKONTIER1,
logical_port_id=linked_logical_port_id,
address_groups=None,
edge_cluster_member_index=edge_cluster_member_index)
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_LINKONTIER0,
logical_port_id=None,
address_groups=None)
linked_logical_port_id = tier0_link_port['id']
def remove_router_link_port(self, tier1_uuid, tier0_uuid):
try:
tier1_link_port = (
self._router_port_client.get_tier1_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'].get('target_id'))
self._router_port_client.delete(tier1_link_port_id)
self._router_port_client.delete(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_LINKONTIER1,
logical_port_id=linked_logical_port_id,
address_groups=None,
edge_cluster_member_index=edge_cluster_member_index)
def update_advertisement(self, 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_nsx_connected_routes=advertise_route_connected)
def delete_gw_snat_rule(self, logical_router_id, gw_ip):
return nsxlib.delete_nat_rule_by_values(logical_router_id,
translated_network=gw_ip)
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'].get('target_id'))
nsxlib.delete_logical_router_port(tier1_link_port_id)
nsxlib.delete_logical_router_port(tier0_link_port_id)
def add_gw_snat_rule(self, 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(self, nsx_router_id, edge_cluster_uuid):
return self._router_client.update(nsx_router_id,
edge_cluster_id=edge_cluster_uuid)
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_nsx_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,
def create_logical_router_intf_port_by_ls_id(self, logical_router_id,
ls_id,
logical_switch_port_id,
address_groups)
else:
return nsxlib.update_logical_router_port(
port['id'], subnets=address_groups)
address_groups):
try:
port = self._router_port_client.get_by_lswitch_id(ls_id)
except nsx_exc.ResourceNotFound:
return self._router_port_client.create(
logical_router_id,
ROUTER_INTF_PORT_NAME,
nsx_constants.LROUTERPORT_DOWNLINK,
logical_switch_port_id,
address_groups)
else:
return self._router_port_client.update(
port['id'], subnets=address_groups)
def add_fip_nat_rules(self, 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 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(self, 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(self, nsx_router_id, route):
return nsxlib.add_static_route(nsx_router_id, route['destination'],
route['nexthop'])
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'])
def delete_static_routes(self, nsx_router_id, route):
return nsxlib.delete_static_route_by_values(
nsx_router_id, dest_cidr=route['destination'],
nexthop=route['nexthop'])

View File

@ -66,7 +66,7 @@ from vmware_nsx.nsxlib import v3 as nsxlib
from vmware_nsx.nsxlib.v3 import client as nsx_client
from vmware_nsx.nsxlib.v3 import dfw_api as firewall
from vmware_nsx.nsxlib.v3 import resources as nsx_resources
from vmware_nsx.nsxlib.v3 import router as routerlib
from vmware_nsx.nsxlib.v3 import router
from vmware_nsx.nsxlib.v3 import security
@ -117,6 +117,11 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin,
self._port_client = nsx_resources.LogicalPort(self._nsx_client)
self.nsgroup_container, self.default_section = (
security.init_nsgroup_container_and_default_section_rules())
self._router_client = nsx_resources.LogicalRouter(self._nsx_client)
self._router_port_client = nsx_resources.LogicalRouterPort(
self._nsx_client)
self._routerlib = router.RouterLib(self._router_client,
self._router_port_client)
LOG.debug("Initializing NSX v3 port spoofguard switching profile")
self._switching_profiles = nsx_resources.SwitchingProfile(
@ -243,7 +248,7 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin,
return net_type, physical_net, vlan_id
def _get_edge_cluster_and_members(self, tier0_uuid):
routerlib.validate_tier0(self.tier0_groups_dict, tier0_uuid)
self._routerlib.validate_tier0(self.tier0_groups_dict, tier0_uuid)
tier0_info = self.tier0_groups_dict[tier0_uuid]
return (tier0_info['edge_cluster_uuid'],
tier0_info['member_index_list'])
@ -255,7 +260,7 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin,
else:
tier0_uuid = net_data[pnet.PHYSICAL_NETWORK]
is_provider_net = True
routerlib.validate_tier0(self.tier0_groups_dict, tier0_uuid)
self._routerlib.validate_tier0(self.tier0_groups_dict, tier0_uuid)
return (is_provider_net, utils.NetworkTypes.L3_EXT, tier0_uuid, 0)
def _create_network_at_the_backend(self, context, net_data):
@ -858,25 +863,26 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin,
# TODO(berlin): revocate bgp announce on org tier0 router
pass
if remove_snat_rules:
routerlib.delete_gw_snat_rule(nsx_router_id, orgaddr)
self._routerlib.delete_gw_snat_rule(nsx_router_id, orgaddr)
if remove_router_link_port:
routerlib.remove_router_link_port(nsx_router_id, org_tier0_uuid)
self._routerlib.remove_router_link_port(
nsx_router_id, org_tier0_uuid)
if add_router_link_port:
# First update edge cluster info for router
edge_cluster_uuid, members = self._get_edge_cluster_and_members(
new_tier0_uuid)
routerlib.update_router_edge_cluster(
self._routerlib.update_router_edge_cluster(
nsx_router_id, edge_cluster_uuid)
routerlib.add_router_link_port(nsx_router_id, new_tier0_uuid,
self._routerlib.add_router_link_port(nsx_router_id, new_tier0_uuid,
members)
if add_snat_rules:
routerlib.add_gw_snat_rule(nsx_router_id, newaddr)
self._routerlib.add_gw_snat_rule(nsx_router_id, newaddr)
if bgp_announce:
# TODO(berlin): bgp announce on new tier0 router
pass
if remove_snat_rules or add_snat_rules:
routerlib.update_advertisement(nsx_router_id,
self._routerlib.update_advertisement(nsx_router_id,
advertise_route_nat_flag,
advertise_route_connected_flag)
@ -884,7 +890,7 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin,
# TODO(berlin): admin_state_up support
gw_info = self._extract_external_gw(context, router, is_extract=True)
tags = utils.build_v3_tags_payload(router['router'])
result = nsxlib.create_logical_router(
result = self._router_client.create(
display_name=router['router'].get('name'),
tags=tags)
@ -922,7 +928,7 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin,
# It is safe to do now as db-level checks for resource deletion were
# passed (and indeed the resource was removed from the Neutron DB
try:
nsxlib.delete_logical_router(nsx_router_id)
self._router_client.delete(nsx_router_id)
except nsx_exc.ResourceNotFound:
# If the logical router was not found on the backend do not worry
# about it. The conditions has already been logged, so there is no
@ -981,9 +987,9 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin,
nsx_router_id = nsx_db.get_nsx_router_id(context.session,
router_id)
for route in routes_removed:
routerlib.delete_static_routes(nsx_router_id, route)
self._routerlib.delete_static_routes(nsx_router_id, route)
for route in routes_added:
routerlib.add_static_routes(nsx_router_id, route)
self._routerlib.add_static_routes(nsx_router_id, route)
return super(NsxV3Plugin, self).update_router(
context, router_id, router)
except nsx_exc.ResourceNotFound:
@ -1000,9 +1006,10 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin,
router_db['status'] = const.NET_STATUS_ERROR
if nsx_router_id:
for route in routes_added:
routerlib.delete_static_routes(nsx_router_id, route)
self._routerlib.delete_static_routes(
nsx_router_id, route)
for route in routes_removed:
routerlib.add_static_routes(nsx_router_id, route)
self._routerlib.add_static_routes(nsx_router_id, route)
router_db['status'] = curr_status
def _get_router_interface_ports_by_network(
@ -1061,7 +1068,7 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin,
router_id)
_ports, address_groups = self._get_ports_and_address_groups(
context, router_id, network_id)
routerlib.create_logical_router_intf_port_by_ls_id(
self._routerlib.create_logical_router_intf_port_by_ls_id(
logical_router_id=nsx_router_id,
ls_id=nsx_net_id,
logical_switch_port_id=nsx_port_id,
@ -1131,12 +1138,12 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin,
new_using_port_id = ports[0]['id']
_net_id, new_nsx_port_id = nsx_db.get_nsx_switch_and_port_id(
context.session, new_using_port_id)
nsxlib.update_logical_router_port_by_ls_id(
self._router_port_client.update_by_lswitch_id(
nsx_router_id, nsx_net_id,
linked_logical_switch_port_id=new_nsx_port_id,
subnets=address_groups)
else:
nsxlib.delete_logical_router_port_by_ls_id(nsx_net_id)
self._router_port_client.delete_by_lswitch_id(nsx_net_id)
except nsx_exc.ResourceNotFound:
LOG.error(_LE("router port on router %(router_id)s for net "
"%(net_id)s not found at the backend"),
@ -1154,7 +1161,7 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin,
try:
nsx_router_id = nsx_db.get_nsx_router_id(context.session,
router_id)
routerlib.add_fip_nat_rules(
self._routerlib.add_fip_nat_rules(
nsx_router_id, new_fip['floating_ip_address'],
new_fip['fixed_ip_address'])
except nsx_exc.ManagerError:
@ -1169,7 +1176,7 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin,
try:
nsx_router_id = nsx_db.get_nsx_router_id(context.session,
router_id)
routerlib.delete_fip_nat_rules(
self._routerlib.delete_fip_nat_rules(
nsx_router_id, fip['floating_ip_address'],
fip['fixed_ip_address'])
except nsx_exc.ResourceNotFound:
@ -1194,7 +1201,7 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin,
try:
old_nsx_router_id = nsx_db.get_nsx_router_id(
context.session, old_fip['router_id'])
routerlib.delete_fip_nat_rules(
self._routerlib.delete_fip_nat_rules(
old_nsx_router_id, old_fip['floating_ip_address'],
old_fip['fixed_ip_address'])
except nsx_exc.ResourceNotFound:
@ -1213,7 +1220,7 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin,
if router_id:
nsx_router_id = nsx_db.get_nsx_router_id(context.session,
router_id)
routerlib.add_fip_nat_rules(
self._routerlib.add_fip_nat_rules(
nsx_router_id, new_fip['floating_ip_address'],
new_fip['fixed_ip_address'])
except nsx_exc.ManagerError:
@ -1234,7 +1241,7 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin,
try:
nsx_router_id = nsx_db.get_nsx_router_id(context.session,
fip_db.router_id)
routerlib.delete_fip_nat_rules(
self._routerlib.delete_fip_nat_rules(
nsx_router_id, fip_db.floating_ip_address,
fip_db.fixed_ip_address)
except nsx_exc.ResourceNotFound:

View File

@ -97,3 +97,20 @@ FAKE_QOS_PROFILE = {
"_create_user": "admin",
"_revision": 0
}
FAKE_ROUTER_UUID = uuidutils.generate_uuid()
FAKE_ROUTER = {
"resource_type": "LogicalRouter",
"revision": 0,
"id": FAKE_ROUTER_UUID,
"display_name": FAKE_NAME
}
FAKE_ROUTER_PORT_UUID = uuidutils.generate_uuid()
FAKE_ROUTER_PORT = {
"resource_type": "LogicalRouterLinkPort",
"revision": 0,
"id": FAKE_ROUTER_PORT_UUID,
"display_name": FAKE_NAME,
"logical_router_id": FAKE_ROUTER_UUID
}

View File

@ -67,7 +67,7 @@ class NsxV3PluginTestCaseMixin(test_plugin.NeutronDbPluginV2TestCase,
self._patchers.append(mocked)
mock_client_module(nsx_plugin.security.firewall)
mock_client_module(nsx_plugin.routerlib.nsxlib)
mock_client_module(nsx_plugin.router.nsxlib)
mock_client_module(nsx_plugin)
super(NsxV3PluginTestCaseMixin, self).setUp(plugin=plugin,

View File

@ -241,3 +241,110 @@ class LogicalPortTestCase(nsxlib_testcase.NsxClientTestCase):
None,
client.JSONRESTClient._DEFAULT_HEADERS,
nsxlib_testcase.NSX_CERT)
class LogicalRouterTestCase(nsxlib_testcase.NsxClientTestCase):
def test_create_logical_router(self):
"""
Test creating a router returns the correct response and 201 status
"""
fake_router = test_constants_v3.FAKE_ROUTER.copy()
api = resources.LogicalRouter(client.NSX3Client())
with self.mocked_resource(api) as mocked:
mocked.get('post').return_value = mocks.MockRequestsResponse(
201, jsonutils.dumps(fake_router))
tier0_router = True
result = api.create(fake_router['display_name'], None, None,
tier0_router)
data = {
'display_name': fake_router['display_name'],
'router_type': 'TIER0' if tier0_router else 'TIER1',
'tags': None
}
self.assertEqual(fake_router, result)
test_client.assert_session_call(
mocked.get('post'),
'https://1.2.3.4/api/v1/logical-routers',
False,
jsonutils.dumps(data),
client.JSONRESTClient._DEFAULT_HEADERS,
nsxlib_testcase.NSX_CERT)
def test_delete_logical_router(self):
"""
Test deleting router
"""
api = resources.LogicalRouter(client.NSX3Client())
with self.mocked_resource(api) as mocked:
mocked.get('delete').return_value = mocks.MockRequestsResponse(
200, None)
uuid = test_constants_v3.FAKE_ROUTER['id']
result = api.delete(uuid)
self.assertIsNone(result.content)
test_client.assert_session_call(
mocked.get('delete'),
'https://1.2.3.4/api/v1/logical-routers/%s' % uuid,
False,
None,
client.JSONRESTClient._DEFAULT_HEADERS,
nsxlib_testcase.NSX_CERT)
class LogicalRouterPortTestCase(nsxlib_testcase.NsxClientTestCase):
def test_create_logical_router_port(self):
"""
Test creating a router returns the correct response and 201 status
"""
fake_router_port = test_constants_v3.FAKE_ROUTER_PORT.copy()
api = resources.LogicalRouterPort(client.NSX3Client())
with self.mocked_resource(api) as mocked:
mocked.get('post').return_value = mocks.MockRequestsResponse(
201, jsonutils.dumps(fake_router_port))
result = api.create(fake_router_port['logical_router_id'],
fake_router_port['display_name'],
fake_router_port['resource_type'],
None, None, None)
data = {
'display_name': fake_router_port['display_name'],
'logical_router_id': fake_router_port['logical_router_id'],
'resource_type': fake_router_port['resource_type']
}
self.assertEqual(fake_router_port, result)
test_client.assert_session_call(
mocked.get('post'),
'https://1.2.3.4/api/v1/logical-router-ports',
False,
jsonutils.dumps(data),
client.JSONRESTClient._DEFAULT_HEADERS,
nsxlib_testcase.NSX_CERT)
def test_delete_logical_router_port(self):
"""
Test deleting router port
"""
api = resources.LogicalRouterPort(client.NSX3Client())
with self.mocked_resource(api) as mocked:
mocked.get('delete').return_value = mocks.MockRequestsResponse(
200, None)
uuid = test_constants_v3.FAKE_ROUTER_PORT['id']
result = api.delete(uuid)
self.assertIsNone(result.content)
test_client.assert_session_call(
mocked.get('delete'),
'https://1.2.3.4/api/v1/logical-router-ports/%s' % uuid,
False,
None,
client.JSONRESTClient._DEFAULT_HEADERS,
nsxlib_testcase.NSX_CERT)