Add Info providers Admin pages
authorSimo Sorce <simo@redhat.com>
Tue, 2 Sep 2014 21:41:07 +0000 (17:41 -0400)
committerPatrick Uiterwijk <puiterwijk@redhat.com>
Wed, 24 Sep 2014 18:29:49 +0000 (20:29 +0200)
Signed-off-by: Simo Sorce <simo@redhat.com>
Reviewed-by: Patrick Uiterwijk <puiterwijk@redhat.com>
ipsilon/admin/common.py
ipsilon/admin/info.py [new file with mode: 0755]
ipsilon/info/common.py
ipsilon/login/common.py
ipsilon/root.py
templates/admin/info.html [new file with mode: 0644]
templates/admin/info_order.html [new file with mode: 0644]
templates/admin/plugin_config.html

index d2ef3cf..2c8ff89 100755 (executable)
@@ -32,6 +32,7 @@ class AdminPluginPage(Page):
         self.url = '%s/%s' % (parent.url, obj.name)
         self.facility = parent.facility
         self.menu = [parent]
         self.url = '%s/%s' % (parent.url, obj.name)
         self.facility = parent.facility
         self.menu = [parent]
+        self.back = parent.url
 
         # Get the defaults
         self.plugin_config = obj.get_config_desc()
 
         # Get the defaults
         self.plugin_config = obj.get_config_desc()
@@ -61,7 +62,7 @@ class AdminPluginPage(Page):
         return self._template('admin/plugin_config.html', title=self.title,
                               name='admin_%s_%s_form' % (self.facility,
                                                          self._obj.name),
         return self._template('admin/plugin_config.html', title=self.title,
                               name='admin_%s_%s_form' % (self.facility,
                                                          self._obj.name),
-                              menu=self.menu, action=self.url,
+                              menu=self.menu, action=self.url, back=self.back,
                               options_order=self.options_order,
                               options=self.plugin_config)
 
                               options_order=self.options_order,
                               options=self.plugin_config)
 
diff --git a/ipsilon/admin/info.py b/ipsilon/admin/info.py
new file mode 100755 (executable)
index 0000000..4154339
--- /dev/null
@@ -0,0 +1,142 @@
+#!/usr/bin/python
+#
+# Copyright (C) 2014  Ipsilon Contributors see COPYING for license
+
+import cherrypy
+from ipsilon.util.page import Page
+from ipsilon.util.page import admin_protect
+from ipsilon.util.plugin import PluginObject
+from ipsilon.admin.common import AdminPluginPage
+from ipsilon.info.common import FACILITY
+
+
+class InfoPluginsOrder(Page):
+
+    def __init__(self, site, parent):
+        super(InfoPluginsOrder, self).__init__(site, form=True)
+        self.url = '%s/order' % parent.url
+        self.menu = [parent]
+
+    @admin_protect
+    def GET(self, *args, **kwargs):
+        opts = [p.name for p in self._site[FACILITY]['enabled']]
+        return self._template('admin/info_order.html',
+                              title='info plugins order',
+                              name='admin_info_order_form',
+                              menu=self.menu, action=self.url,
+                              options=opts)
+
+    @admin_protect
+    def POST(self, *args, **kwargs):
+        message = "Nothing was modified."
+        message_type = "info"
+        plugins_by_name = {p.name: p for p in self._site[FACILITY]['enabled']}
+
+        if 'order' in kwargs:
+            order = kwargs['order'].split(',')
+            if len(order) != 0:
+                new_names = []
+                new_plugins = []
+                try:
+                    for v in order:
+                        val = v.strip()
+                        if val not in plugins_by_name:
+                            error = "Invalid plugin name: %s" % val
+                            raise ValueError(error)
+                        new_names.append(val)
+                        new_plugins.append(plugins_by_name[val])
+                    if len(new_names) < len(plugins_by_name):
+                        for val in plugins_by_name:
+                            if val not in new_names:
+                                new_names.append(val)
+                                new_plugins.append(plugins_by_name[val])
+
+                    po = PluginObject()
+                    po.name = "global"
+                    globalconf = dict()
+                    globalconf['order'] = ','.join(new_names)
+                    po.set_config(globalconf)
+                    po.save_plugin_config(FACILITY)
+
+                    # When all is saved update also live config. The
+                    # live config is a list of the actual plugin
+                    # objects.
+                    self._site[FACILITY]['enabled'] = new_plugins
+
+                    message = "New configuration saved."
+                    message_type = "success"
+
+                except ValueError, e:
+                    message = str(e)
+                    message_type = "error"
+
+                except Exception, e:  # pylint: disable=broad-except
+                    message = "Failed to save data!"
+                    message_type = "error"
+
+        opts = [p.name for p in self._site[FACILITY]['enabled']]
+        return self._template('admin/info_order.html',
+                              message=message,
+                              message_type=message_type,
+                              title='info plugins order',
+                              name='admin_info_order_form',
+                              menu=self.menu, action=self.url,
+                              options=opts)
+
+
+class InfoPlugins(Page):
+    def __init__(self, site, parent):
+        super(InfoPlugins, self).__init__(site)
+        self._master = parent
+        self.title = 'Info Plugins'
+        self.url = '%s/info' % parent.url
+        self.facility = FACILITY
+        parent.add_subtree('info', self)
+
+        for plugin in self._site[FACILITY]['available']:
+            cherrypy.log.error('Admin info plugin: %s' % plugin)
+            obj = self._site[FACILITY]['available'][plugin]
+            self.__dict__[plugin] = AdminPluginPage(obj, self._site, self)
+
+        self.order = InfoPluginsOrder(self._site, self)
+
+    def root_with_msg(self, message=None, message_type=None):
+        info_plugins = self._site[FACILITY]
+        ordered = []
+        for p in info_plugins['enabled']:
+            ordered.append(p.name)
+        return self._template('admin/info.html', title=self.title,
+                              message=message,
+                              message_type=message_type,
+                              available=info_plugins['available'],
+                              enabled=ordered,
+                              menu=self._master.menu)
+
+    def root(self, *args, **kwargs):
+        return self.root_with_msg()
+
+    def enable(self, plugin):
+        msg = None
+        plugins = self._site[FACILITY]
+        if plugin not in plugins['available']:
+            msg = "Unknown plugin %s" % plugin
+            return self.root_with_msg(msg, "error")
+        obj = plugins['available'][plugin]
+        if obj not in plugins['enabled']:
+            obj.enable(self._site)
+            msg = "Plugin %s enabled" % obj.name
+        return self.root_with_msg(msg, "success")
+    enable.exposed = True
+
+    def disable(self, plugin):
+        msg = None
+        plugins = self._site[FACILITY]
+        if plugin not in plugins['available']:
+            msg = "Unknown plugin %s" % plugin
+            return self.root_with_msg(msg, "error")
+        obj = plugins['available'][plugin]
+        if obj in plugins['enabled']:
+            obj.disable(self._site)
+            msg = "Plugin %s disabled" % obj.name
+        return self.root_with_msg(msg, "success")
+    disable.exposed = True
index 6dbaf93..4fbb7ef 100755 (executable)
@@ -9,7 +9,7 @@ from ipsilon.util.plugin import PluginLoader, PluginObject
 from ipsilon.util.plugin import PluginInstaller
 
 
 from ipsilon.util.plugin import PluginInstaller
 
 
