From 83d572530b202a9c155098302de5aecd3b610eca Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Wed, 3 May 2023 02:32:14 -0400 Subject: [PATCH] fix(striker-ui-api): allow get anvil status --- .../lib/request_handlers/anvil/getAnvil.ts | 4 +- .../request_handlers/anvil/getAnvilDetail.ts | 114 ++++++++++++++++++ .../src/lib/request_handlers/anvil/index.ts | 2 + striker-ui-api/src/routes/anvil.ts | 4 +- striker-ui-api/src/types/ApiAn.d.ts | 18 +++ 5 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 striker-ui-api/src/lib/request_handlers/anvil/getAnvilDetail.ts create mode 100644 striker-ui-api/src/lib/request_handlers/anvil/index.ts diff --git a/striker-ui-api/src/lib/request_handlers/anvil/getAnvil.ts b/striker-ui-api/src/lib/request_handlers/anvil/getAnvil.ts index cd21b1dd..3011b19e 100644 --- a/striker-ui-api/src/lib/request_handlers/anvil/getAnvil.ts +++ b/striker-ui-api/src/lib/request_handlers/anvil/getAnvil.ts @@ -4,7 +4,7 @@ import buildGetRequestHandler from '../buildGetRequestHandler'; import buildQueryAnvilDetail from './buildQueryAnvilDetail'; import { sanitize } from '../../sanitize'; -const getAnvil: RequestHandler = buildGetRequestHandler( +export const getAnvil: RequestHandler = buildGetRequestHandler( (request, buildQueryOptions) => { const { anvilUUIDs, isForProvisionServer } = request.query; @@ -77,5 +77,3 @@ const getAnvil: RequestHandler = buildGetRequestHandler( return query; }, ); - -export default getAnvil; diff --git a/striker-ui-api/src/lib/request_handlers/anvil/getAnvilDetail.ts b/striker-ui-api/src/lib/request_handlers/anvil/getAnvilDetail.ts new file mode 100644 index 00000000..3a260e67 --- /dev/null +++ b/striker-ui-api/src/lib/request_handlers/anvil/getAnvilDetail.ts @@ -0,0 +1,114 @@ +import assert from 'assert'; +import { RequestHandler } from 'express'; + +import { getAnvilData, getHostData, query } from '../../accessModule'; +import { stderr } from '../../shell'; + +type DbBoolean = 0 | 1; + +const buildHostStateMessage = (postfix = 2) => `message_022${postfix}`; + +export const getAnvilDetail: RequestHandler< + AnvilDetailParamsDictionary, + AnvilDetailResponseBody, + undefined +> = async (request, response) => { + const { + params: { anvilUuid }, + } = request; + + let anvils: AnvilDataAnvilListHash; + let hosts: AnvilDataHostListHash; + + try { + anvils = await getAnvilData(); + hosts = await getHostData(); + } catch (error) { + stderr(`Failed to get anvil and/or host data; CAUSE: ${error}`); + + return response.status(500).send(); + } + + const { + anvil_uuid: { + [anvilUuid]: { + anvil_node1_host_uuid: n1uuid, + anvil_node2_host_uuid: n2uuid, + }, + }, + } = anvils; + + const result: AnvilDetailResponseBody = { anvil_state: 'optimal', hosts: [] }; + + for (const huuid of [n1uuid, n2uuid]) { + const { + host_uuid: { + [huuid]: { host_status: hstatus, short_host_name: hname }, + }, + } = hosts; + + const { hosts: rhosts } = result; + + const hsummary: AnvilDetailHostSummary = { + host_name: hname, + host_uuid: huuid, + maintenance_mode: false, + state: 'offline', + state_message: buildHostStateMessage(), + state_percent: 0, + }; + + rhosts.push(hsummary); + + if (hstatus !== 'online') continue; + + let rows: [ + inCcm: DbBoolean, + crmdMember: DbBoolean, + clusterMember: DbBoolean, + maintenanceMode: DbBoolean, + ][]; + + try { + rows = await query(`SELECT + scan_cluster_node_in_ccm, + scan_cluster_node_crmd_member, + scan_cluster_node_cluster_member, + scan_cluster_node_maintenance_mode + FROM + scan_cluster_nodes + WHERE + scan_cluster_node_host_uuid = '${huuid}';`); + + assert.ok(rows.length, 'No node cluster info'); + } catch (error) { + stderr(`Failed to get node ${huuid} cluster status; CAUSE: ${error}`); + + continue; + } + + const [[ccm, crmd, cluster, maintenance]] = rows; + + hsummary.maintenance_mode = Boolean(maintenance); + + if (cluster) { + hsummary.state = 'online'; + hsummary.state_message = buildHostStateMessage(3); + hsummary.state_percent = 100; + } else if (crmd) { + hsummary.state = 'crmd'; + hsummary.state_message = buildHostStateMessage(4); + hsummary.state_percent = 75; + } else if (ccm) { + hsummary.state = 'in_ccm'; + hsummary.state_message = buildHostStateMessage(5); + hsummary.state_percent = 50; + } else { + hsummary.state = 'booted'; + hsummary.state_message = buildHostStateMessage(6); + hsummary.state_percent = 25; + } + } + + response.status(200).send(result); +}; diff --git a/striker-ui-api/src/lib/request_handlers/anvil/index.ts b/striker-ui-api/src/lib/request_handlers/anvil/index.ts new file mode 100644 index 00000000..0f91bea6 --- /dev/null +++ b/striker-ui-api/src/lib/request_handlers/anvil/index.ts @@ -0,0 +1,2 @@ +export * from './getAnvil'; +export * from './getAnvilDetail'; diff --git a/striker-ui-api/src/routes/anvil.ts b/striker-ui-api/src/routes/anvil.ts index 52218e4d..5216cc7f 100644 --- a/striker-ui-api/src/routes/anvil.ts +++ b/striker-ui-api/src/routes/anvil.ts @@ -1,9 +1,9 @@ import express from 'express'; -import getAnvil from '../lib/request_handlers/anvil/getAnvil'; +import { getAnvil, getAnvilDetail } from '../lib/request_handlers/anvil'; const router = express.Router(); -router.get('/', getAnvil); +router.get('/', getAnvil).get('/:anvilUuid', getAnvilDetail); export default router; diff --git a/striker-ui-api/src/types/ApiAn.d.ts b/striker-ui-api/src/types/ApiAn.d.ts index d49b8d61..7e7ae3da 100644 --- a/striker-ui-api/src/types/ApiAn.d.ts +++ b/striker-ui-api/src/types/ApiAn.d.ts @@ -1,3 +1,21 @@ +type AnvilDetailHostSummary = { + host_name: string; + host_uuid: string; + maintenance_mode: boolean; + state: string; + state_message: string; + state_percent: number; +}; + +type AnvilDetailParamsDictionary = { + anvilUuid: string; +}; + +type AnvilDetailResponseBody = { + anvil_state: string; + hosts: AnvilDetailHostSummary[]; +}; + type AnvilDetailForProvisionServer = { anvilUUID: string; anvilName: string;