diff --git a/etc/neutron/plugins/ml2/ml2_conf_cisco.ini b/etc/neutron/plugins/ml2/ml2_conf_cisco.ini index 1b69100e775..e7a09af1083 100644 --- a/etc/neutron/plugins/ml2/ml2_conf_cisco.ini +++ b/etc/neutron/plugins/ml2/ml2_conf_cisco.ini @@ -3,6 +3,8 @@ # (StrOpt) A short prefix to prepend to the VLAN number when creating a # VLAN interface. For example, if an interface is being created for # VLAN 2001 it will be named 'q-2001' using the default prefix. +# The total length allowed for the prefix name and VLAN is 32 characters, +# the prefix will be truncated if the total length is greater than 32. # # vlan_name_prefix = q- # Example: vlan_name_prefix = vnet- @@ -27,6 +29,8 @@ # ssh_port= (2) # username= (3) # password= (4) +# nve_src_intf= (5) +# physnet= (6) # # (1) For each host connected to a port on the switch, specify the hostname # and the Nexus physical port (interface) it is connected to. @@ -37,6 +41,21 @@ # port number 22 unless the switch has been configured otherwise. # (3) The username for logging into the switch to manage it. # (4) The password for logging into the switch to manage it. +# (5) Only valid if VXLAN overlay is configured and vxlan_global_config is +# set to True. +# The NVE source interface is a loopback interface that is configured on +# the switch with valid /32 IP address. This /32 IP address must be known +# by the transient devices in the transport network and the remote VTEPs. +# This is accomplished by advertising it through a dynamic routing protocol +# in the transport network. (NB: If no nve_src_intf is defined then a +# default setting of 0 (creates "loopback0") will be used.) +# (6) Only valid if VXLAN overlay is configured. +# The physical network name defined in the network_vlan_ranges variable +# (defined under the ml2_type_vlan section) that this switch is controlling. +# The configured 'physnet' is the physical network domain that is connected +# to this switch. The vlan ranges defined in network_vlan_ranges for a +# a physical network are allocated dynamically and are unique per physical +# network. These dynamic vlans may be reused across physical networks. # # Example: # [ml2_mech_cisco_nexus:1.1.1.1] @@ -46,6 +65,77 @@ # ssh_port=22 # username=admin # password=mySecretPassword +# nve_src_intf=1 +# physnet=physnet1 + +# (StrOpt) A short prefix to prepend to the VLAN number when creating a +# provider VLAN interface. For example, if an interface is being created +# for provider VLAN 3003 it will be named 'p-3003' using the default prefix. +# The total length allowed for the prefix name and VLAN is 32 characters, +# the prefix will be truncated if the total length is greater than 32. +# +# provider_vlan_name_prefix = p- +# Example: provider_vlan_name_prefix = PV- + +# (BoolOpt) A flag indicating whether OpenStack networking should manage the +# creation and removal of VLANs for provider networks on the Nexus +# switches. If the flag is set to False then OpenStack will not create or +# remove VLANs for provider networks, and the administrator needs to +# manage these interfaces manually or by external orchestration. +# +# provider_vlan_auto_create = True + +# (BoolOpt) A flag indicating whether OpenStack networking should manage +# the adding and removing of provider VLANs from trunk ports on the Nexus +# switches. If the flag is set to False then OpenStack will not add or +# remove provider VLANs from trunk ports, and the administrator needs to +# manage these operations manually or by external orchestration. +# +# provider_vlan_auto_trunk = True + +# (BoolOpt) A flag indicating whether OpenStack networking should manage the +# creating and removing of the Nexus switch VXLAN global settings of 'feature +# nv overlay', 'feature vn-segment-vlan-based', 'interface nve 1' and the NVE +# subcommand 'source-interface loopback #'. If the flag is set to False +# (default) then OpenStack will not add or remove these VXLAN settings, and +# the administrator needs to manage these operations manually or by external +# orchestration. +# +# vxlan_global_config = True + +# (BoolOpt) To make Nexus device persistent by running the Nexus +# CLI 'copy run start' after applying successful configurations. +# (default) This flag defaults to False keep consistent with +# existing functionality. +# +# persistent_switch_config = False + +# (IntOpt) Time interval to check the state of the Nexus device. +# (default) This value defaults to 0 seconds which disables this +# functionality. When enabled, 30 seconds is suggested. +# +# switch_heartbeat_time = 0 + +# (IntOpt) Number of times to attempt config replay with switch. +# This variable depends on switch_heartbeat_time being enabled. +# (default) This value defaults to 3 +# +# switch_replay_count = 3 + +[ml2_type_nexus_vxlan] +# (ListOpt) Comma-separated list of : tuples enumerating +# ranges of VXLAN Network IDs that are available for tenant network allocation. +# +# vni_ranges = +# Example: 100:1000,2000:6000 +# +# (ListOpt) Multicast groups for the VXLAN interface. When configured, will +# enable sending all broadcast traffic to this multicast group. Comma separated +# list of min:max ranges of multicast IP's. +# NOTE: must be a valid multicast IP, invalid IP's will be discarded +# +# mcast_ranges = +# Example: mcast_ranges = 224.0.0.1:224.0.0.3,224.0.1.1:224.0.1. [ml2_cisco_apic] @@ -86,7 +176,7 @@ # , = # # You can have multiple sections, one for each switch in your fabric that is -# participating in Openstack. e.g. +# participating in OpenStack. e.g. # # [apic_switch:17] # ubuntu,ubuntu1 = 1/10 @@ -116,3 +206,18 @@ # encap=vlan-100 # cidr_exposed=10.10.40.2/16 # gateway_ip=10.10.40.1 + +[ml2_cisco_ucsm] + +# Cisco UCS Manager IP address +# ucsm_ip=1.1.1.1 + +# Username to connect to UCS Manager +# ucsm_username=user + +# Password to connect to UCS Manager +# ucsm_password=password + +# SR-IOV and VM-FEX vendors supported by this plugin +# xxxx:yyyy represents vendor_id:product_id +# supported_pci_devs = ['2222:3333', '4444:5555'] diff --git a/neutron/db/migration/alembic_migrations/versions/341ee8a4ccb5_sync_with_cisco_repo.py b/neutron/db/migration/alembic_migrations/versions/341ee8a4ccb5_sync_with_cisco_repo.py new file mode 100644 index 00000000000..4b254ef2faf --- /dev/null +++ b/neutron/db/migration/alembic_migrations/versions/341ee8a4ccb5_sync_with_cisco_repo.py @@ -0,0 +1,76 @@ +# Copyright 2015 OpenStack Foundation +# +# 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. +# + +"""sync with cisco repo + +Revision ID: 341ee8a4ccb5 +Revises: f15b1fb526dd +Create Date: 2015-03-10 17:19:57.047080 + +""" + +# revision identifiers, used by Alembic. +revision = '341ee8a4ccb5' +down_revision = 'f15b1fb526dd' + +from alembic import op +import sqlalchemy as sa + + +def upgrade(): + op.create_table( + 'ml2_nexus_vxlan_allocations', + sa.Column('vxlan_vni', sa.Integer(), nullable=False, + autoincrement=False), + sa.Column('allocated', sa.Boolean(), nullable=False, + server_default=sa.sql.false()), + sa.PrimaryKeyConstraint('vxlan_vni') + ) + + op.create_table( + 'ml2_nexus_vxlan_mcast_groups', + sa.Column('id', sa.String(length=36), nullable=False), + sa.Column('mcast_group', sa.String(length=64), nullable=False), + sa.Column('associated_vni', sa.Integer(), nullable=False), + sa.PrimaryKeyConstraint('id'), + sa.ForeignKeyConstraint(['associated_vni'], + ['ml2_nexus_vxlan_allocations.vxlan_vni'], + ondelete='CASCADE') + ) + + op.create_table( + 'cisco_ml2_nexus_nve', + sa.Column('vni', sa.Integer(), nullable=False), + sa.Column('switch_ip', sa.String(length=255), nullable=True), + sa.Column('device_id', sa.String(length=255), nullable=True), + sa.Column('mcast_group', sa.String(length=255), nullable=True), + sa.PrimaryKeyConstraint('vni', 'switch_ip', 'device_id')) + + op.add_column( + 'cisco_ml2_nexusport_bindings', + sa.Column('vni', sa.Integer(), nullable=True)) + + op.add_column('cisco_ml2_nexusport_bindings', sa.Column( + 'is_provider_vlan', sa.Boolean(), nullable=False, + server_default=sa.sql.false())) + + +def downgrade(): + op.drop_table('ml2_nexus_vxlan_mcast_groups') + op.drop_table('ml2_nexus_vxlan_allocations') + op.drop_table('cisco_ml2_nexus_nve') + + op.drop_column('cisco_ml2_nexusport_bindings', 'vni') + op.drop_column('cisco_ml2_nexusport_bindings', 'is_provider_vlan') diff --git a/neutron/db/migration/alembic_migrations/versions/HEAD b/neutron/db/migration/alembic_migrations/versions/HEAD index b553d525922..1f9bcd91d65 100644 --- a/neutron/db/migration/alembic_migrations/versions/HEAD +++ b/neutron/db/migration/alembic_migrations/versions/HEAD @@ -1 +1 @@ -f15b1fb526dd +341ee8a4ccb5 diff --git a/neutron/plugins/ml2/drivers/cisco/nexus/nexus_models_v2.py b/neutron/plugins/ml2/drivers/cisco/nexus/nexus_models_v2.py index ce7c4166321..045499ce326 100644 --- a/neutron/plugins/ml2/drivers/cisco/nexus/nexus_models_v2.py +++ b/neutron/plugins/ml2/drivers/cisco/nexus/nexus_models_v2.py @@ -17,6 +17,7 @@ import sqlalchemy as sa from neutron.db import model_base +from neutron.db import models_v2 class NexusPortBinding(model_base.BASEV2): @@ -27,19 +28,63 @@ class NexusPortBinding(model_base.BASEV2): binding_id = sa.Column(sa.Integer, primary_key=True, autoincrement=True) port_id = sa.Column(sa.String(255)) vlan_id = sa.Column(sa.Integer, nullable=False) + vni = sa.Column(sa.Integer) switch_ip = sa.Column(sa.String(255)) instance_id = sa.Column(sa.String(255)) + is_provider_vlan = sa.Column(sa.Boolean(), nullable=False, default=False, + server_default=sa.sql.false()) def __repr__(self): """Just the binding, without the id key.""" - return ("" % - (self.port_id, self.vlan_id, self.switch_ip, self.instance_id)) + return ("" % + (self.port_id, self.vlan_id, self.vni, self.switch_ip, + self.instance_id, + 'True' if self.is_provider_vlan else 'False')) def __eq__(self, other): """Compare only the binding, without the id key.""" return ( self.port_id == other.port_id and self.vlan_id == other.vlan_id and + self.vni == other.vni and self.switch_ip == other.switch_ip and - self.instance_id == other.instance_id + self.instance_id == other.instance_id and + self.is_provider_vlan == other.is_provider_vlan ) + + +class NexusNVEBinding(model_base.BASEV2): + """Represents Network Virtualization Endpoint configuration.""" + + __tablename__ = "cisco_ml2_nexus_nve" + + vni = sa.Column(sa.Integer, primary_key=True, nullable=False) + device_id = sa.Column(sa.String(255), primary_key=True) + switch_ip = sa.Column(sa.String(255), primary_key=True) + mcast_group = sa.Column(sa.String(255)) + + def __repr__(self): + return ("" % + (self.vni, self.switch_ip, self.device_id, self.mcast_group)) + + +class NexusVxlanAllocation(model_base.BASEV2): + + __tablename__ = 'ml2_nexus_vxlan_allocations' + + vxlan_vni = sa.Column(sa.Integer, nullable=False, primary_key=True, + autoincrement=False) + allocated = sa.Column(sa.Boolean, nullable=False, default=False, + server_default=sa.sql.false()) + + +class NexusMcastGroup(model_base.BASEV2, models_v2.HasId): + + __tablename__ = 'ml2_nexus_vxlan_mcast_groups' + + mcast_group = sa.Column(sa.String(64), nullable=False) + associated_vni = sa.Column(sa.Integer, + sa.ForeignKey( + 'ml2_nexus_vxlan_allocations.vxlan_vni', + ondelete="CASCADE"), + nullable=False) diff --git a/neutron/plugins/ml2/drivers/cisco/nexus/type_nexus_vxlan.py b/neutron/plugins/ml2/drivers/cisco/nexus/type_nexus_vxlan.py new file mode 100644 index 00000000000..933b1e31798 --- /dev/null +++ b/neutron/plugins/ml2/drivers/cisco/nexus/type_nexus_vxlan.py @@ -0,0 +1,21 @@ +# Copyright (c) 2015 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. +# + +from networking_cisco.plugins.ml2.drivers.cisco.nexus import type_nexus_vxlan + + +class NexusVxlanTypeDriver(type_nexus_vxlan.NexusVxlanTypeDriver): + pass diff --git a/setup.cfg b/setup.cfg index 44d7b4c1797..cfc16d91517 100644 --- a/setup.cfg +++ b/setup.cfg @@ -156,6 +156,7 @@ neutron.ml2.type_drivers = vlan = neutron.plugins.ml2.drivers.type_vlan:VlanTypeDriver gre = neutron.plugins.ml2.drivers.type_gre:GreTypeDriver vxlan = neutron.plugins.ml2.drivers.type_vxlan:VxlanTypeDriver + nexus_vxlan = neutron.plugins.ml2.drivers.cisco.nexus.type_nexus_vxlan:NexusVxlanTypeDriver neutron.ml2.mechanism_drivers = opendaylight = neutron.plugins.ml2.drivers.opendaylight.driver:OpenDaylightMechanismDriver logger = neutron.tests.unit.ml2.drivers.mechanism_logger:LoggerMechanismDriver