From 2f8d383a066dd8e0711c56aa91f0ba579a9147b7 Mon Sep 17 00:00:00 2001
From: fanshuai <1141904845@qq.com>
Date: Tue, 26 Mar 2024 16:45:24 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=BF=94=E5=9B=9E=E6=A1=86?=
=?UTF-8?q?=E6=9E=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
react-ui/config/proxy.ts | 2 +-
ruoyi-common/ruoyi-common-core/pom.xml | 4 +
.../ruoyi/common/core/utils/SortUtils.java | 63 ++++++
.../core/web/controller/BaseController.java | 199 ++++++++++++++----
.../core/web/domain/GenericsAjaxResult.java | 171 +++++++++++++++
.../core/web/page/GenericsTableDataInfo.java | 98 +++++++++
.../experiment/ExperimentController.java | 13 +-
.../experiment/ExperimentInsController.java | 1 +
.../tensorBoard/TensorBoardController.java | 39 ++++
.../controller/tensorBoard/tensorBoard.java | 15 --
.../com/ruoyi/platform/domain/Experiment.java | 2 +
.../ruoyi/platform/domain/ExperimentIns.java | 1 +
.../platform/service/TensorBoardService.java | 13 ++
.../service/impl/JupyterServiceImpl.java | 4 +-
.../service/impl/TensorBoardServiceImpl.java | 35 +++
.../ruoyi/platform/utils/K8sClientUtil.java | 73 ++++++-
.../com/ruoyi/platform/vo/FrameLogPathVo.java | 37 ++++
17 files changed, 702 insertions(+), 68 deletions(-)
create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SortUtils.java
create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/domain/GenericsAjaxResult.java
create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/page/GenericsTableDataInfo.java
create mode 100644 ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/tensorBoard/TensorBoardController.java
delete mode 100644 ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/tensorBoard/tensorBoard.java
create mode 100644 ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/TensorBoardService.java
create mode 100644 ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/TensorBoardServiceImpl.java
create mode 100644 ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/FrameLogPathVo.java
diff --git a/react-ui/config/proxy.ts b/react-ui/config/proxy.ts
index 911db70..fc98495 100644
--- a/react-ui/config/proxy.ts
+++ b/react-ui/config/proxy.ts
@@ -15,7 +15,7 @@ export default {
// localhost:8000/api/** -> https://preview.pro.ant.design/api/**
'/api/': {
// 要代理的地址
- // target: 'http://172.20.32.181:31205',
+ // target: 'ci4s-gateway-service.ci4s-test.svc:8082',
// target: 'http://172.20.32.98:8082',
target: 'http://172.20.32.150:8082',
// 配置了这个可以从 http 代理到 https
diff --git a/ruoyi-common/ruoyi-common-core/pom.xml b/ruoyi-common/ruoyi-common-core/pom.xml
index b394ea9..67735a9 100644
--- a/ruoyi-common/ruoyi-common-core/pom.xml
+++ b/ruoyi-common/ruoyi-common-core/pom.xml
@@ -112,6 +112,10 @@
io.swagger
swagger-annotations
+
+ org.projectlombok
+ lombok
+
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SortUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SortUtils.java
new file mode 100644
index 0000000..7d1e233
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SortUtils.java
@@ -0,0 +1,63 @@
+package com.ruoyi.common.core.utils;
+
+import com.ruoyi.common.core.exception.ServiceException;
+
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author otto
+ */
+public class SortUtils {
+ public static List> sort(List> list, final String param, boolean isAsc) {
+ //自定义Comparator对象,自定义排序
+ Comparator c = (o1, o2) -> {
+ try {
+ Field field1 = o1.getClass().getDeclaredField(param);
+ Field field2 = o2.getClass().getDeclaredField(param);
+ field1.setAccessible(true);
+ field2.setAccessible(true);
+ if (Integer.class.equals(field1.getType())) {
+ if ((Integer) field1.get(o1) < (Integer) field2.get(o2)) {
+ return isAsc ? -1 : 1;
+ } else {
+ //注意!!返回值必须是一对相反数,否则无效。jdk1.7以后就是这样。
+ return isAsc ? 1 : -1;
+ }
+ }
+ if (Long.class.equals(field1.getType())) {
+ Long long1 = (Long) field1.get(o1);
+ Long long2 = (Long) field2.get(o2);
+ if (long1 < long2) {
+ return isAsc ? -1 : 1;
+ } else {
+ //注意!!返回值必须是一对相反数,否则无效。jdk1.7以后就是这样。
+ return isAsc ? 1 : -1;
+ }
+ }
+ if (Date.class.equals(field1.getType())) {
+ Date date1 = (Date) field1.get(o1);
+ Date date2 = (Date) field2.get(o2);
+ if (date1.before(date2)) {
+ return isAsc ? -1 : 1;
+ } else {
+ //注意!!返回值必须是一对相反数,否则无效。jdk1.7以后就是这样。
+ return isAsc ? 1 : -1;
+ }
+ }
+
+ } catch (NoSuchFieldException e) {
+ throw new ServiceException(String.format("指定的排序字段不存在[%s]", param));
+ } catch (IllegalAccessException e) {
+ throw new ServiceException(String.format("访问排序字段非法,请检查排序字段[%s]权限", param));
+ }
+ return 1;
+ };
+ Collections.sort(list, c);
+ return list;
+
+ }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/controller/BaseController.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/controller/BaseController.java
index 2bfd8cb..b567af5 100644
--- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/controller/BaseController.java
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/controller/BaseController.java
@@ -1,40 +1,41 @@
package com.ruoyi.common.core.web.controller;
-import java.beans.PropertyEditorSupport;
-import java.util.Date;
-import java.util.List;
+import com.github.pagehelper.PageInfo;
+import com.ruoyi.common.core.constant.Constants;
+import com.ruoyi.common.core.constant.HttpStatus;
+import com.ruoyi.common.core.utils.*;
+import com.ruoyi.common.core.web.domain.AjaxResult;
+import com.ruoyi.common.core.web.domain.GenericsAjaxResult;
+import com.ruoyi.common.core.web.page.GenericsTableDataInfo;
+import com.ruoyi.common.core.web.page.PageDomain;
+import com.ruoyi.common.core.web.page.TableDataInfo;
+import com.ruoyi.common.core.web.page.TableSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
-import com.github.pagehelper.PageInfo;
-import com.ruoyi.common.core.constant.HttpStatus;
-import com.ruoyi.common.core.utils.DateUtils;
-import com.ruoyi.common.core.utils.PageUtils;
-import com.ruoyi.common.core.web.domain.AjaxResult;
-import com.ruoyi.common.core.web.page.TableDataInfo;
+
+import java.beans.PropertyEditorSupport;
+import java.util.Date;
+import java.util.List;
/**
* web层通用数据处理
- *
+ *
* @author ruoyi
*/
-public class BaseController
-{
+public class BaseController {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 将前台传递过来的日期格式的字符串,自动转化为Date类型
*/
@InitBinder
- public void initBinder(WebDataBinder binder)
- {
+ public void initBinder(WebDataBinder binder) {
// Date 类型转换
- binder.registerCustomEditor(Date.class, new PropertyEditorSupport()
- {
+ binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
@Override
- public void setAsText(String text)
- {
+ public void setAsText(String text) {
setValue(DateUtils.parseDate(text));
}
});
@@ -43,25 +44,22 @@ public class BaseController
/**
* 设置请求分页数据
*/
- protected void startPage()
- {
+ protected void startPage() {
PageUtils.startPage();
}
/**
* 清理分页的线程变量
*/
- protected void clearPage()
- {
+ protected void clearPage() {
PageUtils.clearPage();
}
/**
* 响应请求分页数据
*/
- @SuppressWarnings({ "rawtypes", "unchecked" })
- protected TableDataInfo getDataTable(List> list)
- {
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ protected TableDataInfo getDataTable(List> list) {
TableDataInfo rspData = new TableDataInfo();
rspData.setCode(HttpStatus.SUCCESS);
rspData.setRows(list);
@@ -70,73 +68,188 @@ public class BaseController
return rspData;
}
+ /**
+ * 响应请求分页数据
+ */
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ protected GenericsTableDataInfo getGenericsDataTable(List list) {
+ GenericsTableDataInfo rspData = new GenericsTableDataInfo<>();
+ rspData.setCode(HttpStatus.SUCCESS);
+ rspData.setRows(list);
+ rspData.setMsg("查询成功");
+ rspData.setTotal(new PageInfo(list).getTotal());
+ return rspData;
+ }
+
+ /**
+ * 响应请求分页数据
+ */
+
+ protected GenericsTableDataInfo getGenericsDataTable(List list, Integer count) {
+ GenericsTableDataInfo rspData = new GenericsTableDataInfo<>();
+ rspData.setCode(HttpStatus.SUCCESS);
+ rspData.setRows(list);
+ rspData.setMsg("查询成功");
+ rspData.setTotal(count);
+ return rspData;
+ }
+
+ /**
+ * 响应请求分页数据
+ */
+ protected GenericsTableDataInfo getAllGenericsDataTableToPage(List list) {
+ GenericsTableDataInfo rspData = new GenericsTableDataInfo<>();
+ rspData.setCode(HttpStatus.SUCCESS);
+ int total = list.size();
+ rspData.setTotal(total);
+ String orderByStr = ServletUtils.getParameter(Constants.ORDER_BY_COLUMN);
+ if (StringUtils.isNotEmpty(orderByStr)) {
+ String isAscStr = ServletUtils.getParameter(Constants.IS_ASC);
+ if (StringUtils.isNotEmpty(orderByStr)) {
+ String ascString = "asc";
+ boolean isAsc = true;
+ if (isAscStr != null && !ascString.equals(isAscStr.toLowerCase())) {
+ isAsc = false;
+ }
+ SortUtils.sort(list, orderByStr, isAsc);
+ }
+ }
+ if (StringUtils.isNotEmpty(ServletUtils.getParameter(Constants.PAGE_NUM))
+ && StringUtils.isNotEmpty(ServletUtils.getParameter(Constants.PAGE_SIZE))) {
+ PageDomain pageDomain = TableSupport.buildPageRequest();
+ Integer pageNum = pageDomain.getPageNum();
+ Integer pageSize = pageDomain.getPageSize();
+
+ if (pageNum != null && pageSize != null) {
+ if (pageNum > 0) {
+ pageNum = pageNum - 1;
+ } else {
+ pageNum = 0;
+ }
+ int startIndex = pageNum * pageSize;
+ int endIndex = (pageNum + 1) * pageSize;
+
+ int currentSize = total - startIndex;
+ if (currentSize < pageSize && currentSize > 0) {
+ endIndex = startIndex + currentSize;
+ } else if (currentSize <= 0) {
+ if (total > pageSize) {
+ startIndex = total - pageSize - 1;
+ } else {
+ startIndex = 0;
+ endIndex = total;
+ }
+
+ }
+ list = list.subList(startIndex, endIndex);
+ }
+ //todo:暂不考虑 Boolean reasonable = pageDomain.getReasonable();
+ }
+
+ rspData.setRows(list);
+ rspData.setMsg("查询成功");
+ return rspData;
+ }
+
+ /**
+ * 响应请求分页数据
+ */
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ protected TableDataInfo getDataTable(List> list, Integer size) {
+ TableDataInfo rspData = new TableDataInfo();
+ rspData.setCode(HttpStatus.SUCCESS);
+ rspData.setRows(list);
+ rspData.setMsg("查询成功");
+ rspData.setTotal(size);
+ return rspData;
+ }
+
/**
* 返回成功
*/
- public AjaxResult success()
- {
+ public AjaxResult success() {
return AjaxResult.success();
}
/**
* 返回成功消息
*/
- public AjaxResult success(String message)
- {
+ public AjaxResult success(String message) {
return AjaxResult.success(message);
}
/**
* 返回成功消息
*/
- public AjaxResult success(Object data)
- {
+ public AjaxResult success(Object data) {
return AjaxResult.success(data);
}
+ /**
+ * 返回成功消息
+ */
+ public GenericsAjaxResult genericsSuccess(T data) {
+ return GenericsAjaxResult.success(data);
+ }
+
/**
* 返回失败消息
*/
- public AjaxResult error()
- {
+ public AjaxResult error() {
return AjaxResult.error();
}
/**
* 返回失败消息
*/
- public AjaxResult error(String message)
- {
+ public AjaxResult error(String message) {
return AjaxResult.error(message);
}
/**
* 返回警告消息
*/
- public AjaxResult warn(String message)
- {
+ public AjaxResult warn(String message) {
return AjaxResult.warn(message);
}
/**
* 响应返回结果
- *
+ *
* @param rows 影响行数
* @return 操作结果
*/
- protected AjaxResult toAjax(int rows)
- {
+ protected AjaxResult toAjax(int rows) {
return rows > 0 ? AjaxResult.success() : AjaxResult.error();
}
/**
* 响应返回结果
- *
+ *
+ * @param rows 影响行数
+ * @return 操作结果
+ */
+ protected GenericsAjaxResult toGenericsAjax(int rows) {
+ return rows > 0 ? GenericsAjaxResult.success() : GenericsAjaxResult.error();
+ }
+
+ /**
+ * 响应返回结果
+ *
+ * @param data 数据
+ * @return 操作结果
+ */
+ protected GenericsAjaxResult successToGenericsAjax(T data) {
+ return GenericsAjaxResult.success(data);
+ }
+
+ /**
+ * 响应返回结果
+ *
* @param result 结果
* @return 操作结果
*/
- protected AjaxResult toAjax(boolean result)
- {
+ protected AjaxResult toAjax(boolean result) {
return result ? success() : error();
}
}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/domain/GenericsAjaxResult.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/domain/GenericsAjaxResult.java
new file mode 100644
index 0000000..9185011
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/domain/GenericsAjaxResult.java
@@ -0,0 +1,171 @@
+package com.ruoyi.common.core.web.domain;
+
+import com.ruoyi.common.core.constant.HttpStatus;
+import com.ruoyi.common.core.utils.StringUtils;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 操作消息提醒
+ *
+ * @author ruoyi
+ */
+@Data
+@ApiModel("返回对象")
+public class GenericsAjaxResult implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 状态码
+ */
+ @ApiModelProperty("状态码")
+ private Integer code;
+
+ /**
+ * 返回内容
+ */
+ @ApiModelProperty("返回内容")
+ private String msg;
+
+ /**
+ * 数据对象
+ */
+ @ApiModelProperty("数据对象")
+ public T data;
+
+ /**
+ * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
+ */
+ public GenericsAjaxResult() {
+ }
+
+ /**
+ * 初始化一个新创建的 AjaxResult 对象
+ *
+ * @param code 状态码
+ * @param msg 返回内容
+ */
+ public GenericsAjaxResult(int code, String msg) {
+ this.code = code;
+ this.msg = msg;
+ }
+
+ /**
+ * 初始化一个新创建的 AjaxResult 对象
+ *
+ * @param code 状态码
+ * @param msg 返回内容
+ * @param data 数据对象
+ */
+ public GenericsAjaxResult(int code, String msg, T data) {
+ this.code = code;
+ this.msg = msg;
+ if (StringUtils.isNotNull(data)) {
+ this.data = data;
+ }
+ }
+
+ /**
+ * 返回成功消息
+ *
+ * @return 成功消息
+ */
+ public static GenericsAjaxResult success() {
+ return GenericsAjaxResult.success("操作成功");
+ }
+
+ /**
+ * 返回成功数据
+ *
+ * @return 成功消息
+ */
+ public static GenericsAjaxResult success(T data) {
+ return GenericsAjaxResult.success("操作成功", data);
+ }
+
+ /**
+ * 返回成功消息
+ *
+ * @param msg 返回内容
+ * @return 成功消息
+ */
+ public static GenericsAjaxResult success(String msg) {
+ return GenericsAjaxResult.success(msg, null);
+ }
+
+ /**
+ * 返回成功消息
+ *
+ * @param msg 返回内容
+ * @param data 数据对象
+ * @return 成功消息
+ */
+ public static GenericsAjaxResult success(String msg, T data) {
+ return new GenericsAjaxResult<>(HttpStatus.SUCCESS, msg, data);
+ }
+
+ /**
+ * 返回警告消息
+ *
+ * @param msg 返回内容
+ * @return 警告消息
+ */
+ public static GenericsAjaxResult warn(String msg) {
+ return GenericsAjaxResult.warn(msg, null);
+ }
+
+ /**
+ * 返回警告消息
+ *
+ * @param msg 返回内容
+ * @param data 数据对象
+ * @return 警告消息
+ */
+ public static GenericsAjaxResult warn(String msg, T data) {
+ return new GenericsAjaxResult<>(HttpStatus.WARN, msg, data);
+ }
+
+ /**
+ * 返回错误消息
+ *
+ * @return 错误消息
+ */
+ public static GenericsAjaxResult error() {
+ return GenericsAjaxResult.error("操作失败");
+ }
+
+ /**
+ * 返回错误消息
+ *
+ * @param msg 返回内容
+ * @return 错误消息
+ */
+ public static GenericsAjaxResult error(String msg) {
+ return GenericsAjaxResult.error(msg, null);
+ }
+
+ /**
+ * 返回错误消息
+ *
+ * @param msg 返回内容
+ * @param data 数据对象
+ * @return 错误消息
+ */
+ public static GenericsAjaxResult error(String msg, T data) {
+ return new GenericsAjaxResult<>(HttpStatus.ERROR, msg, data);
+ }
+
+ /**
+ * 返回错误消息
+ *
+ * @param code 状态码
+ * @param msg 返回内容
+ * @return 错误消息
+ */
+ public static GenericsAjaxResult error(int code, String msg) {
+ return new GenericsAjaxResult<>(code, msg, null);
+ }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/page/GenericsTableDataInfo.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/page/GenericsTableDataInfo.java
new file mode 100644
index 0000000..9a75e79
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/page/GenericsTableDataInfo.java
@@ -0,0 +1,98 @@
+package com.ruoyi.common.core.web.page;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.github.pagehelper.Page;
+import com.github.pagehelper.PageInfo;
+import com.ruoyi.common.core.constant.HttpStatus;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * 表格分页数据对象
+ *
+ * @author ruoyi
+ */
+@Data
+@ApiModel("表格分页数据对象")
+public class GenericsTableDataInfo implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 总记录数
+ */
+ @ApiModelProperty("总记录数")
+ private long total;
+
+ /**
+ * 列表数据
+ */
+ @ApiModelProperty("列表数据")
+ private List rows;
+
+ /**
+ * 消息状态码
+ */
+ @ApiModelProperty("消息状态码")
+ private int code;
+
+ /**
+ * 消息内容
+ */
+ @ApiModelProperty("消息内容")
+ private String msg;
+
+
+ /**
+ * 表格数据对象
+ */
+ public GenericsTableDataInfo() {
+ this.total = 0;
+ this.rows = new ArrayList<>();
+ this.code = HttpStatus.SUCCESS;
+ this.msg = "查询成功";
+ }
+
+ /**
+ * 将原始列表通过传入方法转换为对应类型,同时根据原始列表分页数据构建分页对象
+ *
+ * @param rows 原始列表(带分页)
+ * @param toList Lambda表达式,对原始列表进行转换
+ * @param 原始列表列席
+ */
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ public GenericsTableDataInfo(List rows, Page.Function, List> toList) {
+ rows = Optional.ofNullable(rows).orElse(Collections.emptyList());
+ this.total = new PageInfo(rows).getTotal();
+ this.rows = toList.apply(rows);
+ this.code = HttpStatus.SUCCESS;
+ this.msg = "查询成功";
+ }
+
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ public GenericsTableDataInfo(List rows) {
+ this.total = new PageInfo(rows).getTotal();
+ this.rows = rows;
+ this.code = HttpStatus.SUCCESS;
+ this.msg = "查询成功";
+ }
+
+ /**
+ * 分页
+ *
+ * @param list 列表数据
+ * @param total 总记录数
+ */
+ public GenericsTableDataInfo(List list, Long total) {
+ this.rows = list;
+ this.total = total;
+ this.code = HttpStatus.SUCCESS;
+ this.msg = "查询成功";
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentController.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentController.java
index 0dc9a52..c6a9636 100644
--- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentController.java
+++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentController.java
@@ -1,12 +1,15 @@
package com.ruoyi.platform.controller.experiment;
+import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
+import com.ruoyi.common.core.web.domain.GenericsAjaxResult;
import com.ruoyi.platform.domain.Experiment;
import com.ruoyi.platform.service.ExperimentService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.data.domain.PageRequest;
+import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@@ -21,7 +24,7 @@ import java.io.IOException;
@RestController
@RequestMapping("experiment")
@Api("实验管理")
-public class ExperimentController {
+public class ExperimentController extends BaseController {
/**
* 服务对象
*/
@@ -50,8 +53,8 @@ public class ExperimentController {
@GetMapping(("/configuration"))
- public AjaxResult showExperimentConfig(@RequestBody Experiment experiment){
- return AjaxResult.success(this.experimentService.showExperimentConfig(experiment));
+ public GenericsAjaxResult> showExperimentConfig(@RequestBody Experiment experiment){
+ return genericsSuccess(this.experimentService.showExperimentConfig(experiment));
}
/**
@@ -62,8 +65,8 @@ public class ExperimentController {
*/
@GetMapping("{id}")
@ApiOperation("通过id查询实验")
- public AjaxResult queryById(@PathVariable("id") Integer id) throws IOException {
- return AjaxResult.success(this.experimentService.queryById(id));
+ public GenericsAjaxResult queryById(@PathVariable("id") Integer id) throws IOException {
+ return genericsSuccess(this.experimentService.queryById(id));
}
/**
diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java
index c3ab713..0a43196 100644
--- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java
+++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/experiment/ExperimentInsController.java
@@ -6,6 +6,7 @@ import com.ruoyi.platform.service.ExperimentInsService;
import com.ruoyi.platform.vo.LogRequestVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
import org.springframework.data.domain.PageRequest;
import org.springframework.web.bind.annotation.*;
diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/tensorBoard/TensorBoardController.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/tensorBoard/TensorBoardController.java
new file mode 100644
index 0000000..23b99a4
--- /dev/null
+++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/tensorBoard/TensorBoardController.java
@@ -0,0 +1,39 @@
+package com.ruoyi.platform.controller.tensorBoard;
+
+import com.ruoyi.common.core.web.domain.AjaxResult;
+import com.ruoyi.platform.service.TensorBoardService;
+import com.ruoyi.platform.vo.FrameLogPathVo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+@RestController
+@RequestMapping("tensorBoard")
+@Api("TensorBoard管理")
+public class TensorBoardController {
+
+ //状态查询接口
+
+ @Resource
+ private TensorBoardService tensorBoardService;
+
+ /**
+ * 启动tensorBoard接口
+ *
+ * @param frameLogPathVo 存储路径
+ * @return url
+ */
+ @PostMapping("/run")
+ @ApiOperation("启动tensorBoard")
+ @ApiResponse
+ public AjaxResult runTensorBoard(@RequestBody FrameLogPathVo frameLogPathVo) throws Exception {
+ return AjaxResult.success(tensorBoardService.runTensorBoard(frameLogPathVo));
+ }
+
+}
diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/tensorBoard/tensorBoard.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/tensorBoard/tensorBoard.java
deleted file mode 100644
index 5fd78fa..0000000
--- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/tensorBoard/tensorBoard.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.ruoyi.platform.controller.tensorBoard;
-
-import io.swagger.annotations.Api;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-@RestController
-@RequestMapping("tensorBoard")
-@Api("流水线管理")
-public class tensorBoard {
-
- //状态查询接口
-
- //启动tensorBoard接口
-}
diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/Experiment.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/Experiment.java
index 222e8fa..2a775f0 100644
--- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/Experiment.java
+++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/Experiment.java
@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableLogic;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import com.ruoyi.common.core.web.domain.BaseEntity;
+import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
@@ -20,6 +21,7 @@ import java.util.List;
* @since 2023-11-07 15:08:22
*/
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
+@ApiModel("实验对象")
public class Experiment implements Serializable {
private static final long serialVersionUID = 409135817108439880L;
// @ApiModelProperty(name = "id")
diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ExperimentIns.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ExperimentIns.java
index 1573938..1ec0923 100644
--- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ExperimentIns.java
+++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ExperimentIns.java
@@ -2,6 +2,7 @@ package com.ruoyi.platform.domain;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
+import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/TensorBoardService.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/TensorBoardService.java
new file mode 100644
index 0000000..f54ad7d
--- /dev/null
+++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/TensorBoardService.java
@@ -0,0 +1,13 @@
+package com.ruoyi.platform.service;
+
+import com.ruoyi.platform.vo.FrameLogPathVo;
+
+public interface TensorBoardService {
+ /**
+ * 在集群中启动TensorBoard容器,并且返回地址,4小时后销毁
+ * @param frameLogPathVo
+ * @return
+ * @throws Exception
+ */
+ String runTensorBoard(FrameLogPathVo frameLogPathVo) throws Exception;
+}
diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/JupyterServiceImpl.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/JupyterServiceImpl.java
index 066b7e4..b95688d 100644
--- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/JupyterServiceImpl.java
+++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/JupyterServiceImpl.java
@@ -44,8 +44,8 @@ public class JupyterServiceImpl implements JupyterService {
@Override
public String getJupyterServiceUrl() {
LoginUser loginUser = SecurityUtils.getLoginUser();
- String podName = loginUser.getUsername() + "-editor-pod";
- String pvcName = loginUser.getUsername() + "-editor-pvc";
+ String podName = loginUser.getUsername().toLowerCase() + "-editor-pod";
+ String pvcName = loginUser.getUsername().toLowerCase() + "-editor-pvc";
V1PersistentVolumeClaim pvc = K8sClientUtil.createPvc(namespace, pvcName, storage,storageClassName);
Integer podPort = K8sClientUtil.createPod(podName, namespace, port, mountPath, pvc, image);
return masterIp + ":" + podPort;
diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/TensorBoardServiceImpl.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/TensorBoardServiceImpl.java
new file mode 100644
index 0000000..1fb9323
--- /dev/null
+++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/TensorBoardServiceImpl.java
@@ -0,0 +1,35 @@
+package com.ruoyi.platform.service.impl;
+
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.security.utils.SecurityUtils;
+import com.ruoyi.platform.service.TensorBoardService;
+import com.ruoyi.platform.utils.K8sClientUtil;
+import com.ruoyi.platform.vo.FrameLogPathVo;
+import com.ruoyi.system.api.model.LoginUser;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+@Service
+public class TensorBoardServiceImpl implements TensorBoardService {
+ @Value("${tensorBoard.image}")
+ private String image;
+ @Value("${tensorBoard.port}")
+ private Integer port;
+ @Value("${tensorBoard.mountPath}")
+ private String mountPath;
+ @Value("${tensorBoard.masterIp}")
+ private String masterIp;
+ @Override
+ public String runTensorBoard(FrameLogPathVo frameLogPathVo) throws Exception {
+ if (StringUtils.isEmpty(frameLogPathVo.getPath())||StringUtils.isEmpty(frameLogPathVo.getPvcName())){
+ throw new Exception("存储路径或存储为空");
+ }
+ LoginUser loginUser = SecurityUtils.getLoginUser();
+ String podName = loginUser.getUsername().toLowerCase()+"-"+frameLogPathVo.getPath().split("/")[2]+ "-tensorboard-pod";
+ Integer podPort = K8sClientUtil.createPodWithSubPath(podName, StringUtils.isEmpty(frameLogPathVo.getNamespace())?"default":frameLogPathVo.getNamespace(), port, mountPath,frameLogPathVo.getPath(), frameLogPathVo.getPvcName(), image);
+ return masterIp + ":" + podPort;
+ }
+}
diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java
index fab2b2c..19beb71 100644
--- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java
+++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java
@@ -265,9 +265,9 @@ public class K8sClientUtil {
try {
pod = api.createNamespacedPod(namespace, pod, null, null, null);
} catch (ApiException e) {
- log.error("创建pvc异常:" + e.getResponseBody(), e);
+ log.error("创建pod异常:" + e.getResponseBody(), e);
} catch (Exception e) {
- log.error("创建pvc系统异常:", e);
+ log.error("创建pod系统异常:", e);
}
V1Service service = createService(namespace, podName + "-svc", port, selector);
@@ -275,6 +275,75 @@ public class K8sClientUtil {
}
+ /**
+ * 创建k8s 临时POD
+ * @param podName pod name
+ * @param namespace 命名空间
+ * @param port port
+ * @param mountPath 映射路径
+ * @param subPath pvc子路径
+ * @param pvcName 存储名
+ * @param image 镜像
+ * @return 创建成功的pod,的nodePort端口
+ */
+
+ public static Integer createPodWithSubPath(String podName, String namespace, Integer port ,String mountPath,String subPath,String pvcName, String image){
+
+ Map selector = new LinkedHashMap();
+ selector.put("k8s-jupyter", podName);
+
+ CoreV1Api api = new CoreV1Api(apiClient);
+ V1PodList v1PodList = null;
+ try {
+ v1PodList = api.listNamespacedPod(namespace, null, null, null, null, null, null, null, null, null, null);
+ } catch (ApiException e) {
+ log.error("获取 POD 异常:", e);
+ }
+ if (v1PodList!=null) {
+ for (V1Pod pod1 : v1PodList.getItems()) {
+ if (StringUtils.equals(pod1.getMetadata().getName(), podName)) {
+ // PVC 已存在
+
+ V1Service service = createService(namespace, podName + "-svc", port, selector);
+ if (service != null) {
+ return service.getSpec().getPorts().get(0).getNodePort();
+ }
+ }
+ }
+ }
+
+ V1Pod pod = new V1PodBuilder()
+ .withNewMetadata()
+ .withName(podName)
+ .withLabels(selector)
+ .endMetadata()
+ .withNewSpec()
+ .addNewContainer()
+ .withName(podName)
+ .withImage(image)
+ .withPorts(new V1ContainerPort().containerPort(port).protocol("TCP"))
+ .withVolumeMounts(new V1VolumeMount().name("workspace").mountPath(mountPath).subPath(subPath))
+ .endContainer()
+ .addNewVolume()
+ .withName("workspace").withPersistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvcName))
+ .endVolume()
+ .withTerminationGracePeriodSeconds(14400L) //默认不被操作4小时后删除
+ .endSpec()
+ .build();
+
+
+ try {
+ pod = api.createNamespacedPod(namespace, pod, null, null, null);
+ } catch (ApiException e) {
+ log.error("创建pod异常:" + e.getResponseBody(), e);
+ } catch (Exception e) {
+ log.error("创建pod系统异常:", e);
+ }
+
+ V1Service service = createService(namespace, podName + "-svc", port, selector);
+ return service.getSpec().getPorts().get(0).getNodePort();
+ }
+
/**
* 根据获取namespace,deploymentName的Pod Name
*
diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/FrameLogPathVo.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/FrameLogPathVo.java
new file mode 100644
index 0000000..99a0301
--- /dev/null
+++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/FrameLogPathVo.java
@@ -0,0 +1,37 @@
+package com.ruoyi.platform.vo;
+
+import com.fasterxml.jackson.databind.PropertyNamingStrategy;
+import com.fasterxml.jackson.databind.annotation.JsonNaming;
+
+import java.io.Serializable;
+
+@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
+public class FrameLogPathVo implements Serializable {
+ String path;
+ String namespace;
+ String pvcName;
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ public String getNamespace() {
+ return namespace;
+ }
+
+ public void setNamespace(String namespace) {
+ this.namespace = namespace;
+ }
+
+ public String getPvcName() {
+ return pvcName;
+ }
+
+ public void setPvcName(String pvcName) {
+ this.pvcName = pvcName;
+ }
+}