| // Copyright The Monogon Project Authors. |
| // SPDX-License-Identifier: Apache-2.0 |
| |
| package shepherd |
| |
| import ( |
| "context" |
| "fmt" |
| "net/netip" |
| |
| "source.monogon.dev/cloud/bmaas/bmdb" |
| "source.monogon.dev/cloud/bmaas/bmdb/model" |
| ) |
| |
| var ErrMachineNotFound = fmt.Errorf("machine not found") |
| var ErrNotImplemented = fmt.Errorf("not implemented") |
| |
| // ProviderID is an opaque unique identifier for a machine within a single |
| // provider instance. It is generated by the Provider and usually the same |
| // as the ID of the machine within the system that the Provider managed. |
| // The Shepherd (and BMaaS in general) requires these IDs to be unique |
| // within a provider and stable. |
| type ProviderID string |
| |
| const InvalidProviderID ProviderID = "invalid" |
| |
| // IsValid reports whether the ProviderID is valid. |
| func (p ProviderID) IsValid() bool { |
| return p != InvalidProviderID |
| } |
| |
| // Availability defines the availability state according to the provider. |
| // See the different states for more information. |
| type Availability int |
| |
| const ( |
| // AvailabilityUndefined is used as a placeholder to prevent that the default |
| // value can create any type of bad behaviour. |
| AvailabilityUndefined Availability = iota |
| // AvailabilityPossiblyUsed defines the state where a machine is possibly used, |
| // this is a state for use in stateless providers where the shepherd has |
| // to check against the bmdb if Machine.ID is already provisioned or not. |
| // These machines must have a valid ID and Addr. |
| AvailabilityPossiblyUsed |
| // AvailabilityKnownUnused defines the state where a machine is know to be free, |
| // e.g. a hardware reservation at equinix. These machines may not have an |
| // ID or Addr. |
| AvailabilityKnownUnused |
| // AvailabilityKnownUsed defines the state where a machine is known to be used, |
| // e.g. a deployed machine that is in use. These machines must have a |
| // valid ID and Addr. |
| AvailabilityKnownUsed |
| ) |
| |
| func (a Availability) String() string { |
| switch a { |
| case AvailabilityUndefined: |
| return "Undefined" |
| case AvailabilityKnownUnused: |
| return "KnownUnused" |
| case AvailabilityKnownUsed: |
| return "KnownUsed" |
| case AvailabilityPossiblyUsed: |
| return "PossiblyUsed" |
| default: |
| return fmt.Sprintf("<invalid value %d>", a) |
| } |
| } |
| |
| type Machine interface { |
| // ID returns the provider id, see ProviderID for more information. |
| ID() ProviderID |
| // Addr returns the machines ip address that is reachable from the |
| // shepherd. It is used to connect to the machine via SSH to execute |
| // all takeover tasks, etc. |
| Addr() netip.Addr |
| // Availability returns the availability of the machine. |
| Availability() Availability |
| // Failed should return true if the machine is in a failed state and |
| // should be ignored if there are inconsistencies between the provider |
| // and BMDB. |
| Failed() bool |
| } |
| |
| type CreateMachineRequest struct { |
| // UnusedMachine resembles a machine to use as deployment target. |
| UnusedMachine Machine |
| } |
| |
| // Provider is the interface that is used to abstract the interaction between |
| // the shepherd and machine providers like Equinix. All methods inside this |
| // interface must not be called concurrently. |
| type Provider interface { |
| // ListMachines returns all existing machines for a provider. Machines |
| // that are still in the state of being created by CreateMachine should |
| // not be returned. |
| ListMachines(context.Context) ([]Machine, error) |
| |
| // GetMachine returns an existing machine for a provider. Machines |
| // that are still in the state of being created by CreateMachine should |
| // not be returned. If a there are no machines found after these filters |
| // an error should be returned. |
| GetMachine(context.Context, ProviderID) (Machine, error) |
| |
| // CreateMachine creates a new machine with the given parameters and |
| // returns the created instance. The provider is required to create the |
| // entry into the machine table and MachineProvided tag. If there are no |
| // more machines avaiable, an error should be returned. |
| CreateMachine(context.Context, *bmdb.Session, CreateMachineRequest) (Machine, error) |
| |
| // Type returns the value that represents this provider inside the database. |
| Type() model.Provider |
| } |
| |
| type Recoverer interface { |
| Provider |
| |
| // RebootMachine tries to bring a machine back from the dead by e.g. rebooting |
| RebootMachine(context.Context, ProviderID) error |
| |
| // ReinstallMachine should reinstall the given machine and if the provider |
| // does not support reinstallation, the function should return an error |
| // stating this. If reinstalled, the installed tag should be updated to |
| // allow the reconcile loop to restart the takeover process. |
| ReinstallMachine(context.Context, ProviderID) error |
| } |