puppet-jenkins/files/safe_jenkins_shutdown
Clark Boylan c61d0588f1 Add utility script for safe master shutdown
This adds a script that will put the jenkins master in shutdown mode,
wait for all jobs to finish running, then optionally delete any offline
slaves. Once this is complete you can restart the jenkins master in
whatever fashion you choose safely.

Change-Id: I0cb858665de0e733267b5f45b071b076167ee63a
2015-09-25 13:35:19 -07:00

93 lines
3.3 KiB
Python
Executable File

#!/usr/bin/env python
# Copyright 2015 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import argparse
import time
import jenkins
def delete_offline_nodes(server, timeout):
start = time.time()
end = start + timeout
while True:
nodes = server.get_nodes()
offline_nodes = [node for node in nodes if node['offline']]
if not offline_nodes:
# We have converged to no offline nodes state
break
elif time.time() > end:
raise Exception("Offline slave deletion timeout exceeded.")
try:
for n in offline_nodes:
server.delete_node(n['name'])
# This may have raced an external system deleting nodes
# after jobs complete. Just retry as we should
# converage on no jobs running and no deletions.
except jenkins.NotFoundException:
pass
except jenkins.JenkinsException as e:
if '[500]' in e.message:
pass
else:
raise
time.sleep(1)
def parse_args():
parser = argparse.ArgumentParser(description='Safely stop Jenkins.')
parser.add_argument('--url', default='http://localhost:8080',
help='Base url for Jenkins master.')
parser.add_argument('--user', required=True,
help='Username to connect to Jenkins with.')
parser.add_argument('--password', required=True,
help='Password to auth with.')
parser.add_argument('--no-delete', dest='delete', action='store_false',
default=True, help="Don't delete offline slaves.")
parser.add_argument('--delete-timeout', type=int, default=300,
help="Seconds to spend deleting offline slaves.")
args = parser.parse_args()
return args
def main():
args = parse_args()
server = jenkins.Jenkins(args.url,
username=args.user,
password=args.password)
# Put in shutdown mode
server.quiet_down()
while True:
try:
if not server.get_running_builds():
break
# This may have raced an external system deleting executors
# while listing the running jobs. Just retry as we should
# converage on no jobs running and no deletions.
except jenkins.NotFoundException:
pass
except jenkins.JenkinsException as e:
if '[500]' in e.message:
pass
else:
raise
# Jobs are slow wait a minute between polls
time.sleep(60)
if args.delete:
# Remove any offline nodes so they don't go online after restart.
delete_offline_nodes(server, args.delete_timeout)
if __name__ == '__main__':
main()