~juju/ubuntu/quantal/juju/0.6

« back to all changes in this revision

Viewing changes to juju/hooks/invoker.py

  • Committer: Clint Byrum
  • Date: 2012-04-10 00:16:52 UTC
  • mfrom: (1.1.11)
  • Revision ID: clint@ubuntu.com-20120410001652-1uskc8x0fwpo0r2n
* New upstream snapshot
* d/p/fix-tests-without-aws-key.patch: Dropped as it has been
  superseded by a better upstream fix (LP: #819329)
* d/p/no-write-sample-on-help.patch: Dropped, Applied upstream.
* d/p/disable-failing-zookeeper-test.patch refreshed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
from twisted.python.failure import Failure
7
7
 
8
8
from juju import errors
 
9
from juju.state.errors import RelationStateNotFound
 
10
from juju.state.hook import RelationHookContext
9
11
 
10
12
 
11
13
class HookProtocol(protocol.ProcessProtocol):
64
66
        self._process_reason(reason, self.ended)
65
67
 
66
68
 
67
 
class FormatItems(object):
68
 
    """Wrapper to delay executing __str_ of items until formatted in log."""
69
 
    def __init__(self, items):
70
 
        self.items = items
 
69
class FormatSettingChanges(object):
 
70
    """Wrapper to delay executing __str_ of changes until written, if at all.
 
71
 
 
72
    :param list changes: Each change is a pair (`relation_ident`,
 
73
       `item`), where `item` may be an `AddedItem`, `DeletedItem`, or
 
74
       `ModifiedItem`. If `relation_ident` is None, this implies that
 
75
       it is a setting on the implied (or parent) context; it is
 
76
       sorted first and the relation_ident for the implied context is
 
77
       not logged.
 
78
    """
 
79
    def __init__(self, changes):
 
80
        self.changes = changes
71
81
 
72
82
    def __str__(self):
73
 
        items = sorted(self.items, key=lambda item: item.key)
74
 
        return "\n".join("    %s" % str(item) for item in items)
 
83
        changes = sorted(
 
84
            self.changes,
 
85
            key=lambda (relation_ident, item): (relation_ident, item.key))
 
86
        lines = []
 
87
        for relation_ident, item in changes:
 
88
            if relation_ident is None:
 
89
                lines.append("    %s" % str(item))
 
90
            else:
 
91
                lines.append("    %s on %r" % (str(item), relation_ident))
 
92
        return "\n".join(lines)
75
93
 
76
94
 
77
95
class Invoker(object):
124
142
        """
125
143
        self.environment = {}
126
144
        self._context = context
 
145
        self._relation_contexts = {}
127
146
        self._change = change
128
147
        self._client_id = client_id
129
148
        self._socket_path = socket_path
143
162
        # properly terminated with loseConnection
144
163
        self._reaper = None
145
164
 
 
165
        # Add the initial context to the relation contexts if it's in
 
166
        # fact such
 
167
        if isinstance(context, RelationHookContext):
 
168
            self._relation_contexts[context.relation_ident] = context
 
169
 
 
170
    @inlineCallbacks
 
171
    def start(self):
 
172
        """Cache relation hook contexts for all relation idents."""
 
173
        # Get all relation idents (None means "all")
 
174
        relation_idents = set((yield self.get_relation_idents(None)))
 
175
        if isinstance(self._context, RelationHookContext):
 
176
            # Exclude the parent context for being looked up as a child
 
177
            relation_idents.discard(self._context.relation_ident)
 
178
        for relation_ident in relation_idents:
 
179
            child = yield self._context.get_relation_hook_context(
 
180
                relation_ident)
 
181
            self._relation_contexts[relation_ident] = child
 
182
        self._log.debug("Cached relation hook contexts: %s" % (
 
183
                sorted(relation_idents)))
 
184
 
146
185
    @property
147
186
    def ended(self):
148
187
        return self._ended
180
219
        """Returns the hook context for the invocation."""
181
220
        return self._context
182
221
 
 
222
    def get_relation_hook_context(self, relation_ident):
 
223
        """Returns a hook context corresponding to `relation_ident`"""
 
224
        try:
 
225
            return self._relation_contexts[relation_ident]
 
226
        except KeyError:
 
227
            raise RelationStateNotFound()
 
228
 
 
229
    def get_relation_idents(self, relation_name):
 
230
        return self._context.get_relation_idents(relation_name)
 
231
 
183
232
    def validate_hook(self, hook_filename):
184
233
        """Verify that the hook_filename exists and is executable. """
185
234
        if not os.path.exists(hook_filename):
252
301
 
253
302
        # Flush context changes back to zookeeper if hook was successful.
254
303
        if result == 0 and self._context:
255
 
            relation_setting_changes = yield self._context.flush()
 
304
            relation_setting_changes = []
 
305
            for context in self._relation_contexts.itervalues():
 
306
                changes = yield context.flush()
 
307
                if changes:
 
308
                    for change in changes:
 
309
                        if context is self._context:
 
310
                            relation_setting_changes.append((None, change))
 
311
                        else:
 
312
                            # Only log relation idents for relation settings
 
313
                            # on child relation hook contexts
 
314
                            relation_setting_changes.append(
 
315
                                (context.relation_ident, change))
256
316
            if relation_setting_changes:
 
317
                if hasattr(self._context, "relation_ident"):
 
318
                    display_parent_relation_ident = " on %r" % \
 
319
                        self._context.relation_ident
 
320
                else:
 
321
                    display_parent_relation_ident = ""
257
322
                self._log.debug(
258
 
                    "Flushed values for hook %r\n%s",
 
323
                    "Flushed values for hook %r%s\n%s",
259
324
                    os.path.basename(hook),
260
 
                    FormatItems(relation_setting_changes))
 
325
                    display_parent_relation_ident,
 
326
                    FormatSettingChanges(relation_setting_changes))
261
327
 
262
328
        returnValue(result)
263
329