1. Skupina serverů a notifikace kontaktům

    Článek: AN0002437Aktualizováno:: 25.01.2021

    V této případové studii si popíšeme řešení zajišťující odeslání notifikací všem kontaktním osobám uvedeným u serverů, které jsou dotčené akcí zaznamenou do Provozního deníku.

    Požadavky

    Řešení má následujicí rysy:

    Každý server může mít u sebe definováno N kontaktů - viz obrazovka níže.

     

    V Provozním deníku popisujeme akci, která je plánována a která se může odkazovat na N serverů nebo skupin serverů. Příklad záznamu v Provozním deníku odkazujícím se na několik serverů a skupinu serverů je na obrázku níže.

    Skupina serverů nám slouží jako množina obsahující definované servery. Pokud se změna týká všech serverů skupiny, můžeme jednoduše vybrat skupinu místo dohledávání všech jednotlivých serverů. Příklad skupiny serverů je níže.

     

    Po vytvoření záznamu v Provozním deníku má dojít k odeslání emailů na všechny kontakty serverů uvedených v Provozním deníku přímo nebo v rámci jejich členství v uvedených skupinách serverů. Pokud se změna týká více serverů, u kterých je jako kontakt uveden ten samý uživatel, dostane daný uživatel pouze jeden email uvádějící všechny servery, kvůli nimž tento email dostal.

    Příklad textu emailu vidíme na obrázku níže

    V případě serverů, které fungují jako cluster, chceme poslat notifikace i kontaktům uvedeným u všech nódů, které jsou členy tohoto clusteru, a také všem virtuálním serverům nebo clusterovým službám běžícím na clusteru. Vztah clusteru, clusterových služeb, nódů a virtuálních serverů je vysvětlen v článku popisujícím typy serverů z pohledu Configuration management a zobrazuje ho i následující obrázek.

    Vztah clusteru, jeho nódů a na něm běžících clusterových služeb a virtuálních serverů 

     

    Řešení

    Vztahy klíčových entit zachycuje následující Entity-relationship diagram.

    Řešení spočívá v pouhých dvou objektech:

    • pravidle Po uložení nového záznamu ve třídě Provozní deník (operations log), které zajistí prohledání kontaktů všech dotčených serverů a odeslání notifikací
    • vlastní notifikaci, která definuje strukturu emailu

     Pravidlo typu Skript volající notifikaci:

    var clMachine = OGDataParent.Model.ClassDefs['machine'];
    var clMachineGroup = OGDataParent.Model.ClassDefs['machine_group'];

    //machines - pro kontrolu duplicitniho prochazeni
    var idMachines = OG.CreateIntList();

    //uzivatele - aby kazdy byl vlozen jen jednou
    var htPersons = OG.CreateHashtable(); //key PersonId, value person
    var htPersonsMachines = OG.CreateHashtable(); //key PersonId, value kolekce machines
    var idPersons = OG.CreateIntList();

    ProcessServers( OGActualDataRow.GetDR('ci'));
    AddServers_MemberOf_VirtualOn();
    SendEmails();

    //-------------------------------------------------
    function ProcessServers( drlCi)
    {
      if (!OG.IsNull(drlCi))
      {
        for( var i = 0; i < drlCi.Count; ++i)
        {
          var drCi = drlCi[i];

          if ( drCi.ChildClassDefId == clMachine.Id)
          {
            var drMachine = OG.DataRow.GetDataById(clMachine.Id, drCi.ChildDataRowId);
            ProcessMachine(drMachine);
          }
          else if ( drCi.ChildClassDefId == clMachineGroup.Id)
          {

            var drf = OG.DataRow.GetDataRowFilter(clMachine.Id);
            drf['machine_group'] = drCi.ChildDataRowId;
            var drlM = OG.DataRow.GetDataByFilter(drf);
            for( i2 = 0; i2 < drlM.Count; ++i2)
            {
              ProcessMachine(drlM[i2]);
            }
          }
        }
      }
    }

    //najit servery, ktere odkazuji na idMachines ve sloupci member_of nebo virtual_on
    function AddServers_MemberOf_VirtualOn()
    {
      var drf = OG.DataRow.GetDataRowFilter(clMachine.Id);

      var sql = 'dr' + clMachine.Id + '.' + clMachine.Columns['member-of'].DBColumnName + ' in (' +  OG.TextUtils.ConvertIntToSeparatedString(idMachines, ',', '') + ')';
      var c1 = OG.DataRow.CreateConSql(sql);
      sql = 'dr' + clMachine.Id + '.' + clMachine.Columns['virtual-on'].DBColumnName + ' in (' + OG.TextUtils.ConvertIntToSeparatedString(idMachines, ',', '') + ')';
      var c2 = OG.DataRow.CreateConSql(sql);
      drf.AddOrCon(c1, c2, true);

      var drlM = OG.DataRow.GetDataByFilter(drf);
      for( i2 = 0; i2 < drlM.Count; ++i2)
      {
        ProcessMachine(drlM[i2]);
      }
    }

    //projit machine, jen pokud jiz nebyl prochazen
    function ProcessMachine(drMachine)
    {

      //jen pokud server jeste nebyl zpracovan - aby se to nezacyklilo
      if (!OG.IsNull(drMachine) && !idMachines.Contains(drMachine.Id))
      {
        idMachines.Add(drMachine.Id);
        AddToPersonsToServer(drMachine['machine_contacts'], drMachine);
      }
    }

    //projet osoby a ke kazde pridat machine
    function AddToPersonsToServer(addPersons, drMachine)
    {
      if (!OG.IsNull(addPersons))
      {
        for( var i = 0; i < addPersons.Count; ++i)
        {
          var p = addPersons[i];
          if (!idPersons.Contains(p.Id))
          {
            idPersons.Add(p.Id);
            htPersons[p.Id] = p;
            htPersonsMachines[p.Id] = OG.DataRow.CreateNewList();
          }
          htPersonsMachines[p.Id].Add(drMachine);
        }
      }
    }

    //odeslat emaily - kazdenu useru jen jeho servery
    function SendEmails()
    {
      var nAll = OG.Notification.GetAll().GetByModelId( OGDataParent.Model.Id, false);
      var n = nAll.GetDefaultByCode(OGDataParent.Model.Id, 'operations_log');

      for( var i = 0; i < idPersons.Count; ++i)
      {
        var p = htPersons[idPersons[i]];
        var machines = htPersonsMachines[idPersons[i]];
        var machinesEI = machines.ToEntityInfoList();
        machinesEI.SortByDisplayName();

        //vytvorit email
        var m = OG.Email.CreateMessage();
        m.AddTo(p);
        m.AssignEmailForDataRow = OGActualDataRow;
        m.SendEmailAsOne = false; //odeslat kazdemu svuj email

        var p2 = OG.Person.GetById(p.Id);

        if ( OG.IsNull(p2.NotificationLanguageId))
        {
          m.Notification = n;
        }
        else
        {
          m.Notification = nAll.GetByCodeLanguage( 'operations_log', p2.NotificationLanguageId);
        }

        //vlozit servery
        var ids = OG.CreateIntList();
        var s = '';
        for( im = 0; im < machinesEI.Count; ++im)
        {
          //kontrola aby byl server v seznamu jen jednou
          if (!ids.Contains(machinesEI[im].Id))
          {
            ids.Add(machinesEI[im].Id);
            if ( im > 0)
            {
              s += ', ';
            }
            s += machinesEI[im].DisplayName;
          }
        }
        m.AddVariable( 'servers', s);

        //odeslat email
        OG.Email.Send(m);
      }
    }

     

    Notifikace používaná skriptem:

×