]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Apic drivers enhancements (second approach): Backend
authorIvar Lazzaro <ivarlazzaro@gmail.com>
Thu, 21 Aug 2014 23:34:27 +0000 (16:34 -0700)
committerIvar Lazzaro <ivarlazzaro@gmail.com>
Thu, 28 Aug 2014 17:37:41 +0000 (10:37 -0700)
- Move backend facing modules to a library

Implements blueprint: apic-driver-enhancements

Change-Id: Ia4553d3885ca1886ca6bc7ea5d96afeace5fc457

12 files changed:
etc/neutron/plugins/ml2/ml2_conf_cisco.ini
neutron/plugins/ml2/drivers/cisco/apic/apic_client.py [deleted file]
neutron/plugins/ml2/drivers/cisco/apic/apic_manager.py [deleted file]
neutron/plugins/ml2/drivers/cisco/apic/config.py
neutron/plugins/ml2/drivers/cisco/apic/exceptions.py [deleted file]
neutron/plugins/ml2/drivers/cisco/apic/mechanism_apic.py
neutron/services/l3_router/l3_apic.py
neutron/tests/unit/ml2/drivers/cisco/apic/test_cisco_apic_client.py [deleted file]
neutron/tests/unit/ml2/drivers/cisco/apic/test_cisco_apic_common.py
neutron/tests/unit/ml2/drivers/cisco/apic/test_cisco_apic_manager.py [deleted file]
neutron/tests/unit/ml2/drivers/cisco/apic/test_cisco_apic_mechanism_driver.py
neutron/tests/unit/services/l3_router/test_l3_apic_plugin.py

index 95f963f8369bc8ba5933d0e1a9cd5c18e9243136..bb2dadbed4f520a39af5cea69ea81c027b521f84 100644 (file)
@@ -49,8 +49,8 @@
 
 [ml2_cisco_apic]
 
-# Hostname for the APIC controller
-# apic_host=1.1.1.1
+# Hostname:port list of APIC controllers
+# apic_hosts=1.1.1.1:80, 1.1.1.2:8080, 1.1.1.3:80
 
 # Username for the APIC controller
 # apic_username=user
@@ -58,9 +58,6 @@
 # Password for the APIC controller
 # apic_password=password
 
-# Port for the APIC Controller
-# apic_port=80
-
 # Names for APIC objects used by Neutron
 # Note: When deploying multiple clouds against one APIC,
 #       these names must be unique between the clouds.
