Browse Source

add tadl

tags/V2.1
之江天枢 3 years ago
parent
commit
18cafe9890
100 changed files with 3955 additions and 176 deletions
  1. +3
    -3
      dubhe-server/README.md
  2. +4
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/AdminApplication.java
  3. +68
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/async/CleanupUserResourcesAsync.java
  4. +42
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/client/GpuConfigClient.java
  5. +60
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/client/ResourceNamespaceClient.java
  6. +6
    -4
      dubhe-server/admin/src/main/java/org/dubhe/admin/client/ResourceQuotaClient.java
  7. +42
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/client/SystemNamespaceClient.java
  8. +45
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/client/SystemNodeClient.java
  9. +33
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/client/fallback/GpuConfigClientFallback.java
  10. +42
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/client/fallback/ResourceNamespaceClientFallback.java
  11. +2
    -2
      dubhe-server/admin/src/main/java/org/dubhe/admin/client/fallback/ResourceQuotaClientFallback.java
  12. +35
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/client/fallback/SystemNamespaceClientFallback.java
  13. +37
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/client/fallback/SystemNodeClientFallback.java
  14. +60
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/client/template/GpuConfigTemplateClient.java
  15. +91
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/client/template/ObtainAccessToken.java
  16. +60
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/client/template/ResourceQuotaTemplateClient.java
  17. +79
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/config/AdminPoolConfig.java
  18. +27
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/dao/GpuResourceMapper.java
  19. +45
    -1
      dubhe-server/admin/src/main/java/org/dubhe/admin/dao/UserConfigMapper.java
  20. +81
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/dao/UserGpuConfigMapper.java
  21. +16
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/dao/UserMapper.java
  22. +1
    -1
      dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/AuthCodeQueryDTO.java
  23. +57
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/GpuResourceCreateDTO.java
  24. +40
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/GpuResourceDeleteDTO.java
  25. +45
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/GpuResourceQueryDTO.java
  26. +64
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/GpuResourceUpdateDTO.java
  27. +2
    -1
      dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/MenuQueryDTO.java
  28. +65
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/QueryUserResourceSpecsDTO.java
  29. +2
    -2
      dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/ResourceSpecsCreateDTO.java
  30. +5
    -2
      dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/ResourceSpecsQueryDTO.java
  31. +2
    -2
      dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/ResourceSpecsUpdateDTO.java
  32. +46
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/UserGpuResourceQueryDTO.java
  33. +35
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/UserGroupConfigSaveDTO.java
  34. +31
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/UserResourceListDTO.java
  35. +41
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/UserResourceQueryDTO.java
  36. +63
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/domain/entity/GpuResource.java
  37. +8
    -2
      dubhe-server/admin/src/main/java/org/dubhe/admin/domain/entity/UserConfig.java
  38. +80
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/domain/entity/UserGpuConfig.java
  39. +59
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/domain/vo/GpuResourceQueryVO.java
  40. +3
    -2
      dubhe-server/admin/src/main/java/org/dubhe/admin/domain/vo/MenuVo.java
  41. +39
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/domain/vo/UserLimitConfigVO.java
  42. +91
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/domain/vo/UserResourceResVO.java
  43. +54
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/enums/ResourceTypeEnum.java
  44. +50
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/enums/StatTypeEnum.java
  45. +1
    -1
      dubhe-server/admin/src/main/java/org/dubhe/admin/event/EmailEventListener.java
  46. +1
    -1
      dubhe-server/admin/src/main/java/org/dubhe/admin/event/EmailEventPublisher.java
  47. +89
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/rest/GpuResourceController.java
  48. +19
    -3
      dubhe-server/admin/src/main/java/org/dubhe/admin/rest/ResourceSpecsController.java
  49. +0
    -1
      dubhe-server/admin/src/main/java/org/dubhe/admin/rest/UserCenterController.java
  50. +35
    -8
      dubhe-server/admin/src/main/java/org/dubhe/admin/rest/UserController.java
  51. +22
    -2
      dubhe-server/admin/src/main/java/org/dubhe/admin/rest/UserGroupController.java
  52. +58
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/rest/UserResourceController.java
  53. +77
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/service/GpuResourceService.java
  54. +21
    -2
      dubhe-server/admin/src/main/java/org/dubhe/admin/service/ResourceSpecsService.java
  55. +16
    -1
      dubhe-server/admin/src/main/java/org/dubhe/admin/service/UserGroupService.java
  56. +48
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/service/UserResourceService.java
  57. +28
    -7
      dubhe-server/admin/src/main/java/org/dubhe/admin/service/UserService.java
  58. +2
    -2
      dubhe-server/admin/src/main/java/org/dubhe/admin/service/impl/AuthCodeServiceImpl.java
  59. +223
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/service/impl/GpuResourceServiceImpl.java
  60. +25
    -13
      dubhe-server/admin/src/main/java/org/dubhe/admin/service/impl/MenuServiceImpl.java
  61. +1
    -1
      dubhe-server/admin/src/main/java/org/dubhe/admin/service/impl/PermissionServiceImpl.java
  62. +2
    -2
      dubhe-server/admin/src/main/java/org/dubhe/admin/service/impl/RecycleTaskServiceImpl.java
  63. +122
    -4
      dubhe-server/admin/src/main/java/org/dubhe/admin/service/impl/ResourceSpecsServiceImpl.java
  64. +54
    -2
      dubhe-server/admin/src/main/java/org/dubhe/admin/service/impl/UserGroupServiceImpl.java
  65. +314
    -0
      dubhe-server/admin/src/main/java/org/dubhe/admin/service/impl/UserResourceServiceImpl.java
  66. +325
    -67
      dubhe-server/admin/src/main/java/org/dubhe/admin/service/impl/UserServiceImpl.java
  67. +3
    -3
      dubhe-server/admin/src/main/resources/bootstrap.yml
  68. +24
    -10
      dubhe-server/admin/src/main/resources/mapper/UserConfigMapper.xml
  69. +12
    -0
      dubhe-server/admin/src/main/resources/mapper/UserGpuConfigMapper.xml
  70. +5
    -0
      dubhe-server/admin/src/main/resources/mapper/UserMapper.xml
  71. +12
    -0
      dubhe-server/admin/src/test/java/org/dubhe/admin/AdminApplicationTests.java
  72. +3
    -3
      dubhe-server/auth/src/main/resources/bootstrap.yml
  73. +4
    -0
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/constant/ApplicationNameConst.java
  74. +4
    -4
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/constant/AuthConst.java
  75. +1
    -0
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/constant/MagicNumConstant.java
  76. +2
    -0
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/constant/NumberConstant.java
  77. +13
    -0
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/constant/Permissions.java
  78. +45
    -4
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/constant/StringConstant.java
  79. +2
    -0
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/constant/SymbolConstant.java
  80. +15
    -0
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/constant/UserConstant.java
  81. +38
    -0
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/DeleteDTO.java
  82. +45
    -0
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/GpuConfigDTO.java
  83. +2
    -1
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/ModelOptAlgorithmCreateDTO.java
  84. +38
    -0
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/NamespaceDeleteDTO.java
  85. +2
    -0
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/PtImageQueryUrlDTO.java
  86. +2
    -2
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/QueryResourceSpecsDTO.java
  87. +121
    -0
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/QueryUserK8sResourceDTO.java
  88. +43
    -0
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/ResourceQuotaDTO.java
  89. +9
    -3
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/SysUserConfigDTO.java
  90. +52
    -0
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/SysUserGpuConfigDTO.java
  91. +50
    -0
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/UserConfigSaveDTO.java
  92. +2
    -0
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/UserDTO.java
  93. +46
    -0
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/UserGpuConfigDTO.java
  94. +1
    -1
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/enums/BaseErrorCodeEnum.java
  95. +4
    -1
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/enums/BizEnum.java
  96. +6
    -5
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/utils/AesUtil.java
  97. +44
    -0
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/utils/CommandUtil.java
  98. +21
    -0
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/utils/DateUtil.java
  99. +39
    -0
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/utils/MapUtil.java
  100. +1
    -0
      dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/utils/MathUtils.java

+ 3
- 3
dubhe-server/README.md View File

@@ -11,8 +11,8 @@ Nacos + Fegin + Gateway + (Spring Security + JWT + OAuth2)

初始化sql位置 /sql

**地址:** 127.0.0.1:3306
**用户名:** test **密码:** test
**地址:** 10.5.29.66:3306
**用户名:** test **密码:** zj12345678

### Nacos

@@ -24,7 +24,7 @@ Nacos + Fegin + Gateway + (Spring Security + JWT + OAuth2)

**详见:** https://nacos.io/zh-cn/docs/quick-start-spring-cloud.html

**地址:** http://127.0.0.1:8848/nacos/#/login
**地址:** http://10.105.1.133:8848/nacos/#/login

**用户名:** nacos **密码:** nacos



+ 4
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/AdminApplication.java View File

@@ -19,6 +19,8 @@ package org.dubhe.admin;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;


/**
@@ -27,6 +29,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
*/
@SpringBootApplication(scanBasePackages = "org.dubhe")
@MapperScan(basePackages = {"org.dubhe.**.dao"})
@EnableScheduling
@EnableAsync
public class AdminApplication {
public static void main(String[] args) {
SpringApplication.run(AdminApplication.class, args);


+ 68
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/async/CleanupUserResourcesAsync.java View File

@@ -0,0 +1,68 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.async;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.dubhe.admin.client.SystemNamespaceClient;
import org.dubhe.admin.dao.UserConfigMapper;
import org.dubhe.admin.dao.UserGpuConfigMapper;
import org.dubhe.admin.domain.entity.UserConfig;
import org.dubhe.admin.domain.entity.UserGpuConfig;
import org.dubhe.biz.base.dto.NamespaceDeleteDTO;
import org.dubhe.biz.base.exception.BusinessException;
import org.dubhe.biz.base.vo.DataResponseBody;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.Set;

/**
* @description 异步清理用户资源
* @date 2021-11-25
*/
@Component
public class CleanupUserResourcesAsync {

@Autowired
private UserConfigMapper userConfigMapper;

@Autowired
private UserGpuConfigMapper userGpuConfigMapper;

@Autowired
private SystemNamespaceClient systemNamespaceClient;

@Async("adminExecutor")
public void cleanUserResource(Set<Long> ids, String accessToken){
//删除用户资源配置
QueryWrapper<UserConfig> userConfigWrapper = new QueryWrapper<>();
userConfigWrapper.in("user_id",ids);
userConfigMapper.delete(userConfigWrapper);
QueryWrapper<UserGpuConfig> userGpuConfigWrapper = new QueryWrapper<>();
userGpuConfigWrapper.in("user_id",ids);
userGpuConfigMapper.delete(userGpuConfigWrapper);
//删除用户namespace
NamespaceDeleteDTO namespaceDeleteDTO = new NamespaceDeleteDTO();
namespaceDeleteDTO.setIds(ids);
DataResponseBody dataResponseBody = systemNamespaceClient.deleteNamespace(namespaceDeleteDTO, accessToken);
if (!dataResponseBody.succeed()) {
throw new BusinessException("远程调用k8s删除namespace失败");
}
}

}

+ 42
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/client/GpuConfigClient.java View File

@@ -0,0 +1,42 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.client;

import org.dubhe.admin.client.fallback.GpuConfigClientFallback;
import org.dubhe.biz.base.constant.ApplicationNameConst;
import org.dubhe.biz.base.dto.GpuConfigDTO;
import org.dubhe.biz.base.vo.DataResponseBody;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

/**
* @description 远程调用k8sGPU资源配额 Client
* @date 2021-9-7
*/
@FeignClient(value = ApplicationNameConst.SERVER_K8S, contextId = "gpuConfigClient",fallback = GpuConfigClientFallback.class)
public interface GpuConfigClient {
/**
* 更新k8sGPU资源配额
*
* @param gpuConfigDTO k8sGPU资源配额
* @return
*/
@PostMapping(value = "/gpuConfig/update")
DataResponseBody updateGpuConfig(@RequestBody GpuConfigDTO gpuConfigDTO);

}

+ 60
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/client/ResourceNamespaceClient.java View File

@@ -0,0 +1,60 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.client;

import org.dubhe.admin.client.fallback.ResourceNamespaceClientFallback;
import org.dubhe.biz.base.constant.ApplicationNameConst;
import org.dubhe.biz.base.vo.DataResponseBody;
import org.dubhe.biz.base.vo.UserAllotVO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;
import java.util.Map;

/**
* @description 远程调用
* @date 2021-11-19
*/
@FeignClient(value = ApplicationNameConst.SERVER_K8S, contextId = "ResourceNamespaceClient", fallback = ResourceNamespaceClientFallback.class)
public interface ResourceNamespaceClient {

/**
* 查看用户资源用量峰值
*
* @param resourceType 资源类型
* @param sumDay 统计时间段
* @return List<UserAllotVO> 用户资源用量峰值VO 实体类
*/
@GetMapping("/namespace/ResourceUsage")
DataResponseBody<List<UserAllotVO>> getResourceNamespace(@RequestParam(value = "resourceType") Integer resourceType,
@RequestParam(value = "sumDay") String sumDay);

/**
* 查询用户某段时间内的资源用量峰值
*
* @param resourceType 资源类型
* @param sumDay 统计时间段
* @param namespaces 用户命名空间
* @return String 资源用量峰值
*/
@GetMapping("/namespace/ResourceByUser")
DataResponseBody<Map<Long, String>> getResourceUsageByUser(@RequestParam(value = "resourceType") Integer resourceType,
@RequestParam(value = "sumDay") String sumDay,
@RequestParam(value = "namespaces") String namespaces);
}

+ 6
- 4
dubhe-server/admin/src/main/java/org/dubhe/admin/client/ResourceQuotaClient.java View File

@@ -17,8 +17,8 @@
package org.dubhe.admin.client;

import org.dubhe.admin.client.fallback.ResourceQuotaClientFallback;
import org.dubhe.admin.domain.dto.UserConfigDTO;
import org.dubhe.biz.base.constant.ApplicationNameConst;
import org.dubhe.biz.base.dto.ResourceQuotaDTO;
import org.dubhe.biz.base.vo.DataResponseBody;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
@@ -28,14 +28,16 @@ import org.springframework.web.bind.annotation.RequestBody;
* @description 远程调用资源配额 Client
* @date 2021-7-21
*/
@FeignClient(value = ApplicationNameConst.SERVER_K8S,fallback = ResourceQuotaClientFallback.class)
@FeignClient(value = ApplicationNameConst.SERVER_K8S, contextId = "resourceQuotaClient", fallback = ResourceQuotaClientFallback.class)
public interface ResourceQuotaClient {

/**
* 更新 ResourceQuota
*
* @param userConfigDTO 用户配置信息
* @param resourceQuotaDTO 用户配置信息
* @return
*/
@PostMapping(value = "/resourceQuota/update")
DataResponseBody updateResourceQuota(@RequestBody UserConfigDTO userConfigDTO);
DataResponseBody updateResourceQuota(@RequestBody ResourceQuotaDTO resourceQuotaDTO);

}

+ 42
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/client/SystemNamespaceClient.java View File

@@ -0,0 +1,42 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.client;

import org.dubhe.admin.client.fallback.SystemNamespaceClientFallback;
import org.dubhe.biz.base.constant.ApplicationNameConst;
import org.dubhe.biz.base.dto.NamespaceDeleteDTO;
import org.dubhe.biz.base.vo.DataResponseBody;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;

/**
* @description 命名空间状态管理feign远程调用
* @date 2021-11-26
*/
@FeignClient(value = ApplicationNameConst.SERVER_K8S, contextId = "systemNamespaceClient", fallback = SystemNamespaceClientFallback.class)
public interface SystemNamespaceClient {

/**
* 删除用户namespace
* @param namespaceDeleteDTO 用户id
* @return DataResponseBody
*/
@DeleteMapping(value="/namespace")
DataResponseBody deleteNamespace(@RequestBody NamespaceDeleteDTO namespaceDeleteDTO, @RequestHeader("Authorization") String accessToken);
}

+ 45
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/client/SystemNodeClient.java View File

@@ -0,0 +1,45 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.client;

import org.dubhe.admin.client.fallback.SystemNodeClientFallback;
import org.dubhe.biz.base.constant.ApplicationNameConst;
import org.dubhe.biz.base.dto.QueryUserK8sResourceDTO;
import org.dubhe.biz.base.vo.DataResponseBody;
import org.dubhe.biz.base.vo.QueryUserResourceSpecsVO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.List;

/**
* @description 远程查询用户k8s资源是否可用
* @date 2021-9-7
*/
@FeignClient(value = ApplicationNameConst.SERVER_K8S, contextId = "systemNodeClient", fallback = SystemNodeClientFallback.class)
public interface SystemNodeClient {
/**
* 查询用户k8s可用资源
*
* @param queryUserK8sResources 用户k8s可用资源查询条件
* @return List<QueryUserResourceSpecsVO> 用户k8s可用资源列表
*/
@PostMapping("/node/queryUserResource")
DataResponseBody<List<QueryUserResourceSpecsVO>> queryUserK8sResource(@RequestBody List<QueryUserK8sResourceDTO> queryUserK8sResources);

}

+ 33
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/client/fallback/GpuConfigClientFallback.java View File

@@ -0,0 +1,33 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.client.fallback;

import org.dubhe.admin.client.GpuConfigClient;
import org.dubhe.biz.base.dto.GpuConfigDTO;
import org.dubhe.biz.base.vo.DataResponseBody;
import org.dubhe.biz.dataresponse.factory.DataResponseFactory;

/**
* @description GpuConfigClient 熔断处理
* @date 2021-9-7
*/
public class GpuConfigClientFallback implements GpuConfigClient {
@Override
public DataResponseBody updateGpuConfig(GpuConfigDTO gpuConfigDTO) {
return DataResponseFactory.failed("Call GpuConfig server updateGpuConfig error");
}
}

+ 42
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/client/fallback/ResourceNamespaceClientFallback.java View File

@@ -0,0 +1,42 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.client.fallback;

import org.dubhe.admin.client.ResourceNamespaceClient;
import org.dubhe.biz.base.vo.DataResponseBody;
import org.dubhe.biz.base.vo.UserAllotVO;
import org.dubhe.biz.dataresponse.factory.DataResponseFactory;

import java.util.List;
import java.util.Map;

/**
* @description
* @date 2021-11-19
*/
public class ResourceNamespaceClientFallback implements ResourceNamespaceClient {

@Override
public DataResponseBody<List<UserAllotVO>> getResourceNamespace(Integer resourceType, String sumDay) {
return DataResponseFactory.failed("Call MetricsApi.getNamespaceUsageRate error");
}

@Override
public DataResponseBody<Map<Long, String>> getResourceUsageByUser(Integer resourceType, String sumDay, String namespaces) {
return DataResponseFactory.failed("Call MetricsApi.getResourceUsageByUser error");
}
}

+ 2
- 2
dubhe-server/admin/src/main/java/org/dubhe/admin/client/fallback/ResourceQuotaClientFallback.java View File

@@ -17,7 +17,7 @@
package org.dubhe.admin.client.fallback;

import org.dubhe.admin.client.ResourceQuotaClient;
import org.dubhe.admin.domain.dto.UserConfigDTO;
import org.dubhe.biz.base.dto.ResourceQuotaDTO;
import org.dubhe.biz.base.vo.DataResponseBody;
import org.dubhe.biz.dataresponse.factory.DataResponseFactory;

@@ -27,7 +27,7 @@ import org.dubhe.biz.dataresponse.factory.DataResponseFactory;
*/
public class ResourceQuotaClientFallback implements ResourceQuotaClient {
@Override
public DataResponseBody updateResourceQuota(UserConfigDTO userConfigDTO) {
public DataResponseBody updateResourceQuota(ResourceQuotaDTO resourceQuotaDTO) {
return DataResponseFactory.failed("Call ResourceQuota server updateResourceQuota error");
}
}

+ 35
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/client/fallback/SystemNamespaceClientFallback.java View File

@@ -0,0 +1,35 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.client.fallback;

import org.dubhe.admin.client.SystemNamespaceClient;
import org.dubhe.biz.base.dto.NamespaceDeleteDTO;
import org.dubhe.biz.base.vo.DataResponseBody;
import org.dubhe.biz.dataresponse.factory.DataResponseFactory;

/**
* @description 命名空间状态管理feign远程调用熔断处理
* @date 2021-11-26
*/
public class SystemNamespaceClientFallback implements SystemNamespaceClient {

@Override
public DataResponseBody deleteNamespace(NamespaceDeleteDTO namespaceDeleteDTO, String accessToken) {
return DataResponseFactory.failed("Call SystemNamespace server deleteNamespace error");
}

}

+ 37
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/client/fallback/SystemNodeClientFallback.java View File

@@ -0,0 +1,37 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.client.fallback;

import org.dubhe.admin.client.SystemNodeClient;
import org.dubhe.biz.base.dto.QueryUserK8sResourceDTO;
import org.dubhe.biz.base.vo.DataResponseBody;
import org.dubhe.biz.base.vo.QueryUserResourceSpecsVO;
import org.dubhe.biz.dataresponse.factory.DataResponseFactory;

import java.util.List;

/**
* @description SystemNodeClient 熔断处理
* @date 2021-9-7
*/
public class SystemNodeClientFallback implements SystemNodeClient {

@Override
public DataResponseBody<List<QueryUserResourceSpecsVO>> queryUserK8sResource(List<QueryUserK8sResourceDTO> queryUserK8sResources) {
return DataResponseFactory.failed("Call SystemNode server queryUserK8sResource error");
}
}

+ 60
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/client/template/GpuConfigTemplateClient.java View File

@@ -0,0 +1,60 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.client.template;

import cn.hutool.http.HttpStatus;
import com.alibaba.fastjson.JSON;
import org.dubhe.biz.base.constant.ApplicationNameConst;
import org.dubhe.biz.base.dto.GpuConfigDTO;
import org.dubhe.biz.base.vo.DataResponseBody;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

/**
* @description 远程调用k8sGPU资源配额 Client
* @date 2021-11-16
*/
@Component
public class GpuConfigTemplateClient {

@Autowired
private RestTemplate restTemplate;

/**
* 更新k8sGPU资源配额
*
* @param gpuConfigDTO k8sGPU资源配额
* @return DataResponseBody
*/
public DataResponseBody updateGpuConfig(GpuConfigDTO gpuConfigDTO, String token) {
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.AUTHORIZATION, token);
headers.setContentType(MediaType.valueOf(MediaType.APPLICATION_JSON_VALUE));
HttpEntity<String> httpEntity = new HttpEntity<>(JSON.toJSONString(gpuConfigDTO), headers);
ResponseEntity<DataResponseBody> responseEntity = restTemplate.postForEntity("http://" + ApplicationNameConst.SERVER_K8S + "/gpuConfig/update", httpEntity, DataResponseBody.class);
if (HttpStatus.HTTP_OK != responseEntity.getStatusCodeValue()) {
return null;
}
DataResponseBody restResult = responseEntity.getBody();
return restResult;
}
}

+ 91
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/client/template/ObtainAccessToken.java View File

@@ -0,0 +1,91 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.client.template;

import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.http.HttpStatus;
import org.dubhe.biz.base.constant.ApplicationNameConst;
import org.dubhe.biz.base.constant.AuthConst;
import org.dubhe.biz.base.exception.BusinessException;
import org.dubhe.biz.base.vo.DataResponseBody;
import org.dubhe.biz.log.enums.LogEnum;
import org.dubhe.biz.log.utils.LogUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.LinkedHashMap;
import java.util.Map;

/**
* @description 模拟登录获取token
* @date 2021-11-11
*/
@Component
public class ObtainAccessToken {

@Autowired
private RestTemplate restTemplate;

@Value("${rsa.private_key}")
private String privateKey;

/**
* 模拟登录获取token
* @return String token
*/
public String generateToken(String username,String userPassword) {
String password = null;
try {
RSA rsa = new RSA(privateKey, null);
password = new String(rsa.decrypt(userPassword, KeyType.PrivateKey));
} catch (Exception e) {
LogUtil.error(LogEnum.BIZ_SYS, "rsa 密钥解析失败, originPassword:{} , 密钥:{},异常:{}", userPassword, KeyType.PrivateKey, e);
throw new BusinessException("密钥解析失败");
}
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("grant_type", AuthConst.GRANT_TYPE);
params.add("client_id", AuthConst.CLIENT_ID);
params.add("client_secret", AuthConst.CLIENT_SECRET);
params.add("username", username);
params.add("password", password);
params.add("scope", "all");
HttpHeaders headers = new HttpHeaders();
// 需求需要传参为application/x-www-form-urlencoded格式
headers.setContentType(MediaType.valueOf(MediaType.APPLICATION_FORM_URLENCODED_VALUE));
HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<>(params, headers);
ResponseEntity<DataResponseBody> responseEntity = restTemplate.postForEntity("http://" + ApplicationNameConst.SERVER_AUTHORIZATION + "/oauth/token", httpEntity, DataResponseBody.class);
if (HttpStatus.HTTP_OK != responseEntity.getStatusCodeValue()) {
return null;
}
DataResponseBody restResult = responseEntity.getBody();
Map map = new LinkedHashMap();
if (restResult.succeed()) {
map = (Map) restResult.getData();
}
// 返回 token
return (String) map.get("token");
}
}

+ 60
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/client/template/ResourceQuotaTemplateClient.java View File

@@ -0,0 +1,60 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.client.template;

import cn.hutool.http.HttpStatus;
import com.alibaba.fastjson.JSON;
import org.dubhe.biz.base.constant.ApplicationNameConst;
import org.dubhe.biz.base.dto.ResourceQuotaDTO;
import org.dubhe.biz.base.vo.DataResponseBody;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

/**
* @description 远程调用资源配额
* @date 2021-11-16
*/
@Component
public class ResourceQuotaTemplateClient {

@Autowired
private RestTemplate restTemplate;

/**
* 更新 ResourceQuota
*
* @param resourceQuotaDTO 用户配置信息
* @return DataResponseBody
*/
public DataResponseBody updateResourceQuota(ResourceQuotaDTO resourceQuotaDTO, String token) {
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.AUTHORIZATION, token);
headers.setContentType(MediaType.valueOf(MediaType.APPLICATION_JSON_VALUE));
HttpEntity<String> httpEntity = new HttpEntity<>(JSON.toJSONString(resourceQuotaDTO), headers);
ResponseEntity<DataResponseBody> responseEntity = restTemplate.postForEntity("http://" + ApplicationNameConst.SERVER_K8S + "/resourceQuota/update", httpEntity, DataResponseBody.class);
if (HttpStatus.HTTP_OK != responseEntity.getStatusCodeValue()) {
return null;
}
DataResponseBody restResult = responseEntity.getBody();
return restResult;
}
}

+ 79
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/config/AdminPoolConfig.java View File

@@ -0,0 +1,79 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.config;

import org.dubhe.biz.log.enums.LogEnum;
import org.dubhe.biz.log.utils.LogUtil;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
* @description 线程池配置类
* @date 2020-07-17
*/
@Configuration
public class AdminPoolConfig implements AsyncConfigurer {

@Value("${basepool.corePoolSize:40}")
private Integer corePoolSize;
@Value("${basepool.maximumPoolSize:60}")
private Integer maximumPoolSize;
@Value("${basepool.keepAliveTime:120}")
private Integer keepAliveTime;
@Value("${basepool.blockQueueSize:20}")
private Integer blockQueueSize;

/**
* 异步处理线程池
* @return Executor 线程实例
*/
@Bean("adminExecutor")
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
//核心线程数
taskExecutor.setCorePoolSize(corePoolSize);
taskExecutor.setAllowCoreThreadTimeOut(true);
//最大线程数
taskExecutor.setMaxPoolSize(maximumPoolSize);
//超时时间
taskExecutor.setKeepAliveSeconds(keepAliveTime);
//配置队列大小
taskExecutor.setQueueCapacity(blockQueueSize);
//配置线程池前缀
taskExecutor.setThreadNamePrefix("async-admin-");
//拒绝策略
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
taskExecutor.initialize();
return taskExecutor;
}

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
LogUtil.error(LogEnum.SYS_ERR, "start capturing the exception information of asynchronous task management admin-----》》》");
return (ex, method, params) -> {
LogUtil.error(LogEnum.SYS_ERR, "async admin task failed,the name of admin is {}, params are {}, exception is {}", method.getName(), params, ex);
};
}
}

