nsx v3 router refactor
Change-Id: I8ffb28b8656d39161da438b5a174e6d25c35f1e2
This commit is contained in:
parent
0e5c1f4ac6
commit
f04849f031
@ -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'
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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")
|
||||
|
@ -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'])
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user