diff --git a/src/components/forms/NetworkDevicesForm.tsx b/src/components/forms/NetworkDevicesForm.tsx index 58f9c9ee..c99bc99a 100644 --- a/src/components/forms/NetworkDevicesForm.tsx +++ b/src/components/forms/NetworkDevicesForm.tsx @@ -23,6 +23,7 @@ import { focusField } from "util/formFields"; import { useNetworks } from "context/useNetworks"; import { useProfiles } from "context/useProfiles"; import NetworkSelector from "pages/projects/forms/NetworkSelector"; +import { bridgeType } from "util/networks"; interface Props { formik: InstanceAndProfileFormikProps; @@ -58,7 +59,9 @@ const NetworkDevicesForm: FC = ({ formik, project }) => { return ; } - const managedNetworks = networks.filter((network) => network.managed); + const filteredNetworks = networks.filter( + (network) => network.managed || network.type == bridgeType, + ); const focusNetwork = (id: number) => { focusField(`devices.${id}.name`); @@ -74,11 +77,23 @@ const NetworkDevicesForm: FC = ({ formik, project }) => { const addNetwork = () => { const copy = [...formik.values.devices]; - copy.push({ - type: "nic", - name: deduplicateName("eth", 1, existingDeviceNames), - network: managedNetworks[0]?.name ?? "", - }); + const isManaged = filteredNetworks[0]?.managed ?? false; + + if (!isManaged) { + copy.push({ + type: "nic", + name: deduplicateName("eth", 1, existingDeviceNames), + parent: filteredNetworks[0]?.name ?? "", + nictype: "bridged", + }); + } else { + copy.push({ + type: "nic", + name: deduplicateName("eth", 1, existingDeviceNames), + network: filteredNetworks[0]?.name ?? "", + }); + } + formik.setFieldValue("devices", copy); focusNetwork(copy.length - 1); @@ -171,21 +186,44 @@ or remove the originating item"
{readOnly ? (
- {(formik.values.devices[index] as LxdNicDevice).network} + {(formik.values.devices[index] as LxdNicDevice) + .network || + (formik.values.devices[index] as LxdNicDevice).parent}
) : ( - void formik.setFieldValue( + setValue={(value) => { + const selectedNetwork = filteredNetworks.find( + (n) => n.name === value, + ); + formik.setFieldValue( `devices.${index}.network`, value, - ) - } + ); + + let nicType = ""; + let parent = ""; + if (selectedNetwork.managed == false) { + nicType = "bridged"; + parent = value; + } + + formik.setFieldValue( + `devices.${index}.nictype`, + nicType, + ); + formik.setFieldValue( + `devices.${index}.parent`, + parent, + ); + }} id={`devices.${index}.network`} name={`devices.${index}.network`} /> diff --git a/src/pages/projects/forms/NetworkSelector.tsx b/src/pages/projects/forms/NetworkSelector.tsx index 79ac41c5..17ca9615 100644 --- a/src/pages/projects/forms/NetworkSelector.tsx +++ b/src/pages/projects/forms/NetworkSelector.tsx @@ -2,6 +2,7 @@ import { Select } from "@canonical/react-components"; import type { SelectProps } from "@canonical/react-components"; import type { FC } from "react"; import { useNetworks } from "context/useNetworks"; +import { bridgeType } from "util/networks"; interface Props { value: string; @@ -21,10 +22,12 @@ const NetworkSelector: FC = ({ }) => { const { data: networks = [] } = useNetworks(project); - const managedNetworks = networks.filter((network) => network.managed); + const filteredNetworks = networks.filter( + (network) => network.managed || network.type == bridgeType, + ); const getNetworkOptions = () => { - const options = managedNetworks.map((network) => { + const options = filteredNetworks.map((network) => { return { label: network.name, value: network.name, diff --git a/src/util/formDevices.tsx b/src/util/formDevices.tsx index b9148600..b5b6e04a 100644 --- a/src/util/formDevices.tsx +++ b/src/util/formDevices.tsx @@ -97,6 +97,21 @@ export const formDeviceToPayload = (devices: FormDevice[]) => { [name]: item.bare, }; } + if (item.type === "nic") { + if (item.parent && item.parent != "") { + delete item.network; + return { + ...obj, + [name]: item, + }; + } + delete item.parent; + delete item.nictype; + return { + ...obj, + [name]: item, + }; + } if (item.type === "disk") { const { bare, ...rest } = item; item = { ...bare, ...rest }; @@ -118,7 +133,8 @@ export const parseDevices = (devices: LxdDevices): FormDevice[] => { const isCustomNetwork = item.type === "nic" && Object.keys(item).some( - (key) => !["type", "name", "network"].includes(key), + (key) => + !["type", "name", "network", "parent", "nictype"].includes(key), ); if (isCustomNetwork) { @@ -139,6 +155,15 @@ export const parseDevices = (devices: LxdDevices): FormDevice[] => { switch (item.type) { case "nic": + if (item.parent && item.parent != "") { + return { + name: key, + parent: item.parent, + nictype: item.nictype, + type: "nic", + }; + } + return { name: key, network: item.network,