-class InfoProviderBase(PluginObject):
+class InfoProviderBase(PluginObject, Log):
 
     def __init__(self):
         super(InfoProviderBase, self).__init__()
 
     def __init__(self):
         super(InfoProviderBase, self).__init__()
@@ -17,17 +17,39 @@ class InfoProviderBase(PluginObject):
     def get_user_attrs(self, user):
         raise NotImplementedError
 
     def get_user_attrs(self, user):
         raise NotImplementedError
 
+    def enable(self, site):
+        plugins = site[FACILITY]
+        if self in plugins['enabled']:
+            return
+
+        # configure self
+        if self.name in plugins['config']:
+            self.set_config(plugins['config'][self.name])
+
+        plugins['enabled'].append(self)
+        self.debug('Info plugin enabled: %s' % self.name)
+
+    def disable(self, site):
+        plugins = site[FACILITY]
+        if self not in plugins['enabled']:
+            return
+
+        plugins['enabled'].remove(self)
+        self.debug('Info plugin disabled: %s' % self.name)
+
 
 FACILITY = 'info_config'
 
 
 class Info(Log):
 
 
 FACILITY = 'info_config'
 
 
 class Info(Log):
 
-    def __init__(self, *args, **kwargs):
+    def __init__(self, site):
+        self._site = site
         self.providers = []
 
         loader = PluginLoader(Info, FACILITY, 'InfoProvider')
         self.providers = []
 
         loader = PluginLoader(Info, FACILITY, 'InfoProvider')
-        plugins = loader.get_plugin_data()
+        self._site[FACILITY] = loader.get_plugin_data()
+        plugins = self._site[FACILITY]
 
         available = plugins['available'].keys()
         self.debug('Available info providers: %s' % str(available))
 
         available = plugins['available'].keys()
         self.debug('Available info providers: %s' % str(available))
index 7fb1342..e59085f 100755 (executable)
@@ -206,7 +206,7 @@ class Login(Page):
     def __init__(self, *args, **kwargs):
         super(Login, self).__init__(*args, **kwargs)
         self.first_login = None
     def __init__(self, *args, **kwargs):
         super(Login, self).__init__(*args, **kwargs)
         self.first_login = None
