coshsh



Gerhard Laußer,  ConSol* Software GmbH

Was ist coshsh?



Ein Framework, mit dem beliebige Datenquellen angezapft werden können, um automatisiert Nagios-Konfigurationsdateien zu erzeugen.



Datenquellen enthalten Hosts und Applikationen. (DB, CSV, ...)

Es gibt Regeln, wie Host- und Applikationsobjekte in Nagios-Hosts und -Services transformiert werden. 



Was ist coshsh nicht?



  • Eine Konfigurations-GUI

    Viel zu kompliziert. Warum sollte ein Windows-Admin oder DBA sich mit max_check_attempts & co  herumschlagen, wenn er einfach einen neuen Server oder einen neuen Tablespace ins Monitoring bringen will?



Was ist coshsh nicht?



  • Ein Inventory-Scanner

    Server im Wert von Millionen und keine Kontrolle? Ts ts ts!
    Was will ich in welchem Umfang monitoren? Was ist mit dem (externen) Betreiberteam vereinbart?

    Folge ich einem Plan oder reisse ich eine Wundertüte auf?
    Kann doch nicht sein, dass mir ein Tool sagen muss, was an IT rumsteht und mir vorschreibt, wie das zu überwachen ist?

    Unterscheidet ein Auto-Inventarisierer zwischen Test und Prod?

    Schneller Anfangserfolg, danach manuelle Konfiguration von Ausnahmen, Ausnahmen, Ausnahmen

Was ist coshsh?




coshsh ist ein Generator für hoch standardisierte Umgebungen, der die Pflege das IT-Bestands von der Pflege des Monitorings trennt.


coshsh sorgt dafür, dass in einer PaaS/SaaS-Umgebung neue Services und VMs nach der Registrierung in kürzester Zeit und bedienerlos ins Monitoring aufgenommen werden.

Grundprinzip


Host- und Applikationsobjekte haben Klassen und Templates


def __mi_ident__(params={}):
    if compare_attr("type", params, ".*ontap.*|.*netapp.*"):
        return ONTAP
class ONTAP(Application):
    template_rules = [
        TemplateRule(needsattr=None, 
            template="os_ontap_default", 
        ),
        TemplateRule(needsattr="volumes", 
            template="os_ontap_fs", 
        ),
    ]

Klasse



Für jede Sorte von Applikation legt man eine Klasse an. Diese erklärt sich für zuständig, wenn ein passender Eintrag aus der Datasource kommt, z.B. das Betriebssystem eines Filers:

def __mi_ident__(params={}):
    if compare_attr("type", params, ".*ontap.*|.*netapp.*"):
        return ONTAP


class ONTAP(Application):
    template_rules = [
        TemplateRule(needsattr=None, 
            template="os_ontap_default", 
        ),
        TemplateRule(needsattr="volumes", 
            template="os_ontap_fs", 
        ),
    ]
 

Template


Eine "fast" fertige Konfigurationsdatei, die mit den realen Werten der Applikation versorgt wird.
{{ application|service("os_ontap_default_check_hw") }}
  host_name                       {{ application.host_name }}
  use                             os_ontap_default
  check_command                   check_naf_v2!$HOSTADDRESS$!60!{{ application.l
oginsnmpv2.community }}!environment
}

{{ application|service("os_ontap_default_check_disks") }}
  host_name            {{ application.host_name }}
  use                  os_ontap_default,srv-pnp
  check_command        check_naf_v2!$HOSTADDRESS$!60!{{ application.loginsnmpv2.
community }}!disk,failed
}

{% for volume in application.volumes %}
{{ application|service("os_ontap_fs_check_vol_"+ volume.name) }}
   host_name                       {{ application.host_name }}
   use                             os_ontap_fs,srv-pnp
   check_interval                  15
   retry_interval                  15
   check_command                   check_naf_v2!$HOSTADDRESS$!60!{{ application.
loginsnmpv2.community }}!vol_data,{{ volume.name }},{{ volume.warning}}{{ volume
.units}},{{ volume.critical }}{{ volume.units }}
}
 

Installation




$ mkdir generator $ cd generator $ git pull https://github.com/lausser/coshsh.git $ mkdir recipes $ mkdir recipes/yns/recipes $ mkdir recipes/yns/classes $ mkdir recipes/yns/data $ mkdir etc $ vi etc/coshsh.cfg
$ export PATH=$PATH:$HOME/generator/coshsh/bin

Konfiguration



coshsh.cfg

