Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🌱 Allow SRM to change network of a registered VM for test failover #803

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions pkg/backup/api/backup_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

package api

// GroupName specifies the group name for VM operator.
const GroupName = "vmoperator.vmware.com"

// ToPersistentVolumeAccessModes returns a string slice from a slice of T.
// This is useful when converting a slice of corev1.PersistentVolumeAccessMode
// to a string slice.
Expand Down Expand Up @@ -105,4 +108,20 @@ const (
// specifying this key, backup/restore and/or disaster recovery solutions are
// responsible to register the VM with Supervisor.
DisableAutoRegistrationExtraConfigKey = "vmservice.virtualmachine.disableAutomaticRegistration"

// TestFailoverLabelKey label signifies that a VirtualMachine is going through
// a test recovery plan scenario. Typically, this involves failing over a VM
// to a dedicated temporary network so as to not exhaust, and cause IP address
// collisions with the production network. This label on a VirtualMachine
// custom resource allows vendors to change the VM's network interface to
// connect to the test network after the VM is registered post a failover.
//
// VM operator does not support mutable networks, so this label allows only
// select vendors (e.g., SRM) to support recovery plan test workflows while we
// build support for true network mutability.
//
// The value of this label does not matter. Its presence is considered a
// sufficient evidence to indicate that the virtual machine is going through
// test fail-over.
TestFailoverLabelKey = "virtualmachine." + GroupName + "/test-failover"
)
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (

vmopv1 "github.com/vmware-tanzu/vm-operator/api/v1alpha3"
"github.com/vmware-tanzu/vm-operator/api/v1alpha3/sysprep"
backupapi "github.com/vmware-tanzu/vm-operator/pkg/backup/api"
"github.com/vmware-tanzu/vm-operator/pkg/builder"
pkgcfg "github.com/vmware-tanzu/vm-operator/pkg/config"
"github.com/vmware-tanzu/vm-operator/pkg/constants"
Expand Down Expand Up @@ -1195,6 +1196,12 @@ func (v validator) validateImmutableNetwork(ctx *pkgctx.WebhookRequestContext, v
return append(allErrs, field.Forbidden(p.Child("interfaces"), "network interfaces cannot be added or removed"))
}

// Skip comparing interfaces if this is a test fail-over to allow vendors to
// connect network each interface to test network.
if _, ok := vm.Labels[backupapi.TestFailoverLabelKey]; ok {
return allErrs
}

for i := range newInterfaces {
newInterface := &newInterfaces[i]
oldInterface := &oldInterfaces[i]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/vmware-tanzu/vm-operator/api/v1alpha3/common"
"github.com/vmware-tanzu/vm-operator/api/v1alpha3/sysprep"
topologyv1 "github.com/vmware-tanzu/vm-operator/external/tanzu-topology/api/v1alpha1"
backupapi "github.com/vmware-tanzu/vm-operator/pkg/backup/api"
pkgbuilder "github.com/vmware-tanzu/vm-operator/pkg/builder"
pkgcfg "github.com/vmware-tanzu/vm-operator/pkg/config"
"github.com/vmware-tanzu/vm-operator/pkg/constants"
Expand Down Expand Up @@ -3015,6 +3016,52 @@ func unitTestsValidateUpdate() {
`spec.network.interfaces: Forbidden: network interfaces cannot be added or removed`),
},
),

Entry("allow interface name change if VM has test failover label",
testParams{
setup: func(ctx *unitValidatingWebhookContext) {
if ctx.oldVM.Labels == nil {
ctx.oldVM.Labels = make(map[string]string)
}
ctx.oldVM.Labels[backupapi.TestFailoverLabelKey] = "foo"

ctx.oldVM.Spec.Network = &vmopv1.VirtualMachineNetworkSpec{
Interfaces: []vmopv1.VirtualMachineNetworkInterfaceSpec{
{
Name: "eth0",
},
},
}

ctx.vm = ctx.oldVM.DeepCopy()
ctx.vm.Spec.Network.Interfaces[0].Name = "eth100"
},
expectAllowed: true,
},
),
Entry("allow changing network interface network if VM has test failover label",
testParams{
setup: func(ctx *unitValidatingWebhookContext) {
if ctx.oldVM.Labels == nil {
ctx.oldVM.Labels = make(map[string]string)
}
ctx.oldVM.Labels[backupapi.TestFailoverLabelKey] = "foo"

ctx.oldVM.Spec.Network = &vmopv1.VirtualMachineNetworkSpec{
Interfaces: []vmopv1.VirtualMachineNetworkInterfaceSpec{
{
Name: "eth0",
Network: &common.PartialObjectRef{Name: "my-network"},
},
},
}

ctx.vm = ctx.oldVM.DeepCopy()
ctx.vm.Spec.Network.Interfaces[0].Network.Name = "my-other-network"
},
expectAllowed: true,
},
),
)

DescribeTable("update network - host and domain names", doTest,
Expand Down