2014-12-16

Manejando errores de S3 en boto

Update: No sé porqué, después de usar la solución que puse acá sigo viendo errores de reseteo de conexión (error: [Errno 104] Connection reset by peer)

Estoy manejando archivos grandes (1 GB) en S3 con boto y, aún cuando estoy corriendo en una instancia en EC2, da errores. Si no entendí mal el código de boto, es porque hay algunas excepciones que da en las conexiones que no está reintentando.

Para entrar en el código de retries de boto con estas excepciones hay que registrarlas, al menos en boto 2.20.1.

Para eso, cuando me conecto a S3 hago:

import boto
import httplib
import socket
import ssl

s3 = boto.connect_s3(
    
    settings.s3_access_key_id,
    settings.s3_secret_access_key,
    https_connection_factory=(httplib.HTTPSConnection, (
        ssl.SSLError, socket.error
    ))
)

Eso evita los errores que estoy viendo (error: [Errno 104] Connection reset by peer y SSLError: The read operation timed out).

Espero que les sirva,
Aureliano.

2014-12-04

Mejorando el mirroring

Hace un tiempito hice un post sobre lo que estoy haciendo para sincronizar directorios con rsync en instancias de EC2. Esto funcionó muy bien para directorios chiquitos, pero cuando tenés más de 100 megas y más de 1400 archivos cada iteración se hace un poco lenta y usa mucho bandwidth. Y no creo que Fibertel esté muy contento con eso.

Así que estuve buscando alguna versión que detecte los cambios que se hacen en los archivos, para no estar mirando todo todo el tiempo. Y lo encontré :D. Existe una cosa que se llama lsyncd, que hace eso :D. Si estás en ubuntu, para instalarlo solo hay que hacer sudo apt-get install lsyncd. Y con eso hice un scriptcito que busca el nombre de la instancia de EC2 con la que me interesa sincronizar y lo usa para mantenerlo sincronizado.

#!/usr/bin/env python

import subprocess
import sys
import time
import boto
import getpass
import tempfile

AKI = "AKIVAUNACCESSKEYID"
USER = "unusername"
INAME = "NOMBRE DE LA INSTANCIA"
TARGET = "DIRECTORIO EN EL TARGET"
SOURCE = "."

CONF_TEMPLATE="""\n
settings {
  logfile = "lsyncd.log",
  statusFile = "lsyncd.status",
  nodaemon = true,
  statusInterval = 2,
  maxProcesses = 8,
}

sync {
  default.rsyncssh,
  source=".",
  host='%(host)s',
  targetdir='%(targetdir)s',
  exclude={
    "*.pyc",
    "*.log",
    "*.swp",
    "*.status",
    "*/.hg/*",

  },
  delay=2,
}
"""

def main():
    sak = getpass.getpass("Enter secret access key:")
    ec2 = boto.connect_ec2( AKI, sak )
    dns_name = ec2.get_only_instances(filters={"tag:Name":INAME})[0].dns_name
    host = USER + "@" + dns_name
    targetdir = TARGET   
    with tempfile.NamedTemporaryFile() as t:
        print CONF_TEMPLATE % locals()
        t.write(CONF_TEMPLATE % locals())
        t.flush()
        subprocess.check_call("lsyncd -nodaemon -log Exec".split(" ") + [t.name])

if __name__ == '__main__':
    main()


Happy hacking,
Aureliano