Statistics
| Branch: | Tag: | Revision:

root / doc / hooks.sgml @ 2395c322

History | View | Annotate | Download (23.2 kB)

1
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V4.2//EN" [
2
]>
3
  <article class="specification">
4
  <articleinfo>
5
    <title>Ganeti customisation using hooks</title>
6
  </articleinfo>
7
  <para>Documents ganeti version 1.2</para>
8
  <section>
9
    <title>Introduction</title>
10

    
11
    <para>
12
      In order to allow customisation of operations, ganeti will run
13
      scripts under <filename
14
      class="directory">/etc/ganeti/hooks</filename> based on certain
15
      rules.
16
    </para>
17

    
18
      <para>This is similar to the <filename
19
      class="directory">/etc/network/</filename> structure present in
20
      Debian for network interface handling.</para>
21

    
22
    </section>
23

    
24
    <section>
25
      <title>Organisation</title>
26

    
27
      <para>For every operation, two sets of scripts are run:
28

    
29
      <itemizedlist>
30
          <listitem>
31
            <simpara>pre phase (for authorization/checking)</simpara>
32
          </listitem>
33
          <listitem>
34
            <simpara>post phase (for logging)</simpara>
35
          </listitem>
36
        </itemizedlist>
37
      </para>
38

    
39
      <para>Also, for each operation, the scripts are run on one or
40
      more nodes, depending on the operation type.</para>
41

    
42
      <para>Note that, even though we call them scripts, we are
43
      actually talking about any executable.</para>
44

    
45
      <section>
46
        <title><emphasis>pre</emphasis> scripts</title>
47

    
48
        <para>The <emphasis>pre</emphasis> scripts have a definite
49
        target: to check that the operation is allowed given the
50
        site-specific constraints. You could have, for example, a rule
51
        that says every new instance is required to exists in a
52
        database; to implement this, you could write a script that
53
        checks the new instance parameters against your
54
        database.</para>
55

    
56
        <para>The objective of these scripts should be their return
57
        code (zero or non-zero for success and failure). However, if
58
        they modify the environment in any way, they should be
59
        idempotent, as failed executions could be restarted and thus
60
        the script(s) run again with exactly the same
61
        parameters.</para>
62

    
63
      <para>
64
        Note that if a node is unreachable at the time a hooks is run,
65
        this will not be interpreted as a deny for the execution. In
66
        other words, only an actual error returned from a script will
67
        cause abort, and not an unreachable node.
68
      </para>
69

    
70
      <para>
71
        Therefore, if you want to guarantee that a hook script is run
72
        and denies an action, it's best to put it on the master node.
73
      </para>
74

    
75
      </section>
76

    
77
      <section>
78
        <title><emphasis>post</emphasis> scripts</title>
79

    
80
        <para>These scripts should do whatever you need as a reaction
81
        to the completion of an operation. Their return code is not
82
        checked (but logged), and they should not depend on the fact
83
        that the <emphasis>pre</emphasis> scripts have been
84
        run.</para>
85

    
86
      </section>
87

    
88
      <section>
89
        <title>Naming</title>
90

    
91
        <para>The allowed names for the scripts consist of (similar to
92
        <citerefentry> <refentrytitle>run-parts</refentrytitle>
93
        <manvolnum>8</manvolnum> </citerefentry>) upper and lower
94
        case, digits, underscores and hyphens. In other words, the
95
        regexp
96
        <computeroutput>^[a-zA-Z0-9_-]+$</computeroutput>. Also,
97
        non-executable scripts will be ignored.
98
        </para>
99
      </section>
100

    
101
      <section>
102
        <title>Order of execution</title>
103

    
104
        <para>On a single node, the scripts in a directory are run in
105
        lexicographic order (more exactly, the python string
106
        comparison order). It is advisable to implement the usual
107
        <emphasis>NN-name</emphasis> convention where
108
        <emphasis>NN</emphasis> is a two digit number.</para>
