From f624d13433089be87db0fb8e5eaeb57bd974d034 Mon Sep 17 00:00:00 2001 From: "Gareth J. Greenaway" Date: Wed, 18 Sep 2019 16:28:29 -0700 Subject: [PATCH] Porting PR #50622 to 2019.2.1 --- salt/modules/openvswitch.py | 5 +++- salt/serializers/yaml.py | 5 ++++ salt/serializers/yamlex.py | 5 ++++ salt/states/openvswitch_port.py | 34 +++++++++++++++++++--- tests/unit/states/test_openvswitch_port.py | 2 ++ 5 files changed, 46 insertions(+), 5 deletions(-) diff --git a/salt/modules/openvswitch.py b/salt/modules/openvswitch.py index 9ad191694333..e4f69542a9e5 100644 --- a/salt/modules/openvswitch.py +++ b/salt/modules/openvswitch.py @@ -184,7 +184,7 @@ def bridge_delete(br, if_exists=True): return _retcode_to_bool(retcode) -def port_add(br, port, may_exist=False): +def port_add(br, port, may_exist=False, internal=False): ''' Creates on bridge a new port named port. @@ -195,6 +195,7 @@ def port_add(br, port, may_exist=False): br: A string - bridge name port: A string - port name may_exist: Bool, if False - attempting to create a port that exists returns False. + internal: A boolean to create an internal interface if one does not exist. .. versionadded:: 2016.3.0 @@ -205,6 +206,8 @@ def port_add(br, port, may_exist=False): ''' param_may_exist = _param_may_exist(may_exist) cmd = 'ovs-vsctl {2}add-port {0} {1}'.format(br, port, param_may_exist) + if internal: + cmd += ' -- set interface {0} type=internal'.format(port) result = __salt__['cmd.run_all'](cmd) retcode = result['retcode'] return _retcode_to_bool(retcode) diff --git a/salt/serializers/yaml.py b/salt/serializers/yaml.py index 2154e5dcabfb..e0fbad9d58be 100644 --- a/salt/serializers/yaml.py +++ b/salt/serializers/yaml.py @@ -20,6 +20,7 @@ from salt.serializers import DeserializationError, SerializationError from salt.ext import six from salt.utils.odict import OrderedDict +from salt.utils.thread_local_proxy import ThreadLocalProxy __all__ = ['deserialize', 'serialize', 'available'] @@ -140,3 +141,7 @@ class Dumper(BaseDumper): # pylint: disable=W0232 Dumper.add_multi_representer(datetime.datetime, Dumper.represent_datetime) Dumper.add_multi_representer(None, Dumper.represent_undefined) Dumper.add_multi_representer(OrderedDict, Dumper.represent_dict) +Dumper.add_representer( + ThreadLocalProxy, + lambda dumper, proxy: + dumper.represent_data(ThreadLocalProxy.unproxy(proxy))) diff --git a/salt/serializers/yamlex.py b/salt/serializers/yamlex.py index e42634f58044..ee4e6b425fb5 100644 --- a/salt/serializers/yamlex.py +++ b/salt/serializers/yamlex.py @@ -113,6 +113,7 @@ from salt.serializers import DeserializationError, SerializationError from salt.utils.aggregation import aggregate, Map, Sequence from salt.utils.odict import OrderedDict +from salt.utils.thread_local_proxy import ThreadLocalProxy # Import 3rd-party libs import yaml @@ -418,6 +419,10 @@ def represent_odict(self, data): Dumper.add_multi_representer(datetime.date, Dumper.represent_date) Dumper.add_multi_representer(datetime.datetime, Dumper.represent_datetime) Dumper.add_multi_representer(None, Dumper.represent_undefined) +Dumper.add_representer( + ThreadLocalProxy, + lambda dumper, proxy: + dumper.represent_data(ThreadLocalProxy.unproxy(proxy))) def merge_recursive(obj_a, obj_b, level=False): diff --git a/salt/states/openvswitch_port.py b/salt/states/openvswitch_port.py index 043a9d2f030a..6004c83355a0 100644 --- a/salt/states/openvswitch_port.py +++ b/salt/states/openvswitch_port.py @@ -56,6 +56,9 @@ def present(name, bridge, tunnel_type=None, id=None, remote=None, dst_port=None, 'new': 'Created port {1} on bridge {0}.'.format(bridge, name), } } + comments['comment_port_internal'] = 'Port {0} already exists, but interface type has been changed to internal.'.format(name) + comments['changes_port_internal'] = {'internal': {'old': False, 'new': True}} + comments['comment_port_internal_not_changed'] = 'Port {0} already exists, but the interface type could not be changed to internal.'.format(name) if tunnel_type: comments['comment_invalid_ip'] = 'Remote is not valid ip address.' @@ -181,7 +184,13 @@ def _check_vxlan(): else: if name in port_list: ret['result'] = True - ret['comment'] = comments['comment_port_exists'] + current_type = __salt__['openvswitch.interface_get_type']( + name) + # The interface type is returned as a single-element list. + if internal and (current_type != ['internal']): + ret['comment'] = comments['comment_port_internal'] + else: + ret['comment'] = comments['comment_port_exists'] else: ret['result'] = None ret['comment'] = comments['comment_port_created'] @@ -227,10 +236,27 @@ def _check_vxlan(): ret['comment'] = comments['comment_gre_notcreated'] else: if name in port_list: - ret['result'] = True - ret['comment'] = comments['comment_port_exists'] + current_type = __salt__['openvswitch.interface_get_type'](name) + # The interface type is returned as a single-element list. + if internal and (current_type != ['internal']): + # We do not have a direct way of only setting the interface + # type to internal, so we add the port with the --may-exist + # option. + port_add = __salt__['openvswitch.port_add']( + bridge, name, may_exist=True, internal=internal) + if port_add: + ret['result'] = True + ret['comment'] = comments['comment_port_internal'] + ret['changes'] = comments['changes_port_internal'] + else: + ret['result'] = False + ret['comment'] = comments[ + 'comment_port_internal_not_changed'] + else: + ret['result'] = True + ret['comment'] = comments['comment_port_exists'] else: - port_add = __salt__['openvswitch.port_add'](bridge, name) + port_add = __salt__['openvswitch.port_add'](bridge, name, internal=internal) if port_add: ret['result'] = True ret['comment'] = comments['comment_port_created'] diff --git a/tests/unit/states/test_openvswitch_port.py b/tests/unit/states/test_openvswitch_port.py index 046b48ca9649..e9f24ece4057 100644 --- a/tests/unit/states/test_openvswitch_port.py +++ b/tests/unit/states/test_openvswitch_port.py @@ -42,6 +42,7 @@ def test_present(self): mock_n = MagicMock(return_value=[]) with patch.dict(openvswitch_port.__salt__, {'openvswitch.bridge_exists': mock, + 'openvswitch.interface_get_type': MagicMock(return_value='""'), 'openvswitch.port_list': mock_l }): comt = 'Port salt already exists.' @@ -49,6 +50,7 @@ def test_present(self): self.assertDictEqual(openvswitch_port.present(name, bridge), ret) with patch.dict(openvswitch_port.__salt__, {'openvswitch.bridge_exists': mock, + 'openvswitch.interface_get_type': MagicMock(return_value='""'), 'openvswitch.port_list': mock_n, 'openvswitch.port_add': mock }):