#!/usr/bin/python3 """install.py copy files from to_system into system directories """ 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.cfg' 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 % ('*_%6.6x' % (apuid + i))) if not cfgfiles: print('no cfg file found for %s' % netaddr) elif len(cfgfiles) > 1: print('ERROR: ambiguous cfg files: %s' % ', '.join(cfgfiles)) else: cfgfile = cfgfiles[0] for ntry in range(1 + bool(doit)): with open('/etc/hostname') as f: hostname = f.read().strip() if cfgfile == CFGPATH % ('%s_%6.6x' % (hostname, apuid)): break if doit: if ntry == 0: os.system('sh sethostname.sh') else: print('ERROR: can not set host name') return False else: if cfgfile: print('host name does not match %r -> %r' % (hostname, basename(cfgfile).rpartition('_')[0])) show.dirty = True break 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')