@@ -36,8 +36,35 @@ service AgentControl {
3636 rpc GetWorkload (GetWorkloadRequest ) returns (GetWorkloadResponse );
3737 rpc GetClusterSummary (GetClusterSummaryRequest ) returns (GetClusterSummaryResponse );
3838
39+ // Cluster-wide events: node joined, node lost, node left, workload
40+ // scheduled, drift detected, retries, reschedules, etc (see
41+ // internal/scheduler/events.go for producers). ListEvents is a
42+ // plain unary call (auto-bridged to REST by persys-gateway's
43+ // reflection-based grpcbridge, no gateway changes needed). WatchEvents
44+ // is a server-streaming call — grpcbridge explicitly does not bridge
45+ // streaming RPCs, so consumers that need HTTP (e.g. a browser
46+ // dashboard) go through a hand-written SSE endpoint on the gateway
47+ // instead of the generic bridge; a gRPC client (e.g. persysctl) can
48+ // call it directly.
49+ rpc ListEvents (ListEventsRequest ) returns (ListEventsResponse );
50+ rpc WatchEvents (WatchEventsRequest ) returns (stream SchedulerEventView );
51+
3952 // Optional future streaming channel
4053 rpc ControlStream (stream ControlMessage ) returns (stream ControlMessage );
54+
55+ // Standalone disk inventory (managed volumes)
56+ rpc CreateDisk (CreateDiskRequest ) returns (CreateDiskResponse );
57+ rpc ListDisks (ListDisksRequest ) returns (ListDisksResponse );
58+ rpc GetDisk (GetDiskRequest ) returns (GetDiskResponse );
59+ rpc DeleteDisk (DeleteDiskRequest ) returns (DeleteDiskResponse );
60+
61+ // Object storage (Ceph RGW / S3-compatible buckets)
62+ rpc CreateBucket (CreateBucketRequest ) returns (CreateBucketResponse );
63+ rpc ListBuckets (ListBucketsRequest ) returns (ListBucketsResponse );
64+ rpc GetBucket (GetBucketRequest ) returns (GetBucketResponse );
65+ rpc DeleteBucket (DeleteBucketRequest ) returns (DeleteBucketResponse );
66+ rpc GetBucketAccess (GetBucketAccessRequest ) returns (GetBucketAccessResponse );
67+ rpc ListBucketObjects (ListBucketObjectsRequest ) returns (ListBucketObjectsResponse );
4168}
4269
4370enum AutomationActionType {
@@ -405,6 +432,42 @@ message ListWorkloadsRequest {
405432 string status = 2 ; // optional filter
406433}
407434
435+ message SchedulerEventView {
436+ string id = 1 ;
437+ string type = 2 ; // e.g. "NodeLost", "WorkloadScheduled", "DriftDetected"
438+ string workload_id = 3 ; // optional, empty if not workload-scoped
439+ string node_id = 4 ; // optional, empty if not node-scoped
440+ string reason = 5 ;
441+ google.protobuf.Timestamp timestamp = 6 ;
442+ // Free-form auxiliary data. Values are stringified on the way out
443+ // (models.SchedulerEvent.Details is map[string]interface{} on the Go
444+ // side) — this is a deliberate simplification over a
445+ // google.protobuf.Struct, since event details are informational/
446+ // display-oriented, not structured data a client needs to
447+ // round-trip losslessly.
448+ map <string , string > details = 7 ;
449+ }
450+
451+ message ListEventsRequest {
452+ int64 limit = 1 ; // 0 means server default
453+ string type = 2 ; // optional filter
454+ string workload_id = 3 ; // optional filter
455+ string node_id = 4 ; // optional filter
456+ }
457+
458+ message ListEventsResponse {
459+ repeated SchedulerEventView events = 1 ;
460+ }
461+
462+ message WatchEventsRequest {
463+ // Same optional filters as ListEventsRequest. The stream first replays
464+ // recent matching events (server-side default limit), then continues
465+ // with new matching events as they're emitted.
466+ string type = 1 ;
467+ string workload_id = 2 ;
468+ string node_id = 3 ;
469+ }
470+
408471message GetWorkloadRequest {
409472 string workload_id = 1 ;
410473}
@@ -456,3 +519,156 @@ message ControlMessage {
456519 DeleteWorkloadRequest delete = 4 ;
457520 }
458521}
522+
523+ // --- Standalone disks (control-plane inventory) ---
524+
525+ message CreateDiskRequest {
526+ string name = 1 ;
527+ string driver = 2 ; // local | ceph-rbd | nfs
528+ int64 size_gb = 3 ;
529+ string fs_type = 4 ;
530+ string access_mode = 5 ;
531+ string retain_policy = 6 ; // Delete | Retain
532+ string node_id = 7 ; // optional pre-pin for local
533+ string mount_path = 8 ;
534+ }
535+
536+ message CreateDiskResponse {
537+ DiskView disk = 1 ;
538+ }
539+
540+ message ListDisksRequest {}
541+
542+ message ListDisksResponse {
543+ repeated DiskView disks = 1 ;
544+ }
545+
546+ message GetDiskRequest {
547+ string disk_id = 1 ;
548+ }
549+
550+ message GetDiskResponse {
551+ DiskView disk = 1 ;
552+ }
553+
554+ message DeleteDiskRequest {
555+ string disk_id = 1 ;
556+ bool force = 2 ;
557+ }
558+
559+ message DeleteDiskResponse {
560+ bool success = 1 ;
561+ string error_message = 2 ;
562+ }
563+
564+ message DiskView {
565+ string id = 1 ;
566+ string name = 2 ;
567+ string driver = 3 ;
568+ int64 size_gb = 4 ;
569+ string fs_type = 5 ;
570+ string access_mode = 6 ;
571+ string retain_policy = 7 ;
572+ string phase = 8 ;
573+ string last_error = 9 ;
574+ string node_id = 10 ;
575+ string device = 11 ;
576+ bool standalone = 12 ;
577+ string mount_path = 13 ;
578+ repeated string workload_refs = 14 ;
579+ repeated string attached_nodes = 15 ;
580+ google.protobuf.Timestamp created_at = 16 ;
581+ google.protobuf.Timestamp updated_at = 17 ;
582+ }
583+
584+ // --- Object storage (Ceph RGW / S3-compatible) ---
585+
586+ message CreateBucketRequest {
587+ string name = 1 ;
588+ string region = 2 ;
589+ bool versioning = 3 ;
590+ }
591+
592+ message CreateBucketResponse {
593+ BucketView bucket = 1 ;
594+ BucketAccess access = 2 ; // credentials returned once on create
595+ }
596+
597+ message ListBucketsRequest {}
598+
599+ message ListBucketsResponse {
600+ repeated BucketView buckets = 1 ;
601+ }
602+
603+ message GetBucketRequest {
604+ string bucket_id = 1 ; // id or name
605+ }
606+
607+ message GetBucketResponse {
608+ BucketView bucket = 1 ;
609+ }
610+
611+ message DeleteBucketRequest {
612+ string bucket_id = 1 ;
613+ bool force = 2 ;
614+ }
615+
616+ message DeleteBucketResponse {
617+ bool success = 1 ;
618+ string error_message = 2 ;
619+ }
620+
621+ message GetBucketAccessRequest {
622+ string bucket_id = 1 ;
623+ }
624+
625+ message GetBucketAccessResponse {
626+ BucketAccess access = 1 ;
627+ }
628+
629+ message ListBucketObjectsRequest {
630+ string bucket_id = 1 ;
631+ string prefix = 2 ;
632+ string continuation_token = 3 ;
633+ int32 max_keys = 4 ;
634+ }
635+
636+ message ListBucketObjectsResponse {
637+ repeated ObjectInfo objects = 1 ;
638+ string next_continuation_token = 2 ;
639+ bool is_truncated = 3 ;
640+ string prefix = 4 ;
641+ }
642+
643+ message BucketView {
644+ string id = 1 ;
645+ string name = 2 ;
646+ string region = 3 ;
647+ string owner = 4 ;
648+ string endpoint = 5 ;
649+ bool versioning = 6 ;
650+ int64 object_count = 7 ;
651+ int64 size_bytes = 8 ;
652+ string phase = 9 ;
653+ string last_error = 10 ;
654+ google.protobuf.Timestamp created_at = 11 ;
655+ google.protobuf.Timestamp updated_at = 12 ;
656+ }
657+
658+ message BucketAccess {
659+ string endpoint = 1 ;
660+ string region = 2 ;
661+ string bucket = 3 ;
662+ string access_key = 4 ;
663+ string secret_key = 5 ;
664+ string vault_path = 6 ; // when secrets live in Vault
665+ string s3_url = 7 ; // e.g. s3://bucket
666+ }
667+
668+ message ObjectInfo {
669+ string key = 1 ;
670+ int64 size_bytes = 2 ;
671+ string etag = 3 ;
672+ string last_modified = 4 ;
673+ string storage_class = 5 ;
674+ }
0 commit comments