X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=policy.py;h=992e5789c4675bcc00b7fc42bce1874eee951cb5;hb=7d52901a1fa58072b9b55aca27ad9f67fa9e5647;hp=7525c0d4e62933797e5022dc9011b4a8242dc966;hpb=7028fdb5e122089f2e1fb1c6a9178ab8f8aa5fe1;p=monitor.git diff --git a/policy.py b/policy.py index 7525c0d..992e578 100755 --- a/policy.py +++ b/policy.py @@ -21,13 +21,14 @@ 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() @@ -36,6 +37,41 @@ def logic(): 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 @@ -76,7 +112,7 @@ def main(hostnames, sitenames): # 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) + sitehist.sendMessage('online_notice', hostname=host, viart=False, saveact=True) print "send message for host %s online" % host @@ -91,25 +127,62 @@ def main(hostnames, sitenames): # 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 nodehist.firewall and \ not found_between(recent_actions, 'try_reboot', 3.5, 1): + # 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) + 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.haspcu and nodehist.status in ['offline', 'down'] and \ changed_greaterthan(nodehist.last_changed,1.5) and \ + not nodehist.firewall and \ found_between(recent_actions, 'try_reboot', 3.5, 1) and \ not found_within(recent_actions, 'pcufailed_notice', 3.5): + # 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 - 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... @@ -119,12 +192,17 @@ 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 + 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') @@ -134,9 +212,13 @@ def main(hostnames, sitenames): 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, @@ -144,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 @@ -160,24 +258,26 @@ 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 and not found_within(recent_actions, 'pause_penalty', 30): - # 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 @@ -251,6 +351,6 @@ if __name__ == "__main__": session.flush() sys.exit(0) except: - #email_exception() + email_exception() print traceback.print_exc(); print "fail all..."