diff --git a/libkpod/containerserver.go b/libkpod/containerserver.go index c9580b78..5f26fefd 100644 --- a/libkpod/containerserver.go +++ b/libkpod/containerserver.go @@ -1,10 +1,14 @@ package libkpod import ( + "encoding/json" + "fmt" "sync" + "github.com/Sirupsen/logrus" "github.com/containers/image/types" cstorage "github.com/containers/storage" + "github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/registrar" "github.com/docker/docker/pkg/truncindex" "github.com/kubernetes-incubator/cri-o/oci" @@ -53,23 +57,79 @@ func (c *ContainerServer) ImageContext() *types.SystemContext { return c.imageContext } -// New creates a new ContainerServer -func New(runtime *oci.Runtime, store cstorage.Store, storageImageServer storage.ImageServer, ctrNameIndex *registrar.Registrar, ctrIDIndex *truncindex.TruncIndex, imageContext *types.SystemContext) *ContainerServer { - containers := oci.NewMemoryStore() +// New creates a new ContainerServer with options provided +func New(runtime *oci.Runtime, store cstorage.Store, imageService storage.ImageServer, signaturePolicyPath string) *ContainerServer { return &ContainerServer{ runtime: runtime, store: store, - storageImageServer: storageImageServer, - ctrNameIndex: ctrNameIndex, - ctrIDIndex: ctrIDIndex, - imageContext: imageContext, + storageImageServer: imageService, + ctrNameIndex: registrar.NewRegistrar(), + ctrIDIndex: truncindex.NewTruncIndex([]string{}), + imageContext: &types.SystemContext{SignaturePolicyPath: signaturePolicyPath}, stateLock: new(sync.Mutex), state: &containerServerState{ - containers: containers, + containers: oci.NewMemoryStore(), }, } } +// ContainerStateFromDisk retrieves information on the state of a running container +// from the disk +func (c *ContainerServer) ContainerStateFromDisk(ctr *oci.Container) error { + if err := ctr.FromDisk(); err != nil { + return err + } + // ignore errors, this is a best effort to have up-to-date info about + // a given container before its state gets stored + c.runtime.UpdateStatus(ctr) + + return nil +} + +// ContainerStateToDisk writes the container's state information to a JSON file +// on disk +func (c *ContainerServer) ContainerStateToDisk(ctr *oci.Container) error { + // ignore errors, this is a best effort to have up-to-date info about + // a given container before its state gets stored + c.Runtime().UpdateStatus(ctr) + + jsonSource, err := ioutils.NewAtomicFileWriter(ctr.StatePath(), 0644) + if err != nil { + return err + } + defer jsonSource.Close() + enc := json.NewEncoder(jsonSource) + return enc.Encode(c.runtime.ContainerStatus(ctr)) +} + +// ReserveContainerName holds a name for a container that is being created +func (c *ContainerServer) ReserveContainerName(id, name string) (string, error) { + if err := c.ctrNameIndex.Reserve(name, id); err != nil { + if err == registrar.ErrNameReserved { + id, err := c.ctrNameIndex.Get(name) + if err != nil { + logrus.Warnf("conflict, ctr name %q already reserved", name) + return "", err + } + return "", fmt.Errorf("conflict, name %q already reserved for ctr %q", name, id) + } + return "", fmt.Errorf("error reserving ctr name %s", name) + } + return name, nil +} + +// ReleaseContainerName releases a container name from the index so that it can +// be used by other containers +func (c *ContainerServer) ReleaseContainerName(name string) { + c.ctrNameIndex.Release(name) +} + +// Shutdown attempts to shut down the server's storage cleanly +func (c *ContainerServer) Shutdown() error { + _, err := c.store.Shutdown(false) + return err +} + type containerServerState struct { containers oci.ContainerStorer } diff --git a/server/container_create.go b/server/container_create.go index ebcd607f..fafd5940 100644 --- a/server/container_create.go +++ b/server/container_create.go @@ -303,7 +303,7 @@ func (s *Server) CreateContainer(ctx context.Context, req *pb.CreateContainerReq defer func() { if err != nil { - s.releaseContainerName(containerName) + s.ReleaseContainerName(containerName) } }() @@ -335,7 +335,7 @@ func (s *Server) CreateContainer(ctx context.Context, req *pb.CreateContainerReq return nil, err } - s.containerStateToDisk(container) + s.ContainerStateToDisk(container) resp := &pb.CreateContainerResponse{ ContainerId: containerID, diff --git a/server/container_remove.go b/server/container_remove.go index c32e4fa0..8e330e60 100644 --- a/server/container_remove.go +++ b/server/container_remove.go @@ -42,7 +42,7 @@ func (s *Server) RemoveContainer(ctx context.Context, req *pb.RemoveContainerReq return nil, fmt.Errorf("failed to delete storage for container %s: %v", c.ID(), err) } - s.releaseContainerName(c.Name()) + s.ReleaseContainerName(c.Name()) if err := s.CtrIDIndex().Delete(c.ID()); err != nil { return nil, err diff --git a/server/container_start.go b/server/container_start.go index d3d97bc5..b8c7fdb0 100644 --- a/server/container_start.go +++ b/server/container_start.go @@ -29,7 +29,7 @@ func (s *Server) StartContainer(ctx context.Context, req *pb.StartContainerReque if err != nil { s.Runtime().SetStartFailed(c, err) } - s.containerStateToDisk(c) + s.ContainerStateToDisk(c) }() err = s.Runtime().StartContainer(c) diff --git a/server/container_status.go b/server/container_status.go index ffa315bb..ece493eb 100644 --- a/server/container_status.go +++ b/server/container_status.go @@ -29,7 +29,7 @@ func (s *Server) ContainerStatus(ctx context.Context, req *pb.ContainerStatusReq if err = s.Runtime().UpdateStatus(c); err != nil { return nil, err } - s.containerStateToDisk(c) + s.ContainerStateToDisk(c) containerID := c.ID() resp := &pb.ContainerStatusResponse{ diff --git a/server/container_stop.go b/server/container_stop.go index d069e603..ccbde3cc 100644 --- a/server/container_stop.go +++ b/server/container_stop.go @@ -30,7 +30,7 @@ func (s *Server) StopContainer(ctx context.Context, req *pb.StopContainerRequest } } - s.containerStateToDisk(c) + s.ContainerStateToDisk(c) resp := &pb.StopContainerResponse{} logrus.Debugf("StopContainerResponse: %+v", resp) diff --git a/server/naming.go b/server/naming.go index 0175158b..881b2510 100644 --- a/server/naming.go +++ b/server/naming.go @@ -66,7 +66,7 @@ func (s *Server) generateContainerIDandNameForSandbox(sandboxConfig *pb.PodSandb err error id = stringid.GenerateNonCryptoID() ) - name, err := s.reserveContainerName(id, makeSandboxContainerName(sandboxConfig)) + name, err := s.ReserveContainerName(id, makeSandboxContainerName(sandboxConfig)) if err != nil { return "", "", err } @@ -78,7 +78,7 @@ func (s *Server) generateContainerIDandName(sandboxMetadata *pb.PodSandboxMetada err error id = stringid.GenerateNonCryptoID() ) - name, err := s.reserveContainerName(id, makeContainerName(sandboxMetadata, containerConfig)) + name, err := s.ReserveContainerName(id, makeContainerName(sandboxMetadata, containerConfig)) if err != nil { return "", "", err } diff --git a/server/sandbox_remove.go b/server/sandbox_remove.go index d9efe7e6..0b22629b 100644 --- a/server/sandbox_remove.go +++ b/server/sandbox_remove.go @@ -65,7 +65,7 @@ func (s *Server) RemovePodSandbox(ctx context.Context, req *pb.RemovePodSandboxR return nil, fmt.Errorf("failed to delete container %s in pod sandbox %s: %v", c.Name(), sb.ID(), err) } - s.releaseContainerName(c.Name()) + s.ReleaseContainerName(c.Name()) s.removeContainer(c) if err := s.CtrIDIndex().Delete(c.ID()); err != nil { return nil, fmt.Errorf("failed to delete container %s in pod sandbox %s from index: %v", c.Name(), sb.ID(), err) @@ -82,7 +82,7 @@ func (s *Server) RemovePodSandbox(ctx context.Context, req *pb.RemovePodSandboxR return nil, fmt.Errorf("failed to remove pod sandbox %s: %v", sb.ID(), err) } - s.releaseContainerName(podInfraContainer.Name()) + s.ReleaseContainerName(podInfraContainer.Name()) if err := s.CtrIDIndex().Delete(podInfraContainer.ID()); err != nil { return nil, fmt.Errorf("failed to delete infra container %s in pod sandbox %s from index: %v", podInfraContainer.ID(), sb.ID(), err) } diff --git a/server/sandbox_run.go b/server/sandbox_run.go index bfff47d2..ab04cf2a 100644 --- a/server/sandbox_run.go +++ b/server/sandbox_run.go @@ -149,7 +149,7 @@ func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest defer func() { if err != nil { - s.releaseContainerName(containerName) + s.ReleaseContainerName(containerName) } }() @@ -500,7 +500,7 @@ func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest return nil, err } - s.containerStateToDisk(container) + s.ContainerStateToDisk(container) resp = &pb.RunPodSandboxResponse{PodSandboxId: id} logrus.Debugf("RunPodSandboxResponse: %+v", resp) diff --git a/server/sandbox_status.go b/server/sandbox_status.go index ba00563d..48eb6695 100644 --- a/server/sandbox_status.go +++ b/server/sandbox_status.go @@ -19,7 +19,7 @@ func (s *Server) PodSandboxStatus(ctx context.Context, req *pb.PodSandboxStatusR if err = s.Runtime().UpdateStatus(podInfraContainer); err != nil { return nil, err } - s.containerStateToDisk(podInfraContainer) + s.ContainerStateToDisk(podInfraContainer) cState := s.Runtime().ContainerStatus(podInfraContainer) diff --git a/server/sandbox_stop.go b/server/sandbox_stop.go index 1f863fc2..1689d87b 100644 --- a/server/sandbox_stop.go +++ b/server/sandbox_stop.go @@ -85,7 +85,7 @@ func (s *Server) StopPodSandbox(ctx context.Context, req *pb.StopPodSandboxReque logrus.Warnf("failed to stop container %s in pod sandbox %s: %v", c.Name(), sb.ID(), err) } } - s.containerStateToDisk(c) + s.ContainerStateToDisk(c) } if err := label.ReleaseLabel(sb.ProcessLabel()); err != nil { diff --git a/server/server.go b/server/server.go index 71cb960b..1229ae8a 100644 --- a/server/server.go +++ b/server/server.go @@ -11,9 +11,7 @@ import ( "time" "github.com/Sirupsen/logrus" - "github.com/containers/image/types" cstorage "github.com/containers/storage" - "github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/registrar" "github.com/docker/docker/pkg/truncindex" "github.com/kubernetes-incubator/cri-o/libkpod" @@ -104,14 +102,14 @@ func (s *Server) loadContainer(id string) error { return err } name := m.Annotations[annotations.Name] - name, err = s.reserveContainerName(id, name) + name, err = s.ReserveContainerName(id, name) if err != nil { return err } defer func() { if err != nil { - s.releaseContainerName(name) + s.ReleaseContainerName(name) } }() @@ -158,37 +156,12 @@ func (s *Server) loadContainer(id string) error { return err } - s.containerStateFromDisk(ctr) + s.ContainerStateFromDisk(ctr) s.addContainer(ctr) return s.CtrIDIndex().Add(id) } -func (s *Server) containerStateFromDisk(c *oci.Container) error { - if err := c.FromDisk(); err != nil { - return err - } - // ignore errors, this is a best effort to have up-to-date info about - // a given container before its state gets stored - s.Runtime().UpdateStatus(c) - - return nil -} - -func (s *Server) containerStateToDisk(c *oci.Container) error { - // ignore errors, this is a best effort to have up-to-date info about - // a given container before its state gets stored - s.Runtime().UpdateStatus(c) - - jsonSource, err := ioutils.NewAtomicFileWriter(c.StatePath(), 0644) - if err != nil { - return err - } - defer jsonSource.Close() - enc := json.NewEncoder(jsonSource) - return enc.Encode(s.Runtime().ContainerStatus(c)) -} - func configNetNsPath(spec rspec.Spec) (string, error) { for _, ns := range spec.Linux.Namespaces { if ns.Type != rspec.NetworkNamespace { @@ -282,13 +255,13 @@ func (s *Server) loadSandbox(id string) error { return err } - cname, err := s.reserveContainerName(m.Annotations[annotations.ContainerID], m.Annotations[annotations.ContainerName]) + cname, err := s.ReserveContainerName(m.Annotations[annotations.ContainerID], m.Annotations[annotations.ContainerName]) if err != nil { return err } defer func() { if err != nil { - s.releaseContainerName(cname) + s.ReleaseContainerName(cname) } }() @@ -302,7 +275,7 @@ func (s *Server) loadSandbox(id string) error { return err } - s.containerStateFromDisk(scontainer) + s.ContainerStateFromDisk(scontainer) if err = label.ReserveLabel(processLabel); err != nil { return err @@ -410,7 +383,7 @@ func (s *Server) update() error { logrus.Warnf("bad state when getting container removed %+v", removedPodContainer) continue } - s.releaseContainerName(c.Name()) + s.ReleaseContainerName(c.Name()) s.removeContainer(c) if err = s.CtrIDIndex().Delete(c.ID()); err != nil { return err @@ -431,7 +404,7 @@ func (s *Server) update() error { continue } podInfraContainer := sb.InfraContainer() - s.releaseContainerName(podInfraContainer.Name()) + s.ReleaseContainerName(podInfraContainer.Name()) s.removeContainer(podInfraContainer) if err = s.CtrIDIndex().Delete(podInfraContainer.ID()); err != nil { return err @@ -482,25 +455,6 @@ func (s *Server) releasePodName(name string) { s.podNameIndex.Release(name) } -func (s *Server) reserveContainerName(id, name string) (string, error) { - if err := s.CtrNameIndex().Reserve(name, id); err != nil { - if err == registrar.ErrNameReserved { - id, err := s.CtrNameIndex().Get(name) - if err != nil { - logrus.Warnf("conflict, ctr name %q already reserved", name) - return "", err - } - return "", fmt.Errorf("conflict, name %q already reserved for ctr %q", name, id) - } - return "", fmt.Errorf("error reserving ctr name %s", name) - } - return name, nil -} - -func (s *Server) releaseContainerName(name string) { - s.CtrNameIndex().Release(name) -} - // cleanupSandboxesOnShutdown Remove all running Sandboxes on system shutdown func (s *Server) cleanupSandboxesOnShutdown() { _, err := os.Stat(shutdownFile) @@ -522,8 +476,7 @@ func (s *Server) Shutdown() error { // notice this won't trigger just on system halt but also on normal // crio.service restart!!! s.cleanupSandboxesOnShutdown() - _, err := s.Store().Shutdown(false) - return err + return s.ContainerServer.Shutdown() } // New creates a new Server with options provided @@ -543,6 +496,11 @@ func New(config *Config) (*Server, error) { return nil, err } + r, err := oci.New(config.Runtime, config.RuntimeUntrustedWorkload, config.DefaultWorkloadTrust, config.Conmon, config.ConmonEnv, config.CgroupManager) + if err != nil { + return nil, err + } + storageRuntimeService := storage.GetRuntimeService(imageService, config.PauseImage) if err != nil { return nil, err @@ -552,10 +510,7 @@ func New(config *Config) (*Server, error) { return nil, err } - r, err := oci.New(config.Runtime, config.RuntimeUntrustedWorkload, config.DefaultWorkloadTrust, config.Conmon, config.ConmonEnv, config.CgroupManager) - if err != nil { - return nil, err - } + containerServer := libkpod.New(r, store, imageService, config.SignaturePolicyPath) sandboxes := make(map[string]*sandbox.Sandbox) netPlugin, err := ocicni.InitCNI(config.NetworkDir, config.PluginDir) @@ -566,7 +521,6 @@ func New(config *Config) (*Server, error) { iptInterface.EnsureChain(utiliptables.TableNAT, iptablesproxy.KubeMarkMasqChain) hostportManager := hostport.NewHostportManager() - containerServer := libkpod.New(r, store, imageService, registrar.NewRegistrar(), truncindex.NewTruncIndex([]string{}), &types.SystemContext{SignaturePolicyPath: config.ImageConfig.SignaturePolicyPath}) s := &Server{ ContainerServer: *containerServer, storageRuntimeServer: storageRuntimeService, @@ -633,7 +587,6 @@ func New(config *Config) (*Server, error) { }() logrus.Debugf("sandboxes: %v", s.state.sandboxes) - logrus.Debugf("containers: %v", s.ContainerServer.ListContainers()) return s, nil }