コード例 #1
0
ファイル: replication_policy.go プロジェクト: vmware/harbor
// Delete : policies which are disabled and have no running jobs
// can be deleted
func (pa *RepPolicyAPI) Delete() {
	id := pa.GetIDFromURL()
	policy, err := dao.GetRepPolicy(id)
	if err != nil {
		log.Errorf("failed to get policy %d: %v", id, err)
		pa.CustomAbort(http.StatusInternalServerError, "")
	}

	if policy == nil || policy.Deleted == 1 {
		pa.CustomAbort(http.StatusNotFound, "")
	}

	if policy.Enabled == 1 {
		pa.CustomAbort(http.StatusPreconditionFailed, "plicy is enabled, can not be deleted")
	}

	jobs, err := dao.GetRepJobByPolicy(id)
	if err != nil {
		log.Errorf("failed to get jobs of policy %d: %v", id, err)
		pa.CustomAbort(http.StatusInternalServerError, "")
	}

	for _, job := range jobs {
		if job.Status == models.JobRunning ||
			job.Status == models.JobRetrying ||
			job.Status == models.JobPending {
			pa.CustomAbort(http.StatusPreconditionFailed, "policy has running/retrying/pending jobs, can not be deleted")
		}
	}

	if err = dao.DeleteRepPolicy(id); err != nil {
		log.Errorf("failed to delete policy %d: %v", id, err)
		pa.CustomAbort(http.StatusInternalServerError, "")
	}
}
コード例 #2
0
ファイル: replication_job.go プロジェクト: vmware/harbor
// List filters jobs according to the parameters
func (ra *RepJobAPI) List() {

	policyID, err := ra.GetInt64("policy_id")
	if err != nil || policyID <= 0 {
		ra.CustomAbort(http.StatusBadRequest, "invalid policy_id")
	}

	policy, err := dao.GetRepPolicy(policyID)
	if err != nil {
		log.Errorf("failed to get policy %d: %v", policyID, err)
		ra.CustomAbort(http.StatusInternalServerError, "")
	}

	if policy == nil {
		ra.CustomAbort(http.StatusNotFound, fmt.Sprintf("policy %d not found", policyID))
	}

	repository := ra.GetString("repository")
	status := ra.GetString("status")

	var startTime *time.Time
	startTimeStr := ra.GetString("start_time")
	if len(startTimeStr) != 0 {
		i, err := strconv.ParseInt(startTimeStr, 10, 64)
		if err != nil {
			ra.CustomAbort(http.StatusBadRequest, "invalid start_time")
		}
		t := time.Unix(i, 0)
		startTime = &t
	}

	var endTime *time.Time
	endTimeStr := ra.GetString("end_time")
	if len(endTimeStr) != 0 {
		i, err := strconv.ParseInt(endTimeStr, 10, 64)
		if err != nil {
			ra.CustomAbort(http.StatusBadRequest, "invalid end_time")
		}
		t := time.Unix(i, 0)
		endTime = &t
	}

	page, pageSize := ra.GetPaginationParams()

	jobs, total, err := dao.FilterRepJobs(policyID, repository, status,
		startTime, endTime, pageSize, pageSize*(page-1))
	if err != nil {
		log.Errorf("failed to filter jobs according policy ID %d, repository %s, status %s, start time %v, end time %v: %v",
			policyID, repository, status, startTime, endTime, err)
		ra.CustomAbort(http.StatusInternalServerError, "")
	}

	ra.SetPaginationHeader(total, page, pageSize)

	ra.Data["json"] = jobs
	ra.ServeJSON()
}
コード例 #3
0
ファイル: replication_policy.go プロジェクト: vmware/harbor
// Get ...
func (pa *RepPolicyAPI) Get() {
	id := pa.GetIDFromURL()
	policy, err := dao.GetRepPolicy(id)
	if err != nil {
		log.Errorf("failed to get policy %d: %v", id, err)
		pa.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
	}

	if policy == nil {
		pa.CustomAbort(http.StatusNotFound, http.StatusText(http.StatusNotFound))
	}

	pa.Data["json"] = policy
	pa.ServeJSON()
}
コード例 #4
0
ファイル: replication_policy.go プロジェクト: vmware/harbor
// UpdateEnablement changes the enablement of the policy
func (pa *RepPolicyAPI) UpdateEnablement() {
	id := pa.GetIDFromURL()
	policy, err := dao.GetRepPolicy(id)
	if err != nil {
		log.Errorf("failed to get policy %d: %v", id, err)
		pa.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
	}

	if policy == nil {
		pa.CustomAbort(http.StatusNotFound, http.StatusText(http.StatusNotFound))
	}

	e := enablementReq{}
	pa.DecodeJSONReq(&e)
	if e.Enabled != 0 && e.Enabled != 1 {
		pa.RenderError(http.StatusBadRequest, "invalid enabled value")
		return
	}

	if policy.Enabled == e.Enabled {
		return
	}

	if err := dao.UpdateRepPolicyEnablement(id, e.Enabled); err != nil {
		log.Errorf("Failed to update policy enablement in DB, error: %v", err)
		pa.RenderError(http.StatusInternalServerError, "Internal Error")
		return
	}

	if e.Enabled == 1 {
		go func() {
			if err := TriggerReplication(id, "", nil, models.RepOpTransfer); err != nil {
				log.Errorf("failed to trigger replication of %d: %v", id, err)
			} else {
				log.Infof("replication of %d triggered", id)
			}
		}()
	} else {
		go func() {
			if err := postReplicationAction(id, "stop"); err != nil {
				log.Errorf("failed to stop replication of %d: %v", id, err)
			} else {
				log.Infof("try to stop replication of %d", id)
			}
		}()
	}
}
コード例 #5
0
ファイル: replication.go プロジェクト: vmware/harbor
// Post creates replication jobs according to the policy.
func (rj *ReplicationJob) Post() {
	var data ReplicationReq
	rj.DecodeJSONReq(&data)
	log.Debugf("data: %+v", data)
	p, err := dao.GetRepPolicy(data.PolicyID)
	if err != nil {
		log.Errorf("Failed to get policy, error: %v", err)
		rj.RenderError(http.StatusInternalServerError, fmt.Sprintf("Failed to get policy, id: %d", data.PolicyID))
		return
	}
	if p == nil {
		log.Errorf("Policy not found, id: %d", data.PolicyID)
		rj.RenderError(http.StatusNotFound, fmt.Sprintf("Policy not found, id: %d", data.PolicyID))
		return
	}
	if len(data.Repo) == 0 { // sync all repositories
		repoList, err := getRepoList(p.ProjectID)
		if err != nil {
			log.Errorf("Failed to get repository list, project id: %d, error: %v", p.ProjectID, err)
			rj.RenderError(http.StatusInternalServerError, err.Error())
			return
		}
		log.Debugf("repo list: %v", repoList)
		for _, repo := range repoList {
			err := rj.addJob(repo, data.PolicyID, models.RepOpTransfer)
			if err != nil {
				log.Errorf("Failed to insert job record, error: %v", err)
				rj.RenderError(http.StatusInternalServerError, err.Error())
				return
			}
		}
	} else { // sync a single repository
		var op string
		if len(data.Operation) > 0 {
			op = data.Operation
		} else {
			op = models.RepOpTransfer
		}
		err := rj.addJob(data.Repo, data.PolicyID, op, data.TagList...)
		if err != nil {
			log.Errorf("Failed to insert job record, error: %v", err)
			rj.RenderError(http.StatusInternalServerError, err.Error())
			return
		}
	}
}
コード例 #6
0
// Reset resets the state machine so it will start handling another job.
func (sm *SM) Reset(jid int64) error {
	//To ensure the new jobID is visible to the thread to stop the SM
	sm.lock.Lock()
	sm.JobID = jid
	sm.desiredState = ""
	sm.lock.Unlock()

	sm.Logger = utils.NewLogger(sm.JobID)
	//init parms
	job, err := dao.GetRepJob(sm.JobID)
	if err != nil {
		return fmt.Errorf("Failed to get job, error: %v", err)
	}
	if job == nil {
		return fmt.Errorf("The job doesn't exist in DB, job id: %d", sm.JobID)
	}
	policy, err := dao.GetRepPolicy(job.PolicyID)
	if err != nil {
		return fmt.Errorf("Failed to get policy, error: %v", err)
	}
	if policy == nil {
		return fmt.Errorf("The policy doesn't exist in DB, policy id:%d", job.PolicyID)
	}
	sm.Parms = &RepJobParm{
		LocalRegURL: config.LocalRegURL(),
		Repository:  job.Repository,
		Tags:        job.TagList,
		Enabled:     policy.Enabled,
		Operation:   job.Operation,
		Insecure:    !config.VerifyRemoteCert(),
	}
	if policy.Enabled == 0 {
		//worker will cancel this job
		return nil
	}
	target, err := dao.GetRepTarget(policy.TargetID)
	if err != nil {
		return fmt.Errorf("Failed to get target, error: %v", err)
	}
	if target == nil {
		return fmt.Errorf("The target doesn't exist in DB, target id: %d", policy.TargetID)
	}
	sm.Parms.TargetURL = target.URL
	sm.Parms.TargetUsername = target.Username
	pwd := target.Password

	if len(pwd) != 0 {
		pwd, err = uti.ReversibleDecrypt(pwd, config.SecretKey())
		if err != nil {
			return fmt.Errorf("failed to decrypt password: %v", err)
		}
	}

	sm.Parms.TargetPassword = pwd

	//init states handlers
	sm.Handlers = make(map[string]StateHandler)
	sm.Transitions = make(map[string]map[string]struct{})
	sm.CurrentState = models.JobPending

	sm.AddTransition(models.JobPending, models.JobRunning, StatusUpdater{sm.JobID, models.JobRunning})
	sm.AddTransition(models.JobRetrying, models.JobRunning, StatusUpdater{sm.JobID, models.JobRunning})
	sm.Handlers[models.JobError] = StatusUpdater{sm.JobID, models.JobError}
	sm.Handlers[models.JobStopped] = StatusUpdater{sm.JobID, models.JobStopped}
	sm.Handlers[models.JobRetrying] = Retry{sm.JobID}

	switch sm.Parms.Operation {
	case models.RepOpTransfer:
		addImgTransferTransition(sm)
	case models.RepOpDelete:
		addImgDeleteTransition(sm)
	default:
		err = fmt.Errorf("unsupported operation: %s", sm.Parms.Operation)
	}

	return err
}
コード例 #7
0
ファイル: replication_policy.go プロジェクト: vmware/harbor
// Put modifies name, description, target and enablement of policy
func (pa *RepPolicyAPI) Put() {
	id := pa.GetIDFromURL()
	originalPolicy, err := dao.GetRepPolicy(id)
	if err != nil {
		log.Errorf("failed to get policy %d: %v", id, err)
		pa.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
	}

	if originalPolicy == nil {
		pa.CustomAbort(http.StatusNotFound, http.StatusText(http.StatusNotFound))
	}

	policy := &models.RepPolicy{}
	pa.DecodeJSONReq(policy)
	policy.ProjectID = originalPolicy.ProjectID
	pa.Validate(policy)

	/*
		// check duplicate name
		if policy.Name != originalPolicy.Name {
			po, err := dao.GetRepPolicyByName(policy.Name)
			if err != nil {
				log.Errorf("failed to get policy %s: %v", policy.Name, err)
				pa.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
			}

			if po != nil {
				pa.CustomAbort(http.StatusConflict, "name is already used")
			}
		}
	*/

	if policy.TargetID != originalPolicy.TargetID {
		//target of policy can not be modified when the policy is enabled
		if originalPolicy.Enabled == 1 {
			pa.CustomAbort(http.StatusBadRequest, "target of policy can not be modified when the policy is enabled")
		}

		// check the existance of target
		target, err := dao.GetRepTarget(policy.TargetID)
		if err != nil {
			log.Errorf("failed to get target %d: %v", policy.TargetID, err)
			pa.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
		}

		if target == nil {
			pa.CustomAbort(http.StatusBadRequest, fmt.Sprintf("target %d does not exist", policy.TargetID))
		}

		// check duplicate policy with the same project and target
		policies, err := dao.GetRepPolicyByProjectAndTarget(policy.ProjectID, policy.TargetID)
		if err != nil {
			log.Errorf("failed to get policy [project ID: %d,targetID: %d]: %v", policy.ProjectID, policy.TargetID, err)
			pa.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
		}

		if len(policies) > 0 {
			pa.CustomAbort(http.StatusConflict, "policy already exists with the same project and target")
		}
	}

	policy.ID = id

	/*
		isTargetChanged := !(policy.TargetID == originalPolicy.TargetID)
		isEnablementChanged := !(policy.Enabled == policy.Enabled)

		var shouldStop, shouldTrigger bool

		// if target and enablement are not changed, do nothing
		if !isTargetChanged && !isEnablementChanged {
			shouldStop = false
			shouldTrigger = false
		} else if !isTargetChanged && isEnablementChanged {
			// target is not changed, but enablement is changed
			if policy.Enabled == 0 {
				shouldStop = true
				shouldTrigger = false
			} else {
				shouldStop = false
				shouldTrigger = true
			}
		} else if isTargetChanged && !isEnablementChanged {
			// target is changed, but enablement is not changed
			if policy.Enabled == 0 {
				// enablement is 0, do nothing
				shouldStop = false
				shouldTrigger = false
			} else {
				// enablement is 1, so stop original target's jobs
				// and trigger new target's jobs
				shouldStop = true
				shouldTrigger = true
			}
		} else {
			// both target and enablement are changed

			// enablement: 1 -> 0
			if policy.Enabled == 0 {
				shouldStop = true
				shouldTrigger = false
			} else {
				shouldStop = false
				shouldTrigger = true
			}
		}

		if shouldStop {
			if err := postReplicationAction(id, "stop"); err != nil {
				log.Errorf("failed to stop replication of %d: %v", id, err)
				pa.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
			}
			log.Infof("replication of %d has been stopped", id)
		}

		if err = dao.UpdateRepPolicy(policy); err != nil {
			log.Errorf("failed to update policy %d: %v", id, err)
			pa.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
		}

		if shouldTrigger {
			go func() {
				if err := TriggerReplication(id, "", nil, models.RepOpTransfer); err != nil {
					log.Errorf("failed to trigger replication of %d: %v", id, err)
				} else {
					log.Infof("replication of %d triggered", id)
				}
			}()
		}
	*/

	if err = dao.UpdateRepPolicy(policy); err != nil {
		log.Errorf("failed to update policy %d: %v", id, err)
		pa.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
	}

	if policy.Enabled != originalPolicy.Enabled && policy.Enabled == 1 {
		go func() {
			if err := TriggerReplication(id, "", nil, models.RepOpTransfer); err != nil {
				log.Errorf("failed to trigger replication of %d: %v", id, err)
			} else {
				log.Infof("replication of %d triggered", id)
			}
		}()
	}
}