diff --git a/main.go b/main.go index c40785abc..65958e50e 100644 --- a/main.go +++ b/main.go @@ -18,9 +18,12 @@ import ( klog "k8s.io/klog/v2" "k8s.io/klog/v2/klogr" + "github.com/vmware-tanzu/vm-operator/api/v1alpha1" + "github.com/vmware-tanzu/vm-operator/api/v1alpha2" "github.com/vmware-tanzu/vm-operator/controllers" "github.com/vmware-tanzu/vm-operator/pkg" "github.com/vmware-tanzu/vm-operator/pkg/context" + "github.com/vmware-tanzu/vm-operator/pkg/lib" "github.com/vmware-tanzu/vm-operator/pkg/manager" "github.com/vmware-tanzu/vm-operator/webhooks" @@ -265,6 +268,12 @@ func main() { return err } + if lib.IsVMServiceV1Alpha2FSSEnabled() { + if err := addConversionWebhooksToManager(ctx, mgr); err != nil { + return err + } + } + return webhooks.AddToManager(ctx, mgr) } @@ -296,6 +305,57 @@ func main() { } } +// addConversionWebhooksToManager adds the ctrl-runtime managed webhooks. We just use these +// for version conversion, but they can also do mutation and validation webhook callbacks +// instead of our separate webhooks. +func addConversionWebhooksToManager(_ *context.ControllerManagerContext, mgr ctrlmgr.Manager) error { + if err := (&v1alpha1.VirtualMachine{}).SetupWebhookWithManager(mgr); err != nil { + return err + } + if err := (&v1alpha1.VirtualMachineClass{}).SetupWebhookWithManager(mgr); err != nil { + return err + } + if err := (&v1alpha1.VirtualMachineImage{}).SetupWebhookWithManager(mgr); err != nil { + return err + } + if err := (&v1alpha1.ClusterVirtualMachineImage{}).SetupWebhookWithManager(mgr); err != nil { + return err + } + if err := (&v1alpha1.VirtualMachinePublishRequest{}).SetupWebhookWithManager(mgr); err != nil { + return err + } + if err := (&v1alpha1.VirtualMachineService{}).SetupWebhookWithManager(mgr); err != nil { + return err + } + if err := (&v1alpha1.VirtualMachineSetResourcePolicy{}).SetupWebhookWithManager(mgr); err != nil { + return err + } + + if err := (&v1alpha2.VirtualMachine{}).SetupWebhookWithManager(mgr); err != nil { + return err + } + if err := (&v1alpha2.VirtualMachineClass{}).SetupWebhookWithManager(mgr); err != nil { + return err + } + if err := (&v1alpha2.VirtualMachineImage{}).SetupWebhookWithManager(mgr); err != nil { + return err + } + if err := (&v1alpha2.ClusterVirtualMachineImage{}).SetupWebhookWithManager(mgr); err != nil { + return err + } + if err := (&v1alpha2.VirtualMachinePublishRequest{}).SetupWebhookWithManager(mgr); err != nil { + return err + } + if err := (&v1alpha2.VirtualMachineService{}).SetupWebhookWithManager(mgr); err != nil { + return err + } + if err := (&v1alpha2.VirtualMachineSetResourcePolicy{}).SetupWebhookWithManager(mgr); err != nil { + return err + } + + return nil +} + func configureWebhookTLS(opts *webhook.Options) { tlsCfgFunc := func(cfg *tls.Config) { cfg.MinVersion = tls.VersionTLS12 diff --git a/pkg/vmprovider/providers/vsphere2/contentlibrary/content_library_provider.go b/pkg/vmprovider/providers/vsphere2/contentlibrary/content_library_provider.go index 4a0ed0e41..be2ff212d 100644 --- a/pkg/vmprovider/providers/vsphere2/contentlibrary/content_library_provider.go +++ b/pkg/vmprovider/providers/vsphere2/contentlibrary/content_library_provider.go @@ -338,7 +338,7 @@ func (cs *provider) generateDownloadURLForLibraryItem( // Content library api to prepare a file for download guarantees eventual end state of either // ERROR or PREPARED in order to avoid posting too many requests to the api. var fileURL string - err = wait.PollImmediateInfinite(cs.retryInterval, func() (bool, error) { + err = wait.PollUntilContextCancel(ctx, cs.retryInterval, true, func(_ context.Context) (bool, error) { downloadSessResp, err := cs.libMgr.GetLibraryItemDownloadSession(ctx, sessionID) if err != nil { return false, err diff --git a/pkg/vmprovider/providers/vsphere2/network/network.go b/pkg/vmprovider/providers/vsphere2/network/network.go index 0e4a6799f..e93627ac6 100644 --- a/pkg/vmprovider/providers/vsphere2/network/network.go +++ b/pkg/vmprovider/providers/vsphere2/network/network.go @@ -6,7 +6,6 @@ package network import ( goctx "context" - "errors" "fmt" "net" "strings" @@ -343,7 +342,7 @@ func waitForReadyNetworkInterface( netIfKey := types.NamespacedName{Namespace: vmCtx.VM.Namespace, Name: name} // TODO: Watch() this type instead. - err := wait.PollImmediate(retryInterval, RetryTimeout, func() (bool, error) { + err := wait.PollUntilContextTimeout(vmCtx, retryInterval, RetryTimeout, true, func(_ goctx.Context) (bool, error) { if err := client.Get(vmCtx, netIfKey, netIf); err != nil { return false, ctrlruntime.IgnoreNotFound(err) } @@ -353,7 +352,7 @@ func waitForReadyNetworkInterface( }) if err != nil { - if errors.Is(err, wait.ErrWaitTimeout) { + if wait.Interrupted(err) { // Try to return a more meaningful error when timed out. if cond := findNetOPCondition(netIf, netopv1alpha1.NetworkInterfaceFailure); cond != nil && cond.Status == corev1.ConditionTrue { return nil, fmt.Errorf("network interface failure: %s - %s", cond.Reason, cond.Message) @@ -505,7 +504,7 @@ func waitForReadyNCPNetworkInterface( vnetIfKey := types.NamespacedName{Namespace: vmCtx.VM.Namespace, Name: name} // TODO: Watch() this type instead. - err := wait.PollImmediate(retryInterval, RetryTimeout, func() (bool, error) { + err := wait.PollUntilContextTimeout(vmCtx, retryInterval, RetryTimeout, true, func(_ goctx.Context) (bool, error) { if err := client.Get(vmCtx, vnetIfKey, vnetIf); err != nil { return false, ctrlruntime.IgnoreNotFound(err) } @@ -521,7 +520,7 @@ func waitForReadyNCPNetworkInterface( }) if err != nil { - if errors.Is(err, wait.ErrWaitTimeout) { + if wait.Interrupted(err) { // Try to return a more meaningful error when timed out. for _, cond := range vnetIf.Status.Conditions { if strings.Contains(cond.Type, "Ready") && !strings.Contains(cond.Status, "True") { diff --git a/pkg/vmprovider/providers/vsphere2/vmprovider_vm.go b/pkg/vmprovider/providers/vsphere2/vmprovider_vm.go index 3aa7b64e9..e142f6ada 100644 --- a/pkg/vmprovider/providers/vsphere2/vmprovider_vm.go +++ b/pkg/vmprovider/providers/vsphere2/vmprovider_vm.go @@ -171,6 +171,12 @@ func (vs *vSphereVMProvider) PublishVirtualMachine( return itemID, nil } +// BackupVirtualMachine backs up the VM data required for restore. +func (vs *vSphereVMProvider) BackupVirtualMachine(ctx goctx.Context, vm *vmopv1.VirtualMachine) error { + // TODO + return nil +} + func (vs *vSphereVMProvider) GetVirtualMachineGuestHeartbeat( ctx goctx.Context, vm *vmopv1.VirtualMachine) (vmopv1.GuestHeartbeatStatus, error) { diff --git a/test/builder/fake.go b/test/builder/fake.go index 7aab65f77..5764ceac1 100644 --- a/test/builder/fake.go +++ b/test/builder/fake.go @@ -42,13 +42,15 @@ func KnownObjectTypes() []client.Object { &v1alpha2.VirtualMachineService{}, &v1alpha1.VirtualMachineClass{}, &v1alpha2.VirtualMachineClass{}, - &cnsv1alpha1.CnsNodeVmAttachment{}, &v1alpha1.VirtualMachinePublishRequest{}, &v1alpha2.VirtualMachinePublishRequest{}, &v1alpha1.ClusterVirtualMachineImage{}, &v1alpha2.ClusterVirtualMachineImage{}, &v1alpha1.VirtualMachineImage{}, &v1alpha2.VirtualMachineImage{}, + &cnsv1alpha1.CnsNodeVmAttachment{}, + &ncpv1alpha1.VirtualNetworkInterface{}, + &netopv1alpha1.NetworkInterface{}, } }