cloud: split shepherd up
Change-Id: I8e386d9eaaf17543743e1e8a37a8d71426910d59
Reviewed-on: https://review.monogon.dev/c/monogon/+/2213
Reviewed-by: Serge Bazanski <serge@monogon.tech>
Tested-by: Jenkins CI
diff --git a/cloud/shepherd/shepherd.go b/cloud/shepherd/shepherd.go
new file mode 100644
index 0000000..3504eb7
--- /dev/null
+++ b/cloud/shepherd/shepherd.go
@@ -0,0 +1,119 @@
+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
+}
+
+// State defines in which state the machine is.
+// See the different states for more information.
+type State int
+
+const (
+ // StateUndefined is used as a placeholder to prevent that the default
+ // value can create any type of bad behaviour.
+ StateUndefined State = iota
+ // StatePossiblyUsed 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.
+ StatePossiblyUsed
+ // StateKnownUnused 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.
+ StateKnownUnused
+ // StateKnownUsed 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.
+ StateKnownUsed
+)
+
+func (s State) String() string {
+ switch s {
+ case StateUndefined:
+ return "Undefined"
+ case StateKnownUnused:
+ return "KnownUnused"
+ case StateKnownUsed:
+ return "KnownUsed"
+ case StatePossiblyUsed:
+ return "PossiblyUsed"
+ default:
+ return fmt.Sprintf("<invalid value %d>", s)
+ }
+}
+
+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
+ // State returns the state in which the machine is
+ State() State
+}
+
+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
+}