Auto-enable loadbalancer VIP ports

By default, when loadbalancer VIP ports are created (either via Octavia
or via neutron-lbaas (v2)), then the port is created with
admin_state_up=False (i.e. the port is disabled). Dragonflow respects
this attribute, and does not 'wire' the port in this case.

Rather than change the default in Octavia and neutron-LBaaS, this patch
detects this case, and enables the VIP ports.

Change-Id: Ibbe927b2672f327349bdd9cff46349d4d01c990a
Partial-Bug: #1720734
This commit is contained in:
Omer Anson 2017-12-10 17:12:16 +02:00
parent 920910cda3
commit 49f836128a
8 changed files with 113 additions and 0 deletions

View File

@ -262,6 +262,7 @@ function configure_df_plugin {
iniset $NEUTRON_CONF DEFAULT service_plugins "$Q_SERVICE_PLUGIN_CLASSES"
iniset $DRAGONFLOW_CONF df auto_detect_port_behind_port "$DF_AUTO_DETECT_PORT_BEHIND_PORT"
iniset $DRAGONFLOW_CONF df_loadbalancer auto_enable_vip_ports "$DF_LBAAS_AUTO_ENABLE_VIP_PORTS"
if is_service_enabled q-dhcp ; then
iniset $DRAGONFLOW_CONF df use_centralized_ipv6_DHCP "True"

View File

@ -12,6 +12,7 @@ DF_PUBLISHER_SERVICE_BINARY=$NEUTRON_BIN_DIR/df-publisher-service
DF_PUBLISHER_MULTIPROC_SOCKET=${DF_PUBLISHER_MULTIPROC_SOCKET:-"/var/run/zmq_pubsub/zmq-publisher-socket"}
DF_AUTO_DETECT_PORT_BEHIND_PORT=${DF_AUTO_DETECT_PORT_BEHIND_PORT:-"False"}
DF_LBAAS_AUTO_ENABLE_VIP_PORTS=${DF_LBAAS_AUTO_ENABLE_VIP_PORTS:-"True"}
# df-metadata
DF_METADATA_SERVICE=${DF_METADATA_SERVICE:-"$NEUTRON_BIN_DIR/df-metadata-service"}

View File

@ -20,6 +20,7 @@ from dragonflow.conf import df_dhcp
from dragonflow.conf import df_dnat
from dragonflow.conf import df_l2
from dragonflow.conf import df_l3
from dragonflow.conf import df_loadbalancer
from dragonflow.conf import df_metadata_service
from dragonflow.conf import df_provider_networks
from dragonflow.conf import df_ryu
@ -32,6 +33,7 @@ CONF = cfg.CONF
df_cassandra.register_opts()
df_common_params.register_opts()
df_dhcp.register_opts()
df_loadbalancer.register_opts()
df_metadata_service.register_opts()
df_active_port_detection.register_opts()
df_l2.register_opts()

View File

@ -0,0 +1,33 @@
# 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 dragonflow._i18n import _
df_loadbalancer_opts = [
cfg.BoolOpt(
'auto_enable_vip_ports',
default='True',
help=_('Automatically set load-balancer VIP ports to be enabled'),
),
]
def register_opts():
cfg.CONF.register_opts(df_loadbalancer_opts, group='df_loadbalancer')
def list_opts():
return {'df_loadbalancer': df_loadbalancer_opts}

View File

@ -33,6 +33,7 @@ from dragonflow.db.neutron import lockedobjects_db as lock_db
from dragonflow.neutron.db.models import l2 as neutron_l2
from dragonflow.neutron.db.models import secgroups as neutron_secgroups
from dragonflow.neutron.ml2 import dhcp_module
from dragonflow.neutron.services.lbaas import vip_port_enabler
from dragonflow.neutron.services.qos.drivers import df_qos
from dragonflow.neutron.services.trunk import driver as trunk_driver
from dragonflow.neutron.services.trunk import port_behind_port
@ -69,6 +70,8 @@ class DFMechDriver(api.MechanismDriver):
if cfg.CONF.df.auto_detect_port_behind_port:
self._port_behind_port_detector = (
port_behind_port.DfPortBehindPortDetector())
if cfg.CONF.df_loadbalancer.auto_enable_vip_ports:
self._vip_port_enabler = vip_port_enabler.DfLBaaSVIPPortEnabler()
self.subscribe_registries()
df_qos.register()
self.dhcp_module = dhcp_module.DFDHCPModule()

View File

@ -0,0 +1,39 @@
# 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 neutron_lib.callbacks import events
from neutron_lib.callbacks import registry
from neutron_lib.callbacks import resources
from neutron_lib import constants
LBAAS_PORT_OWNERS = [
constants.DEVICE_OWNER_LOADBALANCER,
constants.DEVICE_OWNER_LOADBALANCERV2,
]
try:
from octavia.network.drivers.neutron import allowed_address_pairs
LBAAS_PORT_OWNERS.append(allowed_address_pairs.OCTAVIA_OWNER)
except ImportError:
pass # No octavia
@registry.has_registry_receivers
class DfLBaaSVIPPortEnabler(object):
@registry.receives(resources.PORT, [events.BEFORE_CREATE])
def port_create(self, *args, **kwargs):
port = kwargs['port']
if port['device_owner'] not in LBAAS_PORT_OWNERS:
return
port['admin_state_up'] = True

View File

@ -0,0 +1,34 @@
# 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 neutron_lib import constants
from dragonflow import conf as cfg
from dragonflow.tests.unit import test_mech_driver
class TestVIPPortEnabler(test_mech_driver.DFMechanismDriverTestCase):
def setUp(self):
cfg.CONF.set_override('auto_enable_vip_ports',
True,
group='df_loadbalancer')
super(TestVIPPortEnabler, self).setUp()
def test_vip_port_enable(self):
with self.port(device_owner=constants.DEVICE_OWNER_LOADBALANCERV2,
admin_state_up=False) as p:
self.assertTrue(p['port']['admin_state_up'])
def test_vip_port_enable_negative_test(self):
with self.port(device_owner='someone:else',
admin_state_up=False) as p:
self.assertFalse(p['port']['admin_state_up'])