mirror of
https://github.com/bingohuang/docker-labs.git
synced 2025-07-14 18:27:25 +08:00
Delete zombie sessions and instances (#71)
This commit is contained in:
parent
93226e30ff
commit
54045d02f6
@ -9,7 +9,7 @@ import (
|
|||||||
type checkSwarmStatusTask struct {
|
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, err := GetDaemonInfo(i); err == nil {
|
||||||
if info.Swarm.LocalNodeState != swarm.LocalNodeStateInactive && info.Swarm.LocalNodeState != swarm.LocalNodeStateLocked {
|
if info.Swarm.LocalNodeState != swarm.LocalNodeStateInactive && info.Swarm.LocalNodeState != swarm.LocalNodeStateLocked {
|
||||||
i.IsManager = &info.Swarm.ControlAvailable
|
i.IsManager = &info.Swarm.ControlAvailable
|
||||||
@ -18,6 +18,7 @@ func (c checkSwarmStatusTask) Run(i *Instance) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,13 @@ import "log"
|
|||||||
type checkSwarmUsedPortsTask struct {
|
type checkSwarmUsedPortsTask struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c checkSwarmUsedPortsTask) Run(i *Instance) {
|
func (c checkSwarmUsedPortsTask) Run(i *Instance) error {
|
||||||
if i.IsManager != nil && *i.IsManager {
|
if i.IsManager != nil && *i.IsManager {
|
||||||
// This is a swarm manager instance, then check for ports
|
// This is a swarm manager instance, then check for ports
|
||||||
if err := SetInstanceSwarmPorts(i); err != nil {
|
if err := SetInstanceSwarmPorts(i); err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
|
import "log"
|
||||||
|
|
||||||
type checkUsedPortsTask struct {
|
type checkUsedPortsTask struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c checkUsedPortsTask) Run(i *Instance) {
|
func (c checkUsedPortsTask) Run(i *Instance) error {
|
||||||
if ports, err := GetUsedPorts(i); err == nil {
|
if ports, err := GetUsedPorts(i); err == nil {
|
||||||
for _, p := range ports {
|
for _, p := range ports {
|
||||||
i.setUsedPort(p)
|
i.setUsedPort(p)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
log.Println(err)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -19,18 +19,18 @@ type collectStatsTask struct {
|
|||||||
previousSystem uint64
|
previousSystem uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c collectStatsTask) Run(i *Instance) {
|
func (c collectStatsTask) Run(i *Instance) error {
|
||||||
reader, err := GetContainerStats(i.Name)
|
reader, err := GetContainerStats(i.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Error while trying to collect instance stats", err)
|
log.Println("Error while trying to collect instance stats", err)
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
dec := json.NewDecoder(reader)
|
dec := json.NewDecoder(reader)
|
||||||
var v *types.StatsJSON
|
var v *types.StatsJSON
|
||||||
e := dec.Decode(&v)
|
e := dec.Decode(&v)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
log.Println("Error while trying to collect instance stats", e)
|
log.Println("Error while trying to collect instance stats", e)
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
// Memory
|
// Memory
|
||||||
if v.MemoryStats.Limit != 0 {
|
if v.MemoryStats.Limit != 0 {
|
||||||
@ -46,6 +46,8 @@ func (c collectStatsTask) Run(i *Instance) {
|
|||||||
c.previousSystem = v.PreCPUStats.SystemUsage
|
c.previousSystem = v.PreCPUStats.SystemUsage
|
||||||
c.cpuPercent = calculateCPUPercentUnix(c.previousCPU, c.previousSystem, v)
|
c.cpuPercent = calculateCPUPercentUnix(c.previousCPU, c.previousSystem, v)
|
||||||
i.Cpu = fmt.Sprintf("%.2f%%", c.cpuPercent)
|
i.Cpu = fmt.Sprintf("%.2f%%", c.cpuPercent)
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func calculateCPUPercentUnix(previousCPU, previousSystem uint64, v *types.StatsJSON) float64 {
|
func calculateCPUPercentUnix(previousCPU, previousSystem uint64, v *types.StatsJSON) float64 {
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"golang.org/x/text/encoding"
|
"golang.org/x/text/encoding"
|
||||||
@ -22,7 +23,6 @@ type Instance struct {
|
|||||||
IP string `json:"ip"`
|
IP string `json:"ip"`
|
||||||
conn *types.HijackedResponse `json:"-"`
|
conn *types.HijackedResponse `json:"-"`
|
||||||
ctx context.Context `json:"-"`
|
ctx context.Context `json:"-"`
|
||||||
statsReader io.ReadCloser `json:"-"`
|
|
||||||
dockerClient *client.Client `json:"-"`
|
dockerClient *client.Client `json:"-"`
|
||||||
IsManager *bool `json:"is_manager"`
|
IsManager *bool `json:"is_manager"`
|
||||||
Mem string `json:"mem"`
|
Mem string `json:"mem"`
|
||||||
@ -129,22 +129,25 @@ func (i *Instance) Attach() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
func GetInstance(session *Session, name string) *Instance {
|
func GetInstance(session *Session, name string) *Instance {
|
||||||
//TODO: Use redis
|
|
||||||
return session.Instances[name]
|
return session.Instances[name]
|
||||||
}
|
}
|
||||||
func DeleteInstance(session *Session, instance *Instance) error {
|
func DeleteInstance(session *Session, instance *Instance) error {
|
||||||
// stop collecting stats
|
if instance.conn != nil {
|
||||||
if instance.statsReader != nil {
|
instance.conn.Close()
|
||||||
instance.statsReader.Close()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Use redis
|
|
||||||
delete(session.Instances, instance.Name)
|
|
||||||
err := DeleteContainer(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)
|
wsServer.BroadcastTo(session.Id, "delete instance", instance.Name)
|
||||||
|
|
||||||
|
delete(session.Instances, instance.Name)
|
||||||
|
if err := saveSessionsToDisk(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
setGauges()
|
setGauges()
|
||||||
|
|
||||||
return err
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -112,7 +113,16 @@ func (s *Session) SchedulePeriodicTasks() {
|
|||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
for _, t := range periodicTasks {
|
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,24 +171,26 @@ func CloseSession(s *Session) error {
|
|||||||
}
|
}
|
||||||
log.Printf("Starting clean up of session [%s]\n", s.Id)
|
log.Printf("Starting clean up of session [%s]\n", s.Id)
|
||||||
for _, i := range s.Instances {
|
for _, i := range s.Instances {
|
||||||
if i.conn != nil {
|
err := DeleteInstance(s, i)
|
||||||
i.conn.Close()
|
if err != nil {
|
||||||
}
|
|
||||||
if err := DeleteContainer(i.Name); err != nil {
|
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Disconnect PWD daemon from the network
|
// Disconnect PWD daemon from the network
|
||||||
if err := DisconnectNetwork("pwd", s.Id); err != nil {
|
if err := DisconnectNetwork("pwd", s.Id); err != nil {
|
||||||
|
if !strings.Contains(err.Error(), "is not connected to the network") {
|
||||||
log.Println("ERROR NETWORKING")
|
log.Println("ERROR NETWORKING")
|
||||||
return err
|
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 {
|
if err := DeleteNetwork(s.Id); err != nil {
|
||||||
|
if !strings.Contains(err.Error(), "not found") {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
delete(sessions, s.Id)
|
delete(sessions, s.Id)
|
||||||
|
|
||||||
// We store sessions as soon as we delete one
|
// We store sessions as soon as we delete one
|
||||||
@ -296,15 +308,21 @@ func LoadSessionsFromDisk() error {
|
|||||||
|
|
||||||
// Connect PWD daemon to the new network
|
// Connect PWD daemon to the new network
|
||||||
if err := ConnectNetwork("pwd", s.Id); err != nil {
|
if err := ConnectNetwork("pwd", s.Id); err != nil {
|
||||||
log.Println("ERROR NETWORKING")
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
log.Printf("Connected pwd to network [%s]\n", s.Id)
|
log.Printf("Connected pwd to network [%s]\n", s.Id)
|
||||||
|
|
||||||
// Schedule peridic tasks execution
|
// Schedule peridic tasks execution
|
||||||
s.SchedulePeriodicTasks()
|
s.SchedulePeriodicTasks()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
file.Close()
|
file.Close()
|
||||||
setGauges()
|
setGauges()
|
||||||
return err
|
return err
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
type periodicTask interface {
|
type periodicTask interface {
|
||||||
Run(i *Instance)
|
Run(i *Instance) error
|
||||||
}
|
}
|
||||||
|
|
||||||
var periodicTasks []periodicTask
|
var periodicTasks []periodicTask
|
||||||
|
Loading…
x
Reference in New Issue
Block a user