Lekce 2 - Aktualizace CMDB z mnoha zdrojů dat
V předchozí lekci, Proč a jak začít s Konfigurační databází (CMDB), jsme si ukázali, proč a jak začít s Konfigurační databází, s čím nám pomůže a jak se vyhneme možným problémům při implementaci.
V případě aktualizace CMDB čelíme výzvě dat přicházejících z mnoha zdrojů. Níže si ukážeme, jak k dané věci přistoupit z praktického pohledu.
Import dat
V našem příkladě budeme pracovat s entitou serverů (Machine, OS server). V CMDB budeme chtít udržovat seznam všech serverů, protože jde o zásadní konfigurační položku. Jedná se ale o obecný přístup, který můžeme uplatnit při jakýchkoli aktualizacích dat.
V ideálním světě bychom zajistili jeden aktuální soubor, který bychom importovali a pak provedli následující:
- Založili nové záznamy pro servery, které se objevily v souboru, ale ještě nebyly v CMDB.
- Aktualizovali hodnoty serverů, které byly v souboru i v CMDB.
- Smazali záznamy serverů, které jsou v CMDB, ale nejsou v souboru importu.
Všechny tyto tři operace lze jednoduše nastavit zaškrtnutím odpovídajících vlastností v definici importu. Importní soubor v CMDB ObjectGears získáme použitím infrastrukturní funkce OG_Servers. Obdobné funkcionality automatického zjištění konfiguračních položek mají i jiné CMDB. Můžeme však mít jakkoli vynikající CMDB software, ale stejně vždy narazíme na jeden problém.
Ve skutečnosti výše popsaný postup importu a aktualizace dat takto jednoduchý nebývá. Servery se nacházejí v různých sítích, u nichž nejsou nastaveny přístupy pro zajištění skenování infrastruktury. Můžeme používat více domén Active Directory, servery v různých DMZ, vysoce zabezpečené segmenty, cloud nebo sítě sesterských společností, do nichž nemáme vůbec přístup. Taková infrastruktura sítě může vypadat takto:
V takovém případě budeme mít pravděpodobně více vstupních souborů a u některých serverů se rozhodneme pro manuální aktualizaci dat.
Vytvoříme si proto více importů a v každém z nich nastavíme filtr okruhu záznamů, které budou aktualizovány. Pokud například víme, že v určitém souboru jsou všechny servery z testovací domény, nastavíme filtr importu na vlastnost serveru definující testovací doménu. Při vyhodnocení, které servery mají být smazány, se vezmou v potaz pouze servery z této domény. Bez nastavení tohoto filtru by se smazaly všechny ostatní servery (i ty mimo testovací doménu), protože nebyly v importním souboru.
Automatické smazání serverů, které nebyly v importním souboru může být problematické. Může se stát, že soubor není vyplněn správně z důvodu chyby ve skriptu nebo daný server neodpověděl na dotaz ohledně svoji konfigurace. V prvním případě můžeme využít nastavení importu. Import se neprovede, pokud import obsahuje odchylku od očekávaného množství záznamů. Druhý typ problému je vhodné řešit spíše označením záznamů, které nebyly v posledním importu a uvedením data a času posledního importu, v němž byl server nalezen. Takto lze identifikovat záznamy, u kterých bychom měli ověřit, zda nemají být smazány.
Dalším vhodným prvkem je zavedení indikátoru, zda se daný server aktualizuje manuálně. O těchto serverech budeme vědět, že se v importech nikdy neobjeví a budeme tedy muset zajistit jejich ruční aktualizaci.
Řešení problému importu z více zdrojů
Entitu serverů (nebo jinou entitu, kterou budeme chtít importovat) rozšíříme o následující vlastnosti:
Kód | Název | Typ sloupce | Popis |
manual_update | Ruční aktualizace | Ano/Ne | Vlastnost je nastavována ručně. |
present_in_last_import | Nalezen v posledním importu | Ano/Ne | Vlastnost nastavuje skript běžící po dokončení importu. Pro uživatele je pouze ke čtení. |
last_import_datetime | Datum a čas posledního importu | Datum a čas | Vlastnost nastavuje skript běžící po dokončení importu. Pro uživatele je pouze ke čtení. |
Označení záznamů importem
Označení záznamů ve sloupcích present_in_last_import a last_import_datetime zajistí skript importu (záložka Spustit po dokončení importu):
Příklad JavaScriptu, který řeší výše uvedené označení záznamů:
/* U serverů, které byly v importním souboru (matchování sloupce třídy name a sloupce souboru Name) označit pole present_in_last_import jako Ano (u ostatních serverů nastavit Ne). U těchto serverů z importního souboru také nastavit last_import_datetime na aktuální datum a čas. */ var cl = OG.ClassDef.GetById(OGActualImport.ClassDefId); var colPres = cl.Columns['present_in_last_import']; var colLast = cl.Columns['last_import_datetime']; /* present_in_last_import = Ne */ var sql = 'update datarow' + cl.Id + ' set ' + colPres.DBColumnName + ' = 0' + ' where Id not in (select LastChildDataRowId from ' + OGActualImportDbTable + ' where IsError = 0)'; OG.Sql.RunSql(sql); /* present_in_last_import = Ano, last_import_datetime = sysdate */ var sql = 'update datarow' + cl.Id + ' set ' + colPres.DBColumnName + ' = 1, ' + colLast.DBColumnName + ' = getdate() ' + ' where Id in (select LastChildDataRowId from ' + OGActualImportDbTable + ' where IsError = 0)'; OG.Sql.RunSql(sql);
Dotazy mapující kvalitu CMDB
Níže uvedené dva dotazy můžeme vložit do stránky mapující kvalitu dat v CMDB.
Dotaz pro identifikaci nově založených záznamů:
SELECT m.name, d.Name AS Datasource, m.created, '53-' + convert( varchar, m.id) AS FullId FROM {{:class.machine:}} m INNER JOIN DataSource d ON m.createddatasourceid = d.id WHERE d.referenceid IS NOT NULL and m.status IS NULL
Dotaz pro identifikaci záznamů, u nichž by mělo být prověřeno, zda nemají být smazány:
SELECT m.name, m.created, m.last_import_datetime, '53-' + convert( varchar, m.id) AS FullId FROM {{:class.machine:}} m WHERE (m.present_in_last_import IS NULL OR m.present_in_last_import = 0) AND (m.manual_update IS NULL OR m.manual_update = 0) AND m.deleted IS NULL
Notifikace o nově založených serverech
Pokud budou identifikovány nové servery a založeny odpovídající záznamy v CMDB, budeme chtít odeslat notifikaci s uvedením serverů, které byly zřízeny.
Vytvoříme si notifikaci, kterou nastavíme k odeslání po úspěšném spuštění importu:
V notifikaci na záložce Skript uvedeme následující kód:
var data = OG.GetItem('server-notif-data'); if ( OG.IsNull(data)) { // nacist id datasource var sql = OG.TextUtils.Format( "select max(id) from DataSource where ReferenceId = {0} and Name like 'Import {0}: %'", OGImport.Id); var dsId = OG.Sql.RunScalarSql(sql); // nacist z cl nove zaznamy - maji createddatasourceid, byly vytvoreny po ir.start var drf = OG.DataRow.GetDataRowFilter(OGImport.ClassDefId); drf['createddatasourceid'] = dsId; drf.AddAndCon( OG.DataRow.CreateConLe(OGImport.ClassDef.Columns['created'], OGImportRun.DateTimeStart.AddMinutes(-1))); //drf.WriteSqlToLog = true; // projet a vytvorit odkazy na dr data = 'V importu nebyl nalezen žádný nový server.'; var drl = OG.DataRow.GetDataByFilter(drf); if ( drl != null && drl.Count > 0) { data = ''; for( var i = 0; i < drl.Count; ++i) { var dr = drl[i]; data += OG.TextUtils.Format( '<a href="{2}{1}">{0}</a><br />', dr.ShortDescriptionOrFullIdEnvelope, dr.DetailUrl, OG.GetWebUrl()); } } OG.SetItem('server-notif-data', data); } OGMessage.Body = OGMessage.Body.Replace( '#SERVERY#', data);
Výsledkem bude email se seznamem serverů, které se nově objevily v importu s proklikem na příslušný záznam v CMDB.
V další lekci, Konfigurační položky CMDB, se podíváme na konfigurační položky na konkrétním příkladu serverů a hardware.