Firmware批量上传工具2.0

Zss 发表于:

之前编写的Firmware批量上传工具,前提是自己下载好了所有的Firmware固件放置到文件中在运行此工具

于是发现每次发版本的时候,有很多个固件,我需要每次都将其全部下载下来,比较麻烦,所以在之前的工具上添加新的功能

输入搜索的关键字来在服务器上下载所对应的版本和添加自定义ip来上传的测试系统上

通过版本号,或者设备的型号+版本号来确定固件,所只搜索版本则,当前的版本的所有固件下载下来,这样子就解决的每次下载很多个版本的问题

#coding:gbk
import os,zipfile,requests,time
from lxml import etree
from logging import *
basicConfig(level=ERROR)
#添加关键字搜索自动下载Firmware,添加自定义ip
class Zip_fw():
    def __init__(self):
        """
        设置以当前文件夹下的各个文件为公共路径
        """
        self.fw_bin_path = os.getcwd()+'\\firmware\\'
        self.fw_pkg_path = os.getcwd()+'\\pkg\\'
        self.fw_name_list = []

    def check_folder(self):
        """
        判断两个文件夹是否存在,不存在则创建,存在则pass
        删除旧的pkg文件
        """

        if not os.path.exists(self.fw_bin_path):
            os.makedirs(self.fw_bin_path)
        else:
            old_bin = os.listdir(self.fw_bin_path)
            for i in old_bin:
                os.remove(self.fw_bin_path + i)

        if not os.path.exists(self.fw_pkg_path):
            os.makedirs(self.fw_pkg_path)
        else:
            old_flie = os.listdir(self.fw_pkg_path)
            for i in old_flie:
                os.remove(self.fw_pkg_path + i)


    def get_fw_name(self):
        """
        获取firmware中的各个bin文件
        """
        fw_name_list = os.listdir(self.fw_bin_path)
        for i in fw_name_list:
            if '.bin' in i:
                self.fw_name_list.append(i)
        if len(self.fw_name_list) == 0:
            print('         firmware文件夹似乎没看到有固件哦! O(∩_∩)O\n')
            print('          请将bin文件放在当前路径的firmware文件夹下')
            raw_input('\n'+'-'*25 + '>  回车结束  <'+'-'*25)
            exit()
        return self.fw_name_list

    def make_fw_meta_note(self,fw_name):
        """
        生成fw.meta文件和note文件
        """
        if os.path.isfile(self.fw_bin_path + 'fw.meta'):
            os.remove(self.fw_bin_path + 'fw.meta')
        with open(self.fw_bin_path + 'fw.meta','a') as f:
            if len(fw_name.split('_')) != 4:
                f.write('version:' + fw_name.split('_')[1] + '\n')
            else:
                f.write('version:' + fw_name.split('_')[2] + '\n')
            f.write('modelCode:' + fw_name.split('_')[0] + '\n')
            f.write('imageFileName:' + fw_name + '\n')
            f.write('releaseNoteFileName:release_note.txt')
            note_data = """ release_note_file """
            if os.path.isfile(self.fw_bin_path + 'release_note.txt'):
                os.remove(self.fw_bin_path + 'release_note.txt')
            with open(self.fw_bin_path + 'release_note.txt','a') as f:
                f.write(note_data)

    def zip_fw(self,fw_name):
        """
        防止重复文件名情况,存在则先删除此文件,再将其文件打包更名
        """

        if os.path.isfile(self.fw_pkg_path + fw_name[:-3] + 'pkg'):
            os.remove(self.fw_pkg_path + fw_name[:-3] + 'pkg')

        file_list = [fw_name,'fw.meta','release_note.txt']
        fw_pkg = zipfile.ZipFile(self.fw_pkg_path + fw_name[:-3] + 'zip','w', zipfile.ZIP_STORED)
        for i in file_list:
            file_path = os.path.join(self.fw_bin_path,i)
            fw_pkg.write(file_path,i)
        fw_pkg.close()
        os.rename(self.fw_pkg_path + fw_name[:-3] + 'zip',self.fw_pkg_path + fw_name[:-3] + 'pkg') #改文件后缀
        print('Firmware:%s ---> 打包成功! p( ^ O ^ )q')%(fw_name[:-3] + 'pkg')
        time.sleep(0.2)

    def main(self):
        """
        固件打包主体
        """
        bin_list = self.get_fw_name()
        print('-'*26 + '>  Firmware 打包  <'+'-'*26+'\n')
        for file_name in bin_list:
            self.make_fw_meta_note(file_name)
            self.zip_fw(file_name)
        print('\n')

