Эх сурвалжийг харах

[impala] Skeleton of a new Session tab

Romain Rigaux 10 жил өмнө
parent
commit
255e8b2

+ 16 - 0
apps/beeswax/src/beeswax/api.py

@@ -16,6 +16,7 @@
 # limitations under the License.
 
 import logging
+import json
 import re
 
 from django.contrib.auth.models import User
@@ -42,6 +43,7 @@ from beeswax.server.dbms import expand_exception, get_query_server_config, Query
 from beeswax.views import authorized_get_design, authorized_get_query_history, make_parameterization_form,\
                           safe_get_design, save_design, massage_columns_for_json, _get_query_handle_and_state, \
                           _parse_out_hadoop_jobs
+from beeswax.models import Session
 
 LOG = logging.getLogger(__name__)
 
@@ -702,6 +704,20 @@ def get_top_terms(request, database, table, column, prefix=None):
   return JsonResponse(response)
 
 
+def get_session(request):
+  app_name = get_app_name(request)
+  query_server = get_query_server_config(app_name)
+
+  session = Session.objects.get_session(request.user, query_server['server_name'])
+
+  if session:
+    properties = json.loads(session.properties)
+  else:
+    properties = {}
+
+  return JsonResponse({'properties': properties})
+
+
 """
 Utils
 """

+ 115 - 0
apps/beeswax/src/beeswax/migrations/0013_auto__add_field_session_properties.py