109

    
110
        <para>For an operation whose hooks are run on multiple nodes,
111
        there is no specific ordering of nodes with regard to hooks
112
        execution; you should assume that the scripts are run in
113
        parallel on the target nodes (keeping on each node the above
114
        specified ordering).  If you need any kind of inter-node
115
        synchronisation, you have to implement it yourself in the
116
        scripts.</para>
117

    
118
      </section>
119

    
120
      <section>
121
        <title>Execution environment</title>
122

    
123
        <para>The scripts will be run as follows:
124
          <itemizedlist>
125
            <listitem>
126
              <simpara>no command line arguments</simpara>
127
            </listitem>
128
            <listitem>
129
              <simpara>no controlling <acronym>tty</acronym></simpara>
130
            </listitem>
131
            <listitem>
132
              <simpara><varname>stdin</varname> is
133
                actually <filename>/dev/null</filename></simpara>
134
            </listitem>
135
            <listitem>
136
              <simpara><varname>stdout</varname> and
137
                <varname>stderr</varname> are directed to
138
                files</simpara>
139
            </listitem>
140
            <listitem>
141
              <simpara>the <varname>PATH</varname> is reset to
142
                <literal>/sbin:/bin:/usr/sbin:/usr/bin</literal></simpara>
143
            </listitem>
144
            <listitem>
145
              <simpara>the environment is cleared, and only
146
                ganeti-specific variables will be left</simpara>
147
            </listitem>
148
          </itemizedlist>
149

    
150
        </para>
151

    
152
      <para>All informations about the cluster is passed using
153
      environment variables. Different operations will have sligthly
154
      different environments, but most of the variables are
155
      common.</para>
156

    
157
    </section>
158

    
159

    
160
    <section>
161
      <title>Operation list</title>
162
      <table>
163
        <title>Operation list</title>
164
        <tgroup cols="7">
165
          <colspec>
166
          <colspec>
167
          <colspec>
168
          <colspec>
169
          <colspec>
170
          <colspec colname="prehooks">
171
          <colspec colname="posthooks">
172
          <spanspec namest="prehooks" nameend="posthooks"
173
            spanname="bothhooks">
174
          <thead>
175
            <row>
176
              <entry>Operation ID</entry>
177
              <entry>Directory prefix</entry>
178
              <entry>Description</entry>
179
              <entry>Command</entry>
180
              <entry>Supported env. variables</entry>
181
              <entry><emphasis>pre</emphasis> hooks</entry>
182
              <entry><emphasis>post</emphasis> hooks</entry>
183
            </row>
184
          </thead>
185
          <tbody>
186
            <row>
187
              <entry>OP_INIT_CLUSTER</entry>
188
              <entry><filename class="directory">cluster-init</filename></entry>
189
              <entry>Initialises the cluster</entry>
190
              <entry><computeroutput>gnt-cluster init</computeroutput></entry>
191
              <entry><constant>CLUSTER</constant>, <constant>MASTER</constant></entry>
192
              <entry spanname="bothhooks">master node, cluster name</entry>
193
            </row>
194
            <row>
195
              <entry>OP_MASTER_FAILOVER</entry>
196
              <entry><filename class="directory">master-failover</filename></entry>
197
              <entry>Changes the master</entry>
198
              <entry><computeroutput>gnt-cluster master-failover</computeroutput></entry>
199
              <entry><constant>OLD_MASTER</constant>, <constant>NEW_MASTER</constant></entry>
200
              <entry>the new master</entry>
201
              <entry>all nodes</entry>
202
            </row>
203
            <row>
204
              <entry>OP_ADD_NODE</entry>
205
              <entry><filename class="directory">node-add</filename></entry>
206
              <entry>Adds a new node to the cluster</entry>
207
              <entry><computeroutput>gnt-node add</computeroutput></entry>
208
              <entry><constant>NODE_NAME</constant>, <constant>NODE_PIP</constant>, <constant>NODE_SIP</constant></entry>
209
              <entry>all existing nodes</entry>
