func (store *GardenStore) Create(logger lager.Logger, container executor.Container) (executor.Container, error) { if container.State != executor.StateInitializing { return executor.Container{}, executor.ErrInvalidTransition } container.State = executor.StateCreated logStreamer := log_streamer.New( container.LogConfig.Guid, container.LogConfig.SourceName, container.LogConfig.Index, ) fmt.Fprintf(logStreamer.Stdout(), "Creating container\n") container, err := store.exchanger.CreateInGarden(logger, store.gardenClient, container) if err != nil { fmt.Fprintf(logStreamer.Stderr(), "Failed to create container\n") return executor.Container{}, err } fmt.Fprintf(logStreamer.Stdout(), "Successfully created container\n") return container, nil }
package executor_test import ( "github.com/cloudfoundry-incubator/executor" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) var _ = Describe("Container", func() { Describe("HasTags", func() { var container executor.Container Context("when tags are nil", func() { BeforeEach(func() { container = executor.Container{ Tags: nil, } }) It("returns true if requested tags are nil", func() { Expect(container.HasTags(nil)).To(BeTrue()) }) It("returns false if requested tags are not nil", func() { Expect(container.HasTags(executor.Tags{"a": "b"})).To(BeFalse()) }) }) Context("when tags are not nil", func() { BeforeEach(func() { container = executor.Container{
Context("when the tags process index tag is not a number", func() { BeforeEach(func() { tags[rep.ProcessIndexTag] = "hi there" }) It("reports the index is invalid when constructing ActualLRPKey", func() { Expect(keyConversionErr).To(MatchError(rep.ErrInvalidProcessIndex)) }) }) }) }) Describe("ActualLRPInstanceKeyFromContainer", func() { var ( container executor.Container lrpInstanceKey *models.ActualLRPInstanceKey instanceKeyConversionErr error cellID string ) BeforeEach(func() { container = executor.Container{ Guid: "container-guid", Tags: executor.Tags{ rep.LifecycleTag: rep.LRPLifecycle, rep.DomainTag: "my-domain", rep.ProcessGuidTag: "process-guid", rep.ProcessIndexTag: "999", rep.InstanceGuidTag: "some-instance-guid", }, RunInfo: executor.RunInfo{ Ports: []executor.PortMapping{
desiredLRP *models.DesiredLRP expectedLrpKey models.ActualLRPKey expectedInstanceKey models.ActualLRPInstanceKey expectedNetInfo models.ActualLRPNetInfo expectedSessionName string ) BeforeEach(func() { desiredLRP = model_helpers.NewValidDesiredLRP("process-guid") expectedLrpKey = models.NewActualLRPKey("process-guid", 2, "domain") expectedInstanceKey = models.NewActualLRPInstanceKey("instance-guid", "cell-id") expectedNetInfo = models.NewActualLRPNetInfo("1.2.3.4", models.NewPortMapping(61999, 8080)) }) Context("when given an LRP container", func() { var container executor.Container BeforeEach(func() { container = newLRPContainer(expectedLrpKey, expectedInstanceKey, expectedNetInfo) }) JustBeforeEach(func() { processor.Process(logger, container) }) Context("and the container is INVALID", func() { BeforeEach(func() { expectedSessionName = sessionPrefix + "process-invalid-container" container.State = executor.StateInvalid })
var _ = Describe("EvacuationLrpProcessor", func() { Describe("Process", func() { const ( localCellID = "cell-α" evacuationTTL = 1234 ) var ( logger *lagertest.TestLogger fakeBBS *fake_bbs.FakeClient fakeContainerDelegate *fake_internal.FakeContainerDelegate fakeEvacuationReporter *fake_evacuation_context.FakeEvacuationReporter lrpProcessor internal.LRPProcessor processGuid string desiredLRP models.DesiredLRP index int container executor.Container instanceGuid string lrpKey models.ActualLRPKey lrpInstanceKey models.ActualLRPInstanceKey ) BeforeEach(func() { logger = lagertest.NewTestLogger("test") fakeBBS = new(fake_bbs.FakeClient) fakeContainerDelegate = &fake_internal.FakeContainerDelegate{}
It("returns the preset capacity", func() { expectedResources := executor.ExecutorResources{ MemoryMB: int(gardenCapacity.MemoryInBytes / 1024 / 1024), DiskMB: int(gardenCapacity.DiskInBytes / 1024 / 1024), Containers: int(gardenCapacity.MaxContainers), } Expect(resources).To(Equal(expectedResources)) }) }) Describe("allocating a container", func() { var ( container executor.Container guid string allocationErrorMap map[string]string allocErr error ) BeforeEach(func() { guid = generateGuid() container = executor.Container{ Guid: guid, Tags: executor.Tags{"some-tag": "some-value"}, Env: []executor.EnvironmentVariable{ {Name: "ENV1", Value: "val1"}, {Name: "ENV2", Value: "val2"},
func (exchanger exchanger) CreateInGarden(logger lager.Logger, gardenClient GardenClient, executorContainer executor.Container) (executor.Container, error) { logger = logger.Session("create-in-garden", lager.Data{"container-guid": executorContainer.Guid}) containerSpec := garden.ContainerSpec{ Handle: executorContainer.Guid, Privileged: executorContainer.Privileged, RootFSPath: executorContainer.RootFSPath, } if executorContainer.MemoryMB != 0 { logger.Debug("setting-up-memory-limits") containerSpec.Limits.Memory.LimitInBytes = uint64(executorContainer.MemoryMB * 1024 * 1024) } logger.Debug("setting-up-disk-limits") gardenScope := garden.DiskLimitScopeExclusive if executorContainer.DiskScope == executor.TotalDiskLimit { gardenScope = garden.DiskLimitScopeTotal } containerSpec.Limits.Disk = garden.DiskLimits{ ByteHard: uint64(executorContainer.DiskMB * 1024 * 1024), InodeHard: exchanger.containerInodeLimit, Scope: gardenScope, } logger.Debug("setting-up-cpu-limits") containerSpec.Limits.CPU.LimitInShares = uint64(float64(exchanger.containerMaxCPUShares) * float64(executorContainer.CPUWeight) / 100.0) logJson, err := json.Marshal(executorContainer.LogConfig) if err != nil { logger.Error("failed-marshal-log", err) return executor.Container{}, err } metricsConfigJson, err := json.Marshal(executorContainer.MetricsConfig) if err != nil { logger.Error("failed-marshal-metrics-config", err) return executor.Container{}, err } resultJson, err := json.Marshal(executorContainer.RunResult) if err != nil { logger.Error("failed-marshal-run-result", err) return executor.Container{}, err } containerSpec.Properties = garden.Properties{ ContainerOwnerProperty: exchanger.containerOwnerName, ContainerStateProperty: string(executorContainer.State), ContainerAllocatedAtProperty: fmt.Sprintf("%d", executorContainer.AllocatedAt), ContainerStartTimeoutProperty: fmt.Sprintf("%d", executorContainer.StartTimeout), ContainerRootfsProperty: executorContainer.RootFSPath, ContainerLogProperty: string(logJson), ContainerMetricsConfigProperty: string(metricsConfigJson), ContainerResultProperty: string(resultJson), ContainerMemoryMBProperty: fmt.Sprintf("%d", executorContainer.MemoryMB), ContainerDiskMBProperty: fmt.Sprintf("%d", executorContainer.DiskMB), ContainerCPUWeightProperty: fmt.Sprintf("%d", executorContainer.CPUWeight), } for name, value := range executorContainer.Tags { containerSpec.Properties[TagPropertyPrefix+name] = value } for _, env := range executorContainer.Env { containerSpec.Env = append(containerSpec.Env, env.Name+"="+env.Value) } for _, securityRule := range executorContainer.EgressRules { if err := securityRule.Validate(); err != nil { logger.Error("invalid-security-rule", err, lager.Data{"security_group_rule": securityRule}) return executor.Container{}, executor.ErrInvalidSecurityGroup } } logger.Debug("creating-garden-container") gardenContainer, err := gardenClient.Create(containerSpec) if err != nil { logger.Error("failed-creating-garden-container", err) return executor.Container{}, err } logger.Debug("succeeded-creating-garden-container") if executorContainer.Ports != nil { actualPortMappings := make([]executor.PortMapping, len(executorContainer.Ports)) logger.Debug("setting-up-ports") for i, ports := range executorContainer.Ports { actualHostPort, actualContainerPort, err := gardenContainer.NetIn(uint32(ports.HostPort), uint32(ports.ContainerPort)) if err != nil { logger.Error("failed-setting-up-ports", err) exchanger.destroyContainer(logger, gardenClient, gardenContainer) return executor.Container{}, err } actualPortMappings[i].ContainerPort = uint16(actualContainerPort) actualPortMappings[i].HostPort = uint16(actualHostPort) } logger.Debug("succeeded-setting-up-ports") executorContainer.Ports = actualPortMappings } for _, securityRule := range executorContainer.EgressRules { netOutRule, err := securityGroupRuleToNetOutRule(securityRule) if err != nil { logger.Error("failed-to-build-net-out-rule", err, lager.Data{"security_group_rule": securityRule}) return executor.Container{}, err } logger.Debug("setting-up-net-out") err = gardenContainer.NetOut(netOutRule) if err != nil { logger.Error("failed-setting-up-net-out", err, lager.Data{"net-out-rule": netOutRule}) exchanger.destroyContainer(logger, gardenClient, gardenContainer) return executor.Container{}, err } logger.Debug("succeeded-setting-up-net-out") } logger.Debug("getting-garden-container-info") info, err := gardenContainer.Info() if err != nil { logger.Error("failed-getting-garden-container-info", err) gardenErr := gardenClient.Destroy(gardenContainer.Handle()) if gardenErr != nil { logger.Error("failed-destroy-garden-container", gardenErr) } return executor.Container{}, err } logger.Debug("succeeded-getting-garden-container-info") executorContainer.ExternalIP = info.ExternalIP return executorContainer, nil }
func garden2executor(handle string, info garden.ContainerInfo) (executor.Container, error) { executorContainer := executor.Container{ Guid: handle, Tags: executor.Tags{}, ExternalIP: info.ExternalIP, } executorContainer.Ports = make([]executor.PortMapping, len(info.MappedPorts)) for key, value := range info.Properties { switch key { case ContainerStateProperty: state := executor.State(value) if state == executor.StateReserved || state == executor.StateInitializing || state == executor.StateCreated || state == executor.StateRunning || state == executor.StateCompleted { executorContainer.State = state } else { return executor.Container{}, InvalidStateError{value} } case ContainerAllocatedAtProperty: _, err := fmt.Sscanf(value, "%d", &executorContainer.AllocatedAt) if err != nil { return executor.Container{}, MalformedPropertyError{ Property: ContainerAllocatedAtProperty, Value: value, } } case ContainerRootfsProperty: executorContainer.RootFSPath = value case ContainerLogProperty: err := json.Unmarshal([]byte(value), &executorContainer.LogConfig) if err != nil { return executor.Container{}, InvalidJSONError{ Property: key, Value: value, UnmarshalErr: err, } } case ContainerMetricsConfigProperty: err := json.Unmarshal([]byte(value), &executorContainer.MetricsConfig) if err != nil { return executor.Container{}, InvalidJSONError{ Property: key, Value: value, UnmarshalErr: err, } } case ContainerResultProperty: err := json.Unmarshal([]byte(value), &executorContainer.RunResult) if err != nil { return executor.Container{}, InvalidJSONError{ Property: key, Value: value, UnmarshalErr: err, } } case ContainerMemoryMBProperty: memoryMB, err := strconv.Atoi(value) if err != nil { return executor.Container{}, MalformedPropertyError{ Property: key, Value: value, } } executorContainer.MemoryMB = memoryMB case ContainerDiskMBProperty: diskMB, err := strconv.Atoi(value) if err != nil { return executor.Container{}, MalformedPropertyError{ Property: key, Value: value, } } executorContainer.DiskMB = diskMB case ContainerCPUWeightProperty: cpuWeight, err := strconv.Atoi(value) if err != nil { return executor.Container{}, MalformedPropertyError{ Property: key, Value: value, } } executorContainer.CPUWeight = uint(cpuWeight) case ContainerStartTimeoutProperty: startTimeout, err := strconv.Atoi(value) if err != nil { return executor.Container{}, MalformedPropertyError{ Property: key, Value: value, } } executorContainer.StartTimeout = uint(startTimeout) default: if strings.HasPrefix(key, TagPropertyPrefix) { executorContainer.Tags[key[len(TagPropertyPrefix):]] = value } } } for i, mapping := range info.MappedPorts { executorContainer.Ports[i] = executor.PortMapping{ HostPort: uint16(mapping.HostPort), ContainerPort: uint16(mapping.ContainerPort), } } return executorContainer, nil }