Policy DHCP relay support using passthrough api

Adding an api to set the dhcp relay service on the nsx realized link port

Change-Id: Ie3db934b636888c1717e7f948ecc60d4be652d05
This commit is contained in:
Adit Sarfaty 2019-01-03 12:37:40 +02:00
parent 6464ba25ea
commit fd3449f74f
4 changed files with 136 additions and 0 deletions

View File

@ -1914,6 +1914,47 @@ class TestPolicyTier1(NsxPolicyLibTestCase):
tier1_id, tenant=TEST_TENANT,
max_attempts=5, sleep=0.1)
def test_get_realized_downlink_port(self):
tier1_id = '111'
segment_id = '222'
lrp_id = '333'
info = {'state': constants.STATE_REALIZED,
'realization_specific_identifier': lrp_id,
'entity_type': 'RealizedLogicalRouterPort'}
dummy_port = {'resource_type': nsx_constants.LROUTERPORT_DOWNLINK,
'id': lrp_id,
'display_name': 'test_%s' % segment_id}
with mock.patch.object(self.resourceApi.policy_api,
"get_realized_entities",
return_value=[info]),\
mock.patch.object(self.resourceApi.nsx_api.logical_router_port,
"get", return_value=dummy_port):
actual_id = self.resourceApi._get_realized_downlink_port(
tier1_id, segment_id)
self.assertEqual(lrp_id, actual_id)
def test_set_dhcp_relay(self):
tier1_id = '111'
segment_id = '222'
lrp_id = '333'
relay_id = '444'
info = {'state': constants.STATE_REALIZED,
'realization_specific_identifier': lrp_id,
'entity_type': 'RealizedLogicalRouterPort'}
dummy_port = {'resource_type': nsx_constants.LROUTERPORT_DOWNLINK,
'id': lrp_id,
'display_name': 'test_%s' % segment_id}
with mock.patch.object(self.resourceApi.policy_api,
"get_realized_entities",
return_value=[info]),\
mock.patch.object(self.resourceApi.nsx_api.logical_router_port,
"get", return_value=dummy_port),\
mock.patch.object(self.resourceApi.nsx_api.logical_router_port,
"update") as nsx_lrp_update:
self.resourceApi.set_dhcp_relay(tier1_id, segment_id, relay_id)
nsx_lrp_update.assert_called_once_with(
lrp_id, relay_service_uuid=relay_id)
class TestPolicyTier1NoPassthrough(TestPolicyTier1):
@ -1931,6 +1972,27 @@ class TestPolicyTier1NoPassthrough(TestPolicyTier1):
tenant=TEST_TENANT)
realization.assert_not_called()
def test_get_realized_downlink_port(self):
# Will not work without passthrough api
tier1_id = '111'
segment_id = '222'
with mock.patch.object(self.resourceApi.policy_api,
"get_realized_entities") as realization:
actual_id = self.resourceApi._get_realized_downlink_port(
tier1_id, segment_id)
self.assertIsNone(actual_id)
realization.assert_not_called()
def test_set_dhcp_relay(self):
# Will not work without passthrough api
tier1_id = '111'
segment_id = '222'
relay_id = '444'
with mock.patch.object(self.resourceApi.policy_api,
"get_realized_entities") as realization:
self.resourceApi.set_dhcp_relay(tier1_id, segment_id, relay_id)
realization.assert_not_called()
class TestPolicyTier1NatRule(NsxPolicyLibTestCase):

View File

@ -494,6 +494,17 @@ class LogicalPortTestCase(BaseTestResource):
"&attachment_id=%s" % (attachment_type, attachment_id),
headers=self.default_headers())
def test_get_logical_port_by_switch(self):
"""Test deleting port."""
ls_id = '111'
mocked_resource = self.get_mocked_resource()
mocked_resource.get_by_logical_switch(ls_id)
test_client.assert_json_call(
'get', mocked_resource,
"https://1.2.3.4/api/v1/logical-ports/?logical_switch_id"
"=%s" % ls_id,
headers=self.default_headers())
def test_clear_port_bindings(self):
fake_port = copy.copy(test_constants.FAKE_PORT)
fake_port['address_bindings'] = ['a', 'b']

View File

@ -828,6 +828,64 @@ class NsxPolicyTier1Api(NsxPolicyResourceBase):
nsx_router_uuid,
transport_zone_id=transport_zone_id)
@check_allowed_passthrough
def _get_realized_downlink_port(
self, tier1_id, segment_id,
tenant=constants.POLICY_INFRA_TENANT,
sleep=None, max_attempts=None):
"""Return the realized ID of a tier1 downlink port of a segment
If not found, wait until it has been realized
"""
if sleep is None:
sleep = 0.5
if max_attempts is None:
max_attempts = self.nsxlib_config.realization_max_attempts
tier1_def = self.entry_def(tier1_id=tier1_id, tenant=tenant)
path = tier1_def.get_resource_full_path()
test_num = 0
while test_num < max_attempts:
# get all the realized resources of the tier1
entities = self.policy_api.get_realized_entities(path)
for e in entities:
# Look fir router ports
if (e['entity_type'] == 'RealizedLogicalRouterPort' and
e['state'] == constants.STATE_REALIZED):
# Get the NSX port to check if its the downlink port
port = self.nsx_api.logical_router_port.get(
e['realization_specific_identifier'])
# compare the segment ID to the port display name as this
# is the way policy sets it
port_type = port.get('resource_type')
if (port_type == nsx_constants.LROUTERPORT_DOWNLINK and
segment_id in port.get('display_name', '')):
return port['id']
eventlet.sleep(sleep)
test_num += 1
err_msg = (_("Could not find realized downlink port for tier1 "
"%(tier1)s and segment %(seg)s after %(attempts)s "
"attempts with %(sleep)s seconds sleep") %
{'tier1': tier1_id,
'seg': segment_id,
'attempts': max_attempts,
'sleep': sleep})
raise exceptions.ManagerError(details=err_msg)
@check_allowed_passthrough
def set_dhcp_relay(self, tier1_id, segment_id, relay_service_uuid,
tenant=constants.POLICY_INFRA_TENANT):
"""Set relay service on the nsx logical router port
Using passthrough api, as the policy api does not support this yet
"""
downlink_port_id = self._get_realized_downlink_port(
tier1_id, segment_id, tenant=tenant)
self.nsx_api.logical_router_port.update(
downlink_port_id, relay_service_uuid=relay_service_uuid)
class NsxPolicyTier0Api(NsxPolicyResourceBase):
"""NSX Tier0 API """

View File

@ -213,6 +213,11 @@ class LogicalPort(utils.NsxLibApiBase):
(attachment_type, attachment_id))
return self.client.get(self.get_path(url_suffix))
def get_by_logical_switch(self, logical_switch_id):
"""Return all logical port of a logical switch"""
url_suffix = '?logical_switch_id=%s' % logical_switch_id
return self.client.get(self.get_path(url_suffix))
class LogicalRouter(core_resources.NsxLibLogicalRouter):
# TODO(asarfaty): keeping this for backwards compatibility.