210
              <entry>all existing nodes plus the new node</entry>
211
            </row>
212
            <row>
213
              <entry>OP_REMOVE_NODE</entry>
214
              <entry><filename class="directory">node-remove</filename></entry>
215
              <entry>Removes a node from the cluster</entry>
216
              <entry><computeroutput>gnt-node remove</computeroutput></entry>
217
              <entry><constant>NODE_NAME</constant></entry>
218
              <entry spanname="bothhooks">all existing nodes except the removed node</entry>
219
            </row>
220
            <row>
221
              <entry>OP_INSTANCE_ADD</entry>
222
              <entry><filename class="directory">instance-add</filename></entry>
223
              <entry>Creates a new instance</entry>
224
              <entry><computeroutput>gnt-instance add</computeroutput></entry>
225
              <entry><constant>INSTANCE_NAME</constant>, <constant>INSTANCE_PRIMARY</constant>, <constant>INSTANCE_SECONDARIES</constant>, <constant>DISK_TEMPLATE</constant>, <constant>MEM_SIZE</constant>, <constant>DISK_SIZE</constant>, <constant>SWAP_SIZE</constant>, <constant>VCPUS</constant>, <constant>INSTANCE_IP</constant>, <constant>INSTANCE_ADD_MODE</constant>, <constant>SRC_NODE</constant>, <constant>SRC_PATH</constant>, <constant>SRC_IMAGE</constant></entry>
226
              <entry spanname="bothhooks" morerows="4">master node, primary and
227
                   secondary nodes</entry>
228
            </row>
229
            <row>
230
              <entry>OP_BACKUP_EXPORT</entry>
231
              <entry><filename class="directory">instance-export</filename></entry>
232
              <entry>Export the instance</entry>
233
              <entry><computeroutput>gnt-backup export</computeroutput></entry>
234
              <entry><constant>INSTANCE_NAME</constant>, <constant>EXPORT_NODE</constant>, <constant>EXPORT_DO_SHUTDOWN</constant></entry>
235
            </row>
236
            <row>
237
              <entry>OP_INSTANCE_START</entry>
238
              <entry><filename class="directory">instance-start</filename></entry>
239
              <entry>Starts an instance</entry>
240
              <entry><computeroutput>gnt-instance start</computeroutput></entry>
241
              <entry><constant>INSTANCE_NAME</constant>, <constant>INSTANCE_PRIMARY</constant>, <constant>INSTANCE_SECONDARIES</constant>, <constant>FORCE</constant></entry>
242
            </row>
243
            <row>
244
              <entry>OP_INSTANCE_SHUTDOWN</entry>
245
              <entry><filename class="directory">instance-shutdown</filename></entry>
246
              <entry>Stops an instance</entry>
247
              <entry><computeroutput>gnt-instance shutdown</computeroutput></entry>
248
              <entry><constant>INSTANCE_NAME</constant>, <constant>INSTANCE_PRIMARY</constant>, <constant>INSTANCE_SECONDARIES</constant></entry>
249
            </row>
250
            <row>
251
              <entry>OP_INSTANCE_MODIFY</entry>
252
              <entry><filename class="directory">instance-modify</filename></entry>
253
              <entry>Modifies the instance parameters.</entry>
254
              <entry><computeroutput>gnt-instance modify</computeroutput></entry>
255
              <entry><constant>INSTANCE_NAME</constant>, <constant>MEM_SIZE</constant>, <constant>VCPUS</constant>, <constant>INSTANCE_IP</constant></entry>
256
            </row>
257
            <row>
258
              <entry>OP_INSTANCE_FAILOVER</entry>
259
              <entry><filename class="directory">instance-failover</filename></entry>
260
              <entry>Failover an instance</entry>
261
              <entry><computeroutput>gnt-instance start</computeroutput></entry>
262
              <entry><constant>INSTANCE_NAME</constant>, <constant>INSTANCE_PRIMARY</constant>, <constant>INSTANCE_SECONDARIES</constant>, <constant>IGNORE_CONSISTENCY</constant></entry>
