[PATCH] [Kimchi 0/6] Make use of async websockets notification mechanism

This patch set also register for libvirt events to update the page accordindly. Aline Manera (6): Register for libvirt storage pools events to update the UI accordindly Add Storage Pools listeners to update page according to user interations Register for libvirt network events to update the UI accordindly Add Network listeners to update page according to user interations Register for libvirt domain events to update the UI accordindly Add Domain listeners to update page according to user interations model/libvirtevents.py | 53 +++++++++++++++++++++++++++++++++++++++- model/model.py | 18 +++++++++++--- ui/js/src/kimchi.guest_main.js | 18 ++------------ ui/js/src/kimchi.network.js | 11 +++++++-- ui/js/src/kimchi.storage_main.js | 1 + 5 files changed, 79 insertions(+), 22 deletions(-) -- 2.9.4

Signed-off-by: Aline Manera <aline.manera@gmail.com> --- model/libvirtevents.py | 18 +++++++++++++++++- model/model.py | 14 +++++++++++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/model/libvirtevents.py b/model/libvirtevents.py index 716420c..2401c5d 100644 --- a/model/libvirtevents.py +++ b/model/libvirtevents.py @@ -1,7 +1,7 @@ # # Project Kimchi # -# 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 @@ -117,3 +117,19 @@ class LibvirtEvents(object): except libvirt.libvirtError as e: wok_log.error("register detach event failed: %s" % e.message) + + def registerPoolEvents(self, conn, cb, arg): + """ + Register libvirt events to listen to any pool change + """ + pool_events = [libvirt.VIR_STORAGE_POOL_EVENT_DEFINED, + libvirt.VIR_STORAGE_POOL_EVENT_STARTED, + libvirt.VIR_STORAGE_POOL_EVENT_STOPPED, + libvirt.VIR_STORAGE_POOL_EVENT_UNDEFINED] + + for ev in pool_events: + try: + conn.get().storagePoolEventRegisterAny(None, ev, cb, arg) + except libvirt.libvirtError as e: + wok_log.error("Unable to register pool event handler: %s" % + e.message) diff --git a/model/model.py b/model/model.py index 719652d..97def98 100644 --- a/model/model.py +++ b/model/model.py @@ -1,7 +1,7 @@ # # Project Kimchi # -# Copyright IBM Corp, 2015-2016 +# Copyright IBM Corp, 2015-2017 # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -20,6 +20,7 @@ from wok.basemodel import BaseModel from wok.objectstore import ObjectStore from wok.plugins.kimchi import config +from wok.pushserver import send_wok_notification from wok.utils import get_all_model_instances, get_model_instances from wok.plugins.kimchi.model.libvirtconnection import LibvirtConnection @@ -32,9 +33,11 @@ class Model(BaseModel): self.objstore = ObjectStore(objstore_loc or config.get_object_store()) self.conn = LibvirtConnection(libvirt_uri) - # Register for Libvirt's host ENOSPC event and notify UI if it happens + # Register for libvirt events self.events = LibvirtEvents() self.events.handleEnospc(self.conn) + self.events.registerPoolEvents(self.conn, self._events_handler, + 'storages') kargs = {'objstore': self.objstore, 'conn': self.conn, 'eventsloop': self.events} @@ -46,4 +49,9 @@ class Model(BaseModel): for instance in instances: models.append(instance(**kargs)) - return super(Model, self).__init__(models) + super(Model, self).__init__(models) + + def _events_handler(self, conn, pool, ev, details, opaque): + # Do not use any known method (POST, PUT, DELETE) as it is used by Wok + # engine and may lead in having 2 notifications for the same action + send_wok_notification('/plugins/kimchi', opaque, 'METHOD') -- 2.9.4

