haproxy-wrapper 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. #!/usr/bin/env python
  2. # Copyright 2014 Cloudera, Inc.
  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. import os
  16. import signal
  17. import subprocess
  18. import sys
  19. import errno
  20. pidfile = None
  21. def read_pidfile():
  22. if pidfile is not None:
  23. try:
  24. f = open(pidfile)
  25. except IOError:
  26. pass
  27. else:
  28. try:
  29. return [int(pid) for pid in f.readlines()]
  30. finally:
  31. f.close()
  32. return []
  33. def handle_signal(sig, frame):
  34. if pidfile is not None:
  35. for pid in read_pidfile():
  36. os.kill(pid, sig)
  37. def handle_sigusr2(sig, frame):
  38. child_pids = read_pidfile()
  39. spawn_haproxy(child_pids)
  40. def handle_sigchld(sig, frame):
  41. pass
  42. def spawn_haproxy(child_pids):
  43. args = sys.argv[1:]
  44. # Start haproxy in systemd daemon mode, which leaves the parent process still running.
  45. args.append('-Ds')
  46. # send a soft-stop to any processes still open.
  47. if child_pids:
  48. args.append('-sf')
  49. args.extend(str(pid) for pid in child_pids)
  50. return subprocess.Popen(args)
  51. def main():
  52. global pidfile
  53. it = iter(sys.argv)
  54. # Extract the pidfile from the arguments.
  55. pidfile = None
  56. while True:
  57. try:
  58. arg = next(it)
  59. except StopIteration:
  60. break
  61. if arg == '-p':
  62. pidfile = next(it)
  63. signal.signal(signal.SIGHUP, handle_signal)
  64. signal.signal(signal.SIGINT, handle_signal)
  65. signal.signal(signal.SIGQUIT, handle_signal)
  66. signal.signal(signal.SIGTERM, handle_signal)
  67. signal.signal(signal.SIGUSR1, handle_signal)
  68. signal.signal(signal.SIGUSR2, handle_sigusr2)
  69. signal.signal(signal.SIGCHLD, handle_sigchld)
  70. spawn_haproxy([])
  71. while True:
  72. # we could be re-executed, so we want to wait for all child processes,
  73. # not just the haproxy.
  74. try:
  75. (pid, status) = os.waitpid(-1, 0)
  76. except OSError, e:
  77. # Ignore interrupts
  78. if e.errno == errno.EINTR:
  79. continue
  80. elif e.errno == errno.ECHILD:
  81. # No more children to reap
  82. break
  83. else:
  84. raise e
  85. return os.WEXITSTATUS(status)
  86. if __name__ == '__main__':
  87. sys.exit(main())