You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
667 lines
18 KiB
667 lines
18 KiB
package service |
|
|
|
import ( |
|
"context" |
|
"encoding/json" |
|
"strconv" |
|
"strings" |
|
"time" |
|
|
|
"go-common/app/admin/ep/merlin/model" |
|
"go-common/library/ecode" |
|
"go-common/library/log" |
|
) |
|
|
|
// AuthHub Auth Hub. |
|
func (s *Service) AuthHub(c context.Context, sessionID string) (err error) { |
|
return s.dao.AuthHub(c, sessionID) |
|
} |
|
|
|
// AccessAuthHub Access Auth Hub. |
|
func (s *Service) AccessAuthHub(c context.Context, username string) (accessHub bool, err error) { |
|
var ( |
|
personProjectID int |
|
) |
|
|
|
if personProjectID, err = s.ProjectID(c, username); err != nil { |
|
return |
|
} |
|
|
|
if personProjectID > 0 { |
|
accessHub = true |
|
} |
|
|
|
return |
|
} |
|
|
|
// ProjectID Get Project ID. |
|
func (s *Service) ProjectID(c context.Context, projectName string) (projectID int, err error) { |
|
var hubProjects []*model.HubProject |
|
|
|
if hubProjects, err = s.dao.HubProjects(c, projectName); err != nil { |
|
return |
|
} |
|
|
|
for _, hubProject := range hubProjects { |
|
if projectName == hubProject.Name { |
|
projectID = hubProject.ProjectID |
|
return |
|
} |
|
} |
|
return |
|
} |
|
|
|
// ProjectRepositories Get Project Repositories. |
|
func (s *Service) ProjectRepositories(c context.Context, projectID, pn, ps int, keyWord string) (p *model.PaginateProjectRepoRecord, err error) { |
|
var ( |
|
total int |
|
projectRepos []*model.ProjectRepository |
|
) |
|
|
|
if total, err = s.dao.ProjectRepoCount(c, projectID); err != nil { |
|
return |
|
} |
|
|
|
if projectRepos, err = s.dao.ProjectRepos(c, projectID, pn, ps, keyWord); err != nil { |
|
return |
|
} |
|
|
|
p = &model.PaginateProjectRepoRecord{ |
|
PageNum: pn, |
|
PageSize: ps, |
|
Total: total, |
|
ProjectRepository: projectRepos, |
|
} |
|
return |
|
} |
|
|
|
// AccessPullProjects Access Pull Projects. |
|
func (s *Service) AccessPullProjects(c context.Context, username string) (projectsName []string, err error) { |
|
var accessToHub bool |
|
|
|
if accessToHub, err = s.AccessAuthHub(c, username); err != nil { |
|
return |
|
} |
|
|
|
if accessToHub { |
|
projectsName = append(projectsName, s.c.BiliHub.HostName+"/"+username) |
|
} |
|
|
|
projectsName = append(projectsName, s.c.BiliHub.HostName+"/"+s.c.BiliHub.SharePub) |
|
|
|
return |
|
} |
|
|
|
// Projects Get Projects. |
|
func (s *Service) Projects(c context.Context, username string) (projects map[string]int, err error) { |
|
var ( |
|
personProjectID int |
|
merlinProjectID int |
|
publicProjectID int |
|
) |
|
|
|
projects = make(map[string]int) |
|
if personProjectID, err = s.ProjectID(c, username); err != nil { |
|
return |
|
} |
|
projects[username] = personProjectID |
|
|
|
if merlinProjectID, err = s.ProjectID(c, s.c.BiliHub.MerlinPub); err != nil { |
|
return |
|
} |
|
projects[s.c.BiliHub.MerlinPub] = merlinProjectID |
|
|
|
if publicProjectID, err = s.ProjectID(c, s.c.BiliHub.SharePub); err != nil { |
|
return |
|
} |
|
projects[s.c.BiliHub.SharePub] = publicProjectID |
|
|
|
return |
|
} |
|
|
|
// RepositoryTags Get Repository Tags. |
|
func (s *Service) RepositoryTags(c context.Context, repoName string) (repoTags []*model.RepositoryTag, err error) { |
|
var ( |
|
repoTagsRet []*model.RepositoryTagResponse |
|
imageFullNamePrefix = s.c.BiliHub.HostName + "/" + repoName + ":" |
|
) |
|
if repoTagsRet, err = s.dao.RepoTags(c, repoName); err != nil { |
|
return |
|
} |
|
|
|
for _, repoTagRet := range repoTagsRet { |
|
// ignore image that size is 0 |
|
if repoTagRet.Size == 0 { |
|
continue |
|
} |
|
|
|
repoTag := &model.RepositoryTag{ |
|
RepositoryTagResponse: *repoTagRet, |
|
ImageFullName: imageFullNamePrefix + repoTagRet.Name, |
|
} |
|
repoTags = append(repoTags, repoTag) |
|
} |
|
return |
|
} |
|
|
|
// DeleteRepositoryTag Delete Repository Tag. |
|
func (s *Service) DeleteRepositoryTag(c context.Context, username, repoName, tagName string) (status int, err error) { |
|
var hasRight bool |
|
if hasRight = s.hasOperateHubRight(username, repoName); !hasRight { |
|
status = -1 |
|
err = ecode.MerlinHubNoRight |
|
return |
|
} |
|
|
|
if err = s.dao.DeleteRepoTag(c, repoName, tagName); err != nil { |
|
status = -1 |
|
} |
|
|
|
return |
|
} |
|
|
|
// DeleteRepository Delete Repository. |
|
func (s *Service) DeleteRepository(c context.Context, username, repoName string) (status int, err error) { |
|
var hasRight bool |
|
if hasRight = s.hasOperateHubRight(username, repoName); !hasRight { |
|
status = -1 |
|
err = ecode.MerlinHubNoRight |
|
return |
|
} |
|
|
|
if err = s.dao.DeleteRepo(c, repoName); err != nil { |
|
status = -1 |
|
} |
|
|
|
return |
|
} |
|
|
|
// AddRepositoryTag Add Repository Tag. |
|
func (s *Service) AddRepositoryTag(c context.Context, username, repoName, tagName, newRepoName, newTagName string) (status int, err error) { |
|
//操作src image 权限认证 |
|
var hasRight bool |
|
if hasRight = s.hasOperateHubRight(username, repoName); !hasRight { |
|
status = -1 |
|
err = ecode.MerlinHubNoRight |
|
return |
|
} |
|
|
|
//上传的src image权限认证。如果上传的路径 只能为公共路径和个人路径 |
|
if strings.Split(newRepoName, "/")[0] != s.c.BiliHub.SharePub { |
|
if hasRight = s.hasOperateHubRight(username, newRepoName); !hasRight { |
|
status = -1 |
|
err = ecode.MerlinHubNoRight |
|
return |
|
} |
|
} |
|
|
|
imageSrcName := s.getFullRepoName(repoName, tagName) |
|
imageTagName := s.getFullRepoName(newRepoName, newTagName) |
|
|
|
// pull and push image |
|
s.dao.ImageTask(func() { |
|
s.PullAndPush(username, imageSrcName, imageTagName, 0) |
|
}) |
|
return |
|
} |
|
|
|
// AddTagToMachine Add Tag To Machine. |
|
func (s *Service) AddTagToMachine(c context.Context, username, imageSrcName string, machineIDs []int64) (machineImageMap map[int64]string, err error) { |
|
machineImageMap = map[int64]string{} |
|
for _, machineID := range machineIDs { |
|
repoName := strings.Split(imageSrcName, ":")[0] |
|
absRepoName := strings.Replace(repoName, "/", "-", -1) |
|
newRepoName := s.c.BiliHub.MachineTagPri + "/" + absRepoName |
|
newTagName := strconv.FormatInt(machineID, 10) + "-" + time.Now().Format("20060102150405") |
|
imageTagName := s.getFullRepoName(newRepoName, newTagName) |
|
|
|
if _, err = s.PullAndPush(username, imageSrcName, imageTagName, machineID); err != nil { |
|
return |
|
} |
|
machineImageMap[machineID] = imageTagName |
|
} |
|
|
|
return |
|
} |
|
|
|
// GetAllImagesInDocker Get All Images In Docker. |
|
func (s *Service) GetAllImagesInDocker() (imageNames []string, err error) { |
|
return s.dao.ImageGetAll() |
|
} |
|
|
|
// hasOperateHubRight has Operate HubRight. |
|
func (s *Service) hasOperateHubRight(username, repoName string) (hasRight bool) { |
|
//判断是否又权限执行操作 |
|
if username == strings.Split(repoName, "/")[0] { |
|
hasRight = true |
|
return |
|
} |
|
|
|
for _, super := range s.c.BiliHub.SuperOwner { |
|
if username == super { |
|
hasRight = true |
|
return |
|
} |
|
} |
|
|
|
return |
|
} |
|
|
|
// get Full RepoName getFullRepoName. |
|
func (s *Service) getFullRepoName(repoName, tagName string) string { |
|
return s.c.BiliHub.HostName + "/" + repoName + ":" + tagName |
|
} |
|
|
|
//Push Push. |
|
func (s *Service) Push(c context.Context, username, repoName, tagName string, machineID int64) (status int, err error) { |
|
imageSrcName := s.getFullRepoName(repoName, tagName) |
|
|
|
log.Info("start Push target %s", imageSrcName) |
|
|
|
if err = s.dao.ImagePush(imageSrcName); err != nil { |
|
status = model.ImagePushErr |
|
log.Error("ImagePush target %s,err (%+v)", imageSrcName, err) |
|
} |
|
|
|
hubImageLog := &model.HubImageLog{ |
|
UserName: username, |
|
MachineID: machineID, |
|
ImageSrc: "", |
|
ImageTag: imageSrcName, |
|
Status: status, |
|
OperateType: model.ImagePush, |
|
} |
|
s.dao.InsertHubImageLog(hubImageLog) |
|
|
|
log.Info("end Push target %s", imageSrcName) |
|
|
|
return |
|
} |
|
|
|
// ReTag ReTag. |
|
func (s *Service) ReTag(c context.Context, username, repoName, tagName, newRepoName, newTagName string, machineID int64) (status int, err error) { |
|
imageSrcName := s.getFullRepoName(repoName, tagName) |
|
imageTagName := s.getFullRepoName(newRepoName, newTagName) |
|
|
|
log.Info("start ReTag source %s tag %s", imageSrcName, imageTagName) |
|
|
|
if err = s.dao.ImageTag(imageSrcName, imageTagName); err != nil { |
|
status = model.ImageReTagErr |
|
log.Error("ImageTag source %s, target %s,err (%+v)", imageSrcName, imageTagName, err) |
|
} |
|
hubImageLog := &model.HubImageLog{ |
|
UserName: username, |
|
MachineID: machineID, |
|
ImageSrc: imageSrcName, |
|
ImageTag: imageTagName, |
|
Status: status, |
|
OperateType: model.ImageTag, |
|
} |
|
s.dao.InsertHubImageLog(hubImageLog) |
|
|
|
log.Info("end ReTag source %s, tag %s", imageSrcName, imageTagName) |
|
|
|
return |
|
} |
|
|
|
// Pull Pull. |
|
func (s *Service) Pull(c context.Context, username, repoName, tagName string, machineID int64) (status int, err error) { |
|
imageSrcName := s.getFullRepoName(repoName, tagName) |
|
|
|
log.Info("start Pull source %s", imageSrcName) |
|
|
|
if err = s.dao.ImagePull(imageSrcName); err != nil { |
|
status = model.ImagePullErr |
|
log.Error("ImagePull source %s,err (%+v)", imageSrcName, err) |
|
} |
|
|
|
hubImageLog := &model.HubImageLog{ |
|
UserName: username, |
|
MachineID: machineID, |
|
ImageSrc: imageSrcName, |
|
ImageTag: "", |
|
Status: status, |
|
OperateType: model.ImagePull, |
|
} |
|
s.dao.InsertHubImageLog(hubImageLog) |
|
|
|
log.Info("end Pull source %s", imageSrcName) |
|
|
|
return |
|
} |
|
|
|
// CreateSnapShot CreateSnapShot. |
|
func (s *Service) CreateSnapShot(c context.Context, username string, machineID int64) (status int, err error) { |
|
status = -1 |
|
//获取镜像名称 |
|
var ( |
|
machine *model.Machine |
|
passMachineDetail *model.PaasMachineDetail |
|
pqadmr *model.PaasQueryAndDelMachineRequest |
|
tmpSnapshotRecord *model.SnapshotRecord |
|
) |
|
if machine, err = s.dao.QueryMachine(machineID); err != nil { |
|
return |
|
} |
|
|
|
pqadmr = machine.ToPaasQueryAndDelMachineRequest() |
|
|
|
if passMachineDetail, err = s.dao.QueryPaasMachine(c, pqadmr); err != nil { |
|
return |
|
} |
|
snapshotRecord := &model.SnapshotRecord{ |
|
MachineID: machineID, |
|
ImageName: passMachineDetail.Image, |
|
Username: username, |
|
Status: model.SnapshotInit, |
|
} |
|
|
|
if tmpSnapshotRecord, err = s.dao.FindSnapshotRecord(machineID); err != nil { |
|
return |
|
} |
|
|
|
if tmpSnapshotRecord.ID == 0 { |
|
//首次快照 插入 |
|
if err = s.dao.InsertSnapshotRecord(snapshotRecord); err != nil { |
|
return |
|
} |
|
} else if tmpSnapshotRecord.Status == model.SnapshotDoing { |
|
//有快照记录,查看是否正在进行中 |
|
err = ecode.MerlinSnapshotInDoingErr |
|
return |
|
} else if err = s.dao.UpdateSnapshotRecord(snapshotRecord); err != nil { |
|
return |
|
} |
|
|
|
//创建快照 |
|
resultStatus := model.SnapshotDoing |
|
if _, err = s.dao.SnapshotPaasMachineStatus(c, pqadmr); err != nil { |
|
resultStatus = model.SnapShotFailed |
|
} |
|
|
|
if err = s.dao.UpdateSnapshotRecordStatus(machineID, resultStatus); err != nil { |
|
return |
|
} |
|
|
|
status = 0 |
|
return |
|
} |
|
|
|
// QuerySnapShot Query SnapShot. |
|
func (s *Service) QuerySnapShot(c context.Context, machineID int64) (snapshotRecord *model.SnapshotRecord, err error) { |
|
return s.dao.FindSnapshotRecord(machineID) |
|
} |
|
|
|
// QueryMachine2ImageLog Query Machine to ImageLog. |
|
func (s *Service) QueryMachine2ImageLog(c context.Context, queryRequest *model.QueryMachine2ImageLogRequest) (p *model.PaginateHubImageLog, err error) { |
|
var ( |
|
hubImageLogs []*model.HubImageLog |
|
total int64 |
|
) |
|
|
|
if total, hubImageLogs, err = s.dao.FindHubMachine2ImageLog(queryRequest); err != nil { |
|
return |
|
} |
|
p = &model.PaginateHubImageLog{ |
|
PageNum: queryRequest.PageNum, |
|
PageSize: queryRequest.PageSize, |
|
Total: total, |
|
HubImageLogs: hubImageLogs, |
|
} |
|
|
|
return |
|
} |
|
|
|
// CallBackSnapShot Call Back SnapShot. |
|
func (s *Service) CallBackSnapShot(c context.Context, machineName, imageName, msg string, resultStatus bool) (err error) { |
|
var ( |
|
machine *model.Machine |
|
snapshotResultStatus string |
|
) |
|
if machine, err = s.dao.QueryOnlineMachineByName(machineName); err != nil { |
|
return |
|
} |
|
|
|
if resultStatus { |
|
snapshotResultStatus = model.SnapshotSuccess |
|
} else { |
|
snapshotResultStatus = model.SnapShotFailed |
|
} |
|
|
|
err = s.dao.UpdateSnapshotRecordStatus(machine.ID, snapshotResultStatus) |
|
return |
|
} |
|
|
|
// Machine2Image Machine to Image. |
|
func (s *Service) Machine2Image(c context.Context, username, imageName, newImageName string, machineID int64) (err error) { |
|
var ( |
|
accessToHub bool |
|
hubImageLog *model.HubImageLog |
|
hubImageLogs []*model.HubImageLog |
|
machine *model.Machine |
|
passMachineDetail *model.PaasMachineDetail |
|
) |
|
|
|
//判断镜像和机器是否一致 |
|
if machine, err = s.dao.QueryMachine(machineID); err != nil { |
|
return |
|
} |
|
if passMachineDetail, err = s.dao.QueryPaasMachine(c, machine.ToPaasQueryAndDelMachineRequest()); err != nil { |
|
return |
|
} |
|
|
|
if passMachineDetail.Image != imageName { |
|
err = ecode.MerlinMachineImageNotSameErr |
|
return |
|
} |
|
|
|
//判断有无授权hub |
|
if accessToHub, err = s.AccessAuthHub(c, username); err != nil { |
|
return |
|
} |
|
|
|
if !accessToHub { |
|
err = ecode.MerlinHubNoRight |
|
return |
|
} |
|
|
|
//判断new image name是否重名 |
|
if hubImageLog, err = s.dao.FindHubImageLogByImageTag(newImageName); err != nil { |
|
return |
|
} |
|
|
|
if hubImageLog.ID > 0 { |
|
err = ecode.MerlinDuplicateImageNameErr |
|
return |
|
} |
|
|
|
//判断该机器是否有正在进行的机器转镜像任务 |
|
if hubImageLogs, err = s.dao.FindHubImageLogByMachineID(machineID); err != nil { |
|
return |
|
} |
|
|
|
for _, hil := range hubImageLogs { |
|
if hil.OperateType == model.ImageMachine2Image && hil.Status == model.ImageInit { |
|
err = ecode.MerlinMachine2ImageInDoingErr |
|
return |
|
} |
|
} |
|
|
|
status := model.ImageInit |
|
newHubImageLog := &model.HubImageLog{ |
|
UserName: username, |
|
MachineID: machineID, |
|
ImageSrc: imageName, |
|
ImageTag: newImageName, |
|
Status: status, |
|
OperateType: model.ImageMachine2Image, |
|
} |
|
|
|
if err = s.dao.InsertHubImageLog(newHubImageLog); err != nil { |
|
return |
|
} |
|
|
|
s.dao.ImageTask(func() { |
|
s.PullAndPushWithMachine2Image(username, imageName, newImageName, machineID, newHubImageLog.ID) |
|
}) |
|
return |
|
} |
|
|
|
// PullAndPush pull And Push. |
|
func (s *Service) PullAndPush(username, imageSrcName, imageTagName string, machineID int64) (status int, err error) { |
|
log.Info("start pullAndPush source %s, target %s", imageSrcName, imageTagName) |
|
|
|
//pull image |
|
if err = s.dao.ImagePull(imageSrcName); err != nil { |
|
status = model.ImagePullErr |
|
log.Error("ImagePull source %s,err (%+v)", imageSrcName, err) |
|
|
|
} else if err = s.dao.ImageTag(imageSrcName, imageTagName); err != nil { |
|
status = model.ImageReTagErr |
|
log.Error("ImageTag source %s, target %s,err (%+v)", imageSrcName, imageTagName, err) |
|
|
|
} else if err = s.dao.ImagePush(imageTagName); err != nil { |
|
status = model.ImagePushErr |
|
log.Error("ImagePush target %s,err (%+v)", imageTagName, err) |
|
} |
|
|
|
hubImageLog := &model.HubImageLog{ |
|
UserName: username, |
|
MachineID: machineID, |
|
ImageSrc: imageSrcName, |
|
ImageTag: imageTagName, |
|
Status: status, |
|
OperateType: model.ImagePullAndPush, |
|
} |
|
s.dao.InsertHubImageLog(hubImageLog) |
|
|
|
log.Info("end pullAndPush source %s, target %s", imageSrcName, imageTagName) |
|
|
|
return |
|
} |
|
|
|
// PullAndPushWithMachine2Image Pull And Push With Machine to Image. |
|
func (s *Service) PullAndPushWithMachine2Image(username, imageSrcName, imageTagName string, machineID, hubImageLogID int64) (status int, err error) { |
|
log.Info("start PullAndPushWithMachine2Image source %s, target %s", imageSrcName, imageTagName) |
|
status = model.ImageSuccess |
|
//pull image |
|
if err = s.dao.ImagePull(imageSrcName); err != nil { |
|
status = model.ImagePullErr |
|
log.Error("ImagePull source %s,err (%+v)", imageSrcName, err) |
|
|
|
} else if err = s.dao.ImageTag(imageSrcName, imageTagName); err != nil { |
|
status = model.ImageReTagErr |
|
log.Error("ImageTag source %s, target %s,err (%+v)", imageSrcName, imageTagName, err) |
|
|
|
} else if err = s.dao.ImagePush(imageTagName); err != nil { |
|
status = model.ImagePushErr |
|
log.Error("ImagePush target %s,err (%+v)", imageTagName, err) |
|
} |
|
|
|
err = s.dao.UpdateHubImageLogStatus(hubImageLogID, status) |
|
log.Info("end PullAndPushWithMachine2Image source %s, target %s", imageSrcName, imageTagName) |
|
return |
|
} |
|
|
|
// Machine2ImageForceFailed Machine to Image Force Failed. |
|
func (s *Service) Machine2ImageForceFailed(c context.Context, machineID int64) (status int, err error) { |
|
if err = s.dao.UpdateHubImageLogStatusInDoingStatus(machineID, model.ImagePullErr); err != nil { |
|
status = -1 |
|
} |
|
return |
|
} |
|
|
|
// UpdateImageConf Update Image Conf. |
|
func (s *Service) UpdateImageConf(c context.Context, username string, ic *model.ImageConfiguration) (status int, err error) { |
|
var ( |
|
hubImageConf *model.HubImageConf |
|
hasRight bool |
|
envsJson []byte |
|
hostsJson []byte |
|
) |
|
status = -1 |
|
|
|
// 超级用户才能改MerlinPub 配置模板 |
|
ret := strings.Split(ic.ImageFullName, "/") |
|
if len(ret) > 1 && ret[1] == s.c.BiliHub.MerlinPub { |
|
for _, super := range s.c.BiliHub.SuperOwner { |
|
if username == super { |
|
hasRight = true |
|
continue |
|
} |
|
} |
|
|
|
if !hasRight { |
|
err = ecode.MerlinHubNoRight |
|
return |
|
} |
|
} |
|
|
|
if envsJson, err = json.Marshal(ic.Envs); err != nil { |
|
return |
|
} |
|
|
|
if hostsJson, err = json.Marshal(ic.HostAlias); err != nil { |
|
return |
|
} |
|
|
|
if hubImageConf, err = s.dao.FindHubImageConfByImageName(ic.ImageFullName); err != nil { |
|
return |
|
} |
|
|
|
newHubImageConf := &model.HubImageConf{ |
|
ImageName: ic.ImageFullName, |
|
UpdateBy: username, |
|
Command: strings.TrimSpace(ic.Command), |
|
Envs: string(envsJson), |
|
Hosts: string(hostsJson), |
|
} |
|
|
|
if hubImageConf.ID == 0 { |
|
if err = s.dao.InsertHubImageConf(newHubImageConf); err != nil { |
|
return |
|
} |
|
} else { |
|
if err = s.dao.UpdateHubImageConf(newHubImageConf); err != nil { |
|
return |
|
} |
|
} |
|
|
|
status = 0 |
|
return |
|
} |
|
|
|
// QueryImageConf Query Image Conf. |
|
func (s *Service) QueryImageConf(c context.Context, imageName string) (ic *model.ImageConfiguration, err error) { |
|
var ( |
|
hubImageConf *model.HubImageConf |
|
envs []*model.EnvVariable |
|
hostAlias []*model.Host |
|
) |
|
|
|
if hubImageConf, err = s.dao.FindHubImageConfByImageName(imageName); err != nil || hubImageConf.ID == 0 { |
|
return |
|
} |
|
|
|
if err = json.Unmarshal([]byte(hubImageConf.Envs), &envs); err != nil { |
|
return |
|
} |
|
|
|
if err = json.Unmarshal([]byte(hubImageConf.Hosts), &hostAlias); err != nil { |
|
return |
|
} |
|
|
|
ic = &model.ImageConfiguration{ |
|
ImageFullName: imageName, |
|
PaasMachineSystem: model.PaasMachineSystem{ |
|
Command: hubImageConf.Command, |
|
Envs: envs, |
|
HostAlias: hostAlias, |
|
}, |
|
} |
|
|
|
if len(ic.Envs) == 0 && len(ic.HostAlias) == 0 && strings.TrimSpace(ic.Command) == "" { |
|
ic = nil |
|
} |
|
return |
|
}
|
|
|