class Care():
    def __init__(self):
        """
        设置公共路径
        """
        self.fw_pkg_path = os.getcwd()+'\\pkg\\'

    def get_token(self,ip):
        """
        模拟登陆care,获取token
        """
        url = 'http://{}/login'.format(str(ip))
        headers = {
        'Authorization':'Basic Y2FyZTpzdXBlcndpZmk=',
        'Host':'{}'.format(str(ip)),
        'Referer':'http://{}/login'.format(str(ip))
        }
        rsp = requests.get(url=url,headers=headers).text
        token = rsp[10:][:-13]
        return token

    def up_fw(self,ip,token,fw_pkg_name):
        """
        将不同的pkg文件依次上传到单台服务器
        """
        headers = {'Host':ip,
        'Connection':'keep-alive',
        'Referer':'http://%s/firmwares'%ip,
        'X-Auth-Token':token
        }
        file_data = open(self.fw_pkg_path + fw_pkg_name,'rb')
        if len(fw_pkg_name.split('_')) == 4:
            care_fw_name = 'Auto_'+fw_pkg_name.split('_')[0] + '_' + fw_pkg_name.split('_')[2]
        else:care_fw_name = 'Auto_'+fw_pkg_name.split('_')[0] + '_' + fw_pkg_name.split('_')[1]

        file_list = {"projectId": (None,"-1"),"siteId": (None,"-1"),"name": (None,care_fw_name),"file": (fw_pkg_name,file_data.read(),"application/octet-stream")}
        url = 'http://%s/firmwares'%ip
        print('Firmware:%s ---> 正在上传到 %s Server 请稍后...'%(care_fw_name,ip))
        rsp = requests.post(url=url,headers=headers,files=file_list)
        if rsp.status_code == 200:print('Firmware:%s ---> 上传成功!p( ^ O ^ )q\n'%care_fw_name)
        else:
            print('Firmware:%s ---> 上传失败! +﹏+')%care_fw_name
            print('Firmware:{} ---> 错误消息为:{}\n'.format(care_fw_name,rsp.text))



class Down_fw():
    def __init__(self):
        """
        设置以当前文件夹下的各个文件为公共路径
        """
        self.fw_bin_path = os.getcwd()+'\\firmware\\'
        self.fw_pkg_path = os.getcwd()+'\\pkg\\'
        self.fw_down_list = []  #需要下载的bin文件

    def vs_choicc(self):
        print('-' * 15 + '>  欢迎使用 Firmware 上传工具  <' + '-' * 15)
        print('使用说明:')
        print('1:输入需要上传的Firmware版本')
        print('2:note文件和meta文件不需要,会自动生成')
        print('3:请勿随意修改bin文件的文件名,默认格式就好,格式为:型号_版本_日期.bin')
        print('4:可以选择多个服务器来上传,但若服务器不存在请不选择此服务器')
        print('5:选择完服务器后请输入0,开始进行上传')
        print('6:默认使用care/superwifi账号上传,若账号错误则上传失败')
        print('7:固件的作用域为:All Projects 和 All Sites')
        print('-' * 62)
        vs_choice = raw_input('输入您的Firmware版本:')
        return vs_choice

    def check_fw(self,vs_choice):
        print('-' * 5 + '>  关键字为:%s 正在搜索Firmware:   <'%vs_choice + '-' * 5 + '\n')
        ac_url = 'http://10.6.127.6/redmine/projects/altaicare/files'
        cm_url = 'http://10.6.127.6/redmine/projects/a8n-openwrt/files'
        try:
            ac_rsp = requests.get(ac_url).content
            ac_xml = etree.HTML(ac_rsp)
            cm_rsp = requests.get(cm_url).content
            cm_xml = etree.HTML(cm_rsp)
            fw_name_list = ac_xml.xpath('//*[@id="content"]/table/tbody/tr/td[1]/a/text()')+cm_xml.xpath('//*[@id="content"]/table/tbody/tr/td[1]/a/text()')
            fw_url_list = ac_xml.xpath('//*[@id="content"]/table/tbody/tr/td[1]/a/@href')+cm_xml.xpath('//*[@id="content"]/table/tbody/tr/td[1]/a/@href')
            fw_info_list = zip(fw_name_list,fw_url_list)
            #info(fw_info_list)
        except Exception as e:
            print '错误:%s'%e
        if 'AC'in vs_choice:
            for i in fw_info_list:
                if 'A3'in i[0] and 'AC'in i[0]or 'A2'in i[0]and 'AC'in i[0]or 'C1'in i[0]and 'AC'in i[0]or 'A8'in i[0]and 'AC'in i[0]or 'C2'in i[0]and 'AC'in i[0]:
                    if vs_choice in i[0]:
                        fw_url = 'http://10.6.127.6' + i[1]
                        info(fw_url)
                        self.fw_down_list.append((i[0],fw_url))
        else:
            for i in fw_info_list:
                if 'A3'in i[0] and 'AC'not in i[0]or 'A2'in i[0]and 'AC'not in i[0]or 'C1'in i[0]and 'AC'not in i[0]or 'A8'in i[0]and 'AC'not in i[0]or 'C2'in i[0]and 'AC'not in i[0]:
                    if vs_choice in i[0]:
                        fw_url = 'http://10.6.127.6' + i[1]
                        info(fw_url)
                        self.fw_down_list.append((i[0],fw_url))
        if len(self.fw_down_list)==0:
            print('关键字:%s,暂时没有搜索到相对应的Firmware,请重新搜索...'%(vs_choice))
            raw_input('回车结束')
            exit()
        else:
            print('-' * 15 + '>  搜索到的Firmware如下:   <' + '-' * 15 + '\n')
            for i in self.fw_down_list:
                print '---> %s'%(i[0].strip('.bin'))
        print('-' * 62 + '\n')
        return self.fw_down_list

    def down_fw(self,fw_list):
        info(fw_list)
        print('\n'+ '-' * 20 + '>  Firmware 下载  <'+ '-' * 20 + '\n')
        number = len(fw_list)
        index = 1
        for i in fw_list:
            info(i[1])
            print('文件总数:%s  当前下载:%d  当前文件名:%s\n' % (str(number), index, i[0].strip('.bin')))
            rsp = requests.get(i[1]).content
            try:
                with open(self.fw_bin_path + i[0],'wb') as f:
                    f.write(rsp)
                print('Firmware:%s --->下载成功! p( ^ O ^ )q\n' % i[0])
            except Exception as e:
                print '文件下载失败,错误信息:%s'%e
            index += 1

