Add support for notifications with zmq

This commit is contained in:
Liam Young 2014-09-10 17:15:07 +00:00
parent 38e8b51a2b
commit 83536bccde
10 changed files with 100 additions and 21 deletions

View File

@ -1,4 +1,4 @@
branch: lp:charm-helpers
branch: lp:~openstack-charmers/charm-helpers/0mq
destination: hooks/charmhelpers
include:
- core

View File

@ -21,6 +21,7 @@ from charmhelpers.core.hookenv import (
relation_get,
relation_ids,
related_units,
is_relation_made,
relation_set,
unit_get,
unit_private_ip,
@ -49,6 +50,9 @@ from charmhelpers.contrib.network.ip import (
get_ipv6_addr,
)
from charmhelpers.contrib.openstack.utils import (
get_matchmaker_map,
)
CA_CERT_PATH = '/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt'
@ -787,3 +791,37 @@ class SyslogContext(OSContextGenerator):
'use_syslog': config('use-syslog')
}
return ctxt
class ZeroMQContext(OSContextGenerator):
interfaces = ['zeromq-configuration']
def __call__(self):
ctxt = {}
if is_relation_made('zeromq-configuration', 'host'):
for rid in relation_ids('zeromq-configuration'):
for unit in related_units(rid):
ctxt['zmq_nonce'] = relation_get('nonce', unit, rid)
ctxt['zmq_host'] = relation_get('host', unit, rid)
return ctxt
class NotificationDriverContext(OSContextGenerator):
def __init__(self, zmq_relation='zeromq-configuration', amqp_relation='amqp'):
"""
:param zmq_relation : Name of Zeromq relation to check
"""
self.zmq_relation = zmq_relation
self.amqp_relation = amqp_relation
def __call__(self):
ctxt = {
'notifications': "False",
}
if is_relation_made(self.zmq_relation):
matchmaker_data = get_matchmaker_map()
if 'notifications-info' in matchmaker_data:
ctxt['notifications'] = "True"
elif is_relation_made(self.amqp_relation):
ctxt['notifications'] = "True"
return ctxt

View File

@ -3,15 +3,17 @@
# Common python helper functions used for OpenStack charms.
from collections import OrderedDict
import subprocess
import json
import os
import socket
import subprocess
import sys
from charmhelpers.core.hookenv import (
config,
log as juju_log,
charm_dir,
is_relation_made,
ERROR,
INFO
)
@ -70,6 +72,7 @@ SWIFT_CODENAMES = OrderedDict([
('1.13.0', 'icehouse'),
('1.12.0', 'icehouse'),
('1.11.0', 'icehouse'),
('2.0.0', 'juno'),
])
DEFAULT_LOOPBACK_SIZE = '5G'
@ -456,3 +459,11 @@ def get_hostname(address, fqdn=True):
return result
else:
return result.split('.')[0]
def get_matchmaker_map(mm_file='/etc/oslo/matchmaker_ring.json'):
mm_map = {}
if os.path.isfile(mm_file):
with open(mm_file, 'r') as f:
mm_map = json.load(f)
return mm_map

View File

