X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=policy.py;h=992e5789c4675bcc00b7fc42bce1874eee951cb5;hb=ecea36bbf6aad3bbd3e544d336b89a45cff4ab34;hp=4befbd94b3452fe6bed2c39bc76e29c4ab61abeb;hpb=c9d06f3b274ecbc092a0b3eb1f5ceb6c0f734aad;p=monitor.git diff --git a/policy.py b/policy.py index 4befbd9..992e578 100755 --- a/policy.py +++ b/policy.py @@ -21,21 +21,57 @@ from optparse import OptionParser from monitor import config from monitor import parser as parsermodule from monitor.common import * +from monitor.const import MINUP from monitor.model import * from monitor.wrapper import plc from monitor.wrapper import plccache from monitor.database.info.model import * from monitor.database.info.interface import * -from nodequery import verify,query_to_dict,node_select +from monitor.query import verify,query_to_dict,node_select api = plc.getAuthAPI() def logic(): - plc.nodeBootState(host, 'rins') + plc.nodeBootState(host, 'reinstall') node_end_record(host) +def check_node_and_pcu_status_for(loginbase): + """ + this function checks whether all the nodes and associated pcus for a + given site are considered 'good'. + + If so, the function returns True. + Otherwise, the function returns False. + """ + + results = [] + for node in plccache.plcdb_lb2hn[loginbase]: + + noderec = FindbadNodeRecord.findby_or_create(hostname=node['hostname']) + nodehist = HistoryNodeRecord.findby_or_create(hostname=node['hostname']) + nodebl = BlacklistRecord.get_by(hostname=node['hostname']) + pcuhist = HistoryPCURecord.get_by(plc_pcuid=noderec.plc_pcuid) + + if (nodehist is not None and nodehist.status == 'good' and \ + ((pcuhist is not None and pcuhist.status == 'good') or (pcuhist is None)) ): + if nodebl is None: # no entry in blacklist table + results.append(True) + elif nodebl is not None and nodebl.expired(): # expired entry in blacklist table + results.append(True) + else: + results.append(False) # entry that is not expired. + else: + results.append(False) + + try: + print "test: %s" % results + # NOTE: incase results is empty, reduce does not work on an empty set. + return reduce(lambda x,y: x&y, results) and len(results) > MINUP + except: + return False + def main(hostnames, sitenames): # commands: i = 1 @@ -47,6 +83,7 @@ def main(hostnames, sitenames): lb = plccache.plcdb_hn2lb[host] except: print "unknown host in plcdb_hn2lb %s" % host + email_exception(host) continue nodeblack = BlacklistRecord.get_by(hostname=host) @@ -64,38 +101,88 @@ def main(hostnames, sitenames): print "%s %s %s" % (i, nodehist.hostname, nodehist.status) if nodehist.status == 'good' and \ changed_lessthan(nodehist.last_changed, 1.0) and \ + found_within(recent_actions, 'down_notice', 7.0) and \ not found_within(recent_actions, 'online_notice', 0.5): + # NOTE: chronicly flapping nodes will not get 'online' notices + # since, they are never up long enough to be 'good'. + # NOTE: searching for down_notice proves that the node has + # gone through a 'down' state first, rather than just + # flapping through: good, offline, online, ... + # # NOTE: there is a narrow window in which this command must be - # evaluated, otherwise the notice will not go out. this is not ideal. - sitehist.sendMessage('online_notice', hostname=host, viart=False) + # evaluated, otherwise the notice will not go out. + # this is not ideal. + sitehist.sendMessage('online_notice', hostname=host, viart=False, saveact=True) print "send message for host %s online" % host - pass - if ( nodehist.status == 'offline' or nodehist.status == 'down' ) and \ + # if a node is offline and doesn't have a PCU, remind the user that they should have one. + #if not nodehist.haspcu and nodehist.status in ['offline', 'down'] and \ + # changed_greaterthan(nodehist.last_changed,1.0) and \ + # not found_within(recent_actions, 'pcumissing_notice', 7.0): + # + # sitehist.sendMessage('pcumissing_notice', hostname=host) + # print "send message for host %s pcumissing_notice" % host + + # if it is offline and HAS a PCU, then try to use it. + if nodehist.haspcu and nodehist.status in ['offline', 'down'] and \ changed_greaterthan(nodehist.last_changed,1.0) and \ - not found_between(recent_actions, 'first_try_reboot', 3.5, 1): + not nodehist.firewall and \ + not found_between(recent_actions, 'try_reboot', 3.5, 1): - sitehist.attemptReboot(host) - print "send message for host %s first_try_reboot" % host - pass + # TODO: there MUST be a better way to do this... + # get fb node record for pcuid + fbpcu = None + fbnode = FindbadNodeRecord.get_latest_by(hostname=host) + if fbnode: + fbpcu = FindbadPCURecord.get_latest_by(plc_pcuid=fbnode.plc_pcuid) - # NOTE: non-intuitive is that found_between(first_try_reboot, 3.5, 1) + sitehist.attemptReboot(host) + print "send message for host %s try_reboot" % host + if not fbpcu.test_is_ok() and \ + not found_within(recent_actions, 'pcuerror_notice', 3.0): + + args = {} + if fbpcu: + args['pcu_name'] = fbpcu.pcu_name() + args['pcu_errors'] = fbpcu.pcu_errors() + args['plc_pcuid'] = fbpcu.plc_pcuid + else: + args['pcu_name'] = "error looking up pcu name" + args['pcu_errors'] = "" + args['plc_pcuid'] = 0 + + args['hostname'] = host + sitehist.sendMessage('pcuerror_notice', **args) + print "send message for host %s PCU Failure" % host + + + # NOTE: non-intuitive is that found_between(try_reboot, 3.5, 1) # will be false for a day after the above condition is satisfied - if ( nodehist.status == 'offline' or nodehist.status == 'down' ) and \ + if nodehist.haspcu and nodehist.status in ['offline', 'down'] and \ changed_greaterthan(nodehist.last_changed,1.5) and \ - found_between(recent_actions, 'first_try_reboot', 3.5, 1) and \ + not nodehist.firewall and \ + found_between(recent_actions, 'try_reboot', 3.5, 1) and \ not found_within(recent_actions, 'pcufailed_notice', 3.5): - # found_within(recent_actions, 'first_try_reboot', 3.5) and \ + # TODO: there MUST be a better way to do this... + # get fb node record for pcuid + fbpcu = None + fbnode = FindbadNodeRecord.get_latest_by(hostname=host) + if fbnode: + fbpcu = FindbadPCURecord.get_latest_by(plc_pcuid=fbnode.plc_pcuid) + if fbpcu: + pcu_name = fbpcu.pcu_name() + else: + pcu_name = "error looking up pcu name" + + # get fb pcu record for pcuid # send pcu failure message - #act = ActionRecord(**kwargs) - sitehist.sendMessage('pcufailed_notice', hostname=host) + sitehist.sendMessage('pcufailed_notice', hostname=host, pcu_name=pcu_name) print "send message for host %s PCU Failure" % host - pass - if nodehist.status == 'monitordebug' and \ - changed_greaterthan(nodehist.last_changed, 1) and \ + if nodehist.status == 'failboot' and \ + changed_greaterthan(nodehist.last_changed, 0.25) and \ not found_between(recent_actions, 'bootmanager_restore', 0.5, 0): # send down node notice # delay 0.5 days before retrying... @@ -105,23 +192,33 @@ def main(hostnames, sitenames): # sitehist.sendMessage('retry_bootman', hostname=host) if nodehist.status == 'down' and \ - changed_greaterthan(nodehist.last_changed, 2) and \ - not found_within(recent_actions, 'down_notice', 3.5): - # send down node notice - - sitehist.sendMessage('down_notice', hostname=host) - print "send message for host %s down" % host - pass + changed_greaterthan(nodehist.last_changed, 2): + if not nodehist.firewall and not found_within(recent_actions, 'down_notice', 3.5): + # send down node notice + sitehist.sendMessage('down_notice', hostname=host) + print "send message for host %s down" % host + + if nodehist.firewall and not found_within(recent_actions, 'firewall_notice', 3.5): + # send down node notice + #email_exception(host, "firewall_notice") + sitehist.sendMessage('firewall_notice', hostname=host) + print "send message for host %s down" % host node_count = node_count + 1 + print "time: ", time.strftime('%Y-%m-%d %H:%M:%S') + sys.stdout.flush() session.flush() for i,site in enumerate(sitenames): sitehist = SiteInterface.get_or_make(loginbase=site) siteblack = BlacklistRecord.get_by(loginbase=site) + skip_due_to_blacklist=False if siteblack and not siteblack.expired(): print "skipping %s due to blacklist. will expire %s" % (site, siteblack.willExpire() ) + skip_due_to_blacklist=True + sitehist.clearPenalty() + sitehist.applyPenalty() continue # TODO: make query only return records within a certin time range, @@ -129,14 +226,30 @@ def main(hostnames, sitenames): recent_actions = sitehist.getRecentActions(loginbase=site) print "%s %s %s" % (i, sitehist.db.loginbase, sitehist.db.status) + if sitehist.db.status == 'down': - if not found_within(recent_actions, 'pause_penalty', 30) and \ + if sitehist.db.penalty_pause and \ + changed_greaterthan(sitehist.db.penalty_pause_time, 30): + + email_exception("", "clear pause penalty for site: %s" % sitehist.db.loginbase) + sitehist.closeTicket() + # NOTE: but preserve the penalty status. + sitehist.clearPenaltyPause() + + if sitehist.db.message_id != 0 and \ + sitehist.db.message_status == 'open' and \ + not sitehist.db.penalty_pause: + + email_exception("", "pause penalty for site: %s" % sitehist.db.loginbase) + sitehist.setPenaltyPause() + + if not sitehist.db.penalty_pause and \ not found_within(recent_actions, 'increase_penalty', 7) and \ changed_greaterthan(sitehist.db.last_changed, 7): # TODO: catch errors sitehist.increasePenalty() - #sitehist.applyPenalty() + sitehist.applyPenalty() sitehist.sendMessage('increase_penalty') print "send message for site %s penalty increase" % site @@ -145,26 +258,31 @@ def main(hostnames, sitenames): # clear penalty # NOTE: because 'all clear' should have an indefinite status, we # have a boolean value rather than a 'recent action' - if sitehist.db.penalty_applied: + if sitehist.db.penalty_applied or sitehist.db.penalty_pause: # send message that penalties are cleared. sitehist.clearPenalty() - #sitehist.applyPenalty() + sitehist.applyPenalty() sitehist.sendMessage('clear_penalty') sitehist.closeTicket() print "send message for site %s penalty cleared" % site - - # find all ticket ids for site ( could be on the site record? ) - # determine if there are penalties within the last 30 days? - # if so, add a 'pause_penalty' action. - if sitehist.db.message_id != 0 and sitehist.db.message_status == 'open' and sitehist.db.penalty_level > 0: - # pause escalation - print "Pausing penalties for %s" % site - sitehist.pausePenalty() + + # check all nodes and pcus for this site; if they're all ok, + # close the ticket, else leave it open. + # NOTE: in the case where a PCU reboots and fails, a message is + # sent, but the PCU may appear to be ok according to tests. + # NOTE: Also, bootmanager sends messages regarding disks, + # configuration, etc. So, the conditions here are 'good' + # rather than 'not down' as it is in sitebad. + close_ticket = check_node_and_pcu_status_for(site) + if close_ticket: + sitehist.closeTicket() site_count = site_count + 1 + print "time: ", time.strftime('%Y-%m-%d %H:%M:%S') + sys.stdout.flush() session.flush() session.flush() @@ -227,11 +345,12 @@ if __name__ == "__main__": try: main(hostnames, sitenames) + session.flush() except KeyboardInterrupt: print "Killed by interrupt" session.flush() sys.exit(0) except: - #email_exception() + email_exception() print traceback.print_exc(); print "fail all..."