1. Aktualizace CMDB z mnoha zdrojů dat

    Článek: AN0002432Aktualizováno:: 29.05.2020

    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.

    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 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 importním souboru.

    Všechny tyto tři operace, lze jednoduše nastavit zaškrtnutím odpovídajících vlastností v definici importu. Importní soubor bychom získali použitím infrastrukturní funkce OG_Servers.

    Ve skutečnosti tento scénář takto jednoduchý nebývá. Servery se nacházejí v různých sítích, u nichž nejsou nastaveny prostupy pro zajištění skenu infrastruktury. Můžeme používat více domén Active Directory, servery jsou v různých DMZ, vysoce zabezpečených segmentech, v cloudu nebo v sítích sesterských společností, do nichž nemáme vůbec přístup.

    V takovém případě budeme mít pravděpodobně více vstupních souborů a u některých serverů se rozhodeme 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í doménu a při vyhodocení, 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é, protože se může stát, že soubor není vyplněn správně z důvodu chyby ve skriptu nebo proto, že daný server neodpověděl na dotaz ohledně svoji konfigurace. V prvním případě můžeme využít nastavení importu, které import neprovede, pokud import obsahuje odchylku od očekávaného množství zázamů. 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) tedy 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):

    /*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 z emailu na příslušný záznam v CMDB.

×