diff --git a/neutron/plugins/ml2/drivers/cisco/apic/apic_client.py b/neutron/plugins/ml2/drivers/cisco/apic/apic_client.py
deleted file mode 100644 (file)
index 9793009..0000000
+++ /dev/null
@@ -1,416 +0,0 @@
-# Copyright (c) 2014 Cisco Systems
-# 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.
-#
-# @author: Henry Gessau, Cisco Systems
-
-import collections
-import time
-
-import requests
-import requests.exceptions
-
-from neutron.openstack.common import jsonutils
-from neutron.openstack.common import log as logging
-from neutron.plugins.ml2.drivers.cisco.apic import exceptions as cexc
-
-
-LOG = logging.getLogger(__name__)
-
-APIC_CODE_FORBIDDEN = str(requests.codes.forbidden)
-
-
-# Info about a Managed Object's relative name (RN) and container.
-class ManagedObjectName(collections.namedtuple(
-        'MoPath', ['container', 'rn_fmt', 'can_create'])):
-    def __new__(cls, container, rn_fmt, can_create=True):
-        return super(ManagedObjectName, cls).__new__(cls, container, rn_fmt,
-                                                     can_create)
-
-
-class ManagedObjectClass(object):
-
-    """Information about a Managed Object (MO) class.
-
-    Constructs and keeps track of the distinguished name (DN) and relative
-    name (RN) of a managed object (MO) class. The DN is the RN of the MO
-    appended to the recursive RNs of its containers, i.e.:
-        DN = uni/container-RN/.../container-RN/object-RN
-
-    Also keeps track of whether the MO can be created in the APIC, as some
-    MOs are read-only or used for specifying relationships.
-    """
-
-    supported_mos = {
-        'fvTenant': ManagedObjectName(None, 'tn-%s'),
-        'fvBD': ManagedObjectName('fvTenant', 'BD-%s'),
-        'fvRsBd': ManagedObjectName('fvAEPg', 'rsbd'),
-        'fvSubnet': ManagedObjectName('fvBD', 'subnet-[%s]'),
-        'fvCtx': ManagedObjectName('fvTenant', 'ctx-%s'),
-        'fvRsCtx': ManagedObjectName('fvBD', 'rsctx'),
-        'fvAp': ManagedObjectName('fvTenant', 'ap-%s'),
-        'fvAEPg': ManagedObjectName('fvAp', 'epg-%s'),
-        'fvRsProv': ManagedObjectName('fvAEPg', 'rsprov-%s'),
-        'fvRsCons': ManagedObjectName('fvAEPg', 'rscons-%s'),
-        'fvRsConsIf': ManagedObjectName('fvAEPg', 'rsconsif-%s'),
-        'fvRsDomAtt': ManagedObjectName('fvAEPg', 'rsdomAtt-[%s]'),
-        'fvRsPathAtt': ManagedObjectName('fvAEPg', 'rspathAtt-[%s]'),
-
-        'vzBrCP': ManagedObjectName('fvTenant', 'brc-%s'),
-        'vzSubj': ManagedObjectName('vzBrCP', 'subj-%s'),
-        'vzFilter': ManagedObjectName('fvTenant', 'flt-%s'),
-        'vzRsFiltAtt': ManagedObjectName('vzSubj', 'rsfiltAtt-%s'),
-        'vzEntry': ManagedObjectName('vzFilter', 'e-%s'),
-        'vzInTerm': ManagedObjectName('vzSubj', 'intmnl'),
-        'vzRsFiltAtt__In': ManagedObjectName('vzInTerm', 'rsfiltAtt-%s'),
-        'vzOutTerm': ManagedObjectName('vzSubj', 'outtmnl'),
-        'vzRsFiltAtt__Out': ManagedObjectName('vzOutTerm', 'rsfiltAtt-%s'),
-        'vzCPIf': ManagedObjectName('fvTenant', 'cif-%s'),
-        'vzRsIf': ManagedObjectName('vzCPIf', 'rsif'),
-
-        'vmmProvP': ManagedObjectName(None, 'vmmp-%s', False),
-        'vmmDomP': ManagedObjectName('vmmProvP', 'dom-%s'),
-        'vmmEpPD': ManagedObjectName('vmmDomP', 'eppd-[%s]'),
-
-        'physDomP': ManagedObjectName(None, 'phys-%s'),
-
-        'infra': ManagedObjectName(None, 'infra'),
-        'infraNodeP': ManagedObjectName('infra', 'nprof-%s'),
-        'infraLeafS': ManagedObjectName('infraNodeP', 'leaves-%s-typ-%s'),
-        'infraNodeBlk': ManagedObjectName('infraLeafS', 'nodeblk-%s'),
-        'infraRsAccPortP': ManagedObjectName('infraNodeP', 'rsaccPortP-[%s]'),
-        'infraAccPortP': ManagedObjectName('infra', 'accportprof-%s'),
-        'infraHPortS': ManagedObjectName('infraAccPortP', 'hports-%s-typ-%s'),
-        'infraPortBlk': ManagedObjectName('infraHPortS', 'portblk-%s'),
-        'infraRsAccBaseGrp': ManagedObjectName('infraHPortS', 'rsaccBaseGrp'),
-        'infraFuncP': ManagedObjectName('infra', 'funcprof'),
-        'infraAccPortGrp': ManagedObjectName('infraFuncP', 'accportgrp-%s'),
-        'infraRsAttEntP': ManagedObjectName('infraAccPortGrp', 'rsattEntP'),
-        'infraAttEntityP': ManagedObjectName('infra', 'attentp-%s'),
-        'infraRsDomP': ManagedObjectName('infraAttEntityP', 'rsdomP-[%s]'),
-        'infraRsVlanNs__phys': ManagedObjectName('physDomP', 'rsvlanNs'),
-        'infraRsVlanNs__vmm': ManagedObjectName('vmmDomP', 'rsvlanNs'),
-
-        'fvnsVlanInstP': ManagedObjectName('infra', 'vlanns-%s-%s'),
-        'fvnsEncapBlk__vlan': ManagedObjectName('fvnsVlanInstP',
-                                                'from-%s-to-%s'),
-        'fvnsVxlanInstP': ManagedObjectName('infra', 'vxlanns-%s'),
-        'fvnsEncapBlk__vxlan': ManagedObjectName('fvnsVxlanInstP',
-                                                 'from-%s-to-%s'),
-
-        # Read-only
-        'fabricTopology': ManagedObjectName(None, 'topology', False),
-        'fabricPod': ManagedObjectName('fabricTopology', 'pod-%s', False),
-        'fabricPathEpCont': ManagedObjectName('fabricPod', 'paths-%s', False),
-        'fabricPathEp': ManagedObjectName('fabricPathEpCont', 'pathep-%s',
-                                          False),
-    }
-
-    # Note(Henry): The use of a mutable default argument _inst_cache is
-    # intentional. It persists for the life of MoClass to cache instances.
-    # noinspection PyDefaultArgument
-    def __new__(cls, mo_class, _inst_cache={}):
-        """Ensure we create only one instance per mo_class."""
-        try:
-            return _inst_cache[mo_class]
-        except KeyError:
-            new_inst = super(ManagedObjectClass, cls).__new__(cls)
-            new_inst.__init__(mo_class)
-            _inst_cache[mo_class] = new_inst
-            return new_inst
-
-    def __init__(self, mo_class):
-        self.klass = mo_class
-        self.klass_name = mo_class.split('__')[0]
-        mo = self.supported_mos[mo_class]
-        self.container = mo.container
-        self.rn_fmt = mo.rn_fmt
-        self.dn_fmt, self.args = self._dn_fmt()
-        self.arg_count = self.dn_fmt.count('%s')
-        rn_has_arg = self.rn_fmt.count('%s')
-        self.can_create = rn_has_arg and mo.can_create
-
-    def _dn_fmt(self):
-        """Build the distinguished name format using container and RN.
-
-        DN = uni/container-RN/.../container-RN/object-RN
-
-        Also make a list of the required name arguments.
-        Note: Call this method only once at init.
-        """
-        arg = [self.klass] if '%s' in self.rn_fmt else []
-        if self.container:
-            container = ManagedObjectClass(self.container)
-            dn_fmt = '%s/%s' % (container.dn_fmt, self.rn_fmt)
-            args = container.args + arg
-            return dn_fmt, args
-        return 'uni/%s' % self.rn_fmt, arg
-
-    def dn(self, *args):
-        """Return the distinguished name for a managed object."""
-        return self.dn_fmt % args
-
-
-class ApicSession(object):
-
-    """Manages a session with the APIC."""
-
-    def __init__(self, host, port, usr, pwd, ssl):
-        protocol = ssl and 'https' or 'http'
-        self.api_base = '%s://%s:%s/api' % (protocol, host, port)
-        self.session = requests.Session()
-        self.session_deadline = 0
-        self.session_timeout = 0
-        self.cookie = {}
-
-        # Log in
-        self.authentication = None
-        self.username = None
-        self.password = None
-        if usr and pwd:
-            self.login(usr, pwd)
-
-    @staticmethod
-    def _make_data(key, **attrs):
-        """Build the body for a msg out of a key and some attributes."""
-        return jsonutils.dumps({key: {'attributes': attrs}})
-
-    def _api_url(self, api):
-        """Create the URL for a generic API."""
-        return '%s/%s.json' % (self.api_base, api)
-
-    def _mo_url(self, mo, *args):
-        """Create a URL for a MO lookup by DN."""
-        dn = mo.dn(*args)
-        return '%s/mo/%s.json' % (self.api_base, dn)
-
-    def _qry_url(self, mo):
-        """Create a URL for a query lookup by MO class."""
-        return '%s/class/%s.json' % (self.api_base, mo.klass_name)
-
-    def _check_session(self):
-        """Check that we are logged in and ensure the session is active."""
-        if not self.authentication:
-            raise cexc.ApicSessionNotLoggedIn
-        if time.time() > self.session_deadline:
-            self.refresh()
-
-    def _send(self, request, url, data=None, refreshed=None):
-        """Send a request and process the response."""
-        if data is None:
-            response = request(url, cookies=self.cookie)
-        else:
-            response = request(url, data=data, cookies=self.cookie)
-        if response is None:
-            raise cexc.ApicHostNoResponse(url=url)
-        # Every request refreshes the timeout
-        self.session_deadline = time.time() + self.session_timeout
-        if data is None:
-            request_str = url
-        else:
-            request_str = '%s, data=%s' % (url, data)
-            LOG.debug(_("data = %s"), data)
-        # imdata is where the APIC returns the useful information
-        imdata = response.json().get('imdata')
-        LOG.debug(_("Response: %s"), imdata)
-        if response.status_code != requests.codes.ok:
-            try:
-                err_code = imdata[0]['error']['attributes']['code']
-                err_text = imdata[0]['error']['attributes']['text']
-            except (IndexError, KeyError):
-                err_code = '[code for APIC error not found]'
-                err_text = '[text for APIC error not found]'
-            # If invalid token then re-login and retry once
-            if (not refreshed and err_code == APIC_CODE_FORBIDDEN and
-                    err_text.lower().startswith('token was invalid')):
-                self.login()
-                return self._send(request, url, data=data, refreshed=True)
-            raise cexc.ApicResponseNotOk(request=request_str,
-                                         status=response.status_code,
-                                         reason=response.reason,
-                                         err_text=err_text, err_code=err_code)
-        return imdata
-
-    # REST requests
-
-    def get_data(self, request):
-        """Retrieve generic data from the server."""
-        self._check_session()
-        url = self._api_url(request)
-        return self._send(self.session.get, url)
-
-    def get_mo(self, mo, *args):
-        """Retrieve a managed object by its distinguished name."""
-        self._check_session()
-        url = self._mo_url(mo, *args) + '?query-target=self'
-        return self._send(self.session.get, url)
-
-    def list_mo(self, mo):
-        """Retrieve the list of managed objects for a class."""
-        self._check_session()
-        url = self._qry_url(mo)
-        return self._send(self.session.get, url)
-
-    def post_data(self, request, data):
-        """Post generic data to the server."""
-        self._check_session()
-        url = self._api_url(request)
-        return self._send(self.session.post, url, data=data)
-
-    def post_mo(self, mo, *args, **kwargs):
-        """Post data for a managed object to the server."""
-        self._check_session()
-        url = self._mo_url(mo, *args)
-        data = self._make_data(mo.klass_name, **kwargs)
-        return self._send(self.session.post, url, data=data)
-
-    # Session management
-
-    def _save_cookie(self, request, response):
-        """Save the session cookie and its expiration time."""
-        imdata = response.json().get('imdata')
-        if response.status_code == requests.codes.ok:
-            attributes = imdata[0]['aaaLogin']['attributes']
-            try:
-                self.cookie = {'APIC-Cookie': attributes['token']}
-            except KeyError:
-                raise cexc.ApicResponseNoCookie(request=request)
-            timeout = int(attributes['refreshTimeoutSeconds'])
-            LOG.debug(_("APIC session will expire in %d seconds"), timeout)
-            # Give ourselves a few seconds to refresh before timing out
-            self.session_timeout = timeout - 5
-            self.session_deadline = time.time() + self.session_timeout
-        else:
-            attributes = imdata[0]['error']['attributes']
-        return attributes
-
-    def login(self, usr=None, pwd=None):
-        """Log in to controller. Save user name and authentication."""
-        usr = usr or self.username
-        pwd = pwd or self.password
-        name_pwd = self._make_data('aaaUser', name=usr, pwd=pwd)
-        url = self._api_url('aaaLogin')
-        try:
-            response = self.session.post(url, data=name_pwd, timeout=10.0)
-        except requests.exceptions.Timeout:
-            raise cexc.ApicHostNoResponse(url=url)
-        attributes = self._save_cookie('aaaLogin', response)
-        if response.status_code == requests.codes.ok:
-            self.username = usr
-            self.password = pwd
-            self.authentication = attributes
-        else:
-            self.authentication = None
-            raise cexc.ApicResponseNotOk(request=url,
-                                         status=response.status_code,
-                                         reason=response.reason,
-                                         err_text=attributes['text'],
-                                         err_code=attributes['code'])
-
-    def refresh(self):
-        """Called when a session has timed out or almost timed out."""
-        url = self._api_url('aaaRefresh')
-        response = self.session.get(url, cookies=self.cookie)
-        attributes = self._save_cookie('aaaRefresh', response)
-        if response.status_code == requests.codes.ok:
-            # We refreshed before the session timed out.
-            self.authentication = attributes
-        else:
-            err_code = attributes['code']
-            err_text = attributes['text']
-            if (err_code == APIC_CODE_FORBIDDEN and
-                    err_text.lower().startswith('token was invalid')):
-                # This means the token timed out, so log in again.
-                LOG.debug(_("APIC session timed-out, logging in again."))
-                self.login()
-            else:
-                self.authentication = None
-                raise cexc.ApicResponseNotOk(request=url,
-                                             status=response.status_code,
-                                             reason=response.reason,
-                                             err_text=err_text,
-                                             err_code=err_code)
-
-    def logout(self):
-        """End session with controller."""
-        if not self.username:
-            self.authentication = None
-        if self.authentication:
-            data = self._make_data('aaaUser', name=self.username)
-            self.post_data('aaaLogout', data=data)
-        self.authentication = None
-
-
-class ManagedObjectAccess(object):
-
-    """CRUD operations on APIC Managed Objects."""
-
-    def __init__(self, session, mo_class):
-        self.session = session
-        self.mo = ManagedObjectClass(mo_class)
-
-    def _create_container(self, *args):
-        """Recursively create all container objects."""
-        if self.mo.container:
-            container = ManagedObjectAccess(self.session, self.mo.container)
-            if container.mo.can_create:
-                container_args = args[0: container.mo.arg_count]
-                container._create_container(*container_args)
-                container.session.post_mo(container.mo, *container_args)
-
-    def create(self, *args, **kwargs):
-        self._create_container(*args)
-        if self.mo.can_create and 'status' not in kwargs:
-            kwargs['status'] = 'created'
-        return self.session.post_mo(self.mo, *args, **kwargs)
-
-    def _mo_attributes(self, obj_data):
-        if (self.mo.klass_name in obj_data and
-                'attributes' in obj_data[self.mo.klass_name]):
-            return obj_data[self.mo.klass_name]['attributes']
-
-    def get(self, *args):
-        """Return a dict of the MO's attributes, or None."""
-        imdata = self.session.get_mo(self.mo, *args)
-        if imdata:
-            return self._mo_attributes(imdata[0])
-
-    def list_all(self):
-        imdata = self.session.list_mo(self.mo)
-        return filter(None, [self._mo_attributes(obj) for obj in imdata])
-
-    def list_names(self):
-        return [obj['name'] for obj in self.list_all()]
-
-    def update(self, *args, **kwargs):
-        return self.session.post_mo(self.mo, *args, **kwargs)
-
-    def delete(self, *args):
-        return self.session.post_mo(self.mo, *args, status='deleted')
-
-
-class RestClient(ApicSession):
-
-    """APIC REST client for OpenStack Neutron."""
-
-    def __init__(self, host, port=80, usr=None, pwd=None, ssl=False):
-        """Establish a session with the APIC."""
-        super(RestClient, self).__init__(host, port, usr, pwd, ssl)
-
-    def __getattr__(self, mo_class):
-        """Add supported MOs as properties on demand."""
-        if mo_class not in ManagedObjectClass.supported_mos:
-            raise cexc.ApicManagedObjectNotSupported(mo_class=mo_class)
-        self.__dict__[mo_class] = ManagedObjectAccess(self, mo_class)
-        return self.__dict__[mo_class]
diff --git a/neutron/plugins/ml2/drivers/cisco/apic/apic_manager.py b/neutron/plugins/ml2/drivers/cisco/apic/apic_manager.py
deleted file mode 100644 (file)
index ebdb67c..0000000
+++ /dev/null
@@ -1,559 +0,0 @@
-# Copyright (c) 2014 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.
-#
-# @author: Arvind Somya (asomya@cisco.com), Cisco Systems Inc.
-
-import itertools
-import uuid
-
-from oslo.config import cfg
-
-from neutron.openstack.common import excutils
-from neutron.plugins.ml2.drivers.cisco.apic import apic_client
-from neutron.plugins.ml2.drivers.cisco.apic import apic_model
-from neutron.plugins.ml2.drivers.cisco.apic import config
-from neutron.plugins.ml2.drivers.cisco.apic import exceptions as cexc
-
-AP_NAME = 'openstack'
-CONTEXT_ENFORCED = '1'
-CONTEXT_UNENFORCED = '2'
-CONTEXT_DEFAULT = 'default'
-DN_KEY = 'dn'
-PORT_DN_PATH = 'topology/pod-1/paths-%s/pathep-[eth%s]'
-SCOPE_GLOBAL = 'global'
-SCOPE_TENANT = 'tenant'
-TENANT_COMMON = 'common'
-
-
-def group_by_ranges(i):
-    """Group a list of numbers into tuples representing contiguous ranges."""
-    for a, b in itertools.groupby(enumerate(sorted(i)), lambda (x, y): y - x):
-        b = list(b)
-        yield b[0][1], b[-1][1]
-
-
-class APICManager(object):
-    """Class to manage APIC translations and workflow.
-
-    This class manages translation from Neutron objects to APIC
-    managed objects and contains workflows to implement these
-    translations.
-    """
-    def __init__(self):
-        self.db = apic_model.ApicDbModel()
-
-        apic_conf = cfg.CONF.ml2_cisco_apic
-        self.switch_dict = config.create_switch_dictionary()
-
-        # Connect to the APIC
-        self.apic = apic_client.RestClient(
-            apic_conf.apic_host,
-            apic_conf.apic_port,
-            apic_conf.apic_username,
-            apic_conf.apic_password
-        )
-
-        self.port_profiles = {}
-        self.vmm_domain = None
-        self.phys_domain = None
-        self.vlan_ns = None
-        self.node_profiles = {}
-        self.entity_profile = None
-        self.function_profile = None
-        self.clear_node_profiles = apic_conf.apic_clear_node_profiles
-
-    def ensure_infra_created_on_apic(self):
-        """Ensure the infrastructure is setup.
-
-        Loop over the switch dictionary from the config and
-        setup profiles for switches, modules and ports
-        """
-        # Loop over switches
-        for switch in self.switch_dict:
-            # Create a node profile for this switch
-            self.ensure_node_profile_created_for_switch(switch)
-
-            # Check if a port profile exists for this node
-            ppname = self.check_infra_port_profiles(switch)
-
-            # Gather port ranges for this switch
-            modules = self.gather_infra_module_ports(switch)
-
-            # Setup each module and port range
-            for module in modules:
-                profile = self.db.get_profile_for_module(switch, ppname,
-                                                         module)
-                if not profile:
-                    # Create host port selector for this module
-                    hname = uuid.uuid4()
-                    try:
-                        self.apic.infraHPortS.create(ppname, hname, 'range')
-                        # Add relation to the function profile
-                        fpdn = self.function_profile[DN_KEY]
-                        self.apic.infraRsAccBaseGrp.create(ppname, hname,
-                                                           'range', tDn=fpdn)
-                        modules[module].sort()
-                    except (cexc.ApicResponseNotOk, KeyError):
-                        with excutils.save_and_reraise_exception():
-                            self.apic.infraHPortS.delete(ppname, hname,
-                                                         'range')
-                else:
-                    hname = profile.hpselc_id
-
-                ranges = group_by_ranges(modules[module])
-                # Add this module and ports to the profile
-                for prange in ranges:
-                    # Check if this port block is already added to the profile
-                    if not self.db.get_profile_for_module_and_ports(
-                            switch, ppname, module, prange[0], prange[-1]):
-                        # Create port block for this port range
-                        pbname = uuid.uuid4()
-                        self.apic.infraPortBlk.create(ppname, hname, 'range',
-                                                      pbname, fromCard=module,
-                                                      toCard=module,
-                                                      fromPort=str(prange[0]),
-                                                      toPort=str(prange[-1]))
-                        # Add DB row
-                        self.db.add_profile_for_module_and_ports(
-                            switch, ppname, hname, module,
-                            prange[0], prange[-1])
-
-    def check_infra_port_profiles(self, switch):
-        """Check and create infra port profiles for a node."""
-        sprofile = self.db.get_port_profile_for_node(switch)
-        ppname = None
-        if not sprofile:
-            # Generate uuid for port profile name
-            ppname = uuid.uuid4()
-            try:
-                # Create port profile for this switch
-                pprofile = self.ensure_port_profile_created_on_apic(ppname)
-                # Add port profile to node profile
-                ppdn = pprofile[DN_KEY]
-                self.apic.infraRsAccPortP.create(switch, ppdn)
-            except (cexc.ApicResponseNotOk, KeyError):
-                with excutils.save_and_reraise_exception():
-                    # Delete port profile
-                    self.apic.infraAccPortP.delete(ppname)
-        else:
-            ppname = sprofile.profile_id
-
-        return ppname
-
-    def gather_infra_module_ports(self, switch):
-        """Build modules and ports per module dictionary."""
-        ports = self.switch_dict[switch]
-        # Gather common modules
-        modules = {}
-        for port in ports:
-            module, sw_port = port.split('/')
-            if module not in modules:
-                modules[module] = []
-            modules[module].append(int(sw_port))
-
-        return modules
-
-    def ensure_context_unenforced(self, tenant_id=TENANT_COMMON,
-                                  name=CONTEXT_DEFAULT):
-        """Set the specified tenant's context to unenforced."""
-        ctx = self.apic.fvCtx.get(tenant_id, name)
-        if not ctx:
-            self.apic.fvCtx.create(tenant_id, name,
-                                   pcEnfPref=CONTEXT_UNENFORCED)
-        elif ctx['pcEnfPref'] != CONTEXT_UNENFORCED:
-            self.apic.fvCtx.update(tenant_id, name,
-                                   pcEnfPref=CONTEXT_UNENFORCED)
-
-    def ensure_context_enforced(self, tenant_id=TENANT_COMMON,
-                                name=CONTEXT_DEFAULT):
-        """Set the specified tenant's context to enforced."""
-        ctx = self.apic.fvCtx.get(tenant_id, name)
-        if not ctx:
-            self.apic.fvCtx.create(tenant_id, name, pcEnfPref=CONTEXT_ENFORCED)
-        elif ctx['pcEnfPref'] != CONTEXT_ENFORCED:
-            self.apic.fvCtx.update(tenant_id, name, pcEnfPref=CONTEXT_ENFORCED)
-
-    def ensure_entity_profile_created_on_apic(self, name):
-        """Create the infrastructure entity profile."""
-        if self.clear_node_profiles:
-            self.apic.infraAttEntityP.delete(name)
-        self.entity_profile = self.apic.infraAttEntityP.get(name)
-        if not self.entity_profile:
-            try:
-                phys_dn = self.phys_domain[DN_KEY]
-                self.apic.infraAttEntityP.create(name)
-                # Attach phys domain to entity profile
-                self.apic.infraRsDomP.create(name, phys_dn)
-                self.entity_profile = self.apic.infraAttEntityP.get(name)
-            except (cexc.ApicResponseNotOk, KeyError):
-                with excutils.save_and_reraise_exception():
-                    # Delete the created entity profile
-                    self.apic.infraAttEntityP.delete(name)
-
-    def ensure_function_profile_created_on_apic(self, name):
-        """Create the infrastructure function profile."""
-        if self.clear_node_profiles:
-            self.apic.infraAccPortGrp.delete(name)
-        self.function_profile = self.apic.infraAccPortGrp.get(name)
-        if not self.function_profile:
-            try:
-                self.apic.infraAccPortGrp.create(name)
-                # Attach entity profile to function profile
-                entp_dn = self.entity_profile[DN_KEY]
-                self.apic.infraRsAttEntP.create(name, tDn=entp_dn)
-                self.function_profile = self.apic.infraAccPortGrp.get(name)
-            except (cexc.ApicResponseNotOk, KeyError):
-                with excutils.save_and_reraise_exception():
-                    # Delete the created function profile
-                    self.apic.infraAccPortGrp.delete(name)
-
-    def ensure_node_profile_created_for_switch(self, switch_id):
-        """Creates a switch node profile.
-
-        Create a node profile for a switch and add a switch
-        to the leaf node selector
-        """
-        if self.clear_node_profiles:
-            self.apic.infraNodeP.delete(switch_id)
-            self.db.delete_profile_for_node(switch_id)
-        sobj = self.apic.infraNodeP.get(switch_id)
-        if not sobj:
-            try:
-                # Create Node profile
-                self.apic.infraNodeP.create(switch_id)
-                # Create leaf selector
-                lswitch_id = uuid.uuid4()
-                self.apic.infraLeafS.create(switch_id, lswitch_id, 'range')
-                # Add leaf nodes to the selector
-                name = uuid.uuid4()
-                self.apic.infraNodeBlk.create(switch_id, lswitch_id, 'range',
-                                              name, from_=switch_id,
-                                              to_=switch_id)
-                sobj = self.apic.infraNodeP.get(switch_id)
-            except (cexc.ApicResponseNotOk, KeyError):
-                with excutils.save_and_reraise_exception():
-                    # Remove the node profile
-                    self.apic.infraNodeP.delete(switch_id)
-
-        self.node_profiles[switch_id] = {
-            'object': sobj
-        }
-
-    def ensure_port_profile_created_on_apic(self, name):
-        """Create a port profile."""
-        try:
-            self.apic.infraAccPortP.create(name)
-            return self.apic.infraAccPortP.get(name)
-        except (cexc.ApicResponseNotOk, KeyError):
-            with excutils.save_and_reraise_exception():
-                self.apic.infraAccPortP.delete(name)
-
-    def ensure_vmm_domain_created_on_apic(self, vmm_name,
-                                          vlan_ns=None, vxlan_ns=None):
-        """Create Virtual Machine Manager domain.
-
-        Creates the VMM domain on the APIC and adds a VLAN or VXLAN
-        namespace to that VMM domain.
-        TODO (asomya): Add VXLAN support
-        """
-        provider = 'VMware'
-        if self.clear_node_profiles:
-            self.apic.vmmDomP.delete(provider, vmm_name)
-        self.vmm_domain = self.apic.vmmDomP.get(provider, vmm_name)
-        if not self.vmm_domain:
-            try:
-                self.apic.vmmDomP.create(provider, vmm_name)
-                if vlan_ns:
-                    vlan_ns_dn = vlan_ns[DN_KEY]
-                    self.apic.infraRsVlanNs__vmm.create(provider, vmm_name,
-                                                        tDn=vlan_ns_dn)
-                self.vmm_domain = self.apic.vmmDomP.get(provider, vmm_name)
-            except (cexc.ApicResponseNotOk, KeyError):
-                with excutils.save_and_reraise_exception():
-                    # Delete the VMM domain
-                    self.apic.vmmDomP.delete(provider, vmm_name)
-
-    def ensure_phys_domain_created_on_apic(self, phys_name,
-                                           vlan_ns=None):
-        """Create Virtual Machine Manager domain.
-
-        Creates the VMM domain on the APIC and adds a VLAN or VXLAN
-        namespace to that VMM domain.
-        TODO (asomya): Add VXLAN support
-        """
-        if self.clear_node_profiles:
-            self.apic.physDomP.delete(phys_name)
-        self.phys_domain = self.apic.physDomP.get(phys_name)
-        if not self.phys_domain:
-            try:
-                self.apic.physDomP.create(phys_name)
-                if vlan_ns:
-                    vlan_ns_dn = vlan_ns[DN_KEY]
-                    self.apic.infraRsVlanNs__phys.create(phys_name,
-                                                         tDn=vlan_ns_dn)
-                self.phys_domain = self.apic.physDomP.get(phys_name)
-            except (cexc.ApicResponseNotOk, KeyError):
-                with excutils.save_and_reraise_exception():
-                    # Delete the physical domain
-                    self.apic.physDomP.delete(phys_name)
-
-    def ensure_vlan_ns_created_on_apic(self, name, vlan_min, vlan_max):
-        """Creates a static VLAN namespace with the given vlan range."""
-        ns_args = name, 'static'
-        if self.clear_node_profiles:
-            self.apic.fvnsVlanInstP.delete(name, 'dynamic')
-            self.apic.fvnsVlanInstP.delete(*ns_args)
-        self.vlan_ns = self.apic.fvnsVlanInstP.get(*ns_args)
-        if not self.vlan_ns:
-            try:
-                self.apic.fvnsVlanInstP.create(*ns_args)
-                vlan_min = 'vlan-' + vlan_min
-                vlan_max = 'vlan-' + vlan_max
-                ns_blk_args = name, 'static', vlan_min, vlan_max
-                vlan_encap = self.apic.fvnsEncapBlk__vlan.get(*ns_blk_args)
-                if not vlan_encap:
-                    ns_kw_args = {
-                        'name': 'encap',
-                        'from': vlan_min,
-                        'to': vlan_max
-                    }
-                    self.apic.fvnsEncapBlk__vlan.create(*ns_blk_args,
-                                                        **ns_kw_args)
-                self.vlan_ns = self.apic.fvnsVlanInstP.get(*ns_args)
-                return self.vlan_ns
-            except (cexc.ApicResponseNotOk, KeyError):
-                with excutils.save_and_reraise_exception():
-                    # Delete the vlan namespace
-                    self.apic.fvnsVlanInstP.delete(*ns_args)
-
-    def ensure_tenant_created_on_apic(self, tenant_id):
-        """Make sure a tenant exists on the APIC."""
-        if not self.apic.fvTenant.get(tenant_id):
-            self.apic.fvTenant.create(tenant_id)
-
-    def ensure_bd_created_on_apic(self, tenant_id, bd_id):
-        """Creates a Bridge Domain on the APIC."""
-        if not self.apic.fvBD.get(tenant_id, bd_id):
-            try:
-                self.apic.fvBD.create(tenant_id, bd_id)
-                # Add default context to the BD
-                self.ensure_context_enforced()
-                self.apic.fvRsCtx.create(tenant_id, bd_id,
-                                         tnFvCtxName=CONTEXT_DEFAULT)
-            except (cexc.ApicResponseNotOk, KeyError):
-                with excutils.save_and_reraise_exception():
-                    # Delete the bridge domain
-                    self.apic.fvBD.delete(tenant_id, bd_id)
-
-    def delete_bd_on_apic(self, tenant_id, bd_id):
-        """Deletes a Bridge Domain from the APIC."""
-        self.apic.fvBD.delete(tenant_id, bd_id)
-
-    def ensure_subnet_created_on_apic(self, tenant_id, bd_id, gw_ip):
-        """Creates a subnet on the APIC
-
-        The gateway ip (gw_ip) should be specified as a CIDR
-        e.g. 10.0.0.1/24
-        """
-        if not self.apic.fvSubnet.get(tenant_id, bd_id, gw_ip):
-            self.apic.fvSubnet.create(tenant_id, bd_id, gw_ip)
-
-    def ensure_filter_created_on_apic(self, tenant_id, filter_id):
-        """Create a filter on the APIC."""
-        if not self.apic.vzFilter.get(tenant_id, filter_id):
-            self.apic.vzFilter.create(tenant_id, filter_id)
-
-    def ensure_epg_created_for_network(self, tenant_id, network_id, net_name):
-        """Creates an End Point Group on the APIC.
-
-        Create a new EPG on the APIC for the network spcified. This information
-        is also tracked in the local DB and associate the bridge domain for the
-        network with the EPG created.
-        """
-        # Check if an EPG is already present for this network
-        epg = self.db.get_epg_for_network(network_id)
-        if epg:
-            return epg
-
-        # Create a new EPG on the APIC
-        epg_uid = '-'.join([str(net_name), str(uuid.uuid4())])
-        try:
-            self.apic.fvAEPg.create(tenant_id, AP_NAME, epg_uid)
-
-            # Add bd to EPG
-            bd = self.apic.fvBD.get(tenant_id, network_id)
-            bd_name = bd['name']
-
-            # Create fvRsBd
-            self.apic.fvRsBd.create(tenant_id, AP_NAME, epg_uid,
-                                    tnFvBDName=bd_name)
-
-            # Add EPG to physical domain
-            phys_dn = self.phys_domain[DN_KEY]
-            self.apic.fvRsDomAtt.create(tenant_id, AP_NAME, epg_uid, phys_dn)
-        except (cexc.ApicResponseNotOk, KeyError):
-            with excutils.save_and_reraise_exception():
-                # Delete the EPG
-                self.apic.fvAEPg.delete(tenant_id, AP_NAME, epg_uid)
-
-        # Stick it in the DB
-        epg = self.db.write_epg_for_network(network_id, epg_uid)
-
-        return epg
-
-    def delete_epg_for_network(self, tenant_id, network_id):
-        """Deletes the EPG from the APIC and removes it from the DB."""
-        # Check if an EPG is already present for this network
-        epg = self.db.get_epg_for_network(network_id)
-        if not epg:
-            return False
-
-        # Delete this epg
-        self.apic.fvAEPg.delete(tenant_id, AP_NAME, epg.epg_id)
-        # Remove DB row
-        self.db.delete_epg(epg)
-
-    def create_tenant_filter(self, tenant_id):
-        """Creates a tenant filter and a generic entry under it."""
-        fuuid = uuid.uuid4()
-        try:
-            # Create a new tenant filter
-            self.apic.vzFilter.create(tenant_id, fuuid)
-            # Create a new entry
-            euuid = uuid.uuid4()
-            self.apic.vzEntry.create(tenant_id, fuuid, euuid)
-            return fuuid
-        except (cexc.ApicResponseNotOk, KeyError):
-            with excutils.save_and_reraise_exception():
-                self.apic.vzFilter.delete(tenant_id, fuuid)
-
-    def set_contract_for_epg(self, tenant_id, epg_id,
-                             contract_id, provider=False):
-        """Set the contract for an EPG.
-
-        By default EPGs are consumers to a contract. Set provider flag
-        for a single EPG to act as a contract provider.
-        """
-        if provider:
-            try:
-                self.apic.fvRsProv.create(tenant_id, AP_NAME,
-                                          epg_id, contract_id)
-                self.db.set_provider_contract(epg_id)
-                self.make_tenant_contract_global(tenant_id)
-            except (cexc.ApicResponseNotOk, KeyError):
-                with excutils.save_and_reraise_exception():
-                    self.make_tenant_contract_local(tenant_id)
-                    self.apic.fvRsProv.delete(tenant_id, AP_NAME,
-                                              epg_id, contract_id)
-        else:
-            self.apic.fvRsCons.create(tenant_id, AP_NAME, epg_id, contract_id)
-
-    def delete_contract_for_epg(self, tenant_id, epg_id,
-                                contract_id, provider=False):
-        """Delete the contract for an End Point Group.
-
-        Check if the EPG was a provider and attempt to grab another contract
-        consumer from the DB and set that as the new contract provider.
-        """
-        if provider:
-            self.apic.fvRsProv.delete(tenant_id, AP_NAME, epg_id, contract_id)
-            self.db.unset_provider_contract(epg_id)
-            # Pick out another EPG to set as contract provider
-            epg = self.db.get_an_epg(epg_id)
-            self.update_contract_for_epg(tenant_id, epg.epg_id,
-                                         contract_id, True)
-        else:
-            self.apic.fvRsCons.delete(tenant_id, AP_NAME, epg_id, contract_id)
-
-    def update_contract_for_epg(self, tenant_id, epg_id,
-                                contract_id, provider=False):
-        """Updates the contract for an End Point Group."""
-        self.apic.fvRsCons.delete(tenant_id, AP_NAME, epg_id, contract_id)
-        self.set_contract_for_epg(tenant_id, epg_id, contract_id, provider)
-
-    def create_tenant_contract(self, tenant_id):
-        """Creates a tenant contract.
-
-        Create a tenant contract if one doesn't exist. Also create a
-        subject, filter and entry and set the filters to allow all
-        protocol traffic on all ports
-        """
-        contract = self.db.get_contract_for_tenant(tenant_id)
-        if not contract:
-            cuuid = uuid.uuid4()
-            try:
-                # Create contract
-                self.apic.vzBrCP.create(tenant_id, cuuid, scope=SCOPE_TENANT)
-                acontract = self.apic.vzBrCP.get(tenant_id, cuuid)
-                # Create subject
-                suuid = uuid.uuid4()
-                self.apic.vzSubj.create(tenant_id, cuuid, suuid)
-                # Create filter and entry
-                tfilter = self.create_tenant_filter(tenant_id)
-                # Create interm and outterm
-                self.apic.vzInTerm.create(tenant_id, cuuid, suuid)
-                self.apic.vzRsFiltAtt__In.create(tenant_id, cuuid,
-                                                 suuid, tfilter)
-                self.apic.vzOutTerm.create(tenant_id, cuuid, suuid)
-                self.apic.vzRsFiltAtt__Out.create(tenant_id, cuuid,
-                                                  suuid, tfilter)
-                # Create contract interface
-                iuuid = uuid.uuid4()
-                self.apic.vzCPIf.create(tenant_id, iuuid)
-                self.apic.vzRsIf.create(tenant_id, iuuid,
-                                        tDn=acontract[DN_KEY])
-                # Store contract in DB
-                contract = self.db.write_contract_for_tenant(tenant_id,
-                                                             cuuid, tfilter)
-            except (cexc.ApicResponseNotOk, KeyError):
-                with excutils.save_and_reraise_exception():
-                    # Delete tenant contract
-                    self.apic.vzBrCP.delete(tenant_id, cuuid)
-
-        return contract
-
-    def make_tenant_contract_global(self, tenant_id):
-        """Mark the tenant contract's scope to global."""
-        contract = self.db.get_contract_for_tenant(tenant_id)
-        self.apic.vzBrCP.update(tenant_id, contract.contract_id,
-                                scope=SCOPE_GLOBAL)
-
-    def make_tenant_contract_local(self, tenant_id):
-        """Mark the tenant contract's scope to tenant."""
-        contract = self.db.get_contract_for_tenant(tenant_id)
-        self.apic.vzBrCP.update(tenant_id, contract.contract_id,
-                                scope=SCOPE_TENANT)
-
-    def ensure_path_created_for_port(self, tenant_id, network_id,
-                                     host_id, encap, net_name):
-        """Create path attribute for an End Point Group."""
-        encap = 'vlan-' + str(encap)
-        epg = self.ensure_epg_created_for_network(tenant_id, network_id,
-                                                  net_name)
-        eid = epg.epg_id
-
-        # Get attached switch and port for this host
-        host_config = config.get_switch_and_port_for_host(host_id)
-        if not host_config:
-            raise cexc.ApicHostNotConfigured(host=host_id)
-        switch, port = host_config
-        pdn = PORT_DN_PATH % (switch, port)
-
-        # Check if exists
-        patt = self.apic.fvRsPathAtt.get(tenant_id, AP_NAME, eid, pdn)
-        if not patt:
-            self.apic.fvRsPathAtt.create(tenant_id, AP_NAME, eid, pdn,
-                                         encap=encap, mode="regular",
-                                         instrImedcy="immediate")
index c5c43f28ff54e80ae5eeb2cea8e87b3c6d2507db..2b922c1bcacfd2e24f9ac4906ca53a67515930aa 100644 (file)
@@ -19,14 +19,16 @@ from oslo.config import cfg
 
 
 apic_opts = [
-    cfg.StrOpt('apic_host',
-               help=_("Host name or IP Address of the APIC controller")),
+    cfg.ListOpt('apic_hosts',
+                default=[],
+                help=_("An ordered list of host names or IP addresses of "
+                       "the APIC controller(s).")),
     cfg.StrOpt('apic_username',
                help=_("Username for the APIC controller")),
     cfg.StrOpt('apic_password',
                help=_("Password for the APIC controller"), secret=True),
-    cfg.StrOpt('apic_port',
-               help=_("Communication port for the APIC controller")),
+    cfg.BoolOpt('apic_use_ssl', default=True,
+                help=_("Use SSL to connect to the APIC controller")),
     cfg.StrOpt('apic_vmm_provider', default='VMware',
                help=_("Name for the VMM domain provider")),
     cfg.StrOpt('apic_vmm_domain', default='openstack',
diff --git a/neutron/plugins/ml2/drivers/cisco/apic/exceptions.py b/neutron/plugins/ml2/drivers/cisco/apic/exceptions.py
deleted file mode 100644 (file)
index b33abb1..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-# Copyright (c) 2014 Cisco Systems
-# 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.
-#
-# @author: Henry Gessau, Cisco Systems
-
-"""Exceptions used by Cisco APIC ML2 mechanism driver."""
-
-from neutron.common import exceptions
-
-
-class ApicHostNoResponse(exceptions.NotFound):
-    """No response from the APIC via the specified URL."""
-    message = _("No response from APIC at %(url)s")
-
-
-class ApicResponseNotOk(exceptions.NeutronException):
-    """A response from the APIC was not HTTP OK."""
-    message = _("APIC responded with HTTP status %(status)s: %(reason)s, "
-                "Request: '%(request)s', "
-                "APIC error code %(err_code)s: %(err_text)s")
-
-
-class ApicResponseNoCookie(exceptions.NeutronException):
-    """A response from the APIC did not contain an expected cookie."""
-    message = _("APIC failed to provide cookie for %(request)s request")
-
-
-class ApicSessionNotLoggedIn(exceptions.NotAuthorized):
-    """Attempted APIC operation while not logged in to APIC."""
-    message = _("Authorized APIC session not established")
-
-
-class ApicHostNotConfigured(exceptions.NotAuthorized):
-    """The switch and port for the specified host are not configured."""
-    message = _("The switch and port for host '%(host)s' are not configured")
-
-
-class ApicManagedObjectNotSupported(exceptions.NeutronException):
-    """Attempted to use an unsupported Managed Object."""
-    message = _("Managed Object '%(mo_class)s' is not supported")
-
-
-class ApicMultipleVlanRanges(exceptions.NeutronException):
-    """Multiple VLAN ranges specified."""
-    message = _("Multiple VLAN ranges are not supported in the APIC plugin. "
-                "Please specify a single VLAN range. "
-                "Current config: '%(vlan_ranges)s'")
index f526fd7467ecd6ace21b850c8106b2815a147ef1..58bbfb9ab08f4a72b4af81cafc4e3f072431df03 100644 (file)
@@ -15,6 +15,7 @@
 #
 # @author: Arvind Somya (asomya@cisco.com), Cisco Systems Inc.
 
+from apicapi import apic_manager
 import netaddr
 
 from oslo.config import cfg
@@ -23,8 +24,8 @@ from neutron.extensions import portbindings
 from neutron.openstack.common import log
 from neutron.plugins.common import constants
 from neutron.plugins.ml2 import driver_api as api
-from neutron.plugins.ml2.drivers.cisco.apic import apic_manager
-from neutron.plugins.ml2.drivers.cisco.apic import exceptions as apic_exc
+from neutron.plugins.ml2.drivers.cisco.apic import apic_model
+from neutron.plugins.ml2.drivers.cisco.apic import config
 
 
 LOG = log.getLogger(__name__)
@@ -32,40 +33,18 @@ LOG = log.getLogger(__name__)
 
 class APICMechanismDriver(api.MechanismDriver):
 
+    @staticmethod
+    def get_apic_manager():
+        apic_config = cfg.CONF.ml2_cisco_apic
+        network_config = {
+            'vlan_ranges': cfg.CONF.ml2_type_vlan.network_vlan_ranges,
+            'switch_dict': config.create_switch_dictionary(),
+        }
+        return apic_manager.APICManager(apic_model.ApicDbModel(), log,
+                                        network_config, apic_config)
+
     def initialize(self):
-        self.apic_manager = apic_manager.APICManager()
-
-        # Create a Phys domain and VLAN namespace
-        # Get vlan ns name
-        ns_name = cfg.CONF.ml2_cisco_apic.apic_vlan_ns_name
-
-        # Grab vlan ranges
-        if len(cfg.CONF.ml2_type_vlan.network_vlan_ranges) != 1:
-            raise apic_exc.ApicMultipleVlanRanges(
-                cfg.CONF.ml2_type_vlan.network_vlan_ranges)
-        vlan_ranges = cfg.CONF.ml2_type_vlan.network_vlan_ranges[0]
-        if ',' in vlan_ranges:
-            raise apic_exc.ApicMultipleVlanRanges(vlan_ranges)
-        (vlan_min, vlan_max) = vlan_ranges.split(':')[-2:]
-
-        # Create VLAN namespace
-        vlan_ns = self.apic_manager.ensure_vlan_ns_created_on_apic(ns_name,
-                                                                   vlan_min,
-                                                                   vlan_max)
-        phys_name = cfg.CONF.ml2_cisco_apic.apic_vmm_domain
-        # Create Physical domain
-        self.apic_manager.ensure_phys_domain_created_on_apic(phys_name,
-                                                             vlan_ns)
-
-        # Create entity profile
-        ent_name = cfg.CONF.ml2_cisco_apic.apic_entity_profile
-        self.apic_manager.ensure_entity_profile_created_on_apic(ent_name)
-
-        # Create function profile
-        func_name = cfg.CONF.ml2_cisco_apic.apic_function_profile
-        self.apic_manager.ensure_function_profile_created_on_apic(func_name)
-
-        # Create infrastructure on apic
+        self.apic_manager = APICMechanismDriver.get_apic_manager()
         self.apic_manager.ensure_infra_created_on_apic()
 
     def _perform_port_operations(self, context):
@@ -74,7 +53,6 @@ class APICMechanismDriver(api.MechanismDriver):
 
         # Get network
         network = context.network.current['id']
-        net_name = context.network.current['name']
 
         # Get port
         port = context.current
@@ -109,11 +87,10 @@ class APICMechanismDriver(api.MechanismDriver):
             for dhcp_host in dhcp_hosts:
                 self.apic_manager.ensure_path_created_for_port(tenant_id,
                                                                network,
-                                                               dhcp_host, seg,
-                                                               net_name)
+                                                               dhcp_host, seg)
         if host not in dhcp_hosts:
             self.apic_manager.ensure_path_created_for_port(tenant_id, network,
-                                                           host, seg, net_name)
+                                                           host, seg)
 
     def create_port_postcommit(self, context):
         self._perform_port_operations(context)
