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
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
|
# Notes for developers and contributors
This is mostly a list of notes that Dejan prepared for me when I
started working on crmsh (me being Kristoffer). I've decided to update
it at least enough to not be completely outdated, so the information
here should be mostly up-to-date for crmsh 2.1.
## data-manifest
This file contains a list of all shared data files to install.
Whenever a file that is to be installed to `/usr/share/crmsh` is added,
for example a cluster script or crmsh template, the `data-manifest`
file needs to be regenerated, by running `./update-data-manifest.sh`.
## Website
To build the website, you will need **Asciidoc**, **Pygments** plus
two special lexers for Pygments installed as a separate module. This
module is included in the source tree for crmsh under `contrib`. To
install the module and build the website, do the following:
```
cd contrib
sudo python setup.py install
cd ..
cd doc/website-v1
make
```
If everything worked out as it should, the website should now be
generated in `doc/website-v1/gen`.
## Test suite
There are two separate test suites for crmsh:
* `test/unittests` - These are unit tests that test small pieces of
code or functionality. To run these tests, run the `test/run` script
from the project root.
* `test/testcases` - These are larger integration tests which require
a Pacemaker installation on the machine where the tests are to
run. Usually, we run these tests using the OBS and the `osc` command
line tool:
1. Check out the crmsh python package to a directory (usually
`~/build-service/network:ha-clustering:Factory/crmsh`)
2. Replace the tarball for crmsh in the OBS project with an archive
built from the current source tree. Replace the version number with
whatever version is the current one on OBS:
git archive --format=tar --prefix=crmsh-2.3.0+git.1470991992.7deaa3a/ -o <tmpdir>/crmsh-2.3.0+git.1470991992.7deaa3a.tar HEAD
bzip2 <tmpdir>/crmsh-2.3.0+git.1470991992.7deaa3a.tar
cp <tmpdir>/crmsh-2.3.0+git.1470991992.7deaa3a.tar.bz2 ~/build-service/network:ha-clustering:Factory/crmsh/crmsh-2.3.0+git.1470991992.7deaa3a.tar.bz2
3. Build the rpm package for crmsh with the `with_regression_tests`
flag set to 1:
cd ~/build-service/network:ha-clustering:Factory/crmsh
osc build -d --no-verify --release=1 --define with_regression_tests 1 openSUSE_Tumbleweed x86_64 crmsh.spec
To simplify this process, there is a utility called `obs` which can be
downloaded here: https://github.com/krig/obs-scripts
Using the `obs` script, the above is reduced to calling `obs test
factory`, given an appropriate `obs.conf` file. See the README in the
obs-scripts project for more details on using `obs`.
## Modules
This is the list of all modules including short descriptions.
- `crm`
The program. Tries to detect incompatible python versions or a
missing crmsh module, and report an understandable error message
in either case.
- `crmsh/main.py`
This is where execution really starts. Verifies the environment
and detects the pacemaker version.
- `crmsh/config.py`
Reads the `crm.conf` configuration file and tries to detect basic
information about where pacemaker is located etc. Some magic is
used to generate an object hierarchy based on the configuration,
so that the rest of the code can access configuration variables
directly.
- `crmsh/constants.py`
Various hard-coded constants. Many of these should probably be
read from pacemaker metadata for better compatibility across
different versions.
- `crmsh/ui_*.py`
The UI context (`ui_context.py`) parses the input command and
keeps track of which is the current level in the UI. `ui_root.py`
is the root of the UI hierarchy.
- `crmsh/help.py`
Reads help from a text file and presents parts of it in
response to the help command. The text file has special
anchors to demarcate help topics and command help text.
- `doc/crm.8.adoc`
Online help in asciidoc format. Several help topics (search
for +[[topic_+) and command reference (search for
+[[cmdhelp_+). Every user interface change needs to be
reflected here. _Actually, every user interface change has to
start here_. A source for the +crm(8)+ man page too.
- `crmsh/cibconfig.py`
Configuration (CIB) manager. Implements the configure level.
The bigest and the most complex part. There are three major
classes:
- +CibFactory+: operations on the CIB or parts of it.
- +CibObject+: every CIB element is implemented in a
subclass of +CibObject+. The configuration consists of a
set of +CibObject+ instances (subclassed, e.g. +CibNode+ or
+CibPrimitive+).
- +CibObjectSet+: enables operations on sets of CIB
elements. Two subclasses with CLI and XML presentations
of cib elements. Most operations are going via these
subclasses (+show+, +edit+, +save+, +filter+).
- `crmsh/scripts.py`
Implements the cluster scripts. Reads multiple kinds of script
definition languages including the XML wizard format used by
Hawk.
- `crmsh/handles.py`
A primitive handlebar-style templating language used in cluster
scripts.
- `crmsh/idmgmt.py`
CIB id management. Guarantees that all ids are unique.
A helper for CibFactory.
- `crmsh/parse.py`
Parses CLI -> XML.
- `crmsh/cliformat.py`
Parses XML -> CLI.
Not as cleanly separated as the CLI parser, mostly a set of
functions called from `cibconfig.py`.
- `crmsh/clidisplay.py`, `crmsh/term.py`
Applies colors to terminal output.
- `crmsh/crm_gv.py`
Interface to GraphViz. Generates graph specs for dotty(1).
- `crmsh/cibstatus.py`
CIB status section editor and manipulator (cibstatus
level). Interface to crm_simulate.
- `crmsh/ra.py`
Resource agents interface.
- `crmsh/rsctest.py`
Resource tester (configure rsctest command).
- `crmsh/history.py`
Cluster history. Interface to logs and other artifacts left
on disk by the cluster.
- `crmsh/log_patterns.py`, `log_patterns_118.py`
Pacemaker subsystems' log patterns. For versions earlier than
1.1.8 and the latter.
- `crmsh/schema.py`, `pacemaker.py`
Support for pacemaker RNG schema.
- `crmsh/cache.py`
A very rudimentary cache implementation. Used to cache
results of expensive operations (i.e. ra meta).
- `crmsh/crm_pssh.py`
Interface to the parallax library for remote SSH commands.
- `crmsh/corosync.py`
Parse and edit the `corosync.conf` configuration file.
- `crmsh/msg.py`
Messages for users. Can count lines and include line
numbers. Needs refinement.
- `crmsh/utils.py`
A bag of useful functions. Needs more order.
- `crmsh/xmlutil.py`
A bag of useful XML functions. Needs more order.
## Code improvements / TODO
These are some thoughts on how to improve maintainability and
make crmsh nicer. Mostly for people looking at the code, the
users shouldn't notice much (or any) difference.
Everybody's invited to comment and make further suggestions, in
particular experienced pythonistas.
### Syntax bug with automatic constraint handling
See issue on github https://github.com/ClusterLabs/crmsh/issues/140 .
The problem is the sequence of modifications: crmsh tries to be too
smart and changes the constraint which refers to all members of the
group so that it now refers to the group. But when the group is
then deleted, the constraint is also deleted.
### Rewrite the hb_report script completely in Python
Right now, the `hb_report` script is written in bash. This means it
has some duplicated code, for example finding pacemaker binaries,
with crmsh. It also means that it can be difficult to debug and
maintain. It would be better if it was completely implemented in
Python.
### Python 3 compatibility
The code is currently only compatible with Python 2.6+. We will need
to port crmsh to Python 3 eventually. The best solution for this is
probably using the six python library which enables code which is
both Python 2 and Python 3-compatible.
### Validate more using pacemaker schema
- We have the pacemaker CIB schema available (see schema.py),
however using it is difficult and so it is not used in enough
places.
### Investigate switching to python-prompt-toolkit
Either switch crmsh over to using the prompt toolkit for
implementing the interactive mode, or at least look at it
to see what ideas we can lift.
https://github.com/jonathanslenders/python-prompt-toolkit
### History transition should be able to save the graph to a file
See https://github.com/ClusterLabs/crmsh/issues/98
### Add support for ordering attribute on resource sets
See https://github.com/ClusterLabs/crmsh/issues/84
### Better version detection
Be better at detecting and handling the Pacemaker version.
Ensure backwards compatibility, for example with old vs.
new ACL command syntax.
### Syntax highlighting
- syntax highlighting is done before producing output, which
is basically wrong and makes code convoluted; it further
makes extra processing more difficult
- use a python library (pygments seems to be the best
candidate); that should also allow other output formats
(not only terminal)
- how to extend pygments to understand a new language? it'd
be good to be able to get this _without_ pushing the parser
upstream (that would take _long_ to propagate to
distributions)
### CibFactory is huge
- this is a single central CIB class, it'd be good to have it
split into several smaller classes (how?)
### The element create/update procedure is complex
- not sure how to improve this
### Bad namespace separation
- xmlutil and utils are just a loose collection of functions,
need to be organized better (get rid of 'from xyz import *')
|