blob: 4961b9004d7feb66c0c88184902bac89004b0b15 [file] [log] [blame]
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
""" Reboot the slave machine, unless it is run in a development
envirenment (TESTING_MASTER environment variable is defined).
The reboot is also controlled by reboot_on_step_timeout flag in the
master config.
import os
import subprocess
import sys
import time
def Log(message):
"""Log a message.
Use the Buildbot/Twisted log facility if it's imported. Otherwise
assume we are running in a terminal from a command line.
log_mod = sys.modules.get('twisted.python.log')
if log_mod:
print message
def IssueReboot():
"""Issue reboot command according to platform type."""
if sys.platform.startswith('win'):['shutdown', '-r', '-f', '-t', '1'])
elif sys.platform in ('darwin', 'posix', 'linux2'):['sudo', 'shutdown', '-r', 'now'])
raise NotImplementedError('Implement IssueReboot function '
'for %s' % sys.platform)
def SigTerm(*args):
"""Receive a SIGTERM and do nothing."""
Log('SigTerm: Received SIGTERM, doing nothing.')
def UpdateSignals():
"""Override the twisted SIGTERM handler with our own.
Ensure that the signal module is available and do nothing if it is not.
import signal
except ImportError:
Log('UpdateSignals: Warning: signal module unavailable -- '
'not installing signal handlers.')
# Twisted installs a SIGTERM signal handler which tries to shut the system
# down. Use our own handler instead.
Log('UpdateSignals: installed new SIGTERM handler')
signal.signal(signal.SIGTERM, SigTerm)
def Sleep(desired_sleep):
"""Sleep for |desired_sleep| seconds.
time.sleep() can return in less time than desired if the process receives
a signal. We expect that to happen when the shutdown we run causes the system
to send a TERM signal to us. When that happens, we need to ensure we go
back to sleep for the remainder of the time that's left."""
actual_sleep = 0
while True:
sleep_length = desired_sleep - actual_sleep
start_time = int(time.time())
Log('Sleep: Sleeping for %s seconds' % sleep_length)
this_sleep = int(time.time()) - start_time
Log('Sleep: Actually slept for %s seconds' % actual_sleep)
if this_sleep < 0:
Log('Sleep: Error, this_sleep was %d (less than zero)' % actual_sleep)
actual_sleep += this_sleep
if actual_sleep >= desired_sleep:
Log('Sleep: Finished sleeping, returning' % actual_sleep)
Log('Sleep: Awoke too early, sleeping again')
def ReallyReboot():
"""Repeatedly try to reboot the system.
In IssueReboot, use instead of Popen() to ensure that doesn't exit at all when it calls Reboot(). This ensures that won't exit and trigger any cleanup routines by whatever
Since our strategy depends on Reboot() never returning, raise an exception
if that should occur to make it clear in logs that an error condition is
occurring somewhere.
Log('Reboot: Starting system reboot cycle')
i = 0
while True:
Log('Reboot: Reboot cycle %d' % i)
i += 1
Log('Reboot: failed to issue a reboot: %s' % str(sys.exc_info()[0]))
def Reboot():
"""Reboot the buildbot slave machine.
This behavior is controlled by the reboot_on_step_timeout flag in
the active master configuration.
# This envrionment is defined only when testing the slave on a dev machine.
is_testing = 'TESTING_MASTER' in os.environ
should_reboot = False
import config_bootstrap
master = getattr(config_bootstrap.Master, 'active_master', None)
should_reboot = getattr(master, 'reboot_on_step_timeout', True)
Log('Reboot: reboot_on_step_timeout = %r (from master_site_config: %r)'
% (should_reboot, master))
except: # pylint: disable=W0702
Log('Reboot: failed to read master config: %s' % str(sys.exc_info()[0]))
if should_reboot:
if not is_testing:
Log('Reboot: Issuing Reboot...')
Log('Reboot: Testing mode enabled, skipping the actual reboot')