[Kimchi-devel] [PATCH V2] [Wok] Implement Asynchronous Notifications backend

Paulo Ricardo Paz Vital pvital at linux.vnet.ibm.com
Wed Mar 30 14:14:03 UTC 2016


Few comments and questions...

On Mar 29 05:02PM, Lucio Correia wrote:
> * There is no POST method: a notification is
> added through add_notification() method.
> * Notifications are always stored in Wok object store under
> 'notification' type, even if added by a plugin.
> * Every time Wok is started, all notifications are erased,
> since this is a UI feature, intended to be showed to the
> user asynchronously, independent of which tab is opened.
> 
> Signed-off-by: Lucio Correia <luciojhc at linux.vnet.ibm.com>
> ---
>  docs/API/notifications.md        | 34 ++++++++++++++++++++++++
>  src/wok/control/notifications.py | 37 ++++++++++++++++++++++++++
>  src/wok/i18n.py                  |  3 +++
>  src/wok/model/notifications.py   | 56 ++++++++++++++++++++++++++++++++++++++++
>  src/wok/objectstore.py           | 39 ++++++++++++++++++++++++++++
>  src/wok/server.py                |  4 +++
>  6 files changed, 173 insertions(+)
>  create mode 100644 docs/API/notifications.md
>  create mode 100644 src/wok/control/notifications.py
>  create mode 100644 src/wok/model/notifications.py
> 
> Changes in V2:
>  - added timestamp
>  - code as required parameter in add_notification
>  - added DELETE api for notification
> 
> This patch depends on WokMessage V3 patch
> 
> diff --git a/docs/API/notifications.md b/docs/API/notifications.md

Why a new file here? Is it not part of the Kimchi API? 

