def _del_broken_network(network, netAttr, configurator): """ Adapts the network information of broken networks so that they can be deleted via _del_network. """ _netinfo = CachingNetInfo() _netinfo.networks[network] = netAttr _netinfo.networks[network]['dhcpv4'] = False if _netinfo.networks[network]['bridged']: try: nets = configurator.runningConfig.networks except AttributeError: nets = {} # ifcfg does not need net definitions _netinfo.networks[network]['ports'] = _persistence.configuredPorts( nets, network) elif not os.path.exists('/sys/class/net/' + netAttr['iface']): # Bridgeless broken network without underlying device libvirt.removeNetwork(network) if config.get('vars', 'net_persistence') == 'unified': configurator.runningConfig.removeNetwork(network) return canonicalize_networks({network: _netinfo.networks[network]}) _del_network(network, configurator, bypass_validation=True, _netinfo=_netinfo)
def _del_network(network, configurator, vlan=None, bonding=None, bypass_validation=False, _netinfo=None, keep_bridge=False, **options): if _netinfo is None: _netinfo = CachingNetInfo() nics, vlan, vlan_id, bonding = _netinfo.getNicsVlanAndBondingForNetwork( network) bridged = _netinfo.networks[network]['bridged'] logging.info('Removing network %s with vlan=%s, bonding=%s, nics=%s,' 'keep_bridge=%s options=%s', network, vlan, bonding, nics, keep_bridge, options) if not bypass_validation: _validateDelNetwork(network, vlan, bonding, nics, bridged and not keep_bridge, _netinfo) net_ent = _objectivize_network(bridge=network if bridged else None, vlan=vlan, vlan_id=vlan_id, bonding=bonding, nic=nics[0] if nics and not bonding else None, _netinfo=_netinfo, configurator=configurator) net_ent.ipv4.bootproto = ( 'dhcp' if _netinfo.networks[network]['dhcpv4'] else 'none') if bridged and keep_bridge: # we now leave the bridge intact but delete everything underneath it net_ent_to_remove = net_ent.port if net_ent_to_remove is not None: # the configurator will not allow us to remove a bridge interface # (be it vlan, bond or nic) unless it is not used anymore. Since # we are interested to leave the bridge here, we have to disconnect # it from the device so that the configurator will allow its # removal. _disconnect_bridge_port(net_ent_to_remove.name) else: net_ent_to_remove = net_ent # We must first remove the libvirt network and then the network entity. # Otherwise if we first remove the network entity while the libvirt # network is still up, the network entity (In some flows) thinks that # it still has users and thus does not allow its removal configurator.removeLibvirtNetwork(network) if net_ent_to_remove is not None: logging.info('Removing network entity %s', net_ent_to_remove) net_ent_to_remove.remove() # We must remove the QoS last so that no devices nor networks mark the # QoS as used backing_device = hierarchy_backing_device(net_ent) if (backing_device is not None and os.path.exists(NET_PATH + '/' + backing_device.name)): configurator.removeQoS(net_ent)
def __init__(self, name, configurator, ipv4=None, ipv6=None, blockingdhcp=False, mtu=None, _netinfo=None): if _netinfo is None: _netinfo = CachingNetInfo() if name not in _netinfo.nics: raise ConfigNetworkError(ne.ERR_BAD_NIC, 'unknown nic: %s' % name) if _netinfo.ifaceUsers(name): mtu = max(mtu, mtus.getMtu(name)) super(Nic, self).__init__(name, configurator, ipv4, ipv6, blockingdhcp, mtu)
def __init__(self, name, configurator, ipv4=None, ipv6=None, blockingdhcp=False, mtu=None, _netinfo=None): if _netinfo is None: _netinfo = CachingNetInfo() if name not in _netinfo.nics: raise ConfigNetworkError(ne.ERR_BAD_NIC, 'unknown nic: %s' % name) if _netinfo.ifaceUsers(name): mtu = max(mtu, link_iface.iface(name).mtu()) super(Nic, self).__init__(name, configurator, ipv4, ipv6, blockingdhcp, mtu)
def testIterNetworkHierarchy(self): _netinfo = { 'networks': {}, 'vlans': {}, 'nics': ['testnic1', 'testnic2'], 'bondings': {}, 'bridges': {} } fakeInfo = CachingNetInfo(_netinfo) # Vlanned and bonded VM network nic1 = Nic('testnic1', configurator=None, _netinfo=fakeInfo) nic2 = Nic('testnic2', configurator=None, _netinfo=fakeInfo) bond1 = Bond('bond42', configurator=None, slaves=(nic1, nic2)) vlan1 = Vlan(bond1, 4, configurator=None) bridge1 = Bridge('testbridge', configurator=None, port=vlan1) self.assertEqual([dev for dev in bridge1], [bridge1, vlan1, bond1, nic1, nic2]) self.assertEqual(bond1, hierarchy_backing_device(bridge1)) self.assertEqual(4, hierarchy_vlan_tag(bridge1)) # Nic-less VM net bridge2 = Bridge('testbridge', configurator=None, port=None) self.assertEqual([dev for dev in bridge2], [bridge2]) self.assertEqual(None, hierarchy_backing_device(bridge2)) self.assertEqual(None, hierarchy_vlan_tag(bridge2)) # vlan-less VM net bridge3 = Bridge('testbridge', configurator=None, port=bond1) self.assertEqual([dev for dev in bridge3], [bridge3, bond1, nic1, nic2]) self.assertEqual(bond1, hierarchy_backing_device(bridge3)) self.assertEqual(None, hierarchy_vlan_tag(bridge3)) # Bond-less VM net bridge4 = Bridge('testbridge', configurator=None, port=nic1) self.assertEqual([dev for dev in bridge4], [bridge4, nic1]) self.assertEqual(nic1, hierarchy_backing_device(bridge4)) self.assertEqual(None, hierarchy_vlan_tag(bridge4)) # vlanned and bonded non-VM net self.assertEqual([dev for dev in vlan1], [vlan1, bond1, nic1, nic2]) self.assertEqual(bond1, hierarchy_backing_device(vlan1)) self.assertEqual(4, hierarchy_vlan_tag(vlan1)) # vlanned, bond-less non-VM net vlan2 = Vlan(nic1, 5, configurator=None) self.assertEqual([dev for dev in vlan2], [vlan2, nic1]) self.assertEqual(nic1, hierarchy_backing_device(vlan2)) self.assertEqual(5, hierarchy_vlan_tag(vlan2)) # non-vlanned and bonded non-VM net self.assertEqual([dev for dev in bond1], [bond1, nic1, nic2]) self.assertEqual(bond1, hierarchy_backing_device(bond1)) self.assertEqual(None, hierarchy_vlan_tag(bond1)) # non-vlanned and bond-less non-VM net self.assertEqual([dev for dev in nic2], [nic2]) self.assertEqual(nic2, hierarchy_backing_device(nic2)) self.assertEqual(None, hierarchy_vlan_tag(nic2))
def _emergency_network_cleanup(network, networkAttrs, configurator): """Remove all leftovers after failed setupNetwork""" _netinfo = CachingNetInfo() top_net_dev = None if 'bonding' in networkAttrs: if networkAttrs['bonding'] in _netinfo.bondings: top_net_dev = Bond.objectivize( networkAttrs['bonding'], configurator, options=None, nics=None, mtu=None, _netinfo=_netinfo, hwaddr=None, ) elif 'nic' in networkAttrs: if networkAttrs['nic'] in _netinfo.nics: top_net_dev = Nic( networkAttrs['nic'], configurator, _netinfo=_netinfo ) if 'vlan' in networkAttrs and top_net_dev: vlan_name = '%s.%s' % (top_net_dev.name, networkAttrs['vlan']) if vlan_name in _netinfo.vlans: top_net_dev = Vlan(top_net_dev, networkAttrs['vlan'], configurator) if networkAttrs['bridged']: if network in _netinfo.bridges: top_net_dev = Bridge(network, configurator, port=top_net_dev) if top_net_dev: top_net_dev.remove() configurator.runningConfig.removeNetwork(network)
def _get_netinfo(self): response = self.getVdsCapabilities() try: return CachingNetInfo(response[2]) except IndexError: raise Exception('VdsProxy: getVdsCapabilities failed. ' 'code:%s msg:%s' % (response[0], response[1]))
def testIterNetworkHierarchy(self): _netinfo = { 'networks': {}, 'vlans': {}, 'nics': ['testnic1', 'testnic2'], 'bondings': {}, 'bridges': {}, 'nameservers': [], } fakeInfo = CachingNetInfo(_netinfo) # Vlanned and bonded VM network nic1 = Nic('testnic1', configurator=None, _netinfo=fakeInfo) nic2 = Nic('testnic2', configurator=None, _netinfo=fakeInfo) bond1 = Bond('bond42', configurator=None, slaves=(nic1, nic2)) vlan1 = Vlan(bond1, 4, configurator=None) bridge1 = Bridge('testbridge', configurator=None, port=vlan1) assert [dev for dev in bridge1] == [bridge1, vlan1, bond1, nic1, nic2] assert bond1 == hierarchy_backing_device(bridge1) assert 4 == hierarchy_vlan_tag(bridge1) # Nic-less VM net bridge2 = Bridge('testbridge', configurator=None, port=None) assert [dev for dev in bridge2] == [bridge2] assert hierarchy_backing_device(bridge2) is None assert hierarchy_vlan_tag(bridge2) is None # vlan-less VM net bridge3 = Bridge('testbridge', configurator=None, port=bond1) assert [dev for dev in bridge3] == [bridge3, bond1, nic1, nic2] assert bond1 == hierarchy_backing_device(bridge3) assert hierarchy_vlan_tag(bridge3) is None # Bond-less VM net bridge4 = Bridge('testbridge', configurator=None, port=nic1) assert [dev for dev in bridge4] == [bridge4, nic1] assert nic1 == hierarchy_backing_device(bridge4) assert hierarchy_vlan_tag(bridge4) is None # vlanned and bonded non-VM net assert [dev for dev in vlan1] == [vlan1, bond1, nic1, nic2] assert bond1 == hierarchy_backing_device(vlan1) assert 4 == hierarchy_vlan_tag(vlan1) # vlanned, bond-less non-VM net vlan2 = Vlan(nic1, 5, configurator=None) assert [dev for dev in vlan2] == [vlan2, nic1] assert nic1 == hierarchy_backing_device(vlan2) assert 5 == hierarchy_vlan_tag(vlan2) # non-vlanned and bonded non-VM net assert [dev for dev in bond1] == [bond1, nic1, nic2] assert bond1 == hierarchy_backing_device(bond1) assert hierarchy_vlan_tag(bond1) is None # non-vlanned and bond-less non-VM net assert [dev for dev in nic2] == [nic2] assert nic2 == hierarchy_backing_device(nic2) assert hierarchy_vlan_tag(nic2) is None
def _del_broken_network(network, netAttr, configurator): """ Adapts the network information of broken networks so that they can be deleted via _del_network. """ iface = get_net_iface_from_config(network, netAttr) _netinfo = CachingNetInfo() _netinfo.networks[network] = {} _netinfo.networks[network]['iface'] = iface _netinfo.networks[network]['bridged'] = netAttr['bridged'] _netinfo.networks[network]['dhcpv4'] = False if _netinfo.networks[network]['bridged']: try: nets = configurator.runningConfig.networks except AttributeError: nets = {} # ifcfg does not need net definitions _netinfo.networks[network][ 'ports'] = netconfpersistence.configuredPorts(nets, network) elif not os.path.exists('/sys/class/net/' + iface): # Bridgeless broken network without underlying device configurator.runningConfig.removeNetwork(network) return canonicalize_networks({network: _netinfo.networks[network]}) _del_network(network, configurator, _netinfo, None, bypass_validation=True)
def testTextualRepr(self): _netinfo = {'networks': {}, 'vlans': {}, 'nics': ['testnic1', 'testnic2'], 'bondings': {}, 'bridges': {}, 'nameservers': []} fakeInfo = CachingNetInfo(_netinfo) nic1 = Nic('testnic1', None, _netinfo=fakeInfo) nic2 = Nic('testnic2', None, _netinfo=fakeInfo) bond1 = Bond('bond42', None, slaves=(nic1, nic2)) vlan1 = Vlan(bond1, '4', None) bridge1 = Bridge('testbridge', None, port=vlan1) self.assertEqual('%r' % bridge1, 'Bridge(testbridge: Vlan(bond42.4: ' 'Bond(bond42: (Nic(testnic1), Nic(testnic2)))))')
def setupNetworks(self, networks, bonds, options): try: api.setupNetworks(networks, bonds, options) caps = api.network_caps() self.netinfo = CachingNetInfo(caps) self.config = RunningConfig() except errors.ConfigNetworkError as e: status = e.errCode msg = e.message else: status = SUCCESS msg = '' return status, msg
def _setup_legacy(networks, bondings, options, net_info, in_rollback): _netinfo = CachingNetInfo(net_info) with Ifcfg(_netinfo, in_rollback) as configurator: # from this point forward, any exception thrown will be handled by # Configurator.__exit__. legacy_switch.remove_networks(networks, bondings, configurator, _netinfo) legacy_switch.bonds_setup(bondings, configurator, _netinfo, in_rollback) legacy_switch.add_missing_networks(configurator, networks, bondings, _netinfo) connectivity.check(options)
def _setup_legacy(networks, bondings, options, in_rollback): _libvirt_nets = libvirt_nets() _netinfo = CachingNetInfo(netinfo_get(libvirtNets2vdsm(_libvirt_nets))) with legacy_switch.ConfiguratorClass(in_rollback) as configurator: # from this point forward, any exception thrown will be handled by # Configurator.__exit__. legacy_switch.remove_networks(networks, bondings, configurator, _netinfo, _libvirt_nets) legacy_switch.bonds_setup(bondings, configurator, _netinfo, in_rollback) legacy_switch.add_missing_networks(configurator, networks, bondings, _netinfo) connectivity.check(options)
def refreshNetworkCapabilities(self): caps = api.network_caps() self.netinfo = CachingNetInfo(caps)
def _objectivize_network( bridge=None, vlan=None, vlan_id=None, bonding=None, bondattr=None, nic=None, mtu=None, ipaddr=None, netmask=None, gateway=None, bootproto=None, ipv6addr=None, ipv6gateway=None, ipv6autoconf=None, dhcpv6=None, defaultRoute=None, nameservers=None, _netinfo=None, configurator=None, blockingdhcp=None, opts=None, ): """ Constructs an object hierarchy that describes the network configuration that is passed in the parameters. :param bridge: name of the bridge. :param vlan: vlan device name. :param vlan_id: vlan tag id. :param bonding: name of the bond. :param bondattr: bond attributes if defined. :param nic: name of the nic. :param mtu: the desired network maximum transmission unit. :param ipaddr: IPv4 address in dotted decimal format. :param netmask: IPv4 mask in dotted decimal format. :param gateway: IPv4 address in dotted decimal format. :param bootproto: protocol for getting IP config for the net, e.g., 'dhcp' :param ipv6addr: IPv6 address in format address[/prefixlen]. :param ipv6gateway: IPv6 address in format address[/prefixlen]. :param ipv6autoconf: whether to use IPv6's stateless autoconfiguration. :param dhcpv6: whether to use DHCPv6. :param nameservers: a list of DNS servers. :param _netinfo: network information snapshot. :param configurator: instance to use to apply the network configuration. :param blockingdhcp: whether to acquire dhcp IP config in a synced manner. :param defaultRoute: Should this network's gateway be set in the main routing table? :param opts: misc options received by the callee, e.g., {'stp': True}. this function can modify the dictionary. :returns: the top object of the hierarchy. """ if _netinfo is None: _netinfo = CachingNetInfo() if configurator is None: configurator = Ifcfg(_netinfo) if opts is None: opts = {} if bootproto == 'none': bootproto = None top_net_dev = None if bonding: if bondattr is None: bondattr = {} top_net_dev = Bond.objectivize( bonding, configurator, options=bondattr.get('options'), nics=bondattr.get('nics'), hwaddr=bondattr.get('hwaddr'), mtu=mtu, _netinfo=_netinfo, on_removal_just_detach_from_network=True, ) elif nic: top_net_dev = Nic(nic, configurator, mtu=mtu, _netinfo=_netinfo) if vlan is not None: tag = _netinfo.vlans[vlan]['vlanid'] if vlan_id is None else vlan_id top_net_dev = Vlan(top_net_dev, tag, configurator, mtu=mtu, name=vlan) elif vlan_id is not None: top_net_dev = Vlan(top_net_dev, vlan_id, configurator, mtu=mtu) if bridge is not None: top_net_dev = Bridge( bridge, configurator, port=top_net_dev, mtu=mtu, stp=opts.get('stp', None), ) # Inherit DUID from the port's possibly still active DHCP lease so the # bridge gets the same IP address. (BZ#1219429) if top_net_dev.port and bootproto == 'dhcp': top_net_dev.duid_source = top_net_dev.port.name if top_net_dev is None: raise ConfigNetworkError( ne.ERR_BAD_PARAMS, 'Network defined without ' 'devices.' ) top_net_dev.ipv4 = IPv4(ipaddr, netmask, gateway, defaultRoute, bootproto) top_net_dev.ipv6 = IPv6( ipv6addr, ipv6gateway, defaultRoute, ipv6autoconf, dhcpv6 ) top_net_dev.blockingdhcp = configurator._inRollback or tobool(blockingdhcp) top_net_dev.nameservers = nameservers return top_net_dev
def _add_network(network, configurator, nameservers, vlan=None, bonding=None, nic=None, ipaddr=None, netmask=None, prefix=None, mtu=None, gateway=None, dhcpv6=None, ipv6addr=None, ipv6gateway=None, ipv6autoconf=None, bridged=True, _netinfo=None, hostQos=None, defaultRoute=None, blockingdhcp=False, **options): if _netinfo is None: _netinfo = CachingNetInfo() if dhcpv6 is not None: dhcpv6 = utils.tobool(dhcpv6) if ipv6autoconf is not None: ipv6autoconf = utils.tobool(ipv6autoconf) if network == '': raise ConfigNetworkError(ne.ERR_BAD_BRIDGE, 'Empty network names are not valid') if prefix: if netmask: raise ConfigNetworkError(ne.ERR_BAD_PARAMS, 'Both PREFIX and NETMASK supplied') else: try: netmask = addresses.prefix2netmask(int(prefix)) except ValueError as ve: raise ConfigNetworkError(ne.ERR_BAD_ADDR, 'Bad prefix: %s' % ve) logging.debug('Validating network...') if network in _netinfo.networks: raise ConfigNetworkError( ne.ERR_USED_BRIDGE, 'Network already exists (%s)' % (network,)) if bonding: _validate_inter_network_compatibility(_netinfo, vlan, bonding) elif nic: _validate_inter_network_compatibility(_netinfo, vlan, nic) logging.info('Adding network %s with vlan=%s, bonding=%s, nic=%s, ' 'mtu=%s, bridged=%s, defaultRoute=%s, options=%s', network, vlan, bonding, nic, mtu, bridged, defaultRoute, options) bootproto = options.pop('bootproto', None) net_ent = _objectivize_network( bridge=network if bridged else None, vlan_id=vlan, bonding=bonding, nic=nic, mtu=mtu, ipaddr=ipaddr, netmask=netmask, gateway=gateway, bootproto=bootproto, dhcpv6=dhcpv6, blockingdhcp=blockingdhcp, ipv6addr=ipv6addr, ipv6gateway=ipv6gateway, ipv6autoconf=ipv6autoconf, defaultRoute=defaultRoute, nameservers=nameservers, _netinfo=_netinfo, configurator=configurator, opts=options) if bridged and network in _netinfo.bridges: # The bridge already exists, update the configured entity to one level # below and update the mtu of the bridge. # The mtu is updated in the bridge configuration and on all the tap # devices attached to it (for the VMs). # (expecting the bridge running mtu to be updated by the kernel when # the device attached under it has its mtu updated) logging.info('Bridge %s already exists.', network) net_ent_to_configure = net_ent.port _update_mtu_for_an_existing_bridge(network, configurator, mtu) else: net_ent_to_configure = net_ent if net_ent_to_configure is not None: logging.info('Configuring device %s', net_ent_to_configure) net_ent_to_configure.configure(**options) configurator.configureLibvirtNetwork(network, net_ent) if hostQos is not None: configurator.configureQoS(hostQos, net_ent)
def _objectivize_network(bridge=None, vlan=None, vlan_id=None, bonding=None, nic=None, mtu=None, ipaddr=None, netmask=None, gateway=None, bootproto=None, ipv6addr=None, ipv6gateway=None, ipv6autoconf=None, dhcpv6=None, defaultRoute=None, nameservers=None, _netinfo=None, configurator=None, blockingdhcp=None, opts=None): """ Constructs an object hierarchy that describes the network configuration that is passed in the parameters. :param bridge: name of the bridge. :param vlan: vlan device name. :param vlan_id: vlan tag id. :param bonding: name of the bond. :param nic: name of the nic. :param mtu: the desired network maximum transmission unit. :param ipaddr: IPv4 address in dotted decimal format. :param netmask: IPv4 mask in dotted decimal format. :param gateway: IPv4 address in dotted decimal format. :param bootproto: protocol for getting IP config for the net, e.g., 'dhcp' :param ipv6addr: IPv6 address in format address[/prefixlen]. :param ipv6gateway: IPv6 address in format address[/prefixlen]. :param ipv6autoconf: whether to use IPv6's stateless autoconfiguration. :param dhcpv6: whether to use DHCPv6. :param nameservers: a list of DNS servers. :param _netinfo: network information snapshot. :param configurator: instance to use to apply the network configuration. :param blockingdhcp: whether to acquire dhcp IP config in a synced manner. :param defaultRoute: Should this network's gateway be set in the main routing table? :param opts: misc options received by the callee, e.g., {'stp': True}. this function can modify the dictionary. :returns: the top object of the hierarchy. """ if configurator is None: configurator = ConfiguratorClass() if _netinfo is None: _netinfo = CachingNetInfo() if opts is None: opts = {} if bootproto == 'none': bootproto = None top_net_dev = None if bonding: top_net_dev = Bond.objectivize( bonding, configurator, options=None, nics=None, mtu=mtu, _netinfo=_netinfo, on_removal_just_detach_from_network=True) elif nic: bond = _netinfo.getBondingForNic(nic) if bond: raise ConfigNetworkError(ne.ERR_USED_NIC, 'Nic %s already ' 'enslaved to %s' % (nic, bond)) top_net_dev = Nic(nic, configurator, mtu=mtu, _netinfo=_netinfo) if vlan is not None: tag = _netinfo.vlans[vlan]['vlanid'] if vlan_id is None else vlan_id top_net_dev = Vlan(top_net_dev, tag, configurator, mtu=mtu, name=vlan) elif vlan_id is not None: top_net_dev = Vlan(top_net_dev, vlan_id, configurator, mtu=mtu) if bridge is not None: top_net_dev = Bridge( bridge, configurator, port=top_net_dev, mtu=mtu, stp=opts.get('stp', None)) # Inherit DUID from the port's possibly still active DHCP lease so the # bridge gets the same IP address. (BZ#1219429) if top_net_dev.port and bootproto == 'dhcp': top_net_dev.duid_source = top_net_dev.port.name if top_net_dev is None: raise ConfigNetworkError(ne.ERR_BAD_PARAMS, 'Network defined without ' 'devices.') top_net_dev.ipv4 = IPv4(ipaddr, netmask, gateway, defaultRoute, bootproto) top_net_dev.ipv6 = IPv6( ipv6addr, ipv6gateway, defaultRoute, ipv6autoconf, dhcpv6) top_net_dev.blockingdhcp = (configurator._inRollback or utils.tobool(blockingdhcp)) top_net_dev.nameservers = nameservers return top_net_dev