+ 27
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/dao/GpuResourceMapper.java View File

@@ -0,0 +1,27 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.dubhe.admin.domain.entity.GpuResource;

/**
* @description GPU资源管理mapper接口
* @date 2021-08-20
*/
public interface GpuResourceMapper extends BaseMapper<GpuResource> {
}

+ 45
- 1
dubhe-server/admin/src/main/java/org/dubhe/admin/dao/UserConfigMapper.java View File

@@ -17,10 +17,15 @@
package org.dubhe.admin.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.dubhe.admin.domain.entity.UserConfig;
import org.dubhe.admin.domain.vo.UserLimitConfigVO;
import org.dubhe.biz.base.vo.UserAllotResourceVO;
import org.dubhe.biz.base.vo.UserAllotVO;

import java.util.List;
import org.apache.ibatis.annotations.Param;

/**
* @description 用户配置 Mapper
@@ -33,4 +38,43 @@ public interface UserConfigMapper extends BaseMapper<UserConfig> {
* @param userConfig 用户配置
*/
Long insertOrUpdate(UserConfig userConfig);

/**
* 统计内存、CPU配额
*/
@Select("select sum(memory_limit) memoryAllotTotal,sum(cpu_limit) cpuAllotTotal from user_config where deleted=0;")
UserAllotResourceVO selectResourceSum();

/**
* 统计CPU配额Top10
*/
@Select("select u.username,uc.cpu_limit allotTotal from user_config uc, user u where uc.user_id=u.id and uc.deleted=0 order by cpu_limit desc limit 10;")
List<UserAllotVO> selectCpuAllotTotal();

/**
* 统计内存配额Top10
*/
@Select("select u.username,uc.memory_limit allotTotal from user_config uc, user u where uc.user_id=u.id and uc.deleted=0 order by memory_limit desc limit 10;")
List<UserAllotVO> selectMemoryAllotTotal();

/**
* 根据用户id查询资源配额(cpu、memory)
*
* @param userId 用户ID
* @return 资源配额实体
*/
@Select("select * from user_config where user_id=#{userId} AND deleted=0")
UserConfig selectLimitSumByUser(@Param("userId") Long userId);

/**
* 分页查询资源列表
*
* @param page 分页对象
* @param sort 排序字段
* @param order 排序方式
* @return 用户配额列表
*/
List<UserLimitConfigVO> selectLimitSum(Page page,
@Param("sort") String sort,
@Param("order") String order);
}

+ 81
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/dao/UserGpuConfigMapper.java View File

@@ -0,0 +1,81 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.dubhe.admin.domain.entity.UserGpuConfig;
import org.dubhe.biz.base.vo.GpuAllotVO;

import java.util.List;

/**
* @description 用户GPU配置 Mapper
* @date 2021-9-2
*/
public interface UserGpuConfigMapper extends BaseMapper<UserGpuConfig> {

/**
* 批量添加用户GPU配置
*
* @param userGpuConfigs 用户GPU配置实体集合
*/
void insertBatchs(List<UserGpuConfig> userGpuConfigs);

/**
* 根据userId查询用户GPU配置记录数
* @param userId 用户id
* @return Integer 用户GPU配置记录数
*/
@Select("select count(*) from user_gpu_config where user_id= #{userId}")
Integer selectCountByUserId(@Param("userId") Long userId);

/**
* 统计GPU型号配额总量
*
* @return GPU具体型号资源配额
*/
@Select("select gpu_model gpuModel,sum(gpu_limit)allotTotal from user_gpu_config where deleted=0 group by gpu_model")
List<GpuAllotVO> selectGpuAllotSum();

/**
* GPU配额TOP10统计
*/
@Select("SELECT u.username,gc.user_id,SUM(gc.gpu_limit)gpuLimit FROM user_gpu_config gc, user u WHERE gc.user_id=u.id AND gc.deleted=0" +
" GROUP BY gc.user_id ORDER BY gpuLimit DESC LIMIT 10")
List<UserGpuConfig> selectAllotTotal();

/**
* 查询某用户具体的GPU型号配额
*
* @param userId 用户ID
* @return GPU型号配额
*/
@Select("select gpu_model gpuModel,sum(gpu_limit)allotTotal from user_gpu_config where user_id=#{userId} and deleted=0 group by gpuModel")
List<GpuAllotVO> selectGpuModelTotal(@Param("userId") Long userId);

/**
* 根据用户id查询GPU配额总量
*
* @param userId 用户ID
* @return GPU配额总量
*/
@Select("SELECT IFNULL(SUM(gpu_limit),0)gpuSum FROM user_gpu_config WHERE user_id=#{userId} AND deleted=0")
int selectGpuLimitSum(@Param("userId") Long userId);

}

+ 16
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/dao/UserMapper.java View File

@@ -110,6 +110,13 @@ public interface UserMapper extends BaseMapper<User> {
*/
Set<String> queryPermissionByUserId(Long userId);

/**
* 查找用户所在的用户组名
*
* @param userId 用户id
* @return 用户组名
*/
String queryUserGroupNameByUserId(Long userId);

/**
* 查询实体及关联对象
@@ -144,4 +151,13 @@ public interface UserMapper extends BaseMapper<User> {
@ResultMap(value = "userMapperResults")
IPage<User> selectCollPageByRoleId(Page<User> page, @Param("ew") Wrapper<User> queryWrapper, Long roleId);

/**
* 根据用户id查找用户名
*
* @param userId 用户id
* @return 用户名
*/
@Select("SELECT username FROM user WHERE id=#{userId} and enabled=1 AND deleted=0 ")
String findUserNameById(@Param("userId") Long userId);

}

+ 1
- 1
dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/AuthCodeQueryDTO.java View File

@@ -32,6 +32,6 @@ public class AuthCodeQueryDTO extends PageQueryBase implements Serializable {
private static final long serialVersionUID = 1L;

@ApiModelProperty(value = "权限组名称")
private String authCode;
private String keyword;

}

+ 57
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/GpuResourceCreateDTO.java View File

@@ -0,0 +1,57 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.domain.dto;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import org.dubhe.biz.base.constant.MagicNumConstant;
import org.dubhe.biz.base.constant.StringConstant;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import java.io.Serializable;

/**
* @description GPU资源创建
* @date 2021-08-20
*/
@Data
@Accessors(chain = true)
public class GpuResourceCreateDTO implements Serializable {

private static final long serialVersionUID = 1L;

@ApiModelProperty(value = "GPU类型(例如:NVIDIA)", required = true)
@NotBlank(message = "GPU类型")
@Length(max = MagicNumConstant.SIXTY_FOUR, message = "GPU类型错误-输入长度不能超过64个字符")
@Pattern(regexp = StringConstant.REGEXP_GPU_TYPE, message = "支持字母、数字、汉字、英文横杠、英文.号、空白字符和英文斜杠")
private String gpuType;

@ApiModelProperty(value = "GPU型号(例如:v100)", required = true)
@NotBlank(message = "GPU型号")
@Length(max = MagicNumConstant.SIXTY_FOUR, message = "GPU型号错误-输入长度不能超过64个字符")
@Pattern(regexp = StringConstant.REGEXP_GPU_MODEL, message = "支持小写字母、数字、英文横杠、英文.号和英文斜杠")
private String gpuModel;

@ApiModelProperty(value = "k8s GPU资源标签key值(例如:nvidia.com/gpu)", required = true)
@NotBlank(message = "k8s GPU资源标签key值")
@Length(max = MagicNumConstant.SIXTY_FOUR, message = "GPU型号错误-输入长度不能超过64个字符")
@Pattern(regexp = StringConstant.REGEXP_K8S, message = "支持小写字母、数字、英文横杠、英文.号和英文斜杠")
private String k8sLabelKey;
}

+ 40
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/GpuResourceDeleteDTO.java View File

@@ -0,0 +1,40 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.domain.dto;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;

import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Set;

/**
* @description GPU资源删除
* @date 2021-08-20
*/
@Data
@Accessors(chain = true)
public class GpuResourceDeleteDTO implements Serializable {

private static final long serialVersionUID = 1L;

@ApiModelProperty(value = "id", required = true)
@NotNull(message = "id不能为空")
private Set<Long> ids;
}

+ 45
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/GpuResourceQueryDTO.java View File

@@ -0,0 +1,45 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.domain.dto;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import org.dubhe.biz.base.constant.MagicNumConstant;
import org.dubhe.biz.base.constant.StringConstant;
import org.dubhe.biz.db.base.PageQueryBase;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.Pattern;
import java.io.Serializable;

/**
* @description GPU资源查询
* @date 2021-08-20
*/
@Data
@Accessors(chain = true)
public class GpuResourceQueryDTO extends PageQueryBase implements Serializable {

private static final long serialVersionUID = 1L;

@ApiModelProperty(value = "GPU类型(例如:NVIDIA)")
@Length(max = MagicNumConstant.SIXTY_FOUR, message = "GPU类型错误-输入长度不能超过64个字符")
@Pattern(regexp = StringConstant.REGEXP_GPU_TYPE, message = "支持字母、数字、汉字、英文横杠、英文.号、空白字符和英文斜杠")
private String gpuType;

}

+ 64
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/GpuResourceUpdateDTO.java View File

@@ -0,0 +1,64 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.domain.dto;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import org.dubhe.biz.base.constant.MagicNumConstant;
import org.dubhe.biz.base.constant.StringConstant;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.io.Serializable;

/**
* @description GPU资源修改
* @date 2021-08-20
*/
@Data
@Accessors(chain = true)
public class GpuResourceUpdateDTO implements Serializable {

private static final long serialVersionUID = 1L;

@ApiModelProperty(value = "id", required = true)
@NotNull(message = "id不能为null")
@Min(value = MagicNumConstant.ONE, message = "id必须大于1")
private Long id;

@ApiModelProperty(value = "GPU类型(例如:NVIDIA)", required = true)
@NotBlank(message = "GPU类型")
@Length(max = MagicNumConstant.SIXTY_FOUR, message = "GPU类型错误-输入长度不能超过64个字符")
@Pattern(regexp = StringConstant.REGEXP_GPU_TYPE, message = "支持字母、数字、汉字、英文横杠、英文.号、空白字符和英文斜杠")
private String gpuType;

@ApiModelProperty(value = "GPU型号(例如:v100)", required = true)
@NotBlank(message = "GPU型号")
@Length(max = MagicNumConstant.SIXTY_FOUR, message = "GPU型号错误-输入长度不能超过64个字符")
@Pattern(regexp = StringConstant.REGEXP_GPU_MODEL, message = "支持小写字母、数字、英文横杠、英文.号、空白字符和英文斜杠")
private String gpuModel;

@ApiModelProperty(value = "k8s GPU资源标签key值(例如:nvidia.com/gpu)", required = true)
@NotBlank(message = "k8s GPU资源标签key值")
@Length(max = MagicNumConstant.SIXTY_FOUR, message = "GPU型号错误-输入长度不能超过64个字符")
@Pattern(regexp = StringConstant.REGEXP_K8S, message = "支持小写字母、数字、英文横杠、英文.号和英文斜杠")
private String k8sLabelKey;
}

+ 2
- 1
dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/MenuQueryDTO.java View File

@@ -36,8 +36,9 @@ public class MenuQueryDTO {
@Query(propName = "create_time", type = Query.Type.BETWEEN)
private List<Timestamp> createTime;


@Query(propName = "deleted", type = Query.Type.EQ)
private Boolean deleted = false;

@Query(type = Query.Type.ORDER_BY)
private String sort = "sort";
}

+ 65
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/QueryUserResourceSpecsDTO.java View File

@@ -0,0 +1,65 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.domain.dto;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import org.dubhe.biz.base.constant.MagicNumConstant;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.io.Serializable;

/**
* @description 查询用户资源规格
* @date 2021-09-07
*/
@Data
@Accessors(chain = true)
public class QueryUserResourceSpecsDTO implements Serializable {

private static final long serialVersionUID = 1L;

@ApiModelProperty(value = "用户id")
@Min(value = MagicNumConstant.ONE, message = "用户id,不能小于1")
private Long userId;

@ApiModelProperty(value = "所属业务场景(0:通用,1:dubhe-notebook,2:dubhe-train,3:dubhe-serving,4:dubhe-tadl,5:dubhe-optimize))", required = true)
@NotNull(message = "所属业务场景不能为空")
@Min(value = MagicNumConstant.ZERO, message = "所属业务场景错误")
@Max(value = MagicNumConstant.FIVE, message = "所属业务场景错误")
private Integer module;

@ApiModelProperty("规格类型(0为CPU, 1为GPU)")
@NotNull(message = "规格类型(0为CPU, 1为GPU)不能为空")
private Boolean resourcesPoolType;

@ApiModelProperty(value = "节点个数")
@Min(value = MagicNumConstant.ONE, message = "节点个数,默认为1个")
private Integer resourcesPoolNode;

@ApiModelProperty(value = "GPU型号(例如:v100)")
private String gpuModel;

@ApiModelProperty(value = "k8s GPU资源标签key值(例如:nvidia.com/gpu)")
private String k8sLabelKey;

@ApiModelProperty(value = "多GPU,true:GPU数大于1核,false:GPU数等于1核")
private Boolean multiGpu;
}

+ 2
- 2
dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/ResourceSpecsCreateDTO.java View File

@@ -42,10 +42,10 @@ public class ResourceSpecsCreateDTO implements Serializable {
@Pattern(regexp = StringConstant.REGEXP_SPECS, message = "规格名称支持字母、数字、汉字、英文横杠、下划线和空白字符")
private String specsName;

@ApiModelProperty(value = "所属业务场景(0:通用,1:dubhe-notebook,2:dubhe-train,3:dubhe-serving)", required = true)
@ApiModelProperty(value = "所属业务场景(0:通用,1:dubhe-notebook,2:dubhe-train,3:dubhe-serving, 4:dubhe-tadl, 5:dubhe-optimize)", required = true)
@NotNull(message = "所属业务场景不能为空")
@Min(value = MagicNumConstant.ZERO, message = "所属业务场景错误")
@Max(value = MagicNumConstant.THREE, message = "所属业务场景错误")
@Max(value = MagicNumConstant.FIVE, message = "所属业务场景错误")
private Integer module;

@ApiModelProperty(value = "CPU数量,单位:核", required = true)


+ 5
- 2
dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/ResourceSpecsQueryDTO.java View File

@@ -37,6 +37,9 @@ public class ResourceSpecsQueryDTO extends PageQueryBase implements Serializable

private static final long serialVersionUID = 1L;

@ApiModelProperty(value = "多GPU,true:GPU数大于1核,false:GPU数等于1核")
private Boolean multiGpu;

@ApiModelProperty("规格名称")
@Length(max = MagicNumConstant.THIRTY_TWO, message = "规格名称错误")
private String specsName;
@@ -44,8 +47,8 @@ public class ResourceSpecsQueryDTO extends PageQueryBase implements Serializable
@ApiModelProperty("规格类型(0为CPU, 1为GPU)")
private Boolean resourcesPoolType;

@ApiModelProperty("所属业务场景(0:通用,1:dubhe-notebook,2:dubhe-train,3:dubhe-serving)")
@ApiModelProperty("所属业务场景(0:通用,1:dubhe-notebook,2:dubhe-train,3:dubhe-serving,4:dubhe-tadl,5:dubhe-optimize)")
@Min(value = MagicNumConstant.ZERO, message = "所属业务场景错误")
@Max(value = MagicNumConstant.THREE, message = "所属业务场景错误")
@Max(value = MagicNumConstant.FIVE, message = "所属业务场景错误")
private Integer module;
}

+ 2
- 2
dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/ResourceSpecsUpdateDTO.java View File

