func (h *DesiredLRPHandler) DesireDesiredLRP_r0(w http.ResponseWriter, req *http.Request) {
	logger := h.logger.Session("desire-lrp")

	request := &models.DesireLRPRequest{}
	response := &models.DesiredLRPLifecycleResponse{}
	defer func() { exitIfUnrecoverable(logger, h.exitChan, response.Error) }()
	defer writeResponse(w, response)

	err := parseRequestForDesireDesiredLRP_r0(logger, req, request)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}

	err = h.desiredLRPDB.DesireLRP(logger, request.DesiredLrp)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}

	desiredLRP, err := h.desiredLRPDB.DesiredLRPByProcessGuid(logger, request.DesiredLrp.ProcessGuid)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}

	go h.desiredHub.Emit(models.NewDesiredLRPCreatedEvent(desiredLRP))

	schedulingInfo := request.DesiredLrp.DesiredLRPSchedulingInfo()
	h.startInstanceRange(logger, 0, schedulingInfo.Instances, &schedulingInfo)
}
Example #2
0
func (h *TaskHandler) CompleteTask(w http.ResponseWriter, req *http.Request) {
	var err error
	logger := h.logger.Session("complete-task")

	request := &models.CompleteTaskRequest{}
	response := &models.TaskLifecycleResponse{}

	defer func() { exitIfUnrecoverable(logger, h.exitChan, response.Error) }()
	defer writeResponse(w, response)

	err = parseRequest(logger, req, request)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}

	task, err := h.db.CompleteTask(logger, request.TaskGuid, request.CellId, request.Failed, request.FailureReason, request.Result)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}

	if task.CompletionCallbackUrl != "" {
		logger.Info("task-client-completing-task")
		go h.taskCompletionClient.Submit(h.db, task)
	}
}
Example #3
0
func (db *serviceClient) Cells(logger lager.Logger) (models.CellSet, error) {
	kvPairs, _, err := db.consulClient.KV().List(CellSchemaRoot(), nil)
	if err != nil {
		bbsErr := models.ConvertError(convertConsulError(err))
		if bbsErr.Type != models.Error_ResourceNotFound {
			return nil, bbsErr
		}
	}

	if kvPairs == nil {
		err = consuladapter.NewPrefixNotFoundError(CellSchemaRoot())
		bbsErr := models.ConvertError(convertConsulError(err))
		if bbsErr.Type != models.Error_ResourceNotFound {
			return nil, bbsErr
		}
	}

	cellPresences := models.NewCellSet()
	for _, kvPair := range kvPairs {
		if kvPair.Session == "" {
			continue
		}

		cell := kvPair.Value
		presence := new(models.CellPresence)
		err := models.FromJSON(cell, presence)
		if err != nil {
			logger.Error("failed-to-unmarshal-cells-json", err)
			continue
		}
		cellPresences.Add(presence)
	}

	return cellPresences, nil
}
func (h *ActualLRPLifecycleHandler) StartActualLRP(w http.ResponseWriter, req *http.Request) {
	var err error

	logger := h.logger.Session("start-actual-lrp")

	request := &models.StartActualLRPRequest{}
	response := &models.ActualLRPLifecycleResponse{}

	defer func() { exitIfUnrecoverable(logger, h.exitChan, response.Error) }()
	defer writeResponse(w, response)

	err = parseRequest(logger, req, request)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}

	before, after, err := h.db.StartActualLRP(logger, request.ActualLrpKey, request.ActualLrpInstanceKey, request.ActualLrpNetInfo)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}

	if before == nil {
		go h.actualHub.Emit(models.NewActualLRPCreatedEvent(after))
	} else if !before.Equal(after) {
		go h.actualHub.Emit(models.NewActualLRPChangedEvent(before, after))
	}
}
func (h *ActualLRPLifecycleHandler) ClaimActualLRP(w http.ResponseWriter, req *http.Request) {
	var err error
	logger := h.logger.Session("claim-actual-lrp")

	request := &models.ClaimActualLRPRequest{}
	response := &models.ActualLRPLifecycleResponse{}
	defer func() { exitIfUnrecoverable(logger, h.exitChan, response.Error) }()
	defer writeResponse(w, response)

	err = parseRequest(logger, req, request)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}

	before, after, err := h.db.ClaimActualLRP(logger, request.ProcessGuid, request.Index, request.ActualLrpInstanceKey)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}

	if !after.Equal(before) {
		go h.actualHub.Emit(models.NewActualLRPChangedEvent(before, after))
	}
}
Example #6
0
func (h *TaskHandler) DesireTask(w http.ResponseWriter, req *http.Request) {
	var err error
	logger := h.logger.Session("desire-task")

	request := &models.DesireTaskRequest{}
	response := &models.TaskLifecycleResponse{}

	defer func() { exitIfUnrecoverable(logger, h.exitChan, response.Error) }()
	defer writeResponse(w, response)

	err = parseRequest(logger, req, request)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}

	logger = logger.WithData(lager.Data{"task_guid": request.TaskGuid})
	err = h.db.DesireTask(logger, request.TaskDefinition, request.TaskGuid, request.Domain)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}

	logger.Debug("start-task-auction-request")
	taskStartRequest := auctioneer.NewTaskStartRequestFromModel(request.TaskGuid, request.Domain, request.TaskDefinition)
	err = h.auctioneerClient.RequestTaskAuctions([]*auctioneer.TaskStartRequest{&taskStartRequest})
	if err != nil {
		logger.Error("failed-requesting-task-auction", err)
		// The creation succeeded, the auction request error can be dropped
	} else {
		logger.Debug("succeeded-requesting-task-auction")
	}
}
func (h *ActualLRPLifecycleHandler) RemoveActualLRP(w http.ResponseWriter, req *http.Request) {
	var err error
	logger := h.logger.Session("remove-actual-lrp")

	request := &models.RemoveActualLRPRequest{}
	response := &models.ActualLRPLifecycleResponse{}

	defer func() { exitIfUnrecoverable(logger, h.exitChan, response.Error) }()
	defer writeResponse(w, response)

	err = parseRequest(logger, req, request)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}

	beforeActualLRPGroup, err := h.db.ActualLRPGroupByProcessGuidAndIndex(logger, request.ProcessGuid, request.Index)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}

	err = h.db.RemoveActualLRP(logger, request.ProcessGuid, request.Index, request.ActualLrpInstanceKey)
	if err != nil {
		response.Error = models.ConvertError(err)
		return

	}
	go h.actualHub.Emit(models.NewActualLRPRemovedEvent(beforeActualLRPGroup))
}
Example #8
0
func (h *TaskHandler) ConvergeTasks(w http.ResponseWriter, req *http.Request) {
	var err error
	logger := h.logger.Session("converge-tasks")

	request := &models.ConvergeTasksRequest{}
	response := &models.ConvergeTasksResponse{}

	defer func() { exitIfUnrecoverable(logger, h.exitChan, response.Error) }()
	defer writeResponse(w, response)

	err = parseRequest(logger, req, request)

	if err != nil {
		response.Error = models.ConvertError(err)
	}

	logger.Debug("listing-cells")
	cellSet, err := h.serviceClient.Cells(logger)
	if err == models.ErrResourceNotFound {
		logger.Debug("no-cells-found")
		cellSet = models.CellSet{}
	} else if err != nil {
		logger.Debug("failed-listing-cells")
		response.Error = models.ConvertError(err)
		return
	}
	logger.Debug("succeeded-listing-cells")

	tasksToAuction, tasksToComplete := h.db.ConvergeTasks(
		logger,
		cellSet,
		time.Duration(request.KickTaskDuration),
		time.Duration(request.ExpirePendingTaskDuration),
		time.Duration(request.ExpireCompletedTaskDuration),
	)

	if len(tasksToAuction) > 0 {
		logger.Debug("requesting-task-auctions", lager.Data{"num_tasks_to_auction": len(tasksToAuction)})
		if err := h.auctioneerClient.RequestTaskAuctions(tasksToAuction); err != nil {
			taskGuids := make([]string, len(tasksToAuction))
			for i, task := range tasksToAuction {
				taskGuids[i] = task.TaskGuid
			}
			logger.Error("failed-to-request-auctions-for-pending-tasks", err,
				lager.Data{"task_guids": taskGuids})
		}
		logger.Debug("done-requesting-task-auctions", lager.Data{"num_tasks_to_auction": len(tasksToAuction)})
	}

	logger.Debug("submitting-tasks-to-be-completed", lager.Data{"num_tasks_to_complete": len(tasksToComplete)})
	for _, task := range tasksToComplete {
		h.taskCompletionClient.Submit(h.db, task)
	}
	logger.Debug("done-submitting-tasks-to-be-completed", lager.Data{"num_tasks_to_complete": len(tasksToComplete)})
}
Example #9
0
func (db *ETCDDB) UnclaimActualLRP(logger lager.Logger, key *models.ActualLRPKey) (*models.ActualLRPGroup, *models.ActualLRPGroup, error) {
	actualLRP, modifiedIndex, err := db.rawActualLRPByProcessGuidAndIndex(logger, key.ProcessGuid, key.Index)
	bbsErr := models.ConvertError(err)
	if bbsErr != nil {
		return nil, nil, bbsErr
	}
	beforeActualLRP := *actualLRP

	if actualLRP.State == models.ActualLRPStateUnclaimed {
		logger.Debug("already-unclaimed")
		return nil, nil, models.ErrActualLRPCannotBeUnclaimed
	}

	actualLRP.State = models.ActualLRPStateUnclaimed
	actualLRP.ActualLRPKey = *key
	actualLRP.ActualLRPInstanceKey = models.ActualLRPInstanceKey{}
	actualLRP.ActualLRPNetInfo = models.EmptyActualLRPNetInfo()
	actualLRP.Since = db.clock.Now().UnixNano()
	actualLRP.ModificationTag.Increment()

	data, err := db.serializeModel(logger, actualLRP)
	if err != nil {
		return nil, nil, err
	}

	_, err = db.client.CompareAndSwap(ActualLRPSchemaPath(key.ProcessGuid, key.Index), data, 0, modifiedIndex)
	if err != nil {
		logger.Error("failed-compare-and-swap", err)
		return nil, nil, ErrorFromEtcdError(logger, err)
	}

	return &models.ActualLRPGroup{Instance: &beforeActualLRP}, &models.ActualLRPGroup{Instance: actualLRP}, nil
}
Example #10
0
func (h *StopAppHandler) StopApp(resp http.ResponseWriter, req *http.Request) {
	processGuid := req.FormValue(":process_guid")
	logger := h.logger.Session("stop-app", lager.Data{"process-guid": processGuid})

	if processGuid == "" {
		logger.Error("missing-process-guid", missingParameterErr)
		resp.WriteHeader(http.StatusBadRequest)
		return
	}

	logger.Info("stop-request-from-cc", lager.Data{"processGuid": processGuid})

	err := h.bbsClient.RemoveDesiredLRP(processGuid)
	if err != nil {
		logger.Error("failed-to-delete-desired-lrp", err)

		bbsError := models.ConvertError(err)
		if bbsError.Type == models.Error_ResourceNotFound {
			resp.WriteHeader(http.StatusNotFound)
			return
		}

		resp.WriteHeader(http.StatusServiceUnavailable)
		return
	}

	resp.WriteHeader(http.StatusAccepted)
}
Example #11
0
func (m Encryptor) Run(signals <-chan os.Signal, ready chan<- struct{}) error {
	logger := m.logger.Session("encryptor")

	currentEncryptionKey, err := m.db.EncryptionKeyLabel(logger)
	if err != nil {
		if models.ConvertError(err) != models.ErrResourceNotFound {
			return err
		}
	} else {
		if m.keyManager.DecryptionKey(currentEncryptionKey) == nil {
			return errors.New("Existing encryption key version (" + currentEncryptionKey + ") is not among the known keys")
		}
	}

	close(ready)

	if currentEncryptionKey != m.keyManager.EncryptionKey().Label() {
		encryptionStart := m.clock.Now()
		logger.Debug("encryption-started")
		m.performEncryption(logger)
		m.db.SetEncryptionKeyLabel(logger, m.keyManager.EncryptionKey().Label())
		totalTime := m.clock.Since(encryptionStart)
		logger.Debug("encryption-finished", lager.Data{"total-time": totalTime})
		encryptionDuration.Send(totalTime)
	}

	select {
	case <-signals:
		return nil
	}
}
func (h *DesiredLRPHandler) DesiredLRPs_r1(w http.ResponseWriter, req *http.Request) {
	var err error
	logger := h.logger.Session("desired-lrps", lager.Data{"revision": 0})

	request := &models.DesiredLRPsRequest{}
	response := &models.DesiredLRPsResponse{}

	err = parseRequest(logger, req, request)
	if err == nil {
		var lrps []*models.DesiredLRP

		filter := models.DesiredLRPFilter{Domain: request.Domain}
		lrps, err = h.desiredLRPDB.DesiredLRPs(logger, filter)
		if err == nil {
			for i := range lrps {
				transformedLRP := lrps[i].VersionDownTo(format.V1)
				response.DesiredLrps = append(response.DesiredLrps, transformedLRP)
			}
		}
	}

	response.Error = models.ConvertError(err)

	writeResponse(w, response)
	exitIfUnrecoverable(logger, h.exitChan, response.Error)
}
Example #13
0
func (p *taskProcessor) completeTask(logger lager.Logger, container executor.Container) {
	var result string
	var err error
	if !container.RunResult.Failed {
		result, err = p.containerDelegate.FetchContainerResultFile(logger, container.Guid, container.Tags[rep.ResultFileTag])
		if err != nil {
			p.failTask(logger, container.Guid, TaskCompletionReasonFailedToFetchResult)
			return
		}
	}

	logger.Info("completing-task")
	err = p.bbsClient.CompleteTask(container.Guid, p.cellID, container.RunResult.Failed, container.RunResult.FailureReason, result)
	if err != nil {
		logger.Error("failed-completing-task", err)

		bbsErr := models.ConvertError(err)
		if bbsErr.Type == models.Error_InvalidStateTransition {
			p.failTask(logger, container.Guid, TaskCompletionReasonInvalidTransition)
		}
		return
	}

	logger.Info("succeeded-completing-task")
}
func (h *ActualLRPLifecycleHandler) CrashActualLRP(w http.ResponseWriter, req *http.Request) {
	logger := h.logger.Session("crash-actual-lrp")

	request := &models.CrashActualLRPRequest{}
	response := &models.ActualLRPLifecycleResponse{}
	defer func() { exitIfUnrecoverable(logger, h.exitChan, response.Error) }()
	defer writeResponse(w, response)

	err := parseRequest(logger, req, request)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}

	actualLRPKey := request.ActualLrpKey
	actualLRPInstanceKey := request.ActualLrpInstanceKey

	before, after, shouldRestart, err := h.db.CrashActualLRP(logger, actualLRPKey, actualLRPInstanceKey, request.ErrorMessage)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}

	if shouldRestart {
		desiredLRP, err := h.desiredLRPDB.DesiredLRPByProcessGuid(logger, actualLRPKey.ProcessGuid)
		if err != nil {
			logger.Error("failed-fetching-desired-lrp", err)
			response.Error = models.ConvertError(err)
			return
		}

		schedInfo := desiredLRP.DesiredLRPSchedulingInfo()
		startRequest := auctioneer.NewLRPStartRequestFromSchedulingInfo(&schedInfo, int(actualLRPKey.Index))
		logger.Info("start-lrp-auction-request", lager.Data{"app_guid": schedInfo.ProcessGuid, "index": int(actualLRPKey.Index)})
		err = h.auctioneerClient.RequestLRPAuctions([]*auctioneer.LRPStartRequest{&startRequest})
		logger.Info("finished-lrp-auction-request", lager.Data{"app_guid": schedInfo.ProcessGuid, "index": int(actualLRPKey.Index)})
		if err != nil {
			logger.Error("failed-requesting-auction", err)
			response.Error = models.ConvertError(err)
			return
		}
	}

	actualLRP, _ := after.Resolve()
	go h.actualHub.Emit(models.NewActualLRPCrashedEvent(actualLRP))
	go h.actualHub.Emit(models.NewActualLRPChangedEvent(before, after))
}
Example #15
0
func (h *TaskHandler) CancelTask(w http.ResponseWriter, req *http.Request) {
	logger := h.logger.Session("cancel-task")

	request := &models.TaskGuidRequest{}
	response := &models.TaskLifecycleResponse{}
	defer func() { exitIfUnrecoverable(logger, h.exitChan, response.Error) }()
	defer writeResponse(w, response)

	err := parseRequest(logger, req, request)
	if err != nil {
		logger.Error("failed-parsing-request", err)
		response.Error = models.ConvertError(err)
		return
	}

	task, cellID, err := h.db.CancelTask(logger, request.TaskGuid)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}

	if task.CompletionCallbackUrl != "" {
		logger.Info("task-client-completing-task")
		go h.taskCompletionClient.Submit(h.db, task)
	}

	if cellID == "" {
		return
	}

	logger.Info("start-check-cell-presence", lager.Data{"cell_id": cellID})
	cellPresence, err := h.serviceClient.CellById(logger, cellID)
	if err != nil {
		logger.Error("failed-fetching-cell-presence", err)
		return
	}
	logger.Info("finished-check-cell-presence", lager.Data{"cell_id": cellID})

	repClient := h.repClientFactory.CreateClient(cellPresence.RepAddress)
	logger.Info("start-rep-cancel-task", lager.Data{"task_guid": request.TaskGuid})
	repClient.CancelTask(request.TaskGuid)
	if err != nil {
		logger.Error("failed-rep-cancel-task", err)
		return
	}
	logger.Info("finished-rep-cancel-task", lager.Data{"task_guid": request.TaskGuid})
}
Example #16
0
func (h *DomainHandler) Domains(w http.ResponseWriter, req *http.Request) {
	var err error
	logger := h.logger.Session("domains")
	response := &models.DomainsResponse{}
	response.Domains, err = h.db.Domains(logger)
	response.Error = models.ConvertError(err)
	writeResponse(w, response)
}
func (h *ActualLRPLifecycleHandler) RetireActualLRP(w http.ResponseWriter, req *http.Request) {
	logger := h.logger.Session("retire-actual-lrp")
	request := &models.RetireActualLRPRequest{}
	response := &models.ActualLRPLifecycleResponse{}

	var err error
	defer func() { exitIfUnrecoverable(logger, h.exitChan, response.Error) }()
	defer writeResponse(w, response)

	err = parseRequest(logger, req, request)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}

	err = h.retirer.RetireActualLRP(logger, request.ActualLrpKey.ProcessGuid, request.ActualLrpKey.Index)
	response.Error = models.ConvertError(err)
}
Example #18
0
func (db *ETCDDB) StartActualLRP(logger lager.Logger, key *models.ActualLRPKey, instanceKey *models.ActualLRPInstanceKey, netInfo *models.ActualLRPNetInfo) (*models.ActualLRPGroup, *models.ActualLRPGroup, error) {
	logger = logger.WithData(lager.Data{
		"actual_lrp_key":          key,
		"actual_lrp_instance_key": instanceKey,
		"net_info":                netInfo,
	})

	logger.Info("starting")
	defer logger.Info("completed")

	lrp, prevIndex, err := db.rawActualLRPByProcessGuidAndIndex(logger, key.ProcessGuid, key.Index)
	bbsErr := models.ConvertError(err)
	if bbsErr != nil {
		if bbsErr.Type == models.Error_ResourceNotFound {
			lrp, err := db.createRunningActualLRP(logger, key, instanceKey, netInfo)
			return nil, &models.ActualLRPGroup{Instance: lrp}, err
		}
		logger.Error("failed-to-get-actual-lrp", err)
		return nil, nil, err
	}
	beforeActualLRP := *lrp

	if lrp.ActualLRPKey.Equal(key) &&
		lrp.ActualLRPInstanceKey.Equal(instanceKey) &&
		lrp.ActualLRPNetInfo.Equal(netInfo) &&
		lrp.State == models.ActualLRPStateRunning {
		lrpGroup := &models.ActualLRPGroup{Instance: lrp}
		return lrpGroup, lrpGroup, nil
	}

	if !lrp.AllowsTransitionTo(key, instanceKey, models.ActualLRPStateRunning) {
		logger.Error("failed-to-transition-actual-lrp-to-started", nil)
		return nil, nil, models.ErrActualLRPCannotBeStarted
	}

	lrp.ModificationTag.Increment()
	lrp.State = models.ActualLRPStateRunning
	lrp.Since = db.clock.Now().UnixNano()
	lrp.ActualLRPInstanceKey = *instanceKey
	lrp.ActualLRPNetInfo = *netInfo
	lrp.PlacementError = ""

	lrpData, serializeErr := db.serializeModel(logger, lrp)
	if serializeErr != nil {
		return nil, nil, serializeErr
	}

	_, err = db.client.CompareAndSwap(ActualLRPSchemaPath(key.ProcessGuid, key.Index), lrpData, 0, prevIndex)
	if err != nil {
		logger.Error("failed", err)
		return nil, nil, models.ErrActualLRPCannotBeStarted
	}

	return &models.ActualLRPGroup{Instance: &beforeActualLRP}, &models.ActualLRPGroup{Instance: lrp}, nil
}
Example #19
0
func (p *ordinaryLRPProcessor) claimLRPContainer(logger lager.Logger, lrpContainer *lrpContainer) bool {
	err := p.bbsClient.ClaimActualLRP(lrpContainer.ProcessGuid, int(lrpContainer.Index), lrpContainer.ActualLRPInstanceKey)
	bbsErr := models.ConvertError(err)
	if err != nil {
		if bbsErr.Type == models.Error_ActualLRPCannotBeClaimed {
			p.containerDelegate.DeleteContainer(logger, lrpContainer.Guid)
		}
		return false
	}
	return true
}
Example #20
0
func (db *ETCDDB) RetireActualLRP(logger lager.Logger, key *models.ActualLRPKey) error {
	logger = logger.Session("retire-actual-lrp", lager.Data{"actual_lrp_key": key})
	var err error
	var prevIndex uint64
	var lrp *models.ActualLRP
	processGuid := key.ProcessGuid
	index := key.Index

	for i := 0; i < models.RetireActualLRPRetryAttempts; i++ {
		lrp, prevIndex, err = db.rawActuaLLRPByProcessGuidAndIndex(logger, processGuid, index)
		if err != nil {
			break
		}

		switch lrp.State {
		case models.ActualLRPStateUnclaimed, models.ActualLRPStateCrashed:
			err = db.removeActualLRP(logger, lrp, prevIndex)
		default:
			var cell *models.CellPresence
			key := lrp.ActualLRPKey
			instanceKey := lrp.ActualLRPInstanceKey
			cell, err = db.serviceClient.CellById(logger, instanceKey.CellId)
			if err != nil {
				bbsErr := models.ConvertError(err)
				if bbsErr.Type == models.Error_ResourceNotFound {
					err = db.removeActualLRP(logger, lrp, prevIndex)
				}
				err = err
				break
			}

			logger.Info("stopping-lrp-instance", lager.Data{
				"actual-lrp-key": key,
			})

			repClient := db.repClientFactory.CreateClient(cell.RepAddress)
			cellErr := repClient.StopLRPInstance(key, instanceKey)
			if cellErr != nil {
				err = models.ErrActualLRPCannotBeStopped
			}
		}

		if err == nil {
			break
		}

		if i+1 < models.RetireActualLRPRetryAttempts {
			logger.Error("retrying-failed-retire-of-actual-lrp", err, lager.Data{"attempt": i + 1})
		}
	}

	return err
}
Example #21
0
func (db *ETCDDB) UpdateDesiredLRP(logger lager.Logger, processGuid string, update *models.DesiredLRPUpdate) error {
	logger = logger.Session("update-desired-lrp", lager.Data{"process-guid": processGuid})
	logger.Info("starting")
	defer logger.Info("complete")

	var schedulingInfo *models.DesiredLRPSchedulingInfo
	var existingInstances int32
	var err error

	for i := 0; i < 2; i++ {
		var index uint64

		schedulingInfo, index, err = db.rawDesiredLRPSchedulingInfo(logger, processGuid)
		if err != nil {
			logger.Error("failed-to-fetch-scheduling-info", err)
			break
		}

		existingInstances = schedulingInfo.Instances

		schedulingInfo.ApplyUpdate(update)

		err = db.updateDesiredLRPSchedulingInfo(logger, schedulingInfo, index)
		if err != nil {
			logger.Error("update-scheduling-info-failed", err)
			modelErr := models.ConvertError(err)
			if modelErr != models.ErrResourceConflict {
				break
			}
			// Retry on CAS fail
			continue
		}

		break
	}

	if err != nil {
		return err
	}

	switch diff := schedulingInfo.Instances - existingInstances; {
	case diff > 0:
		db.startInstanceRange(logger, existingInstances, schedulingInfo.Instances, schedulingInfo)

	case diff < 0:
		db.stopInstanceRange(logger, schedulingInfo.Instances, existingInstances, schedulingInfo)

	case diff == 0:
		// this space intentionally left blank
	}

	return nil
}
Example #22
0
func (db *ETCDDB) EvacuateActualLRP(
	logger lager.Logger,
	lrpKey *models.ActualLRPKey,
	instanceKey *models.ActualLRPInstanceKey,
	netInfo *models.ActualLRPNetInfo,
	ttl uint64,
) (*models.ActualLRPGroup, error) {
	logger = logger.Session("evacuate-actual-lrp", lager.Data{"process_guid": lrpKey.ProcessGuid, "index": lrpKey.Index})

	logger.Debug("starting")
	defer logger.Debug("complete")

	node, err := db.fetchRaw(logger, EvacuatingActualLRPSchemaPath(lrpKey.ProcessGuid, lrpKey.Index))
	bbsErr := models.ConvertError(err)
	if bbsErr != nil {
		if bbsErr.Type == models.Error_ResourceNotFound {
			return db.createEvacuatingActualLRP(logger, lrpKey, instanceKey, netInfo, ttl)
		}
		return nil, bbsErr
	}

	lrp := models.ActualLRP{}
	err = db.deserializeModel(logger, node, &lrp)
	if err != nil {
		return nil, err
	}

	if lrp.ActualLRPKey.Equal(lrpKey) &&
		lrp.ActualLRPInstanceKey.Equal(instanceKey) &&
		reflect.DeepEqual(lrp.ActualLRPNetInfo, *netInfo) {
		return &models.ActualLRPGroup{Evacuating: &lrp}, nil
	}

	lrp.ActualLRPNetInfo = *netInfo
	lrp.ActualLRPKey = *lrpKey
	lrp.ActualLRPInstanceKey = *instanceKey
	lrp.Since = db.clock.Now().UnixNano()
	lrp.ModificationTag.Increment()

	data, err := db.serializeModel(logger, &lrp)
	if err != nil {
		logger.Error("failed-serializing", err)
		return nil, err
	}

	_, err = db.client.CompareAndSwap(EvacuatingActualLRPSchemaPath(lrp.ProcessGuid, lrp.Index), data, ttl, node.ModifiedIndex)
	if err != nil {
		return nil, ErrorFromEtcdError(logger, err)
	}

	return &models.ActualLRPGroup{Evacuating: &lrp}, nil
}
Example #23
0
func (db *ETCDDB) ActualLRPGroups(logger lager.Logger, filter models.ActualLRPFilter) ([]*models.ActualLRPGroup, error) {
	node, err := db.fetchRecursiveRaw(logger, ActualLRPSchemaRoot)
	bbsErr := models.ConvertError(err)
	if bbsErr != nil {
		if bbsErr.Type == models.Error_ResourceNotFound {
			return []*models.ActualLRPGroup{}, nil
		}
		return nil, err
	}
	if len(node.Nodes) == 0 {
		return []*models.ActualLRPGroup{}, nil
	}

	groups := []*models.ActualLRPGroup{}

	var workErr atomic.Value
	groupChan := make(chan []*models.ActualLRPGroup, len(node.Nodes))
	wg := sync.WaitGroup{}

	logger.Debug("performing-deserialization-work")
	for _, node := range node.Nodes {
		node := node

		wg.Add(1)
		go func() {
			defer wg.Done()
			g, err := db.parseActualLRPGroups(logger, node, filter)
			if err != nil {
				workErr.Store(err)
				return
			}
			groupChan <- g
		}()
	}

	go func() {
		wg.Wait()
		close(groupChan)
	}()

	for g := range groupChan {
		groups = append(groups, g...)
	}

	if err, ok := workErr.Load().(error); ok {
		logger.Error("failed-performing-deserialization-work", err)
		return []*models.ActualLRPGroup{}, models.ErrUnknownError
	}
	logger.Debug("succeeded-performing-deserialization-work", lager.Data{"num_actual_lrp_groups": len(groups)})

	return groups, nil
}
func (h *DesireAppHandler) getDesiredLRP(processGuid string) (*models.DesiredLRP, error) {
	lrp, err := h.bbsClient.DesiredLRPByProcessGuid(processGuid)
	if err == nil {
		return lrp, nil
	}

	bbsError := models.ConvertError(err)
	if bbsError.Type == models.Error_ResourceNotFound {
		return nil, nil
	}

	return nil, err
}
Example #25
0
func (h *CellHandler) Cells(w http.ResponseWriter, req *http.Request) {
	var err error
	logger := h.logger.Session("cells")
	response := &models.CellsResponse{}
	cellSet, err := h.serviceClient.Cells(h.logger)
	cells := []*models.CellPresence{}
	for _, cp := range cellSet {
		cells = append(cells, cp)
	}
	response.Cells = cells
	response.Error = models.ConvertError(err)
	writeResponse(w, response)
	exitIfUnrecoverable(logger, h.exitChan, response.Error)
}
Example #26
0
func (h *EvacuationHandler) EvacuateStoppedActualLRP(w http.ResponseWriter, req *http.Request) {
	var err error
	logger := h.logger.Session("evacuate-stopped-actual-lrp")
	request := &models.EvacuateStoppedActualLRPRequest{}
	response := &models.EvacuationResponse{}

	err = parseRequest(logger, req, request)
	if err == nil {
		response.KeepContainer, err = h.db.EvacuateStoppedActualLRP(logger, request.ActualLrpKey, request.ActualLrpInstanceKey)
	}

	response.Error = models.ConvertError(err)
	writeResponse(w, response)
}
Example #27
0
func (db *ETCDDB) desiredLRPs(logger lager.Logger, filter models.DesiredLRPFilter) ([]*models.DesiredLRP, guidSet, error) {
	root, err := db.fetchRecursiveRaw(logger, DesiredLRPComponentsSchemaRoot)
	bbsErr := models.ConvertError(err)
	if bbsErr != nil {
		if bbsErr.Type == models.Error_ResourceNotFound {
			return []*models.DesiredLRP{}, newGuidSet(), nil
		}
		return nil, newGuidSet(), err
	}
	if root.Nodes.Len() == 0 {
		return []*models.DesiredLRP{}, newGuidSet(), nil
	}

	var schedules map[string]*models.DesiredLRPSchedulingInfo
	var runs map[string]*models.DesiredLRPRunInfo
	var malformedInfos guidSet
	var malformedRunInfos guidSet
	var wg sync.WaitGroup
	for i := range root.Nodes {
		node := root.Nodes[i]
		switch node.Key {
		case DesiredLRPSchedulingInfoSchemaRoot:
			wg.Add(1)
			go func() {
				defer wg.Done()
				schedules, malformedInfos = db.deserializeScheduleInfos(logger, node.Nodes, filter)
			}()
		case DesiredLRPRunInfoSchemaRoot:
			wg.Add(1)
			go func() {
				defer wg.Done()
				runs, malformedRunInfos = db.deserializeRunInfos(logger, node.Nodes, filter)
			}()
		default:
			logger.Error("unexpected-etcd-key", nil, lager.Data{"key": node.Key})
		}
	}

	wg.Wait()

	desiredLRPs := []*models.DesiredLRP{}
	for processGuid, schedule := range schedules {
		desired := models.NewDesiredLRP(*schedule, *runs[processGuid])
		desiredLRPs = append(desiredLRPs, &desired)
	}

	malformedInfos.Merge(malformedRunInfos)
	return desiredLRPs, malformedInfos, nil
}
func (h *DesiredLRPHandler) DesiredLRPByProcessGuid(w http.ResponseWriter, req *http.Request) {
	var err error
	logger := h.logger.Session("desired-lrp-by-process-guid")

	request := &models.DesiredLRPByProcessGuidRequest{}
	response := &models.DesiredLRPResponse{}

	err = parseRequest(logger, req, request)
	if err == nil {
		response.DesiredLrp, err = h.db.DesiredLRPByProcessGuid(logger, request.ProcessGuid)
	}

	response.Error = models.ConvertError(err)
	writeResponse(w, response)
}
Example #29
0
func (db *ETCDDB) ActualLRPGroupsByProcessGuid(logger lager.Logger, processGuid string) ([]*models.ActualLRPGroup, error) {
	node, err := db.fetchRecursiveRaw(logger, ActualLRPProcessDir(processGuid))
	bbsErr := models.ConvertError(err)
	if bbsErr != nil {
		if bbsErr.Type == models.Error_ResourceNotFound {
			return []*models.ActualLRPGroup{}, nil
		}
		return nil, err
	}
	if node.Nodes.Len() == 0 {
		return []*models.ActualLRPGroup{}, nil
	}

	return db.parseActualLRPGroups(logger, node, models.ActualLRPFilter{})
}
func (h *DesiredLRPHandler) UpdateDesiredLRP(w http.ResponseWriter, req *http.Request) {
	var err error
	logger := h.logger.Session("update-desired-lrp")

	request := &models.UpdateDesiredLRPRequest{}
	response := &models.DesiredLRPLifecycleResponse{}

	err = parseRequest(logger, req, request)
	if err == nil {
		err = h.db.UpdateDesiredLRP(logger, request.ProcessGuid, request.Update)
	}

	response.Error = models.ConvertError(err)
	writeResponse(w, response)
}