-        self.info = Info()
+        self.info = Info(self._site)
 
         loader = PluginLoader(Login, FACILITY, 'LoginManager')
         self._site[FACILITY] = loader.get_plugin_data()
 
         loader = PluginLoader(Login, FACILITY, 'LoginManager')
         self._site[FACILITY] = loader.get_plugin_data()
index c5fc5ae..0046ddf 100755 (executable)
@@ -23,6 +23,7 @@ from ipsilon.login.common import Login
 from ipsilon.login.common import Logout
 from ipsilon.admin.common import Admin
 from ipsilon.providers.common import LoadProviders
 from ipsilon.login.common import Logout
 from ipsilon.admin.common import Admin
 from ipsilon.providers.common import LoadProviders
+from ipsilon.admin.info import InfoPlugins
 from ipsilon.admin.login import LoginPlugins
 from ipsilon.admin.providers import ProviderPlugins
 import cherrypy
 from ipsilon.admin.login import LoginPlugins
 from ipsilon.admin.providers import ProviderPlugins
 import cherrypy
@@ -53,6 +54,7 @@ class Root(Page):
 
         # after all plugins are setup we can instantiate the admin pages
         self.admin = Admin(self._site, 'admin')
 
         # after all plugins are setup we can instantiate the admin pages
         self.admin = Admin(self._site, 'admin')
+        InfoPlugins(self._site, self.admin)
         LoginPlugins(self._site, self.admin)
         ProviderPlugins(self._site, self.admin)
 
         LoginPlugins(self._site, self.admin)
         ProviderPlugins(self._site, self.admin)
 
diff --git a/templates/admin/info.html b/templates/admin/info.html
new file mode 100644 (file)
index 0000000..d51231f
--- /dev/null
@@ -0,0 +1,31 @@
+{% extends "master-admin.html" %}
+{% block main %}
+{% if user.is_admin %}
+    <h2>Info plugins</h2>
+    {% if message %}
+    <div class="alert alert-{{message_type}}">
+        <p>{{ message }}</p>
+    </div>
+    {% endif %}
+
+    {% for p in available %}
+        <div class="row">
+        <div class="col-md-3 col-sm-3 col-xs-6">{{ p }}</div>
+        <div class="col-md-3 col-sm-3 col-xs-6">
+        {% if p in enabled %}
+            <a class="btn btn-default" href="{{ basepath }}/admin/info/disable/{{ p }}">Disable</a>
+            <a class="btn btn-default" href="{{ basepath }}/admin/info/{{ p }}">Configure</a>
+        {% else %}
+            <a class="btn btn-default" href="{{ basepath }}/admin/info/enable/{{ p }}">Enable</a>
+        {% endif %}
+        </div>
+        </div>
+    {% endfor %}
+
+    <h3>Plugins order</h3>
+    <div class="col-md-3 col-sm-3 col-xs-6">{{ ', '.join(enabled) }}</div>
+    <div class="col-md-3 col-sm-3 col-xs-6">
+        <a class="btn btn-default" href="{{ basepath }}/admin/info/order">configure</a>
+    </div>
+{% endif %}
+{% endblock %}
diff --git a/templates/admin/info_order.html b/templates/admin/info_order.html
new file mode 100644 (file)
index 0000000..5d929be
--- /dev/null
@@ -0,0 +1,25 @@
+{% extends "master-admin.html" %}
+{% block main %}
+    <h2>{{ title }}</h2>
+    {% if message %}
+    <div class="alert alert-{{message_type}}">
+        <p>{{ message }}</p>
+    </div>
+    {% endif %}
+    <div id="options">
+        <form role="form" id="{{ name }}" action="{{ action }}" method="post" enctype="application/x-www-form-urlencoded">
+
+        <div class="form-group">
+        <label for="order">Info plugins order:</label>
+            <input type="text" class="form-control" name="order" value="{{ ', '.join(options) }}" />
+        </div>
+        <span class="help-block">Plugins order</span>
+
+        <button id="submit" class="btn btn-primary" name="submit" type="submit" value="Submit">
+            Save
+        </button>
+        <a href="{{ basepath }}/admin/info" class="btn btn-default" title="Back">Back</a>
+        </form>
+    </div>
+{% endblock %}
+
index 1f75182..d95bf75 100644 (file)
@@ -20,7 +20,7 @@
         <button id="submit" class="btn btn-primary" name="submit" type="submit" value="Submit">
             Save
         </button>
         <button id="submit" class="btn btn-primary" name="submit" type="submit" value="Submit">
             Save
         </button>
-        <a href="{{ basepath }}/admin/login" class="btn btn-default" title="Back">Back</a>
+        <a href="{{ back }}" class="btn btn-default" title="Back">Back</a>
         </form>
     </div>
 {% endblock %}
         </form>
     </div>
 {% endblock %}