parent
8fff0f8624
commit
4d9c2e79f0
9 changed files with 155 additions and 10 deletions
@ -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(); |
||||
}; |
@ -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'); |
@ -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 PowerJobParams = Omit< |
||||
JobParams, |
||||
'file' | 'line' | 'job_data' | 'job_progress' |
||||
>; |
||||
type PowerJobParams = Omit<JobParams, 'file' | 'line'>; |
||||
|
||||
type BuildPowerJobParamsOptions = { |
||||
isStopServers?: boolean; |
Loading…
Reference in new issue