-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmain.go
More file actions
134 lines (129 loc) · 5.05 KB
/
main.go
File metadata and controls
134 lines (129 loc) · 5.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package main
import (
"log"
"github.com/garyburd/redigo/redis"
"github.com/docker/engine-api/client"
"github.com/docker/engine-api/types"
"golang.org/x/net/context"
"time"
"flag"
"strings"
"gopkg.in/mgo.v2"
)
type hub struct {
cli *client.Client
dbw *dbwriter
containers map[string]*Container
}
var addr = flag.String("addr", "localhost", "http service addr")
var port = flag.String("port", "5000", "http service port")
func main() {
flag.Parse()
log.Println("Canopy container management server started.")
// Start docker client
defaultHeaders := map[string]string{"User-Agent": "engine-api-cli-1.0"}
cli, err := client.NewClient("unix:///var/run/docker.sock",
"v1.18", nil, defaultHeaders)
if err != nil {
panic(err)
}
// Connect to redis database
c, err := redis.Dial("tcp", ":6379")
if err != nil {
panic(err)
}
dbw := dbwriter{redisconn: &c, commChannel: make(chan command, 2)}
go dbw.writer()
h := hub{cli: cli, dbw: &dbw, containers: make(map[string]*Container)}
// Connect to MongoDB database
session, err := mgo.Dial(":3001")
defer session.Close()
// List all existing containers and create container objects for them
options := types.ContainerListOptions{All: true}
containers, err := cli.ContainerList(context.Background(), options)
for _, cont := range containers {
if len(cont.Names) == 0 {
continue;
}
log.Println("Found container:", cont.Names[0][1:])
h.containers[cont.Names[0][1:]] = &Container{name: cont.Names[0][1:], id: cont.ID, started: false, h: &h, quit: make(chan int), mgoSession: session}
go h.containers[cont.Names[0][1:]].statusUpdater()
}
// Set running containers as running in their corresponding container objects
options = types.ContainerListOptions{All: false}
containers, err = cli.ContainerList(context.Background(), options)
for _, cont := range containers {
log.Println("Container already started:", cont.Names[0][1:])
h.containers[cont.Names[0][1:]].started = true
}
for {
// Get the containers that should be running
iter := 0
var list []string
for {
reply, _ := redis.Values(dbw.write("SCAN", iter, "match", "containers:*:status"))
var temp int
var templist []string
reply, _ = redis.Scan(reply, &temp, &templist)
iter = temp
list = append(list, templist...)
if iter == 0 {
break
}
}
for _, cont := range list {
split := strings.Split(cont, ":")
status, _ := redis.String(dbw.write("GET", cont))
cont = split[1];
if val, ok := h.containers[cont]; ok { // If container exists, start it
if status == "running" {
if !val.started {
val.start()
}
} else if status == "stopped" {
if val.started {
val.stop();
}
}
} else { // If container does not exist, create it and start it
h.containers[cont] = create(cli, cont, &h, session)
go h.containers[cont].statusUpdater()
if status == "running" {
h.containers[cont].start()
}
}
}
// Synchronize containers and container object statuses
options = types.ContainerListOptions{All: true}
containers, err = cli.ContainerList(context.Background(), options)
for _, cont := range containers {
if len(cont.Names) == 0 {
continue;
}
// Check if container is supposed to be running
status, _ := redis.String(dbw.write("GET", "containers:" + cont.Names[0][1:] + ":status"))
if status == "" { // Container removed
if h.containers[cont.Names[0][1:]].started {
h.containers[cont.Names[0][1:]].stop()
}
h.containers[cont.Names[0][1:]].remove()
delete(h.containers, cont.Names[0][1:])
} else {
if cont.Status == "" || cont.Status[:6] == "Exited" {
if status == "running" { // If it is not running but supposed to be, start it
h.containers[cont.Names[0][1:]].start()
} else { // Update container object status
h.containers[cont.Names[0][1:]].started = false
}
} else if cont.Status[:2] == "Up" {
if status == "stopped" { // If it is running but not supposed to be, stop it
h.containers[cont.Names[0][1:]].stop()
} else { // Update container object status
h.containers[cont.Names[0][1:]].started = true
}
}
}
}
time.Sleep(100 * time.Millisecond)
}
}