NFP - Enhancements and fixes to master NFP

a) To create policy target
for LB VIP after successful launch of LB service.
It also provides support for building node configuration data
to VPN service.
b) Service Orchestrator fix to do proper cleanup
when OTC service vm reports HEAT_HANDLED notification.
c) Node driver fix to gracefully handle exception when
external policy is not passed for LB provider
d) Device orchestrator change to use common method
for preparing ports info.

Change-Id: I8e221b390c68e69887e574e7ffa98b64e8e6bf8a
Implements: blueprint gbp-network-services-framework
This commit is contained in:
Rajendra Machani
2016-07-27 12:39:07 +05:30
committed by Hemanth Ravi
parent a86db37372
commit cd9fbbab34
7 changed files with 1601 additions and 50 deletions

View File

@@ -350,12 +350,16 @@ class NFPNodeDriver(driver_base.NodeDriverBase):
raise e
def create(self, context):
context._plugin_context = self._get_resource_owner_context(
context._plugin_context)
network_function_id = self._create_network_function(context)
self._set_node_instance_network_function_map(
context.plugin_session, context.current_node['id'],
context.instance['id'], network_function_id)
try:
context._plugin_context = self._get_resource_owner_context(
context._plugin_context)
network_function_id = self._create_network_function(context)
self._set_node_instance_network_function_map(
context.plugin_session, context.current_node['id'],
context.instance['id'], network_function_id)
except Exception as e:
self.sc_node_count -= 1
raise e
# Check for NF status in a separate thread
LOG.debug("Spawning thread for nf ACTIVE poll")
@@ -707,7 +711,6 @@ class NFPNodeDriver(driver_base.NodeDriverBase):
for spec in current_specs:
node_list.extend(spec['nodes'])
self.sc_node_count = len(node_list)
for node_id in node_list:
node_info = context.sc_plugin.get_servicechain_node(
context.plugin_context, node_id)
@@ -734,6 +737,8 @@ class NFPNodeDriver(driver_base.NodeDriverBase):
raise InvalidNodeOrderInChain(
node_order=allowed_chain_combinations)
self.sc_node_count = len(node_list)
def _get_consumers_for_provider(self, context, provider):
'''
{

View File

@@ -0,0 +1,739 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""This module has the input data for heat_driver UTs."""
class DummyDictionaries(object):
"""Implements the input data for heat_driver UTs.
This class holds the input data that are required in
testing the heat_driver test cases.
"""
DEFAULT_LB_CONFIG = {
u'heat_template_version': u'2013-05-23',
u'description': u'Configuration for Haproxy Neutron LB service',
u'parameters': {
u'Subnet': {
u'type': u'string',
u'description': u'Pool Subnet-CIDR, on which VIP port created'
},
u'vip_ip': {
u'type': u'string',
u'description': u'VIP IP Address'
},
u'service_chain_metadata': {
u'type': u'string',
u'description': u'sc metadata'
}
},
u'resources': {
u'LoadBalancerPool': {
u'type': u'OS::Neutron::Pool',
u'properties': {
u'lb_method': u'ROUND_ROBIN',
u'protocol': u'TCP',
u'name': u'Haproxy pool-lb-chain',
u'admin_state_up': True,
u'subnet_id': {
u'get_param': u'Subnet'
},
u'vip': {
u'subnet': {
u'get_param': u'Subnet'
},
u'description': {
u'get_param': u'service_chain_metadata'
},
u'admin_state_up': True,
u'connection_limit': -1,
u'address': {
u'get_param': u'vip_ip'
},
u'protocol_port': 3939,
u'name': u'LoadBalancerPool vip-lb-chain'
},
u'provider': u'haproxy_on_vm',
u'monitors': [{u'get_resource': u'HealthMonitor'}],
u'description': u'Haproxy pool from template'
}
},
u'HealthMonitor': {
u'type': u'OS::Neutron::HealthMonitor',
u'properties': {
u'delay': 20,
u'max_retries': 5,
u'type': u'PING',
u'timeout': 10,
u'admin_state_up': True
}
},
u'LoadBalancer': {
u'type': u'OS::Neutron::LoadBalancer',
u'properties': {
u'protocol_port': 101,
u'pool_id': {
u'get_resource': u'LoadBalancerPool'
}
}
}
}
}
DEFAULT_FW_CONFIG = {
u'heat_template_version': u'2013-05-23',
u'description': u'Template to deploy firewall',
u'resources': {
u'sc_firewall_rule3': {
u'type': u'OS::Neutron::FirewallRule',
u'properties': {
u'action': u'allow',
u'destination_port': u'82',
u'protocol': u'tcp', u'name': u'Rule_3'
}
},
u'sc_firewall_rule2': {
u'type': u'OS::Neutron::FirewallRule',
u'properties': {
u'action': u'allow',
u'destination_port': u'81',
u'protocol': u'tcp', u'name': u'Rule_2'
}
},
u'sc_firewall_rule1': {
u'type': u'OS::Neutron::FirewallRule',
u'properties': {
u'action': u'allow',
u'destination_port': u'80',
u'protocol': u'tcp',
u'name': u'Rule_1'
}
},
u'sc_firewall_rule0': {
u'type': u'OS::Neutron::FirewallRule',
u'properties': {
u'action': u'allow',
u'destination_port': u'22',
u'protocol': u'tcp', u'name': u'Rule_0'
}
},
u'sc_firewall_rule4': {
u'type': u'OS::Neutron::FirewallRule',
u'properties': {
u'action': u'allow',
u'protocol': u'icmp',
u'name': u'Rule_4'
}
},
u'sc_firewall_policy': {
u'type': u'OS::Neutron::FirewallPolicy',
u'properties': {
u'name': u'',
u'firewall_rules': [
{u'get_resource': u'sc_firewall_rule0'},
{u'get_resource': u'sc_firewall_rule1'},
{u'get_resource': u'sc_firewall_rule2'},
{u'get_resource': u'sc_firewall_rule3'},
{u'get_resource': u'sc_firewall_rule4'}]
}
},
u'sc_firewall': {
u'type': u'OS::Neutron::Firewall',
u'properties': {
u'firewall_policy_id': {
u'get_resource': u'sc_firewall_policy'
},
u'name': u'serviceVM_infra_FW',
u'description': {u'insert_type': u'east_west'}
}
}
}
}
DEFAULT_VPN_CONFIG = {
u'resources': {
u'IKEPolicy': {
u'type': u'OS::Neutron::IKEPolicy',
u'properties': {
u'name': u'IKEPolicy',
u'auth_algorithm': u'sha1',
u'encryption_algorithm': u'3des',
u'pfs': u'group5',
u'lifetime': {
u'units': u'seconds',
u'value': 3600
},
u'ike_version': u'v1',
u'phase1_negotiation_mode': u'main'
}
},
u'VPNService': {
u'type': u'OS::Neutron::VPNService',
u'properties': {
u'router_id': {
u'get_param': u'RouterId'
},
u'subnet_id': {
u'get_param': u'Subnet'
},
u'admin_state_up': u'true',
u'description': {
u'get_param': u'ServiceDescription'
},
u'name': u'VPNService'
}
},
u'site_to_site_connection1': {
u'type': u'OS::Neutron::IPsecSiteConnection',
u'properties': {
u'psk': u'secret',
u'initiator': u'bi-directional',
u'name': u'site_to_site_connection1',
u'admin_state_up': u'true',
'description':
u'fip=1.103.1.20;tunnel_local_cidr=11.0.1.0/24;\
user_access_ip=1.103.2.20;fixed_ip=192.168.0.3;\
standby_fip=1.103.1.21;service_vendor=vyos;\
stitching_cidr=192.168.0.0/28;\
stitching_gateway=192.168.0.1;mgmt_gw_ip=120.0.0.1',
u'peer_cidrs': [u'11.0.0.0/24'],
u'mtu': 1500,
u'ikepolicy_id': {
u'get_resource': u'IKEPolicy'
},
u'dpd': {
u'interval': 30,
u'actions': u'hold',
u'timeout': 120
},
u'vpnservice_id': {
u'get_resource': u'VPNService'
},
u'peer_address': u'1.103.2.88',
u'peer_id': u'1.103.2.88',
u'ipsecpolicy_id': {
u'get_resource': u'IPsecPolicy'
}
}
},
u'IPsecPolicy': {
u'type': u'OS::Neutron::IPsecPolicy',
u'properties': {
u'name': u'IPsecPolicy',
u'transform_protocol': u'esp',
u'auth_algorithm': u'sha1',
u'encapsulation_mode': u'tunnel',
u'encryption_algorithm': u'3des',
u'pfs': u'group5',
u'lifetime': {
u'units': u'seconds',
u'value': 3600
}
}
}
}
}
appended_sc_firewall_policy = {
u'type': u'OS::Neutron::FirewallPolicy',
u'properties': {
u'name': u'',
u'firewall_rules': [
{
u'get_resource': u'sc_firewall_rule0'
},
{u'get_resource': u'sc_firewall_rule1'},
{u'get_resource': u'sc_firewall_rule2'},
{u'get_resource': u'sc_firewall_rule3'},
{u'get_resource': u'sc_firewall_rule4'},
{'get_resource': 'node_driver_rule_2b86019a-45f7-44_1'},
{'get_resource': 'node_driver_rule_2b86019a-45f7-44_2'},
{'get_resource': 'node_driver_rule_2b86019a-45f7-44_3'},
{'get_resource': 'node_driver_rule_2b86019a-45f7-44_4'},
{'get_resource': 'node_driver_rule_2b86019a-45f7-44_5'},
]
}
}
updated_sc_firewall_policy = {
u'type': u'OS::Neutron::FirewallPolicy',
u'properties': {
u'name': u'-fw_redirect',
u'firewall_rules': [
{'get_resource': u'node_driver_rule_af6a8a58-1e25-49_1'},
{'get_resource': u'node_driver_rule_af6a8a58-1e25-49_2'},
{'get_resource': u'node_driver_rule_af6a8a58-1e25-49_3'},
{'get_resource': u'node_driver_rule_af6a8a58-1e25-49_4'},
{'get_resource': u'node_driver_rule_af6a8a58-1e25-49_5'},
]
}
}
updated_template_sc_firewall_policy = {
u'type': u'OS::Neutron::FirewallPolicy',
u'properties': {
u'name': u'',
u'firewall_rules': [
{'get_resource': u'node_driver_rule_af6a8a58-1e25-49_1'},
{'get_resource': u'node_driver_rule_af6a8a58-1e25-49_2'},
{'get_resource': u'node_driver_rule_af6a8a58-1e25-49_3'},
{'get_resource': u'node_driver_rule_af6a8a58-1e25-49_4'},
{'get_resource': u'node_driver_rule_af6a8a58-1e25-49_5'},
]
}
}
policy_targets = {
'policy_targets': [
{'name': 'provider_0132c_00b93',
'port_id': 'dde7d849-4c7c-4b48-8c21-f3f52c646fbe',
'id': "dde7d849-4c7c-4b48-8c21-f3f52c646fbf",
'policy_target_group_id': "dde7d849-4c7c-4b48-8c21-f3f52c646fbg"}]
}
policy_target = {
'policy_target': {
'name': 'service_target_provider_0132c_00b93'
}
}
port_info = {
'port': {
u'status': u'ACTIVE',
u'binding:host_id': u'LibertyCompute',
u'name': u'',
u'allowed_address_pairs': [],
u'admin_state_up': True,
u'network_id': u'2286b432-a443-4cd3-be49-e354f531abe3',
u'dns_name': u'',
u'extra_dhcp_opts': [],
u'mac_address': u'fa:16:3e:43:34:33',
u'dns_assignment': [
{u'hostname': u'host-42-0-0-13',
u'ip_address': u'42.0.0.13',
u'fqdn': u'host-42-0-0-13.openstacklocal.'
}],
u'binding:vif_details': {
u'port_filter': True,
u'ovs_hybrid_plug': True
},
u'binding:vif_type': u'ovs',
u'device_owner': u'compute:nova',
u'tenant_id': u'f6b09b7a590642d8ac6de73df0ab0686',
u'binding:profile': {},
u'binding:vnic_type': u'normal',
u'fixed_ips': [
{u'subnet_id': u'b31cdafe-bdf3-4c19-b768-34d623d77d6c',
u'ip_address': u'42.0.0.13'}],
u'id': u'dde7d849-4c7c-4b48-8c21-f3f52c646fbe',
u'security_groups': [u'ad3b95a4-b5ce-4a95-9add-6ef2ee797e72'],
u'device_id': u'36e9a6d9-ea04-4627-93c5-6f708368c070'
}
}
provider_ptg = {
u'shared': False,
u'subnets': [u'a2702d68-6deb-425c-a266-e27b349e00ce'],
u'proxy_group_id': None,
u'description': u'',
u'consumed_policy_rule_sets': [],
u'network_service_policy_id': u'0cdf2cba-90f8-44da-84a5-876e582f6e35',
u'tenant_id': u'8ae6701128994ab281dde6b92207bb19',
u'service_management': False,
u'provided_policy_rule_sets': ['7d4b1ef2-eb80-415d-ad13-abf0ea0c52f3'],
u'policy_targets': [
{'name': 'provider_0132c_00b93',
'port_id': 'dde7d849-4c7c-4b48-8c21-f3f52c646fbe'}],
u'proxy_type': None,
u'proxied_group_id': None,
u'l2_policy_id': u'120aa972-1b58-418d-aa5b-1d2f96612c49',
u'id': u'af6a8a58-1e25-49c4-97a3-d5f50b3aa04b',
u'name': u'fw_redirect'
}
consumer_ptg = {
u'shared': False,
u'subnets': [u'a2702d68-6deb-425c-a266-e27b349e00ce'],
u'proxy_group_id': None,
u'description': u'',
u'consumed_policy_rule_sets': ['7d4b1ef2-eb80-415d-ad13-abf0ea0c52f3'],
u'network_service_policy_id': u'0cdf2cba-90f8-44da-84a5-876e582f6e35',
u'tenant_id': u'8ae6701128994ab281dde6b92207bb19',
u'service_management': False,
u'provided_policy_rule_sets': [],
u'policy_targets': [
{'name': 'provider_0132c_00b93',
'port_id': 'dde7d849-4c7c-4b48-8c21-f3f52c646fbe'}],
u'proxy_type': None,
u'proxied_group_id': None,
u'l2_policy_id': u'120aa972-1b58-418d-aa5b-1d2f96612c49',
u'id': u'af6a8a58-1e25-49c4-97a3-d5f50b3aa04b',
u'name': u'fw_redirect'
}
l3_policies = {
u'l3_policies': [
{u'tenant_id': '8ae6701128994ab281dde6b92207bb19',
u'name': u'remote-vpn-client-pool-cidr-l3policy'}]
}
policy_rule_sets = {
u'policy_rule_sets': [
{u'id': u'7d4b1ef2-eb80-415d-ad13-abf0ea0c52f3',
u'name': u'fw_redirect',
u'policy_rules': [u'493788ad-2b9a-47b1-b04d-9096d4057fb5'],
u'tenant_id': u'8ae6701128994ab281dde6b92207bb19',
u'shared': False,
u'consuming_policy_target_groups':
[u'af6a8a58-1e25-49c4-97a3-d5f50b3aa04b'],
u'consuming_external_policies': None}]
}
policy_rules = {
u'policy_rules': [
{u'id': u'493788ad-2b9a-47b1-b04d-9096d4057fb5',
u'name': u'fw_redirect',
u'policy_actions': [u'0bab5fa6-4f89-4e15-8363-dacc7d825466'],
u'policy_classifier_id': u'8e5fc80f-7544-484c-82d0-2a5794c10664',
u'tenant_id': u'8ae6701128994ab281dde6b92207bb19',
u'shared': False}]
}
policy_actions = {
u'policy_actions': [
{u'id': u'0bab5fa6-4f89-4e15-8363-dacc7d825466',
u'name': u'fw_redirect',
u'action_value': u'1e83b288-4b56-4851-83e2-69c4365aa8e5',
u'action_type': u'redirect',
u'tenant_id': u'8ae6701128994ab281dde6b92207bb19',
u'shared': False}]
}
policy_target_groups = {
u'policy_target_groups': [
{u'shared': False,
u'subnets': [u'a2702d68-6deb-425c-a266-e27b349e00ce'],
u'proxy_group_id': None,
u'description': u'',
u'consumed_policy_rule_sets': [],
u'network_service_policy_id':
u'0cdf2cba-90f8-44da-84a5-876e582f6e35',
u'tenant_id': u'8ae6701128994ab281dde6b92207bb19',
u'service_management': False,
u'provided_policy_rule_sets':
['7d4b1ef2-eb80-415d-ad13-abf0ea0c52f3'],
u'policy_targets': [
{'name': 'provider_0132c_00b93',
'port_id': 'dde7d849-4c7c-4b48-8c21-f3f52c646fbe'}],
u'proxy_type': None,
u'proxied_group_id': None,
u'l2_policy_id': u'120aa972-1b58-418d-aa5b-1d2f96612c49',
u'id': u'af6a8a58-1e25-49c4-97a3-d5f50b3aa04b',
u'name': u'fw_redirect'}]
}
subnet_info = {
u'subnet': {
u'name': u'lb-subnet',
u'enable_dhcp': True,
u'network_id': u'2286b432-a443-4cd3-be49-e354f531abe3',
u'tenant_id': u'f6b09b7a590642d8ac6de73df0ab0686',
u'dns_nameservers': [],
u'ipv6_ra_mode': None,
u'allocation_pools': [{
u'start': u'42.0.0.2', u'end': u'42.0.0.254'}],
u'gateway_ip': u'42.0.0.1',
u'ipv6_address_mode': None,
u'ip_version': 4,
u'host_routes': [],
u'cidr': u'42.0.0.0/24',
u'id': u'b31cdafe-bdf3-4c19-b768-34d623d77d6c',
u'subnetpool_id': None
}
}
subnets_info = {
u'subnets': [
{u'name': u'lb-subnet',
u'enable_dhcp': True,
u'network_id': u'2286b432-a443-4cd3-be49-e354f531abe3',
u'tenant_id': u'f6b09b7a590642d8ac6de73df0ab0686',
u'dns_nameservers': [],
u'ipv6_ra_mode': None,
u'allocation_pools': [{
u'start': u'42.0.0.2', u'end': u'42.0.0.254'}],
u'gateway_ip': u'42.0.0.1',
u'ipv6_address_mode': None,
u'ip_version': 4,
u'host_routes': [],
u'cidr': u'42.0.0.0/24',
u'id': u'b31cdafe-bdf3-4c19-b768-34d623d77d6c',
u'subnetpool_id': None}]
}
external_policies = {u'external_policies': {}}
fw_template_properties = {
'fw_rule_keys': [u'sc_firewall_rule3', u'sc_firewall_rule2',
u'sc_firewall_rule1', u'sc_firewall_rule0',
u'sc_firewall_rule4'],
'name': u'2b8',
'properties_key': 'properties',
'resources_key': 'resources',
'is_template_aws_version': False,
'fw_policy_key': u'sc_firewall_policy'
}
pool_members = {
'type': 'OS::Neutron::PoolMember',
'properties': {
'protocol_port': 101,
'admin_state_up': True,
'pool_id': {'get_resource': u'LoadBalancerPool'},
'weight': 1,
'address': u'42.0.0.13'
}
}
fw_scn_config = "{\"heat_template_version\": \"2013-05-23\",\
\"description\": \"Template to deploy firewall\", \"resources\":\
{\"sc_firewall_rule3\": {\"type\": \"OS::Neutron::FirewallRule\",\
\"properties\": {\"action\": \"allow\", \"destination_port\": \"82\",\
\"protocol\": \"tcp\", \"name\": \"Rule_3\"}}, \"sc_firewall_rule2\":\
{\"type\": \"OS::Neutron::FirewallRule\", \"properties\": {\"action\":\
\"allow\", \"destination_port\": \"81\", \"protocol\": \"tcp\",\
\"name\": \"Rule_2\"}}, \"sc_firewall_rule1\": {\"type\":\
\"OS::Neutron::FirewallRule\", \"properties\": {\"action\": \"allow\",\
\"destination_port\": \"80\", \"protocol\": \"tcp\", \"name\":\
\"Rule_1\"}}, \"sc_firewall_rule0\": {\"type\":\
\"OS::Neutron::FirewallRule\", \"properties\": {\"action\": \"allow\",\
\"destination_port\": \"22\", \"protocol\": \"tcp\", \"name\":\
\"Rule_0\"}}, \"sc_firewall_rule4\": {\"type\":\
\"OS::Neutron::FirewallRule\", \"properties\": {\"action\": \"allow\",\
\"protocol\": \"icmp\", \"name\": \"Rule_4\"}}, \"sc_firewall_policy\"\
:{\"type\": \"OS::Neutron::FirewallPolicy\", \"properties\": {\"name\"\
:\"\", \"firewall_rules\": [{\"get_resource\": \"sc_firewall_rule0\"},\
{\"get_resource\": \"sc_firewall_rule1\"}, {\"get_resource\":\
\"sc_firewall_rule2\"}, {\"get_resource\": \"sc_firewall_rule3\"},\
{\"get_resource\": \"sc_firewall_rule4\"}]}}, \"sc_firewall\":\
{\"type\": \"OS::Neutron::Firewall\", \"properties\":\
{\"firewall_policy_id\": {\"get_resource\": \"sc_firewall_policy\"},\
\"description\": \"{\'insert_type\': \'east_west\',\
\'vm_management_ip\': u'192.168.20.138', \'provider_ptg_info\':\
[\'fa:16:3e:28:7d:b2\']}\", \"name\": \"serviceVM_infra_FW\"}}}}"
lb_scn_config = "{\"heat_template_version\": \"2013-05-23\",\
\"description\": \"Configuration for F5 Neutron Loadbalacer service\",\
\"parameters\": {\"Subnet\": {\"type\": \"string\", \"description\":\
\"Pool Subnet CIDR, on which VIP port should be created\"},\
\"service_chain_metadata\": {\"type\": \"string\", \"description\":\
\"sc metadata\"}, \"vip_ip\": {\"type\": \"string\", \"description\":\
\"VIP IP Address\"}}, \"resources\": {\"LoadBalancerPool\": {\"type\":\
\"OS::Neutron::Pool\", \"properties\": {\"lb_method\":\
\"ROUND_ROBIN\", \"protocol\": \"TCP\", \"name\": \"F5 LB pool\",\
\"admin_state_up\": true, \"subnet_id\": {\"get_param\": \"Subnet\"},\
\"vip\": {\"subnet\": {\"get_param\": \"Subnet\"}, \"description\":\
{\"get_param\": \"service_chain_metadata\"}, \"admin_state_up\": true,\
\"connection_limit\": -1, \"address\": {\"get_param\": \"vip_ip\"},\
\"protocol_port\": 80, \"name\": \"LoadBalancerPool vip\"},\
\"provider\": \"F5\", \"monitors\": [{\"get_resource\":\
\"HealthMonitor\"}], \"description\": \"F5 LB pool from template\"}},\
\"HealthMonitor\": {\"type\": \"OS::Neutron::HealthMonitor\",\
\"properties\": {\"delay\": 20, \"max_retries\": 5, \"type\":\
\"PING\", \"timeout\": 10, \"admin_state_up\": true}},\
\"LoadBalancer\": {\"type\": \"OS::Neutron::LoadBalancer\",\
\"properties\": {\"protocol_port\": 80, \"pool_id\": {\"get_resource\"\
:\"LoadBalancerPool\"}}}}}"
vpn_scn_config = "{\"description\":\"Createsnewvpnservice-ike+ipsec+\
vpnservice+site-siteconnection(s)\", \"heat_template_version\
\":\"2013-05-23\", \"parameters\":{\"RouterId\":{\"description\
\":\"RouterID\", \"type\":\"string\"}, \"ServiceDescription\":{\
\"description\":\"fip;tunnel_local-cidr\", \"type\":\"string\"}, \
\"Subnet\":{\"description\":\"Subnetidonwhichvpnserviceislaunched\
\", \"type\":\"string\"}}, \"resources\":{\"IKEPolicy\":{\"properties\
\":{\"auth_algorithm\":\"sha1\", \"encryption_algorithm\":\"3des\", \
\"ike_version\":\"v1\", \"lifetime\":{\"units\":\"seconds\", \"value\
\":3600}, \"name\":\"IKEPolicy\", \"pfs\":\"group5\", \
\"phase1_negotiation_mode\":\"main\"}, \"type\":\
\"OS::Neutron::IKEPolicy\"}, \"IPsecPolicy\":{\"properties\":{\
\"auth_algorithm\":\"sha1\", \"encapsulation_mode\":\"tunnel\", \
\"encryption_algorithm\":\"3des\", \"lifetime\":{\"units\":\"seconds\
\", \"value\":3600}, \"name\":\"IPsecPolicy\", \"pfs\":\"group5\", \
\"transform_protocol\":\"esp\"}, \"type\":\"OS::Neutron::IPsecPolicy\
\"}, \"VPNService\":{\"properties\":{\"admin_state_up\":\"true\", \
\"description\":{\"get_param\":\"ServiceDescription\"}, \"name\":\
\"VPNService\", \"router_id\":{\"get_param\":\"RouterId\"}, \
\"subnet_id\":{\"get_param\":\"Subnet\"}}, \"type\":\
\"OS::Neutron::VPNService\"}, \"site_to_site_connection1\
\":{\"properties\":{\"admin_state_up\":\"true\", \"dpd\":{\"actions\
\":\"hold\", \"interval\":30, \"timeout\":120}, \"ikepolicy_id\":{\
\"get_resource\":\"IKEPolicy\"}, \"initiator\":\"bi-directional\", \
\"ipsecpolicy_id\":{\"get_resource\":\"IPsecPolicy\"}, \"mtu\":1500, \
\"name\":\"site_to_site_connection1\", \"peer_address\":\
\"192.168.102.117\", \"peer_cidrs\":[\"11.0.0.0/24\"], \"peer_id\":\
\"11.0.0.3\", \"psk\":\"secret\", \"vpnservice_id\":{\"get_resource\
\":\"VPNService\"}}, \"type\":\"OS::Neutron::IPsecSiteConnection\"}}}"
service_profile = {
u'service_flavor': u'vyos',
u'service_type': u'FIREWALL'
}
vpn_service_profile = {
u'service_flavor': u'vyos',
u'service_type': u'VPN'
}
lb_service_profile = {
u'service_flavor': u'haproxy',
u'service_type': u'LOADBALANCER'
}
fw_service_chain_node = {
u'id': u'012345678919',
u'name': u'scn_fw',
u'config': fw_scn_config
}
vpn_service_chain_node = {
u'id': u'012345678919',
u'name': u'scn_vpn',
u'config': vpn_scn_config
}
lb_service_chain_node = {
u'id': u'012345678919',
u'name': u'scn_lb',
u'config': lb_scn_config
}
service_chain_instance = {
u'id': u'7834569034456677',
u'name': u'sci_fw'
}
consumer_port = {
u'fixed_ips': [{
u'ip_address': u'11.0.3.4',
u'subnet_id': u'9876256378888333'
}],
u'id': u'af6a8a58-1e25-49c4-97a3-d5f50b3aa04b'
}
network_function_details = {
'network_function': {
'status': 'ACTIVE',
'description': '',
'heat_stack_id': '57d6b523-ae89-41cd-9b63-9bfb054a20b6',
'tenant_id': 'ee27b1d0d7f04ac390ee7ec4b2fd5b13',
'network_function_instances': [
'4693118c-149a-46e7-b92c-cc729b536a2e'],
'service_chain_id': '507988d2-4b46-4df4-99d2-746676500872',
'service_id': '1200332d-b432-403b-8350-89b782256be5',
'service_profile_id': 'ab3b704b-a7d9-4c55-ab43-57ed5e29867d',
'id': '5ad7439b-7259-47cd-be88-36f641e0b5c8',
'name': 'LOADBALANCER.haproxy.507988d2-4b46-4df4-99d2-746676500872'
},
'network_function_instance': {
'status': 'ACTIVE',
'name': 'LOADBALANCER.haproxy.507988d2-4b46-4df4-99d2-7466765002',
'network_function_device_id': '3c3e502a-256e-4597-91a9-71902380c0',
'tenant_id': 'ee27b1d0d7f04ac390ee7ec4b2fd5b13',
'ha_state': None,
'network_function_id': '5ad7439b-7259-47cd-be88-36f641e0b5c8',
'port_info': ['8cdcc00b-b791-4039-a5b4-e4d8b3d59e9f'],
'id': '4693118c-149a-46e7-b92c-cc729b536a2e',
'description': None
},
'network_function_device': {
'status': 'ACTIVE',
'monitoring_port_network': None,
'monitoring_port_id': None,
'mgmt_ip_address': '11.0.0.27',
'description': '',
'service_vendor': None,
'tenant_id': 'ee27b1d0d7f04ac390ee7ec4b2fd5b13',
'max_interfaces': 10,
'mgmt_port_id': '4497a287-d947-4845-af29-a9d6ad6515e9',
'reference_count': 1,
'interfaces_in_use': 2,
'id': '3c3e502a-256e-4597-91a9-719023808ec0',
'name': 'LOADBALANCER.haproxy.507988d2-4b46-4df4-99d2-7466765008'
}
}
_service_details = {
'consuming_external_policies': [{
'status': None,
'consumed_policy_rule_sets': (
['46de9c30-3f87-4fb7-8e56-5e60827e1e8f']),
'external_segments': ['7648db78-f0e4-403d-91d4-c6d80963d56c'],
'description': '',
'tenant_id': '793827b52b3348929e97b23081dfac27',
'provided_policy_rule_sets': [],
'shared': False,
'status_details': None,
'id': 'aa06bb8b-1250-40e0-a1d0-e25a713cc978',
'name': 'vpn-consumer'}],
'service_vendor': 'vyos',
'image_name': 'vyos',
'network_mode': 'gbp',
'consuming_ptgs_details': [],
'device_type': 'nova',
'service_type': 'VPN'
}
_subnet = {
'shared': False,
'description': None,
'enable_dhcp': True,
'network_id': '1e8612e0-8099-4577-ac27-97e7db6f5841',
'tenant_id': '793827b52b3348929e97b23081dfac27',
'created_at': '2016-07-26T17:05:11',
'dns_nameservers': [],
'updated_at': '2016-07-26T17:05:21',
'ipv6_ra_mode': None,
'allocation_pools': [{
'start': '192.168.0.2',
'end': '192.168.0.14'}],
'gateway_ip': '192.168.0.1',
'ipv6_address_mode': None,
'ip_version': 4,
'host_routes': [{
'nexthop': '192.168.0.3',
'destination': '12.0.0.0/24'}],
'cidr': '192.168.0.0/28',
'id': 'bab31ffb-07e1-42e9-a2b0-776efbf10f4a',
'subnetpool_id': None,
'name': 'ptg_tscp_1_vpn-provider'
}
service_details = {
'service_details': _service_details,
'provider_subnet': _subnet,
'consumer_subnet': _subnet,
}
fip = [{'floating_ip_address': '192.168.102.118',
'port_id': 'af6a8a58-1e25-49c4-97a3-d5f50b3aa04b'}]
mgmt_ip = '11.3.4.5'
l2p = {
'l3_policy_id': '760d1763-9111-410a-a03e-61623afd7b25'
}
l3p = {
'routers': ['64803e64-7db7-4050-a343-cbafbd2d356a']
}
services_nsp = [{'id': '479982d1-7947-478f-bf6c-dc234f38677d'}]
stitching_pts = [{
'policy_target_group_id': '6fa92b57-69ee-4143-9cf9-fcef0d067e65'
}]

View File

@@ -0,0 +1,678 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import copy
from keystoneclient.v2_0 import client as identity_client
import mock
from oslo_config import cfg
from oslo_utils import uuidutils
import unittest
from gbpclient.v2_0 import client as gbp_client
from gbpservice.neutron.tests.unit.nfp.orchestrator import mock_dicts
from gbpservice.nfp.core import log as nfp_logging
from gbpservice.nfp.orchestrator.config_drivers import (
heat_client as heat_client)
from gbpservice.nfp.orchestrator.config_drivers import heat_driver
from neutronclient.v2_0 import client as neutron_client
class MockStackObject(object):
def __init__(self, status):
self.stack_status = status
class MockHeatClientFunctionsDeleteNotFound(object):
def delete(self, stack_id):
raise heat_client.exc.HTTPNotFound()
def create(self, **fields):
return {'stack': {'id': uuidutils.generate_uuid()}}
def get(self, stack_id):
return MockStackObject('DELETE_COMPLETE')
class MockHeatClientFunctions(object):
def delete(self, stack_id):
pass
def create(self, **fields):
return {'stack': {'id': uuidutils.generate_uuid()}}
def get(self, stack_id):
return MockStackObject('DELETE_COMPLETE')
def update(self, *args, **fields):
return {'stack': {'id': uuidutils.generate_uuid()}}
class MockHeatClient(object):
def __init__(self, api_version, endpoint, **kwargs):
self.stacks = MockHeatClientFunctions()
cfg.CONF.import_group('keystone_authtoken', 'keystonemiddleware.auth_token')
IS_SERVICE_ADMIN_OWNED = True
SVC_MGMT_PTG_NAME = 'svc_management_ptg'
RESOURCE_OWNER_TENANT_ID = '8ae6701128994ab281dde6b92207bb19'
class TestHeatDriver(unittest.TestCase):
def __init__(self, *args, **kwargs):
super(TestHeatDriver, self).__init__(*args, **kwargs)
with mock.patch.object(identity_client, "Client"):
self.heat_driver_obj = heat_driver.HeatDriver(cfg.CONF)
self.mock_dict = mock_dicts.DummyDictionaries()
def setUp(self):
cfg.CONF.set_override('is_service_admin_owned',
IS_SERVICE_ADMIN_OWNED,
group='heat_driver')
cfg.CONF.set_override('svc_management_ptg_name',
SVC_MGMT_PTG_NAME,
group='heat_driver')
cfg.CONF.set_override('admin_user',
'neutron',
group='keystone_authtoken')
cfg.CONF.set_override('admin_password',
'admin_pass',
group='keystone_authtoken')
cfg.CONF.set_override('admin_tenant_name',
'admin',
group='keystone_authtoken')
# cfg.CONF.set_override('resource_owner_tenant_id',
# RESOURCE_OWNER_TENANT_ID,
# group='heat_driver')
mock.patch(heat_client.__name__ + ".HeatClient",
new=MockHeatClient).start()
@mock.patch.object(identity_client, "Client")
def test_keystone(self, mock_obj):
keystone_client = mock_obj.return_value
keystone_client.auth_token = 'abcd123'
password = 'neutron_pass'
tenant_name = 'services'
username = 'neutron'
expected_token = 'abcd123'
token = self.heat_driver_obj.keystone(
username, password, tenant_name, tenant_id=None)
self.assertEqual(token, expected_token)
@mock.patch.object(identity_client, "Client")
def test_get_heat_client(self, mock_obj):
keystone_client = mock_obj.return_value
keystone_client.auth_token = True
self.heat_driver_obj._assign_admin_user_to_project = mock.Mock(
return_value=None)
nfp_logging.get_logging_context = mock.Mock(
return_value={'auth_token': '7fd6701128994ab281ccb6b92207bb15'})
tenant_id = '8ae6701128994ab281dde6b92207bb19'
heat_client_obj = self.heat_driver_obj._get_heat_client(
tenant_id)
self.assertIsNotNone(heat_client_obj)
@mock.patch.object(identity_client, "Client")
def test_resource_owner_tenant_id(self, mock_obj):
keystone_client = mock_obj.return_value
keystone_client.auth_token = True
keystone_client.tenants.find().id = '8ae6701128994ab281dde6b92207bb19'
expected_resource_owner_tenant_id = '8ae6701128994ab281dde6b92207bb19'
resource_owner_tenant_id = (
self.heat_driver_obj._resource_owner_tenant_id())
self.assertEqual(resource_owner_tenant_id,
expected_resource_owner_tenant_id)
def mock_objects(self):
with mock.patch.object(identity_client, "Client"):
self.heat_driver_obj = heat_driver.HeatDriver(cfg.CONF)
self.heat_driver_obj.keystoneclient.get_scoped_keystone_token = (
mock.MagicMock(return_value='token'))
self.heat_driver_obj.keystoneclient.get_tenant_id = mock.MagicMock(
return_value='8ae6701128994ab281dde6b92207bb19')
self.heat_driver_obj.neutron_client.get_port = mock.MagicMock(
return_value=self.mock_dict.port_info)
self.heat_driver_obj.neutron_client.get_floating_ips = (
mock.MagicMock(return_value=self.mock_dict.fip))
self.heat_driver_obj.neutron_client.get_subnets = mock.MagicMock(
return_value=self.mock_dict.subnets_info['subnets'])
self.heat_driver_obj.neutron_client.get_subnet = mock.MagicMock(
return_value=self.mock_dict.subnet_info)
self.heat_driver_obj.gbp_client.get_external_policies = (
mock.MagicMock(
return_value=self.mock_dict.external_policies[
'external_policies']))
self.heat_driver_obj.gbp_client.get_network_service_policies = (
mock.MagicMock(return_value=self.mock_dict.services_nsp))
self.heat_driver_obj.gbp_client.get_l3_policies = mock.MagicMock(
return_value=self.mock_dict.l3_policies['l3_policies'])
self.heat_driver_obj.gbp_client.get_policy_targets = (
mock.MagicMock(
return_value=self.mock_dict.policy_targets[
'policy_targets']))
self.heat_driver_obj.gbp_client.get_policy_target_groups = (
mock.MagicMock(
return_value=self.mock_dict.policy_target_groups[
'policy_target_groups']))
self.heat_driver_obj.gbp_client.get_policy_rule_sets = (
mock.MagicMock(
return_value=self.mock_dict.policy_rule_sets[
'policy_rule_sets']))
self.heat_driver_obj.gbp_client.get_policy_rules = mock.MagicMock(
return_value=self.mock_dict.policy_rules['policy_rules'])
self.heat_driver_obj.gbp_client.get_policy_actions = (
mock.MagicMock(
return_value=self.mock_dict.policy_actions[
'policy_actions']))
self.heat_driver_obj.gbp_client.get_l3_policy = mock.MagicMock(
return_value=self.mock_dict.l3p)
self.heat_driver_obj.gbp_client.get_l2_policy = mock.MagicMock(
return_value=self.mock_dict.l2p)
self.heat_driver_obj.gbp_client.update_policy_target_group = (
mock.MagicMock(return_value={}))
self.heat_driver_obj.gbp_client.create_policy_target_group = (
mock.MagicMock(return_value={}))
self.heat_driver_obj.gbp_client.create_policy_target = (
mock.MagicMock(return_value=self.mock_dict.policy_target))
self.heat_driver_obj.gbp_client.create_network_service_policy = (
mock.MagicMock(return_value={}))
def test_get_resource_owner_context(self):
self.mock_objects()
expected_resource_owner_context = (
'token', '8ae6701128994ab281dde6b92207bb19')
resource_owner_context = (
self.heat_driver_obj._get_resource_owner_context())
self.assertEqual(resource_owner_context,
expected_resource_owner_context)
@mock.patch.object(identity_client, "Client")
def test_get_tenant_context(self, mock_obj):
keystone_client = mock_obj.return_value
keystone_client.auth_token = True
tenant_id = '8ae6701128994ab281dde6b92207bb19'
expected_tenant_context = (True, tenant_id)
tenant_context = self.heat_driver_obj._get_tenant_context(tenant_id)
self.assertEqual(tenant_context, expected_tenant_context)
def test_is_service_target(self):
policy_target = {'name': 'service_target_provider_0132c_00b93'}
retval = self.heat_driver_obj._is_service_target(policy_target)
self.assertTrue(retval)
policy_target = {'name': 'mem1_gbpui'}
expected_result = False
result = self.heat_driver_obj._is_service_target(policy_target)
self.assertEqual(result, expected_result)
@mock.patch.object(neutron_client.Client, "show_port")
@mock.patch.object(gbp_client.Client, "list_policy_targets")
def test_get_member_ips(self, list_pt_mock_obj, show_port_mock_obj):
list_pt_mock_obj.return_value = self.mock_dict.policy_targets
show_port_mock_obj.return_value = self.mock_dict.port_info
auth_token = "81273djs138"
expected_member_ips = ['42.0.0.13']
member_ips = self.heat_driver_obj._get_member_ips(
auth_token, self.mock_dict.provider_ptg)
self.assertEqual(member_ips, expected_member_ips)
def test_generate_lb_member_template(self):
is_template_aws_version = False
member_ip = '11.0.0.4'
pool_res_name = 'HaproxyPool'
stack_template = self.mock_dict.DEFAULT_LB_CONFIG
expected_member_template = {
'type': 'OS::Neutron::PoolMember',
'properties': {
'protocol_port': 101, 'admin_state_up': True,
'pool_id': {'get_resource': 'HaproxyPool'},
'weight': 1, 'address': '11.0.0.4'
}
}
member_template = self.heat_driver_obj._generate_lb_member_template(
is_template_aws_version,
pool_res_name, member_ip, stack_template)
self.assertEqual(member_template, expected_member_template)
def test_modify_fw_resources_name(self):
is_template_aws_version = False
stack_template = copy.deepcopy(self.mock_dict.DEFAULT_FW_CONFIG)
expected_fw_resources_name = 'serviceVM_infra_FW-fw_redirect'
self.heat_driver_obj._modify_fw_resources_name(
stack_template, self.mock_dict.provider_ptg,
is_template_aws_version)
modified_fw_resources_name = (
stack_template['resources']['sc_firewall']['properties']['name'])
self.assertEqual(modified_fw_resources_name,
expected_fw_resources_name)
def test_get_heat_resource_key(self):
is_template_aws_version = False
resource_name = 'OS::Neutron::Pool'
template_resource_dict = self.mock_dict.DEFAULT_LB_CONFIG['resources']
expected_heat_resource_key = 'LoadBalancerPool'
heat_resource_key = self.heat_driver_obj._get_heat_resource_key(
template_resource_dict, is_template_aws_version, resource_name)
self.assertEqual(heat_resource_key, expected_heat_resource_key)
def test_get_all_heat_resource_keys(self):
is_template_aws_version = False
resource_name = 'OS::Neutron::Pool'
template_resource_dict = self.mock_dict.DEFAULT_LB_CONFIG['resources']
expected_heat_resource_keys = ['LoadBalancerPool']
all_heat_resource_keys = (
self.heat_driver_obj._get_all_heat_resource_keys(
template_resource_dict, is_template_aws_version,
resource_name))
self.assertEqual(all_heat_resource_keys, expected_heat_resource_keys)
@mock.patch.object(neutron_client.Client, "show_port")
@mock.patch.object(gbp_client.Client, "list_policy_targets")
def test_generate_pool_members(self, list_pt_mock_obj, show_port_mock_obj):
list_pt_mock_obj.return_value = self.mock_dict.policy_targets
show_port_mock_obj.return_value = self.mock_dict.port_info
is_template_aws_version = False
stack_template = self.mock_dict.DEFAULT_LB_CONFIG
auth_token = "81273djs138"
config_param_values = {}
expected_pool_members = self.mock_dict.pool_members
self.heat_driver_obj._generate_pool_members(
auth_token,
stack_template,
config_param_values,
self.mock_dict.provider_ptg,
is_template_aws_version)
generated_pool_members = stack_template['resources']['mem-42.0.0.13']
self.assertEqual(generated_pool_members, expected_pool_members)
def test_append_firewall_rule(self):
stack_template = copy.deepcopy(self.mock_dict.DEFAULT_FW_CONFIG)
provider_cidr = '192.169.0.0/29'
consumer_cidr = '11.0.2.0/24'
consumer_id = '2b86019a-45f7-4441-8e2c-1fbded4432c1'
self.heat_driver_obj._append_firewall_rule(
stack_template,
provider_cidr, consumer_cidr,
self.mock_dict.fw_template_properties,
consumer_id)
self.assertEqual(stack_template['resources']['sc_firewall_policy'],
self.mock_dict.appended_sc_firewall_policy)
@mock.patch.object(heat_client.HeatClient, 'delete')
@mock.patch.object(heat_client.HeatClient, 'get')
@mock.patch.object(identity_client, "Client")
def test_delete_config(self, mock_obj, heat_get_mock_obj,
heat_delete_mock_obj):
heat_get_mock_obj.return_value = MockStackObject('DELETE_COMPLETE')
self.heat_driver_obj._assign_admin_user_to_project = mock.Mock(
return_value=None)
nfp_logging.get_logging_context = mock.Mock(
return_value={'auth_token': '7fd6701128994ab281ccb6b92207bb15'})
instance = mock_obj.return_value
instance.auth_token = True
stack_id = '70754fdd-0325-4856-8a39-f171b65617d6'
self.heat_driver_obj.delete_config(stack_id, '1627')
heat_delete_mock_obj.assert_called_once_with(stack_id)
@mock.patch.object(heat_client.HeatClient, 'get')
@mock.patch.object(identity_client, "Client")
def test_is_config_complete(self, mock_obj, heat_get_mock_obj):
stack_id = '70754fdd-0325-4856-8a39-f171b65617d6'
tenant_id = '8ae6701128994ab281dde6b92207bb19'
self.heat_driver_obj._assign_admin_user_to_project = mock.Mock(
return_value=None)
nfp_logging.get_logging_context = mock.Mock(
return_value={'auth_token': '7fd6701128994ab281ccb6b92207bb15'})
self.heat_driver_obj.loadbalancer_post_stack_create = mock.Mock(
return_value=None)
heat_get_mock_obj.return_value = MockStackObject(
'CREATE_COMPLETE')
instance = mock_obj.return_value
instance.auth_token = True
expected_status = 'COMPLETED'
status = self.heat_driver_obj.is_config_complete(
stack_id, tenant_id, self.mock_dict.network_function_details)
self.assertEqual(status, expected_status)
@mock.patch.object(heat_client.HeatClient, 'get')
@mock.patch.object(identity_client, "Client")
def test_is_config_delete_complete(self, identity_mock_obj,
heat_get_mock_obj):
stack_id = '70754fdd-0325-4856-8a39-f171b65617d6'
tenant_id = '8ae6701128994ab281dde6b92207bb19'
self.heat_driver_obj._assign_admin_user_to_project = mock.Mock(
return_value=None)
nfp_logging.get_logging_context = mock.Mock(
return_value={'auth_token': '7fd6701128994ab281ccb6b92207bb15'})
heat_get_mock_obj.return_value = MockStackObject(
'DELETE_COMPLETE')
identity_mock_obj.return_value.auth_token = "1234"
identity_mock_obj.return_value.tenants.find(
).id = "8ae6701128994ab281dde6b92207bb19"
expected_status = 'COMPLETED'
status = self.heat_driver_obj.is_config_delete_complete(stack_id,
tenant_id)
self.assertEqual(status, expected_status)
def test_get_site_conn_keys(self):
is_template_aws_version = False
resource_name = 'OS::Neutron::IPsecSiteConnection'
template_resource_dict = (
self.mock_dict.DEFAULT_VPN_CONFIG['resources'])
expected_site_conn_keys = ['site_to_site_connection1']
site_conn_keys = self.heat_driver_obj._get_site_conn_keys(
template_resource_dict,
is_template_aws_version, resource_name)
self.assertEqual(site_conn_keys, expected_site_conn_keys)
@mock.patch.object(neutron_client.Client, "show_subnet")
@mock.patch.object(gbp_client.Client, "list_policy_target_groups")
def test_get_management_gw_ip(self, list_ptg_mock_obj,
show_subnet_mock_obj):
list_ptg_mock_obj.return_value = self.mock_dict.policy_target_groups
show_subnet_mock_obj.return_value = self.mock_dict.subnet_info
auth_token = 'jkijqe18381'
expected_management_gw_ip = '42.0.0.1'
management_gw_ip = self.heat_driver_obj._get_management_gw_ip(
auth_token)
self.assertEqual(management_gw_ip, expected_management_gw_ip)
@mock.patch.object(gbp_client.Client, "list_policy_actions")
@mock.patch.object(gbp_client.Client, "list_policy_rules")
@mock.patch.object(gbp_client.Client, "list_policy_rule_sets")
def test_get_consumers_for_chain(self, list_policy_rule_sets_mock_obj,
list_policy_rules_mock_obj,
list_policy_actions_mock_obj):
list_policy_rule_sets_mock_obj.return_value = (
self.mock_dict.policy_rule_sets)
list_policy_rules_mock_obj.return_value = self.mock_dict.policy_rules
list_policy_actions_mock_obj.return_value = (
self.mock_dict.policy_actions)
auth_token = 'jkijqe18381'
expected_consumers_for_chain = (
(['af6a8a58-1e25-49c4-97a3-d5f50b3aa04b'], None))
consumers_for_chain = self.heat_driver_obj._get_consumers_for_chain(
auth_token,
self.mock_dict.provider_ptg)
self.assertEqual(consumers_for_chain, expected_consumers_for_chain)
def test_update_firewall_template(self):
self.mock_objects()
stack_template = copy.deepcopy(self.mock_dict.DEFAULT_FW_CONFIG)
auth_token = 'adakjiq'
stack_template = self.heat_driver_obj._update_firewall_template(
auth_token,
self.mock_dict.provider_ptg, stack_template)
self.assertEqual(
stack_template['resources']['sc_firewall_policy'],
copy.deepcopy(self.mock_dict.updated_template_sc_firewall_policy))
@mock.patch.object(gbp_client.Client, "list_l3_policies")
def test_get_rvpn_l3_policy(self, mock_obj):
mock_obj.return_value = self.mock_dict.l3_policies
auth_token = 'asdaddasd'
node_update = True
expected_rvpn_l3_policy = {
u'tenant_id': '8ae6701128994ab281dde6b92207bb19',
u'name': u'remote-vpn-client-pool-cidr-l3policy'
}
rvpn_l3_policy = self.heat_driver_obj._get_rvpn_l3_policy(
auth_token,
self.mock_dict.provider_ptg, node_update)
self.assertEqual(rvpn_l3_policy, expected_rvpn_l3_policy)
@mock.patch.object(gbp_client.Client, "create_policy_target")
@mock.patch.object(neutron_client.Client, "list_subnets")
@mock.patch.object(neutron_client.Client, "list_pools")
@mock.patch.object(neutron_client.Client, "show_vip")
def test_create_policy_target_for_vip(self, vip, pools, subnets, pt):
pt.return_value = {
'policy_target': {
'name': 'service_target_provider_0132c_00b93'
}
}
subnets.return_value = self.mock_dict.subnets_info
pools.return_value = {
'pools': [{
'vip_id': '1234'
}]
}
vip.return_value = {
'vip': {
'port_id': '1234'
}
}
auth_token = 'adsdsdd'
provider_tenant_id = '8ae6701128994ab281dde6b92207bb19'
provider = self.mock_dict.provider_ptg
self.heat_driver_obj._create_policy_target_for_vip(
auth_token, provider_tenant_id, provider)
pools.assert_called_once_with(
subnet_id=[subnets.return_value['subnets'][0]['id']])
def test_create_node_config_data_vpn(self):
self.mock_objects()
auth_token = 'asdasasd'
tenant_id = '8ae6701128994ab281dde6b92207bb19'
provider = self.mock_dict.provider_ptg
consumer = self.mock_dict.provider_ptg
provider_port = self.mock_dict.port_info['port']
mgmt_ip = self.mock_dict.mgmt_ip
stack_template, stack_params = (
self.heat_driver_obj._create_node_config_data(
auth_token, tenant_id,
self.mock_dict.vpn_service_chain_node,
self.mock_dict.service_chain_instance,
provider, provider_port, consumer,
self.mock_dict.consumer_port,
self.mock_dict.network_function_details['network_function'],
mgmt_ip,
self.mock_dict.service_details))
self.assertEqual(stack_template['resources']['VPNService'][
'properties']['name'], 'VPNService')
self.assertEqual(stack_params['RouterId'],
self.mock_dict.l3p['routers'][0])
def test_update_node_config(self):
self.mock_objects()
auth_token = 'asdasasd'
tenant_id = '8ae6701128994ab281dde6b92207bb19'
provider = self.mock_dict.provider_ptg
provider_port = self.mock_dict.port_info['port']
mgmt_ip = self.mock_dict.mgmt_ip
stack_template, stack_params = (
self.heat_driver_obj._update_node_config(
auth_token, tenant_id,
self.mock_dict.service_profile,
self.mock_dict.fw_service_chain_node,
self.mock_dict.service_chain_instance,
provider, self.mock_dict.consumer_port,
self.mock_dict.network_function_details['network_function'],
provider_port, mgmt_ip))
self.assertEqual(stack_template['resources']['sc_firewall_policy'],
self.mock_dict.updated_sc_firewall_policy)
@mock.patch.object(heat_client.HeatClient, "delete")
@mock.patch.object(heat_client.HeatClient, "update")
@mock.patch.object(heat_client.HeatClient, "get")
@mock.patch.object(heat_client.HeatClient, "create")
def test_update(
self, heat_create, heat_get, heat_update,
heat_delete):
self.mock_objects()
heat_create.return_value = {'stack': {
'id': uuidutils.generate_uuid()}}
heat_delete.return_value = MockStackObject(
'CREATE_COMPLETE')
self.heat_driver_obj._assign_admin_user_to_project = mock.Mock(
return_value=None)
nfp_logging.get_logging_context = mock.Mock(
return_value={'auth_token': '7fd6701128994ab281ccb6b92207bb15'})
auth_token = 'dasddasda'
resource_owner_tenant_id = '8ae6701128994ab281dde6b92207bb19'
provider = self.mock_dict.provider_ptg
provider_port = self.mock_dict.port_info['port']
stack_id = '70754fdd-0325-4856-8a39-f171b65617d6'
mgmt_ip = self.mock_dict.mgmt_ip
service_details = {}
service_details['service_profile'] = self.mock_dict.service_profile
service_details['servicechain_node'] = (
self.mock_dict.fw_service_chain_node)
service_details['servicechain_instance'] = (
self.mock_dict.service_chain_instance)
service_details['policy_target_group'] = self.mock_dict.provider_ptg
service_details['provider_ptg'] = self.mock_dict.provider_ptg
service_details['consumer_ptg'] = self.mock_dict.consumer_ptg
service_details['consumer_port'] = self.mock_dict.consumer_port
service_details['provider_port'] = self.mock_dict.port_info['port']
service_details['mgmt_ip'] = '11.3.4.5'
service_details['heat_stack_id'] = (
'70754fdd-0325-4856-8a39-f171b65617d6')
self.heat_driver_obj.get_service_details = mock.Mock(
return_value=service_details)
stack_id = self.heat_driver_obj._update(
auth_token, resource_owner_tenant_id,
self.mock_dict.service_profile,
self.mock_dict.fw_service_chain_node,
self.mock_dict.service_chain_instance, provider,
self.mock_dict.consumer_port,
self.mock_dict.network_function_details['network_function'],
provider_port, stack_id, mgmt_ip=mgmt_ip,
pt_added_or_removed=False)
self.assertIsNotNone(stack_id)
@mock.patch.object(heat_client.HeatClient, "delete")
@mock.patch.object(heat_client.HeatClient, "update")
@mock.patch.object(heat_client.HeatClient, "get")
@mock.patch.object(heat_client.HeatClient, "create")
def test_handle_consumer_ptg_operations(
self, heat_create,
heat_get, heat_update, heat_delete):
self.mock_objects()
heat_create.return_value = {'stack': {
'id': uuidutils.generate_uuid()}}
heat_delete.return_value = MockStackObject(
'CREATE_COMPLETE')
self.heat_driver_obj._assign_admin_user_to_project = mock.Mock(
return_value=None)
nfp_logging.get_logging_context = mock.Mock(
return_value={'auth_token': '7fd6701128994ab281ccb6b92207bb15'})
service_details = {}
service_details['service_profile'] = self.mock_dict.service_profile
service_details['servicechain_node'] = (
self.mock_dict.fw_service_chain_node)
service_details['servicechain_instance'] = (
self.mock_dict.service_chain_instance)
service_details['policy_target_group'] = self.mock_dict.provider_ptg
service_details['provider_ptg'] = self.mock_dict.provider_ptg
service_details['consumer_ptg'] = self.mock_dict.consumer_ptg
service_details['consumer_port'] = self.mock_dict.consumer_port
service_details['provider_port'] = self.mock_dict.port_info['port']
service_details['mgmt_ip'] = '11.3.4.5'
service_details['heat_stack_id'] = (
'70754fdd-0325-4856-8a39-f171b65617d6')
self.heat_driver_obj.get_service_details = mock.Mock(
return_value=service_details)
policy_target_group = self.mock_dict.provider_ptg
stack_id = self.heat_driver_obj.handle_consumer_ptg_operations(
self.mock_dict.network_function_details,
policy_target_group, "add")
self.assertIsNotNone(stack_id)
@mock.patch.object(heat_client.HeatClient, "delete")
@mock.patch.object(heat_client.HeatClient, "update")
@mock.patch.object(heat_client.HeatClient, "get")
@mock.patch.object(heat_client.HeatClient, "create")
def test_handle_policy_target_operations(
self, heat_create,
heat_get, heat_update, heat_delete):
self.mock_objects()
heat_create.return_value = {'stack': {
'id': uuidutils.generate_uuid()}}
heat_delete.return_value = MockStackObject(
'CREATE_COMPLETE')
self.heat_driver_obj._assign_admin_user_to_project = mock.Mock(
return_value=None)
nfp_logging.get_logging_context = mock.Mock(
return_value={'auth_token': '7fd6701128994ab281ccb6b92207bb15'})
service_details = {}
service_details['service_profile'] = self.mock_dict.lb_service_profile
service_details['servicechain_node'] = (
self.mock_dict.lb_service_chain_node)
service_details['servicechain_instance'] = (
self.mock_dict.service_chain_instance)
service_details['policy_target_group'] = self.mock_dict.provider_ptg
service_details['provider_ptg'] = self.mock_dict.provider_ptg
service_details['consumer_ptg'] = self.mock_dict.consumer_ptg
service_details['consumer_port'] = self.mock_dict.consumer_port
service_details['provider_port'] = self.mock_dict.port_info['port']
service_details['mgmt_ip'] = '11.3.4.5'
service_details['heat_stack_id'] = (
'70754fdd-0325-4856-8a39-f171b65617d6')
self.heat_driver_obj.get_service_details = mock.Mock(
return_value=service_details)
policy_target = {
'name': 'policy_target_0132c_00b93'
}
stack_id = self.heat_driver_obj.handle_policy_target_operations(
self.mock_dict.network_function_details,
policy_target, "add")
self.assertIsNotNone(stack_id)
@mock.patch.object(heat_client.HeatClient, "delete")
@mock.patch.object(heat_client.HeatClient, "update")
@mock.patch.object(heat_client.HeatClient, "get")
@mock.patch.object(heat_client.HeatClient, "create")
def test_apply_config(
self, heat_create,
heat_get, heat_update, heat_delete):
self.mock_objects()
heat_create.return_value = {'stack': {
'id': uuidutils.generate_uuid()}}
heat_delete.return_value = MockStackObject(
'CREATE_COMPLETE')
self.heat_driver_obj._assign_admin_user_to_project = mock.Mock(
return_value=None)
nfp_logging.get_logging_context = mock.Mock(
return_value={'auth_token': '7fd6701128994ab281ccb6b92207bb15'})
service_details = {}
service_details['service_profile'] = self.mock_dict.service_profile
service_details['servicechain_node'] = (
self.mock_dict.fw_service_chain_node)
service_details['servicechain_instance'] = (
self.mock_dict.service_chain_instance)
service_details['policy_target_group'] = self.mock_dict.provider_ptg
service_details['provider_ptg'] = self.mock_dict.provider_ptg
service_details['consumer_ptg'] = self.mock_dict.consumer_ptg
service_details['consumer_port'] = self.mock_dict.consumer_port
service_details['provider_port'] = self.mock_dict.port_info['port']
service_details['mgmt_ip'] = '11.3.4.5'
service_details['heat_stack_id'] = (
'70754fdd-0325-4856-8a39-f171b65617d6')
self.heat_driver_obj.get_service_details = mock.Mock(
return_value=service_details)
stack_id = self.heat_driver_obj.apply_config(
self.mock_dict.network_function_details)
self.assertIsNotNone(stack_id)

View File

@@ -170,7 +170,7 @@ class NfpResourceManager(NfpProcessManager, NfpEventManager):
g_executor.event_complete(event.result, event=event.desc.uuid)
def _scheduled_event_graph(self, event):
if event.graph:
if type(event.graph) == bool:
# Cache the event object
self._event_cache[event.desc.uuid] = event
else:

View File

@@ -246,6 +246,19 @@ class HeatDriver(object):
if port_info['port_model'] != nfp_constants.GBP_PORT:
return
def _post_stack_create(self, nfp_context):
service_details = self.get_service_details_from_nfp_context(
nfp_context)
service_type = service_details['service_details']['service_type']
if service_type in [pconst.LOADBALANCER]:
logging_context = nfp_logging.get_logging_context()
auth_token = logging_context['auth_token']
provider_tenant_id = nfp_context['tenant_id']
provider = service_details['provider_ptg']
self._create_policy_target_for_vip(
auth_token, provider_tenant_id, provider)
def _create_policy_target_for_vip(self, auth_token,
provider_tenant_id, provider):
provider_subnet = None
@@ -479,6 +492,10 @@ class HeatDriver(object):
consuming_ptgs_details = service_details['consuming_ptgs_details']
consumer_eps = service_details['consuming_external_policies']
# Handle a case where a chain is provided first and then consumed
# if (not consuming_ptgs_details) and (not consumer_eps):
# return None
is_template_aws_version = stack_template.get(
'AWSTemplateFormatVersion', False)
resources_key = 'Resources' if is_template_aws_version else 'resources'
@@ -816,6 +833,106 @@ class HeatDriver(object):
'description'] = str(common_desc)
nf_desc = str(firewall_desc)
elif service_type == pconst.VPN:
config_param_values['Subnet'] = (
consumer_port['fixed_ips'][0]['subnet_id']
if consumer_port else None)
l2p = self.gbp_client.get_l2_policy(
auth_token, provider['l2_policy_id'])
l3p = self.gbp_client.get_l3_policy(
auth_token, l2p['l3_policy_id'])
config_param_values['RouterId'] = l3p['routers'][0]
stitching_cidr = service_details['consumer_subnet']['cidr']
mgmt_gw_ip = self._get_management_gw_ip(auth_token)
if not mgmt_gw_ip:
return None, None
services_nsp = self.gbp_client.get_network_service_policies(
auth_token,
filters={'name': ['nfp_services_nsp']})
if not services_nsp:
fip_nsp = {
'network_service_policy': {
'name': 'nfp_services_nsp',
'description': 'nfp_implicit_resource',
'shared': False,
'tenant_id': tenant_id,
'network_service_params': [
{"type": "ip_pool", "value": "nat_pool",
"name": "vpn_svc_external_access"}]
}
}
nsp = self.gbp_client.create_network_service_policy(
auth_token, fip_nsp)
else:
nsp = services_nsp[0]
if not base_mode_support:
stitching_pts = self.gbp_client.get_policy_targets(
auth_token,
filters={'port_id': [consumer_port['id']]})
if not stitching_pts:
LOG.error(_LE("Policy target is not created for the "
"stitching port"))
return None, None
stitching_ptg_id = (
stitching_pts[0]['policy_target_group_id'])
else:
stitching_ptg_id = consumer['id']
self.gbp_client.update_policy_target_group(
auth_token, stitching_ptg_id,
{'policy_target_group': {
'network_service_policy_id': nsp['id']}})
stitching_port_fip = ""
if not base_mode_support:
floatingips = (
self.neutron_client.get_floating_ips(auth_token))
if not floatingips:
LOG.error(_LE("Floating IP for VPN Service has been "
"disassociated Manually"))
return None, None
for fip in floatingips:
if consumer_port['id'] == fip['port_id']:
stitching_port_fip = fip['floating_ip_address']
break
if not stitching_port_fip:
LOG.error(_LE("Floatingip retrival has failed."))
return None, None
try:
desc = ('fip=' + mgmt_ip +
";tunnel_local_cidr=" +
provider_cidr + ";user_access_ip=" +
stitching_port_fip + ";fixed_ip=" +
consumer_port['fixed_ips'][0]['ip_address'] +
';service_vendor=' + service_vendor +
';stitching_cidr=' + stitching_cidr +
';stitching_gateway=' + service_details[
'consumer_subnet']['gateway_ip'] +
';mgmt_gw_ip=' + mgmt_gw_ip +
';network_function_id=' + network_function['id'])
except Exception:
LOG.error(_LE("Problem in preparing description, some of "
"the fields might not have initialized"))
return None, None
stack_params['ServiceDescription'] = desc
siteconn_keys = self._get_site_conn_keys(
stack_template[resources_key],
is_template_aws_version,
'OS::Neutron::IPsecSiteConnection')
for siteconn_key in siteconn_keys:
stack_template[resources_key][siteconn_key][
properties_key]['description'] = str(common_desc)
vpnservice_key = self._get_heat_resource_key(
stack_template[resources_key],
is_template_aws_version,
'OS::Neutron::VPNService')
stack_template[resources_key][vpnservice_key][properties_key][
'description'] = str(common_desc)
nf_desc = str(desc)
if nf_desc:
network_function['description'] = network_function[
@@ -1326,6 +1443,7 @@ class HeatDriver(object):
if stack.stack_status == 'DELETE_FAILED':
return failure_status
elif stack.stack_status == 'CREATE_COMPLETE':
self._post_stack_create(nfp_context)
return success_status
elif stack.stack_status == 'UPDATE_COMPLETE':
return success_status

View File

@@ -471,6 +471,19 @@ class DeviceOrchestrator(nfp_api.NfpEventHandler):
device.update(device_data)
return device
def _make_ports_dict(self, consumer, provider, port_type):
t_ports = []
for ptg in [consumer, provider]:
if (port_type in ptg.keys()) and ptg[port_type]:
t_ports.append({
'id': ptg[port_type].get('id'),
'port_classification': ptg.get(
'port_classification'),
'port_model': ptg.get('port_model')
})
return t_ports
def _prepare_device_data_from_nfp_context(self, nfp_context):
device_data = {}
@@ -493,19 +506,8 @@ class DeviceOrchestrator(nfp_api.NfpEventHandler):
consumer = nfp_context['consumer']
provider = nfp_context['provider']
ports = []
if consumer['port']:
ports.append({
'id': consumer['port']['id'],
'port_classification': consumer['port_classification'],
'port_model': consumer['port_model']})
if provider['port']:
ports.append({
'id': provider['port']['id'],
'port_classification': provider['port_classification'],
'port_model': provider['port_model']})
ports = self._make_ports_dict(consumer, provider, 'pt')
device_data['management_network_info'] = management_network_info
@@ -865,17 +867,8 @@ class DeviceOrchestrator(nfp_api.NfpEventHandler):
orchestration_driver = self._get_orchestration_driver(
service_details['service_vendor'])
ports = []
if consumer['port']:
ports.append(
{'id': consumer['port']['id'],
'port_classification': consumer['port_classification'],
'port_model': consumer['port_model']})
if provider['port']:
ports.append(
{'id': provider['port']['id'],
'port_classification': provider['port_classification'],
'port_model': provider['port_model']})
ports = self._make_ports_dict(consumer, provider, 'port')
device = {
'id': network_function_device['id'],
'ports': ports,

View File

@@ -1001,6 +1001,13 @@ class ServiceOrchestrator(nfp_api.NfpEventHandler):
original_event=event)
def apply_user_config(self, event):
event_results = event.graph.get_leaf_node_results(event)
for c_event in event_results:
if c_event.id == "SEND_HEAT_CONFIG" and (
c_event.result.upper() == "HANDLED"):
self._controller.event_complete(
event, result="SUCCESS")
return
nfp_context = event.data
nfp_core_context.store_nfp_context(nfp_context)
network_function = nfp_context['network_function']
@@ -1360,28 +1367,39 @@ class ServiceOrchestrator(nfp_api.NfpEventHandler):
# Trigger RPC to notify the Create_Service caller with status
def handle_config_applied(self, event):
event_data = event.data
network_function_id = event_data['network_function_id']
network_function_instance_id = event_data.get(
'network_function_instance_id')
if network_function_instance_id:
nfi = {
nfp_context = event.data['nfp_context']
base_mode = nfp_context['base_mode']
network_function_id = event.data['network_function_id']
if base_mode:
network_function = {
'status': nfp_constants.ACTIVE,
}
nfi = self.db_handler.update_network_function_instance(
self.db_session, network_function_instance_id, nfi)
self.db_handler.update_network_function(
self.db_session,
network_function_id,
network_function)
LOG.info(_LI("NSO: applying user config is successfull moving "
"network function %(network_function_id)s to ACTIVE"),
{'network_function_id':
network_function_id})
else:
network_function_instance_id = (
event.data['network_function_instance_id'])
if network_function_instance_id:
nfi = {
'status': nfp_constants.ACTIVE,
}
nfi = self.db_handler.update_network_function_instance(
self.db_session, network_function_instance_id, nfi)
network_function = {
'status': nfp_constants.ACTIVE,
}
self.db_handler.update_network_function(
self.db_session,
network_function_id,
network_function)
LOG.info(_LI("NSO: applying user config is successfull moving "
"network function %(network_function_id)s to ACTIVE"),
{'network_function_id':
network_function_id})
event_desc = nfp_context['event_desc']
key = nfp_context['key']
id = nfp_context['id']
# Complete the original event here
event = self._controller.new_event(id=id, key=key,
desc_dict=event_desc)
self._controller.event_complete(event, result='HANDLED')
def handle_update_user_config_failed(self, event):
event_data = event.data