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