class PluginHandler: def __init__(self): self._plugin_manager = PluginManager() self._category_active = {"Modifier": False, "Analyzer": False, "Comparator": False} self._plugin_from_category = {"Modifier": [], "Analyzer": [], "Comparator": []} self._modifier_plugins = [] self._analyzer_plugins = [] self._collect_all_plugins() def _collect_all_plugins(self): self._plugin_manager.setPluginPlaces( ["hugin/analyze/modifier", "hugin/analyze/analyzer", "hugin/analyze/comparator"] ) # setting filter categories for pluginmanager self._plugin_manager.setCategoriesFilter( { # movie metadata provider "Modifier": IModifier, # movie metadata provider "Comparator": IComparator, # sub metadata provider "Analyzer": IAnalyzer, } ) self._plugin_manager.collectPlugins() def activate_plugins_by_category(self, category): self._toggle_activate_plugins_by_category(category) def deactivate_plugins_by_category(self, category): self._toggle_activate_plugins_by_category(category) def _toggle_activate_plugins_by_category(self, category): plugins = self._plugin_manager.getPluginsOfCategory(category) is_active = self._category_active[category] for pluginInfo in plugins: if is_active: self._plugin_manager.deactivatePluginByName(name=pluginInfo.name, category=category) self._plugin_from_category[category].remove(pluginInfo) else: self._plugin_manager.activatePluginByName(name=pluginInfo.name, category=category) self._plugin_from_category[category].append(pluginInfo) self._category_active[category] = not is_active def get_plugins_from_category(self, category): plugins = [] for plugin in self._plugin_from_category[category]: plugin.plugin_object.name = plugin.name plugin.plugin_object.description = plugin.description plugins.append(plugin.plugin_object) return plugins def is_activated(self, category): """ True if category is activated. """ return self._category_active[category]
class SimpleTestsCase(unittest.TestCase): """ Test the correct loading of a simple plugin as well as basic commands. """ def setUp(self): """ init """ # create the plugin manager self.simplePluginManager = PluginManager(directories_list=[ os.path.join( os.path.dirname(os.path.abspath(__file__)),"plugins")]) # load the plugins that may be found self.simplePluginManager.collectPlugins() # Will be used later self.plugin_info = None def plugin_loading_check(self): """ Test if the correct plugin has been loaded. """ if self.plugin_info is None: # check nb of categories self.assertEqual(len(self.simplePluginManager.getCategories()),1) sole_category = self.simplePluginManager.getCategories()[0] # check the number of plugins self.assertEqual(len(self.simplePluginManager.getPluginsOfCategory(sole_category)),1) self.plugin_info = self.simplePluginManager.getPluginsOfCategory(sole_category)[0] # test that the name of the plugin has been correctly defined self.assertEqual(self.plugin_info.name,"Simple Plugin") self.assertEqual(sole_category,self.plugin_info.category) else: self.assert_(True) def testLoaded(self): """ Test if the correct plugin has been loaded. """ self.plugin_loading_check() def testGetAll(self): """ Test if the correct plugin has been loaded. """ self.plugin_loading_check() self.assertEqual(len(self.simplePluginManager.getAllPlugins()),1) self.assertEqual(self.simplePluginManager.getAllPlugins()[0],self.plugin_info) def testActivationAndDeactivation(self): """ Test if the activation procedure works. """ self.plugin_loading_check() self.assert_(not self.plugin_info.plugin_object.is_activated) self.simplePluginManager.activatePluginByName(self.plugin_info.name, self.plugin_info.category) self.assert_(self.plugin_info.plugin_object.is_activated) self.simplePluginManager.deactivatePluginByName(self.plugin_info.name, self.plugin_info.category) self.assert_(not self.plugin_info.plugin_object.is_activated)
class SimpleTestsCase(unittest.TestCase): """ Test the correct loading of a simple plugin as well as basic commands. """ def setUp(self): """ init """ # create the plugin manager self.simplePluginManager = PluginManager(directories_list=[ os.path.join(os.path.dirname(os.path.abspath(__file__)), "plugins") ]) # load the plugins that may be found self.simplePluginManager.collectPlugins() # Will be used later self.plugin_info = None def plugin_loading_check(self): """ Test if the correct plugin has been loaded. """ if self.plugin_info is None: # check nb of categories self.assertEqual(len(self.simplePluginManager.getCategories()), 1) sole_category = self.simplePluginManager.getCategories()[0] # check the number of plugins self.assertEqual( len( self.simplePluginManager.getPluginsOfCategory( sole_category)), 1) self.plugin_info = self.simplePluginManager.getPluginsOfCategory( sole_category)[0] # test that the name of the plugin has been correctly defined self.assertEqual(self.plugin_info.name, "Simple Plugin") self.assertEqual(sole_category, self.plugin_info.category) else: self.assert_(True) def testLoaded(self): """ Test if the correct plugin has been loaded. """ self.plugin_loading_check() def testGetAll(self): """ Test if the correct plugin has been loaded. """ self.plugin_loading_check() self.assertEqual(len(self.simplePluginManager.getAllPlugins()), 1) self.assertEqual(self.simplePluginManager.getAllPlugins()[0], self.plugin_info) def testActivationAndDeactivation(self): """ Test if the activation procedure works. """ self.plugin_loading_check() self.assert_(not self.plugin_info.plugin_object.is_activated) self.simplePluginManager.activatePluginByName( self.plugin_info.name, self.plugin_info.category) self.assert_(self.plugin_info.plugin_object.is_activated) self.simplePluginManager.deactivatePluginByName( self.plugin_info.name, self.plugin_info.category) self.assert_(not self.plugin_info.plugin_object.is_activated)
class WeaponSystem(rpyc.Service): ''' RPC Services: This is the code that does the actual password cracking and returns the results to orbital control. Currently only supports cracking using rainbow tables (RCrackPy) ''' is_initialized = False mutex = Lock() is_busy = False job_id = None def initialize(self): ''' Initializes variables, this should only be called once ''' logging.info("Weapon system initializing ...") self.plugin_manager = PluginManager() self.plugin_manager.setPluginPlaces(["plugins/"]) self.plugin_manager.setCategoriesFilter(FILTERS) self.plugin_manager.collectPlugins() self.plugins = {} logging.info( "Loaded %d plugin(s)" % len(self.plugin_manager.getAllPlugins()) ) self.__cpu__() logging.info("Weapon system online, good hunting.") @atomic def on_connect(self): ''' Called when successfully connected ''' if not self.is_initialized: self.initialize() self.is_initialized = True logging.info("Uplink to orbital control active") def on_disconnect(self): ''' Called if the connection is lost/disconnected ''' logging.info("Disconnected from orbital command server.") def __cpu__(self): ''' Detects the number of CPU cores on a system (including virtual cores) ''' if cpu_count is not None: try: self.cpu_cores = cpu_count() logging.info("Detected %d CPU core(s)" % self.cpu_cores) except NotImplementedError: logging.error("Could not detect number of processors; assuming 1") self.cpu_cores = 1 else: try: self.cpu_cores = int(sysconf("SC_NPROCESSORS_CONF")) logging.info("Detected %d CPU core(s)" % self.cpu_cores) except ValueError: logging.error("Could not detect number of processors; assuming 1") self.cpu_cores = 1 ############################ [ EXPOSED METHODS ] ############################ @atomic def exposed_crack(self, plugin_name, job_id, hashes, **kwargs): ''' Exposes plugins calls ''' assert plugin_name in self.plugins self.is_busy = True self.job_id = job_id self.plugin_manager.activatePluginByName(plugin_name) plugin = self.plugin_manager.getPluginByName(plugin_name) results = plugin.execute(hashes, **kwargs) self.plugin_manager.deactivatePluginByName(plugin_name) self.job_id = None self.is_busy = False return results def exposed_get_plugin_names(self): ''' Returns what algorithms can be cracked ''' logging.info("Method called: exposed_get_capabilities") plugins = self.plugin_manager.getAllPlugins() return [plugin.name for plugin in plugins] def exposed_get_categories(self): ''' Return categories for which we have plugins ''' categories = [] for category in self.plugin_manager.getCategories(): if 0 < len(self.plugin_manager.getPluginsOfCategory(category)): categories.append(category) return categories def exposed_get_category_plugins(self, category): ''' Get plugin names for a category ''' plugins = self.plugin_manager.getPluginsOfCategory(category) return [plugin.name for plugin in plugins] def exposed_get_plugin_details(self, category, plugin_name): ''' Get plugin based on name details ''' plugin = self.plugin_manager.getPluginByName(plugin_name, category) info = {'name': plugin.name} info['author'] = plugin.details.get('Documentation', 'author') info['website'] = plugin.details.get('Documentation', 'website') info['version'] = plugin.details.get('Documentation', 'version') info['description'] = plugin.details.get('Documentation', 'description') info['copyright'] = plugin.details.get('Documentation', 'copyright') info['precomputation'] = plugin.details.getboolean('Core', 'precomputation') return info def exposed_ping(self): ''' Returns a pong message ''' return "PONG" def exposed_is_busy(self): ''' Returns True/False if the current system is busy (thread safe) ''' return self.is_busy def exposed_current_job_id(self): ''' Returns the current job id (thread safe) ''' return self.job_id def exposed_cpu_count(self): ''' Returns the number of detected cpu cores ''' return self.cpu_cores
class WeaponSystem(rpyc.Service): ''' RPC Services: This is the code that does the actual password cracking and returns the results to orbital control. Currently only supports cracking using rainbow tables (RCrackPy) ''' is_initialized = False mutex = Lock() is_busy = False job_id = None def initialize(self): ''' Initializes variables, this should only be called once ''' logging.info("Weapon system initializing ...") self.plugin_manager = PluginManager() self.plugin_manager.setPluginPlaces(["plugins/"]) self.plugin_manager.setCategoriesFilter(FILTERS) self.plugin_manager.collectPlugins() self.plugins = {} logging.info("Loaded %d plugin(s)" % len(self.plugin_manager.getAllPlugins())) self.__cpu__() logging.info("Weapon system online, good hunting.") @atomic def on_connect(self): ''' Called when successfully connected ''' if not self.is_initialized: self.initialize() self.is_initialized = True logging.info("Uplink to orbital control active") def on_disconnect(self): ''' Called if the connection is lost/disconnected ''' logging.info("Disconnected from orbital command server.") def __cpu__(self): ''' Detects the number of CPU cores on a system (including virtual cores) ''' if cpu_count is not None: try: self.cpu_cores = cpu_count() logging.info("Detected %d CPU core(s)" % self.cpu_cores) except NotImplementedError: logging.error( "Could not detect number of processors; assuming 1") self.cpu_cores = 1 else: try: self.cpu_cores = int(sysconf("SC_NPROCESSORS_CONF")) logging.info("Detected %d CPU core(s)" % self.cpu_cores) except ValueError: logging.error( "Could not detect number of processors; assuming 1") self.cpu_cores = 1 ############################ [ EXPOSED METHODS ] ############################ @atomic def exposed_crack(self, plugin_name, job_id, hashes, **kwargs): ''' Exposes plugins calls ''' assert plugin_name in self.plugins self.is_busy = True self.job_id = job_id self.plugin_manager.activatePluginByName(plugin_name) plugin = self.plugin_manager.getPluginByName(plugin_name) results = plugin.execute(hashes, **kwargs) self.plugin_manager.deactivatePluginByName(plugin_name) self.job_id = None self.is_busy = False return results def exposed_get_plugin_names(self): ''' Returns what algorithms can be cracked ''' logging.info("Method called: exposed_get_capabilities") plugins = self.plugin_manager.getAllPlugins() return [plugin.name for plugin in plugins] def exposed_get_categories(self): ''' Return categories for which we have plugins ''' categories = [] for category in self.plugin_manager.getCategories(): if 0 < len(self.plugin_manager.getPluginsOfCategory(category)): categories.append(category) return categories def exposed_get_category_plugins(self, category): ''' Get plugin names for a category ''' plugins = self.plugin_manager.getPluginsOfCategory(category) return [plugin.name for plugin in plugins] def exposed_get_plugin_details(self, category, plugin_name): ''' Get plugin based on name details ''' plugin = self.plugin_manager.getPluginByName(plugin_name, category) info = {'name': plugin.name} info['author'] = plugin.details.get('Documentation', 'author') info['website'] = plugin.details.get('Documentation', 'website') info['version'] = plugin.details.get('Documentation', 'version') info['description'] = plugin.details.get('Documentation', 'description') info['copyright'] = plugin.details.get('Documentation', 'copyright') info['precomputation'] = plugin.details.getboolean( 'Core', 'precomputation') return info def exposed_ping(self): ''' Returns a pong message ''' return "PONG" def exposed_is_busy(self): ''' Returns True/False if the current system is busy (thread safe) ''' return self.is_busy def exposed_current_job_id(self): ''' Returns the current job id (thread safe) ''' return self.job_id def exposed_cpu_count(self): ''' Returns the number of detected cpu cores ''' return self.cpu_cores
class PluginsManagerService(object): """ Description: main class in order to manage all the plugin operations like loading and triggering """ def __init__(self): self.plugin_manager = PluginManager() self.loaded_plugin_list = [] self.loaded_plugin_objects = None self.plugin_db = Plugins.Plugins(mongodb) self.plugin_location = os.path.abspath( os.path.join(os.getcwd(), 'Plugins')) self.deleted_plugin_location = os.path.abspath( os.path.join(os.getcwd(), 'Plugins_deleted')) self.load_plugin() def load_plugin(self): """loads all plugins from folder and activates the plugins Returns: :dict: active_plugins_dict_from_db Raises: no_value no_active_plugins """ # Build the manager # Tell it the default place(s) where to find plugins print "###################" print "STARTED PLUGIN LOAD " print "###################" if os.path.isdir(self.plugin_location) is True: try: # set plugins from folder self.plugin_manager.setPluginPlaces([self.plugin_location]) # define interfaces to load you have defined self.plugin_manager.setCategoriesFilter({ "PreDeploymentPlugin": IPreDeploymentPlugin, "PostDeploymentPlugin": IPostDeploymentPlugin }) # Load all plugins from plugin folder self.plugin_manager.collectPlugins() loaded_plugin_from_folder = [ x.name for x in self.plugin_manager.getAllPlugins() ] # validate plugin if not valid deactivate for plugin in loaded_plugin_from_folder: if not self.is_valid_plugin(plugin): self.deactivate(plugin) print( "the following plugin is deactivate cause is not valid: " + plugin) # update DB with new plugins self.detect_new_plugins() # load all activated plugins from DB active_plugins_dict_from_db = self.plugin_db.get_all_plugin( status='active') active_plugins_in_db = [ x['name'] for x in self.plugin_db.get_all_plugin(status='active') ] # final active_plugins list if active_plugins_in_db is None: print "no plugins installed" elif loaded_plugin_from_folder is None: print "no plugins in the plugins folder" else: active_plugins = [ x for x in loaded_plugin_from_folder if x in active_plugins_in_db ] for plugin in active_plugins: # validate plugin if not valid deactivate if not self.is_valid_plugin(plugin): print "plugin is not valid: " + plugin + " deactivate" self.deactivate(plugin) else: # activate self.plugin_manager.activatePluginByName(plugin) print "loaded plugin name: " + plugin ValueError("loaded plugin name: " + plugin) print "###################" print "COMPLETED PLUGIN LOAD " print "###################" return active_plugins_dict_from_db except (Exception, ValueError) as error: print error raise ValueError("Unable to load plugins :", error) elif os.path.isdir(self.plugin_location) is False: raise ValueError("plugin folder is set to " + self.plugin_location + " missing or not configured well") else: raise ValueError("unknown err during plugin loading") def detect_new_plugins(self): """ updates new plugins in db :param loaded_plugin_from_folder: :return: """ # load all from db loaded_plugin_from_folder = self.plugin_manager.getAllPlugins() plugins_in_db = [ x.get('name') for x in self.plugin_db.get_all_plugin() ] if not plugins_in_db: new_plugins = loaded_plugin_from_folder else: new_plugins = [ x for x in loaded_plugin_from_folder if x.name not in plugins_in_db ] for plugin_object in new_plugins: # get plugin type parent_class = type(plugin_object.plugin_object).__bases__ parent_class_name = parent_class[0].__name__ plugin_dict = { 'name': plugin_object.name, 'category': parent_class_name[1:], 'author': plugin_object.author, 'version': str(plugin_object.version), 'description': plugin_object.description, 'status': 'inactive' } try: self.plugin_db.add_plugin(plugin_dict) except Exception as error: print error raise RuntimeError("unable to insert the plugin to DB") def install_plugin(self, plugin_name): ''' activates the plugin and triggers the install method of the plugin :param plugin_name: string :return: :raises RuntimeError "unable to insert the plugin to DB" ''' # set plugins from folder # self.plugin_location = os.path.abspath(os.path.join(os.getcwd(), 'Plugins')) # self.load_plugin() plugin_details = self.plugin_db.get_plugin_by_name(plugin_name) plugin_object = self.plugin_manager.getPluginByName( plugin_name, plugin_details.get('category')) if plugin_object: try: self.activate(plugin_name) return plugin_object.plugin_object.install() except Exception as error: print error raise RuntimeError("unable to insert the plugin to DB: ", error) else: raise ValueError("no active plugin with this name") def is_valid_plugin(self, plugin): ''' validate that plugin has all the required methods and attributes :param plugin: :return: True or False ''' # mandatory element lists plugin_mandatory_attributes = [ 'author', 'name', 'version', 'description' ] plugin_mandatory_methods = [ 'preform', 'activate', 'deactivate', 'is_activated' ] # get plugin plugin = self.plugin_manager.getPluginByName(plugin, 'PreDeploymentPlugin') # check plugin manifest try: for attribute in plugin_mandatory_attributes: if str(getattr(plugin, attribute, None)) == "": raise ValueError("plugin is missing value in " + attribute) except (ValueError, AttributeError) as error: print error return False # check plugin methods try: methods = [ x for x in plugin_mandatory_methods if x not in dir(plugin.plugin_object) ] if len(methods) > 0: raise ValueError("folowwing methods are missing " + str(methods)) except (ValueError, AttributeError) as error: print error return False return True def uninstall_plugin(self, plugin): ''' triggers the uninstall method of the plugin by name remove the db details rename the plugin folder :param plugin_name: ''' try: # get category form DB plugin_details = self.plugin_db.get_plugin_by_name(plugin) if plugin_details: plugin_object = self.plugin_manager.getPluginByName( plugin, plugin_details.get('category')) # uninstal plugin_object.plugin_object.uninstall() # delete from db self.plugin_db.delete_plugin_by_name(plugin) # check if deleted folder exists if os.path.isdir(self.deleted_plugin_location) is not True: os.mkdir(self.deleted_plugin_location) # delete folder os.rename( self.plugin_location + "/" + plugin, self.deleted_plugin_location + "/" + plugin + ".deleted") else: raise ValueError('couldnt find plugin') except (ValueError, Exception) as error: print error raise RuntimeError(" could not uninstall plugin " + plugin + " " + error) def activate(self, plugin_name): ''' activates plugin by name :param plugin_name: :raise RuntimeError "could not activate plugin" ''' try: # get category form DB plugin_details = self.plugin_db.get_plugin_by_name(plugin_name) # activate self.plugin_manager.activatePluginByName( plugin_name, plugin_details.get('category')) # updateDB self.plugin_db.update_plugin_status(plugin_name, 'active') except Exception as error: print error raise RuntimeError(" could not activate plugin " + plugin_name) def deactivate(self, plugin_name): ''' deactivates plugin by name :param plugin_name: string :raise RuntimeError "could not deactivate plugin" ''' try: # get category form DB plugin_details = self.plugin_db.get_plugin_by_name(plugin_name) # deactivate self.plugin_manager.deactivatePluginByName( plugin_name, plugin_details.get('category')) # updateDB self.plugin_db.update_plugin_status(plugin_name, 'inactive') except Exception as error: print error raise RuntimeError(" could not deactivate plugin " + plugin_name) def preform(self, category, plugin_name): """ execute the preform method of plugin in category :param plugin_name: string :param category: string :raises RuntimeError unable to trigger operation of plugin: """ try: plugin = self.plugin_manager.getPluginByName(plugin_name, category) plugin.plugin_object.preform() except Exception as error: print error raise RuntimeError(" unable to trigger operation of plugin:" + plugin_name) def preform_all_in_category(self, category, **keyargs): ''' triggers all preform methods of plugin in the provided category :param category: :return: :raises RuntimeError "unable to execute the plugin logic" ''' for (key, value) in keyargs.iteritems(): print(key, value) try: for plugin in self.plugin_manager.getPluginsOfCategory(category): print("preforming action of plugin " + plugin.name) plugin.plugin_object.preform() except (ValueError, Exception) as error: print error raise RuntimeError("unable to execute the plugin logic: " + error) # ## test def test(self): # just for test for p in self.plugin_manager.getPluginsOfCategory( 'PreDeploymentPlugin'): self.install_plugin('TestPlugin')
def main(): #Find and load plugins pm = PluginManager() libpath = '%s/OpenMesher/plugins' % (get_python_lib()) pm.setPluginPlaces([ "/usr/share/openmesher/plugins", "~/.openmesher/plugins", "./OpenMesher/plugins", "./plugins", libpath ]) pm.setPluginInfoExtension('plugin') pm.setCategoriesFilter({ 'config': IOpenMesherConfigPlugin, 'package': IOpenMesherPackagePlugin, 'deploy': IOpenMesherDeployPlugin, }) pm.collectPlugins() parser = argparse.ArgumentParser( formatter_class=argparse.ArgumentDefaultsHelpFormatter, description="Configure, package, and deploy an OpenVPN mesh") parser.add_argument('-r', '--router', action='append', help='Adds a router that can be a client and server') parser.add_argument( '-s', '--server', action='append', help='Adds a router that can only act as a server, not a client.') parser.add_argument( '-c', '--client', action='append', help= 'Adds a router than can only act as a client. For example, a router that is behind NAT and not accessible by a public IP' ) #BUG: Stupid argparse appends your switches to the default. #parser.add_argument('-n', '--network', action='append', default=['10.99.99.0/24']) parser.add_argument('-n', '--network', action='append', required=True) portgroup = parser.add_mutually_exclusive_group() portgroup.add_argument('-p', '--ports', action='append', default=['7000-7999']) portgroup.add_argument('-a', '--random', action='store_true') parser.add_argument( '-v', '--verbose', action='append_const', const='verbose', help='Specify multiple times to make things more verbose') parser.add_argument('--version', action='version', version='v0.6.4') pluginargsgroup = parser.add_argument_group('plugins') for plugin in pm.getAllPlugins(): plugin.plugin_object.setupargs(pluginargsgroup) arg = parser.parse_args() for plugin in pm.getAllPlugins(): if plugin.plugin_object.__class__.__name__.lower() in arg: if eval('arg.%s' % (plugin.plugin_object.__class__.__name__.lower())): logging.debug('Plugin enabled: %s' % (plugin.name)) pm.activatePluginByName(plugin.name) else: logging.debug('Plugin disabled: %s' % (plugin.name)) pm.deactivatePluginByName(plugin.name) else: logging.debug('Plugin disabled: %s' % (plugin.name)) pm.deactivatePluginByName(plugin.name) l = logging.getLogger() if arg.verbose: if len(arg.verbose) == 1: l.setLevel(logging.INFO) if len(arg.verbose) >= 2: l.setLevel(logging.DEBUG) # Call activate() on all plugins so they prep themselves for use for plugin in pm.getAllPlugins(): if eval('arg.%s' % (plugin.plugin_object.__class__.__name__.lower())): logging.info('Enabled plugin: %s' % (plugin.name)) pm.activatePluginByName(plugin.name) plugin.plugin_object.activate() plugin.plugin_object._enabled = True if len(arg.ports) > 1: arg.ports.reverse() arg.ports.pop() port_list = [] if arg.random: numdevs = 0 if arg.router: numdevs += len(arg.router) if arg.server: numdevs += len(arg.server) if arg.client: numdevs += len(arg.client) ports_needed = numdevs * (numdevs - 1) / 2 for i in range(0, ports_needed): port_list.append(random.randrange(1025, 32767)) try: if not arg.random: # If we're not using random ports, pull whatever is in arg.ports for portrange in arg.ports: portstart, portstop = portrange.split('-') port_list += range(int(portstart), int(portstop)) except ValueError as e: print 'Invalid port range: %s' % (portrange) raise ValueError('Invalid port range: %s' % (portrange)) linkmesh = create_link_mesh(routers=arg.router, servers=arg.server, clients=arg.client) m = Mesh(linkmesh, port_list, arg.network) files = None # Run through config plugins configPlugins = [] for plugin in pm.getPluginsOfCategory('config'): if plugin.plugin_object._enabled: plugin.plugin_object.process(m, arg) configPlugins.append(plugin.plugin_object) if files: files = nested_dict_merge(files, plugin.plugin_object.files()) else: files = plugin.plugin_object.files() #Grab list of folders that need to be in the package root includedirs = [] for f in files: for fldr in files[f]: rootfldr = fldr.split('/')[1] if rootfldr not in includedirs: includedirs.append(rootfldr) logging.debug('The following folders will be packaged: %s' % (includedirs)) # Run through packaging plugins packagePlugins = [] for plugin in pm.getPluginsOfCategory('package'): if plugin.plugin_object._enabled: #BUG: Services to restart may not necessarily be the same name as their config dir... plugin.plugin_object.process(m, include_dirs=includedirs, restart_services=includedirs, configPlugins=configPlugins, cliargs=arg) packagePlugins.append(plugin.plugin_object) # Run through deployment plugins for plugin in pm.getPluginsOfCategory('deploy'): if plugin.plugin_object._enabled: try: plugin.plugin_object.deploy(packagePlugins=packagePlugins, cliargs=arg, stoponfailure=False) except Exception as e: print "Unable to deploy due to error: %s" % (e) logging.info('OpenMesher run complete')
class PluginHandler: """ Handles management of provider, postprocessor and converter plugins. .. autosummary:: activate_plugins_by_category deactivate_plugins_by_category get_plugins_from_category is_activated Categories are Provider, Converter and Postprocessor. """ def __init__(self): self._plugin_manager = PluginManager() self._category_active = { 'Provider': False, 'Converter': False, 'Postprocessor': False } self._plugin_from_category = { 'Provider': [], 'Converter': [], 'Postprocessor': [] } self._provider_plugins = [] self._converter_plugins = [] self._postprocessor_plugins = [] self._collect_all_plugins() def _collect_all_plugins(self): """ Collect all provider, converter and postprocessor plugins. """ self._plugin_manager.setPluginPlaces([ 'hugin/harvest/provider', 'hugin/harvest/converter', 'hugin/harvest/postprocessor' ]) # setting filter categories for pluginmanager self._plugin_manager.setCategoriesFilter({ # movie metadata provider 'Provider': IProvider, # sub metadata provider 'Movie': IMovieProvider, 'Person': IPersonProvider, # output converter 'Converter': IConverter, # postprocessor filter 'Postprocessor': IPostprocessor }) self._plugin_manager.collectPlugins() def activate_plugins_by_category(self, category): """ Activate plugins from given category. """ self._toggle_activate_plugins_by_category(category) def deactivate_plugins_by_category(self, category): """ Deactivate plugins from given category. """ self._toggle_activate_plugins_by_category(category) def _toggle_activate_plugins_by_category(self, category): plugins = self._plugin_manager.getPluginsOfCategory(category) is_active = self._category_active[category] for pluginInfo in plugins: if is_active: self._plugin_manager.deactivatePluginByName( name=pluginInfo.name, category=category ) self._plugin_from_category[category].remove(pluginInfo) else: self._plugin_manager.activatePluginByName( name=pluginInfo.name, category=category ) self._plugin_from_category[category].append(pluginInfo) self._category_active[category] = not is_active def get_plugins_from_category(self, category): """ Retrun plugins from the given categrory. Gets plugins from given categrory. Plugin name is set according to name given in yapsy plugin file. :param categrory: The category plugins to load from. :returns: A list with plugins. """ plugins = [] for plugin in self._plugin_from_category[category]: plugin.plugin_object.name = plugin.name plugin.plugin_object.description = plugin.description plugins.append(plugin.plugin_object) return plugins def is_activated(self, category): """ True if category is activated. """ return self._category_active[category]
class NimbusPI(object): """The NimbusPi Weather Station""" # Current NimbusPI Version VERSION = "0.1.0-rc1" def __init__(self, config='nimbus.cfg'): """Initializes the NimbusPI Weather Station""" self.sensors = dict() self.broadcasters = dict() self.threads = [] # Initialize a named logger self.__logger = logging.getLogger('nimbuspi') # Load our config defaults self.config = configparser.ConfigParser(allow_no_value=True) self.config.add_section('station') self.config.set('station', 'name', 'N/A') self.config.set('station', 'location', 'N/A') self.config.set('station', 'longitude', '0.000000') self.config.set('station', 'latitude', '0.000000') self.config.set('station', 'altitude', '0') self.config.add_section('sensors') self.config.add_section('broadcasters') # Load the provided config file if not os.path.isfile(config): self.__logger.warn('Configuration file "%s" not found!', config) else: self.__logger.debug('Loading configuration from "%s"', config) self.config.read(config) # Get our station details self.__logger.debug(' name :: %s', self.config.get('station', 'name')) self.__logger.debug(' location :: %s', self.config.get('station', 'location')) self.__logger.debug(' latitude :: %s', self.config.get('station', 'latitude')) self.__logger.debug(' longitude :: %s', self.config.get('station', 'longitude')) self.__logger.debug(' altitude :: %s feet', self.config.get('station', 'altitude')) self.__logger.debug('Sensors Configured:') for sensor in self.config.options('sensors'): self.__logger.debug(' %s', sensor) self.__logger.debug('Broadcasters Configured:') for broadcaster in self.config.options('broadcasters'): self.__logger.debug(' %s', broadcaster) # Search for available plugins self.__logger.debug("Searching for available plugins...") self.__plugins = PluginManager(plugin_info_ext='info') self.__plugins.setPluginPlaces([ './sensors', './broadcasters', './nimbuspi/sensors', './nimbuspi/broadcasters' ]) self.__plugins.setCategoriesFilter({ plugins.ISensorPlugin.CATEGORY: plugins.ISensorPlugin, plugins.IBroadcasterPlugin.CATEGORY: plugins.IBroadcasterPlugin }) self.__plugins.collectPlugins() for plugin in self.__plugins.getAllPlugins(): self.__logger.debug(" %s (%s)", plugin.name, plugin.path) plugin.plugin_object.set_nimbus(self) self.__logger.debug("%d plugins available", len(self.__plugins.getAllPlugins())) def run(self): """Runs the NimbusPI Weather Station loop""" self.__logger.debug('-' * 80) self.__logger.info('NimbusPI Weather Station v%s', self.VERSION) self.__logger.info('-' * 80) # Load all configured sensor plugins self.__logger.info("Activating sensor plugins...") for sensor in self.config.options('sensors'): try: self.activate_sensor(sensor) except LookupError: self.__logger.error("Could not load sensor '%s'", sensor) return if len(self.sensors) <= 0: self.__logger.error('Cannot continue - no sensors configured') return # Load all configured broadcaster plugins self.__logger.info("Activating broadcaster plugins...") for broadcaster in self.config.options('broadcasters'): try: self.activate_broadcaster(broadcaster) except LookupError: self.__logger.error("Could not load broadcaster '%s'", broadcaster) return if len(self.broadcasters) <= 0: self.__logger.error('Cannot continue - no broadcasters configured') return # # Thread run loop until keyboard interrupt self.__logger.debug("Entering thread loop") while len(self.threads) > 0: try: self.threads = [ t.join(30) for t in self.threads if t is not None and t.isAlive() ] except (KeyboardInterrupt, SystemExit): self.__logger.info( "Shutting down plugins (this may take a minute)...") for thread in self.threads: thread.stop() self.__logger.debug("Exiting thread loop") # Deactivate plugins self.__logger.debug("Deactivating sensors") sensors = self.sensors.keys() for sensor in sensors: self.deactivate_sensor(sensor) self.__logger.debug("Deactivating broadcasters") broadcasters = self.broadcasters.keys() for broadcaster in broadcasters: self.deactivate_broadcaster(broadcaster) def activate_sensor(self, sensor): """Activates a sensor on the service""" if sensor in self.sensors: self.__logger.warn( "Cannot activate sensor '%s' - sensor already active", sensor) return False self.__logger.debug("Activating sensor '%s'", sensor) self.sensors[sensor] = self.__plugins.getPluginByName( sensor, plugins.ISensorPlugin.CATEGORY) if not self.sensors[sensor]: raise LookupError self.__plugins.activatePluginByName(sensor, plugins.ISensorPlugin.CATEGORY) self.threads.append(self.sensors[sensor].plugin_object.thread) return True def deactivate_sensor(self, sensor): """Deactivates a sensor on the service""" if sensor not in self.sensors: self.__logger.warn( "Cannot deactivate sensor '%s' - sensor not active", sensor) return False self.__logger.debug("Deactivating sensor '%s'", sensor) if self.sensors[sensor].plugin_object.thread: self.sensors[sensor].plugin_object.thread.stop() self.__plugins.deactivatePluginByName(sensor, plugins.ISensorPlugin.CATEGORY) del self.sensors[sensor] return True def activate_broadcaster(self, broadcaster): """Activates a broadcaster on the service""" if broadcaster in self.broadcasters: self.__logger.warn( "Cannot activate broadcaster '%s' - broadcaster already active", broadcaster) return False self.__logger.debug("Activating broadcaster '%s'", broadcaster) self.broadcasters[broadcaster] = self.__plugins.getPluginByName( broadcaster, plugins.IBroadcasterPlugin.CATEGORY) if not self.broadcasters[broadcaster]: raise LookupError self.__plugins.activatePluginByName( broadcaster, plugins.IBroadcasterPlugin.CATEGORY) self.threads.append( self.broadcasters[broadcaster].plugin_object.thread) return True def deactivate_broadcaster(self, broadcaster): """Deactivates a broadcaster on the service""" if broadcaster not in self.broadcasters: self.__logger.warn( "Cannot deactivate broadcaster '%s' - broadcaster not active", broadcaster) return False self.__logger.debug("Deactivating broadcaster '%s'", broadcaster) if self.broadcasters[broadcaster].plugin_object.thread: self.broadcasters[broadcaster].plugin_object.thread.stop() self.__plugins.deactivatePluginByName( broadcaster, plugins.IBroadcasterPlugin.CATEGORY) del self.broadcasters[broadcaster] return True def get_states(self): """Returns the current state of all sensors""" states = dict() # Add our station configuration information as well states['config'] = dict() for option in self.config.options('station'): states['config'][option] = self.config.get('station', option) # Add all current plugin states for sensor in self.sensors: states[sensor] = self.sensors[sensor].plugin_object.get_state() return states
def main(): #Find and load plugins pm = PluginManager() libpath = '%s/OpenMesher/plugins' %(get_python_lib()) pm.setPluginPlaces(["/usr/share/openmesher/plugins", "~/.openmesher/plugins", "./OpenMesher/plugins", "./plugins", libpath]) pm.setPluginInfoExtension('plugin') pm.setCategoriesFilter({ 'config': IOpenMesherConfigPlugin, 'package': IOpenMesherPackagePlugin, 'deploy': IOpenMesherDeployPlugin, }) pm.collectPlugins() parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter, description="Configure, package, and deploy an OpenVPN mesh") parser.add_argument('-r', '--router', action='append', help='Adds a router that can be a client and server') parser.add_argument('-s', '--server', action='append', help='Adds a router that can only act as a server, not a client.') parser.add_argument('-c', '--client', action='append', help='Adds a router than can only act as a client. For example, a router that is behind NAT and not accessible by a public IP') #BUG: Stupid argparse appends your switches to the default. #parser.add_argument('-n', '--network', action='append', default=['10.99.99.0/24']) parser.add_argument('-n', '--network', action='append', required=True) portgroup = parser.add_mutually_exclusive_group() portgroup.add_argument('-p', '--ports', action='append', default=['7000-7999']) portgroup.add_argument('-a', '--random', action='store_true') parser.add_argument('-v', '--verbose', action='append_const', const='verbose', help='Specify multiple times to make things more verbose') parser.add_argument('--version', action='version', version='v0.6.4') pluginargsgroup = parser.add_argument_group('plugins') for plugin in pm.getAllPlugins(): plugin.plugin_object.setupargs(pluginargsgroup) arg = parser.parse_args() for plugin in pm.getAllPlugins(): if plugin.plugin_object.__class__.__name__.lower() in arg: if eval('arg.%s' %(plugin.plugin_object.__class__.__name__.lower())): logging.debug('Plugin enabled: %s' %(plugin.name)) pm.activatePluginByName(plugin.name) else: logging.debug('Plugin disabled: %s' %(plugin.name)) pm.deactivatePluginByName(plugin.name) else: logging.debug('Plugin disabled: %s' %(plugin.name)) pm.deactivatePluginByName(plugin.name) l = logging.getLogger() if arg.verbose: if len(arg.verbose) == 1: l.setLevel(logging.INFO) if len(arg.verbose) >= 2: l.setLevel(logging.DEBUG) # Call activate() on all plugins so they prep themselves for use for plugin in pm.getAllPlugins(): if eval('arg.%s' %(plugin.plugin_object.__class__.__name__.lower())): logging.info('Enabled plugin: %s' %(plugin.name)) pm.activatePluginByName(plugin.name) plugin.plugin_object.activate() plugin.plugin_object._enabled = True if len(arg.ports) > 1: arg.ports.reverse() arg.ports.pop() port_list = [] if arg.random: numdevs = 0 if arg.router: numdevs += len(arg.router) if arg.server: numdevs += len(arg.server) if arg.client: numdevs += len(arg.client) ports_needed = numdevs * (numdevs - 1) / 2 for i in range(0, ports_needed): port_list.append(random.randrange(1025,32767)) try: if not arg.random: # If we're not using random ports, pull whatever is in arg.ports for portrange in arg.ports: portstart, portstop = portrange.split('-') port_list += range(int(portstart),int(portstop)) except ValueError as e: print 'Invalid port range: %s' %(portrange) raise ValueError('Invalid port range: %s' %(portrange)) linkmesh = create_link_mesh(routers=arg.router, servers=arg.server, clients=arg.client) m = Mesh(linkmesh, port_list, arg.network) files = None # Run through config plugins configPlugins = [] for plugin in pm.getPluginsOfCategory('config'): if plugin.plugin_object._enabled: plugin.plugin_object.process(m, arg) configPlugins.append(plugin.plugin_object) if files: files = nested_dict_merge(files, plugin.plugin_object.files()) else: files = plugin.plugin_object.files() #Grab list of folders that need to be in the package root includedirs = [] for f in files: for fldr in files[f]: rootfldr = fldr.split('/')[1] if rootfldr not in includedirs: includedirs.append(rootfldr) logging.debug('The following folders will be packaged: %s' %(includedirs)) # Run through packaging plugins packagePlugins = [] for plugin in pm.getPluginsOfCategory('package'): if plugin.plugin_object._enabled: #BUG: Services to restart may not necessarily be the same name as their config dir... plugin.plugin_object.process(m, include_dirs=includedirs, restart_services=includedirs, configPlugins=configPlugins, cliargs=arg) packagePlugins.append(plugin.plugin_object) # Run through deployment plugins for plugin in pm.getPluginsOfCategory('deploy'): if plugin.plugin_object._enabled: try: plugin.plugin_object.deploy(packagePlugins=packagePlugins, cliargs=arg, stoponfailure=False) except Exception as e: print "Unable to deploy due to error: %s" %(e) logging.info('OpenMesher run complete')
class Manager(object): """ This is the main ``octo`` application class. Normally, you would call `octo.main` instead of creating an instance of this class directly, as `octo.main` will make it available globally as `octo.instance` so plugins may interact with it. """ def __init__(self, plugin_dirs=[]): logging.info( "Initializing with plugin directories: {!r}".format(plugin_dirs)) self.plugin_manager = PluginManager(directories_list=plugin_dirs, plugin_info_ext='octoplugin') self.plugin_manager.collectPlugins() for plugin in self.get_plugins(include_inactive=True).values(): # Bind the plugin object so the plugin can refer to it via self plugin.plugin_object.plugin_object = plugin # And bind it's configparser object separately as well for a cleaner API plugin.plugin_object.plugin_config = plugin.details def get_plugins(self, include_inactive=False): """ Return a dictionary of loaded plugins Keys will consist of plugin names, with their values being the plugin instances (yapsy.PluginInfo.PluginInfo objects). When ``include_inactive`` is True, all collected plugins will be returned, otherwise only the activated plugins will be returned. """ if include_inactive: plugins = self.plugin_manager.getAllPlugins() else: plugins = [ plugin for plugin in self.plugin_manager.getAllPlugins() if hasattr(plugin, 'is_activated') and plugin.is_activated ] return dict(zip([plugin.name for plugin in plugins], plugins)) def activate_plugin(self, plugin_name): """ Activate the given plugin plugin_name should be the name of the plugin to be activated. """ self.plugin_manager.activatePluginByName(plugin_name) def deactivate_plugin(self, plugin_name): """ Deactivate the given plugin plugin_name should be the name of the plugin to be deactivated. """ self.plugin_manager.deactivatePluginByName(plugin_name) def call(self, plugin_name, func, args=[], kwargs={}): """ Call the given function on the given plugin object (specifed by plugin name) """ for plugin in self.get_plugins().values(): if plugin.name == plugin_name: return getattr(plugin.plugin_object, func)(*args, **kwargs) raise octo.exceptions.NoSuchPluginError( "The specified plugin isn't active or doesn't exist") def call_many(self, func, args=[], kwargs={}): """ Call the given function on all active plugins and return results as a dictionary The returned dictionary will have the form of {'plugin name': <function_result>} """ results = {} for plugin in self.get_plugins().values(): try: logging.debug("Calling {} on plugin '{}'".format( func, plugin.name)) results[plugin.name] = getattr(plugin.plugin_object, func)(*args, **kwargs) except AttributeError as e: logging.debug("'{}' has no attribute {}".format( plugin.name, func)) except Exception as e: logging.exception( "Exception while calling '{}' on '{}'".format( func, plugin.name)) results[plugin.name] = e return results def start(self): """Start and activate collected plugins A plugin will be activated when it has a config item 'Enable' under the section 'Config' with a value of True""" logging.debug("Activating plugins") for plugin in self.get_plugins(include_inactive=True).values(): try: should_activate = plugin.details.getboolean('Config', 'Enable') except configparser.NoSectionError: should_activate = False if should_activate: logging.debug("Activating plugin {}".format(plugin.name)) self.activate_plugin(plugin.name) else: logging.debug( "Plugin {} not activated because config item Enable " "is not True".format(plugin.name)) logging.debug("Plugin activation done") return self def stop(self): """Stop and deactivate loaded plugins""" logging.debug("Deactivating plugins") for plugin in self.get_plugins().values(): logging.debug("Deactivating plugin {}".format(plugin.name)) self.deactivate_plugin(plugin.name) logging.debug("Plugin deactivation done") return self
class Manager(object): """ This is the main ``octo`` application class. Normally, you would call `octo.main` instead of creating an instance of this class directly, as `octo.main` will make it available globally as `octo.instance` so plugins may interact with it. """ def __init__(self, plugin_dirs=[]): logging.info("Initializing with plugin directories: {!r}".format(plugin_dirs)) self.plugin_manager = PluginManager(directories_list=plugin_dirs, plugin_info_ext='octoplugin') self.plugin_manager.collectPlugins() for plugin in self.get_plugins(include_inactive=True).values(): # Bind the plugin object so the plugin can refer to it via self plugin.plugin_object.plugin_object = plugin # And bind it's configparser object separately as well for a cleaner API plugin.plugin_object.plugin_config = plugin.details def get_plugins(self, include_inactive=False): """ Return a dictionary of loaded plugins Keys will consist of plugin names, with their values being the plugin instances (yapsy.PluginInfo.PluginInfo objects). When ``include_inactive`` is True, all collected plugins will be returned, otherwise only the activated plugins will be returned. """ if include_inactive: plugins = self.plugin_manager.getAllPlugins() else: plugins = [plugin for plugin in self.plugin_manager.getAllPlugins() if hasattr(plugin, 'is_activated') and plugin.is_activated] return dict(zip([plugin.name for plugin in plugins], plugins)) def activate_plugin(self, plugin_name): """ Activate the given plugin plugin_name should be the name of the plugin to be activated. """ self.plugin_manager.activatePluginByName(plugin_name) def deactivate_plugin(self, plugin_name): """ Deactivate the given plugin plugin_name should be the name of the plugin to be deactivated. """ self.plugin_manager.deactivatePluginByName(plugin_name) def call(self, plugin_name, func, args=[], kwargs={}): """ Call the given function on the given plugin object (specifed by plugin name) """ for plugin in self.get_plugins().values(): if plugin.name == plugin_name: return getattr(plugin.plugin_object, func)(*args, **kwargs) raise octo.exceptions.NoSuchPluginError("The specified plugin isn't active or doesn't exist") def call_many(self, func, args=[], kwargs={}): """ Call the given function on all active plugins and return results as a dictionary The returned dictionary will have the form of {'plugin name': <function_result>} """ results = {} for plugin in self.get_plugins().values(): try: logging.debug("Calling {} on plugin '{}'".format(func, plugin.name)) results[plugin.name] = getattr(plugin.plugin_object, func)(*args, **kwargs) except AttributeError as e: logging.debug("'{}' has no attribute {}".format(plugin.name, func)) except Exception as e: logging.exception("Exception while calling '{}' on '{}'".format(func, plugin.name)) results[plugin.name] = e return results def start(self): """Start and activate collected plugins A plugin will be activated when it has a config item 'Enable' under the section 'Config' with a value of True""" logging.debug("Activating plugins") for plugin in self.get_plugins(include_inactive=True).values(): try: should_activate = plugin.details.getboolean('Config', 'Enable') except configparser.NoSectionError: should_activate = False if should_activate: logging.debug("Activating plugin {}".format(plugin.name)) self.activate_plugin(plugin.name) else: logging.debug("Plugin {} not activated because config item Enable " "is not True".format(plugin.name)) logging.debug("Plugin activation done") return self def stop(self): """Stop and deactivate loaded plugins""" logging.debug("Deactivating plugins") for plugin in self.get_plugins().values(): logging.debug("Deactivating plugin {}".format(plugin.name)) self.deactivate_plugin(plugin.name) logging.debug("Plugin deactivation done") return self
class NimbusPI(object): """The NimbusPi Weather Station""" # Current NimbusPI Version VERSION = "0.1.0-rc1" def __init__(self, config='nimbus.cfg'): """Initializes the NimbusPI Weather Station""" self.sensors = dict() self.broadcasters = dict() self.threads = [] # Initialize a named logger self.__logger = logging.getLogger('nimbuspi') # Load our config defaults self.config = configparser.ConfigParser(allow_no_value=True) self.config.add_section('station') self.config.set('station', 'name', 'N/A') self.config.set('station', 'location', 'N/A') self.config.set('station', 'longitude', '0.000000') self.config.set('station', 'latitude', '0.000000') self.config.set('station', 'altitude', '0') self.config.add_section('sensors') self.config.add_section('broadcasters') # Load the provided config file if not os.path.isfile(config): self.__logger.warn('Configuration file "%s" not found!', config) else: self.__logger.debug('Loading configuration from "%s"', config) self.config.read(config) # Get our station details self.__logger.debug(' name :: %s', self.config.get('station', 'name')) self.__logger.debug(' location :: %s', self.config.get('station', 'location')) self.__logger.debug(' latitude :: %s', self.config.get('station', 'latitude')) self.__logger.debug(' longitude :: %s', self.config.get('station', 'longitude')) self.__logger.debug(' altitude :: %s feet', self.config.get('station', 'altitude')) self.__logger.debug('Sensors Configured:') for sensor in self.config.options('sensors'): self.__logger.debug(' %s', sensor) self.__logger.debug('Broadcasters Configured:') for broadcaster in self.config.options('broadcasters'): self.__logger.debug(' %s', broadcaster) # Search for available plugins self.__logger.debug("Searching for available plugins...") self.__plugins = PluginManager(plugin_info_ext='info') self.__plugins.setPluginPlaces([ './sensors', './broadcasters', './nimbuspi/sensors', './nimbuspi/broadcasters' ]) self.__plugins.setCategoriesFilter({ plugins.ISensorPlugin.CATEGORY : plugins.ISensorPlugin, plugins.IBroadcasterPlugin.CATEGORY : plugins.IBroadcasterPlugin }) self.__plugins.collectPlugins() for plugin in self.__plugins.getAllPlugins(): self.__logger.debug(" %s (%s)", plugin.name, plugin.path) plugin.plugin_object.set_nimbus(self) self.__logger.debug("%d plugins available", len(self.__plugins.getAllPlugins())) def run(self): """Runs the NimbusPI Weather Station loop""" self.__logger.debug('-' * 80) self.__logger.info('NimbusPI Weather Station v%s', self.VERSION) self.__logger.info('-' * 80) # Load all configured sensor plugins self.__logger.info("Activating sensor plugins...") for sensor in self.config.options('sensors'): try: self.activate_sensor(sensor) except LookupError: self.__logger.error("Could not load sensor '%s'", sensor) return if len(self.sensors) <= 0: self.__logger.error('Cannot continue - no sensors configured') return # Load all configured broadcaster plugins self.__logger.info("Activating broadcaster plugins...") for broadcaster in self.config.options('broadcasters'): try: self.activate_broadcaster(broadcaster) except LookupError: self.__logger.error("Could not load broadcaster '%s'", broadcaster) return if len(self.broadcasters) <= 0: self.__logger.error('Cannot continue - no broadcasters configured') return # # Thread run loop until keyboard interrupt self.__logger.debug("Entering thread loop") while len(self.threads) > 0: try: self.threads = [t.join(30) for t in self.threads if t is not None and t.isAlive()] except (KeyboardInterrupt, SystemExit): self.__logger.info("Shutting down plugins (this may take a minute)...") for thread in self.threads: thread.stop() self.__logger.debug("Exiting thread loop") # Deactivate plugins self.__logger.debug("Deactivating sensors") sensors = self.sensors.keys() for sensor in sensors: self.deactivate_sensor(sensor) self.__logger.debug("Deactivating broadcasters") broadcasters = self.broadcasters.keys() for broadcaster in broadcasters: self.deactivate_broadcaster(broadcaster) def activate_sensor(self, sensor): """Activates a sensor on the service""" if sensor in self.sensors: self.__logger.warn("Cannot activate sensor '%s' - sensor already active", sensor) return False self.__logger.debug("Activating sensor '%s'", sensor) self.sensors[sensor] = self.__plugins.getPluginByName(sensor, plugins.ISensorPlugin.CATEGORY) if not self.sensors[sensor]: raise LookupError self.__plugins.activatePluginByName(sensor, plugins.ISensorPlugin.CATEGORY) self.threads.append(self.sensors[sensor].plugin_object.thread) return True def deactivate_sensor(self, sensor): """Deactivates a sensor on the service""" if sensor not in self.sensors: self.__logger.warn("Cannot deactivate sensor '%s' - sensor not active", sensor) return False self.__logger.debug("Deactivating sensor '%s'", sensor) if self.sensors[sensor].plugin_object.thread: self.sensors[sensor].plugin_object.thread.stop() self.__plugins.deactivatePluginByName(sensor, plugins.ISensorPlugin.CATEGORY) del self.sensors[sensor] return True def activate_broadcaster(self, broadcaster): """Activates a broadcaster on the service""" if broadcaster in self.broadcasters: self.__logger.warn("Cannot activate broadcaster '%s' - broadcaster already active", broadcaster) return False self.__logger.debug("Activating broadcaster '%s'", broadcaster) self.broadcasters[broadcaster] = self.__plugins.getPluginByName( broadcaster, plugins.IBroadcasterPlugin.CATEGORY ) if not self.broadcasters[broadcaster]: raise LookupError self.__plugins.activatePluginByName(broadcaster, plugins.IBroadcasterPlugin.CATEGORY) self.threads.append(self.broadcasters[broadcaster].plugin_object.thread) return True def deactivate_broadcaster(self, broadcaster): """Deactivates a broadcaster on the service""" if broadcaster not in self.broadcasters: self.__logger.warn("Cannot deactivate broadcaster '%s' - broadcaster not active", broadcaster) return False self.__logger.debug("Deactivating broadcaster '%s'", broadcaster) if self.broadcasters[broadcaster].plugin_object.thread: self.broadcasters[broadcaster].plugin_object.thread.stop() self.__plugins.deactivatePluginByName(broadcaster, plugins.IBroadcasterPlugin.CATEGORY) del self.broadcasters[broadcaster] return True def get_states(self): """Returns the current state of all sensors""" states = dict() # Add our station configuration information as well states['config'] = dict() for option in self.config.options('station'): states['config'][option] = self.config.get('station', option) # Add all current plugin states for sensor in self.sensors: states[sensor] = self.sensors[sensor].plugin_object.get_state() return states
class HandlerManager(QThread): # 返回命令执行结果 # int: 0 -- 返回PlainText # 1 -- 返回RichText # str: 结果 outSignal = pyqtSignal(int, str) def __init__(self): super(HandlerManager, self).__init__() # 创建工作队列,用户输入的命令按照顺序put进该队列 # 由CommandHandler在后台逐个处理 self.workQueue = Queue() # 初始化插件功能 self.initPlugin() def __del__(self): self.wait() def initPlugin(self): ''' 启动插件管理器,获取插件列表 ''' # 创建插件管理器 self.pluginManager = PluginManager() # 设置插件接口为 DPlugin,所有插件必须继承categories.DPlugin self.pluginManager.setCategoriesFilter({"DPlugin": DPlugin}) # 设置插件目录 self.pluginManager.setPluginPlaces(['plugins']) # 加载插件到内存 self.pluginManager.locatePlugins() self.pluginManager.loadPlugins() def getAllPlugins(self): '''获取插件列表''' return self.pluginManager.getPluginsOfCategory('DPlugin') def activateAllPlugins(self): '''使能所有插件''' for plugin in self.pluginManager.getPluginsOfCategory('DPlugin'): plugin.plugin_object.activate() def deactivateAllPlugins(self): '''禁用所有插件''' for plugin in self.pluginManager.getPluginsOfCategory('DPlugin'): plugin.plugin_object.deactivate() def activatePlugin(self, name): '''使能特定插件''' self.pluginManager.activatePluginByName(name, category="DPlugin") def deactivatePlugin(self, name): '''使能特定插件''' self.pluginManager.deactivatePluginByName(name, category="DPlugin") def processInput(self, userInput): '''将命令放入队列''' self.workQueue.put((False, userInput)) def processFile(self, filepath): '''将待处理文件放入队列''' self.workQueue.put((True, filepath)) def run(self): '''不断从Queue中获取数据,然后执行解析命令''' while True: isFile, userInput = self.workQueue.get() if isFile: self.execFile(userInput) else: self.execCommand(userInput, None) def execCommand(self, userInput, currentFile): ''' 解析命令 ''' if not len(userInput) or userInput.startswith('#'): return # 命令回显 self.writeCommand(userInput) # 命令分割 command, *params = userInput.split(maxsplit=1) if command == 'source': if len(params) == 1: filepath = params[0] if not os.path.isabs(filepath): basepath = os.path.dirname(currentFile) filepath = os.path.normpath(filepath) filepath = os.path.join(basepath, filepath) self.execFile(filepath) else: self.writeStderr('syntax error: ' + userInput) else: self.dispatchCommand(userInput) def execFile(self, filepath): self.writeCommand('Processing file ' + filepath) if os.path.isfile(filepath) and os.access(filepath, os.R_OK): with open(filepath, 'r') as f: for line in f.readlines(): line = line.strip() self.execCommand(line, filepath) else: self.writeStderr('Cannot open file: ' + filepath) def dispatchCommand(self, userInput): '''将命令分发给各个插件''' status = DPlugin.EXEC_NOTFOUND for plugin in self.pluginManager.getPluginsOfCategory('DPlugin'): ret, resultText = plugin.plugin_object.execCommand(userInput) if ret == DPlugin.EXEC_SUCCESS: self.writeStdout(resultText) status = DPlugin.EXEC_SUCCESS elif ret == DPlugin.EXEC_FAILED: self.writeStderr(resultText) status = DPlugin.EXEC_FAILED if status == DPlugin.EXEC_NOTFOUND: self.writeStderr(userInput + ': Command not found') def writeCommand(self, text): ''' 输出原始命令,蓝色加粗显示,以示区分 ''' self.outSignal.emit(1, text) def writeStdout(self, text): ''' 返回普通输出,文本后加换行 ''' self.outSignal.emit(0, text) def writeStderr(self, text): ''' 返回错误输出,红色加粗显示,以示区分 ''' self.outSignal.emit(2, text)