Best Python code snippet using lisa_python
configNetwork.py
Source:configNetwork.py  
1#!/usr/bin/python2#3# Copyright 2011 Red Hat, Inc.4#5# This program is free software; you can redistribute it and/or modify6# it under the terms of the GNU General Public License as published by7# the Free Software Foundation; either version 2 of the License, or8# (at your option) any later version.9#10# This program is distributed in the hope that it will be useful,11# but WITHOUT ANY WARRANTY; without even the implied warranty of12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the13# GNU General Public License for more details.14#15# You should have received a copy of the GNU General Public License16# along with this program; if not, write to the Free Software17# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA18#19# Refer to the README and COPYING files for full details of the license20#21import sys, subprocess, os, re, traceback22import shutil23import pipes24import pwd25import time26import logging27from collections import defaultdict28import threading29import constants30import utils31import neterrors as ne32import define33from netinfo import NetInfo, getIpAddresses, NET_CONF_DIR, NET_CONF_BACK_DIR34CONNECTIVITY_TIMEOUT_DEFAULT = 435MAX_VLAN_ID = 409536MAX_BRIDGE_NAME_LEN = 1537ILLEGAL_BRIDGE_CHARS = ':. \t'38class ConfigNetworkError(Exception):39    def __init__(self, errCode, message):40        self.errCode = errCode41        self.message = message42        Exception.__init__(self, self.errCode, self.message)43def _isTrue(b):44    "Check all kinds of boolean input"45    if b in ('true', 'True'):46        return True47    elif b in ('false', 'False'):48        return False49    return bool(b)50def ipcalc(checkopt, s):51    "Validate an ip address (or netmask) using ipcalc"52    if not isinstance(s, basestring):53        return 054    p = subprocess.Popen([constants.EXT_IPCALC, '-c', checkopt, s],55            close_fds=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)56    out, err = p.communicate()57    if err:58        logging.warn(err)59    return not p.returncode60def ifdown(iface):61    "Bring down an interface"62    p = subprocess.Popen([constants.EXT_IFDOWN, iface], stdout=subprocess.PIPE,63                    stderr=subprocess.PIPE, close_fds=True)64    out, err = p.communicate()65    if out.strip():66        logging.info(out)67    if err.strip():68        logging.warn('\n'.join([line for line in err.splitlines()69                                if not line.endswith(' does not exist!')]))70    return p.returncode71def ifup(iface):72    "Bring up an interface"73    p = subprocess.Popen([constants.EXT_IFUP, iface], stdout=subprocess.PIPE,74                    stderr=subprocess.PIPE, close_fds=True)75    out, err = p.communicate()76    if out.strip():77        logging.info(out)78    if err.strip():79        logging.warn(err)80def ifaceUsers(iface):81    "Returns a list of entities using the interface"82    _netinfo = NetInfo()83    users = set()84    for b, bdict in _netinfo.networks.iteritems():85        if iface in bdict['ports']:86            users.add(b)87    for b, bdict in _netinfo.bondings.iteritems():88        if iface in bdict['slaves']:89            users.add(b)90    for v, vdict in _netinfo.vlans.iteritems():91        if iface == vdict['iface']:92            users.add(v)93    return users94def nicOtherUsers(bridge, vlan, bonding, nic):95    "Returns a list of interfaces using a nic, other than the specified one (used for validation)"96    if bonding:97        owner = bonding98    elif vlan:99        owner = nic + '.' + vlan100    else:101        owner = bridge102    users = ifaceUsers(nic)103    if bonding:104        users.update(bondingOtherUsers(bridge, vlan, bonding))105    users.discard(owner)106    return users107def bondingOtherUsers(bridge, vlan, bonding):108    "Return a list of nics/interfaces using a bonding, other than the specified one (used for validation)"109    if vlan:110        owner = bonding + '.' + vlan111    else:112        owner = bridge113    users = ifaceUsers(bonding)114    users.discard(owner)115    return users116def nicSort(nics):117    "Return a list of nics/interfaces ordered by name"118    nics_list = []119    nics_rexp = re.compile("([A-Za-z]+)([0-9]+)")120    for nic_name in nics:121        nic_sre = nics_rexp.match(nic_name)122        if nic_sre:123            nics_list.append((nic_sre.group(1), int(nic_sre.group(2))))124        else:125            nics_list.append((nic_name, ''))126    return [x + str(y) for x, y in sorted(nics_list)]127class ConfigWriter(object):128    NET_CONF_PREF = NET_CONF_DIR + 'ifcfg-'129    CONFFILE_HEADER = '# automatically generated by vdsm'130    DELETED_HEADER = '# original file did not exist'131    def __init__(self):132        self._backups = {}133    def _backup(self, filename):134        self._atomicBackup(filename)135        self._persistentBackup(filename)136    def _atomicBackup(self, filename):137        """Backs up configuration to memory, for a later rollback in case of error."""138        confFile = os.path.join(NET_CONF_DIR, filename)139        if confFile not in self._backups:140            try:141                self._backups[confFile] = open(confFile).read()142                logging.debug("Backed up %s" % confFile)143            except IOError:144                pass145    def restoreAtomicBackup(self):146        logging.info("Rolling back configuration (restoring atomic backup)")147        if not self._backups:148            return149        for confFile, content in self._backups.iteritems():150            open(confFile, 'w').write(content)151            logging.debug('Restored %s', confFile)152        subprocess.Popen(['/etc/init.d/network', 'start'])153    @staticmethod154    def _removeFile(filename):155        """Remove file, umounting ovirt config files if needed."""156        mounts = open('/proc/mounts').read()157        if ' /config ext3' in mounts and ' %s ext3' % filename in mounts:158            subprocess.call([constants.EXT_UMOUNT, '-n', filename])159        utils.rmFile(filename)160    @classmethod161    def _persistentBackup(cls, filename):162        if os.path.exists('/usr/libexec/ovirt-functions'):163            subprocess.call([constants.EXT_SH, '/usr/libexec/ovirt-functions', 'unmount_config', filename])164            logging.debug("unmounted %s using ovirt" % filename)165        (dummy, basename) = os.path.split(filename)166        backup = os.path.join(NET_CONF_BACK_DIR, basename)167        if os.path.exists(backup):168            # original copy already backed up169            return170        vdsm_uid = pwd.getpwnam('vdsm').pw_uid171        # make directory (if it doesn't exist) and assign it to vdsm172        if not os.path.exists(NET_CONF_BACK_DIR):173            os.mkdir(NET_CONF_BACK_DIR)174        os.chown(NET_CONF_BACK_DIR, vdsm_uid, 0)175        if os.path.exists(filename):176            shutil.copy2(filename, backup)177        else:178            open(backup, 'w').write(cls.DELETED_HEADER + '\n')179        os.chown(backup, vdsm_uid, 0)180        logging.debug("Persistently backed up %s (until next 'set safe config')" % filename)181    def addBridge(self, name, ipaddr=None, netmask=None, gateway=None,182            bootproto=None, delay='0', onboot='yes', **kwargs):183        "Based on addNetwork"184        s = """DEVICE=%s\nTYPE=Bridge\nONBOOT=%s\n""" % (pipes.quote(name), pipes.quote(onboot))185        if ipaddr:186            s = s + 'IPADDR=%s\nNETMASK=%s\n' % (pipes.quote(ipaddr), pipes.quote(netmask))187            if gateway:188                s = s + 'GATEWAY=%s\n' % pipes.quote(gateway)189        else:190            if bootproto:191                s = s + 'BOOTPROTO=%s\n' % pipes.quote(bootproto)192        s += 'DELAY=%s\n' % pipes.quote(delay)193        BLACKLIST = ['TYPE', 'NAME', 'DEVICE', 'bondingOptions',194                     'force', 'blockingdhcp',195                     'connectivityCheck', 'connectivityTimeout']196        for k in set(kwargs.keys()).difference(set(BLACKLIST)):197            if re.match('^[a-zA-Z_]\w*$', k):198                s += '%s=%s\n' % (k.upper(), pipes.quote(kwargs[k]))199            else:200                logging.debug('ignoring variable %s' % k)201        conffile = self.NET_CONF_PREF + name202        self._backup(conffile)203        open(conffile, 'w').write(s)204        os.chmod(conffile, 0664)205    def addVlan(self, vlanId, iface, bridge):206        "Based on addNetwork"207        conffile = self.NET_CONF_PREF + iface + '.' + vlanId208        self._backup(conffile)209        open(conffile, 'w').write("""DEVICE=%s.%s\nONBOOT=yes\nVLAN=yes\nBOOTPROTO=none\nBRIDGE=%s\n""" % (pipes.quote(iface), vlanId, pipes.quote(bridge)))210        os.chmod(conffile, 0664)211    def addBonding(self, bonding, bridge=None, bondingOptions=None):212        "Based on addNetwork"213        conffile = self.NET_CONF_PREF + bonding214        self._backup(conffile)215        with open(conffile, 'w') as f:216            f.write("""DEVICE=%s\nONBOOT=yes\nBOOTPROTO=none\n""" % (bonding))217            if bridge:218                f.write('BRIDGE=%s\n' % pipes.quote(bridge))219            if not bondingOptions:220                bondingOptions = 'mode=802.3ad miimon=150'221            f.write('BONDING_OPTS=%s' % pipes.quote(bondingOptions or ''))222        os.chmod(conffile, 0664)223        # create the bonding device to avoid initscripts noise224        if bonding not in open('/sys/class/net/bonding_masters').read().split():225            open('/sys/class/net/bonding_masters', 'w').write('+%s\n' % bonding)226    def addNic(self, nic, bonding=None, bridge=None):227        "Based on addNetwork"228        conffile = self.NET_CONF_PREF + nic229        self._backup(conffile)230        _netinfo = NetInfo()231        hwaddr = _netinfo.nics[nic].get('permhwaddr') or \232                 _netinfo.nics[nic]['hwaddr']233        with open(conffile, 'w') as f:234            f.write('DEVICE=%s\nONBOOT=yes\nBOOTPROTO=none\nHWADDR=%s\n' % (pipes.quote(nic),235                    pipes.quote(hwaddr)))236            if bridge:237                f.write('BRIDGE=%s\n' % pipes.quote(bridge))238            if bonding:239                f.write('MASTER=%s\n' % pipes.quote(bonding))240                f.write('SLAVE=yes\n')241        os.chmod(conffile, 0664)242    def removeNic(self, nic):243        cf = self.NET_CONF_PREF + nic244        self._backup(cf)245        try:246            hwlines = [ line for line in open(cf).readlines()247                        if line.startswith('HWADDR=') ]248            l = ['DEVICE=%s\n' % nic, 'ONBOOT=yes\n', 'BOOTPROTO=none\n'] + hwlines249            open(cf, 'w').writelines(l)250        except IOError:251            pass252    def removeVlan(self, vlanId, iface):253        self._backup(self.NET_CONF_PREF + iface + '.' + vlanId)254        self._removeFile(self.NET_CONF_PREF + iface + '.' + vlanId)255    def removeBonding(self, bonding):256        self._backup(self.NET_CONF_PREF + bonding)257        self._removeFile(self.NET_CONF_PREF + bonding)258    def removeBridge(self, bridge):259        self._backup(self.NET_CONF_PREF + bridge)260        self._removeFile(self.NET_CONF_PREF + bridge)261        # the deleted bridge should never be up at this stage.262        if bridge in NetInfo().networks:263            raise ConfigNetworkError(ne.ERR_USED_BRIDGE, 'delNetwork: bridge %s still exists' % bridge)264def isBridgeNameValid(bridgeName):265    return bridgeName and len(bridgeName) <= MAX_BRIDGE_NAME_LEN and len(set(bridgeName) & set(ILLEGAL_BRIDGE_CHARS)) == 0266def validateBridgeName(bridgeName):267    if not isBridgeNameValid(bridgeName):268        raise ConfigNetworkError(ne.ERR_BAD_BRIDGE, "Bridge name isn't valid: %r"%bridgeName)269def validateIpAddress(ipAddr):270    if not ipcalc('-4', ipAddr):271        raise ConfigNetworkError(ne.ERR_BAD_ADDR, "Bad IP address: %r"%ipAddr)272    if ipAddr in getIpAddresses():273        raise ConfigNetworkError(ne.ERR_BAD_ADDR, "IP address is already in use")274def validateNetmask(netmask):275    if not ipcalc('-m', netmask):276        raise ConfigNetworkError(ne.ERR_BAD_ADDR, "Bad netmask: %r"%netmask)277def validateGateway(gateway):278    if not ipcalc('-4', gateway):279        raise ConfigNetworkError(ne.ERR_BAD_ADDR, "Bad gateway: %r"%gateway)280def validateBondingName(bonding):281    if not re.match('^bond[0-9]+$', bonding):282        raise ConfigNetworkError(ne.ERR_BAD_BONDING, '%r is not a valid bonding device name' % bonding)283def validateBondingOptions(bonding, bondingOptions):284    'Example: BONDING_OPTS="mode=802.3ad miimon=150"'285    try:286        for option in bondingOptions.split():287            key,value = option.split('=')288            if not os.path.exists('/sys/class/net/%(bonding)s/bonding/%(key)s'289                                  % locals()):290                raise ConfigNetworkError(ne.ERR_BAD_BONDING,291                        "%r is not a valid bonding option" % key)292    except ValueError:293        raise ConfigNetworkError(ne.ERR_BAD_BONDING,294                "Error parsing bonding options: %r" % bondingOptions)295def validateVlanId(vlan):296    try:297        if not 0 <= int(vlan) <= MAX_VLAN_ID:298            raise ConfigNetworkError(ne.ERR_BAD_VLAN, 'vlan id out of range: %r, must be 0..%s' % (vlan, MAX_VLAN_ID))299    except ValueError:300        raise ConfigNetworkError(ne.ERR_BAD_VLAN, 'vlan id must be a number')301def _addNetworkValidation(_netinfo, bridge, vlan, bonding, nics, ipaddr, netmask, gateway, bondingOptions):302    if (vlan or bonding) and not nics:303        raise ConfigNetworkError(ne.ERR_BAD_PARAMS, 'vlan/bonding definition requires nics. got: %r'%(nics,))304     # Check bridge305    validateBridgeName(bridge)306    if bridge in _netinfo.networks:307        raise ConfigNetworkError(ne.ERR_USED_BRIDGE, 'Bridge already exists')308    # vlan309    if vlan:310        validateVlanId(vlan)311    if bonding:312        validateBondingName(bonding)313        if bondingOptions:314            validateBondingOptions(bonding, bondingOptions)315    elif bondingOptions:316        raise ConfigNetworkError(ne.ERR_BAD_BONDING, 'Bonding options specified without bonding')317    # Check ip, netmask, gateway318    if ipaddr:319        if not netmask:320            raise ConfigNetworkError(ne.ERR_BAD_ADDR, "Must specify netmask to configure ip for bridge")321        validateIpAddress(ipaddr)322        validateNetmask(netmask)323        if gateway:324            validateGateway(gateway)325    else:326        if netmask or gateway:327            raise ConfigNetworkError(ne.ERR_BAD_ADDR, "Specified netmask or gateway but not ip")328    # Check nics329    for nic in nics:330        if nic not in _netinfo.nics:331            raise ConfigNetworkError(ne.ERR_BAD_NIC, "unknown nic: %r"%nic)332        bridgesForNic = list(_netinfo.getNetworksForNic(nic))333        if bridgesForNic:334            assert len(bridgesForNic) == 1335            raise ConfigNetworkError(ne.ERR_USED_NIC, "nic %r is already bound to bridge %r"%(nic, bridgesForNic[0]))336    if bonding and not vlan:337        for nic in nics:338            vlansForNic = list(_netinfo.getVlansForNic(nic))339            if len(vlansForNic):340                raise ConfigNetworkError(ne.ERR_USED_NIC, 'nic %s already used by vlans %s' % ( nics, vlansForNic))341    # Bonding342    if bonding:343        bonding_ifaces = _netinfo.getNetworksAndVlansForBonding(bonding)344        if vlan:    # Make sure all connected interfaces (if any) are vlans345            for (bonding_bridge, bonding_vlan) in bonding_ifaces:346                if bonding_vlan is None:347                    raise ConfigNetworkError(ne.ERR_BAD_BONDING, 'bonding %r is already member of bridge %r'%(348                                             bonding, bonding_bridge ))349        else:350            bonding_ifaces = list(bonding_ifaces)351            if len(bonding_ifaces):352                raise ConfigNetworkError(ne.ERR_BAD_BONDING, 'bonding %r already has members: %r'%(bonding,bonding_ifaces))353    else:354        if len(nics) > 1:355            raise ConfigNetworkError(ne.ERR_BAD_BONDING, 'multiple nics require a bonding device')356    # Make sure nics don't have a different bonding357    # still relevant if bonding is None358    for nic in nics:359        bondingForNics = _netinfo.getBondingForNic(nic)360        if bondingForNics and bondingForNics != bonding:361            raise ConfigNetworkError(ne.ERR_USED_NIC, 'nic %s already enslaved to %s' % (nic, bondingForNics))362def addNetwork(bridge, vlan=None, bonding=None, nics=None, ipaddr=None, netmask=None, gateway=None,363               force=False, configWriter=None, bondingOptions=None, **options):364    nics = nics or ()365    _netinfo = NetInfo()366    # Validation367    if not _isTrue(force):368        logging.debug('validating bridge...')369        _addNetworkValidation(_netinfo, bridge, vlan=vlan, bonding=bonding, nics=nics,370                              ipaddr=ipaddr, netmask=netmask, gateway=gateway,371                              bondingOptions=bondingOptions)372    logging.info("Adding bridge %s with vlan=%s, bonding=%s, nics=%s. bondingOptions=%s, options=%s"373                 %(bridge, vlan, bonding, nics, bondingOptions, options))374    if configWriter is None:375        configWriter = ConfigWriter()376    configWriter.addBridge(bridge, ipaddr=ipaddr, netmask=netmask, gateway=gateway, **options)377    ifaceBridge = bridge378    if vlan:379        configWriter.addVlan(vlan, bonding or nics[0], bridge)380        # since we have vlan device, it is connected to the bridge. other381        # interfaces should be connected to the bridge through vlan, and not382        # directly.383        ifaceBridge = None384    if bonding:385        configWriter.addBonding(bonding, ifaceBridge, bondingOptions=bondingOptions)386        for nic in nics:387            configWriter.addNic(nic, bonding=bonding)388    else:389        for nic in nics:390            configWriter.addNic(nic, bridge=ifaceBridge)391    # take down nics that need to be changed392    vlanedIfaces = [v['iface'] for v in _netinfo.vlans.values()]393    if bonding not in vlanedIfaces:394        for nic in nics:395            if nic not in vlanedIfaces:396                ifdown(nic)397    ifdown(bridge)398    # nics must be activated in the same order of boot time to expose the correct399    # MAC address.400    for nic in nicSort(nics):401        ifup(nic)402    if bonding:403        ifup(bonding)404    if vlan:405        ifup((bonding or nics[0]) + '.' + vlan)406    if options.get('bootproto') == 'dhcp' and not utils.tobool(options.get('blockingdhcp')):407        # wait for dhcp in another thread, so vdsm won't get stuck (BZ#498940)408        t = threading.Thread(target=ifup, name='ifup-waiting-on-dhcp', args=(bridge,))409        t.daemon = True410        t.start()411    else:412        ifup(bridge)413def assertBridgeClean(bridge, vlan, bonding, nics):414    brifs = os.listdir('/sys/class/net/%s/brif/' % bridge)415    for nic in nics:416        try:417            brifs.remove(nic)418        except:419            pass420    if vlan:421        brif = (bonding or nics[0]) + '.' + vlan422    else:423        brif = bonding424    try:425        brifs.remove(brif)426    except:427        pass428    if brifs:429        raise ConfigNetworkError(ne.ERR_USED_BRIDGE, 'bridge %s has interfaces %s connected' % (bridge, brifs))430def showNetwork(bridge):431    _netinfo = NetInfo()432    if bridge not in _netinfo.networks:433        print "Bridge %r doesn't exist" % bridge434        return435    nics, vlan, bonding = _netinfo.getNicsVlanAndBondingForNetwork(bridge)436    print "Bridge %s: vlan=%s, bonding=%s, nics=%s" % (bridge, vlan, bonding, nics)437def listNetworks():438    _netinfo = NetInfo()439    print "Networks:", _netinfo.networks.keys()440    print "Vlans:", _netinfo.vlans.keys()441    print "Nics:", _netinfo.nics.keys()442    print "Bondings:", _netinfo.bondings.keys()443def delNetwork(bridge, force=False, configWriter=None, **options):444    _netinfo = NetInfo()445    validateBridgeName(bridge)446    if bridge not in _netinfo.networks:447        raise ConfigNetworkError(ne.ERR_BAD_BRIDGE, "Cannot delete bridge %r: It doesn't exist"%bridge)448    nics, vlan, bonding = _netinfo.getNicsVlanAndBondingForNetwork(bridge)449    logging.info("Removing bridge %s with vlan=%s, bonding=%s, nics=%s. options=%s"%(bridge, vlan, bonding, nics, options))450    if not _isTrue(force):451        if bonding:452            validateBondingName(bonding)453            if set(nics) != set(_netinfo.bondings[bonding]["slaves"]):454                raise ConfigNetworkError(ne.ERR_BAD_NIC, 'delNetwork: %s are not all nics enslaved to %s' % (nics, bonding))455        if vlan:456            #assertVlan(vlan)457            validateVlanId(vlan)458        assertBridgeClean(bridge, vlan, bonding, nics)459    if configWriter is None:460        configWriter = ConfigWriter()461    if bridge:462        ifdown(bridge)463        subprocess.call([constants.EXT_BRCTL, 'delbr', bridge])464    if vlan:465        vlandev = (bonding or nics[0]) + '.' + vlan466        ifdown(vlandev)467        subprocess.call([constants.EXT_VCONFIG, 'rem', vlandev], stderr=subprocess.PIPE)468    if bonding:469        if not bondingOtherUsers(bridge, vlan, bonding):470            ifdown(bonding)471    for nic in nics:472        if not nicOtherUsers(bridge, vlan, bonding, nic):473            ifdown(nic)474    for nic in nics:475        if nicOtherUsers(bridge, vlan, bonding, nic):476            continue477        configWriter.removeNic(nic)478    if bonding:479        if not bondingOtherUsers(bridge, vlan, bonding):480            configWriter.removeBonding(bonding)481    if vlan:482        configWriter.removeVlan(vlan, bonding or nics[0])483    if bridge:484        configWriter.removeBridge(bridge)485def clientSeen(timeout):486    start = time.time()487    while timeout >= 0:488        if os.stat(constants.P_VDSM_CLIENT_LOG).st_mtime > start:489            return True490        time.sleep(1)491        timeout -= 1492    return False493def editNetwork(oldBridge, newBridge, vlan=None, bonding=None, nics=None, **options):494    configWriter = ConfigWriter()495    try:496        delNetwork(oldBridge, configWriter=configWriter, **options)497        addNetwork(newBridge, vlan=vlan, bonding=bonding, nics=nics, configWriter=configWriter, **options)498    except:499        configWriter.restoreAtomicBackup()500        raise501    if utils.tobool(options.get('connectivityCheck', False)):502        if not clientSeen(int(options.get('connectivityTimeout', CONNECTIVITY_TIMEOUT_DEFAULT))):503            delNetwork(newBridge, force=True)504            configWriter.restoreAtomicBackup()505            return define.errCode['noConPeer']['status']['code']506def _validateNetworkSetup(networks={}, bondings={}, explicitBonding=False):507    _netinfo = NetInfo()508    # Step 1: Initial validation (validate names, existence of params, etc.)509    for network, networkAttrs in networks.iteritems():510        validateBridgeName(network)511        if networkAttrs.get('remove', False):512            if set(networkAttrs) - set(['remove']):513                raise ConfigNetworkError(ne.ERR_BAD_PARAMS, "Cannot specify any attribute when removing")514            if network not in _netinfo.networks:515                raise ConfigNetworkError(ne.ERR_BAD_BRIDGE, 'Cannot remove bridge %s: Doesn\'t exist' % network)516            continue517        vlan = networkAttrs.get('vlan', None)518        ipaddr = networkAttrs.get('ipaddr', None)519        netmask = networkAttrs.get('netmask', None)520        gateway = networkAttrs.get('gateway', None)521        if vlan:522            validateVlanId(vlan)523        # Check ip, netmask, gateway524        if ipaddr:525            if not netmask:526                raise ConfigNetworkError(ne.ERR_BAD_ADDR, "Must specify netmask to configure ip for bridge")527            validateIpAddress(ipaddr)528            validateNetmask(netmask)529            if gateway:530                validateGateway(gateway)531        else:532            if netmask or gateway:533                raise ConfigNetworkError(ne.ERR_BAD_ADDR, "Specified netmask or gateway but not ip")534        # check nic or bonding535        nic = networkAttrs.get('nic', None)536        bonding = networkAttrs.get('bonding', None)537        if nic and bonding:538            raise ConfigNetworkError(ne.ERR_BAD_PARAMS, "Don't specify both nic and bonding")539        if not nic and not bonding:540            raise ConfigNetworkError(ne.ERR_BAD_PARAMS, "Must specify either nic or bonding")541        if nic and nic not in _netinfo.nics:542            raise ConfigNetworkError(ne.ERR_BAD_NIC, "unknown nic: %r"%nic)543    for bonding, bondingAttrs in bondings.iteritems():544        validateBondingName(bonding)545        if 'options' in bondingAttrs:546            validateBondingOptions(bonding, bondingAttrs['options'])547        if bondingAttrs.get('remove', False):548            if bonding not in _netinfo.bondings:549                raise ConfigNetworkError(ne.ERR_BAD_BONDING, 'Cannot remove bonding %s: Doesn\'t exist' % bonding)550            continue551        nics = bondingAttrs.get('nics', None)552        if not nics:553            raise ConfigNetworkError(ne.ERR_BAD_PARAMS, "Must specify nics for bonding")554        if not set(nics).issubset(set(_netinfo.nics)):555            raise ConfigNetworkError(ne.ERR_BAD_NIC, "Unknown nics in: %r"%list(nics))556    # Step 2: Make sure we have complete information about the Setup, more validation557    # (if explicitBonding==False we complete the missing information ourselves, else we raise an exception)558    nics = defaultdict(lambda: {'networks':[], 'bonding':None})559    for network, networkAttrs in networks.iteritems():560        if networkAttrs.get('remove', False):561            continue562        if 'bonding' in networkAttrs:563            assert 'nic' not in networkAttrs564            bonding = networkAttrs['bonding']565            if bonding not in bondings:566                if explicitBonding:567                    raise ConfigNetworkError(ne.ERR_BAD_PARAMS, "Network %s requires unspecified bonding %s"%(568                                             network, bonding))569                # fill in bonding info570                bondings[bonding] =  {'nics':_netinfo.bondings[bonding]['slaves']}571            if '_networks' not in bondings[bonding]:572                bondings[bonding]['_networks'] = []573            bondings[bonding]['_networks'].append( network )574        else:575            assert 'nic' in networkAttrs576            nics[networkAttrs['nic']]['networks'].append( network )577    for bonding, bondingAttrs in bondings.iteritems():578        if bondingAttrs.get('remove', False):579            continue580        connectedNetworks = _netinfo.getNetworksForNic(bonding)581        for network in connectedNetworks:582            if network not in networks:583                if explicitBonding:584                    raise ConfigNetworkError(ne.ERR_BAD_PARAMS, "Bonding %s is associated with unspecified network %s"%(585                                             bonding, network))586                # fill in network info587                _, vlan, bonding2 = _netinfo.getNicsVlanAndBondingForNetwork(network)588                assert bonding == bonding2589                networks[network] = {'bonding': bonding, 'vlan':vlan}590        for nic in bondingAttrs['nics']:591            if nics[nic]['bonding']:592                raise ConfigNetworkError(ne.ERR_BAD_BONDING, "Nic %s is attached to two different bondings in setup: %s, %s"%(593                                         nic, bonding, nics[nic]['bonding']))594            nics[nic]['bonding'] = bonding595    # At this point the state may be contradictory.596    # Step 3: Apply removals (We're not iterating because we change the dictionary size)597    queue = []598    for network, networkAttrs in networks.items():599        if networkAttrs.get('remove', False):600            del networks[network]601        else:602            queue.append(('network', network, networkAttrs))603    for bonding, bondingAttrs in bondings.items():604        if bondingAttrs.get('remove', False):605            del bondings[bonding]606        else:607            queue.append(('bonding', bonding, bondingAttrs))608    # Step 4: Verify Setup609    for nic, nicAttrs in nics.iteritems():610        if nicAttrs['networks'] and nicAttrs['bonding']:611            raise ConfigNetworkError(ne.ERR_USED_NIC, "Setup attached both network and bonding to nic %s"%(nic))612        if len(networks) > 1:613            for network, networkAttrs in networks.iteritems():614                if not networkAttrs.get('vlan', None):615                    raise ConfigNetworkError(ne.ERR_USED_NIC,616                            "Setup attached more than one network to nic %s, some of which aren't vlans"%(nic))617    for bonding, bondingAttrs in bondings.iteritems():618        networks = bondingAttrs['_networks']619        if len(networks) > 1:620            for network, networkAttrs in networks.iteritems():621                if not networkAttrs.get('vlan', None):622                    raise ConfigNetworkError(ne.ERR_BAD_BONDING,623                            "Setup attached more than one network to bonding %s, some of which aren't vlans"%(bonding))624def setupNetworks(networks={}, bondings={}, **options):625    """Add/Edit/Remove configuration for networks and bondings.626    Params:627        networks - dict of key=network, value=attributes628                   where 'attributes' is a dict with the following optional items:629                        vlan=<id>630                        bonding="<name>" | nic="<name>"631                        (bonding and nics are mutually exclusive)632                        ipaddr="<ip>"633                        netmask="<ip>"634                        gateway="<ip>"635                        bootproto="..."636                        delay="..."637                        onboot="yes"|"no"638                        (other options will be passed to the config file AS-IS)639                        -- OR --640                        remove=True (other attributes can't be specified)641        bondings - dict of key=bonding, value=attributes642                   where 'attributes' is a dict with the following optional items:643                        nics=["<nic1>" , "<nic2>", ...]644                        options="<bonding-options>"645                        -- OR --646                        remove=True (other attributes can't be specified)647        options - dict of options, such as:648                        force=0|1649                        connectivityCheck=0|1650                        connectivityTimeout=<int>651                        explicitBonding=0|1652    Notes:653        Bondings are removed when they change state from 'used' to 'unused'.654        By default, if you edit a network that is attached to a bonding, it's not655        necessary to re-specify the bonding (you need only to note the attachement656        in the network's attributes). Similarly, if you edit a bonding, it's not657        necessary to specify its networks.658        However, if you specify the 'explicitBonding' option as true, the function659        will expect you to specify all networks that are attached to a specified660        bonding, and vice-versa, the bonding attached to a specified network.661    """662    logger = logging.getLogger("setupNetworks")663    try:664        _netinfo = NetInfo()665        configWriter = ConfigWriter()666        networksAdded = []667        #bondingNetworks = {}   # Reminder TODO668        logger.info("Setting up network")669        logger.debug("Setting up network according to configuration: networks:%r, bondings:%r, options:%r" % (networks, bondings, options))670        force = options.get('force', False)671        if not _isTrue(force):672            logging.debug("Validating configuration")673            _validateNetworkSetup(dict(networks), dict(bondings), explicitBonding=options.get('explicitBonding', False))674        logger.debug("Applying...")675        try:676            for network, networkAttrs in networks.items():677                if networkAttrs.pop('remove', False):678                    assert not networkAttrs679                    logger.debug('Removing network %r'%network)680                    delNetwork(network, force=force)681                    continue682                if network in _netinfo.networks:683                    delNetwork(network, force=force)684                else:685                    networksAdded.append(network)686                d = dict(networkAttrs)687                if 'bonding' in d:688                    d['nics'] = bondings[d['bonding']]['nics']689                    d['bondingOptions'] = bondings[d['bonding']].get('options', None)690                else:691                    d['nics'] = [d.pop('nic')]692                d['force'] = force693                logger.debug('Adding network %r'%network)694                addNetwork(network, **d)695        except:696            configWriter.restoreAtomicBackup()697            raise698        if utils.tobool(options.get('connectivityCheck', True)):699            logger.debug('Checking connectivity...')700            if not clientSeen(int(options.get('connectivityTimeout', CONNECTIVITY_TIMEOUT_DEFAULT))):701                logger.info('Connectivity check failed, rolling back')702                for bridge in networksAdded:703                    delNetwork(bridge, force=True)704                configWriter.restoreAtomicBackup()705                raise ConfigNetworkError(ne.ERR_LOST_CONNECTION, 'connectivity check failed')706    except Exception, e:707        # SuperVdsm eats the error, so let's print it ourselves708        logger.error(e, exc_info=True)709        raise710def setSafeNetworkConfig():711    """Declare current network configuration as 'safe'"""712    subprocess.Popen([constants.EXT_VDSM_STORE_NET_CONFIG])713def usage():714    print """Usage:715    ./configNetwork.py add bridge <attributes> <options>716                       edit oldBridge newBridge <attributes> <options>717                       del bridge <options>718                       setup bridge [None|attributes] [++ bridge [None|attributes] [++ ...]] [:: <options>]719                       attributes = [vlan=...] [bonding=...] [nics=<nic1>,...]720                       options = [Force=<True|False>] ...721    """722def _parseKwargs(args):723    return dict(arg.split('=', 1) for arg in args)724def main():725    if len(sys.argv) <= 1:726        usage()727        raise ConfigNetworkError(ne.ERR_BAD_PARAMS, "No action specified")728    if sys.argv[1] == 'list':729        listNetworks()730        return731    if len(sys.argv) <= 2:732        usage()733        raise ConfigNetworkError(ne.ERR_BAD_PARAMS, "No action specified")734    if sys.argv[1] == 'add':735        bridge = sys.argv[2]736        kwargs = _parseKwargs(sys.argv[3:])737        if 'nics' in kwargs:738            kwargs['nics'] = kwargs['nics'].split(',')739        addNetwork(bridge, **kwargs)740    elif sys.argv[1] == 'del':741        bridge = sys.argv[2]742        kwargs = _parseKwargs(sys.argv[3:])743        if 'nics' in kwargs:744            kwargs['nics'] = kwargs['nics'].split(',')745        delNetwork(bridge, **kwargs)746    elif sys.argv[1] == 'edit':747        oldBridge = sys.argv[2]748        newBridge = sys.argv[3]749        kwargs = _parseKwargs(sys.argv[4:])750        if 'nics' in kwargs:751            kwargs['nics'] = kwargs['nics'].split(',')752        editNetwork(oldBridge, newBridge, **kwargs)753    elif sys.argv[1] == 'setup':754        batchCommands, options = utils.listSplit( sys.argv[2:], '::', 1 )755        d = {}756        for batchCommand in utils.listSplit( batchCommands, '++' ):757            d[batchCommand[0]] = _parseKwargs(batchCommand[1:]) or None758        setupNetworks(d, **_parseKwargs(options))759    elif sys.argv[1] == 'show':760        bridge = sys.argv[2]761        kwargs = _parseKwargs(sys.argv[3:])762        showNetwork(bridge, **kwargs)763    else:764        usage()765        raise ConfigNetworkError(ne.ERR_BAD_PARAMS, "Unknown action specified")766if __name__ == '__main__':767    logging.basicConfig(level=logging.INFO)768    try:769        main()770    except ConfigNetworkError, e:771        traceback.print_exc()772        print e.message773        sys.exit(e.errCode)...guestcust_util.py
Source:guestcust_util.py  
...55        nics = fp.read(NICS_SIZE)56    return nics57# This will send a RPC command to the underlying VMware Virtualization platform58# and enable nics.59def enable_nics(nics):60    if not nics:61        logger.warning("No Nics found")62        return63    enableNicsWaitRetries = 564    enableNicsWaitCount = 565    enableNicsWaitSeconds = 166    for attempt in range(0, enableNicsWaitRetries):67        logger.debug("Trying to connect interfaces, attempt %d", attempt)68        (out, _err) = set_customization_status(69            GuestCustStateEnum.GUESTCUST_STATE_RUNNING,70            GuestCustEventEnum.GUESTCUST_EVENT_ENABLE_NICS,71            nics)72        if not out:73            time.sleep(enableNicsWaitCount * enableNicsWaitSeconds)...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
