From 20df2196f2158d8656d1b38580d816567843a5e0 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Fri, 12 Jan 2018 12:41:10 -0500 Subject: Add ability for states to track container dependencies Also prevent containers with dependencies from being removed from in memory states. SQLite already enforced this via FOREIGN KEY constraints. Signed-off-by: Matthew Heon Closes: #220 Approved by: rhatdan --- libpod/in_memory_state.go | 83 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) (limited to 'libpod/in_memory_state.go') diff --git a/libpod/in_memory_state.go b/libpod/in_memory_state.go index 4e4cbb664..b4e224d77 100644 --- a/libpod/in_memory_state.go +++ b/libpod/in_memory_state.go @@ -1,6 +1,8 @@ package libpod import ( + "strings" + "github.com/docker/docker/pkg/truncindex" "github.com/pkg/errors" "github.com/projectatomic/libpod/pkg/registrar" @@ -10,6 +12,7 @@ import ( type InMemoryState struct { pods map[string]*Pod containers map[string]*Container + ctrDepends map[string][]string podNameIndex *registrar.Registrar podIDIndex *truncindex.TruncIndex ctrNameIndex *registrar.Registrar @@ -137,6 +140,15 @@ func (s *InMemoryState) AddContainer(ctr *Container) error { s.containers[ctr.ID()] = ctr + // Add containers this container depends on + s.addCtrToDependsMap(ctr.ID(), ctr.config.IPCNsCtr) + s.addCtrToDependsMap(ctr.ID(), ctr.config.MountNsCtr) + s.addCtrToDependsMap(ctr.ID(), ctr.config.NetNsCtr) + s.addCtrToDependsMap(ctr.ID(), ctr.config.PIDNsCtr) + s.addCtrToDependsMap(ctr.ID(), ctr.config.UserNsCtr) + s.addCtrToDependsMap(ctr.ID(), ctr.config.UTSNsCtr) + s.addCtrToDependsMap(ctr.ID(), ctr.config.CgroupNsCtr) + return nil } @@ -146,6 +158,13 @@ func (s *InMemoryState) RemoveContainer(ctr *Container) error { // Almost no validity checks are performed, to ensure we can kick // misbehaving containers out of the state + // Ensure we don't remove a container which other containers depend on + deps, ok := s.ctrDepends[ctr.ID()] + if ok && len(deps) != 0 { + depsStr := strings.Join(deps, ", ") + return errors.Wrapf(ErrCtrExists, "the following containers depend on container %s: %s", ctr.ID(), depsStr) + } + if _, ok := s.containers[ctr.ID()]; !ok { return errors.Wrapf(ErrNoSuchCtr, "no container exists in state with ID %s", ctr.ID()) } @@ -156,6 +175,16 @@ func (s *InMemoryState) RemoveContainer(ctr *Container) error { delete(s.containers, ctr.ID()) s.ctrNameIndex.Release(ctr.Name()) + delete(s.ctrDepends, ctr.ID()) + + s.removeCtrFromDependsMap(ctr.ID(), ctr.config.IPCNsCtr) + s.removeCtrFromDependsMap(ctr.ID(), ctr.config.MountNsCtr) + s.removeCtrFromDependsMap(ctr.ID(), ctr.config.NetNsCtr) + s.removeCtrFromDependsMap(ctr.ID(), ctr.config.PIDNsCtr) + s.removeCtrFromDependsMap(ctr.ID(), ctr.config.UserNsCtr) + s.removeCtrFromDependsMap(ctr.ID(), ctr.config.UTSNsCtr) + s.removeCtrFromDependsMap(ctr.ID(), ctr.config.CgroupNsCtr) + return nil } @@ -174,6 +203,20 @@ func (s *InMemoryState) SaveContainer(ctr *Container) error { return nil } +// ContainerInUse checks if the given container is being used by other containers +func (s *InMemoryState) ContainerInUse(ctr *Container) ([]string, error) { + if !ctr.valid { + return nil, ErrCtrRemoved + } + + arr, ok := s.ctrDepends[ctr.ID()] + if !ok { + return []string{}, nil + } + + return arr, nil +} + // AllContainers retrieves all containers from the state func (s *InMemoryState) AllContainers() ([]*Container, error) { ctrs := make([]*Container, 0, len(s.containers)) @@ -298,3 +341,43 @@ func (s *InMemoryState) AllPods() ([]*Pod, error) { return pods, nil } + +// Internal Functions + +// Add a container to the dependency mappings +func (s *InMemoryState) addCtrToDependsMap(ctrID, dependsID string) { + if dependsID != "" { + arr, ok := s.ctrDepends[dependsID] + if !ok { + // Do not have a mapping for that container yet + s.ctrDepends[dependsID] = []string{ctrID} + } else { + // Have a mapping for the container + arr = append(arr, ctrID) + s.ctrDepends[dependsID] = arr + } + } +} + +// Remove a container from dependency mappings +func (s *InMemoryState) removeCtrFromDependsMap(ctrID, dependsID string) { + if dependsID != "" { + arr, ok := s.ctrDepends[dependsID] + if !ok { + // Internal state seems inconsistent + // But the dependency is definitely gone + // So just return + return + } + + newArr := make([]string, len(arr), 0) + + for _, id := range arr { + if id != ctrID { + newArr = append(newArr, id) + } + } + + s.ctrDepends[dependsID] = newArr + } +} -- cgit v1.2.3-54-g00ecf