From 83a1315f7417e0ce5a8b6df1f9e5469e58e44550 Mon Sep 17 00:00:00 2001 From: Stefan Majer Date: Mon, 20 Apr 2026 10:55:48 +0200 Subject: [PATCH 1/3] Migrate reserved to tainted machines --- .../internal/datastore/machine_integration_test.go | 8 ++++---- cmd/metal-api/internal/metal/machine.go | 9 +++++++-- cmd/metal-api/internal/service/machine-service_test.go | 4 ++-- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/cmd/metal-api/internal/datastore/machine_integration_test.go b/cmd/metal-api/internal/datastore/machine_integration_test.go index e9203d97..cd6f93aa 100644 --- a/cmd/metal-api/internal/datastore/machine_integration_test.go +++ b/cmd/metal-api/internal/datastore/machine_integration_test.go @@ -614,16 +614,16 @@ func TestRethinkStore_SearchMachines(t *testing.T) { { name: "search by state value reserved", q: &MachineSearchQuery{ - StateValue: pointer.Pointer(string(metal.ReservedState)), + StateValue: pointer.Pointer(string(metal.TaintedState)), }, mock: []*metal.Machine{ {Base: metal.Base{ID: "1"}, State: metal.MachineState{Value: metal.AvailableState}}, - {Base: metal.Base{ID: "2"}, State: metal.MachineState{Value: metal.ReservedState}}, + {Base: metal.Base{ID: "2"}, State: metal.MachineState{Value: metal.TaintedState}}, {Base: metal.Base{ID: "3"}, State: metal.MachineState{Value: metal.AvailableState}}, {Base: metal.Base{ID: "4"}, State: metal.MachineState{Value: metal.LockedState}}, }, want: []*metal.Machine{ - tt.defaultBody(&metal.Machine{Base: metal.Base{ID: "2"}, State: metal.MachineState{Value: metal.ReservedState}}), + tt.defaultBody(&metal.Machine{Base: metal.Base{ID: "2"}, State: metal.MachineState{Value: metal.TaintedState}}), }, wantErr: nil, }, @@ -634,7 +634,7 @@ func TestRethinkStore_SearchMachines(t *testing.T) { }, mock: []*metal.Machine{ {Base: metal.Base{ID: "1"}, State: metal.MachineState{Value: metal.AvailableState}}, - {Base: metal.Base{ID: "2"}, State: metal.MachineState{Value: metal.ReservedState}}, + {Base: metal.Base{ID: "2"}, State: metal.MachineState{Value: metal.TaintedState}}, {Base: metal.Base{ID: "3"}, State: metal.MachineState{Value: metal.AvailableState}}, {Base: metal.Base{ID: "4"}, State: metal.MachineState{Value: metal.LockedState}}, }, diff --git a/cmd/metal-api/internal/metal/machine.go b/cmd/metal-api/internal/metal/machine.go index c1dab748..2c67eb1a 100644 --- a/cmd/metal-api/internal/metal/machine.go +++ b/cmd/metal-api/internal/metal/machine.go @@ -29,7 +29,10 @@ const ( // AvailableState describes a machine state where a machine is available for an allocation AvailableState MState = "" // ReservedState describes a machine state where a machine is not being considered for random allocation + // Deprecated: use TaintedState instead ReservedState MState = "RESERVED" + // TaintedState describes a machine state where a machine is not being considered for random allocation + TaintedState MState = "TAINTED" // LockedState describes a machine state where a machine cannot be deleted or allocated anymore LockedState MState = "LOCKED" ) @@ -43,7 +46,7 @@ var ( var ( // AllStates contains all possible values of a machine state - AllStates = []MState{AvailableState, ReservedState, LockedState} + AllStates = []MState{AvailableState, ReservedState, TaintedState, LockedState} // AllRoles contains all possible values of a role AllRoles = map[Role]bool{ RoleMachine: true, @@ -67,7 +70,9 @@ func MachineStateFrom(name string) (MState, error) { case string(AvailableState): return AvailableState, nil case string(ReservedState): - return ReservedState, nil + return TaintedState, nil + case string(TaintedState): + return TaintedState, nil case string(LockedState): return LockedState, nil default: diff --git a/cmd/metal-api/internal/service/machine-service_test.go b/cmd/metal-api/internal/service/machine-service_test.go index 44e3e11d..39dc6bdc 100644 --- a/cmd/metal-api/internal/service/machine-service_test.go +++ b/cmd/metal-api/internal/service/machine-service_test.go @@ -233,7 +233,7 @@ func TestSetMachineState(t *testing.T) { container := restful.NewContainer().Add(machineservice) stateRequest := v1.MachineState{ - Value: string(metal.ReservedState), + Value: string(metal.TaintedState), Description: "blubber", } js, err := json.Marshal(stateRequest) @@ -253,7 +253,7 @@ func TestSetMachineState(t *testing.T) { require.NoError(t, err) require.Equal(t, "1", result.ID) - require.Equal(t, string(metal.ReservedState), result.State.Value) + require.Equal(t, string(metal.TaintedState), result.State.Value) require.Equal(t, "blubber", result.State.Description) require.Equal(t, "anonymous@metal-stack.io", result.State.Issuer) } From bafab811146387af1898c793b5afae95a34eff81 Mon Sep 17 00:00:00 2001 From: Stefan Majer Date: Mon, 20 Apr 2026 10:55:59 +0200 Subject: [PATCH 2/3] Migrate reserved to tainted machines --- .../datastore/machine_integration_test.go | 2 +- .../010_machine_reserved_tainted.go | 37 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 cmd/metal-api/internal/datastore/migrations/010_machine_reserved_tainted.go diff --git a/cmd/metal-api/internal/datastore/machine_integration_test.go b/cmd/metal-api/internal/datastore/machine_integration_test.go index cd6f93aa..28c066fb 100644 --- a/cmd/metal-api/internal/datastore/machine_integration_test.go +++ b/cmd/metal-api/internal/datastore/machine_integration_test.go @@ -612,7 +612,7 @@ func TestRethinkStore_SearchMachines(t *testing.T) { wantErr: nil, }, { - name: "search by state value reserved", + name: "search by state value tainted", q: &MachineSearchQuery{ StateValue: pointer.Pointer(string(metal.TaintedState)), }, diff --git a/cmd/metal-api/internal/datastore/migrations/010_machine_reserved_tainted.go b/cmd/metal-api/internal/datastore/migrations/010_machine_reserved_tainted.go new file mode 100644 index 00000000..61382fb6 --- /dev/null +++ b/cmd/metal-api/internal/datastore/migrations/010_machine_reserved_tainted.go @@ -0,0 +1,37 @@ +package migrations + +import ( + r "gopkg.in/rethinkdb/rethinkdb-go.v6" + + "github.com/metal-stack/metal-api/cmd/metal-api/internal/datastore" + "github.com/metal-stack/metal-api/cmd/metal-api/internal/metal" +) + +func init() { + datastore.MustRegisterMigration(datastore.Migration{ + Name: "convert reserved machine to tainted machines", + Version: 10, + Up: func(db *r.Term, session r.QueryExecutor, rs *datastore.RethinkStore) error { + ms, err := rs.ListMachines() + if err != nil { + return err + } + + for i := range ms { + old := ms[i] + + n := old + + if n.State.Value == metal.ReservedState { + n.State.Value = metal.TaintedState + } + + err = rs.UpdateMachine(&old, &n) + if err != nil { + return err + } + } + return nil + }, + }) +} From 4e1b8a5aa6c5b32a96e5ab29cbfe1000fef36f9f Mon Sep 17 00:00:00 2001 From: Stefan Majer Date: Wed, 22 Apr 2026 12:59:01 +0200 Subject: [PATCH 3/3] Fix --- cmd/metal-api/internal/datastore/machine_integration_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/metal-api/internal/datastore/machine_integration_test.go b/cmd/metal-api/internal/datastore/machine_integration_test.go index 28c066fb..96d7b42a 100644 --- a/cmd/metal-api/internal/datastore/machine_integration_test.go +++ b/cmd/metal-api/internal/datastore/machine_integration_test.go @@ -614,7 +614,7 @@ func TestRethinkStore_SearchMachines(t *testing.T) { { name: "search by state value tainted", q: &MachineSearchQuery{ - StateValue: pointer.Pointer(string(metal.TaintedState)), + StateValue: new(string(metal.TaintedState)), }, mock: []*metal.Machine{ {Base: metal.Base{ID: "1"}, State: metal.MachineState{Value: metal.AvailableState}},