Port location tracking for BigSwitch Plugin
Adds a new table to the Big Switch plugin to keep track of the nova compute node host IDs that ports reside on. This table is then used to allow users to override the VIF type for a compute node based on the host ID. This allows quantum to control an environment with multiple VIF types. Change-Id: I63eb66d970650237aed2d5dc6676a6d097988f8d Implements: blueprint hostid-vif-override
This commit is contained in:
parent
23284e7c57
commit
d3dd33bc30
@ -51,6 +51,14 @@ servers=localhost:8080
|
||||
# default: ovs
|
||||
# vif_type = ovs
|
||||
|
||||
# Overrides for vif types based on nova compute node host IDs
|
||||
# Comma separated list of host IDs to fix to a specific VIF type
|
||||
# The VIF type is taken from the end of the configuration item
|
||||
# node_override_vif_<vif_type>
|
||||
# For example, the following would set the VIF type to IVS for
|
||||
# host-id1 and host-id2
|
||||
# node_overrride_vif_ivs=host-id1,host-id2
|
||||
|
||||
[router]
|
||||
# Specify the default router rules installed in newly created tenant routers
|
||||
# Specify multiple times for multiple rules
|
||||
|
@ -0,0 +1,63 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
#
|
||||
# Copyright 2013 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.
|
||||
#
|
||||
|
||||
"""Table to track port to host associations
|
||||
|
||||
Revision ID: 3cabb850f4a5
|
||||
Revises: 5918cbddab04
|
||||
Create Date: 2013-06-24 14:30:33.533562
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '3cabb850f4a5'
|
||||
down_revision = '5918cbddab04'
|
||||
|
||||
# Change to ['*'] if this migration applies to all plugins
|
||||
|
||||
migration_for_plugins = [
|
||||
'quantum.plugins.bigswitch.plugin.QuantumRestProxyV2'
|
||||
]
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
from quantum.db import migration
|
||||
|
||||
|
||||
def upgrade(active_plugin=None, options=None):
|
||||
if not migration.should_run(active_plugin, migration_for_plugins):
|
||||
return
|
||||
|
||||
### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('portlocations',
|
||||
sa.Column('port_id', sa.String(length=255),
|
||||
primary_key=True, nullable=False),
|
||||
sa.Column('host_id',
|
||||
sa.String(length=255), nullable=False)
|
||||
)
|
||||
### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade(active_plugin=None, options=None):
|
||||
if not migration.should_run(active_plugin, migration_for_plugins):
|
||||
return
|
||||
|
||||
### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_table('portlocations')
|
||||
### end Alembic commands ###
|
@ -44,6 +44,10 @@ VIF_TYPE_802_QBG = '802.1qbg'
|
||||
VIF_TYPE_802_QBH = '802.1qbh'
|
||||
VIF_TYPE_HYPERV = 'hyperv'
|
||||
VIF_TYPE_OTHER = 'other'
|
||||
VIF_TYPES = [VIF_TYPE_UNBOUND, VIF_TYPE_BINDING_FAILED, VIF_TYPE_OVS,
|
||||
VIF_TYPE_IVS, VIF_TYPE_BRIDGE, VIF_TYPE_802_QBG,
|
||||
VIF_TYPE_802_QBH, VIF_TYPE_HYPERV, VIF_TYPE_OTHER]
|
||||
|
||||
|
||||
EXTENDED_ATTRIBUTES_2_0 = {
|
||||
'ports': {
|
||||
|
18
quantum/plugins/bigswitch/db/__init__.py
Normal file
18
quantum/plugins/bigswitch/db/__init__.py
Normal file
@ -0,0 +1,18 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2013 Big Switch Networks, 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: Kevin Benton, Big Switch Networks, Inc.
|
46
quantum/plugins/bigswitch/db/porttracker_db.py
Normal file
46
quantum/plugins/bigswitch/db/porttracker_db.py
Normal file
@ -0,0 +1,46 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
#
|
||||
# Copyright 2013, Big Switch Networks
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from quantum.db import model_base
|
||||
from quantum.openstack.common import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PortLocation(model_base.BASEV2):
|
||||
port_id = sa.Column(sa.String(255), primary_key=True)
|
||||
host_id = sa.Column(sa.String(255), nullable=False)
|
||||
|
||||
|
||||
def get_port_hostid(context, port_id):
|
||||
with context.session.begin(subtransactions=True):
|
||||
query = context.session.query(PortLocation)
|
||||
res = query.filter_by(port_id=port_id).first()
|
||||
if not res:
|
||||
return False
|
||||
return res.host_id
|
||||
|
||||
|
||||
def put_port_hostid(context, port_id, host_id):
|
||||
if port_id == '':
|
||||
LOG.warning(_("Received an empty port ID for host '%s'"), host_id)
|
||||
return
|
||||
with context.session.begin(subtransactions=True):
|
||||
location = PortLocation(port_id=port_id, host_id=host_id)
|
||||
context.session.add(location)
|
@ -68,6 +68,7 @@ from quantum.extensions import l3
|
||||
from quantum.extensions import portbindings
|
||||
from quantum.openstack.common import log as logging
|
||||
from quantum.openstack.common import rpc
|
||||
from quantum.plugins.bigswitch.db import porttracker_db
|
||||
from quantum.plugins.bigswitch import routerrule_db
|
||||
from quantum.plugins.bigswitch.version import version_string_with_vcs
|
||||
|
||||
@ -126,6 +127,15 @@ nova_opts = [
|
||||
"Nova compute nodes")),
|
||||
]
|
||||
|
||||
# Each VIF Type can have a list of nova host IDs that are fixed to that type
|
||||
for i in portbindings.VIF_TYPES:
|
||||
opt = cfg.ListOpt('node_override_vif_' + i, default=[],
|
||||
help=_("Nova compute nodes to manually set VIF "
|
||||
"type to %s") % i)
|
||||
nova_opts.append(opt)
|
||||
|
||||
# Add the vif types for reference later
|
||||
nova_opts.append(cfg.ListOpt('vif_types', default=portbindings.VIF_TYPES))
|
||||
|
||||
cfg.CONF.register_opts(nova_opts, "NOVA")
|
||||
|
||||
@ -569,6 +579,10 @@ class QuantumRestProxyV2(db_base_plugin_v2.QuantumDbPluginV2,
|
||||
|
||||
# Update DB
|
||||
port["port"]["admin_state_up"] = False
|
||||
if (portbindings.HOST_ID in port['port']
|
||||
and 'device_id' in port['port']):
|
||||
porttracker_db.put_port_hostid(context, port['port']['device_id'],
|
||||
port['port'][portbindings.HOST_ID])
|
||||
new_port = super(QuantumRestProxyV2, self).create_port(context, port)
|
||||
net = super(QuantumRestProxyV2,
|
||||
self).get_network(context, new_port["network_id"])
|
||||
@ -661,7 +675,10 @@ class QuantumRestProxyV2(db_base_plugin_v2.QuantumDbPluginV2,
|
||||
# Update DB
|
||||
new_port = super(QuantumRestProxyV2, self).update_port(context,
|
||||
port_id, port)
|
||||
|
||||
if (portbindings.HOST_ID in port['port']
|
||||
and 'device_id' in port['port']):
|
||||
porttracker_db.put_port_hostid(context, port['port']['device_id'],
|
||||
port['port'][portbindings.HOST_ID])
|
||||
# update on networl ctrl
|
||||
try:
|
||||
resource = PORTS_PATH % (orig_port["tenant_id"],
|
||||
@ -1335,10 +1352,21 @@ class QuantumRestProxyV2(db_base_plugin_v2.QuantumDbPluginV2,
|
||||
"[%s]. Defaulting to ovs. "),
|
||||
cfg_vif_type)
|
||||
cfg_vif_type = portbindings.VIF_TYPE_OVS
|
||||
|
||||
hostid = porttracker_db.get_port_hostid(context,
|
||||
port.get("device_id"))
|
||||
if hostid:
|
||||
override = self._check_hostvif_override(hostid)
|
||||
if override:
|
||||
cfg_vif_type = override
|
||||
port[portbindings.VIF_TYPE] = cfg_vif_type
|
||||
|
||||
port[portbindings.CAPABILITIES] = {
|
||||
portbindings.CAP_PORT_FILTER:
|
||||
'security-group' in self.supported_extension_aliases}
|
||||
return port
|
||||
|
||||
def _check_hostvif_override(self, hostid):
|
||||
for v in cfg.CONF.NOVA.vif_types:
|
||||
if hostid in getattr(cfg.CONF.NOVA, "node_override_vif_" + v, []):
|
||||
return v
|
||||
return False
|
||||
|
@ -30,6 +30,9 @@ serverssl=False
|
||||
# options: ivs or ovs
|
||||
# default: ovs
|
||||
vif_type = ovs
|
||||
# Overrides for vif types based on nova compute node host IDs
|
||||
# Comma separated list of host IDs to fix to a specific VIF type
|
||||
node_override_vif_ivs = ivshost
|
||||
|
||||
[router]
|
||||
# Specify the default router rules installed in newly created tenant routers
|
||||
|
@ -19,6 +19,7 @@ import os
|
||||
|
||||
from mock import patch
|
||||
from oslo.config import cfg
|
||||
import webob.exc
|
||||
|
||||
import quantum.common.test_lib as test_lib
|
||||
from quantum.extensions import portbindings
|
||||
@ -106,6 +107,38 @@ class TestBigSwitchProxyPortsV2IVS(test_plugin.TestPortsV2,
|
||||
cfg.CONF.set_override('vif_type', 'ivs', 'NOVA')
|
||||
|
||||
|
||||
class TestBigSwitchVIFOverride(test_plugin.TestPortsV2,
|
||||
BigSwitchProxyPluginV2TestCase,
|
||||
test_bindings.PortBindingsTestCase):
|
||||
VIF_TYPE = portbindings.VIF_TYPE_OVS
|
||||
HAS_PORT_FILTER = False
|
||||
|
||||
def setUp(self):
|
||||
super(TestBigSwitchVIFOverride,
|
||||
self).setUp()
|
||||
cfg.CONF.set_override('vif_type', 'ovs', 'NOVA')
|
||||
|
||||
def test_port_vif_details(self):
|
||||
kwargs = {'name': 'name', 'binding:host_id': 'ivshost',
|
||||
'device_id': 'override_dev'}
|
||||
with self.port(**kwargs) as port:
|
||||
self.assertEqual(port['port']['binding:vif_type'],
|
||||
portbindings.VIF_TYPE_IVS)
|
||||
kwargs = {'name': 'name2', 'binding:host_id': 'someotherhost',
|
||||
'device_id': 'other_dev'}
|
||||
with self.port(**kwargs) as port:
|
||||
self.assertEqual(port['port']['binding:vif_type'], self.VIF_TYPE)
|
||||
|
||||
def _make_port(self, fmt, net_id, expected_res_status=None, **kwargs):
|
||||
res = self._create_port(fmt, net_id, expected_res_status,
|
||||
('binding:host_id', ), **kwargs)
|
||||
# Things can go wrong - raise HTTP exc with res code only
|
||||
# so it can be caught by unit tests
|
||||
if res.status_int >= 400:
|
||||
raise webob.exc.HTTPClientError(code=res.status_int)
|
||||
return self.deserialize(fmt, res)
|
||||
|
||||
|
||||
class TestBigSwitchProxyNetworksV2(test_plugin.TestNetworksV2,
|
||||
BigSwitchProxyPluginV2TestCase):
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user