From fa87d987e399d7093b4408cda64495a5cd832a09 Mon Sep 17 00:00:00 2001
From: Őry Máté <ory.mate@cloud.bme.hu>
Date: Thu, 27 Feb 2014 17:37:28 +0100
Subject: [PATCH] dashboard: get console token at time of tab loading

closes #87
---
 circle/dashboard/templates/dashboard/vm-detail/console.html | 28 +++++++++++++++++++---------
 circle/dashboard/urls.py                                    |  4 +++-
 circle/dashboard/views.py                                   | 34 ++++++++++++++++++++++++----------
 3 files changed, 46 insertions(+), 20 deletions(-)

diff --git a/circle/dashboard/templates/dashboard/vm-detail/console.html b/circle/dashboard/templates/dashboard/vm-detail/console.html
index 2a9e9af..903b11f 100644
--- a/circle/dashboard/templates/dashboard/vm-detail/console.html
+++ b/circle/dashboard/templates/dashboard/vm-detail/console.html
@@ -63,15 +63,25 @@
 	    port = window.location.port == "" ? "443" : window.location.port;
         }
         password = '';
-        path = 'vnc/?d={{ vnc_url }}';
+        $('#_console .btn-toolbar button').attr('disabled', true);
+        $('#noVNC_status').html('Retreiving authorization token.');
+        $.get('{{ vnc_url }}', function(data) {
+            if (data.indexOf('vnc') != 0) {
+                $('#noVNC_status').html('No authorization token received.');
+            }
+            else {
+                rfb = new RFB({'target': $D('noVNC_canvas'),
+                               'encrypt': (window.location.protocol === "https:"),
+                               'true_color':   true,
+                               'local_cursor': true,
+                               'shared':       true,
+                               'view_only':    false,
+                               'updateState':  updateState});
+                rfb.connect(host, port, password, data);
+        }
+        }).fail(function(){
+            $('#noVNC_status').html("Can't connect to console.");
+        });
 
-        rfb = new RFB({'target': $D('noVNC_canvas'),
-                       'encrypt': (window.location.protocol === "https:"),
-                       'true_color':   true,
-                       'local_cursor': true,
-                       'shared':       true,
-                       'view_only':    false,
-                       'updateState':  updateState});
-        rfb.connect(host, port, password, path);
     });
     </script>
diff --git a/circle/dashboard/urls.py b/circle/dashboard/urls.py
index 974e382..04b030a 100644
--- a/circle/dashboard/urls.py
+++ b/circle/dashboard/urls.py
@@ -9,7 +9,7 @@ from .views import (
     FavouriteView, NodeStatus, GroupList, TemplateDelete, LeaseDelete,
     VmGraphView, TemplateAclUpdateView, GroupDetailView, GroupDelete,
     GroupAclUpdateView, GroupUserDelete, NotificationView, NodeGraphView,
-    VmMigrateView,
+    VmMigrateView, VmDetailVncTokenView,
 )
 
 urlpatterns = patterns(
@@ -37,6 +37,8 @@ urlpatterns = patterns(
         name='dashboard.views.remove-port'),
     url(r'^vm/(?P<pk>\d+)/$', VmDetailView.as_view(),
         name='dashboard.views.detail'),
+    url(r'^vm/(?P<pk>\d+)/vnctoken/$', VmDetailVncTokenView.as_view(),
+        name='dashboard.views.detail-vnc'),
     url(r'^vm/(?P<pk>\d+)/acl/$', AclUpdateView.as_view(model=Instance),
         name='dashboard.views.vm-acl'),
     url(r'^vm/(?P<pk>\d+)/tx/$', TransferOwnershipView.as_view(),
diff --git a/circle/dashboard/views.py b/circle/dashboard/views.py
index 6b8dc93..d62ce5e 100644
--- a/circle/dashboard/views.py
+++ b/circle/dashboard/views.py
@@ -148,6 +148,25 @@ class CheckedDetailView(LoginRequiredMixin, DetailView):
         return context
 
 
+class VmDetailVncTokenView(CheckedDetailView):
+    template_name = "dashboard/vm-detail.html"
+    model = Instance
+
+    def get(self, request, **kwargs):
+        self.object = self.get_object()
+        if not self.object.has_level(request.user, 'operator'):
+            raise PermissionDenied()
+        if self.object.node:
+            port = self.object.vnc_port
+            host = str(self.object.node.host.ipv4)
+            value = signing.dumps({'host': host,
+                                   'port': port},
+                                  key=getenv("PROXY_SECRET", 'asdasd')),
+            return HttpResponse('vnc/?d=%s' % value)
+        else:
+            raise Http404()
+
+
 class VmDetailView(CheckedDetailView):
     template_name = "dashboard/vm-detail.html"
     model = Instance
@@ -155,16 +174,11 @@ class VmDetailView(CheckedDetailView):
     def get_context_data(self, **kwargs):
         context = super(VmDetailView, self).get_context_data(**kwargs)
         instance = context['instance']
-        if instance.node:
-            port = instance.vnc_port
-            host = str(instance.node.host.ipv4)
-            value = signing.dumps({'host': host,
-                                   'port': port},
-                                  key=getenv("PROXY_SECRET", 'asdasd')),
-            context.update({
-                'graphite_enabled': VmGraphView.get_graphite_url() is not None,
-                'vnc_url': '%s' % value
-            })
+        context.update({
+            'graphite_enabled': VmGraphView.get_graphite_url() is not None,
+            'vnc_url': reverse_lazy("dashboard.views.detail-vnc",
+                                    kwargs={'pk': self.object.pk})
+        })
 
         # activity data
         ia = InstanceActivity.objects.filter(
--
libgit2 0.26.0