4
_get_juju_home, path_join, yaml_load, ErrorExit, yaml_dump, temp_file,
8
class BaseEnvironment(object):
10
log = logging.getLogger("deployer.env")
13
def env_config_path(self):
14
jhome = _get_juju_home()
15
env_config_path = path_join(jhome, 'environments.yaml')
16
return env_config_path
18
def _check_call(self, *args, **kwargs):
19
if self.options and self.options.retry_count:
20
kwargs['max_retry'] = self.options.retry_count
21
return _check_call(*args, **kwargs)
23
def _named_env(self, params):
25
params.extend(["-e", self.name])
28
def _get_env_config(self):
29
with open(self.env_config_path) as fh:
30
config = yaml_load(fh.read())
32
if self.name not in config['environments']:
33
self.log.error("Environment %r not found", self.name)
35
return config['environments'][self.name]
37
env_name = config.get('default')
39
if len(config['environments'].keys()) == 1:
40
env_name = config['environments'].keys().pop()
42
self.log.error("Ambigious operation environment")
44
return config['environments'][env_name]
46
def _write_config(self, svc_name, config, fh):
47
fh.write(yaml_dump({svc_name: config}))
50
# def _write_config(self, svc_name, config, fh):
51
# fh.write(yaml_dump(config))
54
def _get_units_in_error(self, status=None):
57
status = self.status()
58
for s in status.get('services', {}).keys():
59
for uid, u in status['services'][s].get('units', {}).items():
60
if 'error' in u['agent-state']:
62
for uid, u in u.get('subordinates', {}).items():
63
if 'error' in u['agent-state']:
67
def deploy(self, name, charm_url,
68
repo=None, config=None,
69
constraints=None, num_units=1, force_machine=None):
70
params = self._named_env(["juju", "deploy"])
71
with temp_file() as fh:
73
fh.write(yaml_dump({name: config}))
75
params.extend(["--config", fh.name])
77
params.extend(['--constraints', constraints])
79
params.extend(["--num-units", str(num_units)])
80
if charm_url.startswith('local'):
83
params.extend(["--repository=%s" % repo])
84
if force_machine is not None:
85
params.extend["--force-machine=%d" % force_machine]
87
params.extend([charm_url, name])
89
params, self.log, "Error deploying service %r", name)
91
def terminate_machine(self, mid, wait=False):
92
"""Terminate a machine.
94
The machine can't have any running units, after removing the units or
95
destroying the service, use wait_for_units to know when its safe to
96
delete the machine (ie units have finished executing stop hooks and are
100
raise RuntimeError("Can't terminate machine 0")
101
params = self._named_env(["juju", "terminate-machine"])
105
params, self.log, "Error terminating machine %r" % mid)
107
if ("machine %s does not exist" % mid) in e.error.output:
111
def get_service_address(self, svc_name):
112
status = self.get_cli_status()
113
if svc_name not in status['services']:
114
self.log.warning("Service %s does not exist", svc_name)
116
units = status['services'][svc_name].get('units', {})
117
unit_keys = list(sorted(units.keys()))
119
return units[unit_keys[0]].get('public-address', '')
120
self.log.warning("Service %s has no units")
122
def get_cli_status(self):
123
params = self._named_env(["juju", "status"])
124
with open('/dev/null', 'w') as fh:
125
output = self._check_call(
126
params, self.log, "Error getting status, is it bootstrapped?",
128
status = yaml_load(output)