1*9c5db199SXin Liimport datetime 2*9c5db199SXin Liimport os 3*9c5db199SXin Liimport re 4*9c5db199SXin Liimport logging 5*9c5db199SXin Li 6*9c5db199SXin Li 7*9c5db199SXin Lidef dprint(msg): 8*9c5db199SXin Li """Log a message on the DEBUG level.""" 9*9c5db199SXin Li logging.debug('%s', msg) 10*9c5db199SXin Li 11*9c5db199SXin Li 12*9c5db199SXin Lidef get_timestamp(mapping, field): 13*9c5db199SXin Li #pylint: disable-msg=C0111 14*9c5db199SXin Li val = mapping.get(field, None) 15*9c5db199SXin Li if val is not None: 16*9c5db199SXin Li val = datetime.datetime.fromtimestamp(int(val)) 17*9c5db199SXin Li return val 18*9c5db199SXin Li 19*9c5db199SXin Li 20*9c5db199SXin Lidef find_toplevel_job_dir(start_dir): 21*9c5db199SXin Li """ Starting from start_dir and moving upwards, find the top-level 22*9c5db199SXin Li of the job results dir. We can't just assume that it corresponds to 23*9c5db199SXin Li the actual job.dir, because job.dir may just be a subdir of the "real" 24*9c5db199SXin Li job dir that autoserv was launched with. Returns None if it can't find 25*9c5db199SXin Li a top-level dir. 26*9c5db199SXin Li @param start_dir: starting directing for the upward search""" 27*9c5db199SXin Li job_dir = start_dir 28*9c5db199SXin Li while not os.path.exists(os.path.join(job_dir, ".autoserv_execute")): 29*9c5db199SXin Li if job_dir == "/" or job_dir == '': 30*9c5db199SXin Li return None 31*9c5db199SXin Li job_dir = os.path.dirname(job_dir) 32*9c5db199SXin Li return job_dir 33*9c5db199SXin Li 34*9c5db199SXin Li 35*9c5db199SXin Lidef drop_redundant_messages(messages): 36*9c5db199SXin Li """ Given a set of message strings discard any 'redundant' messages which 37*9c5db199SXin Li are simple a substring of the existing ones. 38*9c5db199SXin Li 39*9c5db199SXin Li @param messages - a set of message strings 40*9c5db199SXin Li 41*9c5db199SXin Li @return - a subset of messages with unnecessary strings dropped 42*9c5db199SXin Li """ 43*9c5db199SXin Li sorted_messages = sorted(messages, key=len, reverse=True) 44*9c5db199SXin Li filtered_messages = set() 45*9c5db199SXin Li for message in sorted_messages: 46*9c5db199SXin Li for filtered_message in filtered_messages: 47*9c5db199SXin Li if message in filtered_message: 48*9c5db199SXin Li break 49*9c5db199SXin Li else: 50*9c5db199SXin Li filtered_messages.add(message) 51*9c5db199SXin Li return filtered_messages 52*9c5db199SXin Li 53*9c5db199SXin Li 54*9c5db199SXin Lidef get_afe_job_id(tag): 55*9c5db199SXin Li """ Given a tag return the afe_job_id (if any). 56*9c5db199SXin Li 57*9c5db199SXin Li Tag is in the format of JOB_ID-OWNER/HOSTNAME 58*9c5db199SXin Li 59*9c5db199SXin Li @param tag: afe_job_id and hostname are extracted from this tag. 60*9c5db199SXin Li e.g. "1234-chromeos-test/chromeos1-row1-host1" 61*9c5db199SXin Li @return: the afe_job_id as a string if regex matches, else return '' 62*9c5db199SXin Li """ 63*9c5db199SXin Li match = re.search('^([0-9]+)-.+/(.+)$', tag) 64*9c5db199SXin Li return match.group(1) if match else None 65*9c5db199SXin Li 66*9c5db199SXin Li 67*9c5db199SXin Lidef get_skylab_task_id(tag): 68*9c5db199SXin Li """ Given a tag return the skylab_task's id (if any). 69*9c5db199SXin Li 70*9c5db199SXin Li Tag is in the format of swarming-TASK_ID/HOSTNAME 71*9c5db199SXin Li 72*9c5db199SXin Li @param tag: afe_job_id and hostname are extracted from this tag. 73*9c5db199SXin Li e.g. "1234-chromeos-test/chromeos1-row1-host1" 74*9c5db199SXin Li @return: the afe_job_id as a string if regex matches, else return '' 75*9c5db199SXin Li """ 76*9c5db199SXin Li match = re.search('^swarming-([A-Fa-f0-9]+)/(.+)$', tag) 77*9c5db199SXin Li return match.group(1) if match else None 78*9c5db199SXin Li 79*9c5db199SXin Li 80*9c5db199SXin Lidef is_skylab_task(tag): 81*9c5db199SXin Li """Given a tag, determine whether it represents a Skylab task.""" 82*9c5db199SXin Li return get_skylab_task_id(tag) is not None 83