Return actually reachable IP as part of the Floating IP API
[osm/vim-emu.git] / src / emuvim / api / openstack / docker_util.py
1 # Copyright (c) 2015 SONATA-NFV and Paderborn University
2 # ALL RIGHTS RESERVED.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16 # Neither the name of the SONATA-NFV, Paderborn University
17 # nor the names of its contributors may be used to endorse or promote
18 # products derived from this software without specific prior written
19 # permission.
20 #
21 # This work has been performed in the framework of the SONATA project,
22 # funded by the European Commission under Grant number 671517 through
23 # the Horizon 2020 and 5G-PPP programmes. The authors would like to
24 # acknowledge the contributions of their colleagues of the SONATA
25 # partner consortium (www.sonata-nfv.eu).
26 from docker import APIClient
27 import time
28 import re
29
30
31 def docker_container_id(container_name):
32 """
33 Uses the container name to return the container ID.
34
35 :param container_name: The full name of the docker container.
36 :type container_name: ``str``
37 :return: Returns the container ID or None if the container is not running or could not be found.
38 :rtype: ``dict``
39 """
40 c = APIClient()
41 detail = c.inspect_container(container_name)
42 if bool(detail["State"]["Running"]):
43 return detail['Id']
44 return None
45
46
47 def docker_abs_cpu(container_id):
48 """
49 Returns the used CPU time since container startup and the system time in nanoseconds and returns the number
50 of available CPU cores.
51
52 :param container_id: The full ID of the docker container.
53 :type container_id: ``str``
54 :return: Returns a dict with CPU_used in nanoseconds, the current system time in nanoseconds and the number of
55 CPU cores available.
56 :rtype: ``dict``
57 """
58 with open('/sys/fs/cgroup/cpuacct/docker/' + container_id + '/cpuacct.usage_percpu', 'r') as f:
59 line = f.readline()
60 sys_time = int(time.time() * 1000000000)
61 numbers = [int(x) for x in line.split()]
62 cpu_usage = 0
63 for number in numbers:
64 cpu_usage += number
65 return {'CPU_used': cpu_usage,
66 'CPU_used_systime': sys_time, 'CPU_cores': len(numbers)}
67
68
69 def docker_mem_used(container_id):
70 """
71 Bytes of memory used from the docker container.
72
73 Note: If you have problems with this command you have to enable memory control group.
74 For this you have to add the following kernel parameters: `cgroup_enable=memory swapaccount=1`.
75 See: https://docs.docker.com/engine/admin/runmetrics/
76
77 :param container_id: The full ID of the docker container.
78 :type container_id: ``str``
79 :return: Returns the memory utilization in bytes.
80 :rtype: ``str``
81 """
82 with open('/sys/fs/cgroup/memory/docker/' + container_id + '/memory.usage_in_bytes', 'r') as f:
83 return int(f.readline())
84
85
86 def docker_max_mem(container_id):
87 """
88 Bytes of memory the docker container could use.
89
90 :param container_id: The full ID of the docker container.
91 :type container_id: ``str``
92 :return: Returns the bytes of memory the docker container could use.
93 :rtype: ``str``
94 """
95 with open('/sys/fs/cgroup/memory/docker/' + container_id + '/memory.limit_in_bytes', 'r') as f:
96 mem_limit = int(f.readline())
97 with open('/proc/meminfo', 'r') as f:
98 line = f.readline().split()
99 sys_value = int(line[1])
100 unit = line[2]
101 if unit == 'kB':
102 sys_value *= 1024
103 if unit == 'MB':
104 sys_value *= 1024 * 1024
105
106 if sys_value < mem_limit:
107 return sys_value
108 else:
109 return mem_limit
110
111
112 def docker_mem(container_id):
113 """
114 Calculates the current, maximal and percentage usage of the specified docker container.
115
116 :param container_id: The full ID of the docker container.
117 :type container_id: ``str``
118 :return: Returns a dictionary with the total memory usage, the maximal available memory and the percentage
119 memory usage.
120 :rtype: ``dict``
121 """
122 out_dict = dict()
123 out_dict['MEM_used'] = docker_mem_used(container_id)
124 out_dict['MEM_limit'] = docker_max_mem(container_id)
125 out_dict['MEM_%'] = float(out_dict['MEM_used']) / \
126 float(out_dict['MEM_limit'])
127 return out_dict
128
129
130 def docker_abs_net_io(container_id):
131 """
132 Network traffic of all network interfaces within the controller.
133
134 :param container_id: The full ID of the docker container.
135 :type container_id: ``str``
136 :return: Returns the absolute network I/O till container startup, in bytes. The return dict also contains the
137 system time.
138 :rtype: ``dict``
139 """
140 c = APIClient()
141 command = c.exec_create(container_id, 'ifconfig')
142 ifconfig = c.exec_start(command['Id'])
143 sys_time = int(time.time() * 1000000000)
144
145 in_bytes = 0
146 m = re.findall('RX bytes:(\d+)', str(ifconfig))
147 if m:
148 for number in m:
149 in_bytes += int(number)
150 else:
151 in_bytes = None
152
153 out_bytes = 0
154 m = re.findall('TX bytes:(\d+)', str(ifconfig))
155 if m:
156 for number in m:
157 out_bytes += int(number)
158 else:
159 out_bytes = None
160
161 return {'NET_in': in_bytes, 'NET_out': out_bytes, 'NET_systime': sys_time}
162
163
164 def docker_block_rw(container_id):
165 """
166 Determines the disk read and write access from the controller since startup.
167
168 :param container_id: The full ID of the docker container.
169 :type container_id: ``str``
170 :return: Returns a dictionary with the total disc I/O since container startup, in bytes.
171 :rtype: ``dict``
172 """
173 with open('/sys/fs/cgroup/blkio/docker/' + container_id + '/blkio.throttle.io_service_bytes', 'r') as f:
174 read = f.readline().split()
175 write = f.readline().split()
176 rw_dict = dict()
177 rw_dict['BLOCK_systime'] = int(time.time() * 1000000000)
178 if len(read) < 3:
179 rw_dict['BLOCK_read'] = 0
180 else:
181 rw_dict['BLOCK_read'] = read[2]
182 if len(write) < 3:
183 rw_dict['BLOCK_write'] = 0
184 else:
185 rw_dict['BLOCK_write'] = write[2]
186 return rw_dict
187
188
189 def docker_PIDS(container_id):
190 """
191 Determines the number of processes within the docker container.
192
193 :param container_id: The full ID of the docker container.
194 :type container_id: ``str``
195 :return: Returns the number of PIDS within a dictionary.
196 :rtype: ``dict``
197 """
198 with open('/sys/fs/cgroup/cpuacct/docker/' + container_id + '/tasks', 'r') as f:
199 return {'PIDS': len(f.read().split('\n')) - 1}
200
201
202 def monitoring_over_time(container_id):
203 """
204 Calculates the cpu workload and the network traffic per second.
205
206 :param container_id: The full docker container ID
207 :type container_id: ``str``
208 :return: A dictionary with disk read and write per second, network traffic per second (in and out),
209 the cpu workload and the number of cpu cores available.
210 :rtype: ``dict``
211 """
212 first_cpu_usage = docker_abs_cpu(container_id)
213 first = docker_abs_net_io(container_id)
214 first_disk_io = docker_block_rw(container_id)
215 time.sleep(1)
216 second_cpu_usage = docker_abs_cpu(container_id)
217 second = docker_abs_net_io(container_id)
218 second_disk_io = docker_block_rw(container_id)
219
220 # Disk access
221 time_div = (int(second_disk_io['BLOCK_systime']
222 ) - int(first_disk_io['BLOCK_systime']))
223 read_div = int(second_disk_io['BLOCK_read']) - \
224 int(first_disk_io['BLOCK_read'])
225 write_div = int(second_disk_io['BLOCK_write']) - \
226 int(first_disk_io['BLOCK_write'])
227 out_dict = {'BLOCK_read/s': int(read_div * 1000000000 / float(time_div) + 0.5),
228 'BLOCK_write/s': int(write_div * 1000000000 / float(time_div) + 0.5)}
229
230 # Network traffic
231 time_div = (int(second['NET_systime']) - int(first['NET_systime']))
232 in_div = int(second['NET_in']) - int(first['NET_in'])
233 out_div = int(second['NET_out']) - int(first['NET_out'])
234 out_dict.update({'NET_in/s': int(in_div * 1000000000 / float(time_div) + 0.5),
235 'NET_out/s': int(out_div * 1000000000 / float(time_div) + 0.5)})
236
237 # CPU utilization
238 time_div = (int(second_cpu_usage['CPU_used_systime']
239 ) - int(first_cpu_usage['CPU_used_systime']))
240 usage_div = int(second_cpu_usage['CPU_used']) - \
241 int(first_cpu_usage['CPU_used'])
242 out_dict.update({'CPU_%': usage_div / float(time_div),
243 'CPU_cores': first_cpu_usage['CPU_cores']})
244 return out_dict