Projet

Général

Profil

Paste
Télécharger au format
Statistiques
| Branche: | Révision:

root / plugins / systemd / timesync_status @ 3e015885

Historique | Voir | Annoter | Télécharger (3,34 ko)

1 44b604cd Bert Peters
#!/usr/bin/env python3
2
import re
3
import subprocess
4
import sys
5
import textwrap
6
7
8
'''
9
=head1 NAME
10
11
timesync_status - monitor ntp status with systemd-timesyncd
12
13
=head1 APPLICABLE SYSTEMS
14
15
All systems using systemd-timesyncd as its NTP-client. However, this
16
plugin itself also needs Python 3.5+ to call subprocess.run.
17
18
=head1 CONFIGURATION
19
20
This plugin should work out-of-the-box with autoconf. It does expect
21
timedatectl to be on $PATH, but that should always be the case in a
22
normal system.
23
24
=head1 INTERPRETATION
25
26
This plugin shows a graph with one line for every NTP metric it measure.
27
Metrics are shown with their usual name, and are explained in their
28
respective info fields.
29
30
This plugin issues no warnings or critical states.
31
32
=head1 MAGIC MARKERS
33
34
 #%# family=auto
35
 #%# capabilities=autoconf
36
37
=head1 VERSION
38
39
1.0
40
41
=head1 AUTHOR
42
43
Bert Peters <bert@bertptrs.nl>
44
45
=head1 LICENSE
46
47 c6f88968 Lars Kruse
GNU General Public License v2.0 only
48
49
SPDX-License-Identifier: LGPL-2.0-only
50
51
=cut
52 44b604cd Bert Peters
'''
53
54
55
def parse_time(value):
56
    value = value.strip()
57
    if ' ' in value:
58
        return sum(parse_time(x) for x in value.split(' '))
59
60 3e015885 Ondřej Nový
    # If time is exactly zero (for example Jitter), there is no unit (suffix)
61
    if value == "0" or value == "-0":
62
        return 0
63
64 44b604cd Bert Peters
    match = re.match(r'^([+-]?[0-9.]+)([a-z]+)$', value)
65
    if not match:
66
        raise ValueError('Invalid time ' + value)
67
68
    value = float(match.group(1))
69
    suffix = match.group(2)
70
71
    if suffix == 'min':
72
        value *= 60
73
    elif suffix == 'ms':
74
        value /= 1000
75
    elif suffix == 'us':
76
        value /= 1e6
77
78
    return value
79
80
81
def parse_response(data):
82
    values = {}
83
    for line in data.splitlines():
84
        k, v = line.split(': ', 1)
85
        values[k.strip()] = v.strip()
86
87
    return values
88
89
90
def retrieve():
91
    result = subprocess.run(['timedatectl', 'timesync-status'], capture_output=True)
92
    if result.returncode != 0:
93
        sys.exit('timedatectl failed')
94
95
    output = result.stdout.decode('utf-8')
96
    values = parse_response(output)
97
98
    print('offset.value', parse_time(values['Offset']))
99
    print('delay.value', parse_time(values['Delay']))
100
    print('delay.extinfo', 'Server', values['Server'])
101
    print('jitter.value', parse_time(values['Jitter']))
102
    print('poll.value', parse_time(values['Poll interval'].split('(')[0]))
103
104
105
def autoconf():
106
    result = subprocess.run(['timedatectl', 'status'], capture_output=True)
107
    if result.returncode != 0:
108
        print('no (failed to run timedatectl)')
109
        return
110
111
    values = parse_response(result.stdout.decode('utf-8'))
112
    if values['NTP service'] == 'active':
113
        print('yes')
114
    else:
115
        print('no (ntp service not running)')
116
117
118
def config():
119
    print(textwrap.dedent('''\
120
            graph_title Timesync status
121
            graph_vlabel s
122
            graph_category time
123
124
            offset.label Offset
125
            offset.info Time difference between source and local
126
127
            delay.label Delay
128
            delay.info Roundtrip time to the NTP-server
129
130
            jitter.label Jitter
131
            jitter.info Difference in offset between two subsequent samples
132
133
            poll.label Polling time
134
            poll.info Time between two subsequent NTP-polls
135
    '''))
136
137
138
if __name__ == '__main__':
139 493b71d9 Simone Rossetto
    if len(sys.argv) > 1 and sys.argv[1] == 'config':
140 44b604cd Bert Peters
        config()
141 493b71d9 Simone Rossetto
    elif len(sys.argv) > 1 and sys.argv[1] == 'autoconf':
142 44b604cd Bert Peters
        autoconf()
143 493b71d9 Simone Rossetto
    else:
144
        retrieve()