1
0
mirror of https://github.com/bingohuang/docker-labs.git synced 2025-07-14 01:57:32 +08:00

Delete zombie sessions and instances (#71)

This commit is contained in:
Jonathan Leibiusky 2016-12-17 12:48:15 -08:00 committed by Marcos Nils
parent 93226e30ff
commit 54045d02f6
7 changed files with 65 additions and 33 deletions

View File

@ -9,7 +9,7 @@ import (
type checkSwarmStatusTask struct {
}
func (c checkSwarmStatusTask) Run(i *Instance) {
func (c checkSwarmStatusTask) Run(i *Instance) error {
if info, err := GetDaemonInfo(i); err == nil {
if info.Swarm.LocalNodeState != swarm.LocalNodeStateInactive && info.Swarm.LocalNodeState != swarm.LocalNodeStateLocked {
i.IsManager = &info.Swarm.ControlAvailable
@ -18,6 +18,7 @@ func (c checkSwarmStatusTask) Run(i *Instance) {
}
} else {
log.Println(err)
return err
}
return nil
}

View File

@ -5,11 +5,13 @@ import "log"
type checkSwarmUsedPortsTask struct {
}
func (c checkSwarmUsedPortsTask) Run(i *Instance) {
func (c checkSwarmUsedPortsTask) Run(i *Instance) error {
if i.IsManager != nil && *i.IsManager {
// This is a swarm manager instance, then check for ports
if err := SetInstanceSwarmPorts(i); err != nil {
log.Println(err)
return err
}
}
return nil
}

View File

@ -1,12 +1,18 @@
package services
import "log"
type checkUsedPortsTask struct {
}
func (c checkUsedPortsTask) Run(i *Instance) {
func (c checkUsedPortsTask) Run(i *Instance) error {
if ports, err := GetUsedPorts(i); err == nil {
for _, p := range ports {
i.setUsedPort(p)
}
} else {
log.Println(err)
return err
}
return nil
}

View File

@ -19,18 +19,18 @@ type collectStatsTask struct {
previousSystem uint64
}
func (c collectStatsTask) Run(i *Instance) {
func (c collectStatsTask) Run(i *Instance) error {
reader, err := GetContainerStats(i.Name)
if err != nil {
log.Println("Error while trying to collect instance stats", err)
return
return err
}
dec := json.NewDecoder(reader)
var v *types.StatsJSON
e := dec.Decode(&v)
if e != nil {
log.Println("Error while trying to collect instance stats", e)
return
return err
}
// Memory
if v.MemoryStats.Limit != 0 {
@ -46,6 +46,8 @@ func (c collectStatsTask) Run(i *Instance) {
c.previousSystem = v.PreCPUStats.SystemUsage
c.cpuPercent = calculateCPUPercentUnix(c.previousCPU, c.previousSystem, v)
i.Cpu = fmt.Sprintf("%.2f%%", c.cpuPercent)
return nil
}
func calculateCPUPercentUnix(previousCPU, previousSystem uint64, v *types.StatsJSON) float64 {

View File

@ -5,6 +5,7 @@ import (
"io"
"log"
"os"
"strings"
"sync"
"golang.org/x/text/encoding"
@ -22,7 +23,6 @@ type Instance struct {
IP string `json:"ip"`
conn *types.HijackedResponse `json:"-"`
ctx context.Context `json:"-"`
statsReader io.ReadCloser `json:"-"`
dockerClient *client.Client `json:"-"`
IsManager *bool `json:"is_manager"`
Mem string `json:"mem"`
@ -129,22 +129,25 @@ func (i *Instance) Attach() {
}
}
func GetInstance(session *Session, name string) *Instance {
//TODO: Use redis
return session.Instances[name]
}
func DeleteInstance(session *Session, instance *Instance) error {
// stop collecting stats
if instance.statsReader != nil {
instance.statsReader.Close()
if instance.conn != nil {
instance.conn.Close()
}
//TODO: Use redis
delete(session.Instances, instance.Name)
err := DeleteContainer(instance.Name)
if !strings.Contains(err.Error(), "No such container") {
log.Println(err)
return err
}
wsServer.BroadcastTo(session.Id, "delete instance", instance.Name)
delete(session.Instances, instance.Name)
if err := saveSessionsToDisk(); err != nil {
return err
}
setGauges()
return err
return nil
}

View File

@ -9,6 +9,7 @@ import (
"net/http"
"os"
"strconv"
"strings"
"sync"
"time"
@ -112,7 +113,16 @@ func (s *Session) SchedulePeriodicTasks() {
go func() {
defer wg.Done()
for _, t := range periodicTasks {
t.Run(i)
err := t.Run(i)
if err != nil {
if strings.Contains(err.Error(), "No such container") {
log.Printf("Container for instance [%s] doesn't exist any more. Deleting from session.\n", i.IP)
DeleteInstance(i.session, i)
} else {
log.Println(err)
}
break
}
}
}()
}
@ -161,23 +171,25 @@ func CloseSession(s *Session) error {
}
log.Printf("Starting clean up of session [%s]\n", s.Id)
for _, i := range s.Instances {
if i.conn != nil {
i.conn.Close()
}
if err := DeleteContainer(i.Name); err != nil {
err := DeleteInstance(s, i)
if err != nil {
log.Println(err)
return err
}
}
// Disconnect PWD daemon from the network
if err := DisconnectNetwork("pwd", s.Id); err != nil {
log.Println("ERROR NETWORKING")
return err
if !strings.Contains(err.Error(), "is not connected to the network") {
log.Println("ERROR NETWORKING")
return err
}
}
log.Printf("Connected pwd to network [%s]\n", s.Id)
log.Printf("Disconnected pwd from network [%s]\n", s.Id)
if err := DeleteNetwork(s.Id); err != nil {
log.Println(err)
return err
if !strings.Contains(err.Error(), "not found") {
log.Println(err)
return err
}
}
delete(sessions, s.Id)
@ -296,13 +308,19 @@ func LoadSessionsFromDisk() error {
// Connect PWD daemon to the new network
if err := ConnectNetwork("pwd", s.Id); err != nil {
log.Println("ERROR NETWORKING")
return err
}
log.Printf("Connected pwd to network [%s]\n", s.Id)
if strings.Contains(err.Error(), "Could not attach to network") {
log.Printf("Network for session [%s] doesn't exist. Removing all instances and session.", s.Id)
CloseSession(s)
} else {
log.Println("ERROR NETWORKING", err)
return err
}
} else {
log.Printf("Connected pwd to network [%s]\n", s.Id)
// Schedule peridic tasks execution
s.SchedulePeriodicTasks()
// Schedule peridic tasks execution
s.SchedulePeriodicTasks()
}
}
}
file.Close()

View File

@ -1,7 +1,7 @@
package services
type periodicTask interface {
Run(i *Instance)
Run(i *Instance) error
}
var periodicTasks []periodicTask