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()
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')
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)