[PATCH v3] [WoK 0/5] 'reload' API implementation

From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> v3: - 'add_notification' is now being called before the reload command v2: - changed API name to 'reload' - added test_api tests This patch set implements a new WOK API called 'reload' under /config/reload. To test it: $ curl -k -u danielhb -H "Content-Type: application/json" -H "Accept: application/json" -X POST 'https://localhost:8001/config/reload' -d'{}' Enter host password for user 'danielhb': { "proxy_port":"8001", "websockets_port":"64667", "version":"2.3.0-55.git5c9127b", "auth":"pam", "server_root":"" } This will reload WoK and all its plug-ins. Daniel Henrique Barboza (5): reload API: doc changes reload API: control and model changes reload API: new file tests/test_config_model.py reload API: added rest API tests reload API: adding notification before reloading operation docs/API/config.md | 2 +- src/wok/control/config.py | 4 +++- src/wok/i18n.py | 2 ++ src/wok/model/config.py | 22 +++++++++++++++++++++- tests/test_api.py | 9 ++++++++- tests/test_config_model.py | 41 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 tests/test_config_model.py -- 2.7.4

From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> This patch adds the documentation of the new 'reload' API in docs/API/config.md. Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> --- docs/API/config.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/API/config.md b/docs/API/config.md index 0c273e2..4ba455e 100644 --- a/docs/API/config.md +++ b/docs/API/config.md @@ -17,7 +17,7 @@ Contains information about the application environment and configuration. **Actions (POST):** -*No actions defined* +* reload: reloads WoK configuration. This process will drop all existing WoK connections, reloading WoK and all its enabled plug-ins. #### Examples GET /config -- 2.7.4

From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> - added a new action handler called 'reload' in control/config.py - added a method 'reload' in model/config.py that calls 'cherrypy.engine.restart()'. Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> --- src/wok/control/config.py | 4 +++- src/wok/model/config.py | 7 ++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/wok/control/config.py b/src/wok/control/config.py index 338306c..62218f9 100644 --- a/src/wok/control/config.py +++ b/src/wok/control/config.py @@ -1,7 +1,7 @@ # # Project Wok # -# Copyright IBM Corp, 2016 +# Copyright IBM Corp, 2016-2017 # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -25,6 +25,8 @@ from wok.control.utils import UrlSubNode class Config(Resource): def __init__(self, model, id=None): super(Config, self).__init__(model, id) + self.uri_fmt = '/config/%s' + self.reload = self.generate_action_handler('reload') @property def data(self): diff --git a/src/wok/model/config.py b/src/wok/model/config.py index 7e8ae4f..57c5ad8 100644 --- a/src/wok/model/config.py +++ b/src/wok/model/config.py @@ -1,7 +1,7 @@ # # Project Wok # -# Copyright IBM Corp, 2016 +# Copyright IBM Corp, 2016-2017 # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -17,6 +17,8 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +import cherrypy + from wok.config import config, get_version @@ -30,3 +32,6 @@ class ConfigModel(object): 'auth': config.get('authentication', 'method'), 'server_root': config.get('server', 'server_root'), 'version': get_version()} + + def reload(self, name): + cherrypy.engine.restart() -- 2.7.4

From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> Created a new unit test file for model/config.py since the existing test_config.py is testing WokConfig. Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> --- tests/test_config_model.py | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 tests/test_config_model.py diff --git a/tests/test_config_model.py b/tests/test_config_model.py new file mode 100644 index 0000000..f8b0848 --- /dev/null +++ b/tests/test_config_model.py @@ -0,0 +1,41 @@ +# +# Project Wok +# +# Copyright IBM Corp, 2017 +# +# 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 + +import mock +import unittest + +from wok.model import model + + +class ConfigModelTests(unittest.TestCase): + + def test_config_lookup(self): + inst = model.Model() + config = inst.config_lookup('') + self.assertItemsEqual( + ['proxy_port', 'websockets_port', 'auth', + 'server_root', 'version'], + config.keys() + ) + + @mock.patch('cherrypy.engine.restart') + def test_config_reload(self, mock_restart): + inst = model.Model() + inst.config_reload('') + mock_restart.assert_called_once_with() -- 2.7.4

