win_driver_install.py 8.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
import os
import re
import sys
import shutil
import logging
import argparse
import subprocess


def cmd_output(cmd):
    """
    Execute specified cmd and get the cmd output.

    :param cmd: Cmd which will be executed.
    """
    logger.debug("Sending command: %s" % cmd)
    try:
        p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    except Exception:
        stderror = p.stderr.readlines()
        error_msg = ("Failed to execute cmd %s!\n"
                     "Details refers: %s" % (cmd, stderror))
        logger.error(error_msg)
        sys.exit(1)
    stdoutput = p.stdout.readlines()
    logger.debug("Command output is %s" % stdoutput)


def getdpinst(vol_utils):
    """
    Get dpinst.exe and dpinst.xml.

    :param vol_utils: Volume of Win_utils.
    """
    if os.environ.get('PROCESSOR_ARCHITECTURE') == "AMD64":
        dpinst_dir = r"%s\dpinst_64.exe" % vol_utils
    else:
        dpinst_dir = r"%s\dpinst_32.exe" % vol_utils
    if not os.path.exists(r"C:\dpinst.exe"):
        shutil.copy(dpinst_dir, r"C:\dpinst.exe")
    else:
        logger.debug("dpinst.exe is already existed")
    if not os.path.exists(r"C:\dpinst.xml"):
        dpinst_xml = r"%s\dpinst.xml" % vol_utils
        shutil.copy(dpinst_xml, r"C:\dpinst.xml")
    else:
        logger.debug("dpinst.xml is already existed")


def certutil(vol_utils):
    """
    Install certificate.

    :param vol_utils: Volume of Win_utils.
    """
    certutil_cmd = r"certutil -addstore -f TrustedPublisher %s\redhat.cer" % vol_utils
    if not os.path.exists(r"C:\certutil.exe"):
        shutil.copy(r"%s\certutil.exe" % vol_utils, r"C:\certutil.exe")
    if not os.path.exists(r"C:\certadm.dll"):
        shutil.copy(r"%s\certadm.dll" % vol_utils, r"C:\certadm.dll")
    logger.info("Install certificate!")
    cmd_output(certutil_cmd)


def install_driver(driver_path, driver_name, vol_utils):
    """
    Install the specified driver.

    :param driver_path: Driver path which will be installed.
    :param driver_name: Driver name which will be installed.
    :param vol_utils: Volume of Win_utils.
    """
    install_driver_cmd = r"C:\dpinst.exe /A /PATH %s /C /LM /Q /F" % driver_path
    certutil(vol_utils)
    logger.info("Install driver %s!" % driver_name)
    cmd_output(install_driver_cmd)


def get_inf_files(driver_path, driver_name):
    """
    Get inf file path.exists

    :param driver_path: Driver path which will be installed.
    :param driver_name: Driver name which will be installed.
    :return inf_files: Inf file path.
    """
87
    inf_name = ("%s.inf" % driver_name).lower()
88 89 90
    inf_files = []
    for root, dirs, files in os.walk(driver_path):
        files_path = map(lambda x: os.path.join(root, x), files)
91
        inf_files += filter(lambda x: x.lower().endswith(inf_name), files_path)
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
    return inf_files


def uninstall_driver(driver_name):
    """
    Uninstall all specified drivers.
    e.g. has installed 105 and 110 versions for netkvm driver,
         both 105 and 110 will be uninstalled.

    :param driver_name: Driver name which will be installed.
    """
    driver_store = r"C:\Windows\system32\DriverStore\FileRepository"
    uninstall_driver_cmd = r"C:\dpinst.exe /U %s /C /LM /Q /D"
    if not os.path.exists(driver_store):
        logger.error("Driver store path %s does not exist." % driver_store)
        sys.exit(1)
    logger.info("Uninstall driver !")
    inf_files = get_inf_files(driver_store, driver_name)
    map(lambda x: cmd_output(uninstall_driver_cmd % x), inf_files)


def get_current_driver_ver(device_name):
    """
    Get current driver version for the specified driver.

    :param device_name: Corresponding device name with driver.
    :return: Current driver version.
    """
X
Xu Han 已提交
120
    key = r"\d*\.\d*\.\d*\.\d*"
121 122 123
    get_driver_ver_cmd = ("wmic path win32_pnpsigneddriver where"
                          " Devicename='%s' get driverversion" % device_name)
    driver_version = os.popen(get_driver_ver_cmd).read()
