rapi.rst 33.4 KB
Newer Older
1
2
3
Ganeti remote API
=================

Iustin Pop's avatar
Iustin Pop committed
4
Documents Ganeti version |version|
5
6
7
8
9
10
11
12
13
14
15
16
17
18

.. contents::

Introduction
------------

Ganeti supports a remote API for enable external tools to easily
retrieve information about a cluster's state. The remote API daemon,
*ganeti-rapi*, is automatically started on the master node. By default
it runs on TCP port 5080, but this can be changed either in
``.../constants.py`` or via the command line parameter *-p*. SSL mode,
which is used by default, can also be disabled by passing command line
parameters.

19
20
21
22
23

Users and passwords
-------------------

``ganeti-rapi`` reads users and passwords from a file (usually
24
``/var/lib/ganeti/rapi/users``) on startup. Changes to the file will be
25
read automatically.
26
27
28
29
30

Each line consists of two or three fields separated by whitespace. The
first two fields are for username and password. The third field is
optional and can be used to specify per-user options. Currently,
``write`` is the only option supported and enables the user to execute
31
32
operations modifying the cluster. Lines starting with the hash sign
(``#``) are treated as comments.
33
34
35
36
37

Passwords can either be written in clear text or as a hash. Clear text
passwords may not start with an opening brace (``{``) or they must be
prefixed with ``{cleartext}``. To use the hashed form, get the MD5 hash
of the string ``$username:Ganeti Remote API:$password`` (e.g. ``echo -n
38
39
40
'jack:Ganeti Remote API:abc123' | openssl md5``) [#pwhash]_ and prefix
it with ``{ha1}``. Using the scheme prefix for all passwords is
recommended. Scheme prefixes are not case sensitive.
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

Example::

  # Give Jack and Fred read-only access
  jack abc123
  fred {cleartext}foo555

  # Give write access to an imaginary instance creation script
  autocreator xyz789 write

  # Hashed password for Jessica
  jessica {HA1}7046452df2cbb530877058712cf17bd4 write


.. [#pwhash] Using the MD5 hash of username, realm and password is
56
57
   described in :rfc:`2617` ("HTTP Authentication"), sections 3.2.2.2
   and 3.3. The reason for using it over another algorithm is forward
58
59
60
61
62
63
   compatibility. If ``ganeti-rapi`` were to implement HTTP Digest
   authentication in the future, the same hash could be used.
   In the current version ``ganeti-rapi``'s realm, ``Ganeti Remote
   API``, can only be changed by modifying the source code.


64
65
66
Protocol
--------

67
The protocol used is JSON_ over HTTP designed after the REST_ principle.
68
HTTP Basic authentication as per :rfc:`2617` is supported.
69
70
71
72

.. _JSON: http://www.json.org/
.. _REST: http://en.wikipedia.org/wiki/Representational_State_Transfer

73
74
75
76
HTTP requests with a body (e.g. ``PUT`` or ``POST``) require the request
header ``Content-type`` be set to ``application/json`` (see :rfc:`2616`
(HTTP/1.1), section 7.2.1).

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
A note on JSON as used by RAPI
++++++++++++++++++++++++++++++

JSON_ as used by Ganeti RAPI does not conform to the specification in
:rfc:`4627`. Section 2 defines a JSON text to be either an object
(``{"key": "value", …}``) or an array (``[1, 2, 3, …]``). In violation
of this RAPI uses plain strings (``"master-candidate"``, ``"1234"``) for
some requests or responses. Changing this now would likely break
existing clients and cause a lot of trouble.

.. highlight:: ruby

Unlike Python's `JSON encoder and decoder
<http://docs.python.org/library/json.html>`_, other programming
languages or libraries may only provide a strict implementation, not
allowing plain values. For those, responses can usually be wrapped in an
array whose first element is then used, e.g. the response ``"1234"``
becomes ``["1234"]``. This works equally well for more complex values.
Example in Ruby::

  require "json"

  # Insert code to get response here
  response = "\"1234\""

  decoded = JSON.parse("[#{response}]").first

Short of modifying the encoder to allow encoding to a less strict
format, requests will have to be formatted by hand. Newer RAPI requests
already use a dictionary as their input data and shouldn't cause any
problems.


111
112
113
PUT or POST?
------------

114
115
116
According to :rfc:`2616` the main difference between PUT and POST is
that POST can create new resources but PUT can only create the resource
the URI was pointing to on the PUT request.
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136

Unfortunately, due to historic reasons, the Ganeti RAPI library is not
consistent with this usage, so just use the methods as documented below
for each resource.

For more details have a look in the source code at
``lib/rapi/rlib2.py``.


Generic parameter types
-----------------------

A few generic refered parameter types and the values they allow.

``bool``
++++++++

A boolean option will accept ``1`` or ``0`` as numbers but not
i.e. ``True`` or ``False``.

137
138
139
Generic parameters
------------------

140
141
A few parameter mean the same thing across all resources which implement
it.
142
143
144
145

``bulk``
++++++++

Iustin Pop's avatar
Iustin Pop committed
146
147
148
149
150
Bulk-mode means that for the resources which usually return just a list
of child resources (e.g. ``/2/instances`` which returns just instance
names), the output will instead contain detailed data for all these
subresources. This is more efficient than query-ing the sub-resources
themselves.
151
152
153
154

``dry-run``
+++++++++++

155
156
157
The boolean *dry-run* argument, if provided and set, signals to Ganeti
that the job should not be executed, only the pre-execution checks will
be done.
158

Iustin Pop's avatar
Iustin Pop committed
159
160
161
This is useful in trying to determine (without guarantees though, as in
the meantime the cluster state could have changed) if the operation is
likely to succeed or at least start executing.
162

163
164
165
166
167
168
``force``
+++++++++++

Force operation to continue even if it will cause the cluster to become
inconsistent (e.g. because there are not enough master candidates).

169
170
171
Usage examples
--------------

Iustin Pop's avatar
Iustin Pop committed
172
173
You can access the API using your favorite programming language as long
as it supports network connections.
174

175
176
177
178
179
Ganeti RAPI client
++++++++++++++++++

Ganeti includes a standalone RAPI client, ``lib/rapi/client.py``.

180
181
182
Shell
+++++

Iustin Pop's avatar
Iustin Pop committed
183
184
.. highlight:: sh

185
186
Using wget::

Iustin Pop's avatar
Iustin Pop committed
187
   wget -q -O - https://CLUSTERNAME:5080/2/info
188
189
190
191
192
193
194
195
196

or curl::

  curl https://CLUSTERNAME:5080/2/info


Python
++++++

Iustin Pop's avatar
Iustin Pop committed
197
198
199
.. highlight:: python

::
200
201

  import urllib2
Tim Boring's avatar
Tim Boring committed
202
  f = urllib2.urlopen('https://CLUSTERNAME:5080/2/info')
203
204
205
206
207
208
  print f.read()


JavaScript
++++++++++

209
.. warning:: While it's possible to use JavaScript, it poses several
Iustin Pop's avatar
Iustin Pop committed
210
211
212
   potential problems, including browser blocking request due to
   non-standard ports or different domain names. Fetching the data on
   the webserver is easier.
213

Iustin Pop's avatar
Iustin Pop committed
214
215
.. highlight:: javascript

216
217
::

Tim Boring's avatar
Tim Boring committed
218
  var url = 'https://CLUSTERNAME:5080/2/info';
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
  var info;
  var xmlreq = new XMLHttpRequest();
  xmlreq.onreadystatechange = function () {
    if (xmlreq.readyState != 4) return;
    if (xmlreq.status == 200) {
      info = eval("(" + xmlreq.responseText + ")");
      alert(info);
    } else {
      alert('Error fetching cluster info');
    }
    xmlreq = null;
  };
  xmlreq.open('GET', url, true);
  xmlreq.send(null);

Resources
---------

Iustin Pop's avatar
Iustin Pop committed
237
.. highlight:: javascript
238

Iustin Pop's avatar
Iustin Pop committed
239
240
``/``
+++++
241

Iustin Pop's avatar
Iustin Pop committed
242
The root resource.
243

Iustin Pop's avatar
Iustin Pop committed
244
It supports the following commands: ``GET``.
245

Iustin Pop's avatar
Iustin Pop committed
246
247
``GET``
~~~~~~~
248

Iustin Pop's avatar
Iustin Pop committed
249
Shows the list of mapped resources.
250

Iustin Pop's avatar
Iustin Pop committed
251
Returns: a dictionary with 'name' and 'uri' keys for each of them.
252

Iustin Pop's avatar
Iustin Pop committed
253
254
``/2``
++++++
255

Iustin Pop's avatar
Iustin Pop committed
256
The ``/2`` resource, the root of the version 2 API.
257

Iustin Pop's avatar
Iustin Pop committed
258
It supports the following commands: ``GET``.
259

Iustin Pop's avatar
Iustin Pop committed
260
261
``GET``
~~~~~~~
262

Iustin Pop's avatar
Iustin Pop committed
263
Show the list of mapped resources.
264

Iustin Pop's avatar
Iustin Pop committed
265
Returns: a dictionary with ``name`` and ``uri`` keys for each of them.
266

Iustin Pop's avatar
Iustin Pop committed
267
268
``/2/info``
+++++++++++
269

Iustin Pop's avatar
Iustin Pop committed
270
Cluster information resource.
271

Iustin Pop's avatar
Iustin Pop committed
272
It supports the following commands: ``GET``.
273

Iustin Pop's avatar
Iustin Pop committed
274
275
``GET``
~~~~~~~
276

Iustin Pop's avatar
Iustin Pop committed
277
Returns cluster information.
278

Iustin Pop's avatar
Iustin Pop committed
279
Example::
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

  {
    "config_version": 2000000,
    "name": "cluster",
    "software_version": "2.0.0~beta2",
    "os_api_version": 10,
    "export_version": 0,
    "candidate_pool_size": 10,
    "enabled_hypervisors": [
      "fake"
    ],
    "hvparams": {
      "fake": {}
     },
    "default_hypervisor": "fake",
    "master": "node1.example.com",
    "architecture": [
      "64bit",
      "x86_64"
    ],
    "protocol_version": 20,
    "beparams": {
      "default": {
        "auto_balance": true,
        "vcpus": 1,
        "memory": 128
       }
      }
    }

310
311
312
313
314
315
316
317
318
319
320
321
322
323

``/2/redistribute-config``
++++++++++++++++++++++++++

Redistribute configuration to all nodes.

It supports the following commands: ``PUT``.

``PUT``
~~~~~~~

Redistribute configuration to all nodes. The result will be a job id.


324
325
326
327
328
329
330
331
332
``/2/features``
+++++++++++++++

``GET``
~~~~~~~

Returns a list of features supported by the RAPI server. Available
features:

333
334
335
336
337
338
339
340
.. pyassert::

  rlib2.ALL_FEATURES == set([rlib2._INST_CREATE_REQV1,
                             rlib2._INST_REINSTALL_REQV1,
                             rlib2._NODE_MIGRATE_REQV1,
                             rlib2._NODE_EVAC_RES1])

:pyeval:`rlib2._INST_CREATE_REQV1`
341
  Instance creation request data version 1 supported.
342
:pyeval:`rlib2._INST_REINSTALL_REQV1`
343
  Instance reinstall supports body parameters.
344
345
346
347
348
349
:pyeval:`rlib2._NODE_MIGRATE_REQV1`
  Whether migrating a node (``/2/nodes/[node_name]/migrate``) supports
  request body parameters.
:pyeval:`rlib2._NODE_EVAC_RES1`
  Whether evacuating a node (``/2/nodes/[node_name]/evacuate``) returns
  a new-style result (see resource description)
350
351


352
353
354
355
356
357
358
359
360
361
362
363
364
365
``/2/modify``
++++++++++++++++++++++++++++++++++++++++

Modifies cluster parameters.

Supports the following commands: ``PUT``.

``PUT``
~~~~~~~

Returns a job ID.

Body parameters:

366
.. opcode_params:: OP_CLUSTER_SET_PARAMS
367
368


369
370
371
372
373
``/2/groups``
+++++++++++++

The groups resource.

374
It supports the following commands: ``GET``, ``POST``.
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397

``GET``
~~~~~~~

Returns a list of all existing node groups.

Example::

    [
      {
        "name": "group1",
        "uri": "\/2\/groups\/group1"
      },
      {
        "name": "group2",
        "uri": "\/2\/groups\/group2"
      }
    ]

If the optional bool *bulk* argument is provided and set to a true value
(i.e ``?bulk=1``), the output contains detailed information about node
groups as a list.

398
399
Returned fields: :pyeval:`utils.CommaJoin(sorted(rlib2.G_FIELDS))`

400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
Example::

    [
      {
        "name": "group1",
        "node_cnt": 2,
        "node_list": [
          "node1.example.com",
          "node2.example.com"
        ],
        "uuid": "0d7d407c-262e-49af-881a-6a430034bf43"
      },
      {
        "name": "group2",
        "node_cnt": 1,
        "node_list": [
          "node3.example.com"
        ],
        "uuid": "f5a277e7-68f9-44d3-a378-4b25ecb5df5c"
      }
    ]

422
423
424
425
426
427
428
429
430
431
432
433
``POST``
~~~~~~~~

Creates a node group.

If the optional bool *dry-run* argument is provided, the job will not be
actually executed, only the pre-execution checks will be done.

Returns: a job ID that can be used later for polling.

Body parameters:

434
435
436
437
.. opcode_params:: OP_GROUP_ADD

Earlier versions used a parameter named ``name`` which, while still
supported, has been renamed to ``group_name``.
438
439


440
``/2/groups/[group_name]``
441
++++++++++++++++++++++++++
442
443
444

Returns information about a node group.

445
446
447
448
449
450
451
452
It supports the following commands: ``GET``, ``DELETE``.

``GET``
~~~~~~~

Returns information about a node group, similar to the bulk output from
the node group list.

453
454
Returned fields: :pyeval:`utils.CommaJoin(sorted(rlib2.G_FIELDS))`

455
456
457
458
459
460
461
462
``DELETE``
~~~~~~~~~~

Deletes a node group.

It supports the ``dry-run`` argument.


463
464
465
466
467
468
469
470
471
472
473
474
475
476
``/2/groups/[group_name]/modify``
+++++++++++++++++++++++++++++++++

Modifies the parameters of a node group.

Supports the following commands: ``PUT``.

``PUT``
~~~~~~~

Returns a job ID.

Body parameters:

477
478
.. opcode_params:: OP_GROUP_SET_PARAMS
   :exclude: group_name
479

480
481
482
483
Job result:

.. opcode_result:: OP_GROUP_SET_PARAMS

484

485
486
487
488
489
490
491
492
493
494
495
496
497
498
``/2/groups/[group_name]/rename``
+++++++++++++++++++++++++++++++++

Renames a node group.

Supports the following commands: ``PUT``.

``PUT``
~~~~~~~

Returns a job ID.

Body parameters:

499
500
.. opcode_params:: OP_GROUP_RENAME
   :exclude: group_name
501

502
503
504
505
Job result:

.. opcode_result:: OP_GROUP_RENAME

506

507
508
509
510
511
512
513
514
515
516
517
518
519
520
``/2/groups/[group_name]/assign-nodes``
+++++++++++++++++++++++++++++++++++++++

Assigns nodes to a group.

Supports the following commands: ``PUT``.

``PUT``
~~~~~~~

Returns a job ID. It supports the ``dry-run`` and ``force`` arguments.

Body parameters:

521
522
.. opcode_params:: OP_GROUP_ASSIGN_NODES
   :exclude: group_name, force, dry_run
523
524


525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
``/2/groups/[group_name]/tags``
+++++++++++++++++++++++++++++++

Manages per-nodegroup tags.

Supports the following commands: ``GET``, ``PUT``, ``DELETE``.

``GET``
~~~~~~~

Returns a list of tags.

Example::

    ["tag1", "tag2", "tag3"]

``PUT``
~~~~~~~

Add a set of tags.

The request as a list of strings should be ``PUT`` to this URI. The
result will be a job id.

It supports the ``dry-run`` argument.


``DELETE``
~~~~~~~~~~

Delete a tag.

In order to delete a set of tags, the DELETE request should be addressed
to URI like::

    /tags?tag=[tag]&tag=[tag]

It supports the ``dry-run`` argument.


Iustin Pop's avatar
Iustin Pop committed
565
566
``/2/instances``
++++++++++++++++
567

Iustin Pop's avatar
Iustin Pop committed
568
The instances resource.
569

Iustin Pop's avatar
Iustin Pop committed
570
It supports the following commands: ``GET``, ``POST``.
571

Iustin Pop's avatar
Iustin Pop committed
572
573
``GET``
~~~~~~~
574

Iustin Pop's avatar
Iustin Pop committed
575
Returns a list of all available instances.
576

Iustin Pop's avatar
Iustin Pop committed
577
Example::
578
579
580
581
582
583
584
585
586
587
588
589

    [
      {
        "name": "web.example.com",
        "uri": "\/instances\/web.example.com"
      },
      {
        "name": "mail.example.com",
        "uri": "\/instances\/mail.example.com"
      }
    ]

590
591
592
If the optional bool *bulk* argument is provided and set to a true value
(i.e ``?bulk=1``), the output contains detailed information about
instances as a list.
593

594
595
Returned fields: :pyeval:`utils.CommaJoin(sorted(rlib2.I_FIELDS))`

Iustin Pop's avatar
Iustin Pop committed
596
Example::
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625

    [
      {
         "status": "running",
         "disk_usage": 20480,
         "nic.bridges": [
           "xen-br0"
          ],
         "name": "web.example.com",
         "tags": ["tag1", "tag2"],
         "beparams": {
           "vcpus": 2,
           "memory": 512
         },
         "disk.sizes": [
             20480
         ],
         "pnode": "node1.example.com",
         "nic.macs": ["01:23:45:67:89:01"],
         "snodes": ["node2.example.com"],
         "disk_template": "drbd",
         "admin_state": true,
         "os": "debian-etch",
         "oper_state": true
      },
      ...
    ]


Iustin Pop's avatar
Iustin Pop committed
626
627
``POST``
~~~~~~~~
628

Iustin Pop's avatar
Iustin Pop committed
629
Creates an instance.
630

631
632
633
634
If the optional bool *dry-run* argument is provided, the job will not be
actually executed, only the pre-execution checks will be done. Query-ing
the job result will return, in both dry-run and normal case, the list of
nodes selected for the instance.
635

Iustin Pop's avatar
Iustin Pop committed
636
Returns: a job ID that can be used later for polling.
637

638
639
640
641
Body parameters:

``__version__`` (int, required)
  Must be ``1`` (older Ganeti versions used a different format for
642
643
  instance creation requests, version ``0``, but that format is no
  longer supported)
644
645
646
647
648
649

.. opcode_params:: OP_INSTANCE_CREATE

Earlier versions used parameters named ``name`` and ``os``. These have
been replaced by ``instance_name`` and ``os_type`` to match the
underlying opcode. The old names can still be used.
650

651
652
653
654
Job result:

.. opcode_result:: OP_INSTANCE_CREATE

655

Iustin Pop's avatar
Iustin Pop committed
656
657
``/2/instances/[instance_name]``
++++++++++++++++++++++++++++++++
658

Iustin Pop's avatar
Iustin Pop committed
659
Instance-specific resource.
660

Iustin Pop's avatar
Iustin Pop committed
661
It supports the following commands: ``GET``, ``DELETE``.
662

Iustin Pop's avatar
Iustin Pop committed
663
664
``GET``
~~~~~~~
665

Iustin Pop's avatar
Iustin Pop committed
666
667
Returns information about an instance, similar to the bulk output from
the instance list.
668

669
670
Returned fields: :pyeval:`utils.CommaJoin(sorted(rlib2.I_FIELDS))`

Iustin Pop's avatar
Iustin Pop committed
671
672
``DELETE``
~~~~~~~~~~
673

Iustin Pop's avatar
Iustin Pop committed
674
Deletes an instance.
675

676
677
It supports the ``dry-run`` argument.

678

679
680
681
682
683
684
685
686
687
688
``/2/instances/[instance_name]/info``
+++++++++++++++++++++++++++++++++++++++

It supports the following commands: ``GET``.

``GET``
~~~~~~~

Requests detailed information about the instance. An optional parameter,
``static`` (bool), can be set to return only static information from the
689
690
configuration without querying the instance's nodes. The result will be
a job id.
691
692


Iustin Pop's avatar
Iustin Pop committed
693
694
``/2/instances/[instance_name]/reboot``
+++++++++++++++++++++++++++++++++++++++
695

Iustin Pop's avatar
Iustin Pop committed
696
Reboots URI for an instance.
697

Iustin Pop's avatar
Iustin Pop committed
698
It supports the following commands: ``POST``.
699

Iustin Pop's avatar
Iustin Pop committed
700
701
``POST``
~~~~~~~~
702

Iustin Pop's avatar
Iustin Pop committed
703
Reboots the instance.
704

705
706
707
708
709
710
711
712
713
714
715
716
The URI takes optional ``type=soft|hard|full`` and
``ignore_secondaries=0|1`` parameters.

``type`` defines the reboot type. ``soft`` is just a normal reboot,
without terminating the hypervisor. ``hard`` means full shutdown
(including terminating the hypervisor process) and startup again.
``full`` is like ``hard`` but also recreates the configuration from
ground up as if you would have done a ``gnt-instance shutdown`` and
``gnt-instance start`` on it.

``ignore_secondaries`` is a bool argument indicating if we start the
instance even if secondary disks are failing.
717

718
719
720
It supports the ``dry-run`` argument.


Iustin Pop's avatar
Iustin Pop committed
721
722
``/2/instances/[instance_name]/shutdown``
+++++++++++++++++++++++++++++++++++++++++
723

Iustin Pop's avatar
Iustin Pop committed
724
Instance shutdown URI.
725

Iustin Pop's avatar
Iustin Pop committed
726
It supports the following commands: ``PUT``.
727

Iustin Pop's avatar
Iustin Pop committed
728
729
``PUT``
~~~~~~~
730

Iustin Pop's avatar
Iustin Pop committed
731
Shutdowns an instance.
732

733
734
It supports the ``dry-run`` argument.

735
736
737
.. opcode_params:: OP_INSTANCE_SHUTDOWN
   :exclude: instance_name, dry_run

738

Iustin Pop's avatar
Iustin Pop committed
739
740
``/2/instances/[instance_name]/startup``
++++++++++++++++++++++++++++++++++++++++
741

Iustin Pop's avatar
Iustin Pop committed
742
Instance startup URI.
743

Iustin Pop's avatar
Iustin Pop committed
744
It supports the following commands: ``PUT``.
745

Iustin Pop's avatar
Iustin Pop committed
746
747
``PUT``
~~~~~~~
748

Iustin Pop's avatar
Iustin Pop committed
749
Startup an instance.
750

751
752
The URI takes an optional ``force=1|0`` parameter to start the
instance even if secondary disks are failing.
753

754
755
It supports the ``dry-run`` argument.

756
757
758
759
760
761
762
763
764
765
``/2/instances/[instance_name]/reinstall``
++++++++++++++++++++++++++++++++++++++++++++++

Installs the operating system again.

It supports the following commands: ``POST``.

``POST``
~~~~~~~~

766
767
768
769
770
771
772
773
774
775
776
777
778
779
Returns a job ID.

Body parameters:

``os`` (string, required)
  Instance operating system.
``start`` (bool, defaults to true)
  Whether to start instance after reinstallation.
``osparams`` (dict)
  Dictionary with (temporary) OS parameters.

For backwards compatbility, this resource also takes the query
parameters ``os`` (OS template name) and ``nostartup`` (bool). New
clients should use the body parameters.
780

781

782
783
784
785
786
787
788
789
790
791
``/2/instances/[instance_name]/replace-disks``
++++++++++++++++++++++++++++++++++++++++++++++

Replaces disks on an instance.

It supports the following commands: ``POST``.

``POST``
~~~~~~~~

792
793
794
Returns a job ID.

Body parameters:
795

796
797
.. opcode_params:: OP_INSTANCE_REPLACE_DISKS
   :exclude: instance_name
798

799
800
Ganeti 2.4 and below used query parameters. Those are deprecated and
should no longer be used.
801

802

803
804
805
806
807
808
809
810
811
812
``/2/instances/[instance_name]/activate-disks``
+++++++++++++++++++++++++++++++++++++++++++++++

Activate disks on an instance.

It supports the following commands: ``PUT``.

``PUT``
~~~~~~~

813
Takes the bool parameter ``ignore_size``. When set ignore the recorded
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
size (useful for forcing activation when recorded size is wrong).


``/2/instances/[instance_name]/deactivate-disks``
+++++++++++++++++++++++++++++++++++++++++++++++++

Deactivate disks on an instance.

It supports the following commands: ``PUT``.

``PUT``
~~~~~~~

Takes no parameters.


830
831
832
833
834
835
836
837
838
839
840
841
842
843
``/2/instances/[instance_name]/disk/[disk_index]/grow``
+++++++++++++++++++++++++++++++++++++++++++++++++++++++

Grows one disk of an instance.

Supports the following commands: ``POST``.

``POST``
~~~~~~~~

Returns a job ID.

Body parameters:

844
845
.. opcode_params:: OP_INSTANCE_GROW_DISK
   :exclude: instance_name, disk
846
847


848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
``/2/instances/[instance_name]/prepare-export``
+++++++++++++++++++++++++++++++++++++++++++++++++

Prepares an export of an instance.

It supports the following commands: ``PUT``.

``PUT``
~~~~~~~

Takes one parameter, ``mode``, for the export mode. Returns a job ID.


``/2/instances/[instance_name]/export``
+++++++++++++++++++++++++++++++++++++++++++++++++

Exports an instance.

It supports the following commands: ``PUT``.

``PUT``
~~~~~~~

Returns a job ID.

Body parameters:

875
876
877
.. opcode_params:: OP_BACKUP_EXPORT
   :exclude: instance_name
   :alias: target_node=destination
878
879


880
881
882
883
884
885
886
887
888
889
890
891
892
893
``/2/instances/[instance_name]/migrate``
++++++++++++++++++++++++++++++++++++++++

Migrates an instance.

Supports the following commands: ``PUT``.

``PUT``
~~~~~~~

Returns a job ID.

Body parameters:

894
895
.. opcode_params:: OP_INSTANCE_MIGRATE
   :exclude: instance_name, live
896
897


898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
``/2/instances/[instance_name]/failover``
+++++++++++++++++++++++++++++++++++++++++

Does a failover of an instance.

Supports the following commands: ``PUT``.

``PUT``
~~~~~~~

Returns a job ID.

Body parameters:

.. opcode_params:: OP_INSTANCE_FAILOVER
   :exclude: instance_name


916
917
918
919
920
921
922
923
924
925
926
927
928
929
``/2/instances/[instance_name]/rename``
++++++++++++++++++++++++++++++++++++++++

Renames an instance.

Supports the following commands: ``PUT``.

``PUT``
~~~~~~~

Returns a job ID.

Body parameters:

930
931
.. opcode_params:: OP_INSTANCE_RENAME
   :exclude: instance_name
932

933
934
935
936
Job result:

.. opcode_result:: OP_INSTANCE_RENAME

937

938
939
940
941
942
943
944
945
946
947
948
949
950
951
``/2/instances/[instance_name]/modify``
++++++++++++++++++++++++++++++++++++++++

Modifies an instance.

Supports the following commands: ``PUT``.

``PUT``
~~~~~~~

Returns a job ID.

Body parameters:

952
953
.. opcode_params:: OP_INSTANCE_SET_PARAMS
   :exclude: instance_name
954

955
956
957
958
Job result:

.. opcode_result:: OP_INSTANCE_SET_PARAMS

959

960
961
962
963
964
965
966
967
968
969
970
971
972
``/2/instances/[instance_name]/console``
++++++++++++++++++++++++++++++++++++++++

Request information for connecting to instance's console.

Supports the following commands: ``GET``.

``GET``
~~~~~~~

Returns a dictionary containing information about the instance's
console. Contained keys:

973
974
975
976
977
978
979
980
.. pyassert::

   constants.CONS_ALL == frozenset([
     constants.CONS_MESSAGE,
     constants.CONS_SSH,
     constants.CONS_VNC,
     ])

981
982
983
``instance``
  Instance name.
``kind``
984
985
  Console type, one of :pyeval:`constants.CONS_SSH`,
  :pyeval:`constants.CONS_VNC` or :pyeval:`constants.CONS_MESSAGE`.
986
``message``
987
  Message to display (:pyeval:`constants.CONS_MESSAGE` type only).
988
``host``
989
990
  Host to connect to (:pyeval:`constants.CONS_SSH` and
  :pyeval:`constants.CONS_VNC` only).
991
``port``
992
  TCP port to connect to (:pyeval:`constants.CONS_VNC` only).
993
``user``
994
  Username to use (:pyeval:`constants.CONS_SSH` only).
995
``command``
996
  Command to execute on machine (:pyeval:`constants.CONS_SSH` only)
997
``display``
998
  VNC display number (:pyeval:`constants.CONS_VNC` only).
999
1000


Iustin Pop's avatar
Iustin Pop committed
1001
1002
``/2/instances/[instance_name]/tags``
+++++++++++++++++++++++++++++++++++++
1003

Iustin Pop's avatar
Iustin Pop committed
1004
Manages per-instance tags.
1005

Iustin Pop's avatar
Iustin Pop committed
1006
It supports the following commands: ``GET``, ``PUT``, ``DELETE``.
1007

Iustin Pop's avatar
Iustin Pop committed
1008
1009
``GET``
~~~~~~~
1010

Iustin Pop's avatar
Iustin Pop committed
1011
Returns a list of tags.
1012

Iustin Pop's avatar
Iustin Pop committed
1013
Example::
1014

Iustin Pop's avatar
Iustin Pop committed
1015
    ["tag1", "tag2", "tag3"]
1016

Iustin Pop's avatar
Iustin Pop committed
1017
1018
``PUT``
~~~~~~~
1019

Iustin Pop's avatar
Iustin Pop committed
1020
Add a set of tags.
1021

Iustin Pop's avatar
Iustin Pop committed
1022
The request as a list of strings should be ``PUT`` to this URI. The
1023
result will be a job id.
1024

1025
1026
1027
It supports the ``dry-run`` argument.


Iustin Pop's avatar
Iustin Pop committed
1028
1029
``DELETE``
~~~~~~~~~~
1030

Iustin Pop's avatar
Iustin Pop committed
1031
Delete a tag.
1032

Iustin Pop's avatar
Iustin Pop committed
1033
1034
In order to delete a set of tags, the DELETE request should be addressed
to URI like::
1035

Iustin Pop's avatar
Iustin Pop committed
1036
    /tags?tag=[tag]&tag=[tag]
1037

1038
1039
1040
It supports the ``dry-run`` argument.


Iustin Pop's avatar
Iustin Pop committed
1041
1042
``/2/jobs``
+++++++++++
1043

Iustin Pop's avatar
Iustin Pop committed
1044
The ``/2/jobs`` resource.
1045

Iustin Pop's avatar
Iustin Pop committed
1046
It supports the following commands: ``GET``.
1047

Iustin Pop's avatar
Iustin Pop committed
1048
1049
``GET``
~~~~~~~
1050

Iustin Pop's avatar
Iustin Pop committed
1051
Returns a dictionary of jobs.
1052

Iustin Pop's avatar
Iustin Pop committed
1053
Returns: a dictionary with jobs id and uri.
1054

1055
1056
1057
1058
If the optional bool *bulk* argument is provided and set to a true value
(i.e. ``?bulk=1``), the output contains detailed information about jobs
as a list.

1059
1060
1061
1062
Returned fields for bulk requests (unlike other bulk requests, these
fields are not the same as for per-job requests):
:pyeval:`utils.CommaJoin(sorted(rlib2.J_FIELDS_BULK))`

Iustin Pop's avatar
Iustin Pop committed
1063
1064
``/2/jobs/[job_id]``
++++++++++++++++++++
1065
1066


Iustin Pop's avatar
Iustin Pop committed
1067
Individual job URI.
1068

Iustin Pop's avatar
Iustin Pop committed
1069
It supports the following commands: ``GET``, ``DELETE``.
1070

Iustin Pop's avatar
Iustin Pop committed
1071
1072
``GET``
~~~~~~~
1073

1074
1075
Returns a dictionary with job parameters, containing the fields
:pyeval:`utils.CommaJoin(sorted(rlib2.J_FIELDS))`.
1076

Iustin Pop's avatar
Iustin Pop committed
1077
The result includes:
1078

Iustin Pop's avatar
Iustin Pop committed
1079
1080
- id: job ID as a number
- status: current job status as a string
Iustin Pop's avatar
Iustin Pop committed
1081
1082
- ops: involved OpCodes as a list of dictionaries for each opcodes in
  the job
Iustin Pop's avatar
Iustin Pop committed
1083
- opstatus: OpCodes status as a list
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
- opresult: OpCodes results as a list

For a successful opcode, the ``opresult`` field corresponding to it will
contain the raw result from its :term:`LogicalUnit`. In case an opcode
has failed, its element in the opresult list will be a list of two
elements:

- first element the error type (the Ganeti internal error name)
- second element a list of either one or two elements:

  - the first element is the textual error description
  - the second element, if any, will hold an error classification

The error classification is most useful for the ``OpPrereqError``
error type - these errors happen before the OpCode has started
executing, so it's possible to retry the OpCode without side
effects. But whether it make sense to retry depends on the error
classification:

1103
1104
1105
1106
1107
1108
1109
1110
.. pyassert::

   errors.ECODE_ALL == set([errors.ECODE_RESOLVER, errors.ECODE_NORES,
     errors.ECODE_INVAL, errors.ECODE_STATE, errors.ECODE_NOENT,
     errors.ECODE_EXISTS, errors.ECODE_NOTUNIQUE, errors.ECODE_FAULT,
     errors.ECODE_ENVIRON])

:pyeval:`errors.ECODE_RESOLVER`
1111
1112
1113
1114
  Resolver errors. This usually means that a name doesn't exist in DNS,
  so if it's a case of slow DNS propagation the operation can be retried
  later.

1115
:pyeval:`errors.ECODE_NORES`
1116
1117
1118
1119
  Not enough resources (iallocator failure, disk space, memory,
  etc.). If the resources on the cluster increase, the operation might
  succeed.

1120
:pyeval:`errors.ECODE_INVAL`
1121
1122
1123
  Wrong arguments (at syntax level). The operation will not ever be
  accepted unless the arguments change.

1124
:pyeval:`errors.ECODE_STATE`
1125
1126
1127
1128
  Wrong entity state. For example, live migration has been requested for
  a down instance, or instance creation on an offline node. The
  operation can be retried once the resource has changed state.

1129
:pyeval:`errors.ECODE_NOENT`
1130
1131
1132
  Entity not found. For example, information has been requested for an
  unknown instance.

1133
:pyeval:`errors.ECODE_EXISTS`
1134
1135
1136
  Entity already exists. For example, instance creation has been
  requested for an already-existing instance.

1137
:pyeval:`errors.ECODE_NOTUNIQUE`
1138
1139
  Resource not unique (e.g. MAC or IP duplication).

1140
:pyeval:`errors.ECODE_FAULT`
1141
1142
1143
1144
  Internal cluster error. For example, a node is unreachable but not set
  offline, or the ganeti node daemons are not working, etc. A
  ``gnt-cluster verify`` should be run.

1145
:pyeval:`errors.ECODE_ENVIRON`
1146
1147
1148
1149
1150
1151
  Environment error (e.g. node disk error). A ``gnt-cluster verify``
  should be run.

Note that in the above list, by entity we refer to a node or instance,
while by a resource we refer to an instance's disk, or NIC, etc.

1152

Iustin Pop's avatar
Iustin Pop committed
1153
1154
``DELETE``
~~~~~~~~~~
1155

Iustin Pop's avatar
Iustin Pop committed
1156
Cancel a not-yet-started job.
1157

1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181

``/2/jobs/[job_id]/wait``
+++++++++++++++++++++++++

``GET``
~~~~~~~

Waits for changes on a job. Takes the following body parameters in a
dict:

``fields``
  The job fields on which to watch for changes.

``previous_job_info``
  Previously received field values or None if not yet available.

``previous_log_serial``
  Highest log serial number received so far or None if not yet
  available.

Returns None if no changes have been detected and a dict with two keys,
``job_info`` and ``log_entries`` otherwise.


Iustin Pop's avatar
Iustin Pop committed
1182
1183
``/2/nodes``
++++++++++++
1184

Iustin Pop's avatar
Iustin Pop committed
1185
Nodes resource.
1186

Iustin Pop's avatar
Iustin Pop committed
1187
It supports the following commands: ``GET``.
1188

Iustin Pop's avatar
Iustin Pop committed
1189
1190
``GET``
~~~~~~~
1191

Iustin Pop's avatar
Iustin Pop committed
1192
Returns a list of all nodes.
1193

Iustin Pop's avatar
Iustin Pop committed
1194
Example::
1195
1196
1197
1198

    [
      {
        "id": "node1.example.com",
Iustin Pop's avatar
Iustin Pop committed
1199
        "uri": "\/nodes\/node1.example.com"
1200
1201
1202
      },
      {
        "id": "node2.example.com",
Iustin Pop's avatar
Iustin Pop committed
1203
        "uri": "\/nodes\/node2.example.com"
1204
1205
1206
      }
    ]

1207
1208
1209
1210
1211
If the optional bool *bulk* argument is provided and set to a true value
(i.e ``?bulk=1``), the output contains detailed information about nodes
as a list.

Returned fields: :pyeval:`utils.CommaJoin(sorted(rlib2.N_FIELDS))`
1212

Iustin Pop's avatar
Iustin Pop committed
1213
Example::
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230

    [
      {
        "pinst_cnt": 1,
        "mfree": 31280,
        "mtotal": 32763,
        "name": "www.example.com",
        "tags": [],
        "mnode": 512,
        "dtotal": 5246208,
        "sinst_cnt": 2,
        "dfree": 5171712,
        "offline": false
      },
      ...
    ]

1231
1232
1233
1234
1235
1236
1237
``/2/nodes/[node_name]``
+++++++++++++++++++++++++++++++++

Returns information about a node.

It supports the following commands: ``GET``.

1238
1239
Returned fields: :pyeval:`utils.CommaJoin(sorted(rlib2.N_FIELDS))`

1240
1241
1242
``/2/nodes/[node_name]/evacuate``
+++++++++++++++++++++++++++++++++

1243
Evacuates instances off a node.
1244
1245
1246
1247
1248
1249

It supports the following commands: ``POST``.

``POST``
~~~~~~~~

1250
1251
Returns a job ID. The result of the job will contain the IDs of the
individual jobs submitted to evacuate the node.
1252

1253
Body parameters:
1254

1255
1256
.. opcode_params:: OP_NODE_EVACUATE
   :exclude: nodes
1257

1258
1259
1260
Up to and including Ganeti 2.4 query arguments were used. Those are no
longer supported. The new request can be detected by the presence of the
:pyeval:`rlib2._NODE_EVAC_RES1` feature string.
1261

1262
1263
1264
1265
Job result:

.. opcode_result:: OP_NODE_EVACUATE

1266

1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
``/2/nodes/[node_name]/migrate``
+++++++++++++++++++++++++++++++++

Migrates all primary instances from a node.

It supports the following commands: ``POST``.

``POST``
~~~~~~~~

1277
If no mode is explicitly specified, each instances' hypervisor default
1278
1279
1280
1281
migration mode will be used. Body parameters:

.. opcode_params:: OP_NODE_MIGRATE
   :exclude: node_name
1282

1283
1284
1285
The query arguments used up to and including Ganeti 2.4 are deprecated
and should no longer be used. The new request format can be detected by
the presence of the :pyeval:`rlib2._NODE_MIGRATE_REQV1` feature string.
1286
1287


1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
``/2/nodes/[node_name]/role``
+++++++++++++++++++++++++++++

Manages node role.

It supports the following commands: ``GET``, ``PUT``.

The role is always one of the following:

  - drained
  - master-candidate
  - offline
  - regular

1302
1303
1304
1305
Note that the 'master' role is a special, and currently it can't be
modified via RAPI, only via the command line (``gnt-cluster
master-failover``).

1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
``GET``
~~~~~~~

Returns the current node role.

Example::

    "master-candidate"

``PUT``
~~~~~~~

Change the node role.

1320
1321
The request is a string which should be PUT to this URI. The result will
be a job id.
1322

1323
It supports the bool ``force`` argument.
1324

1325
1326
1327
1328
1329
1330
1331
1332
``/2/nodes/[node_name]/storage``
++++++++++++++++++++++++++++++++

Manages storage units on the node.

``GET``
~~~~~~~

1333
1334
1335
1336
1337
1338
.. pyassert::

   constants.VALID_STORAGE_TYPES == set([constants.ST_FILE,
                                         constants.ST_LVM_PV,
                                         constants.ST_LVM_VG])

1339
Requests a list of storage units on a node. Requires the parameters
1340
1341
``storage_type`` (one of :pyeval:`constants.ST_FILE`,
:pyeval:`constants.ST_LVM_PV` or :pyeval:`constants.ST_LVM_VG`) and
1342
1343
``output_fields``. The result will be a job id, using which the result
can be retrieved.
1344

1345
1346
1347
1348
1349
1350
1351
1352
``/2/nodes/[node_name]/storage/modify``
+++++++++++++++++++++++++++++++++++++++

Modifies storage units on the node.

``PUT``
~~~~~~~

1353
Modifies parameters of storage units on the node. Requires the
1354
1355
parameters ``storage_type`` (one of :pyeval:`constants.ST_FILE`,
:pyeval:`constants.ST_LVM_PV` or :pyeval:`constants.ST_LVM_VG`)
1356
and ``name`` (name of the storage unit).  Parameters can be passed
1357
1358
additionally. Currently only :pyeval:`constants.SF_ALLOCATABLE` (bool)
is supported. The result will be a job id.
1359

1360
1361
1362
1363
1364
1365
1366
1367
``/2/nodes/[node_name]/storage/repair``
+++++++++++++++++++++++++++++++++++++++

Repairs a storage unit on the node.

``PUT``
~~~~~~~

1368
1369
1370
1371
1372
1373
.. pyassert::

   constants.VALID_STORAGE_OPERATIONS == {
    constants.ST_LVM_VG: set([constants.SO_FIX_CONSISTENCY]),
    }

1374
Repairs a storage unit on the node. Requires the parameters
1375
1376
1377
``storage_type`` (currently only :pyeval:`constants.ST_LVM_VG` can be
repaired) and ``name`` (name of the storage unit). The result will be a
job id.
1378

Iustin Pop's avatar
Iustin Pop committed
1379
1380
``/2/nodes/[node_name]/tags``
+++++++++++++++++++++++++++++
1381

Iustin Pop's avatar
Iustin Pop committed
1382
Manages per-node tags.
1383

Iustin Pop's avatar
Iustin Pop committed
1384
It supports the following commands: ``GET``, ``PUT``, ``DELETE``.
1385

Iustin Pop's avatar
Iustin Pop committed
1386
1387
``GET``
~~~~~~~
1388

Iustin Pop's avatar
Iustin Pop committed
1389
Returns a list of tags.
1390

Iustin Pop's avatar
Iustin Pop committed
1391
Example::
1392

Iustin Pop's avatar
Iustin Pop committed
1393
    ["tag1", "tag2", "tag3"]
1394

Iustin Pop's avatar
Iustin Pop committed
1395
1396
``PUT``
~~~~~~~
1397

Iustin Pop's avatar
Iustin Pop committed
1398
Add a set of tags.
1399

Iustin Pop's avatar
Iustin Pop committed