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

Side by Side Diff: tools/utils.py

Issue 2640093005: Buildbot: Change --copy-crashdumps to do the actual archiving to CloudStorage. (Closed)
Patch Set: Created 3 years, 11 months 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 unified diff | Download patch
« no previous file with comments | « tools/testing/dart/test_progress.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 # for details. All rights reserved. Use of this source code is governed by a 2 # for details. All rights reserved. Use of this source code is governed by a
3 # BSD-style license that can be found in the LICENSE file. 3 # BSD-style license that can be found in the LICENSE file.
4 4
5 # This file contains a set of utilities functions used by other Python-based 5 # This file contains a set of utilities functions used by other Python-based
6 # scripts. 6 # scripts.
7 7
8 import commands 8 import commands
9 import datetime 9 import datetime
10 import glob
11 import imp
10 import json 12 import json
11 import os 13 import os
12 import platform 14 import platform
13 import re 15 import re
14 import shutil 16 import shutil
15 import subprocess 17 import subprocess
18 import sys
19 import tarfile
16 import tempfile 20 import tempfile
17 import sys 21 import uuid
22
23 try:
24 # Not available on Windows.
25 import resource
26 except:
27 pass
28
29 DART_DIR = os.path.abspath(
30 os.path.normpath(os.path.join(__file__, '..', '..')))
31
32 def GetBotUtils():
33 '''Dynamically load the tools/bots/bot_utils.py python module.'''
34 return imp.load_source('bot_utils', os.path.join(DART_DIR, 'tools', 'bots', 'b ot_utils.py'))
18 35
19 class Version(object): 36 class Version(object):
20 def __init__(self, channel, major, minor, patch, prerelease, 37 def __init__(self, channel, major, minor, patch, prerelease,
21 prerelease_patch): 38 prerelease_patch):
22 self.channel = channel 39 self.channel = channel
23 self.major = major 40 self.major = major
24 self.minor = minor 41 self.minor = minor
25 self.patch = patch 42 self.patch = patch
26 self.prerelease = prerelease 43 self.prerelease = prerelease
27 self.prerelease_patch = prerelease_patch 44 self.prerelease_patch = prerelease_patch
(...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after
650 667
651 def __enter__(self): 668 def __enter__(self):
652 self._old_cwd = os.getcwd() 669 self._old_cwd = os.getcwd()
653 print "Enter directory = ", self._working_directory 670 print "Enter directory = ", self._working_directory
654 os.chdir(self._working_directory) 671 os.chdir(self._working_directory)
655 672
656 def __exit__(self, *_): 673 def __exit__(self, *_):
657 print "Enter directory = ", self._old_cwd 674 print "Enter directory = ", self._old_cwd
658 os.chdir(self._old_cwd) 675 os.chdir(self._old_cwd)
659 676
677 # This class finds and archives all core.* files from the current working
678 # directory and all binaries copied by UnexpectedCrashDumpArchiver into
679 # the current working directory (see tools/testing/dart/test_progress.dart).
680 class CoreDumpArchiver(object):
681 def __init__(self, args):
682 self._enabled = '--copy-coredumps' in args and GuessOS() == 'linux'
683 self._search_dir = os.getcwd()
684 self._bucket = 'dart-temp-crash-archive'
685 self._old_limits = None
686
687 def __enter__(self):
688 if not self._enabled:
689 return
690
691 # Cleanup any stale coredumps
692 coredumps = self._find_coredumps()
693 if coredumps:
694 print "WARNING: Found stale coredumps, removing"
695 MarkCurrentStepWarning()
696 self._remove_coredumps(coredumps)
697
698 self._old_limits = resource.getrlimit(resource.RLIMIT_CORE)
699
700 # Bump core limits to unlimited if core_pattern is correctly configured.
701 if self._check_core_dump_pattern(fatal=False):
702 resource.setrlimit(resource.RLIMIT_CORE, (-1, -1))
703
704 def __exit__(self, *_):
705 if not self._enabled:
706 return
707
708 # Restore old core limit.
709 resource.setrlimit(resource.RLIMIT_CORE, self._old_limits)
710
711 # Check that kernel was correctly configured to use core.%p
712 # core_pattern.
713 self._check_core_dump_pattern(fatal=True)
714
715 coredumps = self._find_coredumps()
716 if coredumps:
717 # If we get a ton of crashes, only archive 10 dumps.
718 archive_coredumps = coredumps[:10]
719 print 'Archiving coredumps: %s' % ', '.join(archive_coredumps)
720 sys.stdout.flush()
721 self._archive(archive_coredumps)
722 self._remove_coredumps(coredumps)
723 coredumps = self._find_coredumps()
724 assert not coredumps
725
726 def _find_coredumps(self):
727 return glob.glob(os.path.join(self._search_dir, 'core.*'))
728
729 def _remove_coredumps(self, coredumps):
730 for name in coredumps:
731 os.unlink(name)
732
733 def _archive(self, coredumps):
734 bot_utils = GetBotUtils()
735 gsutil = bot_utils.GSUtil()
736 storage_path = '%s/%s/' % (self._bucket, uuid.uuid4())
737 gs_prefix = 'gs://%s' % storage_path
738 http_prefix = 'https://storage.cloud.google.com/%s' % storage_path
739
740 for core in coredumps:
741 # Sanitize the name: actual cores follow 'core.%d' pattern, crashed
742 # binaries are copied next to cores and named 'core.<binary_name>'.
743 suffix = os.path.basename(core).split('.')[1]
744 try:
745 # Check if suffix is an integer - in this case it's an actual core.
746 clean_name = 'core.%d' % int(suffix)
747 except:
748 # This is not a coredump but a crashed binary.
749 clean_name = suffix
750
751 tarname = '%s.tar.gz' % clean_name
752
753 # Create a .tar.gz archive out of a crash folder that contains
754 # both binary and the core dump.
755 tar = tarfile.open(tarname, mode='w:gz')
756 tar.add(core, arcname=clean_name)
757 tar.close()
758
759 # Remove / from absolute path to not have // in gs path.
760 gs_url = '%s%s' % (gs_prefix, tarname)
761 http_url = '%s%s' % (http_prefix, tarname)
762
763 try:
764 gsutil.upload(tarname, gs_url)
765 print '@@@STEP_LOG_LINE@coredumps@%s (%s)@@@' % (gs_url, http_url)
766 except Exception as error:
767 message = "Failed to upload coredump %s, error: %s" % (tarname, error)
768 print '@@@STEP_LOG_LINE@coredumps@%s@@@' % message
769
770 os.unlink(tarname)
771
772 print '@@@STEP_LOG_END@coredumps@@@'
773 MarkCurrentStepWarning()
774
775 def _check_core_dump_pattern(self, fatal=False):
776 core_pattern_file = '/proc/sys/kernel/core_pattern'
777 core_pattern = open(core_pattern_file).read()
778
779 expected_core_pattern = 'core.%p'
780 if core_pattern.strip() != expected_core_pattern:
781 if fatal:
782 message = ("Invalid core_pattern configuration. "
783 "The configuration of core dump handling is *not* correct for "
784 "a buildbot. The content of {0} must be '{1}' instead of '{2}'."
785 .format(core_pattern_file, expected_core_pattern, core_pattern))
786 raise Exception(message)
787 else:
788 return False
789 return True
790
791 def MarkCurrentStepWarning():
792 print "@@@STEP_WARNINGS@@@"
793 sys.stdout.flush()
660 794
661 if __name__ == "__main__": 795 if __name__ == "__main__":
662 import sys 796 import sys
663 Main() 797 Main()
OLDNEW
« no previous file with comments | « tools/testing/dart/test_progress.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698