Тесты работоспособности

Самым простым вариантом проверки может служить скрипт, совершающий периодически тестовые вызовы и проверяющий их результат.

Возможная схема организации с помощью утилиты sipp

  1. на АТС заводится клиент, который будет использован для тестовых вызовов. Допустим, получился клиент с префиксом 0012
  2. клиенту добавляется добавочный типа "phone" и "ivr" (например, 100 и 099 соответственно)
  3. добавочному 100 даются права для возможности принудительной отправки вызовов через медиасервера; для простоты тестирования добавочному 100 выставляется авторизацию по ip (с адреса, откуда идет тестирование)
  4. от имени добавочного 100 последовательно на все медиасервера делается вызов в ivr 099 и проверяется результат.

В примере ниже скрипт проверяет возможность дозвона до ivr через медиасервера, перечисленные в списке "checklist"  (префиксы принудительного набора определены параметром "prefix"). Скрипт запоминает результат последней проверки и отсылает сообщение на список адресов из "maillist" в случае изменения статуса.

пример скрипта с анализом работы sipp
#! /usr/bin/python
# -*- coding: utf-8 -*-

import subprocess
import re
import sys
import smtplib
from email.mime.text import MIMEText
import pickle
import os
import datetime

status_file = "mystatus_file.txt"
from_mail = "admin@host.domain"
maillist = ["admin2@host.domain", "admin@host.domain"]
checklist = []
checklist.append({"prefix": "07", "name": "media server 1"})
checklist.append({"prefix": "08", "name": "media server 2"})
sip_address = "sip.host.domain"

cmd_template = "/usr/bin/sipp -sf sip_scen.xml -timeout 10s -f 100 -nostdin -m 1 -s **0908{node_prefix}0012*099 " + sip_address

def send_notify(node, new_staus, out, err, cmd):

    event = "DOWN {node_name}".format(node_name=node["name"])
    if new_staus == "OK":
        event = "UP {node_name}".format(node_name=node["name"])

    for mail in maillist:
        try:
            msg = MIMEText("error from {cmd}:{err}\noutput:{out}".format(cmd=cmd, err=err, out=out), 'plain', 'utf-8')
            msg['Subject'] = event
            msg['From'] = from_mail
            msg['To'] = mail

            s = smtplib.SMTP('localhost')
            s.sendmail(from_mail, [mail], msg.as_string())
            s.quit()
        except Exception as e:
            print e


print datetime.datetime.now()

# get prev check
prev_result = {}
try:
    with open(status_file) as f:
        prev_result = pickle.load(f)
except IOError:
    pass


check_re = re.compile("""Successful call\s+\|\s+0\s+\|\s+1""")
result = {}
os.environ["TERM"] = "xterm" 
for node in checklist:
    node_prefix = node["prefix"]
    cmd = cmd_template.format(node_prefix=node_prefix)
    p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out, err = p.communicate()
    if not check_re.search(out):
        result[node_prefix] = "FAILED"
    else:
        result[node_prefix] = "OK"

    prev = ""
    if isinstance(prev_result, dict):
        prev = prev_result.get(node_prefix, "")
    try:
        if result[node_prefix] != prev:
            print "{prefix} new status != old ({new}!={old}); send notify!".format(prefix=node_prefix, new=result[node_prefix], old=prev)
            send_notify(node, result[node_prefix], out, err, cmd)
        else:
            print "{prefix} new status == old ({new}=={old}); skip notify...".format(prefix=node_prefix, new=result[node_prefix], old=prev)
    except Exception as e:
        print e
        pass

# save new values
with open(status_file, 'w') as f:
    pickle.dump(result, f)


 Сценарий для sipp (используется версия 3.4). Тут строки  "0012*100@sip.host.domain" нужно заменить на соотвествующие добавочному типа "phone".  Для добавочного подразумевается авторизация по ip.

sip_scen.xml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE scenario SYSTEM "sipp.dtd">


<scenario name="Ringme Media Server Tester">
  <!-- In client mode (sipp placing calls), the Call-ID MUST be         -->
  <!-- generated by sipp. To do so, use [call_id] keyword.                -->
  <send retrans="500">
    <![CDATA[

      INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
      Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
      From: sipp <sip:0012*100@sip.host.domain>;tag=zzzzz[pid]SIPpTag00[call_number]
      To: [service] <sip:[service]@[remote_ip]:[remote_port]>
      Call-ID: [call_id]
      CSeq: 1 INVITE
      Contact: sip:0012*100@[local_ip]:[local_port]
      Max-Forwards: 70
      Content-Type: application/sdp
      Content-Length: [len]

      v=0
      o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
      s=-
      c=IN IP[media_ip_type] [media_ip]
      t=0 0
      m=audio [media_port] RTP/AVP 0
      a=rtpmap:0 PCMU/8000

    ]]>
  </send>

  <recv response="100" optional="true"  timeout="3000">
  </recv>

  <recv response="180" optional="true"  timeout="3000">
  </recv>

  <recv response="183" optional="true"  timeout="3000">
  </recv>

  <!-- By adding rrs="true" (Record Route Sets), the route sets         -->
  <!-- are saved and used for following messages sent. Useful to test   -->
  <!-- against stateful SIP proxies/B2BUAs.                             -->
  <recv response="200" rtd="true" rrs="true"  timeout="3000">
  </recv>

  <!-- Packet lost can be simulated in any send/recv message by         -->
  <!-- by adding the 'lost = "10"'. Value can be [1-100] percent.       -->
  <send>
    <![CDATA[

      ACK [next_url] SIP/2.0
      Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
      From: sipp <sip:0012*100@sip.host.domain>;tag=zzzzz[pid]SIPpTag00[call_number]
      To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
      Call-ID: [call_id]
      [routes]
      CSeq: 1 ACK
      Contact: sip:0012*100@[local_ip]:[local_port]
      Max-Forwards: 70
      Content-Length: 0

    ]]>
  </send>



  <recv request="BYE">
  </recv>

  <send>
    <![CDATA[

      SIP/2.0 200 OK
      [last_Via:]
      [last_From:]
      [last_To:]
      [last_Call-ID:]
      [last_CSeq:]
      Contact: <sip:[local_ip]:[local_port];transport=[transport]>
      Content-Length: 0

    ]]>
  </send>
 

  <!-- definition of the response time repartition table (unit is ms)   -->
  <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>

  <!-- definition of the call length repartition table (unit is ms)     -->
  <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>

</scenario>