def _classify_nets_bonds_config(persistent_config): """ Return the configuration of networks and bonds, separating the ones changed and the ones unchanged: changed_nets, changed_bonds, unchanged_nets, unchanged_bonds """ net_info = NetInfo(netswitch.configurator.netinfo()) current_config = kernelconfig.KernelConfig(net_info) desired_config = kernelconfig.normalize(persistent_config) changed_nets_names, extra_nets_names = _classify_entities_difference( desired_config.networks, current_config.networks ) changed_bonds_names, extra_bonds_names = _classify_entities_difference( desired_config.bonds, current_config.bonds ) changed_nets = { net: persistent_config.networks[net] for net in changed_nets_names } changed_bonds = { bond: persistent_config.bonds[bond] for bond in changed_bonds_names } extra_nets = {net: {'remove': True} for net in extra_nets_names} extra_bonds = { bond: {'remove': True} for bond in extra_bonds_names if _owned_ifcfg(bond) } return changed_nets, changed_bonds, extra_nets, extra_bonds
def _setup_nmstate(networks, bondings, options, in_rollback): """ Setup the networks using nmstate as the backend provider. nmstate handles the rollback by itself in case of an error during the transaction or in case the resulted state does not include the desired one. In order to support the connectivity check, the "regular" rollback is used (the Transaction context). """ logging.info('Processing setup through nmstate') desired_state = nmstate.generate_state(networks, bondings) logging.info('Desired state: %s', desired_state) _setup_dynamic_src_routing(networks) nmstate.setup(desired_state, verify_change=not in_rollback) net_info = NetInfo(netinfo_get()) with Transaction(in_rollback=in_rollback, persistent=False) as config: _setup_qos(networks, net_info, config.networks) for net_name, net_attrs in six.viewitems(networks): if net_attrs.get('remove'): config.removeNetwork(net_name) for net_name, net_attrs in six.viewitems(networks): if not net_attrs.get('remove'): config.setNetwork(net_name, net_attrs) for bond_name, bond_attrs in six.viewitems(bondings): if bond_attrs.get('remove'): config.removeBonding(bond_name) for bond_name, bond_attrs in six.viewitems(bondings): if not bond_attrs.get('remove'): config.setBonding(bond_name, bond_attrs) _setup_static_src_routing(networks) config.save() link_setup.setup_custom_bridge_opts(networks) connectivity.check(options)
def _classify_nets_bonds_config(persistent_config): """ Return the configuration of networks and bonds, separating the ones changed and the ones unchanged: changed_nets, changed_bonds, unchanged_nets, unchanged_bonds """ net_info = NetInfo(netswitch.configurator.netinfo()) current_config = kernelconfig.KernelConfig(net_info) desired_config = kernelconfig.normalize(persistent_config) changed_nets_names, extra_nets_names = _classify_entities_difference( desired_config.networks, current_config.networks) changed_bonds_names, extra_bonds_names = _classify_entities_difference( desired_config.bonds, current_config.bonds) changed_nets = { net: persistent_config.networks[net] for net in changed_nets_names } changed_bonds = { bond: persistent_config.bonds[bond] for bond in changed_bonds_names } extra_nets = {net: {'remove': True} for net in extra_nets_names} # We cannot ensure which bond is being owned by us, so we should not # remove them # TODO This should be removed once the cleanup is done extra_bonds = {} return changed_nets, changed_bonds, extra_nets, extra_bonds
def _create_fake_netinfo(switch): common_net_attrs = { 'ipv6addrs': [], 'gateway': '', 'dhcpv4': False, 'netmask': '', 'ipv4defaultroute': False, 'stp': 'off', 'ipv4addrs': [], 'mtu': 1500, 'ipv6gateway': '::', 'dhcpv6': False, 'ipv6autoconf': False, 'addr': '', 'ports': [], 'switch': switch } common_bond_attrs = {'opts': {'mode': '0'}, 'switch': switch} fake_netinfo = { 'networks': { 'fakebrnet1': dict(iface='eth0', bond='', bridged=False, nics=['eth0'], **common_net_attrs), 'fakevlannet1': dict(iface='eth1.1', bond='', bridged=False, nics=['eth1'], vlanid=1, **common_net_attrs), 'fakebondnet1': dict(iface='bond0', bond='bond0', bridged=False, nics=['eth2', 'eth3'], **common_net_attrs) }, 'vlans': { 'eth1.1': { 'iface': 'eth1', 'addr': '10.10.10.10', 'netmask': '255.255.0.0', 'mtu': 1500, 'vlanid': 1 } }, 'nics': ['eth0', 'eth1', 'eth2', 'eth3'], 'bridges': {}, 'bondings': { 'bond0': dict(slaves=['eth2', 'eth3'], **common_bond_attrs) }, 'nameservers': [], } return NetInfo(fake_netinfo)
def _is_explicit_defined_default_class(dev): """ A default class is defined explicitly when a non-vlan network has hostQos definitions. """ netinfo = NetInfo(cache_get()) for attrs in six.itervalues(netinfo.networks): if 'vlan' not in attrs and 'hostQos' in attrs and ( attrs['iface'] == dev): return True return False
def _is_explicit_defined_default_class(dev): """ A default class is defined explicitly when a non-vlan network has hostQos definitions. """ netinfo = NetInfo(cache_get()) for attrs in six.viewvalues(netinfo.networks): if 'vlan' not in attrs and 'hostQos' in attrs: ports = attrs['ports'] if attrs['bridged'] else [attrs['iface']] if dev in ports: return True return False
def validate(networks, bondings, net_info): legacy_nets, ovs_nets, legacy_bonds, ovs_bonds = _split_switch_type( networks, bondings, net_info) use_legacy_switch = legacy_nets or legacy_bonds use_ovs_switch = ovs_nets or ovs_bonds if use_legacy_switch and use_ovs_switch: raise ne.ConfigNetworkError( ne.ERR_BAD_PARAMS, 'Mixing of legacy and OVS networks is not supported inside one ' 'setupNetworks() call.') validator.validate_southbound_devices_usages(networks, NetInfo(net_info)) validator.validate_network_setup(networks, bondings, net_info) if use_legacy_switch: legacy_switch.validate_network_setup(legacy_nets)
def upgrade(): rconfig = RunningConfig() pconfig = PersistentConfig() libvirt_networks = libvirtnetwork.networks() _upgrade_volatile_running_config(rconfig) if rconfig.config_exists() or pconfig.config_exists(): _upgrade_unified_configuration(rconfig) _upgrade_unified_configuration(pconfig) else: # In case unified config has not existed before, it is assumed that # the networks existance have been persisted in libvirt db. vdsmnets = libvirt_vdsm_nets(libvirt_networks) _create_unified_configuration(rconfig, NetInfo(netinfo(vdsmnets))) _cleanup_libvirt_networks(libvirt_networks)
def _handle_setup(nets, bonds, running_config, nets_by_nic): commands = [] netinfo = NetInfo(netswitch.netinfo()) for bond, attrs in six.iteritems(bonds): if 'remove' not in attrs: _validate_bond_configuration(attrs, netinfo) if bond in running_config.bonds: commands.extend(_edit_ovs_bond(bond, attrs, running_config)) else: commands.extend(_setup_ovs_bond(bond, attrs, running_config)) for net, attrs in six.iteritems(nets): if 'remove' not in attrs: _validate_net_configuration(net, attrs, running_config, netinfo) if net in running_config.networks: commands.extend(_edit_ovs_net(net, attrs, running_config, nets_by_nic)) else: commands.extend(_setup_ovs_net(net, attrs, running_config, nets_by_nic)) return commands
def __init__(self, nets, bonds, net_info): self._nets = nets self._bonds = bonds self._net_info = NetInfo(net_info) self._desired_config = self._create_desired_config() self._running_config = RunningConfig()
def _getNetInfo(): def _processNetworks(netinfo): networks = {} defaultGateway = routes.getDefaultGateway() for network, netParams in netinfo.networks.iteritems(): networks[network] = {} # Translate key/value pairs from netinfo to unified if key matches for key, value in netParams.iteritems(): if key in NET_ATTR_WHITELIST and value != "": networks[network][key] = NET_ATTR_WHITELIST[key](value) networks[network]['bridged'] = netParams['bridged'] # Determine devices: nic/bond -> vlan -> bridge topLevelDevice = netParams['iface'] if netParams['bridged']: devices = (netinfo.nics.keys() + netinfo.vlans.keys() + netinfo.bondings.keys()) nonVnicPorts = [ dev for dev in netParams['ports'] if dev in devices ] # A network should only ever have (at most) an underlying # device hierarchy if nonVnicPorts: physicalDevice, = nonVnicPorts else: physicalDevice = None # vdsm allows nicless VM nets else: physicalDevice = topLevelDevice # Copy ip addressing information bootproto = str(misc.getIfaceCfg(topLevelDevice).get('BOOTPROTO')) if bootproto == 'dhcp': networks[network]['bootproto'] = bootproto else: if netParams['addr'] != '': networks[network]['ipaddr'] = netParams['addr'] if netParams['netmask'] != '': networks[network]['netmask'] = netParams['netmask'] if netParams['gateway'] != '': networks[network]['gateway'] = netParams['gateway'] if defaultGateway is not None: networks[network]['defaultRoute'] = ( defaultGateway.device == topLevelDevice) # What if the 'physical device' is actually a VLAN? if physicalDevice in netinfo.vlans: vlanDevice = physicalDevice networks[network]['vlan'] = \ str(netinfo.vlans[vlanDevice]['vlanid']) # The 'new' physical device is the VLAN's device physicalDevice = netinfo.vlans[vlanDevice]['iface'] # Is the physical device a bond or a nic? if physicalDevice in netinfo.bondings: networks[network]['bonding'] = physicalDevice elif physicalDevice in netinfo.nics: networks[network]['nic'] = physicalDevice else: # Nic-less networks pass return networks def _processBondings(netinfo): bondings = {} for bonding, bondingParams in netinfo.bondings.iteritems(): # If the bond is unused, skip it if not bondingParams['slaves']: continue bondings[bonding] = {'nics': bondingParams['slaves']} bondingOptions = misc.getIfaceCfg(bonding). \ get('BONDING_OPTS') if bondingOptions: bondings[bonding]['options'] = bondingOptions return bondings netinfo = NetInfo(netswitch.netinfo()) networks = _processNetworks(netinfo) bonds = _processBondings(netinfo) used_bonds = frozenset(attr['bonding'] for attr in networks.values() if 'bonding' in attr) # we do not want to touch bonds that are unrelated to us for bonding in bonds.keys(): if not _owned(bonding) and bonding not in used_bonds: del bonds[bonding] # assert that all bonds that we depend on are persisted for network, attributes in networks.iteritems(): bond = attributes.get('bonding') if bond is None: continue if bond not in bonds: raise Exception('Network %s depends on missing bond %s' % (network, bond)) return networks, bonds