Browse Source

Merge remote-tracking branch 'origin/dev' into dev-czh

dev-DXTZYK
chenzhihang 1 year ago
parent
commit
2a200fcabf
25 changed files with 269 additions and 325 deletions
  1. +5
    -1
      k8s/template-yaml/k8s-7management.yaml
  2. +2
    -1
      react-ui/src/components/IFramePage/index.tsx
  3. +9
    -1
      react-ui/src/components/ParameterSelect/config.tsx
  4. +4
    -1
      react-ui/src/components/ResourceSelect/index.tsx
  5. +7
    -0
      react-ui/src/pages/Dataset/components/ResourceInfo/index.less
  6. +28
    -16
      react-ui/src/pages/Dataset/components/ResourceInfo/index.tsx
  7. +3
    -3
      react-ui/src/pages/Dataset/components/ResourceList/index.tsx
  8. +2
    -7
      react-ui/src/pages/Model/components/ModelEvolution/index.less
  9. +5
    -8
      react-ui/src/pages/Model/components/ModelEvolution/index.tsx
  10. +71
    -53
      react-ui/src/pages/Model/components/ModelEvolution/utils.tsx
  11. +2
    -0
      react-ui/src/pages/Model/components/NodeTooltips/index.less
  12. +14
    -18
      react-ui/src/pages/Model/components/NodeTooltips/index.tsx
  13. +4
    -1
      react-ui/src/pages/Pipeline/components/PipelineNodeDrawer/index.tsx
  14. +0
    -115
      react-ui/src/pages/Pipeline/components/ResourceSelectorModal/config.tsx
  15. +8
    -1
      react-ui/src/pages/Pipeline/components/ResourceSelectorModal/index.tsx
  16. +6
    -6
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/GitService.java
  17. +3
    -1
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/DatasetVersionServiceImpl.java
  18. +10
    -15
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/GitServiceImpl.java
  19. +3
    -1
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ImageServiceImpl.java
  20. +8
    -6
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/JupyterServiceImpl.java
  21. +15
    -9
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ModelsServiceImpl.java
  22. +23
    -37
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/NewDatasetServiceImpl.java
  23. +7
    -3
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/TensorBoardServiceImpl.java
  24. +21
    -21
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java
  25. +9
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/FrameLogPathVo.java

+ 5
- 1
k8s/template-yaml/k8s-7management.yaml View File

@@ -18,7 +18,11 @@ spec:
image: ${k8s-7management-image} image: ${k8s-7management-image}
ports: ports:
- containerPort: 9213 - containerPort: 9213

env:
- name: http_proxy
value: "http://172.20.32.253:3128"
- name: https_proxy
value: "http://172.20.32.253:3128"
--- ---
apiVersion: v1 apiVersion: v1
kind: Service kind: Service


+ 2
- 1
react-ui/src/components/IFramePage/index.tsx View File

@@ -9,6 +9,7 @@ import {
} from '@/utils/sessionStorage'; } from '@/utils/sessionStorage';
import classNames from 'classnames'; import classNames from 'classnames';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { createPortal } from 'react-dom';
import './index.less'; import './index.less';


