← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~rvb/maas/maas-longpoll-js into lp:maas

 

Raphaël Badin has proposed merging lp:~rvb/maas/maas-longpoll-js into lp:maas with lp:~rvb/maas/maas-longpoll-threaded-server as a prerequisite.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~rvb/maas/maas-longpoll-js/+merge/97204

Longpoll js.
-- 
https://code.launchpad.net/~rvb/maas/maas-longpoll-js/+merge/97204
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~rvb/maas/maas-longpoll-js into lp:maas.
=== modified file 'src/maas/demo.py'
--- src/maas/demo.py	2012-03-13 17:44:20 +0000
+++ src/maas/demo.py	2012-03-13 17:44:21 +0000
@@ -16,12 +16,19 @@
 from maas.settings import *
 from maas.development import *
 
+
 MEDIA_ROOT = os.path.join(os.getcwd(), "media/demo")
 
 MIDDLEWARE_CLASSES += (
     'debug_toolbar.middleware.DebugToolbarMiddleware',
 )
 
+LONGPOLL_SERVER_URL = "http://localhost:4545/";
+
+# Disable longpoll by default for now. Set it back to 'longpoll/' to
+# enable it.
+LONGPOLL_URL = None
+
 # This should match the setting in Makefile:pserv.pid.
 PSERV_URL = "http://localhost:8001/api";
 

=== modified file 'src/maas/settings.py'
--- src/maas/settings.py	2012-03-13 17:44:20 +0000
+++ src/maas/settings.py	2012-03-13 17:44:21 +0000
@@ -43,10 +43,19 @@
 LOGIN_REDIRECT_URL = '/'
 LOGIN_URL = '/accounts/login/'
 
+# The location of the Longpoll server. If LONGPOLL_SERVER_URL is
+# None, the web app won't act as a proxy to the Longpoll server.
+LONGPOLL_SERVER_URL = None
+
+# The relative path where a proxy to the Longpoll server can be
+# reached.  Longpolling will be disabled in the UI if this is None.
+LONGPOLL_URL = 'longpoll/'
+
 if FORCE_SCRIPT_NAME is not None:
     LOGOUT_URL = FORCE_SCRIPT_NAME + LOGOUT_URL
     LOGIN_REDIRECT_URL = FORCE_SCRIPT_NAME + LOGIN_REDIRECT_URL
     LOGIN_URL = FORCE_SCRIPT_NAME + LOGIN_URL
+    LONGPOLL_URL = FORCE_SCRIPT_NAME + LONGPOLL_URL
     # ADMIN_MEDIA_PREFIX will be deprecated in Django 1.4.
     # Admin's media will be served using staticfiles instead.
     ADMIN_MEDIA_PREFIX = FORCE_SCRIPT_NAME
@@ -55,7 +64,6 @@
 METADATA_URL_REGEXP = '^/metadata/'
 
 YUI_COMBO_URL = "combo/"
-
 # We handle exceptions ourselves (in
 # maasserver.middleware.APIErrorsMiddleware)
 PISTON_DISPLAY_ERRORS = False

=== modified file 'src/maasserver/management/commands/createadmin.py'
--- src/maasserver/management/commands/createadmin.py	2012-03-08 11:37:50 +0000
+++ src/maasserver/management/commands/createadmin.py	2012-03-13 17:44:21 +0000
@@ -12,9 +12,13 @@
 __all__ = []
 
 
+from optparse import make_option
+
 from django.contrib.auth.models import User
-from optparse import make_option
-from django.core.management.base import BaseCommand, CommandError
+from django.core.management.base import (
+    BaseCommand,
+    CommandError,
+    )
 from django.db import DEFAULT_DB_ALIAS
 
 

=== modified file 'src/maasserver/messages.py'
--- src/maasserver/messages.py	2012-03-13 17:44:20 +0000
+++ src/maasserver/messages.py	2012-03-13 17:44:21 +0000
@@ -12,7 +12,7 @@
 __all__ = [
     "MaaSMessenger",
     "MessengerBase",
-    "messaging",
+    "get_messaging",
     ]
 
 
