1# Copyright (c) 2013 The Chromium OS 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""" 6Provides utility class for stopping and restarting services 7 8When using this class, one likely wishes to do the following: 9 10 def initialize(self): 11 self._services = service_stopper.ServiceStopper(['service']) 12 self._services.stop_services() 13 14 15 def cleanup(self): 16 self._services.start_services() 17 18As this ensures that the services will be off before the test code runs, and 19the test framework will ensure that the services are restarted through any 20code path out of the test. 21""" 22 23import logging 24import os 25 26from autotest_lib.client.bin import utils 27from autotest_lib.client.cros import upstart 28 29 30class ServiceStopper(object): 31 """Class to manage CrOS services. 32 Public attributes: 33 services_to_stop: list of services that should be stopped 34 35 Public constants: 36 POWER_DRAW_SERVICES: list of services that influence power test in 37 unpredictable/undesirable manners. 38 39 Public methods: 40 stop_sevices: stop running system services. 41 restore_services: restore services that were previously stopped. 42 43 Private attributes: 44 _services_stopped: list of services that were successfully stopped 45 """ 46 47 POWER_DRAW_SERVICES = ['fwupd', 'powerd', 'update-engine', 'vnc'] 48 49 # List of thermal throttling services that should be disabled. 50 # - temp_metrics for link. 51 # - thermal for daisy, snow, pit etc. 52 # - dptf for intel >= baytrail 53 # TODO(ihf): cpu_quiet on nyan isn't a service. We still need to disable it 54 # on nyan. See crbug.com/357457. 55 THERMAL_SERVICES = ['dptf', 'temp_metrics', 'thermal'] 56 57 def __init__(self, services_to_stop=[]): 58 """Initialize instance of class. 59 60 By Default sets an empty list of services. 61 """ 62 self.services_to_stop = services_to_stop 63 self._services_stopped = [] 64 65 66 def stop_services(self): 67 """Turn off managed services.""" 68 69 for service in self.services_to_stop: 70 if not upstart.has_service(service): 71 continue 72 if not upstart.is_running(service): 73 continue 74 upstart.stop_job(service) 75 self._services_stopped.append(service) 76 77 78 def restore_services(self): 79 """Restore services that were stopped.""" 80 for service in reversed(self._services_stopped): 81 upstart.restart_job(service) 82 self._services_stopped = [] 83 84 85 def __enter__(self): 86 self.stop_services() 87 return self 88 89 90 def __exit__(self, exnval, exntype, exnstack): 91 self.restore_services() 92 93 94 def close(self): 95 """Equivalent to restore_services.""" 96 self.restore_services() 97 98 99 def _dptf_fixup_pl1(self): 100 """For intel devices that don't set their PL1 override in coreboot's 101 devicetree.cb (See 'register "tdp_pl1_override') stopping DPTF will 102 change the PL1 limit to the platform default. For eve (KBL-Y) that 103 would be 4.5W. To workaround this until FW can be fixed we should 104 instead query what the PL1 limit is for the proc_thermal driver and 105 write it to the PL1 constraint. 106 107 TODO(b/144020442) 108 """ 109 pl1_max_path = \ 110 '/sys/devices/pci0000:00/0000:00:04.0/power_limits/power_limit_0_max_uw' 111 pl1_constraint_path = \ 112 '/sys/class/powercap/intel-rapl:0/constraint_0_power_limit_uw' 113 if not os.path.exists(pl1_max_path): 114 return 115 116 pl1 = int(utils.read_one_line(pl1_max_path)) 117 logging.debug('PL1 set to %d uw', pl1) 118 utils.system('echo %d > %s' % (pl1, pl1_constraint_path)) 119 120 121def get_thermal_service_stopper(): 122 """Convenience method to retrieve thermal service stopper.""" 123 return ServiceStopper(services_to_stop=ServiceStopper.THERMAL_SERVICES) 124