From dad0dc7b01ee85823688d4a24b6e0d78f6037382 Mon Sep 17 00:00:00 2001 From: Piotr Skamruk Date: Tue, 10 Jul 2018 15:06:21 +0200 Subject: [PATCH] Pass system uuid as domain uuid and in sysinfo --- docs/docs/reference/resources.md | 12 +++ .../TestContainerLifecycle.out.yaml | 3 + ...estDomainDefinitions__system_UUID.out.yaml | 101 ++++++++++++++++++ .../TestDomainForcedShutdown.out.yaml | 1 + pkg/libvirttools/virtualization.go | 24 ++++- pkg/libvirttools/virtualization_test.go | 6 ++ pkg/metadata/types/annotations.go | 12 +++ pkg/metadata/types/annotations_test.go | 19 ++++ tests/e2e/framework/vm_interface.go | 5 + tests/e2e/systemuuid_test.go | 52 +++++++++ 10 files changed, 234 insertions(+), 1 deletion(-) create mode 100755 pkg/libvirttools/TestDomainDefinitions__system_UUID.out.yaml create mode 100644 tests/e2e/systemuuid_test.go diff --git a/docs/docs/reference/resources.md b/docs/docs/reference/resources.md index 48fa7ccbb..35e375f5a 100644 --- a/docs/docs/reference/resources.md +++ b/docs/docs/reference/resources.md @@ -30,6 +30,18 @@ metrics about running containers and Virtlet doesn't create container per each VM, and instead spawns VMs inside Virtlet container. This leads to all the resource usage being lumped together and ascribed to Virtlet pod. +## Using fixed SMBIOS UUID +By default, VM pods use autogenerated SMBIOS UUID values. Some images may expect it to have a fixed value, +for example, due to software license requirements. In such cases, the value of SMBIOS UUID can be passed +using `VirtletSystemUUID` annotation. +For example: +```yaml + annotations: + VirtletSystemUUID: 53008994-44c0-4017-ad44-9c49758083da +``` +Note: Virtlet can't handle multiple VMs with the same SMBIOS UUID on the same node. There can be multiple +VM pods with the same SMBIOS UUIDs residing on different nodes in the cluster, though. + ## CPU management ### CPU cgroups facilities: 1. `shares` - relative value of cpu time assigned, not recommended for using diff --git a/pkg/libvirttools/TestContainerLifecycle.out.yaml b/pkg/libvirttools/TestContainerLifecycle.out.yaml index 940d32c1d..0237c5ab6 100755 --- a/pkg/libvirttools/TestContainerLifecycle.out.yaml +++ b/pkg/libvirttools/TestContainerLifecycle.out.yaml @@ -119,6 +119,7 @@ MetaData: null RootVolumeSize: 0 SSHKeys: null + SystemUUID: null UserData: null UserDataOverwrite: false UserDataScript: "" @@ -176,6 +177,7 @@ MetaData: null RootVolumeSize: 0 SSHKeys: null + SystemUUID: null UserData: null UserDataOverwrite: false UserDataScript: "" @@ -228,6 +230,7 @@ MetaData: null RootVolumeSize: 0 SSHKeys: null + SystemUUID: null UserData: null UserDataOverwrite: false UserDataScript: "" diff --git a/pkg/libvirttools/TestDomainDefinitions__system_UUID.out.yaml b/pkg/libvirttools/TestDomainDefinitions__system_UUID.out.yaml new file mode 100755 index 000000000..c1494df96 --- /dev/null +++ b/pkg/libvirttools/TestDomainDefinitions__system_UUID.out.yaml @@ -0,0 +1,101 @@ +- name: GetImagePathDigestAndVirtualSize + value: fake/image1 +- name: 'storage: CreateStoragePool' + value: |- + + volumes + + /var/lib/virtlet/volumes + + +- name: 'storage: volumes: CreateStorageVol' + value: |- + + virtlet_root_53008994-44c0-4017-ad44-9c49758083da + 0 + 424242 + + + + + /fake/volume/path + + + +- name: 'domain conn: DefineDomain' + value: |- + + virtlet-53008994-44c0-container1 + 53008994-44c0-4017-ad44-9c49758083da + 1024 + 1 + + 0 + 0 + 0 + + + + 53008994-44c0-4017-ad44-9c49758083da + + + + hvm + + + + + + destroy + restart + restart + + /vmwrapper + + + + +
+
+ + + + + +
+
+ +
+
+ + + + + + + + + + +
+ + + + + + +
+- name: 'domain conn: virtlet-53008994-44c0-container1: Create' +- name: 'domain conn: virtlet-53008994-44c0-container1: iso image' + value: + meta-data: '{"instance-id":"testName_0.default","local-hostname":"testName_0"}' + network-config: | + version: 1 + user-data: | + #cloud-config +- name: 'domain conn: virtlet-53008994-44c0-container1: Destroy' +- name: 'domain conn: virtlet-53008994-44c0-container1: Undefine' +- name: 'storage: volumes: RemoveVolumeByName' + value: virtlet_root_53008994-44c0-4017-ad44-9c49758083da diff --git a/pkg/libvirttools/TestDomainForcedShutdown.out.yaml b/pkg/libvirttools/TestDomainForcedShutdown.out.yaml index 0f8d04a36..a8c768a6b 100755 --- a/pkg/libvirttools/TestDomainForcedShutdown.out.yaml +++ b/pkg/libvirttools/TestDomainForcedShutdown.out.yaml @@ -135,6 +135,7 @@ MetaData: null RootVolumeSize: 0 SSHKeys: null + SystemUUID: null UserData: null UserDataOverwrite: false UserDataScript: "" diff --git a/pkg/libvirttools/virtualization.go b/pkg/libvirttools/virtualization.go index e295d771e..baf2152cb 100644 --- a/pkg/libvirttools/virtualization.go +++ b/pkg/libvirttools/virtualization.go @@ -25,6 +25,7 @@ import ( "github.com/golang/glog" "github.com/jonboulle/clockwork" libvirtxml "github.com/libvirt/libvirt-go-xml" + uuid "github.com/nu7hatch/gouuid" "k8s.io/apimachinery/pkg/fields" kubetypes "k8s.io/kubernetes/pkg/kubelet/types" @@ -77,6 +78,7 @@ type domainSettings struct { netFdKey string enableSriov bool cpuModel string + systemUUID *uuid.UUID } func (ds *domainSettings) createDomain(config *types.VMConfig) *libvirtxml.Domain { @@ -181,6 +183,20 @@ func (ds *domainSettings) createDomain(config *types.VMConfig) *libvirtxml.Domai } } + if ds.systemUUID != nil { + domain.SysInfo = &libvirtxml.DomainSysInfo{ + Type: "smbios", + System: &libvirtxml.DomainSysInfoSystem{ + Entry: []libvirtxml.DomainSysInfoEntry{ + { + Name: "uuid", + Value: ds.systemUUID.String(), + }, + }, + }, + } + } + if ds.enableSriov { domain.QEMUCommandline.Envs = append(domain.QEMUCommandline.Envs, libvirtxml.DomainQEMUCommandlineEnv{Name: "VMWRAPPER_KEEP_PRIVS", Value: "1"}) @@ -302,7 +318,12 @@ func (v *VirtualizationTool) CreateContainer(config *types.VMConfig, netFdKey st return "", err } - domainUUID := utils.NewUUID5(ContainerNsUUID, config.PodSandboxID) + var domainUUID string + if config.ParsedAnnotations.SystemUUID != nil { + domainUUID = config.ParsedAnnotations.SystemUUID.String() + } else { + domainUUID = utils.NewUUID5(ContainerNsUUID, config.PodSandboxID) + } // FIXME: this field should be moved to VMStatus struct (to be added) config.DomainUUID = domainUUID cpuModel := v.config.CPUModel @@ -328,6 +349,7 @@ func (v *VirtualizationTool) CreateContainer(config *types.VMConfig, netFdKey st memoryUnit: "b", useKvm: !v.config.DisableKVM, cpuModel: cpuModel, + systemUUID: config.ParsedAnnotations.SystemUUID, } if settings.memory == 0 { settings.memory = defaultMemory diff --git a/pkg/libvirttools/virtualization_test.go b/pkg/libvirttools/virtualization_test.go index 7ac99c65f..6050bffaa 100644 --- a/pkg/libvirttools/virtualization_test.go +++ b/pkg/libvirttools/virtualization_test.go @@ -345,6 +345,12 @@ func TestDomainDefinitions(t *testing.T) { { name: "plain domain", }, + { + name: "system UUID", + annotations: map[string]string{ + "VirtletSystemUUID": "53008994-44c0-4017-ad44-9c49758083da", + }, + }, { name: "raw devices", flexVolumes: map[string]map[string]interface{}{ diff --git a/pkg/metadata/types/annotations.go b/pkg/metadata/types/annotations.go index e133a254d..198bfe5b3 100644 --- a/pkg/metadata/types/annotations.go +++ b/pkg/metadata/types/annotations.go @@ -24,6 +24,7 @@ import ( "github.com/ghodss/yaml" libvirtxml "github.com/libvirt/libvirt-go-xml" + uuid "github.com/nu7hatch/gouuid" "k8s.io/apimachinery/pkg/api/resource" "github.com/Mirantis/virtlet/pkg/utils" @@ -43,6 +44,7 @@ const ( libvirtCPUSetting = "VirtletLibvirtCPUSetting" sshKeysKeyName = "VirtletSSHKeys" chown9pfsMountsKeyName = "VirtletChown9pfsMounts" + systemUUIDKeyName = "VirtletSystemUUID" // CloudInitUserDataSourceKeyName is the name of user data source key in the pod annotations. CloudInitUserDataSourceKeyName = "VirtletCloudInitUserDataSource" // SSHKeySourceKeyName is the name of ssh key source key in the pod annotations. @@ -114,6 +116,9 @@ type VirtletAnnotations struct { // InjectedFiles specifies the files to be injected into VM's // rootfs before booting the VM. InjectedFiles map[string][]byte + // SystemUUID specifies fixed SMBIOS UUID to be used for the domain. + // If not set, the SMBIOS UUID will be automatically generated from the Pod ID. + SystemUUID *uuid.UUID } // ExternalUserDataLoader is a function that loads external user data that's specified @@ -303,5 +308,12 @@ func (va *VirtletAnnotations) parsePodAnnotations(ns string, podAnnotations map[ va.VirtletChown9pfsMounts = true } + if systemUUIDStr, found := podAnnotations[systemUUIDKeyName]; found { + var err error + if va.SystemUUID, err = uuid.ParseHex(systemUUIDStr); err != nil { + return fmt.Errorf("failed to parse %q as a UUID: %v", systemUUIDStr, err) + } + } + return nil } diff --git a/pkg/metadata/types/annotations_test.go b/pkg/metadata/types/annotations_test.go index 010393a5d..7a50ea684 100644 --- a/pkg/metadata/types/annotations_test.go +++ b/pkg/metadata/types/annotations_test.go @@ -19,9 +19,12 @@ package types import ( "reflect" "testing" + + uuid "github.com/nu7hatch/gouuid" ) func TestVirtletAnnotations(t *testing.T) { + for _, testCase := range []struct { name string annotations map[string]string @@ -144,6 +147,22 @@ func TestVirtletAnnotations(t *testing.T) { CDImageType: "nocloud", }, }, + { + name: "system UUID", + annotations: map[string]string{ + "VirtletSystemUUID": "53008994-44c0-4017-ad44-9c49758083da", + }, + va: &VirtletAnnotations{ + VCPUCount: 1, + SystemUUID: &uuid.UUID{ + 0x53, 0, 0x89, 0x94, + 0x44, 0xc0, 0x40, 0x17, 0xad, 0x44, + 0x9c, 0x49, 0x75, 0x80, 0x83, 0xda, + }, + DiskDriver: "scsi", + CDImageType: "nocloud", + }, + }, // bad metadata items follow { name: "bad vcpu count", diff --git a/tests/e2e/framework/vm_interface.go b/tests/e2e/framework/vm_interface.go index d8fa432dc..31f1171a3 100644 --- a/tests/e2e/framework/vm_interface.go +++ b/tests/e2e/framework/vm_interface.go @@ -72,6 +72,8 @@ type VMOptions struct { PVCs []PVCSpec // ConfigMap or Secret to inject into the rootfs InjectFilesToRootfsFrom string + // SystemUUID to set + SystemUUID string } func newVMInterface(controller *Controller, name string) *VMInterface { @@ -215,6 +217,9 @@ func (vmi *VMInterface) buildVMPod(options VMOptions) *v1.Pod { if options.InjectFilesToRootfsFrom != "" { annotations["VirtletFilesFromDataSource"] = options.InjectFilesToRootfsFrom } + if options.SystemUUID != "" { + annotations["VirtletSystemUUID"] = options.SystemUUID + } limits := v1.ResourceList{} for k, v := range options.Limits { diff --git a/tests/e2e/systemuuid_test.go b/tests/e2e/systemuuid_test.go new file mode 100644 index 000000000..c03c2574b --- /dev/null +++ b/tests/e2e/systemuuid_test.go @@ -0,0 +1,52 @@ +/* +Copyright 2019 Mirantis + +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 e2e + +import ( + "time" + + . "github.com/onsi/gomega" + + "github.com/Mirantis/virtlet/tests/e2e/framework" + . "github.com/Mirantis/virtlet/tests/e2e/ginkgo-ext" +) + +var _ = Describe("SystemUUID passing", func() { + var ( + vm *framework.VMInterface + ssh framework.Executor + ) + + BeforeAll(func() { + vm = controller.VM("uuid") + Expect(vm.CreateAndWait(VMOptions{ + SystemUUID: "53008994-44c0-4017-ad44-9c49758083da", + }.ApplyDefaults(), time.Minute*5, nil)).To(Succeed()) + do(vm.Pod()) + }) + + AfterAll(func() { + deleteVM(vm) + }) + + scheduleWaitSSH(&vm, &ssh) + + It("Should have the specified SMBIOS UUID set [Conformance]", func() { + uuid := do(framework.RunSimple(ssh, "sudo", "cat", "/sys/class/dmi/id/product_uuid")).(string) + Expect(uuid).To(Equal("53008994-44C0-4017-AD44-9C49758083DA")) + }) +})