Beispiel #1
0
func (db *ETCDDB) UpdateDesiredLRP(logger lager.Logger, processGuid string, update *models.DesiredLRPUpdate) (*models.DesiredLRP, error) {
	logger.Info("starting")
	defer logger.Info("complete")

	var schedulingInfo *models.DesiredLRPSchedulingInfo
	var err error
	var beforeDesiredLRP *models.DesiredLRP

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

		beforeDesiredLRP, index, err = db.rawDesiredLRPByProcessGuid(logger, processGuid)
		if err != nil {
			logger.Error("failed-to-fetch-desired-lrp", err)
			break
		}

		schedulingInfoValue := beforeDesiredLRP.DesiredLRPSchedulingInfo()
		schedulingInfo = &schedulingInfoValue
		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 nil, err
	}

	return beforeDesiredLRP, nil
}
func (h *DesiredLRPHandler) DesiredLRPByProcessGuid_r1(logger lager.Logger, w http.ResponseWriter, req *http.Request) {
	var err error
	logger = logger.Session("desired-lrp-by-process-guid", lager.Data{"revision": 1})

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

	err = parseRequest(logger, req, request)
	if err == nil {
		var lrp *models.DesiredLRP
		lrp, err = h.desiredLRPDB.DesiredLRPByProcessGuid(logger, request.ProcessGuid)
		if err == nil {
			transformedLRP := lrp.VersionDownTo(format.V1)
			response.DesiredLrp = transformedLRP
		}
	}

	response.Error = models.ConvertError(err)

	writeResponse(w, response)
	exitIfUnrecoverable(logger, h.exitChan, response.Error)
}
func (m *SplitDesiredLRP) WriteRunInfo(logger lager.Logger, desiredLRP models.DesiredLRP) {
	environmentVariables := make([]models.EnvironmentVariable, len(desiredLRP.EnvironmentVariables))
	for i := range desiredLRP.EnvironmentVariables {
		environmentVariables[i] = *desiredLRP.EnvironmentVariables[i]
	}

	egressRules := make([]models.SecurityGroupRule, len(desiredLRP.EgressRules))
	for i := range desiredLRP.EgressRules {
		egressRules[i] = *desiredLRP.EgressRules[i]
	}

	runInfo := models.DesiredLRPRunInfo{
		DesiredLRPKey:        desiredLRP.DesiredLRPKey(),
		EnvironmentVariables: environmentVariables,
		Setup:                desiredLRP.Setup,
		Action:               desiredLRP.Action,
		Monitor:              desiredLRP.Monitor,
		StartTimeoutMs:       desiredLRP.StartTimeoutMs,
		Privileged:           desiredLRP.Privileged,
		CpuWeight:            desiredLRP.CpuWeight,
		Ports:                desiredLRP.Ports,
		EgressRules:          egressRules,
		LogSource:            desiredLRP.LogSource,
		MetricsGuid:          desiredLRP.MetricsGuid,
	}

	runInfoPayload, marshalErr := m.serializer.Marshal(logger, format.ENCRYPTED_PROTO, &runInfo)
	if marshalErr != nil {
		logger.Error("failed-marshaling-run-info", marshalErr, lager.Data{"process_guid": runInfo.ProcessGuid})
	}

	_, setErr := m.storeClient.Set(etcd.DesiredLRPRunInfoSchemaPath(runInfo.ProcessGuid), runInfoPayload, etcd.NO_TTL)
	if setErr != nil {
		logger.Error("failed-set-of-run-info", marshalErr, lager.Data{"process_guid": runInfo.ProcessGuid})
	}
}
func (m *SplitDesiredLRP) WriteSchedulingInfo(logger lager.Logger, desiredLRP models.DesiredLRP) {
	schedulingInfo := models.DesiredLRPSchedulingInfo{
		DesiredLRPKey:      desiredLRP.DesiredLRPKey(),
		Annotation:         desiredLRP.Annotation,
		Instances:          desiredLRP.Instances,
		DesiredLRPResource: desiredLRP.DesiredLRPResource(),
	}
	if desiredLRP.Routes != nil {
		schedulingInfo.Routes = *desiredLRP.Routes
	}
	if desiredLRP.ModificationTag != nil {
		schedulingInfo.ModificationTag = *desiredLRP.ModificationTag
	}

	schedulingInfoPayload, marshalErr := m.serializer.Marshal(logger, format.ENCRYPTED_PROTO, &schedulingInfo)
	if marshalErr != nil {
		logger.Error("failed-marshaling-scheduling-info", marshalErr, lager.Data{"process_guid": schedulingInfo.ProcessGuid})
	}

	_, setErr := m.storeClient.Set(etcd.DesiredLRPSchedulingInfoSchemaPath(desiredLRP.ProcessGuid), schedulingInfoPayload, etcd.NO_TTL)
	if setErr != nil {
		logger.Error("failed-set-of-scheduling-info", marshalErr, lager.Data{"process_guid": schedulingInfo.ProcessGuid})
	}
}
Beispiel #5
0
// DesireLRP creates a DesiredLRPSchedulingInfo and a DesiredLRPRunInfo. In order
// to ensure that the complete model is available and there are no races in
// Desired Watches, DesiredLRPRunInfo is created before DesiredLRPSchedulingInfo.
func (db *ETCDDB) DesireLRP(logger lager.Logger, desiredLRP *models.DesiredLRP) error {
	logger = logger.WithData(lager.Data{"process_guid": desiredLRP.ProcessGuid})
	logger.Info("starting")
	defer logger.Info("complete")

	schedulingInfo, runInfo := desiredLRP.CreateComponents(db.clock.Now())

	err := db.createDesiredLRPRunInfo(logger, &runInfo)
	if err != nil {
		return err
	}

	schedulingErr := db.createDesiredLRPSchedulingInfo(logger, &schedulingInfo)
	if schedulingErr != nil {
		logger.Info("deleting-orphaned-run-info")
		_, err = db.client.Delete(DesiredLRPRunInfoSchemaPath(desiredLRP.ProcessGuid), true)
		if err != nil {
			logger.Error("failed-deleting-orphaned-run-info", err)
		}
		return schedulingErr
	}

	return nil
}
Beispiel #6
0
func (db *SQLDB) DesireLRP(logger lager.Logger, desiredLRP *models.DesiredLRP) error {
	logger = logger.WithData(lager.Data{"process_guid": desiredLRP.ProcessGuid})
	logger.Info("starting")
	defer logger.Info("complete")

	return db.transact(logger, func(logger lager.Logger, tx *sql.Tx) error {
		routesData, err := db.encodeRouteData(logger, desiredLRP.Routes)
		if err != nil {
			logger.Error("failed-encoding-route-data", err)
			return err
		}

		runInfo := desiredLRP.DesiredLRPRunInfo(db.clock.Now())

		runInfoData, err := db.serializeModel(logger, &runInfo)
		if err != nil {
			logger.Error("failed-to-serialize-model", err)
			return err
		}

		volumePlacement := &models.VolumePlacement{}
		volumePlacement.DriverNames = []string{}
		for _, mount := range desiredLRP.VolumeMounts {
			volumePlacement.DriverNames = append(volumePlacement.DriverNames, mount.Driver)
		}

		volumePlacementData, err := db.serializeModel(logger, volumePlacement)
		if err != nil {
			logger.Error("failed-to-serialize-model", err)
			return err
		}

		guid, err := db.guidProvider.NextGUID()
		if err != nil {
			logger.Error("failed-to-generate-guid", err)
			return models.ErrGUIDGeneration
		}

		placementTagData, err := json.Marshal(desiredLRP.PlacementTags)
		if err != nil {
			logger.Error("failed-to-serialize-model", err)
			return err
		}

		desiredLRP.ModificationTag = &models.ModificationTag{Epoch: guid, Index: 0}

		_, err = db.insert(logger, tx, desiredLRPsTable,
			SQLAttributes{
				"process_guid":           desiredLRP.ProcessGuid,
				"domain":                 desiredLRP.Domain,
				"log_guid":               desiredLRP.LogGuid,
				"annotation":             desiredLRP.Annotation,
				"instances":              desiredLRP.Instances,
				"memory_mb":              desiredLRP.MemoryMb,
				"disk_mb":                desiredLRP.DiskMb,
				"rootfs":                 desiredLRP.RootFs,
				"volume_placement":       volumePlacementData,
				"modification_tag_epoch": desiredLRP.ModificationTag.Epoch,
				"modification_tag_index": desiredLRP.ModificationTag.Index,
				"routes":                 routesData,
				"run_info":               runInfoData,
				"placement_tags":         placementTagData,
			},
		)
		if err != nil {
			logger.Error("failed-inserting-desired", err)
			return db.convertSQLError(err)
		}
		return nil
	})
}
			It("provides relevant error information", func() {
				Expect(responseRecorder.Code).To(Equal(http.StatusOK))
				response := models.DesiredLRPSchedulingInfosResponse{}
				err := response.Unmarshal(responseRecorder.Body.Bytes())
				Expect(err).NotTo(HaveOccurred())

				Expect(response.Error).To(Equal(models.ErrUnknownError))
			})
		})
	})

	Describe("DesireDesiredLRP", func() {
		var (
			desiredLRP *models.DesiredLRP

			requestBody interface{}
		)

		BeforeEach(func() {
			desiredLRP = model_helpers.NewValidDesiredLRP("some-guid")
			desiredLRP.Instances = 5
			requestBody = &models.DesireLRPRequest{
				DesiredLrp: desiredLRP,
			}
		})

		JustBeforeEach(func() {
			request := newTestRequest(requestBody)
			handler.DesireDesiredLRP(logger, responseRecorder, request)
		})
				etcdRunner.Stop()
			})

			AfterEach(func() {
				etcdRunner.Start()
			})

			It("errors", func() {
				_, err := etcdDB.DesiredLRPSchedulingInfos(logger, filter)
				Expect(err).To(HaveOccurred())
			})
		})
	})

	Describe("DesireLRP", func() {
		var lrp *models.DesiredLRP

		BeforeEach(func() {
			lrp = model_helpers.NewValidDesiredLRP("some-process-guid")
			lrp.Instances = 5
		})

		Context("when the desired LRP does not yet exist", func() {
			It("persists the scheduling info and run info", func() {
				err := etcdDB.DesireLRP(logger, lrp)
				Expect(err).NotTo(HaveOccurred())

				persisted, err := etcdDB.DesiredLRPByProcessGuid(logger, "some-process-guid")
				Expect(err).NotTo(HaveOccurred())

				Expect(persisted.DesiredLRPKey()).To(Equal(lrp.DesiredLRPKey()))
			Context("when there are no actions", func() {
				BeforeEach(func() {
					task.Action = nil
				})

				It("does nothing", func() {
					Expect(migrationErr).NotTo(HaveOccurred())
					_, err := db.TaskByGuid(logger, task.TaskGuid)
					Expect(err).NotTo(HaveOccurred())
				})
			})
		})

		Describe("DesiredLRP Migration", func() {
			var (
				processGuid string
				desiredLRP  *models.DesiredLRP
			)

			BeforeEach(func() {
				processGuid = "process-guid-1"
				desiredLRP = model_helpers.NewValidDesiredLRP(processGuid)
				desiredLRP.DeprecatedStartTimeoutS = 15
				desiredLRP.Action = models.WrapAction(&models.TimeoutAction{Action: models.WrapAction(&models.RunAction{Path: "ls", User: "******"}),
					DeprecatedTimeoutNs: 4 * int64(time.Second),
				})

				desiredLRP.Setup = models.WrapAction(&models.TimeoutAction{Action: models.WrapAction(&models.RunAction{Path: "ls", User: "******"}),
					DeprecatedTimeoutNs: 7 * int64(time.Second),
				})
				desiredLRP.Monitor = models.WrapAction(models.EmitProgressFor(
					&models.TimeoutAction{
					"domain-0",
				),
				State:       models.ActualLRPStateUnclaimed,
				Since:       1138,
				CrashCount:  1,
				CrashReason: errorMessage,
			}
		})

		JustBeforeEach(func() {
			request := newTestRequest(requestBody)
			handler.CrashActualLRP(logger, responseRecorder, request)
		})

		Context("when crashing the actual lrp in the DB succeeds", func() {
			var desiredLRP *models.DesiredLRP

			BeforeEach(func() {
				desiredLRP = &models.DesiredLRP{
					ProcessGuid: "process-guid",
					Domain:      "some-domain",
					RootFs:      "some-stack",
					MemoryMb:    128,
					DiskMb:      512,
				}

				fakeDesiredLRPDB.DesiredLRPByProcessGuidReturns(desiredLRP, nil)
				fakeActualLRPDB.CrashActualLRPReturns(&models.ActualLRPGroup{Instance: &actualLRP}, &models.ActualLRPGroup{Instance: &afterActualLRP}, true, nil)
			})

			It("response with no error", func() {
	"code.cloudfoundry.org/lager"
	"code.cloudfoundry.org/lager/lagertest"
	"code.cloudfoundry.org/rep"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
)

var _ = Describe("DesiredLRP Handlers", func() {
	var (
		logger               *lagertest.TestLogger
		fakeDesiredLRPDB     *dbfakes.FakeDesiredLRPDB
		fakeActualLRPDB      *dbfakes.FakeActualLRPDB
		fakeAuctioneerClient *auctioneerfakes.FakeClient
		desiredHub           *eventfakes.FakeHub
		actualHub            *eventfakes.FakeHub
		responseRecorder     *httptest.ResponseRecorder
		handler              *handlers.DesiredLRPHandler
		exitCh               chan struct{}

		desiredLRP1 models.DesiredLRP
		desiredLRP2 models.DesiredLRP
	)

	BeforeEach(func() {
		fakeDesiredLRPDB = new(dbfakes.FakeDesiredLRPDB)
		fakeActualLRPDB = new(dbfakes.FakeActualLRPDB)
		fakeAuctioneerClient = new(auctioneerfakes.FakeClient)
		logger = lagertest.NewTestLogger("test")
		responseRecorder = httptest.NewRecorder()
		desiredHub = new(eventfakes.FakeHub)
		actualHub = new(eventfakes.FakeHub)
Beispiel #12
0
func (t *ETCDHelper) SetRawDesiredLRP(lrp *models.DesiredLRP) {
	schedulingInfo, runInfo := lrp.CreateComponents(t.clock.Now())

	t.SetRawDesiredLRPSchedulingInfo(&schedulingInfo)
	t.SetRawDesiredLRPRunInfo(&runInfo)
}
Beispiel #13
0
				Expect(err).NotTo(HaveOccurred())
				rowsAffected, err := result.RowsAffected()
				Expect(err).NotTo(HaveOccurred())
				Expect(rowsAffected).To(BeEquivalentTo(1))
			})

			It("excludes the invalid desired LRP from the response", func() {
				desiredLRPSchedulingInfos, err := sqlDB.DesiredLRPSchedulingInfos(logger, models.DesiredLRPFilter{})
				Expect(err).NotTo(HaveOccurred())
				Expect(desiredLRPSchedulingInfos).To(HaveLen(1))
			})
		})
	})

	Describe("UpdateDesiredLRP", func() {
		var expectedDesiredLRP *models.DesiredLRP
		var update *models.DesiredLRPUpdate

		BeforeEach(func() {
			desiredLRPGuid := "desired-lrp-guid"
			expectedDesiredLRP = model_helpers.NewValidDesiredLRP(desiredLRPGuid)
			Expect(sqlDB.DesireLRP(logger, expectedDesiredLRP)).To(Succeed())
			instances := int32(1)
			update = &models.DesiredLRPUpdate{
				Instances: &instances,
			}
		})

		It("updates the lrp", func() {
			instances := int32(123)
			routeContent := []byte("{}")
			})
		})

		Describe("Desired LRPs", func() {
			var (
				existingDesiredLRPs []migrations.ETCDToSQLDesiredLRP
				desiredLRPsToCreate int
			)

			BeforeEach(func() {
				encoder := format.NewEncoder(cryptor)

				desiredLRPsToCreate = 3
				for i := 0; i < desiredLRPsToCreate; i++ {
					processGuid := fmt.Sprintf("process-guid-%d", i)
					var desiredLRP *models.DesiredLRP
					desiredLRP = model_helpers.NewValidDesiredLRP(processGuid)

					schedulingInfo, runInfo := desiredLRP.CreateComponents(fakeClock.Now())

					var (
						encryptedVolumePlacement []byte
						err                      error
					)
					if i == 0 { // test for nil and full VolumePlacements
						schedulingInfo.VolumePlacement = nil
						encryptedVolumePlacement, err = serializer.Marshal(logger, format.ENCRYPTED_PROTO, &models.VolumePlacement{})
					} else {
						encryptedVolumePlacement, err = serializer.Marshal(logger, format.ENCRYPTED_PROTO, schedulingInfo.VolumePlacement)
					}
					Expect(err).NotTo(HaveOccurred())
Beispiel #15
0
			It("has the correct number of responses", func() {
				Expect(actualDesiredLRPs).To(HaveLen(2))
			})

			It("returns only the desired lrps in the requested domain", func() {
				for _, lrp := range desiredLRPs[domain] {
					expectedDesiredLRPs = append(expectedDesiredLRPs, lrp)
				}
				Expect(actualDesiredLRPs).To(ConsistOf(expectedDesiredLRPs))
			})
		})
	})

	Describe("DesiredLRPByProcessGuid", func() {
		var (
			desiredLRP         *models.DesiredLRP
			expectedDesiredLRP *models.DesiredLRP
		)

		JustBeforeEach(func() {
			expectedDesiredLRP = desiredLRPs["domain-1"][0]
			desiredLRP, getErr = client.DesiredLRPByProcessGuid(logger, expectedDesiredLRP.GetProcessGuid())
			desiredLRP.ModificationTag.Epoch = "epoch"
		})

		It("responds without error", func() {
			Expect(getErr).NotTo(HaveOccurred())
		})

		It("returns all desired lrps from the bbs", func() {
			Expect(desiredLRP).To(Equal(expectedDesiredLRP))
		})
Beispiel #16
0
	"encoding/json"
	"fmt"
	"time"

	"code.cloudfoundry.org/bbs/format"
	"code.cloudfoundry.org/bbs/models"
	"code.cloudfoundry.org/bbs/models/test/model_helpers"
	"github.com/gogo/protobuf/proto"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/ginkgo/extensions/table"
	. "github.com/onsi/gomega"
)

var _ = Describe("DesiredLRP", func() {
	var desiredLRP models.DesiredLRP

	jsonDesiredLRP := `{
    "setup": {
      "serial": {
        "actions": [
          {
            "download": {
              "from": "http://file-server.service.cf.internal:8080/v1/static/buildpack_app_lifecycle/buildpack_app_lifecycle.tgz",
              "to": "/tmp/lifecycle",
              "cache_key": "buildpack-cflinuxfs2-lifecycle",
							"user": "******",
							"checksum_algorithm": "md5",
							"checksum_value": "some random value"
            }
          },