blob: 2c2a6554aa5cbc2335048b977eb73715062c929a [file] [log] [blame]
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +02001package shepherd
2
3import (
4 "context"
5 "fmt"
6 "net/netip"
7
8 "source.monogon.dev/cloud/bmaas/bmdb"
9 "source.monogon.dev/cloud/bmaas/bmdb/model"
10)
11
12var ErrMachineNotFound = fmt.Errorf("machine not found")
13var ErrNotImplemented = fmt.Errorf("not implemented")
14
15// ProviderID is an opaque unique identifier for a machine within a single
16// provider instance. It is generated by the Provider and usually the same
17// as the ID of the machine within the system that the Provider managed.
18// The Shepherd (and BMaaS in general) requires these IDs to be unique
19// within a provider and stable.
20type ProviderID string
21
22const InvalidProviderID ProviderID = "invalid"
23
24// IsValid reports whether the ProviderID is valid.
25func (p ProviderID) IsValid() bool {
26 return p != InvalidProviderID
27}
28
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +010029// Availability defines the availability state according to the provider.
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020030// See the different states for more information.
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +010031type Availability int
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020032
33const (
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +010034 // AvailabilityUndefined is used as a placeholder to prevent that the default
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020035 // value can create any type of bad behaviour.
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +010036 AvailabilityUndefined Availability = iota
37 // AvailabilityPossiblyUsed defines the state where a machine is possibly used,
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020038 // this is a state for use in stateless providers where the shepherd has
39 // to check against the bmdb if Machine.ID is already provisioned or not.
40 // These machines must have a valid ID and Addr.
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +010041 AvailabilityPossiblyUsed
42 // AvailabilityKnownUnused defines the state where a machine is know to be free,
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020043 // e.g. a hardware reservation at equinix. These machines may not have an
44 // ID or Addr.
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +010045 AvailabilityKnownUnused
46 // AvailabilityKnownUsed defines the state where a machine is known to be used,
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020047 // e.g. a deployed machine that is in use. These machines must have a
48 // valid ID and Addr.
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +010049 AvailabilityKnownUsed
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020050)
51
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +010052func (a Availability) String() string {
53 switch a {
54 case AvailabilityUndefined:
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020055 return "Undefined"
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +010056 case AvailabilityKnownUnused:
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020057 return "KnownUnused"
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +010058 case AvailabilityKnownUsed:
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020059 return "KnownUsed"
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +010060 case AvailabilityPossiblyUsed:
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020061 return "PossiblyUsed"
62 default:
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +010063 return fmt.Sprintf("<invalid value %d>", a)
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020064 }
65}
66
67type Machine interface {
68 // ID returns the provider id, see ProviderID for more information.
69 ID() ProviderID
70 // Addr returns the machines ip address that is reachable from the
71 // shepherd. It is used to connect to the machine via SSH to execute
72 // all takeover tasks, etc.
73 Addr() netip.Addr
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +010074 // Availability returns the availability of the machine.
75 Availability() Availability
Tim Windelschmidtfdd87ab2023-12-07 18:03:21 +010076 // Failed should return true if the machine is in a failed state and
77 // should be ignored if there are inconsistencies between the provider
78 // and BMDB.
79 Failed() bool
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020080}
81
82type CreateMachineRequest struct {
83 // UnusedMachine resembles a machine to use as deployment target.
84 UnusedMachine Machine
85}
86
87// Provider is the interface that is used to abstract the interaction between
88// the shepherd and machine providers like Equinix. All methods inside this
89// interface must not be called concurrently.
90type Provider interface {
91 // ListMachines returns all existing machines for a provider. Machines
92 // that are still in the state of being created by CreateMachine should
93 // not be returned.
94 ListMachines(context.Context) ([]Machine, error)
95
96 // GetMachine returns an existing machine for a provider. Machines
97 // that are still in the state of being created by CreateMachine should
98 // not be returned. If a there are no machines found after these filters
99 // an error should be returned.
100 GetMachine(context.Context, ProviderID) (Machine, error)
101
102 // CreateMachine creates a new machine with the given parameters and
103 // returns the created instance. The provider is required to create the
104 // entry into the machine table and MachineProvided tag. If there are no
105 // more machines avaiable, an error should be returned.
106 CreateMachine(context.Context, *bmdb.Session, CreateMachineRequest) (Machine, error)
107
108 // Type returns the value that represents this provider inside the database.
109 Type() model.Provider
110}
111
112type Recoverer interface {
113 Provider
114
115 // RebootMachine tries to bring a machine back from the dead by e.g. rebooting
116 RebootMachine(context.Context, ProviderID) error
117
118 // ReinstallMachine should reinstall the given machine and if the provider
119 // does not support reinstallation, the function should return an error
120 // stating this. If reinstalled, the installed tag should be updated to
121 // allow the reconcile loop to restart the takeover process.
122 ReinstallMachine(context.Context, ProviderID) error
123}