Skip to content

Commit a5865bf

Browse files
committed
api,server,schema,plugin,client: logs web server
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 <abhishek.mrt22@gmail.com>
1 parent 8c86f24 commit a5865bf

45 files changed

Lines changed: 2787 additions & 35 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

api/src/main/java/org/apache/cloudstack/api/ApiConstants.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ public class ApiConstants {
9898
public static final String CONVERT_INSTANCE_HOST_ID = "convertinstancehostid";
9999
public static final String CONVERT_INSTANCE_STORAGE_POOL_ID = "convertinstancepoolid";
100100
public static final String ENABLED_REVOCATION_CHECK = "enabledrevocationcheck";
101-
public static final String CLIENT_ADDRESS = "clientaddress";
102101
public static final String COMBINED_CAPACITY_ORDERING = "COMBINED";
102+
public static final String CONTEXT_ID = "contextid";
103103
public static final String CONTROLLER = "controller";
104104
public static final String CONTROLLER_UNIT = "controllerunit";
105105
public static final String CONSOLE_ENDPOINT_CREATOR_ADDRESS = "consoleendpointcreatoraddress";
@@ -124,6 +124,7 @@ public class ApiConstants {
124124
public static final String DEST_CIDR_LIST = "destcidrlist";
125125
public static final String CLEANUP = "cleanup";
126126
public static final String MAKEREDUNDANT = "makeredundant";
127+
public static final String CLIENT_ADDRESS = "clientaddress";
127128
public static final String CLUSTER_ID = "clusterid";
128129
public static final String CLUSTER_IDS = "clusterids";
129130
public static final String CLUSTER_NAME = "clustername";
@@ -137,12 +138,14 @@ public class ApiConstants {
137138
public static final String CNI_CONFIG_NAME = "cniconfigname";
138139
public static final String CSI_ENABLED = "csienabled";
139140
public static final String COMPONENT = "component";
141+
public static final String CONNECTED = "connected";
140142
public static final String CPU = "CPU";
141143
public static final String CPU_CORE_PER_SOCKET = "cpucorepersocket";
142144
public static final String CPU_NUMBER = "cpunumber";
143145
public static final String CPU_SPEED = "cpuspeed";
144146
public static final String CPU_LOAD_AVERAGE = "cpuloadaverage";
145147
public static final String CREATED = "created";
148+
public static final String CREATOR_ADDRESS = "creatoraddress";
146149
public static final String CROSS_ZONE_INSTANCE_CREATION = "crosszoneinstancecreation";
147150
public static final String CTX_ACCOUNT_ID = "ctxaccountid";
148151
public static final String CTX_DETAILS = "ctxDetails";
@@ -161,6 +164,7 @@ public class ApiConstants {
161164
public static final String ENCRYPT_ROOT = "encryptroot";
162165
public static final String ENCRYPTION_SUPPORTED = "encryptionsupported";
163166
public static final String ETCD_IPS = "etcdips";
167+
public static final String FILTERS = "filters";
164168
public static final String MIN_IOPS = "miniops";
165169
public static final String MAX_IOPS = "maxiops";
166170
public static final String HYPERVISOR_SNAPSHOT_RESERVE = "hypervisorsnapshotreserve";
@@ -1312,6 +1316,8 @@ public class ApiConstants {
13121316
public static final String WEBHOOK_ID = "webhookid";
13131317
public static final String WEBHOOK_NAME = "webhookname";
13141318

1319+
public static final String WEBSOCKET = "websocket";
1320+
13151321
public static final String NFS_MOUNT_OPTIONS = "nfsmountopts";
13161322
public static final String MOUNT_OPTIONS = "mountopts";
13171323

@@ -1328,6 +1334,8 @@ public class ApiConstants {
13281334
public static final String OBJECT_STORAGE_LIMIT = "objectstoragelimit";
13291335
public static final String OBJECT_STORAGE_TOTAL = "objectstoragetotal";
13301336

1337+
public static final String LOGS_WEB_SERVER_ENABLED = "logswebserverenabled";
1338+
13311339
public static final String PARAMETER_DESCRIPTION_ACTIVATION_RULE = "Quota tariff's activation rule. It can receive a JS script that results in either " +
13321340
"a boolean or a numeric value: if it results in a boolean value, the tariff value will be applied according to the result; if it results in a numeric value, the " +
13331341
"numeric value will be applied; if the result is neither a boolean nor a numeric value, the tariff will not be applied. If the rule is not informed, the tariff " +

api/src/main/java/org/apache/cloudstack/api/BaseResponse.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ public abstract class BaseResponse implements ResponseObject {
3232
@Param(description = "the current status of the latest async job acting on this object")
3333
private Integer jobStatus;
3434

35+
@SerializedName(ApiConstants.CONTEXT_ID)
36+
@Param(description = "the ID of the executing context")
37+
private String contextId;
38+
3539
public BaseResponse() {
3640
}
3741

@@ -83,4 +87,14 @@ public Integer getJobStatus() {
8387
public void setJobStatus(Integer jobStatus) {
8488
this.jobStatus = jobStatus;
8589
}
90+
91+
@Override
92+
public String getContextId() {
93+
return contextId;
94+
}
95+
96+
@Override
97+
public void setContextId(String contextId) {
98+
this.contextId = contextId;
99+
}
86100
}

api/src/main/java/org/apache/cloudstack/api/ResponseObject.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ public interface ResponseObject {
7676
*/
7777
void setJobStatus(Integer jobStatus);
7878

79+
String getContextId();
80+
void setContextId(String contextId);
81+
7982
public enum ResponseView {
8083
Full,
8184
Restricted

api/src/main/java/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ public void execute() {
7676
response.setExtensionsPath((String)capabilities.get(ApiConstants.EXTENSIONS_PATH));
7777
response.setDynamicScalingEnabled((Boolean) capabilities.get(ApiConstants.DYNAMIC_SCALING_ENABLED));
7878
response.setAdditionalConfigEnabled((Boolean) capabilities.get(ApiConstants.ADDITONAL_CONFIG_ENABLED));
79+
response.setLogsWebServerEnabled((Boolean)capabilities.get(ApiConstants.LOGS_WEB_SERVER_ENABLED));
7980
response.setObjectName("capability");
8081
response.setResponseName(getCommandName());
8182
this.setResponseObject(response);

api/src/main/java/org/apache/cloudstack/api/response/CapabilitiesResponse.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,10 @@ public class CapabilitiesResponse extends BaseResponse {
153153
@Param(description = "true if additional configurations or extraconfig can be passed to Instances", since = "4.20.2")
154154
private Boolean additionalConfigEnabled;
155155

156+
@SerializedName(ApiConstants.LOGS_WEB_SERVER_ENABLED)
157+
@Param(description = "true if Logs Web Server plugin is enabled, false otherwise", since = "4.21.0")
158+
private boolean logsWebServerEnabled;
159+
156160
public void setSecurityGroupsEnabled(boolean securityGroupsEnabled) {
157161
this.securityGroupsEnabled = securityGroupsEnabled;
158162
}
@@ -279,5 +283,10 @@ public void setDynamicScalingEnabled(Boolean dynamicScalingEnabled) {
279283

280284
public void setAdditionalConfigEnabled(Boolean additionalConfigEnabled) {
281285
this.additionalConfigEnabled = additionalConfigEnabled;
286+
287+
}
288+
289+
public void setLogsWebServerEnabled(boolean logsWebServerEnabled) {
290+
this.logsWebServerEnabled = logsWebServerEnabled;
282291
}
283292
}

client/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,11 @@
246246
<artifactId>cloud-plugin-user-two-factor-authenticator-staticpin</artifactId>
247247
<version>${project.version}</version>
248248
</dependency>
249+
<dependency>
250+
<groupId>org.apache.cloudstack</groupId>
251+
<artifactId>cloud-plugin-logs-web-server</artifactId>
252+
<version>${project.version}</version>
253+
</dependency>
249254
<dependency>
250255
<groupId>org.apache.cloudstack</groupId>
251256
<artifactId>cloud-plugin-metrics</artifactId>
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.apache.cloudstack.util;
19+
20+
import com.fasterxml.jackson.core.JsonProcessingException;
21+
import com.fasterxml.jackson.databind.ObjectMapper;
22+
import javax.persistence.AttributeConverter;
23+
import javax.persistence.Converter;
24+
import java.io.IOException;
25+
import java.util.List;
26+
27+
@Converter
28+
public class StringListJsonConverter implements AttributeConverter<List<String>, String> {
29+
30+
private static final ObjectMapper mapper = new ObjectMapper();
31+
32+
@Override
33+
public String convertToDatabaseColumn(List<String> attribute) {
34+
try {
35+
return attribute == null ? null : mapper.writeValueAsString(attribute);
36+
} catch (JsonProcessingException e) {
37+
throw new IllegalArgumentException("Error converting list to JSON", e);
38+
}
39+
}
40+
41+
@Override
42+
public List<String> convertToEntityAttribute(String dbData) {
43+
try {
44+
return dbData == null ? null : mapper.readValue(dbData, List.class);
45+
} catch (IOException e) {
46+
throw new IllegalArgumentException("Error converting JSON to list", e);
47+
}
48+
}
49+
}
50+

engine/schema/src/main/resources/META-INF/db/schema-42010to42100-cleanup.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,5 @@
1818
--;
1919
-- Schema upgrade cleanup from 4.20.1.0 to 4.21.0.0
2020
--;
21+
22+
DROP TABLE IF EXISTS `cloud`.`logs_web_session`;

engine/schema/src/main/resources/META-INF/db/schema-42010to42100.sql

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ SET `sort_key` = CASE
208208
END;
209209
-- End: Changes for Guest OS category cleanup
210210

211+
<<<<<<< HEAD
211212
-- Update description for configuration: host.capacityType.to.order.clusters
212213
UPDATE `cloud`.`configuration` SET
213214
`description` = 'The host capacity type (CPU, RAM or COMBINED) is used by deployment planner to order clusters during VM resource allocation'
@@ -757,3 +758,19 @@ SET `cs`.`domain_id` = (
757758

758759
-- Re-apply VPC: update default network offering for vpc tier to conserve_mode=1 (#8309)
759760
UPDATE `cloud`.`network_offerings` SET conserve_mode = 1 WHERE name = 'DefaultIsolatedNetworkOfferingForVpcNetworks';
761+
762+
-- Create table for logs web session
763+
CREATE TABLE IF NOT EXISTS `cloud`.`logs_web_session` (
764+
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
765+
`uuid` varchar(40) NOT NULL COMMENT 'UUID generated for the session',
766+
`filter` varchar(64) DEFAULT NULL COMMENT 'Filter keyword for the session',
767+
`created` datetime NOT NULL COMMENT 'When the session was created',
768+
`domain_id` bigint(20) unsigned NOT NULL COMMENT 'Domain of the account who generated the session',
769+
`account_id` bigint(20) unsigned NOT NULL COMMENT 'Account who generated the session',
770+
`creator_address` VARCHAR(45) DEFAULT NULL COMMENT 'Address of the creator of the session',
771+
`connections` int unsigned NOT NULL DEFAULT 0 COMMENT 'Number of connections for the session',
772+
`connected_time` datetime DEFAULT NULL COMMENT 'When the session was connected',
773+
`client_address` VARCHAR(45) DEFAULT NULL COMMENT 'Address of the client that connected to the session',
774+
`removed` datetime COMMENT 'When the session was removed/used',
775+
CONSTRAINT `uc_logs_web_session__uuid` UNIQUE (`uuid`)
776+
);

plugins/logs-web-server/pom.xml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<!--
2+
Licensed to the Apache Software Foundation (ASF) under one
3+
or more contributor license agreements. See the NOTICE file
4+
distributed with this work for additional information
5+
regarding copyright ownership. The ASF licenses this file
6+
to you under the Apache License, Version 2.0 (the
7+
"License"); you may not use this file except in compliance
8+
with the License. You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing,
13+
software distributed under the License is distributed on an
14+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
KIND, either express or implied. See the License for the
16+
specific language governing permissions and limitations
17+
under the License.
18+
-->
19+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
21+
<modelVersion>4.0.0</modelVersion>
22+
<artifactId>cloud-plugin-logs-web-server</artifactId>
23+
<name>Apache CloudStack Plugin - Logs Web Server</name>
24+
<parent>
25+
<groupId>org.apache.cloudstack</groupId>
26+
<artifactId>cloudstack-plugins</artifactId>
27+
<version>4.21.0.0-SNAPSHOT</version>
28+
<relativePath>../pom.xml</relativePath>
29+
</parent>
30+
<dependencies>
31+
<dependency>
32+
<groupId>org.apache.cloudstack</groupId>
33+
<artifactId>cloud-api</artifactId>
34+
<version>${project.version}</version>
35+
</dependency>
36+
<dependency>
37+
<groupId>io.netty</groupId>
38+
<artifactId>netty-all</artifactId>
39+
</dependency>
40+
</dependencies>
41+
</project>

0 commit comments

Comments
 (0)