diff --git a/api/v1alpha1/kubevirtcluster_types.go b/api/v1alpha1/kubevirtcluster_types.go index c13a714d..aaad865a 100644 --- a/api/v1alpha1/kubevirtcluster_types.go +++ b/api/v1alpha1/kubevirtcluster_types.go @@ -38,6 +38,7 @@ const ( //labels const ( // annotations VmiDeletionGraceTime = "capk.cluster.x-k8s.io/vmi-deletion-grace-time" VmiDeletionGraceTimeEscape = "capk.cluster.x-k8s.io~1vmi-deletion-grace-time" + HostnameListAnnotation = "capk.cluster.x-k8s.io/hostname-list" ) // KubevirtClusterSpec defines the desired state of KubevirtCluster. diff --git a/pkg/kubevirt/machine.go b/pkg/kubevirt/machine.go index bb86c110..4554b2cc 100644 --- a/pkg/kubevirt/machine.go +++ b/pkg/kubevirt/machine.go @@ -181,7 +181,19 @@ func (m *Machine) Exists() bool { func (m *Machine) Create(ctx gocontext.Context) error { m.machineContext.Logger.Info(fmt.Sprintf("Creating VM with role '%s'...", nodeRole(m.machineContext))) - virtualMachine := newVirtualMachineFromKubevirtMachine(m.machineContext, m.namespace) + // Get assigned hostname from MachineSet annotation if available + hostnameSelector := NewHostnameSelector(m.client) + assignedHostname, err := hostnameSelector.GetAssignedHostname(ctx, m.machineContext.KubevirtMachine, m.machineContext.Machine) + if err != nil { + m.machineContext.Logger.Error(err, "Failed to get assigned hostname, using original name") + assignedHostname = m.machineContext.KubevirtMachine.Name + } + + if assignedHostname != m.machineContext.KubevirtMachine.Name { + m.machineContext.Logger.Info(fmt.Sprintf("Using assigned hostname '%s' instead of generated name '%s'", assignedHostname, m.machineContext.KubevirtMachine.Name)) + } + + virtualMachine := newVirtualMachineFromKubevirtMachine(m.machineContext, m.namespace, assignedHostname) mutateFn := func() (err error) { if virtualMachine.Labels == nil { diff --git a/pkg/kubevirt/machine_test.go b/pkg/kubevirt/machine_test.go index 18589700..f48f049d 100644 --- a/pkg/kubevirt/machine_test.go +++ b/pkg/kubevirt/machine_test.go @@ -605,7 +605,7 @@ var _ = Describe("util functions", func() { machineContext.KubevirtMachine.Spec.VirtualMachineTemplate.Spec.DataVolumeTemplates = dataVolumeTemplates machineContext.KubevirtMachine.Spec.VirtualMachineTemplate.Spec.Template.Spec.Volumes = volumes - newVM := newVirtualMachineFromKubevirtMachine(machineContext, "default") + newVM := newVirtualMachineFromKubevirtMachine(machineContext, "default", "") Expect(newVM.Spec.DataVolumeTemplates[0].ObjectMeta.Name).To(Equal(kubevirtMachineName + "-dv1")) Expect(newVM.Spec.Template.Spec.Volumes[0].VolumeSource.DataVolume.Name).To(Equal(kubevirtMachineName + "-dv1")) @@ -771,7 +771,7 @@ var _ = Describe("util functions", func() { machineContext.KubevirtMachine.Spec.VirtualMachineTemplate.Spec.DataVolumeTemplates = dataVolumeTemplates machineContext.KubevirtMachine.Spec.VirtualMachineTemplate.Spec.Template.Spec.Volumes = volumes - newVM := newVirtualMachineFromKubevirtMachine(machineContext, "default") + newVM := newVirtualMachineFromKubevirtMachine(machineContext, "default", "") Expect(newVM.Spec.DataVolumeTemplates[0].ObjectMeta.Name).To(Equal(kubevirtMachineName + "-dv1")) Expect(newVM.Spec.Template.Spec.Volumes[0].VolumeSource.DataVolume.Name).To(Equal(kubevirtMachineName + "-dv1")) diff --git a/pkg/kubevirt/utils.go b/pkg/kubevirt/utils.go index afd14413..c7a63e8e 100644 --- a/pkg/kubevirt/utils.go +++ b/pkg/kubevirt/utils.go @@ -68,8 +68,8 @@ func prefixDataVolumeTemplates(vm *kubevirtv1.VirtualMachine, prefix string) *ku } // newVirtualMachineFromKubevirtMachine creates VirtualMachine instance. -func newVirtualMachineFromKubevirtMachine(ctx *context.MachineContext, namespace string) *kubevirtv1.VirtualMachine { - vmiTemplate := buildVirtualMachineInstanceTemplate(ctx) +func newVirtualMachineFromKubevirtMachine(ctx *context.MachineContext, namespace string, assignedHostname string) *kubevirtv1.VirtualMachine { + vmiTemplate := buildVirtualMachineInstanceTemplate(ctx, assignedHostname) virtualMachine := &kubevirtv1.VirtualMachine{ Spec: *ctx.KubevirtMachine.Spec.VirtualMachineTemplate.Spec.DeepCopy(), @@ -80,8 +80,14 @@ func newVirtualMachineFromKubevirtMachine(ctx *context.MachineContext, namespace virtualMachine.APIVersion = "kubevirt.io/v1" virtualMachine.Kind = "VirtualMachine" + // Use assigned hostname if provided, otherwise fall back to original KubevirtMachine name + vmName := assignedHostname + if vmName == "" { + vmName = ctx.KubevirtMachine.Name + } + virtualMachine.ObjectMeta = metav1.ObjectMeta{ - Name: ctx.KubevirtMachine.Name, + Name: vmName, Namespace: namespace, Labels: map[string]string{}, } @@ -94,13 +100,13 @@ func newVirtualMachineFromKubevirtMachine(ctx *context.MachineContext, namespace virtualMachine.ObjectMeta.Annotations = mapCopy(ctx.KubevirtMachine.Spec.VirtualMachineTemplate.ObjectMeta.Annotations) } - virtualMachine.ObjectMeta.Labels["kubevirt.io/vm"] = ctx.KubevirtMachine.Name - virtualMachine.ObjectMeta.Labels["name"] = ctx.KubevirtMachine.Name + virtualMachine.ObjectMeta.Labels["kubevirt.io/vm"] = vmName + virtualMachine.ObjectMeta.Labels["name"] = vmName virtualMachine.ObjectMeta.Labels["cluster.x-k8s.io/role"] = nodeRole(ctx) virtualMachine.ObjectMeta.Labels["cluster.x-k8s.io/cluster-name"] = ctx.Cluster.Name // make each datavolume unique by appending machine name as a prefix - virtualMachine = prefixDataVolumeTemplates(virtualMachine, ctx.KubevirtMachine.Name) + virtualMachine = prefixDataVolumeTemplates(virtualMachine, vmName) return virtualMachine } @@ -115,7 +121,7 @@ func mapCopy(src map[string]string) map[string]string { } // buildVirtualMachineInstanceTemplate creates VirtualMachineInstanceTemplateSpec. -func buildVirtualMachineInstanceTemplate(ctx *context.MachineContext) *kubevirtv1.VirtualMachineInstanceTemplateSpec { +func buildVirtualMachineInstanceTemplate(ctx *context.MachineContext, assignedHostname string) *kubevirtv1.VirtualMachineInstanceTemplateSpec { template := &kubevirtv1.VirtualMachineInstanceTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{}, @@ -131,8 +137,14 @@ func buildVirtualMachineInstanceTemplate(ctx *context.MachineContext) *kubevirtv template.ObjectMeta.Annotations = mapCopy(ctx.KubevirtMachine.Spec.VirtualMachineTemplate.Spec.Template.ObjectMeta.Annotations) } - template.ObjectMeta.Labels["kubevirt.io/vm"] = ctx.KubevirtMachine.Name - template.ObjectMeta.Labels["name"] = ctx.KubevirtMachine.Name + // Use assigned hostname if provided, otherwise fall back to original KubevirtMachine name + vmName := assignedHostname + if vmName == "" { + vmName = ctx.KubevirtMachine.Name + } + + template.ObjectMeta.Labels["kubevirt.io/vm"] = vmName + template.ObjectMeta.Labels["name"] = vmName template.ObjectMeta.Labels["cluster.x-k8s.io/role"] = nodeRole(ctx) template.ObjectMeta.Labels["cluster.x-k8s.io/cluster-name"] = ctx.Cluster.Name