Browse Source

Merge "Pools support with Network Policies"

Zuul 2 months ago
parent
commit
5a6a396854

+ 149
- 68
kuryr_kubernetes/controller/drivers/vif_pool.py View File

@@ -167,23 +167,25 @@ class BaseVIFPool(base.VIFPoolDriver):
167 167
     def update_vif_sgs(self, pod, sgs):
168 168
         self._drv_vif.update_vif_sgs(pod, sgs)
169 169
 
170
-    def _get_pool_size(self, pool_key=None):
171
-        return len(self._available_ports_pools.get(pool_key, []))
170
+    def _get_pool_size(self, pool_key):
171
+        pool = self._available_ports_pools.get(pool_key, {})
172
+        pool_members = []
173
+        for port_list in pool.values():
174
+            pool_members.extend(port_list)
175
+        return len(pool_members)
172 176
 
173 177
     def _get_host_addr(self, pod):
174 178
         return pod['status']['hostIP']
175 179
 
176
-    def _get_pool_key(self, host, project_id, security_groups, net_id=None,
177
-                      subnets=None):
180
+    def _get_pool_key(self, host, project_id, net_id=None, subnets=None):
178 181
         if not net_id and subnets:
179 182
             net_obj = list(subnets.values())[0]
180 183
             net_id = net_obj.id
181
-        pool_key = (host, project_id, tuple(sorted(security_groups)),
182
-                    net_id)
184
+        pool_key = (host, project_id, net_id)
183 185
         return pool_key
184 186
 
185 187
     def _get_pool_key_net(self, pool_key):
186
-        return pool_key[3]
188
+        return pool_key[2]
187 189
 
188 190
     def request_vif(self, pod, project_id, subnets, security_groups):
189 191
         try:
@@ -191,33 +193,37 @@ class BaseVIFPool(base.VIFPoolDriver):
191 193
         except KeyError:
192 194
             LOG.warning("Pod has not been scheduled yet.")
193 195
             raise
194
-        pool_key = self._get_pool_key(host_addr, project_id, security_groups,
195
-                                      None, subnets)
196
+        pool_key = self._get_pool_key(host_addr, project_id, None, subnets)
196 197
 
197 198
         try:
198
-            return self._get_port_from_pool(pool_key, pod, subnets)
199
+            return self._get_port_from_pool(pool_key, pod, subnets,
200
+                                            tuple(sorted(security_groups)))
199 201
         except exceptions.ResourceNotReady:
200 202
             LOG.warning("Ports pool does not have available ports!")
201
-            eventlet.spawn(self._populate_pool, pool_key, pod, subnets)
203
+            eventlet.spawn(self._populate_pool, pool_key, pod, subnets,
204
+                           tuple(sorted(security_groups)))
202 205
             raise
203 206
 
204
-    def _get_port_from_pool(self, pool_key, pod, subnets):
207
+    def _get_port_from_pool(self, pool_key, pod, subnets, security_groups):
205 208
         raise NotImplementedError()
206 209
 
207
-    def _populate_pool(self, pool_key, pod, subnets):
210
+    def _populate_pool(self, pool_key, pod, subnets, security_groups):
208 211
         # REVISIT(ltomasbo): Drop the subnets parameter and get the information
209 212
         # from the pool_key, which will be required when multi-network is
210 213
         # supported
211 214
         now = time.time()
212
-        try:
213
-            if (now - oslo_cfg.CONF.vif_pool.ports_pool_update_frequency <
214
-                    self._last_update.get(pool_key, 0)):
215
-                LOG.info("Not enough time since the last pool update")
215
+        pool_updates = self._last_update.get(pool_key)
216
+        if pool_updates:
217
+            last_update = pool_updates.get(security_groups, 0)
218
+            try:
219
+                if (now - oslo_cfg.CONF.vif_pool.ports_pool_update_frequency <
220
+                        last_update):
221
+                    LOG.info("Not enough time since the last pool update")
222
+                    return
223
+            except AttributeError:
224
+                LOG.info("Kuryr-controller not yet ready to populate pools")
216 225
                 return
217
-        except AttributeError:
218
-            LOG.info("Kuryr-controller not yet ready to populate pools")
219
-            return
220
-        self._last_update[pool_key] = now
226
+        self._last_update[pool_key] = {security_groups: now}
221 227
 
222 228
         pool_size = self._get_pool_size(pool_key)
223 229
         if pool_size < oslo_cfg.CONF.vif_pool.ports_pool_min:
@@ -227,18 +233,19 @@ class BaseVIFPool(base.VIFPoolDriver):
227 233
                 pod=pod,
228 234
                 project_id=pool_key[1],
229 235
                 subnets=subnets,
230
-                security_groups=list(pool_key[2]),
236
+                security_groups=security_groups,
231 237
                 num_ports=num_ports)
232 238
             for vif in vifs:
233 239
                 self._existing_vifs[vif.id] = vif
234
-                self._available_ports_pools.setdefault(pool_key,
235
-                                                       []).append(vif.id)
240
+                self._available_ports_pools.setdefault(
241
+                    pool_key, {}).setdefault(
242
+                        security_groups, []).append(vif.id)
236 243
 
237 244
     def release_vif(self, pod, vif, project_id, security_groups):
238 245
         host_addr = self._get_host_addr(pod)
239 246
 
240
-        pool_key = self._get_pool_key(host_addr, project_id, security_groups,
241
-                                      vif.network.id, None)
247
+        pool_key = self._get_pool_key(host_addr, project_id, vif.network.id,
248
+                                      None)
242 249
 
243 250
         try:
244 251
             if not self._existing_vifs.get(vif.id):
@@ -300,12 +307,10 @@ class BaseVIFPool(base.VIFPoolDriver):
300 307
     @lockutils.synchronized('return_to_pool_baremetal')
301 308
     @lockutils.synchronized('return_to_pool_nested')
302 309
     def sync_pools(self):
303
-        self._available_ports_pools = collections.defaultdict(
304
-            collections.deque)
305
-        self._existing_vifs = collections.defaultdict(collections.defaultdict)
306
-        self._recyclable_ports = collections.defaultdict(
307
-            collections.defaultdict)
308
-        self._last_update = collections.defaultdict(collections.defaultdict)
310
+        self._available_ports_pools = collections.defaultdict()
311
+        self._existing_vifs = collections.defaultdict()
312
+        self._recyclable_ports = collections.defaultdict()
313
+        self._last_update = collections.defaultdict()
309 314
         # NOTE(ltomasbo): Ensure previously created ports are recovered into
310 315
         # their respective pools
311 316
         self._recover_precreated_ports()
@@ -377,11 +382,45 @@ class NeutronVIFPool(BaseVIFPool):
377 382
     def _get_host_addr(self, pod):
378 383
         return pod['spec']['nodeName']
379 384
 
380
-    def _get_port_from_pool(self, pool_key, pod, subnets):
385
+    def _get_port_from_pool(self, pool_key, pod, subnets, security_groups):
381 386
         try:
382
-            port_id = self._available_ports_pools[pool_key].pop()
383
-        except (IndexError, AttributeError):
387
+            pool_ports = self._available_ports_pools[pool_key]
388
+        except (KeyError, AttributeError):
384 389
             raise exceptions.ResourceNotReady(pod)
