diff --git a/src/opserver/opserver.py b/src/opserver/opserver.py index a47fdd05d8f..86b3b1cd683 100644 --- a/src/opserver/opserver.py +++ b/src/opserver/opserver.py @@ -494,6 +494,13 @@ def __init__(self, args_str=' '.join(sys.argv[1:])): self._chksum = hashlib.md5("".join(self._args.collectors)).hexdigest() self.random_collectors = random.sample(self._args.collectors, \ len(self._args.collectors)) + self._api_server_checksum = '' + if self._args.api_server: + self._api_server_checksum = hashlib.md5(''.join( + self._args.api_server)).hexdigest() + self._args.api_server = random.sample(self._args.api_server, + len(self._args.api_server)) + self._sandesh.init_generator( self._moduleid, self._hostname, self._node_type_name, self._instance_id, self.random_collectors, 'opserver_context', @@ -533,6 +540,7 @@ def __init__(self, args_str=' '.join(sys.argv[1:])): body = gevent.queue.Queue() self._vnc_api_client = None + self._vnc_api_client_connect = None if self._args.auth_conf_info.get('cloud_admin_access_only'): self._vnc_api_client = VncCfgApiClient(self._args.auth_conf_info, self._sandesh, self._logger) @@ -863,7 +871,7 @@ def _parse_args(self, args_str=' '.join(sys.argv[1:])): 'sandesh_send_rate_limit': SandeshSystem. \ get_sandesh_send_rate_limit(), 'aaa_mode' : AAA_MODE_RBAC, - 'api_server' : '127.0.0.1:8082', + 'api_server' : ['127.0.0.1:8082'], 'admin_port' : OpServerAdminPort, 'cloud_admin_role' : CLOUD_ADMIN_ROLE, 'api_server_use_ssl': False, @@ -1023,7 +1031,8 @@ def _parse_args(self, args_str=' '.join(sys.argv[1:])): parser.add_argument("--admin_tenant_name", help="Tenant name for keystone admin user") parser.add_argument("--api_server", - help="Address of VNC API server in ip:port format") + help="List of api-servers in ip:port format separated by space", + nargs="+") parser.add_argument("--admin_port", help="Port with local auth for admin access") parser.add_argument("--api_server_use_ssl", @@ -1047,6 +1056,8 @@ def _parse_args(self, args_str=' '.join(sys.argv[1:])): self._args.cassandra_server_list = self._args.cassandra_server_list.split() if type(self._args.zk_list) is str: self._args.zk_list= self._args.zk_list.split() + if type(self._args.api_server) is str: + self._args.api_server = self._args.api_server.split() auth_conf_info = {} auth_conf_info['admin_user'] = self._args.admin_user @@ -1063,9 +1074,7 @@ def _parse_args(self, args_str=' '.join(sys.argv[1:])): auth_conf_info['cloud_admin_role'] = self._args.cloud_admin_role auth_conf_info['aaa_mode'] = self._args.aaa_mode auth_conf_info['admin_port'] = self._args.admin_port - api_server_info = self._args.api_server.split(':') - auth_conf_info['api_server_ip'] = api_server_info[0] - auth_conf_info['api_server_port'] = int(api_server_info[1]) + auth_conf_info['api_servers'] = self._args.api_server self._args.auth_conf_info = auth_conf_info self._args.conf_file = args.conf_file self._args.sandesh_config = SandeshConfig(self._args.sandesh_keyfile, @@ -2531,7 +2540,9 @@ def run(self): self._ad.start() if self._vnc_api_client: - self.gevs.append(gevent.spawn(self._vnc_api_client.connect)) + self._vnc_api_client_connect = gevent.spawn( + self._vnc_api_client.connect) + self.gevs.append(self._vnc_api_client_connect) self._local_app = LocalApp(bottle.app(), self._args.auth_conf_info) self.gevs.append(gevent.spawn(self._local_app.start_http_server)) @@ -2573,6 +2584,9 @@ def sighup_handler(self): if 'DEFAULTS' in config.sections(): try: collectors = config.get('DEFAULTS', 'collectors') + except ConfigParser.NoOptionError as e: + pass + else: if type(collectors) is str: collectors = collectors.split() new_chksum = hashlib.md5("".join(collectors)).hexdigest() @@ -2580,8 +2594,28 @@ def sighup_handler(self): self._chksum = new_chksum random_collectors = random.sample(collectors, len(collectors)) self._sandesh.reconfig_collectors(random_collectors) + try: + api_servers = config.get('DEFAULTS', 'api_server') except ConfigParser.NoOptionError as e: pass + else: + if type(api_servers) is str: + api_servers = api_servers.split() + new_api_server_checksum = hashlib.md5(''.join( + api_servers)).hexdigest() + if new_api_server_checksum != self._api_server_checksum: + self._api_server_checksum = new_api_server_checksum + random_api_servers = random.sample(api_servers, + len(api_servers)) + if self._vnc_api_client_connect: + self.gevs.remove(self._vnc_api_client_connect) + if not self._vnc_api_client_connect.ready(): + self._vnc_api_client_connect.kill() + if self._vnc_api_client: + self._vnc_api_client_connect = gevent.spawn( + self._vnc_api_client.update_api_servers, + random_api_servers) + self.gevs.append(self._vnc_api_client_connect) # end sighup_handler def main(args_str=' '.join(sys.argv[1:])): diff --git a/src/opserver/vnc_cfg_api_client.py b/src/opserver/vnc_cfg_api_client.py index 8fdcc9a9762..78103a40e36 100644 --- a/src/opserver/vnc_cfg_api_client.py +++ b/src/opserver/vnc_cfg_api_client.py @@ -19,10 +19,9 @@ def __init__(self, conf_info, sandesh_instance, logger): # end __init__ def _update_connection_state(self, status, message = ''): - server_addrs = ['%s:%d' % (self._conf_info['api_server_ip'], \ - self._conf_info['api_server_port'])] ConnectionState.update(conn_type=ConnectionType.APISERVER, name='', - status=status, message=message, server_addrs=server_addrs) + status=status, message=message, + server_addrs=self._conf_info['api_servers']) # end _update_connection_state def _get_user_token_info(self, user_token, uuid=None): @@ -33,9 +32,18 @@ def _get_user_token_info(self, user_token, uuid=None): return None # end _get_user_token_info + def update_api_servers(self, api_servers): + self._conf_info['api_servers'] = api_servers + self._vnc_api_client = None + self.connect() + # end update_api_servers + def connect(self): # Retry till API server is up connected = False + api_server_list = [s.split(':')[0] for s in self._conf_info['api_servers']] + api_server_port = self._conf_info['api_servers'][0].split(':')[1] \ + if self._conf_info['api_servers'] else None self._update_connection_state(ConnectionStatus.INIT) while not connected: try: @@ -43,8 +51,7 @@ def connect(self): self._conf_info['admin_user'], self._conf_info['admin_password'], self._conf_info['admin_tenant_name'], - self._conf_info['api_server_ip'], - self._conf_info['api_server_port'], + api_server_list, api_server_port, api_server_use_ssl=self._conf_info['api_server_use_ssl'], auth_host=self._conf_info['auth_host'], auth_port=self._conf_info['auth_port'],