Support transaction for Tier1 NAT rules create & delete

Add PolicyNat def to support Nat rule transactions as all the types
in the transaction hierarchy path should have definitions.

Also add infrastructure for supporting delete under transaction,
and use it for NAT rules deletion

Change-Id: I05116ec8ef06c9fd1dc6fca1f623a3a25c190d3e
This commit is contained in:
asarfaty 2019-11-06 13:30:34 +02:00 committed by Adit Sarfaty
parent bfbe3fa101
commit 897cd37ecc
3 changed files with 141 additions and 3 deletions

View File

@ -21,6 +21,7 @@ import mock
from vmware_nsxlib.tests.unit.v3 import nsxlib_testcase from vmware_nsxlib.tests.unit.v3 import nsxlib_testcase
from vmware_nsxlib.tests.unit.v3.policy import policy_testcase from vmware_nsxlib.tests.unit.v3.policy import policy_testcase
from vmware_nsxlib.v3 import policy from vmware_nsxlib.v3 import policy
from vmware_nsxlib.v3.policy import constants
from vmware_nsxlib.v3.policy import transaction as trans from vmware_nsxlib.v3.policy import transaction as trans
@ -251,6 +252,92 @@ class TestPolicyTransaction(policy_testcase.TestPolicyApi):
self.assert_infra_patch_call(expected_body) self.assert_infra_patch_call(expected_body)
def test_tier1_nat_rules_create(self):
tier1_id = 'tier1-1'
nat_rule_id1 = 'nat1'
nat_rule_id2 = 'nat2'
nat_rule1 = {"action": constants.NAT_ACTION_SNAT,
"display_name": "snat rule",
"id": nat_rule_id1,
"resource_type": "PolicyNatRule"}
nat_rule2 = {"action": constants.NAT_ACTION_DNAT,
"display_name": "dnat rule",
"id": nat_rule_id2,
"resource_type": "PolicyNatRule"}
policy_nat = {"id": "USER",
"resource_type": "PolicyNat",
"children": [
{"PolicyNatRule": nat_rule1,
"resource_type": "ChildPolicyNatRule"},
{"PolicyNatRule": nat_rule2,
"resource_type": "ChildPolicyNatRule"}]}
tier1_dict = {"id": tier1_id,
"resource_type": "Tier1",
"children": [{"PolicyNat": policy_nat,
"resource_type": "ChildPolicyNat"}]}
with trans.NsxPolicyTransaction():
self.policy_lib.tier1_nat_rule.create_or_overwrite(
'snat rule',
tier1_id,
nat_rule_id=nat_rule_id1,
action=constants.NAT_ACTION_SNAT)
self.policy_lib.tier1_nat_rule.create_or_overwrite(
'dnat rule',
tier1_id,
nat_rule_id=nat_rule_id2,
action=constants.NAT_ACTION_DNAT)
expected_body = {"resource_type": "Infra",
"children": [{"Tier1": tier1_dict,
"resource_type": "ChildTier1"}]}
self.assert_infra_patch_call(expected_body)
def test_tier1_nat_rules_delete(self):
tier1_id = 'tier1-1'
nat_rule_id1 = 'nat1'
nat_rule_id2 = 'nat2'
nat_rule1 = {"action": constants.NAT_ACTION_DNAT,
"id": nat_rule_id1,
"resource_type": "PolicyNatRule"}
nat_rule2 = {"action": constants.NAT_ACTION_DNAT,
"id": nat_rule_id2,
"resource_type": "PolicyNatRule"}
policy_nat = {"id": "USER",
"resource_type": "PolicyNat",
"children": [
{"PolicyNatRule": nat_rule1,
"marked_for_delete": True,
"resource_type": "ChildPolicyNatRule"},
{"PolicyNatRule": nat_rule2,
"marked_for_delete": True,
"resource_type": "ChildPolicyNatRule"}]}
tier1_dict = {"id": tier1_id,
"resource_type": "Tier1",
"children": [{"PolicyNat": policy_nat,
"resource_type": "ChildPolicyNat"}]}
with trans.NsxPolicyTransaction():
self.policy_lib.tier1_nat_rule.delete(
tier1_id,
nat_rule_id=nat_rule_id1)
self.policy_lib.tier1_nat_rule.delete(
tier1_id,
nat_rule_id=nat_rule_id2)
expected_body = {"resource_type": "Infra",
"children": [{"Tier1": tier1_dict,
"resource_type": "ChildTier1"}]}
self.assert_infra_patch_call(expected_body)
def test_creating_security_policy_and_dfw_rules(self): def test_creating_security_policy_and_dfw_rules(self):
dfw_rule = {'id': 'rule_id1', 'action': 'ALLOW', dfw_rule = {'id': 'rule_id1', 'action': 'ALLOW',
'display_name': 'rule1', 'description': None, 'display_name': 'rule1', 'description': None,

View File

@ -272,6 +272,9 @@ class ResourceDef(object):
if key not in meta] if key not in meta]
return len(body_args) == 0 return len(body_args) == 0
def set_default_mandatory_vals(self):
pass
class TenantDef(ResourceDef): class TenantDef(ResourceDef):
@property @property
@ -583,6 +586,25 @@ class RouterNatRule(ResourceDef):
'enabled']) 'enabled'])
return body return body
def set_default_mandatory_vals(self):
if not self.has_attr('action'):
self.attrs['action'] = constants.NAT_ACTION_DNAT
class Tier1NatDef(RouterDef):
@property
def path_pattern(self):
return TIER1S_PATH_PATTERN + "%s/nat"
@property
def path_ids(self):
return ('tenant', 'tier1_id')
@staticmethod
def resource_type():
return 'PolicyNat'
class Tier1NatRule(RouterNatRule): class Tier1NatRule(RouterNatRule):
@ -595,7 +617,7 @@ class Tier1NatRule(RouterNatRule):
return ('tenant', 'tier1_id', 'nat_id', 'nat_rule_id') return ('tenant', 'tier1_id', 'nat_id', 'nat_rule_id')
def path_defs(self): def path_defs(self):
return (TenantDef, Tier1Def) return (TenantDef, Tier1Def, Tier1NatDef)
class RouteAdvertisementRule(object): class RouteAdvertisementRule(object):
@ -666,6 +688,21 @@ class Tier0StaticRoute(RouterStaticRoute):
return (TenantDef, Tier0Def) return (TenantDef, Tier0Def)
class Tier0NatDef(RouterDef):
@property
def path_pattern(self):
return TIER0S_PATH_PATTERN + "%s/nat"
@property
def path_ids(self):
return ('tenant', 'tier0_id')
@staticmethod
def resource_type():
return 'PolicyNat'
class Tier0NatRule(RouterNatRule): class Tier0NatRule(RouterNatRule):
@property @property
@ -677,7 +714,7 @@ class Tier0NatRule(RouterNatRule):
return ('tenant', 'tier0_id', 'nat_id', 'nat_rule_id') return ('tenant', 'tier0_id', 'nat_id', 'nat_rule_id')
def path_defs(self): def path_defs(self):
return (TenantDef, Tier0Def) return (TenantDef, Tier0Def, Tier0NatDef)
class Subnet(object): class Subnet(object):

