@@ -245,8 +245,9 @@ def clean_devices(self):
245
245
class DhcpLocalProcess (DhcpBase , metaclass = abc .ABCMeta ):
246
246
PORTS = []
247
247
248
- # Track running interfaces.
249
- _interfaces = set ()
248
+ # Track running interfaces, indexed by network ID, for example,
249
+ # {net-id-1: set(intf_1, intf_2), net-id-2: set(intf_3, intf_4), ...}
250
+ _interfaces = collections .defaultdict (set )
250
251
251
252
def __init__ (self , conf , network , process_monitor , version = None ,
252
253
plugin = None , segment = None ):
@@ -267,20 +268,24 @@ def __init__(self, conf, network, process_monitor, version=None,
267
268
fileutils .ensure_tree (self .network_conf_dir , mode = 0o755 )
268
269
269
270
@classmethod
270
- def _add_running_interface (cls , interface ):
271
- """Safe method that add running interface"""
272
- cls ._interfaces .add (interface )
271
+ def _add_running_interface (cls , interface , network_id ):
272
+ """Safe method that adds a given interface"""
273
+ cls ._interfaces [ network_id ] .add (interface )
273
274
274
275
@classmethod
275
- def _del_running_interface (cls , interface ):
276
- """Safe method that remove given interface"""
277
- if interface in cls ._interfaces :
278
- cls ._interfaces .remove (interface )
276
+ def _del_running_interface (cls , interface , network_id ):
277
+ """Safe method that removes a given interface"""
278
+ if cls ._interfaces .get (network_id ):
279
+ if interface in cls ._interfaces [network_id ]:
280
+ cls ._interfaces [network_id ].remove (interface )
281
+ # no entries, cleanup
282
+ if not cls ._interfaces [network_id ]:
283
+ del cls ._interfaces [network_id ]
279
284
280
285
@classmethod
281
- def _has_running_interfaces (cls ):
282
- """Safe method that remove given interface """
283
- return bool (cls ._interfaces )
286
+ def _has_running_interfaces (cls , network_id ):
287
+ """Safe method that checks for interfaces """
288
+ bool (cls ._interfaces . get ( network_id ) )
284
289
285
290
@staticmethod
286
291
def get_confs_dir (conf ):
@@ -332,7 +337,8 @@ def _enable(self):
332
337
self .network , self .segment )
333
338
self .interface_name = interface_name
334
339
self .spawn_process ()
335
- self ._add_running_interface (self .interface_name )
340
+ self ._add_running_interface (self .interface_name ,
341
+ self .network .id )
336
342
return True
337
343
except exceptions .ProcessExecutionError as error :
338
344
LOG .debug ("Spawning DHCP process for network %s failed; "
@@ -364,7 +370,7 @@ def disable(self, retain_port=False, block=False, **kwargs):
364
370
pm .pid , SIGTERM_TIMEOUT )
365
371
pm .disable (sig = str (int (signal .SIGKILL )))
366
372
common_utils .wait_until_true (lambda : not self .active )
367
- self ._del_running_interface (self .interface_name )
373
+ self ._del_running_interface (self .interface_name , self . network . id )
368
374
if not retain_port :
369
375
self ._destroy_namespace_and_port ()
370
376
self ._remove_config_files ()
@@ -376,8 +382,9 @@ def _destroy_namespace_and_port(self):
376
382
except RuntimeError :
377
383
LOG .warning ('Failed trying to delete interface: %s' ,
378
384
self .interface_name )
379
- if not self ._has_running_interfaces ():
380
- # Delete nm only if we don't serve different segmentation id.
385
+ # Delete namespace only if there are no running interfaces in it,
386
+ # which covers the case where a network has multiple segmentation ids.
387
+ if not self ._has_running_interfaces (self .network .id ):
381
388
try :
382
389
ip_lib .delete_network_namespace (self .network .namespace )
383
390
except RuntimeError :
0 commit comments