diff --git a/DEBIAN/control b/DEBIAN/control index ee663dd..b3d7026 100644 --- a/DEBIAN/control +++ b/DEBIAN/control @@ -1,5 +1,5 @@ Package: system-installer -Version: 2.3.2 +Version: 2.4.3 Maintainer: Thomas Castleman Homepage: https://github.com/drauger-os-development/system-installer Section: admin diff --git a/usr/bin/system-installer.cxx b/usr/bin/system-installer.cxx index 444e789..f2bd0cb 100644 --- a/usr/bin/system-installer.cxx +++ b/usr/bin/system-installer.cxx @@ -46,7 +46,7 @@ using namespace std; -str VERSION = "2.3.2"; +str VERSION = "2.4.3"; str R = "\033[0;31m"; str G = "\033[0;32m"; str Y = "\033[1;33m"; diff --git a/usr/share/system-installer/UI/main.py b/usr/share/system-installer/UI/main.py index 0a5ef1f..46d386c 100755 --- a/usr/share/system-installer/UI/main.py +++ b/usr/share/system-installer/UI/main.py @@ -30,7 +30,7 @@ import common import subprocess import gi -import auto_partitioner +import auto_partitioner as ap import traceback gi.require_version('Gtk', '3.0') @@ -852,12 +852,12 @@ def make_space(self, widget, drive=None): label = self._set_default_margins(label) self.grid.attach(label, 1, 1, 3, 1) - data = auto_partitioner.check_disk_state() + data = ap.check_disk_state() devices = Gtk.ComboBoxText.new() for each in data: devices.append(each["name"], "%s, size: %sGB" % (each["name"], - int(auto_partitioner.bytes_to_gb(each["size"])))) + int(ap.bytes_to_gb(each["size"])))) devices.connect("changed", self.make_space_parts) devices = self._set_default_margins(devices) self.grid.attach(devices, 1, 2, 3, 1) @@ -897,14 +897,14 @@ def make_space(self, widget, drive=None): def make_space_parts(self, widget): """Set partitions to show for make_space()""" self.parts.remove_all() - data = auto_partitioner.check_disk_state() + data = ap.check_disk_state() name = widget.get_active_id() for each in data: if each["name"] == name: if "children" in each: for each1 in each["children"]: self.parts.append(each1["name"], - f"{each1['name']}, filesystem: {each1['fstype']}, size: {int(auto_partitioner.bytes_to_gb(each1['size']))}GB") + f"{each1['name']}, filesystem: {each1['fstype']}, size: {int(ap.bytes_to_gb(each1['size']))}GB") self.show_all() def confirm_remove_part(self, widget): @@ -943,7 +943,7 @@ def confirm_remove_part(self, widget): def remove_part(self, widget): """Interface for removing partitions""" part = self.parts.get_active_id() - auto_partitioner.delete_part(part) + ap.delete_part(part) if "nvme" in part: self.make_space("clicked", drive=part[:-2]) else: @@ -1050,7 +1050,7 @@ def confirm_auto_part(self, button): """Force User to either pick a drive to install to, abort, or backtrack """ - if auto_partitioner.is_EFI(): + if ap.is_EFI(): self.data["EFI"] = True else: self.data["EFI"] = False @@ -1093,7 +1093,7 @@ def set_up_partitioner_label(self, additional_message=""): input_string = """ What are the mount points for the partitions you wish to be used? Leave empty the partitions you don't want. - / MUST BE USED + ROOT PARTITION MUST BE USED """ if additional_message != "": @@ -1114,7 +1114,7 @@ def input_part(self, button): self.grid.attach(label, 1, 1, 3, 1) label2 = Gtk.Label() - label2.set_markup("/") + label2.set_markup("ROOT Partition (Mounted at /)") label2.set_justify(Gtk.Justification.RIGHT) label2 = self._set_default_margins(label2) self.grid.attach(label2, 1, 2, 1, 1) @@ -1124,25 +1124,37 @@ def input_part(self, button): self.root = self._set_default_margins(self.root) self.grid.attach(self.root, 2, 2, 1, 1) - label3 = Gtk.Label() - label3.set_markup("/boot/efi") - label3.set_justify(Gtk.Justification.RIGHT) - label3 = self._set_default_margins(label3) - self.grid.attach(label3, 1, 3, 1, 1) + root_info = Gtk.Button.new_with_label("Info on Root Partition") + root_info.connect("clicked", self.explain_root) + root_info = self._set_default_margins(root_info) + self.grid.attach(root_info, 3, 2, 1, 1) + + + if ap.is_EFI(): + label3 = Gtk.Label() + label3.set_markup("EFI Partition (Mounted at /boot/efi)") + label3.set_justify(Gtk.Justification.RIGHT) + label3 = self._set_default_margins(label3) + self.grid.attach(label3, 1, 3, 1, 1) + + self.efi = Gtk.Entry() + self.efi.set_text(self.data["EFI"]) + self.efi = self._set_default_margins(self.efi) + self.grid.attach(self.efi, 2, 3, 1, 1) - self.efi = Gtk.Entry() - self.efi.set_text(self.data["EFI"]) - self.efi = self._set_default_margins(self.efi) - self.grid.attach(self.efi, 2, 3, 1, 1) + efi_info = Gtk.Button.new_with_label("Info on EFI Partition") + efi_info.connect("clicked", self.explain_efi) + efi_info = self._set_default_margins(efi_info) + self.grid.attach(efi_info, 3, 3, 1, 1) - label5 = Gtk.Label() - label5.set_markup("Must be fat32") - label5.set_justify(Gtk.Justification.RIGHT) - label5 = self._set_default_margins(label5) - self.grid.attach(label5, 3, 3, 1, 1) + # label5 = Gtk.Label() + # label5.set_markup("Must be fat32") + # label5.set_justify(Gtk.Justification.RIGHT) + # label5 = self._set_default_margins(label5) + # self.grid.attach(label5, 3, 3, 1, 1) label4 = Gtk.Label() - label4.set_markup("/home") + label4.set_markup("Home Partition (Mounted at /home) (optional)") label4.set_justify(Gtk.Justification.RIGHT) label4 = self._set_default_margins(label4) self.grid.attach(label4, 1, 4, 1, 1) @@ -1152,6 +1164,11 @@ def input_part(self, button): self.home = self._set_default_margins(self.home) self.grid.attach(self.home, 2, 4, 1, 1) + home_info = Gtk.Button.new_with_label("Info on Home Partition") + home_info.connect("clicked", self.explain_home) + home_info = self._set_default_margins(home_info) + self.grid.attach(home_info, 3, 4, 1, 1) + label6 = Gtk.Label() label6.set_markup("SWAP") label6.set_justify(Gtk.Justification.RIGHT) @@ -1163,14 +1180,19 @@ def input_part(self, button): self.swap = self._set_default_margins(self.swap) self.grid.attach(self.swap, 2, 5, 1, 1) - label7 = Gtk.Label() - label7.set_markup("Must be linux-swap or file") - label7.set_justify(Gtk.Justification.RIGHT) - label7 = self._set_default_margins(label7) - self.grid.attach(label7, 3, 5, 1, 1) + swap_info = Gtk.Button.new_with_label("Info on SWAP") + swap_info.connect("clicked", self.explain_swap) + swap_info = self._set_default_margins(swap_info) + self.grid.attach(swap_info, 3, 5, 1, 1) + + # label7 = Gtk.Label() + # label7.set_markup("Must be linux-swap or file") + # label7.set_justify(Gtk.Justification.RIGHT) + # label7 = self._set_default_margins(label7) + # self.grid.attach(label7, 3, 5, 1, 1) button1 = Gtk.Button.new_with_label("Okay -->") - button1.connect("clicked", self.onnext4clicked) + button1.connect("clicked", self.check_man_part_settings) button1 = self._set_default_margins(button1) self.grid.attach(button1, 3, 6, 1, 1) @@ -1186,8 +1208,255 @@ def input_part(self, button): self.show_all() - def onnext4clicked(self, button): + def explain_root(self, button): + """Explain Root Partition requierments and limitations""" + self.clear_window() + + label = Gtk.Label() + label.set_markup("Info on Root Partition") + label.set_justify(Gtk.Justification.RIGHT) + label = self._set_default_margins(label) + self.grid.attach(label, 1, 1, 2, 1) + + label = Gtk.Label() + label.set_markup("What is an Root Partition?") + label.set_justify(Gtk.Justification.LEFT) + label = self._set_default_margins(label) + self.grid.attach(label, 1, 2, 1, 1) + + label = Gtk.Label() + label.set_markup(""" + The Root Partition is the partition where your operating system is + going to be installed, as well as the vast majority of apps you install + throughout the lifetime of the OS. + """) + label.set_justify(Gtk.Justification.LEFT) + label = self._set_default_margins(label) + self.grid.attach(label, 1, 3, 1, 1) + + label = Gtk.Label() + label.set_markup("Root Partition Requirements") + label.set_justify(Gtk.Justification.LEFT) + label = self._set_default_margins(label) + self.grid.attach(label, 2, 2, 1, 1) + + label = Gtk.Label() + label.set_markup(""" + Root Partitions are expected to be no smaller than 32 GB, and can be any + file system type except FAT32, FAT16, NTFS, or exFAT/vFAT. + + We suggest having a Root Partition of at least 64 GB, with a btrfs + file system. This will provide you with the ability to back up your OS in + case of a potentially risky upgrade or configuration change, while also + providing great file system performance. + """) + label.set_justify(Gtk.Justification.LEFT) + label = self._set_default_margins(label) + self.grid.attach(label, 2, 3, 1, 1) + + button2 = Gtk.Button.new_with_label("Exit") + button2.connect("clicked", self.exit) + button2 = self._set_default_margins(button2) + self.grid.attach(button2, 2, 6, 1, 1) + + button1 = Gtk.Button.new_with_label("<-- Back") + button1.connect("clicked", self.input_part) + button1 = self._set_default_margins(button1) + self.grid.attach(button1, 1, 6, 1, 1) + + self.show_all() + + def explain_efi(self, button): + """Explain efi Partition requierments and limitations""" + self.clear_window() + + label = Gtk.Label() + label.set_markup("Info on EFI Partition") + label.set_justify(Gtk.Justification.RIGHT) + label = self._set_default_margins(label) + self.grid.attach(label, 1, 1, 2, 1) + + label = Gtk.Label() + label.set_markup("What is an EFI Partition?") + label.set_justify(Gtk.Justification.LEFT) + label = self._set_default_margins(label) + self.grid.attach(label, 1, 2, 1, 1) + + label = Gtk.Label() + label.set_markup(""" + An EFI or UEFI Partition is a small partition which + contains the bootloader and related files for a system + using UEFI firmware. + + Since you booted your system in UEFI mode, you are + required to have one of these partitions. + """) + label.set_justify(Gtk.Justification.LEFT) + label = self._set_default_margins(label) + self.grid.attach(label, 1, 3, 1, 1) + + label = Gtk.Label() + label.set_markup("EFI Partition Requirements") + label.set_justify(Gtk.Justification.LEFT) + label = self._set_default_margins(label) + self.grid.attach(label, 2, 2, 1, 1) + + label = Gtk.Label() + label.set_markup(""" + EFI Partitions are expected to be no smaller than 200 MB, + and use a FAT32 or FAT16 file system. We suggest using a + FAT32 file system as it is the most widely supported. + + This partition must also have the \"boot\" and \"esp\" flags set. + """) + label.set_justify(Gtk.Justification.LEFT) + label = self._set_default_margins(label) + self.grid.attach(label, 2, 3, 1, 1) + + button2 = Gtk.Button.new_with_label("Exit") + button2.connect("clicked", self.exit) + button2 = self._set_default_margins(button2) + self.grid.attach(button2, 2, 6, 1, 1) + + button1 = Gtk.Button.new_with_label("<-- Back") + button1.connect("clicked", self.input_part) + button1 = self._set_default_margins(button1) + self.grid.attach(button1, 1, 6, 1, 1) + + self.show_all() + + def explain_home(self, button): + """Explain home Partition requierments and limitations""" + self.clear_window() + + label = Gtk.Label() + label.set_markup("Info on Home Partition") + label.set_justify(Gtk.Justification.RIGHT) + label = self._set_default_margins(label) + self.grid.attach(label, 1, 1, 2, 1) + + label = Gtk.Label() + label.set_markup("What is a Home Partition?") + label.set_justify(Gtk.Justification.LEFT) + label = self._set_default_margins(label) + self.grid.attach(label, 1, 2, 1, 1) + + label = Gtk.Label() + label.set_markup(""" + A Home Partition is a partition which contains all or + most of your user info. Having one of these is completely + optional. If you do opt for one, it can help keep your data + safe from data loss, or if the partition is on another drive, + it can ensure quick access times to data in your home + directory. + """) + label.set_justify(Gtk.Justification.LEFT) + label = self._set_default_margins(label) + self.grid.attach(label, 1, 3, 1, 1) + + label = Gtk.Label() + label.set_markup("Home Partition Requirements") + label.set_justify(Gtk.Justification.LEFT) + label = self._set_default_margins(label) + self.grid.attach(label, 2, 2, 1, 1) + + label = Gtk.Label() + label.set_markup(""" + Home Partitions are expected to be no smaller than 500 MB, + and can be any file system except FAT32, FAT16, exFAT/vFAT, or NTFS. + We suggest using a btrfs file system as it has features useful for + backing up your data, as well as is capable of optimizing itself for + solid-state drives. + """) + label.set_justify(Gtk.Justification.LEFT) + label = self._set_default_margins(label) + self.grid.attach(label, 2, 3, 1, 1) + + button2 = Gtk.Button.new_with_label("Exit") + button2.connect("clicked", self.exit) + button2 = self._set_default_margins(button2) + self.grid.attach(button2, 2, 6, 1, 1) + + button1 = Gtk.Button.new_with_label("<-- Back") + button1.connect("clicked", self.input_part) + button1 = self._set_default_margins(button1) + self.grid.attach(button1, 1, 6, 1, 1) + + self.show_all() + + def explain_swap(self, button): + """Explain swap partitions and files""" + self.clear_window() + + label = Gtk.Label() + label.set_markup("Info on SWAP Partition") + label.set_justify(Gtk.Justification.RIGHT) + label = self._set_default_margins(label) + self.grid.attach(label, 1, 1, 2, 1) + + label = Gtk.Label() + label.set_markup("What is an SWAP Partition?") + label.set_justify(Gtk.Justification.LEFT) + label = self._set_default_margins(label) + self.grid.attach(label, 1, 2, 1, 1) + + label = Gtk.Label() + label.set_markup(""" + A SWAP Partition is a partition which your system may use to + extend system memory. It is useful for when your system is + extreamly low on memory. + + Because it is on your internal drive, it is capable of retaining + data between reboots and even total powerloss events. Thanks to this, + it also enables the usage of the Hibernate and Hybrid Suspend features. + + SWAP can also be used as a file. This can allow you to easily create more + SWAP later, should you deem it necessary. + + Having SWAP is mandatory on this operating system. As such, if you do not + create a SWAP partition, a SWAP file will be created for you. + """) + label.set_justify(Gtk.Justification.LEFT) + label = self._set_default_margins(label) + self.grid.attach(label, 1, 3, 1, 1) + + label = Gtk.Label() + label.set_markup("SWAP Partition Requirements") + label.set_justify(Gtk.Justification.LEFT) + label = self._set_default_margins(label) + self.grid.attach(label, 2, 2, 1, 1) + + label = Gtk.Label() + label.set_markup(""" + SWAP Partitions are expected to be no smaller than 100 MB, + and use linux-swap file system. + + If you are not sure how big you should make your SWAP partition, + simply put in "FILE" and a SWAP file of the appropriate size will + be generated for you. + """) + label.set_justify(Gtk.Justification.LEFT) + label = self._set_default_margins(label) + self.grid.attach(label, 2, 3, 1, 1) + + button2 = Gtk.Button.new_with_label("Exit") + button2.connect("clicked", self.exit) + button2 = self._set_default_margins(button2) + self.grid.attach(button2, 2, 6, 1, 1) + + button1 = Gtk.Button.new_with_label("<-- Back") + button1.connect("clicked", self.input_part) + button1 = self._set_default_margins(button1) + self.grid.attach(button1, 1, 6, 1, 1) + + self.show_all() + + def check_man_part_settings(self, button): """Check device paths provided for manual partitioner""" + try: + efi = self.efi.get_text() + except (AttributeError, NameError): + efi = "" if ((self.root.get_text() == "") or ( self.root.get_text()[0:5] != "/dev/")): label = self.set_up_partitioner_label("ERROR: / NOT SET") @@ -1209,8 +1478,7 @@ def onnext4clicked(self, button): self.show_all() return - elif (((self.efi.get_text() == "") or ( - self.efi.get_text()[0:5] != "/dev/")) and auto_partitioner.is_EFI()): + elif (((efi == "") or (efi[0:5] != "/dev/")) and ap.is_EFI()): label = self.set_up_partitioner_label( "ERROR: System is running EFI. An EFI partition must be set.") try: @@ -1221,8 +1489,7 @@ def onnext4clicked(self, button): self.show_all() return - elif (not os.path.exists(self.efi.get_text()) or ( - self.efi.get_text() == "")) and auto_partitioner.is_EFI(): + elif (not os.path.exists(efi) or (efi == "")) and ap.is_EFI(): label = Gtk.Label() label = self.set_up_partitioner_label("ERROR: Not a Valid Device on /boot/efi") try: @@ -1283,11 +1550,10 @@ def onnext4clicked(self, button): self.show_all() return if ((self.swap.get_text().upper() == "FILE") or (self.swap.get_text() == "")): - if auto_partitioner.size_of_part(self.root.get_text()) < \ - auto_partitioner.get_min_root_size(bytes=False): + if ap.size_of_part(self.root.get_text()) < ap.get_min_root_size(bytes=False): label_string = \ - f""" / is too small. Minimum Root Partition size is { round(auto_partitioner.get_min_root_size(bytes=False)) } GB - Make a swap partition to reduce this minimum to { round(auto_partitioner.get_min_root_size(swap=False, bytes=False)) } GB + f""" / is too small. Minimum Root Partition size is { round(ap.get_min_root_size(bytes=False)) } GB + Make a swap partition to reduce this minimum to { round(ap.get_min_root_size(swap=False, bytes=False)) } GB """ label = self.set_up_partitioner_label(label_string) try: @@ -1299,9 +1565,8 @@ def onnext4clicked(self, button): self.show_all() return else: - if auto_partitioner.size_of_part(self.root.get_text()) < \ - auto_partitioner.get_min_root_size(swap=False, bytes=False): - label_string = f"/ is too small. Minimum Root Partition size is { round(auto_partitioner.get_min_root_size(swap=False, bytes=False)) } GB" + if ap.size_of_part(self.root.get_text()) < ap.get_min_root_size(swap=False, bytes=False): + label_string = f"/ is too small. Minimum Root Partition size is { round(ap.get_min_root_size(swap=False, bytes=False)) } GB" label = self.set_up_partitioner_label(label_string) try: self.grid.remove(self.grid.get_child_at(1, 1)) @@ -1320,10 +1585,10 @@ def onnext4clicked(self, button): self.data["ROOT"] = self.root.get_text() self.show_all() - if self.efi.get_text() in ("", " ", None): + if efi in ("", " ", None): self.data["EFI"] = "NULL" else: - self.data["EFI"] = self.efi.get_text() + self.data["EFI"] = efi if self.home.get_text() in ("", " ", None): self.data["HOME"] = "NULL" else: @@ -1371,18 +1636,18 @@ def options(self, button): self.extras = self._set_default_margins(self.extras) self.grid.attach(self.extras, 1, 3, 2, 1) - label2 = Gtk.Label() - label2.set_markup(""" - Update the system during installation""") - label2.set_justify(Gtk.Justification.LEFT) - label2 = self._set_default_margins(label2) - self.grid.attach(label2, 1, 4, 2, 1) + # label2 = Gtk.Label() + # label2.set_markup(""" + # Update the system during installation""") + # label2.set_justify(Gtk.Justification.LEFT) + # label2 = self._set_default_margins(label2) + # self.grid.attach(label2, 1, 4, 2, 1) - self.updates = Gtk.CheckButton.new_with_label("Update before reboot") - if self.data["UPDATES"] == 1: - self.updates.set_active(True) - self.updates = self._set_default_margins(self.updates) - self.grid.attach(self.updates, 1, 5, 2, 1) + # self.updates = Gtk.CheckButton.new_with_label("Update during Installation") + # if self.data["UPDATES"] == 1: + # self.updates.set_active(True) + # self.updates = self._set_default_margins(self.updates) + # self.grid.attach(self.updates, 1, 5, 2, 1) label2 = Gtk.Label() label2.set_markup(""" @@ -1415,10 +1680,10 @@ def options_next(self, button): self.data["EXTRAS"] = 1 else: self.data["EXTRAS"] = 0 - if self.updates.get_active(): - self.data["UPDATES"] = 1 - else: - self.data["UPDATES"] = 0 + # if self.updates.get_active(): + # self.data["UPDATES"] = 1 + # else: + self.data["UPDATES"] = 0 if self.login.get_active(): self.data["LOGIN"] = 1 else: @@ -1573,6 +1838,8 @@ def keyboard(self, button): self.model_menu.append(model[each8], each8) if self.data["MODEL"] != "": self.model_menu.set_active_id(self.data["MODEL"]) + else: + self.model_menu.set_active_id("pc105") self.model_menu = self._set_default_margins(self.model_menu) self.grid.attach(self.model_menu, 2, 2, 3, 1) diff --git a/usr/share/system-installer/auto_partitioner.py b/usr/share/system-installer/auto_partitioner.py index fae7fba..e48fee7 100755 --- a/usr/share/system-installer/auto_partitioner.py +++ b/usr/share/system-installer/auto_partitioner.py @@ -173,7 +173,7 @@ def size_of_part(part_path, bytes=False): def get_drive_path(part_path): """Get drive path from partition path""" - if "nvme" in part_path: + if ("nvme" in part_path) or ("mmc" in part_path): output = part_path[:part_path.index("p")] else: count = 0 @@ -222,7 +222,13 @@ def get_min_root_size(swap=True, ram_size=False, ram_size_unit=True, def check_disk_state(): """Check disk state as registered with lsblk - Returns data as dictionary""" + Returns data as dictionary + """ + try: + subprocess.check_call(["partprobe"]) + except subprocess.CalledProcessError: + print("`partprobe` failed. Provided info may not be up-to-date.") + time.sleep(0.1) command = ["lsblk", "--json", "--paths", "--bytes", "--output", "name,size,type,fstype"] data = json.loads(subprocess.check_output(command))["blockdevices"] @@ -232,6 +238,18 @@ def check_disk_state(): return data +def get_fs(part_name: str): + """Get filesystem type for given partition""" + disk = check_disk_state() + for each in disk: + if each["name"] == part_name: + return each["fstype"] + if "children" in each: + for each1 in each["children"]: + if each1["name"] == part_name: + return each1["fstype"] + + def __mkfs__(device, fs): """Set partition filesystem""" # pre-define command diff --git a/usr/share/system-installer/common.py b/usr/share/system-installer/common.py index 2014130..8cdadf3 100755 --- a/usr/share/system-installer/common.py +++ b/usr/share/system-installer/common.py @@ -28,7 +28,7 @@ def unique(starting_list): """Function to get a list down to only unique elements""" - # intilize a null list + # initialize a null list unique_list = [] # traverse for all elements for each in starting_list: diff --git a/usr/share/system-installer/installer.py b/usr/share/system-installer/installer.py index f5cd6b8..03fa230 100755 --- a/usr/share/system-installer/installer.py +++ b/usr/share/system-installer/installer.py @@ -96,7 +96,7 @@ def install(settings, local_repo): settings["EFI"] = partitioning["EFI"] settings["HOME"] = partitioning["HOME"] else: - if settings["EFI"] == "NULL": + if settings["EFI"] in ("NULL", None, "", False): auto_partitioner.make_part_boot(settings["ROOT"]) else: auto_partitioner.make_part_boot(settings["EFI"]) @@ -158,7 +158,11 @@ def install(settings, local_repo): except FileNotFoundError: pass common.eprint(" ### EXTRACTING SQUASHFS ### ") - check_call(["unsquashfs", config["squashfs_Location"]]) + cmd = ["unsquashfs", config["squashfs_Location"]] + # we're doing this as a tuple/list so that more can be added to this list later + if auto_partitioner.get_fs(settings["ROOT"]) in ("ext2",): + cmd.append("-no-xattrs") + check_call(cmd) common.eprint(" ### EXTRACTION COMPLETE ### ") file_list = os.listdir("/mnt/squashfs-root") for each in file_list: diff --git a/usr/share/system-installer/modules/install_extras.py b/usr/share/system-installer/modules/install_extras.py index ccfafe7..27215d5 100644 --- a/usr/share/system-installer/modules/install_extras.py +++ b/usr/share/system-installer/modules/install_extras.py @@ -53,47 +53,26 @@ def install_extras(): # Newer cards take different drivers from older cards for each in ("BCM43142", "BCM4331", "BCM4360", "BCM4352"): if each in pci: - install_list = install_list + ["broadcom-sta-dkms", "dkms", "wireless-tools"] + install_list = install_list + ["broadcom-sta-dkms", "dkms", + "wireless-tools"] break if len(install_list) == 2: - for each in ("BCM4311", "BCM4312", "BCM4313", "BCM4321", "BCM4322", "BCM43224", "BCM43225", "BCM43227", "BCM43228"): + for each in ("BCM4311", "BCM4312", "BCM4313", "BCM4321", "BCM4322", + "BCM43224", "BCM43225", "BCM43227", "BCM43228"): if each in pci: - install_list = install_list.append("bcmwl-kernel-source") + install_list.append("bcmwl-kernel-source") break # Nvidia graphics cards if "nvidia" in pci.lower(): - drivers = [] - # We have other work we need to do after installing the Nvidia driver - NVIDIA = True - with cache.actiongroup(): - for each in cache: - if "nvidia-driver-" in each.name: - drivers.append(each.name) - for each in range(len(drivers) - 1, -1, -1): - try: - drivers[each] = int(drivers[each].split("-")[-1]) - except ValueError: - pass - # Get the latest Nvidia driver - largest = drivers[0] - for each in drivers: - try: - if int(each) > largest: - largest = each - except ValueError: - pass - install_list.append("nvidia-driver-" + str(largest)) + # this isn't the ideal thing to do. Logic will be added later to handle + # installing drivers and `disable-nouveau` for older cards. + install_list.append("nvidia-driver-latest") # Install everything we want with cache.actiongroup(): for each in install_list: cache[each].mark_install() cache.commit() - # Puge all the stuff we don't + # Purge all the stuff we don't want purge.purge_package("gstreamer1.0-fluendo-mp3") cache.close() - # Blacklist Nouveau if we installed the Nvidia drivers - if NVIDIA: - __eprint__(" ### NVIDIA DRIVERS MAY HAVE BEEN INSTALLED. DISABLING NOUVEAU. ### ") - with open("/etc/modprobe.d/blacklist-nvidia-nouveau.conf", "w+") as blacklist: - blacklist.write("blacklist nouveau\noptions nouveau modeset=0\n") __eprint__(" ### install_extras.py CLOSED ### ") diff --git a/usr/share/system-installer/modules/install_updates.py b/usr/share/system-installer/modules/install_updates.py index 4f3727c..7b0c8d5 100755 --- a/usr/share/system-installer/modules/install_updates.py +++ b/usr/share/system-installer/modules/install_updates.py @@ -41,7 +41,10 @@ def update_system(): cache = apt.cache.Cache() cache.update() cache.open() - cache.upgrade(dist_upgrade=True) + try: + cache.upgrade(dist_upgrade=True) + except apt.apt_pkg.Error: + print("ERROR: Possible held packages. Update may be partially completed.") cache.commit() purge.autoremove(cache) cache.close() diff --git a/usr/share/system-installer/modules/make_swap.py b/usr/share/system-installer/modules/make_swap.py index deabf66..c55c7e2 100755 --- a/usr/share/system-installer/modules/make_swap.py +++ b/usr/share/system-installer/modules/make_swap.py @@ -51,10 +51,25 @@ def make_swap(): load_balancer = 3 master_string = "\0" * multiplyer swap = round(swap / multiplyer) + loop_count = round(swap / (multiplyer * load_balancer)) + print_point = round(loop_count / 20) + perc = 5 with open("/.swapfile", "w+") as swapfile: - for i in range(round(swap / (multiplyer * load_balancer))): + swapfile.write("") + swapfile.flush() + try: + subprocess.check_call(["chattr", "+C", "/.swapfile"]) + except subprocess.CalledProcessError: + # if this happens, we likely are not using a btrfs file system + # ignore + pass + for i in range(loop_count): swapfile.write(master_string * (multiplyer * load_balancer)) swapfile.flush() + if (i % print_point) == 0: + if perc <= 100: + eprint(f"SWAP FILE { perc }% complete") + perc += 5 chmod("/.swapfile", 0o600) subprocess.check_call(["mkswap", "/.swapfile"], stdout=stderr.buffer) sleep(0.1) diff --git a/usr/share/system-installer/modules/master.py b/usr/share/system-installer/modules/master.py index 325e6d5..2562786 100755 --- a/usr/share/system-installer/modules/master.py +++ b/usr/share/system-installer/modules/master.py @@ -132,12 +132,12 @@ def mk_swap(SWAP): except IOError: eprint("Adding swap failed. Must manually add later") - def apt(UPDATES, EXTRAS, INTERNET): + def apt(UPDATES, EXTRAS): """Run commands for apt sequentially to avoid front-end lock""" # MainInstallation.__install_updates__(UPDATES, INTERNET) - if ((UPDATES) and (INTERNET)): + if UPDATES: install_updates.update_system() - if ((EXTRAS) and (INTERNET)): + if EXTRAS: install_extras.install_extras() def set_passwd(USERNAME, PASSWORD): diff --git a/usr/share/system-installer/tests/auto_partitioner.py b/usr/share/system-installer/tests/auto_partitioner.py new file mode 120000 index 0000000..84df7e3 --- /dev/null +++ b/usr/share/system-installer/tests/auto_partitioner.py @@ -0,0 +1 @@ +../auto_partitioner.py \ No newline at end of file diff --git a/usr/share/system-installer/tests/common.py b/usr/share/system-installer/tests/common.py new file mode 120000 index 0000000..a11703e --- /dev/null +++ b/usr/share/system-installer/tests/common.py @@ -0,0 +1 @@ +../common.py \ No newline at end of file diff --git a/usr/share/system-installer/tests/test_auto_partitioner.py b/usr/share/system-installer/tests/test_auto_partitioner.py new file mode 100755 index 0000000..81c0d67 --- /dev/null +++ b/usr/share/system-installer/tests/test_auto_partitioner.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# test_auto_partitioner.py +# +# Copyright 2022 Thomas Castleman +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. +# +# +"""Tests for auto_partitioner""" +import auto_partitioner as ap +import os + +def test_get_min_root_size_with_swap_part(): + """Make sure our math is correct to get the min root size, assuming no swap partition""" + assert ap.get_min_root_size(swap=False) >= (ap.config["min root size"] * (1000 ** 2)) + assert ap.get_min_root_size(swap=False, bytes=False) >= ap.bytes_to_gb(ap.config["min root size"] * (1000 ** 2)) + + +def test_get_min_root_size_without_swap_part(): + """make sure our root part is big enough to accommodate a swap file""" + assert ap.get_min_root_size(ram_size=4, bytes=False) >= 29 + assert ap.get_min_root_size(ram_size=6, bytes=False) >= 31.449 + assert ap.get_min_root_size(ram_size=8, bytes=False) >= 33.828 + assert ap.get_min_root_size(ram_size=12, bytes=False) >= 38.464 + assert ap.get_min_root_size(ram_size=16, bytes=False) >= 43 + assert ap.get_min_root_size(ram_size=24, bytes=False) >= 51.8989 + assert ap.get_min_root_size(ram_size=64, bytes=False) >= 95 + + +def test_is_EFI(): + """Check if the checks if a system is an EFI system are working""" + assert os.path.isdir("/boot/efi") == ap.is_EFI() diff --git a/usr/share/system-installer/tests/test_common.py b/usr/share/system-installer/tests/test_common.py new file mode 100755 index 0000000..791e6e1 --- /dev/null +++ b/usr/share/system-installer/tests/test_common.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# test_common.py +# +# Copyright 2022 Thomas Castleman +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. +# +# +"""Test Common Library""" +import common +import random +import os +import string + + +def random_string(length=None): + """Generate random string. + + If "length" is None, use a random length, 1-100. + """ + # initializing size of string + if not isinstance(length, (int, float)): + N = random.randint(1,50) + else: + N = int(length) + + # using random.choices() + # generating random strings + res = ''.join(random.choices(string.ascii_uppercase + + string.digits, k=N)) + + # return result + return str(res) + + +def test_real_num(count=0): + """Ensure we calculate real numbers correctly""" + # set up + test_numbers = [] + for each in range(10000): + if random.choice([True, False]): + # random float + test_numbers.append(random.randint(-100000000,100000000) + random.random()) + else: + # random int + test_numbers.append(random.randint(-100000000,100000000)) + + # run the test + outputs = {} + for each in test_numbers: + outputs[each] = common.real_number(each) + + # evaluate results + for each in outputs: + if each <= 0: + assert outputs[each] == 0 + else: + assert isinstance(outputs[each], int) + + # test again, if necessary + if count <= 200: + count += 1 + test_real_num(count=count) + + +def test_recursive_mkdir(): + """Ensure recursive mkdir makes directories correctly and recurses + correctly + """ + for each in range(1000): + # generate random path in current directory, 1000 times over + path = [] + for each1 in range(random.randint(2, 40)): + path.append(random_string()) + path2 = "/".join(path) + + # create random path + common.recursive_mkdir(path2) + + # check if generated path exists + test = "" + for each in path: + if test == "": + test = each + else: + test = f"{ test }/{ each }" + assert os.path.isdir(test) + assert test == path2 + os.removedirs(path2)