@ -156,12 +156,15 @@ def hook_name():
class Config(dict):
"""A Juju charm config dictionary that can write itself to
disk (as json) and track which values have changed since
the previous hook invocation.
"""A dictionary representation of the charm's config.yaml, with some
extra features:
Do not instantiate this object directly - instead call
``hookenv.config()``
- See which values in the dictionary have changed since the previous hook.
- For values that have changed, see what the previous value was.
- Store arbitrary data for use in a later hook.
NOTE: Do not instantiate this object directly - instead call
``hookenv.config()``, which will return an instance of :class:`Config`.
Example usage::
@ -170,8 +173,8 @@ class Config(dict):
>>> config = hookenv.config()
>>> config['foo']
'bar'
>>> # store a new key/value for later use
>>> config['mykey'] = 'myval'
>>> config.save()
>>> # user runs `juju set mycharm foo=baz`
@ -188,22 +191,23 @@ class Config(dict):
>>> # keys/values that we add are preserved across hooks
>>> config['mykey']
'myval'
>>> # don't forget to save at the end of hook!
>>> config.save()
"""
CONFIG_FILE_NAME = '.juju-persistent-config'
def __init__(self, *args, **kw):
super(Config, self).__init__(*args, **kw)
self.implicit_save = True
self._prev_dict = None
self.path = os.path.join(charm_dir(), Config.CONFIG_FILE_NAME)
if os.path.exists(self.path):
self.load_previous()
def load_previous(self, path=None):
"""Load previous copy of config from disk so that current values
can be compared to previous values.
"""Load previous copy of config from disk.
In normal usage you don't need to call this method directly - it
is called automatically at object initialization.
:param path:
@ -218,8 +222,8 @@ class Config(dict):
self._prev_dict = json.load(f)
def changed(self, key):
"""Return true if the value for this key has changed since
the last save.
"""Return True if the current value for this key is different from
the previous value.
"""
if self._prev_dict is None:
@ -228,7 +232,7 @@ class Config(dict):
def previous(self, key):
"""Return previous value for this key, or None if there
is no "previous" value.
is no previous value.
"""
if self._prev_dict:
@ -238,7 +242,13 @@ class Config(dict):
def save(self):
"""Save this config to disk.
Preserves items in _prev_dict that do not exist in self.
If the charm is using the :mod:`Services Framework <services.base>`
or :meth:'@hook <Hooks.hook>' decorator, this
is called automatically at the end of successful hook execution.
Otherwise, it should be called directly by user code.
To disable automatic saves, set ``implicit_save=False`` on this
instance.
"""
if self._prev_dict:
@ -478,6 +488,9 @@ class Hooks(object):
hook_name = os.path.basename(args[0])
if hook_name in self._hooks:
self._hooks[hook_name]()
cfg = config()
if cfg.implicit_save:
cfg.save()
else:
raise UnregisteredHookError(hook_name)

View File

@ -118,6 +118,9 @@ class ServiceManager(object):
else:
self.provide_data()
self.reconfigure_services()
cfg = hookenv.config()
if cfg.implicit_save:
cfg.save()
def provide_data(self):
"""

View File

@ -92,7 +92,9 @@ CONFIG_FILES = OrderedDict([
glance_contexts.ObjectStoreContext(),
glance_contexts.HAProxyContext(),
context.SyslogContext(),
glance_contexts.LoggingConfigContext()],
glance_contexts.LoggingConfigContext(),
context.ZeroMQContext(),
context.NotificationDriverContext(),],
'services': ['glance-api']
}),
(GLANCE_API_PASTE_INI, {

View File

@ -27,6 +27,9 @@ requires:
ha:
interface: hacluster
scope: container
zeromq-configuration:
interface: zeromq-configuration
scope: container
peers:
cluster:
interface: glance-ha

View File

@ -32,9 +32,7 @@ registry_client_protocol = http
{% include "parts/rabbitmq" %}
{% if rabbitmq_host or rabbitmq_hosts -%}
notification_driver = rabbit
{% endif -%}
{% include "parts/zeromq" %}
filesystem_store_datadir = /var/lib/glance/images/

View File

@ -18,4 +18,6 @@ rabbit_port = {{ rabbit_ssl_port }}
kombu_ssl_ca_certs = {{ rabbit_ssl_ca }}
{% endif -%}
{% endif -%}
{% endif -%}
{% if notifications == 'True' -%} notification_driver = rabbit
{% endif -%}
{% endif -%}

9
templates/parts/zeromq Normal file
View File

@ -0,0 +1,9 @@
{% if zmq_host -%}
# ZeroMQ configuration (restart-nonce: {{ zmq_nonce }})
rpc_backend = zmq
rpc_zmq_matchmaker = oslo.messaging._drivers.matchmaker_ring.MatchMakerRing
rpc_zmq_host = {{ zmq_host }}
{% if notifications == 'True' -%}
notification_driver = zmq
{% endif -%}
{% endif -%}