@@ -0,0 +1,115 @@
+# -*- coding: utf-8 -*-
+from south.utils import datetime_utils as datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding field 'Session.properties'
+        db.add_column(u'beeswax_session', 'properties',
+                      self.gf('django.db.models.fields.TextField')(default='{}'),
+                      keep_default=False)
+
+
+    def backwards(self, orm):
+        # Deleting field 'Session.properties'
+        db.delete_column(u'beeswax_session', 'properties')
+
+
+    models = {
+        u'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        u'auth.permission': {
+            'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        u'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        u'beeswax.metainstall': {
+            'Meta': {'object_name': 'MetaInstall'},
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'installed_example': ('django.db.models.fields.BooleanField', [], {})
+        },
+        u'beeswax.queryhistory': {
+            'Meta': {'ordering': "['-submission_date']", 'object_name': 'QueryHistory'},
+            'design': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['beeswax.SavedQuery']", 'null': 'True'}),
+            'extra': ('django.db.models.fields.TextField', [], {'default': "'{}'"}),
+            'has_results': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_redacted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_state': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
+            'log_context': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True'}),
+            'modified_row_count': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
+            'notify': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'operation_type': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
+            'query': ('django.db.models.fields.TextField', [], {}),
+            'query_type': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+            'server_guid': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '1024', 'null': 'True'}),
+            'server_host': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '128'}),
+            'server_id': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True'}),
+            'server_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '128'}),
+            'server_port': ('django.db.models.fields.PositiveIntegerField', [], {'default': '10000'}),
+            'server_type': ('django.db.models.fields.CharField', [], {'default': "'beeswax'", 'max_length': '128'}),
+            'statement_number': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+            'submission_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
+        },
+        u'beeswax.savedquery': {
+            'Meta': {'ordering': "['-mtime']", 'object_name': 'SavedQuery'},
+            'data': ('django.db.models.fields.TextField', [], {'max_length': '65536'}),
+            'desc': ('django.db.models.fields.TextField', [], {'max_length': '1024'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_auto': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
+            'is_redacted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_trashed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
+            'mtime': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
+            'type': ('django.db.models.fields.IntegerField', [], {})
+        },
+        u'beeswax.session': {
+            'Meta': {'object_name': 'Session'},
+            'application': ('django.db.models.fields.CharField', [], {'default': "'beeswax'", 'max_length': '128'}),
+            'guid': ('django.db.models.fields.TextField', [], {'max_length': "'100'"}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'last_used': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
+            'properties': ('django.db.models.fields.TextField', [], {'default': "'{}'"}),
+            'secret': ('django.db.models.fields.TextField', [], {'max_length': "'100'"}),
+            'server_protocol_version': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+            'status_code': ('django.db.models.fields.PositiveSmallIntegerField', [], {})
+        },
+        u'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        }
+    }
+
+    complete_apps = ['beeswax']

+ 1 - 0
apps/beeswax/src/beeswax/models.py

@@ -402,6 +402,7 @@ class Session(models.Model):
   server_protocol_version = models.SmallIntegerField(default=0)
   last_used = models.DateTimeField(auto_now=True, db_index=True, verbose_name=_t('Last used'))
   application = models.CharField(max_length=128, help_text=_t('Application we communicate with.'), default='beeswax')
+  properties = models.TextField(default='{}')
 
   objects = SessionManager()
 

+ 4 - 1
apps/beeswax/src/beeswax/server/hive_server2_lib.py

@@ -17,6 +17,7 @@
 
 import logging
 import itertools
+import json
 import re
 
 from itertools import imap
@@ -534,13 +535,15 @@ class HiveServerClient:
     LOG.info('Opening session %s' % sessionId)
 
     encoded_status, encoded_guid = HiveServerQueryHandle(secret=sessionId.secret, guid=sessionId.guid).get()
+    properties = json.dumps(res.configuration)
 
     return Session.objects.create(owner=user,
                                   application=self.query_server['server_name'],
                                   status_code=res.status.statusCode,
                                   secret=encoded_status,
                                   guid=encoded_guid,
-                                  server_protocol_version=res.serverProtocolVersion)
+                                  server_protocol_version=res.serverProtocolVersion,
+                                  properties=properties)
 
 
   def call(self, fn, req, status=TStatusCode.SUCCESS_STATUS):

+ 18 - 0
apps/beeswax/src/beeswax/templates/execute.mako

@@ -36,6 +36,9 @@ ${layout.menubar(section='query')}
     <ul class="nav nav-tabs" style="margin-bottom: 0">
       <li class="active"><a href="#navigatorTab" data-toggle="tab" class="sidetab">${_('Assist')}</a></li>
       <li><a href="#settingsTab" data-toggle="tab" class="sidetab">${_('Settings')} <span data-bind="visible:design.settings.values().length + design.fileResources.values().length + design.functions.values().length > 0, text: design.settings.values().length + design.fileResources.values().length + design.functions.values().length" class="badge badge-info">12</span></a></li>
+      % if app_name == 'impala':
+      <li><a href="#sessionTab" data-toggle="tab" class="sidetab">${_('Session')}</a></li>
+      % endif
     </ul>
     <div class="tab-content">
       <div class="tab-pane active" id="navigatorTab">
@@ -199,6 +202,21 @@ ${layout.menubar(section='query')}
           </div>
         </div>
       </div>
+      % if app_name == 'impala':
+      <div class="tab-pane" id="sessionTab">
+        <div class="card card-small card-tab">
+          <div class="card-body">
+            <div id="advanced-settings">
+            <form id="advancedSettingsForm" action="" method="POST" class="form form-horizontal">
+
+              link
+
+            </form>
+            </div>
+          </div>
+        </div>
+      </div>
+      % endif
     </div>
   </div>
   <div class="resizer" data-bind="splitDraggable : { appName: '${app_name}', onPosition: onPanelPosition }"><div class="resize-bar"><i class="fa fa-ellipsis-v"></i></div></div>

+ 10 - 0
apps/beeswax/src/beeswax/tests.py

@@ -2106,6 +2106,16 @@ ALTER TABLE alltypes ADD IF NOT EXISTS PARTITION(year=2009, month=2);"""
               hql_query(query).statements, hql_query(query).statements)
 
 
+def test_api_get_session():
+  client = make_logged_in_client(is_superuser=False)
+  grant_access("test", "test", "beeswax")
+
+  resp = client.get(reverse("beeswax:api_get_session"))
+
+  data = json.loads(resp.content)
+  assert_true('properties' in data)
+
+
 class MockHiveServerTable(HiveServerTable):
 
   def __init__(self, describe=None):

+ 1 - 0
apps/beeswax/src/beeswax/urls.py

@@ -57,6 +57,7 @@ urlpatterns += patterns(
 urlpatterns += patterns(
   'beeswax.api',
 
+  url(r'^api/session/$', 'get_session', name='api_get_session'),
   url(r'^api/autocomplete/$', 'autocomplete', name='api_autocomplete_databases'),
   url(r'^api/autocomplete/(?P<database>\w+)$', 'autocomplete', name='api_autocomplete_tables'),
   url(r'^api/autocomplete/(?P<database>\w+)/$', 'autocomplete', name='api_autocomplete_tables'),

+ 6 - 0
apps/impala/src/impala/tests.py

@@ -220,6 +220,12 @@ class TestImpalaIntegration:
     assert_true('531091827' in resp.content, resp.content) # We are getting one or two random rows
     assert_true(len(resp.context['sample']) > 0, resp.context['sample'])
 
+  def test_get_session(self):
+    resp = self.client.get(reverse("impala:api_get_session"))
+    data = json.loads(resp.content)
+    assert_true('properties' in data)
+    assert_true(data['properties'].get('http_addr'))
+
 
 # Could be refactored with SavedQuery.create_empty()
 def create_saved_query(app_name, owner):