Documentation
¶
Overview ¶
Package library builds and runs GoNIX Library images: a kernel, a slim init (cmd/libinit) and one or more Go programs, with no userland. See docs/library-images.md.
Index ¶
- Constants
- Variables
- func BaseCmdline(arch string, debug bool) string
- func IsISO(path string) bool
- func IsImage(path string) bool
- func Pack(ctx context.Context, o Options) (string, error)
- func ParseIndex(r io.Reader) (map[string]Package, error)
- func QEMUCommand(b *Bootable, o RunOptions, tmp string) ([]string, error)
- func Run(ctx context.Context, path string, o RunOptions) error
- func SourceDir(ctx context.Context) (string, error)
- type Bootable
- type CPIOWriter
- func (c *CPIOWriter) CharDev(name string, perm uint32, major, minor uint32) error
- func (c *CPIOWriter) Close() error
- func (c *CPIOWriter) Dir(name string, perm uint32) error
- func (c *CPIOWriter) File(name string, perm uint32, data []byte) error
- func (c *CPIOWriter) Symlink(name, target string) error
- type ExitStatus
- type Image
- type Manifest
- type Options
- type Package
- type PackageFile
- type Program
- type Repo
- type RunOptions
Constants ¶
const ( RestartOnFailure = manifest.RestartOnFailure RestartAlways = manifest.RestartAlways RestartNever = manifest.RestartNever )
Restart policies.
const ( FormatISO = "iso" FormatDir = "dir" )
Image formats.
const ( KernelFile = "kernel" InitrdFile = "initrd" CmdlineFile = "cmdline" ImageFile = "image.json" )
Files inside an image directory.
const DefaultKernelPackage = "kernel-library"
DefaultKernelPackage is the slim kernel built for Library images (ports/kernel-library).
const DefaultRepo = "https://pkgs.ulinux.org"
DefaultRepo is the GoNIX binary package repository. Library images take their kernel (and CA certificates) from the same published packages a full GoNIX system installs, so they boot the kernel the boot suite has proven.
const ManifestPath = manifest.Path
ManifestPath is where the manifest lives inside an image.
const ModulePath = "git.mills.io/prologic/gonix"
ModulePath is the GoNIX module, whose cmd/libinit (and, for debug images, cmd/coreutils) go into every Library image.
const NoStatusExit = 125
NoStatusExit is the exit status for ErrNoStatus: 125, as docker run uses for a failure of the machinery rather than of the program in it.
Variables ¶
var ErrNoStatus = errors.New("the VM stopped without reporting a status: the kernel or init crashed (the console above says how)")
ErrNoStatus is Run's error when the VM stopped without init reporting how its programs ended. The kernel command line carries panic=-1 and QEMU runs with -no-reboot, so a kernel panic — or PID 1 dying, which is one — ends QEMU as cleanly as a poweroff does; only the missing status tells them apart.
Functions ¶
func BaseCmdline ¶
BaseCmdline is the kernel command line every image of an arch starts with. panic=-1 reboots at once on a panic, which a VM run with -no-reboot (as `gonix run` does) turns into exiting.
func ParseIndex ¶
ParseIndex parses a PKGINDEX (tab-separated: name epoch version release buildtime file size sha256 depends; # starts a comment).
func QEMUCommand ¶
func QEMUCommand(b *Bootable, o RunOptions, tmp string) ([]string, error)
QEMUCommand returns the QEMU command line that boots an image. A firmware boot may need a writable UEFI variable store, which it creates in tmp.
func Run ¶
func Run(ctx context.Context, path string, o RunOptions) error
Run boots a packed image in QEMU on this terminal and returns when the VM powers off: nil, an ExitStatus when its programs failed, or ErrNoStatus when the guest crashed before init could say how they ended.
Run owns the terminal rather than handing it to QEMU, so that ^C means "shut down": it presses the VM's power button, which init answers by stopping the programs cleanly; a second ^C kills QEMU. (In a debug image ^C belongs to the console shell and is passed through.) QEMU's own Ctrl-A X still kills it at once.
func SourceDir ¶
SourceDir finds a GoNIX source tree to build the image's init from, in order:
- $GONIX_SRC, for someone working on GoNIX itself;
- the module version this binary was built from, when it was installed with `go install git.mills.io/prologic/gonix/cmd/gonix@<version>` — `go mod download` puts that exact version in the module cache, so the init always matches the tool;
- the tree this binary was compiled from, when it was built from a checkout (`go install ./cmd/gonix`, `go run`).
Types ¶
type Bootable ¶
type Bootable struct {
Image *Image
Kernel string // kernel file
Initrd string // initramfs file
ISO string // the ISO, when the image is one
}
Bootable is an image opened for booting.
type CPIOWriter ¶
type CPIOWriter struct {
// contains filtered or unexported fields
}
CPIOWriter writes an initramfs archive in the "newc" cpio format the kernel unpacks. It is written in Go so `gonix pack` needs no cpio(1) and no root: device nodes are just headers here, so /dev/console can be created by a user on macOS.
The kernel does not create missing parent directories when it unpacks, so the writer adds each parent the first time something beneath it is added. Every entry is owned by root and carries the same mtime, so the same inputs give byte-identical archives.
func NewCPIOWriter ¶
func NewCPIOWriter(w io.Writer, mtime int64) *CPIOWriter
NewCPIOWriter returns a writer whose entries all carry mtime (seconds since the epoch).
func (*CPIOWriter) CharDev ¶
func (c *CPIOWriter) CharDev(name string, perm uint32, major, minor uint32) error
CharDev adds a character device node.
func (*CPIOWriter) Close ¶
func (c *CPIOWriter) Close() error
Close writes the trailer. It does not close the underlying writer.
func (*CPIOWriter) Dir ¶
func (c *CPIOWriter) Dir(name string, perm uint32) error
Dir adds a directory (and its parents).
func (*CPIOWriter) File ¶
func (c *CPIOWriter) File(name string, perm uint32, data []byte) error
File adds a regular file with the given contents.
func (*CPIOWriter) Symlink ¶
func (c *CPIOWriter) Symlink(name, target string) error
Symlink adds a symbolic link at name pointing to target.
type ExitStatus ¶
type ExitStatus int
ExitStatus is the status the image's programs ended with, as reported by init over the status port. A command returning it should exit with it.
func (ExitStatus) Error ¶
func (e ExitStatus) Error() string
type Image ¶
type Image struct {
Name string `json:"name"`
Arch string `json:"arch"`
Kernel string `json:"kernel"` // published kernel version, or "local"
Cmdline string `json:"cmdline"`
Manifest Manifest `json:"manifest"`
}
Image is the on-disk description of a packed image (image.json).
type Options ¶
type Options struct {
// Packages are the Go packages to build, as `go build` takes them (".",
// "./cmd/server", an import path), or pkg@version for a package outside
// the current module. Default ".".
Packages []string
// Dir is the directory the packages are resolved from (default: cwd).
Dir string
// Arch is the target architecture, amd64 or arm64.
Arch string
// Format is FormatISO (the default: one hybrid ISO) or FormatDir (the
// kernel, initramfs, command line and image.json as loose files).
Format string
// Output is the image to write (default <name>.iso, or <name>.vm for a
// directory).
Output string
// Hostname defaults to the first program's name.
Hostname string
// Name overrides the program's name (only with a single package).
Name string
// Args, Env and Restart apply to every program.
Args []string
Env []string
Restart string
// Files are extra files baked in, each "src:dst" with dst absolute; a
// directory src is copied recursively.
Files []string
// Debug adds coreutils, a console shell and the SSH server.
Debug bool
// Kernel is a local kernel image to use instead of a published one.
Kernel string
// KernelPackage is the published kernel to boot (default
// DefaultKernelPackage, the slim one; "kernel" is full GoNIX's).
KernelPackage string
// Bootloader is a local bootloader package archive to use instead of the
// published one (ISO images).
Bootloader string
// Cmdline is appended to the kernel command line.
Cmdline string
// Repo is the package repository (default DefaultRepo).
Repo string
// CacheDir caches downloaded packages (default <user cache>/gonix).
CacheDir string
// Log reports progress.
Log func(format string, args ...any)
}
Options configure Pack.
type Package ¶
type Package struct {
Name string
Version string
Release string
File string
Size int64
SHA256 string
}
Package is one PKGINDEX record.
type PackageFile ¶
type PackageFile struct {
Name string // path inside the archive, without a leading ./ or /
Mode int64
Data []byte // contents of a regular file
Linkname string // target of a symlink
}
PackageFile is one regular file or symlink read out of a package archive.
func ReadPackage ¶
func ReadPackage(archive string, keep func(name string) bool) ([]PackageFile, error)
ReadPackage returns the regular files and symlinks in a package archive whose path satisfies keep. Packages are tar archives, gzipped or not (the published ones are named .tar.gz but are plain tar), so both are accepted.
type Repo ¶
type Repo struct {
URL string // base URL; packages live under <URL>/<arch>/
Arch string // amd64 or arm64
CacheDir string // where downloaded packages are kept
Client *http.Client
// Log, if set, reports downloads.
Log func(format string, args ...any)
// contains filtered or unexported fields
}
Repo fetches packages from a repository, caching them on disk by checksum.
type RunOptions ¶
type RunOptions struct {
// Memory in MiB (default 256).
Memory int
// CPUs (default 1).
CPUs int
// Publish forwards host ports to the guest, each "HOST:GUEST" (TCP),
// listening on 127.0.0.1 unless given as "HOSTADDR:HOST:GUEST".
Publish []string
// Disk is a raw disk image attached as the data disk, mounted at /data.
Disk string
// SSHKey is a public key file authorised for root (debug images).
SSHKey string
// SSHPort forwards this host port, on 127.0.0.1, to the guest's SSH
// (debug images, default 2222).
SSHPort int
// Cmdline is appended to the image's kernel command line.
Cmdline string
// DryRun prints the QEMU command instead of running it.
DryRun bool
// Firmware, for an ISO, boots it through firmware and its bootloader
// instead of loading the kernel directly: "bios" (amd64) or "uefi". A
// UEFI firmware file may follow a colon ("uefi:/path/to/code.fd").
Firmware string
// AsDisk attaches the ISO as a hard disk rather than a CD in a firmware
// boot, which boots it through its hybrid MBR as from a USB stick.
AsDisk bool
// Config is an env file of configuration at boot, attached as a NoCloud
// seed disk (docs/library-images.md, decisions 11–13).
Config string
// QEMU arguments are added to the end of the QEMU command, as given: a
// second network card, say.
QEMU []string
// Log, if set, reports when the VM starts.
Log func(format string, args ...any)
// contains filtered or unexported fields
}
RunOptions configure Run.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package manifest is the contract between the two halves of a Library image (docs/library-images.md): `gonix pack` writes it into the initramfs, and cmd/libinit reads it at boot to learn what to run.
|
Package manifest is the contract between the two halves of a Library image (docs/library-images.md): `gonix pack` writes it into the initramfs, and cmd/libinit reads it at boot to learn what to run. |