3
Program to test that ntpdate will sync the clock with an internet time server.
5
Copyright (C) 2010 Canonical Ltd.
8
Jeff Lane <jeffrey.lane@canonical.com>
10
This program is free software: you can redistribute it and/or modify
11
it under the terms of the GNU General Public License version 2,
12
as published by the Free Software Foundation.
14
This program is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
GNU General Public License for more details.
19
You should have received a copy of the GNU General Public License
20
along with this program. If not, see <http://www.gnu.org/licenses/>.
22
The purpose of this script is to test to see whether the test system can
23
connect to an internet time server and sync the local clock.
25
It will also check to see if ntpd is running locally, and if so, stop it for
26
the duration of the test and restart it after the test is finished.
28
By default, we're hitting ntp.ubuntu.com, however you can use any valid NTP
29
server by passing the URL to the program via --server
37
from datetime import datetime, timedelta
38
from subprocess import Popen, PIPE, STDOUT
39
from optparse import OptionParser
41
def SilentCall(*popenargs):
43
Modified version of subprocess.call() to supress output from the command
44
that is executed. Wait for command to complete, then return the returncode
47
null_fh = open('/dev/null','w',0)
49
return Popen(*popenargs,shell=True,stdout=null_fh,stderr=null_fh).wait()
56
This checks to see if nptd is running or not, if so it returns a tuple
57
(status,pid,command) where status is either on or off.
59
ps_list = Popen('ps axo pid,comm',shell=True,stdout=PIPE).communicate()[0].splitlines()
62
if fields[1] == 'ntpd':
63
logging.debug('Found %s with PID %s' % (fields[1],fields[0]))
65
if fields[1] == 'ntpd':
66
return ('on',fields[0],fields[1])
68
return ('off','0','0')
71
def StartStopNTPD(state,pid=0):
73
This is used to either start or stop ntpd if its running.
76
logging.info('Stopping ntpd process PID: %s' % pid)
77
os.kill(int(pid),signal.SIGHUP)
79
logging.debug('Starting ntp process')
80
status = SilentCall('/etc/init.d/ntp start')
81
ntpd_status = CheckNTPD()
84
logging.info('ntpd restarted with PID: %s' % ntpd_status[1])
86
logging.error('ntpd restart failed for some reason')
88
logging.error('Unknown status')
93
This is used to sync time to the specified ntp server. We use -b here as
94
that syncs time faster than the slewed method that ntpdate uses by default,
95
meaning we'll see something meaningful faster.
97
cmd='ntpdate -b ' + server
98
logging.debug('using %s' % server)
99
sync = Popen(cmd,shell=True,stdout=PIPE,stderr=PIPE)
100
result = sync.communicate()
102
if sync.returncode == 0:
103
logging.info('Successful NTP update from %s' % server)
104
logging.info('%s' % result[0].strip())
107
logging.error('Failed to sync with %s' % server)
108
logging.error('%s' % result[1])
113
Returns current time in a time.localtime() struct
115
return time.localtime()
119
Optional function. We can skew time by 1 hour if we'd like to see real sync
120
changes being enforced
123
logging.info('Time Skewing has been selected. Setting clock ahead 1 hour')
124
# Let's get our current time
125
skewed = datetime.now() + timedelta(hours=TIME_SKEW)
126
logging.info('Current time is: %s' % time.asctime())
127
# Now create new time string in the form MMDDhhmmYYYY for the date program
128
date_time_string = skewed.strftime('%m%d%H%M%Y')
129
logging.debug('New date string is: %s' % date_time_string)
130
logging.debug('Setting new system time/date')
131
status = SilentCall('/bin/date %s' % date_time_string)
132
logging.info('Pre-sync time is: %s' % time.asctime())
135
usage = 'Usage: %prog [OPTIONS]'
136
parser = OptionParser(usage)
137
parser.add_option('--server',
140
default='ntp.ubuntu.com',
141
help='The NTP server to sync from. The default server \
143
parser.add_option('--skew-time',
146
help='Setting this will change system time ahead by 1 \
147
hour to make the results of ntp syncing more dramatic \
149
parser.add_option('-d','--debug',
152
help='Verbose output for debugging purposes')
153
(options, args) = parser.parse_args()
156
format = '%(asctime)s %(levelname)-8s %(message)s'
157
handler = logging.StreamHandler()
158
handler.setFormatter(logging.Formatter(format))
159
logger = logging.getLogger()
160
logger.setLevel(logging.INFO)
162
logger.setLevel(logging.DEBUG)
163
logger.addHandler(handler)
165
# Make sure NTP is installed
166
if not os.access('/usr/sbin/ntpdate',os.F_OK):
167
logging.debug('NTP is not installed!')
170
# Check for and stop the ntp daemon
171
ntpd_status = CheckNTPD()
172
logging.debug('Pre-sync ntpd status: %s %s %s' % (ntpd_status[0],
175
if ntpd_status[0] == 'on':
176
logging.debug('Since ntpd is currently running, stopping it now')
177
StartStopNTPD('off',ntpd_status[1])
179
if options.skew_time:
180
logging.debug('Setting system time ahead one hour')
183
logging.info('Pre-sync time is: %s' % time.asctime(TimeCheck()))
185
sync = SyncTime(options.server)
187
logging.info('Current system time is: %s' % time.asctime(TimeCheck()))
190
if ntpd_status[0] == 'on':
191
logging.debug('Since ntpd was previously running, starting it again')
199
if __name__ == '__main__':