Skip to content

HIVE-29685: Fix LLAP UI status for non-YARN deployments - #6656

Open
Manya0407 wants to merge 4 commits into
apache:masterfrom
Manya0407:HIVE-29685-llap-ui-registry-status
Open

HIVE-29685: Fix LLAP UI status for non-YARN deployments#6656
Manya0407 wants to merge 4 commits into
apache:masterfrom
Manya0407:HIVE-29685-llap-ui-registry-status

Conversation

@Manya0407

@Manya0407 Manya0407 commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

1.This PR fixes the HiveServer2 LLAP status page (/llap.html, backed by GET /llap) on non-YARN deployments such as Kubernetes and Docker. Today LlapServlet delegates to LlapStatusServiceDriver, which only queries YARN for the LLAP application. On K8s/Docker, LLAP daemons register in ZooKeeper instead of YARN, so the driver returns APP_NOT_FOUND and the UI never shows running instances.
2.The main change is config-based routing in LlapStatusServiceDriver: when the deployment is detected as non-YARN (via hive.server2.tez.use.external.sessions=true, tez.am.framework.mode=STANDALONE_ZOOKEEPER, or the override hive.llapcli.status.use-registry), status is populated from the LLAP ZK registry instead of YARN. For those deployments, worker UUIDs are used as container IDs when YARN container IDs are absent. The YARN path is unchanged for classic YARN LLAP.
3.This PR also fixes runningThresholdAchieved not being set for servlet/one-shot callers by calling updateRunningThresholdAchieved() after a successful registry or YARN status lookup. LlapServlet now returns HTTP 500 when status lookup fails. On the UI side, it removes references to missing boolean PNG assets in llap.js, adds a defensive guard in json.human.js so bool icons are only rendered for valid /static/ paths, and adds cache-buster query params in llap.html. Unit tests are added in TestLlapStatus

Why are the changes needed?

On Kubernetes and Docker, LLAP does not run as a YARN application. Daemons register in ZooKeeper, but the status driver only looked up YARN and returned early with APP_NOT_FOUND before consulting the registry. That broke /llap.html for operators running LLAP on K8s/Docker — they could not see cluster state, instance counts, or daemon web URLs from HiveServer2.
The runningThresholdAchieved field was also never set for the servlet path, so the UI always showed false even when all daemons were up. The broken boolean icon beside runningThresholdAchieved is a separate pre-existing UI bug (missing PNG assets since HIVE-13467); this PR fixes that as well so the page renders cleanly.

Does this PR introduce any user-facing change?

Yes. On non-YARN LLAP deployments, /llap.html and GET /llap now report the correct state (RUNNING_ALL / RUNNING_PARTIAL instead of APP_NOT_FOUND), show live instance counts and daemon web URLs from the registry, and set runningThresholdAchieved to true when the running threshold is met. On YARN LLAP deployments, behavior is unchanged. When status lookup fails, the servlet returns HTTP 500 instead of 200 with incomplete JSON. The LLAP UI no longer shows a broken image icon before boolean fields; it displays plain true/false text instead.

Before :
image

After:
image

How was this patch tested?

1.Unit tests were added in TestLlapStatusRegistryFallback.java covering registry instance creation (worker identity vs YARN container ID), state updates from instance counts, config-based detection of registry vs YARN status lookup, and runningThresholdAchieved logic. These were run with mvn test -pl llap-server -Dtest=TestLlapStatusRegistryFallback.
2.End-to-end testing used the Docker LLAP stack in packaging/src/docker/ with ./start-hive.sh --llap and a locally built apache/hive:4.3.0-SNAPSHOT image

@sonarqubecloud

Copy link
Copy Markdown

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes the HiveServer2 LLAP status endpoint/UI (GET /llap and /llap.html) for non-YARN deployments (e.g., Kubernetes/Docker) by routing status discovery to the LLAP ZooKeeper registry when appropriate, while keeping the existing YARN path intact. It also cleans up the UI’s boolean rendering behavior and adds unit coverage for the new registry-based helpers.

Changes:

  • Add config-based routing in LlapStatusServiceDriver to populate status from the LLAP registry for non-YARN deployments, including running-threshold updates.
  • Harden/adjust LLAP UI rendering (avoid missing boolean PNG assets; add cache-busting query params).
  • Add unit tests covering registry fallback behavior and helper logic.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
