Can attach defined networks to domains
This commit is contained in:
parent
54a3013c59
commit
f05ae9fd52
@ -63,11 +63,20 @@ pub struct FeaturesXML {
|
|||||||
#[serde(rename = "acpi")]
|
#[serde(rename = "acpi")]
|
||||||
pub struct ACPIXML {}
|
pub struct ACPIXML {}
|
||||||
|
|
||||||
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
|
#[serde(rename = "source")]
|
||||||
|
pub struct NetIntSourceXML {
|
||||||
|
#[serde(rename(serialize = "@network"))]
|
||||||
|
pub network: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "interface")]
|
#[serde(rename = "interface")]
|
||||||
pub struct DomainNetInterfaceXML {
|
pub struct DomainNetInterfaceXML {
|
||||||
#[serde(rename(serialize = "@type"))]
|
#[serde(rename(serialize = "@type"))]
|
||||||
pub r#type: String,
|
pub r#type: String,
|
||||||
|
|
||||||
|
pub source: Option<NetIntSourceXML>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Devices information
|
/// Devices information
|
||||||
|
@ -3,7 +3,7 @@ use crate::constants;
|
|||||||
use crate::libvirt_lib_structures::{
|
use crate::libvirt_lib_structures::{
|
||||||
DevicesXML, DiskBootXML, DiskDriverXML, DiskReadOnlyXML, DiskSourceXML, DiskTargetXML, DiskXML,
|
DevicesXML, DiskBootXML, DiskDriverXML, DiskReadOnlyXML, DiskSourceXML, DiskTargetXML, DiskXML,
|
||||||
DomainCPUTopology, DomainCPUXML, DomainMemoryXML, DomainNetInterfaceXML, DomainVCPUXML,
|
DomainCPUTopology, DomainCPUXML, DomainMemoryXML, DomainNetInterfaceXML, DomainVCPUXML,
|
||||||
DomainXML, FeaturesXML, GraphicsXML, NetworkDHCPRangeXML, NetworkDHCPXML,
|
DomainXML, FeaturesXML, GraphicsXML, NetIntSourceXML, NetworkDHCPRangeXML, NetworkDHCPXML,
|
||||||
NetworkDNSForwarderXML, NetworkDNSXML, NetworkDomainXML, NetworkForwardXML, NetworkIPXML,
|
NetworkDNSForwarderXML, NetworkDNSXML, NetworkDomainXML, NetworkForwardXML, NetworkIPXML,
|
||||||
NetworkXML, OSLoaderXML, OSTypeXML, XMLUuid, ACPIXML, OSXML,
|
NetworkXML, OSLoaderXML, OSTypeXML, XMLUuid, ACPIXML, OSXML,
|
||||||
};
|
};
|
||||||
@ -68,7 +68,7 @@ pub enum VMArchitecture {
|
|||||||
#[serde(tag = "type")]
|
#[serde(tag = "type")]
|
||||||
pub enum Network {
|
pub enum Network {
|
||||||
UserspaceSLIRPStack,
|
UserspaceSLIRPStack,
|
||||||
// TODO : complete network types
|
DefinedNetwork { network: String }, // TODO : complete network types
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
@ -226,6 +226,11 @@ impl VMInfo {
|
|||||||
networks.push(match n {
|
networks.push(match n {
|
||||||
Network::UserspaceSLIRPStack => DomainNetInterfaceXML {
|
Network::UserspaceSLIRPStack => DomainNetInterfaceXML {
|
||||||
r#type: "user".to_string(),
|
r#type: "user".to_string(),
|
||||||
|
source: None,
|
||||||
|
},
|
||||||
|
Network::DefinedNetwork { network } => DomainNetInterfaceXML {
|
||||||
|
r#type: "network".to_string(),
|
||||||
|
source: Some(NetIntSourceXML { network }),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -344,6 +349,9 @@ impl VMInfo {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|d| match d.r#type.as_str() {
|
.map(|d| match d.r#type.as_str() {
|
||||||
"user" => Ok(Network::UserspaceSLIRPStack),
|
"user" => Ok(Network::UserspaceSLIRPStack),
|
||||||
|
"network" => Ok(Network::DefinedNetwork {
|
||||||
|
network: d.source.as_ref().unwrap().network.to_string(),
|
||||||
|
}),
|
||||||
a => Err(LibVirtStructError::DomainExtraction(format!(
|
a => Err(LibVirtStructError::DomainExtraction(format!(
|
||||||
"Unknown network interface type: {a}! "
|
"Unknown network interface type: {a}! "
|
||||||
))),
|
))),
|
||||||
|
@ -30,12 +30,17 @@ export interface VMDisk {
|
|||||||
deleteType?: "keepfile" | "deletefile";
|
deleteType?: "keepfile" | "deletefile";
|
||||||
}
|
}
|
||||||
|
|
||||||
export type VMNetInterface = VMNetUserspaceSLIRPStack;
|
export type VMNetInterface = VMNetUserspaceSLIRPStack | VMNetDefinedNetwork;
|
||||||
|
|
||||||
export interface VMNetUserspaceSLIRPStack {
|
export interface VMNetUserspaceSLIRPStack {
|
||||||
type: "UserspaceSLIRPStack";
|
type: "UserspaceSLIRPStack";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface VMNetDefinedNetwork {
|
||||||
|
type: "DefinedNetwork";
|
||||||
|
network: string;
|
||||||
|
}
|
||||||
|
|
||||||
interface VMInfoInterface {
|
interface VMInfoInterface {
|
||||||
name: string;
|
name: string;
|
||||||
uuid?: string;
|
uuid?: string;
|
||||||
@ -65,7 +70,7 @@ export class VMInfo implements VMInfoInterface {
|
|||||||
vnc_access: boolean;
|
vnc_access: boolean;
|
||||||
iso_file?: string;
|
iso_file?: string;
|
||||||
disks: VMDisk[];
|
disks: VMDisk[];
|
||||||
networks: VMNetUserspaceSLIRPStack[];
|
networks: VMNetInterface[];
|
||||||
|
|
||||||
constructor(int: VMInfoInterface) {
|
constructor(int: VMInfoInterface) {
|
||||||
this.name = int.name;
|
this.name = int.name;
|
||||||
|
@ -13,11 +13,13 @@ import {
|
|||||||
import { VMInfo, VMNetInterface } from "../../api/VMApi";
|
import { VMInfo, VMNetInterface } from "../../api/VMApi";
|
||||||
import { useConfirm } from "../../hooks/providers/ConfirmDialogProvider";
|
import { useConfirm } from "../../hooks/providers/ConfirmDialogProvider";
|
||||||
import { SelectInput } from "./SelectInput";
|
import { SelectInput } from "./SelectInput";
|
||||||
|
import { NetworkInfo } from "../../api/NetworksApi";
|
||||||
|
|
||||||
export function VMNetworksList(p: {
|
export function VMNetworksList(p: {
|
||||||
vm: VMInfo;
|
vm: VMInfo;
|
||||||
onChange?: () => void;
|
onChange?: () => void;
|
||||||
editable: boolean;
|
editable: boolean;
|
||||||
|
networksList: NetworkInfo[];
|
||||||
}): React.ReactElement {
|
}): React.ReactElement {
|
||||||
const addNew = () => {
|
const addNew = () => {
|
||||||
p.vm.networks.push({ type: "UserspaceSLIRPStack" });
|
p.vm.networks.push({ type: "UserspaceSLIRPStack" });
|
||||||
@ -28,15 +30,14 @@ export function VMNetworksList(p: {
|
|||||||
<>
|
<>
|
||||||
{/* networks list */}
|
{/* networks list */}
|
||||||
{p.vm.networks.map((n, num) => (
|
{p.vm.networks.map((n, num) => (
|
||||||
<NetworkInfo
|
<NetworkInfoWidget
|
||||||
key={num}
|
key={num}
|
||||||
editable={p.editable}
|
|
||||||
network={n}
|
network={n}
|
||||||
onChange={p.onChange}
|
|
||||||
removeFromList={() => {
|
removeFromList={() => {
|
||||||
p.vm.networks.splice(num, 1);
|
p.vm.networks.splice(num, 1);
|
||||||
p.onChange?.();
|
p.onChange?.();
|
||||||
}}
|
}}
|
||||||
|
{...p}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
@ -47,11 +48,12 @@ export function VMNetworksList(p: {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function NetworkInfo(p: {
|
function NetworkInfoWidget(p: {
|
||||||
editable: boolean;
|
editable: boolean;
|
||||||
network: VMNetInterface;
|
network: VMNetInterface;
|
||||||
onChange?: () => void;
|
onChange?: () => void;
|
||||||
removeFromList: () => void;
|
removeFromList: () => void;
|
||||||
|
networksList: NetworkInfo[];
|
||||||
}): React.ReactElement {
|
}): React.ReactElement {
|
||||||
const confirm = useConfirm();
|
const confirm = useConfirm();
|
||||||
const deleteNetwork = async () => {
|
const deleteNetwork = async () => {
|
||||||
@ -65,7 +67,7 @@ function NetworkInfo(p: {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<ListItem
|
<ListItem
|
||||||
secondaryAction={
|
secondaryAction={
|
||||||
p.editable && (
|
p.editable && (
|
||||||
@ -95,6 +97,7 @@ function NetworkInfo(p: {
|
|||||||
value={p.network.type}
|
value={p.network.type}
|
||||||
onValueChange={(v) => {
|
onValueChange={(v) => {
|
||||||
p.network.type = v as any;
|
p.network.type = v as any;
|
||||||
|
p.onChange?.();
|
||||||
}}
|
}}
|
||||||
options={[
|
options={[
|
||||||
{
|
{
|
||||||
@ -103,6 +106,11 @@ function NetworkInfo(p: {
|
|||||||
description:
|
description:
|
||||||
"Provides a virtual LAN with NAT to the outside world. The virtual network has DHCP & DNS services",
|
"Provides a virtual LAN with NAT to the outside world. The virtual network has DHCP & DNS services",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: "Defined network",
|
||||||
|
value: "DefinedNetwork",
|
||||||
|
description: "Attach to a defined network",
|
||||||
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
@ -111,6 +119,32 @@ function NetworkInfo(p: {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
<div style={{ marginLeft: "70px" }}>
|
||||||
|
{p.network.type === "DefinedNetwork" && (
|
||||||
|
<SelectInput
|
||||||
|
editable={p.editable}
|
||||||
|
label="Defined network"
|
||||||
|
options={p.networksList.map((n) => {
|
||||||
|
const chars = [n.forward_mode.toString()];
|
||||||
|
if (n.ip_v4) chars.push("IPv4");
|
||||||
|
if (n.ip_v6) chars.push("IPv6");
|
||||||
|
if (n.description) chars.push(n.description);
|
||||||
|
|
||||||
|
return {
|
||||||
|
label: n.name,
|
||||||
|
value: n.name,
|
||||||
|
description: chars.join(" - "),
|
||||||
|
};
|
||||||
|
})}
|
||||||
|
value={p.network.network}
|
||||||
|
onValueChange={(v) => {
|
||||||
|
if (p.network.type === "DefinedNetwork")
|
||||||
|
p.network.network = v as any;
|
||||||
|
p.onChange?.();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ import { VMSelectIsoInput } from "../forms/VMSelectIsoInput";
|
|||||||
import { VMScreenshot } from "./VMScreenshot";
|
import { VMScreenshot } from "./VMScreenshot";
|
||||||
import { ResAutostartInput } from "../forms/ResAutostartInput";
|
import { ResAutostartInput } from "../forms/ResAutostartInput";
|
||||||
import { VMNetworksList } from "../forms/VMNetworksList";
|
import { VMNetworksList } from "../forms/VMNetworksList";
|
||||||
|
import { NetworkApi, NetworkInfo } from "../../api/NetworksApi";
|
||||||
|
|
||||||
interface DetailsProps {
|
interface DetailsProps {
|
||||||
vm: VMInfo;
|
vm: VMInfo;
|
||||||
@ -27,10 +28,12 @@ export function VMDetails(p: DetailsProps): React.ReactElement {
|
|||||||
const [vcpuCombinations, setVCPUCombinations] = React.useState<
|
const [vcpuCombinations, setVCPUCombinations] = React.useState<
|
||||||
number[] | any
|
number[] | any
|
||||||
>();
|
>();
|
||||||
|
const [networksList, setNetworksList] = React.useState<NetworkInfo[] | any>();
|
||||||
|
|
||||||
const load = async () => {
|
const load = async () => {
|
||||||
setIsoList(await IsoFilesApi.GetList());
|
setIsoList(await IsoFilesApi.GetList());
|
||||||
setVCPUCombinations(await ServerApi.NumberVCPUs());
|
setVCPUCombinations(await ServerApi.NumberVCPUs());
|
||||||
|
setNetworksList(await NetworkApi.GetList());
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -42,6 +45,7 @@ export function VMDetails(p: DetailsProps): React.ReactElement {
|
|||||||
<VMDetailsInner
|
<VMDetailsInner
|
||||||
isoList={isoList}
|
isoList={isoList}
|
||||||
vcpuCombinations={vcpuCombinations}
|
vcpuCombinations={vcpuCombinations}
|
||||||
|
networksList={networksList}
|
||||||
{...p}
|
{...p}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -50,7 +54,11 @@ export function VMDetails(p: DetailsProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function VMDetailsInner(
|
function VMDetailsInner(
|
||||||
p: DetailsProps & { isoList: IsoFile[]; vcpuCombinations: number[] }
|
p: DetailsProps & {
|
||||||
|
isoList: IsoFile[];
|
||||||
|
vcpuCombinations: number[];
|
||||||
|
networksList: NetworkInfo[];
|
||||||
|
}
|
||||||
): React.ReactElement {
|
): React.ReactElement {
|
||||||
return (
|
return (
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
@ -201,12 +209,12 @@ function VMDetailsInner(
|
|||||||
p.onChange?.();
|
p.onChange?.();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<VMDisksList vm={p.vm} editable={p.editable} onChange={p.onChange} />
|
<VMDisksList {...p} />
|
||||||
</EditSection>
|
</EditSection>
|
||||||
|
|
||||||
{/* Networks section */}
|
{/* Networks section */}
|
||||||
<EditSection title="Networks">
|
<EditSection title="Networks">
|
||||||
<VMNetworksList vm={p.vm} editable={p.editable} onChange={p.onChange} />
|
<VMNetworksList {...p} />
|
||||||
</EditSection>
|
</EditSection>
|
||||||
</Grid>
|
</Grid>
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user