Changes from Version 1 of WritingYumPlugins

Show
Ignore:
Author:
skvidal (IP: 24.211.246.61)
Timestamp:
10/23/08 07:01:37 (9 years ago)
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • WritingYumPlugins

    v0 v1  
     1== Introduction == 
     2Yum has a simple but powerful plugin architecture which allows external modules to add new features and/or modify Yum's behaviour. Yum plugins are Python modules (.py files) which are loaded when Yum starts.   
     3 
     4Plugins were created partially as a place to put functionality that was seen as either less common or undesirable for the main yum package.  Functionality in plugins will generally not be moved or included in the core yum package. 
     5 
     6This document explains how to create plugins for Yum. See the {{{yum(8)}}} and {{{yum.conf(5)}}} man pages for information on how to install and configure pre-existing plugins. 
     7 
     8 
     9== A Basic Plugin == 
     10The following example shows a minimal Yum plugin:: 
     11{{{#!python numbering=off 
     12from yum.plugins import PluginYumExit, TYPE_CORE, TYPE_INTERACTIVE 
     13 
     14requires_api_version = '2.3' 
     15plugin_type = (TYPE_CORE, TYPE_INTERACTIVE) 
     16 
     17def init_hook(conduit): 
     18    conduit.info(2, 'Hello world') 
     19 
     20def postreposetup_hook(conduit): 
     21    raise PluginYumExit('Goodbye') 
     22}}} 
     23 
     24This plugin will display "Hello world" as it loads and then will cause Yum to quit with a "Goodbye" message once it has finished initialising its repositories. 
     25 
     26== Slots and Hooks == 
     27Plugins integrate with Yum by registering a 'hook' function that corresponds to a given 'slot'. A slot is simply a point in Yum's execution. All plugin hook functions for a given slot are called as Yum reaches that slot. 
     28 
     29Registration of hook functions is automatic. The plugin module is inspected for functions named {{{<slotname>_hook}}}. If a function matching a valid slot name is found then that function is automatically registered as a hook function. 
     30 
     31Hook functions all take one argument, for a {{{conduit}}} instance. Conduits are explained below. 
     32 
     33The following slots exist: 
     34{{{ 
     35config 
     36    Called first as plugins are initialised. Plugins that need to extend Yum's 
     37    configuration files or command line options should do so during this slot. 
     38 
     39postconfig 
     40    Called immediately after Yum's config object is initialised. Useful for  
     41    extending variables or modifying items in the config, for example the  
     42    $ variables that are used in repo configuration.  
     43    Note: Only available in yum 3.1.7 or later 
     44 
     45init 
     46    Called early in Yum's initialisation. May be used for general plugin 
     47    related initialisation. 
     48 
     49predownload 
     50    Called just before Yum starts downloads of packages. Plugins may access 
     51    information about the packages to be downloaded here. 
     52 
     53postdownload 
     54    Called just after Yum finishes package downloads. Plugins may access 
     55    error information about the packages just downloaded. 
     56 
     57prereposetup 
     58    Called just before Yum initialises its repository information. 
     59 
     60postreposetup 
     61    Called just after Yum initialises its repository information. 
     62 
     63exclude 
     64    Called after package inclusion and exclusions are processed. Plugins 
     65    may modify package exclusions here. 
     66 
     67preresolve 
     68    Called before Yum begins package resolution. 
     69 
     70postresolve 
     71    Called just after Yum finishes package resolution. 
     72 
     73pretrans 
     74    Called before Yum begins the RPM update transation. 
     75 
     76posttrans 
     77    Called just after Yum has finished the RPM update transation. 
     78 
     79close 
     80    Called as Yum is performing a normal exit. Plugins may wish to 
     81    perform cleanup functions here. 
     82 
     83clean 
     84    Called during Yum's cleanup.  This slot will be executed when Yum  
     85    is run with the parameters 'clean all' or 'clean plugins'. 
     86}}} 
     87 
     88== Conduits == 
     89An object known as a conduit is passed into hook functions when they are called. This object provides methods and attributes that should be used for all interaction that the plugin has with the rest of Yum.  
     90 
     91The conduit varies depending on the plugin slot. Different methods and attributes are available as appropriate for the slot. See the {{{yum.plugins.SLOT_TO_CONDUIT}}} dictionary for details on the conduit class used for a particular slot.  All conduits are subclassed from the {{{PluginConduit}}} class. 
     92 
     93== API Dependencies == 
     94The plugin API and general Yum API are subject to change. For this reason, plugins must state which API they were written for via the {{{requires_api_version}}} attribute. Yum will exit with a useful error if it tries to load the plugin which is not compatible with its API version. 
     95 
     96In general, a plugin author should set {{{requires_api_version}}} to the API version at the time that the plugin is written. The current API version can be found at {{{yum.plugins.API_VERSION}}}.  
     97 
     98The {{{yum.plugins}}} module documents how the API version is incremented and the rules for compatibility tests. 
     99 
     100== Plugin Types == 
     101Plugins must advertise what type of plugin they are via the {{{plugin_type}}} tuple. The advertised type(s) can be used by software using the Yum libraries to control the types of plugins that will be loaded. Yum itself will always load all types of plugins. 
     102 
     103A plugin may have more than one type. Two plugin types currently exist.  
     104 
     105{{{ 
     106TYPE_CORE 
     107    A core plugin modifies Yum's base functionality. For example, a core plugin might modify  
     108    package exclusions, dependency resolving or repository loading. 
     109 
     110TYPE_INTERACTIVE 
     111    An interative plugin may modify Yum's user interface flow. For example, a TYPE_INTERACTIVE  
     112    plugin might terminate Yum early in some conditions or output extra information to the user. 
     113 
     114    In Yum versions 2.6.x and earlier (plugin API version < 2.3) this constant was called  
     115    TYPE_INTERFACE. The purpose of TYPE_INTERFACE is the same as TYPE_INTERACTIVE  
     116    but the meaning of the old name wasn't clear and so it has been deprecated.  
     117}}} 
     118 
     119== Stopping Yum == 
     120A plugin may stop Yum's execution at any point by raising the {{{yum.plugins.PluginYumExit}}} exception. The argument of the exception will be displayed to the user as Yum terminates. 
     121 
     122== Reading Private Plugin Options == 
     123Each plugin has its own configuration file in {{{/etc/yum/pluginconf.d/}}}. These configuration files follow standard INI file conventions like Yum's own configuration files. Arbitrary options can be read from a plugin's configuration file at any time by using the following methods. These are available on any conduit instance: 
     124 
     125{{{#!python numbering=off 
     126    def confString(self, section, opt, default=None) 
     127 
     128    def confInt(self, section, opt, default=None) 
     129 
     130    def confFloat(self, section, opt, default=None) 
     131 
     132    def confBool(self, section, opt, default=None) 
     133}}} 
     134 
     135If the option is missing from the configuration file then the default value passed to method will be returned. See {{{yum.plugins}}} for more documentation on these methods and see the {{{yum(8)}}} and {{{yum.conf(5)}}} man pages for general information on plugin configuration files. 
     136 
     137== Extending Yum's Configuration Options == 
     138 
     139In addition to having their own configuration file, plugins may modify the 
     140options available in Yum's own configuration files. A plugin can add new 
     141options or modify the existing options by modifying the {{{YumConf}}} and 
     142{{{RepoConf}}} classes defined in {{{yum.config}}}.  
     143 
     144The {{{YumConf}}} class defines options that are available in the {{{[main]}}} 
     145section of {{{yum.conf}}}. The {{{RepoConf}}} class defines options that are 
     146available in each repository sections of Yum's configuration file(s). 
     147Modifications to {{{YumConf}}} and {{{RepoConf}}} should occur in the {{{config}}} 
     148slot. 
     149 
     150Here is a simple example of how options can be added to Yum's configuration 
     151files. 
     152 
     153{{{#!python numbering=off 
     154from yum import config 
     155from yum.plugins import TYPE_INTERACTIVE 
     156 
     157requires_api_version = '2.4' 
     158plugin_type = (TYPE_INTERACTIVE,) 
     159 
     160def config_hook(conduit): 
     161    # Add a boolean option to the [main] section 
     162    config.YumConf.enable_foo = config.BoolOption(False) 
     163 
     164    # Add a URL option to repository sections  
     165    config.RepoConf.foo_url = config.UrlOption() 
     166 
     167    # Add an option to to [main] and the repository sections. The 
     168    # repository options will inherit the properties of the [main] option 
     169    # and will use the value from [main] if the option is not specified in 
     170    # the repo section. 
     171    config.YumConf.max_foo = config.IntOption(10) 
     172    config.RepoConf.max_foo = config.Inherit(config.YumConf.max_foo) 
     173 
     174def init_hook(conduit): 
     175    conf = conduit.getConf() 
     176 
     177    # Display the options from the [main] section 
     178    conduit.info(2, "enable_foo = %r" % conf.enable_foo) 
     179    conduit.info(2, "max_foo = %r" % conf.max_foo) 
     180 
     181    # Display the options from the repository sections 
     182    for repo in conduit.getRepos().listEnabled(): 
     183        conduit.info(2, "%s.foo_url = %r" % (repo.id, repo.foo_url)) 
     184        conduit.info(2, "%s.max_foo = %r" % (repo.id, repo.max_foo)) 
     185}}} 
     186 
     187Note how different types of options are defined ({{{IntOption}}}, {{{UrlOption}}}, 
     188{{{BoolOption}}}). A wide variety of option types are available in 
     189{{{yum.config}}}. It is even possible for plugins to define their own option 
     190types by subclassing {{{Option}}} if the existing types aren't sufficient. See 
     191the source code for the {{{yum.config}}} module for further details. 
     192 
     193== Extending Yum's Configuration Options (pre Yum 2.9.x, deprecated) == 
     194In addition to having their own configuration file, plugins may add extra options to Yum's main configuration files. A plugin must register new options in the {{{config}}} slot using the {{{registerOpt()}}} conduit method: 
     195{{{#!python numbering=off 
     196    registerOpt(name, valuetype, where, default) 
     197}}} 
     198where the arguments are... 
     199{{{ 
     200name 
     201    The name of the new option. 
     202 
     203valuetype 
     204    The type of the option. Valid values are PLUG_OPT_STRING, PLUG_OPT_INT, 
     205    PLUG_OPT_FLOAT and PLUG_OPT_BOOL (defined in yum.constants). The value 
     206    returned for the option will be automatically parsed according to the type. 
     207 
     208where 
     209    Defines where the option should be available in configuration files. Valid 
     210    values are:  
     211         
     212        - PLUG_OPT_WHERE_MAIN: the option only exists in the [main] section 
     213        - PLUG_OPT_WHERE_REPO: the option only exists in repository sections 
     214        - PLUG_OPT_WHERE_ALL: the option exists in both [main] and repository 
     215          sections 
     216 
     217default 
     218    The default value returned for the option if it isn't present. 
     219}}} 
     220The option values defined in the {{{[main]}}} section may be read by calling the 
     221{{{getConf()}}} repository method. The options will be available as attributes of the returned object. 
     222 
     223New repository options will be available as attributes of the repository objects returned via the {{{getRepos()}}} conduit method. 
     224 
     225The following example plugin shows how a custom option may be defined and 
     226read: 
     227{{{#!python numbering=off 
     228    from yum.constants import * 
     229    from yum.plugins import TYPE_INTERACTIVE 
     230 
     231    requires_api_version = '2.3' 
     232    plugin_type = (TYPE_INTERACTIVE,) 
     233 
     234    def config_hook(conduit): 
     235        conduit.registerOpt('foo', PLUG_OPT_BOOL, PLUG_OPT_WHERE_ALL, False) 
     236 
     237    def init_hook(conduit): 
     238        conduit.info(2, "[main] foo=%r" % conduit.getConf().foo) 
     239 
     240    def exclude_hook(conduit): 
     241        for repo in conduit.getRepos().listEnabled(): 
     242            conduit.info(2, "[%s] foo=%r" % (repo.id, repo.foo)) 
     243}}} 
     244 
     245== Extending Yum's Command Line Options == 
     246A plugin may add extra command line options to Yum. To do this the plugin 
     247should call the {{{getOptParser()}}} conduit method during the {{{config}}} or 
     248{{{init}}} slot. This will return an {{{OptionParser}}} instance which the plugin 
     249may modify.  See the Python standard library {{{optparse}}} module documentation for information on how to manipulate this object. 
     250 
     251The parsed command line options may be read in any slot after the {{{init}}} 
     252slot. The values returned are as for {{{OptionParser.parse_args()}}}. 
     253 
     254Options added by plugins will show up in Yum's command line help output (ie. 
     255{{{yum --help}}}) 
     256 
     257The following plugin demonstrates the addition of new command line options by adding a {{{--downloadonly}}} option: 
     258{{{#!python numbering=off 
     259    from yum.plugins import PluginYumExit, TYPE_INTERACTIVE 
     260 
     261    requires_api_version = '2.3' 
     262    plugin_type = (TYPE_INTERACTIVE,) 
     263 
     264    def config_hook(conduit): 
     265        parser = conduit.getOptParser() 
     266        parser.add_option('', '--downloadonly', dest='dlonly',  
     267                action='store_true', default=False,  
     268                help="don't update, just download") 
     269 
     270    def postdownload_hook(conduit): 
     271        opts, commands = conduit.getCmdLine() 
     272        if opts.dlonly: 
     273            raise PluginYumExit('exiting because --downloadonly specified ') 
     274}}} 
     275 
     276== More Examples == 
     277The easiest way to get started writing Yum plugins is to look at some examples. 
     278The yum-utils package contains a number of useful plugins which will act as a 
     279useful starting point. The yum-utils git tree can be viewed here: [http://devel.linux.duke.edu/gitweb/?p=yum-utils.git;a=tree] 
     280---- 
     281