[datasource_officepcs]
type = csv
dir = %HOME%/generator/recipes/yns/data

[recipe_nsmuc]
objects_dir = %HOME%/siteconfigs/office
datasources = officepcs


Die "CMDB" ist das CSV-File
$HOME/generator/recipes/yns/data/officepcs_hosts.csv

host_name,address,type,os,hardware,virtual,notification_period,location,department
ynspc001,192.168.10.101,pc,Dell Optiplex GX700,ps,7x24,Empfang,Administration
ynspc002,192.168.10.102,pc,Acer veriton M290,ps,7x24,Kasse,Administration



Wir kochen Hosts


Das Kochrezept für nsmuc lautet:

  • Man nehme die Datasource officepcs, also CSV-Dateien namens officepcs_* aus dem Verzeichnis recipes/yns/data
  • Man nehme Classes und Templates (hier: host.py, host.tpl)
  • Man rühre um und fülle alles in siteconfigs/office



$ coshsh/bin/coshsh-cook --cookbook etc/coshsh.cfg --recipe nsmuc
2013-06-15 22:09:03,409 - INFO - recipe nsmuc init
...
2013-06-15 22:09:03,565 - INFO - load template host
2013-06-15 22:09:03,565 - INFO - load items to datarecipient_coshsh_default
2013-06-15 22:09:03,565 - INFO - recipe datarecipient_coshsh_default remove dynamic_dir coshsh/bin/../coshsh/../../siteconfigs/office/dynamic
2013-06-15 22:09:03,565 - INFO - recipient datarecipient_coshsh_default dynamic_dir coshsh/bin/../coshsh/../../siteconfigs/office/dynamic
2013-06-15 22:09:03,565 - INFO - number of files before: 0 hosts, 0 applications
2013-06-15 22:09:03,565 - INFO - number of files after:  2 hosts, 0 applications

Es ist angerichtet


$ find siteconfigs/
siteconfigs/
siteconfigs/office
siteconfigs/office/dynamic
siteconfigs/office/dynamic/hostgroups
siteconfigs/office/dynamic/hosts
siteconfigs/office/dynamic/hosts/ynspc001
siteconfigs/office/dynamic/hosts/ynspc001/host.cfg
siteconfigs/office/dynamic/hosts/ynspc002
siteconfigs/office/dynamic/hosts/ynspc002/host.cfg

und im Detail...

$ cat siteconfigs/office/dynamic/hosts/ynspc001/host.cfg
define host {
use                             generic-host
host_name                       ynspc001
address                         192.168.10.101
alias                           ynspc001
notification_period             7x24
check_command                   check_host_alive
notification_options            d,u,r
_SSH_PORT                       22
}


Hostgroups



h = Host(row)
self.add('hosts', h) 


Erweitern der Datasource

1. Die mitgelieferte Datasource-Klasse ins eigene Verzeichnis kopieren

cp coshsh/recipes/default/classes/datasource_csvfile.py  recipes/yns/classes

2. Hostgruppen erzeugen

