1#
2# Copyright (C) 2016 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#      http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16
17import types
18import threading
19import re
20import logging
21
22from vts.runners.host import const
23from vts.testcases.kernel.ltp.shell_environment import shell_commands
24
25
26class ShellEnvironment(object):
27    '''Class for executing environment definition classes and do cleanup jobs.
28
29    Attributes:
30        shell: shell mirror object, shell to execute commands
31        _cleanup_jobs: set of CheckSetupCleanup objects, a set used to store
32                       clean up jobs if requested.
33        _thread_lock: a threading.Lock object
34    '''
35
36    def __init__(self, shell):
37        self.shell = shell
38        self._cleanup_jobs = []
39        self._thread_lock = threading.Lock()
40
41    def Cleanup(self):
42        '''Final cleanup jobs. Will run all the stored cleanup jobs'''
43        return all([method(*args) for method, args in self._cleanup_jobs])
44
45    def AddCleanupJob(self, method, *args):
46        '''Add a clean up job for final cleanup'''
47        if (method, args) not in self._cleanup_jobs:
48            self._cleanup_jobs.append((method, args))
49
50    @property
51    def shell(self):
52        '''returns an object that can execute a shell command'''
53        return self._shell
54
55    @shell.setter
56    def shell(self, shell):
57        self._shell = shell
58
59    def ExecuteDefinitions(self, definitions):
60        '''Execute a given list of environment check definitions'''
61        self._thread_lock.acquire()
62        if not isinstance(definitions, types.ListType):
63            definitions = [definitions]
64
65        for definition in definitions:
66            definition.context = self
67            if not definition.Execute():
68                self._thread_lock.release()
69                return (False, definition.GetNote())
70
71        self._thread_lock.release()
72        return (True, "")
73
74    def GetDeviceNumberOfPresentCpu(self):
75        '''Get the number of available CPUs on target device'''
76        results = self.shell.Execute('cat %s' %
77                                     shell_commands.FILEPATH_CPU_PRESENT)
78        if (not results or results[const.EXIT_CODE][0] or
79                not results[const.STDOUT][0]):
80            logging.error("Cannot get number of working CPU info."
81                          "\n  Command results: {}".format(results))
82            return 1
83        else:
84            cpu_info = results[const.STDOUT][0].strip()
85            m = re.match("[0-9]+-?[0-9]*", cpu_info)
86            if m and m.span() == (0, len(cpu_info)):
87                logging.info("spam" + str(m.span()))
88                try:
89                    return int(cpu_info.split('-')[-1]) + 1
90                except Exception as e:
91                    logging.error(e)
92
93            logging.error("Cannot parse number of working CPU info."
94                          "\n  CPU info: '{}'".format(cpu_info))
95            return 1
96
97