Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
examples/airgap/build
examples/airgap/data
12 changes: 7 additions & 5 deletions deployer/deployer.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@ import (
"io/ioutil"
"os"

"github.com/kairos-io/AuroraBoot/pkg/schema"

"github.com/rs/zerolog/log"
"github.com/spectrocloud-labs/herd"
"gopkg.in/yaml.v3"
)

func LoadByte(b []byte) (*Config, *ReleaseArtifact, error) {
config := &Config{}
release := &ReleaseArtifact{}
func LoadByte(b []byte) (*schema.Config, *schema.ReleaseArtifact, error) {
config := &schema.Config{}
release := &schema.ReleaseArtifact{}

if err := yaml.Unmarshal(b, config); err != nil {
return nil, nil, err
Expand All @@ -27,7 +29,7 @@ func LoadByte(b []byte) (*Config, *ReleaseArtifact, error) {

// LoadFile loads a configuration file and returns the AuroraBoot configuration
// and release artifact information
func LoadFile(file string) (*Config, *ReleaseArtifact, error) {
func LoadFile(file string) (*schema.Config, *schema.ReleaseArtifact, error) {

dat, err := os.ReadFile(file)
if err != nil {
Expand All @@ -38,7 +40,7 @@ func LoadFile(file string) (*Config, *ReleaseArtifact, error) {
}

// Start starts the auroraboot deployer
func Start(config *Config, release *ReleaseArtifact) error {
func Start(config *schema.Config, release *schema.ReleaseArtifact) error {

f, err := ioutil.TempFile("", "auroraboot-dat")
if err != nil {
Expand Down
161 changes: 81 additions & 80 deletions deployer/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,8 @@ import (
"path/filepath"
"strings"

"github.com/rs/zerolog/log"

"github.com/kairos-io/AuroraBoot/pkg/netboot"
"github.com/kairos-io/AuroraBoot/pkg/ops"
"github.com/kairos-io/kairos/pkg/utils"
"github.com/kairos-io/AuroraBoot/pkg/schema"

"github.com/spectrocloud-labs/herd"
)
Expand Down Expand Up @@ -41,7 +38,7 @@ const (
)

// Register register the op dag based on the configuration and the artifact wanted.
func Register(g *herd.Graph, artifact ReleaseArtifact, c Config, cloudConfigFile string) {
func Register(g *herd.Graph, artifact schema.ReleaseArtifact, c schema.Config, cloudConfigFile string) {
dst := c.StateDir("iso")
dstNetboot := c.StateDir("netboot")

Expand All @@ -64,14 +61,29 @@ func Register(g *herd.Graph, artifact ReleaseArtifact, c Config, cloudConfigFile
kernelFile := filepath.Join(dstNetboot, "kairos-kernel")
initrdFile := filepath.Join(dstNetboot, "kairos-initrd")
isoFile := filepath.Join(dst, "kairos.iso")

tmpRootfs := c.StateDir("temp-rootfs")
fromImage := artifact.ContainerImage != ""
fromImageOption := func() bool { return fromImage }
isoOption := func() bool { return !fromImage }
netbootOption := func() bool { return !c.DisableNetboot }
netbootReleaseOption := func() bool { return !c.DisableNetboot && !fromImage }

// Pull locak docker daemon if container image starts with docker://
containerImage := artifact.ContainerImage
local := false

if strings.HasPrefix(containerImage, "docker://") {
local = true
containerImage = strings.ReplaceAll(containerImage, "docker://", "")
}

// Preparation steps
g.Add(opPreparetmproot, herd.WithCallback(
func(ctx context.Context) error {
return os.MkdirAll(dstNetboot, 0700)
},
))

g.Add(opPrepareNetboot, herd.WithCallback(
func(ctx context.Context) error {
return os.MkdirAll(dstNetboot, 0700)
Expand All @@ -82,80 +94,69 @@ func Register(g *herd.Graph, artifact ReleaseArtifact, c Config, cloudConfigFile
return os.MkdirAll(dst, 0700)
}))

fromImage := artifact.ContainerImage != ""

// Pull locak docker daemon if container image starts with docker://
containerImage := artifact.ContainerImage
local := false

if strings.HasPrefix(containerImage, "docker://") {
local = true
containerImage = strings.ReplaceAll(containerImage, "docker://", "")
}

if fromImage {
g.Add(opContainerPull, herd.WithDeps(opPreparetmproot), herd.WithCallback(ops.PullContainerImage(containerImage, tmpRootfs, local)))
g.Add(opGenISO, herd.WithDeps(opContainerPull), herd.WithCallback(ops.GenISO(kairosDefaultArtifactName, tmpRootfs, dst)))
if !c.DisableNetboot {
g.Add(opExtractNetboot, herd.WithDeps(opGenISO), herd.WithCallback(ops.ExtractNetboot(isoFile, dstNetboot, kairosDefaultArtifactName)))
}
} else {
//TODO: add Validate step
g.Add(opDownloadInitrd, herd.WithDeps(opPrepareNetboot), herd.WithCallback(ops.DownloadArtifact(artifact.InitrdURL(), initrdFile)))
g.Add(opDownloadKernel, herd.WithDeps(opPrepareNetboot), herd.WithCallback(ops.DownloadArtifact(artifact.KernelURL(), kernelFile)))
g.Add(opDownloadSquashFS, herd.WithDeps(opPrepareNetboot), herd.WithCallback(ops.DownloadArtifact(artifact.SquashFSURL(), squashFSfile)))
g.Add(opDownloadISO, herd.WithCallback(ops.DownloadArtifact(artifact.ISOUrl(), isoFile)))
}

if !c.DisableISOboot {
g.Add(opCopyCloudConfig,
herd.WithDeps(opPrepareISO),
herd.WithCallback(func(ctx context.Context) error {
_, err := copy(cloudConfigFile, filepath.Join(dst, "config.yaml"))
return err
}))

g.Add(opInjectCC,
herd.WithDeps(opCopyCloudConfig),
herd.ConditionalOption(func() bool { return !fromImage }, herd.WithDeps(opDownloadISO)),
herd.ConditionalOption(func() bool { return fromImage }, herd.WithDeps(opGenISO)),
herd.WithCallback(func(ctx context.Context) error {
os.Chdir(dst)
injectedIso := isoFile + ".custom.iso"
os.Remove(injectedIso)
out, err := utils.SH(fmt.Sprintf("xorriso -indev %s -outdev %s -map %s /config.yaml -boot_image any replay", isoFile, injectedIso, filepath.Join(dst, "config.yaml")))
log.Print(out)
return err
}))

if !c.DisableHTTPServer {
g.Add(
opStartHTTPServer,
herd.Background,
herd.ConditionalOption(func() bool { return fromImage }, herd.WithDeps(opGenISO, opCopyCloudConfig, opInjectCC)),
herd.ConditionalOption(func() bool { return !fromImage }, herd.WithDeps(opDownloadISO, opCopyCloudConfig, opInjectCC)),
herd.WithCallback(ops.ServeArtifacts(listenAddr, dst)),
)
}
}

if !c.DisableNetboot {
g.Add(
opStartNetboot,
herd.ConditionalOption(func() bool { return !fromImage }, herd.WithDeps(opDownloadInitrd, opDownloadKernel, opDownloadSquashFS)),
herd.ConditionalOption(func() bool { return fromImage }, herd.WithDeps(opExtractNetboot)),
herd.Background,
herd.WithCallback(func(ctx context.Context) error {
log.Info().Msgf("Start pixiecore")

configFile := cloudConfigFile

cmdLine := `rd.neednet=1 ip=dhcp rd.cos.disable root=live:{{ ID "%s" }} netboot nodepair.enable config_url={{ ID "%s" }} console=tty1 console=ttyS0 console=tty0`
return netboot.Server(kernelFile, "AuroraBoot", fmt.Sprintf(cmdLine, squashFSfile, configFile), address, netbootPort, []string{initrdFile}, true)
},
),
)
}
g.Add(opCopyCloudConfig,
herd.WithDeps(opPrepareISO),
herd.WithCallback(func(ctx context.Context) error {
_, err := copy(cloudConfigFile, filepath.Join(dst, "config.yaml"))
return err
}))

// Ops to generate from container image
g.Add(opContainerPull,
herd.EnableIf(fromImageOption),
herd.WithDeps(opPreparetmproot), herd.WithCallback(ops.PullContainerImage(containerImage, tmpRootfs, local)))
g.Add(opGenISO,
herd.EnableIf(fromImageOption),
herd.WithDeps(opContainerPull, opCopyCloudConfig), herd.WithCallback(ops.GenISO(kairosDefaultArtifactName, tmpRootfs, dst, c.ISO)))
g.Add(opExtractNetboot,
herd.EnableIf(func() bool { return fromImage && !c.DisableNetboot }),
herd.WithDeps(opGenISO), herd.WithCallback(ops.ExtractNetboot(isoFile, dstNetboot, kairosDefaultArtifactName)))

//TODO: add Validate step
// Ops to download from releases
g.Add(opDownloadInitrd,
herd.EnableIf(netbootReleaseOption),
herd.WithDeps(opPrepareNetboot), herd.WithCallback(ops.DownloadArtifact(artifact.InitrdURL(), initrdFile)))
g.Add(opDownloadKernel,
herd.EnableIf(netbootReleaseOption),
herd.WithDeps(opPrepareNetboot), herd.WithCallback(ops.DownloadArtifact(artifact.KernelURL(), kernelFile)))
g.Add(opDownloadSquashFS,
herd.EnableIf(netbootReleaseOption),
herd.WithDeps(opPrepareNetboot), herd.WithCallback(ops.DownloadArtifact(artifact.SquashFSURL(), squashFSfile)))
g.Add(opDownloadISO,
herd.EnableIf(isoOption),
herd.WithCallback(ops.DownloadArtifact(artifact.ISOUrl(), isoFile)))

// Inject the data into the ISO
g.Add(opInjectCC,
herd.EnableIf(isoOption),
herd.WithDeps(opCopyCloudConfig),
herd.ConditionalOption(isoOption, herd.WithDeps(opDownloadISO)),
herd.WithCallback(ops.InjectISO(dst, isoFile, c.ISO)))

// Start servers
g.Add(
opStartHTTPServer,
herd.Background,
herd.EnableIf(func() bool { return !c.DisableISOboot && !c.DisableHTTPServer }),
herd.IfElse(
fromImage,
herd.WithDeps(opGenISO, opCopyCloudConfig),
herd.WithDeps(opDownloadISO, opCopyCloudConfig, opInjectCC),
),
herd.WithCallback(ops.ServeArtifacts(listenAddr, dst)),
)

g.Add(
opStartNetboot,
herd.EnableIf(netbootOption),
herd.ConditionalOption(isoOption, herd.WithDeps(opDownloadInitrd, opDownloadKernel, opDownloadSquashFS)),
herd.ConditionalOption(fromImageOption, herd.WithDeps(opExtractNetboot)),
herd.Background,
herd.WithCallback(
ops.StartPixiecore(cloudConfigFile, squashFSfile, address, netbootPort, initrdFile, kernelFile, c.NetBoot),
),
)
}

func copy(src, dst string) (int64, error) {
Expand Down
26 changes: 26 additions & 0 deletions examples/airgap/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/bash
set -ex

pushd image-bundle
docker build -t bundle .
popd

mkdir data

pushd data
docker save bundle -o bundle.tar
popd

docker run -v $PWD/config.yaml:/config.yaml \
-v $PWD/build:/tmp/auroraboot \
-v $PWD/data:/tmp/data \
--rm -ti auroraboot \
--set "disable_http_server=true" \
--set "disable_netboot=true" \
--set "iso.data=/tmp/data" \
--cloud-config /config.yaml \
--set "state_dir=/tmp/auroraboot" \
--set "artifact_version=v1.6.1-k3sv1.26.1+k3s1" \
--set "release_version=v1.6.1" \
--set "flavor=fedora" \
--set "repository=kairos-io/provider-kairos"
22 changes: 22 additions & 0 deletions examples/airgap/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#cloud-config

install:
auto: true
device: "auto"
reboot: true
bundles:
# This bundle needs to run after-install as it consumes assets from the LiveCD
# which is not accessible otherwise at the first boot (there is no live-cd with any bundle.tar)
- targets:
- run:///run/initramfs/live/bundle.tar
local_file: true

# Define the user accounts on the node.
users:
- name: "kairos" # The username for the user.
passwd: "kairos" # The password for the user.
ssh_authorized_keys: # A list of SSH keys to add to the user's authorized keys.
- github:mudler # A key from the user's GitHub account.

k3s:
enabled: true
7 changes: 7 additions & 0 deletions examples/airgap/image-bundle/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FROM alpine as build
WORKDIR /build
RUN wget https://github.com/k3s-io/k3s/releases/download/v1.23.16%2Bk3s1/k3s-airgap-images-amd64.tar.gz

FROM scratch
COPY ./run.sh /
COPY --from=build /build/k3s-airgap-images-amd64.tar.gz /k3s-airgap-images-amd64.tar.gz
4 changes: 4 additions & 0 deletions examples/airgap/image-bundle/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash

mkdir -p /usr/local/.state/var-lib-rancher.bind/k3s/agent/images/
cp -rfv ./k3s-airgap-images-amd64.tar.gz /usr/local/.state/var-lib-rancher.bind/k3s/agent/images/
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ go 1.19
require (
github.com/cavaliergopher/grab/v3 v3.0.1
github.com/kairos-io/kairos v1.5.0
github.com/otiai10/copy v1.9.0
github.com/rs/zerolog v1.29.0
github.com/spectrocloud-labs/herd v0.4.2
github.com/urfave/cli v1.22.12
github.com/urfave/cli/v2 v2.24.4
go.universe.tf/netboot v0.0.0-20230225040044-0e2ca55deb50
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0
gopkg.in/yaml.v3 v3.0.1
Expand Down
Loading