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 87 88 89 90 91 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 120 121 122 123 124 125 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
|
from __future__ import print_function from pyspark import SparkContext
import json import re import sys import time import urllib2 import urlparse import datetime
def read_task_file(filename): with open(filename, 'r') as f: contents = f.read() try: json.loads(contents) except Exception, e: print('Invalid JSON in task file "{0}": {1}\n'.format(filename, repr(e))) sys.exit(1) return contents
def post_task(url, task_json, timeout_at): try: task_url = url.rstrip("/") + "/druid/indexer/v1/task" req = urllib2.Request(task_url, task_json, {'Content-Type' : 'application/json'}) timeleft = timeout_at - time.time() response_timeout = min(max(timeleft, 5), 10) response = urllib2.urlopen(req, None, response_timeout) return response.read().rstrip() except urllib2.URLError as e: if isinstance(e, urllib2.HTTPError) and e.code >= 400 and e.code <= 500: raise_friendly_error(e) elif time.time() >= timeout_at: raise_friendly_error(e) elif isinstance(e, urllib2.HTTPError) and e.code in [301, 302, 303, 305, 307] and \ e.info().getheader("Location") is not None: location = urlparse.urlparse(e.info().getheader("Location")) url = "{0}://{1}".format(location.scheme, location.netloc) print("Redirect response received, setting url to [{0}]\n".format(url)) return post_task(url, task_json, timeout_at) else: sleep_time = 30 extra = '' if hasattr(e, 'read'): extra = e.read().rstrip() print("Waiting up to {0}s for indexing service to become available. [Got: {1} {2}]".format(max(sleep_time, int(timeout_at - time.time())), str(e), extra).rstrip()) print("\n") time.sleep(sleep_time) return post_task(url, task_json, timeout_at)
def await_task_completion(url, task_id, timeout_at): while True: task_url = url.rstrip("/") + "/druid/indexer/v1/task/{0}/status".format(task_id) req = urllib2.Request(task_url) timeleft = timeout_at - time.time() response_timeout = min(max(timeleft, 5), 30) response = urllib2.urlopen(req, None, response_timeout) response_obj = json.loads(response.read()) response_status_code = response_obj["status"]["status"] if response_status_code in ['SUCCESS', 'FAILED']: return response_status_code else: if time.time() < timeout_at: print("Task {0} still running...".format(task_id)) timeleft = timeout_at - time.time() time.sleep(min(30, timeleft)) else: raise Exception("Task {0} did not finish in time!".format(task_id))
def raise_friendly_error(e): if isinstance(e, urllib2.HTTPError): text = e.read().strip() reresult = re.search(r'<pre>(.*?)</pre>', text, re.DOTALL) if reresult: text = reresult.group(1).strip() raise Exception("HTTP Error {0}: {1}, check overlord log for more details.\n{2}".format(e.code, e.reason, text)) raise e
def get_task_json(content, hdfspath, data_source, date, segment, query): input_json = json.loads(content) input_json["spec"]["ioConfig"]["inputSpec"]["paths"] = hdfspath + "/" + date input_json["spec"]["dataSchema"]["dataSource"] = data_source
date_array = [] date_time = datetime.datetime(int(date[0:4]),int(date[4:6]),int(date[6:8])) date_time_next = date_time + datetime.timedelta(days=1)
date_array.append(date_time.strftime('%Y-%m-%dT%H:%M:%S+08:00') + "/" + date_time_next.strftime('%Y-%m-%dT%H:%M:%S+08:00')) input_json["spec"]["dataSchema"]["granularitySpec"]["segmentGranularity"] = segment input_json["spec"]["dataSchema"]["granularitySpec"]["queryGranularity"] = query input_json["spec"]["dataSchema"]["granularitySpec"]["intervals"] = date_array return json.dumps(input_json, indent=2)
def main(): """ Usage: druid_task.py <url> <task_file> <date> <submit_timeout> <complete_timeout> <hdfs_path> <data_source> """ if len(sys.argv) < 10: print("Usage: druid_task.py <url> <task_file> <date> <submit_timeout> <complete_timeout> <hdfs_path> <data_source> <segment> <query>") exit(1) print(sys.argv)
url = sys.argv[1].strip() task_file = sys.argv[2].strip() date = sys.argv[3].strip() submit_timeout = sys.argv[4].strip() complete_timeout = sys.argv[5].strip() hdfspath = sys.argv[6].strip() data_source = sys.argv[7].strip() date_segment = sys.argv[8].strip() date_query = sys.argv[9].strip()
datapath = hdfspath + "/" + date
sc = SparkContext(appName="druid_index_task_day")
datafiles_rdd = sc.wholeTextFiles(datapath) is_empty = datafiles_rdd.isEmpty() print(is_empty) print("datapath:" + datapath) if is_empty == False: submit_timeout_at = time.time() + float(submit_timeout) complete_timeout_at = time.time() + float(complete_timeout) task_json = get_task_json(read_task_file(task_file), hdfspath, data_source, date, date_segment, date_query) print(task_json)
task_id = json.loads(post_task(url, task_json, submit_timeout_at))["task"] sys.stderr.write('\033[1m' + "Task started: " + '\033[0m' + "{0}\n".format(task_id)) sys.stderr.write('\033[1m' + "Task log: " + '\033[0m' + "{0}/druid/indexer/v1/task/{1}/log\n".format(url.rstrip("/"),task_id)) sys.stderr.write('\033[1m' + "Task status: " + '\033[0m' + "{0}/druid/indexer/v1/task/{1}/status\n".format(url.rstrip("/"),task_id))
task_status = await_task_completion(url, task_id, complete_timeout_at) print("Task finished with status: {0}\n".format(task_status)) if task_status != 'SUCCESS': sys.exit(1) else: print("Task finished with no data.")
if __name__ == "__main__": main()
|