Skip to content

Commit f16fa3c

Browse files
committed
Feat: Add gRPC service definitions for agent and control functionalities
1 parent 1db1b4f commit f16fa3c

4 files changed

Lines changed: 1171 additions & 4 deletions

File tree

persys-scheduler/api/proto/agent.proto

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ syntax = "proto3";
22

33
package persys.agent.v1;
44

5-
option go_package = "github.com/persys-dev/persys-cloud/persys-scheduler/internal/agentpb;agentpb";
5+
option go_package = "github.com/persys-dev/compute-agent/pkg/api/v1;v1";
66

77
// AgentService defines the gRPC interface for workload management
88
service AgentService {
@@ -104,6 +104,8 @@ enum WorkloadType {
104104
WORKLOAD_TYPE_CONTAINER = 1;
105105
WORKLOAD_TYPE_COMPOSE = 2;
106106
WORKLOAD_TYPE_VM = 3;
107+
// Firecracker microVM. Shares WorkloadSpec.vm oneof with KVM VMs.
108+
WORKLOAD_TYPE_MICROVM = 4;
107109
}
108110

109111
enum DesiredState {
@@ -158,13 +160,23 @@ message VMSpec {
158160
map<string, string> metadata = 7;
159161
CloudInitConfig cloud_init_config = 8; // advanced cloud-init settings
160162
repeated ManagedVolumeSpec managed_volumes = 9;
163+
// Happy-path OS image: catalog name or absolute path to a read-only base
164+
// image. Agent creates a writable qcow2 overlay; base is never mutated.
165+
string os_image = 10;
166+
// Root disk size in GB when synthesizing from os_image (default 10).
167+
int64 disk_gb = 11;
168+
// Optional runtime selector: "libvirt" (default) or "firecracker".
169+
string runtime = 12;
161170
}
162171

163172
message CloudInitConfig {
164173
string user_data = 1; // cloud-init user-data script
165174
string meta_data = 2; // cloud-init meta-data (JSON)
166175
string network_config = 3; // cloud-init network config (YAML)
167176
string vendor_data = 4; // cloud-init vendor-data
177+
string username = 5; // default login user when generating user-data
178+
string ssh_public_key = 6; // inject authorized key instead of password
179+
string password = 7; // fixed password (otherwise random)
168180
}
169181

170182
message ManagedVolumeSpec {
@@ -202,18 +214,23 @@ message RestartPolicy {
202214
}
203215

204216
message DiskConfig {
205-
string path = 1; // path to disk image or ISO
217+
string path = 1; // path to disk image or ISO (leave empty with os_image set)
206218
string device = 2; // vda, vdb, etc.
207219
string format = 3; // qcow2, raw, iso
208220
int64 size_gb = 4;
209221
string type = 5; // disk or cdrom (for ISO)
210222
bool boot = 6; // true if this is the boot disk/ISO
223+
string backing_file = 7; // optional explicit backing image for overlay
224+
string storage = 8; // local|nfs|ceph-rbd hint
211225
}
212226

213227
message NetworkConfig {
214-
string network = 1; // network name or bridge
228+
string network = 1; // libvirt network name or bridge (default: "default")
215229
string mac_address = 2;
216-
string ip_address = 3; // optional static IP
230+
string ip_address = 3; // optional static guest IP
231+
string host_dev_name = 4; // Firecracker host TAP device
232+
string model = 5; // virtio (default)
233+
string bridge = 6; // optional explicit bridge
217234
}
218235

219236
message WorkloadStatus {

persys-scheduler/api/proto/control.proto

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

4370
enum 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+
408471
message 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

Comments
 (0)