Skip to content

Add install_station service and Rework ZFS page UI layout and swap sizing#13

Merged
ericbsd merged 3 commits into
masterfrom
rc
May 14, 2026
Merged

Add install_station service and Rework ZFS page UI layout and swap sizing#13
ericbsd merged 3 commits into
masterfrom
rc

Conversation

@ericbsd
Copy link
Copy Markdown
Contributor

@ericbsd ericbsd commented May 13, 2026

Redesign the ZFS configuration page with a two-column layout (settings
on the left, disk list on the right), add a user-editable swap size
field that defaults to actual RAM size, make the pool name always
editable, and simplify pool type values to plain identifiers (stripe,
mirror, raidz1/2/3). Consolidate duplicated next-button sensitivity
logic into _update_next_button(), replace deprecated Gtk.STOCK icons
with icon names, encrypt swap when GELI is enabled, and bump version
to 0.4.

Summary by Sourcery

Rework the ZFS installation UI and swap handling while wiring an initial-setup service into the installed system and updating packaging.

New Features:

  • Add a user-editable swap size field on the ZFS configuration page, defaulting to system RAM size.
  • Add an initial_setup rc.d service and enable it for first boot after installation, cleaning up display manager autologin settings.

Bug Fixes:

  • Encrypt the swap partition when disk encryption (GELI) is enabled to keep swap consistent with encrypted ZFS.

Enhancements:

  • Redesign the ZFS configuration page into a two-column layout separating settings from the disk list.
  • Always allow editing of the ZFS pool name and simplify pool layout identifiers to stripe/mirror/raidz1-3.
  • Derive default swap sizes from detected system RAM for both MBR and GPT partitioning flows.
  • Centralize next-button sensitivity logic for ZFS setup and refine password strength/verification handling.
  • Replace deprecated stock icons with named icons in the password verification UI.

Build:

  • Install the new rc.d script via setup.py and bump the application version to 0.4.

ericbsd and others added 2 commits December 21, 2025 20:40
Redesign the ZFS configuration page with a two-column layout (settings
on the left, disk list on the right), add a user-editable swap size
field that defaults to actual RAM size, make the pool name always
editable, and simplify pool type values to plain identifiers (stripe,
mirror, raidz1/2/3). Consolidate duplicated next-button sensitivity
logic into _update_next_button(), replace deprecated Gtk.STOCK icons
with icon names, encrypt swap when GELI is enabled, and bump version
to 0.4.
@ericbsd ericbsd requested review from a team as code owners May 13, 2026 11:13
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 13, 2026

Reviewer's Guide

Refactors the ZFS installation UI and behavior to a two-column layout with simplified pool-type handling and user-configurable swap size (defaulting to RAM), consolidates button-sensitivity logic, introduces encrypted swap when GELI is enabled, adds an initial_setup rc service, and bumps the installer version and data files accordingly.

File-Level Changes

Change Details Files
Refactor ZFS configuration logic to support editable pool name, configurable swap size, simplified pool-type identifiers, and centralized button-sensitivity handling.
  • Remove zpool toggle flag and always persist the pool name from the pool entry field.
  • Introduce a swap_entry widget, read its numeric value, and subtract it from the disk size when computing the ZFS partition size.
  • Encrypt swap partitions when disk encryption is enabled by emitting SWAP.eli instead of SWAP in the partition script.
  • Simplify pool-type values to identifiers (stripe, mirror, raidz1/2/3) and generate pool layout disk lists using a for loop.
  • Add _disk_count_valid and update_next_button helpers and use them wherever disk count or password changes affect the Next button state.
  • Replace deprecated Gtk.STOCK* icons with named icons via set_from_icon_name and add a wrapper on_password_changed to feed password_strength.
  • Add digit_only handler for swap_entry insert-text to enforce numeric-only input and wire up password strength/match UI updates.
install_station/use_zfs.py
Redesign the ZFS configuration page UI into a two-column layout with left-side settings and right-side disk list, and tighten encryption-related UX.
  • Replace the previous single-grid layout with an HBox containing a left Gtk.Grid for settings and a right VBox with mirror tips and the disk list scrolled window.
  • Change the pool type selector to a Gtk.ComboBoxText listing plain identifiers and update mirror tip texts accordingly.
  • Make pool name entry always enabled and prefilled with zroot, and add a Swap Size(MB) field defaulting to system RAM.
  • Refine encryption UI labels (e.g., Encrypt Disk (GELI), Confirm) and place strength label and password-match icon alongside their respective entries.
  • Use a dedicated left_grid for all controls and pack the combined layout into vbox1.
install_station/use_zfs.py
Introduce helper for RAM size, wire it into swap sizing, and update installer configuration/output to support an initial_setup service and new data files.
  • Add get_ram_size_mb() in system_calls.py using sysctl -n hw.realmem and return value in MB.
  • Use get_ram_size_mb() instead of a hard-coded 2048MB for swap_size in both MBR and GPT partition creation paths.
  • Extend create_cfg to append runCommands that enable an initial_setup rc service, warn users about it, and clear LightDM autologin configuration.
  • Update setup.py version from 0.1 to 0.4 and install the new src/install_station rc.d script into etc/rc.d.
