Пример #1
0
 def test_del_bridge_port(self, check_call):
     ovs.del_bridge_port('test', 'eth1')
     check_call.assert_has_calls([
         call(["ovs-vsctl", "--", "--if-exists", "del-port",
               'test', 'eth1']),
         call(['ip', 'link', 'set', 'eth1', 'down']),
         call(['ip', 'link', 'set', 'eth1', 'promisc', 'off'])
     ])
     self.assertTrue(self.log.call_count == 1)
Пример #2
0
def remove_patch_ports(bridge):
    """Remove patch ports from both ends starting with named bridge.

    :param bridge: Name of bridge to look for patch ports to remove.
    :type bridge: str
    """
    # NOTE: We need to consume all output from the `patch_ports_on_bridge`
    # generator prior to removing anything otherwise it will raise an error.
    for patch in list(ch_ovs.patch_ports_on_bridge(bridge)):
        ch_ovs.del_bridge_port(patch.this_end.bridge,
                               patch.this_end.port,
                               linkdown=False)
        ch_ovs.del_bridge_port(patch.other_end.bridge,
                               patch.other_end.port,
                               linkdown=False)
Пример #3
0
 def test_del_bridge_port(self):
     self.patch_object(ovs.subprocess, 'check_call')
     self.patch_object(ovs, 'log')
     ovs.del_bridge_port('test', 'eth1')
     self.check_call.assert_has_calls([
         mock.call(
             ['ovs-vsctl', '--', '--if-exists', 'del-port', 'test',
              'eth1']),
         mock.call(['ip', 'link', 'set', 'eth1', 'down']),
         mock.call(['ip', 'link', 'set', 'eth1', 'promisc', 'off'])
     ])
     self.assertTrue(self.log.call_count == 1)
     self.assertTrue(self.check_call.call_count == 3)
     self.check_call.reset_mock()
     ovs.del_bridge_port('test', 'eth1', linkdown=False)
     self.check_call.assert_called_once_with(
         ['ovs-vsctl', '--', '--if-exists', 'del-port', 'test', 'eth1'])
Пример #4
0
    def configure_bridges(self):
        """Configure Open vSwitch bridges ports and interfaces."""
        if self.check_if_paused() != (None, None):
            ch_core.hookenv.log(
                'Unit is paused, defer Open vSwitch bridge '
                'port interface configuration tasks.',
                level=ch_core.hookenv.INFO)
            return
        bpi = os_context.BridgePortInterfaceMap(bridges_key=self.bridges_key)
        bond_config = os_context.BondConfig()
        ch_core.hookenv.log('BridgePortInterfaceMap: "{}"'.format(bpi.items()),
                            level=ch_core.hookenv.DEBUG)

        # build map of bridges to ovn networks with existing if-mapping on host
        # and at the same time build ovn-bridge-mappings string
        ovn_br_map_str = ''
        ovnbridges = collections.defaultdict(list)
        config_obm = self.config['ovn-bridge-mappings'] or ''
        for pair in sorted(config_obm.split()):
            network, bridge = pair.split(':', 1)
            if bridge in bpi:
                ovnbridges[bridge].append(network)
                if ovn_br_map_str:
                    ovn_br_map_str += ','
                ovn_br_map_str += '{}:{}'.format(network, bridge)

        bridges = ch_ovsdb.SimpleOVSDB('ovs-vsctl').bridge
        ports = ch_ovsdb.SimpleOVSDB('ovs-vsctl').port
        for bridge in bridges.find('external_ids:charm-ovn-chassis=managed'):
            # remove bridges and ports that are managed by us and no longer in
            # config
            if bridge['name'] not in bpi and bridge['name'] != 'br-int':
                ch_core.hookenv.log(
                    'removing bridge "{}" as it is no longer'
                    'present in configuration for this unit.'.format(
                        bridge['name']),
                    level=ch_core.hookenv.DEBUG)
                ch_ovs.del_bridge(bridge['name'])
            else:
                for port in ports.find(
                        'external_ids:charm-ovn-chassis={}'.format(
                            bridge['name'])):
                    if port['name'] not in bpi[bridge['name']]:
                        ch_core.hookenv.log(
                            'removing port "{}" from bridge '
                            '"{}" as it is no longer present '
                            'in configuration for this unit.'.format(
                                port['name'], bridge['name']),
                            level=ch_core.hookenv.DEBUG)
                        ch_ovs.del_bridge_port(bridge['name'], port['name'])
        brdata = {
            'external-ids': {
                'charm-ovn-chassis': 'managed'
            },
            'protocols': 'OpenFlow13,OpenFlow15',
        }
        if self.options.enable_dpdk:
            brdata.update({'datapath-type': 'netdev'})
        else:
            brdata.update({'datapath-type': 'system'})
        # we always update the integration bridge to make sure it has settings
        # apropriate for the current charm configuration
        ch_ovs.add_bridge(
            'br-int',
            brdata={
                **brdata,
                **{
                    # for the integration bridge we want the datapath to await
                    # controller action before adding any flows. This is to avoid
                    # switching packets between isolated logical networks before
                    # `ovn-controller` starts up.
                    'fail-mode': 'secure',
                    # Suppress in-band control flows for the integration bridge,
                    # refer to ovn-architecture(7) for more details.
                    'other-config': {
                        'disable-in-band': 'true'
                    },
                },
            })
        for br in bpi:
            if br not in ovnbridges:
                continue
            ch_ovs.add_bridge(
                br,
                brdata={
                    **brdata,
                    # for bridges used for external connectivity we want the
                    # datapath to act like an ordinary MAC-learning switch.
                    **{
                        'fail-mode': 'standalone'
                    },
                })
            for port in bpi[br]:
                ifdatamap = bpi.get_ifdatamap(br, port)
                ifdatamap = {
                    port: {
                        **ifdata,
                        **{
                            'external-ids': {
                                'charm-ovn-chassis': br
                            }
                        },
                    }
                    for port, ifdata in ifdatamap.items()
                }

                if len(ifdatamap) > 1:
                    ch_ovs.add_bridge_bond(br, port, list(ifdatamap.keys()),
                                           bond_config.get_ovs_portdata(port),
                                           ifdatamap)
                else:
                    ch_ovs.add_bridge_port(
                        br,
                        port,
                        ifdata=ifdatamap.get(port, {}),
                        linkup=not self.options.enable_dpdk,
                        promisc=None,
                        portdata={'external-ids': {
                            'charm-ovn-chassis': br
                        }})

        opvs = ch_ovsdb.SimpleOVSDB('ovs-vsctl').open_vswitch
        if ovn_br_map_str:
            opvs.set('.', 'external_ids:ovn-bridge-mappings', ovn_br_map_str)
            # NOTE(fnordahl): Workaround for LP: #1848757
            opvs.set('.', 'external_ids:ovn-cms-options',
                     'enable-chassis-as-gw')
        else:
            opvs.remove('.', 'external_ids', 'ovn-bridge-mappings')
            # NOTE(fnordahl): Workaround for LP: #1848757
            opvs.remove('.', 'external_ids', 'ovn-cms-options')