~oem-qa/checkbox/patch_deselect_ancestors_when_no_child_is_selected

« back to all changes in this revision

Viewing changes to scripts/network_ntp_test

Imported scripts and jobs from Platform Services.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
'''
 
3
Program to test that ntpdate will sync the clock with an internet time server.
 
4
 
 
5
Copyright (C) 2010 Canonical Ltd.
 
6
 
 
7
Author:
 
8
    Jeff Lane <jeffrey.lane@canonical.com>
 
9
 
 
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.
 
13
 
 
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.
 
18
 
 
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/>.
 
21
 
 
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.
 
24
 
 
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.
 
27
 
 
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
 
30
 
 
31
'''
 
32
import sys
 
33
import os
 
34
import logging
 
35
import signal
 
36
import time
 
37
from datetime import datetime, timedelta
 
38
from subprocess import Popen, PIPE, STDOUT
 
39
from optparse import OptionParser 
 
40
 
 
41
def SilentCall(*popenargs):
 
42
    '''
 
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
 
45
    attribute.
 
46
    '''
 
47
    null_fh = open('/dev/null','w',0)
 
48
    try:
 
49
        return Popen(*popenargs,shell=True,stdout=null_fh,stderr=null_fh).wait()
 
50
    finally:
 
51
        null_fh.close()
 
52
 
 
53
 
 
54
def CheckNTPD():
 
55
    '''
 
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.
 
58
    '''
 
59
    ps_list = Popen('ps axo pid,comm',shell=True,stdout=PIPE).communicate()[0].splitlines()
 
60
    for item in ps_list:
 
61
        fields = item.split()
 
62
        if fields[1] == 'ntpd':
 
63
            logging.debug('Found %s with PID %s' % (fields[1],fields[0]))
 
64
            break
 
65
    if fields[1] == 'ntpd':
 
66
        return ('on',fields[0],fields[1])
 
67
    else:
 
68
        return ('off','0','0')
 
69
 
 
70
 
 
71
def StartStopNTPD(state,pid=0):
 
72
    '''
 
73
    This is used to either start or stop ntpd if its running.
 
74
    '''
 
75
    if state == 'off':
 
76
        logging.info('Stopping ntpd process PID: %s' % pid)
 
77
        os.kill(int(pid),signal.SIGHUP)
 
78
    elif state == 'on':
 
79
        logging.debug('Starting ntp process')
 
80
        status = SilentCall('/etc/init.d/ntp start')
 
81
        ntpd_status = CheckNTPD()
 
82
 
 
83
        if status == 0:
 
84
            logging.info('ntpd restarted with PID: %s' % ntpd_status[1])
 
85
        else:
 
86
            logging.error('ntpd restart failed for some reason') 
 
87
    else:
 
88
        logging.error('Unknown status')
 
89
 
 
90
 
 
91
def SyncTime(server):
 
92
    '''
 
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.
 
96
    '''
 
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()
 
101
    
 
102
    if sync.returncode == 0:
 
103
        logging.info('Successful NTP update from %s' % server)
 
104
        logging.info('%s' % result[0].strip())
 
105
        return True
 
106
    else:
 
107
        logging.error('Failed to sync with %s' % server)
 
108
        logging.error('%s' % result[1])
 
109
        return False
 
110
 
 
111
def TimeCheck():
 
112
    '''
 
113
    Returns current time in a time.localtime() struct
 
114
    '''
 
115
    return time.localtime()
 
116
 
 
117
def SkewTime():
 
118
    '''
 
119
    Optional function. We can skew time by 1 hour if we'd like to see real sync
 
120
    changes being enforced
 
121
    '''
 
122
    TIME_SKEW=1
 
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())
 
133
 
 
134
def main():
 
135
    usage = 'Usage: %prog [OPTIONS]'
 
136
    parser = OptionParser(usage)
 
137
    parser.add_option('--server',
 
138
                        action='store',
 
139
                        type='string',
 
140
                        default='ntp.ubuntu.com',
 
141
                        help='The NTP server to sync from. The default server \
 
142
                        is %default') 
 
143
    parser.add_option('--skew-time',
 
144
                        action='store_true',
 
145
                        default=False,
 
146
                        help='Setting this will change system time ahead by 1 \
 
147
                        hour to make the results of ntp syncing more dramatic \
 
148
                        and noticeable.')
 
149
    parser.add_option('-d','--debug',
 
150
                        action='store_true',
 
151
                        default=False,
 
152
                        help='Verbose output for debugging purposes')
 
153
    (options, args) = parser.parse_args()
 
154
 
 
155
    # Set up logging
 
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)
 
161
    if options.debug:
 
162
        logger.setLevel(logging.DEBUG)
 
163
    logger.addHandler(handler)
 
164
 
 
165
    # Make sure NTP is installed
 
166
    if not os.access('/usr/sbin/ntpdate',os.F_OK):
 
167
        logging.debug('NTP is not installed!')
 
168
        return 1
 
169
    
 
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],
 
173
                                                      ntpd_status[1],
 
174
                                                      ntpd_status[2]))
 
175
    if ntpd_status[0] == 'on':
 
176
        logging.debug('Since ntpd is currently running, stopping it now')
 
177
        StartStopNTPD('off',ntpd_status[1])
 
178
    
 
179
    if options.skew_time:
 
180
        logging.debug('Setting system time ahead one hour')
 
181
        SkewTime()
 
182
    else:
 
183
        logging.info('Pre-sync time is: %s' % time.asctime(TimeCheck()))
 
184
    
 
185
    sync = SyncTime(options.server)
 
186
 
 
187
    logging.info('Current system time is: %s' % time.asctime(TimeCheck()))
 
188
 
 
189
    # Restart ntp daemon
 
190
    if ntpd_status[0] == 'on':
 
191
        logging.debug('Since ntpd was previously running, starting it again')
 
192
        StartStopNTPD('on')
 
193
 
 
194
    if sync is True:
 
195
        return 0
 
196
    else:
 
197
        return 1
 
198
 
 
199
if __name__ == '__main__':
 
200
    sys.exit(main())