Error de MySQL: (2003, "No se puede conectar al servidor MySQL en '2001: db8: 81: 2c :: 2' (-9)")

15

Estoy tratando de configurar Zenoss 4.2.0 en CentOS 6.3 para monitorear un servidor remoto MySQL 5.5.25a a través de IPv6. El firewall está abierto para el servidor de monitoreo y puedo conectarme bien desde la línea de comando:

[root@zenoss ~]# mysql -u zenoss -p -h 2001:db8:81:2c::2
...
mysql> SELECT USER(),CURRENT_USER();
+-----------------------------------------+-----------------------------------------+
| USER()                                  | CURRENT_USER()                          |
+-----------------------------------------+-----------------------------------------+
| zenoss@2001:db8:16:bf:5054:ff:fec0:f7a5 | zenoss@2001:db8:16:bf:5054:ff:fec0:f7a5 |
+-----------------------------------------+-----------------------------------------+
1 row in set (0.09 sec)

Sin embargo, Zenoss genera un evento "No hay datos de rendimiento del complemento" cuyos detalles se quejan de que no se puede conectar al servidor:

MySQL Error: (2003, "Can't connect to MySQL server on '2001:db8:81:2c::2' (-9)")

Hasta donde yo sé, -9 ni siquiera es un error válido. Y, por supuesto, es imposible buscar en Google un número negativo .

ingrese la descripción de la imagen aquí

He comprobado zMySqlUsername y zMySqlPassword, más de una vez, y tienen los valores correctos.

También intenté ingresar la dirección IPv6 con corchetes, pero a MySQL no le gusta para nada, ya sea dentro de Zenoss o en la línea de comandos.

¿Cuál es la causa de este problema?

Michael Hampton
fuente
Si todo lo demás falla, ¿no puede volver a IPv4?
John Gardeniers
@JohnGardeniers A veces. Pero muchas de las máquinas a monitorear no tienen direcciones IPv4 globales, por lo que se requeriría un proxy Zenoss. Entre otras cosas, estoy tratando de alejarme de eso.
Michael Hampton
Ok, pensé que podría ser una opción, especialmente con IPv6 siendo tan incompleto o imperfecto en muchos productos.
John Gardeniers

Respuestas:

11

Finalmente me di por vencido y fui a depurar esto yo mismo.

Basado en la respuesta de @ SelivanovPavel, encendí la depuración zencommandy esperé, y efectivamente, el ZenPack estaba fallando.

2012-08-16 18:16:14,092 INFO zen.zencommand: Datasource MySQL/mysql command: /opt/zenoss/ZenPacks/ZenPacks.zenoss.MySqlMonitor-2.2.0-py2.7.egg/ZenPacks/zenoss/MySqlMonitor/libexec/check_mysql_stats.py -H 2001:db8:81:2c::2 -p 3306 -u zenoss -w 'password' -g
2012-08-16 18:16:14,100 DEBUG zen.zencommand: Running /opt/zenoss/ZenPacks/ZenPacks.zenoss.MySqlMonitor-2.2.0-py2.7.egg/ZenPacks/zenoss/MySqlMonitor/libexec/check_mysql_stats.py
2012-08-16 18:16:14,544 DEBUG zen.zencommand: Datasource: mysql Received exit code: 1 Output: 'MySQL Error: (2003, "Can\'t connect to MySQL server on \'2001:db8:81:2c::2\' (-9)")\n'
2012-08-16 18:16:14,545 DEBUG zen.zencommand: Process MySQL/mysql stopped (1), 0.43 seconds elapsed 

Y cavé en el ZenPack y descubrí que estaba importando (aparentemente una versión antigua de) pymysqla partir /opt/zenoss/lib/python.

Al probar desde la línea de comando de python descubrí de dónde se lanzaba la excepción:

>>> sys.path.insert(0, "/opt/zenoss/lib/python");
>>> import pymysql
>>> pymysql.install_as_MySQLdb()
>>> import MySQLdb
>>> self.conn = MySQLdb.connect(host="2001:db8:81:2c::2", port=3306, db='', user='zenoss', passwd='password')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/zenoss/lib/python/pymysql/__init__.py", line 93, in Connect
    return Connection(*args, **kwargs)
  File "/opt/zenoss/lib/python/pymysql/connections.py", line 504, in __init__
    self._connect()
  File "/opt/zenoss/lib/python/pymysql/connections.py", line 673, in _connect
    raise OperationalError(2003, "Can't connect to MySQL server on %r (%s)" % (self.host, e.args[0]))
pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on '2001:db8:81:2c::2' (-9)")

Y al inspeccionar connections.pyen esa vecindad general descubrí con horror que estaba intentando abrir un AF_INETzócalo, y que no había ningún código en ningún lugar para abrir un AF_INET6zócalo. Boom, falla instantánea.

La versión actual de pymysqltambién parece contener esta deficiencia; no hay soporte de IPv6 en absoluto.

Entonces la "respuesta" es que voy a tener que arreglarlo pymysql. No cómo quería pasar la tarde.

Este pequeño truco desagradable hace que las cosas funcionen (aunque necesitas Python 2.6). Abre /opt/zenoss/lib/python/pymysql/connections.pyy busca AF_INETalrededor de la línea 660. Luego haz el siguiente cambio:

                 if DEBUG: print 'connected using unix_socket'
             else:
-                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-                t = sock.gettimeout()
-                sock.settimeout(self.connect_timeout)
-                sock.connect((self.host, self.port))
-                sock.settimeout(t)
+                sock = socket.create_connection((self.host, self.port), self.connect_timeout)
                 self.host_info = "socket %s:%d" % (self.host, self.port)
                 if DEBUG: print 'connected using socket'

Desde entonces, esto se ha corregido en pymysql ascendente y debería estar disponible en una versión futura.

Michael Hampton
fuente
5

Verifique, ¿hay algún intento de conexión?

tshark -i br200 -f "host 2001:db8:81:2c::2"

tshark es la versión de consola del programa de captura de paquetes Wireshark.

Si el usuario del servicio zenoss no es root, intente conectarse a mysql desde su shell:

su zenoss
mysql ...

¿Qué pasa con los registros de Zenoss (Configuración> Demonios)? Intente aumentar la verbosidad de los registros (establezca logseverity = 30) y vea qué sucede.

Este documento puede ser útil: Solución de problemas_Zenoss

Selivanov Pavel
fuente
Obtienes la recompensa porque te acercaste más que el otro al origen del problema. Gracias. :)
Michael Hampton
3

Intente ponerlo entre paréntesis [2001: 470: ...] o ipv6: []. Muchos analizadores no pueden diferenciar entre una entrada de texto y una dirección v6.

rnxrx
fuente
1
He estado allí, hecho eso. MySQL, al menos, quiere la dirección IP sin paréntesis.
Michael Hampton
2
Ese código de error puede provenir de las bibliotecas que Zenoss está usando en lugar de hacerlo en MySQL. Está escrito principalmente en Python si recuerdo correctamente, por lo que puede ser un lugar para buscar una pista.
rnxrx
1
Si tengo que profundizar en el código fuente, terminaré respondiendo mi propia pregunta. De nuevo. :)
Michael Hampton
3
Sin embargo, ¿no es esa la belleza del código abierto? Todos podemos corregir nuestros propios errores <kidding>. Hola, otro pensamiento, sin embargo. ¿Qué sucede si configura un nombre de host estándar que solo se resolvió en AAAA y luego usó ese nombre de host en lugar de la IP sin procesar?
rnxrx