views.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #!/usr/bin/env python
  2. # Licensed to Cloudera, Inc. under one
  3. # or more contributor license agreements. See the NOTICE file
  4. # distributed with this work for additional information
  5. # regarding copyright ownership. Cloudera, Inc. licenses this file
  6. # to you under the Apache License, Version 2.0 (the
  7. # "License"); you may not use this file except in compliance
  8. # with the License. You may obtain a copy of the License at
  9. #
  10. # http://www.apache.org/licenses/LICENSE-2.0
  11. #
  12. # Unless required by applicable law or agreed to in writing, software
  13. # distributed under the License is distributed on an "AS IS" BASIS,
  14. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. # See the License for the specific language governing permissions and
  16. # limitations under the License.
  17. import base64
  18. import json
  19. import logging
  20. import re
  21. import StringIO
  22. import urllib
  23. from avro import datafile, io
  24. from django.utils.translation import ugettext as _
  25. from desktop.lib.django_util import JsonResponse, render
  26. from hbase import conf
  27. from hbase.settings import DJANGO_APPS
  28. from hbase.api import HbaseApi
  29. from hbase.management.commands import hbase_setup
  30. from server.hbase_lib import get_thrift_type
  31. LOG = logging.getLogger(__name__)
  32. def has_write_access(user):
  33. return user.is_superuser or user.has_hue_permission(action="write", app=DJANGO_APPS[0])
  34. def app(request):
  35. return render('app.mako', request, {
  36. 'can_write': has_write_access(request.user)
  37. })
  38. # action/cluster/arg1/arg2/arg3...
  39. def api_router(request, url): # On split, deserialize anything
  40. def safe_json_load(raw):
  41. try:
  42. return json.loads(re.sub(r'(?:\")([0-9]+)(?:\")', r'\1', str(raw)))
  43. except:
  44. return raw
  45. def deserialize(data):
  46. if type(data) == dict:
  47. special_type = get_thrift_type(data.pop('hue-thrift-type', ''))
  48. if special_type:
  49. return special_type(data)
  50. if hasattr(data, "__iter__"):
  51. for i, item in enumerate(data):
  52. data[i] = deserialize(item) # Sets local binding, needs to set in data
  53. return data
  54. decoded_url_params = [urllib.unquote(arg) for arg in re.split(r'(?<!\\)/', url.strip('/'))]
  55. url_params = [safe_json_load((arg, request.POST.get(arg[0:16], arg))[arg[0:15] == 'hbase-post-key-'])
  56. for arg in decoded_url_params] # Deserialize later
  57. if request.POST.get('dest', False):
  58. url_params += [request.FILES.get(request.REQUEST.get('dest'))]
  59. return api_dump(HbaseApi().query(*url_params))
  60. def api_dump(response):
  61. ignored_fields = ('thrift_spec', '__.+__')
  62. trunc_limit = conf.TRUNCATE_LIMIT.get()
  63. def clean(data):
  64. try:
  65. json.dumps(data)
  66. return data
  67. except:
  68. cleaned = {}
  69. lim = [0]
  70. if isinstance(data, str): # Not JSON dumpable, meaning some sort of bytestring or byte data
  71. #detect if avro file
  72. if(data[:3] == '\x4F\x62\x6A'):
  73. #write data to file in memory
  74. output = StringIO.StringIO()
  75. output.write(data)
  76. #read and parse avro
  77. rec_reader = io.DatumReader()
  78. df_reader = datafile.DataFileReader(output, rec_reader)
  79. return json.dumps(clean([record for record in df_reader]))
  80. return base64.b64encode(data)
  81. if hasattr(data, "__iter__"):
  82. if type(data) is dict:
  83. for i in data:
  84. cleaned[i] = clean(data[i])
  85. elif type(data) is list:
  86. cleaned = []
  87. for i, item in enumerate(data):
  88. cleaned += [clean(item)]
  89. else:
  90. for i, item in enumerate(data):
  91. cleaned[i] = clean(item)
  92. else:
  93. for key in dir(data):
  94. value = getattr(data, key)
  95. if value is not None and not hasattr(value, '__call__') and sum([int(bool(re.search(ignore, key)))
  96. for ignore in ignored_fields]) == 0:
  97. cleaned[key] = clean(value)
  98. return cleaned
  99. return JsonResponse({
  100. 'data': clean(response),
  101. 'truncated': True,
  102. 'limit': trunc_limit,
  103. })
  104. def install_examples(request):
  105. result = {'status': -1, 'message': ''}
  106. if request.method != 'POST':
  107. result['message'] = _('A POST request is required.')
  108. else:
  109. try:
  110. hbase_setup.Command().handle_noargs()
  111. result['status'] = 0
  112. except Exception, e:
  113. LOG.exception(e)
  114. result['message'] = str(e)
  115. return JsonResponse(result)