1
# Copyright 2011-2013 Cloudscaling Group, Inc
3
# Licensed under the Apache License, Version 2.0 (the "License"); you may
4
# not use this file except in compliance with the License. You may obtain
5
# a copy of the License at
7
# http://www.apache.org/licenses/LICENSE-2.0
9
# Unless required by applicable law or agreed to in writing, software
10
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
# License for the specific language governing permissions and limitations
16
The MatchMaker classes should except a Topic or Fanout exchange key and
17
return keys for direct exchanges, per (approximate) AMQP parlance.
23
from oslo.config import cfg
25
from ironic.openstack.common.gettextutils import _
26
from ironic.openstack.common import log as logging
27
from ironic.openstack.common.rpc import matchmaker as mm
31
# Matchmaker ring file
32
cfg.StrOpt('ringfile',
33
deprecated_name='matchmaker_ringfile',
34
deprecated_group='DEFAULT',
35
default='/etc/oslo/matchmaker_ring.json',
36
help='Matchmaker ring file (JSON)'),
40
CONF.register_opts(matchmaker_opts, 'matchmaker_ring')
41
LOG = logging.getLogger(__name__)
44
class RingExchange(mm.Exchange):
45
"""Match Maker where hosts are loaded from a static JSON formatted file.
47
__init__ takes optional ring dictionary argument, otherwise
48
loads the ringfile from CONF.mathcmaker_ringfile.
50
def __init__(self, ring=None):
51
super(RingExchange, self).__init__()
56
with open(CONF.matchmaker_ring.ringfile, 'r') as fh:
57
self.ring = json.load(fh)
60
for k in self.ring.keys():
61
self.ring0[k] = itertools.cycle(self.ring[k])
63
def _ring_has(self, key):
64
return key in self.ring0
67
class RoundRobinRingExchange(RingExchange):
68
"""A Topic Exchange based on a hashmap."""
69
def __init__(self, ring=None):
70
super(RoundRobinRingExchange, self).__init__(ring)
73
if not self._ring_has(key):
75
_("No key defining hosts for topic '%s', "
76
"see ringfile") % (key, )
79
host = next(self.ring0[key])
80
return [(key + '.' + host, host)]
83
class FanoutRingExchange(RingExchange):
84
"""Fanout Exchange based on a hashmap."""
85
def __init__(self, ring=None):
86
super(FanoutRingExchange, self).__init__(ring)
89
# Assume starts with "fanout~", strip it for lookup.
90
nkey = key.split('fanout~')[1:][0]
91
if not self._ring_has(nkey):
93
_("No key defining hosts for topic '%s', "
94
"see ringfile") % (nkey, )
97
return map(lambda x: (key + '.' + x, x), self.ring[nkey])
100
class MatchMakerRing(mm.MatchMakerBase):
101
"""Match Maker where hosts are loaded from a static hashmap."""
102
def __init__(self, ring=None):
103
super(MatchMakerRing, self).__init__()
104
self.add_binding(mm.FanoutBinding(), FanoutRingExchange(ring))
105
self.add_binding(mm.DirectBinding(), mm.DirectExchange())
106
self.add_binding(mm.TopicBinding(), RoundRobinRingExchange(ring))