Cherry pick NSX 3 related patches to Stein
commit: I4f9c3bfd7995bca85a51a6971fc9d784e574301a
commit: Ib8d8a15f23146e09fd6ed839c626724aa4e36952
commit: If1e86a3f0a0049b3022b9645f738440200e337d9
commit: I45b7c50a50b1a69e37b79f684b324bb17496a9df
commit: I59ef2e27f6a2f23a44edcd37da88bdc70fda944d
commit: 27d4662f90
commit: I26ce4b1af9e9b6c19a3245675a3db2c027361acb
commit: I8f8f928d6a7d40a909772b949ea7b49315f69ee3
commit: If51c51fb503dcb5465ad2eda5a3fb0cd24b463b8
commit: Ia34e42a94c10bd3f12ebc658939ed826af53658c
commit: Ibf1c1fc918998f6002e445ad53e32b2c5c54ac1c
Change-Id: Ibf1c1fc918998f6002e445ad53e32b2c5c54ac1c
This commit is contained in:
parent
99d13476df
commit
8985a92978
|
@ -17,6 +17,8 @@
|
|||
import mock
|
||||
|
||||
from vmware_nsxlib.tests.unit.v3.policy import test_resources
|
||||
from vmware_nsxlib.v3 import exceptions as nsxlib_exc
|
||||
from vmware_nsxlib.v3.policy import constants
|
||||
from vmware_nsxlib.v3.policy import lb_defs
|
||||
|
||||
TEST_TENANT = 'test'
|
||||
|
@ -603,6 +605,7 @@ class TestPolicyLBService(test_resources.NsxPolicyLibTestCase):
|
|||
obj_id = '111'
|
||||
size = 'SMALL'
|
||||
connectivity_path = 'path'
|
||||
relax_scale_validation = True
|
||||
with self.mock_create_update() as api_call:
|
||||
result = self.resourceApi.create_or_overwrite(
|
||||
name,
|
||||
|
@ -610,14 +613,17 @@ class TestPolicyLBService(test_resources.NsxPolicyLibTestCase):
|
|||
description=description,
|
||||
size=size,
|
||||
connectivity_path=connectivity_path,
|
||||
relax_scale_validation=relax_scale_validation,
|
||||
tenant=TEST_TENANT)
|
||||
expected_def = (
|
||||
lb_defs.LBServiceDef(
|
||||
nsx_version=self.policy_lib.get_version(),
|
||||
lb_service_id=obj_id,
|
||||
name=name,
|
||||
description=description,
|
||||
size=size,
|
||||
connectivity_path=connectivity_path,
|
||||
relax_scale_validation=relax_scale_validation,
|
||||
tenant=TEST_TENANT))
|
||||
self.assert_called_with_def(api_call, expected_def)
|
||||
self.assertEqual(obj_id, result)
|
||||
|
@ -637,6 +643,25 @@ class TestPolicyLBService(test_resources.NsxPolicyLibTestCase):
|
|||
self.assert_called_with_def(api_call, expected_def)
|
||||
self.assertIsNotNone(result)
|
||||
|
||||
def test_create_with_unsupported_attribute(self):
|
||||
name = 'd1'
|
||||
description = 'desc'
|
||||
relax_scale_validation = True
|
||||
|
||||
with self.mock_create_update() as api_call, \
|
||||
mock.patch.object(self.resourceApi, 'version', '0.0.0'):
|
||||
result = self.resourceApi.create_or_overwrite(
|
||||
name, description=description,
|
||||
relax_scale_validation=relax_scale_validation,
|
||||
tenant=TEST_TENANT)
|
||||
expected_def = (
|
||||
lb_defs.LBServiceDef(lb_service_id=mock.ANY,
|
||||
name=name,
|
||||
description=description,
|
||||
tenant=TEST_TENANT))
|
||||
self.assert_called_with_def(api_call, expected_def)
|
||||
self.assertIsNotNone(result)
|
||||
|
||||
def test_delete(self):
|
||||
obj_id = '111'
|
||||
with mock.patch.object(self.policy_api, "delete") as api_call:
|
||||
|
@ -683,21 +708,26 @@ class TestPolicyLBService(test_resources.NsxPolicyLibTestCase):
|
|||
description = 'new desc'
|
||||
size = 'SMALL'
|
||||
connectivity_path = 'path'
|
||||
relax_scale_validation = True
|
||||
with self.mock_get(obj_id, name), \
|
||||
self.mock_create_update() as update_call:
|
||||
self.resourceApi.update(obj_id,
|
||||
name=name,
|
||||
description=description,
|
||||
tenant=TEST_TENANT,
|
||||
size=size,
|
||||
connectivity_path=connectivity_path)
|
||||
self.resourceApi.update(
|
||||
obj_id,
|
||||
name=name,
|
||||
description=description,
|
||||
tenant=TEST_TENANT,
|
||||
size=size,
|
||||
connectivity_path=connectivity_path,
|
||||
relax_scale_validation=relax_scale_validation)
|
||||
expected_def = lb_defs.LBServiceDef(
|
||||
nsx_version=self.policy_lib.get_version(),
|
||||
lb_service_id=obj_id,
|
||||
name=name,
|
||||
description=description,
|
||||
tenant=TEST_TENANT,
|
||||
size=size,
|
||||
connectivity_path=connectivity_path)
|
||||
connectivity_path=connectivity_path,
|
||||
relax_scale_validation=relax_scale_validation)
|
||||
self.assert_called_with_def(update_call, expected_def)
|
||||
|
||||
def test_get_status(self):
|
||||
|
@ -729,6 +759,62 @@ class TestPolicyLBService(test_resources.NsxPolicyLibTestCase):
|
|||
tenant=TEST_TENANT)
|
||||
self.assert_called_with_def(api_call, expected_def)
|
||||
|
||||
def test_wait_until_realized_fail(self):
|
||||
lbs_id = 'test_lbs'
|
||||
info = {'state': constants.STATE_UNREALIZED,
|
||||
'realization_specific_identifier': lbs_id,
|
||||
'entity_type': 'LbServiceDto'}
|
||||
with mock.patch.object(self.resourceApi, "_get_realization_info",
|
||||
return_value=info):
|
||||
self.assertRaises(nsxlib_exc.RealizationTimeoutError,
|
||||
self.resourceApi.wait_until_realized,
|
||||
lbs_id, max_attempts=5, sleep=0.1,
|
||||
tenant=TEST_TENANT)
|
||||
|
||||
def test_wait_until_realized_error(self):
|
||||
lbs_id = 'test_lbs'
|
||||
error_code = 23500
|
||||
related_error_code = 23707
|
||||
error_msg = 'Found errors in the request.'
|
||||
related_error_msg = 'Exceed maximum number of load balancer.'
|
||||
info = {'state': constants.STATE_ERROR,
|
||||
'realization_specific_identifier': lbs_id,
|
||||
'entity_type': 'LbServiceDto',
|
||||
'alarms': [{
|
||||
'message': error_msg,
|
||||
'error_details': {
|
||||
'related_errors': [{
|
||||
'error_code': related_error_code,
|
||||
'module_name': 'LOAD-BALANCER',
|
||||
'error_message': related_error_msg
|
||||
}],
|
||||
'error_code': error_code,
|
||||
'module_name': 'LOAD-BALANCER',
|
||||
'error_message': error_msg
|
||||
}
|
||||
}]}
|
||||
with mock.patch.object(self.resourceApi, "_get_realization_info",
|
||||
return_value=info):
|
||||
with self.assertRaises(nsxlib_exc.RealizationErrorStateError) as e:
|
||||
self.resourceApi.wait_until_realized(
|
||||
lbs_id, tenant=TEST_TENANT)
|
||||
error_msg_tail = "%s: %s" % (error_msg, related_error_msg)
|
||||
self.assertTrue(e.exception.msg.endswith(error_msg_tail))
|
||||
self.assertEqual(e.exception.error_code, error_code)
|
||||
self.assertEqual(e.exception.related_error_codes,
|
||||
[related_error_code])
|
||||
|
||||
def test_wait_until_realized_succeed(self):
|
||||
lbs_id = 'test_lbs'
|
||||
info = {'state': constants.STATE_REALIZED,
|
||||
'realization_specific_identifier': lbs_id,
|
||||
'entity_type': 'LbServiceDto'}
|
||||
with mock.patch.object(self.resourceApi, "_get_realization_info",
|
||||
return_value=info):
|
||||
actual_info = self.resourceApi.wait_until_realized(
|
||||
lbs_id, max_attempts=5, sleep=0.1, tenant=TEST_TENANT)
|
||||
self.assertEqual(info, actual_info)
|
||||
|
||||
|
||||
class TestPolicyLBVirtualServer(test_resources.NsxPolicyLibTestCase):
|
||||
|
||||
|
@ -1015,6 +1101,29 @@ class TestPolicyLBVirtualServer(test_resources.NsxPolicyLibTestCase):
|
|||
rules=[{'display_name': 'yy'}])
|
||||
self.assert_called_with_def(update_call, expected_def)
|
||||
|
||||
def test_wait_until_realized_fail(self):
|
||||
vs_id = 'test_vs'
|
||||
info = {'state': constants.STATE_UNREALIZED,
|
||||
'realization_specific_identifier': vs_id}
|
||||
with mock.patch.object(self.resourceApi, "_get_realization_info",
|
||||
return_value=info):
|
||||
self.assertRaises(nsxlib_exc.RealizationTimeoutError,
|
||||
self.resourceApi.wait_until_realized,
|
||||
vs_id, max_attempts=5, sleep=0.1,
|
||||
tenant=TEST_TENANT)
|
||||
|
||||
def test_wait_until_realized_succeed(self):
|
||||
vs_id = 'test_vs'
|
||||
info = {'state': constants.STATE_REALIZED,
|
||||
'realization_specific_identifier': vs_id,
|
||||
'entity_type': 'LbVirtualServerDto'}
|
||||
with mock.patch.object(self.resourceApi, "_get_realization_info",
|
||||
return_value=info):
|
||||
actual_info = self.resourceApi.wait_until_realized(
|
||||
vs_id, entity_type='LbVirtualServerDto', max_attempts=5,
|
||||
sleep=0.1, tenant=TEST_TENANT)
|
||||
self.assertEqual(info, actual_info)
|
||||
|
||||
|
||||
class TestPolicyLBPoolApi(test_resources.NsxPolicyLibTestCase):
|
||||
|
||||
|
|
|
@ -1931,7 +1931,7 @@ class TestPolicyCommunicationMap(NsxPolicyLibTestCase):
|
|||
'display_name': 'map_name',
|
||||
'rules': [
|
||||
{'id': entry1_id, 'resource_type': 'Rule',
|
||||
'dsiplay_name': 'name1', 'scope': ['scope1']},
|
||||
'display_name': 'name1', 'scope': ['scope1']},
|
||||
{'id': entry2_id, 'resource_type': 'Rule',
|
||||
'display_name': 'name2', 'scope': ['scope2']},
|
||||
{'id': entry3_id, 'resource_type': 'Rule',
|
||||
|
@ -1943,7 +1943,7 @@ class TestPolicyCommunicationMap(NsxPolicyLibTestCase):
|
|||
'display_name': 'new_map_name',
|
||||
'rules': [
|
||||
{'id': entry1_id, 'resource_type': 'Rule',
|
||||
'dsiplay_name': 'name1', 'scope': ['new_scope1']},
|
||||
'display_name': 'name1', 'scope': ['new_scope1']},
|
||||
{'id': entry2_id, 'resource_type': 'Rule',
|
||||
'display_name': 'name2', 'scope': ['scope2']}]}
|
||||
map_def = self.mapDef(
|
||||
|
@ -1960,6 +1960,51 @@ class TestPolicyCommunicationMap(NsxPolicyLibTestCase):
|
|||
update_call.assert_called_once_with(
|
||||
map_def.get_resource_path(), updated_map)
|
||||
|
||||
def test_update_with_entries_for_IGNORE_entries(self):
|
||||
domain_id = '111'
|
||||
map_id = '222'
|
||||
entry1_id = 'entry1'
|
||||
entry2_id = 'entry2'
|
||||
entry3_id = 'entry3'
|
||||
original_map = {
|
||||
'id': map_id,
|
||||
'resource_type': self.resource_type,
|
||||
'category': constants.CATEGORY_APPLICATION,
|
||||
'display_name': 'map_name',
|
||||
'rules': [
|
||||
{'id': entry1_id, 'resource_type': 'Rule',
|
||||
'display_name': 'name1', 'scope': ['scope1'],
|
||||
'_created_time': 1},
|
||||
{'id': entry2_id, 'resource_type': 'Rule',
|
||||
'display_name': 'name2', 'scope': ['scope2']},
|
||||
{'id': entry3_id, 'resource_type': 'Rule',
|
||||
'display_name': 'name3', 'scope': ['scope3']}]}
|
||||
updated_map = {
|
||||
'id': map_id,
|
||||
'resource_type': self.resource_type,
|
||||
'category': constants.CATEGORY_APPLICATION,
|
||||
'display_name': 'new_map_name',
|
||||
'rules': [
|
||||
{'id': entry1_id, 'resource_type': 'Rule',
|
||||
'display_name': 'name1', 'scope': ['scope1'],
|
||||
'_created_time': 1},
|
||||
{'id': entry2_id, 'resource_type': 'Rule',
|
||||
'display_name': 'name2', 'scope': ['scope2']},
|
||||
{'id': entry3_id, 'resource_type': 'Rule',
|
||||
'display_name': 'name3', 'scope': ['scope3']}]}
|
||||
map_def = self.mapDef(
|
||||
domain_id=domain_id,
|
||||
map_id=map_id,
|
||||
tenant=TEST_TENANT)
|
||||
with mock.patch.object(self.policy_api, "get",
|
||||
return_value=original_map),\
|
||||
mock.patch.object(self.policy_api.client,
|
||||
"update") as update_call:
|
||||
self.resourceApi.update_with_entries(
|
||||
domain_id, map_id, name='new_map_name', tenant=TEST_TENANT)
|
||||
update_call.assert_called_once_with(
|
||||
map_def.get_resource_path(), updated_map)
|
||||
|
||||
def test_unset(self):
|
||||
name = 'hello'
|
||||
domain_id = 'test'
|
||||
|
@ -3050,6 +3095,7 @@ class TestPolicyTier0NatRule(NsxPolicyLibTestCase):
|
|||
tier0_id = '111'
|
||||
nat_rule_id = 'rule1'
|
||||
action = constants.NAT_ACTION_SNAT
|
||||
firewall_match = constants.NAT_FIREWALL_MATCH_INTERNAL
|
||||
cidr1 = '1.1.1.1/32'
|
||||
cidr2 = '2.2.2.0/24'
|
||||
enabled = True
|
||||
|
@ -3063,6 +3109,7 @@ class TestPolicyTier0NatRule(NsxPolicyLibTestCase):
|
|||
action=action,
|
||||
translated_network=cidr1,
|
||||
source_network=cidr2,
|
||||
firewall_match=firewall_match,
|
||||
tenant=TEST_TENANT,
|
||||
enabled=enabled)
|
||||
expected_def = core_defs.Tier0NatRule(
|
||||
|
@ -3074,6 +3121,7 @@ class TestPolicyTier0NatRule(NsxPolicyLibTestCase):
|
|||
action=action,
|
||||
translated_network=cidr1,
|
||||
source_network=cidr2,
|
||||
firewall_match=firewall_match,
|
||||
tenant=TEST_TENANT,
|
||||
enabled=enabled)
|
||||
self.assert_called_with_def(api_call, expected_def)
|
||||
|
@ -3109,6 +3157,44 @@ class TestPolicyTier0NatRule(NsxPolicyLibTestCase):
|
|||
self.assert_called_with_def(api_call, expected_def)
|
||||
self.assertEqual(mock_t0_nat_rule, result)
|
||||
|
||||
def test_update(self):
|
||||
name = 'test'
|
||||
description = 'desc'
|
||||
tier0_id = '111'
|
||||
nat_rule_id = 'rule1'
|
||||
action = constants.NAT_ACTION_SNAT
|
||||
firewall_match = constants.NAT_FIREWALL_MATCH_EXTERNAL
|
||||
cidr1 = '1.1.1.1/32'
|
||||
cidr2 = '2.2.2.0/24'
|
||||
enabled = True
|
||||
|
||||
with mock.patch.object(self.policy_api,
|
||||
"create_or_update") as api_call:
|
||||
self.resourceApi.update(
|
||||
tier0_id, nat_rule_id,
|
||||
name=name,
|
||||
description=description,
|
||||
action=action,
|
||||
translated_network=cidr1,
|
||||
firewall_match=firewall_match,
|
||||
source_network=cidr2,
|
||||
tenant=TEST_TENANT,
|
||||
enabled=enabled)
|
||||
|
||||
expected_def = core_defs.Tier0NatRule(
|
||||
tier0_id=tier0_id,
|
||||
nat_rule_id=nat_rule_id,
|
||||
nat_id=self.resourceApi.DEFAULT_NAT_ID,
|
||||
name=name,
|
||||
description=description,
|
||||
action=action,
|
||||
translated_network=cidr1,
|
||||
firewall_match=firewall_match,
|
||||
source_network=cidr2,
|
||||
tenant=TEST_TENANT,
|
||||
enabled=enabled)
|
||||
self.assert_called_with_def(api_call, expected_def)
|
||||
|
||||
|
||||
class TestPolicyTier1NatRule(NsxPolicyLibTestCase):
|
||||
|
||||
|
@ -3122,6 +3208,7 @@ class TestPolicyTier1NatRule(NsxPolicyLibTestCase):
|
|||
tier1_id = '111'
|
||||
nat_rule_id = 'rule1'
|
||||
action = constants.NAT_ACTION_SNAT
|
||||
firewall_match = constants.NAT_FIREWALL_MATCH_INTERNAL
|
||||
cidr1 = '1.1.1.1/32'
|
||||
cidr2 = '2.2.2.0/24'
|
||||
enabled = True
|
||||
|
@ -3134,6 +3221,7 @@ class TestPolicyTier1NatRule(NsxPolicyLibTestCase):
|
|||
description=description,
|
||||
action=action,
|
||||
translated_network=cidr1,
|
||||
firewall_match=firewall_match,
|
||||
source_network=cidr2,
|
||||
tenant=TEST_TENANT,
|
||||
enabled=enabled)
|
||||
|
@ -3146,6 +3234,7 @@ class TestPolicyTier1NatRule(NsxPolicyLibTestCase):
|
|||
description=description,
|
||||
action=action,
|
||||
translated_network=cidr1,
|
||||
firewall_match=firewall_match,
|
||||
source_network=cidr2,
|
||||
tenant=TEST_TENANT,
|
||||
enabled=enabled)
|
||||
|
@ -3167,6 +3256,44 @@ class TestPolicyTier1NatRule(NsxPolicyLibTestCase):
|
|||
tenant=TEST_TENANT)
|
||||
self.assert_called_with_def(api_call, expected_def)
|
||||
|
||||
def test_update(self):
|
||||
name = 'test'
|
||||
description = 'desc'
|
||||
tier1_id = '111'
|
||||
nat_rule_id = 'rule1'
|
||||
action = constants.NAT_ACTION_SNAT
|
||||
firewall_match = constants.NAT_FIREWALL_MATCH_INTERNAL
|
||||
cidr1 = '1.1.1.1/32'
|
||||
cidr2 = '2.2.2.0/24'
|
||||
enabled = True
|
||||
|
||||
with mock.patch.object(self.policy_api,
|
||||
"create_or_update") as api_call:
|
||||
self.resourceApi.update(
|
||||
tier1_id, nat_rule_id,
|
||||
name=name,
|
||||
description=description,
|
||||
action=action,
|
||||
translated_network=cidr1,
|
||||
firewall_match=firewall_match,
|
||||
source_network=cidr2,
|
||||
tenant=TEST_TENANT,
|
||||
enabled=enabled)
|
||||
|
||||
expected_def = core_defs.Tier1NatRule(
|
||||
tier1_id=tier1_id,
|
||||
nat_rule_id=nat_rule_id,
|
||||
nat_id=self.resourceApi.DEFAULT_NAT_ID,
|
||||
name=name,
|
||||
description=description,
|
||||
action=action,
|
||||
translated_network=cidr1,
|
||||
firewall_match=firewall_match,
|
||||
source_network=cidr2,
|
||||
tenant=TEST_TENANT,
|
||||
enabled=enabled)
|
||||
self.assert_called_with_def(api_call, expected_def)
|
||||
|
||||
|
||||
class TestPolicyTier1StaticRoute(NsxPolicyLibTestCase):
|
||||
|
||||
|
@ -3846,6 +3973,17 @@ class TestPolicyIpPool(NsxPolicyLibTestCase):
|
|||
tenant=TEST_TENANT)
|
||||
self.assert_called_with_def(api_call, expected_def)
|
||||
|
||||
def test_get_realization_info(self):
|
||||
ip_pool_id = '111'
|
||||
with mock.patch.object(
|
||||
self.resourceApi, "_get_realization_info") as api_call:
|
||||
self.resourceApi.get_realization_info(
|
||||
ip_pool_id, tenant=TEST_TENANT)
|
||||
expected_def = core_defs.IpPoolDef(
|
||||
ip_pool_id=ip_pool_id,
|
||||
tenant=TEST_TENANT)
|
||||
self.assert_called_with_def_and_dict(api_call, expected_def, {})
|
||||
|
||||
def test_get_static_subnet_realization_info(self):
|
||||
ip_pool_id = 'ip-pool-id'
|
||||
ip_subnet_id = 'static-subnet-id'
|
||||
|
@ -3870,6 +4008,53 @@ class TestPolicyIpPool(NsxPolicyLibTestCase):
|
|||
wait=True, subnet_type=constants.IPPOOL_STATIC_SUBNET)
|
||||
api_get.assert_called_once()
|
||||
|
||||
def test_wait_until_realized_fail(self):
|
||||
ip_pool_id = 'p1'
|
||||
info = {'state': constants.STATE_UNREALIZED,
|
||||
'realization_specific_identifier': ip_pool_id,
|
||||
'entity_type': 'IpPool'}
|
||||
with mock.patch.object(self.resourceApi, "_get_realization_info",
|
||||
return_value=info):
|
||||
self.assertRaises(nsxlib_exc.RealizationTimeoutError,
|
||||
self.resourceApi.wait_until_realized,
|
||||
ip_pool_id, max_attempts=5, sleep=0.1,
|
||||
tenant=TEST_TENANT)
|
||||
|
||||
def test_wait_until_realized_error(self):
|
||||
ip_alloc_id = 'ip_alloc_1'
|
||||
error_code = 5109
|
||||
error_msg = 'Insufficient free IP addresses.'
|
||||
info = {'state': constants.STATE_ERROR,
|
||||
'realization_specific_identifier': ip_alloc_id,
|
||||
'entity_type': 'AllocationIpAddress',
|
||||
'alarms': [{
|
||||
'message': error_msg,
|
||||
'error_details': {
|
||||
'error_code': error_code,
|
||||
'module_name': 'id-allocation service',
|
||||
'error_message': error_msg
|
||||
}
|
||||
}]}
|
||||
with mock.patch.object(self.resourceApi, "_get_realization_info",
|
||||
return_value=info):
|
||||
with self.assertRaises(nsxlib_exc.RealizationErrorStateError) as e:
|
||||
self.resourceApi.wait_until_realized(
|
||||
ip_alloc_id, tenant=TEST_TENANT)
|
||||
self.assertTrue(e.exception.msg.endswith(error_msg))
|
||||
self.assertEqual(e.exception.error_code, error_code)
|
||||
self.assertEqual(e.exception.related_error_codes, [])
|
||||
|
||||
def test_wait_until_realized_succeed(self):
|
||||
ip_pool_id = 'p1'
|
||||
info = {'state': constants.STATE_REALIZED,
|
||||
'realization_specific_identifier': ip_pool_id,
|
||||
'entity_type': 'IpPool'}
|
||||
with mock.patch.object(self.resourceApi, "_get_realization_info",
|
||||
return_value=info):
|
||||
actual_info = self.resourceApi.wait_until_realized(
|
||||
ip_pool_id, max_attempts=5, sleep=0.1, tenant=TEST_TENANT)
|
||||
self.assertEqual(info, actual_info)
|
||||
|
||||
|
||||
class TestPolicySegmentPort(NsxPolicyLibTestCase):
|
||||
|
||||
|
@ -4747,3 +4932,88 @@ class TestPolicyExcludeList(NsxPolicyLibTestCase):
|
|||
|
||||
def test_update(self):
|
||||
self.skipTest("The action is not supported by this resource")
|
||||
|
||||
|
||||
class TestNsxSearch(NsxPolicyLibTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestNsxSearch, self).setUp()
|
||||
self.search_path = 'search/query?query=%s'
|
||||
|
||||
def test_nsx_search_by_realization(self):
|
||||
"""Test search of resources with the specified tag."""
|
||||
with mock.patch.object(self.policy_lib.client, 'url_get') as search:
|
||||
realized_id = 'xxx'
|
||||
realized_type = 'RealizedLogicalSwitch'
|
||||
query = ('resource_type:GenericPolicyRealizedResource AND '
|
||||
'realization_specific_identifier:%s AND '
|
||||
'entity_type:%s' % (realized_id, realized_type))
|
||||
self.policy_lib.search_resource_by_realized_id(
|
||||
realized_id, realized_type)
|
||||
search.assert_called_with(self.search_path % query)
|
||||
|
||||
|
||||
class TestPolicyGlobalConfig(NsxPolicyLibTestCase):
|
||||
|
||||
def setUp(self, *args, **kwargs):
|
||||
super(TestPolicyGlobalConfig, self).setUp()
|
||||
self.resourceApi = self.policy_lib.global_config
|
||||
|
||||
def test_create_or_overwrite(self):
|
||||
self.skipTest("The action is not supported by this resource")
|
||||
|
||||
def test_delete(self):
|
||||
self.skipTest("The action is not supported by this resource")
|
||||
|
||||
def test_get(self):
|
||||
with mock.patch.object(self.policy_api, "get") as api_call:
|
||||
self.resourceApi.get(tenant=TEST_TENANT)
|
||||
expected_def = core_defs.GlobalConfigDef(
|
||||
tenant=TEST_TENANT)
|
||||
self.assert_called_with_def(api_call, expected_def)
|
||||
|
||||
def test_list(self):
|
||||
self.skipTest("The action is not supported by this resource")
|
||||
|
||||
def test_update(self):
|
||||
self.skipTest("The action is not supported by this resource")
|
||||
|
||||
def test_enable_ipv6(self):
|
||||
current_config = {'l3_forwarding_mode': 'IPV4_ONLY'}
|
||||
with mock.patch.object(self.policy_api, "get",
|
||||
return_value=current_config) as api_get,\
|
||||
mock.patch.object(self.policy_api.client, "update") as api_put:
|
||||
self.resourceApi.enable_ipv6(tenant=TEST_TENANT)
|
||||
api_get.assert_called_once()
|
||||
api_put.assert_called_once_with(
|
||||
"%s/global-config/" % TEST_TENANT,
|
||||
{'l3_forwarding_mode': 'IPV4_AND_IPV6'})
|
||||
|
||||
def test_enable_ipv6_no_call(self):
|
||||
current_config = {'l3_forwarding_mode': 'IPV4_AND_IPV6'}
|
||||
with mock.patch.object(self.policy_api, "get",
|
||||
return_value=current_config) as api_get,\
|
||||
mock.patch.object(self.policy_api.client, "update") as api_put:
|
||||
self.resourceApi.enable_ipv6(tenant=TEST_TENANT)
|
||||
api_get.assert_called_once()
|
||||
api_put.assert_not_called()
|
||||
|
||||
def test_disable_ipv6(self):
|
||||
current_config = {'l3_forwarding_mode': 'IPV4_AND_IPV6'}
|
||||
with mock.patch.object(self.policy_api, "get",
|
||||
return_value=current_config) as api_get,\
|
||||
mock.patch.object(self.policy_api.client, "update") as api_put:
|
||||
self.resourceApi.disable_ipv6(tenant=TEST_TENANT)
|
||||
api_get.assert_called_once()
|
||||
api_put.assert_called_once_with(
|
||||
"%s/global-config/" % TEST_TENANT,
|
||||
{'l3_forwarding_mode': 'IPV4_ONLY'})
|
||||
|
||||
def test_disable_ipv6_no_call(self):
|
||||
current_config = {'l3_forwarding_mode': 'IPV4_ONLY'}
|
||||
with mock.patch.object(self.policy_api, "get",
|
||||
return_value=current_config) as api_get,\
|
||||
mock.patch.object(self.policy_api.client, "update") as api_put:
|
||||
self.resourceApi.disable_ipv6(tenant=TEST_TENANT)
|
||||
api_get.assert_called_once()
|
||||
api_put.assert_not_called()
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
# under the License.
|
||||
#
|
||||
|
||||
import copy
|
||||
|
||||
import mock
|
||||
|
||||
from vmware_nsxlib.tests.unit.v3 import nsxlib_testcase
|
||||
|
@ -248,3 +250,189 @@ class TestPolicyTransaction(policy_testcase.TestPolicyApi):
|
|||
'Segment': seg2}]}
|
||||
|
||||
self.assert_infra_patch_call(expected_body)
|
||||
|
||||
def test_creating_security_policy_and_dfw_rules(self):
|
||||
dfw_rule = {'id': 'rule_id1', 'action': 'ALLOW',
|
||||
'display_name': 'rule1', 'description': None,
|
||||
'direction': 'IN_OUT', 'ip_protocol': 'IPV4_IPV6',
|
||||
'logged': False, 'destination_groups': ['destination_url'],
|
||||
'source_groups': ['src_url'], 'resource_type': 'Rule',
|
||||
'scope': None, 'sequence_number': None, 'tag': None,
|
||||
'services': ['ANY']}
|
||||
security_policy = {'id': 'security_policy_id1',
|
||||
'display_name': 'security_policy',
|
||||
'category': 'Application',
|
||||
'resource_type': 'SecurityPolicy'}
|
||||
domain = {'resource_type': 'Domain', 'id': 'domain1'}
|
||||
domain_id = domain['id']
|
||||
map_id = security_policy['id']
|
||||
dfw_rule_entries = [self.policy_lib.comm_map.build_entry(
|
||||
name=dfw_rule['display_name'],
|
||||
domain_id=domain_id,
|
||||
map_id=map_id,
|
||||
entry_id=dfw_rule['id'],
|
||||
source_groups=dfw_rule['source_groups'],
|
||||
dest_groups=dfw_rule['destination_groups']
|
||||
)]
|
||||
with trans.NsxPolicyTransaction():
|
||||
self.policy_lib.comm_map.create_with_entries(
|
||||
name=security_policy['display_name'],
|
||||
domain_id=domain_id,
|
||||
map_id=map_id,
|
||||
entries=dfw_rule_entries
|
||||
)
|
||||
|
||||
def get_group_path(group_id, domain_id):
|
||||
return '/infra/domains/' + domain_id + '/groups/' + group_id
|
||||
|
||||
dfw_rule['destination_groups'] = [get_group_path(group_id, domain_id)
|
||||
for group_id in
|
||||
dfw_rule['destination_groups']]
|
||||
dfw_rule['source_groups'] = [get_group_path(group_id, domain_id) for
|
||||
group_id in dfw_rule['source_groups']]
|
||||
child_rules = [{'resource_type': 'ChildRule', 'Rule': dfw_rule}]
|
||||
security_policy.update({'children': child_rules})
|
||||
child_security_policies = [{
|
||||
'resource_type': 'ChildSecurityPolicy',
|
||||
'SecurityPolicy': security_policy
|
||||
}]
|
||||
domain.update({'children': child_security_policies})
|
||||
child_domains = [{'resource_type': 'ChildDomain',
|
||||
'Domain': domain}]
|
||||
expected_body = {'resource_type': 'Infra',
|
||||
'children': child_domains}
|
||||
self.assert_infra_patch_call(expected_body)
|
||||
|
||||
@mock.patch('vmware_nsxlib.v3.policy.core_defs.NsxPolicyApi.get')
|
||||
def test_updating_security_policy_and_dfw_rules(self, mock_get_api):
|
||||
dfw_rule1 = {'id': 'rule_id1', 'action': 'ALLOW',
|
||||
'display_name': 'rule1', 'description': None,
|
||||
'direction': 'IN_OUT', 'ip_protocol': 'IPV4_IPV6',
|
||||
'logged': False,
|
||||
'destination_groups': ['destination_url'],
|
||||
'source_groups': ['src_url'], 'resource_type': 'Rule',
|
||||
'scope': None, 'sequence_number': None, 'tag': None,
|
||||
'services': ['ANY'], "_create_time": 1}
|
||||
dfw_rule2 = {'id': 'rule_id2', 'action': 'DROP',
|
||||
'display_name': 'rule2', 'description': None,
|
||||
'direction': 'IN_OUT', 'ip_protocol': 'IPV4_IPV6',
|
||||
'logged': False,
|
||||
'destination_groups': ['destination_url'],
|
||||
'source_groups': ['src_url'], 'resource_type': 'Rule',
|
||||
'scope': None, 'sequence_number': None, 'tag': None,
|
||||
'services': ['ANY'], "_create_time": 1}
|
||||
security_policy = {'id': 'security_policy_id1',
|
||||
'display_name': 'security_policy',
|
||||
'category': 'Application',
|
||||
'resource_type': 'SecurityPolicy'}
|
||||
domain = {'resource_type': 'Domain', 'id': 'domain1'}
|
||||
domain_id = domain['id']
|
||||
map_id = security_policy['id']
|
||||
new_rule_name = 'new_rule1'
|
||||
new_direction = 'IN'
|
||||
dfw_rule_entries = [self.policy_lib.comm_map.build_entry(
|
||||
name=new_rule_name,
|
||||
domain_id=domain_id,
|
||||
map_id=map_id,
|
||||
entry_id=dfw_rule1['id'],
|
||||
source_groups=dfw_rule1['source_groups'],
|
||||
dest_groups=dfw_rule1['destination_groups'],
|
||||
direction=new_direction
|
||||
)]
|
||||
|
||||
def get_group_path(group_id, domain_id):
|
||||
return '/infra/domains/' + domain_id + '/groups/' + group_id
|
||||
|
||||
for dfw_rule in [dfw_rule1, dfw_rule2]:
|
||||
dfw_rule['destination_groups'] = [get_group_path(group_id,
|
||||
domain_id)
|
||||
for group_id in
|
||||
dfw_rule['destination_groups']]
|
||||
dfw_rule['source_groups'] = [get_group_path(group_id, domain_id)
|
||||
for group_id in
|
||||
dfw_rule['source_groups']]
|
||||
|
||||
security_policy_values = copy.deepcopy(security_policy)
|
||||
security_policy_values.update({'rules':
|
||||
copy.deepcopy([dfw_rule1, dfw_rule2])})
|
||||
mock_get_api.return_value = security_policy_values
|
||||
|
||||
with trans.NsxPolicyTransaction():
|
||||
self.policy_lib.comm_map.update_with_entries(
|
||||
name=security_policy['display_name'],
|
||||
domain_id=domain_id,
|
||||
map_id=map_id,
|
||||
entries=dfw_rule_entries
|
||||
)
|
||||
|
||||
dfw_rule1['display_name'] = new_rule_name
|
||||
dfw_rule1['direction'] = new_direction
|
||||
child_rules = [{'resource_type': 'ChildRule', 'Rule': dfw_rule1},
|
||||
{'resource_type': 'ChildRule', 'Rule': dfw_rule2,
|
||||
'marked_for_delete': True}]
|
||||
security_policy.update({'children': child_rules})
|
||||
child_security_policies = [{
|
||||
'resource_type': 'ChildSecurityPolicy',
|
||||
'SecurityPolicy': security_policy
|
||||
}]
|
||||
domain.update({'children': child_security_policies})
|
||||
child_domains = [{
|
||||
'resource_type': 'ChildDomain',
|
||||
'Domain': domain
|
||||
}]
|
||||
expected_body = {'resource_type': 'Infra',
|
||||
'children': child_domains}
|
||||
self.assert_infra_patch_call(expected_body)
|
||||
|
||||
@mock.patch('vmware_nsxlib.v3.policy.core_defs.NsxPolicyApi.get')
|
||||
def test_updating_security_policy_with_no_entries_set(self, mock_get_api):
|
||||
dfw_rule1 = {'id': 'rule_id1', 'action': 'ALLOW',
|
||||
'display_name': 'rule1', 'description': None,
|
||||
'direction': 'IN_OUT', 'ip_protocol': 'IPV4_IPV6',
|
||||
'logged': False,
|
||||
'destination_groups': ['destination_url'],
|
||||
'source_groups': ['src_url'], 'resource_type': 'Rule',
|
||||
'scope': None, 'sequence_number': None, 'tag': None,
|
||||
'services': ['ANY'], "_create_time": 1}
|
||||
security_policy = {'id': 'security_policy_id1',
|
||||
'display_name': 'security_policy',
|
||||
'category': 'Application',
|
||||
'resource_type': 'SecurityPolicy'}
|
||||
domain = {'resource_type': 'Domain', 'id': 'domain1'}
|
||||
domain_id = domain['id']
|
||||
map_id = security_policy['id']
|
||||
|
||||
def get_group_path(group_id, domain_id):
|
||||
return '/infra/domains/' + domain_id + '/groups/' + group_id
|
||||
|
||||
for dfw_rule in [dfw_rule1]:
|
||||
dfw_rule['destination_groups'] = [get_group_path(group_id,
|
||||
domain_id)
|
||||
for group_id in
|
||||
dfw_rule['destination_groups']]
|
||||
dfw_rule['source_groups'] = [get_group_path(group_id, domain_id)
|
||||
for group_id in
|
||||
dfw_rule['source_groups']]
|
||||
|
||||
security_policy.update({'rules': [dfw_rule1]})
|
||||
mock_get_api.return_value = security_policy
|
||||
|
||||
with trans.NsxPolicyTransaction():
|
||||
self.policy_lib.comm_map.update_with_entries(
|
||||
name=security_policy['display_name'],
|
||||
domain_id=domain_id,
|
||||
map_id=map_id
|
||||
)
|
||||
|
||||
child_security_policies = [{
|
||||
'resource_type': 'ChildSecurityPolicy',
|
||||
'SecurityPolicy': security_policy
|
||||
}]
|
||||
domain.update({'children': child_security_policies})
|
||||
child_domains = [{
|
||||
'resource_type': 'ChildDomain',
|
||||
'Domain': domain
|
||||
}]
|
||||
expected_body = {'resource_type': 'Infra',
|
||||
'children': child_domains}
|
||||
self.assert_infra_patch_call(expected_body)
|
||||
|
|
|
@ -334,7 +334,8 @@ FAKE_SERVICE = {
|
|||
"attachment": {
|
||||
"target_id": FAKE_ROUTER_UUID,
|
||||
"target_type": "LogicalRouter"
|
||||
}
|
||||
},
|
||||
"relax_scale_validation": False
|
||||
}
|
||||
|
||||
FAKE_TZ_UUID = uuidutils.generate_uuid()
|
||||
|
|
|
@ -500,15 +500,19 @@ class TestService(nsxlib_testcase.NsxClientTestCase):
|
|||
'description': fake_service['description'],
|
||||
'enabled': fake_service['enabled'],
|
||||
'attachment': fake_service['attachment'],
|
||||
'relax_scale_validation': fake_service['relax_scale_validation'],
|
||||
'tags': consts.FAKE_TAGS
|
||||
}
|
||||
with mock.patch.object(self.nsxlib.client, 'create') as create:
|
||||
self.nsxlib.load_balancer.service.create(
|
||||
body['display_name'], body['description'],
|
||||
consts.FAKE_TAGS, enabled=body['enabled'],
|
||||
attachment=body['attachment'])
|
||||
create.assert_called_with('loadbalancer/services',
|
||||
body)
|
||||
with mock.patch.object(self.nsxlib.client, 'create') as create, \
|
||||
mock.patch.object(self.nsxlib, 'feature_supported') as support:
|
||||
support.return_value = True
|
||||
self.nsxlib.load_balancer.service.create(
|
||||
body['display_name'], body['description'],
|
||||
consts.FAKE_TAGS, enabled=body['enabled'],
|
||||
attachment=body['attachment'],
|
||||
relax_scale_validation=body['relax_scale_validation'])
|
||||
create.assert_called_with('loadbalancer/services',
|
||||
body)
|
||||
|
||||
def test_list_services(self):
|
||||
with mock.patch.object(self.nsxlib.client, 'list') as list_call:
|
||||
|
|
|
@ -1565,13 +1565,27 @@ class IpPoolTestCase(BaseTestResource):
|
|||
|
||||
class TestNsxSearch(nsxlib_testcase.NsxClientTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestNsxSearch, self).setUp()
|
||||
self.search_path = 'search?query=%s'
|
||||
self.mock = mock.patch("vmware_nsxlib.v3.NsxLib.get_version",
|
||||
return_value=self.get_nsxlib_version())
|
||||
self.mock.start()
|
||||
|
||||
def tearDown(self):
|
||||
self.mock.stop()
|
||||
|
||||
@staticmethod
|
||||
def get_nsxlib_version():
|
||||
return '2.5.0'
|
||||
|
||||
def test_nsx_search_tags(self):
|
||||
"""Test search of resources with the specified tag."""
|
||||
with mock.patch.object(self.nsxlib.client, 'url_get') as search:
|
||||
user_tags = [{'scope': 'user', 'tag': 'k8s'}]
|
||||
query = self.nsxlib._build_query(tags=user_tags)
|
||||
self.nsxlib.search_by_tags(tags=user_tags)
|
||||
search.assert_called_with('search?query=%s' % query)
|
||||
search.assert_called_with(self.search_path % query)
|
||||
|
||||
def test_nsx_search_tags_scope_only(self):
|
||||
"""Test search of resources with the specified tag."""
|
||||
|
@ -1579,7 +1593,7 @@ class TestNsxSearch(nsxlib_testcase.NsxClientTestCase):
|
|||
user_tags = [{'scope': 'user'}]
|
||||
query = self.nsxlib._build_query(tags=user_tags)
|
||||
self.nsxlib.search_by_tags(tags=user_tags)
|
||||
search.assert_called_with('search?query=%s' % query)
|
||||
search.assert_called_with(self.search_path % query)
|
||||
|
||||
def test_nsx_search_tags_tag_only(self):
|
||||
"""Test search of resources with the specified tag."""
|
||||
|
@ -1587,7 +1601,7 @@ class TestNsxSearch(nsxlib_testcase.NsxClientTestCase):
|
|||
user_tags = [{'tag': 'k8s'}]
|
||||
query = self.nsxlib._build_query(tags=user_tags)
|
||||
self.nsxlib.search_by_tags(tags=user_tags)
|
||||
search.assert_called_with('search?query=%s' % query)
|
||||
search.assert_called_with(self.search_path % query)
|
||||
|
||||
def test_nsx_search_by_resouce_type_and_attributes(self):
|
||||
with mock.patch.object(self.nsxlib.client, 'url_get') as search:
|
||||
|
@ -1598,7 +1612,7 @@ class TestNsxSearch(nsxlib_testcase.NsxClientTestCase):
|
|||
exp_query = 'resource_type:%s AND color:%s' % (
|
||||
resource_type, attributes['color'])
|
||||
search.assert_called_with(
|
||||
'search?query=%s' % exp_query)
|
||||
self.search_path % exp_query)
|
||||
|
||||
def test_nsx_search_by_resouce_type_only(self):
|
||||
with mock.patch.object(self.nsxlib.client, 'url_get') as search:
|
||||
|
@ -1606,7 +1620,7 @@ class TestNsxSearch(nsxlib_testcase.NsxClientTestCase):
|
|||
self.nsxlib.search_resource_by_attributes(resource_type)
|
||||
exp_query = 'resource_type:%s' % resource_type
|
||||
search.assert_called_with(
|
||||
'search?query=%s' % exp_query)
|
||||
self.search_path % exp_query)
|
||||
|
||||
def test_nsx_search_no_resource_type_fails(self):
|
||||
self.assertRaises(exceptions.NsxSearchInvalidQuery,
|
||||
|
@ -1622,7 +1636,7 @@ class TestNsxSearch(nsxlib_testcase.NsxClientTestCase):
|
|||
exp_query = 'resource_type:%s AND color:%s' % (
|
||||
resource_type, attributes['color'])
|
||||
search.assert_called_with(
|
||||
'search?query=%s&cursor=50&page_size=100' % exp_query)
|
||||
(self.search_path + '&cursor=50&page_size=100') % exp_query)
|
||||
|
||||
def test_nsx_search_tags_tag_and_scope(self):
|
||||
"""Test search of resources with the specified tag."""
|
||||
|
@ -1630,7 +1644,7 @@ class TestNsxSearch(nsxlib_testcase.NsxClientTestCase):
|
|||
user_tags = [{'tag': 'k8s'}, {'scope': 'user'}]
|
||||
query = self.nsxlib._build_query(tags=user_tags)
|
||||
self.nsxlib.search_by_tags(tags=user_tags)
|
||||
search.assert_called_with('search?query=%s' % query)
|
||||
search.assert_called_with(self.search_path % query)
|
||||
|
||||
def test_nsx_search_tags_and_resource_type(self):
|
||||
"""Test search of specified resource with the specified tag."""
|
||||
|
@ -1641,7 +1655,7 @@ class TestNsxSearch(nsxlib_testcase.NsxClientTestCase):
|
|||
# Add resource_type to the query
|
||||
query = "resource_type:%s AND %s" % (res_type, query)
|
||||
self.nsxlib.search_by_tags(tags=user_tags, resource_type=res_type)
|
||||
search.assert_called_with('search?query=%s' % query)
|
||||
search.assert_called_with(self.search_path % query)
|
||||
|
||||
def test_nsx_search_tags_and_cursor(self):
|
||||
"""Test search of resources with the specified tag and cursor."""
|
||||
|
@ -1649,7 +1663,8 @@ class TestNsxSearch(nsxlib_testcase.NsxClientTestCase):
|
|||
user_tags = [{'scope': 'user', 'tag': 'k8s'}]
|
||||
query = self.nsxlib._build_query(tags=user_tags)
|
||||
self.nsxlib.search_by_tags(tags=user_tags, cursor=50)
|
||||
search.assert_called_with('search?query=%s&cursor=50' % query)
|
||||
search.assert_called_with(
|
||||
(self.search_path + '&cursor=50') % query)
|
||||
|
||||
def test_nsx_search_tags_and_page_size(self):
|
||||
"""Test search of resources with the specified tag and page size."""
|
||||
|
@ -1657,7 +1672,8 @@ class TestNsxSearch(nsxlib_testcase.NsxClientTestCase):
|
|||
user_tags = [{'scope': 'user', 'tag': 'k8s'}]
|
||||
query = self.nsxlib._build_query(tags=user_tags)
|
||||
self.nsxlib.search_by_tags(tags=user_tags, page_size=100)
|
||||
search.assert_called_with('search?query=%s&page_size=100' % query)
|
||||
search.assert_called_with(
|
||||
(self.search_path + '&page_size=100') % query)
|
||||
|
||||
def test_nsx_search_invalid_query_fail(self):
|
||||
"""Test search query failure for missing tag argument."""
|
||||
|
@ -1687,8 +1703,8 @@ class TestNsxSearch(nsxlib_testcase.NsxClientTestCase):
|
|||
query = self.nsxlib._build_query(tags=user_tags)
|
||||
results = self.nsxlib.search_all_by_tags(tags=user_tags)
|
||||
search.assert_has_calls([
|
||||
mock.call('search?query=%s' % query),
|
||||
mock.call('search?query=%s&cursor=2' % query)])
|
||||
mock.call(self.search_path % query),
|
||||
mock.call((self.search_path + '&cursor=2') % query)])
|
||||
self.assertEqual(3, len(results))
|
||||
|
||||
def test_get_id_by_resource_and_tag(self):
|
||||
|
@ -1726,6 +1742,18 @@ class TestNsxSearch(nsxlib_testcase.NsxClientTestCase):
|
|||
res_type, scope, tag, alert_multiple=True)
|
||||
|
||||
|
||||
class TestNsxSearchNew(TestNsxSearch):
|
||||
|
||||
def setUp(self):
|
||||
|
||||
super(TestNsxSearchNew, self).setUp()
|
||||
self.search_path = 'search/query?query=%s'
|
||||
|
||||
@staticmethod
|
||||
def get_nsxlib_version():
|
||||
return '3.0.0'
|
||||
|
||||
|
||||
class TransportZone(BaseTestResource):
|
||||
|
||||
def setUp(self):
|
||||
|
|
|
@ -91,7 +91,7 @@ class NsxLib(lib.NsxLibBase):
|
|||
self.ip_pool = resources.IpPool(
|
||||
self.client, self.nsxlib_config, nsxlib=self)
|
||||
self.load_balancer = load_balancer.LoadBalancer(
|
||||
self.client, self.nsxlib_config)
|
||||
self.client, self.nsxlib_config, nsxlib=self)
|
||||
self.trust_management = trust_management.NsxLibTrustManagement(
|
||||
self.client, self.nsxlib_config)
|
||||
self.router = router.RouterLib(
|
||||
|
@ -168,7 +168,13 @@ class NsxLib(lib.NsxLibBase):
|
|||
|
||||
def feature_supported(self, feature):
|
||||
if (version.LooseVersion(self.get_version()) >=
|
||||
version.LooseVersion(nsx_constants.NSX_VERSION_2_5_0)):
|
||||
version.LooseVersion(nsx_constants.NSX_VERSION_3_0_0)):
|
||||
# features available since 3.0.0
|
||||
if (feature == nsx_constants.FEATURE_RELAX_SCALE_VALIDATION):
|
||||
return True
|
||||
|
||||
if (version.LooseVersion(self.get_version()) >=
|
||||
version.LooseVersion(nsx_constants.NSX_VERSION_2_5_0)):
|
||||
# features available since 2.5
|
||||
if (feature == nsx_constants.FEATURE_CONTAINER_CLUSTER_INVENTORY):
|
||||
return True
|
||||
|
@ -178,7 +184,7 @@ class NsxLib(lib.NsxLibBase):
|
|||
return True
|
||||
|
||||
if (version.LooseVersion(self.get_version()) >=
|
||||
version.LooseVersion(nsx_constants.NSX_VERSION_2_4_0)):
|
||||
version.LooseVersion(nsx_constants.NSX_VERSION_2_4_0)):
|
||||
# Features available since 2.4
|
||||
if (feature == nsx_constants.FEATURE_ENS_WITH_SEC):
|
||||
return True
|
||||
|
@ -188,7 +194,7 @@ class NsxLib(lib.NsxLibBase):
|
|||
return True
|
||||
|
||||
if (version.LooseVersion(self.get_version()) >=
|
||||
version.LooseVersion(nsx_constants.NSX_VERSION_2_3_0)):
|
||||
version.LooseVersion(nsx_constants.NSX_VERSION_2_3_0)):
|
||||
# Features available since 2.3
|
||||
if (feature == nsx_constants.FEATURE_ROUTER_ALLOCATION_PROFILE):
|
||||
return True
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
# under the License.
|
||||
|
||||
import abc
|
||||
from distutils import version
|
||||
|
||||
from oslo_log import log
|
||||
import six
|
||||
|
@ -22,6 +23,7 @@ from vmware_nsxlib._i18n import _
|
|||
from vmware_nsxlib.v3 import client
|
||||
from vmware_nsxlib.v3 import cluster
|
||||
from vmware_nsxlib.v3 import exceptions
|
||||
from vmware_nsxlib.v3 import nsx_constants
|
||||
from vmware_nsxlib.v3 import utils
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
@ -80,6 +82,10 @@ class NsxLibBase(object):
|
|||
def feature_supported(self, feature):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_version(self):
|
||||
pass
|
||||
|
||||
def build_v3_api_version_tag(self):
|
||||
return self.general_apis.build_v3_api_version_tag()
|
||||
|
||||
|
@ -107,6 +113,12 @@ class NsxLibBase(object):
|
|||
url += "&page_size=%d" % page_size
|
||||
return url
|
||||
|
||||
def _get_search_url(self):
|
||||
if (version.LooseVersion(self.get_version()) >=
|
||||
version.LooseVersion(nsx_constants.NSX_VERSION_3_0_0)):
|
||||
return "search/query?query=%s"
|
||||
return "search?query=%s"
|
||||
|
||||
# TODO(abhiraut): Revisit this method to generate complex boolean
|
||||
# queries to search resources.
|
||||
def search_by_tags(self, tags, resource_type=None, cursor=None,
|
||||
|
@ -133,7 +145,7 @@ class NsxLibBase(object):
|
|||
query += " AND %s" % query_tags
|
||||
else:
|
||||
query = query_tags
|
||||
url = self._add_pagination_parameters("search?query=%s" % query,
|
||||
url = self._add_pagination_parameters(self._get_search_url() % query,
|
||||
cursor, page_size)
|
||||
|
||||
# Retry the search in case of error
|
||||
|
@ -170,7 +182,7 @@ class NsxLibBase(object):
|
|||
in attributes.items()])
|
||||
query = 'resource_type:%s' % resource_type + (
|
||||
" AND %s" % attributes_query if attributes_query else "")
|
||||
url = self._add_pagination_parameters("search?query=%s" % query,
|
||||
url = self._add_pagination_parameters(self._get_search_url() % query,
|
||||
cursor, page_size)
|
||||
|
||||
# Retry the search in case of error
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
from oslo_log import log as logging
|
||||
|
||||
from vmware_nsxlib.v3 import exceptions as nsxlib_exc
|
||||
from vmware_nsxlib.v3 import nsx_constants
|
||||
from vmware_nsxlib.v3 import utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
@ -411,6 +412,27 @@ class VirtualServer(LoadBalancerBase):
|
|||
class Service(LoadBalancerBase):
|
||||
resource = 'loadbalancer/services'
|
||||
|
||||
def _build_args(self, body, display_name=None, description=None,
|
||||
tags=None, resource_type=None, **kwargs):
|
||||
if display_name:
|
||||
body['display_name'] = display_name
|
||||
if description:
|
||||
body['description'] = description
|
||||
if tags:
|
||||
body['tags'] = tags
|
||||
if resource_type:
|
||||
body['resource_type'] = resource_type
|
||||
|
||||
if ('relax_scale_validation' in kwargs and
|
||||
not self.nsxlib.feature_supported(
|
||||
nsx_constants.FEATURE_RELAX_SCALE_VALIDATION)):
|
||||
kwargs.pop('relax_scale_validation')
|
||||
LOG.warning("Ignoring relax_scale_validation for new "
|
||||
"lb service %s: this feature is not supported.",
|
||||
display_name)
|
||||
body.update(kwargs)
|
||||
return body
|
||||
|
||||
def update_service_with_virtual_servers(self, service_id,
|
||||
virtual_server_ids):
|
||||
# Using internal method so we can access max_attempts in the decorator
|
||||
|
@ -475,8 +497,8 @@ class Service(LoadBalancerBase):
|
|||
class LoadBalancer(object):
|
||||
"""This is the class that have all load balancer resource clients"""
|
||||
|
||||
def __init__(self, client, nsxlib_config=None):
|
||||
self.service = Service(client, nsxlib_config)
|
||||
def __init__(self, client, nsxlib_config=None, nsxlib=None):
|
||||
self.service = Service(client, nsxlib_config, nsxlib)
|
||||
self.virtual_server = VirtualServer(client, nsxlib_config)
|
||||
self.pool = Pool(client, nsxlib_config)
|
||||
self.monitor = Monitor(client, nsxlib_config)
|
||||
|
|
|
@ -169,11 +169,13 @@ FEATURE_ICMP_STRICT = 'Strict list of supported ICMP types and codes'
|
|||
FEATURE_ROUTER_ALLOCATION_PROFILE = 'Router Allocation Profile'
|
||||
FEATURE_ENABLE_STANDBY_RELOCATION = 'Router Enable standby relocation'
|
||||
FEATURE_PARTIAL_UPDATES = 'Partial Update with PATCH'
|
||||
FEATURE_RELAX_SCALE_VALIDATION = 'Relax Scale Validation for LbService'
|
||||
|
||||
# Features available depending on the Policy Manager backend version
|
||||
FEATURE_NSX_POLICY = 'NSX Policy'
|
||||
FEATURE_NSX_POLICY_NETWORKING = 'NSX Policy Networking'
|
||||
FEATURE_NSX_POLICY_MDPROXY = 'NSX Policy Metadata Proxy'
|
||||
FEATURE_NSX_POLICY_GLOBAL_CONFIG = 'NSX Policy Global Config'
|
||||
|
||||
# FEATURE available depending on Inventory service backend version
|
||||
FEATURE_CONTAINER_CLUSTER_INVENTORY = 'Container Cluster Inventory'
|
||||
|
|
|
@ -20,8 +20,10 @@ from oslo_log import log
|
|||
|
||||
from vmware_nsxlib import v3
|
||||
from vmware_nsxlib.v3 import client
|
||||
from vmware_nsxlib.v3 import exceptions
|
||||
from vmware_nsxlib.v3 import lib
|
||||
from vmware_nsxlib.v3 import nsx_constants
|
||||
from vmware_nsxlib.v3 import utils as lib_utils
|
||||
|
||||
from vmware_nsxlib.v3.policy import core_defs
|
||||
from vmware_nsxlib.v3.policy import core_resources
|
||||
|
@ -120,6 +122,7 @@ class NsxPolicyLib(lib.NsxLibBase):
|
|||
self.exclude_list = core_resources.NsxPolicyExcludeListApi(*args)
|
||||
self.load_balancer = lb_resources.NsxPolicyLoadBalancerApi(*args)
|
||||
self.ipsec_vpn = ipsec_vpn_resources.NsxPolicyIpsecVpnApi(*args)
|
||||
self.global_config = core_resources.NsxPolicyGlobalConfig(*args)
|
||||
|
||||
@property
|
||||
def keepalive_section(self):
|
||||
|
@ -161,10 +164,15 @@ class NsxPolicyLib(lib.NsxLibBase):
|
|||
|
||||
if (version.LooseVersion(self.get_version()) >=
|
||||
version.LooseVersion(nsx_constants.NSX_VERSION_3_0_0)):
|
||||
# features available since 3.0.0
|
||||
if feature == nsx_constants.FEATURE_PARTIAL_UPDATES:
|
||||
return True
|
||||
if feature == nsx_constants.FEATURE_NSX_POLICY_MDPROXY:
|
||||
return True
|
||||
if (feature == nsx_constants.FEATURE_RELAX_SCALE_VALIDATION):
|
||||
return True
|
||||
if (feature == nsx_constants.FEATURE_NSX_POLICY_GLOBAL_CONFIG):
|
||||
return True
|
||||
|
||||
return (feature == nsx_constants.FEATURE_NSX_POLICY)
|
||||
|
||||
|
@ -185,3 +193,28 @@ class NsxPolicyLib(lib.NsxLibBase):
|
|||
"value": "0 */%d * * * *" % interval_min}
|
||||
body = {"keyValuePairs": [realization_config]}
|
||||
self.client.patch("system-config", body)
|
||||
|
||||
def search_resource_by_realized_id(self, realized_id, realized_type):
|
||||
"""Search resources by a realized id & type
|
||||
|
||||
:returns: a list of resource pathes matching the realized id and type.
|
||||
"""
|
||||
if not realized_type or not realized_id:
|
||||
raise exceptions.NsxSearchInvalidQuery(
|
||||
reason=_("Resource type or id was not specified"))
|
||||
query = ('resource_type:GenericPolicyRealizedResource AND '
|
||||
'realization_specific_identifier:%s AND '
|
||||
'entity_type:%s' % (realized_id, realized_type))
|
||||
url = self._get_search_url() % query
|
||||
|
||||
# Retry the search on case of error
|
||||
@lib_utils.retry_upon_exception(exceptions.NsxSearchError,
|
||||
max_attempts=self.client.max_attempts)
|
||||
def do_search(url):
|
||||
return self.client.url_get(url)
|
||||
|
||||
results = do_search(url)
|
||||
pathes = []
|
||||
for resource in results['results']:
|
||||
pathes.extend(resource.get('intent_paths', []))
|
||||
return pathes
|
||||
|
|
|
@ -31,6 +31,7 @@ PROVIDERS_PATH_PATTERN = TENANTS_PATH_PATTERN + "providers/"
|
|||
TIER0S_PATH_PATTERN = TENANTS_PATH_PATTERN + "tier-0s/"
|
||||
TIER1S_PATH_PATTERN = TENANTS_PATH_PATTERN + "tier-1s/"
|
||||
SERVICES_PATH_PATTERN = TENANTS_PATH_PATTERN + "services/"
|
||||
GLOBAL_CONFIG_PATH_PATTERN = TENANTS_PATH_PATTERN + "global-config/"
|
||||
ENFORCEMENT_POINT_PATTERN = (TENANTS_PATH_PATTERN +
|
||||
"sites/default/enforcement-points/")
|
||||
TRANSPORT_ZONE_PATTERN = ENFORCEMENT_POINT_PATTERN + "%s/transport-zones/"
|
||||
|
@ -65,14 +66,21 @@ TIER1_LOCALE_SERVICES_PATH_PATTERN = (TIER1S_PATH_PATTERN +
|
|||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class ResourceDef(object):
|
||||
def __init__(self, **kwargs):
|
||||
def __init__(self, nsx_version=None, **kwargs):
|
||||
self.attrs = kwargs
|
||||
|
||||
# nsx_version should be passed in on init if the resource has
|
||||
# version-dependant attributes. Otherwise this is ignored
|
||||
self.nsx_version = nsx_version
|
||||
|
||||
# init default tenant
|
||||
self.attrs['tenant'] = self.get_tenant()
|
||||
|
||||
self.body = {}
|
||||
|
||||
# Whether this entry needs to be deleted
|
||||
self.delete = False
|
||||
|
||||
# As of now, for some defs (ex: services) child entry is required,
|
||||
# meaning parent creation will fail without the child.
|
||||
# Unfortunately in transactional API policy still fails us, even if
|
||||
|
@ -82,6 +90,12 @@ class ResourceDef(object):
|
|||
# TODO(annak): remove this if/when policy solves this
|
||||
self.mandatory_child_def = None
|
||||
|
||||
def set_delete(self):
|
||||
self.delete = True
|
||||
|
||||
def get_delete(self):
|
||||
return self.delete
|
||||
|
||||
def get_obj_dict(self):
|
||||
body = self.body if self.body else {}
|
||||
if self.resource_type():
|
||||
|
@ -192,6 +206,41 @@ class ResourceDef(object):
|
|||
for attr in attr_list:
|
||||
self._set_attr_if_specified(body, attr)
|
||||
|
||||
# Helper to set attr in body if user specified it
|
||||
# and current nsx version supports it
|
||||
# Body name must match attr name
|
||||
def _set_attr_if_supported(self, body, attr, value=None):
|
||||
if self.has_attr(attr) and self._version_dependant_attr_supported(
|
||||
attr):
|
||||
value = value if value is not None else self.get_attr(attr)
|
||||
body[attr] = value
|
||||
|
||||
# Helper to set attrs in body if user specified them
|
||||
# and current nsx version supports it
|
||||
# Body name must match attr name
|
||||
def _set_attrs_if_supported(self, body, attr_list):
|
||||
for attr in attr_list:
|
||||
self._set_attr_if_supported(body, attr)
|
||||
|
||||
def _version_dependant_attr_supported(self, attr):
|
||||
"""Check if a version dependent attr is supported on current NSX
|
||||
|
||||
For each resource def, there could be some attributes which only exist
|
||||
on NSX after certain versions. This abstract method provides a skeleton
|
||||
to define version requirements of version-dependent attributes.
|
||||
|
||||
By design, Devs should use _set_attr_if_supported() to add any attrs
|
||||
that are only known to NSX after a certain version. This method works
|
||||
as a registry for _set_attrs_if_supported() to know the baseline
|
||||
version of each version dependent attr.
|
||||
|
||||
Non-version-dependent attributes should be added to the request body
|
||||
by using _set_attr_if_specified(). This method defaults to false since
|
||||
any version dependent attr unknown to this lib should be excluded
|
||||
for security and safety reasons.
|
||||
"""
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def get_single_entry(cls, obj_body):
|
||||
"""Return the single sub-entry from the object body.
|
||||
|
@ -790,9 +839,11 @@ class SegmentPortDef(ResourceDef):
|
|||
if address_bindings:
|
||||
body['address_bindings'] = [binding.get_obj_dict()
|
||||
for binding in address_bindings]
|
||||
if self.has_attr('attachment_type') or self.has_attr('vif_id'):
|
||||
if (self.has_attr('attachment_type') or self.has_attr('vif_id') or
|
||||
self.has_attr('hyperbus_mode')):
|
||||
if (not self.get_attr('attachment_type') and
|
||||
not self.get_attr('vif_id')):
|
||||
not self.get_attr('vif_id') and
|
||||
not self.get_attr('hyperbus_mode')):
|
||||
# detach operation
|
||||
body['attachment'] = None
|
||||
else:
|
||||
|
@ -801,6 +852,8 @@ class SegmentPortDef(ResourceDef):
|
|||
attachment['type'] = self.get_attr('attachment_type')
|
||||
if self.get_attr('vif_id'):
|
||||
attachment['id'] = self.get_attr('vif_id')
|
||||
if self.get_attr('hyperbus_mode'):
|
||||
self._set_attr_if_supported(attachment, 'hyperbus_mode')
|
||||
|
||||
self._set_attrs_if_specified(attachment,
|
||||
['context_id',
|
||||
|
@ -1347,6 +1400,17 @@ class SecurityPolicyRuleBaseDef(ResourceDef):
|
|||
body['services'] = self.get_services_path(service_ids)
|
||||
return body
|
||||
|
||||
@classmethod
|
||||
def adapt_from_rule_dict(cls, rule_dict, domain_id, map_id):
|
||||
entry_id = rule_dict.pop('id', None)
|
||||
name = rule_dict.pop('display_name', None)
|
||||
|
||||
rule_def = cls(tenant=constants.POLICY_INFRA_TENANT,
|
||||
domain_id=domain_id, map_id=map_id, entry_id=entry_id,
|
||||
name=name)
|
||||
rule_def.set_obj_dict(rule_dict)
|
||||
return rule_def
|
||||
|
||||
|
||||
class CommunicationMapEntryDef(SecurityPolicyRuleBaseDef):
|
||||
|
||||
|
@ -1785,6 +1849,28 @@ class CertificateDef(ResourceDef):
|
|||
return body
|
||||
|
||||
|
||||
class GlobalConfigDef(ResourceDef):
|
||||
|
||||
@property
|
||||
def path_pattern(self):
|
||||
return GLOBAL_CONFIG_PATH_PATTERN
|
||||
|
||||
@property
|
||||
def path_ids(self):
|
||||
# Adding dummy 2nd key to satisfy get_section_path
|
||||
# This resource has no keys, since it is a single object
|
||||
return ('tenant', 'dummy')
|
||||
|
||||
@staticmethod
|
||||
def resource_type():
|
||||
return "GlobalConfig"
|
||||
|
||||
def get_obj_dict(self):
|
||||
body = super(GlobalConfigDef, self).get_obj_dict()
|
||||
self._set_attrs_if_specified(body, ['l3_forwarding_mode'])
|
||||
return body
|
||||
|
||||
|
||||
class ExcludeListDef(ResourceDef):
|
||||
|
||||
@property
|
||||
|
|
|
@ -126,7 +126,7 @@ class NsxPolicyResourceBase(object):
|
|||
def _init_def(self, **kwargs):
|
||||
"""Helper for update function - ignore attrs without explicit value"""
|
||||
args = self._get_user_args(**kwargs)
|
||||
return self.entry_def(**args)
|
||||
return self.entry_def(nsx_version=self.version, **args)
|
||||
|
||||
def _init_parent_def(self, **kwargs):
|
||||
"""Helper for update function - ignore attrs without explicit value"""
|
||||
|
@ -136,7 +136,7 @@ class NsxPolicyResourceBase(object):
|
|||
def _get_and_update_def(self, **kwargs):
|
||||
"""Helper for update function - ignore attrs without explicit value"""
|
||||
args = self._get_user_args(**kwargs)
|
||||
resource_def = self.entry_def(**args)
|
||||
resource_def = self.entry_def(nsx_version=self.version, **args)
|
||||
body = self.policy_api.get(resource_def)
|
||||
if body:
|
||||
resource_def.set_obj_dict(body)
|
||||
|
@ -224,17 +224,23 @@ class NsxPolicyResourceBase(object):
|
|||
realization_info.get('realization_specific_identifier')):
|
||||
return realization_info['realization_specific_identifier']
|
||||
|
||||
def _get_realization_error_message(self, info):
|
||||
def _get_realization_error_message_and_code(self, info):
|
||||
error_msg = 'unknown'
|
||||
error_code = None
|
||||
related_error_codes = []
|
||||
if info.get('alarms'):
|
||||
alarm = info['alarms'][0]
|
||||
error_msg = alarm.get('message')
|
||||
if (alarm.get('error_details') and
|
||||
alarm['error_details'].get('related_errors')):
|
||||
related = alarm['error_details']['related_errors'][0]
|
||||
error_msg = '%s: %s' % (error_msg,
|
||||
related.get('error_message'))
|
||||
return error_msg
|
||||
if alarm.get('error_details'):
|
||||
error_code = alarm['error_details'].get('error_code')
|
||||
if alarm['error_details'].get('related_errors'):
|
||||
related = alarm['error_details']['related_errors']
|
||||
for err_obj in related:
|
||||
error_msg = '%s: %s' % (error_msg,
|
||||
err_obj.get('error_message'))
|
||||
if err_obj.get('error_code'):
|
||||
related_error_codes.append(err_obj['error_code'])
|
||||
return error_msg, error_code, related_error_codes
|
||||
|
||||
def _wait_until_realized(self, resource_def, entity_type=None,
|
||||
sleep=None, max_attempts=None):
|
||||
|
@ -255,11 +261,13 @@ class NsxPolicyResourceBase(object):
|
|||
if info['state'] == constants.STATE_REALIZED:
|
||||
return info
|
||||
if info['state'] == constants.STATE_ERROR:
|
||||
error_msg = self._get_realization_error_message(info)
|
||||
error_msg, error_code, related_error_codes = \
|
||||
self._get_realization_error_message_and_code(info)
|
||||
raise exceptions.RealizationErrorStateError(
|
||||
resource_type=resource_def.resource_type(),
|
||||
resource_id=resource_def.get_id(),
|
||||
error=error_msg)
|
||||
error=error_msg, error_code=error_code,
|
||||
related_error_codes=related_error_codes)
|
||||
|
||||
try:
|
||||
return get_info()
|
||||
|
@ -303,11 +311,13 @@ class NsxPolicyResourceBase(object):
|
|||
if resource_def and test_num % check_status == (check_status - 1):
|
||||
info = self._get_realization_info(resource_def)
|
||||
if info and info['state'] == constants.STATE_ERROR:
|
||||
error_msg = self._get_realization_error_message(info)
|
||||
error_msg, error_code, related_error_codes = \
|
||||
self._get_realization_error_message_and_code(info)
|
||||
raise exceptions.RealizationErrorStateError(
|
||||
resource_type=resource_def.resource_type(),
|
||||
resource_id=resource_def.get_id(),
|
||||
error=error_msg)
|
||||
error=error_msg, error_code=error_code,
|
||||
related_error_codes=related_error_codes)
|
||||
if (info and info['state'] == constants.STATE_REALIZED and
|
||||
info.get('realization_specific_identifier')):
|
||||
LOG.warning("Realization ID for %s was not found via "
|
||||
|
@ -1527,6 +1537,7 @@ class NsxPolicyTier0NatRuleApi(NsxPolicyResourceBase):
|
|||
source_network=IGNORE,
|
||||
destination_network=IGNORE,
|
||||
translated_network=IGNORE,
|
||||
firewall_match=IGNORE,
|
||||
action=IGNORE,
|
||||
sequence_number=IGNORE,
|
||||
log=IGNORE,
|
||||
|
@ -1541,6 +1552,7 @@ class NsxPolicyTier0NatRuleApi(NsxPolicyResourceBase):
|
|||
source_network=source_network,
|
||||
destination_network=destination_network,
|
||||
translated_network=translated_network,
|
||||
firewall_match=firewall_match,
|
||||
action=action,
|
||||
sequence_number=sequence_number,
|
||||
log=log,
|
||||
|
@ -1615,6 +1627,7 @@ class NsxPolicyTier1NatRuleApi(NsxPolicyResourceBase):
|
|||
source_network=IGNORE,
|
||||
destination_network=IGNORE,
|
||||
translated_network=IGNORE,
|
||||
firewall_match=IGNORE,
|
||||
action=IGNORE,
|
||||
sequence_number=IGNORE,
|
||||
log=IGNORE,
|
||||
|
@ -1629,6 +1642,7 @@ class NsxPolicyTier1NatRuleApi(NsxPolicyResourceBase):
|
|||
source_network=source_network,
|
||||
destination_network=destination_network,
|
||||
translated_network=translated_network,
|
||||
firewall_match=firewall_match,
|
||||
action=action,
|
||||
sequence_number=sequence_number,
|
||||
log=log,
|
||||
|
@ -2680,6 +2694,11 @@ class NsxPolicyIpPoolApi(NsxPolicyResourceBase):
|
|||
tenant=tenant)
|
||||
return self.policy_api.get(ip_subnet_def)
|
||||
|
||||
def get_realization_info(self, ip_pool_id, entity_type=None,
|
||||
tenant=constants.POLICY_INFRA_TENANT):
|
||||
ip_pool_def = self.entry_def(ip_pool_id=ip_pool_id, tenant=tenant)
|
||||
return self._get_realization_info(ip_pool_def, entity_type=entity_type)
|
||||
|
||||
def get_ip_subnet_realization_info(
|
||||
self, ip_pool_id, ip_subnet_id,
|
||||
entity_type=None,
|
||||
|
@ -2737,6 +2756,14 @@ class NsxPolicyIpPoolApi(NsxPolicyResourceBase):
|
|||
except IndexError:
|
||||
return
|
||||
|
||||
def wait_until_realized(self, ip_pool_id, entity_type=None,
|
||||
tenant=constants.POLICY_INFRA_TENANT,
|
||||
sleep=None, max_attempts=None):
|
||||
ip_pool_def = self.entry_def(ip_pool_id=ip_pool_id, tenant=tenant)
|
||||
return self._wait_until_realized(ip_pool_def, entity_type=entity_type,
|
||||
sleep=sleep,
|
||||
max_attempts=max_attempts)
|
||||
|
||||
|
||||
class NsxPolicySecurityPolicyBaseApi(NsxPolicyResourceBase):
|
||||
|
||||
|
@ -2889,7 +2916,7 @@ class NsxPolicySecurityPolicyBaseApi(NsxPolicyResourceBase):
|
|||
delay=self.nsxlib_config.realization_wait_sec,
|
||||
max_attempts=self.nsxlib_config.realization_max_attempts)
|
||||
def _do_create_with_retry():
|
||||
self.policy_api.create_with_parent(map_def, entries)
|
||||
self._create_or_store(map_def, entries)
|
||||
|
||||
_do_create_with_retry()
|
||||
return map_id
|
||||
|
@ -3077,34 +3104,63 @@ class NsxPolicySecurityPolicyBaseApi(NsxPolicyResourceBase):
|
|||
map_sequence_number=map_sequence_number)
|
||||
map_path = map_def.get_resource_path()
|
||||
|
||||
def _overwrite_entries(old_entries, new_entries):
|
||||
def _overwrite_entries(old_entries, new_entries, transaction):
|
||||
# Replace old entries with new entries, but copy additional
|
||||
# attributes from old entries for those kept in new entries.
|
||||
# attributes from old entries for those kept in new entries
|
||||
# and marked the unwanted ones in the old entries as deleted
|
||||
# if it is in the transaction call.
|
||||
old_rules = {entry["id"]: entry for entry in old_entries}
|
||||
new_rules = []
|
||||
replaced_entries = []
|
||||
for entry in new_entries:
|
||||
rule_id = entry.get_id()
|
||||
new_rule = entry.get_obj_dict()
|
||||
old_rule = old_rules.get(rule_id)
|
||||
if old_rule:
|
||||
old_rules.pop(rule_id)
|
||||
for key, value in old_rule.items():
|
||||
if key not in new_rule:
|
||||
new_rule[key] = value
|
||||
new_rules.append(new_rule)
|
||||
return new_rules
|
||||
replaced_entries.append(
|
||||
self.entry_def.adapt_from_rule_dict(
|
||||
new_rule, domain_id, map_id))
|
||||
|
||||
if transaction:
|
||||
replaced_entries.extend(
|
||||
_mark_delete_entries(old_rules.values()))
|
||||
return replaced_entries
|
||||
|
||||
def _mark_delete_entries(delete_rule_dicts):
|
||||
delete_entries = []
|
||||
for delete_rule_dict in delete_rule_dicts:
|
||||
delete_entry = self.entry_def.adapt_from_rule_dict(
|
||||
delete_rule_dict, domain_id, map_id)
|
||||
delete_entry.set_delete()
|
||||
delete_entries.append(delete_entry)
|
||||
return delete_entries
|
||||
|
||||
@utils.retry_upon_exception(
|
||||
exceptions.StaleRevision,
|
||||
max_attempts=self.policy_api.client.max_attempts)
|
||||
def _update():
|
||||
transaction = trans.NsxPolicyTransaction.get_current()
|
||||
# Get the current data of communication map & its entries
|
||||
comm_map = self.policy_api.get(map_def)
|
||||
replaced_entries = None
|
||||
ignore_entries = (entries == IGNORE)
|
||||
if not ignore_entries:
|
||||
replaced_entries = _overwrite_entries(comm_map['rules'],
|
||||
entries, transaction)
|
||||
comm_map.pop('rules')
|
||||
map_def.set_obj_dict(comm_map)
|
||||
body = map_def.get_obj_dict()
|
||||
if entries != IGNORE:
|
||||
body['rules'] = _overwrite_entries(comm_map['rules'], entries)
|
||||
# Update the entire map at the NSX
|
||||
self.policy_api.client.update(map_path, body)
|
||||
if transaction:
|
||||
self._create_or_store(map_def, replaced_entries)
|
||||
else:
|
||||
body = map_def.get_obj_dict()
|
||||
if not ignore_entries:
|
||||
body['rules'] = [rule.get_obj_dict() for rule in
|
||||
replaced_entries]
|
||||
self.policy_api.client.update(map_path, body)
|
||||
|
||||
_update()
|
||||
|
||||
|
@ -3926,3 +3982,46 @@ class NsxPolicyExcludeListApi(NsxPolicyResourceBase):
|
|||
raise exceptions.ManagerError(details=err_msg)
|
||||
|
||||
# TODO(asarfaty): Add support for add/remove member
|
||||
|
||||
|
||||
class NsxPolicyGlobalConfig(NsxPolicyResourceBase):
|
||||
|
||||
@property
|
||||
def entry_def(self):
|
||||
return core_defs.GlobalConfigDef
|
||||
|
||||
def create_or_overwrite(self, tenant=constants.POLICY_INFRA_TENANT):
|
||||
err_msg = (_("This action is not supported"))
|
||||
raise exceptions.ManagerError(details=err_msg)
|
||||
|
||||
def delete(self, tenant=constants.POLICY_INFRA_TENANT):
|
||||
err_msg = (_("This action is not supported"))
|
||||
raise exceptions.ManagerError(details=err_msg)
|
||||
|
||||
def get(self, tenant=constants.POLICY_INFRA_TENANT, silent=False):
|
||||
global_config_def = self.entry_def(tenant=tenant)
|
||||
return self.policy_api.get(global_config_def, silent=silent)
|
||||
|
||||
def list(self, tenant=constants.POLICY_INFRA_TENANT):
|
||||
err_msg = (_("This action is not supported"))
|
||||
raise exceptions.ManagerError(details=err_msg)
|
||||
|
||||
def update(self, members=IGNORE,
|
||||
tenant=constants.POLICY_INFRA_TENANT):
|
||||
err_msg = (_("This action is not supported"))
|
||||
raise exceptions.ManagerError(details=err_msg)
|
||||
|
||||
def _set_l3_forwarding_mode(self, mode, tenant):
|
||||
# Using PUT as PATCH is not supported for this API
|
||||
config = self.get()
|
||||
if config['l3_forwarding_mode'] != mode:
|
||||
config['l3_forwarding_mode'] = mode
|
||||
config_def = self.entry_def(tenant=tenant)
|
||||
path = config_def.get_resource_path()
|
||||
self.policy_api.client.update(path, config)
|
||||
|
||||
def enable_ipv6(self, tenant=constants.POLICY_INFRA_TENANT):
|
||||
return self._set_l3_forwarding_mode('IPV4_AND_IPV6', tenant)
|
||||
|
||||
def disable_ipv6(self, tenant=constants.POLICY_INFRA_TENANT):
|
||||
return self._set_l3_forwarding_mode('IPV4_ONLY', tenant)
|
||||
|
|
|
@ -14,9 +14,15 @@
|
|||
# under the License.
|
||||
#
|
||||
|
||||
from distutils import version
|
||||
|
||||
from oslo_log import log as logging
|
||||
from vmware_nsxlib.v3 import nsx_constants
|
||||
from vmware_nsxlib.v3.policy import constants
|
||||
from vmware_nsxlib.v3.policy.core_defs import ResourceDef
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
TENANTS_PATH_PATTERN = "%s/"
|
||||
LB_VIRTUAL_SERVERS_PATH_PATTERN = TENANTS_PATH_PATTERN + "lb-virtual-servers/"
|
||||
LB_SERVICES_PATH_PATTERN = TENANTS_PATH_PATTERN + "lb-services/"
|
||||
|
@ -379,8 +385,24 @@ class LBServiceDef(ResourceDef):
|
|||
def get_obj_dict(self):
|
||||
body = super(LBServiceDef, self).get_obj_dict()
|
||||
self._set_attrs_if_specified(body, ['size', 'connectivity_path'])
|
||||
self._set_attrs_if_supported(body, ['relax_scale_validation'])
|
||||
return body
|
||||
|
||||
def _version_dependant_attr_supported(self, attr):
|
||||
if (version.LooseVersion(self.nsx_version) >=
|
||||
version.LooseVersion(nsx_constants.NSX_VERSION_3_0_0)):
|
||||
if attr == 'relax_scale_validation':
|
||||
return True
|
||||
else:
|
||||
LOG.warning(
|
||||
"Ignoring %s for %s %s: this feature is not supported."
|
||||
"Current NSX version: %s. Minimum supported version: %s",
|
||||
attr, self.resource_type, self.attrs.get('name', ''),
|
||||
self.nsx_version, nsx_constants.NSX_VERSION_3_0_0)
|
||||
return False
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class LBServiceStatisticsDef(ResourceDef):
|
||||
|
||||
|
|
|
@ -558,6 +558,7 @@ class NsxPolicyLoadBalancerPoolApi(NsxPolicyResourceBase):
|
|||
|
||||
class NsxPolicyLoadBalancerServiceApi(NsxPolicyResourceBase):
|
||||
"""NSX Policy LBService."""
|
||||
|
||||
@property
|
||||
def entry_def(self):
|
||||
return lb_defs.LBServiceDef
|
||||
|
@ -567,6 +568,7 @@ class NsxPolicyLoadBalancerServiceApi(NsxPolicyResourceBase):
|
|||
tags=IGNORE,
|
||||
size=IGNORE,
|
||||
connectivity_path=IGNORE,
|
||||
relax_scale_validation=IGNORE,
|
||||
tenant=constants.POLICY_INFRA_TENANT):
|
||||
lb_service_id = self._init_obj_uuid(lb_service_id)
|
||||
lb_service_def = self._init_def(
|
||||
|
@ -576,6 +578,7 @@ class NsxPolicyLoadBalancerServiceApi(NsxPolicyResourceBase):
|
|||
tags=tags,
|
||||
size=size,
|
||||
connectivity_path=connectivity_path,
|
||||
relax_scale_validation=relax_scale_validation,
|
||||
tenant=tenant)
|
||||
|
||||
self._create_or_store(lb_service_def)
|
||||
|
@ -599,14 +602,18 @@ class NsxPolicyLoadBalancerServiceApi(NsxPolicyResourceBase):
|
|||
def update(self, lb_service_id, name=IGNORE,
|
||||
description=IGNORE, tags=IGNORE,
|
||||
size=IGNORE, connectivity_path=IGNORE,
|
||||
relax_scale_validation=IGNORE,
|
||||
tenant=constants.POLICY_INFRA_TENANT):
|
||||
self._update(lb_service_id=lb_service_id,
|
||||
name=name,
|
||||
description=description,
|
||||
tags=tags,
|
||||
size=size,
|
||||
connectivity_path=connectivity_path,
|
||||
tenant=tenant)
|
||||
|
||||
self._update(
|
||||
lb_service_id=lb_service_id,
|
||||
name=name,
|
||||
description=description,
|
||||
tags=tags,
|
||||
size=size,
|
||||
connectivity_path=connectivity_path,
|
||||
relax_scale_validation=relax_scale_validation,
|
||||
tenant=tenant)
|
||||
|
||||
def get_statistics(self, lb_service_id,
|
||||
tenant=constants.POLICY_INFRA_TENANT):
|
||||
|
@ -646,6 +653,15 @@ class NsxPolicyLoadBalancerServiceApi(NsxPolicyResourceBase):
|
|||
tenant=tenant)
|
||||
return profile_def.get_resource_full_path()
|
||||
|
||||
def wait_until_realized(self, lb_service_id, entity_type='LbServiceDto',
|
||||
tenant=constants.POLICY_INFRA_TENANT,
|
||||
sleep=None, max_attempts=None):
|
||||
lb_service_def = self.entry_def(
|
||||
lb_service_id=lb_service_id, tenant=tenant)
|
||||
return self._wait_until_realized(
|
||||
lb_service_def, entity_type=entity_type,
|
||||
sleep=sleep, max_attempts=max_attempts)
|
||||
|
||||
|
||||
class NsxPolicyLoadBalancerVirtualServerAPI(NsxPolicyResourceBase):
|
||||
"""NSX Policy LoadBalancerVirtualServers"""
|
||||
|
@ -884,6 +900,15 @@ class NsxPolicyLoadBalancerVirtualServerAPI(NsxPolicyResourceBase):
|
|||
tenant=tenant)
|
||||
return profile_def.get_resource_full_path()
|
||||
|
||||
def wait_until_realized(self, virtual_server_id, entity_type=None,
|
||||
tenant=constants.POLICY_INFRA_TENANT,
|
||||
sleep=None, max_attempts=None):
|
||||
lbvs_def = self.entry_def(
|
||||
virtual_server_id=virtual_server_id, tenant=tenant)
|
||||
return self._wait_until_realized(
|
||||
lbvs_def, entity_type=entity_type,
|
||||
sleep=sleep, max_attempts=max_attempts)
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class NsxPolicyLBMonitorProfileBase(NsxPolicyResourceBase):
|
||||
|
|
|
@ -67,7 +67,10 @@ class NsxPolicyTransaction(object):
|
|||
|
||||
self.client = client
|
||||
# TODO(annak): raise exception for different tenants
|
||||
self.defs.append(resource_def)
|
||||
if isinstance(resource_def, list):
|
||||
self.defs.extend(resource_def)
|
||||
else:
|
||||
self.defs.append(resource_def)
|
||||
|
||||
def _sort_defs(self):
|
||||
sorted_defs = []
|
||||
|
@ -96,9 +99,12 @@ 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 _build_wrapper_dict(self, resource_class, node, delete=False):
|
||||
wrapper_dict = {'resource_type': 'Child%s' % resource_class,
|
||||
resource_class: node}
|
||||
if delete:
|
||||
wrapper_dict.update({'marked_for_delete': True})
|
||||
return wrapper_dict
|
||||
|
||||
def _find_parent_in_dict(self, d, resource_def, level=1):
|
||||
|
||||
|
@ -179,8 +185,9 @@ class NsxPolicyTransaction(object):
|
|||
child_dict_key = child_def.get_last_section_dict_key
|
||||
node[child_dict_key] = [child_def.get_obj_dict()]
|
||||
parent_dict['children'].append(
|
||||
self._build_wrapper_dict(resource_class, node))
|
||||
|
||||
self._build_wrapper_dict(resource_class,
|
||||
node,
|
||||
resource_def.get_delete()))
|
||||
if body:
|
||||
headers = {'nsx-enable-partial-patch': 'true'}
|
||||
self.client.patch(url, body, headers=headers)
|
||||
|
|
Loading…
Reference in New Issue