From 12cb69406a3a33a3b38c97e35014fa905858fe72 Mon Sep 17 00:00:00 2001
From: Vasiliy Ulyanov <vulyanov@suse.de>
Date: Wed, 19 Jul 2023 10:36:21 +0200
Subject: [PATCH] Support multiple watchdogs in the domain schema

Libvirt allows several watchdog devices since 9.1.0. The documentation
now states:

Having multiple watchdogs is usually not something very common, but be
aware that this might happen, for example, when an implicit watchdog
device is added as part of another device. For example the iTCO watchdog
being part of the ich9 southbridge, which is used with the q35 machine
type.

Signed-off-by: Vasiliy Ulyanov <vulyanov@suse.de>
---
 pkg/virt-launcher/virtwrap/api/deepcopy_generated.go  | 10 ++++++----
 pkg/virt-launcher/virtwrap/api/schema.go              |  2 +-
 pkg/virt-launcher/virtwrap/api/schema_test.go         | 10 ++++++----
 pkg/virt-launcher/virtwrap/converter/converter.go     |  2 +-
 pkg/virt-launcher/virtwrap/converter/pci-placement.go |  4 ++--
 5 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/pkg/virt-launcher/virtwrap/api/deepcopy_generated.go b/pkg/virt-launcher/virtwrap/api/deepcopy_generated.go
index b5cb529e2..c1d3a781a 100644
--- a/pkg/virt-launcher/virtwrap/api/deepcopy_generated.go
+++ b/pkg/virt-launcher/virtwrap/api/deepcopy_generated.go
@@ -736,10 +736,12 @@ func (in *Devices) DeepCopyInto(out *Devices) {
 			(*in)[i].DeepCopyInto(&(*out)[i])
 		}
 	}
-	if in.Watchdog != nil {
-		in, out := &in.Watchdog, &out.Watchdog
-		*out = new(Watchdog)
-		(*in).DeepCopyInto(*out)
+	if in.Watchdogs != nil {
+		in, out := &in.Watchdogs, &out.Watchdogs
+		*out = make([]Watchdog, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
 	}
 	if in.Rng != nil {
 		in, out := &in.Rng, &out.Rng
diff --git a/pkg/virt-launcher/virtwrap/api/schema.go b/pkg/virt-launcher/virtwrap/api/schema.go
index 465c6c6c1..ff4e6e959 100644
--- a/pkg/virt-launcher/virtwrap/api/schema.go
+++ b/pkg/virt-launcher/virtwrap/api/schema.go
@@ -473,7 +473,7 @@ type Devices struct {
 	Inputs      []Input            `xml:"input"`
 	Serials     []Serial           `xml:"serial"`
 	Consoles    []Console          `xml:"console"`
-	Watchdog    *Watchdog          `xml:"watchdog,omitempty"`
+	Watchdogs   []Watchdog         `xml:"watchdog,omitempty"`
 	Rng         *Rng               `xml:"rng,omitempty"`
 	Filesystems []FilesystemDevice `xml:"filesystem,omitempty"`
 	Redirs      []RedirectedDevice `xml:"redirdev,omitempty"`
diff --git a/pkg/virt-launcher/virtwrap/api/schema_test.go b/pkg/virt-launcher/virtwrap/api/schema_test.go
index 8150ea8fd..c315cf13f 100644
--- a/pkg/virt-launcher/virtwrap/api/schema_test.go
+++ b/pkg/virt-launcher/virtwrap/api/schema_test.go
@@ -348,10 +348,12 @@ var _ = ginkgo.Describe("Schema", func() {
 		exampleDomain.Spec.Devices.Consoles = []Console{
 			{Type: "pty"},
 		}
-		exampleDomain.Spec.Devices.Watchdog = &Watchdog{
-			Model:  "i6300esb",
-			Action: "poweroff",
-			Alias:  NewUserDefinedAlias("mywatchdog"),
+		exampleDomain.Spec.Devices.Watchdogs = []Watchdog{
+			{
+				Model:  "i6300esb",
+				Action: "poweroff",
+				Alias:  NewUserDefinedAlias("mywatchdog"),
+			},
 		}
 		exampleDomain.Spec.Devices.Rng = &Rng{
 			Model:   v1.VirtIO,
diff --git a/pkg/virt-launcher/virtwrap/converter/converter.go b/pkg/virt-launcher/virtwrap/converter/converter.go
index db3c0a903..531a5ea71 100644
--- a/pkg/virt-launcher/virtwrap/converter/converter.go
+++ b/pkg/virt-launcher/virtwrap/converter/converter.go
@@ -1582,7 +1582,7 @@ func Convert_v1_VirtualMachineInstance_To_api_Domain(vmi *v1.VirtualMachineInsta
 		if err != nil {
 			return err
 		}
-		domain.Spec.Devices.Watchdog = newWatchdog
+		domain.Spec.Devices.Watchdogs = append(domain.Spec.Devices.Watchdogs, *newWatchdog)
 	}
 
 	if vmi.Spec.Domain.Devices.Rng != nil {
diff --git a/pkg/virt-launcher/virtwrap/converter/pci-placement.go b/pkg/virt-launcher/virtwrap/converter/pci-placement.go
index 38ca8354e..fbe17ba6e 100644
--- a/pkg/virt-launcher/virtwrap/converter/pci-placement.go
+++ b/pkg/virt-launcher/virtwrap/converter/pci-placement.go
@@ -53,8 +53,8 @@ func PlacePCIDevicesOnRootComplex(spec *api.DomainSpec) (err error) {
 			return err
 		}
 	}
-	if spec.Devices.Watchdog != nil {
-		spec.Devices.Watchdog.Address, err = assigner.PlacePCIDeviceAtNextSlot(spec.Devices.Watchdog.Address)
+	for i, watchdog := range spec.Devices.Watchdogs {
+		spec.Devices.Watchdogs[i].Address, err = assigner.PlacePCIDeviceAtNextSlot(watchdog.Address)
 		if err != nil {
 			return err
 		}
-- 
2.41.0

