Browse Source

开发服务功能

dev-lhz
chenzhihang 1 year ago
parent
commit
8392a62979
8 changed files with 579 additions and 18 deletions
  1. +87
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/service/ServiceController.java
  2. +36
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/Service.java
  3. +48
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ServiceVersion.java
  4. +32
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/mapper/ServiceDao.java
  5. +30
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ServiceService.java
  6. +117
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ServiceServiceImpl.java
  7. +95
    -18
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java
  8. +134
    -0
      ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ServiceDaoMapper.xml

+ 87
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/service/ServiceController.java View File

@@ -0,0 +1,87 @@
package com.ruoyi.platform.controller.service;

import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.GenericsAjaxResult;
import com.ruoyi.platform.domain.Service;
import com.ruoyi.platform.domain.ServiceVersion;
import com.ruoyi.platform.service.ServiceService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.io.IOException;

@RestController
@RequestMapping("service")
@Api("服务")
public class ServiceController extends BaseController {
@Resource
private ServiceService serviceService;


@GetMapping
@ApiOperation("分页查询服务列表")
public GenericsAjaxResult<Page<Service>> queryByPageService(Service service, int page, int size) throws IOException {
PageRequest pageRequest = PageRequest.of(page, size);
return genericsSuccess(serviceService.queryByPageService(service, pageRequest));
}

@GetMapping("/serviceVersion")
@ApiOperation("分页查询服务版本列表")
public GenericsAjaxResult<Page<ServiceVersion>> queryByPageServiceVersion(ServiceVersion serviceVersion, int page, int size) throws IOException {
PageRequest pageRequest = PageRequest.of(page, size);
return genericsSuccess(serviceService.queryByPageServiceVersion(serviceVersion, pageRequest));
}

@PostMapping
@ApiOperation("新增服务")
public GenericsAjaxResult<Service> addService(@RequestBody Service service) {
return genericsSuccess(serviceService.addService(service));
}

@PostMapping("/serviceVersion")
@ApiOperation("新增服务版本")
public GenericsAjaxResult<ServiceVersion> addServiceVersion(@RequestBody ServiceVersion serviceVersion) {
return genericsSuccess(serviceService.addServiceVersion(serviceVersion));
}

@PutMapping
@ApiOperation("编辑服务")
public GenericsAjaxResult<Service> editService(@RequestBody Service service) {
return genericsSuccess(serviceService.editService(service));
}

@PutMapping("/serviceVersion")
@ApiOperation("编辑服务版本")
public GenericsAjaxResult<ServiceVersion> editServiceVersion(@RequestBody ServiceVersion serviceVersion) {
return genericsSuccess(serviceService.editServiceVersion(serviceVersion));
}

@GetMapping("/serviceVersionDetail/{id}")
@ApiOperation("查询服务版本详细信息")
public GenericsAjaxResult<ServiceVersion> getServiceVersion(@PathVariable("id") Long id) {
return genericsSuccess(serviceService.getServiceVersion(id));
}

@DeleteMapping("{id}")
@ApiOperation("删除服务")
public GenericsAjaxResult<String> deleteService(@PathVariable("id") Long id){
return genericsSuccess(serviceService.deleteService(id));
}

@DeleteMapping("/serviceVersion/{id}")
@ApiOperation("删除服务版本")
public GenericsAjaxResult<String> deleteServiceVersion(@PathVariable("id") Long id){
return genericsSuccess(serviceService.deleteServiceVersion(id));
}

@GetMapping("/runServiceVersion/{id}")
@ApiOperation("启动服务版本")
public GenericsAjaxResult<String> runServiceVersion(@PathVariable("id") Long id){
serviceService.runServiceVersion(id);
return genericsSuccess("");
}
}

+ 36
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/Service.java View File

@@ -0,0 +1,36 @@
package com.ruoyi.platform.domain;

import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import io.swagger.annotations.ApiModel;
import lombok.Data;

import java.io.Serializable;
import java.util.Date;

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
@ApiModel("服务")
@Data
public class Service implements Serializable {
private Long id;

private String serviceName;

private Integer serviceType;

private String description;

private String createBy;

private String updateBy;

private Date createTime;

private Date updateTime;

private Integer state;

@TableField(exist = false)
private Integer versionCount;
}

+ 48
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ServiceVersion.java View File

