From 3e1918b02a4c003d650dd68041cef9c6da935ce2 Mon Sep 17 00:00:00 2001 From: Kirk Brauer Date: Thu, 25 Sep 2025 10:06:14 -0400 Subject: [PATCH 1/2] Add exporter status reporting --- proto/jumpstarter/client/v1/client.proto | 12 ++------ proto/jumpstarter/v1/common.proto | 27 ++++++++++++++++++ proto/jumpstarter/v1/jumpstarter.proto | 36 +++++++++++++++++++++++- 3 files changed, 64 insertions(+), 11 deletions(-) create mode 100644 proto/jumpstarter/v1/common.proto diff --git a/proto/jumpstarter/client/v1/client.proto b/proto/jumpstarter/client/v1/client.proto index 38416a2..1684d8e 100644 --- a/proto/jumpstarter/client/v1/client.proto +++ b/proto/jumpstarter/client/v1/client.proto @@ -18,6 +18,7 @@ import "google/protobuf/empty.proto"; import "google/protobuf/field_mask.proto"; import "google/protobuf/timestamp.proto"; import "jumpstarter/v1/kubernetes.proto"; +import "jumpstarter/v1/common.proto"; service ClientService { rpc GetExporter(GetExporterRequest) returns (Exporter) { @@ -68,16 +69,7 @@ message Exporter { string name = 1 [(google.api.field_behavior) = IDENTIFIER]; map labels = 2; bool online = 3 [(google.api.field_behavior) = OUTPUT_ONLY, deprecated = true]; - ExporterStatus status = 4 [(google.api.field_behavior) = OUTPUT_ONLY]; -} - -enum ExporterStatus { - EXPORTER_STATUS_UNSPECIFIED = 0; // Unspecified exporter status - EXPORTER_STATUS_OFFLINE = 1; // Exporter is offline - EXPORTER_STATUS_AVAILABLE = 2; // Exporter is available to be leased - EXPORTER_STATUS_BEFORE_LEASE_HOOK = 3; // Exporter is executing before lease hook(s) - EXPORTER_STATUS_LEASE_READY = 4; // Exporter is leased and ready to accept commands - EXPORTER_STATUS_AFTER_LEASE_HOOK = 5; // Exporter is executing after lease hook(s) + jumpstarter.v1.ExporterStatus status = 4 [(google.api.field_behavior) = OUTPUT_ONLY]; } message Lease { diff --git a/proto/jumpstarter/v1/common.proto b/proto/jumpstarter/v1/common.proto new file mode 100644 index 0000000..69b3246 --- /dev/null +++ b/proto/jumpstarter/v1/common.proto @@ -0,0 +1,27 @@ +// Copyright 2024 The Jumpstarter Authors + +syntax = "proto3"; + +package jumpstarter.v1; + +// Shared types used across multiple Jumpstarter services + +// Exporter status information +enum ExporterStatus { + EXPORTER_STATUS_UNSPECIFIED = 0; // Unspecified exporter status + EXPORTER_STATUS_OFFLINE = 1; // Exporter is offline + EXPORTER_STATUS_AVAILABLE = 2; // Exporter is available to be leased + EXPORTER_STATUS_BEFORE_LEASE_HOOK = 3; // Exporter is executing before lease hook(s) + EXPORTER_STATUS_LEASE_READY = 4; // Exporter is leased and ready to accept commands + EXPORTER_STATUS_AFTER_LEASE_HOOK = 5; // Exporter is executing after lease hook(s) + EXPORTER_STATUS_ERROR = 6; // Exporter is in an error state and cannot accept leases +} + +// Source of log stream messages +enum LogSource { + LOG_SOURCE_UNSPECIFIED = 0; // Unspecified log source + LOG_SOURCE_DRIVER = 1; // Driver/device logs + LOG_SOURCE_BEFORE_LEASE_HOOK = 2; // beforeLease hook execution logs + LOG_SOURCE_AFTER_LEASE_HOOK = 3; // afterLease hook execution logs + LOG_SOURCE_SYSTEM = 4; // System/exporter logs +} \ No newline at end of file diff --git a/proto/jumpstarter/v1/jumpstarter.proto b/proto/jumpstarter/v1/jumpstarter.proto index 6f344e5..66fb977 100644 --- a/proto/jumpstarter/v1/jumpstarter.proto +++ b/proto/jumpstarter/v1/jumpstarter.proto @@ -9,6 +9,7 @@ import "google/protobuf/empty.proto"; import "google/protobuf/struct.proto"; import "google/protobuf/timestamp.proto"; import "jumpstarter/v1/kubernetes.proto"; +import "jumpstarter/v1/common.proto"; // A service where a exporter can connect to make itself available service ControllerService { @@ -21,6 +22,10 @@ service ControllerService { // has been invalidated rpc Unregister(UnregisterRequest) returns (UnregisterResponse); + // Exporter status report + // Allows exporters to report their own status + rpc ReportStatus(ReportStatusRequest) returns (ReportStatusResponse); + // Exporter listening // Returns stream tokens for accepting incoming client connections rpc Listen(ListenRequest) returns (stream ListenResponse); @@ -59,7 +64,7 @@ message RegisterRequest { } message DriverInstanceReport { - string uuid = 1; // a unique id within the expoter + string uuid = 1; // a unique id within the exporter optional string parent_uuid = 2; // optional, if device has a parent device map labels = 3; } @@ -109,6 +114,13 @@ message AuditStreamRequest { string message = 4; } +message ReportStatusRequest { + ExporterStatus status = 1; + optional string status_message = 2; // Optional human-readable status detail +} + +message ReportStatusResponse {} + // A service a exporter can share locally to be used without a server // Channel/Call credentials are used to authenticate the client, and routing to the right exporter service ExporterService { @@ -118,6 +130,12 @@ service ExporterService { rpc StreamingDriverCall(StreamingDriverCallRequest) returns (stream StreamingDriverCallResponse); rpc LogStream(google.protobuf.Empty) returns (stream LogStreamResponse); rpc Reset(ResetRequest) returns (ResetResponse); + + // Get current exporter status + rpc GetStatus(GetStatusRequest) returns (GetStatusResponse); + + // Stream status updates + rpc StatusStream(StatusStreamRequest) returns (stream StatusStreamResponse); } message GetReportResponse { @@ -163,6 +181,7 @@ message LogStreamResponse { string uuid = 1; string severity = 2; string message = 3; + optional LogSource source = 4; // New optional field } message ResetRequest {} @@ -201,3 +220,18 @@ message ListLeasesRequest {} message ListLeasesResponse { repeated string names = 1; } + +message GetStatusRequest {} + +message GetStatusResponse { + ExporterStatus status = 1; + optional string status_message = 2; +} + +message StatusStreamRequest {} + +message StatusStreamResponse { + ExporterStatus status = 1; + optional string status_message = 2; + optional google.protobuf.Timestamp timestamp = 3; +} From 9cbdaea7a8567a5cb3f08762ae6febe370bbb31b Mon Sep 17 00:00:00 2001 From: Kirk Brauer Date: Thu, 25 Sep 2025 13:40:40 -0400 Subject: [PATCH 2/2] Add individual failure states for before/after lease hooks, switch to status polling --- proto/jumpstarter/v1/common.proto | 15 ++++++++------- proto/jumpstarter/v1/jumpstarter.proto | 21 ++++----------------- 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/proto/jumpstarter/v1/common.proto b/proto/jumpstarter/v1/common.proto index 69b3246..8748522 100644 --- a/proto/jumpstarter/v1/common.proto +++ b/proto/jumpstarter/v1/common.proto @@ -8,13 +8,14 @@ package jumpstarter.v1; // Exporter status information enum ExporterStatus { - EXPORTER_STATUS_UNSPECIFIED = 0; // Unspecified exporter status - EXPORTER_STATUS_OFFLINE = 1; // Exporter is offline - EXPORTER_STATUS_AVAILABLE = 2; // Exporter is available to be leased - EXPORTER_STATUS_BEFORE_LEASE_HOOK = 3; // Exporter is executing before lease hook(s) - EXPORTER_STATUS_LEASE_READY = 4; // Exporter is leased and ready to accept commands - EXPORTER_STATUS_AFTER_LEASE_HOOK = 5; // Exporter is executing after lease hook(s) - EXPORTER_STATUS_ERROR = 6; // Exporter is in an error state and cannot accept leases + EXPORTER_STATUS_UNSPECIFIED = 0; // Unspecified exporter status + EXPORTER_STATUS_OFFLINE = 1; // Exporter is offline + EXPORTER_STATUS_AVAILABLE = 2; // Exporter is available to be leased + EXPORTER_STATUS_BEFORE_LEASE_HOOK = 3; // Exporter is executing before lease hook(s) + EXPORTER_STATUS_LEASE_READY = 4; // Exporter is leased and ready to accept commands + EXPORTER_STATUS_AFTER_LEASE_HOOK = 5; // Exporter is executing after lease hook(s) + EXPORTER_STATUS_BEFORE_LEASE_HOOK_FAILED = 6; // Exporter before lease hook failed + EXPORTER_STATUS_AFTER_LEASE_HOOK_FAILED = 7; // Exporter after lease hook failed } // Source of log stream messages diff --git a/proto/jumpstarter/v1/jumpstarter.proto b/proto/jumpstarter/v1/jumpstarter.proto index 66fb977..ee40225 100644 --- a/proto/jumpstarter/v1/jumpstarter.proto +++ b/proto/jumpstarter/v1/jumpstarter.proto @@ -23,7 +23,7 @@ service ControllerService { rpc Unregister(UnregisterRequest) returns (UnregisterResponse); // Exporter status report - // Allows exporters to report their own status + // Allows exporters to report their own status to the controller rpc ReportStatus(ReportStatusRequest) returns (ReportStatusResponse); // Exporter listening @@ -116,7 +116,7 @@ message AuditStreamRequest { message ReportStatusRequest { ExporterStatus status = 1; - optional string status_message = 2; // Optional human-readable status detail + optional string message = 2; // Optional human-readable status message } message ReportStatusResponse {} @@ -130,12 +130,7 @@ service ExporterService { rpc StreamingDriverCall(StreamingDriverCallRequest) returns (stream StreamingDriverCallResponse); rpc LogStream(google.protobuf.Empty) returns (stream LogStreamResponse); rpc Reset(ResetRequest) returns (ResetResponse); - - // Get current exporter status rpc GetStatus(GetStatusRequest) returns (GetStatusResponse); - - // Stream status updates - rpc StatusStream(StatusStreamRequest) returns (stream StatusStreamResponse); } message GetReportResponse { @@ -225,13 +220,5 @@ message GetStatusRequest {} message GetStatusResponse { ExporterStatus status = 1; - optional string status_message = 2; -} - -message StatusStreamRequest {} - -message StatusStreamResponse { - ExporterStatus status = 1; - optional string status_message = 2; - optional google.protobuf.Timestamp timestamp = 3; -} + optional string message = 2; +} \ No newline at end of file