xref: /openbmc/openbmc-test-automation/ffdc/docs/plugin.md (revision 94041a34a992d9b5f6418a43e1cd5273a6d9f9b2)
1### Plugin
2
3Plugin feature for the log collector is to load a user python functions at
4runtime by the engine and execute it.
5
6The design infrastructure allows user to extend or call their existing python
7scripts without needing to expose the implementation. This enriches the log
8collection and mechanize the work flow as per user driven as per their
9requirement,
10
11### Understanding Plugin
12
13The plugin works like any stand-alone piece of python script or library
14function.
15
16The main components in plugin infrastructure are:
17
18- plugin directory
19- plugin directive in YAML
20- plugin parser in the collector engine
21
22### Plugin Directory
23
24Python module script are added or copied to `plugins` directory and the log
25engine loads these plugins during runtime and on demand from the YAML else they
26are not invoked automatically.
27
28Example:
29
30```
31plugins/
32├── foo_func.py
33├── ssh_execution.py
34└── telnet_execution.py
35
36```
37
38### Plugin Template Example
39
40Stand-alone functions: plugins/foo_func.py
41
42```
43# Sample for documentation plugin
44
45def print_vars(var):
46    print(var)
47
48def return_vars():
49    return 1
50```
51
52Class function(s): plugins/plugin_class.py
53
54Example:
55
56```
57class  plugin_class:
58
59    def plugin_print_msg(msg):
60        print(msg)
61```
62
63In YAML plugin, you will need to pass self object as part of the arguments.
64
65Static Class function(s): plugins/plugin_class.py
66
67Example:
68
69```
70class  plugin_class:
71
72    @staticmethod
73    def plugin_print_msg(msg):
74        print(msg)
75```
76
77This is to avoid passing object self in plugin args YAML when calling the class
78function(s). However python class static method has its own limitation, do not
79use unless needed.
80
81You can add your own plugin modules to extend further.
82
83Test your plugin:
84
85```
86python3 plugins/foo_func.py
87```
88
89### YAML Syntax
90
91Plugin function without return statement.
92
93```
94    - plugin:
95        - plugin_name: plugins.foo_func
96        - plugin_function: print_vars
97        - plugin_args:
98            - "Hello plugin"
99```
100
101Plugin function with return statement.
102
103```
104    - plugin:
105        - plugin_name: plugins.foo_func
106        - plugin_function: return_value = func_return_vars
107        - plugin_args:
108```
109
110when the return directive is used by implying "=" , the `return_value` can be
111accessed within the same block by another following plugins by using the
112variable name directly.
113
114Example:
115
116```
117    - plugin:
118        - plugin_name: plugins.foo_func
119        - plugin_function: print_vars
120        - plugin_args:
121            - return_value
122```
123
124To accept multiple return values by using coma "," separated statement
125
126```
127     - plugin_function:  return_value1,return_value2 = print_vars
128```
129
130Accessing a class method:
131
132The rule remains same as other functions, however for a class object plugin
133syntax
134
135```
136        - plugin_name: plugins.<file_name>.<class_object>
137        - plugin_function: <class_method>
138```
139
140Example: (from the class example previously mentioned)
141
142```
143    - plugin:
144        - plugin_name: plugins.plugin_class.plugin_class
145        - plugin_function: plugin_print_msg
146        - plugin_args:
147            - self
148            - "Hello Plugin call"
149```
150
151### Plugin execution output for sample
152
153```
154        [PLUGIN-START]
155        Call func: plugin.foo_func.print_vars("Hello plugin")
156        Hello plugin
157        return: None
158        [PLUGIN-END]
159
160        [PLUGIN-START]
161        Call func: plugin.foo_func.return_vars()
162        return: 1
163        [PLUGIN-END]
164```
165
166### Plugin FILES Directive
167
168Rules:
169
170If in the YAML with Plugin module called and corresponding file order
171
172plugin response if there is any will be written to named file, if
173
174```
175    FILES:
176        -'name_file.txt'
177```
178
179Else, plugin response will be skipped and not written to any file.
180
181```
182    FILES:
183        - None
184```
185
186### Plugin ERROR Directive
187
188Error directive on plugin supported
189
190- exit_on_error : If there was an error in a plugin stacked, the subsequent
191  plugin would not be executed if this is declared.
192- continue_on_error : If there was an error and user declare this directive,
193  then the plugin block will continue to execute.
194
195Example:
196
197```
198    - plugin:
199        - plugin_name: plugins.foo_func
200        - plugin_function: print_vars
201        - plugin_args:
202            - return_value
203        - plugin_error: exit_on_error
204```
205
206This error directive would come into force only if there is an error detected by
207the plugin during execution and not the error response returned from the plugin
208function in general.
209
210To go further, there is another directive for plugin to check if the plugin
211function returned a valid data or not.
212
213The directive statement is
214
215```
216    - plugin_expects_return: <data type>
217```
218
219Example:
220
221```
222    - plugin:
223      - plugin_name: plugin.ssh_execution
224      - plugin_function: ssh_execute_cmd
225      - plugin_args:
226        - ${hostname}
227        - ${username}
228        - ${password}
229        - cat /etc/os-release
230        - 3
231      - plugin_expects_return: str
232```
233
234The above example states that, the plugin function is expecting a return data of
235type string. If the plugin function does not return data or the returned data is
236not of type string, then it would throw an error and sets the plugin_error flag
237exit_on_error as True.
238
239This directive helps in validating plugin return data to handle different plugin
240blocks stacked together which are depending on the success of the previous
241plugin execution to do further processing correctly.
242