From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> This patch adds a new test in test_api to assert the function of the 'reload' API. Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> --- tests/test_api.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/test_api.py b/tests/test_api.py index 23c263d..7ed8144 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -1,7 +1,7 @@ # # Project Wok # -# Copyright IBM Corp, 2016 +# Copyright IBM Corp, 2016-2017 # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -18,6 +18,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import json +import mock import time import unittest import utils @@ -102,3 +103,9 @@ class APITests(unittest.TestCase): self.assertEquals(204, resp.status) task = json.loads(self.request('/tasks/%s' % taskid).read()) self.assertEquals('killed', task['status']) + + @mock.patch('cherrypy.engine.restart') + def test_config_reload(self, mock_restart): + resp = self.request('/config/reload', '{}', 'POST') + self.assertEquals(200, resp.status) + mock_restart.assert_called_once_with -- 2.7.4

On 18/01/2017 14:24, dhbarboza82@gmail.com wrote:
From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com>
This patch adds a new test in test_api to assert the function of the 'reload' API.
Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> --- tests/test_api.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/tests/test_api.py b/tests/test_api.py index 23c263d..7ed8144 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -1,7 +1,7 @@ # # Project Wok # -# Copyright IBM Corp, 2016 +# Copyright IBM Corp, 2016-2017 # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -18,6 +18,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
import json +import mock import time import unittest import utils @@ -102,3 +103,9 @@ class APITests(unittest.TestCase): self.assertEquals(204, resp.status) task = json.loads(self.request('/tasks/%s' % taskid).read()) self.assertEquals('killed', task['status']) + + @mock.patch('cherrypy.engine.restart') + def test_config_reload(self, mock_restart): + resp = self.request('/config/reload', '{}', 'POST') + self.assertEquals(200, resp.status) + mock_restart.assert_called_once_with
Missing ()
-- Lucio Correia

On 01/18/2017 04:03 PM, Lucio Correia wrote:
On 18/01/2017 14:24, dhbarboza82@gmail.com wrote:
From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com>
This patch adds a new test in test_api to assert the function of the 'reload' API.
Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> --- tests/test_api.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/tests/test_api.py b/tests/test_api.py index 23c263d..7ed8144 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -1,7 +1,7 @@ # # Project Wok # -# Copyright IBM Corp, 2016 +# Copyright IBM Corp, 2016-2017 # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -18,6 +18,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
import json +import mock import time import unittest import utils @@ -102,3 +103,9 @@ class APITests(unittest.TestCase): self.assertEquals(204, resp.status) task = json.loads(self.request('/tasks/%s' % taskid).read()) self.assertEquals('killed', task['status']) + + @mock.patch('cherrypy.engine.restart') + def test_config_reload(self, mock_restart): + resp = self.request('/config/reload', '{}', 'POST') + self.assertEquals(200, resp.status) + mock_restart.assert_called_once_with
Missing ()
Good catch. How the frak did the test passed? I'll fix in and send a new version. Thanks!

From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> This patch adds an add_notification call to warn the UI about the pending reload process. To allow the UI to actually see the notification before WoK restarts, a 2 seconds wait (value defined by the wok.NOTIFICATION_INTERVAL var in wok.main.js) is given before sending the cherrypy.engine.restart call. Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> --- src/wok/i18n.py | 2 ++ src/wok/model/config.py | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/wok/i18n.py b/src/wok/i18n.py index e454e31..02adcdd 100644 --- a/src/wok/i18n.py +++ b/src/wok/i18n.py @@ -62,4 +62,6 @@ messages = { "WOKRES0001L": _("Request made on resource"), "WOKROOT0001L": _("User '%(username)s' login"), "WOKROOT0002L": _("User '%(username)s' logout"), + + "WOKCONFIG0001I": _("WoK is going to restart. Existing WoK connections will be closed."), } diff --git a/src/wok/model/config.py b/src/wok/model/config.py index 57c5ad8..b69f2dd 100644 --- a/src/wok/model/config.py +++ b/src/wok/model/config.py @@ -18,8 +18,11 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import cherrypy +import time from wok.config import config, get_version +from wok.model.notifications import add_notification +from wok.utils import wok_log class ConfigModel(object): @@ -34,4 +37,16 @@ class ConfigModel(object): 'version': get_version()} def reload(self, name): + add_notification('WOKCONFIG0001I', plugin_name='/') + # If we proceed with the cherrypy.engine.restart() right after + # adding the notification, the server will reboot and the + # opened UIs will most likely not see the notification at all. The + # notification interval is set in wok.main.js as: + # + # wok.NOTIFICATION_INTERVAL = 2000 + # + # Inserting a time.sleep(2) here will ensure that all opened + # UI had the chance to see the reload notification. + wok_log.info('Reloading WoK in two seconds ...') + time.sleep(2) cherrypy.engine.restart() -- 2.7.4

