
This is a very preliminary version of a new APIC mechanism driver utilizing the ACI Integration Module (AIM) library concurrently being developed. A corresponding extension driver exposes details regarding the mapping of the Neutron resources to APIC. These drivers require the Ml2Plus extended driver APIs. See the apic-aim-ml2-driver devref for implementation details and for devstack configuration instructions. Change-Id: I82df32f0880d6a0d53b305f6c6391fcbea049d1b
134 lines
4.9 KiB
Python
134 lines
4.9 KiB
Python
# Copyright (c) 2016 Cisco Systems Inc.
|
|
# All Rights Reserved.
|
|
#
|
|
# 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 re
|
|
|
|
from neutron._i18n import _LI
|
|
|
|
LOG = None
|
|
|
|
|
|
NAME_TYPE_TENANT = 'tenant'
|
|
NAME_TYPE_NETWORK = 'network'
|
|
NAME_TYPE_POLICY_TARGET_GROUP = 'policy_target_group'
|
|
|
|
MAX_APIC_NAME_LENGTH = 46
|
|
|
|
|
|
# TODO(rkukura): This is name mapper is copied from the apicapi repo,
|
|
# and modified to pass in resource names rather than calling the core
|
|
# plugin to get them, and to use the existing DB session. We need
|
|
# decide whether to make these changes in apicapi (maybe on a branch),
|
|
# move this some other repo, or keep it here. The changes are not
|
|
# backwards compatible. The implementation should also be cleaned up
|
|
# and simplified. For example, sessions should be passed in place of
|
|
# contexts, and the core plugin calls eliminated.
|
|
|
|
|
|
def truncate(string, max_length):
|
|
if max_length < 0:
|
|
return ''
|
|
return string[:max_length] if len(string) > max_length else string
|
|
|
|
|
|
class APICNameMapper(object):
|
|
def __init__(self, db, log):
|
|
self.db = db
|
|
self.min_suffix = 5
|
|
global LOG
|
|
LOG = log.getLogger(__name__)
|
|
|
|
def mapper(name_type):
|
|
"""Wrapper to land all the common operations between mappers."""
|
|
def wrap(func):
|
|
def inner(inst, session, resource_id, resource_name=None):
|
|
saved_name = inst.db.get_apic_name(session,
|
|
resource_id,
|
|
name_type)
|
|
if saved_name:
|
|
result = saved_name[0]
|
|
return result
|
|
name = ''
|
|
try:
|
|
name = func(inst, session, resource_id, resource_name)
|
|
except Exception as e:
|
|
LOG.warn(("Exception in looking up name %s"), name_type)
|
|
LOG.error(e.message)
|
|
|
|
purged_id = re.sub(r"-+", "-", resource_id)
|
|
result = purged_id[:inst.min_suffix]
|
|
if name:
|
|
name = re.sub(r"-+", "-", name)
|
|
# Keep as many uuid chars as possible
|
|
id_suffix = "_" + result
|
|
max_name_length = MAX_APIC_NAME_LENGTH - len(id_suffix)
|
|
result = truncate(name, max_name_length) + id_suffix
|
|
|
|
result = truncate(result, MAX_APIC_NAME_LENGTH)
|
|
# Remove forbidden whitespaces
|
|
result = result.replace(' ', '')
|
|
result = inst._grow_id_if_needed(
|
|
session, purged_id, name_type, result,
|
|
start=inst.min_suffix)
|
|
else:
|
|
result = purged_id
|
|
|
|
inst.db.add_apic_name(session, resource_id,
|
|
name_type, result)
|
|
return result
|
|
return inner
|
|
return wrap
|
|
|
|
def _grow_id_if_needed(self, session, resource_id, name_type,
|
|
current_result, start=0):
|
|
result = current_result
|
|
if result.endswith('_'):
|
|
result = result[:-1]
|
|
try:
|
|
x = 0
|
|
while True:
|
|
if self.db.get_filtered_apic_names(session,
|
|
neutron_type=name_type,
|
|
apic_name=result):
|
|
if x == 0 and start == 0:
|
|
result += '_'
|
|
# This name overlaps, add more ID characters
|
|
result += resource_id[start + x]
|
|
x += 1
|
|
else:
|
|
break
|
|
except AttributeError:
|
|
LOG.info(_LI("Current DB API doesn't support "
|
|
"get_filtered_apic_names."))
|
|
except IndexError:
|
|
LOG.debug("Ran out of ID characters.")
|
|
return result
|
|
|
|
@mapper(NAME_TYPE_TENANT)
|
|
def tenant(self, session, tenant_id, tenant_name=None):
|
|
return tenant_name
|
|
|
|
@mapper(NAME_TYPE_NETWORK)
|
|
def network(self, session, network_id, network_name=None):
|
|
return network_name
|
|
|
|
@mapper(NAME_TYPE_POLICY_TARGET_GROUP)
|
|
def policy_target_group(self, session, policy_target_group_id,
|
|
policy_target_group_name=None):
|
|
return policy_target_group_name
|
|
|
|
def delete_apic_name(self, session, object_id):
|
|
self.db.delete_apic_name(session, object_id)
|