From b484d2d5eee1123c3d7b3f19b59e855ce02c6b36 Mon Sep 17 00:00:00 2001 From: yaacov Date: Fri, 7 Jun 2024 12:25:12 +0300 Subject: [PATCH] Add a plan details item to edit boot disk Signed-off-by: yaacov --- .../en/plugin__forklift-console-plugin.json | 11 ++ .../SettingsSection/SettingsSection.tsx | 5 + .../components/RootDiskDetailsItem.tsx | 59 ++++++++ .../SettingsSection/components/index.ts | 1 + .../modals/EditRootDisk/EditRootDisk.tsx | 138 ++++++++++++++++++ .../modals/EditRootDisk/index.ts | 3 + 6 files changed, 217 insertions(+) create mode 100644 packages/forklift-console-plugin/src/modules/Plans/views/details/components/SettingsSection/components/RootDiskDetailsItem.tsx create mode 100644 packages/forklift-console-plugin/src/modules/Plans/views/details/components/SettingsSection/modals/EditRootDisk/EditRootDisk.tsx create mode 100644 packages/forklift-console-plugin/src/modules/Plans/views/details/components/SettingsSection/modals/EditRootDisk/index.ts 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 b7ebdbfaf..d7333c8c2 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 @@ -46,6 +46,11 @@ "Assessment": "Assessment", "Authentication type": "Authentication type", "Bandwidth": "Bandwidth", + "Boot from the fifth disk": "Boot from the fifth disk", + "Boot from the first disk": "Boot from the first disk", + "Boot from the fourth disk": "Boot from the fourth disk", + "Boot from the second disk": "Boot from the second disk", + "Boot from the third disk": "Boot from the third disk", "CA certificate": "CA certificate", "CA certificate - disabled when 'Skip certificate validation' is selected": "CA certificate - disabled when 'Skip certificate validation' is selected", "CA certificate - leave empty to use system CA certificates": "CA certificate - leave empty to use system CA certificates", @@ -112,6 +117,7 @@ "Description": "Description", "Details": "Details", "Determines the frequency with which the system checks the status of snapshot creation or removal during oVirt warm migration. The default value is 10 seconds.": "Determines the frequency with which the system checks the status of snapshot creation or removal during oVirt warm migration. The default value is 10 seconds.", + "Disk {{diskNumber}}": "Disk {{diskNumber}}", "Disk counter": "Disk counter", "Disk transfer": "Disk transfer", "Do not try to preserve the static IPs of VMs with Windows guest operating system from vSphere.": "Do not try to preserve the static IPs of VMs with Windows guest operating system from vSphere.", @@ -138,6 +144,7 @@ "Edit Provider Credentials": "Edit Provider Credentials", "Edit provider credentials.\n Use this link to edit the providers credentials instead of editing the secret directly.": "Edit provider credentials.\n Use this link to edit the providers credentials instead of editing the secret directly.", "Edit provider web UI link": "Edit provider web UI link", + "Edit root disk": "Edit root disk", "Edit Snapshot polling interval (seconds)": "Edit Snapshot polling interval (seconds)", "Edit StorageMap": "Edit StorageMap", "Edit target namespace": "Edit target namespace", @@ -175,6 +182,7 @@ "Filter by template": "Filter by template", "Filter by tenant": "Filter by tenant", "Filter provider": "Filter provider", + "First disk": "First disk", "Flavor": "Flavor", "Folder": "Folder", "GPUs/Host Devices": "GPUs/Host Devices", @@ -375,10 +383,12 @@ "Restore default columns": "Restore default columns", "Return to the providers list page": "Return to the providers list page", "Reveal values": "Reveal values", + "Root disk": "Root disk", "Run the migration plan.": "Run the migration plan.", "Running": "Running", "Running virtual machines": "Running virtual machines", "Save": "Save", + "Second disk": "Second disk", "Secret": "Secret", "Secret failed to load, check if the secret exist.": "Secret failed to load, check if the secret exist.", "Secret is loading, please wait.": "Secret is loading, please wait.", @@ -412,6 +422,7 @@ "Source Only": "Source Only", "Source provider": "Source provider", "Specifies the duration for retaining 'must gather' reports before they are automatically deleted. The default value is -1, which implies automatic cleanup is disabled.": "Specifies the duration for retaining 'must gather' reports before they are automatically deleted. The default value is -1, which implies automatic cleanup is disabled.", + "Specify the root disk for Openshift Virtualization configuration and guest agent setup.": "Specify the root disk for Openshift Virtualization configuration and guest agent setup.", "Specify the type of source provider. Allowed values are ova, ovirt, vsphere,\n openshift, and openstack. This label is needed to verify the credentials are correct when the remote system is accessible and, for RHV, to retrieve the Manager CA certificate when\n a third-party certificate is specified.": "Specify the type of source provider. Allowed values are ova, ovirt, vsphere,\n openshift, and openstack. This label is needed to verify the credentials are correct when the remote system is accessible and, for RHV, to retrieve the Manager CA certificate when\n a third-party certificate is specified.", "Staging": "Staging", "Start": "Start", diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/SettingsSection/SettingsSection.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/SettingsSection/SettingsSection.tsx index b09c62e4e..223553007 100644 --- a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/SettingsSection/SettingsSection.tsx +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/SettingsSection/SettingsSection.tsx @@ -9,6 +9,7 @@ import { DescriptionList } from '@patternfly/react-core'; import { PreserveClusterCpuModelDetailsItem, PreserveStaticIPsDetailsItem, + RootDiskDetailsItem, TargetNamespaceDetailsItem, TransferNetworkDetailsItem, WarmDetailsItem, @@ -70,6 +71,10 @@ export const SettingsSectionInternal: React.FC = ({ obj, p {['vsphere'].includes(sourceProvider?.spec?.type) && ( )} + + {['vsphere'].includes(sourceProvider?.spec?.type) && ( + + )} ); diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/SettingsSection/components/RootDiskDetailsItem.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/SettingsSection/components/RootDiskDetailsItem.tsx new file mode 100644 index 000000000..c53057bea --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/SettingsSection/components/RootDiskDetailsItem.tsx @@ -0,0 +1,59 @@ +import React from 'react'; +import { useModal } from 'src/modules/Providers/modals'; +import { DetailsItem } from 'src/modules/Providers/utils'; +import { useForkliftTranslation } from 'src/utils/i18n'; + +import { Label } from '@patternfly/react-core'; + +import { PlanDetailsItemProps } from '../../DetailsSection'; +import { EditRootDisk } from '../modals/EditRootDisk/EditRootDisk'; + +export const RootDiskDetailsItem: React.FC = ({ + resource, + canPatch, + helpContent, +}) => { + const { t } = useForkliftTranslation(); + const { showModal } = useModal(); + + const defaultHelpContent = t( + `Specify the root disk for Openshift Virtualization configuration and guest agent setup.`, + ); + + const rootDisk = resource?.spec?.vms?.[0].rootDisk || '1'; + + const labelMap = { + '1': ( + + ), + '2': ( + + ), + }; + + const getDiskLabel = (diskNumber: string) => { + if (diskNumber in labelMap) { + return labelMap[diskNumber]; + } + + return ( + + ); + }; + + return ( + showModal())} + /> + ); +}; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/SettingsSection/components/index.ts b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/SettingsSection/components/index.ts index e374504fc..6c2d2579d 100644 --- a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/SettingsSection/components/index.ts +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/SettingsSection/components/index.ts @@ -1,6 +1,7 @@ // @index(['./*', /style/g], f => `export * from '${f.path}';`) export * from './PreserveClusterCpuModelDetailsItem'; export * from './PreserveStaticIPsDetailsItem'; +export * from './RootDiskDetailsItem'; export * from './TargetNamespaceDetailsItem'; export * from './TransferNetworkDetailsItem'; export * from './WarmDetailsItem'; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/SettingsSection/modals/EditRootDisk/EditRootDisk.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/SettingsSection/modals/EditRootDisk/EditRootDisk.tsx new file mode 100644 index 000000000..9b9cd871c --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/SettingsSection/modals/EditRootDisk/EditRootDisk.tsx @@ -0,0 +1,138 @@ +import React from 'react'; +import { useToggle } from 'src/modules/Providers/hooks'; +import { + AlertMessageForModals, + EditModal, + EditModalProps, + ModalInputComponentType, + OnConfirmHookType, +} from 'src/modules/Providers/modals'; +import { useForkliftTranslation } from 'src/utils/i18n'; + +import { Modify, PlanModel, V1beta1Plan } from '@kubev2v/types'; +import { K8sModel, k8sPatch } from '@openshift-console/dynamic-plugin-sdk'; +import { Dropdown, DropdownItem, DropdownToggle } from '@patternfly/react-core'; + +const onConfirm: OnConfirmHookType = async ({ resource, model, newValue }) => { + const plan = resource as V1beta1Plan; + + const resourceValue = plan?.spec?.vms; + const op = resourceValue ? 'replace' : 'add'; + const newVMs = resourceValue.map((vm) => ({ + ...vm, + rootDisk: newValue || undefined, + })); + + const obj = await k8sPatch({ + model: model, + resource: resource, + data: [ + { + op, + path: '/spec/vms', + value: newVMs || undefined, + }, + ], + }); + + return obj; +}; + +interface DropdownRendererProps { + value: string | number; + onChange: (V1beta1PlanSpecTransferNetwork) => void; +} + +const RootDiskInputFactory: () => ModalInputComponentType = () => { + const DropdownRenderer: React.FC = ({ value, onChange }) => { + const { t } = useForkliftTranslation(); + const [isOpen, onToggle] = useToggle(false); + + const diskOptions = [ + { key: '', description: t('Boot from the first disk'), content: 'First disk' }, + { key: '2', description: t('Boot from the second disk'), content: 'Second disk' }, + { key: '3', description: t('Boot from the third disk'), content: 'Third disk' }, + { key: '4', description: t('Boot from the fourth disk'), content: 'Fourth disk' }, + { key: '5', description: t('Boot from the fifth disk'), content: 'Fifth disk' }, + ]; + + const dropdownItems = diskOptions.map((option) => ( + onChange(option.key)} + > + {option.content} + + )); + + return ( + + {diskOptions.find((o) => o.key === value)?.content || 'First disk'} + + } + isOpen={isOpen} + dropdownItems={dropdownItems} + menuAppendTo="parent" + /> + ); + }; + + return DropdownRenderer; +}; + +export const EditRootDisk: React.FC = (props) => { + const { t } = useForkliftTranslation(); + + const plan = props.resource; + const rootDisk = plan.spec.vms?.[0]?.rootDisk; + const allVMsHasMatchingRootDisk = plan.spec.vms.every((vm) => vm?.rootDisk === rootDisk); + + return ( + obj?.spec?.vms?.[0]?.rootDisk} + title={props?.title || t('Edit root disk')} + label={props?.label || t('Root disk')} + model={PlanModel} + onConfirmHook={onConfirm} + body={ + <> + {t( + `Specify the root disk for Openshift Virtualization configuration and guest agent setup.`, + )} + {!allVMsHasMatchingRootDisk && ( + +

+ Warning: not all virtual machines are configures using the same root disk + number, +

+

updating the root disk number will override the current configuration.

+ + } + /> + )} + + } + InputComponent={RootDiskInputFactory()} + /> + ); +}; + +export type EditRootDiskProps = Modify< + EditModalProps, + { + resource: V1beta1Plan; + title?: string; + label?: string; + model?: K8sModel; + jsonPath?: string | string[]; + } +>; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/SettingsSection/modals/EditRootDisk/index.ts b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/SettingsSection/modals/EditRootDisk/index.ts new file mode 100644 index 000000000..7f2a823f1 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/SettingsSection/modals/EditRootDisk/index.ts @@ -0,0 +1,3 @@ +// @index(['./*', /style/g], f => `export * from '${f.path}';`) +export * from './EditRootDisk'; +// @endindex