Can specify MAC addresses for domains
This commit is contained in:
@ -5,6 +5,7 @@ export interface ServerConfig {
|
||||
local_auth_enabled: boolean;
|
||||
oidc_auth_enabled: boolean;
|
||||
iso_mimetypes: string[];
|
||||
net_mac_prefix: string;
|
||||
constraints: ServerConstraints;
|
||||
}
|
||||
|
||||
|
@ -34,10 +34,12 @@ export type VMNetInterface = VMNetUserspaceSLIRPStack | VMNetDefinedNetwork;
|
||||
|
||||
export interface VMNetUserspaceSLIRPStack {
|
||||
type: "UserspaceSLIRPStack";
|
||||
mac: string;
|
||||
}
|
||||
|
||||
export interface VMNetDefinedNetwork {
|
||||
type: "DefinedNetwork";
|
||||
mac: string;
|
||||
network: string;
|
||||
}
|
||||
|
||||
|
11
virtweb_frontend/src/utils/RandUtils.ts
Normal file
11
virtweb_frontend/src/utils/RandUtils.ts
Normal file
@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Generate a random MAC address
|
||||
*/
|
||||
export function randomMacAddress(prefix: string | undefined): string {
|
||||
let mac = "XX:XX:XX:XX:XX:XX";
|
||||
mac = prefix + mac.slice(prefix?.length);
|
||||
|
||||
return mac.replace(/X/g, () =>
|
||||
"0123456789abcdef".charAt(Math.floor(Math.random() * 16))
|
||||
);
|
||||
}
|
46
virtweb_frontend/src/widgets/forms/MACInput.tsx
Normal file
46
virtweb_frontend/src/widgets/forms/MACInput.tsx
Normal file
@ -0,0 +1,46 @@
|
||||
import { TextInput } from "./TextInput";
|
||||
|
||||
export function MACInput(p: {
|
||||
label: string;
|
||||
editable: boolean;
|
||||
value?: string;
|
||||
onValueChange?: (newVal: string | undefined) => void;
|
||||
}): React.ReactElement {
|
||||
const { onValueChange, ...props } = p;
|
||||
return (
|
||||
<TextInput
|
||||
onValueChange={(v) => {
|
||||
onValueChange?.(sanitizeMacAddress(v));
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function sanitizeMacAddress(s: string | undefined): string | undefined {
|
||||
if (s === "" || s === undefined) return s;
|
||||
|
||||
const split = s.split(":");
|
||||
if (split.length > 6) split.splice(6);
|
||||
|
||||
let needAnotherIteration = false;
|
||||
|
||||
const res = split
|
||||
.map((e) => {
|
||||
if (e === "") return e;
|
||||
|
||||
const num = parseInt(e, 16);
|
||||
if (isNaN(num)) return "0";
|
||||
|
||||
let s = num.toString(16).padStart(2, "0");
|
||||
if (num > 0xff) {
|
||||
needAnotherIteration = true;
|
||||
return s.slice(0, 2) + ":" + s.slice(2);
|
||||
}
|
||||
|
||||
return s;
|
||||
})
|
||||
.join(":");
|
||||
|
||||
return needAnotherIteration ? sanitizeMacAddress(res) : res;
|
||||
}
|
@ -14,6 +14,9 @@ import { VMInfo, VMNetInterface } from "../../api/VMApi";
|
||||
import { useConfirm } from "../../hooks/providers/ConfirmDialogProvider";
|
||||
import { SelectInput } from "./SelectInput";
|
||||
import { NetworkInfo } from "../../api/NetworksApi";
|
||||
import { randomMacAddress } from "../../utils/RandUtils";
|
||||
import { ServerApi } from "../../api/ServerApi";
|
||||
import { MACInput } from "./MACInput";
|
||||
|
||||
export function VMNetworksList(p: {
|
||||
vm: VMInfo;
|
||||
@ -22,7 +25,10 @@ export function VMNetworksList(p: {
|
||||
networksList: NetworkInfo[];
|
||||
}): React.ReactElement {
|
||||
const addNew = () => {
|
||||
p.vm.networks.push({ type: "UserspaceSLIRPStack" });
|
||||
p.vm.networks.push({
|
||||
type: "UserspaceSLIRPStack",
|
||||
mac: randomMacAddress(ServerApi.Config.net_mac_prefix),
|
||||
});
|
||||
p.onChange?.();
|
||||
};
|
||||
|
||||
@ -120,6 +126,16 @@ function NetworkInfoWidget(p: {
|
||||
/>
|
||||
</ListItem>
|
||||
<div style={{ marginLeft: "70px" }}>
|
||||
<MACInput
|
||||
editable={p.editable}
|
||||
label="MAC Address"
|
||||
value={p.network.mac}
|
||||
onValueChange={(v) => {
|
||||
p.network.mac = v!;
|
||||
p.onChange?.();
|
||||
}}
|
||||
/>
|
||||
|
||||
{p.network.type === "DefinedNetwork" && (
|
||||
<SelectInput
|
||||
editable={p.editable}
|
||||
|
Reference in New Issue
Block a user