263
            </row>
264
            <row>
265
              <entry>OP_INSTANCE_REMOVE</entry>
266
              <entry><filename class="directory">instance-remove</filename></entry>
267
              <entry>Remove an instance</entry>
268
              <entry><computeroutput>gnt-instance remove</computeroutput></entry>
269
              <entry><constant>INSTANCE_NAME</constant>, <constant>INSTANCE_PRIMARY</constant>, <constant>INSTANCE_SECONDARIES</constant></entry>
270
              <entry spanname="bothhooks">master node</entry>
271
            </row>
272
            <row>
273
              <entry>OP_INSTANCE_ADD_MDDRBD</entry>
274
              <entry><filename class="directory">mirror-add</filename></entry>
275
              <entry>Adds a mirror component</entry>
276
              <entry><computeroutput>gnt-instance add-mirror</computeroutput></entry>
277
              <entry><constant>INSTANCE_NAME</constant>, <constant>NEW_SECONDARY</constant>, <constant>DISK_NAME</constant></entry>
278
            </row>
279
            <row>
280
              <entry>OP_INSTANCE_REMOVE_MDDRBD</entry>
281
              <entry><filename class="directory">mirror-remove</filename></entry>
282
              <entry>Removes a mirror component</entry>
283
              <entry><computeroutput>gnt-instance remove-mirror</computeroutput></entry>
284
              <entry><constant>INSTANCE_NAME</constant>, <constant>OLD_SECONDARY</constant>, <constant>DISK_NAME</constant>, <constant>DISK_ID</constant></entry>
285
            </row>
286
            <row>
287
              <entry>OP_INSTANCE_REPLACE_DISKS</entry>
288
              <entry><filename class="directory">mirror-replace</filename></entry>
289
              <entry>Replace all mirror components</entry>
290
              <entry><computeroutput>gnt-instance replace-disks</computeroutput></entry>
291
              <entry><constant>INSTANCE_NAME</constant>, <constant>OLD_SECONDARY</constant>, <constant>NEW_SECONDARY</constant></entry>
292

    
293
            </row>
294
          </tbody>
295
        </tgroup>
296
      </table>
297
    </section>
298

    
299
    <section>
300
      <title>Environment variables</title>
301

    
302
      <para>Note that all variables listed here are actually prefixed
303
      with <constant>GANETI_</constant> in order to provide a
304
      different namespace.</para>
305

    
306
      <section>
307
        <title>Common variables</title>
308

    
309
        <para>This is the list of environment variables supported by
310
        all operations:</para>
311

    
312
        <variablelist>
313
          <varlistentry>
314
            <term>HOOKS_VERSION</term>
315
            <listitem>
316
              <para>Documents the hooks interface version. In case this
317
            doesnt match what the script expects, it should not
318
            run. The documents conforms to the version
319
            <literal>1</literal>.</para>
320
            </listitem>
321
          </varlistentry>
322
          <varlistentry>
323
            <term>HOOKS_PHASE</term>
324
            <listitem>
325
              <para>one of <constant>PRE</constant> or
326
              <constant>POST</constant> denoting which phase are we
327
              in.</para>
328
            </listitem>
329
          </varlistentry>
330
          <varlistentry>
331
            <term>CLUSTER</term>
332
            <listitem>
333
              <para>the cluster name</para>
334
            </listitem>
335
          </varlistentry>
336
          <varlistentry>
337
            <term>MASTER</term>
338
            <listitem>
339
              <para>the master node</para>
340
            </listitem>
341
          </varlistentry>
342
          <varlistentry>
343
            <term>OP_ID</term>
344
            <listitem>
345
              <para>one of the <constant>OP_*</constant> values from
346
              the table of operations</para>
347
            </listitem>
348
          </varlistentry>
349
          <varlistentry>
350
            <term>OBJECT_TYPE</term>
351
            <listitem>
352
              <para>one of <simplelist type="inline">
