Add several tokens to control events between resources
This commit is contained in:
parent
cfa6c7be72
commit
6451f62628
@ -24,11 +24,11 @@ Propagating events when there is no data changed
|
|||||||
|
|
||||||
Control for specifying events:
|
Control for specifying events:
|
||||||
|
|
||||||
on <emitter>.<emmiter_action> <event> <subscriber>.<subsciber_action>
|
on <emitter>.<emmiter_action> <event> <subscriber>.<subsciber_action>
|
||||||
|
|
||||||
# on mariadb.run changed keystone.run
|
on mariadb.run changed keystone.run
|
||||||
# on keystone.run changed keystone_config.run
|
on keystone.run changed keystone_config.run
|
||||||
# on keystone_config.run changed haproxy.reload
|
on keystone_config.run changed haproxy.reload
|
||||||
|
|
||||||
+---------------------+
|
+---------------------+
|
||||||
| mariadb.run |
|
| mariadb.run |
|
||||||
@ -46,13 +46,13 @@ Control for specifying events:
|
|||||||
| haproxy.reload |
|
| haproxy.reload |
|
||||||
+---------------------+
|
+---------------------+
|
||||||
|
|
||||||
<u> - <event>:<action> - <v>
|
<u>.<action> - <event> - <v>.<action>
|
||||||
|
|
||||||
When connection between several resources created - events connections should
|
When data connection between several resources created - events connections should
|
||||||
be created as well, resource a connect resource b:
|
be created as well, resource a connect resource b:
|
||||||
|
|
||||||
on a changed b reload
|
on a.run changed b.reload
|
||||||
on a removed b run
|
on a.remove changed b.run
|
||||||
|
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
Resolving cycles on a data plane
|
Resolving cycles on a data plane
|
||||||
@ -73,9 +73,9 @@ rmq.2.cluster_join, rmq.2.cluster_join
|
|||||||
|
|
||||||
Also cluster operation should happen only when rmq.cluster is changed.
|
Also cluster operation should happen only when rmq.cluster is changed.
|
||||||
|
|
||||||
on rmq.cluster changed rmq.1 cluster_create
|
on rmq.cluster changed rmq.1.cluster_create
|
||||||
on rmq.1.cluster_create changed rmq.2 cluster_join
|
on rmq.1.cluster_create changed rmq.2.cluster_join
|
||||||
on rmq.1.cluster_create changed rmq.3 cluster_join
|
on rmq.1.cluster_create changed rmq.3.cluster_join
|
||||||
|
|
||||||
+----------------------+
|
+----------------------+
|
||||||
| rmq.1.run |
|
| rmq.1.run |
|
||||||
@ -102,7 +102,7 @@ on rmq.1.cluster_create changed rmq.3 cluster_join
|
|||||||
| rmq.3.run | |
|
| rmq.3.run | |
|
||||||
+----------------------+ |
|
+----------------------+ |
|
||||||
| |
|
| |
|
||||||
| cahnged |
|
| changed |
|
||||||
v |
|
v |
|
||||||
+----------------------+ |
|
+----------------------+ |
|
||||||
| rmq.3.cluster_join | <+
|
| rmq.3.cluster_join | <+
|
||||||
@ -113,7 +113,7 @@ on rmq.1.cluster_create changed rmq.3 cluster_join
|
|||||||
---------------------------------------------------
|
---------------------------------------------------
|
||||||
Resolve cycles on a execution level
|
Resolve cycles on a execution level
|
||||||
|
|
||||||
Lets say we have 5 objects, which forms 2 pathes
|
We have 5 objects, which forms 2 pathes
|
||||||
- keystone-config -> keystone-service -> haproxy-sevice
|
- keystone-config -> keystone-service -> haproxy-sevice
|
||||||
- glance-config -> glance-service -> haproxy-service
|
- glance-config -> glance-service -> haproxy-service
|
||||||
|
|
||||||
|
0
solar/solar/events/__init__.py
Normal file
0
solar/solar/events/__init__.py
Normal file
75
solar/solar/events/control.py
Normal file
75
solar/solar/events/control.py
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
"""
|
||||||
|
Available controls:
|
||||||
|
|
||||||
|
*depends_on* implements relationship that will guarantee that depended action
|
||||||
|
on resource will be executed after parent, if parent will be executed. It means
|
||||||
|
that this control contributes only to ordering, and wont trigger any action
|
||||||
|
if dependent resource isnt changed.
|
||||||
|
|
||||||
|
depends_on:
|
||||||
|
- parent:run -> ok -> dependent:run
|
||||||
|
|
||||||
|
*react_on* - relationship which will guarantee that action on dependent resource
|
||||||
|
will be executed if parent action is going to be executed. This control will
|
||||||
|
trigger action even if no changes noticed on dependent resource.
|
||||||
|
|
||||||
|
react_on:
|
||||||
|
- parent:update -> ok -> dependent:update
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
from solar.core.log import log
|
||||||
|
|
||||||
|
|
||||||
|
EVENT = re.compile(r'\s+->\s+')
|
||||||
|
|
||||||
|
|
||||||
|
class Event(object):
|
||||||
|
|
||||||
|
def __init__(self, event):
|
||||||
|
self.parent, self.dependent, self.state = EVENT.split(event)
|
||||||
|
self.parent_node, self.parent_action = self.parent.split(':')
|
||||||
|
self.dep_node, self.dep_action = self.dependent.split(':')
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '{}({} -> {} -> {})'.format(
|
||||||
|
self.__class__.__name__,
|
||||||
|
self.parent, self.dependent, self.state)
|
||||||
|
|
||||||
|
|
||||||
|
class Dependency(Event):
|
||||||
|
|
||||||
|
def add(self, changed_resources, changes_graph):
|
||||||
|
if self.parent in changes_graph:
|
||||||
|
changes_graph.add_edge(
|
||||||
|
self.parent, self.dependent, state=self.state)
|
||||||
|
|
||||||
|
|
||||||
|
class React(Event):
|
||||||
|
|
||||||
|
def add(self, changed_resources, changes_graph):
|
||||||
|
changes_graph.add_edge(self.parent, self.dependent, state=self.state)
|
||||||
|
changed_resources.append(self.dep_node)
|
||||||
|
|
||||||
|
|
||||||
|
def build_edges(changed_resources, changes_graph, events):
|
||||||
|
"""
|
||||||
|
:param changed_resources: list of resource names that were changed
|
||||||
|
:param changes_graph: nx.DiGraph object with actions to be executed
|
||||||
|
:param events:
|
||||||
|
"""
|
||||||
|
stack = changed_resources[:]
|
||||||
|
while stack:
|
||||||
|
node = stack.pop()
|
||||||
|
events_objects = []
|
||||||
|
|
||||||
|
if node in events:
|
||||||
|
log.debug('Events %s for resource %s', events[node], node)
|
||||||
|
|
||||||
|
for e in events[node].get('react_on', ()):
|
||||||
|
React(e).add(stack, changes_graph)
|
||||||
|
for e in events[node].get('depends_on', ()):
|
||||||
|
Dependency(e).add(stack, changes_graph)
|
||||||
|
|
||||||
|
return changes_graph
|
@ -10,7 +10,7 @@ from solar import errors
|
|||||||
class RedisDB(object):
|
class RedisDB(object):
|
||||||
COLLECTIONS = Enum(
|
COLLECTIONS = Enum(
|
||||||
'Collections',
|
'Collections',
|
||||||
'connection resource state_data state_log'
|
'connection resource state_data state_log events'
|
||||||
)
|
)
|
||||||
DB = {
|
DB = {
|
||||||
'host': 'localhost',
|
'host': 'localhost',
|
||||||
|
@ -3,6 +3,7 @@ import networkx as nx
|
|||||||
from pytest import fixture
|
from pytest import fixture
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
@fixture
|
||||||
def simple():
|
def simple():
|
||||||
dg = nx.DiGraph()
|
dg = nx.DiGraph()
|
||||||
@ -10,24 +11,29 @@ def simple():
|
|||||||
dg.add_edge('keystone_config.run', 'haproxy.reload', event='changed')
|
dg.add_edge('keystone_config.run', 'haproxy.reload', event='changed')
|
||||||
return dg
|
return dg
|
||||||
|
|
||||||
|
|
||||||
def test_simple(simple):
|
def test_simple(simple):
|
||||||
nx.write_dot(simple, 'simple.dot')
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
@fixture
|
||||||
def rmq():
|
def rmq():
|
||||||
"""Example of a case when we have cycles on a data plane."""
|
"""Example of a case when we have cycles on a data plane."""
|
||||||
dg = nx.DiGraph()
|
dg = nx.DiGraph()
|
||||||
dg.add_edge('rmq.1.run', 'rmq.1.cluster_create', event='changed')
|
dg.add_edge('rmq_cluster.run', 'rmq_cluster.1.create', event='changed')
|
||||||
dg.add_edge('rmq.1.cluster_create', 'rmq.2.cluster_join', event='changed')
|
dg.add_edge('rmq_cluster.run', 'rmq_cluster.2.join', event='changed')
|
||||||
dg.add_edge('rmq.1.cluster_create', 'rmq.3.cluster_join', event='changed')
|
dg.add_edge('rmq_cluster.run', 'rmq_cluster.3.join', event='changed')
|
||||||
dg.add_edge('rmq.2.run', 'rmq.2.cluster_join', event='changed')
|
dg.add_edge('rmq.1.run', 'rmq_cluster.1.create', event='changed')
|
||||||
dg.add_edge('rmq.3.run', 'rmq.3.cluster_join', event='changed')
|
dg.add_edge('rmq.2.run', 'rmq_cluster.2.join', event='changed')
|
||||||
|
dg.add_edge('rmq.3.run', 'rmq_cluster.3.join', event='changed')
|
||||||
|
dg.add_edge('rmq_cluster.1.create', 'rmq_cluster.2.join', event='changed')
|
||||||
|
dg.add_edge('rmq_cluster.1.create', 'rmq_cluster.3.join', event='changed')
|
||||||
return dg
|
return dg
|
||||||
|
|
||||||
|
|
||||||
def test_rmq(rmq):
|
def test_rmq(rmq):
|
||||||
nx.write_dot(rmq, 'rmq.dot')
|
pass
|
||||||
|
|
||||||
|
|
||||||
@fixture
|
@fixture
|
||||||
@ -43,4 +49,4 @@ def haproxy():
|
|||||||
|
|
||||||
|
|
||||||
def test_haproxy(haproxy):
|
def test_haproxy(haproxy):
|
||||||
nx.write_dot(haproxy, 'haproxy.dot')
|
pass
|
||||||
|
Loading…
Reference in New Issue
Block a user