func (p *LinuxResourcePool) releaseSystemResources(logger lager.Logger, id string) error { pRunner := logging.Runner{ CommandRunner: p.runner, Logger: logger, } bridgeName, err := ioutil.ReadFile(path.Join(p.depotPath, id, "bridge-name")) if err == nil { if err := p.bridges.Release(string(bridgeName), id); err != nil { return fmt.Errorf("containerpool: release bridge %s: %v", bridgeName, err) } } rootfsProvider, err := ioutil.ReadFile(path.Join(p.depotPath, id, "rootfs-provider")) if err != nil { rootfsProvider = []byte("invalid-rootfs-provider") } destroy := exec.Command(path.Join(p.binPath, "destroy.sh"), path.Join(p.depotPath, id)) err = pRunner.Run(destroy) if err != nil { return err } if shouldCleanRootfs(string(rootfsProvider)) { if err = p.rootfsRemover.Remove(layercake.ContainerID(id)); err != nil { return err } } p.filterProvider.ProvideFilter(id).TearDown() return nil }
func (provider *dockerRootFSProvider) ProvideRootFS(logger lager.Logger, id string, url *url.URL, shouldNamespace bool, quota int64) (string, process.Env, error) { tag := "latest" if len(url.Fragment) > 0 { tag = url.Fragment } fetchedID, envvars, volumes, err := provider.repoFetcher.Fetch(logger, url, tag, quota) if err != nil { return "", nil, err } var imageID layercake.ID = layercake.DockerImageID(fetchedID) if shouldNamespace { provider.mutex.Lock() imageID, err = provider.namespace(imageID) provider.mutex.Unlock() if err != nil { return "", nil, err } } containerID := layercake.ContainerID(id) err = provider.graph.Create(containerID, imageID) if err != nil { return "", nil, err } rootPath, err := provider.graph.Path(containerID) if err != nil { return "", nil, err } for _, v := range volumes { if err = provider.volumeCreator.Create(rootPath, v); err != nil { return "", nil, err } } return rootPath, envvars, nil }
} fakeCake.RemoveStub = func(id layercake.ID) error { delete(child2parent, id) return nil } }) Describe("Remove", func() { Context("when the layer has no parents", func() { BeforeEach(func() { fakeCake.GetReturns(&image.Image{}, nil) }) It("removes the layer", func() { Expect(gc.Remove(layercake.ContainerID("child"))).To(Succeed()) Expect(fakeCake.RemoveCallCount()).To(Equal(1)) Expect(fakeCake.RemoveArgsForCall(0)).To(Equal(layercake.ContainerID("child"))) }) Context("when the layer is retained", func() { BeforeEach(func() { fakeRetainer.IsHeldReturns(true) }) It("should not remove the layer", func() { Expect(gc.Remove(layercake.ContainerID("child"))).To(Succeed()) Expect(fakeCake.RemoveCallCount()).To(Equal(0)) }) }) })
It("fetches it and creates a graph entry with it as the parent", func() { fakeRepositoryFetcher.FetchResult = "some-image-id" fakeCake.PathReturns("/some/graph/driver/mount/point", nil) mountpoint, envvars, err := provider.ProvideRootFS( logger, "some-id", parseURL("docker:///some-repository-name"), false, 0, ) Expect(err).ToNot(HaveOccurred()) Expect(fakeCake.CreateCallCount()).To(Equal(1)) id, parent := fakeCake.CreateArgsForCall(0) Expect(id).To(Equal(layercake.ContainerID("some-id"))) Expect(parent).To(Equal(layercake.DockerImageID("some-image-id"))) Expect(fakeRepositoryFetcher.Fetched()).To(ContainElement( fake_repository_fetcher.FetchSpec{ Repository: "docker:///some-repository-name", Tag: "latest", }, )) Expect(mountpoint).To(Equal("/some/graph/driver/mount/point")) Expect(envvars).To(Equal( process.Env{ "env1": "env1Value", "env2": "env2Value", },
func (p *LinuxResourcePool) acquireSystemResources(id, handle, containerPath, rootFSPath string, resources *linux_backend.Resources, bindMounts []garden.BindMount, diskQuota int64, pLog lager.Logger) (string, process.Env, error) { if err := os.MkdirAll(containerPath, 0755); err != nil { return "", nil, fmt.Errorf("containerpool: creating container directory: %v", err) } rootfsURL, err := url.Parse(rootFSPath) if err != nil { pLog.Error("parse-rootfs-path-failed", err, lager.Data{ "RootFSPath": rootFSPath, }) return "", nil, err } provider, found := p.rootfsProviders[rootfsURL.Scheme] if !found { pLog.Error("unknown-rootfs-provider", nil, lager.Data{ "provider": rootfsURL.Scheme, }) return "", nil, ErrUnknownRootFSProvider } rootfsPath, rootFSEnvVars, err := provider.ProvideRootFS(pLog.Session("create-rootfs"), id, rootfsURL, resources.RootUID != 0, diskQuota) if err != nil { pLog.Error("provide-rootfs-failed", err) return "", nil, err } if resources.Bridge, err = p.bridges.Reserve(resources.Network.Subnet, id); err != nil { pLog.Error("reserve-bridge-failed", err, lager.Data{ "Id": id, "Subnet": resources.Network.Subnet, "Bridge": resources.Bridge, }) p.rootfsRemover.Remove(layercake.ContainerID(rootfsPath)) return "", nil, err } if err = p.saveBridgeName(id, resources.Bridge); err != nil { pLog.Error("save-bridge-name-failed", err, lager.Data{ "Id": id, "Bridge": resources.Bridge, }) p.rootfsRemover.Remove(layercake.ContainerID(rootfsPath)) return "", nil, err } createCmd := path.Join(p.binPath, "create.sh") create := exec.Command(createCmd, containerPath) suff, _ := resources.Network.Subnet.Mask.Size() env := process.Env{ "id": id, "rootfs_path": rootfsPath, "network_host_ip": subnets.GatewayIP(resources.Network.Subnet).String(), "network_container_ip": resources.Network.IP.String(), "network_cidr_suffix": strconv.Itoa(suff), "network_cidr": resources.Network.Subnet.String(), "external_ip": p.externalIP.String(), "container_iface_mtu": fmt.Sprintf("%d", p.mtu), "bridge_iface": resources.Bridge, "root_uid": strconv.FormatUint(uint64(resources.RootUID), 10), "PATH": os.Getenv("PATH"), } create.Env = env.Array() pRunner := logging.Runner{ CommandRunner: p.runner, Logger: pLog.Session("create-script"), } err = pRunner.Run(create) defer cleanup(&err, func() { p.tryReleaseSystemResources(p.logger, id) }) if err != nil { p.logger.Error("create-command-failed", err, lager.Data{ "CreateCmd": createCmd, "Env": create.Env, }) return "", nil, err } err = p.saveRootFSProvider(id, provider.Name()) if err != nil { p.logger.Error("save-rootfs-provider-failed", err, lager.Data{ "Id": id, "rootfs": rootfsURL.String(), }) return "", nil, err } err = p.saveContainerVersion(id) if err != nil { p.logger.Error("save-container-version-failed", err, lager.Data{ "Id": id, "ContainerPath": containerPath, }) return "", nil, err } err = p.writeBindMounts(containerPath, rootfsPath, bindMounts) if err != nil { p.logger.Error("bind-mounts-failed", err) return "", nil, err } filterLog := pLog.Session("setup-filter") filterLog.Debug("starting") if err = p.filterProvider.ProvideFilter(id).Setup(handle); err != nil { p.logger.Error("set-up-filter-failed", err) return "", nil, fmt.Errorf("resource_pool: set up filter: %v", err) } filterLog.Debug("finished") return rootfsPath, rootFSEnvVars, nil }