def _mount_disks(host: DeployHost, device: str) -> None: host.run(f"zpool import -af") # and finally mount host.run(f"mount -t zfs zroot/root/nixos /mnt") host.run(f"mkdir -p /mnt/home /mnt/boot") host.run(f"mount -t zfs zroot/root/home /mnt/home") host.run(f"mount /dev/disk/by-label/NIXOS_BOOT /mnt/boot")
def get_hosts(hosts: str) -> List[DeployHost]: if hosts == "": return [ DeployHost(f"build{n + 1:02d}.nix-community.org") for n in range(4) ] return [DeployHost(f"{h}.nix-community.org") for h in hosts.split(",")]
def deploy_dotfiles(c): """ Deploy to dotfiles """ hosts = [ DeployHost("localhost", meta=dict(flake_attr="desktop")), DeployHost("eve.r", meta=dict(flake_attr="eve")), ] g = DeployGroup(hosts) def deploy_homemanager(host: DeployHost) -> None: host.run( f"""sudo -u joerg zsh <<'EOF' cd $HOME source $HOME/.zshrc homeshick pull homeshick symlink homeshick cd dotfiles nix build --out-link $HOME/.hm-activate ".#hmConfigurations.{host.meta["flake_attr"]}.activation-script" $HOME/.hm-activate/activate EOF""" ) g.run_function(deploy_homemanager)
def deploy(h: DeployHost) -> None: h.run_local( f"rsync {' --exclude '.join([''] + RSYNC_EXCLUDES)} -vaF --delete -e ssh . {h.user}@{h.host}:/etc/nixos" ) # FIXME: build03 has itself as a builder and deadlocks building packages. h.run( f"nixos-rebuild switch --builders '' --option accept-flake-config true" )
def deploy_homemanager(host: DeployHost) -> None: host.run( f"""sudo -u joerg zsh <<'EOF' cd $HOME source $HOME/.zshrc homeshick pull homeshick symlink homeshick cd dotfiles nix build --out-link $HOME/.hm-activate ".#hmConfigurations.{host.meta["flake_attr"]}.activation-script" $HOME/.hm-activate/activate EOF""" )
def deploy(h: DeployHost) -> None: h.run_local( f"rsync {' --exclude '.join([''] + RSYNC_EXCLUDES)} -vaF --delete -e ssh . {h.user}@{h.host}:/etc/nixos" ) flake_path = "/etc/nixos" flake_attr = h.meta.get("flake_attr") if flake_attr: flake_path += "#" + flake_attr target_host = h.meta.get("target_host", "localhost") h.run( f"nixos-rebuild switch --build-host localhost --target-host {target_host} --flake {flake_path}" )
def deploy(h: DeployHost) -> None: h.run_local( f"rsync --exclude=`git ls-files --exclude-standard -oi --directory` --exclude='.git/' -vaF --delete -e ssh . {h.user}@{h.host}:/etc/nixos", ) flake_path = "/etc/nixos" flake_attr = h.meta.get("flake_attr") if flake_attr: flake_path += "#" + flake_attr target_host = h.meta.get("target_host", "localhost") h.run( f"nixos-rebuild switch --build-host localhost --target-host {target_host} --flake {flake_path}" )
def deploy_rock(c): """ Deploy to matchbox """ deploy_nixos( [DeployHost("localhost", meta=dict(target_host="rock.r", flake_attr="rock"))] )
def deploy(c): """ Deploy to eve, eva and localhost """ deploy_nixos( [ DeployHost("eve.r"), DeployHost("localhost"), DeployHost( "eve.r", forward_agent=True, command_prefix="eva.r", meta=dict(target_host="eva.r", flake_attr="eva"), ), ] )
def document_nixos(hosts: List[str]) -> None: """ Generate documentation, expects "hostname.r" """ hosts = DeployGroup([DeployHost(h) for h in HOSTS]) def doc_host(h: DeployHost) -> None: h.run_local(f"../generate-host-info.sh {h.host}") pwd = os.getcwd() os.chdir("docs/hosts") hosts.run_function(doc_host) os.chdir(pwd)
def deploy_matchbox(c): """ Deploy to matchbox """ deploy_nixos( [ DeployHost( "localhost", command_prefix="eva.r", meta=dict(target_host="matchbox.r", flake_attr="matchbox"), ) ] )
def reboot(c, hosts=""): """ Reboot hosts. example usage: fab --hosts clara.r,donna.r reboot """ deploy_hosts = [DeployHost(h) for h in hosts.split(",")] for h in deploy_hosts: g = DeployGroup([h]) g.run("reboot &") print(f"Wait for {h.host} to shutdown", end="") sys.stdout.flush() wait_for_port(h.host, h.port, shutdown=True) print("") print(f"Wait for {h.host} to start", end="") sys.stdout.flush() wait_for_port(h.host, h.port) print("")
def get_lldp_neighbors(hosts: List[str]) -> None: """ Get LLDP-discovered neighbors, expects "hostname.r" """ tum = DeployGroup([DeployHost(h) for h in HOSTS]) def doc_tum(h: DeployHost) -> None: h.run_local(f"../../get-lldp-neighbors.sh {h.host}") pwd = os.getcwd() os.chdir("docs/hosts") if not os.path.exists("lldp"): os.mkdir("lldp") os.chdir("lldp") tum.run_function(doc_tum) os.system("../../generate-lldp-graph.sh") os.chdir("..") shutil.rmtree("lldp", ignore_errors=True) os.chdir(pwd)
def _format_disks(host: DeployHost, device: str) -> None: # format disk with as follow: # - partition 1 will be the boot partition # - partition 2 takes up the rest of the space and is for the system host.run(f"blkdiscard -f {device}") host.run(f"sgdisk -Z -n 1:2048:+1G -N 2 -t 1:ef00 -t 2:8304 {device}") partitions = sfdisk_json(host, device) boot = partitions[0]["node"] uuid = partitions[1]["uuid"].lower() root_part = f"/dev/disk/by-partuuid/{uuid}" host.run( f"zpool create zroot -O acltype=posixacl -O xattr=sa -O compression=lz4 -O atime=off {root_part}" ) host.run(f"partprobe") host.run(f"mkfs.vfat {boot} -n NIXOS_BOOT") # setup zfs dataset host.run(f"zfs create -o mountpoint=none zroot/root") host.run(f"zfs create -o mountpoint=none zroot/docker") host.run(f"zfs create -o mountpoint=legacy zroot/root/nixos") host.run(f"zfs create -o mountpoint=legacy zroot/root/home")
def get_hosts(hosts: str) -> List[DeployHost]: return [DeployHost(h) for h in hosts.split(",")]
def deploy_bernie(c): """ Deploy to bernie """ deploy_nixos([DeployHost("bernie.r")])
def cleanup_gcroots(c, hosts=""): deploy_hosts = [DeployHost(h) for h in hosts.split(",")] for h in deploy_hosts: g = DeployGroup([h]) g.run("find /nix/var/nix/gcroots/auto -type s -delete") g.run("systemctl restart nix-gc")
def deploy_host(c, host): """ Deploy to a single host, i.e. inv deploy-host --host 192.168.1.2 """ deploy_nixos([DeployHost(host)])
def sfdisk_json(host: DeployHost, dev: str) -> List[Any]: out = host.run(f"sfdisk --json {dev}", stdout=subprocess.PIPE) data = json.loads(out.stdout) return data["partitiontable"]["partitions"]
def doc_tum(h: DeployHost) -> None: h.run_local(f"../../get-lldp-neighbors.sh {h.host}")
def doc_host(h: DeployHost) -> None: h.run_local(f"../generate-host-info.sh {h.host}")
def _format_disks(host: DeployHost, devices: List[str]) -> None: assert (len(devices) == 1 or len(devices) == 2 ), "we only support single devices or mirror raids at the moment" # format disk with as follow: # - partition 1 will be the boot partition, needed for legacy (BIOS) boot # - partition 2 is for boot partition # - partition 3 takes up the rest of the space and is for the system for device in devices: host.run( f"sgdisk -Z -n 1:2048:4095 -n 2:4096:+2G -N 3 -t 1:ef02 -t 2:8304 -t 3:8304 {device}" ) # create mdadm raid for /boot with ext4 if len(devices) == 2: boot_parts = [] root_parts = [] for dev in devices: # use partuuids as they are more stable than device names partitions = sfdisk_json(host, dev) boot_parts.append(partitions[1]["node"]) root_parts.append( f"/dev/disk/by-partuuid/{partitions[2]['uuid'].lower()}") host.run( f"mdadm --create --verbose /dev/md127 --raid-devices=2 --level=1 {' '.join(boot_parts)}" ) host.run( f"zpool create zroot -O acltype=posixacl -O xattr=sa -O compression=lz4 mirror {' '.join(root_parts)}" ) boot = "/dev/md127" else: partitions = sfdisk_json(host, devices[0]) boot = partitions[1]["node"] uuid = partitions[2]["uuid"].lower() root_part = f"/dev/disk/by-partuuid/{uuid}" host.run( f"zpool create zroot -O acltype=posixacl -O xattr=sa -O compression=lz4 -O atime=off {root_part}" ) host.run(f"partprobe") host.run(f"mkfs.ext4 -F {boot}") # setup zfs dataset host.run(f"zfs create -o mountpoint=none zroot/root") host.run(f"zfs create -o mountpoint=legacy zroot/root/nixos") host.run(f"zfs create -o mountpoint=legacy zroot/root/home") ## and finally mount host.run(f"mount -t zfs zroot/root/nixos /mnt") host.run(f"mkdir /mnt/home /mnt/boot") host.run(f"mount -t zfs zroot/root/home /mnt/home") host.run(f"mount -t ext4 /dev/md127 /mnt/boot")
def deploy(c): """ Deploy to servers """ deploy_nixos([DeployHost(h) for h in HOSTS])