Test Failed
Push — master ( 626f66...289d9e )
by Tomaz
01:52
created

st2common/st2common/services/coordination.py (8 issues)

Labels
Severity
1
# Licensed to the StackStorm, Inc ('StackStorm') under one or more
0 ignored issues
show
There seems to be a cyclic import (st2common.models.db.liveaction -> st2common.util.action_db -> st2common.persistence.liveaction).

Cyclic imports may cause partly loaded modules to be returned. This might lead to unexpected runtime behavior which is hard to debug.

Loading history...
There seems to be a cyclic import (st2common.models.api.base -> st2common.util.schema -> st2common.util.action_db -> st2common.persistence.liveaction -> st2common.persistence.base -> st2common.transport.reactor -> st2common.models.api.trace).

Cyclic imports may cause partly loaded modules to be returned. This might lead to unexpected runtime behavior which is hard to debug.

Loading history...
There seems to be a cyclic import (st2common.models.db.action -> st2common.models.db.liveaction -> st2common.util.action_db -> st2common.persistence.action).

Cyclic imports may cause partly loaded modules to be returned. This might lead to unexpected runtime behavior which is hard to debug.

Loading history...
There seems to be a cyclic import (st2common.models.api.base -> st2common.util.schema -> st2common.util.action_db -> st2common.persistence.action -> st2common.persistence.actionalias -> st2common.persistence.base -> st2common.transport.reactor -> st2common.models.api.trace).

Cyclic imports may cause partly loaded modules to be returned. This might lead to unexpected runtime behavior which is hard to debug.

Loading history...
There seems to be a cyclic import (st2common.models.api.base -> st2common.util.schema -> st2common.util.action_db -> st2common.persistence.runner -> st2common.persistence.base -> st2common.transport.reactor -> st2common.models.api.trace).

Cyclic imports may cause partly loaded modules to be returned. This might lead to unexpected runtime behavior which is hard to debug.

Loading history...
There seems to be a cyclic import (st2common.models.api.base -> st2common.util.schema -> st2common.util.action_db -> st2common.persistence.liveaction -> st2common.transport -> st2common.transport.reactor -> st2common.models.api.trace).

Cyclic imports may cause partly loaded modules to be returned. This might lead to unexpected runtime behavior which is hard to debug.

Loading history...
There seems to be a cyclic import (st2common.models.api.base -> st2common.util.schema -> st2common.util.action_db -> st2common.persistence.action -> st2common.persistence.execution -> st2common.transport -> st2common.transport.reactor -> st2common.models.api.trace).

Cyclic imports may cause partly loaded modules to be returned. This might lead to unexpected runtime behavior which is hard to debug.

Loading history...
There seems to be a cyclic import (st2common.models.api.base -> st2common.util.schema -> st2common.util.action_db -> st2common.persistence.action -> st2common.persistence.executionstate -> st2common.transport -> st2common.transport.reactor -> st2common.models.api.trace).

Cyclic imports may cause partly loaded modules to be returned. This might lead to unexpected runtime behavior which is hard to debug.

Loading history...
2
# contributor license agreements.  See the NOTICE file distributed with
3
# this work for additional information regarding copyright ownership.
4
# The ASF licenses this file to You under the Apache License, Version 2.0
5
# (the "License"); you may not use this file except in compliance with
6
# the License.  You may obtain a copy of the License at
7
#
8
#     http://www.apache.org/licenses/LICENSE-2.0
9
#
10
# Unless required by applicable law or agreed to in writing, software
11
# distributed under the License is distributed on an "AS IS" BASIS,
12
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
# See the License for the specific language governing permissions and
14
# limitations under the License.
15
16
from __future__ import absolute_import
17
18
import six
19
from oslo_config import cfg
20
from tooz import coordination
21
from tooz import locking
22
23
from st2common import log as logging
24
from st2common.util import system_info
25
26
27
LOG = logging.getLogger(__name__)
28
29
COORDINATOR = None
30
31
__all__ = [
32
    'configured',
33
    'get_coordinator',
34
35
    'coordinator_setup',
36
    'coordinator_teardown'
37
]
38
39
40
class NoOpLock(locking.Lock):
41
    def __init__(self, name='noop'):