@@ -0,0 +1,48 @@
package com.ruoyi.platform.domain;

import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import io.swagger.annotations.ApiModel;
import lombok.Data;

import java.io.Serializable;
import java.util.Date;

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
@ApiModel("服务")
@Data
public class ServiceVersion implements Serializable {
private Long id;

private Long serviceId;

private String version;

private String model;

private String image;

private String resource;

private Integer replicas;

private String mountPath;

private String envVariables;

private String codeConfig;

private String command;

private String url;

private String createBy;

private String updateBy;

private Date createTime;

private Date updateTime;

private Integer state;
}

+ 32
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/mapper/ServiceDao.java View File

@@ -0,0 +1,32 @@
package com.ruoyi.platform.mapper;

import com.ruoyi.platform.domain.Service;
import com.ruoyi.platform.domain.ServiceVersion;
import org.apache.ibatis.annotations.Param;
import org.springframework.data.domain.Pageable;

import java.util.List;

public interface ServiceDao {

long countService(@Param("service") com.ruoyi.platform.domain.Service service);

long countServiceVersion(@Param("serviceVersion") ServiceVersion serviceVersion);

List<Service> queryByPageService(@Param("service") com.ruoyi.platform.domain.Service service, @Param("pageable") Pageable pageable);

List<ServiceVersion> queryByPageServiceVersion(@Param("serviceVersion") ServiceVersion serviceVersion, @Param("pageable") Pageable pageable);

int insertService(@Param("service") com.ruoyi.platform.domain.Service service);

int insertServiceVersion(@Param("serviceVersion") ServiceVersion serviceVersion);

int updateService(@Param("service") Service service);

int updateServiceVersion(@Param("serviceVersion") ServiceVersion serviceVersion);

Service getServiceById(Long id);

ServiceVersion getServiceVersionById(Long id);

}

+ 30
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ServiceService.java View File

@@ -0,0 +1,30 @@
package com.ruoyi.platform.service;

import com.ruoyi.platform.domain.Service;
import com.ruoyi.platform.domain.ServiceVersion;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;

import java.io.IOException;

public interface ServiceService {
Page<Service> queryByPageService(Service service, PageRequest pageRequest) throws IOException;

Page<ServiceVersion> queryByPageServiceVersion(ServiceVersion serviceVersion, PageRequest pageRequest) throws IOException;

Service addService(Service service);

ServiceVersion addServiceVersion(ServiceVersion serviceVersion);

Service editService(Service service);

ServiceVersion editServiceVersion(ServiceVersion serviceVersion);

ServiceVersion getServiceVersion(Long id);

String deleteService(Long id);

String deleteServiceVersion(Long id);

void runServiceVersion(Long id);
}

+ 117
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ServiceServiceImpl.java View File

@@ -0,0 +1,117 @@
package com.ruoyi.platform.service.impl;

import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.platform.constant.Constant;
import com.ruoyi.platform.domain.ServiceVersion;
import com.ruoyi.platform.mapper.ServiceDao;
import com.ruoyi.platform.service.ServiceService;
import com.ruoyi.system.api.model.LoginUser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;

