Send patches - preferably formatted by git format-patch - to patches at archlinux32 dot org.
summaryrefslogtreecommitdiff
path: root/archinstall/lib
diff options
context:
space:
mode:
authorDaniel <blackrabbit256@gmail.com>2022-03-01 01:57:57 +1100
committerGitHub <noreply@github.com>2022-02-28 15:57:57 +0100
commit537b9cab037aecfd18edef156dd3ea55072918e9 (patch)
treefe56cd4af527e816d831b220c6672c1dcfc2958f /archinstall/lib
parentfa87d85708331ad45f28906217f94937bae474fe (diff)
Rework network config (#1001)
* Update network configuration * Rework network configuration * Update documentation * Fix flake8 * Update Co-authored-by: Daniel Girtler <girtler.daniel@gmail.com> Co-authored-by: Anton Hvornum <anton.feeds@gmail.com>
Diffstat (limited to 'archinstall/lib')
-rw-r--r--archinstall/lib/installer.py43
-rw-r--r--archinstall/lib/models/network_configuration.py97
-rw-r--r--archinstall/lib/user_interaction.py35
3 files changed, 140 insertions, 35 deletions
diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py
index cf643b27..894bcc2a 100644
--- a/archinstall/lib/installer.py
+++ b/archinstall/lib/installer.py
@@ -35,6 +35,7 @@ __packages__ = ["base", "base-devel", "linux-firmware", "linux", "linux-lts", "l
__accessibility_packages__ = ["brltty", "espeakup", "alsa-utils"]
from .pacman import run_pacman
+from .models.network_configuration import NetworkConfiguration
class InstallationFile:
@@ -479,37 +480,35 @@ class Installer:
def drop_to_shell(self) -> None:
subprocess.check_call(f"/usr/bin/arch-chroot {self.target}", shell=True)
- def configure_nic(self,
- nic :str,
- dhcp :bool = True,
- ip :Optional[str] = None,
- gateway :Optional[str] = None,
- dns :Optional[str] = None,
- *args :str,
- **kwargs :str
- ) -> None:
+ def configure_nic(self, network_config: NetworkConfiguration) -> None:
from .systemd import Networkd
- if dhcp:
- conf = Networkd(Match={"Name": nic}, Network={"DHCP": "yes"})
+ if network_config.dhcp:
+ conf = Networkd(Match={"Name": network_config.iface}, Network={"DHCP": "yes"})
else:
- assert ip
+ network = {"Address": network_config.ip}
+ if network_config.gateway:
+ network["Gateway"] = network_config.gateway
+ if network_config.dns:
+ dns = network_config.dns
+ network["DNS"] = dns if isinstance(dns, list) else [dns]
- network = {"Address": ip}
- if gateway:
- network["Gateway"] = gateway
- if dns:
- assert type(dns) == list
- network["DNS"] = dns
-
- conf = Networkd(Match={"Name": nic}, Network=network)
+ conf = Networkd(Match={"Name": network_config.iface}, Network=network)
for plugin in plugins.values():
if hasattr(plugin, 'on_configure_nic'):
- if (new_conf := plugin.on_configure_nic(nic, dhcp, ip, gateway, dns)):
+ new_conf = plugin.on_configure_nic(
+ network_config.iface,
+ network_config.dhcp,
+ network_config.ip,
+ network_config.gateway,
+ network_config.dns
+ )
+
+ if new_conf:
conf = new_conf
- with open(f"{self.target}/etc/systemd/network/10-{nic}.network", "a") as netconf:
+ with open(f"{self.target}/etc/systemd/network/10-{network_config.iface}.network", "a") as netconf:
netconf.write(str(conf))
def copy_iso_network_config(self, enable_services :bool = False) -> bool:
diff --git a/archinstall/lib/models/network_configuration.py b/archinstall/lib/models/network_configuration.py
new file mode 100644
index 00000000..f1ee4c3f
--- /dev/null
+++ b/archinstall/lib/models/network_configuration.py
@@ -0,0 +1,97 @@
+from __future__ import annotations
+
+from dataclasses import dataclass
+from enum import Enum
+from typing import List, Optional, Dict
+
+from ... import log
+
+
+class NicType(str, Enum):
+ ISO = "iso"
+ NM = "nm"
+ MANUAL = "manual"
+
+
+@dataclass
+class NetworkConfiguration:
+ type: NicType
+ iface: str = None
+ ip: str = None
+ dhcp: bool = True
+ gateway: str = None
+ dns: List[str] = None
+
+ def __str__(self):
+ if self.is_iso():
+ return "Copy ISO configuration"
+ elif self.is_network_manager():
+ return "Use NetworkManager"
+ elif self.is_manual():
+ if self.dhcp:
+ return f'iface={self.iface}, dhcp=auto'
+ else:
+ return f'iface={self.iface}, ip={self.ip}, dhcp=staticIp, gateway={self.gateway}, dns={self.dns}'
+ else:
+ return 'Unknown type'
+
+ # for json serialization when calling json.dumps(...) on this class
+ def json(self):
+ return self.__dict__
+
+ @classmethod
+ def parse_arguments(cls, config: Dict[str, str]) -> Optional["NetworkConfiguration"]:
+ nic_type = config.get('type', None)
+
+ if not nic_type:
+ return None
+
+ try:
+ type = NicType(nic_type)
+ except ValueError:
+ options = [e.value for e in NicType]
+ log(_('Unknown nic type: {}. Possible values are {}').format(nic_type, options), fg='red')
+ exit(1)
+
+ if type == NicType.MANUAL:
+ if config.get('dhcp', False) or not any([config.get(v) for v in ['ip', 'gateway', 'dns']]):
+ return NetworkConfiguration(type, iface=config.get('iface', ''))
+
+ ip = config.get('ip', '')
+ if not ip:
+ log('Manual nic configuration with no auto DHCP requires an IP address', fg='red')
+ exit(1)
+
+ return NetworkConfiguration(
+ type,
+ iface=config.get('iface', ''),
+ ip=ip,
+ gateway=config.get('gateway', ''),
+ dns=config.get('dns', []),
+ dhcp=False
+ )
+ else:
+ return NetworkConfiguration(type)
+
+ def is_iso(self) -> bool:
+ return self.type == NicType.ISO
+
+ def is_network_manager(self) -> bool:
+ return self.type == NicType.NM
+
+ def is_manual(self) -> bool:
+ return self.type == NicType.MANUAL
+
+ def config_installer(self, installation: 'Installer'):
+ # If user selected to copy the current ISO network configuration
+ # Perform a copy of the config
+ if self.is_iso():
+ installation.copy_iso_network_config(enable_services=True) # Sources the ISO network configuration to the install medium.
+ elif self.is_network_manager():
+ installation.add_additional_packages("networkmanager")
+ installation.enable_service('NetworkManager.service')
+ # Otherwise, if a interface was selected, configure that interface
+ elif self.is_manual():
+ installation.configure_nic(self)
+ installation.enable_service('systemd-networkd')
+ installation.enable_service('systemd-resolved')
diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py
index 7524dd8b..1f62b7fd 100644
--- a/archinstall/lib/user_interaction.py
+++ b/archinstall/lib/user_interaction.py
@@ -14,6 +14,7 @@ from typing import List, Any, Optional, Dict, Union, TYPE_CHECKING
# https://stackoverflow.com/a/39757388/929999
from .menu.text_input import TextInput
+from .models.network_configuration import NetworkConfiguration, NicType
if TYPE_CHECKING:
from .disk.partition import Partition
@@ -450,11 +451,12 @@ def ask_additional_packages_to_install(pre_set_packages :List[str] = []) -> List
return packages
-def ask_to_configure_network(preset :Dict[str, Any] = {}) -> Dict[str, Any]:
- # Optionally configure one network interface.
- # while 1:
- # {MAC: Ifname}
+def ask_to_configure_network(preset :Dict[str, Any] = {}) -> Optional[NetworkConfiguration]:
+ """
+ Configure the network on the newly installed system
+ """
interfaces = {
+ 'none': str(_('No network configuration')),
'iso_config': str(_('Copy ISO network configuration to installation')),
'network_manager': str(_('Use NetworkManager (necessary to configure internet graphically in GNOME and KDE)')),
**list_interfaces()
@@ -473,17 +475,17 @@ def ask_to_configure_network(preset :Dict[str, Any] = {}) -> Dict[str, Any]:
except ValueError:
pass
- nic = Menu(_('Select one network interface to configure'), interfaces.values(),cursor_index=cursor_idx).run()
+ nic = Menu(_('Select one network interface to configure'), interfaces.values(), cursor_index=cursor_idx, sort=False).run()
if not nic:
- return {}
-
- # nic = network_manager_nt
+ return None
- if nic == interfaces['iso_config']:
- return {'type': 'iso_config'}
+ if nic == interfaces['none']:
+ return None
+ elif nic == interfaces['iso_config']:
+ return NetworkConfiguration(NicType.ISO)
elif nic == interfaces['network_manager']:
- return {'type': 'network_manager', 'NetworkManager': True}
+ return NetworkConfiguration(NicType.NM)
else:
# Current workaround:
# For selecting modes without entering text within brackets,
@@ -543,10 +545,17 @@ def ask_to_configure_network(preset :Dict[str, Any] = {}) -> Dict[str, Any]:
if len(dns_input):
dns = dns_input.split(' ')
- return {'type': nic, 'dhcp': False, 'ip': ip, 'gateway': gateway, 'dns': dns}
+ return NetworkConfiguration(
+ NicType.MANUAL,
+ iface=nic,
+ ip=ip,
+ gateway=gateway,
+ dns=dns,
+ dhcp=False
+ )
else:
# this will contain network iface names
- return {'type': nic}
+ return NetworkConfiguration(NicType.MANUAL, iface=nic)
def partition_overlap(partitions :list, start :str, end :str) -> bool: