4
from .base import BaseAction
5
from ..errors import UnitErrors
6
from ..utils import ErrorExit
9
class Importer(BaseAction):
11
log = logging.getLogger("deployer.import")
13
def __init__(self, env, deployment, options):
14
self.options = options
16
self.deployment = deployment
19
self.log.debug("Adding units...")
20
# Add units to existing services that don't match count.
21
env_status = self.env.status()
23
for svc in self.deployment.get_services():
24
delta = (svc.num_units -
25
len(env_status['services'][svc.name].get('units', ())))
27
charm = self.deployment.get_charm_for(svc.name)
28
if charm.is_subordinate():
30
"Config specifies num units for subordinate: %s",
34
"Adding %d more units to %s" % (abs(delta), svc.name))
35
for u in self.env.add_units(svc.name, abs(delta)):
39
" Service %r does not need any more units added.",
44
self.log.debug("Getting charms...")
45
self.deployment.fetch_charms(
46
update=self.options.update_charms,
47
no_local_mods=self.options.no_local_mods)
49
# Load config overrides/includes and verify rels after we can
51
self.deployment.resolve(self.options.overrides or ())
53
def deploy_services(self):
54
self.log.info("Deploying services...")
55
env_status = self.env.status()
56
for svc in self.deployment.get_services():
57
if svc.name in env_status['services']:
59
" Service %r already deployed. Skipping" % svc.name)
62
charm = self.deployment.get_charm_for(svc.name)
64
" Deploying service %s using %s", svc.name, charm.charm_url)
68
self.deployment.repo_path,
75
self.env.expose(svc.name)
77
if self.options.deploy_delay:
78
self.log.debug(" Waiting for deploy delay")
79
time.sleep(self.options.deploy_delay)
81
def add_relations(self):
82
self.log.info("Adding relations...")
85
status = self.env.status()
88
for end_a, end_b in self.deployment.get_relations():
89
if self._rel_exists(status, end_a, end_b):
91
self.log.info(" Adding relation %s <-> %s", end_a, end_b)
92
self.env.add_relation(end_a, end_b)
94
# per the original, not sure the use case.
95
self.log.debug(" Waiting 5s before next relation")
99
def _rel_exists(self, status, end_a, end_b):
100
# Checks for a named relation on one side that matches the local
101
# endpoint and remote service.
102
(name_a, name_b, rem_a, rem_b) = (end_a, end_b, None, None)
105
name_a, rem_a = end_a.split(":", 1)
107
name_b, rem_b = end_b.split(":", 1)
109
rels_svc_a = status['services'][name_a].get('relations', {})
112
for r, related in rels_svc_a.items():
113
if name_b in related:
114
if rem_a and not r in rem_a:
122
def wait_for_units(self, ignore_error=False):
123
timeout = self.options.timeout - (time.time() - self.start_time)
125
self.log.error("Reached deployment timeout.. exiting")
128
self.env.wait_for_units(
129
int(timeout), watch=self.options.watch, no_exit=ignore_error)
135
self.start_time = time.time()
140
if self.options.branch_only:
143
self.deploy_services()
145
# Workaround api issue in juju-core, where any action takes 5s
146
# to be consistent to subsequent watch api interactions, see
147
# http://pad.lv/1203105 which will obviate this wait.
150
self.wait_for_units()
153
rels_created = self.add_relations()
155
# Wait for the units to be up before waiting for rel stability.
156
self.log.debug("Waiting for units to be started")
157
self.wait_for_units(self.options.retry_count)
159
self.log.debug("Waiting for relations %d", self.options.rel_wait)
160
time.sleep(self.options.rel_wait)
161
self.wait_for_units(self.options.retry_count)
163
if self.options.retry_count:
164
self.log.info("Looking for errors to auto-retry")
165
self.env.resolve_errors(
166
self.options.retry_count,
167
self.options.timeout - time.time() - self.start_time)