| @@ -14,14 +14,14 @@ import com.ruoyi.platform.utils.FileUtil; | |||||
| import com.ruoyi.platform.utils.K8sClientUtil; | import com.ruoyi.platform.utils.K8sClientUtil; | ||||
| import com.ruoyi.platform.vo.ImageVo; | import com.ruoyi.platform.vo.ImageVo; | ||||
| import com.ruoyi.system.api.model.LoginUser; | import com.ruoyi.system.api.model.LoginUser; | ||||
| import io.kubernetes.client.openapi.models.V1PersistentVolumeClaim; | |||||
| import io.kubernetes.client.openapi.models.V1Pod; | import io.kubernetes.client.openapi.models.V1Pod; | ||||
| import lombok.Synchronized; | |||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
| import org.springframework.beans.BeanUtils; | |||||
| import org.springframework.beans.factory.annotation.Value; | import org.springframework.beans.factory.annotation.Value; | ||||
| import org.springframework.data.domain.Page; | import org.springframework.data.domain.Page; | ||||
| import org.springframework.data.domain.PageImpl; | import org.springframework.data.domain.PageImpl; | ||||
| import org.springframework.data.domain.PageRequest; | import org.springframework.data.domain.PageRequest; | ||||
| import org.springframework.scheduling.annotation.Async; | |||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||
| import org.springframework.transaction.annotation.Transactional; | import org.springframework.transaction.annotation.Transactional; | ||||
| import org.springframework.web.multipart.MultipartFile; | import org.springframework.web.multipart.MultipartFile; | ||||
| @@ -42,14 +42,12 @@ import java.util.concurrent.CompletableFuture; | |||||
| public class ImageServiceImpl implements ImageService { | public class ImageServiceImpl implements ImageService { | ||||
| @Resource | @Resource | ||||
| private ImageDao imageDao; | private ImageDao imageDao; | ||||
| @Resource | |||||
| private ImageVersionDao imageVersionDao; | |||||
| @Resource | @Resource | ||||
| private ImageVersionService imageVersionService; | private ImageVersionService imageVersionService; | ||||
| @Resource | |||||
| private ImageVersionDao imageVersionDao; | |||||
| @Resource | @Resource | ||||
| private K8sClientUtil k8sClientUtil; | private K8sClientUtil k8sClientUtil; | ||||
| @Resource | @Resource | ||||
| @@ -359,7 +357,8 @@ public class ImageServiceImpl implements ImageService { | |||||
| } | } | ||||
| @Override | @Override | ||||
| @Synchronized | |||||
| @Async | |||||
| @Transactional | |||||
| public String saveImage(ImageVo imageVo) { | public String saveImage(ImageVo imageVo) { | ||||
| if(imageDao.getByName(imageVo.getName()) != null){ | if(imageDao.getByName(imageVo.getName()) != null){ | ||||
| throw new IllegalStateException("镜像名称已存在"); | throw new IllegalStateException("镜像名称已存在"); | ||||
| @@ -373,10 +372,34 @@ public class ImageServiceImpl implements ImageService { | |||||
| String hostIp = k8sClientUtil.getHostIp(podName, namespace); | String hostIp = k8sClientUtil.getHostIp(podName, namespace); | ||||
| dockerClientUtil.commitImage(imageVo,containerId,hostIp,username); | dockerClientUtil.commitImage(imageVo,containerId,hostIp,username); | ||||
| dockerClientUtil.pushImageToHorbor(imageVo,hostIp); | |||||
| HashMap<String, String> resultMap = dockerClientUtil.pushImageToHorbor(imageVo, hostIp); | |||||
| Image image = new Image(); | |||||
| BeanUtils.copyProperties(imageVo,image); | |||||
| image.setCreateBy(username); | |||||
| image.setUpdateBy(username); | |||||
| image.setUpdateTime(new Date()); | |||||
| image.setCreateTime(new Date()); | |||||
| image.setState(1); | |||||
| imageDao.insert(image); | |||||
| ImageVersion imageVersion = new ImageVersion(); | |||||
| imageVersion.setImageId(image.getId()); | |||||
| imageVersion.setVersion(imageVo.getVersion()); | |||||
| imageVersion.setUrl(resultMap.get("imageName")); | |||||
| imageVersion.setTagName(imageVo.getTagName()); | |||||
| imageVersion.setFileSize(resultMap.get("size")); | |||||
| imageVersion.setCreateBy(username); | |||||
| imageVersion.setUpdateBy(username); | |||||
| imageVersion.setUpdateTime(new Date()); | |||||
| imageVersion.setCreateTime(new Date()); | |||||
| imageVersion.setState(1); | |||||
| imageVersion.setStatus("available"); | |||||
| imageVersionDao.insert(imageVersion); | |||||
| return "保存镜像成功"; | |||||
| } catch (Exception e) { | } catch (Exception e) { | ||||
| throw new RuntimeException(e); | |||||
| throw new RuntimeException("保存镜像失败:" +e); | |||||
| } | } | ||||
| return null; | |||||
| } | } | ||||
| } | } | ||||
| @@ -2,6 +2,7 @@ package com.ruoyi.platform.utils; | |||||
| import com.github.dockerjava.api.DockerClient; | import com.github.dockerjava.api.DockerClient; | ||||
| import com.github.dockerjava.api.command.CommitCmd; | import com.github.dockerjava.api.command.CommitCmd; | ||||
| import com.github.dockerjava.api.command.InspectImageResponse; | |||||
| import com.github.dockerjava.api.model.AuthConfig; | import com.github.dockerjava.api.model.AuthConfig; | ||||
| import com.github.dockerjava.core.DefaultDockerClientConfig; | import com.github.dockerjava.core.DefaultDockerClientConfig; | ||||
| import com.github.dockerjava.core.DockerClientConfig; | import com.github.dockerjava.core.DockerClientConfig; | ||||
| @@ -14,6 +15,7 @@ import org.springframework.beans.factory.annotation.Value; | |||||
| import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||
| import java.time.Duration; | import java.time.Duration; | ||||
| import java.util.HashMap; | |||||
| @Slf4j | @Slf4j | ||||
| @Component | @Component | ||||
| @@ -35,7 +37,7 @@ public class DockerClientUtil { | |||||
| //创建DefaultDockerClientConfig(指定docker服务器的配置) | //创建DefaultDockerClientConfig(指定docker服务器的配置) | ||||
| DockerClientConfig config = DefaultDockerClientConfig | DockerClientConfig config = DefaultDockerClientConfig | ||||
| .createDefaultConfigBuilder() | .createDefaultConfigBuilder() | ||||
| .withDockerHost("tcp://"+ dockerServerUrl +":2375") | |||||
| .withDockerHost("tcp://" + dockerServerUrl + ":2375") | |||||
| .withDockerTlsVerify(false) | .withDockerTlsVerify(false) | ||||
| .withApiVersion("1.40") | .withApiVersion("1.40") | ||||
| // .withDockerCertPath(dcokerCertPath) | // .withDockerCertPath(dcokerCertPath) | ||||
| @@ -62,18 +64,16 @@ public class DockerClientUtil { | |||||
| public String commitImage(ImageVo imageVo, String containerId, String hostIp, String userName) { | public String commitImage(ImageVo imageVo, String containerId, String hostIp, String userName) { | ||||
| DockerClient dockerClient = getDockerClient(hostIp); | DockerClient dockerClient = getDockerClient(hostIp); | ||||
| // dockerClient.startContainerCmd(containerId).exec(); | |||||
| // 提交容器为镜像,这里的"new_image"和"new_tag"是新镜像的名字和标签 | // 提交容器为镜像,这里的"new_image"和"new_tag"是新镜像的名字和标签 | ||||
| CommitCmd commitCmd = dockerClient.commitCmd(containerId) | CommitCmd commitCmd = dockerClient.commitCmd(containerId) | ||||
| .withRepository(imageVo.getName()) | .withRepository(imageVo.getName()) | ||||
| .withTag(imageVo.getTagName()) | .withTag(imageVo.getTagName()) | ||||
| .withAuthor(userName) | .withAuthor(userName) | ||||
| .withMessage(imageVo.getDescription()); | .withMessage(imageVo.getDescription()); | ||||
| String exec = commitCmd.exec(); | |||||
| return exec; | |||||
| return commitCmd.exec(); | |||||
| } | } | ||||
| public void pushImageToHorbor(ImageVo imageVo, String hostIp) { | |||||
| public HashMap<String, String> pushImageToHorbor(ImageVo imageVo, String hostIp) { | |||||
| DockerClient dockerClient = getDockerClient(hostIp); | DockerClient dockerClient = getDockerClient(hostIp); | ||||
| //Harbor登录信息 | //Harbor登录信息 | ||||
| @@ -90,8 +90,19 @@ public class DockerClientUtil { | |||||
| dockerClient.pushImageCmd(imageName).withAuthConfig(autoConfig).start().awaitCompletion(); | dockerClient.pushImageCmd(imageName).withAuthConfig(autoConfig).start().awaitCompletion(); | ||||
| //push成功后,删除本地加载的镜像 | //push成功后,删除本地加载的镜像 | ||||
| dockerClient.removeImageCmd(localImageName).exec(); | dockerClient.removeImageCmd(localImageName).exec(); | ||||
| String totalImageName = imageName + ":" + imageVo.getTagName(); | |||||
| InspectImageResponse exec = dockerClient.inspectImageCmd(totalImageName).exec(); | |||||
| String size = String.format("%.1f GB", (float) exec.getSize() / 1073741824.0); | |||||
| HashMap<String, String> resultMap = new HashMap<>(); | |||||
| resultMap.put("imageName",totalImageName); | |||||
| resultMap.put("size",size); | |||||
| return resultMap; | |||||
| } catch (InterruptedException e) { | } catch (InterruptedException e) { | ||||
| throw new RuntimeException("推送镜像失败:"+e); | |||||
| throw new RuntimeException("推送镜像失败:" + e); | |||||
| } | } | ||||
| } | } | ||||
| @@ -405,8 +405,8 @@ public class K8sClientUtil { | |||||
| // 配置卷和卷挂载 | // 配置卷和卷挂载 | ||||
| List<V1VolumeMount> volumeMounts = new ArrayList<>(); | List<V1VolumeMount> volumeMounts = new ArrayList<>(); | ||||
| volumeMounts.add(new V1VolumeMount().name("workspace").mountPath(mountPath)); | volumeMounts.add(new V1VolumeMount().name("workspace").mountPath(mountPath)); | ||||
| volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/datasets").subPath(datasetPath).readOnly(true)); | |||||
| volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/model").subPath(modelPath).readOnly(true)); | |||||
| volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/opt/data").subPath(datasetPath).readOnly(true)); | |||||
| volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/opt/model").subPath(modelPath).readOnly(true)); | |||||
| List<V1Volume> volumes = new ArrayList<>(); | List<V1Volume> volumes = new ArrayList<>(); | ||||
| volumes.add(new V1Volume().name("workspace").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvc.getMetadata().getName()))); | volumes.add(new V1Volume().name("workspace").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvc.getMetadata().getName()))); | ||||
| @@ -24,7 +24,7 @@ public class ImageVo implements Serializable { | |||||
| * 镜像类型 | * 镜像类型 | ||||
| */ | */ | ||||
| @ApiModelProperty(name = "image_type") | |||||
| @ApiModelProperty(name = "imageType") | |||||
| private Integer imageType; | private Integer imageType; | ||||