Browse Source

Split out docker monitoring functionality.

master
Chris Smith 8 years ago
parent
commit
a316226713
4 changed files with 71 additions and 47 deletions
  1. 1
    1
      Dockerfile
  2. 1
    1
      README.md
  3. 63
    0
      monitor.py
  4. 6
    45
      report.py

+ 1
- 1
Dockerfile View File

@@ -6,5 +6,5 @@ RUN \
6 6
     docker-py \
7 7
     python-etcd
8 8
 
9
-COPY report.py /report.py
9
+COPY *.py /
10 10
 ENTRYPOINT ["python", "/report.py"]

+ 1
- 1
README.md View File

@@ -65,7 +65,7 @@ networks in etcd:
65 65
 
66 66
 * The docker node is deleted when the script starts, so you can't run multiple
67 67
   copies on multiple hosts
68
-* Containers that are stopped aren't removed 
68
+* Containers that are stopped aren't removed
69 69
 * There's no way to get notified when the script has finished, rather than
70 70
   mid-update
71 71
 

+ 63
- 0
monitor.py View File

@@ -0,0 +1,63 @@
1
+#!/usr/bin/env python3
2
+
3
+from collections import defaultdict
4
+import docker
5
+
6
+
7
+class Monitor:
8
+
9
+  def __init__(self, host_name, on_added, on_removed):
10
+    self._client = docker.Client(base_url='unix://var/run/docker.sock')
11
+    self._containers = defaultdict(dict)
12
+    self._host = host_name
13
+    self._on_added = on_added
14
+    self._on_removed = on_removed
15
+    self._events = self._client.events(decode=True,
16
+                                       filters={'type': 'container',
17
+                                                'event': ['die', 'start']})
18
+
19
+
20
+  def monitor(self):
21
+    self._add(self._client.containers())
22
+
23
+    for event in self._events:
24
+      if event['Action'] == 'start':
25
+        print('New container %s' % event['id'])
26
+        self._add(self._client.containers(filters={'id': event['id']}))
27
+      elif event['Action'] == 'die':
28
+        print('Dead container %s' % event['id'])
29
+      else:
30
+        print('Unexpected event %s' % event['Action'])
31
+
32
+
33
+  def _add(self, infos):
34
+    res = []
35
+    for info in infos:
36
+      name = info['Names'][0][1:]
37
+      container = {
38
+        'host': self._host,
39
+        'image': info['Image'],
40
+        'labels': info['Labels'],
41
+        'name': name,
42
+        'net': {
43
+          'addr': self._get_addresses(info),
44
+          'ports': self._get_ports(info)
45
+        }
46
+      }
47
+
48
+      self._containers[name] = container
49
+      res.append(container)
50
+
51
+    self._on_added(res)
52
+
53
+
54
+  def _get_addresses(self, container):
55
+    return {k: v['IPAddress'] for k, v in container['NetworkSettings']['Networks'].items()}
56
+
57
+
58
+  def _get_ports(self, container):
59
+    ports = defaultdict(dict)
60
+    for port in container['Ports']:
61
+      ports[port['Type']][port['PrivatePort']] = port['PublicPort'] if 'PublicPort' in port else 0
62
+    return ports
63
+

+ 6
- 45
report.py View File

@@ -1,10 +1,9 @@
1 1
 #!/usr/bin/env python3
2 2
 
3 3
 from collections import defaultdict
4
+from monitor import Monitor
4 5
 import argparse
5
-import docker 
6 6
 import etcd
7
-import sys
8 7
 
9 8
 
10 9
 def etcd_put(client, prefix, obj):
@@ -17,31 +16,10 @@ def etcd_put(client, prefix, obj):
17 16
       client.write(new_prefix, str(value))
18 17
 
19 18
 
20
-def get_addresses(container):
21
-  return {k: v['IPAddress'] for k, v in container['NetworkSettings']['Networks'].items()}
22
-
23
-
24
-def get_ports(container):
25
-  ports = defaultdict(dict)
26
-  for port in container['Ports']:
27
-    ports[port['Type']][port['PrivatePort']] = port['PublicPort'] if 'PublicPort' in port else 0
28
-  return ports
29
-
30
-
31
-def add_containers(infos):
19
+def add_containers(new_containers):
32 20
   global containers, host_index, label_index, network_index
33
-  for info in infos:
34
-    container = {
35
-      'host': host,
36
-      'image': info['Image'],
37
-      'labels': info['Labels'],
38
-      'net': {
39
-        'addr': get_addresses(info),
40
-        'ports': get_ports(info)
41
-      }
42
-    }
43
-
44
-    name = info['Names'][0][1:]
21
+  for container in new_containers:
22
+    name = container['name']
45 23
     containers[name] = container
46 24
 
47 25
     for k, v in container['labels'].items():
@@ -51,8 +29,6 @@ def add_containers(infos):
51 29
 
52 30
     host_index[host][name] = name
53 31
 
54
-
55
-def write_all():
56 32
   etcd_put(etcd_client, prefix + '/containers', containers)
57 33
   etcd_put(etcd_client, prefix + '/labels', label_index)
58 34
   etcd_put(etcd_client, prefix + '/networks', network_index)
@@ -66,34 +42,19 @@ parser.add_argument('--etcd-host', help='Host to connect to etcd on', default='e
66 42
 parser.add_argument('--etcd-prefix', help='Prefix to use when adding keys to etcd', default='/docker')
67 43
 args = parser.parse_args()
68 44
 
69
-docker_client = docker.Client(base_url='unix://var/run/docker.sock')
45
+monitor = Monitor(args.name, add_containers, lambda x: None) 
70 46
 etcd_client = etcd.Client(host=args.etcd_host, port=args.etcd_port)
71 47
 prefix = args.etcd_prefix
72 48
 host = args.name
73 49
 
74
-event_gen = docker_client.events(decode=True, filters={'type': 'container', 'event': ['die', 'start']})
75
-
76 50
 containers = {}
77 51
 label_index = defaultdict(dict) 
78 52
 network_index = defaultdict(dict)
79 53
 host_index = defaultdict(dict)
80 54
 
81
-add_containers(docker_client.containers())
82
-
83 55
 try:
84 56
   etcd_client.delete(prefix, recursive=True)
85 57
 except etcd.EtcdKeyNotFound:
86 58
   pass
87 59
 
88
-write_all()
89
-
90
-for event in event_gen:
91
-  if event['Action'] == 'start':
92
-    print('New container %s' % event['id'])
93
-    add_containers(docker_client.containers(filters={'id': event['id']}))
94
-    write_all()
95
-  elif event['Action'] == 'die':
96
-    print('Dead container %s' % event['id'])
97
-  else:
98
-    print('Unexpected event %s' % event['Action'])
99
-
60
+monitor.monitor()

Loading…
Cancel
Save