@@ -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 | |||
@@ -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); | |||
@@ -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失败"); | |||
} | |||
} | |||
} |
@@ -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); | |||
} |
@@ -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); | |||
} |
@@ -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); | |||
} |
@@ -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); | |||
} |
@@ -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); | |||
} |
@@ -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"); | |||
} | |||
} |
@@ -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"); | |||
} | |||
} |
@@ -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"); | |||
} | |||
} |
@@ -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"); | |||
} | |||
} |
@@ -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"); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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"); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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); | |||
}; | |||
} | |||
} |
@@ -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> { | |||
} |
@@ -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); | |||
} |
@@ -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); | |||
} |
@@ -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); | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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"; | |||
} |
@@ -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; | |||
} |
@@ -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) | |||
@@ -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; | |||
} |
@@ -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数量,单位:核") | |||
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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()); | |||
@@ -41,7 +41,7 @@ public class EmailEventPublisher { | |||
* | |||
* @param dto | |||
*/ | |||
@Async("taskExecutor") | |||
@Async | |||
public void sentEmailEvent(final EmailDTO dto) { | |||
try { | |||
EmailEvent emailEvent = new EmailEvent(dto); | |||
@@ -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(); | |||
} | |||
} |
@@ -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) | |||
@@ -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)); | |||
} | |||
@@ -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(); | |||
} | |||
} |
@@ -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(); | |||
} | |||
} |
@@ -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)); | |||
} | |||
} |
@@ -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); | |||
} |
@@ -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); | |||
} |
@@ -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); | |||
} |
@@ -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); | |||
} |
@@ -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(); | |||
} |
@@ -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())); | |||
} | |||
//排序 | |||
@@ -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); | |||
} | |||
} |
@@ -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)); | |||
// 处理是一级菜单并且没有子菜单的情况 | |||
@@ -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); | |||
@@ -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) { | |||
@@ -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; | |||
} | |||
} |
@@ -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); | |||
}); | |||
} | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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 | |||
@@ -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> |
@@ -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> |
@@ -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> |
@@ -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)); | |||
} | |||
} |
@@ -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 | |||
@@ -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"; | |||
@@ -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 + "**" | |||
}; | |||
/** | |||
@@ -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; | |||
@@ -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; | |||
@@ -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() { | |||
} | |||
@@ -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() { | |||
@@ -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"; | |||
@@ -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"; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -37,4 +37,6 @@ public class PtImageQueryUrlDTO { | |||
private Integer projectType; | |||
private Long id; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -45,6 +45,8 @@ public class UserDTO implements Serializable { | |||
private String remark; | |||
private String userGroupName; | |||
private Date lastPasswordResetTime; | |||
private Timestamp createTime; | |||
@@ -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; | |||
} |
@@ -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, "用户已锁定!"), | |||
@@ -61,7 +61,10 @@ public enum BizEnum { | |||
* 专业版终端 | |||
*/ | |||
TERMINAL("专业版终端", "terminal", 7), | |||
; | |||
/** | |||
* TADL | |||
*/ | |||
TADL("TADL服务", "tadl", 8); | |||
/** | |||
* 业务模块名称 | |||
@@ -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) { | |||
@@ -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(); | |||
} | |||
} |
@@ -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()); | |||
} | |||
} |
@@ -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>>(){}); | |||
} | |||
} |
@@ -72,4 +72,5 @@ public class MathUtils { | |||
return Float.valueOf(num1) / Float.valueOf(num2); | |||
} | |||
} | |||
} |