400
389
command.extend(args)
401
390
retcode, output, err = run_command(command, env=env)
402
391
command_name = " ".join(map(pipes.quote, command))
403
self.addDetail(command_name, text_content(
404
output.decode("UTF-8", "replace")))
405
self.addDetail(command_name, text_content(
406
err.decode("UTF-8", "replace")))
392
self.addDetail(command_name, text_content(output))
393
self.addDetail(command_name, text_content(err))
394
return retcode, output, err
409
396
def get_juju_status(self):
410
status_output = self._run_juju_command(["status"])
397
# Juju2 status defaults to tabular so we need to force YAML
398
_, status_output, _ = self._run_juju_command(["status", "--format=yaml"])
411
399
status = yaml.safe_load(status_output)
419
407
machines = status['machines'].values()
420
408
running_machines = [
421
409
machine for machine in machines
422
if machine.get('agent-state', '') in [
410
if machine.get('machine-status', {}).get('current', '') in [
423
411
'running', 'started']]
424
412
if len(running_machines) >= nb_machines:
428
def _wait_units_started(self, service, nb_units):
429
"""Wait until a service has at least `nb_units` units."""
416
def _wait_units_started(self, application, nb_units):
417
"""Wait until an application has at least `nb_units` units."""
431
419
status = self.get_juju_status()
433
units = status['services'][service]['units'].values()
421
units = status['services'][application]['units'].values()
436
424
started_units = [
437
425
unit for unit in units
438
if unit.get('agent-state', '') == 'started']
426
if unit.get('workload-status', {}).get('current', '') == 'active']
439
427
if len(started_units) >= nb_units:
988
976
def test_configure_juju(self):
989
977
# Proxy is currently broken: disable using the lab's proxy
990
978
# as parent for now.
991
setup_deb_proxy() # Maybe it's not broken anymore
992
979
token_str = get_token_str()
993
980
# Workaround bug 972829 (in juju precise).
994
981
server_url = MAAS_URL.replace('/MAAS', ':80/MAAS')
995
setup_juju_config(server_url, token_str, series=NODE_SERIES)
982
with tempfile.NamedTemporaryFile() as cloud_yaml:
983
# Create cloud configuration
985
server=server_url, cloud_yaml=cloud_yaml
988
retcode, _, _ = self._run_juju_command(
989
['add-cloud', 'testmaas', cloud_yaml.name]
991
self.assertThat(retcode, Equals(0))
992
retcode, list_clouds_output, _ = self._run_juju_command(
995
self.assertThat(retcode, Equals(0))
996
self.assertThat(list_clouds_output, Contains("local:testmaas"))
998
with open(os.path.expanduser(
999
'~/.local/share/juju/credentials.yaml'), mode='w', encoding='utf8') as credentials:
1000
setup_juju_authentication(oauth=token_str, credentials_yaml=credentials)
1001
retcode, list_creds_output, _ = self._run_juju_command(
1002
['list-credentials']
1004
self.assertThat(retcode, Equals(0))
1005
self.assertThat(list_creds_output, Contains("local:testmaas"))
996
1006
setup_local_dns()
998
1009
@skipIf(DO_NOT_TEST_JUJU, "Not testing juju")
1000
1010
def test_juju_bootstrap(self):
1001
1011
# Wait a bit to let all the nodes go down.
1002
1012
# XXX: rvb 2013-04-23 bug=1171418
1005
command = ['bootstrap', '--upload-tools']
1007
command = ['bootstrap']
1008
self._run_juju_command(command)
1010
@skipIf(DO_NOT_TEST_JUJU, "Not testing juju")
1012
def test_juju_bootstrapped(self):
1013
"""Wait for one machine with the Juju agent up."""
1014
self._wait_machines_running(1)
1016
@skipIf(DO_NOT_TEST_JUJU, "Not testing juju")
1017
def test_juju_deploy_mysql(self):
1019
self._run_juju_command(["set-env", "http-proxy=%s" % HTTP_PROXY])
1020
self._run_juju_command(["set-env", "https-proxy=%s" % HTTP_PROXY])
1014
# Proxy has to be set while bootstrapping
1015
with tempfile.NamedTemporaryFile() as bootstrap_config:
1016
bootstrap_config.write("""
1018
https-proxy: {proxy}""".format(proxy=HTTP_PROXY).encode('utf8'))
1019
bootstrap_config.file.flush()
1020
retcode, _, _ = self._run_juju_command([
1021
'bootstrap', 'autopkgtest', 'testmaas', '--upload-tools',
1022
'--config={config}'.format(config=bootstrap_config.name)
1024
self.assertThat(retcode, Equals(0))
1026
@skipIf(DO_NOT_TEST_JUJU, "Not testing juju")
1027
def test_juju_deploy_postgresql(self):
1028
# Deploy postgresql.
1021
1029
env = os.environ.copy()
1022
1030
env['http_proxy'] = HTTP_PROXY
1023
1031
env['https_proxy'] = HTTP_PROXY
1024
self._run_juju_command(["deploy", "mysql"], env=env)
1025
self._wait_machines_running(2)
1026
self._wait_units_started('mysql', 1)
1032
retcode, _, _ = self._run_juju_command(["deploy", "postgresql"], env=env)
1033
self.assertThat(retcode, Equals(0))
1034
self._wait_machines_running(1)
1035
self._wait_units_started('postgresql', 1)
1028
1037
nb_of_deployed_machines = 2
1030
1040
@skipIf(DO_NOT_TEST_JUJU, "Not testing juju")
1032
1041
def test_machines_deployed(self):
1033
allocated_machines = self._wait_machines(
1042
deployed_machines = self._wait_machines(
1034
1043
NODE_STATUS.DEPLOYED, num_expected=self.nb_of_deployed_machines)
1036
"nodes=%s" % node['system_id']
1037
for node in allocated_machines
1039
output, err = self._run_maas_cli(
1040
["nodes", "deployment-status"] + params)
1041
deployment_statuses = loads(output).values()
1043
["Deployed"] * self.nb_of_deployed_machines, deployment_statuses)
1044
for machine in deployed_machines:
1045
self.assertThat(machine.get('status_name', ''), Equals('Deployed'))
1045
1048
@skipIf(DO_NOT_TEST_JUJU, "Not testing juju")
1047
def test_static_ip_addresses(self):
1048
# Make sure the deployed machines have addresses in the static range.
1049
def test_ip_addresses_not_in_dynamic_range(self):
1050
# Make sure the deployed machines have addresses in the dynamic range.
1049
1051
deployed_machines = self._wait_machines(
1050
1052
NODE_STATUS.DEPLOYED, num_expected=self.nb_of_deployed_machines)
1051
1053
for deployed_machine in deployed_machines:
1052
1054
ips = [IPAddress(ip) for ip in deployed_machine['ip_addresses']]
1053
1055
ip_range = IPRange(
1054
REGION_DHCP_CONFIG['static_ip_range_low'],
1055
REGION_DHCP_CONFIG['static_ip_range_high'])
1059
"The IP addresses of the deployed nodes are not in the "
1060
"cluster interface's static range.")
1056
REGION_DHCP_CONFIG['ip_range_low'],
1057
REGION_DHCP_CONFIG['ip_range_high'])
1059
self.assertThat(ip_range, Not(Contains(ip)))
1063
1062
def dump_database(cls):