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