diff --git a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/api/db.json b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/api/db.json
index 784ee8302e35..30fed20baeb6 100644
--- a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/api/db.json
+++ b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/api/db.json
@@ -2247,6 +2247,46 @@
"lastBcsId": 0
}
]
+ },
+ {
+ "containerID": 10,
+ "containerState": "REPLICA_MISMATCH",
+ "unhealthySince": 1665590446222,
+ "expectedReplicaCount": 3,
+ "actualReplicaCount": 3,
+ "replicaDeltaCount": 0,
+ "reason": null,
+ "keys": 1,
+ "pipelineID": "a10ffab6-8ed5-414a-aaf5-79890ff3e8a1",
+ "replicas": [
+ {
+ "containerId": 10,
+ "datanodeUuid": "15526f1b-76f2-4d8f-876c-c343c94ea476",
+ "datanodeHost": "ozone_datanode_2.ozone_overreplicated4",
+ "firstSeenTime": 1665588176660,
+ "lastSeenTime": 1665590397315,
+ "lastBcsId": 2,
+ "dataChecksum": 12345678
+ },
+ {
+ "containerId": 10,
+ "datanodeUuid": "f55476ab-4687-464d-a100-1c65de4366e3",
+ "datanodeHost": "ozone_datanode_3.ozone_overreplicated4",
+ "firstSeenTime": 1665588176616,
+ "lastSeenTime": 1665590392293,
+ "lastBcsId": 2,
+ "dataChecksum": 23456789
+ },
+ {
+ "containerId": 10,
+ "datanodeUuid": "7a457bcb-d63e-49cc-b3ff-8b22bf48d130",
+ "datanodeHost": "ozone_datanode_1.ozone_overreplicated4",
+ "firstSeenTime": 1665588176660,
+ "lastSeenTime": 1665590272289,
+ "lastBcsId": 0,
+ "dataChecksum": 12345678
+ }
+ ]
}
]
},
diff --git a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/tables/containersTable.tsx b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/tables/containersTable.tsx
index a68c9928ee97..424d58cf245e 100644
--- a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/tables/containersTable.tsx
+++ b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/tables/containersTable.tsx
@@ -18,10 +18,14 @@
import React, {useRef} from 'react';
import filesize from 'filesize';
-import {AxiosError} from 'axios';
-import {Popover, Table} from 'antd';
-import {ColumnsType, TablePaginationConfig} from 'antd/es/table';
-import {NodeIndexOutlined} from '@ant-design/icons';
+
+import { AxiosError } from 'axios';
+import { Popover, Table } from 'antd';
+import {
+ ColumnsType,
+ TablePaginationConfig
+} from 'antd/es/table';
+import { CheckCircleOutlined, NodeIndexOutlined } from '@ant-design/icons';
import {getFormattedTime} from '@/v2/utils/momentUtils';
import {showDataFetchError} from '@/utils/common';
@@ -37,6 +41,23 @@ import {
const size = filesize.partial({ standard: 'iec' });
+const getDatanodeWith = (idx: number, host: string) => {
+ return (
+
+ {host}
+
+ );
+}
+
+const getDataNodeWithChecksum = (idx: number, host: string, checksum: string) => {
+ return (
+
+ {host}
+ / {checksum}
+
+ )
+}
+
export const COLUMNS: ColumnsType = [
{
title: 'Container ID',
@@ -69,17 +90,26 @@ export const COLUMNS: ColumnsType = [
key: 'replicas',
render: (replicas: ContainerReplica[]) => {
const renderDatanodes = (replicas: ContainerReplica[]) => {
- return replicas?.map((replica: any, idx: number) => (
-
-
{replica.datanodeHost}
+ return (
+
+ {
+ replicas?.map((replica: any, idx: number) => (
+ (replica.dataChecksum)
+ ? getDataNodeWithChecksum(idx, replica.datanodeHost, replica.dataChecksum)
+ : getDatanodeWith(idx, replica.datanodeHost)
+ ))}
- ))
+ )
}
return (
replica.hasOwnProperty('dataChecksum')))
+ ? 'Datanodes / Checksum'
+ : 'Datanodes'
+ }
placement='bottomRight'
trigger='hover'>
{replicas.length} datanodes
diff --git a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/pages/containers/containers.less b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/pages/containers/containers.less
index f6328ccee640..3f4afc5fc079 100644
--- a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/pages/containers/containers.less
+++ b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/pages/containers/containers.less
@@ -45,6 +45,15 @@
}
}
-.datanode-container-v2 {
- padding: 6px 0px;
+.datanode-container-v2-table {
+ display: table;
+
+ .datanode-container-v2-tr {
+ display: table-row-group;
+
+ .datanode-container-v2-td {
+ display: table-cell;
+ padding: 2px 4px;
+ }
+ }
}
\ No newline at end of file
diff --git a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/pages/containers/containers.tsx b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/pages/containers/containers.tsx
index 78f6424c6e7a..5cdbdd52625a 100644
--- a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/pages/containers/containers.tsx
+++ b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/pages/containers/containers.tsx
@@ -64,6 +64,7 @@ const Containers: React.FC<{}> = () => {
underReplicatedContainerData: [],
overReplicatedContainerData: [],
misReplicatedContainerData: [],
+ mismatchedReplicaContainerData: []
});
const [expandedRow, setExpandedRow] = useState({});
@@ -100,6 +101,9 @@ const Containers: React.FC<{}> = () => {
const misReplicatedContainerData: Container[] = containers?.filter(
container => container.containerState === 'MIS_REPLICATED'
) ?? [];
+ const mismatchedReplicaContainerData: Container[] = containers?.filter(
+ container => container.containerState === 'REPLICA_MISMATCH'
+ ) ?? [];
setState({
...state,
@@ -107,6 +111,7 @@ const Containers: React.FC<{}> = () => {
underReplicatedContainerData: underReplicatedContainerData,
overReplicatedContainerData: overReplicatedContainerData,
misReplicatedContainerData: misReplicatedContainerData,
+ mismatchedReplicaContainerData: mismatchedReplicaContainerData,
lastUpdated: Number(moment())
});
setLoading(false)
@@ -135,7 +140,7 @@ const Containers: React.FC<{}> = () => {
const {
lastUpdated, columnOptions,
missingContainerData, underReplicatedContainerData,
- overReplicatedContainerData, misReplicatedContainerData
+ overReplicatedContainerData, misReplicatedContainerData, mismatchedReplicaContainerData
} = state;
// Mapping the data to the Tab keys for enabling/disabling search
@@ -143,7 +148,8 @@ const Containers: React.FC<{}> = () => {
1: missingContainerData,
2: underReplicatedContainerData,
3: overReplicatedContainerData,
- 4: misReplicatedContainerData
+ 4: misReplicatedContainerData,
+ 5: mismatchedReplicaContainerData
}
const highlightData = (
@@ -168,6 +174,10 @@ const Containers: React.FC<{}> = () => {
Mis-Replicated
{misReplicatedContainerData?.length ?? 'N/A'}
+
+ Mismatched Replicas
+ {mismatchedReplicaContainerData?.length ?? 'N/A'}
+
)
@@ -273,6 +283,19 @@ const Containers: React.FC<{}> = () => {
expandedRowSetter={setExpandedRow}
/>
+
+
+
diff --git a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/types/container.types.ts b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/types/container.types.ts
index 2467a0f26fda..85d542ff0c5f 100644
--- a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/types/container.types.ts
+++ b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/types/container.types.ts
@@ -25,6 +25,7 @@ export type ContainerReplica = {
firstSeenTime: number;
lastSeenTime: number;
lastBcsId: number;
+ dataChecksum?: string;
}
export type Container = {
@@ -91,4 +92,5 @@ export type ContainerState = {
underReplicatedContainerData: Container[];
overReplicatedContainerData: Container[];
misReplicatedContainerData: Container[];
+ mismatchedReplicaContainerData: Container[];
}
\ No newline at end of file