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}