def download(self, name, md5): url = _url_prefix + name response = "" try: request = urlopen(url) txt = request.read() #.decode('utf-8') except urllib.error.HTTPError as e: logging.exception('Unable to get %s - HTTPError = %s' % (name, e.reason)) return False except urllib.error.URLError as e: logging.exception('Unable to get %s - URLError = %s' % (name, e.reason)) return False except httplib.error.HTTPException as e: logging.exception('Unable to get %s - HTTPException' % name) return False except Exception as e: import traceback logging.exception('Unable to get %s - Exception = %s' % (name, traceback.format_exc())) return False web_md5 = self.get_md5(txt) if web_md5 != md5: txt = "Checksum error in %s. Download aborted" % name logging.error(txt) show.error(txt) return False new_name = os.path.join(_base_dir, name + "." + self.web_version.replace(".", "_")) with open(new_name, "wb") as f: f.write(txt) return True
def do_activate(self): """ Override the 'activate' signal of GLib.Application. """ try: import main_window except ImportError as err: msg = "Cannot create Cnchi main window: {0}".format(err) logging.error(msg) sys.exit(1) # Check if we have administrative privileges if os.getuid() != 0: msg = _( 'This installer must be run with administrative privileges, ' 'and cannot continue without them.') show.error(None, msg) return # Check if we're already running if self.already_running(): msg = _( "You cannot run two instances of this installer.\n\n" "If you are sure that the installer is not already running\n" "you can run this installer using the --force option\n" "or you can manually delete the offending file.\n\n" "Offending file: '{0}'").format(self.TMP_RUNNING) show.error(None, msg) return window = main_window.MainWindow(self, cmd_line) self.add_window(window) window.show() with open(self.TMP_RUNNING, "w") as tmp_file: tmp_file.write("Cnchi {0}\n{1}\n".format(info.CNCHI_VERSION, os.getpid()))
def fill_choose_partition_combo(self): self.choose_partition_combo.remove_all() devices = [] for device in sorted(self.oses.keys()): # if "Swap" not in self.oses[device]: if "windows" in self.oses[device].lower(): devices.append(device) if len(devices) > 1: new_device_found = False for device in sorted(devices): if self.get_new_device(device): new_device_found = True line = "{0} ({1})".format(self.oses[device], device) self.choose_partition_combo.append_text(line) self.select_first_combobox_item(self.choose_partition_combo) self.show_all() if not new_device_found: txt = _("Can't find any spare partition number.\nAlongside installation can't continue.") self.choose_partition_label.hide() self.choose_partition_combo.hide() self.label.set_markup(txt) show.error(self.get_toplevel(), txt) elif len(devices) == 1: self.set_resize_widget(devices[0]) self.show_all() self.choose_partition_label.hide() self.choose_partition_combo.hide() else: logging.warning(_("Can't find any installed OS!"))
def create_partition(diskob, part_type, geom): # A lot of this is similar to Anaconda, but customized to fit our needs nstart = geom.start nend = geom.end if nstart < 2048: nstart = 2048 # Just in case you try to create partition larger than disk. # This case should be caught in the frontend! # Never let user specify a length exceeding the free space. if nend > diskob.device.length - 1: nend = diskob.device.length - 1 nalign = diskob.partitionAlignment if not nalign.isAligned(geom, nstart): nstart = nalign.alignNearest(geom, nstart) if not nalign.isAligned(geom, nend): nend = nalign.alignDown(geom, nend) if part_type == 1: nstart = nstart + nalign.grainSize mingeom = parted.Geometry(device=diskob.device, start=nstart, end=nend - 1) maxgeom = parted.Geometry(device=diskob.device, start=nstart, end=nend) if diskob.maxPartitionLength < maxgeom.length: txt = _("Partition is too large!") logging.error(txt) show.error(None, txt) return None else: npartition = parted.Partition(disk=diskob, type=part_type, geometry=maxgeom) nconstraint = parted.Constraint(minGeom=mingeom, maxGeom=maxgeom) diskob.addPartition(partition=npartition, constraint=nconstraint) return npartition
def start_installation(self): # Alongside method shrinks selected partition # and creates root and swap partition in the available space if self.is_room_available() is False: return partition_path = self.row[0] otherOS = self.row[1] fs_type = self.row[2] # what if path is sda10 (two digits) ? this is wrong device_path = self.row[0][:-1] #re.search(r'\d+$', self.row[0]) new_size = self.new_size # first, shrink filesystem res = fs.resize(partition_path, fs_type, new_size) if res: # destroy original partition and create a new resized one pm.split_partition(device_path, partition_path, new_size) else: txt = _("Can't shrink %s(%s) filesystem") % (otherOS, fs_type) logging.error(txt) show.error(txt) return '''
def check_all(self): """ Check that all requirements are meet """ path = "/var/tmp/.cnchi_partitioning_completed" if os.path.exists(path): show.error(_("You must reboot before retrying again.")) return False has_internet = misc.has_connection() self.prepare_network_connection.set_state(has_internet) on_power = not self.on_battery() self.prepare_power_source.set_state(on_power) space = self.has_enough_space() self.prepare_enough_space.set_state(space) if has_internet: updated = self.is_updated() else: updated = False self.updated.set_state(updated) if self.checks_are_optional: return True if has_internet and space: return True return False
def do_activate(self): """ Override the 'activate' signal of GLib.Application. """ try: import main_window except ImportError as err: msg = "Cannot create DSGos_Installer main window: {0}".format(err) logging.error(msg) sys.exit(1) # Check if we have administrative privileges if os.getuid() != 0: msg = _("This installer must be run with administrative privileges, " "and cannot continue without them.") show.error(None, msg) return # Check if we're already running if self.already_running(): msg = _( "You cannot run two instances of this installer.\n\n" "If you are sure that the installer is not already running\n" "you can run this installer using the --force option\n" "or you can manually delete the offending file.\n\n" "Offending file: '{0}'" ).format(self.TMP_RUNNING) show.error(None, msg) return window = main_window.MainWindow(self, cmd_line) self.add_window(window) window.show() with open(self.TMP_RUNNING, "w") as tmp_file: tmp_file.write("DSGos_Installer {0}\n{1}\n".format(info.DSGos_Installer_VERSION, os.getpid()))
def fill_choose_partition_combo(self): self.choose_partition_combo.remove_all() devices = [] for device in sorted(self.oses.keys()): # if "Swap" not in self.oses[device]: if "windows" in self.oses[device].lower(): devices.append(device) if len(devices) > 1: new_device_found = False for device in sorted(devices): if self.get_new_device(device): new_device_found = True line = "{0} ({1})".format(self.oses[device], device) self.choose_partition_combo.append_text(line) self.select_first_combobox_item(self.choose_partition_combo) self.show_all() if not new_device_found: txt = _( "Can't find any spare partition number.\nAlongside installation can't continue." ) self.choose_partition_label.hide() self.choose_partition_combo.hide() self.label.set_markup(txt) show.error(self.get_main_window(), txt) elif len(devices) == 1: self.set_resize_widget(devices[0]) self.show_all() self.choose_partition_label.hide() self.choose_partition_combo.hide() else: logging.warning("Can't find any installed OS")
def create_partition(diskob, part_type, geom): # A lot of this is similar to Anaconda, but customized to fit our needs nstart = geom.start nend = geom.end if nstart < 2048: nstart = 2048 # Just in case you try to create partition larger than disk. # This case should be caught in the frontend! # Never let user specify a length exceeding the free space. if nend > diskob.device.length - 1: nend = diskob.device.length - 1 nalign = diskob.partitionAlignment if not nalign.isAligned(geom, nstart): nstart = nalign.alignNearest(geom, nstart) if not nalign.isAligned(geom, nend): nend = nalign.alignDown(geom, nend) if part_type == 1: nstart += nalign.grainSize mingeom = parted.Geometry(device=diskob.device, start=nstart, end=nend-1) maxgeom = parted.Geometry(device=diskob.device, start=nstart, end=nend) if diskob.maxPartitionLength < maxgeom.length: txt = _('Partition is too large!') logging.error(txt) debugtxt = ("%s\n%s" % (txt, err)) show.error(debugtxt) return None else: npartition = parted.Partition(disk=diskob, type=part_type, geometry=maxgeom) nconstraint = parted.Constraint(minGeom=mingeom, maxGeom=maxgeom) ncont = diskob.addPartition(partition=npartition, constraint=nconstraint) return npartition
def delete_partition(diskob, part): """ Remove partition from disk object """ try: diskob.deletePartition(part) except Exception as ex: template = "Cannot delete partition {1}. An exception of type {1} occured. Arguments:\n{2!r}" message = template.format(part, type(ex).__name__, ex.args) logging.error(message) show.error(None, message)
def delete_partition(diskob, part): try: diskob.deletePartition(part) except Exception as err: txt = _("Can't delete partition %s") % part logging.error(txt) logging.error(err) debugtxt = ("%s\n%s" % (txt, err)) show.error(debugtxt)
def delete_partition(diskob, part): try: diskob.deletePartition(part) except Exception as general_error: txt = _("Can't delete partition {0}").format(part) logging.error(txt) logging.error(general_error) debug_txt = "{0}\n{1}".format(txt, general_error) show.error(None, debug_txt)
def remove_logical_volume(logical_volume): """ Removes a logical volume """ try: subprocess.check_call(["lvremove", "-f", logical_volume]) except subprocess.CalledProcessError as err: txt = _("Can't remove logical volume {0}").format(logical_volume) logging.error(txt) logging.error(err) debugtxt = "{0}\n{1}".format(txt, err) show.error(None, debugtxt)
def remove_physical_volume(physical_volume): """ Removes a physical volume """ try: subprocess.check_call(["pvremove", "-f", physical_volume]) except subprocess.CalledProcessError as err: txt = _("Can't remove physical volume %s") % physical_volume logging.error(txt) logging.error(err) debugtxt = ("%s\n%s" % (txt, err)) show.error(debugtxt)
def get_devices(): device_list = parted.getAllDevices() disk_dic = {} myhomepath = '/bootmnt' if os.path.exists(myhomepath): myhome = subprocess.check_output(["df", "-P", myhomepath]).decode() else: myhome = "" for dev in device_list: if dev.path in myhome: continue # I left all of the below here but commented out to see some use cases # isbusy = in use/mounted. Needs to flag if 'yes' to prompt user to umount # isbusy = dev.busy # path gives /dev/sda or something similar # myname = dev.path # Hard drives measure themselves assuming kilo=1000, mega=1mil, etc # limiter = 1000 # Some disk size calculations # byte_size = dev.length * dev.sectorSize # megabyte_size = byte_size / (limiter * limiter) # gigabyte_size = megabyte_size / limiter # print(byte_size) # print(dev.length) # Must create disk object to drill down # Skip all blacklisted devices dev_name = dev.path[5:] if any(re.search(expr, dev_name) for expr in DEVICE_BLACKLIST): continue # Skip cd drive and special devices like LUKS and LVM disk_obj = None if not dev.path.startswith("/dev/sr") and not dev.path.startswith( "/dev/mapper"): try: disk_obj = parted.Disk(dev) result = OK except parted.DiskLabelException: # logging.warning(_('Unrecognised disk label in device {0}.'.format(dev.path))) result = UNRECOGNISED_DISK_LABEL except Exception as general_error: logging.error(general_error) msg = _( "Exception: {0}.\nFor more information take a look at /tmp/thus.log" ).format(general_error) show.error(None, msg) result = UNKNOWN_ERROR finally: disk_dic[dev.path] = (disk_obj, result) return disk_dic
def get_devices(): """ Get all devices """ device_list = parted.getAllDevices() disk_dic = {} myhomepath = '/run/archiso/bootmnt' if os.path.exists(myhomepath): myhome = subprocess.check_output(["df", "-P", myhomepath]).decode() else: myhome = "" for dev in device_list: if dev.path in myhome: continue # I left all of the below here but commented out to see some use cases # isbusy = in use/mounted. Needs to flag if 'yes' to prompt user to umount # isbusy = dev.busy # path gives /dev/sda or something similar # myname = dev.path # Hard drives measure themselves assuming kilo=1000, mega=1mil, etc # limiter = 1000 # Some disk size calculations # byte_size = dev.length * dev.sectorSize # megabyte_size = byte_size / (limiter * limiter) # gigabyte_size = megabyte_size / limiter # print(byte_size) # print(dev.length) # Must create disk object to drill down # Skip cd drive, special devices like LUKS and LVM and # RPMB (Replay Protected Memory Block) disk_obj = None rpmb = (dev.path.startswith("/dev/mmcblk") and dev.path.endswith("rpmb")) exclude = (dev.path.startswith("/dev/sr") or dev.path.startswith("/dev/mapper")) if not rpmb and not exclude: try: disk_obj = parted.Disk(dev) result = OK except parted.DiskLabelException: # logging.warning('Unrecognised disk label in device %s.', dev.path) result = UNRECOGNISED_DISK_LABEL except Exception as ex: template = "Cannot get devices information. An exception of type {0} occured. Arguments:\n{1!r}" message = template.format(type(ex).__name__, ex.args) logging.error(message) show.error(None, message) result = UNKNOWN_ERROR finally: disk_dic[dev.path] = (disk_obj, result) return disk_dic
def get_devices(): device_list = parted.getAllDevices() disk_dic = {} myhomepath = '/bootmnt' if os.path.exists(myhomepath): myhome = subprocess.check_output(["df", "-P", myhomepath]).decode() else: myhome = "" for dev in device_list: if dev.path in myhome: continue # I left all of the below here but commented out to see some use cases # isbusy = in use/mounted. Needs to flag if 'yes' to prompt user to umount # isbusy = dev.busy # path gives /dev/sda or something similar # myname = dev.path # Hard drives measure themselves assuming kilo=1000, mega=1mil, etc # limiter = 1000 # Some disk size calculations # byte_size = dev.length * dev.sectorSize # megabyte_size = byte_size / (limiter * limiter) # gigabyte_size = megabyte_size / limiter # print(byte_size) # print(dev.length) # Must create disk object to drill down # Skip all blacklisted devices dev_name = dev.path[5:] if any(re.search(expr, dev_name) for expr in DEVICE_BLACKLIST): continue # Skip cd drive and special devices like LUKS and LVM disk_obj = None if not dev.path.startswith("/dev/sr") and not dev.path.startswith("/dev/mapper"): try: disk_obj = parted.Disk(dev) result = OK except parted.DiskLabelException: # logging.warning(_('Unrecognised disk label in device {0}.'.format(dev.path))) result = UNRECOGNISED_DISK_LABEL except Exception as general_error: logging.error(general_error) msg = _("Exception: {0}.\nFor more information take a look at /tmp/thus.log").format(general_error) show.error(None, msg) result = UNKNOWN_ERROR finally: disk_dic[dev.path] = (disk_obj, result) return disk_dic
def get_used_space_from_path(path): try: result = subprocess.check_output(shlex.split('df -H %s' % path)).decode() lines = result.split('\n') used_space = lines[1].split()[2] except subprocess.CalledProcessError as err: used_space = 0 txt = _("Can't detect used space from %s") % path logging.error(txt) logging.error(err) debugtxt = ("%s\n%s" % (txt, err)) show.error(debugtxt) return used_space
def get_used_space_from_path(path): try: cmd = ["df", "-H", path] result = subprocess.check_output(cmd).decode() lines = result.split("\n") used_space = lines[1].split()[2] except subprocess.CalledProcessError as process_error: used_space = 0 txt = _("Can't detect used space from {0}: {1}").format(path, process_error) logging.error(txt) debug_txt = "{0}\n{1}".format(txt, process_error) show.error(None, debug_txt) return used_space
def get_used_space_from_path(path): """ Get partition used space """ try: cmd = ["df", "-H", path] result = subprocess.check_output(cmd).decode() lines = result.split('\n') used_space = lines[1].split()[2] except subprocess.CalledProcessError as process_error: used_space = 0 txt = _("Can't detect used space from {0}: {1}").format(path, process_error) logging.error(txt) debug_txt = "{0}\n{1}".format(txt, process_error) show.error(None, debug_txt) return used_space
def combobox_changed(self, combobox, name): tree_iter = combobox.get_active_iter() d = {'root':'swap', 'swap':'root'} op = d[name] if tree_iter != None: self.device[name] = combobox.get_active_text() log.debug(self.device[name]) if self.device[op] != "": if self.device[op] == self.device[name]: show.error(_("You can't select the same device for both mount points!")) self.forward_button.set_sensitive(False) else: self.forward_button.set_sensitive(True)
def remove_volume_group(volume_group): """ Removes an entire volume group """ # Before removing the volume group, remove its logical volumes logical_volumes = get_logical_volumes(volume_group) for logical_volume in logical_volumes: remove_logical_volume(logical_volume) # Now, remove the volume group try: subprocess.check_call(["vgremove", "-f", volume_group]) except subprocess.CalledProcessError as err: txt = _("Can't remove volume group {0}").format(volume_group) logging.error(txt) logging.error(err) debugtxt = "{0}\n{1}".format(txt, err) show.error(None, debugtxt)
def remove_volume_group(volume_group): """ Removes an entire volume group """ # Before removing the volume group, remove its logical volumes logical_volumes = get_logical_volumes(volume_group) for logical_volume in logical_volumes: remove_logical_volume(logical_volume) # Now, remove the volume group try: subprocess.check_call(["vgremove", "-f", volume_group]) except subprocess.CalledProcessError as err: txt = _("Can't remove volume group %s") % volume_group logging.error(txt) logging.error(err) debugtxt = ("%s\n%s" % (txt, err)) show.error(debugtxt)
def on_treeview_cursor_changed(self, widget): selection = self.treeview.get_selection() if not selection: return model, tree_iter = selection.get_selected() if tree_iter is None: return self.row = model[tree_iter] partition_path = self.row[0] other_os_name = self.row[1] self.min_size = 0 self.max_size = 0 self.new_size = 0 try: subprocess.call(["mount", partition_path, "/mnt"], stderr=subprocess.DEVNULL) x = subprocess.check_output(['df', partition_path]).decode() subprocess.call(["umount", "-l", "/mnt"], stderr=subprocess.DEVNULL) x = x.split('\n') x = x[1].split() self.max_size = int(x[1]) / 1000 self.min_size = int(x[2]) / 1000 except subprocess.CalledProcessError as e: txt = "CalledProcessError.output = %s" % e.output logging.error(txt) show.fatal_error(txt) if self.min_size + MIN_ROOT_SIZE < self.max_size: self.new_size = self.ask_shrink_size(other_os_name) else: txt = _("Can't shrink the partition (maybe it's nearly full?)") logging.error(txt) show.error(txt) return if self.new_size > 0 and self.is_room_available(): self.forward_button.set_sensitive(True) else: self.forward_button.set_sensitive(False)
def get_devices(): device_list = parted.getAllDevices() disk_dic = {} myhomepath = "/bootmnt" if os.path.exists(myhomepath): myhome = subprocess.check_output(["df", "-P", myhomepath]).decode() else: myhome = "" for dev in device_list: if dev.path in myhome: continue # I left all of the below here but commented out to see some use cases # isbusy = in use/mounted. Needs to flag if 'yes' to prompt user to umount # isbusy = dev.busy # path gives /dev/sda or something similar # myname = dev.path # Hard drives measure themselves assuming kilo=1000, mega=1mil, etc # limiter = 1000 # Some disk size calculations # byte_size = dev.length * dev.sectorSize # megabyte_size = byte_size / (limiter * limiter) # gigabyte_size = megabyte_size / limiter # print(byte_size) # print(dev.length) # Must create disk object to drill down # Skip cd drive and special devices like LUKS and LVM if not dev.path.startswith("/dev/sr") and not dev.path.startswith("/dev/mapper"): try: diskob = parted.Disk(dev) result = OK logging.info(_("Adding %s to disk_dic") % dev.path) except parted.DiskLabelException as err: logging.warning(_("Unrecognised disk label in device %s.") % dev.path) diskob = None result = UNRECOGNISED_DISK_LABEL except Exception as err: show.error((_("Exception: %s.\nFor more information take a look at /tmp/thus.log") % err)) diskob = None result = UNKNOWN_ERROR finally: disk_dic[dev.path] = (diskob, result) return disk_dic
def is_room_available(self): partition_path = self.row[0] otherOS = self.row[1] fs_type = self.row[2] # what if path is sda10 (two digits) ? this is wrong device_path = self.row[0][:-1] new_size = self.new_size logging.debug("partition_path: %s" % partition_path) logging.debug("device_path: %s" % device_path) logging.debug("new_size: %s" % new_size) # Find out how many primary partitions device has, and also # if there's already an extended partition extended_path = "" primary_partitions = [] for path in self.partitions: if device_path in path: p = self.partitions[path] if p.type == pm.PARTITION_EXTENDED: extended_path = path elif p.type == pm.PARTITION_PRIMARY: primary_partitions.append(path) primary_partitions.sort() logging.debug("extended partition: %s" % extended_path) logging.debug("primary partitions: %s" % primary_partitions) # we only allow installing if only 2 partitions are already occupied, otherwise there's no room for root + swap if len(primary_partitions) >= 4: txt = _( "There are too many primary partitions, can't create a new one" ) logging.error(txt) show.error(txt) return False self.extended_path = extended_path return True
def run(self): """ Run thread """ # Wait until there is an Internet connection available while not misc.has_connection(): time.sleep(2) # Delay if not os.path.exists(self.rankmirrors_script): logging.warning(_("Can't find rank mirrors script")) return # Run rankmirrors command try: self.rankmirrors_pid = subprocess.Popen(["/usr/share/thus/scripts/rankmirrors-script"]).pid except subprocess.CalledProcessError as err: txt = _("Couldn't execute auto mirroring selection") logging.error(txt) show.error(txt) logging.error(err)
def is_room_available(self): partition_path = self.row[0] otherOS = self.row[1] fs_type = self.row[2] # what if path is sda10 (two digits) ? this is wrong device_path = self.row[0][:-1] new_size = self.new_size logging.debug("partition_path: %s" % partition_path) logging.debug("device_path: %s" % device_path) logging.debug("new_size: %s" % new_size) # Find out how many primary partitions device has, and also # if there's already an extended partition extended_path = "" primary_partitions = [] for path in self.partitions: if device_path in path: p = self.partitions[path] if p.type == pm.PARTITION_EXTENDED: extended_path = path elif p.type == pm.PARTITION_PRIMARY: primary_partitions.append(path) primary_partitions.sort() logging.debug("extended partition: %s" % extended_path) logging.debug("primary partitions: %s" % primary_partitions) # we only allow installing if only 2 partitions are already occupied, otherwise there's no room for root + swap if len(primary_partitions) >= 4: txt = _("There are too many primary partitions, can't create a new one") logging.error(txt) show.error(txt) return False self.extended_path = extended_path return True
def check_pyalpm_version(): """ Checks python alpm binding and alpm library versions """ try: import pyalpm txt = "Using pyalpm v{0} as interface to libalpm v{1}" txt = txt.format(pyalpm.version(), pyalpm.alpmversion()) logging.info(txt) except (NameError, ImportError) as err: try: import show_message as show show.error(None, err) except ImportError as import_error: logging.error(import_error) finally: logging.error(err) return False return True
def run(self): """ Run thread """ # Wait until there is an Internet connection available while not misc.has_connection(): time.sleep(2) # Delay if not os.path.exists(self.rankmirrors_script): logging.warning(_("Can't find rank mirrors script")) return # Run rankmirrors command try: self.rankmirrors_pid = subprocess.Popen( ["/usr/share/thus/scripts/rankmirrors-script"]).pid except subprocess.CalledProcessError as err: txt = _("Couldn't execute auto mirroring selection") logging.error(txt) show.error(txt) logging.error(err)
def on_treeview_cursor_changed(self, widget): selection = self.treeview.get_selection() if not selection: return model, tree_iter = selection.get_selected() if tree_iter == None: return self.row = model[tree_iter] partition_path = self.row[0] other_os_name = self.row[1] self.min_size = 0 self.max_size = 0 self.new_size = 0 try: subprocess.call(["mount", partition_path, "/mnt"], stderr=subprocess.DEVNULL) x = subprocess.check_output(["df", partition_path]).decode() subprocess.call(["umount", "/mnt"], stderr=subprocess.DEVNULL) x = x.split("\n") x = x[1].split() self.max_size = int(x[1]) / 1000 self.min_size = int(x[2]) / 1000 except subprocess.CalledProcessError as e: logging.exception("CalledProcessError.output = %s" % e.output) if self.min_size + _minimum_space_for_antergos < self.max_size: self.new_size = self.ask_shrink_size(other_os_name) else: show.error(_("Can't shrink the partition (maybe it's nearly full)")) return if self.new_size > 0 and self.is_room_available(): self.forward_button.set_sensitive(True) else: self.forward_button.set_sensitive(False)
def update(self): if self.is_web_version_newer(): logging.info("New version found. Updating installer...") num_files = len(self.web_files) i = 1 for f in self.web_files: name = f['name'] md5 = f['md5'] print("Downloading %s (%d/%d)" % (name, i, num_files)) if self.download(name, md5) is False: # download has failed txt = "Download of %s has failed" % name logging.error(txt) show.error(txt) return False i = i + 1 # replace old files with the new ones self.replace_old_with_new_versions() return True else: return False
def get_devices(): device_list = parted.getAllDevices() disk_dic = {} myhomepath = '/bootmnt' if os.path.exists(myhomepath): myhome = subprocess.check_output(["df", "-P", myhomepath]).decode() else: myhome = "" for dev in device_list: if dev.path in myhome: continue #I left all of the below here but commented out to see some use cases #isbusy = in use/mounted. Needs to flag if 'yes' to prompt user to umount #isbusy = dev.busy #path gives /dev/sda or something similar #myname = dev.path #Hard drives measure themselves assuming kilo=1000, mega=1mil, etc #limiter = 1000 #Some disk size calculations #byte_size = dev.length * dev.sectorSize #megabyte_size = byte_size / (limiter * limiter) #gigabyte_size = megabyte_size / limiter #print(byte_size) #print(dev.length) #Must create disk object to drill down # skip cd drive and special devices like LUKS and LVM if not dev.path.startswith("/dev/sr") and not dev.path.startswith("/dev/mapper"): try: diskob = parted.Disk(dev) disk_dic[dev.path] = diskob except Exception as err: logging.error(err) show.error((_("Exception: For more information take a look at /tmp/thus.log"), err)) disk_dic[dev.path] = None return disk_dic
def check_gtk_version(): """ Check GTK version """ # Check desired GTK Version major_needed = int(GTK_VERSION_NEEDED.split(".")[0]) minor_needed = int(GTK_VERSION_NEEDED.split(".")[1]) micro_needed = int(GTK_VERSION_NEEDED.split(".")[2]) # Check system GTK Version major = Gtk.get_major_version() minor = Gtk.get_minor_version() micro = Gtk.get_micro_version() # Cnchi will be called from our liveCD that already # has the latest GTK version. This is here just to # help testing Cnchi in our environment. wrong_gtk_version = False if major_needed > major: wrong_gtk_version = True if major_needed == major and minor_needed > minor: wrong_gtk_version = True if major_needed == major and minor_needed == minor and micro_needed > micro: wrong_gtk_version = True if wrong_gtk_version: text = "Detected GTK version {0}.{1}.{2} but version >= {3} is needed." text = text.format(major, minor, micro, GTK_VERSION_NEEDED) try: import show_message as show show.error(None, text) except ImportError as import_error: logging.error(import_error) finally: return False else: logging.info("Using GTK v{0}.{1}.{2}".format(major, minor, micro)) return True
def check_gtk_version(): """ Check GTK version """ # Check desired GTK Version major_needed = int(GTK_VERSION_NEEDED.split(".")[0]) minor_needed = int(GTK_VERSION_NEEDED.split(".")[1]) micro_needed = int(GTK_VERSION_NEEDED.split(".")[2]) # Check system GTK Version major = Gtk.get_major_version() minor = Gtk.get_minor_version() micro = Gtk.get_micro_version() # DSGos_Installer will be called from our liveCD that already # has the latest GTK version. This is here just to # help testing DSGos_Installer in our environment. wrong_gtk_version = False if major_needed > major: wrong_gtk_version = True if major_needed == major and minor_needed > minor: wrong_gtk_version = True if major_needed == major and minor_needed == minor and micro_needed > micro: wrong_gtk_version = True if wrong_gtk_version: text = "Detected GTK version {0}.{1}.{2} but version >= {3} is needed." text = text.format(major, minor, micro, GTK_VERSION_NEEDED) try: import show_message as show show.error(None, text) except ImportError as import_error: logging.info(text) return False else: logging.info("Using GTK v{0}.{1}.{2}".format(major, minor, micro)) return True
def __init__(self, app, cmd_line): Gtk.ApplicationWindow.__init__(self, title="Thus", application=app) # Check if we have administrative privileges if os.getuid() != 0: msg = _('This installer must be run with administrative privileges, ' 'and cannot continue without them.') show.error(self, msg) sys.exit(1) # Check if we're already running tmp_running = "/tmp/.setup-running" if os.path.exists(tmp_running): logging.error(_("File '{0}' already exists.".format(tmp_running))) msg = _("You cannot run two instances of this installer.\n\n" "If you are sure that the installer is not already running\n" "you can run this installer using the --force option\n" "or you can manually delete the offending file.\n\n" "Offending file: '{0}'").format(tmp_running) show.error(self, msg) sys.exit(1) # workaround for dconf os.system("mkdir -p /root/.cache/dconf") os.system("chmod -R 777 /root/.cache") logging.info(_("Thus installer version {0}".format(info.THUS_VERSION))) self.settings = config.Settings() self.ui_dir = self.settings.get('ui') if not os.path.exists(self.ui_dir): thus_dir = os.path.join(os.path.dirname(__file__), './') self.settings.set('thus', thus_dir) ui_dir = os.path.join(os.path.dirname(__file__), 'ui/') self.settings.set('ui', ui_dir) data_dir = os.path.join(os.path.dirname(__file__), 'data/') self.settings.set('data', data_dir) self.ui_dir = self.settings.get('ui') '''if cmd_line.cache: logging.debug("Thus will use '{0}' as a source directory for cached xz packages".format(cmd_line.cache)) self.settings.set('cache', cmd_line.cache)''' data_dir = self.settings.get('data') # For things we are not ready for users to test self.settings.set('z_hidden', cmd_line.z_hidden) self.ui = Gtk.Builder() path = os.path.join(self.ui_dir, "main_window.ui") self.ui.add_from_file(path) self.add(self.ui.get_object("main")) self.header = self.ui.get_object("header") self.logo = self.ui.get_object("logo") path = os.path.join(data_dir, "images", "manjaro", "manjaro-logo-mini.png") self.logo.set_from_file(path) self.title = self.ui.get_object("title") # To honor our css self.header.set_name("header") self.logo.set_name("logo") self.main_box = self.ui.get_object("main_box") self.progressbar = self.ui.get_object("main_progressbar") self.progressbar.set_name('process_progressbar') self.forward_button = self.ui.get_object("forward_button") self.exit_button = self.ui.get_object("exit_button") self.backwards_button = self.ui.get_object("backwards_button") # image1 = Gtk.Image.new_from_icon_name("go-next", Gtk.IconSize.LARGE_TOOLBAR) # self.forward_button.set_label("") # self.forward_button.set_image(image1) # self.forward_button.set_name('fwd_btn') # self.forward_button.set_always_show_image(True) # self.forward_button.add(Gtk.Arrow(Gtk.ArrowType.RIGHT, Gtk.ShadowType.NONE)) # image2 = Gtk.Image.new_from_icon_name("go-previous", Gtk.IconSize.LARGE_TOOLBAR) # self.backwards_button.set_label("") # self.backwards_button.set_image(image2) self.backwards_button.set_name('bk_btn') self.backwards_button.set_always_show_image(True) # self.backwards_button.add(Gtk.Arrow(Gtk.ArrowType.LEFT, Gtk.ShadowType.NONE)) # Create a queue. Will be used to report pacman messages (pacman/pac.py) # to the main thread (installation/process.py) self.callback_queue = multiprocessing.JoinableQueue() '''# Save in config if we have to use aria2 to download pacman packages self.settings.set("use_aria2", cmd_line.aria2) if cmd_line.aria2: logging.info(_("Using Aria2 to download packages - EXPERIMENTAL"))''' # self.set_titlebar(self.header) # Prepare params dict to pass common parameters to all screens self.params = dict() self.params['title'] = self.title self.params['header'] = self.header self.params['ui_dir'] = self.ui_dir self.params['forward_button'] = self.forward_button self.params['exit_button'] = self.exit_button self.params['backwards_button'] = self.backwards_button self.params['callback_queue'] = self.callback_queue self.params['settings'] = self.settings self.params['main_progressbar'] = self.progressbar # self.params['disable_tryit'] = cmd_line.disable_tryit self.params['testing'] = cmd_line.testing # Just load the first two screens (the other ones will be loaded later) # We do this so the user has not to wait for all the screens to be loaded self.pages = dict() self.pages["language"] = language.Language(self.params) self.connect('delete-event', self.on_exit_button_clicked) self.connect('key-release-event', self.check_escape) self.ui.connect_signals(self) self.set_title(_("Manjaro Installer - Thus {0}".format(info.THUS_VERSION))) self.set_geometry() #self.set_position(Gtk.WindowPosition.CENTER) #self.set_resizable(False) #self.set_size_request(MAIN_WINDOW_WIDTH, MAIN_WINDOW_HEIGHT) # Set window icon icon_path = os.path.join(data_dir, "images", "manjaro", "manjaro-icon.png") self.set_icon_from_file(icon_path) # Set the first page to show self.current_page = self.pages["language"] self.settings.set('timezone_start', True) self.main_box.add(self.current_page) # Use our css file (not in minimal, looks better without) # Sorry, not anymore thanks to gtk 3.16 style_provider = Gtk.CssProvider() style_css = os.path.join(data_dir, "css", "gtk-style.css") with open(style_css, 'rb') as css: css_data = css.read() style_provider.load_from_data(css_data) Gtk.StyleContext.add_provider_for_screen( Gdk.Screen.get_default(), style_provider, Gtk.STYLE_PROVIDER_PRIORITY_USER ) # Show main window self.show_all() self.current_page.prepare('forwards') # Hide backwards button self.backwards_button.hide() self.progressbar.set_fraction(0) self.progressbar_step = 0 ''' # Do not hide progress bar for minimal iso as it would break the widget alignment on language page. if not os.path.exists('/home/manjaro/.config/openbox'): # Hide progress bar self.progressbar.hide() ''' with open(tmp_running, "w") as tmp_file: tmp_file.write("Thus {0}\n".format(1234)) misc.gtk_refresh()
def __init__(self, app, cmd_line): Gtk.Window.__init__(self, title="Cnchi", application=app) # Check if we have administrative privileges if os.getuid() != 0: show.error(_('This installer must be run with administrative' ' privileges, and cannot continue without them.')) sys.exit(1) # Check if we're already running tmp_running = "/tmp/.setup-running" if os.path.exists(tmp_running): show.error(_('You cannot run two instances of this installer.\n\n' 'If you are sure that the installer is not already running\n' 'you can manually delete the file %s\n' 'and run this installer again.') % tmp_running) sys.exit(1) logging.info(_("Cnchi installer version %s"), info.CNCHI_VERSION) current_process = multiprocessing.current_process() #logging.debug("[%d] %s started", current_process.pid, current_process.name) self.settings = config.Settings() self.ui_dir = self.settings.get('ui') if not os.path.exists(self.ui_dir): cnchi_dir = os.path.join(os.path.dirname(__file__), './') self.settings.set('cnchi', cnchi_dir) ui_dir = os.path.join(os.path.dirname(__file__), 'ui/') self.settings.set('ui', ui_dir) data_dir = os.path.join(os.path.dirname(__file__), 'data/') self.settings.set('data', data_dir) self.ui_dir = self.settings.get('ui') if cmd_line.cache: self.settings.set('cache', cmd_line.cache) if cmd_line.copycache: self.settings.set('cache', cmd_line.copycache) self.settings.set('copy_cache', True) # For things we are not ready for users to test self.settings.set('z_hidden', cmd_line.z_hidden) # Set enabled desktops if self.settings.get('z_hidden'): self.settings.set("desktops", desktops.DESKTOPS_DEV) else: self.settings.set("desktops", desktops.DESKTOPS) self.ui = Gtk.Builder() self.ui.add_from_file(self.ui_dir + "cnchi.ui") self.add(self.ui.get_object("main")) self.header_ui = Gtk.Builder() self.header_ui.add_from_file(self.ui_dir + "header.ui") self.header = self.header_ui.get_object("header") self.logo = self.header_ui.get_object("logo") data_dir = self.settings.get('data') logo_path = os.path.join(data_dir, "images", "antergos", "antergos-logo-mini2.png") self.logo.set_from_file(logo_path) # To honor our css self.header.set_name("header") self.logo.set_name("logo") self.main_box = self.ui.get_object("main_box") self.progressbar = self.ui.get_object("main_progressbar") self.progressbar.set_name('process_progressbar') self.forward_button = self.header_ui.get_object("forward_button") self.backwards_button = self.header_ui.get_object("backwards_button") image1 = Gtk.Image() image1.set_from_icon_name("go-next", Gtk.IconSize.BUTTON) self.forward_button.set_label("") self.forward_button.set_image(image1) image2 = Gtk.Image() image2.set_from_icon_name("go-previous", Gtk.IconSize.BUTTON) self.backwards_button.set_label("") self.backwards_button.set_image(image2) # Create a queue. Will be used to report pacman messages (pacman/pac.py) # to the main thread (installation/process.py) self.callback_queue = multiprocessing.JoinableQueue() # Save in config if we have to use aria2 to download pacman packages self.settings.set("use_aria2", cmd_line.aria2) if cmd_line.aria2: logging.info(_("Using Aria2 to download packages - EXPERIMENTAL")) self.set_titlebar(self.header) # Load all pages # (each one is a screen, a step in the install process) params = dict() params['header'] = self.header params['ui_dir'] = self.ui_dir params['forward_button'] = self.forward_button params['backwards_button'] = self.backwards_button params['callback_queue'] = self.callback_queue params['settings'] = self.settings params['main_progressbar'] = self.progressbar if cmd_line.packagelist: params['alternate_package_list'] = cmd_line.packagelist logging.info(_("Using '%s' file as package list"), params['alternate_package_list']) else: params['alternate_package_list'] = "" params['disable_tryit'] = cmd_line.disable_tryit params['testing'] = cmd_line.testing self.pages = dict() self.pages["welcome"] = welcome.Welcome(params) self.pages["language"] = language.Language(params) self.pages["location"] = location.Location(params) self.pages["check"] = check.Check(params) self.pages["desktop"] = desktop.DesktopAsk(params) self.pages["features"] = features.Features(params) self.pages["keymap"] = keymap.Keymap(params) self.pages["timezone"] = timezone.Timezone(params) self.pages["installation_ask"] = installation_ask.InstallationAsk(params) self.pages["installation_automatic"] = installation_automatic.InstallationAutomatic(params) self.pages["installation_alongside"] = installation_alongside.InstallationAlongside(params) self.pages["installation_advanced"] = installation_advanced.InstallationAdvanced(params) self.pages["user_info"] = user_info.UserInfo(params) self.pages["slides"] = slides.Slides(params) self.connect('delete-event', self.on_exit_button_clicked) self.ui.connect_signals(self) self.header_ui.connect_signals(self) title = "Cnchi %s" % info.CNCHI_VERSION self.set_title(title) self.header.set_title(title) self.header.set_subtitle(_("Antergos Installer")) self.header.set_show_close_button(True) self.set_position(Gtk.WindowPosition.CENTER) self.set_resizable(False) self.set_size_request(MAIN_WINDOW_WIDTH, MAIN_WINDOW_HEIGHT) self.set_default_size(MAIN_WINDOW_WIDTH, MAIN_WINDOW_HEIGHT) # Set window icon icon_path = os.path.join(data_dir, "images", "antergos", "antergos-icon.png") self.set_icon_from_file(icon_path) # Set the first page to show self.current_page = self.pages["welcome"] self.main_box.add(self.current_page) # Header style testing style_provider = Gtk.CssProvider() style_css = os.path.join(data_dir, "css", "gtk-style.css") with open(style_css, 'rb') as css: css_data = css.read() style_provider.load_from_data(css_data) Gtk.StyleContext.add_provider_for_screen( Gdk.Screen.get_default(), style_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION ) # Show main window self.show_all() self.current_page.prepare('forwards') # Hide backwards button self.backwards_button.hide() # Hide titlebar but show border decoration #self.get_window().set_accept_focus(True) #self.get_window().set_decorations(Gdk.WMDecoration.BORDER) # Hide progress bar as it's value is zero self.progressbar.set_fraction(0) self.progressbar.hide() self.progressbar_step = 1.0 / (len(self.pages) - 2) with open(tmp_running, "w") as tmp_file: tmp_file.write("Cnchi %d\n" % 1234)
def __init__(self): # This allows to translate all py texts (not the glade ones) gettext.textdomain(APP) gettext.bindtextdomain(APP, DIR) locale_code, encoding = locale.getdefaultlocale() lang = gettext.translation (APP, DIR, [locale_code], None, True) lang.install() # With this we can use _("string") to translate gettext.install(APP, localedir=DIR, codeset=None, names=[locale_code]) if os.getuid() != 0: show.fatal_error(_('This installer must be run with administrative' ' privileges, and cannot continue without them.')) # check if we're already running tmp_running = "/tmp/.setup-running" if os.path.exists(tmp_running): show.error(_('You cannot run two instances of this installer.\n\n' 'If you are sure that the installer is not already running\n' 'you can manually delete the file %s\n' 'and run this installer again.') % tmp_running) sys.exit(1) super().__init__() self.settings = config.Settings() self.ui_dir = self.settings.get("UI_DIR") if not os.path.exists(self.ui_dir): cnchi_dir = os.path.join(os.path.dirname(__file__), './') self.settings.set("CNCHI_DIR", cnchi_dir) ui_dir = os.path.join(os.path.dirname(__file__), 'ui/') self.settings.set("UI_DIR", ui_dir) data_dir = os.path.join(os.path.dirname(__file__), 'data/') self.settings.set("DATA_DIR", data_dir) self.ui_dir = self.settings.get("UI_DIR") # set enabled desktops self.settings.set("desktops", _desktops) self.ui = Gtk.Builder() self.ui.add_from_file(self.ui_dir + "cnchi.ui") self.add(self.ui.get_object("main")) self.header = self.ui.get_object("box5") self.forward_button = self.ui.get_object("forward_button") self.logo = self.ui.get_object("logo") logo_dir = os.path.join(self.settings.get("DATA_DIR"), "antergos-logo-mini.png") self.logo.set_from_file(logo_dir) self.title = self.ui.get_object("title") # To honor our css self.title.set_name("header") self.logo.set_name("header") self.main_box = self.ui.get_object("main_box") self.progressbar = self.ui.get_object("progressbar1") self.forward_button = self.ui.get_object("forward_button") self.exit_button = self.ui.get_object("exit_button") self.backwards_button = self.ui.get_object("backwards_button") # Create a queue. Will be used to report pacman messages (pac.py) # to the main thread (installer_*.py) #self.callback_queue = queue.Queue(0) # Doing some tests with a LIFO queue #self.callback_queue = queue.LifoQueue(0) self.callback_queue = Queue() # save in config if we have to use aria2 to download pacman packages self.settings.set("use_aria2", _use_aria2) if _use_aria2: log.debug(_("Cnchi will use pm2ml and aria2 to download packages - EXPERIMENTAL")) # load all pages # (each one is a screen, a step in the install process) self.pages = dict() params = dict() params['title'] = self.title params['ui_dir'] = self.ui_dir params['forward_button'] = self.forward_button params['backwards_button'] = self.backwards_button params['exit_button'] = self.exit_button params['callback_queue'] = self.callback_queue params['settings'] = self.settings params['alternate_package_list'] = _alternate_package_list params['enable_alongside'] = _enable_alongside if len(_alternate_package_list) > 0: log.debug(_("Using '%s' file as package list") % _alternate_package_list) self.pages["welcome"] = welcome.Welcome(params) self.pages["language"] = language.Language(params) self.pages["location"] = location.Location(params) self.pages["check"] = check.Check(params) self.pages["desktop"] = desktop.DesktopAsk(params) self.pages["keymap"] = keymap.Keymap(params) self.pages["timezone"] = timezone.Timezone(params) self.pages["installation_ask"] = installation_ask.InstallationAsk(params) self.pages["installation_automatic"] = installation_automatic.InstallationAutomatic(params) self.pages["installation_alongside"] = installation_alongside.InstallationAlongside(params) self.pages["installation_advanced"] = installation_advanced.InstallationAdvanced(params) self.pages["user_info"] = user_info.UserInfo(params) self.pages["slides"] = slides.Slides(params) self.connect("delete-event", Gtk.main_quit) self.ui.connect_signals(self) self.set_title(_('Antergos Installer')) self.set_position(Gtk.WindowPosition.CENTER) self.set_resizable(False) self.set_size_request(_main_window_width, _main_window_height); # set window icon icon_dir = os.path.join(self.settings.get("DATA_DIR"), 'antergos-icon.png') self.set_icon_from_file(icon_dir) # set the first page to show self.current_page = self.pages["welcome"] self.main_box.add(self.current_page) # Header style testing style_provider = Gtk.CssProvider() style_css = os.path.join(self.settings.get("DATA_DIR"), "css", "gtk-style.css") with open(style_css, 'rb') as css: css_data = css.read() style_provider.load_from_data(css_data) Gtk.StyleContext.add_provider_for_screen( Gdk.Screen.get_default(), style_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION ) # show main window self.show_all() self.current_page.prepare('forwards') # hide backwards button self.backwards_button.hide() # Hide titlebar but show border decoration self.get_window().set_accept_focus(True) self.get_window().set_decorations(Gdk.WMDecoration.BORDER) # hide progress bar as it's value is zero self.progressbar.set_fraction(0) self.progressbar.hide() self.progressbar_step = 1.0 / (len(self.pages) - 2) # we drop privileges, but where we should do it? before this? ¿? misc.drop_privileges() with open(tmp_running, "wt") as tmp_file: tmp_file.write("Cnchi %d\n" % 1234) GLib.timeout_add(100, self.pages["slides"].manage_events_from_cb_queue)
def mkfs(self, device, fs_type, mount_point, label_name, fs_options="", btrfs_devices=""): """ We have two main cases: "swap" and everything else. """ logging.debug("Will mkfs " + device + " as " + fs_type) if fs_type == "swap": try: swap_devices = check_output("swapon -s") if device in swap_devices: subprocess.check_call(["swapoff", device]) subprocess.check_call(["mkswap", "-L", label_name, device]) subprocess.check_call(["swapon", device]) except subprocess.CalledProcessError as err: logging.warning(err.output) else: mkfs = {"xfs": "mkfs.xfs %s -L %s -f %s" % (fs_options, label_name, device), "jfs": "yes | mkfs.jfs %s -L %s %s" % (fs_options, label_name, device), "reiserfs": "yes | mkreiserfs %s -l %s %s" % (fs_options, label_name, device), "ext2": "mkfs.ext2 -q %s -F -L %s %s" % (fs_options, label_name, device), "ext3": "mkfs.ext3 -q %s -F -L %s %s" % (fs_options, label_name, device), "ext4": "mkfs.ext4 -q %s -F -L %s %s" % (fs_options, label_name, device), "btrfs": "mkfs.btrfs %s -L %s %s" % (fs_options, label_name, btrfs_devices), "nilfs2": "mkfs.nilfs2 %s -L %s %s" % (fs_options, label_name, device), "ntfs-3g": "mkfs.ntfs %s -L %s %s" % (fs_options, label_name, device), "vfat": "mkfs.vfat %s -n %s %s" % (fs_options, label_name, device)} # Make sure the fs type is one we can handle if fs_type not in mkfs.keys(): txt = _("Unknown filesystem type %s") % fs_type logging.error(txt) show.error(txt) return command = mkfs[fs_type] try: subprocess.check_call(command.split()) except subprocess.CalledProcessError as err: txt = _("Can't create filesystem %s") % fs_type logging.error(txt) logging.error(err.cmd) logging.error(err.output) show.error(txt) return # Flush filesystem buffers subprocess.check_call(["sync"]) # Create our mount directory path = self.dest_dir + mount_point subprocess.check_call(["mkdir", "-p", path]) # Mount our new filesystem mopts = "rw,relatime" if fs_type == "ext4": mopts = "rw,relatime,data=ordered" elif fs_type == "btrfs": mopts = 'rw,relatime,space_cache,autodefrag,inode_cache' subprocess.check_call(["mount", "-t", fs_type, "-o", mopts, device, path]) logging.debug("AutoPartition done, filesystems mounted:\n" + subprocess.check_output(["mount"]).decode()) # Change permission of base directories to avoid btrfs issues mode = "755" if mount_point == "/tmp": mode = "1777" elif mount_point == "/root": mode = "750" subprocess.check_call(["chmod", mode, path]) fs_uuid = fs.get_info(device)['UUID'] fs_label = fs.get_info(device)['LABEL'] logging.debug("Device details: %s UUID=%s LABEL=%s", device, fs_uuid, fs_label)
def __init__(self): ## This allows to translate all py texts (not the glade ones) #gettext.textdomain(APP_NAME) #gettext.bindtextdomain(APP_NAME, LOCALE_DIR) # #locale_code, encoding = locale.getdefaultlocale() #lang = gettext.translation(APP_NAME, LOCALE_DIR, [locale_code], None, True) #lang.install() # ## With this we can use _("string") to translate #gettext.install(APP_NAME, localedir=LOCALE_DIR, codeset=None, names=[locale_code]) # Check if we have administrative privileges if os.getuid() != 0: show.fatal_error( _('This installer must be run with administrative' ' privileges and cannot continue without them.')) setup_logging() # Check if we're already running tmp_running = "/tmp/.setup-running" if os.path.exists(tmp_running): show.error( _('You cannot run two instances of this installer.\n\n' 'If you are sure that another installer is not already running\n' 'you can manually delete the file %s\n' 'and run this installer again.') % tmp_running) sys.exit(1) super().__init__() # workaround for dconf os.system("mkdir -p /root/.cache/dconf") os.system("chmod -R 777 /root/.cache") logging.info(_("Thus installer version %s"), info.THUS_VERSION) current_process = multiprocessing.current_process() logging.debug("[%d] %s started", current_process.pid, current_process.name) self.settings = config.Settings() thus_dir = os.path.join(os.path.dirname(__file__), './') if os.path.exists(thus_dir): self.settings.set('thus', thus_dir) else: thus_dir = self.settings.get('thus') ui_dir = os.path.join(os.path.dirname(__file__), 'ui/') if os.path.exists(ui_dir): self.settings.set('ui', ui_dir) else: ui_dir = self.settings.get('ui') data_dir = os.path.join(os.path.dirname(__file__), 'data/') if os.path.exists(data_dir): self.settings.set('data', data_dir) else: data_dir = self.settings.get('data') if os.path.exists("/sys/firmware/efi"): self.settings.set('efi', True) self.ui = Gtk.Builder() self.ui.add_from_file(ui_dir + "thus.ui") self.add(self.ui.get_object("main")) self.header = self.ui.get_object("header") self.forward_button = self.ui.get_object("forward_button") self.logo = self.ui.get_object("logo") logo_dir = os.path.join(data_dir, "manjaro-logo-mini.png") self.logo.set_from_file(logo_dir) self.title = self.ui.get_object("title") # To honor our css self.title.set_name("header") self.logo.set_name("header") self.main_box = self.ui.get_object("main_box") self.progressbar = self.ui.get_object("progressbar1") self.forward_button = self.ui.get_object("forward_button") self.exit_button = self.ui.get_object("exit_button") self.backwards_button = self.ui.get_object("backwards_button") # Create a queue. Will be used to report pacman messages (pac.py) # to the main thread (installer_*.py) self.callback_queue = multiprocessing.JoinableQueue() # Load all pages # (each one is a screen, a step in the install process) self.pages = dict() params = dict() params['title'] = self.title params['forward_button'] = self.forward_button params['backwards_button'] = self.backwards_button params['exit_button'] = self.exit_button params['callback_queue'] = self.callback_queue params['settings'] = self.settings params['main_progressbar'] = self.ui.get_object('progressbar1') params['alternate_package_list'] = "" params['testing'] = cmd_line.testing self.pages["language"] = language.Language(params) self.pages["location"] = location.Location(params) self.pages["check"] = check.Check(params) self.pages["keymap"] = keymap.Keymap(params) self.pages["timezone"] = timezone.Timezone(params) self.pages["installation_ask"] = installation_ask.InstallationAsk( params) self.pages[ "installation_automatic"] = installation_automatic.InstallationAutomatic( params) self.pages[ "installation_alongside"] = installation_alongside.InstallationAlongside( params) self.pages[ "installation_advanced"] = installation_advanced.InstallationAdvanced( params) self.pages["user_info"] = user_info.UserInfo(params) self.pages["slides"] = slides.Slides(params) self.connect("delete-event", Gtk.main_quit) self.ui.connect_signals(self) self.set_title(_('Manjaro Installer')) self.set_position(Gtk.WindowPosition.CENTER) self.set_resizable(False) self.set_size_request(MAIN_WINDOW_WIDTH, MAIN_WINDOW_HEIGHT) # Set window icon icon_dir = os.path.join(data_dir, 'manjaro-icon.png') self.set_icon_from_file(icon_dir) # Set the first page to show self.current_page = self.pages["language"] self.main_box.add(self.current_page) # Header style testing style_provider = Gtk.CssProvider() style_css = os.path.join(data_dir, "css", "gtk-style.css") with open(style_css, 'rb') as css: css_data = css.read() style_provider.load_from_data(css_data) Gtk.StyleContext.add_provider_for_screen( Gdk.Screen.get_default(), style_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) # Show main window self.show_all() self.current_page.prepare('forwards') # Hide backwards button self.backwards_button.hide() # Hide titlebar but show border decoration self.get_window().set_accept_focus(True) #self.get_window().set_decorations(Gdk.WMDecoration.BORDER) # Hide progress bar as it's value is zero self.progressbar.set_fraction(0) self.progressbar.hide() self.progressbar_step = 1.0 / (len(self.pages) - 2) with open(tmp_running, "w") as tmp_file: tmp_file.write("Thus %d\n" % 1234) GLib.timeout_add(1000, self.pages["slides"].manage_events_from_cb_queue)
def __init__(self, app, cmd_line): Gtk.Window.__init__(self, title="Cnchi", application=app) # Check if we have administrative privileges if os.getuid() != 0: show.error( _('This installer must be run with administrative' ' privileges, and cannot continue without them.')) sys.exit(1) # Check if we're already running tmp_running = "/tmp/.setup-running" if os.path.exists(tmp_running): show.error( _('You cannot run two instances of this installer.\n\n' 'If you are sure that the installer is not already running\n' 'you can manually delete the file %s\n' 'and run this installer again.') % tmp_running) sys.exit(1) logging.info(_("Cnchi installer version %s"), info.CNCHI_VERSION) self.settings = config.Settings() self.ui_dir = self.settings.get('ui') if not os.path.exists(self.ui_dir): cnchi_dir = os.path.join(os.path.dirname(__file__), './') self.settings.set('cnchi', cnchi_dir) ui_dir = os.path.join(os.path.dirname(__file__), 'ui/') self.settings.set('ui', ui_dir) data_dir = os.path.join(os.path.dirname(__file__), 'data/') self.settings.set('data', data_dir) self.ui_dir = self.settings.get('ui') if cmd_line.cache: self.settings.set('cache', cmd_line.cache) if cmd_line.copycache: self.settings.set('cache', cmd_line.copycache) self.settings.set('copy_cache', True) # For things we are not ready for users to test self.settings.set('z_hidden', cmd_line.z_hidden) # Set enabled desktops if self.settings.get('z_hidden'): self.settings.set("desktops", desktops.DESKTOPS_DEV) else: self.settings.set("desktops", desktops.DESKTOPS) self.ui = Gtk.Builder() self.ui.add_from_file(self.ui_dir + "cnchi.ui") self.add(self.ui.get_object("main")) self.header_ui = Gtk.Builder() self.header_ui.add_from_file(self.ui_dir + "header.ui") self.header = self.header_ui.get_object("header") self.logo = self.header_ui.get_object("logo") data_dir = self.settings.get('data') logo_path = os.path.join(data_dir, "images", "antergos", "antergos-logo-mini2.png") self.logo.set_from_file(logo_path) # To honor our css self.header.set_name("header") self.logo.set_name("logo") self.main_box = self.ui.get_object("main_box") self.progressbar = self.ui.get_object("main_progressbar") self.progressbar.set_name('process_progressbar') self.forward_button = self.header_ui.get_object("forward_button") self.backwards_button = self.header_ui.get_object("backwards_button") image1 = Gtk.Image() image1.set_from_icon_name("go-next", Gtk.IconSize.BUTTON) self.forward_button.set_label("") self.forward_button.set_image(image1) image2 = Gtk.Image() image2.set_from_icon_name("go-previous", Gtk.IconSize.BUTTON) self.backwards_button.set_label("") self.backwards_button.set_image(image2) # Create a queue. Will be used to report pacman messages (pacman/pac.py) # to the main thread (installation/process.py) self.callback_queue = multiprocessing.JoinableQueue() # Save in config if we have to use aria2 to download pacman packages self.settings.set("use_aria2", cmd_line.aria2) if cmd_line.aria2: logging.info(_("Using Aria2 to download packages - EXPERIMENTAL")) self.set_titlebar(self.header) # Load all pages # (each one is a screen, a step in the install process) params = dict() params['header'] = self.header params['ui_dir'] = self.ui_dir params['forward_button'] = self.forward_button params['backwards_button'] = self.backwards_button params['callback_queue'] = self.callback_queue params['settings'] = self.settings params['main_progressbar'] = self.progressbar if cmd_line.packagelist: params['alternate_package_list'] = cmd_line.packagelist logging.info(_("Using '%s' file as package list"), params['alternate_package_list']) else: params['alternate_package_list'] = "" params['disable_tryit'] = cmd_line.disable_tryit params['testing'] = cmd_line.testing self.pages = dict() self.pages["welcome"] = welcome.Welcome(params) self.pages["language"] = language.Language(params) self.pages["location"] = location.Location(params) self.pages["check"] = check.Check(params) self.pages["desktop"] = desktop.DesktopAsk(params) self.pages["features"] = features.Features(params) self.pages["keymap"] = keymap.Keymap(params) self.pages["timezone"] = timezone.Timezone(params) self.pages["installation_ask"] = installation_ask.InstallationAsk( params) self.pages[ "installation_automatic"] = installation_automatic.InstallationAutomatic( params) self.pages[ "installation_alongside"] = installation_alongside.InstallationAlongside( params) self.pages[ "installation_advanced"] = installation_advanced.InstallationAdvanced( params) self.pages["user_info"] = user_info.UserInfo(params) self.pages["slides"] = slides.Slides(params) self.connect('delete-event', self.on_exit_button_clicked) self.ui.connect_signals(self) self.header_ui.connect_signals(self) title = "Cnchi %s" % info.CNCHI_VERSION self.set_title(title) self.header.set_title(title) self.header.set_subtitle(_("Antergos Installer")) self.header.set_show_close_button(True) self.set_geometry() # Set window icon icon_path = os.path.join(data_dir, "images", "antergos", "antergos-icon.png") self.set_icon_from_file(icon_path) # Set the first page to show self.current_page = self.pages["welcome"] self.main_box.add(self.current_page) # Header style testing style_provider = Gtk.CssProvider() style_css = os.path.join(data_dir, "css", "gtk-style.css") with open(style_css, 'rb') as css: css_data = css.read() style_provider.load_from_data(css_data) Gtk.StyleContext.add_provider_for_screen( Gdk.Screen.get_default(), style_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) # Show main window self.show_all() self.current_page.prepare('forwards') # Hide backwards button self.backwards_button.hide() # Hide titlebar but show border decoration #self.get_window().set_accept_focus(True) #self.get_window().set_decorations(Gdk.WMDecoration.BORDER) # Hide progress bar as it's value is zero self.progressbar.set_fraction(0) self.progressbar.hide() self.progressbar_step = 1.0 / (len(self.pages) - 2) with open(tmp_running, "w") as tmp_file: tmp_file.write("Cnchi %d\n" % 1234)
def mkfs(self, device, fs_type, mount_point, label_name, fs_options="", btrfs_devices=""): """ We have two main cases: "swap" and everything else. """ logging.debug("Will mkfs " + device + " as " + fs_type) if fs_type == "swap": try: swap_devices = check_output("swapon -s") if device in swap_devices: subprocess.check_call(["swapoff", device]) subprocess.check_call(["mkswap", "-L", label_name, device]) subprocess.check_call(["swapon", device]) except subprocess.CalledProcessError as err: logging.warning(err.output) else: mkfs = { "xfs": "mkfs.xfs %s -L %s -f %s" % (fs_options, label_name, device), "jfs": "yes | mkfs.jfs %s -L %s %s" % (fs_options, label_name, device), "reiserfs": "yes | mkreiserfs %s -l %s %s" % (fs_options, label_name, device), "ext2": "mkfs.ext2 -q %s -F -L %s %s" % (fs_options, label_name, device), "ext3": "mkfs.ext3 -q %s -F -L %s %s" % (fs_options, label_name, device), "ext4": "mkfs.ext4 -q %s -F -L %s %s" % (fs_options, label_name, device), "btrfs": "mkfs.btrfs %s -L %s %s" % (fs_options, label_name, btrfs_devices), "nilfs2": "mkfs.nilfs2 %s -L %s %s" % (fs_options, label_name, device), "ntfs-3g": "mkfs.ntfs %s -L %s %s" % (fs_options, label_name, device), "vfat": "mkfs.vfat %s -n %s %s" % (fs_options, label_name, device) } # Make sure the fs type is one we can handle if fs_type not in mkfs.keys(): txt = _("Unknown filesystem type %s") % fs_type logging.error(txt) show.error(txt) return command = mkfs[fs_type] try: subprocess.check_call(command.split()) except subprocess.CalledProcessError as err: txt = _("Can't create filesystem %s") % fs_type logging.error(txt) logging.error(err.cmd) logging.error(err.output) show.error(txt) return # Flush filesystem buffers subprocess.check_call(["sync"]) # Create our mount directory path = self.dest_dir + mount_point subprocess.check_call(["mkdir", "-p", path]) # Mount our new filesystem mopts = "rw,relatime" if fs_type == "ext4": mopts = "rw,relatime,data=ordered" elif fs_type == "btrfs": mopts = 'rw,relatime,space_cache,autodefrag,inode_cache' subprocess.check_call( ["mount", "-t", fs_type, "-o", mopts, device, path]) logging.debug("AutoPartition done, filesystems mounted:\n" + subprocess.check_output(["mount"]).decode()) # Change permission of base directories to avoid btrfs issues mode = "755" if mount_point == "/tmp": mode = "1777" elif mount_point == "/root": mode = "750" subprocess.check_call(["chmod", mode, path]) fs_uuid = fs.get_info(device)['UUID'] fs_label = fs.get_info(device)['LABEL'] logging.debug("Device details: %s UUID=%s LABEL=%s", device, fs_uuid, fs_label)
def start_installation(self): """ Alongside method shrinks selected partition and creates root and swap partition in the available space """ if self.is_room_available() == False: return partition_path = self.row[0] otherOS = self.row[1] fs_type = self.row[2] # What if path is sda10 (two digits) ? this is wrong device_path = self.row[0][:-1] #re.search(r'\d+$', self.row[0]) new_size = self.new_size # First, shrink filesystem res = fs.resize(partition_path, fs_type, new_size) if res: #logging.info("Filesystem on " + partition_path + " shrunk.\nWill recreate partition now on device " + device_path + " partition " + partition_path) txt = _("Filesystem on %s shrunk.") % partition_path txt += "\n" txt += _("Will recreate partition now on device %s partition %s") % (device_path, partition_path) logging.debug(txt) # destroy original partition and create a new resized one res = pm.split_partition(device_path, partition_path, new_size) else: txt = _("Can't shrink %s(%s) filesystem") % (otherOS, fs_type) logging.error(txt) show.error(txt) return # 'res' is either False or a parted.Geometry for the new free space if res is not None: txt = _("Partition %s shrink complete") % partition_path logging.debug(txt) else: txt = _("Can't shrink %s(%s) partition") % (otherOS, fs_type) logging.error(txt) show.error(txt) txt = _("*** FILESYSTEM IN UNSAFE STATE ***") txt += "\n" txt += _("Filesystem shrink succeeded but partition shrink failed.") logging.error(txt) return disc_dic = pm.get_devices() disk = disc_dic[device_path][0] mount_devices = {} fs_devices = {} mem_total = subprocess.check_output(["grep", "MemTotal", "/proc/meminfo"]).decode() mem_total = int(mem_total.split()[1]) mem = mem_total / 1024 # If geometry gives us at least 7.5GB (MIN_ROOT_SIZE + 1GB) we'll create ROOT and SWAP no_swap = False if res.getLength('MB') < MIN_ROOT_SIZE + 1: if mem < 2048: # Less than 2GB RAM and no swap? No way. txt = _("Cannot create new swap partition. Not enough free space") logging.error(txt) show.error(txt) return else: no_swap = True if no_swap: npart = pm.create_partition(device_path, 0, res) if npart is None: txt = _("Cannot create new partition.") logging.error(txt) show.error(txt) return pm.finalize_changes(disk) mount_devices["/"] = npart.path fs_devices[npart.path] = "ext4" fs.create_fs(npart.path, 'ext4', label='ROOT') else: # We know for a fact we have at least MIN_ROOT_SIZE + 1GB of space, # and at least MIN_ROOT_SIZE of those must go to ROOT. # Suggested sizes from Anaconda installer if mem < 2048: swap_part_size = 2 * mem elif 2048 <= mem < 8192: swap_part_size = mem elif 8192 <= mem < 65536: swap_part_size = mem / 2 else: swap_part_size = 4096 # Max swap size is 10% of all available disk size max_swap = res.getLength('MB') * 0.1 if swap_part_size > max_swap: swap_part_size = max_swap # Create swap partition units = 1000000 sec_size = disk.device.sectorSize new_length = int(swap_part_size * units / sec_size) new_end_sector = res.start + new_length my_geometry = pm.geom_builder(disk, res.start, new_end_sector, swap_part_size) logging.debug("create_partition %s", my_geometry) swappart = pm.create_partition(disk, 0, my_geometry) if swappart is None: txt = _("Cannot create new swap partition.") logging.error(txt) show.error(txt) return # Create new partition for / new_size_in_mb = res.getLength('MB') - swap_part_size start_sector = new_end_sector + 1 my_geometry = pm.geom_builder(disk, start_sector, res.end, new_size_in_mb) logging.debug("create_partition %s", my_geometry) npart = pm.create_partition(disk, 0, my_geometry) if npart is None: txt = _("Cannot create new partition.") logging.error(txt) show.error(txt) return pm.finalize_changes(disk) # Mount points mount_devices["swap"] = swappart.path fs_devices[swappart.path] = "swap" fs.create_fs(swappart.path, 'swap', 'SWAP') mount_devices["/"] = npart.path fs_devices[npart.path] = "ext4" fs.create_fs(npart.path, 'ext4', 'ROOT') self.settings.set('install_bootloader', True) if self.settings.get('install_bootloader'): if self.settings.get('efi'): self.settings.set('bootloader_type', "UEFI_x86_64") self.settings.set('bootloader_location', '/boot') else: self.settings.set('bootloader_type', "GRUB2") self.settings.set('bootloader_location', device_path) logging.info(_("Thus will install the bootloader of type %s in %s") % (self.settings.get('bootloader_type'), self.settings.get('bootloader_location'))) else: logging.warning("Cnchi will not install any boot loader") if not self.testing: self.process = installation_process.InstallationProcess( \ self.settings, \ self.callback_queue, \ mount_devices, \ fs_devices, \ None, \ self.alternate_package_list) self.process.start()
def start_installation(self): """ Alongside method shrinks selected partition and creates root and swap partition in the available space """ if self.is_room_available() == False: return partition_path = self.row[0] otherOS = self.row[1] fs_type = self.row[2] # What if path is sda10 (two digits) ? this is wrong device_path = self.row[0][:-1] #re.search(r'\d+$', self.row[0]) new_size = self.new_size # First, shrink filesystem res = fs.resize(partition_path, fs_type, new_size) if res: #logging.info("Filesystem on " + partition_path + " shrunk.\nWill recreate partition now on device " + device_path + " partition " + partition_path) txt = _("Filesystem on %s shrunk.") % partition_path txt += "\n" txt += _("Will recreate partition now on device %s partition %s" ) % (device_path, partition_path) logging.debug(txt) # destroy original partition and create a new resized one res = pm.split_partition(device_path, partition_path, new_size) else: txt = _("Can't shrink %s(%s) filesystem") % (otherOS, fs_type) logging.error(txt) show.error(txt) return # 'res' is either False or a parted.Geometry for the new free space if res is not None: txt = _("Partition %s shrink complete") % partition_path logging.debug(txt) else: txt = _("Can't shrink %s(%s) partition") % (otherOS, fs_type) logging.error(txt) show.error(txt) txt = _("*** FILESYSTEM IN UNSAFE STATE ***") txt += "\n" txt += _( "Filesystem shrink succeeded but partition shrink failed.") logging.error(txt) return disc_dic = pm.get_devices() disk = disc_dic[device_path][0] mount_devices = {} fs_devices = {} mem_total = subprocess.check_output( ["grep", "MemTotal", "/proc/meminfo"]).decode() mem_total = int(mem_total.split()[1]) mem = mem_total / 1024 # If geometry gives us at least 7.5GB (MIN_ROOT_SIZE + 1GB) we'll create ROOT and SWAP no_swap = False if res.getLength('MB') < MIN_ROOT_SIZE + 1: if mem < 2048: # Less than 2GB RAM and no swap? No way. txt = _( "Cannot create new swap partition. Not enough free space") logging.error(txt) show.error(txt) return else: no_swap = True if no_swap: npart = pm.create_partition(device_path, 0, res) if npart is None: txt = _("Cannot create new partition.") logging.error(txt) show.error(txt) return pm.finalize_changes(disk) mount_devices["/"] = npart.path fs_devices[npart.path] = "ext4" fs.create_fs(npart.path, 'ext4', label='ROOT') else: # We know for a fact we have at least MIN_ROOT_SIZE + 1GB of space, # and at least MIN_ROOT_SIZE of those must go to ROOT. # Suggested sizes from Anaconda installer if mem < 2048: swap_part_size = 2 * mem elif 2048 <= mem < 8192: swap_part_size = mem elif 8192 <= mem < 65536: swap_part_size = mem / 2 else: swap_part_size = 4096 # Max swap size is 10% of all available disk size max_swap = res.getLength('MB') * 0.1 if swap_part_size > max_swap: swap_part_size = max_swap # Create swap partition units = 1000000 sec_size = disk.device.sectorSize new_length = int(swap_part_size * units / sec_size) new_end_sector = res.start + new_length my_geometry = pm.geom_builder(disk, res.start, new_end_sector, swap_part_size) logging.debug("create_partition %s", my_geometry) swappart = pm.create_partition(disk, 0, my_geometry) if swappart is None: txt = _("Cannot create new swap partition.") logging.error(txt) show.error(txt) return # Create new partition for / new_size_in_mb = res.getLength('MB') - swap_part_size start_sector = new_end_sector + 1 my_geometry = pm.geom_builder(disk, start_sector, res.end, new_size_in_mb) logging.debug("create_partition %s", my_geometry) npart = pm.create_partition(disk, 0, my_geometry) if npart is None: txt = _("Cannot create new partition.") logging.error(txt) show.error(txt) return pm.finalize_changes(disk) # Mount points mount_devices["swap"] = swappart.path fs_devices[swappart.path] = "swap" fs.create_fs(swappart.path, 'swap', 'SWAP') mount_devices["/"] = npart.path fs_devices[npart.path] = "ext4" fs.create_fs(npart.path, 'ext4', 'ROOT') self.settings.set('install_bootloader', True) if self.settings.get('install_bootloader'): if self.settings.get('efi'): self.settings.set('bootloader_type', "UEFI_x86_64") self.settings.set('bootloader_location', '/boot') else: self.settings.set('bootloader_type', "GRUB2") self.settings.set('bootloader_location', device_path) logging.info( _("Thus will install the bootloader of type %s in %s") % (self.settings.get('bootloader_type'), self.settings.get('bootloader_location'))) else: logging.warning("Cnchi will not install any boot loader") if not self.testing: self.process = installation_process.InstallationProcess( \ self.settings, \ self.callback_queue, \ mount_devices, \ fs_devices, \ None, \ self.alternate_package_list) self.process.start()