1# Copyright 2014 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 subprocess
7
8from telemetry.core import util
9from telemetry.internal import forwarders
10from telemetry.internal.forwarders import do_nothing_forwarder
11
12
13class CrOsForwarderFactory(forwarders.ForwarderFactory):
14
15  def __init__(self, cri):
16    super(CrOsForwarderFactory, self).__init__()
17    self._cri = cri
18
19  # pylint: disable=arguments-differ
20  def Create(self, port_pairs, use_remote_port_forwarding=True):
21    if self._cri.local:
22      return do_nothing_forwarder.DoNothingForwarder(port_pairs)
23    return CrOsSshForwarder(self._cri, use_remote_port_forwarding, port_pairs)
24
25
26class CrOsSshForwarder(forwarders.Forwarder):
27
28  def __init__(self, cri, use_remote_port_forwarding, port_pairs):
29    super(CrOsSshForwarder, self).__init__(port_pairs)
30    self._cri = cri
31    self._proc = None
32    forwarding_args = self._ForwardingArgs(
33        use_remote_port_forwarding, self.host_ip, port_pairs)
34    self._proc = subprocess.Popen(
35        self._cri.FormSSHCommandLine(['sleep', '999999999'], forwarding_args),
36        stdout=subprocess.PIPE,
37        stderr=subprocess.PIPE,
38        stdin=subprocess.PIPE,
39        shell=False)
40    util.WaitFor(
41        lambda: self._cri.IsHTTPServerRunningOnPort(self.host_port), 60)
42    logging.debug('Server started on %s:%d', self.host_ip, self.host_port)
43
44  # pylint: disable=unused-argument
45  @staticmethod
46  def _ForwardingArgs(use_remote_port_forwarding, host_ip, port_pairs):
47    if use_remote_port_forwarding:
48      arg_format = '-R{pp.remote_port}:{host_ip}:{pp.local_port}'
49    else:
50      arg_format = '-L{pp.local_port}:{host_ip}:{pp.remote_port}'
51    return [arg_format.format(**locals()) for pp in port_pairs if pp]
52
53  @property
54  def host_port(self):
55    return self._port_pairs.http.remote_port
56
57  def Close(self):
58    if self._proc:
59      self._proc.kill()
60      self._proc = None
61    super(CrOsSshForwarder, self).Close()
62