clearer names for actions, and infer actions better
[monitor.git] / zabbix / zabbixsite.py
index 9c0267f..052b200 100755 (executable)
@@ -4,11 +4,14 @@ from os import getcwd
 from os.path import dirname, exists, join
 import sys
 import md5
+import glob
 
 from monitor import config
-from monitor.database.dborm import * 
+from monitor.database.dborm import zab_session as session
+from monitor.database.zabbixapi.model import *
 from monitor.database.zabbixapi.emailZabbix import *
 from monitor.database.zabbixapi import defines
+from monitor.util.file import *
 
 
 
@@ -37,6 +40,8 @@ def delete_site(loginbase):
                        #user.delete()
                        pass
                ug.delete()
+       else:
+               print usergroupname, " not found"
 
        hg = HostGroup.get_by(name=hostgroupname)
        if hg: 
@@ -45,20 +50,30 @@ def delete_site(loginbase):
                for host in hg.host_list:
                        host.delete()
                hg.delete()
+       else:
+               print hostgroupname, " not found"
 
        # delete dr
        dr = DiscoveryRule.get_by(name=discovery_rule_name)
        if dr: dr.delete()
+       else: print discovery_rule_name, " not found"
 
        da = Action.get_by(name=discovery_action_name)
        if da: da.delete()
+       else: print discovery_action_name, " not found"
 
        ea = Action.get_by(name=escalation_action_name)
        if ea: ea.delete()
+       else: print escalation_action_name, " not found"
 
        return
 
 
+# NOTE: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+##     These functions can ONLY be run when the server and gui are offline.
+##     Any changes to the db while this is running risks introducing a failure
+##        to commit, and therefore error.
+# NOTE: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 def setup_global():
        # GLOBAL:
        #       update mediatype for email.
@@ -72,6 +87,7 @@ def setup_global():
        print "checking for correct configuration"
        mediatype = MediaType.get_by(smtp_email=config.from_email)
        if not mediatype:
+               mediatype = MediaType.get_by(description="Email")
                # NOTE: assumes smtp server is local to this machine.
                print "updating email server configuration"
                mediatype.smtp_server='localhost'
@@ -86,22 +102,30 @@ def setup_global():
        print "checking zabbix server host info"
        zabbixserver = Host.get_by(host="ZABBIX Server")
        if zabbixserver:
-               print "UPDATING Primary Zabbix server entry"
-               zabbixserver.host="MyPLC Server"
-               zabbixserver.ip=config.MONITOR_IP
-               zabbixserver.dns=config.MONITOR_HOSTNAME
-               zabbixserver.useip=1
+               # TODO: verify that this works.  it has failed once on fresh
+               # install... not sure why.
+#              print "Removing default Zabbix server entry"
+#              zabbixserver.delete()
+               zabbixserver.host="unused default server"
+
+               # NOTE: creating a host and assigning a template cannot work 
+               #       due to the crazy item, trigger, action
+               #               copying that the php code does during a host add.
+               # NOTE: Instead, reformat any *xml.in templates and import those
+               #               during /etc/plc.d/monitor sync
+               for file in glob.glob("%s/zabbix/templates/*.xml.in" % config.MONITOR_SCRIPT_ROOT):
+                       if 'zabbix_server' in file:
+                               buf = loadFile(file)
+                               args = {'hostname' : config.MONITOR_HOSTNAME, 'ip' : config.MONITOR_IP}
+                               dumpFile(file[:-3], buf % args)
 
-       ############################ DEFAULT TEMPLATES
-       # pltemplate - via web, xml import
-       # TODO: os.system("curl --post default_templates.xml")
 
        ##################### SCRIPTS 
        ## TODO: add calls to check/reset the boot states.
        print "checking scripts"
        script1 = Script.find_or_create(name="RebootNode",
                                                                        set_if_new = {
-                                                                               'command':"/usr/share/monitor-server/reboot.py {HOST.CONN}",
+                                                                               'command':"%s/monitor/reboot.py {HOST.CONN}" % config.MONITOR_SCRIPT_ROOT,
                                                                                'host_access':3 # r/w)
                                                                        })
        script2 = Script.find_or_create(name="NMap",
@@ -111,23 +135,52 @@ def setup_global():
                                                })
        return
 
