Browse Source

Merge "Adding extra_params support and stp_edge param"

changes/43/738143/1
Zuul 2 weeks ago
committed by Gerrit Code Review
parent
commit
0fd807c3ef
5 changed files with 92 additions and 36 deletions
  1. +4
    -6
      networking_ansible/config.py
  2. +25
    -0
      networking_ansible/constants.py
  3. +34
    -18
      networking_ansible/ml2/mech_driver.py
  4. +12
    -0
      networking_ansible/tests/unit/base.py
  5. +17
    -12
      networking_ansible/tests/unit/ml2/test_mech_driver.py

+ 4
- 6
networking_ansible/config.py View File

@@ -17,6 +17,7 @@ from oslo_config import cfg
from oslo_config import types
from oslo_log import log as logging

from networking_ansible import constants as c
CONF = cfg.CONF
LOG = logging.getLogger(__name__)

@@ -31,9 +32,6 @@ cfg.CONF.register_opts(anet_opts, group='ml2_ansible')

class Config(object):

driver_tag = 'ansible:'
booleans = ['manage_vlans']

def __init__(self):
"""Get inventory list from config files

@@ -56,14 +54,14 @@ class Config(object):

# filter out sections that begin with the driver's tag
hosts = {k: v for k, v in sections.items()
if k.startswith(self.driver_tag)}
if k.startswith(c.DRIVER_TAG)}

# munge the oslo_config data removing the device tag and
# turning lists with single item strings into strings
for host in hosts:
dev_id = host.partition(self.driver_tag)[2]
dev_id = host.partition(c.DRIVER_TAG)[2]
dev_cfg = {k: v[0] for k, v in hosts[host].items()}
for b in self.booleans:
for b in c.BOOLEANS:
if b in dev_cfg:
dev_cfg[b] = types.Boolean()(dev_cfg[b])
self.inventory[dev_id] = dev_cfg


+ 25
- 0
networking_ansible/constants.py View File

@@ -0,0 +1,25 @@
# Copyright (c) 2018 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.

COORDINATION = 'networking_ansible.ml2.mech_driver.coordination'
DRIVER_TAG = 'ansible:'
LLI = 'local_link_information'
NETWORKING_ENTITY = 'ANSIBLENETWORKING'
PHYSNET = 'provider:physical_network'

# values that will be cast to Bool in the conf process
BOOLEANS = ['manage_vlans', 'stp_edge']
# values that will be rolled into a separate dict and passed to network_runner
EXTRA_PARAMS = ['stp_edge']

+ 34
- 18
networking_ansible/ml2/mech_driver.py View File

@@ -29,6 +29,7 @@ from oslo_config import cfg
from oslo_log import log as logging

from networking_ansible import config
from networking_ansible import constants as c
from networking_ansible import exceptions
from networking_ansible.ml2 import trunk_driver

@@ -39,11 +40,7 @@ from tooz import coordination


LOG = logging.getLogger(__name__)

ANSIBLE_NETWORKING_ENTITY = 'ANSIBLENETWORKING'
PHYSNET = 'provider:physical_network'
CONF = config.CONF
LLI = 'local_link_information'


class AnsibleMechanismDriver(ml2api.MechanismDriver):
@@ -64,6 +61,16 @@ class AnsibleMechanismDriver(ml2api.MechanismDriver):
_inv.deserialize({'all': {'hosts': self.ml2config.inventory}})
self.net_runr = net_runr_api.NetworkRunner(_inv)

# build the extra_params dict.
# this holds extra config params per host passed to network runner
self.extra_params = {}
for host_name in self.ml2config.inventory:
self.extra_params[host_name] = {}
for i in c.EXTRA_PARAMS:
if i in self.ml2config.inventory[host_name]:
self.extra_params[host_name][i] = \
self.ml2config.inventory[host_name].get(i)

self.coordinator = coordination.get_coordinator(
cfg.CONF.ml2_ansible.coordination_uri,
'{}-{}'.format(CONF.host, os.getpid()))
@@ -128,8 +135,10 @@ class AnsibleMechanismDriver(ml2api.MechanismDriver):

# Create VLAN on the switch
try:
self.net_runr.create_vlan(host_name,
segmentation_id)
self.net_runr.create_vlan(
host_name,
segmentation_id,
**self.extra_params[host_name])
LOG.info('Network {net_id}, segmentation '
'{seg} has been added on '
'ansible host {host}'.format(
@@ -201,8 +210,10 @@ class AnsibleMechanismDriver(ml2api.MechanismDriver):

# Delete VLAN on the switch
try:
self.net_runr.delete_vlan(host_name,
segmentation_id)
self.net_runr.delete_vlan(
host_name,
segmentation_id,
**self.extra_params[host_name])
LOG.info('Network {net_id} has been deleted on '
'ansible host {host}'.format(
net_id=network['id'],
@@ -235,7 +246,7 @@ class AnsibleMechanismDriver(ml2api.MechanismDriver):
port = context.current
provisioning_blocks.provisioning_complete(
context._plugin_context, port['id'], resources.PORT,
ANSIBLE_NETWORKING_ENTITY)
c.NETWORKING_ENTITY)

port = context.original
network = context.network.current
@@ -244,7 +255,7 @@ class AnsibleMechanismDriver(ml2api.MechanismDriver):

self.ensure_port(port['id'], context._plugin_context,
port['mac_address'], switch_name, switch_port,
network[PHYSNET], context)
network[c.PHYSNET], context)

def delete_port_postcommit(self, context):
"""Delete a port.
@@ -268,7 +279,7 @@ class AnsibleMechanismDriver(ml2api.MechanismDriver):

