Exemplo n.º 1
0
def cleanup(args):
    """Clean up after Neutron agents."""
    # Check that prerequisites for operation are met
    if not ch_openstack_utils.is_unit_paused_set():
        raise UnitNotPaused()
    if ch_core.hookenv.config('firewall-driver') != 'openvswitch':
        raise MandatoryConfigurationNotSet(
            'Action requires configuration option `firewall-driver` to be set '
            'to "openvswitch" for succesfull operation.')
    if not ch_core.hookenv.action_get('i-really-mean-it'):
        raise MandatoryConfigurationNotSet(
            'Action requires the `i-really-mean-it` parameter to be set to '
            '"true".')

    # The names used for the integration- and tunnel-bridge are
    # configurable, but this configuration is not exposed in the charm.
    #
    # Assume default names are used.
    remove_patch_ports('br-int')
    ch_ovs.del_bridge('br-tun')

    # The Neutron Open vSwitch agent configures each Open vSwitch bridge to
    # establish an active OVSDB connection back to the Neutron Agent.
    #
    # Remove these
    remove_per_bridge_controllers()

    # Remove namespaces set up by Neutron
    neutron_netns_cleanup()

    # Remove ipsets set up by Neutron
    neutron_ipset_cleanup()
Exemplo n.º 2
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')
Exemplo n.º 3
0
 def test_del_bridge(self, check_call):
     ovs.del_bridge('test')
     check_call.assert_called_with(
         ["ovs-vsctl", "--", "--if-exists", "del-br", 'test'])
     self.assertTrue(self.log.call_count == 1)