¡@

Home 

OpenStack Study: mech_cisco_nexus.py

OpenStack Index

**** CubicPower OpenStack Study ****

# Copyright 2013 OpenStack Foundation

# 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.

"""

ML2 Mechanism Driver for Cisco Nexus platforms.

"""

from oslo.config import cfg

from neutron.common import constants as n_const

from neutron.extensions import portbindings

from neutron.openstack.common import log as logging

from neutron.plugins.common import constants as p_const

from neutron.plugins.ml2 import driver_api as api

from neutron.plugins.ml2.drivers.cisco.nexus import config as conf

from neutron.plugins.ml2.drivers.cisco.nexus import credentials_v2 as cred

from neutron.plugins.ml2.drivers.cisco.nexus import exceptions as excep

from neutron.plugins.ml2.drivers.cisco.nexus import nexus_db_v2 as nxos_db

from neutron.plugins.ml2.drivers.cisco.nexus import nexus_network_driver

LOG = logging.getLogger(__name__)

**** CubicPower OpenStack Study ****

class CiscoNexusMechanismDriver(api.MechanismDriver):

"""Cisco Nexus ML2 Mechanism Driver."""

**** CubicPower OpenStack Study ****

    def initialize(self):

        # Create ML2 device dictionary from ml2_conf.ini entries.

        conf.ML2MechCiscoConfig()

        # Extract configuration parameters from the configuration file.

        self._nexus_switches = conf.ML2MechCiscoConfig.nexus_dict

        LOG.debug(_("nexus_switches found = %s"), self._nexus_switches)

        self.credentials = {}

        self.driver = nexus_network_driver.CiscoNexusDriver()

        # Initialize credential store after database initialization.

        cred.Store.initialize()

**** CubicPower OpenStack Study ****

    def _valid_network_segment(self, segment):

        return (cfg.CONF.ml2_cisco.managed_physical_network is None or

                cfg.CONF.ml2_cisco.managed_physical_network ==

                segment[api.PHYSICAL_NETWORK])

**** CubicPower OpenStack Study ****

    def _get_vlanid(self, segment):

        if (segment and segment[api.NETWORK_TYPE] == p_const.TYPE_VLAN and

            self._valid_network_segment(segment)):

            return segment.get(api.SEGMENTATION_ID)

**** CubicPower OpenStack Study ****

    def _is_deviceowner_compute(self, port):

        return port['device_owner'].startswith('compute')

**** CubicPower OpenStack Study ****

    def _is_status_active(self, port):

        return port['status'] == n_const.PORT_STATUS_ACTIVE

**** CubicPower OpenStack Study ****

    def _get_switch_info(self, host_id):

        for switch_ip, attr in self._nexus_switches:

            if str(attr) == str(host_id):

                port_id = self._nexus_switches[switch_ip, attr]

                return port_id, switch_ip

        else:

            raise excep.NexusComputeHostNotConfigured(host=host_id)

**** CubicPower OpenStack Study ****

    def _configure_nxos_db(self, vlan_id, device_id, host_id):

        """Create the nexus database entry.

        Called during update precommit port event.

        """

        port_id, switch_ip = self._get_switch_info(host_id)

        nxos_db.add_nexusport_binding(port_id, str(vlan_id), switch_ip,

                                      device_id)

**** CubicPower OpenStack Study ****

    def _configure_switch_entry(self, vlan_id, device_id, host_id):

        """Create a nexus switch entry.

        if needed, create a VLAN in the appropriate switch/port and

        configure the appropriate interfaces for this VLAN.

        Called during update postcommit port event.

        """

        port_id, switch_ip = self._get_switch_info(host_id)

        vlan_name = cfg.CONF.ml2_cisco.vlan_name_prefix + str(vlan_id)

        # Check to see if this is the first binding to use this vlan on the

        # switch/port. Configure switch accordingly.

        bindings = nxos_db.get_nexusvlan_binding(vlan_id, switch_ip)

        if len(bindings) == 1:

            LOG.debug(_("Nexus: create & trunk vlan %s"), vlan_name)

            self.driver.create_and_trunk_vlan(switch_ip, vlan_id, vlan_name,

                                              port_id)

        else:

            LOG.debug(_("Nexus: trunk vlan %s"), vlan_name)

            self.driver.enable_vlan_on_trunk_int(switch_ip, vlan_id, port_id)

