diff --git a/CHANGELOG.md b/CHANGELOG.md index b31b038b..fddea225 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,3 +14,4 @@ Bob Management GUI changelog - Login Page, backend (#16) - Home page, backend (#18) - Node list page, backend (#19) +- VDisk list page, backend (#20) diff --git a/api/openapi.yaml b/api/openapi.yaml index 8b137891..aa3f3973 100644 --- a/api/openapi.yaml +++ b/api/openapi.yaml @@ -1 +1,1142 @@ +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: + allOf: + - $ref: '#/components/schemas/DiskStatus' + - type: object + required: + - name + - path + - totalSpace + - usedSpace + - iops + properties: + iops: + type: integer + format: int64 + minimum: 0 + name: + type: string + description: Disk name + path: + type: string + description: Disk path + totalSpace: + type: integer + format: int64 + minimum: 0 + usedSpace: + type: integer + format: int64 + minimum: 0 + description: Physical disk definition + 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: 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' + Node: + allOf: + - $ref: '#/components/schemas/NodeStatus' + - type: object + required: + - name + - hostname + - vdisks + 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 + vdisks: + type: array + items: + $ref: '#/components/schemas/VDisk' + 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 + 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: 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: + allOf: + - $ref: '#/components/schemas/ReplicaStatus' + - type: object + required: + - node + - disk + - path + properties: + disk: + type: string + node: + type: string + path: + type: string + description: '[`VDisk`]''s replicas' + 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: 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: + allOf: + - $ref: '#/components/schemas/VDiskStatus' + - type: object + required: + - id + - 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' + description: Virtual disk Component + 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 diff --git a/backend/src/lib.rs b/backend/src/lib.rs index 7e3a68ee..1d146016 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/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,