@Service("serviceService")
public class ServiceServiceImpl implements ServiceService {

@Resource
private ServiceDao serviceDao;

@Override
public Page<com.ruoyi.platform.domain.Service> queryByPageService(com.ruoyi.platform.domain.Service service, PageRequest pageRequest) throws IOException {
long total = serviceDao.countService(service);
List<com.ruoyi.platform.domain.Service> services = serviceDao.queryByPageService(service, pageRequest);
return new PageImpl<>(services, pageRequest, total);
}

@Override
public Page<ServiceVersion> queryByPageServiceVersion(ServiceVersion serviceVersion, PageRequest pageRequest) throws IOException {
long total = serviceDao.countServiceVersion(serviceVersion);
List<ServiceVersion> serviceVersions = serviceDao.queryByPageServiceVersion(serviceVersion, pageRequest);
return new PageImpl<>(serviceVersions, pageRequest, total);
}

@Override
public com.ruoyi.platform.domain.Service addService(com.ruoyi.platform.domain.Service service) {
LoginUser loginUser = SecurityUtils.getLoginUser();
service.setCreateBy(loginUser.getUsername());
service.setUpdateBy(loginUser.getUsername());
serviceDao.insertService(service);
return service;
}

@Override
public ServiceVersion addServiceVersion(ServiceVersion serviceVersion) {
LoginUser loginUser = SecurityUtils.getLoginUser();
serviceVersion.setCreateBy(loginUser.getUsername());
serviceVersion.setUpdateBy(loginUser.getUsername());
serviceDao.insertServiceVersion(serviceVersion);
return serviceVersion;
}

@Override
public com.ruoyi.platform.domain.Service editService(com.ruoyi.platform.domain.Service service) {
LoginUser loginUser = SecurityUtils.getLoginUser();
service.setUpdateBy(loginUser.getUsername());
serviceDao.updateService(service);
return serviceDao.getServiceById(service.getId());
}

@Override
public ServiceVersion editServiceVersion(ServiceVersion serviceVersion) {
LoginUser loginUser = SecurityUtils.getLoginUser();
serviceVersion.setUpdateBy(loginUser.getUsername());
serviceDao.updateServiceVersion(serviceVersion);
return serviceDao.getServiceVersionById(serviceVersion.getId());
}

@Override
public ServiceVersion getServiceVersion(Long id) {
return serviceDao.getServiceVersionById(id);
}

@Override
public String deleteService(Long id) {
com.ruoyi.platform.domain.Service service = serviceDao.getServiceById(id);
if (service == null) {
return "服务不存在";
}

LoginUser loginUser = SecurityUtils.getLoginUser();
String username = loginUser.getUsername();
String createBy = service.getCreateBy();
if (!(StringUtils.equals(username, "admin") || StringUtils.equals(username, createBy))) {
return "无权限删除该服务";
}

ServiceVersion serviceVersion = new ServiceVersion();
serviceVersion.setServiceId(id);
long versionCount = serviceDao.countServiceVersion(serviceVersion);
if (versionCount != 0) {
return "该服务下还有版本,不能删除";
}

service.setState(Constant.State_invalid);
return serviceDao.updateService(service) > 0 ? "删除成功" : "删除失败";
}

@Override
public String deleteServiceVersion(Long id) {
ServiceVersion serviceVersion = serviceDao.getServiceVersionById(id);
serviceVersion.setState(Constant.State_invalid);
return serviceDao.updateServiceVersion(serviceVersion) > 0 ? "删除成功" : "删除失败";
}

@Override
public void runServiceVersion(Long id) {
ServiceVersion serviceVersion = serviceDao.getServiceVersionById(id);



}
}

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

@@ -1,5 +1,6 @@
package com.ruoyi.platform.utils; package com.ruoyi.platform.utils;


import com.alibaba.fastjson2.JSON;
import com.ruoyi.platform.constant.Constant; import com.ruoyi.platform.constant.Constant;
import com.ruoyi.platform.domain.DevEnvironment; import com.ruoyi.platform.domain.DevEnvironment;
import com.ruoyi.platform.mapper.ComputingResourceDao; import com.ruoyi.platform.mapper.ComputingResourceDao;
@@ -8,6 +9,7 @@ import io.kubernetes.client.custom.IntOrString;
import io.kubernetes.client.custom.Quantity; import io.kubernetes.client.custom.Quantity;
import io.kubernetes.client.openapi.ApiClient; import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.ApiException; import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.apis.AppsV1Api;
import io.kubernetes.client.openapi.apis.CoreV1Api; import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.*; import io.kubernetes.client.openapi.models.*;
import io.kubernetes.client.util.ClientBuilder; import io.kubernetes.client.util.ClientBuilder;
@@ -471,24 +473,7 @@ public class K8sClientUtil {




//配置资源 //配置资源
JSONObject standardJson = new JSONObject(devEnvironment.getStandard());
JSONObject valueJson = (JSONObject) standardJson.get("value");
int cpu = (int) valueJson.get("cpu");
String memory = (String) valueJson.get("memory");
memory = memory.substring(0, memory.length() - 1).concat("i");
int gpu = (int) valueJson.get("gpu");

HashMap<String, Quantity> limitMap = new HashMap<>();
if (Constant.Computing_Resource_GPU.equals(devEnvironment.getComputingResource())) {
limitMap.put("nvidia.com/gpu", new Quantity(String.valueOf(gpu)));
}
limitMap.put("cpu", new Quantity(String.valueOf(cpu)));
limitMap.put("memory", new Quantity(memory));
limitMap.put("ephemeral-storage", new Quantity("100Gi"));

V1ResourceRequirements v1ResourceRequirements = new V1ResourceRequirements();
v1ResourceRequirements.setRequests(limitMap);
v1ResourceRequirements.setLimits(limitMap);
V1ResourceRequirements v1ResourceRequirements = setPodResource(devEnvironment.getStandard());


V1Pod pod = new V1PodBuilder() V1Pod pod = new V1PodBuilder()
.withNewMetadata() .withNewMetadata()
@@ -674,6 +659,98 @@ public class K8sClientUtil {
return pod; return pod;
} }