353
                  <member><constant>INSTANCE</constant></member>
354
                  <member><constant>NODE</constant></member>
355
                  <member><constant>CLUSTER</constant></member>
356
                </simplelist>, showing the target of the operation.
357
             </para>
358
            </listitem>
359
          </varlistentry>
360
          <!-- commented out since it causes problems in our rpc
361
               multi-node optimised calls
362
          <varlistentry>
363
            <term>HOST_NAME</term>
364
            <listitem>
365
              <para>The name of the node the hook is run on as known by
366
            the cluster.</para>
367
            </listitem>
368
          </varlistentry>
369
          <varlistentry>
370
            <term>HOST_TYPE</term>
371
            <listitem>
372
              <para>one of <simplelist type="inline">
373
                  <member><constant>MASTER</constant></member>
374
                  <member><constant>NODE</constant></member>
375
                </simplelist>, showing the role of this node in the cluster.
376
             </para>
377
            </listitem>
378
          </varlistentry>
379
          -->
380
        </variablelist>
381
      </section>
382

    
383
      <section>
384
        <title>Specialised variables</title>
385

    
386
        <para>This is the list of variables which are specific to one
387
        or more operations.</para>
388
        <variablelist>
389
          <varlistentry>
390
            <term>INSTANCE_NAME</term>
391
            <listitem>
392
              <para>The name of the instance which is the target of
393
              the operation.</para>
394
            </listitem>
395
          </varlistentry>
396
          <varlistentry>
397
            <term>INSTANCE_DISK_TYPE</term>
398
            <listitem>
399
              <para>The disk type for the instance.</para>
400
            </listitem>
401
          </varlistentry>
402
          <varlistentry>
403
            <term>INSTANCE_DISK_SIZE</term>
404
            <listitem>
405
              <para>The (OS) disk size for the instance.</para>
406
            </listitem>
407
          </varlistentry>
408
          <varlistentry>
409
            <term>INSTANCE_OS</term>
410
            <listitem>
411
              <para>The name of the instance OS.</para>
412
            </listitem>
413
          </varlistentry>
414
          <varlistentry>
415
            <term>INSTANCE_PRIMARY</term>
416
            <listitem>
417
              <para>The name of the node which is the primary for the
418
              instance.</para>
419
            </listitem>
420
          </varlistentry>
421
          <varlistentry>
422
            <term>INSTANCE_SECONDARIES</term>
423
            <listitem>
424
              <para>Space-separated list of secondary nodes for the
425
              instance.</para>
426
            </listitem>
427
          </varlistentry>
428
          <varlistentry>
429
            <term>NODE_NAME</term>
430
            <listitem>
431
              <para>The target node of this operation (not the node on
432
              which the hook runs).</para>
433
            </listitem>
434
          </varlistentry>
435
          <varlistentry>
436
            <term>NODE_PIP</term>
437
            <listitem>
438
              <para>The primary IP of the target node (the one over
439
              which inter-node communication is done).</para>
440
            </listitem>
441
          </varlistentry>
442
          <varlistentry>
443
            <term>NODE_SIP</term>
444
            <listitem>
445
              <para>The secondary IP of the target node (the one over
446
              which drbd replication is done). This can be equal to
447
              the primary ip, in case the cluster is not
448
              dual-homed.</para>
449
            </listitem>
450
          </varlistentry>
451
          <varlistentry>
452
            <term>OLD_MASTER</term>
453
            <term>NEW_MASTER</term>
454
            <listitem>
455
              <para>The old, respectively the new master for the
456
              master failover operation.</para>
457
            </listitem>
458
          </varlistentry>
459
          <varlistentry>
460
            <term>FORCE</term>
461
            <listitem>
462
              <para>This is provided by some operations when the user
463
              gave this flag.</para>
464
            </listitem>
465
          </varlistentry>
466
          <varlistentry>
467
            <term>IGNORE_CONSISTENCY</term>
468
            <listitem>