@@ -120,8 +120,10 @@
             instance.__class__.__name__, event_name)
 
 
-if settings.RABBITMQ_PUBLISH:
-    messaging = RabbitMessaging(MODEL_EXCHANGE_NAME)
-    MaaSMessenger(Node, messaging.getExchange()).register()
-else:
-    messaging = None
+def get_messaging():
+    if settings.RABBITMQ_PUBLISH:
+        messaging = RabbitMessaging(MODEL_EXCHANGE_NAME)
+        MaaSMessenger(Node, messaging.getExchange()).register()
+        return messaging
+    else:
+        return None

=== modified file 'src/maasserver/templates/maasserver/js-conf.html'
--- src/maasserver/templates/maasserver/js-conf.html	2012-03-07 16:37:05 +0000
+++ src/maasserver/templates/maasserver/js-conf.html	2012-03-13 17:44:21 +0000
@@ -28,3 +28,4 @@
 <script type="text/javascript" src="{{ STATIC_URL }}js/prefs.js"></script>
 <script type="text/javascript" src="{{ STATIC_URL }}js/utils.js"></script>
 <script type="text/javascript" src="{{ STATIC_URL }}js/node_views.js"></script>
+

=== modified file 'src/maasserver/tests/test_views.py'
--- src/maasserver/tests/test_views.py	2012-03-13 05:34:38 +0000
+++ src/maasserver/tests/test_views.py	2012-03-13 17:44:21 +0000
@@ -17,6 +17,7 @@
 from django.contrib.auth.models import User
 from django.core.urlresolvers import reverse
 from lxml.html import fromstring
+from maasserver.views import get_longpoll_context
 from maasserver.models import (
     Config,
     NODE_AFTER_COMMISSIONING_ACTION,
@@ -28,6 +29,7 @@
     LoggedInTestCase,
     TestCase,
     )
+from django.conf import settings
 
 
 def get_prefixed_form_data(prefix, data):
@@ -107,6 +109,31 @@
         self.assertEqual("Invalid file type requested.", response.content)
 
 
+class TestUtilities(TestCase):
+
+    def patch_settings(self, name, value):
+        old_value = getattr(settings, name)
+        setattr(settings, name, value)
+        self.addCleanup(setattr, settings, name, old_value)
+
+    def test_get_longpoll_context_empty_if_rabbitmq_publish_is_none(self):
+        self.patch_settings('RABBITMQ_PUBLISH', None)
+        self.assertEqual({}, get_longpoll_context())
+
+    def test_get_longpoll_context_empty_if_longpoll_url_is_None(self):
+        self.patch_settings('LONGPOLL_URL', None)
+        self.assertEqual({}, get_longpoll_context())
+
+    def test_get_longpoll_context(self):
+        longpoll = factory.getRandomString()
+        self.patch_settings('LONGPOLL_URL', longpoll)
+        self.patch_settings('RABBITMQ_PUBLISH', True)
+        context = get_longpoll_context()
+        self.assertItemsEqual(
+            ['LONGPOLL_URL', 'longpoll_queue'], list(context))
+        self.assertEqual(longpoll, context['LONGPOLL_URL'])
+
+
 class UserPrefsViewTest(LoggedInTestCase):
 
     def test_prefs_GET_profile(self):

=== modified file 'src/maasserver/urls.py'
--- src/maasserver/urls.py	2012-03-08 15:53:39 +0000
+++ src/maasserver/urls.py	2012-03-13 17:44:21 +0000
@@ -36,6 +36,7 @@
     logout,
     NodeListView,
     NodesCreateView,
+    proxy_to,
     settings,
     settings_add_archive,
     userprefsview,
@@ -76,6 +77,13 @@
         r'^nodes/create/$', NodesCreateView.as_view(), name='node-create'),
 )
 