service/src/resources/hive-webapps/static/js/llap.js Disables boolean image rendering for LLAP UI JSON viewer options.
service/src/resources/hive-webapps/static/js/json.human.js Adds defensive checks around boolean image rendering (path validation) and disables images when invalid.
service/src/resources/hive-webapps/hiveserver2/llap.html Adds cache-buster query params for JS assets.
service/src/java/org/apache/hive/http/LlapServlet.java Returns HTTP 500 when LLAP status lookup fails (instead of 200 with incomplete JSON).
llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/LlapStatusServiceDriver.java Implements registry-based status path + shared helpers; ensures runningThresholdAchieved is computed after successful lookups.
llap-server/src/test/org/apache/hadoop/hive/llap/cli/status/TestLlapStatusRegistryFallback.java Adds unit tests for registry-only instance creation, state computation, config detection, and running-threshold logic.
Suppressed comments (1)

service/src/resources/hive-webapps/static/js/json.human.js:445

  • Using String.prototype.startsWith here can break option validation in older browsers that don't support it (e.g., IE 11). Use an ES5-safe prefix check so the bool image option handling doesn't throw at runtime.
            if(boolOptions.showImage){
                if(!boolOptions.img || !boolOptions.img.true || !boolOptions.img.false
                    || !('' + boolOptions.img.true).startsWith('/static/')
                    || !('' + boolOptions.img.false).startsWith('/static/')){
                    boolOptions.showImage = false;

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines 73 to +74
private static final EnumSet<State> NO_YARN_SERVICE_INFO_STATES = EnumSet.of(
State.APP_NOT_FOUND, State.COMPLETE, State.LAUNCHING);
State.COMPLETE, State.LAUNCHING);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added an explicit early return when state is APP_NOT_FOUND on the YARN path, so we don’t continue into YARN Service/registry calls. K8s/Docker still uses the registry-only path via usesRegistryBasedLlapStatus() at the top of run().

Comment on lines +141 to +143
if (boolOpt.showImage && boolOpt.img && boolOpt.img.true && boolOpt.img.false
&& ('' + boolOpt.img.true).startsWith('/static/')
&& ('' + boolOpt.img.false).startsWith('/static/')) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced .startsWith('/static/') with .indexOf('/static/') === 0 in both places for IE11 compatibility.

Comment on lines 101 to 105
if (ret == ExitCode.SUCCESS) {
driver.outputJson(writer);
} else {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added Cache-Control: no-store on the error path so proxies don’t cache failed status responses.

Comment on lines +246 to +247
if (NO_YARN_SERVICE_INFO_STATES.contains(appStatusBuilder.getState())) {
updateRunningThresholdAchieved(appStatusBuilder, cl.getRunningNodesThreshold());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is updateRunningThresholdAchieved call needed here? This condition should be true only when state is Complete or Launching, but i believe in that case updateRunningThresholdAchieved just returns ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call was a no-op here since the method only acts on RUNNING_PARTIAL/RUNNING_ALL. Removed it.

Comment on lines +426 to +429
private ExitCode populateAppStatusFromLlapRegistry(AppStatusBuilder appStatusBuilder, long watchTimeoutMs)
throws LlapStatusCliException {
return populateAppStatusFromLlapRegistry(appStatusBuilder, watchTimeoutMs, false);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is no usages of this old definition, i think it can be removed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the unused 2-arg wrapper; run() calls the 3-arg version directly.

ManyaMehrotra added 2 commits August 31, 2026 15:07
…r YARN path, remove dead code,

set no-store on servlet errors, and use IE11-safe path checks in json.human.js.
Comment on lines +18 to +19
<script src="/static/js/json.human.js?v=1"></script>
<script src="/static/js/llap.js?v=2"></script>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason for this change?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added ?v= during testing because browsers kept serving old cached llap.js/json.human.js (still pointing at missing PNGs), so the UI looked broken until a hard refresh. It's a standard cache-bust for upgrades — doesn't break anything or change how caching works.

That said, the actual fix is in the JS changes, so it's optional. As Per feedback I've removed the cache-busting params in the latest push

}
} catch (Exception e) {
LOG.error("Caught exception while processing llap status request", e);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we consider adding same Cache-Control: no-store in case of error here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added Cache-Control: no-store in the catch block as well, same as the non-success path.

@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants