diff --git a/api/specs/specs.pb.go b/api/specs/specs.pb.go index 5de7e9e..17b68cc 100644 --- a/api/specs/specs.pb.go +++ b/api/specs/specs.pb.go @@ -12,6 +12,7 @@ import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" ) const ( @@ -189,6 +190,10 @@ type MachineStatusSpec struct { // // It is used to track if the machine needs to be wiped for an allocation. LastWipeId string `protobuf:"bytes,4,opt,name=last_wipe_id,json=lastWipeId,proto3" json:"last_wipe_id,omitempty"` + // LastRebootTimestamp is the timestamp of the last reboot (or power on) of the machine. + // + // It is used to track the last reboot time of the machine, and to enforce the MinRebootInterval. + LastRebootTimestamp *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=last_reboot_timestamp,json=lastRebootTimestamp,proto3" json:"last_reboot_timestamp,omitempty"` } func (x *MachineStatusSpec) Reset() { @@ -249,6 +254,13 @@ func (x *MachineStatusSpec) GetLastWipeId() string { return "" } +func (x *MachineStatusSpec) GetLastRebootTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.LastRebootTimestamp + } + return nil +} + type PowerManagement_IPMI struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -368,59 +380,66 @@ var File_specs_specs_proto protoreflect.FileDescriptor var file_specs_specs_proto_rawDesc = []byte{ 0x0a, 0x11, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x16, 0x62, 0x61, 0x72, 0x65, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x70, 0x65, 0x63, 0x73, 0x22, 0xa1, 0x02, 0x0a, 0x0f, - 0x50, 0x6f, 0x77, 0x65, 0x72, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, - 0x40, 0x0a, 0x04, 0x69, 0x70, 0x6d, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, - 0x62, 0x61, 0x72, 0x65, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x72, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2e, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x4d, 0x61, 0x6e, 0x61, - 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x49, 0x50, 0x4d, 0x49, 0x52, 0x04, 0x69, 0x70, 0x6d, - 0x69, 0x12, 0x3d, 0x0a, 0x03, 0x61, 0x70, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x70, 0x65, 0x63, 0x73, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa1, 0x02, 0x0a, + 0x0f, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x12, 0x40, 0x0a, 0x04, 0x69, 0x70, 0x6d, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x62, 0x61, 0x72, 0x65, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2e, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x4d, 0x61, 0x6e, - 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x50, 0x49, 0x52, 0x03, 0x61, 0x70, 0x69, - 0x1a, 0x6c, 0x0a, 0x04, 0x49, 0x50, 0x4d, 0x49, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x1a, 0x1f, - 0x0a, 0x03, 0x41, 0x50, 0x49, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, - 0x8d, 0x02, 0x0a, 0x11, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x53, 0x70, 0x65, 0x63, 0x12, 0x52, 0x0a, 0x10, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x6d, - 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x27, 0x2e, 0x62, 0x61, 0x72, 0x65, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x49, 0x50, 0x4d, 0x49, 0x52, 0x04, 0x69, 0x70, + 0x6d, 0x69, 0x12, 0x3d, 0x0a, 0x03, 0x61, 0x70, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2b, 0x2e, 0x62, 0x61, 0x72, 0x65, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2e, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x4d, 0x61, - 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0f, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x4d, - 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x43, 0x0a, 0x0b, 0x70, 0x6f, 0x77, - 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, - 0x2e, 0x62, 0x61, 0x72, 0x65, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, - 0x65, 0x72, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2e, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x52, 0x0a, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x3d, - 0x0a, 0x09, 0x62, 0x6f, 0x6f, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x20, 0x2e, 0x62, 0x61, 0x72, 0x65, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2e, 0x42, 0x6f, 0x6f, 0x74, 0x4d, - 0x6f, 0x64, 0x65, 0x52, 0x08, 0x62, 0x6f, 0x6f, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x20, 0x0a, - 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x77, 0x69, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x61, 0x73, 0x74, 0x57, 0x69, 0x70, 0x65, 0x49, 0x64, 0x2a, - 0x6d, 0x0a, 0x08, 0x42, 0x6f, 0x6f, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x42, - 0x4f, 0x4f, 0x54, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, - 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x42, 0x4f, 0x4f, 0x54, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, - 0x41, 0x47, 0x45, 0x4e, 0x54, 0x5f, 0x50, 0x58, 0x45, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x42, - 0x4f, 0x4f, 0x54, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x54, 0x41, 0x4c, 0x4f, 0x53, 0x5f, 0x50, - 0x58, 0x45, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x42, 0x4f, 0x4f, 0x54, 0x5f, 0x4d, 0x4f, 0x44, - 0x45, 0x5f, 0x54, 0x41, 0x4c, 0x4f, 0x53, 0x5f, 0x44, 0x49, 0x53, 0x4b, 0x10, 0x03, 0x2a, 0x4e, - 0x0a, 0x0a, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x17, 0x0a, 0x13, - 0x50, 0x4f, 0x57, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, - 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x50, 0x4f, 0x57, 0x45, 0x52, 0x5f, 0x53, - 0x54, 0x41, 0x54, 0x45, 0x5f, 0x4f, 0x46, 0x46, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x50, 0x4f, - 0x57, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x4f, 0x4e, 0x10, 0x02, 0x42, 0x40, - 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x69, 0x64, - 0x65, 0x72, 0x6f, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x6f, 0x6d, 0x6e, 0x69, 0x2d, 0x69, 0x6e, 0x66, - 0x72, 0x61, 0x2d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2d, 0x62, 0x61, 0x72, 0x65, - 0x2d, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x73, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x50, 0x49, 0x52, 0x03, 0x61, 0x70, + 0x69, 0x1a, 0x6c, 0x0a, 0x04, 0x49, 0x50, 0x4d, 0x49, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x1a, + 0x1f, 0x0a, 0x03, 0x41, 0x50, 0x49, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x22, 0xdd, 0x02, 0x0a, 0x11, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x53, 0x70, 0x65, 0x63, 0x12, 0x52, 0x0a, 0x10, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x5f, + 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x27, 0x2e, 0x62, 0x61, 0x72, 0x65, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2e, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x4d, + 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0f, 0x70, 0x6f, 0x77, 0x65, 0x72, + 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x43, 0x0a, 0x0b, 0x70, 0x6f, + 0x77, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x22, 0x2e, 0x62, 0x61, 0x72, 0x65, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2e, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x52, 0x0a, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, + 0x3d, 0x0a, 0x09, 0x62, 0x6f, 0x6f, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x62, 0x61, 0x72, 0x65, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x70, 0x65, 0x63, 0x73, 0x2e, 0x42, 0x6f, 0x6f, 0x74, + 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x08, 0x62, 0x6f, 0x6f, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x20, + 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x77, 0x69, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x61, 0x73, 0x74, 0x57, 0x69, 0x70, 0x65, 0x49, 0x64, + 0x12, 0x4e, 0x0a, 0x15, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x62, 0x6f, 0x6f, 0x74, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x13, 0x6c, 0x61, 0x73, + 0x74, 0x52, 0x65, 0x62, 0x6f, 0x6f, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x2a, 0x6d, 0x0a, 0x08, 0x42, 0x6f, 0x6f, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x15, 0x0a, 0x11, + 0x42, 0x4f, 0x4f, 0x54, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, + 0x4e, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x42, 0x4f, 0x4f, 0x54, 0x5f, 0x4d, 0x4f, 0x44, 0x45, + 0x5f, 0x41, 0x47, 0x45, 0x4e, 0x54, 0x5f, 0x50, 0x58, 0x45, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, + 0x42, 0x4f, 0x4f, 0x54, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x54, 0x41, 0x4c, 0x4f, 0x53, 0x5f, + 0x50, 0x58, 0x45, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x42, 0x4f, 0x4f, 0x54, 0x5f, 0x4d, 0x4f, + 0x44, 0x45, 0x5f, 0x54, 0x41, 0x4c, 0x4f, 0x53, 0x5f, 0x44, 0x49, 0x53, 0x4b, 0x10, 0x03, 0x2a, + 0x4e, 0x0a, 0x0a, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x17, 0x0a, + 0x13, 0x50, 0x4f, 0x57, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x4b, + 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x50, 0x4f, 0x57, 0x45, 0x52, 0x5f, + 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x4f, 0x46, 0x46, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x50, + 0x4f, 0x57, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x4f, 0x4e, 0x10, 0x02, 0x42, + 0x40, 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x69, + 0x64, 0x65, 0x72, 0x6f, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x6f, 0x6d, 0x6e, 0x69, 0x2d, 0x69, 0x6e, + 0x66, 0x72, 0x61, 0x2d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2d, 0x62, 0x61, 0x72, + 0x65, 0x2d, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x70, 0x65, 0x63, + 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -438,12 +457,13 @@ func file_specs_specs_proto_rawDescGZIP() []byte { var file_specs_specs_proto_enumTypes = make([]protoimpl.EnumInfo, 2) var file_specs_specs_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_specs_specs_proto_goTypes = []any{ - (BootMode)(0), // 0: baremetalproviderspecs.BootMode - (PowerState)(0), // 1: baremetalproviderspecs.PowerState - (*PowerManagement)(nil), // 2: baremetalproviderspecs.PowerManagement - (*MachineStatusSpec)(nil), // 3: baremetalproviderspecs.MachineStatusSpec - (*PowerManagement_IPMI)(nil), // 4: baremetalproviderspecs.PowerManagement.IPMI - (*PowerManagement_API)(nil), // 5: baremetalproviderspecs.PowerManagement.API + (BootMode)(0), // 0: baremetalproviderspecs.BootMode + (PowerState)(0), // 1: baremetalproviderspecs.PowerState + (*PowerManagement)(nil), // 2: baremetalproviderspecs.PowerManagement + (*MachineStatusSpec)(nil), // 3: baremetalproviderspecs.MachineStatusSpec + (*PowerManagement_IPMI)(nil), // 4: baremetalproviderspecs.PowerManagement.IPMI + (*PowerManagement_API)(nil), // 5: baremetalproviderspecs.PowerManagement.API + (*timestamppb.Timestamp)(nil), // 6: google.protobuf.Timestamp } var file_specs_specs_proto_depIdxs = []int32{ 4, // 0: baremetalproviderspecs.PowerManagement.ipmi:type_name -> baremetalproviderspecs.PowerManagement.IPMI @@ -451,11 +471,12 @@ var file_specs_specs_proto_depIdxs = []int32{ 2, // 2: baremetalproviderspecs.MachineStatusSpec.power_management:type_name -> baremetalproviderspecs.PowerManagement 1, // 3: baremetalproviderspecs.MachineStatusSpec.power_state:type_name -> baremetalproviderspecs.PowerState 0, // 4: baremetalproviderspecs.MachineStatusSpec.boot_mode:type_name -> baremetalproviderspecs.BootMode - 5, // [5:5] is the sub-list for method output_type - 5, // [5:5] is the sub-list for method input_type - 5, // [5:5] is the sub-list for extension type_name - 5, // [5:5] is the sub-list for extension extendee - 0, // [0:5] is the sub-list for field type_name + 6, // 5: baremetalproviderspecs.MachineStatusSpec.last_reboot_timestamp:type_name -> google.protobuf.Timestamp + 6, // [6:6] is the sub-list for method output_type + 6, // [6:6] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name } func init() { file_specs_specs_proto_init() } diff --git a/api/specs/specs.proto b/api/specs/specs.proto index 7af2a5b..85ecaff 100644 --- a/api/specs/specs.proto +++ b/api/specs/specs.proto @@ -4,6 +4,8 @@ package baremetalproviderspecs; option go_package = "github.com/siderolabs/omni-infra-provider-bare-metal/api/specs"; +import "google/protobuf/timestamp.proto"; + message PowerManagement { message IPMI { string address = 1; @@ -46,4 +48,9 @@ message MachineStatusSpec { // // It is used to track if the machine needs to be wiped for an allocation. string last_wipe_id = 4; + + // LastRebootTimestamp is the timestamp of the last reboot (or power on) of the machine. + // + // It is used to track the last reboot time of the machine, and to enforce the MinRebootInterval. + google.protobuf.Timestamp last_reboot_timestamp = 5; } diff --git a/api/specs/specs_vtproto.pb.go b/api/specs/specs_vtproto.pb.go index 22ac619..df292c1 100644 --- a/api/specs/specs_vtproto.pb.go +++ b/api/specs/specs_vtproto.pb.go @@ -9,8 +9,10 @@ import ( io "io" protohelpers "github.com/planetscale/vtprotobuf/protohelpers" + timestamppb1 "github.com/planetscale/vtprotobuf/types/known/timestamppb" proto "google.golang.org/protobuf/proto" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" ) const ( @@ -84,6 +86,7 @@ func (m *MachineStatusSpec) CloneVT() *MachineStatusSpec { r.PowerState = m.PowerState r.BootMode = m.BootMode r.LastWipeId = m.LastWipeId + r.LastRebootTimestamp = (*timestamppb.Timestamp)((*timestamppb1.Timestamp)(m.LastRebootTimestamp).CloneVT()) if len(m.unknownFields) > 0 { r.unknownFields = make([]byte, len(m.unknownFields)) copy(r.unknownFields, m.unknownFields) @@ -182,6 +185,9 @@ func (this *MachineStatusSpec) EqualVT(that *MachineStatusSpec) bool { if this.LastWipeId != that.LastWipeId { return false } + if !(*timestamppb1.Timestamp)(this.LastRebootTimestamp).EqualVT((*timestamppb1.Timestamp)(that.LastRebootTimestamp)) { + return false + } return string(this.unknownFields) == string(that.unknownFields) } @@ -374,6 +380,16 @@ func (m *MachineStatusSpec) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.LastRebootTimestamp != nil { + size, err := (*timestamppb1.Timestamp)(m.LastRebootTimestamp).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x2a + } if len(m.LastWipeId) > 0 { i -= len(m.LastWipeId) copy(dAtA[i:], m.LastWipeId) @@ -481,6 +497,10 @@ func (m *MachineStatusSpec) SizeVT() (n int) { if l > 0 { n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) } + if m.LastRebootTimestamp != nil { + l = (*timestamppb1.Timestamp)(m.LastRebootTimestamp).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } n += len(m.unknownFields) return n } @@ -992,6 +1012,42 @@ func (m *MachineStatusSpec) UnmarshalVT(dAtA []byte) error { } m.LastWipeId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastRebootTimestamp", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.LastRebootTimestamp == nil { + m.LastRebootTimestamp = ×tamppb.Timestamp{} + } + if err := (*timestamppb1.Timestamp)(m.LastRebootTimestamp).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) diff --git a/cmd/provider/main.go b/cmd/provider/main.go index 0741dce..c2a76b9 100644 --- a/cmd/provider/main.go +++ b/cmd/provider/main.go @@ -135,6 +135,8 @@ func init() { "Comma separated list of key=value pairs to be set to the machine. Example: key1=value1,key2,key3=value3") rootCmd.Flags().BoolVar(&providerOptions.InsecureSkipTLSVerify, "insecure-skip-tls-verify", provider.DefaultOptions.InsecureSkipTLSVerify, "Skip TLS verification when connecting to the Omni API.") + rootCmd.Flags().DurationVar(&providerOptions.MinRebootInterval, "min-reboot-interval", provider.DefaultOptions.MinRebootInterval, + "the minimum interval between reboots of the machine issued by the provider. This is to prevent the provider from issuing reboots too frequently.") if constants.IsDebugBuild { rootCmd.Flags().BoolVar(&providerOptions.ClearState, "clear-state", provider.DefaultOptions.ClearState, "Clear the state of the provider on startup.") diff --git a/hack/test/integration.sh b/hack/test/integration.sh index 0902ecf..1bfe1d9 100755 --- a/hack/test/integration.sh +++ b/hack/test/integration.sh @@ -182,6 +182,7 @@ docker run -d --network host \ --agent-test-mode \ --api-power-mgmt-state-dir=/api-power-mgmt-state \ --ipmi-pxe-boot-mode=bios \ + --min-reboot-interval=1m \ --debug docker logs -f provider & diff --git a/internal/provider/controllers/infra_machine_status.go b/internal/provider/controllers/infra_machine_status.go index cc1fe41..8b753c9 100644 --- a/internal/provider/controllers/infra_machine_status.go +++ b/internal/provider/controllers/infra_machine_status.go @@ -23,6 +23,7 @@ import ( "go.uber.org/zap" "google.golang.org/grpc/codes" grpcstatus "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/timestamppb" "github.com/siderolabs/omni-infra-provider-bare-metal/api/specs" "github.com/siderolabs/omni-infra-provider-bare-metal/internal/provider/baremetal" @@ -53,13 +54,16 @@ type APIPowerManager interface { type InfraMachineController = qtransform.QController[*infra.Machine, *infra.MachineStatus] // NewInfraMachineController initializes InfraMachineController. -func NewInfraMachineController(agentService AgentService, apiPowerManager APIPowerManager, state state.State, pxeBootMode pxe.BootMode, requeueInterval time.Duration) *InfraMachineController { +func NewInfraMachineController(agentService AgentService, apiPowerManager APIPowerManager, state state.State, pxeBootMode pxe.BootMode, + requeueInterval, minRebootInterval time.Duration, +) *InfraMachineController { helper := &infraMachineControllerHelper{ - agentService: agentService, - apiPowerManager: apiPowerManager, - state: state, - pxeBootMode: pxeBootMode, - requeueInterval: requeueInterval, + agentService: agentService, + apiPowerManager: apiPowerManager, + state: state, + pxeBootMode: pxeBootMode, + requeueInterval: requeueInterval, + minRebootInterval: minRebootInterval, } return qtransform.NewQController( @@ -89,11 +93,12 @@ func NewInfraMachineController(agentService AgentService, apiPowerManager APIPow } type infraMachineControllerHelper struct { - agentService AgentService - apiPowerManager APIPowerManager - state state.State - pxeBootMode pxe.BootMode - requeueInterval time.Duration + agentService AgentService + apiPowerManager APIPowerManager + state state.State + pxeBootMode pxe.BootMode + requeueInterval time.Duration + minRebootInterval time.Duration } func (h *infraMachineControllerHelper) transform(ctx context.Context, reader controller.Reader, logger *zap.Logger, @@ -302,6 +307,17 @@ func (h *infraMachineControllerHelper) ensureReboot(ctx context.Context, status ctx, cancel := context.WithTimeout(ctx, 10*time.Minute) defer cancel() + now := time.Now() + lastRebootTimestamp := status.TypedSpec().Value.LastRebootTimestamp.AsTime() + + elapsed := now.Sub(lastRebootTimestamp) + + if elapsed < h.minRebootInterval { + logger.Debug("machine was rebooted recently, requeue without issuing a reboot", zap.Duration("elapsed", elapsed)) + + return controller.NewRequeueInterval(h.minRebootInterval - elapsed + time.Second) + } + var powerClient power.Client powerClient, err := power.GetClient(status.TypedSpec().Value.PowerManagement) @@ -319,9 +335,17 @@ func (h *infraMachineControllerHelper) ensureReboot(ctx context.Context, status return err } + if _, err = machinestatus.Modify(ctx, h.state, status.Metadata().ID(), func(status *baremetal.MachineStatus) error { + status.TypedSpec().Value.LastRebootTimestamp = timestamppb.New(now) + + return nil + }); err != nil { + return err + } + logger.Info("rebooted machine, requeue") - return controller.NewRequeueInterval(h.requeueInterval) + return controller.NewRequeueInterval(h.minRebootInterval + time.Second) } // ensurePowerManagement makes sure that the power management for the machine is initialized if it hasn't been done yet. diff --git a/internal/provider/options.go b/internal/provider/options.go index 4f80282..8d3869d 100644 --- a/internal/provider/options.go +++ b/internal/provider/options.go @@ -5,6 +5,8 @@ package provider import ( + "time" + "github.com/siderolabs/omni-infra-provider-bare-metal/internal/provider/ipxe" "github.com/siderolabs/omni-infra-provider-bare-metal/internal/provider/power/pxe" ) @@ -32,6 +34,8 @@ type Options struct { UseLocalBootAssets bool ClearState bool WipeWithZeroes bool + + MinRebootInterval time.Duration } // DefaultOptions returns the default provider options. @@ -44,4 +48,5 @@ var DefaultOptions = Options{ BootFromDiskMethod: string(ipxe.BootIPXEExit), IPMIPXEBootMode: string(pxe.BootModeUEFI), APIPort: 50042, + MinRebootInterval: 5 * time.Minute, } diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 1812451..29e452b 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -141,7 +141,7 @@ func (p *Provider) Run(ctx context.Context) error { // todo: enable if we re-enable reverse tunnel on Omni: https://github.com/siderolabs/omni/pull/746 // reverseTunnel := tunnel.New(omniState, omniAPIClient, p.logger.With(zap.String("component", "reverse_tunnel"))) - infraMachineController := controllers.NewInfraMachineController(agentService, apiPowerManager, omniState, pxeBootMode, 1*time.Minute) + infraMachineController := controllers.NewInfraMachineController(agentService, apiPowerManager, omniState, pxeBootMode, 1*time.Minute, p.options.MinRebootInterval) if err = cosiRuntime.RegisterQController(infraMachineController); err != nil { return fmt.Errorf("failed to register controller: %w", err)