1 # Copyright (c) 2015 SONATA-NFV and Paderborn University
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
8 # http://www.apache.org/licenses/LICENSE-2.0
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.
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
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
31 def docker_container_id(container_name
):
33 Uses the container name to return the container ID.
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.
41 detail
= c
.inspect_container(container_name
)
42 if bool(detail
["State"]["Running"]):
47 def docker_abs_cpu(container_id
):
49 Returns the used CPU time since container startup and the system time in nanoseconds and returns the number
50 of available CPU cores.
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
58 with
open('/sys/fs/cgroup/cpuacct/docker/' + container_id
+ '/cpuacct.usage_percpu', 'r') as f
:
60 sys_time
= int(time
.time() * 1000000000)
61 numbers
= [int(x
) for x
in line
.split()]
63 for number
in numbers
:
65 return {'CPU_used': cpu_usage
,
66 'CPU_used_systime': sys_time
, 'CPU_cores': len(numbers
)}
69 def docker_mem_used(container_id
):
71 Bytes of memory used from the docker container.
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/
77 :param container_id: The full ID of the docker container.
78 :type container_id: ``str``
79 :return: Returns the memory utilization in bytes.
82 with
open('/sys/fs/cgroup/memory/docker/' + container_id
+ '/memory.usage_in_bytes', 'r') as f
:
83 return int(f
.readline())
86 def docker_max_mem(container_id
):
88 Bytes of memory the docker container could use.
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.
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])
104 sys_value
*= 1024 * 1024
106 if sys_value
< mem_limit
:
112 def docker_mem(container_id
):
114 Calculates the current, maximal and percentage usage of the specified docker container.
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
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'])
130 def docker_abs_net_io(container_id
):
132 Network traffic of all network interfaces within the controller.
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
141 command
= c
.exec_create(container_id
, 'ifconfig')
142 ifconfig
= c
.exec_start(command
['Id'])
143 sys_time
= int(time
.time() * 1000000000)
146 m
= re
.findall('RX bytes:(\d+)', str(ifconfig
))
149 in_bytes
+= int(number
)
154 m
= re
.findall('TX bytes:(\d+)', str(ifconfig
))
157 out_bytes
+= int(number
)
161 return {'NET_in': in_bytes
, 'NET_out': out_bytes
, 'NET_systime': sys_time
}
164 def docker_block_rw(container_id
):
166 Determines the disk read and write access from the controller since startup.
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.
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()
177 rw_dict
['BLOCK_systime'] = int(time
.time() * 1000000000)
179 rw_dict
['BLOCK_read'] = 0
181 rw_dict
['BLOCK_read'] = read
[2]
183 rw_dict
['BLOCK_write'] = 0
185 rw_dict
['BLOCK_write'] = write
[2]
189 def docker_PIDS(container_id
):
191 Determines the number of processes within the docker container.
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.
198 with
open('/sys/fs/cgroup/cpuacct/docker/' + container_id
+ '/tasks', 'r') as f
:
199 return {'PIDS': len(f
.read().split('\n')) - 1}
202 def monitoring_over_time(container_id
):
204 Calculates the cpu workload and the network traffic per second.
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.
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
)
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
)
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)}
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)})
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']})