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