summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWeifan Fu <weifan.fu@bigswitch.com>2018-11-28 13:16:59 -0800
committerWeifan Fu <weifan.fu@bigswitch.com>2018-12-19 14:05:18 -0800
commitc3255d8a0e84127500ccdfc2d790af2697603628 (patch)
treeb5d5c841f6c78a3ee071197b4e683961e8607f2d
parent53148f16ff54d866e76770925a6588c0eb111083 (diff)
BCF-11522: Fix inconsitent unicode mode issue
- Initialize capabilities before using it - Trigger capability update only once during server startup - Add more debug level messages - Some cleanup for no longer needed logics There are some issues with OSP threading, with periodic check, only one thread would update capabilities despite there is only one ServerPool instance. Currently we are not sure what causes this. There will be another issue with multiple overcloud controllers, we do not want to read from db for unicode status for every REST call. As a solution, Neutron restart is always required when controller unicode support changes. Change-Id: I71b504e7b7b7f18efd08b9945161bef460390ec7
Notes
Notes (review): Code-Review+2: Aditya Vaja <wolverine.av@gmail.com> Workflow+1: Aditya Vaja <wolverine.av@gmail.com> Verified+2: Zuul Submitted-by: Zuul Submitted-at: Thu, 20 Dec 2018 23:39:32 +0000 Reviewed-on: https://review.openstack.org/625992 Project: openstack/networking-bigswitch Branch: refs/heads/master
-rw-r--r--networking_bigswitch/plugins/bigswitch/servermanager.py91
-rw-r--r--networking_bigswitch/tests/unit/bigswitch/test_base.py1
-rw-r--r--networking_bigswitch/tests/unit/bigswitch/test_servermanager.py2
3 files changed, 33 insertions, 61 deletions
diff --git a/networking_bigswitch/plugins/bigswitch/servermanager.py b/networking_bigswitch/plugins/bigswitch/servermanager.py
index 63587cb..dfa1de7 100644
--- a/networking_bigswitch/plugins/bigswitch/servermanager.py
+++ b/networking_bigswitch/plugins/bigswitch/servermanager.py
@@ -463,6 +463,7 @@ class ServerPool(object):
463 self.neutron_id = cfg.CONF.RESTPROXY.neutron_id 463 self.neutron_id = cfg.CONF.RESTPROXY.neutron_id
464 # unicode config 464 # unicode config
465 self.cfg_unicode_enabled = cfg.CONF.RESTPROXY.naming_scheme_unicode 465 self.cfg_unicode_enabled = cfg.CONF.RESTPROXY.naming_scheme_unicode
466 self.capabilities = set()
466 467
467 if 'keystone_authtoken' in cfg.CONF: 468 if 'keystone_authtoken' in cfg.CONF:
468 self.auth_user = get_keystoneauth_cfg(cfg.CONF, 'username') 469 self.auth_user = get_keystoneauth_cfg(cfg.CONF, 'username')
@@ -497,10 +498,9 @@ class ServerPool(object):
497 # The cache is maintained in a separate thread and sync'ed with 498 # The cache is maintained in a separate thread and sync'ed with
498 # Keystone periodically. 499 # Keystone periodically.
499 self.keystone_tenants = {} 500 self.keystone_tenants = {}
500 self._update_tenant_cache(reconcile=False) 501
501 self.timeout = cfg.CONF.RESTPROXY.server_timeout 502 self.timeout = cfg.CONF.RESTPROXY.server_timeout
502 self.always_reconnect = not cfg.CONF.RESTPROXY.cache_connections 503 self.always_reconnect = not cfg.CONF.RESTPROXY.cache_connections
503 self.capabilities = []
504 default_port = 8000 504 default_port = 8000
505 if timeout is not False: 505 if timeout is not False:
506 self.timeout = timeout 506 self.timeout = timeout
@@ -527,6 +527,12 @@ class ServerPool(object):
527 # strip [] for ipv6 address 527 # strip [] for ipv6 address
528 server = server[1:-1] 528 server = server[1:-1]
529 self.servers.append(self.server_proxy_for(server, int(port))) 529 self.servers.append(self.server_proxy_for(server, int(port)))
530
531 # update capabilities
532 self.get_capabilities()
533
534 self._update_tenant_cache(reconcile=False)
535
530 self.start_background_tasks() 536 self.start_background_tasks()
531 537
532 ServerPool._instance = self 538 ServerPool._instance = self
@@ -534,10 +540,6 @@ class ServerPool(object):
534 LOG.debug("ServerPool: initialization done") 540 LOG.debug("ServerPool: initialization done")
535 541
536 def start_background_tasks(self): 542 def start_background_tasks(self):
537 # update capabilities, starts immediately
538 # updates every 5 minutes, mostly for bcf upgrade/downgrade cases
539 eventlet.spawn(self._capability_watchdog, 300)
540
541 # consistency check, starts after 1* consistency_interval 543 # consistency check, starts after 1* consistency_interval
542 eventlet.spawn(self._consistency_watchdog, 544 eventlet.spawn(self._consistency_watchdog,
543 cfg.CONF.RESTPROXY.consistency_interval) 545 cfg.CONF.RESTPROXY.consistency_interval)
@@ -562,18 +564,8 @@ class ServerPool(object):
562 # if capabilities is empty, the check is either not done, or failed 564 # if capabilities is empty, the check is either not done, or failed
563 if self.capabilities: 565 if self.capabilities:
564 return self.capabilities 566 return self.capabilities
565 else:
566 return self.get_capabilities_force_update()
567
568 def get_capabilities_force_update(self):
569 """Do REST calls to update capabilities
570 567
571 Logs a unicode change message when: 568 # Do REST calls to update capabilities at startup
572 1. the first time that plugin gets capabilities from BCF
573 2. plugin notices the unicode mode is changed
574
575 :return: combined capability list from all servers
576 """
577 # Servers should be the same version 569 # Servers should be the same version
578 # If one server is down, use online server's capabilities 570 # If one server is down, use online server's capabilities
579 capability_list = [set(server.get_capabilities()) 571 capability_list = [set(server.get_capabilities())
@@ -581,8 +573,10 @@ class ServerPool(object):
581 573
582 new_capabilities = set.union(*capability_list) 574 new_capabilities = set.union(*capability_list)
583 575
584 self.log_unicode_status_change(new_capabilities) 576 if new_capabilities:
585 self.capabilities = new_capabilities 577 # Log unicode status
578 self.log_unicode_status(new_capabilities)
579 self.capabilities = new_capabilities
586 580
587 # With multiple workers enabled, the fork may occur after the 581 # With multiple workers enabled, the fork may occur after the
588 # connections to the DB have been established. We need to clear the 582 # connections to the DB have been established. We need to clear the
@@ -603,38 +597,25 @@ class ServerPool(object):
603 LOG.error('Failed to get capabilities on any controller. ') 597 LOG.error('Failed to get capabilities on any controller. ')
604 return self.capabilities 598 return self.capabilities
605 599
606 def log_unicode_status_change(self, new_capabilities): 600 def log_unicode_status(self, new_capabilities):
607 """Log unicode status, if capabilities is initialized or if changed 601 """Log unicode running status
608 602
609 Compares old capabilities with new capabilities
610 :param new_capabilities: new capabilities 603 :param new_capabilities: new capabilities
611 :return: 604 :return:
612 """ 605 """
613 if new_capabilities and self.capabilities != new_capabilities: 606 # unicode disabled by user
614 # unicode disabled by user 607 if not self.cfg_unicode_enabled:
615 if not self.cfg_unicode_enabled: 608 LOG.info('naming_scheme_unicode is set to False,'
616 # Log only during Initialization 609 ' Unicode names Disabled')
617 if not self.capabilities: 610 # unicode enabled and supported by controller
618 LOG.info('naming_scheme_unicode is set to False,' 611 elif 'display-name' in new_capabilities:
619 ' Unicode names Disabled') 612 LOG.info('naming_scheme_unicode is set to True,'
620 # unicode enabled and supported by controller 613 ' Unicode names Enabled')
621 elif 'display-name' in new_capabilities: 614 # unicode enabled, but not supported by controller
622 # Log for 2 situations: 615 else:
623 # 1. Initialization 616 LOG.warning('naming_scheme_unicode is set to True,'
624 # 2. BCF is upgraded to support unicode 617 ' but BCF does not support it.'
625 if 'display-name' not in self.capabilities: 618 ' Unicode names Disabled')
626 LOG.info('naming_scheme_unicode is set to True,'
627 ' Unicode names Enabled')
628 # unicode enabled, but not supported by controller
629 else:
630 # Log for 2 situations:
631 # 1. Initialization
632 # 2. BCF is downgraded, no longer supports unicode
633 if not self.capabilities or 'display-name' in \
634 self.capabilities:
635 LOG.warning('naming_scheme_unicode is set to True,'
636 ' but BCF does not support it.'
637 ' Unicode names Disabled')
638 619
639 def is_unicode_enabled(self): 620 def is_unicode_enabled(self):
640 """Check unicode running status 621 """Check unicode running status
@@ -642,14 +623,17 @@ class ServerPool(object):
642 True: enabled 623 True: enabled
643 False: disabled 624 False: disabled
644 """ 625 """
626 LOG.debug('Current Capabilities: %s', self.get_capabilities())
645 if not self.get_capabilities(): 627 if not self.get_capabilities():
646 msg = 'Capabilities unknown! Please check BCF controller status.' 628 msg = 'Capabilities unknown! Please check BCF controller status.'
647 raise RemoteRestError(reason=msg) 629 raise RemoteRestError(reason=msg)
648 630
649 if self.cfg_unicode_enabled and 'display-name' in \ 631 if self.cfg_unicode_enabled and 'display-name' in \
650 self.get_capabilities(): 632 self.get_capabilities():
633 LOG.debug('Unicode Check=True')
651 return True 634 return True
652 else: 635 else:
636 LOG.debug('Unicode Check=False')
653 return False 637 return False
654 638
655 def server_proxy_for(self, server, port): 639 def server_proxy_for(self, server, port):
@@ -1122,19 +1106,6 @@ class ServerPool(object):
1122 LOG.exception("Encountered an error checking controller " 1106 LOG.exception("Encountered an error checking controller "
1123 "health.") 1107 "health.")
1124 1108
1125 def _capability_watchdog(self, polling_interval=300):
1126 """Check capabilities based on polling_interval
1127
1128 :param polling_interval: interval in seconds
1129 """
1130 while True:
1131 try:
1132 self.get_capabilities_force_update()
1133 except Exception:
1134 LOG.exception("Encountered an error checking capabilities.")
1135 finally:
1136 eventlet.sleep(polling_interval)
1137
1138 def force_topo_sync(self, check_ts=True): 1109 def force_topo_sync(self, check_ts=True):
1139 """Execute a topology_sync between OSP and BCF. 1110 """Execute a topology_sync between OSP and BCF.
1140 1111
diff --git a/networking_bigswitch/tests/unit/bigswitch/test_base.py b/networking_bigswitch/tests/unit/bigswitch/test_base.py
index 1714dc4..a3d4072 100644
--- a/networking_bigswitch/tests/unit/bigswitch/test_base.py
+++ b/networking_bigswitch/tests/unit/bigswitch/test_base.py
@@ -105,6 +105,7 @@ class BigSwitchTestBase(object):
105 self.is_unicode_enabled_p = mock.patch( 105 self.is_unicode_enabled_p = mock.patch(
106 IS_UNICODE_ENABLED, 106 IS_UNICODE_ENABLED,
107 side_effect=self.is_unicode_enabled_side_effect) 107 side_effect=self.is_unicode_enabled_side_effect)
108
108 # start all mock patches 109 # start all mock patches
109 self.log_exc_p.start() 110 self.log_exc_p.start()
110 self.lib_rpc_transport_p.start() 111 self.lib_rpc_transport_p.start()
diff --git a/networking_bigswitch/tests/unit/bigswitch/test_servermanager.py b/networking_bigswitch/tests/unit/bigswitch/test_servermanager.py
index f1fd2a7..0f516a4 100644
--- a/networking_bigswitch/tests/unit/bigswitch/test_servermanager.py
+++ b/networking_bigswitch/tests/unit/bigswitch/test_servermanager.py
@@ -212,7 +212,7 @@ class ServerManagerTests(test_rp.BigSwitchProxyPluginV2TestCase):
212 self.assertEqual(set(['a', 'b', 'c', 'd']), sp.get_capabilities()) 212 self.assertEqual(set(['a', 'b', 'c', 'd']), sp.get_capabilities())
213 self.assertEqual(2, rv.read.call_count) 213 self.assertEqual(2, rv.read.call_count)
214 214
215 # the pool should cache after the first call during a short period 215 # the pool should cache after the first call
216 # so no more HTTP calls should be made 216 # so no more HTTP calls should be made
217 rv.read.side_effect = ['["w","x","y"]', '["x","y","z"]'] 217 rv.read.side_effect = ['["w","x","y"]', '["x","y","z"]']
218 self.assertEqual(set(['a', 'b', 'c', 'd']), sp.get_capabilities()) 218 self.assertEqual(set(['a', 'b', 'c', 'd']), sp.get_capabilities())