2 # -*- coding: utf-8 -*-
6 # Copyright © 2013-2019 RebornOS
8 # This file is part of Cnchi.
10 # Cnchi is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 3 of the License, or
13 # (at your option) any later version.
15 # Cnchi is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
20 # The following additional terms are in effect as per Section 7 of the license:
22 # The preservation of all legal notices and author attributions in
23 # the material or in the Appropriate Legal Notices displayed
24 # by works containing it is required.
26 # You should have received a copy of the GNU General Public License
27 # along with Cnchi; If not, see <http://www.gnu.org/licenses/>.
30 """ Asks which type of installation the user wants to perform """
37 gi.require_version('Gtk', '3.0')
38 from gi.repository import Gtk
41 from pages.gtkbasebox import GtkBaseBox
42 import misc.extra as misc
43 from browser_window import BrowserWindow
45 # When testing, no _() is available
48 except NameError as err:
53 def check_alongside_disk_layout():
54 """ Alongside can only work if user has followed the recommended
55 BIOS-Based Disk-Partition Configurations shown in
56 http://technet.microsoft.com/en-us/library/dd744364(v=ws.10).aspx """
58 # TODO: Add more scenarios where alongside could work
60 partitions = misc.get_partitions()
61 # logging.debug(partitions)
63 for partition in partitions:
64 if misc.is_partition_extended(partition):
70 # We just seek for sda partitions
72 for partition in partitions:
73 if "sda" in partition:
74 partitions_sda.append(partition)
76 # There's no extended partition, so all partitions must be primary
77 if len(partitions_sda) < 4:
84 """ Load ZFS kernel module """
85 cmd = ["modprobe", "zfs"]
87 with misc.raised_privileges():
88 subprocess.check_output(cmd, stderr=subprocess.STDOUT)
89 logging.debug("ZFS kernel module loaded successfully.")
90 except subprocess.CalledProcessError as err:
91 error_msg = err.output.decode().rstrip()
92 logging.warning("%s", error_msg)
97 class InstallationAsk(GtkBaseBox):
98 """ Asks user which type of installation wants to perform """
99 def __init__(self, params, prev_page="mirrors", next_page=None):
100 super().__init__(self, params, "ask", prev_page, next_page)
102 data_dir = self.settings.get("data")
104 partitioner_dir = os.path.join(
110 image = self.gui.get_object("automatic_image")
111 path = os.path.join(partitioner_dir, "automatic.png")
112 image.set_from_file(path)
114 # image = self.gui.get_object("alongside_image")
115 # path = os.path.join(partitioner_dir, "alongside.png")
116 # image.set_from_file(path)
118 image = self.gui.get_object("advanced_image")
119 path = os.path.join(partitioner_dir, "advanced.png")
120 image.set_from_file(path)
124 # DISABLE ALONGSIDE INSTALLATION. IT'S NOT READY YET
125 # enable_alongside = self.check_alongside()
126 enable_alongside = False
127 self.settings.set('enable_alongside', enable_alongside)
129 #if enable_alongside:
130 # msg = "Cnchi will enable the 'alongside' installation mode."
132 # msg = "Cnchi will NOT enable the 'alongside' installation mode."
135 # By default, select automatic installation
136 self.next_page = "installation_automatic"
137 self.settings.set("partition_mode", "automatic")
139 self.is_zfs_available = load_zfs()
141 self.enable_automatic_options(True)
144 "I need help with an RebornOS / Windows(tm) dual boot setup!")
145 btn = Gtk.Button.new_with_label(btn_label)
147 'clicked', self.alongside_wiki_button_clicked)
148 ask_box = self.gui.get_object("ask")
149 ask_box.pack_start(btn, True, False, 0)
153 def alongside_wiki_button_clicked(self, _widget, _data=None):
154 """ Shows dual installation wiki page in a browser window """
156 self.browser = BrowserWindow("RebornOS Wiki - Dual Boot")
157 url = ("https://sourceforge.net/p/rebornos/wiki/Dual%20Boot%20RebornOS%20%26%20Windows%20UEFI%20%28Expanded%29%20%E2%80%93%20by%20linuxhelmet/")
158 self.browser.load_url(url)
159 except Exception as err:
160 logging.warning("Could not show RebornOS wiki: %s", err)
162 def check_alongside(self):
163 """ Check if alongside installation type must be enabled.
164 Alongside only works when Windows is installed on sda """
166 enable_alongside = False
168 # FIXME: Alongside does not work in UEFI systems
169 if os.path.exists("/sys/firmware/efi"):
170 msg = "The 'alongside' installation mode does not work in UEFI systems"
172 enable_alongside = False
174 oses = bootinfo.get_os_dict()
177 # We only check the first hard disk
178 non_valid = ["unknown", "Swap",
179 "Data or Swap", self.other_oses]
180 if "sda" in key and oses[key] not in non_valid:
181 self.other_oses.append(oses[key])
184 for detected_os in self.other_oses:
185 if "windows" in detected_os.lower():
186 logging.debug("Windows(tm) OS detected.")
187 enable_alongside = True
188 if not enable_alongside:
189 logging.debug("Windows(tm) OS not detected.")
190 enable_alongside = False
192 logging.debug("Can't detect any OS in device sda.")
193 enable_alongside = False
195 if not check_alongside_disk_layout():
196 msg = "Unsuported disk layout for the 'alongside' installation mode"
198 enable_alongside = False
200 return enable_alongside
202 def enable_automatic_options(self, status):
203 """ Enables or disables automatic installation options """
205 "encrypt_checkbutton", "encrypt_label",
206 "lvm_checkbutton", "lvm_label",
207 "home_checkbutton", "home_label"]
210 obj = self.gui.get_object(name)
211 obj.set_sensitive(status)
213 names = ["zfs_checkbutton", "zfs_label"]
215 obj = self.gui.get_object(name)
216 obj.set_sensitive(status and self.is_zfs_available)
218 def prepare(self, direction):
219 """ Prepares screen """
220 # Read options and set widgets accordingly
222 ('use_luks', 'encrypt_checkbutton'), ('use_lvm', 'lvm_checkbutton'),
223 ('use_zfs', 'zfs_checkbutton'), ('use_home', 'home_checkbutton')}
225 for (setting_name, widget_id) in widgets_settings:
226 widget = self.gui.get_object(widget_id)
227 setting_value = self.settings.get(setting_name)
228 widget.set_active(setting_value)
233 if not self.settings.get('enable_alongside'):
234 self.hide_option("alongside")
236 self.forward_button.set_sensitive(True)
238 def hide_option(self, option):
239 """ Hides widgets """
241 if option == "alongside":
243 "alongside_radiobutton",
244 "alongside_description",
248 widget = self.gui.get_object(name)
249 if widget is not None:
252 def get_os_list_str(self):
253 """ Get string with the detected os names """
255 len_other_oses = len(self.other_oses)
256 if len_other_oses > 0:
257 if len_other_oses > 1:
258 if len_other_oses == 2:
259 os_str = _(" and ").join(self.other_oses)
261 os_str = ", ".join(self.other_oses)
263 os_str = self.other_oses[0]
265 # Truncate string if it's too large
267 os_str = os_str[:40] + "..."
271 def translate_ui(self):
272 """ Translates screen before showing it """
273 self.header.set_subtitle(_("Installation Type"))
275 self.forward_button.set_always_show_image(True)
276 self.forward_button.set_sensitive(True)
278 # description_style = '<span style="italic">{0}</span>'
279 # bold_style = '<span weight="bold">{0}</span>'
281 oses_str = self.get_os_list_str()
286 radio = self.gui.get_object("automatic_radiobutton")
288 txt = _("Replace {0} with RebornOS").format(oses_str)
290 txt = _("Erase disk and install RebornOS")
292 radio.set_name('auto_radio_btn')
294 label = self.gui.get_object("automatic_description")
295 txt = _("Warning: This will erase ALL data on your disk.")
296 # txt = description_style.format(txt)
298 label.set_name("automatic_desc")
299 label.set_hexpand(False)
300 label.set_line_wrap(True)
301 label.set_max_width_chars(max_width_chars)
303 button = self.gui.get_object("encrypt_checkbutton")
304 txt = _("Encrypt this installation for increased security.")
305 button.set_label(txt)
306 button.set_name("enc_btn")
307 button.set_hexpand(False)
308 # button.set_line_wrap(True)
309 # button.set_max_width_chars(max_width_chars)
311 label = self.gui.get_object("encrypt_label")
312 txt = _("You will be asked to create an encryption password in the "
314 # txt = description_style.format(txt)
316 label.set_name("enc_label")
317 label.set_hexpand(False)
318 label.set_line_wrap(True)
319 label.set_max_width_chars(max_width_chars)
321 button = self.gui.get_object("lvm_checkbutton")
322 txt = _("Use LVM with this installation.")
323 button.set_label(txt)
324 button.set_name("lvm_btn")
325 button.set_hexpand(False)
326 # button.set_line_wrap(True)
327 # button.set_max_width_chars(max_width_chars)
329 label = self.gui.get_object("lvm_label")
330 txt = _("This will setup LVM and allow you to easily manage "
331 "partitions and create snapshots.")
332 # txt = description_style.format(txt)
334 label.set_name("lvm_label")
335 label.set_hexpand(False)
336 label.set_line_wrap(True)
337 label.set_max_width_chars(max_width_chars)
339 button = self.gui.get_object("zfs_checkbutton")
340 txt = _("Use ZFS with this installation.")
341 button.set_label(txt)
342 button.set_name("zfs_btn")
343 button.set_hexpand(False)
344 # button.set_line_wrap(True)
345 # button.set_max_width_chars(max_width_chars)
347 label = self.gui.get_object("zfs_label")
348 txt = _("This will setup ZFS on your drive(s).")
349 # txt = description_style.format(txt)
351 label.set_name("zfs_label")
352 label.set_hexpand(False)
353 label.set_line_wrap(True)
354 label.set_max_width_chars(max_width_chars)
356 button = self.gui.get_object("home_checkbutton")
357 txt = _("Set your Home in a different partition/volume")
358 button.set_label(txt)
359 button.set_name("home_btn")
360 button.set_hexpand(False)
361 # button.set_line_wrap(True)
362 # button.set_max_width_chars(max_width_chars)
364 label = self.gui.get_object("home_label")
365 txt = _("This will setup your /home directory in a different "
366 "partition or volume.")
367 # txt = description_style.format(txt)
369 label.set_name("home_label")
370 label.set_hexpand(False)
371 label.set_line_wrap(True)
372 label.set_max_width_chars(max_width_chars)
374 # Alongside Install (For now, only works with Windows)
375 # if len(oses_str) > 0:
376 # txt = _("Install Antergos alongside {0}").format(oses_str)
377 # radio = self.gui.get_object("alongside_radiobutton")
378 # radio.set_label(txt)
380 # label = self.gui.get_object("alongside_description")
381 # txt = _("Installs Antergos without removing {0}").format(oses_str)
382 # txt = description_style.format(txt)
383 # label.set_markup(txt)
384 # label.set_line_wrap(True)
386 # intro_txt = _("This computer has {0} installed.").format(oses_str)
387 # intro_txt = intro_txt + "\n" + _("What do you want to do?")
389 intro_txt = _("How would you like to proceed?")
391 intro_label = self.gui.get_object("introduction")
392 # intro_txt = bold_style.format(intro_txt)
393 intro_label.set_text(intro_txt)
394 intro_label.set_name("intro_label")
395 intro_label.set_hexpand(False)
396 intro_label.set_line_wrap(True)
397 intro_label.set_max_width_chars(max_width_chars)
400 radio = self.gui.get_object("advanced_radiobutton")
402 _("Choose exactly where RebornOS should be installed."))
403 radio.set_name("advanced_radio_btn")
405 label = self.gui.get_object("advanced_description")
406 txt = _("Edit partition table and choose mount points.")
407 # txt = description_style.format(txt)
409 label.set_name("adv_desc_label")
410 label.set_hexpand(False)
411 label.set_line_wrap(True)
412 label.set_max_width_chars(max_width_chars)
414 def store_values(self):
415 """ Store selected values """
416 check = self.gui.get_object("encrypt_checkbutton")
417 use_luks = check.get_active()
419 check = self.gui.get_object("lvm_checkbutton")
420 use_lvm = check.get_active()
422 check = self.gui.get_object("zfs_checkbutton")
423 use_zfs = check.get_active()
425 check = self.gui.get_object("home_checkbutton")
426 use_home = check.get_active()
428 self.settings.set('use_lvm', use_lvm)
429 self.settings.set('use_luks', use_luks)
430 self.settings.set('use_luks_in_root', True)
431 self.settings.set('luks_root_volume', 'cryptAntergos')
432 self.settings.set('use_zfs', use_zfs)
433 self.settings.set('use_home', use_home)
435 if not self.settings.get('use_zfs'):
436 if self.settings.get('use_luks'):
438 "RebornOS installation will be encrypted using LUKS")
439 if self.settings.get('use_lvm'):
440 logging.info("RebornOS will be installed using LVM volumes")
441 if self.settings.get('use_home'):
443 "RebornOS will be installed using a separate /home volume.")
444 elif self.settings.get('use_home'):
446 "RebornOS will be installed using a separate /home partition.")
448 logging.info("RebornOS will be installed using ZFS")
449 if self.settings.get('use_luks'):
450 logging.info("RebornOS ZFS installation will be encrypted")
451 if self.settings.get('use_home'):
453 "RebornOS will be installed using a separate /home volume.")
455 if self.next_page == "installation_alongside":
456 self.settings.set('partition_mode', 'alongside')
457 elif self.next_page == "installation_advanced":
458 self.settings.set('partition_mode', 'advanced')
459 elif self.next_page == "installation_automatic":
460 self.settings.set('partition_mode', 'automatic')
461 elif self.next_page == "installation_zfs":
462 self.settings.set('partition_mode', 'zfs')
464 # Get sure other modules will know if zfs is activated or not
465 self.settings.set("zfs", use_zfs)
469 def get_next_page(self):
470 """ Returns which page should be the next one """
471 return self.next_page
473 def automatic_radiobutton_toggled(self, widget):
474 """ Automatic selected, enable all options """
475 if widget.get_active():
476 check = self.gui.get_object("zfs_checkbutton")
477 if check.get_active():
478 self.next_page = "installation_zfs"
480 self.next_page = "installation_automatic"
482 self.enable_automatic_options(True)
484 def automatic_lvm_toggled(self, widget):
485 """ Enables / disables LVM installation """
486 if widget.get_active():
487 self.next_page = "installation_automatic"
488 # Disable ZFS if using LVM
489 check = self.gui.get_object("zfs_checkbutton")
490 if check.get_active():
491 check.set_active(False)
493 def automatic_zfs_toggled(self, widget):
494 """ Enables / disables ZFS installation """
495 if widget.get_active():
496 self.next_page = "installation_zfs"
497 # Disable LVM if using ZFS
498 check = self.gui.get_object("lvm_checkbutton")
499 if check.get_active():
500 check.set_active(False)
502 self.next_page = "installation_automatic"
504 def alongside_radiobutton_toggled(self, widget):
505 """ Alongside selected, disable all automatic options """
506 if widget.get_active():
507 self.next_page = "installation_alongside"
508 self.enable_automatic_options(False)
510 def advanced_radiobutton_toggled(self, widget):
511 """ Advanced selected, disable all automatic options """
512 if widget.get_active():
513 self.next_page = "installation_advanced"
514 self.enable_automatic_options(False)
517 if __name__ == '__main__':
518 from test_screen import _, run
520 run('InstallationAsk')