390
+        try:
391
+            port_id = pool_ports[security_groups].pop()
392
+        except (KeyError, IndexError):
393
+            # Get another port from the pool and update the SG to the
394
+            # appropriate one. It uses a port from the group that was updated
395
+            # longer ago
396
+            pool_updates = self._last_update.get(pool_key, {})
397
+            if not pool_updates:
398
+                # No pools update info. Selecting a random one
399
+                for sg_group, ports in pool_ports.items():
400
+                    if len(ports) > 0:
401
+                        port_id = pool_ports[sg_group].pop()
402
+                        break
403
+                else:
404
+                    raise exceptions.ResourceNotReady(pod)
405
+            else:
406
+                min_date = -1
407
+                for sg_group, date in pool_updates.items():
408
+                    if pool_ports.get(sg_group):
409
+                        if min_date == -1 or date < min_date:
410
+                            min_date = date
411
+                            min_sg_group = sg_group
412
+                if min_date == -1:
413
+                    # pool is empty, no port to reuse
414
+                    raise exceptions.ResourceNotReady(pod)
415
+                port_id = pool_ports[min_sg_group].pop()
416
+            neutron = clients.get_neutron_client()
417
+            neutron.update_port(
418
+                port_id,
419
+                {
420
+                    "port": {
421
+                        'security_groups': list(security_groups)
422
+                    }
423
+                })
385 424
         if config.CONF.kubernetes.port_debug:
386 425
             neutron = clients.get_neutron_client()
387 426
             neutron.update_port(
@@ -395,7 +434,8 @@ class NeutronVIFPool(BaseVIFPool):
395 434
         # check if the pool needs to be populated
396 435
         if (self._get_pool_size(pool_key) <
397 436
                 oslo_cfg.CONF.vif_pool.ports_pool_min):
398
-            eventlet.spawn(self._populate_pool, pool_key, pod, subnets)
437
+            eventlet.spawn(self._populate_pool, pool_key, pod, subnets,
438
+                           security_groups)
399 439
         return self._existing_vifs[port_id]
400 440
 
401 441
     def _return_ports_to_pool(self):
@@ -426,7 +466,8 @@ class NeutronVIFPool(BaseVIFPool):
426 466
                 device_owner=kl_const.DEVICE_OWNER)
427 467
             for port in kuryr_ports:
428 468
                 if port['id'] in self._recyclable_ports:
429
-                    sg_current[port['id']] = port['security_groups']
469
+                    sg_current[port['id']] = tuple(sorted(
470
+                        port['security_groups']))
430 471
 
431 472
         for port_id, pool_key in self._recyclable_ports.copy().items():
432 473
             if (not oslo_cfg.CONF.vif_pool.ports_pool_max or
@@ -435,25 +476,24 @@ class NeutronVIFPool(BaseVIFPool):
435 476
                 port_name = (constants.KURYR_PORT_NAME
436 477
                              if config.CONF.kubernetes.port_debug
437 478
                              else '')
438
-                if (config.CONF.kubernetes.port_debug or
439
-                        list(pool_key[2]) != sg_current.get(port_id)):
479
+                if config.CONF.kubernetes.port_debug:
440 480
                     try:
441 481
                         neutron.update_port(
442 482
                             port_id,
443 483
                             {
444 484
                                 "port": {
445 485
                                     'name': port_name,
446
-                                    'device_id': '',
447
-                                    'security_groups': list(pool_key[2])
486
+                                    'device_id': ''
448 487
                                 }
449 488
                             })
450 489
                     except n_exc.NeutronClientException:
451
-                        LOG.warning("Error preparing port %s to be "
490
+                        LOG.warning("Error changing name for port %s to be "
452 491
                                     "reused, put back on the cleanable "
453 492
                                     "pool.", port_id)
454 493
                         continue
455 494
                 self._available_ports_pools.setdefault(
456
-                    pool_key, []).append(port_id)
495
+                    pool_key, {}).setdefault(
496
+                        sg_current.get(port_id), []).append(port_id)
457 497
             else:
458 498
                 try:
459 499
                     del self._existing_vifs[port_id]
@@ -502,12 +542,13 @@ class NeutronVIFPool(BaseVIFPool):
502 542
             net_obj = subnet[subnet_id]
503 543
             pool_key = self._get_pool_key(port_host,
504 544
                                           port['project_id'],
505
-                                          port['security_groups'],
506 545
                                           net_obj.id, None)
507 546
 
508 547
             self._existing_vifs[port['id']] = vif
509 548
             self._available_ports_pools.setdefault(
510
-                pool_key, []).append(port['id'])
549
+                pool_key, {}).setdefault(
550
+                    tuple(sorted(port['security_groups'])), []).append(
551
+                        port['id'])
511 552
 
512 553
         LOG.info("PORTS POOL: pools updated with pre-created ports")
513 554
         self._create_healthcheck_file()
@@ -524,10 +565,13 @@ class NeutronVIFPool(BaseVIFPool):
524 565
         # on the available_ports_pools dict. The next call forces it to be on
525 566
         # that dict before cleaning it up
526 567
         self._trigger_return_to_pool()
527
-        for pool_key, ports_id in self._available_ports_pools.items():
568
+        for pool_key, ports in self._available_ports_pools.items():
528 569
             if self._get_pool_key_net(pool_key) != net_id:
529 570
                 continue
530 571
             self._available_ports_pools[pool_key] = []
572
+            ports_id = []
573
+            for sg_ports in ports.values():
574
+                ports_id.extend(sg_ports)
531 575
             for port_id in ports_id:
532 576
                 try:
533 577
                     del self._existing_vifs[port_id]
@@ -560,11 +604,45 @@ class NestedVIFPool(BaseVIFPool):
560 604
     def set_vif_driver(self, driver):
561 605
         self._drv_vif = driver
562 606
 
563
-    def _get_port_from_pool(self, pool_key, pod, subnets):
607
+    def _get_port_from_pool(self, pool_key, pod, subnets, security_groups):
564 608
         try:
565
-            port_id = self._available_ports_pools[pool_key].pop()
566
-        except (IndexError, AttributeError):
609
+            pool_ports = self._available_ports_pools[pool_key]
610
+        except (KeyError, AttributeError):
567 611
             raise exceptions.ResourceNotReady(pod)
612
+        try:
613
+            port_id = pool_ports[security_groups].pop()
614
+        except (KeyError, IndexError):
615
+            # Get another port from the pool and update the SG to the
616
+            # appropriate one. It uses a port from the group that was updated
617
+            # longer ago
618
+            pool_updates = self._last_update.get(pool_key, {})
619
+            if not pool_updates:
620
+                # No pools update info. Selecting a random one
621
+                for sg_group, ports in pool_ports.items():
622
+                    if len(ports) > 0:
623
+                        port_id = pool_ports[sg_group].pop()
624
+                        break
625
+                else:
626
+                    raise exceptions.ResourceNotReady(pod)
627
+            else:
628
+                min_date = -1
629
+                for sg_group, date in pool_updates.items():
630
+                    if pool_ports.get(sg_group):
631
+                        if min_date == -1 or date < min_date:
632
+                            min_date = date
633
+                            min_sg_group = sg_group
634
+                if min_date == -1:
635
+                    # pool is empty, no port to reuse
636
+                    raise exceptions.ResourceNotReady(pod)
637
+                port_id = pool_ports[min_sg_group].pop()
638
+            neutron = clients.get_neutron_client()
639
+            neutron.update_port(
640
+                port_id,
641
+                {
642
+                    "port": {
643
+                        'security_groups': list(security_groups)
644
+                    }
645
+                })
568 646
         if config.CONF.kubernetes.port_debug:
