1# Copyright 2016 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 6from recipe_engine import recipe_api 7 8import default 9import json # TODO(borenet): No! Remove this. 10 11 12"""Chromebook flavor, used for running code on Chromebooks.""" 13 14 15class ChromebookFlavor(default.DefaultFlavor): 16 17 def __init__(self, m): 18 super(ChromebookFlavor, self).__init__(m) 19 self._user_ip = '' 20 21 self.chromeos_homedir = '/home/chronos/user/' 22 self.device_dirs = default.DeviceDirs( 23 bin_dir = self.chromeos_homedir + 'bin', 24 dm_dir = self.chromeos_homedir + 'dm_out', 25 perf_data_dir = self.chromeos_homedir + 'perf', 26 resource_dir = self.chromeos_homedir + 'resources', 27 images_dir = self.chromeos_homedir + 'images', 28 lotties_dir = self.chromeos_homedir + 'lotties', 29 skp_dir = self.chromeos_homedir + 'skps', 30 svg_dir = self.chromeos_homedir + 'svgs', 31 tmp_dir = self.chromeos_homedir) 32 33 @property 34 def user_ip(self): 35 if not self._user_ip: 36 ssh_info = self.m.run(self.m.python.inline, 'read chromeos ip', 37 program=""" 38 import os 39 SSH_MACHINE_FILE = os.path.expanduser('~/ssh_machine.json') 40 with open(SSH_MACHINE_FILE, 'r') as f: 41 print f.read() 42 """, 43 stdout=self.m.raw_io.output(), 44 infra_step=True).stdout 45 46 self._user_ip = json.loads(ssh_info).get(u'user_ip', 'ERROR') 47 return self._user_ip 48 49 def _ssh(self, title, *cmd, **kwargs): 50 if 'infra_step' not in kwargs: 51 kwargs['infra_step'] = True 52 53 ssh_cmd = ['ssh', '-oConnectTimeout=15', '-oBatchMode=yes', 54 '-t', '-t', self.user_ip] + list(cmd) 55 56 return self._run(title, ssh_cmd, **kwargs) 57 58 def install(self): 59 self._ssh('mkdir %s' % self.device_dirs.resource_dir, 'mkdir', '-p', 60 self.device_dirs.resource_dir) 61 62 # Ensure the home dir is marked executable 63 self._ssh('remount %s as exec' % self.chromeos_homedir, 64 'sudo', 'mount', '-i', '-o', 'remount,exec', '/home/chronos') 65 66 self.create_clean_device_dir(self.device_dirs.bin_dir) 67 68 def create_clean_device_dir(self, path): 69 # use -f to silently return if path doesn't exist 70 self._ssh('rm %s' % path, 'rm', '-rf', path) 71 self._ssh('mkdir %s' % path, 'mkdir', '-p', path) 72 73 def read_file_on_device(self, path, **kwargs): 74 rv = self._ssh('read %s' % path, 75 'cat', path, stdout=self.m.raw_io.output(), 76 **kwargs) 77 return rv.stdout.rstrip() if rv and rv.stdout else None 78 79 def remove_file_on_device(self, path): 80 # use -f to silently return if path doesn't exist 81 self._ssh('rm %s' % path, 'rm', '-f', path) 82 83 def _prefix_device_path(self, device_path): 84 return '%s:%s' % (self.user_ip, device_path) 85 86 def copy_file_to_device(self, host_path, device_path): 87 device_path = self._prefix_device_path(device_path) 88 # Recipe 89 self.m.python.inline(str('scp %s %s' % (host_path, device_path)), 90 """ 91 import subprocess 92 import sys 93 host = sys.argv[1] 94 device = sys.argv[2] 95 print subprocess.check_output(['scp', host, device]) 96 """, args=[host_path, device_path], infra_step=True) 97 98 def _copy_dir(self, src, dest): 99 # We can't use rsync to communicate with the chromebooks because the 100 # chromebooks don't have rsync installed on them. 101 self.m.python.inline(str('scp -r %s %s' % (src, dest)), 102 """ 103 import subprocess 104 import sys 105 src = sys.argv[1] + '/*' 106 dest = sys.argv[2] 107 print subprocess.check_output('scp -r %s %s' % (src, dest), shell=True) 108 """, args=[src, dest], infra_step=True) 109 110 def copy_directory_contents_to_device(self, host_path, device_path): 111 self._copy_dir(host_path, self._prefix_device_path(device_path)) 112 113 def copy_directory_contents_to_host(self, device_path, host_path): 114 self._copy_dir(self._prefix_device_path(device_path), host_path) 115 116 def step(self, name, cmd, **kwargs): 117 # Push and run either dm or nanobench 118 119 name = cmd[0] 120 121 if name == 'dm': 122 self.create_clean_host_dir(self.host_dirs.dm_dir) 123 if name == 'nanobench': 124 self.create_clean_host_dir(self.host_dirs.perf_data_dir) 125 126 app = self.host_dirs.bin_dir.join(cmd[0]) 127 128 cmd[0] = '%s/%s' % (self.device_dirs.bin_dir, cmd[0]) 129 self.copy_file_to_device(app, cmd[0]) 130 131 self._ssh('chmod %s' % name, 'chmod', '+x', cmd[0]) 132 self._ssh(str(name), *cmd) 133