diff --git a/src/main/java/com/gearbox/platform/deadline/service/DeadlineCommandExecutor.java b/src/main/java/com/gearbox/platform/deadline/service/DeadlineCommandExecutor.java index 71dd7ec4980aa86b28591af890feb4a579371d42..b9d74cf6277146745a706b81ecfe1e041d6349af 100644 --- a/src/main/java/com/gearbox/platform/deadline/service/DeadlineCommandExecutor.java +++ b/src/main/java/com/gearbox/platform/deadline/service/DeadlineCommandExecutor.java @@ -16,19 +16,28 @@ public class DeadlineCommandExecutor { private static final String EQUAL_SIGN = "="; public static List getSlaveNames() { + if (DeadlineRestAPIExecutor.isUseRestAPI) { + return DeadlineRestAPIExecutor.getSlaveNames(); + } ShellResult result = ShellExecutor.runCommand(String.format(Locale.ROOT, "deadlinecommand -GetSlaveNames")); CmdExecuteResultAssertion.assertError(result); return result.getReturnValues(); } public static String getSlaveStatusByName(String slaveName) { + if (DeadlineRestAPIExecutor.isUseRestAPI) { + return DeadlineRestAPIExecutor.getSlaveStatusByName(slaveName); + } ShellResult result = ShellExecutor.runCommand( - String.format(Locale.ROOT, "deadlinecommand -GetSlaveInfo %s slavestatus", slaveName)); + String.format(Locale.ROOT, "deadlinecommand -GetSlaveInfo %s slavestatus", slaveName)); CmdExecuteResultAssertion.assertError(result); return result.getReturnValues().get(0); } public static List getSlaveInfos() { + if (DeadlineRestAPIExecutor.isUseRestAPI) { + return DeadlineRestAPIExecutor.getSlaveInfos(); + } ShellResult result = ShellExecutor.runCommand("deadlinecommand -GetSlaves"); CmdExecuteResultAssertion.assertError(result); List nodeList = new ArrayList<>(); @@ -58,29 +67,43 @@ public class DeadlineCommandExecutor { slaveEnabledTemp = false; } } - return nodeList; + return nodeList; } public static boolean isSlaveEnabled(String slaveName) { + if (DeadlineRestAPIExecutor.isUseRestAPI) { + return DeadlineRestAPIExecutor.isSlaveEnabled(slaveName); + } ShellResult result = ShellExecutor.runCommand( - String.format(Locale.ROOT, "deadlinecommand -GetSlaveSetting %s SlaveEnabled", slaveName)); + String.format(Locale.ROOT, "deadlinecommand -GetSlaveSetting %s SlaveEnabled", slaveName)); CmdExecuteResultAssertion.assertError(result); return Boolean.parseBoolean(result.getReturnValues().get(0)); } public static void deleteSlave(String slaveName) { + if (DeadlineRestAPIExecutor.isUseRestAPI) { + DeadlineRestAPIExecutor.deleteSlave(slaveName); + return; + } String cmd = String.format(Locale.ROOT, "deadlinecommand -DeleteSlave %s", slaveName); ShellResult result = ShellExecutor.runCommand(cmd); CmdExecuteResultAssertion.assertError(result); } public static void disableSlave(String slaveName) { + if (DeadlineRestAPIExecutor.isUseRestAPI) { + DeadlineRestAPIExecutor.disableSlave(slaveName); + return; + } String cmd = String.format(Locale.ROOT, "deadlinecommand -setslavesetting %s slaveenabled false", slaveName); ShellResult result = ShellExecutor.runCommand(cmd); CmdExecuteResultAssertion.assertError(result); } public static List listWaitingJobIds() { + if (DeadlineRestAPIExecutor.isUseRestAPI) { + return DeadlineRestAPIExecutor.listWaitingJobIds(); + } String getWaitingJobCmd = "deadlinecommand -GetJobIdsFilter status=queued status=rendering"; ShellResult result = ShellExecutor.runCommand(getWaitingJobCmd); CmdExecuteResultAssertion.assertError(result); @@ -88,6 +111,9 @@ public class DeadlineCommandExecutor { } public static String getJobUserName(String jobId) { + if (DeadlineRestAPIExecutor.isUseRestAPI) { + return DeadlineRestAPIExecutor.getJobUserName(jobId); + } String cmd = String.format(Locale.ROOT, "deadlinecommand -GetJobSetting %s UserName", jobId); ShellResult result = ShellExecutor.runCommand(cmd); CmdExecuteResultAssertion.assertError(result); @@ -95,6 +121,9 @@ public class DeadlineCommandExecutor { } public static int getJobQueuedChunks(String jobId) { + if (DeadlineRestAPIExecutor.isUseRestAPI) { + return DeadlineRestAPIExecutor.getJobQueueChunks(jobId); + } String cmd = String.format(Locale.ROOT, "deadlinecommand -GetJobSetting %s QueuedChunks", jobId); ShellResult result = ShellExecutor.runCommand(cmd); CmdExecuteResultAssertion.assertError(result); diff --git a/src/main/java/com/gearbox/platform/deadline/service/DeadlineRestAPIExecutor.java b/src/main/java/com/gearbox/platform/deadline/service/DeadlineRestAPIExecutor.java new file mode 100644 index 0000000000000000000000000000000000000000..cc99829d2e1d91cbc28a41ca1c717828115eb156 --- /dev/null +++ b/src/main/java/com/gearbox/platform/deadline/service/DeadlineRestAPIExecutor.java @@ -0,0 +1,219 @@ +package com.gearbox.platform.deadline.service; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gearbox.core.constant.DeadlineInstanceStatusEnum; +import com.gearbox.core.constant.NodeStatusEnum; +import com.gearbox.core.model.Node; +import com.gearbox.core.task.CacheRefreshTask; +import okhttp3.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.CollectionUtils; + +import java.io.IOException; +import java.net.ServerSocket; +import java.util.*; +import java.util.concurrent.TimeUnit; + +public class DeadlineRestAPIExecutor { + private static OkHttpClient client; + private static ObjectMapper objectMapper; + private static final Logger LOG = LoggerFactory.getLogger(CacheRefreshTask.class); + public static boolean isUseRestAPI = false; + private static final HashMap statMap = new HashMap() { + { + put(0, "Unknown"); + put(1, "Rendering"); + put(2, "Idle"); + put(3, "Offline"); + put(4, "Stalled"); + put(8, "StartingJob"); + } + }; + + static { + client = new OkHttpClient().newBuilder().connectionPool(new ConnectionPool(5, 10, TimeUnit.MILLISECONDS)) + .readTimeout(60, TimeUnit.SECONDS).writeTimeout(60, TimeUnit.SECONDS).build(); + objectMapper = new ObjectMapper(); + isUseRestAPI = checkWebServiceIsRunning(); + } + + public static List getSlaveNames() { + String url = "http://localhost:8081/api/slaves?NamesOnly=true"; + Request request = new Request.Builder().url(url).build(); + List list = null; + try { + Response response = client.newCall(request).execute(); + String bodyStr = response.body().string(); + list = objectMapper.readValue(bodyStr, new TypeReference>() { + }); + } catch (IOException e) { + LOG.error("use RestAPI get getSlaveNames failed"); + } + if (!CollectionUtils.isEmpty(list)) { + return list; + } + return Collections.emptyList(); + } + + public static String getSlaveStatusByName(String name) { + String url = String.format(Locale.ROOT, "http://localhost:8081/api/slaves?Data=info&Name=%s", name); + Request request = new Request.Builder().url(url).build(); + List> list = null; + try { + Response response = client.newCall(request).execute(); + String bodyStr = response.body().string(); + list = objectMapper.readValue(bodyStr, new TypeReference>>() { + }); + } catch (IOException e) { + LOG.error("use RestAPI get getSlaveStatusByName failed"); + } + if (!CollectionUtils.isEmpty(list)) { + Integer stat = (Integer) list.get(0).get("Stat"); + return statMap.get(stat); + } + return statMap.get(0); + } + + public static List getSlaveInfos() { + List nodeList = new ArrayList<>(); + String url = "http://localhost:8081/api/slaves"; + Request request = new Request.Builder().url(url).build(); + try { + Response response = client.newCall(request).execute(); + String bodyStr = response.body().string(); + List> list = objectMapper.readValue(bodyStr, new TypeReference>>() { + }); + for (HashMap map : list) { + LinkedHashMap infoMap = (LinkedHashMap) map.get("Info"); + String nodeName = (String) infoMap.get("Name"); + Integer stat = (Integer) infoMap.get("Stat"); + String slaveStatus = statMap.get(stat); + HashMap settingsMap = (HashMap) map.get("Settings"); + boolean slaveEnabled = (boolean) settingsMap.get("Enable"); + nodeList.add(new Node(nodeName, NodeStatusEnum.toNodeStatus(DeadlineInstanceStatusEnum.value(slaveStatus)), slaveEnabled)); + } + } catch (IOException e) { + LOG.error("use RestAPI get getSlaveInfos failed"); + } + return nodeList; + } + + public static boolean isSlaveEnabled(String name) { + String url = String.format(Locale.ROOT, "http://localhost:8081/api/slaves?Data=settings&Name=%s", name); + Request request = new Request.Builder().url(url).build(); + boolean enable = false; + List> list = null; + try { + Response response = client.newCall(request).execute(); + String bodyStr = response.body().string(); + list = objectMapper.readValue(bodyStr, new TypeReference>>() { + }); + } catch (IOException e) { + LOG.error("use RestAPI get SlaveEnabled failed"); + } + if (!CollectionUtils.isEmpty(list)) { + enable = (boolean) list.get(0).get("Enable"); + } + return enable; + } + + public static String disableSlave(String name) { + String url = "http://localhost:8081/api/slaves"; + HashMap reqMap = new HashMap<>(); + reqMap.put("Command", "savesettings"); + HashMap settingsMap = new HashMap<>(); + settingsMap.put("Name", name); + settingsMap.put("Enable", false); + reqMap.put("SlaveSettings", settingsMap); + String res = "fail"; + try { + String json = objectMapper.writeValueAsString(reqMap); + MediaType JSON = MediaType.parse("application/json; charset=utf-8"); + RequestBody body = RequestBody.create(json, JSON); + Request request = new Request.Builder().url(url).put(body).build(); + Response response = client.newCall(request).execute(); + res = response.body().string(); + } catch (IOException e) { + LOG.error("use RestAPI get disableSlave failed"); + } + return res; + } + + public static String deleteSlave(String name) { + String url = String.format(Locale.ROOT, "http://localhost:8081/api/slaves?Name=%s", name); + Request request = new Request.Builder().url(url).delete().build(); + String res = null; + try { + Response response = client.newCall(request).execute(); + res = response.body().string(); + } catch (IOException e) { + LOG.error("use RestAPI get deleteSlave failed"); + } + return res; + } + + public static List listWaitingJobIds() { + String url = "http://localhost:8081/api/jobs?IdOnly=true&States=Active"; + Request request = new Request.Builder().url(url).get().build(); + List list = null; + try { + Response response = client.newCall(request).execute(); + String json = response.body().string(); + list = objectMapper.readValue(json, new TypeReference>() { + }); + } catch (IOException e) { + LOG.error("use RestAPI get listWaitingJobIds failed"); + } + return list; + } + + public static String getJobUserName(String jobId) { + HashMap job = getJobByJobId(jobId); + String res = null; + if (!CollectionUtils.isEmpty(job)) { + HashMap props = (HashMap) job.get("Props"); + res = (String) props.get("User"); + } + return res; + } + + public static int getJobQueueChunks(String jobId) { + HashMap job = getJobByJobId(jobId); + Integer num = 0; + if (!CollectionUtils.isEmpty(job)) { + num = (Integer) job.get("QueuedChunks"); + } + return num; + } + + public static HashMap getJobByJobId(String jobId) { + String url = String.format(Locale.ROOT, "http://localhost:8081/api/jobs?JobID=%s", jobId); + Request request = new Request.Builder().url(url).get().build(); + List> list = null; + try { + Response response = client.newCall(request).execute(); + String json = response.body().string(); + list = objectMapper.readValue(json, new TypeReference>>() { + }); + } catch (IOException e) { + LOG.error("use RestAPI get getJobByJobId failed"); + } + if (!CollectionUtils.isEmpty(list)) { + return list.get(0); + } + return new HashMap<>(); + } + + //通过检测webservice端口号8081是否被占用来判断webservice服务是否运行。若端口被占用,则程序会捕获异常,返回true表示webservice服务正在运行。 + public static boolean checkWebServiceIsRunning() { + try { + ServerSocket serverSocket = new ServerSocket(8081); + serverSocket.close(); + return false; + } catch (IOException e) { + return true; + } + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 9a77b112f33c718fd2da8351702a8bf2a2949da1..0db435da273846392d0a57c30de51fef6e308f5e 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -4,7 +4,7 @@ user: # 华为云 console账号的SK,认证使用. SK硬编码或者明文存储都存在较大的安全风险,建议在配置文件或者环境变量中密文存储,使用时解密,确保安全 sk: # 待使用局点的租户ID - project-id: 0d61b5ce7680f3e62fc3c005a9e8bdd7 + project-id: 1 # 代理地址,端口,用户名密码等,无需代理可不配置 proxy-address: proxy-port: @@ -14,7 +14,7 @@ as: # AS服务在待使用局点的终端节点域名 endpoint: as.cn-north-4.myhuaweicloud.com # 预置伸缩组资源的伸缩组ID - group: f12d57a3-ed8a-4a16-8c3f-4817ab7171f2 + group: # 查询伸缩实例时单页最大返回数量,默认100可不修改 list-instance-limit: 100 # 删除伸缩实例时最大数量限制,AS服务最大支持50,可不修改 @@ -30,7 +30,7 @@ metric: # 自定义指标维度名,可不修改 dimension-name: autoscaling_group # 自定义指标维度ID,可配置成伸缩组的ID,该值不影响功能 - dimension-id: f12d57a3-ed8a-4a16-8c3f-4817ab7171f2 + dimension-id: # 指标上报的TTL参数,可不修改 report-ttl: 172800 # CES服务在待使用局点的终端节点域名 @@ -39,7 +39,7 @@ task: # 节点状态检查周期,单位 秒 health-audit-period: 30 # 自定义指标上报周期,单位 秒 - metric-report-period: 60 + metric-report-period: 5 # 检测是否需要缩容的周期,单位 秒 scale-in-period: 5 # 自动删除待缩容节点周期,单位 秒 @@ -47,9 +47,9 @@ task: # 新扩容节点自发现周期 discover-instance-period: 20 # 对比伸缩组与slurm节点数量周期,单位 秒 - diff-instance-and-node-period: 60 + diff-instance-and-node-period: 30 # 内部缓存刷新周期,单位 秒 - refresh-cache-period: 100 + refresh-cache-period: 15 # 配置检查任务运行周期,单位 秒 configuration-check-period: 300 system: @@ -62,9 +62,9 @@ system: #不稳定节点所在的分区 variable-partition: dyn1 # 空闲时间阈值,空间时间超过该值的节点将被缩容,单位 秒 - scale-in-time: 1 + scale-in-time: 10 # 判断job是否属于排队状态的时间限制条件,排队时间超过该值的job被认为是在排队并参与指标计算,建议为0 - job-wait-time: 1 + job-wait-time: 10 # 新节点注册的超时时间,超过该时间依然未注册成功将被AS删除,单位:分钟,建议为10 register-timeout-minutes: 10 # 弹性节点使用的cpu核数 diff --git a/src/test/java/com/gearbox/platform/deadline/service/DeadlineRestAPIExecutorTest.java b/src/test/java/com/gearbox/platform/deadline/service/DeadlineRestAPIExecutorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..99f758eabd17ebb0acc34495b44bdf27e86e4d36 --- /dev/null +++ b/src/test/java/com/gearbox/platform/deadline/service/DeadlineRestAPIExecutorTest.java @@ -0,0 +1,79 @@ +package com.gearbox.platform.deadline.service; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gearbox.core.model.Node; +import okhttp3.ConnectionPool; +import okhttp3.OkHttpClient; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.concurrent.TimeUnit; + + +public class DeadlineRestAPIExecutorTest { + OkHttpClient client = new OkHttpClient().newBuilder().connectionPool(new ConnectionPool(5, 10, TimeUnit.MILLISECONDS)) + .readTimeout(60, TimeUnit.SECONDS).writeTimeout(60, TimeUnit.SECONDS).build(); + ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void testGetSlaveInfosRestAPI() { + List slaveInfosRestAPI = DeadlineRestAPIExecutor.getSlaveInfos(); + Assertions.assertEquals(slaveInfosRestAPI.size(), 1); + } + + @Test + public void testGetSlaveNamesRestAPI() { + List slaveNamesRestAPI = DeadlineRestAPIExecutor.getSlaveNames(); + Assertions.assertEquals(slaveNamesRestAPI.get(0), "worker-192"); + } + + @Test + public void testGetSlaveStatusByNameRestAPI() { + String slaveStatusByNameRestAPI = DeadlineRestAPIExecutor.getSlaveStatusByName("worker-192"); + Assertions.assertEquals(slaveStatusByNameRestAPI, "Idle"); + } + + @Test + public void testIsSlaveEnabledRestAPI() { + boolean slaveEnabledRestAPI = DeadlineRestAPIExecutor.isSlaveEnabled("worker-192"); + Assertions.assertEquals(slaveEnabledRestAPI, true); + } + + @Test + public void testDisableSlaveRestAPI() { + String s = DeadlineRestAPIExecutor.disableSlave("worker-192"); + Assertions.assertEquals(s, "Success"); + } + + @Test + public void testDeleteSlaveRestAPI() { + String s = DeadlineRestAPIExecutor.deleteSlave("worker-192"); + Assertions.assertEquals(s, "Success"); + } + + @Test + public void testListWaitingJobIdsRestAPI() { + List list = DeadlineRestAPIExecutor.listWaitingJobIds(); + Assertions.assertEquals(list.size(), 12); + } + + @Test + public void testGetJobUserNameRestAPI() { + String jobUserNameRestAPI = DeadlineRestAPIExecutor.getJobUserName("6596960866f66719ec4e5619"); + Assertions.assertEquals(jobUserNameRestAPI, "administrator"); + } + + + @Test + public void testGetJobQueueChunksRestAPI() { + int jobQueueChunksRestAPI = DeadlineRestAPIExecutor.getJobQueueChunks("6596960866f66719ec4e5619"); + Assertions.assertEquals(jobQueueChunksRestAPI, 23); + } + + @Test + public void testIsUseRestAPI() { + boolean b = DeadlineRestAPIExecutor.checkWebServiceIsRunning(); + Assertions.assertEquals(b, true); + } +}