clearer names for actions, and infer actions better
[monitor.git] / commands / repair.py
1 #!/usr/bin/python
2
3 # This script is used to manipulate the operational state of nodes in
4 # different node groups.  These are basically set operations on nodes via the
5 # PLC api.
6
7 # Take the ng name as an argument....
8 # optionally, 
9 #  * get a list of nodes in the given nodegroup.
10 #  * set some or all in the set to rins.
11 #  * restart them all.
12 #  * do something else to them all.
13
14
15 import os
16 import time
17 import traceback
18 import sys
19 from optparse import OptionParser
20
21 from monitor import config
22 from monitor import parser as parsermodule
23 from monitor.common import *
24 from monitor.const import MINUP
25 from monitor.model import *
26 from monitor.wrapper import plc
27 from monitor.wrapper import plccache
28 from monitor.database.info.model import *
29 from monitor.database.info.interface import *
30
31 from monitor.query import verify,query_to_dict,node_select
32
33 def main(hostnames, config):
34     # commands:
35     i = 1
36     node_count = 1
37     print "failboot-repair"
38     for i,host in enumerate(hostnames):
39         try:
40             lb = plccache.plcdb_hn2lb[host]
41         except:
42             print "unknown host in plcdb_hn2lb %s" % host
43             email_exception("%s %s" % (i,host))
44             continue
45
46         nodeblack = BlacklistRecord.get_by(hostname=host)
47
48         if nodeblack and not nodeblack.expired():
49             print "skipping %s due to blacklist.  will expire %s" % (host, nodeblack.willExpire() )
50             continue
51
52         sitehist = SiteInterface.get_or_make(loginbase=lb)
53
54         recent_actions = sitehist.getRecentActions(hostname=host)
55
56         nodehist = HistoryNodeRecord.findby_or_create(hostname=host)
57
58         print "%s %s %s" % (i, nodehist.hostname, nodehist.status)
59
60         if nodehist.status == 'failboot' and \
61             changed_greaterthan(nodehist.last_changed, 0.25) and \
62             ( not found_between(recent_actions, 'bootmanager_restore', 0.5, 0) \
63                         or config.force ):
64                 # send down node notice
65                 # delay 0.5 days before retrying...
66                 print "send message for host %s bootmanager_restore" % host
67                 sitehist.runBootManager(host)
68
69         node_count = node_count + 1
70         print "time: ", time.strftime('%Y-%m-%d %H:%M:%S')
71         sys.stdout.flush()
72         session.flush()
73
74     session.flush()
75     return
76
77
78 if __name__ == "__main__":
79     parser = parsermodule.getParser(['nodesets'])
80     parser.set_defaults(rins=False,
81                         reboot=False,
82                         force=False, 
83                         nosetup=False, 
84                         verbose=False, 
85                         quiet=False,)
86
87     parser.add_option("", "--force", dest="force", action="store_true", 
88                         help="Force action regardless of previous actions/logs.")
89     parser.add_option("", "--rins", dest="rins", action="store_true", 
90                         help="Set the boot_state to 'rins' for all nodes.")
91     parser.add_option("", "--reboot", dest="reboot", action="store_true", 
92                         help="Actively try to reboot the nodes, keeping a log of actions.")
93
94     parser.add_option("", "--verbose", dest="verbose", action="store_true", 
95                         help="Extra debug output messages.")
96
97     parser = parsermodule.getParser(['defaults'], parser)
98     config = parsermodule.parse_args(parser)
99
100     fbquery = HistoryNodeRecord.query.all()
101     hostnames = [ n.hostname for n in fbquery ]
102     
103     if config.site:
104         # TODO: replace with calls to local db.  the api fails so often that
105         #         these calls should be regarded as unreliable.
106         l_nodes = plccache.GetNodesBySite(config.site)
107         filter_hostnames = [ n['hostname'] for n in l_nodes ]
108
109         hostnames = filter(lambda x: x in filter_hostnames, hostnames)
110
111     if config.node:
112         hostnames = [ config.node ] 
113
114     try:
115         main(hostnames, config)
116         session.flush()
117     except KeyboardInterrupt:
118         print "Killed by interrupt"
119         session.flush()
120         sys.exit(0)
121     except:
122         email_exception()
123         print traceback.print_exc();
124         print "fail all..."