export enum IframePageType { export enum IframePageType {
@@ -61,7 +62,7 @@ function IframePage({ type, className, style }: IframePageProps) {


return ( return (
<div className={classNames('kf-iframe-page', className)} style={style}> <div className={classNames('kf-iframe-page', className)} style={style}>
{loading && <KFSpin size="large" />}
{loading && createPortal(<KFSpin size="large" />, document.body)}
<FullScreenFrame url={iframeUrl} onload={hideLoading} onerror={hideLoading} /> <FullScreenFrame url={iframeUrl} onload={hideLoading} onerror={hideLoading} />
</div> </div>
); );


+ 9
- 1
react-ui/src/components/ParameterSelect/config.tsx View File

@@ -14,7 +14,15 @@ const filterResourceStandard: SelectProps<string, ComputingResource>['filterOpti
}; };


// id 从 number 转换为 string // id 从 number 转换为 string
const convertId = (item: any) => ({ ...item, id: `${item.id}-${item.identifier}` });
const convertId = (item: any) => ({
...item,
id: JSON.stringify({
id: item.id,
name: item.name,
identifier: item.identifier,
owner: item.owner,
}),
});


export type SelectPropsConfig = { export type SelectPropsConfig = {
getOptions: () => Promise<any>; // 获取下拉数据 getOptions: () => Promise<any>; // 获取下拉数据


+ 4
- 1
react-ui/src/components/ResourceSelect/index.tsx View File

@@ -37,7 +37,7 @@ function ResourceSelect({ type, value, onChange, ...rest }: ResourceSelectProps)
onOk: (res) => { onOk: (res) => {
setSelectedResource(res); setSelectedResource(res);
if (res) { if (res) {
const { activeTab, id, name, version, path } = res;
const { activeTab, id, name, version, path, identifier, owner } = res;
if (type === ResourceSelectorType.Mirror) { if (type === ResourceSelectorType.Mirror) {
onChange?.({ onChange?.({
value: path, value: path,
@@ -50,8 +50,11 @@ function ResourceSelect({ type, value, onChange, ...rest }: ResourceSelectProps)
} else { } else {
const jsonObj = { const jsonObj = {
id, id,
name,
version, version,
path, path,
identifier,
owner,
}; };
const jsonObjStr = JSON.stringify(jsonObj); const jsonObjStr = JSON.stringify(jsonObj);
const showValue = `${name}:${version}`; const showValue = `${name}:${version}`;


+ 7
- 0
react-ui/src/pages/Dataset/components/ResourceInfo/index.less View File

@@ -34,12 +34,19 @@
} }


&__bottom { &__bottom {
position: relative;
height: calc(100% - 135px); height: calc(100% - 135px);
padding: 8px 30px 20px; padding: 8px 30px 20px;
background: #ffffff; background: #ffffff;
border-radius: 10px; border-radius: 10px;
box-shadow: 0px 2px 12px rgba(180, 182, 191, 0.09); box-shadow: 0px 2px 12px rgba(180, 182, 191, 0.09);


&__legend {
position: absolute;
top: 20px;
right: 30px;
}

:global { :global {
.ant-tabs { .ant-tabs {
height: 100%; height: 100%;


+ 28
- 16
react-ui/src/pages/Dataset/components/ResourceInfo/index.tsx View File

@@ -11,14 +11,13 @@ import {
ResourceVersionData, ResourceVersionData,
resourceConfig, resourceConfig,
} from '@/pages/Dataset/config'; } from '@/pages/Dataset/config';
import GraphLegend from '@/pages/Model/components/GraphLegend';
import ModelEvolution from '@/pages/Model/components/ModelEvolution'; import ModelEvolution from '@/pages/Model/components/ModelEvolution';
import { openAntdModal } from '@/utils/modal'; import { openAntdModal } from '@/utils/modal';
import { to } from '@/utils/promise'; import { to } from '@/utils/promise';
import { getSessionStorageItem, resourceItemKey } from '@/utils/sessionStorage';
import { modalConfirm } from '@/utils/ui'; import { modalConfirm } from '@/utils/ui';
import { useParams, useSearchParams } from '@umijs/max'; import { useParams, useSearchParams } from '@umijs/max';
import { App, Button, Flex, Select, Tabs } from 'antd'; import { App, Button, Flex, Select, Tabs } from 'antd';
import { pick } from 'lodash';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import AddVersionModal from '../AddVersionModal'; import AddVersionModal from '../AddVersionModal';
import ResourceIntro from '../ResourceIntro'; import ResourceIntro from '../ResourceIntro';
@@ -40,30 +39,32 @@ const ResourceInfo = ({ resourceType }: ResourceInfoProps) => {
const [info, setInfo] = useState<ResourceData>({} as ResourceData); const [info, setInfo] = useState<ResourceData>({} as ResourceData);
const locationParams = useParams(); const locationParams = useParams();
const [searchParams] = useSearchParams(); const [searchParams] = useSearchParams();
const resourceId = Number(locationParams.id);
// 模型演化传入的 tab // 模型演化传入的 tab
const defaultTab = searchParams.get('tab') || ResourceInfoTabKeys.Introduction; const defaultTab = searchParams.get('tab') || ResourceInfoTabKeys.Introduction;
// 模型演化传入的版本 // 模型演化传入的版本
let versionParam = searchParams.get('version'); let versionParam = searchParams.get('version');
const name = searchParams.get('name') || '';
const owner = searchParams.get('owner') || '';
const identifier = searchParams.get('identifier') || '';
const [versionList, setVersionList] = useState<ResourceVersionData[]>([]); const [versionList, setVersionList] = useState<ResourceVersionData[]>([]);
const [version, setVersion] = useState<string | undefined>(undefined); const [version, setVersion] = useState<string | undefined>(undefined);
const [activeTab, setActiveTab] = useState<string>(defaultTab); const [activeTab, setActiveTab] = useState<string>(defaultTab);
const resourceId = Number(locationParams.id);
const config = resourceConfig[resourceType]; const config = resourceConfig[resourceType];
const typeName = config.name; // 数据集/模型 const typeName = config.name; // 数据集/模型
const { message } = App.useApp(); const { message } = App.useApp();


useEffect(() => { useEffect(() => {
const info = getSessionStorageItem(resourceItemKey, true);
if (info) {
setInfo(info);
getVersionList(pick(info, ['owner', 'identifier']));
}
}, [resourceId]);
getVersionList();
}, [resourceId, owner, identifier]);


useEffect(() => { useEffect(() => {
if (version) { if (version) {
getResourceDetail({ getResourceDetail({
...pick(info, ['owner', 'name', 'id', 'identifier']),
id: resourceId,
owner,
name,
identifier,
version, version,
}); });
} }
@@ -85,9 +86,14 @@ const ResourceInfo = ({ resourceType }: ResourceInfoProps) => {
}; };


// 获取版本列表 // 获取版本列表
const getVersionList = async (params: { owner: string; identifier: string }) => {
const getVersionList = async () => {
const request = config.getVersions; const request = config.getVersions;
const [res] = await to(request(params));
const [res] = await to(
request({
owner,
identifier,
}),
);
if (res && res.data && res.data.length > 0) { if (res && res.data && res.data.length > 0) {
setVersionList(res.data); setVersionList(res.data);
if ( if (
@@ -112,7 +118,7 @@ const ResourceInfo = ({ resourceType }: ResourceInfoProps) => {
resoureName: info.name, resoureName: info.name,
identifier: info.identifier, identifier: info.identifier,
onOk: () => { onOk: () => {
getVersionList(pick(info, ['owner', 'identifier']));
getVersionList();
close(); close();
}, },
}); });
@@ -127,13 +133,16 @@ const ResourceInfo = ({ resourceType }: ResourceInfoProps) => {
const deleteVersion = async () => { const deleteVersion = async () => {
const request = config.deleteVersion; const request = config.deleteVersion;
const params = { const params = {
...pick(info, ['id', 'owner', 'identifier', 'relative_paths']),
id: resourceId,
owner,
identifier,
relative_paths: info.relative_paths,
version, version,
}; };
const [res] = await to(request(params)); const [res] = await to(request(params));
if (res) { if (res) {
message.success('删除成功'); message.success('删除成功');
getVersionList(pick(info, ['owner', 'identifier']));
getVersionList();
} }
}; };


@@ -174,7 +183,7 @@ const ResourceInfo = ({ resourceType }: ResourceInfoProps) => {
<ModelEvolution <ModelEvolution
resourceId={resourceId} resourceId={resourceId}
version={version} version={version}
identifier={info.identifier}
identifier={identifier}
isActive={activeTab === ResourceInfoTabKeys.Evolution} isActive={activeTab === ResourceInfoTabKeys.Evolution}
onVersionChange={handleVersionChange} onVersionChange={handleVersionChange}
></ModelEvolution> ></ModelEvolution>
@@ -228,6 +237,9 @@ const ResourceInfo = ({ resourceType }: ResourceInfoProps) => {
</div> </div>
<div className={styles['resource-info__bottom']}> <div className={styles['resource-info__bottom']}>
<Tabs activeKey={activeTab} items={items} onChange={(key) => setActiveTab(key)}></Tabs> <Tabs activeKey={activeTab} items={items} onChange={(key) => setActiveTab(key)}></Tabs>
<div className={styles['resource-info__bottom__legend']}>
{activeTab === ResourceInfoTabKeys.Evolution && <GraphLegend />}
</div>
</div> </div>
</div> </div>
); );


+ 3
- 3
react-ui/src/pages/Dataset/components/ResourceList/index.tsx View File

@@ -4,7 +4,6 @@ import { CommonTabKeys } from '@/enums';
import AddModelModal from '@/pages/Dataset/components/AddModelModal'; import AddModelModal from '@/pages/Dataset/components/AddModelModal';
import { openAntdModal } from '@/utils/modal'; import { openAntdModal } from '@/utils/modal';
import { to } from '@/utils/promise'; import { to } from '@/utils/promise';
import { resourceItemKey, setSessionStorageItem } from '@/utils/sessionStorage';
import { modalConfirm } from '@/utils/ui'; import { modalConfirm } from '@/utils/ui';
import { useNavigate } from '@umijs/max'; import { useNavigate } from '@umijs/max';
import { App, Button, Input, Pagination, PaginationProps } from 'antd'; import { App, Button, Input, Pagination, PaginationProps } from 'antd';
@@ -138,8 +137,9 @@ function ResourceList(
activeTag: dataTag, activeTag: dataTag,
}); });
const prefix = config.prefix; const prefix = config.prefix;
setSessionStorageItem(resourceItemKey, record, true);
navigate(`/dataset/${prefix}/info/${record.id}`);
navigate(
`/dataset/${prefix}/info/${record.id}?name=${record.name}&owner=${record.owner}&identifier=${record.identifier}`,
);
}; };


// 分页切换 // 分页切换


+ 2
- 7
react-ui/src/pages/Model/components/ModelEvolution/index.less View File

@@ -1,16 +1,11 @@
.model-evolution { .model-evolution {
width: 100%; width: 100%;
height: 100%; height: 100%;
overflow-x: hidden;
background-color: white; background-color: white;


&__top {
padding: 30px 0;
color: @text-color;
font-size: @font-size-content;
}

&__graph { &__graph {
height: calc(100% - 92px);
height: calc(100%);
background-color: @background-color; background-color: @background-color;
background-image: url(@/assets/img/pipeline-canvas-bg.png); background-image: url(@/assets/img/pipeline-canvas-bg.png);
background-size: 100% 100%; background-size: 100% 100%;


+ 5
- 8
react-ui/src/pages/Model/components/ModelEvolution/index.tsx View File

@@ -9,9 +9,8 @@ import { getModelAtlasReq } from '@/services/dataset/index.js';
import themes from '@/styles/theme.less'; import themes from '@/styles/theme.less';
import { to } from '@/utils/promise'; import { to } from '@/utils/promise';
import G6, { G6GraphEvent, Graph, INode } from '@antv/g6'; import G6, { G6GraphEvent, Graph, INode } from '@antv/g6';
import { Flex } from 'antd';
import { useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import GraphLegend from '../GraphLegend';
import NodeTooltips from '../NodeTooltips'; import NodeTooltips from '../NodeTooltips';
import styles from './index.less'; import styles from './index.less';
import type { ModelDepsData, ProjectDependency, TrainDataset } from './utils'; import type { ModelDepsData, ProjectDependency, TrainDataset } from './utils';
@@ -145,14 +144,15 @@ function ModelEvolution({
// 更加缩放,调整 tooltip 位置 // 更加缩放,调整 tooltip 位置
const offsetX = (nodeWidth * zoom) / 4; const offsetX = (nodeWidth * zoom) / 4;
const offsetY = (nodeHeight * zoom) / 4; const offsetY = (nodeHeight * zoom) / 4;
point.x += offsetX;


const canvasWidth = graphRef.current!.clientWidth; const canvasWidth = graphRef.current!.clientWidth;
if (point.x + 300 > canvasWidth) {
point.x = canvasWidth - 300;
if (point.x + 300 > canvasWidth + 30) {
point.x = canvasWidth + 30 - 300;
} }


setHoverNodeData(model); setHoverNodeData(model);
setNodeToolTipX(point.x + offsetX);
setNodeToolTipX(point.x);
setNodeToolTipY(graphRef.current!.clientHeight - point.y + offsetY); setNodeToolTipY(graphRef.current!.clientHeight - point.y + offsetY);
setShowNodeTooltip(true); setShowNodeTooltip(true);
}); });
@@ -248,9 +248,6 @@ function ModelEvolution({


return ( return (
<div className={styles['model-evolution']}> <div className={styles['model-evolution']}>
<Flex align="center" className={styles['model-evolution__top']}>
<GraphLegend style={{ marginRight: 0, marginLeft: 'auto' }}></GraphLegend>
</Flex>
<div className={styles['model-evolution__graph']} id="canvas" ref={graphRef}></div> <div className={styles['model-evolution__graph']} id="canvas" ref={graphRef}></div>
{(showNodeTooltip || enterTooltip) && ( {(showNodeTooltip || enterTooltip) && (
<NodeTooltips <NodeTooltips


+ 71
- 53
react-ui/src/pages/Model/components/ModelEvolution/utils.tsx View File

@@ -38,9 +38,11 @@ export type TrainTask = {
}; };


export interface TrainDataset extends NodeConfig { export interface TrainDataset extends NodeConfig {
dataset_id: number;
dataset_name: string;
dataset_version: string;
repo_id: number;
name: string;
version: string;
identifier: string;
owner: string;
model_type: NodeType.TestDataset | NodeType.TrainDataset; model_type: NodeType.TestDataset | NodeType.TrainDataset;
} }


@@ -51,34 +53,33 @@ export interface ProjectDependency extends NodeConfig {
model_type: NodeType.Project; model_type: NodeType.Project;
} }


export type ModalDetail = {
export type ModelMeta = {
train_datasets?: TrainDataset[];
test_datasets?: TrainDataset[];
project_depency?: ProjectDependency;
train_task?: TrainTask;
name: string; name: string;
available_range: number;
file_name: string;
file_size: string;
description: string;
model_type_name: string;
model_tag_name: string;
version: string;
model_source: string;
model_type: string;
create_time: string; create_time: string;
file_size: string;
is_public: boolean;
}; };


export interface ModelDepsAPIData { export interface ModelDepsAPIData {
current_model_id: number;
repo_id: number;
model_name: string;
version: string; version: string;
workflow_id: number; workflow_id: number;
exp_ins_id: number; exp_ins_id: number;
model_type: NodeType.Children | NodeType.Current | NodeType.Parent; model_type: NodeType.Children | NodeType.Current | NodeType.Parent;
current_model_name: string;
project_dependency?: ProjectDependency;
test_dataset: TrainDataset[];
train_dataset: TrainDataset[];
train_task: TrainTask;
model_version_dependcy_vo: ModalDetail;
children_models: ModelDepsAPIData[];
parent_models: ModelDepsAPIData[];
model_meta: ModelMeta;
child_model_list: ModelDepsAPIData[];
parent_model_vo?: ModelDepsAPIData;
} }


export interface ModelDepsData extends Omit<ModelDepsAPIData, 'children_models'>, TreeGraphData {
export interface ModelDepsData extends Omit<ModelDepsAPIData, 'child_model_list'>, TreeGraphData {
children: ModelDepsData[]; children: ModelDepsData[];
expanded: boolean; // 是否展开 expanded: boolean; // 是否展开
level: number; // 层级,从 0 开始 level: number; // 层级,从 0 开始
@@ -92,8 +93,11 @@ export function normalizeChildren(data: ModelDepsData[]) {
item.model_type = NodeType.Children; item.model_type = NodeType.Children;
item.expanded = false; item.expanded = false;
item.level = 0; item.level = 0;
item.datasetLen = item.train_dataset.length + item.test_dataset.length;
item.id = `$M_${item.current_model_id}_${item.version}`;
item.datasetLen = getDatasetLen(
item.model_meta.train_datasets,
item.model_meta.test_datasets,
);
item.id = `$M_${item.repo_id}_${item.version}`;
item.label = getLabel(item); item.label = getLabel(item);
item.style = getStyle(NodeType.Children); item.style = getStyle(NodeType.Children);
normalizeChildren(item.children); normalizeChildren(item.children);
@@ -104,16 +108,17 @@ export function normalizeChildren(data: ModelDepsData[]) {
// 获取 label // 获取 label
export function getLabel(node: ModelDepsData | ModelDepsAPIData) { export function getLabel(node: ModelDepsData | ModelDepsAPIData) {
return ( return (
fittingString(
`${node.model_version_dependcy_vo.name ?? ''}`,
nodeWidth - labelPadding,
nodeFontSize,
) +
fittingString(`${node.model_name ?? ''}`, nodeWidth - labelPadding, nodeFontSize) +
'\n' + '\n' +
fittingString(`${node.version}`, nodeWidth - labelPadding, nodeFontSize) fittingString(`${node.version}`, nodeWidth - labelPadding, nodeFontSize)
); );
} }


// 获取数据集数量
export function getDatasetLen(train?: TrainDataset[], test?: TrainDataset[]) {
return (train?.length || 0) + (test?.length || 0);
}

// 获取 style // 获取 style
export function getStyle(model_type: NodeType) { export function getStyle(model_type: NodeType) {
let fill = ''; let fill = '';
@@ -148,41 +153,43 @@ export function getStyle(model_type: NodeType) {
export function normalizeTreeData(apiData: ModelDepsAPIData): ModelDepsData { export function normalizeTreeData(apiData: ModelDepsAPIData): ModelDepsData {
// 将 children_models 转换成 children // 将 children_models 转换成 children
let normalizedData = changePropertyName(apiData, { let normalizedData = changePropertyName(apiData, {
children_models: 'children',
child_model_list: 'children',
}) as ModelDepsData; }) as ModelDepsData;


// 设置当前模型的数据 // 设置当前模型的数据
normalizedData.model_type = NodeType.Current; normalizedData.model_type = NodeType.Current;
normalizedData.id = `$M_${normalizedData.current_model_id}_${normalizedData.version}`;
normalizedData.id = `$M_${normalizedData.repo_id}_${normalizedData.version}`;
normalizedData.label = getLabel(normalizedData); normalizedData.label = getLabel(normalizedData);
normalizedData.style = getStyle(NodeType.Current); normalizedData.style = getStyle(NodeType.Current);
normalizedData.expanded = true; normalizedData.expanded = true;
normalizedData.datasetLen =
normalizedData.train_dataset.length + normalizedData.test_dataset.length;
normalizedData.datasetLen = getDatasetLen(
normalizedData.model_meta.train_datasets,
normalizedData.model_meta.test_datasets,
);
normalizeChildren(normalizedData.children as ModelDepsData[]); normalizeChildren(normalizedData.children as ModelDepsData[]);
normalizedData.level = 0; normalizedData.level = 0;


// 将 parent_models 转换成树形结构 // 将 parent_models 转换成树形结构
let parent_models = normalizedData.parent_models || [];
while (parent_models.length > 0) {
const parent = parent_models[0];
let parent_model = normalizedData.parent_model_vo;
while (parent_model) {
const parent = parent_model;
normalizedData = { normalizedData = {
...parent, ...parent,
expanded: false, expanded: false,
level: 0, level: 0,
datasetLen: parent.train_dataset.length + parent.test_dataset.length,
datasetLen: getDatasetLen(parent.model_meta.train_datasets, parent.model_meta.test_datasets),
model_type: NodeType.Parent, model_type: NodeType.Parent,
id: `$M_${parent.current_model_id}_${parent.version}`,
id: `$M_${parent.repo_id}_${parent.version}`,
label: getLabel(parent), label: getLabel(parent),
style: getStyle(NodeType.Parent), style: getStyle(NodeType.Parent),
children: [ children: [
{ {
...normalizedData, ...normalizedData,
parent_models: [],
parent_model: null,
}, },
], ],
}; };
parent_models = normalizedData.parent_models || [];
parent_model = normalizedData.parent_model_vo;
} }
return normalizedData; return normalizedData;
} }
@@ -195,11 +202,12 @@ export function getGraphData(data: ModelDepsData, hierarchyNodes: ModelDepsData[
getWidth: () => nodeWidth, getWidth: () => nodeWidth,
getVGap: (node: NodeConfig) => { getVGap: (node: NodeConfig) => {
const model = node as ModelDepsData; const model = node as ModelDepsData;
const { model_type, expanded, project_dependency } = model;
const { model_type, expanded, model_meta } = model;
const { project_depency } = model_meta;
if (model_type === NodeType.Current || model_type === NodeType.Parent) { if (model_type === NodeType.Current || model_type === NodeType.Parent) {
return vGap / 2; return vGap / 2;
} }
const selfGap = expanded && project_dependency?.url ? nodeHeight + vGap : 0;
const selfGap = expanded && project_depency?.url ? nodeHeight + vGap : 0;
const nextNode = getSameHierarchyNextNode(model, hierarchyNodes); const nextNode = getSameHierarchyNextNode(model, hierarchyNodes);
if (!nextNode) { if (!nextNode) {
return vGap / 2; return vGap / 2;
@@ -254,28 +262,35 @@ const addDatasetDependency = (
nodes: NodeConfig[], nodes: NodeConfig[],
edges: EdgeConfig[], edges: EdgeConfig[],
) => { ) => {
const { train_dataset, test_dataset, id } = data;
train_dataset.forEach((item) => {
item.id = `$DTrain_${id}_${item.dataset_id}_${item.dataset_version}`;
const { repo_id, model_meta } = data;
const { train_datasets, test_datasets } = model_meta;
train_datasets?.forEach((item) => {
if (!item.repo_id) {
item.repo_id = item.id;
}
item.id = `$DTrain_${repo_id}_${item.repo_id}_${item.version}`;
item.model_type = NodeType.TrainDataset; item.model_type = NodeType.TrainDataset;
item.style = getStyle(NodeType.TrainDataset); item.style = getStyle(NodeType.TrainDataset);
}); });
test_dataset.forEach((item) => {
item.id = `$DTest_${id}_${item.dataset_id}_${item.dataset_version}`;
test_datasets?.forEach((item) => {
if (!item.repo_id) {
item.repo_id = item.id;
}
item.id = `$DTest_${repo_id}_${item.repo_id}_${item.version}`;
item.model_type = NodeType.TestDataset; item.model_type = NodeType.TestDataset;
item.style = getStyle(NodeType.TestDataset); item.style = getStyle(NodeType.TestDataset);
}); });


datasetNodes.length = 0; datasetNodes.length = 0;
const len = train_dataset.length + test_dataset.length;
[...train_dataset, ...test_dataset].forEach((item, index) => {
const len = getDatasetLen(train_datasets, test_datasets);
[...(train_datasets ?? []), ...(test_datasets ?? [])].forEach((item, index) => {
const node = { ...item }; const node = { ...item };
node.type = 'ellipse'; node.type = 'ellipse';
node.size = [ellipseWidth, nodeHeight]; node.size = [ellipseWidth, nodeHeight];
node.label = node.label =
fittingString(node.dataset_name, ellipseWidth - labelPadding, nodeFontSize) +
fittingString(node.name, ellipseWidth - labelPadding, nodeFontSize) +
'\n' + '\n' +
fittingString(node.dataset_version, ellipseWidth - labelPadding, nodeFontSize);
fittingString(node.version, ellipseWidth - labelPadding, nodeFontSize);


const half = len / 2 - 0.5; const half = len / 2 - 0.5;
node.x = currentNode.x! - (half - index) * (ellipseWidth + datasetHGap); node.x = currentNode.x! - (half - index) * (ellipseWidth + datasetHGap);
@@ -299,10 +314,11 @@ const addProjectDependency = (
nodes: NodeConfig[], nodes: NodeConfig[],
edges: EdgeConfig[], edges: EdgeConfig[],
) => { ) => {
const { project_dependency, id } = data;
if (project_dependency?.url) {
const node = { ...project_dependency };
node.id = `$P_${id}_${node.url}_${node.branch}`;
const { repo_id, model_meta } = data;
const { project_depency } = model_meta;
if (project_depency?.url) {
const node = { ...project_depency };
node.id = `$P_${repo_id}_${node.url}_${node.branch}`;
node.model_type = NodeType.Project; node.model_type = NodeType.Project;
node.type = 'rect'; node.type = 'rect';
node.label = fittingString(node.name, nodeWidth - labelPadding, nodeFontSize); node.label = fittingString(node.name, nodeWidth - labelPadding, nodeFontSize);
@@ -322,6 +338,7 @@ const addProjectDependency = (
} }
}; };


/*
// 判断两个矩形是否相交 // 判断两个矩形是否相交
function isRectanglesOverlap(rect1: Rect, rect2: Rect) { function isRectanglesOverlap(rect1: Rect, rect2: Rect) {
const a2x = rect1.x + rect1.width / 2; const a2x = rect1.x + rect1.width / 2;
@@ -366,6 +383,7 @@ function adjustDatasetPosition(node: NodeConfig) {
}); });
} }
} }
*/


// 层级遍历树结构 // 层级遍历树结构
export function traverseHierarchically(data: ModelDepsData | undefined): ModelDepsData[] { export function traverseHierarchically(data: ModelDepsData | undefined): ModelDepsData[] {


+ 2
- 0
react-ui/src/pages/Model/components/NodeTooltips/index.less View File

@@ -2,6 +2,7 @@
position: absolute; position: absolute;
bottom: -100px; bottom: -100px;
left: -300px; left: -300px;
z-index: 10;
width: 300px; width: 300px;
padding: 10px; padding: 10px;
background: white; background: white;
@@ -50,6 +51,7 @@
flex: 1; flex: 1;
min-width: 0; min-width: 0;
font-weight: 500; font-weight: 500;
word-break: break-all;


&:hover { &:hover {
text-decoration: underline @underline-color; text-decoration: underline @underline-color;


+ 14
- 18
react-ui/src/pages/Model/components/NodeTooltips/index.tsx View File

@@ -14,9 +14,9 @@ function ModelInfo({ resourceId, data, onVersionChange }: ModelInfoProps) {
const navigate = useNavigate(); const navigate = useNavigate();


const gotoExperimentPage = () => { const gotoExperimentPage = () => {
if (data.train_task?.ins_id) {
if (data.model_meta.train_task?.ins_id) {
const { origin } = location; const { origin } = location;
const url = `${origin}/pipeline/experiment/instance/${data.workflow_id}/${data.train_task.ins_id}`;
const url = `${origin}/pipeline/experiment/instance/${data.model_meta.train_task.task_id}/${data.model_meta.train_task.ins_id}`;
window.open(url, '_blank'); window.open(url, '_blank');
} }
}; };
@@ -25,10 +25,10 @@ function ModelInfo({ resourceId, data, onVersionChange }: ModelInfoProps) {
if (data.model_type === NodeType.Current) { if (data.model_type === NodeType.Current) {
return; return;
} }
if (data.current_model_id === resourceId) {
if (data.repo_id === resourceId) {
onVersionChange?.(data.version); onVersionChange?.(data.version);
} else { } else {
const path = `/dataset/model/info/${data.current_model_id}?tab=${ResourceInfoTabKeys.Evolution}&version=${data.version}`;
const path = `/dataset/model/info/${data.repo_id}?tab=${ResourceInfoTabKeys.Evolution}&version=${data.version}&name=${data.model_name}&owner=${data.owner}&identifier=${data.identifier}`;
navigate(path); navigate(path);
} }
}; };
@@ -40,12 +40,10 @@ function ModelInfo({ resourceId, data, onVersionChange }: ModelInfoProps) {
<div className={styles['node-tooltips__row']}> <div className={styles['node-tooltips__row']}>
<span className={styles['node-tooltips__row__title']}>模型名称:</span> <span className={styles['node-tooltips__row__title']}>模型名称:</span>
{data.model_type === NodeType.Current ? ( {data.model_type === NodeType.Current ? (
<span className={styles['node-tooltips__row__value']}>
{data.model_version_dependcy_vo?.name || '--'}
</span>
<span className={styles['node-tooltips__row__value']}>{data.model_name || '--'}</span>
) : ( ) : (
<ValueLink <ValueLink
value={data.model_version_dependcy_vo?.name}
value={data.model_name}
className={styles['node-tooltips__row__link']} className={styles['node-tooltips__row__link']}
nullClassName={styles['node-tooltips__row__value']} nullClassName={styles['node-tooltips__row__value']}
onClick={gotoModelPage} onClick={gotoModelPage}
@@ -59,25 +57,25 @@ function ModelInfo({ resourceId, data, onVersionChange }: ModelInfoProps) {
<div className={styles['node-tooltips__row']}> <div className={styles['node-tooltips__row']}>
<span className={styles['node-tooltips__row__title']}>模型框架:</span> <span className={styles['node-tooltips__row__title']}>模型框架:</span>
<span className={styles['node-tooltips__row__value']}> <span className={styles['node-tooltips__row__value']}>
{data.model_version_dependcy_vo?.model_type_name || '--'}
{data.model_meta.model_type || '--'}
</span> </span>
</div> </div>
<div className={styles['node-tooltips__row']}> <div className={styles['node-tooltips__row']}>
<span className={styles['node-tooltips__row__title']}>模型大小:</span> <span className={styles['node-tooltips__row__title']}>模型大小:</span>
<span className={styles['node-tooltips__row__value']}> <span className={styles['node-tooltips__row__value']}>
{data.model_version_dependcy_vo?.file_size || '--'}
{data.model_meta.file_size || '--'}
</span> </span>
</div> </div>
<div className={styles['node-tooltips__row']}> <div className={styles['node-tooltips__row']}>
<span className={styles['node-tooltips__row__title']}>创建时间:</span> <span className={styles['node-tooltips__row__title']}>创建时间:</span>
<span className={styles['node-tooltips__row__value']}> <span className={styles['node-tooltips__row__value']}>
{formatDate(data.model_version_dependcy_vo?.create_time)}
{formatDate(data.model_meta.create_time || '--')}
</span> </span>
</div> </div>
<div className={styles['node-tooltips__row']}> <div className={styles['node-tooltips__row']}>
<span className={styles['node-tooltips__row__title']}>模型权限:</span> <span className={styles['node-tooltips__row__title']}>模型权限:</span>
<span className={styles['node-tooltips__row__value']}> <span className={styles['node-tooltips__row__value']}>
{data.model_version_dependcy_vo?.available_range === 1 ? '公开' : '私有'}
{data.model_meta.is_public ? '公开' : '私有'}
</span> </span>
</div> </div>
</div> </div>
@@ -86,7 +84,7 @@ function ModelInfo({ resourceId, data, onVersionChange }: ModelInfoProps) {
<div className={styles['node-tooltips__row']}> <div className={styles['node-tooltips__row']}>
<span className={styles['node-tooltips__row__title']}>训练任务:</span> <span className={styles['node-tooltips__row__title']}>训练任务:</span>
<ValueLink <ValueLink
value={data.train_task?.name}
value={data.model_meta.train_task?.name}
className={styles['node-tooltips__row__link']} className={styles['node-tooltips__row__link']}
nullClassName={styles['node-tooltips__row__value']} nullClassName={styles['node-tooltips__row__value']}
onClick={gotoExperimentPage} onClick={gotoExperimentPage}
@@ -100,7 +98,7 @@ function ModelInfo({ resourceId, data, onVersionChange }: ModelInfoProps) {
function DatasetInfo({ data }: { data: TrainDataset }) { function DatasetInfo({ data }: { data: TrainDataset }) {
const gotoDatasetPage = () => { const gotoDatasetPage = () => {
const { origin } = location; const { origin } = location;
const url = `${origin}/dataset/dataset/info/${data.dataset_id}?tab=${ResourceInfoTabKeys.Version}&version=${data.dataset_version}`;
const url = `${origin}/dataset/dataset/info/${data.repo_id}?tab=${ResourceInfoTabKeys.Version}&version=${data.version}&name=${data.name}&owner=${data.owner}&identifier=${data.identifier}`;
window.open(url, '_blank'); window.open(url, '_blank');
}; };


@@ -111,7 +109,7 @@ function DatasetInfo({ data }: { data: TrainDataset }) {
<div className={styles['node-tooltips__row']}> <div className={styles['node-tooltips__row']}>
<span className={styles['node-tooltips__row__title']}>数据集名称:</span> <span className={styles['node-tooltips__row__title']}>数据集名称:</span>
<ValueLink <ValueLink
value={data.dataset_name}
value={data.name}
className={styles['node-tooltips__row__link']} className={styles['node-tooltips__row__link']}
nullClassName={styles['node-tooltips__row__value']} nullClassName={styles['node-tooltips__row__value']}
onClick={gotoDatasetPage} onClick={gotoDatasetPage}
@@ -119,9 +117,7 @@ function DatasetInfo({ data }: { data: TrainDataset }) {
</div> </div>
<div className={styles['node-tooltips__row']}> <div className={styles['node-tooltips__row']}>
<span className={styles['node-tooltips__row__title']}>数据集版本:</span> <span className={styles['node-tooltips__row__title']}>数据集版本:</span>
<span className={styles['node-tooltips__row__value']}>
{data.dataset_version || '--'}
</span>
<span className={styles['node-tooltips__row__value']}>{data.version || '--'}</span>
</div> </div>
</div> </div>
</> </>


+ 4
- 1
react-ui/src/pages/Pipeline/components/PipelineNodeDrawer/index.tsx View File

@@ -204,11 +204,14 @@ const PipelineNodeParameter = forwardRef(({ onFormChange }: PipelineNodeParamete
}); });
} }
} else { } else {
const { activeTab, id, name, version, path } = res;
const { activeTab, id, name, version, path, identifier, owner } = res;
const value = JSON.stringify({ const value = JSON.stringify({
id, id,
name,
version, version,
path, path,
identifier,
owner,
}); });
const showValue = `${name}:${version}`; const showValue = `${name}:${version}`;
form.setFieldValue(formItemName, { form.setFieldValue(formItemName, {


+ 0
- 115
react-ui/src/pages/Pipeline/components/ResourceSelectorModal/config.tsx View File

@@ -74,121 +74,6 @@ const convertMirrorVersionToTreeData = (
})); }));
}; };


// 从树形数据节点 id 中获取数据集版本列表的参数
// const parseDatasetVersionId = (id: string) => {
// const list = id.split('-');
// return {
// id: Number(list[0]),
// name: list[1],
// owner: list[2],
// identifier: list[3],
// version: list[4],
// };
// };

// 从树形数据节点 id 中获取数据集版本列表的参数
// const parseMirrorVersionId = (id: string) => {
// const list = id.split('-');
// return {
// parentId: Number(list[0]),
// id: list[1],
// url: list[2],
// };
// };

// export type MirrorVersion = {
// id: number; // 镜像版本 id
// status: MirrorVersionStatus; // 镜像版本状态
// tag_name: string; // 镜像版本 name
// url: string; // 镜像版本路径
// };

// export type SelectorTypeInfo = {
// getList: (params: any) => Promise<any>; // 获取资源列表
// getVersions: (params: any) => Promise<any>; // 获取资源版本列表
// getFiles: (params: any) => Promise<any>; // 获取资源文件列表
// handleVersionResponse: (res: any) => any[]; // 处理版本列表接口数据
// dataToTreeData: (data: any) => TreeDataNode[]; // 数据转树形结构
// parseTreeNodeId: (id: string) => any; // 获取版本列表请求参数
// modalIcon: string; // modal icon
// buttonIcon: string; // button icon
// name: string; // 名称
// litReqParamKey: 'available_range' | 'image_type'; // 表示是公开还是私有的参数名称,获取资源列表接口使用
// tabItems: TabsProps['items']; // tab 列表
// buttontTitle: string; // 按钮 title
// };

// export const selectorTypeConfig: Record<ResourceSelectorType, SelectorTypeInfo> = {
// [ResourceSelectorType.Model]: {
// getList: getModelList,
// getVersions: getModelVersionList,
// getFiles: getModelVersionIdList,

// name: '模型',
// modalIcon: modelImg,
// buttonIcon: 'icon-xuanzemoxing',
// litReqParamKey: 'available_range',
// tabItems: [
// {
// key: CommonTabKeys.Private,
// label: '我的模型',
// },
// {
// key: CommonTabKeys.Public,
// label: '公开模型',
// },
// ],
// buttontTitle: '选择模型',
// },
// [ResourceSelectorType.Dataset]: {
// getList: getDatasetList,
// getVersions: getDatasetVersionList,
// getFiles: getDatasetInfo,

// name: '数据集',
// modalIcon: datasetImg,
// buttonIcon: 'icon-xuanzeshujuji',
// litReqParamKey: 'available_range',
// tabItems: [
// {
// key: CommonTabKeys.Private,
// label: '我的数据集',
// },
// {
// key: CommonTabKeys.Public,
// label: '公开数据集',
// },
// ],
// buttontTitle: '选择数据集',
// },
// [ResourceSelectorType.Mirror]: {
// getList: getMirrorListReq,
// getVersions: (id: number) => getMirrorVersionListReq({ image_id: id, page: 0, size: 200 }),
// getFiles: getMirrorFilesReq,
// handleVersionResponse: (res) =>
// res.data?.content?.filter(
// (v: MirrorVersionData) => v.status === MirrorVersionStatus.Available,
// ) || [],
// dataToTreeData: convertMirrorToTreeData,
// parseTreeNodeId: (id: string) => id,
// name: '镜像',
// modalIcon: mirrorImg,
// buttonIcon: 'icon-xuanzejingxiang',
// litReqParamKey: 'image_type',
// tabItems: [
// {
// key: CommonTabKeys.Private,
// label: '我的镜像',
// },
// {
// key: CommonTabKeys.Public,
// label: '公开镜像',
// },
// ],
// buttontTitle: '选择镜像',
// },
// };

interface SelectorTypeInfo { interface SelectorTypeInfo {
getList: (isPublic: boolean) => Promise<any>; // 获取资源列表 getList: (isPublic: boolean) => Promise<any>; // 获取资源列表
getVersions: (parentKey: string, parentNode: any) => Promise<any>; // 获取资源版本列表 getVersions: (parentKey: string, parentNode: any) => Promise<any>; // 获取资源版本列表


+ 8
- 1
react-ui/src/pages/Pipeline/components/ResourceSelectorModal/index.tsx View File

@@ -22,6 +22,8 @@ export type ResourceSelectorResponse = {
name: string; // 数据集\模型\镜像 name name: string; // 数据集\模型\镜像 name
version: string; // 数据集\模型\镜像版本 version: string; // 数据集\模型\镜像版本
path: string; // 数据集\模型\镜像版本路径 path: string; // 数据集\模型\镜像版本路径
identifier: string; // 数据集\模型 identifier
owner: string; // 数据集\模型 owner
activeTab: CommonTabKeys; // 是我的还是公开的 activeTab: CommonTabKeys; // 是我的还是公开的
}; };


@@ -221,12 +223,17 @@ function ResourceSelectorModal({
if (checkedKeys.length > 0) { if (checkedKeys.length > 0) {
const last = checkedKeys[0] as string; const last = checkedKeys[0] as string;
const { id, version } = getIdAndVersion(last); const { id, version } = getIdAndVersion(last);
const name = (treeData.find((v) => v.key === id)?.title ?? '') as string;
const treeNode = treeData.find((v) => v.key === id) as any;
const name = (treeNode?.title ?? '') as string;
const identifier = (treeNode?.identifier ?? '') as string;
const owner = (treeNode?.owner ?? '') as string;
const res = { const res = {
id, id,
name, name,
path: versionPath, path: versionPath,
version, version,
identifier,
owner,
activeTab: activeTab as CommonTabKeys, activeTab: activeTab as CommonTabKeys,
}; };
onOk?.(res); onOk?.(res);


+ 6
- 6
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/GitService.java View File

@@ -12,17 +12,17 @@ public interface GitService {
String checkoutToken(); String checkoutToken();


//输入token,项目名,tag,创建新项目,返回项目地址 //输入token,项目名,tag,创建新项目,返回项目地址
Map createProject(GitProjectVo gitProjectVo) throws Exception;
Map createProject(String token,GitProjectVo gitProjectVo) throws Exception;


void createBranch(String owner, String projectName, String branchName, String oldBranchName) throws Exception;
void createBranch(String token,String owner, String projectName, String branchName, String oldBranchName) throws Exception;


void createTopic(Integer id, String topicName) throws Exception;
void createTopic(String token,Integer id, String topicName) throws Exception;


List<Map<String, Object>> getBrancheList(String owner, String projectName) throws Exception;
List<Map<String, Object>> getBrancheList(String token,String owner, String projectName) throws Exception;


void deleteProject(String owner, String projectName) throws Exception;
void deleteProject(String token,String owner, String projectName) throws Exception;


void deleteBranch(String owner, String projectName, String branchName, String localPath) throws Exception;
void deleteBranch(String token,String owner, String projectName, String branchName, String localPath) throws Exception;


Map getUserInfo(String token) throws Exception; Map getUserInfo(String token) throws Exception;
} }

+ 3
- 1
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/DatasetVersionServiceImpl.java View File

@@ -165,7 +165,9 @@ public class DatasetVersionServiceImpl implements DatasetVersionService {
.findFirst() .findFirst()
.ifPresent(datasetVersion -> { .ifPresent(datasetVersion -> {
String url = datasetVersion.getUrl(); String url = datasetVersion.getUrl();
response.put("path", url);
// response.put("path", url);
String path = bucketName + '/' + url.substring(0, url.lastIndexOf('/'));
response.put("path", path);
}); });


response.put("content", datasetVersionList); response.put("content", datasetVersionList);


+ 10
- 15
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/GitServiceImpl.java View File

@@ -28,7 +28,8 @@ public class GitServiceImpl implements GitService {


@Value("${spring.redis.host}") @Value("${spring.redis.host}")
private String redisHost; private String redisHost;

@Value("${spring.redis.port}")
private Integer redisPort;
private static final Logger log = LoggerFactory.getLogger(GitServiceImpl.class); private static final Logger log = LoggerFactory.getLogger(GitServiceImpl.class);


@Override @Override
@@ -61,7 +62,7 @@ public class GitServiceImpl implements GitService {
LoginUser loginUser = SecurityUtils.getLoginUser(); LoginUser loginUser = SecurityUtils.getLoginUser();
String ci4sUsername = loginUser.getUsername(); String ci4sUsername = loginUser.getUsername();
// 将access_token存入Redis // 将access_token存入Redis
Jedis jedis = new Jedis(redisHost);
Jedis jedis = new Jedis(redisHost,redisPort);
jedis.set(ci4sUsername + "_gitToken", accessToken); jedis.set(ci4sUsername + "_gitToken", accessToken);
jedis.set(ci4sUsername + "_gitUserInfo", userReq); jedis.set(ci4sUsername + "_gitUserInfo", userReq);
return accessToken; return accessToken;
@@ -72,7 +73,7 @@ public class GitServiceImpl implements GitService {
} }


public String checkoutToken() { public String checkoutToken() {
Jedis jedis = new Jedis(redisHost);
Jedis jedis = new Jedis(redisHost,redisPort);
LoginUser loginUser = SecurityUtils.getLoginUser(); LoginUser loginUser = SecurityUtils.getLoginUser();
String ci4sUsername = loginUser.getUsername(); String ci4sUsername = loginUser.getUsername();
String token = jedis.get(ci4sUsername + "_gitToken"); String token = jedis.get(ci4sUsername + "_gitToken");
@@ -98,20 +99,18 @@ public class GitServiceImpl implements GitService {
} }


@Override @Override
public Map createProject(GitProjectVo gitProjectVo) throws Exception {
String token = this.checkoutToken();
public Map createProject(String token,GitProjectVo gitProjectVo) throws Exception {
String userReq = HttpUtils.sendPostWithToken("https://www.gitlink.org.cn/api/projects.json", JsonUtils.objectToJson(gitProjectVo), token); String userReq = HttpUtils.sendPostWithToken("https://www.gitlink.org.cn/api/projects.json", JsonUtils.objectToJson(gitProjectVo), token);
return JsonUtils.jsonToMap(userReq); return JsonUtils.jsonToMap(userReq);
} }


@Override @Override
public void createBranch(String owner, String projectName, String branchName, String oldBranchName) throws Exception {
public void createBranch(String token,String owner, String projectName, String branchName, String oldBranchName) throws Exception {
//https://www.gitlink.org.cn/api/v1/fanshuai/testdssa8755/branches.json //https://www.gitlink.org.cn/api/v1/fanshuai/testdssa8755/branches.json
// { // {
// "new_branch_name": "SsS", // "new_branch_name": "SsS",
// "old_branch_name": "master" // "old_branch_name": "master"
// } // }
String token = this.checkoutToken();
String createBranchUrl = "https://www.gitlink.org.cn/api/v1/" + owner + "/" + projectName + "/branches.json"; String createBranchUrl = "https://www.gitlink.org.cn/api/v1/" + owner + "/" + projectName + "/branches.json";
Map<String, Object> resMap = new HashMap<>(); Map<String, Object> resMap = new HashMap<>();
resMap.put("new_branch_name", branchName); resMap.put("new_branch_name", branchName);
@@ -121,9 +120,8 @@ public class GitServiceImpl implements GitService {
} }


@Override @Override
public void createTopic(Integer id, String topicName) throws Exception {
public void createTopic(String token,Integer id, String topicName) throws Exception {
// https://www.gitlink.org.cn/api/v1/project_topics.json // https://www.gitlink.org.cn/api/v1/project_topics.json
String token = this.checkoutToken();
Map<String, Object> resMap = new HashMap<>(); Map<String, Object> resMap = new HashMap<>();
resMap.put("project_id", id); resMap.put("project_id", id);
resMap.put("name", topicName); resMap.put("name", topicName);
@@ -131,8 +129,7 @@ public class GitServiceImpl implements GitService {
} }


@Override @Override
public List<Map<String, Object>> getBrancheList(String owner, String projectName) throws Exception {
String token = checkoutToken();
public List<Map<String, Object>> getBrancheList(String token,String owner, String projectName) throws Exception {
String req = HttpUtils.sendGetWithToken("https://www.gitlink.org.cn/api/v1/" + owner + "/" + projectName + "/branches/all.json", null, token); String req = HttpUtils.sendGetWithToken("https://www.gitlink.org.cn/api/v1/" + owner + "/" + projectName + "/branches/all.json", null, token);
// 解析响应JSON // 解析响应JSON
if (StringUtils.isEmpty(req)) { if (StringUtils.isEmpty(req)) {
@@ -144,20 +141,18 @@ public class GitServiceImpl implements GitService {
} }


@Override @Override
public void deleteProject(String owner, String projectName) throws Exception {
String token = this.checkoutToken();
public void deleteProject(String token,String owner, String projectName) throws Exception {
HttpUtils.sendDeleteRequest("https://www.gitlink.org.cn/api/" + owner + "/" + projectName + ".json", token); HttpUtils.sendDeleteRequest("https://www.gitlink.org.cn/api/" + owner + "/" + projectName + ".json", token);
} }


@Override @Override
public void deleteBranch(String owner, String projectName, String branchName, String localPath) throws Exception {
public void deleteBranch(String token,String owner, String projectName, String branchName, String localPath) throws Exception {
try (Git git = Git.open(new File(localPath))) { try (Git git = Git.open(new File(localPath))) {
git.checkout().setName("master").call(); git.checkout().setName("master").call();
git.branchDelete().setBranchNames(branchName).setForce(true).call(); git.branchDelete().setBranchNames(branchName).setForce(true).call();
} catch (IOException | GitAPIException e) { } catch (IOException | GitAPIException e) {
log.error("Exception occurred while creating local branch based on master",e); log.error("Exception occurred while creating local branch based on master",e);
} }
String token = this.checkoutToken();
HttpUtils.sendDeleteRequest("https://www.gitlink.org.cn/api/v1/" + owner + "/" + projectName + "/branches/" + branchName + ".json", token); HttpUtils.sendDeleteRequest("https://www.gitlink.org.cn/api/v1/" + owner + "/" + projectName + "/branches/" + branchName + ".json", token);
} }




+ 3
- 1
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ImageServiceImpl.java View File

@@ -61,7 +61,9 @@ public class ImageServiceImpl implements ImageService {


@Resource @Resource
private MinioService minioService; private MinioService minioService;
@Value("${minio.dataReleaseBucketName}")
// @Value("${minio.dataReleaseBucketName}")
// private String bucketName;
@Value("${harbor.bucketName}")
private String bucketName; private String bucketName;
@Value("${harbor.repository}") @Value("${harbor.repository}")
private String repository; private String repository;


+ 8
- 6
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/JupyterServiceImpl.java View File

@@ -90,23 +90,25 @@ public class JupyterServiceImpl implements JupyterService {


// 提取数据集,模型信息,得到数据集模型的path // 提取数据集,模型信息,得到数据集模型的path
Map<String, Object> dataset = JacksonUtil.parseJSONStr2Map(devEnvironment.getDataset()); Map<String, Object> dataset = JacksonUtil.parseJSONStr2Map(devEnvironment.getDataset());
String datasetPath = (String) dataset.get("path");
String datasetPath = "argo-workflow" + "/" + dataset.get("path");
// String datasetPath = (String) dataset.get("path");


Map<String, Object> model = JacksonUtil.parseJSONStr2Map(devEnvironment.getModel()); Map<String, Object> model = JacksonUtil.parseJSONStr2Map(devEnvironment.getModel());
String modelPath = (String) model.get("path");
String modelPath = "argo-workflow" + "/" + model.get("path");
// String modelPath = (String) model.get("path");


LoginUser loginUser = SecurityUtils.getLoginUser(); LoginUser loginUser = SecurityUtils.getLoginUser();
//构造pod名称 //构造pod名称
String podName = loginUser.getUsername().toLowerCase() + "-editor-pod" + "-" + id; String podName = loginUser.getUsername().toLowerCase() + "-editor-pod" + "-" + id;
//新建编辑器的pvc //新建编辑器的pvc
// String pvcName = loginUser.getUsername().toLowerCase() + "-editor-pvc";
// V1PersistentVolumeClaim pvc = k8sClientUtil.createPvc(namespace, pvcName, storage, storageClassName);
String pvcName = loginUser.getUsername().toLowerCase() + "-editor-pvc";
V1PersistentVolumeClaim pvc = k8sClientUtil.createPvc(namespace, pvcName, storage, storageClassName);


//TODO 设置镜像可配置,这里先用默认镜像启动pod //TODO 设置镜像可配置,这里先用默认镜像启动pod


// 调用修改后的 createPod 方法,传入额外的参数 // 调用修改后的 createPod 方法,传入额外的参数
// Integer podPort = k8sClientUtil.createConfiguredPod(podName, namespace, port, mountPath, pvc, devEnvironment, minioPvcName, datasetPath, modelPath);
Integer podPort = k8sClientUtil.createConfiguredPod(podName, namespace, port, mountPath, null, devEnvironment, minioPvcName, datasetPath, modelPath);
Integer podPort = k8sClientUtil.createConfiguredPod(podName, namespace, port, mountPath, pvc, devEnvironment, minioPvcName, datasetPath, modelPath);
// Integer podPort = k8sClientUtil.createConfiguredPod(podName, namespace, port, mountPath, null, devEnvironment, minioPvcName, datasetPath, modelPath);
String url = masterIp + ":" + podPort; String url = masterIp + ":" + podPort;
redisService.setCacheObject(podName, masterIp + ":" + podPort); redisService.setCacheObject(podName, masterIp + ":" + podPort);
devEnvironment.setStatus("Pending"); devEnvironment.setStatus("Pending");


+ 15
- 9
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ModelsServiceImpl.java View File

@@ -86,6 +86,8 @@ public class ModelsServiceImpl implements ModelsService {


@Value("${spring.redis.host}") @Value("${spring.redis.host}")
private String redisHost; private String redisHost;
@Value("${spring.redis.port}")
private Integer redisPort;
@Value("${git.endpoint}") @Value("${git.endpoint}")
String gitendpoint; String gitendpoint;
@Value("${git.localPath}") @Value("${git.localPath}")
@@ -540,6 +542,7 @@ public class ModelsServiceImpl implements ModelsService {
@Override @Override
public String newCreateModel(ModelsVo modelsVo) { public String newCreateModel(ModelsVo modelsVo) {
try { try {
String token = gitService.checkoutToken();
LoginUser loginUser = SecurityUtils.getLoginUser(); LoginUser loginUser = SecurityUtils.getLoginUser();
String ci4sUsername = loginUser.getUsername(); String ci4sUsername = loginUser.getUsername();
String gitLinkUsername = loginUser.getSysUser().getGitLinkUsername(); String gitLinkUsername = loginUser.getSysUser().getGitLinkUsername();
@@ -571,17 +574,17 @@ public class ModelsServiceImpl implements ModelsService {
gitProjectVo.setUserId(userId); gitProjectVo.setUserId(userId);


// 创建项目 // 创建项目
Map project = gitService.createProject(gitProjectVo);
Map project = gitService.createProject(token,gitProjectVo);
Integer gitlinIid = (Integer) project.get("id"); Integer gitlinIid = (Integer) project.get("id");
if (gitlinIid == null) { if (gitlinIid == null) {
throw new Exception("创建模型失败:" + project.get("message")); throw new Exception("创建模型失败:" + project.get("message"));
} }
// 创建分支 // 创建分支
gitService.createBranch((String) userInfo.get("login"), repositoryName, modelsVo.getVersion(), "master");
gitService.createBranch(token,(String) userInfo.get("login"), repositoryName, modelsVo.getVersion(), "master");
// 定义标签 标签1:ci4s_model 标签2:ModelTag 标签3:ModelType // 定义标签 标签1:ci4s_model 标签2:ModelTag 标签3:ModelType
gitService.createTopic(gitlinIid, "ci4s_model");
gitService.createTopic(gitlinIid, "modeltag_" + modelsVo.getModelTag());
gitService.createTopic(gitlinIid, "modeltype_" + modelsVo.getModelType());
gitService.createTopic(token,gitlinIid, "ci4s_model");
gitService.createTopic(token,gitlinIid, "modeltag_" + modelsVo.getModelTag());
gitService.createTopic(token,gitlinIid, "modeltype_" + modelsVo.getModelType());


String branchName = modelsVo.getVersion(); String branchName = modelsVo.getVersion();
String owner = (String) userInfo.get("login"); String owner = (String) userInfo.get("login");
@@ -882,7 +885,8 @@ public class ModelsServiceImpl implements ModelsService {


@Override @Override
public List<Map<String, Object>> getVersionList(String identifier, String owner) throws Exception { public List<Map<String, Object>> getVersionList(String identifier, String owner) throws Exception {
List<Map<String, Object>> brancheList = gitService.getBrancheList(owner, identifier);
String token = gitService.checkoutToken();
List<Map<String, Object>> brancheList = gitService.getBrancheList(token,owner, identifier);
return brancheList.stream() return brancheList.stream()
.filter(branch -> !"master".equals(branch.get("name"))) .filter(branch -> !"master".equals(branch.get("name")))
.collect(Collectors.toList()); .collect(Collectors.toList());
@@ -949,7 +953,8 @@ public class ModelsServiceImpl implements ModelsService {


@Override @Override
public void deleteModel(Integer repoId, String identifier, String owner) throws Exception { public void deleteModel(Integer repoId, String identifier, String owner) throws Exception {
gitService.deleteProject(owner, identifier);
String token = gitService.checkoutToken();
gitService.deleteProject(token,owner, identifier);
//删除模型依赖 //删除模型依赖
modelDependency1Dao.deleteModel(repoId, identifier, owner, null); modelDependency1Dao.deleteModel(repoId, identifier, owner, null);


@@ -962,7 +967,8 @@ public class ModelsServiceImpl implements ModelsService {


@Override @Override
public void deleteVersion(Integer repoId, String identifier, String owner, String version, String relativePath) throws Exception { public void deleteVersion(Integer repoId, String identifier, String owner, String version, String relativePath) throws Exception {
gitService.deleteBranch(owner, identifier, version, localPath + relativePath);
String token = gitService.checkoutToken();
gitService.deleteBranch(token,owner, identifier, version, localPath + relativePath);
//删除模型依赖 //删除模型依赖
modelDependency1Dao.deleteModel(repoId, identifier, owner, version); modelDependency1Dao.deleteModel(repoId, identifier, owner, version);
HashMap<String, Object> map = new HashMap<>(); HashMap<String, Object> map = new HashMap<>();
@@ -1053,7 +1059,7 @@ public class ModelsServiceImpl implements ModelsService {
} }


Map<String, Object> getUserInfo(String ci4sUsername, String gitLinkUsername, String gitLinkPassword) throws IOException { Map<String, Object> getUserInfo(String ci4sUsername, String gitLinkUsername, String gitLinkPassword) throws IOException {
Jedis jedis = new Jedis(redisHost);
Jedis jedis = new Jedis(redisHost,redisPort);
String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); String userReq = jedis.get(ci4sUsername + "_gitUserInfo");
if (userReq == null) { if (userReq == null) {
gitService.login(gitLinkUsername, gitLinkPassword); gitService.login(gitLinkUsername, gitLinkPassword);


+ 23
- 37
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/NewDatasetServiceImpl.java View File

@@ -50,6 +50,8 @@ public class NewDatasetServiceImpl implements NewDatasetService {
private DvcService dvcService; private DvcService dvcService;
@Value("${spring.redis.host}") @Value("${spring.redis.host}")
private String redisHost; private String redisHost;
@Value("${spring.redis.port}")
private Integer redisPort;
@Value("${minio.accessKey}") @Value("${minio.accessKey}")
String accessKeyId; String accessKeyId;
@Value("${minio.secretKey}") @Value("${minio.secretKey}")
@@ -64,7 +66,8 @@ public class NewDatasetServiceImpl implements NewDatasetService {
private DatasetTempStorageService datasetTempStorageService; private DatasetTempStorageService datasetTempStorageService;
@Override @Override
public String newCreateDataset(NewDatasetVo datasetVo) throws Exception { public String newCreateDataset(NewDatasetVo datasetVo) throws Exception {
Jedis jedis = new Jedis(redisHost);
String token = gitService.checkoutToken();
Jedis jedis = new Jedis(redisHost,redisPort);
LoginUser loginUser = SecurityUtils.getLoginUser(); LoginUser loginUser = SecurityUtils.getLoginUser();
String ci4sUsername = loginUser.getUsername(); String ci4sUsername = loginUser.getUsername();
String gitLinkUsername = loginUser.getSysUser().getGitLinkUsername(); String gitLinkUsername = loginUser.getSysUser().getGitLinkUsername();
@@ -82,18 +85,18 @@ public class NewDatasetServiceImpl implements NewDatasetService {
gitProjectVo.setPrivate(!datasetVo.getIsPublic()); gitProjectVo.setPrivate(!datasetVo.getIsPublic());
gitProjectVo.setUserId(userId); gitProjectVo.setUserId(userId);
// 创建项目 // 创建项目
Map project = gitService.createProject(gitProjectVo);
Map project = gitService.createProject(token,gitProjectVo);
Integer gitlinIid = (Integer) project.get("id"); Integer gitlinIid = (Integer) project.get("id");
if (gitlinIid == null){ if (gitlinIid == null){
throw new Exception("创建数据集失败:"+project.get("message")); throw new Exception("创建数据集失败:"+project.get("message"));
} }
// 创建分支 // 创建分支
String branchName = datasetVo.getVersion(); String branchName = datasetVo.getVersion();
gitService.createBranch((String) userInfo.get("login"), repositoryName, branchName, "master");
gitService.createBranch(token,(String) userInfo.get("login"), repositoryName, branchName, "master");
// 定义标签 标签1:ci4s_dataset 标签2:DataTag 标签3:DataType // 定义标签 标签1:ci4s_dataset 标签2:DataTag 标签3:DataType
gitService.createTopic(gitlinIid, "ci4s_dataset");
gitService.createTopic(gitlinIid, "DataTag_" + datasetVo.getDataTag());
gitService.createTopic( gitlinIid, "DataType_" + datasetVo.getDataType());
gitService.createTopic(token,gitlinIid, "ci4s_dataset");
gitService.createTopic(token,gitlinIid, "DataTag_" + datasetVo.getDataTag());
gitService.createTopic(token, gitlinIid, "DataType_" + datasetVo.getDataType());
// 得到项目地址 // 得到项目地址
String projectUrl = gitendpoint + "/" + (String) userInfo.get("login") + "/"+ repositoryName + ".git"; String projectUrl = gitendpoint + "/" + (String) userInfo.get("login") + "/"+ repositoryName + ".git";


@@ -145,10 +148,10 @@ public class NewDatasetServiceImpl implements NewDatasetService {
} }


public String newCreateVersion(NewDatasetVo datasetVo) throws Exception { public String newCreateVersion(NewDatasetVo datasetVo) throws Exception {
Jedis jedis = new Jedis(redisHost);
String token = gitService.checkoutToken();
Jedis jedis = new Jedis(redisHost,redisPort);
LoginUser loginUser = SecurityUtils.getLoginUser(); LoginUser loginUser = SecurityUtils.getLoginUser();
String ci4sUsername = loginUser.getUsername(); String ci4sUsername = loginUser.getUsername();
String token = jedis.get(ci4sUsername + "_gitToken");
String gitLinkUsername = loginUser.getSysUser().getGitLinkUsername(); String gitLinkUsername = loginUser.getSysUser().getGitLinkUsername();
String gitLinkPassword = loginUser.getSysUser().getGitLinkPassword(); String gitLinkPassword = loginUser.getSysUser().getGitLinkPassword();
String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); String userReq = jedis.get(ci4sUsername + "_gitUserInfo");
@@ -215,10 +218,10 @@ public class NewDatasetServiceImpl implements NewDatasetService {


@Override @Override
public Page<NewDatasetVo> newPersonalQueryByPage(Dataset dataset, PageRequest pageRequest) throws Exception { public Page<NewDatasetVo> newPersonalQueryByPage(Dataset dataset, PageRequest pageRequest) throws Exception {
Jedis jedis = new Jedis(redisHost);
String token = gitService.checkoutToken();
Jedis jedis = new Jedis(redisHost,redisPort);
LoginUser loginUser = SecurityUtils.getLoginUser(); LoginUser loginUser = SecurityUtils.getLoginUser();
String ci4sUsername = loginUser.getUsername(); String ci4sUsername = loginUser.getUsername();
String token = jedis.get(ci4sUsername + "_gitToken");
String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); String userReq = jedis.get(ci4sUsername + "_gitUserInfo");
Map<String, Object> userInfo = JsonUtils.jsonToMap(userReq); Map<String, Object> userInfo = JsonUtils.jsonToMap(userReq);
// 拼接查询url // 拼接查询url
@@ -242,10 +245,10 @@ public class NewDatasetServiceImpl implements NewDatasetService {


@Override @Override
public Page<NewDatasetVo> newPubilcQueryByPage(Dataset dataset, PageRequest pageRequest) throws Exception { public Page<NewDatasetVo> newPubilcQueryByPage(Dataset dataset, PageRequest pageRequest) throws Exception {
Jedis jedis = new Jedis(redisHost);
String token = gitService.checkoutToken();
Jedis jedis = new Jedis(redisHost,redisPort);
LoginUser loginUser = SecurityUtils.getLoginUser(); LoginUser loginUser = SecurityUtils.getLoginUser();
String ci4sUsername = loginUser.getUsername(); String ci4sUsername = loginUser.getUsername();
String token = jedis.get(ci4sUsername + "_gitToken");
String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); String userReq = jedis.get(ci4sUsername + "_gitUserInfo");
Map<String, Object> userInfo = JsonUtils.jsonToMap(userReq); Map<String, Object> userInfo = JsonUtils.jsonToMap(userReq);
Integer userId = (Integer) userInfo.get("user_id"); Integer userId = (Integer) userInfo.get("user_id");
@@ -305,7 +308,8 @@ public class NewDatasetServiceImpl implements NewDatasetService {


@Override @Override
public List<Map<String, Object>> getVersionList(String repo, String owner) throws Exception { public List<Map<String, Object>> getVersionList(String repo, String owner) throws Exception {
List<Map<String, Object>> brancheList = gitService.getBrancheList(owner, repo);
String token = gitService.checkoutToken();
List<Map<String, Object>> brancheList = gitService.getBrancheList(token,owner, repo);
return brancheList.stream() return brancheList.stream()
.filter(branch -> !"master".equals(branch.get("name"))) .filter(branch -> !"master".equals(branch.get("name")))
.collect(Collectors.toList()); .collect(Collectors.toList());
@@ -313,20 +317,14 @@ public class NewDatasetServiceImpl implements NewDatasetService {


@Override @Override
public void deleteDatasetNew(String repo, String owner) throws Exception { public void deleteDatasetNew(String repo, String owner) throws Exception {
Jedis jedis = new Jedis(redisHost);
LoginUser loginUser = SecurityUtils.getLoginUser();
String ci4sUsername = loginUser.getUsername();
String token = jedis.get(ci4sUsername+"_gitToken");
gitService.deleteProject(owner, repo);
String token = gitService.checkoutToken();
gitService.deleteProject(token,owner, repo);
} }


@Override @Override
public void deleteDatasetVersionNew(String repo, String owner, String version, String relativePath) throws Exception { public void deleteDatasetVersionNew(String repo, String owner, String version, String relativePath) throws Exception {
Jedis jedis = new Jedis(redisHost);
LoginUser loginUser = SecurityUtils.getLoginUser();
String ci4sUsername = loginUser.getUsername();
String token = jedis.get(ci4sUsername+"_gitToken");
gitService.deleteBranch(owner, repo, version, localPathlocal + relativePath);
String token = gitService.checkoutToken();
gitService.deleteBranch(token,owner, repo, version, localPathlocal + relativePath);
} }


@Override @Override
@@ -341,6 +339,7 @@ public class NewDatasetServiceImpl implements NewDatasetService {
long sizeInBytes = file.getSize(); long sizeInBytes = file.getSize();
String formattedSize = FileUtil.formatFileSize(sizeInBytes); String formattedSize = FileUtil.formatFileSize(sizeInBytes);
File targetFile = new File(path, file.getOriginalFilename()); File targetFile = new File(path, file.getOriginalFilename());

// 确保目录存在 // 确保目录存在
targetFile.getParentFile().mkdirs(); targetFile.getParentFile().mkdirs();
// 保存文件到目标路径 // 保存文件到目标路径
@@ -381,24 +380,11 @@ public class NewDatasetServiceImpl implements NewDatasetService {
public ResponseEntity<InputStreamResource> downloadAllDatasetFilesNew(String name,Integer id, String version) throws Exception { public ResponseEntity<InputStreamResource> downloadAllDatasetFilesNew(String name,Integer id, String version) throws Exception {
// 命令行操作 git clone 项目地址 // 命令行操作 git clone 项目地址
LoginUser loginUser = SecurityUtils.getLoginUser(); LoginUser loginUser = SecurityUtils.getLoginUser();
String gitLinkUsername = loginUser.getSysUser().getGitLinkUsername();
String gitLinkPassword = loginUser.getSysUser().getGitLinkPassword();
String ci4sUsername = loginUser.getUsername(); String ci4sUsername = loginUser.getUsername();
Jedis jedis = new Jedis(redisHost);
Jedis jedis = new Jedis(redisHost,redisPort);
String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); String userReq = jedis.get(ci4sUsername + "_gitUserInfo");
Map<String, Object> userInfo = JsonUtils.jsonToMap(userReq); Map<String, Object> userInfo = JsonUtils.jsonToMap(userReq);
String localPath = localPathlocal+ loginUser.getUsername()+"/datasets/"+id+"/"+name; String localPath = localPathlocal+ loginUser.getUsername()+"/datasets/"+id+"/"+name;
//不需要,没意义,我查看详情已经是最新的了
// if(folder.exists() && folder.isDirectory()){
// //切换分支
// DVCUtils.gitCheckoutBranch(localPath, version);
// //pull
// DVCUtils.gitPull(localPath,gitLinkUsername, gitLinkPassword);
// //dvc pull
// DVCUtils.dvcPull(localPath);
// }else {
// DVCUtils.gitClone(localPath, projectUrl, version, gitLinkUsername, gitLinkPassword);
// }


// 打包 data 文件夹 // 打包 data 文件夹
String dataFolderPath = localPath + "/data"; String dataFolderPath = localPath + "/data";


+ 7
- 3
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/TensorBoardServiceImpl.java View File

@@ -59,13 +59,17 @@ public class TensorBoardServiceImpl implements TensorBoardService {


@Override @Override
public String runTensorBoard(FrameLogPathVo frameLogPathVo) throws Exception { public String runTensorBoard(FrameLogPathVo frameLogPathVo) throws Exception {
if (StringUtils.isEmpty(frameLogPathVo.getPath())) {
throw new Exception("存储路径为空");
if (StringUtils.isEmpty(frameLogPathVo.getPath())||StringUtils.isEmpty(frameLogPathVo.getPvcName())){
throw new Exception("存储路径或存储为空");
} }
// if (StringUtils.isEmpty(frameLogPathVo.getPath())) {
// throw new Exception("存储路径为空");
// }
LoginUser loginUser = SecurityUtils.getLoginUser(); LoginUser loginUser = SecurityUtils.getLoginUser();
String podName = loginUser.getUsername().toLowerCase()+"-"+frameLogPathVo.getPath().split("/")[2]+ "-tensorboard-pod"; 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(), image);
Integer podPort = k8sClientUtil.createPodWithSubPath(podName, StringUtils.isEmpty(frameLogPathVo.getNamespace()) ? "default" : frameLogPathVo.getNamespace(), port, mountPath, frameLogPathVo.getPath(), frameLogPathVo.getPvcName(), image);
// Integer podPort = k8sClientUtil.createPodWithSubPath(podName, StringUtils.isEmpty(frameLogPathVo.getNamespace()) ? "default" : frameLogPathVo.getNamespace(), port, mountPath, frameLogPathVo.getPath(), image);
redisService.setCacheObject(podName, masterIp + ":" + podPort); redisService.setCacheObject(podName, masterIp + ":" + podPort);
return masterIp + ":" + podPort; return masterIp + ":" + podPort;
} }


+ 21
- 21
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java View File

@@ -34,8 +34,8 @@ import java.util.*;
@Component @Component
public class K8sClientUtil { public class K8sClientUtil {


@Value("${jupyter.hostPath}")
private String hostPath;
// @Value("${jupyter.hostPath}")
// private String hostPath;


private String http; private String http;
private String token; private String token;
@@ -314,8 +314,8 @@ public class K8sClientUtil {
* @param image 镜像 * @param image 镜像
* @return 创建成功的pod,的nodePort端口 * @return 创建成功的pod,的nodePort端口
*/ */
public Integer createPodWithSubPath(String podName, String namespace, Integer port, String mountPath, String subPath, String image) {
public Integer createPodWithSubPath(String podName, String namespace, Integer port, String mountPath, String subPath, String pvcName, String image) {
// public Integer createPodWithSubPath(String podName, String namespace, Integer port, String mountPath, String subPath, String image) {


Map<String, String> selector = new LinkedHashMap<>(); Map<String, String> selector = new LinkedHashMap<>();
selector.put("k8s-jupyter", podName); selector.put("k8s-jupyter", podName);
@@ -366,8 +366,8 @@ public class K8sClientUtil {
.endContainer() .endContainer()
.addNewVolume() .addNewVolume()
.withName("workspace") .withName("workspace")
.withHostPath(new V1HostPathVolumeSource().path(hostPath).type("DirectoryOrCreate"))
// .withPersistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvcName))
// .withHostPath(new V1HostPathVolumeSource().path(hostPath).type("DirectoryOrCreate"))
.withPersistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvcName))
.endVolume() .endVolume()
.withTerminationGracePeriodSeconds(14400L) .withTerminationGracePeriodSeconds(14400L)
.endSpec() .endSpec()
@@ -449,25 +449,25 @@ public class K8sClientUtil {
} }
} }


// 配置卷和卷挂载
List<V1VolumeMount> volumeMounts = new ArrayList<>();
volumeMounts.add(new V1VolumeMount().name("workspace").mountPath("/opt/notebooks"));
volumeMounts.add(new V1VolumeMount().name("data").mountPath("/opt/dataset").subPath(datasetPath).readOnly(true));
volumeMounts.add(new V1VolumeMount().name("data").mountPath("/opt/model").subPath(modelPath).readOnly(true));

List<V1Volume> volumes = new ArrayList<>();
volumes.add(new V1Volume().name("workspace").hostPath(new V1HostPathVolumeSource().path(hostPath + "/" + podName + "/notebooks").type("DirectoryOrCreate")));
volumes.add(new V1Volume().name("data").hostPath(new V1HostPathVolumeSource().path(hostPath).type("DirectoryOrCreate")));

// 配置卷和卷挂载 // 配置卷和卷挂载
// List<V1VolumeMount> volumeMounts = new ArrayList<>(); // List<V1VolumeMount> volumeMounts = new ArrayList<>();
// volumeMounts.add(new V1VolumeMount().name("workspace").mountPath(mountPath));
// volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/opt/data").subPath(datasetPath).readOnly(true));
// volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/opt/model").subPath(modelPath).readOnly(true));
// volumeMounts.add(new V1VolumeMount().name("workspace").mountPath("/opt/notebooks"));
// volumeMounts.add(new V1VolumeMount().name("data").mountPath("/opt/dataset").subPath(datasetPath).readOnly(true));
// volumeMounts.add(new V1VolumeMount().name("data").mountPath("/opt/model").subPath(modelPath).readOnly(true));
// //
// List<V1Volume> volumes = new ArrayList<>(); // List<V1Volume> volumes = new ArrayList<>();
// volumes.add(new V1Volume().name("workspace").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvc.getMetadata().getName())));
// volumes.add(new V1Volume().name("minio-pvc").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(dataPvcName)));
// volumes.add(new V1Volume().name("workspace").hostPath(new V1HostPathVolumeSource().path(hostPath + "/" + podName + "/notebooks").type("DirectoryOrCreate")));
// volumes.add(new V1Volume().name("data").hostPath(new V1HostPathVolumeSource().path(hostPath).type("DirectoryOrCreate")));

// 配置卷和卷挂载
List<V1VolumeMount> volumeMounts = new ArrayList<>();
volumeMounts.add(new V1VolumeMount().name("workspace").mountPath(mountPath));
volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/opt/data").subPath(datasetPath).readOnly(true));
volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/opt/model").subPath(modelPath).readOnly(true));

List<V1Volume> volumes = new ArrayList<>();
volumes.add(new V1Volume().name("workspace").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvc.getMetadata().getName())));
volumes.add(new V1Volume().name("minio-pvc").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(dataPvcName)));




//配置资源 //配置资源


+ 9
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/FrameLogPathVo.java View File

@@ -10,6 +10,7 @@ public class FrameLogPathVo implements Serializable {
String path; String path;
String namespace; String namespace;


String pvcName;
public String getPath() { public String getPath() {
return path; return path;
} }
@@ -25,4 +26,12 @@ public class FrameLogPathVo implements Serializable {
public void setNamespace(String namespace) { public void setNamespace(String namespace) {
this.namespace = namespace; this.namespace = namespace;
} }

public String getPvcName() {
return pvcName;
}

public void setPvcName(String pvcName) {
this.pvcName = pvcName;
}
} }

Loading…
Cancel
Save