**** CubicPower OpenStack Study ****

    def _delete_nxos_db(self, vlan_id, device_id, host_id):

        """Delete the nexus database entry.

        Called during delete precommit port event.

        """

        try:

            row = nxos_db.get_nexusvm_binding(vlan_id, device_id)

            nxos_db.remove_nexusport_binding(row.port_id, row.vlan_id,

                                             row.switch_ip, row.instance_id)

        except excep.NexusPortBindingNotFound:

            return

**** CubicPower OpenStack Study ****

    def _delete_switch_entry(self, vlan_id, device_id, host_id):

        """Delete the nexus switch entry.

        By accessing the current db entries determine if switch

        configuration can be removed.

        Called during update postcommit port event.

        """

        port_id, switch_ip = self._get_switch_info(host_id)

        # if there are no remaining db entries using this vlan on this nexus

        # switch port then remove vlan from the switchport trunk.

        try:

            nxos_db.get_port_vlan_switch_binding(port_id, vlan_id, switch_ip)

        except excep.NexusPortBindingNotFound:

            self.driver.disable_vlan_on_trunk_int(switch_ip, vlan_id, port_id)

            # if there are no remaining db entries using this vlan on this

            # nexus switch then remove the vlan.

            try:

                nxos_db.get_nexusvlan_binding(vlan_id, switch_ip)

            except excep.NexusPortBindingNotFound:

                self.driver.delete_vlan(switch_ip, vlan_id)

**** CubicPower OpenStack Study ****

    def _is_vm_migration(self, context):

        if not context.bound_segment and context.original_bound_segment:

            return (context.current.get(portbindings.HOST_ID) !=

                    context.original.get(portbindings.HOST_ID))

**** CubicPower OpenStack Study ****

    def _port_action(self, port, segment, func):

        """Verify configuration and then process event."""

        device_id = port.get('device_id')

        host_id = port.get(portbindings.HOST_ID)

        vlan_id = self._get_vlanid(segment)

        if vlan_id and device_id and host_id:

            func(vlan_id, device_id, host_id)

        else:

            fields = "vlan_id " if not vlan_id else ""

            fields += "device_id " if not device_id else ""

            fields += "host_id" if not host_id else ""

            raise excep.NexusMissingRequiredFields(fields=fields)

**** CubicPower OpenStack Study ****

    def update_port_precommit(self, context):

        """Update port pre-database transaction commit event."""

        # if VM migration is occurring then remove previous database entry

        # else process update event.

        if self._is_vm_migration(context):

            self._port_action(context.original,

                              context.original_bound_segment,

                              self._delete_nxos_db)

        else:

            if (self._is_deviceowner_compute(context.current) and

                self._is_status_active(context.current)):

                self._port_action(context.current,

                                  context.bound_segment,

                                  self._configure_nxos_db)

**** CubicPower OpenStack Study ****

    def update_port_postcommit(self, context):

        """Update port non-database commit event."""

        # if VM migration is occurring then remove previous nexus switch entry

        # else process update event.

        if self._is_vm_migration(context):

            self._port_action(context.original,

                              context.original_bound_segment,

                              self._delete_switch_entry)

        else:

            if (self._is_deviceowner_compute(context.current) and

                self._is_status_active(context.current)):

                self._port_action(context.current,

                                  context.bound_segment,

                                  self._configure_switch_entry)

**** CubicPower OpenStack Study ****

    def delete_port_precommit(self, context):

        """Delete port pre-database commit event."""

        if self._is_deviceowner_compute(context.current):

            self._port_action(context.current,

                              context.bound_segment,

                              self._delete_nxos_db)

**** CubicPower OpenStack Study ****

    def delete_port_postcommit(self, context):

        """Delete port non-database commit event."""

        if self._is_deviceowner_compute(context.current):

            self._port_action(context.current,

                              context.bound_segment,

                              self._delete_switch_entry)