Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion coman/.config/config.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[cscs]
system = "daint"
current_system = "daint"

image = "ubuntu"

Expand All @@ -17,3 +17,11 @@ edf_file_template = """
image = "{{edf_image}}"
mounts = ["${SCRATCH}:/scratch"]
"""

[cscs.systems]

[cscs.systems.daint]
architecture = ["arm64"]

[cscs.systems.eiger]
architecture = ["amd64"]
2 changes: 2 additions & 0 deletions coman/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ tabled = { version = "0.20.0", features = ["macros"] }
nom = "8.0.0"
tera = "1.20.1"
inquire = "0.9.1"
oci-distribution = "0.11.0"
docker_credential = "1.3.2"

[build-dependencies]
anyhow = "1.0.90"
Expand Down
1 change: 0 additions & 1 deletion coman/src/app/user_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ pub enum UserEvent {
Cscs(CscsEvent),
Error(String),
Info(String),
None, // this is mainly used to return a nop result that keeps a port alive, as returning no Event stops the port
}

impl PartialEq for UserEvent {
Expand Down
13 changes: 11 additions & 2 deletions coman/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![allow(dead_code)] // Remove this once you start using the code

use std::{env, path::PathBuf};
use std::{collections::HashMap, env, path::PathBuf};

use color_eyre::Result;
use directories::ProjectDirs;
Expand All @@ -9,6 +9,11 @@ use serde::{Deserialize, Serialize};

const DEFAULT_CONFIG_TOML: &str = include_str!("../.config/config.toml");

#[derive(Clone, Debug, Serialize, Deserialize, Default)]
pub struct SystemDescription {
pub architecture: Vec<String>,
}

#[derive(Clone, Debug, Serialize, Deserialize, Default)]
pub struct AppConfig {
#[serde(default)]
Expand All @@ -20,7 +25,7 @@ pub struct AppConfig {
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
pub struct CscsConfig {
#[serde(default)]
pub system: String,
pub current_system: String,
#[serde(default)]
pub name: Option<String>,
#[serde(default)]
Expand All @@ -31,7 +36,11 @@ pub struct CscsConfig {
pub edf_file_template: String,
#[serde(default)]
pub command: Vec<String>,

#[serde(default)]
pub systems: HashMap<String, SystemDescription>,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct Config {
#[serde(default, flatten)]
Expand Down
2 changes: 2 additions & 0 deletions coman/src/cscs/api_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ impl From<CSCSFileSystem> for FileSystem {

#[derive(Debug, Eq, Clone, PartialEq, PartialOrd, Ord, Display)]
pub enum JobStatus {
Pending,
Running,
Finished,
Cancelled,
Expand All @@ -96,6 +97,7 @@ impl From<JobModelOutput> for Job {
"FAILED" => JobStatus::Failed,
"COMPLETED" => JobStatus::Finished,
"CANCELLED" => JobStatus::Cancelled,
"PENDING" => JobStatus::Pending,
other => panic!("got job status: {}", other),
},
user: value.user.unwrap_or("".to_string()),
Expand Down
61 changes: 44 additions & 17 deletions coman/src/cscs/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use crate::{
cscs::{
api_client::{CscsApi, FileSystemType, Job, JobDetail, System},
oauth2::{
CLIENT_ID_SECRET_NAME, CLIENT_SECRET_SECRET_NAME,
client_credentials_login, finish_cscs_device_login, start_cscs_device_login,
CLIENT_ID_SECRET_NAME, CLIENT_SECRET_SECRET_NAME, client_credentials_login,
finish_cscs_device_login, start_cscs_device_login,
},
},
util::{
Expand Down Expand Up @@ -61,17 +61,22 @@ pub async fn cscs_job_list() -> Result<Vec<Job>> {
Ok(access_token) => {
let api_client = CscsApi::new(access_token.0).unwrap();
let config = Config::new().unwrap();
api_client.list_jobs(&config.cscs.system, Some(true)).await
api_client
.list_jobs(&config.cscs.current_system, Some(true))
.await
}
Err(e) => Err(e),
}
}

pub async fn cscs_job_details(job_id: i64) -> Result<Option<JobDetail>> {
match get_access_token().await {
Ok(access_token) => {
let api_client = CscsApi::new(access_token.0).unwrap();
let config = Config::new().unwrap();
api_client.get_job(&config.cscs.system, job_id).await
api_client
.get_job(&config.cscs.current_system, job_id)
.await
}
Err(e) => Err(e),
}
Expand All @@ -86,9 +91,9 @@ pub async fn cscs_start_job(
Ok(access_token) => {
let api_client = CscsApi::new(access_token.0).unwrap();
let config = Config::new().unwrap();
let user_info = api_client.get_userinfo(&config.cscs.system).await?;
let system = api_client.get_system(&config.cscs.system).await?;
let scratch = match system {
let user_info = api_client.get_userinfo(&config.cscs.current_system).await?;
let current_system = api_client.get_system(&config.cscs.current_system).await?;
let scratch = match current_system {
Some(system) => PathBuf::from(
system
.file_systems
Expand All @@ -101,7 +106,7 @@ pub async fn cscs_start_job(
None => {
return Err(eyre!(
"couldn't get system description for {}",
config.cscs.system
config.cscs.current_system
));
}
};
Expand All @@ -113,21 +118,43 @@ pub async fn cscs_start_job(
let environment_path = base_path.join("environment.toml");
let environment_template = config.cscs.edf_file_template;
tera.add_raw_template("environment.toml", &environment_template)?;

let docker_image = image.unwrap_or(config.cscs.image.try_into()?);
let meta = docker_image.inspect().await?;
if let Some(system_info) = config.cscs.systems.get(&config.cscs.current_system) {
let mut compatible = false;
for sys_platform in system_info.architecture.iter() {
if meta.platforms.contains(&sys_platform.clone().into()) {
compatible = true;
}
}

if !compatible {
return Err(eyre!(
"System {} only supports images with architecture(s) '{}' but the supplied image is for architecture(s) '{}'",
config.cscs.current_system,
system_info.architecture.join(","),
meta.platforms
.iter()
.map(|p| p.to_string())
.collect::<Vec<String>>()
.join(",")
));
}
}

let mut context = tera::Context::new();
context.insert(
"edf_image",
&image.unwrap_or(config.cscs.image.try_into()?).to_edf(),
);
context.insert("edf_image", &docker_image.to_edf());
let environment_file = tera.render("environment.toml", &context)?;
api_client
.mkdir(&config.cscs.system, base_path.clone())
.mkdir(&config.cscs.current_system, base_path.clone())
.await?;
api_client
.chmod(&config.cscs.system, base_path.clone(), "700")
.chmod(&config.cscs.current_system, base_path.clone(), "700")
.await?;
api_client
.upload(
&config.cscs.system,
&config.cscs.current_system,
environment_path.clone(),
environment_file.into_bytes(),
)
Expand All @@ -150,15 +177,15 @@ pub async fn cscs_start_job(
let script = tera.render("script.sh", &context)?;
api_client
.upload(
&config.cscs.system,
&config.cscs.current_system,
script_path.clone(),
script.into_bytes(),
)
.await?;

// start job
api_client
.start_job(&config.cscs.system, &name, script_path)
.start_job(&config.cscs.current_system, &name, script_path)
.await?;
Ok(())
}
Expand Down
Loading