Merge pull request #1200 from runcom/list-sandboxes-refactor-1.0
[release-1.7] libkpod: sandbox: refactor to memory store
This commit is contained in:
commit
40381b9fc0
5 changed files with 174 additions and 25 deletions
|
@ -168,7 +168,7 @@ func New(config *Config) (*ContainerServer, error) {
|
|||
state: &containerServerState{
|
||||
containers: oci.NewMemoryStore(),
|
||||
infraContainers: oci.NewMemoryStore(),
|
||||
sandboxes: make(map[string]*sandbox.Sandbox),
|
||||
sandboxes: sandbox.NewMemoryStore(),
|
||||
processLevels: make(map[string]int),
|
||||
},
|
||||
config: config,
|
||||
|
@ -612,7 +612,7 @@ func (c *ContainerServer) Shutdown() error {
|
|||
type containerServerState struct {
|
||||
containers oci.ContainerStorer
|
||||
infraContainers oci.ContainerStorer
|
||||
sandboxes map[string]*sandbox.Sandbox
|
||||
sandboxes sandbox.Storer
|
||||
// processLevels The number of sandboxes using the same SELinux MCS level. Need to release MCS Level, when count reaches 0
|
||||
processLevels map[string]int
|
||||
}
|
||||
|
@ -621,7 +621,7 @@ type containerServerState struct {
|
|||
func (c *ContainerServer) AddContainer(ctr *oci.Container) {
|
||||
c.stateLock.Lock()
|
||||
defer c.stateLock.Unlock()
|
||||
sandbox := c.state.sandboxes[ctr.Sandbox()]
|
||||
sandbox := c.state.sandboxes.Get(ctr.Sandbox())
|
||||
sandbox.AddContainer(ctr)
|
||||
c.state.containers.Add(ctr.ID(), ctr)
|
||||
}
|
||||
|
@ -660,7 +660,7 @@ func (c *ContainerServer) RemoveContainer(ctr *oci.Container) {
|
|||
c.stateLock.Lock()
|
||||
defer c.stateLock.Unlock()
|
||||
sbID := ctr.Sandbox()
|
||||
sb := c.state.sandboxes[sbID]
|
||||
sb := c.state.sandboxes.Get(sbID)
|
||||
sb.RemoveContainer(ctr)
|
||||
c.state.containers.Delete(ctr.ID())
|
||||
}
|
||||
|
@ -701,7 +701,7 @@ func (c *ContainerServer) ListContainers(filters ...func(*oci.Container) bool) (
|
|||
func (c *ContainerServer) AddSandbox(sb *sandbox.Sandbox) {
|
||||
c.stateLock.Lock()
|
||||
defer c.stateLock.Unlock()
|
||||
c.state.sandboxes[sb.ID()] = sb
|
||||
c.state.sandboxes.Add(sb.ID(), sb)
|
||||
c.state.processLevels[selinux.NewContext(sb.ProcessLabel())["level"]]++
|
||||
}
|
||||
|
||||
|
@ -709,17 +709,14 @@ func (c *ContainerServer) AddSandbox(sb *sandbox.Sandbox) {
|
|||
func (c *ContainerServer) GetSandbox(id string) *sandbox.Sandbox {
|
||||
c.stateLock.Lock()
|
||||
defer c.stateLock.Unlock()
|
||||
return c.state.sandboxes[id]
|
||||
return c.state.sandboxes.Get(id)
|
||||
}
|
||||
|
||||
// GetSandboxContainer returns a sandbox's infra container
|
||||
func (c *ContainerServer) GetSandboxContainer(id string) *oci.Container {
|
||||
c.stateLock.Lock()
|
||||
defer c.stateLock.Unlock()
|
||||
sb, ok := c.state.sandboxes[id]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
sb := c.state.sandboxes.Get(id)
|
||||
return sb.InfraContainer()
|
||||
}
|
||||
|
||||
|
@ -727,21 +724,25 @@ func (c *ContainerServer) GetSandboxContainer(id string) *oci.Container {
|
|||
func (c *ContainerServer) HasSandbox(id string) bool {
|
||||
c.stateLock.Lock()
|
||||
defer c.stateLock.Unlock()
|
||||
_, ok := c.state.sandboxes[id]
|
||||
return ok
|
||||
sb := c.state.sandboxes.Get(id)
|
||||
return sb != nil
|
||||
}
|
||||
|
||||
// RemoveSandbox removes a sandbox from the state store
|
||||
func (c *ContainerServer) RemoveSandbox(id string) {
|
||||
c.stateLock.Lock()
|
||||
defer c.stateLock.Unlock()
|
||||
processLabel := c.state.sandboxes[id].ProcessLabel()
|
||||
delete(c.state.sandboxes, id)
|
||||
sb := c.state.sandboxes.Get(id)
|
||||
processLabel := sb.ProcessLabel()
|
||||
c.state.sandboxes.Delete(id)
|
||||
level := selinux.NewContext(processLabel)["level"]
|
||||
c.state.processLevels[level]--
|
||||
if c.state.processLevels[level] == 0 {
|
||||
label.ReleaseLabel(processLabel)
|
||||
delete(c.state.processLevels, level)
|
||||
pl, ok := c.state.processLevels[level]
|
||||
if ok {
|
||||
c.state.processLevels[level] = pl - 1
|
||||
if c.state.processLevels[level] == 0 {
|
||||
label.ReleaseLabel(processLabel)
|
||||
delete(c.state.processLevels, level)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -749,12 +750,7 @@ func (c *ContainerServer) RemoveSandbox(id string) {
|
|||
func (c *ContainerServer) ListSandboxes() []*sandbox.Sandbox {
|
||||
c.stateLock.Lock()
|
||||
defer c.stateLock.Unlock()
|
||||
sbArray := make([]*sandbox.Sandbox, 0, len(c.state.sandboxes))
|
||||
for _, sb := range c.state.sandboxes {
|
||||
sbArray = append(sbArray, sb)
|
||||
}
|
||||
|
||||
return sbArray
|
||||
return c.state.sandboxes.List()
|
||||
}
|
||||
|
||||
// LibcontainerStats gets the stats for the container with the given id from runc/libcontainer
|
||||
|
|
31
libkpod/sandbox/history.go
Normal file
31
libkpod/sandbox/history.go
Normal file
|
@ -0,0 +1,31 @@
|
|||
package sandbox
|
||||
|
||||
import "sort"
|
||||
|
||||
// History is a convenience type for storing a list of sandboxes,
|
||||
// sorted by creation date in descendant order.
|
||||
type History []*Sandbox
|
||||
|
||||
// Len returns the number of sandboxes in the history.
|
||||
func (history *History) Len() int {
|
||||
return len(*history)
|
||||
}
|
||||
|
||||
// Less compares two sandboxes and returns true if the second one
|
||||
// was created before the first one.
|
||||
func (history *History) Less(i, j int) bool {
|
||||
sandboxes := *history
|
||||
// FIXME: state access should be serialized
|
||||
return sandboxes[j].created.Before(sandboxes[i].created)
|
||||
}
|
||||
|
||||
// Swap switches sandboxes i and j positions in the history.
|
||||
func (history *History) Swap(i, j int) {
|
||||
sandboxes := *history
|
||||
sandboxes[i], sandboxes[j] = sandboxes[j], sandboxes[i]
|
||||
}
|
||||
|
||||
// sort orders the history by creation date in descendant order.
|
||||
func (history *History) sort() {
|
||||
sort.Sort(history)
|
||||
}
|
92
libkpod/sandbox/memory_store.go
Normal file
92
libkpod/sandbox/memory_store.go
Normal file
|
@ -0,0 +1,92 @@
|
|||
package sandbox
|
||||
|
||||
import "sync"
|
||||
|
||||
// memoryStore implements a Store in memory.
|
||||
type memoryStore struct {
|
||||
s map[string]*Sandbox
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
// NewMemoryStore initializes a new memory store.
|
||||
func NewMemoryStore() Storer {
|
||||
return &memoryStore{
|
||||
s: make(map[string]*Sandbox),
|
||||
}
|
||||
}
|
||||
|
||||
// Add appends a new sandbox to the memory store.
|
||||
// It overrides the id if it existed before.
|
||||
func (c *memoryStore) Add(id string, cont *Sandbox) {
|
||||
c.Lock()
|
||||
c.s[id] = cont
|
||||
c.Unlock()
|
||||
}
|
||||
|
||||
// Get returns a sandbox from the store by id.
|
||||
func (c *memoryStore) Get(id string) *Sandbox {
|
||||
c.RLock()
|
||||
res := c.s[id]
|
||||
c.RUnlock()
|
||||
return res
|
||||
}
|
||||
|
||||
// Delete removes a sandbox from the store by id.
|
||||
func (c *memoryStore) Delete(id string) {
|
||||
c.Lock()
|
||||
delete(c.s, id)
|
||||
c.Unlock()
|
||||
}
|
||||
|
||||
// List returns a sorted list of sandboxes from the store.
|
||||
// The sandboxes are ordered by creation date.
|
||||
func (c *memoryStore) List() []*Sandbox {
|
||||
sandboxes := History(c.all())
|
||||
sandboxes.sort()
|
||||
return sandboxes
|
||||
}
|
||||
|
||||
// Size returns the number of sandboxes in the store.
|
||||
func (c *memoryStore) Size() int {
|
||||
c.RLock()
|
||||
defer c.RUnlock()
|
||||
return len(c.s)
|
||||
}
|
||||
|
||||
// First returns the first sandbox found in the store by a given filter.
|
||||
func (c *memoryStore) First(filter StoreFilter) *Sandbox {
|
||||
for _, cont := range c.all() {
|
||||
if filter(cont) {
|
||||
return cont
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ApplyAll calls the reducer function with every sandbox in the store.
|
||||
// This operation is asynchronous in the memory store.
|
||||
// NOTE: Modifications to the store MUST NOT be done by the StoreReducer.
|
||||
func (c *memoryStore) ApplyAll(apply StoreReducer) {
|
||||
wg := new(sync.WaitGroup)
|
||||
for _, cont := range c.all() {
|
||||
wg.Add(1)
|
||||
go func(sandbox *Sandbox) {
|
||||
apply(sandbox)
|
||||
wg.Done()
|
||||
}(cont)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func (c *memoryStore) all() []*Sandbox {
|
||||
c.RLock()
|
||||
sandboxes := make([]*Sandbox, 0, len(c.s))
|
||||
for _, cont := range c.s {
|
||||
sandboxes = append(sandboxes, cont)
|
||||
}
|
||||
c.RUnlock()
|
||||
return sandboxes
|
||||
}
|
||||
|
||||
var _ Storer = &memoryStore{}
|
|
@ -7,6 +7,7 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/docker/docker/pkg/mount"
|
||||
|
@ -156,7 +157,8 @@ type Sandbox struct {
|
|||
portMappings []*hostport.PortMapping
|
||||
stopped bool
|
||||
// ipv4 or ipv6 cache
|
||||
ip string
|
||||
ip string
|
||||
created time.Time
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -201,6 +203,7 @@ func New(id, namespace, name, kubeName, logDir string, labels, annotations map[s
|
|||
sb.resolvPath = resolvPath
|
||||
sb.hostname = hostname
|
||||
sb.portMappings = portMappings
|
||||
sb.created = time.Now()
|
||||
|
||||
return sb, nil
|
||||
}
|
||||
|
|
27
libkpod/sandbox/store.go
Normal file
27
libkpod/sandbox/store.go
Normal file
|
@ -0,0 +1,27 @@
|
|||
package sandbox
|
||||
|
||||
// StoreFilter defines a function to filter
|
||||
// sandboxes in the store.
|
||||
type StoreFilter func(*Sandbox) bool
|
||||
|
||||
// StoreReducer defines a function to
|
||||
// manipulate sandboxes in the store
|
||||
type StoreReducer func(*Sandbox)
|
||||
|
||||
// Storer defines an interface that any container store must implement.
|
||||
type Storer interface {
|
||||
// Add appends a new sandbox to the store.
|
||||
Add(string, *Sandbox)
|
||||
// Get returns a sandbox from the store by the identifier it was stored with.
|
||||
Get(string) *Sandbox
|
||||
// Delete removes a sandbox from the store by the identifier it was stored with.
|
||||
Delete(string)
|
||||
// List returns a list of sandboxes from the store.
|
||||
List() []*Sandbox
|
||||
// Size returns the number of sandboxes in the store.
|
||||
Size() int
|
||||
// First returns the first sandbox found in the store by a given filter.
|
||||
First(StoreFilter) *Sandbox
|
||||
// ApplyAll calls the reducer function with every sandbox in the store.
|
||||
ApplyAll(StoreReducer)
|
||||
}
|
Loading…
Reference in a new issue