From 05dd8fd5639eb07a45662b6876e3e2a251a348db Mon Sep 17 00:00:00 2001 From: hanbingleixue Date: Wed, 13 Sep 2023 14:47:54 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8A=A8=E6=80=81=E5=AE=89?= =?UTF-8?q?=E8=A3=85=E5=8D=B8=E8=BD=BD=E7=9A=84=E5=91=BD=E4=BB=A4=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E6=89=A7=E8=A1=8C=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sermant/core/AgentCoreEntrance.java | 8 ++ .../AgentUnInstallCommandExecutor.java | 32 ++++++++ .../sermant/core/command/Command.java | 47 ++++++++++++ .../sermant/core/command/CommandExecutor.java | 33 ++++++++ .../core/command/CommandProcessor.java | 76 +++++++++++++++++++ .../PluginsInstallCommandExecutor.java | 46 +++++++++++ .../PluginsUnInstallCommandExecutor.java | 46 +++++++++++ .../sermant/core/plugin/PluginManager.java | 22 ++++++ .../core/command/CommandExecutorTest.java | 40 ++++++++++ .../sermant/premain/AgentLauncher.java | 29 +++---- .../premain/common/BootArgsBuilderTest.java | 13 ++++ 11 files changed, 379 insertions(+), 13 deletions(-) create mode 100644 sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/AgentUnInstallCommandExecutor.java create mode 100644 sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/Command.java create mode 100644 sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/CommandExecutor.java create mode 100644 sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/CommandProcessor.java create mode 100644 sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/PluginsInstallCommandExecutor.java create mode 100644 sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/PluginsUnInstallCommandExecutor.java create mode 100644 sermant-agentcore/sermant-agentcore-core/src/test/java/com/huaweicloud/sermant/core/command/CommandExecutorTest.java diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/AgentCoreEntrance.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/AgentCoreEntrance.java index 3802c9405e..94a253b8bb 100644 --- a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/AgentCoreEntrance.java +++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/AgentCoreEntrance.java @@ -26,6 +26,7 @@ import com.huaweicloud.sermant.core.notification.NotificationManager; import com.huaweicloud.sermant.core.notification.SermantNotificationType; import com.huaweicloud.sermant.core.operation.OperationManager; +import com.huaweicloud.sermant.core.plugin.PluginManager; import com.huaweicloud.sermant.core.plugin.PluginSystemEntrance; import com.huaweicloud.sermant.core.plugin.agent.ByteEnhanceManager; import com.huaweicloud.sermant.core.plugin.agent.adviser.AdviserScheduler; @@ -99,4 +100,11 @@ public static void install(String artifact, Map argsMap, Instrum NotificationManager.doNotify(new NotificationInfo(SermantNotificationType.LOAD_COMPLETE, null)); } } + + /** + * agent卸载方法 + */ + public static void unInstall() { + PluginManager.unInstallAll(); + } } diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/AgentUnInstallCommandExecutor.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/AgentUnInstallCommandExecutor.java new file mode 100644 index 0000000000..c648dc72b9 --- /dev/null +++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/AgentUnInstallCommandExecutor.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2023-2023 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. + * 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 com.huaweicloud.sermant.core.command; + +import com.huaweicloud.sermant.core.AgentCoreEntrance; + +/** + * Agent卸载命令执行器 + * + * @author zhp + * @since 2023-09-09 + */ +public class AgentUnInstallCommandExecutor implements CommandExecutor { + @Override + public void execute(String args) { + AgentCoreEntrance.unInstall(); + } +} diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/Command.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/Command.java new file mode 100644 index 0000000000..0e6384a182 --- /dev/null +++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/Command.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2023-2023 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. + * 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 com.huaweicloud.sermant.core.command; + +/** + * 动态安装卸载的指令枚举 + * + * @author zhp + * @since 2023-09-09 + */ +public enum Command { + /** + * 卸载agent指令 + */ + UNINSTALL_AGENT("UNINSTALL-AGENT"), + /** + * 安装插件指令 + */ + INSTALL_PLUGINS("INSTALL-PLUGINS"), + /** + * 卸载插件指令 + */ + UNINSTALL_PLUGINS("UNINSTALL-PLUGINS"); + private final String value; + + Command(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/CommandExecutor.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/CommandExecutor.java new file mode 100644 index 0000000000..5f39b1801c --- /dev/null +++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/CommandExecutor.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2023-2023 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. + * 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 com.huaweicloud.sermant.core.command; + +/** + * 指令执行器 + * + * @author zhp + * @since 2023-09-09 + */ +public interface CommandExecutor { + + /** + * 执行指令 + * + * @param args 指令参数 + */ + void execute(String args); +} diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/CommandProcessor.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/CommandProcessor.java new file mode 100644 index 0000000000..a416b82164 --- /dev/null +++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/CommandProcessor.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2023-2023 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. + * 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 com.huaweicloud.sermant.core.command; + +import com.huaweicloud.sermant.core.common.LoggerFactory; +import com.huaweicloud.sermant.core.utils.StringUtils; + +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.logging.Logger; + +/** + * 命令处理器 + * + * @author zhp + * @since 2023-09-09 + */ +public class CommandProcessor { + /** + * 命令执行器Map + */ + private static final Map COMMAND_EXECUTOR_MAP = new HashMap<>(); + + private static final Logger LOGGER = LoggerFactory.getLogger(); + + static { + COMMAND_EXECUTOR_MAP.put(Command.INSTALL_PLUGINS.getValue(), new PluginsInstallCommandExecutor()); + COMMAND_EXECUTOR_MAP.put(Command.UNINSTALL_AGENT.getValue(), new AgentUnInstallCommandExecutor()); + COMMAND_EXECUTOR_MAP.put(Command.UNINSTALL_PLUGINS.getValue(), new PluginsUnInstallCommandExecutor()); + } + + /** + * 构造函数 + */ + private CommandProcessor() { + } + + /** + * 处理指令 + * + * @param command 指令 + */ + public static void process(String command) { + if (StringUtils.isEmpty(command)) { + LOGGER.warning("Command information is empty."); + return; + } + String[] commandInfo = command.trim().split(":"); + if (commandInfo.length == 0) { + LOGGER.warning("Illegal command information."); + return; + } + CommandExecutor commandExecutor = COMMAND_EXECUTOR_MAP.get(commandInfo[0].toUpperCase(Locale.ROOT)); + if (commandExecutor == null) { + LOGGER.warning("No corresponding command executor found."); + return; + } + String commandArgs = commandInfo.length > 1 ? commandInfo[1] : null; + commandExecutor.execute(commandArgs); + } +} diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/PluginsInstallCommandExecutor.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/PluginsInstallCommandExecutor.java new file mode 100644 index 0000000000..291f116e64 --- /dev/null +++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/PluginsInstallCommandExecutor.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2023-2023 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. + * 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 com.huaweicloud.sermant.core.command; + +import com.huaweicloud.sermant.core.common.LoggerFactory; +import com.huaweicloud.sermant.core.plugin.PluginManager; +import com.huaweicloud.sermant.core.utils.StringUtils; + +import java.util.Arrays; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +/** + * 插件安装命令执行器 + * + * @author zhp + * @since 2023-09-09 + */ +public class PluginsInstallCommandExecutor implements CommandExecutor { + private static final Logger LOGGER = LoggerFactory.getLogger(); + + @Override + public void execute(String args) { + if (StringUtils.isEmpty(args)) { + LOGGER.log(Level.WARNING, "The argument of command[INSTALL-PLUGINS] is empty."); + return; + } + String[] pluginNames = args.split("\\|"); + PluginManager.install(Arrays.stream(pluginNames).collect(Collectors.toSet())); + } +} diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/PluginsUnInstallCommandExecutor.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/PluginsUnInstallCommandExecutor.java new file mode 100644 index 0000000000..1f325fb2ea --- /dev/null +++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/command/PluginsUnInstallCommandExecutor.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2023-2023 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. + * 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 com.huaweicloud.sermant.core.command; + +import com.huaweicloud.sermant.core.common.LoggerFactory; +import com.huaweicloud.sermant.core.plugin.PluginManager; +import com.huaweicloud.sermant.core.utils.StringUtils; + +import java.util.Arrays; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +/** + * 插件卸载命令执行器 + * + * @author zhp + * @since 2023-09-09 + */ +public class PluginsUnInstallCommandExecutor implements CommandExecutor { + private static final Logger LOGGER = LoggerFactory.getLogger(); + + @Override + public void execute(String args) { + if (StringUtils.isEmpty(args)) { + LOGGER.log(Level.WARNING, "The argument of command[UNINSTALL-PLUGINS] is empty."); + return; + } + String[] pluginNames = args.split("\\|"); + PluginManager.unInstall(Arrays.stream(pluginNames).collect(Collectors.toSet())); + } +} diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/plugin/PluginManager.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/plugin/PluginManager.java index 551fffd693..01a5ede63d 100644 --- a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/plugin/PluginManager.java +++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/plugin/PluginManager.java @@ -275,6 +275,28 @@ private static File getServiceDir(String pluginPath) { return new File(pluginPath + File.separatorChar + PluginConstant.SERVICE_DIR_NAME); } + /** + * 安装插件 + * + * @param plugins 插件名称集合 + */ + public static void install(Set plugins) { + } + + /** + * 卸载插件 + * + * @param plugins 插件名称集合 + */ + public static void unInstall(Set plugins) { + } + + /** + * 卸载所有插件 + */ + public static void unInstallAll() { + } + /** * JarFile消费者 * diff --git a/sermant-agentcore/sermant-agentcore-core/src/test/java/com/huaweicloud/sermant/core/command/CommandExecutorTest.java b/sermant-agentcore/sermant-agentcore-core/src/test/java/com/huaweicloud/sermant/core/command/CommandExecutorTest.java new file mode 100644 index 0000000000..208f7e2393 --- /dev/null +++ b/sermant-agentcore/sermant-agentcore-core/src/test/java/com/huaweicloud/sermant/core/command/CommandExecutorTest.java @@ -0,0 +1,40 @@ +package com.huaweicloud.sermant.core.command; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +public class CommandExecutorTest { + private CommandExecutor commandExecutor; + + @BeforeEach + public void setUp() { + commandExecutor = Mockito.mock(CommandExecutor.class); + } + + @AfterEach + public void tearDown() { + commandExecutor = null; + } + + @Test + public void testExecuteWhenArgsIsValidThenNoException() { + // Arrange + String validArgs = "validArgs"; + + // Act & Assert + assertDoesNotThrow(() -> commandExecutor.execute(validArgs)); + } + + @Test + public void testExecuteWhenArgsIsNullThenNoException() { + // Arrange + String nullArgs = null; + + // Act & Assert + assertDoesNotThrow(() -> commandExecutor.execute(nullArgs)); + } +} \ No newline at end of file diff --git a/sermant-agentcore/sermant-agentcore-premain/src/main/java/com/huaweicloud/sermant/premain/AgentLauncher.java b/sermant-agentcore/sermant-agentcore-premain/src/main/java/com/huaweicloud/sermant/premain/AgentLauncher.java index ee73740aaf..ecbf4ded4b 100644 --- a/sermant-agentcore/sermant-agentcore-premain/src/main/java/com/huaweicloud/sermant/premain/AgentLauncher.java +++ b/sermant-agentcore/sermant-agentcore-premain/src/main/java/com/huaweicloud/sermant/premain/AgentLauncher.java @@ -43,6 +43,8 @@ public class AgentLauncher { private static final Logger LOGGER = LoggerUtils.getLogger(); + private static final String COMMAND_CODE = "command"; + private static boolean installFlag = false; private AgentLauncher() { @@ -82,22 +84,23 @@ private static void launchAgent(String agentArgs, Instrumentation instrumentatio final Map argsMap = BootArgsBuilder.build(agentArgs); String artifact = (String) argsMap.get(BootConstant.ARTIFACT_NAME_KEY); - if (SermantManager.checkSermantStatus(artifact)) { - LOGGER.log(Level.WARNING, "Sermant for artifact is running,artifact is: " + artifact); - return; - } - // 添加核心库 LOGGER.info("Loading core library into SermantClassLoader."); SermantClassLoader sermantClassLoader = SermantManager.createSermant(artifact, loadCoreLibUrls()); - - // agent core入口 - LOGGER.log(Level.INFO, "Loading sermant agent, artifact is: " + artifact); - sermantClassLoader.loadClass("com.huaweicloud.sermant.core.AgentCoreEntrance") - .getDeclaredMethod("install", String.class, Map.class, Instrumentation.class, boolean.class) - .invoke(null, artifact, argsMap, instrumentation, isDynamic); - LOGGER.log(Level.INFO, "Load sermant done, artifact is: " + artifact); - SermantManager.updateSermantStatus(artifact, true); + if (!SermantManager.checkSermantStatus(artifact)) { + // 当前artifact未安装,执行agent安装 + LOGGER.log(Level.INFO, "Loading sermant agent, artifact is: " + artifact); + sermantClassLoader.loadClass("com.huaweicloud.sermant.core.AgentCoreEntrance") + .getDeclaredMethod("install", String.class, Map.class, Instrumentation.class, boolean.class) + .invoke(null, artifact, argsMap, instrumentation, isDynamic); + LOGGER.log(Level.INFO, "Load sermant done, artifact is: " + artifact); + SermantManager.updateSermantStatus(artifact, true); + } else { + LOGGER.log(Level.INFO, "Sermant for artifact is running,artifact is: " + artifact); + } + sermantClassLoader.loadClass("com.huaweicloud.sermant.core.command.CommandProcessor") + .getDeclaredMethod("process", String.class) + .invoke(null, argsMap.get(COMMAND_CODE)); } catch (Exception e) { LOGGER.log(Level.SEVERE, "Loading sermant agent failed.", e); } diff --git a/sermant-agentcore/sermant-agentcore-premain/src/test/java/com/huaweicloud/sermant/premain/common/BootArgsBuilderTest.java b/sermant-agentcore/sermant-agentcore-premain/src/test/java/com/huaweicloud/sermant/premain/common/BootArgsBuilderTest.java index 696ee70a15..8e1c9975f7 100644 --- a/sermant-agentcore/sermant-agentcore-premain/src/test/java/com/huaweicloud/sermant/premain/common/BootArgsBuilderTest.java +++ b/sermant-agentcore/sermant-agentcore-premain/src/test/java/com/huaweicloud/sermant/premain/common/BootArgsBuilderTest.java @@ -4,6 +4,7 @@ import static org.junit.Assert.assertEquals; import org.junit.AfterClass; +import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; @@ -105,4 +106,16 @@ private static void setEnv(Map envMap) throws NoSuchFieldException, IllegalAcces } } } + + /** + * 测试参数解析 + */ + @Test + public void testParseArgs(){ + String agentArgs = "appName=test,command=INSTALL_PLUGIN:monitor|flowcontrol,server.port=9000"; + Map argsMap = BootArgsBuilder.build(agentArgs); + Assert.assertEquals("test", argsMap.get("appName")); + Assert.assertEquals("9000", argsMap.get("server.port")); + Assert.assertEquals("INSTALL_PLUGIN:monitor|flowcontrol", argsMap.get("command")); + } } \ No newline at end of file