1# -*- coding:utf-8 -*- 2import traceback 3import uuid 4import sys 5import subprocess 6import os 7import time 8import re 9import shutil 10import random 11import platform 12import socket 13 14from core.base import BaseApp, dec_stepmsg 15from util.file_locker import FileLock 16from util.log_info import logger 17from util.time_info import get_now_time_str_info, get_now_time_info, Timeout, timeout 18from aw.Download.Download import * 19from aw.Common.Constant import CONSTANT 20from aw.Common.Common import getFileName 21from aw.ExtractFile.ExtractFile import * 22from aw.Common.Common import getHostIp, copyFile, copyDirectory 23 24total_time = "" 25lock_suffix = CONSTANT.File.LOCK_SUFFIX 26suc_file = CONSTANT.File.SUC_FILE 27failed_file = CONSTANT.File.FAILED_FILE 28REBOOT_TIMEOUT = 20000000 29 30 31class liteOsUpgrade_RK3568(BaseApp): 32 ''' 33 @author: cwx1076044 34 ''' 35 36 def __init__(self, param_file): 37 super().__init__(param_file) 38 self.param_List = ["upgrade_upgradeLocation", "sn"] 39 40 @dec_stepmsg("hongmeng RK3568 flash") 41 def excute(self): 42 ''' 43 #=================================================================================== 44 # @Method: excute(self) 45 # @Precondition: none 46 # @Func: 升级执行入口 47 # @PostStatus: none 48 # @eg: excute() 49 # @return: True or Flase 50 #=================================================================================== 51 ''' 52 step_index = self.params_dict.get("step_list").index("liteOsUpgrade_RK3568_app") 53 54 # # 执行下载 55 # try: 56 # if not self.download(): 57 # CONSTANT.ENVERRMESSAGE = "image download fail" 58 # logger.printLog(CONSTANT.ENVERRMESSAGE) 59 # return 98 60 # except Exception as e: 61 # logger.error(e) 62 # #raise e 63 # return 98 64 65 # 执行升级 66 try: 67 return_code = self.upgrade() 68 if not return_code: 69 CONSTANT.ENVERRMESSAGE = "board upgrade fail" 70 logger.printLog(CONSTANT.ENVERRMESSAGE) 71 return False 72 if return_code == 98: 73 return 98 74 if return_code == 99: 75 return 99 76 return True 77 except Exception as e: 78 logger.error(e) 79 raise e 80 81 @dec_stepmsg("upgrade") 82 @timeout(3600) 83 def upgrade(self): 84 ''' 85 #=================================================================================== 86 # @Method: upgrade(self) 87 # @Precondition: none 88 # @Func: 升级相关业务逻辑 89 # @PostStatus: none 90 # @eg: upgrade() 91 # @return: True or Flase 92 #=================================================================================== 93 ''' 94 global local_image_path, loader_tool_path, sn, LocationID, test_num, system_type 95 system_type = platform.system() 96 hostname = socket.gethostname() 97 ipaddress = socket.gethostbyname(hostname) 98 logger.printLog("******系统ip为:%s ******" % ipaddress) 99 logger.printLog("******系统为:%s ******" % system_type) 100 if system_type == "Windows": 101 lock_file = r'C:/deviceupgrade/task.lock' 102 else: 103 lock_file = '/home/openharmony/deviceupgrade/task.lock' 104 # 如果上一个任务没执行完成,不往下继续执行 105 if not is_can_exec(lock_file): 106 return False 107 version_savepath = self.params_dict.get("img_path") 108 upgrade_test_type = self.params_dict.get("UpgradeTestType") 109 sn = self.params_dict.get("sn") 110 LocationID = self.params_dict.get("LocationID") 111 test_num = self.params_dict.get("test_num") 112 pr_url = self.params_dict.get("pr_url") 113 logFilePath = self.logFilePath 114 logger.info(logFilePath) 115 if system_type == "Windows": 116 r = logFilePath.rfind("\\") 117 else: 118 r = logFilePath.rfind("/") 119 report_path = logFilePath[:r] 120 logger.info(report_path) 121 scriptpath = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(os.path.dirname(__file__))))) 122 logger.info(scriptpath) 123 local_image_path = os.path.join(version_savepath) 124 logger.info(local_image_path) 125 if system_type == "Windows": 126 loader_tool_path = os.path.join(scriptpath, "resource", "RK3568_tool", "upgrade_tool.exe") 127 else: 128 loader_tool_path = os.path.join(scriptpath, "resource", "RK3568_tool", "upgrade_tool") 129 logger.info(loader_tool_path) 130 mini_path = os.path.join(local_image_path, "mini_system_test", "L2_mini_system_test.py") 131 archive_path = os.path.join(version_savepath) 132 if not self.check_devices_mode(): 133 check_devices_cmd = "hdc list targets" 134 f = send_times(check_devices_cmd) 135 logger.info(f) 136 delete_file_lock(lock_file) 137 if not f or "Empty" in f: 138 logger.error("No devices found,please check the device.") 139 return False 140 else: 141 logger.info("3568 board is connected.") 142 return self.check_devices_mode() 143 else: 144 # 下載鏡像 145 upgrde_loader_cmd = "%s -s %s UL %s/MiniLoaderAll.bin -noreset" % (loader_tool_path, LocationID, local_image_path) 146 h = sendCmd(upgrde_loader_cmd) 147 logger.info(h) 148 if "Upgrade loader ok" not in h: 149 logger.error("Download MiniLoaderAll.bin Fail!") 150 delete_file_lock(lock_file) 151 return False 152 else: 153 logger.printLog("Download MiniLoaderAll.bin Success!") 154 # time.sleep(3) 155 write_gpt_cmd = "%s -s %s DI -p %s/parameter.txt" % (loader_tool_path, LocationID, local_image_path) 156 j = sendCmd(write_gpt_cmd) 157 logger.info(j) 158 if "Write gpt ok" not in j: 159 logger.error("Failed to execute the parameter.txt") 160 delete_file_lock(lock_file) 161 return False 162 else: 163 logger.printLog("Successfully executed parameter.txt.") 164 # time.sleep(5) 165 download_uboot_cmd = "%s -s %s DI -uboot %s/uboot.img %s/parameter.txt" % ( 166 loader_tool_path, LocationID, local_image_path, local_image_path) 167 k = sendCmd(download_uboot_cmd) 168 logger.info(k) 169 if "Download image ok" not in k: 170 logger.error("Failed to download the uboot.image!") 171 delete_file_lock(lock_file) 172 if self.check_devices_mode(): 173 return 98 174 return False 175 else: 176 logger.printLog("The uboot.image downloaded successfully!") 177 # time.sleep(5) 178 if not self.flash_version(): 179 delete_file_lock(lock_file) 180 return False 181 reboot_devices_cmd = "%s -s %s RD" % (loader_tool_path, LocationID) 182 reboot_result = sendCmd(reboot_devices_cmd) 183 logger.info(reboot_result) 184 time.sleep(50) 185 # try: 186 # if upgrade_test_type != "mini_system_test": 187 # if not start_cmd(sn): 188 # if self.check_devices_mode(): 189 # return 98 190 # return False 191 # except Exception as t: 192 # logger.info(t) 193 # if self.check_devices_mode(): 194 # return 98 195 # return False 196 # time.sleep(10) 197 if "Reset Device OK" not in reboot_result: 198 logger.error("Failed to reboot the board!") 199 delete_file_lock(lock_file) 200 return False 201 else: 202 logger.info("Reboot successfully!") 203 # os.system("hdc -t %s shell reboot" % sn) 204 # time.sleep(40) 205 # os.system("hdc -t %s shell set persist.usb.setting.gadget_conn_prompt false" % sn) 206 delete_file_lock(lock_file) 207 logger.printLog("******下载完成,升级成功,开始进行冒烟测试******") 208 hdc_kill() 209 # os.system("hdc_std -t %s shell hilog -w start" % sn) 210 # os.system("hdc_std -t %s shell hilog -w start -t kmsg" % sn) 211 if upgrade_test_type == "null": 212 return True 213 # 临时安装 214 # self.install_third_packages() 215 216 screenshot_path = os.path.join(local_image_path, "screenshot") 217 script_path = os.path.join(screenshot_path, 'new_script') 218 logger.info(script_path) 219 # py_path = os.path.join(script_path, "main.py") 220 py_file = "main.py" 221 new_report_path = os.path.join(report_path, "result") 222 logger.info(new_report_path) 223 time_sleep = random.randint(3, 7) 224 time.sleep(time_sleep) 225 try: 226 if not os.path.exists(new_report_path): 227 os.mkdir(new_report_path) 228 except Exception as e: 229 logger.error(e) 230 return 98 231 if upgrade_test_type == "mini_system_test": 232 save_path = os.path.join(new_report_path) 233 if exec_cmd(mini_path, sn, save_path, archive_path) == 98: 234 return 98 235 return True 236 237 if not upgrade_test_type or upgrade_test_type == "smoke_test": 238 # 进到工程目录 239 cur_path = os.getcwd() 240 os.chdir(script_path) 241 test_return = cmd_test(script_path, py_file, sn, test_num, new_report_path, pr_url) 242 # 执行完回到原来的目录 243 os.chdir(cur_path) 244 if test_return == 1: 245 return True 246 if test_return == 98: 247 return 98 248 if test_return == 99: 249 return 99 250 else: 251 return False 252 253 # def install_third_packages(self): 254 # try: 255 # logger.debug('python -m pip list') 256 # rst = subprocess.run('python -m pip list', capture_output=True, shell=True, encoding='utf-8', timeout=30) 257 # logger.debug(rst) 258 # logger.debug('python -m pip install pytest -U') 259 # rst = subprocess.run('python -m pip install pytest -U', capture_output=True, shell=True, encoding='utf-8', timeout=600) 260 # logger.debug(rst) 261 # logger.debug('python -m pip uninstall pytest-testreport -y') 262 # rst = subprocess.run('python -m pip uninstall pytest-testreport -y', capture_output=True, shell=True, encoding='utf-8', timeout=600) 263 # logger.debug(rst) 264 # logger.debug('python -m pip install pytest-html -U') 265 # rst = subprocess.run('python -m pip install pytest-html -U', capture_output=True, shell=True, encoding='utf-8', timeout=600) 266 # logger.debug(rst) 267 # logger.debug('python -m pip list') 268 # rst = subprocess.run('python -m pip list', capture_output=True, shell=True, encoding='utf-8', timeout=30) 269 # logger.debug(rst) 270 # except: 271 # logger.error(traceback.format_exc()) 272 273 @timeout(1000) 274 def flash_version(self): 275 partList = ["boot_linux", "system", "vendor", "userdata", "resource", "ramdisk", "chipset", "sys-prod", "chip-prod"] 276 for i in partList: 277 if not os.path.exists("%s/%s.img" % (local_image_path, i)): 278 logger.printLog("%s.img is not exist, ignore" % i) 279 continue 280 loadcmd = "%s -s %s DI -%s %s/%s.img" % (loader_tool_path, LocationID, i, local_image_path, i) 281 p = sendCmd(loadcmd) 282 logger.info(p) 283 # time.sleep(5) 284 if "Download image ok" not in p: 285 logger.info("try download %s again!" % i) 286 time.sleep(1) 287 second_cmd = "%s -s %s DI -%s %s/%s.img" % (loader_tool_path, LocationID, i, local_image_path, i) 288 f = sendCmd(second_cmd) 289 logger.info(f) 290 if "Download image ok" not in f: 291 logger.printLog("Failed to download the %s.img!" % i) 292 if self.check_devices_mode(): 293 return 98 294 else: 295 return False 296 return True 297 else: 298 logger.printLog("The %s.img downloaded successfully!" % i) 299 return True 300 301 @timeout(120) 302 def check_devices_mode(self): 303 check_times = 0 304 while check_times < 5: 305 check_mode_cmd = "%s LD" % loader_tool_path 306 g = sendCmd(check_mode_cmd) 307 logger.info(g) 308 # time.sleep(40) 309 if "LocationID=%s Mode=Loader" % LocationID in g: 310 logger.info("3568 board has entered the Loader mode successfully!") 311 return True 312 else: 313 # if test_num != "2/2": 314 # hdc_kill() 315 os.system("hdc -t %s shell reboot loader" % sn) 316 time.sleep(8) 317 check_times += 1 318 logger.error("Failed to enter the loader mode!") 319 return False 320 321 # @dec_stepmsg("download") 322 # @timeout(360) 323 # def download(self): 324 # ''' 325 # #=================================================================================== 326 # # @Method: download(self) 327 # # @Precondition: none 328 # # @Func: 构建下载到本地的路径,执行相应包的下载 329 # # @PostStatus: none 330 # # @eg: download() 331 # # @return: True or Flase 332 # #=================================================================================== 333 # ''' 334 # global version_savepath, version_name 335 # dir_path = CONSTANT.Path.getDirPath() 336 # if self.params_dict.get("pbiid"): 337 # version_path = self.params_dict.get("pbiid") 338 # version_name = str(uuid.uuid5(uuid.NAMESPACE_URL, str(self.params_dict.get("pbiid")) + "FASTBOOT")) 339 # version_savepath = os.path.join(dir_path, self.params_dict.get("flash_type"), version_name) 340 # else: 341 # version_path = self.params_dict.get("upgrade_upgradeLocation") 342 # version_name = str(uuid.uuid5(uuid.NAMESPACE_URL, (self.params_dict.get("upgrade_upgradeLocation")))) 343 # version_savepath = os.path.join(dir_path, version_name, "img") 344 # # 执行img下载 345 # 346 # if self.params_dict.get("isDownload") == "True": 347 # logger.printLog("不需要做下载,直接返回") 348 # return True 349 # 350 # import hashlib 351 # save_file_str = version_path.replace("/", "").replace("\\", "") 352 # save_file_name = hashlib.sha1(save_file_str.encode("utf-8")).hexdigest() 353 # logger.info("download hash string:%s, hash value:%s" % (save_file_str, save_file_name)) 354 # save_path_file = os.path.join(dir_path, "record", "%s%s" % (save_file_name, ".txt")) 355 # logger.info(version_savepath) 356 # logger.info(save_path_file) 357 # t = version_savepath[:-4] 358 # logger.info(t) 359 # if not self.excutedown(version_path, version_savepath, save_path_file, False): 360 # logger.info("download again!") 361 # try: 362 # if os.path.exists(t): 363 # shutil.rmtree(t) 364 # logger.info("remove dir succeed") 365 # if os.path.exists(save_path_file): 366 # logger.info("remove file succeed") 367 # os.remove(save_path_file) 368 # except Exception as p: 369 # logger.error(p) 370 # raise Exception(p) 371 # time.sleep(15) 372 # if not self.excutedown(version_path, version_savepath, save_path_file, False): 373 # logger.error("download img fail") 374 # return False 375 # 376 # # 保存本地版本路径给devicetest去版本路径下取用例 377 # saveVersion(save_path_file, version_savepath) 378 # return True 379 # 380 # def excutedown(self, source_path, download_dir, suc_mark, is_file): 381 # ''' 382 # #=================================================================================== 383 # # @Method: excutedown(source_path, download_dir, suc_mark, is_file) 384 # # @Precondition: none 385 # # @Func: 执行下载动作 386 # # @PostStatus: none 387 # # @Param: source_path:资源文件路径 388 # # download_dir:文件下载到本地的文件夹路径 389 # # is_file:是否是文件 390 # # @eg: excutedown("xxxx", "D:\\local\\image", suc_mark, Flase) 391 # # @return: True or Flase 392 # #=================================================================================== 393 # ''' 394 # failed_mark = os.path.join(download_dir, failed_file) 395 # lock_path = os.path.join(download_dir, lock_suffix) 396 # file_lock = FileLock() 397 # 398 # if isDownLoadSuccess(download_dir, suc_mark, failed_mark): 399 # return True 400 # try: 401 # nowtime = get_now_time_str_info() 402 # logger.printLog("%s Downloading, please wait" % nowtime) 403 # file_lock.lockFile(lock_path) 404 # ret = "" 405 # logger.info("Get lock. Start to ") 406 # try: 407 # if self.params_dict.get("bt_enable") and self.params_dict.get("bt_enable") == "True": 408 # ret = downloadByBitComet(source_path, download_dir, os_method) 409 # elif source_path.startswith('\\\\'): 410 # ret = downloadByCopy(source_path, download_dir, is_file) 411 # elif self.params_dict.get("pbiid"): 412 # ret = downlaodByDownloadTool(version_savepath, self.params_dict.get("version_type"), "FASTBOOT", 413 # self.params_dict.get("pbiid")) 414 # elif source_path.startswith("http"): 415 # ret = run_download(source_path, download_dir) 416 # except Exception as f: 417 # logger.error(f) 418 # 419 # if source_path.endswith(".zip"): 420 # zip_name = os.path.basename(source_path) 421 # ret = extractZipFile(os.path.join(download_dir, zip_name), download_dir) 422 # if source_path.endswith(".tar.gz") or (source_path.startswith("http") and ("file_id=" in source_path)): 423 # if source_path.startswith("http") and ("file_id=" in source_path): 424 # if source_path.endswith(".tar.gz"): 425 # zip_name = source_path.split('=')[-1] 426 # else: 427 # zip_name = "out.tar.gz" 428 # else: 429 # zip_name = os.path.basename(source_path) 430 # ret = unTarFile(os.path.join(download_dir, zip_name), download_dir) 431 # nowtime = get_now_time_str_info() 432 # logger.printLog("%s download to %s end" % (nowtime, download_dir)) 433 # 434 # if not ret: 435 # with open(failed_mark, "a+") as fp: 436 # fp.write("") 437 # return ret 438 # except Exception as e: 439 # logger.printLog(e) 440 # #raise Exception(e) 441 # finally: 442 # file_lock.releaseFile() 443 444 445@timeout(30) 446def hdc_kill(): 447 logger.info("kill the process") 448 os.system("hdc kill") 449 time.sleep(2) 450 logger.info("start the process") 451 os.system("hdc -l5 start") 452 # time.sleep(10) 453 454 455def sendCmd(mycmd): 456 result = "".join(os.popen(mycmd).readlines()) 457 return result 458 459 460def send_times(mycmd): 461 times = 0 462 outcome = sendCmd(mycmd) 463 while times < 3: 464 if not outcome or "Empty" in outcome: 465 times += 1 466 time.sleep(3) 467 else: 468 time.sleep(3) 469 return outcome 470 return outcome 471 472 473@timeout(180) 474def start_cmd(sn): 475 try: 476 os.system("hdc -l5 start") 477 # power_cmd = "hdc -t %s shell \"power-shell setmode 602\"" % sn 478 hilog_cmd = "hdc -t %s shell \"hilog -w start -l 400000000 -m none\"" % sn 479 # logger.info(power_cmd) 480 logger.info(hilog_cmd) 481 # power_result = sendCmd(power_cmd) 482 # logger.info(power_result) 483 # if not power_result: 484 # return False 485 # number = 0 486 # while "Set Mode Success" not in power_result and number < 30: 487 # time.sleep(4) 488 # power_result = sendCmd(power_cmd) 489 # logger.info(power_result) 490 # number += 1 491 # if number >= 20: 492 # logger.error("Set mode failed") 493 # return False 494 hilog_result = sendCmd(hilog_cmd) 495 logger.info(hilog_result) 496 return True 497 except Exception as e: 498 logger.error(e) 499 return False 500 501 502@timeout(900) 503def cmd_test(screenshot_path, py_file, device_num, test_num, new_report_path, pr): 504 global total_time 505 save_screenshot_path = os.path.join(new_report_path, "screenshot_result") 506 logger.info(save_screenshot_path) 507 time_sleep = random.randint(1, 5) 508 time.sleep(time_sleep) 509 try: 510 if not os.path.exists(save_screenshot_path): 511 os.mkdir(save_screenshot_path) 512 logger.info(save_screenshot_path) 513 base_screenshot_path = os.path.join(new_report_path, "screenshot_base") 514 if not os.path.exists(base_screenshot_path): 515 os.mkdir(base_screenshot_path) 516 logger.info(base_screenshot_path) 517 except Exception as e: 518 logger.error(e) 519 return 98 520 # config_path = os.path.join(screenshot_path, "app_capture_screen_test_config.json") 521 py_cmd = "python {} --device_num {} --test_num {} --save_path {} --pr {}".format(py_file, device_num, test_num, save_screenshot_path, pr) 522 time1 = time.time() 523 result = outCmd(py_cmd, save_screenshot_path, base_screenshot_path, screenshot_path) 524 time2 = time.time() 525 total_time = int(time2 - time1) 526 logger.info("total_time: %s" % total_time) 527 if result == 1: 528 return True 529 if result == 98: 530 return 98 531 if result == 99: 532 return 99 533 else: 534 return False 535 536 537@timeout(900) 538def outCmd(cmd, save_screenshot_path, base_screenshot_path, script_path): 539 logger.info("cmd is: %s" % cmd) 540 p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding='utf-8', errors='ignore', universal_newlines=True) 541 # p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, errors='ignore', universal_newlines=True) 542 curline = p.stdout.readline() 543 # list_png_name = [] 544 try: 545 while "End of check" not in curline: 546 curline = p.stdout.readline() 547 logger.info(curline) 548 if 'SmokeTest: End of check, test succeeded!' in curline: 549 return True 550 # if "abnarmal" in curline: 551 # png_name = curline.split(" ")[3].split(".")[0] 552 # list_png_name.append(png_name) 553 if "SmokeTest find some fatal problems" in curline: 554 logger.error("SmokeTest find some fatal problems!") 555 return 99 556 except Exception as e: 557 logger.error(e) 558 logger.error("execute smoke_test.py failed!") 559 return 99 560 # l = list(set(list_png_name)) 561 # if l: 562 # logger.error(l) 563 try: 564 resource_path = os.path.join(script_path, 'resource') 565 for jpeg_file in os.listdir(resource_path): 566 if jpeg_file.endswith('jpeg'): 567 result = os.path.join(resource_path, jpeg_file) 568 base = os.path.join(base_screenshot_path, jpeg_file) 569 shutil.copy(result, base) 570 except Exception as t: 571 logger.info(t) 572 p.wait() 573 logger.info("p.returncode %s" % p.returncode) 574 if p.returncode == 0: 575 logger.info("screenshot check is ok!") 576 return True 577 if p.returncode == 101: 578 logger.error("device disconnection, please check the device!") 579 return False 580 logger.error("screenshot test failed, check the %s" % save_screenshot_path) 581 return 98 582 583 584@timeout(1000) 585def exec_cmd(mini_path, sn, save_path, archive_path): 586 cmd = "python %s --device_num %s --save_path %s --archive_path %s" % (mini_path, sn, save_path, archive_path) 587 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding="gbk") 588 curline = p.stdout.readline() 589 try: 590 while "End of check" not in curline: 591 curline = p.stdout.readline() 592 logger.info(curline) 593 except Exception as e: 594 logger.error(e) 595 p.wait() 596 logger.info("p.returncode %s" % p.returncode) 597 if p.returncode == 0: 598 logger.info("mini_system_test is ok!") 599 return True 600 logger.error("mini_system_test failed!") 601 return 98 602 603@timeout(1000) 604def is_can_exec(lock_file): 605 """ 606 判断升级是否可以执行 607 @param lock_file: 文件路径 608 """ 609 lock_duration = 10 * 60 # 10分钟(以秒为单位) 610 if os.getenv('wait_time') is not None: 611 lock_duration = int(os.getenv('wait_time')) 612 # 检查锁文件 613 if os.path.exists(lock_file): 614 # 获取锁文件的创建时间 615 lock_time = os.path.getmtime(lock_file) 616 current_time = time.time() 617 # 判断锁是否超时 618 if (current_time - lock_time) < lock_duration: 619 logger.error("ask is already running. Exiting.") 620 return False 621 else: 622 logger.warning("ask running time is more than %s second, can exec" % lock_duration) 623 delete_file_lock(lock_file) 624 create_file_lock(lock_file) 625 return True 626 else: 627 logger.info("no tasks are being executed") 628 create_file_lock(lock_file) 629 return True 630 631def create_file_lock(lock_file): 632 """ 633 创建文件锁 634 @param lock_file: 文件路径 635 """ 636 directory = os.path.dirname(lock_file) 637 if not os.path.exists(directory): 638 os.makedirs(directory) 639 logger.info("create_file_lock") 640 with open(lock_file, 'w') as f: 641 f.write('locked, please can not delete') 642def delete_file_lock(lock_file): 643 """ 644 删除文件 645 @param lock_file: 文件路径 646 """ 647 logger.info("delete_file_lock") 648 if os.path.exists(lock_file): 649 os.remove(lock_file)