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 20724f67e..d68e4637a 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 @@ -59,6 +59,7 @@ "Close": "Close", "Cluster": "Cluster", "Clusters": "Clusters", + "Completed at": "Completed at", "Concern": "Concern", "Concerns": "Concerns", "Conditions": "Conditions", @@ -203,6 +204,7 @@ "Metrics": "Metrics", "Migrate": "Migrate", "Migrate without validating a CA certificate": "Migrate without validating a CA certificate", + "Migration": "Migration", "Migration networks maps are used to map network interfaces between source and target workloads.": "Migration networks maps are used to map network interfaces between source and target workloads.", "Migration plans are used to plan migration or virtualization workloads from source providers to target providers.": "Migration plans are used to plan migration or virtualization workloads from source providers to target providers.", "Migration started": "Migration started", @@ -212,6 +214,7 @@ "Migrations (last 31 days)": "Migrations (last 31 days)", "Migrations (last 7 days)": "Migrations (last 7 days)", "Migrations for virtualization": "Migrations for virtualization", + "Migrations not found": "Migrations not found", "MTU": "MTU", "Multiple NICs mapped to Pod Networking ": "Multiple NICs mapped to Pod Networking ", "Multiple NICs on the same network": "Multiple NICs on the same network", @@ -303,6 +306,7 @@ "Pod": "Pod", "Pod network": "Pod network", "Pods": "Pods", + "Pods not found": "Pods not found", "Power state": "Power state", "Powered off": "Powered off", "Powered on": "Powered on", @@ -370,6 +374,7 @@ "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 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", + "Started at": "Started at", "Status": "Status", "Storage": "Storage", "Storage classes": "Storage classes", diff --git a/packages/forklift-console-plugin/src/modules/Overview/views/overview/components/PodsTable.tsx b/packages/forklift-console-plugin/src/modules/Overview/views/overview/components/PodsTable.tsx index 785e0524a..1df33c90b 100644 --- a/packages/forklift-console-plugin/src/modules/Overview/views/overview/components/PodsTable.tsx +++ b/packages/forklift-console-plugin/src/modules/Overview/views/overview/components/PodsTable.tsx @@ -4,26 +4,19 @@ import { useForkliftTranslation } from 'src/utils/i18n'; import { IoK8sApiCoreV1Pod } from '@kubev2v/types'; import { ResourceLink, Timestamp } from '@openshift-console/dynamic-plugin-sdk'; -import { Split, SplitItem } from '@patternfly/react-core'; +import { HelperText, HelperTextItem, Split, SplitItem } from '@patternfly/react-core'; import { TableComposable, Tbody, Td, Th, Thead, Tr } from '@patternfly/react-table'; export const PodsTable: React.FC = ({ pods, showOwner }) => { const { t } = useForkliftTranslation(); if (!pods) { - return <>; - } - - const getStatusLabel = (phase: string) => { return ( - - - - - {phase} - + + {t('Pods not found')} + ); - }; + } return ( @@ -69,6 +62,17 @@ export const PodsTable: React.FC = ({ pods, showOwner }) => { ); }; +const getStatusLabel = (phase: string) => { + return ( + + + + + {phase} + + ); +}; + export type PodsTableProps = { pods: IoK8sApiCoreV1Pod[]; showOwner?: boolean; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/PlanDetailsPage.style.css b/packages/forklift-console-plugin/src/modules/Plans/views/details/PlanDetailsPage.style.css index 2fef000bd..56552e9a2 100644 --- a/packages/forklift-console-plugin/src/modules/Plans/views/details/PlanDetailsPage.style.css +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/PlanDetailsPage.style.css @@ -49,4 +49,8 @@ .forklift-network-map__details-tab--update-button { margin-bottom: var(--pf-global--spacer--md); -} \ No newline at end of file +} + +.forklift-overview__controller-card__status-icon { + padding-right: var(--pf-global--spacer--sm); +} diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/MigrationsSection/MigrationsSection.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/MigrationsSection/MigrationsSection.tsx new file mode 100644 index 000000000..48784321d --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/MigrationsSection/MigrationsSection.tsx @@ -0,0 +1,31 @@ +import React from 'react'; + +import { MigrationModelGroupVersionKind, V1beta1Migration, V1beta1Plan } from '@kubev2v/types'; +import { useK8sWatchResource } from '@openshift-console/dynamic-plugin-sdk'; + +import { Suspend } from '../Suspend'; + +import { MigrationsTable } from './components'; + +export const MigrationsSection: React.FC = ({ obj }) => { + const [migrations, loaded, loadError] = useK8sWatchResource({ + groupVersionKind: MigrationModelGroupVersionKind, + namespaced: true, + isList: true, + namespace: obj?.metadata?.namespace, + }); + + const ownedMigrations = migrations.filter( + (m) => m?.metadata?.ownerReferences?.[0]?.uid === obj.metadata.uid, + ); + + return ( + + + + ); +}; + +export type MigrationsSectionProps = { + obj: V1beta1Plan; +}; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/MigrationsSection/components/MigrationsTable.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/MigrationsSection/components/MigrationsTable.tsx new file mode 100644 index 000000000..fcf6449e3 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/MigrationsSection/components/MigrationsTable.tsx @@ -0,0 +1,102 @@ +import React from 'react'; +import StatusIcon from 'src/components/status/StatusIcon'; +import { useForkliftTranslation } from 'src/utils/i18n'; + +import { + MigrationModelGroupVersionKind, + PlanModelGroupVersionKind, + V1beta1Migration, + V1beta1MigrationStatusConditions, +} from '@kubev2v/types'; +import { ResourceLink, Timestamp } from '@openshift-console/dynamic-plugin-sdk'; +import { HelperText, HelperTextItem, Split, SplitItem } from '@patternfly/react-core'; +import { TableComposable, Tbody, Td, Th, Thead, Tr } from '@patternfly/react-table'; + +export const MigrationsTable: React.FC = ({ migrations, showOwner }) => { + const { t } = useForkliftTranslation(); + + if (!migrations || migrations.length < 1) { + return ( + + {t('Migrations not found')} + + ); + } + + return ( + + + + {t('Migration')} + {showOwner && {t('Owner')}} + {t('Status')} + {t('VMs')} + {t('Started at')} + {t('Completed at')} + + + + {migrations.map((migration) => ( + + + + + {showOwner && ( + + {migration?.metadata?.ownerReferences?.[0] ? ( + + ) : ( + '' + )} + + )} + {getStatusLabel(migration?.status?.conditions)} + {migration?.status?.vms?.length || '-'} + + + + + + + + ))} + + + ); +}; + +const getStatusLabel = (conditions: V1beta1MigrationStatusConditions[]) => { + let phase: string; + + const phases = ['Ready', 'Running', 'Succeeded', 'Failed']; + + // Look for a condition indicating a migration phase + phases.forEach((p) => { + const condition = conditions.find((c) => c.type === p && c.status === 'True'); + if (condition) { + phase = p; + } + }); + + return ( + + + + + {phase} + + ); +}; + +export type MigrationTableProps = { + migrations: V1beta1Migration[]; + showOwner?: boolean; +}; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/MigrationsSection/components/index.ts b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/MigrationsSection/components/index.ts new file mode 100644 index 000000000..d3dab1565 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/MigrationsSection/components/index.ts @@ -0,0 +1,3 @@ +// @index(['./*', /style/g], f => `export * from '${f.path}';`) +export * from './MigrationsTable'; +// @endindex diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/MigrationsSection/index.ts b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/MigrationsSection/index.ts new file mode 100644 index 000000000..9f0c3a34a --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/MigrationsSection/index.ts @@ -0,0 +1,4 @@ +// @index(['./*', /style/g], f => `export * from '${f.path}';`) +export * from './components'; +export * from './MigrationsSection'; +// @endindex diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/index.ts b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/index.ts index 460e0dc5e..3d17da02d 100644 --- a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/index.ts +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/index.ts @@ -2,6 +2,7 @@ export * from './ConditionsSection'; export * from './DetailsSection'; export * from './Loading'; +export * from './MigrationsSection'; export * from './ProvidersSection'; export * from './Suspend'; // @endindex diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/Details/PlanDetails.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/Details/PlanDetails.tsx index eea50c982..ed337c6b2 100644 --- a/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/Details/PlanDetails.tsx +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/Details/PlanDetails.tsx @@ -4,7 +4,13 @@ import { useForkliftTranslation } from 'src/utils/i18n'; import { PageSection } from '@patternfly/react-core'; -import { ConditionsSection, DetailsSection, ProvidersSection, Suspend } from '../../components'; +import { + ConditionsSection, + DetailsSection, + MigrationsSection, + ProvidersSection, + Suspend, +} from '../../components'; import { PlanDetailsTabProps } from '../../PlanDetailsPage'; export const PlanDetails: React.FC = ({ plan, loaded, loadError }) => { @@ -22,6 +28,11 @@ export const PlanDetails: React.FC = ({ plan, loaded, loadE + + + + +