1# Copyright 2015 The Chromium 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
5import logging
6import os
7
8from py_utils import binary_manager
9from py_utils import dependency_util
10import dependency_manager
11from devil import devil_env
12
13from telemetry.core import exceptions
14from telemetry.core import util
15from telemetry.core import platform as platform_module
16
17
18TELEMETRY_PROJECT_CONFIG = os.path.join(
19    util.GetTelemetryDir(), 'telemetry', 'internal', 'binary_dependencies.json')
20
21
22CHROME_BINARY_CONFIG = os.path.join(util.GetCatapultDir(), 'common', 'py_utils',
23                                    'py_utils', 'chrome_binaries.json')
24
25
26BATTOR_BINARY_CONFIG = os.path.join(util.GetCatapultDir(), 'common', 'battor',
27                                    'battor', 'battor_binary_dependencies.json')
28
29
30NoPathFoundError = dependency_manager.NoPathFoundError
31CloudStorageError = dependency_manager.CloudStorageError
32
33
34_binary_manager = None
35
36
37def NeedsInit():
38  return not _binary_manager
39
40
41def InitDependencyManager(client_configs):
42  global _binary_manager
43  if _binary_manager:
44    raise exceptions.InitializationError(
45        'Trying to re-initialize the binary manager with config %s'
46        % client_configs)
47  configs = []
48  if client_configs:
49    configs += client_configs
50  configs += [TELEMETRY_PROJECT_CONFIG, CHROME_BINARY_CONFIG]
51  _binary_manager = binary_manager.BinaryManager(configs)
52
53  devil_env.config.Initialize()
54
55
56def FetchPath(binary_name, arch, os_name, os_version=None):
57  """ Return a path to the appropriate executable for <binary_name>, downloading
58      from cloud storage if needed, or None if it cannot be found.
59  """
60  if _binary_manager is None:
61    raise exceptions.InitializationError(
62        'Called FetchPath with uninitialized binary manager.')
63  return _binary_manager.FetchPath(binary_name, os_name, arch, os_version)
64
65
66def LocalPath(binary_name, arch, os_name, os_version=None):
67  """ Return a local path to the given binary name, or None if an executable
68      cannot be found. Will not download the executable.
69      """
70  if _binary_manager is None:
71    raise exceptions.InitializationError(
72        'Called LocalPath with uninitialized binary manager.')
73  return _binary_manager.LocalPath(binary_name, os_name, arch, os_version)
74
75
76def FetchBinaryDependencies(platform, client_configs,
77                          fetch_reference_chrome_binary):
78  """ Fetch all binary dependenencies for the given |platform|.
79
80  Note: we don't fetch browser binaries by default because the size of the
81  binary is about 2Gb, and it requires cloud storage permission to
82  chrome-telemetry bucket.
83
84  Args:
85    platform: an instance of telemetry.core.platform
86    client_configs: A list of paths (string) to dependencies json files.
87    fetch_reference_chrome_binary: whether to fetch reference chrome binary for
88      the given platform.
89  """
90  configs = [
91      dependency_manager.BaseConfig(TELEMETRY_PROJECT_CONFIG),
92      dependency_manager.BaseConfig(BATTOR_BINARY_CONFIG)
93  ]
94  dep_manager = dependency_manager.DependencyManager(configs)
95  target_platform = '%s_%s' % (platform.GetOSName(), platform.GetArchName())
96  dep_manager.PrefetchPaths(target_platform)
97
98  host_platform = None
99  fetch_devil_deps = False
100  if platform.GetOSName() == 'android':
101    host_platform = '%s_%s' % (
102        platform_module.GetHostPlatform().GetOSName(),
103        platform_module.GetHostPlatform().GetArchName())
104    dep_manager.PrefetchPaths(host_platform)
105    # TODO(aiolos): this is a hack to prefetch the devil deps.
106    if host_platform == 'linux_x86_64':
107      fetch_devil_deps = True
108    else:
109      logging.error('Devil only supports 64 bit linux as a host platform. '
110                    'Android tests may fail.')
111
112  if fetch_reference_chrome_binary:
113    _FetchReferenceBrowserBinary(platform)
114
115  # For now, handle client config separately because the BUILD.gn & .isolate of
116  # telemetry tests in chromium src failed to include the files specified in its
117  # client config.
118  # (https://github.com/catapult-project/catapult/issues/2192)
119  # For now this is ok because the client configs usually don't include cloud
120  # storage infos.
121  # TODO(nednguyen): remove the logic of swallowing exception once the issue is
122  # fixed on Chromium side.
123  if client_configs:
124    manager = dependency_manager.DependencyManager(
125        list(dependency_manager.BaseConfig(c) for c in client_configs))
126    try:
127      manager.PrefetchPaths(target_platform)
128      if host_platform is not None:
129        manager.PrefetchPaths(host_platform)
130
131    except dependency_manager.NoPathFoundError as e:
132      logging.error('Error when trying to prefetch paths for %s: %s',
133                    target_platform, e.message)
134
135  if fetch_devil_deps:
136    devil_env.config.Initialize()
137    devil_env.config.PrefetchPaths(arch=platform.GetArchName())
138    devil_env.config.PrefetchPaths()
139
140
141def _FetchReferenceBrowserBinary(platform):
142  os_name = platform.GetOSName()
143  arch_name = platform.GetArchName()
144  manager = binary_manager.BinaryManager(
145             [CHROME_BINARY_CONFIG])
146  if os_name == 'android':
147    os_version = dependency_util.GetChromeApkOsVersion(
148        platform.GetOSVersionName())
149    manager.FetchPath(
150        'chrome_stable', os_name, arch_name, os_version)
151  else:
152    manager.FetchPath(
153        'chrome_stable', os_name, arch_name)
154