Skip to content

Commit 9bde235

Browse files
committed
server, agent: allow jobs to identify factory used for worker
1 parent c4d051d commit 9bde235

File tree

6 files changed

+169
-5
lines changed

6 files changed

+169
-5
lines changed

agent/src/control/mod.rs

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use tokio::{
1313
net::UnixStream,
1414
};
1515

16-
use protocol::{Decoder, Message, Payload};
16+
use protocol::{Decoder, FactoryInfo, Message, Payload};
1717

1818
pub(crate) mod protocol;
1919
pub(crate) mod server;
@@ -79,6 +79,7 @@ pub async fn main() -> Result<()> {
7979
l.cmd("store", "access the job store", cmd!(cmd_store))?;
8080
l.cmd("address", "manage IP addresses for this job", cmd!(cmd_address))?;
8181
l.cmd("process", "manage background processes", cmd!(cmd_process))?;
82+
l.cmd("factory", "factory information for this worker", cmd!(cmd_factory))?;
8283
l.hcmd("eng", "for working on and testing buildomat", cmd!(cmd_eng))?;
8384

8485
sel!(l).run().await
@@ -491,3 +492,89 @@ async fn cmd_process_start(mut l: Level<Stuff>) -> Result<()> {
491492
}
492493
}
493494
}
495+
496+
async fn factory_info(s: &mut Stuff) -> Result<FactoryInfo> {
497+
let mout =
498+
Message { id: s.ids.next().unwrap(), payload: Payload::FactoryInfo };
499+
500+
match s.send_and_recv(&mout).await {
501+
Ok(min) => {
502+
match min.payload {
503+
Payload::Error(e) => {
504+
/*
505+
* This request is purely local to the agent, so an
506+
* error is not something we should retry indefinitely.
507+
*/
508+
bail!("could not get factory info: {e}");
509+
}
510+
Payload::FactoryInfoResult(fi) => Ok(fi),
511+
other => bail!("unexpected response: {other:?}"),
512+
}
513+
}
514+
Err(e) => {
515+
/*
516+
* Requests to the agent are relatively simple and over a UNIX
517+
* socket; they should not fail. This implies something has
518+
* gone seriously wrong and it is unlikely that it will be fixed
519+
* without intervention. Don't retry.
520+
*/
521+
bail!("could not talk to the agent: {e}");
522+
}
523+
}
524+
}
525+
526+
async fn cmd_factory(mut l: Level<Stuff>) -> Result<()> {
527+
l.context_mut().connect().await?;
528+
529+
l.cmd(
530+
"name",
531+
"print the name of the factory that produced this worker",
532+
cmd!(cmd_factory_name),
533+
)?;
534+
l.cmd(
535+
"id",
536+
"print the unique ID of the factory that produced this worker",
537+
cmd!(cmd_factory_id),
538+
)?;
539+
l.cmd(
540+
"private",
541+
"print the factory-specific identifier for the underlying resource",
542+
cmd!(cmd_factory_private),
543+
)?;
544+
545+
sel!(l).run().await
546+
}
547+
548+
async fn cmd_factory_id(mut l: Level<Stuff>) -> Result<()> {
549+
no_args!(l);
550+
551+
let fi = factory_info(l.context_mut()).await?;
552+
553+
println!("{}", fi.id);
554+
555+
Ok(())
556+
}
557+
558+
async fn cmd_factory_name(mut l: Level<Stuff>) -> Result<()> {
559+
no_args!(l);
560+
561+
let fi = factory_info(l.context_mut()).await?;
562+
563+
println!("{}", fi.name);
564+
565+
Ok(())
566+
}
567+
568+
async fn cmd_factory_private(mut l: Level<Stuff>) -> Result<()> {
569+
no_args!(l);
570+
571+
let fi = factory_info(l.context_mut()).await?;
572+
573+
let Some(fp) = &fi.private else {
574+
bail!("factory private info not available");
575+
};
576+
577+
println!("{fp}");
578+
579+
Ok(())
580+
}

agent/src/control/protocol.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ use buildomat_types::metadata;
99
use bytes::{Buf, BufMut, BytesMut};
1010
use serde::{Deserialize, Serialize};
1111

12+
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
13+
pub struct FactoryInfo {
14+
pub id: String,
15+
pub name: String,
16+
pub private: Option<String>,
17+
}
18+
1219
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
1320
pub struct StoreEntry {
1421
pub name: String,
@@ -38,6 +45,9 @@ pub enum Payload {
3845
uid: u32,
3946
gid: u32,
4047
},
48+
49+
FactoryInfo,
50+
FactoryInfoResult(FactoryInfo),
4151
}
4252

4353
#[derive(Clone, Debug, Serialize, Deserialize)]

