This is an automated email from the ASF dual-hosted git repository.

arshad pushed a commit to branch frontend-refactor
in repository https://gitbox.apache.org/repos/asf/ambari.git


The following commit(s) were added to refs/heads/frontend-refactor by this push:
     new d808da2cc3 AMBARI-26376 : Ambari Web React: Check host component 
(#4057)
d808da2cc3 is described below

commit d808da2cc30de048503347a3e4e5c0a8feeb6c84
Author: Himanshu Maurya <[email protected]>
AuthorDate: Tue Sep 9 11:50:05 2025 +0530

    AMBARI-26376 : Ambari Web React: Check host component (#4057)
---
 ambari-web/latest/src/hooks/useHostChecks.tsx      | 1098 ++++++++++++++++++++
 ambari-web/latest/src/screens/Hosts/HostChecks.tsx |  530 ++++++++++
 ambari-web/latest/src/screens/Hosts/constants.ts   |  445 ++++++++
 ambari-web/latest/src/screens/Hosts/helpers.ts     |  109 ++
 4 files changed, 2182 insertions(+)

diff --git a/ambari-web/latest/src/hooks/useHostChecks.tsx 
b/ambari-web/latest/src/hooks/useHostChecks.tsx
new file mode 100644
index 0000000000..e1a15a1422
--- /dev/null
+++ b/ambari-web/latest/src/hooks/useHostChecks.tsx
@@ -0,0 +1,1098 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { useContext, useEffect, useRef, useState } from "react";
+import {
+  finishStates,
+  minDiskSpace,
+  minDiskSpaceUsrLib,
+} from "../screens/Hosts/constants";
+import { HostsApi } from "../api/hostsApi";
+import usePolling from "./usePolling";
+import { cloneDeep, get, isEmpty, map, set } from "lodash";
+import { AppContext } from "../store/context";
+import { sortPropertyLight } from "../screens/Hosts/helpers";
+
+enum BootStatus {
+  PENDING = "PENDING",
+  DONE = "DONE",
+  REGISTERING = "REGISTERING",
+  REGISTERED = "REGISTERED",
+  FAILED = "FAILED",
+  RUNNING = "RUNNING",
+}
+
+type BootHostType = {
+  name: string;
+};
+
+export const initialWarningData: any = {
+  allWarnings: [],
+  repoCategoryWarnings: [],
+  diskCategoryWarnings: [],
+  thpCategoryWarnings: [],
+  hostCheckWarnings: [],
+  warningsByHost: [],
+  jdkCategoryWarnings: [],
+};
+
+export const useHostChecks = (
+  isAddHostWizard = false,
+  isClusterInstallationWizard = false
+) => {
+  const { clusterName, ambariProperties } = useContext(AppContext);
+
+  const [requestID, setRequestID] = useState(-1);
+  const [warningData, setWarningData] = useState<any>(initialWarningData);
+  const [componentInfo, setComponentInfo] = useState({});
+  const [isHostCheckRunning, setIsHostCheckRunning] = useState(false);
+
+  const hostsPackagesData = useRef([]);
+  const hostCheckResult = useRef(null);
+  const skipBootstrap = useRef(false);
+  const hostPackagesData = useRef([]);
+  const bootHosts = useRef<BootHostType[]>([]);
+  const dataForHostCheck = useRef({});
+
+  const getHostCheckTasks = async () => {
+    const response = await HostsApi.getRequestStatus(
+      requestID,
+      
"Requests/inputs,Requests/request_status,tasks/Tasks/host_name,tasks/Tasks/structured_out/host_resolution_check/hosts_with_failures,tasks/Tasks/structured_out/host_resolution_check/failed_count,tasks/Tasks/structured_out/installed_packages,tasks/Tasks/structured_out/last_agent_env_check,tasks/Tasks/structured_out/transparentHugePage,tasks/Tasks/stdout,tasks/Tasks/stderr,tasks/Tasks/error_log,tasks/Tasks/command_detail,tasks/Tasks/status&minimal_response=true"
+    );
+    getHostCheckTasksSuccess(response);
+  };
+
+  const { pausePolling, resumePolling } = usePolling(getHostCheckTasks, 1000);
+
+  useEffect(() => {
+    pausePolling();
+    if (!isClusterInstallationWizard) {
+      getClusterComponents();
+    }
+  }, []);
+
+  useEffect(() => {
+    if (requestID !== -1) {
+      resumePolling();
+    }
+  }, [requestID]);
+
+  const getClusterComponents = async () => {
+    const response = await HostsApi.getClusterComponents(
+      clusterName,
+      "ServiceComponentInfo/component_name,host_components/HostRoles/host_name"
+    );
+    setComponentInfo(response);
+  };
+
+  const getMasterComponentHosts = () => {
+    const components = get(componentInfo, "items", []);
+    return components
+      .map((component: any) => {
+        return get(component, "host_components", []).map(
+          (hostComponent: any) => {
+            return get(hostComponent, "HostRoles.host_name", "");
+          }
+        );
+      })
+      .flat();
+  };
+
+  const cleanup = () => {
+    setWarningData(initialWarningData);
+  };
+
+  const stopHostCheck = () => {
+    setIsHostCheckRunning(false);
+    pausePolling();
+    cleanup();
+  };
+
+  const requestToPerformHostCheck = async () => {
+    if (!isEmpty(dataForHostCheck.current)) {
+      const data = {
+        RequestInfo: get(dataForHostCheck.current, "RequestInfo", {}),
+        "Requests/resource_filters": [
+          get(dataForHostCheck.current, "resource_filters", {}),
+        ],
+      };
+      const response = await HostsApi.makeRequest(data);
+      setRequestID(get(response, "Requests.id", -1));
+    }
+  };
+
+  const getDataForCheckRequest = (
+    checkExecuteList: string,
+    addHostsParameter: boolean
+  ) => {
+    const newHosts = bootHosts.current
+      .filter((host) => get(host, "bootStatus") === BootStatus.REGISTERED)
+      .map((host) => get(host, "name"));
+    const hosts = isAddHostWizard
+      ? [...new Set([...getMasterComponentHosts(), ...newHosts])]
+      : newHosts;
+    const hostsString = hosts.join(",");
+    if (hostsString.length === 0) return null;
+    const jdkLocation = get(
+      ambariProperties,
+      "RootServiceComponents.properties.jdk_location",
+      ""
+    );
+    const RequestInfo = {
+      action: "check_host",
+      context: "Check host",
+      parameters: {
+        check_execute_list: checkExecuteList,
+        jdk_location: jdkLocation,
+        threshold: "20",
+      },
+    };
+    if (addHostsParameter) {
+      set(RequestInfo, "parameters.hosts", hostsString);
+    }
+    const resourceFilters = {
+      hosts: hostsString,
+    };
+    return {
+      RequestInfo,
+      resource_filters: resourceFilters,
+    };
+  };
+
+  const getGeneralHostCheck = () => {
+    const data = getDataForCheckRequest(
+      
"last_agent_env_check,installed_packages,existing_repos,transparentHugePage",
+      false
+    );
+    if (data) {
+      requestToPerformHostCheck();
+    } else {
+      stopHostCheck();
+    }
+  };
+
+  const filterHostsData = (data: any) => {
+    const bootHostNames = new Set(
+      bootHosts.current.map((bootHost: any) => bootHost.name)
+    );
+    const filteredData = {
+      href: data.href,
+      tasks: data.tasks.filter((task: any) =>
+        bootHostNames.has(task.Tasks.host_name)
+      ),
+    };
+    return filteredData;
+  };
+
+  const filterBootHosts = (data: any) => {
+    const bootHostNames = new Set(
+      bootHosts.current.map((bootHost: any) => bootHost.name)
+    );
+    const filteredData = {
+      href: data.href,
+      items: data.items.filter((host: any) =>
+        bootHostNames.has(host.Hosts.host_name)
+      ),
+    };
+    return filteredData;
+  };
+
+  const parseHostCheckWarnings = (warningDataCopy: any, data: any) => {
+    data = filterHostsData(data);
+    let warnings: any[] = [];
+    let warning;
+    let hosts: any[] = [];
+    let warningCategories = {
+      fileFoldersWarnings: {},
+      packagesWarnings: {},
+      processesWarnings: {},
+      servicesWarnings: {},
+      usersWarnings: {},
+      alternativeWarnings: {},
+    };
+
+    sortPropertyLight(data.tasks, "Tasks.host_name").forEach((_task: any) => {
+      let hostName = get(_task, "Tasks.host_name", "");
+      let host: any = {
+        name: hostName,
+        warnings: [],
+      };
+
+      if (
+        !get(_task, "Tasks.structured_out", "") ||
+        !get(_task, "Tasks.structured_out.last_agent_env_check", "")
+      ) {
+        return;
+      }
+
+      let lastAgentEnvCheck = get(
+        _task,
+        "Tasks.structured_out.last_agent_env_check",
+        ""
+      );
+
+      let stackFoldersAndFiles = get(
+        lastAgentEnvCheck,
+        "stackFoldersAndFiles",
+        []
+      );
+      stackFoldersAndFiles.forEach((path: any) => {
+        warning = get(warningCategories, "fileFoldersWarnings." + path.name);
+        if (warning) {
+          warning.hosts.push(hostName);
+          warning.hostsLong.push(hostName);
+        } else {
+          warning = {
+            name: path.name,
+            hosts: [hostName],
+            hostsLong: [hostName],
+            category: "fileFolders",
+          };
+          set(warningCategories, "fileFoldersWarnings." + path.name, warning);
+        }
+        host.warnings.push(warning);
+      });
+
+      // parse all package warnings for host
+      let _hostPackagesData = hostsPackagesData.current.find(
+        (hpd: any) => get(hpd, "hostName") === hostName
+      );
+
+      if (!isEmpty(_hostPackagesData)) {
+        get(_hostPackagesData, "installedPackages", []).forEach(
+          (_package: any) => {
+            warning = get(
+              warningCategories,
+              "packagesWarnings." + _package.name
+            );
+            if (warning) {
+              warning.hosts.push(hostName);
+              warning.hostsLong.push(hostName);
+              warning.version = _package.version;
+            } else {
+              warning = {
+                name: _package.name,
+                version: _package.version,
+                hosts: [hostName],
+                hostsLong: [hostName],
+                category: "packages",
+              };
+              set(
+                warningCategories,
+                "packagesWarnings." + _package.name,
+                warning
+              );
+            }
+            host.warnings.push(warning);
+          }
+        );
+      }
+
+      // parse all process warnings for host
+      let hostHealth = lastAgentEnvCheck.hostHealth;
+
+      let liveServices = get(hostHealth, "liveServices", null);
+      let javaProcs = get(hostHealth, "activeJavaProcs", null);
+
+      if (javaProcs) {
+        javaProcs.forEach((process: any) => {
+          warning = get(warningCategories, "processesWarnings." + process.pid);
+          if (warning) {
+            warning.hosts.push(hostName);
+            warning.hostsLong.push(hostName);
+          } else {
+            let command = `pid=${process.pid}, user=${process.user}`;
+            warning = {
+              name:
+                command.length > 36
+                  ? command.substring(0, 35) + "..."
+                  : command,
+              hosts: [hostName],
+              hostsLong: [hostName],
+              category: "processes",
+              user: process.user,
+              pid: process.pid,
+              command: command,
+            };
+            set(warningCategories, "processesWarnings." + process.pid, 
warning);
+          }
+          host.warnings.push(warning);
+        });
+      }
+
+      // parse all service warnings for host
+      if (liveServices) {
+        liveServices.forEach((service: any) => {
+          if (service.status === "Unhealthy") {
+            warning = get(
+              warningCategories,
+              "servicesWarnings." + service.name
+            );
+            if (warning) {
+              warning.hosts.push(hostName);
+              warning.hostsLong.push(hostName);
+            } else {
+              warning = {
+                name: service.name,
+                hosts: [hostName],
+                hostsLong: [hostName],
+                category: "services",
+              };
+              set(
+                warningCategories,
+                "servicesWarnings" + service.name,
+                warning
+              );
+            }
+            host.warnings.push(warning);
+          }
+        });
+      }
+
+      // parse all user warnings for host
+      let existingUsers = lastAgentEnvCheck.existingUsers;
+      if (existingUsers) {
+        existingUsers.forEach((user: any) => {
+          warning = get(warningCategories, "usersWarnings." + user.name);
+          if (warning) {
+            warning.hosts.push(hostName);
+            warning.hostsLong.push(hostName);
+          } else {
+            warning = {
+              name: user.name,
+              hosts: [hostName],
+              hostsLong: [hostName],
+              category: "users",
+            };
+            set(warningCategories, "usersWarnings." + user.name, warning);
+          }
+          host.warnings.push(warning);
+        });
+      }
+
+      // parse misc warnings for host
+      let umask = lastAgentEnvCheck.umask;
+      if (umask && umask > 23) {
+        warning = warnings.find(
+          (w) => w.category === "misc" && w.name === umask
+        );
+        if (warning) {
+          warning.hosts.push(hostName);
+          warning.hostsLong.push(hostName);
+        } else {
+          warning = {
+            name: umask,
+            hosts: [hostName],
+            hostsLong: [hostName],
+            category: "misc",
+          };
+          warnings.push(warning);
+        }
+        host.warnings.push(warning);
+      }
+
+      let firewallRunning = lastAgentEnvCheck.firewallRunning;
+      if (firewallRunning !== null && firewallRunning) {
+        let name = `${lastAgentEnvCheck.firewallName} Running`;
+        warning = warnings.find(
+          (w) => w.category === "firewall" && w.name === name
+        );
+        if (warning) {
+          warning.hosts.push(hostName);
+          warning.hostsLong.push(hostName);
+        } else {
+          warning = {
+            name: name,
+            hosts: [hostName],
+            hostsLong: [hostName],
+            category: "firewall",
+          };
+          warnings.push(warning);
+        }
+        host.warnings.push(warning);
+      }
+
+      if (lastAgentEnvCheck.alternatives) {
+        lastAgentEnvCheck.alternatives.forEach((alternative: any) => {
+          warning = get(
+            warningCategories,
+            "alternativeWarnings" + alternative.name
+          );
+          if (warning) {
+            warning.hosts.push(hostName);
+            warning.hostsLong.push(hostName);
+          } else {
+            warning = {
+              name: alternative.name,
+              target: alternative.target,
+              hosts: [hostName],
+              hostsLong: [hostName],
+              category: "alternatives",
+            };
+            set(
+              warningCategories,
+              "alternativeWarnings" + alternative.name,
+              warning
+            );
+          }
+          host.warnings.push(warning);
+        });
+      }
+
+      if (lastAgentEnvCheck.reverseLookup === false) {
+        let name = "Reverse Lookup validation failed on";
+        warning = warnings.find(
+          (w) => w.category === "reverseLookup" && w.name === name
+        );
+        if (warning) {
+          warning.hosts.push(hostName);
+          warning.hostsLong.push(hostName);
+        } else {
+          warning = {
+            name: name,
+            hosts: [hostName],
+            hostsLong: [hostName],
+            category: "reverseLookup",
+          };
+          warnings.push(warning);
+        }
+        host.warnings.push(warning);
+      }
+      hosts.push(host);
+    });
+
+    for (let categoryId in warningCategories) {
+      let category = get(warningCategories, categoryId);
+      for (let warningId in category) {
+        warnings.push(category[warningId]);
+      }
+    }
+
+    hosts.unshift({
+      name: "All Hosts",
+      warnings: warnings,
+    });
+
+    set(warningDataCopy, "allWarnings", warnings);
+    set(warningDataCopy, "warningsByHost", hosts);
+  };
+
+  function parseWarnings(warningDataCopy: any, data: any) {
+    data = filterBootHosts(data);
+    let warnings: any[] = [];
+    let warning;
+    let hosts: any[] = [];
+    let warningCategories = {
+      fileFoldersWarnings: {},
+      packagesWarnings: {},
+      processesWarnings: {},
+      servicesWarnings: {},
+      usersWarnings: {},
+      alternativeWarnings: {},
+    };
+
+    sortPropertyLight(data.items, "Hosts.host_name").forEach((_host: any) => {
+      let host: any = {
+        name: _host.Hosts.host_name,
+        warnings: [],
+      };
+      if (!_host.Hosts.last_agent_env) {
+        return;
+      }
+
+      let stackFoldersAndFiles = get(
+        _host,
+        "Hosts.last_agent_env.stackFoldersAndFiles",
+        []
+      );
+      stackFoldersAndFiles.forEach((path: any) => {
+        warning = get(warningCategories, "fileFoldersWarnings." + path.name);
+        if (warning) {
+          warning.hosts.push(_host.Hosts.host_name);
+          warning.hostsLong.push(_host.Hosts.host_name);
+        } else {
+          warning = {
+            name: path.name,
+            hosts: [_host.Hosts.host_name],
+            hostsLong: [_host.Hosts.host_name],
+            category: "fileFolders",
+          };
+          set(warningCategories, "fileFoldersWarnings." + path.name, warning);
+        }
+        host.warnings.push(warning);
+      });
+
+      let _hostPackagesData: any = hostsPackagesData.current.find(
+        (hpd: any) => get(hpd, "hostName") === get(_host, "Hosts.host_name")
+      );
+      if (_hostPackagesData) {
+        _hostPackagesData.installedPackages.forEach((_package: any) => {
+          warning = get(warningCategories, "packagesWarnings." + 
_package.name);
+          if (warning) {
+            warning.hosts.push(_host.Hosts.host_name);
+            warning.hostsLong.push(_host.Hosts.host_name);
+            warning.version = _package.version;
+          } else {
+            warning = {
+              name: _package.name,
+              version: _package.version,
+              hosts: [_host.Hosts.host_name],
+              hostsLong: [_host.Hosts.host_name],
+              category: "packages",
+            };
+            set(
+              warningCategories,
+              "packagesWarnings." + _package.name,
+              warning
+            );
+          }
+          host.warnings.push(warning);
+        });
+      }
+
+      let javaProcs = _host.Hosts.last_agent_env.hostHealth
+        ? _host.Hosts.last_agent_env.hostHealth.activeJavaProcs
+        : _host.Hosts.last_agent_env.javaProcs;
+      if (javaProcs) {
+        javaProcs.forEach((process: any) => {
+          warning = get(warningCategories, "processesWarnings." + process.pid);
+          if (warning) {
+            warning.hosts.push(_host.Hosts.host_name);
+            warning.hostsLong.push(_host.Hosts.host_name);
+          } else {
+            let command = "pid=" + process.pid + ", user=" + process.user;
+            warning = {
+              name:
+                command.length > 36
+                  ? command.substring(0, 35) + "..."
+                  : command,
+              hosts: [_host.Hosts.host_name],
+              hostsLong: [_host.Hosts.host_name],
+              category: "processes",
+              user: process.user,
+              pid: process.pid,
+              command: command,
+            };
+            set(warningCategories, "processesWarnings." + process.pid, 
warning);
+          }
+          host.warnings.push(warning);
+        });
+      }
+
+      if (
+        _host.Hosts.last_agent_env.hostHealth &&
+        _host.Hosts.last_agent_env.hostHealth.liveServices
+      ) {
+        _host.Hosts.last_agent_env.hostHealth.liveServices.forEach(
+          (service: any) => {
+            if (service.status === "Unhealthy") {
+              warning = get(
+                warningCategories,
+                "servicesWarnings" + service.name
+              );
+              if (warning) {
+                warning.hosts.push(_host.Hosts.host_name);
+                warning.hostsLong.push(_host.Hosts.host_name);
+              } else {
+                warning = {
+                  name: service.name,
+                  hosts: [_host.Hosts.host_name],
+                  hostsLong: [_host.Hosts.host_name],
+                  category: "services",
+                };
+                set(
+                  warningCategories,
+                  "servicesWarnings" + service.name,
+                  warning
+                );
+              }
+              host.warnings.push(warning);
+            }
+          }
+        );
+      }
+
+      if (_host.Hosts.last_agent_env.existingUsers) {
+        _host.Hosts.last_agent_env.existingUsers.forEach((user: any) => {
+          warning = get(warningCategories, "usersWarnings." + user.name);
+          if (warning) {
+            warning.hosts.push(_host.Hosts.host_name);
+            warning.hostsLong.push(_host.Hosts.host_name);
+          } else {
+            warning = {
+              name: user.name,
+              hosts: [_host.Hosts.host_name],
+              hostsLong: [_host.Hosts.host_name],
+              category: "users",
+            };
+            set(warningCategories, "usersWarnings." + user.name, warning);
+          }
+          host.warnings.push(warning);
+        });
+      }
+
+      let umask = _host.Hosts.last_agent_env.umask;
+      if (umask && umask > 23) {
+        warning = warnings.find(
+          (w) => w.category === "misc" && w.name === umask
+        );
+        if (warning) {
+          warning.hosts.push(_host.Hosts.host_name);
+          warning.hostsLong.push(_host.Hosts.host_name);
+        } else {
+          warning = {
+            name: umask,
+            hosts: [_host.Hosts.host_name],
+            hostsLong: [_host.Hosts.host_name],
+            category: "misc",
+          };
+          warnings.push(warning);
+        }
+        host.warnings.push(warning);
+      }
+
+      let firewallRunning = _host.Hosts.last_agent_env.firewallRunning;
+      if (firewallRunning !== null && firewallRunning) {
+        let name = _host.Hosts.last_agent_env.firewallName + " Running";
+        warning = warnings.find(
+          (w) => w.category === "firewall" && w.name === name
+        );
+        if (warning) {
+          warning.hosts.push(_host.Hosts.host_name);
+          warning.hostsLong.push(_host.Hosts.host_name);
+        } else {
+          warning = {
+            name: name,
+            hosts: [_host.Hosts.host_name],
+            hostsLong: [_host.Hosts.host_name],
+            category: "firewall",
+          };
+          warnings.push(warning);
+        }
+        host.warnings.push(warning);
+      }
+
+      if (_host.Hosts.last_agent_env.alternatives) {
+        _host.Hosts.last_agent_env.alternatives.forEach((alternative: any) => {
+          warning = get(
+            warningCategories,
+            "alternativeWarnings" + alternative.name
+          );
+          if (warning) {
+            warning.hosts.push(_host.Hosts.host_name);
+            warning.hostsLong.push(_host.Hosts.host_name);
+          } else {
+            warning = {
+              name: alternative.name,
+              target: alternative.target,
+              hosts: [_host.Hosts.host_name],
+              hostsLong: [_host.Hosts.host_name],
+              category: "alternatives",
+            };
+            set(
+              warningCategories,
+              "alternativeWarnings" + alternative.name,
+              warning
+            );
+          }
+          host.warnings.push(warning);
+        });
+      }
+
+      if (_host.Hosts.last_agent_env.reverseLookup === false) {
+        let name = "Reverse Lookup validation failed on";
+        warning = warnings.find(
+          (w) => w.category === "reverseLookup" && w.name === name
+        );
+        if (warning) {
+          warning.hosts.push(_host.Hosts.host_name);
+          warning.hostsLong.push(_host.Hosts.host_name);
+        } else {
+          warning = {
+            name: name,
+            hosts: [_host.Hosts.host_name],
+            hostsLong: [_host.Hosts.host_name],
+            category: "reverseLookup",
+          };
+          warnings.push(warning);
+        }
+        host.warnings.push(warning);
+      }
+      hosts.push(host);
+    });
+
+    for (let categoryId in warningCategories) {
+      let category = get(warningCategories, categoryId);
+      for (let warningId in category) {
+        warnings.push(category[warningId]);
+      }
+    }
+
+    hosts.unshift({
+      name: "All Hosts",
+      warnings: warnings,
+    });
+
+    set(warningDataCopy, "allWarnings", warnings);
+    set(warningDataCopy, "warningsByHost", hosts);
+  }
+
+  const setHostDataWithSkipBootstrap = (host: any) => {
+    set(host, "cpu", 2);
+    set(host, "memory", parseInt("2000000").toFixed(2));
+    set(host, "disk_info", [
+      { mountpoint: "/", type: "ext4" },
+      { mountpoint: "/grid/0", type: "ext4" },
+      { mountpoint: "/grid/1", type: "ext4" },
+      { mountpoint: "/grid/2", type: "ext4" },
+    ]);
+    return host;
+  };
+
+  const setHostDataFromLoadedHostInfo = (host: any, hostInfo: any) => {
+    set(host, "cpu", get(hostInfo, "Hosts.cpu_count", 2));
+    set(
+      host,
+      "memory",
+      parseInt(get(hostInfo, "Hosts.total_mem", "2000000")).toFixed(2)
+    );
+    set(
+      host,
+      "disk_info",
+      get(hostInfo, "Hosts.disk_info", []).filter(
+        (h: any) => h.mountpoint != "/boot"
+      )
+    );
+    set(host, "os_type", get(hostInfo, "Hosts.os_type", ""));
+    set(host, "os_family", get(hostInfo, "Hosts.os_family", ""));
+    set(host, "os_arch", get(hostInfo, "Hosts.os_arch", ""));
+    set(host, "ip", get(hostInfo, "Hosts.ip", ""));
+    return host;
+  };
+
+  const checkHostOSType = (osFamily: any, hostName: any) => {
+    const stacks: any[] = []; //TODO: figure out and get the stack from 
content or App
+    if (!isEmpty(stacks)) {
+      const selectedStack = stacks.find((stack: any) => stack.isSelected);
+      const selectedOS: any[] = [];
+      let isValid = false;
+      if (selectedStack && selectedStack.operatingSystems) {
+        selectedStack.operatingSystems
+          .filter((os: any) => os.isSelected)
+          .forEach((os: any) => {
+            selectedOS.push(os.osType);
+            if (os.osType === osFamily) {
+              isValid = true;
+            }
+          });
+      }
+      if (isValid) {
+        return "";
+      } else {
+        return `Host (${hostName}) is ${osFamily} OS type, but the 
repositories chosen in "Select Stack" step was ${[
+          ...new Set(selectedOS),
+        ].join(", ")}. Selected repositories do not support this host OS 
type.`;
+      }
+    } else {
+      return "";
+    }
+  };
+
+  const checkHostDiskSpace = (hostName: any, diskInfo: any) => {
+    const minFreeRootSpace = minDiskSpace * 1024 * 1024;
+    const minFreeUsrLibSpace = minDiskSpaceUsrLib * 1024 * 1024;
+    let warningString = "";
+
+    diskInfo.forEach((info: any) => {
+      switch (info.mountpoint) {
+        case "/":
+          warningString =
+            info.available < minFreeRootSpace
+              ? `A minimum of ${minDiskSpace}GB is required for 
"${info.mountpoint}" mount. ${warningString}`
+              : warningString;
+          break;
+        case "/usr":
+        case "/usr/lib":
+          warningString =
+            info.available < minFreeUsrLibSpace
+              ? `A minimum of ${minDiskSpaceUsrLib}GB is required for 
"${info.mountpoint}" mount. ${warningString}`
+              : warningString;
+          break;
+        default:
+          break;
+      }
+    });
+
+    return warningString
+      ? `Not enough disk space on host (${hostName}). ${warningString}`
+      : "";
+  };
+
+  const checkTHP = (hostName: any, transparentHugePage: any) => {
+    if (transparentHugePage === "always") {
+      return hostName;
+    } else {
+      return "";
+    }
+  };
+
+  const getHostInfoSuccessCallback = (data: any) => {
+    const warningDataCopy = cloneDeep(warningData);
+    const hosts = bootHosts.current;
+    let repoWarnings: any[] = [],
+      diskWarnings: any[] = [],
+      thpWarnings: any[] = [],
+      hostsRepoNames: any[] = [],
+      hostsDiskContext: any[] = [],
+      thpContext: any[] = [],
+      hostsContext: any[] = [],
+      hostsDiskNames: any[] = [],
+      thpHostsNames: any[] = [];
+
+    const hostCheckRes = hostCheckResult.current;
+    if (hostCheckRes) {
+      parseHostCheckWarnings(warningDataCopy, hostCheckRes);
+      hostCheckResult.current = null;
+    } else {
+      parseWarnings(warningDataCopy, data);
+    }
+    hosts.forEach((_host) => {
+      const host = get(data, "items", []).filter((item: any) => {
+        return get(item, "Hosts.host_name") === get(_host, "name");
+      })[0];
+      if (skipBootstrap.current) {
+        _host = setHostDataWithSkipBootstrap(_host);
+      } else if (!isEmpty(host)) {
+        _host = setHostDataFromLoadedHostInfo(_host, host);
+        const hostName = get(host, "Hosts.host_name", "");
+
+        let context = checkHostOSType(
+          get(host, "Hosts.os_family", ""),
+          hostName
+        );
+        if (!isEmpty(context)) {
+          hostsContext.push(context);
+          hostsRepoNames.push(hostName);
+        }
+
+        const diskContext = checkHostDiskSpace(
+          hostName,
+          get(host, "Hosts.disk_info", [])
+        );
+        if (!isEmpty(diskContext)) {
+          hostsDiskContext.push(diskContext);
+          hostsDiskNames.push(hostName);
+        }
+        const _hostPackagesData = hostPackagesData.current.filter(
+          (hostData: any) => {
+            return get(hostData, "hostName") === hostName;
+          }
+        );
+        if (!isEmpty(_hostPackagesData)) {
+          const transparentHugePage = get(
+            _hostPackagesData,
+            "transparentHugePage",
+            []
+          );
+          context = checkTHP(hostName, transparentHugePage);
+        } else {
+          context = checkTHP(
+            hostName,
+            get(host, "Hosts.last_agent_env.transparentHugePage")
+          );
+        }
+        if (!isEmpty(context)) {
+          thpContext.push(context);
+          thpHostsNames.push(hostName);
+        }
+      }
+    });
+
+    if (hostsContext.length > 0) {
+      repoWarnings.push({
+        name: "Repository for OS not available",
+        hosts: hostsContext,
+        hostsLong: hostsContext,
+        hostsNames: hostsRepoNames,
+        category: "repositories",
+      });
+    }
+
+    if (hostsDiskContext.length > 0) {
+      diskWarnings.push({
+        name: "Not enough disk space",
+        hosts: hostsDiskContext,
+        hostsLong: hostsDiskContext,
+        hostsNames: hostsDiskNames,
+        category: "disk",
+      });
+    }
+
+    if (thpContext.length > 0) {
+      thpWarnings.push({
+        name: "Transparent Huge Pages",
+        hosts: thpContext,
+        hostsLong: thpContext,
+        hostsNames: thpHostsNames,
+        category: "thp",
+      });
+    }
+
+    set(warningDataCopy, "repoCategoryWarnings", repoWarnings);
+    set(warningDataCopy, "diskCategoryWarnings", diskWarnings);
+    set(warningDataCopy, "thpCategoryWarnings", thpWarnings);
+    setWarningData(warningDataCopy);
+  };
+
+  const getHostInfo = async () => {
+    const response = await HostsApi.getHostsData(
+      
"Hosts/total_mem,Hosts/cpu_count,Hosts/disk_info,Hosts/last_agent_env,Hosts/host_name,Hosts/os_type,Hosts/os_arch,Hosts/os_family,Hosts/ip"
+    );
+    getHostInfoSuccessCallback(response);
+  };
+
+  const parseHostNameResolution = (data: any) => {
+    if (!data) {
+      return;
+    }
+    const warningDataCopy = cloneDeep(warningData);
+    data.tasks.forEach((task: any) => {
+      const name = "Hostname resolution";
+      let hostInfo = get(warningDataCopy, "allWarnings", []).find(
+        (warning: any) => warning.name === name
+      );
+      if (finishStates.includes(task.Tasks.status)) {
+        if (
+          task.Tasks.status === "COMPLETED" &&
+          !!get(task, 
"Tasks.structured_out.host_resolution_check.failed_count")
+        ) {
+          const targetHostName = get(task, "Tasks.host_name");
+          const relatedHostNames = get(
+            task,
+            "Tasks.structured_out.host_resolution_check.hosts_with_failures",
+            []
+          );
+          const contextMessage = `${targetHostName} could not resolve: ${
+            relatedHostNames.length
+          } host${relatedHostNames.length === 1 ? "" : "s"}.`;
+          const contextMessageLong = `${targetHostName} could not resolve: 
${relatedHostNames.join(
+            ", "
+          )}.`;
+          if (!hostInfo) {
+            hostInfo = {
+              name: name,
+              hosts: [contextMessage],
+              hostsLong: [contextMessageLong],
+              hostsNames: [targetHostName],
+              category: "hostNameResolution",
+            };
+            warningDataCopy.hostCheckWarnings = [
+              ...warningDataCopy.hostCheckWarnings,
+              hostInfo,
+            ];
+          } else {
+            if (!hostInfo.hostsNames.includes(targetHostName)) {
+              hostInfo.hosts.push(contextMessage);
+              hostInfo.hostsLong.push(contextMessageLong);
+              hostInfo.hostsNames.push(targetHostName);
+              warningDataCopy.hostCheckWarnings =
+                warningDataCopy.hostCheckWarnings.map((warning: any) =>
+                  warning.name === name ? hostInfo : warning
+                );
+            }
+          }
+        }
+      }
+    });
+    setWarningData(warningDataCopy);
+  };
+
+  const getHostCheckTasksSuccess = (data: any) => {
+    if (isEmpty(data)) {
+      getGeneralHostCheck();
+      return;
+    }
+    if (finishStates.includes(get(data, "Requests.request_status"))) {
+      if (get(data, "Requests.inputs", "").includes("last_agent_env_check")) {
+        pausePolling();
+        setIsHostCheckRunning(false);
+        hostsPackagesData.current = get(data, "tasks", []).map((task: any) => {
+          const installedPackages = get(
+            task,
+            "Tasks.structured_out.installed_packages",
+            []
+          );
+          return {
+            hostName: get(task, "Tasks.host_name", ""),
+            transparentHugePage: get(
+              task,
+              "Tasks.structured_out.transparentHugePage.message",
+              ""
+            ),
+            installedPackages: installedPackages,
+          };
+        });
+        hostCheckResult.current = data;
+        getHostInfo();
+      } else if (
+        get(data, "Requests.inputs", "").includes("host_resolution_check")
+      ) {
+        parseHostNameResolution(data);
+        getGeneralHostCheck();
+      }
+    }
+  };
+
+  const startHostCheck = (bootHostsList: BootHostType[]) => {
+    cleanup();
+    bootHosts.current = bootHostsList;
+    if (!isEmpty(ambariProperties)) {
+      const hostName = map(bootHosts.current, "name").join(",");
+      const jdkLocation = get(
+        ambariProperties,
+        "RootServiceComponents.properties.jdk_location",
+        ""
+      );
+      const requestInfo = {
+        action: "check_host",
+        context: "Check host",
+        parameters: {
+          hosts: hostName,
+          check_execute_list:
+            
"last_agent_env_check,installed_packages,existing_repos,transparentHugePage",
+          jdk_location: jdkLocation,
+          threshold: "20",
+        },
+      };
+      const data = {
+        RequestInfo: requestInfo,
+        resource_filters: { hosts: hostName },
+      };
+      dataForHostCheck.current = data;
+    }
+    setIsHostCheckRunning(true);
+    requestToPerformHostCheck();
+  };
+
+  return {
+    startHostCheck,
+    stopHostCheck,
+    isHostCheckRunning,
+    hostCheckResult: warningData,
+  };
+};
diff --git a/ambari-web/latest/src/screens/Hosts/HostChecks.tsx 
b/ambari-web/latest/src/screens/Hosts/HostChecks.tsx
new file mode 100644
index 0000000000..181ab1d6c8
--- /dev/null
+++ b/ambari-web/latest/src/screens/Hosts/HostChecks.tsx
@@ -0,0 +1,530 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Accordion, Form } from "react-bootstrap";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import {
+  faCheck,
+  faExclamationTriangle,
+  faExternalLink,
+} from "@fortawesome/free-solid-svg-icons";
+import Spinner from "../../components/Spinner";
+import Modal from "../../components/Modal";
+import { cloneDeep, forEach, get, isEmpty, set } from "lodash";
+import {
+  categoriesToReportMap,
+  checkHostIssues,
+  hostCheckReportConstants,
+  restWarningCategories,
+  restWarningCategoriesToIssuesKeyMap,
+} from "./constants";
+import { useEffect, useState } from "react";
+import modalManager from "../../store/ModalManager";
+import { initialWarningData } from "../../hooks/useHostChecks";
+import { translate } from "../../Utils/Utility";
+
+enum HostOption {
+  ALL = "All Hosts",
+}
+
+type HostChecksModalProps = {
+  isOpen: boolean;
+  onClose: () => void;
+  successCallback: () => void;
+  hostCheckResult: any;
+  loading: boolean;
+};
+
+export const getHostWithIssues = (hostCheckResult: any) => {
+  const hostNameList: any[] = [];
+
+  get(hostCheckResult, "warningsByHost")
+    ?.slice(1)
+    ?.forEach((_host: any) => {
+      if (_host?.warnings?.length) {
+        hostNameList.push({
+          name: _host?.name,
+          count: _host?.warnings?.length,
+        });
+      }
+    });
+
+  restWarningCategories.forEach((category: any) => {
+    if (hostCheckResult?.[category]?.length) {
+      hostCheckResult?.[category]?.[0]?.hostsNames?.forEach(
+        (_hostName: any) => {
+          const prevEntry = hostNameList.find(
+            (host: any) => host?.name === _hostName
+          );
+          if (!prevEntry) {
+            hostNameList.push({
+              name: _hostName,
+              count: 1,
+            });
+          } else {
+            prevEntry.count++;
+          }
+        }
+      );
+    }
+  });
+
+  return hostNameList;
+};
+
+export const getTotalIssuesCount = (hostCheckResult: any) => {
+  let totalIssues = 0;
+  const warningNames = new Set<string>();
+  hostCheckResult.warningsByHost
+    .filter((_host: any) => _host.name === HostOption.ALL)
+    .forEach((_host: any) => {
+      _host.warnings.forEach((warning: any) => {
+        if (warningNames.has(warning.name)) {
+          return;
+        } else {
+          warningNames.add(warning.name);
+          totalIssues++;
+        }
+      });
+    });
+
+  restWarningCategories.forEach((category: any) => {
+    if (hostCheckResult?.[category]?.length) {
+      totalIssues++;
+    }
+  });
+
+  return totalIssues;
+};
+
+export default function HostChecks({
+  isOpen,
+  onClose,
+  successCallback,
+  hostCheckResult,
+  loading,
+}: HostChecksModalProps) {
+  const [issues, setIssues] = useState<any>(checkHostIssues);
+  const [filteredHostCheckRes, setFilteredHostCheckRes] =
+    useState<any>(hostCheckResult);
+  const [selectedHost, setSelectedHost] = useState(HostOption.ALL);
+
+  const showHostListModal = (hostsList: any[]) => {
+    const modalProps = {
+      onClose: () => {},
+      modalTitle: "List of hosts",
+      modalBody: getHostListModalBody(hostsList),
+      successCallback: () => {
+        modalManager.hide();
+      },
+      options: {
+        cancelableViaIcon: true,
+        cancelableViaBtn: false,
+      },
+    };
+    modalManager.show(modalProps);
+  };
+
+  const getHostListModalBody = (hostsList: any[]) => {
+    return (
+      <div>
+        {hostsList.map((host: any) => {
+          return <div className="fs-12 mb-1">{host}</div>;
+        })}
+      </div>
+    );
+  };
+
+  const getWarningListItemStructure = (warning: any, customText: string) => {
+    return (
+      <div className="d-flex mb-1">
+        <div className="fs-12 w-70">{warning.name}</div>
+        <div className="fs-12 w-30">
+          {customText}{" "}
+          <span
+            className="custom-link fs-12"
+            onClick={() => {
+              showHostListModal(warning.hosts);
+            }}
+          >
+            {warning.hosts.length} {warning.hosts.length > 1 ? "hosts" : 
"host"}
+          </span>
+        </div>
+      </div>
+    );
+  };
+
+  useEffect(() => {
+    if (
+      JSON.stringify(filteredHostCheckRes) !==
+      JSON.stringify(initialWarningData)
+    ) {
+      const issuesCopy = cloneDeep(checkHostIssues);
+      const warningNames = new Set<string>();
+      filteredHostCheckRes.warningsByHost
+        .filter((_host: any) => _host.name === selectedHost)
+        .forEach((_host: any) => {
+          _host.warnings.forEach((warning: any) => {
+            const category = warning.category;
+            if (warningNames.has(warning.name)) {
+              return;
+            } else {
+              warningNames.add(warning.name);
+            }
+            const issue = get(issuesCopy, category, {});
+            issue.count = issue.count + 1;
+            switch (category) {
+              case "packages":
+                issue.data.push(
+                  <div className="d-flex mb-1">
+                    <div className="fs-12 w-40">{warning.name}</div>
+                    <div className="fs-12 w-30">{warning.version}</div>
+                    <div className="fs-12 w-30">
+                      Installed on{" "}
+                      <span
+                        className="custom-link fs-12"
+                        onClick={() => {
+                          showHostListModal(warning.hosts);
+                        }}
+                      >
+                        {warning.hosts.length} host
+                      </span>
+                    </div>
+                  </div>
+                );
+                break;
+              case "processes":
+              case "firewall":
+                issue.data.push(
+                  getWarningListItemStructure(warning, "Running on")
+                );
+                break;
+              case "services":
+                issue.data.push(
+                  getWarningListItemStructure(warning, "Unhealthy on")
+                );
+                break;
+              case "users":
+              case "fileFolders":
+                issue.data.push(
+                  getWarningListItemStructure(warning, "Present on")
+                );
+                break;
+              case "misc":
+                issue.data.push(
+                  getWarningListItemStructure(warning, "Umask on")
+                );
+                break;
+              case "alternatives":
+                issue.data.push(
+                  <div className="d-flex mb-1">
+                    <div className="fs-12 w-40">{warning.name}</div>
+                    <div className="fs-12 w-30">{warning.target}</div>
+                    <div className="fs-12 w-30">
+                      On{" "}
+                      <span
+                        className="custom-link fs-12"
+                        onClick={() => {
+                          showHostListModal(warning.hosts);
+                        }}
+                      >
+                        {warning.hosts.length} host
+                      </span>
+                    </div>
+                  </div>
+                );
+                break;
+              case "reverseLookup":
+                issue.data.push(getWarningListItemStructure(warning, ""));
+                break;
+            }
+          });
+        });
+
+      restWarningCategories.forEach((category) => {
+        const issue = get(
+          issuesCopy,
+          get(restWarningCategoriesToIssuesKeyMap, category),
+          {}
+        );
+        set(issue, "count", get(filteredHostCheckRes, category, []).length);
+        set(
+          issue,
+          "data",
+          get(filteredHostCheckRes, category, []).map((warning: any) => {
+            return (
+              <div>
+                {forEach(warning.hosts, (host: any) => {
+                  return (
+                    <div className="d-flex mb-1">
+                      <div className="fs-12 w-70">
+                        {warning.name + " " + host}
+                      </div>
+                    </div>
+                  );
+                })}
+              </div>
+            );
+          })
+        );
+        set(
+          issuesCopy,
+          get(restWarningCategoriesToIssuesKeyMap, category),
+          issue
+        );
+      });
+      setIssues(issuesCopy);
+    }
+  }, [JSON.stringify(filteredHostCheckRes)]);
+
+  useEffect(() => {
+    if (!isEmpty(hostCheckResult)) {
+      if (selectedHost === HostOption.ALL) {
+        setFilteredHostCheckRes(hostCheckResult);
+      } else {
+        const filteredHostCheckResCopy = cloneDeep(hostCheckResult);
+        filteredHostCheckResCopy.warningsByHost =
+          filteredHostCheckResCopy.warningsByHost.filter(
+            (host: any) => host.name === selectedHost
+          );
+        restWarningCategories.forEach((category) => {
+          filteredHostCheckResCopy[category].forEach((warning: any) => {
+            warning.hosts = [selectedHost];
+            warning.hostsLong = [selectedHost];
+            warning.hostsNames = [selectedHost];
+          });
+        });
+        setFilteredHostCheckRes(filteredHostCheckResCopy);
+      }
+    }
+  }, [hostCheckResult, selectedHost]);
+
+  const getIssue = (issue: string) => {
+    return get(issues, issue);
+  };
+
+  const getHostNames = (result: any) => {
+    const hostNames = get(result, "warningsByHost", []).map(
+      (host: any) => host.name
+    );
+    return hostNames;
+  };
+
+  const contentInDetails = () => {
+    let newContent = "";
+    let hostNamesWithWarnings = getHostNames(filteredHostCheckRes);
+    if (selectedHost === HostOption.ALL) {
+      hostNamesWithWarnings = hostNamesWithWarnings.filter(
+        (hostName: string) => hostName !== HostOption.ALL
+      );
+    }
+
+    newContent +=
+      hostCheckReportConstants[
+        "installer.step3.hostWarningsPopup.report.header"
+      ] + new Date();
+    newContent +=
+      hostCheckReportConstants[
+        "installer.step3.hostWarningsPopup.report.hosts"
+      ];
+    newContent += hostNamesWithWarnings.join(" ");
+
+    const isHostPresent = (hostNames: string[]) => {
+      return hostNames.some((name) => hostNamesWithWarnings.includes(name));
+    };
+
+    const processContent = filteredHostCheckRes?.allWarnings?.filter(
+      (item: any) =>
+        item?.category === "processes" && isHostPresent(item?.hosts)
+    );
+    if (processContent.length) {
+      newContent +=
+        hostCheckReportConstants[
+          "installer.step3.hostWarningsPopup.report.process"
+        ];
+      processContent.forEach((process: any, i: number) => {
+        process?.hosts?.forEach((host: any, j: number) => {
+          if (!!i || !!j) {
+            newContent += ",";
+          }
+          newContent += `(${host},${process?.user},${process?.pid})`;
+        });
+      });
+    }
+
+    categoriesToReportMap.forEach((category) => {
+      if (restWarningCategories.includes(category?.key)) {
+        const catContent = filteredHostCheckRes?.[category?.key];
+        if (catContent.length) {
+          newContent += hostCheckReportConstants[category?.label];
+          newContent += catContent?.[0]?.hostsNames?.join(category?.separator);
+        }
+      } else {
+        const catContent = filteredHostCheckRes?.allWarnings?.filter(
+          (item: any) =>
+            item?.category === category?.key && isHostPresent(item?.hosts)
+        );
+        if (catContent.length) {
+          newContent += hostCheckReportConstants[category?.label];
+          if (category?.mapProperty) {
+            newContent += catContent
+              .map((warning: any) => warning[category?.mapProperty])
+              .join(category?.separator);
+          }
+        }
+      }
+    });
+
+    newContent += "</p>";
+    return newContent;
+  };
+
+  const getModalBody = () => {
+    if (loading) {
+      return <Spinner />;
+    }
+
+    return (
+      <div>
+        <div className="fs-12 mb-1">
+          Host Checks found{" "}
+          <span className="fw-bold text-dark fs-12">
+            {getTotalIssuesCount(hostCheckResult)} issues on{" "}
+            {getHostWithIssues(hostCheckResult).length} host.
+          </span>
+        </div>
+        <div className="fs-12 mb-4">
+          After manually resolving the issues, click{" "}
+          <span className="fw-bold text-dark fs-12">Rerun Checks.</span>
+        </div>
+        <div className="d-flex justify-content-between mb-2">
+          <div className="d-flex">
+            <Form.Label className="fw-bold text-dark pt-2 fs-12 me-5">
+              Hosts
+            </Form.Label>
+            <Form.Select
+              className="custom-form-control fs-12"
+              value={selectedHost}
+              onChange={(e) => setSelectedHost(e.target.value as HostOption)}
+            >
+              <option value={HostOption.ALL}>All Hosts</option>
+              {getHostNames(hostCheckResult)
+                .slice(1)
+                .map((hostName: string) => (
+                  <option key={hostName} value={hostName}>
+                    {hostName}
+                  </option>
+                ))}
+            </Form.Select>
+          </div>
+          <div
+            className="custom-link fs-12 pt-2"
+            onClick={() => {
+              const content = contentInDetails();
+              const newWindow = window.open("", "_blank");
+              newWindow?.document.write(content);
+            }}
+          >
+            <FontAwesomeIcon icon={faExternalLink} className="fs-12" /> Show
+            Report
+          </div>
+        </div>
+        <div>
+          {Object.keys(issues).map((issue: string) => {
+            return (
+              <Accordion className="border-0" key={issue}>
+                <Accordion.Item eventKey={issue} className="border-0">
+                  <Accordion.Header className="p-0">
+                    <div className="d-flex justify-content-between">
+                      <div className="d-flex">
+                        {getIssue(issue).data.length ? (
+                          <FontAwesomeIcon
+                            icon={faExclamationTriangle}
+                            className="me-2 text-danger"
+                          />
+                        ) : (
+                          <FontAwesomeIcon
+                            icon={faCheck}
+                            className="me-2 text-success"
+                          />
+                        )}
+                        <div className="fs-12">
+                          {getIssue(issue).displayName}
+                        </div>
+                      </div>
+                      <div className="fs-12 px-1">
+                        ({getIssue(issue).count})
+                      </div>
+                    </div>
+                  </Accordion.Header>
+                  <hr className="m-0" />
+                  <Accordion.Body>
+                    <div className="fs-12">
+                      {getIssue(issue).data.length
+                        ? getIssue(issue).dataMessage
+                        : `There were no ${getIssue(
+                            issue
+                          ).displayName.toLowerCase()}`}
+                    </div>
+                    <hr />
+                    <div>
+                      {getIssue(issue).data.map((data: any) => {
+                        return (
+                          <div>
+                            {data}
+                            <hr className="p-0" />
+                          </div>
+                        );
+                      })}
+                    </div>
+                  </Accordion.Body>
+                </Accordion.Item>
+              </Accordion>
+            );
+          })}
+        </div>
+      </div>
+    );
+  };
+
+  return (
+    <div>
+      {isOpen ? (
+        <Modal
+          isOpen={isOpen}
+          onClose={onClose}
+          modalTitle={String(
+            translate("installer.step3.warnings.popup.header")
+          )}
+          modalBody={getModalBody()}
+          successCallback={successCallback}
+          options={{
+            okButtonDisabled: loading,
+            okButtonText: String(
+              translate("installer.step3.hostWarningsPopup.rerunChecks")
+            ).toUpperCase(),
+            okButtonVariant: "warning",
+            cancelButtonText: String(translate("common.close")).toUpperCase(),
+            cancelableViaIcon: true,
+            cancelableViaBtn: true,
+          }}
+        />
+      ) : null}
+    </div>
+  );
+}
diff --git a/ambari-web/latest/src/screens/Hosts/constants.ts 
b/ambari-web/latest/src/screens/Hosts/constants.ts
new file mode 100644
index 0000000000..95c9aa5aef
--- /dev/null
+++ b/ambari-web/latest/src/screens/Hosts/constants.ts
@@ -0,0 +1,445 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { translate } from "../../Utils/Utility";
+
+export const sortByColIdToKeyMapping = {
+  hostname: "Hosts/host_name",
+  ip: "Hosts/ip",
+  rack: "Hosts/rack_info",
+  cores: "Hosts/cpu_count",
+  ram: "Hosts/total_mem",
+  disk: "metrics/disk/disk_free",
+  load: "metrics/load/load_one",
+};
+
+export const hostMetricsOption = [
+  "Last 1 hour",
+  "Last 2 hours",
+  "Last 4 hours",
+  "Last 12 hours",
+  "Last 24 hours",
+  "Last 1 week",
+  "Last 1 month",
+  "Last 1 year",
+];
+
+export const actionToStateMapping = {
+  start: {
+    PENDING: "INSTALLED",
+    IN_PROGRESS: "STARTING",
+    COMPLETED: "STARTED",
+    FAILED: "INSTALLED",
+  },
+  restart: {
+    PENDING: "INSTALLED",
+    IN_PROGRESS: "STARTING",
+    COMPLETED: "STARTED",
+    FAILED: "INSTALLED",
+  },
+  stop: {
+    PENDING: "STARTED",
+    IN_PROGRESS: "STOPPING",
+    COMPLETED: "INSTALLED",
+    FAILED: "STARTED",
+  },
+};
+
+export const finishStates = ["FAILED", "COMPLETED", "TIMEDOUT", "ABORTED"];
+export const componentFinishStates = ["INSTALLED", "STARTED"];
+export const maintenanceStates = ["ON", "OFF"];
+export const minDiskSpace = 2.0;
+export const minDiskSpaceUsrLib = 1.0;
+
+export const restWarningCategories = [
+  "repoCategoryWarnings",
+  "diskCategoryWarnings",
+  "jdkCategoryWarnings",
+  "hostCheckWarnings",
+  "thpCategoryWarnings",
+];
+
+export const restWarningCategoriesToIssuesKeyMap = {
+  repoCategoryWarnings: "repositories",
+  diskCategoryWarnings: "disk",
+  jdkCategoryWarnings: "jdk",
+  hostCheckWarnings: "hostNameResolution",
+  thpCategoryWarnings: "thp",
+};
+
+export const checkHostIssues = {
+  packages: {
+    displayName: "Package Issues",
+    count: 0,
+    data: [],
+    dataMessage: "The following packages should be uninstalled",
+    noDataMessage: "There were no unwanted packages",
+  },
+  processes: {
+    displayName: "Process Issues",
+    count: 0,
+    data: [],
+    dataMessage: "The following processes should not be running",
+    noDataMessage: "There were no unwanted processes",
+  },
+  thp: {
+    displayName: "Transparent Huge Pages Issues",
+    count: 0,
+    data: [],
+    dataMessage: "The following THP issues should be fixed",
+    noDataMessage: "There were no THP issues",
+  },
+  jdk: {
+    displayName: "JDK Issues",
+    count: 0,
+    data: [],
+    dataMessage: "The following JDK issues should be fixed",
+    noDataMessage: "There were no JDK issues",
+  },
+  disk: {
+    displayName: "Disk Issues",
+    count: 0,
+    data: [],
+    dataMessage: "The following disks should be cleaned",
+    noDataMessage: "There were no disk space issues",
+  },
+  repositories: {
+    displayName: "Repository Issues ",
+    count: 0,
+    data: [],
+    dataMessage:
+      "The following repositories has OS type mis-match with registered hosts",
+    noDataMessage:
+      "There were no repositories OS type mis-match with registered hosts",
+  },
+  firewall: {
+    displayName: "Firewall Issues",
+    count: 0,
+    data: [],
+    dataMessage: "The following firewalls should be disabled",
+    noDataMessage: "There were no firewalls running",
+  },
+  fileFolders: {
+    displayName: "File and Folder Issues",
+    count: 0,
+    data: [],
+    dataMessage: "The following files/folders should be removed",
+    noDataMessage: "There were no unwanted files and folders",
+  },
+  services: {
+    displayName: "Service Issues",
+    count: 0,
+    data: [],
+    dataMessage: "The following services should be stopped",
+    noDataMessage: "There were no unwanted services",
+  },
+  users: {
+    displayName: "User Issues",
+    count: 0,
+    data: [],
+    dataMessage: "The following users should be removed",
+    noDataMessage: "There were no unwanted users",
+  },
+  misc: {
+    displayName: "Misc Issues",
+    count: 0,
+    data: [],
+    dataMessage: "The following issues should be resolved",
+    noDataMessage: "There were no issues",
+  },
+  alternatives: {
+    displayName: "Alternatives Issues",
+    count: 0,
+    data: [],
+    dataMessage: "The following alternatives should be removed",
+    noDataMessage: "There were no alternative issues",
+  },
+  reverseLookup: {
+    displayName: "Reverse Lookup Issues",
+    count: 0,
+    data: [],
+    dataMessage: "The following hosts have reverse lookup issues",
+    noDataMessage: "There were no reverse DNS lookup issues",
+  },
+  hostNameResolution: {
+    displayName: "Hostname Resolution Issues",
+    count: 0,
+    data: [],
+    dataMessage: "The following hosts have hostname resolution issues",
+    noDataMessage: "There were no hostname resolution issues",
+  },
+};
+
+export const categoriesToReportMap = [
+  {
+    key: "thp",
+    label: "installer.step3.hostWarningsPopup.report.thp",
+    separator: " ",
+  },
+  {
+    key: "jdk",
+    label: "installer.step3.hostWarningsPopup.report.jdk",
+    separator: "<br>",
+  },
+  {
+    key: "disk",
+    label: "installer.step3.hostWarningsPopup.report.disk",
+    separator: "<br>",
+  },
+  {
+    key: "repositories",
+    label: "installer.step3.hostWarningsPopup.report.repositories",
+    separator: "<br>",
+  },
+  {
+    key: "hostNameResolution",
+    label: "installer.step3.hostWarningsPopup.report.hostNameResolution",
+    separator: "<br>",
+  },
+  {
+    key: "firewall",
+    label: "installer.step3.hostWarningsPopup.report.firewall",
+    separator: "<br>",
+    mapProperty: "name",
+  },
+  {
+    key: "fileFolders",
+    label: "installer.step3.hostWarningsPopup.report.fileFolders",
+    separator: " ",
+    mapProperty: "name",
+  },
+  {
+    key: "reverseLookup",
+    label: "installer.step3.hostWarningsPopup.report.reverseLookup",
+    separator: " ",
+    mapProperty: "hostsLong",
+  },
+  {
+    key: "packages",
+    label: "installer.step3.hostWarningsPopup.report.package",
+    separator: " ",
+    mapProperty: "name",
+  },
+  {
+    key: "services",
+    label: "installer.step3.hostWarningsPopup.report.service",
+    separator: " ",
+    mapProperty: "name",
+  },
+  {
+    key: "users",
+    label: "installer.step3.hostWarningsPopup.report.user",
+    separator: " ",
+    mapProperty: "name",
+  },
+];
+
+// To be moved to internationalization
+export const hostCheckReportConstants: any = {
+  "installer.step3.hostWarningsPopup.report.header":
+    '<p style="font-family: 
monospace">######################################<br># Host Checks 
Report<br>#<br># Generated: ',
+  "installer.step3.hostWarningsPopup.report.hosts":
+    
"<br>######################################<br><br>######################################<br>#
 Hosts<br>#<br># A space delimited list of hosts which have issues.<br># 
Provided so that administrators can easily copy hostnames into scripts, email 
etc.<br>######################################<br>HOSTS<br>",
+  "installer.step3.hostWarningsPopup.report.jdk":
+    "<br><br>######################################<br># JDK Check <br>#<br># 
A newline delimited list of JDK 
issues.<br>######################################<br>JDK ISSUES<br>",
+  "installer.step3.hostWarningsPopup.report.disk":
+    "<br><br>######################################<br># Disk <br>#<br># A 
newline delimited list of disk 
issues.<br>######################################<br>DISK ISSUES<br>",
+  "installer.step3.hostWarningsPopup.report.repositories":
+    "<br><br>######################################<br># Repositories 
<br>#<br># A newline delimited list of repositories 
issues.<br>######################################<br>REPOSITORIES ISSUES<br>",
+  "installer.step3.hostWarningsPopup.report.hostNameResolution":
+    "<br><br>######################################<br># Hostname 
Resolution<br>#<br># A newline delimited list of hostname resolution 
issues.<br>######################################<br>HOSTNAME RESOLUTION 
ISSUES<br>",
+  "installer.step3.hostWarningsPopup.report.thp":
+    "<br><br>######################################<br># Transparent Huge 
Pages(THP) <br>#<br># A space delimited list of hostnames on which Transparent 
Huge Pages are enabled.<br>######################################<br>THP ISSUES 
HOSTS<br>",
+  "installer.step3.hostWarningsPopup.report.firewall":
+    "<br><br>######################################<br># Firewall<br>#<br># A 
newline delimited list of firewall 
issues.<br>######################################<br>FIREWALL<br>",
+  "installer.step3.hostWarningsPopup.report.fileFolders":
+    "<br><br>######################################<br># Files and 
Folders<br>#<br># A space delimited list of files and folders which should not 
exist.<br># Provided so that administrators can easily copy paths into scripts, 
email etc.<br># Example: rm -r /etc/hadoop 
/etc/hbase<br>######################################<br>FILES AND FOLDERS<br>",
+  "installer.step3.hostWarningsPopup.report.reverseLookup":
+    "<br><br>######################################<br># Reverse Lookup<br># 
<br># The hostname was not found in the reverse DNS lookup. This may result in 
incorrect behavior. <br># Please check the DNS setup and fix the 
issue.<br>######################################<br>REVERSE LOOKUP<br>",
+  "installer.step3.hostWarningsPopup.report.process":
+    "<br><br>######################################<br># Processes<br>#<br># A 
comma separated list of process tuples which should not be running.<br># 
Provided so that administrators can easily copy paths into scripts, email 
etc.<br>######################################<br>PROCESSES<br>",
+  "installer.step3.hostWarningsPopup.report.package":
+    "<br><br>######################################<br># Packages<br>#<br># A 
space delimited list of software packages which should be uninstalled.<br># 
Provided so that administrators can easily copy paths into scripts, email 
etc.<br># Example: yum remove hadoop-hdfs 
yarn<br>######################################<br>PACKAGES<br>",
+  "installer.step3.hostWarningsPopup.report.service":
+    "<br><br>######################################<br># Services<br>#<br># A 
space delimited list of services which should be up and running.<br># Provided 
so that administrators can easily copy paths into scripts, email etc.<br># 
Example: services start ntpd 
httpd<br>######################################<br>SERVICES<br>",
+  "installer.step3.hostWarningsPopup.report.user":
+    "<br><br>######################################<br># Users<br>#<br># A 
space delimited list of users who should not exist.<br># Provided so that 
administrators can easily copy paths into scripts, email etc.<br># Example: 
userdel hdfs<br>######################################<br>USERS<br>",
+};
+
+// These fields cannot be selected again if already selected in the filter
+export const nonRepeatableHostFieldOptions = ["cpu", "memoryFormatted"];
+
+export const healthClassesForHostFilter = [
+  {
+    label: translate("hosts.host.healthStatusCategory.green"),
+    value: "HEALTHY",
+    name: "healthClass",
+  },
+  {
+    label: translate("hosts.host.healthStatusCategory.red"),
+    value: "UNHEALTHY",
+    name: "healthClass",
+  },
+  {
+    label: translate("hosts.host.healthStatusCategory.orange"),
+    value: "ALERT",
+    name: "healthClass",
+  },
+  {
+    label: translate("hosts.host.healthStatusCategory.yellow"),
+    value: "UNKNOWN",
+    name: "healthClass",
+  },
+  {
+    label: translate("hosts.host.alerts.label"),
+    value: [">0", ">0"],
+    name: "criticalWarningAlertsCount",
+  },
+  {
+    label: translate("common.restart"),
+    value: "true",
+    name: "componentsWithStaleConfigsCount",
+  },
+  {
+    label: translate("common.passive_state"),
+    value: [
+      "ON",
+      "IMPLIED_FROM_HOST",
+      "IMPLIED_FROM_SERVICE",
+      "IMPLIED_FROM_SERVICE_AND_HOST",
+    ],
+    name: "componentsInPassiveStateCount",
+  },
+];
+
+export const hostFilterProperties = [
+  {
+    name: "hostName",
+    key: "Hosts/host_name",
+    type: "MATCH",
+  },
+  {
+    name: "ip",
+    key: "Hosts/ip",
+    type: "MATCH",
+  },
+  {
+    name: "cpu",
+    key: "Hosts/cpu_count",
+    type: "EQUAL",
+    valueType: "number",
+  },
+  {
+    name: "memoryFormatted",
+    key: "Hosts/total_mem",
+    type: "EQUAL",
+    valueType: "ambari-bandwidth",
+  },
+  {
+    name: "loadAvg",
+    key: "metrics/load/load_one",
+    type: "EQUAL",
+  },
+  {
+    name: "rack",
+    key: "Hosts/rack_info",
+    type: "MATCH",
+  },
+  {
+    name: "hostComponents",
+    key: "host_components/HostRoles/component_name",
+    type: "EQUAL",
+  },
+  {
+    name: "services",
+    key: "host_components/HostRoles/service_name",
+    type: "MATCH",
+  },
+  {
+    name: "state",
+    key: "host_components/HostRoles/state",
+    type: "MATCH",
+  },
+  {
+    name: "healthClass",
+    key: "Hosts/host_status",
+    type: "EQUAL",
+  },
+  {
+    name: "criticalWarningAlertsCount",
+    key: "(alerts_summary/CRITICAL{0}|alerts_summary/WARNING{1})",
+    type: "CUSTOM",
+  },
+  {
+    name: "componentsWithStaleConfigsCount",
+    key: "host_components/HostRoles/stale_configs",
+    type: "EQUAL",
+  },
+  {
+    name: "componentsInPassiveStateCount",
+    key: "host_components/HostRoles/maintenance_state",
+    type: "MULTIPLE",
+  },
+  {
+    name: "selected",
+    key: "Hosts/host_name",
+    type: "MULTIPLE",
+  },
+  {
+    name: "version",
+    key: "stack_versions/repository_versions/RepositoryVersions/display_name",
+    type: "EQUAL",
+  },
+  {
+    name: "versionState",
+    key: "stack_versions/HostStackVersions/state",
+    type: "EQUAL",
+  },
+  {
+    name: "hostStackVersion",
+    key: "stack_versions",
+    type: "EQUAL",
+  },
+  {
+    name: "componentState",
+    key: [
+      "(host_components/HostRoles/component_name={0})",
+      
"(host_components/HostRoles/component_name={0}&host_components/HostRoles/state={1})",
+      
"(host_components/HostRoles/component_name={0}&host_components/HostRoles/desired_admin_state={1})",
+      
"(host_components/HostRoles/component_name={0}&host_components/HostRoles/maintenance_state={1})",
+    ],
+    type: "COMBO",
+  },
+];
+
+export const serviceNameToModelKeyMap: any = {
+  HDFS: "hdfs",
+  YARN: "yarn",
+  MAPREDUCE2: "mapreduce2",
+  TEZ: "tez",
+  HIVE: "hive",
+  HBASE: "hbase",
+  ZOOKEEPER: "zk",
+  AMBARI_METRICS: "ambari_metrics",
+  RANGER: "ranger",
+  RANGER_KMS: "ranger_kms",
+  KERBEROS: "kerberos",
+  SPARK3: "spark3",
+  SSM: "ssm",
+  TRINO: "trino",
+};
diff --git a/ambari-web/latest/src/screens/Hosts/helpers.ts 
b/ambari-web/latest/src/screens/Hosts/helpers.ts
new file mode 100644
index 0000000000..961352c2cc
--- /dev/null
+++ b/ambari-web/latest/src/screens/Hosts/helpers.ts
@@ -0,0 +1,109 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { get, startCase } from "lodash";
+
+const components = {
+  API: "API",
+  DECOMMISSION_DATANODE: "Update Exclude File",
+  DRPC: "DRPC",
+  FLUME_HANDLER: "Flume",
+  GLUSTERFS: "GLUSTERFS",
+  HBASE: "HBase",
+  HBASE_REGIONSERVER: "RegionServer",
+  HCAT: "HCat Client",
+  HDFS: "HDFS",
+  HISTORYSERVER: "History Server",
+  HIVE_SERVER: "HiveServer2",
+  JCE: "JCE",
+  MAPREDUCE2: "MapReduce2",
+  MYSQL: "MySQL",
+  REST: "REST",
+  SECONDARY_NAMENODE: "SNameNode",
+  STORM_REST_API: "Storm REST API Server",
+  WEBHCAT: "WebHCat",
+  YARN: "YARN",
+  UI: "UI",
+  ZKFC: "ZKFailoverController",
+  ZOOKEEPER: "ZooKeeper",
+  ZOOKEEPER_QUORUM_SERVICE_CHECK: "ZK Quorum Service Check",
+  HAWQ: "HAWQ",
+  PXF: "PXF",
+};
+
+export const normalizeName = (name: string) => {
+  if (!name || typeof name !== "string") return "";
+  if (get(components, name, "")) return get(components, name, "");
+  name = name.toLowerCase();
+  const suffixNoSpaces = ["node", "tracker", "manager"];
+  const suffixRegExp = new RegExp(`(\\w+)(${suffixNoSpaces.join("|")})`, "gi");
+  if (/_/g.test(name)) {
+    name = name
+      .split("_")
+      .map((singleName) => normalizeName(singleName.toUpperCase()))
+      .join(" ");
+  } else if (suffixRegExp.test(name)) {
+    suffixRegExp.lastIndex = 0;
+    const matches = suffixRegExp.exec(name);
+    if (matches) {
+      name =
+        startCase(matches[1].toLowerCase()) +
+        startCase(matches[2].toLowerCase());
+    }
+  }
+  return startCase(name.toLowerCase());
+};
+
+export const normalizeNameBySeparators = (
+  name: string,
+  separators: string[]
+) => {
+  if (!name || typeof name !== "string") return "";
+  name = name.toLowerCase();
+  if (!separators || separators.length === 0) {
+    separators = ["_"];
+  }
+
+  for (const separator of separators) {
+    if (new RegExp(separator, "g").test(name)) {
+      name = name
+        .split(separator)
+        .map((singleName) => {
+          return normalizeName(singleName.toUpperCase());
+        })
+        .join(" ");
+      break;
+    }
+  }
+  return startCase(name.toLowerCase());
+};
+
+export const sortPropertyLight = (data: any[], path: any) => {
+  const realPath = typeof path === "string" ? path.split('.') : [];
+  return data.sort((a, b) => {
+    let aProperty: any = a;
+    let bProperty: any = b;
+    realPath.forEach((key) => {
+      aProperty = aProperty[key];
+      bProperty = bProperty[key];
+    });
+    if (aProperty > bProperty) return 1;
+    if (aProperty < bProperty) return -1;
+    return 0;
+  });
+}
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to