bea862803c9ed720698ed20b3697ea12252e7b7b
[platform/framework/web/crosswalk.git] / src / tools / telemetry / telemetry / core / platform / linux_platform_backend.py
1 # Copyright 2013 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
5 import logging
6 import os
7 import subprocess
8 import sys
9
10 from telemetry import decorators
11 from telemetry.core.platform import linux_based_platform_backend
12 from telemetry.core.platform import platform_backend
13 from telemetry.core.platform import posix_platform_backend
14 from telemetry.core.platform.power_monitor import msr_power_monitor
15 from telemetry.util import cloud_storage
16 from telemetry.util import support_binaries
17
18
19 _POSSIBLE_PERFHOST_APPLICATIONS = [
20   'perfhost_precise',
21   'perfhost_trusty',
22 ]
23
24
25 class LinuxPlatformBackend(
26     posix_platform_backend.PosixPlatformBackend,
27     linux_based_platform_backend.LinuxBasedPlatformBackend):
28   def __init__(self):
29     super(LinuxPlatformBackend, self).__init__()
30     self._power_monitor = msr_power_monitor.MsrPowerMonitor(self)
31
32   def StartRawDisplayFrameRateMeasurement(self):
33     raise NotImplementedError()
34
35   def StopRawDisplayFrameRateMeasurement(self):
36     raise NotImplementedError()
37
38   def GetRawDisplayFrameRateMeasurements(self):
39     raise NotImplementedError()
40
41   def IsThermallyThrottled(self):
42     raise NotImplementedError()
43
44   def HasBeenThermallyThrottled(self):
45     raise NotImplementedError()
46
47   def GetOSName(self):
48     return 'linux'
49
50   @decorators.Cache
51   def GetOSVersionName(self):
52     if not os.path.exists('/etc/lsb-release'):
53       raise NotImplementedError('Unknown Linux OS version')
54
55     codename = None
56     version = None
57     for line in self.GetFileContents('/etc/lsb-release').splitlines():
58       key, _, value = line.partition('=')
59       if key == 'DISTRIB_CODENAME':
60         codename = value.strip()
61       elif key == 'DISTRIB_RELEASE':
62         try:
63           version = float(value)
64         except ValueError:
65           version = 0
66       if codename and version:
67         break
68     return platform_backend.OSVersion(codename, version)
69
70   def CanFlushIndividualFilesFromSystemCache(self):
71     return True
72
73   def FlushEntireSystemCache(self):
74     p = subprocess.Popen(['/sbin/sysctl', '-w', 'vm.drop_caches=3'])
75     p.wait()
76     assert p.returncode == 0, 'Failed to flush system cache'
77
78   def CanLaunchApplication(self, application):
79     if application == 'ipfw' and not self._IsIpfwKernelModuleInstalled():
80       return False
81     return super(LinuxPlatformBackend, self).CanLaunchApplication(application)
82
83   def InstallApplication(self, application):
84     if application == 'ipfw':
85       self._InstallIpfw()
86     elif application == 'avconv':
87       self._InstallBinary(application, fallback_package='libav-tools')
88     elif application in _POSSIBLE_PERFHOST_APPLICATIONS:
89       self._InstallBinary(application)
90     else:
91       raise NotImplementedError(
92           'Please teach Telemetry how to install ' + application)
93
94   def CanMonitorPower(self):
95     return self._power_monitor.CanMonitorPower()
96
97   def CanMeasurePerApplicationPower(self):
98     return self._power_monitor.CanMeasurePerApplicationPower()
99
100   def StartMonitoringPower(self, browser):
101     self._power_monitor.StartMonitoringPower(browser)
102
103   def StopMonitoringPower(self):
104     return self._power_monitor.StopMonitoringPower()
105
106   def ReadMsr(self, msr_number, start=0, length=64):
107     cmd = ['/usr/sbin/rdmsr', '-d', str(msr_number)]
108     (out, err) = subprocess.Popen(cmd,
109                                   stdout=subprocess.PIPE,
110                                   stderr=subprocess.PIPE).communicate()
111     if err:
112       raise OSError(err)
113     try:
114       result = int(out)
115     except ValueError:
116       raise OSError('Cannot interpret rdmsr output: %s' % out)
117     return result >> start & ((1 << length) - 1)
118
119   def _IsIpfwKernelModuleInstalled(self):
120     return 'ipfw_mod' in subprocess.Popen(
121         ['lsmod'], stdout=subprocess.PIPE).communicate()[0]
122
123   def _InstallIpfw(self):
124     ipfw_bin = support_binaries.FindPath('ipfw', self.GetOSName())
125     ipfw_mod = support_binaries.FindPath('ipfw_mod.ko', self.GetOSName())
126
127     try:
128       changed = cloud_storage.GetIfChanged(
129           ipfw_bin, cloud_storage.INTERNAL_BUCKET)
130       changed |= cloud_storage.GetIfChanged(
131           ipfw_mod, cloud_storage.INTERNAL_BUCKET)
132     except cloud_storage.CloudStorageError, e:
133       logging.error(str(e))
134       logging.error('You may proceed by manually building and installing'
135                     'dummynet for your kernel. See: '
136                     'http://info.iet.unipi.it/~luigi/dummynet/')
137       sys.exit(1)
138
139     if changed or not self.CanLaunchApplication('ipfw'):
140       if not self._IsIpfwKernelModuleInstalled():
141         subprocess.check_call(['sudo', 'insmod', ipfw_mod])
142       os.chmod(ipfw_bin, 0755)
143       subprocess.check_call(['sudo', 'cp', ipfw_bin, '/usr/local/sbin'])
144
145     assert self.CanLaunchApplication('ipfw'), 'Failed to install ipfw. ' \
146         'ipfw provided binaries are not supported for linux kernel < 3.13. ' \
147         'You may proceed by manually building and installing dummynet for ' \
148         'your kernel. See: http://info.iet.unipi.it/~luigi/dummynet/'
149
150   def _InstallBinary(self, bin_name, fallback_package=None):
151     bin_path = support_binaries.FindPath(bin_name, self.GetOSName())
152     if not bin_path:
153       raise Exception('Could not find the binary package %s' % bin_name)
154     os.environ['PATH'] += os.pathsep + os.path.dirname(bin_path)
155
156     try:
157       cloud_storage.GetIfChanged(bin_path, cloud_storage.INTERNAL_BUCKET)
158       os.chmod(bin_path, 0755)
159     except cloud_storage.CloudStorageError, e:
160       logging.error(str(e))
161       if fallback_package:
162         raise Exception('You may proceed by manually installing %s via:\n'
163                         'sudo apt-get install %s' %
164                         (bin_name, fallback_package))
165
166     assert self.CanLaunchApplication(bin_name), 'Failed to install ' + bin_name