Skip to content
Open
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
12 changes: 9 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ RUN go install github.com/go-delve/delve/cmd/dlv@latest

FROM "${RUST_IMAGE}" AS libkrun-build
ARG LIBKRUN_VERSION=v1.18.1
ARG KERNEL_ARCH="x86_64"
# Pin to the commit that fixes get_extent_at binary search at extent
# boundaries (merged into imago main as 1907e11b). A [patch.crates-io]
# git override substitutes by crate name regardless of version, so this
Expand All @@ -274,14 +275,17 @@ RUN git clone --depth 1 --branch ${LIBKRUN_VERSION} https://github.com/container
printf '\n[patch.crates-io]\nimago = { git = "https://gitlab.com/hreitz/imago.git", rev = "%s" }\n' \
"${IMAGO_FIX_REV}" >> Cargo.toml && \
cargo update imago && \
make -j$(nproc) BLK=1 NET=1
make -j$(nproc) BLK=1 NET=1 && \
cp /libkrun/target/release/libkrun.so /libkrun/target/release/libkrun-nerdbox-${KERNEL_ARCH}.so

FROM scratch AS libkrun
COPY --from=libkrun-build /libkrun/target/release/libkrun.so /libkrun.so
ARG KERNEL_ARCH="x86_64"
COPY --from=libkrun-build /libkrun/target/release/libkrun-nerdbox-${KERNEL_ARCH}.so /libkrun-nerdbox-${KERNEL_ARCH}.so
Comment thread
dmcgowan marked this conversation as resolved.

FROM ${GOLANG_IMAGE} AS dev
ARG CONTAINERD_VERSION=2.1.4
ARG TARGETARCH
ARG KERNEL_ARCH="x86_64"

ENV PATH=/go/src/github.com/containerd/nerdbox/_output:$PATH
WORKDIR /go/src/github.com/containerd/nerdbox
Expand All @@ -299,7 +303,9 @@ COPY --from=docker-cli /usr/local/libexec/docker/cli-plugins/docker-buildx /usr/

COPY --from=dlv /go/bin/dlv /usr/local/bin/dlv

COPY --from=libkrun /libkrun.so /usr/local/lib64/libkrun.so
COPY --from=libkrun /libkrun-nerdbox-${KERNEL_ARCH}.so /usr/local/lib64/libkrun-nerdbox-${KERNEL_ARCH}.so
RUN ln -s libkrun-nerdbox-${KERNEL_ARCH}.so /usr/local/lib64/libkrun-nerdbox.so && \
ln -s libkrun-nerdbox-${KERNEL_ARCH}.so /usr/local/lib64/libkrun.so
ENV LIBKRUN_PATH=/go/src/github.com/containerd/nerdbox/_output

VOLUME /var/lib/containerd
Expand Down
3 changes: 1 addition & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,7 @@ ifeq ($(OS),Darwin)
endif

_output/libkrun.so: FORCE
@echo "$(WHALE) $@"
$(BUILDX) bake libkrun
@task build:libkrun


generate: protos
Expand Down
9 changes: 9 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ tasks:
- cmd: codesign --entitlements cmd/containerd-shim-nerdbox-v1/containerd-shim-nerdbox-v1.entitlements --force -s - {{.OUTPUT_DIR}}/containerd-shim-nerdbox-v1
platforms: [darwin]

build:libkrun:
desc: Build libkrun via Docker Buildx Bake and create generic symlinks in _output/
cmds:
- KERNEL_ARCH={{.KERNEL_ARCH}} docker buildx bake libkrun
- cmd: |
cd {{.OUTPUT_DIR}}
ln -sf libkrun-nerdbox-{{.KERNEL_ARCH}}.so libkrun-nerdbox.so
ln -sf libkrun-nerdbox-{{.KERNEL_ARCH}}.so libkrun.so

