fix(striker-ui-api): replace get anvil network summary endpoint

main
Tsu-ba-me 2 years ago
parent ab4a4cee9a
commit 0360b39598
  1. 20
      striker-ui-api/src/lib/accessModule.ts
  2. 159
      striker-ui-api/src/lib/request_handlers/anvil/getAnvilNetwork.ts
  3. 1
      striker-ui-api/src/lib/request_handlers/anvil/index.ts
  4. 2
      striker-ui-api/src/routes/anvil.ts
  5. 25
      striker-ui-api/src/types/ApiAn.d.ts
  6. 127
      striker-ui-api/src/types/GetAnvilDataFunction.d.ts

@ -309,6 +309,25 @@ const getManifestData = async (manifestUuid?: string) => {
return getData<AnvilDataManifestListHash>('manifests'); return getData<AnvilDataManifestListHash>('manifests');
}; };
const getNetworkData = async (hostUuid: string, hostName?: string) => {
let replacementKey = hostName;
if (!replacementKey) {
({
host_uuid: {
[hostUuid]: { short_host_name: replacementKey },
},
} = await getHostData());
}
await subroutine('load_interfces', {
params: [{ host: replacementKey, host_uuid: hostUuid }],
pre: ['Network'],
});
return getData<AnvilDataNetworkListHash>('network');
};
const getPeerData: GetPeerDataFunction = async ( const getPeerData: GetPeerDataFunction = async (
target, target,
{ password, port } = {}, { password, port } = {},
@ -358,6 +377,7 @@ export {
getLocalHostName, getLocalHostName,
getLocalHostUuid as getLocalHostUUID, getLocalHostUuid as getLocalHostUUID,
getManifestData, getManifestData,
getNetworkData,
getPeerData, getPeerData,
getUpsSpec, getUpsSpec,
query, query,

@ -0,0 +1,159 @@
import assert from 'assert';
import { RequestHandler } from 'express';
import { REP_UUID } from '../../consts';
import { getAnvilData, getHostData, getNetworkData } from '../../accessModule';
import { sanitize } from '../../sanitize';
import { stderr } from '../../shell';
const degrade = (current: string) =>
current === 'optimal' ? 'degraded' : current;
const compare = (a: string, b: string) => (a > b ? 1 : -1);
const buildSubnodeBonds = (
ifaces: AnvilDataSubnodeNetwork['interface'],
): AnvilDetailSubnodeBond[] => {
const bondList = Object.entries(ifaces)
.sort(([an, { type: at }], [bn, { type: bt }]) => {
const ab = at === 'bond';
const bb = bt === 'bond';
if (ab && bb) return compare(an, bn);
if (ab) return -1;
if (bb) return 1;
return compare(an, bn);
})
.reduce<{
[bondUuid: string]: AnvilDetailSubnodeBond;
}>((previous, [ifname, ifvalue]) => {
const { type } = ifvalue;
if (type === 'bond') {
const { active_interface, uuid: bondUuid } =
ifvalue as AnvilDataHostNetworkBond;
previous[bondUuid] = {
active_interface,
bond_name: ifname,
bond_uuid: bondUuid,
links: [],
};
} else if (type === 'interface') {
const {
bond_uuid: bondUuid,
operational,
speed,
uuid: linkUuid,
} = ifvalue as AnvilDataHostNetworkLink;
// Link without bond UUID can be ignored
if (!REP_UUID.test(bondUuid)) return previous;
const {
[bondUuid]: { active_interface, links },
} = previous;
let linkState: string = operational === 'up' ? 'optimal' : 'down';
links.forEach((xLink) => {
const { link_speed: xlSpeed, link_state: xlState } = xLink;
if (xlSpeed < speed) {
// Seen link is slower than current link, mark seen link as 'degraded'
xLink.link_state = degrade(xlState);
} else if (xlSpeed > speed) {
// Current link is slower than seen link, mark current link as 'degraded'
linkState = degrade(linkState);
}
});
links.push({
is_active: ifname === active_interface,
link_name: ifname,
link_speed: speed,
link_state: linkState,
link_uuid: linkUuid,
});
}
return previous;
}, {});
return Object.values(bondList);
};
export const getAnvilNetwork: RequestHandler<
AnvilDetailParamsDictionary
> = async (request, response) => {
const {
params: { anvilUuid: rAnUuid },
} = request;
const anUuid = sanitize(rAnUuid, 'string', { modifierType: 'sql' });
try {
assert(
REP_UUID.test(anUuid),
`Param UUID must be a valid UUIDv4; got [${anUuid}]`,
);
} catch (error) {
stderr(`Failed to assert value during get anvil network; CAUSE: ${error}`);
return response.status(400).send();
}
let ans: AnvilDataAnvilListHash;
let hosts: AnvilDataHostListHash;
try {
ans = await getAnvilData();
hosts = await getHostData();
} catch (error) {
stderr(`Failed to get anvil and host data; CAUSE: ${error}`);
return response.status(500).send();
}
const {
anvil_uuid: {
[anUuid]: {
anvil_node1_host_uuid: n1uuid,
anvil_node2_host_uuid: n2uuid,
},
},
} = ans;
const rsbody: AnvilDetailNetworkSummary = { hosts: [] };
for (const hostUuid of [n1uuid, n2uuid]) {
try {
const {
host_uuid: {
[hostUuid]: { short_host_name: hostName },
},
} = hosts;
const { [hostName]: subnodeNetwork } = await getNetworkData(
hostUuid,
hostName,
);
const { interface: ifaces } = subnodeNetwork as AnvilDataSubnodeNetwork;
rsbody.hosts.push({
bonds: buildSubnodeBonds(ifaces),
host_name: hostName,
host_uuid: hostUuid,
});
} catch (error) {
stderr(`Failed to get host ${hostUuid} network data; CAUSE: ${error}`);
return response.status(500).send();
}
}
return response.json(rsbody);
};

@ -2,3 +2,4 @@ export * from './getAnvil';
export * from './getAnvilCpu'; export * from './getAnvilCpu';
export * from './getAnvilDetail'; export * from './getAnvilDetail';
export * from './getAnvilMemory'; export * from './getAnvilMemory';
export * from './getAnvilNetwork';

@ -5,6 +5,7 @@ import {
getAnvilCpu, getAnvilCpu,
getAnvilDetail, getAnvilDetail,
getAnvilMemory, getAnvilMemory,
getAnvilNetwork,
} from '../lib/request_handlers/anvil'; } from '../lib/request_handlers/anvil';
const router = express.Router(); const router = express.Router();
@ -13,6 +14,7 @@ router
.get('/', getAnvil) .get('/', getAnvil)
.get('/:anvilUuid/cpu', getAnvilCpu) .get('/:anvilUuid/cpu', getAnvilCpu)
.get('/:anvilUuid/memory', getAnvilMemory) .get('/:anvilUuid/memory', getAnvilMemory)
.get('/:anvilUuid/network', getAnvilNetwork)
.get('/:anvilUuid', getAnvilDetail); .get('/:anvilUuid', getAnvilDetail);
export default router; export default router;

@ -36,6 +36,31 @@ type AnvilDetailHostForProvisionServer = {
hostMemory: string; hostMemory: string;
}; };
type AnvilDetailSubnodeLink = {
is_active: boolean;
link_name: string;
link_speed: number;
link_state: string;
link_uuid: string;
};
type AnvilDetailSubnodeBond = {
active_interface: string;
bond_name: string;
bond_uuid: string;
links: AnvilDetailSubnodeLink[];
};
type AnvilDetailSubnodeNetwork = {
bonds: AnvilDetailSubnodeBond[];
host_name: string;
host_uuid: string;
};
type AnvilDetailNetworkSummary = {
hosts: AnvilDetailSubnodeNetwork[];
};
type AnvilDetailServerForProvisionServer = { type AnvilDetailServerForProvisionServer = {
serverUUID: string; serverUUID: string;
serverName: string; serverName: string;

@ -47,6 +47,133 @@ type AnvilDataHostListHash = {
}; };
}; };
type AnvilDataHostNetworkBond = {
active_interface: string;
bridge_uuid: string;
down_delay: number;
interfaces: string[];
mac_address: string;
mii_polling_interval: number;
mode: string;
mtu: number;
operational: 'up' | 'down';
primary_interface: string;
primary_reselect: string;
type: 'bond';
up_delay: number;
uuid: string;
};
type AnvilDataHostNetworkBridge = {
id: string;
interfaces: string[];
mac_address: string;
mtu: number;
stp_enabled: string;
type: 'bridge';
uuid: string;
};
type AnvilDataHostNetworkLink = {
bond_name: string;
bond_uuid: string;
bridge_name: string;
bridge_uuid: string;
changed_order: number;
duplex: string;
link_state: string;
mac_address: string;
medium: string;
mtu: number;
operational: 'up' | 'down';
speed: number;
type: 'interface';
uuid: string;
};
type AnvilDataHostNetworkPrimaryLink = AnvilDataHostNetworkLink & {
default_gateway: NumberBoolean;
dns: string;
gateway: string;
ip: string;
network_interface_uuid: string;
subnet_mask: string;
};
type AnvilDataStrikerNetworkPrimaryLink = Omit<
AnvilDataHostNetworkPrimaryLink,
| 'bond_name'
| 'bond_uuid'
| 'bridge_name'
| 'bridge_uuid'
| 'changed_order'
| 'duplex'
| 'link_state'
| 'medium'
| 'mtu'
| 'operational'
| 'speed'
| 'type'
| 'uuid'
| 'network_interface_uuid'
> & {
file: string;
mtu: string;
rx_bytes: string;
status: string;
tx_bytes: string;
variable: {
BOOTPROTO: string;
DEFROUTE: string;
DEVICE: string;
DSN1?: string;
GATEWAY?: string;
HWADDR: string;
IPADDR: string;
IPV6INIT: string;
NAME: string;
NM_CONTROLLED: string;
ONBOOT: string;
PREFIX: string;
TYPE: string;
USERCTL: string;
UUID: string;
ZONE: string;
};
};
type AnvilDataSubnodeNetwork = {
bond_uuid: {
[uuid: string]: { name: string };
};
bridge_uuid: {
[uuid: string]: { name: string };
};
interface: {
[name: string]:
| AnvilDataHostNetworkBond
| AnvilDataHostNetworkBridge
| AnvilDataHostNetworkLink
| AnvilDataHostNetworkPrimaryLink;
};
};
type AnvilDataStrikerNetwork = {
interface: {
[ifname: string]:
| AnvilDataHostNetworkLink
| AnvilDataHostNetworkPrimaryLink;
};
};
type AnvilDataHostNetworkHash =
| AnvilDataSubnodeNetwork
| AnvilDataStrikerNetwork;
type AnvilDataNetworkListHash = {
[hostId: string]: AnvilDataHostNetworkHash;
};
type AnvilDataManifestListHash = { type AnvilDataManifestListHash = {
manifest_uuid: { manifest_uuid: {
[manifestUUID: string]: { [manifestUUID: string]: {

Loading…
Cancel
Save