42
        super(NoOpLock, self).__init__(name=name)
43
44
    def acquire(self, blocking=True):
45
        return True
46
47
    def release(self):
48
        return True
49
50
    def heartbeat(self):
51
        return True
52
53
54
class NoOpDriver(coordination.CoordinationDriver):
55
    """
56
    Tooz driver where each operation is a no-op.
57
58
    This driver is used if coordination service is not configured.
59
    """
60
61
    def __init__(self, member_id, parsed_url=None, options=None):
62
        super(NoOpDriver, self).__init__(member_id, parsed_url, options)
63
64
    def watch_join_group(self, group_id, callback):
65
        self._hooks_join_group[group_id].append(callback)
66
67
    def unwatch_join_group(self, group_id, callback):
68
        return None
69
70
    def watch_leave_group(self, group_id, callback):
71
        return None
72
73
    def unwatch_leave_group(self, group_id, callback):
74
        return None
75
76
    def watch_elected_as_leader(self, group_id, callback):
77
        return None
78
79
    def unwatch_elected_as_leader(self, group_id, callback):
80
        return None
81
82
    @staticmethod
83
    def stand_down_group_leader(group_id):
84
        return None
85
86
    @staticmethod
87
    def create_group(group_id):
88
        return None
89
90
    @staticmethod
91
    def get_groups():
92
        return None
93
94
    @staticmethod
95
    def join_group(group_id, capabilities=''):
96
        return None
97
98
    @staticmethod
99
    def leave_group(group_id):
100
        return None
101
102
    @staticmethod
103
    def delete_group(group_id):
104
        return None
105
106
    @staticmethod
107
    def get_members(group_id):
108
        return None
109
110
    @staticmethod
111
    def get_member_capabilities(group_id, member_id):
112
        return None
113
114
    @staticmethod
115
    def update_capabilities(group_id, capabilities):
116
        return None
117
118
    @staticmethod
119
    def get_leader(group_id):
120
        return None
121
122
    @staticmethod
123
    def get_lock(name):
124
        return NoOpLock(name='noop')
125
126
127
def configured():
128
    """
129
    Return True if the coordination service is properly configured.
130
131
    :rtype: ``bool``
132
    """
133
    backend_configured = cfg.CONF.coordination.url is not None
134
    mock_backend = backend_configured and (cfg.CONF.coordination.url.startswith('zake') or
135
                                           cfg.CONF.coordination.url.startswith('file'))
136
137
    return backend_configured and not mock_backend
138
139
140
def coordinator_setup():
141
    """
142
    Sets up the client for the coordination service.
143
144
    URL examples for connection:
145
        zake://
146
        file:///tmp
147
        redis://username:password@host:port
148
        mysql://username:password@host:port/dbname
149
    """
150
    url = cfg.CONF.coordination.url
151
    lock_timeout = cfg.CONF.coordination.lock_timeout
152
    proc_info = system_info.get_process_info()
153
    member_id = six.b('%s_%d' % (proc_info['hostname'], proc_info['pid']))
154
155
    if url:
156
        coordinator = coordination.get_coordinator(url, member_id, lock_timeout=lock_timeout)
157
    else:
158
        # Use a no-op backend
159
        # Note: We don't use tooz to obtain a reference since for this to work we would need to
160
        # register a plugin inside setup.py entry_point and use python setup.py develop for tests
161
        # to work
162
        coordinator = NoOpDriver(member_id)
163
164
    coordinator.start()
165
    return coordinator
166
167
168
def coordinator_teardown(coordinator):
169
    coordinator.stop()
170
171
172
def get_coordinator():
173
    global COORDINATOR
174
175
    if not configured():
176
        LOG.warn('Coordination backend is not configured. Code paths which use coordination '
177
                 'service will use best effort approach and race conditions are possible.')
178
179
    if not COORDINATOR:
180
        COORDINATOR = coordinator_setup()
181
182
    return COORDINATOR
183