From 2125470298e69d30bd454b2b86048d0747e9e8f8 Mon Sep 17 00:00:00 2001 From: lilai Date: Thu, 19 Dec 2024 14:58:13 +0800 Subject: [PATCH] support dynamic install external agent by Sermant Backend Signed-off-by: lilai --- .../entity/heartbeat/ExternalAgentInfo.java | 56 +++++++++++ .../entity/heartbeat/HeartbeatMessage.java | 12 ++- .../entity/hotplugging/CommandType.java | 7 +- .../entity/hotplugging/HotPluggingConfig.java | 5 + .../backend/service/HotPluggingService.java | 15 ++- .../src/main/resources/application.properties | 4 +- .../frontend/src/composables/translations.ts | 38 ++++++-- .../webapp/frontend/src/views/EventsView.vue | 6 +- .../frontend/src/views/InstancesView.vue | 94 ++++++++++++++----- .../heartbeat/ExternalAgentInfoTest.java | 65 +++++++++++++ 10 files changed, 264 insertions(+), 38 deletions(-) create mode 100644 sermant-backend/src/main/java/io/sermant/backend/entity/heartbeat/ExternalAgentInfo.java create mode 100644 sermant-backend/src/test/java/io/sermant/backend/entity/heartbeat/ExternalAgentInfoTest.java diff --git a/sermant-backend/src/main/java/io/sermant/backend/entity/heartbeat/ExternalAgentInfo.java b/sermant-backend/src/main/java/io/sermant/backend/entity/heartbeat/ExternalAgentInfo.java new file mode 100644 index 0000000000..b540b8eee3 --- /dev/null +++ b/sermant-backend/src/main/java/io/sermant/backend/entity/heartbeat/ExternalAgentInfo.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2024-2024 Sermant Authors. All rights reserved. + * + * Licensed 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. + */ + +package io.sermant.backend.entity.heartbeat; + +/** + * Information of external agent + * + * @author lilai + * @since 2024-12-18 + */ +public class ExternalAgentInfo { + private String name; + + private String version; + + /** + * constructor + * + * @param name agent name + * @param version agent version + */ + public ExternalAgentInfo(String name, String version) { + this.name = name; + this.version = version; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } +} diff --git a/sermant-backend/src/main/java/io/sermant/backend/entity/heartbeat/HeartbeatMessage.java b/sermant-backend/src/main/java/io/sermant/backend/entity/heartbeat/HeartbeatMessage.java index e468bddf00..e158345af8 100644 --- a/sermant-backend/src/main/java/io/sermant/backend/entity/heartbeat/HeartbeatMessage.java +++ b/sermant-backend/src/main/java/io/sermant/backend/entity/heartbeat/HeartbeatMessage.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (C) 2022-2024 Huawei Technologies Co., Ltd. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -54,6 +54,8 @@ public class HeartbeatMessage { private Map pluginInfoMap = new HashMap<>(); + private Map externalAgentInfoMap = new HashMap<>(); + private String appName; private String artifact; @@ -186,4 +188,12 @@ public void setDynamicInstall(boolean dynamicInstall) { public void setProcessId(String processId) { this.processId = processId; } + + public Map getExternalAgentInfoMap() { + return externalAgentInfoMap; + } + + public void setExternalAgentInfoMap(Map externalAgentInfoMap) { + this.externalAgentInfoMap = externalAgentInfoMap; + } } diff --git a/sermant-backend/src/main/java/io/sermant/backend/entity/hotplugging/CommandType.java b/sermant-backend/src/main/java/io/sermant/backend/entity/hotplugging/CommandType.java index 0dc4188bef..bb77a6c798 100644 --- a/sermant-backend/src/main/java/io/sermant/backend/entity/hotplugging/CommandType.java +++ b/sermant-backend/src/main/java/io/sermant/backend/entity/hotplugging/CommandType.java @@ -34,7 +34,12 @@ public enum CommandType { /** * Uninstall plugin instruction */ - UNINSTALL_PLUGINS("UNINSTALL-PLUGINS"); + UNINSTALL_PLUGINS("UNINSTALL-PLUGINS"), + + /** + * Install external agent instruction + */ + INSTALL_EXTERNAL_AGENT("INSTALL-EXTERNAL-AGENT"); private final String value; diff --git a/sermant-backend/src/main/java/io/sermant/backend/entity/hotplugging/HotPluggingConfig.java b/sermant-backend/src/main/java/io/sermant/backend/entity/hotplugging/HotPluggingConfig.java index 0ba81b688b..0a87b69cab 100644 --- a/sermant-backend/src/main/java/io/sermant/backend/entity/hotplugging/HotPluggingConfig.java +++ b/sermant-backend/src/main/java/io/sermant/backend/entity/hotplugging/HotPluggingConfig.java @@ -33,6 +33,11 @@ public class HotPluggingConfig { */ private String pluginNames; + /** + * External agent name + */ + private String externalAgentName; + /** * JavaAgent Path */ diff --git a/sermant-backend/src/main/java/io/sermant/backend/service/HotPluggingService.java b/sermant-backend/src/main/java/io/sermant/backend/service/HotPluggingService.java index 6b29d6a486..4ae836e8e5 100644 --- a/sermant-backend/src/main/java/io/sermant/backend/service/HotPluggingService.java +++ b/sermant-backend/src/main/java/io/sermant/backend/service/HotPluggingService.java @@ -78,7 +78,18 @@ public Result publishHotPluggingConfig(HotPluggingConfig hotPluggingCon * @return verification results */ private boolean validateParam(HotPluggingConfig hotPluggingConfig) { - return StringUtils.isNotEmpty(hotPluggingConfig.getPluginNames()) - || !commandTypeSet.contains(hotPluggingConfig.getCommandType()); + if (!commandTypeSet.contains(hotPluggingConfig.getCommandType())) { + return false; + } + + if (CommandType.INSTALL_EXTERNAL_AGENT.getValue().equals(hotPluggingConfig.getCommandType())) { + if (StringUtils.isEmpty(hotPluggingConfig.getAgentPath()) || StringUtils.isEmpty( + hotPluggingConfig.getExternalAgentName())) { + return false; + } + return true; + } else { + return StringUtils.isNotEmpty(hotPluggingConfig.getPluginNames()); + } } } diff --git a/sermant-backend/src/main/resources/application.properties b/sermant-backend/src/main/resources/application.properties index 2c7a94822a..700db3dd85 100644 --- a/sermant-backend/src/main/resources/application.properties +++ b/sermant-backend/src/main/resources/application.properties @@ -45,9 +45,9 @@ dynamic.config.namespace=default # Interface timeout for configuration center dynamic.config.timeout=30000 # Address of Configuration Center -dynamic.config.serverAddress=127.0.0.1:30110 +dynamic.config.serverAddress=127.0.0.1:2181 # The type of configuration center supports ZOOKEEPER, NACOS, KIE -dynamic.config.dynamicConfigType=KIE +dynamic.config.dynamicConfigType=ZOOKEEPER # Timeout for connecting to the configuration center dynamic.config.connectTimeout=3000 # Is the configuration center connected through authorization authentication diff --git a/sermant-backend/src/main/webapp/frontend/src/composables/translations.ts b/sermant-backend/src/main/webapp/frontend/src/composables/translations.ts index 22ebcb7ae1..be8087976c 100644 --- a/sermant-backend/src/main/webapp/frontend/src/composables/translations.ts +++ b/sermant-backend/src/main/webapp/frontend/src/composables/translations.ts @@ -18,25 +18,31 @@ export const messages = { application: 'Application', appName: 'Application', service: 'Service', - sermantName: 'Sermant', - processId: 'Process Id', + artifactName: 'Artifact', + processId: 'Process ID', DynamicInstall: 'Dynamic Install', uninstallPlugin: 'Uninstall Plugin', installPlugin: 'Install Plugin', uninstallAgent: 'Uninstall Agent', updatePlugin: 'Update Plugin', updateAgent: 'Update Agent', + installExternalAgent: "Install External Agent", commandTypePlaceholder: 'Please select The command type', - agentPathPlaceholder: 'Please input the Sermant path', + agentPathPlaceholder: 'Please input the Agent path', pluginNamePlaceholder: 'Please enter the plugin name', + externalAgentPathPlaceholder: 'Please input the Agent path', + externalAgentNamePlaceholder: 'Please enter the Agent name', paramPlaceholder: 'Please input the parameter information', commandTypeNotice: 'Supported command types for hot plugging functionality', - agentPathNotice: 'Absolute path of the directory where the Agent file is located', + agentPathNotice: 'Fill in the absolute path of the parent directory of sermant-agent.jar here(If empty, use the original agent path)', + externalAgentPathNotice: 'Absolute path of the directory where the Agent file is located', pluginNameNotice: 'Names of plugins to update or uninstall, separated by commas for multiple plugins', + externalAgentNameNotice: 'Give the name of your Agent, input OTEL for OpenTelemetry(specially supported)', paramNotice: 'Configuration information specified when updating plugins or Sermant, in the format xxx=xxx,xxx=xxx', commandType: 'Command Type', pluginName: 'Plugin Name', - agentPath: 'Sermant Path', + agentPath: 'Agent Path', + externalAgentName: "Agent Name", param: 'Param', instance: 'Instance', version: 'Version', @@ -44,6 +50,7 @@ export const messages = { instanceID: 'Instance ID', heartbeat: 'Heartbeat', plugin: 'Plugin', + externalAgent: 'External Agent', successfullyObtainedInstances: 'Successfully obtained instances', failedToObtainInstances: 'Failed to obtain instances', notSelectInstance: 'Please select the instance for hot plugging first', @@ -127,6 +134,8 @@ export const messages = { pluginInstall: 'Plugin Install', pluginUninstall: 'Plugin Uninstall', pluginUpdate: 'Plugin Update', + externalAgentInstall: "External Agent Install", + otelStart: "OTEL Agent Start", }, eventConfigView: { event: 'Event', @@ -281,25 +290,31 @@ export const messages = { application: '应用', appName: '应用', service: '服务', - sermantName: 'Sermant', - processId: '进程Id', + artifactName: 'Artifact', + processId: '进程ID', DynamicInstall: '动态安装', uninstallPlugin: '卸载插件', installPlugin: '安装插件', uninstallAgent: '卸载Agent', updatePlugin: '升级插件', updateAgent: '升级Agent', + installExternalAgent: "安装外部Agent", commandTypePlaceholder: '请选择命令类型', - agentPathPlaceholder: '请输入Sermant路径', + agentPathPlaceholder: '请输入Agent路径', pluginNamePlaceholder: '请输入插件名称', + externalAgentPathPlaceholder: '请输入Agent路径', + externalAgentNamePlaceholder: '请输入Agent名称', paramPlaceholder: '请输入参数信息', commandTypeNotice: '动态挂载功能的支持的命令类型', - agentPathNotice: 'Agent文件所在目录的绝对路径', + agentPathNotice: '此处填写sermant-agent.jar的上级目录的绝对路径(如果不填则使用原有Agent路径)', + externalAgentPathNotice: 'Agent文件所在目录的绝对路径', pluginNameNotice: '更新或者卸载的插件名称,多个插件时用,隔开', + externalAgentNameNotice: '定义您的Agent的名称,如使用OpenTelemetry请输入OTEL(已特别支持)', paramNotice: '更新插件或者Sermant时指定的配置信息,格式为xxx=xxx,xxx=xxx', commandType: '命令类型', pluginName: '插件名称', - agentPath: 'Sermant路径', + agentPath: 'Agent路径', + externalAgentName: "Agent名称", param: '参数', instance: '实例', version: '版本', @@ -307,6 +322,7 @@ export const messages = { instanceID: '实例ID', heartbeat: '心跳时间', plugin: '插件', + externalAgent: '外部Agent', successfullyObtainedInstances: '获取实例数据成功', failedToObtainInstances: '获取实例数据失败', notSelectInstance: '请先选择动态挂载的实例', @@ -390,6 +406,8 @@ export const messages = { pluginInstall: '插件安装', pluginUninstall: '插件卸载', pluginUpdate: '插件更新', + externalAgentInstall: "安装外部Agent", + otelStart: "OTEL Agent启动", }, eventConfigView: { event: '事件', diff --git a/sermant-backend/src/main/webapp/frontend/src/views/EventsView.vue b/sermant-backend/src/main/webapp/frontend/src/views/EventsView.vue index 79eb78d145..626a70f4e6 100644 --- a/sermant-backend/src/main/webapp/frontend/src/views/EventsView.vue +++ b/sermant-backend/src/main/webapp/frontend/src/views/EventsView.vue @@ -188,7 +188,7 @@ + :label="$t('eventViews.event')" width="180" column-key="name">