Skip to content
Open
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
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ require (
github.com/onsi/ginkgo v1.16.5
github.com/onsi/gomega v1.36.3
github.com/pkg/errors v0.9.1
github.com/spectrocloud/maas-client-go v0.1.4-beta1
github.com/spectrocloud/maas-client-go v0.1.4-beta2
Copy link
Copy Markdown
Contributor

@AmitSahastra AmitSahastra Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reason to go for beta2 naming instead of updating minor version?

Also, maas client go release looks wrong, its a public repo we can avoid PCP taging there.
v0.1.4-beta2: Merge pull request #44 from spectrocloud/PCP-6208

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. I'll add a new feature in maas-client-go and update the minor version

github.com/spf13/pflag v1.0.6
k8s.io/api v0.32.3
k8s.io/apiextensions-apiserver v0.32.3
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,8 @@ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/spectrocloud/maas-client-go v0.1.4-beta1 h1:adYeve0oaYjiPuNnogMzw8LN9VenQK/iwNOO74H4lKE=
github.com/spectrocloud/maas-client-go v0.1.4-beta1/go.mod h1:LSxLlmaNCmkaldtysbp7Beq/O2wptBb6qE5iKj+Y7Lw=
github.com/spectrocloud/maas-client-go v0.1.4-beta2 h1:xiJ7UydMvFwI7CjsDbU50+oTZia0v8LuibiK/CMbyjo=
github.com/spectrocloud/maas-client-go v0.1.4-beta2/go.mod h1:LSxLlmaNCmkaldtysbp7Beq/O2wptBb6qE5iKj+Y7Lw=
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
Expand Down
84 changes: 84 additions & 0 deletions pkg/maas/client/mock/clienset_mock.go

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

1 change: 1 addition & 0 deletions pkg/maas/dns/dns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ func (f *fakeClientSet) Spaces() maasclient.Spaces { retur
func (f *fakeClientSet) Users() maasclient.Users { return nil }
func (f *fakeClientSet) Zones() maasclient.Zones { return nil }
func (f *fakeClientSet) SSHKeys() maasclient.SSHKeys { return nil }
func (f *fakeClientSet) Subnets() maasclient.Subnets { return nil }
func (f *fakeClientSet) VMHosts() maasclient.VMHosts { return nil }

// fakeIPAddress satisfies maasclient.IPAddress for tests
Expand Down
29 changes: 24 additions & 5 deletions pkg/maas/machine/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ import (

// Service manages the MaaS machine
var (
ErrBrokenMachine = errors.New("broken machine encountered")
ErrVMComposing = errors.New("vm composing/commissioning")
reHostID = regexp.MustCompile(`host (\d+)`)
reMachineID = regexp.MustCompile(`machine[s]? ([a-z0-9]{4,6})`)
ErrBrokenMachine = errors.New("broken machine encountered")
ErrVMComposing = errors.New("vm composing/commissioning")
reHostID = regexp.MustCompile(`host (\d+)`)
reMachineID = regexp.MustCompile(`machine[s]? ([a-z0-9]{4,6})`)
)

const (
Expand Down Expand Up @@ -497,6 +497,26 @@ func (s *Service) PrepareLXDVM(ctx context.Context) (*infrav1beta1.Machine, erro
}
}

// Before composing: check if the static IP is already allocated in MAAS
if s.scope.IsControlPlane() {
if staticIPToCheck := s.scope.GetStaticIP(); staticIPToCheck != "" {
s.scope.Info("Checking static IP availability before VM compose", "ip", staticIPToCheck)
existingIP, ipErr := s.maasClient.IPAddresses().GetAll(ctx, staticIPToCheck)
if ipErr == nil {
if ifaces := existingIP.InterfaceSet(); len(ifaces) > 0 {
return nil, fmt.Errorf("static IP %s is already in use (allocated to %d interface(s)); cannot compose VM — will retry when IP is available", staticIPToCheck, len(ifaces))
}
// IP exists with no interfaces — stale/floating allocation; release before compose
s.scope.Info("Static IP has stale allocation with no interfaces; releasing before compose", "ip", staticIPToCheck)
if releaseErr := s.maasClient.IPAddresses().Release(ctx, staticIPToCheck); releaseErr != nil {
return nil, fmt.Errorf("static IP %s has a stale allocation that could not be released before compose: %w", staticIPToCheck, releaseErr)
}
s.scope.Info("Released stale IP allocation, proceeding with compose", "ip", staticIPToCheck)
}
// ipErr != nil means IP not found in MAAS — available, proceed normally
}
}

// Create the VM on the selected host
m, err := selectedHost.Composer().Compose(ctx, params)
if err != nil {
Expand Down Expand Up @@ -827,7 +847,6 @@ func (s *Service) setMachineStaticIP(systemID string, config *infrav1beta1.Stati
// Special handling for Commissioning state: skip static IP configuration to avoid blocking commissioning
if machineState == "Commissioning" {
s.scope.Info("Machine is commissioning, skipping static IP configuration to avoid interfering with commissioning process. Will configure after commissioning completes", "systemID", systemID)
// Return error to requeue - static IP will be configured after commissioning completes
return fmt.Errorf("machine is commissioning, static IP configuration will be retried after commissioning completes")
}
Comment on lines 847 to 851
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding a unit test for this commissioning-path in setMachineStaticIP. Right now there are no tests asserting that when MAAS reports State() == "Commissioning", the method returns ErrMachineCommissioning (and that the error remains detectable via errors.Is after any wrapping). This is an important behavioral contract because the controller reconciliation flow depends on it for requeue behavior.

Copilot uses AI. Check for mistakes.

Expand Down