Skip to content

Conversation

@shwstppr
Copy link
Contributor

@shwstppr shwstppr commented Nov 12, 2025

Description

This PR introduces a WebSocket framework, enabling flexible configuration and management of WebSocket server and contexts.
The framework allows WebSocket services to run either as:

  • Standalone server: A new Netty-based implementation, suitable for dedicated WebSocket routing and scalability.
  • Embedded mode (same port as API server): Integration within the existing Jetty server, extending current servlet-based behaviour.

The first implementation built on this framework is the Logs Web Session, which allows ROOT administrators to securely stream and view logs in real-time via the UI, tied to specific API calls or actions.

Key Features

  • Adds a generic framework to initialize and configure WebSocket server and contexts.
  • Supports both Jetty (embedded) and Netty (standalone) modes.
  • Introduces a Logs WebSocket session handler to stream management server logs for API calls.
  • Enhances the UI to display live logs for ROOT admins through authenticated WebSocket connections.
  • Provides configuration flexibility for enabling/disabling WebSocket modes.

Types of changes

  • Breaking change (fix or feature that would cause existing functionality to change)
  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Enhancement (improves an existing feature and functionality)
  • Cleanup (Code refactoring and cleanup, that may add test cases)
  • Build/CI
  • Test (unit or integration test code)

Feature/Enhancement Scale or Bug Severity

Feature/Enhancement Scale

  • Major
  • Minor

Bug Severity

  • BLOCKER
  • Critical
  • Major
  • Minor
  • Trivial

Screenshots (if appropriate):

How Has This Been Tested?

How did you try to break this feature and the system with this change?

This feature enables administrators to view management server logs directly in the UI through a dedicated API call. It leverages a Netty-based websocket server to stream logs in real time, offering an efficient way to monitor and debug server operations. Note that the plugin is disabled by default and must be enabled manually.

Signed-off-by: Abhishek Kumar <[email protected]>
Signed-off-by: Abhishek Kumar <[email protected]>
Signed-off-by: Abhishek Kumar <[email protected]>
@codecov
Copy link

codecov bot commented Nov 12, 2025

Codecov Report

❌ Patch coverage is 2.33766% with 1504 lines in your changes missing coverage. Please review.
✅ Project coverage is 17.52%. Comparing base (dc8f465) to head (d4b9d57).
⚠️ Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
...e/cloudstack/logsws/LogsWebSessionManagerImpl.java 3.60% 213 Missing and 1 partial ⚠️
...ack/logsws/server/LogsWebSocketRoutingHandler.java 0.00% 132 Missing ⚠️
...loudstack/logsws/LogsWebSessionApiServiceImpl.java 0.00% 122 Missing ⚠️
.../apache/cloudstack/logsws/server/LogsStreamer.java 0.00% 105 Missing ⚠️
...ework/websocket/server/common/WebSocketRouter.java 0.00% 97 Missing ⚠️
...ket/server/manager/WebSocketServerManagerImpl.java 0.00% 88 Missing ⚠️
...ebsocket/server/WebSocketServerRoutingHandler.java 0.00% 78 Missing ⚠️
.../apache/cloudstack/logsws/vo/LogsWebSessionVO.java 0.00% 77 Missing ⚠️
...ck/framework/websocket/server/WebSocketServer.java 0.00% 73 Missing ⚠️
...e/cloudstack/logsws/dao/LogsWebSessionDaoImpl.java 0.00% 52 Missing ⚠️
... and 28 more
Additional details and impacted files
@@             Coverage Diff              @@
##               main   #12053      +/-   ##
============================================
- Coverage     17.56%   17.52%   -0.05%     
- Complexity    15539    15546       +7     
============================================
  Files          5911     5940      +29     
  Lines        529359   531063    +1704     
  Branches      64655    64822     +167     
