From 342e830e251d39e7f160db6ae75bd997862e22c2 Mon Sep 17 00:00:00 2001 From: Simeon Romanov Date: Wed, 15 Nov 2023 08:57:11 +0300 Subject: [PATCH 1/3] add Home Page --- api/openapi.yaml | 1101 ---------------------------------------------- 1 file changed, 1101 deletions(-) diff --git a/api/openapi.yaml b/api/openapi.yaml index 1d74e2d1..8b137891 100644 --- a/api/openapi.yaml +++ b/api/openapi.yaml @@ -1,1102 +1 @@ -openapi: 3.0.3 -info: - title: bob-management - description: Bob Management GUI - contact: - name: Romanov Simeon ArchArcheoss@proton.me - license: - name: '' - version: 0.0.0 -paths: - /api/v1/disks/count: - get: - tags: - - services::api - summary: Returns count of Physical Disks per status - description: Returns count of Physical Disks per status - operationId: get_disks_count - responses: - '200': - description: Returns a list with count of physical disks per status - content: - application/json: - schema: - $ref: '#/components/schemas/DiskCount' - '401': - description: Unauthorized - security: - - api_key: [] - /api/v1/login: - post: - tags: - - services::auth - summary: Login to a BOB cluster - description: | - Login to a BOB cluster - # Errors - This function can return the following errors - - 1. [`StatusCode::BAD_REQUEST`] - The function failed to parse hostname of the request - - 2. [`StatusCode::NOT_FOUND`] - The client was unable to reach the host - - 3. [`StatusCode::UNAUTHORIZED`] - The client couldn't authorize on the host - operationId: login - parameters: - - name: hostname - in: path - description: Address to connect to - required: true - schema: - $ref: '#/components/schemas/Hostname' - - name: credentials - in: path - description: '[Optional] Credentials used for BOB authentication' - required: true - schema: - allOf: - - $ref: '#/components/schemas/Credentials' - nullable: true - requestBody: - description: '' - content: - application/json: - schema: - $ref: '#/components/schemas/BobConnectionData' - required: true - responses: - '200': - description: Successful authorization - '400': - description: Bad Hostname - '401': - description: Bad Credentials - '404': - description: Can't reach specified hostname - /api/v1/logout: - post: - tags: - - services::auth - operationId: logout - responses: - '200': - description: Logged out - /api/v1/nodes/count: - get: - tags: - - services::api - summary: Get Nodes count per Status - description: Get Nodes count per Status - operationId: get_nodes_count - responses: - '200': - description: Node count list per status - content: - application/json: - schema: - $ref: '#/components/schemas/NodeCount' - '401': - description: Unauthorized - security: - - api_key: [] - /api/v1/nodes/list: - get: - tags: - - services::api - summary: Returns simple list of all known nodes - description: |- - Returns simple list of all known nodes - - # Errors - - This function will return an error if a call to the primary node will fail - operationId: get_nodes_list - responses: - '200': - description: Simple Node List - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/dto.Node' - '401': - description: Unauthorized - security: - - api_key: [] - /api/v1/nodes/rps: - get: - tags: - - services::api - summary: Returns Total RPS on cluster - description: Returns Total RPS on cluster - operationId: get_rps - responses: - '200': - description: RPS list per operation on all nodes - content: - application/json: - schema: - $ref: '#/components/schemas/RPS' - '401': - description: Unauthorized - security: - - api_key: [] - /api/v1/nodes/space: - get: - tags: - - services::api - summary: Return inforamtion about space on cluster - description: Return inforamtion about space on cluster - operationId: get_space - responses: - '200': - description: Cluster Space Information - content: - application/json: - schema: - $ref: '#/components/schemas/SpaceInfo' - '401': - description: Unauthorized - security: - - api_key: [] - /api/v1/nodes/{node_name}: - get: - tags: - - services::api - summary: Returns node inforamtion by their node name - description: |- - Returns node inforamtion by their node name - - # Errors - - This function will return an error if a call to the specified node will fail or node with - specified name not found - operationId: get_node_info - responses: - '200': - description: Node Inforamtion - content: - application/json: - schema: - $ref: '#/components/schemas/Node' - '401': - description: Unauthorized - '404': - description: Node not found - security: - - api_key: [] - /api/v1/nodes/{node_name}/configuration: - get: - tags: - - services::api - summary: Get Configuration from Node - description: |- - Get Configuration from Node - - # Errors - - This function will return an error if the server was unable to get node'a client or the request to get configuration fails - operationId: raw_configuration_by_node - responses: - '200': - description: Node's configuration - content: - application/json: - schema: - $ref: '#/components/schemas/NodeConfiguration' - '401': - description: Unauthorized - '404': - description: Node Not Found - security: - - api_key: [] - /api/v1/nodes/{node_name}/metrics: - get: - tags: - - services::api - summary: Get Raw Metrics from Node - description: |- - Get Raw Metrics from Node - - # Errors - - This function will return an error if the server was unable to get node'a client or the request to get metrics fails - operationId: raw_metrics_by_node - responses: - '200': - description: Node's metrics - content: - application/json: - schema: - $ref: '#/components/schemas/TypedMetrics' - '401': - description: Unauthorized - '404': - description: Node Not Found - security: - - api_key: [] -components: - schemas: - BobConnectionData: - type: object - description: Data needed to connect to a BOB cluster - required: - - hostname - properties: - credentials: - allOf: - - $ref: '#/components/schemas/Credentials' - nullable: true - hostname: - $ref: '#/components/schemas/Hostname' - example: - credentials: - login: archeoss - password: '12345' - hostname: 0.0.0.0:7000 - Credentials: - type: object - description: Optional auth credentials for a BOB cluster - required: - - login - - password - properties: - login: - type: string - description: Login used during auth - password: - type: string - description: Password used during auth - example: - login: archeoss - password: '12345' - Disk: - type: object - description: Physical disk definition - required: - - name - - path - - status - - totalSpace - - usedSpace - - iops - properties: - iops: - type: integer - format: int64 - minimum: 0 - name: - type: string - description: Disk name - path: - type: string - description: Disk path - status: - $ref: '#/components/schemas/DiskStatus' - totalSpace: - type: integer - format: int64 - minimum: 0 - usedSpace: - type: integer - format: int64 - minimum: 0 - DiskCount: - type: object - description: Disk count by their status - required: - - good - - bad - - offline - properties: - bad: - type: integer - format: int64 - minimum: 0 - good: - type: integer - format: int64 - minimum: 0 - offline: - type: integer - format: int64 - minimum: 0 - example: - bad: 0 - good: 0 - offline: 0 - DiskProblem: - type: string - description: Defines kind of problem on disk - enum: - - freeSpaceRunningOut - DiskStatus: - oneOf: - - type: object - required: - - status - properties: - status: - type: string - enum: - - good - - type: object - required: - - status - - problems - properties: - problems: - type: object - required: - - problems - properties: - problems: - type: array - items: - $ref: '#/components/schemas/DiskProblem' - status: - type: string - enum: - - bad - - type: object - required: - - status - properties: - status: - type: string - enum: - - offline - description: |- - Defines disk status - - Variant - Disk Status - Content - List of problems on disk. 'null' if status != 'bad' - discriminator: - propertyName: status - DiskStatusName: - type: string - description: Defines disk status names - enum: - - good - - bad - - offline - Hostname: - type: string - MetricsEntryModel: - type: object - required: - - value - - timestamp - properties: - timestamp: - type: integer - format: int64 - minimum: 0 - value: - type: integer - format: int64 - minimum: 0 - MetricsSnapshotModel: - type: object - required: - - metrics - properties: - metrics: - type: object - additionalProperties: - $ref: '#/components/schemas/MetricsEntryModel' - NodeConfiguration: - type: object - properties: - blob_file_name_prefix: - type: string - nullable: true - root_dir_name: - type: string - nullable: true - NodeCount: - type: object - description: Node count by their status - required: - - good - - bad - - offline - properties: - bad: - type: integer - format: int64 - minimum: 0 - good: - type: integer - format: int64 - minimum: 0 - offline: - type: integer - format: int64 - minimum: 0 - example: - bad: 0 - good: 0 - offline: 0 - NodeInfo: - type: object - required: - - name - - hostname - - vdisks - - status - properties: - alienCount: - type: integer - format: int64 - nullable: true - minimum: 0 - corruptedCount: - type: integer - format: int64 - nullable: true - minimum: 0 - hostname: - type: string - name: - type: string - rps: - allOf: - - $ref: '#/components/schemas/RPS' - nullable: true - space: - allOf: - - $ref: '#/components/schemas/SpaceInfo' - nullable: true - status: - $ref: '#/components/schemas/NodeStatus' - vdisks: - type: array - items: - $ref: '#/components/schemas/VDisk' - NodeProblem: - type: string - description: Defines kind of problem on Node - enum: - - aliensExists - - corruptedExists - - freeSpaceRunningOut - - virtualMemLargerThanRAM - - highCPULoad - NodeStatus: - oneOf: - - type: object - required: - - status - properties: - status: - type: string - enum: - - good - - type: object - required: - - status - - problems - properties: - problems: - type: object - required: - - problems - properties: - problems: - type: array - items: - $ref: '#/components/schemas/NodeProblem' - status: - type: string - enum: - - bad - - type: object - required: - - status - properties: - status: - type: string - enum: - - offline - description: |- - Defines status of node - - Variants - Node status - - Content - List of problems on node. 'null' if status != 'bad' - discriminator: - propertyName: status - NodeStatusName: - type: string - description: Defines node status names - enum: - - good - - bad - - offline - Operation: - type: string - description: Types of operations on BOB cluster - enum: - - put - - get - - exist - - delete - RPS: - type: object - description: Requests per second by operation - required: - - put - - get - - exist - - delete - properties: - delete: - type: integer - format: int64 - minimum: 0 - exist: - type: integer - format: int64 - minimum: 0 - get: - type: integer - format: int64 - minimum: 0 - put: - type: integer - format: int64 - minimum: 0 - example: - delete: 0 - exist: 0 - get: 0 - put: 0 - RawMetricEntry: - type: string - enum: - - cluster_grinder.get_count_rate - - cluster_grinder.put_count_rate - - cluster_grinder.exist_count_rate - - cluster_grinder.delete_count_rate - - pearl.exist_count_rate - - pearl.get_count_rate - - pearl.put_count_rate - - pearl.delete_count_rate - - backend.alien_count - - backend.corrupted_blob_count - - hardware.bob_virtual_ram - - hardware.total_ram - - hardware.used_ram - - hardware.bob_cpu_load - - hardware.free_space - - hardware.total_space - - hardware.descr_amount - Replica: - type: object - description: '[`VDisk`]''s replicas' - required: - - node - - disk - - path - - status - properties: - disk: - type: string - node: - type: string - path: - type: string - status: - $ref: '#/components/schemas/ReplicaStatus' - ReplicaProblem: - type: string - description: Reasons why Replica is offline - enum: - - nodeUnavailable - - diskUnavailable - ReplicaStatus: - oneOf: - - type: object - required: - - status - properties: - status: - type: string - enum: - - good - - type: object - required: - - status - - problems - properties: - problems: - type: object - required: - - problems - properties: - problems: - type: array - items: - $ref: '#/components/schemas/ReplicaProblem' - status: - type: string - enum: - - offline - description: |- - Replica status. It's either good or offline with the reasons why it is offline - - Variants - Replica status - - Content - List of problems on replica. 'null' if status != 'offline' - discriminator: - propertyName: status - SpaceInfo: - type: object - description: Disk space information in bytes - required: - - total_disk - - free_disk - - used_disk - - occupied_disk - properties: - free_disk: - type: integer - format: int64 - description: The amount of free disk space - minimum: 0 - occupied_disk: - type: integer - format: int64 - description: Disk space occupied only by BOB. occupied_disk should be lesser than used_disk - minimum: 0 - total_disk: - type: integer - format: int64 - description: Total disk space amount - minimum: 0 - used_disk: - type: integer - format: int64 - description: Used disk space amount - minimum: 0 - TypedMetrics: - type: object - description: Raw metrics information - required: - - cluster_grinder.get_count_rate - - cluster_grinder.put_count_rate - - cluster_grinder.exist_count_rate - - cluster_grinder.delete_count_rate - - pearl.exist_count_rate - - pearl.get_count_rate - - pearl.put_count_rate - - pearl.delete_count_rate - - backend.alien_count - - backend.corrupted_blob_count - - hardware.bob_virtual_ram - - hardware.total_ram - - hardware.used_ram - - hardware.bob_cpu_load - - hardware.free_space - - hardware.total_space - - hardware.descr_amount - properties: - backend.alien_count: - type: object - required: - - value - - timestamp - properties: - timestamp: - type: integer - format: int64 - minimum: 0 - value: - type: integer - format: int64 - minimum: 0 - backend.corrupted_blob_count: - type: object - required: - - value - - timestamp - properties: - timestamp: - type: integer - format: int64 - minimum: 0 - value: - type: integer - format: int64 - minimum: 0 - cluster_grinder.delete_count_rate: - type: object - required: - - value - - timestamp - properties: - timestamp: - type: integer - format: int64 - minimum: 0 - value: - type: integer - format: int64 - minimum: 0 - cluster_grinder.exist_count_rate: - type: object - required: - - value - - timestamp - properties: - timestamp: - type: integer - format: int64 - minimum: 0 - value: - type: integer - format: int64 - minimum: 0 - cluster_grinder.get_count_rate: - type: object - required: - - value - - timestamp - properties: - timestamp: - type: integer - format: int64 - minimum: 0 - value: - type: integer - format: int64 - minimum: 0 - cluster_grinder.put_count_rate: - type: object - required: - - value - - timestamp - properties: - timestamp: - type: integer - format: int64 - minimum: 0 - value: - type: integer - format: int64 - minimum: 0 - hardware.bob_cpu_load: - type: object - required: - - value - - timestamp - properties: - timestamp: - type: integer - format: int64 - minimum: 0 - value: - type: integer - format: int64 - minimum: 0 - hardware.bob_virtual_ram: - type: object - required: - - value - - timestamp - properties: - timestamp: - type: integer - format: int64 - minimum: 0 - value: - type: integer - format: int64 - minimum: 0 - hardware.descr_amount: - type: object - required: - - value - - timestamp - properties: - timestamp: - type: integer - format: int64 - minimum: 0 - value: - type: integer - format: int64 - minimum: 0 - hardware.free_space: - type: object - required: - - value - - timestamp - properties: - timestamp: - type: integer - format: int64 - minimum: 0 - value: - type: integer - format: int64 - minimum: 0 - hardware.total_ram: - type: object - required: - - value - - timestamp - properties: - timestamp: - type: integer - format: int64 - minimum: 0 - value: - type: integer - format: int64 - minimum: 0 - hardware.total_space: - type: object - required: - - value - - timestamp - properties: - timestamp: - type: integer - format: int64 - minimum: 0 - value: - type: integer - format: int64 - minimum: 0 - hardware.used_ram: - type: object - required: - - value - - timestamp - properties: - timestamp: - type: integer - format: int64 - minimum: 0 - value: - type: integer - format: int64 - minimum: 0 - pearl.delete_count_rate: - type: object - required: - - value - - timestamp - properties: - timestamp: - type: integer - format: int64 - minimum: 0 - value: - type: integer - format: int64 - minimum: 0 - pearl.exist_count_rate: - type: object - required: - - value - - timestamp - properties: - timestamp: - type: integer - format: int64 - minimum: 0 - value: - type: integer - format: int64 - minimum: 0 - pearl.get_count_rate: - type: object - required: - - value - - timestamp - properties: - timestamp: - type: integer - format: int64 - minimum: 0 - value: - type: integer - format: int64 - minimum: 0 - pearl.put_count_rate: - type: object - required: - - value - - timestamp - properties: - timestamp: - type: integer - format: int64 - minimum: 0 - value: - type: integer - format: int64 - minimum: 0 - example: - backend.alien_count: - timestamp: 0 - value: 0 - backend.corrupted_blob_count: - timestamp: 0 - value: 0 - cluster_grinder.delete_count_rate: - timestamp: 0 - value: 0 - cluster_grinder.exist_count_rate: - timestamp: 0 - value: 0 - cluster_grinder.get_count_rate: - timestamp: 0 - value: 0 - cluster_grinder.put_count_rate: - timestamp: 0 - value: 0 - hardware.bob_cpu_load: - timestamp: 0 - value: 0 - hardware.bob_virtual_ram: - timestamp: 0 - value: 0 - hardware.descr_amount: - timestamp: 0 - value: 0 - hardware.free_space: - timestamp: 0 - value: 0 - hardware.total_ram: - timestamp: 0 - value: 0 - hardware.total_space: - timestamp: 0 - value: 0 - hardware.used_ram: - timestamp: 0 - value: 0 - pearl.delete_count_rate: - timestamp: 0 - value: 0 - pearl.exist_count_rate: - timestamp: 0 - value: 0 - pearl.get_count_rate: - timestamp: 0 - value: 0 - pearl.put_count_rate: - timestamp: 0 - value: 0 - VDisk: - type: object - description: Virtual disk Component - required: - - id - - status - - partitionCount - - replicas - properties: - id: - type: integer - format: int64 - minimum: 0 - partitionCount: - type: integer - format: int64 - minimum: 0 - replicas: - type: array - items: - $ref: '#/components/schemas/Replica' - status: - $ref: '#/components/schemas/VDiskStatus' - VDiskStatus: - oneOf: - - type: object - required: - - status - properties: - status: - type: string - enum: - - good - - type: object - required: - - status - properties: - status: - type: string - enum: - - bad - - type: object - required: - - status - properties: - status: - type: string - enum: - - offline - description: |- - Virtual disk status. - - Variants - Virtual Disk status - status == 'bad' when at least one of its replicas has problems - dto.Node: - type: object - required: - - name - - address - properties: - address: - type: string - name: - type: string - vdisks: - type: array - items: - $ref: '#/components/schemas/dto.VDisk' - nullable: true - dto.Replica: - type: object - required: - - node - - disk - - path - properties: - disk: - type: string - node: - type: string - path: - type: string - dto.VDisk: - type: object - required: - - id - properties: - id: - type: integer - format: int32 - replicas: - type: array - items: - $ref: '#/components/schemas/dto.Replica' - nullable: true - securitySchemes: - api_key: - type: apiKey - in: header - name: bob_apikey -tags: -- name: bob - description: BOB management API From a4bb10dfe5eb12a52967cd9ad0b02005d53d7653 Mon Sep 17 00:00:00 2001 From: Simeon Romanov Date: Thu, 9 Nov 2023 07:25:15 +0300 Subject: [PATCH 2/3] VDisk list page added --- CHANGELOG.md | 1 + backend/src/lib.rs | 2 + backend/src/models/api.rs | 16 +- backend/src/services/api.rs | 30 +++- backend/src/services/mod.rs | 4 + .../src/components/VDiskList/VDiskList.tsx | 114 ++++++++++++++ .../VDiskTable/VDiskTable.module.css | 27 ++++ .../src/components/VDiskTable/VDiskTable.tsx | 145 ++++++++++++++++++ .../src/components/diskState/diskState.tsx | 20 +-- .../src/components/nodeTable/nodeTable.tsx | 10 +- .../src/components/totalNodes/totalNodes.tsx | 20 +-- frontend/src/pages/vdisklist/index.astro | 10 ++ .../{vdiskslist => vdisklist}/page.module.css | 0 frontend/src/pages/vdiskslist/index.astro | 5 - frontend/src/types/data.d.ts | 13 ++ frontend/src/types/rust.d.ts | 12 +- 16 files changed, 382 insertions(+), 47 deletions(-) create mode 100644 frontend/src/components/VDiskList/VDiskList.tsx create mode 100644 frontend/src/components/VDiskTable/VDiskTable.module.css create mode 100644 frontend/src/components/VDiskTable/VDiskTable.tsx create mode 100644 frontend/src/pages/vdisklist/index.astro rename frontend/src/pages/{vdiskslist => vdisklist}/page.module.css (100%) delete mode 100644 frontend/src/pages/vdiskslist/index.astro diff --git a/CHANGELOG.md b/CHANGELOG.md index 12716910..65639372 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,3 +17,4 @@ Bob Management GUI changelog - Node list page, backend (#19) - Home page, frontend (#22) - Node list page, frontend (#23) +- VDisk list page, backend (#20) diff --git a/backend/src/lib.rs b/backend/src/lib.rs index 21fb1523..59a828b2 100644 --- a/backend/src/lib.rs +++ b/backend/src/lib.rs @@ -45,6 +45,8 @@ impl Modify for SecurityAddon { services::api::raw_configuration_by_node, services::api::get_node_info, services::api::get_nodes_list, + services::api::get_vdisk_info, + services::api::get_vdisks_list, ), components( schemas(models::shared::Credentials, models::shared::Hostname, models::shared::BobConnectionData, diff --git a/backend/src/models/api.rs b/backend/src/models/api.rs index a2eb1a33..33517d40 100644 --- a/backend/src/models/api.rs +++ b/backend/src/models/api.rs @@ -51,11 +51,8 @@ pub enum DiskProblem { #[cfg_attr(all(feature = "swagger", debug_assertions), derive(ToSchema))] #[tsync] pub enum DiskStatus { - #[serde(rename = "good")] Good, - #[serde(rename = "bad")] Bad { problems: Vec }, - #[serde(rename = "offline")] Offline, } @@ -82,7 +79,6 @@ impl DiskStatus { /// Defines disk status names #[derive(Debug, Clone, Eq, PartialEq, Serialize, Hash, EnumIter)] -#[serde(rename_all = "camelCase")] #[cfg_attr(all(feature = "swagger", debug_assertions), derive(ToSchema))] #[tsync] pub enum DiskStatusName { @@ -190,11 +186,8 @@ impl NodeProblem { #[cfg_attr(all(feature = "swagger", debug_assertions), derive(ToSchema))] #[tsync] pub enum NodeStatus { - #[serde(rename = "good")] Good, - #[serde(rename = "bad")] Bad { problems: Vec }, - #[serde(rename = "offline")] Offline, } @@ -227,7 +220,6 @@ impl TypedMetrics { /// Defines node status names #[derive(Debug, Clone, Eq, PartialEq, Serialize, Hash, EnumIter)] -#[serde(rename_all = "camelCase")] #[cfg_attr(all(feature = "swagger", debug_assertions), derive(ToSchema))] #[tsync] pub enum NodeStatusName { @@ -273,9 +265,7 @@ pub enum ReplicaProblem { #[cfg_attr(all(feature = "swagger", debug_assertions), derive(ToSchema))] #[tsync] pub enum ReplicaStatus { - #[serde(rename = "good")] Good, - #[serde(rename = "offline")] Offline { problems: Vec }, } @@ -330,6 +320,7 @@ impl Add for SpaceInfo { /// Virtual disk Component #[derive(Debug, Clone, Eq, PartialEq, Serialize)] #[cfg_attr(all(feature = "swagger", debug_assertions), derive(ToSchema))] +#[tsync] pub struct VDisk { pub id: u64, @@ -347,17 +338,14 @@ pub struct VDisk { /// Variants - Virtual Disk status /// status == 'bad' when at least one of its replicas has problems #[derive(Debug, Clone, Eq, PartialEq, Serialize)] -#[serde(tag = "status")] +// #[serde(tag = "status")] #[cfg_attr(all(feature = "swagger", debug_assertions), derive(ToSchema))] #[tsync] // #[cfg_attr(all(feature = "swagger", debug_assertions), // schema(example = json!({"status": "good"})))] pub enum VDiskStatus { - #[serde(rename = "good")] Good, - #[serde(rename = "bad")] Bad, - #[serde(rename = "offline")] Offline, } diff --git a/backend/src/services/api.rs b/backend/src/services/api.rs index fee57f4d..b684fdf4 100644 --- a/backend/src/services/api.rs +++ b/backend/src/services/api.rs @@ -1,4 +1,8 @@ -use super::prelude::*; +use super::{auth::HttpClient, prelude::*}; + +// TODO: For methods, that requires information from all nodes (/disks/count, /nodes/rps, etc.), +// think of better method of returning info +// another thread that constantly updates info in period and cache the results? // TODO: For methods, that requires information from all nodes (/disks/count, /nodes/rps, etc.), // think of better method of returning info @@ -458,3 +462,27 @@ pub async fn raw_configuration_by_node( .await?, )) } + +async fn get_client_by_node( + client: &HttpBobClient, + node_name: NodeName, +) -> AxumResult> { + let nodes = fetch_nodes(client.api_main()).await?; + + let node = nodes + .iter() + .find(|node| node.name == node_name) + .ok_or_else(|| { + tracing::error!("Couldn't find specified node"); + APIError::RequestFailed + })?; + + client + .cluster_with_addr() + .get(&node.name) + .ok_or_else(|| { + tracing::error!("Couldn't find specified node"); + APIError::RequestFailed.into() + }) + .cloned() +} diff --git a/backend/src/services/mod.rs b/backend/src/services/mod.rs index 7ac21ae8..659220fe 100644 --- a/backend/src/services/mod.rs +++ b/backend/src/services/mod.rs @@ -32,6 +32,8 @@ use api::{ use auth::{login, logout, require_auth, AuthState, BobUser, HttpBobClient, InMemorySessionStore}; use prelude::*; +use self::api::{get_vdisk_info, get_vdisks_list}; + type BobAuthState = AuthState< BobUser, Uuid, @@ -54,6 +56,8 @@ pub fn api_router_v1(auth_state: BobAuthState) -> Result, R .api_route("/nodes/space", &Method::GET, get_space) .api_route("/nodes/list", &Method::GET, get_nodes_list) .api_route("/nodes/:node_name", &Method::GET, get_node_info) + .api_route("/vdisks/list", &Method::GET, get_vdisks_list) + .api_route("/vdisks/:vdisk_id", &Method::GET, get_vdisk_info) .api_route( "/nodes/:node_name/metrics", &Method::GET, diff --git a/frontend/src/components/VDiskList/VDiskList.tsx b/frontend/src/components/VDiskList/VDiskList.tsx new file mode 100644 index 00000000..64d163bf --- /dev/null +++ b/frontend/src/components/VDiskList/VDiskList.tsx @@ -0,0 +1,114 @@ +import { Context } from '@appTypes/context.ts'; +import defaultTheme from '@layouts/DefaultTheme.ts'; +import { Box, ThemeProvider } from '@mui/system'; +import { useStore } from '@nanostores/react'; +import axios from 'axios'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; + +import FetchingBackdrop from '../backdrop/backdrop.tsx'; +import VDiskTable from '../VDiskTable/VDiskTable.tsx'; + +const stubVDisk: VDisk = { + id: 0, + status: 'Offline', + partition_count: 0, + replicas: [], +}; + +axios.defaults.withCredentials = true; + +const VDiskPage = () => { + const [vdisks, setVdisks] = useState([]); + const [vdiskList, setVdiskList] = useState([]); + const [isPageLoaded, setIsPageLoaded] = useState(false); + const context = useStore(Context); + + const fetchVdiskList = useMemo( + () => async () => { + try { + const [res] = await Promise.all([axios.get('/api/v1/vdisks/list')]); + setVdisks( + res.data + .map((dtoVdisk: DTOVDisk) => { + return { + ...stubVDisk, + id: dtoVdisk.id, + } as VDisk; + }) + .sort((a, b) => (a.id < b.id ? -1 : 1)), + ); + setVdiskList(res.data); + } catch (err) { + console.log(err); + } + }, + [], + ); + + const fetchVdisk = useCallback( + (vdisk: number) => async () => { + try { + const [res] = await Promise.all([axios.get('/api/v1/vdisks/' + vdisk)]); + return res.data; + } catch (err) { + console.log(err); + } + }, + [], + ); + useEffect(() => { + fetchVdiskList(); + }, [fetchVdiskList]); + + useEffect(() => { + const fetchNodes = async () => { + const res = ( + await Promise.all( + vdiskList.map(async (vdisk) => { + return fetchVdisk(vdisk.id)() + .catch(console.error) + .then((resultVdisk) => resultVdisk); + }), + ) + ).filter((vdisk): vdisk is VDisk => { + return typeof vdisk !== undefined; + }); + setVdisks(res.concat(vdisks.filter((item) => !res.find((n) => (n?.id || '') == item.id)))); + }; + if (!isPageLoaded && vdiskList.length !== 0) { + fetchNodes(); + setIsPageLoaded(true); + } + const interval = setInterval(() => { + fetchNodes(); + }, context.refreshTime * 1000); + + return () => clearInterval(interval); + }, [isPageLoaded, fetchVdisk, context.enabled, context.refreshTime, vdiskList, vdisks]); + + if (!isPageLoaded) { + return ; + } + return ( + + + + + + ); +}; + +export default VDiskPage; diff --git a/frontend/src/components/VDiskTable/VDiskTable.module.css b/frontend/src/components/VDiskTable/VDiskTable.module.css new file mode 100644 index 00000000..6a01bc59 --- /dev/null +++ b/frontend/src/components/VDiskTable/VDiskTable.module.css @@ -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; +} + +.greyHeader { + background-color: #35373c; +} diff --git a/frontend/src/components/VDiskTable/VDiskTable.tsx b/frontend/src/components/VDiskTable/VDiskTable.tsx new file mode 100644 index 00000000..4e4d7472 --- /dev/null +++ b/frontend/src/components/VDiskTable/VDiskTable.tsx @@ -0,0 +1,145 @@ +import { Box } from '@mui/system'; +import { + DataGrid, + type GridColDef, + type GridRenderCellParams, + GridToolbar, + type GridValidRowModel, +} from '@mui/x-data-grid'; +import React from 'react'; + +import style from './VDiskTable.module.css'; + +const BarLabelColor: Record = { + Good: style.greendot, + Bad: style.graydot, + Offline: style.reddot, +}; + +const columns: GridColDef[] = [ + { + field: 'vdiskid', + headerName: 'VDisk Number', + flex: 1, + align: 'center', + headerAlign: 'center', + headerClassName: style.greyHeader, + }, + { + field: 'replicas', + headerName: 'Replicas on nodes', + flex: 3, + align: 'center', + headerAlign: 'center', + headerClassName: style.greyHeader, + renderCell: (params: GridRenderCellParams) => { + return ( + + {params.value?.map((replica) => replica.node).join(', ') || ''} + + ); + }, + }, + { + field: 'availability', + headerName: 'Availability', + flex: 1, + align: 'center', + headerAlign: 'center', + headerClassName: style.greyHeader, + renderCell: (params: GridRenderCellParams) => { + return ( + + + {params.value?.goodReplicas || 0} / {params.value?.totalReplicas || 0} + + + ); + }, + }, + { + field: 'status', + headerName: 'Status', + flex: 1, + align: 'left', + headerAlign: 'center', + headerClassName: style.greyHeader, + renderCell: (params: GridRenderCellParams) => { + const status = params.value || 'Offline'; + return ( + + + {params.value} + + ); + }, + }, +]; +const VDiskTable = ({ vdisks }: { vdisks: VDisk[] }) => { + const data = vdisks.sort() + ? vdisks.map((vdisk, i) => { + return { + id: i, + vdiskid: vdisk.id, + replicas: vdisk.replicas, + availability: { + goodReplicas: vdisk.replicas.filter((replica) => replica.status.status === 'Good').length, + totalReplicas: vdisk.replicas.length, + }, + status: vdisk.status, + } as VDiskTableCols; + }) + : []; + return ( + searchInput.split(',').map((value) => value.trim()), + }, + }, + }} + /> + ); +}; + +export default VDiskTable; diff --git a/frontend/src/components/diskState/diskState.tsx b/frontend/src/components/diskState/diskState.tsx index ba3b4140..000e9192 100644 --- a/frontend/src/components/diskState/diskState.tsx +++ b/frontend/src/components/diskState/diskState.tsx @@ -4,19 +4,19 @@ import React from 'react'; import style from './diskState.module.css'; const BarColor: Record = { - good: '#5EB36B', - bad: '#7C817E', - offline: '#B3344D', + Good: '#5EB36B', + Bad: '#7C817E', + Offline: '#B3344D', }; const BarLabelColor: Record = { - good: style.totalGoodDisksLabel, - bad: style.totalBadDisksLabel, - offline: style.totalOfflineDisksLabel, + Good: style.totalGoodDisksLabel, + Bad: style.totalBadDisksLabel, + Offline: style.totalOfflineDisksLabel, }; const DiskState = ({ diskCount, status }: { diskCount: Record; status: DiskStatusName }) => { - const total = diskCount.good + diskCount.bad + diskCount.offline; + const total = diskCount.Good + diskCount.Bad + diskCount.Offline; const percent = Math.floor((diskCount[status] / total) * 100) || 0; return (

