Skip to content

Commit

Permalink
Installer rewrite
Browse files Browse the repository at this point in the history
  • Loading branch information
themylogin committed Feb 22, 2024
1 parent 9fa4a59 commit 9106278
Show file tree
Hide file tree
Showing 22 changed files with 739 additions and 1,207 deletions.
22 changes: 22 additions & 0 deletions .github/workflows/flake8.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: flake8

on:
pull_request:
types:
- 'synchronize'
- 'opened'

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v1
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8
- name: Run flake8
run: flake8 .
24 changes: 24 additions & 0 deletions .github/workflows/unit_tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: unit_tests

on:
pull_request:
types:
- 'synchronize'
- 'opened'

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v1
- name: Install pytest
run: |
python -m pip install --upgrade pip
pip install pytest pytest-asyncio setuptools
- name: Install package
run: python setup.py install
- name: Run tests
run: pytest -v tests
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.idea/*
build/*
dist/*
ixhardware.egg*
__pycache__
*.pyc
42 changes: 25 additions & 17 deletions debian/control
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
Source: truenas-installer
Section: admin
Priority: optional
Maintainer: Kris Moore <[email protected]>
Build-Depends: debhelper-compat (= 12)
Maintainer: Vladimir Vinogradenko <[email protected]>
Build-Depends: debhelper-compat (= 12),
dh-python,
python3-all,
python3-ixhardware,
python3-licenselib,
python3-humanfriendly,
python3-psutil,
python3-setuptools
Standards-Version: 4.4.0

Package: truenas-installer
Package-Type: deb
Package: python3-truenas-installer
Architecture: all
Section: debian-installer
Depends: ${misc:Depends}, dialog, python3-psutil, squashfs-tools, gdisk, openzfs
Description: TrueNAS installation for Debian
This package provides the TrueNAS Debian installation scripts and tools.

Package: truenas-installer-udeb
Package-Type: udeb
Architecture: all
Section: debian-installer
Depends: ${misc:Depends}, debootstrap, partman-base, finish-install, gawk, setserial
Description: TrueNAS installation for Debian
This package provides the TrueNAS Debian installation scripts and tools.

Depends: ${misc:Depends},
${python3:Depends},
dialog,
gdisk,
openzfs,
parted,
python3-ixhardware,
python3-licenselib,
python3-humanfriendly,
python3-psutil,
setserial,
squashfs-tools,
util-linux
Description: TrueNAS Installer
TrueNAS Installer
26 changes: 3 additions & 23 deletions debian/rules
Original file line number Diff line number Diff line change
@@ -1,26 +1,6 @@
#!/usr/bin/make -f
export PYBUILD_NAME=truenas_installer

clean:
rm -rf debian/truenas-installer
rm -rf dist/
%:
dh $@ --with python3 --buildsystem=pybuild

build:
@# Do nothing

build-arch: build

build-indep: build

binary: binary-arch

binary-arch: binary-stamp

binary-indep: binary-stamp

binary-stamp:
mkdir -p debian/truenas-installer/usr/sbin
chmod -R 755 debian/truenas-installer/usr
cp -a usr/sbin/* debian/truenas-installer/usr/sbin/
dh_lintian
dh_gencontrol
dh_builddeb
38 changes: 0 additions & 38 deletions jenkins/Jenkinsfile-buildd

This file was deleted.

12 changes: 0 additions & 12 deletions mk-deb.sh

This file was deleted.

2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[flake8]
max-line-length=120
10 changes: 10 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from setuptools import find_packages, setup


setup(
name="truenas_installer",
version="1.0",
description="TrueNAS installer",
license="GNU3",
packages=find_packages(),
)
21 changes: 21 additions & 0 deletions tests/test_serial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import io
from unittest.mock import Mock, patch

import pytest

from truenas_installer.serial import serial_sql


@pytest.mark.asyncio
async def test__serial_sql():
async def run(args, **kwargs):
return Mock(stdout={
"dmesg": "[ 0.613041] 00:07: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550",
"setserial -G /dev/ttyS0": "/dev/ttyS0 uart 16550A port 0x03f8 irq 4 baud_base 115200 spd_normal skip_test",
}[" ".join(args)])

with patch("truenas_installer.serial.open", lambda path: io.StringIO("console=ttyS")):
with patch("truenas_installer.serial.run", run):
assert await serial_sql() == ("update system_advanced set adv_serialconsole = 1;"
"update system_advanced set adv_serialport = 'ttyS0';"
"update system_advanced set adv_serialspeed = 115200;")
Empty file added truenas_installer/__init__.py
Empty file.
13 changes: 13 additions & 0 deletions truenas_installer/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from ixhardware import parse_dmi

from .installer import Installer


if __name__ == "__main__":
with open("/etc/version") as f:
version = f.read().strip()

dmi = parse_dmi()

installer = Installer(version, dmi)
installer.run()
135 changes: 135 additions & 0 deletions truenas_installer/dialog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import os

import textwrap

import asyncio
import subprocess
import tempfile

__all__ = ["dialog", "dialog_checklist", "dialog_menu", "dialog_msgbox", "dialog_yesno"]


async def dialog(args, check=False):
args = ["dialog"] + args

process = await asyncio.create_subprocess_exec(*args, stderr=subprocess.PIPE)
_, stderr = await process.communicate()

stderr = stderr.decode("utf-8", "ignore")

if check:
if process.returncode != 0:
raise subprocess.CalledProcessError(process.returncode, args, stderr=stderr)

return subprocess.CompletedProcess(args, process.returncode, stderr=stderr)


async def dialog_checklist(title, text, items):
result = await dialog(
[
"--clear",
"--title", title,
"--checklist", text, "20", "60", "0"
] +
sum(
[
[k, v, "off"]
for k, v in items.items()
],
[],
)
)

if result.returncode == 0:
return result.stderr.split()
else:
return None


async def dialog_menu(title, items):
result = await dialog(
[
"--clear",
"--title", title,
"--menu", "", "12", "73", "6"
] +
sum(
[
[str(i), title]
for i, title in enumerate(items.keys(), start=1)
],
[],
)
)

if result.returncode == 0:
return await list(items.values())[int(result.stderr) - 1]()
else:
return None


async def dialog_msgbox(title, text):
await dialog([
"--clear",
"--title", title,
"--msgbox", text,
str(4 + len(text.rstrip().splitlines())), "60",
])


async def dialog_password(title):
with tempfile.NamedTemporaryFile("w") as dialogrc:
dialogrc.write(textwrap.dedent("""\
bindkey formfield TAB FORM_NEXT
bindkey formfield DOWN FORM_NEXT
bindkey formfield UP FORM_PREV
bindkey formbox DOWN FORM_NEXT
bindkey formbox TAB FORM_NEXT
bindkey formbox UP FORM_PREV
"""))
dialogrc.flush()

while True:
with tempfile.NamedTemporaryFile("r+") as output:
fd = os.open(output.name, os.O_WRONLY)
os.set_inheritable(fd, True)

process = await asyncio.create_subprocess_exec(
*(
[
"dialog",
"--insecure",
"--output-fd", f"{fd}",
"--visit-items",
"--passwordform", title,
"10", "70", "0",
"Password:", "1", "10", "", "0", "30", "25", "50",
"Confirm Password:", "2", "10", "", "2", "30", "25", "50",
]
),
env=dict(os.environ, DIALOGRC=dialogrc.name),
pass_fds=(fd,),
)
await process.communicate()
if process.returncode != 0:
return None

passwords = [p.strip() for p in output.read().splitlines()]
if len(passwords) != 2 or not passwords[0] or not passwords[1]:
await dialog_msgbox("Error", "Empty passwords are not allowed.")
continue
elif passwords[0] != passwords[1]:
await dialog_msgbox("Error", "Passwords do not match.")
continue

return passwords[0]


async def dialog_yesno(title, text) -> bool:
result = await dialog([
"--clear",
"--title", title,
"--yesno", text,
"13", "74",
])
return result.returncode == 0
Loading

0 comments on commit 9106278

Please sign in to comment.