Plugins

From RackTables Wiki
Revision as of 09:16, 17 February 2016 by Infrastation (talk | contribs) (add a warning)
Jump to navigation Jump to search

Warning






This page is a part of work in progress, it documents a feature that is not yet in RackTables source code.






Overview

Plugins provide the ability to add functionality to RackTables and, in some cases, override existing behavior. See the racktables-contribs repository for user-submitted plugins.

Note that this guide details features that may or may not be included in a future release.

States

A plugin may be in one of three states.

  • Not installed - it exists in the plugins directory, but hasn't been installed yet
  • Enabled - it has been installed and is active
  • Disabled - it has been installed and was subsequently disabled

Administration

To install a plugin, first copy it to the "plugins" directory. Then visit the Configuration -> Plugins page and click the Edit tab. The new plugin should be listed with a state of "Not installed". Click the Install icon.

To upgrade a plugin, first backup the appropriate "plugins" sub-directory. To be safe, it's also a good idea to backup your entire database. Afterwards, copy over the new version into the "plugins" directory. When you visit the Edit tab of the Configuration -> Plugins page, you should see a variance in the Code Version and DB Version columns. Click the Upgrade icon.

Writing a Plugin

The old procedure involves placing a PHP file in the "plugins" directory of your RackTables installation. That method has limited functionality and may be deprecated at a later date.

A new plugin architecture was introduced in version 0.20.11. It includes the ability to install, uninstall, enable and disable plugins from the web interface. It is assumed that each plugin resides in its own directory within the main "plugins" directory, and that each plugin contains a "plugin.php" file which includes certain functions. The design was inspired by Cacti's plugin architecture.

Files

Each plugin is expected to contain certain files. While the only required file is "plugin.php", it is recommended that you include all mentioned files, especially if you intend to publish it for others.

  • README - Provide a general description. If you expect the plugin to be accepted into the racktables-contribs repo, use the Markdown format.
  • ChangeLog - Document changes made to each revision.
  • LICENSE

Functions

Name Returns Description
plugin_PLUGINNAME_info array Array contains 'name', 'longname', 'version' & 'home_url'
plugin_PLUGINNAME_init void Initialize the plugin. Register pages, tabs, triggers, handlers, etc.
plugin_PLUGINNAME_install boolean Make any necessary modifications (create tables, create Config settings, etc.)
plugin_PLUGINNAME_uninstall boolean Make any necessary modifications (drop tables, delete Config settings, etc.)
plugin_PLUGINNAME_upgrade boolean Make any necessary modifications (alter tables, modify Config settings, etc.)
plugin_PLUGINNAME_HOOKNAME varies Run when called by a system-level function (described below in the Hooks section)

Hooks

There are used in cases where custom functions defined by a plugin should be called at specific times.

Examples:

  • When resetting or deleting an object
  • Resetting the Config settings (Configuration -> User interface)
  • Viewing the Data Integrity report

Hooks are already supported in some functions, such as commitResetObject(). If you need it supported by another function, create a GitHub pull request and it will probably be accepted.

Upgrades

The plugin_PLUGINNAME_upgrade function is mandatory. If this is the first version, or if no upgrade steps are required, simply have the function return TRUE.

There are many cases where upgrades involve adding/modifying/deleting tables, Config settings or other pieces of information. These transitions should be handled by the upgrade function.

Example modeled after the core RackTables upgrader:

function plugin_myplugin_upgrade ()
{
	$db_info = getPlugin ('myplugin');
	$v1 = $db_info['db_version'];
	$code_info = plugin_plugin_info ();
	$v2 = $code_info['version'];
	
	if ($v1 == $v2)
		throw new RackTablesError ('Versions are identical', RackTablesError::INTERNAL);

	// find the upgrade path to be taken
	$versionhistory = array
	(
		'1.0',
		'2.0',
		'3.0'
	);
	$skip = TRUE;
	$path = NULL;
	foreach ($versionhistory as $v)
	{
		if ($skip and $v == $v1)
		{
			$skip = FALSE;
			$path = array();
			continue;
		}
		if ($skip)
			continue;
		$path[] = $v;
		if ($v == $v2)
			break;
	}
	if ($path === NULL or ! count ($path))
		throw new RackTablesError ('Unable to determine upgrade path', RackTablesError::INTERNAL);

	// build the list of queries to execute
	$queries = array ();
	foreach ($path as $batchid)
	{
		switch ($batchid)
		{
			case '2.0':
				// perform some upgrade step here
				$queries[] = "UPDATE Plugin SET version = '2.0' WHERE name = 'myplugin'";
				break;
			case '3.0':
				// perform some upgrade step here
				$queries[] = "UPDATE Plugin SET version = '3.0' WHERE name = 'myplugin'";
				break;
			default:
				throw new RackTablesError ("Preparing to upgrade to $batchid failed", RackTablesError::INTERNAL);
		}
	}

	// execute the queries
	global $dbxlink;
	foreach ($queries as $q)
	{
		try
		{
			$result = $dbxlink->query ($q);
		}
		catch (PDOException $e)
		{
			$errorInfo = $dbxlink->errorInfo();
			throw new RackTablesError ("Query: ${errorInfo[2]}", RackTablesError::INTERNAL);
		}
	}
}