On 18/01/2017 14:24, dhbarboza82@gmail.com wrote:
From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com>
This patch adds an add_notification call to warn the UI about the pending reload process. To allow the UI to actually see the notification before WoK restarts, a 2 seconds wait (value defined by the wok.NOTIFICATION_INTERVAL var in wok.main.js) is given before sending the cherrypy.engine.restart call.
Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> --- src/wok/i18n.py | 2 ++ src/wok/model/config.py | 15 +++++++++++++++ 2 files changed, 17 insertions(+)
diff --git a/src/wok/i18n.py b/src/wok/i18n.py index e454e31..02adcdd 100644 --- a/src/wok/i18n.py +++ b/src/wok/i18n.py @@ -62,4 +62,6 @@ messages = { "WOKRES0001L": _("Request made on resource"), "WOKROOT0001L": _("User '%(username)s' login"), "WOKROOT0002L": _("User '%(username)s' logout"), + + "WOKCONFIG0001I": _("WoK is going to restart. Existing WoK connections will be closed."), To not mix with user log messages, include this one before the ones ending in L.
} diff --git a/src/wok/model/config.py b/src/wok/model/config.py index 57c5ad8..b69f2dd 100644 --- a/src/wok/model/config.py +++ b/src/wok/model/config.py @@ -18,8 +18,11 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
import cherrypy +import time
from wok.config import config, get_version +from wok.model.notifications import add_notification +from wok.utils import wok_log
class ConfigModel(object): @@ -34,4 +37,16 @@ class ConfigModel(object): 'version': get_version()}
def reload(self, name): + add_notification('WOKCONFIG0001I', plugin_name='/')
It may be working this way, but it should work as well with plugin_name=None. It makes more sense to be None than '/', since there is no plugin '/'. Anyway, just a suggestion.
+ # If we proceed with the cherrypy.engine.restart() right after + # adding the notification, the server will reboot and the + # opened UIs will most likely not see the notification at all. The + # notification interval is set in wok.main.js as: + # + # wok.NOTIFICATION_INTERVAL = 2000 + # + # Inserting a time.sleep(2) here will ensure that all opened + # UI had the chance to see the reload notification. + wok_log.info('Reloading WoK in two seconds ...') + time.sleep(2) cherrypy.engine.restart()
-- Lucio Correia

On 01/18/2017 04:03 PM, Lucio Correia wrote:
On 18/01/2017 14:24, dhbarboza82@gmail.com wrote:
From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com>
This patch adds an add_notification call to warn the UI about the pending reload process. To allow the UI to actually see the notification before WoK restarts, a 2 seconds wait (value defined by the wok.NOTIFICATION_INTERVAL var in wok.main.js) is given before sending the cherrypy.engine.restart call.
Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> --- src/wok/i18n.py | 2 ++ src/wok/model/config.py | 15 +++++++++++++++ 2 files changed, 17 insertions(+)
diff --git a/src/wok/i18n.py b/src/wok/i18n.py index e454e31..02adcdd 100644 --- a/src/wok/i18n.py +++ b/src/wok/i18n.py @@ -62,4 +62,6 @@ messages = { "WOKRES0001L": _("Request made on resource"), "WOKROOT0001L": _("User '%(username)s' login"), "WOKROOT0002L": _("User '%(username)s' logout"), + + "WOKCONFIG0001I": _("WoK is going to restart. Existing WoK connections will be closed."), To not mix with user log messages, include this one before the ones ending in L.
Alright!
} diff --git a/src/wok/model/config.py b/src/wok/model/config.py index 57c5ad8..b69f2dd 100644 --- a/src/wok/model/config.py +++ b/src/wok/model/config.py @@ -18,8 +18,11 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
import cherrypy +import time
from wok.config import config, get_version +from wok.model.notifications import add_notification +from wok.utils import wok_log
class ConfigModel(object): @@ -34,4 +37,16 @@ class ConfigModel(object): 'version': get_version()}
def reload(self, name): + add_notification('WOKCONFIG0001I', plugin_name='/')
It may be working this way, but it should work as well with plugin_name=None. It makes more sense to be None than '/', since there is no plugin '/'. Anyway, just a suggestion.
Yeah, it works either way. I've asked Aline her option on it (I have no favorites between plugin_name='/' and plugin_name=None and even plugin_name='wok') and she said that she prefers '/'. You can interpret it as 'this is not a plugin, this is the root URI'. But I agree that None works too.
+ # If we proceed with the cherrypy.engine.restart() right after + # adding the notification, the server will reboot and the + # opened UIs will most likely not see the notification at all. The + # notification interval is set in wok.main.js as: + # + # wok.NOTIFICATION_INTERVAL = 2000 + # + # Inserting a time.sleep(2) here will ensure that all opened + # UI had the chance to see the reload notification. + wok_log.info('Reloading WoK in two seconds ...') + time.sleep(2) cherrypy.engine.restart()

