parent
d90d2bc7c5
commit
c35bc358b9
9 changed files with 225 additions and 77 deletions
@ -0,0 +1,14 @@ |
||||
export const buildJobData = <T extends [string, unknown][]>({ |
||||
entries, |
||||
getValue = (v) => String(v), |
||||
}: { |
||||
entries: T; |
||||
getValue?: (value: T[number][1]) => string; |
||||
}) => |
||||
entries |
||||
.reduce<string>((previous, [key, value]) => { |
||||
previous += `${key}=${getValue(value)}\\n`; |
||||
|
||||
return previous; |
||||
}, '') |
||||
.trim(); |
@ -0,0 +1,42 @@ |
||||
import { buildNetworkLinkConfig } from './buildNetworkLinkConfig'; |
||||
import { cvar } from '../varn'; |
||||
|
||||
export const buildNetworkConfig = ( |
||||
networks: InitializeStrikerNetworkForm[], |
||||
configStep = 2, |
||||
): FormConfigData => { |
||||
const { counters: ncounts, data: cdata } = networks.reduce<{ |
||||
counters: Record<InitializeStrikerNetworkForm['type'], number>; |
||||
data: FormConfigData; |
||||
}>( |
||||
(previous, { interfaces, ipAddress, subnetMask, type }) => { |
||||
const { counters } = previous; |
||||
|
||||
counters[type] = counters[type] ? counters[type] + 1 : 1; |
||||
|
||||
const networkShortName = `${type}${counters[type]}`; |
||||
|
||||
previous.data = { |
||||
...previous.data, |
||||
[cvar(configStep, `${networkShortName}_ip`)]: { |
||||
step: configStep, |
||||
value: ipAddress, |
||||
}, |
||||
[cvar(configStep, `${networkShortName}_subnet_mask`)]: { |
||||
step: configStep, |
||||
value: subnetMask, |
||||
}, |
||||
...buildNetworkLinkConfig(networkShortName, interfaces), |
||||
}; |
||||
|
||||
return previous; |
||||
}, |
||||
{ counters: {}, data: {} }, |
||||
); |
||||
|
||||
Object.entries(ncounts).forEach(([ntype, ncount]) => { |
||||
cdata[cvar(1, `${ntype}_count`)] = { value: ncount }; |
||||
}); |
||||
|
||||
return cdata; |
||||
}; |
@ -0,0 +1,19 @@ |
||||
import { cvar } from '../varn'; |
||||
|
||||
export const buildNetworkLinkConfig = ( |
||||
networkShortName: string, |
||||
interfaces: InitializeStrikerNetworkForm['interfaces'], |
||||
configStep = 2, |
||||
) => |
||||
interfaces.reduce<FormConfigData>((previous, iface, index) => { |
||||
if (iface) { |
||||
const { networkInterfaceMACAddress } = iface; |
||||
const linkNumber = index + 1; |
||||
|
||||
previous[ |
||||
cvar(configStep, `${networkShortName}_link${linkNumber}_mac_to_set`) |
||||
] = { step: configStep, value: networkInterfaceMACAddress }; |
||||
} |
||||
|
||||
return previous; |
||||
}, {}); |
@ -0,0 +1,2 @@ |
||||
export * from './buildNetworkConfig'; |
||||
export * from './buildNetworkLinkConfig'; |
@ -0,0 +1,125 @@ |
||||
import assert from 'assert'; |
||||
import { RequestHandler } from 'express'; |
||||
|
||||
import { |
||||
REP_IPV4, |
||||
REP_IPV4_CSV, |
||||
REP_PEACEFUL_STRING, |
||||
REP_UUID, |
||||
SERVER_PATHS, |
||||
} from '../../consts'; |
||||
|
||||
import { job, variable } from '../../accessModule'; |
||||
import { buildJobData } from '../../buildJobData'; |
||||
import { buildNetworkConfig } from '../../fconfig'; |
||||
import { sanitize } from '../../sanitize'; |
||||
import { stderr, stdoutVar } from '../../shell'; |
||||
import { cvar } from '../../varn'; |
||||
|
||||
export const prepareNetwork: RequestHandler< |
||||
UpdateHostParams, |
||||
undefined, |
||||
PrepareNetworkRequestBody |
||||
> = async (request, response) => { |
||||
const { |
||||
body: { |
||||
dns: rDns, |
||||
gateway: rGateway, |
||||
hostName: rHostName, |
||||
gatewayInterface: rGatewayInterface, |
||||
networks = [], |
||||
} = {}, |
||||
params: { hostUUID }, |
||||
} = request; |
||||
|
||||
const dns = sanitize(rDns, 'string'); |
||||
const gateway = sanitize(rGateway, 'string'); |
||||
const hostName = sanitize(rHostName, 'string'); |
||||
const gatewayInterface = sanitize(rGatewayInterface, 'string'); |
||||
|
||||
try { |
||||
assert( |
||||
REP_UUID.test(hostUUID), |
||||
`Host UUID must be a valid UUIDv4; got [${hostUUID}]`, |
||||
); |
||||
|
||||
assert( |
||||
REP_IPV4_CSV.test(dns), |
||||
`DNS must be a valid IPv4 CSV; got [${dns}]`, |
||||
); |
||||
|
||||
assert( |
||||
REP_IPV4.test(gateway), |
||||
`Gateway must be a valid IPv4; got [${gateway}]`, |
||||
); |
||||
|
||||
assert( |
||||
REP_PEACEFUL_STRING.test(hostName), |
||||
`Host name must be a peaceful string; got [${hostName}]`, |
||||
); |
||||
|
||||
assert( |
||||
REP_PEACEFUL_STRING.test(gatewayInterface), |
||||
`Gateway interface must be a peaceful string; got [${gatewayInterface}]`, |
||||
); |
||||
} catch (error) { |
||||
stderr(`Failed to assert value when prepare network; CAUSE: ${error}`); |
||||
|
||||
return response.status(400).send(); |
||||
} |
||||
|
||||
const configData: FormConfigData = { |
||||
[cvar(2, 'dns')]: { step: 2, value: dns }, |
||||
[cvar(2, 'gateway')]: { step: 2, value: gateway }, |
||||
[cvar(2, 'gateway_interface')]: { step: 2, value: gatewayInterface }, |
||||
[cvar(2, 'host_name')]: { step: 2, value: hostName }, |
||||
...buildNetworkConfig(networks), |
||||
}; |
||||
|
||||
stdoutVar( |
||||
configData, |
||||
`Config data before prepare network on host ${hostUUID}: `, |
||||
); |
||||
|
||||
const configEntries = Object.entries(configData); |
||||
|
||||
try { |
||||
for (const [ckey, cdetail] of configEntries) { |
||||
const { step = 1, value } = cdetail; |
||||
|
||||
const vuuid = await variable({ |
||||
file: __filename, |
||||
variable_default: '', |
||||
varaible_description: '', |
||||
variable_name: ckey, |
||||
variable_section: `config_step${step}`, |
||||
variable_source_uuid: hostUUID, |
||||
variable_source_table: 'hosts', |
||||
variable_value: value, |
||||
}); |
||||
|
||||
assert( |
||||
REP_UUID.test(vuuid), |
||||
`Not a UUIDv4 post insert or update of ${ckey} with [${cdetail}]`, |
||||
); |
||||
} |
||||
|
||||
await job({ |
||||
file: __filename, |
||||
job_command: SERVER_PATHS.usr.sbin['anvil-configure-host'].self, |
||||
job_data: buildJobData({ |
||||
entries: configEntries, |
||||
getValue: ({ value }) => String(value), |
||||
}), |
||||
job_name: 'configure::network', |
||||
job_title: 'job_0001', |
||||
job_description: 'job_0071', |
||||
}); |
||||
} catch (error) { |
||||
stderr(`Failed to queue prepare network; CAUSE: ${error}`); |
||||
|
||||
return response.status(500).send(); |
||||
} |
||||
|
||||
return response.send(); |
||||
}; |
@ -0,0 +1,2 @@ |
||||
export const cvar = (step: number, name: string) => |
||||
['form', `config_step${step}`, name, 'value'].join('::'); |
Loading…
Reference in new issue