Repository: rucio/rucio

Issue:
WebUI page to list Liftetime Model exceptions
Motivation
----------
WebUI page to list Liftetime Model exceptions



Discussion:

Resolving patch:
diff --git a/lib/rucio/core/lifetime_exception.py b/lib/rucio/core/lifetime_exception.py
--- a/lib/rucio/core/lifetime_exception.py
+++ b/lib/rucio/core/lifetime_exception.py
@@ -1,14 +1,12 @@
-'''
-  Copyright European Organization for Nuclear Research (CERN)
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  You may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-  http://www.apache.org/licenses/LICENSE-2.0
-
-  Authors:
-  - Cedric Serfon, <cedric.serfon@cern.ch>, 2016-2017
-'''
+#  Copyright European Organization for Nuclear Research (CERN)
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  You may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Authors:
+#  - Cedric Serfon, <cedric.serfon@cern.ch>, 2016-2018
 
 from re import match
 from datetime import datetime, timedelta
@@ -50,7 +48,8 @@ def list_exceptions(exception_id, states, session=None):
                           models.LifetimeExceptions.pattern,
                           models.LifetimeExceptions.comments,
                           models.LifetimeExceptions.state,
-                          models.LifetimeExceptions.expires_at)
+                          models.LifetimeExceptions.expires_at,
+                          models.LifetimeExceptions.created_at)
     if state_clause != []:
         query = query.filter(or_(*state_clause))
     if exception_id:
@@ -60,7 +59,8 @@ def list_exceptions(exception_id, states, session=None):
         yield {'id': exception.id, 'scope': exception.scope, 'name': exception.name,
                'did_type': exception.did_type, 'account': exception.account,
                'pattern': exception.pattern, 'comments': exception.comments,
-               'state': exception.state, 'expires_at': exception.expires_at}
+               'state': exception.state, 'created_at': exception.created_at,
+               'expires_at': exception.expires_at}
 
 
 @transactional_session
diff --git a/lib/rucio/web/ui/main.py b/lib/rucio/web/ui/main.py
--- a/lib/rucio/web/ui/main.py
+++ b/lib/rucio/web/ui/main.py
@@ -19,16 +19,16 @@
 # - Mario Lassnig <mario.lassnig@cern.ch>, 2014-2018
 # - Martin Barisits <martin.barisits@cern.ch>, 2014-2015
 # - Ralph Vigne <ralph.vigne@cern.ch>, 2015
-# - Cedric Serfon <cedric.serfon@cern.ch>, 2015-2017
+# - Cedric Serfon <cedric.serfon@cern.ch>, 2015-2018
 # - Stefan Prenner <stefan.prenner@cern.ch>, 2018
 
 from io import BytesIO
 from json import dumps
 from os.path import dirname, join
+from tarfile import open, TarError
 
 from gzip import GzipFile
 from requests import get, ConnectionError
-from tarfile import open, TarError
 from web import application, header, input as param_input, seeother, template
 
 from rucio.common.config import config_get
@@ -46,6 +46,7 @@
     '/did', 'DID',
     '/heartbeats', 'Heartbeats',
     '/lifetime_exception', 'LifetimeException',
+    '/list_lifetime_exceptions', 'ListLifetimeExceptions',
     '/list_accounts', 'ListAccounts',
     '/list_rules', 'ListRulesRedirect',
     '/r2d2/approve', 'ApproveRules',
@@ -228,6 +229,14 @@ def GET(self):  # pylint:disable=no-self-use,invalid-name
         return check_token(render.lifetime_exception())
 
 
+class ListLifetimeExceptions():
+    """ List lifetime exceptions requests """
+    def GET(self):  # pylint:disable=no-self-use,invalid-name
+        """ GET """
+        render = template.render(join(dirname(__file__), 'templates/'))
+        return check_token(render.list_lifetime_exceptions())
+
+
 class ListAccounts(object):
     """ Account list """
     def GET(self):  # pylint:disable=no-self-use,invalid-name


Test patch: