From 0e24f37a19362f946356fd3bfaf1d08d9d1c5793 Mon Sep 17 00:00:00 2001 From: viju Date: Mon, 18 May 2026 18:58:50 +0530 Subject: [PATCH 1/2] fix: use annotation for MirageOS block device name Related: #315 Signed-off-by: viju --- pkg/unikontainers/config.go | 15 +++++++++++ pkg/unikontainers/config_test.go | 4 +++ pkg/unikontainers/types/types.go | 1 + pkg/unikontainers/unikernels/mirage.go | 17 ++++++++---- pkg/unikontainers/unikernels/mirage_test.go | 30 +++++++++++++++++++++ pkg/unikontainers/unikontainers.go | 11 ++++---- 6 files changed, 68 insertions(+), 10 deletions(-) diff --git a/pkg/unikontainers/config.go b/pkg/unikontainers/config.go index 9184db979..350a54648 100644 --- a/pkg/unikontainers/config.go +++ b/pkg/unikontainers/config.go @@ -45,6 +45,7 @@ const ( annotBlock = "com.urunc.unikernel.block" annotBlockMntPoint = "com.urunc.unikernel.blkMntPoint" annotMountRootfs = "com.urunc.unikernel.mountRootfs" + annotBlkDev = "com.urunc.unikernel.blkDev" ) // A UnikernelConfig struct holds the info provided by bima image on how to execute our unikernel @@ -58,6 +59,7 @@ type UnikernelConfig struct { Block string `json:"com.urunc.unikernel.block,omitempty"` BlkMntPoint string `json:"com.urunc.unikernel.blkMntPoint,omitempty"` MountRootfs string `json:"com.urunc.unikernel.mountRootfs"` + BlkDev string `json:"com.urunc.unikernel.blkDev,omitempty"` } // validate checks if the mandatory configuration fields are present. @@ -119,6 +121,7 @@ func getConfigFromSpec(spec *specs.Spec) *UnikernelConfig { block := spec.Annotations[annotBlock] blkMntPoint := spec.Annotations[annotBlockMntPoint] MountRootfs := spec.Annotations[annotMountRootfs] + blkDev := spec.Annotations[annotBlkDev] uniklog.WithFields(logrus.Fields{ "unikernelType": tryDecode(unikernelType), "unikernelVersion": tryDecode(unikernelVersion), @@ -129,6 +132,7 @@ func getConfigFromSpec(spec *specs.Spec) *UnikernelConfig { "block": tryDecode(block), "blkMntPoint": tryDecode(blkMntPoint), "mountRootfs": tryDecode(MountRootfs), + "blkDev": tryDecode(blkDev), }).WithField("source", "spec").Debug("urunc annotations") return &UnikernelConfig{ @@ -141,6 +145,7 @@ func getConfigFromSpec(spec *specs.Spec) *UnikernelConfig { Block: block, BlkMntPoint: blkMntPoint, MountRootfs: MountRootfs, + BlkDev: blkDev, } } @@ -180,6 +185,7 @@ func getConfigFromJSON(jsonFilePath string) (*UnikernelConfig, error) { "block": tryDecode(conf.Block), "blkMntPoint": tryDecode(conf.BlkMntPoint), "mountRootfs": tryDecode(conf.MountRootfs), + "blkDev": tryDecode(conf.BlkDev), }).WithField("source", uruncJSONFilename).Debug("urunc annotations") return &conf, nil @@ -250,6 +256,12 @@ func (c *UnikernelConfig) decode() error { } c.MountRootfs = string(decoded) + decoded, err = base64.StdEncoding.DecodeString(c.BlkDev) + if err != nil { + return fmt.Errorf("failed to decode blkDev: %v", err) + } + c.BlkDev = string(decoded) + return nil } @@ -283,6 +295,9 @@ func (c *UnikernelConfig) Map() map[string]string { if c.MountRootfs != "" { myMap[annotMountRootfs] = c.MountRootfs } + if c.BlkDev != "" { + myMap[annotBlkDev] = c.BlkDev + } return myMap } diff --git a/pkg/unikontainers/config_test.go b/pkg/unikontainers/config_test.go index 5579122f3..97410f9af 100644 --- a/pkg/unikontainers/config_test.go +++ b/pkg/unikontainers/config_test.go @@ -38,6 +38,7 @@ func TestGetConfigFromSpec(t *testing.T) { annotBlock: "block1", annotBlockMntPoint: "point1", annotMountRootfs: "true", + annotBlkDev: "mydisk", }, } @@ -50,6 +51,7 @@ func TestGetConfigFromSpec(t *testing.T) { Block: "block1", BlkMntPoint: "point1", MountRootfs: "true", + BlkDev: "mydisk", } config := getConfigFromSpec(spec) @@ -239,6 +241,7 @@ func TestMap(t *testing.T) { Block: "block_value", BlkMntPoint: "point_value", MountRootfs: "false", + BlkDev: "blkdev_value", } expectedMap := map[string]string{ annotCmdLine: "cmd_value", @@ -249,6 +252,7 @@ func TestMap(t *testing.T) { annotBlock: "block_value", annotBlockMntPoint: "point_value", annotMountRootfs: "false", + annotBlkDev: "blkdev_value", } resultMap := config.Map() assert.Equal(t, expectedMap, resultMap) diff --git a/pkg/unikontainers/types/types.go b/pkg/unikontainers/types/types.go index c6388e2cc..fc54e93c9 100644 --- a/pkg/unikontainers/types/types.go +++ b/pkg/unikontainers/types/types.go @@ -86,6 +86,7 @@ type UnikernelParams struct { Monitor string // The monitor where guest will execute Version string // The version of the unikernel InitrdPath string // The path to the initrd of the unikernel + BlkDevName string // The name of the guest block device declared at build time Net NetDevParams Block []BlockDevParams Rootfs RootfsParams // Information about rootfs diff --git a/pkg/unikontainers/unikernels/mirage.go b/pkg/unikontainers/unikernels/mirage.go index 17ad02389..738bf3b97 100644 --- a/pkg/unikontainers/unikernels/mirage.go +++ b/pkg/unikontainers/unikernels/mirage.go @@ -24,10 +24,11 @@ import ( const MirageUnikernel string = "mirage" type Mirage struct { - Command string - Monitor string - Net MirageNet - Block []MirageBlock + Command string + Monitor string + Net MirageNet + Block []MirageBlock + blkDevName string } type MirageNet struct { @@ -83,7 +84,7 @@ func (m *Mirage) MonitorBlockCli() []types.MonitorBlockArgs { // how MirageOS handles/configures them. return []types.MonitorBlockArgs{ { - ID: "storage", + ID: m.blkDevName, Path: m.Block[0].HostPath, }, } @@ -118,6 +119,12 @@ func (m *Mirage) Init(data types.UnikernelParams) error { m.Command = strings.Join(data.CmdLine, " ") m.Monitor = data.Monitor + if data.BlkDevName != "" { + m.blkDevName = data.BlkDevName + } else { + m.blkDevName = "storage" + } + return nil } diff --git a/pkg/unikontainers/unikernels/mirage_test.go b/pkg/unikontainers/unikernels/mirage_test.go index 6d749bb41..7a76c92da 100644 --- a/pkg/unikontainers/unikernels/mirage_test.go +++ b/pkg/unikontainers/unikernels/mirage_test.go @@ -73,3 +73,33 @@ func TestMirageInitSubnetMask(t *testing.T) { }) } } + +func TestMirageBlkDevName(t *testing.T) { + t.Run("uses block device name from annotation", func(t *testing.T) { + t.Parallel() + m := &Mirage{} + err := m.Init(types.UnikernelParams{ + Monitor: "hvt", + BlkDevName: "mydisk", + Block: []types.BlockDevParams{{Source: "/path/to/img"}}, + }) + assert.NoError(t, err) + args := m.MonitorBlockCli() + assert.Len(t, args, 1) + assert.Equal(t, "mydisk", args[0].ID) + assert.Equal(t, "/path/to/img", args[0].Path) + }) + + t.Run("falls back to storage when annotation is absent", func(t *testing.T) { + t.Parallel() + m := &Mirage{} + err := m.Init(types.UnikernelParams{ + Monitor: "hvt", + Block: []types.BlockDevParams{{Source: "/path/to/img"}}, + }) + assert.NoError(t, err) + args := m.MonitorBlockCli() + assert.Len(t, args, 1) + assert.Equal(t, "storage", args[0].ID) + }) +} diff --git a/pkg/unikontainers/unikontainers.go b/pkg/unikontainers/unikontainers.go index fc297f937..6dc4b9f03 100644 --- a/pkg/unikontainers/unikontainers.go +++ b/pkg/unikontainers/unikontainers.go @@ -391,11 +391,12 @@ func (u *Unikontainer) Exec(metrics m.Writer) error { // UnikernelParams // populate unikernel params unikernelParams := types.UnikernelParams{ - CmdLine: u.Spec.Process.Args, - EnvVars: u.Spec.Process.Env, - Monitor: vmmType, - Version: unikernelVersion, - ProcConf: procAttrs, + CmdLine: u.Spec.Process.Args, + EnvVars: u.Spec.Process.Env, + Monitor: vmmType, + Version: unikernelVersion, + ProcConf: procAttrs, + BlkDevName: u.State.Annotations[annotBlkDev], } if len(unikernelParams.CmdLine) == 0 { unikernelParams.CmdLine = strings.Fields(u.State.Annotations[annotCmdLine]) From b5ac803850d3ceb23d991f10c1130ff2486724e5 Mon Sep 17 00:00:00 2001 From: viju Date: Mon, 8 Jun 2026 04:59:18 +0530 Subject: [PATCH 2/2] refactor: apply solo5 prefix to block device go identifiers Ref: #315 Signed-off-by: viju --- pkg/unikontainers/config.go | 20 ++++++++++---------- pkg/unikontainers/config_test.go | 8 ++++---- pkg/unikontainers/types/types.go | 11 ++++++----- pkg/unikontainers/unikernels/mirage.go | 18 +++++++++--------- pkg/unikontainers/unikernels/mirage_test.go | 8 ++++---- pkg/unikontainers/unikontainers.go | 12 ++++++------ 6 files changed, 39 insertions(+), 38 deletions(-) diff --git a/pkg/unikontainers/config.go b/pkg/unikontainers/config.go index 350a54648..e0abba930 100644 --- a/pkg/unikontainers/config.go +++ b/pkg/unikontainers/config.go @@ -45,7 +45,7 @@ const ( annotBlock = "com.urunc.unikernel.block" annotBlockMntPoint = "com.urunc.unikernel.blkMntPoint" annotMountRootfs = "com.urunc.unikernel.mountRootfs" - annotBlkDev = "com.urunc.unikernel.blkDev" + annotSolo5BlkDev = "com.urunc.unikernel.blkDev" ) // A UnikernelConfig struct holds the info provided by bima image on how to execute our unikernel @@ -59,7 +59,7 @@ type UnikernelConfig struct { Block string `json:"com.urunc.unikernel.block,omitempty"` BlkMntPoint string `json:"com.urunc.unikernel.blkMntPoint,omitempty"` MountRootfs string `json:"com.urunc.unikernel.mountRootfs"` - BlkDev string `json:"com.urunc.unikernel.blkDev,omitempty"` + Solo5BlkDev string `json:"com.urunc.unikernel.blkDev,omitempty"` } // validate checks if the mandatory configuration fields are present. @@ -121,7 +121,7 @@ func getConfigFromSpec(spec *specs.Spec) *UnikernelConfig { block := spec.Annotations[annotBlock] blkMntPoint := spec.Annotations[annotBlockMntPoint] MountRootfs := spec.Annotations[annotMountRootfs] - blkDev := spec.Annotations[annotBlkDev] + solo5BlkDev := spec.Annotations[annotSolo5BlkDev] uniklog.WithFields(logrus.Fields{ "unikernelType": tryDecode(unikernelType), "unikernelVersion": tryDecode(unikernelVersion), @@ -132,7 +132,7 @@ func getConfigFromSpec(spec *specs.Spec) *UnikernelConfig { "block": tryDecode(block), "blkMntPoint": tryDecode(blkMntPoint), "mountRootfs": tryDecode(MountRootfs), - "blkDev": tryDecode(blkDev), + "solo5BlkDev": tryDecode(solo5BlkDev), }).WithField("source", "spec").Debug("urunc annotations") return &UnikernelConfig{ @@ -145,7 +145,7 @@ func getConfigFromSpec(spec *specs.Spec) *UnikernelConfig { Block: block, BlkMntPoint: blkMntPoint, MountRootfs: MountRootfs, - BlkDev: blkDev, + Solo5BlkDev: solo5BlkDev, } } @@ -185,7 +185,7 @@ func getConfigFromJSON(jsonFilePath string) (*UnikernelConfig, error) { "block": tryDecode(conf.Block), "blkMntPoint": tryDecode(conf.BlkMntPoint), "mountRootfs": tryDecode(conf.MountRootfs), - "blkDev": tryDecode(conf.BlkDev), + "solo5BlkDev": tryDecode(conf.Solo5BlkDev), }).WithField("source", uruncJSONFilename).Debug("urunc annotations") return &conf, nil @@ -256,11 +256,11 @@ func (c *UnikernelConfig) decode() error { } c.MountRootfs = string(decoded) - decoded, err = base64.StdEncoding.DecodeString(c.BlkDev) + decoded, err = base64.StdEncoding.DecodeString(c.Solo5BlkDev) if err != nil { return fmt.Errorf("failed to decode blkDev: %v", err) } - c.BlkDev = string(decoded) + c.Solo5BlkDev = string(decoded) return nil } @@ -295,8 +295,8 @@ func (c *UnikernelConfig) Map() map[string]string { if c.MountRootfs != "" { myMap[annotMountRootfs] = c.MountRootfs } - if c.BlkDev != "" { - myMap[annotBlkDev] = c.BlkDev + if c.Solo5BlkDev != "" { + myMap[annotSolo5BlkDev] = c.Solo5BlkDev } return myMap diff --git a/pkg/unikontainers/config_test.go b/pkg/unikontainers/config_test.go index 97410f9af..ebfdba9cd 100644 --- a/pkg/unikontainers/config_test.go +++ b/pkg/unikontainers/config_test.go @@ -38,7 +38,7 @@ func TestGetConfigFromSpec(t *testing.T) { annotBlock: "block1", annotBlockMntPoint: "point1", annotMountRootfs: "true", - annotBlkDev: "mydisk", + annotSolo5BlkDev: "mydisk", }, } @@ -51,7 +51,7 @@ func TestGetConfigFromSpec(t *testing.T) { Block: "block1", BlkMntPoint: "point1", MountRootfs: "true", - BlkDev: "mydisk", + Solo5BlkDev: "mydisk", } config := getConfigFromSpec(spec) @@ -241,7 +241,7 @@ func TestMap(t *testing.T) { Block: "block_value", BlkMntPoint: "point_value", MountRootfs: "false", - BlkDev: "blkdev_value", + Solo5BlkDev: "blkdev_value", } expectedMap := map[string]string{ annotCmdLine: "cmd_value", @@ -252,7 +252,7 @@ func TestMap(t *testing.T) { annotBlock: "block_value", annotBlockMntPoint: "point_value", annotMountRootfs: "false", - annotBlkDev: "blkdev_value", + annotSolo5BlkDev: "blkdev_value", } resultMap := config.Map() assert.Equal(t, expectedMap, resultMap) diff --git a/pkg/unikontainers/types/types.go b/pkg/unikontainers/types/types.go index fc54e93c9..8d6642d3d 100644 --- a/pkg/unikontainers/types/types.go +++ b/pkg/unikontainers/types/types.go @@ -86,11 +86,12 @@ type UnikernelParams struct { Monitor string // The monitor where guest will execute Version string // The version of the unikernel InitrdPath string // The path to the initrd of the unikernel - BlkDevName string // The name of the guest block device declared at build time - Net NetDevParams - Block []BlockDevParams - Rootfs RootfsParams // Information about rootfs - ProcConf ProcessConfig // Information for the process execution inside the guest + // Solo5BlkDevName is the Solo5 block device name declared at build time + Solo5BlkDevName string + Net NetDevParams + Block []BlockDevParams + Rootfs RootfsParams // Information about rootfs + ProcConf ProcessConfig // Information for the process execution inside the guest } // ExecArgs holds the data required by Execve to start the VMM diff --git a/pkg/unikontainers/unikernels/mirage.go b/pkg/unikontainers/unikernels/mirage.go index 738bf3b97..567f279e2 100644 --- a/pkg/unikontainers/unikernels/mirage.go +++ b/pkg/unikontainers/unikernels/mirage.go @@ -24,11 +24,11 @@ import ( const MirageUnikernel string = "mirage" type Mirage struct { - Command string - Monitor string - Net MirageNet - Block []MirageBlock - blkDevName string + Command string + Monitor string + Net MirageNet + Block []MirageBlock + solo5BlkDevName string } type MirageNet struct { @@ -84,7 +84,7 @@ func (m *Mirage) MonitorBlockCli() []types.MonitorBlockArgs { // how MirageOS handles/configures them. return []types.MonitorBlockArgs{ { - ID: m.blkDevName, + ID: m.solo5BlkDevName, Path: m.Block[0].HostPath, }, } @@ -119,10 +119,10 @@ func (m *Mirage) Init(data types.UnikernelParams) error { m.Command = strings.Join(data.CmdLine, " ") m.Monitor = data.Monitor - if data.BlkDevName != "" { - m.blkDevName = data.BlkDevName + if data.Solo5BlkDevName != "" { + m.solo5BlkDevName = data.Solo5BlkDevName } else { - m.blkDevName = "storage" + m.solo5BlkDevName = "storage" } return nil diff --git a/pkg/unikontainers/unikernels/mirage_test.go b/pkg/unikontainers/unikernels/mirage_test.go index 7a76c92da..9eb311f72 100644 --- a/pkg/unikontainers/unikernels/mirage_test.go +++ b/pkg/unikontainers/unikernels/mirage_test.go @@ -74,14 +74,14 @@ func TestMirageInitSubnetMask(t *testing.T) { } } -func TestMirageBlkDevName(t *testing.T) { +func TestMirageSolo5BlkDevName(t *testing.T) { t.Run("uses block device name from annotation", func(t *testing.T) { t.Parallel() m := &Mirage{} err := m.Init(types.UnikernelParams{ - Monitor: "hvt", - BlkDevName: "mydisk", - Block: []types.BlockDevParams{{Source: "/path/to/img"}}, + Monitor: "hvt", + Solo5BlkDevName: "mydisk", + Block: []types.BlockDevParams{{Source: "/path/to/img"}}, }) assert.NoError(t, err) args := m.MonitorBlockCli() diff --git a/pkg/unikontainers/unikontainers.go b/pkg/unikontainers/unikontainers.go index 6dc4b9f03..c1a9e6a8d 100644 --- a/pkg/unikontainers/unikontainers.go +++ b/pkg/unikontainers/unikontainers.go @@ -391,12 +391,12 @@ func (u *Unikontainer) Exec(metrics m.Writer) error { // UnikernelParams // populate unikernel params unikernelParams := types.UnikernelParams{ - CmdLine: u.Spec.Process.Args, - EnvVars: u.Spec.Process.Env, - Monitor: vmmType, - Version: unikernelVersion, - ProcConf: procAttrs, - BlkDevName: u.State.Annotations[annotBlkDev], + CmdLine: u.Spec.Process.Args, + EnvVars: u.Spec.Process.Env, + Monitor: vmmType, + Version: unikernelVersion, + ProcConf: procAttrs, + Solo5BlkDevName: u.State.Annotations[annotSolo5BlkDev], } if len(unikernelParams.CmdLine) == 0 { unikernelParams.CmdLine = strings.Fields(u.State.Annotations[annotCmdLine])