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 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…
Reference in new issue