============================================
+ Hits          92979    93043      +64     
- Misses       425922   427554    +1632     
- Partials      10458    10466       +8     
Flag Coverage Δ
uitests 3.61% <ø> (+0.02%) ⬆️
unittests 18.58% <2.33%> (-0.05%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Signed-off-by: Abhishek Kumar <[email protected]>
Signed-off-by: Abhishek Kumar <[email protected]>
@shwstppr
Copy link
Contributor Author

@blueorangutan package

@blueorangutan
Copy link

@shwstppr a [SL] Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.

@blueorangutan
Copy link

Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 15730

@shwstppr
Copy link
Contributor Author

@blueorangutan package

@blueorangutan
Copy link

@shwstppr a [SL] Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.

@blueorangutan
Copy link

Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✖️ debian ✔️ suse15. SL-JID 15742

@shwstppr shwstppr requested a review from Copilot November 13, 2025 14:11
Copy link
Contributor

Copilot AI left a comment

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 introduces a comprehensive WebSocket server framework enabling both standalone (Netty-based) and embedded (Jetty-based) WebSocket server modes. The first implementation provides a Logs Web Session feature allowing ROOT administrators to securely stream and view management server logs in real-time via the UI.

Key changes:

  • New WebSocket framework with flexible server configuration (standalone/embedded modes)
  • Logs Web Session API and UI for real-time log streaming with filtering
  • Database schema additions for session and management server configuration storage

Reviewed Changes

Copilot reviewed 88 out of 88 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
framework/websocket-server/* Core WebSocket server framework with Netty implementation and router
plugins/logs-web-server/* Logs web session plugin with API, streaming, and session management
ui/src/components/view/LogsConsole.vue New UI component for displaying real-time logs with filtering
ui/src/utils/plugins.js Enhanced job polling with log viewing capabilities
engine/schema/.../schema-42200to42300.sql Database schema for logs sessions and management server details
client/src/main/java/.../ServerDaemon.java Jetty server integration for embedded WebSocket support
server/src/main/java/.../ManagementServerImpl.java Management server capabilities and configuration updates

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


public class LogsWebSessionTokenCryptoUtil {
private static final String ALGORITHM = "AES";
private static final String TRANSFORMATION = "AES";
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

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

Weak encryption: Using AES in ECB mode (default when only "AES" is specified as transformation) is insecure as it doesn't use an initialization vector. Consider using "AES/GCM/NoPadding" or "AES/CBC/PKCS5Padding" with a random IV for better security.

Copilot uses AI. Check for mistakes.
export const pollJobPlugin = {
install (app) {
function canViewLogs (logIds) {
console.log('canViewLogs', store.getters.features.logswebserverenabled, 'createLogsWebSession' in store.getters.apis, logIds, logIds && logIds.length > 0)
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

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

Console.log statement should be removed from production code. This debug logging can expose sensitive information and impact performance.

Copilot uses AI. Check for mistakes.
if (result.logids) {
allLogIds.push(...result.logids)
}
console.log('pollJobPlugin', result.logids, allLogIds)
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

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

Console.log statement should be removed from production code. Debug logging should use proper logging mechanisms instead of console.log.

Copilot uses AI. Check for mistakes.
}
},
created () {
console.log('---------------', this.$route.meta.name)
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

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

Console.log statement should be removed from production code. This appears to be debug code that was left in.

Copilot uses AI. Check for mistakes.
CREATE TABLE IF NOT EXISTS `cloud`.`logs_web_session` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id of the session',
`uuid` varchar(40) NOT NULL COMMENT 'UUID generated for the session',
`filter` varchar(64) DEFAULT NULL COMMENT 'Filter keyword for the session',
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

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

The field name in the database schema is 'filter' (singular) but the converter is used for a List. This should be 'filters' (plural) to match the Java field name and be semantically correct. The SQL definition on line 38 should use filters instead of filter.

Suggested change
`filter` varchar(64) DEFAULT NULL COMMENT 'Filter keyword for the session',
`filters` varchar(64) DEFAULT NULL COMMENT 'Filter keywords for the session',

Copilot uses AI. Check for mistakes.
return null;
}
String keystoreFile = ServerPropertiesUtil.getProperty(ServerPropertiesUtil.KEY_KEYSTORE_FILE);
String keystorePassword = ServerPropertiesUtil.getProperty(ServerPropertiesUtil.KEY_KEYSTORE_FILE);
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

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

Wrong property key is being used. Line 127 should retrieve KEY_KEYSTORE_PASSWORD but it's retrieving KEY_KEYSTORE_FILE again. This will cause SSL context creation to fail as it will use the keystore file path as the password.

Suggested change
String keystorePassword = ServerPropertiesUtil.getProperty(ServerPropertiesUtil.KEY_KEYSTORE_FILE);
String keystorePassword = ServerPropertiesUtil.getProperty(ServerPropertiesUtil.KEY_KEYSTORE_PASSWORD);

Copilot uses AI. Check for mistakes.
if (StringUtils.isBlank(keystoreFile) || StringUtils.isBlank(keystorePassword)) {
throw new IllegalArgumentException("SSL is enabled but keystore file or password is not configured");
}
if (Files.exists(Path.of(keystoreFile))) {
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

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

Inverted logic: the condition checks Files.exists(...) but the error message says "does not exist". This should be !Files.exists(Path.of(keystoreFile)) to correctly validate that the keystore file exists.

Suggested change
if (Files.exists(Path.of(keystoreFile))) {
if (!Files.exists(Path.of(keystoreFile))) {

Copilot uses AI. Check for mistakes.
<div
v-if="showRawLogs"
class="content"
v-html="webSocketData">
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

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

Potential XSS vulnerability: HTML content is rendered using v-html without sanitization. The webSocketData contains unsanitized log data that could include malicious scripts. Consider using a library like DOMPurify to sanitize the HTML before rendering, or avoid using v-html altogether.

Copilot uses AI. Check for mistakes.
Signed-off-by: Abhishek Kumar <[email protected]>
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.

2 participants