17
by Aaron Bentley
Split out jujupy library. |
1 |
#!/usr/bin/env python
|
162
by Curtis Hovey
Windows and py3 love. |
2 |
from __future__ import print_function |
17
by Aaron Bentley
Split out jujupy library. |
3 |
|
4 |
||
155.1.1
by Aaron Bentley
Support a local prefix and repository for deployment. |
5 |
from argparse import ArgumentParser |
1036.1.1
by John George
Correct variable name passed to background_chaos. |
6 |
from contextlib import ( |
7 |
contextmanager, |
|
8 |
nested, |
|
9 |
)
|
|
1449.4.24
by Nicholas Skaggs
move directory creation to bootstrap manager |
10 |
from datetime import ( |
11 |
datetime, |
|
12 |
)
|
|
13 |
||
14 |
import errno |
|
611.1.3
by Menno Smits
use glob() to simplify log dumping code |
15 |
import glob |
424.1.4
by Aaron Bentley
Implement bootstrapping with specific agent-version. |
16 |
import logging |
379.1.1
by Aaron Bentley
Move portions of deploy job to Python. |
17 |
import os |
365.1.3
by Aaron Bentley
Use a random token in dummy deploy. |
18 |
import random |
365.1.2
by Aaron Bentley
Remove trailing line feeds. |
19 |
import re |
365.1.3
by Aaron Bentley
Use a random token in dummy deploy. |
20 |
import string |
379.1.1
by Aaron Bentley
Move portions of deploy job to Python. |
21 |
import subprocess |
155.1.1
by Aaron Bentley
Support a local prefix and repository for deployment. |
22 |
import sys |
931.1.2
by Martin Packman
Retry check_token for desired result for 120 seconds in all cases |
23 |
import time |
881.1.1
by Seman Said
Added a test for juju run |
24 |
import json |
908.1.1
by seman.said at canonical
Added script to retain jenv file during a failure. |
25 |
import shutil |
155.1.1
by Aaron Bentley
Support a local prefix and repository for deployment. |
26 |
|
1014.2.5
by John George
deploy_dummy_stack with chaos. |
27 |
from chaos import background_chaos |
1515.2.1
by Martin Packman
Move fake_juju_client and related code into a new top level fakejuju file |
28 |
from fakejuju import ( |
29 |
FakeBackend, |
|
30 |
fake_juju_client, |
|
31 |
)
|
|
1409.1.1
by Martin
First pass at new jujucharm module. |
32 |
from jujucharm import ( |
33 |
local_charm_path, |
|
34 |
)
|
|
422.1.4
by Aaron Bentley
Fix import. |
35 |
from jujuconfig import ( |
36 |
get_jenv_path, |
|
424.1.4
by Aaron Bentley
Implement bootstrapping with specific agent-version. |
37 |
get_juju_home, |
717.2.2
by Aaron Bentley
Checkpoint with assess_recovery working. |
38 |
translate_to_env, |
422.1.4
by Aaron Bentley
Fix import. |
39 |
)
|
89.1.2
by Aaron Bentley
Fix imports |
40 |
from jujupy import ( |
1465.5.2
by Aaron Bentley
Implement client_from_config, delete by_version. |
41 |
client_from_config, |
663.1.2
by Aaron Bentley
Port bootstrap_from_env to EnvJujuClient, add unit tests. |
42 |
get_local_root, |
1153.4.3
by Martin Packman
Changes from review by abentley |
43 |
get_machine_dns_name, |
1049.1.1
by Aaron Bentley
Add --pre-destroy option to deploy_job script. |
44 |
jes_home_path, |
1674.1.4
by Aaron Bentley
More conversion. |
45 |
NoProvider, |
880.1.1
by Aaron Bentley
Remove Environment from deploy_stack.py |
46 |
SimpleEnvironment, |
884
by John George
Add juju-deployer test support. |
47 |
temp_bootstrap_env, |
719.1.3
by John George
Move libvirt_domain functions from jujupy to substrate. |
48 |
)
|
994.3.1
by Martin Packman
Make Remote an abstract class and implement winrm based version |
49 |
from remote import ( |
50 |
remote_from_address, |
|
51 |
remote_from_unit, |
|
1289
by Curtis Hovey
copy_remote_logs cannot ever throw an error because winrm is fucked. |
52 |
winrm, |
994.3.1
by Martin Packman
Make Remote an abstract class and implement winrm based version |
53 |
)
|
719.1.3
by John George
Move libvirt_domain functions from jujupy to substrate. |
54 |
from substrate import ( |
982.1.2
by Curtis Hovey
Remove euca_dump_logs because it has not been used this year. |
55 |
destroy_job_instances, |
719.1.4
by John George
Add LIBVIRT_DOMAIN state constants and sleep statements, to increase the interval between virsh calls. |
56 |
LIBVIRT_DOMAIN_RUNNING, |
994.4.4
by Martin Packman
Update with extra tests and addresses review comments by sinzui |
57 |
resolve_remote_dns_names, |
982.1.1
by Curtis Hovey
Move substrate (not juju) functions to substrate.py. |
58 |
run_instances, |
687.1.1
by John George
Add use of KVM start and stop functions, when env type is maas, to deploy_stack.py and cloud_deploy.py |
59 |
start_libvirt_domain, |
60 |
stop_libvirt_domain, |
|
719.1.3
by John George
Move libvirt_domain functions from jujupy to substrate. |
61 |
verify_libvirt_domain, |
385.1.1
by Aaron Bentley
Support upgrades. |
62 |
)
|
63 |
from utility import ( |
|
1028.2.2
by Curtis Hovey
deploy_stack.py uses add_basic_testing_arguments. |
64 |
add_basic_testing_arguments, |
751.2.2
by Aaron Bentley
Log success/failure for each step (of SteppedStageAttempt). |
65 |
configure_logging, |
777.2.1
by Aaron Bentley
Always delete jenv in industrial test. |
66 |
ensure_deleted, |
1303.1.3
by Martin Packman
Handle creation of log dirs correctly for hosted environments |
67 |
ensure_dir, |
1735.1.1
by Martin Packman
New utility.logged_exception factored out from deploy_stack |
68 |
logged_exception, |
1211.2.5
by Aaron Bentley
LoggedException in BootstrapManager, convert to sys.exit in booted_context |
69 |
LoggedException, |
457
by Aaron Bentley
Don't raise an exception when logs cannot be dumped. |
70 |
PortTimeoutError, |
717.2.2
by Aaron Bentley
Checkpoint with assess_recovery working. |
71 |
print_now, |
422.1.1
by Aaron Bentley
Support bootstrap with customized options. |
72 |
until_timeout, |
385.1.1
by Aaron Bentley
Support upgrades. |
73 |
wait_for_port, |
89.1.2
by Aaron Bentley
Fix imports |
74 |
)
|
17
by Aaron Bentley
Split out jujupy library. |
75 |
|
155.1.1
by Aaron Bentley
Support a local prefix and repository for deployment. |
76 |
|
1092.2.2
by Aaron Bentley
Fix lint. |
77 |
__metaclass__ = type |
78 |
||
79 |
||
717.2.1
by Aaron Bentley
Extract EnvJujuClient.backup from assess_recovery. |
80 |
def destroy_environment(client, instance_tag): |
834.2.6
by Curtis Hovey
Added rule to destroy manual envs, then remove instances (which may not exist). |
81 |
client.destroy_environment() |
1674.1.4
by Aaron Bentley
More conversion. |
82 |
if (client.env.provider == 'manual' and |
1092.2.2
by Aaron Bentley
Fix lint. |
83 |
'AWS_ACCESS_KEY' in os.environ): |
717.2.1
by Aaron Bentley
Extract EnvJujuClient.backup from assess_recovery. |
84 |
destroy_job_instances(instance_tag) |
419.1.6
by Aaron Bentley
Use python path for ec2-terminate-job-instances. |
85 |
|
86 |
||
1345.1.6
by Seman
Upated variable name. |
87 |
def deploy_dummy_stack(client, charm_series): |
1289
by Curtis Hovey
copy_remote_logs cannot ever throw an error because winrm is fucked. |
88 |
""""Deploy a dummy stack in the specified environment."""
|
1091.4.1
by James Tunnicliffe
Merged upstream |
89 |
# Centos requires specific machine configuration (i.e. network device
|
90 |
# order).
|
|
1355.1.1
by Seman
Updated deploy_dummy_stack to support CentOS and Windows charms. |
91 |
if charm_series.startswith("centos") and client.env.maas: |
1251.1.1
by Aaron Bentley
Implement and use set_model_constraints. |
92 |
client.set_model_constraints({'tags': 'MAAS_NIC_1'}) |
1345.1.5
by Seman
Deploy charm by path #2. |
93 |
platform = 'ubuntu' |
1355.1.1
by Seman
Updated deploy_dummy_stack to support CentOS and Windows charms. |
94 |
if charm_series.startswith('win'): |
95 |
platform = 'win' |
|
96 |
elif charm_series.startswith('centos'): |
|
97 |
platform = 'centos' |
|
1345.1.5
by Seman
Deploy charm by path #2. |
98 |
charm = local_charm_path(charm='dummy-source', juju_ver=client.version, |
1345.1.6
by Seman
Upated variable name. |
99 |
series=charm_series, platform=platform) |
100 |
client.deploy(charm, series=charm_series) |
|
1345.1.5
by Seman
Deploy charm by path #2. |
101 |
charm = local_charm_path(charm='dummy-sink', juju_ver=client.version, |
1345.1.6
by Seman
Upated variable name. |
102 |
series=charm_series, platform=platform) |
103 |
client.deploy(charm, series=charm_series) |
|
880.1.17
by Aaron Bentley
Fake merge of trunk into no-environment. |
104 |
client.juju('add-relation', ('dummy-source', 'dummy-sink')) |
105 |
client.juju('expose', ('dummy-sink',)) |
|
993.1.1
by John George
Give deploy_stack extra time to complete on MAAS. |
106 |
if client.env.kvm or client.env.maas: |
650.1.18
by Aaron Bentley
Reduce diff. |
107 |
# A single virtual machine may need up to 30 minutes before
|
108 |
# "apt-get update" and other initialisation steps are
|
|
109 |
# finished; two machines initializing concurrently may
|
|
993.1.1
by John George
Give deploy_stack extra time to complete on MAAS. |
110 |
# need even 40 minutes. In addition Windows image blobs or
|
111 |
# any system deployment using MAAS requires extra time.
|
|
1506
by Nicholas Skaggs
bump MAAS timeout to 7200 before killing |
112 |
client.wait_for_started(7200) |
650.1.18
by Aaron Bentley
Reduce diff. |
113 |
else: |
1507
by Nicholas Skaggs
set timeout to 3600 for deploy_dummy_stack (precise, windows can take some time) |
114 |
client.wait_for_started(3600) |
1169.1.1
by John George
Factor out relation check, so assess_upgrade can be re-used by run_deployer.py |
115 |
|
116 |
||
117 |
def assess_juju_relations(client): |
|
118 |
token = get_random_string() |
|
1239.1.1
by Aaron Bentley
Implement and use EnvJujuClient.set_config. |
119 |
client.set_config('dummy-source', {'token': token}) |
880.1.17
by Aaron Bentley
Fake merge of trunk into no-environment. |
120 |
check_token(client, token) |
121 |
||
122 |
||
931.1.3
by Martin Packman
Tidy up changes and basic test coverage |
123 |
GET_TOKEN_SCRIPT = """ |
124 |
for x in $(seq 120); do
|
|
125 |
if [ -f /var/run/dummy-sink/token ]; then
|
|
126 |
if [ "$(cat /var/run/dummy-sink/token)" != "" ]; then
|
|
127 |
break
|
|
128 |
fi
|
|
129 |
fi
|
|
130 |
sleep 1
|
|
131 |
done
|
|
132 |
cat /var/run/dummy-sink/token
|
|
1262.1.1
by Curtis Hovey
Sleep 2s when checking token, and provide more info. |
133 |
sleep 2
|
931.1.3
by Martin Packman
Tidy up changes and basic test coverage |
134 |
"""
|
135 |
||
136 |
||
1523.1.1
by Curtis Hovey
Added get_token_from_status |
137 |
def get_token_from_status(client): |
1523.1.4
by Curtis Hovey
Updated docstrings. |
138 |
"""Return the token from the application status message or None."""
|
1523.1.1
by Curtis Hovey
Added get_token_from_status |
139 |
status = client.get_status() |
140 |
unit = status.get_unit('dummy-sink/0') |
|
141 |
app_status = unit.get('workload-status') |
|
142 |
if app_status is not None: |
|
143 |
message = app_status.get('message', '') |
|
144 |
parts = message.split() |
|
145 |
if parts: |
|
146 |
return parts[-1] |
|
147 |
return None |
|
148 |
||
149 |
||
1262.1.1
by Curtis Hovey
Sleep 2s when checking token, and provide more info. |
150 |
def check_token(client, token, timeout=120): |
1523.1.4
by Curtis Hovey
Updated docstrings. |
151 |
"""Check the token found on dummy-sink/0 or raise ValueError."""
|
1526.1.1
by Curtis Hovey
Wait for applications to be active before checking token. |
152 |
logging.info('Waiting for applications to reach ready.') |
153 |
client.wait_for_workloads() |
|
880.1.17
by Aaron Bentley
Fake merge of trunk into no-environment. |
154 |
# Wait up to 120 seconds for token to be created.
|
155 |
logging.info('Retrieving token.') |
|
994.3.1
by Martin Packman
Make Remote an abstract class and implement winrm based version |
156 |
remote = remote_from_unit(client, "dummy-sink/0") |
994.4.4
by Martin Packman
Update with extra tests and addresses review comments by sinzui |
157 |
# Update remote with real address if needed.
|
158 |
resolve_remote_dns_names(client.env, [remote]) |
|
931.1.2
by Martin Packman
Retry check_token for desired result for 120 seconds in all cases |
159 |
start = time.time() |
160 |
while True: |
|
994.3.1
by Martin Packman
Make Remote an abstract class and implement winrm based version |
161 |
if remote.is_windows(): |
1523.1.1
by Curtis Hovey
Added get_token_from_status |
162 |
result = get_token_from_status(client) |
163 |
if not result: |
|
164 |
try: |
|
165 |
result = remote.cat("%ProgramData%\\dummy-sink\\token") |
|
166 |
except winrm.exceptions.WinRMTransportError as e: |
|
1523.1.3
by Curtis Hovey
Added tests, log warning when returning early. |
167 |
logging.warning( |
168 |
"Skipping token check because of: {}".format(str(e))) |
|
1523.1.1
by Curtis Hovey
Added get_token_from_status |
169 |
return
|
994.3.1
by Martin Packman
Make Remote an abstract class and implement winrm based version |
170 |
else: |
171 |
result = remote.run(GET_TOKEN_SCRIPT) |
|
1266
by Curtis Hovey
quote shell args. |
172 |
token_pattern = re.compile(r'([^\n\r]*)\r?\n?') |
173 |
result = token_pattern.match(result).group(1) |
|
931.1.2
by Martin Packman
Retry check_token for desired result for 120 seconds in all cases |
174 |
if result == token: |
931.1.3
by Martin Packman
Tidy up changes and basic test coverage |
175 |
logging.info("Token matches expected %r", result) |
931.1.2
by Martin Packman
Retry check_token for desired result for 120 seconds in all cases |
176 |
return
|
1262.1.1
by Curtis Hovey
Sleep 2s when checking token, and provide more info. |
177 |
if time.time() - start > timeout: |
178 |
if not remote.is_windows() and remote.use_juju_ssh: |
|
179 |
# 'juju ssh' didn't error, but try raw ssh to verify
|
|
180 |
# the result is the same.
|
|
181 |
remote.get_address() |
|
182 |
remote.use_juju_ssh = False |
|
183 |
result = remote.run(GET_TOKEN_SCRIPT) |
|
1266
by Curtis Hovey
quote shell args. |
184 |
result = token_pattern.match(result).group(1) |
1262.1.1
by Curtis Hovey
Sleep 2s when checking token, and provide more info. |
185 |
if result == token: |
186 |
logging.info("Token matches expected %r", result) |
|
187 |
logging.error("juju ssh to unit is broken.") |
|
931.1.2
by Martin Packman
Retry check_token for desired result for 120 seconds in all cases |
188 |
raise ValueError('Token is %r' % result) |
931.1.3
by Martin Packman
Tidy up changes and basic test coverage |
189 |
logging.info("Found token %r expected %r", result, token) |
931.1.2
by Martin Packman
Retry check_token for desired result for 120 seconds in all cases |
190 |
time.sleep(5) |
357.1.1
by Aaron Bentley
Add option to deploy a dummy stack. |
191 |
|
706.1.1
by Aaron Bentley
Switch to flake8 and fix lint. |
192 |
|
650.1.7
by Aaron Bentley
Start testing mixed environs. |
193 |
def get_random_string(): |
194 |
allowed_chars = string.ascii_uppercase + string.digits |
|
195 |
return ''.join(random.choice(allowed_chars) for n in range(20)) |
|
196 |
||
197 |
||
1053.1.1
by Martin Packman
Refactor log collection to ensure local logs are only collected once |
198 |
def _can_run_ssh(): |
1289
by Curtis Hovey
copy_remote_logs cannot ever throw an error because winrm is fucked. |
199 |
"""Return true if local system can use ssh to access remote machines."""
|
1053.1.1
by Martin Packman
Refactor log collection to ensure local logs are only collected once |
200 |
# When client is run on a windows machine, we have no local ssh binary.
|
201 |
return sys.platform != "win32" |
|
202 |
||
203 |
||
1050.2.9
by Aaron Bentley
Merged trunk into copy-cache. |
204 |
def dump_env_logs(client, bootstrap_host, artifacts_dir, runtime_config=None): |
1173.2.1
by Aaron Bentley
Extract dump_env_logs_known_hosts. |
205 |
if bootstrap_host is None: |
206 |
known_hosts = {} |
|
207 |
else: |
|
208 |
known_hosts = {'0': bootstrap_host} |
|
209 |
dump_env_logs_known_hosts(client, artifacts_dir, runtime_config, |
|
210 |
known_hosts) |
|
211 |
||
212 |
||
213 |
def dump_env_logs_known_hosts(client, artifacts_dir, runtime_config=None, |
|
214 |
known_hosts=None): |
|
215 |
if known_hosts is None: |
|
216 |
known_hosts = {} |
|
1053.1.1
by Martin Packman
Refactor log collection to ensure local logs are only collected once |
217 |
if client.env.local: |
218 |
logging.info("Retrieving logs for local environment") |
|
219 |
copy_local_logs(client.env, artifacts_dir) |
|
220 |
else: |
|
1173.2.1
by Aaron Bentley
Extract dump_env_logs_known_hosts. |
221 |
remote_machines = get_remote_machines(client, known_hosts) |
1053.1.1
by Martin Packman
Refactor log collection to ensure local logs are only collected once |
222 |
|
223 |
for machine_id in sorted(remote_machines, key=int): |
|
224 |
remote = remote_machines[machine_id] |
|
225 |
if not _can_run_ssh() and not remote.is_windows(): |
|
226 |
logging.info("No ssh, skipping logs for machine-%s using %r", |
|
1056.1.3
by John George
Lint cleanup. |
227 |
machine_id, remote) |
1053.1.1
by Martin Packman
Refactor log collection to ensure local logs are only collected once |
228 |
continue
|
229 |
logging.info("Retrieving logs for machine-%s using %r", machine_id, |
|
230 |
remote) |
|
1056.1.3
by John George
Lint cleanup. |
231 |
machine_dir = os.path.join(artifacts_dir, |
232 |
"machine-%s" % machine_id) |
|
1303.1.3
by Martin Packman
Handle creation of log dirs correctly for hosted environments |
233 |
ensure_dir(machine_dir) |
1053.1.1
by Martin Packman
Refactor log collection to ensure local logs are only collected once |
234 |
copy_remote_logs(remote, machine_dir) |
235 |
archive_logs(artifacts_dir) |
|
1050.2.9
by Aaron Bentley
Merged trunk into copy-cache. |
236 |
retain_config(runtime_config, artifacts_dir) |
1050.2.2
by Aaron Bentley
Retain config.yaml instead of .jenv for JES. |
237 |
|
238 |
||
239 |
def retain_config(runtime_config, log_directory): |
|
240 |
if not runtime_config: |
|
908.1.1
by seman.said at canonical
Added script to retain jenv file during a failure. |
241 |
return False |
242 |
||
243 |
try: |
|
1050.2.2
by Aaron Bentley
Retain config.yaml instead of .jenv for JES. |
244 |
shutil.copy(runtime_config, log_directory) |
908.1.1
by seman.said at canonical
Added script to retain jenv file during a failure. |
245 |
return True |
246 |
except IOError: |
|
1050.2.2
by Aaron Bentley
Retain config.yaml instead of .jenv for JES. |
247 |
print_now("Failed to copy file. Source: %s Destination: %s" % |
248 |
(runtime_config, log_directory)) |
|
908.1.1
by seman.said at canonical
Added script to retain jenv file during a failure. |
249 |
return False |
611.1.5
by Menno Smits
Added dump_env_logs: archives all Juju logs possible for all machines in an environment |
250 |
|
251 |
||
1048.2.1
by John George
Capture duration of juju commands from the client perspective. |
252 |
def dump_juju_timings(client, log_directory): |
253 |
try: |
|
254 |
with open(os.path.join(log_directory, 'juju_command_times.json'), |
|
255 |
'w') as timing_file: |
|
256 |
json.dump(client.get_juju_timings(), timing_file, indent=2, |
|
257 |
sort_keys=True) |
|
258 |
timing_file.write('\n') |
|
259 |
except Exception as e: |
|
260 |
print_now("Failed to save timings") |
|
261 |
print_now(str(e)) |
|
262 |
||
263 |
||
1173.2.1
by Aaron Bentley
Extract dump_env_logs_known_hosts. |
264 |
def get_remote_machines(client, known_hosts): |
994.4.4
by Martin Packman
Update with extra tests and addresses review comments by sinzui |
265 |
"""Return a dict of machine_id to remote machines.
|
984.1.8
by Curtis Hovey
Added test for case where status cannot provide machine dns-name. |
266 |
|
994.4.4
by Martin Packman
Update with extra tests and addresses review comments by sinzui |
267 |
A bootstrap_host address may be provided as a fallback for machine 0 if
|
268 |
status fails. For some providers such as MAAS the dns-name will be
|
|
269 |
resolved to a real ip address using the substrate api.
|
|
984.1.8
by Curtis Hovey
Added test for case where status cannot provide machine dns-name. |
270 |
"""
|
611.1.5
by Menno Smits
Added dump_env_logs: archives all Juju logs possible for all machines in an environment |
271 |
# Try to get machine details from environment if possible.
|
994.4.2
by Martin Packman
Use winrm copy implementation to get logs from windows machines |
272 |
machines = dict(iter_remote_machines(client)) |
994.4.4
by Martin Packman
Update with extra tests and addresses review comments by sinzui |
273 |
# The bootstrap host is added as a fallback in case status failed.
|
1173.2.1
by Aaron Bentley
Extract dump_env_logs_known_hosts. |
274 |
for machine_id, address in known_hosts.items(): |
275 |
if machine_id not in machines: |
|
276 |
machines[machine_id] = remote_from_address(address) |
|
994.4.4
by Martin Packman
Update with extra tests and addresses review comments by sinzui |
277 |
# Update remote machines in place with real addresses if substrate needs.
|
278 |
resolve_remote_dns_names(client.env, machines.itervalues()) |
|
994.4.2
by Martin Packman
Use winrm copy implementation to get logs from windows machines |
279 |
return machines |
280 |
||
281 |
||
282 |
def iter_remote_machines(client): |
|
611.1.5
by Menno Smits
Added dump_env_logs: archives all Juju logs possible for all machines in an environment |
283 |
try: |
717.2.1
by Aaron Bentley
Extract EnvJujuClient.backup from assess_recovery. |
284 |
status = client.get_status() |
611.1.5
by Menno Smits
Added dump_env_logs: archives all Juju logs possible for all machines in an environment |
285 |
except Exception as err: |
286 |
logging.warning("Failed to retrieve status for dumping logs: %s", err) |
|
287 |
return
|
|
994.4.2
by Martin Packman
Use winrm copy implementation to get logs from windows machines |
288 |
|
611.1.5
by Menno Smits
Added dump_env_logs: archives all Juju logs possible for all machines in an environment |
289 |
for machine_id, machine in status.iter_machines(): |
290 |
hostname = machine.get('dns-name') |
|
291 |
if hostname: |
|
994.4.2
by Martin Packman
Use winrm copy implementation to get logs from windows machines |
292 |
remote = remote_from_address(hostname, machine.get('series')) |
293 |
yield machine_id, remote |
|
294 |
||
295 |
||
1053.1.1
by Martin Packman
Refactor log collection to ensure local logs are only collected once |
296 |
def archive_logs(log_dir): |
297 |
"""Compress log files in given log_dir using gzip."""
|
|
1091.4.1
by James Tunnicliffe
Merged upstream |
298 |
log_files = [] |
299 |
for r, ds, fs in os.walk(log_dir): |
|
1582.1.1
by Andrew Beach
This might be all we need to get the syslog compressed, have yet to test it. |
300 |
log_files.extend(os.path.join(r, f) for f in fs if is_log(f)) |
751.4.1
by Martin Packman
Avoid hanging job when no logs have been gathered for whatever reason |
301 |
if log_files: |
1053.1.1
by Martin Packman
Refactor log collection to ensure local logs are only collected once |
302 |
subprocess.check_call(['gzip', '--best', '-f'] + log_files) |
611.1.5
by Menno Smits
Added dump_env_logs: archives all Juju logs possible for all machines in an environment |
303 |
|
611.1.2
by Menno Smits
Dump more types of log files |
304 |
|
1582.1.1
by Andrew Beach
This might be all we need to get the syslog compressed, have yet to test it. |
305 |
def is_log(file_name): |
306 |
"""Check to see if the given file name is the name of a log file."""
|
|
307 |
return file_name.endswith('.log') or file_name.endswith('syslog') |
|
308 |
||
309 |
||
919.1.1
by Martin Packman
Add lxc container logs to local artifacts collected |
310 |
lxc_template_glob = '/var/lib/juju/containers/juju-*-lxc-template/*.log' |
311 |
||
312 |
||
994.4.2
by Martin Packman
Use winrm copy implementation to get logs from windows machines |
313 |
def copy_local_logs(env, directory): |
1053.1.1
by Martin Packman
Refactor log collection to ensure local logs are only collected once |
314 |
"""Copy logs for all machines in local environment."""
|
994.4.2
by Martin Packman
Use winrm copy implementation to get logs from windows machines |
315 |
local = get_local_root(get_juju_home(), env) |
611.1.2
by Menno Smits
Dump more types of log files |
316 |
log_names = [os.path.join(local, 'cloud-init-output.log')] |
611.1.3
by Menno Smits
use glob() to simplify log dumping code |
317 |
log_names.extend(glob.glob(os.path.join(local, 'log', '*.log'))) |
919.1.1
by Martin Packman
Add lxc container logs to local artifacts collected |
318 |
log_names.extend(glob.glob(lxc_template_glob)) |
1053.1.1
by Martin Packman
Refactor log collection to ensure local logs are only collected once |
319 |
try: |
320 |
subprocess.check_call(['sudo', 'chmod', 'go+r'] + log_names) |
|
321 |
subprocess.check_call(['cp'] + log_names + [directory]) |
|
322 |
except subprocess.CalledProcessError as e: |
|
323 |
logging.warning("Could not retrieve local logs: %s", e) |
|
611.1.2
by Menno Smits
Dump more types of log files |
324 |
|
325 |
||
994.4.2
by Martin Packman
Use winrm copy implementation to get logs from windows machines |
326 |
def copy_remote_logs(remote, directory): |
796.1.10
by Curtis Hovey
Added test to verify errors do not stop the attempt to recover logs. |
327 |
"""Copy as many logs from the remote host as possible to the directory."""
|
328 |
# This list of names must be in the order of creation to ensure they
|
|
329 |
# are retrieved.
|
|
994.4.2
by Martin Packman
Use winrm copy implementation to get logs from windows machines |
330 |
if remote.is_windows(): |
331 |
log_paths = [ |
|
332 |
"%ProgramFiles(x86)%\\Cloudbase Solutions\\Cloudbase-Init\\log\\*", |
|
994.4.3
by Martin Packman
Selection of fixes needed for passing job |
333 |
"C:\\Juju\\log\\juju\\*.log", |
994.4.2
by Martin Packman
Use winrm copy implementation to get logs from windows machines |
334 |
]
|
335 |
else: |
|
336 |
log_paths = [ |
|
337 |
'/var/log/cloud-init*.log', |
|
338 |
'/var/log/juju/*.log', |
|
1091.4.1
by James Tunnicliffe
Merged upstream |
339 |
# TODO(gz): Also capture kvm container logs?
|
340 |
'/var/lib/juju/containers/juju-*-lxc-*/', |
|
1440.1.3
by Aaron Bentley
Add lxd logs. |
341 |
'/var/log/lxd/juju-*', |
1457.1.1
by Aaron Bentley
Add /var/log/lxd/lxd.log to list of collected logs. |
342 |
'/var/log/lxd/lxd.log', |
1361.1.1
by Aaron Bentley
Include syslog and mongodb log when duming logs. |
343 |
'/var/log/syslog', |
344 |
'/var/log/mongodb/mongodb.log', |
|
1464.1.6
by Curtis Hovey
create a log of ifconfig. |
345 |
'/etc/network/interfaces', |
1655.1.16
by Curtis Hovey
Collect /etc/environment for analysis. |
346 |
'/etc/environment', |
1464.1.6
by Curtis Hovey
create a log of ifconfig. |
347 |
'/home/ubuntu/ifconfig.log', |
994.4.2
by Martin Packman
Use winrm copy implementation to get logs from windows machines |
348 |
]
|
349 |
||
350 |
try: |
|
351 |
wait_for_port(remote.address, 22, timeout=60) |
|
352 |
except PortTimeoutError: |
|
353 |
logging.warning("Could not dump logs because port 22 was closed.") |
|
354 |
return
|
|
355 |
||
356 |
try: |
|
1091.4.1
by James Tunnicliffe
Merged upstream |
357 |
remote.run('sudo chmod -Rf go+r ' + ' '.join(log_paths)) |
1464.1.7
by Curtis Hovey
capture ifconfig state in separate block. |
358 |
except subprocess.CalledProcessError as e: |
359 |
# The juju log dir is not created until after cloud-init succeeds.
|
|
360 |
logging.warning("Could not allow access to the juju logs:") |
|
361 |
logging.warning(e.output) |
|
362 |
try: |
|
1464.1.6
by Curtis Hovey
create a log of ifconfig. |
363 |
remote.run('ifconfig > /home/ubuntu/ifconfig.log') |
994.4.2
by Martin Packman
Use winrm copy implementation to get logs from windows machines |
364 |
except subprocess.CalledProcessError as e: |
1464.1.7
by Curtis Hovey
capture ifconfig state in separate block. |
365 |
logging.warning("Could not capture ifconfig state:") |
994.4.2
by Martin Packman
Use winrm copy implementation to get logs from windows machines |
366 |
logging.warning(e.output) |
611.1.2
by Menno Smits
Dump more types of log files |
367 |
|
796.1.1
by Curtis Hovey
Report log retrieval errors and continue. Retrieve remote logs in the proper order. |
368 |
try: |
983.1.1
by Martin Packman
Add new Remote class for accessing juju machines |
369 |
remote.copy(directory, log_paths) |
1289
by Curtis Hovey
copy_remote_logs cannot ever throw an error because winrm is fucked. |
370 |
except (subprocess.CalledProcessError, |
371 |
winrm.exceptions.WinRMTransportError) as e: |
|
796.1.10
by Curtis Hovey
Added test to verify errors do not stop the attempt to recover logs. |
372 |
# The juju logs will not exist if cloud-init failed.
|
796.1.1
by Curtis Hovey
Report log retrieval errors and continue. Retrieve remote logs in the proper order. |
373 |
logging.warning("Could not retrieve some or all logs:") |
1291
by Curtis Hovey
Return None from getattr. |
374 |
if getattr(e, 'output', None): |
1290
by Curtis Hovey
Let me see the error. |
375 |
logging.warning(e.output) |
376 |
else: |
|
1292
by Curtis Hovey
Fix test broken by quick fix for log collection. |
377 |
logging.warning(repr(e)) |
379.1.1
by Aaron Bentley
Move portions of deploy job to Python. |
378 |
|
1302.1.2
by Aaron Bentley
Fix lint. |
379 |
|
880.1.17
by Aaron Bentley
Fake merge of trunk into no-environment. |
380 |
def assess_juju_run(client): |
1631.4.9
by Andrew Beach
Adjusted the check in assess_to to use hostname rather than dns name. (Might have to use both.) Updated EnvJujuClient.run to accomidate. |
381 |
responses = client.run(('uname',), |
382 |
applications=['dummy-source', 'dummy-sink']) |
|
881.1.1
by Seman Said
Added a test for juju run |
383 |
for machine in responses: |
384 |
if machine.get('ReturnCode', 0) != 0: |
|
881.1.3
by Seman Said
Added unit test for test_juju_run |
385 |
raise ValueError('juju run on machine %s returned %d: %s' % ( |
881.1.4
by Seman Said
Renamed the function to assess_juju_run and added return value. Also, updated the unit test to check for the return value |
386 |
machine.get('MachineId'), |
387 |
machine.get('ReturnCode'), |
|
388 |
machine.get('Stderr'))) |
|
953
by Curtis Hovey
Remove extra ")" causing a syntax error and make test failure. |
389 |
logging.info( |
390 |
"juju run succeeded on machines: %r", |
|
391 |
[str(machine.get("MachineId")) for machine in responses]) |
|
881.1.4
by Seman Said
Renamed the function to assess_juju_run and added return value. Also, updated the unit test to check for the return value |
392 |
return responses |
881.1.1
by Seman Said
Added a test for juju run |
393 |
|
394 |
||
1169.1.1
by John George
Factor out relation check, so assess_upgrade can be re-used by run_deployer.py |
395 |
def assess_upgrade(old_client, juju_path): |
1612.2.11
by Christopher Lee
Cleanup. |
396 |
all_clients = _get_clients_to_upgrade(old_client, juju_path) |
397 |
||
398 |
# all clients have the same provider type, work this out once.
|
|
1674.1.4
by Aaron Bentley
More conversion. |
399 |
if all_clients[0].env.provider == 'maas': |
1612.2.11
by Christopher Lee
Cleanup. |
400 |
timeout = 1200 |
401 |
else: |
|
402 |
timeout = 600 |
|
403 |
||
404 |
for client in all_clients: |
|
1612.2.1
by Christopher Lee
Make assess_upgrade 2.0 safe; upgrade the controller first. |
405 |
upgrade_juju(client) |
406 |
client.wait_for_version(client.get_matching_agent_version(), timeout) |
|
880.1.17
by Aaron Bentley
Fake merge of trunk into no-environment. |
407 |
|
408 |
||
1612.2.10
by Christopher Lee
Fix for deploy_stack/upgrade test |
409 |
def _get_clients_to_upgrade(old_client, juju_path): |
410 |
"""Return a list of cloned clients to upgrade.
|
|
411 |
||
412 |
Ensure that the controller (if available) is the first client in the list.
|
|
413 |
"""
|
|
414 |
new_client = old_client.clone_path_cls(juju_path) |
|
415 |
all_clients = sorted( |
|
416 |
new_client.iter_model_clients(), |
|
1612.2.17
by Christopher Lee
Update commit. |
417 |
key=lambda m: m.model_name == 'controller', |
418 |
reverse=True) |
|
1612.2.10
by Christopher Lee
Fix for deploy_stack/upgrade test |
419 |
|
420 |
return all_clients |
|
421 |
||
422 |
||
880.1.17
by Aaron Bentley
Fake merge of trunk into no-environment. |
423 |
def upgrade_juju(client): |
1540.3.4
by Christopher Lee
Actually rename the method in places it's used. |
424 |
client.set_testing_agent_metadata_url() |
1540.3.2
by Christopher Lee
Change tools_ to agent_ |
425 |
tools_metadata_url = client.get_agent_metadata_url() |
1612.2.6
by Christopher Lee
Update log message to use the right url name. |
426 |
logging.info( |
427 |
'The {url_type} is {url}'.format( |
|
428 |
url_type=client.agent_metadata_url, |
|
429 |
url=tools_metadata_url)) |
|
880.1.17
by Aaron Bentley
Fake merge of trunk into no-environment. |
430 |
client.upgrade_juju() |
385.1.1
by Aaron Bentley
Support upgrades. |
431 |
|
432 |
||
927.1.1
by Aaron Bentley
Add --upload-tools to deploy_job.py |
433 |
def deploy_job_parse_args(argv=None): |
884
by John George
Add juju-deployer test support. |
434 |
parser = ArgumentParser('deploy_job') |
1028.2.2
by Curtis Hovey
deploy_stack.py uses add_basic_testing_arguments. |
435 |
add_basic_testing_arguments(parser) |
884
by John George
Add juju-deployer test support. |
436 |
parser.add_argument('--upgrade', action="store_true", default=False, |
437 |
help='Perform an upgrade test.') |
|
1014.2.5
by John George
deploy_dummy_stack with chaos. |
438 |
parser.add_argument('--with-chaos', default=0, type=int, |
439 |
help='Deploy and run Chaos Monkey in the background.') |
|
1049.1.1
by Aaron Bentley
Add --pre-destroy option to deploy_job script. |
440 |
parser.add_argument('--jes', action='store_true', |
441 |
help='Use JES to control environments.') |
|
1711.3.10
by Aaron Bentley
Accept --controller-host to use public controller. |
442 |
parser.add_argument( |
1711.3.12
by Aaron Bentley
Fix lint. |
443 |
'--controller-host', help=( |
444 |
'Host with a controller to use. If supplied, SSO_EMAIL and'
|
|
445 |
' SSO_PASSWORD environment variables will be used for oauth'
|
|
446 |
' authentication.')) |
|
927.1.1
by Aaron Bentley
Add --upload-tools to deploy_job.py |
447 |
return parser.parse_args(argv) |
448 |
||
449 |
||
450 |
def deploy_job(): |
|
451 |
args = deploy_job_parse_args() |
|
1028.2.2
by Curtis Hovey
deploy_stack.py uses add_basic_testing_arguments. |
452 |
configure_logging(args.verbose) |
639
by Aaron Bentley
Remove charm_prefix argument. |
453 |
series = args.series |
454 |
if series is None: |
|
455 |
series = 'precise' |
|
1345.1.5
by Seman
Deploy charm by path #2. |
456 |
charm_series = series |
1091.4.1
by James Tunnicliffe
Merged upstream |
457 |
# Don't need windows or centos state servers.
|
458 |
if series.startswith("win") or series.startswith("centos"): |
|
459 |
logging.info('Setting default series to trusty for win and centos.') |
|
994.2.1
by Martin Packman
Use a trusty state server when testing windows charms |
460 |
series = 'trusty' |
1345.1.5
by Seman
Deploy charm by path #2. |
461 |
return _deploy_job(args, charm_series, series) |
710.1.1
by Aaron Bentley
Support deploy_job --agent-url. |
462 |
|
463 |
||
464 |
def update_env(env, new_env_name, series=None, bootstrap_host=None, |
|
1092.2.3
by Aaron Bentley
Add --region support. |
465 |
agent_url=None, agent_stream=None, region=None): |
650.1.2
by Aaron Bentley
Extract update_env from _deploy_job |
466 |
# Rename to the new name.
|
1315.2.23
by Aaron Bentley
Introduce set_model_name, update tests, check controller on bootstrap. |
467 |
env.set_model_name(new_env_name) |
1674.1.16
by Aaron Bentley
Switch call sites to update_config. |
468 |
new_config = {} |
650.1.2
by Aaron Bentley
Extract update_env from _deploy_job |
469 |
if series is not None: |
1674.1.16
by Aaron Bentley
Switch call sites to update_config. |
470 |
new_config['default-series'] = series |
650.1.2
by Aaron Bentley
Extract update_env from _deploy_job |
471 |
if bootstrap_host is not None: |
1674.1.16
by Aaron Bentley
Switch call sites to update_config. |
472 |
new_config['bootstrap-host'] = bootstrap_host |
710.1.1
by Aaron Bentley
Support deploy_job --agent-url. |
473 |
if agent_url is not None: |
1674.1.16
by Aaron Bentley
Switch call sites to update_config. |
474 |
new_config['tools-metadata-url'] = agent_url |
945.1.2
by Curtis Hovey
Pass agent_stream down to update_env. |
475 |
if agent_stream is not None: |
1674.1.16
by Aaron Bentley
Switch call sites to update_config. |
476 |
new_config['agent-stream'] = agent_stream |
477 |
env.update_config(new_config) |
|
1092.2.3
by Aaron Bentley
Add --region support. |
478 |
if region is not None: |
1674.1.9
by Aaron Bentley
Switch deploy_stack to set_region. |
479 |
env.set_region(region) |
650.1.2
by Aaron Bentley
Extract update_env from _deploy_job |
480 |
|
481 |
||
1173.2.12
by Aaron Bentley
Tear down JES environments more carefully. |
482 |
@contextmanager
|
483 |
def temp_juju_home(client, new_home): |
|
484 |
"""Temporarily override the client's home directory."""
|
|
1193.2.4
by Aaron Bentley
Switch FakeJujuClient to raise on accessing juju_home. |
485 |
old_home = client.env.juju_home |
1193.2.1
by Aaron Bentley
Make EnvJujuClient.juju_home a reference to EnvJUjuClient.env.juju_home. |
486 |
client.env.juju_home = new_home |
1173.2.12
by Aaron Bentley
Tear down JES environments more carefully. |
487 |
try: |
488 |
yield
|
|
489 |
finally: |
|
1193.2.1
by Aaron Bentley
Make EnvJujuClient.juju_home a reference to EnvJUjuClient.env.juju_home. |
490 |
client.env.juju_home = old_home |
1173.2.12
by Aaron Bentley
Tear down JES environments more carefully. |
491 |
|
492 |
||
1711.3.9
by Aaron Bentley
Implement make_controller_strategy. |
493 |
def make_controller_strategy(client, tear_down_client, controller_host): |
494 |
if controller_host is None: |
|
495 |
return CreateController(client, tear_down_client) |
|
496 |
else: |
|
497 |
return PublicController( |
|
498 |
controller_host, os.environ['SSO_EMAIL'], |
|
499 |
os.environ['SSO_PASSWORD'], client, tear_down_client) |
|
500 |
||
501 |
||
1711.3.1
by Aaron Bentley
Introduce CreateController strategy. |
502 |
class CreateController: |
503 |
"""A Controller strategy where the controller is created.
|
|
504 |
||
505 |
Intended for use with BootstrapManager.
|
|
506 |
"""
|
|
507 |
||
508 |
def __init__(self, client, tear_down_client): |
|
509 |
self.client = client |
|
510 |
self.tear_down_client = tear_down_client |
|
511 |
||
512 |
def prepare(self): |
|
513 |
"""Prepare client for use by killing the existing controller."""
|
|
514 |
self.tear_down_client.kill_controller() |
|
515 |
||
516 |
def create_initial_model(self, upload_tools, series, boot_kwargs): |
|
517 |
"""Create the initial model by bootstrapping."""
|
|
518 |
self.client.bootstrap( |
|
519 |
upload_tools=upload_tools, bootstrap_series=series, |
|
520 |
**boot_kwargs) |
|
521 |
||
522 |
def get_hosts(self): |
|
523 |
"""Provide the controller host."""
|
|
524 |
host = get_machine_dns_name( |
|
525 |
self.client.get_controller_client(), '0') |
|
526 |
if host is None: |
|
527 |
raise ValueError('Could not get machine 0 host') |
|
528 |
return {'0': host} |
|
529 |
||
530 |
def tear_down(self): |
|
531 |
"""Tear down via client.tear_down."""
|
|
532 |
self.tear_down_client.tear_down() |
|
533 |
||
534 |
||
1711.3.8
by Aaron Bentley
Implement PublicController strategy. |
535 |
class PublicController: |
536 |
"""A controller strategy where the controller is public.
|
|
537 |
||
538 |
The user registers with the controller, and adds the initial model.
|
|
539 |
"""
|
|
540 |
def __init__(self, controller_host, email, password, client, |
|
541 |
tear_down_client): |
|
542 |
self.controller_host = controller_host |
|
543 |
self.email = email |
|
544 |
self.password = password |
|
545 |
self.client = client |
|
546 |
self.tear_down_client = tear_down_client |
|
547 |
||
548 |
def prepare(self): |
|
549 |
"""Prepare by destroying the model and unregistering if possible."""
|
|
550 |
try: |
|
551 |
self.tear_down() |
|
552 |
except subprocess.CalledProcessError: |
|
1711.5.3
by Aaron Bentley
Add comment. |
553 |
# Assume that any error tearing down means that there was nothing
|
554 |
# to tear down.
|
|
1711.3.8
by Aaron Bentley
Implement PublicController strategy. |
555 |
pass
|
556 |
||
557 |
def create_initial_model(self, upload_tools, series, boot_kwargs): |
|
558 |
"""Register controller and add model."""
|
|
559 |
self.client.register_host( |
|
560 |
self.controller_host, self.email, self.password) |
|
561 |
self.client.env.controller.explicit_region = True |
|
562 |
self.client.add_model(self.client.env) |
|
563 |
||
564 |
def get_hosts(self): |
|
565 |
"""There are no user-owned controller hosts, so no-op."""
|
|
566 |
return {} |
|
567 |
||
568 |
def tear_down(self): |
|
569 |
"""Remove the current model and clean up the controller."""
|
|
570 |
try: |
|
571 |
self.tear_down_client.destroy_model() |
|
572 |
finally: |
|
573 |
controller = self.tear_down_client.env.controller.name |
|
574 |
self.tear_down_client.juju('unregister', ('-y', controller), |
|
575 |
include_e=False) |
|
576 |
||
577 |
||
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
578 |
class BootstrapManager: |
579 |
"""
|
|
1162.2.10
by Aaron Bentley
Update docs. |
580 |
Helper class for running juju tests.
|
581 |
||
582 |
Enables running tests on the manual provider and on MAAS systems, with
|
|
583 |
automatic cleanup, logging, etc. See BootstrapManager.booted_context.
|
|
584 |
||
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
585 |
:ivar temp_env_name: a unique name for the juju env, such as a Jenkins
|
586 |
job name.
|
|
587 |
:ivar client: an EnvJujuClient.
|
|
1173.2.2
by Aaron Bentley
Switch runtime_context to dump using known_hosts. |
588 |
:ivar tear_down_client: an EnvJujuClient for tearing down the environment
|
589 |
(may be more reliable/capable/compatible than client.)
|
|
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
590 |
:ivar bootstrap_host: None, or the address of a manual or MAAS host to
|
591 |
bootstrap on.
|
|
592 |
:ivar machine: [] or a list of machines to use add to a manual env
|
|
593 |
before deploying services.
|
|
594 |
:ivar series: None or the default-series for the temp config.
|
|
595 |
:ivar agent_url: None or the agent-metadata-url for the temp config.
|
|
596 |
:ivar agent_stream: None or the agent-stream for the temp config.
|
|
597 |
:ivar log_dir: The path to the directory to store logs.
|
|
598 |
:ivar keep_env: False or True to not destroy the environment and keep
|
|
599 |
it alive to do an autopsy.
|
|
600 |
:ivar upload_tools: False or True to upload the local agent instead of
|
|
601 |
using streams.
|
|
1173.2.2
by Aaron Bentley
Switch runtime_context to dump using known_hosts. |
602 |
:ivar known_hosts: A dict mapping machine_ids to hosts for
|
603 |
dump_env_logs_known_hosts.
|
|
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
604 |
"""
|
605 |
||
1162.2.24
by Aaron Bentley
Use tear_down_client for teardown. |
606 |
def __init__(self, temp_env_name, client, tear_down_client, bootstrap_host, |
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
607 |
machines, series, agent_url, agent_stream, region, log_dir, |
1711.3.2
by Aaron Bentley
Use CreateController in BootstrapManager. |
608 |
keep_env, permanent, jes_enabled, controller_strategy=None): |
1162.2.11
by Aaron Bentley
Update docs |
609 |
"""Constructor.
|
610 |
||
611 |
Please see see `BootstrapManager` for argument descriptions.
|
|
1162.2.10
by Aaron Bentley
Update docs. |
612 |
"""
|
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
613 |
self.temp_env_name = temp_env_name |
614 |
self.bootstrap_host = bootstrap_host |
|
615 |
self.machines = machines |
|
616 |
self.series = series |
|
617 |
self.agent_url = agent_url |
|
618 |
self.agent_stream = agent_stream |
|
619 |
self.region = region |
|
620 |
self.log_dir = log_dir |
|
621 |
self.keep_env = keep_env |
|
1201.1.1
by Aaron Bentley
Ensure that permanent is always True when jes_enabled is True. |
622 |
if jes_enabled and not permanent: |
623 |
raise ValueError('Cannot set permanent False if jes_enabled is' |
|
624 |
' True.') |
|
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
625 |
self.permanent = permanent |
626 |
self.jes_enabled = jes_enabled |
|
1173.2.2
by Aaron Bentley
Switch runtime_context to dump using known_hosts. |
627 |
self.known_hosts = {} |
628 |
if bootstrap_host is not None: |
|
629 |
self.known_hosts['0'] = bootstrap_host |
|
1711.3.2
by Aaron Bentley
Use CreateController in BootstrapManager. |
630 |
if controller_strategy is None: |
631 |
controller_strategy = CreateController(client, tear_down_client) |
|
632 |
self.controller_strategy = controller_strategy |
|
1724.1.7
by Curtis Hovey
Convert BootstrapMamanger.has_controller into a simple boolean attribute. |
633 |
self.has_controller = False |
1711.3.2
by Aaron Bentley
Use CreateController in BootstrapManager. |
634 |
|
635 |
@property
|
|
636 |
def client(self): |
|
637 |
return self.controller_strategy.client |
|
638 |
||
639 |
@property
|
|
640 |
def tear_down_client(self): |
|
641 |
return self.controller_strategy.tear_down_client |
|
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
642 |
|
1162.2.13
by Aaron Bentley
Switch quickstart to BootstrapManager. |
643 |
@classmethod
|
1449.4.27
by Nicholas Skaggs
restore _generate_default_clean_dir |
644 |
def _generate_default_clean_dir(cls, temp_env_name): |
645 |
"""Creates a new unique directory for logging and returns name"""
|
|
646 |
logging.info('Environment {}'.format(temp_env_name)) |
|
647 |
test_name = temp_env_name.split('-')[0] |
|
648 |
timestamp = datetime.now().strftime("%Y%m%d%H%M%S") |
|
649 |
log_dir = os.path.join('/tmp', test_name, 'logs', timestamp) |
|
650 |
||
651 |
try: |
|
652 |
os.makedirs(log_dir) |
|
653 |
logging.info('Created logging directory {}'.format(log_dir)) |
|
654 |
except OSError as e: |
|
655 |
if e.errno == errno.EEXIST: |
|
656 |
logging.warn('"Directory {} already exists'.format(log_dir)) |
|
657 |
else: |
|
658 |
raise('Failed to create logging directory: {} ' + |
|
659 |
log_dir + |
|
660 |
'. Please specify empty folder or try again') |
|
661 |
return log_dir |
|
662 |
||
663 |
@classmethod
|
|
1162.2.13
by Aaron Bentley
Switch quickstart to BootstrapManager. |
664 |
def from_args(cls, args): |
1449.4.25
by Nicholas Skaggs
flake8 |
665 |
if not args.logs: |
1449.4.27
by Nicholas Skaggs
restore _generate_default_clean_dir |
666 |
args.logs = cls._generate_default_clean_dir(args.temp_env_name) |
1449.4.24
by Nicholas Skaggs
move directory creation to bootstrap manager |
667 |
|
1543.1.2
by Martin Packman
Doc and comments from review by abentley |
668 |
# GZ 2016-08-11: Move this logic into client_from_config maybe?
|
1433.1.2
by Aaron Bentley
Support FAKE as a juju binary. |
669 |
if args.juju_bin == 'FAKE': |
1465.5.2
by Aaron Bentley
Implement client_from_config, delete by_version. |
670 |
env = SimpleEnvironment.from_config(args.env) |
1433.1.2
by Aaron Bentley
Support FAKE as a juju binary. |
671 |
client = fake_juju_client(env=env) |
672 |
else: |
|
1465.5.2
by Aaron Bentley
Implement client_from_config, delete by_version. |
673 |
client = client_from_config(args.env, args.juju_bin, |
1575.2.7
by Aaron Bentley
Fake merge of soft-timeouts-4 into soft-timeouts-5. |
674 |
debug=args.debug, |
675 |
soft_deadline=args.deadline) |
|
1745.2.1
by Aaron Bentley
Extract BootstrapManager.from_client. |
676 |
return cls.from_client(args, client) |
677 |
||
678 |
@classmethod
|
|
679 |
def from_client(cls, args, client): |
|
1162.2.13
by Aaron Bentley
Switch quickstart to BootstrapManager. |
680 |
jes_enabled = client.is_jes_enabled() |
681 |
return cls( |
|
1162.2.24
by Aaron Bentley
Use tear_down_client for teardown. |
682 |
args.temp_env_name, client, client, args.bootstrap_host, |
683 |
args.machine, args.series, args.agent_url, args.agent_stream, |
|
684 |
args.region, args.logs, args.keep_env, permanent=jes_enabled, |
|
1162.2.13
by Aaron Bentley
Switch quickstart to BootstrapManager. |
685 |
jes_enabled=jes_enabled) |
686 |
||
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
687 |
@contextmanager
|
688 |
def maas_machines(self): |
|
1162.2.8
by Aaron Bentley
Update docs. |
689 |
"""Handle starting/stopping MAAS machines."""
|
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
690 |
running_domains = dict() |
691 |
try: |
|
1674.1.4
by Aaron Bentley
More conversion. |
692 |
if self.client.env.provider == 'maas' and self.machines: |
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
693 |
for machine in self.machines: |
694 |
name, URI = machine.split('@') |
|
695 |
# Record already running domains, so we can warn that
|
|
696 |
# we're deleting them following the test.
|
|
697 |
if verify_libvirt_domain(URI, name, |
|
698 |
LIBVIRT_DOMAIN_RUNNING): |
|
699 |
running_domains = {machine: True} |
|
700 |
logging.info("%s is already running" % name) |
|
701 |
else: |
|
702 |
running_domains = {machine: False} |
|
703 |
logging.info("Attempting to start %s at %s" |
|
704 |
% (name, URI)) |
|
705 |
status_msg = start_libvirt_domain(URI, name) |
|
706 |
logging.info("%s" % status_msg) |
|
707 |
# No further handling of machines down the line is required.
|
|
708 |
yield [] |
|
709 |
else: |
|
710 |
yield self.machines |
|
711 |
finally: |
|
1674.1.4
by Aaron Bentley
More conversion. |
712 |
if self.client.env.provider == 'maas' and not self.keep_env: |
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
713 |
logging.info("Waiting for destroy-environment to complete") |
714 |
time.sleep(90) |
|
715 |
for machine, running in running_domains.items(): |
|
716 |
name, URI = machine.split('@') |
|
717 |
if running: |
|
718 |
logging.warning( |
|
719 |
"%s at %s was running when deploy_job started." |
|
720 |
" Shutting it down to ensure a clean environment."
|
|
721 |
% (name, URI)) |
|
722 |
logging.info("Attempting to stop %s at %s" % (name, URI)) |
|
723 |
status_msg = stop_libvirt_domain(URI, name) |
|
724 |
logging.info("%s" % status_msg) |
|
725 |
||
726 |
@contextmanager
|
|
727 |
def aws_machines(self): |
|
1162.2.8
by Aaron Bentley
Update docs. |
728 |
"""Handle starting/stopping AWS machines.
|
729 |
||
730 |
Machines are deliberately killed by tag so that any stray machines
|
|
731 |
from previous runs will be killed.
|
|
732 |
"""
|
|
1162.2.9
by Aaron Bentley
Fix lint. |
733 |
if ( |
1674.1.4
by Aaron Bentley
More conversion. |
734 |
self.client.env.provider != 'manual' or |
1162.2.9
by Aaron Bentley
Fix lint. |
735 |
self.bootstrap_host is not None): |
1173.2.6
by Aaron Bentley
aws_machines doesn't yield bootstrap_host. |
736 |
yield [] |
1162.2.9
by Aaron Bentley
Fix lint. |
737 |
return
|
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
738 |
try: |
1334
by Curtis Hovey
Pass region to run_instances for manual testings. |
739 |
instances = run_instances( |
740 |
3, self.temp_env_name, self.series, region=self.region) |
|
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
741 |
new_bootstrap_host = instances[0][1] |
1173.2.3
by Aaron Bentley
runtime_context doesn't take bootstrap_host as a parameter. |
742 |
self.known_hosts['0'] = new_bootstrap_host |
1173.2.6
by Aaron Bentley
aws_machines doesn't yield bootstrap_host. |
743 |
yield [i[1] for i in instances[1:]] |
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
744 |
finally: |
745 |
if self.keep_env: |
|
746 |
return
|
|
747 |
destroy_job_instances(self.temp_env_name) |
|
748 |
||
1162.2.25
by Aaron Bentley
Call is_jes_enabled on bootstrap_client. |
749 |
def tear_down(self, try_jes=False): |
1688.1.1
by Andrew Beach
Changed the BootstrapManager.tear_down method. Still have to finish intergating it. |
750 |
"""Tear down the client using tear_down_client.
|
751 |
||
752 |
Attempts to use the soft method destroy_controller, if that fails
|
|
753 |
it will use the hard kill_controller.
|
|
754 |
||
755 |
:param try_jes: Ignored."""
|
|
1193.2.1
by Aaron Bentley
Make EnvJujuClient.juju_home a reference to EnvJUjuClient.env.juju_home. |
756 |
if self.tear_down_client.env is not self.client.env: |
757 |
raise AssertionError('Tear down client needs same env!') |
|
1711.3.2
by Aaron Bentley
Use CreateController in BootstrapManager. |
758 |
self.controller_strategy.tear_down() |
1724.1.7
by Curtis Hovey
Convert BootstrapMamanger.has_controller into a simple boolean attribute. |
759 |
self.has_controller = False |
1162.2.25
by Aaron Bentley
Call is_jes_enabled on bootstrap_client. |
760 |
|
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
761 |
@contextmanager
|
1242.3.7
by Aaron Bentley
BootstrapManager support for bootstrap option. |
762 |
def bootstrap_context(self, machines, omit_config=None): |
1162.2.8
by Aaron Bentley
Update docs. |
763 |
"""Context for bootstrapping a state server."""
|
1173.2.4
by Aaron Bentley
bootstrap_context doesn't accept bootstrap_host. |
764 |
bootstrap_host = self.known_hosts.get('0') |
1242.3.7
by Aaron Bentley
BootstrapManager support for bootstrap option. |
765 |
kwargs = dict( |
766 |
series=self.series, bootstrap_host=bootstrap_host, |
|
767 |
agent_url=self.agent_url, agent_stream=self.agent_stream, |
|
768 |
region=self.region) |
|
769 |
if omit_config is not None: |
|
770 |
for key in omit_config: |
|
771 |
kwargs.pop(key.replace('-', '_'), None) |
|
772 |
update_env(self.client.env, self.temp_env_name, **kwargs) |
|
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
773 |
ssh_machines = list(machines) |
774 |
if bootstrap_host is not None: |
|
775 |
ssh_machines.append(bootstrap_host) |
|
776 |
for machine in ssh_machines: |
|
777 |
logging.info('Waiting for port 22 on %s' % machine) |
|
778 |
wait_for_port(machine, 22, timeout=120) |
|
1193.2.4
by Aaron Bentley
Switch FakeJujuClient to raise on accessing juju_home. |
779 |
jenv_path = get_jenv_path(self.client.env.juju_home, |
1162.2.18
by Aaron Bentley
Use client.juju_home for getting jenv. |
780 |
self.client.env.environment) |
1173.2.12
by Aaron Bentley
Tear down JES environments more carefully. |
781 |
torn_down = False |
1162.2.19
by Aaron Bentley
Do automatic teardown in bootstrap_context. |
782 |
if os.path.isfile(jenv_path): |
1162.2.21
by Aaron Bentley
Implement and use tear_down(try_jes=True) |
783 |
# An existing .jenv implies JES was not used, because when JES is
|
784 |
# enabled, cache.yaml is enabled.
|
|
1688.1.10
by Andrew Beach
Changed calls of tear_down for clean-up to kill_controller. Fixed a test. |
785 |
self.tear_down_client.kill_controller() |
1162.2.19
by Aaron Bentley
Do automatic teardown in bootstrap_context. |
786 |
torn_down = True |
787 |
else: |
|
1173.2.12
by Aaron Bentley
Tear down JES environments more carefully. |
788 |
jes_home = jes_home_path( |
1193.2.4
by Aaron Bentley
Switch FakeJujuClient to raise on accessing juju_home. |
789 |
self.client.env.juju_home, self.client.env.environment) |
1173.2.12
by Aaron Bentley
Tear down JES environments more carefully. |
790 |
with temp_juju_home(self.client, jes_home): |
1240.2.1
by Aaron Bentley
Support models/cache.yaml |
791 |
cache_path = self.client.get_cache_path() |
1173.2.12
by Aaron Bentley
Tear down JES environments more carefully. |
792 |
if os.path.isfile(cache_path): |
793 |
# An existing .jenv implies JES was used, because when JES
|
|
794 |
# is enabled, cache.yaml is enabled.
|
|
1711.3.2
by Aaron Bentley
Use CreateController in BootstrapManager. |
795 |
self.controller_strategy.prepare() |
1173.2.12
by Aaron Bentley
Tear down JES environments more carefully. |
796 |
torn_down = True |
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
797 |
ensure_deleted(jenv_path) |
1193.2.4
by Aaron Bentley
Switch FakeJujuClient to raise on accessing juju_home. |
798 |
with temp_bootstrap_env(self.client.env.juju_home, self.client, |
1242.3.16
by Aaron Bentley
Make agent-version omission client-dependent. |
799 |
permanent=self.permanent, set_home=False): |
1564.3.1
by Aaron Bentley
Extract common exception handling from bootstrap contexts. |
800 |
with self.handle_bootstrap_exceptions(): |
801 |
if not torn_down: |
|
1711.3.2
by Aaron Bentley
Use CreateController in BootstrapManager. |
802 |
self.controller_strategy.prepare() |
1724.1.4
by Curtis Hovey
rename lost_controller to has_controller. |
803 |
self.has_controller = True |
1564.3.1
by Aaron Bentley
Extract common exception handling from bootstrap contexts. |
804 |
yield
|
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
805 |
|
806 |
@contextmanager
|
|
1427.1.2
by Christopher Lee
Initial run of Model Migration test. Passes with current charm. |
807 |
def existing_bootstrap_context(self, machines, omit_config=None): |
1427.2.6
by Christopher Lee
Improve docstrings. |
808 |
""" Context for bootstrapping a state server that shares the
|
809 |
environment with an existing bootstrap environment.
|
|
810 |
||
811 |
Using this context makes it possible to boot multiple simultaneous
|
|
812 |
environments that share a JUJU_HOME.
|
|
1427.1.2
by Christopher Lee
Initial run of Model Migration test. Passes with current charm. |
813 |
|
814 |
"""
|
|
815 |
bootstrap_host = self.known_hosts.get('0') |
|
816 |
kwargs = dict( |
|
817 |
series=self.series, bootstrap_host=bootstrap_host, |
|
818 |
agent_url=self.agent_url, agent_stream=self.agent_stream, |
|
819 |
region=self.region) |
|
820 |
if omit_config is not None: |
|
821 |
for key in omit_config: |
|
822 |
kwargs.pop(key.replace('-', '_'), None) |
|
823 |
update_env(self.client.env, self.temp_env_name, **kwargs) |
|
824 |
ssh_machines = list(machines) |
|
825 |
if bootstrap_host is not None: |
|
826 |
ssh_machines.append(bootstrap_host) |
|
827 |
for machine in ssh_machines: |
|
828 |
logging.info('Waiting for port 22 on %s' % machine) |
|
829 |
wait_for_port(machine, 22, timeout=120) |
|
830 |
||
1564.3.1
by Aaron Bentley
Extract common exception handling from bootstrap contexts. |
831 |
with self.handle_bootstrap_exceptions(): |
832 |
yield
|
|
833 |
||
834 |
@contextmanager
|
|
835 |
def handle_bootstrap_exceptions(self): |
|
1564.3.3
by Aaron Bentley
Add docs. |
836 |
"""If an exception is raised during bootstrap, handle it.
|
837 |
||
838 |
Log the exception, re-raise as a LoggedException.
|
|
839 |
Copy logs for the bootstrap host
|
|
840 |
Tear down. (self.keep_env is ignored.)
|
|
841 |
"""
|
|
1427.1.2
by Christopher Lee
Initial run of Model Migration test. Passes with current charm. |
842 |
try: |
843 |
# If an exception is raised that indicates an error, log it
|
|
844 |
# before tearing down so that the error is closely tied to
|
|
845 |
# the failed operation.
|
|
1735.1.1
by Martin Packman
New utility.logged_exception factored out from deploy_stack |
846 |
with logged_exception(logging): |
847 |
yield
|
|
1427.1.2
by Christopher Lee
Initial run of Model Migration test. Passes with current charm. |
848 |
except: |
849 |
# If run from a windows machine may not have ssh to get
|
|
850 |
# logs
|
|
1564.3.1
by Aaron Bentley
Extract common exception handling from bootstrap contexts. |
851 |
with self.client.ignore_soft_deadline(): |
852 |
with self.tear_down_client.ignore_soft_deadline(): |
|
853 |
if self.bootstrap_host is not None and _can_run_ssh(): |
|
854 |
remote = remote_from_address(self.bootstrap_host, |
|
855 |
series=self.series) |
|
856 |
copy_remote_logs(remote, self.log_dir) |
|
857 |
archive_logs(self.log_dir) |
|
1711.3.2
by Aaron Bentley
Use CreateController in BootstrapManager. |
858 |
self.controller_strategy.prepare() |
1427.1.2
by Christopher Lee
Initial run of Model Migration test. Passes with current charm. |
859 |
raise
|
860 |
||
861 |
@contextmanager
|
|
1173.2.3
by Aaron Bentley
runtime_context doesn't take bootstrap_host as a parameter. |
862 |
def runtime_context(self, addable_machines): |
1162.2.8
by Aaron Bentley
Update docs. |
863 |
"""Context for running non-bootstrap operations.
|
864 |
||
865 |
If any manual machines need to be added, they will be added before
|
|
866 |
control is yielded.
|
|
867 |
"""
|
|
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
868 |
try: |
1735.1.1
by Martin Packman
New utility.logged_exception factored out from deploy_stack |
869 |
with logged_exception(logging): |
1191.2.1
by Curtis Hovey
Always add addable_machines in runtime_context. |
870 |
if len(self.known_hosts) == 0: |
1711.3.2
by Aaron Bentley
Use CreateController in BootstrapManager. |
871 |
self.known_hosts.update( |
872 |
self.controller_strategy.get_hosts()) |
|
1191.2.1
by Curtis Hovey
Always add addable_machines in runtime_context. |
873 |
if addable_machines is not None: |
874 |
self.client.add_ssh_machines(addable_machines) |
|
1173.2.3
by Aaron Bentley
runtime_context doesn't take bootstrap_host as a parameter. |
875 |
yield
|
1386.1.1
by Martin Packman
Propogate errors from show-status in BootstrapManager |
876 |
except: |
1724.1.5
by Curtis Hovey
revised doc |
877 |
if self.has_controller: |
878 |
safe_print_status(self.client) |
|
879 |
else: |
|
880 |
logging.info("Client lost controller, not calling status.") |
|
1386.1.1
by Martin Packman
Propogate errors from show-status in BootstrapManager |
881 |
raise
|
882 |
else: |
|
1564.2.6
by Aaron Bentley
Ignore soft deadlines for tearing down runtime_context. |
883 |
with self.client.ignore_soft_deadline(): |
884 |
self.client.list_controllers() |
|
885 |
self.client.list_models() |
|
886 |
for m_client in self.client.iter_model_clients(): |
|
887 |
m_client.show_status() |
|
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
888 |
finally: |
1564.2.6
by Aaron Bentley
Ignore soft deadlines for tearing down runtime_context. |
889 |
with self.client.ignore_soft_deadline(): |
1564.2.9
by Aaron Bentley
Check runtime_context with tear_down_client. |
890 |
with self.tear_down_client.ignore_soft_deadline(): |
891 |
try: |
|
892 |
self.dump_all_logs() |
|
893 |
except KeyboardInterrupt: |
|
894 |
pass
|
|
895 |
if not self.keep_env: |
|
896 |
self.tear_down(self.jes_enabled) |
|
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
897 |
|
1543.1.2
by Martin Packman
Doc and comments from review by abentley |
898 |
# GZ 2016-08-11: Should this method be elsewhere to avoid poking backend?
|
1440.1.1
by Aaron Bentley
Fix log dumping tests with relative imports. |
899 |
def _should_dump(self): |
1440.1.2
by Aaron Bentley
Fix cases where dumping makes sense. |
900 |
return not isinstance(self.client._backend, FakeBackend) |
1440.1.1
by Aaron Bentley
Fix log dumping tests with relative imports. |
901 |
|
1485.6.14
by Christopher Lee
Keep a running storage of the logs between runs. |
902 |
def dump_all_logs(self, patch_dir=None): |
1440.1.1
by Aaron Bentley
Fix log dumping tests with relative imports. |
903 |
"""Dump logs for all models in the bootstrapped controller."""
|
1315.2.8
by Aaron Bentley
Dump logs for all models, including on JES. |
904 |
# This is accurate because we bootstrapped self.client. It might not
|
905 |
# be accurate for a model created by create_environment.
|
|
1440.1.1
by Aaron Bentley
Fix log dumping tests with relative imports. |
906 |
if not self._should_dump(): |
907 |
return
|
|
1493.1.1
by Martin
Rename methods and variables refering to admin model to new term controller model |
908 |
controller_client = self.client.get_controller_client() |
1315.2.8
by Aaron Bentley
Dump logs for all models, including on JES. |
909 |
if not self.jes_enabled: |
910 |
clients = [self.client] |
|
911 |
else: |
|
1315.2.16
by Aaron Bentley
Make iteration support more robust. |
912 |
try: |
913 |
clients = list(self.client.iter_model_clients()) |
|
914 |
except Exception: |
|
1315.2.17
by Aaron Bentley
Add explanation. |
915 |
# Even if the controller is unreachable, we may still be able
|
1493.1.1
by Martin
Rename methods and variables refering to admin model to new term controller model |
916 |
# to gather some logs. The controller_client and self.client
|
917 |
# instances are all we have knowledge of.
|
|
918 |
clients = [controller_client] |
|
919 |
if self.client is not controller_client: |
|
1315.2.16
by Aaron Bentley
Make iteration support more robust. |
920 |
clients.append(self.client) |
1315.2.8
by Aaron Bentley
Dump logs for all models, including on JES. |
921 |
for client in clients: |
1647.1.3
by Aaron Bentley
Ignore soft deadline when dumping logs. |
922 |
with client.ignore_soft_deadline(): |
923 |
if client.env.environment == controller_client.env.environment: |
|
924 |
known_hosts = self.known_hosts |
|
925 |
if self.jes_enabled: |
|
926 |
runtime_config = self.client.get_cache_path() |
|
927 |
else: |
|
928 |
runtime_config = get_jenv_path( |
|
929 |
self.client.env.juju_home, |
|
930 |
self.client.env.environment) |
|
1315.2.8
by Aaron Bentley
Dump logs for all models, including on JES. |
931 |
else: |
1647.1.3
by Aaron Bentley
Ignore soft deadline when dumping logs. |
932 |
known_hosts = {} |
933 |
runtime_config = None |
|
934 |
artifacts_dir = os.path.join(self.log_dir, |
|
935 |
client.env.environment) |
|
936 |
os.mkdir(artifacts_dir) |
|
937 |
dump_env_logs_known_hosts( |
|
938 |
client, artifacts_dir, runtime_config, known_hosts) |
|
1315.2.8
by Aaron Bentley
Dump logs for all models, including on JES. |
939 |
|
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
940 |
@contextmanager
|
941 |
def top_context(self): |
|
1162.2.8
by Aaron Bentley
Update docs. |
942 |
"""Context for running all juju operations in."""
|
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
943 |
with self.maas_machines() as machines: |
1173.2.6
by Aaron Bentley
aws_machines doesn't yield bootstrap_host. |
944 |
with self.aws_machines() as new_machines: |
1629.1.1
by Aaron Bentley
Move log dump to top_context, skip if no log_dir. |
945 |
try: |
946 |
yield machines + new_machines |
|
947 |
finally: |
|
948 |
# This is not done in dump_all_logs because it should be
|
|
949 |
# done after tear down.
|
|
950 |
if self.log_dir is not None: |
|
951 |
dump_juju_timings(self.client, self.log_dir) |
|
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
952 |
|
953 |
@contextmanager
|
|
1614.1.3
by Andrew Beach
Made the adjustements to bootstrap_manage, but can't get passing tests for them. |
954 |
def booted_context(self, upload_tools, **kwargs): |
1162.2.8
by Aaron Bentley
Update docs. |
955 |
"""Create a temporary environment in a context manager to run tests in.
|
956 |
||
957 |
Bootstrap a new environment from a temporary config that is suitable
|
|
958 |
to run tests in. Logs will be collected from the machines. The
|
|
959 |
environment will be destroyed when the test completes or there is an
|
|
960 |
unrecoverable error.
|
|
961 |
||
962 |
The temporary environment is created by updating a EnvJujuClient's
|
|
963 |
config with series, agent_url, agent_stream.
|
|
964 |
||
965 |
:param upload_tools: False or True to upload the local agent instead
|
|
966 |
of using streams.
|
|
1614.1.3
by Andrew Beach
Made the adjustements to bootstrap_manage, but can't get passing tests for them. |
967 |
:param **kwargs: All remaining keyword arguments are passed to the
|
968 |
client's bootstrap.
|
|
1162.2.8
by Aaron Bentley
Update docs. |
969 |
"""
|
1211.2.5
by Aaron Bentley
LoggedException in BootstrapManager, convert to sys.exit in booted_context |
970 |
try: |
971 |
with self.top_context() as machines: |
|
1242.3.7
by Aaron Bentley
BootstrapManager support for bootstrap option. |
972 |
with self.bootstrap_context( |
1242.3.18
by Aaron Bentley
Rename bootstrap_supports to bootstrap_replaces. |
973 |
machines, omit_config=self.client.bootstrap_replaces): |
1711.3.2
by Aaron Bentley
Use CreateController in BootstrapManager. |
974 |
self.controller_strategy.create_initial_model( |
975 |
upload_tools, self.series, kwargs) |
|
1211.2.5
by Aaron Bentley
LoggedException in BootstrapManager, convert to sys.exit in booted_context |
976 |
with self.runtime_context(machines): |
1449.2.1
by Curtis Hovey
Fix list-models and show the state of the env. |
977 |
self.client.list_controllers() |
978 |
self.client.list_models() |
|
1449.2.6
by Curtis Hovey
show_status for all models. |
979 |
for m_client in self.client.iter_model_clients(): |
980 |
m_client.show_status() |
|
1211.2.5
by Aaron Bentley
LoggedException in BootstrapManager, convert to sys.exit in booted_context |
981 |
yield machines |
1704.1.14
by Andrew Beach
Removed a bit of debugging code that krept in. |
982 |
except LoggedException: |
1211.2.5
by Aaron Bentley
LoggedException in BootstrapManager, convert to sys.exit in booted_context |
983 |
sys.exit(1) |
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
984 |
|
1427.1.2
by Christopher Lee
Initial run of Model Migration test. Passes with current charm. |
985 |
@contextmanager
|
1614.1.3
by Andrew Beach
Made the adjustements to bootstrap_manage, but can't get passing tests for them. |
986 |
def existing_booted_context(self, upload_tools, **kwargs): |
1427.1.2
by Christopher Lee
Initial run of Model Migration test. Passes with current charm. |
987 |
try: |
988 |
with self.top_context() as machines: |
|
989 |
# Existing does less things as there is no pre-cleanup needed.
|
|
990 |
with self.existing_bootstrap_context( |
|
991 |
machines, omit_config=self.client.bootstrap_replaces): |
|
992 |
self.client.bootstrap( |
|
1614.1.1
by Andrew Beach
Saving some changes that make calls to client.bootstrap more robust so I don't have to worry about loosing them. |
993 |
upload_tools=upload_tools, |
1614.1.3
by Andrew Beach
Made the adjustements to bootstrap_manage, but can't get passing tests for them. |
994 |
bootstrap_series=self.series, |
995 |
**kwargs) |
|
1427.1.2
by Christopher Lee
Initial run of Model Migration test. Passes with current charm. |
996 |
with self.runtime_context(machines): |
997 |
yield machines |
|
998 |
except LoggedException: |
|
999 |
sys.exit(1) |
|
1000 |
||
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
1001 |
|
925.1.2
by Aaron Bentley
Extract boot_context. |
1002 |
@contextmanager
|
1024.1.5
by Curtis Hovey
Use args.temp_env_name instead of args.job_name to be clear about the purpose. |
1003 |
def boot_context(temp_env_name, client, bootstrap_host, machines, series, |
1044.1.9
by Aaron Bentley
Update and add tests. |
1004 |
agent_url, agent_stream, log_dir, keep_env, upload_tools, |
1201.1.1
by Aaron Bentley
Ensure that permanent is always True when jes_enabled is True. |
1005 |
region=None): |
1028.2.7
by Curtis Hovey
Added docstrings. |
1006 |
"""Create a temporary environment in a context manager to run tests in.
|
1007 |
||
1008 |
Bootstrap a new environment from a temporary config that is suitable to
|
|
1009 |
run tests in. Logs will be collected from the machines. The environment
|
|
1010 |
will be destroyed when the test completes or there is an unrecoverable
|
|
1011 |
error.
|
|
1012 |
||
1028.2.8
by Curtis Hovey
Revised docstrings. |
1013 |
The temporary environment is created by updating a EnvJujuClient's config
|
1028.2.7
by Curtis Hovey
Added docstrings. |
1014 |
with series, agent_url, agent_stream.
|
1015 |
||
1028.2.8
by Curtis Hovey
Revised docstrings. |
1016 |
:param temp_env_name: a unique name for the juju env, such as a Jenkins
|
1028.2.7
by Curtis Hovey
Added docstrings. |
1017 |
job name.
|
1018 |
:param client: an EnvJujuClient.
|
|
1019 |
:param bootstrap_host: None, or the address of a manual or MAAS host to
|
|
1020 |
bootstrap on.
|
|
1028.2.8
by Curtis Hovey
Revised docstrings. |
1021 |
:param machine: [] or a list of machines to use add to a manual env
|
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
1022 |
before deploying services. This is mutated to indicate all machines,
|
1023 |
including new instances, that have been manually added.
|
|
1028.2.7
by Curtis Hovey
Added docstrings. |
1024 |
:param series: None or the default-series for the temp config.
|
1025 |
:param agent_url: None or the agent-metadata-url for the temp config.
|
|
1026 |
:param agent_stream: None or the agent-stream for the temp config.
|
|
1027 |
:param log_dir: The path to the directory to store logs.
|
|
1028.2.8
by Curtis Hovey
Revised docstrings. |
1028 |
:param keep_env: False or True to not destroy the environment and keep
|
1028.2.7
by Curtis Hovey
Added docstrings. |
1029 |
it alive to do an autopsy.
|
1028.2.8
by Curtis Hovey
Revised docstrings. |
1030 |
:param upload_tools: False or True to upload the local agent instead of
|
1028.2.7
by Curtis Hovey
Added docstrings. |
1031 |
using streams.
|
1032 |
"""
|
|
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
1033 |
jes_enabled = client.is_jes_enabled() |
1034 |
bs_manager = BootstrapManager( |
|
1162.2.24
by Aaron Bentley
Use tear_down_client for teardown. |
1035 |
temp_env_name, client, client, bootstrap_host, machines, series, |
1201.1.1
by Aaron Bentley
Ensure that permanent is always True when jes_enabled is True. |
1036 |
agent_url, agent_stream, region, log_dir, keep_env, |
1037 |
permanent=jes_enabled, jes_enabled=jes_enabled) |
|
1162.2.1
by Aaron Bentley
Extract BootstrapManager. |
1038 |
with bs_manager.booted_context(upload_tools) as new_machines: |
1039 |
machines[:] = new_machines |
|
1040 |
yield
|
|
379.1.1
by Aaron Bentley
Move portions of deploy job to Python. |
1041 |
|
1042 |
||
1345.1.5
by Seman
Deploy charm by path #2. |
1043 |
def _deploy_job(args, charm_series, series): |
1236.1.1
by Martin Packman
Refactor _deploy_job and make sane when jes is on by default |
1044 |
start_juju_path = None if args.upgrade else args.juju_bin |
925.1.2
by Aaron Bentley
Extract boot_context. |
1045 |
if sys.platform == 'win32': |
1046 |
# Ensure OpenSSH is never in the path for win tests.
|
|
1047 |
sys.path = [p for p in sys.path if 'OpenSSH' not in p] |
|
1236.1.1
by Martin Packman
Refactor _deploy_job and make sane when jes is on by default |
1048 |
# GZ 2016-01-22: When upgrading, could make sure to tear down with the
|
1049 |
# newer client instead, this will be required for major version upgrades?
|
|
1575.2.7
by Aaron Bentley
Fake merge of soft-timeouts-4 into soft-timeouts-5. |
1050 |
client = client_from_config(args.env, start_juju_path, args.debug, |
1051 |
soft_deadline=args.deadline) |
|
1236.1.1
by Martin Packman
Refactor _deploy_job and make sane when jes is on by default |
1052 |
if args.jes and not client.is_jes_enabled(): |
1044.1.9
by Aaron Bentley
Update and add tests. |
1053 |
client.enable_jes() |
1236.1.1
by Martin Packman
Refactor _deploy_job and make sane when jes is on by default |
1054 |
jes_enabled = client.is_jes_enabled() |
1711.3.10
by Aaron Bentley
Accept --controller-host to use public controller. |
1055 |
controller_strategy = make_controller_strategy(client, client, |
1056 |
args.controller_host) |
|
1162.2.2
by Aaron Bentley
Switch to direct BootstrapManager. |
1057 |
bs_manager = BootstrapManager( |
1236.1.1
by Martin Packman
Refactor _deploy_job and make sane when jes is on by default |
1058 |
args.temp_env_name, client, client, args.bootstrap_host, args.machine, |
1059 |
series, args.agent_url, args.agent_stream, args.region, args.logs, |
|
1711.3.10
by Aaron Bentley
Accept --controller-host to use public controller. |
1060 |
args.keep_env, permanent=jes_enabled, jes_enabled=jes_enabled, |
1061 |
controller_strategy=controller_strategy) |
|
1236.1.1
by Martin Packman
Refactor _deploy_job and make sane when jes is on by default |
1062 |
with bs_manager.booted_context(args.upload_tools): |
925.1.2
by Aaron Bentley
Extract boot_context. |
1063 |
if sys.platform in ('win32', 'darwin'): |
1064 |
# The win and osx client tests only verify the client
|
|
1065 |
# can bootstrap and call the state-server.
|
|
1066 |
return
|
|
1236.1.1
by Martin Packman
Refactor _deploy_job and make sane when jes is on by default |
1067 |
if args.with_chaos > 0: |
1068 |
manager = background_chaos(args.temp_env_name, client, |
|
1069 |
args.logs, args.with_chaos) |
|
1014.2.5
by John George
deploy_dummy_stack with chaos. |
1070 |
else: |
1036.1.1
by John George
Correct variable name passed to background_chaos. |
1071 |
# Create a no-op context manager, to avoid duplicate calls of
|
1072 |
# deploy_dummy_stack(), as was the case prior to this revision.
|
|
1073 |
manager = nested() |
|
1074 |
with manager: |
|
1345.1.5
by Seman
Deploy charm by path #2. |
1075 |
deploy_dummy_stack(client, charm_series) |
1169.1.1
by John George
Factor out relation check, so assess_upgrade can be re-used by run_deployer.py |
1076 |
assess_juju_relations(client) |
1345.1.5
by Seman
Deploy charm by path #2. |
1077 |
skip_juju_run = charm_series.startswith(("centos", "win")) |
1091.4.1
by James Tunnicliffe
Merged upstream |
1078 |
if not skip_juju_run: |
994.4.3
by Martin Packman
Selection of fixes needed for passing job |
1079 |
assess_juju_run(client) |
1236.1.1
by Martin Packman
Refactor _deploy_job and make sane when jes is on by default |
1080 |
if args.upgrade: |
1221.5.15
by Aaron Bentley
Use 'show-status' instead of 'status'. |
1081 |
client.show_status() |
1243
by Aaron Bentley
Fix bad arg. |
1082 |
assess_upgrade(client, args.juju_bin) |
1169.1.1
by John George
Factor out relation check, so assess_upgrade can be re-used by run_deployer.py |
1083 |
assess_juju_relations(client) |
1084 |
if not skip_juju_run: |
|
1085 |
assess_juju_run(client) |
|
925.1.2
by Aaron Bentley
Extract boot_context. |
1086 |
|
1087 |
||
1593.2.9
by Curtis Hovey
Require get_model() to be fast. |
1088 |
def safe_print_status(client): |
893.1.2
by seman.said at canonical
Added safe_print_status() to output juju status without raising exceptions |
1089 |
"""Show the output of juju status without raising exceptions."""
|
1090 |
try: |
|
1647.1.1
by Aaron Bentley
Ignore soft deadline in safe_print_status. |
1091 |
with client.ignore_soft_deadline(): |
1092 |
for m_client in client.iter_model_clients(): |
|
1093 |
m_client.show_status() |
|
893.1.2
by seman.said at canonical
Added safe_print_status() to output juju status without raising exceptions |
1094 |
except Exception as e: |
1095 |
logging.exception(e) |
|
884
by John George
Add juju-deployer test support. |
1096 |
|
1097 |
||
1452.3.7
by Curtis Hovey
Added a timeout for slow azure. |
1098 |
def wait_for_state_server_to_shutdown(host, client, instance_id, timeout=60): |
717.2.2
by Aaron Bentley
Checkpoint with assess_recovery working. |
1099 |
print_now("Waiting for port to close on %s" % host) |
1452.3.7
by Curtis Hovey
Added a timeout for slow azure. |
1100 |
wait_for_port(host, 17070, closed=True, timeout=timeout) |
717.2.2
by Aaron Bentley
Checkpoint with assess_recovery working. |
1101 |
print_now("Closed.") |
1674.1.4
by Aaron Bentley
More conversion. |
1102 |
try: |
1103 |
provider_type = client.env.provider |
|
1104 |
except NoProvider: |
|
1105 |
provider_type = None |
|
717.2.2
by Aaron Bentley
Checkpoint with assess_recovery working. |
1106 |
if provider_type == 'openstack': |
1107 |
environ = dict(os.environ) |
|
1108 |
environ.update(translate_to_env(client.env.config)) |
|
1109 |
for ignored in until_timeout(300): |
|
1110 |
output = subprocess.check_output(['nova', 'list'], env=environ) |
|
1111 |
if instance_id not in output: |
|
1112 |
print_now('{} was removed from nova list'.format(instance_id)) |
|
1113 |
break
|
|
1114 |
else: |
|
1115 |
raise Exception( |
|
1116 |
'{} was not deleted:\n{}'.format(instance_id, output)) |