Skip to content

Commit

Permalink
add nodelist
Browse files Browse the repository at this point in the history
  • Loading branch information
archeoss committed Jan 31, 2024
1 parent 961f341 commit 4360fc5
Show file tree
Hide file tree
Showing 17 changed files with 589 additions and 41 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ Bob Management GUI changelog
- Home page, backend (#18)
- Node list page, backend (#19)
- Home page, frontend (#22)
- Node list page, frontend (#23)
2 changes: 1 addition & 1 deletion backend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl Modify for SecurityAddon {
models::api::DiskStatus,
models::api::DiskStatusName,
models::api::DiskCount,
models::api::Node,
models::api::NodeInfo,
models::api::NodeProblem,
models::api::NodeStatus,
models::api::NodeStatusName,
Expand Down
40 changes: 25 additions & 15 deletions backend/src/models/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ pub use crate::models::shared::{BobConnectionData, Credentials};
/// Physical disk definition
#[derive(Debug, Clone, Eq, PartialEq, Serialize)]
#[cfg_attr(all(feature = "swagger", debug_assertions), derive(ToSchema))]
#[serde(rename_all = "camelCase")]
#[tsync]
pub struct Disk {
/// Disk name
pub name: String,
Expand All @@ -19,7 +21,7 @@ pub struct Disk {
pub path: String,

/// Disk status
#[serde(flatten)]
// #[serde(flatten)]
pub status: DiskStatus,

#[serde(rename = "totalSpace")]
Expand Down Expand Up @@ -52,7 +54,7 @@ pub enum DiskStatus {
#[serde(rename = "good")]
Good,
#[serde(rename = "bad")]
Bad(Vec<DiskProblem>),
Bad { problems: Vec<DiskProblem> },
#[serde(rename = "offline")]
Offline,
}
Expand All @@ -66,7 +68,9 @@ impl DiskStatus {
/ space.total_disk_space_bytes as f64)
< DEFAULT_MIN_FREE_SPACE_PERCENTAGE
{
Self::Bad(vec![DiskProblem::FreeSpaceRunningOut])
Self::Bad {
problems: vec![DiskProblem::FreeSpaceRunningOut],
}
} else {
Self::Good
}
Expand All @@ -89,13 +93,15 @@ pub enum DiskStatusName {

#[derive(Debug, Clone, Serialize)]
#[cfg_attr(all(feature = "swagger", debug_assertions), derive(ToSchema))]
pub struct Node {
#[serde(rename_all = "camelCase")]
#[tsync]
pub struct NodeInfo {
pub name: String,

pub hostname: String,

pub vdisks: Vec<VDisk>,
#[serde(flatten)]
// #[serde(flatten)]
pub status: NodeStatus,

#[serde(rename = "rps")]
Expand Down Expand Up @@ -158,10 +164,8 @@ impl NodeProblem {
if node_metrics[RawMetricEntry::HardwareBobCpuLoad].value >= max_cpu {
res.push(Self::HighCPULoad);
}
if (1.
- (node_metrics[RawMetricEntry::HardwareTotalSpace].value
- node_metrics[RawMetricEntry::HardwareFreeSpace].value) as f64
/ node_metrics[RawMetricEntry::HardwareTotalSpace].value as f64)
if (node_metrics[RawMetricEntry::HardwareFreeSpace].value as f64
/ node_metrics[RawMetricEntry::HardwareTotalSpace].value as f64)
< min_free_space_perc
{
res.push(Self::FreeSpaceRunningOut);
Expand Down Expand Up @@ -189,7 +193,7 @@ pub enum NodeStatus {
#[serde(rename = "good")]
Good,
#[serde(rename = "bad")]
Bad(Vec<NodeProblem>),
Bad { problems: Vec<NodeProblem> },
#[serde(rename = "offline")]
Offline,
}
Expand All @@ -200,7 +204,7 @@ impl NodeStatus {
if problems.is_empty() {
Self::Good
} else {
Self::Bad(problems)
Self::Bad { problems }
}
}
}
Expand Down Expand Up @@ -235,14 +239,16 @@ pub enum NodeStatusName {
/// [`VDisk`]'s replicas
#[derive(Debug, Clone, Eq, PartialEq, Serialize)]
#[cfg_attr(all(feature = "swagger", debug_assertions), derive(ToSchema))]
#[serde(rename_all = "camelCase")]
#[tsync]
pub struct Replica {
pub node: String,

pub disk: String,

pub path: String,

#[serde(flatten)]
// #[serde(flatten)]
pub status: ReplicaStatus,
}

Expand Down Expand Up @@ -270,7 +276,7 @@ pub enum ReplicaStatus {
#[serde(rename = "good")]
Good,
#[serde(rename = "offline")]
Offline(Vec<ReplicaProblem>),
Offline { problems: Vec<ReplicaProblem> },
}

/// Disk space information in bytes
Expand Down Expand Up @@ -327,7 +333,7 @@ impl Add for SpaceInfo {
pub struct VDisk {
pub id: u64,

#[serde(flatten)]
// #[serde(flatten)]
pub status: VDiskStatus,

#[serde(rename = "partitionCount")]
Expand Down Expand Up @@ -593,7 +599,11 @@ impl From<dto::MetricsSnapshotModel> for TypedMetrics {
let mut value = value.metrics;
for key in RawMetricEntry::iter() {
let value = value
.remove(&serde_json::to_string(&key).expect("infallible"))
.remove(
serde_json::to_string(&key)
.expect("infallible")
.trim_matches('"'),
)
.unwrap_or_default();
map.insert(key, value);
}
Expand Down
43 changes: 30 additions & 13 deletions backend/src/services/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub async fn get_disks_count(Extension(client): Extension<HttpBobClient>) -> Jso
match DiskStatus::from_space_info(&space, &disk.name) {
DiskStatus::Good => count[DiskStatusName::Good] += 1,
DiskStatus::Offline => count[DiskStatusName::Offline] += 1,
DiskStatus::Bad(_) => count[DiskStatusName::Bad] += 1,
DiskStatus::Bad { .. } => count[DiskStatusName::Bad] += 1,
}
});
count[DiskStatusName::Offline] = (disks.len() - active) as u64;
Expand Down Expand Up @@ -308,7 +308,7 @@ pub async fn get_vdisk_info(
pub async fn get_node_info(
Extension(client): Extension<HttpBobClient>,
Path(node_name): Path<NodeName>,
) -> AxumResult<Json<Node>> {
) -> AxumResult<Json<NodeInfo>> {
tracing::info!("get /nodes/{node_name} : {client:?}");
let handle = Arc::new(
client
Expand All @@ -317,6 +317,10 @@ pub async fn get_node_info(
.ok_or(StatusCode::NOT_FOUND)?,
);

let nodes = {
let handle = client.api_main().clone();
tokio::spawn(async move { fetch_nodes(&handle).await })
};
let status = {
let handle = handle.clone();
tokio::spawn(async move { handle.get_status().await })
Expand All @@ -330,9 +334,32 @@ pub async fn get_node_info(
tokio::spawn(async move { handle.clone().get_space_info().await })
};

let mut node = NodeInfo {
name: node_name.clone(),
hostname: String::new(),
vdisks: vec![],
status: NodeStatus::Offline,
rps: None,
alien_count: None,
corrupted_count: None,
space: None,
};

let Ok(Ok(GetStatusResponse::AJSONWithNodeInfo(status))) = status.await else {
return Err(StatusCode::NOT_FOUND.into());
// Fallback to general info
node.hostname = if let Ok(Ok(nodes)) = nodes.await {
nodes
.iter()
.find(|node| node.name == node_name)
.ok_or(StatusCode::NOT_FOUND)?
.address
.clone()
} else {
String::new()
};
return Ok(Json(node));
};
node.hostname = status.address;

let mut vdisks: FuturesUnordered<_> = status
.vdisks
Expand All @@ -345,16 +372,6 @@ pub async fn get_node_info(
})
.collect();

let mut node = Node {
name: status.name.clone(),
hostname: status.address.clone(),
vdisks: vec![],
status: NodeStatus::Offline,
rps: None,
alien_count: None,
corrupted_count: None,
space: None,
};
if let (
Ok(Ok(GetMetricsResponse::Metrics(metric))),
Ok(Ok(GetSpaceInfoResponse::SpaceInfo(space))),
Expand Down
10 changes: 6 additions & 4 deletions backend/src/services/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,9 @@ pub async fn get_vdisk_by_id(client: &HttpBobClient, vdisk_id: u64) -> AxumResul
node: replica.node,
disk: replica.disk,
path: replica.path,
status: ReplicaStatus::Offline(vec![ReplicaProblem::NodeUnavailable]),
status: ReplicaStatus::Offline {
problems: vec![ReplicaProblem::NodeUnavailable],
},
},
)
})
Expand All @@ -237,8 +239,8 @@ pub async fn get_vdisk_by_id(client: &HttpBobClient, vdisk_id: u64) -> AxumResul
status: disk
.is_active
.then_some(ReplicaStatus::Good)
.unwrap_or_else(|| {
ReplicaStatus::Offline(vec![ReplicaProblem::DiskUnavailable])
.unwrap_or_else(|| ReplicaStatus::Offline {
problems: vec![ReplicaProblem::DiskUnavailable],
}),
},
);
Expand All @@ -251,7 +253,7 @@ pub async fn get_vdisk_by_id(client: &HttpBobClient, vdisk_id: u64) -> AxumResul
let replicas: Vec<_> = replicas.into_values().collect();
let count = replicas
.iter()
.filter(|replica| matches!(replica.status, ReplicaStatus::Offline(_)))
.filter(|replica| matches!(replica.status, ReplicaStatus::Offline { .. }))
.count();
let status = if count == 0 {
VDiskStatus::Good
Expand Down
2 changes: 1 addition & 1 deletion frontend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ readme.workspace = true
repository.workspace = true

[lib]
name = "frontend"
name = "bindings"
path = "/dev/null"
crate-type = ["lib"]

Expand Down
43 changes: 43 additions & 0 deletions frontend/bindings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Some structs that must be redefined for transpiling without changing actual types on backend

#[tsync]
pub type Hostname = String;

// Same as in `backend/src/connector/dto.rs`
// Imported for bindings generation (tsync doesn't respect serde(rename))

/// BOB's Node interface
#[tsync]
pub struct DTONode {
pub name: String,

pub address: String,

pub vdisks: Option<Vec<VDisk>>,
}

/// BOB's Node Configuration interface
#[tsync]
pub struct DTONodeConfiguration {
pub blob_file_name_prefix: Option<String>,

pub root_dir_name: Option<String>,
}

/// BOB's VDisk interface
#[tsync]
pub struct DTOVDisk {
pub id: i32,

pub replicas: Option<Vec<Replica>>,
}

/// BOB's Replica interface
#[tsync]
pub struct DTOReplica {
pub node: String,

pub disk: String,

pub path: String,
}
2 changes: 1 addition & 1 deletion frontend/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub fn build_types() {

inputs[0].push("backend");
inputs[1].push("frontend");
inputs[1].push("frontend.rs");
inputs[1].push("bindings.rs");
output.push("src/types/rust.d.ts");

tsync::generate_typescript_defs(inputs, output, false);
Expand Down
4 changes: 0 additions & 4 deletions frontend/frontend.rs

This file was deleted.

27 changes: 27 additions & 0 deletions frontend/src/components/nodeList/nodeList.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.greendot {
height: 16px;
width: 16px;
background-color: #34b663;
border-radius: 50%;
display: inline-block;
}

.reddot {
height: 16px;
width: 16px;
background-color: #c3234b;
border-radius: 50%;
display: inline-block;
}

.graydot {
height: 16px;
width: 16px;
background-color: #7b817e;
border-radius: 50%;
display: inline-block;
}

.totalspace {
color: #7b817e;
}
Loading

0 comments on commit 4360fc5

Please sign in to comment.