-
Notifications
You must be signed in to change notification settings - Fork 9
/
README.API
238 lines (178 loc) · 5.37 KB
/
README.API
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
otopi -- API
============
The installer is fully pluggable framework, plugins are assigned
to groups, each groups can be loaded at startup.
For example two plugins within group1:
/usr/share/otopi/plugins/group1/plugin1
/usr/share/otopi/plugins/group1/plugin2
Groups are loaded by looking at the BASE/pluginGroups environment
variable.
At the core of the implementation there is the 'environment'.
The environment is the state of the installation, all plugins
have access to the environment. Environment can be loaded at
initialization from configuration file, and can be examine using
command-line triggered by the DIALOG/customization environment
variable.
Plugins entries are loaded and sorted by Stages, and within each
stage by priority, order by before and after hints. Then entries
are called one by one by their order.
Plugin class inherit from PluginBase and uses @plugin.event
decoration in order to declare entry points (see example bellow).
Plugins are loaded per python module, using the createPlugins()
method.
Please notice that installer change working directory to '/',
every file that is being access that has the potential to be
relative should be resolved using plugin.resolveFile() function.
NOTICE: Boot exceptions (ImportError and such) are not printed, in
order to see then set OTOPI_DEBUG=1 environment before
running the script.
PRIORITIES
----------
PRIORITY_FIRST
PRIORITY_HIGH
PRIORITY_MEDIUM
PRIORITY_DEFAULT
PRIORITY_POST
PRIORITY_LOW
PRIORITY_LAST
STAGES
------
By order.
STAGE_BOOT
Use to setup boot environment.
Usually avoid.
STAGE_INIT
Use this stage to initialize components.
Also initialize key environment.
Use only setdefault() to set environment.
STAGE_SETUP
Use this stage to setup environment.
Use only setdefault() to set environment.
STAGE_INTERNAL_PACKAGES
Install local packages required for setup.
No rollback for these packages.
STAGE_PROGRAMS
Detect local programs.
STAGE_LATE_SETUP
Late setup actions.
STAGE_CUSTOMIZATION
Customization phase for dialog, avoid.
STAGE_VALIDATION
Perform any process validations here.
STAGE_TRANSACTION_BEGIN
Transaction begins here, you can add elements
before, at this point these will be prepared.
STAGE_EARLY_MISC
Early misc actions.
STAGE_PACKAGES
Package installation.
STAGE_MISC
Misc actions go to here.
STAGE_TRANSACTION_END
Transaction commit.
STAGE_CLOSEUP
Non destructive actions.
Executed if no error.
STAGE_CLEANUP
Clean up.
Executed always.
STAGE_PRE_TERMINATE
Termination dialog, avoid.
STAGE_TERMINATE
Termination, avoid.
STAGE_REBOOT
Reboot, avoid.
BUNDLE
------
An installer bundle allows transferring of an installer to
remote machine via ssh and executing it directly with no
dependencies other than python.
To create a bundle use the otopi-bundle script
located at the datadir of the package.
Usage:
otopi-bundle gettext_domains target [root]
After doing so symlink any of the required plugins, and add
installation script such as the following:
#!/bin/sh
exec "$(dirname "$0")/otopi" "APPEND:BASE/pluginGroups=str:my-group $*"
Bundle can be executed using the following command, provided initial script is called
setup:
bundledir=LOCATION
( tar -hc -C "${bundledir}" . && cat) | \
ssh "${HOST}" '( \
dest="$(mktemp -t install-XXXXXXXXXX)"; \
trap "chmod -R u+rwX \"${dest}\" > /dev/null 2>&1; \
rm -fr \"${dest}\" > /dev/null 2>&1" 0;
rm -fr "${dest}" && mkdir -p "${dest}" && \
tar -C "${dest}" -x && "${dest}"/setup \
)'
EXAMPLE
-------
We write example plugin within group1.
/usr/share/otopi/plugins/group1/example1
---
__init__.py
---
from otopi import util
from . import example1
@util.export
def createPlugins(context):
example1.Plugin(context=context)
---
---
example1.py
---
import gettext
_ = lambda m: gettext.dgettext(message=m, domain='otopi')
from otopi import constants
from otopi import util
from otopi import plugin
from otopi import filetransaction
@util.export
class Plugin(plugin.PluginBase):
def __init__(self, context):
super(Plugin, self).__init__(context=context)
#
# Register init stage at default priority.
#
@plugin.event(
stage=plugin.Stages.STAGE_INIT,
)
def _init(self):
#
# Use only setdefault to keep existing environment
#
self.environment.setdefault('var1', False)
#
# perform validation, last chance before changes.
#
@plugin.event(
stage=plugin.Stages.STAGE_VALIDATION,
priority=plugin.Stages.PRIORITY_LOW,
)
def _validate(self):
if not self._distribution in ('redhat', 'fedora'):
raise RuntimeError(
_('Unsupported distribution for iptables plugin')
)
#
# perform some action.
#
@plugin.event(
stage=plugin.Stages.STAGE_MISC,
condition=lambda self: self.environment['var1'],
)
def _store_iptables(self):
self.environment[constants.CoreEnv.TRANSACTION].append(
filetransaction.FileTransaction(
name='/etc/example1.conf',
content=(
'hello',
'world',
)
)
)
@util.export
def createPlugins(context):
Plugin(context=context)
---