+def merge_iplist(iplist):
+       # TODO:  rewrite addresses as x.x.x.y-z rather than x.x.x.y,x.x.x.z if y-z==1
+       ips = iplist.split(',')
+       ips.sort()
+       prev=None
+       newlist=""
+       for ip in ips:
+               fields = ip.split('.')
+               first = ".".join(fields[:2])
+               last  = int(fields[3])
+               if prev:
+                       if last - prev == 1:
+                               pass
+               prev=last
+               newlist += "%s,"
+       return newlist[:-1]
+
 def setup_site(loginbase, techemail, piemail, iplist):
 
-       # TODO: Initially adding this info is ok. what about updates to users,
-       # additional hosts, removed users from plc, 
-       # TODO: send a message when host is discovered.
-       # TODO: update 'discovered' hosts with dns name.
        # TODO: remove old nodes that are no longer in the plcdb.
+       # TODO: remove old users that are no longer in the plcdb.
+       # TODO: consider creating two user groups for Tech & PI emails
+
+       # NOTE: setup default valus for EMAIL
+       mailtxt.reformat({'hostname' : config.MONITOR_HOSTNAME, 
+                                         'support_email' : config.support_email})
+
+       # NOTE: verify arguments
+       if len(iplist) > 255:
+               raise Exception("iplist length is too long!")
 
        BI_WEEKLY_ESC_PERIOD = int(60*60*24)
-       BI_WEEKLY_ESC_PERIOD = int(60) # testing...
+       DISCOVERY_DELAY = 3600
+       BI_WEEKLY_ESC_PERIOD = int(300)
+       DISCOVERY_DELAY = 240 # testing
 
        # User Group
-       site_user_group = UsrGrp.find_or_create(name="%s_usergroup" % loginbase)
-       for user in set(techemail + piemail):
+       site_user_group = UsrGrp.find_or_create(name=USERGROUP_NAME % loginbase)
+       #for user in set(techemail + piemail + [config.cc_email]):
+       for user in set([config.cc_email]):
+               if not user: continue
                # USER
                u = User.find_or_create(alias=user, type=1,
                                                                set_if_new={'passwd' : md5.md5(user).hexdigest()},
+                                                               # exec_if_new avoids creating a Media object that
+                                                               # will not actually be used, if the user already exists
                                                                exec_if_new=lambda obj: \
                                                                obj.media_list.append( Media(mediatypeid=1, sendto=user)))
 
@@ -136,8 +189,10 @@ def setup_site(loginbase, techemail, piemail, iplist):
 
        # HOST GROUP
        plc_host_group = HostGroup.find_or_create(name="MyPLC Hosts")
-       site_host_group = HostGroup.find_or_create(name="%s_hostgroup" % loginbase)
-       plctemplate = Host.get_by(host="Template_Linux_PLHost")
+       print "myplc groupid: ", plc_host_group.groupid
+       site_host_group = HostGroup.find_or_create(name=HOSTGROUP_NAME % loginbase)
+       print "site groupid: ", site_host_group.groupid
+       plctemplate = Host.get_by(host="Template_Linux_PLC_Host")
        escalation_action_name = ESCALATION_ACTION_NAME % loginbase
        discovery_action_name = DISCOVERY_ACTION_NAME % loginbase
        discovery_rule_name = DISCOVERY_RULE_NAME % loginbase
@@ -148,7 +203,7 @@ def setup_site(loginbase, techemail, piemail, iplist):
 
        # DISCOVERY RULE & CHECK
        dr = DiscoveryRule.find_or_create(name=discovery_rule_name,
-                         delay=3600,
+                         delay=DISCOVERY_DELAY,
                          proxy_hostid=0,
                          set_if_new = {'iprange':iplist},
                          exec_if_new=lambda obj: \
@@ -156,10 +211,7 @@ def setup_site(loginbase, techemail, piemail, iplist):
                                                                                key_="system.uname", ports=10050) )
                        )
        if dr.iprange != iplist:
-               if len(iplist) < 255:
-                       dr.iprange = iplist
-               else:
-                       raise Exception("iplist length is too long!")
+               dr.iprange = iplist
                
 
        # DISCOVERY ACTION for these servers
@@ -192,6 +244,15 @@ def setup_site(loginbase, techemail, piemail, iplist):
                                ]
                                # THEN
                a.actionoperation_list=[
+                                       ## Send Email
+                                       #ActionOperation(
+                                       #       operationtype=defines.OPERATION_TYPE_MESSAGE,
+                                       #       shortdata=mailtxt.node_discovered_subject,
+                                       #       longdata=mailtxt.node_discovered,
+                                       #       object=defines.OPERATION_OBJECT_GROUP, 
+                                       #       objectid=site_user_group.usrgrpid, 
+                                       #       esc_period=0, esc_step_to=1, esc_step_from=1, 
+                                       #),
                                        # Add Host
                                        ActionOperation(
                                                operationtype=defines.OPERATION_TYPE_HOST_ADD,
@@ -207,7 +268,7 @@ def setup_site(loginbase, techemail, piemail, iplist):
                                                operationtype=defines.OPERATION_TYPE_GROUP_ADD,
                                                object=0, objectid=site_host_group.groupid,
                                                esc_period=0, esc_step_from=1, esc_step_to=1),
-                                       # Link to Template 'Template_Linux_Minimal'
+                                       # Link to Template 'Template_Linux_PLC_Host'
                                        ActionOperation(
                                                operationtype=defines.OPERATION_TYPE_TEMPLATE_ADD,
                                                object=0, objectid=plctemplate.hostid,
@@ -215,7 +276,14 @@ def setup_site(loginbase, techemail, piemail, iplist):
                                ]
        else:
                # TODO: verify iplist is up-to-date
-               pass
+               # NOTE: len(a.actioncondition_list) > 0
+               #ip_condition  = a.actioncondition_list[0]
+               ip_condition = filter(lambda x: x.conditiontype == defines.CONDITION_TYPE_DHOST_IP, a.actioncondition_list)[0]
+               print ip_condition.conditiontype
+               print defines.CONDITION_TYPE_DHOST_IP
+               assert ip_condition.conditiontype == defines.CONDITION_TYPE_DHOST_IP
+               if ip_condition.value != iplist:
+                       ip_condition.value = iplist
 
        # ESCALATION ACTION for these servers
        ea = Action.find_or_create(name=escalation_action_name,
@@ -251,19 +319,19 @@ def setup_site(loginbase, techemail, piemail, iplist):
                                        objectid=site_user_group.usrgrpid, 
                                        esc_period=0, esc_step_to=3, esc_step_from=3, 
                                        operationcondition_list=[ OperationConditionNotAck() ] ),
-                               ActionOperation(operationtype=defines.OPERATION_TYPE_MESSAGE,
-                                       shortdata=mailtxt.nodedown_one_subject,
-                                       longdata=mailtxt.nodedown_one,
-                                       object=defines.OPERATION_OBJECT_GROUP, 
-                                       objectid=site_user_group.usrgrpid, 
-                                       esc_period=0, esc_step_to=7, esc_step_from=7, 
-                                       operationcondition_list=[ OperationConditionNotAck() ] ),
+                               #ActionOperation(operationtype=defines.OPERATION_TYPE_MESSAGE,
+                               #       shortdata=mailtxt.nodedown_one_subject,
+                               #       longdata=mailtxt.nodedown_one,
+                               #       object=defines.OPERATION_OBJECT_GROUP, 
+                               #       objectid=site_user_group.usrgrpid, 
+                               #       esc_period=0, esc_step_to=7, esc_step_from=7, 
+                               #       operationcondition_list=[ OperationConditionNotAck() ] ),
                                # STAGE 2
                                ActionOperation(operationtype=defines.OPERATION_TYPE_COMMAND, 
                                        esc_step_from=10, esc_step_to=10, 
                                        esc_period=0,
                                        shortdata="",
-                                       longdata="zabbixserver:/usr/share/monitor-server/checkslices.py {HOSTNAME} disablesite"
+                                       longdata="%s:%s/checkslices.py {HOSTNAME} disablesite" % ( config.MONITOR_HOSTNAME, config.MONITOR_SCRIPT_ROOT )
                                        operationcondition_list=[ OperationConditionNotAck() ]),
                                ActionOperation(operationtype=defines.OPERATION_TYPE_MESSAGE, 
                                        shortdata=mailtxt.nodedown_two_subject,
@@ -273,37 +341,37 @@ def setup_site(loginbase, techemail, piemail, iplist):
                                        object=defines.OPERATION_OBJECT_GROUP, 
                                        objectid=site_user_group.usrgrpid, 
                                        operationcondition_list=[ OperationConditionNotAck() ] ), 
-                               ActionOperation(operationtype=defines.OPERATION_TYPE_MESSAGE, 
-                                       shortdata=mailtxt.nodedown_two_subject,
-                                       longdata=mailtxt.nodedown_two,
-                                       esc_step_from=14, esc_step_to=14, 
-                                       esc_period=0, 
-                                       object=defines.OPERATION_OBJECT_GROUP, 
-                                       objectid=site_user_group.usrgrpid, 
-                                       operationcondition_list=[ OperationConditionNotAck() ] ), 
+                               #ActionOperation(operationtype=defines.OPERATION_TYPE_MESSAGE, 
+                               #       shortdata=mailtxt.nodedown_two_subject,
+                               #       longdata=mailtxt.nodedown_two,
+                               #       esc_step_from=14, esc_step_to=14, 
+                               #       esc_period=0, 
+                               #       object=defines.OPERATION_OBJECT_GROUP, 
+                               #       objectid=site_user_group.usrgrpid, 
+                               #       operationcondition_list=[ OperationConditionNotAck() ] ), 
 
                                # STAGE 3
                                ActionOperation(operationtype=defines.OPERATION_TYPE_COMMAND, 
                                        esc_step_from=17, esc_step_to=17, 
                                        esc_period=0, 
                                        shortdata="",
-                                       longdata="zabbixserver:/usr/share/monitor-server/checkslices.py {HOSTNAME} disableslices"
+                                       longdata="%s:%s/monitor/reboot.py {HOSTNAME}" % ( config.MONITOR_HOSTNAME, config.MONITOR_SCRIPT_ROOT )
                                        # TODO: send notice to users of slices
                                        operationcondition_list=[ OperationConditionNotAck() ]),
-                               ActionOperation(operationtype=defines.OPERATION_TYPE_MESSAGE, 
-                                       shortdata=mailtxt.nodedown_three_subject,
-                                       longdata=mailtxt.nodedown_three,
-                                       esc_step_from=17, esc_step_to=17, 
-                                       esc_period=0, 
-                                       object=defines.OPERATION_OBJECT_GROUP, 
-                                       objectid=site_user_group.usrgrpid, 
-                                       operationcondition_list=[ OperationConditionNotAck() ] ), 
+                               #ActionOperation(operationtype=defines.OPERATION_TYPE_MESSAGE, 
+                               #       shortdata=mailtxt.nodedown_three_subject,
+                               #       longdata=mailtxt.nodedown_three,
+                               #       esc_step_from=17, esc_step_to=17, 
+                               #       esc_period=0, 
+                               #       object=defines.OPERATION_OBJECT_GROUP, 
+                               #       objectid=site_user_group.usrgrpid, 
+                               #       operationcondition_list=[ OperationConditionNotAck() ] ), 
                                # STAGE 4++
                                ActionOperation(operationtype=defines.OPERATION_TYPE_COMMAND, 
                                        esc_step_from=21, esc_step_to=0, 
                                        esc_period=int(BI_WEEKLY_ESC_PERIOD*3.5),
                                        shortdata="",
-                                       longdata="zabbixserver:/usr/share/monitor-server/checkslices.py {HOSTNAME} forever"
+                                       longdata="%s:%s/checkslices.py {HOSTNAME} forever" % ( config.MONITOR_HOSTNAME, config.MONITOR_SCRIPT_ROOT)
                                        operationcondition_list=[ OperationConditionNotAck() ]),
                                ActionOperation(operationtype=defines.OPERATION_TYPE_MESSAGE, 
                                        shortdata=mailtxt.nodedown_four_subject,