index 3405ad6517ee43dc962f7f58741d26f932208098..75622fbc70e6753ebebee353940fb039bcdb144e 100644 (file)
@@ -21,7 +21,7 @@ from neutron.db import l3_gwmode_db
 from neutron.openstack.common import excutils
 from neutron.openstack.common import log as logging
 from neutron.plugins.common import constants
-from neutron.plugins.ml2.drivers.cisco.apic import apic_manager
+from neutron.plugins.ml2.drivers.cisco.apic import mechanism_apic as ma
 
 LOG = logging.getLogger(__name__)
 
@@ -39,7 +39,7 @@ class ApicL3ServicePlugin(db_base_plugin_v2.NeutronDbPluginV2,
 
     def __init__(self):
         super(ApicL3ServicePlugin, self).__init__()
-        self.manager = apic_manager.APICManager()
+        self.manager = ma.APICMechanismDriver.get_apic_manager()
 
     @staticmethod
     def get_plugin_type():
@@ -100,14 +100,14 @@ class ApicL3ServicePlugin(db_base_plugin_v2.NeutronDbPluginV2,
     def remove_router_interface(self, context, router_id, interface_info):
         """Detach a subnet from a router."""
         tenant_id = context.tenant_id
-        subnet_id = interface_info['subnet_id']
-        LOG.debug("Detaching subnet %(subnet_id)s from "
-                  "router %(router_id)s" % {'subnet_id': subnet_id,
-                                            'router_id': router_id})
+        if 'subnet_id' in interface_info:
+            subnet = self.get_subnet(context, interface_info['subnet_id'])
+            network_id = subnet['network_id']
+        else:
+            port = self.get_port(context, interface_info['port_id'])
+            network_id = port['network_id']
 
         # Get network for this subnet
-        subnet = self.get_subnet(context, subnet_id)
-        network_id = subnet['network_id']
         network = self.get_network(context, network_id)
 
         contract = self.manager.create_tenant_contract(tenant_id)
@@ -124,8 +124,5 @@ class ApicL3ServicePlugin(db_base_plugin_v2.NeutronDbPluginV2,
             return super(ApicL3ServicePlugin, self).remove_router_interface(
                 context, router_id, interface_info)
         except Exception:
-            LOG.error(_("Error detaching subnet %(subnet_id)s from "
-                        "router %(router_id)s") % {'subnet_id': subnet_id,
-                                                   'router_id': router_id})
             with excutils.save_and_reraise_exception():
                 self._add_epg_to_contract(tenant_id, epg, contract)
diff --git a/neutron/tests/unit/ml2/drivers/cisco/apic/test_cisco_apic_client.py b/neutron/tests/unit/ml2/drivers/cisco/apic/test_cisco_apic_client.py
deleted file mode 100644 (file)
index 2344403..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-# Copyright (c) 2014 Cisco Systems
-# 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.
-#
-# @author: Henry Gessau, Cisco Systems
-
-import mock
-import requests
-import requests.exceptions
-
-from neutron.plugins.ml2.drivers.cisco.apic import apic_client as apic
-from neutron.plugins.ml2.drivers.cisco.apic import exceptions as cexc
-from neutron.tests import base
-from neutron.tests.unit.ml2.drivers.cisco.apic import (
-    test_cisco_apic_common as mocked)
-
-
-class TestCiscoApicClient(base.BaseTestCase, mocked.ControllerMixin):
-
-    def setUp(self):
-        super(TestCiscoApicClient, self).setUp()
-        self.set_up_mocks()
-        self.apic = apic.RestClient(mocked.APIC_HOST)
-        self.addCleanup(mock.patch.stopall)
-
-    def _mock_authenticate(self, timeout=300):
-        self.reset_reponses()
-        self.mock_apic_manager_login_responses(timeout=timeout)
-        self.apic.login(mocked.APIC_USR, mocked.APIC_PWD)
-
-    def test_login_by_instantiation(self):
-        self.reset_reponses()
-        self.mock_apic_manager_login_responses()
-        apic2 = apic.RestClient(mocked.APIC_HOST,
-                                usr=mocked.APIC_USR, pwd=mocked.APIC_PWD)
-        self.assertIsNotNone(apic2.authentication)
-        self.assertEqual(apic2.username, mocked.APIC_USR)
-
-    def test_client_session_login_ok(self):
-        self._mock_authenticate()
-        self.assertEqual(
-            self.apic.authentication['userName'], mocked.APIC_USR)
-        self.assertTrue(self.apic.api_base.startswith('http://'))
-        self.assertEqual(self.apic.username, mocked.APIC_USR)
-        self.assertIsNotNone(self.apic.authentication)
-        self.apic = apic.RestClient(mocked.APIC_HOST, mocked.APIC_PORT,
-                                    ssl=True)
-        self.assertTrue(self.apic.api_base.startswith('https://'))
-
-    def test_client_session_login_fail(self):
-        self.mock_error_post_response(requests.codes.unauthorized,
-                                      code='599',
-                                      text=u'Fake error')
-        self.assertRaises(cexc.ApicResponseNotOk, self.apic.login,
-                          mocked.APIC_USR, mocked.APIC_PWD)
-
-    def test_client_session_login_timeout(self):
-        self.response['post'].append(requests.exceptions.Timeout)
-        self.assertRaises(cexc.ApicHostNoResponse, self.apic.login,
-                          mocked.APIC_USR, mocked.APIC_PWD)
-
-    def test_client_session_logout_ok(self):
-        self.mock_response_for_post('aaaLogout')
-        self.apic.logout()
-        self.assertIsNone(self.apic.authentication)
-        # Multiple signouts should not cause an error
-        self.apic.logout()
-        self.assertIsNone(self.apic.authentication)
-
-    def test_client_session_logout_fail(self):
-        self._mock_authenticate()
-        self.mock_error_post_response(requests.codes.timeout,
-                                      code='123', text='failed')
-        self.assertRaises(cexc.ApicResponseNotOk, self.apic.logout)
-
-    def test_query_not_logged_in(self):
-        self.apic.authentication = None
-        self.assertRaises(cexc.ApicSessionNotLoggedIn,
-                          self.apic.fvTenant.get, mocked.APIC_TENANT)
-
-    def test_query_no_response(self):
-        self._mock_authenticate()
-        requests.Session.get = mock.Mock(return_value=None)
-        self.assertRaises(cexc.ApicHostNoResponse,
-                          self.apic.fvTenant.get, mocked.APIC_TENANT)
-
-    def test_query_error_response_no_data(self):
-        self._mock_authenticate()
-        self.mock_error_get_response(requests.codes.bad)  # No error attrs.
-        self.assertRaises(cexc.ApicResponseNotOk,
-                          self.apic.fvTenant.get, mocked.APIC_TENANT)
-
-    def test_generic_get_data(self):
-        self._mock_authenticate()
-        self.mock_response_for_get('topSystem', name='ifc1')
-        top_system = self.apic.get_data('class/topSystem')
-        self.assertIsNotNone(top_system)
-        name = top_system[0]['topSystem']['attributes']['name']
-        self.assertEqual(name, 'ifc1')
-
-    def test_session_timeout_refresh_ok(self):
-        self._mock_authenticate(timeout=-1)
-        # Client will do refresh before getting tenant
-        self.mock_response_for_get('aaaLogin', token='ok',
-                                   refreshTimeoutSeconds=300)
-        self.mock_response_for_get('fvTenant', name=mocked.APIC_TENANT)
-        tenant = self.apic.fvTenant.get(mocked.APIC_TENANT)
-        self.assertEqual(tenant['name'], mocked.APIC_TENANT)
-
-    def test_session_timeout_refresh_no_cookie(self):
-        self._mock_authenticate(timeout=-1)
-        # Client will do refresh before getting tenant
-        self.mock_response_for_get('aaaLogin', notoken='test')
-        self.assertRaises(cexc.ApicResponseNoCookie,
-                          self.apic.fvTenant.get, mocked.APIC_TENANT)
-
-    def test_session_timeout_refresh_error(self):
-        self._mock_authenticate(timeout=-1)
-        self.mock_error_get_response(requests.codes.timeout,
-                                     code='503', text=u'timed out')
-        self.assertRaises(cexc.ApicResponseNotOk,
-                          self.apic.fvTenant.get, mocked.APIC_TENANT)
-
-    def test_session_timeout_refresh_timeout_error(self):
-        self._mock_authenticate(timeout=-1)
-        # Client will try to get refresh, we fake a refresh error.
-        self.mock_error_get_response(requests.codes.bad_request,
-                                     code='403',
-                                     text=u'Token was invalid. Expired.')
-        # Client will then try to re-login.
-        self.mock_apic_manager_login_responses()
-        # Finally the client will try to get the tenant.
-        self.mock_response_for_get('fvTenant', name=mocked.APIC_TENANT)
-        tenant = self.apic.fvTenant.get(mocked.APIC_TENANT)
-        self.assertEqual(tenant['name'], mocked.APIC_TENANT)
-
-    def test_lookup_mo_bad_token_retry(self):
-        self._mock_authenticate()
-        # For the first get request we mock a bad token.
-        self.mock_error_get_response(requests.codes.bad_request,
-                                     code='403',
-                                     text=u'Token was invalid. Expired.')
-        # Client will then try to re-login.
-        self.mock_apic_manager_login_responses()
-        # Then the client will retry to get the tenant.
-        self.mock_response_for_get('fvTenant', name=mocked.APIC_TENANT)
-        tenant = self.apic.fvTenant.get(mocked.APIC_TENANT)
-        self.assertEqual(tenant['name'], mocked.APIC_TENANT)
-
-    def test_use_unsupported_managed_object(self):
-        self._mock_authenticate()
-        # unittest.assertRaises cannot catch exceptions raised in
-        # __getattr__, so we need to defer the evaluation using lambda.
-        self.assertRaises(cexc.ApicManagedObjectNotSupported,
-                          lambda: self.apic.nonexistentObject)
-
-    def test_lookup_nonexistant_mo(self):
-        self._mock_authenticate()
-        self.mock_response_for_get('fvTenant')
-        self.assertIsNone(self.apic.fvTenant.get(mocked.APIC_TENANT))
-
-    def test_lookup_existing_mo(self):
-        self._mock_authenticate()
-        self.mock_response_for_get('fvTenant', name='infra')
-        tenant = self.apic.fvTenant.get('infra')
-        self.assertEqual(tenant['name'], 'infra')
-
-    def test_list_mos_ok(self):
-        self._mock_authenticate()
-        self.mock_response_for_get('fvTenant', name='t1')
-        self.mock_append_to_response('fvTenant', name='t2')
-        tlist = self.apic.fvTenant.list_all()
-        self.assertIsNotNone(tlist)
-        self.assertEqual(len(tlist), 2)
-        self.assertIn({'name': 't1'}, tlist)
-        self.assertIn({'name': 't2'}, tlist)
-
-    def test_list_mo_names_ok(self):
-        self._mock_authenticate()
-        self.mock_response_for_get('fvTenant', name='t1')
-        self.mock_append_to_response('fvTenant', name='t2')
-        tnlist = self.apic.fvTenant.list_names()
-        self.assertIsNotNone(tnlist)
-        self.assertEqual(len(tnlist), 2)
-        self.assertIn('t1', tnlist)
-        self.assertIn('t2', tnlist)
-
-    def test_list_mos_split_class_fail(self):
-        self._mock_authenticate()
-        self.mock_response_for_get('fvnsEncapBlk', name='Blk1')
-        encap_blks = self.apic.fvnsEncapBlk__vlan.list_all()
-        self.assertEqual(len(encap_blks), 1)
-
-    def test_delete_mo_ok(self):
-        self._mock_authenticate()
-        self.mock_response_for_post('fvTenant')
-        self.assertTrue(self.apic.fvTenant.delete(mocked.APIC_TENANT))
-
-    def test_create_mo_ok(self):
-        self._mock_authenticate()
-        self.mock_response_for_post('fvTenant', name=mocked.APIC_TENANT)
-        self.mock_response_for_get('fvTenant', name=mocked.APIC_TENANT)
-        self.apic.fvTenant.create(mocked.APIC_TENANT)
-        tenant = self.apic.fvTenant.get(mocked.APIC_TENANT)
-        self.assertEqual(tenant['name'], mocked.APIC_TENANT)
-
-    def test_create_mo_already_exists(self):
-        self._mock_authenticate()
-        self.mock_error_post_response(requests.codes.bad_request,
-                                      code='103',
-                                      text=u'Fake 103 error')
-        self.assertRaises(cexc.ApicResponseNotOk,
-                          self.apic.vmmProvP.create, mocked.APIC_VMMP)
-
-    def test_create_mo_with_prereq(self):
-        self._mock_authenticate()
-        self.mock_response_for_post('fvTenant', name=mocked.APIC_TENANT)
-        self.mock_response_for_post('fvBD', name=mocked.APIC_NETWORK)
-        self.mock_response_for_get('fvBD', name=mocked.APIC_NETWORK)
-        bd_args = mocked.APIC_TENANT, mocked.APIC_NETWORK
-        self.apic.fvBD.create(*bd_args)
-        network = self.apic.fvBD.get(*bd_args)
-        self.assertEqual(network['name'], mocked.APIC_NETWORK)
-
-    def test_create_mo_prereq_exists(self):
-        self._mock_authenticate()
-        self.mock_response_for_post('vmmDomP', name=mocked.APIC_DOMAIN)
-        self.mock_response_for_get('vmmDomP', name=mocked.APIC_DOMAIN)
-        self.apic.vmmDomP.create(mocked.APIC_VMMP, mocked.APIC_DOMAIN)
-        dom = self.apic.vmmDomP.get(mocked.APIC_VMMP, mocked.APIC_DOMAIN)
-        self.assertEqual(dom['name'], mocked.APIC_DOMAIN)
-
-    def test_create_mo_fails(self):
-        self._mock_authenticate()
-        self.mock_response_for_post('fvTenant', name=mocked.APIC_TENANT)
-        self.mock_error_post_response(requests.codes.bad_request,
-                                      code='not103',
-                                      text=u'Fake not103 error')
-        bd_args = mocked.APIC_TENANT, mocked.APIC_NETWORK
-        self.assertRaises(cexc.ApicResponseNotOk,
-                          self.apic.fvBD.create, *bd_args)
-
-    def test_update_mo(self):
-        self._mock_authenticate()
-        self.mock_response_for_post('fvTenant', name=mocked.APIC_TENANT)
-        self.mock_response_for_get('fvTenant', name=mocked.APIC_TENANT,
-                                   more='extra')
-        self.apic.fvTenant.update(mocked.APIC_TENANT, more='extra')
-        tenant = self.apic.fvTenant.get(mocked.APIC_TENANT)
-        self.assertEqual(tenant['name'], mocked.APIC_TENANT)
-        self.assertEqual(tenant['more'], 'extra')
-
-    def test_attr_fail_empty_list(self):
-        self._mock_authenticate()
-        self.mock_response_for_get('fvTenant')  # No attrs for tenant.
-        self.assertIsNone(self.apic.fvTenant.get(mocked.APIC_TENANT))
-
-    def test_attr_fail_other_obj(self):
-        self._mock_authenticate()
-        self.mock_response_for_get('other', name=mocked.APIC_TENANT)
-        self.assertIsNone(self.apic.fvTenant.get(mocked.APIC_TENANT))
index e150c1f093010c8350fdb7e1fa5e1d225a223c80..12318a2d7597921dec126bc8a4b76aa14e5ce0b1 100644 (file)
@@ -22,13 +22,12 @@ from oslo.config import cfg
 
 from neutron.common import config as neutron_config
 from neutron.plugins.ml2 import config as ml2_config
-from neutron.plugins.ml2.drivers.cisco.apic import apic_client as apic
 from neutron.tests import base
 
 
 OK = requests.codes.ok
 
-APIC_HOST = 'fake.controller.local'
+APIC_HOSTS = ['fake.controller.local']
 APIC_PORT = 7580
 APIC_USR = 'notadmin'
 APIC_PWD = 'topsecret'
@@ -103,20 +102,6 @@ class ControllerMixin(object):
         attrs['debug_mo'] = mo  # useful for debugging
         self._stage_mocked_response('post', OK, mo, **attrs)
 
-    def mock_response_for_get(self, mo, **attrs):
-        self._stage_mocked_response('get', OK, mo, **attrs)
-
-    def mock_append_to_response(self, mo, **attrs):
-        # Append a MO to the last get response.
-        mo_attrs = attrs and {mo: {'attributes': attrs}} or {}
-        self.response['get'][-1].json.return_value['imdata'].append(mo_attrs)
-
-    def mock_error_post_response(self, status, **attrs):
-        self._stage_mocked_response('post', status, 'error', **attrs)
-
-    def mock_error_get_response(self, status, **attrs):
-        self._stage_mocked_response('get', status, 'error', **attrs)
-
     def _stage_mocked_response(self, req, mock_status, mo, **attrs):
         response = mock.MagicMock()
         response.status_code = mock_status
@@ -124,41 +109,11 @@ class ControllerMixin(object):
         response.json.return_value = {'imdata': mo_attrs}
         self.response[req].append(response)
 
-    def mock_responses_for_create(self, obj):
-        self._mock_container_responses_for_create(
-            apic.ManagedObjectClass(obj).container)
-        name = '-'.join([obj, 'name'])  # useful for debugging
-        self._stage_mocked_response('post', OK, obj, name=name)
-
-    def _mock_container_responses_for_create(self, obj):
-        # Recursively generate responses for creating obj's containers.
-        if obj:
-            mo = apic.ManagedObjectClass(obj)
-            if mo.can_create:
-                if mo.container:
-                    self._mock_container_responses_for_create(mo.container)
-                name = '-'.join([obj, 'name'])  # useful for debugging
-                self._stage_mocked_response('post', OK, obj, debug_name=name)
-
     def mock_apic_manager_login_responses(self, timeout=300):
         # APIC Manager tests are based on authenticated session
         self.mock_response_for_post('aaaLogin', userName=APIC_USR,
                                     token='ok', refreshTimeoutSeconds=timeout)
 
-    def assert_responses_drained(self, req=None):
-        """Fail if all the expected responses have not been consumed."""
-        request = {'post': self.session.post, 'get': self.session.get}
-        reqs = req and [req] or ['post', 'get']  # Both if none specified.
-        for req in reqs:
-            try:
-                request[req]('some url')
-            except StopIteration:
-                pass
-            else:
-                # User-friendly error message
-                msg = req + ' response queue not drained'
-                self.fail(msg=msg)
-
 
 class ConfigMixin(object):
 
@@ -182,10 +137,9 @@ class ConfigMixin(object):
 
         # Configure the Cisco APIC mechanism driver
         apic_test_config = {
-            'apic_host': APIC_HOST,
+            'apic_hosts': APIC_HOSTS,
             'apic_username': APIC_USR,
             'apic_password': APIC_PWD,
-            'apic_port': APIC_PORT,
             'apic_vmm_domain': APIC_DOMAIN,
             'apic_vlan_ns_name': APIC_VLAN_NAME,
             'apic_vlan_range': '%d:%d' % (APIC_VLANID_FROM, APIC_VLANID_TO),
@@ -205,21 +159,3 @@ class ConfigMixin(object):
                                                'MultiConfigParser').start()
         self.mocked_parser.return_value.read.return_value = [apic_switch_cfg]
         self.mocked_parser.return_value.parsed = [apic_switch_cfg]
-
-
-class DbModelMixin(object):
-
-    """Mock the DB models for the APIC driver and service unit tests."""
-
-    def __init__(self):
-        self.mocked_session = None
-
-    def set_up_mocks(self):
-        self.mocked_session = mock.Mock()
-        get_session = mock.patch('neutron.db.api.get_session').start()
-        get_session.return_value = self.mocked_session
-
-    def mock_db_query_filterby_first_return(self, value):
-        """Mock db.session.query().filterby().first() to return value."""
-        query = self.mocked_session.query.return_value
-        query.filter_by.return_value.first.return_value = value
diff --git a/neutron/tests/unit/ml2/drivers/cisco/apic/test_cisco_apic_manager.py b/neutron/tests/unit/ml2/drivers/cisco/apic/test_cisco_apic_manager.py
deleted file mode 100644 (file)
index 24a2c21..0000000
+++ /dev/null
@@ -1,698 +0,0 @@
-# Copyright (c) 2014 Cisco Systems
-# 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.
-#
-# @author: Henry Gessau, Cisco Systems
-
-import mock
-from webob import exc as wexc
-
-from neutron.openstack.common import uuidutils
-
-from neutron.plugins.ml2.drivers.cisco.apic import apic_manager
-from neutron.plugins.ml2.drivers.cisco.apic import exceptions as cexc
-from neutron.tests import base
-from neutron.tests.unit.ml2.drivers.cisco.apic import (
-    test_cisco_apic_common as mocked)
-
-
-class TestCiscoApicManager(base.BaseTestCase,
-                           mocked.ControllerMixin,
-                           mocked.ConfigMixin,
-                           mocked.DbModelMixin):
-
-    def setUp(self):
-        super(TestCiscoApicManager, self).setUp()
-        mocked.ControllerMixin.set_up_mocks(self)
-        mocked.ConfigMixin.set_up_mocks(self)
-        mocked.DbModelMixin.set_up_mocks(self)
-
-        self.mock_apic_manager_login_responses()
-        self.mgr = apic_manager.APICManager()
-        self.session = self.mgr.apic.session
-        self.assert_responses_drained()
-        self.reset_reponses()
-
-    def test_mgr_session_login(self):
-        login = self.mgr.apic.authentication
-        self.assertEqual(login['userName'], mocked.APIC_USR)
-
-    def test_mgr_session_logout(self):
-        self.mock_response_for_post('aaaLogout')
-        self.mgr.apic.logout()
-        self.assert_responses_drained()
-        self.assertIsNone(self.mgr.apic.authentication)
-
-    def test_to_range(self):
-        port_list = [4, 2, 3, 1, 7, 8, 10, 20, 6, 22, 21]
-        expected_ranges = [(1, 4), (6, 8), (10, 10), (20, 22)]
-        port_ranges = [r for r in apic_manager.group_by_ranges(port_list)]
-        self.assertEqual(port_ranges, expected_ranges)
-
-    def test_get_profiles(self):
-        self.mock_db_query_filterby_first_return('faked')
-        self.assertEqual(
-            self.mgr.db.get_port_profile_for_node('node'),
-            'faked'
-        )
-        self.assertEqual(
-            self.mgr.db.get_profile_for_module('node', 'prof', 'module'),
-            'faked'
-        )
-        self.assertEqual(
-            self.mgr.db.get_profile_for_module_and_ports(
-                'node', 'prof', 'module', 'from', 'to'
-            ),
-            'faked'
-        )
-
-    def test_add_profile(self):
-        self.mgr.db.add_profile_for_module_and_ports(
-            'node', 'prof', 'hpselc', 'module', 'from', 'to')
-        self.assertTrue(self.mocked_session.add.called)
-        self.assertTrue(self.mocked_session.flush.called)
-
-    def test_ensure_port_profile_created(self):
-        port_name = mocked.APIC_PORT
-        self.mock_responses_for_create('infraAccPortP')
-        self.mock_response_for_get('infraAccPortP', name=port_name)
-        port = self.mgr.ensure_port_profile_created_on_apic(port_name)
-        self.assert_responses_drained()
-        self.assertEqual(port['name'], port_name)
-
-    def test_ensure_port_profile_created_exc(self):
-        port_name = mocked.APIC_PORT
-        self.mock_error_post_response(wexc.HTTPBadRequest)
-        self.mock_response_for_post('infraAccPortP')
-        self.assertRaises(cexc.ApicResponseNotOk,
-                          self.mgr.ensure_port_profile_created_on_apic,
-                          port_name)
-        self.assert_responses_drained()
-
-    def test_ensure_node_profile_created_for_switch_old(self):
-        old_switch = mocked.APIC_NODE_PROF
-        self.mock_response_for_get('infraNodeP', name=old_switch)
-        self.mgr.ensure_node_profile_created_for_switch(old_switch)
-        self.assert_responses_drained()
-        old_name = self.mgr.node_profiles[old_switch]['object']['name']
-        self.assertEqual(old_name, old_switch)
-
-    def test_ensure_node_profile_created_for_switch_new(self):
-        new_switch = mocked.APIC_NODE_PROF
-        self.mock_response_for_get('infraNodeP')
-        self.mock_responses_for_create('infraNodeP')
-        self.mock_responses_for_create('infraLeafS')
-        self.mock_responses_for_create('infraNodeBlk')
-        self.mock_response_for_get('infraNodeP', name=new_switch)
-        self.mgr.ensure_node_profile_created_for_switch(new_switch)
-        self.assert_responses_drained()
-        new_name = self.mgr.node_profiles[new_switch]['object']['name']
-        self.assertEqual(new_name, new_switch)
-
-    def test_ensure_node_profile_created_for_switch_new_exc(self):
-        new_switch = mocked.APIC_NODE_PROF
-        self.mock_response_for_get('infraNodeP')
-        self.mock_error_post_response(wexc.HTTPBadRequest)
-        self.mock_response_for_post('infraNodeP')
-        self.assertRaises(cexc.ApicResponseNotOk,
-                          self.mgr.ensure_node_profile_created_for_switch,
-                          new_switch)
-        self.assert_responses_drained()
-
-    def test_ensure_vmm_domain_created_old(self):
-        dom = mocked.APIC_DOMAIN
-        self.mock_response_for_get('vmmDomP', name=dom)
-        self.mgr.ensure_vmm_domain_created_on_apic(dom)
-        self.assert_responses_drained()
-        old_dom = self.mgr.vmm_domain['name']
-        self.assertEqual(old_dom, dom)
-
-    def _mock_new_vmm_dom_responses(self, dom, seg_type=None):
-        vmm = mocked.APIC_VMMP
-        dn = self.mgr.apic.vmmDomP.mo.dn(vmm, dom)
-        self.mock_response_for_get('vmmDomP')
-        self.mock_responses_for_create('vmmDomP')
-        if seg_type:
-            self.mock_responses_for_create(seg_type)
-        self.mock_response_for_get('vmmDomP', name=dom, dn=dn)
-
-    def test_ensure_vmm_domain_created_new_no_vlan_ns(self):
-        dom = mocked.APIC_DOMAIN
-        self._mock_new_vmm_dom_responses(dom)
-        self.mgr.ensure_vmm_domain_created_on_apic(dom)
-        self.assert_responses_drained()
-        new_dom = self.mgr.vmm_domain['name']
-        self.assertEqual(new_dom, dom)
-
-    def test_ensure_vmm_domain_created_new_no_vlan_ns_exc(self):
-        dom = mocked.APIC_DOMAIN
-        self.mock_response_for_get('vmmDomP')
-        self.mock_error_post_response(wexc.HTTPBadRequest)
-        self.mock_response_for_post('vmmDomP')
-        self.assertRaises(cexc.ApicResponseNotOk,
-                          self.mgr.ensure_vmm_domain_created_on_apic, dom)
-        self.assert_responses_drained()
-
-    def test_ensure_vmm_domain_created_new_with_vlan_ns(self):
-        dom = mocked.APIC_DOMAIN
-        self._mock_new_vmm_dom_responses(dom, seg_type='infraRsVlanNs__vmm')
-        ns = {'dn': 'test_vlan_ns'}
-        self.mgr.ensure_vmm_domain_created_on_apic(dom, vlan_ns=ns)
-        self.assert_responses_drained()
-        new_dom = self.mgr.vmm_domain['name']
-        self.assertEqual(new_dom, dom)
-
-    def test_ensure_vmm_domain_created_new_with_vxlan_ns(self):
-        dom = mocked.APIC_DOMAIN
-        # TODO(Henry): mock seg_type vxlan when vxlan is ready
-        self._mock_new_vmm_dom_responses(dom, seg_type=None)
-        ns = {'dn': 'test_vxlan_ns'}
-        self.mgr.ensure_vmm_domain_created_on_apic(dom, vxlan_ns=ns)
-        self.assert_responses_drained()
-        new_dom = self.mgr.vmm_domain['name']
-        self.assertEqual(new_dom, dom)
-
-    def test_ensure_infra_created_no_infra(self):
-        self.mgr.switch_dict = {}
-        self.mgr.ensure_infra_created_on_apic()
-
-    def _ensure_infra_created_seq1_setup(self):
-        am = 'neutron.plugins.ml2.drivers.cisco.apic.apic_manager.APICManager'
-        np_create_for_switch = mock.patch(
-            am + '.ensure_node_profile_created_for_switch').start()
-        self.mock_db_query_filterby_first_return(None)
-        pp_create_for_switch = mock.patch(
-            am + '.ensure_port_profile_created_on_apic').start()
-        pp_create_for_switch.return_value = {'dn': 'port_profile_dn'}
-        return np_create_for_switch, pp_create_for_switch
-
-    def test_ensure_infra_created_seq1(self):
-        np_create_for_switch, pp_create_for_switch = (
-            self._ensure_infra_created_seq1_setup())
-
-        def _profile_for_module(aswitch, ppn, module):
-            profile = mock.Mock()
-            profile.ppn = ppn
-            profile.hpselc_id = '-'.join([aswitch, module, 'hpselc_id'])
-            return profile
-
-        self.mgr.db.get_profile_for_module = mock.Mock(
-            side_effect=_profile_for_module)
-        self.mgr.db.get_profile_for_module_and_ports = mock.Mock(
-            return_value=None)
-        self.mgr.db.add_profile_for_module_and_ports = mock.Mock()
-
-        num_switches = len(self.mgr.switch_dict)
-        for loop in range(num_switches):
-            self.mock_responses_for_create('infraRsAccPortP')
-            self.mock_responses_for_create('infraPortBlk')
-
-        self.mgr.ensure_infra_created_on_apic()
-        self.assert_responses_drained()
-        self.assertEqual(np_create_for_switch.call_count, num_switches)
-        self.assertEqual(pp_create_for_switch.call_count, num_switches)
-        for switch in self.mgr.switch_dict:
-            np_create_for_switch.assert_any_call(switch)
-
-    def test_ensure_infra_created_seq1_exc(self):
-        np_create_for_switch, __ = self._ensure_infra_created_seq1_setup()
-        self.mock_error_post_response(wexc.HTTPBadRequest)
-        self.mock_response_for_post('infraAccPortP')
-
-        self.assertRaises(cexc.ApicResponseNotOk,
-                          self.mgr.ensure_infra_created_on_apic)
-        self.assert_responses_drained()
-        self.assertTrue(np_create_for_switch.called)
-        self.assertEqual(np_create_for_switch.call_count, 1)
-
-    def _ensure_infra_created_seq2_setup(self):
-        am = 'neutron.plugins.ml2.drivers.cisco.apic.apic_manager.APICManager'
-        np_create_for_switch = mock.patch(
-            am + '.ensure_node_profile_created_for_switch').start()
-
-        def _profile_for_node(aswitch):
-            profile = mock.Mock()
-            profile.profile_id = '-'.join([aswitch, 'profile_id'])
-            return profile
-
-        self.mgr.db.get_port_profile_for_node = mock.Mock(
-            side_effect=_profile_for_node)
-        self.mgr.db.get_profile_for_module = mock.Mock(
-            return_value=None)
-        self.mgr.function_profile = {'dn': 'dn'}
-        self.mgr.db.get_profile_for_module_and_ports = mock.Mock(
-            return_value=True)
-
-        return np_create_for_switch
-
-    def test_ensure_infra_created_seq2(self):
-        np_create_for_switch = self._ensure_infra_created_seq2_setup()
-
-        num_switches = len(self.mgr.switch_dict)
-        for loop in range(num_switches):
-            self.mock_responses_for_create('infraHPortS')
-            self.mock_responses_for_create('infraRsAccBaseGrp')
-
-        self.mgr.ensure_infra_created_on_apic()
-        self.assert_responses_drained()
-        self.assertEqual(np_create_for_switch.call_count, num_switches)
-        for switch in self.mgr.switch_dict:
-            np_create_for_switch.assert_any_call(switch)
-
-    def test_ensure_infra_created_seq2_exc(self):
-        np_create_for_switch = self._ensure_infra_created_seq2_setup()
-
-        self.mock_error_post_response(wexc.HTTPBadRequest)
-        self.mock_response_for_post('infraHPortS')
-
-        self.assertRaises(cexc.ApicResponseNotOk,
-                          self.mgr.ensure_infra_created_on_apic)
-        self.assert_responses_drained()
-        self.assertTrue(np_create_for_switch.called)
-        self.assertEqual(np_create_for_switch.call_count, 1)
-
-    def test_ensure_context_unenforced_new_ctx(self):
-        self.mock_response_for_get('fvCtx')
-        self.mock_responses_for_create('fvCtx')
-        self.mgr.ensure_context_unenforced()
-        self.assert_responses_drained()
-
-    def test_ensure_context_unenforced_pref1(self):
-        self.mock_response_for_get('fvCtx', pcEnfPref='1')
-        self.mock_response_for_post('fvCtx')
-        self.mgr.ensure_context_unenforced()
-        self.assert_responses_drained()
-
-    def test_ensure_context_unenforced_pref2(self):
-        self.mock_response_for_get('fvCtx', pcEnfPref='2')
-        self.mgr.ensure_context_unenforced()
-        self.assert_responses_drained()
-
-    def _mock_vmm_dom_prereq(self, dom):
-        self._mock_new_vmm_dom_responses(dom)
-        self.mgr.ensure_vmm_domain_created_on_apic(dom)
-
-    def _mock_new_phys_dom_responses(self, dom, seg_type=None):
-        dn = self.mgr.apic.physDomP.mo.dn(dom)
-        self.mock_response_for_get('physDomP')
-        self.mock_responses_for_create('physDomP')
-        if seg_type:
-            self.mock_responses_for_create(seg_type)
-        self.mock_response_for_get('physDomP', name=dom, dn=dn)
-
-    def _mock_phys_dom_prereq(self, dom):
-        self._mock_new_phys_dom_responses(dom)
-        self.mgr.ensure_phys_domain_created_on_apic(dom)
-
-    def test_ensure_entity_profile_created_old(self):
-        ep = mocked.APIC_ATT_ENT_PROF
-        self.mock_response_for_get('infraAttEntityP', name=ep)
-        self.mgr.ensure_entity_profile_created_on_apic(ep)
-        self.assert_responses_drained()
-
-    def _mock_new_entity_profile(self, exc=None):
-        self.mock_response_for_get('infraAttEntityP')
-        self.mock_responses_for_create('infraAttEntityP')
-        self.mock_responses_for_create('infraRsDomP')
-        if exc:
-            self.mock_error_get_response(exc, code='103', text=u'Fail')
-        else:
-            self.mock_response_for_get('infraAttEntityP')
-
-    def test_ensure_entity_profile_created_new(self):
-        self._mock_phys_dom_prereq(mocked.APIC_PDOM)
-        ep = mocked.APIC_ATT_ENT_PROF
-        self._mock_new_entity_profile()
-        self.mgr.ensure_entity_profile_created_on_apic(ep)
-        self.assert_responses_drained()
-
-    def test_ensure_entity_profile_created_new_exc(self):
-        self._mock_phys_dom_prereq(mocked.APIC_PDOM)
-        ep = mocked.APIC_ATT_ENT_PROF
-        self._mock_new_entity_profile(exc=wexc.HTTPBadRequest)
-        self.mock_response_for_post('infraAttEntityP')
-        self.assertRaises(cexc.ApicResponseNotOk,
-                          self.mgr.ensure_entity_profile_created_on_apic, ep)
-        self.assert_responses_drained()
-
-    def _mock_entity_profile_preqreq(self):
-        self._mock_phys_dom_prereq(mocked.APIC_PDOM)
-        ep = mocked.APIC_ATT_ENT_PROF
-        self._mock_new_entity_profile()
-        self.mgr.ensure_entity_profile_created_on_apic(ep)
-
-    def test_ensure_function_profile_created_old(self):
-        self._mock_entity_profile_preqreq()
-        fp = mocked.APIC_FUNC_PROF
-        self.mock_response_for_get('infraAccPortGrp', name=fp)
-        self.mgr.ensure_function_profile_created_on_apic(fp)
-        self.assert_responses_drained()
-        old_fp = self.mgr.function_profile['name']
-        self.assertEqual(old_fp, fp)
-
-    def _mock_new_function_profile(self, fp):
-        dn = self.mgr.apic.infraAttEntityP.mo.dn(fp)
-        self.mock_responses_for_create('infraAccPortGrp')
-        self.mock_responses_for_create('infraRsAttEntP')
-        self.mock_response_for_get('infraAccPortGrp', name=fp, dn=dn)
-
-    def test_ensure_function_profile_created_new(self):
-        fp = mocked.APIC_FUNC_PROF
-        dn = self.mgr.apic.infraAttEntityP.mo.dn(fp)
-        self.mgr.entity_profile = {'dn': dn}
-        self.mock_response_for_get('infraAccPortGrp')
-        self.mock_responses_for_create('infraAccPortGrp')
-        self.mock_responses_for_create('infraRsAttEntP')
-        self.mock_response_for_get('infraAccPortGrp', name=fp, dn=dn)
-        self.mgr.ensure_function_profile_created_on_apic(fp)
-        self.assert_responses_drained()
-        new_fp = self.mgr.function_profile['name']
-        self.assertEqual(new_fp, fp)
-
-    def test_ensure_function_profile_created_new_exc(self):
-        fp = mocked.APIC_FUNC_PROF
-        dn = self.mgr.apic.infraAttEntityP.mo.dn(fp)
-        self.mgr.entity_profile = {'dn': dn}
-        self.mock_response_for_get('infraAccPortGrp')
-        self.mock_error_post_response(wexc.HTTPBadRequest)
-        self.mock_response_for_post('infraAccPortGrp')
-        self.assertRaises(cexc.ApicResponseNotOk,
-                          self.mgr.ensure_function_profile_created_on_apic, fp)
-        self.assert_responses_drained()
-
-    def test_ensure_vlan_ns_created_old(self):
-        ns = mocked.APIC_VLAN_NAME
-        mode = mocked.APIC_VLAN_MODE
-        self.mock_response_for_get('fvnsVlanInstP', name=ns, mode=mode)
-        new_ns = self.mgr.ensure_vlan_ns_created_on_apic(ns, '100', '199')
-        self.assert_responses_drained()
-        self.assertIsNone(new_ns)
-
-    def _mock_new_vlan_instance(self, ns, vlan_encap=None):
-        self.mock_responses_for_create('fvnsVlanInstP')
-        if vlan_encap:
-            self.mock_response_for_get('fvnsEncapBlk', **vlan_encap)
-        else:
-            self.mock_response_for_get('fvnsEncapBlk')
-            self.mock_responses_for_create('fvnsEncapBlk__vlan')
-        self.mock_response_for_get('fvnsVlanInstP', name=ns)
-
-    def test_ensure_vlan_ns_created_new_no_encap(self):
-        ns = mocked.APIC_VLAN_NAME
-        self.mock_response_for_get('fvnsVlanInstP')
-        self._mock_new_vlan_instance(ns)
-        new_ns = self.mgr.ensure_vlan_ns_created_on_apic(ns, '200', '299')
-        self.assert_responses_drained()
-        self.assertEqual(new_ns['name'], ns)
-
-    def test_ensure_vlan_ns_created_new_exc(self):
-        ns = mocked.APIC_VLAN_NAME
-        self.mock_response_for_get('fvnsVlanInstP')
-        self.mock_error_post_response(wexc.HTTPBadRequest)
-        self.mock_response_for_post('fvnsVlanInstP')
-        self.assertRaises(cexc.ApicResponseNotOk,
-                          self.mgr.ensure_vlan_ns_created_on_apic,
-                          ns, '200', '299')
-        self.assert_responses_drained()
-
-    def test_ensure_vlan_ns_created_new_with_encap(self):
-        ns = mocked.APIC_VLAN_NAME
-        self.mock_response_for_get('fvnsVlanInstP')
-        ns_args = {'name': 'encap', 'from': '300', 'to': '399'}
-        self._mock_new_vlan_instance(ns, vlan_encap=ns_args)
-        new_ns = self.mgr.ensure_vlan_ns_created_on_apic(ns, '300', '399')
-        self.assert_responses_drained()
-        self.assertEqual(new_ns['name'], ns)
-
-    def test_ensure_tenant_created_on_apic(self):
-        self.mock_response_for_get('fvTenant', name='any')
-        self.mgr.ensure_tenant_created_on_apic('two')
-        self.mock_response_for_get('fvTenant')
-        self.mock_responses_for_create('fvTenant')
-        self.mgr.ensure_tenant_created_on_apic('four')
-        self.assert_responses_drained()
-
-    def test_ensure_bd_created_existing_bd(self):
-        self.mock_response_for_get('fvBD', name='BD')
-        self.mgr.ensure_bd_created_on_apic('t1', 'two')
-        self.assert_responses_drained()
-
-    def test_ensure_bd_created_not_ctx(self):
-        self.mock_response_for_get('fvBD')
-        self.mock_responses_for_create('fvBD')
-        self.mock_response_for_get('fvCtx')
-        self.mock_responses_for_create('fvCtx')
-        self.mock_responses_for_create('fvRsCtx')
-        self.mgr.ensure_bd_created_on_apic('t2', 'three')
-        self.assert_responses_drained()
-
-    def test_ensure_bd_created_exc(self):
-        self.mock_response_for_get('fvBD')
-        self.mock_error_post_response(wexc.HTTPBadRequest)
-        self.mock_response_for_post('fvBD')
-        self.assertRaises(cexc.ApicResponseNotOk,
-                          self.mgr.ensure_bd_created_on_apic, 't2', 'three')
-        self.assert_responses_drained()
-
-    def test_ensure_bd_created_ctx_pref1(self):
-        self.mock_response_for_get('fvBD')
-        self.mock_responses_for_create('fvBD')
-        self.mock_response_for_get('fvCtx', pcEnfPref='1')
-        self.mock_responses_for_create('fvRsCtx')
-        self.mgr.ensure_bd_created_on_apic('t3', 'four')
-        self.assert_responses_drained()
-
-    def test_ensure_bd_created_ctx_pref2(self):
-        self.mock_response_for_get('fvBD')
-        self.mock_responses_for_create('fvBD')
-        self.mock_response_for_get('fvCtx', pcEnfPref='2')
-        self.mock_response_for_post('fvCtx')
-        self.mock_responses_for_create('fvRsCtx')
-        self.mgr.ensure_bd_created_on_apic('t3', 'four')
-        self.assert_responses_drained()
-
-    def test_delete_bd(self):
-        self.mock_response_for_post('fvBD')
-        self.mgr.delete_bd_on_apic('t1', 'bd')
-        self.assert_responses_drained()
-
-    def test_ensure_subnet_created(self):
-        self.mock_response_for_get('fvSubnet', name='sn1')
-        self.mgr.ensure_subnet_created_on_apic('t0', 'bd1', '2.2.2.2/8')
-        self.mock_response_for_get('fvSubnet')
-        self.mock_responses_for_create('fvSubnet')
-        self.mgr.ensure_subnet_created_on_apic('t2', 'bd3', '4.4.4.4/16')
-        self.assert_responses_drained()
-
-    def test_ensure_filter_created(self):
-        self.mock_response_for_get('vzFilter', name='f1')
-        self.mgr.ensure_filter_created_on_apic('t1', 'two')
-        self.mock_response_for_get('vzFilter')
-        self.mock_responses_for_create('vzFilter')
-        self.mgr.ensure_filter_created_on_apic('t2', 'four')
-        self.assert_responses_drained()
-
-    def test_ensure_epg_created_for_network_old(self):
-        self.mock_db_query_filterby_first_return('faked')
-        epg = self.mgr.ensure_epg_created_for_network('X', 'Y', 'Z')
-        self.assertEqual(epg, 'faked')
-
-    def test_ensure_epg_created_for_network_new(self):
-        tenant = mocked.APIC_TENANT
-        network = mocked.APIC_NETWORK
-        netname = mocked.APIC_NETNAME
-        self._mock_phys_dom_prereq(mocked.APIC_PDOM)
-        self.mock_db_query_filterby_first_return(None)
-        self.mock_responses_for_create('fvAEPg')
-        self.mock_response_for_get('fvBD', name=network)
-        self.mock_responses_for_create('fvRsBd')
-        self.mock_responses_for_create('fvRsDomAtt')
-        new_epg = self.mgr.ensure_epg_created_for_network(tenant,
-                                                          network, netname)
-        self.assert_responses_drained()
-        self.assertEqual(new_epg.network_id, network)
-        self.assertTrue(self.mocked_session.add.called)
-        self.assertTrue(self.mocked_session.flush.called)
-
-    def test_ensure_epg_created_for_network_exc(self):
-        tenant = mocked.APIC_TENANT
-        network = mocked.APIC_NETWORK
-        netname = mocked.APIC_NETNAME
-        self.mock_db_query_filterby_first_return(None)
-        self.mock_error_post_response(wexc.HTTPBadRequest)
-        self.mock_response_for_post('fvAEPg')
-        self.assertRaises(cexc.ApicResponseNotOk,
-                          self.mgr.ensure_epg_created_for_network,
-                          tenant, network, netname)
-        self.assert_responses_drained()
-
-    def test_delete_epg_for_network_no_epg(self):
-        self.mock_db_query_filterby_first_return(None)
-        self.mgr.delete_epg_for_network('tenant', 'network')
-
-    def test_delete_epg_for_network(self):
-        epg = mock.Mock()
-        epg.epg_id = mocked.APIC_EPG
-        self.mock_db_query_filterby_first_return(epg)
-        self.mock_response_for_post('fvAEPg')
-        self.mgr.delete_epg_for_network('tenant', 'network')
-        self.assertTrue(self.mocked_session.delete.called)
-        self.assertTrue(self.mocked_session.flush.called)
-
-    def test_ensure_path_created_for_port(self):
-        epg = mock.Mock()
-        epg.epg_id = 'epg01'
-        eepg = mock.Mock(return_value=epg)
-        apic_manager.APICManager.ensure_epg_created_for_network = eepg
-        self.mock_response_for_get('fvRsPathAtt', tDn='foo')
-        self.mgr.ensure_path_created_for_port('tenant', 'network', 'rhel01',
-                                              'static', 'netname')
-        self.assert_responses_drained()
-
-    def test_ensure_path_created_for_port_no_path_att(self):
-        epg = mock.Mock()
-        epg.epg_id = 'epg2'
-        eepg = mock.Mock(return_value=epg)
-        self.mgr.ensure_epg_created_for_network = eepg
-        self.mock_response_for_get('fvRsPathAtt')
-        self.mock_responses_for_create('fvRsPathAtt')
-        self.mgr.ensure_path_created_for_port('tenant', 'network', 'ubuntu2',
-                                              'static', 'netname')
-        self.assert_responses_drained()
-
-    def test_ensure_path_created_for_port_unknown_host(self):
-        epg = mock.Mock()
-        epg.epg_id = 'epg3'
-        eepg = mock.Mock(return_value=epg)
-        apic_manager.APICManager.ensure_epg_created_for_network = eepg
-        self.mock_response_for_get('fvRsPathAtt', tDn='foo')
-        self.assertRaises(cexc.ApicHostNotConfigured,
-                          self.mgr.ensure_path_created_for_port,
-                          'tenant', 'network', 'cirros3', 'static', 'netname')
-
-    def test_create_tenant_filter(self):
-        tenant = mocked.APIC_TENANT
-        self.mock_responses_for_create('vzFilter')
-        self.mock_responses_for_create('vzEntry')
-        filter_id = self.mgr.create_tenant_filter(tenant)
-        self.assert_responses_drained()
-        self.assertTrue(uuidutils.is_uuid_like(str(filter_id)))
-
-    def test_create_tenant_filter_exc(self):
-        tenant = mocked.APIC_TENANT
-        self.mock_error_post_response(wexc.HTTPBadRequest)
-        self.mock_response_for_post('vzFilter')
-        self.assertRaises(cexc.ApicResponseNotOk,
-                          self.mgr.create_tenant_filter, tenant)
-        self.assert_responses_drained()
-
-    def test_set_contract_for_epg_consumer(self):
-        tenant = mocked.APIC_TENANT
-        epg = mocked.APIC_EPG
-        contract = mocked.APIC_CONTRACT
-        self.mock_responses_for_create('fvRsCons')
-        self.mgr.set_contract_for_epg(tenant, epg, contract)
-        self.assert_responses_drained()
-
-    def test_set_contract_for_epg_provider(self):
-        tenant = mocked.APIC_TENANT
-        epg = mocked.APIC_EPG
-        contract = mocked.APIC_CONTRACT
-        epg_obj = mock.Mock()
-        epg_obj.epg_id = epg
-        epg_obj.provider = False
-        self.mock_db_query_filterby_first_return(epg_obj)
-        self.mock_responses_for_create('fvRsProv')
-        self.mock_response_for_post('vzBrCP')
-        self.mgr.set_contract_for_epg(tenant, epg, contract, provider=True)
-        self.assert_responses_drained()
-        self.assertTrue(self.mocked_session.merge.called)
-        self.assertTrue(self.mocked_session.flush.called)
-        self.assertTrue(epg_obj.provider)
-
-    def test_set_contract_for_epg_provider_exc(self):
-        tenant = mocked.APIC_TENANT
-        epg = mocked.APIC_EPG
-        contract = mocked.APIC_CONTRACT
-        self.mock_error_post_response(wexc.HTTPBadRequest)
-        self.mock_response_for_post('vzBrCP')
-        self.mock_response_for_post('fvRsProv')
-        self.assertRaises(cexc.ApicResponseNotOk,
-                          self.mgr.set_contract_for_epg,
-                          tenant, epg, contract, provider=True)
-        self.assert_responses_drained()
-
-    def test_delete_contract_for_epg_consumer(self):
-        tenant = mocked.APIC_TENANT
-        epg = mocked.APIC_EPG
-        contract = mocked.APIC_CONTRACT
-        self.mock_response_for_post('fvRsCons')
-        self.mgr.delete_contract_for_epg(tenant, epg, contract)
-        self.assert_responses_drained()
-
-    def test_delete_contract_for_epg_provider(self):
-        tenant = mocked.APIC_TENANT
-        epg = mocked.APIC_EPG
-        contract = mocked.APIC_CONTRACT
-        epg_obj = mock.Mock()
-        epg_obj.epg_id = epg + '-other'
-        epg_obj.provider = False
-        self.mock_db_query_filterby_first_return(epg_obj)
-        self.mock_response_for_post('fvRsProv')
-        self.mock_response_for_post('fvRsCons')
-        self.mock_responses_for_create('fvRsProv')
-        self.mock_response_for_post('vzBrCP')
-        self.mgr.delete_contract_for_epg(tenant, epg, contract, provider=True)
-        self.assert_responses_drained()
-        self.assertTrue(self.mocked_session.merge.called)
-        self.assertTrue(self.mocked_session.flush.called)
-        self.assertTrue(epg_obj.provider)
-
-    def test_create_tenant_contract_existing(self):
-        tenant = mocked.APIC_TENANT
-        contract = mocked.APIC_CONTRACT
-        self.mock_db_query_filterby_first_return(contract)
-        new_contract = self.mgr.create_tenant_contract(tenant)
-        self.assertEqual(new_contract, contract)
-
-    def test_create_tenant_contract_new(self):
-        tenant = mocked.APIC_TENANT
-        contract = mocked.APIC_CONTRACT
-        dn = self.mgr.apic.vzBrCP.mo.dn(tenant, contract)
-        self.mock_db_query_filterby_first_return(None)
-        self.mock_responses_for_create('vzBrCP')
-        self.mock_response_for_get('vzBrCP', dn=dn)
-        self.mock_responses_for_create('vzSubj')
-        self.mock_responses_for_create('vzFilter')
-        self.mock_responses_for_create('vzEntry')
-        self.mock_responses_for_create('vzInTerm')
-        self.mock_responses_for_create('vzRsFiltAtt__In')
-        self.mock_responses_for_create('vzOutTerm')
-        self.mock_responses_for_create('vzRsFiltAtt__Out')
-        self.mock_responses_for_create('vzCPIf')
-        self.mock_responses_for_create('vzRsIf')
-        new_contract = self.mgr.create_tenant_contract(tenant)
-        self.assert_responses_drained()
-        self.assertTrue(self.mocked_session.add.called)
-        self.assertTrue(self.mocked_session.flush.called)
-        self.assertEqual(new_contract['tenant_id'], tenant)
-
-    def test_create_tenant_contract_exc(self):
-        tenant = mocked.APIC_TENANT
-        self.mock_db_query_filterby_first_return(None)
-        self.mock_error_post_response(wexc.HTTPBadRequest)
-        self.mock_response_for_post('vzBrCP')
-        self.assertRaises(cexc.ApicResponseNotOk,
-                          self.mgr.create_tenant_contract, tenant)
-        self.assert_responses_drained()
index fbd30e67d17a95f1b669b36377e57a67165c864f..8526132e0525f0996fae3f55f543d6c20ea2b45e 100644 (file)
 # @author: Henry Gessau, Cisco Systems
 
 import mock
+import sys
 
-from oslo.config import cfg
+sys.modules["apicapi"] = mock.Mock()
 
 from neutron.extensions import portbindings
 from neutron.plugins.ml2.drivers.cisco.apic import mechanism_apic as md
-from neutron.plugins.ml2.drivers import type_vlan  # noqa
 from neutron.tests import base
 from neutron.tests.unit.ml2.drivers.cisco.apic import (
     test_cisco_apic_common as mocked)
@@ -41,14 +41,12 @@ TEST_SEGMENT2 = 'test-segment2'
 
 class TestCiscoApicMechDriver(base.BaseTestCase,
                               mocked.ControllerMixin,
-                              mocked.ConfigMixin,
-                              mocked.DbModelMixin):
+                              mocked.ConfigMixin):
 
     def setUp(self):
         super(TestCiscoApicMechDriver, self).setUp()
         mocked.ControllerMixin.set_up_mocks(self)
         mocked.ConfigMixin.set_up_mocks(self)
-        mocked.DbModelMixin.set_up_mocks(self)
 
         self.mock_apic_manager_login_responses()
         self.driver = md.APICMechanismDriver()
@@ -56,21 +54,9 @@ class TestCiscoApicMechDriver(base.BaseTestCase,
         self.driver.cap_port_filter = 'test-cap_port_filter'
 
     def test_initialize(self):
-        cfg.CONF.set_override('network_vlan_ranges', ['physnet1:100:199'],
-                              'ml2_type_vlan')
-        ns = mocked.APIC_VLAN_NAME
-        mode = mocked.APIC_VLAN_MODE
-        self.mock_response_for_get('fvnsVlanInstP', name=ns, mode=mode)
-        self.mock_response_for_get('physDomP', name=mocked.APIC_DOMAIN)
-        self.mock_response_for_get('infraAttEntityP',
-                                   name=mocked.APIC_ATT_ENT_PROF)
-        self.mock_response_for_get('infraAccPortGrp',
-                                   name=mocked.APIC_ACC_PORT_GRP)
-        mock.patch('neutron.plugins.ml2.drivers.cisco.apic.apic_manager.'
-                   'APICManager.ensure_infra_created_on_apic').start()
+        mgr = self.driver.apic_manager = mock.Mock()
         self.driver.initialize()
-        self.session = self.driver.apic_manager.apic.session
-        self.assert_responses_drained()
+        mgr.ensure_infra_created_on_apic.assert_called_once()
 
     def test_update_port_postcommit(self):
         net_ctx = self._get_network_context(mocked.APIC_TENANT,
@@ -85,7 +71,7 @@ class TestCiscoApicMechDriver(base.BaseTestCase,
             mocked.APIC_TENANT)
         mgr.ensure_path_created_for_port.assert_called_once_with(
             mocked.APIC_TENANT, mocked.APIC_NETWORK, HOST_ID1,
-            ENCAP, mocked.APIC_NETWORK + '-name')
+            ENCAP)
 
     def test_create_network_postcommit(self):
         ctx = self._get_network_context(mocked.APIC_TENANT,
index 55b168e88775abc45810985e7d8f2535bdc169bd..f05b7cdacc48bea3d20496e94e226d5105a42533 100644 (file)
@@ -16,6 +16,9 @@
 # @author: Arvind Somya (asomya@cisco.com), Cisco Systems
 
 import mock
+import sys
+
+sys.modules["apicapi"] = mock.Mock()
 
 from neutron.services.l3_router import l3_apic
 from neutron.tests.unit import testlib_api
@@ -59,8 +62,6 @@ class TestCiscoApicL3Plugin(testlib_api.SqlTestCase):
 
     def setUp(self):
         super(TestCiscoApicL3Plugin, self).setUp()
-        mock.patch('neutron.plugins.ml2.drivers.cisco.apic.apic_manager.'
-                   'APICManager').start()
         self.plugin = l3_apic.ApicL3ServicePlugin()
         self.context = FakeContext()
         self.context.tenant_id = TENANT