Send patches - preferably formatted by git format-patch - to patches at archlinux32 dot org.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--archinstall/__init__.py1
-rw-r--r--archinstall/lib/exceptions.py2
-rw-r--r--archinstall/lib/hardware.py36
-rw-r--r--archinstall/lib/installer.py50
-rw-r--r--archinstall/lib/networking.py49
-rw-r--r--examples/guided.py17
7 files changed, 149 insertions, 7 deletions
diff --git a/.gitignore b/.gitignore
index aebb999d..dc75bed8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,3 +20,4 @@ SAFETY_LOCK
**/**.network
**/**.target
**/**.qcow2
+**/test.py
diff --git a/archinstall/__init__.py b/archinstall/__init__.py
index 174c6885..ee2d0361 100644
--- a/archinstall/__init__.py
+++ b/archinstall/__init__.py
@@ -12,3 +12,4 @@ from .lib.services import *
from .lib.packages import *
from .lib.output import *
from .lib.storage import *
+from .lib.hardware import * \ No newline at end of file
diff --git a/archinstall/lib/exceptions.py b/archinstall/lib/exceptions.py
index 2a1cae14..84e6a766 100644
--- a/archinstall/lib/exceptions.py
+++ b/archinstall/lib/exceptions.py
@@ -7,4 +7,6 @@ class ProfileError(BaseException):
class SysCallError(BaseException):
pass
class ProfileNotFound(BaseException):
+ pass
+class HardwareIncompatibilityError(BaseException):
pass \ No newline at end of file
diff --git a/archinstall/lib/hardware.py b/archinstall/lib/hardware.py
new file mode 100644
index 00000000..93eb560f
--- /dev/null
+++ b/archinstall/lib/hardware.py
@@ -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 \ No newline at end of file
diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py
index 8c22b51f..c9d7e9cc 100644
--- a/archinstall/lib/installer.py
+++ b/archinstall/lib/installer.py
@@ -1,4 +1,4 @@
-import os, stat, time
+import os, stat, time, shutil
from .exceptions import *
from .disk import *
@@ -48,6 +48,7 @@ class Installer():
}
self.base_packages = base_packages.split(' ')
+ self.post_base_install = []
storage['session'] = self
self.partition = partition
@@ -182,6 +183,47 @@ class Installer():
with open(f"{self.mountpoint}/etc/systemd/network/10-{nic}.network", "a") as netconf:
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):
## Add nessecary packages if encrypting the drive
## (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')
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
def add_bootloader(self, bootloader='systemd-bootctl'):
diff --git a/archinstall/lib/networking.py b/archinstall/lib/networking.py
index 4829a58b..882bcff3 100644
--- a/archinstall/lib/networking.py
+++ b/archinstall/lib/networking.py
@@ -1,8 +1,11 @@
+import os
import fcntl
import socket
import struct
from collections import OrderedDict
-
+from .exceptions import *
+from .general import sys_command
+from .storage import storage
def getHwAddr(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
@@ -19,5 +22,47 @@ def list_interfaces(skip_loopback=True):
interfaces[mac] = iface
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):
- return list_interfaces().get(mac.lower(), None) \ No newline at end of file
+ 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) \ No newline at end of file
diff --git a/examples/guided.py b/examples/guided.py
index 7726d5b9..ab284721 100644
--- a/examples/guided.py
+++ b/examples/guided.py
@@ -49,11 +49,18 @@ def perform_installation(device, boot_partition, language, mirrors):
installation.set_keyboard_language(language)
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.enable_service('systemd-networkd')
installation.enable_service('systemd-resolved')
+
if archinstall.storage['_guided']['packages'] and archinstall.storage['_guided']['packages'][0] != '':
installation.add_additional_packages(archinstall.storage['_guided']['packages'])
@@ -188,11 +195,12 @@ while 1:
# Optionally configure one network interface.
#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
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}: ")
if mode == 'IP (static)':
while 1:
@@ -217,7 +225,8 @@ if nic:
archinstall.storage['_guided']['network'] = {'nic': nic, 'dhcp': False, 'ip': ip, 'gateway' : gateway, 'dns' : dns}
else:
archinstall.storage['_guided']['network'] = {'nic': nic}
-
+elif nic:
+ archinstall.storage['_guided']['network'] = nic
print()
print('This is your chosen configuration:')