Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / chromite / cbuildbot / archive_lib.py
1 # Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 """Module with utilities for archiving functionality."""
6
7 from __future__ import print_function
8
9 import os
10
11 from chromite.cbuildbot import cbuildbot_config
12 from chromite.cbuildbot import commands
13 from chromite.cbuildbot import constants
14
15 from chromite.lib import cros_build_lib
16 from chromite.lib import gs
17 from chromite.lib import osutils
18
19
20 def GetBaseUploadURI(config, archive_base=None, bot_id=None,
21                      remote_trybot=False):
22   """Get the base URL where artifacts from this builder are uploaded.
23
24   Each build run stores its artifacts in a subdirectory of the base URI.
25   We also have LATEST files under the base URI which help point to the
26   latest build available for a given builder.
27
28   Args:
29     config: The build config to examine.
30     archive_base: Optional. The root URL under which objects from all
31       builders are uploaded. If not specified, we use the default archive
32       bucket.
33     bot_id: The bot ID to archive files under.
34     remote_trybot: Whether this is a remote trybot run. This is used to
35       make sure that uploads from remote trybot runs do not conflict with
36       uploads from production builders.
37
38   Returns:
39     Google Storage URI (i.e. 'gs://...') under which all archived files
40       should be uploaded.  In other words, a path like a directory, even
41       through GS has no real directories.
42   """
43   if not bot_id:
44     bot_id = config.GetBotId(remote_trybot=remote_trybot)
45
46   if archive_base:
47     return '%s/%s' % (archive_base, bot_id)
48   elif remote_trybot or config.gs_path == cbuildbot_config.GS_PATH_DEFAULT:
49     return '%s/%s' % (constants.DEFAULT_ARCHIVE_BUCKET, bot_id)
50   else:
51     return config.gs_path
52
53
54 def GetUploadACL(config):
55   """Get the ACL we should use to upload artifacts for a given config."""
56   if config.internal:
57     # Use the bucket default ACL.
58     return None
59
60   return 'public-read'
61
62
63 class Archive(object):
64   """Class to represent the archive for one builder run.
65
66   An Archive object is a read-only object with attributes and methods useful
67   for archive purposes.  Most of the attributes are supported as properties
68   because they depend on the ChromeOS version and if they are calculated too
69   soon (i.e. before the sync stage) they will raise an exception.
70
71   Attributes:
72     archive_path: The full local path where output from this builder is stored.
73     download_url: The URL where we can download artifacts.
74     upload_url: The Google Storage location where we should upload artifacts.
75     version: The ChromeOS version for this archive.
76   """
77
78   _BUILDBOT_ARCHIVE = 'buildbot_archive'
79   _TRYBOT_ARCHIVE = 'trybot_archive'
80
81   def __init__(self, bot_id, version_getter, options, config):
82     """Initialize.
83
84     Args:
85       bot_id: The bot id associated with this archive.
86       version_getter: Functor that should return the ChromeOS version for
87         this run when called, if the version is known.  Typically, this
88         is BuilderRun.GetVersion.
89       options: The command options object for this run.
90       config: The build config for this run.
91     """
92     self._options = options
93     self._config = config
94     self._version_getter = version_getter
95     self._version = None
96
97     self.bot_id = bot_id
98
99   @property
100   def version(self):
101     if self._version is None:
102       self._version = self._version_getter()
103
104     return self._version
105
106   @property
107   def archive_path(self):
108     return os.path.join(self.GetLocalArchiveRoot(), self.bot_id, self.version)
109
110   @property
111   def upload_url(self):
112     base_upload_url = GetBaseUploadURI(
113         self._config,
114         archive_base=self._options.archive_base,
115         bot_id=self.bot_id,
116         remote_trybot=self._options.remote_trybot)
117     return '%s/%s' % (base_upload_url, self.version)
118
119   @property
120   def upload_acl(self):
121     """Get the ACL we should use to upload artifacts for a given config."""
122     return GetUploadACL(self._config)
123
124   @property
125   def download_url(self):
126     if self._options.buildbot or self._options.remote_trybot:
127       # Translate the gs:// URI to the URL for downloading the same files.
128       return self.upload_url.replace('gs://', gs.PRIVATE_BASE_HTTPS_URL)
129     else:
130       return self.archive_path
131
132   def GetLocalArchiveRoot(self, trybot=None):
133     """Return the location on disk where archive images are kept."""
134     buildroot = os.path.abspath(self._options.buildroot)
135
136     if trybot is None:
137       trybot = not self._options.buildbot or self._options.debug
138
139     archive_base = self._TRYBOT_ARCHIVE if trybot else self._BUILDBOT_ARCHIVE
140     return os.path.join(buildroot, archive_base)
141
142   def SetupArchivePath(self):
143     """Create a fresh directory for archiving a build."""
144     cros_build_lib.Info('Preparing local archive directory at "%s".',
145                         self.archive_path)
146     if self._options.buildbot:
147       # Buildbot: Clear out any leftover build artifacts, if present, for
148       # this particular run.  The Clean stage is responsible for trimming
149       # back the number of archive paths to the last X runs.
150       osutils.RmDir(self.archive_path, ignore_missing=True)
151     else:
152       # Clear the list of uploaded file if it exists.  In practice, the Clean
153       # stage deletes everything in the archive root, so this may not be
154       # doing anything at all.
155       osutils.SafeUnlink(os.path.join(self.archive_path,
156                                       commands.UPLOADED_LIST_FILENAME))
157
158     osutils.SafeMakedirs(self.archive_path)
159
160   def UpdateLatestMarkers(self, manifest_branch, debug, upload_urls=None):
161     """Update the LATEST markers in GS archive area.
162
163     Args:
164       manifest_branch: The name of the branch in the manifest for this run.
165       debug: Boolean debug value for this run.
166       upload_urls: Google storage urls to upload the Latest Markers to.
167     """
168     if not upload_urls:
169       upload_urls = [self.upload_url]
170     # self.version will be one of these forms, shown through examples:
171     # R35-1234.5.6 or R35-1234.5.6-b123.  In either case, we want "1234.5.6".
172     version_marker = self.version.split('-')[1]
173
174     filenames = ('LATEST-%s' % manifest_branch,
175                  'LATEST-%s' % version_marker)
176     base_archive_path = os.path.dirname(self.archive_path)
177     base_upload_urls = [os.path.dirname(url) for url in upload_urls]
178     for base_upload_url in base_upload_urls:
179       for filename in filenames:
180         latest_path = os.path.join(base_archive_path, filename)
181         osutils.WriteFile(latest_path, self.version, mode='w')
182         commands.UploadArchivedFile(
183             base_archive_path, [base_upload_url], filename,
184             debug, acl=self.upload_acl)