@@ -49,10 +49,10 @@ public class ResourceSpecsUpdateDTO implements Serializable {
@Pattern(regexp = StringConstant.REGEXP_SPECS, message = "规格名称支持字母、数字、汉字、英文横杠、下划线和空白字符")
private String specsName;

@ApiModelProperty(value = "所属业务场景(0:通用,1:dubhe-notebook,2:dubhe-train,3:dubhe-serving)", required = true)
@ApiModelProperty(value = "所属业务场景(0:通用,1:dubhe-notebook,2:dubhe-train,3:dubhe-serving, 4:dubhe-tadl, 5:dubhe-optimize)", required = true)
@NotNull(message = "所属业务场景不能为空")
@Min(value = MagicNumConstant.ZERO, message = "所属业务场景错误")
@Max(value = MagicNumConstant.THREE, message = "所属业务场景错误")
@Max(value = MagicNumConstant.FIVE, message = "所属业务场景错误")
private Integer module;

@ApiModelProperty(value = "CPU数量,单位:核")


+ 46
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/UserGpuResourceQueryDTO.java View File

@@ -0,0 +1,46 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.domain.dto;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import org.dubhe.biz.base.constant.MagicNumConstant;
import org.dubhe.biz.base.constant.StringConstant;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import java.io.Serializable;

/**
* @description 用户GPU资源查询
* @date 2021-08-20
*/
@Data
@Accessors(chain = true)
public class UserGpuResourceQueryDTO implements Serializable {

private static final long serialVersionUID = 1L;

@ApiModelProperty(value = "GPU类型(例如:NVIDIA)")
@NotBlank(message = "GPU类型")
@Length(max = MagicNumConstant.SIXTY_FOUR, message = "GPU类型错误-输入长度不能超过64个字符")
@Pattern(regexp = StringConstant.REGEXP_GPU_TYPE, message = "支持字母、数字、汉字、英文横杠、英文.号、空白字符和英文斜杠")
private String gpuType;

}

+ 35
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/UserGroupConfigSaveDTO.java View File

@@ -0,0 +1,35 @@
package org.dubhe.admin.domain.dto;

import lombok.Data;
import lombok.experimental.Accessors;
import org.dubhe.biz.base.dto.UserGpuConfigDTO;

import javax.validation.constraints.NotNull;
import java.util.List;

/**
* @date 2021-11-24
* @description 用户组用户统一配置DTO
*/
@Data
@Accessors(chain = true)
public class UserGroupConfigSaveDTO {

private static final long serialVersionUID = 1L;

@NotNull(message = "用户组ID 不能为空")
private Long groupId;

@NotNull(message = "Notebook 延迟删除时间配置不能为空")
private Integer notebookDelayDeleteTime;

@NotNull(message = "CPU 资源限制配置不能为空")
private Integer cpuLimit;

@NotNull(message = "内存资源限制配置不能为空")
private Integer memoryLimit;

private Long defaultImageId;

private List<UserGpuConfigDTO> gpuResources;
}

+ 31
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/UserResourceListDTO.java View File

@@ -0,0 +1,31 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.domain.dto;

import org.dubhe.biz.db.base.PageQueryBase;

import java.io.Serializable;

/**
* @description 用户资源列表
* @date 2021-11-25
*/
public class UserResourceListDTO extends PageQueryBase implements Serializable {
private static final long serialVersionUID = 1L;
}

+ 41
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/domain/dto/UserResourceQueryDTO.java View File

@@ -0,0 +1,41 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.domain.dto;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import javax.validation.constraints.NotNull;

/**
* @description 用户资源统计DTO
* @date 2021-11-17
*/
@Data
public class UserResourceQueryDTO {

@ApiModelProperty("资源统计类型")
@NotNull
private Integer statType;

@ApiModelProperty("资源类型")
@NotNull
private Integer resourceType;

@ApiModelProperty("统计时间段")
private String sumDay;
}

+ 63
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/domain/entity/GpuResource.java View File

@@ -0,0 +1,63 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.domain.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import org.dubhe.biz.db.entity.BaseEntity;

import javax.validation.constraints.NotNull;

/**
* @description GPU资源实体类
* @date 2021-08-20
*/
@Data
@Accessors(chain = true)
@TableName("gpu_resource")
public class GpuResource extends BaseEntity {

/**
* 主键ID
*/
@TableId(value = "id", type = IdType.AUTO)
@NotNull(groups = {Update.class})
private Long id;

/**
* GPU类型(例如:NVIDIA)
*/
@TableField(value = "gpu_type")
private String gpuType;

/**
* GPU型号(例如:v100)
*/
@TableField(value = "gpu_model")
private String gpuModel;

/**
* k8s GPU资源标签key值(例如:nvidia.com/gpu)
*/
@TableField(value = "k8s_label_key")
private String k8sLabelKey;

}

+ 8
- 2
dubhe-server/admin/src/main/java/org/dubhe/admin/domain/entity/UserConfig.java View File

@@ -39,6 +39,12 @@ public class UserConfig extends BaseEntity {
@TableId(value = "user_id")
private Long userId;

@TableField(exist = false)
private String userName;

@TableField(exist = false)
private String nickName;

@TableId(value = "notebook_delay_delete_time")
private Integer notebookDelayDeleteTime;

@@ -48,6 +54,6 @@ public class UserConfig extends BaseEntity {
@TableId(value = "memory_limit")
private Integer memoryLimit;

@TableId(value = "gpu_limit")
private Integer gpuLimit;
@TableId(value = "default_image_id")
private Long defaultImageId;
}

+ 80
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/domain/entity/UserGpuConfig.java View File

@@ -0,0 +1,80 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.domain.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import org.dubhe.biz.db.entity.BaseEntity;

import javax.validation.constraints.NotNull;

/**
* @description 用户GPU配置实体
* @date 2021-08-20
*/
@Data
@Accessors(chain = true)
@TableName("user_gpu_config")
public class UserGpuConfig extends BaseEntity {

/**
* 主键ID
*/
@TableId(value = "id", type = IdType.AUTO)
@NotNull(groups = {Update.class})
private Long id;

/**
* 用户id
*/
@TableId(value = "user_id")
private Long userId;

/**
* 用户名
*/
@TableField(exist = false)
private String userName;

/**
* GPU类型(例如:NVIDIA)
*/
@TableField(value = "gpu_type")
private String gpuType;

/**
* GPU型号(例如:v100)
*/
@TableField(value = "gpu_model")
private String gpuModel;

/**
* k8s GPU资源标签key值(例如:nvidia.com/gpu)
*/
@TableField(value = "k8s_label_key")
private String k8sLabelKey;

/**
* 用户显卡资源限制配置,单位:卡
*/
@TableId(value = "gpu_limit")
private Integer gpuLimit;
}

+ 59
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/domain/vo/GpuResourceQueryVO.java View File

@@ -0,0 +1,59 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.domain.vo;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.sql.Timestamp;

/**
* @description GPU资源查询结果封装类
* @date 2021-08-20
*/
@Data
@Accessors(chain = true)
public class GpuResourceQueryVO implements Serializable {

private static final long serialVersionUID = 1L;

@ApiModelProperty("主键ID")
private Long id;

@ApiModelProperty("GPU类型(例如:NVIDIA)")
private String gpuType;

@ApiModelProperty("GPU型号(例如:v100)")
private String gpuModel;

@ApiModelProperty("k8s GPU资源标签key值(例如:nvidia.com/gpu)")
private String k8sLabelKey;

@ApiModelProperty("创建人")
private Long createUserId;

@ApiModelProperty("创建时间")
private Timestamp createTime;

@ApiModelProperty("更新人")
private Long updateUserId;

@ApiModelProperty("更新时间")
private Timestamp updateTime;
}

+ 3
- 2
dubhe-server/admin/src/main/java/org/dubhe/admin/domain/vo/MenuVo.java View File

@@ -20,13 +20,14 @@ import lombok.Data;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

/**
* @description 菜单VO
* @date 2020-06-01
*/
@Data
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class MenuVo implements Serializable {

private static final long serialVersionUID = 7145999097655311261L;
@@ -38,7 +39,7 @@ public class MenuVo implements Serializable {

private String component;

private MenuMetaVo meta;
private Map<String,Object> meta;

private List<MenuVo> children;
}

+ 39
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/domain/vo/UserLimitConfigVO.java View File

@@ -0,0 +1,39 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.domain.vo;

import lombok.Data;

/**
* @description
* @date 2021-11-26
*/
@Data
public class UserLimitConfigVO {

private Long userId;

private String userName;

private String nickName;

private String gpu;

private String cpu;

private String mem;
}

+ 91
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/domain/vo/UserResourceResVO.java View File

@@ -0,0 +1,91 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.domain.vo;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import org.dubhe.biz.base.vo.GpuAllotVO;

import java.util.List;

/**
* @description 用户资源分页列表VO
* @date 2021-11-23
*/
@Data
@Accessors(chain = true)
public class UserResourceResVO {

@ApiModelProperty("编号")
private Long id;

@ApiModelProperty("用户名")
private String userName;

@ApiModelProperty("账户名(昵称)")
private String nickName;

@ApiModelProperty("GPU配额")
private String gpu;

@ApiModelProperty("GPU具体型号配额")
private List<GpuAllotVO> gpuModelAllots;

@ApiModelProperty("7天内GPU峰值使用率")
private String gpu7;

@ApiModelProperty("7天内GPU峰值使用量")
private String gpu7unit;

@ApiModelProperty("15天内GPU峰值使用率")
private String gpu15;

@ApiModelProperty("15天内GPU峰值使用量")
private String gpu15unit;

@ApiModelProperty("内存配额")
private String mem;

@ApiModelProperty("7天内内存峰值使用率")
private String mem7;

@ApiModelProperty("7天内内存峰值使用量")
private String mem7unit;

@ApiModelProperty("15天内内存峰值使用率")
private String mem15;

@ApiModelProperty("15天内内存峰值使用量")
private String mem15unit;

@ApiModelProperty("CPU配额")
private String cpu;

@ApiModelProperty("7天内CPU峰值使用率")
private String cpu7;

@ApiModelProperty("7天内CPU峰值使用量")
private String cpu7unit;

@ApiModelProperty("15天内CPU峰值使用率")
private String cpu15;

@ApiModelProperty("15天内CPU峰值使用量")
private String cpu15unit;

}

+ 54
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/enums/ResourceTypeEnum.java View File

@@ -0,0 +1,54 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.enums;

/**
* @description
* @date 2021-11-17
*/
public enum ResourceTypeEnum {
GPU_TYPE(1, "gpu"),
CPU_TYPE(2, "cpu"),
MEMORY_TYPE(3, "memory");


private Integer code;

private String desc;

ResourceTypeEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}

public Integer getCode() {
return code;
}

public String getDesc() {
return desc;
}

@Override
public String toString() {
return "[" + this.code + "]" + this.desc;
}

public static boolean isGpuType(Integer code) {
return GPU_TYPE.code.equals(code);
}
}

+ 50
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/enums/StatTypeEnum.java View File

@@ -0,0 +1,50 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.enums;

/**
* @description 资源统计类型
* @date 2021-11-17
*/
public enum StatTypeEnum {
ALLOT_TYPE(1, "统计资源配额"),
USAGE_RATE_TYPE(2, "统计资源使用率峰值"),
USAGE_TYPE(3, "统计资源用量峰值");

private Integer code;

private String desc;

StatTypeEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}

public Integer getCode() {
return code;
}

public String getDesc() {
return desc;
}

@Override
public String toString() {
return "[" + this.code + "]" + this.desc;
}
}

+ 1
- 1
dubhe-server/admin/src/main/java/org/dubhe/admin/event/EmailEventListener.java View File

@@ -42,7 +42,7 @@ public class EmailEventListener {


@EventListener
@Async("taskExecutor")
@Async
public void onApplicationEvent(EmailEvent event) {
EmailDTO emailDTO = (EmailDTO) event.getSource();
sendMail(emailDTO.getReceiverMailAddress(), emailDTO.getSubject(), emailDTO.getCode());


+ 1
- 1
dubhe-server/admin/src/main/java/org/dubhe/admin/event/EmailEventPublisher.java View File

@@ -41,7 +41,7 @@ public class EmailEventPublisher {
*
* @param dto
*/
@Async("taskExecutor")
@Async
public void sentEmailEvent(final EmailDTO dto) {
try {
EmailEvent emailEvent = new EmailEvent(dto);


+ 89
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/rest/GpuResourceController.java View File

@@ -0,0 +1,89 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.rest;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.dubhe.admin.domain.dto.*;
import org.dubhe.admin.service.GpuResourceService;
import org.dubhe.biz.base.constant.Permissions;
import org.dubhe.biz.base.vo.DataResponseBody;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;

/**
* @description GPU资源管理
* @date 2021-08-20
*/
@Api(tags = "系统:GPU资源管理")
@RestController
@RequestMapping("/gpuResource")
public class GpuResourceController {

@Autowired
private GpuResourceService gpuResourceService;

@ApiOperation("查询GPU资源")
@GetMapping
public DataResponseBody getGpuResource(GpuResourceQueryDTO gpuResourceQueryDTO) {
return new DataResponseBody(gpuResourceService.getGpuResource(gpuResourceQueryDTO));
}

@ApiOperation("查询用户GPU类型")
@GetMapping("/getUserGpuType")
public DataResponseBody getUserGpuType() {
return new DataResponseBody(gpuResourceService.getUserGpuType());
}

@ApiOperation("根据用户GPU类型查询用户GPU资源")
@GetMapping("/getUserGpuModel")
public DataResponseBody getUserGpuResource(UserGpuResourceQueryDTO userGpuResourceQueryDTO) {
return new DataResponseBody(gpuResourceService.getUserGpuResource(userGpuResourceQueryDTO));
}

@ApiOperation("查询GPU类型")
@GetMapping("/getGpuType")
public DataResponseBody getGpuType() {
return new DataResponseBody(gpuResourceService.getGpuType());
}

@ApiOperation("新增GPU资源")
@PostMapping
@PreAuthorize(Permissions.GPU_CREATE)
public DataResponseBody create(@Valid @RequestBody GpuResourceCreateDTO gpuResourceCreateDTO) {
return new DataResponseBody(gpuResourceService.create(gpuResourceCreateDTO));
}

@ApiOperation("修改GPU资源")
@PutMapping
@PreAuthorize(Permissions.GPU_EDIT)
public DataResponseBody update(@Valid @RequestBody GpuResourceUpdateDTO gpuResourceUpdateDTO) {
return new DataResponseBody(gpuResourceService.update(gpuResourceUpdateDTO));
}

@ApiOperation("删除GPU资源")
@DeleteMapping
@PreAuthorize(Permissions.GPU_DELETE)
public DataResponseBody delete(@Valid @RequestBody GpuResourceDeleteDTO gpuResourceDeleteDTO) {
gpuResourceService.delete(gpuResourceDeleteDTO);
return new DataResponseBody();
}

}

+ 19
- 3
dubhe-server/admin/src/main/java/org/dubhe/admin/rest/ResourceSpecsController.java View File

@@ -25,10 +25,12 @@ import org.dubhe.admin.domain.dto.ResourceSpecsUpdateDTO;
import org.dubhe.admin.service.ResourceSpecsService;
import org.dubhe.biz.base.constant.Permissions;
import org.dubhe.biz.base.dto.QueryResourceSpecsDTO;
import org.dubhe.admin.domain.dto.QueryUserResourceSpecsDTO;
import org.dubhe.biz.base.vo.DataResponseBody;
import org.dubhe.biz.base.vo.QueryResourceSpecsVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
@@ -47,16 +49,30 @@ public class ResourceSpecsController {

@ApiOperation("查询资源规格")
@GetMapping
public DataResponseBody getResourceSpecs(ResourceSpecsQueryDTO resourceSpecsQueryDTO) {
public DataResponseBody getResourceSpecs(@Validated ResourceSpecsQueryDTO resourceSpecsQueryDTO) {
return new DataResponseBody(resourceSpecsService.getResourceSpecs(resourceSpecsQueryDTO));
}

@ApiOperation("查询资源规格(远程调用)")

@ApiOperation("查询资源规格(训练远程调用)")
@GetMapping("/queryResourceSpecs")
public DataResponseBody<QueryResourceSpecsVO> queryResourceSpecs(QueryResourceSpecsDTO queryResourceSpecsDTO) {
public DataResponseBody<QueryResourceSpecsVO> queryResourceSpecs(@Validated QueryResourceSpecsDTO queryResourceSpecsDTO) {
return new DataResponseBody(resourceSpecsService.queryResourceSpecs(queryResourceSpecsDTO));
}

@ApiOperation("查询用户资源规格")
@GetMapping("/queryUserResourceSpecs")
public DataResponseBody<QueryResourceSpecsVO> getUserResourceSpecs(@Validated QueryUserResourceSpecsDTO queryUserResourceSpecsDTO) {
return new DataResponseBody(resourceSpecsService.getUserResourceSpecs(queryUserResourceSpecsDTO));
}


@ApiOperation("查询资源规格(tadl远程调用)")
@GetMapping("/queryTadlResourceSpecs")
public DataResponseBody<QueryResourceSpecsVO> queryTadlResourceSpecs(Long id) {
return new DataResponseBody(resourceSpecsService.queryTadlResourceSpecs(id));
}

@ApiOperation("新增资源规格")
@PostMapping
@PreAuthorize(Permissions.SPECS_CREATE)


+ 0
- 1
dubhe-server/admin/src/main/java/org/dubhe/admin/rest/UserCenterController.java View File

@@ -78,7 +78,6 @@ public class UserCenterController {
List<RoleSmallDTO> roles = roleService.getRoleByUserId(curUserId);
List<MenuDTO> menuDtoList = menuService.findByRoles(roles);
List<MenuDTO> menuDtos = (List<MenuDTO>) menuService.buildTree(menuDtoList).get("result");

return new DataResponseBody(menuService.buildMenus(menuDtos));
}



+ 35
- 8
dubhe-server/admin/src/main/java/org/dubhe/admin/rest/UserController.java View File

@@ -19,7 +19,6 @@ package org.dubhe.admin.rest;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.dubhe.admin.domain.dto.UserConfigDTO;
import org.dubhe.admin.domain.dto.UserCreateDTO;
import org.dubhe.admin.domain.dto.UserDeleteDTO;
import org.dubhe.admin.domain.dto.UserQueryDTO;
@@ -27,12 +26,23 @@ import org.dubhe.admin.domain.dto.UserUpdateDTO;
import org.dubhe.admin.service.UserService;
import org.dubhe.biz.base.constant.Permissions;
import org.dubhe.biz.base.context.UserContext;
import org.dubhe.biz.base.dto.UserConfigSaveDTO;
import org.dubhe.biz.base.dto.UserDTO;
import org.dubhe.biz.base.vo.DataResponseBody;
import org.dubhe.biz.base.vo.UserConfigVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
@@ -81,22 +91,23 @@ public class UserController {
@ApiOperation("删除用户")
@DeleteMapping
@PreAuthorize(Permissions.USER_DELETE)
public DataResponseBody delete(@Valid @RequestBody UserDeleteDTO userDeleteDTO) {
userService.delete(userDeleteDTO.getIds());
public DataResponseBody delete(@Valid @RequestBody UserDeleteDTO userDeleteDTO, @RequestHeader("Authorization") String accessToken) {
userService.delete(userDeleteDTO.getIds(), accessToken);
return new DataResponseBody();
}

@ApiOperation("根据用户ID查询用户配置")
@GetMapping(value = "/getUserConfig")
public DataResponseBody getUserConfig(@RequestParam(value = "userId") Long userId) {
public DataResponseBody<UserConfigVO> getUserConfig(@RequestParam(value = "userId") Long userId) {
return new DataResponseBody(userService.findUserConfig(userId));
}

@ApiOperation("新增或修改用户配置")
@PutMapping(value = "/setUserConfig")
@PreAuthorize(Permissions.USER_CONFIG_EDIT)
public DataResponseBody setUserConfig(@Validated @RequestBody UserConfigDTO userConfigDTO) {
return new DataResponseBody(userService.createOrUpdateUserConfig(userConfigDTO));
public DataResponseBody setUserConfig(@Validated @RequestBody UserConfigSaveDTO userConfigSaveDTO) {
userService.saveUserConfig(userConfigSaveDTO, null);
return new DataResponseBody();
}

/**
@@ -121,7 +132,7 @@ public class UserController {

@ApiOperation("根据用户昵称搜索用户列表")
@GetMapping(value = "/findByNickName")
public DataResponseBody<List<UserDTO>> findByNickName(@RequestParam(value = "nickName",required = false) String nickName) {
public DataResponseBody<List<UserDTO>> findByNickName(@RequestParam(value = "nickName", required = false) String nickName) {
return new DataResponseBody(userService.findByNickName(nickName));
}

@@ -130,4 +141,20 @@ public class UserController {
public DataResponseBody<List<UserDTO>> getUserList(@RequestParam(value = "ids") List<Long> ids) {
return new DataResponseBody(userService.getUserList(ids));
}

@ApiOperation("重置密码")
@PostMapping(value = "/resetPassword/{userId}")
@PreAuthorize(Permissions.USER_RESET_PASSWORD)
public DataResponseBody resetPassword(@PathVariable Long userId) {
return userService.resetPassword(userId);
}


@ApiOperation("获取用户资源配额总量")
@GetMapping("/userAllot")
@PreAuthorize(Permissions.SYSTEM_NODE)
public DataResponseBody getUserAllotTotal() {
return userService.getAllotResources();
}
}

+ 22
- 2
dubhe-server/admin/src/main/java/org/dubhe/admin/rest/UserGroupController.java View File

@@ -18,6 +18,7 @@ package org.dubhe.admin.rest;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.dubhe.admin.domain.dto.UserGroupConfigSaveDTO;
import org.dubhe.admin.domain.dto.UserGroupDTO;
import org.dubhe.admin.domain.dto.UserGroupDeleteDTO;
import org.dubhe.admin.domain.dto.UserGroupQueryDTO;
@@ -32,9 +33,11 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@@ -118,8 +121,8 @@ public class UserGroupController {
@DeleteMapping("/delete")
@ApiOperation("批量删除组用户")
@PreAuthorize(Permissions.USER_GROUP_DELETE_USER)
public DataResponseBody delUser(@Validated @RequestBody UserGroupUpdDTO userGroupUpdDTO) {
userGroupService.delUser(userGroupUpdDTO);
public DataResponseBody delUser(@Validated @RequestBody UserGroupUpdDTO userGroupUpdDTO, @RequestHeader("Authorization") String accessToken) {
userGroupService.delUser(userGroupUpdDTO, accessToken);
return new DataResponseBody();
}

@@ -130,4 +133,21 @@ public class UserGroupController {
userGroupService.updateUserRole(userRoleUpdateDTO);
return new DataResponseBody();
}

@PutMapping("/resetPassword/{groupId}")
@ApiOperation("批量重置组成员密码")
@PreAuthorize(Permissions.USER_GROUP_RESET_USER_PASSWORD)
public DataResponseBody resetUserPassword(@PathVariable Long groupId) {
userGroupService.resetUserPassword(groupId);
return new DataResponseBody();
}

@ApiOperation("批量新增或修改组成员配置")
@PutMapping(value = "/setUserConfig")
@PreAuthorize(Permissions.USER_GROUP_CONFIG_EDIT)
public DataResponseBody setUserConfig(@Validated @RequestBody UserGroupConfigSaveDTO userGroupConfigSaveDTO) {
userGroupService.saveUserConfig(userGroupConfigSaveDTO);
return new DataResponseBody();
}

}

+ 58
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/rest/UserResourceController.java View File

@@ -0,0 +1,58 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.rest;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.dubhe.admin.domain.dto.UserResourceListDTO;
import org.dubhe.admin.domain.dto.UserResourceQueryDTO;
import org.dubhe.admin.service.UserResourceService;
import org.dubhe.biz.base.vo.DataResponseBody;
import org.dubhe.biz.base.vo.UserAllotVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
* @description 用户资源控制层
* @date 2021-11-23
*/
@Api(tags = "控制台:用户统计")
@RestController
@RequestMapping("/resource")
public class UserResourceController {

@Autowired
private UserResourceService userResourceService;


@ApiOperation("用户Top统计")
@GetMapping("/total")
public DataResponseBody<List<UserAllotVO>> getUserResourceTotal(@Validated UserResourceQueryDTO resourceQueryDTO) {
return new DataResponseBody(userResourceService.getResourceTotal(resourceQueryDTO));
}

@ApiOperation("用户资源统计列表")
@GetMapping("/list")
public DataResponseBody getUserResourceList(UserResourceListDTO UserResourceListDTO) {
return new DataResponseBody(userResourceService.getResourceList(UserResourceListDTO));
}
}

+ 77
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/service/GpuResourceService.java View File

@@ -0,0 +1,77 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.service;

import org.dubhe.admin.domain.dto.*;
import org.dubhe.admin.domain.entity.GpuResource;
import org.dubhe.admin.domain.vo.GpuResourceQueryVO;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* @description GPU资源管理
* @date 2021-08-20
*/
public interface GpuResourceService {

/**
* 查询GPU资源
* @param gpuResourceQueryDTO 查询GPU资源请求实体
* @return List<GpuResource> gpuResourceSpecs GPU资源列表
*/
Map<String, Object> getGpuResource(GpuResourceQueryDTO gpuResourceQueryDTO);

/**
* 新增GPU资源
* @param gpuResourceCreateDTO 新增GPU资源实体
* @return List<Long> 新增GPU资源id
*/
List<Long> create(GpuResourceCreateDTO gpuResourceCreateDTO);

/**
* 修改GPU资源
* @param gpuResourceUpdateDTO 修改GPU资源实体
* @return List<Long> 修改GPU资源id
*/
List<Long> update(GpuResourceUpdateDTO gpuResourceUpdateDTO);

/**
* GPU资源删除
* @param gpuResourceDeleteDTO GPU资源删除id集合
*/
void delete(GpuResourceDeleteDTO gpuResourceDeleteDTO);

/**
* 查询GPU类型
* @return List<string> GPU类型列表
*/
List<String> getGpuType();

/**
* 查询用户GPU类型
* @return Set<string> GPU类型列表
*/
Set<String> getUserGpuType();

/**
* 根据用户GPU类型查询用户GPU资源
* @return List<GpuResource> 用户GPU资源列表
*/
List<GpuResource> getUserGpuResource(UserGpuResourceQueryDTO userGpuResourceQueryDTO);
}

+ 21
- 2
dubhe-server/admin/src/main/java/org/dubhe/admin/service/ResourceSpecsService.java View File

@@ -16,9 +16,14 @@
*/
package org.dubhe.admin.service;

import org.dubhe.admin.domain.dto.*;
import org.dubhe.biz.base.vo.QueryResourceSpecsVO;
import org.dubhe.admin.domain.dto.ResourceSpecsCreateDTO;
import org.dubhe.admin.domain.dto.ResourceSpecsDeleteDTO;
import org.dubhe.admin.domain.dto.ResourceSpecsQueryDTO;
import org.dubhe.admin.domain.dto.ResourceSpecsUpdateDTO;
import org.dubhe.biz.base.vo.QueryUserResourceSpecsVO;
import org.dubhe.biz.base.dto.QueryResourceSpecsDTO;
import org.dubhe.admin.domain.dto.QueryUserResourceSpecsDTO;
import org.dubhe.biz.base.vo.QueryResourceSpecsVO;

import java.util.List;
import java.util.Map;
@@ -62,4 +67,18 @@ public interface ResourceSpecsService {
* @return QueryResourceSpecsVO 资源规格返回结果实体类
*/
QueryResourceSpecsVO queryResourceSpecs(QueryResourceSpecsDTO queryResourceSpecsDTO);

/**
* 查询用户资源规格
* @param queryUserResourceSpecsDTO 查询用户资源规格请求实体
* @return List<QueryUserResourceSpecsVO> 用户资源规格返回结果实体类集合
*/
List<QueryUserResourceSpecsVO> getUserResourceSpecs(QueryUserResourceSpecsDTO queryUserResourceSpecsDTO);

/**
* 查询资源规格
* @param id 资源规格id
* @return QueryResourceSpecsVO 资源规格返回结果实体类
*/
QueryResourceSpecsVO queryTadlResourceSpecs(Long id);
}

+ 16
- 1
dubhe-server/admin/src/main/java/org/dubhe/admin/service/UserGroupService.java View File

@@ -101,7 +101,7 @@ public interface UserGroupService {
*
* @param userGroupUpdDTO 批量删除用户组用户DTO
*/
void delUser(UserGroupUpdDTO userGroupUpdDTO);
void delUser(UserGroupUpdDTO userGroupUpdDTO, String accessToken);

/**
* 批量修改用户组用户的角色
@@ -109,4 +109,19 @@ public interface UserGroupService {
* @param userRoleUpdateDTO
*/
void updateUserRole(UserRoleUpdateDTO userRoleUpdateDTO);


/**
* 批量重置用户组用户的密码
*
* @param groupId
*/
void resetUserPassword(Long groupId);

/**
* 批量修改用户组用户的设置
*
* @param userGroupConfigSaveDTO
*/
void saveUserConfig(UserGroupConfigSaveDTO userGroupConfigSaveDTO);
}

+ 48
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/service/UserResourceService.java View File

@@ -0,0 +1,48 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.service;

import org.dubhe.admin.domain.dto.UserResourceListDTO;
import org.dubhe.admin.domain.dto.UserResourceQueryDTO;
import org.dubhe.admin.domain.vo.UserResourceResVO;
import org.dubhe.biz.base.vo.UserAllotVO;

import java.util.List;
import java.util.Map;

/**
* @description 用户资源统计接口层
* @date 2021-11-23
*/
public interface UserResourceService {

/**
* 用户资源统计
*
* @param resourceQueryDTO 查询DTO实体
* @return List<UserAllotVO> 用户资源Top数据
*/
List<UserAllotVO> getResourceTotal(UserResourceQueryDTO resourceQueryDTO);

/**
* 用户资源统计列表
*
* @return List<UserResourceResVO> 用户资源列表VO实体
*/
Map<String, Object> getResourceList(UserResourceListDTO resourceListDTO);

}

+ 28
- 7
dubhe-server/admin/src/main/java/org/dubhe/admin/service/UserService.java View File

@@ -18,13 +18,21 @@ package org.dubhe.admin.service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import org.dubhe.admin.domain.dto.*;
import org.dubhe.admin.domain.dto.AuthUserDTO;
import org.dubhe.admin.domain.dto.UserCenterUpdateDTO;
import org.dubhe.admin.domain.dto.UserCreateDTO;
import org.dubhe.admin.domain.dto.UserEmailUpdateDTO;
import org.dubhe.admin.domain.dto.UserQueryDTO;
import org.dubhe.admin.domain.dto.UserRegisterDTO;
import org.dubhe.admin.domain.dto.UserRegisterMailDTO;
import org.dubhe.admin.domain.dto.UserResetPasswordDTO;
import org.dubhe.admin.domain.dto.UserUpdateDTO;
import org.dubhe.admin.domain.entity.User;
import org.dubhe.admin.domain.vo.UserConfigCreateVO;
import org.dubhe.admin.domain.vo.UserConfigVO;
import org.dubhe.biz.base.dto.TeamDTO;
import org.dubhe.biz.base.dto.UserConfigSaveDTO;
import org.dubhe.biz.base.dto.UserDTO;
import org.dubhe.biz.base.vo.DataResponseBody;
import org.dubhe.biz.base.vo.UserConfigVO;
import org.dubhe.cloud.authconfig.service.AdminUserService;

import javax.servlet.http.HttpServletResponse;
@@ -69,7 +77,7 @@ public interface UserService extends AdminUserService, IService<User> {
*
* @param ids 用户ID列表
*/
void delete(Set<Long> ids);
void delete(Set<Long> ids, String accessToken);

/**
* 根据用户名称获取用户信息
@@ -235,8 +243,21 @@ public interface UserService extends AdminUserService, IService<User> {
/**
* 创建或更新用户配置
*
* @param userConfigDTO 用户配置
* @return org.dubhe.admin.domain.vo.UserConfigCreateVO 用户配置 VO
* @param userConfigSaveDTO 用户配置
*/
UserConfigCreateVO createOrUpdateUserConfig(UserConfigDTO userConfigDTO);
void saveUserConfig(UserConfigSaveDTO userConfigSaveDTO, String token);

/**
* 重置密码
*
* @return 重置密码结果集
*/
DataResponseBody resetPassword(Long userId);

/**
* 获取用户分配的资源总量
*
* @return 资源配额总量统计
*/
DataResponseBody getAllotResources();
}

+ 2
- 2
dubhe-server/admin/src/main/java/org/dubhe/admin/service/impl/AuthCodeServiceImpl.java View File

@@ -79,8 +79,8 @@ public class AuthCodeServiceImpl extends ServiceImpl<AuthCodeMapper, Auth> imple
Page page = authCodeQueryDTO.toPage();
QueryWrapper<Auth> queryWrapper = new QueryWrapper<>();

if (StringUtils.isNotEmpty(authCodeQueryDTO.getAuthCode())) {
queryWrapper.and(x -> x.eq("id", authCodeQueryDTO.getAuthCode()).or().like("authCOde", authCodeQueryDTO.getAuthCode()));
if (StringUtils.isNotEmpty(authCodeQueryDTO.getKeyword())) {
queryWrapper.and(x -> x.eq("id", authCodeQueryDTO.getKeyword()).or().like("authCOde", authCodeQueryDTO.getKeyword()));
}

//排序


+ 223
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/service/impl/GpuResourceServiceImpl.java View File

@@ -0,0 +1,223 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.collections4.CollectionUtils;
import org.dubhe.admin.dao.GpuResourceMapper;
import org.dubhe.admin.domain.dto.*;
import org.dubhe.admin.domain.entity.GpuResource;
import org.dubhe.admin.domain.vo.GpuResourceQueryVO;
import org.dubhe.admin.service.GpuResourceService;
import org.dubhe.admin.service.UserService;
import org.dubhe.biz.base.constant.StringConstant;
import org.dubhe.biz.base.context.UserContext;
import org.dubhe.biz.base.exception.BusinessException;
import org.dubhe.biz.base.service.UserContextService;
import org.dubhe.biz.base.utils.StringUtils;
import org.dubhe.biz.base.vo.UserConfigVO;
import org.dubhe.biz.base.vo.UserGpuConfigVO;
import org.dubhe.biz.db.utils.PageUtil;
import org.dubhe.biz.log.enums.LogEnum;
import org.dubhe.biz.log.utils.LogUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
* @description GPU资源管理
* @date 2021-08-20
*/
@Service
public class GpuResourceServiceImpl implements GpuResourceService {

@Autowired
private GpuResourceMapper gpuResourceMapper;

@Autowired
private UserContextService userContextService;

@Autowired
private UserService userService;

/**
* 查询GPU资源
* @param gpuResourceQueryDTO 查询GPU资源请求实体
* @return List<GpuResource> gpuResourceSpecs GPU资源列表
*/
@Override
public Map<String, Object> getGpuResource(GpuResourceQueryDTO gpuResourceQueryDTO) {
Page page = gpuResourceQueryDTO.toPage();
//排序字段
String sort = null == gpuResourceQueryDTO.getSort() ? StringConstant.ID : gpuResourceQueryDTO.getSort();
QueryWrapper<GpuResource> queryResourceWrapper = new QueryWrapper<>();
queryResourceWrapper.eq(gpuResourceQueryDTO.getGpuType() != null, "gpu_type", gpuResourceQueryDTO.getGpuType());
if (StringConstant.SORT_ASC.equals(gpuResourceQueryDTO.getOrder())) {
queryResourceWrapper.orderByAsc(StringUtils.humpToLine(sort));
} else {
queryResourceWrapper.orderByDesc(StringUtils.humpToLine(sort));
}
Page<GpuResource> pageGpuResourceResult = gpuResourceMapper.selectPage(page, queryResourceWrapper);
//结果集处理
//查询结果数
page.setTotal(pageGpuResourceResult.getTotal());
List<GpuResource> gpuResource = pageGpuResourceResult.getRecords();
List<GpuResourceQueryVO> gpuResourceQueryVOS = new ArrayList<>();
if (CollectionUtils.isNotEmpty(gpuResource)) {
gpuResourceQueryVOS = gpuResource.stream().map(x -> {
GpuResourceQueryVO gpuResourceQueryVO = new GpuResourceQueryVO();
BeanUtils.copyProperties(x, gpuResourceQueryVO);
return gpuResourceQueryVO;
}).collect(Collectors.toList());
}
return PageUtil.toPage(page, gpuResourceQueryVOS);
}

/**
* 新增GPU资源
* @param gpuResourceCreateDTO 新增GPU资源实体
* @return List<Long> 新增GPU资源id
*/
@Override
@Transactional(rollbackFor = Exception.class)
public List<Long> create(GpuResourceCreateDTO gpuResourceCreateDTO) {
UserContext curUser = userContextService.getCurUser();
//GPU资源校验
QueryWrapper<GpuResource> resourceWrapper = new QueryWrapper<>();
resourceWrapper.eq("gpu_type", gpuResourceCreateDTO.getGpuType())
.eq("gpu_model", gpuResourceCreateDTO.getGpuModel());
if (gpuResourceMapper.selectCount(resourceWrapper) > 0) {
throw new BusinessException("GPU资源已存在");
}
GpuResource gpuResource = new GpuResource();
BeanUtils.copyProperties(gpuResourceCreateDTO, gpuResource);
try {
gpuResourceMapper.insert(gpuResource);
} catch (Exception e) {
LogUtil.error(LogEnum.SYS_ERR, "The user: {} saved the GpuResource parameters GpuResourceCreateDTO: {} was not successful. Failure reason: {}", curUser.getUsername(), gpuResourceCreateDTO, e);
throw new BusinessException("内部错误");
}
return Collections.singletonList(gpuResource.getId());
}

/**
* 修改GPU资源
* @param gpuResourceUpdateDTO 修改GPU资源实体
* @return List<Long> 修改GPU资源id
*/
@Override
@Transactional(rollbackFor = Exception.class)
public List<Long> update(GpuResourceUpdateDTO gpuResourceUpdateDTO) {
UserContext curUser = userContextService.getCurUser();
GpuResource gpuResource = new GpuResource();
gpuResource.setId(gpuResourceUpdateDTO.getId());
//规格名称校验
QueryWrapper<GpuResource> resourceWrapper = new QueryWrapper<>();
resourceWrapper.eq("gpu_type", gpuResourceUpdateDTO.getGpuType())
.eq("gpu_model", gpuResourceUpdateDTO.getGpuModel()).ne("id", gpuResourceUpdateDTO.getId());
if (gpuResourceMapper.selectCount(resourceWrapper) > 0) {
throw new BusinessException("GPU资源已存在");
}
gpuResource.setGpuType(gpuResourceUpdateDTO.getGpuType()).setGpuModel(gpuResourceUpdateDTO.getGpuModel()).setK8sLabelKey(gpuResourceUpdateDTO.getK8sLabelKey());
try {
gpuResourceMapper.updateById(gpuResource);
} catch (Exception e) {
LogUtil.error(LogEnum.SYS_ERR, "The user: {} updated the GpuResource parameters gpuResourceUpdateDTO: {} was not successful. Failure reason :{}", curUser.getUsername(), gpuResourceUpdateDTO, e);
throw new BusinessException("内部错误");
}
return Collections.singletonList(gpuResource.getId());
}

/**
* GPU资源删除
* @param gpuResourceDeleteDTO GPU资源删除id集合
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void delete(GpuResourceDeleteDTO gpuResourceDeleteDTO) {
UserContext curUser = userContextService.getCurUser();
Set<Long> idList = gpuResourceDeleteDTO.getIds();
try {
gpuResourceMapper.deleteBatchIds(idList);
} catch (Exception e) {
LogUtil.error(LogEnum.SYS_ERR, "The user: {} Deleted the ResourceSpecs parameters resourceSpecsDeleteDTO: {} was not successful. Failure reason :{}", curUser.getUsername(), gpuResourceDeleteDTO, e);
throw new BusinessException("内部错误");
}
}

/**
* 查询GPU类型
* @return List<string> GPU类型列表
*/
@Override
public List<String> getGpuType() {
//查询GPU类型
QueryWrapper<GpuResource> queryGpuModelWrapper = new QueryWrapper<>();
queryGpuModelWrapper.orderByDesc("id");
List<GpuResource> gpuResources = gpuResourceMapper.selectList(queryGpuModelWrapper);
List<String> gpuTypes = new ArrayList<>();
if (CollectionUtils.isNotEmpty(gpuResources)) {
gpuTypes = gpuResources.stream().map(GpuResource::getGpuType).distinct().collect(Collectors.toList());
}
return gpuTypes;
}

/**
* 查询用户GPU类型
* @return List<string> GPU类型列表
*/
@Override
public Set<String> getUserGpuType() {
UserContext curUser = userContextService.getCurUser();
UserConfigVO userConfig = userService.findUserConfig(curUser.getId());
Set<String> userGpuTypes = new HashSet<>();
if (CollectionUtils.isNotEmpty(userConfig.getGpuResources())) {
for (UserGpuConfigVO userGpuConfig : userConfig.getGpuResources()) {
if (userGpuConfig.getGpuLimit() > 0) {
userGpuTypes.add(userGpuConfig.getGpuType());
}
}
}
return userGpuTypes;
}

/**
* 根据用户GPU类型查询用户GPU资源
* @return List<GpuResource> 用户GPU资源列表
*/
@Override
public List<GpuResource> getUserGpuResource(UserGpuResourceQueryDTO userGpuResourceQueryDTO) {
UserContext curUser = userContextService.getCurUser();
UserConfigVO userConfig = userService.findUserConfig(curUser.getId());
Set<String> userGpuModels = new HashSet<>();
if (CollectionUtils.isNotEmpty(userConfig.getGpuResources())) {
for (UserGpuConfigVO userGpuConfig : userConfig.getGpuResources()) {
if (userGpuConfig.getGpuLimit() > 0 && userGpuResourceQueryDTO.getGpuType().equals(userGpuConfig.getGpuType())) {
userGpuModels.add(userGpuConfig.getGpuModel());
}
}
}
QueryWrapper<GpuResource> queryGpuModelWrapper = new QueryWrapper<>();
queryGpuModelWrapper.orderByDesc("id").eq("gpu_type", userGpuResourceQueryDTO.getGpuType()).in("gpu_model", userGpuModels);
return gpuResourceMapper.selectList(queryGpuModelWrapper);
}
}

+ 25
- 13
dubhe-server/admin/src/main/java/org/dubhe/admin/service/impl/MenuServiceImpl.java View File

@@ -15,7 +15,6 @@
*/
package org.dubhe.admin.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -27,7 +26,6 @@ import org.dubhe.admin.domain.dto.MenuQueryDTO;
import org.dubhe.admin.domain.dto.MenuUpdateDTO;
import org.dubhe.admin.domain.dto.RoleSmallDTO;
import org.dubhe.admin.domain.entity.Menu;
import org.dubhe.admin.domain.vo.MenuMetaVo;
import org.dubhe.admin.domain.vo.MenuVo;
import org.dubhe.admin.enums.MenuTypeEnum;
import org.dubhe.admin.service.MenuService;
@@ -44,6 +42,7 @@ import org.dubhe.biz.log.utils.LogUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@@ -150,13 +149,13 @@ public class MenuServiceImpl implements MenuService {
.sort(resources.getSort())
.type(resources.getType())
.build();
if(MenuTypeEnum.PAGE_TYPE.getValue().equals(resources.getType())){
if (MenuTypeEnum.PAGE_TYPE.getValue().equals(resources.getType()) || MenuTypeEnum.DIR_TYPE.getValue().equals(resources.getType())) {
menu.setBackTo(resources.getBackTo());
menu.setExtConfig(resources.getExtConfig());
}
menuMapper.insert(menu);
//管理员新增默认权限
roleService.tiedRoleMenu(PermissionConstant.ADMIN_ROLE_ID,menu.getId());
roleService.tiedRoleMenu(PermissionConstant.ADMIN_ROLE_ID, menu.getId());

return menuConvert.toDto(menu);
}
@@ -202,9 +201,9 @@ public class MenuServiceImpl implements MenuService {
menu.setHidden(resources.getHidden());
menu.setComponentName(resources.getComponentName());
menu.setPermission(resources.getPermission());
if(MenuTypeEnum.PAGE_TYPE.getValue().equals(resources.getType())){
if (MenuTypeEnum.PAGE_TYPE.getValue().equals(resources.getType()) || MenuTypeEnum.DIR_TYPE.getValue().equals(resources.getType())) {
ExtConfigDTO extConfigDTO = analyzeBackToValue(resources.getExtConfig());
menu.setBackTo(Objects.isNull(extConfigDTO)?null:extConfigDTO.getBackTo());
menu.setBackTo(Objects.isNull(extConfigDTO) ? null : extConfigDTO.getBackTo());
menu.setExtConfig(resources.getExtConfig());
}
menuMapper.updateById(menu);
@@ -215,16 +214,16 @@ public class MenuServiceImpl implements MenuService {
* 解析扩展配置中 backTO 属性值
*
* @param extConfig 扩展配置
* @return ExtConfigDTO扩展配置
* @return ExtConfigDTO扩展配置
*/
private ExtConfigDTO analyzeBackToValue(String extConfig){
private ExtConfigDTO analyzeBackToValue(String extConfig) {
ExtConfigDTO dto = ExtConfigDTO.builder().build();
try {
if(!Objects.isNull(extConfig)){
if (!Objects.isNull(extConfig)) {
dto = JSONObject.parseObject(extConfig, ExtConfigDTO.class);
}
}catch (Exception e){
LogUtil.error(LogEnum.SYS_ERR,"analyzeBackToValue error, params:{} , error:{}",JSONObject.toJSONString(extConfig),e);
} catch (Exception e) {
LogUtil.error(LogEnum.SYS_ERR, "analyzeBackToValue error, params:{} , error:{}", JSONObject.toJSONString(extConfig), e);
}
return dto;
}
@@ -358,7 +357,7 @@ public class MenuServiceImpl implements MenuService {
if (menuDTO != null) {
List<MenuDTO> menuDtoList = menuDTO.getChildren();
MenuVo menuVo = new MenuVo();
menuVo.setName(ObjectUtil.isNotEmpty(menuDTO.getComponentName()) ? menuDTO.getComponentName() : menuDTO.getName());
menuVo.setName(menuDTO.getComponentName());
// 一级目录需要加斜杠,不然会报警告
menuVo.setPath(menuDTO.getPid() == 0 ? "/" + menuDTO.getPath() : menuDTO.getPath());
menuVo.setHidden(menuDTO.getHidden());
@@ -370,7 +369,20 @@ public class MenuServiceImpl implements MenuService {
menuVo.setComponent(menuDTO.getComponent());
}
}
menuVo.setMeta(new MenuMetaVo(menuDTO.getName(), menuDTO.getIcon(), menuDTO.getLayout(), !menuDTO.getCache()));
Map<String, Object> metaMap = new HashMap<>();
metaMap.put("title", menuDTO.getName());
metaMap.put("icon", menuDTO.getIcon());
metaMap.put("layout", menuDTO.getLayout());
metaMap.put("noCache", !menuDTO.getCache());
if (menuDTO.getExtConfig() != null) {
Map json = (Map) JSONObject.parse(menuDTO.getExtConfig());
if(!CollectionUtils.isEmpty(json)){
for (Object key : json.keySet()){
metaMap.put(key.toString(),json.get(key));
}
}
}
menuVo.setMeta(metaMap);
if (menuDtoList != null && menuDtoList.size() != 0) {
menuVo.setChildren(buildMenus(menuDtoList));
// 处理是一级菜单并且没有子菜单的情况


+ 1
- 1
dubhe-server/admin/src/main/java/org/dubhe/admin/service/impl/PermissionServiceImpl.java View File

@@ -134,7 +134,7 @@ public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permiss

Map<String, Object> map = new HashMap<>(2);
if (trees.size() == 0) {
permissions.stream().filter(x -> !ids.contains(x.getId())).collect(Collectors.toList());
trees = permissions.stream().filter(x -> !ids.contains(x.getId())).collect(Collectors.toList());
}

Map<String, Object> page = new HashMap<>(3);


+ 2
- 2
dubhe-server/admin/src/main/java/org/dubhe/admin/service/impl/RecycleTaskServiceImpl.java View File

@@ -329,7 +329,7 @@ public class RecycleTaskServiceImpl implements RecycleTaskService {
}
String emptyDir = recycleFileTmpPath + randomPath + File.separator;
LogUtil.debug(LogEnum.GARBAGE_RECYCLE, "recycle task sourcePath:{},emptyDir:{}", sourcePath, emptyDir);
Process process = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", String.format(ShellFileStoreApiImpl.DEL_COMMAND, userName, ip, emptyDir, emptyDir, sourcePath, emptyDir, sourcePath)});
Process process = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", String.format(ShellFileStoreApiImpl.DEL_COMMAND, emptyDir, emptyDir, sourcePath, emptyDir, sourcePath)});
return processRecycle(process);
} else {
LogUtil.error(LogEnum.GARBAGE_RECYCLE, "file recycle is failed! sourcePath:{}", sourcePath);
@@ -460,7 +460,7 @@ public class RecycleTaskServiceImpl implements RecycleTaskService {
String delRealPath = fileStoreApi.formatPath(sourcePath + File.separator + fileName + File.separator + directoryName);
delRealPath = delRealPath.endsWith(File.separator) ? delRealPath : delRealPath + File.separator;
String emptyDir = invalidFileTmpPath + directoryName + File.separator;
Process process = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", String.format(ShellFileStoreApiImpl.DEL_COMMAND, userName, ip, emptyDir, emptyDir, delRealPath, emptyDir, delRealPath)});
Process process = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", String.format(ShellFileStoreApiImpl.DEL_COMMAND, emptyDir, emptyDir, delRealPath, emptyDir, delRealPath)});
Integer deleteStatus = process.waitFor();
LogUtil.info(LogEnum.GARBAGE_RECYCLE, "recycle resources path:{},recycle status:{}", delRealPath, deleteStatus);
} catch (Exception e) {


+ 122
- 4
dubhe-server/admin/src/main/java/org/dubhe/admin/service/impl/ResourceSpecsServiceImpl.java View File

@@ -19,21 +19,27 @@ package org.dubhe.admin.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.collections4.CollectionUtils;
import org.dubhe.admin.client.SystemNodeClient;
import org.dubhe.admin.dao.ResourceSpecsMapper;
import org.dubhe.admin.domain.dto.ResourceSpecsCreateDTO;
import org.dubhe.admin.domain.dto.ResourceSpecsDeleteDTO;
import org.dubhe.admin.domain.dto.ResourceSpecsQueryDTO;
import org.dubhe.admin.domain.dto.ResourceSpecsUpdateDTO;
import org.dubhe.admin.dao.UserGpuConfigMapper;
import org.dubhe.admin.domain.dto.*;
import org.dubhe.admin.domain.entity.ResourceSpecs;
import org.dubhe.admin.domain.entity.UserGpuConfig;
import org.dubhe.admin.domain.vo.ResourceSpecsQueryVO;
import org.dubhe.admin.service.ResourceSpecsService;
import org.dubhe.admin.service.UserService;
import org.dubhe.biz.base.constant.MagicNumConstant;
import org.dubhe.biz.base.constant.StringConstant;
import org.dubhe.biz.base.context.UserContext;
import org.dubhe.biz.base.dto.QueryResourceSpecsDTO;
import org.dubhe.biz.base.dto.QueryUserK8sResourceDTO;
import org.dubhe.biz.base.exception.BusinessException;
import org.dubhe.biz.base.service.UserContextService;
import org.dubhe.biz.base.utils.StringUtils;
import org.dubhe.biz.base.vo.DataResponseBody;
import org.dubhe.biz.base.vo.QueryResourceSpecsVO;
import org.dubhe.biz.base.vo.QueryUserResourceSpecsVO;
import org.dubhe.biz.base.vo.UserConfigVO;
import org.dubhe.biz.db.utils.PageUtil;
import org.dubhe.biz.log.enums.LogEnum;
import org.dubhe.biz.log.utils.LogUtil;
@@ -58,6 +64,15 @@ public class ResourceSpecsServiceImpl implements ResourceSpecsService {
@Autowired
private UserContextService userContextService;

@Autowired
private UserService userService;

@Autowired
private SystemNodeClient systemNodeClient;

@Autowired
private UserGpuConfigMapper userGpuConfigMapper;

/**
* 查询资源规格
* @param resourceSpecsQueryDTO 查询资源规格请求实体
@@ -72,6 +87,13 @@ public class ResourceSpecsServiceImpl implements ResourceSpecsService {
queryResourceSpecsWrapper.like(resourceSpecsQueryDTO.getSpecsName() != null, "specs_name", resourceSpecsQueryDTO.getSpecsName())
.eq(resourceSpecsQueryDTO.getResourcesPoolType() != null, "resources_pool_type", resourceSpecsQueryDTO.getResourcesPoolType())
.eq(resourceSpecsQueryDTO.getModule() != null, "module", resourceSpecsQueryDTO.getModule());
if (resourceSpecsQueryDTO.getMultiGpu() != null) {
if (resourceSpecsQueryDTO.getMultiGpu()) {
queryResourceSpecsWrapper.gt("gpu_num", MagicNumConstant.ONE);
} else {
queryResourceSpecsWrapper.eq("gpu_num", MagicNumConstant.ONE);
}
}
if (StringConstant.SORT_ASC.equals(resourceSpecsQueryDTO.getOrder())) {
queryResourceSpecsWrapper.orderByAsc(StringUtils.humpToLine(sort));
} else {
@@ -206,4 +228,100 @@ public class ResourceSpecsServiceImpl implements ResourceSpecsService {
BeanUtils.copyProperties(resourceSpecs, queryResourceSpecsVO);
return queryResourceSpecsVO;
}


/**
* 查询用户资源规格
* @param queryUserResourceSpecsDTO 查询用户资源规格请求实体
* @return List<QueryUserResourceSpecsVO> 用户资源规格返回结果实体类集合
*/
@Override
public List<QueryUserResourceSpecsVO> getUserResourceSpecs(QueryUserResourceSpecsDTO queryUserResourceSpecsDTO) {
Long userId;
if (queryUserResourceSpecsDTO.getUserId() == null) {
userId = userContextService.getCurUser().getId();
} else {
userId = queryUserResourceSpecsDTO.getUserId();
}
UserConfigVO userConfig = userService.findUserConfig(userId);
if (queryUserResourceSpecsDTO.getResourcesPoolNode() == null) {
queryUserResourceSpecsDTO.setResourcesPoolNode(MagicNumConstant.ONE);
}
QueryWrapper<ResourceSpecs> queryResourceSpecsWrapper = new QueryWrapper<>();
queryResourceSpecsWrapper.eq("module", queryUserResourceSpecsDTO.getModule()).eq("resources_pool_type", queryUserResourceSpecsDTO.getResourcesPoolType())
.le("cpu_num", userConfig.getCpuLimit()).le("mem_num", userConfig.getMemoryLimit() * MagicNumConstant.ONE_THOUSAND_TWENTY_FOUR);
if (queryUserResourceSpecsDTO.getResourcesPoolType()) {
if (queryUserResourceSpecsDTO.getGpuModel() == null || queryUserResourceSpecsDTO.getK8sLabelKey() == null) {
throw new BusinessException("传参错误");
}
UserGpuConfig userGpuConfig = userGpuConfigMapper.selectOne(new QueryWrapper<>(new UserGpuConfig().setUserId(userId).setGpuModel(queryUserResourceSpecsDTO.getGpuModel())
.setK8sLabelKey(queryUserResourceSpecsDTO.getK8sLabelKey())).last(" limit 1 "));
Integer gpuLimit = null;
if (userGpuConfig != null) {
gpuLimit = userGpuConfig.getGpuLimit();
}
// 如果老用户未初始化GPU配置,则设置默认配置
if (userGpuConfig == null && userGpuConfigMapper.selectCountByUserId(userId) == 0) {
UserGpuConfig preUserGpuConfig = userGpuConfigMapper.selectOne(new QueryWrapper<>(new UserGpuConfig().setUserId(0L).setGpuModel(queryUserResourceSpecsDTO.getGpuModel()).setK8sLabelKey(queryUserResourceSpecsDTO.getK8sLabelKey())));
if (preUserGpuConfig != null) {
gpuLimit = preUserGpuConfig.getGpuLimit();
}
}
if (gpuLimit != null) {
queryResourceSpecsWrapper.le("gpu_num", gpuLimit);
}
}

if (queryUserResourceSpecsDTO.getMultiGpu() != null) {
if (queryUserResourceSpecsDTO.getMultiGpu()) {
queryResourceSpecsWrapper.gt("gpu_num", MagicNumConstant.ONE);
} else {
queryResourceSpecsWrapper.eq("gpu_num", MagicNumConstant.ONE);
}
}

queryResourceSpecsWrapper.orderByAsc("cpu_num");
List<ResourceSpecs> resourceSpecs = resourceSpecsMapper.selectList(queryResourceSpecsWrapper);
List<QueryUserResourceSpecsVO> queryUserResourceSpecsVOS = new ArrayList<>();
List<QueryUserK8sResourceDTO> QueryUserK8sResources = new ArrayList<>();
if (CollectionUtils.isNotEmpty(resourceSpecs)) {
QueryUserK8sResources = resourceSpecs.stream().map(x -> {
QueryUserK8sResourceDTO queryUserK8sResourceDTO = new QueryUserK8sResourceDTO();
BeanUtils.copyProperties(x, queryUserK8sResourceDTO);
queryUserK8sResourceDTO.setUserId(userId).setResourcesPoolNode(queryUserResourceSpecsDTO.getResourcesPoolNode());
if (queryUserResourceSpecsDTO.getResourcesPoolType()) {
queryUserK8sResourceDTO.setGpuModel(queryUserResourceSpecsDTO.getGpuModel()).setK8sLabelKey(queryUserResourceSpecsDTO.getK8sLabelKey());
}
return queryUserK8sResourceDTO;
}).collect(Collectors.toList());
}
//过滤k8s集群资源
if (CollectionUtils.isNotEmpty(QueryUserK8sResources)) {
DataResponseBody<List<QueryUserResourceSpecsVO>> dataResponseBody = systemNodeClient.queryUserK8sResource(QueryUserK8sResources);
if (!dataResponseBody.succeed()) {
throw new BusinessException("dubhe-k8s服务调用异常,查询集群资源是否可用失败");
}
return dataResponseBody.getData();
}
return queryUserResourceSpecsVOS;
}

/**
* 查询资源规格
* @param id 资源规格id
* @return QueryResourceSpecsVO 资源规格返回结果实体类
*/
@Override
public QueryResourceSpecsVO queryTadlResourceSpecs(Long id) {
LogUtil.info(LogEnum.BIZ_SYS,"Query resource specification information with resource id:{}",id);
ResourceSpecs resourceSpecs = resourceSpecsMapper.selectById(id);
LogUtil.info(LogEnum.BIZ_SYS,"Obtain resource specification information:{} ",resourceSpecs);
if (resourceSpecs == null) {
throw new BusinessException("资源规格不存在或已被删除");
}
QueryResourceSpecsVO queryResourceSpecsVO = new QueryResourceSpecsVO();
BeanUtils.copyProperties(resourceSpecs, queryResourceSpecsVO);
LogUtil.info(LogEnum.BIZ_SYS,"Return resource specification information :{} ",queryResourceSpecsVO);
return queryResourceSpecsVO;
}
}

+ 54
- 2
dubhe-server/admin/src/main/java/org/dubhe/admin/service/impl/UserGroupServiceImpl.java View File

@@ -22,6 +22,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.dubhe.admin.dao.UserGroupMapper;
import org.dubhe.admin.dao.UserMapper;
import org.dubhe.admin.dao.UserRoleMapper;
import org.dubhe.admin.domain.dto.*;
import org.dubhe.admin.domain.entity.Group;
@@ -32,6 +33,7 @@ import org.dubhe.admin.service.UserGroupService;
import org.dubhe.admin.service.UserService;
import org.dubhe.biz.base.constant.StringConstant;
import org.dubhe.biz.base.context.UserContext;
import org.dubhe.biz.base.dto.UserConfigSaveDTO;
import org.dubhe.biz.base.exception.BusinessException;
import org.dubhe.biz.base.service.UserContextService;
import org.dubhe.biz.base.utils.ReflectionUtils;
@@ -39,9 +41,12 @@ import org.dubhe.biz.base.utils.StringUtils;
import org.dubhe.biz.db.utils.PageUtil;
import org.dubhe.biz.log.enums.LogEnum;
import org.dubhe.biz.log.utils.LogUtil;
import org.dubhe.cloud.authconfig.factory.PasswordEncoderFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@@ -55,10 +60,16 @@ import java.util.stream.Collectors;
@Service
public class UserGroupServiceImpl implements UserGroupService {

@Value("${initial_password}")
private String initialPassword;

@Autowired
private UserGroupMapper userGroupMapper;

@Autowired
private UserMapper userMapper;

@Autowired
private UserContextService userContextService;

@Autowired
@@ -248,7 +259,7 @@ public class UserGroupServiceImpl implements UserGroupService {
* @param userGroupUpdDTO 批量删除用户组用户DTO
*/
@Override
public void delUser(UserGroupUpdDTO userGroupUpdDTO) {
public void delUser(UserGroupUpdDTO userGroupUpdDTO, String accessToken) {
//获取用户组的成员id
List<User> userList = userGroupMapper.queryUserByGroupId(userGroupUpdDTO.getGroupId());
userGroupMapper.delUserByGroupId(userGroupUpdDTO.getGroupId());
@@ -258,7 +269,7 @@ public class UserGroupServiceImpl implements UserGroupService {
ids.add(user.getId());
}
}
userService.delete(ids);
userService.delete(ids, accessToken);
}

/**
@@ -289,4 +300,45 @@ public class UserGroupServiceImpl implements UserGroupService {
//添加用户的新角色
userRoleMapper.insertBatchs(userRoleList);
}

/**
* 批量重置用户组用户的密码
*
* @param groupId
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void resetUserPassword(Long groupId) {
//获取用户组的成员id
List<User> userList = userGroupMapper.queryUserByGroupId(groupId);
Set<Long> ids = new HashSet<>();
if (CollUtil.isNotEmpty(userList)) {
for (User user : userList) {
ids.add(user.getId());
}
}
PasswordEncoder passwordEncoder = PasswordEncoderFactory.getPasswordEncoder();
//重置为默认密码123456,加密密码
String encode = passwordEncoder.encode(initialPassword);

LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.in(User::getId, ids);
updateWrapper.set(User::getPassword,encode);
updateWrapper.set(User::getLastPasswordResetTime,new Date());
userService.update(updateWrapper);
}

@Override
public void saveUserConfig(UserGroupConfigSaveDTO userGroupConfigSaveDTO) {
UserConfigSaveDTO userConfigSaveDTO = new UserConfigSaveDTO();
BeanUtils.copyProperties(userGroupConfigSaveDTO,userConfigSaveDTO);

List<User> users = userGroupMapper.queryUserByGroupId(userGroupConfigSaveDTO.getGroupId());
if(CollUtil.isNotEmpty(users)) {
users.forEach(user -> {
userConfigSaveDTO.setUserId(user.getId());
userService.saveUserConfig(userConfigSaveDTO,null);
});
}
}
}

+ 314
- 0
dubhe-server/admin/src/main/java/org/dubhe/admin/service/impl/UserResourceServiceImpl.java View File

@@ -0,0 +1,314 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.admin.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Maps;
import org.dubhe.admin.client.ResourceNamespaceClient;
import org.dubhe.admin.dao.UserConfigMapper;
import org.dubhe.admin.dao.UserGpuConfigMapper;
import org.dubhe.admin.dao.UserMapper;
import org.dubhe.admin.domain.dto.UserResourceListDTO;
import org.dubhe.admin.domain.dto.UserResourceQueryDTO;
import org.dubhe.admin.domain.entity.UserConfig;
import org.dubhe.admin.domain.entity.UserGpuConfig;
import org.dubhe.admin.domain.vo.UserLimitConfigVO;
import org.dubhe.admin.domain.vo.UserResourceResVO;
import org.dubhe.admin.enums.ResourceTypeEnum;
import org.dubhe.admin.enums.StatTypeEnum;
import org.dubhe.admin.service.UserResourceService;
import org.dubhe.biz.base.constant.NumberConstant;
import org.dubhe.biz.base.constant.StringConstant;
import org.dubhe.biz.base.constant.SymbolConstant;
import org.dubhe.biz.base.constant.UserConstant;
import org.dubhe.biz.base.exception.BusinessException;
import org.dubhe.biz.base.utils.MathUtils;
import org.dubhe.biz.base.vo.DataResponseBody;
import org.dubhe.biz.base.vo.GpuAllotVO;
import org.dubhe.biz.base.vo.UserAllotVO;
import org.dubhe.biz.db.utils.PageUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* @description 用户资源统计实现层
* @date 2021-11-23
*/
@Service
public class UserResourceServiceImpl implements UserResourceService {

@Autowired
private UserConfigMapper userConfigMapper;

@Autowired
private UserGpuConfigMapper userGpuConfigMapper;

@Autowired
private ResourceNamespaceClient resourceNamespaceClient;

@Autowired
private UserMapper userMapper;

private Map<String, Map<Long, String>> gpuMap = Maps.newHashMap();
private Map<String, Map<Long, String>> cpuMap = Maps.newHashMap();
private Map<String, Map<Long, String>> memMap = Maps.newHashMap();
private Map<Long, UserAllotVO> gpuAllotMap = Maps.newHashMap();

private final static List<String> SUMDAYS = new ArrayList();

static {
SUMDAYS.add(UserConstant.UNIT_7D);
SUMDAYS.add(UserConstant.UNIT_15D);
}

/**
* 用户资源Top10统计
*
* @param resourceQueryDTO 请求DTO实体
* @return List<UserAllotVO> 用户Top10资源列表
*/
@Override
public List<UserAllotVO> getResourceTotal(UserResourceQueryDTO resourceQueryDTO) {
List<UserAllotVO> userAllotList;
//获取资源配额
if (resourceQueryDTO.getStatType().equals(StatTypeEnum.ALLOT_TYPE.getCode())) {
userAllotList = toResourceAllot(resourceQueryDTO);
} else {
userAllotList = toResourceUsage(resourceQueryDTO);
}
return userAllotList;
}

/**
* 用户资源统计
*
* @return List<UserResourceResVO> 用户资源统计列表VO
*/
@Override
public Map<String, Object> getResourceList(UserResourceListDTO resourceListDTO) {
List<UserResourceResVO> userResourceResList = new ArrayList<>();
Page page = resourceListDTO.toPage();
String sort = StrUtil.isEmpty(resourceListDTO.getSort()) ? ResourceTypeEnum.GPU_TYPE.getDesc() : resourceListDTO.getSort();
String order = StrUtil.isEmpty(resourceListDTO.getOrder()) ? StringConstant.SORT_DESC : resourceListDTO.getOrder();

List<UserLimitConfigVO> userLimitConfigs = userConfigMapper.selectLimitSum(page, sort, order);
List<Long> userIds = userLimitConfigs.stream().map(UserLimitConfigVO::getUserId).collect(Collectors.toList());
String namespaces = userIds.stream().map(id -> UserConstant.NAMESPACE_PREFIX + id).collect(Collectors.joining("|"));
//查询gpu具体型号的配额
toGpuAllotMap(userIds);
//查询不同条件下的资源使用峰值
SUMDAYS.stream().forEach(day -> {
EnumSet.allOf(ResourceTypeEnum.class).forEach(code -> {
toResourceUsageMap(code.getCode(), day, namespaces);
});
});


for (UserLimitConfigVO userLimitConfig : userLimitConfigs) {
UserResourceResVO userResourceRes = new UserResourceResVO();
userResourceRes.setId(userLimitConfig.getUserId())
.setUserName(userLimitConfig.getUserName())
.setNickName(userLimitConfig.getNickName())
.setGpu(userLimitConfig.getGpu())
.setCpu(userLimitConfig.getCpu())
.setMem(userLimitConfig.getMem());
if (gpuAllotMap.containsKey(userLimitConfig.getUserId())) {
userResourceRes.setGpuModelAllots(new ArrayList<>());
} else {
userResourceRes.setGpuModelAllots(gpuAllotMap.get(userLimitConfig.getUserId()).getGpuAllotList());
}
userResourceRes.setGpu7unit(gpuMap.get(UserConstant.UNIT_7D).getOrDefault(userLimitConfig.getUserId(), SymbolConstant.ZERO));
userResourceRes.setGpu15unit(gpuMap.get(UserConstant.UNIT_15D).getOrDefault(userLimitConfig.getUserId(), SymbolConstant.ZERO));
userResourceRes.setGpu7(MathUtils.floatDivision(userResourceRes.getGpu7unit(), userResourceRes.getGpu(), NumberConstant.NUMBER_2).toString());
userResourceRes.setGpu15(MathUtils.floatDivision(userResourceRes.getGpu15unit(), userResourceRes.getGpu(), NumberConstant.NUMBER_2).toString());

userResourceRes.setCpu7unit(MathUtils.floatDivision(cpuMap.get(UserConstant.UNIT_7D).getOrDefault(userLimitConfig.getUserId(), SymbolConstant.ZERO), SymbolConstant.ONE, NumberConstant.NUMBER_2).toString());
userResourceRes.setCpu15unit(MathUtils.floatDivision(cpuMap.get(UserConstant.UNIT_15D).getOrDefault(userLimitConfig.getUserId(), SymbolConstant.ZERO), SymbolConstant.ONE, NumberConstant.NUMBER_2).toString());
userResourceRes.setCpu7(MathUtils.floatDivision(userResourceRes.getCpu7unit(), userResourceRes.getCpu(), NumberConstant.NUMBER_2).toString());
userResourceRes.setCpu15(MathUtils.floatDivision(userResourceRes.getCpu15unit(), userResourceRes.getCpu(), NumberConstant.NUMBER_2).toString());

userResourceRes.setMem7unit(MathUtils.floatDivision(memMap.get(UserConstant.UNIT_7D).getOrDefault(userLimitConfig.getUserId(), SymbolConstant.ZERO), StringConstant.MEM_UNIT, NumberConstant.NUMBER_2).toString());
userResourceRes.setMem15unit(MathUtils.floatDivision(memMap.get(UserConstant.UNIT_15D).getOrDefault(userLimitConfig.getUserId(), SymbolConstant.ZERO), StringConstant.MEM_UNIT, NumberConstant.NUMBER_2).toString());
userResourceRes.setMem7(MathUtils.floatDivision(userResourceRes.getMem7unit(), userResourceRes.getMem(), NumberConstant.NUMBER_2).toString());
userResourceRes.setMem15(MathUtils.floatDivision(userResourceRes.getMem15unit(), userResourceRes.getMem(), NumberConstant.NUMBER_2).toString());

userResourceResList.add(userResourceRes);
}
return PageUtil.toPage(page, userResourceResList);
}

/**
* 根据namespace-userId批量查询资源用量峰值
*
* @param resourceType 资源类型
* @param sumDay 查询周期
* @param namespaces 拼接的namespace字符串,例:namespace-1 | namespace-2 | namespace-3
*/
private void toResourceUsageMap(Integer resourceType, String sumDay, String namespaces) {
DataResponseBody<Map<Long, String>> result = resourceNamespaceClient.getResourceUsageByUser(resourceType, sumDay, namespaces);
if (!result.succeed()) {
throw new BusinessException("查询某用户用量峰值远程调用失败");
}
if (resourceType.equals(ResourceTypeEnum.GPU_TYPE.getCode())) {
gpuMap.put(sumDay, result.getData());
} else if (resourceType.equals(ResourceTypeEnum.CPU_TYPE.getCode())) {
cpuMap.put(sumDay, result.getData());
} else if (resourceType.equals(ResourceTypeEnum.MEMORY_TYPE.getCode())) {
memMap.put(sumDay, result.getData());
}
}

/**
* 统计用户GPU具体型号的配额
*
* @param userIds 用户id集合
*/
private void toGpuAllotMap(List<Long> userIds) {
//按型号获取gpu分配总量
List<UserGpuConfig> userGpuConfigs = userGpuConfigMapper.selectList(new LambdaQueryWrapper<UserGpuConfig>().in(UserGpuConfig::getUserId, userIds));
for (Long userId : userIds) {
UserAllotVO userAllotVO = new UserAllotVO();
List<GpuAllotVO> gpuAllots = new ArrayList<>();
for (UserGpuConfig gpuConfig : userGpuConfigs) {
if (userId.equals(gpuConfig.getUserId())) {
GpuAllotVO gpuAllotVO = new GpuAllotVO();
gpuAllotVO.setGpuModel(gpuConfig.getGpuModel());
gpuAllotVO.setAllotTotal(gpuConfig.getGpuLimit());
gpuAllots.add(gpuAllotVO);
userAllotVO.setAllotTotal(MathUtils.add(userAllotVO.getAllotTotal(), gpuConfig.getGpuLimit().toString()));
userAllotVO.setUserId(gpuConfig.getUserId());
userAllotVO.setGpuAllotList(gpuAllots);
}
}
gpuAllotMap.put(userId, userAllotVO);
}
}

/**
* 远程调用prometheus统计用户资源使用峰值
*
* @param resourceQueryDTO 查询DTO实体
* @return List<UserAllotVO> GPU型号资源配额列表
*/
private List<UserAllotVO> toResourceUsage(UserResourceQueryDTO resourceQueryDTO) {
List<UserAllotVO> userAllotList = new ArrayList<>();
DataResponseBody<List<UserAllotVO>> result = resourceNamespaceClient.getResourceNamespace(resourceQueryDTO.getResourceType(), resourceQueryDTO.getSumDay());
if (!result.succeed()) {
throw new BusinessException("查询用户用量峰值远程调用失败");
}
if (CollUtil.isNotEmpty(result.getData())) {
userAllotList = result.getData().stream().map(userAllotVO -> {
Long userId = Long.valueOf(userAllotVO.getUserName().replaceAll(UserConstant.NAMESPACE_PREFIX, StrUtil.EMPTY));
userAllotVO.setUserName(userMapper.findUserNameById(userId));
userAllotVO.setUserId(userId);
if (!resourceQueryDTO.getResourceType().equals(ResourceTypeEnum.GPU_TYPE.getCode())) {
userAllotVO.setAllotTotal(MathUtils.floatDivision(userAllotVO.getAllotTotal(), StringConstant.MEM_UNIT, 2).toString());
} else {
userAllotVO.setAllotTotal(userAllotVO.getAllotTotal());
}

return userAllotVO;
}).collect(Collectors.toList());
}
if (resourceQueryDTO.getStatType().equals(StatTypeEnum.USAGE_RATE_TYPE.getCode())) {
userAllotList = toUserAllotById(resourceQueryDTO.getResourceType(), userAllotList);
}
return userAllotList;
}

/**
* TOP10资源统计配额
*
* @param resourceQueryDTO 用户资源统计DTO
* @return List<UserAllotVO> 用户Top10资源列表
*/
private List<UserAllotVO> toResourceAllot(UserResourceQueryDTO resourceQueryDTO) {
List<UserAllotVO> userAllotList = new ArrayList<>();
switch (resourceQueryDTO.getResourceType()) {
case 2:
userAllotList = userConfigMapper.selectCpuAllotTotal();
break;
case 3:
userAllotList = userConfigMapper.selectMemoryAllotTotal();
break;
case 1:
List<UserGpuConfig> gpuConfigList = userGpuConfigMapper.selectAllotTotal();
for (UserGpuConfig gpuConfig : gpuConfigList) {
UserAllotVO userAllotVO = new UserAllotVO();
userAllotVO.setUserName(gpuConfig.getUserName());
userAllotVO.setAllotTotal(gpuConfig.getGpuLimit().toString());
userAllotVO.setGpuAllotList(userGpuConfigMapper.selectGpuModelTotal(gpuConfig.getUserId()));
userAllotList.add(userAllotVO);
}
default:
break;
}
return userAllotList;
}

/**
* 用户资源配额统计
*
* @param resourceType 资源类型
* @param userAllotList 用户Top10资源列表
* @return List<UserAllotVO> 用户Top10资源列表
*/
private List<UserAllotVO> toUserAllotById(Integer resourceType, List<UserAllotVO> userAllotList) {
switch (resourceType) {
//GPU配额总量
case 1:
userAllotList = userAllotList.stream().map(userAllotVO -> {
int gpuSum = userGpuConfigMapper.selectGpuLimitSum(userAllotVO.getUserId());
userAllotVO.setAllotTotal(MathUtils.floatDivision(userAllotVO.getAllotTotal(), String.valueOf(gpuSum), NumberConstant.NUMBER_2).toString());
return userAllotVO;
}).collect(Collectors.toList());
break;
//CPU配额总量
case 2:
userAllotList = userAllotList.stream().map(userAllotVO -> {
UserConfig userConfig = userConfigMapper.selectLimitSumByUser(userAllotVO.getUserId());
if (userConfig != null) {
userAllotVO.setAllotTotal(MathUtils.floatDivision(userAllotVO.getAllotTotal(), String.valueOf(userConfig.getCpuLimit()), 2).toString());
}
return userAllotVO;
}).collect(Collectors.toList());
break;
//内存配额总量
case 3:
userAllotList = userAllotList.stream().map(userAllotVO -> {
UserConfig userConfig = userConfigMapper.selectLimitSumByUser(userAllotVO.getUserId());
if (userConfig != null) {
userAllotVO.setAllotTotal(MathUtils.floatDivision(userAllotVO.getAllotTotal(), String.valueOf(userConfig.getMemoryLimit()), NumberConstant.NUMBER_2).toString());
}
return userAllotVO;
}).collect(Collectors.toList());
break;
default:
break;
}
return userAllotList;
}
}

+ 325
- 67
dubhe-server/admin/src/main/java/org/dubhe/admin/service/impl/UserServiceImpl.java View File

@@ -16,6 +16,7 @@
*/
package org.dubhe.admin.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.asymmetric.KeyType;
@@ -26,18 +27,39 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.dubhe.admin.async.CleanupUserResourcesAsync;
import org.dubhe.admin.client.AuthServiceClient;
import org.dubhe.admin.client.GpuConfigClient;
import org.dubhe.admin.client.ResourceQuotaClient;
import org.dubhe.admin.dao.*;
import org.dubhe.admin.domain.dto.*;
import org.dubhe.admin.client.template.GpuConfigTemplateClient;
import org.dubhe.admin.client.template.ObtainAccessToken;
import org.dubhe.admin.client.template.ResourceQuotaTemplateClient;
import org.dubhe.admin.dao.MenuMapper;
import org.dubhe.admin.dao.PermissionMapper;
import org.dubhe.admin.dao.RoleMapper;
import org.dubhe.admin.dao.TeamMapper;
import org.dubhe.admin.dao.UserAvatarMapper;
import org.dubhe.admin.dao.UserConfigMapper;
import org.dubhe.admin.dao.UserGpuConfigMapper;
import org.dubhe.admin.dao.UserMapper;
import org.dubhe.admin.dao.UserRoleMapper;
import org.dubhe.admin.domain.dto.AuthUserDTO;
import org.dubhe.admin.domain.dto.EmailDTO;
import org.dubhe.admin.domain.dto.UserCenterUpdateDTO;
import org.dubhe.admin.domain.dto.UserCreateDTO;
import org.dubhe.admin.domain.dto.UserEmailUpdateDTO;
import org.dubhe.admin.domain.dto.UserQueryDTO;
import org.dubhe.admin.domain.dto.UserRegisterDTO;
import org.dubhe.admin.domain.dto.UserRegisterMailDTO;
import org.dubhe.admin.domain.dto.UserResetPasswordDTO;
import org.dubhe.admin.domain.dto.UserUpdateDTO;
import org.dubhe.admin.domain.entity.Role;
import org.dubhe.admin.domain.entity.User;
import org.dubhe.admin.domain.entity.UserAvatar;
import org.dubhe.admin.domain.entity.UserConfig;
import org.dubhe.admin.domain.entity.UserGpuConfig;
import org.dubhe.admin.domain.entity.UserRole;
import org.dubhe.admin.domain.vo.EmailVo;
import org.dubhe.admin.domain.vo.UserConfigCreateVO;
import org.dubhe.admin.domain.vo.UserConfigVO;
import org.dubhe.admin.domain.vo.UserVO;
import org.dubhe.admin.enums.UserMailCodeEnum;
import org.dubhe.admin.event.EmailEventPublisher;
@@ -48,16 +70,29 @@ import org.dubhe.biz.base.constant.AuthConst;
import org.dubhe.biz.base.constant.ResponseCode;
import org.dubhe.biz.base.constant.UserConstant;
import org.dubhe.biz.base.context.UserContext;
import org.dubhe.biz.base.dto.*;
import org.dubhe.biz.base.dto.GpuConfigDTO;
import org.dubhe.biz.base.dto.Oauth2TokenDTO;
import org.dubhe.biz.base.dto.ResourceQuotaDTO;
import org.dubhe.biz.base.dto.SysPermissionDTO;
import org.dubhe.biz.base.dto.SysRoleDTO;
import org.dubhe.biz.base.dto.SysUserConfigDTO;
import org.dubhe.biz.base.dto.SysUserGpuConfigDTO;
import org.dubhe.biz.base.dto.TeamDTO;
import org.dubhe.biz.base.dto.UserConfigSaveDTO;
import org.dubhe.biz.base.dto.UserDTO;
import org.dubhe.biz.base.dto.UserGpuConfigDTO;
import org.dubhe.biz.base.enums.BaseErrorCodeEnum;
import org.dubhe.biz.base.enums.SwitchEnum;
import org.dubhe.biz.base.exception.BusinessException;
import org.dubhe.biz.base.exception.CaptchaException;
import org.dubhe.biz.base.utils.DateUtil;
import org.dubhe.biz.base.utils.Md5Util;
import org.dubhe.biz.base.utils.RandomUtil;
import org.dubhe.biz.base.utils.RsaEncrypt;
import org.dubhe.biz.base.vo.DataResponseBody;
import org.dubhe.biz.base.vo.GpuAllotVO;
import org.dubhe.biz.base.vo.UserAllotResourceVO;
import org.dubhe.biz.base.vo.UserConfigVO;
import org.dubhe.biz.base.vo.UserGpuConfigVO;
import org.dubhe.biz.dataresponse.factory.DataResponseFactory;
import org.dubhe.biz.db.utils.PageUtil;
import org.dubhe.biz.db.utils.WrapperHelp;
@@ -65,6 +100,7 @@ import org.dubhe.biz.file.utils.DubheFileUtil;
import org.dubhe.biz.log.enums.LogEnum;
import org.dubhe.biz.log.utils.LogUtil;
import org.dubhe.biz.permission.annotation.DataPermissionMethod;
import org.dubhe.biz.permission.aspect.PermissionAspect;
import org.dubhe.biz.redis.utils.RedisUtils;
import org.dubhe.cloud.authconfig.dto.JwtUserDTO;
import org.dubhe.cloud.authconfig.factory.PasswordEncoderFactory;
@@ -73,15 +109,28 @@ import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
@@ -89,6 +138,7 @@ import java.util.stream.Collectors;
* @date 2020-11-26
*/
@Service
@RefreshScope
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

@Value("${rsa.private_key}")
@@ -98,7 +148,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
private String initialPassword;

@Value("${user.config.notebook-delay-delete-time}")
private Integer defaultNotebookDelayDeleteTime;
private Integer userConfigNotebookDelayDeleteTime;

@Value("${user.config.cpu-limit}")
private Integer cpuLimit;
@@ -106,8 +156,17 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
@Value("${user.config.memory-limit}")
private Integer memoryLimit;

@Value("${user.config.gpu-limit}")
private Integer gpuLimit;
@Value("${user.config.gpu-limit.gpu-type}")
private String gpuType;

@Value("${user.config.gpu-limit.gpu-model}")
private String gpuModel;

@Value("${user.config.gpu-limit.k8s-label-key}")
private String k8sLabelKey;

@Value("${user.config.gpu-limit.gpu-num-limit}")
private Integer gpuNumLimit;

@Autowired
private UserMapper userMapper;
@@ -131,7 +190,6 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
@Autowired
private UserAvatarMapper userAvatarMapper;


@Autowired
private RedisUtils redisUtils;

@@ -151,15 +209,34 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
private UserConfigMapper userConfigMapper;

@Autowired
private UserGpuConfigMapper userGpuConfigMapper;

@Autowired
ResourceQuotaClient resourceQuotaClient;

@Autowired
ResourceQuotaTemplateClient resourceQuotaTemplateClient;

@Autowired
GpuConfigTemplateClient gpuConfigTemplateClient;

@Autowired
private GpuConfigClient gpuConfigClient;

@Autowired
private CleanupUserResourcesAsync cleanupUserResourcesAsync;

@Autowired
private ObtainAccessToken obtainAccessToken;
/**
* 测试标识 true:允许debug false:拒绝debug
*/
@Value("${debug.flag}")
private Boolean debugFlag;

@Value("${email.send-limit}")
private Integer emailSendLimit;

private final String LOCK_SEND_CODE = "LOCK_SEND_CODE";

/**
@@ -173,10 +250,12 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
public Object queryAll(UserQueryDTO criteria, Page page) {
if (criteria.getRoleId() == null) {
IPage<User> users = userMapper.selectCollPage(page, WrapperHelp.getWrapper(criteria));
return PageUtil.toPage(users, userConvert::toDto);
List<UserDTO> userDTOList = convertToUserDTO(users);
return PageUtil.toPage(users, userDTOList);
} else {
IPage<User> users = userMapper.selectCollPageByRoleId(page, WrapperHelp.getWrapper(criteria), criteria.getRoleId());
return PageUtil.toPage(users, userConvert::toDto);
List<UserDTO> userDTOList = convertToUserDTO(users);
return PageUtil.toPage(users, userDTOList);
}
}

@@ -189,7 +268,17 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
@Override
public List<UserDTO> queryAll(UserQueryDTO criteria) {
List<User> users = userMapper.selectCollList(WrapperHelp.getWrapper(criteria));
return userConvert.toDto(users);
List<UserDTO> userDTOList = null;
if (CollectionUtil.isEmpty(users)) {
return userDTOList;
}
userDTOList = userConvert.toDto(users);
for (UserDTO userDTO : userDTOList) {
String userGroupName = userMapper.queryUserGroupNameByUserId(userDTO.getId());
userDTO.setUserGroupName(userGroupName);
}

return userDTOList;
}

/**
@@ -248,15 +337,14 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
for (Role role : resources.getRoles()) {
roleMapper.tiedUserRole(user.getId(), role.getId());
}
UserConfigDTO userConfigDTO = new UserConfigDTO();
userConfigDTO.setUserId(user.getId());
userConfigDTO.setCpuLimit(cpuLimit);
userConfigDTO.setMemoryLimit(memoryLimit);
userConfigDTO.setGpuLimit(gpuLimit);
DataResponseBody dataResponseBody = resourceQuotaClient.updateResourceQuota(userConfigDTO);
if (!dataResponseBody.succeed()){
throw new BusinessException("用户配置更新失败");
}
//初始化用户配置
UserConfigSaveDTO userConfigDTO = new UserConfigSaveDTO();
userConfigDTO.setUserId(user.getId()).setCpuLimit(cpuLimit).setMemoryLimit(memoryLimit)
.setNotebookDelayDeleteTime(userConfigNotebookDelayDeleteTime);
List<UserGpuConfigDTO> userGpuConfigs = new ArrayList<>();
userGpuConfigs.add(new UserGpuConfigDTO().setGpuType(gpuType).setGpuModel(gpuModel).setK8sLabelKey(k8sLabelKey).setGpuLimit(gpuNumLimit));
userConfigDTO.setGpuResources(userGpuConfigs);
saveUserConfig(userConfigDTO, null);
return userConvert.toDto(user);
}

@@ -307,19 +395,15 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void delete(Set<Long> ids) {
public void delete(Set<Long> ids, String accessToken) {
if (!CollectionUtils.isEmpty(ids)) {
Long adminId = Long.valueOf(UserConstant.ADMIN_USER_ID);
if (ids.contains(adminId)) {
throw new BusinessException(BaseErrorCodeEnum.SYSTEM_USER_CANNOT_DELETE);
}
ids.forEach(id -> {
userMapper.updateById(
User.builder()
.id(id)
.deleted(SwitchEnum.getBooleanValue(SwitchEnum.ON.getValue()))
.build());
});
userMapper.deleteBatchIds(ids);
//异步清理用户资源
cleanupUserResourcesAsync.cleanUserResource(ids, accessToken);
}
}

@@ -339,6 +423,9 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
}
UserDTO dto = new UserDTO();
BeanUtils.copyProperties(user, dto);
if (user.getUserAvatar() != null && StrUtil.isNotBlank(user.getUserAvatar().getPath())) {
dto.setUserAvatarPath(user.getUserAvatar().getPath());
}
List<Role> roles = roleMapper.findRolesByUserId(user.getId());
if (!CollectionUtils.isEmpty(roles)) {
dto.setRoles(roles.stream().map(a -> {
@@ -357,12 +444,36 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us

private SysUserConfigDTO getUserConfig(Long userId) {
UserConfig userConfig = userConfigMapper.selectOne(new QueryWrapper<>(new UserConfig().setUserId(userId)));
SysUserConfigDTO sysUserConfigDTO= new SysUserConfigDTO();
if (userConfig == null){
return sysUserConfigDTO.setCpuLimit(cpuLimit).setMemoryLimit(memoryLimit)
.setGpuLimit(gpuLimit).setNotebookDelayDeleteTime(defaultNotebookDelayDeleteTime);
SysUserConfigDTO sysUserConfigDTO = new SysUserConfigDTO();
// 如果用户配置为空,则返回默认配置
if (userConfig == null) {
sysUserConfigDTO.setCpuLimit(cpuLimit).setMemoryLimit(memoryLimit)
.setNotebookDelayDeleteTime(userConfigNotebookDelayDeleteTime);
} else {
BeanUtils.copyProperties(userConfig, sysUserConfigDTO);
}
// 查询用户GPU配置
List<UserGpuConfig> userGpuConfigs = userGpuConfigMapper.selectList(new QueryWrapper<>(new UserGpuConfig().setUserId(userId)));
// 如果老用户未初始化GPU配置,则返回默认配置
if (CollectionUtils.isEmpty(userGpuConfigs) && userGpuConfigMapper.selectCountByUserId(userId) == 0) {
List<UserGpuConfig> preUserGpuConfigs = userGpuConfigMapper.selectList(new QueryWrapper<>(new UserGpuConfig().setUserId(0L)));
if (CollectionUtil.isNotEmpty(preUserGpuConfigs)) {
userGpuConfigs.addAll(preUserGpuConfigs);
}
}
List<SysUserGpuConfigDTO> sysUserGpuConfigDTOs = userGpuConfigs.stream().map(x -> {
SysUserGpuConfigDTO sysUserGpuConfigDTO = new SysUserGpuConfigDTO();
BeanUtils.copyProperties(x, sysUserGpuConfigDTO);
return sysUserGpuConfigDTO;
}).collect(Collectors.toList());
sysUserConfigDTO.setGpuResources(sysUserGpuConfigDTOs);
//如果当前用户如果没有默认镜像,就使用管理员的
if (userConfig == null || userConfig.getDefaultImageId() == null) {
LambdaQueryWrapper<UserConfig> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(UserConfig::getUserId, PermissionAspect.PUBLIC_DATA_USER_ID);
UserConfig adminConfig = userConfigMapper.selectOne(queryWrapper);
sysUserConfigDTO.setDefaultImageId(adminConfig.getDefaultImageId());
}
BeanUtils.copyProperties(userConfig, sysUserConfigDTO);
return sysUserConfigDTO;
}

@@ -491,6 +602,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
//用户信息校验
checkoutUserInfo(userRegisterDTO);
String encode = passwordEncoder.encode(RsaEncrypt.decrypt(userRegisterDTO.getPassword(), privateKey));
Long userId;
try {
User newUser = User.builder()
.email(userRegisterDTO.getEmail())
@@ -503,18 +615,42 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us

//新增用户注册信息
userMapper.insert(newUser);
userId = newUser.getId();
//绑定用户默认权限
userRoleMapper.insert(UserRole.builder().roleId((long) UserConstant.REGISTER_ROLE_ID).userId(newUser.getId()).build());

userRoleMapper.insert(UserRole.builder().roleId((long) UserConstant.REGISTER_ROLE_ID).userId(userId).build());
} catch (Exception e) {
LogUtil.error(LogEnum.SYS_ERR, "UserServiceImpl userRegister error , param:{} error:{}", JSONObject.toJSONString(userRegisterDTO), e);
throw new BusinessException(BaseErrorCodeEnum.ERROR_SYSTEM.getCode(), BaseErrorCodeEnum.ERROR_SYSTEM.getMsg());
}

//初始化用户配置
execute(userId, userRegisterDTO.getUsername(), userRegisterDTO.getPassword());
return new DataResponseBody();
}

/**
* 同步初始化用户配置
* @param userId 用户id
* @param username 用户名
* @param password 用户密码
*/
public void execute(Long userId, String username, String password) {
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
//为注册用户生成token
String token = obtainAccessToken.generateToken(username, password);
//初始化用户配置
UserConfigSaveDTO userConfigDTO = new UserConfigSaveDTO();
userConfigDTO.setUserId(userId).setCpuLimit(cpuLimit).setMemoryLimit(memoryLimit)
.setNotebookDelayDeleteTime(userConfigNotebookDelayDeleteTime);
List<UserGpuConfigDTO> userGpuConfigs = new ArrayList<>();
userGpuConfigs.add(new UserGpuConfigDTO().setGpuType(gpuType).setGpuModel(gpuModel).setK8sLabelKey(k8sLabelKey).setGpuLimit(gpuNumLimit));
userConfigDTO.setGpuResources(userGpuConfigs);
saveUserConfig(userConfigDTO, token);
}
});
}

/**
* 获取code通过发送邮件
@@ -565,6 +701,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us

} catch (Exception e) {
redisUtils.hdel(UserConstant.USER_EMAIL_REGISTER.concat(email), email);
redisUtils.hdel(UserConstant.USER_EMAIL_LIMIT_COUNT.concat(email), email);
LogUtil.error(LogEnum.SYS_ERR, "UserServiceImpl getCodeBySentEmail error , param:{} error:{}", email, e);
throw new BusinessException(BaseErrorCodeEnum.ERROR_SYSTEM.getCode(), BaseErrorCodeEnum.ERROR_SYSTEM.getMsg());
}
@@ -623,7 +760,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
.email(curUser.getUser().getEmail())
.password(Md5Util.createMd5(Md5Util.createMd5(curUser.getUsername()).concat(initialPassword)))
.username(curUser.getUsername())
.is_staff(!CollectionUtils.isEmpty(userRoles) ? true : false).build();
.is_staff(!CollectionUtils.isEmpty(userRoles)).build();

return BeanMap.create(vo);
}
@@ -752,43 +889,112 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
// 查询用户配置
UserConfig userConfig = userConfigMapper.selectOne(new QueryWrapper<>(new UserConfig().setUserId(userId)));
UserConfigVO userConfigVO = new UserConfigVO();
// 如果用户配置为空,则返回
if (userConfig == null){
return userConfigVO.setUserId(userId).setCpuLimit(cpuLimit).setMemoryLimit(memoryLimit)
.setGpuLimit(gpuLimit).setNotebookDelayDeleteTime(defaultNotebookDelayDeleteTime);
// 如果用户配置为空,则返回默认配置
if (userConfig == null) {
userConfigVO.setUserId(userId).setCpuLimit(cpuLimit).setMemoryLimit(memoryLimit)
.setNotebookDelayDeleteTime(userConfigNotebookDelayDeleteTime);
} else {
BeanUtils.copyProperties(userConfig, userConfigVO);
}
// 封装用户配置 VO
BeanUtils.copyProperties(userConfig, userConfigVO);
// 查询用户GPU配置
List<UserGpuConfig> userGpuConfigs = userGpuConfigMapper.selectList(new QueryWrapper<>(new UserGpuConfig().setUserId(userId)));
List<UserGpuConfigVO> userGpuConfigVOList = new ArrayList<>();
// 如果老用户未初始化GPU配置,则返回默认配置
if (CollectionUtils.isEmpty(userGpuConfigs) && userGpuConfigMapper.selectCountByUserId(userId) == 0) {
List<UserGpuConfig> preUserGpuConfigs = userGpuConfigMapper.selectList(new QueryWrapper<>(new UserGpuConfig().setUserId(PermissionAspect.PUBLIC_DATA_USER_ID)));
userGpuConfigs = preUserGpuConfigs;
}
userGpuConfigs.forEach(userGpuConfig -> {
UserGpuConfigVO userGpuConfigVO = new UserGpuConfigVO();
BeanUtils.copyProperties(userGpuConfig, userGpuConfigVO);
userGpuConfigVOList.add(userGpuConfigVO);
});

userConfigVO.setGpuResources(userGpuConfigVOList);
return userConfigVO;
}

/**
* 创建或更新用户配置
*
* @param userConfigDTO 用户配置
* @return org.dubhe.admin.domain.vo.UserConfigCreateVO 用户配置 VO
* @param userConfigSaveDTO 用户配置
*/
@Override
@Transactional(rollbackFor = Exception.class)
public UserConfigCreateVO createOrUpdateUserConfig(UserConfigDTO userConfigDTO) {
DataResponseBody dataResponseBody = resourceQuotaClient.updateResourceQuota(userConfigDTO);
if (!dataResponseBody.succeed()){
throw new BusinessException("用户配置更新失败");
public void saveUserConfig(UserConfigSaveDTO userConfigSaveDTO, String token) {
//设置k8s quota (k8s quota设置只支持以厂商为单位的配置)
ResourceQuotaDTO resourceQuotaDTO = new ResourceQuotaDTO();
BeanUtils.copyProperties(userConfigSaveDTO, resourceQuotaDTO);
//目前只有nvidia和suiyuan,map初始化空间设置为2
Map<String, Integer> map = new HashMap<>(2);
if (!CollectionUtils.isEmpty(userConfigSaveDTO.getGpuResources())) {
for (UserGpuConfigDTO userGpuConfigDTO : userConfigSaveDTO.getGpuResources()) {
Integer gpuNumLimit = userGpuConfigDTO.getGpuLimit();
if (map.containsKey(userGpuConfigDTO.getK8sLabelKey())) {
gpuNumLimit = map.get(userGpuConfigDTO.getK8sLabelKey()) + userGpuConfigDTO.getGpuLimit();
}
map.put(userGpuConfigDTO.getK8sLabelKey(), gpuNumLimit);
}
}
resourceQuotaDTO.setGpuLimit(map);

//设置k8s GPU型号配置
GpuConfigDTO gpuConfigDTO = new GpuConfigDTO();
gpuConfigDTO.setUserId(userConfigSaveDTO.getUserId());
if (!CollectionUtils.isEmpty(userConfigSaveDTO.getGpuResources())) {
List<SysUserGpuConfigDTO> sysUserGpuConfigs = userConfigSaveDTO.getGpuResources().stream().map(x -> {
SysUserGpuConfigDTO sysUserGpuConfigDTO = new SysUserGpuConfigDTO();
BeanUtils.copyProperties(x, sysUserGpuConfigDTO);
return sysUserGpuConfigDTO;
}).collect(Collectors.toList());
gpuConfigDTO.setGpuResources(sysUserGpuConfigs);
}
DataResponseBody gpuConfigDataResponse;
if (token == null) {
gpuConfigDataResponse = gpuConfigClient.updateGpuConfig(gpuConfigDTO);
} else {
gpuConfigDataResponse = gpuConfigTemplateClient.updateGpuConfig(gpuConfigDTO, AuthConst.ACCESS_TOKEN_PREFIX + token);
}
if (gpuConfigDataResponse == null || !gpuConfigDataResponse.succeed()) {
throw new BusinessException("k8s GPU型号配置更新失败");
}
//创建或更新用户配置
UserConfig userConfig = new UserConfig();
BeanUtils.copyProperties(userConfigDTO, userConfig);
BeanUtils.copyProperties(userConfigSaveDTO, userConfig);
userConfigMapper.insertOrUpdate(userConfig);
// 封装用户配置 VO
UserConfigCreateVO userConfigCreateVO = new UserConfigCreateVO().setId(userConfig.getId());
return userConfigCreateVO;
}
//创建或更新用户GPU配置
//删除原有记录
if (userGpuConfigMapper.selectCount(new QueryWrapper<>(new UserGpuConfig().setUserId(userConfigSaveDTO.getUserId()))) > 0) {
userGpuConfigMapper.delete(new QueryWrapper<>(new UserGpuConfig().setUserId(userConfigSaveDTO.getUserId())));
}
if (!CollectionUtils.isEmpty(userConfigSaveDTO.getGpuResources())) {
List<UserGpuConfig> userGpuConfigs = userConfigSaveDTO.getGpuResources().stream().map(x ->
{
UserGpuConfig userGpuConfig = new UserGpuConfig();
BeanUtils.copyProperties(x, userGpuConfig);
userGpuConfig.setUserId(userConfigSaveDTO.getUserId());
return userGpuConfig;
}).collect(Collectors.toList());
userGpuConfigMapper.insertBatchs(userGpuConfigs);
}

//更新quota中GPU的配额
DataResponseBody dataResponseBody;
if (token == null) {
dataResponseBody = resourceQuotaClient.updateResourceQuota(resourceQuotaDTO);
} else {
dataResponseBody = resourceQuotaTemplateClient.updateResourceQuota(resourceQuotaDTO, AuthConst.ACCESS_TOKEN_PREFIX + token);
}
if (dataResponseBody == null || !dataResponseBody.succeed()) {
throw new BusinessException("k8s quota用户配置更新失败");
}
}

/**
* 校验验证码
*
* @param loginCaptcha 验证码参数
* @param uuid 验证码redis-key
* @param loginCaptcha 验证码参数
* @param uuid 验证码redis-key
*/
private void validateCode(String loginCaptcha, String uuid) {
// 验证码未输入
@@ -853,17 +1059,15 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
*/
private void limitSendEmail(final String receiverMailAddress) {
double count = redisUtils.hincr(UserConstant.USER_EMAIL_LIMIT_COUNT.concat(receiverMailAddress), receiverMailAddress, 1);
if (count > UserConstant.COUNT_SENT_EMAIL) {
LogUtil.error(LogEnum.SYS_ERR, "Email verification code cannot exceed three times , error:{}", UserConstant.COUNT_SENT_EMAIL);
if (count > emailSendLimit) {
LogUtil.error(LogEnum.SYS_ERR, "Email verification code cannot exceed three times , error:{}", emailSendLimit);
throw new BusinessException(BaseErrorCodeEnum.SYSTEM_USER_EMAIL_CODE_CANNOT_EXCEED_TIMES.getCode(),
BaseErrorCodeEnum.SYSTEM_USER_EMAIL_CODE_CANNOT_EXCEED_TIMES.getMsg());
} else {
// 验证码次数凌晨清除
String concat = UserConstant.USER_EMAIL_LIMIT_COUNT.concat(receiverMailAddress);

Long secondsNextEarlyMorning = DateUtil.getSecondTime();

redisUtils.expire(concat, secondsNextEarlyMorning);
Duration duration = Duration.between(LocalDateTime.now(), LocalDate.now().plusDays(1).atTime(0, 0, 0));
redisUtils.expire(concat, duration.getSeconds());
}
}

@@ -889,8 +1093,8 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
/**
* 校验 邮箱地址 和 验证码
*
* @param code 验证码
* @param email 邮箱
* @param code 验证码
* @param email 邮箱
* @param codeRedisKey redis-key
*/
private void checkoutEmailAndCode(String code, String email, String codeRedisKey) {
@@ -993,4 +1197,58 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
dto.setUserConfig(sysUserConfigDTO);
return DataResponseFactory.success(dto);
}

/**
* 重置密码
*
* @return 重置密码结果集
*/
@Transactional(rollbackFor = Exception.class)
@Override
public DataResponseBody resetPassword(Long userId) {

PasswordEncoder passwordEncoder = PasswordEncoderFactory.getPasswordEncoder();
//重置为默认密码123456,加密密码
String encode = passwordEncoder.encode(initialPassword);
userMapper.updateById(User.builder().id(userId).password(encode).lastPasswordResetTime(new Date()).build());
return new DataResponseBody();
}

/**
* 获取用户分配的资源总量
*
* @return 资源配额总量统计
*/
@Override
public DataResponseBody getAllotResources() {
//获取内存、cpu分配总量
UserAllotResourceVO userAllotResourceVO = userConfigMapper.selectResourceSum();
//按型号获取gpu分配总量
List<GpuAllotVO> gpuAllotVOList = userGpuConfigMapper.selectGpuAllotSum();
List<Integer> gpuAllotTotal = gpuAllotVOList.stream().map(allot -> Integer.valueOf(allot.getAllotTotal())).collect(Collectors.toList());
userAllotResourceVO.setGpuAllotTotal(gpuAllotTotal.stream().reduce(Integer::sum).get());
userAllotResourceVO.setGpuAllotList(gpuAllotVOList);
return new DataResponseBody(userAllotResourceVO);
}


/**
* 将user转换为userDTO,并且设置对应的用户组名
*
* @return userDTO list
*/
private List<UserDTO> convertToUserDTO(IPage<User> users) {
List<UserDTO> userDTOList = new ArrayList<>();
if (CollectionUtil.isEmpty(users.getRecords())) {
return userDTOList;
}
userDTOList = userConvert.toDto(users.getRecords());
for (UserDTO userDTO : userDTOList) {
String userGroupName = userMapper.queryUserGroupNameByUserId(userDTO.getId());
userDTO.setUserGroupName(userGroupName);
}

return userDTOList;
}

}

+ 3
- 3
dubhe-server/admin/src/main/resources/bootstrap.yml View File

@@ -10,8 +10,8 @@ spring:
nacos:
config:
enabled: true
server-addr: 127.0.0.1:8848
namespace: dubhe-server-cloud-prod
server-addr: 10.105.1.133:8848
namespace: dubhe-server-cloud-dev
shared-configs[0]:
data-id: common-biz.yaml
group: dubhe
@@ -33,5 +33,5 @@ spring:
enabled: true
namespace: dubhe-server-cloud-dev
group: dubhe
server-addr: 127.0.0.1:8848
server-addr: 10.105.1.133:8848


+ 24
- 10
dubhe-server/admin/src/main/resources/mapper/UserConfigMapper.xml View File

@@ -21,9 +21,6 @@
<if test="memoryLimit != null">
memory_limit,
</if>
<if test="gpuLimit != null">
gpu_limit,
</if>
<if test="createUserId != null">
create_user_id,
</if>
@@ -33,6 +30,9 @@
<if test="updateUserId != null">
update_user_id,
</if>
<if test="defaultImageId != null">
default_image_id,
</if>
<if test="deleted != null">
deleted,
</if>
@@ -50,9 +50,6 @@
<if test="memoryLimit != null">
#{memoryLimit},
</if>
<if test="gpuLimit != null">
#{gpuLimit},
</if>
<if test="createUserId != null">
#{createUserId},
</if>
@@ -62,6 +59,9 @@
<if test="updateUserId != null">
#{updateUserId},
</if>
<if test="defaultImageId != null">
#{defaultImageId},
</if>
<if test="deleted != null">
#{deleted},
</if>
@@ -77,9 +77,6 @@
<if test="memoryLimit != null">
memory_limit = #{memoryLimit},
</if>
<if test="gpuLimit != null">
gpu_limit = #{gpuLimit},
</if>
<if test="createTime != null">
create_time = #{createTime},
</if>
@@ -92,9 +89,26 @@
<if test="updateUserId != null">
update_user_id = #{updateUserId},
</if>
<if test="defaultImageId != null">
default_image_id = #{defaultImageId},
</if>
<if test="deleted != null">
deleted = #{deleted},
</if>
</trim>
</insert>
</mapper>
<select id="selectLimitSum" resultType="org.dubhe.admin.domain.vo.UserLimitConfigVO">
select
u.id userId,
u.username userName,
u.nick_name nickName,
uc.cpu_limit cpu,
uc.memory_limit mem,
sum(ugc.gpu_limit) gpu
from user u
left join user_config uc on u.id=uc.user_id
left join user_gpu_config ugc on uc.user_id=ugc.user_id
where uc.deleted=0 and ugc.deleted=0 group by userId order by ${sort} ${order}
</select>
</mapper>

+ 12
- 0
dubhe-server/admin/src/main/resources/mapper/UserGpuConfigMapper.xml View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >

<mapper namespace="org.dubhe.admin.dao.UserGpuConfigMapper">

<insert id="insertBatchs" parameterType="java.util.List">
insert into user_gpu_config (user_id,gpu_type,gpu_model,k8s_label_key,gpu_limit) values
<foreach collection="list" item="item" separator=",">
(#{item.userId}, #{item.gpuType}, #{item.gpuModel}, #{item.k8sLabelKey}, #{item.gpuLimit})
</foreach>
</insert>
</mapper>

+ 5
- 0
dubhe-server/admin/src/main/resources/mapper/UserMapper.xml View File

@@ -13,4 +13,9 @@
left join users_roles ur on ra.role_id = ur.role_id
where ur.user_id = #{userId} and p.deleted=0;
</select>

<select id="queryUserGroupNameByUserId" parameterType="Long" resultType="java.lang.String">
select g.name from pt_group g, user u, user_group ug
where u.id = #{userId} and u.id = ug.user_id and ug.group_id = g.id and g.deleted = 0 and u.deleted = 0
</select>
</mapper>

+ 12
- 0
dubhe-server/admin/src/test/java/org/dubhe/admin/AdminApplicationTests.java View File

@@ -1,5 +1,6 @@
package org.dubhe.admin;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.dubhe.admin.domain.dto.DictCreateDTO;
import org.dubhe.admin.domain.dto.DictDetailDTO;
@@ -7,8 +8,10 @@ import org.dubhe.admin.domain.dto.DictDetailQueryDTO;
import org.dubhe.admin.domain.entity.DictDetail;
import org.dubhe.admin.rest.DictController;
import org.dubhe.admin.service.DictDetailService;
import org.dubhe.admin.service.UserService;
import org.dubhe.biz.base.utils.DateUtil;
import org.dubhe.biz.base.vo.DataResponseBody;
import org.dubhe.biz.base.vo.UserConfigVO;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@@ -28,6 +31,9 @@ public class AdminApplicationTests {
@Autowired
private DictDetailService dictDetailService;

@Autowired
private UserService userService;

/**
* 字典分页查询
*/
@@ -67,4 +73,10 @@ public class AdminApplicationTests {

}

@Test
public void findUserConfig() {
UserConfigVO userConfig = userService.findUserConfig(1l);
System.out.println(JSON.toJSONString(userConfig));
}

}

+ 3
- 3
dubhe-server/auth/src/main/resources/bootstrap.yml View File

@@ -11,8 +11,8 @@ spring:
nacos:
config:
enabled: true
server-addr: 127.0.0.1:8848
namespace: dubhe-server-cloud-prod
server-addr: 10.105.1.133:8848
namespace: dubhe-server-cloud-dev
shared-configs[0]:
data-id: common-biz.yaml
group: dubhe
@@ -25,5 +25,5 @@ spring:
enabled: true
namespace: dubhe-server-cloud-dev
group: dubhe
server-addr: 127.0.0.1:8848
server-addr: 10.105.1.133:8848


+ 4
- 0
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/constant/ApplicationNameConst.java View File

@@ -82,6 +82,10 @@ public class ApplicationNameConst {
public final static String SERVER_DATA_DCM = "dubhe-data-dcm";

/**
* TADL
*/
public final static String SERVER_TADL = "dubhe-tadl";
/**
* k8s
*/
public final static String SERVER_K8S = "dubhe-k8s";


+ 4
- 4
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/constant/AuthConst.java View File

@@ -54,10 +54,10 @@ public class AuthConst {
* 默认匿名访问路径
*/
public final static String[] DEFAULT_PERMIT_PATHS = {"/swagger**/**", "/webjars/**", "/v2/api-docs/**", "/doc.html/**",
"/users/findUserByUsername", "/auth/login", "/auth/code",
"/datasets/files/annotations/auto","/datasets/versions/**/convert/finish", "/datasets/enhance/finish",
"/auth/getCodeBySentEmail","/auth/userRegister","/ws/**",
StringConstant.RECYCLE_CALL_URI+"**"
"/users/findUserByUsername", "/auth/login", "/auth/code", "/auth/resetPassword",
"/datasets/files/annotations/auto", "/datasets/versions/**/convert/finish", "/datasets/enhance/finish",
"/auth/getCodeBySentEmail", "/auth/userRegister", "/ws/**",
StringConstant.RECYCLE_CALL_URI + "**"
};

/**


+ 1
- 0
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/constant/MagicNumConstant.java View File

@@ -68,6 +68,7 @@ public final class MagicNumConstant {
public static final int TWO_THOUSAND_TWENTY_EIGHT = 2048;
public static final int THREE_THOUSAND = 3000;
public static final int FOUR_THOUSAND = 4000;
public static final int EIGHT_THOUSAND_ONE_HUNDRED_NINETY_TWO = 8192;
public static final int NINE_THOUSAND = 9000;
public static final int NINE_THOUSAND_NINE_HUNDRED_NINTY_NINE = 9999;
public static final int TEN_THOUSAND = 10000;


+ 2
- 0
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/constant/NumberConstant.java View File

@@ -32,6 +32,8 @@ public class NumberConstant {
public final static int NUMBER_6 = 6;
public final static int NUMBER_8 = 8;
public final static int NUMBER_10 = 10;
public final static int NUMBER_12 = 12;
public final static int NUMBER_24 = 24;
public final static int NUMBER_30 = 30;
public final static int NUMBER_32 = 32;
public final static int NUMBER_50 = 50;


+ 13
- 0
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/constant/Permissions.java View File

@@ -132,6 +132,9 @@ public final class Permissions {
public static final String USER_GROUP_EDIT_USER_ROLE = "hasAuthority('ROLE_system:userGroup:editUserRole')";
public static final String USER_GROUP_EDIT_USER_STATE = "hasAuthority('ROLE_system:userGroup:editUserState')";
public static final String USER_GROUP_DELETE_USER = "hasAuthority('ROLE_system:userGroup:deleteUser')";
public static final String USER_GROUP_RESET_USER_PASSWORD ="hasAuthority('ROLE_system:userGroup:resetUserPassword')" ;
public static final String USER_GROUP_CONFIG_EDIT ="hasAuthority('ROLE_system:userGroup:editUserConfig')" ;


/**
* 控制台:用户管理
@@ -142,6 +145,7 @@ public final class Permissions {
public static final String USER_DOWNLOAD = "hasAuthority('ROLE_system:user:download')";
public static final String USER_CONFIG_EDIT = "hasAuthority('ROLE_system:user:configEdit')";
public static final String USER_RESOURCE_INFO = "hasAuthority('ROLE_system:user:resourceInfo')";
public static final String USER_RESET_PASSWORD = "hasAuthority('ROLE_system:user:resetPassword')";

/**
* 控制台:角色管理
@@ -203,6 +207,13 @@ public final class Permissions {
public static final String SPECS_DELETE = "hasAuthority('ROLE_system:specs:delete')";

/**
* 控制台:GPU资源管理
*/
public static final String GPU_CREATE = "hasAuthority('ROLE_system:gpu:create')";
public static final String GPU_EDIT = "hasAuthority('ROLE_system:gpu:edit')";
public static final String GPU_DELETE = "hasAuthority('ROLE_system:gpu:delete')";

/**
* 专业版:终端
*/
public static final String TERMINAL_CREATE = "hasAuthority('ROLE_terminal:specs:create')";
@@ -211,6 +222,8 @@ public final class Permissions {
public static final String TERMINAL_DELETE = "hasAuthority('ROLE_terminal:specs:delete')";
public static final String TERMINAL_DETAIL = "hasAuthority('ROLE_terminal:specs:detail')";
public static final String TERMINAL_LIST = "hasAuthority('ROLE_terminal:specs:list')";
public static final String TERMINAL_UPDATE = "hasAuthority('ROLE_terminal:specs:update')";


private Permissions() {
}


+ 45
- 4
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/constant/StringConstant.java View File

@@ -30,7 +30,7 @@ public final class StringConstant {
public static final String REQUEST_METHOD_GET = "GET";

/**
* 字母、数字、英文横杠和下划线匹配
* 字母、数字、汉字、英文横杠和下划线匹配
*/
public static final String REGEXP_NAME = "^[a-zA-Z0-9\\-\\_\\u4e00-\\u9fa5]+$";

@@ -50,9 +50,42 @@ public final class StringConstant {
public static final String REGEXP_SPECS = "^[a-zA-Z0-9\\-\\_\\s\\u4e00-\\u9fa5]+$";

/**
* GPU类型支持字母、数字、汉字、英文横杠、英文.号、空白字符和英文斜杠
*/
public static final String REGEXP_GPU_TYPE = "^[a-zA-Z0-9\\-\\.\\s\\/\\u4e00-\\u9fa5]+$";

/**
* GPU型号支持小写字母、数字、英文横杠、英文.号和英文斜杠
*/
public static final String REGEXP_GPU_MODEL = "^[a-z0-9\\-\\.\\/]+$";

/**
* k8s GPU资源名称支持小写字母、数字、英文横杠、英文.号和英文斜杠
*/
public static final String REGEXP_K8S = "^[a-z0-9\\-\\.\\/]+$";

/**
* 整数匹配
*/
public static final Pattern PATTERN_NUM = Pattern.compile("^[-\\+]?[\\d]*$");
/**
* 数字匹配
*/
public static final String NUMBER ="(\\d+)";
/**
* 整数匹配
*/
public static final Pattern PATTERN_NUMBER = Pattern.compile("(\\d+)");
/**
* 小数匹配
*/
public static final Pattern PATTERN_DECIMAL = Pattern.compile("(\\d+\\.\\d+)");


/**
* 描述内容支持字母、数字、汉字、英文横杠和下划线
*/
public static final String REGEXP_DESCRIPTION = "^[a-zA-Z0-9\\-\\_\\u4e00-\\u9fa5]+$";


/**
@@ -80,7 +113,7 @@ public final class StringConstant {
public static final String K8S_CALLBACK_PATH_DEPLOYMENT = "/api/k8s/callback/deployment";
public static final String MULTIPART = "multipart/form-data";

public static final String PIP_SITE_PACKAGE ="pip-site-package";
public static final String PIP_SITE_PACKAGE = "pip-site-package";

/**
* 分页内容
@@ -106,12 +139,20 @@ public final class StringConstant {
public static final String START_LOW = "start";
public static final String END_LOW = "end";
public static final String STEP_LOW = "step";
//1024*1024*1024
public static final String MEM_UNIT = "1073741824";

/**
* 任务缓存
*/
public static final String CACHE_TASK_ID ="task_id";
public static final String CACHE_TASK_NAME ="task_name";
public static final String CACHE_TASK_ID = "task_id";
public static final String CACHE_TASK_NAME = "task_name";


/**
* python命令行参数格式
*/
public static final String PYTHON_COMMAND_PATTERN = " --%s=%s";


private StringConstant() {


+ 2
- 0
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/constant/SymbolConstant.java View File

@@ -27,8 +27,10 @@ public class SymbolConstant {
public static final String COLON = ":";
public static final String LINEBREAK = "\n";
public static final String BLANK = "";
public static final String SPACE = " ";
public static final String QUESTION = "?";
public static final String ZERO = "0";
public static final String ONE = "1";
public static final String DOT = ".";
public static final String TOKEN = "token";
public static final String GET = "get";


+ 15
- 0
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/constant/UserConstant.java View File

@@ -101,4 +101,19 @@ public class UserConstant {
*/
public final static Long DEFAULT_CREATE_USER_ID = 0L;

/**
* namespace前缀
*/
public final static String NAMESPACE_PREFIX = "namespace-";

/**
* 查询7d内的用户资源用量
*/
public final static String UNIT_7D = "7d";

/**
* 查询15d内的用户资源用量
*/
public final static String UNIT_15D = "15d";

}

+ 38
- 0
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/DeleteDTO.java View File

@@ -0,0 +1,38 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/

package org.dubhe.biz.base.dto;

import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;
import java.util.Set;

/**
* @description 删除用数据包
* @date 2020-03-15
*/
@Getter
@Setter
public class DeleteDTO implements Serializable {

private static final long serialVersionUID = 1L;

private Set<Long> ids;

}

+ 45
- 0
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/GpuConfigDTO.java View File

@@ -0,0 +1,45 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.biz.base.dto;

import lombok.Data;
import lombok.experimental.Accessors;

import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.List;

/**
* @description 用户配置DTO
* @date 2021-09-06
*/
@Data
@Accessors(chain = true)
public class GpuConfigDTO implements Serializable {
private static final long serialVersionUID = 1L;

/**
* 用户 ID
*/
@NotNull(message = "用户 ID 不能为空")
private Long userId;

/**
* GPU 资源限制
*/
private List<SysUserGpuConfigDTO> gpuResources;
}

+ 2
- 1
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/ModelOptAlgorithmCreateDTO.java View File

@@ -18,6 +18,7 @@ package org.dubhe.biz.base.dto;

import lombok.Data;
import lombok.experimental.Accessors;
import org.dubhe.biz.base.constant.MagicNumConstant;
import org.dubhe.biz.base.constant.NumberConstant;
import org.dubhe.biz.base.constant.StringConstant;
import org.hibernate.validator.constraints.Length;
@@ -42,7 +43,7 @@ public class ModelOptAlgorithmCreateDTO implements Serializable {
private String name;

@NotBlank(message = "代码目录不能为空")
@Length(max = NumberConstant.NUMBER_64, message = "代码目录-输入长度不能超过128个字符")
@Length(max = MagicNumConstant.ONE_HUNDRED_TWENTY_EIGHT, message = "代码目录-输入长度不能超过128个字符")
private String path;

}

+ 38
- 0
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/NamespaceDeleteDTO.java View File

@@ -0,0 +1,38 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.biz.base.dto;

import lombok.Data;
import lombok.experimental.Accessors;

import javax.validation.constraints.NotEmpty;
import java.io.Serializable;
import java.util.Set;

/**
* @description 命名空间删除DTO
* @date 2021-11-29
*/
@Data
@Accessors(chain = true)
public class NamespaceDeleteDTO implements Serializable {

private static final long serialVersionUID = 1L;

@NotEmpty(message = "id不能为空")
Set<Long> ids;
}

+ 2
- 0
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/PtImageQueryUrlDTO.java View File

@@ -37,4 +37,6 @@ public class PtImageQueryUrlDTO {

private Integer projectType;

private Long id;

}

+ 2
- 2
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/QueryResourceSpecsDTO.java View File

@@ -45,10 +45,10 @@ public class QueryResourceSpecsDTO implements Serializable {
private String specsName;

/**
* 所属业务场景(0:通用,1:dubhe-notebook,2:dubhe-train,3:dubhe-serving)
* 所属业务场景(0:通用,1:dubhe-notebook,2:dubhe-train,3:dubhe-serving,4:dubhe-tadl,5:dubhe-optimize)
*/
@NotNull(message = "所属业务场景不能为空")
@Min(value = MagicNumConstant.ZERO, message = "所属业务场景错误")
@Max(value = MagicNumConstant.THREE, message = "所属业务场景错误")
@Max(value = MagicNumConstant.FIVE, message = "所属业务场景错误")
private Integer module;
}

+ 121
- 0
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/QueryUserK8sResourceDTO.java View File

@@ -0,0 +1,121 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.biz.base.dto;

import lombok.Data;
import lombok.experimental.Accessors;
import org.dubhe.biz.base.constant.MagicNumConstant;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.List;

/**
* @description 用户k8s可用资源查询实体类
* @date 2021-09-10
*/
@Data
@Accessors(chain = true)
public class QueryUserK8sResourceDTO implements Serializable {

private static final long serialVersionUID = 1L;

@NotNull(message = "用户 ID 不能为空")
private Long userId;

@NotNull(message = "节点个数")
private Integer resourcesPoolNode;

/**
* GPU型号(例如:v100)
*/
private String gpuModel;

/**
*k8s GPU资源标签key值(例如:nvidia.com/gpu)
*/
private String k8sLabelKey;


/**
* 主键ID
*/
@NotNull(message = "主键ID")
private Long id;

/**
*规格名称
*/
private String specsName;

/**
*规格类型(0为CPU, 1为GPU)
*/
@NotNull(message = "规格类型(0为CPU, 1为GPU)")
private Boolean resourcesPoolType;

/**
*所属业务场景(0:通用,1:dubhe-notebook,2:dubhe-train,3:dubhe-serving,4:dubhe-tadl)
*/
private Integer module;

/**
*CPU数量,单位:核
*/
@NotNull(message = "CPU数量,单位:核")
private Integer cpuNum;

/**
*GPU数量,单位:核
*/
@NotNull(message = "GPU数量,单位:核")
private Integer gpuNum;

/**
*内存大小,单位:M
*/
@NotNull(message = "内存大小,单位:M")
private Integer memNum;

/**
*工作空间的存储配额,单位:M
*/
private Integer workspaceRequest;

/**
*创建人
*/
private Long createUserId;

/**
*创建时间
*/
private Timestamp createTime;

/**
*更新人
*/
private Long updateUserId;

/**
*更新时间
*/
private Timestamp updateTime;
}

+ 43
- 0
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/ResourceQuotaDTO.java View File

@@ -0,0 +1,43 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/

package org.dubhe.biz.base.dto;

import lombok.Data;

import javax.validation.constraints.NotNull;
import java.util.Map;

/**
* @description k8s节点资源隔离DTO
* @date 2021-07-21
*/
@Data
public class ResourceQuotaDTO {

@NotNull(message = "用户 ID 不能为空")
private Long userId;

@NotNull(message = "CPU 资源限制配置不能为空")
private Integer cpuLimit;

@NotNull(message = "内存资源限制配置不能为空")
private Integer memoryLimit;

@NotNull(message = "GPU 资源限制配置不能为空")
private Map<String, Integer> gpuLimit;
}

+ 9
- 3
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/SysUserConfigDTO.java View File

@@ -18,7 +18,9 @@ package org.dubhe.biz.base.dto;

import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.util.List;

/**
* @description 系统用户配置 DTO
@@ -26,7 +28,7 @@ import java.io.Serializable;
*/
@Data
@Accessors(chain = true)
public class SysUserConfigDTO implements Serializable{
public class SysUserConfigDTO implements Serializable {

private static final long serialVersionUID = 1L;

@@ -46,8 +48,12 @@ public class SysUserConfigDTO implements Serializable{
private Integer memoryLimit;

/**
* GPU 资源限制配置
* GPU 资源限制
*/
private Integer gpuLimit;
private List<SysUserGpuConfigDTO> gpuResources;

/**
* 用户默认镜像
*/
private Long defaultImageId;
}

+ 52
- 0
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/SysUserGpuConfigDTO.java View File

@@ -0,0 +1,52 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.biz.base.dto;

import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;

/**
* @description 系统用户GPU配置 DTO
* @date 2021-09-03
*/
@Data
@Accessors(chain = true)
public class SysUserGpuConfigDTO implements Serializable {
private static final long serialVersionUID = 1L;

/**
* GPU类型(例如:NVIDIA)
*/
private String gpuType;

/**
* GPU型号(例如:v100)
*/
private String gpuModel;

/**
* k8s GPU资源标签key值(例如:nvidia.com/gpu)
*/
private String k8sLabelKey;

/**
* GPU 资源限制配置不能为空
*/
private Integer gpuLimit;
}

+ 50
- 0
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/UserConfigSaveDTO.java View File

@@ -0,0 +1,50 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.biz.base.dto;

import lombok.Data;
import lombok.experimental.Accessors;

import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.List;

/**
* @description 用户配置DTO
* @date 2021-7-1
*/
@Data
@Accessors(chain = true)
public class UserConfigSaveDTO implements Serializable {
private static final long serialVersionUID = 1L;

@NotNull(message = "用户 ID 不能为空")
private Long userId;

@NotNull(message = "Notebook 延迟删除时间配置不能为空")
private Integer notebookDelayDeleteTime;

@NotNull(message = "CPU 资源限制配置不能为空")
private Integer cpuLimit;

@NotNull(message = "内存资源限制配置不能为空")
private Integer memoryLimit;

private Long defaultImageId;

private List<UserGpuConfigDTO> gpuResources;
}

+ 2
- 0
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/UserDTO.java View File

@@ -45,6 +45,8 @@ public class UserDTO implements Serializable {

private String remark;

private String userGroupName;

private Date lastPasswordResetTime;

private Timestamp createTime;


+ 46
- 0
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/dto/UserGpuConfigDTO.java View File

@@ -0,0 +1,46 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
package org.dubhe.biz.base.dto;

import lombok.Data;
import lombok.experimental.Accessors;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;

/**
* @description 用户GPU配置DTO
* @date 2021-7-1
*/
@Data
@Accessors(chain = true)
public class UserGpuConfigDTO implements Serializable {
private static final long serialVersionUID = 1L;

@NotBlank(message = "GPU类型")
private String gpuType;

@NotBlank(message = "GPU型号")
private String gpuModel;

@NotBlank(message = "k8s GPU资源标签key值")
private String k8sLabelKey;

@NotNull(message = "GPU 资源限制配置不能为空")
private Integer gpuLimit;
}

+ 1
- 1
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/enums/BaseErrorCodeEnum.java View File

@@ -43,7 +43,7 @@ public enum BaseErrorCodeEnum implements ErrorCode {
SYSTEM_USER_ALREADY_REGISTER(20003, "账号已注册!"),
SYSTEM_USER_REGISTER_EMAIL_INFO_EXPIRED(20004, "邮箱验证码已过期!"),
SYSTEM_USER_EMAIL_ALREADY_EXISTS(20004, "该邮箱已被注册!"),
SYSTEM_USER_EMAIL_PASSWORD_ERROR(20005, "邮件密码错误!"),
SYSTEM_USER_EMAIL_PASSWORD_ERROR(20005, "密码错误!"),
SYSTEM_USER_EMAIL_CODE_CANNOT_EXCEED_TIMES(20006, "邮件发送不能超过三次!"),
SYSTEM_USER_EMAIL_OR_CODE_ERROR(20007, "邮箱地址或验证码错误、请重新输入!"),
SYSTEM_USER_IS_LOCKED(20008, "用户已锁定!"),


+ 4
- 1
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/enums/BizEnum.java View File

@@ -61,7 +61,10 @@ public enum BizEnum {
* 专业版终端
*/
TERMINAL("专业版终端", "terminal", 7),
;
/**
* TADL
*/
TADL("TADL服务", "tadl", 8);

/**
* 业务模块名称


+ 6
- 5
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/utils/AesUtil.java View File

@@ -35,8 +35,9 @@ public class AesUtil {

private static final String AES = "AES";

public static final String RESOURCE_KYE = "123456";

private AesUtil(){
private AesUtil() {

}

@@ -50,7 +51,7 @@ public class AesUtil {
* @throws NoSuchPaddingException
* @throws InvalidKeyException
*/
private static Cipher getCipher(int mode,String key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
private static Cipher getCipher(int mode, String key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
MessageDigest md5Digest = MessageDigest.getInstance("MD5");
SecretKeySpec secretKeySpec = new SecretKeySpec(md5Digest.digest(key.getBytes(StandardCharsets.UTF_8)), AES);
Cipher cipher = Cipher.getInstance(AES);
@@ -67,7 +68,7 @@ public class AesUtil {
*/
public static String encrypt(String data, String key) {
try {
Cipher cipher = getCipher(Cipher.ENCRYPT_MODE,key);
Cipher cipher = getCipher(Cipher.ENCRYPT_MODE, key);
byte[] content = data.getBytes(StandardCharsets.UTF_8);
return new String(HexUtil.encodeHex(cipher.doFinal(content), false));
} catch (Exception e) {
@@ -79,11 +80,11 @@ public class AesUtil {
* 解密
* @param hexData 十六进制密文
* @param key 秘钥
* @return String 密文
* @return String 密文
*/
public static String decrypt(String hexData, String key) {
try {
Cipher cipher = getCipher(Cipher.DECRYPT_MODE,key);
Cipher cipher = getCipher(Cipher.DECRYPT_MODE, key);
byte[] content = HexUtil.decodeHex(hexData);
return new String(cipher.doFinal(content), StandardCharsets.UTF_8);
} catch (Exception e) {


+ 44
- 0
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/utils/CommandUtil.java View File

@@ -0,0 +1,44 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/

package org.dubhe.biz.base.utils;

import com.alibaba.fastjson.JSONObject;

import static org.dubhe.biz.base.constant.StringConstant.PYTHON_COMMAND_PATTERN;

/**
* @description 命令行工具类
* @date 2021-09-22
*/
public class CommandUtil {
/**
* 构造python运行命令
*
* @param runCommand
* @param runParams
* @return
*/
public static String buildPythonCommand(String runCommand, JSONObject runParams) {
StringBuilder sb = new StringBuilder();
sb.append(runCommand);
if (null != runParams && !runParams.isEmpty()) {
runParams.forEach((k, v) -> sb.append(String.format(PYTHON_COMMAND_PATTERN, k, v)));
}
return sb.toString();
}
}

+ 21
- 0
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/utils/DateUtil.java View File

@@ -19,6 +19,7 @@ package org.dubhe.biz.base.utils;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
@@ -125,4 +126,24 @@ public class DateUtil {

return Timestamp.valueOf(sdf.format(calendar.getTime()));
}

/**
* CST时间转换成UTC Date String
* 输入:2021-11-17T08:50:23Z
* 返回:2021-11-17 16:50:23
*
* @param time
* @return
* @throws ParseException
*/
public static String convertCST2UTCDate(String time) throws ParseException {
SimpleDateFormat parseFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
Date dateTime = parseFormat.parse(time);

Calendar calendar = Calendar.getInstance();
calendar.setTime(dateTime);
calendar.set(Calendar.HOUR,calendar.get(Calendar.HOUR) + 8);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return simpleDateFormat.format(calendar.getTime());
}
}

+ 39
- 0
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/utils/MapUtil.java View File

@@ -0,0 +1,39 @@
/**
* Copyright 2020 Tianshu AI Platform. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/


package org.dubhe.biz.base.utils;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;

import java.util.HashMap;
import java.util.Map;

/**
* @description Map工具类
* @date 2021-09-22
*/
public class MapUtil {
public static Map<String, String> convertJsonObject(JSONObject object) {
if (object == null) {
return new HashMap<>();
}
return JSONObject.parseObject(object.toJSONString(),
new TypeReference<Map<String, String>>(){});
}
}

+ 1
- 0
dubhe-server/common-biz/base/src/main/java/org/dubhe/biz/base/utils/MathUtils.java View File

@@ -72,4 +72,5 @@ public class MathUtils {
return Float.valueOf(num1) / Float.valueOf(num2);
}
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save