merge
authorLoic Baron <loic.baron@lip6.fr>
Tue, 28 Apr 2015 09:39:12 +0000 (11:39 +0200)
committerLoic Baron <loic.baron@lip6.fr>
Tue, 28 Apr 2015 09:39:12 +0000 (11:39 +0200)
196 files changed:
.settings/org.eclipse.core.resources.prefs
Makefile
README
README.django-1.7 [new file with mode: 0644]
activity/__init__.py
influxdb/client.py
localauth/__init__.py [moved from auth/__init__.py with 100% similarity]
localauth/manifoldbackend.py [moved from auth/manifoldbackend.py with 65% similarity]
localauth/models.py [moved from auth/models.py with 100% similarity]
localauth/static/css/login.css [moved from auth/static/css/login.css with 100% similarity]
localauth/static/css/logout.css [moved from auth/static/css/logout.css with 100% similarity]
localauth/static/img/form_input_password.png [moved from auth/static/img/form_input_password.png with 100% similarity]
localauth/static/js/logout.js [moved from auth/static/js/logout.js with 100% similarity]
localauth/tests.py [moved from auth/tests.py with 100% similarity]
localauth/views.py [moved from auth/views.py with 87% similarity]
manifoldapi/manifoldapi.py
manifoldapi/manifoldproxy.py
manifoldapi/manifoldresult.py
manifoldapi/metadata.py
manifoldapi/static/js/manifold.js
myslice.sqlite3.dummy [new file with mode: 0644]
myslice/components.py
myslice/myslice.ini.onelab
myslice/settings.py
myslice/urls.py
plugins/columns_editor/__init__.py
plugins/filter_status/__init__.py
plugins/filter_status/static/js/filter_status.js
plugins/form/__init__.py
plugins/querygrid/__init__.py
plugins/querytable/__init__.py
plugins/querytable/static/js/querytable.js
plugins/scheduler2/static/js/scheduler2.js
plugins/scheduler2/templates/scheduler.html
plugins/sladialog/static/css/sladialog.css
plugins/sladialog/static/js/sladialog.js
plugins/sladialog/templates/sladialog.html
plugins/univbris/__init__.py
plugins/univbrisfoam/__init__.py
plugins/univbrisfv/__init__.py
plugins/univbristopo/__init__.py
plugins/univbrisvtam/__init__.py
portal/about.py
portal/account.py
portal/accountview.py
portal/actions.py
portal/contactview.py
portal/dashboardview.py
portal/emailactivationview.py
portal/forms.py
portal/homeview.py
portal/institution.py
portal/joinview.py
portal/managementtababout.py
portal/managementtabrequests.py
portal/manageuserview.py
portal/models.py
portal/native_migrations/0001_initial.py [new file with mode: 0644]
portal/native_migrations/__init__.py [new file with mode: 0644]
portal/platformview.py
portal/projectrequestview.py
portal/registrationview.py
portal/reputationview.py
portal/resourceview.py
portal/slicerequestview.py
portal/sliceresourceview.py
portal/slicetabexperiment.py
portal/slicetabmeasurements.py
portal/sliceview.py
portal/static/css/fed4fire.css
portal/static/css/onelab.css
portal/static/img/testbeds/NITOS-Volos.png [new file with mode: 0644]
portal/static/img/testbeds/Netmode.png [new file with mode: 0644]
portal/static/img/testbeds/PLE.png [moved from portal/static/img/testbeds/ple.png with 100% similarity]
portal/static/img/testbeds/netmode.png [deleted file]
portal/static/img/testbeds/w-iLab.t.png [moved from portal/static/img/testbeds/wilab2.ilabt.iminds.be.png with 100% similarity]
portal/static/img/testbeds/wall2.ilabt.iminds.be.png [new file with mode: 0644]
portal/static/js/common.functions.js
portal/static/js/institution.js
portal/static/js/my_account.edit_profile.js
portal/static/js/myslice.js
portal/static/js/requests.js [new file with mode: 0644]
portal/supportview.py
portal/templates/_widget-monitor.html
portal/templates/_widget-topmenu.html
portal/templates/base.html
portal/templates/fed4fire/fed4fire_account-view.html
portal/templates/fed4fire/fed4fire_activate_user.html
portal/templates/fed4fire/fed4fire_contact_support_email.html
portal/templates/fed4fire/fed4fire_home-view.html
portal/templates/fed4fire/fed4fire_institution.html
portal/templates/fed4fire/fed4fire_join_request_denied.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_join_request_denied.txt [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_join_request_email.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_join_request_email.txt [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_join_request_validated.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_join_request_validated.txt [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_project_request_denied.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_project_request_denied.txt [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_project_request_email.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_project_request_email.txt [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_project_request_validated.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_project_request_validated.txt [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_projectrequest_view.html
portal/templates/fed4fire/fed4fire_registration_view.html
portal/templates/fed4fire/fed4fire_slice-request-done-view.html [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_slice-resource-view.html
portal/templates/fed4fire/fed4fire_slice-view.html
portal/templates/fed4fire/fed4fire_slice_request_denied.html
portal/templates/fed4fire/fed4fire_slice_request_email.html
portal/templates/fed4fire/fed4fire_slice_request_email.txt
portal/templates/fed4fire/fed4fire_slice_request_validated.html
portal/templates/fed4fire/fed4fire_slicerequest_view.html
portal/templates/fed4fire/fed4fire_user_request_denied.html
portal/templates/fed4fire/fed4fire_user_request_email.html
portal/templates/fed4fire/fed4fire_user_request_validated.html
portal/templates/fed4fire/fed4fire_user_request_validated_subject.txt [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_widget-slice-sections.html
portal/templates/fed4fire/fed4fire_widget-topmenu.html
portal/templates/institution.html
portal/templates/management-tab-requests.html
portal/templates/onelab/onelab_account-view.html
portal/templates/onelab/onelab_slice-view.html
portal/templates/onelab/onelab_slicerequest_view.html
portal/templates/onelab/onelab_user_request_email.html
portal/templates/onelab/onelab_user_request_email.txt
portal/templates/onelab/onelab_widget-slice-sections.html
portal/templates/onelab/onelab_widget-topmenu.html
portal/templates/project-request-ack-view.html
portal/templates/slice-request-ack-view.html
portal/templates/slice-tab-info.html
portal/templates/slice-tab-users-view.html
portal/templates/slice-view.html
portal/templates/slice_request_email.html
portal/templates/slice_request_email.txt
portal/templates/slicerequest_view.html
portal/templates/smartfire/smartfire_user_request_email.html
portal/templates/user_request_validated_subject.txt [new file with mode: 0644]
portal/univbrisview.py
portal/validationview.py
portal/views/__init__.py
rest/__init__.py
rest/authority.py [new file with mode: 0644]
rest/cache.py
rest/create.py
rest/get.py
rest/initscript.py
rest/sfa_api.py
rest/update.py
sample/tabview.py
sample/topmenuvalidationview.py
sla/README [deleted file]
sla/samples/TemplateIMindsService.xml [deleted file]
sla/samples/providerCreate.bat [deleted file]
sla/samples/providerIMinds.xml [deleted file]
sla/samples/simpleAgreementCreation.bat [deleted file]
sla/samples/simpleAgreementCreationParameters.json [deleted file]
sla/samples/templateCreate.bat [deleted file]
sla/sla_utils/bin/load-samples.sh [deleted file]
sla/sla_utils/bin/startagreement.sh [deleted file]
sla/sla_utils/bin/stopagreement.sh [deleted file]
sla/sla_utils/samples/agreement03.xml [deleted file]
sla/sla_utils/samples/agreement04.xml [deleted file]
sla/sla_utils/samples/enforcement03.xml [deleted file]
sla/sla_utils/samples/enforcement04.xml [deleted file]
sla/sla_utils/samples/old/agreement01.xml [deleted file]
sla/sla_utils/samples/old/agreement02.xml [deleted file]
sla/sla_utils/samples/old/agreement03_old.xml [deleted file]
sla/sla_utils/samples/old/agreement04_old.xml [deleted file]
sla/sla_utils/samples/old/agreement05.xml [deleted file]
sla/sla_utils/samples/old/agreement05_old.xml [deleted file]
sla/sla_utils/samples/old/enforcement.xml [deleted file]
sla/sla_utils/samples/old/enforcement02.xml [deleted file]
sla/sla_utils/samples/old/enforcement05.xml [deleted file]
sla/sla_utils/samples/old/template01.xml [deleted file]
sla/sla_utils/samples/provider-virtualwall.xml [deleted file]
sla/sla_utils/samples/provider-wilab2.xml [deleted file]
sla/sla_utils/samples/template.xml [deleted file]
sla/slaclient/restclient.py
sla/slaclient/wsag_model.py
sla/slaclient/xmlconverter.py
sla/slicetabsla.py
sla/templates/slice-tab-sla.html
sla/templates/violations_template.sublime-workspace [deleted file]
sla/urls.py
sla/wsag_helper.py
ui/templates/messages-transient-header.html
ui/topmenu.py
unfold/collectstatic.py
unfold/composite.py
unfold/loginrequired.py
unfold/page.py
unfold/plugin.py
unfold/prelude.py
unfold/sessioncache.py [new file with mode: 0644]
unfold/tests.py

index dad9009..00f180d 100644 (file)
@@ -1,4 +1,6 @@
 eclipse.preferences.version=1
+encoding//forge/forms.py=utf-8
+encoding//forge/views.py=utf-8
 encoding//portal/django_passresetview.py=utf-8
 encoding//portal/forms.py=utf-8
 encoding//portal/migrations/0002_extend_slice.py=utf-8
@@ -6,6 +8,8 @@ encoding//portal/migrations/0005_extend_user.py=utf-8
 encoding//portal/migrations/0008_extend_user.py=utf-8
 encoding//portal/migrations/0009_initial.py=utf-8
 encoding//portal/migrations/0010_project.py=utf-8
+encoding//portal/migrations/0011_join.py=utf-8
 encoding//portal/models.py=utf-8
 encoding//portal/urls.py=utf-8
 encoding//portal/validationview.py=utf-8
+encoding//portal/views/__init__.py=utf-8
index 80d49c4..6f557ba 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -96,6 +96,9 @@ redo-templates: clean-templates templates
 myfiles: force
        @git ls-files | egrep -v 'insert(_|-)above|third-party/|to-be-integrated/'
 
+pyfiles: force
+       @git ls-files | grep '\.py$$'
+
 # in general it's right to rely on the contents as reported by git
 tags: force
        $(MAKE-SILENT) myfiles | xargs etags
diff --git a/README b/README
index 4e4e195..41de01d 100644 (file)
--- a/README
+++ b/README
@@ -1,9 +1,9 @@
-This file documents the contents of this module
-change
-Last update 20 FEB. 2015
+Last update 18 MAR. 2015
 
 Installation
 =================================================================
+Complete Guide: http://trac.myslice.info/wiki/Manifold/Install
+
 Recommended OS
 ===============
 Debian GNU/Linux 7.5 (wheezy) x64
diff --git a/README.django-1.7 b/README.django-1.7
new file mode 100644 (file)
index 0000000..382c422
--- /dev/null
@@ -0,0 +1,30 @@
+Thierry Parmentelat <thierry.parmentelat@inria.fr>
+
+As of March 31 2015, the code should be mostly ready for django-1.7,
+with the following restrictions
+
+* migrations : django-1.7 comes with its own native migrations system
+  and so south is not needed/recommended any longer. So for now we have a
+  version of such native migrations that does a one-shot setup of a db
+  schema but this is stored in
+
+  portal/native_migrations
+
+  instead of the standard location
+
+  portal/migrations
+
+  because this one is still expected to hold south code with earlier djangos
+  You might need to rename native_migrations/ into migrations/ before
+  running manage.py migrate in the first place
+
+* testing quite a few issues related to 1.7 have been addressed but it
+  would be presomptuous to state that things were tested very
+  thoroughly, far from that.
+
+  So please use with care and let meknow of any additional issues
+
+
+
+  
+
index 4719a61..b749672 100644 (file)
@@ -14,6 +14,8 @@ import base64
 import time
 import datetime
 from myslice.configengine import ConfigEngine
+from myslice.settings import logger
+
 
 config = ConfigEngine()
 if config.activity and config.activity.apikey :
@@ -37,10 +39,10 @@ else :
 def logWrite(request, action, message, objects = None):
     
     if not apikey :
-        print "===============>> activity: no apikey"
+        logger.info("===============>> activity: no apikey")
         return
     if not secret :
-        print "===============>> activity: no secret"
+        logger.info("===============>> activity: no secret")
         return
     
     timestamp = time.mktime(datetime.datetime.today().timetuple())
@@ -69,12 +71,11 @@ def logWrite(request, action, message, objects = None):
     
     try :
         result = urllib2.urlopen(server, urllib.urlencode(log))
-        print "===============>> activity: %s <%s> %s" % (action, request.user,message)
+        logger.info("===============>> activity: {} <{}> {}".format(action, request.user,message))
         content = result.read()
     except urllib2.URLError as e:
-        print "===============>> activity: connection to " + server + " impossible, could not log action"
-        print e.strerror
-        print ""
+        logger.error("===============>> activity: connection to {} impossible, could not log action".format(server))
+        logger.error(e.strerror)
 
 def log(request, action, message, objects = None):
     # Create a new thread in Daemon mode to send the log entry
@@ -83,14 +84,14 @@ def log(request, action, message, objects = None):
     t.start()
 
 def getClientIp(request):
-    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
-    if x_forwarded_for:
+    try :
+        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
         ip = x_forwarded_for.split(',')[0]
-    else:
+    except:
         ip = request.META.get('REMOTE_ADDR')
     return ip
 
 #
 # sign the request with the secret key
 def sign(secret, message):
-    return hmac.new(secret, msg=message, digestmod=hashlib.sha256).hexdigest()
\ No newline at end of file
+    return hmac.new(secret, msg=message, digestmod=hashlib.sha256).hexdigest()
index 50daa30..8d28dd8 100644 (file)
@@ -1,15 +1,19 @@
 from django.http import HttpResponse
 from rest import error
-import os,json
-import ConfigParser
-import string, random
+import os,json,string,random
+import logging,ConfigParser
 
 from portal.models import MeasurementsDB
 
 from manifold.core.query             import Query, AnalyzedQuery
 from manifoldapi.manifoldapi         import execute_query
 
-from influxdb import InfluxDBClient
+logger = logging.getLogger(__name__)
+
+try :
+    from influxdb import InfluxDBClient
+except :
+    logger.error('can\'t import InfluxDBClient module')
 
 def createDatabase(request, slicename):
     result = {}
similarity index 100%
rename from auth/__init__.py
rename to localauth/__init__.py
similarity index 65%
rename from auth/manifoldbackend.py
rename to localauth/manifoldbackend.py
index c7ac7fa..504a85b 100644 (file)
@@ -7,6 +7,10 @@ from manifold.core.query        import Query
 
 from myslice.settings import config, logger, DEBUG
 
+from portal.actions import authority_check_pis
+
+# from unfold.sessioncache import SessionCache
+
 # Name my backend 'ManifoldBackend'
 class ManifoldBackend:
 
@@ -28,13 +32,14 @@ class ManifoldBackend:
             sessions_result = api.forward(Query.create('local:session').to_dict())
             sessions = sessions_result.ok_value()
             if not sessions:
-                logger.error("GetSession failed", sessions_result.error())
-                return
+                logger.error("GetSession failed: {}".format(sessions_result.error()))
+                return None
             session = sessions[0]
-            logger.debug("SESSION : %s" % session)
+            logger.debug("SESSION : {}".format(session.keys()))
             
             # Change to session authentication
             api.auth = {'AuthMethod': 'session', 'session': session['session']}
+            #api.auth = session_auth
             self.api = api
 
             # Get account details
@@ -42,19 +47,24 @@ class ManifoldBackend:
             persons_result = api.forward(Query.get('local:user').to_dict())
             persons = persons_result.ok_value()
             if not persons:
-                logger.error("GetPersons failed",persons_result.error())
-                return
+                logger.error("GetPersons failed: {}".format(persons_result.error()))
+                return None
             person = persons[0]
-            logger.debug("PERSON : %s" % person)
-            #logger.info("%s %s <%s> logged in" % (person['config']['first_name'], person['config']['last_name'], person['config']['email']))
-
+            logger.debug("PERSON : {}".format(person))
+            
             request.session['manifold'] = {'auth': api.auth, 'person': person, 'expires': session['expires']}
-        except ManifoldException, e:
-            logger.error("Manifold Auth Backend: %s" % e.manifold_result)
-        except Exception, e:
-            logger.error("Manifold Auth Backend: %s" % e)
-            #import traceback
-            #traceback.print_exc()
+
+            #logger.info("{} {} <{}> logged in"\
+            #    .format(person['config']['first_name'], person['config']['last_name'], person['config']['email']))
+
+            #SessionCache().store_auth(request, session_auth)
+
+        except ManifoldException as e:
+            logger.error("ManifoldException in Auth Backend: {}".format(e.manifold_result))
+        except Exception as e:
+            logger.error("Exception in Manifold Auth Backend: {}".format(e))
+            import traceback
+            logger.error(traceback.format_exc())
             return None
 
         try:
@@ -70,6 +80,8 @@ class ManifoldBackend:
         if 'lastname' in person:
             user.last_name = person['lastname']
 
+        user.pi = authority_check_pis (request, user.email)
+        request.session['user'] = {'email':user.email,'pi':user.pi,'firstname':user.first_name,'lastname':user.last_name}
         return user
 
     # Required for your backend to work properly - unchanged in most scenarios
similarity index 100%
rename from auth/models.py
rename to localauth/models.py
similarity index 100%
rename from auth/tests.py
rename to localauth/tests.py
similarity index 87%
rename from auth/views.py
rename to localauth/views.py
index b959e73..bcba326 100644 (file)
@@ -1,6 +1,8 @@
 from django.contrib.auth import logout
 from django.http import HttpResponseRedirect
 
+from myslice.settings import logger
+
 import activity.user
 
 # hard question : where should we redirect requests to logout if user is not logged in ?
@@ -8,7 +10,7 @@ def logout_user (request):
     # check that we're indeed logged in
     if not request.user.is_authenticated():
         return HttpResponseRedirect ('/')
-    print "LOGGING OUT"
+    logger.info("LOGGING OUT")
     
     # log user activity
     activity.user.logout(request)
index a9834ed..29236c0 100644 (file)
@@ -1,14 +1,17 @@
 # Manifold API Python interface
-import copy, xmlrpclib, ssl
-from myslice.settings import config, logger, DEBUG
+import copy
+import xmlrpclib
+import ssl
 
 from django.contrib import messages
 from django.shortcuts import redirect
-from manifoldresult import ManifoldResult, ManifoldCode, ManifoldException
+
 from manifold.core.result_value import ResultValue
+from manifoldresult import ManifoldResult, ManifoldCode, ManifoldException, truncate_result
+
+# from unfold.sessioncache import SessionCache
 
-debug_deep=False
-#debug_deep=True
+from myslice.settings import config, logger
 
 class ManifoldAPI:
 
@@ -25,7 +28,8 @@ class ManifoldAPI:
         # Manifold uses a self signed certificate
         # https://www.python.org/dev/peps/pep-0476/
         if hasattr(ssl, '_create_unverified_context'): 
-            self.server = xmlrpclib.Server(self.url, verbose=False, allow_none=True, context=ssl._create_unverified_context())
+            self.server = xmlrpclib.Server(self.url, verbose=False, allow_none=True,
+                                           context=ssl._create_unverified_context())
         else :
             self.server = xmlrpclib.Server(self.url, verbose=False, allow_none=True)
 
@@ -39,52 +43,41 @@ class ManifoldAPI:
 
         def func(*args, **kwds):
             import time
-            
             start = time.time()
+            
+            # the message to display
+            auth_message = "<AuthMethod not set in {}>".format(self.auth) if 'AuthMethod' not in self.auth \
+                           else "[session]" if self.auth['AuthMethod'] == 'session' \
+                           else "user:{}".format(self.auth['Username']) if self.auth['AuthMethod'] == 'password' \
+                           else "anonymous" if self.auth['AuthMethod'] == 'anonymous' \
+                           else "[???]" + "{}".format(self.auth)
+            end_message = "MANIFOLD <- {}( {}( {} ) ) with auth={} to {}"\
+                          .format(methodName,
+                                  args[0]['action'] or '', 
+                                  args[0]['object'] or '',
+                                  auth_message,
+                                  self.url)
             try:
-                
-                #logger.debug("MANIFOLD %s( %s( %s ) ) to %s" % (methodName, args[0]['action'], args[0]['object'], self.url))
-                
-                if ('Username' in self.auth) :
-                    username = self.auth['Username']
-                else :
-                    username = "-"
-                
                 args += ({ 'authentication': self.auth },)
-                                
                 result = getattr(self.server, methodName)(*args, **kwds)
-                
-                logger.debug("MANIFOLD %s( %s( %s ) ) as %s to %s executed in %s seconds -> %s" % 
-                             (methodName, 
-                              args[0]['action'] or '', 
-                              args[0]['object'] or '',
-                              username,
-                              self.url, 
-                              (time.time() - start),
-                              args))
-
+                logger.debug("{} executed in {} seconds -> {}"\
+                             .format(end_message, time.time() - start, truncate_result(result)))
                 return ResultValue(**result)
 
-            except Exception, error:
-                if True: 
-                    print "===== xmlrpc catch-all exception:", error
-                    import traceback
-                    traceback.print_exc(limit=3)
+            except Exception as error:
+                logger.error("===== xmlrpc catch-all exception: {}".format(error))
+                import traceback
+                logger.error(traceback.format_exc(limit=3))
                 
                 if "Connection refused" in error:
                     raise ManifoldException ( ManifoldResult (code=ManifoldCode.SERVER_UNREACHABLE,
-                                                              output="%s answered %s" % (self.url,error)))
+                                                              output="{} answered {}".format(self.url, error)))
                 # otherwise
-                logger.error("MANIFOLD %s( %s( %s ) ) as %s to %s executed in %s seconds -> %s" % 
-                             (methodName, 
-                              args[0]['action'] or '', 
-                              args[0]['object'] or '',
-                              username,
-                              self.url, 
-                              (time.time() - start),
-                              args))
-                logger.error("MANIFOLD %s", error)
-                raise ManifoldException ( ManifoldResult (code = ManifoldCode.SERVER_UNREACHABLE, output = "%s" % error) )
+                logger.error("{} FAILED - executed in {} seconds"\
+                             .format(end_message, time.time() - start)) 
+                logger.error("MANIFOLD {}".format(error))
+                raise ManifoldException ( ManifoldResult (code = ManifoldCode.SERVER_UNREACHABLE,
+                                                          output = "{}".format(error)))
 
         return func
 
@@ -92,21 +85,22 @@ def _execute_query(request, query, manifold_api_session_auth):
     
     manifold_api = ManifoldAPI(auth = manifold_api_session_auth)
     
-    logger.debug("MANIFOLD QUERY : %s" % " ".join(str(query).split()))
-    #logger.debug("MANIFOLD DICT : %s" % query.to_dict())
+    logger.debug("MANIFOLD -> QUERY : {}".format(" ".join(str(query).split())))
     result = manifold_api.forward(query.to_dict())
     if result['code'] == 2:
         # this is gross; at the very least we need to logout() 
         # but most importantly there is a need to refine that test, since 
         # code==2 does not necessarily mean an expired session
         # XXX only if we know it is the issue
-        del request.session['manifold']
+        #SessionCache().end_session(request)
         # Flush django session
+        del request.session['manifold']
+
         request.session.flush()
-        #raise Exception, 'Error running query: %r' % result
+        #raise Exception, 'Error running query: {}'.format(result)
     
     if result['code'] == 1:
-        logger.warning("MANIFOLD : %s" % result['description'])
+        logger.warning("MANIFOLD : {}".format(result['description']))
 
     # XXX Handle errors
     #Error running query: {'origin': [0, 'XMLRPCAPI'], 'code': 2, 'description': 'No such session: No row was found for one()', 'traceback': 'Traceback (most recent call last):\n  File "/usr/local/lib/python2.7/dist-packages/manifold/core/xmlrpc_api.py", line 68, in xmlrpc_forward\n    user = Auth(auth).check()\n  File "/usr/local/lib/python2.7/dist-packages/manifold/auth/__init__.py", line 245, in check\n    return self.auth_method.check()\n  File "/usr/local/lib/python2.7/dist-packages/manifold/auth/__init__.py", line 95, in check\n    raise AuthenticationFailure, "No such session: %s" % e\nAuthenticationFailure: No such session: No row was found for one()\n', 'type': 2, 'ts': None, 'value': None}
@@ -114,17 +108,25 @@ def _execute_query(request, query, manifold_api_session_auth):
     return result['value'] 
 
 def execute_query(request, query):
+    
+    logger.debug("EXECUTE QUERY: request - {}".format(request.session.items()))
+    
     if not 'manifold' in request.session or not 'auth' in request.session['manifold']:
+    #manifold_api_session_auth = SessionCache().get_auth(request)
+    #if not manifold_api_session_auth:
         request.session.flush()
         #raise Exception, "User not authenticated"
         host = request.get_host()
         return redirect('/')
     
     manifold_api_session_auth = request.session['manifold']['auth']
-    
+
     return _execute_query(request, query, manifold_api_session_auth)
 
 def execute_admin_query(request, query):
     admin_user, admin_password = config.manifold_admin_user_password()
+    if not admin_user or not admin_password:
+        logger.error("""CONFIG: you need to setup admin_user and admin_password in myslice.ini
+Some functions won't work properly until you do so""")
     admin_auth = {'AuthMethod': 'password', 'Username': admin_user, 'AuthString': admin_password}
     return _execute_query(request, query, admin_auth)
index a6f29c3..eba37bb 100644 (file)
@@ -12,7 +12,9 @@ from manifoldapi                import ManifoldAPI
 from manifoldresult             import ManifoldException
 from manifold.util.log          import Log
 
-from myslice.settings import config, logger, DEBUG
+# from unfold.sessioncache import SessionCache
+
+from myslice.settings import config, logger
 
 # register activity
 import activity.slice
@@ -35,18 +37,18 @@ def proxy (request,format):
     
     # expecting a POST
     if request.method != 'POST':
-        logger.error("MANIFOLDPROXY unexpected method %s -- exiting" % request.method)
-        return HttpResponse ({"ret":0}, mimetype="application/json")
+        logger.error("MANIFOLDPROXY unexpected method {} -- exiting".format(request.method))
+        return HttpResponse ({"ret":0}, content_type="application/json")
     # we only support json for now
     # if needed in the future we should probably cater for
     # format_in : how is the query encoded in POST
     # format_out: how to serve the results
     if format != 'json':
-        logger.error("MANIFOLDPROXY unexpected format %s -- exiting" % format)
-        return HttpResponse ({"ret":0}, mimetype="application/json")
+        logger.error("MANIFOLDPROXY unexpected format {} -- exiting".format(format))
+        return HttpResponse ({"ret":0}, content_type="application/json")
     try:
         # translate incoming POST request into a query object
-        #logger.debug("MANIFOLDPROXY request.POST %s" % request.POST)
+        #logger.debug("MANIFOLDPROXY request.POST {}".format(request.POST))
 
         manifold_query = Query()
         #manifold_query = ManifoldQuery()
@@ -62,10 +64,12 @@ def proxy (request,format):
             if 'manifold' in request.session:
                 manifold_api_session_auth = request.session['manifold']['auth']
             else:
-                return HttpResponse (json.dumps({'code':0,'value':[]}), mimetype="application/json")
+            #manifold_api_session_auth = SessionCache().get_auth(request)
+            #if not manifold_api_session_auth:
+                return HttpResponse (json.dumps({'code':0,'value':[]}), content_type="application/json")
                 
         if debug_empty and manifold_query.action.lower()=='get':
-            return HttpResponse (json.dumps({'code':0,'value':[]}), mimetype="application/json")
+            return HttpResponse (json.dumps({'code':0,'value':[]}), content_type="application/json")
                 
         # actually forward
         manifold_api= ManifoldAPI(auth=manifold_api_session_auth)
@@ -85,7 +89,7 @@ def proxy (request,format):
         #
         # resource reservation
         if (manifold_query.action.lower() == 'update') :
-            print result['value'][0]
+            logger.debug(result['value'][0])
             if 'resource' in result['value'][0] :
                 for resource in result['value'][0]['resource'] :
                     activity.slice.resource(request, 
@@ -100,13 +104,13 @@ def proxy (request,format):
         
         json_answer=json.dumps(result)
 
-        return HttpResponse (json_answer, mimetype="application/json")
+        return HttpResponse (json_answer, content_type="application/json")
 
-    except Exception,e:
-        logger.error("MANIFOLDPROXY %s" % e)
+    except Exception as e:
+        logger.error("MANIFOLDPROXY {}".format(e))
         import traceback
-        traceback.print_exc()
-        return HttpResponse ({"ret":0}, mimetype="application/json")
+        logger.error(traceback.format_exc())
+        return HttpResponse ({"ret":0}, content_type="application/json")
 
 #################### 
 # see CSRF_FAILURE_VIEW in settings.py
@@ -114,5 +118,5 @@ def proxy (request,format):
 # this however turns out disappointing/not very informative
 failure_answer=[ "csrf_failure" ]
 def csrf_failure(request, reason=""):
-    print "CSRF failure with reason '%s'"%reason
-    return HttpResponseForbidden (json.dumps (failure_answer), mimetype="application/json")
+    logger.error("CSRF failure with reason '{}'".format(reason))
+    return HttpResponseForbidden (json.dumps (failure_answer), content_type="application/json")
index 4ffe072..3680864 100644 (file)
@@ -1,3 +1,4 @@
+# black magic to define enums
 def enum(*sequential, **named):
     enums = dict(zip(sequential, range(len(sequential))), **named)
     return type('Enum', (), enums)
@@ -10,47 +11,65 @@ ManifoldCode = enum (
     SERVER_UNREACHABLE=3,
 )
 
+def truncate(result, length=50):
+    plain = "{}".format(result)
+    if len(plain) <= length-3:
+        return plain
+    else:
+        return plain[:(length-3)]+'...'
+
 _messages_ = { -1 : "Unknown", 0: "OK", 1: "Session Expired", 2: "Not Implemented", 3: "Backend server unreachable"}
 
+def truncate_result(result, length=50):
+    self = result
+    code = self['code']
+    result = "[MFresult {} (code={})".format(_messages_.get(code, "???"), code)
+    if code == 0:
+        value = self['value']
+        if isinstance(value, list):
+            result += " [value=list with {} elts]".format(len(value))
+        elif isinstance(value, dict):
+            result += " [value=dict with keys {}]".format(value.keys())
+        else:
+            result += " [value={}: {}]".format(type(value).__name__, value)
+    elif 'output' in self:
+        result += " [output={}]".format(self['output'])
+    else:
+        result += "<no output>"
+    result += "]"
+    return truncate(result, 60)
+
 # being a dict this can be used with json.dumps
 class ManifoldResult (dict):
     def __init__ (self, code=ManifoldCode.SUCCESS, value=None, output=""):
-        self['code']=code
-        self['value']=value
-        self['output']=output
+        self['code'] = code
+        self['value'] = value
+        self['output'] = output
         self['description'] = '' # Jordan: needed by javascript code
 
     def from_json (self, json_string):
         d=json.dumps(json_string)
-        for k in ['code','value','output']:
-            self[k]=d[k]
+        for k in ['code', 'value', 'output']:
+            self[k] = d[k]
 
     # raw accessors
-    def code (self): return self['code']
-    def output (self): return self['output']
+    def code (self):
+        return self['code']
+    def output (self):
+        return self['output']
 
     # this returns None if there's a problem, the value otherwise
     def ok_value (self):
-        if self['code']==ManifoldCode.SUCCESS:
+        if self['code'] == ManifoldCode.SUCCESS:
             return self['value']
 
     # both data in a single string
     def error (self):
-        return "code=%s -- %s"%(self['code'],self['output'])
+        return "code={} -- {}".format(self['code'], self['output'])
     
 
     def __repr__ (self):
-        code=self['code']
-        result="[MFresult %s (code=%s)"%(_messages_.get(code,"???"),code)
-        if code==0:
-            value=self['value']
-            if isinstance(value,list): result += " [value=list with %d elts]"%len(value)
-            elif isinstance(value,dict): result += " [value=dict with keys %s]"%value.keys()
-            else: result += " [value=%s: %s]"%(type(value).__name__,value)
-        else:
-            result += " [output=%s]"%self['output']
-        result += "]"
-        return result
+        return truncate_result(self, 60)
 
 # probably simpler to use a single class and transport the whole result there
 # instead of a clumsy set of derived classes 
@@ -58,4 +77,4 @@ class ManifoldException (Exception):
     def __init__ (self, manifold_result):
         self.manifold_result=manifold_result
     def __repr__ (self):
-        return "Manifold Exception %s"%(self.manifold_result.error())
+        return "<Manifold Exception {}>".format(self.manifold_result.error())
index 300397c..f8e9b34 100644 (file)
@@ -6,6 +6,8 @@ from manifoldapi        import ManifoldAPI
 
 from django.contrib     import messages
 
+from myslice.settings   import logger
+
 debug=False
 #debug=True
 
@@ -34,10 +36,10 @@ class MetaData:
         # xxx need a way to export error messages to the UI
         if result['code'] == 1: # warning
             # messages.warning(request, result['description'])
-            print ("METADATA WARNING -",request,result['description'])
+            logger.warning(("METADATA WARNING - {} {}".format(request,result['description'])))
         elif result['code'] == 2:
             # messages.error(request, result['description'])
-            print ("METADATA ERROR -",request,result['description'])
+            logger.error(("METADATA ERROR - {} {}".format(request,result['description'])))
             # XXX FAIL HERE XXX
             return
 
@@ -58,5 +60,6 @@ class MetaData:
         return self.hash_by_object[object]['column'].sort()
 
     def get_field_type(self, object, field):
-        if debug: print "Temp fix for metadata::get_field_type() -> consider moving to manifold.core.metadata soon"
+        if debug:
+            logger.debug("Temp fix for metadata::get_field_type() -> consider moving to manifold.core.metadata soon")
         return field
index 517ab69..d6f0932 100644 (file)
@@ -141,10 +141,10 @@ var QUERY_STATE_DONE        = 2;
  * RECORD STATES (for query_store)
  ******************************************************************************/
 
-var STATE_SET       = 0;
-var STATE_VALUE     = 1;
-var STATE_WARNINGS  = 2;
-var STATE_VISIBLE   = 3;
+var STATE_SET       = 20;
+var STATE_VALUE     = 21;
+var STATE_WARNINGS  = 22;
+var STATE_VISIBLE   = 23;
 
 // ACTIONS
 var STATE_SET_CHANGE = 0;
@@ -177,6 +177,10 @@ var CONSTRAINT_RESERVABLE_LEASE     = 0;
 
 var CONSTRAINT_RESERVABLE_LEASE_MSG = "Configuration required: this resource needs to be scheduled";
 
+var CONSTRAINT_SLA                  = 1;
+
+var CONSTRAINT_SLA_MSG              = "SLA acceptance required: testbed offers SLA for its resources"
+
 // A structure for storing queries
 
 function QueryExt(query, parent_query_ext, main_query_ext, update_query_ext, disabled, domain_query_ext) {
@@ -1689,13 +1693,15 @@ case TYPE_LIST_OF_VALUES:
         switch(query.object) {
 
             case 'resource':
+
+                var warnings = manifold.query_store.get_record_state(query.query_uuid, record_key, STATE_WARNINGS);
                 // CONSTRAINT_RESERVABLE_LEASE
                 // 
                 // +) If a reservable node is added to the slice, then it should have a corresponding lease
                 // XXX Not always a resource
                 var is_reservable = (record.exclusive == true);
                 if (is_reservable) {
-                    var warnings = manifold.query_store.get_record_state(query.query_uuid, record_key, STATE_WARNINGS);
+                    // var warnings = manifold.query_store.get_record_state(query.query_uuid, record_key, STATE_WARNINGS);
 
                     if (event_type == STATE_SET_ADD) {
                         // We should have a lease_query associated
@@ -1708,6 +1714,17 @@ case TYPE_LIST_OF_VALUES:
                             // XXX Need for a better function to manage warnings
                             var warn = CONSTRAINT_RESERVABLE_LEASE_MSG;
                             warnings[CONSTRAINT_RESERVABLE_LEASE] = warn;
+
+                            /*manifold.query_store.set_record_state(query.query_uuid, record_key, STATE_WARNINGS, warnings);
+                            // Signal the change to plugins (even if the constraint does not apply, so that the plugin can display a checkmark)
+                            data = {
+                                state:  STATE_WARNINGS,
+                                key   : record_key,
+                                op    : null,
+                                value : warnings
+                            }
+                            manifold.raise_record_event(query.query_uuid, FIELD_STATE_CHANGED, data);*/
+
                         } else {
                             // Lease are defined, delete the warning in case it was set previously
                             delete warnings[CONSTRAINT_RESERVABLE_LEASE];
@@ -1716,13 +1733,24 @@ case TYPE_LIST_OF_VALUES:
                         // Remove warnings attached to this resource
                         delete warnings[CONSTRAINT_RESERVABLE_LEASE];
                     }
-
-                    manifold.query_store.set_record_state(query.query_uuid, record_key, STATE_WARNINGS, warnings);
                 }
 
-                /* This was redundant */
-                // manifold.query_store.recount(query.query_uuid); 
+                /*var urn_regexp = /\+(.*?)\+/;
+                var testbed_urn = urn_regexp.exec(record.urn)[1];
+                var has_sla = $.inArray(testbed_urn, localStorage.getItem("sla_testbeds").split(",")) != -1;
+
+                if (has_sla) {
+                    // var warnings = manifold.query_store.get_record_state(query.query_uuid, record_key, STATE_WARNINGS);
 
+                    if (event_type == STATE_SET_ADD) {
+                        var warn = CONSTRAINT_SLA_MSG;
+                        warnings[CONSTRAINT_SLA] = warn;
+                    } else {
+                        delete warnings[CONSTRAINT_SLA];
+                    }
+                }*/
+
+                manifold.query_store.set_record_state(query.query_uuid, record_key, STATE_WARNINGS, warnings);
                 // Signal the change to plugins (even if the constraint does not apply, so that the plugin can display a checkmark)
                 data = {
                     state:  STATE_WARNINGS,
@@ -1731,6 +1759,46 @@ case TYPE_LIST_OF_VALUES:
                     value : warnings
                 }
                 manifold.raise_record_event(query.query_uuid, FIELD_STATE_CHANGED, data);
+
+                // JGLL: SLA code
+                /*get_testbeds_with_sla()
+                    .done( function(testbeds) {
+                        var urn_regexp = /\+(.*?)\+/;
+                        var testbed_urn = urn_regexp.exec(record.urn)[1];
+
+                        var warnings = manifold.query_store.get_record_state(query.query_uuid, record_key, STATE_WARNINGS);
+
+                        if ($.inArray(testbed_urn, testbeds) != -1) {
+                            // JGLL: Set a warning on resources covered by testbeds offering SLAs
+                            // CONSTRAINT_SLA
+
+                            if (event_type == STATE_SET_ADD) {
+                                var warn = CONSTRAINT_SLA_MSG;
+                                warnings[CONSTRAINT_SLA] = warn;
+                            } else {
+                                delete warnings[CONSTRAINT_SLA]
+                            }
+                        }
+
+                        manifold.query_store.set_record_state(query.query_uuid, record_key, STATE_WARNINGS, warnings);
+
+                        // Signal the change to plugins (even if the constraint does not apply, so that the plugin can display a checkmark)
+                        data = {
+                            state:  STATE_WARNINGS,
+                            key   : record_key,
+                            op    : null,
+                            value : warnings
+                        }
+
+                        manifold.raise_record_event(query.query_uuid, FIELD_STATE_CHANGED, data);
+                    })
+                    .fail( function(err) {
+                       console.log("SLA - Error retrieving testbeds that support SLAs");
+                    });*/
+
+                /* This was redundant */
+                // manifold.query_store.recount(query.query_uuid);
+
                 break;
 
             case 'lease':
@@ -1738,7 +1806,7 @@ case TYPE_LIST_OF_VALUES:
                 var resource_query = query_ext.parent_query_ext.query.subqueries['resource'];
                 var warnings = manifold.query_store.get_record_state(resource_query.query_uuid, resource_key, STATE_WARNINGS);
 
-                if (event_type == STATE_SET_ADD) {
+                if (event_type == STATE_SET_ADD || event_type == STATE_SET_IN_PENDING) {
                      // A lease is added, it removes the constraint
                     delete warnings[CONSTRAINT_RESERVABLE_LEASE];
                 } else {
@@ -1749,23 +1817,22 @@ case TYPE_LIST_OF_VALUES:
                         // XXX Need for a better function to manage warnings
                         var warn = CONSTRAINT_RESERVABLE_LEASE_MSG;
                         warnings[CONSTRAINT_RESERVABLE_LEASE] = warn;
+
+                        // Signal the change to plugins (even if the constraint does not apply, so that the plugin can display a checkmark)
+                        data = {
+                            state:  STATE_WARNINGS,
+                            key   : resource_key,
+                            op    : null,
+                            value : warnings
+                        }
+                        manifold.raise_record_event(resource_query.query_uuid, FIELD_STATE_CHANGED, data);
                     } else {
                         // Lease are defined, delete the warning in case it was set previously
                         delete warnings[CONSTRAINT_RESERVABLE_LEASE];
                     }
-                    
                 }
-
+                /* Adding a lease can remove a warning and reduce the unconfigured resources  */
                 manifold.query_store.recount(resource_query.query_uuid); 
-
-                // Signal the change to plugins (even if the constraint does not apply, so that the plugin can display a checkmark)
-                data = {
-                    state:  STATE_WARNINGS,
-                    key   : resource_key,
-                    op    : null,
-                    value : warnings
-                }
-                manifold.raise_record_event(resource_query.query_uuid, FIELD_STATE_CHANGED, data);
                 break;
         }
 
@@ -1806,6 +1873,10 @@ case TYPE_LIST_OF_VALUES:
         query = query_ext.query;
 
         switch(event_type) {
+            case STATUS_REMOVE_WARNING:
+                record = manifold.query_store.get_record(query_uuid, data.value);
+                this._enforce_constraints(query_ext, record, data.value, STATE_SET_REMOVE);
+                break;
 
             // XXX At some point, should be renamed to RECORD_STATE_CHANGED
             case FIELD_STATE_CHANGED:
diff --git a/myslice.sqlite3.dummy b/myslice.sqlite3.dummy
new file mode 100644 (file)
index 0000000..f7b5885
Binary files /dev/null and b/myslice.sqlite3.dummy differ
index 84e392c..ea4d88c 100644 (file)
@@ -14,9 +14,9 @@ def urls():
             __import__(component)
             u.append( url(r'^%s/' % component, include('%s.urls' % component)) )
         except Exception, e:
-            logger.info("Cannot load component (%s): %s" % (component, e))
+            logger.error("Cannot load component ({}): {}".format(component, e))
         else:
-            logger.info("Loaded component %s" % component)
+            logger.info("Loaded component {}".format(component))
             
     return u
 
index 7cfe494..190c50d 100644 (file)
@@ -1,2 +1,28 @@
 [manifold]
 url = https://portal.onelab.eu:7080/
+admin_user = 
+admin_password = 
+
+[myslice]
+theme = onelab
+debug = true
+httproot =
+dataroot =
+components = sla,influxdb,forge
+
+[database]
+# postgresql_psycopg2, mysql, sqlite3 or oracle
+engine = sqlite3
+#name = myslice
+name = /Users/parmentelat/git/myslice/unfold.sqlite3
+server = 
+port = 
+user =
+password =
+
+
+
+[activity]
+#server = http://athos.ipv6.lip6.fr/activity/push/log
+#apikey = 
+#secret = 
index 3f79a19..5fe2169 100644 (file)
@@ -8,7 +8,7 @@ try:
     ROOT = os.path.realpath(os.path.dirname(__file__) + '/..')
 except:
     import traceback
-    traceback.print_exc()
+    logger.error(traceback.format_exc())
 
 
 from myslice.configengine import ConfigEngine
@@ -34,6 +34,7 @@ except:
 # DEBUG
 if config.myslice.debug :
     DEBUG = True
+    INTERNAL_IPS = ("127.0.0.1","132.227.84.195","132.227.78.191","132.227.84.191")
 else :
     DEBUG = False
 
@@ -242,15 +243,13 @@ INSTALLED_APPS = [
     # our django project
     'myslice',
     # the core of the UI
-    'auth', 
+    'localauth', 
     'manifoldapi',
     'unfold',
     # plugins
     'plugins',
     # views - more or less stable 
     'ui',
-    # managing database migrations
-    'south', 
     # Uncomment the next line to enable the admin:
      'django.contrib.admin',
        # FORGE Plugin app
@@ -258,9 +257,18 @@ INSTALLED_APPS = [
     # Uncomment the next line to enable admin documentation:
     # 'django.contrib.admindocs',
     'portal',
+    #'debug_toolbar',
 ]
+# with django-1.7 we leave south and use native migrations
+# managing database migrations
+import django
+major, minor, _, _, _ = django.VERSION
+if major == 1 and minor <= 6:
+    INSTALLED_APPS.append('south')
+
 # this app won't load in a build environment
-if not building: INSTALLED_APPS.append ('rest')
+if not building:
+    INSTALLED_APPS.append ('rest')
 
 for component in components.list() :
     INSTALLED_APPS.append(component)
@@ -269,7 +277,7 @@ BROKER_URL = "amqp://myslice:myslice@localhost:5672/myslice"
 
 for aux in auxiliaries:
     if os.path.isdir(os.path.join(ROOT,aux)): 
-        print("Using devel auxiliary",aux)
+        logger.info("Using devel auxiliary {}".format(aux))
         INSTALLED_APPS.append(aux)
 
 ACCOUNT_ACTIVATION_DAYS = 7 # One-week activation window; you may, of course, use a different value.
@@ -336,7 +344,7 @@ LOGGING = {
     }
 }
 
-AUTHENTICATION_BACKENDS = ('auth.manifoldbackend.ManifoldBackend',
+AUTHENTICATION_BACKENDS = ('localauth.manifoldbackend.ManifoldBackend',
                            'django.contrib.auth.backends.ModelBackend')
 
 ### the view to redirect malformed (i.e. with a wrong CSRF) incoming requests
@@ -351,7 +359,6 @@ CSRF_FAILURE_VIEW = 'manifoldapi.manifoldproxy.csrf_failure'
 
 ####SLA#####
 
-SLA_MANAGER_URL = "http://157.193.215.125:4001/sla-collector/sla"
-#SLA_MANAGER_URL = "http://172.24.76.28:8000/sla"
-SLA_MANAGER_USER = "portal"
-SLA_MANAGER_PASSWORD = "password"
+SLA_COLLECTOR_URL = "http://157.193.215.125:4001/sla-collector/sla"
+SLA_COLLECTOR_USER = "portal"
+SLA_COLLECTOR_PASSWORD = "password"
index f792a05..236e5ca 100644 (file)
@@ -12,7 +12,12 @@ import components
 # admin.autodiscover()
 
 # to enable insert_above stuff
-from django.template.loader import add_to_builtins
+# add_to_builtins has changed location with django-1.7
+# also note this will probably go away some day
+try:
+    from django.template.loader import add_to_builtins
+except:
+    from django.template.base import add_to_builtins
 add_to_builtins('insert_above.templatetags.insert_tags')
 
 from settings import auxiliaries, INSTALLED_APPS
@@ -65,7 +70,7 @@ urls = [
     # seems to be what login_required uses to redirect ...
     (r'^accounts/login/$', portal.homeview.HomeView.as_view()),
     (r'^login/?$', portal.homeview.HomeView.as_view()),
-    (r'^logout/?$', 'auth.views.logout_user'),
+    (r'^logout/?$', 'localauth.views.logout_user'),
     #
     # the manifold proxy
     (r'^manifold/proxy/(?P<format>\w+)/?$', 'manifoldapi.manifoldproxy.proxy'),
@@ -83,6 +88,7 @@ urls = [
     (r'^credentials/(?P<action>[^/]+)/?$', 'rest.credentials.dispatch'),
     (r'^cache/(?P<action>[^/]+)/?$', 'rest.cache.dispatch'),
     (r'^initscript/(?P<action>[^/]+)/?$', 'rest.initscript.dispatch'),
+    (r'^authority/(?P<action>[^/]+)/?$', 'rest.authority.dispatch'),
     #
     # REST monitoring
     (r'^monitor/services/?$', 'rest.monitor.servicesStatus'),
@@ -121,7 +127,7 @@ urls = [
     url(r'^portal/', include('portal.urls')),
 
     # SLA
-#    url(r'^sla/', include('sla.urls')),
+    #url(r'^sla/', include('sla.urls')),
 ]
 
 urls.extend( components.urls() )
index a58d412..b651da3 100644 (file)
@@ -41,6 +41,18 @@ class ColumnsEditor(Plugin):
         metadata = self.page.get_metadata()
         md_fields = metadata.details_by_object('resource')
 
+        sla_column_info = {
+            'name': 'sla_supported',
+            'default': '',
+            'is_array': False,
+            'description': '',
+            'type': 'bool',
+            'qualifier': None
+        }
+
+        if sla_column_info not in md_fields['column']:
+            md_fields['column'].append(sla_column_info)
+
         # XXX use django templating system here
         for md_field in sorted(md_fields['column']):
             if md_field['type'] == 'string':
index a0d269b..38a5ffc 100644 (file)
@@ -2,10 +2,13 @@ from unfold.plugin import Plugin
 
 class FilterStatusPlugin(Plugin):
     
-    def __init__ (self, query=None, **settings):
+    def __init__ (self, query=None, query_lease=None, **settings):
         Plugin.__init__ (self, **settings)
         self.query              = query
 
+        self.query_lease = query_lease
+        self.query_lease_uuid = query_lease.query_uuid
+
     def template_file (self):
         return "filter_status.html"
 
@@ -24,7 +27,7 @@ class FilterStatusPlugin(Plugin):
         # query_uuid will pass self.query results to the javascript
         # and will be available as "record" in :
         # on_new_record: function(record)
-        return ['plugin_uuid', 'domid', 'query_uuid']
+        return ['plugin_uuid', 'domid', 'query_uuid', 'query_lease_uuid']
 
     def export_json_settings (self):
         return True
index 9c1c244..324634c 100644 (file)
@@ -28,6 +28,7 @@
 
             /* Setup query and record handlers */
             this.listen_query(options.query_uuid);
+            this.listen_query(options.query_lease_uuid, 'leases');
 
             /* Setup click handlers */
             this.elts('list-group-item').click({'instance': this}, this._on_click);
         // XXX
     },
 
+    on_leases_field_state_changed: function(data) 
+    {
+        console.log('leases_field_state_changed');
+        this.on_field_state_changed(data);
+    },
     on_field_state_changed: function(data) 
     {
         var query_ext;
index d4dce75..d232811 100644 (file)
@@ -5,7 +5,6 @@ class CreateForm (Plugin):
 
     def __init__ (self, **settings):
         Plugin.__init__(self, **settings)
-        print "SETTINGS", settings
         assert 'page'   in settings, "You should specify page"
         assert 'object' in settings, "You should specify object"
 
index 587637a..2a1cca5 100644 (file)
@@ -1,5 +1,7 @@
 from unfold.plugin import Plugin
 
+from myslice.settings import logger
+
 class QueryGrid (Plugin):
 
     """A plugin for displaying a query as a list
@@ -67,7 +69,7 @@ Current implementation makes the following assumptions
         if self.checkboxes:
             # we use aoColumnDefs rather than aoColumns -- ignore user-provided aoColumns
             if 'aoColumns' in self.datatables_options:
-                print 'WARNING: querygrid uses aoColumnDefs, your aoColumns spec. is discarded'
+                logger.warning('WARNING: querygrid uses aoColumnDefs, your aoColumns spec. is discarded')
                 del self.datatables_options['aoColumns']
             # set aoColumnDefs in datatables_options - might already have stuff in there
             aoColumnDefs = self.datatables_options.setdefault ('aoColumnDefs',[])
index fe486d5..60265fc 100644 (file)
@@ -1,5 +1,7 @@
 from unfold.plugin import Plugin
 
+from myslice.settings import logger
+
 class QueryTable (Plugin):
 
     """A plugin for displaying a query as a list
@@ -50,7 +52,7 @@ Current implementation makes the following assumptions
             _columns = columns
             _hidden_columns = []
         elif self.query:
-            print "self.query.fields = ", self.query_all.fields
+            logger.debug("self.query.fields = {}".format(self.query_all.fields))
             # Columns displayed by default
             if self.default_fields is not None:
                 _columns = [field for field in self.default_fields if not field == 'urn']
@@ -59,7 +61,7 @@ Current implementation makes the following assumptions
             if query_all:
                 # We need a list because sets are not JSON-serializable
                 if self.default_fields is not None:
-                    print self.query_all.fields
+                    logger.debug(self.query_all.fields)
                     _hidden_columns = list(self.query_all.fields - set(self.default_fields))
                 else:
                     _hidden_columns = list(self.query_all.fields - self.query.fields)
@@ -70,11 +72,11 @@ Current implementation makes the following assumptions
             _columns = []
             _hidden_columns = []
 
-        print "_columns=", _columns
+        logger.debug("_columns={}".format(_columns))
         self.columns = { self.mapping.get(c, c) : c for c in _columns }
         self.hidden_columns = { self.mapping.get(c, c) : c for c in _hidden_columns }
-        print "self.columns", self.columns
-        print "self.hidden_columns", self.hidden_columns
+        logger.debug("self.columns {}".format(self.columns))
+        logger.debug("self.hidden_columns {}".format(self.hidden_columns))
 
         self.init_key=init_key
         self.datatables_options=datatables_options
@@ -84,7 +86,7 @@ Current implementation makes the following assumptions
         if self.checkboxes:
             # we use aoColumnDefs rather than aoColumns -- ignore user-provided aoColumns
             if 'aoColumns' in self.datatables_options:
-                print 'WARNING: querytable uses aoColumnDefs, your aoColumns spec. is discarded'
+                logger.warning('WARNING: querytable uses aoColumnDefs, your aoColumns spec. is discarded')
                 del self.datatables_options['aoColumns']
             # set aoColumnDefs in datatables_options - might already have stuff in there
             aoColumnDefs = self.datatables_options.setdefault ('aoColumnDefs',[])
index ab20810..c1b1923 100644 (file)
@@ -204,7 +204,7 @@ QUERYTABLE_BGCOLOR_REMOVED = 2;
                     resourceData['type'] = 'node ( Hardware: <a target="_blank" href="https://www.iot-lab.info/hardware/'+n[0]+'/">'+n[0]+'</a> )';
                     var coordinates = resourceData['testbed'];
                 } else {
-                    var logo = network_hrn;
+                    var logo = resourceData['testbed'];
                     var resourceLocation = {
                         'longitude' : aData[13],
                         'latitude' : aData[23],
@@ -533,11 +533,11 @@ QUERYTABLE_BGCOLOR_REMOVED = 2;
                             this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_RESET);
                             break;
                         case STATE_SET_IN_PENDING:
-                            this.set_checkbox_from_data(data.key, true);
+                            this.set_checkbox_from_data(data.value, true);
                             this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_ADDED);
                             break;  
                         case STATE_SET_OUT_PENDING:
-                            this.set_checkbox_from_data(data.key, false);
+                            this.set_checkbox_from_data(data.value, false);
                             this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_REMOVED);
                             break;
                     }
index a13856a..933f32f 100755 (executable)
@@ -196,11 +196,29 @@ var SCHEDULER_COLWIDTH = 50;
                 op   : STATE_SET_ADD,
                 value: new_lease
             }
+            prev_state = manifold.query_store.get_record_state($scope.instance.options.query_uuid, resource_urn, STATE_SET);
             manifold.raise_event($scope.instance.options.query_lease_uuid, FIELD_STATE_CHANGED, data);
+
             /* Add to local cache also, unless we listen to events from outside */
-            if (!(resource_urn in $scope._leases_by_resource))
+            if (!(resource_urn in $scope._leases_by_resource)){
                 $scope._leases_by_resource[resource_urn] = [];
+                /* Add the resource of the selected timeslot to the pending list */
+                data_resource = {
+                    state: STATE_SET,
+                    key  : null,
+                    op   : STATE_SET_ADD,
+                    value: resource_urn
+                };
+                /* Send the message to the list of resources, depending on the previous state */
+                prev_state = manifold.query_store.get_record_state($scope.instance.options.query_uuid, data_resource.value, STATE_SET);
+                if(jQuery.inArray(prev_state,[STATE_SET_OUT,STATE_SET_OUT_SUCCESS,STATE_SET_OUT_PENDING,STATE_SET_IN_FAILURE])>-1){
+                    manifold.raise_event($scope.instance.options.query_uuid, FIELD_STATE_CHANGED, data_resource);
+                }
+                /* Remove the warning on resource as we have added Leases to it */
+                //manifold.raise_event($scope.instance.options.query_uuid, STATUS_REMOVE_WARNING, data_resource);
+            }
             $scope._leases_by_resource[resource_urn].push(new_lease);
+
         }
 
         $scope._remove_lease = function(other)
@@ -224,10 +242,30 @@ var SCHEDULER_COLWIDTH = 50;
                 op   : STATE_SET_REMOVE,
                 value: other_key
             }
+            prev_state = manifold.query_store.get_record_state($scope.instance.options.query_uuid, other.resource, STATE_SET);
             manifold.raise_event($scope.instance.options.query_lease_uuid, FIELD_STATE_CHANGED, data);
-            /* Remove from local cache also, unless we listen to events from outside */
+            /* Remove Lease from local cache also, unless we listen to events from outside */
             $scope._leases_by_resource[other.resource] = $.grep($scope._leases_by_resource[other.resource], function(x) { return x != other; });
-
+            /* Last lease removed for this resource -> remove the resource from the list */
+            if($scope._leases_by_resource.hasOwnProperty(other.resource) && $scope._leases_by_resource[other.resource].length == 0){
+                /* remove resource from the list of selected resources */
+                 data_resource = {
+                    state: STATE_SET,
+                    key  : null,
+                    op   : STATE_SET_REMOVE,
+                    value: other.resource
+                };
+
+                prev_state = manifold.query_store.get_record_state($scope.instance.options.query_uuid, data_resource.value, STATE_SET);
+                /* Remove Resource from local cache */
+                delete $scope._leases_by_resource[data_resource.value]
+                /* Send the message to the list of resources, depending on the previous state */
+                if(jQuery.inArray(prev_state,[STATE_SET_IN,STATE_SET_IN_SUCCESS,STATE_SET_IN_PENDING,STATE_SET_OUT_FAILURE])>-1){
+                    manifold.raise_event($scope.instance.options.query_uuid, FIELD_STATE_CHANGED, data_resource);
+                    //manifold.raise_event($scope.instance.options.query_uuid, STATUS_REMOVE_WARNING, data_resource);
+                }
+               
+            }
         }
 
         $scope.select = function(index, model_lease, model_resource)
@@ -676,26 +714,42 @@ var SCHEDULER_COLWIDTH = 50;
             on_leases_filter_removed:    function(filter) { this._get_scope().$apply(); },
             on_leases_filter_clear:      function()       { this._get_scope().$apply(); },
 
-            on_field_state_changed: function(data)
+            on_resources_field_state_changed: function(data)
             {
-                /*
-                this._set_lease_slots(lease_key, lease);
-
+                console.log('on_resources_field_state_changed');
+                console.log(data);
                 switch(data.state) {
                     case STATE_SET:
                         switch(data.op) {
+                            /*
                             case STATE_SET_IN:
                             case STATE_SET_IN_SUCCESS:
                             case STATE_SET_OUT_FAILURE:
-                                this.set_checkbox_from_data(data.value, true);
-                                this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_RESET);
+                                //this.set_checkbox_from_data(data.value, true);
+                                //this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_RESET);
                                 break;  
+                            */
                             case STATE_SET_OUT:
                             case STATE_SET_OUT_SUCCESS:
                             case STATE_SET_IN_FAILURE:
-                                this.set_checkbox_from_data(data.value, false);
-                                this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_RESET);
+                                // A resource has been removed
+                                console.log(this._get_scope()._leases_by_resource);
+                                s = this._get_scope();
+                                // loop over the list of leases by resource cached
+                                $.each(this._get_scope()._leases_by_resource, function(k,v){
+                                    // if the resource removed is in the list
+                                    // we need to remove all the leases corresponding to that resoruce
+                                    if(k == data.value){
+                                        console.log(k,v);
+                                        // loop each lease should be removed
+                                        $.each(v, function(i,lease){
+                                            console.log(i,lease);
+                                            s._remove_lease(lease);
+                                        });
+                                    }
+                                });
                                 break;
+                            /*
                             case STATE_SET_IN_PENDING:
                                 this.set_checkbox_from_data(data.key, true);
                                 this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_ADDED);
@@ -704,14 +758,15 @@ var SCHEDULER_COLWIDTH = 50;
                                 this.set_checkbox_from_data(data.key, false);
                                 this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_REMOVED);
                                 break;
+                            */
                         }
                         break;
-
+                    /*
                     case STATE_WARNINGS:
                         this.change_status(data.key, data.value);
                         break;
+                    */
                 }
-                */
             },
 
 
index 259723b..89f3419 100755 (executable)
             //alert("1");\r
         </script>\r
     </div>\r
+</div>
\ No newline at end of file
index e69de29..ae14740 100644 (file)
@@ -0,0 +1,12 @@
+#sla_dialog {
+  //margin-top: 2em;
+  margin-left: 1em;
+}
+
+#sla_offers div.row p {
+  line-height: 40px;
+}
+
+span.provider {
+  font-weight: bold;
+}
\ No newline at end of file
index 1098e2e..2773df0 100644 (file)
@@ -15,6 +15,9 @@
 
     var SlaDialog = Plugin.extend({
 
+        accepted_slas: {},
+        queries: [],
+
         /** XXX to check
          * @brief Plugin constructor
          * @param options : an associative array of setting values
             
             /* GUI setup and event binding */
             // call function
+            this.button_binding();
+
+            // Get testbeds with sla and store them in localStorage
+            //this.get_testbeds_with_sla();
+
+        },
 
+        get_testbeds_with_sla: function () {
+            return $.get('/sla/testbeds/', function(data) {
+                if (typeof(Storage) !== "undefined") {
+                    if (!localStorage.getItem("sla_testbeds")) {
+                        var testbeds = data;
+                        localStorage.setItem("sla_testbeds", testbeds);
+                    }
+                }
+            });
         },
 
         find_row: function(key)
             return cols[0];
         },
 
+        check_template_status: function() {
+            for (var testbed in this.accepted_slas) {
+                if (!this.accepted_slas[testbed]) { return false; }
+            }
+
+            return true;
+        },
+
         /* PLUGIN EVENTS */
         // on_show like in querytable
 
 
         /* GUI EVENTS */
 
+        button_binding: function() {
+            var self = this;
+            $(".sla-accept-button").click(function() {
+                // set SLA as accepted and remove warnings
+                var id = $(this).closest(".row").attr("id");
+                self.accepted_slas[id] = true;
+                var is_ok = self.check_template_status();
+
+                $(".sla-alert").show();
+                $(this).button("complete");
+                $(this).prop("disabled", true);
+
+                if (is_ok) {
+                    // remove warnings
+                    // var warnings = manifold.query_store.get_record_state(resource_query.query_uuid, resource_key, STATE_WARNINGS);
+                }
+            });
+
+            $(".sla-alert-close").click(function() {
+                $(this).closest(".sla-alert").hide();
+            });
+        },
+
+        create_sla: function(record) {
+            var self = this;
+
+            var urns = [];
+
+            if (record.resource.length != 0 && typeof record.resource[0] === "object") {
+
+                record.resource.forEach(function(r) {
+                    if ($.inArray(r.component_id, record.resource) == -1) { // if not already selected
+                        urns.push(r.component_id);
+                    }
+                });
+
+                var data = {
+                    "SLIVER_INFO_AGGREGATE_URN": record.resource[0].component_manager_id,
+                    "SLIVER_INFO_EXPIRATION": record.lease[0].end_time,     // FIXME: only working with leases
+                    "SLIVER_INFO_SLICE_URN": record.slice_urn,
+                    "SLIVER_INFO_CREATOR_URN": record.users[0],
+                    "SLIVER_INFO_URN": urns,
+                    "SLIVER_INFO_SLA_ID": self._getUUID()
+                };
+
+                console.log(data);
+
+                $.post("/sla/agreements/create/", data)
+                    .done(function (response) {
+                        console.log("SLA created");
+                    });
+            }
+        },
+
         uncheck: function(urn)
         {
-            $('#slamodal').on('hidden.bs.modal', function(e){
-                $('#' + (urn).replace(/"/g,'')).click();
-                console.log('#' + (data.value).replace(/"/g,''));
-            });
+//            $('#slamodal').on('hidden.bs.modal', function(e){
+//                $('#' + (urn).replace(/"/g,'')).click();
+//                console.log('#' + (data.value).replace(/"/g,''));
+//            });
         },
 
         // a function to bind events here: click change
 
         },
 
-        on_field_state_changed: function(result)
+        on_field_state_changed: function(data)
         {
-            console.log("triggered state_changed: "+result);
+            var self = this;
             // this.set_state(result, this.options.username);
+
+             switch(data.state) {
+                case STATE_SET:
+                    switch(data.op) {
+                        case STATE_SET_IN_PENDING:
+                            if (typeof(data.value) == 'string') {
+                                // data.value = urn
+                                this._supports_sla(data.value)
+                                    .done( function(testbeds) {
+                                        var urn_regexp = /\+(.*?)\+/;
+                                        var urn = urn_regexp.exec(data.value)[1];
+                                        var pos = $.inArray(urn, testbeds);
+                                        if ( pos != -1) {
+                                            var id_ref = testbeds[pos].replace(/\.|:/g, "-");
+                                            $("#" + id_ref).data("urns").push(data.value);
+                                            $("#" + id_ref).show();
+                                            self.accepted_slas[id_ref] = false;
+                                            //$( "#sla_offers_list" ).append(
+                                            //    $("<li>").text("Testbed " + testbeds[pos] + " offers SLA for its resources")
+                                            //);
+                                        }
+                                    });
+                            }
+                            break;
+                        case STATE_SET_OUT:
+                            // data.value = urn
+                            if (typeof(data.value) == 'string') {
+                                // data.value = urn
+                                this._supports_sla(data.value)
+                                    .done( function(testbeds) {
+                                        var urn_regexp = /\+(.*?)\+/;
+                                        var urn = urn_regexp.exec(data.value)[1];
+                                        var pos = $.inArray(urn, testbeds);
+                                        if ( pos != -1) {
+                                            var id_ref = testbeds[pos].replace(/\.|:/g, "-");
+                                            var array = $("#" + id_ref).data("urns");
+                                            array.splice(array.indexOf(data.value), 1);
+
+                                            if ($("#" + id_ref).data("urns").length == 0) {
+                                                $("#" + id_ref).hide();
+                                                delete self.accepted_slas[id_ref];
+                                                $(".sla-accept-button").button("reset");
+                                                $(".sla-accept-button").prop("disabled", false);
+                                            }
+                                            //$( "#sla_offers_list" ).append(
+                                            //    $("<li>").text("Testbed " + testbeds[pos] + " offers SLA for its resources")
+                                            //);
+                                        }
+                                    });
+                            }
+                            break;
+                    }
+                    break;
+
+                case STATE_WARNINGS:
+                    // Add resource to SLA
+                    // data.key = urn
+                    // data.value = {1: "SLA acceptance required..."}
+                    // this.change_status(data.key, data.value);
+                    break;
+             }
         }, 
 
         // ... be sure to list all events here
 
         on_new_record: function(record)
         {
-
+            this.create_sla(record);
         },
 
         /* INTERNAL FUNCTIONS */
             // only convention, not strictly enforced at the moment
         },
 
+        _supports_sla: function(resource_urn) {
+            return $.ajax("/sla/testbeds/");
+        },
+
+
+
+        _getUUID: function() {
+            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+                var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8);
+                return v.toString(16);
+            });
+        },
+
     });
 
     /* Plugin registration */
index cb50c29..b1a9ab2 100644 (file)
@@ -1,47 +1,95 @@
 <div id={{ domid }}>
-<div class="modal fade" id="slamodal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"
-               data-backdrop="static" data-keyboard="false">
-  <div class="modal-dialog">
-    <div class="modal-content">
-      <div class="modal-header">
-        <h4 class="modal-title" id="myModalLabel">Selected testbed(s) provide the following SLAs</h4>
-      </div>
-      <div class="modal-body"  id="modal-body">
-        <table class="table" id="sla-modal-table">
-          <thead>
-          <tr>
-            <th>Testbed</th>
-            <th>SLA Description</th>
-            <th>Accept</th>
-          </tr>
-          </thead>
-          <tbody id="sla-table-body">
-          </tbody>
-        </table>
-      </div>
-      <div class="modal-footer">
-        <button type="button" id="cancel_sla" class="btn btn-default" data-dismiss="modal">Cancel</button>
-        <button type="button" id="submit_sla" class="btn btn-primary">Submit</button>
-      </div>
+    <div id="sla_template_modal" class="modal fade">
+        <div class="modal-dialog">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+                    <h4 class="modal-title">SLA Template description</h4>
+                </div>
+                <div class="modal-body">
+                    <p>Testbed offers:</p>
+                    <p>99% availability for 99% of the selected resources</p>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+                </div>
+            </div>
+        </div>
     </div>
-  </div>
-</div>
-<!-- <div class="modal fade" id="slamodal-virtualwall" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"
-    data-backdrop="static" data-keyboard="false">
-  <div class="modal-dialog">
-    <div class="modal-content">
-      <div class="modal-header">
-        <h4 class="modal-title" id="modalTitleId">Provider iMinds offers the following SLA</h4>
-      </div>
-      <div class="modal-body" id="modal-body">
-        <p>SLA description</p>
-        <p>Testbed guarantees 0.99 Uptime rate for 0.99 rate of the VirtualWall resources during the sliver lifetime</p>
-      </div>
-      <div class="modal-footer">
-        <button type="button" id="dismiss_sla_vwall" class="btn btn-default" data-dismiss="modal">Dismiss</button>
-        <button type="button" id="accept_sla_vwall" class="btn btn-primary">Accept</button>
-      </div>
+    <div class="sla-alert" hidden="hidden">
+        <div class="alert alert-success fade in">
+            <a href="#" class="sla-alert-close">&times;</a>
+            <strong>Accepted!</strong> The SLA has been accepted.
+        </div>
     </div>
-  </div>
-</div> -->
-</div>
+    <div id="sla_offers" class="container">
+        <div id="fuseco-fokus-fraunhofer-de" class="row" data-urns="[]" style="display: none">
+            <div class="col-md-6">
+                <p>Testbed <span class="provider">fuseco.fokus.fraunhofer.de</span> offers the following SLA for its resources</p>
+            </div>
+            <div class="col-md-1">
+                <button class="sla-info-button btn btn-default" data-toggle="modal" data-target="#sla_template_modal">
+                    <span class="glyphicon glyphicon-info-sign"></span>
+                    Details
+                </button>
+            </div>
+            <div class="col-md-1">
+                <button class="sla-accept-button btn btn-default" data-complete-text="Accepted" autocomplete="off">
+                    <span class="glyphicon glyphicon-ok"></span>
+                    Accept
+                </button>
+            </div>
+        </div>
+        <div id="omf-netmode" class="row" data-urns="[]" style="display: none">
+            <div class="col-md-6">
+                <p>Testbed <span class="provider">omf:netmode</span> offers the following SLA for its resources</p>
+            </div>
+            <div class="col-md-1">
+                <button class="sla-info-button btn btn-default" data-toggle="modal" data-target="#sla_template_modal">
+                    <span class="glyphicon glyphicon-info-sign"></span>
+                    Details
+                </button>
+            </div>
+            <div class="col-md-1">
+                <button class="sla-accept-button btn btn-default" data-complete-text="Accepted" autocomplete="off">
+                    <span class="glyphicon glyphicon-ok"></span>
+                    Accept
+                </button>
+            </div>
+        </div>
+        <div id="wilab2-ilabt-iminds-be" class="row" data-urns="[]" style="display: none">
+            <div class="col-md-6">
+                <p>Testbed <span class="provider">wilab2.ilabt.iminds.be</span> offers the following SLA for its resources</p>
+            </div>
+            <div class="col-md-1">
+                <button class="sla-info-button btn btn-default" data-toggle="modal" data-target="#sla_template_modal">
+                    <span class="glyphicon glyphicon-info-sign"></span>
+                    Details
+                </button>
+            </div>
+            <div class="col-md-1">
+                <button class="sla-accept-button btn btn-default" data-complete-text="Accepted" autocomplete="off">
+                    <span class="glyphicon glyphicon-ok"></span>
+                    Accept
+                </button>
+            </div>
+        </div>
+        <div id="wall2-ilabt-iminds-be" class="row" data-urns="[]" style="display: none">
+            <div class="col-md-6">
+                <p>Testbed <span class="provider">wall2.ilabt.iminds.be</span> offers the following SLA for its resources</p>
+            </div>
+            <div class="col-md-1">
+                <button class="sla-info-button btn btn-default" data-toggle="modal" data-target="#sla_template_modal">
+                    <span class="glyphicon glyphicon-info-sign"></span>
+                    Details
+                </button>
+            </div>
+            <div class="col-md-1">
+                <button class="sla-accept-button btn btn-default" data-complete-text="Accepted" autocomplete="off">
+                    <span class="glyphicon glyphicon-ok"></span>
+                    Accept
+                </button>
+            </div>
+        </div>
+    </div>
+</div>
\ No newline at end of file
index 89b3ec5..64322fd 100644 (file)
@@ -1,24 +1,27 @@
 from unfold.plugin import Plugin
 
+from myslice.settings import logger
+
 class Univbris(Plugin):
     
     def __init__ (self, query=None, **settings):
         Plugin.__init__ (self, **settings)
         self.query=query
-       self.query_uuid = query.query_uuid if query else None
-       print "called univbris plugin"
+        self.query_uuid = query.query_uuid if query else None
+        logger.info("called univbris plugin")
 
     def template_file (self):
         try:
             return "univbris_welcome.html"
-        except Exception:
-                   print "error template"
+        except Exception as e:
+            logger.error("error template {}".format(e))
 
     def requirements (self):
         reqs = {
-            'js_files' : [ "js/spin-presets.js", "js/spin.min.js", "js/jquery.spin.js",
-                           "js/manifold.js", "js/manifold-query.js",
-                           "js/unfold-helper.js",
+            'js_files' : [
+                "js/spin-presets.js", "js/spin.min.js", "js/jquery.spin.js",
+                "js/manifold.js", "js/manifold-query.js",
+                "js/unfold-helper.js",
                 'js/univbris.js',
             ],
             'css_files': [
@@ -31,7 +34,7 @@ class Univbris(Plugin):
         # query_uuid will pass self.query results to the javascript
         # and will be available as "record" in :
         # on_new_record: function(record)
-        return ['plugin_uuid', 'domid', 'query_uuid','init_key',]
+        return ['plugin_uuid', 'domid', 'query_uuid', 'init_key', ]
 
     def export_json_settings (self):
         return True
index 254fda2..5d15c3a 100644 (file)
@@ -1,5 +1,7 @@
 from unfold.plugin import Plugin
 
+from myslice.settings import logger
+
 class UnivbrisFoam (Plugin):
 
     """
@@ -49,20 +51,20 @@ Current implementation makes the following assumptions
         # Until we have a proper way to access queries in Python
         self.query_all      = query_all
         self.query_all_uuid = query_all.query_uuid if query_all else None
-       self.sync_query_uuid = sync_query.query_uuid if sync_query else None
+        self.sync_query_uuid = sync_query.query_uuid if sync_query else None
         self.checkboxes     = checkboxes
         # XXX We need to have some hidden columns until we properly handle dynamic queries
         if columns is not None:
             self.columns=columns
             self.hidden_columns = []
         elif self.query:
-           self.columns = list (['testbed','head node id/port','tail node id/port','link type','selected'])
-           #replace production
+            self.columns = list (['testbed','head node id/port','tail node id/port','link type','selected'])
+            #replace production
             #self.columns = self.query.fields
             if query_all:
                 #replace production
-               self.hidden_columns = []
-               # We need a list because sets are not JSON-serializable
+                self.hidden_columns = []
+                # We need a list because sets are not JSON-serializable
                 #self.hidden_columns = #list(self.query_all.fields - self.query.fields)
             else:
                 self.hidden_columns = []
@@ -77,7 +79,7 @@ Current implementation makes the following assumptions
         if self.checkboxes:
             # we use aoColumnDefs rather than aoColumns -- ignore user-provided aoColumns
             if 'aoColumns' in self.datatables_options:
-                print 'WARNING: querytable uses aoColumnDefs, your aoColumns spec. is discarded'
+                logger.warning('WARNING: querytable uses aoColumnDefs, your aoColumns spec. is discarded')
                 del self.datatables_options['aoColumns']
             # set aoColumnDefs in datatables_options - might already have stuff in there
             aoColumnDefs = self.datatables_options.setdefault ('aoColumnDefs',[])
index 6c9aef2..e2c6ab3 100644 (file)
@@ -1,5 +1,7 @@
 from unfold.plugin import Plugin
 
+from myslice.settings import logger
+
 class UnivbrisFv (Plugin):
 
     """
@@ -55,13 +57,13 @@ Current implementation makes the following assumptions
             self.columns=columns
             self.hidden_columns = []
         elif self.query:
-           self.columns = list (['Flowspace Name', 'Edit', 'Delete'])
-           #replace production
+            self.columns = list (['Flowspace Name', 'Edit', 'Delete'])
+            #replace production
             #self.columns = self.query.fields
             if query_all:
                 #replace production
-               self.hidden_columns = []
-               # We need a list because sets are not JSON-serializable
+                self.hidden_columns = []
+                # We need a list because sets are not JSON-serializable
                 #self.hidden_columns = #list(self.query_all.fields - self.query.fields)
             else:
                 self.hidden_columns = []
@@ -69,7 +71,7 @@ Current implementation makes the following assumptions
             self.columns = []
             self.hidden_columns = []
 
-       self.columns = list (['Flowspace Name', 'Edit', 'Delete'])
+        self.columns = list (['Flowspace Name', 'Edit', 'Delete'])
         self.init_key=init_key
         self.datatables_options=datatables_options
         # if checkboxes were required, we tell datatables about this column's type
@@ -78,7 +80,7 @@ Current implementation makes the following assumptions
         if self.checkboxes:
             # we use aoColumnDefs rather than aoColumns -- ignore user-provided aoColumns
             if 'aoColumns' in self.datatables_options:
-                print 'WARNING: querytable uses aoColumnDefs, your aoColumns spec. is discarded'
+                logger.warning('WARNING: querytable uses aoColumnDefs, your aoColumns spec. is discarded')
                 del self.datatables_options['aoColumns']
             # set aoColumnDefs in datatables_options - might already have stuff in there
             aoColumnDefs = self.datatables_options.setdefault ('aoColumnDefs',[])
@@ -98,12 +100,13 @@ Current implementation makes the following assumptions
     def requirements (self):
         reqs = {
             'js_files' : [ "js/spin-presets.js", "js/spin.min.js", "js/jquery.spin.js",
- "js/dataTables.js",  "js/dataTables.bootstrap.js", "js/with-datatables.js", "js/jquery.jeditable.js", 
+                           "js/dataTables.js",  "js/dataTables.bootstrap.js",
+                           "js/with-datatables.js", "js/jquery.jeditable.js", 
                            "js/manifold.js", "js/manifold-query.js", 
                            "js/unfold-helper.js",
                           # querytable.js needs to be loaded after dataTables.js as it extends 
                           # dataTableExt.afnSortData
-                         # "js/jquery-ui.min.js" "js/jquery.dataTables.editable.js", "js/jquery.validate.js",
+                          # "js/jquery-ui.min.js" "js/jquery.dataTables.editable.js", "js/jquery.validate.js",
                            "js/univbrisfv.js",#"js/univbrisfv.js",
                            ] ,
             'css_files': [ "css/dataTables.bootstrap.css",
index c9e92c9..6a9a47f 100644 (file)
@@ -1,24 +1,27 @@
 from unfold.plugin import Plugin
 
+from myslice.settings import logger
+
 class UnivbrisTopo(Plugin):
     
     def __init__ (self, query=None, **settings):
         Plugin.__init__ (self, **settings)
         self.query=query
-       self.query_uuid = query.query_uuid if query else None
-       print "called univbris topo plugin"
+        self.query_uuid = query.query_uuid if query else None
+        logger.info("called univbris topo plugin")
 
     def template_file (self):
-       try:
-               return "univbris_topology.html"
-       except:
-               print "error template"
+        try:
+            return "univbris_topology.html"
+        except Exception as e :
+            logger.error("error template {}".format(e))
 
     def requirements (self):
         reqs = {
-            'js_files' : [ "js/spin-presets.js", "js/spin.min.js", "js/jquery.spin.js",
-                           "js/manifold.js", "js/manifold-query.js", 
-                           "js/unfold-helper.js",
+            'js_files' : [
+                "js/spin-presets.js", "js/spin.min.js", "js/jquery.spin.js",
+                "js/manifold.js", "js/manifold-query.js", 
+                "js/unfold-helper.js",
                 'js/univbristopo.js', 'js/d3.v2.min.js','js/tooltip.topology.js',
             ],
             'css_files': [
index bc2bf9e..50da3ee 100644 (file)
@@ -1,5 +1,7 @@
 from unfold.plugin import Plugin
 
+from myslice.settings import logger
+
 class UnivbrisVtam (Plugin):
     def __init__ (self, query=None, query_all=None, sync_query=None,
                   checkboxes=False, columns=None, 
@@ -7,24 +9,24 @@ class UnivbrisVtam (Plugin):
                   datatables_options={}, **settings):
         Plugin.__init__ (self, **settings)
         self.query          = query
-       self.query_uuid     = query.query_uuid if query else None
+        self.query_uuid     = query.query_uuid if query else None
         # Until we have a proper way to access queries in Python
         self.query_all      = query_all
         self.query_all_uuid = query_all.query_uuid if query_all else None
-       self.sync_query_uuid = sync_query.query_uuid if sync_query else None
+        self.sync_query_uuid = sync_query.query_uuid if sync_query else None
         self.checkboxes     = checkboxes
         # XXX We need to have some hidden columns until we properly handle dynamic queries
         if columns is not None:
             self.columns=columns
             self.hidden_columns = []
         elif self.query:
-           self.columns = list (['Testbed', 'Virtualization Server', 'VM name', 'Delete'])
-           #replace production
+            self.columns = list (['Testbed', 'Virtualization Server', 'VM name', 'Delete'])
+            #replace production
             #self.columns = self.query.fields
             if query_all:
                 #replace production
-               self.hidden_columns = []
-               # We need a list because sets are not JSON-serializable
+                self.hidden_columns = []
+                # We need a list because sets are not JSON-serializable
                 #self.hidden_columns = #list(self.query_all.fields - self.query.fields)
             else:
                 self.hidden_columns = []
@@ -32,7 +34,7 @@ class UnivbrisVtam (Plugin):
             self.columns = []
             self.hidden_columns = []
 
-       self.columns = list (['Testbed', 'Virtualization Server', 'VM name', 'Delete'])
+        self.columns = list (['Testbed', 'Virtualization Server', 'VM name', 'Delete'])
         self.init_key=init_key
         self.datatables_options=datatables_options
         # if checkboxes were required, we tell datatables about this column's type
@@ -41,7 +43,7 @@ class UnivbrisVtam (Plugin):
         if self.checkboxes:
             # we use aoColumnDefs rather than aoColumns -- ignore user-provided aoColumns
             if 'aoColumns' in self.datatables_options:
-                print 'WARNING: querytable uses aoColumnDefs, your aoColumns spec. is discarded'
+                logger.warning('WARNING: querytable uses aoColumnDefs, your aoColumns spec. is discarded')
                 del self.datatables_options['aoColumns']
             # set aoColumnDefs in datatables_options - might already have stuff in there
             aoColumnDefs = self.datatables_options.setdefault ('aoColumnDefs',[])
index 99434a7..1bc51fc 100644 (file)
@@ -20,8 +20,8 @@ class AboutView (FreeAccessView, ThemeView):
     # expose this so we can mention the backend URL on the welcome page
     def default_env (self):
         return { 
-                 'MANIFOLD_URL':ConfigEngine().manifold_url(),
-                 }
+            'MANIFOLD_URL':ConfigEngine().manifold_url(),
+        }
 
     def post (self,request):
         env = self.default_env()
@@ -39,13 +39,14 @@ class AboutView (FreeAccessView, ThemeView):
         env['theme'] = self.theme
         env['section'] = "About"
 
-        env['username']=the_user(request)
+        env['username'] = the_user(request)
         env['topmenu_items'] = topmenu_items(None, request)
-        if state: env['state'] = state
-        elif not env['username']: env['state'] = None
+        if state:
+            env['state'] = state
+        elif not env['username']:
+            env['state'] = None
         # use one or two columns for the layout - not logged in users will see the login prompt
-        env['layout_1_or_2']="layout-unfold2.html" if not env['username'] else "layout-unfold1.html"
-        
+        env['layout_1_or_2'] = "layout-unfold2.html" if not env['username'] else "layout-unfold1.html"
         
         return render_to_response(self.template, env, context_instance=RequestContext(request))
 
index 7d08e1c..fc6d955 100644 (file)
@@ -10,14 +10,17 @@ import json, os, re, itertools
 
 class Account:
     def __init__ (self, platform_id, user_id):
-        account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config').filter_by('platform_id', '==', platform_id).filter_by('user_id', '==', user_id)
+        account_query  = Query().get('local:account')\
+                                .select('user_id','platform_id','auth_type','config')\
+                                .filter_by('platform_id', '==', platform_id)\
+                                .filter_by('user_id', '==', user_id)
  
-        account_details = execute_query(self.request, account_query)
+        account_details  = execute_query(self.request, account_query)
         self.user_id     = account_details['user_id']
         self.platform_id = account_details['platform_id']
         self.auth_type   = account_details['auth_type']
         self.config      = account_details['config']
-        account_config = json.loads(account_details['config'])
+        account_config   = json.loads(account_details['config'])
 
         self.usr_hrn = account_config.get('user_hrn',None)
         self.pub_key = account_config.get('user_public_key',None)
index dfda182..ffed13f 100644 (file)
@@ -1,25 +1,29 @@
-from unfold.loginrequired               import LoginRequiredAutoLogoutView
-#
-#
-from manifold.core.query                import Query
-from manifoldapi.manifoldapi            import execute_query
-from portal.actions                     import manifold_update_user, manifold_update_account, manifold_add_account, manifold_delete_account, sfa_update_user, sfa_get_user, clear_user_creds
 #
-from unfold.page                        import Page    
-from ui.topmenu                         import topmenu_items_live, the_user
+import json, os, re, itertools, time
+from OpenSSL import crypto
+from Crypto.PublicKey import RSA
+
 #
 from django.http                        import HttpResponse, HttpResponseRedirect
 from django.contrib                     import messages
 from django.contrib.auth.decorators     import login_required
 
-from myslice.configengine           import ConfigEngine
-from myslice.theme import ThemeView
+#
+from manifold.core.query                import Query
+from manifoldapi.manifoldapi            import execute_query
+
+from unfold.loginrequired               import LoginRequiredAutoLogoutView
+from unfold.page                        import Page    
+from ui.topmenu                         import topmenu_items_live, the_user
 
+from portal.actions                     import (
+    manifold_update_user, manifold_update_account, manifold_add_account,
+    manifold_delete_account, sfa_update_user, sfa_get_user, clear_user_creds, get_myslice_account, get_myslice_platform, get_registry_url, get_jfed_identity )
 from portal.account                     import Account, get_expiration
-#
-import json, os, re, itertools, time
-from OpenSSL import crypto
-from Crypto.PublicKey import RSA
+
+from myslice.settings                   import logger
+from myslice.configengine               import ConfigEngine
+from myslice.theme                      import ThemeView
 
 # requires login
 class AccountView(LoginRequiredAutoLogoutView, ThemeView):
@@ -34,7 +38,8 @@ class AccountView(LoginRequiredAutoLogoutView, ThemeView):
         metadata = page.get_metadata()
         page.expose_js_metadata()
 
-        page.add_js_files  ( [ "js/jquery.validate.js", "js/my_account.register.js", "js/my_account.edit_profile.js","js/jquery-ui.js" ] )
+        page.add_js_files  ( [ "js/jquery.validate.js", "js/my_account.register.js",
+                               "js/my_account.edit_profile.js","js/jquery-ui.js" ] )
         page.add_css_files ( [ "css/onelab.css", "css/account_view.css","css/plugin.css" ] )
 
         # Execute a Query to delegate credentials if necessary
@@ -174,8 +179,13 @@ class AccountView(LoginRequiredAutoLogoutView, ThemeView):
                         pub_key_list.append(account_pub_key)
                         user_status_list.append(user_status)
                         # combining 5 lists into 1 [to render in the template] 
-                        principal_acc_list = [{'platform_name': t[0], 'account_type': t[1], 'delegation_type': t[2], 'usr_hrn':t[3], 'usr_pubkey':t[4], 'user_status':t[5],} 
-                            for t in zip(platform_name_list, account_type_list, delegation_type_list, usr_hrn_list, pub_key_list, user_status_list)]
+                        principal_acc_list = [
+                            {'platform_name' : pn, 'account_type' : at,
+                             'delegation_type' : dt, 'usr_hrn' : uh,
+                             'usr_pubkey' : up, 'user_status' : us,} 
+                            for pn, at, dt, uh, up, us in zip(platform_name_list, account_type_list, delegation_type_list,
+                                         usr_hrn_list, pub_key_list, user_status_list)
+                        ]
                     # to hide private key row if it doesn't exist    
                     if 'myslice' in platform_detail['platform']:
                         account_config = json.loads(account_detail['config'])
@@ -191,25 +201,6 @@ class AccountView(LoginRequiredAutoLogoutView, ThemeView):
         platform_list = [{'platform_no_access': t[0]}
             for t in itertools.izip_longest(total_platform_list)]
 
-
-        ## check user is pi or not
-      #  platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
-      #  account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config')
-      #  platform_details = execute_query(self.request, platform_query)
-      #  account_details = execute_query(self.request, account_query)
-      #  for platform_detail in platform_details:
-      #      for account_detail in account_details:
-      #          if platform_detail['platform_id'] == account_detail['platform_id']:
-      #              if 'config' in account_detail and account_detail['config'] is not '':
-      #                  account_config = json.loads(account_detail['config'])
-      #                  if 'myslice' in platform_detail['platform']:
-      #                      acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
-        # assigning values
-        if acc_auth_cred == {} or acc_auth_cred == 'N/A':
-            pi = "is_not_pi"
-        else:
-            pi = "is_pi"
-
         # check if the user has creds or not
         if acc_user_cred == {} or acc_user_cred == 'N/A':
             user_cred = 'no_creds'
@@ -225,7 +216,6 @@ class AccountView(LoginRequiredAutoLogoutView, ThemeView):
         context['ref_acc'] = ref_acc_list
         context['platform_list'] = platform_list
         context['my_users'] = my_users
-        context['pi'] = pi
         context['user_cred'] = user_cred
         context['my_slices'] = my_slices
         context['my_auths'] = my_auths
@@ -247,27 +237,14 @@ class AccountView(LoginRequiredAutoLogoutView, ThemeView):
         context['theme'] = self.theme
         context['section'] = "User account"
 #        context ['firstname'] = config['firstname']
+
+        context['request'] = self.request
+
         prelude_env = page.prelude_env()
         context.update(prelude_env)
         return context
 
 @login_required
-def get_myslice_platform(request):
-    platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled','config').filter_by('platform','==','myslice')
-    platform_details = execute_query(request, platform_query)
-    for platform_detail in platform_details:
-        return platform_detail
-
-@login_required
-def get_myslice_account(request):
-    platform_myslice = get_myslice_platform(request)
-    account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config').filter_by('platform_id','==',platform_myslice['platform_id'])
-    account_details = execute_query(request, account_query)
-    for account_detail in account_details:
-        return account_detail
-
-@login_required
-#my_acc form value processing
 def account_process(request):
     from sfa.trust.credential               import Credential
     from sfa.trust.certificate              import Keypair
@@ -289,24 +266,28 @@ def account_process(request):
             if user_email == request.user.email:                                          
                 authorize_query = True                                                    
             else:                                                                         
-                print "SECURITY: %s tried to update %s" % (user_email, request.user.email)
+                logger.error("SECURITY: {} tried to update {}".format(user_email, request.user.email))
                 messages.error(request, 'You are not authorized to modify another user.') 
                 return HttpResponseRedirect("/portal/account/")                               
-        except Exception,e:
-            print "Exception = %s" % e
+        except Exception as e:
+            logger.error("exception in account_process {}".format(e))
 
     for account_detail in account_details:
         for platform_detail in platform_details:
             # Add reference account to the platforms
-            if 'add_'+platform_detail['platform'] in request.POST or request.POST['button_value'] == 'add_'+platform_detail['platform']:
+            if 'add_'+platform_detail['platform'] in request.POST\
+               or request.POST['button_value'] == 'add_'+platform_detail['platform']:
                 platform_id = platform_detail['platform_id']
-                user_params = {'platform_id': platform_id, 'user_id': user_id, 'auth_type': "reference", 'config': '{"reference_platform": "myslice"}'}
+                user_params = {'platform_id': platform_id, 'user_id': user_id,
+                               'auth_type': "reference",
+                               'config': '{"reference_platform": "myslice"}'}
                 manifold_add_account(request,user_params)
                 messages.info(request, 'Reference Account is added to the selected platform successfully!')
                 return HttpResponseRedirect("/portal/account/")
 
             # Delete reference account from the platforms
-            if 'delete_'+platform_detail['platform'] in request.POST or request.POST['button_value'] == 'delete_'+platform_detail['platform']:
+            if 'delete_'+platform_detail['platform'] in request.POST\
+               or request.POST['button_value'] == 'delete_'+platform_detail['platform']:
                 platform_id = platform_detail['platform_id']
                 user_params = {'user_id':user_id}
                 manifold_delete_account(request,platform_id, user_id, user_params)
@@ -352,7 +333,7 @@ def account_process(request):
                 response['Content-Disposition'] = 'attachment; filename="auth_credential.txt"'
                 return response
 
-
+    account_detail = get_myslice_account(request)
              
     if 'submit_name' in request.POST:
         edited_first_name =  request.POST['fname']
@@ -368,7 +349,8 @@ def account_process(request):
                 updated_config = json.dumps(config)
                 user_params = {'config': updated_config}
             else: # it's needed if the config is empty 
-                user_config['config']= '{"firstname":"' + edited_first_name + '", "lastname":"'+ edited_last_name + '", "authority": "Unknown Authority"}'
+                user_config['config'] = '{{"firstname":"{}", "lastname":"{}", "authority": "Unknown Authority"}}'\
+                                        .format(edited_first_name, edited_last_name)
                 user_params = {'config': user_config['config']} 
         # updating config local:user in manifold       
         manifold_update_user(request, request.user.email,user_params)
@@ -383,10 +365,10 @@ def account_process(request):
         for user_pass in user_details:
             user_pass['password'] = edited_password
         #updating password in local:user
-        user_params = { 'password': user_pass['password']}
-        manifold_update_user(request,request.user.email,user_params)
+        user_params = { 'password' : user_pass['password']}
+        manifold_update_user(request, request.user.email, user_params)
 #        return HttpResponse('Success: Password Changed!!')
-        messages.success(request, 'Sucess: Password Updated.')
+        messages.success(request, 'Success: Password Updated.')
         return HttpResponseRedirect("/portal/account/")
 
 # XXX TODO: Factorize with portal/registrationview.py
@@ -394,158 +376,136 @@ def account_process(request):
 # XXX TODO: Factorize with portal/joinview.py
 
     elif 'generate' in request.POST:
-        for account_detail in account_details:
-            for platform_detail in platform_details:
-                if platform_detail['platform_id'] == account_detail['platform_id']:
-                    if 'myslice' in platform_detail['platform']:
-                        private = RSA.generate(1024)
-                        private_key = json.dumps(private.exportKey())
-                        public  = private.publickey()
-                        public_key = json.dumps(public.exportKey(format='OpenSSH'))
-                        # updating manifold local:account table
-                        account_config = json.loads(account_detail['config'])
-                        # preserving user_hrn
-                        user_hrn = account_config.get('user_hrn','N/A')
-                        keypair = '{"user_public_key":'+ public_key + ', "user_private_key":'+ private_key + ', "user_hrn":"'+ user_hrn + '"}'
-                        #updated_config = json.dumps(account_config) 
-                        # updating manifold
-                        #user_params = { 'config': keypair, 'auth_type':'managed'}
-                        #manifold_update_account(request, user_id, user_params)
-                        # updating sfa
-                        public_key = public_key.replace('"', '');
-                        user_pub_key = {'keys': public_key}
-
-                        sfa_update_user(request, user_hrn, user_pub_key)
-                        result_sfa_user = sfa_get_user(request, user_hrn, public_key)
-                        try:
-                            if 'keys' in result_sfa_user and result_sfa_user['keys'][0] == public_key:
-                                # updating manifold
-                                updated_config = json.dumps(account_config) 
-                                user_params = { 'config': keypair, 'auth_type':'managed'}
-                                manifold_update_account(request, user_id, user_params)
-                                messages.success(request, 'Sucess: New Keypair Generated! Delegation of your credentials will be automatic.')
-                            else:
-                                raise Exception,"Keys are not matching"
-                        except Exception, e:
-                            messages.error(request, 'Error: An error occured during the update of your public key at the Registry, or your public key is not matching the one stored.')
-                            print "Exception in accountview ", e
-                        return HttpResponseRedirect("/portal/account/")
-        else:
+        try:
+            private = RSA.generate(1024)
+            private_key = json.dumps(private.exportKey())
+            public  = private.publickey()
+            public_key = json.dumps(public.exportKey(format='OpenSSH'))
+            # updating manifold local:account table
+            account_config = json.loads(account_detail['config'])
+            # preserving user_hrn
+            user_hrn = account_config.get('user_hrn','N/A')
+            keypair = '{"user_public_key":'+ public_key + ', "user_private_key":'+ private_key + ', "user_hrn":"'+ user_hrn + '"}'
+            #updated_config = json.dumps(account_config) 
+            # updating manifold
+            #user_params = { 'config': keypair, 'auth_type':'managed'}
+            #manifold_update_account(request, user_id, user_params)
+            # updating sfa
+            public_key = public_key.replace('"', '');
+            user_pub_key = {'keys': public_key}
+
+            sfa_update_user(request, user_hrn, user_pub_key)
+            result_sfa_user = sfa_get_user(request, user_hrn, public_key)
+            try:
+                if 'keys' in result_sfa_user and result_sfa_user['keys'][0] == public_key:
+                    # updating manifold
+                    updated_config = json.dumps(account_config) 
+                    user_params = { 'config': keypair, 'auth_type':'managed'}
+                    manifold_update_account(request, user_id, user_params)
+                    messages.success(request, 'Sucess: New Keypair Generated! Delegation of your credentials will be automatic.')
+                else:
+                    raise Exception,"Keys are not matching"
+            except Exception as e:
+                messages.error(request, 'Error: An error occured during the update of your public key at the Registry, or your public key is not matching the one stored.')
+                logger.error("Exception in accountview {}".format(e))
+            return HttpResponseRedirect("/portal/account/")
+        except Exception as e:
             messages.error(request, 'Account error: You need an account in myslice platform to perform this action')
             return HttpResponseRedirect("/portal/account/")
                        
     elif 'upload_key' in request.POST:
-        for account_detail in account_details:
-            for platform_detail in platform_details:
-                if platform_detail['platform_id'] == account_detail['platform_id']:
-                    if 'myslice' in platform_detail['platform']:
-                        up_file = request.FILES['pubkey']
-                        file_content =  up_file.read()
-                        file_name = up_file.name
-                        file_extension = os.path.splitext(file_name)[1] 
-                        allowed_extension =  ['.pub','.txt']
-                        if file_extension in allowed_extension and re.search(r'ssh-rsa',file_content):
-                            account_config = json.loads(account_detail['config'])
-                            # preserving user_hrn
-                            user_hrn = account_config.get('user_hrn','N/A')
-                            file_content = '{"user_public_key":"'+ file_content + '", "user_hrn":"'+ user_hrn +'"}'
-                            #file_content = re.sub("\r", "", file_content)
-                            #file_content = re.sub("\n", "\\n",file_content)
-                            file_content = ''.join(file_content.split())
-                            #update manifold local:account table
-                            user_params = { 'config': file_content, 'auth_type':'user'}
-                            manifold_update_account(request, user_id, user_params)
-                            # updating sfa
-                            user_pub_key = {'keys': file_content}
-                            sfa_update_user(request, user_hrn, user_pub_key)
-                            messages.success(request, 'Publickey uploaded! Please delegate your credentials using SFA: http://trac.myslice.info/wiki/DelegatingCredentials')
-                            return HttpResponseRedirect("/portal/account/")
-                        else:
-                            messages.error(request, 'RSA key error: Please upload a valid RSA public key [.txt or .pub].')
-                            return HttpResponseRedirect("/portal/account/")
-        else:
+        try:
+            up_file = request.FILES['pubkey']
+            file_content =  up_file.read()
+            file_name = up_file.name
+            file_extension = os.path.splitext(file_name)[1] 
+            allowed_extension =  ['.pub','.txt']
+            if file_extension in allowed_extension and re.search(r'ssh-rsa',file_content):
+                account_config = json.loads(account_detail['config'])
+                # preserving user_hrn
+                user_hrn = account_config.get('user_hrn','N/A')
+                file_content = '{"user_public_key":"'+ file_content + '", "user_hrn":"'+ user_hrn +'"}'
+                #file_content = re.sub("\r", "", file_content)
+                #file_content = re.sub("\n", "\\n",file_content)
+                file_content = ''.join(file_content.split())
+                #update manifold local:account table
+                user_params = { 'config': file_content, 'auth_type':'user'}
+                manifold_update_account(request, user_id, user_params)
+                # updating sfa
+                user_pub_key = {'keys': file_content}
+                sfa_update_user(request, user_hrn, user_pub_key)
+                messages.success(request, 'Publickey uploaded! Please delegate your credentials using SFA: http://trac.myslice.info/wiki/DelegatingCredentials')
+                return HttpResponseRedirect("/portal/account/")
+            else:
+                messages.error(request, 'RSA key error: Please upload a valid RSA public key [.txt or .pub].')
+                return HttpResponseRedirect("/portal/account/")
+
+        except Exception as e:
             messages.error(request, 'Account error: You need an account in myslice platform to perform this action')
             return HttpResponseRedirect("/portal/account/")
 
     elif 'dl_pubkey' in request.POST or request.POST['button_value'] == 'dl_pubkey':
-        for account_detail in account_details:
-            for platform_detail in platform_details:
-                if platform_detail['platform_id'] == account_detail['platform_id']:
-                    if 'myslice' in platform_detail['platform']:
-                        account_config = json.loads(account_detail['config'])
-                        public_key = account_config['user_public_key'] 
-                        response = HttpResponse(public_key, content_type='text/plain')
-                        response['Content-Disposition'] = 'attachment; filename="pubkey.txt"'
-                        return response
-                        break
-        else:
+        try:
+            account_config = json.loads(account_detail['config'])
+            public_key = account_config['user_public_key'] 
+            response = HttpResponse(public_key, content_type='text/plain')
+            response['Content-Disposition'] = 'attachment; filename="pubkey.txt"'
+            return response
+        except Exception as e:
             messages.error(request, 'Account error: You need an account in myslice platform to perform this action')
             return HttpResponseRedirect("/portal/account/")
                
     elif 'dl_pkey' in request.POST or request.POST['button_value'] == 'dl_pkey':
-        for account_detail in account_details:
-            for platform_detail in platform_details:
-                if platform_detail['platform_id'] == account_detail['platform_id']:
-                    if 'myslice' in platform_detail['platform']:
-                        account_config = json.loads(account_detail['config'])
-                        if 'user_private_key' in account_config:
-                            private_key = account_config['user_private_key']
-                            response = HttpResponse(private_key, content_type='text/plain')
-                            response['Content-Disposition'] = 'attachment; filename="privkey.txt"'
-                            return response
-                        else:
-                            messages.error(request, 'Download error: Private key is not stored in the server')
-                            return HttpResponseRedirect("/portal/account/")
+        try:
+            account_config = json.loads(account_detail['config'])
+            if 'user_private_key' in account_config:
+                private_key = account_config['user_private_key']
+                response = HttpResponse(private_key, content_type='text/plain')
+                response['Content-Disposition'] = 'attachment; filename="privkey.txt"'
+                return response
+            else:
+                messages.error(request, 'Download error: Private key is not stored in the server')
+                return HttpResponseRedirect("/portal/account/")
 
-        else:
+        except Exception as e:
             messages.error(request, 'Account error: You need an account in myslice platform to perform this action')
             return HttpResponseRedirect("/portal/account/")
     
     elif 'delete' in request.POST or request.POST['button_value'] == 'delete':
-        for account_detail in account_details:
-            for platform_detail in platform_details:
-                if platform_detail['platform_id'] == account_detail['platform_id']:
-                    if 'myslice' in platform_detail['platform']:
-                        account_config = json.loads(account_detail['config'])
-                        if 'user_private_key' in account_config:
-                            for key in account_config.keys():
-                                if key == 'user_private_key':    
-                                    del account_config[key]
-                                
-                            updated_config = json.dumps(account_config)
-                            user_params = { 'config': updated_config, 'auth_type':'user'}
-                            manifold_update_account(request, user_id, user_params)
-                            messages.success(request, 'Private Key deleted. You need to delegate credentials manually once it expires.')
-                            messages.success(request, 'Once your credentials expire, Please delegate manually using SFA: http://trac.myslice.info/wiki/DelegatingCredentials')
-                            return HttpResponseRedirect("/portal/account/")
-                        else:
-                            messages.error(request, 'Delete error: Private key is not stored in the server')
-                            return HttpResponseRedirect("/portal/account/")
-                           
-        else:
+        try:
+            account_config = json.loads(account_detail['config'])
+            if 'user_private_key' in account_config:
+                for key in account_config.keys():
+                    if key == 'user_private_key':    
+                        del account_config[key]
+                    
+                updated_config = json.dumps(account_config)
+                user_params = { 'config': updated_config, 'auth_type':'user'}
+                manifold_update_account(request, user_id, user_params)
+                messages.success(request, 'Private Key deleted. You need to delegate credentials manually once it expires.')
+                messages.success(request, 'Once your credentials expire, Please delegate manually using SFA: http://trac.myslice.info/wiki/DelegatingCredentials')
+                return HttpResponseRedirect("/portal/account/")
+            else:
+                messages.error(request, 'Delete error: Private key is not stored in the server')
+                return HttpResponseRedirect("/portal/account/")
+                          
+        except Exception as e:
             messages.error(request, 'Account error: You need an account in myslice platform to perform this action')    
             return HttpResponseRedirect("/portal/account/")
     
     # download identity for jfed
     elif 'dl_identity' in request.POST or request.POST['button_value'] == 'dl_identity':
-        for account_detail in account_details:
-            for platform_detail in platform_details:
-                if platform_detail['platform_id'] == account_detail['platform_id']:
-                    if 'myslice' in platform_detail['platform']:
-                        account_config = json.loads(account_detail['config'])
-                        if 'user_private_key' in account_config:
-                            private_key = account_config['user_private_key']
-                            user_hrn = account_config.get('user_hrn','N/A')
-                            registry = 'http://sfa-fed4fire.pl.sophia.inria.fr:12345/'
-                            jfed_identity = user_hrn + '\n' + registry + '\n' + private_key 
-                            response = HttpResponse(jfed_identity, content_type='text/plain')
-                            response['Content-Disposition'] = 'attachment; filename="jfed_identity.txt"'
-                            return response
-                        else:
-                            messages.error(request, 'Download error: Private key is not stored in the server')
-                            return HttpResponseRedirect("/portal/account/")
+        try:
+            jfed_identity = get_jfed_identity(request)
+            if jfed_identity is not None:
+                response = HttpResponse(jfed_identity, content_type='text/plain')
+                response['Content-Disposition'] = 'attachment; filename="jfed_identity.txt"'
+                return response
+            else:
+                messages.error(request, 'Download error: Private key is not stored in the server')
+                return HttpResponseRedirect("/portal/account/")
 
-        else:
+        except Exception as e:
             messages.error(request, 'Account error: You need an account in myslice platform to perform this action')
             return HttpResponseRedirect("/portal/account/")
 
@@ -559,13 +519,10 @@ def account_process(request):
         user_hrn = account_config.get('user_hrn','N/A')
         t_user_hrn = user_hrn.split('.')
         authority_hrn = t_user_hrn[0] + '.' + t_user_hrn[1]
+        registry = get_registry_url(request)
         import socket
         hostname = socket.gethostbyaddr(socket.gethostname())[0]
-        registry = platform_config.get('registry','N/A')
         admin_user = platform_config.get('user','N/A')
-        if 'localhost' in registry:
-            port = registry.split(':')[-1:][0]
-            registry = "http://" + hostname +':'+ port
         manifold_host = ConfigEngine().manifold_url()
         if 'localhost' in manifold_host:
             manifold_host = manifold_host.replace('localhost',hostname)
@@ -591,8 +548,8 @@ def account_process(request):
                 messages.success(request, 'All Credentials cleared')
             else:
                 messages.error(request, 'Delete error: Credentials are not stored in the server')
-        except Exception,e:
-            print "Exception in accountview.py in clear_user_creds %s" % e
+        except Exception as e:
+            logger.error("Exception in accountview.py in clear_user_creds {}".format(e))
             messages.error(request, 'Account error: You need an account in myslice platform to perform this action')
         return HttpResponseRedirect("/portal/account/")
 
index 82221ab..a6b33a5 100644 (file)
@@ -14,7 +14,7 @@ from django.core.mail               import EmailMultiAlternatives, send_mail
 
 from myslice.theme                  import ThemeView
 from myslice.configengine           import ConfigEngine
-
+from myslice.settings               import logger
 
 theme = ThemeView()
 
@@ -25,6 +25,58 @@ import activity.slice
 # XXX tmp sfa dependency, should be moved to SFA gateway
 #from sfa.util.xrn                import Xrn 
 
+def get_myslice_platform(request):
+    platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled','config').filter_by('platform','==','myslice')
+    platform_details = execute_query(request, platform_query)
+    if isinstance(platform_details,list):
+        for platform_detail in platform_details:
+            return platform_detail
+    else:
+        return None
+
+def get_myslice_account(request):
+    try:
+        platform_myslice = get_myslice_platform(request)
+        account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config').filter_by('platform_id','==',platform_myslice['platform_id'])
+        account_details = execute_query(request, account_query)
+        for account_detail in account_details:
+            return account_detail
+    except Exception as e:
+        print e
+        return None
+
+def get_registry_url(request):
+    try:
+        platform_detail = get_myslice_platform(request)
+        platform_config = json.loads(platform_detail['config'])
+        import socket
+        hostname = socket.gethostbyaddr(socket.gethostname())[0]
+        registry = platform_config.get('registry','N/A')
+        if 'localhost' in registry:
+            port = registry.split(':')[-1:][0]
+            registry = "http://" + hostname +':'+ port
+        return registry
+    except Exception as e:
+        print e
+        return None
+
+def get_jfed_identity(request):
+    try:
+        account_detail = get_myslice_account(request)
+        account_config = json.loads(account_detail['config'])
+        if 'user_private_key' in account_config:
+            private_key = account_config['user_private_key']
+            user_hrn = account_config.get('user_hrn','N/A')
+            platform_detail = get_myslice_platform(request)
+            registry = get_registry_url(request)
+            #registry = 'http://sfa-fed4fire.pl.sophia.inria.fr:12345/'
+            jfed_identity = user_hrn + '\n' + registry + '\n' + private_key 
+            return jfed_identity
+        else:
+            return None
+    except Exception as e:
+        print e
+        return None
 
 # Get the list of pis in a given authority
 def authority_get_pis(request, authority_hrn):
@@ -81,13 +133,14 @@ def authority_check_pis(request, user_email):
             pi_status = True
         return pi_status
 
-    except Exception,e:
-        print "Exception in actions.py in authority_check_pis %s" % e
+    except Exception as e:
+        logger.error("Exception in actions.py in authority_check_pis {}".format(e))
         return None
 
 
-def authority_add_pis(request, authority_hrn,user_hrn):
+def authority_add_pis(request, authority_hrn, user_hrn):
     try:
+        pi_list = []
         # getting pis of the authority of the user
         pis = authority_get_pis (request, authority_hrn)
         for pi in pis:
@@ -97,32 +150,58 @@ def authority_add_pis(request, authority_hrn,user_hrn):
         query = Query.update('myslice:authority').filter_by('authority_hrn', '==', authority_hrn).set({'pi_users':pi_list})
         results = execute_query(request,query)
         newpis = authority_get_pis (request, authority_hrn)
-        return newpis
-    except Exception,e: 
-        print "Exception in actions.py in authority_add_pis %s" % e
-        return None
+       
+        # Add the user to the slices of the project he/she joined
+        if len(authority_hrn.split('.')) > 2:
+            # this authority_hrn is a project
+            query_slices = Query.get('myslice:slice').filter_by('parent_authority', '==', authority_hrn).select('slice_hrn')
+            results_slices = execute_query(request,query_slices)
+            for s in results_slices:
+                sfa_add_user_to_slice(request, user_hrn, s['slice_hrn'])
+        # Clear Credentials of the user 
+        user_email = get_user_email(request, user_hrn)
+        clear_user_creds(request, user_email)
 
+        return newpis
+    except Exception as e: 
+        logger.error("Exception in actions.py in authority_add_pis {}".format(e))
+        raise Exception, "Exception in actions.py in authority_add_pis {}".format(e)
 
-def authority_remove_pis(request, authority_hrn,user_hrn):
+def authority_remove_pis(request, authority_hrn, user_hrn):
     try:
+        pi_list = []
         # getting pis of the authority of the user
         pis = authority_get_pis (request, authority_hrn)
         for pi in pis:
             pi_list = pi['pi_users']
  
         updated_pi_list = pi_list.remove(user_hrn) 
-        query = Query.update('authority').filter_by('authority_hrn', '==', authority_hrn).set({'pi_users':pi_list})
+        query = Query.update('myslice:authority').filter_by('authority_hrn', '==', authority_hrn).set({'pi_users':pi_list})
         results = execute_query(request,query)
         newpis = authority_get_pis (request, authority_hrn)
+
+        # Remove the user from the slices of the project he/she left
+        if len(authority_hrn.split('.')) > 2:
+            # this authority_hrn is a project
+            query_slices = Query.get('myslice:slice').filter_by('parent_authority', '==', authority_hrn).select('slice_hrn')
+            results_slices = execute_query(request,query_slices)
+            for s in results_slices:
+                print 'remove from slice %s' % s
+                sfa_remove_user_from_slice(request, user_hrn, s['slice_hrn'])
+
+        # Clear Credentials of the user 
+        user_email = get_user_email(request, user_hrn)
+        clear_user_creds(request, user_email)
+
         return newpis
-    except Exception,e: 
-        print "Exception in actions.py in authority_remove_pis %s" % e
-        return None
+    except Exception as e: 
+        logger.error("Exception in actions.py in authority_remove_pis {}".format(e))
+        raise Exception, "Exception in actions.py in authority_remove_pis {}".format(e)
 
 
 def authority_get_pi_emails(request, authority_hrn):
     pi_users = authority_get_pis(request,authority_hrn)
-    print "pi_users = %s" % pi_users
+    logger.info("pi_users = %s" % pi_users)
 
     if any(pi['pi_users'] == None or not pi['pi_users']  for pi in pi_users):
         #theme.template_name = 'email_default_recipients.txt' 
@@ -139,6 +218,11 @@ def authority_get_pi_emails(request, authority_hrn):
         results = execute_admin_query(request, query)
         return [result['user_email'] for result in results]
 
+def get_user_email(request, user_hrn):
+    query = Query.get('myslice:user').filter_by('user_hrn', '==', user_hrn).select('user_email')
+    results = execute_admin_query(request, query)
+    return results[0]['user_email'] 
+
 #clear user credentials
 def clear_user_creds(request, user_email):
     try:
@@ -174,13 +258,13 @@ def clear_user_creds(request, user_email):
                         else:
                             return None
 
-    except Exception,e:
-        print "Exception in actions.py in clear_user_creds %s" % e
+    except Exception as e:
+        logger.error("Exception in actions.py in clear_user_creds {}".format(e))
         return None
 
 def is_pi(wsgi_request, user_hrn, authority_hrn):
     # authorities from user where user_hrn == "ple.upmc.jordan_auge"
-    print "#### actions.py is_pi authority_hrn = ", authority_hrn
+    logger.debug("#### actions.py is_pi authority_hrn = {}".format(authority_hrn))
     try:
         # CACHE PB with fields
         page = Page(wsgi_request)
@@ -192,12 +276,11 @@ def is_pi(wsgi_request, user_hrn, authority_hrn):
         query  = Query().get('myslice:user').select(user_fields).filter_by('user_hrn','==',user_hrn)
         #query = Query.get('myslice:user').filter_by('user_hrn', '==', user_hrn).select('pi_authorities')
         results = execute_query(wsgi_request, query)
-        #print "is_pi results = ", results
         for user_detail in results:
             if authority_hrn in user_detail['pi_authorities']:
                 return True
-    except Exception,e:
-        print "Exception in actions.py in is_pi %s" % e
+    except Exception as e:
+        logger.error("Exception in actions.py in is_pi {}".format(e))
     return False
     
 # SFA get record
@@ -224,26 +307,48 @@ def sfa_add_authority(request, authority_params):
     # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
     query = Query.create('myslice:authority').set(authority_params).select('authority_hrn')
     results = execute_query(request, query)
-    print "sfa_add_auth results=",results
+    logger.info("sfa_add_auth results={}".format(results))
     if not results:
         raise Exception, "Could not create %s. Already exists ?" % authority_params['hrn']
     return results
 
-def sfa_add_user_to_slice(request, user_hrn, slice_params):
-# UPDATE myslice:slice SET researcher=['ple.upmc.jordan_auge','ple.inria.thierry_parmentelat','ple.upmc.loic_baron','ple.upmc.ciro_scognamiglio','ple.upmc.mohammed-yasin_rahman','ple.upmc.azerty'] where slice_hrn=='ple.upmc.myslicedemo'
+def sfa_add_user_to_slice(request, user_hrn, slice_hrn):
+# UPDATE myslice:slice SET users = ['fed4fire.upmc.loic_baron', 'fed4fire.upmc.mohammed-yasin_rahman', 'fed4fire.upmc.demo'] WHERE slice_hrn == 'fed4fire.upmc.project_y.test_under' SELECT slice_hrn, slice_urn
+    # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+    query_current_users = Query.get('myslice:slice').select('users').filter_by('slice_hrn','==',slice_hrn)
+    results_current_users = execute_query(request, query_current_users)
+    current_users = list()
+    for r in results_current_users:
+        current_users.extend(r['users'])
+    users = list(set([user_hrn]) | set(current_users))
+
+    # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+    query = Query.update('myslice:slice').filter_by('slice_hrn', '==', slice_hrn).set({'users':users}).select('slice_hrn')
+    results = execute_query(request, query)
+# Also possible but not supported yet
+# UPDATE myslice:user SET slice=['ple.upmc.agent','ple.upmc.myslicedemo','ple.upmc.tophat'] where user_hrn=='ple.upmc.azerty'
+    if not results:
+        raise Exception, "Could not add user %s to slice %s" % (user_hrn, slice_hrn)
+    return results
 
+def sfa_remove_user_from_slice(request, user_hrn, slice_hrn):
+# UPDATE myslice:slice SET users = ['fed4fire.upmc.loic_baron', 'fed4fire.upmc.demo'] WHERE slice_hrn == 'fed4fire.upmc.project_y.test_under' SELECT slice_hrn, slice_urn
     # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
-    query_current_users = Query.get('myslice:slice').select('user').filter_by('slice_hrn','==',slice_params['hrn'])
+    query_current_users = Query.get('myslice:slice').select('users').filter_by('slice_hrn','==',slice_hrn)
     results_current_users = execute_query(request, query_current_users)
-    slice_params['researcher'] = slice_params['researcher'] | results_current_users
+    current_users = list()
+    for r in results_current_users:
+        current_users.extend(r['users'])
+    if user_hrn in current_users:
+        current_users.remove(user_hrn)
 
     # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
-    query = Query.update('myslice:slice').filter_by('user_hrn', '==', user_hrn).set(slice_params).select('slice_hrn')
+    query = Query.update('myslice:slice').filter_by('slice_hrn', '==', slice_hrn).set({'users':current_users}).select('slice_hrn')
     results = execute_query(request, query)
 # Also possible but not supported yet
 # UPDATE myslice:user SET slice=['ple.upmc.agent','ple.upmc.myslicedemo','ple.upmc.tophat'] where user_hrn=='ple.upmc.azerty'
     if not results:
-        raise Exception, "Could not create %s. Already exists ?" % slice_params['hrn']
+        raise Exception, "Could not remove user %s to slice %s" % (user_hrn, slice_hrn)
     return results
 
 # Propose hrn
@@ -430,7 +535,7 @@ def make_request_authority(authority):
     return request
 
 def make_requests(pending_users, pending_slices, pending_authorities, pending_projects, pending_joins):
-    print "$$$$$$$$$$$$$$$  make_request"
+    logger.info("$$$$$$$$$$$$$$$  make_request")
     requests = []
     for user in pending_users:
         requests.append(make_request_user(user))
@@ -445,7 +550,7 @@ def make_requests(pending_users, pending_slices, pending_authorities, pending_pr
     return requests   
 
 def get_request_by_id(ids):
-    print "$$$$$$$$$$$$$$$$  get_request_by_id"
+    logger.info("$$$$$$$$$$$$$$$$  get_request_by_id")
     sorted_ids = { 'user': [], 'slice': [], 'authority': [], 'project': [], 'join': [] }
     for type__id in ids:
         type, id = type__id.split('__')
@@ -467,7 +572,7 @@ def get_request_by_id(ids):
     return make_requests(pending_users, pending_slices, pending_authorities, pending_projects, pending_joins)
 
 def get_requests(authority_hrns=None):
-    print "$$$$$$$$$$$$$   get_request_by_authority auth_hrns = ", authority_hrns
+    logger.info("$$$$$$$$$$$$$   get_request_by_authority auth_hrns = {}".format(authority_hrns))
     if not authority_hrns:
         ## get those pending users who have confirmed their emails
         pending_users  = PendingUser.objects.filter(status__iexact = 'True')
@@ -519,47 +624,39 @@ def portal_validate_request(wsgi_request, request_ids):
         # slice : number of nodes, type of nodes, purpose
         
         request_status = {}
-
-        if request['type'] == 'user':
-
-            try:
+        try:
+            if request['type'] == 'user':
                 create_user(wsgi_request, request)
                 request_status['SFA user'] = {'status': True }
+                u = PendingUser.objects.get(id=request['id'])
+                ctx = {
+                    'first_name'    : u.first_name, 
+                    'last_name'     : u.last_name,
+                    'email'         : u.email,        
+                }      
+                user_email = u.email
+
                 PendingUser.objects.get(id=request['id']).delete()
-            except Exception, e:
-                 request_status['SFA user'] = {'status': False, 'description': str(e)}
-                       
-#            user_params = {'status':2}
-#            manifold_update_user(request, request['email'], user_params)
-
-            # MANIFOLD user should be added beforehand, during registration
-            #try:
-            #    manifold_user_params = { key: request[key] for key in MANIFOLD_USER_KEYS }
-            #    # XXX # manifold_add_user(manifold_user_params)
-            #    request_status['MySlice user'] = {'status': True }
-            #except Exception, e:
-            #    request_status['MySlice user'] = {'status': False, 'description': str(e)}
-
-            # XXX
-            #manifold_account_params = { key: request[key] for key in MANIFOLD_ACCOUNT_KEYS }
-            #manifold_add_account(manifold_account_params)
-            #request_status['MySlice testbed accounts'] = {'status': False }
-
-        elif request['type'] == 'slice':
-            try:
+
+            elif request['type'] == 'slice':
                 create_slice(wsgi_request, request)
                 request_status['SFA slice'] = {'status': True }
+                s = PendingSlice.objects.get(id=request['id'])
+                ctx = {
+                    'slice_name'    : s.slice_name, 
+                    'url'           : s.url,
+                    'purpose'       : s.purpose,        
+                    'email'         : s.email,        
+                }      
+                user_email = s.email
+
                 PendingSlice.objects.get(id=request['id']).delete()
 
                 # Clear user's Credentials
                 sfa_user = sfa_get_user(wsgi_request, request['user_hrn'])
                 clear_user_creds(wsgi_request,sfa_user['user_email'])
 
-            except Exception, e:
-                request_status['SFA slice'] = {'status': False, 'description': str(e)}
-
-        elif request['type'] == 'authority':
-            try:
+            elif request['type'] == 'authority':
                 #hrn = "%s.%s" % (request['authority_hrn'], request['site_authority'])
                 hrn = request['site_authority']
                 # XXX tmp sfa dependency
@@ -574,16 +671,27 @@ def portal_validate_request(wsgi_request, request_ids):
                     #'pi'        : None,
                     #'enabled'    : True
                 }
-                print "ADD Authority"
+                logger.info("ADD Authority")
                 sfa_add_authority(wsgi_request, sfa_authority_params)
                 request_status['SFA authority'] = {'status': True }
-                PendingAuthority.objects.get(id=request['id']).delete()
+                a = PendingAuthority.objects.get(id=request['id'])
+                ctx = { 
+                    'site_name'     : a.site_name,
+                    'short_name'    : a.short_name,
+                    'url'           : a.url,
+                    'city'          : a.city,
+                    'country'       : a.country,                          
+                    'portal_url'    : a.current_site,
+                }
+                user_email = a.email
 
-            except Exception, e:
-                request_status['SFA authority'] = {'status': False, 'description': str(e)}
+                PendingAuthority.objects.get(id=request['id']).delete()
+                
+                # Clear Admin Cache as it is used to display the list of authorities in Registration page
+                query = Query.update('myslice:authority').filter_by('authority_hrn', '==', sfa_authority_params['authority_hrn']).set({'authority_hrn':sfa_authority_params['authority_hrn']}).select('authority_hrn')
+                res = execute_admin_query(request, query)
 
-        elif request['type'] == 'project':
-            try:
+            elif request['type'] == 'project':
                 hrn = request['authority_hrn'] + '.' + request['project_name']
 
                 # Only hrn is required for Manifold Query 
@@ -591,35 +699,51 @@ def portal_validate_request(wsgi_request, request_ids):
                     'authority_hrn'        : hrn
                 }
                 sfa_add_authority(wsgi_request, sfa_authority_params)
-                request_status['SFA project'] = {'status': True }
-                PendingProject.objects.get(id=request['id']).delete()
                 
                 # Add user as a PI of the project
+                # Clear user's Credentials
                 authority_add_pis(wsgi_request, hrn , request['user_hrn'])
 
-                # Clear user's Credentials
-                #sfa_user = sfa_get_user(wsgi_request, request['user_hrn'])
-                clear_user_creds(wsgi_request,request['email'])
+                request_status['SFA project'] = {'status': True }
+                p = PendingProject.objects.get(id=request['id'])
+                ctx = {
+                    'project_name'  : p.project_name, 
+                    'authority_hrn' : p.authority_hrn,
+                    'email'         : p.email,        
+                    'purpose'       : p.purpose,
+                }      
+                user_email = p.email
+
+                PendingProject.objects.get(id=request['id']).delete()
+
+                # Clear Admin Cache as it is used to display the list of projects in Slice request page
+                query = Query.update('myslice:authority').filter_by('authority_hrn', '==', sfa_authority_params['authority_hrn']).set({'authority_hrn':sfa_authority_params['authority_hrn']}).select('authority_hrn')
+                res = execute_admin_query(request, query)
 
-            except Exception, e:
-                request_status['SFA project'] = {'status': False, 'description': str(e)}
 
-        elif request['type'] == 'join':
-            try:
+            elif request['type'] == 'join':
                 # Add user as a PI of the project
+                # Clear user's Credentials
                 authority_add_pis(wsgi_request, request['authority_hrn'] , request['user_hrn'])
 
                 request_status['SFA join'] = {'status': True }
-                PendingJoin.objects.get(id=request['id']).delete()
+                j = PendingJoin.objects.get(id=request['id'])
+                ctx = {
+                    'project_name'  : j.project_name, 
+                    'authority_hrn' : j.authority_hrn,
+                    'email'         : j.email,        
+                    'user_hrn'      : j.user_hrn,
+                }      
+                user_email = j.email
 
-                # Clear user's Credentials
-                clear_user_creds(wsgi_request,request['email'])
+                PendingJoin.objects.get(id=request['id']).delete()
+            else:
+                raise Exception, 'unknown type of request %s' % request['type']
+            # XXX Remove from Pendings in database
 
-            except Exception, e:
-                request_status['SFA join'] = {'status': False, 'description': str(e)+' - '+str(request)}
-        else:
-            request_status['other'] = {'status': False, 'description': 'unknown type of request'}
-        # XXX Remove from Pendings in database
+            send_status_email(ctx, user_email, request['type'], 'validated')
+        except Exception, e:
+            request_status['SFA '+request['type']] = {'status': False, 'description': str(e)}
 
         status['%s__%s' % (request['type'], request['id'])] = request_status
 
@@ -629,14 +753,14 @@ def validate_action(request, **kwargs):
     ids = filter(None, kwargs['id'].split('/'))
     status = portal_validate_request(request, ids)
     json_answer = json.dumps(status)
-    return HttpResponse (json_answer, mimetype="application/json")
+    return HttpResponse (json_answer, content_type="application/json")
 
 
 def reject_action(request, **kwargs):
     ids = filter(None, kwargs['id'].split('/'))
     status = portal_reject_request(request, ids)
     json_answer = json.dumps(status)
-    return HttpResponse (json_answer, mimetype="application/json")
+    return HttpResponse (json_answer, content_type="application/json")
 
 
 def portal_reject_request(wsgi_request, request_ids):
@@ -658,8 +782,8 @@ def portal_reject_request(wsgi_request, request_ids):
         
         request_status = {}
 
-        if request['type'] == 'user':
-            try:
+        try:
+            if request['type'] == 'user':
                 request_status['SFA user'] = {'status': True }
                 # getting user email based on id 
                 ## RAW SQL queries on Django DB- https://docs.djangoproject.com/en/dev/topics/db/sql/
@@ -671,120 +795,114 @@ def portal_reject_request(wsgi_request, request_ids):
                 ctx = {
                     'first_name'    : first_name, 
                     'last_name'     : last_name, 
+                    'email'         : user_email,
                     'portal_url'    : current_site,
                     }
-                try:
-                    theme.template_name = 'user_request_denied.txt'
-                    text_content = render_to_string(theme.template, ctx)
-                    theme.template_name = 'user_request_denied.html'
-                    html_content = render_to_string(theme.template, ctx)
-                    theme.template_name = 'email_default_sender.txt'
-                    sender =  render_to_string(theme.template, ctx)
-                    sender = sender.replace('\n', '')
-                               
-                    subject = 'User request denied.'
-
-                    msg = EmailMultiAlternatives(subject, text_content, sender, [user_email])
-                    msg.attach_alternative(html_content, "text/html")
-                    msg.send()
-                except Exception, e:
-                    print "Failed to send email, please check the mail templates and the SMTP configuration of your server"   
 
                 # removing from Django portal_pendinguser
                 PendingUser.objects.get(id=request['id']).delete()
-            
+                
                 delete_local_user(wsgi_request, user_email)
-            except Exception, e:
-                request_status['SFA authority'] = {'status': False, 'description': str(e)}
-                      
-        elif request['type'] == 'slice':
-            request_status['SFA slice'] = {'status': True } 
-
-            # getting user email based on id 
-            ## RAW SQL queries on Django DB- https://docs.djangoproject.com/en/dev/topics/db/sql/
-            for user in PendingSlice.objects.raw('SELECT * FROM portal_pendingslice WHERE id = %s', [request['id']]):
-                user_email= user.type_of_nodes # XXX type_of_nodes field contains the email [shd be renamed in DB]
-                slice_name = user.slice_name
-                purpose = user.purpose
-                url = user.number_of_nodes
-
-            ctx = {
-                'slice_name': slice_name,
-                'purpose': purpose,
-                'url': url,
-                'portal_url': current_site,
-                }
-            try:
-                theme.template_name = 'slice_request_denied.txt'
-                text_content = render_to_string(theme.template, ctx)
-                theme.template_name = 'slice_request_denied.html'
-                html_content = render_to_string(theme.template, ctx)
-                theme.template_name = 'email_default_sender.txt'
-                sender =  render_to_string(theme.template, ctx)
-                sender = sender.replace('\n', '')
-                               
-                subject = 'Slice request denied.'
-
-                msg = EmailMultiAlternatives(subject, text_content, sender, [user_email])
-                msg.attach_alternative(html_content, "text/html")
-                msg.send()
-            except Exception, e:
-                print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
-                      
-            PendingSlice.objects.get(id=request['id']).delete()
-
-        elif request['type'] == 'authority':
-            request_status['SFA authority'] = {'status': True }
-            
-            # getting user email based on id 
-            ## RAW SQL queries on Django DB- https://docs.djangoproject.com/en/dev/topics/db/sql/
-            for user in PendingAuthority.objects.raw('SELECT * FROM portal_pendingauthority WHERE id = %s', [request['id']]):
-                user_email= user.address_line1 # XXX address_line1 field contains the email [shd be renamed in DB]
-                site_name = user.site_name
-                city = user.address_city
-                country = user.address_country
-                short_name = user.site_abbreviated_name
-                url = user.site_url
-
-            ctx = { 
-                'site_name': site_name,
-                'short_name': short_name,
-                'url': url,
-                'city': city,
-                'country': country,                          
-                'portal_url'    : current_site,
-                }
+                          
+            elif request['type'] == 'slice':
+                request_status['SFA slice'] = {'status': True } 
+
+                # getting user email based on id 
+                ## RAW SQL queries on Django DB- https://docs.djangoproject.com/en/dev/topics/db/sql/
+                for user in PendingSlice.objects.raw('SELECT * FROM portal_pendingslice WHERE id = %s', [request['id']]):
+                    user_email= user.type_of_nodes # XXX type_of_nodes field contains the email [shd be renamed in DB]
+                    slice_name = user.slice_name
+                    purpose = user.purpose
+                    url = user.number_of_nodes
+
+                ctx = {
+                    'slice_name': slice_name,
+                    'purpose': purpose,
+                    'url': url,
+                    'portal_url': current_site,
+                    }
+
+                PendingSlice.objects.get(id=request['id']).delete()
+
+            elif request['type'] == 'authority':
+                request_status['SFA authority'] = {'status': True }
                 
-            try:
-                theme.template_name = 'authority_request_denied.txt'
-                text_content = render_to_string(theme.template, ctx)
-                theme.template_name = 'authority_request_denied.html'
-                html_content = render_to_string(theme.template, ctx)
-                theme.template_name = 'email_default_sender.txt'
-                sender =  render_to_string(theme.template, ctx)
-                sender = sender.replace('\n', '')
-                subject = 'Authority request denied.'
-                msg = EmailMultiAlternatives(subject, text_content, sender, [user_email])
-                msg.attach_alternative(html_content, "text/html")
-                msg.send()
-            except Exception, e:
-                print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
-
-            PendingAuthority.objects.get(id=request['id']).delete()
-
-        # XXX TMP we should send an email to the user to inform him/her
-        elif request['type'] == 'project':
-            request_status['SFA project'] = {'status': True }
-            PendingProject.objects.get(id=request['id']).delete()
-
-        elif request['type'] == 'join':
-            request_status['SFA join'] = {'status': True }
-            PendingJoin.objects.get(id=request['id']).delete()
+                # getting user email based on id 
+                ## RAW SQL queries on Django DB- https://docs.djangoproject.com/en/dev/topics/db/sql/
+                for user in PendingAuthority.objects.raw('SELECT * FROM portal_pendingauthority WHERE id = %s', [request['id']]):
+                    user_email= user.address_line1 # XXX address_line1 field contains the email [shd be renamed in DB]
+                    site_name = user.site_name
+                    city = user.address_city
+                    country = user.address_country
+                    short_name = user.site_abbreviated_name
+                    url = user.site_url
+
+                ctx = { 
+                    'site_name': site_name,
+                    'short_name': short_name,
+                    'url': url,
+                    'city': city,
+                    'country': country,                          
+                    'portal_url'    : current_site,
+                    }
+                    
+                PendingAuthority.objects.get(id=request['id']).delete()
+
+            # XXX TMP we should send an email to the user to inform him/her
+            elif request['type'] == 'project':
+                request_status['SFA project'] = {'status': True }
+                p = PendingProject.objects.get(id=request['id'])
+                ctx = {
+                    'project_name'  : p.project_name, 
+                    'authority_hrn' : p.authority_hrn,
+                    'email'         : p.email,        
+                    'purpose'       : p.purpose,
+                }      
+                user_email = p.email
+                PendingProject.objects.get(id=request['id']).delete()
+
+            elif request['type'] == 'join':
+                request_status['SFA join'] = {'status': True }
+                j = PendingJoin.objects.get(id=request['id'])
+                ctx = {
+                    'project_name'  : j.project_name, 
+                    'authority_hrn' : j.authority_hrn,
+                    'email'         : j.email,        
+                    'user_hrn'      : j.user_hrn,
+                }      
+
+                user_email = j.email
+                PendingJoin.objects.get(id=request['id']).delete()
+            else:
+                raise Exception, 'unknown type of request %s' % request['type']
+
+            send_status_email(ctx, user_email, request['type'], 'denied')
+        except Exception, e:
+            request_status['SFA '+request['type']] = {'status': False, 'description': str(e)}
 
         status['%s__%s' % (request['type'], request['id'])] = request_status
 
     return status
 
+def send_status_email(ctx, user_email, obj_type, status):
+    try:
+        theme.template_name = obj_type + '_request_' + status + '.txt'
+        text_content = render_to_string(theme.template, ctx)
+        theme.template_name = obj_type + '_request_' + status + '.html'
+        html_content = render_to_string(theme.template, ctx)
+        theme.template_name = 'email_default_sender.txt'
+        sender =  render_to_string(theme.template, ctx)
+        sender = sender.replace('\n', '')
+                       
+        subject = obj_type + ' request '+ status +'.'
+    
+        msg = EmailMultiAlternatives(subject, text_content, sender, [user_email])
+        msg.attach_alternative(html_content, "text/html")
+        msg.send()
+    except Exception as e:
+        logger.error("Failed to send email, please check the mail templates and the SMTP configuration of your server")
+
+
 # Django and ajax
 # http://djangosnippets.org/snippets/942/
 
@@ -831,6 +949,14 @@ def create_slice(wsgi_request, request):
     if not 'number_of_nodes' in request:
         request['number_of_nodes']=""
 
+    # Slice is under a project
+    if len(request['authority_hrn'].split('.')) > 2:
+        pi_list = []
+        pis = authority_get_pis(wsgi_request, request['authority_hrn'])
+        for pi in pis:
+            pi_list = pi['pi_users']
+        user_hrns.extend(pi_list)
+
     # XXX We should create a slice with Manifold terminology
     slice_params = {
         'slice_hrn'        : hrn, 
@@ -848,26 +974,15 @@ def create_slice(wsgi_request, request):
     if not results:
         raise Exception, "Could not create %s. Already exists ?" % slice_params['hrn']
     else:
-        clear_user_creds(wsgi_request,user_email)
+        try:
+            for u_hrn in user_hrns:
+                u_email = get_user_email(wsgi_request, u_hrn)
+                clear_user_creds(wsgi_request, u_email)
+        except Exception as e:
+            logger.error("Failed clear credentials for all users")
+            clear_user_creds(wsgi_request,user_email)
         # log user activity
         activity.slice.validate(request, { "slice" : hrn })
-        try:
-            theme.template_name = 'slice_request_validated.txt'
-            text_content = render_to_string(theme.template, request)
-            theme.template_name = 'slice_request_validated.html'
-            html_content = render_to_string(theme.template, request)
-        
-            theme.template_name = 'email_default_sender.txt'
-            sender =  render_to_string(theme.template, request)
-            sender = sender.replace('\n', '')
-
-            subject = 'Slice request validated'
-
-            msg = EmailMultiAlternatives(subject, text_content, sender, [user_email])
-            msg.attach_alternative(html_content, "text/html")
-            msg.send()
-        except Exception, e:
-            print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
        
     return results
 
@@ -886,27 +1001,7 @@ def create_pending_slice(wsgi_request, request, email):
     )
     s.save()
 
-    try:
-        # Send an email: the recipients are the PI of the authority
-        recipients = authority_get_pi_emails(wsgi_request, request['authority_hrn'])
-
-        theme.template_name = 'slice_request_email.txt' 
-        text_content = render_to_string(theme.template, request)
-    
-        theme.template_name = 'slice_request_email.html' 
-        html_content = render_to_string(theme.template, request)
-    
-        theme.template_name = 'slice_request_email_subject.txt'
-        subject = render_to_string(theme.template, request)
-        subject = subject.replace('\n', '')
-    
-        sender = email
-        msg = EmailMultiAlternatives(subject, text_content, sender, recipients)
-        msg.attach_alternative(html_content, "text/html")
-        msg.send()
-    except Exception, e:
-        print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
-
+    send_email_to_pis(wsgi_request, request, 'slice')
 
 def create_pending_project(wsgi_request, request):
     """
@@ -922,6 +1017,8 @@ def create_pending_project(wsgi_request, request):
     )
     s.save()
 
+    send_email_to_pis(wsgi_request, request, 'project')
+
 def create_pending_join(wsgi_request, request):
     """
     """
@@ -935,27 +1032,36 @@ def create_pending_join(wsgi_request, request):
     )
     s.save()
 
+    send_email_to_pis(wsgi_request, request, 'join')
+
+#-------------------------------------------------------------------------------
+# SEND EMAILS
+#-------------------------------------------------------------------------------
+
+def send_email_to_pis(wsgi_request, request, obj_type):
+    try:
+        # Send an email: the recipients are the PIs of the authority
+        recipients = authority_get_pi_emails(wsgi_request, request['authority_hrn'])
+
+        theme.template_name = obj_type + '_request_email.txt' 
+        text_content = render_to_string(theme.template, request)
+
+        theme.template_name = obj_type + '_request_email.html' 
+        html_content = render_to_string(theme.template, request)
 
-#     try:
-#         # Send an email: the recipients are the PI of the authority
-#         recipients = authority_get_pi_emails(wsgi_request, request['authority_hrn'])
-# 
-#         theme.template_name = 'slice_request_email.txt' 
-#         text_content = render_to_string(theme.template, request)
-#     
-#         theme.template_name = 'slice_request_email.html' 
-#         html_content = render_to_string(theme.template, request)
-#     
-#         theme.template_name = 'slice_request_email_subject.txt'
-#         subject = render_to_string(theme.template, request)
-#         subject = subject.replace('\n', '')
-#     
-#         sender = email
-#         msg = EmailMultiAlternatives(subject, text_content, sender, recipients)
-#         msg.attach_alternative(html_content, "text/html")
-#         msg.send()
-#     except Exception, e:
-#         print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
+        theme.template_name = obj_type + '_request_email_subject.txt'
+        subject = render_to_string(theme.template, request)
+        subject = subject.replace('\n', '')
+
+        theme.template_name = 'email_default_sender.txt'
+        sender =  render_to_string(theme.template, request)
+        sender = sender.replace('\n', '')
+
+        msg = EmailMultiAlternatives(subject, text_content, sender, recipients)
+        msg.attach_alternative(html_content, "text/html")
+        msg.send()
+    except Exception, e:
+        print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
 
 
 #-------------------------------------------------------------------------------
@@ -1044,25 +1150,6 @@ def sfa_create_user(wsgi_request, request, namespace = None, as_admin = False):
 
     if not results:
         raise Exception, "Could not create %s. Already exists ?" % sfa_user_params['user_hrn']
-    else:
-        try:
-            theme.template_name = 'user_request_validated.txt'
-            text_content = render_to_string(theme.template, request)
-            theme.template_name = 'user_request_validated.html'
-            html_content = render_to_string(theme.template, request)
-        
-            theme.template_name = 'email_default_sender.txt'
-            sender =  render_to_string(theme.template, request)
-            sender = sender.replace('\n', '')
-
-
-            subject = 'User validated'
-
-            msg = EmailMultiAlternatives(subject, text_content, sender, [request['email']])
-            msg.attach_alternative(html_content, "text/html")
-            msg.send()
-        except Exception, e:
-            print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
 
     return results
 
@@ -1100,7 +1187,7 @@ def iotlab_create_user (wsgi_request, request, namespace = None, as_admin=False)
    
     iotlab_user_params1 = json.dumps(iotlab_user_params)
     r=requests.post(url=URL_REST, data=iotlab_user_params1, headers=headers, auth=auth)
-    print 'Create iotlab user : ', r.status_code, r.text
+    logger.info('Create iotlab user : {} {}'.format(r.status_code, r.text))
     return r.text
 
 def create_user(wsgi_request, request, namespace = None, as_admin = False):
@@ -1196,32 +1283,10 @@ def create_pending_user(wsgi_request, request, user_detail):
             'config'        : json.dumps(account_config),
         }
         manifold_add_account(wsgi_request, account_params)
-    except Exception, e:
-        print "Failed creating manifold account on platform %s for user: %s" % ('myslice', request['email'])
 
-    try:
-        # Send an email: the recipients are the PI of the authority
-        # If No PI is defined for this Authority, send to a default email (different for each theme)
-        recipients = authority_get_pi_emails(wsgi_request, request['authority_hrn'])
-        
-        theme.template_name = 'user_request_email.html'
-        html_content = render_to_string(theme.template, request)
-        theme.template_name = 'user_request_email.txt'
-        text_content = render_to_string(theme.template, request)
-    
-        theme.template_name = 'user_request_email_subject.txt'
-        subject = render_to_string(theme.template, request)
-        subject = subject.replace('\n', '')
-    
-        theme.template_name = 'email_default_sender.txt'
-        sender =  render_to_string(theme.template, request)
-        sender = sender.replace('\n', '')
-    
-        msg = EmailMultiAlternatives(subject, text_content, sender, recipients)
-        msg.attach_alternative(html_content, "text/html")
-        msg.send()
-    except Exception, e:
-        print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
-        import traceback
-        traceback.print_exc()
+    # Email to PIs is sent when the user activates his email
+    # portal/emailactivationview.py
+
+    except Exception as e:
+        logger.error("Failed creating manifold account on platform {} for user: {}".format('myslice', request['email']))
+
index 19cc1b9..f3899a0 100644 (file)
@@ -72,7 +72,7 @@ class ContactView (FreeAccessView, ThemeView):
                 username = None
             # log user activity
             activity.user.contact(self.request)
-            return render(request,'contact_sent.html', { 'theme' : self.theme,  'username': username}) # Redirect after POST
+            return render(request,'contact_sent.html', { 'theme' : self.theme,  'username': username, 'request':request}) # Redirect after POST
         else:
             return self._display (request, form)
 
@@ -82,23 +82,6 @@ class ContactView (FreeAccessView, ThemeView):
     def _display (self, request, form):
         if request.user.is_authenticated():
             username = request.user.email
-            ## check user is pi or not
-            platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
-            account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config')
-            platform_details = execute_query(self.request, platform_query)
-            account_details = execute_query(self.request, account_query)
-            for platform_detail in platform_details:
-                for account_detail in account_details:
-                    if platform_detail['platform_id'] == account_detail['platform_id']:
-                        if 'config' in account_detail and account_detail['config'] is not '':
-                            account_config = json.loads(account_detail['config'])
-                            if 'myslice' in platform_detail['platform']:
-                                acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
-            # assigning values
-            if acc_auth_cred == {} or acc_auth_cred == 'N/A':
-                pi = "is_not_pi"
-            else:
-                pi = "is_pi"
         else :
             username = None
             pi = "is_not_pi"
@@ -107,6 +90,6 @@ class ContactView (FreeAccessView, ThemeView):
                 'topmenu_items': topmenu_items('Contact', request),
                 'theme' : self.theme,
                 'username': username,
-                'pi': pi,
-                'section': "Contact"
+                'section': "Contact",
+                'request': request,
                 })
index 0de9b93..4beb7a9 100644 (file)
@@ -11,7 +11,9 @@ from unfold.loginrequired        import LoginRequiredAutoLogoutView
 
 from ui.topmenu                  import topmenu_items_live, the_user
 
-from myslice.theme import ThemeView
+from myslice.theme               import ThemeView
+from myslice.settings            import logger
+
 
 #This view requires login 
 class DashboardView (LoginRequiredAutoLogoutView, ThemeView):
@@ -25,7 +27,7 @@ class DashboardView (LoginRequiredAutoLogoutView, ThemeView):
         #messages.info(self.request, 'You have logged in')
         page = Page(self.request)
 
-        print "Dashboard page"
+        logger.info("Dashboard page")
         # Slow...
         #slice_query = Query().get('slice').filter_by('user.user_hrn', 'contains', user_hrn).select('slice_hrn')
         testbed_query  = Query().get('network').select('network_hrn','platform','version')
@@ -47,8 +49,8 @@ class DashboardView (LoginRequiredAutoLogoutView, ThemeView):
 #            root_authority = sub_authority[0]
 #            slice_query = Query().get(root_authority+':user').filter_by('user_hrn', '==', '$user_hrn').select('user_hrn', 'slice.slice_hrn')
 #        else:
-        print "SLICE QUERY"
-        print "-" * 80
+        logger.debug("SLICE QUERY")
+        logger.debug("-" * 80)
         slice_query = Query().get('myslice:user').filter_by('user_hrn', '==', '$user_hrn').select('slices.slice_hrn')
         page.enqueue_query(slice_query)
         page.enqueue_query(testbed_query)
index 4424c2e..79f2c0e 100644 (file)
@@ -1,22 +1,31 @@
-from unfold.loginrequired               import FreeAccessView
-#
-from manifold.core.query                import Query
-from manifoldapi.manifoldapi            import execute_query, execute_admin_query
-from portal.actions                     import manifold_update_user, manifold_update_account, manifold_add_account, manifold_delete_account, sfa_update_user, authority_get_pi_emails, make_request_user, create_user
-#
-from unfold.page                        import Page    
-from ui.topmenu                         import topmenu_items_live, the_user
-#
+import json
+import os
+import re
+import itertools
+
 from django.http                        import HttpResponse, HttpResponseRedirect
 from django.contrib                     import messages
 from django.contrib.auth.decorators     import login_required
-from myslice.theme                      import ThemeView
-from portal.models                      import PendingUser, PendingAuthority
 from django.core.mail                   import EmailMultiAlternatives, send_mail
 from django.contrib.sites.models        import Site
 
-#
-import json, os, re, itertools
+from manifold.core.query                import Query
+from manifoldapi.manifoldapi            import execute_query, execute_admin_query
+
+from unfold.loginrequired               import FreeAccessView
+
+from portal.actions                     import (
+    manifold_update_user, manifold_update_account, manifold_add_account,
+    manifold_delete_account, sfa_update_user, authority_get_pi_emails,
+    make_request_user, create_user, send_email_to_pis)
+from portal.models                      import PendingUser, PendingAuthority
+
+from unfold.page                        import Page    
+from ui.topmenu                         import topmenu_items_live, the_user
+
+from myslice.theme                      import ThemeView
+from myslice.settings                   import logger
+
 
 def ValuesQuerySetToDict(vqs):
     return [item for item in vqs]
@@ -36,8 +45,8 @@ class ActivateEmailView(FreeAccessView, ThemeView):
                 # User is enabled in PLE
                 if 'enabled' in result and result['enabled']==True:
                     return True
-        except Exception, e:
-            print "Exception in myplc query = ",e
+        except Exception as e:
+            logger.error("Exception in myplc query = {}".format(e))
 
         return False
 
@@ -50,12 +59,18 @@ class ActivateEmailView(FreeAccessView, ThemeView):
         #page.add_js_files  ( [ "js/jquery.validate.js", "js/my_account.register.js", "js/my_account.edit_profile.js" ] )
         #page.add_css_files ( [ "css/onelab.css", "css/account_view.css","css/plugin.css" ] )
 
+        # get the domain url
+        current_site = Site.objects.get_current()
+        current_site = current_site.domain
+
         for key, value in kwargs.iteritems():
-            #print "%s = %s" % (key, value)
             if key == "hash_code":
                 hash_code=value
+
         if PendingUser.objects.filter(email_hash__iexact = hash_code).filter(status__iexact = 'False'):           
             activation = 'success'
+            pending_users = PendingUser.objects.filter(email_hash__iexact = hash_code)
+            pending_user = pending_users[0]
 
             # AUTO VALIDATION of PLE enabled users (only for OneLab Portal)
             if self.theme == "onelab":
@@ -64,14 +79,11 @@ class ActivateEmailView(FreeAccessView, ThemeView):
                 # as we currently need to do a Resolve on each user_hrn of the Registry in order to get its email
                 # TODO in SFA XXX We need a Resolve based on email
                 # TODO maybe we can use MyPLC API for PLE
-                pending_users = PendingUser.objects.filter(email_hash__iexact = hash_code)
 
                 # by default user is not in PLE
                 ple_user_enabled = False
 
-                if pending_users:
-                    pending_user = pending_users[0]
-                    
+                if pending_user:
                     # Auto Validation 
                     if self.is_ple_enabled(pending_user):
                         pending_user_request = make_request_user(pending_user)
@@ -82,37 +94,22 @@ class ActivateEmailView(FreeAccessView, ThemeView):
 
                         # template user auto validated
                         activation = 'validated'
-
-                        # sending email after activation success
-                        #try:
-                        #    # Send an email: the recipient is the user
-                        #    recipients = pending_user_eamil 
-                        #    theme.template_name = 'user_request_email.html'
-                        #    html_content = render_to_string(theme.template, request)
-                        #    theme.template_name = 'user_request_email.txt'
-                        #    text_content = render_to_string(theme.template, request)
-                        #    theme.template_name = 'user_request_email_subject.txt'
-                        #    subject = render_to_string(theme.template, request)
-                        #    subject = subject.replace('\n', '')
-                        #    theme.template_name = 'email_default_sender.txt'
-                        #    sender =  render_to_string(theme.template, request)
-                        #    sender = sender.replace('\n', '')
-                        #    msg = EmailMultiAlternatives(subject, text_content, sender, recipients)
-                        #    msg.attach_alternative(html_content, "text/html")
-                        #    msg.send()
-                        #except Exception, e:
-                        #    print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
-                        #    import traceback
-                        #    traceback.print_exc()
             
             PendingUser.objects.filter(email_hash__iexact = hash_code).update(status='True')
+            u = {}
+            u['first_name']    =  pending_user.first_name   
+            u['last_name']     =  pending_user.last_name    
+            u['authority_hrn'] =  pending_user.authority_hrn
+            u['email']         =  pending_user.email        
+            u['user_hrn']      =  pending_user.user_hrn     
+            u['pi']            =  pending_user.pi           
+            u['public_key']    =  pending_user.public_key
+            u['current_site']  = current_site
+
+            send_email_to_pis(self.request, u, 'user')
         else:
             activation = 'failed'
         
-        # get the domain url
-        current_site = Site.objects.get_current()
-        current_site = current_site.domain
-
         
         context = super(ActivateEmailView, self).get_context_data(**kwargs)
         context['activation_status'] = activation
@@ -126,10 +123,8 @@ class ActivateEmailView(FreeAccessView, ThemeView):
         #context['first_name'] = first_name
         #context['last_name'] = last_name
         #context['authority_hrn'] = authority_hrn
-        #context['public_key'] = public_key
         #context['email'] = email
         #context['user_hrn'] = user_hrn
-        #context['current_site'] = current_site
         context['theme'] = self.theme
 #        context ['firstname'] = config['firstname']
         prelude_env = page.prelude_env()
index e5087d8..581822c 100644 (file)
@@ -21,8 +21,9 @@
 # this program; see the file COPYING.  If not, write to the Free Software
 # Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
+# TODO: Remove these automated forms and use html templates and views like any other page !
+
 from django import forms
-from portal.models import PendingUser, PendingSlice
 #from crispy_forms.helper import FormHelper
 #from crispy_forms.layout import Submit
 from django.utils.translation import ugettext_lazy as _
@@ -32,8 +33,12 @@ from django.contrib.sites.models import get_current_site
 from django.utils.http import int_to_base36
 from django.template import loader
 
-# TODO: Remove these automated forms and use html templates and views like any other page !
 from django.contrib.auth.hashers import identify_hasher
+
+from portal.models import PendingUser, PendingSlice
+
+from myslice.settings import logger
+
 # adapted from https://sourcegraph.com/github.com/fusionbox/django-authtools/symbols/python/authtools/forms
 
 def is_password_unusable(pw):
@@ -205,8 +210,8 @@ class PasswordResetForm(forms.Form):
                 subject = ''.join(subject.splitlines())
                 email = loader.render_to_string(email_template_name, c)
                 send_mail(subject, email, from_email, [user.email])
-        except Exception, e:
-            print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
+        except Exception as e:
+            logger.error("Failed to send email, please check the mail templates and the SMTP configuration of your server")
 
 
 class SetPasswordForm(forms.Form):
index 1fe1d2a..b417e09 100644 (file)
@@ -1,3 +1,6 @@
+import time
+import json
+
 # this somehow is not used anymore - should it not be ?
 from django.core.context_processors     import csrf
 from django.http                        import HttpResponseRedirect
@@ -6,30 +9,28 @@ from django.template                    import RequestContext
 from django.shortcuts                   import render_to_response
 from django.shortcuts                   import render
 
-
 from unfold.loginrequired               import FreeAccessView
+from ui.topmenu                         import topmenu_items, the_user
 
 from manifold.core.query                import Query
 from manifoldapi.manifoldapi            import execute_query
-
 from manifoldapi.manifoldresult         import ManifoldResult
-from ui.topmenu                         import topmenu_items, the_user
-from myslice.configengine               import ConfigEngine
 
+from myslice.configengine               import ConfigEngine
 from myslice.theme                      import ThemeView
+
 from portal.account                     import Account, get_expiration
 from portal.models                      import PendingSlice
-from portal.actions                     import authority_check_pis
+from portal.actions                     import authority_check_pis, get_jfed_identity, get_myslice_account
 
-import json, time
 import activity.user
 
 class HomeView (FreeAccessView, ThemeView):
     template_name = 'home-view.html'
-        
+
     # expose this so we can mention the backend URL on the welcome page
     def default_env (self):
-        return { 
+        return {
                  'MANIFOLD_URL':ConfigEngine().manifold_url(),
                  }
 
@@ -37,12 +38,12 @@ class HomeView (FreeAccessView, ThemeView):
         env = self.default_env()
         env['theme'] = self.theme
         env['section'] = "Dashboard"
-        
+
         username = request.POST.get('username')
         password = request.POST.get('password')
-        
+
         # pass request within the token, so manifold session key can be attached to the request session.
-        token = {'username': username, 'password': password, 'request': request}    
+        token = {'username': username, 'password': password, 'request': request}
 
         # our authenticate function returns either
         # . a ManifoldResult - when something has gone wrong, like e.g. backend is unreachable
@@ -55,189 +56,153 @@ class HomeView (FreeAccessView, ThemeView):
             manifoldresult = auth_result
             # let's use ManifoldResult.__repr__
             env['state']="%s"%manifoldresult
-            
-            return render_to_response(self.template,env, context_instance=RequestContext(request))
+
         # user was authenticated at the backend
         elif auth_result is not None:
             user=auth_result
-            if user.is_active:
-                print "LOGGING IN"
+            if user is not None and user.is_active:
                 login(request, user)
-                
-                if request.user.is_authenticated(): 
-                    env['person'] = self.request.user
-                    env['username'] = self.request.user
-                    
-                    # log user activity
-                    activity.user.login(self.request)
-                    
-                    ## check user is pi or not
-                    platform_details = {}
-                    account_details = {}
-                    acc_auth_cred = {}
-                    acc_user_cred = {}
-                    platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
-                    account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config')
-                    platform_details = execute_query(self.request, platform_query)
-                    account_details = execute_query(self.request, account_query)
-                    if platform_details is not None and platform_details != {}:
-                        for platform_detail in platform_details:
-                            for account_detail in account_details:
-                                if platform_detail['platform_id'] == account_detail['platform_id']:
-                                    if 'config' in account_detail and account_detail['config'] is not '':
-                                        account_config = json.loads(account_detail['config'])
-                                        if 'myslice' in platform_detail['platform']:
-                                            acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
-                                            acc_user_cred = account_config.get('delegated_user_credential','N/A')
-                    # assigning values
-                    #if acc_auth_cred=={} or acc_auth_cred=='N/A':
-                    #    pi = "is_not_pi"
-                    #else:
-                    #    pi = "is_pi"
-                    user_email = str(self.request.user)                   
-                    pi = authority_check_pis(self.request, user_email)
-
-                    # check if the user has creds or not
-                    if acc_user_cred == {} or acc_user_cred == 'N/A':
-                        user_cred = 'no_creds'
-                    else:
-                        exp_date = get_expiration(acc_user_cred, 'timestamp')
-                        if exp_date < time.time():
-                            user_cred = 'creds_expired'
-                        else:
-                            user_cred = 'has_creds'
 
-                    # list the pending slices of this user
-                    pending_slices = []
-                    for slices in PendingSlice.objects.filter(type_of_nodes__iexact=self.request.user).all():
-                        pending_slices.append(slices.slice_name)
-
-                    env['pending_slices'] = pending_slices
-                    env['pi'] = pi
-                    env['user_cred'] = user_cred                
-                else: 
+                if request.user.is_authenticated():
+                    try:
+                        env['person'] = self.request.user
+                        env['username'] = self.request.user
+
+                        # log user activity
+                        activity.user.login(self.request)
+
+                        ## check user is pi or not
+                        acc_auth_cred = {}
+                        acc_user_cred = {}
+
+                        account_detail = get_myslice_account(self.request)
+                        if 'config' in account_detail and account_detail['config'] is not '':
+                            account_config = json.loads(account_detail['config'])
+                            acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
+                            acc_user_cred = account_config.get('delegated_user_credential','N/A')
+                        # assigning values
+                        #if acc_auth_cred=={} or acc_auth_cred=='N/A':
+                        #    pi = "is_not_pi"
+                        #else:
+                        #    pi = "is_pi"
+                        user_email = str(self.request.user)
+                        #pi = authority_check_pis(self.request, user_email)
+
+                        # check if the user has creds or not
+                        if acc_user_cred == {} or acc_user_cred == 'N/A':
+                            user_cred = 'no_creds'
+                        else:
+                            exp_date = get_expiration(acc_user_cred, 'timestamp')
+                            if exp_date < time.time():
+                                user_cred = 'creds_expired'
+                            else:
+                                user_cred = 'has_creds'
+
+                        # list the pending slices of this user
+                        pending_slices = []
+                        for slices in PendingSlice.objects.filter(type_of_nodes__iexact=self.request.user).all():
+                            pending_slices.append(slices.slice_name)
+
+                        env['pending_slices'] = pending_slices
+                        #env['pi'] = pi
+                        env['user_cred'] = user_cred
+                    except Exception as e:
+                        print e
+                        env['person'] = None
+                        env['state'] = "Your session has expired"
+                else:
                     env['person'] = None
-                return render_to_response(self.template,env, context_instance=RequestContext(request))
             else:
                 # log user activity
                 activity.user.login(self.request, "notactive")
                 env['state'] = "Your account is not active, please contact the site admin."
                 env['layout_1_or_2']="layout-unfold2.html"
-                
-                return render_to_response(self.template,env, context_instance=RequestContext(request))
+
+            jfed_identity = get_jfed_identity(request)
+            if jfed_identity is not None:
+                import base64
+                encoded_jfed_identity = base64.b64encode(jfed_identity)
+                env['jfed_identity'] = encoded_jfed_identity 
+            else:
+                env['jfed_identity'] = None
+
         # otherwise
         else:
             # log user activity
             activity.user.login(self.request, "error")
             env['state'] = "Your username and/or password were incorrect."
-            
-            return render_to_response(self.template, env, context_instance=RequestContext(request))
+        env['request'] = request
+        return render_to_response(self.template,env, context_instance=RequestContext(request))
 
     def get (self, request, state=None):
         env = self.default_env()
         acc_auth_cred={}
-        if request.user.is_authenticated():
-           
-            ## check user is pi or not
-            platform_details = {}
-            account_details = {}
-            acc_auth_cred = {}
-            acc_user_cred = {}
-            platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
-            account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config')
-            # XXX Something like an invalid session seems to make the execute fail sometimes, and thus gives an error on the main page
-            platform_details = execute_query(self.request, platform_query)
-            account_details = execute_query(self.request, account_query)
-            if platform_details is not None and platform_details != {}:
-                for platform_detail in platform_details:
-                    for account_detail in account_details:
-                        if 'platform_id' in platform_detail:
-                            if platform_detail['platform_id'] == account_detail['platform_id']:
-                                if 'config' in account_detail and account_detail['config'] is not '':
-                                    account_config = json.loads(account_detail['config'])
-                                    if 'myslice' in platform_detail['platform']:
-                                        acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
-                                        acc_user_cred = account_config.get('delegated_user_credential','N/A')
-            # assigning values
-            #if acc_auth_cred=={} or acc_auth_cred=='N/A':
-            #    pi = "is_not_pi"
-            #else:
-            #    pi = "is_pi"
-            user_email = str(self.request.user) 
-            pi = authority_check_pis(self.request, user_email)
-            # check if the user has creds or not
-            if acc_user_cred == {} or acc_user_cred == 'N/A':
-                user_cred = 'no_creds'
-            else:
-                exp_date = get_expiration(acc_user_cred, 'timestamp')
-                if exp_date < time.time():
-                    user_cred = 'creds_expired'
+
+        try:
+            if request.user.is_authenticated():
+                jfed_identity = get_jfed_identity(request)
+                if jfed_identity is not None:
+                    import base64
+                    encoded_jfed_identity = base64.b64encode(jfed_identity)
+                    env['jfed_identity'] = encoded_jfed_identity 
+                else:
+                    env['jfed_identity'] = None
+
+                ## check user is pi or not
+                platform_details = {}
+                account_details = {}
+                acc_auth_cred = {}
+                acc_user_cred = {}
+                platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
+                account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config')
+                # XXX Something like an invalid session seems to make the execute fail sometimes, and thus gives an error on the main page
+
+                account_detail = get_myslice_account(self.request)
+                if 'config' in account_detail and account_detail['config'] is not '':
+                    account_config = json.loads(account_detail['config'])
+                    acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
+                    acc_user_cred = account_config.get('delegated_user_credential','N/A')
+                # assigning values
+                #if acc_auth_cred=={} or acc_auth_cred=='N/A':
+                #    pi = "is_not_pi"
+                #else:
+                #    pi = "is_pi"
+                user_email = str(self.request.user)
+                #pi = authority_check_pis(self.request, user_email)
+                # check if the user has creds or not
+                if acc_user_cred == {} or acc_user_cred == 'N/A':
+                    user_cred = 'no_creds'
                 else:
-                    user_cred = 'has_creds'
-
-            # list the pending slices of this user
-            pending_slices = []
-            for slices in PendingSlice.objects.filter(type_of_nodes__iexact=self.request.user).all():
-                pending_slices.append(slices.slice_name)
-        
-            env['pending_slices'] = pending_slices
-            env['pi'] = pi
-            env['user_cred'] = user_cred                
-            env['person'] = self.request.user
-        else: 
+                    exp_date = get_expiration(acc_user_cred, 'timestamp')
+                    if exp_date < time.time():
+                        user_cred = 'creds_expired'
+                    else:
+                        user_cred = 'has_creds'
+
+                # list the pending slices of this user
+                pending_slices = []
+                for slices in PendingSlice.objects.filter(type_of_nodes__iexact=self.request.user).all():
+                    pending_slices.append(slices.slice_name)
+
+                env['pending_slices'] = pending_slices
+                #env['pi'] = pi
+                env['user_cred'] = user_cred
+                env['person'] = self.request.user
+            else:
+                env['person'] = None
+        except Exception as e:
+            print e
             env['person'] = None
+            env['state'] = "Your session has expired"
 
         env['theme'] = self.theme
         env['section'] = "Dashboard"
 
-
         env['username']=the_user(request)
         env['topmenu_items'] = topmenu_items(None, request)
+        env['request'] = request
         if state: env['state'] = state
         elif not env['username']: env['state'] = None
         # use one or two columns for the layout - not logged in users will see the login prompt
-        
-#         account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config')
-#         account_details = execute_query(self.request, account_query)
-#         for account_detail in account_details:
-#             account_config = json.loads(account_detail['config'])
-#             platform_name = platform_detail['platform']
-#             if 'myslice' in platform_detail['platform']:
-#                 acc_user_cred = account_config.get('delegated_user_credential','N/A')
-#                 acc_slice_cred = account_config.get('delegated_slice_credentials','N/A')
-#                 acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
-# 
-#                 if 'N/A' not in acc_user_cred:
-#                     exp_date = re.search('<expires>(.*)</expires>', acc_user_cred)
-#                     if exp_date:
-#                         user_exp_date = exp_date.group(1)
-#                         user_cred_exp_list.append(user_exp_date)
-# 
-#                     my_users = [{'cred_exp': t[0]}
-#                         for t in zip(user_cred_exp_list)]
-#                
-# 
-#                 if 'N/A' not in acc_slice_cred:
-#                     for key, value in acc_slice_cred.iteritems():
-#                         slice_list.append(key)
-#                         # get cred_exp date
-#                         exp_date = re.search('<expires>(.*)</expires>', value)
-#                         if exp_date:
-#                             exp_date = exp_date.group(1)
-#                             slice_cred_exp_list.append(exp_date)
-# 
-#                     my_slices = [{'slice_name': t[0], 'cred_exp': t[1]}
-#                         for t in zip(slice_list, slice_cred_exp_list)]
-# 
-#                 if 'N/A' not in acc_auth_cred:
-#                     for key, value in acc_auth_cred.iteritems():
-#                         auth_list.append(key)
-#                         #get cred_exp date
-#                         exp_date = re.search('<expires>(.*)</expires>', value)
-#                         if exp_date:
-#                             exp_date = exp_date.group(1)
-#                             auth_cred_exp_list.append(exp_date)
-
-        
         return render_to_response(self.template, env, context_instance=RequestContext(request))
 
index 8a00435..f0a3b2d 100644 (file)
@@ -1,3 +1,5 @@
+import json
+
 from django.core.context_processors import csrf
 from django.http                    import HttpResponseRedirect
 from django.contrib.auth            import authenticate, login, logout
@@ -16,7 +18,8 @@ from myslice.configengine           import ConfigEngine
 
 from portal.actions                 import is_pi, authority_check_pis
 from myslice.theme                  import ThemeView
-import json
+from myslice.settings               import logger
+
 
 class InstitutionView (LoginRequiredAutoLogoutView, ThemeView):
     template_name = 'institution.html'
@@ -30,6 +33,7 @@ class InstitutionView (LoginRequiredAutoLogoutView, ThemeView):
     def post (self,request):
         env = self.default_env()
         env['theme'] = self.theme
+        env['request'] = request
         return render_to_response(self.template, env, context_instance=RequestContext(request))
 
     def get (self, request, authority_hrn=None, state=None):
@@ -66,12 +70,12 @@ class InstitutionView (LoginRequiredAutoLogoutView, ThemeView):
                 env['project'] = True
                 env['user_details'] = {'parent_authority': authority_hrn}
 
+            logger.debug("BEFORE  ####------####  is_pi")
+            logger.debug("is_pi = {}".format(is_pi))
+            pi = is_pi(self.request, '$user_hrn', env['user_details']['parent_authority']) 
         else: 
             env['person'] = None
-        print "BEFORE  ####------####  is_pi"
-        pi = is_pi(self.request, '$user_hrn', env['user_details']['parent_authority']) 
-        print "is_pi = ",is_pi
-
+            pi = False
         env['theme'] = self.theme
         env['section'] = "Institution"
         env['pi'] = pi 
@@ -82,6 +86,6 @@ class InstitutionView (LoginRequiredAutoLogoutView, ThemeView):
         # use one or two columns for the layout - not logged in users will see the login prompt
         env['layout_1_or_2']="layout-unfold2.html" if not env['username'] else "layout-unfold1.html"
         
-        
+        env['request'] = request
         return render_to_response(self.template, env, context_instance=RequestContext(request))
 
index 2add3a4..6f0d77c 100644 (file)
@@ -22,6 +22,7 @@ from portal.models              import PendingUser,PendingAuthority
 from portal.actions             import authority_get_pi_emails, manifold_add_user,manifold_add_account, create_pending_user
 
 from myslice.theme import ThemeView
+from myslice.settings import logger
 
 import activity.institution
 
@@ -229,9 +230,9 @@ class JoinView (FreeAccessView, ThemeView):
                     msg.send()
     
                 except Exception, e:
-                    print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
+                    logger.error("Failed to send email, please check the mail templates and the SMTP configuration of your server")
                     import traceback
-                    traceback.print_exc()
+                    logger.error(traceback.format_exc())
 
                 self.template_name = 'join_complete.html'
                 # log institution activity
index ec39f8f..02714d4 100644 (file)
@@ -1,3 +1,4 @@
+import json
 # this somehow is not used anymore - should it not be ?
 from django.core.context_processors import csrf
 from django.http import HttpResponseRedirect
@@ -11,10 +12,10 @@ from unfold.loginrequired import FreeAccessView
 from manifold.core.query            import Query
 from manifoldapi.manifoldapi        import execute_query
 from manifoldapi.manifoldresult import ManifoldResult
-from myslice.configengine import ConfigEngine
 
+from myslice.configengine import ConfigEngine
 from myslice.theme import ThemeView
-import json
+from myslice.settings import logger
 
 class ManagementAboutView (FreeAccessView, ThemeView):
     template_name = 'management-tab-about.html'
@@ -27,7 +28,7 @@ class ManagementAboutView (FreeAccessView, ThemeView):
             user_local_query  = Query().get('local:user').select('config').filter_by('email','==',str(self.request.user))
             user_local_details = execute_query(self.request, user_local_query)
             user_authority = json.loads(user_local_details[0]['config']).get('authority')
-            print "**************________    management about  = ",user_authority
+            logger.info("**************________    management about  = {}".format(user_authority))
             # XXX Should be done using Metadata
             # select column.name from local:object where table=='authority'
             authority_query = Query().get('authority').select('authority_hrn', 'name', 'address', 'enabled','description', 
index 2c80e41..2d1cdef 100644 (file)
@@ -1,3 +1,5 @@
+import json
+
 from django.template                 import RequestContext
 from django.shortcuts                import render_to_response
 
@@ -18,8 +20,7 @@ from manifoldapi.manifoldapi        import execute_query
 from portal.actions                 import get_requests
 
 from myslice.theme import ThemeView
-
-import json
+from myslice.settings import logger
 
 class ManagementRequestsView (LoginRequiredView, ThemeView):
     template_name = "management-tab-requests.html"
@@ -47,7 +48,7 @@ class ManagementRequestsView (LoginRequiredView, ThemeView):
             sfa_platforms_query = Query().get('local:platform').filter_by('gateway_type', '==', 'sfa').select('platform_id', 'platform', 'auth_type')
             sfa_platforms = execute_query(self.request, sfa_platforms_query)
             for sfa_platform in sfa_platforms:
-                print "SFA PLATFORM > ", sfa_platform['platform']
+                logger.info("SFA PLATFORM > {}".format(sfa_platform['platform']))
                 if not 'auth_type' in sfa_platform:
                     continue
                 auth = sfa_platform['auth_type']
@@ -55,7 +56,7 @@ class ManagementRequestsView (LoginRequiredView, ThemeView):
                     all_authorities.append(auth)
                 platform_ids.append(sfa_platform['platform_id'])
 
-            print "W: Hardcoding platform myslice"
+            logger.warning("W: Hardcoding platform myslice")
             # There has been a tweak on how new platforms are referencing a
             # so-called 'myslice' platform for storing authentication tokens.
             # XXX This has to be removed in final versions.
@@ -101,8 +102,8 @@ class ManagementRequestsView (LoginRequiredView, ThemeView):
             try:
                 for pa in pi_authorities_tmp:
                     pi_authorities |= set(pa['pi_authorities'])
-            except:
-                print 'No pi_authorities'
+            except Exception as e:
+                logger.error('No pi_authorities')
 
             pi_credential_authorities = pi_authorities & credential_authorities
             pi_no_credential_authorities = pi_authorities - credential_authorities - credential_authorities_expired
index 1be4e82..47e6974 100644 (file)
@@ -1,19 +1,24 @@
+import os
+import re
+import itertools
+import json
+
 from unfold.loginrequired               import LoginRequiredAutoLogoutView
-#
+
 from manifold.core.query                import Query
 from manifoldapi.manifoldapi            import execute_query, execute_admin_query
 from portal.actions                     import manifold_update_user, manifold_update_account, manifold_add_account, manifold_delete_account
-from portal.actions                     import sfa_update_user, authority_get_pis, authority_add_pis, authority_remove_pis,authority_check_pis ,clear_user_creds
-#
+from portal.actions                     import (
+    sfa_update_user, authority_get_pis, authority_add_pis,
+    authority_remove_pis,authority_check_pis ,clear_user_creds )
+
 from unfold.page                        import Page    
 from ui.topmenu                         import topmenu_items_live, the_user
-#
+
 from django.http                        import HttpResponse, HttpResponseRedirect
 from django.contrib                     import messages
 from django.contrib.auth.decorators     import login_required
 from myslice.theme import ThemeView
-#
-import json, os, re, itertools
 
 # requires login
 class UserView(LoginRequiredAutoLogoutView, ThemeView):
@@ -29,7 +34,6 @@ class UserView(LoginRequiredAutoLogoutView, ThemeView):
         page.add_css_files ( [ "css/onelab.css", "css/account_view.css","css/plugin.css","css/jquery-ui.css" ] )
 
         for key, value in kwargs.iteritems():
-            #print "%s = %s" % (key, value)
             if key == "email":
                 selected_email=value
     
index f578d93..9ffff60 100644 (file)
@@ -33,11 +33,11 @@ from django.template.loader   import render_to_string
 
 #from django.core.validators import validate_email
 
-try:
-    from django.contrib.auth import get_user_model
-    User = get_user_model()
-except ImportError:
-    from django.contrib.auth.models import User
+#try:
+#    from django.contrib.auth import get_user_model
+#    User = get_user_model()
+#except ImportError:
+#    from django.contrib.auth.models import User
 
 try:
     from django.utils.timezone import now as datetime_now
diff --git a/portal/native_migrations/0001_initial.py b/portal/native_migrations/0001_initial.py
new file mode 100644 (file)
index 0000000..d307a59
--- /dev/null
@@ -0,0 +1,114 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Institution',
+            fields=[
+                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                ('name', models.TextField()),
+            ],
+            options={
+            },
+            bases=(models.Model,),
+        ),
+        migrations.CreateModel(
+            name='PendingAuthority',
+            fields=[
+                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                ('site_name', models.TextField()),
+                ('site_authority', models.TextField()),
+                ('site_abbreviated_name', models.TextField()),
+                ('site_url', models.TextField()),
+                ('site_latitude', models.TextField()),
+                ('site_longitude', models.TextField()),
+                ('address_line1', models.TextField()),
+                ('address_line2', models.TextField()),
+                ('address_line3', models.TextField()),
+                ('address_city', models.TextField()),
+                ('address_postalcode', models.TextField()),
+                ('address_state', models.TextField()),
+                ('address_country', models.TextField()),
+                ('authority_hrn', models.TextField()),
+                ('created', models.DateTimeField(auto_now_add=True)),
+            ],
+            options={
+            },
+            bases=(models.Model,),
+        ),
+        migrations.CreateModel(
+            name='PendingJoin',
+            fields=[
+                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                ('user_hrn', models.TextField()),
+                ('email', models.TextField()),
+                ('project_name', models.TextField(null=True)),
+                ('authority_hrn', models.TextField()),
+                ('created', models.DateTimeField(auto_now_add=True)),
+            ],
+            options={
+            },
+            bases=(models.Model,),
+        ),
+        migrations.CreateModel(
+            name='PendingProject',
+            fields=[
+                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                ('project_name', models.TextField()),
+                ('user_hrn', models.TextField()),
+                ('email', models.TextField()),
+                ('authority_hrn', models.TextField(null=True)),
+                ('purpose', models.TextField(default=b'NA')),
+                ('created', models.DateTimeField(auto_now_add=True)),
+            ],
+            options={
+            },
+            bases=(models.Model,),
+        ),
+        migrations.CreateModel(
+            name='PendingSlice',
+            fields=[
+                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                ('slice_name', models.TextField()),
+                ('user_hrn', models.TextField()),
+                ('authority_hrn', models.TextField(null=True)),
+                ('number_of_nodes', models.TextField(default=0)),
+                ('type_of_nodes', models.TextField(default=b'NA')),
+                ('purpose', models.TextField(default=b'NA')),
+                ('created', models.DateTimeField(auto_now_add=True)),
+            ],
+            options={
+            },
+            bases=(models.Model,),
+        ),
+        migrations.CreateModel(
+            name='PendingUser',
+            fields=[
+                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                ('first_name', models.TextField()),
+                ('last_name', models.TextField()),
+                ('email', models.EmailField(max_length=75)),
+                ('password', models.TextField()),
+                ('user_hrn', models.TextField()),
+                ('public_key', models.TextField()),
+                ('private_key', models.TextField()),
+                ('authority_hrn', models.TextField()),
+                ('login', models.TextField()),
+                ('pi', models.TextField()),
+                ('email_hash', models.TextField()),
+                ('status', models.TextField()),
+                ('created', models.DateTimeField(auto_now_add=True)),
+            ],
+            options={
+            },
+            bases=(models.Model,),
+        ),
+    ]
diff --git a/portal/native_migrations/__init__.py b/portal/native_migrations/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
index b0fc3ec..ec5454d 100644 (file)
@@ -16,6 +16,7 @@ from plugins.querytable          import QueryTable
 
 from myslice.configengine        import ConfigEngine
 from myslice.theme import ThemeView
+from myslice.settings import logger
 
 # View for 1 platform and its details
 class PlatformView(FreeAccessView, ThemeView):
@@ -26,7 +27,7 @@ class PlatformView(FreeAccessView, ThemeView):
         page.add_js_files  ( [ "js/common.functions.js" ] )
 
         for key, value in kwargs.iteritems():
-            print "%s = %s" % (key, value)       
+            logger.debug("{} = {}".format(key, value))
             if key == "platformname":
                 platformname=value
                 
index 8a48428..69941b3 100644 (file)
@@ -1,3 +1,7 @@
+import json
+import time
+import re
+
 from django.shortcuts           import render
 from django.contrib.sites.models import Site
 
@@ -10,18 +14,23 @@ from portal.actions import create_pending_project, create_pending_join, sfa_add_
 from portal.models import PendingProject, PendingJoin
 
 from myslice.theme import ThemeView
-
-import json, time, re
+from myslice.settings import logger
 
 class ProjectRequestView(LoginRequiredAutoLogoutView, ThemeView):
     template_name = 'projectrequest_view.html'
     
     def getAuthorities(self, request):
-        authorities_query = Query.get('authority').select('name', 'authority_hrn')
+        if self.theme == 'fed4fire':
+            authorities_query = Query.get('myslice:authority').select('authority_hrn')
+        else:
+            authorities_query = Query.get('authority').select('name', 'authority_hrn')
         authorities = execute_admin_query(request, authorities_query)
         if authorities is not None:
-            authorities = sorted(authorities, key=lambda k: k['authority_hrn'])
-            authorities = sorted(authorities, key=lambda k: k['name'])
+            # Remove the root authority from the list
+            matching = [s for s in authorities if "." in s['authority_hrn']]
+            authorities = sorted(matching, key=lambda k: k['authority_hrn'])
+            if self.theme != 'fed4fire':
+                authorities = sorted(matching, key=lambda k: k['name'])
         return authorities
     
     def getUserAuthority(self, request):
@@ -82,18 +91,25 @@ class ProjectRequestView(LoginRequiredAutoLogoutView, ThemeView):
         user_authority = self.getUserAuthority(wsgi_request)
         
         # getting the org from authority
-        for authority in authorities:
-            if authority['authority_hrn'] == user_authority:
-                authority_name = authority['name']
+        #for authority in authorities:
+        #    if authority['authority_hrn'] == user_authority:
+        #        authority_name = authority['name']
         
         if method == 'POST' :
-        
+
+            project_name = wsgi_request.POST.get('project_name', '')
+            if not project_name or len(project_name) == 0 :
+                errors.append('Project name can\'t be empty')
+
+            # accept only lowercase names
+            project_name = project_name.lower()
+
             if 'join' in wsgi_request.POST:
                 post = {
                     'user_hrn'          : user_hrn,
                     'email'             : user_email,
-                    'project_name'      : wsgi_request.POST.get('project_name', ''),
-                    'authority_hrn'     : wsgi_request.POST.get('project_name', ''),
+                    'project_name'      : project_name,
+                    'authority_hrn'     : project_name,
                 }
 
             else:
@@ -101,30 +117,36 @@ class ProjectRequestView(LoginRequiredAutoLogoutView, ThemeView):
                     'user_hrn'          : user_hrn,
                     'email'             : user_email,
                     'authority_hrn'     : wsgi_request.POST.get('authority_name', ''),
-                    'project_name'      : wsgi_request.POST.get('project_name', ''),
+                    'project_name'      : project_name,
                     'purpose'           : wsgi_request.POST.get('purpose', ''),
                 }
 
-                if (post['authority_hrn'] is None or post['authority_hrn'] == ''):
-                    errors.append('Organization is mandatory')
+                # for new projects max project_name length is 10
+                if (len(post['project_name']) >10):
+                    errors.append('Project name can be maximum 10 characters long')
+
+                #if (post['authority_hrn'] is None or post['authority_hrn'] == ''):
+                #    errors.append('Organization is mandatory')
     
-                if (post['purpose'] is None or post['purpose'] == ''):
+                if post['purpose'] is None or post['purpose'] == '':
                     errors.append('Project purpose is mandatory')
 
-                if (re.search(r'^[A-Za-z0-9_]*$', post['project_name']) == None):
+                if re.search(r'^[A-Za-z0-9_]*$', post['project_name']) is None:
                     errors.append('Project name may contain only letters, numbers, and underscore.')
 
             # What kind of project name is valid?
-            if (post['project_name'] is None or post['project_name'] == ''):
-                errors.append('Project name is mandatory')
+            if post['project_name'] is None or post['project_name'] == '':
+                errors.append('Project name is mandatory')   
             
             if not errors:
-                print "is_pi on auth_hrn = ", user_authority
+                logger.info("is_pi on auth_hrn = {}".format(user_authority))
                 if is_pi(wsgi_request, user_hrn, user_authority):
                     # PIs can directly create/join project in their own authority...
                     if 'join' in wsgi_request.POST:
+                        # join existing project
                         authority_add_pis(wsgi_request, post['project_name'], user_hrn)
                     else:
+                        # Create project
                         hrn = post['authority_hrn'] + '.' + post['project_name']
                         sfa_add_authority(wsgi_request, {'authority_hrn':hrn})
                         authority_add_pis(wsgi_request, hrn, user_hrn)
@@ -154,167 +176,3 @@ class ProjectRequestView(LoginRequiredAutoLogoutView, ThemeView):
                'pending_join_projects': pending_join_projects,
         }
         return render(wsgi_request, self.template, env)
-    
-        
-    
-        """
-        """
-        errors = []
-        slice_name =''
-        purpose=''
-        url=''
-        authority_hrn = None
-        authority_name = None
-        # Retrieve the list of authorities
-        authorities_query = Query.get('authority').select('name', 'authority_hrn')
-        authorities = execute_admin_query(wsgi_request, authorities_query)
-        if authorities is not None:
-            authorities = sorted(authorities, key=lambda k: k['authority_hrn'])
-            authorities = sorted(authorities, key=lambda k: k['name'])
-
-        # Get user_email (XXX Would deserve to be simplified)
-        user_query  = Query().get('local:user').select('email','config')
-        user_details = execute_query(wsgi_request, user_query)
-        user_email = user_details[0].get('email')
-        # getting user_hrn
-        for user_detail in user_details:
-            user_config = json.loads(user_detail['config'])
-            user_authority = user_config.get('authority','N/A')              
-        # getting the org from authority        
-        for authority in authorities:
-            if authority['authority_hrn'] == user_authority:
-                authority_name = authority['name']
-
-        # Handle the case when we use only hrn and not name
-        if authority_name is None:
-            authority_name = user_authority
-        #
-        account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config')
-        account_details = execute_query(wsgi_request, account_query)
-        #
-        platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
-        platform_details = execute_query(wsgi_request, platform_query)
-        
-        user_hrn = None
-        # getting user_hrn from local:account
-        for account_detail in account_details:
-            for platform_detail in platform_details:
-                if platform_detail['platform_id'] == account_detail['platform_id']:
-                    # taking user_hrn only from myslice account
-                    # NOTE: we should later handle accounts filter_by auth_type= managed OR user
-                    if 'myslice' in platform_detail['platform']:
-                        account_config = json.loads(account_detail['config'])
-                        user_hrn = account_config.get('user_hrn','N/A')
-                        acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
-
-
-        # checking if pi or not
-        if acc_auth_cred == {} or acc_auth_cred == 'N/A':
-            pi = "is_not_pi"
-        else:
-            pi = "is_pi"
-
-
-        # Page rendering
-#         page = Page(wsgi_request)
-#         page.add_js_files  ( [ "js/jquery.validate.js", "js/jquery-ui.js" ] )
-#         page.add_css_files ( [ "https://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" ] )
-#         page.expose_js_metadata()
-
-        if method == 'POST':
-            # The form has been submitted
-
-            # get the domain url
-#             current_site = Site.objects.get_current()
-#             current_site = current_site.domain
-            
-            # getting the authority_hrn from the selected organization
-            for authority in authorities:
-                if authority['name'] == wsgi_request.POST.get('org_name', ''):
-                    authority_hrn = authority['authority_hrn']
-
-            # Handle the case when we use only hrn and not name
-            if authority_hrn is None:
-                authority_hrn = wsgi_request.POST.get('org_name', '')
-
-            slice_request = {
-                'type'              : 'slice',
-                'id'                : None,
-                'user_hrn'          : user_hrn,
-                'email'             : user_email,
-                'timestamp'         : time.time(),
-                'authority_hrn'     : authority_hrn,
-                'organization'      : wsgi_request.POST.get('org_name', ''),
-                'slice_name'        : wsgi_request.POST.get('slice_name', ''),
-                'url'               : wsgi_request.POST.get('url', ''),
-                'purpose'           : wsgi_request.POST.get('purpose', ''),
-                'current_site'      : current_site
-            }
-            
-            # create slice_hrn based on authority_hrn and slice_name
-#             slice_name = slice_request['slice_name']
-            req_slice_hrn = authority_hrn + '.' + slice_name
-            # comparing requested slice_hrn with the existing slice_hrn 
-            slice_query  = Query().get('myslice:slice').select('slice_hrn','parent_authority').filter_by('parent_authority','==',authority_hrn)
-            slice_details_sfa = execute_admin_query(wsgi_request, slice_query)
-            for _slice in slice_details_sfa:
-                if _slice['slice_hrn'] == req_slice_hrn:
-                    errors.append('Slice already exists. Please use a different slice name.')
-            
-
-            # What kind of slice name is valid?
-            if (slice_name is None or slice_name == ''):
-                errors.append('Slice name is mandatory')
-            
-            if (re.search(r'^[A-Za-z0-9_]*$', slice_name) == None):
-                errors.append('Slice name may contain only letters, numbers, and underscore.')
-            
-            organization = slice_request['organization']    
-            if (organization is None or organization == ''):
-                errors.append('Organization is mandatory')
-
-
-    
-            purpose = slice_request['purpose']
-            if (purpose is None or purpose == ''):
-                errors.append('Experiment purpose is mandatory')
-
-            url = slice_request['url']
-
-            if not errors:
-                if is_pi(wsgi_request, user_hrn, authority_hrn):
-                    # PIs can directly create slices in their own authority...
-                    create_slice(wsgi_request, slice_request)
-                    clear_user_creds(wsgi_request, user_email)
-                    self.template_name = 'slice-request-done-view.html'
-                else:
-                    # Otherwise a wsgi_request is sent to the PI
-                    create_pending_slice(wsgi_request, slice_request, user_email)
-                    self.template_name = 'slice-request-ack-view.html'
-                
-                # log user activity
-                activity.user.slice(wsgi_request)
-                
-                return render(wsgi_request, self.template, {'theme': self.theme}) # Redirect after POST
-        else:
-            slice_request = {}
-
-        template_env = {
-            'username': wsgi_request.user.email,
-            'errors': errors,
-            'slice_name': slice_name,
-            'purpose': purpose,
-            'email': user_email,
-            'user_hrn': user_hrn,
-            'url': url,
-            'pi': pi,
-            'authority_name': authority_name,        
-            'authority_hrn': user_authority,        
-            'cc_myself': True,
-            'authorities': authorities,
-            'theme': self.theme,
-            'section': "Slice request"
-        }
-        template_env.update(slice_request)
-        template_env.update(page.prelude_env())
-        return render(wsgi_request, self.template, template_env)
index 2ce1efa..9032125 100644 (file)
@@ -1,4 +1,5 @@
-import os.path, re
+import os.path
+import re
 import json
 from random     import randint
 from hashlib    import md5
@@ -21,6 +22,7 @@ from portal.models              import PendingUser
 from portal.actions             import create_pending_user
 
 from myslice.theme import ThemeView
+from myslice.settings import logger
 
 import activity.user
 
@@ -44,14 +46,14 @@ class RegistrationView (FreeAccessView, ThemeView):
         # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
         authorities_query = Query.get('authority').select('name', 'authority_hrn')
         authorities = execute_admin_query(wsgi_request, authorities_query)
-        print "RegistrationView authorities = ", authorities
+        logger.info("RegistrationView authorities = {}".format(authorities))
         if authorities is not None:
             # Remove the root authority from the list
             matching = [s for s in authorities if "." in s['authority_hrn']]
             authorities = sorted(matching, key=lambda k: k['authority_hrn'])
             authorities = sorted(matching, key=lambda k: k['name'])
         
-        print "############ BREAKPOINT 1 #################"
+        logger.debug("############ BREAKPOINT 1 #################")
         # Page rendering
         page = Page(wsgi_request)
 
@@ -61,7 +63,7 @@ class RegistrationView (FreeAccessView, ThemeView):
 
         page.add_css_files ( [ "css/onelab.css", "css/registration.css", "css/jquery.qtip.min.css", "css/jquery.ui.combobox.css" ] )
         page.expose_js_metadata()
-        print "############ BREAKPOINT 2 #################"
+        logger.debug("############ BREAKPOINT 2 #################")
         if method == 'POST':
             reg_form = {}
             # The form has been submitted
@@ -70,7 +72,7 @@ class RegistrationView (FreeAccessView, ThemeView):
             current_site = Site.objects.get_current()
             current_site = current_site.domain
            
-            print "############ BREAKPOINT 3 #################"
+            logger.debug("############ BREAKPOINT 3 #################")
             post_email = wsgi_request.POST.get('email','').lower()
             salt = randint(1,100000)
             email_hash = md5(str(salt)+post_email).hexdigest()
@@ -87,13 +89,13 @@ class RegistrationView (FreeAccessView, ThemeView):
                 'validation_link': current_site + '/portal/email_activation/'+ email_hash
             }
 
-            print "############ BREAKPOINT 4 #################"
+            logger.debug("############ BREAKPOINT 4 #################")
             auth = wsgi_request.POST.get('org_name', None)
             if auth is None or auth == "":
                 errors.append('Organization required: please select one or request its addition')
             else:
                
-                print "############ BREAKPOINT 5 #################"
+                logger.debug("############ BREAKPOINT 5 #################")
                 
                 # Construct user_hrn from email (XXX Should use common code)
                 split_email = user_request['email'].split("@")[0] 
@@ -183,7 +185,7 @@ class RegistrationView (FreeAccessView, ThemeView):
                     return render(wsgi_request, self.template, {'theme': self.theme}) 
 
         else:
-            print "############ BREAKPOINT A #################"
+            logger.debug("############ BREAKPOINT A #################")
             user_request = {}
             ## this is coming from onelab website onelab.eu
             reg_form = {
@@ -193,7 +195,7 @@ class RegistrationView (FreeAccessView, ThemeView):
                 }
             # log user activity
             activity.user.signup(self.request)
-            print "############ BREAKPOINT B #################"
+            logger.debug("############ BREAKPOINT B #################")
 
         template_env = {
           #'topmenu_items': topmenu_items_live('Register', page),
@@ -204,5 +206,5 @@ class RegistrationView (FreeAccessView, ThemeView):
         template_env.update(user_request)
         template_env.update(reg_form)
         template_env.update(page.prelude_env ())
-        print "############ BREAKPOINT C #################"
+        logger.debug("############ BREAKPOINT C #################")
         return render(wsgi_request, self.template,template_env)
index f160d7d..a08ad46 100644 (file)
-from django.contrib.auth        import authenticate, login, logout\r
-from django.template            import RequestContext\r
-from django.shortcuts           import render, render_to_response\r
-\r
-from manifoldapi.manifoldresult import ManifoldResult\r
-from ui.topmenu                 import topmenu_items, the_user\r
-from myslice.configengine       import ConfigEngine\r
-from manifold.core.query        import Query\r
-from unfold.page                import Page\r
-from manifoldapi.manifoldapi    import execute_admin_query, execute_query\r
-from unfold.loginrequired       import LoginRequiredAutoLogoutView\r
-\r
-from myslice.theme import ThemeView\r
-import json\r
-import hashlib\r
-import datetime\r
-import urllib2\r
-import ast\r
-import time\r
-\r
-from django.views.decorators.csrf import csrf_exempt\r
-from django.http                  import *\r
-\r
-\r
-def response_mimetype(request):\r
-        \r
-    if "application/json" in request.META['HTTP_ACCEPT']:\r
-        return "application/json"\r
-    else:\r
-        return "text/plain"\r
-    \r
-\r
-def json_to_rest(url, data ):\r
-        \r
-    req = urllib2.Request(url)\r
-    req.add_header('Content-Type', 'application/json')\r
-    response = urllib2.urlopen(req, json.dumps(data))\r
-    \r
-    if data == "a":\r
-        mylist = ast.literal_eval(response.read())\r
-    else:\r
-        mylist = response.read().translate(None, '"[]').split(",")\r
-        \r
-    return (mylist)\r
-\r
-\r
-def unix_to_timestamp(timest):\r
-    try:\r
-        return datetime.datetime.fromtimestamp(int(timest)).strftime('%Y-%m-%d %H:%M:%S')\r
-    except:\r
-        return timest\r
-\r
-def timestamp_to_unix(timest):\r
-    try:\r
-        pass\r
-    except:\r
-        pass\r
-    \r
-    \r
-def slice_to_exp(slices_users):\r
-    experiments = {}\r
-    testbeds = {}\r
-    wildcard_testbeds = {}\r
-   \r
-    \r
-    for slice in slices_users:  \r
-        nodes={}\r
-        leases = slice['lease']\r
-         \r
-        if leases is not None and leases:\r
-            for lease in leases:\r
-                resource = lease['resource']\r
-                start_t = lease['start_time']\r
-                end_t = lease['end_time']\r
-                \r
-                testbed_start = resource.index('IDN+')+4\r
-                testbed_end = resource.index('+node+')\r
-                \r
-                testbed = resource[testbed_start:testbed_end]\r
-                node = resource[testbed_end+6:]\r
-                if 'omf:nitos' in testbed:\r
-                    testbed = 'omf:nitos'\r
-                if testbed in testbeds:\r
-                    if node not in testbeds[testbed]:\r
-                        testbeds[testbed].append(node)\r
-                else:\r
-                    testbeds[testbed] = [node]\r
-                \r
-                #group nodes in consecutive timeslots\r
-                if not node in nodes:       \r
-                    nodes[node]={str(start_t):{'start_t':start_t, 'nodes':node, 'end_t':end_t}}\r
-                else:\r
-                    if not str(start_t) in nodes[node]:\r
-                        f=0\r
-                        for n in nodes[node]:\r
-                            if n[str(end_t)] == start_t:\r
-                                n[str(end_t)] == end_t\r
-                                f=1\r
-                        if f==0:\r
-                            nodes[node][str(start_t)]={'start_t':start_t, 'nodes':node, 'end_t':end_t}\r
-\r
-            ######### FOR PLE LIKE start ##################\r
-            for resource in slice['resource']:\r
-                testbed_start = resource.index('IDN+')+4\r
-                testbed_end = resource.index('+node+')\r
-                tb = resource[testbed_start:testbed_end]\r
-                node = resource[testbed_end+6:]\r
-                if 'ple:' in tb:\r
-                    tb = 'ple'\r
-                if 'omf:nitos' in tb:\r
-                    tb = 'omf:nitos'\r
-                if tb not in testbeds:\r
-                    try:\r
-                        if node not in wildcard_testbeds[slice['slice_hrn']][tb]:\r
-                            wildcard_testbeds[slice['slice_hrn']][tb].append([node])\r
-                    except:\r
-                        try:\r
-                            wildcard_testbeds[slice['slice_hrn']][tb] = [node]\r
-                        except:\r
-                            wildcard_testbeds[slice['slice_hrn']]={tb:[node]}\r
-                    \r
-            \r
-        else:\r
-            s = slice['slice_last_updated']\r
-            #s_time = int(time.mktime(datetime.datetime.strptime(s, "%Y%m%dT%H:%M:%Ss").timetuple()))\r
-            s_time = time.mktime(s.timetuple())                \r
-                \r
-            if slice['resource'] is not None:\r
-                                    \r
-                for resource in slice['resource']:\r
-                    testbed_start = resource.index('IDN+')+4\r
-                    testbed_end = resource.index('+node+')\r
-                    tb = resource[testbed_start:testbed_end]\r
-                    if 'ple:' in tb:\r
-                        tb = 'ple'\r
-                    if 'omf:nitos' in tb:\r
-                        tb = 'omf:nitos'\r
-                    node = resource[testbed_end+6:]\r
-                    \r
-                    if testbed in testbeds:\r
-                        if node not in testbeds[testbed]:\r
-                            testbeds[testbed].append(node)\r
-                    else:\r
-                        testbeds[testbed] = [node]       \r
-                    \r
-                    if not node in nodes:  \r
-                        #nodes[node] = {str(start_t):{'start_t':s_time, 'nodes':node, 'end_t':int(time.time())}} \r
-                        nodes[node] = {str(start_t):{'start_t':s_time, 'nodes':node, 'end_t':s_time}}    \r
-            ######### FOR PLE LIKE end ##################\r
\r
-                        \r
-        #group grouped nodes in experiments\r
-        for n in nodes:\r
-            for exp in nodes[n]:\r
-                key = str(exp) + str(nodes[n][exp]['end_t']) + slice['slice_hrn']\r
-                \r
-                if key not in experiments:\r
-                    experiments[key]={'slice_hrn':slice['slice_hrn'], \\r
-                                      'start':nodes[n][exp]['start_t'], 'end':nodes[n][exp]['end_t'], 'nodes':[nodes[n][exp]['nodes']]}   \r
-                    \r
-                    \r
-                    ######### FOR PLE LIKE start ##################\r
-                    for item in wildcard_testbeds:\r
-                        if item == experiments[key]['slice_hrn']:\r
-                            for testbed in wildcard_testbeds[item]:\r
-                                \r
-                                if testbed not in testbeds:\r
-                                    testbeds[testbed] = wildcard_testbeds[item][testbed] \r
-                                \r
-                                for n in wildcard_testbeds[item][testbed]:\r
-                                    if n not in experiments[key]['nodes']:\r
-                                        experiments[key]['nodes'].append(n)                                           \r
-                    ######### FOR PLE LIKE end ##################\r
-                    \r
-                elif nodes[n][exp]['end_t'] == experiments[key]['end']:\r
-                    experiments[key]['nodes'].append(nodes[n][exp]['nodes'])\r
-                    \r
-                    \r
-                    ######### FOR PLE LIKE start ##################\r
-                    for item in wildcard_testbeds:\r
-                        if item == experiments[key]['slice_hrn']:\r
-                            for testbed in wildcard_testbeds[item]:\r
-                                \r
-                                if testbed not in testbeds:\r
-                                    testbeds[testbed] = wildcard_testbeds[item][testbed] \r
-                                \r
-                                for n in wildcard_testbeds[item][testbed]:\r
-                                    if n not in experiments[key]['nodes']:\r
-                                        experiments[key]['nodes'].append(n)                       \r
-                    ######### FOR PLE LIKE end ##################\r
-                    \r
-    return (experiments,testbeds)\r
-   \r
-class ReputationView (LoginRequiredAutoLogoutView, ThemeView):\r
-    template_name = 'reputation.html'\r
-        \r
-    # expose this so we can mention the backend URL on the welcome page\r
-    def default_env (self):\r
-        return { \r
-                 'MANIFOLD_URL':ConfigEngine().manifold_url(),\r
-                 }\r
-\r
-    def post (self,request):\r
-        env = self.default_env()\r
-        env['theme'] = self.theme\r
-                \r
-        return render_to_response(self.template, env, context_instance=RequestContext(request))    \r
-    \r
-    def get (self, request, state=None):\r
-        env = self.default_env()\r
-                \r
-        #####    *** Reputation Plugin-specific START       ***     ############\r
-        #The following 'if' is a dirty way for bypassing the JS AJAX cross-domain prevention policy...not pretty\r
-        if request.GET.has_key(u'slicedata[user_eval][overall]'):\r
-            dict_to_send = {}\r
-            dict_to_send['eid'] = str(request.GET[u'slicedata[id]'])\r
-            dict_to_send['slice_hrn'] = str(request.GET[u'slicedata[slice_hrn]'])\r
-            dict_to_send['user_hrn'] = str(request.GET[u'slicedata[user_hrn]'])\r
-            dict_to_send['start_tunix'] = str(request.GET[u'slicedata[start_tunix]'])\r
-            dict_to_send['end_tunix'] = str(request.GET[u'slicedata[end_tunix]'])\r
-            dict_to_send['start_t'] = str(request.GET[u'slicedata[start_t]'])\r
-            dict_to_send['end_t'] = str(request.GET[u'slicedata[end_t]'])\r
-            dict_to_send['testbeds'] = ast.literal_eval(str(request.GET[u'testbeds']))\r
-            dict_to_send['user_eval'] = {}\r
-            dict_to_send['user_eval']['reuse'] = str(request.GET[u'slicedata[user_eval][reuse]'])\r
-            dict_to_send['user_eval']['availability'] = str(request.GET[u'slicedata[user_eval][availability]'])\r
-            dict_to_send['user_eval']['pay'] = str(request.GET[u'slicedata[user_eval][pay]'])\r
-            dict_to_send['user_eval']['support'] = str(request.GET[u'slicedata[user_eval][support]'])\r
-            dict_to_send['user_eval']['overall'] = str(request.GET[u'slicedata[user_eval][overall]'])\r
-            dict_to_send['user_eval']['link_quality'] = str(request.GET[u'slicedata[user_eval][link_quality]'])\r
-            dict_to_send['user_eval']['problems'] = str(request.GET[u'slicedata[user_eval][problems]'])\r
-            dict_to_send['user_eval']['quality'] = str(request.GET[u'slicedata[user_eval][quality]'])\r
-            \r
-            slicedata_received = json_to_rest('http://survivor.lab.netmode.ntua.gr:4567/reputation/json', dict_to_send )\r
-                        \r
-            return HttpResponse(json.dumps(slicedata_received), content_type = response_mimetype(self.request))\r
-\r
-                \r
-        slices_users = []\r
-        \r
-        #get slices\r
-        userslice_query = Query().get('slice').select('slice_urn', 'slice_hrn', 'users', 'resource', 'lease', 'slice_last_updated')\r
-        slice_details = execute_query(self.request, userslice_query)\r
-        \r
-        #get local users\r
-        local_user_query  = Query().get('local:user').select('email','status','config')\r
-        local_user_details = execute_admin_query(self.request, local_user_query)\r
-                   \r
-        #get users - create dict[email]=hrn\r
-        user_query  = Query().get('user').select('user_hrn','user_urn','user_email')\r
-        user_details = execute_admin_query(self.request, user_query)\r
-        users_hrn = {}\r
-        for item in user_details:\r
-            users_hrn[item['user_email']] = item['user_hrn']\r
-        \r
-        #get currenct username (email)\r
-        if request.user.is_authenticated():\r
-            cur_username = request.user.username  \r
-        \r
-        #get a list of all the slices for the logged in user\r
-        testbeds = []\r
-        #env['slices_users'] = json.dumps(slice_details, ensure_ascii=False)\r
-        for slice in slice_details:\r
-            \r
-            if users_hrn[cur_username] in slice['users']:\r
-                slices_users.append({'slice_hrn':slice['slice_hrn'], 'user':cur_username, 'user_hrn':users_hrn[cur_username] \\r
-                                     , 'resource':slice['resource'], 'lease':slice['lease'], 'slice_last_updated':slice['slice_last_updated']  })  \r
-                \r
-                             \r
-        #env['slices_users'] = slices_users  ### For logging\r
-        #####create slicelist for template & JSON\r
-        experiments,testbeds =  slice_to_exp(slices_users)\r
-            \r
-        all_exp = []\r
-        iddata = []\r
-                          \r
-        for exp in experiments:\r
-            experiment = {}\r
-            experiment['slice_hrn'] = experiments[exp]['slice_hrn']\r
-            experiment['user_hrn'] = users_hrn[cur_username]\r
-            experiment['start_tunix'] = experiments[exp]['start']\r
-            experiment['end_tunix'] = experiments[exp]['end']\r
-            experiment['start_t'] = unix_to_timestamp(experiments[exp]['start'])\r
-            experiment['end_t'] = unix_to_timestamp(experiments[exp]['end'])\r
-            experiment['testbeds'] = {}\r
-            for exp_node in experiments[exp]['nodes']:\r
-                list_testbeds = [ key for key,val in testbeds.items()]\r
-                for tkey in list_testbeds:\r
-                    if exp_node in testbeds[tkey]:\r
-                        if tkey in experiment['testbeds']:\r
-                            if exp_node not in experiment['testbeds'][tkey]:\r
-                                experiment['testbeds'][tkey].append(exp_node)\r
-                        else:\r
-                            experiment['testbeds'][tkey] = [exp_node]\r
-            tempid = hashlib.sha1(str(experiment)).hexdigest()                    \r
-            experiment['id'] = tempid\r
-            \r
-            iddata.append(tempid)\r
-            all_exp.append(experiment)\r
-            env['logging_test'] = json.dumps(all_exp, ensure_ascii=False)\r
-            env['slices_users'] = json.dumps(all_exp, ensure_ascii=False)\r
-        ###### Check which experiments have not been rated yet. Pop from all_exp any experiment that has already been rated\r
-        \r
-        unrated_exp = json_to_rest('http://survivor.lab.netmode.ntua.gr:4567/reputation/qid', iddata)    \r
-        \r
-        for item in all_exp:\r
-            if item['id'] in unrated_exp:\r
-                pass\r
-            else:\r
-                all_exp.pop(all_exp.index(item))\r
-\r
-        ###### Get Reputation values from Reputation DB\r
-        reps = json_to_rest('http://survivor.lab.netmode.ntua.gr:4567/reputation/showrep', "a")\r
-        #env['logging_test'] = reps    \r
-        \r
-        #create a services list and a dict containing the services for each testbed\r
-        serv_per_tb = {}\r
-        services = []\r
-        for item in reps:\r
-            serv_per_tb[item['testbed']]=[]\r
-            for serv in item['services']:\r
-                if serv.keys()[0] not in services:\r
-                    services.append(serv.keys()[0])\r
-                    serv_per_tb[item['testbed']].append(serv.keys()[0])        \r
-        \r
-        #in json, sevices are in the form: 'services':[{'serv1':x}, {'serv2':y}], so we transform it to 'services':[x,y] based on\r
-        # the services dict above. If for a specific service there is no applicable value, we put N/A            \r
-        for testbed in reps:\r
-            d = list(testbed['services'])\r
-            del testbed['services']\r
-            testbed['services'] = []\r
-            for s in services:\r
-                set_v = 0\r
-                for i in d:\r
-                    try:\r
-                        testbed['services'].append(i[s])\r
-                        set_v=1\r
-                    except:\r
-                        pass\r
-                if set_v == 0 :\r
-                    testbed['services'].append('N/A')\r
-                \r
-        ###### Pass variables to template\r
-        #env['logging_test'] = json.dumps(all_exp, ensure_ascii=False)\r
-        env['serv_per_tb'] = json.dumps(serv_per_tb, ensure_ascii=False)\r
-        env['reputation'] = reps\r
-        env['rep_serv'] = services\r
-        env['slicelist'] = all_exp\r
-        env['json_data'] = json.dumps(all_exp, ensure_ascii=False)\r
-        \r
-        ######    *** Reputation Plugin-specific END       ***     ############\r
-        \r
-        \r
-        if request.user.is_authenticated(): \r
-            env['person'] = self.request.user\r
-        else: \r
-            env['person'] = None\r
-    \r
-        env['theme'] = self.theme\r
-        #env['user_list']= user_list\r
-\r
-        env['username']=the_user(request)\r
-        env['topmenu_items'] = topmenu_items(None, request)\r
-        if state: env['state'] = state\r
-        elif not env['username']: env['state'] = None\r
-        # use one or two columns for the layout - not logged in users will see the login prompt\r
-        env['layout_1_or_2']="layout-unfold2.html" if not env['username'] else "layout-unfold1.html"        \r
-        \r
-        return render_to_response(self.template, env, context_instance=RequestContext(request))\r
-    \r
-\r
-\r
-    \r
-\r
-                    \r
-                    \r
-                    \r
-                    \r
-            
\ No newline at end of file
+from django.contrib.auth        import authenticate, login, logout
+from django.template            import RequestContext
+from django.shortcuts           import render, render_to_response
+
+from manifoldapi.manifoldresult import ManifoldResult
+from ui.topmenu                 import topmenu_items, the_user
+from myslice.configengine       import ConfigEngine
+from manifold.core.query        import Query
+from unfold.page                import Page
+from manifoldapi.manifoldapi    import execute_admin_query, execute_query
+from unfold.loginrequired       import LoginRequiredAutoLogoutView
+
+from myslice.theme import ThemeView
+import json
+import hashlib
+import datetime
+import urllib2
+import ast
+import time
+
+from django.views.decorators.csrf import csrf_exempt
+from django.http                  import *
+
+
+def response_content_type(request):
+        
+    if "application/json" in request.META['HTTP_ACCEPT']:
+        return "application/json"
+    else:
+        return "text/plain"
+    
+
+def json_to_rest(url, data ):
+        
+    req = urllib2.Request(url)
+    req.add_header('Content-Type', 'application/json')
+    response = urllib2.urlopen(req, json.dumps(data))
+    
+    if data == "a":
+        mylist = ast.literal_eval(response.read())
+    else:
+        mylist = response.read().translate(None, '"[]').split(",")
+        
+    return (mylist)
+
+
+def unix_to_timestamp(timest):
+    try:
+        return datetime.datetime.fromtimestamp(int(timest)).strftime('%Y-%m-%d %H:%M:%S')
+    except:
+        return timest
+
+def timestamp_to_unix(timest):
+    try:
+        pass
+    except:
+        pass
+    
+    
+def slice_to_exp(slices_users):
+    experiments = {}
+    testbeds = {}
+    wildcard_testbeds = {}
+   
+    
+    for slice in slices_users:  
+        nodes={}
+        leases = slice['lease']
+         
+        if leases is not None and leases:
+            for lease in leases:
+                resource = lease['resource']
+                start_t = lease['start_time']
+                end_t = lease['end_time']
+                
+                testbed_start = resource.index('IDN+')+4
+                testbed_end = resource.index('+node+')
+                
+                testbed = resource[testbed_start:testbed_end]
+                node = resource[testbed_end+6:]
+                if 'omf:nitos' in testbed:
+                    testbed = 'omf:nitos'
+                if testbed in testbeds:
+                    if node not in testbeds[testbed]:
+                        testbeds[testbed].append(node)
+                else:
+                    testbeds[testbed] = [node]
+                
+                #group nodes in consecutive timeslots
+                if not node in nodes:       
+                    nodes[node]={str(start_t):{'start_t':start_t, 'nodes':node, 'end_t':end_t}}
+                else:
+                    if not str(start_t) in nodes[node]:
+                        f=0
+                        for n in nodes[node]:
+                            if n[str(end_t)] == start_t:
+                                n[str(end_t)] == end_t
+                                f=1
+                        if f==0:
+                            nodes[node][str(start_t)]={'start_t':start_t, 'nodes':node, 'end_t':end_t}
+
+            ######### FOR PLE LIKE start ##################
+            for resource in slice['resource']:
+                testbed_start = resource.index('IDN+')+4
+                testbed_end = resource.index('+node+')
+                tb = resource[testbed_start:testbed_end]
+                node = resource[testbed_end+6:]
+                if 'ple:' in tb:
+                    tb = 'ple'
+                if 'omf:nitos' in tb:
+                    tb = 'omf:nitos'
+                if tb not in testbeds:
+                    try:
+                        if node not in wildcard_testbeds[slice['slice_hrn']][tb]:
+                            wildcard_testbeds[slice['slice_hrn']][tb].append([node])
+                    except:
+                        try:
+                            wildcard_testbeds[slice['slice_hrn']][tb] = [node]
+                        except:
+                            wildcard_testbeds[slice['slice_hrn']]={tb:[node]}
+                    
+            
+        else:
+            s = slice['slice_last_updated']
+            #s_time = int(time.mktime(datetime.datetime.strptime(s, "%Y%m%dT%H:%M:%Ss").timetuple()))
+            s_time = time.mktime(s.timetuple())                
+                
+            if slice['resource'] is not None:
+                                    
+                for resource in slice['resource']:
+                    testbed_start = resource.index('IDN+')+4
+                    testbed_end = resource.index('+node+')
+                    tb = resource[testbed_start:testbed_end]
+                    if 'ple:' in tb:
+                        tb = 'ple'
+                    if 'omf:nitos' in tb:
+                        tb = 'omf:nitos'
+                    node = resource[testbed_end+6:]
+                    
+                    if testbed in testbeds:
+                        if node not in testbeds[testbed]:
+                            testbeds[testbed].append(node)
+                    else:
+                        testbeds[testbed] = [node]       
+                    
+                    if not node in nodes:  
+                        #nodes[node] = {str(start_t):{'start_t':s_time, 'nodes':node, 'end_t':int(time.time())}} 
+                        nodes[node] = {str(start_t):{'start_t':s_time, 'nodes':node, 'end_t':s_time}}    
+            ######### FOR PLE LIKE end ##################
+                        
+        #group grouped nodes in experiments
+        for n in nodes:
+            for exp in nodes[n]:
+                key = str(exp) + str(nodes[n][exp]['end_t']) + slice['slice_hrn']
+                
+                if key not in experiments:
+                    experiments[key]={'slice_hrn':slice['slice_hrn'], \
+                                      'start':nodes[n][exp]['start_t'], 'end':nodes[n][exp]['end_t'], 'nodes':[nodes[n][exp]['nodes']]}   
+                    
+                    
+                    ######### FOR PLE LIKE start ##################
+                    for item in wildcard_testbeds:
+                        if item == experiments[key]['slice_hrn']:
+                            for testbed in wildcard_testbeds[item]:
+                                
+                                if testbed not in testbeds:
+                                    testbeds[testbed] = wildcard_testbeds[item][testbed] 
+                                
+                                for n in wildcard_testbeds[item][testbed]:
+                                    if n not in experiments[key]['nodes']:
+                                        experiments[key]['nodes'].append(n)                                           
+                    ######### FOR PLE LIKE end ##################
+                    
+                elif nodes[n][exp]['end_t'] == experiments[key]['end']:
+                    experiments[key]['nodes'].append(nodes[n][exp]['nodes'])
+                    
+                    
+                    ######### FOR PLE LIKE start ##################
+                    for item in wildcard_testbeds:
+                        if item == experiments[key]['slice_hrn']:
+                            for testbed in wildcard_testbeds[item]:
+                                
+                                if testbed not in testbeds:
+                                    testbeds[testbed] = wildcard_testbeds[item][testbed] 
+                                
+                                for n in wildcard_testbeds[item][testbed]:
+                                    if n not in experiments[key]['nodes']:
+                                        experiments[key]['nodes'].append(n)                       
+                    ######### FOR PLE LIKE end ##################
+                    
+    return (experiments,testbeds)
+   
+class ReputationView (LoginRequiredAutoLogoutView, ThemeView):
+    template_name = 'reputation.html'
+        
+    # expose this so we can mention the backend URL on the welcome page
+    def default_env (self):
+        return { 
+                 'MANIFOLD_URL':ConfigEngine().manifold_url(),
+                 }
+
+    def post (self,request):
+        env = self.default_env()
+        env['theme'] = self.theme
+                
+        return render_to_response(self.template, env, context_instance=RequestContext(request))    
+    
+    def get (self, request, state=None):
+        env = self.default_env()
+                
+        #####    *** Reputation Plugin-specific START       ***     ############
+        #The following 'if' is a dirty way for bypassing the JS AJAX cross-domain prevention policy...not pretty
+        if request.GET.has_key(u'slicedata[user_eval][overall]'):
+            dict_to_send = {}
+            dict_to_send['eid'] = str(request.GET[u'slicedata[id]'])
+            dict_to_send['slice_hrn'] = str(request.GET[u'slicedata[slice_hrn]'])
+            dict_to_send['user_hrn'] = str(request.GET[u'slicedata[user_hrn]'])
+            dict_to_send['start_tunix'] = str(request.GET[u'slicedata[start_tunix]'])
+            dict_to_send['end_tunix'] = str(request.GET[u'slicedata[end_tunix]'])
+            dict_to_send['start_t'] = str(request.GET[u'slicedata[start_t]'])
+            dict_to_send['end_t'] = str(request.GET[u'slicedata[end_t]'])
+            dict_to_send['testbeds'] = ast.literal_eval(str(request.GET[u'testbeds']))
+            dict_to_send['user_eval'] = {}
+            dict_to_send['user_eval']['reuse'] = str(request.GET[u'slicedata[user_eval][reuse]'])
+            dict_to_send['user_eval']['availability'] = str(request.GET[u'slicedata[user_eval][availability]'])
+            dict_to_send['user_eval']['pay'] = str(request.GET[u'slicedata[user_eval][pay]'])
+            dict_to_send['user_eval']['support'] = str(request.GET[u'slicedata[user_eval][support]'])
+            dict_to_send['user_eval']['overall'] = str(request.GET[u'slicedata[user_eval][overall]'])
+            dict_to_send['user_eval']['link_quality'] = str(request.GET[u'slicedata[user_eval][link_quality]'])
+            dict_to_send['user_eval']['problems'] = str(request.GET[u'slicedata[user_eval][problems]'])
+            dict_to_send['user_eval']['quality'] = str(request.GET[u'slicedata[user_eval][quality]'])
+            
+            slicedata_received = json_to_rest('http://survivor.lab.netmode.ntua.gr:4567/reputation/json', dict_to_send )
+                        
+            return HttpResponse(json.dumps(slicedata_received), content_type = response_content_type(self.request))
+
+                
+        slices_users = []
+        
+        #get slices
+        userslice_query = Query().get('slice').select('slice_urn', 'slice_hrn', 'users', 'resource', 'lease', 'slice_last_updated')
+        slice_details = execute_query(self.request, userslice_query)
+        
+        #get local users
+        local_user_query  = Query().get('local:user').select('email','status','config')
+        local_user_details = execute_admin_query(self.request, local_user_query)
+                   
+        #get users - create dict[email]=hrn
+        user_query  = Query().get('user').select('user_hrn','user_urn','user_email')
+        user_details = execute_admin_query(self.request, user_query)
+        users_hrn = {}
+        for item in user_details:
+            users_hrn[item['user_email']] = item['user_hrn']
+        
+        #get currenct username (email)
+        if request.user.is_authenticated():
+            cur_username = request.user.username  
+        
+        #get a list of all the slices for the logged in user
+        testbeds = []
+        #env['slices_users'] = json.dumps(slice_details, ensure_ascii=False)
+        for slice in slice_details:
+            
+            if users_hrn[cur_username] in slice['users']:
+                slices_users.append({'slice_hrn':slice['slice_hrn'], 'user':cur_username, 'user_hrn':users_hrn[cur_username] \
+                                     , 'resource':slice['resource'], 'lease':slice['lease'], 'slice_last_updated':slice['slice_last_updated']  })  
+                
+                             
+        #env['slices_users'] = slices_users  ### For logging
+        #####create slicelist for template & JSON
+        experiments,testbeds =  slice_to_exp(slices_users)
+            
+        all_exp = []
+        iddata = []
+                          
+        for exp in experiments:
+            experiment = {}
+            experiment['slice_hrn'] = experiments[exp]['slice_hrn']
+            experiment['user_hrn'] = users_hrn[cur_username]
+            experiment['start_tunix'] = experiments[exp]['start']
+            experiment['end_tunix'] = experiments[exp]['end']
+            experiment['start_t'] = unix_to_timestamp(experiments[exp]['start'])
+            experiment['end_t'] = unix_to_timestamp(experiments[exp]['end'])
+            experiment['testbeds'] = {}
+            for exp_node in experiments[exp]['nodes']:
+                list_testbeds = [ key for key,val in testbeds.items()]
+                for tkey in list_testbeds:
+                    if exp_node in testbeds[tkey]:
+                        if tkey in experiment['testbeds']:
+                            if exp_node not in experiment['testbeds'][tkey]:
+                                experiment['testbeds'][tkey].append(exp_node)
+                        else:
+                            experiment['testbeds'][tkey] = [exp_node]
+            tempid = hashlib.sha1(str(experiment)).hexdigest()                    
+            experiment['id'] = tempid
+            
+            iddata.append(tempid)
+            all_exp.append(experiment)
+            env['logging_test'] = json.dumps(all_exp, ensure_ascii=False)
+            env['slices_users'] = json.dumps(all_exp, ensure_ascii=False)
+        ###### Check which experiments have not been rated yet. Pop from all_exp any experiment that has already been rated
+        
+        unrated_exp = json_to_rest('http://survivor.lab.netmode.ntua.gr:4567/reputation/qid', iddata)    
+        
+        for item in all_exp:
+            if item['id'] in unrated_exp:
+                pass
+            else:
+                all_exp.pop(all_exp.index(item))
+
+        ###### Get Reputation values from Reputation DB
+        reps = json_to_rest('http://survivor.lab.netmode.ntua.gr:4567/reputation/showrep', "a")
+        #env['logging_test'] = reps    
+        
+        #create a services list and a dict containing the services for each testbed
+        serv_per_tb = {}
+        services = []
+        for item in reps:
+            serv_per_tb[item['testbed']]=[]
+            for serv in item['services']:
+                if serv.keys()[0] not in services:
+                    services.append(serv.keys()[0])
+                    serv_per_tb[item['testbed']].append(serv.keys()[0])        
+        
+        #in json, sevices are in the form: 'services':[{'serv1':x}, {'serv2':y}], so we transform it to 'services':[x,y] based on
+        # the services dict above. If for a specific service there is no applicable value, we put N/A            
+        for testbed in reps:
+            d = list(testbed['services'])
+            del testbed['services']
+            testbed['services'] = []
+            for s in services:
+                set_v = 0
+                for i in d:
+                    try:
+                        testbed['services'].append(i[s])
+                        set_v=1
+                    except:
+                        pass
+                if set_v == 0 :
+                    testbed['services'].append('N/A')
+                
+        ###### Pass variables to template
+        #env['logging_test'] = json.dumps(all_exp, ensure_ascii=False)
+        env['serv_per_tb'] = json.dumps(serv_per_tb, ensure_ascii=False)
+        env['reputation'] = reps
+        env['rep_serv'] = services
+        env['slicelist'] = all_exp
+        env['json_data'] = json.dumps(all_exp, ensure_ascii=False)
+        
+        ######    *** Reputation Plugin-specific END       ***     ############
+        
+        
+        if request.user.is_authenticated(): 
+            env['person'] = self.request.user
+        else: 
+            env['person'] = None
+    
+        env['theme'] = self.theme
+        #env['user_list']= user_list
+
+        env['username']=the_user(request)
+        env['topmenu_items'] = topmenu_items(None, request)
+        if state: env['state'] = state
+        elif not env['username']: env['state'] = None
+        # use one or two columns for the layout - not logged in users will see the login prompt
+        env['layout_1_or_2']="layout-unfold2.html" if not env['username'] else "layout-unfold1.html"        
+        
+        return render_to_response(self.template, env, context_instance=RequestContext(request))
+    
+
+
+    
+
+                    
+                    
+                    
+                    
+            
index d670645..1d3b9af 100644 (file)
@@ -22,7 +22,6 @@ class ResourceView(FreeAccessView, ThemeView):
         page.add_js_files  ( [ "js/common.functions.js" ] )
 
         for key, value in kwargs.iteritems():
-            print "%s = %s" % (key, value)       
             if key == "urn":
                 resource_urn=value
                 
index a880d39..c7102dc 100644 (file)
@@ -1,7 +1,12 @@
+import json
+import time
+import re
+
 from django.shortcuts           import render
+from django.shortcuts           import render_to_response
+from django.template                    import RequestContext
 from django.contrib.sites.models import Site
 
-
 from unfold.page                import Page
 
 from manifold.core.query        import Query
@@ -13,10 +18,10 @@ from unfold.loginrequired       import LoginRequiredAutoLogoutView
 from ui.topmenu                 import topmenu_items_live, the_user
 
 from myslice.theme import ThemeView
-
-import json, time, re
+from myslice.settings import logger
 
 import activity.user
+theme = ThemeView()
 
 class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView):
     template_name = 'slicerequest_view.html'
@@ -29,9 +34,10 @@ class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView):
     def get (self, request):
         return self.get_or_post (request, 'GET')
 
-    def get_or_post  (self, wsgi_request, method):
+    def get_or_post  (self, request, method):
         """
         """
+
         errors = []
         slice_name =''
         purpose=''
@@ -39,15 +45,19 @@ class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView):
         authority_hrn = None
         authority_name = None
         # Retrieve the list of authorities
-        authorities_query = Query.get('authority').select('name', 'authority_hrn')
-        authorities = execute_admin_query(wsgi_request, authorities_query)
+        if self.theme == 'fed4fire':
+            authorities_query = Query.get('myslice:authority').select('authority_hrn')
+        else:
+            authorities_query = Query.get('authority').select('name', 'authority_hrn')
+        authorities = execute_admin_query(request, authorities_query)
         if authorities is not None:
             authorities = sorted(authorities, key=lambda k: k['authority_hrn'])
-            authorities = sorted(authorities, key=lambda k: k['name'])
+            if self.theme != 'fed4fire':
+                authorities = sorted(authorities, key=lambda k: k['name'])
 
         # Get user_email (XXX Would deserve to be simplified)
         user_query  = Query().get('local:user').select('email','config')
-        user_details = execute_query(wsgi_request, user_query)
+        user_details = execute_query(request, user_query)
         user_email = user_details[0].get('email')
         # getting user_hrn
         for user_detail in user_details:
@@ -55,7 +65,7 @@ class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView):
             user_authority = user_config.get('authority','N/A')              
         # getting the org from authority        
         for authority in authorities:
-            if authority['authority_hrn'] == user_authority:
+            if 'name' in authority and authority['authority_hrn'] == user_authority:
                 authority_name = authority['name']
 
         # Handle the case when we use only hrn and not name
@@ -63,10 +73,10 @@ class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView):
             authority_name = user_authority
         
         account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config')
-        account_details = execute_query(wsgi_request, account_query)
+        account_details = execute_query(request, account_query)
         
         platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
-        platform_details = execute_query(wsgi_request, platform_query)
+        platform_details = execute_query(request, platform_query)
         user_hrn = None
         #getting user_hrn from local:account
         for account_detail in account_details:
@@ -86,11 +96,11 @@ class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView):
         #else:
         #    pi = "is_pi"
 
-        pi = authority_check_pis (wsgi_request, user_email)
-        print "SLICEREQUESTVIEW.PY -----  pi=",pi
+        pi = authority_check_pis (request, user_email)
+        logger.debug("SLICEREQUESTVIEW.PY -----  pi= {}".format(pi))
 
         # Page rendering
-        page = Page(wsgi_request)
+        page = Page(request)
         page.add_js_files  ( [ "js/jquery.validate.js", "js/jquery-ui.js" ] )
         page.add_css_files ( [ "css/jquery-ui.css" ] )
         page.expose_js_metadata()
@@ -101,21 +111,29 @@ class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView):
             # get the domain url
             current_site = Site.objects.get_current()
             current_site = current_site.domain
-            
-            # getting the authority_hrn from the selected organization
-            for authority in authorities:
-                if authority['name'] == wsgi_request.POST.get('org_name', ''):
-                    authority_hrn = authority['authority_hrn']
+           
+            if theme.theme != 'fed4fire':
+                # getting the authority_hrn from the selected organization
+                for authority in authorities:
+                    if authority['name'] == request.POST.get('org_name', ''):
+                        authority_hrn = authority['authority_hrn']
 
             # Handle the case when we use only hrn and not name
             if authority_hrn is None:
-                authority_hrn = wsgi_request.POST.get('org_name', '')
+                authority_hrn = request.POST.get('org_name', '')
 
             # Handle project if used
-            project = wsgi_request.POST.get('project', None)
+            project = request.POST.get('project', None)
             if project is not None and project != '':
                 authority_hrn = project
 
+            slice_name = request.POST.get('slice_name', '')
+            if not slice_name or len(slice_name) == 0 :
+                errors.append('Slice name can\'t be empty')
+
+            # accept only lowercase names
+            slice_name = slice_name.lower()
+
             slice_request = {
                 'type'              : 'slice',
                 'id'                : None,
@@ -123,63 +141,70 @@ class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView):
                 'email'             : user_email,
                 'timestamp'         : time.time(),
                 'authority_hrn'     : authority_hrn,
-                'organization'      : wsgi_request.POST.get('org_name', ''),
-                'slice_name'        : wsgi_request.POST.get('slice_name', ''),
-                'url'               : wsgi_request.POST.get('url', ''),
-                'purpose'           : wsgi_request.POST.get('purpose', ''),
+                'organization'      : request.POST.get('org_name', ''),
+                'slice_name'        : slice_name,
+                'url'               : request.POST.get('url', ''),
+                'purpose'           : request.POST.get('purpose', ''),
                 'current_site'      : current_site
             }
-            
-            # create slice_hrn based on authority_hrn and slice_name
-            slice_name = slice_request['slice_name']
-            req_slice_hrn = authority_hrn + '.' + slice_name
-            # comparing requested slice_hrn with the existing slice_hrn 
-            slice_query  = Query().get('myslice:slice').select('slice_hrn','parent_authority').filter_by('parent_authority','==',authority_hrn)
-            slice_details_sfa = execute_admin_query(wsgi_request, slice_query)
+
+            # slice name is unique among all authorities 
+            slice_query = Query().get('myslice:slice').select('slice_hrn')
+            slice_details_sfa = execute_admin_query(request, slice_query)
             for _slice in slice_details_sfa:
-                if _slice['slice_hrn'] == req_slice_hrn:
+                split_list = _slice['slice_hrn'].split('.')
+                sfa_slice_name = split_list[-1]
+                if sfa_slice_name == slice_name:
                     errors.append('Slice already exists. Please use a different slice name.')
             
 
             # What kind of slice name is valid?
-            if (slice_name is None or slice_name == ''):
+            if slice_name is None or slice_name == '':
                 errors.append('Slice name is mandatory')
             
-            if (re.search(r'^[A-Za-z0-9_]*$', slice_name) == None):
+            if re.search(r'^[A-Za-z0-9_]*$', slice_name) is None:
                 errors.append('Slice name may contain only letters, numbers, and underscore.')
             
-            organization = slice_request['organization']    
-            if (organization is None or organization == ''):
-                errors.append('Organization is mandatory')
+            organization = slice_request['organization']
+            if theme.theme == 'fed4fire':
+                if organization is None or organization == '':
+                    errors.append('Selecting project is mandatory')
+            else:
+                if organization is None or organization == '':
+                    errors.append('Organization is mandatory')
+
+            slice_length= len(slice_request['slice_name'])
+            if slice_length >19:
+                errors.append('Slice name can be maximum 19 characters long')
 
 
     
             purpose = slice_request['purpose']
-            if (purpose is None or purpose == ''):
+            if purpose is None or purpose == '':
                 errors.append('Experiment purpose is mandatory')
 
             url = slice_request['url']
 
             if not errors:
-                if is_pi(wsgi_request, user_hrn, authority_hrn):
+                if is_pi(request, user_hrn, authority_hrn):
                     # PIs can directly create slices in their own authority...
-                    create_slice(wsgi_request, slice_request)
-                    clear_user_creds(wsgi_request, user_email)
+                    create_slice(request, slice_request)
+                    clear_user_creds(request, user_email)
                     self.template_name = 'slice-request-done-view.html'
                 else:
-                    # Otherwise a wsgi_request is sent to the PI
-                    create_pending_slice(wsgi_request, slice_request, user_email)
+                    # Otherwise a request is sent to the PI
+                    create_pending_slice(request, slice_request, user_email)
                     self.template_name = 'slice-request-ack-view.html'
                 
                 # log user activity
-                activity.user.slice(wsgi_request)
-                
-                return render(wsgi_request, self.template, {'theme': self.theme}) # Redirect after POST
+                activity.user.slice(request)
+                return render_to_response(self.template, {'theme': self.theme, 'request':request}, context_instance=RequestContext(request))
+                #return render(request, self.template, {'theme': self.theme}) # Redirect after POST
         else:
             slice_request = {}
 
         template_env = {
-            'username': wsgi_request.user.email,
+            'username': request.user.email,
             'topmenu_items': topmenu_items_live('Request a slice', page),
             'errors': errors,
             'slice_name': slice_name,
@@ -193,8 +218,11 @@ class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView):
             'cc_myself': True,
             'authorities': authorities,
             'theme': self.theme,
-            'section': "Slice request"
+            'section': "Slice request",
+            'request': request,
         }
         template_env.update(slice_request)
         template_env.update(page.prelude_env())
-        return render(wsgi_request, self.template, template_env)
+
+        return render_to_response(self.template,template_env, context_instance=RequestContext(request))
+        #return render(request, self.template, template_env)
index c394345..341fa4b 100644 (file)
@@ -1,16 +1,16 @@
+import json
+
 from django.template                    import RequestContext
 from django.shortcuts                   import render_to_response
+from django.views.generic.base          import TemplateView
+from django.http import HttpResponse
+from django.shortcuts import render
 
 from manifold.core.query                import Query, AnalyzedQuery
 from manifoldapi.manifoldapi            import execute_query
-import json
 
-from django.views.generic.base          import TemplateView
 
 from unfold.loginrequired               import LoginRequiredView
-from django.http import HttpResponse
-from django.shortcuts import render
-
 from unfold.page                        import Page
 
 from myslice.configengine               import ConfigEngine
@@ -30,7 +30,7 @@ from plugins.univbrisfv                 import UnivbrisFv
 from plugins.univbrisfvf                import UnivbrisFvf
 from plugins.univbrisfvfo              import UnivbrisFvfo
 from plugins.univbristopo               import UnivbrisTopo
-from plugins.univbrisvtam                  import UnivbrisVtam as UnivbrisVtamPlugin
+from plugins.univbrisvtam               import UnivbrisVtam as UnivbrisVtamPlugin
 from plugins.univbrisvtamform          import UnivbrisVtamForm
 
 from plugins.columns_editor             import ColumnsEditor
@@ -38,6 +38,7 @@ from plugins.sladialog                  import SlaDialog
 from plugins.lists.simplelist           import SimpleList
 
 from myslice.theme import ThemeView
+from myslice.settings import logger
 
 class SliceResourceView (LoginRequiredView, ThemeView):
     template_name = "slice-resource-view.html"
@@ -71,7 +72,7 @@ class SliceResourceView (LoginRequiredView, ThemeView):
 
         slice_md = metadata.details_by_object('slice')
         slice_fields = [column['name'] for column in slice_md['column']]
-        print "SLICE RES VIEW fields = %s" % slice_fields
+        logger.debug("SLICE RES VIEW fields = {}".format(slice_fields))
         # TODO The query to run is embedded in the URL
         # Example: select slice_hrn, resource.urn, lease.resource, lease.start_time, lease.end_time from slice where slice_hrn == "ple.upmc.myslicedemo"
         main_query = Query.get('slice').filter_by('slice_hrn', '=', slicename)
@@ -282,6 +283,7 @@ class SliceResourceView (LoginRequiredView, ThemeView):
             page            = page,
             domid           = "filter-status",
             query           = sq_resource,
+            query_lease     = sq_lease,
         )
         apply = ApplyPlugin(
             page            = page,
@@ -396,42 +398,25 @@ class SliceResourceView (LoginRequiredView, ThemeView):
        #         },
        # )
 
-       # # --------------------------------------------------------------------------
-       # # SLA View and accept dialog
-       # 
-       # sla_dialog = SlaDialog(
-       #     page                = page,
-       #     title               = 'sla dialog',
-       #     query               = main_query,
-       #     togglable           = False,
-       #     # start turned off, it will open up itself when stuff comes in
-       #     toggled             = True,
-       #     domid               = 'sla_dialog',
-       #     outline_complete    = True,
-       #     username            = request.user,
-       # )
-       # 
-        ## check user is pi or not
-        platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
-        account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config')
-        platform_details = execute_query(self.request, platform_query)
-        account_details = execute_query(self.request, account_query)
-
-        # XXX When session has expired, this is None and thus not iterable
-        for platform_detail in platform_details:
-            for account_detail in account_details:
-                if platform_detail['platform_id'] == account_detail['platform_id']:
-                    if 'config' in account_detail and account_detail['config'] is not '':
-                        account_config = json.loads(account_detail['config'])
-                        if 'myslice' in platform_detail['platform']:
-                            acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
-        # assigning values
-        if acc_auth_cred == {} or acc_auth_cred == 'N/A':
-            pi = "is_not_pi"
-        else:
-            pi = "is_pi"
+        # --------------------------------------------------------------------------
+        # SLA View and accept dialog
+
+        sla_dialog = SlaDialog(
+           page                = page,
+           title               = 'sla dialog',
+           query               = main_query,
+           #togglable           = False,
+           # start turned off, it will open up itself when stuff comes in
+           #toggled             = True,
+           domid               = 'sla_dialog',
+           #outline_complete    = True,
+           username            = request.user,
+        )
         
         template_env = {}
+
+        template_env['request'] = self.request       
+
         template_env['list_resources'] = list_resources.render(self.request)
         template_env['list_reserved_resources'] = list_reserved_resources.render(self.request)
         template_env['list_reserved_leases'] = list_reserved_leases.render(self.request)
@@ -455,11 +440,10 @@ class SliceResourceView (LoginRequiredView, ThemeView):
        # template_env['vms_list'] = univbrisvtamplugin.render(self.request)
        # template_env['vm_form'] = univbrisvtamform.render(self.request)
 
-#        template_env['pending_resources'] = pending_resources.render(self.request)
-       # template_env['sla_dialog'] = '' # sla_dialog.render(self.request)
+       # template_env['pending_resources'] = pending_resources.render(self.request)
+        template_env['sla_dialog'] = sla_dialog.render(self.request)
         template_env["theme"] = self.theme
         template_env["username"] = request.user
-        template_env["pi"] = pi
         template_env["slice"] = slicename
         template_env["section"] = "resources"
         template_env["msg"] = msg
index ab2fee2..cc20df2 100644 (file)
@@ -16,12 +16,15 @@ from myslice.configengine import ConfigEngine
 
 from myslice.theme import ThemeView
 from myslice.configengine import ConfigEngine
+from myslice.settings import logger
 
 from sfa.planetlab.plxrn import hash_loginbase
 
 import urllib2,json
 
 class ExperimentView (FreeAccessView, ThemeView):
+    # parent View is portal/sliceview.py
+
     template_name = 'slice-tab-experiment.html'
 
     def get (self, request, slicename, state=None):
@@ -43,12 +46,8 @@ class ExperimentView (FreeAccessView, ThemeView):
         try:
             for resources in current_resources:
                 list_res = resources['resource']
-                #print "list_b4"
-                #print list_res
                 for res in list_res:
                     split_list = res.split('+') # split the resource urn
-                    #print "list_after"
-                    #print split_list
                     if [s for s in split_list if 'ple' in s]: # find ple resources
                         res_hrn = split_list[-1] # last element is resource hrn
                         ple_resource_list.append(res_hrn)
@@ -66,17 +65,17 @@ class ExperimentView (FreeAccessView, ThemeView):
                         nitos_resource_list.append(res_hrn)
 
 
-        except Exception,e:
-            print "Exception in slicetabexperiment.py in OneLab resource search %s" % e
+        except Exception as e:
+            logger.error("Exception in slicetabexperiment.py in OneLab resource search {}".format(e))
         
-        #print "list of ple res hrns"
-        #print ple_resource_list
-        #print "list of nit_paris res hrns"
-        #print nitos_paris_resource_list
-        #print "list of iotLab res hrns"
-        #print iotlab_resource_list
-        #print "list of nitos res hrns"
-        #print nitos_resource_list
+        #logger.debug("list of ple res hrns")
+        #logger.debug(ple_resource_list)
+        #logger.debug("list of nit_paris res hrns")
+        #logger.debug(nitos_paris_resource_list)
+        #logger.debug("list of iotLab res hrns")
+        #logger.debug(iotlab_resource_list)
+        #logger.debug("list of nitos res hrns")
+        #logger.debug(nitos_resource_list)
 
         all_users = list() 
         #get all  iotlab users
@@ -92,7 +91,7 @@ class ExperimentView (FreeAccessView, ThemeView):
             res = urllib2.urlopen(req)
             all_users = json.load(res) 
         except urllib2.URLError as e:
-            print "There is a problem in getting iotlab users %s" % e.reason
+            logger.error("There is a problem in getting iotlab users {}".format(e.reason))
        
 
         #getting the login from email
@@ -102,6 +101,16 @@ class ExperimentView (FreeAccessView, ThemeView):
         for user in all_users:
             if user['email'] == username:
                 iot_login = user['login']
-            
-        return render_to_response(self.template, { 'theme' : self.theme,'slicename':slicename, 'ple_slicename':ple_slicename, 'username':username, 'ple_resources':ple_resource_list, 'nitos_resources': nitos_resource_list, 'nitos_paris_resources':nitos_paris_resource_list, 'iotlab_resources':iotlab_resource_list, 'iot_login':iot_login }, context_instance=RequestContext(request))
+        env = { 'theme' : self.theme,
+                'slicename':slicename, 
+                'ple_slicename':ple_slicename, 
+                'username':username, 
+                'ple_resources':ple_resource_list, 
+                'nitos_resources': nitos_resource_list, 
+                'nitos_paris_resources':nitos_paris_resource_list, 
+                'iotlab_resources':iotlab_resource_list, 
+                'iot_login':iot_login,
+                'request':self.request,
+              }
+        return render_to_response(self.template, env, context_instance=RequestContext(request))
 
index 49afc69..a62067f 100644 (file)
@@ -6,7 +6,7 @@ from unfold.loginrequired           import LoginRequiredView
 from myslice.theme import ThemeView
 
 class SliceTabMeasurements (LoginRequiredView, ThemeView):
-    template_name = "slice-tab-measurement.html"
+    template_name = "slice-tab-measurements.html"
     
     def get(self, request, slicename):
-        return render_to_response(self.template, {"theme": self.theme, "username": request.user, "slice" : slicename, "section":"measurements"}, context_instance=RequestContext(request))
+        return render_to_response(self.template, {"theme": self.theme, "username": request.user, "slicename" : slicename, "section":"measurements"}, context_instance=RequestContext(request))
index 309347c..b5fe92f 100644 (file)
@@ -20,21 +20,10 @@ class SliceView (LoginRequiredView, ThemeView):
     template_name = "slice-view.html"
     
     def get(self, request, slicename):
-        ## check user is pi or not
-        platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
-        account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config')
-        platform_details = execute_query(self.request, platform_query)
-        account_details = execute_query(self.request, account_query)
-        for platform_detail in platform_details:
-            for account_detail in account_details:
-                if platform_detail['platform_id'] == account_detail['platform_id']:
-                    if 'config' in account_detail and account_detail['config'] is not '':
-                        account_config = json.loads(account_detail['config'])
-                        if 'myslice' in platform_detail['platform']:
-                            acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
-        # assigning values
-        if acc_auth_cred == {} or acc_auth_cred == 'N/A':
-            pi = "is_not_pi"
-        else:
-            pi = "is_pi"
-        return render_to_response(self.template, {"slice": slicename, "theme": self.theme, "username": request.user,"pi":pi, "section": "Slice %s" % slicename }, context_instance=RequestContext(request))
+
+        return render_to_response(self.template,
+                                  {"slice" : slicename,
+                                   "theme" : self.theme,
+                                   "username" : request.user,
+                                   "section" : "Slice {}".format(slicename),'request':request },
+                                  context_instance=RequestContext(request))
index 70de2a8..712c723 100644 (file)
@@ -27,7 +27,18 @@ h2 {
     color:#333333;
 }
 h3 {
-    font-size:13pt;
+    font-size:12pt;
+    letter-spacing:0.6pt;
+    color:#201E62;
+}
+h4 {
+    font-size:12pt;
+    letter-spacing:0.6pt;
+    color:#201E62;
+}
+label {
+    font-weight:normal;
+    font-size:13px;
     color:#201E62;
 }
 input[type=checkbox] {
@@ -651,17 +662,97 @@ div.secondary .account span {
 div.secondary .account a {
     color:black;
 }
-div.dashboard div {
-    margin:25px 0;
+
+div.home {
+    padding-top:50px;
+}
+div.home h1 {
+    font-size:22pt;
+    border:0;
+}
+div.home h3, div.home h4 {
+    color:#424242;
+    line-height:1.4em;
+}
+
+div.home h3 a {
+    color:#FD6D2C;
 }
 div.dashboard {
-    text-align:center;
+}
+div.dashboard a {
+    color:#206090;
+}
+
+div.dashboard a:hover {
+    text-decoration:underline;
+}
+div.dashboard div.projects-tree {
+    margin-left:49px;
 }
 div.dashboard ul {
+    list-style-type:disc;
+    list-style-position:inside;
     text-align:left;
-    margin-left:24px;
+    margin:0 0 15px 0;
+    padding:0;
+    
+}
+div.dashboard ul ul {
+    margin:5px 0 15px 25px;
     list-style:none;
 }
+div.dashboard li {
+    margin:0 0 5px 0;
+    padding:0;
+}
+div.dashboard ul ul li {
+    margin:0;
+}
+div.dashboard ul ul a {
+}
+div.dashboard h3 {
+    border-bottom:1px solid #E0E0E0;
+    margin-right:15px;
+    margin-bottom:25px;
+}
+div.dashboard h3 a {
+     color:#201E62;
+}
+div.dashboard h3 img {
+    margin:15px 15px 15px 0;
+}
+div.dashboard span.glyphicon {
+    text-align:center;
+    width:45px;
+    height:25px;
+}
+div.dashboard-create-slice {
+    display:none;
+}
+div.experiment-tools {
+}
+div.experiment-tools h4 {
+    border-bottom:1px solid #E0E0E0;
+    margin:25px 15px 25px 0;
+    padding-bottom:5px;
+}
+div.experiment-tools .jfed {
+    text-align:center;
+    margin-right:25px;
+}
+div.experiment-tools button {
+    margin:0;
+    padding:7px 10px 4px 0;
+    color:white;
+    vertical-align:middle;
+}
+
+div.experiment-tools button span {
+    margin:0;
+    padding:0;
+}
+
 div.dataTables_filter label{
     float:left;
     width:400px;
@@ -671,6 +762,15 @@ div.breadcrumbs {
     color:gray;
     font-size:10pt;
 }
+
+.sublabel {
+    color:gray;
+    font-style:italic;
+    font-weight:normal;
+}
+.tab-pane {
+    padding-top:25px;
+}
 /* Service Directory */
 
 div#appservices div.row {
index 45f5efc..4023e6c 100644 (file)
@@ -56,6 +56,12 @@ h4 {
     font-size:12pt;
     color:#333333;
 }
+ul {
+    margin:0 0 0 15px;
+    padding:0;
+}
+li {
+}
 span.subtitle {
     color:#454545;
     font-size:9pt;
@@ -121,7 +127,6 @@ div.breadcrumbs a:hover {
     text-decoration:underline;
 }
 .tab-pane {
-    padding-top:15px;
 }
 /* buttons */
 button.btn, input.btn {
@@ -389,6 +394,31 @@ div.sl-filter-facilities {
 div.sl-filter-facilities h4 {
     margin-bottom:15px;
     
+}
+.sl-menu {
+    padding:0;
+}
+.sl-menu h4 {
+    margin:0 0 15px 0;
+    padding:0;
+}
+.sl-menu ul {
+    list-style:none;
+    margin:0;
+    padding:0;
+}
+.sl-menu li {
+    color:gray;
+    cursor:pointer;
+    padding:4px 8px;
+}
+.sl-menu li img {
+    vertical-align:top;
+}
+.sl-menu li.active {
+    color:black;
+}
+.sl-menu-item {
 }
 img.sl-image {
     margin:0 5px 5px 0;
diff --git a/portal/static/img/testbeds/NITOS-Volos.png b/portal/static/img/testbeds/NITOS-Volos.png
new file mode 100644 (file)
index 0000000..311fbbb
Binary files /dev/null and b/portal/static/img/testbeds/NITOS-Volos.png differ
diff --git a/portal/static/img/testbeds/Netmode.png b/portal/static/img/testbeds/Netmode.png
new file mode 100644 (file)
index 0000000..a6e410a
Binary files /dev/null and b/portal/static/img/testbeds/Netmode.png differ
diff --git a/portal/static/img/testbeds/netmode.png b/portal/static/img/testbeds/netmode.png
deleted file mode 100644 (file)
index 8918573..0000000
Binary files a/portal/static/img/testbeds/netmode.png and /dev/null differ
diff --git a/portal/static/img/testbeds/wall2.ilabt.iminds.be.png b/portal/static/img/testbeds/wall2.ilabt.iminds.be.png
new file mode 100644 (file)
index 0000000..4ce8035
Binary files /dev/null and b/portal/static/img/testbeds/wall2.ilabt.iminds.be.png differ
index 481e947..a74132e 100644 (file)
@@ -19,13 +19,13 @@ function getKeySplitId(id,separator){
 if ( typeof String.prototype.startsWith != 'function' ) {
   String.prototype.startsWith = function( str ) {
     return this.substring( 0, str.length ) === str;
-  }
+  };
 };
 
 if ( typeof String.prototype.endsWith != 'function' ) {
   String.prototype.endsWith = function( str ) {
     return this.substring( this.length - str.length, this.length ) === str;
-  }
+  };
 };
 // http://stackoverflow.com/questions/646628/javascript-startswith
 
@@ -58,15 +58,19 @@ jQuery.fn.spin = function(opts) {
 // FROM Triptych : http://stackoverflow.com/users/43089/triptych
 // http://stackoverflow.com/questions/979256/how-to-sort-an-array-of-javascript-objects
 // data.sort(sort_by('city', false, function(a){return a.toUpperCase()}));
-var sort_by = function(field, reverse, primer){
+var sort_by = function(field, reverse, primer) {
 
-   var key = function (x) {return primer ? primer(x[field]) : x[field]};
+   var key = function(x) { return primer ? primer(x[field]) : x[field]; };
    //var key = primer ? function (x) { return primer(x[field]); } : function (x) { return x[field]; }
    
-   return function (a,b) {
+   return function(a,b) {
        var A = key(a), B = key(b);
        return (A < B ? -1 : (A > B ? 1 : 0)) * [1,-1][+!!reverse];
        //return ((A < B) ? -1 :
        //        (A > B) ? +1 : 0)) * [-1,1][+!!reverse];                  
-   }
+   };
+};
+
+function escapeRegExp(str) {
+  return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
 }
index da0cacf..1545263 100644 (file)
@@ -1,3 +1,17 @@
+function unspin_all(){
+    $('input:checkbox').each(function (index) {
+        if(this.checked){
+            this.nextElementSibling.style.display = "none";
+        }
+    });
+}
+function spin_all(){
+    $('input:checkbox').each(function (index) {
+        if(this.checked){
+            this.nextElementSibling.style.display = "inline";
+        }
+    });
+}
 $(document).ready(function() {
        loadedTabs = [];
        
@@ -17,6 +31,7 @@ $(document).ready(function() {
        });
 
     $('button#deleteusers').click(function() {
+        spin_all();
         $('input:checkbox.user').each(function (index) {
             if(this.checked){
                 var record_id = this.id;
@@ -40,6 +55,7 @@ $(document).ready(function() {
                         mysliceAlert('Rest Error for: '+data.error,'warning', true);
                         //alert("Rest Error for "+record_id+": "+data.error);
                     }   
+                    unspin_all();
                 });
             } 
         });
@@ -47,10 +63,12 @@ $(document).ready(function() {
 
     /* TODO: factorize into functions */
     $('button#deleteslices').click(function() {
+        spin_all();
         var flag = false;
         $('input:checkbox.slice').each(function (index) {
             if(this.checked){
                 var record_id = this.id;
+                $('#'+record_id+'-loading').spin();
                 $.post("/delete/slice/",{'filters':{'slice_hrn':this.id}}, function(data) {
                     if(data.success){
                         localStorage.clear();
@@ -61,11 +79,13 @@ $(document).ready(function() {
                         mysliceAlert('Rest Error for: '+data.error,'warning', true);
                         //alert("Rest Error for "+record_id+": "+data.error);
                     }
+                    unspin_all();
                 });
             }
         });
     });
     $('button#renewslices').click(function() {
+        spin_all();
         var now = new Date();
         /* In Javascript getMonth() gives month[0] = january, month[1] = february, and so on...  */
         var month = now.getMonth()+2;
@@ -73,6 +93,7 @@ $(document).ready(function() {
         $('input:checkbox.slice').each(function (index) {
             if(this.checked){
                 var record_id = this.id;
+                $('#'+record_id+'-loading').spin();
                 $.post("/update/slice/",{'filters':{'slice_hrn':this.id},'params':{'expires':one_month_later}}, function(data) {
                     if(data.success){
                         // TODO: highlight row after success
@@ -82,6 +103,7 @@ $(document).ready(function() {
                         mysliceAlert('Rest Error for: '+data.error,'warning', true);
                         //alert("Rest Error for "+record_id+": "+data.error);
                     }
+                    unspin_all();
                 });
                 
             }
@@ -90,10 +112,12 @@ $(document).ready(function() {
         //window.location="/portal/institution#slices";
     });
     $('button#deleteprojects').click(function() {
+        spin_all();
         var flag = false;
         $('input:checkbox.project').each(function (index) {
             if(this.checked){
                 var record_id = this.id;
+                $('#'+record_id+'-loading').spin();
                 console.log(record_id);
                 $.post("/delete/myslice:authority/",{'filters':{'authority_hrn':this.id}}, function(data) {
                     if(data.success){
@@ -105,6 +129,7 @@ $(document).ready(function() {
                         mysliceAlert('Rest Error for: '+data.error,'warning', true);
                         //alert("Rest Error for "+record_id+": "+data.error);
                     }
+                    unspin_all();
                 });
             }
         });
index f98427e..026321f 100644 (file)
@@ -136,7 +136,7 @@ jQuery(document).ready(function(){
                       jQuery("#upload_file").click(function(){
 
                               jQuery("#span_upload").show();
-                              jQuery("#dl_file").hide();
+                              jQuery("#dl_pubkey").hide();
                               jQuery("#upload_file").hide();
                               jQuery("#keyval").hide();
                               // enforcing when one edit is clicked the rest will not work at same time
@@ -157,7 +157,7 @@ jQuery(document).ready(function(){
 
                               jQuery("#span_upload").hide();
                               jQuery("#keyval").show();
-                              jQuery("#dl_file").show();
+                              jQuery("#dl_pubkey").show();
                               jQuery("#upload_file").show();
                       });
                   });
index 548d5da..d97d6b0 100644 (file)
@@ -107,7 +107,7 @@ user.prototype.list = function() {
 var myslice = {
        user: {},
        
-       user: function() {
+       get_user: function() {
                if ($.isEmptyObject(this.user)) {
                        //this.login(function() { return this.user; });
             if(localStorage.getItem('user')!='undefined'){
@@ -120,7 +120,7 @@ var myslice = {
        },
        projects: {},
        
-       projects: function() {
+       get_projects: function() {
                if ($.isEmptyObject(this.projects)) {
                        //this.login(function() { return this.user; });
             if(localStorage.getItem('projects')!='undefined'){
@@ -186,7 +186,6 @@ var myslice = {
                             // What are the projects under this authority?
                             $.post("/rest/myslice:authority/",{'fields':['authority_hrn'],'filters':{'authority_hrn':'CONTAINS'+auth}}, function( data ) {
                                        $.each(data, function(idx, project) {
-                                    console.log(project.authority_hrn);
                                     if($.inArray(project.authority_hrn,projects) == -1){
                                         projects.push(project.authority_hrn);
                                     }
@@ -201,14 +200,16 @@ var myslice = {
                     if(isFunction(fn)){
                         fn();
                     }
+                }else{
+                    $('#credentials_msg').css('display','block');
                 }
                    });
         }else{
+            $('#credentials_msg').css('display','block');
             if(isFunction(fn)){
                 fn();
             }
         }
-
        },
 
 
diff --git a/portal/static/js/requests.js b/portal/static/js/requests.js
new file mode 100644 (file)
index 0000000..09535a7
--- /dev/null
@@ -0,0 +1,105 @@
+function unspin_all_status(){
+    $('.portal__validate__checkbox').each(function (index) {
+        if(this.checked){
+            t_id = this.id.split('__');
+            status_id = t_id[t_id.length-2]+'__'+t_id[t_id.length-1]+'-status-loading';
+            $('#'+status_id).css('display','none');    
+        }
+    });
+}
+function spin_all_status(){
+    $('.portal__validate__checkbox').each(function (index) {
+        if(this.checked){
+            t_id = this.id.split('__');
+            status_id = t_id[t_id.length-2]+'__'+t_id[t_id.length-1]+'-status-loading';
+            $('#'+status_id).css('display','inline');
+        }
+    });
+}
+       $(document).ready(function() {
+               $("li#nav-request").addClass("active");
+               $('table.requests').dataTable({
+                   "sDom": "frtiS",
+            "bScrollCollapse": true,
+            "bStateSave": true,
+            "bPaginate": false,
+            "bLengthChange": false,
+            "bFilter": false,
+            "bSort": true,
+            "bInfo": false,
+            "bAutoWidth": true,
+            "bAutoHeight": false,
+               });
+       });
+       function on_click_event() {
+               var ids = []; 
+               $('.portal__validate__checkbox').each(function(i, el) {
+                       if ($(el).prop('checked')) {
+                               // portal__validate__checkbox__slice__2
+                               var id_array = $(el).attr('id').split('__');
+                               // push(slice__2)
+                               ids.push(id_array[3] + '__' + id_array[4]);
+                       }
+               });
+               if (ids.length > 0) {
+            spin_all_status();
+                       var id_str = ids.join('/');
+
+                       // XXX spinner
+                       $.getJSON('/portal/validate_action/' + id_str, function(status) {
+                               $.each(status, function(request_type__id, request_status) {
+                                       // request_status: NAME -> dict (status, description)
+                                       var status_str = '';
+                                       $.each(request_status, function(name, result) {
+                                               if (status_str != '')
+                                                       status_str += ' -- ';
+
+                                               if (result.status) {
+                                                       status_str += '<font color="green">OK</font>';
+                                                       $('#portal__validate__checkbox__' + request_type__id).hide();
+                                               } else {
+                                                       status_str += '<font color="red">ERROR: ' + result.description + '</font>';
+                                               }
+                                       });
+                                       $('#portal__status__' + request_type__id).html(status_str);
+                               });
+                unspin_all_status();
+                       });
+               }
+       }
+       function on_click_reject() {
+               var ids = []; 
+               $('.portal__validate__checkbox').each(function(i, el) {
+                       if ($(el).prop('checked')) {
+                               // portal__validate__checkbox__slice__2
+                               var id_array = $(el).attr('id').split('__');
+                               // push(slice__2)
+                               ids.push(id_array[3] + '__' + id_array[4]);
+                       }
+               });
+               if (ids.length > 0) {
+            spin_all_status();
+                       var id_str = ids.join('/');
+
+                       // XXX spinner
+                       $.getJSON('/portal/reject_action/' + id_str, function(status) {
+                               $.each(status, function(request_type__id, request_status) {
+                                       // request_status: NAME -> dict (status, description)
+                                       var status_str = '';
+                                       $.each(request_status, function(name, result) {
+                                               if (status_str != '')
+                                                       status_str += ' -- ';
+
+                                               if (result.status) {
+                                                       status_str += '<font color="green">Rejected</font>';
+                                                       $('#portal__validate__checkbox__' + request_type__id).hide();
+                                               } else {
+                                                       status_str += '<font color="red">ERROR: ' + result.description + '</font>';
+                                               }
+                                       });
+                                       $('#portal__status__' + request_type__id).html(status_str);
+                               });
+                unspin_all_status();
+                       });
+               }
+       }
index 80653e8..23bcf76 100644 (file)
@@ -31,24 +31,6 @@ class SupportView (FreeAccessView, ThemeView):
 
         if request.user.is_authenticated(): 
             env['person'] = self.request.user
-            ## check user is pi or not
-            platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
-            account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config')
-            platform_details = execute_query(self.request, platform_query)
-            account_details = execute_query(self.request, account_query)
-            for platform_detail in platform_details:
-                for account_detail in account_details:
-                    if platform_detail['platform_id'] == account_detail['platform_id']:
-                        if 'config' in account_detail and account_detail['config'] is not '':
-                            account_config = json.loads(account_detail['config'])
-                            if 'myslice' in platform_detail['platform']:
-                                acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
-            # assigning values
-            if acc_auth_cred == {} or acc_auth_cred == 'N/A':
-                pi = "is_not_pi"
-            else:
-                pi = "is_pi"
-            env['pi'] = pi
         else: 
             env['person'] = None
     
@@ -60,6 +42,6 @@ class SupportView (FreeAccessView, ThemeView):
         if state: env['state'] = state
         elif not env['username']: env['state'] = None
         # use one or two columns for the layout - not logged in users will see the login prompt
-
+        env['request'] = request
         return render_to_response(self.template, env, context_instance=RequestContext(request))
 
index cb7af4f..6a7ab7a 100644 (file)
        $(document).ready(function() {
                $.get('/monitor/services', function(result) {
                        for (var r in result) {
-                               html = '<div class="col-xs-6 col-sm-4 col-md-3 s-monitor"><div class="row">';
-                               html += '<div class="col-md-2"><img src="{{ STATIC_URL }}icons/'+result[r].status+'.png"></div>';
-                               html += '<div class="col-md-8">';
-                               html += '<h4>'+result[r].name+'<h4>';
-                               html += '<span class="subtitle">'+result[r].type+'</span>';
-                               if (typeof(result[r].version) != 'undefined')
-                                       html += ' <span class="version">version '+result[r].version+'</span>';
-                               html += '</div></div></div>';
+                if(r == 'error'){
+                    html = '<div style="padding-left:20px;">no monitoring available</div>'
+                }else{
+                                   html = '<div class="col-xs-6 col-sm-4 col-md-3 s-monitor"><div class="row">';
+                                   html += '<div class="col-md-2"><img src="{{ STATIC_URL }}icons/'+result[r].status+'.png"></div>';
+                                   html += '<div class="col-md-8">';
+                                   html += '<h4>'+result[r].name+'<h4>';
+                                   html += '<span class="subtitle">'+result[r].type+'</span>';
+                                   if (typeof(result[r].version) != 'undefined')
+                                       html += ' <span class="version">version '+result[r].version+'</span>';
+                                   html += '</div></div></div>';
+                }
                                $('div#monitor-services').append(html);
                        }
                });
index 668c3d3..320642f 100644 (file)
@@ -19,9 +19,9 @@
                                                        </ul>
                                        </div>
                                </li>
-                               {%if 'is_pi'  in pi %}  
+                {% if request.session.user.pi %}
                                <li id="nav-institution" class=""><a href="/institution">MANAGEMENT</a></li>
-                                {%endif%}
+                               {%endif%}
                                <li><a href="/support/">SUPPORT</a></li>
                        </ul>
                </div>
index 9c6eb1b..5a1248c 100644 (file)
@@ -1,6 +1,7 @@
 {% load portal_filters %}
 {# This is required by insert_above #}{% insert_handler %}<!DOCTYPE html>
-<html lang="en"><head>
+<html lang="en">
+<head>
 <title>{{theme}} portal - {{ section }}</title>
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 
 <script src="{{ STATIC_URL }}js/jquery.dataTables.min.js"></script>
 <script src="{{ STATIC_URL }}js/jquery.qtip.min.js"></script>
 <script src="{{ STATIC_URL }}js/bootstrap.datatables.js"></script>
-<!-- <script src="{{ STATIC_URL }}js/stash.min.js"></script> -->
+<script src="{{ STATIC_URL }}js/common.functions.js"></script>
 <script src="{{ STATIC_URL }}js/myslice.js"></script>
 <script src="{{ STATIC_URL }}js/myslice-ui.js"></script>
+
+<script type="text/javascript" src="{{STATIC_URL}}/js/spin-presets.js"></script>
+<script type="text/javascript" src="{{STATIC_URL}}/js/spin.min.js"></script>
+<script type="text/javascript" src="{{STATIC_URL}}/js/jquery.spin.js"></script>
+
 <style type="text/css">{# In case we need to add raw css code #}{% container prelude_css %}</style>
 {{ header_prelude }}
 {% block head %} {% endblock head %}
@@ -60,7 +66,7 @@ This list of slices should go into SESSION !
 $(document).ready(function() {
 {% if username %}
     myslice.login(function(){
-        user = myslice.user();
+        user = myslice.get_user();
 
         var slices = [];
         if($.isEmptyObject(user)){
@@ -70,12 +76,15 @@ $(document).ready(function() {
             slices.push("no slice");
         }else{
             slices = user.slices;
+            {% if theme != "fed4fire" %}
             drawSlices(slices);
+            {% endif %}
         }
         {% if theme == "fed4fire" %}
-        p = myslice.projects();
+        p = myslice.get_projects();
         if(p != null){
-            drawProjects(p);
+            //drawProjects(p);
+            drawProjectsTree(p,slices);
         }
         {% endif %}
     });
@@ -100,6 +109,32 @@ $(document).ready(function() {
         $("div#home-project-list").html($( "<ul/>", { html: items.join( "" ) }));
         $("ul#dropdown-project-list").append(items.join( "" ));
     }
+    function drawProjectsTree(projects,slices) {
+        var items = [];
+        var items_sl = [];
+        $.each( projects, function(i, p) {
+            $.each( slices, function(y, s) {
+                if (s.match('^' + escapeRegExp(p))) {
+                     items_sl.push( "<li><a href=\"/resources/" + s + "\">" + s.replace(p + '.','') + "</a></li>" );
+                }
+            });
+            el = "<li><a href=\"/portal/project/" + p + "\">" + p + "</a>";
+            if (items_sl.length > 0) {
+                el += "<ul>" + items_sl.join( "" ) + "</ul>";
+            }
+            el += "</li>";
+            items.push(el);
+            items_sl = [];
+        });
+        $("div#home-project-tree").html($( "<ul/>", { html: items.join( "" ) }));
+        if (projects.length > 0) {
+            $('.dashboard-create-slice').show();
+        }
+    }
+    
+    window.setTimeout(function() {
+        $('.projects-loading').hide();
+    },20000);
     {% endif %}
 {% endif %}
        jQuery('[title!=""]').qtip();
index 985974f..b71f3da 100644 (file)
@@ -33,7 +33,6 @@
                <ul class="nav nav-tabs nav-section">
                        <li class="active"><a href="#profile">User Profile</a></li>
                        <li><a href="#account">Account</a></li>
-                       <li><a href="#access">Testbed Access</a></li>
                </ul>
     </div>
 </div>
                        {%endif%}
                </div>
        </div>
-
-
-       <div class="tab-pane row" id="access">
-               <div class="col-md-12">
-       
-               <h3>Testbed Access <small>Reference Accounts in the following testbeds</small></h3>
-        <table class="mytable table table-bordered table-hover"> 
-            <tr class="odd"> 
-                <th>Platform</th> 
-                <th>Account Type</th>
-                               <th>Reference to</th>
-                               <th>Remove Account</th>
-            </tr>   
-            {% for row in ref_acc %}         
-            <tr class="border_bottom">
-                <td class="odd"> {{ row.platform_name }} </td>
-                <td class="odd"> {{ row.account_type }} </td>
-                               <td class="odd"> {{ row.account_reference }} </td>
-                               <td class="odd">
-                               <button class="btn btn-danger" name="delete_{{row.platform_name}}" type="submit" title="Delete account from this platform" onclick="javascript:document.getElementById('button_value').value='delete_{{row.platform_name}}';">
-                                               <span class="glyphicon glyphicon-minus"></span>
-                                       </button>
-                               </td>
-            </tr> 
-            {%endfor%}               
-        </table>               
-               
-               
-               <h3>Add reference account to the following testbeds</h3>
-        <table class="mytable table table-bordered table-hover"> 
-            <tr class="odd"> 
-                <th>Platforms</th> 
-                <th>Add Account</th>
-            </tr>   
-            {% for platform in platform_list %}         
-            <tr class="border_bottom">
-                <td class="odd"> {{ platform.platform_no_access }} </td>
-                <td class="odd">
-                                       <button class="btn btn-success btn-sm" name= "add_{{platform.platform_no_access}}" type="submit" title="Add account to this platform" onclick="javascript:document.getElementById('button_value').value='add_{{platform.platform_no_access}}';">
-                                               <span class="glyphicon glyphicon-plus"></span>
-                                       </button>
-                               </td>
-            </tr> 
-            {%endfor%}               
-        </table>
-       </div>
 {%endif%} 
 </div>
-</div>
 
 </form>
 <script>
index 4ad469b..e1fa009 100644 (file)
@@ -1,4 +1,4 @@
-<img src="http://doc.fed4fire.eu/_static/fed4fire-logo.jpg">
+<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png" width="80px">
 <br>
 <p>We have received a user signup request for your email address at {{current_site}}</p>
 <p>You have the following user details:</p>
index 6330475..74ca3da 100644 (file)
@@ -1,4 +1,4 @@
-<img src="http://doc.fed4fire.eu/_static/fed4fire-logo.jpg">
+<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png" width="80px">
 <br>
 <b>Email        :</b> {{email}}
 
index 5d632b6..ba48951 100644 (file)
 {% widget '_widget-news.html' %}
 </div> -->
 {% if username %}
+
+{% block head %} 
+<script type="text/javascript" src="https://java.com/js/dtjava.js"></script>
+{% endblock head %}
+
 {% widget "_widget-no_credentials.html" %}
 <div class="container dashboard">
        <div class="row">
+           <div class="col-md-12" id="credentials_msg" style="display:none;">
        {%if 'no_creds'  in user_cred %}
        <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">NO CREDENTIALS</a> are delegated to the portal!</p>
        {%endif%}
        {%if 'creds_expired'  in user_cred %}
        <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">EXPIRED CREDENTIALS</a> Please delegate again your credentials to the portal!</p>
     {%endif%}
-               <div class="col-md-3">
-                       <h3>
-                               EXPERIMENT
-                       </h3>
-                       <div>
-                               <a href="#"><img src="{{ STATIC_URL }}img/icon_slices.png" alt="" /></a>
-                       </div>
-                       <div>
-                               <button id="slicerequestbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Create Slice</button>
-                       </div>
-                       <div>
-                               <p><strong>Your slices </strong>
-                                       <span title="A slice is a set of testbed resources on which you can conduct an experiment. 
-                                       Either ask your colleagues to give you access to an existing slice or request a new slice by clicking 'Request Slice'. 
-                                       However, on the Fed4FIRE portal, you will only see slices that you have created through Fed4FIRE. If you have created slices elsewhere, 
-                                       those slices will not appear here."
-                                       class="glyphicon glyphicon-info-sign">
-                               </span>
-
-                               </p>
-                       </div>
-                       <div>   
-                               <div id="home-slice-list"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
-                       </div>
-                       <h3 title="Some tools do their own slice creation and management.">Experiment now</h3>
-                       <a class="btn btn-primary" style="width: 150px;" 
-                    href='http://jfed.iminds.be/releases/5.4-dev/r2289/webstart/experimenter/jfed-experimenter.jnlp'
-                                       title="Click here to start your experiment with jFed" 
-                                       onclick="return  launchApplication('http://jfed.iminds.be/releases/5.4-dev/r2289/webstart/experimenter/jfed-experimenter.jnlp');">
-                    <span class="glyphicon glyphicon-cloud"></span> jFed</a>
-               </div>
-               <div class="col-md-3">
-                       <h3>MANAGEMENT</h3>
-                       <div>
-                               <a href="/portal/institution"><img src="{{ STATIC_URL }}img/icon_authority_color.png" alt="" /></a>
-                       </div>
-                       <div>
-                               <button id="projectrequestbtn" type="button" class="btn btn-default" style="width:165px;"><span class="glyphicon glyphicon-plus"></span> Join Project</button>
-                       </div>
-                       <div>
-                               <button id="validaterequestbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-ok"></span> Validate Requests</button>
-                       </div>
-                       <div>
-                               <p><strong>Your projects </strong>
-                                       <span title="A project is a sub-authority under the responsability of your institution gathering users, who will be able to create slices for their experiments."
-                                       class="glyphicon glyphicon-info-sign">
-                               </span>
-                               </p>
-                       </div>
-                       <div>   
-                               <div id="home-project-list"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading projects" /></div>
-                       </div>
-
-               </div>
-               <div class="col-md-3">
-                       <h3>
-                               SUPPORT
-                       </h3>
-                       <div>
-                               <a href="/portal/support"><img src="{{ STATIC_URL }}img/icon_support.png" alt="" /></a>
-                       </div>
-                       <div>
-                               <button id="ticketbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-envelope"></span> Contact</button>
-                       </div>
-                       <p></p>
-                       <div>
-                       <button id="statbtn" type="button" style="width: 170px;" class="btn btn-default"><span class="glyphicon glyphicon-stats" style="margin-right: 10px;"></span>Testbeds' status</button>
-                       </div>
-                       <div>
-                       <button id="repbtn" type="button" style="width: 170px;" class="btn btn-default"><span class="glyphicon glyphicon-stats"></span>Testbeds' reputation</button>
-                       </div>
-               </div>
-               
-               <div class="col-md-3">
-                       <h3>
-                               ACCOUNT
-                       </h3>
-                       <div>
-                               <a href="/portal/account/"><img src="{{ STATIC_URL }}img/icon_user_color.png" alt="" /></a>
-                       </div>
-                       <div>
-                               <button id="logoutbtn" type="button" class="btn btn-default" data-username="{{ username }}"><span class="glyphicon glyphicon-off"></span> Logout</button>
-                       </div>
-                       <div>
-                               {% if person.last_name %}
-                                       {{person.first_name}} {{person.last_name}}<br />
-                               {% endif %}
-                       <span class="label">Username:</span> <a href='/portal/account/' title="Click here to see and edit your account details.">{{person.email}}</a>
-               </div>
-               </div>
-       </div>
+        </div>
+    </div>
+    <div class="row">
+        <div class="col-sm-4">
+            <h3>
+                <img src="{{ STATIC_URL }}img/icon_slices_small.png" alt="" />EXPERIMENT
+            </h3>
+            <div>
+                <span class="glyphicon glyphicon-cog"></span> <a href="/portal/project_request/">Create/Join project</a>
+            </div>
+            <div class="dashboard-create-slice">
+                <span class="glyphicon glyphicon-plus"></span> <a href="/portal/slice_request/">Create slice</a>
+            </div>
+            <div class="projects-tree">
+                Your projects and slices
+                <span title="A <b>slice</b> is a set of testbed resources on which you can conduct an experiment. 
+                Either ask your colleagues to give you access to an existing slice or request a new slice by clicking 'Request Slice'. 
+                However, on the Fed4FIRE portal, you will only see slices that you have created through Fed4FIRE. If you have created slices elsewhere, 
+                those slices will not appear here. <br /><br /> A <b>project</b> is a sub-authority under the responsability of your institution gathering users, 
+                who will be able to create slices for their experiments." class="glyphicon glyphicon-info-sign">&nbsp;</span> 
+             
+                <div id="home-project-tree"><img class="projects-loading" src="{{ STATIC_URL }}img/loading.gif" alt="Loading projects" /></div>
+            </div>
+                        
+            <div class="experiment-tools">
+                <h4 title="Some tools do their own slice creation and management.">Experiment now</h4>
+                
+                <p class="jfed">
+                    <button id="start" class="btn btn-primary" type="button" onclick="launchjFed()"><span class="glyphicon glyphicon-cloud"></span> Start jFed</button>
+                </p>
+                <div id='java7Dialog' title="Old Java version detected" >
+                <p>The latest version of jFed is only compatible with Java 8 or higher. We detected that you are using an older version.</p>
+                <p>Please upgrade to Java 8 to get access to the newest version of jFed. Otherwise, you can use jFed 5.3.2, which is Java 7-compatible.</p>
+                </div>
+                
+                <div id='noJavaDialog' title="No Java detected" >
+                <p>jFed requires Java to run. We however couldn't detect a Java installation in your browser.</p>
+                <p>Please install the latest version of Java to continue.</p>
+                </div>
 
+            </div>
+        </div>
+        <div class="col-sm-4">
+            <div class="row">
+                <div class="col-sm-12">
+                    <h3>
+                        <a href="/portal/account/"><img src="{{ STATIC_URL }}img/icon_user_small.png" alt="" /></a><a href="/portal/account/">ACCOUNT</a>
+                    </h3>
+                    {% if person.last_name %}
+                    <p>
+                        {{person.first_name}} {{person.last_name}}
+                    </p>
+                    {% endif %}
+                    <p>
+                        <span class="glyphicon glyphicon-user"></span> <a href='/portal/account/' title="Click here to see and edit your account details.">{{person.email}}</a>
+                    </p>
+                </div>
+            </div>
+            <div class="row">
+                <div class="col-sm-12">
+                    <h3>
+                        <a href="/portal/institution"><img src="{{ STATIC_URL }}img/icon_authority_color_small.png" alt="" /></a><a href="/portal/institution">MANAGEMENT</a>
+                    </h3>
+                   
+                    <div>
+                        <span class="glyphicon glyphicon-ok"></span> <a href="/portal/institution#requests">Validate Requests</a>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="col-sm-4">
+            <div class="row">
+                <div class="col-sm-12">
+                    <h3>
+                        <a href="/portal/support"><img src="{{ STATIC_URL }}img/icon_support_small.png" alt="" /></a><a href="/portal/support">SUPPORT</a>
+                    </h3>
+                    <p>
+                        <span class="glyphicon glyphicon-envelope"></span> <a href="/portal/contact/">Contact</a>
+                    </p>
+                    <p>
+                        <span class="glyphicon glyphicon-stats"></span> <a target="_blank" href="https://flsmonitor.fed4fire.eu">Testbeds' status</a>
+                        </br />
+                        <span class="glyphicon glyphicon-stats"></span> <a href="/portal/reputation">Testbeds' reputation</a>
+                        
+                    </p>
+                    <p>
+                        <span class="glyphicon glyphicon-book"></span> <a target="_blank" href="http://doc.fed4fire.eu/">Documentation</a>
+                    </p>
+                </div>
+            </div>            
+        </div>
+    </div>
 </div>
 {% else %}
-<div class="container-fluid home">
+<div class="container home">
        <div class="">
-               <div class="col-sm-2"></div>
-               <div class="col-sm-4 slogan">
-                       <h2>
+               <div class="col-sm-4 col-sm-offset-1 slogan">
+                       <h1>
                                Fed4FIRE Portal
-                       </h2>
+                       </h1>
                        <h3>
-                               Your easy access to Future Internet Research and Experimentation testbeds belonging to the Fed4FIRE federation.
+                               Your easy access to Future Internet Research and Experimentation testbeds belonging to the 
+                               <a target="_blank" href="http://www.fed4fire.eu/">Fed4FIRE</a> federation.
                        </h3>
-                       <h3>
+                       <br />
+                       <h4>
                                 <a href='http://doc.fed4fire.eu'>Want to learn more?</a>
-                       </h3>
+                       </h4>
                </div>
                <div class="col-sm-4 col-sm-offset-1" style="width:400px; top:16px; float:left;">
                        <div class="row">
                                {% widget '_widget-login-user.html' %}
                        </div>
                </div>
-               <div class="col-sm-1"></div>
        </div>
 </div>
+
+<script type="text/javascript">
+       $(document).ready(function() {
+        localStorage.clear();
+    });
+</script>
+
 {% endif %}
 
 
 <script type="text/javascript">
+   var config = {
+       java8_jnlp: 'http://jfed.iminds.be/jfed-f4f-java8.jnlp',
+       java7_jnlp: 'http://jfed.iminds.be/jfed-f4f-java7.jnlp'
+   };
+
+   var certkey = "{{jfed_identity}}";
+
        $(document).ready(function() {
            {%if 'no_creds' in user_cred or 'creds_expired' in user_cred %}
         localStorage.clear();
+        /*
         $.post("/cache/clear/", function( data ) {
         });
+        */
         {% endif %}
                $('a.home-tab').click(function() {
                        $('ul.nav-tabs li').removeClass('active');
                        $('div.home-panel').hide();
                        $('div#'+$(this).data('panel')).show();
                });
-               $('button#validaterequestbtn').click(function() {
-                       window.location="/portal/institution#requests";
-               });
-               $('button#ticketbtn').click(function() {
-                       window.location="/portal/contact/";
-               });
-               $('button#statbtn').click(function() {
-               window.location="https://flsmonitor.fed4fire.eu";
-               });
-                $('button#repbtn').click(function() {
-               window.location="/portal/reputation";
-                });
-               $('button#signupbtn').click(function() {
-                       window.location="/portal/register/";
-               });
-               $('button#slicerequestbtn').click(function() {
-                       window.location="/portal/slice_request/";
-               });
-               $('button#projectrequestbtn').click(function() {
-                       window.location="/portal/project_request/";
-               });
-
-        myslice.loadSlices();
-});
-</script>
-
-<!--for jfed tool-->
-<script type="text/javascript" src="{{STATIC_URL}}js/fed4fire_dtjava_orig.js"></script>
-<script>
-       function launchApplication(jnlpfile) {
-       dtjava.launch(
-               { url : jnlpfile },
-            {
-               javafx : '2.2+',
-                toolkit: 'swing'
-               },
-                {}
-        );
-        return false;
-     }
+               
+    });
 </script>
-{# widget "_widget-monitor.html" #}
-{# widget "_widget-stats-top-slices.html" #}
-
+<script src='https://authority.ilabt.iminds.be/js/jquery/jquery-ui.min.js'></script>
+<script src="//java.com/js/dtjava.js"></script>
+<script src='https://authority.ilabt.iminds.be/js/jfed_webstart_f4fportal.js'></script>
+<link rel='stylesheet' href='https://authority.ilabt.iminds.be/js/jquery/jquery-ui.css' />
 {% endblock %}
index 7e9c176..facc118 100644 (file)
@@ -2,6 +2,7 @@
 
 {% block head %} 
 <script type="text/javascript" src="{{STATIC_URL}}/js/institution.js"></script>
+<script type="text/javascript" src="{{STATIC_URL}}js/requests.js"></script>
 {% endblock head %}
 
 {% block content %}
@@ -26,8 +27,9 @@
                                <li><a href="#users">Users</a></li>
                 {% if not project %}
                                <li><a href="#projects">Projects</a></li>
-                {% endif %}
+                {% else %}
                                <li><a href="#slices">Slices</a></li>
+                {% endif %}
                                <li><a href="#requests">Requests</a></li>
                        </ul>
            </div>
@@ -42,7 +44,7 @@
        
        <div class="tab-pane row" id="users" data-authority="{{user_details.parent_authority}}">
                <div class="col-md-12 el">
-                       <div id="user-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
+                       <div id="user-tab-loading" style="padding-bottom:10px;"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
                                <div id="user-tab-loaded" style="display:none;">
                                <table id="user-tab" class="table">
                                        <tr>
@@ -77,7 +79,7 @@
     {% if not project %}
        <div class="tab-pane row" id="projects" data-authority="{{user_details.parent_authority}}">
                <div class="col-md-12 el">
-                       <div id="project-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Projects" /></div>
+                       <div id="project-tab-loading" style="padding-bottom:10px;"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Projects" /></div>
                                <div id="project-tab-loaded" style="display:none;">
                                <table id="project-tab" class="table">
                                        <tr>
    {% endif %}
        <div class="tab-pane row" id="slices">
                <div class="col-md-12 el">
-           <div id="slice-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
+           <div id="slice-tab-loading" style="padding-bottom:10px;"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
            <div id="slice-tab-loaded" style="display:none;">
                <table id="slice-tab" class="table">
                    <tr>
           </div>
        </div>
        <div class="tab-pane row" id="requests">
+        <div id="spinner" style="padding-top:40px; padding-left:40px;"></div>
        </div>
 </div>
 <script>
 $(document).ready(function() {
     {% if person %}
     {% if user_details.parent_authority %}
-
+        $('#spinner').spin();
+        
         $.post("/rest/myslice:slice/",{'fields':['slice_hrn','users','url','slice_date_created'],'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
             var list_slices = [];
             var table_slices = [];
@@ -143,7 +147,6 @@ $(document).ready(function() {
                 }else{
                     nodes_length=val.nodes.length;
                 }
-                //console.log(val);
                 if(val.users=="undefined" || val.users==null){
                     users_length=0;
                 }else{
@@ -157,7 +160,7 @@ $(document).ready(function() {
                 }
                 
                 slice_row = "<tr id='"+val.slice_hrn+"'>";
-                slice_row += "<td><input type='checkbox' class='slice' id='"+val.slice_hrn+"'></td>";
+                slice_row += "<td><input type='checkbox' class='slice' id='"+val.slice_hrn+"'><div id='"+val.slice_hrn+"-loading' style='display:none;padding-left:3px;'><img src='{{ STATIC_URL }}img/loading.gif'></div></td>";
 
                 // filter links to slices, only those that the user has credentials for
                 s = myslice.user.slices;
@@ -186,9 +189,8 @@ $(document).ready(function() {
            
             var table_users = [];
             $.each( data[0].pi_users, function( key, val ) {
-                //console.log(val);
                 user_row = "<tr id='"+val+"'>";
-                user_row += "<td><input type='checkbox' class='user' id='"+val+"'></td>";
+                user_row += "<td><input type='checkbox' class='user' id='"+val+"'><div id='"+val+"-loading' style='display:none;padding-left:3px;'><img src='{{ STATIC_URL }}img/loading.gif'></div></td>";
                 user_row += "<td>"+val+"</td>";
                 user_row += "</tr>";
                 table_users.push(user_row);
@@ -209,7 +211,7 @@ $(document).ready(function() {
             $.each( data, function( key, val ) {
                 list_users.push( "<li><a href=\"portal/user/"+val.user_email+"\">" + val.user_email + "</a></li>" );
                 user_row = "<tr id='"+val.user_hrn+"'>";
-                user_row += "<td><input type='checkbox' class='user' id='"+val.user_hrn+"' data-email='"+val.user_email+"'></td>";
+                user_row += "<td><input type='checkbox' class='user' id='"+val.user_hrn+"' data-email='"+val.user_email+"'><div id='"+val.user_hrn+"-loading' style='display:none;padding-left:3px;'><img src='{{ STATIC_URL }}img/loading.gif'></div></td>";
                 user_row += "<td>"+val.user_email+"</td>";
                 user_row += "<td>"+val.user_hrn+"</td>";
                 /*
@@ -228,9 +230,8 @@ $(document).ready(function() {
            
             var table_projects = [];
             $.each( data, function( key, val ) {
-                console.log(val);
                 project_row = "<tr id='"+val.authority_hrn+"'>";
-                project_row += "<td><input type='checkbox' class='project' id='"+val.authority_hrn+"'></td>";
+                project_row += "<td><input type='checkbox' class='project' id='"+val.authority_hrn+"'><div id='"+val.authority_hrn+"-loading' style='display:none;padding-left:3px;'><img src='{{ STATIC_URL }}img/loading.gif'></div></td>";
 
                 // filter links to projects, only those that the user has credentials for
                 p = myslice.projects;
@@ -273,11 +274,10 @@ $(document).ready(function() {
        } else {
                $('.nav-tabs a[href=#about]').click();
        }
-});
 
-//upgrade users to PI
-$(document).ready(function() {
+    //upgrade users to PI
     $('button#makepi').click(function() {
+        spin_all();
         var flag = false;
         var pi_users = [];
         $.post("/rest/myslice:authority/",{'filters':{'authority_hrn': '{{user_details.parent_authority}}'}}, function( data ) {
@@ -286,6 +286,8 @@ $(document).ready(function() {
                 if(this.checked){
                     var record_id = this.id;
                     pi_users.push(record_id)
+                    $.post("/credentials/clear/",{'emails':[this.dataset['email']]}, function(data) {
+                    }); // post credentials clear
                     flag = true;                
                 }
             });
@@ -297,14 +299,14 @@ $(document).ready(function() {
                         mysliceAlert('Rest Error for: '+data.error,'warning', true);
                         //alert("Rest Error for "+record_id+": "+data.error);
                     }
+                    unspin_all();
                 });
             }
         });
     });
-});
 //downgrade to user [in projects:remove from project]
-$(document).ready(function() {
     $('button#removepi').click(function() {
+        spin_all();
         var flag = false;
         var pi_users = [];
         $.post("/rest/myslice:authority/",{'filters':{'authority_hrn': '{{user_details.parent_authority}}'}}, function( data ) {
@@ -316,9 +318,11 @@ $(document).ready(function() {
                                        for (var i=pi_users.length-1; i>=0; i--) {
                                        if (pi_users[i] === record_id) {
                                                pi_users.splice(i, 1);
+                            $.post("/credentials/clear/",{'emails':[this.dataset['email']]}, function(data) {
+                            }); // post credentials clear
+                            flag = true;                
                                        }
                                        }
-                    flag = true;                
                 }
             });
             if(flag == true){
@@ -340,7 +344,11 @@ $(document).ready(function() {
                         mysliceAlert('Rest Error for: '+data.error,'warning', true);
                         //alert("Rest Error for "+record_id+": "+data.error);
                     }
+                    unspin_all();
                 });
+            }else{
+                mysliceAlert('No action: User had no rights on: {{user_details.parent_authority}}','success', true);
+                unspin_all();
             }
         });
     });
diff --git a/portal/templates/fed4fire/fed4fire_join_request_denied.html b/portal/templates/fed4fire/fed4fire_join_request_denied.html
new file mode 100644 (file)
index 0000000..5b98402
--- /dev/null
@@ -0,0 +1,18 @@
+<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png" width="80px">
+<br>
+<p>Dear Fed4FIRE user,</p>
+<p></p>
+<p>You have recently requested to join a project in the Fed4FIRE portal.</p>
+<br>
+<b>Project name  :</b> {{project_name}}</br>
+<b>Authority     :</b> {{authority_hrn}}</br>
+<b>Email         :</b> {{email}}</br>
+<p></p>
+<br>
+<p>We regret to inform you that, a manager of your institution has rejected your request. Please contact the manager of your institution for further information. 
+For any other queries, please contact us by replying to this email.</p>
+<br>
+<p>We wish you a fruitful user experience on Fed4FIRE.</p>
+<br>
+<p>Yours sincerely,</p>
+<p>The Fed4FIRE team</p>
diff --git a/portal/templates/fed4fire/fed4fire_join_request_denied.txt b/portal/templates/fed4fire/fed4fire_join_request_denied.txt
new file mode 100644 (file)
index 0000000..45bab22
--- /dev/null
@@ -0,0 +1,15 @@
+Dear Fed4FIRE user,
+
+You have recently requested to join a project in the Fed4FIRE portal.
+
+Project name  : {{project_name}}
+Authority     : {{authority_hrn}}
+Email         : {{email}}
+We regret to inform you that, a manager of your institution has rejected your request. Please contact the manager of your institution for further information. For any other queries, please contact us by replying to this email.
+
+We wish you a fruitful user experience on Fed4FIRE.
+
+Yours sincerely,
+The Fed4FIRE team
+
diff --git a/portal/templates/fed4fire/fed4fire_join_request_email.html b/portal/templates/fed4fire/fed4fire_join_request_email.html
new file mode 100644 (file)
index 0000000..f7949d0
--- /dev/null
@@ -0,0 +1,18 @@
+<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png" width="80px">
+<br>
+<h1>JOIN PROJECT REQUEST</h1>
+<br>
+<p>You are receiving this request because we have you listed as a manager of a project that uses Fed4FIRE.</p>
+<p>A user has requested to join your project, which will allow him or her to reserve testbed resources to conduct an experiment.</p>
+<br>
+<b>Project name  :</b> {{project_name}}</br>
+<b>Authority     :</b> {{authority_hrn}}</br>
+<b>Email         :</b> {{email}}</br>
+<p></p>
+<p>You can accept or reject this request <a href="{{current_site}}/portal/project/{{authority_hrn}}.{{project_name}}#requests">in the portal.</a><p>
+<p>Please be sure that you know the user who is requesting to join your project.</p>
+<p>Fed4FIRE and its affiliated testbeds exist purely to support useful and interesting work. To ensure the future of these environments, we need to know what work is actually being done.</p>
+<p></p>
+<p>If you believe that you have received this message in error, or if you have any questions, kindly contact contact@fed4fire.eu</p>
+
+
diff --git a/portal/templates/fed4fire/fed4fire_join_request_email.txt b/portal/templates/fed4fire/fed4fire_join_request_email.txt
new file mode 100644 (file)
index 0000000..57cc4d7
--- /dev/null
@@ -0,0 +1,19 @@
+JOIN PROJECT REQUEST
+
+You are receiving this request because we have you listed as a manager a project that uses Fed4FIRE.
+A user has requested to join your project, which will allow him or her to reserve testbed resources to conduct an experiment.
+
+Project name  : {{project_name}}
+Authority     : {{authority_hrn}}
+Email         : {{email}}
+
+You can accept or reject thisrequest in: 
+{{current_site}}/portal/project/{{authority_hrn}}.{{project_name}}#requests
+
+
+Please be sure that you know the user who is requesting to join your project.
+
+Fed4FIRE and its affiliated testbeds exist purely to support useful and interesting work. To ensure the future of these environments, we need to know what work is actually being done. 
+
+If you believe that you have received this message in error, or if you have any questions, kindly contact contact@fed4fire.eu
+
diff --git a/portal/templates/fed4fire/fed4fire_join_request_validated.html b/portal/templates/fed4fire/fed4fire_join_request_validated.html
new file mode 100644 (file)
index 0000000..bc0a77a
--- /dev/null
@@ -0,0 +1,21 @@
+<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png" width="80px">
+<br>
+<p>Dear Fed4FIRE user,</p>
+<p></p>
+<p>You have recently requested to join a project in the Fed4FIRE portal.</p>
+<br>
+<b>Project name  :</b> {{project_name}}</br>
+<b>Authority     :</b> {{authority_hrn}}</br>
+<b>Email         :</b> {{email}}</br>
+<p></p>
+<p>
+       We are pleased to inform you that a project manager has validated your request on the Fed4FIRE portal. 
+       You can now create slices in this project and start experimenting.
+</p>
+<p></p>
+<p>We wish you a fruitful user experience with the Fed4FIRE portal.</p>
+<p></p>
+<p>Yours sincerely,</p>
+<p>The Fed4FIRE team</p>
+
+
diff --git a/portal/templates/fed4fire/fed4fire_join_request_validated.txt b/portal/templates/fed4fire/fed4fire_join_request_validated.txt
new file mode 100644 (file)
index 0000000..fed677c
--- /dev/null
@@ -0,0 +1,15 @@
+Dear Fed4FIRE user,
+
+You have recently requested to join a project in the Fed4FIRE portal.
+
+Project name  : {{project_name}}
+Authority     : {{authority_hrn}}
+Email         : {{email}}
+
+We are pleased to inform you that a project manager has validated your request on the Fed4FIRE portal. 
+You can now create slices in this project and start experimenting.
+
+We wish you a fruitful user experience with the Fed4FIRE portal.
+
+Yours sincerely,
+The Fed4FIRE team
diff --git a/portal/templates/fed4fire/fed4fire_project_request_denied.html b/portal/templates/fed4fire/fed4fire_project_request_denied.html
new file mode 100644 (file)
index 0000000..5c4916c
--- /dev/null
@@ -0,0 +1,19 @@
+<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png" width="80px">
+<br>
+<p>Dear Fed4FIRE user,</p>
+<p></p>
+<p>You have recently requested a project in the Fed4FIRE portal.</p>
+<br>
+<b>Project name  :</b> {{project_name}}</br>
+<b>Authority     :</b> {{authority_hrn}}</br>
+<b>Email         :</b> {{email}}</br>
+<b>Purpose         :</b> {{purpose}}</br>
+<p></p>
+<br>
+<p>We regret to inform you that, a manager of your institution has rejected your request. Please contact the manager of your institution for further information. 
+For any other queries, please contact us by replying to this email.</p>
+<br>
+<p>We wish you a fruitful user experience on Fed4FIRE.</p>
+<br>
+<p>Yours sincerely,</p>
+<p>The Fed4FIRE team</p>
diff --git a/portal/templates/fed4fire/fed4fire_project_request_denied.txt b/portal/templates/fed4fire/fed4fire_project_request_denied.txt
new file mode 100644 (file)
index 0000000..e5502d8
--- /dev/null
@@ -0,0 +1,16 @@
+Dear Fed4FIRE user,
+
+You have recently requested a project in the Fed4FIRE portal.
+
+Project name  : {{project_name}}
+Authority     : {{authority_hrn}}
+Email         : {{email}}
+Purpose       : {{purpose}}
+
+We regret to inform you that, a manager of your institution has rejected your request. Please contact the manager of your institution for further information. For any other queries, please contact us by replying to this email.
+
+We wish you a fruitful user experience on Fed4FIRE.
+
+Yours sincerely,
+The Fed4FIRE team
+
diff --git a/portal/templates/fed4fire/fed4fire_project_request_email.html b/portal/templates/fed4fire/fed4fire_project_request_email.html
new file mode 100644 (file)
index 0000000..c93ab40
--- /dev/null
@@ -0,0 +1,21 @@
+<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png" width="80px">
+<br>
+<h1>NEW PROJECT REQUEST</h1>
+<br>
+<p>You are receiving this request because we have you listed as a manager at an organization that uses Fed4FIRE.</p>
+<p>A user from your organization has requested the creation of a new project.</p>
+<br>
+<b>Project name  :</b> {{project_name}}</br>
+<b>Authority     :</b> {{authority_hrn}}</br>
+<b>Email         :</b> {{email}}</br>
+<b>Purpose         :</b> {{purpose}}</br>
+<b>Portal url     :</b> {{current_site}}</br> 
+<p></p>
+<p>You can see this new project request <a href="{{current_site}}/portal/institution#requests">in the portal.</a><p>
+<p>Please be sure that you know the user who is requesting this project, as you are responsible for his or her actions.</p>
+<p>And kindly ensure that the stated experiment purpose is clear.</p>
+<p>Fed4FIRE and its affiliated testbeds exist purely to support useful and interesting work. To ensure the future of these environments, we need to know what work is actually being done.</p>
+<p></p>
+<p>If you believe that you have received this message in error, or if you have any questions, kindly contact contact@fed4fire.eu</p>
+
+
diff --git a/portal/templates/fed4fire/fed4fire_project_request_email.txt b/portal/templates/fed4fire/fed4fire_project_request_email.txt
new file mode 100644 (file)
index 0000000..f38fd8c
--- /dev/null
@@ -0,0 +1,20 @@
+NEW SLICE REQUEST
+
+You are receiving this request because we have you listed as a manager at an organization that uses Fed4FIRE.
+A user from your organization has requested the creation of a new slice, which will allow him or her to reserve testbed resources to conduct an experiment.
+
+Project name  : {{project_name}}
+Authority     : {{authority_hrn}}
+Email         : {{email}}
+Purpose       : {{purpose}}
+Portal url       : {{current_site}}
+
+You can see this new project request in: {{current_site}}/portal/institution#requests
+
+Please be sure that you know the user who is requesting this project, as you are responsible for his or her actions.
+And kindly ensure that the stated experiment purpose is clear. 
+Fed4FIRE and its affiliated testbeds exist purely to support useful and interesting work. To ensure the future of these environments, we need to know what work is actually being done. 
+
+If you believe that you have received this message in error, or if you have any questions, kindly contact contact@fed4fire.eu
+
diff --git a/portal/templates/fed4fire/fed4fire_project_request_validated.html b/portal/templates/fed4fire/fed4fire_project_request_validated.html
new file mode 100644 (file)
index 0000000..b8356dc
--- /dev/null
@@ -0,0 +1,22 @@
+<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png" width="80px">
+<br>
+<p>Dear Fed4FIRE user,</p>
+<p></p>
+<p>You have recently requested a project in the Fed4FIRE portal.</p>
+<br>
+<b>Project name  :</b> {{project_name}}</br>
+<b>Authority     :</b> {{authority_hrn}}</br>
+<b>Email         :</b> {{email}}</br>
+<b>Purpose       :</b> {{purpose}}</br>
+<p></p>
+<p>
+       We are pleased to inform you that a manager from your institution has validated your project request on the Fed4FIRE portal. 
+       You can now create slices and start experimenting.
+</p>
+<p></p>
+<p>We wish you a fruitful user experience with the Fed4FIRE portal.</p>
+<p></p>
+<p>Yours sincerely,</p>
+<p>The Fed4FIRE team</p>
+
+
diff --git a/portal/templates/fed4fire/fed4fire_project_request_validated.txt b/portal/templates/fed4fire/fed4fire_project_request_validated.txt
new file mode 100644 (file)
index 0000000..559bbb5
--- /dev/null
@@ -0,0 +1,15 @@
+Dear Fed4FIRE user,
+
+You have recently requested a project in the Fed4FIRE portal.
+
+Project name  : {{project_name}}
+Authority     : {{authority_hrn}}
+Email         : {{email}}
+Purpose       : {{purpose}}
+
+We are pleased to inform you that a manager from your institution has validated your project request on the Fed4FIRE portal. You can now create slices and start experimenting.
+
+We wish you a fruitful user experience with the Fed4FIRE portal.
+
+Yours sincerely,
+The Fed4FIRE team
index d5885a0..3b267bf 100644 (file)
@@ -1,17 +1,24 @@
 {% extends "layout.html" %}
 {% load i18n %}
-
-{% block content %}
+{% block head %}
 <script src="{{ STATIC_URL }}js/jquery-ui.js"></script>
 <script src="{{ STATIC_URL }}js/jquery-ui-combobox.js"></script>
-<link rel='stylesheet' type='text/css' href="{{ STATIC_URL }}css/jquery-ui.css">
+<link rel='stylesheet' type='text/css' href="//code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css">
 <link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}css/jquery.ui.combobox.css">
-<br />
+{% endblock head %}
+{% block content %}
+<div class="row">
+    <div class="col-md-12">
+         <div class="breadcrumbs" style="line-height: 3;">
+             Experiment &nbsp;>&nbsp; Create or join a Project
+         </div>
+    </div>
+</div>
 <div class="row">
     <div class="col-md-12">
         <ul class="nav nav-tabs nav-section">
-            <li class="active"><a href="#existing">Join existing Project</a></li>
-            <li><a href="#new">Create new Project</a></li>
+            <li class="active"><a href="#new">Create new Project</a></li>
+            <li><a href="#existing">Join existing Project</a></li>
             
         </ul>
     </div>
 {% endif %}
 
 <div class="container tab-content">
+
+    <div class="tab-pane active" id="new"> 
+        
+        <div class="row">
+            <div class="col-sm-6 col-sm-offset-3">
+                <form role="form" method="post" action="/portal/project_request">
+                {% csrf_token %}
+                    <label>
+                        Please insert a name for your project under which you will be able to create slices <br />
+                        <span class="sublabel">
+                         The project name should only contain letters, numbers and the underscore "_"  (10 max length)<br />
+                        </span>
+                    </label>
+                    <div class="form-group">
+                        <input type="text" name="project_name" value="" class="form-control" maxlength="10"  style="width:100%;" title="The project name should not contain spaces but only letters, numbers and the underscore character" placeholder="Project name" required>
+                    </div>
+                    
+                    <label>
+                        The authority under which your project will be managed <br />
+                        <span class="sublabel">
+                        Before you can access your project a manager of this authority should approve the request
+                        </span>
+                    </label>
+                    <div class="form-group">
+                        <select id="org_name" name="authority_name" class="form-control" style="width:100%" value="{{ organization }}" required> 
+                        {% if authorities %}
+                            {% for authority in authorities %}
+                                {% if authority.name %}
+                                    <option value="{{ authority.authority_hrn }}" {% if authority.authority_hrn == authority_hrn %}selected{% endif %}>{{authority.name}}</option>
+                                {% else %}
+                                    <option value="{{ authority.authority_hrn }}" {% if authority.authority_hrn == authority_hrn %}selected{% endif %}>{{authority.authority_hrn}}</option>
+                                {% endif %}
+                            {% endfor %} 
+                        {% endif %}
+                        </select>
+                    </div>
+                  
+                    <label>
+                        Please provide a description of the purpose for your project
+                    </label>
+                    <div class="form-group">
+                        <textarea id="purpose" name="purpose" class="form-control" rows="6" placeholder="Project description" style="width:100%" title="Purpose of your project (informative)" required="required"></textarea>
+                    </div>
+                    <button type="submit" class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Send Request</button>
+                </form>
+        
+            </div>
+        </div>
+    </div>
     
-       <div class="tab-pane active" id="existing"> 
+       <div class="tab-pane" id="existing"> 
         <div class="row">
             <div class="col-md-6">
                  <h3>Join an existing Project</h3>
                 <form role="form" method="post" action="/portal/project_request">
                 {% csrf_token %}
                 <div id="project_loading" style="display:inline;"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading projects" /></div> 
-                <select id="projects" name="project_name" style="display:none;"></select> <div style="display:none;" id="projects_button"><input type="submit" id="join" name="join" value="Join" class="btn"/></div>
+                <select id="projects" name="project_name" style="display:none;"></select> 
+                <div style="display:none;" id="projects_button">
+                    <input type="submit" id="join" name="join" value="Join" class="btn"/>
+                </div>
                 </form>
             </div>
             <div class="col-md-6">
             </div>
         </div>
     </div>
-    
-    <div class="tab-pane" id="new"> 
-        <div class="row">
-            <div class="col-md-12">
-                 <h3>Create a new Project</h3>
-            </div>
-        </div>
-    
-        
-        <div class="row">
-            <div class="col-md-12">
-                <form role="form" method="post" action="/portal/project_request">
-                {% csrf_token %}
-                  <div class="form-group">
-                    <input type="text" name="project_name" value="" style="width:380px;" placeholder="Name" required>
-                  </div>
-                  <div class="form-group">
-                    <select id="org_name" name="authority_name" class="form-control" style="width:380px" value="{{ organization }}" required> 
-                    {% if authorities %}
-                        {% for authority in authorities %}
-                            {% if authority.name %}
-                                <option value="{{ authority.authority_hrn }}">{{authority.name}}</option>
-                            {% else %}
-                                <option value="{{ authority.authority_hrn }}">{{authority.authority_hrn}}</option>
-                            {% endif %}
-                        {% endfor %} 
-                    {% endif %}
-                    </select>
-                  </div>
-                  
-                  
-                  <div class="form-group">
-                    <textarea id="purpose" name="purpose" class="form-control" rows="6" placeholder="Description" style="width:380px" title="Purpose of your project (informative)" required="required"></textarea>
-                  </div>
-                  <button type="submit" class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Send Request</button>
-                </form>
-        
-            </div>
-        </div>
-    </div>
-    
 </div>
                
 <script>
 $(document).ready(function() {
     var myprojects = JSON.parse(localStorage.getItem('projects'));
-    console.log(myprojects);
     if (myprojects) {
         $.each(myprojects, function (i, val){
-            console.log(val);
             $('.project-list').append('<tr><td>'+ val +'</td></tr>');
         });
     } else {
@@ -141,10 +157,16 @@ $(document).ready(function() {
         $("#project_loading").hide();
         $("#projects").html(projects.join( "" ));
         $("#projects").combobox();
+        var $s = jQuery("#projects").next().attr('id','listProjects');
+        jQuery('#listProjects').bind("click",function(){
+            // show all items click
+            this.childNodes[1].click();
+        });
+
     });
 /*
        
-       $("#authority_hrn").load("/rest/user/", {"fields" : ["parent_authority"], "filters": {"user_hrn": "{{ user_hrn }}"}}, function(data) {
+       $("#authority_hrn").load("/rest/myslice:user/", {"fields" : ["parent_authority"], "filters": {"user_hrn": "{{ user_hrn }}"}}, function(data) {
                var jsonData = JSON.parse(data);
         $(this).attr("value", jsonData[0]['parent_authority']);
     });
@@ -186,6 +208,9 @@ $(document).ready(function() {
        // auto-complete the form
     jQuery("#org_name").combobox();
 
+    $('input[name=project_name]').keyup(function(){
+        this.value = this.value.toLowerCase();
+    });
 });
 </script>
 {% endblock %}
index 50b7fff..fd2c968 100644 (file)
                        </div>
                        <div class="modal-body">
                                <p align="left">
-                                       The exact terms and conditions for Fed4FIRE are currently under development.
+<div style="text-align: left;" class="mk-text-block  "><h4>Fed4FIRE Umbrella Terms and Conditions</h4>
+<h4><span style="color: #f97352;">Purpose of this document</span></h4>
+<p>These Terms and Conditions are provided to inform the user (hereinafter â€˜You’) about what constitutes acceptable and permitted use of testbed resources and tools (hereinafter â€˜the Platform’) in the Fed4FIRE federation (hereinafter â€˜Fed4FIRE’).</p>
+<p>The regulations are not intended to constrain You unnecessarily, but to make You aware and protect You, along with all the participating institutions, from the consequences of any misuse or illegal activity as far as is reasonable.</p>
+<p>It is important to understand that when You use the Platform You are bound by these global Fed4FIRE terms and conditions (as provided online at <a href="http://www.fed4fire.eu/terms">http://www.fed4fire.eu/terms</a>), and also by the ICT regulations of Your own institution and the Acceptable Use Policy of the network providers connecting You to the testbed and interconnecting the resources You use. Thus You must have read and understood these before using Platform resources.</p>
+<p>This policy may be updated as necessary. The current version in force will be available at <a href="http://www.fed4fire.eu/terms">http://www.fed4fire.eu/terms</a>.</p>
+<h4><span style="color: #f97352;">Context</span></h4>
+<p>Fed4FIRE provides an experimental platform for testing new ideas and technologies in the area of computer networking (<a href="http://www.fed4fire.eu">http://www.fed4fire.eu</a>). The federated facility consists of individual testbeds and tools, with different owners. The Fed4FIRE consortium is coordinated by iMinds.</p>
+<p>Fed4FIRE provides You with basic access (through a single account, common tools, support and documentation) to the Platform, while each individual testbed provider determines the specifics of this access in terms of available resources, access policies, etc.</p>
+<h4><span style="color: #f97352;">Scope</span></h4>
+<p>These Terms and Conditions apply to every user of the Platform.</p>
+<p>The Terms and Conditions apply to the use of all equipment connected to the Platform. This includes servers, network(s), and Your workstations (whether owned by You, a company or an institution) and any other equipment or facilities connected to the Platform.</p>
+<p>These Terms and Conditions apply to all use of the Platform.</p>
+<p>These Terms and Conditions apply to third parties using the Platform through services You have made available through the Platform as part of an experiment. You will have to inform these third parties of the Terms and Conditions.</p>
+<h4><span style="color: #f97352;">Limitation of Liability</span></h4>
+<p>No liability is assumed by service providers involved on the Platform or any member of the Fed4FIRE consortium in regards to interruption, corruption, loss or disclosure of the services, tools, processes and data hosted<strong>, </strong>unless it is explicitly mentioned otherwise.</p>
+<h4><span style="color: #f97352;">Service Provision</span></h4>
+<p>You are granted Resources within the Fed4FIRE testbed so that You can use the Platform for the purposes described in the experiment projects You are taking part in. These resources can not be used for any other purposes.</p>
+<p>Platform resource providers aim to provide a stable, high-quality service. If there is evidence that the actions of users are adversely impacting this, resource providers are empowered to take reasonable measures to terminate or reprioritise usage in order to protect the overall operation of their services. Implicated users will be contacted by testbed providers as early as is reasonable.</p>
+<h4><span style="color: #f97352;">Acceptable Usage Policy</span></h4>
+<p>You are granted an account solely for Your own and personal use. You should take appropriate measure to protect Your credentials and prevent their use by third parties. The information You provide when requesting an account should be correct to the best of Your knowledge. You shall be responsible for all loss or damages to any part of the Platform as a result of any use of Your credentials to access the Platform, whether they are authorised or unauthorised by You.</p>
+<p>You shall be liable for actions performed on the Platform, by You, at your request or at the request of any other user invited or permitted by You to use services running on Fed4FIRE. In case of any loss or damage to the Platform originating from Your account, You are responsible for repairing or compensating for all damages to the Platform. In addition, You must respect the regulations of the various testbed resources You use in Your work, as described at <a href="http://www.fed4fire.eu/terms">http://www.fed4fire.eu/terms</a>. Your need to do this arises from co-operative agreements that have been made between all the organisations participating in the Platform.</p>
+<p>You may not interfere with others’ work or attempt to invade their privacy.</p>
+<p>You may not attempt to disrupt the working of the Platform.</p>
+<p>You must respect all Copyright for any software and data used on the Platform.</p>
+<p>The terms of software and data licences must be respected.</p>
+<p>You are not entitled to move proprietary data to, from, or via Platform systems without the prior agreement of its owner.</p>
+<p>Once You have registered to use the Platform, it is Your responsibility to remain aware of these regulations and of any changes made to them, and your continued use of the Platform means that you shall abide by the latest version of these terms and conditions.</p>
+<p>In order to keep the Platform operating correctly in both the technical and legal senses, it may become necessary to investigate network traffic (including, for example, e-mails) as well as examine information held on systems that are, or have been, connected to the Platform. You are deemed to have agreed to this.</p>
+<p>You must ensure that all known or obvious threats and vulnerabilities of the systems You run are adequately addressed.</p>
+<p>Should Your usage imply giving access to the Platform to third parties, You understand You will need to gather explicit consent from the operators of the individual testbed providers You will use, and You agree to enforce any restrictions imposed by an individual testbed provider and accept to fulfil Your legal obligations regarding data protection and retention laws.</p>
+<p>The following are explicitly forbidden on the Platform:</p>
+<ul>
+<li>Any military usage, including the development and production of weapons of mass destruction.</li>
+<li>Any activity resulting in compromising the security or integrity of any sites or networks connected to the Fed4FIRE facility</li>
+<li>Distribution of documents or materials containing insults or defamation, racial hatred or revisionism, terrorism, advertising, or distribution of material in a way that infringes the copyright of another person.</li>
+<li>Any illegal activity.</li>
+</ul>
+<p>You must comply to any additional national regulations from the government of the operators of the local testbeds.</p>
+<h4><span style="color: #f97352;">Enforcement</span></h4>
+<p>Whenever You use the Platform, You are bound by all the regulations in the current form of these terms and conditions and the legislation in force at the time.</p>
+<p>The regulations and legislation which applies to You will be enforced by iMinds, as leader of the Fed4FIRE consortium, or/and by the affected testbed providers, even if a breach of either has been evidenced from elsewhere.</p>
+<p>Note that for breaches of some legislation, the law enforcement can be involved.</p>
+<p>Ignorance of regulations or legislation is not a defence.</p>
+<p>Penalties, as defined in the individual testbed regulations at <a href="http://www.fed4fire.eu/terms">http://www.fed4fire.eu/terms</a>, will be levied for confirmed breaches of regulations.</p>
+<p>Disciplinary and investigative processes may also involve any Fed4FIRE partners, users and testbed providers involved in or affected by Your actions.</p>
+<p>Note that all testbed providers have agreed to co-operate in investigating disciplinary cases.</p>
+<p>You agree that the testbed and network providers in Fed4FIRE may monitor the systems and traffic for vulnerabilities and conformance to the acceptable uses, and You will collaborate with Fed4FIRE and any third party involved should any violations or breaches be noticed. The testbed providers involved may suspend or stop systems or suspend network connectivity without notice if such violations are found or suspected. To fulfil legal and contractual requirements, they may communicate to authorized third parties the owner and user of any resource provisioned and connected to the internet.</p>
+<h4><span style="color: #f97352;">Non-research use of Platform resources</span></h4>
+<p>The Fed4FIRE federation Platform has been constructed for experiment-driven research activities, where experiment-driven research is defined as any activity that furthers the user’s knowledge and/or understanding of algorithms, complex data structures or user behaviour.</p>
+<p>If You wish to use the Platform for any other purpose this must be authorized in advance by the Fed4FIRE testbed providers You will use. You will be expected to provide detailed information in support of Your request.</p>
+<p>Experiments must obtain prior agreement from the providers of all resources (e.g. computers, software, data, networks, and any other facilities) before these are used for any purposes other than experiment-driven research activities.</p>
+<p>The use of Fed4FIRE to host commercial services is explicitly disallowed.</p>
+<p>Experimenters that wish to use additional resources also have to agree with the policies of the testbed providers that offer the requested resources (when applicable). The individual testbed policies can be found here:</p>
+<p><a href="http://www.fed4fire.eu/terms/" target="_blank">fed4fire testbeds</a></p>
+<div class="clearboth"></div></div>
                                </p>
 
                        </div>
diff --git a/portal/templates/fed4fire/fed4fire_slice-request-done-view.html b/portal/templates/fed4fire/fed4fire_slice-request-done-view.html
new file mode 100644 (file)
index 0000000..c848b06
--- /dev/null
@@ -0,0 +1,14 @@
+{% extends "layout.html" %}
+
+{% block content %}
+
+  <h1>Success</h1>
+
+Your slice has been created. You can view all your slices in the <a href="/">dashboard.</a>
+<script>
+$(document).ready(function() {
+    localStorage.clear();
+});
+</script>
+{% endblock %}
+
index 3fefedf..650092f 100644 (file)
@@ -55,6 +55,7 @@ $(document).ready(function() {
                          <li class="active"><a href="#resourcelist" role="tab" data-toggle="tab">Table</a></li>
                          <li> <a href="#resourcemap" role="tab" data-toggle="tab">Map</a></li>
                          <li> <a href="#resourcescheduler" role="tab" data-toggle="tab">Scheduler</a></li>
+              <li> <a href="#resourcesla" role="tab" data-toggle="tab">SLA offers</a></li>
                        </ul>
                        </div>
                </div>
@@ -90,6 +91,9 @@ $(document).ready(function() {
                                <div class="tab-pane" id="resourcemap">
                        {{map_resources}}
                                </div>
+                <div class="tab-pane" id="resourcesla">
+                       {{sla_dialog}}
+                               </div>
                                <div class="tab-pane" id="resourcescheduler">
                        {{scheduler}}
                                </div>
index c2d52c3..05a43a6 100644 (file)
@@ -14,5 +14,6 @@
   <!-- <div class="tab-pane row" id="statistics">...</div> -->
   <!-- <div class="tab-pane row" id="measurements">...</div> -->
   <div class="tab-pane row" id="experiment">...</div>
+  <div class="tab-pane row" id="sla">...</div>
 </div>         
 {% endblock %}
index c472fab..7a1c12c 100644 (file)
@@ -1,4 +1,4 @@
-<img src="http://doc.fed4fire.eu/_static/fed4fire-logo.jpg">
+<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png" width="80px">
 <br>
 <p>Dear Fed4FIRE user,</p>
 <p></p>
@@ -7,7 +7,7 @@
 <b>Slice name   :</b> {{slice_name}}<br>
 <b>URL          :</b> {{url}}<br>
 <b>Purpose      :</b> {{purpose}}<br>
-<br>c
+<br>
 <p>We regret to inform you that, a manager of your institution has not confirmed your request. Please contact the manager of your institution for further information. 
 For any other queries, please contact us by replying to this email.</p>
 <br>
index 6a26829..5a217d8 100644 (file)
@@ -1,4 +1,4 @@
-<img src="http://doc.fed4fire.eu/_static/fed4fire-logo.jpg">
+<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png" width="80px">
 <br>
 <h1>NEW SLICE REQUEST</h1>
 <br>
@@ -12,7 +12,7 @@
 <b>Email           :</b> {{email}}</br>
 <b>Portal url     :</b> {{current_site}}</br> 
 <p></p>
-<p>You can see new slice request <a href="{{current_site}}/portal/validate">in the portal.</a><p>
+<p>You can see new slice request <a href="{{current_site}}/portal/institution#requests">in the portal.</a><p>
 <p>Please be sure that you know the user who is requesting this slice, as you are responsible for his or her actions.</p>
 <p>And kindly ensure that the stated experiment purpose is clear, and, if there is a website that explains the website, that a URL is provided.</p>
 <p>Fed4FIRE and its affiliated testbeds exist purely to support useful and interesting work. To ensure the future of these environments, we need to know what work is actually being done.</p>
index b530cda..5e8d24d 100644 (file)
@@ -10,7 +10,7 @@ Email           : {{email}}
 Organization   : {{organization}}
 Portal url             : {{current_site}}
 
-You can see new slice request in: {{current_site}}/portal/validate
+You can see new slice request in: {{current_site}}/portal/institution#requests
 Please be sure that you know the user who is requesting this slice, as you are responsible for his or her actions.
  
 And kindly ensure that the stated experiment purpose is clear, and, if there is a website that explains the website, that a URL is provided. 
index 7c9e198..6fdcbbf 100644 (file)
@@ -1,4 +1,4 @@
-<img src="http://doc.fed4fire.eu/_static/fed4fire-logo.jpg">
+<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png" width="80px">
 <br>
 <p>Dear Fed4FIRE user,</p>
 <p></p>
index 7bcd56d..07a4597 100644 (file)
@@ -9,7 +9,7 @@
                         </div>
                </div>
        </div>
-
+       
        {% if errors %}
        <div class="row">
                <div class="col-md-12">
        {% endif %}
        
        <div class="row">
-               <div class="col-md-8 el">
+               <div class="col-md-5 col-md-offset-3">
                        <form role="form" method="post">
                        {% csrf_token %}
-                         <div class="form-group" style="display:none">
-                           <input type="email" class="form-control" id="email" style="width:300px" value="{{ email }}" readonly="readonly">
-                         </div>
                          <div class="form-group">
-                           <input type="text" class="form-control" name="slice_name" id="slice_name" style="width:300px" placeholder="Slice name" value="{{slice_name}}" 
-                               title="Please enter a name for your slice"required="required">
+                            <input type="hidden" id="email" value="{{ email }}" readonly="readonly">
+                            <label>
+                                Please enter a name for your slice <br />
+                                <span class="sublabel">
+                                    The slice name should only contain letters, numbers and the underscore "_" (19 max length) <br />
+                                </span>
+                            </label>
+                            <input type="text" class="form-control" name="slice_name" id="slice_name" maxlength="19" style="width:100%" placeholder="Slice name" value="{{slice_name}}" required="required">
                          </div>
                          <div class="form-group">
-                               {% if pi %}
-                               <input type="text" class="form-control" id="authority_hrn" name="org_name" style="width:300px" placeholder="Organization" 
-                               title="An authority responsible for vetting your slice" required="required">
-                               {% else %}
-                           <input type="hidden" class="form-control" id="authority_hrn" name="org_name" placeholder="Organization" style="width:300px;" 
-                               title="An authority responsible for vetting your slice" required="required" readonly>
-                <span style="float:left;">Authority: &nbsp;</span>
-                <div id="authority_display">
-                <img src="{{ STATIC_URL }}img/loading.gif" alt="Loading authority" />
-                </div>
-                               {% endif %}
+                             <label>
+                                 Select a project under which you want your slice to be created <br />
+                                 If your are not part of any projects you can <a href="/portal/project_request/">join or create one</a>
+                             </label>
+                               <input type="text" class="form-control" id="authority_hrn" name="org_name" style="width:100%" placeholder="Project" 
+                                       title="Select a project under which you want to create your slice" required="required">
                          </div>
                          <div class="form-group">
-                Project: <div id="project_loading" style="display:inline;"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading projects" /></div> 
-                <select id="project" name="project" style="display:none;">
-                </select>
-              </div>
-                         <div class="form-group">
-                           <input type="text" class="form-control" name="url" id="url" style="width:300px" placeholder="Experiment URL (if one exists)"
-                               title="Please provide the url of your experiment if you have one." value="{{url}}">
+                             <label>
+                                 Provide an URL for your experiment (not required)
+                             </label>
+                             <input type="text" class="form-control" name="url" id="url" style="width:100%" placeholder="Experiment URL (if one exists)"
+                                       title="Please provide the url of your experiment" value="{{url}}">
                          </div>
                          <div class="form-group">
-                               <textarea id="purpose" name="purpose" class="form-control" rows="6" placeholder="Experiment purpose" style="width:300px" 
-                               title="Purpose of your experiment (informative)" required="required">{{ purpose }}</textarea>
+                             <label>
+                        Please provide a description of the purpose for your experiment
+                   </label>
+                                 <textarea id="purpose" name="purpose" class="form-control" rows="6" placeholder="Experiment description" style="width:100%" 
+                                       title="Description of your experiment" required="required">{{ purpose }}</textarea>
                          </div>
-                         {% if pi %}   
                          <button type="submit" id=submit_pi class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Create slice</button>
-                         {% else %}
-                         <button type="submit" class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Request slice</button>
-                         {% endif %}   
                        </form>
        
                </div>
                
 <script>
 jQuery(document).ready(function(){
-       
-       $("#authority_hrn").load("/rest/user/", {"fields" : ["parent_authority"], "filters": {"user_hrn": "{{ user_hrn }}"}}, function(data) {
-               var jsonData = JSON.parse(data);
-        $(this).attr("value", jsonData[0]['parent_authority']);
-           {% if pi %}
-        draw_projects(jsonData[0]['parent_authority']);
-        {% else %}
-        $('#authority_display').html(jsonData[0]['parent_authority']);
-        draw_projects('');
-        {% endif %}
-    });
-
-       {% if pi %}
-       $("#authority_hrn").val("{{authority_name}}");
-       var availableTags = [
-    {% if authorities %}
-        {% for authority in authorities %}
-            {% if authority.name %}
-                {value:"{{ authority.name }}",label:"{{authority.name}}"},
-                       // to show only full name
-            {% else %}
-                {value:"{{ authority.authority_hrn }}",label:"{{authority.authority_hrn}}"},
-            {% endif %}
-        {% endfor %}    
-    {% else %}
-        {value:"",label:"No authority found !!!"}
-    {% endif %}
-    ];
-       // sorting the list
-       availableTags.sort(function(a,b){
-               var nameA=a.value.toLowerCase(), nameB=b.value.toLowerCase();
-               if (nameA < nameB) {
-               return -1;
-               }
-               if (nameA > nameB) {
-               return 1;
-               }
-       return 0;
-       }); 
+    var myprojects = JSON.parse(localStorage.getItem('projects'));
     $( "#authority_hrn" ).autocomplete({
-      source: availableTags,
-      minLength: 0,
-      select: function( event, ui ) {
-        $("#project").hide();
-        $("#project_loading").css('display', 'inline-block');
-        draw_projects(jQuery('.ui-state-focus').html());
-      },
+        minLength: 0,
+        source: myprojects,
+        change: function (event, ui) {
+                if(!ui.item){
+                    //http://api.jqueryui.com/autocomplete/#event-change -
+                    // The item selected from the menu, if any. Otherwise the property is null
+                    //so clear the item for force selection
+                    $("#authority_hrn").val("");
+                }
+        }
+    }).bind('focus', function(){ $(this).autocomplete("search"); } );
+    $('input[name=slice_name]').keyup(function(){
+        this.value = this.value.toLowerCase();
     });
-    {% endif %}
 });
-
-function draw_projects(authority_hrn){
-
-    var projects = [];
-    project_row = "<option value=''> - </option>";
-    projects.push(project_row);
-
-    if(authority_hrn.length > 0){
-        // Not for root authority
-        if(authority_hrn.split('.').length > 1){
-            $.post("/rest/myslice:authority/",{'fields':['authority_hrn','pi_users'],'filters':{'authority_hrn':'CONTAINS'+authority_hrn}}, function( data ) {
-               
-                $.each( data, function( key, val ) {
-                    project_row = "<option value='"+val.authority_hrn+"'>"+val.authority_hrn+"</option>";
-                    projects.push(project_row);
-                });
-                $("#project").html(projects.join( "" ));
-            });
-        }else{
-            $("#project").html(projects.join( "" ));
-        }
-    }else{
-        my_projects = JSON.parse(localStorage.getItem('projects'));
-        $.each( my_projects, function( i, val ) {
-            project_row = "<option value='"+val+"'>"+val+"</option>";
-            projects.push(project_row);
-        });
-        $("#project").html(projects.join( "" ));
-    }
-    $("#project").show();
-    $("#project_loading").hide();
-}
 </script>
 {% endblock %}
 
index 7b49f43..9245cbd 100644 (file)
@@ -1,4 +1,4 @@
-<img src="http://doc.fed4fire.eu/_static/fed4fire-logo.jpg">
+<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png" width="80px">
 <br>
 <p>Dear {{first_name}} {{last_name}},</p>
 <p></p>
index e54d0bf..b9b090f 100644 (file)
@@ -1,4 +1,4 @@
-<img src="http://doc.fed4fire.eu/_static/fed4fire-logo.jpg">
+<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png" width="80px">
 <br>
 <h1>NEW USER REQUEST</h1>
 <br>
@@ -11,6 +11,6 @@
 <b>User hrn     :</b> {{user_hrn}}<br>
 <b>Portal url  :</b> {{ current_site }}<br>
 <p></p>
-<p>You can validate the user <a href="{{current_site}}/portal/validate">here</a>.<p>
+<p>You can validate the user <a href="{{current_site}}/portal/institution#requests">here</a>.<p>
 <br>
 <p>Please note that the validation request will only become visible once the user has confirmed his/her email address.</p>
index 7d6833b..b3cda42 100644 (file)
@@ -1,12 +1,10 @@
-<img src="http://doc.fed4fire.eu/_static/fed4fire-logo.jpg">
+<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png" width="80px">
 <br>
 <p>Dear {{first_name}} {{last_name}},</p>
 <p></p>
-<p>It is my pleasure to welcome you as a fully signed-up user of the Fed4FIRE portal. Fed4FIRE provides you with access to world class computer networking testbeds. Our aim at Fed4FIRE is to promote the use of these testbeds for research and development by industry, for scientific research, and for university level laboratory exercises.</p>
+<p>It is my pleasure to welcome you as a fully registered user of the Fed4FIRE portal. Fed4FIRE provides you with access to world-class computer networking testbeds. Our aim in Fed4FIRE is to promote the use of these testbeds for industrial research and development, scientific research, and university-level laboratory exercises.</p>
 <p></p>
-</p>
-Your entry point for access to the testbeds is the Fed4FIRE portal, which provides a web-based interface for browsing and reserving resources on the various testbeds. To run an experiment using those resources, you may log in to the testbed and/or individual nodes on the testbed with your Fed4FIRE public/private key pair, or you may use an experiment control tool such as as NEPI or OMF. The Fed4FIRE  operations team is standing by at contact@fed4fire.eu to provide you with help regarding the portal and to refer your testbed- and tool-specific queries to those best able to answer them.
-</p>
+<p>Your entry point for access to our testbeds is the Fed4FIRE portal, which provides a web-based interface for browsing and reserving resources on the various testbeds. To run an experiment using these resources, you may either log into the specific testbed and/or individual nodes on the testbed using your Fed4FIRE public/private key pair, or you may use an experiment control tool such as as NEPI or OMF. The Fed4FIRE operations team is standing by at contact@fed4fire.eu to provide you with any help regarding the portal, or to refer your testbed and tool-specific queries to those best able to answer them.</p>
 <p></p>
 </p>We  wish you a fruitful user experience with the Fed4FIRE portal.</p>
 <p></p>
diff --git a/portal/templates/fed4fire/fed4fire_user_request_validated_subject.txt b/portal/templates/fed4fire/fed4fire_user_request_validated_subject.txt
new file mode 100644 (file)
index 0000000..4c2582b
--- /dev/null
@@ -0,0 +1 @@
+Fed4FIRE portal: Account validated
index 40761b5..d4fa7cd 100644 (file)
@@ -20,6 +20,7 @@
        <!-- <li><a href="/slice/{{ slice }}#experiment">Statistics</a></li> -->
        <!-- <li><a href="/slice/{{ slice }}#experiment">Measurements</a></li> -->
        <li><a href="/slice/{{ slice }}#experiment">Tools</a></li>
+    <li><a href="/slice/{{ slice }}#sla">SLA status</a></li>
 </ul>
 {% else %}
 <ul class="nav nav-tabs nav-section">
@@ -30,6 +31,7 @@
        <!-- <li class="statistics"><a href="#experiment">Statistics</a></li> -->
        <!-- <li class="measurements"><a href="#experiment">Measurements</a></li> -->
        <li class="experiment"><a href="#experiment">Tools</a></li>
+    <li class="sla"><a href="#sla">SLA status</a></li>
 </ul>
 
 <script>
@@ -38,7 +40,7 @@ $(document).ready(function() {
                if ($(this).hasClass('link')) return;
                e.preventDefault();
                $(this).tab('show');
-       var id = $(this).attr('href').substr(1);        
+       var id = $(this).attr('href').substr(1);
        $("#" + id).load('/' + id + '/{{ slice }}/');
        });
        
index 680163e..3f2bd7a 100644 (file)
@@ -9,7 +9,6 @@
         
            <div id="secondary" class="col-sm-8 col-md-8 secondary">
                        <ul>
-                           <li><a href="/">Home</a></li>
                                <li><a href="/portal/about">About</a></li>
                                <li><a href="http://doc.fed4fire.eu/">Documentation</a></li>
                                <li><a target="_blank" href="http://www.fed4fire.eu">Project website</a></li>
@@ -23,7 +22,7 @@
           {% if username %}
         <div class="col-md-12 navigation">
             <ul>
-                <li id="nav-account"><a href="/portal/account/">{{ username }}</a></li>
+                <li><a href="/">DASHBOARD</a></li>
                 <li>|</li>
                 <!--<li id="nav-institution" class=""><a href="/portal/institution">AUTHORITY</a></li>-->
                 <li class="slices">
@@ -38,6 +37,7 @@
                 <li id="nav-service"><a href="/portal/servicedirectory">SERVICES</a></li>
                 <li id="nav-support"><a href="http://doc.fed4fire.eu/support.html">SUPPORT</a></li>
                 <li>|</li>
+                <li id="nav-account"><a href="/portal/account/">{{ username }}</a></li>
                 <li id="nav-logout"><span class="glyphicon glyphicon-off iconlogout"></span> <a id="logout" data-username="{{ username }}" href="#">LOGOUT</a></li>
             </ul>
         </div>
index 0494855..1675654 100644 (file)
           </div>
        </div>
        <div class="tab-pane row" id="requests">
+        <div id="spinner" style="padding-top:40px; padding-left:40px;"></div>
        </div>
 </div>
 <script>
 $(document).ready(function() {
     {% if person %}
     {% if user_details.parent_authority %}
+        $('#spinner').spin();
 
         $.post("/rest/myslice:slice/",{'fields':['slice_hrn','users','url','slice_date_created'],'filters':{'parent_authority':'{{user_details.parent_authority}}'}}, function( data ) {
             var list_slices = [];
index db4ace2..eea4846 100644 (file)
@@ -1,99 +1,3 @@
-<script type="text/javascript">
-       $(document).ready(function() {
-               $("li#nav-request").addClass("active");
-               $('table.requests').dataTable({
-                   "sDom": "frtiS",
-            "bScrollCollapse": true,
-            "bStateSave": true,
-            "bPaginate": false,
-            "bLengthChange": false,
-            "bFilter": false,
-            "bSort": true,
-            "bInfo": false,
-            "bAutoWidth": true,
-            "bAutoHeight": false,
-               });
-       });
-       function on_click_event() {
-               var ids = []; 
-               $('.portal__validate__checkbox').each(function(i, el) {
-                       if ($(el).prop('checked')) {
-                               // portal__validate__checkbox__slice__2
-                               var id_array = $(el).attr('id').split('__');
-                               // push(slice__2)
-                               ids.push(id_array[3] + '__' + id_array[4]);
-                       }
-               });
-               if (ids.length > 0) {
-                       var id_str = ids.join('/');
-
-                       // XXX spinner
-
-                       $.getJSON('/portal/validate_action/' + id_str,
-                               function(status) {
-                                       $.each(status, function(request_type__id, request_status) {
-                                               // request_status: NAME -> dict (status, description)
-                                               var status_str = '';
-                                               $.each(request_status, function(name, result) {
-                                                       if (status_str != '')
-                                                               status_str += ' -- ';
-
-                                                       if (result.status) {
-                                                               status_str += '<font color="green">OK</font>';
-                                                               $('#portal__validate__checkbox__' + request_type__id).hide();
-                                                       } else {
-                                                               status_str += '<font color="red">ERROR: ' + result.description + '</font>';
-                                                       }
-                                               });
-                                               $('#portal__status__' + request_type__id).html(status_str);
-
-
-                                       });
-                               }
-                       );
-               }
-       }
-       function on_click_reject() {
-               var ids = []; 
-               $('.portal__validate__checkbox').each(function(i, el) {
-                       if ($(el).prop('checked')) {
-                               // portal__validate__checkbox__slice__2
-                               var id_array = $(el).attr('id').split('__');
-                               // push(slice__2)
-                               ids.push(id_array[3] + '__' + id_array[4]);
-                       }
-               });
-               if (ids.length > 0) {
-                       var id_str = ids.join('/');
-
-                       // XXX spinner
-
-                       $.getJSON('/portal/reject_action/' + id_str,
-                               function(status) {
-                                       $.each(status, function(request_type__id, request_status) {
-                                               // request_status: NAME -> dict (status, description)
-                                               var status_str = '';
-                                               $.each(request_status, function(name, result) {
-                                                       if (status_str != '')
-                                                               status_str += ' -- ';
-
-                                                       if (result.status) {
-                                                               status_str += '<font color="green">Rejected</font>';
-                                                               $('#portal__validate__checkbox__' + request_type__id).hide();
-                                                       } else {
-                                                               status_str += '<font color="red">ERROR: ' + result.description + '</font>';
-                                                       }
-                                               });
-                                               $('#portal__status__' + request_type__id).html(status_str);
-
-
-                                       });
-                               }
-                       );
-               }
-       }
-</script>
-
 <div class="container-fluid">
 <div class="col-md-12">
        <h2>From your authorities</h2>
                </td>
                <td>{{ request.timestamp }}</td>
                
-               <td><span id='portal__status__{{request.type}}__{{request.id}}'></span></td>
+               <td>
+            <span id='portal__status__{{request.type}}__{{request.id}}'></span>
+            <div id='{{request.type}}__{{request.id}}-status-loading' style="display:none;"><img src="{{ STATIC_URL }}img/loading.gif"></div>
+            </td>
     
         <!--<div class='portal_validate_request {{request.type}} {% if forloop.counter|divisibleby:2 %}even{% else %}odd{% endif %}'> -->
          </tr>
        </div>
 {% endif %}
 </div>
-
-{% if sub_authorities %}
-<br />
-<div class="col-md-12">
-       <h2>From your sub-authorities</h2>
-</div>
-
-       {% for authority, requests in sub_authorities.items %}
-       <div class="col-md-12">
-       <h3>{{authority}}</h3>
-           <table class="table">
-             <th>
-               <td>Type</td>
-               <td>Id</td>
-               <td>Details</td>
-               <td>Timestamp</td>
-               <td>Status</td>
-             </th>
-           {% for request in requests %}
-                 <tr>
-                       <td>
-                       {% if request.allowed == 'allowed' %}
-                       <input class='portal__validate__checkbox' id='portal__validate__checkbox__{{request.type}}__{{request.id}}' type='checkbox'/>
-                       {% else %}
-                               {% if request.allowed == 'expired' %}
-                                       expired
-                               {% else %} {# denied #}
-                                       denied
-                               {% endif %}
-                       {% endif %}
-                       </td>
-                       <td>{{ request.type }}</td>
-                       <td>{{ request.id }}</td>
-                       <td>
-               {% if request.type == 'user' %}
-               Login: {{request.login}} -- First name: {{request.first_name}} -- Last name: {{request.last_name}} -- Email: {{request.email}}
-               {% else %}
-                   {% if request.type == 'slice' %}
-               Slice name: {{request.slice_name}} -- Number of nodes: {{request.number_of_nodes}} -- Type of nodes: {{request.type_of_nodes}} -- Purpose: {{request.purpose}}
-                  {% elif request.type == 'project' %}
-            <b>{{request.project_name}}</b>  -- {{ request.user_hrn }} -- Purpose: {{request.purpose}}
-                  {% elif request.type == 'join' %}
-            <b>{{request.user_hrn}}</b> --  to join {{ request.authority_hrn }}
-                   {% else %} {# authority #}
-               Authority name: {{request.site_name}} -- authority_hrn: {{request.site_authority}} -- City: {{request.address_city}} -- Country: {{request.address_country}}
-                   {% endif %}
-               {% endif %}
-                       </td>
-                       <td>{{ request.timestamp }}</td>
-                       
-                       <td><span id='portal__status__{{request.type}}__{{request.id}}'></span></td>
-       
-           <!--<div class='portal_validate_request {{request.type}} {% if forloop.counter|divisibleby:2 %}even{% else %}odd{% endif %}'> -->
-                 </tr>
-           {% endfor %}
-           </table>
-       </div>
-       {% endfor %}
-{% endif %}
-{% if delegation_authorities %}
-<br />
-<div class="col-md-12">
-       <h2>From your authorities with delegation</h2>
-</div>
-
-       {% for authority, requests in delegation_authorities.items %}
-       <div class="col-md-12">
-               <h3>{{authority}}</h3>
-                   <table class="table">
-                     <th>
-                       <td>Type</td>
-                       <td>Id</td>
-                       <td>Details</td>
-                       <td>Timestamp</td>
-                       <td>Status</td>
-                     </th>
-                   {% for request in requests %}
-                         <tr>
-                               <td>
-                               {% if request.allowed == 'allowed' %}
-                               <input class='portal__validate__checkbox' id='portal__validate__checkbox__{{request.type}}__{{request.id}}' type='checkbox'/>
-                               {% else %}
-                                       {% if request.allowed == 'expired' %}
-                                               expired
-                                       {% else %} {# denied #}
-                                               denied
-                                       {% endif %}
-                               {% endif %}
-                               </td>
-                               <td>{{ request.type }}</td>
-                               <td>{{ request.id }}</td>
-                               <td>
-                       {% if request.type == 'user' %}
-                       Login: {{request.login}} -- First name: {{request.first_name}} -- Last name: {{request.last_name}} -- Email: {{request.email}}
-                       {% else %}
-                           {% if request.type == 'slice' %}
-                       Slice name: {{request.slice_name}} -- Number of nodes: {{request.number_of_nodes}} -- Type of nodes: {{request.type_of_nodes}} -- Purpose: {{request.purpose}}
-                           {% elif request.type == 'project' %}
-                    <b>{{request.project_name}}</b>  -- {{ request.user_hrn }} -- Purpose: {{request.purpose}}
-                           {% else %} {# authority #}
-                       Authority name: {{request.site_name}} -- authority_hrn: {{request.site_authority}} -- City: {{request.address_city}} -- Country: {{request.address_country}}
-                           {% endif %}
-                      {% endif %}
-                               </td>
-                               <td>{{ request.timestamp }}</td>
-                               
-                               <td><span id='portal__status__{{request.type}}__{{request.id}}'></span></td>
-               
-                   <!--<div class='portal_validate_request {{request.type}} {% if forloop.counter|divisibleby:2 %}even{% else %}odd{% endif %}'> -->
-                         </tr>
-                   {% endfor %}
-                   </table>
-               </div>
-               {% endfor %}
-{% endif %}
 <br />
 <div class="col-md-12">
        <button class="btn btn-onelab" type="button" id="portal__validate" onclick="on_click_event();"><span class="glyphicon glyphicon-ok"></span> Validate</button>
index 985974f..ffa882f 100644 (file)
                                                                                <input type="file" name="pubkey" class="required" id="pubkey"/>  
                                                                                <input class="btn btn-default btn-xs" name="upload_key" id="upload_key"  type="submit" title="Upload your public key" value="Upload"
                                                                                   onclick="return confirm('Are you sure? It will overwrite your current credentials and you have delegate it manually.');"/>
-                                                               </span>
+                                                       
                                                                <div style='display:none;'> <input type='hidden'  name='dload'  /> </div> 
                                                                <button type="submit" name="dl_pubkey" class="btn btn-default btn-xs" title="Download your public key" id="dl_pubkey" onclick="javascript:document.getElementById('button_value').value='dl_pubkey';">
                                                                        <span class="glyphicon glyphicon-download"></span> Download
                                        <th>Slice Name</th> 
                                <th>Expiration Date</th>
                                        <th>Download</th>
+                    <th>Delete</th>
                        </tr>
                                {% for row in my_slices %}     
                        <tr class="border_bottom">
                                                        <span class="glyphicon glyphicon-download"></span> Download
                                                </button> 
                                        </td>
+                    <td class="odd"> 
+                        <button class="btn btn-danger btn-xs" name= "del_{{row.slice_name}}" type="submit" title="Download Slice Credentials" onclick="return confirm('Are you sure? If you do so, the slice will be permanently deleted.'); javascript:document.getElementById('button_value').value='del_{{row.slice_name}}';">
+                            <span class="glyphicon glyphicon-remove"></span> Delete
+                        </button> 
+                    </td>
                        </tr>
                        {%endfor%}
                        </table>
index c8b6b44..21a7dae 100644 (file)
@@ -5,15 +5,14 @@
 
 {% block content %}
 {% include theme|add:"_widget-slice-sections.html" %}
-         
 <div class="container-fluid tab-content container-slice">
-  <div class="tab-pane active row" id="info">...</div>
-  <div class="tab-pane row" id="testbeds">...</div>
-  <div class="tab-pane row" id="resources">...</div>
-  <div class="tab-pane row" id="users">...</div>
-  <!-- <div class="tab-pane row" id="statistics">...</div> -->
-  <!-- <div class="tab-pane row" id="measurements">...</div> -->
-  <div class="tab-pane row" id="experiment">...</div>
-  <!-- <div class="tab-pane row" id="studentslabs">...</div> -->
+  <div class="tab-pane active row" id="info"></div>
+  <div class="tab-pane row" id="testbeds"></div>
+  <div class="tab-pane row" id="resources"></div>
+  <div class="tab-pane row" id="users"></div>
+  <!-- <div class="tab-pane row" id="statistics"></div> -->
+  <div class="tab-pane row" id="measurements"></div>
+  <div class="tab-pane row" id="experiment"></div>
+  <!-- <div class="tab-pane row" id="studentslabs"></div> -->
 </div>         
 {% endblock %}
index 3394e59..c226482 100644 (file)
                                title="Please enter a name for your slice"required="required">
                          </div>
                          <div class="form-group">
-                               {% if pi %}
-                               <input type="text" class="form-control" id="authority_hrn" name="org_name" style="width:300px" placeholder="Organization
+                {% if request.session.user.pi %}
+                <input type="text" class="form-control" id="authority_hrn" name="authority_hrn" style="width:300px" placeholder="Authority
                                title="An authority responsible for vetting your slice" required="required">
-                               {% else %}
-                           <input type="text" class="form-control" id="authority_hrn" name="org_name" placeholder="Organization" style="width:300px;" 
-                               title="An authority responsible for vetting your slice" required="required" readonly>
-                               {% endif %}
+                {% else %}
+                <input type="text" class="form-control" id="authority_hrn" name="authority_hrn" placeholder="Authority" style="width:300px; display:none;" 
+                               title="An authority responsible for vetting your slice" required="required" readonly="readonly">
+                {% endif %}
                          </div>
                          <div class="form-group">
                            <input type="text" class="form-control" name="url" id="url" style="width:300px" placeholder="Experiment URL (if one exists)"
index e4cf19b..f5f4573 100644 (file)
@@ -14,7 +14,7 @@
 <b>User hrn     :</b> {{user_hrn}}<br>
 <b>Portal url  :</b> {{ current_site }}<br>
 <p></p>
-<p>You can see new user request <a href="{{current_site}}/portal/validate">in the portal.</a><p>
+<p>You can see new user request <a href="{{current_site}}/portal/institution#requests">in the portal.</a><p>
 <p>Please note that the request will only become visible to you on the OneLab portal once the user has confirmed his/her email address.</p>
 <p>Please only validate users who you know for whose actions you are prepared to take responsibility, as described in the 
 <a href="{{current_site}}/terms">OneLab terms and conditions.</a> If you find any anomalies in the request 
index ce8d548..68a8253 100644 (file)
@@ -12,7 +12,7 @@ Email        : {{email}}
 User hrn     : {{user_hrn}}
 Portal url   : {{ current_site }}
 
-You can see new user request in the portal: {{current_site}}/portal/validate
+You can see new user request in the portal: {{current_site}}/portal/institution#requests
 
 Please note that the request will only become visible to you on the OneLab portal once the user has confirmed his/her email address.
 
index e03a53c..44b5d63 100644 (file)
@@ -18,7 +18,7 @@
        <li><a href="/slice/{{ slice }}#users">Users</a></li>
        <li><a href="/slice/{{ slice }}#info">Information</a></li>
        <!-- <li><a href="/slice/{{ slice }}#experiment">Statistics</a></li> -->
-       <!-- <li><a href="/slice/{{ slice }}#experiment">Measurements</a></li> -->
+       <li><a href="/slice/{{ slice }}#measurements">Measurements</a></li>
        <li><a href="/slice/{{ slice }}#experiment">Tools</a></li>
        <!-- <li><a href="/slice/{{ slice }}#studentslabs">Students Labs</a></li> -->
 </ul>
@@ -29,7 +29,7 @@
        <li class="users"><a href="#users">Users</a></li>
        <li class="active"><a href="#info">Information</a></li>
        <!-- <li class="statistics"><a href="#experiment">Statistics</a></li> -->
-       <!-- <li class="measurements"><a href="#experiment">Measurements</a></li> -->
+       <li class="measurements"><a href="#measurements">Measurements</a></li>
        <li class="experiment"><a href="#experiment">Tools</a></li>
        <!-- <li class="studentslabs"><a href="#studentslabs">Students Labs</a></li> -->
 </ul>
index 668c3d3..320642f 100644 (file)
@@ -19,9 +19,9 @@
                                                        </ul>
                                        </div>
                                </li>
-                               {%if 'is_pi'  in pi %}  
+                {% if request.session.user.pi %}
                                <li id="nav-institution" class=""><a href="/institution">MANAGEMENT</a></li>
-                                {%endif%}
+                               {%endif%}
                                <li><a href="/support/">SUPPORT</a></li>
                        </ul>
                </div>
index 9b70c5f..493b5f4 100644 (file)
@@ -2,8 +2,8 @@
 
 {% block content %}
 
-<h1><img src="{{ STATIC_URL }}icons/slices-xs.png" alt="Slice" />Request received</h1>
+<h1><img src="{{ STATIC_URL }}icons/slices-xs.png" alt="Slice" />Project request sent</h1>
 
-We will process your request and get back to you as soon as possible.
+You will receive an email as soon as your request will be validated by a manager.
 {% endblock %}
 
index a9240bc..64f49fc 100644 (file)
@@ -4,6 +4,6 @@
 
 <h1><img src="{{ STATIC_URL }}icons/slices-xs.png" alt="Slice" /> Slice request sent</h1>
 
-We will process your request and get back to you as soon as possible.
+You will receive an email as soon as your request will be validated by a manager.
 {% endblock %}
 
index 15d85e2..7dfddc9 100644 (file)
                     slice_url="<a href='"+val.slice_url+"' target='_blank'>"+val.slice_url+"</a>";
                 }
                 
-                slice_row = "<tr><td>Description:</b></td><td>"+val.slice_description+"</td></tr>";
-                slice_row += "<tr><td>url:</td><td><a href='"+val.slice_url+" target='_blank'>"+val.slice_url+"</a></td></tr>";
-                slice_row += "<tr><td>users:</td><td>"+user_length+"</td></tr>";
+               // slice_row = "<tr><td>Description:</b></td><td>"+val.slice_description+"</td></tr>";
+               // slice_row += "<tr><td>url:</td><td><a href='"+val.slice_url+" target='_blank'>"+val.slice_url+"</a></td></tr>";
+                //slice_row = "<tr><td>users:</td><td>"+user_length+"</td></tr>";
                 //slice_row += "<tr><td>resources:</td><td>"+nodes_length+"</td></tr>";
-                slice_row += "<tr><td>created:</td><td>"+val.created+"</td></tr>";
-                slice_row += "<tr><td>last update:</td><td>"+val.slice_last_updated+"</td></tr>";
-                slice_row += "<tr><td>expires:</td><td>"+val.slice_expires+"</td></tr>";
+                //slice_row += "<tr><td>created:</td><td>"+val.created+"</td></tr>";
+                slice_row = "<tr><td>Last updated on:</td><td>"+val.slice_last_updated+"</td></tr>";
+                //slice_row += "<tr><td>expires:</td><td>"+val.slice_expires+"</td></tr>";
                 table_slices.push(slice_row);
             });
            $("div#slice-info").html("<table>" + table_slices.join( "" ) + "</table>");
         });
+        $('button#renewslices').click(function() {
+            var now = new Date();
+            /* In Javascript getMonth() gives month[0] = january, month[1] = february, and so on...  */
+            var month = now.getMonth()+2;
+            var one_month_later = now.getFullYear()+"-"+month+"-"+now.getDate()+" "+now.getHours()+":"+now.getMinutes()+":"+now.getSeconds();
+            $.post("/update/slice/",{'filters':{'slice_hrn':'{{slice}}'},'params':{'expires':one_month_later}}, function(data) {
+                if(data.success){
+                    mysliceAlert('Success: slice renewed','success', true);
+                }
+                else{
+                    mysliceAlert('Rest Error for: '+data.error,'warning', true);
+                }
+            });
+        });
+        $('button#deleteslices').click(function() {
+            if (confirm('Are you sure? It will remove the slice permanently.')) {
+                $.post("/delete/slice/",{'filters':{'slice_hrn':'{{slice}}'}}, function(data) {
+                    if(data.success){
+                        localStorage.clear();
+                        var user_email = [];
+                        user_email.push ('{{username}}');
+                        $.post("/credentials/clear/",{'emails':user_email}, function(data) {
+                        }); // post credentials clear
+                        mysliceAlert('Success: slice deleted','success', true);
+                    }else{
+                        mysliceAlert('Rest Error for: '+data.error,'warning', true);
+                    }
+                    window.location.replace("/");
+                });
+            } 
+            else {
+                return false;
+            }
+        });
     });
+
 </script>
+
+<div>
+    <button id="renewslices" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-refresh"></span> Renew slice</button>
+    <button id="deleteslices" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete slice</button>
+</div>
index 82acd01..6f06c1f 100644 (file)
@@ -4,13 +4,12 @@
 <link rel="stylesheet" href="{{ STATIC_URL }}css/jquery-ui.css">
 <script>
     function get_users_in_slice(authority_hrn){
-        console.log(authority_hrn);
         $("table#user-tab").html("<tr><th>+/-</th><th>Email</th><th>User hrn</th></tr>");
        var slice_users = [];
        var slice_users_removed = [];
                var slice_users_emails = [];
        var slice_users_emails_removed = [];
-       $.post("/rest/user/",{'filters':{'parent_authority': authority_hrn}}, function( data ) {
+       $.post("/rest/myslice:user/",{'filters':{'parent_authority': authority_hrn}}, function( data ) {
                var list_users = [];
                var table_users = [];
                /* Available fields
@@ -69,7 +68,7 @@
        }); // post rest/use
 
                $('button#addusers').click(function() {
-               $.post("/update/slice/",{'filters':{'slice_hrn':'{{slice}}'},'params':{'users':slice_users}}, function(data) {
+               $.post("/update/myslice:slice/",{'filters':{'slice_hrn':'{{slice}}'},'params':{'users':slice_users}}, function(data) {
                        if(data.success){
                        // TODO: highlight row after success
                        //$('tr[id="'+record_id+'"]').highlight();
@@ -88,7 +87,7 @@
 
     $(document).ready(function() {
             // TODO: Add a filter based on the list of authorities
-               $.post("/rest/authority/",{'fields':['authority_hrn']}, function( data ) {
+               $.post("/rest/myslice:authority/",{'fields':['authority_hrn']}, function( data ) {
                 var list_authorities = [];
                 $.each( data, function( key, val ) {
                     auth_hrn = val.authority_hrn;
index 91d3f73..4aebe06 100644 (file)
@@ -6,7 +6,6 @@
 {% endblock %}
 
 {% block content %}
-
 <div class="container">
        <div class="row">
                <div class="col-md-12">
        </div>
 </div>
 <div class="container-fluid tab-content">
-  <div class="tab-pane active row" id="info">...</div>
-  <div class="tab-pane row" id="testbeds">...</div>
-  <div class="tab-pane row" id="resources">...</div>
-  <div class="tab-pane row" id="users">...</div>
+  <div class="tab-pane active row" id="info"></div>
+  <div class="tab-pane row" id="testbeds"></div>
+  <div class="tab-pane row" id="resources"></div>
+  <div class="tab-pane row" id="users"></div>
   <!-- <div class="tab-pane row" id="statistics">...</div> -->
-  <div class="tab-pane row" id="measurements">...</div>
-  <div class="tab-pane row" id="experiment">...</div>
-  <div class="tab-pane row" id="sla">...</div>
+  <div class="tab-pane row" id="measurements"></div>
+  <div class="tab-pane row" id="experiment"></div>
+  <div class="tab-pane row" id="sla"></div>
 </div>         
 {% endblock %}
index d76655e..a9ca8f2 100644 (file)
@@ -12,7 +12,7 @@
 <b>Email           :</b> {{email}}</br>
 <b>Portal url     :</b> {{current_site}}</br> 
 <p></p>
-<p>You can see new slice request <a href="{{current_site}}/portal/validate">in the portal.</a><p>
+<p>You can see new slice request <a href="{{current_site}}/portal/institution#requests">in the portal.</a><p>
 <p>Please be sure that you know the user who is requesting this slice, as you are responsible for his or her actions, as described in the 
 <a href="{{current_site}}/terms">OneLab terms and conditions.</a></p>
 <p>And kindly ensure that the stated experiment purpose is clear, and, if there is a website that explains the website, that a URL is provided.</p>
index 6188b53..0f3c5b9 100644 (file)
@@ -10,7 +10,7 @@ Email           : {{email}}
 Organization   : {{organization}}
 Portal url             : {{current_site}}
 
-You can see new slice request in: {{current_site}}/portal/validate
+You can see new slice request in: {{current_site}}/portal/institution#requests
 Please be sure that you know the user who is requesting this slice, as you are responsible for his or her actions, as described in the OneLab terms and conditions:
        {{current_site}}/terms
  
index 880521b..0faf5c1 100644 (file)
                                title="Please enter a name for your slice"required="required">
                          </div>
                          <div class="form-group">
-                               {%if 'is_pi'  in pi %}
-                               <input type="text" class="form-control" id="authority_hrn" name="authority_hrn" style="width:300px" placeholder="Authority" 
+                {% if request.session.user.pi %}
+                <input type="text" class="form-control" id="authority_hrn" name="authority_hrn" style="width:300px" placeholder="Authority" 
                                title="An authority responsible for vetting your slice" required="required">
-                               {%else%}
-                           <input type="text" class="form-control" id="authority_hrn" name="authority_hrn" placeholder="Authority" style="width:300px; display:none;" 
+                {% else %}
+                <input type="text" class="form-control" id="authority_hrn" name="authority_hrn" placeholder="Authority" style="width:300px; display:none;" 
                                title="An authority responsible for vetting your slice" required="required" readonly="readonly">
-                               {%endif%}
+                {% endif %}
                          </div>
                          <div class="form-group">
                            <input type="number" class="form-control" name="number_of_nodes" id="number_of_nodes" style="width:300px" placeholder="Number of nodes"
@@ -79,6 +79,9 @@ jQuery(document).ready(function(){
       minLength: 0,
       select: function( event, ui ) {console.log(jQuery(this));}
     });
+    $('input[name=slice_name]').keyup(function(){
+        this.value = this.value.toLowerCase();
+    });
 });
 </script>
 {% endblock %}
index e9522ff..92c1cb4 100644 (file)
@@ -11,6 +11,6 @@
 <b>User hrn     :</b> {{user_hrn}}<br>
 <b>Portal url  :</b> {{ current_site }}<br>
 <p></p>
-<p>You can validate the user <a href="{{current_site}}/portal/validate">here</a>.<p>
+<p>You can validate the user <a href="{{current_site}}/portal/institution#requests">here</a>.<p>
 <br>
 <p>Please note that the validation request will only become visible once the user has confirmed his/her email address.</p>
diff --git a/portal/templates/user_request_validated_subject.txt b/portal/templates/user_request_validated_subject.txt
new file mode 100644 (file)
index 0000000..da9ce74
--- /dev/null
@@ -0,0 +1 @@
+Account validated
index 7154b8a..40b7521 100644 (file)
@@ -30,7 +30,6 @@ class UnivbrisView (LoginRequiredAutoLogoutView):
     def get_context_data(self, **kwargs):
         
         page = Page(self.request)
-        #print "UNIVBRIS page"
         metadata = page.get_metadata()
         page.expose_js_metadata()
     
index b87a250..8c9d210 100644 (file)
@@ -44,7 +44,9 @@ from portal.actions             import get_requests
 from manifoldapi.manifoldapi    import execute_query
 from manifold.core.query        import Query
 from unfold.page                import Page
+
 from myslice.theme import ThemeView
+from myslice.settings import logger
 
 class ValidatePendingView(LoginRequiredAutoLogoutView, ThemeView):
     template_name = "validate_pending.html"
@@ -90,7 +92,7 @@ class ValidatePendingView(LoginRequiredAutoLogoutView, ThemeView):
             sfa_platforms_query = Query().get('local:platform').filter_by('gateway_type', '==', 'sfa').select('platform_id', 'platform', 'auth_type')
             sfa_platforms = execute_query(self.request, sfa_platforms_query)
             for sfa_platform in sfa_platforms:
-                print "SFA PLATFORM > ", sfa_platform['platform']
+                logger.info("SFA PLATFORM > {}".format(sfa_platform['platform']))
                 if not 'auth_type' in sfa_platform:
                     continue
                 auth = sfa_platform['auth_type']
@@ -98,7 +100,7 @@ class ValidatePendingView(LoginRequiredAutoLogoutView, ThemeView):
                     all_authorities.append(auth)
                 platform_ids.append(sfa_platform['platform_id'])
 
-            print "W: Hardcoding platform myslice"
+            logger.warning("W: Hardcoding platform myslice")
             # There has been a tweak on how new platforms are referencing a
             # so-called 'myslice' platform for storing authentication tokens.
             # XXX This has to be removed in final versions.
@@ -120,30 +122,30 @@ class ValidatePendingView(LoginRequiredAutoLogoutView, ThemeView):
             #print "=" * 80
             for user_account in user_accounts:
 
-                print "USER ACCOUNT", user_account
+                logger.debug("USER ACCOUNT {}".format(user_account))
                 if user_account['auth_type'] == 'reference':
                     continue # we hardcoded the myslice platform...
 
                 config = json.loads(user_account['config'])
                 creds = []
-                print "CONFIG KEYS", config.keys()
+                logger.debug("CONFIG KEYS {}".format(config.keys()))
                 if 'authority_credentials' in config:
-                    print "***", config['authority_credentials'].keys()
+                    logger.debug("*** AC {}".format(config['authority_credentials'].keys()))
                     for authority_hrn, credential in config['authority_credentials'].items():
                         #if credential is not expired:
                         credential_authorities.add(authority_hrn)
                         #else
                         #    credential_authorities_expired.add(authority_hrn)
                 if 'delegated_authority_credentials' in config:
-                    print "***", config['delegated_authority_credentials'].keys()
+                    logger.debug("*** DAC {}".format(config['delegated_authority_credentials'].keys()))
                     for authority_hrn, credential in config['delegated_authority_credentials'].items():
                         #if credential is not expired:
                         credential_authorities.add(authority_hrn)
                         #else
                         #    credential_authorities_expired.add(authority_hrn)
 
-            print 'credential_authorities =', credential_authorities
-            print 'credential_authorities_expired =', credential_authorities_expired
+            logger.debug('credential_authorities = {}'.format(credential_authorities))
+            logger.debug('credential_authorities_expired = {}'.format(credential_authorities_expired))
 
 #            # Using cache manifold-tables to get the list of authorities faster
 #            all_authorities_query = Query.get('authority').select('name', 'authority_hrn')
@@ -157,8 +159,8 @@ class ValidatePendingView(LoginRequiredAutoLogoutView, ThemeView):
             try:
                 for pa in pi_authorities_tmp:
                     pi_authorities |= set(pa['pi_authorities'])
-            except:
-                print 'No pi_authorities'
+            except Exception as e:
+                logger.error('No pi_authorities')
 # TODO: exception if no parent_authority
 #             try:
 #                 for pa in pi_authorities_tmp:
@@ -260,8 +262,8 @@ class ValidatePendingView(LoginRequiredAutoLogoutView, ThemeView):
                 dest[auth_hrn].append(request)
         
         context = super(ValidatePendingView, self).get_context_data(**kwargs)
-        print "testing"
-        print ctx_my_authorities
+        logger.debug("testing")
+        logger.debug(ctx_my_authorities)
         context['my_authorities']   = ctx_my_authorities
         context['sub_authorities']   = ctx_sub_authorities
         context['delegation_authorities'] = ctx_delegation_authorities
index d58593c..7ed4e08 100644 (file)
@@ -139,7 +139,7 @@ def pres_view_methods(request, type):
         config.close()
     else:
         return 0
-    return HttpResponse (json_answer, mimetype="application/json")
+    return HttpResponse (json_answer, content_type="application/json")
 
 def pres_view_animation(request, constraints, id):
 
@@ -184,7 +184,7 @@ def pres_view_animation(request, constraints, id):
     }]
 
     json_answer = json.dumps(cmd)
-    return HttpResponse (json_answer, mimetype="application/json")
+    return HttpResponse (json_answer, content_type="application/json")
 
 def pres_view_static(request, constraints, id):
     #constraints = "']date_created':1262325600"
@@ -221,4 +221,4 @@ def pres_view_static(request, constraints, id):
     }]
 
     json_answer = json.dumps(cmd)
-    return HttpResponse (json_answer, mimetype="application/json")
+    return HttpResponse (json_answer, content_type="application/json")
index c348483..65ff7e6 100644 (file)
@@ -1,13 +1,15 @@
-from manifold.core.query            import Query
-from manifoldapi.manifoldapi        import execute_query
-from portal.actions                 import is_pi
+import decimal
+import datetime
+import json
 
 from django.http                    import HttpResponse
 
+from manifold.core.query            import Query
+from manifoldapi.manifoldapi        import execute_query
 
-import decimal
-import datetime
-import json
+from portal.actions                 import is_pi
+
+from myslice.settings               import logger
 
 # handles serialization of datetime in json
 DateEncoder = lambda obj: obj.strftime("%B %d, %Y %H:%M:%S") if isinstance(obj, datetime.datetime) else None
@@ -75,7 +77,7 @@ class ObjectRequest(object):
         # What about key formed of multiple fields???
         query = Query.get('local:object').filter_by('table', '==', self.type).select('key')
         results = execute_query(self.request, query)
-        print "key of object = %s" % results
+        logger.debug("key of object = {}".format(results))
         if results :
             for r in results[0]['key'] :
                 self.id = r
@@ -136,9 +138,9 @@ class ObjectRequest(object):
         if self.params :
             for p in self.params :
                 for k,v in p.iteritems() :
-                    print "param: %s : %s" % (k,v)
+                    logger.debug("param: {} : {}".format(k, v))
                     query.set({k : v})
-            print "query = ",query
+            logger.debug("query = {}".format(query))
         else:
             raise Exception, "Params are required for create"
         return execute_query(self.request, query)
@@ -150,9 +152,9 @@ class ObjectRequest(object):
         if self.params :
             for p in self.params :
                 for k,v in p.iteritems() :
-                    print "param: %s : %s" % (k,v)
+                    logger.debug("param: {} : {}".format(k, v))
                     query.set({k : v})
-            print "query = ",query
+            logger.debug("query = {}".format(query))
         else:
             raise Exception, "Params are required for update"
 
diff --git a/rest/authority.py b/rest/authority.py
new file mode 100644 (file)
index 0000000..8f3c31d
--- /dev/null
@@ -0,0 +1,29 @@
+from django.http                    import HttpResponse
+from portal.actions                 import authority_add_pis, authority_remove_pis
+import json
+
+def dispatch(request, action):
+    
+    try:
+        if request.method == 'POST':
+            req_items = request.POST
+        elif request.method == 'GET':
+            req_items = request.GET
+
+        if 'user_hrn' in req_items:
+            user_hrn = str(req_items['user_hrn'])
+        if 'authority_hrn' in req_items:
+            authority_hrn = str(req_items['authority_hrn'])
+
+        if (action == 'add') :
+            new_pis = authority_add_pis(request, authority_hrn, user_hrn)
+            result = {'ret':1}
+        elif (action == 'remove'):
+            new_pis = authority_remove_pis(request, authority_hrn, user_hrn)
+            result = {'ret':1}
+        else:
+            raise Exception, "action not supported"
+    except Exception as e:
+        result = {'ret': -1, 'msg':'error: %s' % e}
+    return HttpResponse(json.dumps(result), content_type="application/json")
+
index 3943946..e934818 100644 (file)
@@ -9,7 +9,7 @@ import json
 def dispatch(request, action):
     
     if (action == 'clear') :
-        query = Query.update('myslice:user').filter_by('user_hrn', '==', '$user_hrn').set({'user_email':str(request.user)})
+        query = Query.update('myslice:user').filter_by('user_hrn', '==', '$user_hrn').set({'user_email':str(request.user)}).select('user_hrn')
         try:
             res = execute_query(request, query)
         except Exception, e:
index afb62b7..e3b8e4d 100644 (file)
@@ -23,8 +23,7 @@ def dispatch(request, object_type, object_name):
     elif request.method == 'GET':
         #return error('only post request is supported')
         req_items = request.GET
-    print req_items
-    for el in req_items.items():
+    for el in list(req_items.items()):
         # Filters not used for create
         if el[0].startswith('filters'):
             o.filters[el[0][8:-1]] = el[1]
@@ -44,6 +43,6 @@ def dispatch(request, object_type, object_name):
         else :
             return error('an error has occurred')
  
-    except Exception, e:
+    except Exception as e:
         return error(str(e))
 
index 21e9087..02c651b 100644 (file)
@@ -19,7 +19,6 @@ def dispatch(request, object_type, object_name):
         if el[0].startswith('filters'):
             o.filters[el[0][8:-1]] = el[1]
         elif el[0].startswith('fields'):
-            print req_items.getlist('fields[]')
             o.setFields(req_items.getlist('fields[]'))
         elif el[0].startswith('options'):
             o.options = req_items.getlist('options[]')
index 41dbc9b..fd2c317 100644 (file)
@@ -46,7 +46,6 @@ def dispatch(request, action):
                 error = "Error in delete return value"
     except Exception, e:
         error = str(e)
-        #print "Exception : ",e
     if error is not None:
         ret = { "ret" : 1, "error" : error }
     elif not results :
index 04b156b..800429a 100644 (file)
@@ -1,25 +1,23 @@
+import os
+import json
+import ConfigParser 
+
+from django.shortcuts           import render_to_response
+from django.http import HttpResponse
+
 from sfa.trust.certificate      import Keypair, Certificate
 from sfa.client.sfaserverproxy  import SfaServerProxy
 from sfa.client.return_value    import ReturnValue
 from sfa.util.xrn               import Xrn, get_leaf, get_authority, hrn_to_urn, urn_to_hrn
+
 from manifold.core.query        import Query
 from manifold.models            import db
 from manifold.models.platform   import Platform
 from manifold.models.user       import User
 
-from django.shortcuts           import render_to_response
-
 from unfold.loginrequired       import LoginRequiredView
 
-from rest import ObjectRequest, error
-
-from string import join
-
-from django.http import HttpResponse
-from rest import error
-import os,json
-
-import ConfigParser 
+from myslice.settings import logger
 
 def dispatch(request, method):
     Config = ConfigParser.ConfigParser()
@@ -58,15 +56,15 @@ def dispatch(request, method):
     from manifoldapi.manifoldapi    import execute_admin_query
     for pf in platforms:
         platform = get_platform_config(pf)
-        print platform
+        logger.debug("platform={}".format(platform))
         if 'sm' in platform and len(platform['sm']) > 0:
-            print 'sm'
+            logger.debug('sm')
             server_url = platform['sm']
         if 'rm' in platform and len(platform['rm']) > 0:
-            print 'rm'
+            logger.debug('rm')
             server_url = platform['rm']
         if 'registry' in platform and len(platform['registry']) > 0:
-            print 'registry'
+            logger.debug('registry')
             server_url = platform['registry']
     
         if not Config.has_option('monitor', 'cert') :
index 8deb428..fdd9578 100644 (file)
@@ -1,18 +1,15 @@
+from rest import ObjectRequest, error, success
+
 from django.views.generic.base      import TemplateView
 from django.shortcuts               import render_to_response
+from django.http                    import HttpResponse
 
 from unfold.loginrequired           import LoginRequiredView
-from django.http                    import HttpResponse
 
 from manifold.core.query            import Query, AnalyzedQuery
 from manifoldapi.manifoldapi        import execute_query
 
-from rest import ObjectRequest, error, success
-
-from string import join
-
-import json
-
+from myslice.settings import logger
 
 def dispatch(request, object_type, object_name):
     
@@ -23,15 +20,15 @@ def dispatch(request, object_type, object_name):
     elif request.method == 'GET':
         #return error('only post request is supported')
         req_items = request.GET
-    print req_items
+    logger.debug(req_items)
     for el in req_items.items():
         
-        print "#===============>",el
+        logger.debug("#===============> {}".format(el))
         if el[0].startswith('filters'):
             o.filters[el[0][8:-1]] = el[1]
         elif el[0].startswith('params'):
-            print "#======> 0 ", el[0]
-            print "#======> 1 ", req_items.getlist(el[0])
+            logger.debug("#======> 0 {}".format(el[0]))
+            logger.debug("#======> 1 {}".format(req_items.getlist(el[0])))
 
             if (el[0][-2:] == '[]') :
                 # when receiving params[key][] = 'value1' ...
@@ -41,7 +38,7 @@ def dispatch(request, object_type, object_name):
                 # when receiving params[key] = 'value'
                 o.params.append({el[0][7:-1]:el[1]})
             
-            print "o.params = ",o.params
+            logger.debug("o.params = {}".format(o.params))
             
         elif el[0].startswith('fields'):
             o.fields=req_items.getlist('fields[]')
index 641e491..53e0782 100644 (file)
@@ -9,10 +9,12 @@ from ui.topmenu import topmenu_items, the_user
 # tmp
 from trashutils import lorem, hard_wired_slice_names
 
+from myslice.settings import logger
+
 @login_required
 def tab_view (request):
-    print "request", request.__class__
-    print request
+    logger.info("request {}".format(request.__class__))
+    logger.info("{}".format(request))
     prelude=Prelude( js_files='js/bootstrap.js', css_files='css/bootstrap.css')
 
     tab_env = {'title':'Page for playing with Tabs',
index 506423c..e14efb8 100644 (file)
@@ -9,6 +9,8 @@ from unfold.page import Page
 
 from ui.topmenu import topmenu_items_live, the_user
 
+from myslice.settings import logger
+
 class TopmenuValidationView (TemplateView):
 
     # mention a user name in the URL as .../trash/simpletopmenuvalidation/ple.inria.thierry_parmentelat
@@ -35,9 +37,9 @@ class TopmenuValidationView (TemplateView):
         # define {js,css}_{files,chunks}
         prelude_env = page.prelude_env()
 
-#        print prelude_env.keys()
+#        logger.info(prelude_env.keys())
 #        for k in [ 'js_files' ] :
-#            print 'prelude_env',prelude_env,k,prelude_env[k]
+#            logger.info('prelude_env {} {} {}'.format(prelude_env,k,prelude_env[k]))
 
         template_env.update(prelude_env)
         result=render_to_response ('view-unfold1.html',template_env,
diff --git a/sla/README b/sla/README
deleted file mode 100755 (executable)
index 3ecd9d9..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-This is the README.txt file for sla-dashboard application.\r
-\r
-sla-dashboard application is composed by the following directories:\r
-* sladashboard: the app related to the application itself. The settings\r
-    file maybe need to be modified: read below.\r
-* slagui: the sla dashboard GUI project.\r
-* slaclient: this project contains all the code needed to connect to\r
-    SLA Manager REST interface, and the conversion from xml/json to python\r
-    objects.\r
-* samples: this directory contains sample files to load in the SLA Manager for\r
-    testing.\r
-* bin: some useful scripts\r
-\r
-\r
-Software requirements\r
----------------------\r
-Python version: 2.7.x\r
-\r
-The required python packages are listed in requirements.txt\r
-\r
-Installing the requirements inside a virtualenv is recommended.\r
-\r
-SLA Manager (java backend) needs to be running in order to use the dashboard.\r
-\r
-Installing\r
-----------\r
-(to be corrected/completed)\r
-\r
-#\r
-# Install virtualenv\r
-#\r
-$ pip install virtualenv\r
-\r
-\r
-#\r
-# Create virtualenv.\r
-# E.g.: VIRTUALENVS_DIR=~/virtualenvs\r
-#\r
-$ virtualenv $VIRTUALENVS_DIR/sla-dashboard\r
-\r
-#\r
-# Activate virtualenv\r
-#\r
-$ . $VIRTUALENVS_DIR/sla-dashboard/bin/activate\r
-\r
-#\r
-# Change to application dir and install requirements\r
-#\r
-$ cd $SLA_DASHBOARD\r
-$ pip install -r requirements.txt\r
-\r
-#\r
-# Create needed tables for sessions, admin, etc\r
-#\r
-$ ./manage.py syncdb\r
-\r
-Settings\r
---------\r
-\r
-* sladashboard/settings.py:\r
-    - SLA_MANAGER_URL : The URL of the SLA Manager REST interface.\r
-    - DEBUG: Please, set this to FALSE in production\r
-\r
-* sladashboard/urls.py:\r
-    - dashboard root url: the slagui project is accessed by default\r
-        in $server:$port/slagui. Change "slagui" with the desired path.\r
-\r
-\r
-Running\r
--------\r
-NOTE: this steps are not suitable in production mode.\r
-\r
-#\r
-# Activate virtualenv\r
-#\r
-$ . $VIRTUALENVS_DIR/sla-dashboard/bin/activate\r
-\r
-#\r
-# Cd to application dir\r
-#\r
-$ cd $SLA_DASHBOARD\r
-\r
-#\r
-# Start server listing in port 8000 (change port as desired)\r
-#\r
-$ ./manage.py runserver 0.0.0.0:8000\r
-\r
-#\r
-# Test\r
-#\r
-curl http://localhost:8000/slagui
\ No newline at end of file
diff --git a/sla/samples/TemplateIMindsService.xml b/sla/samples/TemplateIMindsService.xml
deleted file mode 100755 (executable)
index 2faccaf..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<wsag:Template xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement"
-       TemplateId="iMindsServiceTemplate">
-       <wsag:Name>Template for iMinds service</wsag:Name>
-       <wsag:Context>
-               <wsag:AgreementInitiator>iMinds</wsag:AgreementInitiator>
-               <wsag:ServiceProvider>AgreementInitiator</wsag:ServiceProvider>
-               <wsag:ExpirationTime>2015-03-07T12:00:00:000</wsag:ExpirationTime>
-               <sla:Service xmlns:sla="http://sla.atos.eu">iMinds service</sla:Service>
-       </wsag:Context>
-       <wsag:Terms>
-               <wsag:All>
-                       <!-- FUNCTIONAL DESCRIPTION -->
-                       <wsag:ServiceDescriptionTerm wsag:Name="SDTName1" wsag:ServiceName="iMinds service">
-                               The template for iMinds service
-                       </wsag:ServiceDescriptionTerm>
-                       
-                       <!-- OPTIONAL SERVICE REFERENCE -->
-                       
-                       <!-- OPTIONAL SERVICE PROPERTIES : non funcional properties-->
-                       <wsag:ServiceProperties wsag:Name="NonFunctional" wsag:ServiceName="iMinds service">
-                               <wsag:VariableSet>
-                                       <wsag:Variable Name="UpTime" Metric="xs:double">
-                                               <wsag:Location>iMinds/UpTime</wsag:Location>
-                                       </wsag:Variable>
-                                       <wsag:Variable Name="Performance" Metric="xs:decimal">
-                                               <wsag:Location>iMinds/Performance</wsag:Location>
-                                       </wsag:Variable>
-                               </wsag:VariableSet>
-                       </wsag:ServiceProperties>
-                       <wsag:GuaranteeTerm Name="GT_CPULoad">
-                               <wsag:ServiceScope ServiceName="iMinds service"/>
-                               <wsag:ServiceLevelObjective>
-                                       <wsag:KPITarget>
-                                               <wsag:KPIName>UpTime</wsag:KPIName>
-                                               <wsag:CustomServiceLevel>
-                                                       {"constraint" : "UpTime GT 75"}
-                                               </wsag:CustomServiceLevel>
-                                       </wsag:KPITarget>
-                               </wsag:ServiceLevelObjective>
-                       </wsag:GuaranteeTerm>
-                       <wsag:GuaranteeTerm Name="GT_Performance">
-                               <wsag:ServiceScope ServiceName="iMinds service"/>
-                               <wsag:ServiceLevelObjective>
-                                       <wsag:KPITarget>
-                                               <wsag:KPIName>Performance</wsag:KPIName>
-                                               <wsag:CustomServiceLevel>
-                                                       {"constraint" : "Performance GT 50"}
-                                               </wsag:CustomServiceLevel>
-                                       </wsag:KPITarget>
-                               </wsag:ServiceLevelObjective>
-                       </wsag:GuaranteeTerm>
-               </wsag:All>
-       </wsag:Terms>
-</wsag:Template>
diff --git a/sla/samples/providerCreate.bat b/sla/samples/providerCreate.bat
deleted file mode 100755 (executable)
index 58354f6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-curl -u normal_user:password -H "Content-type: application/xml" -d@providerIMinds.xml localhost:8080/sla-service/providers -X POST
\ No newline at end of file
diff --git a/sla/samples/providerIMinds.xml b/sla/samples/providerIMinds.xml
deleted file mode 100755 (executable)
index 1f81ce1..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<provider>
-    <uuid>iMinds</uuid>
-    <name>iMinds Testbed</name>
-</provider>
diff --git a/sla/samples/simpleAgreementCreation.bat b/sla/samples/simpleAgreementCreation.bat
deleted file mode 100755 (executable)
index 3a35b06..0000000
+++ /dev/null
@@ -1 +0,0 @@
-curl -Umyuser:mypassword -H "Content-type: application/json" -d@simpleAgreementCreationParameters.json localhost:8000/sla/agreements/simplecreate -X POST
\ No newline at end of file
diff --git a/sla/samples/simpleAgreementCreationParameters.json b/sla/samples/simpleAgreementCreationParameters.json
deleted file mode 100755 (executable)
index c013f73..0000000
+++ /dev/null
@@ -1 +0,0 @@
-{"template_id":"iMindsServiceTemplate","user":"imauser"}
diff --git a/sla/samples/templateCreate.bat b/sla/samples/templateCreate.bat
deleted file mode 100755 (executable)
index 56c2c96..0000000
+++ /dev/null
@@ -1 +0,0 @@
-curl -u normal_user:password -H "Content-type: application/xml" -d@TemplateIMindsService.xml localhost:8080/sla-service/templateso -X POST
\ No newline at end of file
diff --git a/sla/sla_utils/bin/load-samples.sh b/sla/sla_utils/bin/load-samples.sh
deleted file mode 100755 (executable)
index c316129..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/env bash
-#
-# To be executed from application root path
-#
-
-#cmd=$($(grep SLA_MANAGER sladashboard/settings.py) && eval $cmd & print $SLA_MANAGER))
-#eval $(grep SLA_MANAGER_URL sladashboard/settings.py)
-#echo SLA_MANAGER_URL=$SLA_MANAGER_URL
-
-SLA_MANAGER_URL="http://localhost:8080/sla-service"
-
-#
-echo \#Add provider virtualwall
-#
-curl -H "Content-type: application/xml" -d @samples/provider-virtualwall.xml $SLA_MANAGER_URL/providers -X POST
-
-#
-echo \#Add provider wiLab2
-#
-curl -H "Content-type: application/xml" -d @samples/provider-wilab2.xml $SLA_MANAGER_URL/providers -X POST
-
-#
-echo \#Add template
-#
-curl -H "Content-type: application/xml" -d @samples/template.xml $SLA_MANAGER_URL/templates -X POST
-
-#
-echo \#Add agreement03
-#
-curl -H "Content-type: application/xml" -d @samples/agreement03.xml $SLA_MANAGER_URL/agreements -X POST
-curl -H "Content-type: application/xml" -d @samples/enforcement03.xml $SLA_MANAGER_URL/enforcements -X POST
-#curl $SLA_MANAGER_URL/enforcements/agreement03/start -X PUT
-
-#
-echo \#Add agreement04
-#
-curl -H "Content-type: application/xml" -d @samples/agreement04.xml $SLA_MANAGER_URL/agreements -X POST
-curl -H "Content-type: application/xml" -d @samples/enforcement04.xml $SLA_MANAGER_URL/enforcements -X POST
-#curl $SLA_MANAGER_URL/enforcements/agreement04/start -X PUT
-
-#
-#echo \#Add agreement05
-#
-#curl -H "Content-type: application/xml" -d@samples/agreement05.xml $SLA_MANAGER_URL/agreements -X POST
-#curl -d@samples/enforcement05.xml -H "Content-type: application/xml" $SLA_MANAGER_URL/enforcements -X POST
-#curl $SLA_MANAGER_URL/enforcements/agreement05/start -X PUT
-
diff --git a/sla/sla_utils/bin/startagreement.sh b/sla/sla_utils/bin/startagreement.sh
deleted file mode 100755 (executable)
index b9736fc..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-
-if [ $# -eq 1  ] ; then
-       curl localhost:8080/sla-service/enforcements/agreement0$1/start -X PUT
-else
-       curl localhost:8080/sla-service/enforcements/agreement03/start -X PUT
-       curl localhost:8080/sla-service/enforcements/agreement04/start -X PUT
-fi
-
diff --git a/sla/sla_utils/bin/stopagreement.sh b/sla/sla_utils/bin/stopagreement.sh
deleted file mode 100755 (executable)
index c431f50..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-
-if [ $# -eq 1  ] ; then
-       curl localhost:8080/sla-service/enforcements/agreement0$1/stop -X PUT
-else
-       curl localhost:8080/sla-service/enforcements/agreement03/stop -X PUT
-       curl localhost:8080/sla-service/enforcements/agreement04/stop -X PUT
-fi
-
diff --git a/sla/sla_utils/samples/agreement03.xml b/sla/sla_utils/samples/agreement03.xml
deleted file mode 100755 (executable)
index b6b7a9b..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>\r
-<wsag:Agreement xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement"\r
-       AgreementId="agreement03">\r
-\r
-       <wsag:Name>ExampleAgreement</wsag:Name>\r
-       <wsag:Context>\r
-               <wsag:AgreementInitiator>experimenter01</wsag:AgreementInitiator>\r
-               <wsag:AgreementResponder>virtualwall</wsag:AgreementResponder>\r
-               <wsag:ServiceProvider>AgreementResponder</wsag:ServiceProvider>\r
-               <wsag:ExpirationTime>2014-03-07T12:00:00</wsag:ExpirationTime>\r
-               <wsag:TemplateId>template</wsag:TemplateId>\r
-               <sla:Service xmlns:sla="http://sla.atos.eu">Testbed_guarantee_0.99_Uptime_rate_for_0.99_rate_of_the_resources_during_the_sliver</sla:Service>\r
-       </wsag:Context>\r
-       <wsag:Terms>\r
-               <wsag:All>\r
-                       \r
-                       <wsag:ServiceProperties Name="ServiceProperties" ServiceName="ServiceName">\r
-                               <wsag:VariableSet>\r
-                                       <wsag:Variable Name="UpTime" Metric="xs:double">\r
-                        <wsag:Location>qos:UpTime</wsag:Location>\r
-                    </wsag:Variable>\r
-                    <wsag:Variable Name="Performance" Metric="xs:double">\r
-                        <wsag:Location>qos:Performance</wsag:Location>\r
-                    </wsag:Variable>\r
-                               </wsag:VariableSet>\r
-                       </wsag:ServiceProperties>\r
-\r
-                       <!-- Uptime GuaranteTerm-->\r
-            <wsag:GuaranteeTerm Name="GT_UpTime">\r
-                <wsag:ServiceScope ServiceName="sla:virtualwall" />\r
-                <wsag:ServiceLevelObjective>\r
-                    <wsag:KPITarget>\r
-                        <wsag:KPIName>UpTime</wsag:KPIName>\r
-                        <wsag:CustomServiceLevel>\r
-                               {"constraint" : "UpTime GT 0.99"}\r
-                        </wsag:CustomServiceLevel>\r
-                    </wsag:KPITarget>\r
-                </wsag:ServiceLevelObjective>\r
-            </wsag:GuaranteeTerm>\r
-\r
-            <!-- Resource Performance GuaranteTerm-->\r
-            <wsag:GuaranteeTerm Name="GT_Performance">\r
-                <wsag:ServiceScope ServiceName="sla:virtualwall" />\r
-                <wsag:ServiceLevelObjective>\r
-                    <wsag:KPITarget>\r
-                        <wsag:KPIName>Performance</wsag:KPIName>\r
-                        <wsag:CustomServiceLevel>\r
-                               {"constraint" : "Performance GT 0.99"}\r
-                        </wsag:CustomServiceLevel>\r
-                    </wsag:KPITarget>\r
-                </wsag:ServiceLevelObjective>\r
-            </wsag:GuaranteeTerm>\r
-               </wsag:All>\r
-       </wsag:Terms>\r
-</wsag:Agreement>\r
diff --git a/sla/sla_utils/samples/agreement04.xml b/sla/sla_utils/samples/agreement04.xml
deleted file mode 100755 (executable)
index fab041b..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>\r
-<wsag:Agreement xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement"\r
-       AgreementId="agreement04">\r
-\r
-       <wsag:Name>ExampleAgreement</wsag:Name>\r
-       <wsag:Context>\r
-               <wsag:AgreementInitiator>experimenter01</wsag:AgreementInitiator>\r
-               <wsag:AgreementResponder>wiLab2</wsag:AgreementResponder>\r
-               <wsag:ServiceProvider>AgreementResponder</wsag:ServiceProvider>\r
-               <wsag:ExpirationTime>2014-03-07T12:00:00</wsag:ExpirationTime>\r
-               <wsag:TemplateId>template</wsag:TemplateId>\r
-        <sla:Service xmlns:sla="http://sla.atos.eu">Testbed_guarantee_0.99_Uptime_rate_for_0.99_rate_of_the_resources_during_the_sliver</sla:Service>\r
-       </wsag:Context>\r
-       <wsag:Terms>\r
-               <wsag:All>\r
-               \r
-               <wsag:ServiceProperties Name="ServiceProperties" ServiceName="ServiceName">\r
-                               <wsag:VariableSet>\r
-                                       <wsag:Variable Name="UpTime" Metric="xs:double">\r
-                        <wsag:Location>qos:UpTime</wsag:Location>\r
-                    </wsag:Variable>\r
-                    <wsag:Variable Name="Performance" Metric="xs:double">\r
-                        <wsag:Location>qos:Performance</wsag:Location>\r
-                    </wsag:Variable>\r
-                               </wsag:VariableSet>\r
-                       </wsag:ServiceProperties>\r
-\r
-                       <!-- Uptime GuaranteTerm-->\r
-            <wsag:GuaranteeTerm Name="GT_UpTime">\r
-                <wsag:ServiceScope ServiceName="sla:wiLab2" />\r
-                <wsag:ServiceLevelObjective>\r
-                    <wsag:KPITarget>\r
-                        <wsag:KPIName>UpTime</wsag:KPIName>\r
-                        <wsag:CustomServiceLevel>\r
-                            {"constraint" : "UpTime GT 0.99"}\r
-                        </wsag:CustomServiceLevel> \r
-                    </wsag:KPITarget>\r
-                </wsag:ServiceLevelObjective>\r
-            </wsag:GuaranteeTerm>\r
-\r
-            <!-- Resource Performance GuaranteTerm-->\r
-            <wsag:GuaranteeTerm Name="GT_Performance">\r
-                <wsag:ServiceScope ServiceName="sla:wiLab2" />\r
-                <wsag:ServiceLevelObjective>\r
-                    <wsag:KPITarget>\r
-                        <wsag:KPIName>Performance</wsag:KPIName>\r
-                        <wsag:CustomServiceLevel>\r
-                            {"constraint" : "Performance GT 0.99"}\r
-                        </wsag:CustomServiceLevel>\r
-                    </wsag:KPITarget>\r
-                </wsag:ServiceLevelObjective>\r
-            </wsag:GuaranteeTerm>\r
-               </wsag:All>\r
-       </wsag:Terms>\r
-</wsag:Agreement>\r
diff --git a/sla/sla_utils/samples/enforcement03.xml b/sla/sla_utils/samples/enforcement03.xml
deleted file mode 100755 (executable)
index 8f43267..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-<enforcement_job>
-    <agreement_id>agreement03</agreement_id>
-    <enabled>false</enabled>
-</enforcement_job>
diff --git a/sla/sla_utils/samples/enforcement04.xml b/sla/sla_utils/samples/enforcement04.xml
deleted file mode 100755 (executable)
index bf2f5a9..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-<enforcement_job>
-    <agreement_id>agreement04</agreement_id>
-    <enabled>false</enabled>
-</enforcement_job>
diff --git a/sla/sla_utils/samples/old/agreement01.xml b/sla/sla_utils/samples/old/agreement01.xml
deleted file mode 100755 (executable)
index 547d149..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>\r
-<wsag:Agreement xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement">\r
-       <wsag:Name>ExampleAgreement</wsag:Name>\r
-       <wsag:Context>\r
-               <wsag:AgreementInitiator>RandomClient</wsag:AgreementInitiator>\r
-               <wsag:AgreementResponder>Provider01</wsag:AgreementResponder>\r
-               <!-- The AgreementResponder (in this case) is mandatory if sla is multi \r
-                       service provider -->\r
-               <wsag:ServiceProvider>AgreementResponder</wsag:ServiceProvider>\r
-               <wsag:ExpirationTime>2014-03-07T12:00</wsag:ExpirationTime>\r
-               <wsag:TemplateId>contract-template-2007-12-04</wsag:TemplateId>\r
-       </wsag:Context>\r
-       <wsag:Terms>\r
-               <wsag:All>\r
-                       <!-- FUNCTIONAL DESCRIPTION -->\r
-                       <!-- <wsag:ServiceDescriptionTerm wsag:Name="SDTName" wsag:ServiceName="ServiceName"> \r
-                               DSL expression </wsag:ServiceDescriptionTerm> -->\r
-\r
-                       <!-- OPTIONAL SERVICE REFERENCE -->\r
-\r
-                       <!-- OPTIONAL SERVICE PROPERTIES : non funcional properties -->\r
-                       <wsag:ServiceProperties wsag:Name="NonFunctional"\r
-                               wsag:ServiceName="ServiceName">\r
-                               <wsag:Variables>\r
-                                       <wsag:Variable wsag:Name="ResponseTime" wsag:Metric="xs:double">\r
-                                               <wsag:Location>qos:ResponseTime</wsag:Location>\r
-                                       </wsag:Variable>\r
-                               </wsag:Variables>\r
-                       </wsag:ServiceProperties>\r
-                       <wsag:GuaranteeTerm wsag:Name="GT_ResponseTime">\r
-                               <wsag:ServiceScope wsag:ServiceName="ServiceName" />\r
-                               <!-- The qualifying conditions that must be met before the guarantee \r
-                                       is evaluated -->\r
-                               <!-- <wsag:QualifyingCondition>state EQ 'ready'</wsag:QualifyingCondition> -->\r
-                               <wsag:ServiceLevelObjective>\r
-                                       <wsag:KPITarget>\r
-                                               <wsag:KPIName>ResponseTime</wsag:KPIName> <!-- same name as property for the moment -->\r
-                                               <wsag:CustomServiceLevel>{"contraint" : "ResponseTime LT 100"}</wsag:CustomServiceLevel> <!-- the ServiceProperty is referenced here -->\r
-                                       </wsag:KPITarget>\r
-                               </wsag:ServiceLevelObjective>\r
-                       </wsag:GuaranteeTerm>\r
-               </wsag:All>\r
-       </wsag:Terms>\r
-</wsag:Agreement>\r
diff --git a/sla/sla_utils/samples/old/agreement02.xml b/sla/sla_utils/samples/old/agreement02.xml
deleted file mode 100755 (executable)
index 707bcda..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>\r
-<wsag:Agreement xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement"\r
-       AgreementId="agreement02">\r
-\r
-       <wsag:Name>ExampleAgreement</wsag:Name>\r
-       <wsag:Context>\r
-               <wsag:AgreementInitiator>RandomClient</wsag:AgreementInitiator>\r
-               <wsag:AgreementResponder>provider-prueba</wsag:AgreementResponder>\r
-               <!--\r
-               The AgreementResponder (in this case) is mandatory if sla is multi service provider   \r
-               -->\r
-               <wsag:ServiceProvider>AgreementResponder</wsag:ServiceProvider>\r
-               <wsag:ExpirationTime>2014-03-07T12:00:00</wsag:ExpirationTime>\r
-               <wsag:TemplateId>template02</wsag:TemplateId>\r
-       </wsag:Context>\r
-       <wsag:Terms>\r
-               <wsag:All>\r
-                       <!-- FUNCTIONAL DESCRIPTION -->\r
-                       <wsag:ServiceDescriptionTerm Name="SDTName1" ServiceName="ServiceName">\r
-                               DSL expression\r
-                       </wsag:ServiceDescriptionTerm>\r
-                       <wsag:ServiceDescriptionTerm Name="SDTName2" ServiceName="ServiceName">\r
-                               DSL expression\r
-                       </wsag:ServiceDescriptionTerm>\r
-                       \r
-                       <!-- OPTIONAL SERVICE REFERENCE -->\r
-                       \r
-                       <!-- OPTIONAL SERVICE PROPERTIES : non funcional properties-->\r
-                       <wsag:ServiceProperties Name="NonFunctional" ServiceName="ServiceName">\r
-                               <wsag:VariableSet>\r
-                                       <wsag:Variable Name="ResponseTime" Metric="xs:double">\r
-                                               <wsag:Location>qos:ResponseTime</wsag:Location>\r
-                                       </wsag:Variable>\r
-                                       <wsag:Variable Name="Performance" Metric="xs:double">\r
-                                               <wsag:Location>qos:Performance</wsag:Location>\r
-                                       </wsag:Variable>\r
-                               </wsag:VariableSet>\r
-                       </wsag:ServiceProperties>\r
-                       <wsag:GuaranteeTerm Name="GT_ResponseTime">\r
-                               <wsag:ServiceScope ServiceName="ServiceName"/>\r
-                               <!-- The qualifying conditions that must be met before the guarantee is evaluated -->\r
-                               <!-- \r
-                               <wsag:QualifyingCondition>state EQ 'ready'</wsag:QualifyingCondition>\r
-                               -->\r
-                               <wsag:ServiceLevelObjective>\r
-                                       <wsag:KPITarget>\r
-                                               <wsag:KPIName>ResponseTime</wsag:KPIName> <!--  same name as property for the moment -->\r
-                                               <wsag:CustomServiceLevel>{"constraint" : "ResponseTime LT 0.9"}</wsag:CustomServiceLevel> <!--  the ServiceProperty is referenced here -->\r
-                                       </wsag:KPITarget>\r
-                               </wsag:ServiceLevelObjective>\r
-                       </wsag:GuaranteeTerm>\r
-                       <wsag:GuaranteeTerm Name="GT_Performance">\r
-                               <wsag:ServiceScope ServiceName="ServiceName"/>\r
-                               <wsag:ServiceLevelObjective>\r
-                                       <wsag:KPITarget>\r
-                                               <wsag:KPIName>Performance</wsag:KPIName> <!--  same name as property for the moment -->\r
-                                               <wsag:CustomServiceLevel>{"constraint" : "Performance GT 0.1"}</wsag:CustomServiceLevel>\r
-                                       </wsag:KPITarget>\r
-                               </wsag:ServiceLevelObjective>\r
-                               <wsag:BusinessValueList>\r
-                                       <wsag:Importante>3</wsag:Importante>    <!-- optional importance (integer) -->\r
-                                       <wsag:Penalty>\r
-                                               <wsag:AssessmentInterval>\r
-                                                       <wsag:Count>10</wsag:Count>\r
-                                               </wsag:AssessmentInterval>\r
-                                               <wsag:ValueUnit>EUR</wsag:ValueUnit>\r
-                                               <wsag:ValueExpression>99</wsag:ValueExpression>\r
-                                       </wsag:Penalty>\r
-                                       \r
-                                       <wsag:Reward></wsag:Reward>\r
-                                       <wsag:Preference></wsag:Preference>\r
-                                       <wsag:CustomBusinessValue></wsag:CustomBusinessValue>\r
-                               </wsag:BusinessValueList>\r
-                       </wsag:GuaranteeTerm>\r
-               </wsag:All>\r
-       </wsag:Terms>\r
-</wsag:Agreement>\r
diff --git a/sla/sla_utils/samples/old/agreement03_old.xml b/sla/sla_utils/samples/old/agreement03_old.xml
deleted file mode 100755 (executable)
index 291ff4c..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>\r
-<wsag:Agreement xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement"\r
-       AgreementId="agreement03">\r
-\r
-       <wsag:Name>ExampleAgreement</wsag:Name>\r
-       <wsag:Context>\r
-               <wsag:AgreementInitiator>experimenter01</wsag:AgreementInitiator>\r
-               <wsag:AgreementResponder>virtualwall</wsag:AgreementResponder>\r
-               <wsag:ServiceProvider>AgreementResponder</wsag:ServiceProvider>\r
-               <wsag:ExpirationTime>2014-03-07T12:00:00</wsag:ExpirationTime>\r
-               <wsag:TemplateId>template02</wsag:TemplateId>\r
-               <sla:Service xmlns:sla="http://sla.atos.eu">Testbed_guarantee_0.75_Uptime_rate_for_0.8_rate_of_the_resources_during_the_sliver</sla:Service>\r
-       </wsag:Context>\r
-       <wsag:Terms>\r
-               <wsag:All>\r
-                       <!--\r
-                       <wsag:ServiceDescriptionTerm Name="SDTName1" ServiceName="ServiceName">\r
-                               { "servicename": "service-prueba" }\r
-                       </wsag:ServiceDescriptionTerm>\r
-                       -->\r
-                       <wsag:ServiceProperties Name="ServiceProperties" ServiceName="ServiceName">\r
-                               <wsag:VariableSet>\r
-                                       <wsag:Variable Name="ResponseTime" Metric="xs:double">\r
-                                               <wsag:Location>service-prueba/ResponseTime</wsag:Location>\r
-                                       </wsag:Variable>\r
-                                       <wsag:Variable Name="Performance" Metric="xs:double">\r
-                                               <wsag:Location>service-prueba/Performance</wsag:Location>\r
-                                       </wsag:Variable>\r
-                               </wsag:VariableSet>\r
-                       </wsag:ServiceProperties>\r
-                       <wsag:GuaranteeTerm Name="GT_ResponseTime">\r
-                               <wsag:ServiceScope ServiceName="ServiceName"/>\r
-                               <wsag:ServiceLevelObjective>\r
-                                       <wsag:KPITarget>\r
-                                               <wsag:KPIName>ResponseTime</wsag:KPIName>\r
-                                               <wsag:CustomServiceLevel>\r
-                                                       {"constraint" : "ResponseTime BETWEEN (0, 200)"}\r
-                                               </wsag:CustomServiceLevel>\r
-                                       </wsag:KPITarget>\r
-                               </wsag:ServiceLevelObjective>\r
-                       </wsag:GuaranteeTerm>\r
-                       <wsag:GuaranteeTerm Name="GT_Performance">\r
-                               <wsag:ServiceScope ServiceName="ServiceName"/>\r
-                               <wsag:ServiceLevelObjective>\r
-                                       <wsag:KPITarget>\r
-                                               <wsag:KPIName>Performance</wsag:KPIName>\r
-                                               <wsag:CustomServiceLevel>\r
-                                                       {"constraint" : "Performance BETWEEN (0.1,1)"}\r
-                                               </wsag:CustomServiceLevel>\r
-                                       </wsag:KPITarget>\r
-                               </wsag:ServiceLevelObjective>\r
-                       </wsag:GuaranteeTerm>\r
-               </wsag:All>\r
-       </wsag:Terms>\r
-</wsag:Agreement>\r
diff --git a/sla/sla_utils/samples/old/agreement04_old.xml b/sla/sla_utils/samples/old/agreement04_old.xml
deleted file mode 100755 (executable)
index 28d3dd6..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>\r
-<wsag:Agreement xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement"\r
-       AgreementId="agreement04">\r
-\r
-       <wsag:Name>ExampleAgreement</wsag:Name>\r
-       <wsag:Context>\r
-               <wsag:AgreementInitiator>experimenter01</wsag:AgreementInitiator>\r
-               <wsag:AgreementResponder>wiLab2</wsag:AgreementResponder>\r
-               <wsag:ServiceProvider>AgreementResponder</wsag:ServiceProvider>\r
-               <wsag:ExpirationTime>2014-03-07T12:00:00</wsag:ExpirationTime>\r
-               <wsag:TemplateId>template02</wsag:TemplateId>\r
-               <sla:Service xmlns:sla="http://sla.atos.eu">Testbed_guarantee_0.80_uptime_rate_for_0.75_rate_of_the_resources_during_the_sliver</sla:Service>\r
-       </wsag:Context>\r
-       <wsag:Terms>\r
-               <wsag:All>\r
-                       <wsag:ServiceProperties Name="ServiceProperties" ServiceName="ServiceName">\r
-                               <wsag:VariableSet>\r
-                                       <wsag:Variable Name="metric1" Metric="xs:double">\r
-                                               <wsag:Location>metric1</wsag:Location>\r
-                                       </wsag:Variable>\r
-                                       <wsag:Variable Name="metric2" Metric="xs:double">\r
-                                               <wsag:Location>metric2</wsag:Location>\r
-                                       </wsag:Variable>\r
-                                       <wsag:Variable Name="metric3" Metric="xs:double">\r
-                                               <wsag:Location>metric3</wsag:Location>\r
-                                       </wsag:Variable>\r
-                               </wsag:VariableSet>\r
-                       </wsag:ServiceProperties>\r
-                       <wsag:GuaranteeTerm Name="GT_Metric1">\r
-                               <wsag:ServiceScope ServiceName="ServiceName"/>\r
-                               <wsag:ServiceLevelObjective>\r
-                                       <wsag:KPITarget>\r
-                                               <wsag:KPIName>metric1</wsag:KPIName>\r
-                                               <wsag:CustomServiceLevel>\r
-                                                       {"constraint" : "metric1 BETWEEN (0.1, 1)"}\r
-                                               </wsag:CustomServiceLevel>\r
-                                       </wsag:KPITarget>\r
-                               </wsag:ServiceLevelObjective>\r
-                       </wsag:GuaranteeTerm>\r
-                       <wsag:GuaranteeTerm Name="GT_Metric2">\r
-                               <wsag:ServiceScope ServiceName="ServiceName"/>\r
-                               <wsag:ServiceLevelObjective>\r
-                                       <wsag:KPITarget>\r
-                                               <wsag:KPIName>metric2</wsag:KPIName>\r
-                                               <wsag:CustomServiceLevel>\r
-                                                       {"constraint" : "metric2 BETWEEN (0.15, 1)"}\r
-                                               </wsag:CustomServiceLevel>\r
-                                       </wsag:KPITarget>\r
-                               </wsag:ServiceLevelObjective>\r
-                       </wsag:GuaranteeTerm>\r
-                       <wsag:GuaranteeTerm Name="GT_Metric3">\r
-                               <wsag:ServiceScope ServiceName="ServiceName"/>\r
-                               <wsag:ServiceLevelObjective>\r
-                                       <wsag:KPITarget>\r
-                                               <wsag:KPIName>metric3</wsag:KPIName>\r
-                                               <wsag:CustomServiceLevel>\r
-                                                       {"constraint" : "metric3 BETWEEN (0.2, 1)"}\r
-                                               </wsag:CustomServiceLevel>\r
-                                       </wsag:KPITarget>\r
-                               </wsag:ServiceLevelObjective>\r
-                       </wsag:GuaranteeTerm>\r
-               </wsag:All>\r
-       </wsag:Terms>\r
-</wsag:Agreement>\r
diff --git a/sla/sla_utils/samples/old/agreement05.xml b/sla/sla_utils/samples/old/agreement05.xml
deleted file mode 100755 (executable)
index bd7c35c..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>\r
-<wsag:Agreement xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement"\r
-       AgreementId="agreement05">\r
-\r
-       <wsag:Name>ExampleAgreement</wsag:Name>\r
-       <wsag:Context>\r
-               <wsag:AgreementInitiator>client-prueba</wsag:AgreementInitiator>\r
-               <wsag:AgreementResponder>f4c993580-03fe-41eb-8a21-a56709f9370f</wsag:AgreementResponder>\r
-               <wsag:ServiceProvider>AgreementResponder</wsag:ServiceProvider>\r
-               <wsag:ExpirationTime>2014-03-07T12:00:00</wsag:ExpirationTime>\r
-               <wsag:TemplateId>template02</wsag:TemplateId>\r
-               <sla:Service xmlns:sla="http://sla.atos.eu">service5</sla:Service>\r
-       </wsag:Context>\r
-       <wsag:Terms>\r
-               <wsag:All>\r
-                       <wsag:ServiceProperties Name="ServiceProperties" ServiceName="ServiceName">\r
-                               <wsag:VariableSet>\r
-                                       <wsag:Variable Name="metric1" Metric="xs:double">\r
-                                               <wsag:Location>metric1</wsag:Location>\r
-                                       </wsag:Variable>\r
-                                       <wsag:Variable Name="metric2" Metric="xs:double">\r
-                                               <wsag:Location>metric2</wsag:Location>\r
-                                       </wsag:Variable>\r
-                                       <wsag:Variable Name="metric3" Metric="xs:double">\r
-                                               <wsag:Location>metric3</wsag:Location>\r
-                                       </wsag:Variable>\r
-                                       <wsag:Variable Name="metric4" Metric="xs:double">\r
-                                               <wsag:Location>metric4</wsag:Location>\r
-                                       </wsag:Variable>\r
-                               </wsag:VariableSet>\r
-                       </wsag:ServiceProperties>\r
-                       <wsag:GuaranteeTerm Name="GT_Metric1">\r
-                               <wsag:ServiceScope ServiceName="ServiceName"/>\r
-                               <wsag:ServiceLevelObjective>\r
-                                       <wsag:KPITarget>\r
-                                               <wsag:KPIName>metric1</wsag:KPIName>\r
-                                               <wsag:CustomServiceLevel>\r
-                                                       {"constraint" : "metric1 BETWEEN (0.05, 1)"}\r
-                                               </wsag:CustomServiceLevel>\r
-                                       </wsag:KPITarget>\r
-                               </wsag:ServiceLevelObjective>\r
-                       </wsag:GuaranteeTerm>\r
-                       <wsag:GuaranteeTerm Name="GT_Metric2">\r
-                               <wsag:ServiceScope ServiceName="ServiceName"/>\r
-                               <wsag:ServiceLevelObjective>\r
-                                       <wsag:KPITarget>\r
-                                               <wsag:KPIName>metric2</wsag:KPIName>\r
-                                               <wsag:CustomServiceLevel>\r
-                                                       {"constraint" : "metric2 BETWEEN (0.1, 1)"}\r
-                                               </wsag:CustomServiceLevel>\r
-                                       </wsag:KPITarget>\r
-                               </wsag:ServiceLevelObjective>\r
-                       </wsag:GuaranteeTerm>\r
-                       <wsag:GuaranteeTerm Name="GT_Metric3">\r
-                               <wsag:ServiceScope ServiceName="ServiceName"/>\r
-                               <wsag:ServiceLevelObjective>\r
-                                       <wsag:KPITarget>\r
-                                               <wsag:KPIName>metric3</wsag:KPIName>\r
-                                               <wsag:CustomServiceLevel>\r
-                                                       {"constraint" : "metric3 BETWEEN (0.15, 1)"}\r
-                                               </wsag:CustomServiceLevel>\r
-                                       </wsag:KPITarget>\r
-                               </wsag:ServiceLevelObjective>\r
-                       </wsag:GuaranteeTerm>\r
-                       <wsag:GuaranteeTerm Name="GT_Metric4">\r
-                               <wsag:ServiceScope ServiceName="ServiceName"/>\r
-                               <wsag:ServiceLevelObjective>\r
-                                       <wsag:KPITarget>\r
-                                               <wsag:KPIName>metric4</wsag:KPIName>\r
-                                               <wsag:CustomServiceLevel>\r
-                                                       {"constraint" : "metric4 BETWEEN (0.2, 1)"}\r
-                                               </wsag:CustomServiceLevel>\r
-                                       </wsag:KPITarget>\r
-                               </wsag:ServiceLevelObjective>\r
-                       </wsag:GuaranteeTerm>\r
-               </wsag:All>\r
-       </wsag:Terms>\r
-</wsag:Agreement>\r
diff --git a/sla/sla_utils/samples/old/agreement05_old.xml b/sla/sla_utils/samples/old/agreement05_old.xml
deleted file mode 100755 (executable)
index 777a1e6..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>\r
-<wsag:Agreement xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement"\r
-       AgreementId="agreement05">\r
-\r
-       <wsag:Name>ExampleAgreement</wsag:Name>\r
-       <wsag:Context>\r
-               <wsag:AgreementInitiator>experimenter01</wsag:AgreementInitiator>\r
-               <wsag:AgreementResponder>virtualwall</wsag:AgreementResponder>\r
-               <wsag:ServiceProvider>AgreementResponder</wsag:ServiceProvider>\r
-               <wsag:ExpirationTime>2014-03-07T12:00:00</wsag:ExpirationTime>\r
-               <wsag:TemplateId>template02</wsag:TemplateId>\r
-               <sla:Service xmlns:sla="http://sla.atos.eu">service5</sla:Service>\r
-       </wsag:Context>\r
-       <wsag:Terms>\r
-               <wsag:All>\r
-                       <wsag:ServiceProperties Name="ServiceProperties" ServiceName="ServiceName">\r
-                               <wsag:VariableSet>\r
-                                       <wsag:Variable Name="metric1" Metric="xs:double">\r
-                                               <wsag:Location>metric1</wsag:Location>\r
-                                       </wsag:Variable>\r
-                                       <wsag:Variable Name="metric2" Metric="xs:double">\r
-                                               <wsag:Location>metric2</wsag:Location>\r
-                                       </wsag:Variable>\r
-                                       <wsag:Variable Name="metric3" Metric="xs:double">\r
-                                               <wsag:Location>metric3</wsag:Location>\r
-                                       </wsag:Variable>\r
-                                       <wsag:Variable Name="metric4" Metric="xs:double">\r
-                                               <wsag:Location>metric4</wsag:Location>\r
-                                       </wsag:Variable>\r
-                               </wsag:VariableSet>\r
-                       </wsag:ServiceProperties>\r
-                       <wsag:GuaranteeTerm Name="GT_Metric1">\r
-                               <wsag:ServiceScope ServiceName="ServiceName"/>\r
-                               <wsag:ServiceLevelObjective>\r
-                                       <wsag:KPITarget>\r
-                                               <wsag:KPIName>metric1</wsag:KPIName>\r
-                                               <wsag:CustomServiceLevel>\r
-                                                       {"constraint" : "metric1 BETWEEN (0.05, 1)"}\r
-                                               </wsag:CustomServiceLevel>\r
-                                       </wsag:KPITarget>\r
-                               </wsag:ServiceLevelObjective>\r
-                       </wsag:GuaranteeTerm>\r
-                       <wsag:GuaranteeTerm Name="GT_Metric2">\r
-                               <wsag:ServiceScope ServiceName="ServiceName"/>\r
-                               <wsag:ServiceLevelObjective>\r
-                                       <wsag:KPITarget>\r
-                                               <wsag:KPIName>metric2</wsag:KPIName>\r
-                                               <wsag:CustomServiceLevel>\r
-                                                       {"constraint" : "metric2 BETWEEN (0.1, 1)"}\r
-                                               </wsag:CustomServiceLevel>\r
-                                       </wsag:KPITarget>\r
-                               </wsag:ServiceLevelObjective>\r
-                       </wsag:GuaranteeTerm>\r
-                       <wsag:GuaranteeTerm Name="GT_Metric3">\r
-                               <wsag:ServiceScope ServiceName="ServiceName"/>\r
-                               <wsag:ServiceLevelObjective>\r
-                                       <wsag:KPITarget>\r
-                                               <wsag:KPIName>metric3</wsag:KPIName>\r
-                                               <wsag:CustomServiceLevel>\r
-                                                       {"constraint" : "metric3 BETWEEN (0.15, 1)"}\r
-                                               </wsag:CustomServiceLevel>\r
-                                       </wsag:KPITarget>\r
-                               </wsag:ServiceLevelObjective>\r
-                       </wsag:GuaranteeTerm>\r
-                       <wsag:GuaranteeTerm Name="GT_Metric4">\r
-                               <wsag:ServiceScope ServiceName="ServiceName"/>\r
-                               <wsag:ServiceLevelObjective>\r
-                                       <wsag:KPITarget>\r
-                                               <wsag:KPIName>metric4</wsag:KPIName>\r
-                                               <wsag:CustomServiceLevel>\r
-                                                       {"constraint" : "metric4 BETWEEN (0.2, 1)"}\r
-                                               </wsag:CustomServiceLevel>\r
-                                       </wsag:KPITarget>\r
-                               </wsag:ServiceLevelObjective>\r
-                       </wsag:GuaranteeTerm>\r
-               </wsag:All>\r
-       </wsag:Terms>\r
-</wsag:Agreement>\r
diff --git a/sla/sla_utils/samples/old/enforcement.xml b/sla/sla_utils/samples/old/enforcement.xml
deleted file mode 100755 (executable)
index bf2f5a9..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-<enforcement_job>
-    <agreement_id>agreement04</agreement_id>
-    <enabled>false</enabled>
-</enforcement_job>
diff --git a/sla/sla_utils/samples/old/enforcement02.xml b/sla/sla_utils/samples/old/enforcement02.xml
deleted file mode 100755 (executable)
index e81c83d..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-<enforcement_job>
-    <agreement_id>agreement02</agreement_id>
-    <enabled>true</enabled>
-</enforcement_job>
diff --git a/sla/sla_utils/samples/old/enforcement05.xml b/sla/sla_utils/samples/old/enforcement05.xml
deleted file mode 100755 (executable)
index 1b4dc7e..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-<enforcement_job>
-    <agreement_id>agreement05</agreement_id>
-    <enabled>true</enabled>
-</enforcement_job>
diff --git a/sla/sla_utils/samples/old/template01.xml b/sla/sla_utils/samples/old/template01.xml
deleted file mode 100755 (executable)
index 90b24c1..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-From http://serviceqos.wikispaces.com/WSAgExample
- -->
-<wsag:Template xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement" TemplateId="contract-template-2007-12-04">
-   <wsag:Name>ExampleTemplate</wsag:Name>
-   <wsag:Context>
-      <wsag:AgreementInitiator>Provider</wsag:AgreementInitiator>
-      <wsag:ServiceProvider>AgreementInitiator</wsag:ServiceProvider>
-      <wsag:ExpirationTime>2013-12-15-1200</wsag:ExpirationTime>
-      <wsag:TemplateId>contract-template-2013-12-15</wsag:TemplateId>
-   </wsag:Context>
-   <wsag:Terms>
-      <wsag:All>
-         <!-- functional description --> 
-         <wsag:ServiceDescriptionTerm
-            wsag:Name="General" 
-            wsag:ServiceName="Service0001">
-            A GPS service
-         </wsag:ServiceDescriptionTerm>
-         <wsag:ServiceDescriptionTerm
-            wsag:Name="GetCoordsOperation" 
-            wsag:ServiceName="GPSService0001">
-            operation to call to get the coords
-         </wsag:ServiceDescriptionTerm>
-         <!-- domain specific reference to a service (additional or optional to SDT) --> 
-         <wsag:ServiceReference 
-            wsag:Name="CoordsRequest" 
-            wsag:ServiceName="GPSService0001">
-        <wsag:EndpointReference>
-               <wsag:Address>http://www.gps.com/coordsservice/getcoords</wsag:Address>
-               <wsag:ServiceName>gps:CoordsRequest</wsag:ServiceName>
-            </wsag:EndpointReference>
-         </wsag:ServiceReference>
-         <!-- non-functional properties -->
-         <wsag:ServiceProperties
-            wsag:Name="AvailabilityProperties" 
-            wsag:ServiceName="GPS0001">
-            <wsag:Variables>
-               <wsag:Variable 
-                  wsag:Name="ResponseTime" 
-                  wsag:Metric="metric:Duration">
-                  <wsag:Location>qos:ResponseTime</wsag:Location>
-               </wsag:Variable>
-            </wsag:Variables>
-         </wsag:ServiceProperties>
-         <wsag:ServiceProperties
-            wsag:Name="UsabilityProperties" 
-            wsag:ServiceName="GPS0001">
-            <wsag:Variables>
-               <wsag:Variable 
-                  wsag:Name="CoordDerivation" 
-                  wsag:Metric="metric:CoordDerivationMetric">
-                  <wsag:Location>qos:CoordDerivation</wsag:Location>
-               </wsag:Variable>
-            </wsag:Variables>
-         </wsag:ServiceProperties>
-         <!-- statements to offered service level(s) -->
-         <wsag:GuaranteeTerm 
-            Name="FastReaction" Obligated="ServiceProvider">
-            <wsag:ServiceScope ServiceName="GPS0001">
-               http://www.gps.com/coordsservice/getcoords
-            </wsag:ServiceScope>
-            <wsag:QualifyingCondition>
-               applied when current time in week working hours
-            </wsag:QualifyingCondition>
-            <wsag:ServiceLevelObjective>
-               <wsag:KPITarget>
-                  <wsag:KPIName>FastResponseTime</wsag:KPIName>
-                  <wsag:Target>
-                     //Variable/@Name="ResponseTime" LOWERTHAN 1 second
-                  </wsag:Target>
-               </wsag:KPITarget>
-            </wsag:ServiceLevelObjective>
-         </wsag:GuaranteeTerm>
-      </wsag:All>
-   </wsag:Terms>
-</wsag:Template>
diff --git a/sla/sla_utils/samples/provider-virtualwall.xml b/sla/sla_utils/samples/provider-virtualwall.xml
deleted file mode 100755 (executable)
index 6299a9f..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<provider>
-    <uuid>virtualwall</uuid>
-    <name>virtualwall</name>
-</provider>
diff --git a/sla/sla_utils/samples/provider-wilab2.xml b/sla/sla_utils/samples/provider-wilab2.xml
deleted file mode 100755 (executable)
index 2671656..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<provider>
-    <uuid>wiLab2</uuid>
-    <name>wiLab2</name>
-</provider>
diff --git a/sla/sla_utils/samples/template.xml b/sla/sla_utils/samples/template.xml
deleted file mode 100755 (executable)
index ab3ce59..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<wsag:Template xmlns:wsag="http://www.ggf.org/namespaces/ws-agreement"
-       TemplateId="template">
-       <wsag:Name>ExampleTemplate2</wsag:Name>
-       <wsag:Context>
-               <wsag:ExpirationTime>2014-03-07T12:00:00:000</wsag:ExpirationTime>
-       </wsag:Context>
-       <wsag:Terms>
-               <wsag:All>
-                       <!-- FUNCTIONAL DESCRIPTION -->
-                       <wsag:ServiceDescriptionTerm wsag:Name="SDTName1" wsag:ServiceName="ServiceName">
-                               DSL expression
-                       </wsag:ServiceDescriptionTerm>
-                       <wsag:ServiceDescriptionTerm wsag:Name="SDTName2" wsag:ServiceName="ServiceName">
-                               DSL expression
-                       </wsag:ServiceDescriptionTerm>
-                       
-                       <!-- OPTIONAL SERVICE REFERENCE -->
-                       
-                       <!-- OPTIONAL SERVICE PROPERTIES : non funcional properties-->
-                       <wsag:ServiceProperties wsag:Name="NonFunctional" wsag:ServiceName="ServiceName">
-                               <wsag:Variables>
-                                       <wsag:Variable wsag:Name="ResponseTime" wsag:Metric="xs:double">
-                                               <wsag:Location>qos:ResponseTime</wsag:Location>
-                                       </wsag:Variable>
-                                       <wsag:Variable wsag:Name="Performance" wsag:Metric="xs:double">
-                                               <wsag:Location>qos:Performance</wsag:Location>
-                                       </wsag:Variable>
-                               </wsag:Variables>
-                       </wsag:ServiceProperties>
-                       <wsag:GuaranteeTerm wsag:Name="GT_ResponseTime">
-                               <wsag:ServiceScope wsag:ServiceName="ServiceName"/>
-                               <!-- The qualifying conditions that must be met before the guarantee is evaluated -->
-                               <!-- 
-                               <wsag:QualifyingCondition>state EQ 'ready'</wsag:QualifyingCondition>
-                               -->
-                               <wsag:ServiceLevelObjective>
-                                       <wsag:KPITarget>
-                                               <wsag:KPIName>ResponseTime</wsag:KPIName> <!--  same name as property for the moment -->
-                                               <wsag:CustomServiceLevel>{"constraint" : "ResponseTime LT qos:ResponseTime"}</wsag:CustomServiceLevel> <!--  the ServiceProperty is referenced here -->
-                                       </wsag:KPITarget>
-                               </wsag:ServiceLevelObjective>
-                       </wsag:GuaranteeTerm>
-                       <wsag:GuaranteeTerm wsag:Name="GT_Performance">
-                               <wsag:ServiceScope wsag:ServiceName="ServiceName"/>
-                               <wsag:ServiceLevelObjective>
-                                       <wsag:KPITarget>
-                                               <wsag:KPIName>Performance</wsag:KPIName> <!--  same name as property for the moment -->
-                                               <wsag:CustomServiceLevel>{"constraint" : "Performance GT qos:Performance"}</wsag:CustomServiceLevel>
-                                       </wsag:KPITarget>
-                               </wsag:ServiceLevelObjective>
-                               <wsag:BusinessValueList>
-                                       <wsag:Importante>3</wsag:Importante>    <!-- optional importance (integer) -->
-                                       <wsag:Penalty>
-                                               <wsag:AssessmentInterval>
-                                                       <wsag:Count>10</wsag:Count>
-                                               </wsag:AssessmentInterval>
-                                               <wsag:ValueUnit>EUR</wsag:ValueUnit>
-                                               <wsag:ValueExpression>99</wsag:ValueExpression>
-                                       </wsag:Penalty>
-                                       
-                                       <wsag:Reward></wsag:Reward>
-                                       <wsag:Preference></wsag:Preference>
-                                       <wsag:CustomBusinessValue></wsag:CustomBusinessValue>
-                               </wsag:BusinessValueList>
-                       </wsag:GuaranteeTerm>
-               </wsag:All>
-       </wsag:Terms>
-</wsag:Template>
index 8091f4e..a344554 100755 (executable)
@@ -3,6 +3,7 @@
 import requests
 
 from requests.auth import HTTPBasicAuth
+from myslice.settings import logger
 
 import xmlconverter
 import wsag_model
@@ -38,17 +39,17 @@ _TEMPLATES_PATH = "templates"
 _VIOLATIONS_PATH = "violations"
 _ENFORCEMENTJOBS_PATH = "enforcements"
 
-rooturl = settings.SLA_MANAGER_URL
+rooturl = settings.SLA_COLLECTOR_URL
 
 
 class Factory(object):
     @staticmethod
-    def agreements(path=_AGREEMENTS_PATH):
+    def agreements():
         """Returns a REST client for Agreements
 
         :rtype : Agreements
          """
-        return Agreements(rooturl, path)
+        return Agreements(rooturl)
 
     @staticmethod
     def providers():
@@ -111,23 +112,25 @@ class Client(object):
             c = Client("http://localhost:8080/service")
             c.get("/resource", headers = { "accept": "application/json" })
         """
-        url = _buildpath_(self.rooturl, path)
+        url = _buildpath(self.rooturl, path)
         if "testbed" in kwargs:
             url = url + "?testbed=" + kwargs["testbed"]
 
         if "headers" not in kwargs:
             kwargs["headers"] = {"accept": "application/xml"}
 
-        kwargs["auth"] = HTTPBasicAuth(settings.SLA_MANAGER_USER,
-                                       settings.SLA_MANAGER_PASSWORD)
+
+        kwargs["auth"] = HTTPBasicAuth(settings.SLA_COLLECTOR_USER,
+                                       settings.SLA_COLLECTOR_PASSWORD)
 
         # for key, values in kwargs.iteritems():
         #     print key, values
 
         result = requests.get(url, **kwargs)
-        print "GET {} {} {}".format(
-            result.url, result.status_code, result.text[0:70])
-        print result.encoding
+        logger.debug('SLA GET {} - result: {}'.format(result.url, result.status_code))
+        # print "GET {} {} {}".format(
+        #     result.url, result.status_code, result.text[0:70])
+        # print result.encoding
 
         return result
 
@@ -150,22 +153,23 @@ class Client(object):
                 }
             )
         """
-        url = _buildpath_(self.rooturl, path)
+        url = _buildpath(self.rooturl, path)
 
         if "testbed" in kwargs:
             url = url + "?testbed=" + kwargs["testbed"]
+            del kwargs["testbed"]
 
         if "headers" not in kwargs:
             kwargs["headers"] = {"accept": "application/xml",
                                  "content-type": "application/xml"}
 
-        kwargs["auth"] = HTTPBasicAuth(settings.SLA_MANAGER_USER,
-                                       settings.SLA_MANAGER_PASSWORD)
+        kwargs["auth"] = HTTPBasicAuth(settings.SLA_COLLECTOR_USER,
+                                      settings.SLA_COLLECTOR_PASSWORD)
 
         result = requests.post(url, data, **kwargs)
         location = result.headers["location"] \
             if "location" in result.headers else "<null>"
-        print "POST {} {} Location: {}".format(
+        print "POST {} {} Location: {}".format(
             result.url, result.status_code, location)
         return result
 
@@ -228,13 +232,11 @@ class _Resource(object):
         resource = _Resource._processresult(r, self.converter)
         return resource, r
 
-    def get(self, path, params):
+    def get(self, path="", params={}):
         """Generic query over resource: GET /resource?q1=v1&q2=v2...
 
         :param dict[str,str] params: values to pass as get parameters
         """
-        if path is None:
-            path = ""
 
         r = self.client.get(path, params=params)
         resources = self._processresult(r, self.listconverter)
@@ -262,9 +264,9 @@ class Agreements(object):
 
         The final url to the resource is root_url + "/" + path
         """
-        resourceurl = _buildpath_(root_url, path)
-        converter = xmlconverter.AgreementConverter()
-        self.res = _Resource(resourceurl, converter)
+        self.resourceurl = _buildpath(root_url, path)
+        self.converter = xmlconverter.AgreementConverter()
+        self.res = _Resource(self.resourceurl, self.converter)
 
     def getall(self):
         """
@@ -301,12 +303,12 @@ class Agreements(object):
         :param str agreementid :
         :rtype : wsag_model.AgreementStatus
         """
-        path = _buildpath_(_AGREEMENTS_PATH, agreementid, "guaranteestatus")
+        # path = _buildpath(_AGREEMENTS_PATH, agreementid, "guaranteestatus")
+        path = _buildpath(agreementid, "guaranteestatus")
         r = self.res.client.get(path, headers={'accept': 'application/json'},
                                 params={'testbed': testbed})
 
         json_obj = r.json()
-
         status = wsag_model.AgreementStatus.json_decode(json_obj)
 
         return status, r
@@ -316,7 +318,9 @@ class Agreements(object):
 
         :rtype : list[wsag_model.Agreement]
         """
-        return self.res.get(slicename, dict())
+        self.resourceurl = _buildpath(rooturl, 'slice')
+        self.res = _Resource(self.resourceurl, self.converter)
+        return self.res.get(slicename)
 
     def create(self, agreement, testbed):
         """Create a new agreement
@@ -335,7 +339,7 @@ class Templates(object):
 
         The final url to the resource is root_url + "/" + path
         """
-        resourceurl = _buildpath_(root_url, path)
+        resourceurl = _buildpath(root_url, path)
         converter = xmlconverter.AgreementConverter()
         self.res = _Resource(resourceurl, converter)
 
@@ -370,7 +374,7 @@ class Providers(object):
 
         The final url to the resource is root_url + "/" + path
         """
-        resourceurl = _buildpath_(root_url, path)
+        resourceurl = _buildpath(root_url, path)
         converter = xmlconverter.ProviderConverter()
         self.res = _Resource(resourceurl, converter)
 
@@ -406,7 +410,7 @@ class Violations(object):
 
         The final url to the resource is root_url + "/" + path
         """
-        resourceurl = _buildpath_(root_url, path)
+        resourceurl = _buildpath(root_url, path)
         converter = xmlconverter.ViolationConverter()
         self.res = _Resource(resourceurl, converter)
 
@@ -445,7 +449,7 @@ class Enforcements(object):
 
         The final url to the resource is root_url + "/" + path
         """
-        resourceurl = _buildpath_(root_url, path)
+        resourceurl = _buildpath(root_url, path)
         converter = xmlconverter.EnforcementConverter()
         self.res = _Resource(resourceurl, converter)
 
@@ -465,7 +469,7 @@ class Enforcements(object):
         return self.res.getbyid(agreement_id, params={"testbed": testbed})
 
 
-def _buildpath_(*paths):
+def _buildpath(*paths):
     if "" in paths:
         paths = [path for path in paths if path != ""]
 
index 271a8f5..d190e30 100755 (executable)
@@ -165,10 +165,13 @@ class AgreementStatus(object):
             s = "<GuaranteeTermStatus(name='{}' status='{}')>"
             return s.format(self.name, self.status)
 
-    def __init__(self):
+    def __init__(self, lst=None):
         self.agreement_id = ""
         self.guaranteestatus = ""
-        self.guaranteeterms = []
+        if lst is None:
+            self.guaranteeterms = []
+        else:
+            self.guaranteeterms = lst
 
     def __repr__(self):
         return (
index d32a591..35dc58c 100755 (executable)
@@ -21,6 +21,7 @@ root = ElementTree.parse("file.xml")
 c.convert(root.getroot())
 
 """
+from myslice.settings import logger
 
 try:
     # Much faster and lighter library (C implementation)
@@ -200,8 +201,8 @@ class AgreementConverter(Converter):
         :param Element xmlroot: root element of xml to convert.
         :rtype: wsag_model.Agreement
         """
-        for name, value in xmlroot.attrib.items():
-            print '{0}="{1}"'.format(name, value)
+        for name, value in xmlroot.attrib.items():
+        #      logger.debug('SLA xmlconverter: {} = {}'.format(name, value))
 
         if xmlroot.tag in self.agreement_tags:
             result = Agreement()
@@ -280,7 +281,7 @@ class AgreementConverter(Converter):
         nss = self._namespaces
         for element in elements:
             servicename = _get_attribute(element, "ServiceName")
-            for var in element.findall("wsag:Variables/wsag:Variable", nss):
+            for var in element.findall("wsag:VariableSet/wsag:Variable", nss):
                 key, value = self._parse_property(var, servicename)
                 result[key] = value
 
index fea71f2..c9043f6 100755 (executable)
@@ -1,10 +1,17 @@
+from __future__ import print_function
+
 # this somehow is not used anymore - should it not be ?
+import ast
+from datetime import datetime
+import json
+import pytz
 from django.template import RequestContext
 from django.shortcuts import render_to_response
 from django.shortcuts import render
 from django import forms
+import re
 
-from unfold.loginrequired import FreeAccessView
+from unfold.loginrequired import LoginRequiredView, FreeAccessView
 from unfold.page import Page
 from sla.slaclient import restclient
 from sla.slaclient import wsag_model
@@ -15,144 +22,146 @@ from django.core.urlresolvers import reverse
 from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
 
 import slaclient.service.fed4fire.fed4fireservice as fed4fireservice
-from rest_framework.views import APIView
 from django.http import HttpResponse
 
-import json
-import traceback
-import re
-from math import ceil
-from datetime import datetime
-from dateutil.relativedelta import relativedelta
-from dateutil.tz import tzlocal
-from django.conf import settings
-
-
-class Rol:
-    CONSUMER = "CONSUMER"
-    PROVIDER = "PROVIDER"
-
-
-class AgreementsFilter(object):
-    def __init__(self, status=None, provider=None, consumer=None):
-        self.status = status
-        self.provider = provider
-        self.consumer = consumer
-
-    def __repr__(self):
-        return "<AgreementsFilter(status={}, provider={}, consumer={})>".format(
-            self.status, self.provider, self.consumer
-        )
-
-    @staticmethod
-    def _check(expectedvalue, actualvalue):
-        if expectedvalue is None or expectedvalue == '':
-            return True
-        else:
-            return actualvalue == expectedvalue
-
-    def check(self, agreement):
-        """Check if this agreement satisfy the filter.
-
-        The agreement must be previously annotated
-        """
-        guaranteestatus = agreement.guaranteestatus
-        provider = agreement.context.provider
-        consumer = agreement.context.consumer
-        return (
-            AgreementsFilter._check(self.status, guaranteestatus) and
-            AgreementsFilter._check(self.provider, provider) and
-            AgreementsFilter._check(self.consumer, consumer)
-        )
-
-
-class FilterForm(forms.Form):
-    _attrs = {'class': 'form-control'}
-    exclude = ()
-    status = forms.ChoiceField(
-        choices=[
-            ('', 'All'),
-            (wsag_model.AgreementStatus.StatusEnum.FULFILLED, 'Fulfilled'),
-            (wsag_model.AgreementStatus.StatusEnum.VIOLATED, 'Violated'),
-            (wsag_model.AgreementStatus.StatusEnum.NON_DETERMINED, 'Non determined')],
-        widget=forms.Select(attrs=_attrs),
-        required=False
-    )
-    provider = forms.CharField(
-        widget=forms.TextInput(attrs=_attrs),
-        required=False
-    )
-    consumer = forms.CharField(
-        widget=forms.TextInput(attrs=_attrs),
-        required=False
-    )
-
-
-class SLAView (FreeAccessView, ThemeView):
+from myslice.settings import logger, SLA_COLLECTOR_URL
+
+
+# class AgreementsFilter(object):
+# def __init__(self, status=None, provider=None, consumer=None):
+#         self.status = status
+#         self.provider = provider
+#         self.consumer = consumer
+#
+#     def __repr__(self):
+#         return "<AgreementsFilter(status={}, provider={}, consumer={})>".format(
+#             self.status, self.provider, self.consumer
+#         )
+#
+#     @staticmethod
+#     def _check(expectedvalue, actualvalue):
+#         if expectedvalue is None or expectedvalue == '':
+#             return True
+#         else:
+#             return actualvalue == expectedvalue
+#
+#     def check(self, agreement):
+#         """Check if this agreement satisfy the filter.
+#
+#         The agreement must be previously annotated
+#         """
+#         guaranteestatus = agreement.guaranteestatus
+#         provider = agreement.context.provider
+#         consumer = agreement.context.consumer
+#         return (
+#             AgreementsFilter._check(self.status, guaranteestatus) and
+#             AgreementsFilter._check(self.provider, provider) and
+#             AgreementsFilter._check(self.consumer, consumer)
+#         )
+
+
+# class FilterForm(forms.Form):
+#     _attrs = {'class': 'form-control'}
+#     exclude = ()
+#     status = forms.ChoiceField(
+#         choices=[
+#             ('', 'All'),
+#             (wsag_model.AgreementStatus.StatusEnum.FULFILLED, 'Fulfilled'),
+#             (wsag_model.AgreementStatus.StatusEnum.VIOLATED, 'Violated'),
+#             (wsag_model.AgreementStatus.StatusEnum.NON_DETERMINED, 'Non determined')],
+#         widget=forms.Select(attrs=_attrs),
+#         required=False
+#     )
+#     provider = forms.CharField(
+#         widget=forms.TextInput(attrs=_attrs),
+#         required=False
+#     )
+#     consumer = forms.CharField(
+#         widget=forms.TextInput(attrs=_attrs),
+#         required=False
+#     )
+
+
+class SLAView(FreeAccessView, ThemeView):
     template_name = 'slice-tab-sla.html'
 
-    def get (self, request, slicename, state=None):
+    def get(self, request, slicename):
+
+        page = Page(request)
 
-        page=Page(request)
+        # logger.debug("SLA slice name: {}".format(slicename))
 
-        consumer_id = None
+        consumer_id = None
         agreement_id = None
         enforcements = {}
         violations = {}
-        keys = ['provider','agreement','date','status','result','ok']
+        keys = ['provider', 'agreement',
+                'date', 'status', 'result',
+                'ok', 'slivers']
         ag_info = []
 
-        filter_ = None
-        form = FilterForm(request.GET)
-        if form.is_valid():
-            filter_ = _get_filter_from_form(form)
+        filter_ = None
+        form = FilterForm(request.GET)
+        if form.is_valid():
+            filter_ = _get_filter_from_form(form)
 
-        consumer_id = _get_consumer_id(request)
+        consumer_id = _get_consumer_id(request)
 
-        #agreements = _get_agreements(agreement_id, consumer_id=consumer_id, filter_=filter_)
-        agreements = _get_agreements(agreement_id, slice=slicename)
+        # agreements = _get_agreements(agreement_id, consumer_id=consumer_id, filter_=filter_)
+        agreements = _get_agreements_by_slice(slicename)
 
         for agreement in agreements:
             row = []
             provider = agreement.context.provider
-            row.append(provider) # Provider
-            row.append(agreement) # Agreement
-            row.append(agreement.context.time_formatted()) # Date
+            row.append(provider)  # Provider
+            row.append(agreement)  # Agreement
+            row.append(agreement.context.time_formatted())  # Date
 
             enf = _get_enforcement(agreement.agreement_id, provider)
+            # logger.debug("SLA guarantee status {}: {}".format(agreement.agreement_id,
+            #                                                   agreement.guaranteestatus))
 
             if enf.enabled == 'true':
-                row.append('Evaluating') # Status
-                row.append('') # Result
-                row('') # Ok
+                row.append('Evaluating')  # Status
+                row.append('')  # Result
+                row.append('')  # Ok
             else:
                 if agreement.guaranteestatus == "NON_DETERMINED":
-                    row.append('Provisioned') # Status
-                    row.append('') # Result
-                    row.append('') # Ok
-                
+                    row.append('Provisioned')  # Status
+                    row.append('')  # Result
+                    row.append('')  # Ok
+
                 else:
-                    row.append('Finished') # Status
+                    row.append('Finished')  # Status
 
                     violations_list = _get_agreement_violations(agreement.agreement_id, provider, "GT_Performance")
-                    
+
                     if len(violations_list) > 0:
-                        value = '%.2f'%float(violations_list[0].actual_value)
-                        row.append('%d'%(float(value)*100)) # Result
+                        value = '%.2f' % float(violations_list[0].actual_value)
+                        row.append('%d' % (float(value) * 100))  # Result
                     else:
-                        row.append('100') # Result
+                        row.append('100')  # Result
 
                     if agreement.guaranteestatus == "VIOLATED":
-                        row.append('false') # Ok
+                        row.append('false')  # Ok
 
                     if agreement.guaranteestatus == "FULFILLED":
-                        row.append('true') # Ok
+                        row.append('true')  # Ok
 
-            ag_info.append(dict(zip(keys,row)))
+            for _, terms in agreement.guaranteeterms.items():
+                try:
+                    s = ast.literal_eval(terms.scopes[0].scope.lstrip())
+                    logger.debug('SLA scope: {}'.format(s))
+                    row.append(s)
+                    break
+                except Exception as e:
+                    logger.debug("SLA EXCEPTION: {}".format(e.message))
+
+            ag_info.append(dict(zip(keys, row)))
 
         template_env = {}
-       # write something of our own instead
-       # more general variables expected in the template
+        # write something of our own instead
+        # more general variables expected in the template
         template_env['title'] = 'SLA Agreements'
         template_env['agreements'] = agreements
         template_env['username'] = request.user
@@ -161,90 +170,90 @@ class SLAView (FreeAccessView, ThemeView):
         template_env['last_violation_list'] = violations
         template_env['ag_info'] = ag_info
 
-
-       # the prelude object in page contains a summary of the requirements() for all plugins
-       # define {js,css}_{files,chunks}
+        # the prelude object in page contains a summary of the requirements() for all plugins
+        # define {js,css}_{files,chunks}
         prelude_env = page.prelude_env()
         template_env.update(prelude_env)
 
         return render_to_response(self.template_name, template_env, context_instance=RequestContext(request))
 
 
-class AgreementsFilter(object):
-    def __init__(self, status=None, provider=None, consumer=None):
-        self.status = status
-        self.provider = provider
-        self.consumer = consumer
-
-    def __repr__(self):
-        return "<AgreementsFilter(status={}, provider={}, consumer={})>".format(
-            self.status, self.provider, self.consumer
-        )
-
-    @staticmethod
-    def _check(expectedvalue, actualvalue):
-        if expectedvalue is None or expectedvalue == '':
-            return True
-        else:
-            return actualvalue == expectedvalue
-
-    def check(self, agreement):
-        """Check if this agreement satisfy the filter.
-
-        The agreement must be previously annotated
-        """
-        guaranteestatus = agreement.guaranteestatus
-        provider = agreement.context.provider
-        consumer = agreement.context.consumer
-        return (
-            AgreementsFilter._check(self.status, guaranteestatus) and
-            AgreementsFilter._check(self.provider, provider) and
-            AgreementsFilter._check(self.consumer, consumer)
-        )
-
-
-class ContactForm(forms.Form):
-    subject = forms.CharField(max_length=100)
-    message = forms.CharField()
-    sender = forms.EmailField()
-    cc_myself = forms.BooleanField(required=False)
-
-
-def _get_agreements_client(path=""):
-    return restclient.Factory.agreements(path)
+class AgreementsFilter(object):
+    def __init__(self, status=None, provider=None, consumer=None):
+        self.status = status
+        self.provider = provider
+        self.consumer = consumer
+#
+    def __repr__(self):
+        return "<AgreementsFilter(status={}, provider={}, consumer={})>".format(
+            self.status, self.provider, self.consumer
+        )
+#
+    @staticmethod
+    def _check(expectedvalue, actualvalue):
+        if expectedvalue is None or expectedvalue == '':
+            return True
+        else:
+            return actualvalue == expectedvalue
+#
+    def check(self, agreement):
+        """Check if this agreement satisfy the filter.
+#
+        The agreement must be previously annotated
+        """
+        guaranteestatus = agreement.guaranteestatus
+        provider = agreement.context.provider
+        consumer = agreement.context.consumer
+        return (
+            AgreementsFilter._check(self.status, guaranteestatus) and
+            AgreementsFilter._check(self.provider, provider) and
+            AgreementsFilter._check(self.consumer, consumer)
+        )
+
+
+class ContactForm(forms.Form):
+    subject = forms.CharField(max_length=100)
+    message = forms.CharField()
+    sender = forms.EmailField()
+    cc_myself = forms.BooleanField(required=False)
+
+
+def _get_agreements_client():
+    return restclient.Factory.agreements()
 
 
 def _get_violations_client():
     return restclient.Factory.violations()
 
+
 def _get_enforcements_client():
     return restclient.Factory.enforcements()
 
+
 def _get_consumer_id(request):
     return request.user
 
 
 def _get_agreement(agreement_id):
-
     agreements_client = _get_agreements_client()
     agreement, response = agreements_client.getbyid(agreement_id)
     return agreement
 
-def _get_enforcement(agreement_id, testbed):
 
+def _get_enforcement(agreement_id, testbed):
     enforcements_client = _get_enforcements_client()
     enforcement, response = enforcements_client.getbyagreement(agreement_id, testbed)
     return enforcement
 
-def _get_filter_from_form(form):
 
-    data = form.cleaned_data
-    result = AgreementsFilter(
-        data["status"], data["provider"], data["consumer"])
-    return result
+# def _get_filter_from_form(form):
+#
+#     data = form.cleaned_data
+#     result = AgreementsFilter(
+#         data["status"], data["provider"], data["consumer"])
+#     return result
 
 def agreement_term_violations(request, agreement_id, guarantee_name):
-
     page = Page(request)
     prelude_env = page.prelude_env()
 
@@ -252,12 +261,12 @@ def agreement_term_violations(request, agreement_id, guarantee_name):
     agreement = _get_agreement(agreement_id)
     violations = _get_agreement_violations(agreement_id, guarantee_name)
     annotator.annotate_agreement(agreement)
-    
+
     slicename = request.POST.get('slicename')
-    
-    paginator = Paginator(violations, 25) # Show 25 violations per page
+
+    paginator = Paginator(violations, 25)  # Show 25 violations per page
     page_num = request.GET.get('page')
-    
+
     try:
         violation_page = paginator.page(page_num)
     except PageNotAnInteger:
@@ -266,7 +275,7 @@ def agreement_term_violations(request, agreement_id, guarantee_name):
     except EmptyPage:
         # If page is out of range (e.g. 9999), deliver first page.
         violation_page = paginator.page(1)
+
     context = {
         'agreement_id': agreement_id,
         'guarantee_term': agreement.guaranteeterms[guarantee_name],
@@ -275,17 +284,20 @@ def agreement_term_violations(request, agreement_id, guarantee_name):
         'slicename': slicename,
         'last_violation': violations[-1].actual_value
     }
-    
+
     context.update(prelude_env)
-    
-    return render_to_response ('violations_template.html', context, context_instance=RequestContext(request))
+
+    return render_to_response('violations_template.html', context, context_instance=RequestContext(request))
+
+
 #     return render(request, 'violations_template.html', context)
 
+
+# TODO Change function to class
 def agreement_details(request, agreement_id):
-    
     page = Page(request)
     prelude_env = page.prelude_env()
-    
+
     annotator = wsag_helper.AgreementAnnotator()
     agreement = _get_agreement(agreement_id)
     violations = _get_agreement_violations(agreement_id)
@@ -299,35 +311,48 @@ def agreement_details(request, agreement_id):
         'status': status,
         'violations_by_date': violations_by_date
     }
-    
-    context.update(prelude_env)
-    
-    return render_to_response ('violations_template.html', context, context_instance=RequestContext(request))
-    #return render(request, 'agreement_detail.html', context)
 
-def _get_agreement(agreement_id):
+    context.update(prelude_env)
 
-    agreements_client = _get_agreements_client()
-    agreement, response = agreements_client.getbyid(agreement_id)
-    return agreement
+    return render_to_response('violations_template.html', context, context_instance=RequestContext(request))
+    #return render(request, 'agreement_detail.html', context)
 
-def _get_agreements(agreement_id, slice=None, provider_id=None, consumer_id=None, filter_=None):
 
+# def _get_agreements(agreement_id, slice=None, provider_id=None, consumer_id=None, filter_=None):
+#
+#     agreements_client = _get_agreements_client()
+#     if agreement_id is None:
+#         if consumer_id is not None:
+#             agreements, response = agreements_client.getbyconsumer(consumer_id)
+#         elif provider_id is not None:
+#             agreements, response = agreements_client.getbyprovider(provider_id)
+#         elif slice is not None:
+#             agreements_client = _get_agreements_client("slice")
+#             agreements, response = agreements_client.getbyslice(slice)
+#         else:
+#             raise ValueError(
+#                 "Invalid values: consumer_id and provider_id are None")
+#     else:
+#         agreement, response = agreements_client.getbyid(agreement_id)
+#         agreements = [agreement]
+#
+#     annotator = wsag_helper.AgreementAnnotator()
+#     for agreement in agreements:
+#         id_ = agreement.agreement_id
+#         testbed = agreement.context.provider
+#         status = _get_agreement_status(id_, testbed)
+#         annotator.annotate_agreement(agreement, status)
+#
+#     if filter_ is not None:
+#         print "FILTERING ", repr(filter_)
+#         agreements = filter(filter_.check, agreements)
+#     else:
+#         print "NOT FILTERING"
+#     return agreements
+
+def _get_agreements_by_slice(slice):
     agreements_client = _get_agreements_client()
-    if agreement_id is None:
-        if consumer_id is not None:
-            agreements, response = agreements_client.getbyconsumer(consumer_id)
-        elif provider_id is not None:
-            agreements, response = agreements_client.getbyprovider(provider_id)
-        elif slice is not None:
-            agreements_client = _get_agreements_client("slice")
-            agreements, response = agreements_client.getbyslice(slice)
-        else:
-            raise ValueError(
-                "Invalid values: consumer_id and provider_id are None")
-    else:
-        agreement, response = agreements_client.getbyid(agreement_id)
-        agreements = [agreement]
+    agreements, response = agreements_client.getbyslice(slice)
 
     annotator = wsag_helper.AgreementAnnotator()
     for agreement in agreements:
@@ -336,108 +361,73 @@ def _get_agreements(agreement_id, slice=None, provider_id=None, consumer_id=None
         status = _get_agreement_status(id_, testbed)
         annotator.annotate_agreement(agreement, status)
 
-    if filter_ is not None:
-        print "FILTERING ", repr(filter_)
-        agreements = filter(filter_.check, agreements);
-    else:
-        print "NOT FILTERING"
     return agreements
 
 
-def _get_agreements_by_consumer(consumer_id):
-
-    agreements_client = _get_agreements_client()
-    agreements, response = agreements_client.getbyconsumer(consumer_id)
-    return agreements
+def _get_agreements_by_consumer(consumer_id):
+#
+    agreements_client = _get_agreements_client()
+    agreements, response = agreements_client.getbyconsumer(consumer_id)
+    return agreements
 
 def _get_agreement_status(agreement_id, testbed):
-
     agreements_client = _get_agreements_client()
     status, response = agreements_client.getstatus(agreement_id, testbed)
     return status
 
-def _get_agreement_violations(agreement_id, testbed, term=None):
 
+def _get_agreement_violations(agreement_id, testbed, term=None):
     violations_client = _get_violations_client()
     violations, response = violations_client.getbyagreement(agreement_id, testbed, term)
     return violations
 
 
-class AgreementSimple(APIView):
+class Testbeds(FreeAccessView, ThemeView):
+    def get(self, request, *args, **kwargs):
+        c = restclient.Client(SLA_COLLECTOR_URL)
+        #url = settings.SLA_MANAGER_URL.replace("/sla","")
+        #c = restclient.Client(url)
+        # print "**** URL ******", url
+        SLAtestbeds = c.get("testbeds/")
+        # Future work: get SLA description for each testbed
 
-    regex = r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"
+        return HttpResponse(SLAtestbeds.text, content_type="application/json", status=SLAtestbeds.status_code)
 
-    def build_response(self, code, text):
-        response = HttpResponse(text, content_type="text/plain", status=code)
-        return response 
 
-    def post(self, request, **kwargs):
-        #import pdb; pdb.set_trace()
-        print "------------------------------------------------1"
-        data = request.POST
+class CreateAgreement(LoginRequiredView, ThemeView):
+    def post(self, request, *args, **kwargs):
 
-        url = settings.SLA_MANAGER_URL
-        c = restclient.Client(url)
-        # for key, value in request.DATA.items(): # jgarcia review this
-        #     data[key] = value
-        
-        # print "---- DATA: ----"
-        # print "Data type: ", type(data)
-        # for key in data:
-        #     print key, data.getlist(key)
+        c = restclient.Client(SLA_COLLECTOR_URL)
+        data = request.POST.copy()
 
-        try:
-            # template_id = data['template_id']
-            testbeds = data.getlist("testbeds")
-            user = data["user"]
-            resources = data.getlist("resources")
-            slice_id = data["slice"]
-        except:
-            print "FAIL!"
-            return self.build_response(400, 'Invalid data')
-
-        selected_resources = {}
-
-        now = datetime.now(tzlocal())
-        expiration_time = now + relativedelta(years=1)
-
-        for testbed in testbeds:
-            selected_resources[testbed] = [r for r in resources if testbed in r]
-            template_id = testbed
-            try:
-                print "Calling createagreementsimplified with template_id:",template_id,"and user:",user
-                result = fed4fireservice.createagreementsimplified(
-                            template_id, user, expiration_time, selected_resources)
-                print result
-            except Exception, e:
-                print traceback.format_exc()
-                print '%s (%s)' % (e, type(e))
-                return self.build_response(400, 'Problem creating agreement')
-
-            agreement_id = re.compile(self.regex).search(result.text).group(0)
-         
-            data = '{{ "id": "{}", \
-                      "slice": "{}", \
-                      "testbed": "{}" }}'.format(agreement_id, slice_id, testbed)
-
-            c.post(
-                "sliver",
-                data,
-                headers = {
-                    "content-type": "application/json",
-                    "accept": "application/xml"
-                }
-            )   
-
-        return self.build_response(200, result)            
-
-class Testbeds(APIView):
-    def get(self, request, **kwargs):
-        c = restclient.Client("http://157.193.215.125:4001/sla-collector")
-        #url = settings.SLA_MANAGER_URL.replace("/sla","")
-        #c = restclient.Client(url)
-        print "**** URL ******", url
-        SLAtestbeds = c.get("testbeds")
-        # Future work: get SLA description for each testbed
+        testbed_urn_regex = r"\+(.*?)\+"
+        pattern = re.compile(testbed_urn_regex)
+        testbed_urn = pattern.search(data["SLIVER_INFO_AGGREGATE_URN"]).group(1)
 
-        return HttpResponse(SLAtestbeds.text, content_type="application/json", status=SLAtestbeds.status_code)
+        # Fix for django QueryDict list parameters
+        slivers = data.getlist("SLIVER_INFO_URN[]")
+        data["SLIVER_INFO_URN"] = slivers
+        del data["SLIVER_INFO_URN[]"]
+
+        # Timestamp to ISO date + timezone
+        tstmp = data["SLIVER_INFO_EXPIRATION"]
+        dt = datetime.fromtimestamp(float(tstmp))
+        # gmt_2 = pytz.timezone("Etc/GMT-2")
+        # dlocal = gmt_2.localize(dt).isoformat()
+        dlocal = dt.isoformat() + "CET" # FIXME: hardcoded for demo purposes
+        data["SLIVER_INFO_EXPIRATION"] = dlocal
+
+        # logger.debug("SLA Agreement parameters: {}".format(data.dict()))
+        # import pdb; pdb.set_trace()
+
+        try:
+            response = c.post("agreementslist/", data=json.dumps(data),
+                              headers={"accept": "application/json",
+                                 "content-type": "application/json"})
+        except Exception as e:
+            # import traceback, sys
+            #
+            # traceback.print_exc(file=sys.stdout)
+            logger.debug("SLA Error: CreateAgreement {}".format(e.message))
+
+        return HttpResponse(response.text, status=response.status_code)
index 725d7d9..a737577 100755 (executable)
@@ -1,8 +1,8 @@
 
-<div class="col-md-2">
+<div class="col-md-1">
 </div>
 
- <div class="col-md-9">
+ <div class="col-md-10">
    <div class="row" id="agreements" style="padding-top:1em;">
     
         
                 <dt>Experimenter</dt>
                 <dd>{{ row.agreement.context.consumer|default:"&nbsp;" }}</dd>
                 <dt>Service</dt>
-                <dd>Testbed guarantees 0.99 Uptime rate for 0.99 rate of the resources during the sliver lifetime</dd>
+                <dd>Testbed guarantees 0.99 Uptime rate for 0.99 rate of the selected resources</dd>
                 <dt>Testbed</dt>
                 <dd>{{ row.agreement.context.testbed_formatted }}</dd>
                 <dt>Expiration date:</dt>
                 <dd>{{ row.date|default:"&nbsp;" }}</dd>
+
+                <dt>Covered resources:</dt>
+                {% for sliver in row.slivers %}
+                <dd>{{ sliver|default:"&nbsp;" }}</dd>
+                {% endfor %}
+
                        </div>
                        <div class="modal-footer">
                                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
@@ -66,7 +72,7 @@
                
           <td>{{ row.provider }}</td>
 
-          <td><a class="agreement-detail" data-toggle="modal" data-target="#agreementModal{{row.agreement.agreement_id}}">{{ row.agreement.context.template_id }}</a></td>
+          <td><a class="agreement-detail" data-toggle="modal" data-target="#agreementModal{{row.agreement.agreement_id}}">{{ row.agreement.agreement_id }}</a></td>
                  
           <td>{{ row.date }}</td>
           <td>{{ row.status }}</td>
diff --git a/sla/templates/violations_template.sublime-workspace b/sla/templates/violations_template.sublime-workspace
deleted file mode 100644 (file)
index 2de266d..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-{
-       "auto_complete":
-       {
-               "selected_items":
-               [
-               ]
-       },
-       "buffers":
-       [
-               {
-                       "file": "slice-tab-sla.html",
-                       "settings":
-                       {
-                               "buffer_size": 6021,
-                               "line_ending": "Unix"
-                       }
-               }
-       ],
-       "build_system": "",
-       "command_palette":
-       {
-               "height": 0.0,
-               "selected_items":
-               [
-               ],
-               "width": 0.0
-       },
-       "console":
-       {
-               "height": 0.0,
-               "history":
-               [
-               ]
-       },
-       "distraction_free":
-       {
-               "menu_visible": true,
-               "show_minimap": false,
-               "show_open_files": false,
-               "show_tabs": false,
-               "side_bar_visible": false,
-               "status_bar_visible": false
-       },
-       "file_history":
-       [
-       ],
-       "find":
-       {
-               "height": 0.0
-       },
-       "find_in_files":
-       {
-               "height": 0.0,
-               "where_history":
-               [
-               ]
-       },
-       "find_state":
-       {
-               "case_sensitive": false,
-               "find_history":
-               [
-               ],
-               "highlight": true,
-               "in_selection": false,
-               "preserve_case": false,
-               "regex": false,
-               "replace_history":
-               [
-               ],
-               "reverse": false,
-               "show_context": true,
-               "use_buffer2": true,
-               "whole_word": false,
-               "wrap": true
-       },
-       "groups":
-       [
-               {
-                       "selected": 0,
-                       "sheets":
-                       [
-                               {
-                                       "buffer": 0,
-                                       "file": "slice-tab-sla.html",
-                                       "semi_transient": false,
-                                       "settings":
-                                       {
-                                               "buffer_size": 6021,
-                                               "regions":
-                                               {
-                                               },
-                                               "selection":
-                                               [
-                                                       [
-                                                               0,
-                                                               0
-                                                       ]
-                                               ],
-                                               "settings":
-                                               {
-                                                       "syntax": "Packages/HTML/HTML.tmLanguage"
-                                               },
-                                               "translation.x": 0.0,
-                                               "translation.y": 0.0,
-                                               "zoom_level": 1.0
-                                       },
-                                       "stack_index": 0,
-                                       "type": "text"
-                               }
-                       ]
-               }
-       ],
-       "incremental_find":
-       {
-               "height": 0.0
-       },
-       "input":
-       {
-               "height": 0.0
-       },
-       "layout":
-       {
-               "cells":
-               [
-                       [
-                               0,
-                               0,
-                               1,
-                               1
-                       ]
-               ],
-               "cols":
-               [
-                       0.0,
-                       1.0
-               ],
-               "rows":
-               [
-                       0.0,
-                       1.0
-               ]
-       },
-       "menu_visible": true,
-       "output.find_results":
-       {
-               "height": 0.0
-       },
-       "project": "violations_template.sublime-project",
-       "replace":
-       {
-               "height": 0.0
-       },
-       "save_all_on_build": true,
-       "select_file":
-       {
-               "height": 0.0,
-               "selected_items":
-               [
-               ],
-               "width": 0.0
-       },
-       "select_project":
-       {
-               "height": 0.0,
-               "selected_items":
-               [
-               ],
-               "width": 0.0
-       },
-       "select_symbol":
-       {
-               "height": 0.0,
-               "selected_items":
-               [
-               ],
-               "width": 0.0
-       },
-       "settings":
-       {
-       },
-       "show_minimap": true,
-       "show_open_files": false,
-       "show_tabs": true,
-       "side_bar_visible": true,
-       "side_bar_width": 150.0,
-       "status_bar_visible": true,
-       "template_settings":
-       {
-       }
-}
index 676d108..03ab14f 100755 (executable)
@@ -13,6 +13,8 @@ urlpatterns = patterns('',
             slicetabsla.agreement_details, name='agreement_details'),
        url(r'^agreements/(?P<agreement_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/guarantees/(?P<guarantee_name>\w+)/violations$',
             slicetabsla.agreement_term_violations, name='agreement_term_violations'),
-       url(r'^agreements/simplecreate/?$',
-            slicetabsla.AgreementSimple.as_view(), name="agreementsimple"),
+    url(r'^agreements/create/$',
+            slicetabsla.CreateAgreement.as_view(), name="agreement_create"),
+       # url(r'^agreements/simplecreate/?$',
+    #        slicetabsla.AgreementSimple.as_view(), name="agreementsimple"),
 )
index 2256ea9..162e828 100755 (executable)
@@ -1,5 +1,6 @@
 import re\r
 import datetime\r
+from myslice.settings import logger\r
 \r
 from slaclient import wsag_model\r
 from slaclient.wsag_model import AgreementStatus\r
index 2c2495c..3bcacc9 100644 (file)
@@ -4,6 +4,9 @@
 <!--<link rel='stylesheet' href='{{ STATIC_URL }}css/ui.notify.css' type='text/css' />-->
 
 <script type="text/javascript">
+// XXX disabled since jquery ui conflicts with bootstrap!
+
+/*
 function create( template, vars, opts ){
        return $container.notify("create", template, vars, opts);
 }
@@ -14,7 +17,6 @@ $(function(){
        // container, but can be overwritten on notification-by-notification
        // basis.
 
-       // XXX disabled since jquery ui conflicts with bootstrap!
        //$container = $("#notifications").notify();
        
        // create two when the pg loads
@@ -37,4 +39,5 @@ $(function(){
 
 
 });
+*/
 </script>
index 667711d..0c8d225 100644 (file)
@@ -1,5 +1,7 @@
 # a set of utilities to help make the global layout consistent across views
 
+from myslice.settings import logger
+
 def the_user (request):
     "retrieves logged in user's email, or empty string"
     if not request.user.is_authenticated (): 
@@ -22,7 +24,7 @@ def the_user (request):
 def topmenu_items_static (current, request):
     has_user=request.user.is_authenticated()
     result=[]
-    print request.user
+    logger.debug("request user = {}".format(request.user))
     if has_user:
         result.append({'label':'Dashboard', 'href': '/portal/dashboard/'})
         result.append({'label':'Request a slice', 'href': '/portal/slice_request/'})
@@ -58,7 +60,7 @@ def topmenu_items_static (current, request):
 
 # tmp - transition phase
 def topmenu_items (current, request):
-    print "WARNING -- please now use topmenu_items_live (label, page) toplevel_items is deprecated -- WARNING"
+    logger.warning("WARNING -- please now use topmenu_items_live (label, page) toplevel_items is deprecated -- WARNING")
     return topmenu_items_static (current, request)
 
 # integrated helper function for an animated menu
@@ -74,8 +76,11 @@ def topmenu_items_live (current, page):
     # We might use local storage instead
 
     # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
-    query_pi_auths = Query.get('myslice:user').filter_by('user_hrn', '==', '$user_hrn' ).select('user_hrn','pi_authorities')
-    page.enqueue_query(query_pi_auths)
+    if request.user.is_authenticated ():
+        query_pi_auths = Query.get('myslice:user').filter_by('user_hrn', '==', '$user_hrn' ).select('user_hrn','pi_authorities')
+        page.enqueue_query(query_pi_auths)
+    else:
+        query_pi_auths = Query()
 #        # even though this plugin does not have any html materialization, the corresponding domid
 #        # must exist because it is searched at init-time to create the JS plugin
 #        # so we simply piggy-back the target button created in the topmenu
index 0c6a1d2..bee1fe4 100644 (file)
@@ -1,3 +1,5 @@
+from __future__ import print_function
+
 import os
 from django.conf import settings
 from django.utils.datastructures import SortedDict
@@ -79,7 +81,7 @@ class ThirdPartyFinder(BaseFinder):
                         matched_path = os.path.join(path, file) 
                         if not all:
                             return matched_path
-                        print 'ThirdPartyFinder, adding',matched_path
+                        print('ThirdPartyFinder, adding',matched_path)
                         matches.append(matched_path)
         return matches
 
index f3d42fc..39be524 100644 (file)
@@ -1,5 +1,7 @@
 from unfold.plugin import Plugin
 
+from myslice.settings import logger
+
 class Composite (Plugin):
 
     """a simple base class for plugins that contain/arrange a set of other plugins
@@ -11,17 +13,17 @@ if a valid active_domid is not provided
 
     def __init__ (self, sons=None, active_domid=None, *args, **kwds):
         Plugin.__init__ (self, *args, **kwds)
-        self.sons= sons if sons else []
-        self.active_domid=active_domid
+        self.sons = sons if sons else []
+        self.active_domid = active_domid
         # make sure this is valid, unset otherwise, so we always have exactly one active
         self.check_active_domid()
         
     def check_active_domid(self):
         matches= [ son for son in self.sons if son.domid==self.active_domid ]
         if len(matches)!=1: 
-            print "WARNING: %s has %d valid son(s) for being active - expecting 1, resetting"%\
-                (self,len(matches))
-            self.active_domid=None
+            logger.warning("WARNING: {} has {} valid son(s) for being active - expecting 1, resetting"\
+                           .format(self,len(matches)))
+            self.active_domid = None
         
     def insert (self, plugin):
         self.sons.append(plugin)
@@ -31,9 +33,10 @@ if a valid active_domid is not provided
         # {% for son in sons %} {{ son.rendered }} ...
         def is_active (son,rank):
             # if active_domid is not specified, make the first one active
-            if not self.active_domid: return rank==0
-            return son.domid==self.active_domid
-        ranks=range(len(self.sons))
+            if not self.active_domid:
+                return rank==0
+            return son.domid == self.active_domid
+        ranks = range(len(self.sons))
         env = { 'sons':
                  [ { 'rendered': son.render(request),
                      'rank': rank,
index d4f9e98..afe24f3 100644 (file)
@@ -4,7 +4,9 @@ from django.http                        import HttpResponseRedirect
 # for 'as_view' that we need to call in urls.py and the like
 from django.views.generic.base          import TemplateView
 
-from manifoldapi.manifoldresult            import ManifoldException
+from manifoldapi.manifoldresult         import ManifoldException
+
+from myslice.settings import logger
 
 ###
 # IMPORTANT NOTE
@@ -33,7 +35,6 @@ class LoginRequiredView (TemplateView):
 
 def logout_on_manifold_exception (fun_that_returns_httpresponse):
     def wrapped (request, *args, **kwds):
-#        print 'wrapped by logout_on_manifold_exception'
         try:
             return fun_that_returns_httpresponse(request,*args, **kwds)
         except ManifoldException, manifold_result:
@@ -45,9 +46,9 @@ def logout_on_manifold_exception (fun_that_returns_httpresponse):
             return HttpResponseRedirect ('/')
         except Exception, e:
             # xxx we need to sugarcoat this error message in some error template...
-            print "Unexpected exception",e
+            logger.error("Unexpected exception {}".format(e))
             import traceback
-            traceback.print_exc()
+            logger.error(traceback.format_exc())
             return HttpResponseRedirect ('/')
     return wrapped
 
index 821c662..a9228ec 100644 (file)
@@ -9,8 +9,10 @@ from django.template.loader import render_to_string
 from manifoldapi.metadata import MetaData
 
 from unfold.prelude import Prelude
-
+from unfold.sessioncache import SessionCache
+    
 from myslice.configengine import ConfigEngine
+from myslice.settings import logger
 
 # decorator to deflect calls on this Page to its prelude
 def to_prelude (method):
@@ -106,16 +108,21 @@ class Page:
 
         # if cached, use it
         if 'metadata' in manifold and isinstance(manifold['metadata'],MetaData):
-            if debug: print "Page.get_metadata: return cached value"
+
+#         cached_metadata = SessionCache().get_metadata(self.request)
+#         if cached_metadata and isinstance(cached_metadata, MetaData):
+            logger.debug("Page.get_metadata: return cached value")
             return manifold['metadata']
+#             return cached_metadata
 
         metadata_auth = {'AuthMethod':'anonymous'}
 
-        metadata=MetaData (metadata_auth)
+        metadata = MetaData (metadata_auth)
         metadata.fetch(self.request)
         # store it for next time
         manifold['metadata']=metadata
-        if debug: print "Page.get_metadata: return new value"
+#         SessionCache().store_metadata(self.request, metadata)
+        logger.debug("Page.get_metadata: return new value")
         return metadata
             
     def expose_js_metadata (self):
index 229f196..9a65f59 100644 (file)
@@ -9,30 +9,32 @@ from django.template.loader import render_to_string
 from unfold.page import Page
 from unfold.prelude import Prelude
 
+from myslice.settings import logger
+
 #################### 
 # set DEBUG to
 # . False : silent
 # . [ 'SliceList', 'TabbedView' ] : to debug these classes
 # . True : to debug all plugin
 
-DEBUG= False
-#DEBUG= [ 'SimpleList' ]
-#DEBUG=True
+DEBUG = False
+#DEBUG = [ 'SimpleList' ]
+#DEBUG = True
 
 # decorator to deflect calls on Plugin to its Prelude through self.page.prelude
 def to_prelude (method):
     def actual (self, *args, **kwds):
         if not self.page: # jordan
             return None
-        prelude_method=Prelude.__dict__[method.__name__]
-        return prelude_method(self.page.prelude,*args, **kwds)
+        prelude_method = Prelude.__dict__[method.__name__]
+        return prelude_method(self.page.prelude, *args, **kwds)
     return actual
 
 class Plugin:
 
     # using a simple incremental scheme to generate domids for now
     # we just need this to be unique in a page
-    domid=0
+    domid = 0
 
     # when a domid is not set by the caller, we name plugins after their respective class as well, 
     # so as to limit name clashes between different views
@@ -41,7 +43,7 @@ class Plugin:
     # and maybe xxx we should just enforce that...
     def newdomid(self):
         Plugin.domid += 1
-        return "plugin-%s-%d"%(self.__class__.__name__.lower(),Plugin.domid)
+        return "plugin-{}-{}".format(self.__class__.__name__.lower(), Plugin.domid)
 
     ########## 
     # Constructor
@@ -84,31 +86,34 @@ class Plugin:
                   **settings):
         self.page = page
         # callers can provide their domid for css'ing 
-        if not domid: domid=self.newdomid()
-        self.domid=domid
+        if not domid:
+            domid=self.newdomid()
+        self.domid = domid
         # title is shown when togglable
         #if not title: title="Plugin title for %s"%domid
-        self.title=title
-        self.classname=self._py_classname()
-        self.plugin_classname=self._js_classname()
-        self.visible=visible
-        if togglable is None:           self.togglable=self.default_togglable()
-        else:                           self.togglable=togglable
-        if toggled is None:             self.toggled=self.default_toggled()
-        else:                           self.toggled=toggled
-        if outline_complete is None:    self.outline_complete=self.default_outline_complete()
-        else:                           self.outline_complete=outline_complete
-        if outline_body is None:        self.outline_body=self.default_outline_body()
-        else:                           self.outline_body=outline_body
+        self.title = title
+        self.classname = self._py_classname()
+        self.plugin_classname = self._js_classname()
+        self.visible = visible
+        if togglable is None:           self.togglable = self.default_togglable()
+        else:                           self.togglable = togglable
+        if toggled is None:             self.toggled = self.default_toggled()
+        else:                           self.toggled = toggled
+        if outline_complete is None:    self.outline_complete = self.default_outline_complete()
+        else:                           self.outline_complete = outline_complete
+        if outline_body is None:        self.outline_body = self.default_outline_body()
+        else:                           self.outline_body = outline_body
         # what comes from subclasses
         for (k,v) in settings.iteritems():
-            setattr(self,k,v)
-            if self.need_debug(): print "%s init - subclass setting %s"%(self.classname,k)
+            setattr(self, k, v)
+            if self.need_debug():
+                logger.debug("{} init - subclass setting {}".format(self.classname, k))
         # minimal debugging
         if self.need_debug():
-            print "%s init dbg .... BEG"%self.classname
-            for (k,v) in self.__dict__.items(): print "dbg %s:%s"%(k,v)
-            print "%s init dbg .... END"%self.classname
+            logger.debug("{} init dbg .... BEG".format(self.classname))
+            for (k, v) in self.__dict__.items():
+                logger.debug("dbg {}:{}".format(k, v))
+            logger.debug("{} init dbg .... END".format(self.classname))
         # do this only once the structure is fine
         if self.page: # I assume we can have a None page (Jordan)
             self.page.record_plugin(self)
@@ -132,18 +137,19 @@ class Plugin:
 
     def setting_json (self, setting):
         # TMP: js world expects plugin_uuid
-        if setting=='plugin_uuid':
-            value=self.domid
-        elif setting=='query_uuid':
-            try: value=self.query.query_uuid
-            except: return '%s:"undefined"'%setting
+        if setting == 'plugin_uuid':
+            value = self.domid
+        elif setting == 'query_uuid':
+            try: value = self.query.query_uuid
+            except: return '{}:"undefined"'.format(setting)
         else:
-            value=getattr(self,setting,None)
-            if value is None: value = "unknown-setting-%s"%setting
+            value = getattr(self,setting,None)
+            if value is None:
+                value = "unknown-setting-%s"%setting
         # first try to use to_json method (json.dumps not working on class instances)
-        try:    value_json=value.to_json()
-        except: value_json=json.dumps(value,separators=(',',':'))
-        return "%s:%s"%(setting,value_json)
+        try:    value_json = value.to_json()
+        except: value_json = json.dumps(value,separators=(',',':'))
+        return "{}:{}".format(setting, value_json)
 
     # expose in json format to js the list of fields as described in json_settings_list()
     # and add plugin_uuid: domid in the mix
@@ -151,7 +157,7 @@ class Plugin:
     def settings_json (self):
         exposed_settings=self.json_settings_list()
         if 'query' in exposed_settings:
-            print "WARNING, cannot expose 'query' directly in json_settings_list, query_uuid is enough"
+            logger.debug("WARNING, cannot expose 'query' directly in json_settings_list, query_uuid is enough")
         result = "{"
         result += ",".join([ self.setting_json(setting) for setting in self.json_settings_list() ])
         result += "}"
@@ -170,24 +176,25 @@ class Plugin:
         plugin_content = self.render_content (request)
         # shove this into plugin.html
         env = {}
-        env ['plugin_content']= plugin_content
+        env['plugin_content'] = plugin_content
         env.update(self.__dict__)
         # translate high-level 'toggled' into 4 different booleans
         self.need_toggle = False
-        if self.toggled=='persistent':
+        if self.toggled == 'persistent':
             # start with everything turned off and let the js callback do its job
-            env.update({'persistent_toggle':True,'display_hide_button':False,
-                        'display_show_button':False,'display_body':False})
-        elif self.toggled==False:
-            env.update({'persistent_toggle':False,'display_hide_button':False,
-                        'display_show_button':True,'display_body':False})
+            env.update({'persistent_toggle' : True, 'display_hide_button' : False,
+                        'display_show_button' : False, 'display_body' : False})
+        elif self.toggled == False:
+            env.update({'persistent_toggle' : False, 'display_hide_button' : False,
+                        'display_show_button' : True, 'display_body' : False})
         else:
-            env.update({'persistent_toggle':False,'display_hide_button':True,
-                        'display_show_button':False,'display_body':True})
+            env.update({'persistent_toggle' : False, 'display_hide_button' : True,
+                        'display_show_button' : False, 'display_body' : True})
         if self.need_debug(): 
-            print "rendering plugin.html with env keys %s"%env.keys()
+            logger.debug("rendering plugin.html with env keys {}".format(env.keys()))
             for (k,v) in env.items(): 
-                if "display" in k or "persistent" in k: print k,'->',v
+                if "display" in k or "persistent" in k:
+                    logger.debug("{} -> {}".format(k, v))
         result = render_to_string ('plugin.html',env)
 
         # export this only for relevant plugins
@@ -210,40 +217,38 @@ class Plugin:
         """Should return an HTML fragment"""
         template = self.template_file()
         # start with a fresh one
-        env={}
+        env = {}
         # add our own settings as defaults
         env.update(self.__dict__)
         # then the things explicitly defined in template_env()
         env.update(self.template_env(request))
         if not isinstance (env,dict):
             raise Exception, "%s.template_env returns wrong type"%self.classname
-        result=render_to_string (template, env)
+        result = render_to_string (template, env)
         if self.need_debug():
-            print "%s.render_content: BEG --------------------"%self.classname
-            print "template=%s"%template
-            print "env.keys=%s"%env.keys()
-            #print "env=%s"%env
-            #print result
-            print "%s.render_content: END --------------------"%self.classname
+            logger.debug("{}.render_content: BEG --------------------".format(self.classname))
+            logger.debug("template={}".format(template))
+            logger.debug("env.keys={}".format(env.keys()))
+            logger.debug("{}.render_content: END --------------------".format(self.classname))
         return result
 
     # or from the result of self.requirements()
     def handle_requirements (self, request):
         try:
-            d=self.requirements()
+            d = self.requirements()
             for (k,v) in d.iteritems():
                 if self.need_debug():
-                    print "%s: handling requirement %s"%(self.classname,v)
+                    logger.debug("{}: handling requirement {}".format(self.classname, v))
                 # e.g. js_files -> add_js_files
-                method_name='add_'+k
-                method=Page.__dict__[method_name]
-                method(self.page,v)
+                method_name = 'add_' + k
+                method = Page.__dict__[method_name]
+                method(self.page, v)
         except AttributeError: 
             # most likely the object does not have that method defined, which is fine
             pass
         except:
             import traceback
-            traceback.print_exc()
+            logger.log(traceback.format_exc())
             pass
 
     #################### requirements/prelude management
index 03e6def..13e1d6f 100644 (file)
@@ -2,6 +2,8 @@ from types import StringTypes, ListType
 
 from django.template.loader import render_to_string
 
+from myslice.settings import logger
+
 debug=False
 
 # the need for js_init_chunks is because we need to have the plugins initialized
@@ -53,7 +55,7 @@ class Prelude:
         result += ",".join( [ "%s->%s"%(k,len(getattr(self,k))) for k in Prelude.keys ] )
         return result
     def inspect (self,msg):
-        print self.inspect_string(msg)
+        logger.debug(self.inspect_string(msg))
 
     # first attempt was to use a simple dict like this
     #    env={}
@@ -86,8 +88,9 @@ class Prelude:
         env['all_js_chunks']= self.js_init_chunks + self.js_chunks
         env['css_chunks']=self.css_chunks
         if debug:
-            print "prelude has %d js_files, %d css files, (%d+%d) js chunks and %d css_chunks"%\
-                (len(self.js_files),len(self.css_files),len(self.js_init_chunks),len(self.js_chunks),len(self.css_chunks),)
+            logger.debug("prelude has {} js_files, {} css files, ({}+{}) js chunks and {} css_chunks"\
+                         .format (len(self.js_files), len(self.css_files),
+                                  len(self.js_init_chunks), len(self.js_chunks), len(self.css_chunks),))
         # render this with prelude.html and put the result in header_prelude
         header_prelude = render_to_string ('prelude.html',env)
         return { 'header_prelude' : header_prelude }
diff --git a/unfold/sessioncache.py b/unfold/sessioncache.py
new file mode 100644 (file)
index 0000000..7abb22b
--- /dev/null
@@ -0,0 +1,127 @@
+import uuid
+
+from manifold.util.singleton import Singleton
+
+from myslice.settings import logger
+
+# the key attached to the session object, where we store
+# the uuid attached to that session in this cache
+cache_key = 'cached_uuid'
+
+class _SessionExtension(object):
+    """
+    This object holds all the data we need to attach to a django session object
+    """
+
+    def __init__(self):
+        self.metadata = None
+        self.auth = None
+
+    def __repr__(self):
+        result = "<SessionExtension"
+        if self.metadata: result += " .metadata"
+        if self.auth:     result += " .auth"
+        result += ">"
+        return result
+
+class SessionCache(dict):
+    """
+    As of django1.7, the session object as attached to a django request
+    gets JSON-serialized instead of pickled
+    This breaks our previous or passing data from request to request across
+    a given session - in particular for metadata and auth/session keys
+    Not that the problem is more with metadata as this is a class instance
+    and JSON cannot handle that
+    So instead we decorate the session object with a UID and retrieve all the rest 
+    from the present - singleton - cache instance
+    """
+
+    __metaclass__ = Singleton
+
+    def get_auth(self, request):
+        """
+        Get the auth previously attached to the request's session, or None
+        """
+        result = self._get(request, 'auth')
+        return result
+
+    def store_auth(self, request, auth):
+        """
+        Store the auth object attached to this request's session
+        create that extension if needed
+        """
+        return self._store(request, 'auth', auth)
+
+    def get_metadata(self, request):
+        """
+        retrieve metadata attached to this request's session, or None
+        """
+        return self._get(request, 'metadata')
+
+    def store_metadata(self, request, metadata):
+        """
+        Store the metadata object attached to this request's session
+        create that extension if needed
+        """
+        return self._store(request, 'metadata', metadata)
+
+    def _get(self, request, key):
+        "internal - retrieve key - do not create anything"
+        session = request.session
+        logger.debug("sessioncache._get_{} session={}".format(key, SessionCache._debug_session(session)))
+#        self._debug(request)
+        if cache_key not in session:
+            return None
+        cached_uuid = session[cache_key]
+        if cached_uuid not in self:
+            return None
+        extension = self[cached_uuid]
+        return getattr(extension, key)
+
+    def _store(self, request, key, value):
+        "internal - set key, attach and create extension if needed"
+        session = request.session
+        if cache_key not in session:
+            session[cache_key] = uuid.uuid1().int
+        cached_uuid = session[cache_key]
+        if cached_uuid not in self:
+            self[cached_uuid] = _SessionExtension()
+        extension = self[cached_uuid]
+        setattr(extension, key, value)
+        logger.debug("sessioncache._store_{} session={}".format(key, SessionCache._debug_session(session)))
+#        self._debug(request)
+
+    def end_session(self, request):
+        """
+        Clear all data related to this request's session has we are logging out
+        This is for garbage collection
+        """
+        session = request.session
+        logger.debug("SessionCache.end_session() {}".format(self._debug_session(session)))
+        if cache_key not in session:
+            return
+        cached_uuid = session[cache_key]
+        if cached_uuid in self:
+            del self[cached_uuid]
+
+    def _debug(self, request):
+        session = request.session
+        logger.debug("SessionCache: ---------- with session {}".format(self._debug_session(session)))
+        for k,v in self.iteritems():
+            logger.debug("SessionCache {} -> {}".format(k,v))
+        if cache_key not in session:
+            return
+        cached_uuid = session[cache_key]
+        if cached_uuid not in self:
+            return
+        extension = self[cached_uuid]
+        logger.debug("SessionCache: found extension {}".format(extension))
+        logger.debug("SessionCache: ----------")
+        
+    @staticmethod
+    def _debug_session(session):
+        result = ""
+        result += "{} x {}".format(session, session.keys())
+        if cache_key in session:
+            result += " <{} = {}>".format(cache_key, session[cache_key])
+        return result
index 4ef3cd1..b8b1c91 100644 (file)
@@ -1,3 +1,5 @@
+from __future__ import print_function
+
 """
 This file demonstrates writing tests using the unittest module. These will pass
 when you run "manage.py test".
@@ -14,8 +16,8 @@ class PluginTest(TestCase):
         """
         Tests that 1 + 1 always equals 2.
         """
-        print 'test_basic is broken'
+        print('test_basic is broken')
         return True
         sl = SimpleList (visible=True)
-        print 'rendering', sl.render()
+        print('rendering', sl.render())
         self.assertEqual(1 + 1, 2)