Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Unified Diff: appengine_apps/chromium_status/appengine_module/chromium_status/event_push.py

Issue 778533003: Moved chromium_status to appengine/ (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: appengine_apps/chromium_status/appengine_module/chromium_status/event_push.py
diff --git a/appengine_apps/chromium_status/appengine_module/chromium_status/event_push.py b/appengine_apps/chromium_status/appengine_module/chromium_status/event_push.py
deleted file mode 100644
index 54e32ab414901e9b35ec70cb40cf2d0ac7a76cc1..0000000000000000000000000000000000000000
--- a/appengine_apps/chromium_status/appengine_module/chromium_status/event_push.py
+++ /dev/null
@@ -1,239 +0,0 @@
-# Copyright (c) 2011 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""StatusPush handler from the buildbot master.
-
-See event_sample.txt for event format examples.
-"""
-
-import datetime
-import json
-import logging
-import time
-
-from google.appengine.api.labs import taskqueue
-from google.appengine.ext import db
-from google.appengine.ext.db import polymodel
-from google.appengine.runtime import DeadlineExceededError
-from google.appengine.runtime.apiproxy_errors import CapabilityDisabledError
-
-from appengine_module.chromium_status.base_page import BasePage
-
-from appengine_module.chromium_status import utils
-
-
-class Event(polymodel.PolyModel):
- """Base class for every events pushed by buildbot's StatusPush."""
- eventid = db.IntegerProperty(required=True, indexed=False)
- projectname = db.StringProperty(required=True)
- projectstarted = db.DateTimeProperty(required=True)
- created = db.DateTimeProperty(auto_now_add=True)
-
-
-class Change(Event):
- """Buildbot detected a change"""
- comments = db.TextProperty()
- files = db.StringListProperty()
- # Buildbot's master change number in changes.pck
- number = db.IntegerProperty(required=True)
- revision = db.StringProperty(indexed=False)
- when = db.DateTimeProperty(required=True)
- who = db.StringProperty(indexed=False)
- revlink = db.StringProperty(indexed=False)
-
-
-class Build(Event):
- """Buildbot completed a build"""
- buildername = db.StringProperty(required=True)
- buildnumber = db.IntegerProperty(required=True)
- finished = db.DateTimeProperty(indexed=False)
- reason = db.TextProperty()
- results = db.IntegerProperty(indexed=False)
- revision = db.StringProperty()
- slave = db.StringProperty(indexed=False)
- text = db.StringListProperty()
-
-
-class BuildStep(Event):
- """Buildbot completed a build step"""
- buildername = db.StringProperty(required=True)
- buildnumber = db.IntegerProperty(required=True)
- finished = db.DateTimeProperty(indexed=False)
- # TODO(maruel): Require it ASAP
- stepnumber = db.IntegerProperty(required=False, indexed=False)
- stepname = db.StringProperty(required=True)
- text = db.StringListProperty()
- results = db.IntegerProperty(indexed=False)
-
-
-def ModelToStr(obj):
- """Converts a model to a human readable string, for debugging"""
- assert isinstance(obj, db.Model)
- out = [obj.__class__.__name__]
- for k in obj.properties():
- if k.startswith('_'):
- continue
- out.append(' %s: %s' % (k, str(getattr(obj, k))))
- return '\n'.join(out)
-
-
-def onChangeAdded(packet):
- change = packet['payload']['change']
- obj = Change.gql(
- 'WHERE projectname = :1 AND projectstarted = :2 AND number = :3',
- packet['project'], packet['projectstarted'],
- change['number']).get()
- if obj:
- logging.info('Received duplicate %s/%s event for %s %s' %
- (packet['event'], packet['eventid'], obj.__class__.__name__,
- obj.number))
- return None
- return Change(
- eventid=packet['id'],
- projectname=packet['project'],
- projectstarted=packet['projectstarted'],
- comments=change['comments'],
- files=change['files'],
- number=change['number'],
- revision=change['revision'],
- # TODO(maruel): Timezones
- when=datetime.datetime.fromtimestamp(change['when']),
- who=change['who'],
- revlink=change['revlink'])
-
-
-def onBuildFinished(packet):
- build = packet['payload']['build']
- obj = Build.gql(
- 'WHERE projectname = :1 AND projectstarted = :2 '
- 'AND buildername = :3 AND buildnumber = :4',
- packet['project'], packet['projectstarted'],
- build['builderName'], build['number']).get()
- if obj:
- logging.info('Received duplicate %s/%d event for %s %s' %
- (packet['event'], packet['id'], obj.__class__.__name__,
- obj.build_number))
- return None
- # properties is an array of 3 values, keep the first 2 in a dict.
- props = dict(((i[0], i[1]) for i in build['properties']))
- return Build(
- eventid=packet['id'],
- projectname=packet['project'],
- projectstarted=packet['projectstarted'],
- buildername=build['builderName'],
- buildnumber=build['number'],
- # TODO(maruel): Timezones
- finished=datetime.datetime.fromtimestamp(build['times'][1]),
- reason=build['reason'],
- results=build.get('results', 0),
- revision=props.get('got_revision', props.get('revision', None)),
- slave=build['slave'],
- text=build['text'])
-
-
-def onStepFinished(packet):
- payload = packet['payload']
- step = payload['step']
- # properties is an array of 3 values, keep the first 2 in a dict.
- props = dict(((i[0], i[1]) for i in payload['properties']))
- obj = BuildStep.gql(
- 'WHERE projectname = :1 AND projectstarted = :2 '
- 'AND buildername = :3 AND buildnumber = :4 AND stepname = :5',
- packet['project'], packet['projectstarted'],
- props['buildername'], props['buildnumber'],
- step['name']).get()
- if obj:
- logging.info('Received duplicate %s/%d event for %s %s' %
- (packet['event'], packet['id'], obj.__class__.__name__,
- obj.buildnumber))
- return None
- return BuildStep(
- eventid=packet['id'],
- projectname=packet['project'],
- projectstarted=packet['projectstarted'],
- buildername=props['buildername'],
- buildnumber=props['buildnumber'],
- # TODO(maruel): Send step number
- #number=???
- stepname=step['name'],
- text=step['text'],
- results=step.get('results', (0,))[0])
-
-
-SUPPORTED_EVENTS = {
- 'changeAdded': onChangeAdded,
- 'buildFinished': onBuildFinished,
- 'stepFinished': onStepFinished,
-}
-
-
-class StatusReceiver(BasePage):
- """Buildbot's HttpStatusPush event receiver"""
- @utils.requires_write_access
- def post(self):
- self.response.headers['Content-Type'] = 'text/plain'
- try:
- # TODO(maruel): Safety check, pwd?
- packets = json.loads(self.request.POST['packets'])
- # A list of packets should have been submitted, store each event.
- objs = []
- for index in xrange(len(packets)):
- packet = packets[index]
- # To simplify getKwargs.
- packet['projectname'] = packet['project']
- # TODO(maruel): Timezones
- ts = time.strptime(packet['started'].split('.', 1)[0],
- '%Y-%m-%d %H:%M:%S')
- packet['projectstarted'] = (
- datetime.datetime.fromtimestamp(time.mktime(ts)))
- packet['eventid'] = packet['id']
- if not 'payload' in packet:
- packet['payload'] = json.loads(packet['payload_json'])
- functor = SUPPORTED_EVENTS.get(packet['event'], None)
- if not functor:
- continue
- obj = functor(packet)
- if obj:
- objs.append(obj)
- # Save all the objects at once to reduce the number of rpc.
- db.put(objs)
- except CapabilityDisabledError:
- logging.info('CapabilityDisabledError: read-only datastore')
- self.response.out.write('CapabilityDisabledError: read-only datastore')
- self.error(500)
- return
- except DeadlineExceededError:
- logging.info('DeadlineExceededError')
- self.response.out.write('DeadlineExceededError')
- self.error(500)
- return
- taskqueue.add(url='/restricted/status-processor')
- self.response.out.write('Success')
-
-
-class RecentEvents(BasePage):
- """Returns the most recent events.
-
- Mostly for testing"""
- @utils.requires_read_access
- def get(self):
- self.response.headers['Content-Type'] = 'text/plain'
- limit = int(self.request.GET.get('limit', 25))
- nb = 0
- for obj in Event.gql('ORDER BY created DESC LIMIT %d' % limit):
- self.response.out.write('%s\n\n' % ModelToStr(obj))
- nb += 1
- logging.debug('RecentEvents(limit=%d) got %d' % (limit, nb))
-
-
-class StatusProcessor(BasePage):
- """TODO(maruel): Implement http://crbug.com/21801
-
- i.e. implement GateKeeper on appengine, close the tree when the buildbot
- master shuts down, etc."""
-
- @utils.requires_work_queue_login
- def post(self):
- self.response.headers['Content-Type'] = 'text/plain'
- self.response.out.write('Success')

Powered by Google App Engine
This is Rietveld 408576698