From dd1906f61fff8493e91fa771217eb4e8cdea375b Mon Sep 17 00:00:00 2001 From: Dan Sneddon Date: Wed, 27 Mar 2019 14:57:09 -0700 Subject: [PATCH] Add ovs_options and ovs_extra parameters to VLAN object This patch adds the ovs_options and ovs_extra parameters to the VLAN object, and OVS_OPTIONS/OVS_EXTRA to the OVS VLAN ifcfg. An OVS VLAN is an internal port on the bridge, and when ifup is run the ovs-vsctl command will be called with the commands in OVS_OPTIONS and the list of commands in OVS_EXTRA. This makes OVS VLANs work the same as other OVS object types. These settings are ignored for VLANs not on an OVS bridge. Change-Id: Ie1db61eea48e3426a59ae02b13dd8ab8ef85e851 Closes-bug: 1821816 --- etc/os-net-config/samples/bridge_vlan.json | 4 ++++ etc/os-net-config/samples/bridge_vlan.yaml | 3 +++ os_net_config/impl_ifcfg.py | 4 ++++ os_net_config/objects.py | 13 +++++++++++-- os_net_config/schema.yaml | 6 +++++- os_net_config/tests/test_impl_ifcfg.py | 12 ++++++++++++ os_net_config/tests/test_objects.py | 8 ++++++++ 7 files changed, 47 insertions(+), 3 deletions(-) diff --git a/etc/os-net-config/samples/bridge_vlan.json b/etc/os-net-config/samples/bridge_vlan.json index 244c89ab..5d84f822 100644 --- a/etc/os-net-config/samples/bridge_vlan.json +++ b/etc/os-net-config/samples/bridge_vlan.json @@ -11,6 +11,10 @@ { "type": "vlan", "vlan_id": 16, + "ovs_options": "mac=00:11:22:33:44:55", + "ovs_extra": [ + "foo=bar" + ], "addresses": [{ "ip_netmask": "192.0.2.1/24" }] diff --git a/etc/os-net-config/samples/bridge_vlan.yaml b/etc/os-net-config/samples/bridge_vlan.yaml index fdf90418..46d2069a 100644 --- a/etc/os-net-config/samples/bridge_vlan.yaml +++ b/etc/os-net-config/samples/bridge_vlan.yaml @@ -10,6 +10,9 @@ network_config: - type: vlan vlan_id: 16 + ovs_options: "mac=00:11:22:33:44:55" + ovs_extra: + - "foo=bar" addresses: - ip_netmask: 192.0.2.1/24 diff --git a/os_net_config/impl_ifcfg.py b/os_net_config/impl_ifcfg.py index f655a3eb..1fca36cb 100644 --- a/os_net_config/impl_ifcfg.py +++ b/os_net_config/impl_ifcfg.py @@ -364,6 +364,10 @@ class IfcfgNetConfig(os_net_config.NetConfig): data += "PHYSDEV=%s\n" % base_opt.device elif base_opt.linux_bond_name: data += "PHYSDEV=%s\n" % base_opt.linux_bond_name + else: + if base_opt.ovs_options: + data += "OVS_OPTIONS=\"%s\"\n" % base_opt.ovs_options + ovs_extra.extend(base_opt.ovs_extra) elif isinstance(base_opt, objects.IvsInterface): data += "TYPE=IVSIntPort\n" elif isinstance(base_opt, objects.NfvswitchInternal): diff --git a/os_net_config/objects.py b/os_net_config/objects.py index 179b8099..4e9f6158 100644 --- a/os_net_config/objects.py +++ b/os_net_config/objects.py @@ -492,7 +492,8 @@ class Vlan(_BaseOpts): addresses=None, routes=None, rules=None, mtu=None, primary=False, nic_mapping=None, persist_mapping=False, defroute=True, dhclient_args=None, dns_servers=None, - nm_controlled=False, onboot=True, domain=None): + nm_controlled=False, onboot=True, domain=None, + ovs_options=None, ovs_extra=None): addresses = addresses or [] routes = routes or [] rules = rules or [] @@ -503,6 +504,9 @@ class Vlan(_BaseOpts): persist_mapping, defroute, dhclient_args, dns_servers, nm_controlled, onboot, domain) self.vlan_id = int(vlan_id) + self.ovs_options = ovs_options + ovs_extra = ovs_extra or [] + self.ovs_extra = format_ovs_extra(self, ovs_extra) mapped_nic_names = mapped_nics(nic_mapping) if device in mapped_nic_names: self.device = mapped_nic_names[device] @@ -515,7 +519,12 @@ class Vlan(_BaseOpts): device = json.get('device') vlan_id = _get_required_field(json, 'vlan_id', 'Vlan') opts = _BaseOpts.base_opts_from_json(json) - return Vlan(device, vlan_id, *opts) + ovs_options = json.get('ovs_options') + ovs_extra = json.get('ovs_extra', []) + if not isinstance(ovs_extra, list): + ovs_extra = [ovs_extra] + return Vlan(device, vlan_id, *opts, ovs_options=ovs_options, + ovs_extra=ovs_extra) class IvsInterface(_BaseOpts): diff --git a/os_net_config/schema.yaml b/os_net_config/schema.yaml index 952cea8b..95c1708c 100644 --- a/os_net_config/schema.yaml +++ b/os_net_config/schema.yaml @@ -197,7 +197,7 @@ definitions: ovs_options_string: type: string - pattern: "^((?:[a-zA-Z][a-zA-Z0-9: _-]*)=(?:[a-zA-Z0-9._-]+)[ ]*)+$" + pattern: "^((?:[a-zA-Z][a-zA-Z0-9: _-]*)=(?:[a-zA-Z0-9:._-]+)[ ]*)+$" ovs_options_string_or_param: oneOf: - $ref: "#/definitions/ovs_options_string" @@ -459,6 +459,10 @@ definitions: $ref: "#/definitions/bool_or_param" domain: $ref: "#/definitions/domain_name_string" + ovs_options: + $ref: "#/definitions/ovs_options_string_or_param" + ovs_extra: + $ref: "#/definitions/ovs_extra_or_param" required: - type - vlan_id diff --git a/os_net_config/tests/test_impl_ifcfg.py b/os_net_config/tests/test_impl_ifcfg.py index dc8982f0..f3fdc7fc 100644 --- a/os_net_config/tests/test_impl_ifcfg.py +++ b/os_net_config/tests/test_impl_ifcfg.py @@ -335,6 +335,10 @@ _VLAN_NO_IP = _BASE_VLAN + "BOOTPROTO=none\n" _VLAN_OVS = _BASE_VLAN_OVS + "DEVICETYPE=ovs\nBOOTPROTO=none\n" +_VLAN_OVS_EXTRA = _BASE_VLAN_OVS + "OVS_OPTIONS=\"foo\"\nDEVICETYPE=ovs\n" + \ + "BOOTPROTO=none\nOVS_EXTRA=\"bar -- baz\"\n" + + _VLAN_OVS_BRIDGE = _BASE_VLAN_OVS + """DEVICETYPE=ovs TYPE=OVSIntPort OVS_BRIDGE=br-ctlplane @@ -1055,6 +1059,14 @@ class TestIfcfgNetConfig(base.TestCase): self.provider.add_vlan(vlan) self.assertEqual(_VLAN_OVS, self.get_vlan_config('vlan5')) + def test_add_vlan_ovs_options(self): + vlan = objects.Vlan('em1', 5) + vlan.ovs_port = True + vlan.ovs_options = 'foo' + vlan.ovs_extra = ['bar', 'baz'] + self.provider.add_vlan(vlan) + self.assertEqual(_VLAN_OVS_EXTRA, self.get_vlan_config('vlan5')) + def test_add_vlan_mtu_1500(self): vlan = objects.Vlan('em1', 5, mtu=1500) self.provider.add_vlan(vlan) diff --git a/os_net_config/tests/test_objects.py b/os_net_config/tests/test_objects.py index 8a056dd4..383dad10 100644 --- a/os_net_config/tests/test_objects.py +++ b/os_net_config/tests/test_objects.py @@ -381,6 +381,14 @@ class TestVlan(base.TestCase): self.assertEqual(16, vlan.vlan_id) self.assertTrue(vlan.use_dhcp) + def test_from_json_ovs_options_extra(self): + data = '{"type": "vlan", "device": "em1", "vlan_id": 16,' \ + '"use_dhcp": true, "ovs_options": "foo",' \ + '"ovs_extra": ["bar","baz"]}' + vlan = objects.object_from_json(json.loads(data)) + self.assertEqual("foo", vlan.ovs_options) + self.assertEqual(["bar", "baz"], vlan.ovs_extra) + class TestBridge(base.TestCase):