aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Slagle <jslagle@redhat.com>2016-06-14 11:40:55 -0400
committerJames Slagle <jslagle@redhat.com>2016-06-14 17:50:56 -0400
commit789bd1ea089314b49db02ddd517809a82c380cf1 (patch)
tree828cbac57e63232bedb2910609835a5f3eed0ef9
parent4d88e7f349f725704c707093c8b44d7409eae481 (diff)
Add support for OVS patch ports
OVS patch ports are used to connect two OVS bridges so traffic can flow between them. This is generally useful for various cases. Specifically it could be used to connect the bridges created by TripleO networking configurations (br-ex, etc) to the bridge created by the multinode networking setup in infra's nodepool (br_pub). This allows the nodes in a multinode deployment to have connectivity across private subnets where such traffic is typically firewalled off in public clouds. Change-Id: I11404106cb3f53734f6fc9a35c22f905a0770245
-rw-r--r--etc/os-net-config/samples/ovs_patch_port.json37
-rw-r--r--etc/os-net-config/samples/ovs_patch_port.yaml23
-rw-r--r--os_net_config/__init__.py9
-rw-r--r--os_net_config/impl_ifcfg.py17
-rw-r--r--os_net_config/objects.py37
-rw-r--r--os_net_config/tests/test_impl_ifcfg.py21
-rw-r--r--os_net_config/tests/test_objects.py16
7 files changed, 160 insertions, 0 deletions
diff --git a/etc/os-net-config/samples/ovs_patch_port.json b/etc/os-net-config/samples/ovs_patch_port.json
new file mode 100644
index 0000000..d457371
--- /dev/null
+++ b/etc/os-net-config/samples/ovs_patch_port.json
@@ -0,0 +1,37 @@
+{
+ "network_config": [
+ {
+ "name": "br-ctlplane",
+ "type": "ovs_bridge",
+ "members": [
+ {
+ "mtu": 1500,
+ "primary": "true",
+ "name": "eth1",
+ "type": "interface"
+ }
+ ],
+ "ovs_extra": [
+ "br-set-external-id br-ctlplane bridge-id br-ctlplane"
+ ],
+ "mtu": 1500,
+ "addresses": [
+ {
+ "ip_netmask": "192.0.2.1/24"
+ }
+ ]
+ },
+ {
+ "name": "br_pub-patch",
+ "type": "ovs_patch_port",
+ "bridge_name": "br-ctlplane",
+ "peer": "br-ctlplane-patch"
+ },
+ {
+ "name": "br-ctlplane-patch",
+ "type": "ovs_patch_port",
+ "bridge_name": "br_pub",
+ "peer": "br_pub-patch"
+ }
+ ]
+}
diff --git a/etc/os-net-config/samples/ovs_patch_port.yaml b/etc/os-net-config/samples/ovs_patch_port.yaml
new file mode 100644
index 0000000..91858be
--- /dev/null
+++ b/etc/os-net-config/samples/ovs_patch_port.yaml
@@ -0,0 +1,23 @@
+network_config:
+ -
+ type: ovs_bridge
+ name: br-ctlplane
+ mtu: 1500
+ members:
+ -
+ type: interface
+ name: eth1
+ # force the MAC address of the bridge to this interface
+ primary: true
+ mtu: 1500
+ ovs_extra: "br-set-external-id br-ctlplane bridge-id br-ctlplane"
+ -
+ type: ovs_patch_port
+ name: br_pub-patch
+ bridge_name: br-ctlplane
+ peer: br-ctlplane-patch
+ -
+ type: ovs_patch_port
+ name: br-ctlplane-patch
+ bridge_name: br_pub
+ peer: br_pub-patch
diff --git a/os_net_config/__init__.py b/os_net_config/__init__.py
index 700a09d..88e8900 100644
--- a/os_net_config/__init__.py
+++ b/os_net_config/__init__.py
@@ -73,6 +73,8 @@ class NetConfig(object):
self.add_object(member)
elif isinstance(obj, objects.OvsTunnel):
self.add_ovs_tunnel(obj)
+ elif isinstance(obj, objects.OvsPatchPort):
+ self.add_ovs_patch_port(obj)
def add_interface(self, interface):
"""Add an Interface object to the net config object.
@@ -130,6 +132,13 @@ class NetConfig(object):
"""
raise NotImplemented("add_ovs_tunnel is not implemented.")
+ def add_ovs_patch_port(self, ovs_patch_port):
+ """Add a OvsPatchPort object to the net config object.
+
+ :param ovs_patch_port: The OvsPatchPort object to add.
+ """
+ raise NotImplemented("add_ovs_patch_port is not implemented.")
+
def apply(self, cleanup=False):
"""Apply the network configuration.
diff --git a/os_net_config/impl_ifcfg.py b/os_net_config/impl_ifcfg.py
index f6b4617..fbd1c3a 100644
--- a/os_net_config/impl_ifcfg.py
+++ b/os_net_config/impl_ifcfg.py
@@ -185,11 +185,18 @@ class IfcfgNetConfig(os_net_config.NetConfig):
data += "OVS_TUNNEL_TYPE=%s\n" % base_opt.tunnel_type
data += "OVS_TUNNEL_OPTIONS=\"%s\"\n" % \
' '.join(base_opt.ovs_options)
+ elif isinstance(base_opt, objects.OvsPatchPort):
+ ovs_extra.extend(base_opt.ovs_extra)
+ data += "DEVICETYPE=ovs\n"
+ data += "TYPE=OVSPatchPort\n"
+ data += "OVS_BRIDGE=%s\n" % base_opt.bridge_name
+ data += "OVS_PATCH_PEER=%s\n" % base_opt.peer
else:
if base_opt.use_dhcp:
data += "BOOTPROTO=dhcp\n"
elif not base_opt.addresses:
data += "BOOTPROTO=none\n"
+
if base_opt.mtu:
data += "MTU=%i\n" % base_opt.mtu
if base_opt.use_dhcpv6 or base_opt.v6_addresses():
@@ -374,6 +381,16 @@ class IfcfgNetConfig(os_net_config.NetConfig):
logger.debug('ovs tunnel data: %s' % data)
self.interface_data[tunnel.name] = data
+ def add_ovs_patch_port(self, ovs_patch_port):
+ """Add a OvsPatchPort object to the net config object.
+
+ :param ovs_patch_port: The OvsPatchPort object to add.
+ """
+ logger.info('adding ovs patch port: %s' % ovs_patch_port.name)
+ data = self._add_common(ovs_patch_port)
+ logger.debug('ovs patch port data: %s' % data)
+ self.interface_data[ovs_patch_port.name] = data
+
def generate_ivs_config(self, ivs_uplinks, ivs_interfaces):
"""Generate configuration content for ivs."""
diff --git a/os_net_config/objects.py b/os_net_config/objects.py
index 2958f84..9815832 100644
--- a/os_net_config/objects.py
+++ b/os_net_config/objects.py
@@ -50,6 +50,8 @@ def object_from_json(json):
return IvsInterface.from_json(json)
elif obj_type == "ovs_tunnel":
return OvsTunnel.from_json(json)
+ elif obj_type == "ovs_patch_port":
+ return OvsPatchPort.from_json(json)
def _get_required_field(json, name, object_name):
@@ -652,3 +654,38 @@ class OvsTunnel(_BaseOpts):
opts = _BaseOpts.base_opts_from_json(json)
return OvsTunnel(name, *opts, tunnel_type=tunnel_type,
ovs_options=ovs_options, ovs_extra=ovs_extra)
+
+
+class OvsPatchPort(_BaseOpts):
+ """Base class for OVS Patch Ports."""
+
+ def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=None,
+ routes=None, mtu=None, primary=False, nic_mapping=None,
+ persist_mapping=False, defroute=True, dhclient_args=None,
+ dns_servers=None, bridge_name=None, peer=None,
+ ovs_options=None, ovs_extra=None):
+ addresses = addresses or []
+ routes = routes or []
+ ovs_extra = ovs_extra or []
+ dns_servers = dns_servers or []
+ super(OvsPatchPort, self).__init__(name, use_dhcp, use_dhcpv6,
+ addresses, routes, mtu, primary,
+ nic_mapping, persist_mapping,
+ defroute, dhclient_args,
+ dns_servers)
+ self.bridge_name = bridge_name
+ self.peer = peer
+ self.ovs_options = ovs_options or []
+ self.ovs_extra = ovs_extra or []
+
+ @staticmethod
+ def from_json(json):
+ name = _get_required_field(json, 'name', 'OvsPatchPort')
+ bridge_name = _get_required_field(json, 'bridge_name', 'OvsPatchPort')
+ peer = _get_required_field(json, 'peer', 'OvsPatchPort')
+ ovs_options = json.get('ovs_options', [])
+ ovs_options = ['options:%s' % opt for opt in ovs_options]
+ ovs_extra = json.get('ovs_extra', [])
+ opts = _BaseOpts.base_opts_from_json(json)
+ return OvsPatchPort(name, *opts, bridge_name=bridge_name, peer=peer,
+ ovs_options=ovs_options, ovs_extra=ovs_extra)
diff --git a/os_net_config/tests/test_impl_ifcfg.py b/os_net_config/tests/test_impl_ifcfg.py
index f4701a0..71ad9ae 100644
--- a/os_net_config/tests/test_impl_ifcfg.py
+++ b/os_net_config/tests/test_impl_ifcfg.py
@@ -258,6 +258,18 @@ NETMASK=255.255.255.0
_IVS_CONFIG = ('DAEMON_ARGS=\"--hitless --certificate /etc/ivs '
'--inband-vlan 4092 -u em1 --internal-port=storage5\"')
+_OVS_IFCFG_PATCH_PORT = """# This file is autogenerated by os-net-config
+DEVICE=br-pub-patch
+ONBOOT=yes
+HOTPLUG=no
+NM_CONTROLLED=no
+PEERDNS=no
+DEVICETYPE=ovs
+TYPE=OVSPatchPort
+OVS_BRIDGE=br-ex
+OVS_PATCH_PEER=br-ex-patch
+"""
+
class TestIfcfgNetConfig(base.TestCase):
@@ -309,6 +321,15 @@ class TestIfcfgNetConfig(base.TestCase):
self.provider.add_interface(interface)
self.assertEqual(_OVS_IFCFG_TUNNEL, self.get_interface_config('tun0'))
+ def test_add_ovs_patch_port(self):
+ patch_port = objects.OvsPatchPort("br-pub-patch")
+ patch_port.type = 'ovs_patch_port'
+ patch_port.bridge_name = 'br-ex'
+ patch_port.peer = 'br-ex-patch'
+ self.provider.add_interface(patch_port)
+ self.assertEqual(_OVS_IFCFG_PATCH_PORT,
+ self.get_interface_config('br-pub-patch'))
+
def test_add_interface_with_v4(self):
v4_addr = objects.Address('192.168.1.2/24')
interface = objects.Interface('em1', addresses=[v4_addr])
diff --git a/os_net_config/tests/test_objects.py b/os_net_config/tests/test_objects.py
index 3367df0..7d8d3b3 100644
--- a/os_net_config/tests/test_objects.py
+++ b/os_net_config/tests/test_objects.py
@@ -548,6 +548,22 @@ class TestOvsTunnel(base.TestCase):
tun0.ovs_extra)
+class TestOvsPatchPort(base.TestCase):
+
+ def test_from_json(self):
+ data = """{
+"type": "ovs_patch_port",
+"name": "br-pub-patch",
+"bridge_name": "br-ex",
+"peer": "br-ex-patch"
+}
+"""
+ patch_port = objects.object_from_json(json.loads(data))
+ self.assertEqual("br-pub-patch", patch_port.name)
+ self.assertEqual("br-ex", patch_port.bridge_name)
+ self.assertEqual("br-ex-patch", patch_port.peer)
+
+
class TestNumberedNicsMapping(base.TestCase):
# We want to test the function, not the dummy..