agent/src/control/server.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,8 @@ async fn handle_client_turn(
204204
Payload::StoreGet(..)
205205
| Payload::StorePut(..)
206206
| Payload::MetadataAddresses
207-
| Payload::ProcessStart { .. } => {
207+
| Payload::ProcessStart { .. }
208+
| Payload::FactoryInfo => {
208209
/*
209210
* These are requests from the control program. Pass them
210211
* on to the main loop.

agent/src/main.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ mod exec;
3636
mod shadow;
3737
mod upload;
3838

39-
use control::protocol::Payload;
39+
use control::protocol::{FactoryInfo, Payload};
4040
use exec::ExitDetails;
4141

4242
const CONFIG_PATH: &str = "/opt/buildomat/etc/agent.json";
@@ -1201,6 +1201,7 @@ async fn cmd_run(mut l: Level<()>) -> Result<()> {
12011201
let mut bgprocs = exec::BackgroundProcesses::new();
12021202

12031203
let mut metadata: Option<metadata::FactoryMetadata> = None;
1204+
let mut factory: Option<WorkerPingFactoryInfo> = None;
12041205
let mut set_root_password = false;
12051206
let mut set_root_keys = false;
12061207
let mut dump_device_configured = false;
@@ -1295,6 +1296,10 @@ async fn cmd_run(mut l: Level<()>) -> Result<()> {
12951296
continue;
12961297
}
12971298

1299+
if let Some(fi) = &p.factory_info {
1300+
factory = Some(fi.clone());
1301+
}
1302+
12981303
if let Some(md) = &p.factory_metadata {
12991304
/*
13001305
* If the factory has given us a post-job diagnostic
@@ -1431,6 +1436,17 @@ async fn cmd_run(mut l: Level<()>) -> Result<()> {
14311436
Err(e) => Payload::Error(e.to_string()),
14321437
}
14331438
}
1439+
Payload::FactoryInfo => {
1440+
if let Some(f) = &factory {
1441+
Payload::FactoryInfoResult(FactoryInfo {
1442+
id: f.id.to_string(),
1443+
name: f.name.to_string(),
1444+
private: f.private.clone(),
1445+
})
1446+
} else {
1447+
Payload::Error("factory info not available".into())
1448+
}
1449+
}
14341450
_ => Payload::Error("unexpected message type".to_string()),
14351451
};
14361452

client/openapi.json

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2767,6 +2767,10 @@
27672767
"nullable": true,
27682768
"type": "string"
27692769
},
2770+
"rpool_disable_sync": {
2771+
"nullable": true,
2772+
"type": "boolean"
2773+
},
27702774
"v": {
27712775
"type": "string",
27722776
"enum": [
@@ -3929,6 +3933,25 @@
39293933
"value"
39303934
]
39313935
},
3936+
"WorkerPingFactoryInfo": {
3937+
"type": "object",
3938+
"properties": {
3939+
"id": {
3940+
"type": "string"
3941+
},
3942+
"name": {
3943+
"type": "string"
3944+
},
3945+
"private": {
3946+
"nullable": true,
3947+
"type": "string"
3948+
}
3949+
},
3950+
"required": [
3951+
"id",
3952+
"name"
3953+
]
3954+
},
39323955
"WorkerPingInput": {
39333956
"type": "object",
39343957
"properties": {
@@ -4006,6 +4029,14 @@
40064029
"WorkerPingResult": {
40074030
"type": "object",
40084031
"properties": {
4032+
"factory_info": {
4033+
"nullable": true,
4034+
"allOf": [
4035+
{
4036+
"$ref": "#/components/schemas/WorkerPingFactoryInfo"
4037+
}
4038+
]
4039+
},
40094040
"factory_metadata": {
40104041
"nullable": true,
40114042
"allOf": [
@@ -4127,4 +4158,4 @@
41274158
}
41284159
}
41294160
}
4130-
}
4161+
}

server/src/api/worker.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,19 @@ pub(crate) struct WorkerPingJob {
118118
inputs: Vec<WorkerPingInput>,
119119
}
120120

121+
#[derive(Serialize, JsonSchema)]
122+
pub(crate) struct WorkerPingFactoryInfo {
123+
id: String,
124+
name: String,
125+
private: Option<String>,
126+
}
127+
121128
#[derive(Serialize, JsonSchema)]
122129
pub(crate) struct WorkerPingResult {
123130
poweroff: bool,
124131
job: Option<WorkerPingJob>,
125132
factory_metadata: Option<metadata::FactoryMetadata>,
133+
factory_info: Option<WorkerPingFactoryInfo>,
126134
}
127135

128136
#[endpoint {
@@ -143,6 +151,8 @@ pub(crate) async fn worker_ping(
143151

144152
let factory_metadata = w.factory_metadata().or_500()?;
145153

154+
let factory = c.db.factory(w.factory()).or_500()?;
155+
146156
let job = if w.wait_for_flush {
147157
/*
148158
* The factory may have event records (e.g., boot time console logs or
@@ -217,7 +227,16 @@ pub(crate) async fn worker_ping(
217227
w.recycle || w.deleted
218228
};
219229

220-
let res = WorkerPingResult { poweroff, job, factory_metadata };
230+
let res = WorkerPingResult {
231+
poweroff,
232+
job,
233+
factory_metadata,
234+
factory_info: Some(WorkerPingFactoryInfo {
235+
id: factory.id.to_string(),
236+
name: factory.name,
237+
private: w.factory_private.clone(),
238+
}),
239+
};
221240

222241
Ok(HttpResponseOk(res))
223242
}

0 commit comments

Comments
 (0)