28
34
that is specifically for use by OpenStack charms.
31
def __init__(self, series=None, openstack=None, source=None, stable=True):
37
def __init__(self, series=None, openstack=None, source=None,
38
stable=True, log_level=DEBUG):
32
39
"""Initialize the deployment environment."""
33
40
super(OpenStackAmuletDeployment, self).__init__(series)
41
self.log = self.get_logger(level=log_level)
42
self.log.info('OpenStackAmuletDeployment: init')
34
43
self.openstack = openstack
35
44
self.source = source
36
45
self.stable = stable
39
48
self.current_next = "trusty"
50
def get_logger(self, name="deployment-logger", level=logging.DEBUG):
51
"""Get a logger object that will log to stdout."""
53
logger = log.getLogger(name)
54
fmt = log.Formatter("%(asctime)s %(funcName)s "
55
"%(levelname)s: %(message)s")
57
handler = log.StreamHandler(stream=sys.stdout)
58
handler.setLevel(level)
59
handler.setFormatter(fmt)
61
logger.addHandler(handler)
62
logger.setLevel(level)
41
66
def _determine_branch_locations(self, other_services):
42
67
"""Determine the branch locations for the other services.
95
124
'ceph-osd', 'ceph-radosgw']
97
126
# Charms which can not use openstack-origin, ie. many subordinates
98
no_origin = ['cinder-ceph', 'hacluster', 'neutron-openvswitch', 'nrpe']
127
no_origin = ['cinder-ceph', 'hacluster', 'neutron-openvswitch', 'nrpe',
128
'openvswitch-odl', 'neutron-api-odl', 'odl-controller']
100
130
if self.openstack:
101
131
for svc in services:
112
142
def _configure_services(self, configs):
113
143
"""Configure all of the services."""
144
self.log.info('OpenStackAmuletDeployment: configure services')
114
145
for service, config in six.iteritems(configs):
115
146
self.d.configure(service, config)
148
def _auto_wait_for_status(self, message=None, exclude_services=None,
149
include_only=None, timeout=1800):
150
"""Wait for all units to have a specific extended status, except
151
for any defined as excluded. Unless specified via message, any
152
status containing any case of 'ready' will be considered a match.
154
Examples of message usage:
156
Wait for all unit status to CONTAIN any case of 'ready' or 'ok':
157
message = re.compile('.*ready.*|.*ok.*', re.IGNORECASE)
159
Wait for all units to reach this status (exact match):
160
message = re.compile('^Unit is ready and clustered$')
162
Wait for all units to reach any one of these (exact match):
163
message = re.compile('Unit is ready|OK|Ready')
165
Wait for at least one unit to reach this status (exact match):
168
See Amulet's sentry.wait_for_messages() for message usage detail.
169
https://github.com/juju/amulet/blob/master/amulet/sentry.py
171
:param message: Expected status match
172
:param exclude_services: List of juju service names to ignore,
173
not to be used in conjuction with include_only.
174
:param include_only: List of juju service names to exclusively check,
175
not to be used in conjuction with exclude_services.
176
:param timeout: Maximum time in seconds to wait for status match
177
:returns: None. Raises if timeout is hit.
179
self.log.info('Waiting for extended status on units...')
181
all_services = self.d.services.keys()
183
if exclude_services and include_only:
184
raise ValueError('exclude_services can not be used '
188
if isinstance(message, re._pattern_type):
189
match = message.pattern
193
self.log.debug('Custom extended status wait match: '
196
self.log.debug('Default extended status wait match: contains '
197
'READY (case-insensitive)')
198
message = re.compile('.*ready.*', re.IGNORECASE)
201
self.log.debug('Excluding services from extended status match: '
202
'{}'.format(exclude_services))
204
exclude_services = []
207
services = include_only
209
services = list(set(all_services) - set(exclude_services))
211
self.log.debug('Waiting up to {}s for extended status on services: '
212
'{}'.format(timeout, services))
213
service_messages = {service: message for service in services}
214
self.d.sentry.wait_for_messages(service_messages, timeout=timeout)
117
217
def _get_openstack_release(self):
118
218
"""Get openstack release.
125
225
self.precise_havana, self.precise_icehouse,
126
226
self.trusty_icehouse, self.trusty_juno, self.utopic_juno,
127
227
self.trusty_kilo, self.vivid_kilo, self.trusty_liberty,
128
self.wily_liberty) = range(12)
228
self.wily_liberty, self.trusty_mitaka,
229
self.xenial_mitaka) = range(14)
131
232
('precise', None): self.precise_essex,
137
238
('trusty', 'cloud:trusty-juno'): self.trusty_juno,
138
239
('trusty', 'cloud:trusty-kilo'): self.trusty_kilo,
139
240
('trusty', 'cloud:trusty-liberty'): self.trusty_liberty,
241
('trusty', 'cloud:trusty-mitaka'): self.trusty_mitaka,
140
242
('utopic', None): self.utopic_juno,
141
243
('vivid', None): self.vivid_kilo,
142
('wily', None): self.wily_liberty}
244
('wily', None): self.wily_liberty,
245
('xenial', None): self.xenial_mitaka}
143
246
return releases[(self.series, self.openstack)]
145
248
def _get_openstack_release_string(self):