public Integer createDeployment(String dpName, String namespace, Integer replicas, String model, String image, Integer port, String resource, String mountPath
, String envVariables, String codeConfig) {
AppsV1Api api = new AppsV1Api(apiClient);

//配置标签选择
HashMap<String, String> selector = new HashMap<>();
selector.put("app", dpName);

//配置资源
V1ResourceRequirements v1ResourceRequirements = setPodResource(resource);

//配置环境变量
List<V1EnvVar> env = new ArrayList<>();
if (StringUtils.isNotEmpty(envVariables)) {
HashMap<String, String> envMap = JSON.parseObject(envVariables, HashMap.class);
for (String key : envMap.keySet()) {
V1EnvVar envVar = new V1EnvVar().name(key).value(envMap.get(key));
env.add(envVar);
}
}

// 配置卷和卷挂载
// List<V1VolumeMount> volumeMounts = new ArrayList<>();
// volumeMounts.add(new V1VolumeMount().name("workspace").mountPath(mountPath));
// volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/opt/code").subPath(codeConfig).readOnly(true));
// volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/opt/model").subPath(model).readOnly(true));
//
// List<V1Volume> volumes = new ArrayList<>();
// volumes.add(new V1Volume().name("workspace").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvc.getMetadata().getName())));
// volumes.add(new V1Volume().name("minio-pvc").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(dataPvcName)));


//创建deployment
V1Deployment deployment = new V1DeploymentBuilder().withNewMetadata()
.withName(dpName)
.endMetadata()
.withNewSpec()
.withReplicas(replicas)
.withSelector(new V1LabelSelector().matchLabels(selector))
.withNewTemplate()
.withNewMetadata()
.addToLabels("app", dpName)
.endMetadata()
.withNewSpec()
.addNewContainer()
.withName(dpName)
.withImage(image)
.withEnv(env)
.withPorts(new V1ContainerPort().containerPort(port).protocol("TCP"))
.withResources(v1ResourceRequirements)
.endContainer()
.endSpec()
.endTemplate()
.endSpec()
.build();

try {
api.createNamespacedDeployment(namespace, deployment, null, null, null);
} catch (ApiException e) {
throw new RuntimeException("创建deployment异常:" + e.getResponseBody());
}

V1Service service = createService(namespace, dpName + "-svc", port, selector);
return service.getSpec().getPorts().get(0).getNodePort();
}


V1ResourceRequirements setPodResource(String resource) {
//配置pod资源
JSONObject standardJson = new JSONObject(resource);
JSONObject valueJson = (JSONObject) standardJson.get("value");
int cpu = (int) valueJson.get("cpu");
String memory = (String) valueJson.get("memory");
memory = memory.substring(0, memory.length() - 1).concat("i");
Integer gpu = (Integer) valueJson.get("gpu");

HashMap<String, Quantity> limitMap = new HashMap<>();
if (gpu != null && gpu != 0) {
limitMap.put("nvidia.com/gpu", new Quantity(String.valueOf(gpu)));
}
limitMap.put("cpu", new Quantity(String.valueOf(cpu)));
limitMap.put("memory", new Quantity(memory));
limitMap.put("ephemeral-storage", new Quantity("100Gi"));

V1ResourceRequirements v1ResourceRequirements = new V1ResourceRequirements();
v1ResourceRequirements.setRequests(limitMap);
v1ResourceRequirements.setLimits(limitMap);

return v1ResourceRequirements;
}

