fix issues with apu
rework: create utils.BoxInfo
This commit is contained in:
@ -1,10 +1,10 @@
|
|||||||
[NETWORK]
|
[NETWORK]
|
||||||
; please refer to README.md for help
|
; please refer to README.md for help
|
||||||
eth0=192.168.127.254
|
eth0=wan
|
||||||
eth1=192.168.2.1
|
eth1=192.168.2.2
|
||||||
eth2=192.168.3.5
|
eth2=192.168.3.3
|
||||||
eth3=dhcp
|
eth3=192.168.127.254
|
||||||
|
|
||||||
[ROUTER]
|
[ROUTER]
|
||||||
; please refer to README.md for help
|
; please refer to README.md for help
|
||||||
5900=192.168.2.1
|
3001=192.168.127.254:3001
|
122
install.py
122
install.py
@ -20,33 +20,26 @@ from glob import glob
|
|||||||
from ipaddress import IPv4Interface
|
from ipaddress import IPv4Interface
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
from os.path import join, getmtime, exists, basename
|
from os.path import join, getmtime, exists, basename
|
||||||
from utils import get_config
|
from utils import BoxInfo
|
||||||
|
|
||||||
if os.geteuid() != 0:
|
if os.geteuid() != 0:
|
||||||
exit("You need to have root privileges to run this script.\nPlease try again, this time using 'sudo'. Exiting.")
|
exit("You need to have root privileges to run this script.\nPlease try again, this time using 'sudo'. Exiting.")
|
||||||
|
|
||||||
TOOLS = '/home/l_samenv/boxtools'
|
TOOLS = BoxInfo.TOOLS
|
||||||
|
|
||||||
BOX_TYPES = {
|
|
||||||
'00:0d:b9': 'apu', # bare apu or control box
|
|
||||||
'b8:27:eb': 'cm3', # iono pi
|
|
||||||
'd8:3a:dd': 'cm4', # dual-eth-rpi
|
|
||||||
}
|
|
||||||
|
|
||||||
more_info = False
|
more_info = False
|
||||||
|
|
||||||
DEL = '__to_delete__'
|
DEL = '__to_delete__'
|
||||||
CFGPATH = f'{TOOLS}/cfg/%s_%6.6x.cfg'
|
|
||||||
STARTUP_TEXT = f'{TOOLS}/startup_display.txt'
|
STARTUP_TEXT = f'{TOOLS}/startup_display.txt'
|
||||||
|
|
||||||
COMMENT = "; please refer to README.md for help"
|
COMMENT = "; please refer to README.md for help"
|
||||||
|
|
||||||
CONFIG_TEMPLATE = f"""[NETWORK]
|
CONFIG_TEMPLATE = f"""[NETWORK]
|
||||||
{COMMENT}
|
{COMMENT}
|
||||||
eth0=192.168.127.254
|
eth0=wan
|
||||||
eth1=192.168.2.2
|
eth1=192.168.2.2
|
||||||
eth2=192.168.3.3
|
eth2=192.168.3.3
|
||||||
eth3=dhcp
|
eth3=192.168.127.254
|
||||||
|
|
||||||
[ROUTER]
|
[ROUTER]
|
||||||
{COMMENT}
|
{COMMENT}
|
||||||
@ -115,32 +108,10 @@ pip_requirements = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
net_addr = {} # dict <if name> of <ethernet address>
|
box = BoxInfo()
|
||||||
dhcp_server_cfg = [] # configuration for dhcp
|
dhcp_server_cfg = []
|
||||||
main_info = { # info to be determined depending on cfg
|
|
||||||
'ifname': '', # name of interface of wan (dhcp) port
|
|
||||||
'addr': '', # addr of wan port
|
|
||||||
'hostname': socket.gethostname() # effective or given host name
|
|
||||||
}
|
|
||||||
|
|
||||||
change_if_names = False
|
TO_SYSTEM = f'{TOOLS}/to_{box.typ}'
|
||||||
|
|
||||||
for netif in os.scandir('/sys/class/net'):
|
|
||||||
if netif.name != 'lo': # do not consider loopback interface
|
|
||||||
with open(os.path.join(netif.path, 'address')) as f:
|
|
||||||
addr = f.read().strip().lower()
|
|
||||||
n = netif.name
|
|
||||||
if n.startswith('enp'):
|
|
||||||
change_if_names = True
|
|
||||||
n = f'eth{int(n[3]) - 1}'
|
|
||||||
net_addr[n] = addr
|
|
||||||
|
|
||||||
sorted_if = sorted(net_addr)
|
|
||||||
boxaddr = net_addr[sorted_if[0]]
|
|
||||||
boxid = int(''.join(boxaddr.split(':')[-3:]), 16) & 0xffffff
|
|
||||||
boxtype = BOX_TYPES.get(boxaddr[:8])
|
|
||||||
|
|
||||||
TO_SYSTEM = f'{TOOLS}/to_{boxtype}'
|
|
||||||
if not exists(TO_SYSTEM):
|
if not exists(TO_SYSTEM):
|
||||||
TO_SYSTEM = f'{TOOLS}/to_system'
|
TO_SYSTEM = f'{TOOLS}/to_system'
|
||||||
os.chdir(TO_SYSTEM)
|
os.chdir(TO_SYSTEM)
|
||||||
@ -172,8 +143,8 @@ def router(**opts):
|
|||||||
|
|
||||||
def display_update(cfg):
|
def display_update(cfg):
|
||||||
text = '\n'.join(cfg.get('startup_text', '').split('|')[:3])
|
text = '\n'.join(cfg.get('startup_text', '').split('|')[:3])
|
||||||
text = text.replace('HOST', main_info['hostname']) \
|
text = text.replace('HOST', box.hostname) \
|
||||||
.replace('ADDR', main_info['addr']) + '\n'
|
.replace('ADDR', box.get_macaddr()) + '\n'
|
||||||
if write_when_new(STARTUP_TEXT, text):
|
if write_when_new(STARTUP_TEXT, text):
|
||||||
print('change startup text')
|
print('change startup text')
|
||||||
if doit:
|
if doit:
|
||||||
@ -285,10 +256,10 @@ def create_if(name, cfg):
|
|||||||
if cfg == 'off':
|
if cfg == 'off':
|
||||||
result = None
|
result = None
|
||||||
elif cfg.startswith('wan') or cfg == 'dhcp':
|
elif cfg.startswith('wan') or cfg == 'dhcp':
|
||||||
if main_info.get('mainif', name) != name:
|
if box.main_if != name:
|
||||||
|
print(box.main_if, name)
|
||||||
raise ValueError('can not have more than one WAN/DHCP port')
|
raise ValueError('can not have more than one WAN/DHCP port')
|
||||||
main_info['mainif'] = name
|
box.main_if = name
|
||||||
main_info['addr'] = net_addr[name]
|
|
||||||
# default: all <= 192.0.0.0
|
# default: all <= 192.0.0.0
|
||||||
# others have to be added explicitly
|
# others have to be added explicitly
|
||||||
dhcp_server_cfg.append(('0.0.0.0/128.0.0.0', []))
|
dhcp_server_cfg.append(('0.0.0.0/128.0.0.0', []))
|
||||||
@ -407,68 +378,54 @@ class Do(Walker):
|
|||||||
|
|
||||||
|
|
||||||
def handle_config():
|
def handle_config():
|
||||||
cfgfile = None
|
|
||||||
cfgfiles = []
|
|
||||||
dhcp_server_cfg.clear()
|
dhcp_server_cfg.clear()
|
||||||
for file in glob(CFGPATH % ('*', boxid)):
|
cfgfile = box.cfgfile
|
||||||
cfgfiles.append(file)
|
newhostname = box.hostname
|
||||||
if boxtype == 'apu':
|
if not cfgfile:
|
||||||
for i in [1, 2, 3]:
|
template = CONFIG_TEMPLATE
|
||||||
bad = glob(CFGPATH % ('*', boxid+i))
|
if box.typ == 'apu':
|
||||||
if bad:
|
# determine if display is present
|
||||||
print('cfg files found with bad apu id (use net addr of leftmost plug)')
|
disp = serial.Serial('/dev/ttyS1', baudrate=115200, timeout=1)
|
||||||
print(bad)
|
disp.write(b'\x1b\x1b\x01\xf3')
|
||||||
return False
|
display_available = disp.read(8)[0:4] == b'\x1b\x1b\x05\xf3'
|
||||||
newhostname = main_info['hostname']
|
if display_available:
|
||||||
if not cfgfiles:
|
typ = 'controlbox'
|
||||||
# determine if display is present
|
template = CONTROLBOX_TEMPLATE
|
||||||
disp = serial.Serial('/dev/ttyS1', baudrate=115200, timeout=1)
|
else:
|
||||||
disp.write(b'\x1b\x1b\x01\xf3')
|
typ = 'bare apu'
|
||||||
display_available = disp.read(8)[0:4] == b'\x1b\x1b\x05\xf3'
|
|
||||||
if display_available:
|
|
||||||
# leftmost interface labelled 'eth0'
|
|
||||||
# main_info['mainif'] = sorted_if[0]
|
|
||||||
typ = 'controlbox'
|
|
||||||
template = CONTROLBOX_TEMPLATE
|
|
||||||
else:
|
else:
|
||||||
# rightmost interface
|
typ = 'rpi'
|
||||||
# main_info['mainif'] = sorted_if[-1]
|
print('no cfg file found for this', typ,
|
||||||
typ = 'bare apu'
|
f'with id {box.id:06x} (hostname={box.hostname})')
|
||||||
template = CONFIG_TEMPLATE
|
|
||||||
print('no cfg file found for this', typ, f'with id {boxid:%6.6x} (hostname={hostname})')
|
|
||||||
newhostname = input('enter host name: ')
|
newhostname = input('enter host name: ')
|
||||||
if not newhostname:
|
if not newhostname:
|
||||||
print('no hostname given')
|
print('no hostname given')
|
||||||
return False
|
return False
|
||||||
cfgfile = CFGPATH % (newhostname, boxid)
|
cfgfile = BoxInfo.CFGPATH % (newhostname, box.id)
|
||||||
with open(cfgfile, 'w') as f:
|
with open(cfgfile, 'w') as f:
|
||||||
f.write(template)
|
f.write(template)
|
||||||
elif len(cfgfiles) > 1:
|
if cfgfile != BoxInfo.CFGPATH % (newhostname, box.id):
|
||||||
print('ERROR: ambiguous cfg files: %s' % ', '.join(cfgfiles))
|
|
||||||
else:
|
|
||||||
cfgfile = cfgfiles[0]
|
|
||||||
if cfgfile != CFGPATH % (newhostname, boxid):
|
|
||||||
if cfgfile:
|
if cfgfile:
|
||||||
newhostname = basename(cfgfile).rpartition('_')[0]
|
newhostname = basename(cfgfile).rpartition('_')[0]
|
||||||
if doit:
|
if doit:
|
||||||
os.system('sh sethostname.sh')
|
os.system('sh sethostname.sh')
|
||||||
else:
|
else:
|
||||||
if cfgfile:
|
if cfgfile:
|
||||||
print('replace host name %r by %r' % (main_info['hostname'], newhostname))
|
print('replace host name %r by %r' % (box.hostname, newhostname))
|
||||||
show.dirty = True
|
show.dirty = True
|
||||||
main_info['hostname'] = newhostname
|
config = box.read_config()
|
||||||
|
box.hostname = newhostname
|
||||||
if cfgfile is None:
|
if cfgfile is None:
|
||||||
return False
|
return False
|
||||||
to_start = {}
|
to_start = {}
|
||||||
ifname = ''
|
ifname = ''
|
||||||
config = get_config()
|
|
||||||
try:
|
try:
|
||||||
netcfg = config['NETWORK']
|
netcfg = config['NETWORK']
|
||||||
for name in netcfg:
|
for name in netcfg:
|
||||||
if name not in net_addr:
|
if name not in box.macaddr:
|
||||||
print(f'{name} is not a valid network interface name')
|
print(f'{name} is not a valid network interface name')
|
||||||
raise RuntimeError('network interface name system does not match')
|
raise RuntimeError('network interface name system does not match')
|
||||||
for ifname in net_addr:
|
for ifname in box.macaddr:
|
||||||
content = create_if(ifname, netcfg.get(ifname, 'off'))
|
content = create_if(ifname, netcfg.get(ifname, 'off'))
|
||||||
# content = '\n'.join('%s=%s' % kv for kv in content.items())
|
# content = '\n'.join('%s=%s' % kv for kv in content.items())
|
||||||
todo = write_when_new(f'/etc/network/interfaces.d/{ifname}', content)
|
todo = write_when_new(f'/etc/network/interfaces.d/{ifname}', content)
|
||||||
@ -517,7 +474,7 @@ def handle_config():
|
|||||||
#with open(cfgfile, 'w') as f:
|
#with open(cfgfile, 'w') as f:
|
||||||
# f.write('\n'.join(content))
|
# f.write('\n'.join(content))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print('ERROR: can not handle %s %s: %r' % (main_info['hostname'], ifname, e))
|
print('ERROR: can not handle %s %s: %r' % (box.hostname, ifname, e))
|
||||||
raise
|
raise
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -573,14 +530,15 @@ def handle_config():
|
|||||||
unix_cmd('systemctl restart %s' % service)
|
unix_cmd('systemctl restart %s' % service)
|
||||||
unix_cmd('systemctl enable %s' % service)
|
unix_cmd('systemctl enable %s' % service)
|
||||||
|
|
||||||
if change_if_names:
|
if box.change_if_names:
|
||||||
|
print('interface name system has to be changed from enp*s0 to eth*')
|
||||||
with open('/etc/default/grub') as f:
|
with open('/etc/default/grub') as f:
|
||||||
content = f.read()
|
content = f.read()
|
||||||
|
|
||||||
prev = 'GRUB_CMDLINE_LINUX_DEFAULT="quiet"'
|
prev = 'GRUB_CMDLINE_LINUX_DEFAULT="quiet"'
|
||||||
repl = 'GRUB_CMDLINE_LINUX_DEFAULT="quiet net.ifnames=0"'
|
repl = 'GRUB_CMDLINE_LINUX_DEFAULT="quiet net.ifnames=0"'
|
||||||
newcontent = content.replace(prev, repl)
|
newcontent = content.replace(prev, repl)
|
||||||
if repl not in newcontent:
|
if repl not in content:
|
||||||
write_when_new('/etc/default/grub', newcontent)
|
write_when_new('/etc/default/grub', newcontent)
|
||||||
unix_cmd('update-grub')
|
unix_cmd('update-grub')
|
||||||
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
ETHNAME=$(cat /sys/class/net/eth0/address)
|
ETHNAME=$(cat /sys/class/net/eth0/address)
|
||||||
ETHNAME=${ETHNAME//:/}
|
ETHNAME=${ETHNAME//:/}
|
||||||
APUID=${ETHNAME: -6}
|
BOXID=${ETHNAME: -6}
|
||||||
FOUND="$(shopt -s nullglob; echo /home/l_samenv/boxtools/cfg/*_$APUID.cfg)"
|
FOUND="$(shopt -s nullglob; echo /home/l_samenv/boxtools/cfg/*_$BOXID.cfg)"
|
||||||
if [ -z "$FOUND" ]; then
|
if [ -z "$FOUND" ]; then
|
||||||
HOSTNAME=apu$APUID
|
HOSTNAME=box$BOXID
|
||||||
else
|
else
|
||||||
FOUND=$(basename ${FOUND[0]}) # remove directory part
|
FOUND=$(basename ${FOUND[0]}) # remove directory part
|
||||||
HOSTNAME=${FOUND%%.*} # remove extension
|
HOSTNAME=${FOUND%%.*} # remove extension
|
||||||
if [ $HOSTNAME != "apu$APUID" ]; then
|
if [ $HOSTNAME != "apu$BOXID" ]; then
|
||||||
HOSTNAME=${HOSTNAME%_*}
|
HOSTNAME=${HOSTNAME%_*}
|
||||||
fi
|
fi
|
||||||
echo "hostname $HOSTNAME"
|
echo "hostname $HOSTNAME"
|
||||||
|
72
utils.py
72
utils.py
@ -14,37 +14,51 @@ else:
|
|||||||
os.system(cmd)
|
os.system(cmd)
|
||||||
|
|
||||||
|
|
||||||
def get_config(section=None):
|
class BoxInfo:
|
||||||
"""get content of box configuration
|
TOOLS = '/home/l_samenv/boxtools'
|
||||||
|
CFGPATH = f'{TOOLS}/cfg/%s_%06x.cfg'
|
||||||
|
BOX_TYPES = {
|
||||||
|
'00:0d:b9': 'apu', # bare apu or control box
|
||||||
|
'b8:27:eb': 'cm3', # iono pi
|
||||||
|
'd8:3a:dd': 'cm4', # dual-eth-rpi
|
||||||
|
}
|
||||||
|
|
||||||
:param section: if not None, return only given section
|
def __init__(self):
|
||||||
:return: configuration as dict
|
self.id = None
|
||||||
"""
|
self.typ = None
|
||||||
parser = ConfigParser()
|
self.hostname = socket.gethostname()
|
||||||
cfgfiles = glob('/home/l_samenv/boxtools/cfg/%s_*.cfg' % socket.gethostname())
|
self.change_if_names = False
|
||||||
if not cfgfiles:
|
self.cfgfile = None
|
||||||
# look by id
|
self.config = None
|
||||||
boxid = None
|
self.macaddr = {}
|
||||||
for ifname in ('enp1s0', 'eth0'):
|
self.main_if = None
|
||||||
try:
|
for ifdev in glob('/sys/class/net/*/address'):
|
||||||
with open(f'/sys/class/net/{ifname}/address') as f:
|
ifname = ifdev.split('/')[-2]
|
||||||
addr = f.read().strip().lower()
|
if ifname == 'lo': # do not consider loopback interface
|
||||||
except FileNotFoundError:
|
|
||||||
continue
|
continue
|
||||||
boxid = int(''.join(addr.split(':')[-3:]), 16) & 0xffffff
|
if ifname.startswith('enp'):
|
||||||
break
|
self.change_if_names = True
|
||||||
if boxid:
|
ifname = f'eth{int(ifname[3]) - 1}'
|
||||||
cfgfiles = glob('/home/l_samenv/boxtools/cfg/*_%6.6x.cfg' % boxid)
|
print(ifname)
|
||||||
if len(cfgfiles) != 1:
|
with open(ifdev) as f:
|
||||||
raise ValueError('there must be one and only one single cfgfile %r' % cfgfiles)
|
self.macaddr[ifname] = addr = f.read().strip().lower()
|
||||||
parser.read(cfgfiles[0])
|
if ifname in ('eth0', 'enp1s0'):
|
||||||
try:
|
self.id = int(''.join(addr.split(':')[-3:]), 16) & 0xffffff
|
||||||
result = {k: dict(parser[k]) for k in ([section] if section else parser.sections())}
|
self.typ = self.BOX_TYPES.get(addr[:8])
|
||||||
except KeyError:
|
self.main_if = ifname
|
||||||
return {}
|
|
||||||
if section:
|
def get_macaddr(self):
|
||||||
return result[section]
|
return self.macaddr.get(self.main_if)
|
||||||
return result
|
|
||||||
|
def read_config(self):
|
||||||
|
cfgfiles = glob(self.CFGPATH % ('*', self.id))
|
||||||
|
if len(cfgfiles) != 1:
|
||||||
|
raise ValueError('there must be one and only one single cfgfile %r' % cfgfiles)
|
||||||
|
if cfgfiles:
|
||||||
|
self.cfgfile = cfgfiles[0]
|
||||||
|
parser = ConfigParser()
|
||||||
|
parser.read(self.cfgfile)
|
||||||
|
return {k: dict(parser[k]) for k in parser.sections()}
|
||||||
|
|
||||||
|
|
||||||
def gethostthread(ip, event, result):
|
def gethostthread(ip, event, result):
|
||||||
|
Reference in New Issue
Block a user