fix(striker-ui-api): replace handle subnode cluster membership endpoint

main
Tsu-ba-me 2 years ago
parent 8fff0f8624
commit 4d9c2e79f0
  1. 1
      striker-ui-api/src/lib/consts/SERVER_PATHS.ts
  2. 123
      striker-ui-api/src/lib/request_handlers/command/buildMembershipHandler.ts
  3. 12
      striker-ui-api/src/lib/request_handlers/command/buildPowerHandler.ts
  4. 2
      striker-ui-api/src/lib/request_handlers/command/index.ts
  5. 3
      striker-ui-api/src/lib/request_handlers/command/joinAn.ts
  6. 3
      striker-ui-api/src/lib/request_handlers/command/leaveAn.ts
  7. 4
      striker-ui-api/src/routes/command.ts
  8. 12
      striker-ui-api/src/types/BuildMembershipHandlerFunction.d.ts
  9. 5
      striker-ui-api/src/types/BuildPowerHandlerFunction.d.ts

@ -30,6 +30,7 @@ const EMPTY_SERVER_PATHS: ServerPath = {
'anvil-manage-keys': {}, 'anvil-manage-keys': {},
'anvil-manage-power': {}, 'anvil-manage-power': {},
'anvil-provision-server': {}, 'anvil-provision-server': {},
'anvil-safe-start': {},
'anvil-safe-stop': {}, 'anvil-safe-stop': {},
'anvil-sync-shared': {}, 'anvil-sync-shared': {},
'anvil-update-system': {}, 'anvil-update-system': {},

@ -0,0 +1,123 @@
import assert from 'assert';
import { RequestHandler } from 'express';
import { REP_UUID, SERVER_PATHS } from '../../consts';
import { job, query } from '../../accessModule';
import { sanitize } from '../../sanitize';
import { stderr } from '../../shell';
const MAP_TO_MEMBERSHIP_JOB_PARAMS_BUILDER: Record<
MembershipTask,
BuildMembershipJobParamsFunction
> = {
join: async (uuid, { isActiveMember } = {}) => {
// Host is already a cluster member
if (isActiveMember) return undefined;
const rows: [[number]] = await query(
`SELECT
CASE
WHEN host_status = 'online'
THEN CAST('1' AS BOOLEAN)
ELSE CAST('0' AS BOOLEAN)
END
FROM hosts WHERE host_uuid = '${uuid}';`,
);
assert.ok(rows.length, 'No entry found');
const [[isOnline]] = rows;
return isOnline
? {
job_command: SERVER_PATHS.usr.sbin['anvil-safe-start'].self,
job_description: 'job_0337',
job_host_uuid: uuid,
job_name: 'set_membership::join',
job_title: 'job_0336',
}
: undefined;
},
leave: async (uuid, { isActiveMember } = {}) =>
isActiveMember
? {
job_command: SERVER_PATHS.usr.sbin['anvil-safe-stop'].self,
job_description: 'job_0339',
job_host_uuid: uuid,
job_name: 'set_membership::leave',
job_title: 'job_0338',
}
: undefined,
};
export const buildMembershipHandler: (
task: MembershipTask,
) => RequestHandler<{ uuid: string }> = (task) => async (request, response) => {
const {
params: { uuid },
} = request;
const hostUuid = sanitize(uuid, 'string', { modifierType: 'sql' });
try {
assert(
REP_UUID.test(hostUuid),
`Param UUID must be a valid UUIDv4; got: [${hostUuid}]`,
);
} catch (error) {
stderr(
`Failed to assert value when changing host membership; CAUSE: ${error}`,
);
return response.status(500).send();
}
let rows: [
[
hostInCcm: NumberBoolean,
hostCrmdMember: NumberBoolean,
hostClusterMember: NumberBoolean,
],
];
try {
rows = await query(
`SELECT
scan_cluster_node_in_ccm,
scan_cluster_node_crmd_member,
scan_cluster_node_cluster_member
FROM scan_cluster_nodes
WHERE scan_cluster_node_host_uuid = '${hostUuid}';`,
);
assert.ok(rows.length, `No entry found`);
} catch (error) {
stderr(`Failed to get cluster status of host ${hostUuid}; CAUSE: ${error}`);
return response.status(500).send();
}
const isActiveMember = rows[0].every((stage) => Boolean(stage));
try {
const restParams = await MAP_TO_MEMBERSHIP_JOB_PARAMS_BUILDER[task](
hostUuid,
{
isActiveMember,
},
);
if (restParams) {
await job({ file: __filename, ...restParams });
}
} catch (error) {
stderr(
`Failed to initiate ${task} cluster for host ${hostUuid}; CAUSE: ${error}`,
);
return response.status(500).send();
}
return response.status(204).send();
};

@ -12,21 +12,21 @@ import { stderr } from '../../shell';
* * poweroff, reboot targets the striker this express app operates on * * poweroff, reboot targets the striker this express app operates on
* * start, stop targets subnode or DR host * * start, stop targets subnode or DR host
*/ */
const MANAGE_HOST_POWER_JOB_PARAMS: Record< const MAP_TO_POWER_JOB_PARAMS_BUILDER: Record<
PowerTask, PowerTask,
BuildPowerJobParamsFunction BuildPowerJobParamsFunction
> = { > = {
poweroff: () => ({ poweroff: () => ({
job_command: `${SERVER_PATHS.usr.sbin['anvil-manage-power'].self} --poweroff -y`, job_command: `${SERVER_PATHS.usr.sbin['anvil-manage-power'].self} --poweroff -y`,
job_description: 'job_0008',
job_name: 'poweroff::system', job_name: 'poweroff::system',
job_title: 'job_0010', job_title: 'job_0010',
job_description: 'job_0008',
}), }),
reboot: () => ({ reboot: () => ({
job_command: `${SERVER_PATHS.usr.sbin['anvil-manage-power'].self} --reboot -y`, job_command: `${SERVER_PATHS.usr.sbin['anvil-manage-power'].self} --reboot -y`,
job_description: 'job_0006',
job_name: 'reboot::system', job_name: 'reboot::system',
job_title: 'job_0009', job_title: 'job_0009',
job_description: 'job_0006',
}), }),
start: ({ uuid } = {}) => ({ start: ({ uuid } = {}) => ({
job_command: `${SERVER_PATHS.usr.sbin['striker-boot-machine'].self} --host-uuid '${uuid}'`, job_command: `${SERVER_PATHS.usr.sbin['striker-boot-machine'].self} --host-uuid '${uuid}'`,
@ -49,13 +49,13 @@ const queuePowerJob = async (
task: PowerTask, task: PowerTask,
options?: BuildPowerJobParamsOptions, options?: BuildPowerJobParamsOptions,
) => { ) => {
const subParams: JobParams = { const params: JobParams = {
file: __filename, file: __filename,
...MANAGE_HOST_POWER_JOB_PARAMS[task](options), ...MAP_TO_POWER_JOB_PARAMS_BUILDER[task](options),
}; };
return await job(subParams); return await job(params);
}; };
export const buildPowerHandler: ( export const buildPowerHandler: (

@ -1,4 +1,6 @@
export * from './getHostSSH'; export * from './getHostSSH';
export * from './joinAn';
export * from './leaveAn';
export * from './poweroffStriker'; export * from './poweroffStriker';
export * from './rebootStriker'; export * from './rebootStriker';
export * from './runManifest'; export * from './runManifest';

@ -0,0 +1,3 @@
import { buildMembershipHandler } from './buildMembershipHandler';
export const joinAn = buildMembershipHandler('join');

@ -0,0 +1,3 @@
import { buildMembershipHandler } from './buildMembershipHandler';
export const leaveAn = buildMembershipHandler('leave');

@ -2,6 +2,8 @@ import express from 'express';
import { import {
getHostSSH, getHostSSH,
joinAn,
leaveAn,
poweroffStriker, poweroffStriker,
rebootStriker, rebootStriker,
runManifest, runManifest,
@ -16,6 +18,8 @@ const router = express.Router();
router router
.put('/inquire-host', getHostSSH) .put('/inquire-host', getHostSSH)
.put('/join-an/:uuid', joinAn)
.put('/leave-an/:uuid', leaveAn)
.put('/poweroff-host', poweroffStriker) .put('/poweroff-host', poweroffStriker)
.put('/reboot-host', rebootStriker) .put('/reboot-host', rebootStriker)
.put('/run-manifest/:manifestUuid', runManifest) .put('/run-manifest/:manifestUuid', runManifest)

@ -0,0 +1,12 @@
type MembershipTask = 'join' | 'leave';
type MembershipJobParams = Omit<JobParams, 'file' | 'line'>;
type BuildMembershipJobParamsOptions = {
isActiveMember?: boolean;
};
type BuildMembershipJobParamsFunction = (
uuid: string,
options?: BuildMembershipJobParamsOptions,
) => Promise<MembershipJobParams | undefined>;

@ -1,9 +1,6 @@
type PowerTask = 'poweroff' | 'reboot' | 'start' | 'stop'; type PowerTask = 'poweroff' | 'reboot' | 'start' | 'stop';
type PowerJobParams = Omit< type PowerJobParams = Omit<JobParams, 'file' | 'line'>;
JobParams,
'file' | 'line' | 'job_data' | 'job_progress'
>;
type BuildPowerJobParamsOptions = { type BuildPowerJobParamsOptions = {
isStopServers?: boolean; isStopServers?: boolean;
Loading…
Cancel
Save