/** /**
* 删除 Pod * 删除 Pod
* *


+ 134
- 0
ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ServiceDaoMapper.xml View File

@@ -0,0 +1,134 @@
<?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="com.ruoyi.platform.mapper.ServiceDao">
<select id="countService" resultType="java.lang.Long">
select count(1) from service
<where>
state = 1
<if test="service.serviceName != null and service.serviceName != ''">
and service_name like concat('%', #{service.serviceName}, '%')
</if>
<if test="service.serviceType != null">
and service_type = #{service.serviceType}
</if>
</where>
</select>

<select id="queryByPageService" resultType="com.ruoyi.platform.domain.Service">
select a.*,count(b.id) as version_count from service a
left join (select * from service_version where state = 1) b on a.id = b.service_id
<where>
a.state = 1
<if test="service.serviceName != null and service.serviceName != ''">
and a.service_name like concat('%', #{service.serviceName}, '%')
</if>
<if test="service.serviceType != null">
and a. = #{service.serviceType}
</if>
</where>
group by a.id
order by a.update_time DESC
limit #{pageable.offset}, #{pageable.pageSize}
</select>

<select id="countServiceVersion" resultType="java.lang.Long">
select count(1) from
( <include refid="queryServiceVersion"></include> ) t
</select>

<select id="queryByPageServiceVersion" resultType="com.ruoyi.platform.domain.ServiceVersion">
<include refid="queryServiceVersion"></include>
limit #{pageable.offset}, #{pageable.pageSize}
</select>

<sql id="queryServiceVersion">
select * from service_version
<where>
state = 1
<if test="serviceVersion.version != null and serviceVersion.version !=''">
and version like concat('%', #{serviceVersion.version}, '%')
</if>
<if test="serviceVersion.serviceId != null and serviceVersion.serviceId !=''">
and service_id = #{serviceVersion.serviceId}
</if>
</where>
order by update_time DESC
</sql>

<select id="getServiceById" resultType="com.ruoyi.platform.domain.Service">
select *
from service
where id = #{id}
</select>

<select id="getServiceVersionById" resultType="com.ruoyi.platform.domain.ServiceVersion">
select *
from service_version
where id = #{id}
</select>

<insert id="insertService">
insert into service(service_name, service_type, description, create_by, update_by)
values (#{serviceName}, #{serviceType}, #{description}, #{createBy}, #{updateBy})
</insert>

<insert id="insertServiceVersion">
insert into service_version(service_id, version, model, image, resouce, replicas, mount_path, env_variables,
code_config, command, create_by, update_by)
values (#{serviceId}, #{version}, #{model}, #{image}, #{replicas}, #{mountPath}, #{envVariables},
#{codeConfig}, #{command}, #{createBy}, #{updateBy})
</insert>

<update id="updateService">
update service
<set>
<if test="service.serviceName != null and service.serviceName !=''">
service_name = #{service.serviceName}
</if>
<if test="service.serviceType != null">
service_type = #{service.serviceType}
</if>
<if test="service.description != null and service.description !=''">
description = #{service.description}
</if>
<if test="service.state != null">
state = #{service.state}
</if>
</set>
where id = #{service.id}
</update>

<update id="updateServiceVersion">
update service_version
<set>
<if test="serviceVersion.model != null and serviceVersion.model !=''">
model = #{serviceVersion.model},
</if>
<if test="serviceVersion.image != null and serviceVersion.image !=''">
image = #{serviceVersion.image},
</if>
<if test="serviceVersion.resouce != null and serviceVersion.resouce !=''">
resouce = #{serviceVersion.resouce},
</if>
<if test="serviceVersion.replicas != null">
replicas = #{serviceVersion.replicas},
</if>
<if test="serviceVersion.mountPath != null and serviceVersion.mountPath !=''">
mount_path = #{serviceVersion.mountPath},
</if>
<if test="serviceVersion.envVariables != null and serviceVersion.envVariables !=''">
env_variables = #{serviceVersion.envVariables},
</if>
<if test="serviceVersion.codeConfig != null and serviceVersion.codeConfig !=''">
code_config = #{serviceVersion.codeConfig},
</if>
<if test="serviceVersion.command != null and serviceVersion.command !=''">
command = #{serviceVersion.command},
</if>
<if test="serviceVersion.url != null and serviceVersion.url !=''">
url = #{serviceVersion.url},
</if>
</set>
where id = #{serviceVersion.id}
</update>
</mapper>

Loading…
Cancel
Save