Enhance support for policy transaction
Add support for non first level objects, such as segment ports Change-Id: I55f7f7f1921f7ff9c57adb93355943ffc7a9c542
This commit is contained in:
@@ -158,3 +158,91 @@ class TestPolicyTransaction(policy_testcase.TestPolicyApi):
|
||||
'IpAddressPool': pool}]}
|
||||
|
||||
self.assert_infra_patch_call(expected_body)
|
||||
|
||||
def test_groups_only(self):
|
||||
|
||||
g1 = {'resource_type': 'Group', 'id': 'group1',
|
||||
'display_name': 'g1',
|
||||
'description': 'first group'}
|
||||
g2 = {'resource_type': 'Group', 'id': 'group2',
|
||||
'description': 'second group',
|
||||
'display_name': 'g2'}
|
||||
d1 = {'resource_type': 'Domain', 'id': 'domain1'}
|
||||
|
||||
d2 = {'resource_type': 'Domain', 'id': 'domain2'}
|
||||
|
||||
with trans.NsxPolicyTransaction():
|
||||
|
||||
for d in (d1, d2):
|
||||
d['children'] = []
|
||||
|
||||
for g in (g1, g2):
|
||||
self.policy_lib.group.create_or_overwrite(
|
||||
g['display_name'],
|
||||
d['id'],
|
||||
g['id'],
|
||||
g['description'])
|
||||
|
||||
d['children'].append({'resource_type': 'ChildGroup',
|
||||
'Group': g})
|
||||
|
||||
expected_body = {'resource_type': 'Infra',
|
||||
'children': [{'resource_type': 'ChildDomain',
|
||||
'Domain': d1},
|
||||
{'resource_type': 'ChildDomain',
|
||||
'Domain': d2}]}
|
||||
|
||||
self.assert_infra_patch_call(expected_body)
|
||||
|
||||
def test_segment_ports(self):
|
||||
|
||||
port1 = {'id': 'port_on_seg1',
|
||||
'resource_type': 'SegmentPort',
|
||||
'display_name': 'port_on_seg1',
|
||||
'attachment': {'type': 'VIF',
|
||||
'app_id': 'app1',
|
||||
'traffic_tag': 5}
|
||||
}
|
||||
|
||||
port2 = {'id': 'port1_on_seg2',
|
||||
'resource_type': 'SegmentPort',
|
||||
'display_name': 'port_on_seg2',
|
||||
'attachment': {'type': 'CHILD',
|
||||
'app_id': 'app2',
|
||||
'traffic_tag': None}
|
||||
}
|
||||
|
||||
seg1 = {'id': 'seg1',
|
||||
'resource_type': 'Segment',
|
||||
'children': [{'resource_type': 'ChildSegmentPort',
|
||||
'SegmentPort': port1}]}
|
||||
seg2 = {'id': 'seg2',
|
||||
'resource_type': 'Segment',
|
||||
'children': [{'resource_type': 'ChildSegmentPort',
|
||||
'SegmentPort': port2}]}
|
||||
|
||||
with trans.NsxPolicyTransaction():
|
||||
|
||||
self.policy_lib.segment_port.create_or_overwrite(
|
||||
port1['display_name'],
|
||||
seg1['id'],
|
||||
port1['id'],
|
||||
attachment_type=port1['attachment']['type'],
|
||||
app_id=port1['attachment']['app_id'],
|
||||
traffic_tag=port1['attachment']['traffic_tag'])
|
||||
|
||||
self.policy_lib.segment_port.create_or_overwrite(
|
||||
port2['display_name'],
|
||||
seg2['id'],
|
||||
port2['id'],
|
||||
attachment_type=port2['attachment']['type'],
|
||||
app_id=port2['attachment']['app_id'],
|
||||
traffic_tag=port2['attachment']['traffic_tag'])
|
||||
|
||||
expected_body = {'resource_type': 'Infra',
|
||||
'children': [{'resource_type': 'ChildSegment',
|
||||
'Segment': seg1},
|
||||
{'resource_type': 'ChildSegment',
|
||||
'Segment': seg2}]}
|
||||
|
||||
self.assert_infra_patch_call(expected_body)
|
||||
|
||||
@@ -96,15 +96,28 @@ class NsxPolicyTransaction(object):
|
||||
|
||||
self.defs = sorted_defs
|
||||
|
||||
def _build_wrapper_dict(self, resource_class, node):
|
||||
return {'resource_type': 'Child%s' % resource_class,
|
||||
resource_class: node}
|
||||
|
||||
def _find_parent_in_dict(self, d, resource_def, level=1):
|
||||
|
||||
if len(resource_def.path_defs()) <= level:
|
||||
return
|
||||
|
||||
parent_type = resource_def.path_defs()[level]
|
||||
|
||||
is_leaf = (level + 1 == len(resource_def.path_defs()))
|
||||
resource_type = parent_type.resource_type()
|
||||
resource_class = parent_type.resource_class()
|
||||
parent_id = resource_def.get_attr(resource_def.path_ids[level])
|
||||
|
||||
def create_missing_node():
|
||||
node = {'resource_type': resource_type,
|
||||
'id': parent_id,
|
||||
'children': []}
|
||||
return self._build_wrapper_dict(resource_class, node), node
|
||||
|
||||
# iterate over all objects in d, and look for resource type
|
||||
for child in d:
|
||||
if resource_type in child and child[resource_type]:
|
||||
@@ -113,17 +126,20 @@ class NsxPolicyTransaction(object):
|
||||
if parent['id'] == parent_id:
|
||||
if is_leaf:
|
||||
return parent
|
||||
if 'children' in parent:
|
||||
if 'children' not in parent:
|
||||
parent['children'] = []
|
||||
|
||||
return self._find_parent_in_dict(
|
||||
parent['children'], resource_def, level + 1)
|
||||
|
||||
# Parent not found - for now, raise an exception
|
||||
# Support for this will come later
|
||||
# TODO(annak): remove this when missing parent body is
|
||||
# created on demand
|
||||
raise NsxPolicyTransactionException(
|
||||
"Transactional create is supported for infra level"
|
||||
" objects and their children")
|
||||
# Parent not found - create a node for missing parent
|
||||
wrapper, node = create_missing_node()
|
||||
d.append(wrapper)
|
||||
if is_leaf:
|
||||
# This is the last parent that needs creation
|
||||
return node
|
||||
return self._find_parent_in_dict(node['children'], resource_def,
|
||||
level + 1)
|
||||
|
||||
def apply_defs(self):
|
||||
# TODO(annak): find longest common URL, for now always
|
||||
@@ -136,7 +152,8 @@ class NsxPolicyTransaction(object):
|
||||
|
||||
top_def = self.defs[0]
|
||||
url = top_def.get_resource_path()
|
||||
body = {'resource_type': top_def.resource_type()}
|
||||
body = {'resource_type': top_def.resource_type(),
|
||||
'children': []}
|
||||
# iterate over defs (except top level def)
|
||||
for resource_def in self.defs[1:]:
|
||||
parent_dict = None
|
||||
@@ -145,16 +162,16 @@ class NsxPolicyTransaction(object):
|
||||
resource_def)
|
||||
|
||||
if not parent_dict:
|
||||
# Top level resource
|
||||
parent_dict = body
|
||||
|
||||
if 'children' not in parent_dict:
|
||||
parent_dict['children'] = []
|
||||
|
||||
resource_class = resource_def.resource_class()
|
||||
parent_dict['children'].append({
|
||||
'resource_type': 'Child%s' % resource_class,
|
||||
resource_class: resource_def.get_obj_dict()
|
||||
})
|
||||
parent_dict['children'].append(
|
||||
self._build_wrapper_dict(resource_class,
|
||||
resource_def.get_obj_dict()))
|
||||
|
||||
if body:
|
||||
self.client.patch(url, body)
|
||||
|
||||
Reference in New Issue
Block a user