diff --git a/pkg/unikontainers/hypervisors/hyperlight.go b/pkg/unikontainers/hypervisors/hyperlight.go new file mode 100644 index 000000000..cb77b5d1e --- /dev/null +++ b/pkg/unikontainers/hypervisors/hyperlight.go @@ -0,0 +1,74 @@ +// Copyright (c) 2023-2026, Nubificus LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hypervisors + +import ( + "fmt" + + "github.com/urunc-dev/urunc/pkg/unikontainers/types" +) + +const ( + HyperlightVmm VmmType = "hyperlight" + HyperlightBinary string = "hyperlight-unikraft" +) + +type Hyperlight struct { + binaryPath string + binary string +} + +// Stop kills the hyperlight process +func (h *Hyperlight) Stop(pid int) error { + return killProcess(pid) +} + +// UsesKVM returns a bool value depending on if the monitor uses KVM +func (h *Hyperlight) UsesKVM() bool { + return true +} + +// SupportsSharedfs returns a bool value depending on the monitor support for shared-fs +func (h *Hyperlight) SupportsSharedfs(_ string) bool { + return false +} + +// Path returns the path to the hyperlight binary. +func (h *Hyperlight) Path() string { + return h.binaryPath +} + +// Ok checks if the hyperlight-unikraft binary is available. +// Binary availability is already verified by getVMMPath via exec.LookPath. +func (h *Hyperlight) Ok() error { + return nil +} + +// BuildExecCmd constructs the hyperlight-unikraft command line. +func (h *Hyperlight) BuildExecCmd(args types.ExecArgs, _ types.Unikernel) ([]string, error) { + cmdArgs := []string{h.binaryPath, args.UnikernelPath} + if args.InitrdPath != "" { + cmdArgs = append(cmdArgs, "--initrd", args.InitrdPath) + } + if args.MemSizeB > 0 { + cmdArgs = append(cmdArgs, "--memory", fmt.Sprintf("%d", args.MemSizeB)) + } + return cmdArgs, nil +} + +// PreExec performs pre-execution setup. Hyperlight has no special pre-exec requirements. +func (h *Hyperlight) PreExec(_ types.ExecArgs) error { + return nil +} diff --git a/pkg/unikontainers/hypervisors/hyperlight_test.go b/pkg/unikontainers/hypervisors/hyperlight_test.go new file mode 100644 index 000000000..ddc0f59d5 --- /dev/null +++ b/pkg/unikontainers/hypervisors/hyperlight_test.go @@ -0,0 +1,51 @@ +// Copyright (c) 2023-2026, Nubificus LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hypervisors + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/urunc-dev/urunc/pkg/unikontainers/types" +) + +func TestHyperlightBuildExecCmd(t *testing.T) { + h := &Hyperlight{ + binaryPath: "/usr/local/bin/hyperlight-unikraft", + } + args := types.ExecArgs{ + UnikernelPath: "/path/to/unikernel", + InitrdPath: "/path/to/initrd", + MemSizeB: 1024 * 1024 * 256, + } + + cmd, err := h.BuildExecCmd(args, nil) + assert.NoError(t, err) + assert.Equal(t, []string{"/usr/local/bin/hyperlight-unikraft", "/path/to/unikernel", "--initrd", "/path/to/initrd", "--memory", "268435456"}, cmd) +} + +func TestHyperlightBuildExecCmdNoInitrd(t *testing.T) { + h := &Hyperlight{ + binaryPath: "/usr/local/bin/hyperlight-unikraft", + } + args := types.ExecArgs{ + UnikernelPath: "/path/to/unikernel", + MemSizeB: 1024 * 1024 * 256, + } + + cmd, err := h.BuildExecCmd(args, nil) + assert.NoError(t, err) + assert.Equal(t, []string{"/usr/local/bin/hyperlight-unikraft", "/path/to/unikernel", "--memory", "268435456"}, cmd) +} diff --git a/pkg/unikontainers/hypervisors/vmm.go b/pkg/unikontainers/hypervisors/vmm.go index c8600957b..f724d6ea8 100644 --- a/pkg/unikontainers/hypervisors/vmm.go +++ b/pkg/unikontainers/hypervisors/vmm.go @@ -66,6 +66,12 @@ var vmmFactories = map[VmmType]VMMFactory{ return &CloudHypervisor{binary: binary, binaryPath: binaryPath} }, }, + HyperlightVmm: { + binary: HyperlightBinary, + createFunc: func(binary, binaryPath string, _ bool) types.VMM { + return &Hyperlight{binary: binary, binaryPath: binaryPath} + }, + }, } func NewVMM(vmmType VmmType, monitors map[string]types.MonitorConfig) (vmm types.VMM, err error) { diff --git a/tests/e2e/test_cases.go b/tests/e2e/test_cases.go index 31bec3d88..6bfe23a28 100644 --- a/tests/e2e/test_cases.go +++ b/tests/e2e/test_cases.go @@ -597,6 +597,23 @@ func ctrTestCases() []containerTestArgs { ExpectOut: "\"Unikraft\" \"FC\" \"urunc\"", TestFunc: matchTest, }, + { + Image: "ghcr.io/hyperlight-dev/hello-hyperlight-unikraft:latest", + Name: "Hyperlight-unikraft-hello", + Devmapper: false, + Seccomp: true, + UID: 0, + GID: 0, + Groups: []int64{}, + Memory: "", + Cli: "", + Volumes: []containerVolume{}, + StaticNet: false, + SideContainers: []string{}, + Skippable: false, + ExpectOut: "Hello World!", + TestFunc: matchTest, + }, { Image: "harbor.nbfc.io/nubificus/urunc/hello-env-qemu-unikraft-initrd:latest", Name: "Qemu-unikraft-environment-variables",