From 6b924d4e1d98de7b26ac6982c0c1e0e95df4602f Mon Sep 17 00:00:00 2001 From: Liran Rotenberg Date: Mon, 27 Nov 2023 15:44:14 +0200 Subject: [PATCH 1/5] Validate TPM device If the source VM is set with windows 2022 or windows 11 that must have a TPM warn about it. Signed-off-by: Liran Rotenberg --- .../io/konveyor/forklift/ovirt/tpm.rego | 16 ++++++++++++ .../io/konveyor/forklift/ovirt/tpm_test.rego | 25 +++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 validation/policies/io/konveyor/forklift/ovirt/tpm.rego create mode 100644 validation/policies/io/konveyor/forklift/ovirt/tpm_test.rego diff --git a/validation/policies/io/konveyor/forklift/ovirt/tpm.rego b/validation/policies/io/konveyor/forklift/ovirt/tpm.rego new file mode 100644 index 000000000..05d404a8a --- /dev/null +++ b/validation/policies/io/konveyor/forklift/ovirt/tpm.rego @@ -0,0 +1,16 @@ +package io.konveyor.forklift.ovirt + +default has_tpm_os = false + +has_tpm_os = true { + regex.match(`windows_2022|windows_11`, input.osType) +} + +concerns[flag] { + has_tpm_os + flag := { + "category": "Warning", + "label": "VM configured with a TPM device", + "assessment": "The VM is detected with an operation system that must have a TPM device. TPM data is not transferred during the migration." + } +} diff --git a/validation/policies/io/konveyor/forklift/ovirt/tpm_test.rego b/validation/policies/io/konveyor/forklift/ovirt/tpm_test.rego new file mode 100644 index 000000000..2ae0eaf97 --- /dev/null +++ b/validation/policies/io/konveyor/forklift/ovirt/tpm_test.rego @@ -0,0 +1,25 @@ +package io.konveyor.forklift.ovirt + +test_without_tpm_enabled { + mock_vm := { "name": "test", + "osType": "rhel_9x64" + } + results = concerns with input as mock_vm + count(results) == 0 +} + +test_with_tpm_enabled_w11 { + mock_vm := { "name": "test", + "osType": "windows_11" + } + results = concerns with input as mock_vm + count(results) == 1 +} + +test_with_tpm_enabled_w2k22 { + mock_vm := { "name": "test", + "osType": "windows_2022" + } + results = concerns with input as mock_vm + count(results) == 1 +} \ No newline at end of file From 1b10a66c0de7a2ad1f91daba840a665dbcc4961d Mon Sep 17 00:00:00 2001 From: Liran Rotenberg Date: Mon, 27 Nov 2023 15:52:15 +0200 Subject: [PATCH 2/5] Create TPM device based on ovirt source When having Windows 2k22 or Windows 11 OS, a TPM device is a must. Therefore, we will create it also for the destination VM. The data is persist in ovirt. If supported by kubevirt the TPM will be persistent TPM, otherwise the TPM is without persistent data. In order to have the TPM persistent it is required to have kubvirt v1.0.0 and adding configuration manually as described in: https://kubevirt.io/user-guide/virtual_machines/persistent_tpm_and_uefi_state/ It is also supported in CNV running on OCP 4.14, and you need to follow: https://access.redhat.com/documentation/en-us/openshift_container_platform/4.14/html/virtualization/virtual-machines#virt-using-vtpm-devices Signed-off-by: Liran Rotenberg --- pkg/controller/plan/adapter/ovirt/builder.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkg/controller/plan/adapter/ovirt/builder.go b/pkg/controller/plan/adapter/ovirt/builder.go index 3e9ba26cc..1e629d307 100644 --- a/pkg/controller/plan/adapter/ovirt/builder.go +++ b/pkg/controller/plan/adapter/ovirt/builder.go @@ -287,6 +287,7 @@ func (r *Builder) VirtualMachine(vmRef ref.Ref, object *cnv.VirtualMachineSpec, r.mapMemory(vm, object) r.mapClock(vm, object) r.mapInput(object) + r.mapTpm(vm, object) err = r.mapNetworks(vm, object) if err != nil { return @@ -504,6 +505,13 @@ func (r *Builder) mapDisks(vm *model.Workload, persistentVolumeClaims []core.Per object.Template.Spec.Domain.Devices.Disks = kDisks } +func (r *Builder) mapTpm(vm *model.Workload, object *cnv.VirtualMachineSpec) { + if vm.OSType == "windows_2022" || vm.OSType == "windows_11" { + persistData := true + object.Template.Spec.Domain.Devices.TPM = &cnv.TPMDevice{Persistent: &persistData} + } +} + // Build tasks. func (r *Builder) Tasks(vmRef ref.Ref) (list []*plan.Task, err error) { vm := &model.Workload{} From ea5460054931bce1ea01737ee476e73102d97198 Mon Sep 17 00:00:00 2001 From: Liran Rotenberg Date: Mon, 27 Nov 2023 19:29:46 +0200 Subject: [PATCH 3/5] Introduce TPM to vsphere inventory Signed-off-by: Liran Rotenberg --- pkg/controller/provider/container/vsphere/collector.go | 2 ++ pkg/controller/provider/container/vsphere/model.go | 4 ++++ pkg/controller/provider/model/vsphere/model.go | 1 + pkg/controller/provider/web/vsphere/vm.go | 2 ++ 4 files changed, 9 insertions(+) diff --git a/pkg/controller/provider/container/vsphere/collector.go b/pkg/controller/provider/container/vsphere/collector.go index d9b620c73..78372b630 100644 --- a/pkg/controller/provider/container/vsphere/collector.go +++ b/pkg/controller/provider/container/vsphere/collector.go @@ -110,6 +110,7 @@ const ( fChangeTracking = "config.changeTrackingEnabled" fGuestName = "summary.config.guestFullName" fGuestID = "summary.guest.guestId" + fTpmPresent = "summary.config.tpmPresent" fBalloonedMemory = "summary.quickStats.balloonedMemory" fVmIpAddress = "summary.guest.ipAddress" fStorageUsed = "summary.storage.committed" @@ -714,6 +715,7 @@ func (r *Collector) propertySpec() []types.PropertySpec { fExtraConfig, fGuestName, fGuestID, + fTpmPresent, fBalloonedMemory, fVmIpAddress, fStorageUsed, diff --git a/pkg/controller/provider/container/vsphere/model.go b/pkg/controller/provider/container/vsphere/model.go index 51efc9f87..394355b90 100644 --- a/pkg/controller/provider/container/vsphere/model.go +++ b/pkg/controller/provider/container/vsphere/model.go @@ -570,6 +570,10 @@ func (v *VmAdapter) Apply(u types.ObjectUpdate) { if s, cast := p.Val.(string); cast { v.model.GuestName = s } + case fTpmPresent: + if b, cast := p.Val.(bool); cast { + v.model.TpmEnabled = b + } case fGuestID: if s, cast := p.Val.(string); cast { // When the VM isn't powered on, the guest tools don't report diff --git a/pkg/controller/provider/model/vsphere/model.go b/pkg/controller/provider/model/vsphere/model.go index b58a4f760..42503faf7 100644 --- a/pkg/controller/provider/model/vsphere/model.go +++ b/pkg/controller/provider/model/vsphere/model.go @@ -256,6 +256,7 @@ type VM struct { Snapshot Ref `sql:""` IsTemplate bool `sql:""` ChangeTrackingEnabled bool `sql:""` + TpmEnabled bool `sql:""` Devices []Device `sql:""` NICs []NIC `sql:""` Disks []Disk `sql:""` diff --git a/pkg/controller/provider/web/vsphere/vm.go b/pkg/controller/provider/web/vsphere/vm.go index 0ec3e4e36..9236d4c03 100644 --- a/pkg/controller/provider/web/vsphere/vm.go +++ b/pkg/controller/provider/web/vsphere/vm.go @@ -229,6 +229,7 @@ type VM struct { BalloonedMemory int32 `json:"balloonedMemory"` IpAddress string `json:"ipAddress"` StorageUsed int64 `json:"storageUsed"` + TpmEnabled bool `json:"tpmEnabled"` NumaNodeAffinity []string `json:"numaNodeAffinity"` Devices []model.Device `json:"devices"` NICs []model.NIC `json:"nics"` @@ -255,6 +256,7 @@ func (r *VM) With(m *model.VM) { r.BalloonedMemory = m.BalloonedMemory r.IpAddress = m.IpAddress r.StorageUsed = m.StorageUsed + r.TpmEnabled = m.TpmEnabled r.FaultToleranceEnabled = m.FaultToleranceEnabled r.Devices = m.Devices r.NumaNodeAffinity = m.NumaNodeAffinity From addc13c76a8d432d621ec6e535b3f66ec692b951 Mon Sep 17 00:00:00 2001 From: Liran Rotenberg Date: Mon, 27 Nov 2023 19:36:10 +0200 Subject: [PATCH 4/5] Validate TPM on vsphere Warn in case TPM device is detected on a VM. Signed-off-by: Liran Rotenberg --- .../konveyor/forklift/vmware/tpm_enabled.rego | 16 ++++++++++++++++ .../forklift/vmware/tpm_enabled_test.rego | 19 +++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 validation/policies/io/konveyor/forklift/vmware/tpm_enabled.rego create mode 100644 validation/policies/io/konveyor/forklift/vmware/tpm_enabled_test.rego diff --git a/validation/policies/io/konveyor/forklift/vmware/tpm_enabled.rego b/validation/policies/io/konveyor/forklift/vmware/tpm_enabled.rego new file mode 100644 index 000000000..22708e0b3 --- /dev/null +++ b/validation/policies/io/konveyor/forklift/vmware/tpm_enabled.rego @@ -0,0 +1,16 @@ +package io.konveyor.forklift.vmware + +default has_tpm_enabled = false + +has_tpm_enabled = true { + input.tpmEnabled == true +} + +concerns[flag] { + has_tpm_enabled + flag := { + "category": "Warning", + "label": "VM configured with a TPM device", + "assessment": "The VM is configured with a TPM device. TPM data is not transferred during the migration." + } +} \ No newline at end of file diff --git a/validation/policies/io/konveyor/forklift/vmware/tpm_enabled_test.rego b/validation/policies/io/konveyor/forklift/vmware/tpm_enabled_test.rego new file mode 100644 index 000000000..d9b2a80b5 --- /dev/null +++ b/validation/policies/io/konveyor/forklift/vmware/tpm_enabled_test.rego @@ -0,0 +1,19 @@ +package io.konveyor.forklift.vmware + +test_with_tpm_disabled { + mock_vm := { + "name": "test", + "tpmEnabled": false, + } + results := concerns with input as mock_vm + count(results) == 0 +} + +test_with_cpu_hot_add_enabled { + mock_vm := { + "name": "test", + "tpmEnabled": true + } + results := concerns with input as mock_vm + count(results) == 1 +} \ No newline at end of file From 2e9c8fb0d08d0f57ccaf071729d8397940f979ae Mon Sep 17 00:00:00 2001 From: Liran Rotenberg Date: Mon, 27 Nov 2023 19:38:59 +0200 Subject: [PATCH 5/5] Add TPM to vsphere builder When having TPM device from the source, create it also for the destination VM. The data is persist in ovirt. If supported by kubevirt the TPM will be persistent TPM, otherwise the TPM without persistent data. Signed-off-by: Liran Rotenberg --- pkg/controller/plan/adapter/vsphere/builder.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkg/controller/plan/adapter/vsphere/builder.go b/pkg/controller/plan/adapter/vsphere/builder.go index 77240d5da..ac7c7c6cc 100644 --- a/pkg/controller/plan/adapter/vsphere/builder.go +++ b/pkg/controller/plan/adapter/vsphere/builder.go @@ -462,6 +462,7 @@ func (r *Builder) VirtualMachine(vmRef ref.Ref, object *cnv.VirtualMachineSpec, r.mapMemory(vm, object) r.mapClock(host, object) r.mapInput(object) + r.mapTpm(vm, object) err = r.mapNetworks(vm, object) if err != nil { return @@ -639,6 +640,13 @@ func (r *Builder) mapDisks(vm *model.VM, persistentVolumeClaims []core.Persisten object.Template.Spec.Domain.Devices.Disks = kDisks } +func (r *Builder) mapTpm(vm *model.VM, object *cnv.VirtualMachineSpec) { + if vm.TpmEnabled { + persistData := true + object.Template.Spec.Domain.Devices.TPM = &cnv.TPMDevice{Persistent: &persistData} + } +} + // Build tasks. func (r *Builder) Tasks(vmRef ref.Ref) (list []*plan.Task, err error) { vm := &model.VM{}