group-based-policy/gbpservice/nfp/orchestrator/drivers/orchestration_driver.py

1071 lines
42 KiB
Python

# 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 ast
from collections import defaultdict
from gbpservice.nfp.common import constants as nfp_constants
from gbpservice.nfp.common import data_formatter as df
from gbpservice.nfp.common import exceptions
from gbpservice.nfp.core import executor as nfp_executor
from gbpservice.nfp.core import log as nfp_logging
from gbpservice.nfp.lib import nfp_context_manager as nfp_ctx_mgr
from gbpservice.nfp.orchestrator.coal.networking import (
nfp_gbp_network_driver
)
from gbpservice.nfp.orchestrator.coal.networking import (
nfp_neutron_network_driver
)
from gbpservice.nfp.orchestrator.openstack import openstack_driver
LOG = nfp_logging.getLogger(__name__)
def _set_network_handler(f):
def wrapped(self, *args, **kwargs):
if type(args[0]) == dict:
device_data = args[0]
else:
device_data = args[1]
if device_data.get('service_details'):
network_mode = device_data['service_details'].get('network_mode')
if network_mode:
kwargs['network_handler'] = self.network_handlers[network_mode]
return f(self, *args, **kwargs)
return wrapped
class OrchestrationDriver(object):
"""Generic Driver class for orchestration of virtual appliances
Launches the VM with all the management and data ports and a new VM
is launched for each Network Service Instance
"""
def __init__(self, config, supports_device_sharing=False,
supports_hotplug=False, max_interfaces=8):
self.service_vendor = 'general'
self.supports_device_sharing = supports_device_sharing
self.supports_hotplug = supports_hotplug
self.maximum_interfaces = max_interfaces
self.identity_handler = openstack_driver.KeystoneClient(config)
self.compute_handler_nova = openstack_driver.NovaClient(config)
self.network_handlers = {
nfp_constants.GBP_MODE:
nfp_gbp_network_driver.NFPGBPNetworkDriver(config),
nfp_constants.NEUTRON_MODE:
nfp_neutron_network_driver.NFPNeutronNetworkDriver(config)
}
self.config = config
def _get_admin_tenant_id(self, token=None):
with nfp_ctx_mgr.KeystoneContextManager as kcm:
if not token:
token = kcm.retry(
self.identity_handler.get_admin_token, tries=3)
admin_tenant_name = (
self.config.nfp_keystone_authtoken.admin_tenant_name)
admin_tenant_id = kcm.retry(self.identity_handler.get_tenant_id,
token,
admin_tenant_name, tries=3)
return admin_tenant_id
def _get_token(self, device_data_token):
with nfp_ctx_mgr.KeystoneContextManager as kcm:
token = (device_data_token
if device_data_token
else kcm.retry(
self.identity_handler.get_admin_token, tries=3))
return token
def _is_device_sharing_supported(self):
return False
def _create_management_interface(self, token, admin_tenant_id,
device_data, network_handler):
name = nfp_constants.MANAGEMENT_INTERFACE_NAME
mgmt_interface = network_handler.create_port(
token,
admin_tenant_id,
device_data['management_network_info']['id'],
name=name)
return {'id': mgmt_interface['id'],
'port_id': mgmt_interface['port_id'],
'port_model': (nfp_constants.GBP_PORT
if device_data['service_details'][
'network_mode'] ==
nfp_constants.GBP_MODE
else nfp_constants.NEUTRON_PORT),
'port_classification': nfp_constants.MANAGEMENT,
'port_role': None}
def _delete_interface(self, device_data, interface,
network_handler=None):
token = self._get_token(device_data.get('token'))
if not token:
return None
network_handler.delete_port(token, interface['id'])
def _get_interfaces_for_device_create(self, token, admin_tenant_id,
network_handler, device_data):
try:
mgmt_interface = self._create_management_interface(
token,
admin_tenant_id,
device_data,
network_handler)
device_data['interfaces'] = [mgmt_interface]
except Exception as e:
LOG.exception('Failed to get interfaces for device creation.'
'Error: %(error)s', {'error': e})
def _delete_interfaces(self, device_data, interfaces,
network_handler=None):
for interface in interfaces:
self._delete_interface(
device_data, interface,
network_handler=network_handler)
def _verify_provider_metadata(self, image_name, metadata):
provider_metadata = {}
try:
for attr in metadata:
if attr in nfp_constants.METADATA_SUPPORTED_ATTRIBUTES:
provider_metadata[attr] = ast.literal_eval(metadata[attr])
except Exception as e:
LOG.error('Wrong metadata: %(metadata)s provided for '
'image name: %(image_name)s. Error: %(error)s',
{'image_name': image_name, 'metadata': metadata,
'error': e})
return None
return provider_metadata
def _get_provider_metadata(self, device_data, image_name):
token = self._get_token(device_data.get('token'))
if not token:
return None
with nfp_ctx_mgr.NovaContextManager as ncm:
metadata = ncm.retry(self.compute_handler_nova.get_image_metadata,
token,
self._get_admin_tenant_id(token=token),
image_name)
provider_metadata = self._verify_provider_metadata(
image_name, metadata)
if not provider_metadata:
return {}
return provider_metadata
def _get_provider_metadata_fast(self, token,
admin_tenant_id, image_name, device_data):
with nfp_ctx_mgr.NovaContextManager as ncm:
metadata = ncm.retry(self.compute_handler_nova.get_image_metadata,
token,
admin_tenant_id,
image_name)
provider_metadata = self._verify_provider_metadata(
image_name, metadata)
if not provider_metadata:
return {}
return provider_metadata
def _update_self_with_provider_metadata(self, provider_metadata, attr):
attr_value = getattr(self, attr)
if attr in provider_metadata:
setattr(self, attr, provider_metadata[attr])
else:
LOG.debug("Provider metadata specified in image, doesn't contains "
"%s value, proceeding with default value "
"%s", (attr, attr_value))
def _update_provider_metadata(self, device_data, token=None):
provider_metadata = {}
try:
image_name = self._get_image_name(device_data)
provider_metadata = self._get_provider_metadata(device_data,
image_name)
LOG.debug("Provider metadata, specified in image: %s",
provider_metadata)
if provider_metadata:
self._update_self_with_provider_metadata(
provider_metadata,
nfp_constants.MAXIMUM_INTERFACES)
self._update_self_with_provider_metadata(
provider_metadata,
nfp_constants.SUPPORTS_HOTPLUG)
else:
LOG.debug("No provider metadata specified in image,"
" proceeding with default values")
except Exception:
LOG.error("Error while getting metadata for image name:"
"%(image_name)s, proceeding with default values",
{'image_name': image_name})
return provider_metadata
def _update_provider_metadata_fast(self, token, admin_tenant_id,
image_name, device_data):
provider_metadata = None
try:
provider_metadata = self._get_provider_metadata_fast(
token, admin_tenant_id, image_name, device_data)
LOG.debug("Provider metadata, specified in image: %s",
provider_metadata)
if provider_metadata:
self._update_self_with_provider_metadata(
provider_metadata,
nfp_constants.MAXIMUM_INTERFACES)
self._update_self_with_provider_metadata(
provider_metadata,
nfp_constants.SUPPORTS_HOTPLUG)
else:
LOG.debug("No provider metadata specified in image,"
" proceeding with default values")
except Exception:
LOG.error("Error while getting metadata for image name: "
"%(image_name)s, proceeding with default values",
{'image_name': image_name})
return provider_metadata
def _get_image_name(self, device_data):
if device_data['service_details'].get('image_name'):
image_name = device_data['service_details']['image_name']
else:
LOG.debug("No image name provided in service profile's "
"service flavor field, image will be selected "
"based on service vendor's name : %s",
(device_data['service_details']['service_vendor']))
image_name = device_data['service_details']['service_vendor']
image_name = '%s' % image_name.lower()
device_data['service_details']['image_name'] = image_name
return image_name
def _get_service_type(self, token, service_profile_id, network_handler):
service_profile = network_handler.get_service_profile(
token, service_profile_id)
return service_profile['service_type']
def _get_device_service_types_map(self, token, devices, network_handler):
device_service_types_map = defaultdict(set)
for device in devices:
for network_function in device['network_functions']:
service_type = self._get_service_type(
token,
network_function['service_profile_id'],
network_handler)
device_service_types_map[device['id']].add(service_type)
return device_service_types_map
def get_image_id(self, nova, token, admin_tenant_id, image_name):
try:
image_id = nova.get_image_id(token, admin_tenant_id, image_name)
return image_id
except Exception as e:
LOG.error('Failed to get image id for device creation.'
' image name: %(image_name)s. Error: %(error)s',
{'image_name': image_name, 'error': e})
def create_instance(self, nova, token, admin_tenant_id,
image_id, flavor, interfaces_to_attach,
instance_name, volume_support,
volume_size, files=None, user_data=None,
server_grp_id=None):
try:
instance_id = nova.create_instance(
token, admin_tenant_id, image_id, flavor,
interfaces_to_attach, instance_name, volume_support,
volume_size, files=files, userdata=user_data,
server_grp_id=server_grp_id)
return instance_id
except Exception as e:
LOG.error('Failed to create instance.'
'Error: %(error)s', {'error': e})
def get_neutron_port_details(self, network_handler, token, port_id):
try:
(mgmt_ip_address,
mgmt_mac, mgmt_cidr, gateway_ip,
mgmt_port, mgmt_subnet) = (
network_handler.get_neutron_port_details(token, port_id))
result = {'neutron_port': mgmt_port['port'],
'neutron_subnet': mgmt_subnet['subnet'],
'ip_address': mgmt_ip_address,
'mac': mgmt_mac,
'cidr': mgmt_cidr,
'gateway_ip': gateway_ip}
return result
except Exception as e:
import sys
import traceback
exc_type, exc_value, exc_traceback = sys.exc_info()
LOG.error(traceback.format_exception(exc_type, exc_value,
exc_traceback))
LOG.error('Failed to get management port details. '
'Error: %(error)s', {'error': e})
@_set_network_handler
def create_network_function_device(self, device_data,
network_handler=None):
""" Create a NFD
:param device_data: NFD data
:type device_data: dict
:returns: None -- when there is a failure in creating NFD
:return: dict -- NFD created
:raises: exceptions.IncompleteData,
exceptions.ComputePolicyNotSupported
"""
self._validate_create_nfd_data(device_data)
token = device_data['token']
admin_tenant_id = device_data['admin_tenant_id']
image_name = self._get_image_name(device_data)
pre_launch_executor = nfp_executor.TaskExecutor(jobs=3)
image_id_result = {}
provider_metadata_result = {}
pre_launch_executor.add_job('UPDATE_PROVIDER_METADATA',
self._update_provider_metadata_fast,
token, admin_tenant_id,
image_name, device_data,
result_store=provider_metadata_result)
pre_launch_executor.add_job('GET_INTERFACES_FOR_DEVICE_CREATE',
self._get_interfaces_for_device_create,
token, admin_tenant_id,
network_handler, device_data)
pre_launch_executor.add_job('GET_IMAGE_ID',
self.get_image_id,
self.compute_handler_nova, token,
admin_tenant_id,
image_name, result_store=image_id_result)
pre_launch_executor.fire()
interfaces, image_id, provider_metadata = (
self._validate_pre_launch_executor_results(
network_handler,
device_data,
image_name,
image_id_result,
provider_metadata_result))
if not interfaces:
return None
management_interface = interfaces[0]
flavor = self._get_service_instance_flavor(device_data)
interfaces_to_attach = []
try:
for interface in interfaces:
interfaces_to_attach.append({'port': interface['port_id']})
if provider_metadata.get('supports_hotplug') is False:
self._update_interfaces_for_non_hotplug_support(
network_handler,
interfaces,
interfaces_to_attach,
device_data)
except Exception as e:
LOG.error('Failed to fetch list of interfaces to attach'
' for device creation %(error)s', {'error': e})
self._delete_interfaces(device_data, interfaces,
network_handler=network_handler)
return None
instance_name = device_data['name']
create_instance_executor = nfp_executor.TaskExecutor(jobs=3)
instance_id_result = {}
port_details_result = {}
volume_support = device_data['volume_support']
volume_size = device_data['volume_size']
create_instance_executor.add_job(
'CREATE_INSTANCE', self.create_instance,
self.compute_handler_nova, token,
admin_tenant_id, image_id, flavor,
interfaces_to_attach, instance_name,
volume_support, volume_size,
files=device_data.get('files'),
user_data=device_data.get('user_data'),
result_store=instance_id_result)
create_instance_executor.add_job(
'GET_NEUTRON_PORT_DETAILS',
self.get_neutron_port_details,
network_handler, token,
management_interface['port_id'],
result_store=port_details_result)
create_instance_executor.fire()
instance_id, mgmt_neutron_port_info = (
self._validate_create_instance_executor_results(
network_handler,
device_data,
interfaces,
instance_id_result,
port_details_result))
if not instance_id:
return None
mgmt_ip_address = mgmt_neutron_port_info['ip_address']
return {'id': instance_id,
'name': instance_name,
'provider_metadata': provider_metadata,
'mgmt_ip_address': mgmt_ip_address,
'mgmt_port_id': interfaces[0],
'mgmt_neutron_port_info': mgmt_neutron_port_info,
'max_interfaces': self.maximum_interfaces,
'interfaces_in_use': len(interfaces_to_attach),
'description': ''} # TODO(RPM): what should be the description
def _validate_create_nfd_data(self, device_data):
if (
any(key not in device_data
for key in ['service_details',
'name',
'management_network_info',
'ports']) or
type(device_data['service_details']) is not dict or
any(key not in device_data['service_details']
for key in ['service_vendor',
'device_type',
'network_mode']) or
any(key not in device_data['management_network_info']
for key in ['id']) or
type(device_data['ports']) is not list or
any(key not in port
for port in device_data['ports']
for key in ['id',
'port_classification',
'port_model'])
):
raise exceptions.IncompleteData()
if (
device_data['service_details']['device_type'] !=
nfp_constants.NOVA_MODE
):
raise exceptions.ComputePolicyNotSupported(
compute_policy=device_data['service_details']['device_type'])
def _validate_pre_launch_executor_results(self, network_handler,
device_data,
image_name,
image_id_result,
provider_metadata_result,
server_grp_id_result=None):
interfaces = device_data.pop('interfaces', None)
if not interfaces:
LOG.exception('Failed to get interfaces for device creation.')
return None, _, _
image_id = image_id_result.get('result', None)
if not image_id:
LOG.error('Failed to get image id for device creation.')
self._delete_interfaces(device_data, interfaces,
network_handler=network_handler)
return None, _, _
if server_grp_id_result and not server_grp_id_result.get('result'):
LOG.error('Validation failed for Nova anti-affinity '
'server group.')
return None, _, _
provider_metadata = provider_metadata_result.get('result', None)
if not provider_metadata:
LOG.warning('Failed to get provider metadata for'
' device creation.')
provider_metadata = {}
return interfaces, image_id, provider_metadata
def _get_service_instance_flavor(self, device_data):
if device_data['service_details'].get('flavor'):
flavor = device_data['service_details']['flavor']
else:
LOG.debug("No Device flavor provided in service profile's "
"service flavor field, using default "
"flavor: m1.medium")
flavor = 'm1.medium'
return flavor
def _update_interfaces_for_non_hotplug_support(self, network_handler,
interfaces,
interfaces_to_attach,
device_data):
token = device_data['token']
enable_port_security = device_data.get('enable_port_security')
if not device_data['interfaces_to_attach']:
for port in device_data['ports']:
if (port['port_classification'] ==
nfp_constants.PROVIDER):
if (device_data['service_details'][
'service_type'].lower()
in [nfp_constants.FIREWALL.lower(),
nfp_constants.VPN.lower()]):
network_handler.set_promiscuos_mode(
token, port['id'], enable_port_security)
port_id = network_handler.get_port_id(
token, port['id'])
interfaces_to_attach.append({'port': port_id})
for port in device_data['ports']:
if (port['port_classification'] ==
nfp_constants.CONSUMER):
if (device_data['service_details'][
'service_type'].lower()
in [nfp_constants.FIREWALL.lower(),
nfp_constants.VPN.lower()]):
network_handler.set_promiscuos_mode(
token, port['id'], enable_port_security)
port_id = network_handler.get_port_id(
token, port['id'])
interfaces_to_attach.append({'port': port_id})
else:
for interface in device_data['interfaces_to_attach']:
interfaces_to_attach.append(
{'port': interface['port']})
interfaces.append({'id': interface['id']})
def _validate_create_instance_executor_results(self,
network_handler,
device_data,
interfaces,
instance_id_result,
port_details_result):
token = device_data['token']
admin_tenant_id = device_data['admin_tenant_id']
instance_id = instance_id_result.get('result', None)
if not instance_id:
LOG.error('Failed to create instance with device data:'
'%(data)s.',
{'data': device_data})
self._delete_interfaces(device_data, interfaces,
network_handler=network_handler)
return None, _
mgmt_neutron_port_info = port_details_result.get('result', None)
if not mgmt_neutron_port_info:
LOG.error('Failed to get management port details. ')
with nfp_ctx_mgr.NovaContextManager as ncm:
ncm.retry(self.compute_handler_nova.delete_instance,
token,
admin_tenant_id,
instance_id)
self._delete_interfaces(device_data, interfaces,
network_handler=network_handler)
return None, _
return instance_id, mgmt_neutron_port_info
@_set_network_handler
def delete_network_function_device(self, device_data,
network_handler=None):
""" Delete the NFD
:param device_data: NFD
:type device_data: dict
:returns: None -- Both on success and Failure
:raises: exceptions.IncompleteData,
exceptions.ComputePolicyNotSupported
"""
if (
any(key not in device_data
for key in ['service_details',
'mgmt_port_id']) or
type(device_data['service_details']) is not dict or
any(key not in device_data['service_details']
for key in ['service_vendor',
'device_type',
'network_mode']) or
type(device_data['mgmt_port_id']) is not dict or
any(key not in device_data['mgmt_port_id']
for key in ['id',
'port_classification',
'port_model'])
):
raise exceptions.IncompleteData()
if (
device_data['service_details']['device_type'] !=
nfp_constants.NOVA_MODE
):
raise exceptions.ComputePolicyNotSupported(
compute_policy=device_data['service_details']['device_type'])
token = self._get_token(device_data.get('token'))
if not token:
return None
if device_data.get('id'):
# delete the device instance
#
# this method will be invoked again
# once the device instance deletion is completed
with nfp_ctx_mgr.NovaContextManager.new(
suppress=(Exception,)) as ncm:
ncm.retry(self.compute_handler_nova.delete_instance,
token,
device_data['tenant_id'],
device_data['id'])
else:
# device instance deletion is done, delete remaining resources
try:
interfaces = [device_data['mgmt_port_id']]
self._delete_interfaces(device_data,
interfaces,
network_handler=network_handler)
except Exception as e:
LOG.error('Failed to delete the management data port(s). '
'Error: %(error)s', {'error': e})
def get_network_function_device_status(self, device_data,
ignore_failure=False):
""" Get the status of NFD
:param device_data: NFD
:type device_data: dict
:returns: None -- On failure
:return: str -- status string
:raises: exceptions.IncompleteData,
exceptions.ComputePolicyNotSupported
"""
if (
any(key not in device_data
for key in ['id',
'service_details']) or
type(device_data['service_details']) is not dict or
any(key not in device_data['service_details']
for key in ['service_vendor',
'device_type',
'network_mode'])
):
raise exceptions.IncompleteData()
if (
device_data['service_details']['device_type'] !=
nfp_constants.NOVA_MODE
):
raise exceptions.ComputePolicyNotSupported(
compute_policy=device_data['service_details']['device_type'])
token = self._get_token(device_data.get('token'))
if not token:
return None
with nfp_ctx_mgr.NovaContextManager.new(suppress=(Exception,)) as ncm:
device = ncm.retry(self.compute_handler_nova.get_instance,
device_data['token'],
device_data['tenant_id'],
device_data['id'])
return device['status']
@_set_network_handler
def plug_network_function_device_interfaces(self, device_data,
network_handler=None):
""" Attach the network interfaces for NFD
:param device_data: NFD
:type device_data: dict
:returns: bool -- False on failure and True on Success
:raises: exceptions.IncompleteData,
exceptions.ComputePolicyNotSupported
"""
if (
any(key not in device_data
for key in ['id',
'service_details',
'ports']) or
type(device_data['service_details']) is not dict or
any(key not in device_data['service_details']
for key in ['service_vendor',
'device_type',
'network_mode']) or
type(device_data['ports']) is not list or
any(key not in port
for port in device_data['ports']
for key in ['id',
'port_classification',
'port_model'])
):
raise exceptions.IncompleteData()
if (
device_data['service_details']['device_type'] !=
nfp_constants.NOVA_MODE
):
raise exceptions.ComputePolicyNotSupported(
compute_policy=device_data['service_details']['device_type'])
token = device_data['token']
tenant_id = device_data['tenant_id']
provider_metadata = device_data['provider_metadata']
enable_port_security = device_data.get('enable_port_security')
if provider_metadata.get('supports_hotplug') is False:
return True
try:
executor = nfp_executor.TaskExecutor(jobs=10)
for port in device_data['ports']:
if port['port_classification'] == nfp_constants.PROVIDER:
service_type = device_data[
'service_details']['service_type'].lower()
if service_type.lower() in [
nfp_constants.FIREWALL.lower(),
nfp_constants.VPN.lower()]:
executor.add_job(
'SET_PROMISCUOS_MODE',
network_handler.set_promiscuos_mode_fast,
token, port['id'], enable_port_security)
executor.add_job(
'ATTACH_INTERFACE',
self.compute_handler_nova.attach_interface,
token, tenant_id, device_data['id'],
port['id'])
break
executor.fire()
for port in device_data['ports']:
if port['port_classification'] == nfp_constants.CONSUMER:
service_type = device_data[
'service_details']['service_type'].lower()
if service_type.lower() in [
nfp_constants.FIREWALL.lower(),
nfp_constants.VPN.lower()]:
executor.add_job(
'SET_PROMISCUOS_MODE',
network_handler.set_promiscuos_mode_fast,
token, port['id'], enable_port_security)
executor.add_job(
'ATTACH_INTERFACE',
self.compute_handler_nova.attach_interface,
token, tenant_id, device_data['id'],
port['id'])
break
executor.fire()
except Exception as e:
LOG.error('Failed to plug interface(s) to the device.'
'Error: %(error)s', {'error': e})
return None
else:
return True
@_set_network_handler
def unplug_network_function_device_interfaces(self, device_data,
network_handler=None):
""" Detach the network interfaces for NFD
:param device_data: NFD
:type device_data: dict
:returns: bool -- False on failure and True on Success
:raises: exceptions.IncompleteData,
exceptions.ComputePolicyNotSupported
"""
if (
any(key not in device_data
for key in ['id',
'service_details',
'ports']) or
type(device_data['service_details']) is not dict or
any(key not in device_data['service_details']
for key in ['service_vendor',
'device_type',
'network_mode']) or
any(key not in port
for port in device_data['ports']
for key in ['id',
'port_classification',
'port_model'])
):
raise exceptions.IncompleteData()
if (
device_data['service_details']['device_type'] !=
nfp_constants.NOVA_MODE
):
raise exceptions.ComputePolicyNotSupported(
compute_policy=device_data['service_details']['device_type'])
token = self._get_token(device_data.get('token'))
if not token:
return None
image_name = self._get_image_name(device_data)
provider_metadata = {}
if image_name:
provider_metadata = (
self._update_provider_metadata_fast(token,
device_data['tenant_id'],
image_name,
device_data))
if not provider_metadata:
LOG.debug('Failed to get provider metadata for'
' device deletion.')
if provider_metadata.get('supports_hotplug') is False:
return True
with nfp_ctx_mgr.NovaContextManager.new(suppress=(Exception,)) as ncm:
for port in device_data['ports']:
port_id = self._get_port_from_pt(device_data, port['id'])
ncm.retry(self.compute_handler_nova.detach_interface,
token,
device_data['tenant_id'],
device_data['id'],
port_id)
# Async change
self._delete_port(token, port_id)
# Async change: Delete stale l2ps
try:
self._delete_l2ps(token, device_data, network_handler)
except Exception:
pass
return True
def _delete_l2ps(self, token, device_data, network_handler):
'''
delete l2 policies
'''
gbp_cli = network_handler.network_handler
for ptg in device_data['provider']['ptg']:
try:
ptg_details = gbp_cli.get_policy_target_group(token,
ptg['id'])
if ptg_details:
LOG.debug('Provider ptg is in use !!')
continue
except Exception:
LOG.debug('Provider not found !!')
with nfp_ctx_mgr.GBPContextManager as gcm:
l2p = gbp_cli.get_l2_policy(token, ptg['l2_policy_id'])
# deleting l2p if it is created implicitly
if 'Implicitly' in l2p['description']:
gcm.retry(gbp_cli.delete_l2_policy, token,
ptg['l2_policy_id'])
if ('consumer' not in device_data.keys() or not device_data[
'consumer'].get('ptg')):
return
for ptg in device_data['consumer']['ptg']:
try:
ptg_details = gbp_cli.get_policy_target_group(token,
ptg['id'])
if ptg_details:
LOG.debug('Stitching PTG is in use !!')
continue
except Exception:
LOG.debug('Stitching PTG not found !!')
with nfp_ctx_mgr.GBPContextManager as gcm:
l2p = gbp_cli.get_l2_policy(token, ptg['l2_policy_id'])
# deleting l2p if it is created implicitly
if 'Implicitly' in l2p['description']:
gcm.retry(gbp_cli.delete_l2_policy, token,
ptg['l2_policy_id'])
def _delete_port(self, token, port_id):
'''
delete neutron port
'''
try:
network_handler = self.network_handlers[nfp_constants.NEUTRON_MODE]
network_handler.delete_port(token, port_id)
except Exception as exc:
LOG.error("Failed to delete port %(port_id)s. Error: %(exc)s",
{"port_id": port_id, 'exc': exc})
def _get_port_from_pt(self, device_data, pt_id):
'''
get neutron_port_id from pt_id using data
'''
port_id = None
for pt in device_data['provider']['pt']:
if pt['id'] == pt_id:
return pt['port_id']
if not device_data['consumer'].get('pt'):
return port_id
for pt in device_data['consumer']['pt']:
if pt['id'] == pt_id:
return pt['port_id']
LOG.error('Policy Target %(pt_id) not found in provided data',
{'pt_id': pt_id})
return port_id
def get_port_details(self, port_id, port_model, data):
'''
function to retrieve port details from data
'''
if 'gbp' in port_model:
for pt in data['pt']:
if port_id == pt['id']:
port_id = pt['port_id']
break
for port in data['port']:
if port_id == port['id']:
ip = port['fixed_ips'][0]['ip_address']
mac = port['mac_address']
cidr = data['subnet']['cidr']
gateway_ip = data['subnet']['gateway_ip']
return (ip, mac, cidr, gateway_ip, port, data['subnet'])
@_set_network_handler
def get_delete_device_data(self, device_data, network_handler=None,
devices_data=None):
""" Get the configuration information for NFD
:param device_data: NFD
:type device_data: dict
:param devices_data: metadata of NFD and NF
:type device_data: dict
:returns: None -- On Failure
:returns: dict
:raises: exceptions.IncompleteData
"""
if (
any(key not in device_data
for key in ['service_details',
'mgmt_ip_address',
'ports']) or
type(device_data['service_details']) is not dict or
any(key not in device_data['service_details']
for key in ['service_vendor',
'device_type',
'network_mode']) or
type(device_data['ports']) is not list or
any(key not in port
for port in device_data['ports']
for key in ['id',
'port_classification',
'port_model'])
):
LOG.error('Incomplete device data received for delete '
'network function device.')
return None
token = self._get_token(device_data.get('token'))
if not token:
return None
provider_ip = None
provider_mac = None
provider_cidr = None
consumer_ip = None
consumer_mac = None
consumer_cidr = None
consumer_gateway_ip = None
for port in device_data['ports']:
if port['port_classification'] == nfp_constants.PROVIDER:
try:
(provider_ip, provider_mac, provider_cidr, dummy, _, _) = (
self.get_port_details(port['id'], port['port_model'],
devices_data['provider'])
)
except Exception:
LOG.error('Failed to get provider port details'
' for get device config info operation')
return None
elif port['port_classification'] == nfp_constants.CONSUMER:
try:
(consumer_ip, consumer_mac, consumer_cidr,
consumer_gateway_ip, _, _) = (
self.get_port_details(port['id'], port['port_model'],
devices_data['consumer'])
)
except Exception:
LOG.error('Failed to get consumer port details'
' for get device config info operation')
return None
device_data.update({
'provider_ip': provider_ip, 'provider_mac': provider_mac,
'provider_cidr': provider_cidr, 'consumer_ip': consumer_ip,
'consumer_mac': consumer_mac, 'consumer_cidr': consumer_cidr,
'consumer_gateway_ip': consumer_gateway_ip})
return device_data
@_set_network_handler
def get_network_function_device_config(self, device_data,
resource_type, is_delete=False,
network_handler=None,
devices_data=None):
""" Get the configuration information for NFD
:returns: dict
"""
if is_delete:
device_data = self.get_delete_device_data(
device_data, network_handler=network_handler,
devices_data=devices_data)
if not device_data:
return None
return df.get_network_function_info(
device_data, resource_type)