Merge pull request #96 from Torxed/hardware-n-wifi
Added wifi-configuration support (basic) by copying existing `iwd` configurations. Also added some hardware detection helpers such as `UEFI` detection and wifi hardware as well as detection for three common graphic cards.
This commit is contained in:
commit
190ec7ad42
|
|
@ -20,3 +20,4 @@ SAFETY_LOCK
|
||||||
**/**.network
|
**/**.network
|
||||||
**/**.target
|
**/**.target
|
||||||
**/**.qcow2
|
**/**.qcow2
|
||||||
|
**/test.py
|
||||||
|
|
|
||||||
|
|
@ -12,3 +12,4 @@ from .lib.services import *
|
||||||
from .lib.packages import *
|
from .lib.packages import *
|
||||||
from .lib.output import *
|
from .lib.output import *
|
||||||
from .lib.storage import *
|
from .lib.storage import *
|
||||||
|
from .lib.hardware import *
|
||||||
|
|
@ -8,3 +8,5 @@ class SysCallError(BaseException):
|
||||||
pass
|
pass
|
||||||
class ProfileNotFound(BaseException):
|
class ProfileNotFound(BaseException):
|
||||||
pass
|
pass
|
||||||
|
class HardwareIncompatibilityError(BaseException):
|
||||||
|
pass
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
import os
|
||||||
|
from .general import sys_command
|
||||||
|
from .networking import list_interfaces, enrichIfaceTypes
|
||||||
|
|
||||||
|
def hasWifi():
|
||||||
|
if 'WIRELESS' in enrichIfaceTypes(list_interfaces().values()).values():
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def hasUEFI():
|
||||||
|
return os.path.isdir('/sys/firmware/efi')
|
||||||
|
|
||||||
|
def graphicsDevices():
|
||||||
|
cards = {}
|
||||||
|
for line in sys_command(f"lspci"):
|
||||||
|
if b' VGA ' in line:
|
||||||
|
_, identifier = line.split(b': ',1)
|
||||||
|
cards[identifier.strip().lower().decode('UTF-8')] = line
|
||||||
|
return cards
|
||||||
|
|
||||||
|
def hasNvidiaGraphics():
|
||||||
|
if [x for x in graphicsDevices() if 'nvidia' in x]:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def hasAmdGraphics():
|
||||||
|
if [x for x in graphicsDevices() if 'amd' in x]:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def hasIntelGraphics():
|
||||||
|
if [x for x in graphicsDevices() if 'intel' in x]:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
# TODO: Add more identifiers
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import os, stat, time
|
import os, stat, time, shutil
|
||||||
|
|
||||||
from .exceptions import *
|
from .exceptions import *
|
||||||
from .disk import *
|
from .disk import *
|
||||||
|
|
@ -48,6 +48,7 @@ class Installer():
|
||||||
}
|
}
|
||||||
|
|
||||||
self.base_packages = base_packages.split(' ')
|
self.base_packages = base_packages.split(' ')
|
||||||
|
self.post_base_install = []
|
||||||
storage['session'] = self
|
storage['session'] = self
|
||||||
|
|
||||||
self.partition = partition
|
self.partition = partition
|
||||||
|
|
@ -182,6 +183,47 @@ class Installer():
|
||||||
with open(f"{self.mountpoint}/etc/systemd/network/10-{nic}.network", "a") as netconf:
|
with open(f"{self.mountpoint}/etc/systemd/network/10-{nic}.network", "a") as netconf:
|
||||||
netconf.write(str(conf))
|
netconf.write(str(conf))
|
||||||
|
|
||||||
|
def copy_ISO_network_config(self, enable_services=False):
|
||||||
|
# Copy (if any) iwd password and config files
|
||||||
|
if os.path.isdir('/var/lib/iwd/'):
|
||||||
|
if (psk_files := glob.glob('/var/lib/iwd/*.psk')):
|
||||||
|
if not os.path.isdir(f"{self.mountpoint}/var/lib/iwd"):
|
||||||
|
os.makedirs(f"{self.mountpoint}/var/lib/iwd")
|
||||||
|
|
||||||
|
if enable_services:
|
||||||
|
# If we haven't installed the base yet (function called pre-maturely)
|
||||||
|
if self.helper_flags.get('base', False) is False:
|
||||||
|
self.base_packages.append('iwd')
|
||||||
|
# This function will be called after minimal_installation()
|
||||||
|
# as a hook for post-installs. This hook is only needed if
|
||||||
|
# base is not installed yet.
|
||||||
|
def post_install_enable_iwd_service(*args, **kwargs):
|
||||||
|
self.enable_service('iwd')
|
||||||
|
self.enable_service('systemd-networkd')
|
||||||
|
self.enable_service('systemd-resolved')
|
||||||
|
|
||||||
|
self.post_base_install.append(post_install_enable_iwd_service)
|
||||||
|
# Otherwise, we can go ahead and add the required package
|
||||||
|
# and enable it's service:
|
||||||
|
else:
|
||||||
|
self.pacstrap('iwd')
|
||||||
|
self.enable_service('iwd')
|
||||||
|
self.enable_service('systemd-networkd')
|
||||||
|
self.enable_service('systemd-resolved')
|
||||||
|
|
||||||
|
for psk in psk_files:
|
||||||
|
shutil.copy2(psk, f"{self.mountpoint}/var/lib/iwd/{os.path.basename(psk)}")
|
||||||
|
|
||||||
|
# Copy (if any) systemd-networkd config files
|
||||||
|
if (netconfigurations := glob.glob('/etc/systemd/network/*')):
|
||||||
|
if not os.path.isdir(f"{self.mountpoint}/etc/systemd/network/"):
|
||||||
|
os.makedirs(f"{self.mountpoint}/etc/systemd/network/")
|
||||||
|
|
||||||
|
for netconf_file in netconfigurations:
|
||||||
|
shutil.copy2(netconf_file, f"{self.mountpoint}/etc/systemd/network/{os.path.basename(netconf_file)}")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def minimal_installation(self):
|
def minimal_installation(self):
|
||||||
## Add nessecary packages if encrypting the drive
|
## Add nessecary packages if encrypting the drive
|
||||||
## (encrypted partitions default to btrfs for now, so we need btrfs-progs)
|
## (encrypted partitions default to btrfs for now, so we need btrfs-progs)
|
||||||
|
|
@ -220,6 +262,12 @@ class Installer():
|
||||||
sys_command(f'/usr/bin/arch-chroot {self.mountpoint} mkinitcpio -p linux')
|
sys_command(f'/usr/bin/arch-chroot {self.mountpoint} mkinitcpio -p linux')
|
||||||
|
|
||||||
self.helper_flags['base'] = True
|
self.helper_flags['base'] = True
|
||||||
|
|
||||||
|
# Run registered post-install hooks
|
||||||
|
for function in self.post_base_install:
|
||||||
|
self.log(f"Running post-installation hook: {function}", level=LOG_LEVELS.Info)
|
||||||
|
function(self)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def add_bootloader(self, bootloader='systemd-bootctl'):
|
def add_bootloader(self, bootloader='systemd-bootctl'):
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
|
import os
|
||||||
import fcntl
|
import fcntl
|
||||||
import socket
|
import socket
|
||||||
import struct
|
import struct
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
from .exceptions import *
|
||||||
|
from .general import sys_command
|
||||||
|
from .storage import storage
|
||||||
|
|
||||||
def getHwAddr(ifname):
|
def getHwAddr(ifname):
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
|
@ -19,5 +22,47 @@ def list_interfaces(skip_loopback=True):
|
||||||
interfaces[mac] = iface
|
interfaces[mac] = iface
|
||||||
return interfaces
|
return interfaces
|
||||||
|
|
||||||
|
def enrichIfaceTypes(interfaces :dict):
|
||||||
|
result = {}
|
||||||
|
for iface in interfaces:
|
||||||
|
if os.path.isdir(f"/sys/class/net/{iface}/bridge/"):
|
||||||
|
result[iface] = 'BRIDGE'
|
||||||
|
elif os.path.isfile(f"/sys/class/net/{iface}/tun_flags"):
|
||||||
|
# ethtool -i {iface}
|
||||||
|
result[iface] = 'TUN/TAP'
|
||||||
|
elif os.path.isdir(f"/sys/class/net/{iface}/device"):
|
||||||
|
if os.path.isdir(f"/sys/class/net/{iface}/wireless/"):
|
||||||
|
result[iface] = 'WIRELESS'
|
||||||
|
else:
|
||||||
|
result[iface] = 'PHYSICAL'
|
||||||
|
else:
|
||||||
|
result[iface] = 'UNKNOWN'
|
||||||
|
return result
|
||||||
|
|
||||||
def get_interface_from_mac(mac):
|
def get_interface_from_mac(mac):
|
||||||
return list_interfaces().get(mac.lower(), None)
|
return list_interfaces().get(mac.lower(), None)
|
||||||
|
|
||||||
|
def wirelessScan(interface):
|
||||||
|
interfaces = enrichIfaceTypes(list_interfaces().values())
|
||||||
|
if interfaces[interface] != 'WIRELESS':
|
||||||
|
raise HardwareIncompatibilityError(f"Interface {interface} is not a wireless interface: {interfaces}")
|
||||||
|
|
||||||
|
sys_command(f"iwctl station {interface} scan")
|
||||||
|
|
||||||
|
if not '_WIFI' in storage:
|
||||||
|
storage['_WIFI'] = {}
|
||||||
|
if not interface in storage['_WIFI']:
|
||||||
|
storage['_WIFI'][interface] = {}
|
||||||
|
|
||||||
|
storage['_WIFI'][interface]['scanning'] = True
|
||||||
|
|
||||||
|
# TOOD: Full WiFi experience might get evolved in the future, pausing for now 2021-01-25
|
||||||
|
def getWirelessNetworks(interface):
|
||||||
|
# TODO: Make this oneliner pritter to check if the interface is scanning or not.
|
||||||
|
if not '_WIFI' in storage or interface not in storage['_WIFI'] or storage['_WIFI'][interface].get('scanning', False) is False:
|
||||||
|
import time
|
||||||
|
wirelessScan(interface)
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
|
for line in sys_command(f"iwctl station {interface} get-networks"):
|
||||||
|
print(line)
|
||||||
|
|
@ -49,11 +49,18 @@ def perform_installation(device, boot_partition, language, mirrors):
|
||||||
installation.set_keyboard_language(language)
|
installation.set_keyboard_language(language)
|
||||||
installation.add_bootloader()
|
installation.add_bootloader()
|
||||||
|
|
||||||
if archinstall.storage['_guided']['network']:
|
# If user selected to copy the current ISO network configuration
|
||||||
|
# Perform a copy of the config
|
||||||
|
if archinstall.storage['_guided']['network'] == 'Copy ISO network configuration to installation':
|
||||||
|
installation.copy_ISO_network_config(enable_services=True) # Sources the ISO network configuration to the install medium.
|
||||||
|
|
||||||
|
# Otherwise, if a interface was selected, configure that interface
|
||||||
|
elif archinstall.storage['_guided']['network']:
|
||||||
installation.configure_nic(**archinstall.storage['_guided']['network'])
|
installation.configure_nic(**archinstall.storage['_guided']['network'])
|
||||||
installation.enable_service('systemd-networkd')
|
installation.enable_service('systemd-networkd')
|
||||||
installation.enable_service('systemd-resolved')
|
installation.enable_service('systemd-resolved')
|
||||||
|
|
||||||
|
|
||||||
if archinstall.storage['_guided']['packages'] and archinstall.storage['_guided']['packages'][0] != '':
|
if archinstall.storage['_guided']['packages'] and archinstall.storage['_guided']['packages'][0] != '':
|
||||||
installation.add_additional_packages(archinstall.storage['_guided']['packages'])
|
installation.add_additional_packages(archinstall.storage['_guided']['packages'])
|
||||||
|
|
||||||
|
|
@ -188,11 +195,12 @@ while 1:
|
||||||
|
|
||||||
# Optionally configure one network interface.
|
# Optionally configure one network interface.
|
||||||
#while 1:
|
#while 1:
|
||||||
interfaces = archinstall.list_interfaces() # {MAC: Ifname}
|
# {MAC: Ifname}
|
||||||
|
interfaces = {'ISO-CONFIG' : 'Copy ISO network configuration to installation', **archinstall.list_interfaces()}
|
||||||
archinstall.storage['_guided']['network'] = None
|
archinstall.storage['_guided']['network'] = None
|
||||||
|
|
||||||
nic = archinstall.generic_select(interfaces.values(), "Select one network interface to configure (leave blank to skip): ")
|
nic = archinstall.generic_select(interfaces.values(), "Select one network interface to configure (leave blank to skip): ")
|
||||||
if nic:
|
if nic and nic != 'Copy ISO network configuration to installation':
|
||||||
mode = archinstall.generic_select(['DHCP (auto detect)', 'IP (static)'], f"Select which mode to configure for {nic}: ")
|
mode = archinstall.generic_select(['DHCP (auto detect)', 'IP (static)'], f"Select which mode to configure for {nic}: ")
|
||||||
if mode == 'IP (static)':
|
if mode == 'IP (static)':
|
||||||
while 1:
|
while 1:
|
||||||
|
|
@ -217,7 +225,8 @@ if nic:
|
||||||
archinstall.storage['_guided']['network'] = {'nic': nic, 'dhcp': False, 'ip': ip, 'gateway' : gateway, 'dns' : dns}
|
archinstall.storage['_guided']['network'] = {'nic': nic, 'dhcp': False, 'ip': ip, 'gateway' : gateway, 'dns' : dns}
|
||||||
else:
|
else:
|
||||||
archinstall.storage['_guided']['network'] = {'nic': nic}
|
archinstall.storage['_guided']['network'] = {'nic': nic}
|
||||||
|
elif nic:
|
||||||
|
archinstall.storage['_guided']['network'] = nic
|
||||||
|
|
||||||
print()
|
print()
|
||||||
print('This is your chosen configuration:')
|
print('This is your chosen configuration:')
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue