Se ha liberado la versión 3.0.1 del proxy SIP Kamailio.
El historial de cambios completo lo tenéis aquí
Technorati tags: kamailio, 3.0.1
Technorati tags: kamailio, 3.0.1
Technorati tags: opensips, web, server, interface, control, panel
Technorati tags: openbts, asterisk, voip, gsm, opensource
Technorati tags: asterisk, fax, t.30, t.38, attrafax, attractel, zoiper

Technorati tags: fritbox, dect, phones, avm
Y no es que hayan cambiado el CSS de la web. OpenSIPS va a ser reescrito por completo a partir del diseño que fue publicado hace unos días.
OpenSIPS tiene ya más de 7 años, tiempo en el que ta tecnología ha ido cambiado y han ido surgiendo necesidades y problemas que antes no había. Intuyo que no habrá sido fácil decidir reescribirlo, ya que supone mucho esfuerzo, pero seguramente sea lo mejor para un futuro.
El nuevo diseño se basa en el patrón reactor asíncrono, gracias al cual no habrá problemas de bloqueo entre los procesos de OpenSIPS, algo que actualmente si que puede suceder al hacer operaciones como consultas a BBDD, etc. Además, habrá dos importantes partes: el core y el routing engine.
Otro importante cambio con respecto al diseño actual es la posibilidad de utilizar varios routing engines con un solo core, de manera que cada routing engine implemente un funcionamiento diferente, pero un único core se encargue del procesamiento SIP a bajo nivel.
Hasta ahora, la lógica de OpenSIPS se definía en un fichero cfg en una sintaxis similar a C, pero con el nuevo diseño tendremos dos opciones para definir el funcionamiento de nuestro servidor:
Éste post es solo un resumen del documento que podéis ver aquí. Os recomiendo echarle un vistazo, veremos que tal sale la cosa dentro de unos 12 meses.
Si tenéis alguna duda, mañana viernes 5 de Marzo el tema central de la VoIP Users Conference será el diseño de OpenSIPS, y como invitados estarán Bogdan-Andrei Iancu (CEO en Voice-System), Adrian Georgescu (CEO en AG Projects) y Flavio Golcalves (autor de ‘Building Telephony Systems with OpenSIPS 1.6′).
¿Te lo vas a perder?
Por último me gustaría felicitar al equipo de ‘arquitectos’ que ha diseñado el nuevo OpenSIPS: Bogdan Iancu, Anca Vamanu, Andrei Dragus y Dan Pascu, OpenSIPS 2.0, here we go!
Technorati tags: skype, symbian, nokia, 5800
Technorati tags: fritz!, labor, laboratorio, avm, 7270, 7170, beta, firmware
Este es uno de los principales problemas con los que me he encontrado (un poco tarde por cierto) a la hora de crear un honeypot VoIP. Y el problema ya hecho que ahora llege a un punto muerto, la idea inicial de emular un proxy SIP (stateless) queda corto de cara a la multitud de soluciones VoIP existentes en el mercado actual. Sería interesante también un Honeypot que emulara el comportamiento de una PBX como Asterisk, o un completo proxy SIP del nivel de Kamailio.
Technorati tags: voip, vodafone, 3g, si, tarifa, plana, p2p, ilimitado, contigo
Tras estar varias semanas trabajando en éste tema me he decidido a escribir un (largo) post comentando qué es y cómo funciona esto del ICE, ya que no es algo que se esté utilizando demasiado desafortunadamente.
Introducción
Interactive Connection Establishment (ICE) define un protocolo de actuación gracias al cual dos dispositivos SIP son capaces de mantener una sesión multimedia salvando todas las dificultades que el NAT pueda poner de por medio. Aún se encuentra en estado de draft (la última es la revisión 19), pero está en la cola para obtener un número de RFC.
ICE permite que los dispositivos involucrados en la sesión SIP prueben distintos medios o rutas para comunicarse entre sí y acuerden uno común. Gracias a ICE es posible que dos terminales que se encuentran en la misma LAN envíen el tráfico RTP de manera local, en lugar de utilizar un relay como MediaProxy o RTPProxy, sin realizar ninguna configuración exótica en el servidor. La inteligencia está en los terminales.
¿Cómo funciona?
ICE es un proceso bastante complejo que consta de 9 pasos que intentaré simplificar aquí. Para obtener una información más completa os recomiendo leeros el draft, que aunque es bastante denso describe el mecanismo completo.
Paso 1: Obtención de candidatos
En éste primer paso el llamante obtiene todos los candidados que pueda para posteriormente añadirlos al SDP. Lo habitual es que disponga de dos tipos de candidatos:
Paso 2: Aplicar prioridades
Tras obtener la lista de candidatos se aplican prioridades, de manera que unos candidatos se prefieran frente a otros. Por ejemplo, la especificación indica que un candidato host ha de ser más prioritario que uno de tipo relayed, es decir, se prefiere mandar el audio por la LAN que a través de un servidor externo que encamina nuestro audio, lo cual tiene bastante sentido.
Al finalizar este paso se construye el SDP que será enviado. Veamos un ejemplo:
v=0
o=- 3476345811 3476345811 IN IP4 192.168.99.53
s=sipsimple 0.12.0
c=IN IP4 192.168.99.53
t=0 0
m=audio 60770 RTP/AVP 103 102 9 0 8 117 3 101
a=rtcp:60771 IN IP4 62.131.6.55
a=rtpmap:103 speex/16000
a=rtpmap:102 speex/8000
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:117 iLBC/8000
a=fmtp:117 mode=20
a=rtpmap:3 GSM/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15
a=ice-ufrag:3e0cc9fc
a=ice-pwd:19d32c8c
a=candidate:Sc0a86335 1 UDP 1862270975 62.131.6.55 60770 typ srflx raddr 192.168.99.53 rport 48649
a=candidate:Hc0a86335 1 UDP 1694498815 192.168.99.53 48649 typ host
a=candidate:Ha45450a 1 UDP 1694498815 10.69.69.10 48649 typ host
a=candidate:Sc0a86335 2 UDP 1862270974 62.131.6.55 60771 typ srflx raddr 192.168.99.53 rport 48868
a=candidate:Hc0a86335 2 UDP 1694498814 192.168.99.53 48868 typ host
a=candidate:Ha45450a 2 UDP 1694498814 10.69.69.10 48868 typ host
a=sendrecv
Paso 3: Iniciación
En este paso simplemente se envía el INVITE al usuario correspondiente con el SDP creado en el paso 2. SIP atravesará el NAT mediante los mecanismos tradicionales (rport, etc.) por lo que no hay que hacer tratamiento de NAT para el SDP.
Paso 4: Obtención de candidatos (llamado)
Al recibir el INVITE con la oferta en el SDP, el llamado comienza a obtener sus propios candidatos de la misma manera que lo hizo el llamante. Una vez más, lo habitual es obtener candidatos host y server reflexive. Una vez se obtienen los candidatos, se aplican prioridades y se construye el SDP que será enviado.
Paso 5: Información
El llamado responde al INVITE con una respuesta (provisional o definitiva) y en su SDP habrá incluido sus candidatos.
NOTA: Aunque puede tener sentido enviar la respuesta en una respuesta provisional (18X) SIP no especifica como actuar ante la recepción de múltiples respuestas 18X con SDP, por lo que si encima añadimos ICE al asunto lo mas probable es que no podamos establecer la comunicación. En todas las pruebas que he hecho (y han sido muchas) la negociación ICE no lleva más de 2 segundos, por lo que hacerla tras el 200 OK no es un problema IMHO.
Paso 6: Verificación
Cada agente (llamado y llamante) involucrado en la comunación empareja sus candidatos con los candidatos remotos para formar parejas de candidatos. Éstas parejas serán evaluadas por orden de prioridad descendente por el agente controlador. Por simplificar, diremos que el agente controlador siempre el el llamante (esto puede variar, pero en casos bastante peculiares, que creo que añadirían demasiada confusión al tema).
En éste momento ambos agentes comienzan a realizar pruebas de conectividad cada 20ms. Éstas pruebas se llevan a cabo mediante paquetes especiales STUN que contienen binding requests. El agente remoto contestará con la IP y el puerto desde los que ha recibido dicha binding request y así el agente que ha enviado la petición sabrá que el test ha sido satisfactorio y marcará el candidato como válido.
Si uno de los agentes involucrados en la sesión se encuentra tras un NAT simétrico, esto será detectado al ver la diferencia entre el server reflexive candidate publicado y el origen del binding request que mandará. Entonces se crea un nuevo candidato de tipo peer reflexive, que contiene la IP y puerto donde estará el RTP (los test de conectividad de hacen enviando paquetes STUN a los puertos donde posteriormente habrá RTP). Gracias a esto es posible que un usuario tras NAT simétrico y otro tras un NAT no simétrico hablen entre si con audio de router a router. Increíble, ¿no?
Paso 7: Coordinación
Tras la negociación ambos agentes involucrados en ella han de terminar con un par de candidatos válidos por cada componente. Lo habitual es tener dos componentes por cada stream en el SDP: un componente para el RTP y otro para el RTCP.
El agente controlador (habitualmente el que realiza la llamada) elegirá un candidato. A éste proceso se le llama nominación. Para validar éste candidato se envía otra binding request (STUN) pero en esta ocasión se incluye un flag. Ambos agentes utilizarán el par de candidatos que ha pasado las pruebas de conectividad y que además esté nominado.
Recordemos que todo éste proceso ha sido realizado por los agentes utilizando paquetes STUN entre si, sin ninguna interacción por parte del servidor.
Paso 8: Comunicación
Ahora que ambos agentes saben cómo comunicarse, ya pueden enpezar ha hablar, y tenemos garantizado que habrá audio bidireccional, ya que las pruebas de conectividad se realizan en ambas direcciones.
Paso 9: Confirmación
Aunque toda la negociación ha tenido lugar entre los agentes es posible (y habitual) que haya otros agentes en el medio de la señalización, como por ejemplo proxys. Para que los proxys o las middle-boxes entre el llamado y el llamante estén al tanto de lo sucedido, se enviará un re-INVITE o un UPDATE con el resultado de la negociación en el caso de que el candidato seleccionado no sea el candidato por defecto (las líneas c y m del SDP).
¡Qué way!, esto funciona, ¿no?
Pues, para variar, no. Lo habitual para el tratamiento de NAT consiste en que el proxy modifica el SDP si detecta NAT e indica como origen del RTP y RTCP un servidor que hará las veces de media relay.
Al modificar el SDP, no habrá ningún candidato que corresponda a la IP y puerto de las líneas c y m del SDP, por lo que al recibir un INVITE así el otro extremo nos responderá con ésto en su SDP: a=ice-missmatch. Mal tema. ¡Hay que solucionarlo!
“Arreglando” la negociación ICE con OpenSIPS y MediaProxy
Para solucionar éste problema ha sido necesario modificar OpenSIPS y MediaProxy (los componentes con los que trabajo actualmente, pero lo mismo puede hacerse para Kamailio/SIP-Router y RTPProxy).
Resumiendo un poco (tenéis una explicación más completa aquí) lo que sucederá es que OpenSIPS añadirá un nuevo candidato de tipo relayed cuando modifique el SDP, de manera que corresponda con la IP y puerto de las líneas c y m. MediaProxy es ahora capaz de “dejar pasar” las pruebas de conectividad STUN, por lo que al modificar el INVITE inicial y su correspondiente respuesta habremos “engañado” a los agente insertando un nuevo candidato.
Mediante un parámetro es posible controlar la prioridad del candidato que OpenSIPS insertará, afectando así al resultado de la negociación.
Ahora sí, ¡funciona! puedo hablar con audio P2P en mi LAN aunque fuerce el uso de MediaProxy, porque al detectar una negociación ICE satisfactoria MediaProxy se “quita de en medio”. También he probado ha hablar con audio de router a router entre un NAT simétrico y otro de tipo port restricted. How f*c*i*g cool is that?
¡Quiero probarlo!
No tan rápido vaquero. Nos falta hablar de el tema más importante: los clientes SIP. Sólo conozco tres (en esencia uno) que implemente ICE correctamente. Y cuando digo correctamente es que me he leído el draft, el código y he probado que funciona
Los clientes SIP con soporte ICE (draft versión 19) son PJSIP, SIPSIMPLE client (su core es PJSIP) y Blink (su core es SIPSIMPLE).
Si alguien descubre o está desarrollando un cliente SIP que cumpla la especificación ICE (draft 19) me encantaría probar la interoperabilidad con él.
Actualmente no hay ninguna versión (release) de OpenSIPS que incluya el parche para “solucionar” el problema de ICE, así que podéis parchear manualmente como se menciona aquí o podéis utilizar el servicio gratuito SIP2SIP, que ya dispone de todo lo necesario (parches para OpenSIPS y última versión de MediaProxy).
Conclusiones
Tras estar un mes con éste tema por fin he podido comprobar que funciona. No obstante, es triste ver que hay muy pocas implementaciones de ICE y que solo una funcione. Es cuanto menos sorprendente que softphones de pago de supuesto prestigio digan que soportan ICE y en el SDP se vea claramente no de la manera correcta.
Hay que agradecer a Benny Prijono y el equipo de PJSIP el buen trabajo que han realizado al respecto acudiendo en enumerosas ocasiones al SIPit para mejorar su SIP stack.
¡Joder que largo me ha quedado esto! Para más información podéis leer el draft y echarle un ojo a ésta presentación.
Happy ICE skating!
En el precedente articulo hemos visto como usar la replicación MySQL Master-Slave para la base de datos de Asterisk. Hoy veremos como utilizar la replicación MySQL Master-Master para la misma base de datos pero solamente para la tabla CDR. Que diferencia hay entra una replicación Maestro-Esclavo y una Maestro-Maestro?
En el primer caso tenemos una copia de todos los registros en otro servidor y podemos efectuar estadísticas usando el Esclavo sin sobrecargar el Maestro. En el segundo caso la configuración se utiliza para la alta disponibilidad en Asterisk. Dos servidores asterisk: A y B. Si A se cae B toma su lugar. Cuando A vuelve a funcionar, B vuelve a ser el servidor de respaldo. Como veremos en un próximo articulo, para la alta disponibilidad en Asterisk, además de la replicación Master-Master, necesitaremos configurar otros programa. Por ahora nos interesa configurar la replicación MySQL Master-Master.
Escenario:
ServidorA
IP 192.168.142.248
Base de datos a replicar: asterisk – Tabla: cdr
MasterA SlaveA
ServidorB
IP 192.168.146.90
Base de datos a replicar: asterisk – Tabla: cdr
MasterB SlaveB
La tabla CDR en el ServidorA ya existe y tiene unos cuantos datos registrados. El problema principal de la replicación Master-Master es el conflicto que se puede presentar en las entradas de la tabla. Ejemplo:
el servidorA se cae y toma su lugar el servidorB. Se registran unos cuantos datos en la tabla cdr del servidorB. Mientras el servidorA vuelve a funcionar y antes que el servidorB pueda actualizar los datos de la tabla CDR en el servidorA, este empieza a grabar nuevas entradas en la misma tabla. En este escenario se pueden generar conflictos entre los datos de las dos tablas y se genera un error de replicación porque los dos presentan entradas con el mismo ID en la clave primaria de la tabla (siendo progresivo).
Para solucionar este tipo de problema se usarán estos dos parámetros:
Mano a la obra.
La tabla CDR de la base de datos Asterisk no tiene un ID progresivo para cada entrada. Entramos en el cliente MySQL y miramos la fecha de las llamadas de la extension 2300:
mysql –u root –p
mysql> use asterisk
mysql> select calldate from cdr where dst=2300;
+---------------------+
| calldate |
+---------------------+
| 2009-10-19 13:16:12 |
| 2009-10-19 13:16:12 |
| 2009-11-04 20:30:48 |
| 2009-11-04 20:30:48 |
| 2009-11-04 20:33:31 |
| 2009-11-04 20:33:31 |
| 2009-11-06 21:03:29 |
| 2009-11-06 21:03:29 |
| 2009-11-06 21:04:09 |
| 2009-11-06 21:04:09 |
| 2009-11-06 21:08:37 |
| 2009-11-06 21:08:37 |
| 2009-12-17 20:59:42 |
| 2009-12-17 20:59:42 |
+---------------------+
14 rows in set (0.01 sec)
Ahora añadimos un id progresivo en la estructura de la tabla:
mysql> ALTER TABLE cdr ADD ID int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY;
Query OK, 2747 rows affected (0.01 sec)
Records: 2747 Duplicates: 0 Warnings: 0
Miramos el cambio:
mysql> select id,calldate from cdr where dst=2300;
+------+---------------------+
| id | calldate |
+------+---------------------+
| 610 | 2009-10-19 13:16:12 |
| 611 | 2009-10-19 13:16:12 |
| 1236 | 2009-11-04 20:30:48 |
| 1237 | 2009-11-04 20:30:48 |
| 1238 | 2009-11-04 20:33:31 |
| 1239 | 2009-11-04 20:33:31 |
| 1336 | 2009-11-06 21:03:29 |
| 1337 | 2009-11-06 21:03:29 |
| 1338 | 2009-11-06 21:04:09 |
| 1339 | 2009-11-06 21:04:09 |
| 1342 | 2009-11-06 21:08:37 |
| 1343 | 2009-11-06 21:08:37 |
| 1912 | 2009-12-17 20:59:42 |
| 1913 | 2009-12-17 20:59:42 |
+------+---------------------+
14 rows in set (0.00 sec)
Ahora cada entrada seleccionada tiene un ID que la identifica.
Creamos una carpeta donde guardar los Binary log de MySQL y cambiamos usuario y grupo que tiene los permisos en la carpeta creada:
mkdir /var/log/mysql
chown mysql:mysql /var/log/mysql
ls -l /var/log/my*
-rw-r----- 1 mysql mysql 41201 Feb 24 07:19 /var/log/mysqld.log
/var/log/mysql:
total 0
Volvemos al cliente MySQl y creamos los privilegios de replicación para un nuevo usuario:
mysql –u root –p
mysql> GRANT REPLICATION SLAVE ON *.* TO 'masterb'@'192.168.146.90' IDENTIFIED BY 'sesamo';
mysql> flush privileges;
mysql> quit
Ahora modificamos el archivo de configuración de MySQL:
nano /etc/my.cnf
bajo la etiqueta [mysqld] ponemos:
server-id = 10
auto_increment_increment = 10
auto_increment_offset = 1
log_bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 10
max_binlog_size = 100M
replicate-do-table =asterisk.cdr
sync_binlog =1
Los parámetros:
Con auto_increment_increment a 10 cada entrada en la tabla cdr tendrá un ID progresivo que irá de 10 en 10
Con auto_increment_offset a 1 cada entrada usará el entero 1
En el caso de tres entradas en la tabla el resultado será:
ID 1
ID 11
ID 21
Con replicate-do-table definimos que la replicación es solamente para la tabla cdr de la base de datos Asterisk
Reiniciamos mysql:
/etc/init.d/mysql restart
Considerando que nuestro servidor Asterisk tiene tiempo trabajando tenemos que crear una copia de la base de datos para luego importarla en el servidorB:
mysql -u root -p
Primero seleccionamos la base de datos asterisk:
mysql> use asterisk
Segundo bloqueamos la lectura de todas las tablas de todas las bases de datos:
mysql> FLUSH TABLES WITH READ LOCK;
Por ultimo miramos el estado del Master:
mysql> SHOW MASTER STATUS;
Aparecerá algo por el estilo:
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 | 98 | asterisk | |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
Apuntamos los datos que aparecen en la columna File (mysql-bin.000001) y en la columna Position (98)
Sin cerrar esta ventana, abrimos otra ventana terminal o otra conexión al servidor Linux y creamos una copia de la base de datos asterisk:
cd /tmp
mysqldump -u root -p asterisk cdr > cdr.sql
copiamos el archivo en el servidorB en la carpeta tmp:
scp cdr.sql root@192.168.146.90:/tmp
Cerramos esta ventana y volvemos a la primera:
desbloqueamos las tablas:
mysql> UNLOCK TABLES;
y salimos del cliente:
mysql> quit
Creamos la carpeta para guardar los Bynary log con los permisos para el usuario mysql:
mkdir /var/log/mysql
chown mysql:mysql /var/log/mysql
Entramos en el cliente mysql y creamos la base de datos asterisk:
mysql -u root –p
mysql> create database asterisk;
mysql> quit
Importamos la tabal cdr:
cd /tmp
mysql -u root -p asterisk < cdr.sql
Y averiguamos que efectivamente las tabla y los datos presentes se han guardado:
mysql -u root –p
mysql> use asterisk
mysql> select id,calldate from cdr where dst=2300;
+------+---------------------+
| id | calldate |
+------+---------------------+
| 610 | 2009-10-19 13:16:12 |
| 611 | 2009-10-19 13:16:12 |
| 1236 | 2009-11-04 20:30:48 |
| 1237 | 2009-11-04 20:30:48 |
| 1238 | 2009-11-04 20:33:31 |
| 1239 | 2009-11-04 20:33:31 |
| 1336 | 2009-11-06 21:03:29 |
| 1337 | 2009-11-06 21:03:29 |
| 1338 | 2009-11-06 21:04:09 |
| 1339 | 2009-11-06 21:04:09 |
| 1342 | 2009-11-06 21:08:37 |
| 1343 | 2009-11-06 21:08:37 |
| 1912 | 2009-12-17 20:59:42 |
| 1913 | 2009-12-17 20:59:42 |
+------+---------------------+
14 rows in set (0.01 sec)
Creamos un nuevo usuarios con los permisos de replicación
mysql> GRANT REPLICATION SLAVE ON *.* TO 'mastera'@'192.168.142.248' IDENTIFIED BY 'sesamo';
mysql> flush privileges;
mysql> quit
Ahora modificamos el archivo de configuración de MySQL:
nano /etc/my.cnf
bajo la etiqueta [mysqld] ponemos:
server-id = 20
auto_increment_increment = 10
auto_increment_offset = 2
log_bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 10
max_binlog_size = 100M
replicate-do-table =asterisk.cdr
sync_binlog =1
El auto_increment_offset es igual a 2. En el caso de tres entradas el ID sería:
ID 2
ID 12
ID 22
Como pueden ver, de esta forma no se presentarán conflictos en las entradas de la tabla CDR
Reiniciamos Mysql:
/etc/init.d/mysqld restart
Y ahora como para el servidorA miramos el Binary log y apuntamos los datos:
mysql -u root -p
mysql> FLUSH TABLES WITH READ LOCK;
mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 | 98 | | |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
mysql> quit
Ahora conectamos el servidorB al servidorA:
mysql -u root –p
mysql> CHANGE MASTER TO MASTER_HOST='192.168.142.248',
MASTER_USER='masterb',
MASTER_PASSWORD='sesamo',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=98;
Query OK, 0 rows affected (0.00 sec)
Iniciamos el esclavo:
mysql> START SLAVE;
Query OK, 0 rows affected (0.00 sec)
y miramos el resultado:
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.142.248
Master_User: masterb
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 98
Relay_Log_File: mysqld-relay-bin.000002
Relay_Log_Pos: 235
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table: asterisk.cdr
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 98
Relay_Log_Space: 235
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
1 row in set (0.00 sec)
Seguimos el mismo procedimiento para el ServidorA:
mysql –u root –p
mysql> CHANGE MASTER TO MASTER_HOST='192.168.146.90',
MASTER_USER='mastera',
MASTER_PASSWORD='sesamo',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=98;
Query OK, 0 rows affected (0.10 sec)
mysql> START SLAVE;
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.146.90
Master_User: mastera
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 98
Relay_Log_File: mysqld-relay-bin.000002
Relay_Log_Pos: 235
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table: asterisk.cdr
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 98
Relay_Log_Space: 235
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
1 row in set (0.00 sec)
Ahora la prueba.
Paramos el MySQL del servidorB y hacemos dos llamadas al buzón de voz con asterisk activo en el servidorA
El resultado en la base de datos:
mysql -u root -p
mysql> use asterisk
mysql> select id,calldate from cdr where dst=97;
| 2736 | 2010-02-23 13:06:56 |
| 2737 | 2010-02-23 13:06:56 |
| 2738 | 2010-02-24 06:05:53 |
| 2739 | 2010-02-24 06:05:53 |
| 2791 | 2010-02-24 09:48:44 |
| 2801 | 2010-02-24 09:49:00 |
+------+---------------------+
207 rows in set (0.00 sec)
Mientras antes el ID era progresivo, las ultimas dos entradas tienen un salto de 10 y cada una termina con el numero 1
Terminada la operación, paramos MySQL en el servidorA y iniciamos MySQL en el servidorB haciendo dos llamadas al buzón de voz usando el Asterisk del servidorB
El resultado en la base de datos:
mysql -u root -p
mysql> use asterisk
mysql> select id,calldate from cdr where dst=97;
| 2736 | 2010-02-23 13:06:56 |
| 2737 | 2010-02-23 13:06:56 |
| 2738 | 2010-02-24 06:05:53 |
| 2739 | 2010-02-24 06:05:53 |
| 2752 | 2010-02-24 09:55:07 |
| 2762 | 2010-02-24 09:57:17 |
+------+---------------------+
207 rows in set (0.01 sec)
El ID progresivo en el servidorB cambia con saltos de 10 y cada entrada termina con el numero 2
Ahora iniciamos MySQL en el servidorA y miramos que pasa en los dos servidores:
ServidorA:
mysql -u root –p
mysql> use asterisk
mysql> select id,calldate from cdr where dst=97;
| 2737 | 2010-02-23 13:06:56 |
| 2738 | 2010-02-24 06:05:53 |
| 2739 | 2010-02-24 06:05:53 |
| 2752 | 2010-02-24 09:55:07 |
| 2762 | 2010-02-24 09:57:17 |
| 2791 | 2010-02-24 09:48:44 |
| 2801 | 2010-02-24 09:49:00 |
+------+---------------------+
209 rows in set (0.00 sec)
ServidorB
mysql -u root –p
mysql> use asterisk
mysql> select id,calldate from cdr where dst=97;
| 2739 | 2010-02-24 06:05:53 |
| 2752 | 2010-02-24 09:55:07 |
| 2762 | 2010-02-24 09:57:17 |
| 2791 | 2010-02-24 09:48:44 |
| 2801 | 2010-02-24 09:49:00 |
+------+---------------------+
209 rows in set (0.01 sec)
Los datos se han replicado y no hubo ningún tipo de conflicto en la tabla cdr gracias al uso de:
auto_increment_increment
auto_increment_offset
Eso es todo.

Technorati tags: avm, dect, voip, cable, modem, hfc, ono,