@@ -27,6 +27,8 @@ class FirewallDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]):
2727 POLICY_ACCEPT = 0
2828 POLICY_DROP = 1
2929
30+ ALL_NODES = "all"
31+
3032 _notification_callback = QtCore .pyqtSignal (str , ui_pb2 .NotificationReply )
3133
3234 def __init__ (self , parent = None , appicon = None , node = None ):
@@ -64,6 +66,7 @@ def __init__(self, parent=None, appicon=None, node=None):
6466 self .cmdAllowINService .clicked .connect (self ._cb_allow_in_service_clicked )
6567 self .comboInput .currentIndexChanged .connect (lambda : self ._cb_combo_policy_changed (self .COMBO_IN ))
6668 self .comboProfile .currentIndexChanged .connect (self ._cb_combo_profile_changed )
69+ self .comboNodes .currentIndexChanged .connect (self ._cb_combo_nodes_changed )
6770 self .sliderFwEnable .valueChanged .connect (self ._cb_enable_fw_changed )
6871 self .cmdClose .clicked .connect (self ._cb_close_clicked )
6972 self .cmdHelp .clicked .connect (
@@ -103,7 +106,16 @@ def _cb_notification_callback(self, addr, reply):
103106
104107 @QtCore .pyqtSlot (int )
105108 def _cb_nodes_updated (self , total ):
106- self ._check_fw_status ()
109+ if self ._nodes .count () <= 1 :
110+ self .load_fw_policies ()
111+
112+ def _cb_combo_nodes_changed (self , idx ):
113+ nIdx = self .comboNodes .currentIndex ()
114+ addr = self .comboNodes .itemData (nIdx )
115+ if nIdx >= 1 :
116+ self .block_combo_signals ()
117+ self .load_node_fw_policy (addr )
118+ self .block_combo_signals (False )
107119
108120 def _cb_combo_profile_changed (self , idx ):
109121 combo_profile = self ._fw_profiles [idx ]
@@ -184,14 +196,13 @@ def _cb_enable_fw_changed(self, enable):
184196 self .sliderFwEnable .setValue (False )
185197 self .sliderFwEnable .blockSignals (False )
186198 return
187- self .enable_fw (enable )
199+ nIdx = self .comboNodes .currentIndex ()
200+ addr = self .comboNodes .itemData (nIdx )
201+ self .enable_fw (addr , enable )
188202
189203 def _cb_close_clicked (self ):
190204 self ._close ()
191205
192- def _load_nodes (self ):
193- self ._nodes = self ._nodes .get ()
194-
195206 def _close (self ):
196207 self .hide ()
197208
@@ -202,63 +213,69 @@ def _change_fw_backend(self, addr, node_cfg):
202213 def showEvent (self , event ):
203214 super (FirewallDialog , self ).showEvent (event )
204215 self ._reset_fields ()
205- self ._check_fw_status ()
216+ self ._load_nodes ()
217+ self .load_fw_policies ()
206218 self ._fw_profiles = FwProfiles .Profiles .load_predefined_profiles ()
207219 self .comboProfile .blockSignals (True )
208220 for pr in self ._fw_profiles :
209221 self .comboProfile .addItem ([pr [k ] for k in pr ][0 ]['Name' ])
210222 self .comboProfile .blockSignals (False )
211223
224+ def _load_nodes (self ):
225+ self .comboNodes .blockSignals (True )
226+ self .comboNodes .clear ()
227+ node_list = self ._nodes .get ()
228+
229+ self .comboNodes .addItem (QC .translate ("firewall" , "All" ), self .ALL_NODES )
230+ for node in node_list :
231+ hostname = self ._nodes .get_node_hostname (node )
232+ self .comboNodes .addItem (hostname + " - " + node , node )
233+
234+ show_nodes = len (node_list ) > 1
235+ if show_nodes is False :
236+ self .comboNodes .setCurrentIndex (1 )
237+ self .comboNodes .setVisible (show_nodes )
238+
239+ self .comboNodes .blockSignals (False )
240+
212241 def send_notification (self , node_addr , fw_config ):
213242 self ._set_status_message (QC .translate ("firewall" , "Applying changes..." ))
214- nid , notif = self ._nodes .reload_fw (node_addr , fw_config , self ._notification_callback )
215- self ._notifications_sent [nid ] = {'addr' : node_addr , 'notif' : notif }
216243
217- def _check_fw_status (self ):
244+ nIdx = self .comboNodes .currentIndex ()
245+ addr = self .comboNodes .itemData (nIdx )
246+ if addr == self .ALL_NODES and self ._nodes .count () > 1 :
247+ for addr in self ._nodes .get ():
248+ nid , notif = self ._nodes .reload_fw (addr , fw_config , self ._notification_callback )
249+ self ._notifications_sent [nid ] = {'addr' : addr , 'notif' : notif }
250+
251+ return
252+
253+ nid , notif = self ._nodes .reload_fw (addr , fw_config , self ._notification_callback )
254+ self ._notifications_sent [nid ] = {'addr' : addr , 'notif' : notif }
255+
256+ def load_fw_policies (self , node_addr = None ):
218257 self .lblFwStatus .setText ("" )
219258 self .sliderFwEnable .blockSignals (True )
220- self .comboInput .blockSignals (True )
221- self .comboOutput .blockSignals (True )
222- self .comboProfile .blockSignals (True )
259+ self .block_combo_signals ()
223260
224261 self ._disable_widgets ()
225262
263+ enableFw = False
226264 try :
227- enableFw = False
228265 enableFwBtn = (self ._nodes .count () > 0 )
229266 self .sliderFwEnable .setEnabled (enableFwBtn )
230267 if not enableFwBtn :
231268 return
232269
233- # TODO: handle nodes' firewall properly
234- for addr in self ._nodes .get ():
235- node = self ._nodes .get_node (addr )
236- self ._fwConfig = node ['firewall' ]
237- enableFw |= self ._fwConfig .Enabled
270+ enableFw = self ._nodes .count () > 1
271+ if node_addr is None :
238272
239- if self .fw_is_incompatible (addr , node ):
240- enableFw = False
273+ if self ._nodes .count () == 1 :
274+ nIdx = self .comboNodes .currentIndex ()
275+ node_addr = self .comboNodes .itemData (nIdx )
276+ enableFw = self .load_node_fw_policy (node_addr )
241277 return
242278
243- # XXX: Here we loop twice over the chains. We could have 1 loop.
244- pol_in = self ._fw .chains .get_policy (addr , Fw .Hooks .INPUT .value )
245- pol_out = self ._fw .chains .get_policy (addr , Fw .Hooks .OUTPUT .value , Fw .ChainType .MANGLE .value )
246-
247- if pol_in != None :
248- self .comboInput .setCurrentIndex (
249- Fw .Policy .values ().index (pol_in )
250- )
251- else :
252- self ._set_status_error (QC .translate ("firewall" , "Error getting INPUT chain policy" ))
253- self ._disable_widgets ()
254- if pol_out != None :
255- self .comboOutput .setCurrentIndex (
256- Fw .Policy .values ().index (pol_out )
257- )
258- else :
259- self ._set_status_error (QC .translate ("firewall" , "Error getting OUTPUT chain policy" ))
260- self ._disable_widgets ()
261-
262279 except Exception as e :
263280 self ._set_status_error ("Firewall status error (report on github please): {0}" .format (e ))
264281
@@ -272,9 +289,44 @@ def _check_fw_status(self):
272289 self .sliderFwEnable .setValue (enableFw )
273290
274291 self .sliderFwEnable .blockSignals (False )
275- self .comboInput .blockSignals (False )
276- self .comboOutput .blockSignals (False )
277- self .comboProfile .blockSignals (False )
292+ self .block_combo_signals (False )
293+
294+ def load_node_fw_policy (self , addr ):
295+ enableFw = False
296+ try :
297+ node = self ._nodes .get_node (addr )
298+ self ._fwConfig = node ['firewall' ]
299+ enableFw |= self ._fwConfig .Enabled
300+
301+ if self .fw_is_incompatible (addr , node ):
302+ enableFw = False
303+ return
304+
305+ # XXX: Here we loop twice over the chains. We could have 1 loop.
306+ pol_in = self ._fw .chains .get_policy (addr , Fw .Hooks .INPUT .value )
307+ pol_out = self ._fw .chains .get_policy (addr , Fw .Hooks .OUTPUT .value , Fw .ChainType .MANGLE .value )
308+
309+ if pol_in != None :
310+ self .comboInput .setCurrentIndex (
311+ Fw .Policy .values ().index (pol_in )
312+ )
313+ else :
314+ self ._set_status_error (QC .translate ("firewall" , "Error getting INPUT chain policy" ))
315+ self ._disable_widgets ()
316+ if pol_out != None :
317+ self .comboOutput .setCurrentIndex (
318+ Fw .Policy .values ().index (pol_out )
319+ )
320+ else :
321+ self ._set_status_error (QC .translate ("firewall" , "Error getting OUTPUT chain policy" ))
322+ self ._disable_widgets ()
323+
324+ except Exception as e :
325+ self ._set_status_error ("Firewall status error (report on github please): {0}" .format (e ))
326+ enableFw = False
327+
328+ return enableFw
329+
278330
279331 def fw_is_incompatible (self , addr , node ):
280332 """Check if the fw is compatible with this GUI.
@@ -290,7 +342,7 @@ def fw_is_incompatible(self, addr, node):
290342 if self .isHidden () == False and self .change_fw (addr , node_cfg ):
291343 node_cfg ['Firewall' ] = "nftables"
292344 self .sliderFwEnable .setEnabled (True )
293- self .enable_fw (True )
345+ self .enable_fw (addr , True )
294346 self ._change_fw_backend (addr , node_cfg )
295347 return False
296348 incompatible = True
@@ -321,7 +373,7 @@ def change_fw(self, addr, node_cfg):
321373
322374 return False
323375
324- def enable_fw (self , enable ):
376+ def enable_fw (self , addr , enable ):
325377 try :
326378 self ._disable_widgets (not enable )
327379 if enable :
@@ -357,30 +409,31 @@ def enable_fw(self, enable):
357409 )
358410 return
359411
360- for addr in self ._nodes .get ():
361- # FIXME:
362- # Due to how the daemon reacts to events when the fw configuration
363- # is modified, changing the policy + disabling the fw doesn't work
364- # as expected.
365- # The daemon detects that the fw is disabled, and it never changes
366- # the policy.
367- # As a workaround to this problem, we send 2 fw changes:
368- # - one for changing the policy
369- # - another one for disabling the fw
412+ # FIXME:
413+ # Due to how the daemon reacts to events when the fw configuration
414+ # is modified, changing the policy + disabling the fw doesn't work
415+ # as expected.
416+ # The daemon detects that the fw is disabled, and it never changes
417+ # the policy.
418+ # As a workaround to this problem, we send 2 fw changes:
419+ # - one for changing the policy
420+ # - another one for disabling the fw
370421
371- fwcfg = self ._nodes .get_node (addr )['firewall' ]
372- self .send_notification (addr , fwcfg )
373- time .sleep (0.5 )
374- fwcfg .Enabled = True if enable else False
375- self .send_notification (addr , fwcfg )
422+ fwcfg = self ._nodes .get_node (addr )['firewall' ]
423+ self .send_notification (addr , fwcfg )
424+ time .sleep (0.5 )
425+ fwcfg .Enabled = True if enable else False
426+ self .send_notification (addr , fwcfg )
376427
377428 self .lblStatusIcon .setEnabled (enable )
378429 self .policiesBox .setEnabled (enable )
379430
380431 time .sleep (0.5 )
381432
382433 except Exception as e :
383- QC .translate ("firewall" , "Error: {0}" .format (e ))
434+ self ._set_status_error (
435+ QC .translate ("firewall" , "Error: {0}" .format (e ))
436+ )
384437
385438 def load_rule (self , addr , uuid ):
386439 self ._fwrule_dialog .load (addr , uuid )
@@ -416,9 +469,16 @@ def _reset_status_message(self):
416469 def _reset_fields (self ):
417470 self ._reset_status_message ()
418471
472+ def block_combo_signals (self , state = True ):
473+ self .comboInput .blockSignals (state )
474+ self .comboOutput .blockSignals (state )
475+ self .comboNodes .blockSignals (state )
476+ self .comboProfile .blockSignals (state )
477+
419478 def _disable_widgets (self , disable = True ):
420479 self .comboInput .setEnabled (not disable )
421480 self .comboOutput .setEnabled (not disable )
422481 self .cmdNewRule .setEnabled (not disable )
423482 self .cmdAllowOUTService .setEnabled (not disable )
424483 self .cmdAllowINService .setEnabled (not disable )
484+ self .comboNodes .setEnabled (not disable )
0 commit comments