#!/usr/bin/env python
# -*- coding: utf-8 -*-

#---------- Para utilizar o pyodbc tem que instalar o modulo
'''
---------- Para utilizar o pyodbc tem que instalar o modulo pyodbc
Ubuntu 13
no arquivo /etc/apt/sources.list.d
Comentar as quatro linhas abaixo:
deb http://br.archive.ubuntu.com/ubuntu/ saucy universe
deb-src http://br.archive.ubuntu.com/ubuntu/ saucy universe
deb http://br.archive.ubuntu.com/ubuntu/ saucy-updates universe
deb-src http://br.archive.ubuntu.com/ubuntu/ saucy-updates universe

Acrescentar estas quatro:

deb http://br.archive.ubuntu.com/ubuntu/ utopic universe
deb-src http://br.archive.ubuntu.com/ubuntu/ utopic universe
deb http://br.archive.ubuntu.com/ubuntu/ utopic-updates universe
deb-src http://br.archive.ubuntu.com/ubuntu/ utopic-updates universe


sudo apt-get update --fix-missing
sudo apt  install unixodbc unixodbc-dev tdsodbc freetds-dev python-dev
sudo easy_install pip

#necessário fechar a conexão a abrir de novo para carregar o prompt novamente.

sudo pip install pyodbc

fonte: http://blog.tryolabs.com/2012/06/25/connecting-sql-server-database-python-under-ubuntu/
---------------------------------------------------------------------
# executar este comando para iniciar os arquivos para conexão
odbcinst -j

resultado esperado
unixODBC 2.3.1
DRIVERS............: /etc/odbcinst.ini
SYSTEM DATA SOURCES: /etc/odbc.ini
FILE DATA SOURCES..: /etc/ODBCDataSources
USER DATA SOURCES..: /home/samuelpampolini/.odbc.ini
SQLULEN Size.......: 8
SQLLEN Size........: 8
SQLSETPOSIROW Size.: 8


editar o arquivo

sudo nano /etc/odbcinst.ini

[FreeTDS]
Description = FreeTDS
Driver = /usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so
---------------------------------------------------------------------

'''
import argparse, shlex, sys, traceback, subprocess
import pyodbc, threading, time, re

from subprocess import Popen, PIPE


parser = argparse.ArgumentParser(description='GESP - Execução de bath')
#por este caminho será recuperado o ambiente e a string de conexão com a base de dados
parser.add_argument('-i', '--infra', default='/var/projetos/gesp/Infra/', help='Pasta do Infra. Default /var/projetos/gesp/Infra/')
parser.add_argument('-p', '--process', nargs='+', default=[], help='Processos a serem executados. Caso informado será desconsiderado filtro de dia.')
args = parser.parse_args()

caminhoInfra = args.infra
processos = []

#ajuste para acentuação da linha de comando
for p in args.process:
    processos.append(p.decode('utf-8'))

def getConteudoArquivo(caminho):
    linhas = [line.rstrip('\n') for line in open(caminho)]
    conteudo = ''
    for linha in linhas:
        conteudo += linha

    return conteudo

def getAmbiente():
    conteudo = getConteudoArquivo('{0}{1}'.format(caminhoInfra, 'ConfigAmbiente.php'))
    ambiente = ''

    #resultado = re.search('getAmbiente[\(][\s]*[\)][\s]*[\{][\s]*[\w]+[\s]*[\'][\w]+[\']+', str(conteudo))
    resultado = re.search('getAmbiente(.*?)[\}]', str(conteudo))
    if resultado is not None:
        resultadoAmbiente = re.search('[\'][\w]+[\']', resultado.group(0))
        if resultadoAmbiente is not None:
            ambiente = str(resultadoAmbiente.group(0)).replace('\'', '')
        else:
            raise Exception('Não foi possível recuperar o ambiente')
    
    return ambiente

def getItemConfiguracao(chave, conteudo):
    regChave = re.search(chave + '(.*?)[\,]', conteudo)
    resultado = ''

    if regChave is not None:
        dadosSeparados = re.split('[=][>]', str(regChave.group(0)))
        resultado = str(dadosSeparados[1]).replace('\"', '').replace(',', '').strip(' ')
    else:
        raise Exception('Não foi possível recuperar a chave {0}'.format(chave))

    return resultado

def getHostAndDataBaseName(dados):
    resultado = {}
    string = getItemConfiguracao('HOST', dados)
    regHost = re.search('host=(.*?)[\;|:]', string)
    regBanco = re.search('dbname=(.*?)[\;]', string)
    regPort = re.search('port=(.*?)[\;]', string)

    if regHost is not None:
        resultado['host'] = str(regHost.group(0)).replace(';', '').replace(':', '').replace('host=', '')
    else:
        raise Exception('Não foi possível recuperar o host')

    if regBanco is not None:
        resultado['database'] = str(regBanco.group(0)).replace(';', '').replace('dbname=', '')
    else:
        raise Exception('Não foi possível recuperar o banco')

    if regPort is not None:
        resultado['port'] = str(regPort.group(0)).replace(';', '').replace('port=', '')
    else:
        resultado['port'] = None

    return resultado

