2 Copyright (c) 2017 SONATA-NFV and Paderborn University
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
9 http://www.apache.org/licenses/LICENSE-2.0
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
17 Neither the name of the SONATA-NFV, Paderborn University
18 nor the names of its contributors may be used to endorse or promote
19 products derived from this software without specific prior written
22 This work has been performed in the framework of the SONATA project,
23 funded by the European Commission under Grant number 671517 through
24 the Horizon 2020 and 5G-PPP programmes. The authors would like to
25 acknowledge the contributions of their colleagues of the SONATA
26 partner consortium (www.sonata-nfv.eu).
28 from docker
import DockerClient
, APIClient
33 def docker_container_id(container_name
):
35 Uses the container name to return the container ID.
37 :param container_name: The full name of the docker container.
38 :type container_name: ``str``
39 :return: Returns the container ID or None if the container is not running or could not be found.
43 detail
= c
.inspect_container(container_name
)
44 if bool(detail
["State"]["Running"]):
49 def docker_abs_cpu(container_id
):
51 Returns the used CPU time since container startup and the system time in nanoseconds and returns the number
52 of available CPU cores.
54 :param container_id: The full ID of the docker container.
55 :type container_id: ``str``
56 :return: Returns a dict with CPU_used in nanoseconds, the current system time in nanoseconds and the number of
60 with
open('/sys/fs/cgroup/cpuacct/docker/' + container_id
+ '/cpuacct.usage_percpu', 'r') as f
:
62 sys_time
= int(time
.time() * 1000000000)
63 numbers
= [int(x
) for x
in line
.split()]
65 for number
in numbers
:
67 return {'CPU_used': cpu_usage
, 'CPU_used_systime': sys_time
, 'CPU_cores': len(numbers
)}
70 def docker_mem_used(container_id
):
72 Bytes of memory used from the docker container.
74 Note: If you have problems with this command you have to enable memory control group.
75 For this you have to add the following kernel parameters: `cgroup_enable=memory swapaccount=1`.
76 See: https://docs.docker.com/engine/admin/runmetrics/
78 :param container_id: The full ID of the docker container.
79 :type container_id: ``str``
80 :return: Returns the memory utilization in bytes.
83 with
open('/sys/fs/cgroup/memory/docker/' + container_id
+ '/memory.usage_in_bytes', 'r') as f
:
84 return int(f
.readline())
87 def docker_max_mem(container_id
):
89 Bytes of memory the docker container could use.
91 :param container_id: The full ID of the docker container.
92 :type container_id: ``str``
93 :return: Returns the bytes of memory the docker container could use.
96 with
open('/sys/fs/cgroup/memory/docker/' + container_id
+ '/memory.limit_in_bytes', 'r') as f
:
97 mem_limit
= int(f
.readline())
98 with
open('/proc/meminfo', 'r') as f
:
99 line
= f
.readline().split()
100 sys_value
= int(line
[1])
105 sys_value
*= 1024 * 1024
107 if sys_value
< mem_limit
:
113 def docker_mem(container_id
):
115 Calculates the current, maximal and percentage usage of the specified docker container.
117 :param container_id: The full ID of the docker container.
118 :type container_id: ``str``
119 :return: Returns a dictionary with the total memory usage, the maximal available memory and the percentage
124 out_dict
['MEM_used'] = docker_mem_used(container_id
)
125 out_dict
['MEM_limit'] = docker_max_mem(container_id
)
126 out_dict
['MEM_%'] = float(out_dict
['MEM_used']) / 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']) - int(first_disk_io
['BLOCK_systime']))
222 read_div
= int(second_disk_io
['BLOCK_read']) - int(first_disk_io
['BLOCK_read'])
223 write_div
= int(second_disk_io
['BLOCK_write']) - int(first_disk_io
['BLOCK_write'])
224 out_dict
= {'BLOCK_read/s': int(read_div
* 1000000000 / float(time_div
) + 0.5),
225 'BLOCK_write/s': int(write_div
* 1000000000 / float(time_div
) + 0.5)}
228 time_div
= (int(second
['NET_systime']) - int(first
['NET_systime']))
229 in_div
= int(second
['NET_in']) - int(first
['NET_in'])
230 out_div
= int(second
['NET_out']) - int(first
['NET_out'])
231 out_dict
.update({'NET_in/s': int(in_div
* 1000000000 / float(time_div
) + 0.5),
232 'NET_out/s': int(out_div
* 1000000000 / float(time_div
) + 0.5)})
235 time_div
= (int(second_cpu_usage
['CPU_used_systime']) - int(first_cpu_usage
['CPU_used_systime']))
236 usage_div
= int(second_cpu_usage
['CPU_used']) - int(first_cpu_usage
['CPU_used'])
237 out_dict
.update({'CPU_%': usage_div
/ float(time_div
), 'CPU_cores': first_cpu_usage
['CPU_cores']})