Skip to content

Commit

Permalink
Merge pull request #743 from ylei-tsubame/issues/685-micro-anvil-netconf
Browse files Browse the repository at this point in the history
Web UI: rework striker init, and host network init forms
  • Loading branch information
ylei-tsubame authored Oct 3, 2024
2 parents b4f660e + d999d20 commit b3cfb20
Show file tree
Hide file tree
Showing 110 changed files with 2,949 additions and 490 deletions.
2 changes: 1 addition & 1 deletion striker-ui-api/out/index.js

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions striker-ui-api/src/lib/fconfig/buildNetworkConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ export const buildNetworkConfig = (
counters: Record<InitializeStrikerNetworkForm['type'], number>;
data: FormConfigData;
}>(
(previous, { createBridge, interfaces, ipAddress, subnetMask, type }) => {
(
previous,
{ createBridge, interfaces, ipAddress, sequence, subnetMask, type },
) => {
const { counters } = previous;

counters[type] = counters[type] ? counters[type] + 1 : 1;

const networkShortName = `${type}${counters[type]}`;
const networkShortName = `${type}${sequence}`;

previous.data = {
...previous.data,
Expand Down
4 changes: 2 additions & 2 deletions striker-ui-api/src/lib/fconfig/buildNetworkLinkConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ export const buildNetworkLinkConfig = (
) =>
interfaces.reduce<FormConfigData>((previous, iface, index) => {
if (iface) {
const { networkInterfaceMACAddress } = iface;
const { mac } = iface;
const linkNumber = index + 1;

previous[
cvar(configStep, `${networkShortName}_link${linkNumber}_mac_to_set`)
] = { step: configStep, value: networkInterfaceMACAddress };
] = { step: configStep, value: mac };
}

return previous;
Expand Down
8 changes: 5 additions & 3 deletions striker-ui-api/src/lib/request_handlers/host/configStriker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { cvar } from '../../varn';

export const configStriker: RequestHandler<
unknown,
undefined,
InitializeStrikerResponseBody,
Partial<InitializeStrikerForm>
> = async (request, response) => {
const { body = {} } = request;
Expand Down Expand Up @@ -120,6 +120,8 @@ export const configStriker: RequestHandler<

const configEntries = Object.entries(configData);

let jobUuid: string;

try {
const localHostUuid = getLocalHostUUID();

Expand All @@ -143,7 +145,7 @@ export const configStriker: RequestHandler<
);
}

await job({
jobUuid = await job({
file: __filename,
job_command: SERVER_PATHS.usr.sbin['anvil-configure-host'].self,
job_data: buildJobData({
Expand All @@ -160,5 +162,5 @@ export const configStriker: RequestHandler<
return response.status(500).send();
}

response.status(200).send();
response.status(200).send({ jobUuid });
};
19 changes: 16 additions & 3 deletions striker-ui-api/src/lib/request_handlers/host/getHost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,34 @@ export const getHost = buildGetRequestHandler((request, buildQueryOptions) => {
a.host_type,
a.host_uuid,
b.anvil_uuid,
b.anvil_name
b.anvil_name,
c.variable_value
FROM hosts AS a
LEFT JOIN anvils AS b
ON a.host_uuid IN (
b.anvil_node1_host_uuid,
b.anvil_node2_host_uuid,
b.anvil_dr1_host_uuid
)
LEFT JOIN variables AS c
ON c.variable_name = 'system::configured'
AND c.variable_source_table = 'hosts'
AND a.host_uuid = c.variable_source_uuid
${condition}
ORDER BY a.host_name ASC;`;

let afterQueryReturn: QueryResultModifierFunction | undefined =
buildQueryResultReducer<{ [hostUUID: string]: HostOverview }>(
(previous, row) => {
const [hostName, hostStatus, hostType, hostUUID, anvilUuid, anvilName] =
row;
const [
hostName,
hostStatus,
hostType,
hostUUID,
anvilUuid,
anvilName,
hostConfigured,
] = row;

const key = toLocal(hostUUID, localHostUUID);

Expand All @@ -60,6 +72,7 @@ export const getHost = buildGetRequestHandler((request, buildQueryOptions) => {

previous[key] = {
anvil,
hostConfigured: hostConfigured === '1',
hostName,
hostStatus,
hostType,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,60 +1,75 @@
import { DELETED, LOCAL } from '../../consts';

import buildGetRequestHandler from '../buildGetRequestHandler';
import { buildQueryResultReducer } from '../../buildQueryResultModifier';
import { toHostUUID } from '../../convertHostUUID';

export const getNetworkInterface = buildGetRequestHandler(
(request, buildQueryOptions) => {
const {
params: { hostUUID: rHostUUID = LOCAL },
params: { hostUUID: rHostUuid = LOCAL },
} = request;

const hostUUID = toHostUUID(rHostUUID);
const hostUuid = toHostUUID(rHostUuid);

const query = `
SELECT
network_interface_uuid,
network_interface_mac_address,
network_interface_name,
a.network_interface_uuid,
a.network_interface_mac_address,
a.network_interface_name,
CASE
WHEN network_interface_link_state = '1'
AND network_interface_operational = 'up'
WHEN a.network_interface_link_state = '1'
AND a.network_interface_operational = 'up'
THEN 'up'
ELSE 'down'
END AS network_interface_state,
network_interface_speed,
ROW_NUMBER() OVER(ORDER BY modified_date ASC) AS network_interface_order
FROM network_interfaces
WHERE network_interface_operational != '${DELETED}'
AND network_interface_name NOT SIMILAR TO '(vnet\\d+|virbr\\d+-nic)%'
AND network_interface_host_uuid = '${hostUUID}';`;
END AS iface_state,
a.network_interface_speed,
ROW_NUMBER() OVER(ORDER BY a.modified_date DESC) AS iface_order,
b.ip_address_address,
b.ip_address_subnet_mask,
b.ip_address_gateway,
b.ip_address_dns
FROM network_interfaces AS a
LEFT JOIN ip_addresses AS b
ON b.ip_address_on_uuid = a.network_interface_uuid
WHERE a.network_interface_operational != '${DELETED}'
AND a.network_interface_name NOT SIMILAR TO '(vnet\\d+|virbr\\d+-nic)%'
AND a.network_interface_host_uuid = '${hostUuid}';`;

if (buildQueryOptions) {
buildQueryOptions.afterQueryReturn = (queryStdout) => {
let result = queryStdout;

if (queryStdout instanceof Array) {
result = queryStdout.map<NetworkInterfaceOverview>(
([
networkInterfaceUUID,
networkInterfaceMACAddress,
networkInterfaceName,
networkInterfaceState,
networkInterfaceSpeed,
networkInterfaceOrder,
]) => ({
networkInterfaceUUID,
networkInterfaceMACAddress,
networkInterfaceName,
networkInterfaceState,
networkInterfaceSpeed,
networkInterfaceOrder,
}),
);
}

return result;
};
buildQueryOptions.afterQueryReturn =
buildQueryResultReducer<NetworkInterfaceOverviewList>(
(previous, row) => {
const [
uuid,
mac,
name,
state,
speed,
order,
ip,
subnetMask,
gateway,
dns,
] = row;

previous[uuid] = {
dns,
gateway,
ip,
mac,
name,
order: Number(order),
speed: Number(speed),
state,
subnetMask,
uuid,
};

return previous;
},
{},
);
}

return query;
Expand Down
22 changes: 2 additions & 20 deletions striker-ui-api/src/routes/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,13 @@ import express from 'express';
import { assertInit } from '../middlewares';

import { configStriker } from '../lib/request_handlers/host';
import { getJob } from '../lib/request_handlers/job';
import { getJobDetail } from '../lib/request_handlers/job';
import { getNetworkInterface } from '../lib/request_handlers/network-interface';

const router = express.Router();

router
.get(
'/job',
(request, response, next) => {
const {
path,
query: { command },
} = request;

const script = 'anvil-configure-host';

if (command === script) return next();

return response.redirect(`/api/init${path}?command=${script}`);
},
assertInit({
fail: (request, response, next) => next(),
}),
getJob,
)
.get('/job/:uuid', getJobDetail)
.get(
'/network-interface/:hostUUID?',
assertInit({
Expand Down
7 changes: 6 additions & 1 deletion striker-ui-api/src/types/ApiHost.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ type HostOverview = {
name: string;
uuid: string;
};
hostConfigured: boolean;
hostName: string;
hostStatus: string;
hostType: string;
Expand All @@ -68,7 +69,7 @@ type InitializeStrikerNetworkForm = {
createBridge?: StringBoolean;
interfaces: Array<NetworkInterfaceOverview | null | undefined>;
ipAddress: string;
name: string;
sequence: number;
subnetMask: string;
type: string;
};
Expand All @@ -86,6 +87,10 @@ type InitializeStrikerForm = {
organizationPrefix: string;
};

type InitializeStrikerResponseBody = {
jobUuid: string;
};

type PrepareHostRequestBody = {
enterpriseUUID?: string;
hostIPAddress: string;
Expand Down
19 changes: 13 additions & 6 deletions striker-ui-api/src/types/ApiNetworkInterface.d.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
type NetworkInterfaceOverview = {
networkInterfaceUUID: string;
networkInterfaceMACAddress: string;
networkInterfaceName: string;
networkInterfaceState: string;
networkInterfaceSpeed: number;
networkInterfaceOrder: number;
dns: null | string;
gateway: null | string;
ip: null | string;
mac: string;
name: string;
order: number;
// Unit: Mbps
speed: number;
state: string;
subnetMask: null | string;
uuid: string;
};

type NetworkInterfaceOverviewList = Record<string, NetworkInterfaceOverview>;
67 changes: 30 additions & 37 deletions striker-ui/components/Decorator.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Box as MUIBox, BoxProps as MUIBoxProps } from '@mui/material';
import { Box, BoxProps, styled } from '@mui/material';
import { FC } from 'react';

import {
BLUE,
GREY,
Expand All @@ -8,9 +9,9 @@ import {
BORDER_RADIUS,
} from '../lib/consts/DEFAULT_THEME';

export type Colours = 'ok' | 'off' | 'error' | 'warning';
type Colours = 'ok' | 'off' | 'error' | 'warning';

type DecoratorProps = MUIBoxProps & {
type DecoratorProps = BoxProps & {
colour: Colours;
};

Expand All @@ -23,40 +24,32 @@ const classes = {
off: `${PREFIX}-off`,
};

const Decorator: FC<DecoratorProps> = ({
colour,
sx,
...restDecoratorProps
}): JSX.Element => (
<MUIBox
{...{
...restDecoratorProps,
className: classes[colour],
sx: {
borderRadius: BORDER_RADIUS,
height: '100%',
width: '1.4em',

[`&.${classes.ok}`]: {
backgroundColor: BLUE,
},

[`&.${classes.warning}`]: {
backgroundColor: PURPLE,
},

[`&.${classes.error}`]: {
backgroundColor: RED,
},

[`&.${classes.off}`]: {
backgroundColor: GREY,
},

...sx,
},
}}
/>
const BaseBox = styled(Box)({
borderRadius: BORDER_RADIUS,
height: '100%',
width: '1.4em',

[`&.${classes.ok}`]: {
backgroundColor: BLUE,
},

[`&.${classes.warning}`]: {
backgroundColor: PURPLE,
},

[`&.${classes.error}`]: {
backgroundColor: RED,
},

[`&.${classes.off}`]: {
backgroundColor: GREY,
},
});

const Decorator: FC<DecoratorProps> = ({ colour, ...restDecoratorProps }) => (
<BaseBox {...restDecoratorProps} className={classes[colour]} />
);

export type { Colours };

export default Decorator;
Loading

0 comments on commit b3cfb20

Please sign in to comment.