Add support to bridge option on Web UI
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is passing
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	continuous-integration/drone/push Build is passing
				
			This commit is contained in:
		@@ -217,4 +217,16 @@ export class ServerApi {
 | 
				
			|||||||
      })
 | 
					      })
 | 
				
			||||||
    ).data;
 | 
					    ).data;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Get host networks bridges list
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  static async GetNetworksBridgesList(): Promise<string[]> {
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					      await APIClient.exec({
 | 
				
			||||||
 | 
					        method: "GET",
 | 
				
			||||||
 | 
					        uri: "/server/bridges",
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					    ).data;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,7 +50,11 @@ export interface VMNetInterfaceFilter {
 | 
				
			|||||||
  parameters: VMNetInterfaceFilterParams[];
 | 
					  parameters: VMNetInterfaceFilterParams[];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type VMNetInterface = (VMNetUserspaceSLIRPStack | VMNetDefinedNetwork) &
 | 
					export type VMNetInterface = (
 | 
				
			||||||
 | 
					  | VMNetUserspaceSLIRPStack
 | 
				
			||||||
 | 
					  | VMNetDefinedNetwork
 | 
				
			||||||
 | 
					  | VMNetBridge
 | 
				
			||||||
 | 
					) &
 | 
				
			||||||
  VMNetInterfaceBase;
 | 
					  VMNetInterfaceBase;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface VMNetInterfaceBase {
 | 
					export interface VMNetInterfaceBase {
 | 
				
			||||||
@@ -67,6 +71,11 @@ export interface VMNetDefinedNetwork {
 | 
				
			|||||||
  network: string;
 | 
					  network: string;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface VMNetBridge {
 | 
				
			||||||
 | 
					  type: "Bridge";
 | 
				
			||||||
 | 
					  bridge: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface VMInfoInterface {
 | 
					interface VMInfoInterface {
 | 
				
			||||||
  name: string;
 | 
					  name: string;
 | 
				
			||||||
  uuid?: string;
 | 
					  uuid?: string;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,6 +29,7 @@ export function VMNetworksList(p: {
 | 
				
			|||||||
  onChange?: () => void;
 | 
					  onChange?: () => void;
 | 
				
			||||||
  editable: boolean;
 | 
					  editable: boolean;
 | 
				
			||||||
  networksList: NetworkInfo[];
 | 
					  networksList: NetworkInfo[];
 | 
				
			||||||
 | 
					  bridgesList: string[];
 | 
				
			||||||
  networkFiltersList: NWFilter[];
 | 
					  networkFiltersList: NWFilter[];
 | 
				
			||||||
}): React.ReactElement {
 | 
					}): React.ReactElement {
 | 
				
			||||||
  const addNew = () => {
 | 
					  const addNew = () => {
 | 
				
			||||||
@@ -72,6 +73,7 @@ function NetworkInfoWidget(p: {
 | 
				
			|||||||
  onChange?: () => void;
 | 
					  onChange?: () => void;
 | 
				
			||||||
  removeFromList: () => void;
 | 
					  removeFromList: () => void;
 | 
				
			||||||
  networksList: NetworkInfo[];
 | 
					  networksList: NetworkInfo[];
 | 
				
			||||||
 | 
					  bridgesList: string[];
 | 
				
			||||||
  networkFiltersList: NWFilter[];
 | 
					  networkFiltersList: NWFilter[];
 | 
				
			||||||
}): React.ReactElement {
 | 
					}): React.ReactElement {
 | 
				
			||||||
  const confirm = useConfirm();
 | 
					  const confirm = useConfirm();
 | 
				
			||||||
@@ -130,6 +132,11 @@ function NetworkInfoWidget(p: {
 | 
				
			|||||||
                    value: "DefinedNetwork",
 | 
					                    value: "DefinedNetwork",
 | 
				
			||||||
                    description: "Attach to a defined network",
 | 
					                    description: "Attach to a defined network",
 | 
				
			||||||
                  },
 | 
					                  },
 | 
				
			||||||
 | 
					                  {
 | 
				
			||||||
 | 
					                    label: "Host bridge",
 | 
				
			||||||
 | 
					                    value: "Bridge",
 | 
				
			||||||
 | 
					                    description: "Attach to an host's bridge",
 | 
				
			||||||
 | 
					                  },
 | 
				
			||||||
                ]}
 | 
					                ]}
 | 
				
			||||||
              />
 | 
					              />
 | 
				
			||||||
            ) : (
 | 
					            ) : (
 | 
				
			||||||
@@ -149,31 +156,53 @@ function NetworkInfoWidget(p: {
 | 
				
			|||||||
          }}
 | 
					          }}
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        {/* Defined network selection */}
 | 
				
			||||||
        {p.network.type === "DefinedNetwork" && (
 | 
					        {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?.();
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
 | 
					        )}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        {/* Bridge selection */}
 | 
				
			||||||
 | 
					        {p.network.type === "Bridge" && (
 | 
				
			||||||
 | 
					          <SelectInput
 | 
				
			||||||
 | 
					            editable={p.editable}
 | 
				
			||||||
 | 
					            label="Host bridge"
 | 
				
			||||||
 | 
					            options={p.bridgesList.map((n) => {
 | 
				
			||||||
 | 
					              return {
 | 
				
			||||||
 | 
					                label: n,
 | 
				
			||||||
 | 
					                value: n,
 | 
				
			||||||
 | 
					              };
 | 
				
			||||||
 | 
					            })}
 | 
				
			||||||
 | 
					            value={p.network.bridge}
 | 
				
			||||||
 | 
					            onValueChange={(v) => {
 | 
				
			||||||
 | 
					              if (p.network.type === "Bridge") p.network.bridge = v as any;
 | 
				
			||||||
 | 
					              p.onChange?.();
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
 | 
					        )}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        {p.network.type !== "UserspaceSLIRPStack" && (
 | 
				
			||||||
          <>
 | 
					          <>
 | 
				
			||||||
            <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?.();
 | 
					 | 
				
			||||||
              }}
 | 
					 | 
				
			||||||
            />
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            {/* Network Filter */}
 | 
					            {/* Network Filter */}
 | 
				
			||||||
            <NWFilterSelectInput
 | 
					            <NWFilterSelectInput
 | 
				
			||||||
              editable={p.editable}
 | 
					              editable={p.editable}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -725,6 +725,11 @@ export function TokenRightsEditor(p: {
 | 
				
			|||||||
          right={{ verb: "GET", path: "/api/server/networks" }}
 | 
					          right={{ verb: "GET", path: "/api/server/networks" }}
 | 
				
			||||||
          label="Get list of network cards"
 | 
					          label="Get list of network cards"
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
 | 
					        <RouteRight
 | 
				
			||||||
 | 
					          {...p}
 | 
				
			||||||
 | 
					          right={{ verb: "GET", path: "/api/server/bridges" }}
 | 
				
			||||||
 | 
					          label="Get list of network bridges"
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
      </RightsSection>
 | 
					      </RightsSection>
 | 
				
			||||||
    </>
 | 
					    </>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,6 +38,7 @@ interface DetailsProps {
 | 
				
			|||||||
export function VMDetails(p: DetailsProps): React.ReactElement {
 | 
					export function VMDetails(p: DetailsProps): React.ReactElement {
 | 
				
			||||||
  const [groupsList, setGroupsList] = React.useState<string[] | undefined>();
 | 
					  const [groupsList, setGroupsList] = React.useState<string[] | undefined>();
 | 
				
			||||||
  const [isoList, setIsoList] = React.useState<IsoFile[] | undefined>();
 | 
					  const [isoList, setIsoList] = React.useState<IsoFile[] | undefined>();
 | 
				
			||||||
 | 
					  const [bridgesList, setBridgesList] = React.useState<string[] | undefined>();
 | 
				
			||||||
  const [vcpuCombinations, setVCPUCombinations] = React.useState<
 | 
					  const [vcpuCombinations, setVCPUCombinations] = React.useState<
 | 
				
			||||||
    number[] | undefined
 | 
					    number[] | undefined
 | 
				
			||||||
  >();
 | 
					  >();
 | 
				
			||||||
@@ -51,6 +52,7 @@ export function VMDetails(p: DetailsProps): React.ReactElement {
 | 
				
			|||||||
  const load = async () => {
 | 
					  const load = async () => {
 | 
				
			||||||
    setGroupsList(await GroupApi.GetList());
 | 
					    setGroupsList(await GroupApi.GetList());
 | 
				
			||||||
    setIsoList(await IsoFilesApi.GetList());
 | 
					    setIsoList(await IsoFilesApi.GetList());
 | 
				
			||||||
 | 
					    setBridgesList(await ServerApi.GetNetworksBridgesList());
 | 
				
			||||||
    setVCPUCombinations(await ServerApi.NumberVCPUs());
 | 
					    setVCPUCombinations(await ServerApi.NumberVCPUs());
 | 
				
			||||||
    setNetworksList(await NetworkApi.GetList());
 | 
					    setNetworksList(await NetworkApi.GetList());
 | 
				
			||||||
    setNetworkFiltersList(await NWFilterApi.GetList());
 | 
					    setNetworkFiltersList(await NWFilterApi.GetList());
 | 
				
			||||||
@@ -65,6 +67,7 @@ export function VMDetails(p: DetailsProps): React.ReactElement {
 | 
				
			|||||||
        <VMDetailsInner
 | 
					        <VMDetailsInner
 | 
				
			||||||
          groupsList={groupsList!}
 | 
					          groupsList={groupsList!}
 | 
				
			||||||
          isoList={isoList!}
 | 
					          isoList={isoList!}
 | 
				
			||||||
 | 
					          bridgesList={bridgesList!}
 | 
				
			||||||
          vcpuCombinations={vcpuCombinations!}
 | 
					          vcpuCombinations={vcpuCombinations!}
 | 
				
			||||||
          networksList={networksList!}
 | 
					          networksList={networksList!}
 | 
				
			||||||
          networkFiltersList={networkFiltersList!}
 | 
					          networkFiltersList={networkFiltersList!}
 | 
				
			||||||
@@ -87,6 +90,7 @@ enum VMTab {
 | 
				
			|||||||
type DetailsInnerProps = DetailsProps & {
 | 
					type DetailsInnerProps = DetailsProps & {
 | 
				
			||||||
  groupsList: string[];
 | 
					  groupsList: string[];
 | 
				
			||||||
  isoList: IsoFile[];
 | 
					  isoList: IsoFile[];
 | 
				
			||||||
 | 
					  bridgesList: string[];
 | 
				
			||||||
  vcpuCombinations: number[];
 | 
					  vcpuCombinations: number[];
 | 
				
			||||||
  networksList: NetworkInfo[];
 | 
					  networksList: NetworkInfo[];
 | 
				
			||||||
  networkFiltersList: NWFilter[];
 | 
					  networkFiltersList: NWFilter[];
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user