Merge "moving readiness checks into stream"
This commit is contained in:
commit
9a195644d1
@ -144,8 +144,7 @@ class RecheckWatch(threading.Thread):
|
|||||||
change_id = "%s,%s" % (change, rev)
|
change_id = "%s,%s" % (change, rev)
|
||||||
project = event['change']['project']
|
project = event['change']['project']
|
||||||
try:
|
try:
|
||||||
bug_numbers = classifier.classify(change, rev,
|
bug_numbers = classifier.classify(change, rev)
|
||||||
event['comment'])
|
|
||||||
if not bug_numbers:
|
if not bug_numbers:
|
||||||
self._read(event)
|
self._read(event)
|
||||||
else:
|
else:
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
import gerritlib.gerrit
|
import gerritlib.gerrit
|
||||||
import pyelasticsearch
|
import pyelasticsearch
|
||||||
import urllib2
|
|
||||||
|
|
||||||
import ConfigParser
|
import ConfigParser
|
||||||
import logging
|
import logging
|
||||||
@ -32,16 +31,24 @@ from elastic_recheck import results
|
|||||||
|
|
||||||
logging.basicConfig()
|
logging.basicConfig()
|
||||||
|
|
||||||
|
ES_URL = "http://logstash.openstack.org/elasticsearch"
|
||||||
|
|
||||||
REQUIRED_FILES = [
|
|
||||||
'console.html',
|
def required_files(job):
|
||||||
|
files = ['console.html']
|
||||||
|
if re.match("tempest-dsvm", job):
|
||||||
|
files.extend([
|
||||||
'logs/screen-n-api.txt',
|
'logs/screen-n-api.txt',
|
||||||
'logs/screen-n-cpu.txt',
|
'logs/screen-n-cpu.txt',
|
||||||
'logs/screen-n-sch.txt',
|
'logs/screen-n-sch.txt',
|
||||||
'logs/screen-c-api.txt',
|
'logs/screen-c-api.txt',
|
||||||
'logs/screen-c-vol.txt',
|
'logs/screen-c-vol.txt',
|
||||||
'logs/syslog.txt',
|
'logs/syslog.txt'])
|
||||||
]
|
return files
|
||||||
|
|
||||||
|
|
||||||
|
class ResultNotReady(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Stream(object):
|
class Stream(object):
|
||||||
@ -55,6 +62,7 @@ class Stream(object):
|
|||||||
def __init__(self, user, host, key, thread=True):
|
def __init__(self, user, host, key, thread=True):
|
||||||
port = 29418
|
port = 29418
|
||||||
self.gerrit = gerritlib.gerrit.Gerrit(host, user, port, key)
|
self.gerrit = gerritlib.gerrit.Gerrit(host, user, port, key)
|
||||||
|
self.es = results.SearchEngine(ES_URL)
|
||||||
if thread:
|
if thread:
|
||||||
self.gerrit.startWatching()
|
self.gerrit.startWatching()
|
||||||
|
|
||||||
@ -79,40 +87,82 @@ class Stream(object):
|
|||||||
failed_tests[m.group(1)] = m.group(2)
|
failed_tests[m.group(1)] = m.group(2)
|
||||||
return failed_tests
|
return failed_tests
|
||||||
|
|
||||||
def _failed_unit_tests(self, line):
|
def _job_console_uploaded(self, change, patch, name):
|
||||||
"""Did we fail unit tests? If so not a valid failure."""
|
query = qb.result_ready(change, patch, name)
|
||||||
fail = ("FAILURE" in line and ("python2" in line or "pep8" in line))
|
r = self.es.search(query, size='10')
|
||||||
if fail:
|
if len(r) == 0:
|
||||||
self.log.debug("Failed unit tests, skipping this result")
|
raise ResultNotReady()
|
||||||
return fail
|
|
||||||
|
|
||||||
def _valid_failure(self, line):
|
def _has_required_files(self, change, patch, name):
|
||||||
"""Is this the kind of failure we track."""
|
query = qb.files_ready(change, patch)
|
||||||
return "FAILURE" in line and "tempest" in line
|
r = self.es.search(query, size='80')
|
||||||
|
files = [x['term'] for x in r.terms]
|
||||||
|
required = required_files(name)
|
||||||
|
missing_files = [x for x in required if x not in files]
|
||||||
|
if len(missing_files) != 0:
|
||||||
|
raise ResultNotReady()
|
||||||
|
|
||||||
|
def _does_es_have_data(self, change_number, patch_number, job_fails):
|
||||||
|
"""Wait till ElasticSearch is ready, but return False if timeout."""
|
||||||
|
NUMBER_OF_RETRIES = 20
|
||||||
|
SLEEP_TIME = 40
|
||||||
|
# this checks that we've got the console log uploaded, need to retry
|
||||||
|
# in case ES goes bonkers on cold data, which it does some times.
|
||||||
|
for i in range(NUMBER_OF_RETRIES):
|
||||||
|
try:
|
||||||
|
for job_name in job_fails:
|
||||||
|
self._job_console_uploaded(
|
||||||
|
change_number, patch_number, job_name)
|
||||||
|
break
|
||||||
|
|
||||||
|
except ResultNotReady:
|
||||||
|
time.sleep(SLEEP_TIME)
|
||||||
|
continue
|
||||||
|
except pyelasticsearch.exceptions.InvalidJsonResponseError:
|
||||||
|
# If ElasticSearch returns an error code, sleep and retry
|
||||||
|
# TODO(jogo): if this works pull out search into a helper
|
||||||
|
# function that does this.
|
||||||
|
self.log.exception(
|
||||||
|
"Elastic Search not responding on attempt %d" % i)
|
||||||
|
time.sleep(NUMBER_OF_RETRIES)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if i == NUMBER_OF_RETRIES - 1:
|
||||||
|
return False
|
||||||
|
|
||||||
|
self.log.debug(
|
||||||
|
"Found hits for change_number: %s, patch_number: %s"
|
||||||
|
% (change_number, patch_number))
|
||||||
|
|
||||||
|
for i in range(NUMBER_OF_RETRIES):
|
||||||
|
try:
|
||||||
|
for job_name in job_fails:
|
||||||
|
self._has_required_files(
|
||||||
|
change_number, patch_number, job_name)
|
||||||
|
self.log.debug(
|
||||||
|
"All files present for change_number: %s, patch_number: %s"
|
||||||
|
% (change_number, patch_number))
|
||||||
|
time.sleep(10)
|
||||||
|
return True
|
||||||
|
except ResultNotReady:
|
||||||
|
time.sleep(SLEEP_TIME)
|
||||||
|
|
||||||
|
# if we get to the end, we're broken
|
||||||
|
return False
|
||||||
|
|
||||||
def get_failed_tempest(self):
|
def get_failed_tempest(self):
|
||||||
self.log.debug("entering get_failed_tempest")
|
self.log.debug("entering get_failed_tempest")
|
||||||
while True:
|
while True:
|
||||||
event = self.gerrit.getEvent()
|
event = self.gerrit.getEvent()
|
||||||
failed_jobs = Stream.parse_jenkin_failure(event)
|
failed_jobs = Stream.parse_jenkins_failure(event)
|
||||||
if not failed_jobs:
|
if not failed_jobs:
|
||||||
# nothing to see here, lets try the next event
|
# nothing to see here, lets try the next event
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self.log.debug("potential failed_tempest")
|
change = event['change']['number']
|
||||||
found = False
|
rev = event['patchSet']['number']
|
||||||
for line in event['comment'].split('\n'):
|
if self._does_es_have_data(change, rev, failed_jobs):
|
||||||
if self._failed_unit_tests(line):
|
|
||||||
found = False
|
|
||||||
break
|
|
||||||
if self._valid_failure(line):
|
|
||||||
url = [x for x in line.split() if "http" in x][0]
|
|
||||||
if RequiredFiles.files_at_url(url):
|
|
||||||
self.log.debug("All file present")
|
|
||||||
found = True
|
|
||||||
if found:
|
|
||||||
return event
|
return event
|
||||||
continue
|
|
||||||
|
|
||||||
def leave_comment(self, project, commit, bugs=None):
|
def leave_comment(self, project, commit, bugs=None):
|
||||||
if bugs:
|
if bugs:
|
||||||
@ -147,12 +197,11 @@ class Classifier():
|
|||||||
that are mapped to specific bugs.
|
that are mapped to specific bugs.
|
||||||
"""
|
"""
|
||||||
log = logging.getLogger("recheckwatchbot")
|
log = logging.getLogger("recheckwatchbot")
|
||||||
ES_URL = "http://logstash.openstack.org/elasticsearch"
|
|
||||||
|
|
||||||
queries = None
|
queries = None
|
||||||
|
|
||||||
def __init__(self, queries_dir):
|
def __init__(self, queries_dir):
|
||||||
self.es = results.SearchEngine(self.ES_URL)
|
self.es = results.SearchEngine(ES_URL)
|
||||||
self.queries_dir = queries_dir
|
self.queries_dir = queries_dir
|
||||||
self.queries = loader.load(self.queries_dir)
|
self.queries = loader.load(self.queries_dir)
|
||||||
|
|
||||||
@ -160,20 +209,11 @@ class Classifier():
|
|||||||
es_query = qb.generic(query, facet=facet)
|
es_query = qb.generic(query, facet=facet)
|
||||||
return self.es.search(es_query, size=size)
|
return self.es.search(es_query, size=size)
|
||||||
|
|
||||||
def classify(self, change_number, patch_number, comment,
|
def classify(self, change_number, patch_number, skip_resolved=True):
|
||||||
skip_resolved=True):
|
|
||||||
"""Returns either empty list or list with matched bugs."""
|
"""Returns either empty list or list with matched bugs."""
|
||||||
self.log.debug("Entering classify")
|
self.log.debug("Entering classify")
|
||||||
#Reload each time
|
#Reload each time
|
||||||
self.queries = loader.load(self.queries_dir, skip_resolved)
|
self.queries = loader.load(self.queries_dir, skip_resolved)
|
||||||
#Wait till Elastic search is ready
|
|
||||||
self.log.debug("checking if ElasticSearch is ready")
|
|
||||||
if not self._is_ready(change_number, patch_number, comment):
|
|
||||||
self.log.error(
|
|
||||||
"something went wrong, ElasticSearch is still not ready, "
|
|
||||||
"giving up and trying next failure")
|
|
||||||
return None
|
|
||||||
self.log.debug("ElasticSearch is ready, starting to classify")
|
|
||||||
bug_matches = []
|
bug_matches = []
|
||||||
for x in self.queries:
|
for x in self.queries:
|
||||||
self.log.debug(
|
self.log.debug(
|
||||||
@ -181,89 +221,10 @@ class Classifier():
|
|||||||
% x['bug'])
|
% x['bug'])
|
||||||
query = qb.single_patch(x['query'], change_number, patch_number)
|
query = qb.single_patch(x['query'], change_number, patch_number)
|
||||||
results = self.es.search(query, size='10')
|
results = self.es.search(query, size='10')
|
||||||
if self._urls_match(comment, results):
|
if len(results) > 0:
|
||||||
bug_matches.append(x['bug'])
|
bug_matches.append(x['bug'])
|
||||||
return bug_matches
|
return bug_matches
|
||||||
|
|
||||||
def _is_ready(self, change_number, patch_number, comment):
|
|
||||||
"""Wait till ElasticSearch is ready, but return False if timeout."""
|
|
||||||
NUMBER_OF_RETRIES = 20
|
|
||||||
SLEEP_TIME = 40
|
|
||||||
query = qb.result_ready(change_number, patch_number)
|
|
||||||
for i in range(NUMBER_OF_RETRIES):
|
|
||||||
try:
|
|
||||||
results = self.es.search(query, size='10')
|
|
||||||
except pyelasticsearch.exceptions.InvalidJsonResponseError:
|
|
||||||
# If ElasticSearch returns an error code, sleep and retry
|
|
||||||
# TODO(jogo): if this works pull out search into a helper
|
|
||||||
# function that does this.
|
|
||||||
print "UHUH hit InvalidJsonResponseError"
|
|
||||||
time.sleep(NUMBER_OF_RETRIES)
|
|
||||||
continue
|
|
||||||
if (len(results) > 0 and self._urls_match(comment, results)):
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
time.sleep(SLEEP_TIME)
|
|
||||||
if i == NUMBER_OF_RETRIES - 1:
|
|
||||||
return False
|
|
||||||
self.log.debug(
|
|
||||||
"Found hits for change_number: %s, patch_number: %s"
|
|
||||||
% (change_number, patch_number))
|
|
||||||
|
|
||||||
query = qb.files_ready(change_number, patch_number)
|
|
||||||
for i in range(NUMBER_OF_RETRIES):
|
|
||||||
results = self.es.search(query, size='80')
|
|
||||||
files = [x['term'] for x in results.terms]
|
|
||||||
missing_files = [x for x in REQUIRED_FILES if x not in files]
|
|
||||||
if len(missing_files) is 0:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
time.sleep(SLEEP_TIME)
|
|
||||||
if i == NUMBER_OF_RETRIES - 1:
|
|
||||||
return False
|
|
||||||
self.log.debug(
|
|
||||||
"All files present for change_number: %s, patch_number: %s"
|
|
||||||
% (change_number, patch_number))
|
|
||||||
# Just because one file is parsed doesn't mean all are, so wait a
|
|
||||||
# bit
|
|
||||||
time.sleep(10)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def _urls_match(self, comment, results):
|
|
||||||
for result in results:
|
|
||||||
url = result.log_url
|
|
||||||
if RequiredFiles.prep_url(url) in comment:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
class RequiredFiles(object):
|
|
||||||
|
|
||||||
log = logging.getLogger("recheckwatchbot")
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def prep_url(url):
|
|
||||||
if isinstance(url, list):
|
|
||||||
# The url is sometimes a list of one value
|
|
||||||
url = url[0]
|
|
||||||
if "/logs/" in url:
|
|
||||||
return '/'.join(url.split('/')[:-2])
|
|
||||||
return '/'.join(url.split('/')[:-1])
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def files_at_url(url):
|
|
||||||
for f in REQUIRED_FILES:
|
|
||||||
try:
|
|
||||||
urllib2.urlopen(url + '/' + f)
|
|
||||||
except urllib2.HTTPError:
|
|
||||||
try:
|
|
||||||
urllib2.urlopen(url + '/' + f + '.gz')
|
|
||||||
except urllib2.HTTPError:
|
|
||||||
# File does not exist at URL
|
|
||||||
RequiredFiles.log.debug("missing file %s" % f)
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
config = ConfigParser.ConfigParser()
|
config = ConfigParser.ConfigParser()
|
||||||
@ -285,7 +246,7 @@ def main():
|
|||||||
rev = event['patchSet']['number']
|
rev = event['patchSet']['number']
|
||||||
print "======================="
|
print "======================="
|
||||||
print "https://review.openstack.org/#/c/%(change)s/%(rev)s" % locals()
|
print "https://review.openstack.org/#/c/%(change)s/%(rev)s" % locals()
|
||||||
bug_numbers = classifier.classify(change, rev, event['comment'])
|
bug_numbers = classifier.classify(change, rev)
|
||||||
if not bug_numbers:
|
if not bug_numbers:
|
||||||
print "unable to classify failure"
|
print "unable to classify failure"
|
||||||
else:
|
else:
|
||||||
|
@ -59,7 +59,7 @@ def generic(raw_query, facet=None):
|
|||||||
return query
|
return query
|
||||||
|
|
||||||
|
|
||||||
def result_ready(review=None, patch=None):
|
def result_ready(review=None, patch=None, name=None):
|
||||||
"""A query to determine if we have a failure for a particular patch.
|
"""A query to determine if we have a failure for a particular patch.
|
||||||
|
|
||||||
This is looking for a particular FAILURE line in the console log, which
|
This is looking for a particular FAILURE line in the console log, which
|
||||||
@ -70,8 +70,9 @@ def result_ready(review=None, patch=None):
|
|||||||
'OR message:"[SCP] Copying console log") '
|
'OR message:"[SCP] Copying console log") '
|
||||||
'AND build_status:"FAILURE" '
|
'AND build_status:"FAILURE" '
|
||||||
'AND build_change:"%s" '
|
'AND build_change:"%s" '
|
||||||
'AND build_patchset:"%s"' %
|
'AND build_patchset:"%s" '
|
||||||
(review, patch))
|
'AND build_name:"%s"' %
|
||||||
|
(review, patch, name))
|
||||||
|
|
||||||
|
|
||||||
def files_ready(review, patch):
|
def files_ready(review, patch):
|
||||||
|
35
elastic_recheck/tests/unit/fake_gerrit.py
Normal file
35
elastic_recheck/tests/unit/fake_gerrit.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# Copyright 2014 Samsung Electronics. All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
class GerritDone(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Gerrit(object):
|
||||||
|
"""A fake gerrit libobject that emits a bunch of events."""
|
||||||
|
def __init__(self, *args):
|
||||||
|
with open("elastic_recheck/tests/unit/gerrit/events.json") as f:
|
||||||
|
self.events = json.load(f)
|
||||||
|
|
||||||
|
def startWatching(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def getEvent(self):
|
||||||
|
if len(self.events) > 0:
|
||||||
|
return self.events.pop()
|
||||||
|
else:
|
||||||
|
raise GerritDone()
|
402
elastic_recheck/tests/unit/gerrit/events.json
Normal file
402
elastic_recheck/tests/unit/gerrit/events.json
Normal file
@ -0,0 +1,402 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"comment": "Build succeeded.\n\n- gate-keystone-pep8 http:\/\/logs.openstack.org\/44\/60244\/12\/check\/gate-keystone-pep8\/5ef9f24 : SUCCESS in 1m 40s\n- gate-keystone-docs http:\/\/docs-draft.openstack.org\/44\/60244\/12\/check\/gate-keystone-docs\/60c7b1b\/doc\/build\/html\/ : SUCCESS in 4m 01s\n- gate-keystone-python26 http:\/\/logs.openstack.org\/44\/60244\/12\/check\/gate-keystone-python26\/d66253a : SUCCESS in 18m 02s\n- gate-keystone-python27 http:\/\/logs.openstack.org\/44\/60244\/12\/check\/gate-keystone-python27\/04102a5 : SUCCESS in 13m 57s\n- check-tempest-dsvm-full http:\/\/logs.openstack.org\/44\/60244\/12\/check\/check-tempest-dsvm-full\/0893acf : SUCCESS in 42m 30s\n- check-tempest-dsvm-postgres-full http:\/\/logs.openstack.org\/44\/60244\/12\/check\/check-tempest-dsvm-postgres-full\/671d371 : SUCCESS in 49m 30s\n- check-tempest-dsvm-neutron http:\/\/logs.openstack.org\/44\/60244\/12\/check\/check-tempest-dsvm-neutron\/4981e54 : SUCCESS in 35m 09s\n- gate-tempest-dsvm-large-ops http:\/\/logs.openstack.org\/44\/60244\/12\/check\/gate-tempest-dsvm-large-ops\/9e825fb : SUCCESS in 13m 11s\n- gate-tempest-dsvm-neutron-large-ops http:\/\/logs.openstack.org\/44\/60244\/12\/check\/gate-tempest-dsvm-neutron-large-ops\/286d887 : SUCCESS in 13m 22s\n- check-grenade-dsvm http:\/\/logs.openstack.org\/44\/60244\/12\/check\/check-grenade-dsvm\/b3b7478 : SUCCESS in 32m 01s\n- check-swift-dsvm-functional http:\/\/logs.openstack.org\/44\/60244\/12\/check\/check-swift-dsvm-functional\/350f34c : SUCCESS in 13m 12s\n",
|
||||||
|
"author": {
|
||||||
|
"username": "jenkins",
|
||||||
|
"name": "Jenkins"
|
||||||
|
},
|
||||||
|
"approvals": [
|
||||||
|
{
|
||||||
|
"type": "VRIF",
|
||||||
|
"description": "Verified",
|
||||||
|
"value": "1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"patchSet": {
|
||||||
|
"createdOn": 1389371115,
|
||||||
|
"ref": "refs\/changes\/44\/60244\/12",
|
||||||
|
"number": "12",
|
||||||
|
"uploader": {
|
||||||
|
"username": "stevemar",
|
||||||
|
"name": "Steve Martinelli",
|
||||||
|
"email": "stevemar@ca.ibm.com"
|
||||||
|
},
|
||||||
|
"revision": "74d75a1050c96eef498e9daaa80fcb9652003a20"
|
||||||
|
},
|
||||||
|
"type": "comment-added",
|
||||||
|
"change": {
|
||||||
|
"topic": "bp\/mapping",
|
||||||
|
"url": "https:\/\/review.openstack.org\/60244",
|
||||||
|
"number": "60244",
|
||||||
|
"project": "openstack\/keystone",
|
||||||
|
"branch": "master",
|
||||||
|
"owner": {
|
||||||
|
"username": "marek-denis",
|
||||||
|
"name": "Marek Denis",
|
||||||
|
"email": "marek.denis@cern.ch"
|
||||||
|
},
|
||||||
|
"id": "I0ce62e720e797718dbfde6bfcd4b22a213985867",
|
||||||
|
"subject": "Identity Providers CRUD operations."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comment": "Build failed. For information on how to proceed, see https:\/\/wiki.openstack.org\/wiki\/GerritJenkinsGit#Test_Failures\n\n- gate-requirements-pep8 http:\/\/logs.openstack.org\/61\/65361\/2\/check\/gate-requirements-pep8\/e8429d9 : SUCCESS in 25s\n- gate-requirements-python27 http:\/\/logs.openstack.org\/61\/65361\/2\/check\/gate-requirements-python27\/fb66d97 : SUCCESS in 1m 09s\n- gate-requirements-pypy http:\/\/logs.openstack.org\/61\/65361\/2\/check\/gate-requirements-pypy\/592002c : SUCCESS in 2m 09s\n- check-requirements-integration-dsvm http:\/\/logs.openstack.org\/61\/65361\/2\/check\/check-requirements-integration-dsvm\/8209fb4 : FAILURE in 9m 44s\n- check-tempest-dsvm-full http:\/\/logs.openstack.org\/61\/65361\/2\/check\/check-tempest-dsvm-full\/0db6b3f : SUCCESS in 48m 02s\n- check-tempest-dsvm-postgres-full http:\/\/logs.openstack.org\/61\/65361\/2\/check\/check-tempest-dsvm-postgres-full\/4a0c319 : SUCCESS in 45m 10s\n- check-tempest-dsvm-neutron http:\/\/logs.openstack.org\/61\/65361\/2\/check\/check-tempest-dsvm-neutron\/f4323cc : SUCCESS in 36m 49s\n- gate-tempest-dsvm-large-ops http:\/\/logs.openstack.org\/61\/65361\/2\/check\/gate-tempest-dsvm-large-ops\/1e625fc : SUCCESS in 17m 31s\n- gate-tempest-dsvm-neutron-large-ops http:\/\/logs.openstack.org\/61\/65361\/2\/check\/gate-tempest-dsvm-neutron-large-ops\/ffa7ae8 : SUCCESS in 14m 24s\n- check-grenade-dsvm http:\/\/logs.openstack.org\/61\/65361\/2\/check\/check-grenade-dsvm\/c416726 : SUCCESS in 31m 26s\n- check-swift-dsvm-functional http:\/\/logs.openstack.org\/61\/65361\/2\/check\/check-swift-dsvm-functional\/d027be3 : SUCCESS in 14m 30s\n",
|
||||||
|
"author": {
|
||||||
|
"username": "jenkins",
|
||||||
|
"name": "Jenkins"
|
||||||
|
},
|
||||||
|
"approvals": [
|
||||||
|
{
|
||||||
|
"type": "VRIF",
|
||||||
|
"description": "Verified",
|
||||||
|
"value": "-1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"patchSet": {
|
||||||
|
"createdOn": 1389384794,
|
||||||
|
"ref": "refs\/changes\/61\/65361\/2",
|
||||||
|
"number": "2",
|
||||||
|
"uploader": {
|
||||||
|
"username": "jaegerandi",
|
||||||
|
"name": "Andreas Jaeger",
|
||||||
|
"email": "jaegerandi@gmail.com"
|
||||||
|
},
|
||||||
|
"revision": "10d31584a0696cd77200a8fee45900d2343e295e"
|
||||||
|
},
|
||||||
|
"type": "comment-added",
|
||||||
|
"change": {
|
||||||
|
"topic": "65361",
|
||||||
|
"url": "https:\/\/review.openstack.org\/65361",
|
||||||
|
"number": "65361",
|
||||||
|
"project": "openstack\/requirements",
|
||||||
|
"branch": "master",
|
||||||
|
"owner": {
|
||||||
|
"username": "jaegerandi",
|
||||||
|
"name": "Andreas Jaeger",
|
||||||
|
"email": "jaegerandi@gmail.com"
|
||||||
|
},
|
||||||
|
"id": "Id6a79d3596c6cfaab92cfb8fc89d4298db61b7f0",
|
||||||
|
"subject": "Add openstack-doc-tools"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comment": "Build failed. For information on how to proceed, see https:\/\/wiki.openstack.org\/wiki\/GerritJenkinsGit#Test_Failures\n\n- gate-horizon-pep8 http:\/\/logs.openstack.org\/78\/63078\/19\/check\/gate-horizon-pep8\/37c96e0 : SUCCESS in 2m 54s\n- gate-horizon-docs http:\/\/docs-draft.openstack.org\/78\/63078\/19\/check\/gate-horizon-docs\/53f3535\/doc\/build\/html\/ : SUCCESS in 7m 10s\n- gate-horizon-python26 http:\/\/logs.openstack.org\/78\/63078\/19\/check\/gate-horizon-python26\/1006347 : SUCCESS in 4m 15s\n- gate-horizon-python27 http:\/\/logs.openstack.org\/78\/63078\/19\/check\/gate-horizon-python27\/a9fb840 : SUCCESS in 4m 07s\n- gate-horizon-python27-django14 http:\/\/logs.openstack.org\/78\/63078\/19\/check\/gate-horizon-python27-django14\/1f9c8e5 : SUCCESS in 5m 18s\n- gate-horizon-selenium http:\/\/logs.openstack.org\/78\/63078\/19\/check\/gate-horizon-selenium\/b215898 : SUCCESS in 3m 08s\n- check-tempest-dsvm-full http:\/\/logs.openstack.org\/78\/63078\/19\/check\/check-tempest-dsvm-full\/ab07162 : FAILURE in 54m 09s\n- check-tempest-dsvm-postgres-full http:\/\/logs.openstack.org\/78\/63078\/19\/check\/check-tempest-dsvm-postgres-full\/9bed62d : SUCCESS in 52m 49s\n- check-tempest-dsvm-neutron http:\/\/logs.openstack.org\/78\/63078\/19\/check\/check-tempest-dsvm-neutron\/06a24c0 : SUCCESS in 36m 00s\n- gate-tempest-dsvm-large-ops http:\/\/logs.openstack.org\/78\/63078\/19\/check\/gate-tempest-dsvm-large-ops\/a522f39 : SUCCESS in 13m 33s\n- gate-tempest-dsvm-neutron-large-ops http:\/\/logs.openstack.org\/78\/63078\/19\/check\/gate-tempest-dsvm-neutron-large-ops\/bcbe1da : SUCCESS in 13m 38s\n- check-grenade-dsvm http:\/\/logs.openstack.org\/78\/63078\/19\/check\/check-grenade-dsvm\/9c5b5d0 : SUCCESS in 27m 49s\n",
|
||||||
|
"author": {
|
||||||
|
"username": "jenkins",
|
||||||
|
"name": "Jenkins"
|
||||||
|
},
|
||||||
|
"approvals": [
|
||||||
|
{
|
||||||
|
"type": "VRIF",
|
||||||
|
"description": "Verified",
|
||||||
|
"value": "-1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"patchSet": {
|
||||||
|
"createdOn": 1389383805,
|
||||||
|
"ref": "refs\/changes\/78\/63078\/19",
|
||||||
|
"number": "19",
|
||||||
|
"uploader": {
|
||||||
|
"username": "yves",
|
||||||
|
"name": "Yves-Gwenael Bourhis",
|
||||||
|
"email": "yves-gwenael.bourhis@cloudwatt.com"
|
||||||
|
},
|
||||||
|
"revision": "2e5a51c3f4e0121dbaf47c13b12809f6e7820d09"
|
||||||
|
},
|
||||||
|
"type": "comment-added",
|
||||||
|
"change": {
|
||||||
|
"topic": "bp\/image-flavor-selection-ux-enhancement",
|
||||||
|
"url": "https:\/\/review.openstack.org\/63078",
|
||||||
|
"number": "63078",
|
||||||
|
"project": "openstack\/horizon",
|
||||||
|
"branch": "master",
|
||||||
|
"owner": {
|
||||||
|
"username": "yves",
|
||||||
|
"name": "Yves-Gwenael Bourhis",
|
||||||
|
"email": "yves-gwenael.bourhis@cloudwatt.com"
|
||||||
|
},
|
||||||
|
"id": "I6674ed1983904334c98a7b7d71c58a393858cbc4",
|
||||||
|
"subject": "Changed LaunchInstance workflow to wizard mode"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comment": "Build succeeded.\n\n- check-dg-tempest-dsvm-full http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-dg-tempest-dsvm-full\/6762ddb : SUCCESS in 51m 22s\n- check-dg-tempest-dsvm-full-reexec http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-dg-tempest-dsvm-full-reexec\/e97d803 : SUCCESS in 55m 24s\n- check-tempest-dsvm-full http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-full\/9181576 : SUCCESS in 1h 04m 35s\n- check-tempest-dsvm-postgres-full http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-postgres-full\/74b4386 : SUCCESS in 1h 29m 32s\n- check-tempest-dsvm-neutron http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-neutron\/54850dd : SUCCESS in 39m 48s\n- gate-tempest-dsvm-large-ops http:\/\/logs.openstack.org\/05\/65805\/1\/check\/gate-tempest-dsvm-large-ops\/18d9e01 : SUCCESS in 13m 58s\n- gate-tempest-dsvm-neutron-large-ops http:\/\/logs.openstack.org\/05\/65805\/1\/check\/gate-tempest-dsvm-neutron-large-ops\/ee4b7eb : SUCCESS in 14m 12s\n- check-grenade-dsvm http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-grenade-dsvm\/d1e83f8 : SUCCESS in 35m 05s\n- check-swift-dsvm-functional http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-swift-dsvm-functional\/5f30c9f : SUCCESS in 15m 23s\n- check-tempest-dsvm-full-grizzly http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-full-grizzly\/1b8d155 : FAILURE in 57m 18s (non-voting)\n- check-tempest-dsvm-neutron-grizzly http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-neutron-grizzly\/70ee0a6 : SUCCESS in 22m 14s (non-voting)\n- check-tempest-dsvm-postgres-full-grizzly http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-postgres-full-grizzly\/fa497b2 : FAILURE in 46m 51s (non-voting)\n- check-devstack-dsvm-cells-grizzly http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-devstack-dsvm-cells-grizzly\/5318390 : FAILURE in 13m 30s (non-voting)\n- check-tempest-dsvm-cells-grizzly http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-cells-grizzly\/c01c8a0 : FAILURE in 28m 36s (non-voting)\n- check-tempest-dsvm-cells-full-grizzly http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-cells-full-grizzly\/78b0d12 : FAILURE in 42m 59s (non-voting)\n- check-tempest-dsvm-full-havana http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-full-havana\/183d433 : SUCCESS in 51m 17s (non-voting)\n- check-tempest-dsvm-neutron-havana http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-neutron-havana\/85453e1 : SUCCESS in 31m 06s (non-voting)\n- check-tempest-dsvm-postgres-full-havana http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-postgres-full-havana\/5243bb4 : SUCCESS in 41m 37s (non-voting)\n- check-devstack-dsvm-cells-havana http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-devstack-dsvm-cells-havana\/9432a96 : SUCCESS in 11m 11s (non-voting)\n- check-tempest-dsvm-cells-havana http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-cells-havana\/d856118 : FAILURE in 15m 25s (non-voting)\n- check-tempest-dsvm-cells-full-havana http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-cells-full-havana\/cc09d3c : FAILURE in 25m 32s (non-voting)\n",
|
||||||
|
"author": {
|
||||||
|
"username": "jenkins",
|
||||||
|
"name": "Jenkins"
|
||||||
|
},
|
||||||
|
"approvals": [
|
||||||
|
{
|
||||||
|
"type": "VRIF",
|
||||||
|
"description": "Verified",
|
||||||
|
"value": "1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"patchSet": {
|
||||||
|
"createdOn": 1389306576,
|
||||||
|
"ref": "refs\/changes\/05\/65805\/1",
|
||||||
|
"number": "1",
|
||||||
|
"uploader": {
|
||||||
|
"username": "russellb",
|
||||||
|
"name": "Russell Bryant",
|
||||||
|
"email": "rbryant@redhat.com"
|
||||||
|
},
|
||||||
|
"revision": "3ca110f8dc6a552e951074faaca3a11ce65e40f3"
|
||||||
|
},
|
||||||
|
"type": "comment-added",
|
||||||
|
"change": {
|
||||||
|
"topic": "slow-down-there-cowboy",
|
||||||
|
"url": "https:\/\/review.openstack.org\/65805",
|
||||||
|
"number": "65805",
|
||||||
|
"project": "openstack-infra\/devstack-gate",
|
||||||
|
"branch": "master",
|
||||||
|
"owner": {
|
||||||
|
"username": "russellb",
|
||||||
|
"name": "Russell Bryant",
|
||||||
|
"email": "rbryant@redhat.com"
|
||||||
|
},
|
||||||
|
"id": "I2338ebf5df8bced935e9ed9b0ebd2d4e859b5dbe",
|
||||||
|
"subject": "Cut tempest concurrency in half"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comment": "Build succeeded.\n\n- gate-noop http:\/\/logs.openstack.org\/78\/65378\/15\/check\/gate-noop\/05e95c4 : SUCCESS in 0s\n",
|
||||||
|
"author": {
|
||||||
|
"username": "jenkins",
|
||||||
|
"name": "Jenkins"
|
||||||
|
},
|
||||||
|
"approvals": [
|
||||||
|
{
|
||||||
|
"type": "VRIF",
|
||||||
|
"description": "Verified",
|
||||||
|
"value": "1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"patchSet": {
|
||||||
|
"createdOn": 1389391347,
|
||||||
|
"ref": "refs\/changes\/78\/65378\/15",
|
||||||
|
"number": "15",
|
||||||
|
"uploader": {
|
||||||
|
"username": "diane-fleming",
|
||||||
|
"name": "Diane Fleming",
|
||||||
|
"email": "diane.fleming@rackspace.com"
|
||||||
|
},
|
||||||
|
"revision": "4fe4f8b6dda390c432b2c6d2f6cff2152d3475f3"
|
||||||
|
},
|
||||||
|
"type": "comment-added",
|
||||||
|
"change": {
|
||||||
|
"topic": "1187119-a",
|
||||||
|
"url": "https:\/\/review.openstack.org\/65378",
|
||||||
|
"number": "65378",
|
||||||
|
"project": "openstack\/api-site",
|
||||||
|
"branch": "master",
|
||||||
|
"owner": {
|
||||||
|
"username": "diane-fleming",
|
||||||
|
"name": "Diane Fleming",
|
||||||
|
"email": "diane.fleming@rackspace.com"
|
||||||
|
},
|
||||||
|
"id": "I82331b1c3cfc5b19f91f7ac1379476e6a9e6806d",
|
||||||
|
"subject": "Update object-api wadl with comments from Donagh"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comment": "Build failed. For information on how to proceed, see https:\/\/wiki.openstack.org\/wiki\/GerritJenkinsGit#Test_Failures\n\n- gate-keystone-pep8 http:\/\/logs.openstack.org\/49\/64749\/6\/check\/gate-keystone-pep8\/16e0b97 : SUCCESS in 2m 25s\n- gate-keystone-docs http:\/\/docs-draft.openstack.org\/49\/64749\/6\/check\/gate-keystone-docs\/77c8f7a\/doc\/build\/html\/ : SUCCESS in 5m 25s\n- gate-keystone-python26 http:\/\/logs.openstack.org\/49\/64749\/6\/check\/gate-keystone-python26\/d3fd328 : FAILURE in 18m 04s\n- gate-keystone-python27 http:\/\/logs.openstack.org\/49\/64749\/6\/check\/gate-keystone-python27\/5dd41fe : FAILURE in 10m 01s\n- check-tempest-dsvm-full http:\/\/logs.openstack.org\/49\/64749\/6\/check\/check-tempest-dsvm-full\/fce905d : SUCCESS in 46m 00s\n- check-tempest-dsvm-postgres-full http:\/\/logs.openstack.org\/49\/64749\/6\/check\/check-tempest-dsvm-postgres-full\/e5cd968 : SUCCESS in 53m 30s\n- check-tempest-dsvm-neutron http:\/\/logs.openstack.org\/49\/64749\/6\/check\/check-tempest-dsvm-neutron\/0673b30 : SUCCESS in 37m 25s\n- gate-tempest-dsvm-large-ops http:\/\/logs.openstack.org\/49\/64749\/6\/check\/gate-tempest-dsvm-large-ops\/bdc661a : SUCCESS in 13m 21s\n- gate-tempest-dsvm-neutron-large-ops http:\/\/logs.openstack.org\/49\/64749\/6\/check\/gate-tempest-dsvm-neutron-large-ops\/991887c : SUCCESS in 12m 28s\n- check-grenade-dsvm http:\/\/logs.openstack.org\/49\/64749\/6\/check\/check-grenade-dsvm\/d098069 : SUCCESS in 31m 05s\n- check-swift-dsvm-functional http:\/\/logs.openstack.org\/49\/64749\/6\/check\/check-swift-dsvm-functional\/2f9377b : SUCCESS in 11m 56s\n",
|
||||||
|
"author": {
|
||||||
|
"username": "jenkins",
|
||||||
|
"name": "Jenkins"
|
||||||
|
},
|
||||||
|
"approvals": [
|
||||||
|
{
|
||||||
|
"type": "VRIF",
|
||||||
|
"description": "Verified",
|
||||||
|
"value": "-1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"patchSet": {
|
||||||
|
"createdOn": 1389378289,
|
||||||
|
"ref": "refs\/changes\/49\/64749\/6",
|
||||||
|
"number": "6",
|
||||||
|
"uploader": {
|
||||||
|
"username": "blk-u",
|
||||||
|
"name": "Brant Knudson",
|
||||||
|
"email": "bknudson@us.ibm.com"
|
||||||
|
},
|
||||||
|
"revision": "06b14616cb2a11514b0c151cc213c1ab5cea324b"
|
||||||
|
},
|
||||||
|
"type": "comment-added",
|
||||||
|
"change": {
|
||||||
|
"topic": "bug\/1265108",
|
||||||
|
"url": "https:\/\/review.openstack.org\/64749",
|
||||||
|
"number": "64749",
|
||||||
|
"project": "openstack\/keystone",
|
||||||
|
"branch": "master",
|
||||||
|
"owner": {
|
||||||
|
"username": "blk-u",
|
||||||
|
"name": "Brant Knudson",
|
||||||
|
"email": "bknudson@us.ibm.com"
|
||||||
|
},
|
||||||
|
"id": "I890a1c798d7f4a8a345404cd7754708ab0d36651",
|
||||||
|
"subject": "Enhance auth tests for non-default default_domain_id"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comment": "Build succeeded.\n\n- gate-neutron-pep8 http:\/\/logs.openstack.org\/02\/65902\/3\/check\/gate-neutron-pep8\/0ef123c : SUCCESS in 2m 13s\n- gate-neutron-docs http:\/\/docs-draft.openstack.org\/02\/65902\/3\/check\/gate-neutron-docs\/4a7a2ce\/doc\/build\/html\/ : SUCCESS in 1m 43s\n- gate-neutron-python26 http:\/\/logs.openstack.org\/02\/65902\/3\/check\/gate-neutron-python26\/d3e596e : SUCCESS in 43m 38s\n- gate-neutron-python27 http:\/\/logs.openstack.org\/02\/65902\/3\/check\/gate-neutron-python27\/525acec : SUCCESS in 27m 10s\n- check-tempest-dsvm-neutron http:\/\/logs.openstack.org\/02\/65902\/3\/check\/check-tempest-dsvm-neutron\/469682a : SUCCESS in 35m 59s\n- check-tempest-dsvm-neutron-pg http:\/\/logs.openstack.org\/02\/65902\/3\/check\/check-tempest-dsvm-neutron-pg\/91e8f4f : SUCCESS in 37m 11s\n- check-tempest-dsvm-neutron-isolated http:\/\/logs.openstack.org\/02\/65902\/3\/check\/check-tempest-dsvm-neutron-isolated\/90021b9 : SUCCESS in 41m 27s\n- check-tempest-dsvm-neutron-pg-isolated http:\/\/logs.openstack.org\/02\/65902\/3\/check\/check-tempest-dsvm-neutron-pg-isolated\/7bc809a : SUCCESS in 45m 35s\n- gate-tempest-dsvm-neutron-large-ops http:\/\/logs.openstack.org\/02\/65902\/3\/check\/gate-tempest-dsvm-neutron-large-ops\/aea24f9 : SUCCESS in 15m 01s\n- check-grenade-dsvm-neutron http:\/\/logs.openstack.org\/02\/65902\/3\/check\/check-grenade-dsvm-neutron\/59354b6 : FAILURE in 20m 16s (non-voting)\n- check-devstack-dsvm-neutron http:\/\/logs.openstack.org\/02\/65902\/3\/check\/check-devstack-dsvm-neutron\/d347313 : FAILURE in 17m 10s (non-voting)\n",
|
||||||
|
"author": {
|
||||||
|
"username": "jenkins",
|
||||||
|
"name": "Jenkins"
|
||||||
|
},
|
||||||
|
"approvals": [
|
||||||
|
{
|
||||||
|
"type": "VRIF",
|
||||||
|
"description": "Verified",
|
||||||
|
"value": "1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"patchSet": {
|
||||||
|
"createdOn": 1389387264,
|
||||||
|
"ref": "refs\/changes\/02\/65902\/3",
|
||||||
|
"number": "3",
|
||||||
|
"uploader": {
|
||||||
|
"username": "nanjj",
|
||||||
|
"name": "Jun Jie Nan",
|
||||||
|
"email": "nanjj@cn.ibm.com"
|
||||||
|
},
|
||||||
|
"revision": "8044bcbfe8f10aa3f965992e30e9548258d6c736"
|
||||||
|
},
|
||||||
|
"type": "comment-added",
|
||||||
|
"change": {
|
||||||
|
"topic": "bugs\/1267682",
|
||||||
|
"url": "https:\/\/review.openstack.org\/65902",
|
||||||
|
"number": "65902",
|
||||||
|
"project": "openstack\/neutron",
|
||||||
|
"branch": "master",
|
||||||
|
"owner": {
|
||||||
|
"username": "nanjj",
|
||||||
|
"name": "Jun Jie Nan",
|
||||||
|
"email": "nanjj@cn.ibm.com"
|
||||||
|
},
|
||||||
|
"id": "Id52c04b4739d2d11fe52d4b1631cb4f39e6b577f",
|
||||||
|
"subject": "Check vxlan enablement via modinfo"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comment": "Build succeeded.\n\n- gate-glance-pep8 http:\/\/logs.openstack.org\/64\/66064\/1\/check\/gate-glance-pep8\/250a70c : SUCCESS in 1m 50s\n- gate-glance-docs http:\/\/docs-draft.openstack.org\/64\/66064\/1\/check\/gate-glance-docs\/c641b72\/doc\/build\/html\/ : SUCCESS in 1m 55s\n- gate-glance-python26 http:\/\/logs.openstack.org\/64\/66064\/1\/check\/gate-glance-python26\/c36e87a : SUCCESS in 8m 57s\n- gate-glance-python27 http:\/\/logs.openstack.org\/64\/66064\/1\/check\/gate-glance-python27\/fb29142 : SUCCESS in 12m 30s\n- check-tempest-dsvm-full http:\/\/logs.openstack.org\/64\/66064\/1\/check\/check-tempest-dsvm-full\/21c38f3 : SUCCESS in 43m 54s\n- check-tempest-dsvm-postgres-full http:\/\/logs.openstack.org\/64\/66064\/1\/check\/check-tempest-dsvm-postgres-full\/958323e : SUCCESS in 42m 43s\n- check-tempest-dsvm-neutron http:\/\/logs.openstack.org\/64\/66064\/1\/check\/check-tempest-dsvm-neutron\/3824a0d : SUCCESS in 35m 09s\n- gate-tempest-dsvm-large-ops http:\/\/logs.openstack.org\/64\/66064\/1\/check\/gate-tempest-dsvm-large-ops\/3f113a8 : SUCCESS in 13m 20s\n- gate-tempest-dsvm-neutron-large-ops http:\/\/logs.openstack.org\/64\/66064\/1\/check\/gate-tempest-dsvm-neutron-large-ops\/f527f8c : SUCCESS in 12m 49s\n- check-grenade-dsvm http:\/\/logs.openstack.org\/64\/66064\/1\/check\/check-grenade-dsvm\/ab6a585 : SUCCESS in 28m 47s\n",
|
||||||
|
"author": {
|
||||||
|
"username": "jenkins",
|
||||||
|
"name": "Jenkins"
|
||||||
|
},
|
||||||
|
"approvals": [
|
||||||
|
{
|
||||||
|
"type": "VRIF",
|
||||||
|
"description": "Verified",
|
||||||
|
"value": "1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"patchSet": {
|
||||||
|
"createdOn": 1389388172,
|
||||||
|
"ref": "refs\/changes\/64\/66064\/1",
|
||||||
|
"number": "1",
|
||||||
|
"uploader": {
|
||||||
|
"username": "arnaud",
|
||||||
|
"name": "Arnaud Legendre",
|
||||||
|
"email": "arnaudleg@gmail.com"
|
||||||
|
},
|
||||||
|
"revision": "b05c9313f6873239897d7c88babdfa8ebe5fefed"
|
||||||
|
},
|
||||||
|
"type": "comment-added",
|
||||||
|
"change": {
|
||||||
|
"topic": "bug\/1253497",
|
||||||
|
"url": "https:\/\/review.openstack.org\/66064",
|
||||||
|
"number": "66064",
|
||||||
|
"project": "openstack\/glance",
|
||||||
|
"branch": "master",
|
||||||
|
"owner": {
|
||||||
|
"username": "arnaud",
|
||||||
|
"name": "Arnaud Legendre",
|
||||||
|
"email": "arnaudleg@gmail.com"
|
||||||
|
},
|
||||||
|
"id": "I657e20ac39fbace60f230652912a4bf792836206",
|
||||||
|
"subject": "Update `openstack\/common\/context.py' from Oslo"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comment": "Build succeeded.\n\n- gate-savanna-docs http:\/\/docs-draft.openstack.org\/25\/65925\/1\/gate\/gate-savanna-docs\/412dd7e\/doc\/build\/html\/ : SUCCESS in 2m 19s\n- gate-savanna-pep8 http:\/\/logs.openstack.org\/25\/65925\/1\/gate\/gate-savanna-pep8\/0e076e8 : SUCCESS in 2m 40s\n- gate-savanna-python26 http:\/\/logs.openstack.org\/25\/65925\/1\/gate\/gate-savanna-python26\/6f15ba8 : SUCCESS in 1m 57s\n- gate-savanna-python27 http:\/\/logs.openstack.org\/25\/65925\/1\/gate\/gate-savanna-python27\/e0545bd : SUCCESS in 2m 12s\n- gate-tempest-dsvm-savanna-full http:\/\/logs.openstack.org\/25\/65925\/1\/gate\/gate-tempest-dsvm-savanna-full\/04a5c22 : SUCCESS in 53m 34s (non-voting)\n- gate-tempest-dsvm-savanna-postgres-full http:\/\/logs.openstack.org\/25\/65925\/1\/gate\/gate-tempest-dsvm-savanna-postgres-full\/0143007 : SUCCESS in 43m 15s (non-voting)\n- gate-tempest-dsvm-savanna-neutron http:\/\/logs.openstack.org\/25\/65925\/1\/gate\/gate-tempest-dsvm-savanna-neutron\/350d103 : SUCCESS in 39m 27s (non-voting)\n",
|
||||||
|
"author": {
|
||||||
|
"username": "jenkins",
|
||||||
|
"name": "Jenkins"
|
||||||
|
},
|
||||||
|
"approvals": [
|
||||||
|
{
|
||||||
|
"type": "VRIF",
|
||||||
|
"description": "Verified",
|
||||||
|
"value": "2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"patchSet": {
|
||||||
|
"createdOn": 1389354908,
|
||||||
|
"ref": "refs\/changes\/25\/65925\/1",
|
||||||
|
"number": "1",
|
||||||
|
"uploader": {
|
||||||
|
"username": "sreshetniak",
|
||||||
|
"name": "Sergey Reshetnyak",
|
||||||
|
"email": "sreshetniak@mirantis.com"
|
||||||
|
},
|
||||||
|
"revision": "fd9bee400259d370e837799236b0a4a6f0343438"
|
||||||
|
},
|
||||||
|
"type": "comment-added",
|
||||||
|
"change": {
|
||||||
|
"topic": "del-param",
|
||||||
|
"url": "https:\/\/review.openstack.org\/65925",
|
||||||
|
"number": "65925",
|
||||||
|
"project": "openstack\/savanna",
|
||||||
|
"branch": "master",
|
||||||
|
"owner": {
|
||||||
|
"username": "sreshetniak",
|
||||||
|
"name": "Sergey Reshetnyak",
|
||||||
|
"email": "sreshetniak@mirantis.com"
|
||||||
|
},
|
||||||
|
"id": "I3e48e344b079c8eef81a18176147b8aec3c9f3b1",
|
||||||
|
"subject": "Remove unused node_group parameter in get_config_value"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comment": "Build succeeded.\n\n- gate-heat-docs http:\/\/docs-draft.openstack.org\/74\/61074\/12\/gate\/gate-heat-docs\/6afb5bb\/doc\/build\/html\/ : SUCCESS in 2m 20s\n- gate-heat-pep8 http:\/\/logs.openstack.org\/74\/61074\/12\/gate\/gate-heat-pep8\/9e7f091 : SUCCESS in 2m 33s\n- gate-heat-python26 http:\/\/logs.openstack.org\/74\/61074\/12\/gate\/gate-heat-python26\/011dd18 : SUCCESS in 2m 50s\n- gate-heat-python27 http:\/\/logs.openstack.org\/74\/61074\/12\/gate\/gate-heat-python27\/c883c86 : SUCCESS in 1m 54s\n- gate-tempest-dsvm-full http:\/\/logs.openstack.org\/74\/61074\/12\/gate\/gate-tempest-dsvm-full\/f228dfb : SUCCESS in 42m 46s\n- gate-tempest-dsvm-postgres-full http:\/\/logs.openstack.org\/74\/61074\/12\/gate\/gate-tempest-dsvm-postgres-full\/6f05326 : SUCCESS in 1h 21m 14s\n- gate-tempest-dsvm-neutron http:\/\/logs.openstack.org\/74\/61074\/12\/gate\/gate-tempest-dsvm-neutron\/3b361dc : SUCCESS in 43m 33s\n- gate-tempest-dsvm-large-ops http:\/\/logs.openstack.org\/74\/61074\/12\/gate\/gate-tempest-dsvm-large-ops\/47d0217 : SUCCESS in 14m 39s\n- gate-tempest-dsvm-neutron-large-ops http:\/\/logs.openstack.org\/74\/61074\/12\/gate\/gate-tempest-dsvm-neutron-large-ops\/cb67ba1 : SUCCESS in 15m 26s\n",
|
||||||
|
"author": {
|
||||||
|
"username": "jenkins",
|
||||||
|
"name": "Jenkins"
|
||||||
|
},
|
||||||
|
"approvals": [
|
||||||
|
{
|
||||||
|
"type": "VRIF",
|
||||||
|
"description": "Verified",
|
||||||
|
"value": "2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"patchSet": {
|
||||||
|
"createdOn": 1387806669,
|
||||||
|
"ref": "refs\/changes\/74\/61074\/12",
|
||||||
|
"number": "12",
|
||||||
|
"uploader": {
|
||||||
|
"username": "smelikyan",
|
||||||
|
"name": "Serg Melikyan",
|
||||||
|
"email": "smelikyan@mirantis.com"
|
||||||
|
},
|
||||||
|
"revision": "af064c7a5304c672f7d71e4c8df5f69c195c739a"
|
||||||
|
},
|
||||||
|
"type": "comment-added",
|
||||||
|
"change": {
|
||||||
|
"topic": "bug\/1259078",
|
||||||
|
"url": "https:\/\/review.openstack.org\/61074",
|
||||||
|
"number": "61074",
|
||||||
|
"project": "openstack\/heat",
|
||||||
|
"branch": "master",
|
||||||
|
"owner": {
|
||||||
|
"username": "smelikyan",
|
||||||
|
"name": "Serg Melikyan",
|
||||||
|
"email": "smelikyan@mirantis.com"
|
||||||
|
},
|
||||||
|
"id": "I9afd1a8c222110899a90a940e7a549278c4467b7",
|
||||||
|
"subject": "Added session_persistence property to VIP"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
@ -1,116 +0,0 @@
|
|||||||
# All Rights Reserved.
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
# not use this file except in compliance with the License. You may obtain
|
|
||||||
# a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
# License for the specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
|
|
||||||
from elastic_recheck import elasticRecheck
|
|
||||||
from elastic_recheck import loader
|
|
||||||
from elastic_recheck import results
|
|
||||||
from elastic_recheck import tests
|
|
||||||
|
|
||||||
|
|
||||||
def fake_queries(directory='queries', skip_resolved=True):
|
|
||||||
queries = [
|
|
||||||
{'query': '@message:"fake query" AND @fields.filename:"fake"\n',
|
|
||||||
'bug': 1226337},
|
|
||||||
{'query': 'magic query',
|
|
||||||
'bug': 1234567},
|
|
||||||
{'query': '@message:"fake_query3" AND @fields.filename:"fake"\n',
|
|
||||||
'bug': 1235437}]
|
|
||||||
if not skip_resolved:
|
|
||||||
queries.append({'query': 'magic query',
|
|
||||||
'bug': 1252514,
|
|
||||||
'resolved_at': 'Tue Dec 10 12:08:42 EST 2013'})
|
|
||||||
return queries
|
|
||||||
|
|
||||||
|
|
||||||
def _fake_search(query, size=None):
|
|
||||||
files = ['console.html', 'logs/screen-n-api.txt',
|
|
||||||
'logs/screen-n-cpu.txt', 'logs/screen-n-sch.txt',
|
|
||||||
'logs/screen-c-api.txt', 'logs/screen-c-vol.txt',
|
|
||||||
'logs/syslog.txt']
|
|
||||||
file_list = []
|
|
||||||
for f in files:
|
|
||||||
file_list.append({'term': f})
|
|
||||||
log_url = ('http://logs.openstack.org/57/51057/1/gate/gate-tempest-'
|
|
||||||
'devstack-vm-full/f8965ee/console.html')
|
|
||||||
hit_dict = {'_source': {'@fields': {'log_url': log_url}}}
|
|
||||||
if 'magic query' in query['query']['query_string']['query']:
|
|
||||||
fake_result = results.ResultSet(
|
|
||||||
{'hits': {'total': 2, 'hits': [hit_dict, hit_dict]},
|
|
||||||
'facets': {'tag': {'terms': file_list}}})
|
|
||||||
else:
|
|
||||||
fake_result = results.ResultSet(
|
|
||||||
{'hits': {'total': 1, 'hits': [hit_dict]},
|
|
||||||
'facets': {'tag': {'terms': file_list}}})
|
|
||||||
return fake_result
|
|
||||||
|
|
||||||
|
|
||||||
def _fake_urls_match(comment, results):
|
|
||||||
# TODO(sdague): this is not a good fake url work around, however it will
|
|
||||||
# get us through the merge in of the new result sets. We'll eventually
|
|
||||||
# make this actual life like data.
|
|
||||||
if len(results) == 2:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def _fake_is_ready_urls_match(comment, results):
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def _fake_is_ready(change_number, patch_number, comment):
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
class TestClassifier(tests.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(TestClassifier, self).setUp()
|
|
||||||
self.stubs.Set(loader, 'load', fake_queries)
|
|
||||||
self.classifier = elasticRecheck.Classifier('queries.yaml')
|
|
||||||
|
|
||||||
def test_is_ready(self):
|
|
||||||
self.stubs.Set(self.classifier.es, 'search', _fake_search)
|
|
||||||
result = self.classifier._is_ready(
|
|
||||||
'49282',
|
|
||||||
'3',
|
|
||||||
'BLAH http://logs.openstack.org/57/51057/1/gate/'
|
|
||||||
'gate-tempest-devstack-vm-full/f8965ee'
|
|
||||||
)
|
|
||||||
self.assertTrue(result)
|
|
||||||
|
|
||||||
def test_classify(self):
|
|
||||||
self.stubs.Set(self.classifier.es, 'search', _fake_search)
|
|
||||||
self.stubs.Set(self.classifier, '_urls_match', _fake_urls_match)
|
|
||||||
self.stubs.Set(self.classifier, '_is_ready', _fake_is_ready)
|
|
||||||
bug_numbers = self.classifier.classify(
|
|
||||||
'47463',
|
|
||||||
'3',
|
|
||||||
' blah http://logs.openstack.org/63/47463/3/gate/gate-tempest'
|
|
||||||
'-devstack-vm-postgres-full/99bb8f6'
|
|
||||||
)
|
|
||||||
self.assertEqual(bug_numbers, [1234567])
|
|
||||||
|
|
||||||
def test_classify_without_skipping_resolved_bugs(self):
|
|
||||||
self.stubs.Set(self.classifier.es, 'search', _fake_search)
|
|
||||||
self.stubs.Set(self.classifier, '_urls_match', _fake_urls_match)
|
|
||||||
self.stubs.Set(self.classifier, '_is_ready', _fake_is_ready)
|
|
||||||
bug_numbers = self.classifier.classify(
|
|
||||||
'47463',
|
|
||||||
'3',
|
|
||||||
' blah http://logs.openstack.org/63/47463/3/gate/gate-tempest'
|
|
||||||
'-devstack-vm-postgres-full/99bb8f6',
|
|
||||||
False
|
|
||||||
)
|
|
||||||
self.assertEqual(bug_numbers, [1234567, 1252514])
|
|
@ -1,51 +0,0 @@
|
|||||||
# All Rights Reserved.
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
# not use this file except in compliance with the License. You may obtain
|
|
||||||
# a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
# License for the specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
|
|
||||||
import urllib2
|
|
||||||
|
|
||||||
from elastic_recheck import elasticRecheck
|
|
||||||
from elastic_recheck import tests
|
|
||||||
|
|
||||||
|
|
||||||
class TestRequiredFiles(tests.TestCase):
|
|
||||||
def test_url(self):
|
|
||||||
url = elasticRecheck.RequiredFiles.prep_url(
|
|
||||||
'http://logs.openstack.org/13/46613/2/check/'
|
|
||||||
'gate-tempest-devstack-vm-full/864bf44/console.html')
|
|
||||||
self.assertEqual(
|
|
||||||
url,
|
|
||||||
'http://logs.openstack.org/13/46613/2/check/'
|
|
||||||
'gate-tempest-devstack-vm-full/864bf44')
|
|
||||||
|
|
||||||
def _fake_urlopen(self, url):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def test_files_at_url_pass(self):
|
|
||||||
self.stubs.Set(urllib2, 'urlopen', self._fake_urlopen)
|
|
||||||
result = elasticRecheck.RequiredFiles.files_at_url(
|
|
||||||
'http://logs.openstack.org/13/46613/2/check/'
|
|
||||||
'gate-tempest-devstack-vm-full/864bf44')
|
|
||||||
self.assertTrue(result)
|
|
||||||
|
|
||||||
def _invalid_url_open(self, url):
|
|
||||||
raise urllib2.HTTPError(url, 404, 'NotFound', '', None)
|
|
||||||
|
|
||||||
def test_files_at_url_fail(self):
|
|
||||||
self.stubs.Set(urllib2, 'urlopen', self._invalid_url_open)
|
|
||||||
self.assertFalse(elasticRecheck.RequiredFiles.files_at_url(
|
|
||||||
'http://logs.openstack.org/02/44502/7/check/'
|
|
||||||
'gate-tempest-devstack-vm-neutron/4f386e5'))
|
|
||||||
self.assertFalse(elasticRecheck.RequiredFiles.files_at_url(
|
|
||||||
'http://logs.openstack.org/45/47445/3/check/'
|
|
||||||
'gate-tempest-devstack-vm-full/0e43e09/'))
|
|
@ -14,26 +14,50 @@
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
import fixtures
|
||||||
|
import mock
|
||||||
|
|
||||||
from elastic_recheck import elasticRecheck
|
from elastic_recheck import elasticRecheck
|
||||||
from elastic_recheck import tests
|
from elastic_recheck import tests
|
||||||
|
import elastic_recheck.tests.unit.fake_gerrit as fg
|
||||||
|
|
||||||
|
|
||||||
class TestStream(tests.TestCase):
|
class TestStream(tests.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestStream, self).setUp()
|
super(TestStream, self).setUp()
|
||||||
with open("elastic_recheck/tests/unit/jenkins/events.json") as f:
|
self.useFixture(fixtures.MonkeyPatch(
|
||||||
j = json.load(f)
|
'gerritlib.gerrit.Gerrit',
|
||||||
self.events = j['events']
|
fg.Gerrit))
|
||||||
|
|
||||||
def test_gerrit_parsing_none(self):
|
def test_gerrit_stream(self):
|
||||||
self.assertFalse(
|
"""Tests that we can use our mock gerrit to process events."""
|
||||||
elasticRecheck.Stream.parse_jenkins_failure(self.events[1]))
|
with mock.patch.object(
|
||||||
self.assertFalse(
|
elasticRecheck.Stream, '_does_es_have_data') as mock_data:
|
||||||
elasticRecheck.Stream.parse_jenkins_failure(self.events[2]))
|
mock_data.return_value = True
|
||||||
|
stream = elasticRecheck.Stream("", "", "")
|
||||||
|
|
||||||
|
# there are currently 10 events in the stream, 3 are
|
||||||
|
# failures
|
||||||
|
for i in xrange(3):
|
||||||
|
event = stream.get_failed_tempest()
|
||||||
|
self.assertEqual(event['author']['username'], 'jenkins')
|
||||||
|
self.assertIn('Build failed', event['comment'])
|
||||||
|
self.assertRaises(
|
||||||
|
fg.GerritDone,
|
||||||
|
stream.get_failed_tempest)
|
||||||
|
|
||||||
def test_gerrit_parsing(self):
|
def test_gerrit_parsing(self):
|
||||||
jobs = elasticRecheck.Stream.parse_jenkins_failure(self.events[0])
|
with open("elastic_recheck/tests/unit/jenkins/events.json") as f:
|
||||||
|
j = json.load(f)
|
||||||
|
events = j['events']
|
||||||
|
|
||||||
|
self.assertFalse(
|
||||||
|
elasticRecheck.Stream.parse_jenkins_failure(events[1]))
|
||||||
|
self.assertFalse(
|
||||||
|
elasticRecheck.Stream.parse_jenkins_failure(events[2]))
|
||||||
|
|
||||||
|
jobs = elasticRecheck.Stream.parse_jenkins_failure(events[0])
|
||||||
self.assertIn('check-requirements-integration-dsvm', jobs)
|
self.assertIn('check-requirements-integration-dsvm', jobs)
|
||||||
self.assertIn('check-tempest-dsvm-full', jobs)
|
self.assertIn('check-tempest-dsvm-full', jobs)
|
||||||
self.assertIn('check-tempest-dsvm-postgres-full', jobs)
|
self.assertIn('check-tempest-dsvm-postgres-full', jobs)
|
||||||
|
@ -10,3 +10,4 @@ testrepository>=0.0.17
|
|||||||
testscenarios>=0.4,<0.5
|
testscenarios>=0.4,<0.5
|
||||||
testtools>=0.9.32
|
testtools>=0.9.32
|
||||||
mox>=0.5.3
|
mox>=0.5.3
|
||||||
|
mock>=1.0
|
||||||
|
Loading…
Reference in New Issue
Block a user