Skip to content

Commit

Permalink
Reconcile machine power state annotation
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexander Demichev committed May 12, 2020
1 parent b5b340a commit 5c34c0a
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 2 deletions.
24 changes: 24 additions & 0 deletions pkg/controller/vsphere/reconciler.go
Expand Up @@ -233,6 +233,11 @@ func (r *Reconciler) reconcileMachineWithCloudState(vm *virtualMachine, taskRef
return err
}

klog.V(3).Infof("%v: reconciling powerstate annotation", r.machine.GetName())
if err := r.reconcilePowerStateAnnontation(vm); err != nil {
return err
}

return setProviderStatus(taskRef, conditionSuccess(), r.machineScope, vm)
}

Expand Down Expand Up @@ -333,6 +338,25 @@ func (r *Reconciler) reconcileNetwork(vm *virtualMachine) error {
return nil
}

func (r *Reconciler) reconcilePowerStateAnnontation(vm *virtualMachine) error {
if vm == nil {
return errors.New("provided VM is nil")
}

// This can return an error if machine is being deleted
powerState, err := vm.getPowerState()
if err != nil {
return err
}

if r.machine.Annotations == nil {
r.machine.Annotations = map[string]string{}
}
r.machine.Annotations[machinecontroller.MachineInstanceStateAnnotationName] = string(powerState)

return nil
}

func validateMachine(machine machinev1.Machine) error {
if machine.Labels[machinev1.MachineClusterIDLabel] == "" {
return machinecontroller.InvalidMachineConfiguration("%v: missing %q label", machine.GetName(), machinev1.MachineClusterIDLabel)
Expand Down
84 changes: 82 additions & 2 deletions pkg/controller/vsphere/reconciler_test.go
Expand Up @@ -24,6 +24,7 @@ import (

machinev1 "github.com/openshift/machine-api-operator/pkg/apis/machine/v1beta1"
vsphereapi "github.com/openshift/machine-api-operator/pkg/apis/vsphereprovider/v1beta1"
machinecontroller "github.com/openshift/machine-api-operator/pkg/controller/machine"
"github.com/openshift/machine-api-operator/pkg/controller/vsphere/session"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/simulator"
Expand All @@ -40,6 +41,8 @@ import (
_ "github.com/vmware/govmomi/vapi/simulator"
)

const poweredOnState = "poweredOn"

func initSimulator(t *testing.T) (*simulator.Model, *session.Session, *simulator.Server) {
model := simulator.VPX()
model.Host = 0
Expand Down Expand Up @@ -289,7 +292,7 @@ func TestTaskIsFinished(t *testing.T) {

obj := simulator.Map.Any("VirtualMachine").(*simulator.VirtualMachine)
// Validate VM is powered on
if obj.Runtime.PowerState != "poweredOn" {
if obj.Runtime.PowerState != poweredOnState {
t.Fatal(obj.Runtime.PowerState)
}
vm := object.NewVirtualMachine(session.Client.Client, obj.Reference())
Expand Down Expand Up @@ -1456,10 +1459,87 @@ func TestReconcileMachineWithCloudState(t *testing.T) {
}

if expectedProviderID != *reconciler.machine.Spec.ProviderID {
t.Errorf("Expected: %s, got: %s", expectedProviderID, *reconciler.machine.Spec.ProviderID)
t.Errorf("Expected providerId: %s, got: %s", expectedProviderID, *reconciler.machine.Spec.ProviderID)
}

actualPowerState := reconciler.machine.Annotations[machinecontroller.MachineInstanceStateAnnotationName]
if poweredOnState != actualPowerState {
t.Errorf("Expected power state annotation: %s, got: %s", poweredOnState, actualPowerState)
}

// TODO: add zones and networks
}

func TestReconcilePowerStateAnnontation(t *testing.T) {
model, session, server := initSimulator(t)
defer model.Remove()
defer server.Close()

simulatorVM := simulator.Map.Any("VirtualMachine").(*simulator.VirtualMachine)
managedObjRef := simulatorVM.VirtualMachine.Reference()
vmObj := object.NewVirtualMachine(session.Client.Client, simulatorVM.Reference())
_, err := vmObj.PowerOn(context.Background())
if err != nil {
t.Fatal(err)
}

vm := &virtualMachine{
Context: context.Background(),
Obj: object.NewVirtualMachine(session.Client.Client, managedObjRef),
Ref: managedObjRef,
}

testCases := []struct {
name string
vm *virtualMachine
expectedError bool
}{
{
name: "Succefully reconcile annotation",
vm: vm,
},
{
name: "Error on nil VM",
vm: nil,
expectedError: true,
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
r := &Reconciler{
machineScope: &machineScope{
machine: &machinev1.Machine{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{},
},
},
},
}

err := r.reconcilePowerStateAnnontation(tc.vm)

if tc.expectedError {
if err == nil {
t.Errorf("reconcilePowerStateAnnontation is expected to return an error")
}

actualPowerState := r.machine.Annotations[machinecontroller.MachineInstanceStateAnnotationName]
if actualPowerState != "" {
t.Errorf("Expected power state annotation to be empty, got: %s", actualPowerState)
}
} else {
if err != nil {
t.Errorf("reconcilePowerStateAnnontation is not expected to return an error")
}

actualPowerState := r.machine.Annotations[machinecontroller.MachineInstanceStateAnnotationName]
if poweredOnState != actualPowerState {
t.Errorf("Expected power state annotation: %s, got: %s", poweredOnState, actualPowerState)
}
}
})
}
}

// See https://github.com/vmware/govmomi/blob/master/simulator/example_extend_test.go#L33:6 for extending behaviour example

0 comments on commit 5c34c0a

Please sign in to comment.