forked from clan/clan-core
clan-cli: add simple flash command
This commit is contained in:
parent
cd45bb3174
commit
b780754621
@ -69,6 +69,12 @@
|
||||
json metadata about the vm
|
||||
'';
|
||||
};
|
||||
iso = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
description = ''
|
||||
A generated iso of the machine for the flash command
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
description = ''
|
||||
@ -84,6 +90,5 @@
|
||||
inherit (config.clanCore) secretsUploadDirectory;
|
||||
};
|
||||
system.clan.deployment.file = pkgs.writeText "deployment.json" (builtins.toJSON config.system.clan.deployment.data);
|
||||
|
||||
};
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
clanCore.imports = [
|
||||
inputs.sops-nix.nixosModules.sops
|
||||
./clanCore
|
||||
./iso
|
||||
({ pkgs, lib, ... }: {
|
||||
clanCore.clanPkgs = lib.mkDefault self.packages.${pkgs.hostPlatform.system};
|
||||
})
|
||||
|
84
nixosModules/iso/default.nix
Normal file
84
nixosModules/iso/default.nix
Normal file
@ -0,0 +1,84 @@
|
||||
{ config, extendModules, lib, pkgs, ... }:
|
||||
let
|
||||
# Generates a fileSystems entry for bind mounting a given state folder path
|
||||
# It binds directories from /var/clanstate/{some-path} to /{some-path}.
|
||||
# As a result, all state paths will be persisted across reboots, because
|
||||
# the state folder is mounted from the host system.
|
||||
mkBindMount = path: {
|
||||
name = path;
|
||||
value = {
|
||||
device = "/var/clanstate/${path}";
|
||||
options = [ "bind" ];
|
||||
};
|
||||
};
|
||||
|
||||
# Flatten the list of state folders into a single list
|
||||
stateFolders = lib.flatten (
|
||||
lib.mapAttrsToList
|
||||
(_item: attrs: attrs.folders)
|
||||
config.clanCore.state
|
||||
);
|
||||
|
||||
# A module setting up bind mounts for all state folders
|
||||
stateMounts = {
|
||||
virtualisation.fileSystems =
|
||||
lib.listToAttrs
|
||||
(map mkBindMount stateFolders);
|
||||
};
|
||||
|
||||
isoModule = { config, ... }: {
|
||||
imports = [
|
||||
stateMounts
|
||||
];
|
||||
options.clan.iso.disko = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
freeformType = (pkgs.formats.json { }).type;
|
||||
};
|
||||
default = {
|
||||
disk = {
|
||||
iso = {
|
||||
type = "disk";
|
||||
imageSize = "10G"; # TODO add auto image size in disko
|
||||
content = {
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
boot = {
|
||||
size = "1M";
|
||||
type = "EF02"; # for grub MBR
|
||||
};
|
||||
ESP = {
|
||||
size = "100M";
|
||||
type = "EF00";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "vfat";
|
||||
mountpoint = "/boot";
|
||||
};
|
||||
};
|
||||
root = {
|
||||
size = "100%";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "ext4";
|
||||
mountpoint = "/";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
config.disko.devices = lib.mkOverride 51 config.clan.iso.disko;
|
||||
};
|
||||
|
||||
isoConfig = extendModules {
|
||||
modules = [ isoModule ];
|
||||
};
|
||||
in
|
||||
{
|
||||
config = {
|
||||
# for clan vm create
|
||||
system.clan.iso = isoConfig.config.system.build.diskoImages;
|
||||
};
|
||||
}
|
@ -6,7 +6,7 @@ from pathlib import Path
|
||||
from types import ModuleType
|
||||
from typing import Any
|
||||
|
||||
from . import backups, config, flakes, history, machines, secrets, vms
|
||||
from . import backups, config, flakes, flash, history, machines, secrets, vms
|
||||
from .custom_logger import setup_logging
|
||||
from .dirs import get_clan_flake_toplevel
|
||||
from .errors import ClanCmdError, ClanError
|
||||
@ -102,6 +102,11 @@ def create_parser(prog: str | None = None) -> argparse.ArgumentParser:
|
||||
parser_history = subparsers.add_parser("history", help="manage history")
|
||||
history.register_parser(parser_history)
|
||||
|
||||
parser_flash = subparsers.add_parser(
|
||||
"flash", help="flash machines to usb sticks or into isos"
|
||||
)
|
||||
flash.register_parser(parser_flash)
|
||||
|
||||
if argcomplete:
|
||||
argcomplete.autocomplete(parser)
|
||||
|
||||
|
62
pkgs/clan-cli/clan_cli/flash.py
Normal file
62
pkgs/clan-cli/clan_cli/flash.py
Normal file
@ -0,0 +1,62 @@
|
||||
import argparse
|
||||
import importlib
|
||||
import logging
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
from .machines.machines import Machine
|
||||
from .secrets.generate import generate_secrets
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def flash_machine(machine: Machine, device: str | None = None) -> None:
|
||||
secrets_module = importlib.import_module(machine.secrets_module)
|
||||
secret_store = secrets_module.SecretStore(machine=machine)
|
||||
|
||||
generate_secrets(machine)
|
||||
|
||||
with TemporaryDirectory() as tmpdir_:
|
||||
tmpdir = Path(tmpdir_)
|
||||
upload_dir_ = machine.secrets_upload_directory
|
||||
|
||||
if upload_dir_.startswith("/"):
|
||||
upload_dir_ = upload_dir_[1:]
|
||||
upload_dir = tmpdir / upload_dir_
|
||||
upload_dir.mkdir(parents=True)
|
||||
secret_store.upload(upload_dir)
|
||||
|
||||
fs_image = machine.build_nix("config.system.clan.iso")
|
||||
print(fs_image)
|
||||
|
||||
|
||||
@dataclass
|
||||
class FlashOptions:
|
||||
flake: Path
|
||||
machine: str
|
||||
device: str | None
|
||||
|
||||
|
||||
def flash_command(args: argparse.Namespace) -> None:
|
||||
opts = FlashOptions(
|
||||
flake=args.flake,
|
||||
machine=args.machine,
|
||||
device=args.device,
|
||||
)
|
||||
machine = Machine(opts.machine, flake=opts.flake)
|
||||
flash_machine(machine, device=opts.device)
|
||||
|
||||
|
||||
def register_parser(parser: argparse.ArgumentParser) -> None:
|
||||
parser.add_argument(
|
||||
"machine",
|
||||
type=str,
|
||||
help="machine to install",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--device",
|
||||
type=str,
|
||||
help="device to flash the system to",
|
||||
)
|
||||
parser.set_defaults(func=flash_command)
|
Loading…
Reference in New Issue
Block a user