Photo de famille aka 'Big picture'

Pour un téléphone (encore dans son emballage) à attribuer/déployer/allouer, vous ouvrez une interface web (ou lancez un script CLI) muni de votre douchette code barre (genre douchette USB clavier à deux balles ... Vous n'en avez pas? Bah tappez l'adresse MAC, c'est pas très difficile non plus):

L'application django/YMMV effectue les opérations suivantes:

Dés que le téléphone est connecté, il télécharge son fichier identifié par son MAC après la danse DHCP et il est prêt à opérer.

Modèle Django et schéma asterisk

Les modèles django sont plus ou moins calqués sur les schéma utilisés par les différents pilotes de stockage utilisés par “Asterisk Realtime Architecture" ARA (http://www.voip-info.org/wiki/view/Asterisk+RealTime Dommage mais bon ça va changer un jour aussi grâce à ce que Tom apelle l'effet Obama Heu!)

#-*- coding: utf-8 -*-
from django.db import models

from django.db import models
from django.contrib import admin
from django.template.loader import render_to_string
from django.template import loader, Context
from django.utils.encoding import smart_str
from datetime import datetime

# Le mot de passe utilisé par le téléphone pour s'authentifier auprès
# d'Asterisk, Bah qui en a besoin en dehors des deux parties?
def make_pass():
    return 'Pas très difficile de générer des mots de passe du tout'

# celui-ci a l'id qui va bien comme serial deja
class ExtensionsConf(models.Model):
    context = models.CharField(blank=True, null=True, max_length=256)
    exten = models.CharField(blank=True, null=True, max_length=256)
    priority = models.CharField(blank=True, null=True, max_length=256)
    app = models.CharField(blank=True, null=True, max_length=256)
    appdata = models.CharField(blank=True, null=True, max_length=1024)
    class Meta:
        db_table = u'extensions_conf'
admin.site.register(ExtensionsConf)

class VoicemailUsers(models.Model):
    customer_id = models.IntegerField(default=0)
    context = models.CharField(blank=True, null=True, max_length=50)
    mailbox = models.CharField(max_length=32)
    password = models.CharField(max_length=8, default='0000')
    fullname = models.CharField(blank=True, null=True, max_length=50)
    email = models.CharField(blank=True, null=True, max_length=50)
    pager = models.CharField(blank=True, null=True, max_length=50)
    stamp = models.DateTimeField(default=datetime.now)
    class Meta:
        db_table = u'voicemail_users'
admin.site.register(VoicemailUsers)

class SipConf(models.Model):
    adresse_mac = models.CharField(“Adresse MAC (Douchette ou sans les ':' )”, max_length=128)
    # Ceci détermine la template à utiliser pour le fichier de conf
    type_telephone = models.CharField(u'Type de téléphone', max_length=128, choices=(('st20XX', 'Thomson ST 20XX'), ('922', 'SPA 922'), ('942', 'SPA 942'), ('962', 'SPA 962'), ('962+932', 'SPA 962+932'), ('962+932+932', 'SPA 962+932+932'), ('ip6000', 'SoundStation IP 6000')), default='922')

    adresse_ip = models.CharField('Adresse IP', max_length=128)
    mask_sr = models.CharField('Masque de sous réseau', max_length=128, default='255.255.255.0')
    passerelle = models.CharField('Passerelle par défaut', max_length=128, default='192.168.167.254')
    dns_primaire = models.CharField('DNS', max_length=128, default='192.168.167.100')
    username = models.CharField('N° Téléphone', blank=True, null=True, max_length=128)
    callerid = models.CharField('Nom complet', blank=True, null=True, max_length=128)

    serveur_sip = models.CharField('Serveur Téléphonie', max_length=128, default='192.168.167.67')
    secret = models.CharField(blank=True, null=True, max_length=128, default=make_pass)
    context = models.CharField(blank=True, null=True, max_length=128, default='default', choices=(('default', 'Interne'), ('national', 'Na
tional'), ('portable', 'Portable'), ('inter', 'International')))

    # Bah le reste on s'en occupe, dans le genre touchez plus à rien au delà
    # de cette ligne à moins que vous ne savhiez vraiment ce que vous faites :)
    serveur_log = models.CharField('Serveur journal', blank=True, null=True, max_length=128)
    serveur_prov = models.CharField('Serveur Provisionning', max_length=128)
    dns_secondaire = models.CharField(blank=True, null=True, max_length=128)

    name = models.CharField(blank=True, null=True, max_length=128)
    accountcode = models.CharField(blank=True, null=True, max_length=20)
    amaflags = models.CharField(blank=True, null=True, max_length=7)
    callgroup = models.CharField(blank=True, null=True, max_length=10)

    canreinvite = models.CharField(default='yes', max_length=3)

    defaultip = models.CharField(blank=True, null=True, max_length=15)
    dtmfmode = models.CharField(blank=True, null=True, max_length=7)
    fromuser = models.CharField(blank=True, null=True, max_length=128)
    fromdomain = models.CharField(blank=True, null=True, max_length=128)
    host = models.CharField(blank=True, null=True, max_length=31, default='dynamic')
    insecure = models.CharField(blank=True, null=True, max_length=4)
    language = models.CharField(blank=True, null=True, max_length=2, default='fr')
    mailbox = models.CharField(blank=True, null=True, max_length=50)
    md5secret = models.CharField(blank=True, null=True, max_length=128)
    nat = models.CharField(default='no', max_length=5)
    permit = models.CharField(blank=True, null=True, max_length=95)
    deny = models.CharField(blank=True, null=True, max_length=95)
    mask = models.CharField(blank=True, null=True, max_length=95)
    pickupgroup = models.CharField(blank=True, null=True, max_length=10)
    port = models.CharField(blank=True, null=True, max_length=5)
    qualify = models.CharField(blank=True, null=True, max_length=3)
    restrictcid = models.CharField(blank=True, null=True, max_length=1)
    rtptimeout = models.CharField(blank=True, null=True, max_length=3)
    rtpholdtimeout = models.CharField(blank=True, null=True, max_length=3)

    type = models.CharField(default='friend', max_length=25)
    disallow = models.CharField(default='all', max_length=1024)
    allow = models.CharField(default='g729;ilbc;gsm;ulaw;alaw', max_length=100)
    musiconhold = models.CharField(blank=True, null=True, max_length=100)
    regseconds = models.IntegerField(default=0) 
    ipaddr = models.CharField(blank=True, null=True, max_length=128)
    regexten = models.CharField(blank=True, null=True, max_length=128)
    cancallforward = models.CharField(default='yes', max_length=3)
    call_limit = models.CharField(default='99', max_length=10, db_column='call-limit') 
    limitonpeers = models.CharField(default='yes', max_length=10)
    fullcontact = models.CharField(blank=True, null=True, max_length=256)
    cur_ip = models.CharField(blank=True, null=True, max_length=256)

    prenoms = models.CharField(u'Prénoms', blank=True, null=True, max_length=256)
    nom = models.CharField(u'Nom', blank=True, null=True, max_length=256)
    fonction = models.CharField(u'Fonction', blank=True, null=True, max_length=256)
    site = models.CharField(u'Site', blank=True, null=True, max_length=256)
    nom_court = models.CharField(u'Nom court', blank=True, null=True, max_length=256)
    email = models.EmailField(blank=True, null=True)

    class Meta:
        db_table = u'sip_conf'


    def _mac(self):
        return (":".join([self.adresse_mac[i:i+2] for i in range(0,len(self.adresse_mac), 2)])).upper()

    mac = property(_mac)
    def __unicode__(self):
        return u"%s <%s>" %(self.callerid, self.username)

    def save(self):
        import time
        from commands import getoutput

        if not self.callerid:
            self.callerid = u"%s %s" % (self.prenoms, self.nom)
 
        if not self.nom_court:
            self.nom_court = "%s. %s" %(". ".join([s[0] for s in self.prenoms.split()]), self.nom.upper())
        self.adresse_mac = self.adresse_mac.lower()
        if not self.serveur_log:
            self.serveur_log = self.serveur_sip

        if not self.serveur_prov:
            self.serveur_prov = self.serveur_sip

        if not self.mailbox:
            self.mailbox = self.username

        if not self.secret:
            self.secret = make_pass()

        if not self.name:
            self.name = self.username

        if not self.host:
            self.host = 'dynamic'

        # Ok on Sauve, ce qui nous donne le compte SIP en même temps
        super(SipConf, self).save()

        # On génère le fichier de provisionninhg
        postes = [] # Les postes pour un subscribe/notify/blf par exemple
        print self.type_telephone
          postes = None ≈
        try:
            fd = open('/tftpboot/%s.cfg'% self.adresse_mac, 'w')
            t = loader.get_template('spa-%s.html'% self.type_telephone)
            c = Context({'u': self, 'postes':postes})
            bstring = t.render(c)
            fd.write(smart_str(bstring))
            fd.close()
        except Exception, e:
            print e # Allez mieux que print quand même
            
        # On génère les extensions associées ... En fait on fait généralement
        # pas ça, il y a un catchall pour les numéros internes
        pr1, created = ExtensionsConf.objects.get_or_create(context=self.context, exten=self.username, priority='1')
        pr1.app = 'Dial'
        pr1.appdata = 'SIP/%s' % self.username
        pr1.save()

        # Présence par exmple
        pr2, created = ExtensionsConf.objects.get_or_create(context=self.context, exten="%s" % self.username, priority='hint')
        pr2.app='SIP/%s' %self.username
        pr2.appdata = ''
        pr2.save()

        # On génère le Voicemail associé
        vm, created = VoicemailUsers.objects.get_or_create(context='omvs', mailbox=self.username)
        vm.fullname = self.callerid
        vm.save()

        m_extens = open('/tmp/subscribe.conf', 'w')
        m_extens.write('\n'.join([ "exten => %s,hint,%s"%(e.exten, e.app) for e in ExtensionsConf.objects.filter(priority='hint')]))
        m_extens.close()
        
            
        
admin.site.register(SipConf)

Vues Django

Quelques vues basiques permettant d'avoir la liste des comptes et d'ajouter de nouveaux comptes:

views.py

#-*- coding: utf-8 -*-
from django.forms import ModelForm, ValidationError
from django.template import Context, loader
from django.utils.encoding import force_unicode
from django.utils.encoding import smart_str, smart_unicode
from django.contrib.auth.decorators import user_passes_test, login_required
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from django.core.exceptions import ObjectDoesNotExist


from noyau.models import ExtensionsConf, SipConf

class SipModelForm(ModelForm):
    class Meta:
        model = SipConf
        fields = ('prenoms',
                  'nom',
                  'fonction',
                  'site',
                  'adresse_mac', 
                  'type_telephone', 
                  'adresse_ip', 
                  'cur_ip', 
                  'mask_sr', 
                  'passerelle', 
                  'dns_primaire', 
                  'username', 
                  'callerid', 
                  'serveur_sip', 
                  'context')

    def clean_adresse_mac(self):
        if 'adresse_mac' in self.cleaned_data:
            if len(self.cleaned_data['adresse_mac']) != 12 :
                raise ValidationError(u"L'adresse MAC fournit n'est pas valide, n'omettez pas les zéros")
            return self.cleaned_data['adresse_mac']

@login_required
def siplist(request, action):
    if action == 'list':
        return render_to_response('sip/list.html', {'users':SipConf.objects.filter(site__startswith='02').order_by('username') })

    if request.method == 'POST':
        form = SipModelForm(request.POST)
        if form.is_valid():
            new_user = form.save()
            return HttpResponseRedirect('/sip/list/')
    else:
        form = SipModelForm()
    return render_to_response('sip/add.html', {'form': form})
        

@login_required
def sipuser(request, action, id):
    try:
        user = SipConf.objects.get(pk=int(id))
    except ObjectDoesNotExist:
        return HttpResponseRedirect('/sip/list/')

    if action == 'delete':
        user.delete()
        return HttpResponseRedirect('/sip/list/')

    
    if request.method == 'POST':
        form = SipModelForm(request.POST, instance=user)
        if form.is_valid():
            new_user = form.save()
            return HttpResponseRedirect('/sip/list/')
    else:
        form = SipModelForm(instance=user)

    return render_to_response('sip/edit.html', {'form': form})


sip/add.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
  <head>
    <title>IP Phone Deploy</title>
  </head>
  <body>
    <h1>Ajouter un poste à l'implantation</h1>
    <form method="post" enctype="multipart/form-data">
      <table>
        {{ form }}
      </table>
      <p><input type="submit" value="Ajouter" class="submit" /></p>
    </form>
  </body>
  </html>

sip/edit.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
  <head>
    <title>IP Phone Deploy</title>
  </head>
  <body>
    <h1>Editer un poste de l'implantation</h1>
    <form method="post" enctype="multipart/form-data">
      <table>
        {{ form }}
      </table>
      <p><input type="submit" value="Editer" class="submit" /></p>
    </form>
  </body>
  </html>

sip/list.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
  <head>
    <title>Proxima C. IPBX v2</title>
  </head>
  <body>
    <h1>Liste des postes de l'implantation</h1>
    <p align="right"><a href="/sip/add/">Ajouter un poste</a></p>
    <table border="1">
      <tr><th>MAC</th><th>Type</th><th>Numéros</th><th>Nom</th><th>IP</th><th>Site</th><th>_</th><th>_</th><th>_</th></tr>
      {% for u in users %}
      <tr>
        <td><a href="/sip/edit/{{ u.id }}">{{ u.mac }}</a></td>
        <td>{{ u.type_telephone }}</td>
        <td>{{ u.username }}</td>       
        <td>{{ u.callerid }}</td>       
        <td>{{ u.adresse_ip }}</td>
        <td>{{ u.site }}</td>
        <td><a href="http://{% if u.cur_ip %}{{ u.cur_ip }}{% else %}{{ u.adresse_ip }}{% endif %}/admin/resync?http://{{ u.serveur_sip }}
/{{ u.adresse_mac}}.cfg">Recharger</a>
<td><a href="http://{{ u.adresse_ip }}/admin/upgrade?http://{{ u.serveur_sip }}/spa{{ u.type_telephone }}-6-1-3a.bin">Upgrade</a>
        <td><a href="/sip/delete/{{ u.id }}">Supprimer</a></td>
      </tr>
      {% endfor %}
    </table>
  </body>
</html>

Templates de configuration

Dans le cas des ST 20XX, les fichiers templates dont on peut se servir sont (Page 88 du guide d'Admin):

Example of file INF SIP:

Exemple:

[provision_mode] 
provision_mode=auto_provisioning 
 
[application] 
fw_filename=st2030SEG_fw.zz 
dsp_filename=v2030_dsp_ver_.zz 
boot_filename=v2030_boot_ver.zz 
 
[config] 
telcfg=TelConf2030SEG_telcfg.txt 
common_config=st2030s_common.txt 
 
melodies=Melodies.txt 
system_melodies=S_Melodies.txt 
call_waiting_tone=ringtone.txt 
tone_table=ToneTb.txt 
language_table=langtable.txt 

Ce fichier va contenir un ensemble de paramètres varaibles qui seront remplacé par le moteur de template en fonction du contexte qui lui sera passé.

Exemple:

[ipp]
AutoAnsMode= {{ mode_auto_answer }}
AutoAnsTimer=0 
Autocall=0 
AutocallNumber= 
AutoRejectTimer=0 
AutoStopTimer=0 
AutoHangUpTimer=3 
CaLogPrefix= 
Check_phonebook_domain_name=1 
Disable_call_progress=0 
Hide_Phone_Number_Display=0 
HideMissedCall=0 
LanguageType=0 
LocalMusicOnHold=1 
ManualLog=0 
OptionVisible=8191 
PasswordString=0000 
PhoneLock=0 
Pick_up_call=1 
Ringer_default_vol=4 
Ringer_lock=0 
RingToneMP1=0 
RingToneMP2=0 
RingToneMP3=0 
RingToneMP4=0 
Suppress-DomainName-Flag=1 
Transfer_to_voice_mail=1 
TransfOnRingFlag=0 
[net] 
DNSSrv1=0.0.0.0 
DNSSrv2=0.0.0.0 
DNSFLG=1 
DSCPflag=0 
ESWITCH_LAN=1 
ESWITCH_PC=1 
Gateway=0.0.0.0 
ipwan=10.1.24.88 
IpDFflag=0 
MaskWan=0.0.0.0 
PersistentVLANfromDHCP=0 
TelnetTime=240 
TelnetSrv=1 
VLAN=0 
WanModFlag=1 
 
 
 
[pstn] 
 
[sip] 
ACD=0 
AuthMessageServer=0.0.0.0 
KeppAliveDest=0.0.0.0 
KeepAliveTimer=0 
AuthNotifyCheckSync=0.0.0.0 
CallBlockType=0 
CF_Address1= 
CFNA_Time1=30 
CF_domain= 
ConnectReuseFlgMP1=0 
ConnectReuseFlgMP2=0 
ConnectReuseFlgMP3=0 
ConnectReuseFlgMP4=0 
ConnectReuseFlgBK1=0 
ConnectReuseFlgBK2=0 
ConnectReuseFlgBK3=0 
ConnectReuseFlgBK4=0 
ConferenceMode=0 
ConferenceFactoryURI=conf 
CallParkType=0 
CLIPDisplayPrior=ppreferred(1)passerted(2)remoteparty(3)from(4) 
CalledDisplayPrior=dialed(1)passerted(2)remoteparty(3) 
CallPkupFlg=local 
CallPkupSC= 
CallFwdFlg=local 
CallFwdOffSC= 
CallFwdAlwaysSC= 
CallFwdBusySC= 
CallFwdNoAnswerSC= 
CallParkFlg=local 
CallParkSC= 
CallRetreiveSC= 
CallBlockFlg=local 
CallBlockAllowSC= 
CallBlockRejectSC= 
CallBlockOFFSC= 
ClirFlg=local 
ClirOnSC= 
ClirOffSC= 
CallWaitingFlg=local 
CallWaitingOnSC= 
CallWaitingOffSC= 
call_hold_method=0 
CFUOnSV= 
CFUOffSV= 
DisplayNumFlag1=0 
DisplayNumFlag2=0 
DisplayNumFlag3=0 
DisplayNumFlag4=0 
DisplayNum1= 
DisplayNum2= 
DisplayNum3= 
DisplayNum4= 
DNDFlg=local 
DNDOnSC= 
DNDOffSC= 
DNDOnSV= 
DNDOffSV= 
DNDResp=1 
DisplayName1= 
DisplayName2= 
DisplayName3= 
DisplayName4= 
DisplayNameFlag1=0 
DisplayNameFlag2=0 
DisplayNameFlag3=0 
DisplayNameFlag4=0 
DiversionHeaderFlag=0 
ExpireTimeMP1=3600 
ExpireTimeMP2=3600 
ExpireTimeMP3=3600 
ExpireTimeMP4=3600 
ExpireTimeBK1=3600 
ExpireTimeBK2=3600 
ExpireTimeBK3=3600 
ExpireTimeBK4=3600 
Earlymediatype=0 
HGOnSC= 
HGOffSC= 
HGOnSV= 
HGOffSV= 
MissedCallSummary=0 
OutBoundProxy0= 
OutBoundPort0=5060 
OutBoundType=0 
ProfileName1=Profile 1 
ProfileName2=Profile 2 
ProfileName3=Profile 3 
ProfileName4=Profile 4 
PrivacyFlag1=4 
ProxyServerMP1= 
ProxyServerMP2= 
ProxyServerMP3= 
ProxyServerMP4= 
ProxyServerBK1= 
ProxyServerBK2= 
ProxyServerBK3= 
ProxyServerBK4= 
P-AssertedIDforCallee=0 
regid1= {{ username }}
regid2= 
regid3= 
regid4= 
regpwd1= 
regpwd2= 
regpwd3= 
regpwd4= 
RegisterServerMP1= 
RegisterServerMP2= 
RegisterServerMP3= 
RegisterServerMP4= 
RegisterServerBK1= 
RegisterServerBK2= 
RegisterServerBK3= 
RegisterServerBK4= 
RtpPort=41000 
ReTransTimer1=500 
ReTransTimer2=4 
RegisterFrequencyMP1=600 
RegisterFrequencyMP2=600 
RegisterFrequencyMP3=600 
RegisterFrequencyMP4=600 
RegisterFrequencyBK1=600 
RegisterFrequencyBK2=600 
RegisterFrequencyBK3=600 
RegisterFrequencyBK4=600 
REQ_RUI_with_port=1 
RFC2833=1 
RFC2833_rtp_pltype=96 
RFC3262=0 
RandomCSeqFlag=0 
SubscribeDilaogBeforeLogin=1 
RandomRTPPortFlag=0 
RegEventServer= 
ServiceDomainMP1= 
ServiceDomainMP2= 
ServiceDomainMP3= 
ServiceDomainMP4= 
ServiceDomainBK1= 
ServiceDomainBK2= 
ServiceDomainBK3= 
ServiceDomainBK4= 
SessionExpire=1800 
SessionExpireMin=100 
SessionMethod=0 
SessionRefresher=0 
sip_portMP1=5060 
sip_portMP2=5060 
sip_portMP3=5060 
sip_portMP4=5060 
sip_portBK1=5060 
sip_portBK2=5060 
sip_portBK3=5060 
sip_portBK4=5060 
sip_reg_srv_portMP1=5060 
sip_reg_srv_portMP2=5060 
sip_reg_srv_portMP3=5060 
sip_reg_srv_portMP4=5060 
sip_reg_srv_portBK1=5060 
sip_reg_srv_portBK2=5060 
sip_reg_srv_portBK3=5060 
sip_reg_srv_portBK4=5060 
sip_pxy_srv_portMP1=5060 
sip_pxy_srv_portMP2=5060 
sip_pxy_srv_portMP3=5060 
sip_pxy_srv_portMP4=5060 
sip_pxy_srv_portBK1=5060 
sip_pxy_srv_portBK2=5060 
sip_pxy_srv_portBK3=5060 
sip_pxy_srv_portBK4=5060 
SubscriptionExpire=3600 
SubscriptionExpireCB=60 
SharedCallAppearance=0 
SCAMainLinePrivate=0 
Specific_IP_flag=0 
HeaderCompact=0 
subscribe_event=0 
sw_anon_reject=0 
sw_CF=0 
sw_CFA=0 
sw_CFNA=0 
sw_CFB=0 
sw_not_disturb=0 
sw_call_park=0 
sw_notify_autoprovision=0 
sw_tr_vmail_address1= 
sw_tr_vmail_address2= 
sw_tr_vmail_address3= 
sw_tr_vmail_address4= 
sw_tr_vmail_flag=0 
sw_park_srv_addr1= 
sip_instance_id=0 
SFOnSC= 
SFOffSC= 
SFOnSV= 
SFOffSV= 
TransferOnRingSC= 
TrVoiceMailFlg0=local 
TrVoiceMailFlg1=local 

TrVoiceMailFlg2=local 
TrVoiceMailFlg3=local 
TrVoiceMailFlg4=local 
TrVoiceMailOnSC0= 
TrVoiceMailOnSC1= 
TrVoiceMailOnSC2= 
TrVoiceMailOnSC3= 
TrVoiceMailOnSC4= 
TrVoiceMailOffSC0= 
TrVoiceMailOffSC1= 
TrVoiceMailOffSC2= 
TrVoiceMailOffSC3= 
TrVoiceMailOffSC4= 
TrVoiceMailRingSC0= 
TrVoiceMailRingSC1= 
TrVoiceMailRingSC2= 
TrVoiceMailRingSC3= 
TrVoiceMailRingSC4= 
TEL1Number= 
TEL2Number= 
TEL3Number= 
TEL4Number= 
TransportFlgMP1=0 
TransportFlgMP2=0 
TransportFlgMP3=0 
TransportFlgMP4=0 
TransportFlgBK1=0 
TransportFlgBK2=0 
TransportFlgBK3=0 
TransportFlgBK4=0 
TransferUseContact=1 
URLTypeMP1=0 
URLTypeMP2=0 
URLTypeMP3=0 
URLTypeMP4=0 
URLTypeBK1=0 
URLTypeBK2=0 
URLTypeBK3=0 
URLTypeBK4=0 
USRPhoneFlg=1 
UnRegister_priorFlgMP1=1 
UnRegister_priorFlgMP2=1 
UnRegister_priorFlgMP3=1 
UnRegister_priorFlgMP4=1 
UnRegister_priorFlgBK1=1 
UnRegister_priorFlgBK2=1 
UnRegister_priorFlgBK3=1 
UnRegister_priorFlgBK4=1 
use_PrivateNumber=0 
VoiceMailAddr= 
VoiceMailTelNum= 
VoiceMailPort=5060 
[snmp] 
commRW1=0 
commRW2=0 
commRW3=0 
flag=1 
filter=0 
snmpManager1=0.0.0.0 
snmpManager2=0.0.0.0 
snmpManager3=0.0.0.0 
snmpManager4=0.0.0.0 
snmpManager5=0.0.0.0 
sysTrapSrv=0.0.0.0 
sysCommName1=public 
sysCommName2= 
sysCommName3= 
sysContact=Thomson 
sysDescr=Thomson IP Phone 
sysLocation=France 
sysName=ST2030 SIP 
TrapLevel=0 
 
 
[sys] 
2833_volume=0 
AEC=1 
BLFType=0 
BLFListSipUri=L/<sip:> 
CountryCode=US 
config_sn=200402190001 
Current_Max_Multiline=10 
CodecJitterBufMult=g711a(1/2/4)g711mu(1/2/4)g729(1/2/4)g723(1/2/4) 
CodecPktime=g711a(10)g711mu(10)g729(10)g723(30) 
CodecAdaptivePlayout=g711a(1)g711mu(1)g729(1)g723(1) 
DisableCWtone=0 
Dialednum_timeout=4 
dtmf_mode_flag=1 
EmergencyDialPlan=|911|11x|1[2-8]| 
FeatureKeyExt01=L/<sip:> 
FeatureKeyExt02=L/<sip:> 
FeatureKeyExt03=L/<sip:> 
FeatureKeyExt04=L/<sip:> 
FeatureKeyExt05=L/<sip:> 
FeatureKeyExt06=L/<sip:> 
FeatureKeyExt07=L/<sip:> 
FeatureKeyExt08=L/<sip:> 
FeatureKeyExt09=L/<sip:> 
FeatureKeyExt10=L/<sip:> 
FeatureKeyExt11=L/<sip:> 
FeatureKeyExt12=L/<sip:> 
FeatureKeyExt13=L/<sip:> 
FeatureKeyExt14=L/<sip:> 
FeatureKeyExt15=L/<sip:> 
FeatureKeyExt16=L/<sip:> 
FeatureKeyExt17=L/<sip:> 
FeatureKeyExt18=L/<sip:> 
FeatureKeyExt19=L/<sip:> 
FeatureKeyExt20=L/<sip:> 
FeatureKeyExt21=L/<sip:> 
FeatureKeyExt22=L/<sip:> 
FeatureKeyExt23=L/<sip:> 
FeatureKeyExt24=L/<sip:> 
FeatureKeyExt25=L/<sip:> 
FeatureKeyExt26=L/<sip:> 
FeatureKeyExt27=L/<sip:> 
FeatureKeyExt28=L/<sip:> 
FeatureKeyExt29=L/<sip:> 
FeatureKeyExt30=L/<sip:> 
FeatureKeyExt31=L/<sip:> 
FeatureKeyExt32=L/<sip:> 
FeatureKeyExt33=L/<sip:> 
FeatureKeyExt34=L/<sip:> 
FeatureKeyExt35=L/<sip:> 
FeatureKeyExt36=L/<sip:> 
FeatureKeyExt37=L/<sip:> 
FeatureKeyExt38=L/<sip:> 
FeatureKeyExt39=L/<sip:> 
FeatureKeyExt40=L/<sip:> 
FeatureKeyExt41=L/<sip:> 
FeatureKeyExt42=L/<sip:> 
FeatureKeyExt43=L/<sip:> 
FeatureKeyExt44=L/<sip:> 
FeatureKeyExt45=L/<sip:> 
FeatureKeyExt46=L/<sip:> 
FeatureKeyExt47=L/<sip:> 
FeatureKeyExt48=L/<sip:> 
FeatureKeyExt49=L/<sip:> 
FeatureKeyExt50=L/<sip:> 
FeatureKeyExt51=L/<sip:> 
FeatureKeyExt52=L/<sip:> 
FeatureKeyExt53=L/<sip:> 
FeatureKeyExt54=L/<sip:> 
FeatureKeyExt55=L/<sip:> 
FeatureKeyExt56=L/<sip:> 
FeatureKeyExt57=L/<sip:> 
FeatureKeyExt58=L/<sip:> 
FeatureKeyExt59=L/<sip:> 
FeatureKeyExt60=L/<sip:> 
FeatureKeyExt61=L/<sip:> 
FeatureKeyExt62=L/<sip:> 
FeatureKeyExt63=L/<sip:> 
FeatureKeyExt64=L/<sip:> 
FeatureKeyExt65=L/<sip:> 
FeatureKeyExt66=L/<sip:> 
FeatureKeyOpt01=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt02=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt03=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt04=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt05=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt06=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt07=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt08=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt09=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt10=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt11=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt12=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt13=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt14=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt15=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt16=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt17=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt18=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt19=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt20=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt21=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt22=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt23=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt24=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt25=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt26=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt27=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt28=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt29=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt30=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt31=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt32=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt33=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt34=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt35=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt36=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt37=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt38=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt39=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt40=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt41=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt42=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt43=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt44=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt45=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt46=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt47=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt48=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt49=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt50=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt51=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt52=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt53=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt54=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt55=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt56=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt57=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt58=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt59=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt60=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt61=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt62=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt63=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt64=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt65=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
FeatureKeyOpt66=dialog(1)regDND(0)ua-profile(0:cfu(0)dnd(0)sf(0)hg(0)) 
NormalDigitFlag=1 
PCallLogURL= 
PSettingURLdl= 
PSettingURLul= 
Phonebook1_url= 
Phonebook2_url= 
Phonebook3_url= 
Phonebook4_url= 
Phonebook5_url= 
Phonebook6_url= 
Phonebook7_url= 
Phonebook8_url= 
Phonebook1_name= 
Phonebook2_name= 
Phonebook3_name= 
Phonebook4_name= 
Phonebook5_name= 
Phonebook6_name= 
Phonebook7_name= 
Phonebook8_name= 
PBXconfiguration=0 
PBXprefix= 
softkey01=TrVoiceMail 
softkey02=CallLog 
softkey03=PickUp 
softkey04=LockPhone 
softkey05=VoiceMail 
softkey06=RetrievePark 
softkey07=DNDstate 
softkey08=ShortCut1 
softkey09=ShortCut2 
softkey10=ACDCheckIn 
softkey11=ACDAvailable 
softkey12=Login 
StartSpareFK=0 
ServiceSupervisionFK=11 
ServiceSupOrder=callfwd(0)dnd(0)secfilter(0)huntgroup(0) 
SuppressRTCP=0 
TelnetID=administrator 
TelnetPWD=789234 
UserID=user 
UserPWD= 
VOIPDialPlan=x.T 
WebPWD=784518 
 
[autoprovision] 
AutoprovisionFlag=1 
AutoprovisionHTTPServer= 
AutoprovisionTFTPServer= 
AutoprovisionTimeDays=0 
Autoprovisionstarttime=00:00 
AutoprovisionTimeSpan=0 
AutoprovisionRetryPeriod=30 
 
[qos] 
DHCPVLANid1=1 
DHCPVLANid2=1 
DSCP1=46 
DSCP2=40 
DSCPdata=40 
TOS=160 
VLANid1=1 
VLANid2=1 
VLANTag1=6 
VLANTagdata=6 
 
[ftp] 
FTPID= 
FTPPWD= 
 
[ntp] 
NtpDaylight=1 
NTPFlag=0 

NtpIP= {{ serveur_ntp }}
NtpMode=0 
NtpSyncTime=1 
NtpZoneNum=23 
 
 
[pppoe] 
PPPoEID= 
PPPoELCPMod=2 
PPPoELCPTimer=60 
PPPoEPWD= 
PPPoEMTU=1454 
 
[stun] 
STUNSrv= 
STUNPort=0 
STUNFlag=0 
[upnp] 
UPnPFlag=1 
 
[customer] 
sw_call_wait=1 

Identique au fichier précédant, sauf qu'il faut mettre à jour le numéros de série pour chaque APS (config_sn=xxxxxxxxxxxx)

Il est recommandé de ne pas le changer disent-ils Heu!

Preuve du concept en CLI

Qui s'y colle? Pour utiliser Django en script il suffit d'ajouter ces quelques lignes au début pour accèder au projet Django:

import os, sys, email
rep_projet = '/usr/local/voip_projets'
nom_projet = 'ipphonedeploy'
modules_projet = __import__(nom_projet, '', '', [''])
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'

Idées de migration de peers asterisk

L'idée ce serait de parser le sip.conf/iax.conf et d'en extraire les comptes pour les insérer dans la base, ensuite il faudra juste leurs allouer les adresses MAC associées.

Script inotify pour asterisk -rx "sip reload"

try:
    # import local build
    import autopath
    from src.pyinotify.pyinotify import ThreadedINotify, EventsCodes
except ImportError:
    # import global (installed) pyinotify
    from pyinotify import ThreadedINotify, EventsCodes

from pyinotify import ProcessEvent
from commands import getoutput
from datetime import datetime

class ProcessAsterisk(ProcessEvent):
    def process_default(self, event_k, event):
        pass

    def process_IN_MODIFY(self, event_k):
        print '_IN_CREATE'
        astatus = getoutput("/usr/sbin/asterisk -rx 'sip reload'")
        

    def process_IN_OPEN(self, event_k):
        pass

    def process_IN_CREATE(self, event_k):
        print '_IN_CREATE'
        astatus = getoutput("/usr/sbin/asterisk -rx 'sip reload'")

if __name__ == '__main__':
    import sys
    path = '/home/watchasteriskconfig' # default watched path
    if sys.argv[1:]:
        path = sys.argv[1]
    # only watch those events
    mask = EventsCodes.IN_MODIFY | EventsCodes.IN_DELETE | \
           EventsCodes.IN_OPEN | EventsCodes.IN_ATTRIB | \
           EventsCodes.IN_CREATE
    # class instance and init
    ino = ThreadedINotify()
    # start thread
    ino.start()
    ino.add_watch(path, mask, ProcessAsterisk())
    print 'start monitoring %s with mask %d' % (path, mask)
    # keep artificially the main thread alive forever
    while True:
        try:
            import time
            time.sleep(5)
        except KeyboardInterrupt:
            # ...until c^c signal
            print 'stop monitoring...'
            ino.stop()
            break
        except Exception, err:
            # otherwise keep on looping
            print err

Configuration DHCP (d'après la DOC page 87)

option tftp-server-name "@IP serveur TFTP";                        -------------->   option 66  
option bootfile-name "nomDeFichierINF.txt";                        -------------->   option 67 
option provision-server-ip code 150 = text   ------------->option 150 is text, not binary mode 
option provision-server-ip "@IP serveur TFTP ";             -------------> next server address 
option vendor-encapsulated-options "http://192.168.70.10/swupgrade_st2030m.txt" ---->option 43 


CatégorieVoIP


CatégorieVoIP

VoIP/ClientMatériel/ScenarioDeploiement (dernière édition le 2009-03-23 17:01:25 par OusmaneWilane)