Skip to content

Commit

Permalink
feat: add support for install with subvolumes
Browse files Browse the repository at this point in the history
  • Loading branch information
Vilez0 committed Apr 12, 2024
1 parent 1ee5e0f commit 5a88b16
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 47 deletions.
14 changes: 14 additions & 0 deletions live-installer/frontend/gtk_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -1244,6 +1244,20 @@ def activate_page(self, nex=0, index=0, goback=False):
if not QuestionDialog(_("Installer"), _(
"The root partition is too small. It should be at least 16GB. Do you want to continue?")):
return
if not found_root_partition:
for partition in self.setup.partitions:
for subvolume in partition.subvolumes:
print("subvolume",subvolume.mount_as, "name", subvolume.name)
if(subvolume.mount_as == "/"):
found_root_partition = True
if partition.format_as is None or partition.format_as == "":
if not QuestionDialog(_("Installer"), _(
"Root filesystem type not specified. Installation will continue without disk formatting. Do you want to continue?")):
return
if int(float(partition.partition.getLength('GB'))) < 16:
if not QuestionDialog(_("Installer"), _(
"The root partition is too small. It should be at least 16GB. Do you want to continue?")):
return

if not found_root_partition:
ErrorDialog(_("Installer"), "<b>%s</b>" % _("Please select a root (/) partition."), _(
Expand Down
3 changes: 1 addition & 2 deletions live-installer/frontend/partitioning.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,7 @@ def create_subvolume_dialog(widget):

def assign_mount_point(partition, mount_point, filesystem, read_only = False, subvolume_name = None):
# Assign it in the treeview
model, itervar = installer.builder.get_object(
"treeview_disks").get_selection().get_selected()
model = installer.builder.get_object("treeview_disks").get_model()
for disk in model:
for part in disk.iterchildren():
if partition == part[IDX_PART_OBJECT]:
Expand Down
99 changes: 54 additions & 45 deletions live-installer/installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import frontend.partitioning as partitioning
import config
import shutil
from utils import run, set_governor, is_cmd
from utils import run, set_governor, is_cmd, getoutput
from logger import log, err, inf, set_logfile

gettext.install("live-installer", "/usr/share/locale")
Expand Down Expand Up @@ -408,30 +408,32 @@ def mount_partitions(self):
self.setup.partitions = partitions_sorted
# Mount the target partition
for partition in self.setup.partitions:
if(partition.mount_as not in ["", None, "swap"]):
if partition.mount_as == "/":
if(partition.mount_as not in [None, "swap"] and partition.subvolumes != [] and not self.is_subvolume_has_mountpoint(partition.subvolumes,"")) or (partition.mount_as not in ["", None, "swap"]):
if partition.mount_as == "/" or self.is_subvolume_has_mountpoint(partition.subvolumes, "/"):
self.update_progress(_("Mounting %(partition)s on %(mountpoint)s") % {
'partition': partition.path, 'mountpoint': "/target/"})
log(" ------ Mounting partition %s on %s" %
(partition.path, "/target/"))
fs = partition.type
if 0 == self.do_mount(partition.path, "/target", partition.type, None):
if fs == "btrfs":
log(" ------ Found btrfs filesystem")
# Create subvolumes for Btrfs
os.system("btrfs subvolume create /target/@")
os.system("btrfs subvolume list -p /target")
log(" ------ Umount btrfs to remount subvolume @")
os.system("umount --force /target")
self.do_mount(partition.path, "/target", fs, "subvol=@")
if not self.setup_has_dedicated_home():
# If there is no dedicated home partition, add a @home subvolume to /
os.system("mkdir -p /target/home")
self.do_mount(partition.path, "/target/home", fs, None)
os.system("btrfs subvolume create /target/home/@home")
os.system("btrfs subvolume list -p /target/home")
log(" ------- Umount btrfs to remount subvolume @home")
os.system("umount --force /target/home")
self.do_mount(partition.path, "/target/home", fs, "subvol=@home")
if partition.subvolumes != []:
partition.subvolumes.sort(key = lambda x : x.mount_as, reverse=False)
for subvolume in partition.subvolumes:
print("mounting subvolume {}".format(subvolume.name))
log(" ------ Mounting btrfs subvolume {} on /target/{}".format(subvolume.name,subvolume.mount_as))
os.system("btrfs subvolume create /target/{}".format(subvolume.name))
os.system("umount --force /target")
for subvolume in partition.subvolumes:
log(" ------ Umount btrfs to remount subvolume {}".format(subvolume.name))
# self.do_mount(partition.path, "/target", fs, "subvol={}".format(subvolume))

print("mounting subvolume {}".format(subvolume.mount_as))
self.do_mount(partition.path, "/target/{}".format(subvolume.mount_as), fs, "subvol={}".format(subvolume.name),"--mkdir")
if partition.mount_as != "":
self.do_mount(partition.path, "/target", fs, "subvol=@")
else:
self.error_message(
"Cannot mount rootfs (type: {}): {}".format(partition.type, partition.path))
Expand All @@ -450,23 +452,29 @@ def mount_partitions(self):

# Mount the other partitions
for partition in self.setup.partitions:
if(partition.mount_as not in [ None, "/", "swap", ""]):
if(partition.mount_as not in [ None, "/", "swap"] and partition.subvolumes != [] and not self.is_subvolume_has_mountpoint(partition.subvolumes,"") and not self.is_subvolume_has_mountpoint(partition.subvolumes,"/")) or (partition.mount_as not in ["", None, "/", "swap"]):
log(" ------ Mounting %s on %s" %
(partition.path, "/target" + partition.mount_as))
self.run("mkdir -p /target" + partition.mount_as)
if partition.subvolumes != []:
tempdir = getoutput("mktemp -d").decode("utf-8").strip()
self.do_mount(partition.path, tempdir, partition.type, None)
for subvolume in partition.subvolumes:
os.system("btrfs subvolume create {}/{}".format(tempdir,subvolume.name))
os.system("umount --force {}".format(tempdir))

if partition.type == "fat16" or partition.type == "fat32":
fs = "vfat"
else:
fs = partition.type
self.do_mount(partition.path, "/target" +
partition.mount_as, fs, None)
if partition.mount_as == "/home" and fs == "btrfs":
# Dedicated home partition with Btrfs, needs a @home subvolume
os.system("btrfs subvolume create /target/home/@home")
os.system("btrfs subvolume list -p /target/home")
print(" ------- Umount btrfs to remount subvolume @home")
os.system("umount --force /target/home")
self.do_mount(partition.path, "/target/home", fs, "subvol=@home")

if partition.mount_as != "":
self.do_mount(partition.path, "/target" +
partition.mount_as, fs, None)
elif partition.subvolumes != []:
for subvolume in partition.subvolumes:
self.do_mount(partition.path, "/target" +
subvolume.mount_as, fs, "subvol={}".format(subvolume.name),"--mkdir")

def get_blkid(self, path):
uuid = path # If we can't find the UUID we use the path
Expand All @@ -482,14 +490,11 @@ def get_blkid(self, path):
break
return uuid

def setup_has_dedicated_home(self):
# Find out if there is a dedicated home partition
has_dedicated_home = False
for partition in self.setup.partitions:
if partition.mount_as == "/home":
has_dedicated_home = True
break
return has_dedicated_home
def is_subvolume_has_mountpoint(self, subvolumes, mountpoint):
for subvolume in subvolumes:
if subvolume.mount_as == mountpoint:
return True
return False

def write_fstab(self):
# write the /etc/fstab
Expand Down Expand Up @@ -541,10 +546,6 @@ def write_fstab(self):
rw="ro"
if fs == "fat16" or fs == "fat32":
fs = "vfat"
if fs == "btrfs" and partition.mount_as == "/":
fstab_mount_options = "defaults,subvol=@"
elif fs == "btrfs" and self.setup_has_dedicated_home():
fstab_mount_options = "defaults,subvol=@home"
else:
fstab_mount_options = "defaults,{}".format(rw)

Expand All @@ -556,9 +557,17 @@ def write_fstab(self):
fstab.write("%s %s %s %s %s %s\n" % (
partition_uuid, partition.mount_as, fs, fstab_mount_options, "0", fstab_fsck_option))

if fs == "btrfs" and partition.mount_as == "/" and not self.setup_has_dedicated_home():
fstab.write("%s %s %s %s %s %s\n" % (
partition_uuid, "/home", "btrfs", "defaults,subvol=@home", "0", "0"))
if partition.subvolumes != []:
for subvolume in partition.subvolumes:
fstab.write("# %s\n" % (partition.path))
rw="rw"
if partition.read_only:
rw="ro"
fstab_mount_options = "defaults,subvol={},{}".format(subvolume.name,rw)

partition_uuid = self.get_blkid(partition.path)
fstab.write("%s %s %s %s 0 0\n" % (
partition_uuid, subvolume.mount_as, partition.type, fstab_mount_options))

if self.setup.luks:
self.run("echo '{} {} none luks,tries=3' >> /target/etc/crypttab".format(
Expand Down Expand Up @@ -895,17 +904,17 @@ def do_check_grub(self):
err("!No /target/boot/grub/grub.cfg file found!")
return False

def do_mount(self, device, dest, typevar="auto", options=None):
def do_mount(self, device, dest, typevar="auto", options=None, args=""):
''' Mount a filesystem '''
if typevar == "none" or typevar == "":
return 0
while not os.path.exists(device):
os.sync()
time.sleep(0.1)
if(options is not None):
cmd = "mount -o %s -t %s %s %s" % (options, typevar, device, dest)
cmd = "mount -o %s -t %s %s %s %s" % (options, typevar, device, dest, args)
else:
cmd = "mount -t %s %s %s" % (typevar, device, dest)
cmd = "mount -t %s %s %s %s" % (typevar, device, dest, args)
return self.run(cmd)

def do_unmount(self, mountpoint):
Expand Down

0 comments on commit 5a88b16

Please sign in to comment.