h = Host(row)
h.hostgroups.append("dept_" + row["departement".lower())
h.hostgroups.append("loc_" + row["location"].lower()) self.add('hosts', h) 
self.add('hosts', h)

Applikationen - Betriebssystem


Jeder Host bekommt eine Applikation mit dem Namen "os" und dem Typ "Windows", "Linux" [, "IOS", "ESX", "OnTAP",...]


$ cat recipes/yns/data/officepcs_applications.csv
host_name,name,type,component,version,check_period
ynspc001,os,Windows,,2008R2,7x24
ynspc002,os,Windows,,2008R2,7x24


$ coshsh/bin/coshsh-cook --cookbook etc/coshsh.cfg --recipe nsmuc
2013-06-16 00:43:33,767 - INFO - recipe nsmuc init
...
2013-06-16 00:43:33,959 - INFO - number of files before: 2 hosts, 0 applications
2013-06-16 00:43:33,960 - INFO - number of files after:  2 hosts, 2 applications

 

2 hosts, 2 applications



$ find siteconfigs
siteconfigs/
siteconfigs/office
siteconfigs/office/dynamic
siteconfigs/office/dynamic/hostgroups
siteconfigs/office/dynamic/hosts
siteconfigs/office/dynamic/hosts/ynspc001
siteconfigs/office/dynamic/hosts/ynspc001/host.cfg
siteconfigs/office/dynamic/hosts/ynspc001/os_windows_default.cfg
siteconfigs/office/dynamic/hosts/ynspc002
siteconfigs/office/dynamic/hosts/ynspc002/host.cfg
siteconfigs/office/dynamic/hosts/ynspc002/os_windows_default.cfg

os_windows_default.cfg



$ cat siteconfigs/office/dynamic/hosts/ynspc001/os_windows_default.cfg
define service {
service_description os_windows_default_check_nsclient
host_name ynspc001
use os_windows_default
check_command check_nrpe_arg!60!checkUpTime!MinWarn=5m MinCrit=1m
}

define service {
service_description os_windows_default_check_cpu
host_name ynspc001
use os_windows_default,srv-pnp
max_check_attempts 10
check_command check_nrpe_arg!60!checkCPU!warn=80 crit=90 time=5m time=1m time=30s
}

os_windows.py


Wenn aus der Datasource irgendwas rauskommt, dessen type-Feld mit .*windows.* matcht, mach ein Objekt der Klasse Windows draus

template_rules geben an, welche tpl-Files hierfür gerendert werden

$ more coshsh/recipes/default/classes/os_windows.py
from application import Application
from templaterule import TemplateRule
from util import compare_attr

def __mi_ident__(params={}):
if compare_attr("type", params, ".*windows.*"):
return Windows


class Windows(Application):
template_rules = [
TemplateRule(needsattr=None,
template="os_windows_default"),
TemplateRule(needsattr="filesystems",
template="os_windows_fs"),
]

os_windows_default.tpl



Ein tpl-File beinhaltet Platzhalter, die durch Attribute des Objekts ersetzt werden

$ more coshsh/recipes/default/templates/os_windows_default.tpl
{{ application|service("os_windows_default_check_nsclient") }}
host_name {{ application.host_name }}
use os_windows_default
check_command check_nrpe_arg!60!checkUpTime!MinWarn=5m MinCrit=1m
}

{{ application|service("os_windows_default_check_cpu") }}
host_name {{ application.host_name }}
use os_windows_default,srv-pnp
max_check_attempts 10
check_command check_nrpe_arg!60!checkCPU!warn=80 crit=90 time=5m time=1m time=30s
}

os_windows_fs.tpl



$ more coshsh/recipes/default/templates/os_windows_fs.tpl
{#
fs.path
fs.warning
fs.critical
fs.units
#}
{% for fs in application.filesystems %}
{{ application|service("os_windows_fs_check_" + fs.path) }}
host_name                       {{ application.host_name }}
use                             os_windows,srv-pnp
check_interval                  15
check_command                   check_nrpe_arg!60!CheckDriveSize!ShowAll \ 
                                MinWarnFree={{ fs.warning }}{{ fs.units }} \
                                MinCritFree={{ fs.critical }}{{ fs.units }} \
                                Drive={{ fs.path }}:
}
{% endfor %}


Wie kommt eine Applikation der Klasse Windows zu .filesystems?

Applikationsdetails


Mit diesen Details werden Applikationen genauer spezifiziert.

  • Windows/Unix-Applikationen bekommen Filesysteme
  • OnTap-Applikationen bekommen Volumes, Community
  • IOS-Applikationen bekommen Interfaces, Community
  • Apache-Applikationen bekommen URLs
  • Oracle-Applikationen bekommen Tablespaces, User, Passwort
  • ...

$ cat recipes/yns/data/officepcs_applicationdetails.csv
host_name,application_name,application_type,monitoring_type,monitoring_0,monitoring_1,... ynspc001,os,Windows,FILESYSTEM,C,20,10,,, ynspc001,os,Windows,FILESYSTEM,D,20,10,,, ynspc001,os,Windows,FILESYSTEM,F,10,5,,, ynspc002,os,Windows,FILESYSTEM,C,25,10,,,

Applicationdetails




$ cd coshsh/recipes/default/classes
$ ls detail*
detail_access.py      detail_loginsnmpv2.py  detail_socket.py
detail_datastore.py   detail_loginsnmpv3.py  detail_tablespace.py
detail_depth.py       detail_nagiosconf.py   detail_tag.py
detail_filesystem.py  detail_nagios.py       detail_url.py
detail_interface.py   detail_port.py         detail_volume.py
detail_keyvalues.py   detail_process.py
detail_login.py       detail_role.py




Eigene Applikationen


Man braucht für eine neue Applikation eine Klasse und Templates.
Die legt man in einem eigenen Verzeichnis an (nicht mit dem coshsh-Unterverzeichnis bzw. recipes/default mischen)

