Ad Widget

Collapse

Расширяем snmp lld скриптами

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Jimson
    Senior Member
    • Jan 2008
    • 1327

    #46
    В продолжении темы, а точнее апдейт срипта и шаблонов, а так же принципа "фильтрации".

    1) Я изначально все это задумывал с таким расчетом что бы можно было не только эзернет свичи опрашивать, но и MPLS маршрутизаторы. Если я "натравлю" SNMP_Interfaces шаблон на PE router, то получу сотни интерфейсов у одного хоста и большинство этих интерфейсов будут линки на клиеские CE routers. Смысл такого "мега хоста" лично от меня ускользает, для мониторинга бэкбона достаточно мониторить только собственные физические линки, а для мониторинга клиенских VRF нужно "разделить" этот PE на кучу хостов (один хост - один VRF), в этом случае можно и клиенту показать этот хост и схему для клиента сделать.

    2) Фильтрация LLD через стандартный механизм регулярных выражений не удобна. Простой пример, у нас есть шаблон универсальный, мы можем маркировать интерфейсы (на оборудовании которое поддерживает изменение дескрипшенов через конфиг), все клево, но есть оборудование на котором нужно мониторить только интерфейсы определенного типа и дескрипшены оно не поддержкивает. В моем случае появились какие то мотороловские WiFi точки, нужно снимать данные только с интерфейсов radio1 и radio2. Как быть?
    Первое решение это сделать "наследника" от SNMP_Interfaces и изменить фильтр, но если вы после этого начнете менять фильтр SNMP_Interfaces то он обновится и у "наследника". Следить за этим стремно.

    3) Наглядная демострация использования макросов, как на мой взгляд нужно делать универсальные шаблоны.

    Итак.

    a) Глобальный regex я использую в качестве шаблона LLD только для разделения Counter64/Counter32 интерфейсов, для детекта "физических" интерфейсов и для отфильтровки AdminDown.

    b) Макрос {$LLD_IF_FLAG} перенесен в шаблон, смысла его объявлять глобально не вижу, лучше пусть будет все в одном месте. Значение по умолчанию '[D]' - если эта подстрока есть в дескрипшене интерфейса то шаблон "увидит" этот интерфейс. Этот макрос теперь можно "отключить", если значение этого макроса пустая строка или 0 (ноль), то скрипт не пытается искать подстроку и при этом считает что все интерфейсы "помечены". По другому скажу: если макрос переопределен в 0, то скрипт для всех интерфейсов добавит ",FLAG," в {#IFTAGS}, а следовательно глобальное регулярное выражение (см. пункт a) дает совпадение со всеми интерфейсами.

    c) Макрос дополнительной фильтрации {$LLD_IF_REGEX}. Скрипт не проверяет валидность этого агрумента, будьте аккуратны. Фильтрация осуществляется через обычный перловый regexp по {#IFTAGS}. Значение по умолчанию 0 (ноль), срипт ничего не сравнивает и не отфильтровывает.

    В качестве примера по пунктам a, b, и c: мне нужно для определенного хоста отмониторить интерфейсы radio1 и radio2, при этом маркировать через дескрипшен я не могу или не хочу. В таком случае для этого хоста мы переопределяем макросы:
    {$LLD_IF_FLAG} = 0
    {$LLD_IF_REGEX} = ,radio[12],
    Мы отключили фильтрацию по "флагу" в дескрипшене и включили обычную regex фильтрацию. В JSON мы получим два объекта, интерфейсы radio1 и radio2.

    d) Новый макрос {$MPLS_VRF_RD} для фильтрации по RD (объяснять что такое RD не буду, кому надо и так знают). По умолчанию значение 0, т.е. фильтрация отключена и скрипт не "выкачивает" требуемые для этой фильтрации индексы.

    Приведу пример. Есть у нас хост BIG_PE_RTR, адрес у него 10.0.0.1, интерфейсы мониторим через шаблон, макросы стандартные. Таким образом на хосте BIG_PE_RTR у нас отдискаверятся только интерфейсы у которых в дескрипшене установлен флаг '[D]', а выставим мы этот флаг только на бэкбонных интерфейсах, в том числе на всяких там транках на Трастелеком, Ростелеком, Комкор и прочих, а вот интерфейсы в сторону CE мы помечать не станем.
    Затем мы создадим еще один хост BIG_PE_RTR_VPN123, адрес у него будет тот же 10.0.0.1, и макросы мы у него зададим следующие:
    {$LLD_IF_FLAG} = 0
    {$MPLS_VRF_RD} = 12345:123
    Итак, мы отключили фильтрацию по флагу, и включили фильтрацию по RD. В итоге на хосте BIG_PE_RTR_VPN123 у нас задискаверятся только те интерфейсы, которые "ip forwarded vrf VPN123", а точнее те которые forwarded в VRF с RD равным "12345:123". Вуаля.

    e) Используем макросы в триггерах.
    {$IF_LOAD_HYSTERESIS} = 0.10
    {$IF_LOAD_THRESHOLD} = 0.75
    Несколько триггеров в шаблоне, проверяем загрузку интерфейсов, смысл макросов думаю понятен, как и то что мы их можем переопределять как на хостах, так и сделав шаблон-наследник. Загрузка сравнивается с ifSpeed/ifHCSpeed, который в свою очередь вы можете задать явно в конфигурации оборудовании, ну во всяком случае на cisco IOS параметр bandwidth поддерживается для всех интерфейсов в том числе для сабинтерфейсов. По умолчанию ifSpeed равен скорости интерфейса.

    P.S. Если кто то решит "апгрейдится", то сразу предупреждаю, что простая замена "шаблона" поломает вам дискаверинг, будете плакать. Связано это с тем что отдискаверенные элементы "привязаны" к ID правила дискаверинга, следовательно что бы все проапгрейдилось как надо правила дискаверинга (ключи этих элементов) не должны изменится. Ключем для правила дискаверинга как и для любой "внешней проверки" выступает сам скрипт с параметрами. Вообщем я поменял и имя скрипта и добавил параметры, так что просто так нифига не получится. Что бы "проапгрейдится" прийдется отключить шаблон без удаления элементов, затем вручную изменить правила LLD (можно предварительно деактивировать само правило LLD, а затем уже спокойно менять), изменяем "ключ" правила через cut&paste, иначе кто то точно будет плакать, ну и затем подключаем новый шаблон. Если новый шаблон подключился и при этом у нас не создались новые правила, а старые при этом получили принадлежность шаблону, значит у вас все получилось.
    Attached Files

    Comment

    • Melanxolik
      Senior Member
      • Nov 2009
      • 174

      #47
      Jimson, подскажи пожалуйста, пытаюсь понять как работает старый скрипт, сейчас столкнулся с тем что есть железка которая нормально дисковерится но счетчики такое чувство что видятся с неё только 32битные через скрипт, хотя умеет она 64битные, как это можно отследить и разобрать?

      Comment

      • Jimson
        Senior Member
        • Jan 2008
        • 1327

        #48
        По ключам элементов данных вы можете опеределить что создалось, у 64 битных в ключе будет "HC".

        Скрипт при генерации JSON для LLD выбирает по SNMP несколько "индексных" деревьев, в том числе ifHCInOctets (.1.3.6.1.2.1.31.1.1.1.6), затем для каждого интерфейса в отдельности проверяет, если этот интерфейс был в дереве ifHCInOctets, значит для него определены 64 битный счетчики, и в {#IFTAGS} добавляется метка ",Counter64,".

        В шаблоне, который я давал, три правила, все три обрабатывают один и тот же JSON, первое правило отфильтрует только интерфейсы с меткой ",Counter64," в {#IFTAGS} и создаст элементы данных по 64 битным счетчикам, второе правило отфильтрует все интерфейсы у которых НЕТ метки ",Counter64," и создаст им элементы данных по 32 битным счетчикам, третье правило отфильтрует все элементы у которых есть метка ",Physical," и создаст для этих интерфейсов элементы данных ifErrors и тп.

        Такая логика дискаверинга обусловленна тем что наличие 64 битных счетчиков определяется не только железкой (роутером), но и тем что это за интерфейс, для low speed интерфейсов как прапвило 64 битных счетчиков нету, например, у вас на роутере есть GigabitEthernet порты и серийные 2 мегабитные порты (E1 контроллеры, как вариант, или V.35), для эзернет интерфейсов 64 разрядные SNMP будут опеределены, а для серийников нет. Соответсвенно мой шаблон сгенерит для эзернета "HC" элементы данных, а для серийных портов обычные.

        Comment

        • OKyHb
          Senior Member
          • Sep 2010
          • 103

          #49
          Хочется использовать LLD для мониторинга BGP сессий на Juniper. При чём не просто Established/Idle... , но и к-во полученных и отправленных префиксов. Думал сделать на основе cisco_ifindex.pl, но возникли проблемы уже с самим snmp. Может кто из более опытных коллег подскажет ...

          Использую таблицу BGP4-V2-MIB-JUNIPER::jnxBgpM2PeerTable. На примере одного пира:

          Code:
          15:31:05 osa@zinc[6]~>snmpwalk -On 10.0.255.1 BGP4-V2-MIB-JUNIPER::jnxBgpM2PeerTable | grep 195.35.65.11
          .1.3.6.1.4.1.2636.5.1.1.2.1.1.1.1.7.1.195.35.65.92.1.195.35.65.11 = STRING: 195.35.65.11
          .1.3.6.1.4.1.2636.5.1.1.2.1.1.1.2.7.1.195.35.65.92.1.195.35.65.11 = INTEGER: established(6)
          .1.3.6.1.4.1.2636.5.1.1.2.1.1.1.3.7.1.195.35.65.92.1.195.35.65.11 = INTEGER: running(2)
          .1.3.6.1.4.1.2636.5.1.1.2.1.1.1.4.7.1.195.35.65.92.1.195.35.65.11 = Gauge32: 4
          .1.3.6.1.4.1.2636.5.1.1.2.1.1.1.5.7.1.195.35.65.92.1.195.35.65.11 = Gauge32: 0
          .1.3.6.1.4.1.2636.5.1.1.2.1.1.1.6.7.1.195.35.65.92.1.195.35.65.11 = INTEGER: ipv4(1)
          .1.3.6.1.4.1.2636.5.1.1.2.1.1.1.7.7.1.195.35.65.92.1.195.35.65.11 = Hex-STRING: C3 23 41 5C 
          .1.3.6.1.4.1.2636.5.1.1.2.1.1.1.8.7.1.195.35.65.92.1.195.35.65.11 = Gauge32: 179
          .1.3.6.1.4.1.2636.5.1.1.2.1.1.1.9.7.1.195.35.65.92.1.195.35.65.11 = Gauge32: 39608
          .1.3.6.1.4.1.2636.5.1.1.2.1.1.1.10.7.1.195.35.65.92.1.195.35.65.11 = INTEGER: ipv4(1)
          .1.3.6.1.4.1.2636.5.1.1.2.1.1.1.11.7.1.195.35.65.92.1.195.35.65.11 = Hex-STRING: C3 23 41 0B 
          .1.3.6.1.4.1.2636.5.1.1.2.1.1.1.12.7.1.195.35.65.92.1.195.35.65.11 = Gauge32: 35770
          .1.3.6.1.4.1.2636.5.1.1.2.1.1.1.13.7.1.195.35.65.92.1.195.35.65.11 = Gauge32: 15645
          .1.3.6.1.4.1.2636.5.1.1.2.1.1.1.14.7.1.195.35.65.92.1.195.35.65.11 = Gauge32: 20
          .1.3.6.1.4.1.2636.5.1.1.2.1.1.1.15.7.1.195.35.65.92.1.195.35.65.11 = Gauge32: 7
          При этом одиночный snmpget с такими значениями не работает. Пробую проверить jnxBgpM2PeerStatus:
          Code:
          15:31:12 osa@zinc[6]~>snmpget 10.0.255.1 .1.3.6.1.4.1.2636.5.1.1.2.1.1.1.2.7.1.195.35.65.92.1.195.35.65.11
          
          .1.3.6.1.4.1.2636.5.1.1.2.1.1.1.2.7.1.195.35.65.92.1.195.35.65.11: Unknown Object Identifier (Index out of range: 195 (jnxBgpM2PeerLocalAddr))
          Как правильно формировать snmp-oid'ы для полученния данных из этой таблицы, чтоб потом это можно было скормить zabbix'у?

          UPD: Вывод куска snmpwalk в читабельном виде:

          Code:
          15:52:10 osa@zinc[6]~>snmpwalk 10.0.255.1 BGP4-V2-MIB-JUNIPER::jnxBgpM2PeerTable | grep 195.35.65.11
          BGP4-V2-MIB-JUNIPER::jnxBgpM2PeerIdentifier.7.ipv4.195.35.65.92.1.195.35.65.11 = STRING: 195.35.65.11
          BGP4-V2-MIB-JUNIPER::jnxBgpM2PeerState.7.ipv4.195.35.65.92.1.195.35.65.11 = INTEGER: established(6)
          BGP4-V2-MIB-JUNIPER::jnxBgpM2PeerStatus.7.ipv4.195.35.65.92.1.195.35.65.11 = INTEGER: running(2)
          BGP4-V2-MIB-JUNIPER::jnxBgpM2PeerConfiguredVersion.7.ipv4.195.35.65.92.1.195.35.65.11 = Gauge32: 4
          BGP4-V2-MIB-JUNIPER::jnxBgpM2PeerLocalAddrType.7.ipv4.195.35.65.92.1.195.35.65.11 = INTEGER: ipv4(1)
          BGP4-V2-MIB-JUNIPER::jnxBgpM2PeerLocalAddr.7.ipv4.195.35.65.92.1.195.35.65.11 = Hex-STRING: C3 23 41 5C 
          BGP4-V2-MIB-JUNIPER::jnxBgpM2PeerRemoteAddrType.7.ipv4.195.35.65.92.1.195.35.65.11 = INTEGER: ipv4(1)
          BGP4-V2-MIB-JUNIPER::jnxBgpM2PeerRemoteAddr.7.ipv4.195.35.65.92.1.195.35.65.11 = Hex-STRING: C3 23 41 0B 
          BGP4-V2-MIB-JUNIPER::jnxBgpM2PeerIndex.7.ipv4.195.35.65.92.1.195.35.65.11 = Gauge32: 20
          BGP4-V2-MIB-JUNIPER::jnxBgpM2PeerRoutingInstance.7.ipv4.195.35.65.92.1.195.35.65.11 = Gauge32: 7
          Last edited by OKyHb; 29-08-2013, 14:54. Reason: читабельный snmpwalk

          Comment

          • OKyHb
            Senior Member
            • Sep 2010
            • 103

            #50
            Всё, прошу прощения за офтоп и глупые вопросы.
            Если не загружать mib (mib-jnx-bgpmib2.txt) и так же запрашивать тупо oid - всё ок.

            Comment

            • Melanxolik
              Senior Member
              • Nov 2009
              • 174

              #51
              Jimson, был бы признаттелен за помощь в настройки новой версии скрипта.
              Старая работает на ура, но если ты делаешь, значит есть что-то интересное.

              Импортировал template, положил скрипт, при запуске вручную выдает кучу данных, а вот в самом забикс item не появляются.
              В логе увидел такую строку:

              95227:20130913:104155.207 invalid discovery rule ID [27714]

              И дальше тишина, ничего нету по поводу этого хоста.

              Comment

              • Jimson
                Senior Member
                • Jan 2008
                • 1327

                #52
                Сорри, в отпуске был. Давай подробнее. Запуск в ручную тоже должен работать на ура. Пример:
                Code:
                msk-be-srv-zbx[jimson]:.../mibs $ /usr/local/etc/zabbix/externalscripts/cisco_ifmib.pl
                Usage: /usr/local/etc/zabbix/externalscripts/cisco_ifmib.pl <host> <port> <community> [RD] [flag] [regex]
                
                msk-be-srv-zbx[jimson]:.../mibs $ /usr/local/etc/zabbix/externalscripts/cisco_ifmib.pl 0.0.1.1 161 community | wc -l
                     172
                
                msk-be-srv-zbx[jimson]:.../mibs $ /usr/local/etc/zabbix/externalscripts/cisco_ifmib.pl 0.0.1.1 161 community 0 '[D]' | grep ',FLAG,'
                {"{#IFINDEX}":"2","{#IFDESCR}":"GigabitEthernet0/1","{#IFTAGS}":",GigabitEthernet0/1,Type:6,AdminStatus:up,Physical,Counter64,FLAG,","{#IFALIAS}":"msk-be-rtr-brd_Gi0/3"},
                {"{#IFINDEX}":"5","{#IFDESCR}":"GigabitEthernet0/3","{#IFTAGS}":",GigabitEthernet0/3,Type:6,AdminStatus:up,Physical,Counter64,FLAG,","{#IFALIAS}":"trunk_to_msk-m9-rtr_Gi0/1 via msk-be-omux_Gi1"},
                {"{#IFINDEX}":"4","{#IFDESCR}":"GigabitEthernet0/2","{#IFTAGS}":",GigabitEthernet0/2,Type:6,AdminStatus:up,Physical,Counter64,FLAG,","{#IFALIAS}":"trunk_to_3550_Fa0/1"},
                
                msk-be-srv-zbx[jimson]:.../mibs $ /usr/local/etc/zabbix/externalscripts/cisco_ifmib.pl 0.0.1.1 161 community 'AS:203'
                {"data":[
                {"{#IFINDEX}":"84","{#IFDESCR}":"GigabitEthernet0/2.203","{#IFTAGS}":",GigabitEthernet0/2.203,Type:135,AdminStatus:up,Counter64,FLAG,","{#IFALIAS}":"VPN203 description"},
                {"{#IFINDEX}":"164","{#IFDESCR}":"GigabitEthernet0/2.156","{#IFTAGS}":",GigabitEthernet0/2.156,Type:135,AdminStatus:up,Counter64,FLAG,","{#IFALIAS}":"VPN203 other description"},
                ]}
                
                msk-be-srv-zbx[jimson]:.../mibs $ /usr/local/etc/zabbix/externalscripts/cisco_ifmib.pl 0.0.1.1 161 community 'AS:203' '[D]'
                {"data":[
                {"{#IFINDEX}":"84","{#IFDESCR}":"GigabitEthernet0/2.203","{#IFTAGS}":",GigabitEthernet0/2.203,Type:135,AdminStatus:up,Counter64,","{#IFALIAS}":"VPN203 description"},
                {"{#IFINDEX}":"164","{#IFDESCR}":"GigabitEthernet0/2.156","{#IFTAGS}":",GigabitEthernet0/2.156,Type:135,AdminStatus:up,Counter64,","{#IFALIAS}":"VPN203 other description"},
                ]}
                
                msk-be-srv-zbx[jimson]:.../mibs $ /usr/local/etc/zabbix/externalscripts/cisco_ifmib.pl 0.0.1.1 161 community 'AS:203' 0 '0/2.156'
                {"data":[
                {"{#IFINDEX}":"164","{#IFDESCR}":"GigabitEthernet0/2.156","{#IFTAGS}":",GigabitEthernet0/2.156,Type:135,AdminStatus:up,Counter64,FLAG,","{#IFALIAS}":"VPN203 other description"},
                ]}

                Comment

                • Melanxolik
                  Senior Member
                  • Nov 2009
                  • 174

                  #53
                  Jimson, извините, нашел свой недочет, это глобальные регулярные выражения, добавил их и заработало.
                  Но вылезло следующее:
                  IF-MIB HC: In Broadcast Packets on ge-0/0/5
                  IF-MIB HC: In Broadcast Packets on ge-0/0/5.0

                  это Juniper, подскажите как лучше изменить систему так чтобы мониторились только физические интерфейсы, а логические только по надобности.
                  Раньше конечно писал примерно так:
                  (Type:6,AdminStatus:up), а как лучше почтупить сейчас?
                  Стараюсь понять логику системы.

                  Comment

                  • Melanxolik
                    Senior Member
                    • Nov 2009
                    • 174

                    #54
                    О. Добавил для каждого хоста макрос: {$LLD_IF_REGEX}=Type:6,AdminStatus:up

                    Comment

                    • Jimson
                      Senior Member
                      • Jan 2008
                      • 1327

                      #55
                      Originally posted by Melanxolik
                      это Juniper, подскажите как лучше изменить систему так чтобы мониторились только физические интерфейсы, а логические только по надобности.
                      Раньше конечно писал примерно так:
                      (Type:6,AdminStatus:up), а как лучше почтупить сейчас?
                      Стараюсь понять логику системы.
                      Для физических интерфейсов у меня есть отдельный "тэг" - Physical, он появляется в {#IFTAGS} если для интерфейса существует ifInErrors (.1.3.6.1.2.1.2.2.1.14). Собственно по этому тэгу (через глобальное регулярное выражение) интерфейс "попадает" в третье правило дискаверинга в шаблоне, и по этому "третьему правилу" создаются элементы данных характерные для реальных (физических) интерфейсов, как то if*Errors и if*Discard.

                      А в целом вы все правильно поняли, {$LLD_IF_REGEX} для простого механизма фильтрации уникальной для хоста. Вот только AdminStatus лишний, в глобальных регулярных выражениях он проверяется, так что или просто ',Type:6,' в качестве маски используйте для выборки физических ethernet интерфейсов, или ',Physical,' для более общего фильтра, который даст список всех "физических" интерфейсов, и эзернеты, и атм, и serial, etc.

                      Comment

                      • Melanxolik
                        Senior Member
                        • Nov 2009
                        • 174

                        #56
                        Смотрите, в прототипах не хватает элемента ifAlias, если интересно, опишу как у меня сделано:

                        так как в сети много тригеров, то правила выглядят примерно так:

                        {SNMP_Interfaces_LLD_scripts:ifInUnicastPPS[{#IFDESCR}].max(60)}>307200 & {SNMP_Interfaces_LLD_scripts:ifSpeed[{#IFDESCR}].last(0)}=1000000000 & {SNMP_Interfaces_LLD_scripts:sysName.str(magistral )}=1 & {SNMP_Interfaces_LLD_scripts:ifAlias[{#IFINDEX}].str(ITSAS1)}#1 & {SNMP_Interfaces_LLD_scripts:ifAlias[{#IFINDEX}].str(PROV1)}#1 & {SNMP_Interfaces_LLD_scripts:ifAlias[{#IFINDEX}].str(toJuniper)}#1
                        С помощью такой мощной комбинации формирую правило по куче критериев и дальше разруливаю, что удобно это динамика, хотя вычислений много.

                        Сейчас возник еще один интересный вопрос. В стандартной реализации чтобы вывести текущее значение, требуется в имя тригера дописать: CURENT:{ITEM.VALUE}, но проблема в том что в случае протитипов почему-то прилетает hostname, интересно есть ли способ динамически получать текущее значение в имени тригера?

                        Comment

                        • Jimson
                          Senior Member
                          • Jan 2008
                          • 1327

                          #57
                          В моем шаблоне действительно нет ifAlias, добавьте если вам нужно, это же шаблон. Собственно сам шаблон я прикрепил только в качестве примера того как дискаверить разнотипные интерфейсы одним шаблоном (поддерживающие 64 счетчики, не поддерживающие, физические интерфейсы или виртуальные/сабы).

                          По второму вопросу, в моем примере шаблона есть пара триггеров на проверку загрузки интерфейса и там используется {ITEM.VALUE}. Это работает, у меня работает на 2.0.6rc1. Или я не понял вопроса?

                          Comment

                          • Melanxolik
                            Senior Member
                            • Nov 2009
                            • 174

                            #58
                            Перепроверил.
                            Имя тригера:
                            wan in {hostname} over 500mbit/s {#ifdescr} {item.value}
                            возвращает:
                            wan out jmx-1.dc.ff.net-core over 500mbit/s ge-1/0/0 jmx-1.dc.ff.net
                            Вместо того чтобы вернуть текущее значение загрузки порта.

                            Comment

                            • dima_dm
                              Senior Member
                              • Dec 2009
                              • 2697

                              #59
                              Jimson, исправил баг в скрипте.
                              Если в дискрипшине интерфейса встречается символ ", он портит json структуру на выходе скрипта.
                              Code:
                              diff -u cisco_ifmib.pl.old cisco_ifmib.pl
                              --- cisco_ifmib.pl.old  2013-09-20 11:08:00.276264451 +0400
                              +++ cisco_ifmib.pl      2013-09-18 10:45:06.137264318 +0400
                              @@ -115,6 +115,7 @@
                                       $alias = $_->val;
                                       if (not $FLAG or $alias =~ s/^(.*)$FLAG\s*/$1/o) {
                                           $alias =~ s/\s*$//o;
                              +           $alias =~ s/"//g;
                                           $json{ $_->iid }->{IFTAGS} .= "FLAG" . TAGSEP;
                                       }
                                       $json{ $_->iid }->{IFALIAS} = $alias;

                              Comment

                              • Jimson
                                Senior Member
                                • Jan 2008
                                • 1327

                                #60
                                Спасибо. А если на &quot; замену делать интерфейс забикса не отобразит кавычку?

                                Comment

                                Working...