def getConnDefaults():
    ambiente = getAmbiente()
    conteudo = getConteudoArquivo('{0}{1}'.format(caminhoInfra, 'TBanco.php'))
    resultado = re.search('[\']' + ambiente + '[\'](.*?)[\]]', str(conteudo))

    usuario = ''
    senha = ''
    dadosConexao = ''

    if resultado is not None:
        dados = str(resultado.group(0))
        usuario = getItemConfiguracao('USER', dados)
        senha = getItemConfiguracao('PASS', dados)
        dadosConexao = getHostAndDataBaseName(dados)
    else:
        raise Exception('Não foi possível recuperar os dados do ambiente {0}'.format(ambiente))
        
    myDriver = 'DRIVER={FreeTDS};'
    myServer = 'SERVER={0};'.format(dadosConexao['host'])
    myDB = 'DATABASE={0};'.format(dadosConexao['database'])
    myUser = 'UID={0};'.format(usuario)
    myPass = 'PWD={0};'.format(senha)
    myPort = ''
    if dadosConexao['port'] is not None:
        myPort = 'PORT={0};'.format(dadosConexao['port'])

    myConn = myDriver+myServer+myDB+myPort+myUser+myPass    
    
    return pyodbc.connect(myConn)

def doSelect(conexao, mystatement, parametros=()):
    cursor = conexao.cursor()
    cursor.execute(mystatement, parametros)
    myresult = cursor.fetchall()
    return myresult

def doInsert(conexao, mystatement, parametros=()):
    cursor = conexao.cursor()
    cursor.executemany(mystatement, parametros)
    return cursor.rowcount

def doInsertMany(conexao, mystatement, parametros=()):
    if len(parametros) > 0:
        cursor = conexao.cursor()
        cursor.executemany(mystatement, parametros)
        return cursor.rowcount
    return 0

def execCommand(cmd):
    process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    output = ''

    # Poll process for new output until finished
    for line in iter(process.stdout.readline, ""):
        print line,
        output += line


    process.wait()
    exitCode = process.returncode

    if (exitCode == 0):
        return output
    else:
        raise Exception(command, exitCode, output)

def salvarLog(conexao, parametros=[]):
    sql = "INSERT INTO TB_LOG_BATCH (DATA_INICIO, DATA_FIM, MENSAGEM, SUCESSO, ID_PROCESSO_BATCH) values (?, ?, ?, ?, ?)"
    return doInsertMany(conexao, sql, parametros)

def executarProcessos(conexao, arrayProcessos):
    dataBanco = getDataAtual()
    dia = time.strftime("%d")
    mes = time.strftime("%d")
    sql = """SELECT *
    FROM TB_PROCESSO_BATCH
    {0}
    ORDER BY ORDEM ASC"""
    where = ""
    parametros = ()

    if len(arrayProcessos) <= 0:
        where = """WHERE (DIA IS NULL OR DIA = ?) AND
            (MES IS NULL OR MES = ?) AND
            ATIVO = ?"""
        parametros = ( dia, mes, True )
    else:
        questions = ""
        separador = ""
        for param in arrayProcessos:
            questions += separador + "?"
            separador = ","
            parametros = parametros + (param,)

        where = "WHERE NOME in ({0})".format(questions)

    print "Recuperando os processos a serem executados"
    
    batchs = doSelect(conexao, sql.format(where), parametros)
    batch = None
    logs = []

    #armazena o status de execução de cada batch
    statusExecucao = {}
    
    for obj in batchs:
        try:
            batch = obj
            statusExecucao[batch.ID_PROCESSO_BATCH] = False
            requisitoCumprido = True
            dataInicio = getDataAtual()
            
            print "========================================"
            print "Executando: {0}".format(batch.NOME).decode('iso8859-1')
            print "========================================"
            #verifica se é para verificar o pré-requisito e se a chave existe. Caso a chave não exista é porque ele
            #não foi executado neste momento e devemos prosseguir com a execução.
            if batch.ID_PROCESSO_BATCH_REQUISITO is not None and batch.ID_PROCESSO_BATCH_REQUISITO in statusExecucao:
                requisitoCumprido = statusExecucao[batch.ID_PROCESSO_BATCH_REQUISITO]

            if requisitoCumprido:
                execCommand(batch.COMANDO.decode('iso8859-1'))
            
                logs.append((dataInicio, getDataAtual(), u'Sucesso'.encode('iso8859-1'), True, batch.ID_PROCESSO_BATCH ))
                statusExecucao[batch.ID_PROCESSO_BATCH] = True
        except Exception, e:
            if batch is not None:
                logs.append((dataInicio, getDataAtual(), u'Argumentos: {0}, Mensagem: {1}'.format(e.args, e).encode('iso8859-1'), False, batch.ID_PROCESSO_BATCH ))

    salvarLog(conexao, logs)

def getDataAtual():
    return time.strftime("%Y-%m-%d %H:%M:%S")

print "========================================"
print "Executando"
print "========================================"

conexao = None
try:
    conexao = getConnDefaults()
    executarProcessos(conexao, processos)

    #commita os dados de log da conexão
    conexao.commit()
    print "Processo finalizado com sucesso"
except Exception as error:
    print "Deu erro"
    print error
    traceback.print_exc(file=sys.stdout)
finally:
    if conexao is not None:
        conexao.close()