def __init__(self): self._cnf = bus.cnf self._nginx_v2_flag_filepath = os.path.join(bus.etc_path, "private.d/nginx_v2") ServiceCtlHandler.__init__(self, BEHAVIOUR, initdv2.lookup('nginx'), NginxCnfController()) self._logger = logging.getLogger(__name__) self.preset_provider = NginxPresetProvider() self.api = NginxAPI() self.api.init_service() self._terminating_servers = [] bus.define_events("nginx_upstream_reload") bus.on(init=self.on_init, reload=self.on_reload) self.on_reload()
def __init__(self): self._cnf = bus.cnf ServiceCtlHandler.__init__(self, BEHAVIOUR, initdv2.lookup('nginx'), NginxCnfController()) self._logger = logging.getLogger(__name__) self.preset_provider = NginxPresetProvider() self.api = NginxAPI() self._terminating_servers = [] preset_service.services[BEHAVIOUR] = self.preset_provider bus.define_events("nginx_upstream_reload") bus.on(init=self.on_init, reload=self.on_reload) self.on_reload()
class NginxHandler(ServiceCtlHandler): _nginx_v2_flag_filepath = os.path.join(bus.etc_path, "private.d/nginx_v2") def __init__(self): self._cnf = bus.cnf ServiceCtlHandler.__init__(self, BEHAVIOUR, initdv2.lookup('nginx'), NginxCnfController()) self._logger = logging.getLogger(__name__) self.preset_provider = NginxPresetProvider() self.api = NginxAPI() self._terminating_servers = [] preset_service.services[BEHAVIOUR] = self.preset_provider bus.define_events("nginx_upstream_reload") bus.on(init=self.on_init, reload=self.on_reload) self.on_reload() def on_init(self): bus.on(start=self.on_start, before_host_up=self.on_before_host_up, host_init_response=self.on_host_init_response) self._insert_iptables_rules() if __node__['state'] == ScalarizrState.BOOTSTRAPPING: self._stop_service('Configuring') def on_reload(self): self._queryenv = bus.queryenv_service self._nginx_binary = __nginx__['binary_path'] self._app_inc_path = __nginx__['app_include_path'] self._app_port = __nginx__['app_port'] try: self._upstream_app_role = __nginx__['upstream_app_role'] except ConfigParser.Error: self._upstream_app_role = None def on_host_init_response(self, message): self._logger.debug('Handling on_host_init_response message') if hasattr(message, BEHAVIOUR): data = getattr(message, BEHAVIOUR) if not data and hasattr(message, 'nginx'): data = getattr(message, 'nginx') self._logger.debug('message data: %s' % data) if data and 'preset' in data: self.initial_preset = data['preset'].copy() if data and data.get('proxies'): self._set_nginx_v2_mode_flag(True) self._proxies = list(data.get('proxies', [])) else: self._proxies = None self._logger.debug('proxies: %s' % self._proxies) def accept(self, message, queue, behaviour=None, platform=None, os=None, dist=None): return (BEHAVIOUR in behaviour or 'nginx' in behaviour) and \ message.name in (Messages.HOST_UP, Messages.HOST_DOWN, Messages.BEFORE_HOST_TERMINATE, Messages.VHOST_RECONFIGURE, Messages.UPDATE_SERVICE_CONFIGURATION) def _set_nginx_v2_mode_flag(self, on): if on and not self._get_nginx_v2_mode_flag(): open(self._nginx_v2_flag_filepath, 'w').close() elif not on and self._get_nginx_v2_mode_flag(): os.remove(self._nginx_v2_flag_filepath) def _get_nginx_v2_mode_flag(self): return os.path.exists(self._nginx_v2_flag_filepath) def _recreate_compat_mode(self): self._logger.debug('Compatibility mode proxying recreation') roles_for_proxy = [] if __nginx__['upstream_app_role']: roles_for_proxy = [__nginx__['upstream_app_role']] else: roles_for_proxy = self.get_all_app_roles() self.api.fix_app_servers_inc() self.make_default_proxy(roles_for_proxy) https_inc_path = os.path.join(os.path.dirname(self.api.app_inc_path), 'https.include') nginx_dir = os.path.dirname(https_inc_path) for file_path in os.listdir(nginx_dir): if file_path.startswith('https.include'): self._logger.debug('Removing %s' % file_path) os.remove(file_path) def on_start(self): self._logger.debug('Handling on_start message') if __node__['state'] == 'running': role_params = self._queryenv.list_farm_role_params(__node__['farm_role_id'])['params'] nginx_params = role_params.get(BEHAVIOUR) v2_mode = (nginx_params and nginx_params.get('proxies')) \ or self._get_nginx_v2_mode_flag() self._logger.debug('Updating main config') self._update_main_config(remove_server_section=v2_mode, reload_service=False) if v2_mode: self._set_nginx_v2_mode_flag(True) proxies = nginx_params.get('proxies', []) if nginx_params else [] self._logger.debug('Recreating proxying with proxies:\n%s' % proxies) self.api.recreate_proxying(proxies) else: self._recreate_compat_mode() def on_before_host_up(self, message): self._logger.debug('Handling on_before_host_up message') log = bus.init_op.logger self._init_script.stop() log.info('Copy default html error pages') self._copy_error_pages() log.info('Setup proxying') self._logger.debug('Updating main config') v2_mode = bool(self._proxies) or self._get_nginx_v2_mode_flag() self._update_main_config(remove_server_section=v2_mode, reload_service=False) if v2_mode: self._logger.debug('Recreating proxying with proxies:\n%s' % self._proxies) self.api.recreate_proxying(self._proxies) else: # default behaviour roles_for_proxy = [] if __nginx__['upstream_app_role']: roles_for_proxy = [__nginx__['upstream_app_role']] else: roles_for_proxy = self.get_all_app_roles() self.make_default_proxy(roles_for_proxy) bus.fire('service_configured', service_name=SERVICE_NAME, preset=self.initial_preset) def on_HostUp(self, message): server = '' role_id = message.farm_role_id role_name = message.role_name behaviours = message.behaviour if message.cloud_location == __node__['cloud_location']: server = message.local_ip else: server = message.remote_ip self._logger.debug('on host up backend table is %s' % self.api.backend_table) # Assuming backend `backend` can be only in default behaviour mode if not self._get_nginx_v2_mode_flag(): self._recreate_compat_mode() # upstream_role = __nginx__['upstream_app_role'] # self._logger.debug('upstream app role is %s and server is up in role %s', # __nginx__['upstream_app_role'], # role_name) # if (upstream_role and upstream_role == role_name) or \ # (not upstream_role and BuiltinBehaviours.APP in behaviours): # for default_backend in ['backend', 'backend.ssl']: # if default_backend not in self.api.backend_table: # continue # server_list = [] # for dest in self.api.backend_table[default_backend]: # server_list.extend(dest['servers']) # if server in server_list: # continue # self.api.remove_server(default_backend, # '127.0.0.1', # reload_service=False, # update_backend_table=True) # self._logger.info('adding new app server %s to default backend', server) # self.api.add_server(default_backend, server, # update_backend_table=True) else: self._logger.info('adding new app server %s to role %s backend(s)', server, role_id) # self.api.add_server_to_role(server, role_id) role_params = self._queryenv.list_farm_role_params(__node__['farm_role_id'])['params'] nginx_params = role_params.get(BEHAVIOUR) proxies = nginx_params.get('proxies', []) if nginx_params else [] self._logger.debug('Recreating proxying with proxies:\n%s' % proxies) self.api.recreate_proxying(proxies) self._logger.info('After %s host up backend table is %s' % (server, self.api.backend_table)) def _remove_shut_down_server(self, server, role_id, role_name, behaviours, cache_remove=False): if server in self._terminating_servers: self._terminating_servers.remove(server) return self._logger.debug('on host down backend table is %s' % self.api.backend_table) self._logger.debug('removing server %s from backends' % server) # Assuming backend `backend` can be only in default behaviour mode if not self._get_nginx_v2_mode_flag(): self._recreate_compat_mode() # upstream_role = __nginx__['upstream_app_role'] # if (upstream_role and upstream_role == role_name) or \ # (not upstream_role and BuiltinBehaviours.APP in behaviours): # self._logger.info('removing server %s from default backend' % # server) # for default_backend in ['backend', 'backend.ssl']: # if default_backend not in self.api.backend_table: # continue # server_list = [] # for dest in self.api.backend_table[default_backend]: # server_list.extend(dest['servers']) # if server not in server_list: # continue # if len(server_list) == 1: # self._logger.debug('adding localhost to default backend') # self.api.add_server(default_backend, '127.0.0.1', # reload_service=False, # update_backend_table=True) # self._logger.info('Removing %s server from backend' % server) # self.api.remove_server(default_backend, server, # update_backend_table=True) else: # self._logger.info('removing server %s from role %s backend(s)', server, role_id) # self.api.remove_server_from_role(server, role_id) self._logger.info('adding new app server %s to role %s backend(s)', server, role_id) # self.api.add_server_to_role(server, role_id) role_params = self._queryenv.list_farm_role_params(__node__['farm_role_id'])['params'] nginx_params = role_params.get(BEHAVIOUR) proxies = nginx_params.get('proxies', []) if nginx_params else [] self._logger.debug('Recreating proxying with proxies:\n%s' % proxies) self.api.recreate_proxying(proxies) self._logger.debug('After %s host down backend table is %s' % (server, self.api.backend_table)) if cache_remove: self._terminating_servers.append(server) def on_HostDown(self, message): server = '' role_id = message.farm_role_id role_name = message.role_name behaviours = message.behaviour if message.cloud_location == __node__['cloud_location']: server = message.local_ip else: server = message.remote_ip self._remove_shut_down_server(server, role_id, role_name, behaviours) def on_BeforeHostTerminate(self, message): server = '' role_id = message.farm_role_id role_name = message.role_name behaviours = message.behaviour if message.cloud_location == __node__['cloud_location']: server = message.local_ip else: server = message.remote_ip self._remove_shut_down_server(server, role_id, role_name, behaviours, True) def on_VhostReconfigure(self, message): if not self._get_nginx_v2_mode_flag(): self._logger.debug('updating certificates') cert, key, cacert = self._queryenv.get_https_certificate() self.api.update_ssl_certificate('', cert, key, cacert) self._logger.debug('before vhost reconf backend table is %s' % self.api.backend_table) roles_for_proxy = [] if __nginx__['upstream_app_role']: roles_for_proxy = [__nginx__['upstream_app_role']] else: roles_for_proxy = self.get_all_app_roles() self.make_default_proxy(roles_for_proxy) self._logger.debug('after vhost reconf backend table is %s' % self.api.backend_table) def on_SSLCertificateUpdate(self, message): ssl_cert_id = message.id # TODO: check datastructure private_key = message.private_key certificate = message.certificate cacertificate = message.cacertificate self.api.update_ssl_certificate(ssl_cert_id, certificate, private_key, cacertificate) self.api._reload_service() def _copy_error_pages(self): pages_source = '/usr/share/scalr/nginx/html/' pages_destination = '/usr/share/nginx/html/' current_dir = '' for d in pages_destination.split(os.path.sep)[1:-1]: current_dir = current_dir + '/' + d if not os.path.exists(current_dir): os.makedirs(current_dir) if not os.path.exists(pages_destination + '500.html'): shutil.copy(pages_source + '500.html', pages_destination) if not os.path.exists(pages_destination + '502.html'): shutil.copy(pages_source + '502.html', pages_destination) if not os.path.exists(pages_destination + 'noapp.html'): shutil.copy(pages_source + 'noapp.html', pages_destination) def _https_config_exists(self): config_dir = os.path.dirname(self.api.app_inc_path) conf_path = os.path.join(config_dir, 'https.include') config = None try: config = Configuration('nginx') config.read(conf_path) except (Exception, BaseException), e: raise HandlerError('Cannot read/parse nginx main configuration file: %s' % str(e)) return config.get('server') != None
class NginxHandler(ServiceCtlHandler): def __init__(self): self._cnf = bus.cnf self._nginx_v2_flag_filepath = os.path.join(bus.etc_path, "private.d/nginx_v2") ServiceCtlHandler.__init__(self, BEHAVIOUR, initdv2.lookup('nginx'), NginxCnfController()) self._logger = logging.getLogger(__name__) self.preset_provider = NginxPresetProvider() self.api = NginxAPI() self._terminating_servers = [] bus.define_events("nginx_upstream_reload") bus.on(init=self.on_init, reload=self.on_reload) self.on_reload() def on_init(self): bus.on(start=self.on_start, before_host_up=self.on_before_host_up, host_init_response=self.on_host_init_response) self._insert_iptables_rules() if __node__['state'] == ScalarizrState.BOOTSTRAPPING: self._stop_service('Configuring') def on_reload(self): self._queryenv = bus.queryenv_service self._nginx_binary = __nginx__['binary_path'] self._app_inc_path = __nginx__['app_include_path'] self._app_port = __nginx__['app_port'] try: self._upstream_app_role = __nginx__['upstream_app_role'] except ConfigParser.Error: self._upstream_app_role = None def on_host_init_response(self, message): self._logger.debug('Handling on_host_init_response message') if hasattr(message, BEHAVIOUR): data = getattr(message, BEHAVIOUR) if not data and hasattr(message, 'nginx'): data = getattr(message, 'nginx') self._logger.debug('message data: %s' % data) if data and 'preset' in data: self.initial_preset = data['preset'].copy() if data and data.get('proxies'): self._set_nginx_v2_mode_flag(True) self._proxies = list(data.get('proxies', [])) else: self._proxies = None self._logger.debug('proxies: %s' % self._proxies) def accept(self, message, queue, behaviour=None, platform=None, os=None, dist=None): return (BEHAVIOUR in behaviour or 'nginx' in behaviour) and \ message.name in (Messages.HOST_UP, Messages.HOST_DOWN, Messages.BEFORE_HOST_TERMINATE, Messages.VHOST_RECONFIGURE, Messages.UPDATE_SERVICE_CONFIGURATION, Messages.SSL_CERTIFICATE_UPDATE) def _set_nginx_v2_mode_flag(self, on): if on and not self._get_nginx_v2_mode_flag(): open(self._nginx_v2_flag_filepath, 'w').close() elif not on and self._get_nginx_v2_mode_flag(): os.remove(self._nginx_v2_flag_filepath) def _get_nginx_v2_mode_flag(self): return os.path.exists(self._nginx_v2_flag_filepath) def on_start(self): self._logger.debug('Handling on_start message') if __node__['state'] == 'running': self.api.init_service() role_params = self._queryenv.list_farm_role_params( __node__['farm_role_id'])['params'] nginx_params = role_params.get(BEHAVIOUR) v2_mode = (nginx_params and nginx_params.get('proxies')) \ or self._get_nginx_v2_mode_flag() self._logger.debug('Updating main config') self.api._update_main_config(remove_server_section=v2_mode, reload_service=False) if v2_mode: self._set_nginx_v2_mode_flag(True) proxies = nginx_params.get('proxies', []) if nginx_params else [] self._logger.debug('Recreating proxying with proxies:\n%s' % proxies) self.api.recreate_proxying(proxies) else: self.api._recreate_compat_mode() def on_before_host_up(self, message): self._logger.debug('Handling on_before_host_up message') self.api.init_service() log = bus.init_op.logger self._init_script.stop() log.info('Copy default html error pages') self._copy_error_pages() log.info('Setup proxying') self._logger.debug('Updating main config') v2_mode = bool(self._proxies) or self._get_nginx_v2_mode_flag() self.api._update_main_config(remove_server_section=v2_mode, reload_service=False) if v2_mode: self._logger.debug('Recreating proxying with proxies:\n%s' % self._proxies) self.api.recreate_proxying(self._proxies) else: # default behaviour roles_for_proxy = [] if __nginx__['upstream_app_role']: roles_for_proxy = [__nginx__['upstream_app_role']] else: roles_for_proxy = get_all_app_roles() self.api.make_default_proxy(roles_for_proxy) bus.fire('service_configured', service_name=SERVICE_NAME, preset=self.initial_preset) def on_HostUp(self, message): server = '' role_id = message.farm_role_id role_name = message.role_name behaviours = message.behaviour if message.cloud_location == __node__['cloud_location']: server = message.local_ip else: server = message.remote_ip self._logger.debug('on host up backend table is %s' % self.api.backend_table) # Assuming backend `backend` can be only in default behaviour mode if not self._get_nginx_v2_mode_flag(): self.api._recreate_compat_mode() # upstream_role = __nginx__['upstream_app_role'] # self._logger.debug('upstream app role is %s and server is up in role %s', # __nginx__['upstream_app_role'], # role_name) # if (upstream_role and upstream_role == role_name) or \ # (not upstream_role and BuiltinBehaviours.APP in behaviours): # for default_backend in ['backend', 'backend.ssl']: # if default_backend not in self.api.backend_table: # continue # server_list = [] # for dest in self.api.backend_table[default_backend]: # server_list.extend(dest['servers']) # if server in server_list: # continue # self.api.remove_server(default_backend, # '127.0.0.1', # reload_service=False, # update_backend_table=True) # self._logger.info('adding new app server %s to default backend', server) # self.api.add_server(default_backend, server, # update_backend_table=True) else: self._logger.info('adding new app server %s to role %s backend(s)', server, role_id) # self.api.add_server_to_role(server, role_id) role_params = self._queryenv.list_farm_role_params( __node__['farm_role_id'])['params'] nginx_params = role_params.get(BEHAVIOUR) proxies = nginx_params.get('proxies', []) if nginx_params else [] self._logger.debug('Recreating proxying with proxies:\n%s' % proxies) self.api.recreate_proxying(proxies) self._logger.info('After %s host up backend table is %s' % (server, self.api.backend_table)) def _remove_shut_down_server(self, server, role_id, role_name, behaviours, cache_remove=False): if server in self._terminating_servers: self._terminating_servers.remove(server) return self._logger.debug('on host down backend table is %s' % self.api.backend_table) self._logger.debug('removing server %s from backends' % server) # Assuming backend `backend` can be only in default behaviour mode if not self._get_nginx_v2_mode_flag(): self.api._recreate_compat_mode() # upstream_role = __nginx__['upstream_app_role'] # if (upstream_role and upstream_role == role_name) or \ # (not upstream_role and BuiltinBehaviours.APP in behaviours): # self._logger.info('removing server %s from default backend' % # server) # for default_backend in ['backend', 'backend.ssl']: # if default_backend not in self.api.backend_table: # continue # server_list = [] # for dest in self.api.backend_table[default_backend]: # server_list.extend(dest['servers']) # if server not in server_list: # continue # if len(server_list) == 1: # self._logger.debug('adding localhost to default backend') # self.api.add_server(default_backend, '127.0.0.1', # reload_service=False, # update_backend_table=True) # self._logger.info('Removing %s server from backend' % server) # self.api.remove_server(default_backend, server, # update_backend_table=True) else: # self._logger.info('removing server %s from role %s backend(s)', server, role_id) # self.api.remove_server_from_role(server, role_id) # self._logger.info('adding new app server %s to role %s backend(s)', server, role_id) # self.api.add_server_to_role(server, role_id) role_params = self._queryenv.list_farm_role_params( __node__['farm_role_id'])['params'] nginx_params = role_params.get(BEHAVIOUR) proxies = nginx_params.get('proxies', []) if nginx_params else [] self._logger.debug('Recreating proxying with proxies:\n%s' % proxies) self.api.recreate_proxying(proxies) self._logger.debug('After %s host down backend table is %s' % (server, self.api.backend_table)) if cache_remove: self._terminating_servers.append(server) def on_HostDown(self, message): server = '' role_id = message.farm_role_id role_name = message.role_name behaviours = message.behaviour if message.cloud_location == __node__['cloud_location']: server = message.local_ip else: server = message.remote_ip self._remove_shut_down_server(server, role_id, role_name, behaviours) def on_BeforeHostTerminate(self, message): server = '' role_id = message.farm_role_id role_name = message.role_name behaviours = message.behaviour if message.cloud_location == __node__['cloud_location']: server = message.local_ip else: server = message.remote_ip self._remove_shut_down_server(server, role_id, role_name, behaviours, True) def on_VhostReconfigure(self, message): if not self._get_nginx_v2_mode_flag(): self._logger.debug('updating certificates') cert, key, cacert = self._queryenv.get_https_certificate() update_ssl_certificate('', cert, key, cacert) self._logger.debug('before vhost reconf backend table is %s' % self.api.backend_table) roles_for_proxy = [] if __nginx__['upstream_app_role']: roles_for_proxy = [__nginx__['upstream_app_role']] else: roles_for_proxy = get_all_app_roles() self.api.make_default_proxy(roles_for_proxy) self._logger.debug('after vhost reconf backend table is %s' % self.api.backend_table) def on_SSLCertificateUpdate(self, message): ssl_cert_id = message.body['id'] private_key = message.private_key certificate = message.certificate cacertificate = message.cacertificate update_ssl_certificate(ssl_cert_id, certificate, private_key, cacertificate) self.api._reload_service() def _copy_error_pages(self): pages_source = __node__['share_dir'] + '/nginx/html/' pages_destination = '/usr/share/nginx/html/' current_dir = '' for d in pages_destination.split(os.path.sep)[1:-1]: current_dir = current_dir + '/' + d if not os.path.exists(current_dir): os.makedirs(current_dir) if not os.path.exists(pages_destination + '500.html'): shutil.copy(pages_source + '500.html', pages_destination) if not os.path.exists(pages_destination + '502.html'): shutil.copy(pages_source + '502.html', pages_destination) if not os.path.exists(pages_destination + 'noapp.html'): shutil.copy(pages_source + 'noapp.html', pages_destination) def _https_config_exists(self): config_dir = os.path.dirname(self.api.app_inc_path) conf_path = os.path.join(config_dir, 'https.include') config = None try: config = Configuration('nginx') config.read(conf_path) except (Exception, BaseException), e: raise HandlerError( 'Cannot read/parse nginx main configuration file: %s' % str(e)) return config.get('server') != None