State of the physical disks in the cluster

- - - + + +
); }; diff --git a/frontend/src/components/nodeTable/nodeTable.tsx b/frontend/src/components/nodeTable/nodeTable.tsx index c8609f86..36642a76 100644 --- a/frontend/src/components/nodeTable/nodeTable.tsx +++ b/frontend/src/components/nodeTable/nodeTable.tsx @@ -11,9 +11,9 @@ import style from './nodeTable.module.css'; axios.defaults.withCredentials = true; const DotMap: Record = { - good: style.greendot, - bad: style.graydot, - offline: style.reddot, + Good: style.greendot, + Bad: style.graydot, + Offline: style.reddot, }; const defaultRps: RPS = { @@ -68,7 +68,7 @@ const columns: GridColDef[] = [ headerAlign: 'center', headerClassName: style.greyHeader, renderCell: (params: GridRenderCellParams) => { - const status = params.value || 'offline'; + const status = params.value || 'Offline'; return ( { id: i, nodename: node.name, hostname: node.hostname, - status: node.status.status.toLowerCase(), + status: node.status.status, space: node.space, rps: node.rps, aliens: node.alienCount || 0, diff --git a/frontend/src/components/totalNodes/totalNodes.tsx b/frontend/src/components/totalNodes/totalNodes.tsx index 6b6ad0f9..c9ddbbe5 100644 --- a/frontend/src/components/totalNodes/totalNodes.tsx +++ b/frontend/src/components/totalNodes/totalNodes.tsx @@ -4,19 +4,19 @@ import React from 'react'; import style from './totalNodes.module.css'; const NodeColor: Record = { - good: '#5EB36B', - bad: '#7C817E', - offline: '#B3344D', + Good: '#5EB36B', + Bad: '#7C817E', + Offline: '#B3344D', }; const NodeLabelColor: Record = { - good: style.totalGoodNodesLabel, - bad: style.totalBadNodesLabel, - offline: style.totalOfflineNodesLabel, + Good: style.totalGoodNodesLabel, + Bad: style.totalBadNodesLabel, + Offline: style.totalOfflineNodesLabel, }; const NodeState = ({ nodeCount, status }: { nodeCount: Record; status: NodeStatusName }) => { - const total = nodeCount.good + nodeCount.bad + nodeCount.offline; + const total = nodeCount.Good + nodeCount.Bad + nodeCount.Offline; const percent = Math.floor((nodeCount[status] / total) * 100) || 0; return ( }} >

State of the nodes in the cluster

- - - + + +
); }; diff --git a/frontend/src/pages/vdisklist/index.astro b/frontend/src/pages/vdisklist/index.astro new file mode 100644 index 00000000..6d07c6a6 --- /dev/null +++ b/frontend/src/pages/vdisklist/index.astro @@ -0,0 +1,10 @@ +--- +import Layout from '@layouts/Layout.astro'; +import VDiskPage from '@components/VDiskList/VDiskList.tsx'; +--- + + +
+ +
+
diff --git a/frontend/src/pages/vdiskslist/page.module.css b/frontend/src/pages/vdisklist/page.module.css similarity index 100% rename from frontend/src/pages/vdiskslist/page.module.css rename to frontend/src/pages/vdisklist/page.module.css diff --git a/frontend/src/pages/vdiskslist/index.astro b/frontend/src/pages/vdiskslist/index.astro deleted file mode 100644 index 8309eb95..00000000 --- a/frontend/src/pages/vdiskslist/index.astro +++ /dev/null @@ -1,5 +0,0 @@ ---- -import Layout from '@layouts/Layout.astro'; ---- - - diff --git a/frontend/src/types/data.d.ts b/frontend/src/types/data.d.ts index 07e37272..b04db5b7 100644 --- a/frontend/src/types/data.d.ts +++ b/frontend/src/types/data.d.ts @@ -22,3 +22,16 @@ interface NodeTableCols { aliens?: number; corruptedBlobs?: number; } + +interface ReplicaCount { + goodReplicas: number; + totalReplicas: number; +} + +interface VDiskTableCols { + id: number; + vdiskid: number; + replicas: Replica[]; + availability: ReplicaCount; + status: VDiskStatus; +} diff --git a/frontend/src/types/rust.d.ts b/frontend/src/types/rust.d.ts index 294e15d9..07e8a814 100644 --- a/frontend/src/types/rust.d.ts +++ b/frontend/src/types/rust.d.ts @@ -41,7 +41,7 @@ type DiskStatus__Offline = { /** Defines disk status names */ type DiskStatusName = - | "good" | "bad" | "offline"; + | "Good" | "Bad" | "Offline"; interface NodeInfo { name: string; @@ -83,7 +83,7 @@ type NodeStatus__Offline = { /** Defines node status names */ type NodeStatusName = - | "good" | "bad" | "offline"; + | "Good" | "Bad" | "Offline"; /** [`VDisk`]'s replicas */ interface Replica { @@ -128,6 +128,14 @@ interface SpaceInfo { occupied_disk: number; } +/** Virtual disk Component */ +interface VDisk { + id: number; + status: VDiskStatus; + partition_count: number; + replicas: Array; +} + /** * Virtual disk status. * From 55003318492b8d135b235d3547c96dd91ea1fd87 Mon Sep 17 00:00:00 2001 From: archeoss Date: Sun, 3 Mar 2024 17:17:36 +0000 Subject: [PATCH 3/3] Autogenerate API --- api/openapi.yaml | 1140 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1140 insertions(+) diff --git a/api/openapi.yaml b/api/openapi.yaml index 8b137891..2e4a9134 100644 --- a/api/openapi.yaml +++ b/api/openapi.yaml @@ -1 +1,1141 @@ +openapi: 3.0.3 +info: + title: bob-management + description: Bob Management GUI + contact: + name: Romanov Simeon ArchArcheoss@proton.me + license: + name: '' + version: 0.0.0 +paths: + /api/v1/disks/count: + get: + tags: + - services::api + summary: Returns count of Physical Disks per status + description: Returns count of Physical Disks per status + operationId: get_disks_count + responses: + '200': + description: Returns a list with count of physical disks per status + content: + application/json: + schema: + $ref: '#/components/schemas/DiskCount' + '401': + description: Unauthorized + security: + - api_key: [] + /api/v1/login: + post: + tags: + - services::auth + summary: Login to a BOB cluster + description: | + Login to a BOB cluster + # Errors + This function can return the following errors + + 1. [`StatusCode::BAD_REQUEST`] + The function failed to parse hostname of the request + + 2. [`StatusCode::NOT_FOUND`] + The client was unable to reach the host + + 3. [`StatusCode::UNAUTHORIZED`] + The client couldn't authorize on the host + operationId: login + parameters: + - name: hostname + in: path + description: Address to connect to + required: true + schema: + $ref: '#/components/schemas/Hostname' + - name: credentials + in: path + description: '[Optional] Credentials used for BOB authentication' + required: true + schema: + allOf: + - $ref: '#/components/schemas/Credentials' + nullable: true + requestBody: + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/BobConnectionData' + required: true + responses: + '200': + description: Successful authorization + '400': + description: Bad Hostname + '401': + description: Bad Credentials + '404': + description: Can't reach specified hostname + /api/v1/logout: + post: + tags: + - services::auth + operationId: logout + responses: + '200': + description: Logged out + /api/v1/nodes/count: + get: + tags: + - services::api + summary: Get Nodes count per Status + description: Get Nodes count per Status + operationId: get_nodes_count + responses: + '200': + description: Node count list per status + content: + application/json: + schema: + $ref: '#/components/schemas/NodeCount' + '401': + description: Unauthorized + security: + - api_key: [] + /api/v1/nodes/list: + get: + tags: + - services::api + summary: Returns simple list of all known nodes + description: |- + Returns simple list of all known nodes + + # Errors + + This function will return an error if a call to the primary node will fail + operationId: get_nodes_list + responses: + '200': + description: Simple Node List + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/dto.Node' + '401': + description: Unauthorized + security: + - api_key: [] + /api/v1/nodes/rps: + get: + tags: + - services::api + summary: Returns Total RPS on cluster + description: Returns Total RPS on cluster + operationId: get_rps + responses: + '200': + description: RPS list per operation on all nodes + content: + application/json: + schema: + $ref: '#/components/schemas/RPS' + '401': + description: Unauthorized + security: + - api_key: [] + /api/v1/nodes/space: + get: + tags: + - services::api + summary: Return inforamtion about space on cluster + description: Return inforamtion about space on cluster + operationId: get_space + responses: + '200': + description: Cluster Space Information + content: + application/json: + schema: + $ref: '#/components/schemas/SpaceInfo' + '401': + description: Unauthorized + security: + - api_key: [] + /api/v1/nodes/{node_name}: + get: + tags: + - services::api + summary: Returns node inforamtion by their node name + description: |- + Returns node inforamtion by their node name + + # Errors + + This function will return an error if a call to the specified node will fail or node with + specified name not found + operationId: get_node_info + responses: + '200': + description: Node Inforamtion + content: + application/json: + schema: + $ref: '#/components/schemas/Node' + '401': + description: Unauthorized + '404': + description: Node not found + security: + - api_key: [] + /api/v1/nodes/{node_name}/configuration: + get: + tags: + - services::api + summary: Get Configuration from Node + description: |- + Get Configuration from Node + + # Errors + + This function will return an error if the server was unable to get node'a client or the request to get configuration fails + operationId: raw_configuration_by_node + responses: + '200': + description: Node's configuration + content: + application/json: + schema: + $ref: '#/components/schemas/NodeConfiguration' + '401': + description: Unauthorized + '404': + description: Node Not Found + security: + - api_key: [] + /api/v1/nodes/{node_name}/metrics: + get: + tags: + - services::api + summary: Get Raw Metrics from Node + description: |- + Get Raw Metrics from Node + + # Errors + + This function will return an error if the server was unable to get node'a client or the request to get metrics fails + operationId: raw_metrics_by_node + responses: + '200': + description: Node's metrics + content: + application/json: + schema: + $ref: '#/components/schemas/TypedMetrics' + '401': + description: Unauthorized + '404': + description: Node Not Found + security: + - api_key: [] + /api/v1/vdisks/list: + get: + tags: + - services::api + summary: Returns simple list of all known vdisks + description: |- + Returns simple list of all known vdisks + + # Errors + + This function will return an error if a call to the primary node will fail + operationId: get_vdisks_list + responses: + '200': + description: Simple Node List + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/dto.VDisk' + '401': + description: Unauthorized + security: + - api_key: [] + /api/v1/vdisks/{vdisk_id}: + get: + tags: + - services::api + summary: Returns vdisk inforamtion by their id + description: |- + Returns vdisk inforamtion by their id + + # Errors + + This function will return an error if a call to the main node will fail or vdisk with + specified id not found + operationId: get_vdisk_info + parameters: + - name: vdisk_id + in: path + required: true + schema: + type: integer + format: int64 + minimum: 0 + responses: + '200': + description: VDisk Inforamtion + content: + application/json: + schema: + $ref: '#/components/schemas/VDisk' + '401': + description: Unauthorized + '404': + description: VDisk not found + security: + - api_key: [] +components: + schemas: + BobConnectionData: + type: object + description: Data needed to connect to a BOB cluster + required: + - hostname + properties: + credentials: + allOf: + - $ref: '#/components/schemas/Credentials' + nullable: true + hostname: + $ref: '#/components/schemas/Hostname' + example: + credentials: + login: archeoss + password: '12345' + hostname: 0.0.0.0:7000 + Credentials: + type: object + description: Optional auth credentials for a BOB cluster + required: + - login + - password + properties: + login: + type: string + description: Login used during auth + password: + type: string + description: Password used during auth + example: + login: archeoss + password: '12345' + Disk: + type: object + description: Physical disk definition + required: + - name + - path + - status + - totalSpace + - usedSpace + - iops + properties: + iops: + type: integer + format: int64 + minimum: 0 + name: + type: string + description: Disk name + path: + type: string + description: Disk path + status: + $ref: '#/components/schemas/DiskStatus' + totalSpace: + type: integer + format: int64 + minimum: 0 + usedSpace: + type: integer + format: int64 + minimum: 0 + DiskCount: + type: object + description: Disk count by their status + required: + - Good + - Bad + - Offline + properties: + Bad: + type: integer + format: int64 + minimum: 0 + Good: + type: integer + format: int64 + minimum: 0 + Offline: + type: integer + format: int64 + minimum: 0 + example: + Bad: 0 + Good: 0 + Offline: 0 + DiskProblem: + type: string + description: Defines kind of problem on disk + enum: + - freeSpaceRunningOut + DiskStatus: + oneOf: + - type: object + required: + - status + properties: + status: + type: string + enum: + - Good + - type: object + required: + - status + - problems + properties: + problems: + type: object + required: + - problems + properties: + problems: + type: array + items: + $ref: '#/components/schemas/DiskProblem' + status: + type: string + enum: + - Bad + - type: object + required: + - status + properties: + status: + type: string + enum: + - Offline + description: |- + Defines disk status + + Variant - Disk Status + Content - List of problems on disk. 'null' if status != 'bad' + discriminator: + propertyName: status + DiskStatusName: + type: string + description: Defines disk status names + enum: + - Good + - Bad + - Offline + Hostname: + type: string + MetricsEntryModel: + type: object + required: + - value + - timestamp + properties: + timestamp: + type: integer + format: int64 + minimum: 0 + value: + type: integer + format: int64 + minimum: 0 + MetricsSnapshotModel: + type: object + required: + - metrics + properties: + metrics: + type: object + additionalProperties: + $ref: '#/components/schemas/MetricsEntryModel' + NodeConfiguration: + type: object + properties: + blob_file_name_prefix: + type: string + nullable: true + root_dir_name: + type: string + nullable: true + NodeCount: + type: object + description: Node count by their status + required: + - Good + - Bad + - Offline + properties: + Bad: + type: integer + format: int64 + minimum: 0 + Good: + type: integer + format: int64 + minimum: 0 + Offline: + type: integer + format: int64 + minimum: 0 + example: + Bad: 0 + Good: 0 + Offline: 0 + NodeInfo: + type: object + required: + - name + - hostname + - vdisks + - status + properties: + alienCount: + type: integer + format: int64 + nullable: true + minimum: 0 + corruptedCount: + type: integer + format: int64 + nullable: true + minimum: 0 + hostname: + type: string + name: + type: string + rps: + allOf: + - $ref: '#/components/schemas/RPS' + nullable: true + space: + allOf: + - $ref: '#/components/schemas/SpaceInfo' + nullable: true + status: + $ref: '#/components/schemas/NodeStatus' + vdisks: + type: array + items: + $ref: '#/components/schemas/VDisk' + NodeProblem: + type: string + description: Defines kind of problem on Node + enum: + - aliensExists + - corruptedExists + - freeSpaceRunningOut + - virtualMemLargerThanRAM + - highCPULoad + NodeStatus: + oneOf: + - type: object + required: + - status + properties: + status: + type: string + enum: + - Good + - type: object + required: + - status + - problems + properties: + problems: + type: object + required: + - problems + properties: + problems: + type: array + items: + $ref: '#/components/schemas/NodeProblem' + status: + type: string + enum: + - Bad + - type: object + required: + - status + properties: + status: + type: string + enum: + - Offline + description: |- + Defines status of node + + Variants - Node status + + Content - List of problems on node. 'null' if status != 'bad' + discriminator: + propertyName: status + NodeStatusName: + type: string + description: Defines node status names + enum: + - Good + - Bad + - Offline + Operation: + type: string + description: Types of operations on BOB cluster + enum: + - put + - get + - exist + - delete + RPS: + type: object + description: Requests per second by operation + required: + - put + - get + - exist + - delete + properties: + delete: + type: integer + format: int64 + minimum: 0 + exist: + type: integer + format: int64 + minimum: 0 + get: + type: integer + format: int64 + minimum: 0 + put: + type: integer + format: int64 + minimum: 0 + example: + delete: 0 + exist: 0 + get: 0 + put: 0 + RawMetricEntry: + type: string + enum: + - cluster_grinder.get_count_rate + - cluster_grinder.put_count_rate + - cluster_grinder.exist_count_rate + - cluster_grinder.delete_count_rate + - pearl.exist_count_rate + - pearl.get_count_rate + - pearl.put_count_rate + - pearl.delete_count_rate + - backend.alien_count + - backend.corrupted_blob_count + - hardware.bob_virtual_ram + - hardware.total_ram + - hardware.used_ram + - hardware.bob_cpu_load + - hardware.free_space + - hardware.total_space + - hardware.descr_amount + Replica: + type: object + description: '[`VDisk`]''s replicas' + required: + - node + - disk + - path + - status + properties: + disk: + type: string + node: + type: string + path: + type: string + status: + $ref: '#/components/schemas/ReplicaStatus' + ReplicaProblem: + type: string + description: Reasons why Replica is offline + enum: + - nodeUnavailable + - diskUnavailable + ReplicaStatus: + oneOf: + - type: object + required: + - status + properties: + status: + type: string + enum: + - Good + - type: object + required: + - status + - problems + properties: + problems: + type: object + required: + - problems + properties: + problems: + type: array + items: + $ref: '#/components/schemas/ReplicaProblem' + status: + type: string + enum: + - Offline + description: |- + Replica status. It's either good or offline with the reasons why it is offline + + Variants - Replica status + + Content - List of problems on replica. 'null' if status != 'offline' + discriminator: + propertyName: status + SpaceInfo: + type: object + description: Disk space information in bytes + required: + - total_disk + - free_disk + - used_disk + - occupied_disk + properties: + free_disk: + type: integer + format: int64 + description: The amount of free disk space + minimum: 0 + occupied_disk: + type: integer + format: int64 + description: Disk space occupied only by BOB. occupied_disk should be lesser than used_disk + minimum: 0 + total_disk: + type: integer + format: int64 + description: Total disk space amount + minimum: 0 + used_disk: + type: integer + format: int64 + description: Used disk space amount + minimum: 0 + TypedMetrics: + type: object + description: Raw metrics information + required: + - cluster_grinder.get_count_rate + - cluster_grinder.put_count_rate + - cluster_grinder.exist_count_rate + - cluster_grinder.delete_count_rate + - pearl.exist_count_rate + - pearl.get_count_rate + - pearl.put_count_rate + - pearl.delete_count_rate + - backend.alien_count + - backend.corrupted_blob_count + - hardware.bob_virtual_ram + - hardware.total_ram + - hardware.used_ram + - hardware.bob_cpu_load + - hardware.free_space + - hardware.total_space + - hardware.descr_amount + properties: + backend.alien_count: + type: object + required: + - value + - timestamp + properties: + timestamp: + type: integer + format: int64 + minimum: 0 + value: + type: integer + format: int64 + minimum: 0 + backend.corrupted_blob_count: + type: object + required: + - value + - timestamp + properties: + timestamp: + type: integer + format: int64 + minimum: 0 + value: + type: integer + format: int64 + minimum: 0 + cluster_grinder.delete_count_rate: + type: object + required: + - value + - timestamp + properties: + timestamp: + type: integer + format: int64 + minimum: 0 + value: + type: integer + format: int64 + minimum: 0 + cluster_grinder.exist_count_rate: + type: object + required: + - value + - timestamp + properties: + timestamp: + type: integer + format: int64 + minimum: 0 + value: + type: integer + format: int64 + minimum: 0 + cluster_grinder.get_count_rate: + type: object + required: + - value + - timestamp + properties: + timestamp: + type: integer + format: int64 + minimum: 0 + value: + type: integer + format: int64 + minimum: 0 + cluster_grinder.put_count_rate: + type: object + required: + - value + - timestamp + properties: + timestamp: + type: integer + format: int64 + minimum: 0 + value: + type: integer + format: int64 + minimum: 0 + hardware.bob_cpu_load: + type: object + required: + - value + - timestamp + properties: + timestamp: + type: integer + format: int64 + minimum: 0 + value: + type: integer + format: int64 + minimum: 0 + hardware.bob_virtual_ram: + type: object + required: + - value + - timestamp + properties: + timestamp: + type: integer + format: int64 + minimum: 0 + value: + type: integer + format: int64 + minimum: 0 + hardware.descr_amount: + type: object + required: + - value + - timestamp + properties: + timestamp: + type: integer + format: int64 + minimum: 0 + value: + type: integer + format: int64 + minimum: 0 + hardware.free_space: + type: object + required: + - value + - timestamp + properties: + timestamp: + type: integer + format: int64 + minimum: 0 + value: + type: integer + format: int64 + minimum: 0 + hardware.total_ram: + type: object + required: + - value + - timestamp + properties: + timestamp: + type: integer + format: int64 + minimum: 0 + value: + type: integer + format: int64 + minimum: 0 + hardware.total_space: + type: object + required: + - value + - timestamp + properties: + timestamp: + type: integer + format: int64 + minimum: 0 + value: + type: integer + format: int64 + minimum: 0 + hardware.used_ram: + type: object + required: + - value + - timestamp + properties: + timestamp: + type: integer + format: int64 + minimum: 0 + value: + type: integer + format: int64 + minimum: 0 + pearl.delete_count_rate: + type: object + required: + - value + - timestamp + properties: + timestamp: + type: integer + format: int64 + minimum: 0 + value: + type: integer + format: int64 + minimum: 0 + pearl.exist_count_rate: + type: object + required: + - value + - timestamp + properties: + timestamp: + type: integer + format: int64 + minimum: 0 + value: + type: integer + format: int64 + minimum: 0 + pearl.get_count_rate: + type: object + required: + - value + - timestamp + properties: + timestamp: + type: integer + format: int64 + minimum: 0 + value: + type: integer + format: int64 + minimum: 0 + pearl.put_count_rate: + type: object + required: + - value + - timestamp + properties: + timestamp: + type: integer + format: int64 + minimum: 0 + value: + type: integer + format: int64 + minimum: 0 + example: + backend.alien_count: + timestamp: 0 + value: 0 + backend.corrupted_blob_count: + timestamp: 0 + value: 0 + cluster_grinder.delete_count_rate: + timestamp: 0 + value: 0 + cluster_grinder.exist_count_rate: + timestamp: 0 + value: 0 + cluster_grinder.get_count_rate: + timestamp: 0 + value: 0 + cluster_grinder.put_count_rate: + timestamp: 0 + value: 0 + hardware.bob_cpu_load: + timestamp: 0 + value: 0 + hardware.bob_virtual_ram: + timestamp: 0 + value: 0 + hardware.descr_amount: + timestamp: 0 + value: 0 + hardware.free_space: + timestamp: 0 + value: 0 + hardware.total_ram: + timestamp: 0 + value: 0 + hardware.total_space: + timestamp: 0 + value: 0 + hardware.used_ram: + timestamp: 0 + value: 0 + pearl.delete_count_rate: + timestamp: 0 + value: 0 + pearl.exist_count_rate: + timestamp: 0 + value: 0 + pearl.get_count_rate: + timestamp: 0 + value: 0 + pearl.put_count_rate: + timestamp: 0 + value: 0 + VDisk: + type: object + description: Virtual disk Component + required: + - id + - status + - partitionCount + - replicas + properties: + id: + type: integer + format: int64 + minimum: 0 + partitionCount: + type: integer + format: int64 + minimum: 0 + replicas: + type: array + items: + $ref: '#/components/schemas/Replica' + status: + $ref: '#/components/schemas/VDiskStatus' + VDiskStatus: + type: string + description: |- + Virtual disk status. + + Variants - Virtual Disk status + status == 'bad' when at least one of its replicas has problems + enum: + - Good + - Bad + - Offline + dto.Node: + type: object + required: + - name + - address + properties: + address: + type: string + name: + type: string + vdisks: + type: array + items: + $ref: '#/components/schemas/dto.VDisk' + nullable: true + dto.Replica: + type: object + required: + - node + - disk + - path + properties: + disk: + type: string + node: + type: string + path: + type: string + dto.VDisk: + type: object + required: + - id + properties: + id: + type: integer + format: int32 + replicas: + type: array + items: + $ref: '#/components/schemas/dto.Replica' + nullable: true + securitySchemes: + api_key: + type: apiKey + in: header + name: bob_apikey +tags: +- name: bob + description: BOB management API