"math/rand" "sync" "runtime" "github.com/cloudfoundry-incubator/garden-linux/repository_fetcher" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) var _ = Describe("Graph Lock", func() { var lock *repository_fetcher.FetchLock BeforeEach(func() { lock = repository_fetcher.NewFetchLock() }) Describe("Acquire", func() { Context("when the layer is locked", func() { BeforeEach(func() { lock.Acquire("some-key") }) It("waits for the lock to be released", func() { gotLock := make(chan struct{}, 1) go func(lock *repository_fetcher.FetchLock, gotLock chan struct{}) { go GinkgoRecover() lock.Acquire("some-key") close(gotLock)
func main() { if reexec.Init() { return } cf_debug_server.AddFlags(flag.CommandLine) cf_lager.AddFlags(flag.CommandLine) flag.Parse() runtime.GOMAXPROCS(runtime.NumCPU()) logger, reconfigurableSink := cf_lager.New("garden-linux") if dbgAddr := cf_debug_server.DebugAddress(flag.CommandLine); dbgAddr != "" { debug.Run(dbgAddr, reconfigurableSink) } initializeDropsonde(logger) if *binPath == "" { missing("-bin") } if *depotPath == "" { missing("-depot") } if len(*tag) > 2 { println("-tag parameter must be less than 3 characters long") println() flag.Usage() return } _, dynamicRange, err := net.ParseCIDR(*networkPool) if err != nil { logger.Fatal("failed-to-parse-network-pool", err) } subnetPool, err := subnets.NewSubnets(dynamicRange) if err != nil { logger.Fatal("failed-to-create-subnet-pool", err) } // TODO: use /proc/sys/net/ipv4/ip_local_port_range by default (end + 1) portPool, err := port_pool.New(uint32(*portPoolStart), uint32(*portPoolSize)) if err != nil { logger.Fatal("invalid pool range", err) } useKernelLogging := true switch *iptablesLogMethod { case "nflog": useKernelLogging = false case "kernel": /* noop */ default: println("-iptablesLogMethod value not recognized") println() flag.Usage() return } config := sysconfig.NewConfig(*tag, *allowHostAccess) runner := sysconfig.NewRunner(config, linux_command_runner.New()) if err := os.MkdirAll(*graphRoot, 0755); err != nil { logger.Fatal("failed-to-create-graph-directory", err) } dockerGraphDriver, err := graphdriver.New(*graphRoot, nil) if err != nil { logger.Fatal("failed-to-construct-graph-driver", err) } dockerGraph, err := graph.NewGraph(*graphRoot, dockerGraphDriver) if err != nil { logger.Fatal("failed-to-construct-graph", err) } graphMountPoint := mountPoint(logger, *graphRoot) var cake layercake.Cake = &layercake.Docker{ Graph: dockerGraph, Driver: dockerGraphDriver, } if cake.DriverName() == "btrfs" { cake = &layercake.BtrfsCleaningCake{ Cake: cake, Runner: runner, BtrfsMountPoint: graphMountPoint, RemoveAll: os.RemoveAll, Logger: logger.Session("btrfs-cleanup"), } } retainer := layercake.NewRetainer() cake = &layercake.OvenCleaner{ Cake: cake, Retainer: retainer, Logger: logger.Session("oven-cleaner"), } lock := repository_fetcher.NewFetchLock() repoFetcher := repository_fetcher.Retryable{ repository_fetcher.NewRemote( repository_fetcher.NewRepositoryProvider( *dockerRegistry, strings.Split(*insecureRegistries, ","), ), cake, map[registry.APIVersion]repository_fetcher.VersionedFetcher{ registry.APIVersion1: &repository_fetcher.RemoteV1Fetcher{ Cake: cake, Retainer: retainer, GraphLock: lock, }, registry.APIVersion2: &repository_fetcher.RemoteV2Fetcher{ Cake: cake, Retainer: retainer, GraphLock: lock, }, }, repository_fetcher.EndpointPinger{}, ), } maxId := sysinfo.Min(sysinfo.MustGetMaxValidUID(), sysinfo.MustGetMaxValidGID()) mappingList := rootfs_provider.MappingList{ { FromID: 0, ToID: maxId, Size: 1, }, { FromID: 1, ToID: 1, Size: maxId - 1, }, } rootFSNamespacer := &rootfs_provider.UidNamespacer{ Logger: logger, Translator: rootfs_provider.NewUidTranslator( mappingList, // uid mappingList, // gid ), } remoteRootFSProvider, err := rootfs_provider.NewDocker(fmt.Sprintf("docker-remote-%s", cake.DriverName()), repoFetcher, cake, rootfs_provider.SimpleVolumeCreator{}, rootFSNamespacer, clock.NewClock()) if err != nil { logger.Fatal("failed-to-construct-docker-rootfs-provider", err) } localRootFSProvider, err := rootfs_provider.NewDocker(fmt.Sprintf("docker-local-%s", cake.DriverName()), &repository_fetcher.Local{ Cake: cake, DefaultRootFSPath: *rootFSPath, IDProvider: repository_fetcher.LayerIDProvider{}, }, cake, rootfs_provider.SimpleVolumeCreator{}, rootFSNamespacer, clock.NewClock()) if err != nil { logger.Fatal("failed-to-construct-warden-rootfs-provider", err) } rootFSProviders := map[string]rootfs_provider.RootFSProvider{ "": localRootFSProvider, "docker": remoteRootFSProvider, } if *externalIP == "" { ip, err := localip.LocalIP() if err != nil { panic("couldn't determine local IP to use for -externalIP parameter. You can use the -externalIP flag to pass an external IP") } externalIP = &ip } parsedExternalIP := net.ParseIP(*externalIP) if parsedExternalIP == nil { panic(fmt.Sprintf("Value of -externalIP %s could not be converted to an IP", *externalIP)) } var quotaManager linux_container.QuotaManager = quota_manager.DisabledQuotaManager{} if !*disableQuotas { quotaManager = "a_manager.BtrfsQuotaManager{ Runner: runner, MountPoint: graphMountPoint, } } injector := &provider{ useKernelLogging: useKernelLogging, chainPrefix: config.IPTables.Filter.InstancePrefix, runner: runner, log: logger, portPool: portPool, sysconfig: config, quotaManager: quotaManager, } currentContainerVersion, err := semver.Make(CurrentContainerVersion) if err != nil { logger.Fatal("failed-to-parse-container-version", err) } pool := resource_pool.New( logger, *binPath, *depotPath, config, rootFSProviders, cake, mappingList, parsedExternalIP, *mtu, subnetPool, bridgemgr.New("w"+config.Tag+"b-", &devices.Bridge{}, &devices.Link{}), injector, iptables.NewGlobalChain(config.IPTables.Filter.DefaultChain, runner, logger.Session("global-chain")), portPool, strings.Split(*denyNetworks, ","), strings.Split(*allowNetworks, ","), runner, quotaManager, currentContainerVersion, ) systemInfo := sysinfo.NewProvider(*depotPath) backend := linux_backend.New(logger, pool, container_repository.New(), injector, systemInfo, *snapshotsPath, int(*maxContainers)) err = backend.Setup() if err != nil { logger.Fatal("failed-to-set-up-backend", err) } graceTime := *containerGraceTime gardenServer := server.New(*listenNetwork, *listenAddr, graceTime, backend, logger) err = gardenServer.Start() if err != nil { logger.Fatal("failed-to-start-server", err) } signals := make(chan os.Signal, 1) go func() { <-signals gardenServer.Stop() os.Exit(0) }() signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP) logger.Info("started", lager.Data{ "network": *listenNetwork, "addr": *listenAddr, }) select {} }