diff --git a/pkg/unikontainers/hypervisors/cloud_hypervisor.go b/pkg/unikontainers/hypervisors/cloud_hypervisor.go index 606a3c02..fe0d5518 100644 --- a/pkg/unikontainers/hypervisors/cloud_hypervisor.go +++ b/pkg/unikontainers/hypervisors/cloud_hypervisor.go @@ -120,15 +120,15 @@ func (ch *CloudHypervisor) BuildExecCmd(args types.ExecArgs, ukernel types.Unike } } - // Initrd configuration - if args.InitrdPath != "" { - exArgs = append(exArgs, "--initramfs", args.InitrdPath) - } - - // Check for extra initrd from unikernel monitor args extraMonArgs := ukernel.MonitorCli() - if extraMonArgs.ExtraInitrd != "" { - exArgs = append(exArgs, "--initramfs", extraMonArgs.ExtraInitrd) + + // Initrd configuration — prefer args.InitrdPath, fall back to unikernel extra initrd + initrdPath := args.InitrdPath + if initrdPath == "" { + initrdPath = extraMonArgs.ExtraInitrd + } + if initrdPath != "" { + exArgs = append(exArgs, "--initramfs", initrdPath) } switch args.Sharedfs.Type { diff --git a/pkg/unikontainers/hypervisors/cloud_hypervisor_test.go b/pkg/unikontainers/hypervisors/cloud_hypervisor_test.go new file mode 100644 index 00000000..c171ec25 --- /dev/null +++ b/pkg/unikontainers/hypervisors/cloud_hypervisor_test.go @@ -0,0 +1,59 @@ +// 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" +) + +type mockUnikernel struct { + extraInitrd string +} + +func (m *mockUnikernel) Init(_ types.UnikernelParams) error { return nil } +func (m *mockUnikernel) CommandString() (string, error) { return "", nil } +func (m *mockUnikernel) SupportsBlock() bool { return false } +func (m *mockUnikernel) SupportsFS(_ string) bool { return false } +func (m *mockUnikernel) MonitorNetCli(_, _ string) string { return "" } +func (m *mockUnikernel) MonitorBlockCli() []types.MonitorBlockArgs { return nil } +func (m *mockUnikernel) MonitorCli() types.MonitorCliArgs { + return types.MonitorCliArgs{ExtraInitrd: m.extraInitrd} +} + +func TestCloudHypervisorSingleInitrd(t *testing.T) { + t.Parallel() + ch := &CloudHypervisor{binary: CloudHypervisorBinary, binaryPath: "/usr/bin/cloud-hypervisor"} + args := types.ExecArgs{ + UnikernelPath: "/unikernel", + InitrdPath: "/primary/initrd", + MemSizeB: 256 * 1024 * 1024, + Command: "console=ttyS0", + } + ukernel := &mockUnikernel{extraInitrd: "/extra/initrd"} + + result, err := ch.BuildExecCmd(args, ukernel) + assert.NoError(t, err) + + count := 0 + for _, arg := range result { + if arg == "--initramfs" { + count++ + } + } + assert.Equal(t, 1, count, "expected exactly one --initramfs flag") +}