From 2c685d4b5cca6830fe134733befe93387befce73 Mon Sep 17 00:00:00 2001 From: Radoslaw Szwajkowski Date: Wed, 27 Sep 2023 20:55:32 +0200 Subject: [PATCH] Add template column for OpenShift VMs Signed-off-by: Radoslaw Szwajkowski --- .../en/plugin__forklift-console-plugin.json | 1 + .../OpenShiftVirtualMachinesList.tsx | 14 + .../OpenShiftVirtualMachinesRow.tsx | 7 + .../mocks/src/definitions/basic/vms.mock.ts | 134 +++++++- .../types/src/types/k8s/V1VirtualMachine.ts | 294 +++++++++++++++++- 5 files changed, 448 insertions(+), 2 deletions(-) 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 3c94c8e42..68d60dd63 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 @@ -130,6 +130,7 @@ "Filter by path": "Filter by path", "Filter by power state": "Filter by power state", "Filter by status": "Filter by status", + "Filter by template": "Filter by template", "Filter by tenant": "Filter by tenant", "Flavor": "Flavor", "From": "From", 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 aafc1880f..8a4a5c8e9 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 @@ -1,6 +1,7 @@ import React from 'react'; import { EnumToTuple, ResourceFieldFactory } from '@kubev2v/common'; +import { OpenshiftVM } from '@kubev2v/types'; import { ProviderVirtualMachinesList } from './components/ProviderVirtualMachinesList'; import { VmData } from './components'; @@ -34,6 +35,19 @@ const openShiftVmFieldsMetadataFactory: ResourceFieldFactory = (t) => [ }, sortable: true, }, + { + resourceFieldId: 'template', + jsonPath: (data: VmData) => + (data?.vm as OpenshiftVM)?.object?.metadata?.labels?.['vm.kubevirt.io/template'] ?? '', + label: t('Template'), + isVisible: true, + isIdentity: false, + filter: { + type: 'freetext', + placeholderLabel: t('Filter by template'), + }, + sortable: true, + }, ]; export const OpenShiftVirtualMachinesList: React.FC = ({ diff --git a/packages/forklift-console-plugin/src/modules/Providers/views/details/tabs/VirtualMachines/OpenShiftVirtualMachinesRow.tsx b/packages/forklift-console-plugin/src/modules/Providers/views/details/tabs/VirtualMachines/OpenShiftVirtualMachinesRow.tsx index 0af8c2932..c7927a1fd 100644 --- a/packages/forklift-console-plugin/src/modules/Providers/views/details/tabs/VirtualMachines/OpenShiftVirtualMachinesRow.tsx +++ b/packages/forklift-console-plugin/src/modules/Providers/views/details/tabs/VirtualMachines/OpenShiftVirtualMachinesRow.tsx @@ -1,6 +1,8 @@ import React from 'react'; +import { TableCell } from 'src/modules/Providers/utils'; import { ResourceField, RowProps } from '@kubev2v/common'; +import { OpenshiftVM } from '@kubev2v/types'; import { Td, Tr } from '@patternfly/react-table'; import { PowerStateCellRenderer } from './components/PowerStateCellRenderer'; @@ -9,6 +11,11 @@ import { VMCellProps, VmData, VMNameCellRenderer } from './components'; const cellRenderers: Record> = { name: VMNameCellRenderer, status: PowerStateCellRenderer, + template: ({ data }) => ( + + {(data?.vm as OpenshiftVM)?.object?.metadata?.labels?.['vm.kubevirt.io/template'] ?? ''} + + ), }; const renderTd = ({ resourceData, resourceFieldId, resourceFields }: RenderTdProps) => { diff --git a/packages/mocks/src/definitions/basic/vms.mock.ts b/packages/mocks/src/definitions/basic/vms.mock.ts index 81c91e856..4e56f291e 100644 --- a/packages/mocks/src/definitions/basic/vms.mock.ts +++ b/packages/mocks/src/definitions/basic/vms.mock.ts @@ -1,9 +1,14 @@ /* eslint-disable @cspell/spellchecker */ -import { OVirtVM, VSphereVM } from '@kubev2v/types'; +import { OpenshiftVM, OVirtVM, VSphereVM } from '@kubev2v/types'; import { MOCK_DISK_ATTACHMENTS } from './disks.mock'; import { MOCK_NICS } from './nicProfiles.mock'; import { + OPENSHIFT_01_UID, + OPENSHIFT_02_UID, + OPENSHIFT_03_UID, + OPENSHIFT_HOST_UID, + OpenshiftProviderIDs, OVIRT_01_UID, OVIRT_02_UID, OVIRT_03_UID, @@ -362,3 +367,130 @@ export const MOCK_RHV_VMS: { [uid in OvirtProviderIDs]: OVirtVM[] } = { }, ], }; + +export const MOCK_OPENSHIFT_VMS: { [uid in OpenshiftProviderIDs]: OpenshiftVM[] } = { + [OPENSHIFT_01_UID]: [], + [OPENSHIFT_02_UID]: [], + [OPENSHIFT_03_UID]: [], + [OPENSHIFT_HOST_UID]: [ + // source: https://kubevirt.io/user-guide/virtual_machines/templates/ + { + name: '', + namespace: '', + selfLink: '', + uid: '', + version: '', + object: { + kind: 'VirtualMachine', + apiVersion: 'kubevirt.io/v1', + metadata: { + annotations: { + ['vm.kubevirt.io/flavor']: 'tiny', + ['vm.kubevirt.io/os']: 'rhel8', + ['vm.kubevirt.io/validations']: ` + { + name: 'minimal-required-memory', + path: 'jsonpath::.spec.domain.resources.requests.memory', + rule: 'integer', + message: 'This VM requires more memory.', + min: 1610612736, + }`, + ['vm.kubevirt.io/workload']: 'server', + }, + labels: { + app: 'rheltinyvm', + ['vm.kubevirt.io/template']: 'rhel8-server-tiny', + ['vm.kubevirt.io/template.revision']: '45', + ['vm.kubevirt.io/template.version']: '0.11.3', + }, + name: 'rheltinyvm', + }, + spec: { + dataVolumeTemplates: [ + { + apiVersion: 'cdi.kubevirt.io/v1beta1', + kind: 'DataVolume', + metadata: { + name: 'rheltinyvm', + }, + spec: { + pvc: { + accessModes: ['ReadWriteMany'], + resources: { + requests: { + storage: '30Gi', + }, + }, + }, + source: { + pvc: { + name: 'rhel', + namespace: 'kubevirt', + }, + }, + }, + }, + ], + running: false, + template: { + metadata: { + labels: { + ['kubevirt.io/domain']: 'rheltinyvm', + ['kubevirt.io/size']: 'tiny', + }, + }, + spec: { + domain: { + cpu: { + cores: 1, + sockets: 1, + threads: 1, + }, + devices: { + disks: [ + { + disk: { + bus: 'virtio', + }, + name: 'rheltinyvm', + }, + { + disk: { + bus: 'virtio', + }, + name: 'cloudinitdisk', + }, + ], + interfaces: [ + { + masquerade: {}, + name: 'default', + }, + ], + networkInterfaceMultiqueue: true, + rng: {}, + }, + resources: { + requests: { + memory: '1.5Gi', + }, + }, + }, + networks: [{ name: 'default', pod: {} }], + terminationGracePeriodSeconds: 180, + volumes: [ + { + dataVolume: { + name: 'rheltinyvm', + }, + name: 'rheltinyvm', + }, + ], + }, + }, + }, + }, + providerType: 'openshift', + }, + ], +}; diff --git a/packages/types/src/types/k8s/V1VirtualMachine.ts b/packages/types/src/types/k8s/V1VirtualMachine.ts index 712fb20c8..da0544bad 100644 --- a/packages/types/src/types/k8s/V1VirtualMachine.ts +++ b/packages/types/src/types/k8s/V1VirtualMachine.ts @@ -18,10 +18,32 @@ export interface V1VirtualMachine { // Template is the direct specification of VirtualMachineInstance // Template *VirtualMachineInstanceTemplateSpec `json:"template"` + template: V1VirtualMachineInstanceTemplateSpec; // dataVolumeTemplates is a list of dataVolumes that the VirtualMachineInstance template can reference. // DataVolumes in this list are dynamically created for the VirtualMachine and are tied to the VirtualMachine's life-cycle. // DataVolumeTemplates []DataVolumeTemplateSpec `json:"dataVolumeTemplates,omitempty"` + dataVolumeTemplates: { + apiVersion: 'cdi.kubevirt.io/v1beta1'; + kind: 'DataVolume'; + metadata: IoK8sApimachineryPkgApisMetaV1ObjectMeta; + spec: { + pvc: { + accessModes: string[]; + resources: { + requests: { + storage: string; + }; + }; + }; + source: { + pvc: { + name: string; + namespace: string; + }; + }; + }; + }[]; }; status?: { // SnapshotInProgress is the name of the VirtualMachineSnapshot currently executing @@ -51,7 +73,7 @@ export interface V1VirtualMachine { }; } -type VirtualMachinePrintableStatus = +export type VirtualMachinePrintableStatus = // VirtualMachineStatusStopped indicates that the virtual machine is currently stopped and isn't expected to start. | 'Stopped' // VirtualMachineStatusProvisioning indicates that cluster resources associated with the virtual machine @@ -74,3 +96,273 @@ type VirtualMachinePrintableStatus = // VirtualMachineStatusUnknown indicates that the state of the virtual machine could not be obtained, // typically due to an error in communicating with the host on which it's running. | 'Unknown'; + +export interface V1VirtualMachineInstanceTemplateSpec { + // ObjectMeta metav1.ObjectMeta `json:"metadata,omitempty"` + metadata: IoK8sApimachineryPkgApisMetaV1ObjectMeta; + // VirtualMachineInstance Spec contains the VirtualMachineInstance specification. + // Spec VirtualMachineInstanceSpec `json:"spec,omitempty" valid:"required"` + spec: V1VirtualMachineInstanceSpec; +} + +interface V1VirtualMachineInstanceSpec { + // If specified, indicates the pod's priority. + // If not specified, the pod priority will be default or zero if there is no + // default. + // +optional + // PriorityClassName string `json:"priorityClassName,omitempty"` + + // Specification of the desired behavior of the VirtualMachineInstance on the host. + // Domain DomainSpec `json:"domain"` + domain: DomainSpec; + + // 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. + // More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + // +optional + // NodeSelector map[string]string `json:"nodeSelector,omitempty"` + + // If affinity is specifies, obey all the affinity rules + // Affinity *k8sv1.Affinity `json:"affinity,omitempty"` + + // If specified, the VMI will be dispatched by specified scheduler. + // If not specified, the VMI will be dispatched by default scheduler. + // +optional + // SchedulerName string `json:"schedulerName,omitempty"` + + // If toleration is specified, obey all the toleration rules. + // Tolerations []k8sv1.Toleration `json:"tolerations,omitempty"` + + // EvictionStrategy can be set to "LiveMigrate" if the VirtualMachineInstance should be + // migrated instead of shut-off in case of a node drain. + // + // +optional + // EvictionStrategy *EvictionStrategy `json:"evictionStrategy,omitempty"` + + // StartStrategy can be set to "Paused" if Virtual Machine should be started in paused state. + // + // +optional + // StartStrategy *StartStrategy `json:"startStrategy,omitempty"` + + // Grace period observed after signalling a VirtualMachineInstance to stop after which the VirtualMachineInstance is force terminated. + //TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty"` + terminationGracePeriodSeconds?: number; + + // List of volumes that can be mounted by disks belonging to the vmi. + // Volumes []Volume `json:"volumes,omitempty"` + volumes: { + // Volume represents a named volume in a vmi. + + // Volume's name. + // Must be a DNS_LABEL and unique within the vmi. + // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + // Name string `json:"name"` + name: string; + // VolumeSource represents the location and type of the mounted volume. + // Defaults to Disk, if no type is specified. + // VolumeSource `json:",inline"` + + // DataVolume represents the dynamic creation a PVC for this volume as well as + // the process of populating that PVC with a disk image. + // +optional + // DataVolume *DataVolumeSource `json:"dataVolume,omitempty"` + dataVolume: { + // Name represents the name of the DataVolume in the same namespace + // Name string `json:"name"` + name: string; + }; + }[]; + + // Periodic probe of VirtualMachineInstance liveness. + // VirtualmachineInstances will be stopped if the probe fails. + // Cannot be updated. + // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + // +optional + // LivenessProbe *Probe `json:"livenessProbe,omitempty"` + + // Periodic probe of VirtualMachineInstance service readiness. + // VirtualmachineInstances will be removed from service endpoints if the probe fails. + // Cannot be updated. + // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + // +optional + // ReadinessProbe *Probe `json:"readinessProbe,omitempty"` + + // Specifies the hostname of the vmi + // If not specified, the hostname will be set to the name of the vmi, if dhcp or cloud-init is configured properly. + // +optional + // Hostname string `json:"hostname,omitempty"` + + // If specified, the fully qualified vmi hostname will be "...svc.". + // If not specified, the vmi will not have a domainname at all. The DNS entry will resolve to the vmi, + // no matter if the vmi itself can pick up a hostname. + // +optional + // Subdomain string `json:"subdomain,omitempty"` + + // List of networks that can be attached to a vm's virtual interface. + // Networks []Network `json:"networks,omitempty"` + networks: { + // Network represents a network type and a resource that should be connected to the vm. + // Network name. + // Must be a DNS_LABEL and unique within the vm. + // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + // Name string `json:"name"` + name: string; + // NetworkSource represents the network type and the source interface that should be connected to the virtual machine. + // Defaults to Pod, if no type is specified. + // NetworkSource `json:",inline"` + pod?: object; + multus?: object; + }[]; + + // Set DNS policy for the pod. + // Defaults to "ClusterFirst". + // Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. + // DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. + // To have DNS options set along with hostNetwork, you have to specify DNS policy + // explicitly to 'ClusterFirstWithHostNet'. + // +optional + // DNSPolicy k8sv1.DNSPolicy `json:"dnsPolicy,omitempty" protobuf:"bytes,6,opt,name=dnsPolicy,casttype=DNSPolicy"` + + // Specifies the DNS parameters of a pod. + // Parameters specified here will be merged to the generated DNS + // configuration based on DNSPolicy. + // +optional + // DNSConfig *k8sv1.PodDNSConfig `json:"dnsConfig,omitempty" protobuf:"bytes,26,opt,name=dnsConfig"` + + // Specifies a set of public keys to inject into the vm guest + // +listType=atomic + // +optional + //AccessCredentials []AccessCredential `json:"accessCredentials,omitempty"` +} + +interface DomainSpec { + // Resources describes the Compute Resources required by this vmi. + // Resources ResourceRequirements `json:"resources,omitempty"` + resources?: { + requests?: { + memory: string; + }; + }; + + // CPU allow specified the detailed CPU topology inside the vmi. + // +optional + // CPU *CPU `json:"cpu,omitempty"` + cpu?: { + cores: number; + sockets: number; + threads: number; + }; + + // Memory allow specifying the VMI memory features. + // +optional + // Memory *Memory `json:"memory,omitempty"` + + // Machine type. + // +optional + // Machine *Machine `json:"machine,omitempty"` + + // Firmware. + // +optional + // Firmware *Firmware `json:"firmware,omitempty"` + + // Clock sets the clock and timers of the vmi. + // +optional + // Clock *Clock `json:"clock,omitempty"` + + // Features like acpi, apic, hyperv, smm. + // +optional + // Features *Features `json:"features,omitempty"` + + // Devices allows adding disks, network interfaces, and others + // Devices Devices `json:"devices"` + devices: Devices; + + // Controls whether or not disks will share IOThreads. + // Omitting IOThreadsPolicy disables use of IOThreads. + // One of: shared, auto + // +optional + // IOThreadsPolicy *IOThreadsPolicy `json:"ioThreadsPolicy,omitempty"` + + // Chassis specifies the chassis info passed to the domain. + // +optional + // Chassis *Chassis `json:"chassis,omitempty"` +} + +interface Devices { + // Fall back to legacy virtio 0.9 support if virtio bus is selected on devices. + // This is helpful for old machines like CentOS6 or RHEL6 which + // do not understand virtio_non_transitional (virtio 1.0). + // UseVirtioTransitional *bool `json:"useVirtioTransitional,omitempty"` + + // DisableHotplug disabled the ability to hotplug disks. + // DisableHotplug bool `json:"disableHotplug,omitempty"` + + // Disks describes disks, cdroms, floppy and luns which are connected to the vmi. + // Disks []Disk `json:"disks,omitempty"` + disks: { + disk?: { + bus?: string; + }; + name: string; + }[]; + + // Watchdog describes a watchdog device which can be added to the vmi. + // Watchdog *Watchdog `json:"watchdog,omitempty"` + + // Interfaces describe network interfaces which are added to the vmi. + // Interfaces []Interface `json:"interfaces,omitempty"` + interfaces: { + name: string; + masquerade?: object; + }[]; + + // Inputs describe input devices + // Inputs []Input `json:"inputs,omitempty"` + + // Whether to attach a pod network interface. Defaults to true. + // AutoattachPodInterface *bool `json:"autoattachPodInterface,omitempty"` + + // Whether to attach the default graphics device or not. + // VNC will not be available if set to false. Defaults to true. + // AutoattachGraphicsDevice *bool `json:"autoattachGraphicsDevice,omitempty"` + + // Whether to attach the default serial console or not. + // Serial console access will not be available if set to false. Defaults to true. + // AutoattachSerialConsole *bool `json:"autoattachSerialConsole,omitempty"` + + // Whether to attach the Memory balloon device with default period. + // Period can be adjusted in virt-config. + // Defaults to true. + // +optional + // AutoattachMemBalloon *bool `json:"autoattachMemBalloon,omitempty"` + + // Whether to have random number generator from host + // +optional + // Rng *Rng `json:"rng,omitempty"` + rng?: object; + + // Whether or not to enable virtio multi-queue for block devices. + // Defaults to false. + // +optional + // BlockMultiQueue *bool `json:"blockMultiQueue,omitempty"` + + // If specified, virtual network interfaces configured with a virtio bus will also enable the vhost multiqueue feature for network devices. The number of queues created depends on additional factors of the VirtualMachineInstance, like the number of guest CPUs. + // +optional + // NetworkInterfaceMultiQueue *bool `json:"networkInterfaceMultiqueue,omitempty"` + networkInterfaceMultiqueue?: boolean; + + //Whether to attach a GPU device to the vmi. + // +optional + // +listType=atomic + // GPUs []GPU `json:"gpus,omitempty"` + + // Filesystems describes filesystem which is connected to the vmi. + // +optional + // +listType=atomic + // Filesystems []Filesystem `json:"filesystems,omitempty"` + + //Whether to attach a host device to the vmi. + // +optional + // +listType=atomic + // HostDevices []HostDevice `json:"hostDevices,omitempty"` +}