self.ensure_port(port['id'], context._plugin_context,
port['mac_address'], switch_name, switch_port,
network[PHYSNET], context)
network[c.PHYSNET], context)

def bind_port(self, context):
"""Attempt to bind a port.
@@ -332,11 +343,11 @@ class AnsibleMechanismDriver(ml2api.MechanismDriver):

provisioning_blocks.add_provisioning_component(
context._plugin_context, port['id'], resources.PORT,
ANSIBLE_NETWORKING_ENTITY)
c.NETWORKING_ENTITY)

self.ensure_port(port['id'], context._plugin_context,
port['mac_address'], switch_name, switch_port,
network[PHYSNET], context)
network[c.PHYSNET], context)

def _link_info_from_port(self, port, network=None):
network = network or {}
@@ -486,12 +497,15 @@ class AnsibleMechanismDriver(ml2api.MechanismDriver):
self.net_runr.conf_trunk_port(switch_name,
switch_port,
segmentation_id,
trunked_vlans)
trunked_vlans,
**self.extra_params[switch_name])

else:
self.net_runr.conf_access_port(switch_name,
switch_port,
segmentation_id)
self.net_runr.conf_access_port(
switch_name,
switch_port,
segmentation_id,
**self.extra_params[switch_name])

LOG.info('Port {neutron_port} has been plugged into '
'switch port {sp} on device {switch_name}'.format(
@@ -516,7 +530,9 @@ class AnsibleMechanismDriver(ml2api.MechanismDriver):
'on {switch_name}'.format(switch_port=switch_port,
switch_name=switch_name))
try:
self.net_runr.delete_port(switch_name, switch_port)
self.net_runr.delete_port(switch_name,
switch_port,
**self.extra_params[switch_name])
LOG.info('Unplugged port {switch_port} '
'on {switch_name}'.format(switch_port=switch_port,
switch_name=switch_name))


+ 12
- 0
networking_ansible/tests/unit/base.py View File

@@ -49,6 +49,10 @@ class MockConfig(object):
self.inventory = {host: {'mac': mac}} if host and mac else {}
self.mac_map = {}

def add_extra_params(self):
for i in self.inventory:
self.inventory[i]['stp_edge'] = True


class BaseTestCase(base.BaseTestCase):
test_config_files = []
@@ -152,6 +156,14 @@ class NetworkingAnsibleTestCase(BaseTestCase):
'binding:vif_type': 'other',
'mac_address': self.testmac
}
self.mock_port_context.original = {
'id': self.testid,
'binding:profile': self.lli_no_mac,
'binding:vnic_type': 'baremetal',
'binding:vif_type': 'other',
'mac_address': self.testmac
}

self.mock_port_context._plugin_context = mock.MagicMock()
self.mock_port_context.network = mock.Mock()
self.mock_port_context.network.current = {


+ 17
- 12
networking_ansible/tests/unit/ml2/test_mech_driver.py View File

@@ -32,16 +32,10 @@ from neutron_lib.api.definitions import provider_net
from neutron_lib.callbacks import resources
import webob.exc

from networking_ansible import constants as c
from networking_ansible.tests.unit import base
from tooz import coordination

COORDINATION = 'networking_ansible.ml2.mech_driver.coordination'

ANSIBLE_NETWORKING_ENTITY = 'ANSIBLENETWORKING'
COORDINATION = 'networking_ansible.ml2.mech_driver.coordination'
BIND_PROF = 'binding:profile'
LOCAL_LINK_INFO = 'local_link_information'


class TestLibTestConfigFixture(fixtures.Fixture):
def __init__(self):
@@ -59,7 +53,7 @@ class TestLibTestConfigFixture(fixtures.Fixture):
class NetAnsibleML2Base(test_plugin.Ml2PluginV2TestCase):
def setUp(self):
base.patch_neutron_quotas()
with mock.patch(COORDINATION) as m_coord:
with mock.patch(c.COORDINATION) as m_coord:
m_coord.get_coordinator = lambda *args: mock.create_autospec(
coordination.CoordinationDriver).return_value
super(NetAnsibleML2Base, self).setUp()
@@ -274,13 +268,24 @@ class TestDeletePortPostCommit(base.NetworkingAnsibleTestCase):
@mock.patch('networking_ansible.config.Config')
class TestInit(base.NetworkingAnsibleTestCase):
def test_intialize(self, m_config):
with mock.patch(COORDINATION) as m_coord:
with mock.patch(c.COORDINATION) as m_coord:
m_coord.get_coordinator = lambda *args: mock.create_autospec(
coordination.CoordinationDriver).return_value
m_config.return_value = base.MockConfig()
self.mech.initialize()
m_config.assert_called_once_with()

def test_intialize_w_extra_params(self, m_config):
with mock.patch(c.COORDINATION) as m_coord:
m_coord.get_coordinator = lambda *args: mock.create_autospec(
coordination.CoordinationDriver).return_value
m_config.return_value = base.MockConfig(self.testhost,
self.testmac)
m_config.return_value.add_extra_params()
self.mech.initialize()
assert self.mech.extra_params == {self.testhost:
{'stp_edge': True}}


@mock.patch('networking_ansible.ml2.mech_driver.'
'AnsibleMechanismDriver._is_port_bound')
@@ -300,7 +305,7 @@ class TestUpdatePortPostCommit(base.NetworkingAnsibleTestCase):
self.mock_port_context._plugin_context,
self.testid,
resources.PORT,
ANSIBLE_NETWORKING_ENTITY)
c.NETWORKING_ENTITY)
mock_ensure_port.assert_called_once_with(
self.testid,
self.mock_port_context._plugin_context,
@@ -376,8 +381,8 @@ class TestDeleteSwitchPort(base.NetworkingAnsibleTestCase):
2)

def test_delete_switch_port(self, mock_delete):
self.mech._delete_switch_port(1, 2)
mock_delete.assert_called_once_with(1, 2)
self.mech._delete_switch_port(self.testhost, self.testport)
mock_delete.assert_called_once_with(self.testhost, self.testport)


@mock.patch.object(ports.Port, 'get_objects')


Loading…
Cancel
Save