def main(ip):
    """
    给单台服务器进行上传固件操作
    """
    up_fw = Care()
    token = up_fw.get_token(ip)
    print('-'*18 + '>  Firmware 上传 ---> %s <'%ip+'-'*18+'\n')
    for pkg in os.listdir(up_fw.fw_pkg_path):
        up_fw.up_fw(ip,token,pkg)

def ip_choice():
    """
    用户选择列表,支持多选来分别给不同的服务器上传固件
    """
    ip_list = ['52.74.53.225','52.74.80.211','10.6.161.123','10.6.161.135','10.6.161.20']
    choice_list = []
    print('服务器地址如下:')
    index = 1
    print('(0).开始上传')
    for ip in ip_list:
        if ip == '52.74.53.225':
            print('(%d).Alati Care 2.2    ---> %s'%(index,ip))
        elif ip == '52.74.80.211':
            print('(%d).Alati Care 2.1    ---> %s'%(index,ip))
        elif ip == '10.6.161.123':
            print('(%d).On Premise        ---> %s'%(index,ip))
        elif ip == '10.6.161.135':
            print('(%d).On Premise        ---> %s'%(index,ip))
        elif ip == '10.6.161.20':
            print('(%d).Altai Gate        ---> %s'%(index,ip))
        else:pass
        index += 1
    print('(6).自定义IP')
    print('-'*62 + '\n')
    while 1:
        choice = raw_input('输入您的选择:')
        if choice == '0':break
        elif choice == '1':choice_list.append('52.74.53.225')
        elif choice == '2':choice_list.append('52.74.80.211')
        elif choice == '3':choice_list.append('10.6.161.123')
        elif choice == '4':choice_list.append('10.6.161.135')
        elif choice == '5':choice_list.append('10.6.161.20')
        elif choice == '6':
            ip = raw_input('输入您的服务器IP:')
            choice_list.append(ip)
            break
        else:pass
    print('\n')
    return choice_list

def vs_choice():
    print('-'*15 + '>  欢迎使用 Firmware 上传工具 2.0  <'+'-'*15)
    print('使用说明:')
    print('1:输入你的关键字来搜索Firmware')
    print('2:搜索:2.2.0.1604.AC05  将上传所有1604.AC05的Firmware')
    print('3:搜索:2.1.0.1553  将上传所有1553的Firmware')
    print('4:搜索:C2_2.1.0.1553  将上传C2_1553的Firmware')
    print('5:关键字区分大小写')
    print('6:可以选择多个服务器来上传,但若服务器不存在请不选择此服务器')
    print('7:选择完服务器后请输入0,开始进行上传')
    print('8:默认使用care/superwifi账号上传,若账号错误则上传失败')
    print('9:固件的作用域为:All Projects 和 All Sites')
    print('-'*62)
    vs_choice = raw_input('输入你的关键字:')
    return vs_choice

if __name__ == '__main__':
    down_fw = Down_fw()
    check = Zip_fw()
    make_pkg = Zip_fw()
    vs_choice = vs_choice()
    fw_list = down_fw.check_fw(vs_choice)
    ip_list = ip_choice()
    check.check_folder()
    down_fw.down_fw(fw_list)
    make_pkg.main()
    for ip in ip_list:
        main(ip)
    raw_input('\n'+'-'*25 + '>  回车结束  <'+'-'*25)