We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Installation fails in encryption step  with DiskError and NameError
I tried to test the installer but hit this error while encrypting a partition. I followed the instructions in the [README](https://github.com/Torxed/archinstall#testing).

```
{
    "!encryption-password": "******",
    "!root-password": "******",
    "filesystem": "ext4",
    "harddrive": {
        "model": null,
        "path": "/dev/loop2",
        "size": "5G"
    },
    "hostname": "laptop",
    "keyboard-language": "l1",
    "mirror-region": {
       ...
    },
    "nic": {
        "nic": "wlp4s0"
    },
    "packages": [
        "firefox",
        "thunderbird"
    ],
    "profile": {
        "path": "/usr/lib/python3.9/site-packages/archinstall/profiles/gnome.py"
    },
    "superusers": {
        "admin": {
            "!password": "******"
        }
    },
    "timezone": "Europe/Berlin",
    "users": {}
}
```

```
Encrypting Partition(path=/dev/loop2p2, real_device=/dev/loop2, fs=ext4, rel_mountpoint=/) (This might take a while)
Traceback (most recent call last):
  File "/usr/lib/python3.9/runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/usr/lib/python3.9/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/usr/lib/python3.9/site-packages/archinstall/__main__.py", line 34, in <module>
    run_as_a_module()
  File "/usr/lib/python3.9/site-packages/archinstall/__main__.py", line 31, in run_as_a_module
    script.execute()
  File "/usr/lib/python3.9/site-packages/archinstall/lib/profiles.py", line 143, in execute
    self.spec.loader.exec_module(sys.modules[self.namespace])
  File "<frozen importlib._bootstrap_external>", line 790, in exec_module
  File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
  File "/usr/lib/python3.9/site-packages/archinstall/examples/guided.py", line 342, in <module>
    perform_installation_steps()
  File "/usr/lib/python3.9/site-packages/archinstall/examples/guided.py", line 283, in perform_installation_steps
    perform_installation(device=fs.find_partition('/'),
  File "/usr/lib/python3.9/site-packages/archinstall/lib/disk.py", line 422, in __exit__
    raise args[1]
  File "/usr/lib/python3.9/site-packages/archinstall/examples/guided.py", line 265, in perform_installation_steps
    partition.encrypt(password=passwd)
  File "/usr/lib/python3.9/site-packages/archinstall/lib/disk.py", line 263, in encrypt
    return handle.encrypt(self, *args, **kwargs)
  File "/usr/lib/python3.9/site-packages/archinstall/lib/luks.py", line 98, in encrypt
    raise DiskError(f'Could not encrypt volume "{partition.path}": {o}')
NameError: name 'o' is not defined
```

Congratulations on the inclusion in an official arch installer image! :partying_face: (Even if this turns out to be an April fools joke ;-)

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `archinstall/lib/luks.py`
Content:
```
1 import os
2 from .exceptions import *
3 from .general import *
4 from .disk import Partition
5 from .output import log, LOG_LEVELS
6 from .storage import storage
7 
8 class luks2():
9 	def __init__(self, partition, mountpoint, password, key_file=None, auto_unmount=False, *args, **kwargs):
10 		self.password = password
11 		self.partition = partition
12 		self.mountpoint = mountpoint
13 		self.args = args
14 		self.kwargs = kwargs
15 		self.key_file = key_file
16 		self.auto_unmount = auto_unmount
17 		self.filesystem = 'crypto_LUKS'
18 		self.mapdev = None
19 
20 	def __enter__(self):
21 		#if self.partition.allow_formatting:
22 		#	self.key_file = self.encrypt(self.partition, *self.args, **self.kwargs)
23 		#else:
24 		if not self.key_file:
25 			self.key_file = f"/tmp/{os.path.basename(self.partition.path)}.disk_pw"  # TODO: Make disk-pw-file randomly unique?
26 		
27 		if type(self.password) != bytes:
28 			self.password = bytes(self.password, 'UTF-8')
29 
30 		with open(self.key_file, 'wb') as fh:
31 			fh.write(self.password)
32 
33 		return self.unlock(self.partition, self.mountpoint, self.key_file)
34 
35 	def __exit__(self, *args, **kwargs):
36 		# TODO: https://stackoverflow.com/questions/28157929/how-to-safely-handle-an-exception-inside-a-context-manager
37 		if self.auto_unmount:
38 			self.close()
39 
40 		if len(args) >= 2 and args[1]:
41 			raise args[1]
42 		return True
43 
44 	def encrypt(self, partition, password=None, key_size=512, hash_type='sha512', iter_time=10000, key_file=None):
45 		# TODO: We should be able to integrate this into the main log some how.
46 		#       Perhaps post-mortem?
47 		if not self.partition.allow_formatting:
48 			raise DiskError(f'Could not encrypt volume {self.partition} due to it having a formatting lock.')
49 
50 		log(f'Encrypting {partition} (This might take a while)', level=LOG_LEVELS.Info)
51 
52 		if not key_file:
53 			if self.key_file:
54 				key_file = self.key_file
55 			else:
56 				key_file = f"/tmp/{os.path.basename(self.partition.path)}.disk_pw"  # TODO: Make disk-pw-file randomly unique?
57 
58 		if not password:
59 			password = self.password
60 
61 		if type(password) != bytes:
62 			password = bytes(password, 'UTF-8')
63 
64 		with open(key_file, 'wb') as fh:
65 			fh.write(password)
66 
67 		try:
68 			# Try to setup the crypt-device
69 			cmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}')
70 		except SysCallError as err:
71 			if err.exit_code == 256:
72 				log(f'{partition} is being used, trying to unmount and crypt-close the device and running one more attempt at encrypting the device.', level=LOG_LEVELS.Debug)
73 				# Partition was in use, unmount it and try again
74 				partition.unmount()
75 
76 				# Get crypt-information about the device by doing a reverse lookup starting with the partition path
77 				# For instance: /dev/sda
78 				devinfo = json.loads(b''.join(sys_command(f"lsblk --fs -J {partition.path}")).decode('UTF-8'))['blockdevices'][0]
79 
80 				# For each child (sub-partition/sub-device)
81 				if len(children := devinfo.get('children', [])):
82 					for child in children:
83 						# Unmount the child location
84 						if child_mountpoint := child.get('mountpoint', None):
85 							log(f'Unmounting {child_mountpoint}', level=LOG_LEVELS.Debug)
86 							sys_command(f"umount -R {child_mountpoint}")
87 
88 						# And close it if possible.
89 						log(f"Closing crypt device {child['name']}", level=LOG_LEVELS.Debug)
90 						sys_command(f"cryptsetup close {child['name']}")
91 
92 				# Then try again to set up the crypt-device
93 				cmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}')
94 			else:
95 				raise err
96 
97 		if b'Command successful.' not in b''.join(cmd_handle):
98 			raise DiskError(f'Could not encrypt volume "{partition.path}": {o}')
99 	
100 		return key_file
101 
102 	def unlock(self, partition, mountpoint, key_file):
103 		"""
104 		Mounts a lukts2 compatible partition to a certain mountpoint.
105 		Keyfile must be specified as there's no way to interact with the pw-prompt atm.
106 
107 		:param mountpoint: The name without absolute path, for instance "luksdev" will point to /dev/mapper/luksdev
108 		:type mountpoint: str
109 		"""
110 		from .disk import get_filesystem_type
111 		if '/' in mountpoint:
112 			os.path.basename(mountpoint)  # TODO: Raise exception instead?
113 		sys_command(f'/usr/bin/cryptsetup open {partition.path} {mountpoint} --key-file {os.path.abspath(key_file)} --type luks2')
114 		if os.path.islink(f'/dev/mapper/{mountpoint}'):
115 			self.mapdev = f'/dev/mapper/{mountpoint}'
116 			unlocked_partition = Partition(self.mapdev, None, encrypted=True, filesystem=get_filesystem_type(self.mapdev), autodetect_filesystem=False)
117 			unlocked_partition.allow_formatting = self.partition.allow_formatting
118 			return unlocked_partition
119 
120 	def close(self, mountpoint=None):
121 		if not mountpoint:
122 			mountpoint = self.mapdev
123 
124 		sys_command(f'/usr/bin/cryptsetup close {self.mapdev}')
125 		return os.path.islink(self.mapdev) is False
126 
127 	def format(self, path):
128 		if (handle := sys_command(f"/usr/bin/cryptsetup -q -v luksErase {path}")).exit_code != 0:
129 			raise DiskError(f'Could not format {path} with {self.filesystem} because: {b"".join(handle)}')
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/archinstall/lib/luks.py b/archinstall/lib/luks.py
--- a/archinstall/lib/luks.py
+++ b/archinstall/lib/luks.py
@@ -94,8 +94,8 @@
 			else:
 				raise err
 
-		if b'Command successful.' not in b''.join(cmd_handle):
-			raise DiskError(f'Could not encrypt volume "{partition.path}": {o}')
+		if b'Command successful.' not in (cmd_output := b''.join(cmd_handle)):
+			raise DiskError(f'Could not encrypt volume "{partition.path}": {cmd_output}')
 	
 		return key_file
 
@@ -126,4 +126,4 @@
 
 	def format(self, path):
 		if (handle := sys_command(f"/usr/bin/cryptsetup -q -v luksErase {path}")).exit_code != 0:
-			raise DiskError(f'Could not format {path} with {self.filesystem} because: {b"".join(handle)}')
\ No newline at end of file
+			raise DiskError(f'Could not format {path} with {self.filesystem} because: {b"".join(handle)}')

{"golden_diff": "diff --git a/archinstall/lib/luks.py b/archinstall/lib/luks.py\n--- a/archinstall/lib/luks.py\n+++ b/archinstall/lib/luks.py\n@@ -94,8 +94,8 @@\n \t\t\telse:\n \t\t\t\traise err\n \n-\t\tif b'Command successful.' not in b''.join(cmd_handle):\n-\t\t\traise DiskError(f'Could not encrypt volume \"{partition.path}\": {o}')\n+\t\tif b'Command successful.' not in (cmd_output := b''.join(cmd_handle)):\n+\t\t\traise DiskError(f'Could not encrypt volume \"{partition.path}\": {cmd_output}')\n \t\n \t\treturn key_file\n \n@@ -126,4 +126,4 @@\n \n \tdef format(self, path):\n \t\tif (handle := sys_command(f\"/usr/bin/cryptsetup -q -v luksErase {path}\")).exit_code != 0:\n-\t\t\traise DiskError(f'Could not format {path} with {self.filesystem} because: {b\"\".join(handle)}')\n\\ No newline at end of file\n+\t\t\traise DiskError(f'Could not format {path} with {self.filesystem} because: {b\"\".join(handle)}')\n", "issue": "Installation fails in encryption step  with DiskError and NameError\nI tried to test the installer but hit this error while encrypting a partition. I followed the instructions in the [README](https://github.com/Torxed/archinstall#testing).\r\n\r\n```\r\n{\r\n    \"!encryption-password\": \"******\",\r\n    \"!root-password\": \"******\",\r\n    \"filesystem\": \"ext4\",\r\n    \"harddrive\": {\r\n        \"model\": null,\r\n        \"path\": \"/dev/loop2\",\r\n        \"size\": \"5G\"\r\n    },\r\n    \"hostname\": \"laptop\",\r\n    \"keyboard-language\": \"l1\",\r\n    \"mirror-region\": {\r\n       ...\r\n    },\r\n    \"nic\": {\r\n        \"nic\": \"wlp4s0\"\r\n    },\r\n    \"packages\": [\r\n        \"firefox\",\r\n        \"thunderbird\"\r\n    ],\r\n    \"profile\": {\r\n        \"path\": \"/usr/lib/python3.9/site-packages/archinstall/profiles/gnome.py\"\r\n    },\r\n    \"superusers\": {\r\n        \"admin\": {\r\n            \"!password\": \"******\"\r\n        }\r\n    },\r\n    \"timezone\": \"Europe/Berlin\",\r\n    \"users\": {}\r\n}\r\n```\r\n\r\n```\r\nEncrypting Partition(path=/dev/loop2p2, real_device=/dev/loop2, fs=ext4, rel_mountpoint=/) (This might take a while)\r\nTraceback (most recent call last):\r\n  File \"/usr/lib/python3.9/runpy.py\", line 197, in _run_module_as_main\r\n    return _run_code(code, main_globals, None,\r\n  File \"/usr/lib/python3.9/runpy.py\", line 87, in _run_code\r\n    exec(code, run_globals)\r\n  File \"/usr/lib/python3.9/site-packages/archinstall/__main__.py\", line 34, in <module>\r\n    run_as_a_module()\r\n  File \"/usr/lib/python3.9/site-packages/archinstall/__main__.py\", line 31, in run_as_a_module\r\n    script.execute()\r\n  File \"/usr/lib/python3.9/site-packages/archinstall/lib/profiles.py\", line 143, in execute\r\n    self.spec.loader.exec_module(sys.modules[self.namespace])\r\n  File \"<frozen importlib._bootstrap_external>\", line 790, in exec_module\r\n  File \"<frozen importlib._bootstrap>\", line 228, in _call_with_frames_removed\r\n  File \"/usr/lib/python3.9/site-packages/archinstall/examples/guided.py\", line 342, in <module>\r\n    perform_installation_steps()\r\n  File \"/usr/lib/python3.9/site-packages/archinstall/examples/guided.py\", line 283, in perform_installation_steps\r\n    perform_installation(device=fs.find_partition('/'),\r\n  File \"/usr/lib/python3.9/site-packages/archinstall/lib/disk.py\", line 422, in __exit__\r\n    raise args[1]\r\n  File \"/usr/lib/python3.9/site-packages/archinstall/examples/guided.py\", line 265, in perform_installation_steps\r\n    partition.encrypt(password=passwd)\r\n  File \"/usr/lib/python3.9/site-packages/archinstall/lib/disk.py\", line 263, in encrypt\r\n    return handle.encrypt(self, *args, **kwargs)\r\n  File \"/usr/lib/python3.9/site-packages/archinstall/lib/luks.py\", line 98, in encrypt\r\n    raise DiskError(f'Could not encrypt volume \"{partition.path}\": {o}')\r\nNameError: name 'o' is not defined\r\n```\r\n\r\nCongratulations on the inclusion in an official arch installer image! :partying_face: (Even if this turns out to be an April fools joke ;-)\n", "before_files": [{"content": "import os\nfrom .exceptions import *\nfrom .general import *\nfrom .disk import Partition\nfrom .output import log, LOG_LEVELS\nfrom .storage import storage\n\nclass luks2():\n\tdef __init__(self, partition, mountpoint, password, key_file=None, auto_unmount=False, *args, **kwargs):\n\t\tself.password = password\n\t\tself.partition = partition\n\t\tself.mountpoint = mountpoint\n\t\tself.args = args\n\t\tself.kwargs = kwargs\n\t\tself.key_file = key_file\n\t\tself.auto_unmount = auto_unmount\n\t\tself.filesystem = 'crypto_LUKS'\n\t\tself.mapdev = None\n\n\tdef __enter__(self):\n\t\t#if self.partition.allow_formatting:\n\t\t#\tself.key_file = self.encrypt(self.partition, *self.args, **self.kwargs)\n\t\t#else:\n\t\tif not self.key_file:\n\t\t\tself.key_file = f\"/tmp/{os.path.basename(self.partition.path)}.disk_pw\"  # TODO: Make disk-pw-file randomly unique?\n\t\t\n\t\tif type(self.password) != bytes:\n\t\t\tself.password = bytes(self.password, 'UTF-8')\n\n\t\twith open(self.key_file, 'wb') as fh:\n\t\t\tfh.write(self.password)\n\n\t\treturn self.unlock(self.partition, self.mountpoint, self.key_file)\n\n\tdef __exit__(self, *args, **kwargs):\n\t\t# TODO: https://stackoverflow.com/questions/28157929/how-to-safely-handle-an-exception-inside-a-context-manager\n\t\tif self.auto_unmount:\n\t\t\tself.close()\n\n\t\tif len(args) >= 2 and args[1]:\n\t\t\traise args[1]\n\t\treturn True\n\n\tdef encrypt(self, partition, password=None, key_size=512, hash_type='sha512', iter_time=10000, key_file=None):\n\t\t# TODO: We should be able to integrate this into the main log some how.\n\t\t#       Perhaps post-mortem?\n\t\tif not self.partition.allow_formatting:\n\t\t\traise DiskError(f'Could not encrypt volume {self.partition} due to it having a formatting lock.')\n\n\t\tlog(f'Encrypting {partition} (This might take a while)', level=LOG_LEVELS.Info)\n\n\t\tif not key_file:\n\t\t\tif self.key_file:\n\t\t\t\tkey_file = self.key_file\n\t\t\telse:\n\t\t\t\tkey_file = f\"/tmp/{os.path.basename(self.partition.path)}.disk_pw\"  # TODO: Make disk-pw-file randomly unique?\n\n\t\tif not password:\n\t\t\tpassword = self.password\n\n\t\tif type(password) != bytes:\n\t\t\tpassword = bytes(password, 'UTF-8')\n\n\t\twith open(key_file, 'wb') as fh:\n\t\t\tfh.write(password)\n\n\t\ttry:\n\t\t\t# Try to setup the crypt-device\n\t\t\tcmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}')\n\t\texcept SysCallError as err:\n\t\t\tif err.exit_code == 256:\n\t\t\t\tlog(f'{partition} is being used, trying to unmount and crypt-close the device and running one more attempt at encrypting the device.', level=LOG_LEVELS.Debug)\n\t\t\t\t# Partition was in use, unmount it and try again\n\t\t\t\tpartition.unmount()\n\n\t\t\t\t# Get crypt-information about the device by doing a reverse lookup starting with the partition path\n\t\t\t\t# For instance: /dev/sda\n\t\t\t\tdevinfo = json.loads(b''.join(sys_command(f\"lsblk --fs -J {partition.path}\")).decode('UTF-8'))['blockdevices'][0]\n\n\t\t\t\t# For each child (sub-partition/sub-device)\n\t\t\t\tif len(children := devinfo.get('children', [])):\n\t\t\t\t\tfor child in children:\n\t\t\t\t\t\t# Unmount the child location\n\t\t\t\t\t\tif child_mountpoint := child.get('mountpoint', None):\n\t\t\t\t\t\t\tlog(f'Unmounting {child_mountpoint}', level=LOG_LEVELS.Debug)\n\t\t\t\t\t\t\tsys_command(f\"umount -R {child_mountpoint}\")\n\n\t\t\t\t\t\t# And close it if possible.\n\t\t\t\t\t\tlog(f\"Closing crypt device {child['name']}\", level=LOG_LEVELS.Debug)\n\t\t\t\t\t\tsys_command(f\"cryptsetup close {child['name']}\")\n\n\t\t\t\t# Then try again to set up the crypt-device\n\t\t\t\tcmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}')\n\t\t\telse:\n\t\t\t\traise err\n\n\t\tif b'Command successful.' not in b''.join(cmd_handle):\n\t\t\traise DiskError(f'Could not encrypt volume \"{partition.path}\": {o}')\n\t\n\t\treturn key_file\n\n\tdef unlock(self, partition, mountpoint, key_file):\n\t\t\"\"\"\n\t\tMounts a lukts2 compatible partition to a certain mountpoint.\n\t\tKeyfile must be specified as there's no way to interact with the pw-prompt atm.\n\n\t\t:param mountpoint: The name without absolute path, for instance \"luksdev\" will point to /dev/mapper/luksdev\n\t\t:type mountpoint: str\n\t\t\"\"\"\n\t\tfrom .disk import get_filesystem_type\n\t\tif '/' in mountpoint:\n\t\t\tos.path.basename(mountpoint)  # TODO: Raise exception instead?\n\t\tsys_command(f'/usr/bin/cryptsetup open {partition.path} {mountpoint} --key-file {os.path.abspath(key_file)} --type luks2')\n\t\tif os.path.islink(f'/dev/mapper/{mountpoint}'):\n\t\t\tself.mapdev = f'/dev/mapper/{mountpoint}'\n\t\t\tunlocked_partition = Partition(self.mapdev, None, encrypted=True, filesystem=get_filesystem_type(self.mapdev), autodetect_filesystem=False)\n\t\t\tunlocked_partition.allow_formatting = self.partition.allow_formatting\n\t\t\treturn unlocked_partition\n\n\tdef close(self, mountpoint=None):\n\t\tif not mountpoint:\n\t\t\tmountpoint = self.mapdev\n\n\t\tsys_command(f'/usr/bin/cryptsetup close {self.mapdev}')\n\t\treturn os.path.islink(self.mapdev) is False\n\n\tdef format(self, path):\n\t\tif (handle := sys_command(f\"/usr/bin/cryptsetup -q -v luksErase {path}\")).exit_code != 0:\n\t\t\traise DiskError(f'Could not format {path} with {self.filesystem} because: {b\"\".join(handle)}')", "path": "archinstall/lib/luks.py"}], "after_files": [{"content": "import os\nfrom .exceptions import *\nfrom .general import *\nfrom .disk import Partition\nfrom .output import log, LOG_LEVELS\nfrom .storage import storage\n\nclass luks2():\n\tdef __init__(self, partition, mountpoint, password, key_file=None, auto_unmount=False, *args, **kwargs):\n\t\tself.password = password\n\t\tself.partition = partition\n\t\tself.mountpoint = mountpoint\n\t\tself.args = args\n\t\tself.kwargs = kwargs\n\t\tself.key_file = key_file\n\t\tself.auto_unmount = auto_unmount\n\t\tself.filesystem = 'crypto_LUKS'\n\t\tself.mapdev = None\n\n\tdef __enter__(self):\n\t\t#if self.partition.allow_formatting:\n\t\t#\tself.key_file = self.encrypt(self.partition, *self.args, **self.kwargs)\n\t\t#else:\n\t\tif not self.key_file:\n\t\t\tself.key_file = f\"/tmp/{os.path.basename(self.partition.path)}.disk_pw\"  # TODO: Make disk-pw-file randomly unique?\n\t\t\n\t\tif type(self.password) != bytes:\n\t\t\tself.password = bytes(self.password, 'UTF-8')\n\n\t\twith open(self.key_file, 'wb') as fh:\n\t\t\tfh.write(self.password)\n\n\t\treturn self.unlock(self.partition, self.mountpoint, self.key_file)\n\n\tdef __exit__(self, *args, **kwargs):\n\t\t# TODO: https://stackoverflow.com/questions/28157929/how-to-safely-handle-an-exception-inside-a-context-manager\n\t\tif self.auto_unmount:\n\t\t\tself.close()\n\n\t\tif len(args) >= 2 and args[1]:\n\t\t\traise args[1]\n\t\treturn True\n\n\tdef encrypt(self, partition, password=None, key_size=512, hash_type='sha512', iter_time=10000, key_file=None):\n\t\t# TODO: We should be able to integrate this into the main log some how.\n\t\t#       Perhaps post-mortem?\n\t\tif not self.partition.allow_formatting:\n\t\t\traise DiskError(f'Could not encrypt volume {self.partition} due to it having a formatting lock.')\n\n\t\tlog(f'Encrypting {partition} (This might take a while)', level=LOG_LEVELS.Info)\n\n\t\tif not key_file:\n\t\t\tif self.key_file:\n\t\t\t\tkey_file = self.key_file\n\t\t\telse:\n\t\t\t\tkey_file = f\"/tmp/{os.path.basename(self.partition.path)}.disk_pw\"  # TODO: Make disk-pw-file randomly unique?\n\n\t\tif not password:\n\t\t\tpassword = self.password\n\n\t\tif type(password) != bytes:\n\t\t\tpassword = bytes(password, 'UTF-8')\n\n\t\twith open(key_file, 'wb') as fh:\n\t\t\tfh.write(password)\n\n\t\ttry:\n\t\t\t# Try to setup the crypt-device\n\t\t\tcmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}')\n\t\texcept SysCallError as err:\n\t\t\tif err.exit_code == 256:\n\t\t\t\tlog(f'{partition} is being used, trying to unmount and crypt-close the device and running one more attempt at encrypting the device.', level=LOG_LEVELS.Debug)\n\t\t\t\t# Partition was in use, unmount it and try again\n\t\t\t\tpartition.unmount()\n\n\t\t\t\t# Get crypt-information about the device by doing a reverse lookup starting with the partition path\n\t\t\t\t# For instance: /dev/sda\n\t\t\t\tdevinfo = json.loads(b''.join(sys_command(f\"lsblk --fs -J {partition.path}\")).decode('UTF-8'))['blockdevices'][0]\n\n\t\t\t\t# For each child (sub-partition/sub-device)\n\t\t\t\tif len(children := devinfo.get('children', [])):\n\t\t\t\t\tfor child in children:\n\t\t\t\t\t\t# Unmount the child location\n\t\t\t\t\t\tif child_mountpoint := child.get('mountpoint', None):\n\t\t\t\t\t\t\tlog(f'Unmounting {child_mountpoint}', level=LOG_LEVELS.Debug)\n\t\t\t\t\t\t\tsys_command(f\"umount -R {child_mountpoint}\")\n\n\t\t\t\t\t\t# And close it if possible.\n\t\t\t\t\t\tlog(f\"Closing crypt device {child['name']}\", level=LOG_LEVELS.Debug)\n\t\t\t\t\t\tsys_command(f\"cryptsetup close {child['name']}\")\n\n\t\t\t\t# Then try again to set up the crypt-device\n\t\t\t\tcmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}')\n\t\t\telse:\n\t\t\t\traise err\n\n\t\tif b'Command successful.' not in (cmd_output := b''.join(cmd_handle)):\n\t\t\traise DiskError(f'Could not encrypt volume \"{partition.path}\": {cmd_output}')\n\t\n\t\treturn key_file\n\n\tdef unlock(self, partition, mountpoint, key_file):\n\t\t\"\"\"\n\t\tMounts a lukts2 compatible partition to a certain mountpoint.\n\t\tKeyfile must be specified as there's no way to interact with the pw-prompt atm.\n\n\t\t:param mountpoint: The name without absolute path, for instance \"luksdev\" will point to /dev/mapper/luksdev\n\t\t:type mountpoint: str\n\t\t\"\"\"\n\t\tfrom .disk import get_filesystem_type\n\t\tif '/' in mountpoint:\n\t\t\tos.path.basename(mountpoint)  # TODO: Raise exception instead?\n\t\tsys_command(f'/usr/bin/cryptsetup open {partition.path} {mountpoint} --key-file {os.path.abspath(key_file)} --type luks2')\n\t\tif os.path.islink(f'/dev/mapper/{mountpoint}'):\n\t\t\tself.mapdev = f'/dev/mapper/{mountpoint}'\n\t\t\tunlocked_partition = Partition(self.mapdev, None, encrypted=True, filesystem=get_filesystem_type(self.mapdev), autodetect_filesystem=False)\n\t\t\tunlocked_partition.allow_formatting = self.partition.allow_formatting\n\t\t\treturn unlocked_partition\n\n\tdef close(self, mountpoint=None):\n\t\tif not mountpoint:\n\t\t\tmountpoint = self.mapdev\n\n\t\tsys_command(f'/usr/bin/cryptsetup close {self.mapdev}')\n\t\treturn os.path.islink(self.mapdev) is False\n\n\tdef format(self, path):\n\t\tif (handle := sys_command(f\"/usr/bin/cryptsetup -q -v luksErase {path}\")).exit_code != 0:\n\t\t\traise DiskError(f'Could not format {path} with {self.filesystem} because: {b\"\".join(handle)}')\n", "path": "archinstall/lib/luks.py"}]}