> new file mode 100644
> index 0000000..851352f
> --- /dev/null
> +++ b/docs/API/notifications.md
> @@ -0,0 +1,34 @@
> +## REST API Specification for Notifications
> +
> +### Collection: Notifications
> +
> +**URI:** /notifications
> +
> +**Methods:**
> +
> +* **GET**: Retrieve a summarized list of current Notifications
> +
> +#### Examples
> +GET /notifications
> +[{Notification1}, {Notification2}, ...]
> +
> +### Resource: Notification
> +
> +**URI:** /notifications/*:id*
> +
> +A task represents an asynchronous operation that is being performed by the
> +server.
> +
> +**Methods:**
> +
> +* **GET**: Retrieve the full description of the Notification
> +    * code: message ID
> +    * message: message text already translated
> +
> +#### Examples
> +GET /notifications/KCHLIBVIRT0001W
> +{
> + id: "KCHLIBVIRT0001W",
> + message: "KCHLIBVIRT0001W: Lack of storage space in guest vm-1",
> + timestamp: first time notification was emitted
> +}
> diff --git a/src/wok/control/notifications.py b/src/wok/control/notifications.py
> new file mode 100644
> index 0000000..37d45f2
> --- /dev/null
> +++ b/src/wok/control/notifications.py
> @@ -0,0 +1,37 @@
> +#
> +# Project Wok
> +#
> +# Copyright IBM Corp, 2016
> +#
> +# This library is free software; you can redistribute it and/or
> +# modify it under the terms of the GNU Lesser General Public
> +# License as published by the Free Software Foundation; either
> +# version 2.1 of the License, or (at your option) any later version.
> +#
> +# This library is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +# Lesser General Public License for more details.
> +#
> +# You should have received a copy of the GNU Lesser General Public
> +# License along with this library; if not, write to the Free Software
> +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
> +
> +from wok.control.base import Collection, Resource
> +from wok.control.utils import UrlSubNode
> +
> +
> + at UrlSubNode('notifications', True)
> +class Notifications(Collection):
> +    def __init__(self, model):
> +        super(Notifications, self).__init__(model)
> +        self.resource = Notification
> +
> +
> +class Notification(Resource):
> +    def __init__(self, model, id):
> +        super(Notification, self).__init__(model, id)
> +
> +    @property
> +    def data(self):
> +        return self.info
> diff --git a/src/wok/i18n.py b/src/wok/i18n.py
> index e6087f4..5a2876f 100644
> --- a/src/wok/i18n.py
> +++ b/src/wok/i18n.py
> @@ -45,6 +45,9 @@ messages = {
>      "WOKLOG0001E": _("Invalid filter parameter. Filter parameters allowed: %(filters)s"),
>      "WOKLOG0002E": _("Creation of log file failed: %(err)s"),
> 
> +    "WOKNOT0001E": _("Unable to find notification %(id)s"),
> +    "WOKNOT0002E": _("Unable to delete notification %(id)s: %(message)s"),
> +
>      "WOKOBJST0001E": _("Unable to find %(item)s in datastore"),
> 
>      "WOKUTILS0001E": _("Unable to reach %(url)s. Make sure it is accessible and try again."),
> diff --git a/src/wok/model/notifications.py b/src/wok/model/notifications.py
> new file mode 100644
> index 0000000..77184db
> --- /dev/null
> +++ b/src/wok/model/notifications.py
> @@ -0,0 +1,56 @@
> +#
> +# Project Wok
> +#
> +# Copyright IBM Corp, 2016
> +#
> +# This library is free software; you can redistribute it and/or
> +# modify it under the terms of the GNU Lesser General Public
> +# License as published by the Free Software Foundation; either
> +# version 2.1 of the License, or (at your option) any later version.
> +#
> +# This library is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +# Lesser General Public License for more details.
> +#
> +# You should have received a copy of the GNU Lesser General Public
> +# License along with this library; if not, write to the Free Software
> +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
> +
> +from wok.exception import NotFoundError, OperationFailed
> +from wok.message import WokMessage
> +
> +
> +class NotificationsModel(object):
> +    def __init__(self, **kargs):
> +        self.objstore = kargs['objstore']
> +
> +    def get_list(self):
> +        with self.objstore as session:
> +            return session.get_list('notification')
> +
> +
> +class NotificationModel(object):
> +    def __init__(self, **kargs):
> +        self.objstore = kargs['objstore']
> +
> +    def lookup(self, id):
> +        with self.objstore as session:
> +            notification = session.get('notification', str(id))
> +
> +            # use WokMessage to translate the notification
> +            if notification:
> +                timestamp = notification['timestamp']
> +                plugin = notification.pop('_plugin_name', None)
> +                message = WokMessage(id, notification, plugin).get_text()
> +                return {"code": id, "message": message, "timestamp": timestamp}
> +
> +        raise NotFoundError("WOKNOT0001E", {'id': str(id)})
> +
> +    def delete(self, id):
> +        try:
> +            with self.objstore as session:
> +                session.delete('notification', str(id))
> +        except Exception as e:
> +            raise OperationFailed("WOKNOT0002E", {'id': str(id),
> +                                                  'msg': e.msg()})
> diff --git a/src/wok/objectstore.py b/src/wok/objectstore.py
> index 59354f3..dbc3ee3 100644
> --- a/src/wok/objectstore.py
> +++ b/src/wok/objectstore.py
> @@ -23,6 +23,8 @@ import sqlite3
>  import threading
>  import traceback
> 
> +from datetime import datetime
> +
>  try:
>      from collections import OrderedDict
>  except ImportError:
> @@ -144,3 +146,40 @@ class ObjectStore(object):
>                  # exception again
>                  wok_log.error(traceback.format_exc())
>                  return False
> +
> +
> +def add_notification(code, args={}, plugin_name=None):
> +    if not code:
> +        wok_log.error("Unable to add notification: invalide code '%(code)s'" %

s/invalide/invalid

> +                      {'code': str(code)})
> +        return
> +
> +    found = True
> +    try:
> +        with ObjectStore() as session:
> +            notification = session.get('notification', code)
> +    except NotFoundError:
> +        found = False
> +
> +    try:
> +        args.update({"_plugin_name": plugin_name,
> +                     "timestamp": datetime.now().isoformat()})
> +
> +        # do not update timestamp if notification already exists
> +        if found:
> +            args["timestamp"] = notification["timestamp"]
> +
> +        with ObjectStore() as session:
> +            session.store('notification', code, args)
> +    except Exception as e:
> +        wok_log.error("Unable to store notification: %s" % e.message)
> +
> +
> +def clean_notifications():
> +    try:
> +        with ObjectStore() as session:
> +            notifications = session.get_list('notification')
> +            for item in notifications:
> +                session.delete('notification', item)
> +    except Exception as e:
> +        wok_log.error("Unable to clean notifications: %s" % e.message)
> diff --git a/src/wok/server.py b/src/wok/server.py
> index 902d4bf..a329ed4 100644
> --- a/src/wok/server.py
> +++ b/src/wok/server.py
> @@ -33,6 +33,7 @@ from wok.config import config as configParser
>  from wok.config import paths, PluginConfig, WokConfig
>  from wok.control import sub_nodes
>  from wok.model import model
> +from wok.objectstore import clean_notifications
>  from wok.proxy import start_proxy, terminate_proxy
>  from wok.reqlogger import RequestLogger
>  from wok.root import WokRoot
> @@ -106,6 +107,9 @@ class Server(object):
>          if dev_env:
>              cherrypy.log.screen = True
> 
> +        # clean object store notifications
> +        clean_notifications()
> +
>          # close standard file handlers because we are going to use a
>          # watchedfiled handler, otherwise we will have two file handlers
>          # pointing to the same file, duplicating log enries
> -- 
> 1.9.1
> 
> _______________________________________________
> Kimchi-devel mailing list
> Kimchi-devel at ovirt.org
> http://lists.ovirt.org/mailman/listinfo/kimchi-devel
> 

-- 
Paulo Ricardo Paz Vital
IBM Linux Technology Center
http://www.ibm.com




More information about the Kimchi-devel mailing list