#!/usr/bin/python3 """install.py - copy files from to_system into system directories - set host name / network settings from aputools/servercfg file """ import os import filecmp import shutil from glob import glob from ipaddress import IPv4Interface from configparser import ConfigParser from os.path import join, getmtime, exists, basename os.chdir('/root/aputools/to_system') DEL = '__to_delete__' CFGPATH = '/root/aputools/servercfg/%s_%6.6x.cfg' TEMPLATE_CFG = """[NETWORK] enp1s0=192.168.127.1/24 enp2s0=192.168.2.1/24 enp3s0=192.168.3.1/24 enp4s0=dhcp [ROUTER] 3001=192.168.127.254:3001 """ def write_when_new(filename, content, doit): if not content.endswith('\n'): content += '\n' with open(filename) as fil: old = fil.read() if old == content: return False if doit: with open(filename, 'w') as fil: fil.write(content) return True def create_if(name, cfg, mac): result = dict( TYPE='Ethernet', NAME=name, DEVICE=name, BOOTPROTO='none', ONBOOT='yes', PROXY_METHOD='none', BROWSER_ONLY='no', IPV4_FAILURE_FATAL='yes', IPV6INIT='no') if cfg == 'off': result['ONBOOT']='no' elif cfg == 'dhcp': result['BOOTPROTO']='dhcp' else: interface = IPv4Interface(cfg) if '/' not in cfg: if interface < IPv4Interface('128.0.0.0'): cfg += '/8' elif interface < IPv4Interface('192.0.0.0'): cfg += '/16' else: cfg += '/24' interface = IPv4Interface(cfg) result['IPADDR'], result['NETMASK'] = interface.with_netmask.split('/') _, result['PREFIX'] = interface.with_prefixlen.split('/') return result def walk(action): for dirpath, _, files in os.walk('.'): syspath = dirpath[1:] # remove leading '.' action.dirpath = dirpath action.syspath = syspath if files: match, mismatch, missing = filecmp.cmpfiles(dirpath, syspath, files) if mismatch: newer = [f for f in mismatch if getmtime(join(syspath, f)) > getmtime(join(dirpath, f))] if newer: action.newer(newer) if len(newer) < len(mismatch): newer = set(newer) action.older([f for f in mismatch if f not in newer]) if missing: if DEL in missing: missing.remove(DEL) with open(join(dirpath, DEL)) as fil: to_delete = [] for f in fil: f = f.strip() if f and exists(join(syspath, f)): if exists(join(dirpath, f)): print('ERROR: %s in %s, but also in repo -> ignored' % (f, DEL)) else: to_delete.append(f) action.delete(to_delete) if missing: action.missing(missing) class Show: dirty = False def show(self, title, files): self.dirty = True print('%s %s:\n %s' % (title, self.syspath, ' '.join(files))) def newer(self, files): self.show('get from', files) def older(self, files): self.show('replace in', files) def missing(self, files): self.show('install in', files) def delete(self, files): self.show('remove from', files) class Do: def newer(self, files): for file in files: shutil.copy(join(self.syspath, file), join(self.dirpath, file)) def older(self, files): for file in files: shutil.copy(join(self.dirpath, file), join(self.syspath, file)) def missing(self, files): self.older(files) def delete(self, files): for file in files: os.remove(join(self.syspath, file)) IFNAMES = ['enp%ds0' % i for i in range(1,5)] def network(doit): netaddr_dict = {} for ifname in IFNAMES: with open('/sys/class/net/%s/address' % ifname) as f: netaddr_dict[ifname] = f.read().strip().lower() netaddr = netaddr_dict[IFNAMES[0]] apuid = int(''.join(netaddr.split(':')[-3:]), 16) & 0xfffffc cfgfile = None cfgfiles = [] for i in range(4): # goodie: look for mac addresses of all 4 ports cfgfiles += glob(CFGPATH % ('*', apuid + i)) with open('/etc/hostname') as f: hostname = f.read().strip() if not cfgfiles: print('no cfg file found for %s' % hostname) newname = input('enter host name: ') if not newname: print('no hostname given') return False cfgfile = CFGPATH % (newname, apuid) with open(cfgfile, 'w') as f: f.write(TEMPLATE_CFG) elif len(cfgfiles) > 1: print('ERROR: ambiguous cfg files: %s' % ', '.join(cfgfiles)) else: cfgfile = cfgfiles[0] if cfgfile != CFGPATH % (hostname, apuid): if doit: os.system('sh ../sethostname.sh') else: if cfgfile: print('replace host name %r by %r' % (hostname, basename(cfgfile).rpartition('_')[0])) show.dirty = True if cfgfile is None: return False ifname = '' parser = ConfigParser() try: parser.read(cfgfile) network = dict(parser['NETWORK']) for ifname in IFNAMES: content = create_if(ifname, network.get(ifname, 'off'), netaddr_dict[ifname]) content = '\n'.join('%s=%s' % kv for kv in content.items()) todo = write_when_new('/etc/sysconfig/network-scripts/ifcfg-%s' % ifname, content, doit) if todo: print('change ', ifname) show.dirty = True except Exception as e: print('ERROR: can not handle %s %s: %r' % (hostname, ifname, e)) return False return True print('---') show = Show() result = network(False) walk(show) if not result: print('fix first above errors') elif show.dirty: print('---') answer = input('do above? ') if answer.lower().startswith('y'): network(True) walk(Do()) else: print('nothing to do')