Beispiel #1
0
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)
Beispiel #3
0
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
Beispiel #5
0
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
Beispiel #6
0
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')
Beispiel #7
0
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')
Beispiel #8
0
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]
Beispiel #9
0
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')
Beispiel #11
0
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
Beispiel #12
0
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
Beispiel #13
0
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
Beispiel #14
0
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)