It makes use of the async websockets notification mechanism provided by Wok to update the Storage tab content when a pool is added, removed or updated without the need to polling requests to server. Signed-off-by: Aline Manera <aline.manera@gmail.com> --- ui/js/src/kimchi.storage_main.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/js/src/kimchi.storage_main.js b/ui/js/src/kimchi.storage_main.js index 0429456..f58f070 100644 --- a/ui/js/src/kimchi.storage_main.js +++ b/ui/js/src/kimchi.storage_main.js @@ -753,6 +753,7 @@ kimchi.storage_main = function() { } kimchi.doListStoragePools(); kimchi.initLogicalPoolExtend(); + wok.addNotificationListener('METHOD:/kimchi/storages', kimchi.doListStoragePools); wok.topic('kimchi/storageVolumeAdded').subscribe(function() { pool = kimchi.selectedSP; -- 2.9.4

Signed-off-by: Aline Manera <aline.manera@gmail.com> --- model/libvirtevents.py | 16 ++++++++++++++++ model/model.py | 2 ++ 2 files changed, 18 insertions(+) diff --git a/model/libvirtevents.py b/model/libvirtevents.py index 2401c5d..890ae31 100644 --- a/model/libvirtevents.py +++ b/model/libvirtevents.py @@ -133,3 +133,19 @@ class LibvirtEvents(object): except libvirt.libvirtError as e: wok_log.error("Unable to register pool event handler: %s" % e.message) + + def registerNetworkEvents(self, conn, cb, arg): + """ + Register libvirt events to listen to any network change + """ + net_events = [libvirt.VIR_NETWORK_EVENT_DEFINED, + libvirt.VIR_NETWORK_EVENT_STARTED, + libvirt.VIR_NETWORK_EVENT_STOPPED, + libvirt.VIR_NETWORK_EVENT_UNDEFINED] + + for ev in net_events: + try: + conn.get().networkEventRegisterAny(None, ev, cb, arg) + except libvirt.libvirtError as e: + wok_log.error("Unable to register network event handler: %s" % + e.message) diff --git a/model/model.py b/model/model.py index 97def98..aa63519 100644 --- a/model/model.py +++ b/model/model.py @@ -38,6 +38,8 @@ class Model(BaseModel): self.events.handleEnospc(self.conn) self.events.registerPoolEvents(self.conn, self._events_handler, 'storages') + self.events.registerNetworkEvents(self.conn, self._events_handler, + 'networks') kargs = {'objstore': self.objstore, 'conn': self.conn, 'eventsloop': self.events} -- 2.9.4

It makes use of the async websockets notification mechanism provided by Wok to update the Network tab content when a network is added or removed without the need to polling requests to server. Signed-off-by: Aline Manera <aline.manera@gmail.com> --- ui/js/src/kimchi.network.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/ui/js/src/kimchi.network.js b/ui/js/src/kimchi.network.js index ea15228..430b7ae 100644 --- a/ui/js/src/kimchi.network.js +++ b/ui/js/src/kimchi.network.js @@ -1,7 +1,7 @@ /* * Project Kimchi * - * Copyright IBM Corp, 2013-2016 + * Copyright IBM Corp, 2013-2017 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,7 +21,6 @@ kimchi.NETWORK_TYPE_PASSTHROUGH = "passthrough"; kimchi.NETWORK_TYPE_BRIDGED = "bridge"; kimchi.NETWORK_TYPE_VEPA = "vepa"; - kimchi.initNetwork = function() { $('body').removeClass('wok-list wok-gallery'); @@ -36,6 +35,11 @@ kimchi.initNetwork = function() { kimchi.initNetworkListView(); }; +wok.addNotificationListener('METHOD:/kimchi/networks', function() { + $("#networkBody").empty(); + kimchi.initNetworkListView(); +}); + kimchi.initNetworkListView = function() { $('.wok-mask').removeClass('hidden'); kimchi.listNetworks(function(data) { @@ -57,6 +61,9 @@ kimchi.initNetworkListView = function() { network.persistent = data[i].persistent; kimchi.addNetworkItem(network); } + if($('#networkGrid').hasClass('wok-datagrid')) { + $('#networkGrid').dataGrid('destroy'); + } $('#networkGrid').dataGrid({enableSorting: false}); $('#networkGrid').removeClass('hidden'); $('.wok-mask').fadeOut(300, function() {}); -- 2.9.4

Signed-off-by: Aline Manera <aline.manera@gmail.com> --- model/libvirtevents.py | 19 +++++++++++++++++++ model/model.py | 2 ++ 2 files changed, 21 insertions(+) diff --git a/model/libvirtevents.py b/model/libvirtevents.py index 890ae31..35fb1d0 100644 --- a/model/libvirtevents.py +++ b/model/libvirtevents.py @@ -149,3 +149,22 @@ class LibvirtEvents(object): except libvirt.libvirtError as e: wok_log.error("Unable to register network event handler: %s" % e.message) + + def registerDomainEvents(self, conn, cb, arg): + """ + Register libvirt events to listen to any domain change + """ + net_events = [libvirt.VIR_DOMAIN_EVENT_DEFINED, + libvirt.VIR_DOMAIN_EVENT_PMSUSPENDED, + libvirt.VIR_DOMAIN_EVENT_RESUMED, + libvirt.VIR_DOMAIN_EVENT_STARTED, + libvirt.VIR_DOMAIN_EVENT_STOPPED, + libvirt.VIR_DOMAIN_EVENT_SUSPENDED, + libvirt.VIR_DOMAIN_EVENT_UNDEFINED] + + for ev in net_events: + try: + conn.get().domainEventRegisterAny(None, ev, cb, arg) + except libvirt.libvirtError as e: + wok_log.error("Unable to register domain event handler: %s" % + e.message) diff --git a/model/model.py b/model/model.py index aa63519..a72593f 100644 --- a/model/model.py +++ b/model/model.py @@ -40,6 +40,8 @@ class Model(BaseModel): 'storages') self.events.registerNetworkEvents(self.conn, self._events_handler, 'networks') + self.events.registerDomainEvents(self.conn, self._events_handler, + 'vms') kargs = {'objstore': self.objstore, 'conn': self.conn, 'eventsloop': self.events} -- 2.9.4

It makes use of the async websockets notification mechanism provided by Wok to update the Guests tab content when a guest is added or removed without the need to polling requests to server. Signed-off-by: Aline Manera <aline.manera@gmail.com> --- ui/js/src/kimchi.guest_main.js | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/ui/js/src/kimchi.guest_main.js b/ui/js/src/kimchi.guest_main.js index b08b714..8cfd229 100644 --- a/ui/js/src/kimchi.guest_main.js +++ b/ui/js/src/kimchi.guest_main.js @@ -1,7 +1,7 @@ /* * Project Kimchi * - * Copyright IBM Corp, 2013-2016 + * Copyright IBM Corp, 2013-2017 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -395,9 +395,6 @@ kimchi.guest_main = function() { } kimchi.guestTemplate = $('#guest-tmpl').html(); kimchi.guestElem = $('<div/>').html(kimchi.guestTemplate).find('li[name="guest"]'); - $('#guests-root-container').on('remove', function() { - kimchi.vmTimeout && clearTimeout(kimchi.vmTimeout); - }); $('#guest-gallery-table-button').on('click', function(event) { kimchi.toggleGuestsGallery(); @@ -406,6 +403,7 @@ kimchi.guest_main = function() { kimchi.resetGuestFilter(); kimchi.initGuestFilter(); kimchi.listVmsAuto(); + wok.addNotificationListener('METHOD:/kimchi/vms', kimchi.listVmsAuto); }; kimchi.guest_clonevm_main = function() { @@ -791,9 +789,6 @@ kimchi.listVmsAuto = function() { var $isDropdownOpened = $('[name="guest-actions"] ul.dropdown-menu').is(":visible"); var $isModalOpened = $('#migrate-guest-window').is(":visible"); if (!$isDropdownOpened && !$isModalOpened) { - if (kimchi.vmTimeout) { - clearTimeout(kimchi.vmTimeout); - } var getCreatingGuests = function() { var guests = []; kimchi.getTasksByFilter('status=running&target_uri=' + encodeURIComponent('^/plugins/kimchi/vms/[^/]+$'), function(tasks) { @@ -916,7 +911,6 @@ kimchi.listVmsAuto = function() { $('#guests-root-container > .wok-mask').fadeOut(300, function() {}); } } - kimchi.setListVMAutoTimeout(); }, function(errorResponse, textStatus, errorThrown) { if (errorResponse.responseJSON && errorResponse.responseJSON.reason) { @@ -925,11 +919,7 @@ kimchi.listVmsAuto = function() { $('#guests-root-container > .wok-mask').addClass('hidden'); }); } - kimchi.setListVMAutoTimeout(); }); - } else { - clearTimeout(kimchi.vmTimeout); - kimchi.setListVMAutoTimeout(); } }; @@ -939,7 +929,3 @@ kimchi.editTemplate = function(guestTemplate, oldPopStat) { } return guestTemplate; }; - -kimchi.setListVMAutoTimeout = function() { - kimchi.vmTimeout = window.setTimeout("kimchi.listVmsAuto();", 5000); -} -- 2.9.4
participants (2)
-
Aline Manera
-
Aline Manera