385.1.1
by Aaron Bentley
Support upgrades. |
1 |
from contextlib import contextmanager |
777.1.1
by Aaron Bentley
Move find_candidates, get under test. |
2 |
from datetime import ( |
3 |
datetime, |
|
4 |
timedelta, |
|
5 |
)
|
|
379.1.1
by Aaron Bentley
Move portions of deploy job to Python. |
6 |
import errno |
1071.1.1
by Aaron Bentley
Implement find_latest_branch_candidates. |
7 |
import json |
751.2.1
by Aaron Bentley
Use timestamped logs. |
8 |
import logging |
385.1.1
by Aaron Bentley
Support upgrades. |
9 |
import os |
663.1.2
by Aaron Bentley
Port bootstrap_from_env to EnvJujuClient, add unit tests. |
10 |
import re |
11 |
import subprocess |
|
379.1.1
by Aaron Bentley
Move portions of deploy job to Python. |
12 |
import socket |
386.1.8
by Aaron Bentley
Add missing dependency. |
13 |
import sys |
777.1.1
by Aaron Bentley
Move find_candidates, get under test. |
14 |
from time import ( |
15 |
sleep, |
|
16 |
time, |
|
17 |
)
|
|
1354.1.1
by Martin Packman
Sane warnings from _clean_dir helper for common arg parsing |
18 |
import warnings |
1889.2.2
by Aaron Bentley
Extract jujupy.utility from utility. |
19 |
from jujupy.utility import ( |
20 |
ensure_deleted, |
|
21 |
ensure_dir, |
|
22 |
get_timeout_path, |
|
23 |
is_ipv6_address, |
|
24 |
print_now, |
|
25 |
qualified_model_name, |
|
26 |
quote, |
|
27 |
scoped_environ, |
|
28 |
skip_on_missing_file, |
|
29 |
temp_dir, |
|
30 |
temp_yaml_file, |
|
31 |
until_timeout
|
|
32 |
)
|
|
994.3.1
by Martin Packman
Make Remote an abstract class and implement winrm based version |
33 |
|
1889.2.2
by Aaron Bentley
Extract jujupy.utility from utility. |
34 |
# Imported for other call sites to use.
|
35 |
__all__ = [ |
|
36 |
'ensure_deleted', |
|
37 |
'ensure_dir', |
|
38 |
'get_timeout_path', |
|
39 |
'qualified_model_name', |
|
40 |
'quote', |
|
41 |
'scoped_environ', |
|
42 |
'skip_on_missing_file', |
|
43 |
'temp_dir', |
|
44 |
'temp_yaml_file', |
|
45 |
]
|
|
1409.1.5
by Martin
Lint on transitional import in utility |
46 |
|
385.1.1
by Aaron Bentley
Support upgrades. |
47 |
|
1167.2.1
by Martin Packman
Support IPv6 in wait_for_port and move handling of literal addresses closer to final use |
48 |
# Equivalent of socket.EAI_NODATA when using windows sockets
|
49 |
# <https://msdn.microsoft.com/ms740668#WSANO_DATA>
|
|
50 |
WSANO_DATA = 11004 |
|
1873.6.6
by Nicholas Skaggs
revert 1878 |
51 |
|
1167.2.1
by Martin Packman
Support IPv6 in wait_for_port and move handling of literal addresses closer to final use |
52 |
|
385.1.1
by Aaron Bentley
Support upgrades. |
53 |
@contextmanager
|
1575.1.7
by Aaron Bentley
Add timeout handling to wait_for_model. |
54 |
def noop_context(): |
55 |
"""A context manager that does nothing."""
|
|
56 |
yield
|
|
57 |
||
58 |
||
457
by Aaron Bentley
Don't raise an exception when logs cannot be dumped. |
59 |
class PortTimeoutError(Exception): |
60 |
pass
|
|
61 |
||
62 |
||
1211.2.4
by Aaron Bentley
Move LoggedException to utility. |
63 |
class LoggedException(BaseException): |
64 |
"""Raised in place of an exception that has already been logged.
|
|
65 |
||
66 |
This is a wrapper to avoid double-printing real Exceptions while still
|
|
67 |
unwinding the stack appropriately.
|
|
68 |
"""
|
|
69 |
def __init__(self, exception): |
|
70 |
self.exception = exception |
|
71 |
||
72 |
||
1410.1.1
by Seman
Added CI test for deploying a charm with resources. |
73 |
class JujuAssertionError(AssertionError): |
74 |
"""Exception for juju assertion failures."""
|
|
75 |
||
76 |
||
1303.1.2
by Martin Packman
Warn if log_dir has pre-existing contents |
77 |
def _clean_dir(maybe_dir): |
78 |
"""Pseudo-type that validates an argument to be a clean directory path.
|
|
79 |
||
80 |
For safety, this function will not attempt to remove existing directory
|
|
81 |
contents but will just report a warning.
|
|
82 |
"""
|
|
83 |
try: |
|
84 |
contents = os.listdir(maybe_dir) |
|
85 |
except OSError as e: |
|
1449.4.1
by Nicholas Skaggs
modify utility to allow for positional arguments to be optional, with sane defaults. fixes bug #1587925 |
86 |
if e.errno == errno.ENOENT: |
1449.4.14
by Nicholas Skaggs
add docstring and comment |
87 |
# we don't raise this error due to tests abusing /tmp/logs
|
1449.4.17
by Nicholas Skaggs
update old-school string formatting to new |
88 |
warnings.warn('Not a directory {}'.format(maybe_dir)) |
1449.4.13
by Nicholas Skaggs
add _generate_default_binary, update tests, deal with /tmp/logs issue |
89 |
if e.errno == errno.EEXIST: |
1449.4.17
by Nicholas Skaggs
update old-school string formatting to new |
90 |
warnings.warn('Directory {} already exists'.format(maybe_dir)) |
1303.1.2
by Martin Packman
Warn if log_dir has pre-existing contents |
91 |
else: |
1354.1.1
by Martin Packman
Sane warnings from _clean_dir helper for common arg parsing |
92 |
if contents and contents != ["empty"]: |
1449.4.17
by Nicholas Skaggs
update old-school string formatting to new |
93 |
warnings.warn( |
1449.4.18
by Nicholas Skaggs
restore repr expression |
94 |
'Directory {!r} has existing contents.'.format(maybe_dir)) |
1303.1.2
by Martin Packman
Warn if log_dir has pre-existing contents |
95 |
return maybe_dir |
96 |
||
97 |
||
1167.2.1
by Martin Packman
Support IPv6 in wait_for_port and move handling of literal addresses closer to final use |
98 |
def as_literal_address(address): |
99 |
"""Returns address in form suitable for embedding in URL or similar.
|
|
100 |
||
101 |
In practice, this just puts square brackets round IPv6 addresses which
|
|
102 |
avoids conflict with port seperators and other uses of colons.
|
|
103 |
"""
|
|
104 |
if is_ipv6_address(address): |
|
105 |
return address.join("[]") |
|
106 |
return address |
|
107 |
||
108 |
||
379.1.1
by Aaron Bentley
Move portions of deploy job to Python. |
109 |
def wait_for_port(host, port, closed=False, timeout=30): |
1167.2.1
by Martin Packman
Support IPv6 in wait_for_port and move handling of literal addresses closer to final use |
110 |
family = socket.AF_INET6 if is_ipv6_address(host) else socket.AF_INET |
379.1.1
by Aaron Bentley
Move portions of deploy job to Python. |
111 |
for remaining in until_timeout(timeout): |
808.2.12
by Aaron Bentley
Handle 'No address associated with hostname'. |
112 |
try: |
1167.2.1
by Martin Packman
Support IPv6 in wait_for_port and move handling of literal addresses closer to final use |
113 |
addrinfo = socket.getaddrinfo(host, port, family, |
808.2.12
by Aaron Bentley
Handle 'No address associated with hostname'. |
114 |
socket.SOCK_STREAM) |
115 |
except socket.error as e: |
|
1167.2.1
by Martin Packman
Support IPv6 in wait_for_port and move handling of literal addresses closer to final use |
116 |
if e.errno not in (socket.EAI_NODATA, WSANO_DATA): |
808.2.12
by Aaron Bentley
Handle 'No address associated with hostname'. |
117 |
raise
|
118 |
if closed: |
|
119 |
return
|
|
120 |
else: |
|
121 |
continue
|
|
808.2.5
by Aaron Bentley
Treat 0.0.0.0 address as a closed port. |
122 |
sockaddr = addrinfo[0][4] |
123 |
# Treat Azure messed-up address lookup as a closed port.
|
|
124 |
if sockaddr[0] == '0.0.0.0': |
|
125 |
if closed: |
|
126 |
return
|
|
127 |
else: |
|
128 |
continue
|
|
129 |
conn = socket.socket(*addrinfo[0][:3]) |
|
1771.1.5
by Seman Said
Updated after a code review. |
130 |
conn.settimeout(max(remaining or 0, 5)) |
379.1.1
by Aaron Bentley
Move portions of deploy job to Python. |
131 |
try: |
808.2.5
by Aaron Bentley
Treat 0.0.0.0 address as a closed port. |
132 |
conn.connect(sockaddr) |
379.1.1
by Aaron Bentley
Move portions of deploy job to Python. |
133 |
except socket.timeout: |
134 |
if closed: |
|
135 |
return
|
|
136 |
except socket.error as e: |
|
1167.2.2
by Martin Packman
Expect ENETUNREACH as a posible socket connection error in wait_for_port |
137 |
if e.errno not in (errno.ECONNREFUSED, errno.ENETUNREACH, |
1296
by Curtis Hovey
errno.EHOSTUNREACH is evidence that the port is closed; the host is deleted. |
138 |
errno.ETIMEDOUT, errno.EHOSTUNREACH): |
379.1.1
by Aaron Bentley
Move portions of deploy job to Python. |
139 |
raise
|
140 |
if closed: |
|
141 |
return
|
|
787
by Curtis Hovey
Do not swallow errors retrieving logs. |
142 |
except socket.gaierror as e: |
143 |
print_now(str(e)) |
|
379.1.1
by Aaron Bentley
Move portions of deploy job to Python. |
144 |
except Exception as e: |
1449.4.17
by Nicholas Skaggs
update old-school string formatting to new |
145 |
print_now('Unexpected {!r}: {}'.format((type(e), e))) |
379.1.1
by Aaron Bentley
Move portions of deploy job to Python. |
146 |
raise
|
147 |
else: |
|
148 |
conn.close() |
|
149 |
if not closed: |
|
150 |
return
|
|
151 |
sleep(1) |
|
457
by Aaron Bentley
Don't raise an exception when logs cannot be dumped. |
152 |
raise PortTimeoutError('Timed out waiting for port.') |
379.1.1
by Aaron Bentley
Move portions of deploy job to Python. |
153 |
|
154 |
||
621.1.1
by Abel Deuring
new helper function to find successful build for a given build_revision; build_vagrant_boxes.py uses this function. |
155 |
def get_revision_build(build_info): |
156 |
for action in build_info['actions']: |
|
157 |
if 'parameters' in action: |
|
158 |
for parameter in action['parameters']: |
|
159 |
if parameter['name'] == 'revision_build': |
|
160 |
return parameter['value'] |
|
161 |
||
162 |
||
163 |
def builds_for_revision(job, revision_build, jenkins): |
|
164 |
"""Return the build_info data for the given job and revision_build.
|
|
165 |
||
166 |
Only successful builds are included.
|
|
167 |
||
168 |
:param job: The name of the job.
|
|
621.1.2
by Abel Deuring
typo fixed |
169 |
:param revision_build: The revision_build to searh for. Note that
|
621.1.1
by Abel Deuring
new helper function to find successful build for a given build_revision; build_vagrant_boxes.py uses this function. |
170 |
this parameter is a string.
|
171 |
:parameter jenkins: A Jenkins instance.
|
|
172 |
"""
|
|
173 |
job_info = jenkins.get_job_info(job) |
|
174 |
result = [] |
|
175 |
for build in job_info['builds']: |
|
176 |
build_info = jenkins.get_build_info(job, build['number']) |
|
177 |
if (get_revision_build(build_info) == revision_build and |
|
706.1.1
by Aaron Bentley
Switch to flake8 and fix lint. |
178 |
build_info['result'] == 'SUCCESS'): |
621.1.1
by Abel Deuring
new helper function to find successful build for a given build_revision; build_vagrant_boxes.py uses this function. |
179 |
result.append(build_info) |
180 |
return result |
|
663.1.2
by Aaron Bentley
Port bootstrap_from_env to EnvJujuClient, add unit tests. |
181 |
|
182 |
||
994.3.1
by Martin Packman
Make Remote an abstract class and implement winrm based version |
183 |
def get_winrm_certs(): |
184 |
""""Returns locations of key and cert files for winrm in cloud-city."""
|
|
185 |
home = os.environ['HOME'] |
|
186 |
return ( |
|
187 |
os.path.join(home, 'cloud-city/winrm_client_cert.key'), |
|
188 |
os.path.join(home, 'cloud-city/winrm_client_cert.pem'), |
|
189 |
)
|
|
190 |
||
191 |
||
683.1.1
by Abel Deuring
function s3_cmd moved from backup-to-s3.py to utility.py |
192 |
def s3_cmd(params, drop_output=False): |
193 |
s3cfg_path = os.path.join( |
|
194 |
os.environ['HOME'], 'cloud-city/juju-qa.s3cfg') |
|
683.1.3
by Abel Deuring
If two result files exist for one revision, use the timestamp of the older file but the data from the newer file. |
195 |
command = ['s3cmd', '-c', s3cfg_path, '--no-progress'] + params |
683.1.1
by Abel Deuring
function s3_cmd moved from backup-to-s3.py to utility.py |
196 |
if drop_output: |
197 |
return subprocess.check_call( |
|
683.1.3
by Abel Deuring
If two result files exist for one revision, use the timestamp of the older file but the data from the newer file. |
198 |
command, stdout=open('/dev/null', 'w')) |
683.1.1
by Abel Deuring
function s3_cmd moved from backup-to-s3.py to utility.py |
199 |
else: |
683.1.3
by Abel Deuring
If two result files exist for one revision, use the timestamp of the older file but the data from the newer file. |
200 |
return subprocess.check_output(command) |
751.2.1
by Aaron Bentley
Use timestamped logs. |
201 |
|
1449.4.3
by Nicholas Skaggs
flake8 |
202 |
|
1449.4.1
by Nicholas Skaggs
modify utility to allow for positional arguments to be optional, with sane defaults. fixes bug #1587925 |
203 |
def _get_test_name_from_filename(): |
1449.4.5
by Nicholas Skaggs
make env optional too |
204 |
try: |
205 |
calling_file = sys._getframe(2).f_back.f_globals['__file__'] |
|
206 |
return os.path.splitext(os.path.basename(calling_file))[0] |
|
207 |
except: |
|
208 |
return 'unknown_test' |
|
1449.4.1
by Nicholas Skaggs
modify utility to allow for positional arguments to be optional, with sane defaults. fixes bug #1587925 |
209 |
|
1873.6.10
by Nicholas Skaggs
lint |
210 |
|
1873.6.12
by Nicholas Skaggs
make _generate_default_clean_dir public |
211 |
def generate_default_clean_dir(temp_env_name): |
1873.6.8
by Nicholas Skaggs
wip |
212 |
"""Creates a new unique directory for logging and returns name"""
|
213 |
logging.debug('Environment {}'.format(temp_env_name)) |
|
214 |
test_name = temp_env_name.split('-')[0] |
|
215 |
timestamp = datetime.now().strftime("%Y%m%d%H%M%S") |
|
216 |
log_dir = os.path.join('/tmp', test_name, 'logs', timestamp) |
|
217 |
||
218 |
try: |
|
219 |
os.makedirs(log_dir) |
|
220 |
logging.info('Created logging directory {}'.format(log_dir)) |
|
221 |
except OSError as e: |
|
222 |
if e.errno == errno.EEXIST: |
|
223 |
logging.warn('"Directory {} already exists'.format(log_dir)) |
|
224 |
else: |
|
225 |
raise('Failed to create logging directory: {} ' + |
|
226 |
log_dir + |
|
227 |
'. Please specify empty folder or try again') |
|
228 |
return log_dir |
|
1449.4.3
by Nicholas Skaggs
flake8 |
229 |
|
1873.6.10
by Nicholas Skaggs
lint |
230 |
|
1449.4.24
by Nicholas Skaggs
move directory creation to bootstrap manager |
231 |
def _generate_default_temp_env_name(): |
1449.4.1
by Nicholas Skaggs
modify utility to allow for positional arguments to be optional, with sane defaults. fixes bug #1587925 |
232 |
"""Creates a new unique name for environment and returns the name"""
|
1449.4.20
by Nicholas Skaggs
fix for bug #1601987 |
233 |
# we need to sanitize the name
|
1449.4.24
by Nicholas Skaggs
move directory creation to bootstrap manager |
234 |
timestamp = datetime.now().strftime("%Y%m%d%H%M%S") |
1449.4.20
by Nicholas Skaggs
fix for bug #1601987 |
235 |
test_name = re.sub('[^a-zA-Z]', '', _get_test_name_from_filename()) |
236 |
return '{}-{}-temp-env'.format(test_name, timestamp) |
|
751.2.1
by Aaron Bentley
Use timestamped logs. |
237 |
|
1449.4.3
by Nicholas Skaggs
flake8 |
238 |
|
1575.2.1
by Aaron Bentley
Shove dealine from arg down to client_from_config. |
239 |
def _to_deadline(timeout): |
240 |
return datetime.utcnow() + timedelta(seconds=int(timeout)) |
|
241 |
||
242 |
||
1711.6.4
by Aaron Bentley
Initial assess_add_cloud test. |
243 |
def add_arg_juju_bin(parser): |
244 |
parser.add_argument('juju_bin', nargs='?', |
|
245 |
help='Full path to the Juju binary. By default, this' |
|
1873.6.7
by Nicholas Skaggs
wip |
246 |
' will use $PATH/juju', |
247 |
default=None) |
|
1711.6.4
by Aaron Bentley
Initial assess_add_cloud test. |
248 |
|
249 |
||
1745.2.3
by Aaron Bentley
Allow env to be omitted. |
250 |
def add_basic_testing_arguments(parser, using_jes=False, deadline=True, |
251 |
env=True): |
|
1028.2.7
by Curtis Hovey
Added docstrings. |
252 |
"""Returns the parser loaded with basic testing arguments.
|
253 |
||
254 |
The basic testing arguments, used in conjuction with boot_context ensures
|
|
255 |
a test can be run in any supported substrate in parallel.
|
|
256 |
||
1449.4.5
by Nicholas Skaggs
make env optional too |
257 |
This helper adds 4 positional arguments that defines the minimum needed
|
258 |
to run a test script.
|
|
1449.4.1
by Nicholas Skaggs
modify utility to allow for positional arguments to be optional, with sane defaults. fixes bug #1587925 |
259 |
|
1449.4.5
by Nicholas Skaggs
make env optional too |
260 |
These arguments (env, juju_bin, logs, temp_env_name) allow you to specify
|
261 |
specifics for which env, juju binary, which folder for logging and an
|
|
1449.4.1
by Nicholas Skaggs
modify utility to allow for positional arguments to be optional, with sane defaults. fixes bug #1587925 |
262 |
environment name for your test respectively.
|
1028.2.7
by Curtis Hovey
Added docstrings. |
263 |
|
264 |
There are many optional args that either update the env's config or
|
|
265 |
manipulate the juju command line options to test in controlled situations
|
|
266 |
or in uncommon substrates: --debug, --verbose, --agent-url, --agent-stream,
|
|
995.1.18
by Martin Packman
Add using_jes flag to add_basic_testing_arguments |
267 |
--series, --bootstrap-host, --machine, --keep-env. If not using_jes, the
|
268 |
--upload-tools arg will also be added.
|
|
1028.2.7
by Curtis Hovey
Added docstrings. |
269 |
|
270 |
:param parser: an ArgumentParser.
|
|
995.1.18
by Martin Packman
Add using_jes flag to add_basic_testing_arguments |
271 |
:param using_jes: whether args should be tailored for JES testing.
|
1575.3.5
by Aaron Bentley
Fix help text. |
272 |
:param deadline: If true, support the --timeout option and convert to a
|
273 |
deadline.
|
|
1028.2.7
by Curtis Hovey
Added docstrings. |
274 |
"""
|
1449.4.5
by Nicholas Skaggs
make env optional too |
275 |
|
276 |
# Optional postional arguments
|
|
1745.2.3
by Aaron Bentley
Allow env to be omitted. |
277 |
if env: |
278 |
parser.add_argument( |
|
279 |
'env', nargs='?', |
|
280 |
help='The juju environment to base the temp test environment on.', |
|
281 |
default='lxd') |
|
1711.6.4
by Aaron Bentley
Initial assess_add_cloud test. |
282 |
add_arg_juju_bin(parser) |
1549.1.1
by Curtis Hovey
Removed get_toekn; all jobs require authentication anyway. |
283 |
parser.add_argument('logs', nargs='?', type=_clean_dir, |
1449.4.15
by Nicholas Skaggs
clarify defaults in help, remove try catch block, switch default logging dir name |
284 |
help='A directory in which to store logs. By default,' |
1449.4.23
by Nicholas Skaggs
remove directory creation as part of arg parsing. By default if nothing is specified, we will us the current directory |
285 |
' this will use the current directory', |
1449.4.24
by Nicholas Skaggs
move directory creation to bootstrap manager |
286 |
default=None) |
1449.4.1
by Nicholas Skaggs
modify utility to allow for positional arguments to be optional, with sane defaults. fixes bug #1587925 |
287 |
parser.add_argument('temp_env_name', nargs='?', |
1449.4.15
by Nicholas Skaggs
clarify defaults in help, remove try catch block, switch default logging dir name |
288 |
help='A temporary test environment name. By default, ' |
289 |
' this will generate an enviroment name using the '
|
|
290 |
' timestamp and testname. '
|
|
291 |
' test_name_timestamp_temp_env', |
|
1449.4.24
by Nicholas Skaggs
move directory creation to bootstrap manager |
292 |
default=_generate_default_temp_env_name()) |
1449.4.1
by Nicholas Skaggs
modify utility to allow for positional arguments to be optional, with sane defaults. fixes bug #1587925 |
293 |
|
1303.1.1
by Martin Packman
Unroll common positional args in helper |
294 |
# Optional keyword arguments.
|
995.1.18
by Martin Packman
Add using_jes flag to add_basic_testing_arguments |
295 |
parser.add_argument('--debug', action='store_true', |
906.2.1
by John George
Added the add_basic_testing_arguments function for setting up arguments needed for quickstart, deployer and charmstore tests. |
296 |
help='Pass --debug to Juju.') |
297 |
parser.add_argument('--verbose', action='store_const', |
|
908.2.1
by John George
Re-write quickstart_deploy.py to use EnvJujuClient. |
298 |
default=logging.INFO, const=logging.DEBUG, |
906.2.1
by John George
Added the add_basic_testing_arguments function for setting up arguments needed for quickstart, deployer and charmstore tests. |
299 |
help='Verbose test harness output.') |
1793.4.3
by viswesn
Updated specific to code review comments. |
300 |
parser.add_argument('--region', help='Override environment region.') |
1912.3.1
by Curtis Hovey
Move --to from assess_bootstrap to add_basic_testing_arguments. |
301 |
parser.add_argument('--to', default=None, |
302 |
help='Place the controller at a location.') |
|
1024.1.2
by Curtis Hovey
Added --agent-stream to add_basic_testing_arguments. |
303 |
parser.add_argument('--agent-url', action='store', default=None, |
304 |
help='URL for retrieving agent binaries.') |
|
305 |
parser.add_argument('--agent-stream', action='store', default=None, |
|
1120.3.3
by Aaron Bentley
Fix help |
306 |
help='Stream for retrieving agent binaries.') |
1793.4.3
by viswesn
Updated specific to code review comments. |
307 |
parser.add_argument('--series', action='store', default=None, |
1024.1.2
by Curtis Hovey
Added --agent-stream to add_basic_testing_arguments. |
308 |
help='Name of the Ubuntu series to use.') |
995.1.18
by Martin Packman
Add using_jes flag to add_basic_testing_arguments |
309 |
if not using_jes: |
310 |
parser.add_argument('--upload-tools', action='store_true', |
|
311 |
help='upload local version of tools to bootstrap.') |
|
1024.1.3
by Curtis Hovey
Added arguments for manual env tests. |
312 |
parser.add_argument('--bootstrap-host', |
313 |
help='The host to use for bootstrap.') |
|
314 |
parser.add_argument('--machine', help='A machine to add or when used with ' |
|
315 |
'KVM based MaaS, a KVM image to start.', |
|
316 |
action='append', default=[]) |
|
995.1.18
by Martin Packman
Add using_jes flag to add_basic_testing_arguments |
317 |
parser.add_argument('--keep-env', action='store_true', |
1024.1.3
by Curtis Hovey
Added arguments for manual env tests. |
318 |
help='Keep the Juju environment after the test' |
319 |
' completes.') |
|
1575.2.2
by Aaron Bentley
Fix special cases where deadline may be ignored. |
320 |
if deadline: |
1575.2.12
by Aaron Bentley
Add --timeout help. |
321 |
parser.add_argument('--timeout', dest='deadline', type=_to_deadline, |
322 |
help="The script timeout, in seconds.") |
|
906.2.1
by John George
Added the add_basic_testing_arguments function for setting up arguments needed for quickstart, deployer and charmstore tests. |
323 |
return parser |
324 |
||
325 |
||
1315.2.23
by Aaron Bentley
Introduce set_model_name, update tests, check controller on bootstrap. |
326 |
# suppress nosetests
|
327 |
add_basic_testing_arguments.__test__ = False |
|
328 |
||
329 |
||
751.2.1
by Aaron Bentley
Use timestamped logs. |
330 |
def configure_logging(log_level): |
331 |
logging.basicConfig( |
|
332 |
level=log_level, format='%(asctime)s %(levelname)s %(message)s', |
|
333 |
datefmt='%Y-%m-%d %H:%M:%S') |
|
777.1.1
by Aaron Bentley
Move find_candidates, get under test. |
334 |
|
335 |
||
336 |
def get_candidates_path(root_dir): |
|
337 |
return os.path.join(root_dir, 'candidate') |
|
338 |
||
339 |
||
1091.4.1
by James Tunnicliffe
Merged upstream |
340 |
# GZ 2015-10-15: Paths returned in filesystem dependent order, may want sort?
|
1029.1.1
by seman.said at canonical
Added --all option to schedule all candidates for client-server testing. |
341 |
def find_candidates(root_dir, find_all=False): |
1071.1.1
by Aaron Bentley
Implement find_latest_branch_candidates. |
342 |
return (path for path, buildvars in _find_candidates(root_dir, find_all)) |
343 |
||
344 |
||
345 |
def find_latest_branch_candidates(root_dir): |
|
346 |
"""Return a list of one candidate per branch.
|
|
347 |
||
348 |
:param root_dir: The root directory to find candidates from.
|
|
349 |
"""
|
|
350 |
candidates = [] |
|
1367.1.1
by Aaron Bentley
Switch schedule_reliability_tests to use artifacts dirs and omit path. |
351 |
for path, buildvars_path in _find_candidates(root_dir, find_all=False, |
352 |
artifacts=True): |
|
1071.1.1
by Aaron Bentley
Implement find_latest_branch_candidates. |
353 |
with open(buildvars_path) as buildvars_file: |
354 |
buildvars = json.load(buildvars_file) |
|
355 |
candidates.append( |
|
356 |
(buildvars['branch'], int(buildvars['revision_build']), path)) |
|
1302.1.1
by Aaron Bentley
Include revision_build in industrial-test job params. |
357 |
latest = dict( |
358 |
(branch, (path, build)) for branch, build, path in sorted(candidates)) |
|
1071.1.1
by Aaron Bentley
Implement find_latest_branch_candidates. |
359 |
return latest.values() |
360 |
||
361 |
||
1367.1.1
by Aaron Bentley
Switch schedule_reliability_tests to use artifacts dirs and omit path. |
362 |
def _find_candidates(root_dir, find_all=False, artifacts=False): |
777.1.1
by Aaron Bentley
Move find_candidates, get under test. |
363 |
candidates_path = get_candidates_path(root_dir) |
364 |
a_week_ago = time() - timedelta(days=7).total_seconds() |
|
365 |
for candidate_dir in os.listdir(candidates_path): |
|
1367.1.1
by Aaron Bentley
Switch schedule_reliability_tests to use artifacts dirs and omit path. |
366 |
if candidate_dir.endswith('-artifacts') != artifacts: |
777.1.1
by Aaron Bentley
Move find_candidates, get under test. |
367 |
continue
|
368 |
candidate_path = os.path.join(candidates_path, candidate_dir) |
|
369 |
buildvars = os.path.join(candidate_path, 'buildvars.json') |
|
370 |
try: |
|
371 |
stat = os.stat(buildvars) |
|
372 |
except OSError as e: |
|
373 |
if e.errno in (errno.ENOENT, errno.ENOTDIR): |
|
374 |
continue
|
|
375 |
raise
|
|
1029.1.1
by seman.said at canonical
Added --all option to schedule all candidates for client-server testing. |
376 |
if not find_all and stat.st_mtime < a_week_ago: |
777.1.1
by Aaron Bentley
Move find_candidates, get under test. |
377 |
continue
|
1071.1.1
by Aaron Bentley
Implement find_latest_branch_candidates. |
378 |
yield candidate_path, buildvars |
889.6.1
by Aaron Bentley
Make utility for determining architecture. |
379 |
|
380 |
||
381 |
def get_deb_arch(): |
|
382 |
"""Get the debian machine architecture."""
|
|
383 |
return subprocess.check_output(['dpkg', '--print-architecture']).strip() |
|
889.6.6
by Aaron Bentley
Extract extract_deb. |
384 |
|
385 |
||
386 |
def extract_deb(package_path, directory): |
|
387 |
"""Extract a debian package to a specified directory."""
|
|
388 |
subprocess.check_call(['dpkg', '-x', package_path, directory]) |
|
1001.1.1
by John George
Add openstack_basic_check.py |
389 |
|
390 |
||
391 |
def run_command(command, dry_run=False, verbose=False): |
|
392 |
"""Optionally execute a command and maybe print the output."""
|
|
393 |
if verbose: |
|
394 |
print_now('Executing: {}'.format(command)) |
|
395 |
if not dry_run: |
|
396 |
output = subprocess.check_output(command) |
|
397 |
if verbose: |
|
398 |
print_now(output) |
|
1426.1.7
by Leo Zhang
updates after review |
399 |
|
400 |
||
1718.2.9
by Christopher Lee
Move get_ip_address to utility.py |
401 |
def get_unit_ipaddress(client, unit_name): |
402 |
status = client.get_status() |
|
403 |
return status.get_unit(unit_name)['public-address'] |
|
1735.1.1
by Martin Packman
New utility.logged_exception factored out from deploy_stack |
404 |
|
405 |
||
406 |
def log_and_wrap_exception(logger, exc): |
|
1738.1.1
by Andrew Beach
Pollished the new logged_exception function just a bit. |
407 |
"""Record exc details to logger and return wrapped in LoggedException."""
|
1735.1.1
by Martin Packman
New utility.logged_exception factored out from deploy_stack |
408 |
logger.exception(exc) |
409 |
stdout = getattr(exc, 'output', None) |
|
410 |
stderr = getattr(exc, 'stderr', None) |
|
411 |
if stdout or stderr: |
|
1738.1.1
by Andrew Beach
Pollished the new logged_exception function just a bit. |
412 |
logger.info('Output from exception:\nstdout:\n%s\nstderr:\n%s', |
413 |
stdout, stderr) |
|
1735.1.1
by Martin Packman
New utility.logged_exception factored out from deploy_stack |
414 |
return LoggedException(exc) |
415 |
||
416 |
||
417 |
@contextmanager
|
|
418 |
def logged_exception(logger): |
|
1738.1.1
by Andrew Beach
Pollished the new logged_exception function just a bit. |
419 |
"""\
|
1735.1.1
by Martin Packman
New utility.logged_exception factored out from deploy_stack |
420 |
Record exceptions in managed context to logger and reraise LoggedException.
|
421 |
||
1738.1.1
by Andrew Beach
Pollished the new logged_exception function just a bit. |
422 |
Note that BaseException classes like SystemExit, GeneratorExit and
|
423 |
LoggedException itself are not wrapped, except for KeyboardInterrupt.
|
|
1735.1.1
by Martin Packman
New utility.logged_exception factored out from deploy_stack |
424 |
"""
|
425 |
try: |
|
426 |
yield
|
|
1735.1.2
by Martin Packman
Also wrap KeyboardInterrupt as SIGINT is used for timeout |
427 |
except (Exception, KeyboardInterrupt) as e: |
1735.1.1
by Martin Packman
New utility.logged_exception factored out from deploy_stack |
428 |
raise log_and_wrap_exception(logger, e) |