1FirstAidKit Plugins(1)      General Commands Manual     FirstAidKit Plugins(1)
2
3
4

NAME firstaidkit-plugins

6
7

DESCRIPTION

9       This man page tries to describe the inner workings of the plugin system
10       for FirstAidKit.  It also contains  useful  information  to  develop  a
11       plugin for firstaidkit.
12
13

Plugin Suffixes

15       All  plugins belong to configured plugin directory. Recognized suffixes
16       are:    .py,     .pyc,     placed     in     a     default     location
17       (/usr/{lib,lib64}/firstaidkit-plugins).
18
19

Plugin Model

21       The building blocks of the plugins are functions and flows.  A function
22       is a certain action that is taken inside the plugin.   This  action  is
23       more  or  less independent from the rest of the plugin actions.  Things
24       like fix, backup, restore... qualify as actions/functions.   This  does
25       not  mean that functions do not relate to each other.  They are related
26       by using the flow data structure (The data structure used for the flows
27       is a dictionary).
28
29       A  flow  is  the  organization of functions in a directional graph that
30       defines the "flow" of functions.  Understand flow here as the order  in
31       which  functions are executed when the plugin is used.  This order/flow
32       is specified using the function names, their return codes and the  flow
33       data  structure.   All this is contained within a dictionary (The Exam‐
34       ples Sections shows how this is done.)
35
36

Coding a Plugin

38       1. Class methods and class attributes:
39              The main plugin class has some  class  methods  and  some  class
40              attributes.  These  elements are used to describe the plugin and
41              are used without actually using a instance of the plugin.   This
42              is  important  because  we  do  not want to execute the __init__
43              function and cause lots of unnecessary  stuff to go into  memory
44              when we are querying for plugin basic information.
45
46              The  class attributes are: name, version, author and the defined
47              flows.  For the information to be  displayed  correctly  to  the
48              user  the  plugin  developer must include at least name, version
49              and author as class attributes.   The  flows  attribute  is  not
50              necesarry  if custom flows aren't present.  If the plugin devel‐
51              oper is planning to create a custom flows he  must  declare  the
52              flows dictionary for your plugin.  More information of the class
53              attributes in the "Class Attribute" section.
54
55              The class methods are: info() (returns  the  name,  version  and
56              author   in  a tuple), getDeps() (returns list of required flags
57              for automated mode) and getFlows() (returns a list  of  possible
58              flow  names  that the plugin can execute).  The plugin developer
59              doesn't really have to worry  about  the  methods  as  they  are
60              defined  in  the  father  class Plugin.  Section "Class Methods"
61              gives more infor on each one.
62
63
64       2. Plugin dependencies
65              You can also specify flags, which are required to  be  satisfied
66              before  the automated mode can use this plugin. The requirements
67              should be returned as python set of  strings  by  the  getDeps()
68              class  method.   Setting  flags  is also easy. Just use the pro‐
69              vide() method common to all plugins.
70
71              There is also getConflicts() method, with the very  same  behav‐
72              iour as getDeps(), but with the opposite meaning. Meaning, it is
73              a set of flags, which have to NOT be satisfied for the plugin to
74              be processed.
75
76
77       3. Default functions:
78              See section "Common stuff for plugins"
79
80
81       4. Flows:
82              There are two basic flows hardcoded into the system. These flows
83              may *not* be used by  plugin  developers.   The  first  flow  is
84              called  diagnose:  the  intention  with this flow is to give the
85              user information of the state of the system that the  plugin  is
86              analysing.   This  flow  is intended to give general information
87              and needs to be very fast.  If the plugin needs to do some  more
88              detailed  diagnose  analysis,  we suggest to create another flow
89              called  'detailedAnalysis'.   When  coding  the  diagnose  flow,
90              remember  that  it  will  be executed when the user asks for the
91              information of *all* the plugins.  The diagnose flow calls  only
92              the  prepare,  diagnose  and  clean  tasks.   The second flow is
93              called fix:  the intention with this flow  is  to  actually  fix
94              whatever  is  wrong with the system.  We suggest this flow to be
95              as thorough as it needs to be.  If there is more than one way to
96              fix  the problem, this flow would be the easiest one (the plugin
97              developer can create other flow for the more complex ones).  For
98              this  flow to be successfull the prepare, diagnose, backup, fix,
99              restore and clean tasks must be present in the plugin.  for more
100              info  see section "Common stuff for plugins".  Finally, to add a
101              custom flow the plugin developer must  initialize  a  dictionary
102              named  flows  using  flows = Flow.init(parent class) and fill it
103              with the custom flows.  For more info on adding  flows  see  the
104              "Examples" section.
105
106
107       5. self._result and self._state
108              These  are  the  two  variables  that define the location of the
109              plugin inside the flow dictionary.  In each function,  after  it
110              has  done its intended action, the self._result variable must be
111              changed to a correct value.  Think of the  self._result  as  the
112              return  value  of  each  task.  Before any task is executed, the
113              self._result is set to None, so we can handle exceptions as spe‐
114              cial  direction  in  flows.  The  self._result  usually  takes a
115              firstaidkit return value (classes that define the return value).
116
117              Firstaidkit comes with predifined return value classes  but  the
118              plugin  developer may define his own return classes.  One reason
119              to define a custom return class is  to  have  actual  values  be
120              passed  between  tasks (this is not yet implemented as the tasks
121              are in the same class and can interchange values using the class
122              variable).   The  self._state  is the name of the task where the
123              plugin is at a certain moment.  The self._state variable  is  of
124              no real use to the plugin developer as he must know in what task
125              the plugin is in.
126
127
128       6. get_plugin()
129              Each plugin must define a get_plugin  function.   This  function
130              must  return the main class of the plugin.  This is used to take
131              out info from the plugin, and to instantiate it.  If  in  doubt,
132              take  a  look  at  the  sample  plugins  that  come with the man
133              FirstAidKit code base. They can give you a pretty good  idea  of
134              what to do when using a  module, file ...
135
136
137       7. return values:
138              For  each  function you code in a plugin you must use predefined
139              return classes.  It is  necessary  to  have  the  extra  wrapper
140              because  the  python native types can get messy (1==True).  Just
141              use the ones provided by  the plugin system, or create your own.
142
143

