treadmill_rs/api/supervisor_puppet.rs
1//! Types used in the interface between supervisors and the puppet
2//! daemon running on hosts.
3
4use std::collections::HashMap;
5
6use serde::{Deserialize, Serialize};
7use uuid::Uuid;
8
9pub use super::switchboard_supervisor::ParameterValue;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
12#[serde(rename_all = "lowercase")]
13#[serde(tag = "type")]
14#[non_exhaustive]
15pub enum PuppetReq {
16 Ping,
17 JobInfo,
18 SSHKeys,
19 NetworkConfig,
20 Parameters,
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize)]
24#[serde(rename_all = "lowercase")]
25pub enum CommandOutputStream {
26 Stdout,
27 Stderr,
28}
29
30#[derive(Debug, Clone, Serialize, Deserialize)]
31#[serde(rename_all = "lowercase")]
32#[serde(tag = "type")]
33#[non_exhaustive]
34pub enum PuppetEvent {
35 /// The puppet has started and completed all initialization necessary for
36 /// the host to be used, either to run automated commands or for interactive
37 /// sessions.
38 Ready,
39
40 /// The puppet is about to shut down.
41 ///
42 /// If this happens in response to a supervisor-issued event, the puppet
43 /// should include its event id here.
44 ///
45 /// A puppet should inform the supervisor of every host shutdown, but is
46 /// allowed to only inform it of ones that have been requested by it.
47 Shutdown { supervisor_event_id: Option<u64> },
48
49 /// The puppet is about to reboot.
50 ///
51 /// If this happens in response to a supervisor-issued event, the puppet
52 /// should include its event id here.
53 ///
54 /// A puppet should inform the supervisor of every host reboot, but is
55 /// allowed to only inform it of ones that have been requested by it.
56 Reboot { supervisor_event_id: Option<u64> },
57
58 /// Running a command requested by the supervisor failed. This event
59 /// includes an error message of what went wrong.
60 ///
61 /// This event will be the last event related to a given `RunCommand` event
62 /// sent by the supervisor.
63 RunCommandError {
64 supervisor_event_id: u64,
65 error: String,
66 },
67
68 /// Output of a command (streaming).
69 RunCommandOutput {
70 supervisor_event_id: u64,
71 output: Vec<u8>,
72 stream: CommandOutputStream,
73 },
74
75 /// Exit code of a command.
76 ///
77 /// This event will be the last event related to a given `RunCommand` event
78 /// sent by the supervisor.
79 RunCommandExitCode {
80 supervisor_event_id: u64,
81 exit_code: Option<i32>,
82 killed: bool,
83 },
84
85 /// Ask the supervisor to terminate this job.
86 ///
87 /// This is an infallible operation, and the puppet will not have a chance
88 /// to be notified of the successful completion of this operation. Thus we
89 /// implement it as an event, not as a request.
90 ///
91 /// If this termination is performed in response to a request by a
92 /// supervisor, the puppet should include this original supervisor event ID
93 /// here:
94 TerminateJob { supervisor_event_id: Option<u64> },
95}
96
97#[derive(Debug, Clone, Serialize, Deserialize)]
98#[serde(rename_all = "lowercase")]
99#[serde(untagged)]
100pub enum PuppetMsg {
101 Event {
102 puppet_event_id: u64,
103 event: PuppetEvent,
104 },
105 Request {
106 request_id: u64,
107 request: PuppetReq,
108 },
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize)]
112#[serde(rename_all = "lowercase")]
113#[serde(tag = "type")]
114#[non_exhaustive]
115pub enum SupervisorEvent {
116 // Events:
117 /// The set of SSH keys provided by the supervisor has been updated.
118 ///
119 /// Based on this event, the puppet may want to update the set of SSH keys
120 /// that is authorized to log into the host.
121 SSHKeysUpdated,
122
123 /// Request that the host on which the puppet is running be shut
124 /// down.
125 ///
126 /// Before executing the shutdown request, the puppet should acknowledge
127 /// that this event will be executed through a `PuppetMsg`. The puppet may
128 /// perform a delayed shutdown, to ensure successful message delivery and
129 /// perhaps inform any active users. The delay should be kept short, usually
130 /// under a minute.
131 ShutdownReq,
132
133 /// Request that the host on which the puppet is running be rebooted.
134 ///
135 /// Before executing the reboot request, the puppet should acknowledge that
136 /// this event will be executed through a `PuppetMsg`. The puppet may
137 /// perform a delayed reboot, to ensure successful message delivery and
138 /// perhaps inform any active users. The delay should be kept short, usually
139 /// under a minute.
140 RebootReq,
141
142 /// Request to run a command on the host.
143 ///
144 /// Multiple commands may be executed at the same time (i.e., this should be
145 /// non-blocking). The command can be executed from an arbitrary working
146 /// directory, with the same permissions as the puppet process (likely, root
147 /// user). Related output (stdout, stderr, exit code) should be streamed
148 /// back to the supervisor while referencing this event's id.
149 ///
150 /// The supervisor is responsible for sending the puppet a command line and
151 /// environment parameters that the puppet can decode into `OsStr`s valid
152 /// for its host platform.
153 ///
154 /// In case that running a command failed, the puppet should send back a
155 /// `RunCommandError`.
156 RunCommand {
157 cmdline: Vec<u8>,
158 environment: Vec<(Vec<u8>, Vec<u8>)>,
159 },
160
161 /// Request a command to be killed.
162 KillCommand { supervisor_event_id: u64 },
163}
164
165#[derive(Debug, Clone, Serialize, Deserialize)]
166#[serde(rename_all = "lowercase")]
167pub struct Ipv4NetworkConfig {
168 pub address: std::net::Ipv4Addr,
169 pub prefix_length: u8,
170 pub gateway: Option<std::net::Ipv4Addr>,
171 pub nameservers: Vec<std::net::Ipv4Addr>,
172}
173
174#[derive(Debug, Clone, Serialize, Deserialize)]
175#[serde(rename_all = "lowercase")]
176pub struct Ipv6NetworkConfig {
177 pub address: std::net::Ipv6Addr,
178 pub prefix_length: u8,
179 pub gateway: Option<std::net::Ipv6Addr>,
180 pub nameservers: Vec<std::net::Ipv6Addr>,
181}
182
183#[derive(Debug, Clone, Serialize, Deserialize)]
184#[serde(rename_all = "lowercase")]
185pub struct NetworkConfig {
186 pub hostname: String,
187 pub interface: Option<String>,
188 pub ipv4: Option<Ipv4NetworkConfig>,
189 pub ipv6: Option<Ipv6NetworkConfig>,
190}
191
192#[derive(Debug, Clone, Serialize, Deserialize)]
193#[serde(rename_all = "lowercase")]
194pub struct JobInfo {
195 pub job_id: Uuid,
196 pub host_id: Uuid,
197}
198
199#[derive(Debug, Clone, Serialize, Deserialize)]
200#[serde(rename_all = "lowercase")]
201#[serde(tag = "type")]
202#[non_exhaustive]
203pub enum SupervisorResp {
204 // Request reponses:
205 PingResp,
206 JobInfo(JobInfo),
207 SSHKeysResp {
208 ssh_keys: Vec<String>,
209 },
210 NetworkConfig(NetworkConfig),
211 Parameters {
212 parameters: HashMap<String, ParameterValue>,
213 },
214
215 // Error responses:
216 UnsupportedRequest,
217 JobNotFound,
218}
219
220#[derive(Debug, Clone, Serialize, Deserialize)]
221#[serde(rename_all = "lowercase")]
222#[serde(untagged)]
223pub enum SupervisorMsg {
224 Event {
225 supervisor_event_id: u64,
226 event: SupervisorEvent,
227 },
228 Response {
229 request_id: u64,
230 response: SupervisorResp,
231 },
232
233 // Generic error, when no more specific error applies (for
234 // instance, if a message cannot be parsed at all)
235 Error {
236 message: String,
237 },
238}