Тесты работоспособности
Самым простым вариантом проверки может служить скрипт, совершающий периодически тестовые вызовы и проверяющий их результат.
Возможная схема организации с помощью утилиты sipp
- на АТС заводится клиент, который будет использован для тестовых вызовов. Допустим, получился клиент с префиксом 0012
- клиенту добавляется добавочный типа "phone" и "ivr" (например, 100 и 099 соответственно)
- добавочному 100 даются права для возможности принудительной отправки вызовов через медиасервера; для простоты тестирования добавочному 100 выставляется авторизацию по ip (с адреса, откуда идет тестирование)
- от имени добавочного 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>