creation : creates nagios config from a set of sites
authorthierry <thierry@41d37cc5-eb28-0410-a9bf-d37491348ade>
Sun, 18 Feb 2007 15:31:25 +0000 (15:31 +0000)
committerthierry <thierry@41d37cc5-eb28-0410-a9bf-d37491348ade>
Sun, 18 Feb 2007 15:31:25 +0000 (15:31 +0000)
nagios/configurator/NagiosConfig.py [new file with mode: 0644]
nagios/configurator/cgi.cfg [new file with mode: 0644]
nagios/configurator/comon_query.py [new file with mode: 0755]
nagios/configurator/configurator.py [new file with mode: 0755]
nagios/configurator/generic.cfg [new file with mode: 0644]
nagios/configurator/makeHTML.py [new file with mode: 0644]
nagios/configurator/misccommands.cfg [new file with mode: 0644]
nagios/configurator/nagios.cfg [new file with mode: 0644]
nagios/configurator/nagios.py [new file with mode: 0644]
nagios/configurator/onelab.txt [new file with mode: 0644]

diff --git a/nagios/configurator/NagiosConfig.py b/nagios/configurator/NagiosConfig.py
new file mode 100644 (file)
index 0000000..d159279
--- /dev/null
@@ -0,0 +1,450 @@
+import os
+import sys
+import xmlrpclib
+
+### downloaded makeHTML from:
+### article
+### http://www.hoboes.com/Mimsy/?ART=128
+### download \
+### http://www.hoboes.com/Mimsy/library/downloads/makeHTML.py.gz
+import makeHTML
+
+# utilities for building comon queries
+import comon_query
+    
+
+class NagiosConfig:
+
+    # static
+    _admin_role=10
+    _pi_role=20
+    # person emails to exclude
+    _exclude_admins={'maint@localhost.localdomain':True}
+
+    # set of services to check on each node
+    # these refer to generic services you must have in generic.cfg
+    _full_node_services = ['ssh',
+                           'ssh-root',
+                           'ssh-pl_conf',
+                           ]
+    _restricted_node_services = ['ssh',
+                                 'planetlab',
+                                 ]
+
+    _verbose = False
+# WARNING : some site names come with wierd unicode chars
+# in this case verbose mode might fail
+#    _verbose = True
+
+    plchost=None
+    xmlrpcserver = None
+    auth=None
+
+    dest_email = None
+
+    # a tree of sites, for access to nodes and contacts
+    siteTree = None
+    # list of admin people
+    allAdmins = {}
+
+    ### record arguments
+    def __init__ (self, plchost, plcid, plcpasswd, plcrole):
+        self.plchost = plchost
+
+        self.auth={}
+        self.auth['Username'] = plcid
+        self.auth['AuthMethod'] = "password"
+        self.auth['AuthString'] = plcpasswd
+        self.auth['Role']=plcrole
+
+    def Auth (self):
+        return self.auth
+
+    ### connect to xml rpc server
+    def Connect (self):
+            
+        try:
+            self.xmlrpcserver = xmlrpclib.Server("https://%s/PLCAPI/"
+                                                 % (self.plchost))
+        except:
+            self.xmlrpcserver = None
+            
+        return self.xmlrpcserver
+
+    def set_verbose (self):
+       self._verbose =  True
+
+    def verbose (self,arg):
+        if (self._verbose):
+            print str(arg)
+
+    def GatherData (self, email, sitefile):
+
+        # if email is None, we NEED to have admin role
+        # otherwise let's dont wait 10 minutes before we fail
+        AdminRoleRequired = "admin role required, or provide -o/-O"
+        if not email:
+            if self.auth['Role'] != 'admin':
+                raise AdminRoleRequired
+
+        self.dest_email = email
+
+        self.verbose ("Gathering")
+        server = self.Connect()
+        auth = self.Auth ()
+
+        if sitefile:
+            # open and parse the file, let's gather site_ids in the process
+            self.verbose("Opening site file %s"%sitefile)
+            siteF=open(sitefile,'r')
+            selected_ids=[]
+            while 1:
+                siteline=siteF.readline()
+                if not siteline:
+                    break
+                selected_ids += [int(siteline.split(' ')[0])]
+            siteF.close()
+            sitesList = server.GetSites(auth,selected_ids)
+        else:
+            # get list of all sites
+            sitesList = server.GetSites(auth)
+        self.verbose("Working on a total of %d sites"%len(sitesList))
+
+        selectedNodeIds = [];
+        for site in sitesList:
+            selectedNodeIds += site['node_ids']
+
+       # get all nodenetworks
+       allNodeNetworks = server.GetNodeNetworks (auth)
+       allNodeNetworksIndex = dict ( [ ( nn['nodenetwork_id'],nn) for nn in allNodeNetworks ] )
+
+        # get list of nodes
+        # might wish to restrict the returned attributes
+        selectedNodes = server.GetNodes(auth,selectedNodeIds,['node_id','hostname','nodenetwork_ids'])
+        self.verbose("Got a total of %d nodes"%len(selectedNodes))
+
+        for node in selectedNodes:
+           if not node['nodenetwork_ids']:
+               print 'WARNING : Node %s has no nodenetwork thus no IP'%node['hostname']
+           nn = allNodeNetworksIndex[node['nodenetwork_ids'][0]]
+           node['ip'] = nn['ip']
+       
+
+        # index it by node_id
+        selectedNodesIndex = dict( [ (node['node_id'],node) for node in selectedNodes ] )
+
+        self.siteTree = {}
+        for site in sitesList :
+            self.verbose( "SITE = %s" % site['name'])
+            site_id=site['site_id']
+            siteHash = {}
+            self.siteTree[site_id] = siteHash
+           node_ids = site['node_ids']
+            self.verbose( "NODES IDS = " + str(node_ids))
+           siteNodes=[ selectedNodesIndex[node_id] for node_id in node_ids ]
+           nodesHash = dict ( [ (node['node_id'],node) for node in siteNodes ] )
+            personsHash = {}
+            siteHash['site'] = site
+            siteHash['nodes'] = nodesHash
+            siteHash['persons'] = personsHash
+        
+        # We are provided a hard-wired e-mail :
+        # dont scan all people (maybe we cannot)
+        if not email:
+            
+            # get list of people
+            allPersons = server.GetPersons (auth, [],['person_id','email',
+                                                     'first_name','last_name'])
+            for person in allPersons:
+                person_id = person['person_id']
+                # keep only PIs
+                roles = server.AdmGetPersonRoles (auth,person_id)
+                is_admin = roles.has_key(str(self._admin_role))
+                is_pi = roles.has_key(str(self._pi_role))
+                if is_admin:
+                    ### handle exclude list
+                    if not self._exclude_admins.has_key(person['email']):
+                        self.allAdmins[person_id]=person
+                elif is_pi:
+                    person_sites=server.AdmGetPersonSites(auth,person_id)
+                    for site_id in person_sites:
+                        personsHash = self.siteTree[site_id]['persons']
+                        personsHash[person_id]=person
+                        person['full_name']=person['first_name']+person['last_name']
+                        self.verbose("Added PI %s" % person['full_name'])
+
+    _define_host="""define host{
+        use                             generic-host
+        host_name                       %s
+        alias                           %s
+        address                         %s
+        contact_groups                  %s_pis
+        }\n"""
+    _define_hostgroup="""define hostgroup{
+        hostgroup_name                  %s
+        alias                           %s
+        members                         %s
+        }\n"""
+    # as of nagios-2.5-2.fc4 - apparently cannot use genericity in contacts
+    _define_contact="""define contact{
+        contact_name                    %s
+        alias                           %s %s
+        email                           %s
+        service_notification_period     24x7
+        host_notification_period        24x7
+        service_notification_options    w,u,c,r
+        host_notification_options       d,r
+        service_notification_commands   notify-by-email
+        host_notification_commands      host-notify-by-email
+        }\n"""
+    _define_contactgroup="""define contactgroup{
+        contactgroup_name               %s_pis
+        alias                           %s
+        members                         %s
+        }\n"""
+    _define_service="""define service{
+        use                             generic-%s
+        host_name                       %s
+        contact_groups                  %s_pis
+        servicegroups                   %s
+        }\n"""
+    _define_servicegroup="""define servicegroup{
+        servicegroup_name               %s
+        alias                           all %s
+        }\n"""
+
+    def WriteNagiosConfig (self, dirname):
+
+        site_ids=self.siteTree.keys()
+        site_ids.sort()
+
+
+        # by default use all avail services
+        node_services = self._full_node_services
+        # but in restricted mode some wont work out
+        if self.dest_email:
+            node_services = self._restricted_node_services
+
+        # generate contact file
+        # with people with admin roles, and also
+        # centraladmin if email was provided 
+        # located in main dir so we can have control on load order
+        filename = "%s/%s.cfg"%(dirname,"planetlab")
+        print ( "Opening %s for writing" % filename)
+        file = open (filename,'w')
+        for admin_id in self.allAdmins.keys():
+            admin=self.allAdmins[admin_id]
+            file.write(self._define_contact%
+                       ('rootadmin','root','admin',admin['email']))
+        if self.dest_email:
+            file.write(self._define_contact%
+                       (self.dest_email,'central','admin',self.dest_email))
+
+        for service in node_services:
+            file.write(self._define_servicegroup
+                       %(service,service))
+        
+        file.close()
+
+        ### manage planetlab subdir
+        planetlabdir="%s/planetlab/"%dirname
+        import os.path
+        if not os.path.isdir (planetlabdir):
+            try:
+                print "Trying to create subdir %s"%planetlabdir
+                os.mkdir (planetlabdir)
+            except Exception,e:
+                print "Failed -- exiting"
+                sys.exit(1)
+
+        import dircache
+        ls = dircache.listdir(planetlabdir)
+        import re
+        m=re.compile('^.*\.cfg$')
+        cfgs=filter(lambda x: m.match(x),ls)
+        if len(cfgs) != 0:
+            print "Warning : you have %d nagios configs left in %s"%(
+                len(cfgs),planetlabdir)
+            print "It's OK to keep them, if that's what you're trying to do"
+
+        ### scan over sites
+        for site_id in site_ids:
+
+            siteHash=self.siteTree[site_id]
+            site = siteHash['site']
+            sitename = site['name']
+            sitebase = site['login_base']
+
+            nodes = siteHash['nodes']
+            node_ids = nodes.keys()
+            node_ids.sort()
+            if len(node_ids) != 0:
+
+                filename = "%s/%s.cfg"%(planetlabdir,sitebase)
+                print ( "Opening %s for writing" % filename)
+                file = open (filename,'w')
+
+                ### without email / use real people
+                if not self.dest_email:
+                    persons = siteHash ['persons']
+
+                    self.verbose("retrieved PIs = %s"%str(persons))
+                        
+                    if len(persons) != 0:
+                        personnames=''
+                        for person_id in persons.keys():
+                            person=persons[person_id]
+                            personname=person['full_name']
+                            if len(personnames) == 0:
+                                personnames = personname
+                            else:
+                                personnames = "%s,%s"%(personnames,personname)
+                            file.write(self._define_contact
+                                       %(personname,
+                                         person['first_name'],
+                                         person['last_name'],
+                                         person['email']))
+
+                        file.write(self._define_contactgroup
+                                   %(sitebase,sitename,personnames))
+                else:
+                    file.write(self._define_contactgroup
+                               %(sitebase,sitename,self.dest_email))
+                    
+
+                nodenames=""
+                for node_id in node_ids:
+                    node = nodes[node_id]
+                    if len(nodenames) == 0:
+                        nodenames = node['hostname']
+                    else:
+                        nodenames = "%s,%s"%(nodenames,node['hostname'])
+                    file.write(self._define_host
+                               %(node['hostname'],node['hostname'],
+                                 node['ip'],sitebase))
+
+                    for service in node_services:
+                        file.write(self._define_service
+                                   %(service,node['hostname'],sitebase,service))
+
+            
+                file.write(self._define_hostgroup
+                           %(sitebase,sitename,nodenames))
+
+                file.close()
+
+#################### static html file with bookmarks to comon site-centric queries
+# a first draft tried to create a column for easying the bookmarking process
+# I did not completely succeed, because
+# the javascript interface for firefox seems to only allow
+# the creation of bookmarks in the sidebar
+# in fact you can bookmark the link, but when you use that bookmark
+# the target url is opened in the sidebar
+# you can easily fix this by editing the bookmark and uncheck 
+# a dialob box, but that's not what we want
+# it's much easier to directly use the 'Bookmark this link'
+# from the firefox menu
+# so let's forget about this altogether
+
+#    ### bookmarks
+#    def ManualBookmark (self, url, text, bookmark_name):
+#        bookmark_link="""<a href='javascript:addToFavorites("%s","%s")'>
+#        <font color='#0000FF' face="Verdana">%s</font></a>"""
+#        # the single quotes in the URL need to be html-encoded 
+#        cleanurl = url.replace ("'","%27")
+#        return bookmark_link%(makeHTML.encode(cleanurl),bookmark_name,text)
+#
+#    bookmark_code="""<script language="JavaScript" type="Text/Javascript">
+#<!-- // Hide script from older browsers
+#     // script by http://www.hypergurl.com
+#     function addToFavorites(url,title) {
+#      if (window.sidebar) { // Mozilla Firefox Bookmark
+#         window.sidebar.addPanel(title, url,"");
+#        } else if (window.external) { // IE Favorite
+#           window.external.AddFavorite(url,title) 
+#        } else {
+#           alert("Sorry! Your browser doesn't support this function."); 
+#        }
+#     }
+#// -->
+#</script>""" ### ' for fooling emacs
+
+    def ComonNodesSelect (self,nodes):
+        names = map(lambda node: node['hostname'],nodes)
+        filters = map (comon_query.filter_node,names)
+        server = comon_query.SERVER
+        return comon_query.full_url(server,'||'.join(filters))
+
+    ### could not find the makeHTML tool for that
+    def ManualAnchor (self,name,value):
+        return '<a name="%s">%s</a>' % (name,value)
+
+    def SiteRow (self,site_id):
+    ### returns a (makeHTML) row for the given site
+
+        siteHash = self.siteTree[site_id]
+        site = siteHash['site']
+        sitename = site['name']
+        sitebase = site['login_base']
+
+        nodes = siteHash['nodes'].values()
+        if len(nodes) == 0 :
+            return None
+        else:
+            row = makeHTML.tableRow()
+            query=self.ComonNodesSelect(nodes)
+            row.addCells([makeHTML.link(content=sitename, url=query),
+                          self.ManualAnchor(sitebase,sitebase),
+#                          self.ManualBookmark(query,
+#                                              "Bookmark it",
+#                                              "Comon on %s"%sitename),
+                          ])
+            return row
+
+    def MakeSiteTable (self, sites):
+        ### create table / sitename
+        table = makeHTML.table ()
+        ### first row
+        head_row = makeHTML.tableRow()
+        head_row.addCells ( ['Site name',
+                             'Site login',
+#                             'Comon query',
+                             ])
+        table.addRow(rowList=[head_row])
+
+        for site in sites: 
+            table.addRow ( rowList=[self.SiteRow(site['site_id'])])
+        return table
+
+    ### Write a single index page that contains one bookmark per site
+    def WriteComonLinks (self, indexname):
+
+        pageHead = makeHTML.part('head')
+        pageHead.addPart('title',content='Comon links for all sites')
+#        pageHead.addPiece(bookmark_code)
+        
+        pageBody = makeHTML.part('body')
+        pageBody.addPart('h1',content='Comon links, per site')
+
+        sites = map(lambda s: s['site'],self.siteTree.values())
+
+        pageBody.addPart('h2',content='By site name')
+
+        sites.sort (lambda s1,s2: cmp(s1['name'],s2['name']))
+        pageBody.addPart('p',self.MakeSiteTable(sites))
+
+        pageBody.addPart('h2',content='By site login')
+
+        sites.sort (lambda s1,s2: cmp(s1['login_base'],s2['login_base']))
+        pageBody.addPart('p',self.MakeSiteTable(sites))
+
+        fullPage = makeHTML.part('html')
+        fullPage.addPiece(pageHead)
+        fullPage.addPiece(pageBody)
+
+        text=fullPage.make()
+
+        print ( "Opening %s for writing" % indexname)
+        index=open (indexname,"w")
+        index.write(text+"\n")
+        index.close()
diff --git a/nagios/configurator/cgi.cfg b/nagios/configurator/cgi.cfg
new file mode 100644 (file)
index 0000000..b5f1752
--- /dev/null
@@ -0,0 +1,275 @@
+#################################################################
+#
+# CGI.CFG - Sample CGI Configuration File for Nagios 
+#
+# Last Modified: 05-05-2005
+#
+#################################################################
+
+
+# MAIN CONFIGURATION FILE
+# This tells the CGIs where to find your main configuration file.
+# The CGIs will read the main and host config files for any other
+# data they might need.
+
+main_config_file=/etc/nagios/nagios.cfg
+
+
+
+# PHYSICAL HTML PATH
+# This is the path where the HTML files for Nagios reside.  This
+# value is used to locate the logo images needed by the statusmap
+# and statuswrl CGIs.
+
+physical_html_path=/usr/share/nagios/share
+
+
+
+# URL HTML PATH
+# This is the path portion of the URL that corresponds to the
+# physical location of the Nagios HTML files (as defined above).
+# This value is used by the CGIs to locate the online documentation
+# and graphics.  If you access the Nagios pages with an URL like
+# http://www.myhost.com/nagios, this value should be '/nagios'
+# (without the quotes).
+
+url_html_path=/nagios
+
+
+
+# CONTEXT-SENSITIVE HELP
+# This option determines whether or not a context-sensitive
+# help icon will be displayed for most of the CGIs.
+# Values: 0 = disables context-sensitive help
+#         1 = enables context-sensitive help
+
+show_context_help=0
+
+
+
+# NAGIOS PROCESS CHECK COMMAND
+# This is the full path and filename of the program used to check
+# the status of the Nagios process.  It is used only by the CGIs
+# and is completely optional.  However, if you don't use it, you'll
+# see warning messages in the CGIs about the Nagios process
+# not running and you won't be able to execute any commands from
+# the web interface.  The program should follow the same rules
+# as plugins; the return codes are the same as for the plugins,
+# it should have timeout protection, it should output something
+# to STDIO, etc.
+#
+# Note: The command line for the check_nagios plugin below may
+# have to be tweaked a bit, as different versions of the plugin
+# use different command line arguments/syntaxes.
+
+nagios_check_command=/usr/lib/nagios/plugins/check_nagios /var/log/nagios/status.dat 5 '/usr/sbin/nagios'
+
+
+
+# AUTHENTICATION USAGE
+# This option controls whether or not the CGIs will use any 
+# authentication when displaying host and service information, as
+# well as committing commands to Nagios for processing.  
+#
+# Read the HTML documentation to learn how the authorization works!
+#
+# NOTE: It is a really *bad* idea to disable authorization, unless
+# you plan on removing the command CGI (cmd.cgi)!  Failure to do
+# so will leave you wide open to kiddies messing with Nagios and
+# possibly hitting you with a denial of service attack by filling up
+# your drive by continuously writing to your command file!
+#
+# Setting this value to 0 will cause the CGIs to *not* use
+# authentication (bad idea), while any other value will make them
+# use the authentication functions (the default).
+
+use_authentication=1
+
+
+
+# DEFAULT USER
+# Setting this variable will define a default user name that can
+# access pages without authentication.  This allows people within a
+# secure domain (i.e., behind a firewall) to see the current status
+# without authenticating.  You may want to use this to avoid basic
+# authentication if you are not using a sercure server since basic
+# authentication transmits passwords in the clear.
+#
+# Important:  Do not define a default username unless you are
+# running a secure web server and are sure that everyone who has
+# access to the CGIs has been authenticated in some manner!  If you
+# define this variable, anyone who has not authenticated to the web
+# server will inherit all rights you assign to this user!
+#default_user_name=guest
+
+
+
+# SYSTEM/PROCESS INFORMATION ACCESS
+# This option is a comma-delimited list of all usernames that
+# have access to viewing the Nagios process information as
+# provided by the Extended Information CGI (extinfo.cgi).  By
+# default, *no one* has access to this unless you choose to
+# not use authorization.  You may use an asterisk (*) to
+# authorize any user who has authenticated to the web server.
+
+#authorized_for_system_information=nagiosadmin,theboss,jdoe
+
+
+
+# CONFIGURATION INFORMATION ACCESS
+# This option is a comma-delimited list of all usernames that
+# can view ALL configuration information (hosts, commands, etc).
+# By default, users can only view configuration information
+# for the hosts and services they are contacts for. You may use
+# an asterisk (*) to authorize any user who has authenticated
+# to the web server.
+
+#authorized_for_configuration_information=nagiosadmin,jdoe
+
+
+
+# SYSTEM/PROCESS COMMAND ACCESS
+# This option is a comma-delimited list of all usernames that
+# can issue shutdown and restart commands to Nagios via the
+# command CGI (cmd.cgi).  Users in this list can also change
+# the program mode to active or standby. By default, *no one*
+# has access to this unless you choose to not use authorization.
+# You may use an asterisk (*) to authorize any user who has
+# authenticated to the web server.
+
+#authorized_for_system_commands=nagiosadmin
+
+
+
+# GLOBAL HOST/SERVICE VIEW ACCESS
+# These two options are comma-delimited lists of all usernames that
+# can view information for all hosts and services that are being
+# monitored.  By default, users can only view information
+# for hosts or services that they are contacts for (unless you
+# you choose to not use authorization). You may use an asterisk (*)
+# to authorize any user who has authenticated to the web server.
+
+
+authorized_for_all_services=thierry.parmentelat@sophia.inria.fr
+authorized_for_all_hosts=thierry.parmentelat@sophia.inria.fr
+
+
+
+# GLOBAL HOST/SERVICE COMMAND ACCESS
+# These two options are comma-delimited lists of all usernames that
+# can issue host or service related commands via the command
+# CGI (cmd.cgi) for all hosts and services that are being monitored. 
+# By default, users can only issue commands for hosts or services 
+# that they are contacts for (unless you you choose to not use 
+# authorization).  You may use an asterisk (*) to authorize any
+# user who has authenticated to the web server.
+
+#authorized_for_all_service_commands=nagiosadmin
+#authorized_for_all_host_commands=nagiosadmin
+
+
+
+
+# STATUSMAP BACKGROUND IMAGE
+# This option allows you to specify an image to be used as a 
+# background in the statusmap CGI.  It is assumed that the image
+# resides in the HTML images path (i.e. /usr/local/nagios/share/images).
+# This path is automatically determined by appending "/images"
+# to the path specified by the 'physical_html_path' directive.
+# Note:  The image file may be in GIF, PNG, JPEG, or GD2 format.
+# However, I recommend that you convert your image to GD2 format
+# (uncompressed), as this will cause less CPU load when the CGI
+# generates the image.
+
+#statusmap_background_image=smbackground.gd2
+
+
+
+# DEFAULT STATUSMAP LAYOUT METHOD
+# This option allows you to specify the default layout method
+# the statusmap CGI should use for drawing hosts.  If you do
+# not use this option, the default is to use user-defined
+# coordinates.  Valid options are as follows:
+#      0 = User-defined coordinates
+#      1 = Depth layers
+#       2 = Collapsed tree
+#       3 = Balanced tree
+#       4 = Circular
+#       5 = Circular (Marked Up)
+
+default_statusmap_layout=5
+
+
+
+# DEFAULT STATUSWRL LAYOUT METHOD
+# This option allows you to specify the default layout method
+# the statuswrl (VRML) CGI should use for drawing hosts.  If you
+# do not use this option, the default is to use user-defined
+# coordinates.  Valid options are as follows:
+#      0 = User-defined coordinates
+#       2 = Collapsed tree
+#       3 = Balanced tree
+#       4 = Circular
+
+default_statuswrl_layout=4
+
+
+
+# STATUSWRL INCLUDE
+# This option allows you to include your own objects in the 
+# generated VRML world.  It is assumed that the file
+# resides in the HTML path (i.e. /usr/local/nagios/share).
+
+#statuswrl_include=myworld.wrl
+
+
+
+# PING SYNTAX
+# This option determines what syntax should be used when
+# attempting to ping a host from the WAP interface (using
+# the statuswml CGI.  You must include the full path to
+# the ping binary, along with all required options.  The
+# $HOSTADDRESS$ macro is substituted with the address of
+# the host before the command is executed.
+# Please note that the syntax for the ping binary is
+# notorious for being different on virtually ever *NIX
+# OS and distribution, so you may have to tweak this to
+# work on your system.
+
+ping_syntax=/bin/ping -n -U -c 5 $HOSTADDRESS$
+
+
+
+# REFRESH RATE
+# This option allows you to specify the refresh rate in seconds
+# of various CGIs (status, statusmap, extinfo, and outages).  
+
+refresh_rate=90
+
+
+
+# SOUND OPTIONS
+# These options allow you to specify an optional audio file
+# that should be played in your browser window when there are
+# problems on the network.  The audio files are used only in
+# the status CGI.  Only the sound for the most critical problem
+# will be played.  Order of importance (higher to lower) is as
+# follows: unreachable hosts, down hosts, critical services,
+# warning services, and unknown services. If there are no
+# visible problems, the sound file optionally specified by
+# 'normal_sound' variable will be played.
+#
+#
+# <varname>=<sound_file>
+#
+# Note: All audio files must be placed in the /media subdirectory
+# under the HTML path (i.e. /usr/local/nagios/share/media/).
+
+#host_unreachable_sound=hostdown.wav
+#host_down_sound=hostdown.wav
+#service_critical_sound=critical.wav
+#service_warning_sound=warning.wav
+#service_unknown_sound=warning.wav
+#normal_sound=noproblem.wav
+
diff --git a/nagios/configurator/comon_query.py b/nagios/configurator/comon_query.py
new file mode 100755 (executable)
index 0000000..9aa2685
--- /dev/null
@@ -0,0 +1,188 @@
+#!/usr/bin/env python
+
+#
+# This module checks for a planetlab node by
+# (*) connecting to the comon central query interface
+# (*) retrieving the latest info for a given node
+#
+
+import sys
+import socket
+import re
+import string
+import urllib2
+
+import nagios
+
+# default server
+SERVER='summer.cs.princeton.edu'
+
+NodeUnknownException="NodeUnknownByComon"
+
+####################
+def check (node,server=None):
+
+    if (server == None):
+        server = SERVER
+
+    try:
+    
+        # compute node IP number
+        node_address = compute_address (node)
+#        print 'int address',node_address
+        # build URL, connect and return attributes dict
+        node_dict = query_node (server,node_address)
+        for key in node_dict.keys():
+            print key,node_dict[key]
+        # interpret
+        return  interpret (node_dict)
+
+    except NodeUnknownException:
+        return nagios.UNKNOWN
+    except Exception,e:
+        print "comon_query.check got exception",e
+        return nagios.UNKNOWN
+
+##########
+re_dec="([0-9]{1,3})"
+re_ipsep="\."
+re_ip=(re_dec+re_ipsep)*3+re_dec
+ma_ip = re.compile (re_ip)
+
+def compute_address (nodename):
+    ip=socket.gethostbyname(nodename)
+    ints=map(int,ma_ip.match(ip).groups())
+    res=ints[0]
+    for i in range(1,4):
+        res = (res*256)+ints[i]
+    return res
+
+##########
+URL_FORMAT="http://%s/status/tabulator.cgi"
+ARGS_FORMAT="table=table_nodeviewshort&select='%s'"
+FILTER_FORMAT="address==%d"
+CSV_FORMAT="&format=formatcsv"
+
+def filter_address (address):
+    return FILTER_FORMAT%address
+def filter_node (nodename):
+    return filter_address(compute_address(nodename))
+
+def full_url (server, filter):
+    return (URL_FORMAT%server
+            + '?'
+            + ARGS_FORMAT%filter)
+
+def full_url_csv (server,filter):
+    return full_url(server,filter)+CSV_FORMAT
+
+
+# mention field here means we'll parse it and keep it
+# see store_dict below 
+FIELDS_FOCUS={
+    'resptime': 'float',
+    'sshstatus':'int',
+    'bootstate':'string',
+    }
+
+NOTHING_MATCHED='nothing matched select statement'
+##########
+def query_node (server,address):
+    filter=filter_address(address)
+    full_url=full_url_csv(server,filter)
+    req = urllib2.urlopen(full_url)
+    # let's parse this manually
+    headers=map(string.strip,req.readline().split(','))
+    # handle the case where the node is unknown to comon
+    values=req.readline()
+    if values.find(NOTHING_MATCHED) != -1:
+        raise NodeUnknownException
+
+    values=values.split(',')
+
+    print 'h',headers
+    print 'v', values
+    
+    dict={}
+#    store_dict=lambda key,val: dict[key]=val
+#    -> SyntaxError: can't assign to lambda
+    def store_dict (key,val):
+        if FIELDS_FOCUS.has_key(key):
+            format = FIELDS_FOCUS[key]
+            if format == 'float':
+                dict[key]=float(val)
+            elif format == 'int':
+                dict[key]=int(val)
+            elif format == 'string':
+                dict[key]=string.strip(val)
+    map (store_dict, headers, values)
+
+    return dict
+
+##########
+# function for decomposing a number along units
+# tuple [n] must be a multiple of tuple[n+1]
+# e.g.
+#   1223456, (10000, 500, 10)  -> (122, 68, 5)
+# coz 1223456 = 122*10000 + 68*500 + 5*10 + 6 
+def split_number (n,tuple):
+    result=()
+    for i in range(0,len(tuple)):
+        base=tuple[i]
+        result+=(n/base,)
+        n=n%base
+    return result
+
+###
+MINUTE=60
+HOUR=60*MINUTE
+DAY=HOUR*24
+WEEK=DAY*7
+MONTH=DAY*30
+
+# from a delay in seconds, returns a human-readable string
+def seconds_printable (seconds):
+    month,week,day,hour,minute = split_number(seconds,
+                                              (MONTH,WEEK,DAY,HOUR,MINUTE))
+    if month != 0:
+        return "%d month(s), %d weeks, %d day(s)"%(month,week,day)
+    elif week !=0:
+        return "%d weeks, %d day(s), %d hour(s)"%(week,day,hour)
+    elif day != 0:
+        return "%d day(s), %d hour(s)"%(day,hour)
+    elif hour != 0:
+        return "%d hour(s), %d minute(s)"%(hour,minute)
+    else:
+        return "%d minute(s)"%(minute)
+
+##########
+def interpret (dict):
+    # check sshstatus is null
+    sshstatus=dict['sshstatus']
+    if sshstatus != 0:
+        print 'No response to comon/ssh for %s'%seconds_printable(sshstatus)
+        if sshstatus >= 10*MINUTE:
+            return nagios.KO
+        else:
+            return nagios.WARNING
+    else:
+        # let's focus on resptime
+        resptime = dict['resptime']
+        print "Response time as measured by comon = %.2f s"%resptime
+        if resptime >= 10.0:
+            return nagios.KO
+        elif resptime >= 5.0:
+            return nagios.WARNING
+        else:
+            return nagios.OK
+
+#################### quick test
+def usage():
+    print "Usage comon_query.py node"
+    sys.exit(1)
+
+if __name__=='__main__':
+    if len(sys.argv) != 2:
+        usage()
+    print 'comon_query.check would return %d'%check(sys.argv[1])
+#     print 'get >%s<',seconds_printable(int(sys.argv[1]))
diff --git a/nagios/configurator/configurator.py b/nagios/configurator/configurator.py
new file mode 100755 (executable)
index 0000000..e9f8090
--- /dev/null
@@ -0,0 +1,111 @@
+#!/usr/bin/env python
+
+# WARNING - you might need to set your locale before you can run this script
+# e.g.
+# export LANG=en_US.UTF-8
+# nagios.py ...
+
+import sys 
+import getopt
+
+from NagiosConfig import NagiosConfig
+
+SERVER="www.planet-lab.org"
+DIRNAME="/etc/nagios"
+
+options='h:o:Os:d:nNv'
+
+usage_string="""Usage : %s [options] plc-id plc-passwd role
+Outputs a nagios config for watching a given set of sites
+Also writes a static HTML page for bookmarking site-centric queries to comon
+Options:
+  -h plc-hostname       To provide an alternate plc hostname
+                        (defaults to %s)
+  -o e-mail             If you provide an e-mail address, all notifications
+                        will be sent there. Otherwise, you'll need admin role
+                        so that we can determine the respective PI's e-mails
+  -O                    same as -e with the plc-id as dest. e-mail
+  -s site-file          You can provide a list of sites in a separate file
+                        expected format is one line per site, site_id first
+                        the default is to list all sites
+  -d dirname            To specify an alternate output dir
+                        (defaults to %s)
+  -n                    Does not generate the nagios config
+  -N                    Does not generate the HTML page
+  -v                   Runs in verbose mode
+"""%(sys.argv[0],SERVER,DIRNAME)
+
+def usage ():
+    print usage_string
+    sys.exit(1)
+
+
+def main ():
+    command = sys.argv[0]
+    argv = sys.argv[1:]
+
+    try:
+        opts,args = getopt.getopt(argv, options)
+    except getopt.GetoptError:
+        print "Unknown option"
+        usage()
+
+    plc_server=SERVER
+    output_mail=None
+    opt_same_email=False
+    site_file=None
+    dirname=DIRNAME
+    opt_nagios = True
+    opt_html = True
+    opt_verbose = False
+    
+    for o,a in opts:
+        if o in ['-h']:
+            plc_server = a
+        elif o in ['-o']:
+            output_mail = a
+        elif o in ['-O']:
+            opt_same_email = True
+        elif o in ['-s']:
+            site_file = a
+        elif o in ['-d']:
+            dirname = a
+        elif o in ['-n']:
+            opt_nagios = False
+        elif o in ['-N']:
+            opt_html = False
+       elif o in ['-v']:
+           opt_verbose = True
+        else:
+            print "Unknown option",o
+            usage()
+
+    if not len(args) == 3:
+        usage()
+
+    (plc_id,passwd,role) = args
+    if opt_same_email:
+        output_mail=plc_id
+
+#    print plc_server,output_mail,dirname,opt_nagios,opt_html
+#    print plc_id,passwd,role,site_file
+
+    print "Connecting to %s and gathering data"%plc_server
+    config = NagiosConfig (plc_server,plc_id,passwd,role)
+    if opt_verbose:
+       config.set_verbose()
+    config.GatherData (output_mail,site_file)
+
+    if opt_nagios:
+        print "Creating nagios config in %s"%dirname
+        config.WriteNagiosConfig (dirname)
+
+    if opt_html:
+        html_page = "%s/comon.html"%dirname
+        config.WriteComonLinks (html_page)
+
+    
+####################
+if __name__ == "__main__":
+    main ()
+
diff --git a/nagios/configurator/generic.cfg b/nagios/configurator/generic.cfg
new file mode 100644 (file)
index 0000000..3788228
--- /dev/null
@@ -0,0 +1,212 @@
+###############################################################################
+# MINIMAL.CFG
+#
+# MINIMALISTIC OBJECT CONFIG FILE (Template-Based Object File Format)
+#
+# Last Modified: 05-30-2006
+#
+#
+# NOTE: This config file is intended to be used to test a Nagios installation
+#       that has been compiled with support for the template-based object
+#       configuration files.
+#
+#       This config file is intended to servce as an *extremely* simple 
+#       example of how you can create your object configuration file(s).
+#       If you're interested in more complex object configuration files for
+#       Nagios, look in the sample-config/template-object/ subdirectory of
+#       the distribution.
+#
+###############################################################################
+
+
+
+###############################################################################
+###############################################################################
+#
+# TIME PERIODS
+#
+###############################################################################
+###############################################################################
+
+# This defines a timeperiod where all times are valid for checks, 
+# notifications, etc.  The classic "24x7" support nightmare. :-)
+
+define timeperiod{
+        timeperiod_name                        24x7
+        alias                          24 Hours A Day, 7 Days A Week
+        sunday                         00:00-24:00
+        monday                         00:00-24:00
+        tuesday                        00:00-24:00
+        wednesday                      00:00-24:00
+        thursday                       00:00-24:00
+        friday                         00:00-24:00
+        saturday                       00:00-24:00
+        }
+
+
+################################################################################
+#
+# SERVICE CHECK COMMANDS
+#
+################################################################################
+
+# 'check_udp' command definition
+define command{
+       command_name    check_udp
+       command_line    $USER1$/check_udp -H $HOSTADDRESS$ -p $ARG1$
+       }
+
+define command{
+       command_name    check_ssh
+       command_line    $USER1$/check_ssh $HOSTADDRESS$
+       }
+
+define command{
+       command_name    check_ssh_root
+       command_line    $USER1$/check_by_ssh -H $HOSTADDRESS$ -l root -i /etc/nagios/root_ssh_key.rsa -C date
+       }
+
+define command{
+       command_name    check_ssh_pl_conf
+       command_line    $USER1$/check_by_ssh -H $HOSTADDRESS$ -l root -i /etc/nagios/root_ssh_key.rsa -C "server pl_conf status 2>/dev/null"
+       }
+
+define command{
+       command_name    check_planetlab
+       command_line    $USER1$/check_planetlab.py -t 3 $HOSTADDRESS$ 
+       }
+
+################################################################################
+#
+# HOST CHECK COMMAND
+#
+################################################################################
+
+# This command checks to see if a host is "alive" by pinging it
+# The check must result in a 100% packet loss or 5 second (5000ms) round trip 
+# average time to produce a critical error.
+# Note: Only one ICMP echo packet is sent (determined by the '-p 1' argument)
+
+# 'check-host-alive' command definition
+define command{
+        command_name    check-host-alive
+        command_line    $USER1$/check_ping -H $HOSTADDRESS$ -w 3000.0,40% -c 5000.0,80% -p 1
+        }
+
+###############################################################################
+###############################################################################
+#
+# HOSTS
+#
+###############################################################################
+###############################################################################
+
+# Generic host definition template - This is NOT a real host, just a template!
+
+define host{
+        name                            generic-host    ; The name of this host template
+        notifications_enabled           1       ; Host notifications are enabled
+        event_handler_enabled           1       ; Host event handler is enabled
+        flap_detection_enabled          1       ; Flap detection is enabled
+        failure_prediction_enabled      1       ; Failure prediction is enabled
+        process_perf_data               1       ; Process performance data
+        retain_status_information       1       ; Retain status information across program restarts
+        retain_nonstatus_information    1       ; Retain non-status information across program restarts
+        check_command                  check-host-alive
+        max_check_attempts             10
+        check_period                   24x7
+        notification_interval          1440
+        notification_period            24x7
+        notification_options           d,r
+        register                        0       ; DONT REGISTER THIS DEFINITION - ITS NOT A REAL HOST, JUST A TEMPLATE!
+        }
+
+# actual hosts to be defined by python in planetlab.cfg
+
+###############################################################################
+###############################################################################
+#
+# SERVICES
+#
+###############################################################################
+###############################################################################
+
+# Generic service definition template - This is NOT a real service, just a template!
+
+define service{
+        name                            generic-service ; The 'name' of this service template
+        active_checks_enabled           1       ; Active service checks are enabled
+        passive_checks_enabled          1       ; Passive service checks are enabled/accepted
+        parallelize_check               1       ; Active service checks should be parallelized (disabling this can lead to major performance problems)
+        obsess_over_service             1       ; We should obsess over this service (if necessary)
+        check_freshness                 0       ; Default is to NOT check service 'freshness'
+        notifications_enabled           1       ; Service notifications are enabled
+        event_handler_enabled           1       ; Service event handler is enabled
+        flap_detection_enabled          1       ; Flap detection is enabled
+        failure_prediction_enabled      1       ; Failure prediction is enabled
+        process_perf_data               1       ; Process performance data
+        retain_status_information       1       ; Retain status information across program restarts
+        retain_nonstatus_information    1       ; Retain non-status information across program restarts
+        register                        0       ; DONT REGISTER THIS DEFINITION - ITS NOT A REAL SERVICE, JUST A TEMPLATE!
+        is_volatile                     0
+        check_period                    24x7
+        max_check_attempts              2
+        normal_check_interval           240    ; every 2 hours is OK
+        retry_check_interval            5
+### 
+       notification_options            c,r
+        notification_interval           1440
+        notification_period             24x7
+        }
+
+
+### ping tunings
+# warning  is set to 2 seconds, 40% packet loss
+# critical is set to 5 seconds, 80% packet loss
+### We DONT register this service because it's basically what nagios reverts to
+# if the others services turn out to be not responding
+define service{
+       use                             generic-service
+       name                            generic-ping
+        service_description             ping
+#      check_command                   check_ping!100.0,20%!500.0,60%
+       check_command                   check_ping!2000.0,40%!5000.0,80%
+       register                        0
+       }
+
+
+define service{
+       use                             generic-service
+       name                            generic-ssh
+        service_description             ssh server
+       check_command                   check_ssh
+       register                        0
+       }
+
+define service{
+       use                             generic-service
+       name                            generic-ssh-root
+        service_description             ssh root
+       check_command                   check_ssh_root
+       register                        0
+       }
+
+define service{
+       use                             generic-service
+       name                            generic-ssh-pl_conf
+        service_description             pl_conf vserver
+       check_command                   check_ssh_pl_conf
+       register                        0
+       }
+
+define service{
+       use                             generic-service
+       name                            generic-planetlab
+       service_description             comon
+       check_command                   check_planetlab
+       register                        0
+       }
+
+# actual services to be defined by python in planetlab.cfg
+
+# EOF
diff --git a/nagios/configurator/makeHTML.py b/nagios/configurator/makeHTML.py
new file mode 100644 (file)
index 0000000..54e0623
--- /dev/null
@@ -0,0 +1,590 @@
+#makeHTML.py version 0.8 May 1, 2005 Jerry Stratton
+#
+#part(code="tag" (defaults to paragraph), content="text" style="css style name", id="css id", attributes={named array of attributes for tag}
+#      addAttribute(attributename="name for tag attribute", attributevalue="value for tag attribute")
+#      addPart(code, content, style, id, attributes): adds at end
+#      addPiece(thePart=another part object or "content text")
+#      addPieces(pices=a list of part objects or content texts)
+#      insertPart(code, content, style, id, attributes): inserts at start
+#      insertPiece(thePart)
+#      make(tab="initial tabs")
+#      makePart(code, content, style, id, attributes): returns a part object
+#      __len__: parts support the len() function; return number of pieces directly contained
+#snippet(code (defaults to "em"), content, posttext="text that comes directly after tag", pretext="text that comes directly before tag", style, id, attributes)
+#
+#head(title="text for title of page")
+#body(title="text for main headline", style, id, attributes)
+#page(pieces, style, id, attributes)
+#styleSheet(sheet="url of stylesheet", media="relevance of style sheet")
+#
+#headline(content="text content" (required), level="numerical level", style, id, attributes)
+#
+#table(rows=list of data for rows, style, thStyle="css style for table headers", tdStyle="css style for table cells",
+#              trStyle="css style for table rows", tdBlankStyle="css style for blank cells", firstRowHeader=1--if first row is a header row,
+#              firstColumnHeader=1--if first column is a header column, id, attributes)
+#      addRow(rowList=[list of cells or data], celltype="th or td", cellclass="css style of cells", attributes, style)
+#      addRows(rows=[list of list of cells or data], celltype, cellclass, attributes)
+#      columnCount()
+#tableByColumn(columns=[list of columns], style, thStyle, tdStyle, trStyle, tdBlankStyle, firstRowHeader, firstColumnHeader, id, attributes)
+#      addColumn(columnList=[list of column data or cells], celltype, cellclass, attributes)
+#      addColumns(columns=[list of list of columns or column data], celltype, cellclass, attributes)   
+#tableColumn(column=[list of data or cells for column], celltype, cellclass, firstRowHeader, thStyle, tdBlankStyle, attributes)
+#      addCell(cell="cell or cell content", celltype, cellclass, id, attributes)
+#      addCells(column="list of cells or cell contents", celltype, cellclass, attributes)
+#tableRow(celltype, row=[list of cells or cell data], style, cellclass, firstColumnHeader, thStyle, id, attributes)
+#      addCell(cell="cell or cell content", celltype, cellclass, colspan="numerical span of cell vertically", rowspan="numerical span of cell horizontally")
+#      addCells(cells=[list of cells or cell content])
+#      columnCount()
+#
+#linkedList(links=[list of items of the form [url, name]], outer="outer html tag", inner="inner html tag", style="outer css style",
+#              iclass="inner css style", id, attributes)
+#      addLink(link=[url, name])
+#      addLinks(links)
+#simpleList(items=[list of text items], outer, inner, defaultname="text for marking default entry", default="text of default entry",
+#              style, iclass, id, attributes)
+#      addItem(item="text of item")
+#      addItems(items)
+#
+#image(src="url of image", alt="alternate text for image", align="alignment", style, id, attributes)
+#link(content, url, posttext, pretext, style, id, attributes)
+#
+#form(submitText="text of submit button", pieces, method="submit method", action="form action", submitName="name for submit button", submitAction="javascript for submission"
+#              headline="headline text", headlineLevel (defaults to 2), style, attributes, id)
+#input(type="type of form input", name="name for input", value="default value for input", size="size for input", maxlength="maximum characters accepted",
+#              style, id, attributes)
+#select(name, items, default, style, iclass, id, attributes
+#textinput(name, text, value, size, maxlength, style, id, attributes, type, tableRow=true if this should be a tr row, otherwise it is a paragraph)
+
+#basic parts
+class part:
+       def __init__(self, code="p", content=None, style=None, id=None, attributes=None):
+               self.style = style
+               self.id=id
+               self.pieces = []
+               self.code = code
+               if attributes == None:
+                       self.attributes = {}
+               else:
+                       self.attributes = attributes
+               if isinstance(content, list):
+                       self.addPieces(content)
+               elif content != None:
+                       self.addPiece(content)
+       
+       def __len__(self):
+               return len(self.pieces)
+
+       def addAttribute(self, attributename, attributevalue):
+               self.attributes[attributename] = attributevalue
+
+       def addPart(self, code='p', content=None, style=None, id=None, attributes=None):
+               newPart = self.makePart(code, content, style, id, attributes)
+               self.addPiece(newPart)
+
+       def addPiece(self, thePart):
+               self.pieces.append(thePart)
+       
+       def addPieces(self, theParts):
+               if theParts != None:
+                       if isinstance(theParts, list):
+                               for part in theParts:
+                                       self.addPiece(part)
+                       else:
+                               self.addPiece(theParts)
+       
+       def insertPart(self, code='p', content=None, style=None, id=None, attributes=None):
+               newPart = self.makePart(code, content, style, id, attributes)
+               self.insertPiece(newPart)
+               
+       def insertPiece(self, thePart):
+               self.pieces.insert(0, thePart)
+
+       def make(self, tab="\t"):
+               startHTML = '<' + self.code
+               
+               if (self.attributes):
+                       for attribute in self.attributes:
+                               content = self.attributes[attribute]
+                               if content == None:
+                                       startHTML += ' ' + attribute
+                               else:
+                                       startHTML += ' ' + attribute + '="' + str(content) + '"'
+       
+               if (self.style):
+                       startHTML += ' class="' + self.style + '"'
+               
+               if (self.id):
+                       startHTML += ' id="' + self.id + '"'
+
+               if self.pieces:
+                       startHTML += '>'
+                       
+                       partItems = [startHTML]
+                       
+                       if len(self.pieces) > 1:
+                               sep = "\n" + tab
+                               finalSep = sep[:-1]
+                               newtab = tab + "\t"
+                       else:
+                               newtab = tab
+                               sep = ""
+                               finalSep = ""
+                       
+                       for piece in self.pieces:
+                               if isinstance(piece, str):
+                                       partItems.append(piece)
+                               elif isinstance(piece, int) or isinstance(piece, float):
+                                       partItems.append(str(piece))
+                               elif piece == None:
+                                       partItems.append("")
+                               else:
+                                       partItems.append(piece.make(newtab))
+               
+                       code = sep.join(partItems)
+                       code += finalSep + '</' + self.code + '>'
+                       return code
+                       
+               else:
+                       startHTML += ' />'
+                       return startHTML
+       
+       def makePart(self, code='p', content=None, style=None, id=None, attributes=None):
+               if content == None:
+                       newPart = part(code)
+               else:
+                       newPart = part(code, content, style, id, attributes)
+
+               return newPart
+
+class snippet(part):
+       def __init__(self, code="em", content=None, posttext=None, pretext=None, style=None, id=None, attributes=None):
+               part.__init__(self, code, content, style, id, attributes)
+               self.posttext = posttext
+               self.pretext = pretext
+       
+       def make(self, tab=''):
+               snippets = []
+
+               if self.pretext:
+                       snippets.append(self.pretext)
+               
+               snippets.append(part.make(self, tab))
+               
+               if self.posttext:
+                       snippets.append(self.posttext)
+
+               return "".join(snippets)
+
+#common body parts
+
+class head(part):
+       def __init__(self, title=None):
+               part.__init__(self, code="head")
+               if title:
+                       self.addPiece(part("title", title))
+
+class body(part):
+       def __init__(self, title=None, style=None, id=None, attributes=None):
+               part.__init__(self, code="body", style=style, id=id, attributes=attributes)
+               if title:
+                       self.addPiece(headline(title, 1))
+
+class page(part):
+       def __init__(self, pieces=None, style=None, id=None, attributes=None):
+               part.__init__(self, code="html", style=style, id=id, attributes=attributes)
+               if isinstance(pieces, list):
+                       self.addPieces(pieces)
+               elif isinstance(pieces, part):
+                       self.addPiece(pieces)
+
+       def make(self, tab=''):
+               pageContent = part.make(self)
+               
+               print 'Content-type: text/html'
+               print ''
+
+               print pageContent
+
+class styleSheet(part):
+       def __init__(self, sheet, media='all'):
+               attributes = {}
+               attributes['rel'] = "StyleSheet"
+               attributes['href'] = sheet + '.css'
+               attributes['type'] = "text/css"
+               attributes['media'] = media
+               part.__init__(self, code="link", attributes=attributes)
+
+
+#paragraph level parts
+class headline(part):
+       def __init__(self, content, level=2, style=None, id=None, attributes=None):
+               code = "h"+str(level)
+               part.__init__(self, content=content, style=style, code=code, id=id, attributes=attributes)
+
+
+
+#tables
+class table(part):
+       def __init__(self, rows=None, style=None, thStyle=None, tdStyle=None, trStyle=None, tdBlankStyle=None, firstRowHeader=None, firstColumnHeader=None, id=None, attributes=None):
+               part.__init__(self, code="table", style=style, id=id, attributes=attributes)
+               self.rowclass=trStyle
+               self.cellclass=tdStyle
+               self.cellheaderclass=thStyle
+               self.cellblankclass=tdBlankStyle
+               self.firstRowHeader=firstRowHeader
+               self.firstColumnHeader=firstColumnHeader
+               if rows:
+                       self.addRows(rows)
+
+       def addRow(self, rowList, celltype=None, cellclass=None, attributes=None, style=None):
+               if cellclass==None:
+                       if self.firstRowHeader and len(self.pieces) == 0:
+                               celltype="th"
+                               cellclass=self.cellheaderclass
+                       else:
+                               cellclass=self.cellclass
+
+               if style==None:
+                       style = self.rowclass
+
+               newRow = tableRow(celltype, rowList, style, cellclass, self.firstColumnHeader, self.cellheaderclass, attributes)
+               self.addPiece(newRow)
+       
+       def addRows(self, rows, cellclass=None, celltype=None, attributes=None):
+               for row in rows:
+                       self.addRow(row)
+
+       def columnCount(self):
+               maxCount = 0
+               for row in self.pieces:
+                       if isinstance(row, tableRow):
+                               colCount = row.columnCount()
+                               maxCount = max(maxCount, colCount)
+               
+               return maxCount
+
+class tableByColumn(table):
+       def __init__(self, columns=None, style=None, thStyle=None, tdStyle=None, trStyle=None, tdBlankStyle=None, firstRowHeader=None, firstColumnHeader=None, id=None, attributes=None):
+               table.__init__(self, [], style, thStyle, tdStyle, trStyle, tdBlankStyle, firstRowHeader, firstColumnHeader, id, attributes)
+               self.columns = []
+               if columns:
+                       self.addColumns(columns)
+
+       def addColumn(self, columnList, celltype=None, cellclass=None, attributes=None):
+               if cellclass==None:
+                       if celltype == "th" or (self.firstColumnHeader and len(self.columns) == 0):
+                               celltype="th"
+                               cellclass=self.cellheaderclass
+                       else:
+                               cellclass=self.cellclass
+
+               newColumn = tableColumn(columnList, celltype, cellclass, self.firstRowHeader, self.cellheaderclass, self.cellblankclass, attributes)
+               self.columns.append(newColumn)
+
+       def addColumns(self, columns, celltype=None, cellclass=None, attributes=None):
+               for column in columns:
+                       self.addColumn(column)
+
+       def addPiece(self, thePart):
+               if isinstance(thePart, tableColumn):
+                       self.columns.append(thePart)
+               else:
+                       part.addPiece(self, thePart)
+
+       def make(self, tabs):
+               rowCount = 0
+               for column in self.columns:
+                       rowCount = max(rowCount, len(column.pieces))
+
+               if rowCount:
+                       for cRow in range(rowCount):
+                               row = tableRow()
+                               for column in self.columns:
+                                       if cRow < len(column.pieces):
+                                               cell = column.pieces[cRow]
+                                       else:
+                                               cell = part("td")
+                                       row.addPiece(cell)
+                               
+                               self.addPiece(row)
+
+               myPart = part.make(self, tabs)
+               return myPart
+
+
+class tableColumn(part):
+       def __init__(self, column=None, celltype="td", cellclass=None, firstRowHeader=None, thStyle=None, tdBlankStyle=None, attributes=None):
+               part.__init__(self, "column", style=cellclass, attributes=attributes)
+               if celltype==None:
+                       self.celltype = "td"
+               else:
+                       self.celltype=celltype
+               
+               self.firstRowHeader=firstRowHeader
+               self.cellheaderclass=thStyle
+               self.cellblankclass=tdBlankStyle
+               
+               if column:
+                       self.addCells(column)
+
+       def addCell(self, cell=None, celltype=None, cellclass=None, id=None, attributes=None):
+               if self.cellblankclass and (cell==None or cell==""):
+                       celltype="td"
+                       cellclass = self.cellblankclass
+               elif self.firstRowHeader and len(self.pieces) == 0:
+                       celltype = "th"
+                       cellclass = self.cellheaderclass
+               else:
+                       if celltype == None:
+                               celltype = self.celltype
+                       if cellclass == None:
+                               cellclass = self.style
+               if cell == None:
+                       cell = ""
+               
+               tableCell = part(code=celltype, style=cellclass, content=cell, id=id, attributes=attributes)
+               self.addPiece(tableCell)
+
+       def addCells(self, column, celltype=None, cellclass=None,  attributes=None):
+               for cell in column:
+                       self.addCell(cell, celltype, cellclass, attributes=attributes)
+       
+       def make(self):
+               print "Problem: columns should never be requested to make themselves."
+               print "Columns are not true html structures, and should only be added to tableByColumn parts."
+
+
+class tableRow(part):
+       def __init__(self, celltype="td", row=None, style=None, cellclass=None, firstColumnHeader=None, thStyle=None, id=None, attributes=None):
+               part.__init__(self, "tr", style=style, id=id, attributes=attributes)
+               self.celltype=celltype
+               self.cellclass=cellclass
+               self.firstColumnHeader=firstColumnHeader
+               self.cellheaderclass=thStyle
+               if row:
+                       self.addCells(row)
+               
+       def addCell(self, cell, celltype=None, cellclass=None, colspan=None, rowspan=None):
+               if self.firstColumnHeader and len(self.pieces) == 0:
+                       celltype="th"
+                       cellclass=self.cellheaderclass
+               elif celltype == None:
+                       celltype = self.celltype
+               
+               if celltype == None:
+                       celltype = "td"
+               
+               if cellclass==None:
+                       cellclass=self.cellclass
+               
+               attributes = {}
+               if colspan:
+                       attributes['colspan'] = colspan
+               if rowspan:
+                       attributes['rowspan'] = rowspan
+               
+               if cell == None:
+                       cell = ""
+               
+               self.addPiece(part(code=celltype, style=cellclass, content=cell, attributes=attributes))
+
+       def addCells(self, cells):
+               for cell in cells:
+                       self.addCell(cell)
+
+       def columnCount(self):
+               return len(self.pieces)
+
+
+#lists
+
+class linkedList(part):
+       def __init__(self, links=None, outer = "ul", inner="li", style=None, iclass=None, id=None, attributes=None):
+               part.__init__(self, code=outer, style=style, id=id, attributes=attributes)
+               self.innercode = inner
+               self.innerstyle = iclass
+               if isinstance(links, list):
+                       self.addLinks(links)
+
+       def addLink(self, link):
+               [url, name] = link
+               link = part("a", attributes={"href": url}, content=name)
+               listitem = part(self.innercode, content=link, style=self.innerstyle)
+               self.pieces.append(listitem)
+       
+       def addLinks(self, links):
+               theLinks = []
+               for link in links:
+                       self.addLink(link)
+
+class simpleList(part):
+       def __init__(self, items=None, outer = "ul", inner="li", defaultname=None, default=None, style=None, iclass=None, id=None, attributes=None):
+               part.__init__(self, code=outer, style=style, id=id, attributes=attributes)
+               self.innercode = inner
+               self.innerstyle = iclass
+               self.defaultname = defaultname
+               self.default=default
+               if isinstance(items, list):
+                       self.addItems(items)
+                       
+       def addItem(self, item):
+               attributes = {}
+               if self.defaultname:
+                       if item == self.default:
+                               attributes[self.defaultname] = None
+       
+               theItem = part(self.innercode, content=item, style=self.innerstyle, attributes=attributes)
+               self.pieces.append(theItem)
+
+       def addItems(self, items):
+               theList = []
+               for item in items:
+                       self.addItem(item)
+
+#individual pieces
+
+class image(part):
+       def __init__(self, src, alt=None, align=None, style=None, id=None, attributes=None):
+               if attributes == None:
+                       attributes = {}
+               attributes['src'] = src
+               if alt:
+                       attributes['alt'] = alt
+               if align:
+                       attributes['align'] = align
+
+               part.__init__(self, 'img', style=style, id=id, attributes=attributes)
+
+class link(snippet):
+       def __init__(self, content=None, url=None, posttext=None, pretext=None, style=None, id=None, attributes=None):
+               if url != None:
+                       if attributes == None:
+                               attributes = {}
+                       attributes['href'] = url
+
+               snippet.__init__(self, "a", content, posttext, pretext, style, id, attributes)
+               
+
+#forms
+
+class form(part):
+       def __init__(self, submitText="Submit", pieces=None, method="get", action='./', submitName = None, submitAction=None, headline=None, headlineLevel = 2, style=None, attributes=None):
+               self.submitText = submitText
+               self.submitName = submitName
+               self.making = None
+               if attributes == None:
+                       attributes = {}
+               if action != None:
+                       attributes['action'] = action
+               if method != None:
+                       attributes['method'] = method
+               if submitAction != None:
+                       attributes['onSubmit'] = '"' + submitaction + '"'
+               
+               part.__init__(self, 'form', style=style, attributes=attributes)
+               
+               if headline != None:
+                       headcode = "h" + headlineLevel
+                       self.addPart(headcode, content=headline)
+               
+               self.addPieces(pieces)
+
+
+       def make(self, tab=''):
+               if self.making:
+                       return part.make(self, tab)
+               else:
+                       if self.submitName:
+                               submitButton = input("submit", value=self.submitText, name=self.submitName)
+                       else:
+                               submitButton = input("submit", value=self.submitText)
+                       trueForm = self
+                       trueForm.making = 1
+                       trueForm.addPiece(submitButton)
+                       pageContent = trueForm.make(tab)
+                       return pageContent
+
+class input(part):
+       def __init__(self, type, name=None, value=None, size=None, maxlength=None, style=None, id=None, attributes=None):
+               if attributes == None:
+                       attributes = {}
+
+               attributes['type'] = type
+               if name:
+                       attributes['name'] = name
+               if value!=None:
+                       attributes['value'] = value
+               if size:
+                       attributes['size'] = size
+               if maxlength:
+                       attributes['maxlength'] = maxlength
+
+               part.__init__(self, 'input', style=style, id=id, attributes=attributes)
+
+class select(simpleList):
+       def __init__(self, name, items=None, default=None, style=None, iclass=None, id=None, attributes=None):
+               if attributes==None:
+                       attributes={}
+               attributes['name'] = name
+
+               simpleList.__init__(self, items, outer='select', inner='option', defaultname='selected', default=default, style=style, iclass=iclass, id=id, attributes=attributes)
+               
+class textinput(part):
+       def __init__(self, name=None, text=None, value=None, size=None, maxlength=None, style=None, id=None, attributes=None, type="text", tableRow=None):
+               if (text == None):
+                       text = name
+               self.field = input(type=type, name=name, value=value, size=size, maxlength=maxlength, style=style, id=id, attributes=attributes)
+               self.text = text
+               
+               if tableRow == None:
+                       part.__init__(self, 'p', style=style, attributes=attributes)
+                       self.addPiece(self.text)
+                       self.addPiece(self.field)
+               else:
+                       part.__init__(self, 'tr', style=style, attributes=attributes)
+                       self.addPart('th', content=self.text)
+                       self.addPart('td', content=self.field)
+
+
+
+#need some functions for HTML
+#ought to be somewhere else in Python?
+#cgi.escape only seems to do <, >, and &
+from htmlentitydefs import entitydefs
+import re
+
+entitydefs_inverted = {}
+for k,v in entitydefs.items():
+       entitydefs_inverted[v] = k
+
+needencoding = re.compile('|'.join(entitydefs.values()))
+alreadyencoded = re.compile('&\w+;|&#[0-9]+;')
+
+#encodes any special characters to their HTML equivalents
+def encode(text, skip=None, once_only=1):
+       # if extra_careful, check to see if this text has already been converted
+       if not (once_only and alreadyencoded.findall(text)):
+               if not isinstance(skip, list):
+                       skip = [skip]
+
+               #do ampersands on their own or we might end up converting our conversions
+               if '&' not in skip:
+                       text = text.replace('&','&amp;')
+                       skip.append('&')
+
+               needlist= []
+               #grab the characters in the text that need encoding
+               for x in needencoding.findall(text):
+                       #and make sure we aren't skipping them
+                       if x not in skip:
+                               needlist.append(x)
+
+               for uncoded in needlist:
+                       encoded = entitydefs_inverted[uncoded]
+                       #if it is not a numerical encoding, we need to do the & and ; ourselves
+                       if not encoded.startswith('&#'):
+                               encoded = '&%s;'%entitydefs_inverted[uncoded]
+       
+                       text = text.replace(uncoded, encoded)
+
+       return text
diff --git a/nagios/configurator/misccommands.cfg b/nagios/configurator/misccommands.cfg
new file mode 100644 (file)
index 0000000..715e515
--- /dev/null
@@ -0,0 +1,104 @@
+################################################################################
+# Sample object config file for Nagios 
+#
+# Read the documentation for more information on this configuration file.  I've
+# provided some comments here, but things may not be so clear without further
+# explanation, so make sure to read the HTML documentation!
+# 
+# Last Modified: 12-17-2005
+#
+################################################################################
+
+
+################################################################################
+# COMMAND DEFINITIONS
+#
+# SYNTAX:
+#
+#      define command{
+#               template      <templatename>
+#              name          <objectname>
+#               command_name  <commandname>
+#               command_line  <commandline>
+#               }
+#
+# WHERE:
+#
+# <templatename> = object name of another command definition that should be
+#                  used as a template for this definition (optional)
+# <objectname>   = object name of command definition, referenced by other
+#                  command definitions that use it as a template (optional)
+# <commandname>  = name of the command, as recognized/used by Nagios
+# <commandline>  = command line
+#
+################################################################################
+
+
+
+
+################################################################################
+#
+# SAMPLE NOTIFICATION COMMANDS
+#
+# These are some example notification commands.  They may or may not work on
+# your system without modification.
+#
+################################################################################
+
+
+# 'host-notify-by-email' command definition
+define command{
+       command_name    host-notify-by-email
+       command_line    /usr/bin/printf "%b" "***** Nagios  *****\n\nNotification Type: $NOTIFICATIONTYPE$\nHost: $HOSTNAME$\nState: $HOSTSTATE$\nAddress: $HOSTADDRESS$\nInfo: $HOSTOUTPUT$\n\nDate/Time: $LONGDATETIME$\n" | /bin/mail -s "Host $HOSTSTATE$ alert for $HOSTNAME$!" $CONTACTEMAIL$
+       }
+
+
+# 'host-notify-by-epager' command definition
+define command{
+       command_name    host-notify-by-epager
+       command_line    /usr/bin/printf "%b" "Host '$HOSTALIAS$' is $HOSTSTATE$\nInfo: $HOSTOUTPUT$\nTime: $LONGDATETIME$" | /bin/mail -s "$NOTIFICATIONTYPE$ alert - Host $HOSTNAME$ is $HOSTSTATE$" $CONTACTPAGER$
+       }
+
+# 'notify-by-email' command definition
+define command{
+       command_name    notify-by-email
+       command_line    /usr/bin/printf "%b" "***** Nagios  *****\n\nNotification Type: $NOTIFICATIONTYPE$\n\nService: $SERVICEDESC$\nHost: $HOSTALIAS$\nAddress: $HOSTADDRESS$\nState: $SERVICESTATE$\n\nDate/Time: $LONGDATETIME$\n\nAdditional Info:\n\n$SERVICEOUTPUT$" | /bin/mail -s "** $NOTIFICATIONTYPE$ alert - $HOSTALIAS$/$SERVICEDESC$ is $SERVICESTATE$ **" $CONTACTEMAIL$
+       }
+
+
+# 'notify-by-epager' command definition
+define command{
+       command_name    notify-by-epager
+       command_line    /usr/bin/printf "%b" "Service: $SERVICEDESC$\nHost: $HOSTNAME$\nAddress: $HOSTADDRESS$\nState: $SERVICESTATE$\nInfo: $SERVICEOUTPUT$\nDate: $LONGDATETIME$" | /bin/mail -s "$NOTIFICATIONTYPE$: $HOSTALIAS$/$SERVICEDESC$ is $SERVICESTATE$" $CONTACTPAGER$
+       }
+
+
+
+
+
+################################################################################
+#
+# SAMPLE PERFORMANCE DATA COMMANDS
+#
+# These are sample performance data commands that can be used to send performance
+# data output to two text files (one for hosts, another for services).  If you
+# plan on simply writing performance data out to a file, consider using the 
+# host_perfdata_file and service_perfdata_file options in the main config file.
+#
+################################################################################
+
+
+# 'process-host-perfdata' command definition
+define command{
+       command_name    process-host-perfdata
+       command_line    /usr/bin/printf "%b" "$LASTHOSTCHECK$\t$HOSTNAME$\t$HOSTSTATE$\t$HOSTATTEMPT$\t$HOSTSTATETYPE$\t$HOSTEXECUTIONTIME$\t$HOSTOUTPUT$\t$HOSTPERFDATA$\n" >> /var/log/nagios/host-perfdata.out
+       }
+
+
+# 'process-service-perfdata' command definition
+define command{
+       command_name    process-service-perfdata
+       command_line    /usr/bin/printf "%b" "$LASTSERVICECHECK$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICESTATE$\t$SERVICEATTEMPT$\t$SERVICESTATETYPE$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t$SERVICEPERFDATA$\n" >> /var/log/nagios/service-perfdata.out
+       }
+
+
diff --git a/nagios/configurator/nagios.cfg b/nagios/configurator/nagios.cfg
new file mode 100644 (file)
index 0000000..f79e782
--- /dev/null
@@ -0,0 +1,939 @@
+##############################################################################
+#
+# NAGIOS.CFG - Sample Main Config File for Nagios 
+#
+# Read the documentation for more information on this configuration
+# file.  I've provided some comments here, but things may not be so
+# clear without further explanation.
+#
+# Last Modified: 11-23-2005
+#
+##############################################################################
+
+
+# LOG FILE
+# This is the main log file where service and host events are logged
+# for historical purposes.  This should be the first option specified 
+# in the config file!!!
+
+log_file=/var/log/nagios/nagios.log
+
+
+
+# OBJECT CONFIGURATION FILE(S)
+# This is the configuration file in which you define hosts, host
+# groups, contacts, contact groups, services, etc.  I guess it would
+# be better called an object definition file, but for historical
+# reasons it isn't.  You can split object definitions into several
+# different config files by using multiple cfg_file statements here.
+# Nagios will read and process all the config files you define.
+# This can be very useful if you want to keep command definitions 
+# separate from host and contact definitions...
+
+# Plugin commands (service and host check commands)
+# Arguments are likely to change between different releases of the
+# plugins, so you should use the same config file provided with the
+# plugin release rather than the one provided with Nagios.
+# merged into generic.cfg
+#cfg_file=/etc/nagios/checkcommands.cfg
+
+# Misc commands (notification and event handler commands, etc)
+cfg_file=/etc/nagios/misccommands.cfg
+
+# You can split other types of object definitions across several
+# config files if you wish (as done here), or keep them all in a
+# single config file.
+
+# we define here the generic stuff that planetlab.cfg relies upon
+cfg_file=/etc/nagios/generic.cfg
+
+# python-generated common definitions - need to be loaded first
+cfg_file=/etc/nagios/planetlab.cfg
+
+# python-generated details
+cfg_dir=/etc/nagios/planetlab/
+
+
+
+# OBJECT CACHE FILE
+# This option determines where object definitions are cached when
+# Nagios starts/restarts.  The CGIs read object definitions from 
+# this cache file (rather than looking at the object config files
+# directly) in order to prevent inconsistencies that can occur
+# when the config files are modified after Nagios starts.
+
+object_cache_file=/var/log/nagios/objects.cache
+
+
+# RESOURCE FILE
+# This is an optional resource file that contains $USERx$ macro
+# definitions. Multiple resource files can be specified by using
+# multiple resource_file definitions.  The CGIs will not attempt to
+# read the contents of resource files, so information that is
+# considered to be sensitive (usernames, passwords, etc) can be
+# defined as macros in this file and restrictive permissions (600)
+# can be placed on this file.
+
+resource_file=/etc/nagios/private/resource.cfg
+
+
+
+# STATUS FILE
+# This is where the current status of all monitored services and
+# hosts is stored.  Its contents are read and processed by the CGIs.
+# The contents of the status file are deleted every time Nagios
+#  restarts.
+
+status_file=/var/log/nagios/status.dat
+
+
+
+# NAGIOS USER
+# This determines the effective user that Nagios should run as.  
+# You can either supply a username or a UID.
+
+nagios_user=nagios
+
+
+
+# NAGIOS GROUP
+# This determines the effective group that Nagios should run as.  
+# You can either supply a group name or a GID.
+
+nagios_group=nagios
+
+
+
+# EXTERNAL COMMAND OPTION
+# This option allows you to specify whether or not Nagios should check
+# for external commands (in the command file defined below).  By default
+# Nagios will *not* check for external commands, just to be on the
+# cautious side.  If you want to be able to use the CGI command interface
+# you will have to enable this.  Setting this value to 0 disables command
+# checking (the default), other values enable it.
+
+check_external_commands=1
+
+
+
+# EXTERNAL COMMAND CHECK INTERVAL
+# This is the interval at which Nagios should check for external commands.
+# This value works of the interval_length you specify later.  If you leave
+# that at its default value of 60 (seconds), a value of 1 here will cause
+# Nagios to check for external commands every minute.  If you specify a
+# number followed by an "s" (i.e. 15s), this will be interpreted to mean
+# actual seconds rather than a multiple of the interval_length variable.
+# Note: In addition to reading the external command file at regularly 
+# scheduled intervals, Nagios will also check for external commands after
+# event handlers are executed.
+# NOTE: Setting this value to -1 causes Nagios to check the external
+# command file as often as possible.
+
+#command_check_interval=1
+#command_check_interval=15s
+command_check_interval=-1
+
+
+
+# EXTERNAL COMMAND FILE
+# This is the file that Nagios checks for external command requests.
+# It is also where the command CGI will write commands that are submitted
+# by users, so it must be writeable by the user that the web server
+# is running as (usually 'nobody').  Permissions should be set at the 
+# directory level instead of on the file, as the file is deleted every
+# time its contents are processed.
+
+command_file=/var/spool/nagios/cmd/nagios.cmd
+
+
+
+# COMMENT FILE
+# This is the file that Nagios will use for storing host and service
+# comments.
+
+comment_file=/var/log/nagios/comments.dat
+
+
+
+# DOWNTIME FILE
+# This is the file that Nagios will use for storing host and service
+# downtime data.
+
+downtime_file=/var/log/nagios/downtime.dat
+
+
+
+# LOCK FILE
+# This is the lockfile that Nagios will use to store its PID number
+# in when it is running in daemon mode.
+
+lock_file=/var/run/nagios.pid
+
+
+
+# TEMP FILE
+# This is a temporary file that is used as scratch space when Nagios
+# updates the status log, cleans the comment file, etc.  This file
+# is created, used, and deleted throughout the time that Nagios is
+# running.
+
+temp_file=/var/log/nagios/nagios.tmp
+
+
+
+# EVENT BROKER OPTIONS
+# Controls what (if any) data gets sent to the event broker.
+# Values:  0      = Broker nothing
+#         -1      = Broker everything
+#         <other> = See documentation
+
+event_broker_options=-1
+
+
+
+# EVENT BROKER MODULE(S)
+# This directive is used to specify an event broker module that should
+# by loaded by Nagios at startup.  Use multiple directives if you want
+# to load more than one module.  Arguments that should be passed to
+# the module at startup are seperated from the module path by a space.
+#
+# Example:
+#
+#   broker_module=<modulepath> [moduleargs]
+
+#broker_module=/somewhere/module1.o
+#broker_module=/somewhere/module2.o arg1 arg2=3 debug=0
+
+
+
+
+# LOG ROTATION METHOD
+# This is the log rotation method that Nagios should use to rotate
+# the main log file. Values are as follows..
+#      n       = None - don't rotate the log
+#      h       = Hourly rotation (top of the hour)
+#      d       = Daily rotation (midnight every day)
+#      w       = Weekly rotation (midnight on Saturday evening)
+#      m       = Monthly rotation (midnight last day of month)
+
+log_rotation_method=d
+
+
+
+# LOG ARCHIVE PATH
+# This is the directory where archived (rotated) log files should be 
+# placed (assuming you've chosen to do log rotation).
+
+log_archive_path=/var/log/nagios/archives
+
+
+
+# LOGGING OPTIONS
+# If you want messages logged to the syslog facility, as well as the
+# NetAlarm log file set this option to 1.  If not, set it to 0.
+
+use_syslog=1
+
+
+
+# NOTIFICATION LOGGING OPTION
+# If you don't want notifications to be logged, set this value to 0.
+# If notifications should be logged, set the value to 1.
+
+log_notifications=1
+
+
+
+# SERVICE RETRY LOGGING OPTION
+# If you don't want service check retries to be logged, set this value
+# to 0.  If retries should be logged, set the value to 1.
+
+log_service_retries=1
+
+
+
+# HOST RETRY LOGGING OPTION
+# If you don't want host check retries to be logged, set this value to
+# 0.  If retries should be logged, set the value to 1.
+
+log_host_retries=1
+
+
+
+# EVENT HANDLER LOGGING OPTION
+# If you don't want host and service event handlers to be logged, set
+# this value to 0.  If event handlers should be logged, set the value
+# to 1.
+
+log_event_handlers=1
+
+
+
+# INITIAL STATES LOGGING OPTION
+# If you want Nagios to log all initial host and service states to
+# the main log file (the first time the service or host is checked)
+# you can enable this option by setting this value to 1.  If you
+# are not using an external application that does long term state
+# statistics reporting, you do not need to enable this option.  In
+# this case, set the value to 0.
+
+log_initial_states=0
+
+
+
+# EXTERNAL COMMANDS LOGGING OPTION
+# If you don't want Nagios to log external commands, set this value
+# to 0.  If external commands should be logged, set this value to 1.
+# Note: This option does not include logging of passive service
+# checks - see the option below for controlling whether or not
+# passive checks are logged.
+
+log_external_commands=1
+
+
+
+# PASSIVE CHECKS LOGGING OPTION
+# If you don't want Nagios to log passive host and service checks, set
+# this value to 0.  If passive checks should be logged, set
+# this value to 1.
+
+log_passive_checks=1
+
+
+
+# GLOBAL HOST AND SERVICE EVENT HANDLERS
+# These options allow you to specify a host and service event handler
+# command that is to be run for every host or service state change.
+# The global event handler is executed immediately prior to the event
+# handler that you have optionally specified in each host or
+# service definition. The command argument is the short name of a
+# command definition that you define in your host configuration file.
+# Read the HTML docs for more information.
+
+#global_host_event_handler=somecommand
+#global_service_event_handler=somecommand
+
+
+
+# SERVICE INTER-CHECK DELAY METHOD
+# This is the method that Nagios should use when initially
+# "spreading out" service checks when it starts monitoring.  The
+# default is to use smart delay calculation, which will try to
+# space all service checks out evenly to minimize CPU load.
+# Using the dumb setting will cause all checks to be scheduled
+# at the same time (with no delay between them)!  This is not a
+# good thing for production, but is useful when testing the
+# parallelization functionality.
+#      n       = None - don't use any delay between checks
+#      d       = Use a "dumb" delay of 1 second between checks
+#      s       = Use "smart" inter-check delay calculation
+#       x.xx    = Use an inter-check delay of x.xx seconds
+
+service_inter_check_delay_method=s
+
+
+
+# MAXIMUM SERVICE CHECK SPREAD
+# This variable determines the timeframe (in minutes) from the
+# program start time that an initial check of all services should
+# be completed.  Default is 30 minutes.
+
+max_service_check_spread=30
+
+
+
+# SERVICE CHECK INTERLEAVE FACTOR
+# This variable determines how service checks are interleaved.
+# Interleaving the service checks allows for a more even
+# distribution of service checks and reduced load on remote
+# hosts.  Setting this value to 1 is equivalent to how versions
+# of Nagios previous to 0.0.5 did service checks.  Set this
+# value to s (smart) for automatic calculation of the interleave
+# factor unless you have a specific reason to change it.
+#       s       = Use "smart" interleave factor calculation
+#       x       = Use an interleave factor of x, where x is a
+#                 number greater than or equal to 1.
+
+service_interleave_factor=s
+
+
+
+# HOST INTER-CHECK DELAY METHOD
+# This is the method that Nagios should use when initially
+# "spreading out" host checks when it starts monitoring.  The
+# default is to use smart delay calculation, which will try to
+# space all host checks out evenly to minimize CPU load.
+# Using the dumb setting will cause all checks to be scheduled
+# at the same time (with no delay between them)!
+#      n       = None - don't use any delay between checks
+#      d       = Use a "dumb" delay of 1 second between checks
+#      s       = Use "smart" inter-check delay calculation
+#       x.xx    = Use an inter-check delay of x.xx seconds
+
+host_inter_check_delay_method=s
+
+
+
+# MAXIMUM HOST CHECK SPREAD
+# This variable determines the timeframe (in minutes) from the
+# program start time that an initial check of all hosts should
+# be completed.  Default is 30 minutes.
+
+max_host_check_spread=30
+
+
+
+# MAXIMUM CONCURRENT SERVICE CHECKS
+# This option allows you to specify the maximum number of 
+# service checks that can be run in parallel at any given time.
+# Specifying a value of 1 for this variable essentially prevents
+# any service checks from being parallelized.  A value of 0
+# will not restrict the number of concurrent checks that are
+# being executed.
+
+max_concurrent_checks=0
+
+
+
+# SERVICE CHECK REAPER FREQUENCY
+# This is the frequency (in seconds!) that Nagios will process
+# the results of services that have been checked.
+
+service_reaper_frequency=10
+
+
+
+
+# AUTO-RESCHEDULING OPTION
+# This option determines whether or not Nagios will attempt to
+# automatically reschedule active host and service checks to
+# "smooth" them out over time.  This can help balance the load on
+# the monitoring server.  
+# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE
+# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY
+
+auto_reschedule_checks=0
+
+
+
+# AUTO-RESCHEDULING INTERVAL
+# This option determines how often (in seconds) Nagios will
+# attempt to automatically reschedule checks.  This option only
+# has an effect if the auto_reschedule_checks option is enabled.
+# Default is 30 seconds.
+# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE
+# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY
+
+auto_rescheduling_interval=30
+
+
+
+
+# AUTO-RESCHEDULING WINDOW
+# This option determines the "window" of time (in seconds) that
+# Nagios will look at when automatically rescheduling checks.
+# Only host and service checks that occur in the next X seconds
+# (determined by this variable) will be rescheduled. This option
+# only has an effect if the auto_reschedule_checks option is
+# enabled.  Default is 180 seconds (3 minutes).
+# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE
+# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY
+
+auto_rescheduling_window=180
+
+
+
+# SLEEP TIME
+# This is the number of seconds to sleep between checking for system
+# events and service checks that need to be run.
+
+sleep_time=0.25
+
+
+
+# TIMEOUT VALUES
+# These options control how much time Nagios will allow various
+# types of commands to execute before killing them off.  Options
+# are available for controlling maximum time allotted for
+# service checks, host checks, event handlers, notifications, the
+# ocsp command, and performance data commands.  All values are in
+# seconds.
+
+service_check_timeout=60
+host_check_timeout=30
+event_handler_timeout=30
+notification_timeout=30
+ocsp_timeout=5
+perfdata_timeout=5
+
+
+
+# RETAIN STATE INFORMATION
+# This setting determines whether or not Nagios will save state
+# information for services and hosts before it shuts down.  Upon
+# startup Nagios will reload all saved service and host state
+# information before starting to monitor.  This is useful for 
+# maintaining long-term data on state statistics, etc, but will
+# slow Nagios down a bit when it (re)starts.  Since its only
+# a one-time penalty, I think its well worth the additional
+# startup delay.
+
+retain_state_information=1
+
+
+
+# STATE RETENTION FILE
+# This is the file that Nagios should use to store host and
+# service state information before it shuts down.  The state 
+# information in this file is also read immediately prior to
+# starting to monitor the network when Nagios is restarted.
+# This file is used only if the preserve_state_information
+# variable is set to 1.
+
+state_retention_file=/var/log/nagios/retention.dat
+
+
+
+# RETENTION DATA UPDATE INTERVAL
+# This setting determines how often (in minutes) that Nagios
+# will automatically save retention data during normal operation.
+# If you set this value to 0, Nagios will not save retention
+# data at regular interval, but it will still save retention
+# data before shutting down or restarting.  If you have disabled
+# state retention, this option has no effect.
+
+retention_update_interval=60
+
+
+
+# USE RETAINED PROGRAM STATE
+# This setting determines whether or not Nagios will set 
+# program status variables based on the values saved in the
+# retention file.  If you want to use retained program status
+# information, set this value to 1.  If not, set this value
+# to 0.
+
+use_retained_program_state=1
+
+
+
+# USE RETAINED SCHEDULING INFO
+# This setting determines whether or not Nagios will retain
+# the scheduling info (next check time) for hosts and services
+# based on the values saved in the retention file.  If you
+# If you want to use retained scheduling info, set this
+# value to 1.  If not, set this value to 0.
+
+use_retained_scheduling_info=0
+
+
+
+# INTERVAL LENGTH
+# This is the seconds per unit interval as used in the
+# host/contact/service configuration files.  Setting this to 60 means
+# that each interval is one minute long (60 seconds).  Other settings
+# have not been tested much, so your mileage is likely to vary...
+
+interval_length=60
+
+
+
+# AGGRESSIVE HOST CHECKING OPTION
+# If you don't want to turn on aggressive host checking features, set
+# this value to 0 (the default).  Otherwise set this value to 1 to
+# enable the aggressive check option.  Read the docs for more info
+# on what aggressive host check is or check out the source code in
+# base/checks.c
+
+use_aggressive_host_checking=0
+
+
+
+# SERVICE CHECK EXECUTION OPTION
+# This determines whether or not Nagios will actively execute
+# service checks when it initially starts.  If this option is 
+# disabled, checks are not actively made, but Nagios can still
+# receive and process passive check results that come in.  Unless
+# you're implementing redundant hosts or have a special need for
+# disabling the execution of service checks, leave this enabled!
+# Values: 1 = enable checks, 0 = disable checks
+
+execute_service_checks=1
+
+
+
+# PASSIVE SERVICE CHECK ACCEPTANCE OPTION
+# This determines whether or not Nagios will accept passive
+# service checks results when it initially (re)starts.
+# Values: 1 = accept passive checks, 0 = reject passive checks
+
+accept_passive_service_checks=1
+
+
+
+# HOST CHECK EXECUTION OPTION
+# This determines whether or not Nagios will actively execute
+# host checks when it initially starts.  If this option is 
+# disabled, checks are not actively made, but Nagios can still
+# receive and process passive check results that come in.  Unless
+# you're implementing redundant hosts or have a special need for
+# disabling the execution of host checks, leave this enabled!
+# Values: 1 = enable checks, 0 = disable checks
+
+execute_host_checks=1
+
+
+
+# PASSIVE HOST CHECK ACCEPTANCE OPTION
+# This determines whether or not Nagios will accept passive
+# host checks results when it initially (re)starts.
+# Values: 1 = accept passive checks, 0 = reject passive checks
+
+accept_passive_host_checks=1
+
+
+
+# NOTIFICATIONS OPTION
+# This determines whether or not Nagios will sent out any host or
+# service notifications when it is initially (re)started.
+# Values: 1 = enable notifications, 0 = disable notifications
+
+enable_notifications=1
+
+
+
+# EVENT HANDLER USE OPTION
+# This determines whether or not Nagios will run any host or
+# service event handlers when it is initially (re)started.  Unless
+# you're implementing redundant hosts, leave this option enabled.
+# Values: 1 = enable event handlers, 0 = disable event handlers
+
+enable_event_handlers=1
+
+
+
+# PROCESS PERFORMANCE DATA OPTION
+# This determines whether or not Nagios will process performance
+# data returned from service and host checks.  If this option is
+# enabled, host performance data will be processed using the
+# host_perfdata_command (defined below) and service performance
+# data will be processed using the service_perfdata_command (also
+# defined below).  Read the HTML docs for more information on
+# performance data.
+# Values: 1 = process performance data, 0 = do not process performance data
+
+process_performance_data=0
+
+
+
+# HOST AND SERVICE PERFORMANCE DATA PROCESSING COMMANDS
+# These commands are run after every host and service check is
+# performed.  These commands are executed only if the
+# enable_performance_data option (above) is set to 1.  The command
+# argument is the short name of a command definition that you 
+# define in your host configuration file.  Read the HTML docs for
+# more information on performance data.
+
+#host_perfdata_command=process-host-perfdata
+#service_perfdata_command=process-service-perfdata
+
+
+
+# HOST AND SERVICE PERFORMANCE DATA FILES
+# These files are used to store host and service performance data.
+# Performance data is only written to these files if the
+# enable_performance_data option (above) is set to 1.
+
+#host_perfdata_file=/tmp/host-perfdata
+#service_perfdata_file=/tmp/service-perfdata
+
+
+
+# HOST AND SERVICE PERFORMANCE DATA FILE TEMPLATES
+# These options determine what data is written (and how) to the
+# performance data files.  The templates may contain macros, special
+# characters (\t for tab, \r for carriage return, \n for newline)
+# and plain text.  A newline is automatically added after each write
+# to the performance data file.  Some examples of what you can do are
+# shown below.
+
+#host_perfdata_file_template=[HOSTPERFDATA]\t$TIMET$\t$HOSTNAME$\t$HOSTEXECUTIONTIME$\t$HOSTOUTPUT$\t$HOSTPERFDATA$
+#service_perfdata_file_template=[SERVICEPERFDATA]\t$TIMET$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t$SERVICEPERFDATA$
+
+
+
+
+# HOST AND SERVICE PERFORMANCE DATA FILE MODES
+# This option determines whether or not the host and service
+# performance data files are opened in write ("w") or append ("a")
+# mode.  Unless you are the files are named pipes, you will probably
+# want to use the default mode of append ("a").
+
+#host_perfdata_file_mode=a
+#service_perfdata_file_mode=a
+
+
+
+# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING INTERVAL
+# These options determine how often (in seconds) the host and service
+# performance data files are processed using the commands defined
+# below.  A value of 0 indicates the files should not be periodically
+# processed.
+
+#host_perfdata_file_processing_interval=0
+#service_perfdata_file_processing_interval=0
+
+
+
+# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING COMMANDS
+# These commands are used to periodically process the host and
+# service performance data files.  The interval at which the
+# processing occurs is determined by the options above.
+
+#host_perfdata_file_processing_command=process-host-perfdata-file
+#service_perfdata_file_processing_command=process-service-perfdata-file
+
+
+
+# OBSESS OVER SERVICE CHECKS OPTION
+# This determines whether or not Nagios will obsess over service
+# checks and run the ocsp_command defined below.  Unless you're
+# planning on implementing distributed monitoring, do not enable
+# this option.  Read the HTML docs for more information on
+# implementing distributed monitoring.
+# Values: 1 = obsess over services, 0 = do not obsess (default)
+
+obsess_over_services=0
+
+
+
+# OBSESSIVE COMPULSIVE SERVICE PROCESSOR COMMAND
+# This is the command that is run for every service check that is
+# processed by Nagios.  This command is executed only if the
+# obsess_over_service option (above) is set to 1.  The command 
+# argument is the short name of a command definition that you
+# define in your host configuration file. Read the HTML docs for
+# more information on implementing distributed monitoring.
+
+#ocsp_command=somecommand
+
+
+
+# ORPHANED SERVICE CHECK OPTION
+# This determines whether or not Nagios will periodically 
+# check for orphaned services.  Since service checks are not
+# rescheduled until the results of their previous execution 
+# instance are processed, there exists a possibility that some
+# checks may never get rescheduled.  This seems to be a rare
+# problem and should not happen under normal circumstances.
+# If you have problems with service checks never getting
+# rescheduled, you might want to try enabling this option.
+# Values: 1 = enable checks, 0 = disable checks
+
+check_for_orphaned_services=0
+
+
+
+# SERVICE FRESHNESS CHECK OPTION
+# This option determines whether or not Nagios will periodically
+# check the "freshness" of service results.  Enabling this option
+# is useful for ensuring passive checks are received in a timely
+# manner.
+# Values: 1 = enabled freshness checking, 0 = disable freshness checking
+
+check_service_freshness=1
+
+
+
+# SERVICE FRESHNESS CHECK INTERVAL
+# This setting determines how often (in seconds) Nagios will
+# check the "freshness" of service check results.  If you have
+# disabled service freshness checking, this option has no effect.
+
+service_freshness_check_interval=60
+
+
+
+# HOST FRESHNESS CHECK OPTION
+# This option determines whether or not Nagios will periodically
+# check the "freshness" of host results.  Enabling this option
+# is useful for ensuring passive checks are received in a timely
+# manner.
+# Values: 1 = enabled freshness checking, 0 = disable freshness checking
+
+check_host_freshness=0
+
+
+
+# HOST FRESHNESS CHECK INTERVAL
+# This setting determines how often (in seconds) Nagios will
+# check the "freshness" of host check results.  If you have
+# disabled host freshness checking, this option has no effect.
+
+host_freshness_check_interval=60
+
+
+
+# AGGREGATED STATUS UPDATES
+# This option determines whether or not Nagios will 
+# aggregate updates of host, service, and program status
+# data.  Normally, status data is updated immediately when
+# a change occurs.  This can result in high CPU loads if
+# you are monitoring a lot of services.  If you want Nagios
+# to only refresh status data every few seconds, disable
+# this option.
+# Values: 1 = enable aggregate updates, 0 = disable aggregate updates
+
+aggregate_status_updates=1
+
+
+
+# AGGREGATED STATUS UPDATE INTERVAL
+# Combined with the aggregate_status_updates option,
+# this option determines the frequency (in seconds!) that
+# Nagios will periodically dump program, host, and 
+# service status data.  If you are not using aggregated
+# status data updates, this option has no effect.
+
+status_update_interval=15
+
+
+
+# FLAP DETECTION OPTION
+# This option determines whether or not Nagios will try
+# and detect hosts and services that are "flapping".  
+# Flapping occurs when a host or service changes between
+# states too frequently.  When Nagios detects that a 
+# host or service is flapping, it will temporarily suppress
+# notifications for that host/service until it stops
+# flapping.  Flap detection is very experimental, so read
+# the HTML documentation before enabling this feature!
+# Values: 1 = enable flap detection
+#         0 = disable flap detection (default)
+
+enable_flap_detection=0
+
+
+
+# FLAP DETECTION THRESHOLDS FOR HOSTS AND SERVICES
+# Read the HTML documentation on flap detection for
+# an explanation of what this option does.  This option
+# has no effect if flap detection is disabled.
+
+low_service_flap_threshold=5.0
+high_service_flap_threshold=20.0
+low_host_flap_threshold=5.0
+high_host_flap_threshold=20.0
+
+
+
+# DATE FORMAT OPTION
+# This option determines how short dates are displayed. Valid options
+# include:
+#      us              (MM-DD-YYYY HH:MM:SS)
+#      euro            (DD-MM-YYYY HH:MM:SS)
+#      iso8601         (YYYY-MM-DD HH:MM:SS)
+#      strict-iso8601  (YYYY-MM-DDTHH:MM:SS)
+#
+
+date_format=us
+
+
+
+# P1.PL FILE LOCATION
+# This value determines where the p1.pl perl script (used by the
+# embedded Perl interpreter) is located.  If you didn't compile
+# Nagios with embedded Perl support, this option has no effect.
+
+p1_file=/usr/sbin/p1.pl
+
+
+
+# ILLEGAL OBJECT NAME CHARACTERS
+# This option allows you to specify illegal characters that cannot
+# be used in host names, service descriptions, or names of other
+# object types.
+
+illegal_object_name_chars=`~!$%^&*|'"<>?,()=
+
+
+
+# ILLEGAL MACRO OUTPUT CHARACTERS
+# This option allows you to specify illegal characters that are
+# stripped from macros before being used in notifications, event
+# handlers, etc.  This DOES NOT affect macros used in service or
+# host check commands.
+# The following macros are stripped of the characters you specify:
+#      $HOSTOUTPUT$
+#      $HOSTPERFDATA$
+#      $HOSTACKAUTHOR$
+#      $HOSTACKCOMMENT$
+#      $SERVICEOUTPUT$
+#      $SERVICEPERFDATA$
+#      $SERVICEACKAUTHOR$
+#      $SERVICEACKCOMMENT$
+
+illegal_macro_output_chars=`~$&|'"<>
+
+
+
+# REGULAR EXPRESSION MATCHING
+# This option controls whether or not regular expression matching
+# takes place in the object config files.  Regular expression
+# matching is used to match host, hostgroup, service, and service
+# group names/descriptions in some fields of various object types.
+# Values: 1 = enable regexp matching, 0 = disable regexp matching
+
+use_regexp_matching=0
+
+
+
+# "TRUE" REGULAR EXPRESSION MATCHING
+# This option controls whether or not "true" regular expression 
+# matching takes place in the object config files.  This option
+# only has an effect if regular expression matching is enabled
+# (see above).  If this option is DISABLED, regular expression
+# matching only occurs if a string contains wildcard characters
+# (* and ?).  If the option is ENABLED, regexp matching occurs
+# all the time (which can be annoying).
+# Values: 1 = enable true matching, 0 = disable true matching
+
+use_true_regexp_matching=0
+
+
+
+
+# ADMINISTRATOR EMAIL ADDRESS
+# The email address of the administrator of *this* machine (the one
+# doing the monitoring).  Nagios never uses this value itself, but
+# you can access this value by using the $ADMINEMAIL$ macro in your
+# notification commands.
+
+admin_email=nagios
+
+
+
+# ADMINISTRATOR PAGER NUMBER/ADDRESS
+# The pager number/address for the administrator of *this* machine.
+# Nagios never uses this value itself, but you can access this
+# value by using the $ADMINPAGER$ macro in your notification
+# commands.
+
+admin_pager=pagenagios
+
+
+
+# DAEMON CORE DUMP OPTION
+# This option determines whether or not Nagios is allowed to create
+# a core dump when it runs as a daemon.  Note that it is generally
+# considered bad form to allow this, but it may be useful for
+# debugging purposes.
+# Values: 1 - Allow core dumps
+#         0 - Do not allow core dumps (default)
+
+daemon_dumps_core=0
+
+
+
+# EOF (End of file)
+
diff --git a/nagios/configurator/nagios.py b/nagios/configurator/nagios.py
new file mode 100644 (file)
index 0000000..0cccbe1
--- /dev/null
@@ -0,0 +1,6 @@
+## as per nagios doc
+OK=0
+WARNING=1
+KO=2
+UNKNOWN=3
+
diff --git a/nagios/configurator/onelab.txt b/nagios/configurator/onelab.txt
new file mode 100644 (file)
index 0000000..89d5ec5
--- /dev/null
@@ -0,0 +1 @@
+2 INRIA Sophia OneLab