View File

@ -370,6 +370,20 @@ class NsxPolicyResourceBase(object):
_do_create_with_retry() _do_create_with_retry()
def _delete_or_store(self, policy_def):
transaction = trans.NsxPolicyTransaction.get_current()
if transaction:
# Mark this resource is about to be deleted
policy_def.set_delete()
# Set some mandatory default values to avoid failure
# TODO(asarfaty): This can be removed once platform bug is fixed
policy_def.set_default_mandatory_vals()
# Store this def for batch apply for this transaction
transaction.store_def(policy_def, self.policy_api.client)
else:
# No transaction - apply now
self.policy_api.delete(policy_def)
class NsxPolicyDomainApi(NsxPolicyResourceBase): class NsxPolicyDomainApi(NsxPolicyResourceBase):
"""NSX Policy Domain.""" """NSX Policy Domain."""
@ -1645,7 +1659,7 @@ class NsxPolicyTier1NatRuleApi(NsxPolicyResourceBase):
tenant=constants.POLICY_INFRA_TENANT): tenant=constants.POLICY_INFRA_TENANT):
nat_rule_def = self.entry_def(tier1_id=tier1_id, nat_id=nat_id, nat_rule_def = self.entry_def(tier1_id=tier1_id, nat_id=nat_id,
nat_rule_id=nat_rule_id, tenant=tenant) nat_rule_id=nat_rule_id, tenant=tenant)
self.policy_api.delete(nat_rule_def) self._delete_or_store(nat_rule_def)
def get(self, tier1_id, nat_rule_id, nat_id=DEFAULT_NAT_ID, def get(self, tier1_id, nat_rule_id, nat_id=DEFAULT_NAT_ID,
tenant=constants.POLICY_INFRA_TENANT): tenant=constants.POLICY_INFRA_TENANT):