Home | History | Annotate | Download | only in devlib
      1 #    Copyright 2015 ARM Limited
      2 #
      3 # Licensed under the Apache License, Version 2.0 (the "License");
      4 # you may not use this file except in compliance with the License.
      5 # You may obtain a copy of the License at
      6 #
      7 #     http://www.apache.org/licenses/LICENSE-2.0
      8 #
      9 # Unless required by applicable law or agreed to in writing, software
     10 # distributed under the License is distributed on an "AS IS" BASIS,
     11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 # See the License for the specific language governing permissions and
     13 # limitations under the License.
     14 #
     15 from glob import iglob
     16 import os
     17 import signal
     18 import shutil
     19 import subprocess
     20 import logging
     21 from getpass import getpass
     22 
     23 from devlib.exception import TargetError
     24 from devlib.utils.misc import check_output
     25 
     26 PACKAGE_BIN_DIRECTORY = os.path.join(os.path.dirname(__file__), 'bin')
     27 
     28 def kill_children(pid, signal=signal.SIGKILL):
     29     with open('/proc/{0}/task/{0}/children'.format(pid), 'r') as fd:
     30         for cpid in map(int, fd.read().strip().split()):
     31             kill_children(cpid, signal)
     32             os.kill(cpid, signal)
     33 
     34 class LocalConnection(object):
     35 
     36     name = 'local'
     37 
     38     def __init__(self, platform=None, keep_password=True, unrooted=False,
     39                  password=None, timeout=None):
     40         self.logger = logging.getLogger('local_connection')
     41         self.keep_password = keep_password
     42         self.unrooted = unrooted
     43         self.password = password
     44 
     45     def push(self, source, dest, timeout=None, as_root=False):  # pylint: disable=unused-argument
     46         self.logger.debug('cp {} {}'.format(source, dest))
     47         shutil.copy(source, dest)
     48 
     49     def pull(self, source, dest, timeout=None, as_root=False): # pylint: disable=unused-argument
     50         self.logger.debug('cp {} {}'.format(source, dest))
     51         if ('*' in source or '?' in source) and os.path.isdir(dest):
     52             # Pull all files matching a wildcard expression
     53             for each_source in iglob(source):
     54                 shutil.copy(each_source, dest)
     55         else:
     56             shutil.copy(source, dest)
     57 
     58     def execute(self, command, timeout=None, check_exit_code=True,
     59                 as_root=False, strip_colors=True):
     60         self.logger.debug(command)
     61         if as_root:
     62             if self.unrooted:
     63                 raise TargetError('unrooted')
     64             password = self._get_password()
     65             command = 'echo \'{}\' | sudo -S '.format(password) + command
     66         ignore = None if check_exit_code else 'all'
     67         try:
     68             return check_output(command, shell=True, timeout=timeout, ignore=ignore)[0]
     69         except subprocess.CalledProcessError as e:
     70             message = 'Got exit code {}\nfrom: {}\nOUTPUT: {}'.format(
     71                 e.returncode, command, e.output)
     72             raise TargetError(message)
     73 
     74     def background(self, command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, as_root=False):
     75         if as_root:
     76             if self.unrooted:
     77                 raise TargetError('unrooted')
     78             password = self._get_password()
     79             command = 'echo \'{}\' | sudo -S '.format(password) + command
     80         return subprocess.Popen(command, stdout=stdout, stderr=stderr, shell=True)
     81 
     82     def close(self):
     83         pass
     84 
     85     def cancel_running_command(self):
     86         pass
     87 
     88     def _get_password(self):
     89         if self.password:
     90             return self.password
     91         password = getpass('sudo password:')
     92         if self.keep_password:
     93             self.password = password
     94         return password
     95