469
              <para>The user has specified this flag. It is used when
470
              failing over instances in case the primary node is
471
              down.</para>
472
            </listitem>
473
          </varlistentry>
474
          <varlistentry>
475
            <term>MEM_SIZE, DISK_SIZE, SWAP_SIZE, VCPUS</term>
476
            <listitem>
477
              <para>The memory, disk, swap size and the number of
478
              processor selected for the instance (in
479
              <command>gnt-instance add</command> or
480
              <command>gnt-instance modify</command>).</para>
481
            </listitem>
482
          </varlistentry>
483
          <varlistentry>
484
            <term>INSTANCE_IP</term>
485
            <listitem>
486
              <para>If defined, the instance IP in the
487
              <command>gnt-instance add</command> and
488
              <command>gnt-instance set</command> commands. If not
489
              defined, it means that no IP has been defined.</para>
490
            </listitem>
491
          </varlistentry>
492
          <varlistentry>
493
            <term>DISK_TEMPLATE</term>
494
            <listitem>
495
              <para>The disk template type when creating the instance.</para>
496
            </listitem>
497
          </varlistentry>
498
          <varlistentry>
499
            <term>INSTANCE_ADD_MODE</term>
500
            <listitem>
501
              <para>The mode of the create: either
502
              <constant>create</constant> for create from scratch or
503
              <constant>import</constant> for restoring from an
504
              exported image.</para>
505
            </listitem>
506
          </varlistentry>
507
          <varlistentry>
508
            <term>SRC_NODE, SRC_PATH, SRC_IMAGE</term>
509
            <listitem>
510
              <para>In case the instance has been added by import,
511
              these variables are defined and point to the source
512
              node, source path (the directory containing the image
513
              and the config file) and the source disk image
514
              file.</para>
515
            </listitem>
516
          </varlistentry>
517
          <varlistentry>
518
            <term>DISK_NAME</term>
519
            <listitem>
520
              <para>The disk name (either <filename>sda</filename> or
521
              <filename>sdb</filename>) in mirror operations
522
              (add/remove mirror).</para>
523
            </listitem>
524
          </varlistentry>
525
          <varlistentry>
526
            <term>DISK_ID</term>
527
            <listitem>
528
              <para>The disk id for mirror remove operations. You can
529
              look this up using <command>gnt-instance
530
              info</command>.</para>
531
            </listitem>
532
          </varlistentry>
533
          <varlistentry>
534
            <term>NEW_SECONDARY</term>
535
            <listitem>
536
              <para>The name of the node on which the new mirror
537
              componet is being added. This can be the name of the
538
              current secondary, if the new mirror is on the same
539
              secondary.</para>
540
            </listitem>
541
          </varlistentry>
542
          <varlistentry>
543
            <term>OLD_SECONDARY</term>
544
            <listitem>
545
              <para>The name of the old secondary. This is used in
546
              both <command>replace-disks</command> and
547
              <command>remove-mirror</command>. Note that this can be
548
              equal to the new secondary (only
549
              <command>replace-disks</command> has both variables) if
550
              the secondary node hasn't actually changed).</para>
551
            </listitem>
552
          </varlistentry>
553
          <varlistentry>
554
            <term>EXPORT_NODE</term>
555
            <listitem>
556
              <para>The node on which the exported image of the
557
              instance was done.</para>
558
            </listitem>
559
          </varlistentry>
560
          <varlistentry>
561
            <term>EXPORT_DO_SHUTDOWN</term>
562
            <listitem>
563
              <para>This variable tells if the instance has been
564
              shutdown or not while doing the export. In the "was
565
              shutdown" case, it's likely that the filesystem is
566
              consistent, whereas in the "did not shutdown" case, the
567
              filesystem would need a check (journal replay or full
568
              fsck) in order to guarantee consistency.</para>
569
            </listitem>
570
          </varlistentry>
571
        </variablelist>
572

    
573
      </section>
574

    
575
    </section>
576

    
577
  </section>
578
  </article>