From 4f57b65147780ea5e3c8d05685991617f41d59cd Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Thu, 22 Mar 2018 10:55:04 +0800 Subject: [PATCH] hypervisor: add initrd image support If an initrd image is configured in HypervisorConfig or passed in by annotations, append it to qemu command line arguments. Fixes: #97 Signed-off-by: Peng Tao --- virtcontainers/asset.go | 5 ++++ virtcontainers/hypervisor.go | 20 +++++++++++-- virtcontainers/pkg/annotations/annotations.go | 6 ++++ virtcontainers/pkg/oci/utils.go | 1 + virtcontainers/pod.go | 11 +++++++- virtcontainers/qemu.go | 28 +++++++++++++------ virtcontainers/qemu_test.go | 1 + virtcontainers/virtcontainers_test.go | 3 ++ 8 files changed, 63 insertions(+), 12 deletions(-) diff --git a/virtcontainers/asset.go b/virtcontainers/asset.go index 8db6b7106..6b223c47a 100644 --- a/virtcontainers/asset.go +++ b/virtcontainers/asset.go @@ -34,6 +34,8 @@ func (t assetType) annotations() (string, string, error) { return annotations.KernelPath, annotations.KernelHash, nil case imageAsset: return annotations.ImagePath, annotations.ImageHash, nil + case initrdAsset: + return annotations.InitrdPath, annotations.InitrdHash, nil case hypervisorAsset: return annotations.HypervisorPath, annotations.HypervisorHash, nil case firmwareAsset: @@ -46,6 +48,7 @@ func (t assetType) annotations() (string, string, error) { const ( kernelAsset assetType = "kernel" imageAsset assetType = "image" + initrdAsset assetType = "initrd" hypervisorAsset assetType = "hypervisor" firmwareAsset assetType = "firmware" ) @@ -66,6 +69,8 @@ func (a *asset) valid() bool { return true case imageAsset: return true + case initrdAsset: + return true case hypervisorAsset: return true case firmwareAsset: diff --git a/virtcontainers/hypervisor.go b/virtcontainers/hypervisor.go index ad867bc2e..cfbd885fa 100644 --- a/virtcontainers/hypervisor.go +++ b/virtcontainers/hypervisor.go @@ -157,6 +157,10 @@ type HypervisorConfig struct { // ImagePath is the guest image host path. ImagePath string + // InitrdPath is the guest initrd image host path. + // ImagePath and InitrdPath cannot be set at the same time. + InitrdPath string + // FirmwarePath is the bios host path FirmwarePath string @@ -225,8 +229,8 @@ func (conf *HypervisorConfig) valid() (bool, error) { return false, fmt.Errorf("Missing kernel path") } - if conf.ImagePath == "" { - return false, fmt.Errorf("Missing image path") + if conf.ImagePath == "" && conf.InitrdPath == "" { + return false, fmt.Errorf("Missing image and initrd path") } if conf.DefaultVCPUs == 0 { @@ -299,6 +303,8 @@ func (conf *HypervisorConfig) assetPath(t assetType) (string, error) { return conf.KernelPath, nil case imageAsset: return conf.ImagePath, nil + case initrdAsset: + return conf.InitrdPath, nil case hypervisorAsset: return conf.HypervisorPath, nil case firmwareAsset: @@ -337,6 +343,16 @@ func (conf *HypervisorConfig) CustomImageAsset() bool { return conf.isCustomAsset(imageAsset) } +// InitrdAssetPath returns the guest initrd path +func (conf *HypervisorConfig) InitrdAssetPath() (string, error) { + return conf.assetPath(initrdAsset) +} + +// CustomInitrdAsset returns true if the initrd asset is a custom one, false otherwise. +func (conf *HypervisorConfig) CustomInitrdAsset() bool { + return conf.isCustomAsset(initrdAsset) +} + // HypervisorAssetPath returns the VM hypervisor path func (conf *HypervisorConfig) HypervisorAssetPath() (string, error) { return conf.assetPath(hypervisorAsset) diff --git a/virtcontainers/pkg/annotations/annotations.go b/virtcontainers/pkg/annotations/annotations.go index 8fb3b6477..27baea8dd 100644 --- a/virtcontainers/pkg/annotations/annotations.go +++ b/virtcontainers/pkg/annotations/annotations.go @@ -25,6 +25,9 @@ const ( // ImagePath is a pod annotation for passing a per container path pointing at the guest image that will run in the container VM. ImagePath = vcAnnotationsPrefix + "ImagePath" + // InitrdPath is a pod annotation for passing a per container path pointing at the guest initrd image that will run in the container VM. + InitrdPath = vcAnnotationsPrefix + "InitrdPath" + // HypervisorPath is a pod annotation for passing a per container path pointing at the hypervisor that will run the container VM. HypervisorPath = vcAnnotationsPrefix + "HypervisorPath" @@ -37,6 +40,9 @@ const ( // ImageHash is an pod annotation for passing a container guest image SHA-512 hash value. ImageHash = vcAnnotationsPrefix + "ImageHash" + // InitrdHash is an pod annotation for passing a container guest initrd SHA-512 hash value. + InitrdHash = vcAnnotationsPrefix + "InitrdHash" + // HypervisorHash is an pod annotation for passing a container hypervisor binary SHA-512 hash value. HypervisorHash = vcAnnotationsPrefix + "HypervisorHash" diff --git a/virtcontainers/pkg/oci/utils.go b/virtcontainers/pkg/oci/utils.go index 01cad1721..afb161945 100644 --- a/virtcontainers/pkg/oci/utils.go +++ b/virtcontainers/pkg/oci/utils.go @@ -447,6 +447,7 @@ func addAssetAnnotations(ocispec CompatOCISpec, config *vc.PodConfig) { assetAnnotations := []string{ vcAnnotations.KernelPath, vcAnnotations.ImagePath, + vcAnnotations.InitrdPath, vcAnnotations.KernelHash, vcAnnotations.ImageHash, vcAnnotations.AssetHashType, diff --git a/virtcontainers/pod.go b/virtcontainers/pod.go index e0779477b..5d0d6d37b 100644 --- a/virtcontainers/pod.go +++ b/virtcontainers/pod.go @@ -551,7 +551,16 @@ func createAssets(podConfig *PodConfig) error { return err } - for _, a := range []*asset{kernel, image} { + initrd, err := newAsset(podConfig, initrdAsset) + if err != nil { + return err + } + + if image != nil && initrd != nil { + return fmt.Errorf("%s and %s cannot be both set", imageAsset, initrdAsset) + } + + for _, a := range []*asset{kernel, image, initrd} { if err := podConfig.HypervisorConfig.addCustomAsset(a); err != nil { return err } diff --git a/virtcontainers/qemu.go b/virtcontainers/qemu.go index c7025230a..369ff0c1f 100644 --- a/virtcontainers/qemu.go +++ b/virtcontainers/qemu.go @@ -284,9 +284,15 @@ func (q *qemu) createPod(podConfig PodConfig) error { return err } + initrdPath, err := q.config.InitrdAssetPath() + if err != nil { + return err + } + kernel := govmmQemu.Kernel{ - Path: kernelPath, - Params: q.kernelParameters(), + Path: kernelPath, + InitrdPath: initrdPath, + Params: q.kernelParameters(), } rtc := govmmQemu.RTC{ @@ -336,14 +342,18 @@ func (q *qemu) createPod(podConfig PodConfig) error { devices = q.arch.append9PVolumes(devices, podConfig.Volumes) devices = q.arch.appendConsole(devices, q.getPodConsole(podConfig.ID)) - imagePath, err := q.config.ImageAssetPath() - if err != nil { - return err - } + if initrdPath == "" { + imagePath, err := q.config.ImageAssetPath() + if err != nil { + return err + } - devices, err = q.arch.appendImage(devices, imagePath) - if err != nil { - return err + if imagePath != "" { + devices, err = q.arch.appendImage(devices, imagePath) + if err != nil { + return err + } + } } if q.config.BlockDeviceDriver == VirtioBlock { diff --git a/virtcontainers/qemu_test.go b/virtcontainers/qemu_test.go index 6693ba056..dac4dd4bb 100644 --- a/virtcontainers/qemu_test.go +++ b/virtcontainers/qemu_test.go @@ -32,6 +32,7 @@ func newQemuConfig() HypervisorConfig { return HypervisorConfig{ KernelPath: testQemuKernelPath, ImagePath: testQemuImagePath, + InitrdPath: testQemuInitrdPath, HypervisorPath: testQemuPath, DefaultVCPUs: defaultVCPUs, DefaultMemSz: defaultMemSzMiB, diff --git a/virtcontainers/virtcontainers_test.go b/virtcontainers/virtcontainers_test.go index 552ba44e8..ce98a023c 100644 --- a/virtcontainers/virtcontainers_test.go +++ b/virtcontainers/virtcontainers_test.go @@ -30,6 +30,7 @@ import ( const testPodID = "7f49d00d-1995-4156-8c79-5f5ab24ce138" const testContainerID = "containerID" const testKernel = "kernel" +const testInitrd = "initrd" const testImage = "image" const testHypervisor = "hypervisor" const testBundle = "bundle" @@ -45,6 +46,7 @@ var podDirLock = "" var podFileState = "" var podFileLock = "" var testQemuKernelPath = "" +var testQemuInitrdPath = "" var testQemuImagePath = "" var testQemuPath = "" var testHyperstartCtlSocket = "" @@ -135,6 +137,7 @@ func TestMain(m *testing.M) { podFileLock = filepath.Join(runStoragePath, testPodID, lockFileName) testQemuKernelPath = filepath.Join(testDir, testKernel) + testQemuInitrdPath = filepath.Join(testDir, testInitrd) testQemuImagePath = filepath.Join(testDir, testImage) testQemuPath = filepath.Join(testDir, testHypervisor)