$ mkdir -p generator/recipes/yns/{classes, templates}

Man erweitert das Recipe um diese Pfade
[datasource_officepcs]
type = csv
dir = %HOME%/generator/recipes/yns/data

[recipe_nsmuc]
objects_dir = %HOME%/siteconfigs/office
classes = %HOME%/generator/recipes/yns/classes
templates = %HOME%/generator/recipes/yns/templates
datasources = officepcs 

Klasse für Suelzomat


Wenn man in der Datasource Applikationen stehen hat mit type=suelzomat:

$ cat generator/recipes/yns/classes/app_ns_suelzomat.py
from application import Application
from templaterule import TemplateRule
from util import compare_attr

def __mi_ident__(params={}):
    if compare_attr("type", params, ".*suelzomat.*"):
        return Windows

class Suelzomat(Application):
    template_rules = [
        TemplateRule(needsattr=None, 
            template="os_windows_default"),
    ]

Template für Suelzomat



$ cat generator/recipes/yns/templates/app_ns_suelzomat_default.tpl
{{ application|service("app_ns_suelzomat_default_check_cpu") }}
  host_name                       {{ application.host_name }}
  use                             app_ns_suelzomat_default,srv-pnp
  max_check_attempts              20
  check_command                   check_nrpe_arg!60!checkSUELZ!80!90
}
...

Datasource-Gerüst

Wir haben bereits datasource_csvfile.py nach recipes/yns/classes kopiert. Die Datei kann modifiziert werden oder als Vorlage dienen.


Mit __ds_ident__ sagt das datasource-Modul: ich fühle mich zuständig für type=csv. Meine Klasse CsvFile weiss, wie es geht.

def __ds_ident__(params={}):
    if compare_attr("type", params, "csv"):      # type = csv in coshsh.cfg
        return CsvFile 


CsvFile liest Rohdaten und bereitet diese für coshsh auf

class CsvFile(Datasource):
    def __init__(self, **kwargs):
        super(CsvFile, self).__init__(**kwargs)
        #self.name = kwargs["name"]        # [datasource_officepcs] in coshsh.csv 
        self.dir = kwargs["dir"]           # dir = %COSHSH_HOME%/.../data in coshsh.csv 
        self.objects = {}                  # wichtig, Speicher für Hosts, Apps, ..

Datasource-Methoden


Dateien, Datenbank,... öffnen

     def open(self):
logger.info('open datasource %s' % self.name)
...

Hosts und Applikationen auslesen

     def read(self, filter=None, objects={}, force=False, **kwargs):
self.objects = objects
for row in ....Records der Datasource, aus DB-Tabelle, CSV-Zeile, ...
... # Hosts lesen
h = Host(row)
self.add('hosts', h) # diesen Host "registrieren"
... # Applikationen lesen
a = Application(row)
self.add('applications', a)
... # Details lesen
if self.find('applications', a.fingerprint()):
self.get('applications', \ a.fingerprint()).monitoring_details.append(detail)


Datasource-Methoden


Optionales Schliessen der Datasource

     def close(self):
# Datenbank.close()


Fehlerbehandlung

from datasource import Datasource, DatasourceNotAvailable, DatasourceNotCurrent
...
raise DatasourceNotAvailable    # falls ein Öffnen nicht möglich ist
raise DatasourceNotCurrent      # falls keine neuen Daten vorliegen



Contacts


Registrierung im datasource_-Modul
cg = ContactGroup({ 'contactgroup_name' : 'admins' })
self.add('contactgroups', cg)
h = Host(row) h.contactgroups.append(cg) a = Application(row) a.contactgroups.append(cg)
c = Contact('lausser', 'WEBREADWRITE', 'lausser@...', 'lausser', '7x24') c.contactgroups.append('admins')

WEBREADWRITE, WEBREADONLY, MAIL, SMS

Verzeichnisstruktur



coshsh legt ein Verzeichnis dynamic unterhalb von objects_dir an
Darin gibt es die Unterverzeichnisse hosts, hostgroups, contacts, contactgroups

Jeder Host bekommt ein Unterverzeichnis mit seinem Namen unterhalb von hosts

In dieses schreibt coshsh die host.cfg, die os_*.cfg und für jede Applikation dieses Hosts die entspr. app_*.cfg


(Stichwort datarecipient: die Ausgabe kann auch mit einem eigenen Modul anders gestaltet werden)

Made with Slides.com