def run(self): _logger.debug('Service: setting signal handlers.') # Set SIGTERM signal Handler signal.signal(signal.SIGTERM, signal_term_handler) signal.signal(signal.SIGHUP, signal_hup_handler) _logger.info('Starting Silent Dune firewall.') # This loop allows for restarting and reloading the configuration after a SIGHUP signal has been received. while True: # Reset loop controllers self.stopProcessing = False self.reload = False # Read the local configuration file. self._config = ClientConfiguration( self._args.config).read_config() mods, pmanager, mqueue, cprocs, cqueues, mlist = self.startup_modules( ) # RUn main loop until we get an external signal. _logger.debug('Service: starting main processing loop.') while not self.stopProcessing: mods, mqueue, cprocs, cqueues = self.check_module_state( mods, mqueue, cprocs, cqueues, mlist) # Check manage queue for any QueueTask object. try: task = mqueue.get_nowait() _logger.debug( 'Service: forwarding task ({0}) from {1} to {2}'. format(task.get_task_id(), task.get_sender(), task.get_dest_name())) if task: # Find the destination module and send task to it. if not task.get_dest_name() or not cqueues[ task.get_dest_name()]: _logger.error( 'Service: task from {0} has unknown destination.' .format(task.get_sender())) cqueues[task.get_dest_name()].put(task) except: pass # Sleep. time.sleep(0.25) # Stop all module processing threads _logger.debug('Service: terminating active modules...') self.terminate_modules(mods, cprocs, cqueues) # If we are not reloading, just shutdown. if not self.reload: break _logger.debug('Service: reloading firewall.') _logger.info('Firewall shutdown complete.') # exit process sys.exit(0)
def run(): class SDCDaemon(Daemon): # Node configuration information _args = None _config = None stopProcessing = False reload = False t_start = time.time() t_mod_check = 0 def __init__(self, *args, **kwargs): self._args = kwargs.pop('args', None) super(SDCDaemon, self).__init__(*args, **kwargs) def startup_modules(self): # Get the path where this file is located. app_path = os.path.split(os.path.realpath(__file__))[0] # Get our package path and package name base_path, package_name = os.path.split(app_path) # Get loadable module list mods = modules.__load_modules__(base_path=base_path) active_mods = [] # List of modules marked as active. running_mods = [] # List of modules that are really running. # Set the configuration in each module. for mod in mods: mod.set_config( self._config ) # Set the configuration information in the module. # If the module is enabled, add it to the active_mods list. if mod.module_enabled(): active_mods.append(mod) else: _logger.debug('Service: module {0} is disabled.'.format( mod.get_name())) pmanager = Manager() mqueue = pmanager.Queue() # Keep the created child processes. cprocs = dict() # Dictionary of module process handlers. cqueues = dict() # Dictionary of module Queue objects. mlist = list() # List of module names. # Sort modules by the priority attribute so we can start them in the proper order. sorted_mods = sorted(active_mods, key=operator.attrgetter('priority')) for mod in sorted_mods: _logger.debug('Service: starting module {0}: ({1})'.format( mod.get_name(), mod.priority)) if mod.service_startup() is False: _logger.critical( 'Service: module ({0}) failed during startup.'.format( mod.get_name)) # sys.exit(1) continue name = mod.get_name() running_mods.append(mod) mlist.append(name) cprocs[ name] = None # Add a place holder for the module process. # Setup thread for modules wanting a processing thread. if mod.wants_processing_thread: # _logger.debug('Initializing thread for {0}.'.format(name)) cqueues[name] = multiprocessing.Queue() cprocs[name] = multiprocessing.Process( target=mod.process_handler, args=(cqueues[name], mqueue, mlist)) cprocs[name].start() # Give the firewall manager time to setup the initial rules. if name == 'SilentDuneClientFirewallModule': time.sleep(2) return running_mods, pmanager, mqueue, cprocs, cqueues, mlist def check_module_state(self, mods, mqueue, cprocs, cqueues, mlist, force=False): """ Check each module that has a thread and make sure it is still alive. :param mods: :return: False if all threads are running fine, True if failed module. """ # We only want to do a check once a minute. time_t = int((time.time() - self.t_start)) if (time_t > self.t_mod_check and time_t % 60.0 == 0.0) or force: self.t_mod_check = int((time.time() - self.t_start)) # Check to see that module process threads are still running. _logger.debug('Service: checking module threads.') for mod in mods: name = mod.get_name() _logger.debug( '{0}: checking module thread...'.format(name)) if name in cprocs and cprocs[name]: if cprocs[name].is_alive(): mod.restart_count = 0 else: # See if we should attempt to restart this module if mod.restart_count < 10: _logger.critical( 'service: {0} module has unexpectedly stopped.' .format(name)) mod.restart_count += 1 _logger.info( 'service: attempting to restart module {0} (rc:{1})' .format(name, mod.restart_count)) if mod.wants_processing_thread: # _logger.debug('Initializing thread for {0}.'.format(name)) cqueues[name] = multiprocessing.Queue() cprocs[name] = multiprocessing.Process( target=mod.process_handler, args=(cqueues[name], mqueue, mlist)) cprocs[name].start() else: if mod.restart_count == 10: _logger.warning( 'service: module restart limit exceeded for {0}, giving up.' .format(name, mod.restart_count)) mod.restart_count += 1 if mod.restart_count % 60 == 0: _logger.warning( 'service: module {0} is dead.'.format( name)) return mods, mqueue, cprocs, cqueues def terminate_modules(self, mods, cprocs, cqueues): """ Shutdown modules. """ for mod in mods: name = mod.get_name() if cprocs[name] and cprocs[name].is_alive(): _logger.debug( 'Service: signalling {0} module to stop processing.'. format(name)) cqueues[name].put( modules.QueueTask(modules.TASK_STOP_PROCESSING)) cqueues[name].close() cqueues[name].join_thread() cprocs[name].join() def run(self): _logger.debug('Service: setting signal handlers.') # Set SIGTERM signal Handler signal.signal(signal.SIGTERM, signal_term_handler) signal.signal(signal.SIGHUP, signal_hup_handler) _logger.info('Starting Silent Dune firewall.') # This loop allows for restarting and reloading the configuration after a SIGHUP signal has been received. while True: # Reset loop controllers self.stopProcessing = False self.reload = False # Read the local configuration file. self._config = ClientConfiguration( self._args.config).read_config() mods, pmanager, mqueue, cprocs, cqueues, mlist = self.startup_modules( ) # RUn main loop until we get an external signal. _logger.debug('Service: starting main processing loop.') while not self.stopProcessing: mods, mqueue, cprocs, cqueues = self.check_module_state( mods, mqueue, cprocs, cqueues, mlist) # Check manage queue for any QueueTask object. try: task = mqueue.get_nowait() _logger.debug( 'Service: forwarding task ({0}) from {1} to {2}'. format(task.get_task_id(), task.get_sender(), task.get_dest_name())) if task: # Find the destination module and send task to it. if not task.get_dest_name() or not cqueues[ task.get_dest_name()]: _logger.error( 'Service: task from {0} has unknown destination.' .format(task.get_sender())) cqueues[task.get_dest_name()].put(task) except: pass # Sleep. time.sleep(0.25) # Stop all module processing threads _logger.debug('Service: terminating active modules...') self.terminate_modules(mods, cprocs, cqueues) # If we are not reloading, just shutdown. if not self.reload: break _logger.debug('Service: reloading firewall.') _logger.info('Firewall shutdown complete.') # exit process sys.exit(0) def signal_term_handler(signal, frame): if not _daemon.stopProcessing: _logger.debug('Service: received SIGTERM signal.') _daemon.stopProcessing = True def signal_hup_handler(signal, frame): if not _daemon.reload: _logger.debug('Service: received SIGHUP signal.') _daemon.reload = True _daemon.stopProcessing = True setup_logging(_logger, '--debug' in sys.argv) os.environ['TMPDIR'] = '/var/run/silentdune' if not os.path.isdir(os.environ['TMPDIR']): os.makedirs(os.environ['TMPDIR']) # Setup i18n - Good for 2.x and 3.x python. kwargs = {} if sys.version_info[0] < 3: kwargs['unicode'] = True gettext.install('sdc_service', **kwargs) # Setup program arguments. parser = argparse.ArgumentParser(prog='sdc-firewall') parser.add_argument('-c', '--config', help=_('Use config file'), default=None, type=str) # noqa parser.add_argument('--debug', help=_('Enable debug output'), default=False, action='store_true') # noqa parser.add_argument('--nodaemon', help=_('Do not daemonize process'), default=False, action='store_true') # noqa parser.add_argument('action', choices=('start', 'stop', 'restart'), default='') args = parser.parse_args() if os.getuid() != 0: print('sdc-firewall: error: must be run as root') sys.exit(4) # --nodaemon only valid with start action if args.nodaemon and args.action != 'start': print( 'sdc-firewall: error: --nodaemon option not valid with stop or restart action' ) sys.exit(1) # Read the local configuration file. config = ClientConfiguration(args.config).read_config() # Dump debug information if args.debug: node_info_dump(args) if not config: _logger.error('Invalid configuration file information, aborting.') sys.exit(1) # Do not fork the daemon process, run in foreground. For systemd service or debugging. if args.nodaemon: _daemon = SDCDaemon(args=args) _daemon.run() else: # Setup daemon object _daemon = SDCDaemon(os.path.split(config.get('settings', 'pidfile'))[0], '0o700', os.path.split(config.get('settings', 'pidfile'))[1], 'root', 'root', '/dev/null', '/dev/null', '/dev/null', args=args) if args.action == 'start': _logger.debug('Starting daemon.') _daemon.start() elif args.action == 'stop': _logger.debug('Stopping daemon.') _daemon.stop() elif args.action == 'restart': _logger.debug('Restarting daemon.') _daemon.restart() return 0
def __init__(self, args, modules, node_info): self.__modules = modules self.args = args self.node_info = node_info self.__config = ClientConfiguration()
def run(): class SDCDaemon(Daemon): # Node configuration information _args = None _config = None stopProcessing = False reload = False t_start = time.time() t_mod_check = 0 def __init__(self, *args, **kwargs): self._args = kwargs.pop('args', None) super(SDCDaemon, self).__init__(*args, **kwargs) def startup_modules(self): # Get the path where this file is located. app_path = os.path.split(os.path.realpath(__file__))[0] # Get our package path and package name base_path, package_name = os.path.split(app_path) # Get loadable module list mods = modules.__load_modules__(base_path=base_path) # Have each module do their startup work now. for mod in mods: mod.set_config(self._config) # Set the configuration information in the module. result = mod.service_startup() if result is not None and result is False: _logger.critical('Module ({0}) failed during startup.'.format(mod.get_name)) sys.exit(1) pmanager = Manager() mqueue = pmanager.Queue() # Keep the created child processes. cprocs = dict() # Dictionary of module process handlers. cqueues = dict() # Dictionary of module Queue objects. mlist = list() # List of module names. # Get list of module names for mod in mods: mlist.append(mod.get_name()) # Setup thread for modules wanting a processing thread. for mod in mods: name = mod.get_name() cprocs[name] = None # Add a place holder for the module process if mod.wants_processing_thread: _logger.debug('Initializing thread for {0}.'.format(name)) cqueues[name] = multiprocessing.Queue() cprocs[name] = multiprocessing.Process( target=mod.process_handler, args=(cqueues[name], mqueue, mlist)) cprocs[name].start() return mods, pmanager, mqueue, cprocs, cqueues, mlist def check_module_state(self, mods, cprocs, force=False): """ Check each module that has a thread and make sure it is still alive. :param mods: :return: False if all threads are running fine, True if failed module. """ # We only want to do a check once a minute. time_t = int((time.time() - self.t_start)) if (time_t > self.t_mod_check and time_t % 60.0 == 0.0) or force: self.t_mod_check = int((time.time() - self.t_start)) # Check to see that module process threads are still running. _logger.debug('Checking module threads.') for mod in mods: if mod.get_name() in cprocs and cprocs[mod.get_name()]: if not cprocs[mod.get_name()].is_alive(): # TODO: Maybe restart the module? _logger.critical('{0} module has unexpectedly stopped.'.format(mod.get_name())) return True return False def terminate_modules(self, mods, cprocs, cqueues): """ Shutdown modules. """ for mod in mods: name = mod.get_name() if cprocs[name] and cprocs[name].is_alive(): _logger.debug('Signalling {0} module to stop processing.'.format(name)) cqueues[name].put(modules.QueueTask(modules.TASK_STOP_PROCESSING)) cqueues[name].close() cqueues[name].join_thread() cprocs[name].join() def run(self): _logger.debug('Setting signal handlers.') # Set SIGTERM signal Handler signal.signal(signal.SIGTERM, signal_term_handler) signal.signal(signal.SIGHUP, signal_hup_handler) _logger.info('Starting firewall service.') # This loop allows for restarting and reloading the configuration after a SIGHUP signal has been received. while True: # Reset loop controllers self.stopProcessing = False self.reload = False # Read the local configuration file. self._config = ClientConfiguration(self._args.config).read_config() mods, pmanager, mqueue, cprocs, cqueues, mlist = self.startup_modules() # RUn main loop until we get an external signal. _logger.debug('Starting main processing loop.') while not self.stopProcessing: if self.check_module_state(mods, cprocs): self.stopProcessing = True break # Check manage queue for any QueueTask object. try: task = mqueue.get_nowait() _logger.debug('Forwarding task ({0}) from {1} to {2}'.format( task.get_task_id(), task.get_sender(), task.get_dest_name())) if task: # Find the destination module and send task to it. if not task.get_dest_name() or not cqueues[task.get_dest_name()]: _logger.error('Task from {0} has unknown destination.'.format(task.get_sender())) cqueues[task.get_dest_name()].put(task) except: pass # Sleep. time.sleep(0.25) # Stop all module processing threads _logger.debug('Shutting firewall service down.') self.terminate_modules(mods, cprocs, cqueues) # If we are not reloading, just shutdown. if not self.reload: break _logger.debug('Reloading firewall.') _logger.info('Firewall shutdown complete.') # exit process sys.exit(0) def signal_term_handler(signal, frame): if not _daemon.stopProcessing: _logger.debug('Received SIGTERM signal.') _daemon.stopProcessing = True def signal_hup_handler(signal, frame): if not _daemon.reload: _logger.debug('Received SIGHUP signal.') _daemon.reload = True _daemon.stopProcessing = True _logger.addHandler(setup_logging('--debug' in sys.argv)) # Setup i18n - Good for 2.x and 3.x python. kwargs = {} if sys.version_info[0] < 3: kwargs['unicode'] = True gettext.install('sdc_service', **kwargs) # Setup program arguments. parser = argparse.ArgumentParser(prog='sdc-firewall') parser.add_argument('-c', '--config', help=_('Use config file'), default=None, type=str) # noqa parser.add_argument('--debug', help=_('Enable debug output'), default=False, action='store_true') # noqa parser.add_argument('--nodaemon', help=_('Do not daemonize process'), default=False, action='store_true') # noqa parser.add_argument('action', choices=('start', 'stop', 'restart'), default='') args = parser.parse_args() if os.getuid() != 0: print('sdc-firewall: error: must be run as root') sys.exit(4) # --nodaemon only valid with start action if args.nodaemon and args.action != 'start': print('sdc-firewall: error: --nodaemon option not valid with stop or restart action') sys.exit(1) # Read the local configuration file. config = ClientConfiguration(args.config).read_config() # Dump debug information if args.debug: node_info_dump(args) if not config: _logger.error('Invalid configuration file information, aborting.') sys.exit(1) # Do not fork the daemon process, run in foreground. For systemd service or debugging. if args.nodaemon: _daemon = SDCDaemon(args=args) _daemon.run() else: # Setup daemon object _daemon = SDCDaemon( os.path.split(config.get('settings', 'pidfile'))[0], '0o700', os.path.split(config.get('settings', 'pidfile'))[1], config.get('settings', 'user'), config.get('settings', 'group'), '/dev/null', config.get('settings', 'logfile'), '/dev/null', args=args ) if args.action == 'start': _logger.debug('Starting daemon.') _daemon.start() elif args.action == 'stop': _logger.debug('Stopping daemon.') _daemon.stop() elif args.action == 'restart': _logger.debug('Restarting daemon.') _daemon.restart() return 0
class Installer(ConsoleBase): # Modules dictionary list __modules = None __config = None # parser args args = None bad_arg = False node_info = None previous_firewall_service = None # Location of the installed service unit or script file. service_out_file = None def __init__(self, args, modules, node_info): self.__modules = modules self.args = args self.node_info = node_info self.__config = ClientConfiguration() def write_config(self): """ Loop through the modules to set their configuration file items and then save the configuration. """ for mod in self.__modules: result = mod.prepare_config(self.__config) if result is False: # If prepare_config() returns None, we just want to continue. _logger.error( 'Preparing configuration file items failed in module {0}.'. format(mod.get_name())) return False # Write the configuration file out. return self.__config.write_config() def install_service(self): """ Based on everything we know, lets install the init service. :return: True if successful, otherwise False. """ self.cwrite('Installing firewall service...') # Figure out our path base_path = os.path.split(os.path.realpath(__file__))[0] systemd_in_file = os.path.join(base_path, 'init/sdc-firewall.service.in') init_in_file = os.path.join(base_path, 'init/sdc-firewall.init.in') # Check and make sure we can find the init scripts. if not os.path.exists(systemd_in_file) or \ not os.path.exists(init_in_file): _logger.critical('Unable to find init service files.') return False firewall_exec = which('sdc-firewall') if not firewall_exec: self.cwriteline('[Error]', 'Unable to locate our firewall executable.') return False # Install systemd service file. if self.node_info.sysd_installed: path = None # TODO: Need to look for selinux and apply a service policy module before saving to system locations. # # # Determine systemd service unit install directory. # if os.path.exists('/usr/lib/systemd/system/'): # Redhat based # path = '/usr/lib/systemd/system/' # elif os.path.exists('/lib/systemd/system/'): # Ubuntu based # path = '/lib/systemd/system/' # elif os.path.exists('/etc/systemd/system/'): # Last resort location # path = '/etc/systemd/system/' # Just save to the systemd user defined location until we get a selinux serivce policy built. if os.path.exists('/etc/systemd/system/'): path = '/etc/systemd/system/' if not path: self.cwriteline('[Error]', 'Unable to locate systemd service unit path.') return False self.service_out_file = os.path.join(path, 'sdc-firewall.service') # shutil.copy(systemd_in_file, self.service_out_file) # Replace key words with local file locations. sed_args = 's/%%KILL%%/{0}/g;s/%%SDC-FIREWALL%%/{1}/g'.format( self.node_info.kill.replace('/', '\/'), firewall_exec.replace('/', '\/')) args = [self.node_info.sed, sed_args, systemd_in_file] try: _logger.debug('Saving systemd service file to {0}'.format( self.service_out_file)) with open(self.service_out_file, 'w') as handle: subprocess.call(args, stdout=handle) except CalledProcessError: _logger.error( 'Unable to copy systemd service file to system location.') return False # Set file permissions. os.chmod(self.service_out_file, 0o644) # Enable and start service if not self.node_info.enable_service('sdc-firewall'): self.cwriteline('[Error]', 'Firewall service failed to enable.') return False if not self.node_info.start_service('sdc-firewall'): self.cwriteline('[Error]', 'Firewall service failed to start.') return False if self.node_info.sysv_installed: # TODO: Write the sysv service install code. # Just save to the systemd user defined location until we get a selinux serivce policy built. if os.path.exists('/etc/systemd/system/'): path = '/etc/systemd/system/' pass # http://askubuntu.com/questions/2263/chkconfig-alternative-for-ubuntu-server self.cwriteline('[OK]', 'Firewall service installed and started.') return True def remove_service(self): # Remove the systemd service file. if self.node_info.sysd_installed: if self.node_info.is_service_running('sdc-firewall'): if not self.node_info.stop_service('sdc-firewall'): _logger.debug('Firewall service failed to stop.') if not self.node_info.disable_service('sdc-firewall'): _logger.debug('Unable to disable firewall service.') if os.path.exists(self.service_out_file): os.remove(self.service_out_file) if self.node_info.sysv_installed: # TODO: Write the sysv service removal code. pass self.cwriteline('[OK]', 'Firewall service removed.') def disable_previous_firewall(self): """ Disable the previous firewall service. :return: True if successful, otherwise False. """ if not self.node_info.previous_firewall_service: return True # Check to see if the previous firewall service is running. if not is_process_running(self.node_info.previous_firewall_service): _logger.info( 'The current firewall service does not seem to be running.') return True self.cwrite('Stopping the current firewall service...') # Stop and Disable the previous firewall service. if not self.node_info.stop_service( self.node_info.previous_firewall_service): self.cwriteline('[Error]', 'Unable to stop the current firewall service.') return False self.cwriteline('[OK]', 'Successfully stopped the current firewall service.') self.cwrite('Disabling the current firewall service...') if not self.node_info.disable_service( self.node_info.previous_firewall_service): self.cwriteline('[Error]', 'Unable to disable the current firewall service.') return False self.cwriteline('[OK]', 'Successfully disabled the current firewall service.') return True def clean_up(self): """ Use this method to clean up after a failed install """ self.cwrite('Cleaning up...') return # The following code can only run if we are running under privileged account. if self.node_info.root_user: # Remove our firewall service. self.remove_service() # Remove the directories the daemon process uses. self.__config.delete_directories() _logger.debug('Removed daemon process directories.') # Remove the system user the daemon process uses. self.__config.delete_user() _logger.debug('Removed daemon process system user.') # Check to see if the previous firewall service is running or not if self.node_info.previous_firewall_service: if not is_process_running( self.node_info.previous_firewall_service): self.node_info.enable_service( self.node_info.previous_firewall_service) self.node_info.start_service( self.node_info.previous_firewall_service) # if we are running as root, delete the configuration directory if self.node_info.config_root is not None \ and os.path.exists(self.node_info.config_root) \ and os.path.realpath(self.node_info.config_root) != '/': rmdir(self.node_info.config_root) self.cwriteline('[OK]', 'Finished cleaning up.') def start_install(self): """ Begin installing the Silent Dune Client. """ # If this node is running systemd, remove the pidfile setting. if self.node_info.sysd_installed: self.__config.delete('settings', 'pidfile') # Check to see that the NodeInformation information gathering was successful. if self.node_info.error: _logger.error('Gathering information about this node failed.') return False # See if we haven't determined the configuration root directory. if not self.node_info.config_root: _logger.error( 'Error determining the configuration root directory.') return False if self.node_info.previous_firewall_service == 'sdc-firewall': self.cwriteline( '[Error]', 'Silent Dune firewall service is already running, please uninstall first.' ) return False # # Have each module do their pre install work now. # for mod in self.__modules: result = mod.pre_install() if result is not None and result is False: return False # The following code can only run if we are running under privileged account. if self.node_info.root_user: # # Create the daemon process user # if not self.__config.create_service_user(): # return False # Create the directories the daemon process uses. if not self.__config.create_directories(): return False # # Have each module do their install work now. # for mod in self.__modules: result = mod.install_module() if result is not None and result is False: return False # The following code can only run if we are running under privileged account. if self.node_info.root_user: # Disable the current firewall service if self.node_info.previous_firewall_service: if not self.disable_previous_firewall(): return False if not self.write_config(): return False # Have each module do their post install work now. for mod in self.__modules: result = mod.post_install() if result is not None and result is False: return False # Finally install and start the firewalls service. if self.node_info.root_user: if not self.install_service(): return False return True
class Installer(ConsoleBase): # Modules dictionary list __modules = None __config = None # parser args args = None bad_arg = False node_info = None previous_firewall_service = None # Location of the installed service unit or script file. service_out_file = None def __init__(self, args, modules, node_info): self.__modules = modules self.args = args self.node_info = node_info self.__config = ClientConfiguration() def write_config(self): """ Loop through the modules to set their configuration file items and then save the configuration. """ for mod in self.__modules: result = mod.prepare_config(self.__config) if result is False: # If prepare_config() returns None, we just want to continue. _logger.error('Preparing configuration file items failed in module {0}.'.format(mod.get_name())) return False # Write the configuration file out. return self.__config.write_config() def install_service(self): """ Based on everything we know, lets install the init service. :return: True if successful, otherwise False. """ self.cwrite('Configuring Silent Dune firewall service...') # Figure out our path base_path = os.path.split(os.path.realpath(__file__))[0] systemd_in_file = os.path.join(base_path, 'init/sdc-firewall.systemd.in') init_in_file = os.path.join(base_path, 'init/sdc-firewall.sysv.in') # Check and make sure we can find the init scripts. if not os.path.exists(systemd_in_file) or \ not os.path.exists(init_in_file): _logger.critical('Unable to find init service files.') return False firewall_exec = which('sdc-firewall') if not firewall_exec: self.cwriteline('[Error]', 'Unable to locate our firewall executable.') return False # Install systemd service file. if self.node_info.sysd_installed: path = None # Determine systemd service unit install directory. if os.path.exists('/usr/lib/systemd/system/'): # Redhat based path = '/usr/lib/systemd/system/' elif os.path.exists('/lib/systemd/system/'): # Ubuntu based path = '/lib/systemd/system/' elif os.path.exists('/etc/systemd/system/'): # Last resort location path = '/etc/systemd/system/' if not path: self.cwriteline('[Error]', 'Unable to locate systemd service unit path.') return False self.service_out_file = os.path.join(path, 'sdc-firewall.service') # See if we need to copy the service unit file to the destination if not os.path.isfile(self.service_out_file): shutil.copy(systemd_in_file, self.service_out_file) os.chmod(self.service_out_file, 0o644) if self.node_info.sysv_installed: # http://askubuntu.com/questions/2263/chkconfig-alternative-for-ubuntu-server path = '/etc/init.d/' self.service_out_file = os.path.join(path, 'sdc-firewall') # See if we need to copy the service unit file to the destination if not os.path.isfile(self.service_out_file): shutil.copy(init_in_file, self.service_out_file) os.chmod(self.service_out_file, 0o755) # Enable service # if not self.node_info.enable_service('sdc-firewall'): # self.cwriteline('[Error]', 'Firewall service failed to enable.') # return False # Start service # if not self.node_info.start_service('sdc-firewall'): # self.cwriteline('[Error]', 'Firewall service failed to start.') # return False self.cwriteline(' [OK]', 'Firewall service installed. Please start "sdc-firewall" service now.') return True def remove_service(self): # Remove the systemd service file. if self.node_info.sysd_installed: if is_service_running('sdc-firewall'): if not self.node_info.stop_service('sdc-firewall'): _logger.debug('Firewall service failed to stop.') if not self.node_info.disable_service('sdc-firewall'): _logger.debug('Unable to disable firewall service.') if os.path.exists(self.service_out_file): os.remove(self.service_out_file) if self.node_info.sysv_installed: # TODO: Write the sysv service removal code. pass self.cwriteline('[OK]', 'Firewall service removed.') def disable_previous_firewall(self): """ Disable the previous firewall service. :return: True if successful, otherwise False. """ if not self.node_info.previous_firewall_service or self.node_info.previous_firewall_service == 'sdc-firewall': return True # Check to see if the previous firewall service is running. if not is_service_running(self.node_info.previous_firewall_service): _logger.info('The current firewall service does not seem to be running.') return True self.cwrite('Stopping the current firewall service...') # Stop and Disable the previous firewall service. if not self.node_info.stop_service(self.node_info.previous_firewall_service): self.cwriteline('[Error]', 'Unable to stop the current firewall service.') return False self.cwriteline('[OK]', 'Successfully stopped the current firewall service.') self.cwrite('Disabling the current firewall service...') if not self.node_info.disable_service(self.node_info.previous_firewall_service): self.cwriteline('[Error]', 'Unable to disable the current firewall service.') return False self.cwriteline('[OK]', 'Successfully disabled the current firewall service.') return True def clean_up(self): """ Use this method to clean up after a failed install """ self.cwrite('Cleaning up...') # # The following code can only run if we are running under privileged account. # if self.node_info.root_user: # # # Remove our firewall service. # self.remove_service() # # # Remove the directories the daemon process uses. # self.__config.delete_directories() # _logger.debug('Removed daemon process directories.') # # # Remove the system user the daemon process uses. # self.__config.delete_user() # _logger.debug('Removed daemon process system user.') # # # Check to see if the previous firewall service is running or not # if self.node_info.previous_firewall_service: # if not is_service_running(self.node_info.previous_firewall_service): # self.node_info.enable_service(self.node_info.previous_firewall_service) # self.node_info.start_service(self.node_info.previous_firewall_service) # # # if we are running as root, delete the configuration directory # if self.node_info.config_root is not None \ # and os.path.exists(self.node_info.config_root) \ # and os.path.realpath(self.node_info.config_root) != '/': # rmdir(self.node_info.config_root) self.cwriteline('[OK]', 'Finished cleaning up.') def start_install(self): """ Begin installing the Silent Dune Client. """ # If this node is running systemd, remove the pidfile setting. if self.node_info.sysd_installed: self.__config.delete('settings', 'pidfile') # Check to see that the NodeInformation information gathering was successful. if self.node_info.error: _logger.error('Gathering information about this node failed.') return False # See if we haven't determined the configuration root directory. if not self.node_info.config_root: _logger.error('Error determining the configuration root directory.') return False # if self.node_info.previous_firewall_service == 'sdc-firewall': # self.cwriteline('[Error]', 'Silent Dune firewall service is already running, please uninstall first.') # return False # # Have each module do their pre install work now. # for mod in self.__modules: result = mod.pre_install() if result is not None and result is False: return False # The following code can only run if we are running under privileged account. if self.node_info.root_user: # # Create the daemon process user # if not self.__config.create_service_user(): # return False # Create the directories the daemon process uses. if not self.__config.create_directories(): return False # # Have each module do their install work now. # for mod in self.__modules: result = mod.install_module() if result is not None and result is False: return False # The following code can only run if we are running under privileged account. if self.node_info.root_user: # Disable the current firewall service if self.node_info.previous_firewall_service: if not self.disable_previous_firewall(): return False if not self.write_config(): return False # Have each module do their post install work now. for mod in self.__modules: result = mod.post_install() if result is not None and result is False: return False # Finally install the firewall service. if self.node_info.root_user: if not self.install_service(): return False self.node_info.restorecon('/etc/silentdune') if not os.path.isdir('/var/run/silentdune'): os.makedirs('/var/run/silentdune') self.node_info.restorecon('/var/run/silentdune') return True
class Installer(ConsoleBase): # Modules dictionary list __modules = None __config = None # parser args args = None bad_arg = False node_info = None previous_firewall_service = None # Location of the installed service unit or script file. service_out_file = None def __init__(self, args, modules, node_info): self.__modules = modules self.args = args self.node_info = node_info self.__config = ClientConfiguration() def write_config(self): """ Loop through the modules to set their configuration file items and then save the configuration. """ for mod in self.__modules: result = mod.prepare_config(self.__config) if result is False: # If prepare_config() returns None, we just want to continue. _logger.error('Preparing configuration file items failed in module {0}.'.format(mod.get_name())) return False # Write the configuration file out. return self.__config.write_config() def install_service(self): """ Based on everything we know, lets install the init service. :return: True if successful, otherwise False. """ self.cwrite('Installing firewall service...') # Figure out our path base_path = os.path.split(os.path.realpath(__file__))[0] systemd_in_file = os.path.join(base_path, 'init/sdc-firewall.service.in') init_in_file = os.path.join(base_path, 'init/sdc-firewall.init.in') # Check and make sure we can find the init scripts. if not os.path.exists(systemd_in_file) or \ not os.path.exists(init_in_file): _logger.critical('Unable to find init service files.') return False firewall_exec = which('sdc-firewall') if not firewall_exec: self.cwriteline('[Error]', 'Unable to locate our firewall executable.') return False # Install systemd service file. if self.node_info.sysd_installed: path = None # TODO: Need to look for selinux and apply a service policy module before saving to system locations. # # # Determine systemd service unit install directory. # if os.path.exists('/usr/lib/systemd/system/'): # Redhat based # path = '/usr/lib/systemd/system/' # elif os.path.exists('/lib/systemd/system/'): # Ubuntu based # path = '/lib/systemd/system/' # elif os.path.exists('/etc/systemd/system/'): # Last resort location # path = '/etc/systemd/system/' # Just save to the systemd user defined location until we get a selinux serivce policy built. if os.path.exists('/etc/systemd/system/'): path = '/etc/systemd/system/' if not path: self.cwriteline('[Error]', 'Unable to locate systemd service unit path.') return False self.service_out_file = os.path.join(path, 'sdc-firewall.service') # shutil.copy(systemd_in_file, self.service_out_file) # Replace key words with local file locations. sed_args = 's/%%KILL%%/{0}/g;s/%%SDC-FIREWALL%%/{1}/g'.format( self.node_info.kill.replace('/', '\/'), firewall_exec.replace('/', '\/') ) args = [self.node_info.sed, sed_args, systemd_in_file] try: _logger.debug('Saving systemd service file to {0}'.format(self.service_out_file)) with open(self.service_out_file, 'w') as handle: subprocess.call(args, stdout=handle) except CalledProcessError: _logger.error('Unable to copy systemd service file to system location.') return False # Set file permissions. os.chmod(self.service_out_file, 0o644) # Enable and start service if not self.node_info.enable_service('sdc-firewall'): self.cwriteline('[Error]', 'Firewall service failed to enable.') return False if not self.node_info.start_service('sdc-firewall'): self.cwriteline('[Error]', 'Firewall service failed to start.') return False if self.node_info.sysv_installed: # TODO: Write the sysv service install code. # Just save to the systemd user defined location until we get a selinux serivce policy built. if os.path.exists('/etc/systemd/system/'): path = '/etc/systemd/system/' pass # http://askubuntu.com/questions/2263/chkconfig-alternative-for-ubuntu-server self.cwriteline('[OK]', 'Firewall service installed and started.') return True def remove_service(self): # Remove the systemd service file. if self.node_info.sysd_installed: if self.node_info.is_service_running('sdc-firewall'): if not self.node_info.stop_service('sdc-firewall'): _logger.debug('Firewall service failed to stop.') if not self.node_info.disable_service('sdc-firewall'): _logger.debug('Unable to disable firewall service.') if os.path.exists(self.service_out_file): os.remove(self.service_out_file) if self.node_info.sysv_installed: # TODO: Write the sysv service removal code. pass self.cwriteline('[OK]', 'Firewall service removed.') def disable_previous_firewall(self): """ Disable the previous firewall service. :return: True if successful, otherwise False. """ if not self.node_info.previous_firewall_service: return True # Check to see if the previous firewall service is running. if not is_process_running(self.node_info.previous_firewall_service): _logger.info('The current firewall service does not seem to be running.') return True self.cwrite('Stopping the current firewall service...') # Stop and Disable the previous firewall service. if not self.node_info.stop_service(self.node_info.previous_firewall_service): self.cwriteline('[Error]', 'Unable to stop the current firewall service.') return False self.cwriteline('[OK]', 'Successfully stopped the current firewall service.') self.cwrite('Disabling the current firewall service...') if not self.node_info.disable_service(self.node_info.previous_firewall_service): self.cwriteline('[Error]', 'Unable to disable the current firewall service.') return False self.cwriteline('[OK]', 'Successfully disabled the current firewall service.') return True def clean_up(self): """ Use this method to clean up after a failed install """ self.cwrite('Cleaning up...') return # The following code can only run if we are running under privileged account. if self.node_info.root_user: # Remove our firewall service. self.remove_service() # Remove the directories the daemon process uses. self.__config.delete_directories() _logger.debug('Removed daemon process directories.') # Remove the system user the daemon process uses. self.__config.delete_user() _logger.debug('Removed daemon process system user.') # Check to see if the previous firewall service is running or not if self.node_info.previous_firewall_service: if not is_process_running(self.node_info.previous_firewall_service): self.node_info.enable_service(self.node_info.previous_firewall_service) self.node_info.start_service(self.node_info.previous_firewall_service) # if we are running as root, delete the configuration directory if self.node_info.config_root is not None \ and os.path.exists(self.node_info.config_root) \ and os.path.realpath(self.node_info.config_root) != '/': rmdir(self.node_info.config_root) self.cwriteline('[OK]', 'Finished cleaning up.') def start_install(self): """ Begin installing the Silent Dune Client. """ # If this node is running systemd, remove the pidfile setting. if self.node_info.sysd_installed: self.__config.delete('settings', 'pidfile') # Check to see that the NodeInformation information gathering was successful. if self.node_info.error: _logger.error('Gathering information about this node failed.') return False # See if we haven't determined the configuration root directory. if not self.node_info.config_root: _logger.error('Error determining the configuration root directory.') return False if self.node_info.previous_firewall_service == 'sdc-firewall': self.cwriteline('[Error]', 'Silent Dune firewall service is already running, please uninstall first.') return False # # Have each module do their pre install work now. # for mod in self.__modules: result = mod.pre_install() if result is not None and result is False: return False # The following code can only run if we are running under privileged account. if self.node_info.root_user: # # Create the daemon process user # if not self.__config.create_service_user(): # return False # Create the directories the daemon process uses. if not self.__config.create_directories(): return False # # Have each module do their install work now. # for mod in self.__modules: result = mod.install_module() if result is not None and result is False: return False # The following code can only run if we are running under privileged account. if self.node_info.root_user: # Disable the current firewall service if self.node_info.previous_firewall_service: if not self.disable_previous_firewall(): return False if not self.write_config(): return False # Have each module do their post install work now. for mod in self.__modules: result = mod.post_install() if result is not None and result is False: return False # Finally install and start the firewalls service. if self.node_info.root_user: if not self.install_service(): return False return True