1. 程式人生 > >如何實現OpenStack STT隧道(by quqi99)

如何實現OpenStack STT隧道(by quqi99)

diff --git a/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD b/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD
index cf26eb1..6a75db4 100644
--- a/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD
+++ b/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD
@@ -1 +1 @@
-30107ab6a3ee
+3abed5b82c57
diff --git a/neutron/db/migration/alembic_migrations/versions/newton/contract/3abed5b82c57_add_stt_type_driver.py b/neutron/db/migration/alembic_migrations/versions/newton/contract/3abed5b82c57_add_stt_type_driver.py
new file mode 100644
index 0000000..c305f6c
--- /dev/null
+++ b/neutron/db/migration/alembic_migrations/versions/newton/contract/3abed5b82c57_add_stt_type_driver.py
@@ -0,0 +1,49 @@
+# 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.
+#
+
+"""add_stt_type_driver
+
+Revision ID: 3abed5b82c57
+Revises: 30107ab6a3ee
+Create Date: 2016-05-19 12:52:40.546353
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '3abed5b82c57'
+down_revision = '30107ab6a3ee'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+    op.create_table(
+        'ml2_stt_allocations',
+        sa.Column('stt_context_id', sa.Integer(),
+                  autoincrement=False, nullable=False),
+        sa.Column('allocated', sa.Boolean(),
+                  server_default=sa.sql.false(), nullable=False),
+        sa.PrimaryKeyConstraint('stt_context_id'),
+    )
+    op.create_index(op.f('ix_ml2_stt_allocations_allocated'),
+                    'ml2_stt_allocations', ['allocated'], unique=False)
+    op.create_table(
+        'ml2_stt_endpoints',
+        sa.Column('ip_address', sa.String(length=64), nullable=False),
+        sa.Column('host', sa.String(length=255), nullable=True),
+        sa.PrimaryKeyConstraint('ip_address'),
+        sa.UniqueConstraint('host', name='unique_ml2_stt_endpoints0host'),
+    )
diff --git a/neutron/db/migration/models/head.py b/neutron/db/migration/models/head.py
index 6112dbf..2b336ac 100644
--- a/neutron/db/migration/models/head.py
+++ b/neutron/db/migration/models/head.py
@@ -54,6 +54,7 @@ from neutron.ipam.drivers.neutrondb_ipam import db_models  # noqa
 from neutron.plugins.ml2.drivers import type_flat  # noqa
 from neutron.plugins.ml2.drivers import type_geneve  # noqa
 from neutron.plugins.ml2.drivers import type_gre  # noqa
+from neutron.plugins.ml2.drivers import type_stt  # noqa
 from neutron.plugins.ml2.drivers import type_vlan  # noqa
 from neutron.plugins.ml2.drivers import type_vxlan  # noqa
 from neutron.plugins.ml2 import models  # noqa
diff --git a/neutron/plugins/common/constants.py b/neutron/plugins/common/constants.py
index 4b38514..2a6ced1 100644
--- a/neutron/plugins/common/constants.py
+++ b/neutron/plugins/common/constants.py
@@ -69,6 +69,7 @@ TYPE_GENEVE = 'geneve'
 TYPE_GRE = 'gre'
 TYPE_LOCAL = 'local'
 TYPE_VXLAN = 'vxlan'
+TYPE_STT = 'stt'
 TYPE_VLAN = 'vlan'
 TYPE_NONE = 'none'
 
@@ -86,6 +87,10 @@ MAX_GENEVE_VNI = 2 ** 24 - 1
 MIN_GRE_ID = 1
 MAX_GRE_ID = 2 ** 32 - 1
 
+# For STT Tunnel
+MIN_STT_CONTEXT_ID = 1
+MAX_STT_CONTEXT_ID = 2 ** 64 - 1
+
 # For VXLAN Tunnel
 MIN_VXLAN_VNI = 1
 MAX_VXLAN_VNI = 2 ** 24 - 1
@@ -95,3 +100,6 @@ VXLAN_UDP_PORT = 4789
 GENEVE_ENCAP_MIN_OVERHEAD = 50
 GRE_ENCAP_OVERHEAD = 42
 VXLAN_ENCAP_OVERHEAD = 50
+# NOTE(arosen): STT does not need an ENCAP_OVERHEAD as it's TCP based
+# thus L2 fragmentation will not come into play. The packets will be
+# sized to the systems configured MTU.
diff --git a/neutron/plugins/ml2/config.py b/neutron/plugins/ml2/config.py
index 4e2e43d..f85a9f5 100644
--- a/neutron/plugins/ml2/config.py
+++ b/neutron/plugins/ml2/config.py
@@ -19,7 +19,8 @@ from neutron._i18n import _
 
 ml2_opts = [
     cfg.ListOpt('type_drivers',
-                default=['local', 'flat', 'vlan', 'gre', 'vxlan', 'geneve'],
+                default=['local', 'flat', 'vlan', 'gre', 'vxlan', 'stt',
+                         'geneve'],
                 help=_("List of network type driver entrypoints to be loaded "
                        "from the neutron.ml2.type_drivers namespace.")),
     cfg.ListOpt('tenant_network_types',
diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/common/constants.py b/neutron/plugins/ml2/drivers/openvswitch/agent/common/constants.py
index 96903d3..b996f39 100644
--- a/neutron/plugins/ml2/drivers/openvswitch/agent/common/constants.py
+++ b/neutron/plugins/ml2/drivers/openvswitch/agent/common/constants.py
@@ -33,7 +33,7 @@ NONEXISTENT_PEER = 'nonexistent-peer'
 
 # The different types of tunnels
 TUNNEL_NETWORK_TYPES = [p_const.TYPE_GRE, p_const.TYPE_VXLAN,
-                        p_const.TYPE_GENEVE]
+                        p_const.TYPE_GENEVE, p_const.TYPE_STT]
 
 ### OpenFlow table IDs
 
@@ -75,6 +75,7 @@ DVR_PROCESS = 1
 PATCH_LV_TO_TUN = 2
 GRE_TUN_TO_LV = 3
 VXLAN_TUN_TO_LV = 4
+STT_TUN_TO_LV = 5
 GENEVE_TUN_TO_LV = 6
 
 DVR_NOT_LEARN = 9
@@ -98,7 +99,8 @@ ARP_REPLY = '0x2'
 # Map tunnel types to tables number
 TUN_TABLE = {p_const.TYPE_GRE: GRE_TUN_TO_LV,
              p_const.TYPE_VXLAN: VXLAN_TUN_TO_LV,
-             p_const.TYPE_GENEVE: GENEVE_TUN_TO_LV}
+             p_const.TYPE_GENEVE: GENEVE_TUN_TO_LV,
+             p_const.TYPE_STT: STT_TUN_TO_LV}
 
 
 # The default respawn interval for the ovsdb monitor
diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py
index 93fbc19..41d4976 100644
--- a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py
+++ b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py
@@ -367,6 +367,7 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
     def _reset_tunnel_ofports(self):
         self.tun_br_ofports = {p_const.TYPE_GENEVE: {},
                                p_const.TYPE_GRE: {},
+                               p_const.TYPE_STT: {},
                                p_const.TYPE_VXLAN: {}}
 
     def setup_rpc(self):
@@ -629,7 +630,7 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
 
         :param net_uuid: the uuid of the network associated with this vlan.
         :param network_type: the network type ('gre', 'vxlan', 'vlan', 'flat',
-                                               'local', 'geneve')
+                                               'local', 'stt', 'geneve')
         :param physical_network: the physical network for 'vlan' or 'flat'
         :param segmentation_id: the VID for 'vlan' or tunnel ID for 'tunnel'
         '''
@@ -2110,7 +2111,7 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
         if (self.enable_distributed_routing and self.enable_tunneling
             and not self.l2_pop):
 
-            raise ValueError(_("DVR deployments for VXLAN/GRE/Geneve "
+            raise ValueError(_("DVR deployments for VXLAN/GRE/STT/Geneve "
                                "underlays require L2-pop to be enabled, "
                                "in both the Agent and Server side."))
 
diff --git a/neutron/plugins/ml2/drivers/type_stt.py b/neutron/plugins/ml2/drivers/type_stt.py
new file mode 100644
index 0000000..27b8e9a
--- /dev/null
+++ b/neutron/plugins/ml2/drivers/type_stt.py
@@ -0,0 +1,142 @@
+# Copyright (c) 2015 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.
+
+from oslo_config import cfg
+from oslo_log import log
+from six import moves
+import sqlalchemy as sa
+from sqlalchemy import sql
+
+from neutron.common import exceptions as n_exc
+from neutron.db import api as db_api
+from neutron.db import model_base
+from neutron.i18n import _LE
+from neutron.plugins.common import constants as p_const
+from neutron.plugins.ml2.drivers import type_tunnel
+
+LOG = log.getLogger(__name__)
+
+stt_opts = [
+    cfg.ListOpt('context_id_ranges',
+                default=['1000:3000'],
+                help=_("Comma-separated list of "
+                       "<context_id_min>:<context_id_max> tuples "
+                       "enumerating ranges of STT Context IDs that are "
+                       "available for tenant network allocation"))
+]
+
+cfg.CONF.register_opts(stt_opts, "ml2_type_stt")
+
+
+class SttAllocation(model_base.BASEV2):
+
+    __tablename__ = 'ml2_stt_allocations'
+
+    stt_context_id = sa.Column(sa.Integer, nullable=False, primary_key=True,
+                               autoincrement=False)
+    allocated = sa.Column(sa.Boolean, nullable=False, default=False,
+                          server_default=sql.false(), index=True)
+
+
+class SttEndpoints(model_base.BASEV2):
+    """Represents tunnel endpoint in RPC mode."""
+
+    __tablename__ = 'ml2_stt_endpoints'
+    __table_args__ = (
+        sa.UniqueConstraint('host',
+                            name='unique_ml2_stt_endpoints0host'),
+        model_base.BASEV2.__table_args__
+    )
+    ip_address = sa.Column(sa.String(64), primary_key=True)
+    host = sa.Column(sa.String(255), nullable=True)
+
+    def __repr__(self):
+        return "<SttTunnelEndpoint(%s)>" % self.ip_address
+
+
+class SttTypeDriver(type_tunnel.EndpointTunnelTypeDriver):
+
+    def __init__(self):
+        super(SttTypeDriver, self).__init__(SttAllocation,
+                                            SttEndpoints)
+
+    def get_type(self):
+        return p_const.TYPE_STT
+
+    def initialize(self):
+        try:
+            self._initialize(cfg.CONF.ml2_type_stt.context_id_ranges)
+        except n_exc.NetworkTunnelRangeError:
+            LOG.exception(_LE("Failed to parse context_id_ranges. "
+                              "Service terminated!"))
+            raise SystemExit()
+
+    def sync_allocations(self):
+        # FIXME(arosen) - refactor out duplicate code from type_vxlan driver.
+
+        # determine current configured allocatable context_ids
+        stt_context_ids = set()
+        for tun_min, tun_max in self.tunnel_ranges:
+            if tun_max + 1 - tun_min > p_const.MAX_STT_CONTEXT_ID:
+                LOG.error(_LE("Skipping unreasonable STT VNI range "
+                              "%(tun_min)s:%(tun_max)s"),
+                          {'tun_min': tun_min, 'tun_max': tun_max})
+            else:
+                stt_context_ids |= set(moves.range(tun_min, tun_max + 1))
+
+        session = db_api.get_session()
+        with session.begin(subtransactions=True):
+            # remove from table unallocated tunnels not currently allocatable
+            # fetch results as list via all() because we'll be iterating
+            # through them twice
+            allocs = (session.query(SttAllocation).
+                      with_lockmode("update").all())
+            # collect all context_ids present in db
+            existing_context_ids = set(alloc.stt_context_id
+                                       for alloc in allocs)
+            # collect those context_ids that needs to be deleted from db
+            context_ids_to_remove = [
+                alloc.stt_context_id for alloc in allocs
+                if (alloc.stt_context_id not in stt_context_ids and
+                    not alloc.allocated)]
+            # Immediately delete context_ids in chunks. This leaves no work for
+            # flush at the end of transaction
+            bulk_size = 100
+            chunked_context_ids = (
+                context_ids_to_remove[i:i + bulk_size]
+                for i in range(0, len(context_ids_to_remove), bulk_size))
+            for context_id_list in chunked_context_ids:
+                if context_id_list:
+                    session.query(SttAllocation).filter(
+                        SttAllocation.stt_context_id.in_(context_id_list)).delete(
+                            synchronize_session=False)
+            # collect context_ids that need to be added
+            context_ids = list(stt_context_ids - existing_context_ids)
+            chunked_context_ids = (context_ids[i:i + bulk_size] for i in
+                            range(0, len(context_ids), bulk_size))
+            for context_id_list in chunked_context_ids:
+                bulk = [{'stt_context_id': context_id, 'allocated': False}
+                        for context_id in context_id_list]
+                session.execute(SttAllocation.__table__.insert(), bulk)
+
+    def get_endpoints(self):
+        """Get every stt endpoints from database."""
+        stt_endpoints = self._get_endpoints()
+        return [{'ip_address': stt_endpoint.ip_address,
+                 'host': stt_endpoint.host}
+                for stt_endpoint in stt_endpoints]
+
+    def add_endpoint(self, ip, host):
+        return self._add_endpoint(ip, host)
diff --git a/setup.cfg b/setup.cfg
index 5479a7c..7098b9d 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -91,6 +91,7 @@ neutron.ml2.type_drivers =
     geneve = neutron.plugins.ml2.drivers.type_geneve:GeneveTypeDriver
     gre = neutron.plugins.ml2.drivers.type_gre:GreTypeDriver
     vxlan = neutron.plugins.ml2.drivers.type_vxlan:VxlanTypeDriver
+    stt = neutron.plugins.ml2.drivers.type_stt:SttTypeDriver
 neutron.ml2.mechanism_drivers =
     logger = neutron.tests.unit.plugins.ml2.drivers.mechanism_logger:LoggerMechanismDriver
     test = neutron.tests.unit.plugins.ml2.drivers.mechanism_test:TestMechanismDriver

測試結果