Common stuff

145       Each plugin, by default, should exports some steps. The mandatory  ones
146       are:
147
148       prepare
149              Initialize plugin, get environment.
150
151       backup Backup  everything  we could touch in this plugin. (Also see the
152              firstaidkit-backup manpage)
153
154       diagnose
155              Get info about the investigated system and determine  where  the
156              problems are.
157
158       fix    Auto fix the errors from diagnose step.
159
160       restore
161              Restore system from backup.
162
163       clean  Destroy the plugin, cleanup.
164
165       The plugin should ensure that the calling order is correct and the sys‐
166       tem cannot end in some indeterminate state.
167
168

Python Modules:

170       A plugin for the FirstAidKit must inherit from the pyfirstaidkit.Plugin
171       class.  It  must  also  implement  the  mandatory  plugin  steps.   The
172       pyfirstaidkit.Plugin parent will provide a default flow that  will  use
173       the  functions  defined  by  the  plugin  developer.  Moreover, for the
174       mandatory steps, the plugin developer must guarantee that the  function
175       will  return  a  valid return  class (see "Return Values section").  In
176       other words, the function  must  return  one  of  the  possible  return
177       classes  included  in  the  default  flow.   Each  plugin must have the
178       get_plugin method in order to actually be seen by the firstaidkit back‐
179       end.
180
181

Class Attributes:

183       This  is how the diagnose and fix flows are coded in the backend plugin
184       system.
185        flows["diagnose"] = Flow({
186          initial      : {Return: "prepare"},
187          "prepare"    : {ReturnSuccess: "diagnose", None: "clean"},
188          "diagnose"    :  {ReturnSuccess:  "clean",  ReturnFailure:  "clean",
189       None: "clean"},
190          "clean"       :  {ReturnSuccess:  final, ReturnFailure: final, None:
191       final}
192          }, description="The default, fully automated, diagnose sequence")
193
194        flows["fix"] = Flow({
195          initial      : {Return: "prepare"},
196          "prepare"    : {ReturnSuccess: "diagnose", None: "clean"},
197          "diagnose"   :  {ReturnSuccess:  "clean",  ReturnFailure:  "backup",
198       None: "clean"},
199          "backup"      : {ReturnSuccess: "fix", ReturnFailure: "clean", None:
200       "clean"},
201          "fix"        : {ReturnSuccess:  "clean",  ReturnFailure:  "restore",
202       None: "restore"},
203          "restore"     :  {ReturnSuccess:  "clean",  ReturnFailure:  "clean",
204       None: "clean"},
205          "clean"      : {ReturnSuccess: final,  ReturnFailure:  final,  None:
206       final}
207          }, description="The default, fully automated, fixing sequence")
208
209       Other  important  class  attributes  are:  name,  version,  author  and
210       description.  They are selfexplanatory.
211
212
213

Class Methods:

215       pyfirstaidkit.Plugin defines:
216
217       nextstep()
218              This is used to return the next function  that  should  be  exe‐
219              cuted.   __iter__() is not used because there is no control over
220              __iter__() in an iteration.  nextstep() allows us  execution  of
221              the  flow without the need for an iteration.  However the itera‐
222              tion is present in the class and can be used accordingly.
223
224       __iter__() and next()
225              Iterator protocol, works in the same way as nextstep()  but  end
226              with StopIteration exception
227
228       actions()
229              Returns list of available step names
230
231       call(step)
232              Calls one specific step identified by name
233
234       info() Returns  tuple  of  strings defined as (name of plugin, version,
235              author)
236
237       changeFlow()
238              Allows the caller to change to some other flow  defined  in  the
239              plugin.
240
241       getFlows()
242              Returns  all the possible flows that the plugin supports. And of
243              course the steps itself. They are defined as  methods  with  the
244              same names as used in actions().
245
246       getDeps()
247              Returns  list  of  flags  which  are required for this plugin to
248              operate in automated mode.
249
250       provide(flag)
251              Adds flag into the pool of satisfied flags.
252
253       require(flag)
254              Queries the state of flag. Returns True if set, False otherwise.
255
256

Arbitrary Executable Modules

258       The current approach is to create a wrapper python plugin, which  holds
259       the meta data and calls the binaries as necessary (see the examples).
260
261

Examples

263       Flow description (Example 1):
264              Consider the following flow and its dictionary:
265                  start->fix->end
266                  dict = { start:fix,
267                           fix:end
268                         }
269
270
271       Flow description (Example 2):
272              Consider the following flow and its dictionary:
273                                 ,>end
274                  start->diagnose
275                                 `>fix->end
276                  dict = { start:diagnose,
277                           diagnose:{"goodSys":end,"badSys":fix},
278                           fix:end
279                         }
280
281              This  flow  has  a  conditional after the diagnose function.  If
282              diagnose results in a corrupt state  of  the  system,  then  the
283              plugin  proceeds   with fix.  If all is good in the system, then
284              the flow end.  Note that the next step in the diagnose  case  is
285              defined buy whatever diagnose returned.
286
287
288       Adding a flow (Example 3):
289              class MyPlugin(Plugin):
290                  flows = Flow.init(Plugin)
291                  flows["myflow"] = Flow({flow rules}, description="")
292
293

SEE ALSO

295       firstaidkit-reporting manpage firstaidkit-backup manpage http://fedora
296       hosted.org/firstaidkit
297
298

AUTHORS

300       Martin Sivak <msivak@redhat.com> Joel Granados <jgranado@redhat.com>
301
302

BUGS

304       Please   search/report   bugs   at    http://fedorahosted.org/firstaid
305       kit/newticket
306
307
308
309                                                        FirstAidKit Plugins(1)
Impressum