Mark OVS bridges and ports as managed by charm-neutron-gateway
This patchset updates the configure_ovs() function in hooks/neutron_utils.py such that ports and bridges in OVS are marked as being managed by this charm. This will allow us to clean up obsolete managed bridges and ports in a later patchset. (On configuration change new ports and bridges might be created and former ones might become obsolete.) This patchset also fully deprecates the 'ext-port' config option such that if both 'data-port' and 'ext-port' config options are set, the unit is blocked. The README and config.yaml are updated to reflect this change. This patchset also fixes and removes a few dead links. Relies on a charm-helpers version containing these patchsets: https://github.com/juju/charm-helpers/pull/443 https://github.com/juju/charm-helpers/pull/447 https://github.com/juju/charm-helpers/pull/449 Related documentation: * Deployment guide / Upgrades / Known issues: https://review.opendev.org/630290 * Release notes: https://review.opendev.org/742660 Change-Id: I8b459135d131e16865de40ff3eae16ea3bc7195e Partial-Bug: #1809190
This commit is contained in:
parent
a8f1661d61
commit
bbc621edca
12
README.md
12
README.md
|
@ -10,7 +10,7 @@ instances plug into.
|
||||||
Neutron supports a rich plugin/extension framework for propriety networking
|
Neutron supports a rich plugin/extension framework for propriety networking
|
||||||
solutions and supports (in core) Nicira NVP, NEC, Cisco and others...
|
solutions and supports (in core) Nicira NVP, NEC, Cisco and others...
|
||||||
|
|
||||||
See the upstream [Neutron documentation](http://docs.openstack.org/trunk/openstack-network/admin/content/use_cases_single_router.html)
|
See the upstream [Neutron documentation](https://docs.openstack.org/neutron/latest/)
|
||||||
for more details.
|
for more details.
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
|
@ -44,8 +44,6 @@ The gateway provides two key services; L3 network routing and DHCP services.
|
||||||
|
|
||||||
These are both required in a fully functional Neutron OpenStack deployment.
|
These are both required in a fully functional Neutron OpenStack deployment.
|
||||||
|
|
||||||
See upstream [Neutron multi extnet](http://docs.openstack.org/trunk/config-reference/content/adv_cfg_l3_agent_multi_extnet.html)
|
|
||||||
|
|
||||||
Configuration Options
|
Configuration Options
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
@ -109,6 +107,11 @@ This replaces the previous system of using ext-port, which always created a brid
|
||||||
called br-ex for external networks which was used implicitly by external router
|
called br-ex for external networks which was used implicitly by external router
|
||||||
interfaces.
|
interfaces.
|
||||||
|
|
||||||
|
Note: if the 'data-port' config item is set, then the 'ext-port' option is
|
||||||
|
ignored. This is to prevent misconfiguration of the charm. A warning is
|
||||||
|
logged and the unit is marked as blocked in order to indicate that the charm is
|
||||||
|
misconfigured.
|
||||||
|
|
||||||
Instance MTU
|
Instance MTU
|
||||||
============
|
============
|
||||||
|
|
||||||
|
@ -119,7 +122,4 @@ charm's instance-mtu option can be used to reduce instance MTU via DHCP.
|
||||||
|
|
||||||
juju set neutron-gateway instance-mtu=1400
|
juju set neutron-gateway instance-mtu=1400
|
||||||
|
|
||||||
OpenStack upstream documentation recommends a MTU value of 1400:
|
|
||||||
[OpenStack documentation](http://docs.openstack.org/admin-guide-cloud/content/openvswitch_plugin.html)
|
|
||||||
|
|
||||||
Note that this option was added in Havana and will be ignored in older releases.
|
Note that this option was added in Havana and will be ignored in older releases.
|
||||||
|
|
|
@ -86,6 +86,10 @@ options:
|
||||||
traffic to the external public network. Valid values are either MAC
|
traffic to the external public network. Valid values are either MAC
|
||||||
addresses (in which case only MAC addresses for interfaces without an IP
|
addresses (in which case only MAC addresses for interfaces without an IP
|
||||||
address already assigned will be used), or interfaces (eth0)
|
address already assigned will be used), or interfaces (eth0)
|
||||||
|
.
|
||||||
|
Note that if data-port is used then this config item is ignored, a
|
||||||
|
warning is logged, and the unit is marked as blocked in order to indicate
|
||||||
|
that the charm is misconfigured.
|
||||||
data-port:
|
data-port:
|
||||||
type: string
|
type: string
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -16,6 +16,7 @@ from charmhelpers.core.hookenv import (
|
||||||
log,
|
log,
|
||||||
DEBUG,
|
DEBUG,
|
||||||
INFO,
|
INFO,
|
||||||
|
WARNING,
|
||||||
ERROR,
|
ERROR,
|
||||||
config,
|
config,
|
||||||
is_relation_made,
|
is_relation_made,
|
||||||
|
@ -34,25 +35,27 @@ from charmhelpers.fetch import (
|
||||||
from charmhelpers.contrib.network.ovs import (
|
from charmhelpers.contrib.network.ovs import (
|
||||||
add_bridge,
|
add_bridge,
|
||||||
add_bridge_port,
|
add_bridge_port,
|
||||||
is_linuxbridge_interface,
|
|
||||||
add_ovsbridge_linuxbridge,
|
add_ovsbridge_linuxbridge,
|
||||||
full_restart,
|
|
||||||
enable_ipfix,
|
enable_ipfix,
|
||||||
disable_ipfix,
|
disable_ipfix,
|
||||||
|
full_restart,
|
||||||
|
get_bridges_and_ports_map,
|
||||||
|
is_linuxbridge_interface,
|
||||||
)
|
)
|
||||||
from charmhelpers.contrib.hahelpers.cluster import (
|
from charmhelpers.contrib.hahelpers.cluster import (
|
||||||
get_hacluster_config,
|
get_hacluster_config,
|
||||||
)
|
)
|
||||||
from charmhelpers.contrib.openstack.utils import (
|
from charmhelpers.contrib.openstack.utils import (
|
||||||
|
CompareOpenStackReleases,
|
||||||
configure_installation_source,
|
configure_installation_source,
|
||||||
get_os_codename_install_source,
|
get_os_codename_install_source,
|
||||||
make_assess_status_func,
|
make_assess_status_func,
|
||||||
|
os_application_version_set,
|
||||||
os_release,
|
os_release,
|
||||||
pause_unit,
|
pause_unit,
|
||||||
reset_os_release,
|
reset_os_release,
|
||||||
resume_unit,
|
resume_unit,
|
||||||
os_application_version_set,
|
workload_state_compare,
|
||||||
CompareOpenStackReleases,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
from charmhelpers.contrib.openstack.neutron import (
|
from charmhelpers.contrib.openstack.neutron import (
|
||||||
|
@ -841,28 +844,70 @@ def do_openstack_upgrade(configs):
|
||||||
|
|
||||||
|
|
||||||
def configure_ovs():
|
def configure_ovs():
|
||||||
|
"""Configure the OVS plugin.
|
||||||
|
|
||||||
|
This function uses the config.yaml parameters ext-port, data-port and
|
||||||
|
bridge-mappings to configure the bridges and ports on the ovs on the
|
||||||
|
unit.
|
||||||
|
|
||||||
|
Note that the ext-port is deprecated and data-port/bridge-mappings are
|
||||||
|
preferred.
|
||||||
|
|
||||||
|
Thus, if data-port is set, then ext-port is ignored (and if set, then
|
||||||
|
it is removed from the set of bridges unless it is defined in
|
||||||
|
bridge-mappings/data-port). A warning is issued, if both data-port and
|
||||||
|
ext-port are set.
|
||||||
|
"""
|
||||||
if config('plugin') in [OVS, OVS_ODL]:
|
if config('plugin') in [OVS, OVS_ODL]:
|
||||||
if not service_running('openvswitch-switch'):
|
if not service_running('openvswitch-switch'):
|
||||||
full_restart()
|
full_restart()
|
||||||
add_bridge(INT_BRIDGE)
|
# Get existing set of bridges and ports
|
||||||
add_bridge(EXT_BRIDGE)
|
current_bridges_and_ports = get_bridges_and_ports_map()
|
||||||
ext_port_ctx = ExternalPortContext()()
|
log("configure OVS: Current bridges and ports map: {}"
|
||||||
if ext_port_ctx and ext_port_ctx['ext_port']:
|
.format(", ".join("{}: {}".format(b, ",".join(v))
|
||||||
add_bridge_port(EXT_BRIDGE, ext_port_ctx['ext_port'])
|
for b, v in current_bridges_and_ports.items())))
|
||||||
|
|
||||||
|
add_bridge(INT_BRIDGE, brdata=_ovs_additional_data())
|
||||||
|
add_bridge(EXT_BRIDGE, brdata=_ovs_additional_data())
|
||||||
|
|
||||||
|
ext_port_ctx = ExternalPortContext()()
|
||||||
portmaps = DataPortContext()()
|
portmaps = DataPortContext()()
|
||||||
bridgemaps = parse_bridge_mappings(config('bridge-mappings'))
|
bridgemaps = parse_bridge_mappings(config('bridge-mappings'))
|
||||||
|
|
||||||
|
# if we have portmaps, then we ignore its value and log an
|
||||||
|
# error/warning to the unit's log.
|
||||||
|
if config('data-port') and config('ext-port'):
|
||||||
|
log("Both ext-port and data-port are set. ext-port is deprecated"
|
||||||
|
" and is not used when data-port is set", level=ERROR)
|
||||||
|
|
||||||
|
# only use ext-port if data-port is not set
|
||||||
|
if not portmaps and ext_port_ctx and ext_port_ctx['ext_port']:
|
||||||
|
_port = ext_port_ctx['ext_port']
|
||||||
|
add_bridge_port(EXT_BRIDGE, _port,
|
||||||
|
ifdata=_ovs_additional_data(EXT_BRIDGE),
|
||||||
|
portdata=_ovs_additional_data(EXT_BRIDGE))
|
||||||
|
log("DEPRECATION: using ext-port to set the port {} on the "
|
||||||
|
"EXT_BRIDGE ({}) is deprecated. Please use data-port instead."
|
||||||
|
.format(_port, EXT_BRIDGE),
|
||||||
|
level=WARNING)
|
||||||
|
|
||||||
for br in bridgemaps.values():
|
for br in bridgemaps.values():
|
||||||
add_bridge(br)
|
add_bridge(br, brdata=_ovs_additional_data())
|
||||||
if not portmaps:
|
if not portmaps:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for port, _br in portmaps.items():
|
for port, _br in portmaps.items():
|
||||||
if _br == br:
|
if _br == br:
|
||||||
if not is_linuxbridge_interface(port):
|
if not is_linuxbridge_interface(port):
|
||||||
add_bridge_port(br, port, promisc=True)
|
add_bridge_port(br, port, promisc=True,
|
||||||
|
ifdata=_ovs_additional_data(br),
|
||||||
|
portdata=_ovs_additional_data(br))
|
||||||
else:
|
else:
|
||||||
add_ovsbridge_linuxbridge(br, port)
|
# NOTE(lourot): this will raise on focal+ and/or if the
|
||||||
|
# system has no `ifup`. See lp:1877594
|
||||||
|
add_ovsbridge_linuxbridge(
|
||||||
|
br, port, ifdata=_ovs_additional_data(br),
|
||||||
|
portdata=_ovs_additional_data(br))
|
||||||
|
|
||||||
target = config('ipfix-target')
|
target = config('ipfix-target')
|
||||||
bridges = [INT_BRIDGE, EXT_BRIDGE]
|
bridges = [INT_BRIDGE, EXT_BRIDGE]
|
||||||
|
@ -878,11 +923,42 @@ def configure_ovs():
|
||||||
for bridge in bridges:
|
for bridge in bridges:
|
||||||
disable_ipfix(bridge)
|
disable_ipfix(bridge)
|
||||||
|
|
||||||
|
new_bridges_and_ports = get_bridges_and_ports_map()
|
||||||
|
log("configure OVS: Final bridges and ports map: {}"
|
||||||
|
.format(", ".join("{}: {}".format(b, ",".join(v))
|
||||||
|
for b, v in new_bridges_and_ports.items())),
|
||||||
|
level=DEBUG)
|
||||||
|
|
||||||
# Ensure this runs so that mtu is applied to data-port interfaces if
|
# Ensure this runs so that mtu is applied to data-port interfaces if
|
||||||
# provided.
|
# provided.
|
||||||
service_restart('os-charm-phy-nic-mtu')
|
service_restart('os-charm-phy-nic-mtu')
|
||||||
|
|
||||||
|
|
||||||
|
def _ovs_additional_data(external_id_value=None):
|
||||||
|
"""Returns OVS additional data from the given external-id value.
|
||||||
|
|
||||||
|
The returned value is in the input format expected by the
|
||||||
|
charmhelpers.contrib.network.ovs functions.
|
||||||
|
|
||||||
|
We set an external-id as OVS additional data on all the bridges and ports
|
||||||
|
that we create in order to mark them as managed by us. See
|
||||||
|
http://docs.openvswitch.org/en/latest/topics/integration/
|
||||||
|
|
||||||
|
:param external_id_value: Value to be set as external ID. For a bridge,
|
||||||
|
typically 'managed' (which is also the default if nothing is passed).
|
||||||
|
For a port, typically the name of the corresponding bridge.
|
||||||
|
:type external_id_value: str
|
||||||
|
:rtype: Dict[str,Dict[str,str]]
|
||||||
|
"""
|
||||||
|
external_id_value = ('managed' if external_id_value is None
|
||||||
|
else external_id_value)
|
||||||
|
return {
|
||||||
|
'external-ids': {
|
||||||
|
'charm-neutron-gateway': external_id_value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def copy_file(src, dst, perms=None, force=False):
|
def copy_file(src, dst, perms=None, force=False):
|
||||||
"""Copy file to destination and optionally set permissionss.
|
"""Copy file to destination and optionally set permissionss.
|
||||||
|
|
||||||
|
@ -1066,6 +1142,45 @@ def check_optional_relations(configs):
|
||||||
return validate_ovs_use_veth()
|
return validate_ovs_use_veth()
|
||||||
|
|
||||||
|
|
||||||
|
def check_ext_port_data_port_config(configs):
|
||||||
|
"""Checks that if data-port is set (other than None) then if ext-port is
|
||||||
|
also set, add a warning to the status line.
|
||||||
|
|
||||||
|
:param configs: an OSConfigRender() instance.
|
||||||
|
:type configs: OSConfigRender
|
||||||
|
:returns: (status, message)
|
||||||
|
:rtype: (str, str)
|
||||||
|
"""
|
||||||
|
if config('data-port') and config('ext-port'):
|
||||||
|
return ("blocked", "ext-port set when data-port set: see config.yaml")
|
||||||
|
# return 'unknown' as the lowest priority to not clobber an existing
|
||||||
|
# status.
|
||||||
|
return 'unknown', ''
|
||||||
|
|
||||||
|
|
||||||
|
def sequence_functions(*functions):
|
||||||
|
"""Sequence the functions passed so that they all get a chance to run as
|
||||||
|
the check_charm_func for the assess_status.
|
||||||
|
|
||||||
|
:param *functions: a list of functions that return (state, message)
|
||||||
|
:type *functions: List[Callable[[OSConfigRender], (str, str)]]
|
||||||
|
:returns: the Callable that takes configs and returns (state, message)
|
||||||
|
:rtype: Callable[[OSConfigRender], (str, str)]
|
||||||
|
"""
|
||||||
|
def _inner_sequenced_functions(configs):
|
||||||
|
state, message = 'unknown', ''
|
||||||
|
for f in functions:
|
||||||
|
new_state, new_message = f(configs)
|
||||||
|
state = workload_state_compare(state, new_state)
|
||||||
|
if message:
|
||||||
|
message = "{}, {}".format(message, new_message)
|
||||||
|
else:
|
||||||
|
message = new_message
|
||||||
|
return state, message
|
||||||
|
|
||||||
|
return _inner_sequenced_functions
|
||||||
|
|
||||||
|
|
||||||
def assess_status(configs):
|
def assess_status(configs):
|
||||||
"""Assess status of current unit
|
"""Assess status of current unit
|
||||||
Decides what the state of the unit should be based on the current
|
Decides what the state of the unit should be based on the current
|
||||||
|
@ -1101,9 +1216,11 @@ def assess_status_func(configs):
|
||||||
required_interfaces = REQUIRED_INTERFACES.copy()
|
required_interfaces = REQUIRED_INTERFACES.copy()
|
||||||
required_interfaces.update(get_optional_interfaces())
|
required_interfaces.update(get_optional_interfaces())
|
||||||
active_services = [s for s in services() if s not in STOPPED_SERVICES]
|
active_services = [s for s in services() if s not in STOPPED_SERVICES]
|
||||||
|
charm_func = sequence_functions(check_optional_relations,
|
||||||
|
check_ext_port_data_port_config)
|
||||||
return make_assess_status_func(
|
return make_assess_status_func(
|
||||||
configs, required_interfaces,
|
configs, required_interfaces,
|
||||||
charm_func=check_optional_relations,
|
charm_func=charm_func,
|
||||||
services=active_services, ports=None)
|
services=active_services, ports=None)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ tests:
|
||||||
- zaza.openstack.charm_tests.neutron.tests.NeutronGatewayTest
|
- zaza.openstack.charm_tests.neutron.tests.NeutronGatewayTest
|
||||||
- zaza.openstack.charm_tests.neutron.tests.SecurityTest
|
- zaza.openstack.charm_tests.neutron.tests.SecurityTest
|
||||||
- zaza.openstack.charm_tests.neutron.tests.NeutronNetworkingTest
|
- zaza.openstack.charm_tests.neutron.tests.NeutronNetworkingTest
|
||||||
|
- zaza.openstack.charm_tests.neutron.tests.NeutronOvsVsctlTest
|
||||||
configure:
|
configure:
|
||||||
- zaza.openstack.charm_tests.glance.setup.add_lts_image
|
- zaza.openstack.charm_tests.glance.setup.add_lts_image
|
||||||
- zaza.openstack.charm_tests.neutron.setup.basic_overcloud_network
|
- zaza.openstack.charm_tests.neutron.setup.basic_overcloud_network
|
||||||
|
|
|
@ -25,6 +25,7 @@ TO_PATCH = [
|
||||||
'add_bridge',
|
'add_bridge',
|
||||||
'add_bridge_port',
|
'add_bridge_port',
|
||||||
'add_ovsbridge_linuxbridge',
|
'add_ovsbridge_linuxbridge',
|
||||||
|
'get_bridges_and_ports_map',
|
||||||
'is_linuxbridge_interface',
|
'is_linuxbridge_interface',
|
||||||
'headers_package',
|
'headers_package',
|
||||||
'full_restart',
|
'full_restart',
|
||||||
|
@ -297,11 +298,13 @@ class TestNeutronUtils(CharmTestCase):
|
||||||
DummyExternalPortContext(return_value={'ext_port': 'eth0'})
|
DummyExternalPortContext(return_value={'ext_port': 'eth0'})
|
||||||
neutron_utils.configure_ovs()
|
neutron_utils.configure_ovs()
|
||||||
self.add_bridge.assert_has_calls([
|
self.add_bridge.assert_has_calls([
|
||||||
call('br-int'),
|
call('br-int', brdata=ANY),
|
||||||
call('br-ex'),
|
call('br-ex', brdata=ANY),
|
||||||
call('br-data')
|
call('br-data', brdata=ANY)
|
||||||
])
|
])
|
||||||
self.add_bridge_port.assert_called_with('br-ex', 'eth0')
|
self.add_bridge_port.assert_called_with(
|
||||||
|
'br-ex', 'eth0', ifdata=ANY, portdata=ANY
|
||||||
|
)
|
||||||
|
|
||||||
@patch('charmhelpers.contrib.openstack.context.list_nics',
|
@patch('charmhelpers.contrib.openstack.context.list_nics',
|
||||||
return_value=['eth0', 'eth0.100', 'eth0.200'])
|
return_value=['eth0', 'eth0.100', 'eth0.200'])
|
||||||
|
@ -318,11 +321,12 @@ class TestNeutronUtils(CharmTestCase):
|
||||||
self.test_config.set('data-port', 'eth0')
|
self.test_config.set('data-port', 'eth0')
|
||||||
neutron_utils.configure_ovs()
|
neutron_utils.configure_ovs()
|
||||||
self.add_bridge.assert_has_calls([
|
self.add_bridge.assert_has_calls([
|
||||||
call('br-int'),
|
call('br-int', brdata=ANY),
|
||||||
call('br-ex'),
|
call('br-ex', brdata=ANY),
|
||||||
call('br-data')
|
call('br-data', brdata=ANY)
|
||||||
])
|
])
|
||||||
calls = [call('br-data', 'eth0', promisc=True)]
|
calls = [call('br-data', 'eth0', promisc=True, ifdata=ANY,
|
||||||
|
portdata=ANY)]
|
||||||
self.add_bridge_port.assert_has_calls(calls)
|
self.add_bridge_port.assert_has_calls(calls)
|
||||||
|
|
||||||
# Now test with bridge:port format and bogus bridge
|
# Now test with bridge:port format and bogus bridge
|
||||||
|
@ -331,9 +335,9 @@ class TestNeutronUtils(CharmTestCase):
|
||||||
self.add_bridge_port.reset_mock()
|
self.add_bridge_port.reset_mock()
|
||||||
neutron_utils.configure_ovs()
|
neutron_utils.configure_ovs()
|
||||||
self.add_bridge.assert_has_calls([
|
self.add_bridge.assert_has_calls([
|
||||||
call('br-int'),
|
call('br-int', brdata=ANY),
|
||||||
call('br-ex'),
|
call('br-ex', brdata=ANY),
|
||||||
call('br-data')
|
call('br-data', brdata=ANY)
|
||||||
])
|
])
|
||||||
# Not called since we have a bogus bridge in data-ports
|
# Not called since we have a bogus bridge in data-ports
|
||||||
self.assertFalse(self.add_bridge_port.called)
|
self.assertFalse(self.add_bridge_port.called)
|
||||||
|
@ -345,12 +349,13 @@ class TestNeutronUtils(CharmTestCase):
|
||||||
self.add_bridge_port.reset_mock()
|
self.add_bridge_port.reset_mock()
|
||||||
neutron_utils.configure_ovs()
|
neutron_utils.configure_ovs()
|
||||||
self.add_bridge.assert_has_calls([
|
self.add_bridge.assert_has_calls([
|
||||||
call('br-int'),
|
call('br-int', brdata=ANY),
|
||||||
call('br-ex'),
|
call('br-ex', brdata=ANY),
|
||||||
call('br1')
|
call('br1', brdata=ANY)
|
||||||
])
|
])
|
||||||
calls = [call('br1', 'eth0.100', promisc=True),
|
calls = [
|
||||||
call('br1', 'eth0.200', promisc=True)]
|
call('br1', 'eth0.100', promisc=True, ifdata=ANY, portdata=ANY),
|
||||||
|
call('br1', 'eth0.200', promisc=True, ifdata=ANY, portdata=ANY)]
|
||||||
self.add_bridge_port.assert_has_calls(calls, any_order=True)
|
self.add_bridge_port.assert_has_calls(calls, any_order=True)
|
||||||
|
|
||||||
@patch('charmhelpers.contrib.openstack.context.list_nics',
|
@patch('charmhelpers.contrib.openstack.context.list_nics',
|
||||||
|
@ -367,12 +372,23 @@ class TestNeutronUtils(CharmTestCase):
|
||||||
# assumed)
|
# assumed)
|
||||||
self.test_config.set('data-port', 'br-eth0')
|
self.test_config.set('data-port', 'br-eth0')
|
||||||
neutron_utils.configure_ovs()
|
neutron_utils.configure_ovs()
|
||||||
|
|
||||||
|
# Also check that new bridges and ports are marked as managed by us:
|
||||||
|
expected_brdata = {
|
||||||
|
'external-ids': {'charm-neutron-gateway': 'managed'},
|
||||||
|
}
|
||||||
|
expected_ifdata = {
|
||||||
|
'external-ids': {'charm-neutron-gateway': 'br-data'},
|
||||||
|
}
|
||||||
|
expected_portdata = expected_ifdata
|
||||||
|
|
||||||
self.add_bridge.assert_has_calls([
|
self.add_bridge.assert_has_calls([
|
||||||
call('br-int'),
|
call('br-int', brdata=expected_brdata),
|
||||||
call('br-ex'),
|
call('br-ex', brdata=expected_brdata),
|
||||||
call('br-data')
|
call('br-data', brdata=expected_brdata)
|
||||||
])
|
])
|
||||||
calls = [call('br-data', 'br-eth0')]
|
calls = [call('br-data', 'br-eth0', ifdata=expected_ifdata,
|
||||||
|
portdata=expected_portdata)]
|
||||||
self.add_ovsbridge_linuxbridge.assert_has_calls(calls)
|
self.add_ovsbridge_linuxbridge.assert_has_calls(calls)
|
||||||
|
|
||||||
@patch('charmhelpers.contrib.openstack.context.config')
|
@patch('charmhelpers.contrib.openstack.context.config')
|
||||||
|
@ -388,6 +404,36 @@ class TestNeutronUtils(CharmTestCase):
|
||||||
call('br-data', '127.0.0.1:80'),
|
call('br-data', '127.0.0.1:80'),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@patch.object(neutron_utils, 'DataPortContext')
|
||||||
|
@patch('charmhelpers.contrib.openstack.context.config')
|
||||||
|
def test_configure_ovs_ensure_ext_port_overriden(
|
||||||
|
self, mock_config, mock_data_port_context):
|
||||||
|
mock_config.side_effect = self.test_config.get
|
||||||
|
self.config.side_effect = self.test_config.get
|
||||||
|
self.test_config.set('plugin', 'ovs')
|
||||||
|
self.get_bridges_and_ports_map.return_value = {
|
||||||
|
'br-data': ['p4', 'p5'],
|
||||||
|
'br1': ['p6'],
|
||||||
|
}
|
||||||
|
self.test_config.set(
|
||||||
|
'data-port',
|
||||||
|
'br-data:p4 br-data:p5 br1:p6')
|
||||||
|
self.test_config.set('bridge-mappings', 'net0:br-data net1:br1')
|
||||||
|
self.test_config.set('ext-port', None)
|
||||||
|
self.ExternalPortContext.return_value = \
|
||||||
|
DummyExternalPortContext(return_value={'ext_port': 'eth0'})
|
||||||
|
mock_data_port_context.return_value = \
|
||||||
|
DummyDataPortContext(return_value={
|
||||||
|
'p4': 'br-data',
|
||||||
|
'p5': 'br-data',
|
||||||
|
'p6': 'br1',
|
||||||
|
})
|
||||||
|
self.is_linuxbridge_interface.return_value = False
|
||||||
|
neutron_utils.configure_ovs()
|
||||||
|
# Ensure that ext-port was ignored.
|
||||||
|
self.assertNotIn(call('br-ex', 'eth0', ifdata=ANY, portdata=ANY),
|
||||||
|
self.add_bridge_port.call_args_list)
|
||||||
|
|
||||||
@patch.object(neutron_utils, 'register_configs')
|
@patch.object(neutron_utils, 'register_configs')
|
||||||
@patch('charmhelpers.contrib.openstack.templating.OSConfigRenderer')
|
@patch('charmhelpers.contrib.openstack.templating.OSConfigRenderer')
|
||||||
def test_do_openstack_upgrade(self, mock_renderer,
|
def test_do_openstack_upgrade(self, mock_renderer,
|
||||||
|
@ -1006,6 +1052,15 @@ class DummyExternalPortContext():
|
||||||
return self.return_value
|
return self.return_value
|
||||||
|
|
||||||
|
|
||||||
|
class DummyDataPortContext():
|
||||||
|
|
||||||
|
def __init__(self, return_value):
|
||||||
|
self.return_value = return_value
|
||||||
|
|
||||||
|
def __call__(self):
|
||||||
|
return self.return_value
|
||||||
|
|
||||||
|
|
||||||
cluster1 = ['cluster1-machine1.internal']
|
cluster1 = ['cluster1-machine1.internal']
|
||||||
cluster2 = ['cluster2-machine1.internal', 'cluster2-machine2.internal'
|
cluster2 = ['cluster2-machine1.internal', 'cluster2-machine2.internal'
|
||||||
'cluster2-machine3.internal']
|
'cluster2-machine3.internal']
|
||||||
|
@ -1035,7 +1090,7 @@ class TestNeutronAgentReallocation(CharmTestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
@patch.object(neutron_utils, 'get_optional_interfaces')
|
@patch.object(neutron_utils, 'get_optional_interfaces')
|
||||||
@patch.object(neutron_utils, 'check_optional_relations')
|
@patch.object(neutron_utils, 'sequence_functions')
|
||||||
@patch.object(neutron_utils, 'REQUIRED_INTERFACES')
|
@patch.object(neutron_utils, 'REQUIRED_INTERFACES')
|
||||||
@patch.object(neutron_utils, 'services')
|
@patch.object(neutron_utils, 'services')
|
||||||
@patch.object(neutron_utils, 'make_assess_status_func')
|
@patch.object(neutron_utils, 'make_assess_status_func')
|
||||||
|
@ -1043,17 +1098,21 @@ class TestNeutronAgentReallocation(CharmTestCase):
|
||||||
make_assess_status_func,
|
make_assess_status_func,
|
||||||
services,
|
services,
|
||||||
REQUIRED_INTERFACES,
|
REQUIRED_INTERFACES,
|
||||||
check_optional_relations,
|
sequence_functions,
|
||||||
get_optional_interfaces):
|
get_optional_interfaces):
|
||||||
services.return_value = ['s1']
|
services.return_value = ['s1']
|
||||||
REQUIRED_INTERFACES.copy.return_value = {'int': ['test 1']}
|
REQUIRED_INTERFACES.copy.return_value = {'int': ['test 1']}
|
||||||
get_optional_interfaces.return_value = {'opt': ['test 2']}
|
get_optional_interfaces.return_value = {'opt': ['test 2']}
|
||||||
|
sequence_functions.return_value = 'sequence_return'
|
||||||
neutron_utils.assess_status_func('test-config')
|
neutron_utils.assess_status_func('test-config')
|
||||||
# ports=None whilst port checks are disabled.
|
# ports=None whilst port checks are disabled.
|
||||||
make_assess_status_func.assert_called_once_with(
|
make_assess_status_func.assert_called_once_with(
|
||||||
'test-config',
|
'test-config',
|
||||||
{'int': ['test 1'], 'opt': ['test 2']},
|
{'int': ['test 1'], 'opt': ['test 2']},
|
||||||
charm_func=check_optional_relations, services=['s1'], ports=None)
|
charm_func='sequence_return', services=['s1'], ports=None)
|
||||||
|
sequence_functions.assert_called_once_with(
|
||||||
|
neutron_utils.check_optional_relations,
|
||||||
|
neutron_utils.check_ext_port_data_port_config)
|
||||||
|
|
||||||
def test_pause_unit_helper(self):
|
def test_pause_unit_helper(self):
|
||||||
with patch.object(neutron_utils, '_pause_resume_helper') as prh:
|
with patch.object(neutron_utils, '_pause_resume_helper') as prh:
|
||||||
|
|
Loading…
Reference in New Issue