-
Notifications
You must be signed in to change notification settings - Fork 4
/
import2nfs.py
executable file
·162 lines (134 loc) · 5.26 KB
/
import2nfs.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#!/usr/bin/env python
import os
import re
import subprocess
BASE_DIR = os.path.dirname((os.path.abspath(__file__)))
# avocado logs path
LOGS_DIR = '%s/test_logs/' % BASE_DIR
# nfs server
NFS = {'bos': 'xxxx',
'pek': 'xxxx'
}
# log url
LOG_URL = 'xxxx'
# mounting directory name
DIR_NAME = 'LOG'
# absolute mount path is the /tmp
MOUNT_DIR = os.path.join('/tmp', DIR_NAME)
def system_status_output(cmd):
"""Run a subprocess, returning its exit code and output."""
sp = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
stdout, stderr = sp.communicate()
return sp.poll(), stdout.decode()
def system_output(cmd):
"""Run a subprocess, returning its output."""
return system_status_output(cmd)[1]
def get_avg_rtt(host):
"""
Get average around trip time of the given host.
:param host: Host name or ip address.
"""
cmd_out = system_output("ping %s -c 5" % host)
result = re.search(r"rtt min/avg.*?/([\d\.]+)", cmd_out)
if not result:
return float('+inf')
return float(result.group(1))
def _get_default_nfs():
"""Choosing the fast nfs based on the avg rtt."""
nfs_rtt = {}
for k in list(NFS.keys()):
nfs_rtt[k] = get_avg_rtt(NFS[k].split(':')[0])
return min(nfs_rtt, key=nfs_rtt.get)
def _get_job_id():
"""Try to get the machine's job id, return None if id is not available."""
try:
# machines that run the beaker task successfully should have
# this file containing job_id.
with open(os.path.join('/home', 'job_env.txt')) as f:
job_id = f.read().strip()
except IOError:
job_id = None
return job_id
def _print_log_url(target, path):
"""Assemble log url and print it out."""
# target in url means targeted nfs
query_params = 'target=%s&path=%s' % (target, path)
url = '?'.join([LOG_URL, query_params])
print('logs available at: %s' % url)
def create_mount_dir(directory=MOUNT_DIR):
"""Create a mount point for the nfs."""
if os.path.exists(directory):
print('directory: %s exists, mkdir skiped.' % directory)
else:
os.makedirs(directory)
print('%s is successfully created.' % directory)
def mount_nfs(source, target=MOUNT_DIR):
"""Mount the given nfs to the mount point."""
if os.path.ismount(target):
subprocess.check_call(['umount', '-v', target])
subprocess.check_call(['mount', source, target])
print('successfully mounted %s to %s' % (source, target))
def import_log(source, target, force=False, builtin_nfs=None):
"""Import test logs from source to target."""
log_source = os.path.join(LOGS_DIR, source)
log_dest = os.path.join(MOUNT_DIR, target)
if not os.path.exists(log_dest):
os.makedirs(log_dest)
print('copying %s to %s , this may take a while.' % (log_source, log_dest))
realpath = os.path.realpath(log_source)
if force:
# --force, ignore existent files
subprocess.check_call(['cp', '-RT', realpath, log_dest])
else:
# by default it will not overwrite existent files
subprocess.check_call(['cp', '-RTn', realpath, log_dest])
if builtin_nfs:
_print_log_url(builtin_nfs, target)
print('\nimport done!')
if __name__ == '__main__':
import argparse
# default log source.
source_dir = 'latest'
# default log dest will be the beaker job id
# if job id is not available or a -d is provide
# it will under imported-logs
dest_dir = _get_job_id() if _get_job_id() else 'imported-logs'
# nfs
print('pinging built-in NFSs, please be patient')
default_nfs = _get_default_nfs()
parser = argparse.ArgumentParser(description='import the test \
results to a NFS')
parser.add_argument("-s", "--source",
help="log source directory, "
"by default it uses %s" % source_dir,
default=source_dir,
action="store")
parser.add_argument("-d", "--dest",
help="log destination directory, "
"if you want to create nested directories, "
"use dir1/dri2/dir3 ... "
"by default it uses %s" % dest_dir,
default=dest_dir,
action="store")
parser.add_argument("-n", "--nfs",
help="choose the nfs from [bos, pek] or "
"provide your nfs source, "
"by default it uses %s" % default_nfs,
default=default_nfs,
action="store")
parser.add_argument("-f", "--force",
help="ignore existent files, force to copy",
action="store_true")
args = parser.parse_args()
# validate source
if args.source not in os.listdir(LOGS_DIR):
parser.error('%s is an invalid source.' % args.source)
# validate dest, removing leading and trailing slashes
args.dest = args.dest.strip('/')
create_mount_dir()
if args.nfs in list(NFS.keys()):
mount_nfs(NFS[args.nfs])
import_log(args.source, args.dest, args.force, args.nfs)
else:
mount_nfs(args.nfs)
import_log(args.source, args.dest, args.force)