Skip to content

Commit

Permalink
Support toggling provisioning checks (#290)
Browse files Browse the repository at this point in the history
* Support toggling provisioning checks

Signed-off-by: ekarlso <endre.karlson@gmail.com>

* Generate descriptions

Signed-off-by: ekarlso <endre.karlson@gmail.com>

* Fix tests

Signed-off-by: ekarlso <endre.karlson@gmail.com>

---------

Signed-off-by: ekarlso <endre.karlson@gmail.com>
  • Loading branch information
ekarlso authored Oct 13, 2024
1 parent 7d9b12b commit 0d011ce
Show file tree
Hide file tree
Showing 13 changed files with 320 additions and 10 deletions.
12 changes: 12 additions & 0 deletions api/v1alpha1/proxmoxmachine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@ const (
IPV6Format = "v6"
)

// ProxmoxMachineChecks defines possibibles checks to skip.
type ProxmoxMachineChecks struct {
// Skip checking CloudInit which can be very useful for specific Operating Systems like TalOS
// +optional
SkipCloudInitStatus *bool `json:"skipCloudInitStatus,omitempty"`
// Skip checking QEMU Agent readiness which can be very useful for specific Operating Systems like TalOS
// +optional
SkipQemuGuestAgent *bool `json:"skipQemuGuestAgent,omitempty"`
}

// ProxmoxMachineSpec defines the desired state of a ProxmoxMachine.
type ProxmoxMachineSpec struct {
VirtualMachineCloneSpec `json:",inline"`
Expand Down Expand Up @@ -90,6 +100,8 @@ type ProxmoxMachineSpec struct {
// Network is the network configuration for this machine's VM.
// +optional
Network *NetworkSpec `json:"network,omitempty"`

Checks *ProxmoxMachineChecks `json:"checks,omitempty"`
}

// Storage is the physical storage on the node.
Expand Down
30 changes: 30 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,20 @@ spec:
description: ProxmoxMachineSpec defines the desired state of
a ProxmoxMachine.
properties:
checks:
description: ProxmoxMachineChecks defines possibibles checks
to skip.
properties:
skipCloudInitStatus:
description: Skip checking CloudInit which can be very
useful for specific Operating Systems like TalOS
type: boolean
skipQemuGuestAgent:
description: Skip checking QEMU Agent readiness which
can be very useful for specific Operating Systems
like TalOS
type: boolean
type: object
description:
description: Description for the new VM.
type: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,21 @@ spec:
description: ProxmoxMachineSpec defines the desired
state of a ProxmoxMachine.
properties:
checks:
description: ProxmoxMachineChecks defines possibibles
checks to skip.
properties:
skipCloudInitStatus:
description: Skip checking CloudInit which can
be very useful for specific Operating Systems
like TalOS
type: boolean
skipQemuGuestAgent:
description: Skip checking QEMU Agent readiness
which can be very useful for specific Operating
Systems like TalOS
type: boolean
type: object
description:
description: Description for the new VM.
type: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,18 @@ spec:
spec:
description: ProxmoxMachineSpec defines the desired state of a ProxmoxMachine.
properties:
checks:
description: ProxmoxMachineChecks defines possibibles checks to skip.
properties:
skipCloudInitStatus:
description: Skip checking CloudInit which can be very useful
for specific Operating Systems like TalOS
type: boolean
skipQemuGuestAgent:
description: Skip checking QEMU Agent readiness which can be very
useful for specific Operating Systems like TalOS
type: boolean
type: object
description:
description: Description for the new VM.
type: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,20 @@ spec:
description: ProxmoxMachineSpec defines the desired state of a
ProxmoxMachine.
properties:
checks:
description: ProxmoxMachineChecks defines possibibles checks
to skip.
properties:
skipCloudInitStatus:
description: Skip checking CloudInit which can be very
useful for specific Operating Systems like TalOS
type: boolean
skipQemuGuestAgent:
description: Skip checking QEMU Agent readiness which
can be very useful for specific Operating Systems like
TalOS
type: boolean
type: object
description:
description: Description for the new VM.
type: string
Expand Down
24 changes: 16 additions & 8 deletions internal/service/vmservice/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,16 +114,24 @@ func checkCloudInitStatus(ctx context.Context, machineScope *scope.MachineScope)
return true, nil
}

if running, err := machineScope.InfraCluster.ProxmoxClient.CloudInitStatus(ctx, machineScope.VirtualMachine); err != nil || running {
if running {
return true, nil
if !machineScope.SkipQemuGuestCheck() {
if err := machineScope.InfraCluster.ProxmoxClient.QemuAgentStatus(ctx, machineScope.VirtualMachine); err != nil {
return true, errors.Wrap(err, "error waiting for agent")
}
if errors.Is(goproxmox.ErrCloudInitFailed, err) {
conditions.MarkFalse(machineScope.ProxmoxMachine, infrav1alpha1.VMProvisionedCondition, infrav1alpha1.VMProvisionFailedReason, clusterv1.ConditionSeverityError, err.Error())
machineScope.SetFailureMessage(err)
machineScope.SetFailureReason(capierrors.MachineStatusError("BootstrapFailed"))
}

if !machineScope.SkipCloudInitCheck() {
if running, err := machineScope.InfraCluster.ProxmoxClient.CloudInitStatus(ctx, machineScope.VirtualMachine); err != nil || running {
if running {
return true, nil
}
if errors.Is(goproxmox.ErrCloudInitFailed, err) {
conditions.MarkFalse(machineScope.ProxmoxMachine, infrav1alpha1.VMProvisionedCondition, infrav1alpha1.VMProvisionFailedReason, clusterv1.ConditionSeverityError, err.Error())
machineScope.SetFailureMessage(err)
machineScope.SetFailureReason(capierrors.MachineStatusError("BootstrapFailed"))
}
return false, err
}
return false, err
}

return false, nil
Expand Down
63 changes: 63 additions & 0 deletions internal/service/vmservice/vm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,67 @@ func TestReconcileVM_EverythingReady(t *testing.T) {

proxmoxClient.EXPECT().GetVM(context.Background(), "node1", int64(123)).Return(vm, nil).Once()
proxmoxClient.EXPECT().CloudInitStatus(context.Background(), vm).Return(false, nil).Once()
proxmoxClient.EXPECT().QemuAgentStatus(context.Background(), vm).Return(nil).Once()

result, err := ReconcileVM(context.Background(), machineScope)
require.NoError(t, err)
require.Equal(t, infrav1alpha1.VirtualMachineStateReady, result.State)
require.Equal(t, "10.10.10.10", machineScope.ProxmoxMachine.Status.Addresses[1].Address)
}

func TestReconcileVM_QemuAgentCheckDisabled(t *testing.T) {
machineScope, proxmoxClient, _ := setupReconcilerTest(t)
vm := newRunningVM()
machineScope.SetVirtualMachineID(int64(vm.VMID))
machineScope.ProxmoxMachine.Status.IPAddresses = map[string]infrav1alpha1.IPAddress{infrav1alpha1.DefaultNetworkDevice: {IPV4: "10.10.10.10"}}
machineScope.ProxmoxMachine.Status.BootstrapDataProvided = ptr.To(true)
machineScope.ProxmoxMachine.Status.Ready = true
machineScope.ProxmoxMachine.Spec.Checks = &infrav1alpha1.ProxmoxMachineChecks{
SkipQemuGuestAgent: ptr.To(true),
}

proxmoxClient.EXPECT().GetVM(context.Background(), "node1", int64(123)).Return(vm, nil).Once()
// proxmoxClient.EXPECT().CloudInitStatus(context.Background(), vm).Return(false, nil).Once()

result, err := ReconcileVM(context.Background(), machineScope)
require.NoError(t, err)
require.Equal(t, infrav1alpha1.VirtualMachineStateReady, result.State)
require.Equal(t, "10.10.10.10", machineScope.ProxmoxMachine.Status.Addresses[1].Address)
}

func TestReconcileVM_CloudInitCheckDisabled(t *testing.T) {
machineScope, proxmoxClient, _ := setupReconcilerTest(t)
vm := newRunningVM()
machineScope.SetVirtualMachineID(int64(vm.VMID))
machineScope.ProxmoxMachine.Status.IPAddresses = map[string]infrav1alpha1.IPAddress{infrav1alpha1.DefaultNetworkDevice: {IPV4: "10.10.10.10"}}
machineScope.ProxmoxMachine.Status.BootstrapDataProvided = ptr.To(true)
machineScope.ProxmoxMachine.Status.Ready = true
machineScope.ProxmoxMachine.Spec.Checks = &infrav1alpha1.ProxmoxMachineChecks{
SkipCloudInitStatus: ptr.To(true),
}

proxmoxClient.EXPECT().GetVM(context.Background(), "node1", int64(123)).Return(vm, nil).Once()
proxmoxClient.EXPECT().QemuAgentStatus(context.Background(), vm).Return(nil)

result, err := ReconcileVM(context.Background(), machineScope)
require.NoError(t, err)
require.Equal(t, infrav1alpha1.VirtualMachineStateReady, result.State)
require.Equal(t, "10.10.10.10", machineScope.ProxmoxMachine.Status.Addresses[1].Address)
}

func TestReconcileVM_InitCheckDisabled(t *testing.T) {
machineScope, proxmoxClient, _ := setupReconcilerTest(t)
vm := newRunningVM()
machineScope.SetVirtualMachineID(int64(vm.VMID))
machineScope.ProxmoxMachine.Status.IPAddresses = map[string]infrav1alpha1.IPAddress{infrav1alpha1.DefaultNetworkDevice: {IPV4: "10.10.10.10"}}
machineScope.ProxmoxMachine.Status.BootstrapDataProvided = ptr.To(true)
machineScope.ProxmoxMachine.Status.Ready = true
machineScope.ProxmoxMachine.Spec.Checks = &infrav1alpha1.ProxmoxMachineChecks{
SkipCloudInitStatus: ptr.To(true),
SkipQemuGuestAgent: ptr.To(true),
}

proxmoxClient.EXPECT().GetVM(context.Background(), "node1", int64(123)).Return(vm, nil).Once()

result, err := ReconcileVM(context.Background(), machineScope)
require.NoError(t, err)
Expand Down Expand Up @@ -323,6 +384,7 @@ func TestReconcileVM_CloudInitFailed(t *testing.T) {

proxmoxClient.EXPECT().GetVM(context.Background(), "node1", int64(123)).Return(vm, nil).Once()
proxmoxClient.EXPECT().CloudInitStatus(context.Background(), vm).Return(false, goproxmox.ErrCloudInitFailed).Once()
proxmoxClient.EXPECT().QemuAgentStatus(context.Background(), vm).Return(nil).Once()

_, err := ReconcileVM(context.Background(), machineScope)
require.Error(t, err, "unknown error")
Expand All @@ -340,6 +402,7 @@ func TestReconcileVM_CloudInitRunning(t *testing.T) {

proxmoxClient.EXPECT().GetVM(context.Background(), "node1", int64(123)).Return(vm, nil).Once()
proxmoxClient.EXPECT().CloudInitStatus(context.Background(), vm).Return(true, nil).Once()
proxmoxClient.EXPECT().QemuAgentStatus(context.Background(), vm).Return(nil).Once()

result, err := ReconcileVM(context.Background(), machineScope)
require.NoError(t, err)
Expand Down
3 changes: 2 additions & 1 deletion pkg/proxmox/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ type Client interface {
TagVM(ctx context.Context, vm *proxmox.VirtualMachine, tag string) (*proxmox.Task, error)

UnmountCloudInitISO(ctx context.Context, vm *proxmox.VirtualMachine, device string) error

CloudInitStatus(ctx context.Context, vm *proxmox.VirtualMachine) (bool, error)

QemuAgentStatus(ctx context.Context, vm *proxmox.VirtualMachine) error
}
11 changes: 10 additions & 1 deletion pkg/proxmox/goproxmox/api_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ func (c *APIClient) UnmountCloudInitISO(ctx context.Context, vm *proxmox.Virtual

// CloudInitStatus returns the cloud-init status of the VM.
func (c *APIClient) CloudInitStatus(ctx context.Context, vm *proxmox.VirtualMachine) (running bool, err error) {
if err := vm.WaitForAgent(ctx, 5); err != nil {
if err := c.QemuAgentStatus(ctx, vm); err != nil {
return false, errors.Wrap(err, "error waiting for agent")
}

Expand All @@ -300,3 +300,12 @@ func (c *APIClient) CloudInitStatus(ctx context.Context, vm *proxmox.VirtualMach

return false, nil
}

// QemuAgentStatus returns the qemu-agent status of the VM.
func (c *APIClient) QemuAgentStatus(ctx context.Context, vm *proxmox.VirtualMachine) error {
if err := vm.WaitForAgent(ctx, 5); err != nil {
return errors.Wrap(err, "error waiting for agent")
}

return nil
}
43 changes: 43 additions & 0 deletions pkg/proxmox/proxmoxtest/mock_client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions pkg/scope/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,3 +243,25 @@ func (m *MachineScope) GetBootstrapSecret(ctx context.Context, secret *corev1.Se

return m.client.Get(ctx, secretKey, secret)
}

// SkipQemuGuestCheck check whether qemu-agent status check is enabled.
func (m *MachineScope) SkipQemuGuestCheck() bool {
if m.ProxmoxMachine.Spec.Checks != nil {
return ptr.Deref(m.ProxmoxMachine.Spec.Checks.SkipQemuGuestAgent, false)
}

return false
}

// SkipCloudInitCheck check whether cloud-init status check is enabled.
func (m *MachineScope) SkipCloudInitCheck() bool {
if m.SkipQemuGuestCheck() {
return true
}

if m.ProxmoxMachine.Spec.Checks != nil {
return ptr.Deref(m.ProxmoxMachine.Spec.Checks.SkipCloudInitStatus, false)
}

return false
}
Loading

0 comments on commit 0d011ce

Please sign in to comment.