On 01/18/2017 06:47 PM, Daniel Henrique Barboza wrote:
On 01/18/2017 04:03 PM, Lucio Correia wrote:
On 18/01/2017 14:24, dhbarboza82@gmail.com wrote:
From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com>
This patch adds an add_notification call to warn the UI about the pending reload process. To allow the UI to actually see the notification before WoK restarts, a 2 seconds wait (value defined by the wok.NOTIFICATION_INTERVAL var in wok.main.js) is given before sending the cherrypy.engine.restart call.
Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> --- src/wok/i18n.py | 2 ++ src/wok/model/config.py | 15 +++++++++++++++ 2 files changed, 17 insertions(+)
diff --git a/src/wok/i18n.py b/src/wok/i18n.py index e454e31..02adcdd 100644 --- a/src/wok/i18n.py +++ b/src/wok/i18n.py @@ -62,4 +62,6 @@ messages = { "WOKRES0001L": _("Request made on resource"), "WOKROOT0001L": _("User '%(username)s' login"), "WOKROOT0002L": _("User '%(username)s' logout"), + + "WOKCONFIG0001I": _("WoK is going to restart. Existing WoK connections will be closed."), To not mix with user log messages, include this one before the ones ending in L.
Alright!
} diff --git a/src/wok/model/config.py b/src/wok/model/config.py index 57c5ad8..b69f2dd 100644 --- a/src/wok/model/config.py +++ b/src/wok/model/config.py @@ -18,8 +18,11 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
import cherrypy +import time
from wok.config import config, get_version +from wok.model.notifications import add_notification +from wok.utils import wok_log
class ConfigModel(object): @@ -34,4 +37,16 @@ class ConfigModel(object): 'version': get_version()}
def reload(self, name): + add_notification('WOKCONFIG0001I', plugin_name='/')
It may be working this way, but it should work as well with plugin_name=None. It makes more sense to be None than '/', since there is no plugin '/'. Anyway, just a suggestion.
Yeah, it works either way. I've asked Aline her option on it (I have no favorites between plugin_name='/' and plugin_name=None and even plugin_name='wok') and she said that she prefers '/'. You can interpret it as 'this is not a plugin, this is the root URI'. But I agree that None works too.
I have suggested '/' because after looking at the WokMessage class, that parameters represents the plugin URI so... But if you prefer, None I will not oppose to it =)
+ # If we proceed with the cherrypy.engine.restart() right after + # adding the notification, the server will reboot and the + # opened UIs will most likely not see the notification at all. The + # notification interval is set in wok.main.js as: + # + # wok.NOTIFICATION_INTERVAL = 2000 + # + # Inserting a time.sleep(2) here will ensure that all opened + # UI had the chance to see the reload notification. + wok_log.info('Reloading WoK in two seconds ...') + time.sleep(2) cherrypy.engine.restart()
_______________________________________________ Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel
participants (4)
-
Aline Manera
-
Daniel Henrique Barboza
-
dhbarboza82@gmail.com
-
Lucio Correia