def start(self): """ Start the frontend """ self.header(_("Summary")) # Parse changed partitions print(_("These partitions will be used:") + "\n") changed = self.moduleclass.modules_settings["partdisks"]["changed"] for obj, value in changed.items(): try: fs = value["obj"].fileSystem.type mountpoint = value["changes"]["useas"] # If /, tell the user that the distribution will be installed here if mountpoint == "/": text = ": " + bold(_("%(distroname)s will be installed here.") % {"distroname":self.moduleclass.main_settings["distro"]}) else: text = "" print(_(" - %(part)s (%(filesystem)s, mounts on %(mountpoint)s)%(text)s") % {"part":obj, "filesystem":fs, "mountpoint":mountpoint, "text":text}) except: verbose("Unable to print details for %s" % obj) #print(_("%(distroname)s will be installed in %(rootpartition)s.") % {"distroname":self.moduleclass.main_settings["distro"], "rootpartition":self.moduleclass.modules_settings["partdisks"]["root"]}) #print(_("%(swappartition)s will be used as swap.") % {"swappartition":self.moduleclass.modules_settings["partdisks"]["swap"]}) print # USB-Persistence try: size = self.moduleclass.modules_settings["echo.partusb"]["size"] print(_("The persistence partion will be of %s MB.") % size) print except: pass try: print(_("The default locale will be %(locale)s.") % {"locale":self.moduleclass.modules_settings["language"]["language"]}) except: pass try: print(_("The default keyboard layout will be %(layout)s.") % {"layout":",".join(self.moduleclass.modules_settings["language"]["layout"])}) except: pass print try: print(_("The main user will be %(userfullname)s (%(username)s).") % {"userfullname":self.moduleclass.modules_settings["userhost"]["userfullname"], "username":self.moduleclass.modules_settings["userhost"]["username"]}) if self.moduleclass.modules_settings["userhost"]["root"]: # Root enabled print(_("Root account is enabled.")) print(_("The computer hostname will be %(hostname)s.") % {"hostname":self.moduleclass.modules_settings["userhost"]["hostname"]}) except: pass try: print(_("The machine will use this timezone: %(timezone)s.") % {"timezone":self.moduleclass.modules_settings["timezone"]["timezone"]}) except: pass print try: print(_("The bootloader (%(bootloader)s) will be installed in %(bootloaderpath)s.") % {"bootloader":self.moduleclass.modules_settings["bootloader"]["bootloader"],"bootloaderpath":self.moduleclass.modules_settings["bootloader"]["device"]}) except: pass print # We should continue? res = self.question(_("Do you really want to continue?"), default=True) if not res: self.end() verbose("Beginning installation.") self.header(_("Installing..."))
def print_devices_partitions(self, interactive=False, only_disks=False, skip_notable=False): """ Prints hard disks and partititons """ num = 0 choices = {} for device, obj in self.devices.iteritems(): disk = self.disks[device] # If should skip disks without table, do it now. if skip_notable: if disk == "notable": verbose("Disk %s has no partition table. Create a partition table then re-run this action." % device) continue num +=1 if interactive: _num = "%s) " % num else: _num = "" choices[num] = disk if disk == "notable": choices[num] = obj # Cache obj in self.changed if not obj.path in self.changed: self.changed[obj.path] = {"obj":choices[num], "changes":{}} # Check if this should be changed. if obj.path in self.changed and not self.changed[obj.path]["changes"] == {}: _changed = ": " + str(self.changed[obj.path]["changes"]) else: _changed = "" print("%s%s - %s (%s GB)%s" % (_num, obj.path, obj.model, round(obj.getSize(unit="GB"), 2),_changed)) if disk == "notable": print print(" No partition table.") print if not only_disks and disk != "notable": print # now print available partitions. for part in list(disk._partitions) + disk.getFreeSpacePartitions(): if part.fileSystem == None and not part.number == -1 and not part.type == 2: # If filesystem == None, skip. _fs = _("not formatted") elif part.number == -1: _fs = _("free space") elif part.type == 2: # Extended partition _fs = _("extended") else: _fs = part.fileSystem.type if part.name: _name = part.name else: _name = "Untitled" if int(part.getSize("GB")) > 0: # We can use GigaBytes to represent partition size. _size = round(part.getSize("GB"), 2) _unit = "GB" elif int(part.getSize("MB")) > 0: # Partition is too small to be represented with gigabytes. Use megabytes instead. _size = round(part.getSize("MB"), 2) _unit = "MB" else: # Last try.. using kilobytes _size = round(part.getSize("kB"), 2) _unit = "kB" # Cache part in self.changed if not part.path in self.changed: self.changed[part.path] = {"obj":part, "changes":{}} __changes = copy.copy(self.changed[part.path]["changes"]) if "format_real" in __changes: del __changes["format_real"] # Check if this should be changed. if part.path in self.changed and not __changes == {}: _changed = ": " + str(__changes) else: _changed = "" num +=1 if interactive: _num = "%s) " % num choices[num] = part else: _num = "" if part.path in self.distribs: # This partition contains a distribution! _moarspace = "%s: " % bold(self.distribs[part.path]) else: _moarspace = "" print(" %s%s%s (%s) - %s (%s %s)%s" % (_num, _moarspace, _name, part.path, _fs, _size, _unit, _changed)) print if interactive: if not only_disks: # Guided partitioning num += 1 choices[num] = "automatic" print("%s) " % num + bold(_("Automatic partitioning"))) # Write to memory num += 1 choices[num] = "write" print("%s) " % num + _("Write to memory")) # Reload original structure num += 1 choices[num] = "reload" print("%s) " % num + _("Reload original structure")) # Commit num += 1 choices[num] = "commit" print("%s) " % num + _("Commit")) # back num += 1 choices[num] = "back" print("%s) " % num + _("<- Back") + "\n") if interactive: # Prompt res = self.entry(_("Enter the number of the partition(s)/device(s) you want to edit here")) return res, choices
def edit_partitions_write(self): """ Writes, in memory, the changes made. """ self.header(_("Write to memory")) print(_("Do you want to write to memory your changes?")) print(_("This will let you continue to manage the partitioning scheme.") + "\n") print(_("%(note)s: This will %(not)s write the changes to the disk! It only simulates it. You should write to memory every time you delete and resize partitions. This will let you add new partitions on the freed space.") % {"note":bold(_("NOTE")), "not":bold(_("not"))}) print(_("You can always restore original structure via the appropriate option into the main menu.")) print res = self.question(_("Do you want to write to memory the changes?"), default=False) if res: failed = lib.write_memory(self.changed) if failed != {}: return self.edit_partitions(warning=_("Something has failed: %s!") % str(failed)) else: return self.edit_partitions(information=_("Ok! You can continue."))
def automatic(self, warning=False, information=False, jumpto=False, by="freespace"): """ Automatic partitioner. That's cool, babe! """ self.header(_("Automatic partitioner")) if warning: warn(warning + "\n") if information: info(information + "\n") # *RELOAD* original structure self._reload() if not jumpto: print(_("Available disks:")) res, choices = self.print_devices_partitions(interactive=True, only_disks=True, skip_notable=True) try: res = int(res) except ValueError: return self.edit_partitions(warning=_("You didn't entered a valid number.")) if not res in choices: # Number doesn't is in choices. return self.edit_partitions(warning=_("You didn't entered a valid number.")) obj = choices[res] if obj == "back": return self.edit_partitions() # Go back. self.header(_("Automatic partitioner") + " - %s" % obj.device.path) actions = {} actions[0] = (_("Use the free space"), "freespace") actions[1] = (_("Delete another system"), "delete") actions[2] = (_("Delete all partitions"), "deleteall") actions[3] = (_("Back"), "back") # Print actions for num, act in actions.iteritems(): print(" %d) %s") % (num, act[0]) print result = self.entry(_("Please insert your action here")) try: result = int(result) except: return self.edit_partitions(warning=_("You haven't entered a valid action.")) if not result in actions: return self.edit_partitions(warning=_("You haven't entered a valid action.")) by = actions[result][1] if by == "back": return self.edit_partitions() # Go back. if jumpto: obj = jumpto # We can continue. if by == "freespace": part, swap, swapcreated = lib.automatic_check(obj, by=by) if part == None: return self.automatic(information=_("Too little free space")) elif part == False: # Failed. return self.automatic(warning=_("Failed to add partition (AUTOMATIC)")) else: # Yey! self.header(_("Automatic partitioner choices")) if swap: # Get swap size. if int(swap.getSize("GB")) == 0: # GB is too big, use MB instead. _swap_unit = "MB" _swap_size = round(swap.getSize("MB")) else: # We can use GB. _swap_unit = "GB" _swap_size = round(swap.getSize("GB")) # Set-up touched... self.touched[part.path] = True if swap: self.touched[swap.path] = True print(" / - %s (%s - %s GB)" % (part.path, part.fileSystem.type, round(part.getSize("GB"), 2))) if swap: print(" swap - %s (%s %s)" % (swap.path, _swap_size, _swap_unit)) elif by == "delete": delete, swap = lib.automatic_check(obj, by=by) swapcreated = False print delete if not delete: # No distribution to delete. return self.automatic(warning=_("No distribution to delete!")) else: # Yey! self.header(_("Automatic partitioner choices")) if swap: # Get swap size. if int(swap.getSize("GB")) == 0: # GB is too big, use MB instead. _swap_unit = "MB" _swap_size = round(swap.getSize("MB")) else: # We can use GB. _swap_unit = "GB" _swap_size = round(swap.getSize("GB")) actions = {} num = 0 for part, distrib in delete: actions[num] = part print(" %s) (%s) / - %s (%s - %s GB)" % (num, bold(distrib), part.path, part.fileSystem.type, round(part.getSize("GB"), 2))) num += 1 print print(" %s) " % num + _("<- Back")) actions[num] = "back" print if swap: print(_("Whatever will be the selection, this swap partition will be used:") + "\n") print(" swap - %s (%s %s)" % (swap.path, _swap_size, _swap_unit)) print else: # Swap will be created - hopefully - by freespace. print(_("A swap partition, if all conditions are meet, will be created.")) print # Select action result = self.entry(_("Please insert your value here")) try: result = int(result) except: return self.automatic(warning=_("You didn't entered a valid value.")) if not result in actions: return self.automatic(warning=_("You didn't entered a valid value.")) if actions[result] == "back": # Go back. return self.automatic() # If we can continue, delete partition!! lib.delete_partition(actions[result]) # Now there is freespace ;-) # So use "freespace". return self.automatic(jumpto=obj, by="freespace") elif by == "deleteall": # The simplest ever! lib.delete_all(obj) # Now there is freespace ;-) # So use "freespace". return self.automatic(jumpto=obj, by="freespace") print res = self.question(_("Are you happy with this? Enter 'y' to write changes in memory"), default=True) # Cache part in self.changed if not part.path in self.changed: self.changed[part.path] = {"obj":part, "changes":{}} # Cache swap in self.changed if swap: if not swap.path in self.changed: self.changed[swap.path] = {"obj":swap, "changes":{}} if res: # Add useas. self.changed[part.path]["changes"] = {"useas":"/", "format_real":"ext4"} if swap: self.changed[swap.path]["changes"] = {"useas":"swap", "format_real":"linux-swap(v1)"} elif by == "freespace" and not jumpto: # We should deleted created partitions lib.delete_partition(part) if swapcreated: lib.delete_partition(swap) # We should delete swap if it was created. else: # We cannot undo, restore old structure self._reload() # Remove useas flags self.changed[part.path]["changes"] = {} if swap: self.changed[swap.path]["changes"] = {} return self.edit_partitions(information=_("Successfully added partitions."))
def edit_partitions(self, warning=None, information=None, device=False, device_changes=False): """ Partition editor. """ self.header(_("Edit Partition structure")) if warning: warn(warning + "\n") if information: info(information + "\n") res, choices = self.print_devices_partitions(interactive=True) try: res = int(res) except ValueError: return self.edit_partitions(warning=_("You didn't entered a valid number.")) if not res in choices: # Number doesn't is in choices. return self.edit_partitions(warning=_("You didn't entered a valid number.")) # We can continue. obj = choices[res] if obj == "back": return self.back() # We should go back. if obj == "write": return self.edit_partitions_write() # We should write to disk. if obj == "automatic": return self.automatic() # Automatic partitioning. if obj == "reload": return self._reload(interactive=True) # Reload. if obj == "commit": return self.commit(interactive=True) # Commit. self.header(_("Editing disk/partition")) print(_("You've selected:") + "\n") if type(obj) == lib.p.partition.Partition: if obj.fileSystem == None and not obj.number == -1 and not obj.type == 2: # If filesystem == None, skip. _fs = _("not formatted") elif obj.number == -1: _fs = _("free space") elif obj.type == 2: # Extended objition _fs = _("extended") else: _fs = obj.fileSystem.type if obj.name: _name = obj.name else: _name = "Untitled" if obj.path in self.distribs: # This partition contains a distribution! _moarspace = "%s: " % self.distribs[obj.path] else: _moarspace = "" if int(obj.getSize("GB")) > 0: # We can use GigaBytes to represent partition size. _size = round(obj.getSize("GB"), 2) _unit = "GB" elif int(obj.getSize("MB")) > 0: # Partition is too small to be represented with gigabytes. Use megabytes instead. _size = round(obj.getSize("MB"), 2) _unit = "MB" else: # Last try.. using kilobytes _size = round(obj.getSize("kB"), 2) _unit = "kB" print(bold(" %s%s (%s) - %s (%s %s)\n" % (_moarspace, _name, obj.path, _fs, _size, _unit))) actions = {} # Populate actions if obj.number == -1: actions[1] = (_("Add partition"), self.edit_partitions_add) num = 1 else: actions[1] = (_("Format partition"), self.edit_partitions_format) actions[2] = (_("Delete partition"), self.edit_partitions_delete) actions[3] = (_("Resize partition"), self.edit_partitions_resize) actions[4] = (_("Use as..."), self.edit_partitions_useas) actions[5] = (_("Unmark changes"), self.edit_partitions_unmark) num = 5 actions[num + 1] = (_("<- Back"), self.edit_partitions) elif type(obj) == lib.p.disk.Disk: # A disk. device = obj.device print(" %s - %s (%s GB)\n" % (device.path, device.model, round(device.getSize(unit="GB"), 2))) actions = {} # Populate actions actions[1] = (_("Delete all partitions on the disk"), self.edit_partitions_deleteall) actions[2] = (_("Unmark changes"), self.edit_partitions_unmark) actions[3] = (_("<- Back"), self.edit_partitions) else: # A device. device = obj print(" %s - %s (%s GB)\n" % (device.path, device.model, round(device.getSize(unit="GB"), 2))) actions = {} # Populate actions actions[1] = (_("Create MBR partition table"), self.edit_partitions_newmbr) actions[2] = (_("Create GPT partition table"), self.edit_partitions_newgpt) actions[3] = (_("<- Back"), self.edit_partitions) # Print actions for num, act in actions.iteritems(): print(" %d) %s") % (num, act[0]) print result = self.entry(_("Please insert your action here")) try: result = int(result) except: return self.edit_partitions(warning=_("You didn't entered a valid action.")) if not result in actions: return self.edit_partitions(warning=_("You didn't entered a valid action.")) # Generate a new device_changes, if any if type(obj) == lib.p.disk.Disk: # It is a Disk object, we should use Disk.device _path = obj.device.path else: _path = obj.path if not _path in self.changed: self.changed[_path] = {"obj":obj, "changes":{}} return actions[result][1](device=obj, device_changes=self.changed[_path]["changes"])
def commit(self, interactive=False): """ Commits all the changes to the disks. """ if interactive: self.header(_("Commit changes")) print(_("This table is going to be applied:")) print self.print_devices_partitions() print print(_("%(warning)s: This will COMMIT ALL THE CHANGES YOU'VE DONE on the physical disks.") % {"warning":bold(_("WARNING"))}) print(_("This is the last time that you can check your new partition table.")) print(_("If you continue, you CAN'T RESTORE THE OLD TABLE!") + "\n") result = self.question(_("Do you really want to continue?"), default=False) else: result = True if result: # Ok, continue. lst, dct = lib.device_sort(self.changed) for key in lst: try: obj = dct[key]["obj"] cng = dct[key]["changes"] except: verbose("Unable to get a correct object/changes from %s." % key) continue # Skip. verbose("Committing changes in %s" % key) # If working in a Virtual freespace partition, pyparted will segfault. # The following is a workaround, but should be fixed shortly. # FIXME # FIXME FIXME # FIXME ______ FIXME # FIXME | | FIXME # FIXME | | FIXME # FIXME FIXME FIXME FIXME FIXME FIXME FIXME # ------------------------------------------ # Figure 1: A FIXME big like an house. if "-1" in key: continue # New partition table? if "newtable" in cng: progress = lib.new_table(obj, cng["newtable"]) info(_("Creating new partition table on %s...") % key) status = progress.wait() if status != 0: # Failed ... if interactive: return self.edit_partitions(warning=_("FAILED: new partition table in %s") % key) else: raise m.CmdError(_("FAILED: new partition table in %s") % key) # Clear touched, as only this action can be done if we do not own a disk. del self.touched[obj.path] # Commit on the disk. lib.commit(obj, self.touched) # Should format? if "format_real" in cng: # If this is going to be the swap partition, if swap_nofromat is setted, we should not format. #if "useas" in cng and cng["useas"] == "swap" and self.settings["swap_noformat"]: # continue # Yes. progress = lib.format_partition_for_real(obj, cng["format_real"]) info(_("Formatting %s...") % key) status = progress.wait() if status != 0: # Failed ... if interactive: return self.edit_partitions(warning=_("FAILED: formatting %s") % key) else: raise m.CmdError(_("FAILED: formatting %s") % key) # Check if it is root or swap if "useas" in cng: if cng["useas"] == "/": # Preseed self.settings["root"] = key self.settings["root_noformat"] = True elif cng["useas"] == "swap": # Preseed self.settings["swap"] = key self.settings["swap_noformat"] = True # Preseed *all* changes self.settings["changed"] = self.changed # Reload. self._reload(complete=False) # Preserve useas. # Return. if interactive: return self.edit_partitions()