// 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, "") } }
// 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() }
// 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() }
// 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) } }() } }
// 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 } } }
// 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 }
// 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) } }() } }