diff options
author | Sam Thursfield <sam.thursfield@codethink.co.uk> | 2015-05-05 11:53:39 +0000 |
---|---|---|
committer | Baserock Gerrit <gerrit@baserock.org> | 2015-05-07 15:43:13 +0000 |
commit | 0b2b24a53316bee939d8921d8eb11254be7ce8a2 (patch) | |
tree | fdf43a078d026d954fc36a1b19eb1afef89608bb /distbuild/initiator_connection.py | |
parent | f6e36277bb06620f1f25ef10caed950fa22c1f5b (diff) | |
download | morph-0b2b24a53316bee939d8921d8eb11254be7ce8a2.tar.gz |
distbuild: Fix initiator hanging when protocol errors occur
If the initiator sends an invalid build-request message, it will now
exit with the following sort of error:
ERROR: Failed to build baserock:baserock/definitions
f2d78e9b7221bca65cba53af3f3b50d50d90628f
systems/build-system-x86_64.morph: Invalid build-request message. Check
you are using a supported version of Morph. This distbuild network uses
protocol version 2.
Previously, the controller would log an error to its log file, but it
would not send any response to the initiator so the initiator would
hang forever.
Behaviour is the same as before for the case where the initiator sends a
build-request message with the wrong protocol version: the initiator
will exit with an error message.
Change-Id: I94fdee02bc701d4a679a0261b3c46dbdf14cfcaf
Diffstat (limited to 'distbuild/initiator_connection.py')
-rw-r--r-- | distbuild/initiator_connection.py | 53 |
1 files changed, 34 insertions, 19 deletions
diff --git a/distbuild/initiator_connection.py b/distbuild/initiator_connection.py index 7fd45d4d..f0586d9d 100644 --- a/distbuild/initiator_connection.py +++ b/distbuild/initiator_connection.py @@ -100,7 +100,7 @@ class InitiatorConnection(distbuild.StateMachine): ('closing', self, _Close, None, self._close), ] self.add_transitions(spec) - + def _handle_msg(self, event_source, event): '''Handle message from initiator.''' @@ -114,25 +114,40 @@ class InitiatorConnection(distbuild.StateMachine): 'build-status': self._handle_build_status, } try: - if event.msg.get('protocol_version') != distbuild.protocol.VERSION: - msg = distbuild.message('build-failed', - # use build-failed as it is understood by older versions of - # morph; if morph is old enough (protocol_version < 1) it - # won't understand a new message and ignore it or cause the - # request to hang - id=event.msg['id'], - reason=('Protocol version mismatch between server & ' - 'initiator: distbuild network uses distbuild ' - 'protocol version %i, but client uses version %i.' - % (distbuild.protocol.VERSION, - event.msg.get('protocol_version')))) - self.jm.send(msg) - self._log_send(msg) - return - msg_handler[event.msg['type']](event) + if event.msg.get('protocol_version') == distbuild.protocol.VERSION: + msg_handler[event.msg['type']](event) + else: + response = ( + 'Protocol version mismatch between server & initiator: ' + 'distbuild network uses distbuild protocol version %i, ' + 'but client uses version %i.' % + (distbuild.protocol.VERSION, + event.msg.get('protocol_version'))) + self._refuse_build_request(event.msg, response) except (KeyError, ValueError) as ex: - logging.error('Invalid message from initiator: %s: exception %s', - event.msg, ex) + response = ( + 'Invalid build-request message. Check you are using a ' + 'supported version of Morph. This distbuild network uses ' + 'protocol version %i.' % distbuild.protocol.VERSION) + self._refuse_build_request(event.msg, response) + logging.info('Invalid message from initiator: %s: exception %r', + event.msg, ex) + + def _refuse_build_request(self, build_request_message, reason): + '''Send an error message back to the initiator. + + In order for this to be understood by all versions of Morph, we use the + 'build-failed' message. Morph initiators ignore any messages they don't + understand right now, so will hang forever without giving feedback if + we ignore the request without sending 'build-failed'. + + ''' + # If there was no 'id' in the incoming request, we send a fake one in + # the hope that initiator still does the right thing. + response_id = build_request_message.get('id', '000') + msg = distbuild.message('build-failed', id=response_id, reason=reason) + self.jm.send(msg) + self._log_send(msg) def _handle_build_request(self, event): new_id = self._idgen.next() |