124 125
    if not driver_version.strip():
        return ""
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
    return re.findall(key, driver_version, re.M)[-1].strip()


def get_expected_driver_ver(driver_path, driver_name):
    """
    Get expected driver version, which is wanted to be installed.

    :param driver_path: Driver path which will be installed.
    :param driver_name: Driver name which will be installed.
    :return: Expected driver version.
    """
    inf_file = get_inf_files(driver_path, driver_name)
    with open("".join(inf_file)) as fd:
        driver_info = os.linesep.join(fd.readlines())
        return re.findall(r"DriverVer=.*,([\d.]+)", driver_info, re.M)[-1].strip()


def verify_driver_ver(driver_path, device_name, driver_name):
    """
    Verify the installed driver version is same as the expected.

    :param driver_path: Driver path which will be installed.
    :param device_name: Corresponding device name with driver.
    :param driver_name: Driver name which will be installed.
    """
    current_driver_ver = get_current_driver_ver(device_name)
    expected_driver_ver = get_expected_driver_ver(driver_path, driver_name)
    logger.info("Compare whether driver version is same as expected.")
    if current_driver_ver != expected_driver_ver:
        error_msg = ("Driver installation failed !\n"
                     "Current driver version %s is not equal"
                     " to the expected %s." % (current_driver_ver, expected_driver_ver))
        logger.error(error_msg)
        sys.exit(1)
    logger.info("Current driver version %s is same as expected." % current_driver_ver)


def show_log_output(result_file):
    """
    Show execution logs.

    :param result_file: File which saves execution logs.
    """
    with open(result_file) as fd:
X
Xu Han 已提交
170
        print(os.linesep.join(fd.readlines()))
171

L
Lucas Meneghel Rodrigues 已提交
172

173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description='Windows Driver Operation')
    parser.add_argument('-i', '--install_driver',
                        help='operation for install driver',
                        dest='install_driver', action='store_true')
    parser.add_argument('-u', '--uninstall_driver',
                        help='operation for uninstall driver',
                        dest='uninstall_driver', action='store_true')
    parser.add_argument('-q', '--query_driver',
                        help='operation for query driver',
                        dest='query_driver', action='store_true')
    parser.add_argument('-v', '--verify_driver',
                        help='operation for verify driver',
                        dest='verify_driver', action='store_true')
    parser.add_argument('-o', '--log_output',
                        help='operation for show log output',
                        dest='log_output', action='store_true')
    parser.add_argument('--driver_path',
                        help='driver path', dest='driver_path', action='store')
    parser.add_argument('--driver_name',
                        help='driver name', dest='driver_name', action='store')
    parser.add_argument('--device_name',
                        help='the corresponding device name with driver',
                        dest='device_name', action='store')
    parser.add_argument('--vol_utils',
                        help='volume of WIN_UTILS',
                        dest='vol_utils', action='store')
    arguments = parser.parse_args()

    result_file = r"C:\driver_install.log"
    logger = logging.getLogger("driver_install")
    logger.setLevel(logging.DEBUG)
206
    fh = logging.FileHandler(result_file, mode="a+")
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
    fh.setLevel(logging.DEBUG)
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    fh.setFormatter(formatter)
    logger.addHandler(fh)

    if not os.path.exists(arguments.driver_path):
        logger.error("Driver path %s does not exist" % arguments.driver_path)
        sys.exit(1)

    if arguments.uninstall_driver:
        getdpinst(arguments.vol_utils)
        uninstall_driver(arguments.driver_name)
    elif arguments.install_driver:
        getdpinst(arguments.vol_utils)
        install_driver(arguments.driver_path, arguments.driver_name,
                       arguments.vol_utils)
    elif arguments.query_driver:
        current_driver_ver = get_current_driver_ver(arguments.device_name)
        msg = "Current driver version for %s is %s" % (arguments.driver_name,
                                                       current_driver_ver)
        logger.debug(msg)
    elif arguments.verify_driver:
        verify_driver_ver(arguments.driver_path, arguments.device_name,
                          arguments.driver_name)
    elif arguments.log_output:
X
Xu Han 已提交
232
        print("Execution log:\n")
233
        show_log_output(result_file)
X
Xu Han 已提交
234
        print("DPINST.log:\n")
235
        show_log_output(r"C:\Windows\DPINST.log")