569 647
             neutron = clients.get_neutron_client()
570 648
             neutron.update_port(
@@ -577,7 +655,8 @@ class NestedVIFPool(BaseVIFPool):
577 655
         # check if the pool needs to be populated
578 656
         if (self._get_pool_size(pool_key) <
579 657
                 oslo_cfg.CONF.vif_pool.ports_pool_min):
580
-            eventlet.spawn(self._populate_pool, pool_key, pod, subnets)
658
+            eventlet.spawn(self._populate_pool, pool_key, pod, subnets,
659
+                           security_groups)
581 660
         return self._existing_vifs[port_id]
582 661
 
583 662
     def _return_ports_to_pool(self):
@@ -608,7 +687,8 @@ class NestedVIFPool(BaseVIFPool):
608 687
                 device_owner=['trunk:subport', kl_const.DEVICE_OWNER])
609 688
             for subport in kuryr_subports:
610 689
                 if subport['id'] in self._recyclable_ports:
611
-                    sg_current[subport['id']] = subport['security_groups']
690
+                    sg_current[subport['id']] = tuple(sorted(
691
+                        subport['security_groups']))
612 692
 
613 693
         for port_id, pool_key in self._recyclable_ports.copy().items():
614 694
             if (not oslo_cfg.CONF.vif_pool.ports_pool_max or
@@ -617,24 +697,23 @@ class NestedVIFPool(BaseVIFPool):
617 697
                 port_name = (constants.KURYR_PORT_NAME
618 698
                              if config.CONF.kubernetes.port_debug
619 699
                              else '')
620
-                if (config.CONF.kubernetes.port_debug or
621
-                        list(pool_key[2]) != sg_current.get(port_id)):
700
+                if config.CONF.kubernetes.port_debug:
622 701
                     try:
623 702
                         neutron.update_port(
624 703
                             port_id,
625 704
                             {
626 705
                                 "port": {
627 706
                                     'name': port_name,
628
-                                    'security_groups': list(pool_key[2])
629 707
                                 }
630 708
                             })
631 709
                     except n_exc.NeutronClientException:
632
-                        LOG.warning("Error preparing port %s to be "
710
+                        LOG.warning("Error changing name for port %s to be "
633 711
                                     "reused, put back on the cleanable "
634 712
                                     "pool.", port_id)
635 713
                         continue
636 714
                 self._available_ports_pools.setdefault(
637
-                    pool_key, []).append(port_id)
715
+                    pool_key, {}).setdefault(
716
+                        sg_current.get(port_id), []).append(port_id)
638 717
             else:
639 718
                 trunk_id = self._get_trunk_id(neutron, pool_key)
640 719
                 try:
@@ -713,8 +792,6 @@ class NestedVIFPool(BaseVIFPool):
713 792
                     net_obj = subnet[subnet_id]
714 793
                     pool_key = self._get_pool_key(host_addr,
715 794
                                                   kuryr_subport['project_id'],
716
-                                                  kuryr_subport[
717
-                                                      'security_groups'],
718 795
                                                   net_obj.id, None)
719 796
 
720 797
                     if action == 'recover':
@@ -723,7 +800,9 @@ class NestedVIFPool(BaseVIFPool):
723 800
 
724 801
                         self._existing_vifs[kuryr_subport['id']] = vif
725 802
                         self._available_ports_pools.setdefault(
726
-                            pool_key, []).append(kuryr_subport['id'])
803
+                            pool_key, {}).setdefault(tuple(sorted(
804
+                                kuryr_subport['security_groups'])),
805
+                                []).append(kuryr_subport['id'])
727 806
 
728 807
                     elif action == 'free':
729 808
                         try:
@@ -733,8 +812,9 @@ class NestedVIFPool(BaseVIFPool):
733 812
                             self._drv_vif._release_vlan_id(
734 813
                                 subport['segmentation_id'])
735 814
                             del self._existing_vifs[kuryr_subport['id']]
736
-                            self._available_ports_pools[pool_key].remove(
737
-                                kuryr_subport['id'])
815
+                            self._available_ports_pools[pool_key][
816
+                                tuple(sorted(kuryr_subport['security_groups']
817
+                                             ))].remove(kuryr_subport['id'])
738 818
                         except n_exc.PortNotFoundClient:
739 819
                             LOG.debug('Unable to release port %s as it no '
740 820
                                       'longer exists.', kuryr_subport['id'])
@@ -764,12 +844,11 @@ class NestedVIFPool(BaseVIFPool):
764 844
             num_ports=num_ports,
765 845
             trunk_ip=trunk_ip)
766 846
 
767
-        pool_key = self._get_pool_key(trunk_ip, project_id, security_groups,
768
-                                      None, subnets)
847
+        pool_key = self._get_pool_key(trunk_ip, project_id, None, subnets)
769 848
         for vif in vifs:
770 849
             self._existing_vifs[vif.id] = vif
771
-            self._available_ports_pools.setdefault(pool_key,
772
-                                                   []).append(vif.id)
850
+            self._available_ports_pools.setdefault(pool_key, {}).setdefault(
851
+                tuple(sorted(security_groups)), []).append(vif.id)
773 852
 
774 853
     def free_pool(self, trunk_ips=None):