build:guest:
desc: Build guest artifacts (kernel and initrd) via Docker Buildx Bake
cmds:
Expand Down
65 changes: 51 additions & 14 deletions internal/vm/libkrun/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,39 +73,76 @@ func (*vmManager) NewInstance(ctx context.Context, state string) (vm.Instance, e
p2 = []string{"/usr/local/lib", "/usr/local/lib64", "/usr/lib", "/lib"}
}
arch := kernelArch()
sharedNames := []string{fmt.Sprintf("libkrun-%s.so", arch), "libkrun.so"}

// variants lists distinct library families in priority order. Each family

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code path has been a pain point up the stack historically. I wonder if it'd make sense to write a small lookup plugin that we can easily swap out. WDYT?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll have to think a bit more about how we would want to do that. We could certainly put the resolution logic in a library, I'm not sure how it would be pluggable though. Since this is specific to the libkrun plugin itself, its reasonable that other backends may have slightly different resolution logic or not have a "nerdbox" specific build at all.

// represents a different patchset / ABI, so we exhaust all search paths
// for one variant before falling back to the next. Within a variant, the
// arch-tagged name is preferred over the generic name.
//
// Priority: libkrun-nerdbox (custom patches) > libkrun (stock upstream)
variants := [][]string{
{fmt.Sprintf("libkrun-nerdbox-%s.so", arch), "libkrun-nerdbox.so"},
{fmt.Sprintf("libkrun-%s.so", arch), "libkrun.so"},
}
switch runtime.GOOS {
case "darwin":
sharedNames = []string{fmt.Sprintf("libkrun-%s.dylib", arch), "libkrun.dylib", fmt.Sprintf("libkrun-efi-%s.dylib", arch), "libkrun-efi.dylib"}
variants = [][]string{
{fmt.Sprintf("libkrun-nerdbox-%s.dylib", arch), "libkrun-nerdbox.dylib"},
{fmt.Sprintf("libkrun-%s.dylib", arch), "libkrun.dylib"},
{fmt.Sprintf("libkrun-efi-%s.dylib", arch), "libkrun-efi.dylib"},
}
p2 = append(p2, "/opt/homebrew/lib")
case "windows":
sharedNames = []string{"krun.dll"}
variants = [][]string{{"krun.dll"}}
}

for _, dir := range append(p1, p2...) {
if dir == "" {
// Unix shell semantics: path element "" means "."
dir = "."
dirs := append(p1, p2...)

// Search: variant → name → directory. All paths are checked for a given
// name before moving to the next name, and all names in a variant are
// exhausted before trying the next variant.
var sharedNames []string // flattened, for use in the error message
for _, variant := range variants {
sharedNames = append(sharedNames, variant...)
}
for _, variant := range variants {
if krunPath != "" {
break
}
var path string
if krunPath == "" {
for _, sharedName := range sharedNames {
path = filepath.Join(dir, sharedName)
for _, name := range variant {
if krunPath != "" {
break
}
for _, dir := range dirs {
if dir == "" {
// Unix shell semantics: path element "" means "."
dir = "."
}
path := filepath.Join(dir, name)
if _, err := os.Stat(path); err == nil {
krunPath = path
break
}
}
}
}

// Kernel and initrd use a single name variant each; still search all dirs.
kernelName := fmt.Sprintf("nerdbox-kernel-%s", arch)
initrdNames := []string{fmt.Sprintf("nerdbox-initrd-%s", arch), "nerdbox-initrd"}
for _, dir := range dirs {
if dir == "" {
dir = "."
}
if kernelPath == "" {
path = filepath.Join(dir, fmt.Sprintf("nerdbox-kernel-%s", kernelArch()))
path := filepath.Join(dir, kernelName)
if _, err := os.Stat(path); err == nil {
kernelPath = path
}
}
if initrdPath == "" {
for _, name := range []string{fmt.Sprintf("nerdbox-initrd-%s", arch), "nerdbox-initrd"} {
path = filepath.Join(dir, name)
for _, name := range initrdNames {
path := filepath.Join(dir, name)
if _, err := os.Stat(path); err == nil {
initrdPath = path
break
Expand Down
Loading