1. 程式人生 > >python多執行緒併發

python多執行緒併發

# coding=utf8
# 使用前需安裝net-snmp-utils或net-snmp包
from _utils.patrol2 import run_cmd
import sys
import os
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
from zipfile import ZipFile
import stat
import time
import datetime

now_time = datetime.datetime.now().strftime('%Y-%m-%d_%H:%M:%S')


# def get_host_ip():
#     try:
#         s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#         s.connect(('8.8.8.8', 80))
#         ip = s.getsockname()[0]
#     finally:
#         s.close()
#     return ip
#
# ftp_ips = get_host_ip()
# if ftp_ips in (None,'') or ftp_ips.startswith('127.'):
#
# print 'ftp_ip:',ftp_ip


def get_type(host):
    cmd = 'snmpwalk -v {} -c {} {}|head -1'.format(snmp_version, community, host)
    # print cmd
    code, result = run_cmd(cmd)
    if code:
        print '查詢型別失敗'
        sys.exit(1)
    # print result
    if 'H3C' in result:
        return 'H3C'
    else:
        return 'Cisco'


def snmp_set(host, oid):
    cmd = 'snmpset -r 0 -v {} -c {} {} {}'.format(snmp_version, community, host, oid)
    # print cmd
    code, result = run_cmd(cmd)
    return code, result


def snmp_test(pre_oid, host, flag):
    cmd = 'snmpwalk -r 0 -v {} -c {} {} {}.{}'.format(snmp_version, community, host, pre_oid, flag)
    # print cmd
    code, result = run_cmd(cmd)
    return code, result


def do_snmp(host, filename, ftp_ip):
    if connect_type != 'tftp' and (not username or not password):
        print '檔案伺服器的登入使用者名稱或密碼缺失,請重新輸入後嘗試'
        sys.exit(1)

    device_type = get_type(host)
    print device_type
    if device_type == 'H3C':
        pre_oid = '1.3.6.1.4.1.25506.2.4.1.2.4.1.9'
    elif device_type == 'Cisco':
        pre_oid = '.1.3.6.1.4.1.9.9.96.1.1.1.1.3'

    flag_num = 1
    while 1:
        code, res = snmp_test(pre_oid, host, flag_num)
        if (code and res) or 'No Such Instance currently exists at this OID' in res:
            break
        flag_num += 1

    if device_type == 'H3C':
        action_type = '1.3.6.1.4.1.25506.2.4.1.2.4.1.2.{} i 3'.format(
            flag_num)  # 指定配置檔案操作型別,3為當前系統執行的配置
        filename = '1.3.6.1.4.1.25506.2.4.1.2.4.1.4.{} s {}'.format(flag_num,
                                                                    filename)  # 指定檔名,目的檔名
        ftp_ip = '1.3.6.1.4.1.25506.2.4.1.2.4.1.5.{} a {}'.format(flag_num, ftp_ip)  # 指定伺服器地址
        if connect_type == 'tftp':
            protocol_type = '1.3.6.1.4.1.25506.2.4.1.2.4.1.3.{} i 2'.format(flag_num)  # 2 #使用TFTP協議
        elif connect_type == 'ftp':  # 1 #使用FTP協議
            login_info = '1.3.6.1.4.1.25506.2.4.1.2.4.1.6.{flag_num} s {username} 1.3.6.1.4.1.25506.2.4.1.2.4.1.7.{flag_num} s {password} '.format(
                username=username, password=password, flag_num=flag_num)
            ftp_ip = ftp_ip + ' ' + login_info
            protocol_type = '1.3.6.1.4.1.25506.2.4.1.2.4.1.3.{} i 1'.format(flag_num)  # 1 #使用FTP協議

        save_log = '1.3.6.1.4.1.25506.2.4.1.2.4.1.9.{} i 4'.format(flag_num)
        oid = '{action_type} {protocol_type} {filename} {ftp_ip} {save_log}'.format(
            action_type=action_type, filename=filename, protocol_type=protocol_type, ftp_ip=ftp_ip,
            save_log=save_log)
    elif device_type == 'Cisco':
        action_type = '.1.3.6.1.4.1.9.9.96.1.1.1.1.3.{} i 4'.format(
            flag_num)  # 指定配置檔案操作型別,3為當前系統執行的配置
        filename = '.1.3.6.1.4.1.9.9.96.1.1.1.1.6.{} s "{}"'.format(flag_num, filename)  # 指定檔名
        ftp_ip = '.1.3.6.1.4.1.9.9.96.1.1.1.1.5.{} a {}'.format(flag_num, ftp_ip)  # 指定伺服器地址
        if connect_type == 'tftp':
            protocol_type = '.1.3.6.1.4.1.9.9.96.1.1.1.1.4.{} i 1'.format(flag_num)  # 2 #使用TFTP協議
        elif connect_type == 'ftp':  # 1 #使用FTP協議
            protocol_type == ''
        save_log = '.1.3.6.1.4.1.9.9.96.1.1.1.1.14.{} i 4'.format(flag_num)
        oid = '{action_type} {protocol_type} {ftp_ip} {filename} {save_log}'.format(
            action_type=action_type, filename=filename, protocol_type=protocol_type, ftp_ip=ftp_ip,
            save_log=save_log)
    print oid
    code, res = snmp_set(host, oid)
    if code:
        print '{}配置備份失敗'.format(host)
        print res
        return False,filename,ftp_ip
    else:
        print '{}配置備份成功'.format(host)
        time.sleep(2)
        # print res
        return True,filename,ftp_ip


def zip_file(filenames):
    has_file = False
    dest_path = os.path.join(ftp_directory, '{}.zip'.format(now_time))

    for path in filenames:
        if not os.path.exists(path):
            print '{}檔案不存在'.format(path)
            filename = path.split(os.sep)[-1]
            failhosts.append(filename.split('_')[0])
            continue
        run_cmd('chmod 777 {}'.format(path))
        dest_path = '{}/{}.zip'.format(ftp_directory, now_time)
        code, res = run_cmd('tar -rvf {} {}'.format(dest_path, path))
        if not code:
            has_file = True
            os.remove(path)
        else:
            failhosts.append(path.split('_')[0])
            print res
            # filename = path.split(os.sep)[-1]
            # print path, filename
            # with ZipFile(dest_path, mode='a') as fp:
            #     fp.write(path, filename)
    if has_file:
        return dest_path
    else:
        return 'no back files'


def get_result(status):
    status,name,host_member = status.result()
    if status:
        filenames.append(os.path.join(ftp_directory, name))
    else:
        failhosts.append(host_member)


if __name__ == '__main__':
    try:
        filenames = []
        failhosts = []
        if host_file not in ([], [''], '', None):
            with open(host_file[0], 'r') as f:
                hosts = f.readlines()
        else:
            hosts = host.split(',')

        p = ProcessPoolExecutor()
        for host_member in hosts:
            host_member = host_member.strip()
            if filename:
                name = '{}_{}_{}'.format(host_member, now_time, filename)
            else:
                name = '{}_{}.cfg'.format(host_member, now_time)

            res = p.submit(do_snmp, host_member, name, ftp_ip).add_done_callback(get_result)

        p.shutdown()
        if filenames:
            backup_file = zip_file(filenames)
            print '備份完成,備份檔案路徑:', backup_file

        if not filenames:
            backup_file = 'no back files'
            print '備份失敗'
        if failhosts:
            print '裝置備份失敗:', ','.join(failhosts)
        failhosts = ','.join(failhosts)
        if not failhosts:
            failhosts='null'
    except Exception as e:
        print '裝置備份失敗:', e