install_station/system_calls.py
install_station/partition.py
install_station/create_cfg.py
setup.py
src/install_station

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 3 issues, and left some high level feedback:

  • In save_selection, consider validating the user-provided swap_size (e.g., non-negative and less than the available size) to avoid generating a negative or zero zfs_num and producing an invalid ZFS partition line.
  • In get_ram_size_mb, it would be safer to avoid shell=True and to handle parsing errors (e.g., missing or malformed sysctl output) by catching exceptions and returning a sensible default rather than raising.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `save_selection`, consider validating the user-provided `swap_size` (e.g., non-negative and less than the available `size`) to avoid generating a negative or zero `zfs_num` and producing an invalid ZFS partition line.
- In `get_ram_size_mb`, it would be safer to avoid `shell=True` and to handle parsing errors (e.g., missing or malformed `sysctl` output) by catching exceptions and returning a sensible default rather than raising.

## Individual Comments

### Comment 1
<location path="install_station/use_zfs.py" line_range="77-79" />
<code_context>
             raise ValueError("Password cannot be empty when disk encryption is enabled")
-            
+
         size = int(cls.zfs_disk_list[0].partition('-')[2].rstrip()) - 512
-        swap = 0
-        zfs_num = size - swap
-        if cls.disk_encrypt is True:
-            dgeli = '.eli'
-        else:
-            dgeli = ''
+        swap_size = int(cls.swap_entry.get_text() or '0')
+        zfs_num = size - swap_size
+        dgeli = '.eli' if cls.disk_encrypt else ''

</code_context>
<issue_to_address>
**issue (bug_risk):** Guard against swap size larger than available disk size to avoid negative ZFS partition size.

Since `size` comes from the disk and `zfs_num = size - swap_size`, a user-provided `swap_size` larger than `size` will make `zfs_num` negative and likely produce an invalid partition layout. Please either clamp `swap_size` to `size` or raise a clear error when `swap_size >= size` before writing the config.
</issue_to_address>

### Comment 2
<location path="install_station/use_zfs.py" line_range="229-238" />
<code_context>
+            cls._update_next_button()
+
+    @classmethod
+    def on_password_changed(cls, _widget):
+        """
+        Handle password entry changes and update strength display.
+
+        Wraps the common password_strength function to extract the text
+        from the Entry widget and pass it with the strength label.
+
+        Args:
+            _widget: Entry widget that triggered the change (unused)
+        """
+        password_strength(cls.password.get_text(), cls.strenght_label)
+
+    @classmethod
</code_context>
<issue_to_address>
**issue (bug_risk):** Update the next button state when the primary password changes.

Since `_update_next_button` now owns the Next button sensitivity logic, `on_password_changed` should also call it so the button reflects the current match state. Otherwise, changing only the primary password can leave Next enabled even when the passwords no longer match.
</issue_to_address>

### Comment 3
<location path="install_station/system_calls.py" line_range="261-273" />
<code_context>
     return dictionary


+def get_ram_size_mb() -> int:
+    """Query the system RAM size in megabytes using sysctl.
+
+    Returns:
+        System RAM size in MB
+    """
+    output = Popen(
+        'sysctl -n hw.realmem',
+        shell=True,
+        stdout=PIPE,
+        universal_newlines=True
+    ).stdout.read().strip()
+    return int(output) // 1048576
+
+
</code_context>
<issue_to_address>
**suggestion:** Add basic error handling around the sysctl invocation and parsing.

This currently assumes `sysctl -n hw.realmem` always returns a valid integer. If the command fails or returns empty/non-numeric output, `int(output)` will raise and can break partition sizing. Please add minimal guarding (e.g., handle empty output, catch `ValueError`, and/or define a safe fallback).

```suggestion
def get_ram_size_mb() -> int:
    """Query the system RAM size in megabytes using sysctl.

    Returns:
        System RAM size in MB. Returns 0 if the RAM size cannot be determined.
    """
    try:
        process = Popen(
            'sysctl -n hw.realmem',
            shell=True,
            stdout=PIPE,
            universal_newlines=True,
        )
    except OSError:
        # sysctl command not found or could not be executed
        return 0

    output = process.stdout.read().strip() if process.stdout is not None else ""

    if not output:
        # No output from sysctl; treat as unknown
        return 0

    try:
        ram_bytes = int(output)
    except ValueError:
        # Non-numeric output from sysctl; treat as unknown
        return 0

    return ram_bytes // 1048576
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread install_station/use_zfs.py
Comment thread install_station/use_zfs.py
Comment thread install_station/system_calls.py
Replace the swap size text entry with a SpinButton capped to the
selected disk size, consolidate _disk_count_valid and _update_next_button
into a single _is_ready method that checks all preconditions, update the
Next button from on_password_changed so it disables when passwords stop
matching, re-enable the Next button in back_page so navigating back no
longer leaves it stuck disabled, reduce the left panel gap, and fix a
startup crash from mirror_selection firing before swap_entry was created.
@ericbsd ericbsd merged commit 3b5a409 into master May 14, 2026
1 check passed
@ericbsd ericbsd deleted the rc branch May 14, 2026 02:10
@github-project-automation github-project-automation Bot moved this from In Review to Done in Development Tracker May 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants