1 | #!/bin/env python |
---|
2 | |
---|
3 | '''Utility functions for the cluster acceptance test suite.''' |
---|
4 | |
---|
5 | import os |
---|
6 | import sys |
---|
7 | import time |
---|
8 | |
---|
9 | |
---|
10 | # information about each cluster. |
---|
11 | # 'node_stem' key defines a compute node name. |
---|
12 | # update this if adding a new cluster. |
---|
13 | # should get this from the machines_<cluster> file? |
---|
14 | Cluster_Info = {'cyclone': {'num_nodes': 23, |
---|
15 | 'node_stem': 'compute-1-%d', |
---|
16 | 'bad_nodes': [13, 22]}, |
---|
17 | # 13 bad - 'no route to host' |
---|
18 | # 22 bad - forgets password, can't find file |
---|
19 | 'tornado': {'num_nodes': 20, |
---|
20 | 'node_stem': 'compute-0-%d', |
---|
21 | 'bad_nodes': []} |
---|
22 | 'off_site': {'num_nodes': 1, |
---|
23 | 'node_stem': 'xyzzy-%d', |
---|
24 | 'bad_nodes': []} |
---|
25 | } |
---|
26 | |
---|
27 | |
---|
28 | def log(logfile, msg=''): |
---|
29 | '''Write a message to the log file.''' |
---|
30 | |
---|
31 | fd = open(logfile, 'a') |
---|
32 | fd.write(msg) |
---|
33 | fd.close() |
---|
34 | |
---|
35 | |
---|
36 | def log_nl(logfile, msg=''): |
---|
37 | '''Write a message to the log file, with a newline added.''' |
---|
38 | |
---|
39 | log(logfile, msg) |
---|
40 | log(logfile, '\n') |
---|
41 | |
---|
42 | |
---|
43 | def log_print(logfile, msg=''): |
---|
44 | '''Write a message to the log file and stdout. |
---|
45 | |
---|
46 | The message doesn't have a '\n' added to it. |
---|
47 | ''' |
---|
48 | |
---|
49 | log(logfile, msg) |
---|
50 | print msg, |
---|
51 | sys.stdout.flush() |
---|
52 | |
---|
53 | |
---|
54 | def log_print_nl(logfile, msg=''): |
---|
55 | '''Write a message to the log file and stdout, with a newline added. |
---|
56 | |
---|
57 | Appends '\n' to msg. |
---|
58 | ''' |
---|
59 | |
---|
60 | log_nl(logfile, msg) |
---|
61 | print msg |
---|
62 | sys.stdout.flush() |
---|
63 | |
---|
64 | |
---|
65 | def header(logfile, module, msg): |
---|
66 | '''Write testlet header to log and stdout.''' |
---|
67 | |
---|
68 | # current time |
---|
69 | time_now = time.strftime('%H:%M:%S %Y-%m-%d') |
---|
70 | |
---|
71 | log_print_nl(logfile, '#' * 80) |
---|
72 | log_print_nl(logfile, '# ' + time_now + ' - ' + msg) |
---|
73 | log_print_nl(logfile, '# Module: %s' % module) |
---|
74 | log_print_nl(logfile, '#' * 80) |
---|
75 | log_print_nl(logfile) |
---|
76 | |
---|
77 | |
---|
78 | def footer(logfile, start_time=None): |
---|
79 | '''Write testlet footer to log and stdout.''' |
---|
80 | |
---|
81 | if start_time: |
---|
82 | end_time = time.time() |
---|
83 | msg = 'Test took %.1f s' % (end_time - start_time) |
---|
84 | else: |
---|
85 | msg = 'Finished at %s' % time.ctime() |
---|
86 | |
---|
87 | log_nl(logfile) |
---|
88 | log_nl(logfile, '# ' + msg) |
---|
89 | log_print_nl(logfile) |
---|
90 | |
---|
91 | |
---|
92 | def get_hostname(): |
---|
93 | '''Return (<host>, <domain>) for machine. |
---|
94 | |
---|
95 | For example, on the GA cyclone main node, return ('cyclone', 'agso.gov.au'). |
---|
96 | ''' |
---|
97 | |
---|
98 | fd = os.popen('hostname') |
---|
99 | hostname = fd.read() |
---|
100 | fd.close() |
---|
101 | |
---|
102 | try: |
---|
103 | result = hostname.strip().split('.', 1) |
---|
104 | if len(result) < 2: |
---|
105 | result.append('') |
---|
106 | except: |
---|
107 | result = (hostname, '') |
---|
108 | |
---|
109 | return result |
---|
110 | |
---|
111 | |
---|
112 | def get_cluster_info(cluster): |
---|
113 | '''Get dictionary containing information for 'cluster'. |
---|
114 | |
---|
115 | If 'cluster' is not recognized, return None. |
---|
116 | ''' |
---|
117 | |
---|
118 | return Cluster_Info.get(cluster, None) |
---|
119 | |
---|
120 | |
---|
121 | def get_node_numbers(cluster, strip_bad_nodes=True): |
---|
122 | '''Get a list of node numbers for the cluster. |
---|
123 | |
---|
124 | If 'strip_bad_nodes' is True remove bad nodes from the result. |
---|
125 | ''' |
---|
126 | |
---|
127 | result = [] |
---|
128 | info = Cluster_Info[cluster] |
---|
129 | for n in xrange(info['num_nodes']): |
---|
130 | if strip_bad_nodes and n in info['bad_nodes']: |
---|
131 | continue |
---|
132 | result.append(n) |
---|
133 | |
---|
134 | return result |
---|
135 | |
---|
136 | |
---|