summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ci_ctl.rs1
-rw-r--r--src/ci_driver.rs21
-rw-r--r--src/ci_runner.rs10
-rw-r--r--src/dbctx.rs93
-rw-r--r--src/main.rs1
-rw-r--r--src/protocol.rs6
-rw-r--r--src/sql.rs27
7 files changed, 136 insertions, 23 deletions
diff --git a/src/ci_ctl.rs b/src/ci_ctl.rs
index 15feca9..74e6e55 100644
--- a/src/ci_ctl.rs
+++ b/src/ci_ctl.rs
@@ -4,6 +4,7 @@ mod sql;
mod dbctx;
mod notifier;
mod io;
+mod protocol;
use dbctx::DbCtx;
use notifier::NotifierConfig;
diff --git a/src/ci_driver.rs b/src/ci_driver.rs
index c6bef14..d8e60e5 100644
--- a/src/ci_driver.rs
+++ b/src/ci_driver.rs
@@ -109,12 +109,12 @@ async fn activate_run(dbctx: Arc<DbCtx>, run: &PendingRun, clients: &mut mpsc::R
}
};
- let run_host = client_job.client.name.clone();
+ let host_id = client_job.client.host_id;
let connection = dbctx.conn.lock().unwrap();
connection.execute(
- "update runs set started_time=?1, run_host=?2, state=1, artifacts_path=?3, build_token=?4 where id=?5",
- (now as u64, run_host, format!("{}", artifacts.display()), &client_job.client.build_token, run.id)
+ "update runs set started_time=?1, host_id=?2, state=1, artifacts_path=?3, build_token=?4 where id=?5",
+ (now as u64, host_id, format!("{}", artifacts.display()), &client_job.client.build_token, run.id)
)
.expect("can update");
std::mem::drop(connection);
@@ -129,15 +129,11 @@ async fn activate_run(dbctx: Arc<DbCtx>, run: &PendingRun, clients: &mut mpsc::R
struct RunnerClient {
tx: mpsc::Sender<Result<String, String>>,
rx: BodyStream,
- name: String,
+ host_id: u32,
build_token: String,
accepted_sources: Option<Vec<String>>,
}
-fn random_name() -> String {
- "random name".to_string()
-}
-
fn token_for_job() -> String {
let mut data = [0u8; 32];
std::fs::File::open("/dev/urandom")
@@ -250,13 +246,12 @@ impl ClientJob {
}
impl RunnerClient {
- async fn new(sender: mpsc::Sender<Result<String, String>>, resp: BodyStream, accepted_sources: Option<Vec<String>>) -> Result<Self, String> {
- let name = random_name();
+ async fn new(sender: mpsc::Sender<Result<String, String>>, resp: BodyStream, accepted_sources: Option<Vec<String>>, host_id: u32) -> Result<Self, String> {
let token = token_for_job();
let client = RunnerClient {
tx: sender,
rx: resp,
- name,
+ host_id,
build_token: token,
accepted_sources,
};
@@ -455,7 +450,9 @@ async fn handle_next_job(State(ctx): State<(Arc<DbCtx>, mpsc::Sender<RunnerClien
eprintln!("client identifies itself as {:?}", host_info);
- let client = match RunnerClient::new(tx_sender, job_resp, accepted_pushers).await {
+ let host_info_id = ctx.0.id_for_host(&host_info).expect("can get a host info id");
+
+ let client = match RunnerClient::new(tx_sender, job_resp, accepted_pushers, host_info_id).await {
Ok(v) => v,
Err(e) => {
eprintln!("unable to register client");
diff --git a/src/ci_runner.rs b/src/ci_runner.rs
index 11d8566..6356dcb 100644
--- a/src/ci_runner.rs
+++ b/src/ci_runner.rs
@@ -498,11 +498,14 @@ mod host_info {
fn collect_cpu_info() -> CpuInfo {
let cpu_lines: Vec<String> = std::fs::read_to_string("/proc/cpuinfo").unwrap().split("\n").map(|line| line.to_string()).collect();
let model_names: Vec<&String> = cpu_lines.iter().filter(|line| line.starts_with("model name")).collect();
- let model = model_names.first().expect("can get model name").to_string().split(":").last().unwrap().trim().to_string();
+ let model_name = model_names.first().expect("can get model name").to_string().split(":").last().unwrap().trim().to_string();
let cores = model_names.len() as u32;
+ let vendor_id = cpu_lines.iter().find(|line| line.starts_with("vendor_id")).expect("vendor_id line is present").split(":").last().unwrap().trim().to_string();
+ let family = cpu_lines.iter().find(|line| line.starts_with("vendor_id")).expect("vendor_id line is present").split(":").last().unwrap().trim().to_string();
+ let model = cpu_lines.iter().find(|line| line.starts_with("model\t")).expect("vendor_id line is present").split(":").last().unwrap().trim().to_string();
let microcode = cpu_lines.iter().find(|line| line.starts_with("microcode")).expect("microcode line is present").split(":").last().unwrap().trim().to_string();
- CpuInfo { model, microcode, cores }
+ CpuInfo { model_name, microcode, cores, vendor_id, family, model }
}
fn collect_mem_info() -> MemoryInfo {
@@ -536,10 +539,11 @@ mod host_info {
pub fn collect_host_info() -> HostInfo {
let cpu_info = collect_cpu_info();
let memory_info = collect_mem_info();
-// let hostname = hostname();
+ let hostname = hostname();
let env_info = collect_env_info();
HostInfo {
+ hostname,
cpu_info,
memory_info,
env_info,
diff --git a/src/dbctx.rs b/src/dbctx.rs
index 3eb68bd..0b1b7ad 100644
--- a/src/dbctx.rs
+++ b/src/dbctx.rs
@@ -56,7 +56,7 @@ pub struct Run {
pub job_id: u64,
pub artifacts_path: Option<String>,
pub state: sql::RunState,
- pub run_host: Option<String>,
+ pub host_id: Option<u64>,
pub create_time: u64,
pub start_time: Option<u64>,
pub complete_time: Option<u64>,
@@ -126,6 +126,8 @@ impl DbCtx {
conn.execute(sql::CREATE_REPO_NAME_INDEX, ()).unwrap();
conn.execute(sql::CREATE_REMOTES_TABLE, ()).unwrap();
conn.execute(sql::CREATE_REMOTES_INDEX, ()).unwrap();
+ conn.execute(sql::CREATE_RUNS_TABLE, ()).unwrap();
+ conn.execute(sql::CREATE_HOSTS_TABLE, ()).unwrap();
Ok(())
}
@@ -551,6 +553,95 @@ impl DbCtx {
Ok(remotes)
}
+ /// try to find a host close to `host_info`, but maybe not an exact match.
+ ///
+ /// specifically, we'll ignore microcode and family/os - enough that measurements ought to be
+ /// comparable but maybe not perfectly so.
+ pub fn find_id_like_host(&self, host_info: &crate::protocol::HostInfo) -> Result<Option<u32>, String> {
+ self.conn.lock()
+ .unwrap()
+ .query_row(
+ "select id from hosts where \
+ ( \
+ hostname=?1, cpu_vendor=?2, cpu_model_name=?3, cpu_family=?4, \
+ cpu_model=?5, cpu_cores=?6, mem_total=?7, \
+ arch=?10 \
+ );",
+ (
+ &host_info.hostname,
+ &host_info.cpu_info.vendor_id,
+ &host_info.cpu_info.model_name,
+ &host_info.cpu_info.family,
+ &host_info.cpu_info.model,
+ &host_info.cpu_info.cores,
+ &host_info.memory_info.total,
+ &host_info.env_info.arch,
+ ),
+ |row| { row.get(0) }
+ )
+ .map_err(|e| e.to_string())
+ }
+
+ /// get an id for the host described by `host_info`. this may create a new record if no such
+ /// host exists.
+ pub fn id_for_host(&self, host_info: &crate::protocol::HostInfo) -> Result<u32, String> {
+ let conn = self.conn.lock().unwrap();
+
+ conn
+ .execute(
+ "insert or ignore into hosts \
+ (\
+ hostname, cpu_vendor_id, cpu_model_name, cpu_family, \
+ cpu_model, cpu_microcode, cpu_cores, mem_total, \
+ arch, family, os\
+ ) values (\
+ ?1, ?2, ?3, ?4, \
+ ?5, ?6, ?7, ?8, \
+ ?9, ?10, ?11 \
+ );",
+ (
+ &host_info.hostname,
+ &host_info.cpu_info.vendor_id,
+ &host_info.cpu_info.model_name,
+ &host_info.cpu_info.family,
+ &host_info.cpu_info.model,
+ &host_info.cpu_info.microcode,
+ &host_info.cpu_info.cores,
+ &host_info.memory_info.total,
+ &host_info.env_info.arch,
+ &host_info.env_info.family,
+ &host_info.env_info.os,
+ )
+ )
+ .expect("can insert");
+
+ self.conn.lock()
+ .unwrap()
+ .query_row(
+ "select id from hosts where \
+ ( \
+ hostname=?1, cpu_vendor=?2, cpu_model_name=?3, cpu_family=?4, \
+ cpu_model=?5, cpu_microcode=?6, cpu_cores=?7, mem_total=?8, \
+ arch=?9, family=?10, os=?11 \
+ );",
+ (
+ &host_info.hostname,
+ &host_info.cpu_info.vendor_id,
+ &host_info.cpu_info.model_name,
+ &host_info.cpu_info.family,
+ &host_info.cpu_info.model,
+ &host_info.cpu_info.microcode,
+ &host_info.cpu_info.cores,
+ &host_info.memory_info.total,
+ &host_info.env_info.arch,
+ &host_info.env_info.family,
+ &host_info.env_info.os,
+ ),
+ |row| { row.get(0) }
+ )
+ .map_err(|e| e.to_string())
+ }
+
pub fn last_run_for_job(&self, job_id: u64) -> Result<Option<Run>, String> {
let conn = self.conn.lock().unwrap();
diff --git a/src/main.rs b/src/main.rs
index d83826b..0ca0765 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -34,6 +34,7 @@ mod io;
mod sql;
mod notifier;
mod dbctx;
+mod protocol;
use sql::RunState;
diff --git a/src/protocol.rs b/src/protocol.rs
index 78c7303..9f79a7c 100644
--- a/src/protocol.rs
+++ b/src/protocol.rs
@@ -73,6 +73,7 @@ impl TaskInfo {
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct HostInfo {
+ pub hostname: String,
pub cpu_info: CpuInfo,
pub memory_info: MemoryInfo,
pub env_info: EnvInfo,
@@ -80,9 +81,12 @@ pub struct HostInfo {
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct CpuInfo {
- pub model: String,
+ pub model_name: String,
pub microcode: String,
pub cores: u32,
+ pub vendor_id: String,
+ pub family: String,
+ pub model: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
diff --git a/src/sql.rs b/src/sql.rs
index 9d8613a..1ed9205 100644
--- a/src/sql.rs
+++ b/src/sql.rs
@@ -36,14 +36,14 @@ impl TryFrom<u8> for RunState {
}
pub(crate) fn row2run(row: &rusqlite::Row) -> Run {
- let (id, job_id, artifacts_path, state, run_host, build_token, create_time, start_time, complete_time, run_timeout, build_result, final_text) = row.try_into().unwrap();
+ let (id, job_id, artifacts_path, state, host_id, build_token, create_time, start_time, complete_time, run_timeout, build_result, final_text) = row.try_into().unwrap();
let state: u8 = state;
Run {
id,
job_id,
artifacts_path,
state: state.try_into().unwrap(),
- run_host,
+ host_id,
create_time,
start_time,
complete_time,
@@ -101,12 +101,12 @@ pub const CREATE_ARTIFACTS_TABLE: &'static str = "\
created_time INTEGER,
completed_time INTEGER);";
-pub const CREATE_RUN_TABLE: &'static str = "\
+pub const CREATE_RUNS_TABLE: &'static str = "\
CREATE TABLE IF NOT EXISTS runs (id INTEGER PRIMARY KEY AUTOINCREMENT,
job_id INTEGER,
artifacts_path TEXT,
state INTEGER NOT NULL,
- run_host TEXT,
+ host_id INTEGER,
build_token TEXT,
created_time INTEGER,
started_time INTEGER,
@@ -115,6 +115,21 @@ pub const CREATE_RUN_TABLE: &'static str = "\
build_result INTEGER,
final_status TEXT);";
+pub const CREATE_HOSTS_TABLE: &'static str = "\
+ CREATE TABLE IF NOT EXISTS hosts (id INTEGER PRIMARY KEY AUTOINCREMENT,
+ hostname TEXT,
+ cpu_vendor TEXT,
+ cpu_model_name TEXT,
+ cpu_family TEXT,
+ cpu_model TEXT,
+ cpu_microcode TEXT,
+ cpu_cores INTEGER,
+ mem_total TEXT,
+ arch TEXT,
+ family TEXT,
+ os TEXT,
+ UNIQUE(hostname, cpu_vendor, cpu_model_name, cpu_family, cpu_model, cpu_microcode, cpu_cores, mem_total, arch, family, os));";
+
pub const CREATE_REMOTES_INDEX: &'static str = "\
CREATE INDEX IF NOT EXISTS 'repo_to_remote' ON remotes(repo_id);";
@@ -129,7 +144,7 @@ pub const ACTIVE_RUNS: &'static str = "\
job_id,
artifacts_path,
state,
- run_host,
+ host_id,
build_token,
created_time,
started_time,
@@ -170,7 +185,7 @@ pub const LAST_RUN_FOR_JOB: &'static str = "\
job_id,
artifacts_path,
state,
- run_host,
+ host_id,
build_token,
created_time,
started_time,