1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

# This file is part of Buildbot.  Buildbot is free software: you can 

# redistribute it and/or modify it under the terms of the GNU General Public 

# License as published by the Free Software Foundation, version 2. 

# 

# This program is distributed in the hope that it will be useful, but WITHOUT 

# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 

# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 

# details. 

# 

# You should have received a copy of the GNU General Public License along with 

# this program; if not, write to the Free Software Foundation, Inc., 51 

# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 

# 

# Copyright Buildbot Team Members 

 

from __future__ import with_statement 

 

 

import os 

import signal 

import platform 

from twisted.internet import reactor 

 

from buildbot.scripts.logwatcher import LogWatcher, BuildmasterTimeoutError, \ 

     ReconfigError 

from buildbot.util import in_reactor 

 

class Reconfigurator: 

 

    rc = 0 

 

    def run(self, basedir, quiet): 

        # Returns "Microsoft" for Vista and "Windows" for other versions 

        if platform.system() in ("Windows", "Microsoft"): 

            print "Reconfig (through SIGHUP) is not supported on Windows." 

            print "The 'buildbot debugclient' tool can trigger a reconfig" 

            print "remotely, but requires Gtk+ libraries to run." 

            return 

 

        with open(os.path.join(basedir, "twistd.pid"), "rt") as f: 

            self.pid = int(f.read().strip()) 

        if quiet: 

            os.kill(self.pid, signal.SIGHUP) 

            return 

 

        # keep reading twistd.log. Display all messages between "loading 

        # configuration from ..." and "configuration update complete" or 

        # "I will keep using the previous config file instead.", or until 

        # 10 seconds have elapsed. 

 

        self.sent_signal = False 

        reactor.callLater(0.2, self.sighup) 

 

        lw = LogWatcher(os.path.join(basedir, "twistd.log")) 

        d = lw.start() 

        d.addCallbacks(self.success, self.failure) 

        d.addBoth(lambda _ : self.rc) 

        return d 

 

    def sighup(self): 

        if self.sent_signal: 

            return 

        print "sending SIGHUP to process %d" % self.pid 

        self.sent_signal = True 

        os.kill(self.pid, signal.SIGHUP) 

 

    def success(self, res): 

        print """ 

Reconfiguration appears to have completed successfully. 

""" 

 

    def failure(self, why): 

        self.rc = 1 

        if why.check(BuildmasterTimeoutError): 

            print "Never saw reconfiguration finish." 

        elif why.check(ReconfigError): 

            print """ 

Reconfiguration failed. Please inspect the master.cfg file for errors, 

correct them, then try 'buildbot reconfig' again. 

""" 

        elif why.check(IOError): 

            # we were probably unable to open the file in the first place 

            self.sighup() 

        else: 

            print "Error while following twistd.log: %s" % why 

 

@in_reactor 

def reconfig(config): 

    basedir = config['basedir'] 

    quiet = config['quiet'] 

    r = Reconfigurator() 

    return r.run(basedir, quiet)