Skip to content

Commit

Permalink
feat: add tooling for creating snapshots programmatically
Browse files Browse the repository at this point in the history
  • Loading branch information
renan061 committed Aug 15, 2024
1 parent 8870048 commit 04ffa77
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 53 deletions.
54 changes: 1 addition & 53 deletions build/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -103,58 +103,6 @@ RUN <<EOF
rm -rf /var/lib/apt/lists/*
EOF

# =============================================================================
# STAGE: emulator-devel
#
# - Install libarchive13 (setup -- required by xgenext2fs).
# - Install libcmt.
# - Install xgenext2fs.
# =============================================================================

FROM emulator AS emulator-devel

ARG MACHINE_TOOLS_VERSION
ARG MACHINE_XGENEXT2FS_VERSION
ARG DEBIAN_FRONTEND=noninteractive

# Install libarchive13 (setup -- required by xgenext2fs).
RUN <<EOF
set -e
apt-get update
apt-get install -y --no-install-recommends libarchive13
EOF

# Install libcmt (cartesi/machine-emulator-tools).
RUN <<EOF
set -e
URL=https://github.com/cartesi/machine-emulator-tools/releases/download
VERSION=v${MACHINE_TOOLS_VERSION}
ARTIFACT=libcmt-${VERSION}-dev.deb
curl -fsSL ${URL}/${VERSION}/${ARTIFACT} -o ./libcmt.deb
apt-get install -y ./libcmt.deb
rm ./libcmt.deb
mv /usr/riscv64-linux-gnu/include/libcmt /usr/include/
mv /usr/riscv64-linux-gnu/lib/libcmt.a /usr/lib/
rm -rf /usr/riscv64-linux-gnu
EOF

# Install xgenext2fs (cartesi/genext2fs).
RUN <<EOF
set -e
URL=https://github.com/cartesi/genext2fs/releases/download
VERSION=v${MACHINE_XGENEXT2FS_VERSION}
ARCH=$(dpkg --print-architecture)
ARTIFACT=xgenext2fs_${ARCH}.deb
curl -fsSL ${URL}/${VERSION}/${ARTIFACT} -o ./xgenext2fs.deb
apt-get install -y ./xgenext2fs.deb
rm ./xgenext2fs.deb
EOF

# Clean up.
RUN <<EOF
rm -rf /var/lib/apt/lists/*
EOF

# =============================================================================
# STAGE: rollups-node-ci
#
Expand All @@ -165,7 +113,7 @@ EOF
# - Install docker.
# =============================================================================

FROM emulator-devel AS rollups-node-ci
FROM emulator AS rollups-node-ci

# Install git and build-essential (setup).
RUN <<EOF
Expand Down
114 changes: 114 additions & 0 deletions test/snapshot/snapshot.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// (c) Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: Apache-2.0 (see LICENSE)

// Package snapshot implements dynamic snapshot instantiation.
// It defines the Snapshot type, which manages the lifecycle of a snapshot.
package snapshot

import (
"errors"
"fmt"
"math"
"math/rand"
"os"
"strings"

"github.com/cartesi/rollups-node/pkg/emulator"
)

const ramLength = 64 << 20

// ImagesPath is the path to the folder containing the linux.bin and rootfs.ext2 files.
// It can be redefined in case the files are not in the default folder.
var ImagesPath = "/usr/share/cartesi-machine/images/"

type Snapshot struct {
id string // an unique id used to avoid name clashing
temp string // path to the temporary directory containing snapshot relevant files
path string // path to the snapshot directory

// Reason why the snapshot stopped running before being stored.
BreakReason emulator.BreakReason
}

// FromScript creates a snapshot given an script command.
func FromScript(command string, cycles uint64) (*Snapshot, error) {
snapshot := &Snapshot{id: fmt.Sprintf("fromscript%d", rand.Int())}

err := snapshot.createTempDir()
if err != nil {
return nil, err
}

config := defaultMachineConfig()
config.Dtb.Entrypoint = command

err = snapshot.createRunAndStore(config, cycles)
return snapshot, err
}

// Path returns the path to the directory where the snapshot is stored.
func (snapshot *Snapshot) Path() string {
return snapshot.path
}

// Close deletes the temporary directory created to hold the snapshot files.
func (snapshot *Snapshot) Close() error {
return os.RemoveAll(snapshot.temp)
}

// ------------------------------------------------------------------------------------------------

func defaultMachineConfig() *emulator.MachineConfig {
config := emulator.NewDefaultMachineConfig()
config.Ram.Length = ramLength
config.Ram.ImageFilename = ImagesPath + "linux.bin"
config.Dtb.Bootargs = strings.Join([]string{"quiet",
"no4lvl",
"quiet",
"earlycon=sbi",
"console=hvc0",
"rootfstype=ext2",
"root=/dev/pmem0",
"rw",
"init=/usr/sbin/cartesi-init"}, " ")
config.FlashDrive = []emulator.MemoryRangeConfig{{
Start: 0x80000000000000, //nolint:mnd
Length: math.MaxUint64,
ImageFilename: ImagesPath + "rootfs.ext2",
}}
return config
}

func (snapshot *Snapshot) createTempDir() error {
temp, err := os.MkdirTemp("", snapshot.id+"-*")
if err != nil {
return err
}
snapshot.temp = temp
snapshot.path = snapshot.temp + "/snapshot"
return nil
}

func (snapshot *Snapshot) createRunAndStore(config *emulator.MachineConfig, cycles uint64) error {
// Creates the (local) machine.
machine, err := emulator.NewMachine(config, &emulator.MachineRuntimeConfig{})
if err != nil {
return errors.Join(err, snapshot.Close())
}
defer machine.Delete()

// Runs the machine.
snapshot.BreakReason, err = machine.Run(cycles)
if err != nil {
return errors.Join(err, snapshot.Close())
}

// Stores the machine.
err = machine.Store(snapshot.path)
if err != nil {
return errors.Join(err, snapshot.Close())
}

return nil
}

0 comments on commit 04ffa77

Please sign in to comment.