775 854
         """Removes subports from the pool and deletes neutron port resource.
@@ -791,19 +870,21 @@ class NestedVIFPool(BaseVIFPool):
791 870
         # on the available_ports_pools dict. The next call forces it to be on
792 871
         # that dict before cleaning it up
793 872
         self._trigger_return_to_pool()
794
-        for pool_key, ports_ids in self._available_ports_pools.items():
873
+        for pool_key, ports in self._available_ports_pools.items():
795 874
             if self._get_pool_key_net(pool_key) != net_id:
796 875
                 continue
797 876
             self._available_ports_pools[pool_key] = []
798 877
             trunk_id = self._get_trunk_id(neutron, pool_key)
878
+            ports_id = [p_id for sg_ports in ports.values()
879
+                        for p_id in sg_ports]
799 880
             try:
800
-                self._drv_vif._remove_subports(neutron, trunk_id, ports_ids)
881
+                self._drv_vif._remove_subports(neutron, trunk_id, ports_id)
801 882
             except n_exc.NeutronClientException:
802 883
                 LOG.exception('Error removing subports from trunk: %s',
803 884
                               trunk_id)
804 885
                 continue
805 886
 
806
-            for port_id in ports_ids:
887
+            for port_id in ports_id:
807 888
                 try:
808 889
                     self._drv_vif._release_vlan_id(
809 890
                         self._existing_vifs[port_id].vlan_id)

+ 298
- 66
kuryr_kubernetes/tests/unit/controller/drivers/test_vif_pool.py View File

@@ -187,15 +187,14 @@ class BaseVIFPool(test_base.TestCase):
187 187
         pod = mock.sentinel.pod
188 188
         project_id = str(uuid.uuid4())
189 189
         subnets = mock.sentinel.subnets
190
-        security_groups = [mock.sentinel.security_groups]
191
-        pool_key = (mock.sentinel.host_addr, project_id,
192
-                    tuple(security_groups))
190
+        security_groups = 'test-sg'
191
+        pool_key = (mock.sentinel.host_addr, project_id)
193 192
         vif = osv_vif.VIFOpenVSwitch(id='0fa0e837-d34e-4580-a6c4-04f5f607d93e')
194 193
         vifs = [vif]
195 194
 
196 195
         m_driver._existing_vifs = {}
197 196
         m_driver._available_ports_pools = {}
198
-        m_driver._last_update = {pool_key: 1}
197
+        m_driver._last_update = {pool_key: {tuple(security_groups): 1}}
199 198
 
200 199
         oslo_cfg.CONF.set_override('ports_pool_min',
201 200
                                    5,
@@ -206,7 +205,8 @@ class BaseVIFPool(test_base.TestCase):
206 205
         m_driver._get_pool_size.return_value = 2
207 206
         vif_driver.request_vifs.return_value = vifs
208 207
 
209
-        cls._populate_pool(m_driver, pool_key, pod, subnets)
208
+        cls._populate_pool(m_driver, pool_key, pod, subnets,
209
+                           tuple(security_groups))
210 210
         m_driver._get_pool_size.assert_called_once()
211 211
         m_driver._drv_vif.request_vifs.assert_called_once()
212 212
 
@@ -218,16 +218,16 @@ class BaseVIFPool(test_base.TestCase):
218 218
         pod = mock.sentinel.pod
219 219
         project_id = str(uuid.uuid4())
220 220
         subnets = mock.sentinel.subnets
221
-        security_groups = [mock.sentinel.security_groups]
222
-        pool_key = (mock.sentinel.host_addr, project_id,
223
-                    tuple(security_groups))
221
+        security_groups = 'test-sg'
222
+        pool_key = (mock.sentinel.host_addr, project_id)
224 223
 
225 224
         oslo_cfg.CONF.set_override('ports_pool_update_frequency',
226 225
                                    15,
227 226
                                    group='vif_pool')
228
-        m_driver._last_update = {pool_key: 1}
227
+        m_driver._last_update = {pool_key: {tuple(security_groups): 1}}
229 228
 
230
-        cls._populate_pool(m_driver, pool_key, pod, subnets)
229
+        cls._populate_pool(m_driver, pool_key, pod, subnets,
230
+                           tuple(security_groups))
231 231
         m_driver._get_pool_size.assert_not_called()
232 232
 
233 233
     @mock.patch('time.time', return_value=50)
@@ -244,9 +244,8 @@ class BaseVIFPool(test_base.TestCase):
244 244
         pod = mock.sentinel.pod
245 245
         project_id = str(uuid.uuid4())
246 246
         subnets = mock.sentinel.subnets
247
-        security_groups = [mock.sentinel.security_groups]
248
-        pool_key = (mock.sentinel.host_addr, project_id,
249
-                    tuple(security_groups))
247
+        security_groups = 'test-sg'
248
+        pool_key = (mock.sentinel.host_addr, project_id)
250 249
 
251 250
         oslo_cfg.CONF.set_override('ports_pool_update_frequency',
252 251
                                    15,
@@ -254,10 +253,11 @@ class BaseVIFPool(test_base.TestCase):
254 253
         oslo_cfg.CONF.set_override('ports_pool_min',
255 254
                                    5,
256 255
                                    group='vif_pool')
257
-        m_driver._last_update = {pool_key: 1}
256
+        m_driver._last_update = {pool_key: {tuple(security_groups): 1}}
258 257
         m_driver._get_pool_size.return_value = 10
259 258
 
260
-        cls._populate_pool(m_driver, pool_key, pod, subnets)
259
+        cls._populate_pool(m_driver, pool_key, pod, subnets,
260
+                           tuple(security_groups))
261 261
         m_driver._get_pool_size.assert_called_once()
262 262
         m_driver._drv_vif.request_vifs.assert_not_called()
263 263
 
@@ -341,11 +341,12 @@ class NeutronVIFPool(test_base.TestCase):
341 341
         port_id = str(uuid.uuid4())
342 342
         port = mock.sentinel.port
343 343
         subnets = mock.sentinel.subnets
344
+        security_groups = 'test-sg'
344 345
 
345 346
         pod = get_pod_obj()
346 347
 
347 348
         m_driver._available_ports_pools = {
348
-            pool_key: collections.deque([port_id])}
349
+            pool_key: {tuple(security_groups): collections.deque([port_id])}}
349 350
         m_driver._existing_vifs = {port_id: port}
350 351
         m_get_port_name.return_value = get_pod_name(pod)
351 352
 
@@ -362,7 +363,7 @@ class NeutronVIFPool(test_base.TestCase):
362 363
         m_driver._get_pool_size.return_value = pool_length
363 364
 
364 365
         self.assertEqual(port, cls._get_port_from_pool(
365
-            m_driver, pool_key, pod, subnets))
366
+            m_driver, pool_key, pod, subnets, tuple(security_groups)))
366 367
 
367 368
         neutron.update_port.assert_called_once_with(
368 369
             port_id,
@@ -386,11 +387,12 @@ class NeutronVIFPool(test_base.TestCase):
386 387
         port_id = str(uuid.uuid4())
387 388
         port = mock.sentinel.port
388 389
         subnets = mock.sentinel.subnets
390
+        security_groups = 'test-sg'
389 391
 
390 392
         pod = get_pod_obj()
391 393
 
392 394
         m_driver._available_ports_pools = {
393
-            pool_key: collections.deque([port_id])}
395
+            pool_key: {tuple(security_groups): collections.deque([port_id])}}
394 396
         m_driver._existing_vifs = {port_id: port}
395 397
         m_get_port_name.return_value = get_pod_name(pod)
396 398
 
@@ -404,7 +406,7 @@ class NeutronVIFPool(test_base.TestCase):
404 406
         m_driver._get_pool_size.return_value = pool_length
405 407
 
406 408
         self.assertEqual(port, cls._get_port_from_pool(
407
-            m_driver, pool_key, pod, subnets))
409
+            m_driver, pool_key, pod, subnets, tuple(security_groups)))
408 410
 
409 411
         neutron.update_port.assert_called_once_with(
410 412
             port_id,
@@ -424,11 +426,124 @@ class NeutronVIFPool(test_base.TestCase):
424 426
         pod = get_pod_obj()
425 427
         pool_key = mock.sentinel.pool_key
426 428
         subnets = mock.sentinel.subnets
429
+        security_groups = 'test-sg'
430
+
431
+        m_driver._available_ports_pools = {
432
+            pool_key: {tuple(security_groups): collections.deque([])}}
433
+        m_driver._last_update = {pool_key: {tuple(security_groups): 1}}
434
+
435
+        self.assertRaises(exceptions.ResourceNotReady, cls._get_port_from_pool,
436
+                          m_driver, pool_key, pod, subnets,
437
+                          tuple(security_groups))
438
+
439
+        neutron.update_port.assert_not_called()
440
+
441
+    @mock.patch('eventlet.spawn')
442
+    def test__get_port_from_pool_empty_pool_reuse(self, m_eventlet):
443
+        cls = vif_pool.NeutronVIFPool
444
+        m_driver = mock.MagicMock(spec=cls)
445
+        neutron = self.useFixture(k_fix.MockNeutronClient()).client
446
+
447
+        pod = get_pod_obj()
448
+        port_id = str(uuid.uuid4())
449
+        port = mock.sentinel.port
450
+        pool_key = mock.sentinel.pool_key
451
+        subnets = mock.sentinel.subnets
452
+        security_groups = 'test-sg'
453
+        security_groups_2 = 'test-sg2'
454
+
455
+        oslo_cfg.CONF.set_override('port_debug',
456
+                                   False,
457
+                                   group='kubernetes')
458
+        pool_length = 5
459
+        m_driver._get_pool_size.return_value = pool_length
460
+
461
+        m_driver._available_ports_pools = {
462
+            pool_key: {tuple(security_groups): collections.deque([]),
463
+                       tuple(security_groups_2): collections.deque([port_id])}}
464
+        m_driver._last_update = {pool_key: {tuple(security_groups): 1,
465
+                                            tuple(security_groups_2): 0}}
466
+        m_driver._existing_vifs = {port_id: port}
467
+
468
+        self.assertEqual(port, cls._get_port_from_pool(
469
+            m_driver, pool_key, pod, subnets, tuple(security_groups)))
470
+
471
+        neutron.update_port.assert_called_once_with(
472
+            port_id,
473
+            {
474
+                "port": {
475
+                    'security_groups': list(security_groups),
476
+                }
477
+            })
478
+        m_eventlet.assert_not_called()
479
+
480
+    @mock.patch('eventlet.spawn')
481
+    def test__get_port_from_pool_empty_pool_reuse_no_update_info(self,
482
+                                                                 m_eventlet):
483
+        cls = vif_pool.NeutronVIFPool
484
+        m_driver = mock.MagicMock(spec=cls)
485
+        neutron = self.useFixture(k_fix.MockNeutronClient()).client
427 486
 
428
-        m_driver._available_ports_pools = {pool_key: collections.deque([])}
487
+        pod = get_pod_obj()
488
+        port_id = str(uuid.uuid4())
489
+        port = mock.sentinel.port
490
+        pool_key = mock.sentinel.pool_key
491
+        subnets = mock.sentinel.subnets
492
+        security_groups = 'test-sg'
493
+        security_groups_2 = 'test-sg2'
494
+
495
+        oslo_cfg.CONF.set_override('port_debug',
496
+                                   False,
497
+                                   group='kubernetes')
498
+        pool_length = 5
499
+        m_driver._get_pool_size.return_value = pool_length
500
+
501
+        m_driver._available_ports_pools = {
502
+            pool_key: {tuple(security_groups): collections.deque([]),
503
+                       tuple(security_groups_2): collections.deque([port_id])}}
504
+        m_driver._last_update = {}
505
+        m_driver._existing_vifs = {port_id: port}
506
+
507
+        self.assertEqual(port, cls._get_port_from_pool(
508
+            m_driver, pool_key, pod, subnets, tuple(security_groups)))
509
+
510
+        neutron.update_port.assert_called_once_with(
511
+            port_id,
512
+            {
513
+                "port": {
514
+                    'security_groups': list(security_groups),
515
+                }
516
+            })
517
+        m_eventlet.assert_not_called()
518
+
519
+    def test__get_port_from_pool_empty_pool_reuse_no_ports(self):
520
+        cls = vif_pool.NeutronVIFPool
521
+        m_driver = mock.MagicMock(spec=cls)
522
+        neutron = self.useFixture(k_fix.MockNeutronClient()).client
523
+
524
+        pod = get_pod_obj()
525
+        port_id = str(uuid.uuid4())
526
+        port = mock.sentinel.port
527
+        pool_key = mock.sentinel.pool_key
528
+        subnets = mock.sentinel.subnets
529
+        security_groups = 'test-sg'
530
+        security_groups_2 = 'test-sg2'
531
+
532
+        oslo_cfg.CONF.set_override('port_debug',
533
+                                   False,
534
+                                   group='kubernetes')
535
+        pool_length = 5
536
+        m_driver._get_pool_size.return_value = pool_length
537
+
538
+        m_driver._available_ports_pools = {
539
+            pool_key: {tuple(security_groups): collections.deque([]),
540
+                       tuple(security_groups_2): collections.deque([])}}
541
+        m_driver._last_update = {}
542
+        m_driver._existing_vifs = {port_id: port}
429 543
 
430 544
         self.assertRaises(exceptions.ResourceNotReady, cls._get_port_from_pool,
431
-                          m_driver, pool_key, pod, subnets)
545
+                          m_driver, pool_key, pod, subnets, tuple(
546
+                              security_groups))
432 547
 
433 548
         neutron.update_port.assert_not_called()
434 549
 
@@ -438,7 +553,7 @@ class NeutronVIFPool(test_base.TestCase):
438 553
         m_driver = mock.MagicMock(spec=cls)
439 554
         neutron = self.useFixture(k_fix.MockNeutronClient()).client
440 555
 
441
-        pool_key = ('node_ip', 'project_id', tuple(['security_group']))
556
+        pool_key = ('node_ip', 'project_id')
442 557
         port_id = str(uuid.uuid4())
443 558
         pool_length = 5
444 559
 
@@ -462,7 +577,6 @@ class NeutronVIFPool(test_base.TestCase):
462 577
                 "port": {
463 578
                     'name': constants.KURYR_PORT_NAME,
464 579
                     'device_id': '',
465
-                    'security_groups': ['security_group']
466 580
                 }
467 581
             })
468 582
         neutron.delete_port.assert_not_called()
@@ -473,7 +587,7 @@ class NeutronVIFPool(test_base.TestCase):
473 587
         m_driver = mock.MagicMock(spec=cls)
474 588
         neutron = self.useFixture(k_fix.MockNeutronClient()).client
475 589
 
476
-        pool_key = ('node_ip', 'project_id', tuple(['security_group']))
590
+        pool_key = ('node_ip', 'project_id')
477 591
         port_id = str(uuid.uuid4())
478 592
         pool_length = 5
479 593
 
@@ -499,7 +613,7 @@ class NeutronVIFPool(test_base.TestCase):
499 613
         m_driver = mock.MagicMock(spec=cls)
500 614
         neutron = self.useFixture(k_fix.MockNeutronClient()).client
501 615
 
502
-        pool_key = ('node_ip', 'project_id', tuple(['security_group']))
616
+        pool_key = ('node_ip', 'project_id')
503 617
         port_id = str(uuid.uuid4())
504 618
         pool_length = 10
505 619
         vif = mock.sentinel.vif
@@ -524,7 +638,7 @@ class NeutronVIFPool(test_base.TestCase):
524 638
         m_driver = mock.MagicMock(spec=cls)
525 639
         neutron = self.useFixture(k_fix.MockNeutronClient()).client
526 640
 
527
-        pool_key = ('node_ip', 'project_id', tuple(['security_group']))
641
+        pool_key = ('node_ip', 'project_id')
528 642
         port_id = str(uuid.uuid4())
529 643
         pool_length = 5
530 644
 
@@ -552,7 +666,6 @@ class NeutronVIFPool(test_base.TestCase):
552 666
                 "port": {
553 667
                     'name': constants.KURYR_PORT_NAME,
554 668
                     'device_id': '',
555
-                    'security_groups': ['security_group']
556 669
                 }
557 670
             })
558 671
         neutron.delete_port.assert_not_called()
@@ -562,7 +675,7 @@ class NeutronVIFPool(test_base.TestCase):
562 675
         m_driver = mock.MagicMock(spec=cls)
563 676
         neutron = self.useFixture(k_fix.MockNeutronClient()).client
564 677
 
565
-        pool_key = ('node_ip', 'project_id', tuple(['security_group']))
678
+        pool_key = ('node_ip', 'project_id')
566 679
         port_id = str(uuid.uuid4())
567 680
         pool_length = 10
568 681
         vif = mock.sentinel.vif
@@ -588,7 +701,7 @@ class NeutronVIFPool(test_base.TestCase):
588 701
         m_driver = mock.MagicMock(spec=cls)
589 702
         neutron = self.useFixture(k_fix.MockNeutronClient()).client
590 703
 
591
-        pool_key = ('node_ip', 'project_id', tuple(['security_group']))
704
+        pool_key = ('node_ip', 'project_id')
592 705
         port_id = str(uuid.uuid4())
593 706
         pool_length = 10
594 707
 
@@ -639,8 +752,7 @@ class NeutronVIFPool(test_base.TestCase):
639 752
         vif = mock.sentinel.vif
640 753
         m_to_osvif.return_value = vif
641 754
 
642
-        pool_key = (port['binding:host_id'], port['project_id'],
643
-                    tuple(port['security_groups']), net_id)
755
+        pool_key = (port['binding:host_id'], port['project_id'], net_id)
644 756
         m_driver._get_pool_key.return_value = pool_key
645 757
         m_driver._get_trunks_info.return_value = ({}, {}, {})
646 758
 
@@ -652,7 +764,8 @@ class NeutronVIFPool(test_base.TestCase):
652 764
         m_to_osvif.assert_called_once_with(vif_plugin, port, subnet)
653 765
 
654 766
         self.assertEqual(m_driver._existing_vifs[port_id], vif)
655
-        self.assertEqual(m_driver._available_ports_pools[pool_key], [port_id])
767
+        self.assertEqual(m_driver._available_ports_pools[pool_key],
768
+                         {tuple(port['security_groups']): [port_id]})
656 769
 
657 770
     @mock.patch('kuryr_kubernetes.os_vif_util.neutron_to_osvif_vif')
658 771
     @mock.patch('kuryr_kubernetes.utils.get_subnet')
@@ -681,9 +794,10 @@ class NeutronVIFPool(test_base.TestCase):
681 794
         neutron = self.useFixture(k_fix.MockNeutronClient()).client
682 795
 
683 796
         net_id = mock.sentinel.net_id
684
-        pool_key = ('node_ip', 'project_id', tuple(['security_group']))
797
+        pool_key = ('node_ip', 'project_id')
685 798
         port_id = str(uuid.uuid4())
686
-        m_driver._available_ports_pools = {pool_key: [port_id]}
799
+        m_driver._available_ports_pools = {pool_key: {
800
+            tuple(['security_group']): [port_id]}}
687 801
         m_driver._existing_vifs = {port_id: mock.sentinel.vif}
688 802
 
689 803
         m_driver._get_pool_key_net.return_value = net_id
@@ -701,9 +815,10 @@ class NeutronVIFPool(test_base.TestCase):
701 815
         neutron = self.useFixture(k_fix.MockNeutronClient()).client
702 816
 
703 817
         net_id = mock.sentinel.net_id
704
-        pool_key = ('node_ip', 'project_id', tuple(['security_group']))
818
+        pool_key = ('node_ip', 'project_id')
705 819
         port_id = str(uuid.uuid4())
706
-        m_driver._available_ports_pools = {pool_key: [port_id]}
820
+        m_driver._available_ports_pools = {pool_key: {
821
+            tuple(['security_group']): [port_id]}}
707 822
         m_driver._existing_vifs = {}
708 823
         neutron.delete_port.side_effect = n_exc.PortNotFoundClient
709 824
 
@@ -765,11 +880,12 @@ class NestedVIFPool(test_base.TestCase):
765 880
         port_id = str(uuid.uuid4())
766 881
         port = mock.sentinel.port
767 882
         subnets = mock.sentinel.subnets
883
+        security_groups = 'test-sg'
768 884
 
769 885
         pod = get_pod_obj()
770 886
 
771 887
         m_driver._available_ports_pools = {
772
-            pool_key: collections.deque([port_id])}
888
+            pool_key: {tuple(security_groups): collections.deque([port_id])}}
773 889
         m_driver._existing_vifs = {port_id: port}
774 890
         m_get_port_name.return_value = get_pod_name(pod)
775 891
 
@@ -783,7 +899,7 @@ class NestedVIFPool(test_base.TestCase):
783 899
         m_driver._get_pool_size.return_value = pool_length
784 900
 
785 901
         self.assertEqual(port, cls._get_port_from_pool(
786
-            m_driver, pool_key, pod, subnets))
902
+            m_driver, pool_key, pod, subnets, tuple(security_groups)))
787 903
 
788 904
         neutron.update_port.assert_called_once_with(
789 905
             port_id,
@@ -806,11 +922,12 @@ class NestedVIFPool(test_base.TestCase):
806 922
         port_id = str(uuid.uuid4())
807 923
         port = mock.sentinel.port
808 924
         subnets = mock.sentinel.subnets
925
+        security_groups = 'test-sg'
809 926
 
810 927
         pod = get_pod_obj()
811 928
 
812 929
         m_driver._available_ports_pools = {
813
-            pool_key: collections.deque([port_id])}
930
+            pool_key: {tuple(security_groups): collections.deque([port_id])}}
814 931
         m_driver._existing_vifs = {port_id: port}
815 932
         m_get_port_name.return_value = get_pod_name(pod)
816 933
 
@@ -824,7 +941,7 @@ class NestedVIFPool(test_base.TestCase):
824 941
         m_driver._get_pool_size.return_value = pool_length
825 942
 
826 943
         self.assertEqual(port, cls._get_port_from_pool(
827
-            m_driver, pool_key, pod, subnets))
944
+            m_driver, pool_key, pod, subnets, tuple(security_groups)))
828 945
 
829 946
         neutron.update_port.assert_called_once_with(
830 947
             port_id,
@@ -843,11 +960,124 @@ class NestedVIFPool(test_base.TestCase):
843 960
         pod = mock.sentinel.pod
844 961
         pool_key = mock.sentinel.pool_key
845 962
         subnets = mock.sentinel.subnets
963
+        security_groups = 'test-sg'
846 964
 
847
-        m_driver._available_ports_pools = {pool_key: collections.deque([])}
965
+        m_driver._available_ports_pools = {
966
+            pool_key: {tuple(security_groups): collections.deque([])}}
967
+        m_driver._last_update = {pool_key: {tuple(security_groups): 1}}
848 968
 
849 969
         self.assertRaises(exceptions.ResourceNotReady, cls._get_port_from_pool,
850
-                          m_driver, pool_key, pod, subnets)
970
+                          m_driver, pool_key, pod, subnets, tuple(
971
+                              security_groups))
972
+
973
+        neutron.update_port.assert_not_called()
974
+
975
+    @mock.patch('eventlet.spawn')
976
+    def test__get_port_from_pool_empty_pool_reuse(self, m_eventlet):
977
+        cls = vif_pool.NestedVIFPool
978
+        m_driver = mock.MagicMock(spec=cls)
979
+        neutron = self.useFixture(k_fix.MockNeutronClient()).client
980
+
981
+        pod = mock.sentinel.pod
982
+        port_id = str(uuid.uuid4())
983
+        port = mock.sentinel.port
984
+        pool_key = mock.sentinel.pool_key
985
+        subnets = mock.sentinel.subnets
986
+        security_groups = 'test-sg'
987
+        security_groups_2 = 'test-sg2'
988
+
989
+        oslo_cfg.CONF.set_override('port_debug',
990
+                                   False,
991
+                                   group='kubernetes')
992
+        pool_length = 5
993
+        m_driver._get_pool_size.return_value = pool_length
994
+
995
+        m_driver._available_ports_pools = {
996
+            pool_key: {tuple(security_groups): collections.deque([]),
997
+                       tuple(security_groups_2): collections.deque([port_id])}}
998
+        m_driver._last_update = {pool_key: {tuple(security_groups): 1,
999
+                                            tuple(security_groups_2): 0}}
1000
+        m_driver._existing_vifs = {port_id: port}
1001
+
1002
+        self.assertEqual(port, cls._get_port_from_pool(
1003
+            m_driver, pool_key, pod, subnets, tuple(security_groups)))
1004
+
1005
+        neutron.update_port.assert_called_once_with(
1006
+            port_id,
1007
+            {
1008
+                "port": {
1009
+                    'security_groups': list(security_groups),
1010
+                }
1011
+            })
1012
+        m_eventlet.assert_not_called()
1013
+
1014
+    @mock.patch('eventlet.spawn')
1015
+    def test__get_port_from_pool_empty_pool_reuse_no_update_info(self,
1016
+                                                                 m_eventlet):
1017
+        cls = vif_pool.NestedVIFPool
1018
+        m_driver = mock.MagicMock(spec=cls)
1019
+        neutron = self.useFixture(k_fix.MockNeutronClient()).client
1020
+
1021
+        pod = mock.sentinel.pod
1022
+        port_id = str(uuid.uuid4())
1023
+        port = mock.sentinel.port
1024
+        pool_key = mock.sentinel.pool_key
1025
+        subnets = mock.sentinel.subnets
1026
+        security_groups = 'test-sg'
1027
+        security_groups_2 = 'test-sg2'
1028
+
1029
+        oslo_cfg.CONF.set_override('port_debug',
1030
+                                   False,
1031
+                                   group='kubernetes')
1032
+        pool_length = 5
1033
+        m_driver._get_pool_size.return_value = pool_length
1034
+
1035
+        m_driver._available_ports_pools = {
1036
+            pool_key: {tuple(security_groups): collections.deque([]),
1037
+                       tuple(security_groups_2): collections.deque([port_id])}}
1038
+        m_driver._last_update = {}
1039
+        m_driver._existing_vifs = {port_id: port}
1040
+
1041
+        self.assertEqual(port, cls._get_port_from_pool(
1042
+            m_driver, pool_key, pod, subnets, tuple(security_groups)))
1043
+
1044
+        neutron.update_port.assert_called_once_with(
1045
+            port_id,
1046
+            {
1047
+                "port": {
1048
+                    'security_groups': list(security_groups),
1049
+                }
1050
+            })
1051
+        m_eventlet.assert_not_called()
1052
+
1053
+    def test__get_port_from_pool_empty_pool_reuse_no_ports(self):
1054
+        cls = vif_pool.NestedVIFPool
1055
+        m_driver = mock.MagicMock(spec=cls)
1056
+        neutron = self.useFixture(k_fix.MockNeutronClient()).client
1057
+
1058
+        pod = mock.sentinel.pod
1059
+        port_id = str(uuid.uuid4())
1060
+        port = mock.sentinel.port
1061
+        pool_key = mock.sentinel.pool_key
1062
+        subnets = mock.sentinel.subnets
1063
+        security_groups = 'test-sg'
1064
+        security_groups_2 = 'test-sg2'
1065
+
1066
+        oslo_cfg.CONF.set_override('port_debug',
1067
+                                   False,
1068
+                                   group='kubernetes')
1069
+        pool_length = 5
1070
+        m_driver._get_pool_size.return_value = pool_length
1071
+
1072
+        m_driver._available_ports_pools = {
1073
+            pool_key: {tuple(security_groups): collections.deque([]),
1074
+                       tuple(security_groups_2): collections.deque([])}}
1075
+        m_driver._last_update = {}
1076
+        m_driver._existing_vifs = {port_id: port}
1077
+
1078
+        self.assertRaises(exceptions.ResourceNotReady, cls._get_port_from_pool,
1079
+                          m_driver, pool_key, pod, subnets, tuple(
1080
+                              security_groups))
851 1081
 
852 1082
         neutron.update_port.assert_not_called()
853 1083
 
@@ -857,7 +1087,7 @@ class NestedVIFPool(test_base.TestCase):
857 1087
         m_driver = mock.MagicMock(spec=cls)
858 1088
         neutron = self.useFixture(k_fix.MockNeutronClient()).client
859 1089
 
860
-        pool_key = ('node_ip', 'project_id', tuple(['security_group']))
1090
+        pool_key = ('node_ip', 'project_id')
861 1091
         port_id = str(uuid.uuid4())
862 1092
         pool_length = 5
863 1093
 
@@ -880,7 +1110,6 @@ class NestedVIFPool(test_base.TestCase):
880 1110
             {
881 1111
                 "port": {
882 1112
                     'name': constants.KURYR_PORT_NAME,
883
-                    'security_groups': ['security_group']
884 1113
                 }
885 1114
             })
886 1115
         neutron.delete_port.assert_not_called()
@@ -891,7 +1120,7 @@ class NestedVIFPool(test_base.TestCase):
891 1120
         m_driver = mock.MagicMock(spec=cls)
892 1121
         neutron = self.useFixture(k_fix.MockNeutronClient()).client
893 1122
 
894
-        pool_key = ('node_ip', 'project_id', tuple(['security_group']))
1123
+        pool_key = ('node_ip', 'project_id')
895 1124
         port_id = str(uuid.uuid4())
896 1125
         pool_length = 5
897 1126
 
@@ -920,7 +1149,7 @@ class NestedVIFPool(test_base.TestCase):
920 1149
         vif_driver = mock.MagicMock(spec=cls_vif_driver)
921 1150
         m_driver._drv_vif = vif_driver
922 1151
 
923
-        pool_key = ('node_ip', 'project_id', tuple(['security_group']))
1152
+        pool_key = ('node_ip', 'project_id')
924 1153
         port_id = str(uuid.uuid4())
925 1154
         pool_length = 10
926 1155
         vif = mock.MagicMock()
@@ -953,7 +1182,7 @@ class NestedVIFPool(test_base.TestCase):
953 1182
         m_driver = mock.MagicMock(spec=cls)
954 1183
         neutron = self.useFixture(k_fix.MockNeutronClient()).client
955 1184
 
956
-        pool_key = ('node_ip', 'project_id', tuple(['security_group']))
1185
+        pool_key = ('node_ip', 'project_id')
957 1186
         port_id = str(uuid.uuid4())
958 1187
         pool_length = 5
959 1188
 
@@ -977,7 +1206,6 @@ class NestedVIFPool(test_base.TestCase):
977 1206
             {
978 1207
                 "port": {
979 1208
                     'name': constants.KURYR_PORT_NAME,
980
-                    'security_groups': ['security_group']
981 1209
                 }
982 1210
             })
983 1211
         neutron.delete_port.assert_not_called()
@@ -990,7 +1218,7 @@ class NestedVIFPool(test_base.TestCase):
990 1218
         vif_driver = mock.MagicMock(spec=cls_vif_driver)
991 1219
         m_driver._drv_vif = vif_driver
992 1220
 
993
-        pool_key = ('node_ip', 'project_id', tuple(['security_group']))
1221
+        pool_key = ('node_ip', 'project_id')
994 1222
         port_id = str(uuid.uuid4())
995 1223
         pool_length = 10
996 1224
         vif = mock.MagicMock()
@@ -1027,7 +1255,7 @@ class NestedVIFPool(test_base.TestCase):
1027 1255
         vif_driver = mock.MagicMock(spec=cls_vif_driver)
1028 1256
         m_driver._drv_vif = vif_driver
1029 1257
 
1030
-        pool_key = ('node_ip', 'project_id', tuple(['security_group']))
1258
+        pool_key = ('node_ip', 'project_id')
1031 1259
         port_id = str(uuid.uuid4())
1032 1260
         pool_length = 10
1033 1261
         trunk_id = str(uuid.uuid4())
@@ -1163,15 +1391,15 @@ class NestedVIFPool(test_base.TestCase):
1163 1391
         vif = mock.sentinel.vif
1164 1392
         m_to_osvif.return_value = vif
1165 1393
 
1166
-        pool_key = (port['binding:host_id'], port['project_id'],
1167
-                    tuple(port['security_groups']), net_id)
1394
+        pool_key = (port['binding:host_id'], port['project_id'], net_id)
1168 1395
         m_driver._get_pool_key.return_value = pool_key
1169 1396
 
1170 1397
         cls._precreated_ports(m_driver, 'recover')
1171 1398
 
1172 1399
         m_driver._get_trunks_info.assert_called_once()
1173 1400
         self.assertEqual(m_driver._existing_vifs[port_id], vif)
1174
-        self.assertEqual(m_driver._available_ports_pools[pool_key], [port_id])
1401
+        self.assertEqual(m_driver._available_ports_pools[pool_key],
1402
+                         {tuple(port['security_groups']): [port_id]})
1175 1403
         neutron.delete_port.assert_not_called()
1176 1404
 
1177 1405
     def test__precreated_ports_free(self):
@@ -1200,10 +1428,10 @@ class NestedVIFPool(test_base.TestCase):
1200 1428
         m_driver._get_trunks_info.return_value = (p_ports, a_subports,
1201 1429
                                                   subnets)
1202 1430
 
1203
-        pool_key = (port['binding:host_id'], port['project_id'],
1204
-                    tuple(port['security_groups']), net_id)
1431
+        pool_key = (port['binding:host_id'], port['project_id'], net_id)
1205 1432
         m_driver._get_pool_key.return_value = pool_key
1206
-        m_driver._available_ports_pools = {pool_key: [port_id]}
1433
+        m_driver._available_ports_pools = {
1434
+            pool_key: {tuple(port['security_groups']): [port_id]}}
1207 1435
         m_driver._existing_vifs = {port_id: mock.sentinel.vif}
1208 1436
 
1209 1437
         cls._precreated_ports(m_driver, 'free')
@@ -1214,7 +1442,8 @@ class NestedVIFPool(test_base.TestCase):
1214 1442
         m_driver._drv_vif._release_vlan_id.assert_called_once()
1215 1443
 
1216 1444
         self.assertEqual(m_driver._existing_vifs, {})
1217
-        self.assertEqual(m_driver._available_ports_pools[pool_key], [])
1445
+        self.assertEqual(m_driver._available_ports_pools[pool_key][tuple(
1446
+            port['security_groups'])], [])
1218 1447
 
1219 1448
     @mock.patch('kuryr_kubernetes.os_vif_util.'
1220 1449
                 'neutron_to_osvif_vif_nested_vlan')
@@ -1302,8 +1531,7 @@ class NestedVIFPool(test_base.TestCase):
1302 1531
         vif = mock.sentinel.vif
1303 1532
         m_to_osvif.return_value = vif
1304 1533
 
1305
-        pool_key = (port1['binding:host_id'], port1['project_id'],
1306
-                    tuple(port1['security_groups']), net_id)
1534
+        pool_key = (port1['binding:host_id'], port1['project_id'], net_id)
1307 1535
         m_driver._get_pool_key.return_value = pool_key
1308 1536
         cls._precreated_ports(m_driver, 'recover')
1309 1537
 
@@ -1311,7 +1539,8 @@ class NestedVIFPool(test_base.TestCase):
1311 1539
         self.assertEqual(m_driver._existing_vifs, {port_id1: vif,
1312 1540
                                                    port_id2: vif})
1313 1541
         self.assertEqual(m_driver._available_ports_pools[pool_key],
1314
-                         [port_id1, port_id2])
1542
+                         {tuple(port1['security_groups']): [port_id1,
1543
+                                                            port_id2]})
1315 1544
         neutron.delete_port.assert_not_called()
1316 1545
 
1317 1546
     @ddt.data(('recover'), ('free'))
@@ -1382,13 +1611,14 @@ class NestedVIFPool(test_base.TestCase):
1382 1611
         neutron = self.useFixture(k_fix.MockNeutronClient()).client
1383 1612
 
1384 1613
         net_id = mock.sentinel.net_id
1385
-        pool_key = ('node_ip', 'project_id', tuple(['security_group']))
1614
+        pool_key = ('node_ip', 'project_id')
1386 1615
         port_id = str(uuid.uuid4())
1387 1616
         trunk_id = str(uuid.uuid4())
1388 1617
         vif = mock.MagicMock()
1389 1618
         vlan_id = mock.sentinel.vlan_id
1390 1619
         vif.vlan_id = vlan_id
1391
-        m_driver._available_ports_pools = {pool_key: [port_id]}
1620
+        m_driver._available_ports_pools = {pool_key: {
1621
+            tuple(['security_group']): [port_id]}}
1392 1622
         m_driver._existing_vifs = {port_id: vif}
1393 1623
 
1394 1624
         m_driver._get_trunk_id.return_value = trunk_id
@@ -1415,13 +1645,14 @@ class NestedVIFPool(test_base.TestCase):
1415 1645
         neutron = self.useFixture(k_fix.MockNeutronClient()).client
1416 1646
 
1417 1647
         net_id = mock.sentinel.net_id
1418
-        pool_key = ('node_ip', 'project_id', tuple(['security_group']))
1648
+        pool_key = ('node_ip', 'project_id')
1419 1649
         port_id = str(uuid.uuid4())
1420 1650
         trunk_id = str(uuid.uuid4())
1421 1651
         vif = mock.MagicMock()
1422 1652
         vlan_id = mock.sentinel.vlan_id
1423 1653
         vif.vlan_id = vlan_id
1424
-        m_driver._available_ports_pools = {pool_key: [port_id]}
1654
+        m_driver._available_ports_pools = {pool_key: {
1655
+            tuple(['security_group']): [port_id]}}
1425 1656
         m_driver._existing_vifs = {port_id: vif}
1426 1657
 
1427 1658
         m_driver._get_trunk_id.return_value = trunk_id
@@ -1450,13 +1681,14 @@ class NestedVIFPool(test_base.TestCase):
1450 1681
         neutron = self.useFixture(k_fix.MockNeutronClient()).client
1451 1682
 
1452 1683
         net_id = mock.sentinel.net_id
1453
-        pool_key = ('node_ip', 'project_id', tuple(['security_group']))
1684
+        pool_key = ('node_ip', 'project_id')
1454 1685
         port_id = str(uuid.uuid4())
1455 1686
         trunk_id = str(uuid.uuid4())
1456 1687
         vif = mock.MagicMock()
1457 1688
         vlan_id = mock.sentinel.vlan_id
1458 1689
         vif.vlan_id = vlan_id
1459
-        m_driver._available_ports_pools = {pool_key: [port_id]}
1690
+        m_driver._available_ports_pools = {pool_key: {
1691
+            tuple(['security_group']): [port_id]}}
1460 1692
         m_driver._existing_vifs = {}
1461 1693
 
1462 1694
         m_driver._get_trunk_id.return_value = trunk_id

Loading…
Cancel
Save