1*61046927SAndroid Build Coastguard Workerimport argparse 2*61046927SAndroid Build Coastguard Workerimport logging 3*61046927SAndroid Build Coastguard Workerfrom datetime import datetime 4*61046927SAndroid Build Coastguard Workerfrom pathlib import Path 5*61046927SAndroid Build Coastguard Worker 6*61046927SAndroid Build Coastguard Workerfrom structured_logger import StructuredLogger 7*61046927SAndroid Build Coastguard Worker 8*61046927SAndroid Build Coastguard Worker 9*61046927SAndroid Build Coastguard Workerclass CustomLogger: 10*61046927SAndroid Build Coastguard Worker def __init__(self, log_file): 11*61046927SAndroid Build Coastguard Worker self.log_file = log_file 12*61046927SAndroid Build Coastguard Worker self.logger = StructuredLogger(file_name=self.log_file) 13*61046927SAndroid Build Coastguard Worker 14*61046927SAndroid Build Coastguard Worker def get_last_dut_job(self): 15*61046927SAndroid Build Coastguard Worker """ 16*61046927SAndroid Build Coastguard Worker Gets the details of the most recent DUT job. 17*61046927SAndroid Build Coastguard Worker 18*61046927SAndroid Build Coastguard Worker Returns: 19*61046927SAndroid Build Coastguard Worker dict: Details of the most recent DUT job. 20*61046927SAndroid Build Coastguard Worker 21*61046927SAndroid Build Coastguard Worker Raises: 22*61046927SAndroid Build Coastguard Worker ValueError: If no DUT jobs are found in the logger's data. 23*61046927SAndroid Build Coastguard Worker """ 24*61046927SAndroid Build Coastguard Worker try: 25*61046927SAndroid Build Coastguard Worker job = self.logger.data["dut_jobs"][-1] 26*61046927SAndroid Build Coastguard Worker except KeyError: 27*61046927SAndroid Build Coastguard Worker raise ValueError( 28*61046927SAndroid Build Coastguard Worker "No DUT jobs found. Please create a job via create_dut_job call." 29*61046927SAndroid Build Coastguard Worker ) 30*61046927SAndroid Build Coastguard Worker 31*61046927SAndroid Build Coastguard Worker return job 32*61046927SAndroid Build Coastguard Worker 33*61046927SAndroid Build Coastguard Worker def update(self, **kwargs): 34*61046927SAndroid Build Coastguard Worker """ 35*61046927SAndroid Build Coastguard Worker Updates the log file with provided key-value pairs. 36*61046927SAndroid Build Coastguard Worker 37*61046927SAndroid Build Coastguard Worker Args: 38*61046927SAndroid Build Coastguard Worker **kwargs: Key-value pairs to be updated. 39*61046927SAndroid Build Coastguard Worker 40*61046927SAndroid Build Coastguard Worker """ 41*61046927SAndroid Build Coastguard Worker with self.logger.edit_context(): 42*61046927SAndroid Build Coastguard Worker for key, value in kwargs.items(): 43*61046927SAndroid Build Coastguard Worker self.logger.data[key] = value 44*61046927SAndroid Build Coastguard Worker 45*61046927SAndroid Build Coastguard Worker def create_dut_job(self, **kwargs): 46*61046927SAndroid Build Coastguard Worker """ 47*61046927SAndroid Build Coastguard Worker Creates a new DUT job with provided key-value pairs. 48*61046927SAndroid Build Coastguard Worker 49*61046927SAndroid Build Coastguard Worker Args: 50*61046927SAndroid Build Coastguard Worker **kwargs: Key-value pairs for the new DUT job. 51*61046927SAndroid Build Coastguard Worker 52*61046927SAndroid Build Coastguard Worker """ 53*61046927SAndroid Build Coastguard Worker with self.logger.edit_context(): 54*61046927SAndroid Build Coastguard Worker if "dut_jobs" not in self.logger.data: 55*61046927SAndroid Build Coastguard Worker self.logger.data["dut_jobs"] = [] 56*61046927SAndroid Build Coastguard Worker new_job = { 57*61046927SAndroid Build Coastguard Worker "status": "", 58*61046927SAndroid Build Coastguard Worker "submitter_start_time": datetime.now().isoformat(), 59*61046927SAndroid Build Coastguard Worker "dut_submit_time": "", 60*61046927SAndroid Build Coastguard Worker "dut_start_time": "", 61*61046927SAndroid Build Coastguard Worker "dut_end_time": "", 62*61046927SAndroid Build Coastguard Worker "dut_name": "", 63*61046927SAndroid Build Coastguard Worker "dut_state": "pending", 64*61046927SAndroid Build Coastguard Worker "dut_job_phases": [], 65*61046927SAndroid Build Coastguard Worker **kwargs, 66*61046927SAndroid Build Coastguard Worker } 67*61046927SAndroid Build Coastguard Worker self.logger.data["dut_jobs"].append(new_job) 68*61046927SAndroid Build Coastguard Worker 69*61046927SAndroid Build Coastguard Worker def update_dut_job(self, key, value): 70*61046927SAndroid Build Coastguard Worker """ 71*61046927SAndroid Build Coastguard Worker Updates the last DUT job with a key-value pair. 72*61046927SAndroid Build Coastguard Worker 73*61046927SAndroid Build Coastguard Worker Args: 74*61046927SAndroid Build Coastguard Worker key : The key to be updated. 75*61046927SAndroid Build Coastguard Worker value: The value to be assigned. 76*61046927SAndroid Build Coastguard Worker 77*61046927SAndroid Build Coastguard Worker """ 78*61046927SAndroid Build Coastguard Worker with self.logger.edit_context(): 79*61046927SAndroid Build Coastguard Worker job = self.get_last_dut_job() 80*61046927SAndroid Build Coastguard Worker job[key] = value 81*61046927SAndroid Build Coastguard Worker 82*61046927SAndroid Build Coastguard Worker def update_status_fail(self, reason=""): 83*61046927SAndroid Build Coastguard Worker """ 84*61046927SAndroid Build Coastguard Worker Sets the status of the last DUT job to 'fail' and logs the failure reason. 85*61046927SAndroid Build Coastguard Worker 86*61046927SAndroid Build Coastguard Worker Args: 87*61046927SAndroid Build Coastguard Worker reason (str, optional): The reason for the failure. Defaults to "". 88*61046927SAndroid Build Coastguard Worker 89*61046927SAndroid Build Coastguard Worker """ 90*61046927SAndroid Build Coastguard Worker with self.logger.edit_context(): 91*61046927SAndroid Build Coastguard Worker job = self.get_last_dut_job() 92*61046927SAndroid Build Coastguard Worker job["status"] = "fail" 93*61046927SAndroid Build Coastguard Worker job["dut_job_fail_reason"] = reason 94*61046927SAndroid Build Coastguard Worker 95*61046927SAndroid Build Coastguard Worker def create_job_phase(self, phase_name): 96*61046927SAndroid Build Coastguard Worker """ 97*61046927SAndroid Build Coastguard Worker Creates a new job phase for the last DUT job. 98*61046927SAndroid Build Coastguard Worker 99*61046927SAndroid Build Coastguard Worker Args: 100*61046927SAndroid Build Coastguard Worker phase_name : The name of the new job phase. 101*61046927SAndroid Build Coastguard Worker 102*61046927SAndroid Build Coastguard Worker """ 103*61046927SAndroid Build Coastguard Worker with self.logger.edit_context(): 104*61046927SAndroid Build Coastguard Worker job = self.get_last_dut_job() 105*61046927SAndroid Build Coastguard Worker if job["dut_job_phases"] and job["dut_job_phases"][-1]["end_time"] == "": 106*61046927SAndroid Build Coastguard Worker # If the last phase exists and its end time is empty, set the end time 107*61046927SAndroid Build Coastguard Worker job["dut_job_phases"][-1]["end_time"] = datetime.now().isoformat() 108*61046927SAndroid Build Coastguard Worker 109*61046927SAndroid Build Coastguard Worker # Create a new phase 110*61046927SAndroid Build Coastguard Worker phase_data = { 111*61046927SAndroid Build Coastguard Worker "name": phase_name, 112*61046927SAndroid Build Coastguard Worker "start_time": datetime.now().isoformat(), 113*61046927SAndroid Build Coastguard Worker "end_time": "", 114*61046927SAndroid Build Coastguard Worker } 115*61046927SAndroid Build Coastguard Worker job["dut_job_phases"].append(phase_data) 116*61046927SAndroid Build Coastguard Worker 117*61046927SAndroid Build Coastguard Worker def check_dut_timings(self, job): 118*61046927SAndroid Build Coastguard Worker """ 119*61046927SAndroid Build Coastguard Worker Check the timing sequence of a job to ensure logical consistency. 120*61046927SAndroid Build Coastguard Worker 121*61046927SAndroid Build Coastguard Worker The function verifies that the job's submission time is not earlier than its start time and that 122*61046927SAndroid Build Coastguard Worker the job's end time is not earlier than its start time. If either of these conditions is found to be true, 123*61046927SAndroid Build Coastguard Worker an error is logged for each instance of inconsistency. 124*61046927SAndroid Build Coastguard Worker 125*61046927SAndroid Build Coastguard Worker Args: 126*61046927SAndroid Build Coastguard Worker job (dict): A dictionary containing timing information of a job. Expected keys are 'dut_start_time', 127*61046927SAndroid Build Coastguard Worker 'dut_submit_time', and 'dut_end_time'. 128*61046927SAndroid Build Coastguard Worker 129*61046927SAndroid Build Coastguard Worker Returns: 130*61046927SAndroid Build Coastguard Worker None: This function does not return a value; it logs errors if timing inconsistencies are detected. 131*61046927SAndroid Build Coastguard Worker 132*61046927SAndroid Build Coastguard Worker The function checks the following: 133*61046927SAndroid Build Coastguard Worker - If 'dut_start_time' and 'dut_submit_time' are both present and correctly sequenced. 134*61046927SAndroid Build Coastguard Worker - If 'dut_start_time' and 'dut_end_time' are both present and correctly sequenced. 135*61046927SAndroid Build Coastguard Worker """ 136*61046927SAndroid Build Coastguard Worker 137*61046927SAndroid Build Coastguard Worker # Check if the start time and submit time exist 138*61046927SAndroid Build Coastguard Worker if job.get("dut_start_time") and job.get("dut_submit_time"): 139*61046927SAndroid Build Coastguard Worker # If they exist, check if the submission time is before the start time 140*61046927SAndroid Build Coastguard Worker if job["dut_start_time"] < job["dut_submit_time"]: 141*61046927SAndroid Build Coastguard Worker logging.error("Job submission is happening before job start.") 142*61046927SAndroid Build Coastguard Worker 143*61046927SAndroid Build Coastguard Worker # Check if the start time and end time exist 144*61046927SAndroid Build Coastguard Worker if job.get("dut_start_time") and job.get("dut_end_time"): 145*61046927SAndroid Build Coastguard Worker # If they exist, check if the end time is after the start time 146*61046927SAndroid Build Coastguard Worker if job["dut_end_time"] < job["dut_start_time"]: 147*61046927SAndroid Build Coastguard Worker logging.error("Job ended before it started.") 148*61046927SAndroid Build Coastguard Worker 149*61046927SAndroid Build Coastguard Worker # Method to update DUT start, submit and end time 150*61046927SAndroid Build Coastguard Worker def update_dut_time(self, value, custom_time): 151*61046927SAndroid Build Coastguard Worker """ 152*61046927SAndroid Build Coastguard Worker Updates DUT start, submit, and end times. 153*61046927SAndroid Build Coastguard Worker 154*61046927SAndroid Build Coastguard Worker Args: 155*61046927SAndroid Build Coastguard Worker value : Specifies which DUT time to update. Options: 'start', 'submit', 'end'. 156*61046927SAndroid Build Coastguard Worker custom_time : Custom time to set. If None, use current time. 157*61046927SAndroid Build Coastguard Worker 158*61046927SAndroid Build Coastguard Worker Raises: 159*61046927SAndroid Build Coastguard Worker ValueError: If an invalid argument is provided for value. 160*61046927SAndroid Build Coastguard Worker 161*61046927SAndroid Build Coastguard Worker """ 162*61046927SAndroid Build Coastguard Worker with self.logger.edit_context(): 163*61046927SAndroid Build Coastguard Worker job = self.get_last_dut_job() 164*61046927SAndroid Build Coastguard Worker timestamp = custom_time if custom_time else datetime.now().isoformat() 165*61046927SAndroid Build Coastguard Worker if value == "start": 166*61046927SAndroid Build Coastguard Worker job["dut_start_time"] = timestamp 167*61046927SAndroid Build Coastguard Worker job["dut_state"] = "running" 168*61046927SAndroid Build Coastguard Worker elif value == "submit": 169*61046927SAndroid Build Coastguard Worker job["dut_submit_time"] = timestamp 170*61046927SAndroid Build Coastguard Worker job["dut_state"] = "submitted" 171*61046927SAndroid Build Coastguard Worker elif value == "end": 172*61046927SAndroid Build Coastguard Worker job["dut_end_time"] = timestamp 173*61046927SAndroid Build Coastguard Worker job["dut_state"] = "finished" 174*61046927SAndroid Build Coastguard Worker else: 175*61046927SAndroid Build Coastguard Worker raise ValueError( 176*61046927SAndroid Build Coastguard Worker "Error: Invalid argument provided for --update-dut-time. Use 'start', 'submit', 'end'." 177*61046927SAndroid Build Coastguard Worker ) 178*61046927SAndroid Build Coastguard Worker # check the sanity of the partial structured log 179*61046927SAndroid Build Coastguard Worker self.check_dut_timings(job) 180*61046927SAndroid Build Coastguard Worker 181*61046927SAndroid Build Coastguard Worker def close_dut_job(self): 182*61046927SAndroid Build Coastguard Worker """ 183*61046927SAndroid Build Coastguard Worker Closes the most recent DUT (Device Under Test) job in the logger's data. 184*61046927SAndroid Build Coastguard Worker 185*61046927SAndroid Build Coastguard Worker The method performs the following operations: 186*61046927SAndroid Build Coastguard Worker 1. Validates if there are any DUT jobs in the logger's data. 187*61046927SAndroid Build Coastguard Worker 2. If the last phase of the most recent DUT job has an empty end time, it sets the end time to the current time. 188*61046927SAndroid Build Coastguard Worker 189*61046927SAndroid Build Coastguard Worker Raises: 190*61046927SAndroid Build Coastguard Worker ValueError: If no DUT jobs are found in the logger's data. 191*61046927SAndroid Build Coastguard Worker """ 192*61046927SAndroid Build Coastguard Worker with self.logger.edit_context(): 193*61046927SAndroid Build Coastguard Worker job = self.get_last_dut_job() 194*61046927SAndroid Build Coastguard Worker # Check if the last phase exists and its end time is empty, then set the end time 195*61046927SAndroid Build Coastguard Worker if job["dut_job_phases"] and job["dut_job_phases"][-1]["end_time"] == "": 196*61046927SAndroid Build Coastguard Worker job["dut_job_phases"][-1]["end_time"] = datetime.now().isoformat() 197*61046927SAndroid Build Coastguard Worker 198*61046927SAndroid Build Coastguard Worker def close(self): 199*61046927SAndroid Build Coastguard Worker """ 200*61046927SAndroid Build Coastguard Worker Closes the most recent DUT (Device Under Test) job in the logger's data. 201*61046927SAndroid Build Coastguard Worker 202*61046927SAndroid Build Coastguard Worker The method performs the following operations: 203*61046927SAndroid Build Coastguard Worker 1. Determines the combined status of all DUT jobs. 204*61046927SAndroid Build Coastguard Worker 2. Sets the submitter's end time to the current time. 205*61046927SAndroid Build Coastguard Worker 3. Updates the DUT attempt counter to reflect the total number of DUT jobs. 206*61046927SAndroid Build Coastguard Worker 207*61046927SAndroid Build Coastguard Worker """ 208*61046927SAndroid Build Coastguard Worker with self.logger.edit_context(): 209*61046927SAndroid Build Coastguard Worker job_status = [] 210*61046927SAndroid Build Coastguard Worker for job in self.logger.data["dut_jobs"]: 211*61046927SAndroid Build Coastguard Worker if "status" in job: 212*61046927SAndroid Build Coastguard Worker job_status.append(job["status"]) 213*61046927SAndroid Build Coastguard Worker 214*61046927SAndroid Build Coastguard Worker if not job_status: 215*61046927SAndroid Build Coastguard Worker job_combined_status = "null" 216*61046927SAndroid Build Coastguard Worker else: 217*61046927SAndroid Build Coastguard Worker # Get job_combined_status 218*61046927SAndroid Build Coastguard Worker if "pass" in job_status: 219*61046927SAndroid Build Coastguard Worker job_combined_status = "pass" 220*61046927SAndroid Build Coastguard Worker else: 221*61046927SAndroid Build Coastguard Worker job_combined_status = "fail" 222*61046927SAndroid Build Coastguard Worker 223*61046927SAndroid Build Coastguard Worker self.logger.data["job_combined_status"] = job_combined_status 224*61046927SAndroid Build Coastguard Worker self.logger.data["dut_attempt_counter"] = len(self.logger.data["dut_jobs"]) 225*61046927SAndroid Build Coastguard Worker job["submitter_end_time"] = datetime.now().isoformat() 226*61046927SAndroid Build Coastguard Worker 227*61046927SAndroid Build Coastguard Worker 228*61046927SAndroid Build Coastguard Workerdef process_args(args): 229*61046927SAndroid Build Coastguard Worker # Function to process key-value pairs and call corresponding logger methods 230*61046927SAndroid Build Coastguard Worker def process_key_value_pairs(args_list, action_func): 231*61046927SAndroid Build Coastguard Worker if not args_list: 232*61046927SAndroid Build Coastguard Worker raise ValueError( 233*61046927SAndroid Build Coastguard Worker f"No key-value pairs provided for {action_func.__name__.replace('_', '-')}" 234*61046927SAndroid Build Coastguard Worker ) 235*61046927SAndroid Build Coastguard Worker if len(args_list) % 2 != 0: 236*61046927SAndroid Build Coastguard Worker raise ValueError( 237*61046927SAndroid Build Coastguard Worker f"Incomplete key-value pairs for {action_func.__name__.replace('_', '-')}" 238*61046927SAndroid Build Coastguard Worker ) 239*61046927SAndroid Build Coastguard Worker kwargs = dict(zip(args_list[::2], args_list[1::2])) 240*61046927SAndroid Build Coastguard Worker action_func(**kwargs) 241*61046927SAndroid Build Coastguard Worker 242*61046927SAndroid Build Coastguard Worker # Create a CustomLogger object with the specified log file path 243*61046927SAndroid Build Coastguard Worker custom_logger = CustomLogger(Path(args.log_file)) 244*61046927SAndroid Build Coastguard Worker 245*61046927SAndroid Build Coastguard Worker if args.update: 246*61046927SAndroid Build Coastguard Worker process_key_value_pairs(args.update, custom_logger.update) 247*61046927SAndroid Build Coastguard Worker 248*61046927SAndroid Build Coastguard Worker if args.create_dut_job: 249*61046927SAndroid Build Coastguard Worker process_key_value_pairs(args.create_dut_job, custom_logger.create_dut_job) 250*61046927SAndroid Build Coastguard Worker 251*61046927SAndroid Build Coastguard Worker if args.update_dut_job: 252*61046927SAndroid Build Coastguard Worker key, value = args.update_dut_job 253*61046927SAndroid Build Coastguard Worker custom_logger.update_dut_job(key, value) 254*61046927SAndroid Build Coastguard Worker 255*61046927SAndroid Build Coastguard Worker if args.create_job_phase: 256*61046927SAndroid Build Coastguard Worker custom_logger.create_job_phase(args.create_job_phase) 257*61046927SAndroid Build Coastguard Worker 258*61046927SAndroid Build Coastguard Worker if args.update_status_fail: 259*61046927SAndroid Build Coastguard Worker custom_logger.update_status_fail(args.update_status_fail) 260*61046927SAndroid Build Coastguard Worker 261*61046927SAndroid Build Coastguard Worker if args.update_dut_time: 262*61046927SAndroid Build Coastguard Worker if len(args.update_dut_time) == 2: 263*61046927SAndroid Build Coastguard Worker action, custom_time = args.update_dut_time 264*61046927SAndroid Build Coastguard Worker elif len(args.update_dut_time) == 1: 265*61046927SAndroid Build Coastguard Worker action, custom_time = args.update_dut_time[0], None 266*61046927SAndroid Build Coastguard Worker else: 267*61046927SAndroid Build Coastguard Worker raise ValueError("Invalid number of values for --update-dut-time") 268*61046927SAndroid Build Coastguard Worker 269*61046927SAndroid Build Coastguard Worker if action in ["start", "end", "submit"]: 270*61046927SAndroid Build Coastguard Worker custom_logger.update_dut_time(action, custom_time) 271*61046927SAndroid Build Coastguard Worker else: 272*61046927SAndroid Build Coastguard Worker raise ValueError( 273*61046927SAndroid Build Coastguard Worker "Error: Invalid argument provided for --update-dut-time. Use 'start', 'submit', 'end'." 274*61046927SAndroid Build Coastguard Worker ) 275*61046927SAndroid Build Coastguard Worker 276*61046927SAndroid Build Coastguard Worker if args.close_dut_job: 277*61046927SAndroid Build Coastguard Worker custom_logger.close_dut_job() 278*61046927SAndroid Build Coastguard Worker 279*61046927SAndroid Build Coastguard Worker if args.close: 280*61046927SAndroid Build Coastguard Worker custom_logger.close() 281*61046927SAndroid Build Coastguard Worker 282*61046927SAndroid Build Coastguard Worker 283*61046927SAndroid Build Coastguard Workerdef main(): 284*61046927SAndroid Build Coastguard Worker parser = argparse.ArgumentParser(description="Custom Logger Command Line Tool") 285*61046927SAndroid Build Coastguard Worker parser.add_argument("log_file", help="Path to the log file") 286*61046927SAndroid Build Coastguard Worker parser.add_argument( 287*61046927SAndroid Build Coastguard Worker "--update", 288*61046927SAndroid Build Coastguard Worker nargs=argparse.ZERO_OR_MORE, 289*61046927SAndroid Build Coastguard Worker metavar=("key", "value"), 290*61046927SAndroid Build Coastguard Worker help="Update a key-value pair e.g., --update key1 value1 key2 value2)", 291*61046927SAndroid Build Coastguard Worker ) 292*61046927SAndroid Build Coastguard Worker parser.add_argument( 293*61046927SAndroid Build Coastguard Worker "--create-dut-job", 294*61046927SAndroid Build Coastguard Worker nargs=argparse.ZERO_OR_MORE, 295*61046927SAndroid Build Coastguard Worker metavar=("key", "value"), 296*61046927SAndroid Build Coastguard Worker help="Create a new DUT job with key-value pairs (e.g., --create-dut-job key1 value1 key2 value2)", 297*61046927SAndroid Build Coastguard Worker ) 298*61046927SAndroid Build Coastguard Worker parser.add_argument( 299*61046927SAndroid Build Coastguard Worker "--update-dut-job", 300*61046927SAndroid Build Coastguard Worker nargs=argparse.ZERO_OR_MORE, 301*61046927SAndroid Build Coastguard Worker metavar=("key", "value"), 302*61046927SAndroid Build Coastguard Worker help="Update a key-value pair in DUT job", 303*61046927SAndroid Build Coastguard Worker ) 304*61046927SAndroid Build Coastguard Worker parser.add_argument( 305*61046927SAndroid Build Coastguard Worker "--create-job-phase", 306*61046927SAndroid Build Coastguard Worker help="Create a new job phase (e.g., --create-job-phase name)", 307*61046927SAndroid Build Coastguard Worker ) 308*61046927SAndroid Build Coastguard Worker parser.add_argument( 309*61046927SAndroid Build Coastguard Worker "--update-status-fail", 310*61046927SAndroid Build Coastguard Worker help="Update fail as the status and log the failure reason (e.g., --update-status-fail reason)", 311*61046927SAndroid Build Coastguard Worker ) 312*61046927SAndroid Build Coastguard Worker parser.add_argument( 313*61046927SAndroid Build Coastguard Worker "--update-dut-time", 314*61046927SAndroid Build Coastguard Worker nargs=argparse.ZERO_OR_MORE, 315*61046927SAndroid Build Coastguard Worker metavar=("action", "custom_time"), 316*61046927SAndroid Build Coastguard Worker help="Update DUT start and end time. Provide action ('start', 'submit', 'end') and custom_time (e.g., '2023-01-01T12:00:00')", 317*61046927SAndroid Build Coastguard Worker ) 318*61046927SAndroid Build Coastguard Worker parser.add_argument( 319*61046927SAndroid Build Coastguard Worker "--close-dut-job", 320*61046927SAndroid Build Coastguard Worker action="store_true", 321*61046927SAndroid Build Coastguard Worker help="Close the dut job by updating end time of last dut job)", 322*61046927SAndroid Build Coastguard Worker ) 323*61046927SAndroid Build Coastguard Worker parser.add_argument( 324*61046927SAndroid Build Coastguard Worker "--close", 325*61046927SAndroid Build Coastguard Worker action="store_true", 326*61046927SAndroid Build Coastguard Worker help="Updates combined status, submitter's end time and DUT attempt counter", 327*61046927SAndroid Build Coastguard Worker ) 328*61046927SAndroid Build Coastguard Worker args = parser.parse_args() 329*61046927SAndroid Build Coastguard Worker 330*61046927SAndroid Build Coastguard Worker process_args(args) 331*61046927SAndroid Build Coastguard Worker 332*61046927SAndroid Build Coastguard Worker 333*61046927SAndroid Build Coastguard Workerif __name__ == "__main__": 334*61046927SAndroid Build Coastguard Worker main() 335