From 1009efdc06b09bcb1f6de83f369a92d903304024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Hor=C3=A1=C4=8Dek?= Date: Fri, 29 Jun 2018 16:31:50 +0200 Subject: [PATCH] hooks: functional tests --- .gitignore | 1 - ...consumer.yml => vm-with-sidecar-hook.yaml} | 15 +- cmd/example-hook-sidecar/Dockerfile | 2 +- cmd/example-hook-sidecar/README.md | 5 +- cmd/example-hook-sidecar/smbios.go | 2 +- cmd/virt-launcher/virt-launcher.go | 5 +- glide.yaml | 2 +- pkg/hooks/info/api.proto | 2 +- pkg/hooks/manager.go | 61 +++---- pkg/hooks/v1alpha1/api.proto | 2 +- pkg/virt-controller/services/template.go | 8 +- pkg/virt-controller/services/template_test.go | 8 +- tests/vm_hook_sidecar_test.go | 152 ++++++++++++++++++ tools/vms-generator/vms-generator.go | 54 ++++--- 14 files changed, 245 insertions(+), 74 deletions(-) rename cluster/examples/{hook-sidecar-consumer.yml => vm-with-sidecar-hook.yaml} (79%) create mode 100644 tests/vm_hook_sidecar_test.go diff --git a/.gitignore b/.gitignore index a598aa09a3d9..c5c684f0e146 100644 --- a/.gitignore +++ b/.gitignore @@ -27,5 +27,4 @@ _out vendor/**/*_test.go **/polarion.xml tools/manifest-templator/manifest-templator -.coverprofile tools/vms-generator/vms-generator diff --git a/cluster/examples/hook-sidecar-consumer.yml b/cluster/examples/vm-with-sidecar-hook.yaml similarity index 79% rename from cluster/examples/hook-sidecar-consumer.yml rename to cluster/examples/vm-with-sidecar-hook.yaml index 75efb68d01ae..959466dffca5 100644 --- a/cluster/examples/hook-sidecar-consumer.yml +++ b/cluster/examples/vm-with-sidecar-hook.yaml @@ -1,16 +1,13 @@ -status: {} apiVersion: kubevirt.io/v1alpha1 kind: VirtualMachine metadata: - creationTimestamp: null - labels: - special: vm-hook-sidecar-consumer - name: vm-hook-sidecar-consumer annotations: - # Request the hook sidecar hooks.kubevirt.io/hookSidecars: '[{"image": "registry:5000/kubevirt/example-hook-sidecar:devel"}]' - # Overwrite base board manufacturer name - smbios.vm.kubevirt.io/baseBoardManufacturer: "Radical Edward" + smbios.vm.kubevirt.io/baseBoardManufacturer: Radical Edward + creationTimestamp: null + labels: + special: vm-with-sidecar-hook + name: vm-with-sidecar-hook spec: domain: devices: @@ -39,4 +36,4 @@ spec: password: fedora chpasswd: { expire: False } name: cloudinitvolume -status: {} \ No newline at end of file +status: {} diff --git a/cmd/example-hook-sidecar/Dockerfile b/cmd/example-hook-sidecar/Dockerfile index ff94fcb46fe0..7f8636b15db3 100644 --- a/cmd/example-hook-sidecar/Dockerfile +++ b/cmd/example-hook-sidecar/Dockerfile @@ -4,4 +4,4 @@ MAINTAINER "The KubeVirt Project" COPY example-hook-sidecar /example-hook-sidecar -ENTRYPOINT [ "/example-hook-sidecar" ] \ No newline at end of file +ENTRYPOINT [ "/example-hook-sidecar" ] diff --git a/cmd/example-hook-sidecar/README.md b/cmd/example-hook-sidecar/README.md index 398a77d5190c..c7aef50ceaf0 100644 --- a/cmd/example-hook-sidecar/README.md +++ b/cmd/example-hook-sidecar/README.md @@ -14,10 +14,10 @@ annotations: ```shell # Create a VM requesting the hook sidecar -cluster/kubectl.sh create -f cluster/examples/hook-sidecar-consumer.yml +cluster/kubectl.sh create -f cluster/examples/hook-with-sidecar-hook.yml # Once the VM is ready, connect to its display and login using name and password "fedora" -cluster/virtctl.sh vnc vm-hook-sidecar-consumer +cluster/virtctl.sh vnc vm-with-sidecar-hook # Install dmidecode sudo dnf install -y dmidecode @@ -25,4 +25,3 @@ sudo dnf install -y dmidecode # Check whether the base board manufacturer value was successfully overwritten sudo dmidecode -s baseboard-manufacturer ``` - diff --git a/cmd/example-hook-sidecar/smbios.go b/cmd/example-hook-sidecar/smbios.go index 147a181985db..a2e81a60883f 100644 --- a/cmd/example-hook-sidecar/smbios.go +++ b/cmd/example-hook-sidecar/smbios.go @@ -41,7 +41,7 @@ func (s infoServer) Info(ctx context.Context, params *hooksInfo.InfoParams) (*ho type v1alpha1Server struct{} func (s v1alpha1Server) OnDefineDomain(ctx context.Context, params *hooksV1alpha1.OnDefineDomainParams) (*hooksV1alpha1.OnDefineDomainResult, error) { - log.Log.Info("Hook's OnDefinedComain callback method has been called") + log.Log.Info("Hook's OnDefineDomain callback method has been called") vmJSON := params.GetVm() vmSpec := vmSchema.VirtualMachine{} diff --git a/cmd/virt-launcher/virt-launcher.go b/cmd/virt-launcher/virt-launcher.go index a01fcb9ead5e..2f5ed5b7cf2c 100644 --- a/cmd/virt-launcher/virt-launcher.go +++ b/cmd/virt-launcher/virt-launcher.go @@ -50,6 +50,7 @@ import ( const defaultStartTimeout = 3 * time.Minute const defaultWatchdogInterval = 5 * time.Second +const hookSidecarsCollectTimeout = 10 * time.Second func markReady(readinessFile string) { f, err := os.OpenFile(readinessFile, os.O_RDONLY|os.O_CREATE, 0666) @@ -255,7 +256,7 @@ func main() { readinessFile := flag.String("readiness-file", "/tmp/health", "Pod looks for this file to determine when virt-launcher is initialized") gracePeriodSeconds := flag.Int("grace-period-seconds", 30, "Grace period to observe before sending SIGTERM to vm process") useEmulation := flag.Bool("use-emulation", false, "Use software emulation") - requestedHooks := flag.Uint("requested-hooks", 0, "Number of requested hooks, virt-launcher will wait for all of them to become available") + hookSidecars := flag.Uint("hook-sidecars", 0, "Number of requested hook sidecars, virt-launcher will wait for all of them to become available") // set new default verbosity, was set to 0 by glog flag.Set("v", "2") @@ -267,7 +268,7 @@ func main() { // Block until all requested hookSidecars are ready hookManager := hooks.GetManager() - err := hookManager.Collect(*requestedHooks) + err := hookManager.Collect(*hookSidecars, hookSidecarsCollectTimeout) if err != nil { panic(err) } diff --git a/glide.yaml b/glide.yaml index c1ba42107993..95875831cec8 100644 --- a/glide.yaml +++ b/glide.yaml @@ -63,7 +63,7 @@ import: - package: github.com/ant31/crd-validation version: eabcf70a1bd73e9296fa0c5f57de604689200a1b - package: kubevirt.io/qe-tools - version: v0.1.1 + version: 13fc8573324cd2af42c88043b5a7c6e03bf39f95 repo: https://github.com/kubevirt/qe-tools.git - package: github.com/golang/protobuf subpackages: diff --git a/pkg/hooks/info/api.proto b/pkg/hooks/info/api.proto index 49b26a1a1cda..feb48ab20a95 100644 --- a/pkg/hooks/info/api.proto +++ b/pkg/hooks/info/api.proto @@ -22,4 +22,4 @@ message HookPoint { string name = 1; // priority is used to sort hooks prior to their execution (second key is the name) int32 priority = 2; -} \ No newline at end of file +} diff --git a/pkg/hooks/manager.go b/pkg/hooks/manager.go index ff7c2cebfb63..6e8ccd269078 100644 --- a/pkg/hooks/manager.go +++ b/pkg/hooks/manager.go @@ -32,19 +32,18 @@ var manager *Manager var once sync.Once type Manager struct { - collected bool callbacksPerHookPoint map[string][]*callackClient } func GetManager() *Manager { once.Do(func() { - manager = &Manager{collected: false} + manager = &Manager{callbacksPerHookPoint: make(map[string][]*callackClient)} }) return manager } -func (m *Manager) Collect(numberOfRequestedHookSidecars uint) error { - callbacksPerHookPoint, err := collectSideCarSockets(numberOfRequestedHookSidecars) +func (m *Manager) Collect(numberOfRequestedHookSidecars uint, timeout time.Duration) error { + callbacksPerHookPoint, err := collectSideCarSockets(numberOfRequestedHookSidecars, timeout) if err != nil { return err } @@ -53,16 +52,18 @@ func (m *Manager) Collect(numberOfRequestedHookSidecars uint) error { sortCallbacksPerHookPoint(callbacksPerHookPoint) log.Log.Infof("Sorted all collected sidecar sockets per hook point based on their priority and name: %v", callbacksPerHookPoint) - m.collected = true m.callbacksPerHookPoint = callbacksPerHookPoint return nil } -func collectSideCarSockets(numberOfRequestedHookSidecars uint) (map[string][]*callackClient, error) { +// TODO: Handle sockets in parallel, when a socket appears, run a goroutine trying to read Info from it +func collectSideCarSockets(numberOfRequestedHookSidecars uint, timeout time.Duration) (map[string][]*callackClient, error) { callbacksPerHookPoint := make(map[string][]*callackClient) processedSockets := make(map[string]bool) + timeoutCh := time.After(timeout) + for uint(len(processedSockets)) < numberOfRequestedHookSidecars { sockets, err := ioutil.ReadDir(HookSocketsSharedDirectory) if err != nil { @@ -70,24 +71,29 @@ func collectSideCarSockets(numberOfRequestedHookSidecars uint) (map[string][]*ca } for _, socket := range sockets { - if _, processed := processedSockets[socket.Name()]; processed { - continue - } + select { + case <-timeoutCh: + return nil, fmt.Errorf("Failed to collect all expected sidecar hook sockets within given timeout") + default: + if _, processed := processedSockets[socket.Name()]; processed { + continue + } - callackClient, notReady, err := processSideCarSocket(HookSocketsSharedDirectory + "/" + socket.Name()) - if notReady { - log.Log.Info("Sidecar server might not be ready yet, retrying in the next iteration") - continue - } else if err != nil { - log.Log.Reason(err).Infof("Failed to process sidecar socket: %s", socket.Name()) - return nil, err - } + callackClient, notReady, err := processSideCarSocket(HookSocketsSharedDirectory + "/" + socket.Name()) + if notReady { + log.Log.Info("Sidecar server might not be ready yet, retrying in the next iteration") + continue + } else if err != nil { + log.Log.Reason(err).Infof("Failed to process sidecar socket: %s", socket.Name()) + return nil, err + } - for _, subsribedHookPoint := range callackClient.subsribedHookPoints { - callbacksPerHookPoint[subsribedHookPoint.GetName()] = append(callbacksPerHookPoint[subsribedHookPoint.GetName()], callackClient) - } + for _, subsribedHookPoint := range callackClient.subsribedHookPoints { + callbacksPerHookPoint[subsribedHookPoint.GetName()] = append(callbacksPerHookPoint[subsribedHookPoint.GetName()], callackClient) + } - processedSockets[socket.Name()] = true + processedSockets[socket.Name()] = true + } } time.Sleep(time.Second) @@ -105,7 +111,9 @@ func processSideCarSocket(socketPath string) (*callackClient, bool, error) { defer conn.Close() infoClient := hooksInfo.NewInfoClient(conn) - info, err := infoClient.Info(context.Background(), &hooksInfo.InfoParams{}) + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + info, err := infoClient.Info(ctx, &hooksInfo.InfoParams{}) if err != nil { return nil, false, err } @@ -141,10 +149,6 @@ func sortCallbacksPerHookPoint(callbacksPerHookPoint map[string][]*callackClient } func (m *Manager) OnDefineDomain(domainSpec *virtwrapApi.DomainSpec, vm *v1.VirtualMachine) (*virtwrapApi.DomainSpec, error) { - if !m.collected { - return nil, fmt.Errorf("Hook sidecars have not been collected yet") - } - if callbacks, found := m.callbacksPerHookPoint[hooksInfo.OnDefineDomainHookPointName]; found { for _, callback := range callbacks { if callback.Version == hooksV1alpha1.Version { @@ -166,7 +170,9 @@ func (m *Manager) OnDefineDomain(domainSpec *virtwrapApi.DomainSpec, vm *v1.Virt client := hooksV1alpha1.NewCallbacksClient(conn) - result, err := client.OnDefineDomain(context.Background(), &hooksV1alpha1.OnDefineDomainParams{ + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + result, err := client.OnDefineDomain(ctx, &hooksV1alpha1.OnDefineDomainParams{ DomainXML: domainSpecXML, Vm: vmJSON, }) @@ -198,5 +204,6 @@ func dialSocket(socketPath string) (*grpc.ClientConn, error) { grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) { return net.DialTimeout("unix", addr, timeout) }), + grpc.WithTimeout(time.Second), ) } diff --git a/pkg/hooks/v1alpha1/api.proto b/pkg/hooks/v1alpha1/api.proto index e7bdfde1b207..7f784a26d60a 100644 --- a/pkg/hooks/v1alpha1/api.proto +++ b/pkg/hooks/v1alpha1/api.proto @@ -16,4 +16,4 @@ message OnDefineDomainParams { message OnDefineDomainResult { // domainXML is processed libvirt domain specification bytes domainXML = 1; -} \ No newline at end of file +} diff --git a/pkg/virt-controller/services/template.go b/pkg/virt-controller/services/template.go index 218aa88aafb9..0652e424dc25 100644 --- a/pkg/virt-controller/services/template.go +++ b/pkg/virt-controller/services/template.go @@ -219,13 +219,13 @@ func (t *templateService) RenderLaunchManifest(vmi *v1.VirtualMachineInstance) ( if len(requestedHookSidecarList) != 0 { volumes = append(volumes, k8sv1.Volume{ - Name: "hooks", + Name: "hook-sidecar-sockets", VolumeSource: k8sv1.VolumeSource{ EmptyDir: &k8sv1.EmptyDirVolumeSource{}, }, }) volumesMounts = append(volumesMounts, k8sv1.VolumeMount{ - Name: "hooks", + Name: "hook-sidecar-sockets", MountPath: hooks.HookSocketsSharedDirectory, }) } @@ -237,7 +237,7 @@ func (t *templateService) RenderLaunchManifest(vmi *v1.VirtualMachineInstance) ( "--kubevirt-share-dir", t.virtShareDir, "--readiness-file", "/tmp/healthy", "--grace-period-seconds", strconv.Itoa(int(gracePeriodSeconds)), - "--requested-hooks", strconv.Itoa(len(requestedHookSidecarList)), + "--hook-sidecars", strconv.Itoa(len(requestedHookSidecarList)), } useEmulation, err := IsEmulationAllowed(t.store) @@ -337,7 +337,7 @@ func (t *templateService) RenderLaunchManifest(vmi *v1.VirtualMachineInstance) ( ImagePullPolicy: requestedHookSidecar.ImagePullPolicy, VolumeMounts: []k8sv1.VolumeMount{ k8sv1.VolumeMount{ - Name: "hooks", + Name: "hook-sidecar-sockets", MountPath: hooks.HookSocketsSharedDirectory, }, }, diff --git a/pkg/virt-controller/services/template_test.go b/pkg/virt-controller/services/template_test.go index da4cc978393d..55beada990f4 100644 --- a/pkg/virt-controller/services/template_test.go +++ b/pkg/virt-controller/services/template_test.go @@ -76,8 +76,8 @@ var _ = Describe("Template", func() { "--kubevirt-share-dir", "/var/run/kubevirt", "--readiness-file", "/tmp/healthy", "--grace-period-seconds", "45", - "--requested-hooks", "1"})) - Expect(pod.Spec.Containers[1].Name).To(Equal("hook-sidecar-some-image:v1")) + "--hook-sidecars", "1"})) + Expect(pod.Spec.Containers[1].Name).To(Equal("hook-sidecar-0")) Expect(pod.Spec.Containers[1].Image).To(Equal("some-image:v1")) Expect(pod.Spec.Containers[1].ImagePullPolicy).To(Equal(kubev1.PullPolicy("IfNotPresent"))) Expect(*pod.Spec.TerminationGracePeriodSeconds).To(Equal(int64(60))) @@ -119,8 +119,8 @@ var _ = Describe("Template", func() { "--kubevirt-share-dir", "/var/run/kubevirt", "--readiness-file", "/tmp/healthy", "--grace-period-seconds", "45", - "--requested-hooks", "1"})) - Expect(pod.Spec.Containers[1].Name).To(Equal("hook-sidecar-some-image:v1")) + "--hook-sidecars", "1"})) + Expect(pod.Spec.Containers[1].Name).To(Equal("hook-sidecar-0")) Expect(pod.Spec.Containers[1].Image).To(Equal("some-image:v1")) Expect(pod.Spec.Containers[1].ImagePullPolicy).To(Equal(kubev1.PullPolicy("IfNotPresent"))) Expect(pod.Spec.Containers[1].VolumeMounts[0].MountPath).To(Equal(hooks.HookSocketsSharedDirectory)) diff --git a/tests/vm_hook_sidecar_test.go b/tests/vm_hook_sidecar_test.go new file mode 100644 index 000000000000..10569a0b9bf7 --- /dev/null +++ b/tests/vm_hook_sidecar_test.go @@ -0,0 +1,152 @@ +/* + * This file is part of the KubeVirt project + * + * 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. + * + * Copyright 2018 Red Hat, Inc. + * + */ + +package tests_test + +import ( + "flag" + "fmt" + "time" + "strings" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + k8sv1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "kubevirt.io/kubevirt/pkg/api/v1" + "kubevirt.io/kubevirt/pkg/kubecli" + "kubevirt.io/kubevirt/tests" +) + +var _ = Describe("HookSidecars", func() { + + flag.Parse() + + virtClient, err := kubecli.GetKubevirtClient() + tests.PanicOnError(err) + + var vm *v1.VirtualMachine + + BeforeEach(func() { + tests.BeforeTestCleanup() + vm = tests.NewRandomVMWithEphemeralDisk(tests.RegistryDiskFor(tests.RegistryDiskAlpine)) + vm.ObjectMeta.Annotations = map[string]string{ + "hooks.kubevirt.io/hookSidecars": `[{"image": "registry:5000/kubevirt/example-hook-sidecar:devel"}]`, + "smbios.vm.kubevirt.io/baseBoardManufacturer": "Radical Edward", + } + }) + + Describe("VM definition", func() { + Context("with SM BIOS hook sidecar", func() { + It("should successfully start with hook sidecar annotation", func() { + By("Starting a VM") + vm, err = virtClient.VM(tests.NamespaceTestDefault).Create(vm) + Expect(err).ToNot(HaveOccurred()) + tests.WaitForSuccessfulVMStart(vm) + }, 300) + + It("should call Collect on the hook sidecar", func() { + By("Getting hook-sidecar logs") + vm, err = virtClient.VM(tests.NamespaceTestDefault).Create(vm) + Expect(err).ToNot(HaveOccurred()) + logs := func() string { return getHookSidecarLogs(virtClient, vm) } + tests.WaitForSuccessfulVMStart(vm) + Eventually(logs, + 11*time.Second, + 500*time.Millisecond). + Should(ContainSubstring("Hook's Info method has been called")) + }, 300) + + It("should call OnDefineDomain on the hook sidecar", func() { + By("Getting hook-sidecar logs") + vm, err = virtClient.VM(tests.NamespaceTestDefault).Create(vm) + Expect(err).ToNot(HaveOccurred()) + logs := func() string { return getHookSidecarLogs(virtClient, vm) } + tests.WaitForSuccessfulVMStart(vm) + Eventually(logs, + 11*time.Second, + 500*time.Millisecond). + Should(ContainSubstring("Hook's OnDefineDomain callback method has been called")) + }, 300) + + It("should update domain XML with SM BIOS properties", func() { + By("Reading domain XML using virsh") + tests.SkipIfNoKubectl() + vm, err = virtClient.VM(tests.NamespaceTestDefault).Create(vm) + tests.WaitForSuccessfulVMStart(vm) + domainXml := getVmDomainXml(virtClient, vm) + Expect(domainXml).Should(ContainSubstring("")) + Expect(domainXml).Should(ContainSubstring("")) + Expect(domainXml).Should(ContainSubstring("Radical Edward")) + }, 300) + }) + }) + +}) + +func getHookSidecarLogs(virtCli kubecli.KubevirtClient, vm *v1.VirtualMachine) string { + namespace := vm.GetObjectMeta().GetNamespace() + podName := getVmPodName(virtCli, vm) + + var tailLines int64 = 100 + logsRaw, err := virtCli.CoreV1(). + Pods(namespace). + GetLogs(podName, &k8sv1.PodLogOptions{ + TailLines: &tailLines, + Container: "hook-sidecar-0", + }). + DoRaw() + Expect(err).To(BeNil()) + + return string(logsRaw) +} + +func getVmDomainXml(virtCli kubecli.KubevirtClient, vm *v1.VirtualMachine) string { + podName := getVmPodName(virtCli, vm) + + vmNameListRaw, err := tests.RunKubectlCommand("exec", "-ti", "--namespace", vm.GetObjectMeta().GetNamespace(), podName, "--container", "compute", "--", "virsh", "list", "--name") + Expect(err).ToNot(HaveOccurred()) + + vmName := strings.Split(vmNameListRaw, "\n")[0] + vmDomainXML, err := tests.RunKubectlCommand("exec", "-ti", "--namespace", vm.GetObjectMeta().GetNamespace(), podName, "--container", "compute", "--", "virsh", "dumpxml", vmName) + Expect(err).ToNot(HaveOccurred()) + + return vmDomainXML +} + +func getVmPodName(virtCli kubecli.KubevirtClient, vm *v1.VirtualMachine) string { + namespace := vm.GetObjectMeta().GetNamespace() + domain := vm.GetObjectMeta().GetName() + labelSelector := fmt.Sprintf("kubevirt.io/domain in (%s)", domain) + + pods, err := virtCli.CoreV1().Pods(namespace).List(metav1.ListOptions{LabelSelector: labelSelector}) + Expect(err).ToNot(HaveOccurred()) + + podName := "" + for _, pod := range pods.Items { + if pod.ObjectMeta.DeletionTimestamp == nil { + podName = pod.ObjectMeta.Name + break + } + } + Expect(podName).ToNot(BeEmpty()) + + return podName +} diff --git a/tools/vms-generator/vms-generator.go b/tools/vms-generator/vms-generator.go index b028170fe8e7..fe8d06440acc 100644 --- a/tools/vms-generator/vms-generator.go +++ b/tools/vms-generator/vms-generator.go @@ -44,17 +44,18 @@ import ( ) const ( - vmiEphemeral = "vmi-ephemeral" - vmiFlavorSmall = "vmi-flavor-small" - vmiSata = "vmi-sata" - vmiFedora = "vmi-fedora" - vmiNoCloud = "vmi-nocloud" - vmiPVC = "vmi-pvc" - vmiWindows = "vmi-windows" - vmiSlirp = "vmi-slirp" - vmTemplateFedora = "vm-template-fedora" - vmTemplateRHEL7 = "vm-template-rhel7" - vmTemplateWindows = "vm-template-windows2012r2" + vmiEphemeral = "vmi-ephemeral" + vmiFlavorSmall = "vmi-flavor-small" + vmiSata = "vmi-sata" + vmiFedora = "vmi-fedora" + vmiNoCloud = "vmi-nocloud" + vmiPVC = "vmi-pvc" + vmiWindows = "vmi-windows" + vmiSlirp = "vmi-slirp" + vmiWithHookSidecar = "vmi-with-sidecar-hook" + vmTemplateFedora = "vm-template-fedora" + vmTemplateRHEL7 = "vm-template-rhel7" + vmTemplateWindows = "vm-template-windows2012r2" ) const ( @@ -577,6 +578,20 @@ func getVMIPresetSmall() *v1.VirtualMachineInstancePreset { return vmPreset } +func getVmWithHookSidecar() *v1.VirtualMachine { + vm := getBaseVMI(vmiWithHookSidecar) + vm.Spec.Domain.Resources.Requests[k8sv1.ResourceMemory] = resource.MustParse("1024M") + + addRegistryDisk(&vm.Spec, fmt.Sprintf("%s/%s:%s", dockerPrefix, imageFedora, dockerTag), busVirtio) + addNoCloudDiskWitUserData(&vm.Spec, "#cloud-config\npassword: fedora\nchpasswd: { expire: False }") + + vm.ObjectMeta.Annotations = map[string]string{ + "hooks.kubevirt.io/hookSidecars": `[{"image": "registry:5000/kubevirt/example-hook-sidecar:devel"}]`, + "smbios.vm.kubevirt.io/baseBoardManufacturer": "Radical Edward", + } + return vm +} + func main() { flag.StringVar(&dockerPrefix, "docker-prefix", dockerPrefix, "") flag.StringVar(&dockerTag, "docker-tag", dockerTag, "") @@ -589,14 +604,15 @@ func main() { } var vmis = map[string]*v1.VirtualMachineInstance{ - vmiEphemeral: getVMIEphemeral(), - vmiFlavorSmall: getVMIFlavorSmall(), - vmiSata: getVMISata(), - vmiFedora: getVMIEphemeralFedora(), - vmiNoCloud: getVMINoCloud(), - vmiPVC: getVMIPvc(), - vmiWindows: getVMIWindows(), - vmiSlirp: getVMISlirp(), + vmiEphemeral: getVMIEphemeral(), + vmiFlavorSmall: getVMIFlavorSmall(), + vmiSata: getVMISata(), + vmiFedora: getVMIEphemeralFedora(), + vmiNoCloud: getVMINoCloud(), + vmiPVC: getVMIPvc(), + vmiWindows: getVMIWindows(), + vmiSlirp: getVMISlirp(), + vmiWithHookSidecar: getVMIWithHookSidecar(), } var vmireplicasets = map[string]*v1.VirtualMachineInstanceReplicaSet{