diff --git a/packages/forklift-console-plugin/locales/en/plugin__forklift-console-plugin.json b/packages/forklift-console-plugin/locales/en/plugin__forklift-console-plugin.json index dfc3c4e66..d45892113 100644 --- a/packages/forklift-console-plugin/locales/en/plugin__forklift-console-plugin.json +++ b/packages/forklift-console-plugin/locales/en/plugin__forklift-console-plugin.json @@ -67,6 +67,7 @@ "Data centers": "Data centers", "Data stores": "Data stores", "Dates are compared in UTC. End of the interval is included.": "Dates are compared in UTC. End of the interval is included.", + "Dedicated CPU": "Dedicated CPU", "Default": "Default", "Default Transfer Network": "Default Transfer Network", "Defines the CPU limits allocated to the main container in the controller pod. The default value is 500 milliCPU.": "Defines the CPU limits allocated to the main container in the controller pod. The default value is 500 milliCPU.", @@ -118,8 +119,10 @@ "Error: VDDK init image must be valid.": "Error: VDDK init image must be valid.", "Failed": "Failed", "False": "False", + "Features": "Features", "Filter by cluster": "Filter by cluster", "Filter by endpoint": "Filter by endpoint", + "Filter by features": "Filter by features", "Filter by flavor": "Filter by flavor", "Filter by host": "Filter by host", "Filter by image": "Filter by image", @@ -133,10 +136,12 @@ "Filter by tenant": "Filter by tenant", "Flavor": "Flavor", "From": "From", + "GPUs": "GPUs", "Hide values": "Hide values", "Hooks for virtualization": "Hooks for virtualization", "Host": "Host", "Host cluster": "Host cluster", + "Host Devices": "Host Devices", "Hosts": "Hosts", "If true, the provider's REST API TLS certificate won't be validated.": "If true, the provider's REST API TLS certificate won't be validated.", "If true, the provider's TLS certificate won't be validated.": "If true, the provider's TLS certificate won't be validated.", @@ -221,6 +226,7 @@ "No StorageMaps found in namespace <1>{namespace}.": "No StorageMaps found in namespace <1>{namespace}.", "No StorageMaps found.": "No StorageMaps found.", "Not Ready": "Not Ready", + "NUMA": "NUMA", "Number of cluster in provider": "Number of cluster in provider", "Number of data centers in provider": "Number of data centers in provider", "Number of data stores in provider": "Number of data stores in provider", @@ -260,6 +266,8 @@ "Owner": "Owner", "Password": "Password", "Path": "Path", + "Persistent EFI": "Persistent EFI", + "Persistent TPM": "Persistent TPM", "Plans": "Plans", "Plans for virtualization": "Plans for virtualization", "Please choose a NetworkAttachmentDefinition for default data transfer.": "Please choose a NetworkAttachmentDefinition for default data transfer.", diff --git a/packages/forklift-console-plugin/src/modules/Providers/views/details/tabs/VirtualMachines/OpenShiftVirtualMachinesList.tsx b/packages/forklift-console-plugin/src/modules/Providers/views/details/tabs/VirtualMachines/OpenShiftVirtualMachinesList.tsx index a3fb05daa..0ca795e86 100644 --- a/packages/forklift-console-plugin/src/modules/Providers/views/details/tabs/VirtualMachines/OpenShiftVirtualMachinesList.tsx +++ b/packages/forklift-console-plugin/src/modules/Providers/views/details/tabs/VirtualMachines/OpenShiftVirtualMachinesList.tsx @@ -5,7 +5,7 @@ import { EnumToTuple, ResourceFieldFactory } from '@kubev2v/common'; import { ProviderVirtualMachinesList, VmData } from './components'; import { OpenShiftVirtualMachinesRow } from './OpenShiftVirtualMachinesRow'; import { ProviderVirtualMachinesProps } from './ProviderVirtualMachines'; -import { getVmPowerState } from './utils'; +import { getOpenShiftFeatureMap, getVmPowerState } from './utils'; const openShiftVmFieldsMetadataFactory: ResourceFieldFactory = (t) => [ { @@ -33,6 +33,26 @@ const openShiftVmFieldsMetadataFactory: ResourceFieldFactory = (t) => [ }, sortable: true, }, + { + resourceFieldId: 'features', + jsonPath: (data: VmData) => getOpenShiftFeatureMap(data?.vm), + label: t('Features'), + isVisible: true, + isIdentity: false, + filter: { + type: 'enum', + placeholderLabel: t('Filter by features'), + values: EnumToTuple({ + numa: t('NUMA'), + gpus: t('GPUs'), + hostDevices: t('Host Devices'), + persistentTpm: t('Persistent TPM'), + persistentEfi: t('Persistent EFI'), + dedicatedCpu: t('Dedicated CPU'), + }), + }, + sortable: true, + }, { resourceFieldId: 'template', jsonPath: "$.vm.object.metadata.labels['vm.kubevirt.io/template']", diff --git a/packages/forklift-console-plugin/src/modules/Providers/views/details/tabs/VirtualMachines/components/ProviderVirtualMachinesList.tsx b/packages/forklift-console-plugin/src/modules/Providers/views/details/tabs/VirtualMachines/components/ProviderVirtualMachinesList.tsx index 964041aac..0193991f7 100644 --- a/packages/forklift-console-plugin/src/modules/Providers/views/details/tabs/VirtualMachines/components/ProviderVirtualMachinesList.tsx +++ b/packages/forklift-console-plugin/src/modules/Providers/views/details/tabs/VirtualMachines/components/ProviderVirtualMachinesList.tsx @@ -53,8 +53,9 @@ export const ProviderVirtualMachinesList: React.FC ); }; @@ -64,3 +65,8 @@ const concernsMatcher: ValueMatcher = { matchValue: (concerns: Concern[]) => (filter: string) => Array.isArray(concerns) && concerns.some(({ category }) => category === filter), }; + +const featuresMatcher: ValueMatcher = { + filterType: 'features', + matchValue: (features: { [key: string]: boolean }) => (filter: string) => !!features?.[filter], +}; diff --git a/packages/forklift-console-plugin/src/modules/Providers/views/details/tabs/VirtualMachines/utils/helpers/getOpenShiftFeatureMap.ts b/packages/forklift-console-plugin/src/modules/Providers/views/details/tabs/VirtualMachines/utils/helpers/getOpenShiftFeatureMap.ts new file mode 100644 index 000000000..9a6a59446 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Providers/views/details/tabs/VirtualMachines/utils/helpers/getOpenShiftFeatureMap.ts @@ -0,0 +1,20 @@ +import { ProviderVirtualMachine, V1DomainSpec } from '@kubev2v/types'; + +export const getOpenShiftFeatureMap = (vm: ProviderVirtualMachine) => { + if (vm.providerType !== 'openshift') { + return {}; + } + const domain: V1DomainSpec = vm.object?.spec?.template?.spec?.domain; + if (!domain) { + return {}; + } + + return { + numa: !!domain.cpu?.numa, + gpus: !!domain.devices?.gpus?.length, + hostDevices: !!domain?.devices?.hostDevices?.length, + persistentTpm: domain?.devices?.tpm?.persistent, + persistentEfi: domain?.firmware?.bootloader?.efi?.persistent, + dedicatedCpu: domain?.cpu?.dedicatedCpuPlacement, + }; +}; diff --git a/packages/forklift-console-plugin/src/modules/Providers/views/details/tabs/VirtualMachines/utils/helpers/index.ts b/packages/forklift-console-plugin/src/modules/Providers/views/details/tabs/VirtualMachines/utils/helpers/index.ts index aa2d06682..c97ba37f1 100644 --- a/packages/forklift-console-plugin/src/modules/Providers/views/details/tabs/VirtualMachines/utils/helpers/index.ts +++ b/packages/forklift-console-plugin/src/modules/Providers/views/details/tabs/VirtualMachines/utils/helpers/index.ts @@ -1,4 +1,5 @@ // @index(['./*', /style/g], f => `export * from '${f.path}';`) +export * from './getOpenShiftFeatureMap'; export * from './getVmPowerState'; export * from './vmProps'; // @endindex diff --git a/packages/types/src/types/k8s/V1VirtualMachine.ts b/packages/types/src/types/k8s/V1VirtualMachine.ts index da0544bad..4234a6942 100644 --- a/packages/types/src/types/k8s/V1VirtualMachine.ts +++ b/packages/types/src/types/k8s/V1VirtualMachine.ts @@ -114,7 +114,7 @@ interface V1VirtualMachineInstanceSpec { // Specification of the desired behavior of the VirtualMachineInstance on the host. // Domain DomainSpec `json:"domain"` - domain: DomainSpec; + domain: V1DomainSpec; // NodeSelector is a selector which must be true for the vmi to fit on a node. // Selector which must match a node's labels for the vmi to be scheduled on that node. @@ -235,7 +235,7 @@ interface V1VirtualMachineInstanceSpec { //AccessCredentials []AccessCredential `json:"accessCredentials,omitempty"` } -interface DomainSpec { +export interface V1DomainSpec { // Resources describes the Compute Resources required by this vmi. // Resources ResourceRequirements `json:"resources,omitempty"` resources?: { @@ -251,6 +251,8 @@ interface DomainSpec { cores: number; sockets: number; threads: number; + dedicatedCpuPlacement?: boolean; + numa?: unknown; }; // Memory allow specifying the VMI memory features. @@ -264,6 +266,13 @@ interface DomainSpec { // Firmware. // +optional // Firmware *Firmware `json:"firmware,omitempty"` + firmware?: { + bootloader?: { + efi?: { + persistent?: boolean; + }; + }; + }; // Clock sets the clock and timers of the vmi. // +optional @@ -355,6 +364,7 @@ interface Devices { // +optional // +listType=atomic // GPUs []GPU `json:"gpus,omitempty"` + gpus?: unknown[]; // Filesystems describes filesystem which is connected to the vmi. // +optional @@ -365,4 +375,9 @@ interface Devices { // +optional // +listType=atomic // HostDevices []HostDevice `json:"hostDevices,omitempty"` + hostDevices?: unknown[]; + + tpm?: { + persistent?: boolean; + }; } diff --git a/packages/types/src/types/k8s/index.ts b/packages/types/src/types/k8s/index.ts index 5ccaae0b0..d7939b817 100644 --- a/packages/types/src/types/k8s/index.ts +++ b/packages/types/src/types/k8s/index.ts @@ -5,4 +5,5 @@ export * from './K8sResourceCondition'; export * from './V1Namespace'; export * from './V1NetworkAttachmentDefinition'; export * from './V1Secret'; +export * from './V1VirtualMachine'; // @endindex