+if django_settings.LONGPOLL_SERVER_URL is not None:
+    urlpatterns += patterns('maasserver.views',
+        url(
+            r'^%s$' % re.escape(django_settings.LONGPOLL_URL), proxy_to,
+            name='proxy'),
+        )
+
 # URLs for admin users.
 urlpatterns += patterns('maasserver.views',
     adminurl(r'^settings/$', settings, name='settings'),

=== modified file 'src/maasserver/views.py'
--- src/maasserver/views.py	2012-03-08 22:31:14 +0000
+++ src/maasserver/views.py	2012-03-13 17:44:21 +0000
@@ -15,12 +15,15 @@
     "NodesCreateView",
     ]
 
+import mimetypes
 import os
+import urllib2
 
 from convoy.combo import (
     combine_files,
     parse_qs,
     )
+from django.conf import settings as django_settings
 from django.contrib import messages
 from django.contrib.auth.forms import PasswordChangeForm as PasswordForm
 from django.contrib.auth.models import User
@@ -54,6 +57,7 @@
     ProfileForm,
     UbuntuForm,
     )
+from maasserver.messages import get_messaging
 from maasserver.models import (
     Node,
     SSHKeys,
@@ -66,6 +70,17 @@
     return dj_logout(request, next_page=reverse('login'))
 
 
+def get_longpoll_context():
+    messaging = get_messaging()
+    if messaging is not None and django_settings.LONGPOLL_URL is not None:
+        return {
+            'longpoll_queue': messaging.getQueue().name,
+            'LONGPOLL_URL': django_settings.LONGPOLL_URL,
+            }
+    else:
+        return {}
+
+
 class NodeListView(ListView):
 
     context_object_name = "node_list"
@@ -73,6 +88,11 @@
     def get_queryset(self):
         return Node.objects.get_visible_nodes(user=self.request.user)
 
+    def get_context_data(self, **kwargs):
+        context = super(NodeListView, self).get_context_data(**kwargs)
+        context.update(get_longpoll_context())
+        return context
+
 
 class NodesCreateView(CreateView):
 
@@ -221,6 +241,19 @@
         return reverse('settings')
 
 
+def proxy_to(request):
+    url = django_settings.LONGPOLL_SERVER_URL
+    assert url is not None, (
+        "LONGPOLL_SERVER_URL should point to a Longpoll server.")
+    if 'QUERY_STRING' in request.META:
+        url += '?' + request.META['QUERY_STRING']
+    proxied_request = urllib2.urlopen(url)
+    status_code = proxied_request.code
+    mimetype = proxied_request.headers.typeheader or mimetypes.guess_type(url)
+    content = proxied_request.read()
+    return HttpResponse(content, status=status_code, mimetype=mimetype)
+
+
 def settings(request):
     user_list = UserProfile.objects.all_users().order_by('username')
     # Process the MaaS & network form.

=== modified file 'vdenv/api-list.py'
--- vdenv/api-list.py	2012-03-09 22:07:14 +0000
+++ vdenv/api-list.py	2012-03-13 17:44:21 +0000
@@ -11,8 +11,9 @@
 
 __metaclass__ = type
 
+import sys
 import xmlrpclib
-import sys
+
 
 host = "192.168.123.2"
 user = "cobbler"

=== modified file 'vdenv/setup.py'
--- vdenv/setup.py	2012-03-09 22:05:55 +0000
+++ vdenv/setup.py	2012-03-13 17:44:21 +0000
@@ -11,14 +11,16 @@
 
 __metaclass__ = type
 
-import yaml
 import os
 import re
+import subprocess
 import sys
+import xmlrpclib
+
+from Cheetah.Template import Template
 import libvirt
-from Cheetah.Template import Template
-import subprocess
-import xmlrpclib
+import yaml
+
 
 NODES_RANGE = range(1,4)
 


Follow ups