def handle_login(self, request): "Log this client in." request = request.cast_to(LoginMessage) self.account = Account.create(request['username'], request['password']) if self.auth.verify(self.account): # TODO: verify machine & type values self.machine, self.type = request['machine'], request['type'] self.namespace = request['username'] print self.address_str(), "=>", self.id if not self.tracker.assign_namespace(self): yield gen.Task(self.stream.write, ResponseMessage.error( request.id, reason="Machine of name %r already connected." % self.machine, code=ErrorCodes.MACHINE_CONFLICT )) self.close() raise StopIteration msg = ResponseMessage.success(request.id) yield gen.Task(self.stream.write, msg) print self.id, '<-', msg self.process_request() else: self.fail(request.id, reason='Invalid username or password', code=ErrorCodes.BAD_AUTH, close_stream=False)
def handle_login(self, request): "Log this client in." request = request.cast_to(LoginMessage) self.account = Account.create(request['username'], request['password']) if self.auth.verify(self.account): # TODO: verify machine & type values self.machine, self.type = request['machine'], request['type'] self.namespace = request['username'] print self.address_str(), "=>", self.id if not self.tracker.assign_namespace(self): yield gen.Task( self.stream.write, ResponseMessage.error( request.id, reason="Machine of name %r already connected." % self.machine, code=ErrorCodes.MACHINE_CONFLICT)) self.close() raise StopIteration msg = ResponseMessage.success(request.id) yield gen.Task(self.stream.write, msg) print self.id, '<-', msg self.process_request() else: self.fail(request.id, reason='Invalid username or password', code=ErrorCodes.BAD_AUTH, close_stream=False)
def do_download(self, mclient, request): if self._invalid_project(mclient, request): raise StopIteration if not self.builder.has_file(request['project'], request['filepath']): yield gen.Task(mclient.write_response, ResponseMessage.error( request.id, reason="Invalid filepath", code=ErrorCodes.MISSING_FILEPATH, )) raise StopIteration contents = self.builder.read_file(request['project'], request['filepath']) if contents is None: yield gen.Task(mclient.write_response, ResponseMessage.error( request.id, reason="Invalid filepath", code=ErrorCodes.MISSING_FILEPATH, )) raise StopIteration yield gen.Task(mclient.write_response, ResponseMessage.success( request.id, project=request['project'], filepath=request['filepath'], contents=contents, ))
def handle_register(self, request): "Register a new user account fo this client." error = self.auth.create(request['username'], request['password']) if not error: msg = ResponseMessage.success(request.id) print self.id, '<-', msg yield gen.Task(self.stream.write, msg) else: msg = ResponseMessage.error(request.id, **error) print self.id, '<-', msg yield gen.Task(self.stream.write, msg)
def do_clients(self, request): machines = {} for name, client in self.tracker.get_namespace(self.namespace).items(): machines[name] = client.type msg = ResponseMessage.success(request.id, clients=machines) print self.id, '<-', msg yield gen.Task(self.stream.write, msg)
def wrapped(self, *args, **kwargs): mclient = args[mclient_index] request = args[request_index] if not validator(self, request[key]): yield gen.Task(mclient.write_response, ResponseMessage.error(request.id, reason=reason, code=code)) raise StopIteration fn(self, *args, **kwargs)
def do_request(self, request): # TODO: reject if sender or command is malformed print 'REQUEST: namespace =', self.namespace, '; machine =', request[ 'machine'] target = self.tracker.get_client_in_namespace(self.namespace, request['machine']) if target is None: print "No machine named:", request['machine'] msg = ResponseMessage.error(request.id, reason="No machine exists named %r" % request['machine'], code=ErrorCodes.UNKNOWN_MACHINE) yield gen.Task(self.stream.write, msg) raise StopIteration msg = InvocationMessage.create(request['command']) if not msg: print "bad message:", repr(msg) raise StopIteration msg.sender = self.machine print target.id, '<-', msg.name, '[forwarding]' response = yield gen.Task(target.request, msg) print '[forwarding]', target.id, '->', response response.sender = target.machine print self.id, '<-', response, '[forwarding]' yield gen.Task(self.stream.write, response)
def _invalid_project(self, mclient, request, callback=None): if request["project"] not in self.builder.project_names: mclient.write_response( ResponseMessage.error(request.id, reason="Invalid Project", code=ErrorCodes.MISSING_PROJECT), callback=callback, ) return True return False
def do_commit(self, mclient, request): if self._invalid_project(mclient, request): raise StopIteration self.builder.commit(request['project'], request['message']) yield gen.Task(mclient.write_response, ResponseMessage.success( request.id, ))
def do_stage_file(self, mclient, request): if self._invalid_project(mclient, request): raise StopIteration self.builder.add_to_index(request['project'], request['filepath']) yield gen.Task(mclient.write_response, ResponseMessage.success( request.id, ))
def do_diff_stats(self, mclient, request): if self._invalid_project(mclient, request): raise StopIteration yield gen.Task( mclient.write_response, ResponseMessage.success(request.id, stats=self.builder.diff_stats(request["project"])), )
def do_diff_stats(self, mclient, request): if self._invalid_project(mclient, request): raise StopIteration yield gen.Task(mclient.write_response, ResponseMessage.success( request.id, stats=self.builder.diff_stats(request['project']) ))
def do_perform(self, mclient, request): if self._invalid_project(mclient, request): raise StopIteration project = self.builder.projects[request['project']] if project.is_busy: yield gen.Task(mclient.write_response, ResponseMessage.error( request.id, reason="Project is busy. Use cancel to stop existing command.", code=ErrorCodes.ACTION_CONFLICT, )) raise StopIteration if request['action'] not in project.actions: yield gen.Task(mclient.write_response, ResponseMessage.error( request.id, reason="Invalid Action", code=ErrorCodes.MISSING_ACTION, )) raise StopIteration self.process_query = project.perform_action(request['action']) target = request.sender yield gen.Task(mclient.write_response, ResponseMessage.success(request.id)) # TODO: handle stdin while not self.process_query.has_terminated or self.process_query.can_read: if self.process_query.can_read: yield gen.Task(mclient.send, target, StreamNotification( project=project.name, contents=self.process_query.read(), )) else: # wait, to allow processing of other IO yield gen.Task(self.wait) yield gen.Task(mclient.send, target, StreamEOFNotification( project=project.name, )) yield gen.Task(mclient.send, target, ReturnCodeNotification( project=project.name, code=self.process_query.return_code, )) self.process_query = None
def do_cancel(self, mclient, request): if self._invalid_project(mclient, request): raise StopIteration if not self.process_query: yield gen.Task(mclient.write_response, ResponseMessage.error( request.id, reason="No process running for %r." % request['project'] )) raise StopIteration self.process_query.terminate() yield gen.Task(mclient.write_response, ResponseMessage.success(request.id)) # really kill it if we need to yield gen.Task(mclient.wait_for, seconds=1) self.process_query.kill() self.process_query = None
def fail(self, id, **kwargs): close = kwargs.pop('close_stream', False) msg = ResponseMessage.error(id, **kwargs) if close: print self.id, '<-', msg, '+ close' else: print self.id, '<-', msg closefn = lambda: self.tracker.remove(self) self.stream.write(msg, callback=closefn if close else None)
def _invalid_project(self, mclient, request, callback=None): if request['project'] not in self.builder.project_names: mclient.write_response(ResponseMessage.error( request.id, reason="Invalid Project", code=ErrorCodes.MISSING_PROJECT, ), callback=callback) return True return False
def do_cancel(self, mclient, request): if self._invalid_project(mclient, request): raise StopIteration if not self.process_query: yield gen.Task( mclient.write_response, ResponseMessage.error(request.id, reason="No process running for %r." % request["project"]), ) raise StopIteration self.process_query.terminate() yield gen.Task(mclient.write_response, ResponseMessage.success(request.id)) # really kill it if we need to yield gen.Task(mclient.wait_for, seconds=1) self.process_query.kill() self.process_query = None
def do_branches(self, mclient, request): if self._invalid_project(mclient, request): raise StopIteration yield gen.Task(mclient.write_response, ResponseMessage.success( request.id, branches=self.builder.get_branches(request['project']), head=self.builder.get_current_branch(request['project']), ))
def do_perform(self, mclient, request): if self._invalid_project(mclient, request): raise StopIteration project = self.builder.projects[request["project"]] if project.is_busy: yield gen.Task( mclient.write_response, ResponseMessage.error( request.id, reason="Project is busy. Use cancel to stop existing command.", code=ErrorCodes.ACTION_CONFLICT, ), ) raise StopIteration if request["action"] not in project.actions: yield gen.Task( mclient.write_response, ResponseMessage.error(request.id, reason="Invalid Action", code=ErrorCodes.MISSING_ACTION), ) raise StopIteration self.process_query = project.perform_action(request["action"]) target = request.sender yield gen.Task(mclient.write_response, ResponseMessage.success(request.id)) # TODO: handle stdin while not self.process_query.has_terminated or self.process_query.can_read: if self.process_query.can_read: yield gen.Task( mclient.send, target, StreamNotification(project=project.name, contents=self.process_query.read()) ) else: # wait, to allow processing of other IO yield gen.Task(self.wait) yield gen.Task(mclient.send, target, StreamEOFNotification(project=project.name)) yield gen.Task( mclient.send, target, ReturnCodeNotification(project=project.name, code=self.process_query.return_code) ) self.process_query = None
def wrapped(self, *args, **kwargs): mclient = args[mclient_index] request = args[request_index] if not validator(self, request[key]): yield gen.Task(mclient.write_response, ResponseMessage.error( request.id, reason=reason, code=code, )) raise StopIteration fn(self, *args, **kwargs)
def do_upload(self, mclient, request): if self._invalid_project(mclient, request): raise StopIteration if request['contents'] is None: yield gen.Task(mclient.write_response, ResponseMessage.error( request.id, reason="Bad Request", code=ErrorCodes.BAD_REQUEST, )) raise StopIteration # no op for now try: self.builder.write_file(request['project'], request['filepath'], request['contents'] or '') except IOError: yield gen.Task(mclient.write_response, ResponseMessage.error( request.id, reason="Failed to write", code=ErrorCodes.INTERNAL_ERROR)) raise StopIteration yield gen.Task(mclient.write_response, ResponseMessage.success(request.id))
def do_files(self, mclient, request): if self._invalid_project(mclient, request): raise StopIteration files = self.builder.get_files(request["project"], request["branch"]) # files is None when switching branches fails. # TODO: perhaps we should stash & apply instead? if files is None: yield gen.Task( mclient.write_response, ResponseMessage.error(request.id, reason="Failed to checkout files", code=ErrorCodes.INTERNAL_ERROR), ) else: yield gen.Task( mclient.write_response, ResponseMessage.success( request.id, files=files, branch=self.builder.get_current_branch(request["project"]) ), )
def handler(raw_msg): if 'result' in raw_msg: op = ResponseMessage.create(raw_msg) else: op = invocation_message(raw_msg) if op or not self.ignore_invalid_messages: callback(op) else: if callable(self.on_bad_message): self.on_bad_message(raw_msg) else: print "Bad Message", repr(raw_msg)
def do_upload(self, mclient, request): if self._invalid_project(mclient, request): raise StopIteration if request["contents"] is None: yield gen.Task( mclient.write_response, ResponseMessage.error(request.id, reason="Bad Request", code=ErrorCodes.BAD_REQUEST), ) raise StopIteration # no op for now try: self.builder.write_file(request["project"], request["filepath"], request["contents"] or "") except IOError: yield gen.Task( mclient.write_response, ResponseMessage.error(request.id, reason="Failed to write", code=ErrorCodes.INTERNAL_ERROR), ) raise StopIteration yield gen.Task(mclient.write_response, ResponseMessage.success(request.id))
def do_branches(self, mclient, request): if self._invalid_project(mclient, request): raise StopIteration yield gen.Task( mclient.write_response, ResponseMessage.success( request.id, branches=self.builder.get_branches(request["project"]), head=self.builder.get_current_branch(request["project"]), ), )
def do_input(self, mclient, request): if self._invalid_project(mclient, request): raise StopIteration if request["contents"] is None: yield gen.Task( mclient.write_response, ResponseMessage.error(request.id, reason="Bad Request", code=ErrorCodes.BAD_REQUEST), ) raise StopIteration if not self.process_query: yield gen.Task( mclient.write_response, ResponseMessage.error( request.id, reason="No process running for %r." % request["project"], code=ErrorCodes.NO_ACTIVITY ), ) raise StopIteration self.process_query.write(str(request["contents"])) yield gen.Task(mclient.write_response, ResponseMessage.success(request.id))
def do_input(self, mclient, request): if self._invalid_project(mclient, request): raise StopIteration if request['contents'] is None: yield gen.Task(mclient.write_response, ResponseMessage.error( request.id, reason="Bad Request", code=ErrorCodes.BAD_REQUEST, )) raise StopIteration if not self.process_query: yield gen.Task(mclient.write_response, ResponseMessage.error( request.id, reason="No process running for %r." % request['project'], code=ErrorCodes.NO_ACTIVITY, )) raise StopIteration self.process_query.write(str(request['contents'])) yield gen.Task(mclient.write_response, ResponseMessage.success(request.id))
def do_download(self, mclient, request): if self._invalid_project(mclient, request): raise StopIteration if not self.builder.has_file(request["project"], request["filepath"]): yield gen.Task( mclient.write_response, ResponseMessage.error(request.id, reason="Invalid filepath", code=ErrorCodes.MISSING_FILEPATH), ) raise StopIteration contents = self.builder.read_file(request["project"], request["filepath"]) if contents is None: yield gen.Task( mclient.write_response, ResponseMessage.error(request.id, reason="Invalid filepath", code=ErrorCodes.MISSING_FILEPATH), ) raise StopIteration yield gen.Task( mclient.write_response, ResponseMessage.success( request.id, project=request["project"], filepath=request["filepath"], contents=contents ), )
def do_files(self, mclient, request): if self._invalid_project(mclient, request): raise StopIteration files = self.builder.get_files( request['project'], request['branch'] ) # files is None when switching branches fails. # TODO: perhaps we should stash & apply instead? if files is None: yield gen.Task(mclient.write_response, ResponseMessage.error( request.id, reason="Failed to checkout files", code=ErrorCodes.INTERNAL_ERROR, )) else: yield gen.Task(mclient.write_response, ResponseMessage.success( request.id, files=files, branch=self.builder.get_current_branch(request['project']), ))
def handle_message(self, message, mclient): # dispatch if message.is_response and message.id in self.inbox: self.inbox[message.id]() del self.inbox[message.id] elif message.is_invocation: method = getattr(self, 'do_' + message.name, None) if callable(method): print 'invoking', 'do_' + message.name method(mclient, message) else: yield gen.Task(mclient.write_response, ResponseMessage.error(message.id, reason="Malformed request", code=ErrorCodes.BAD_REQUEST))
def handle_message(self, message, mclient): # dispatch if message.is_response and message.id in self.inbox: self.inbox[message.id]() del self.inbox[message.id] elif message.is_invocation: method = getattr(self, "do_" + message.name, None) if callable(method): print "invoking", "do_" + message.name method(mclient, message) else: yield gen.Task( mclient.write_response, ResponseMessage.error(message.id, reason="Malformed request", code=ErrorCodes.BAD_REQUEST), )
def do_request(self, request): # TODO: reject if sender or command is malformed print 'REQUEST: namespace =', self.namespace, '; machine =', request['machine'] target = self.tracker.get_client_in_namespace(self.namespace, request['machine']) if target is None: print "No machine named:", request['machine'] msg = ResponseMessage.error(request.id, reason="No machine exists named %r" % request['machine'], code=ErrorCodes.UNKNOWN_MACHINE) yield gen.Task(self.stream.write, msg) raise StopIteration msg = InvocationMessage.create(request['command']) if not msg: print "bad message:", repr(msg) raise StopIteration msg.sender = self.machine print target.id, '<-', msg.name, '[forwarding]' response = yield gen.Task(target.request, msg) print '[forwarding]', target.id, '->', response response.sender = target.machine print self.id, '<-', response, '[forwarding]' yield gen.Task(self.stream.write, response)
def write_response(self, command, callback): "Sends a given command back as a response." if not callable(getattr(command, "to_network", None)): command = ResponseMessage.create(command) self.stream.write(command, callback=callback) print "mediator <-", command
def do_stats(self, mclient, request): yield gen.Task(mclient.write_response, ResponseMessage.success( request.id, activity=self.builder.activities, ))
def do_projects(self, mclient, request): yield gen.Task(mclient.write_response, ResponseMessage.success(request.id, projects=self.builder.project_names))
def do_commit(self, mclient, request): if self._invalid_project(mclient, request): raise StopIteration self.builder.commit(request["project"], request["message"]) yield gen.Task(mclient.write_response, ResponseMessage.success(request.id))
def do_stage_file(self, mclient, request): if self._invalid_project(mclient, request): raise StopIteration self.builder.add_to_index(request["project"], request["filepath"]) yield gen.Task(mclient.write_response, ResponseMessage.success(request.id))
def do_stats(self, mclient, request): yield gen.Task(mclient.write_response, ResponseMessage.success(request.id, activity=self.builder.activities))
def write_response(self, command, callback): "Sends a given command back as a response." if not callable(getattr(command, 'to_network', None)): command = ResponseMessage.create(command) self.stream.write(command, callback=callback) print "mediator <-", command