Statistics
| Branch: | Tag: | Revision:

root / doc / rapi.rst @ 06c2fb4a

History | View | Annotate | Download (50.5 kB)

1
Ganeti remote API
2
=================
3

    
4
Documents Ganeti version |version|
5

    
6
.. contents::
7

    
8
Introduction
9
------------
10

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

    
19
.. _rapi-users:
20

    
21
Users and passwords
22
-------------------
23

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

    
28
Lines starting with the hash sign (``#``) are treated as comments. Each
29
line consists of two or three fields separated by whitespace. The first
30
two fields are for username and password. The third field is optional
31
and can be used to specify per-user options (separated by comma without
32
spaces).
33

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

    
42
Options control a user's access permissions. The section
43
:ref:`rapi-access-permissions` lists the permissions required for each
44
resource. If the ``--require-authentication`` command line option is
45
given to the ``ganeti-rapi`` daemon, all requests require
46
authentication. Available options:
47

    
48
.. pyassert::
49

    
50
  rapi.RAPI_ACCESS_ALL == set([
51
    rapi.RAPI_ACCESS_WRITE,
52
    rapi.RAPI_ACCESS_READ,
53
    ])
54

    
55
.. pyassert::
56

    
57
  rlib2.R_2_nodes_name_storage.GET_ACCESS == [rapi.RAPI_ACCESS_WRITE]
58

    
59
.. pyassert::
60

    
61
  rlib2.R_2_jobs_id_wait.GET_ACCESS == [rapi.RAPI_ACCESS_WRITE]
62

    
63
:pyeval:`rapi.RAPI_ACCESS_WRITE`
64
  Enables the user to execute operations modifying the cluster. Implies
65
  :pyeval:`rapi.RAPI_ACCESS_READ` access. Resources blocking other
66
  operations for read-only access, such as
67
  :ref:`/2/nodes/[node_name]/storage <rapi-res-nodes-node_name-storage+get>`
68
  or blocking server-side processes, such as
69
  :ref:`/2/jobs/[job_id]/wait <rapi-res-jobs-job_id-wait+get>`, use
70
  :pyeval:`rapi.RAPI_ACCESS_WRITE` to control access to their
71
  :pyeval:`http.HTTP_GET` method.
72
:pyeval:`rapi.RAPI_ACCESS_READ`
73
  Allow access to operations querying for information.
74

    
75
Example::
76

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

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

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

    
87
  # Monitoring can query for values
88
  monitoring {HA1}ec018ffe72b8e75bb4d508ed5b6d079c read
89

    
90
  # A user who can read and write (the former is implied by granting
91
  # write access)
92
  superuser {HA1}ec018ffe72b8e75bb4d508ed5b6d079c read,write
93

    
94
When using the RAPI, username and password can be sent to the server
95
by using the standard HTTP basic access authentication. This means that
96
for accessing the protected URL ``https://cluster.example.com/resource``,
97
the address ``https://username:password@cluster.example.com/resource`` should
98
be used instead.
99
Alternatively, the appropriate parameter of your HTTP client
100
(such as ``-u`` for ``curl``) can be used.
101

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

    
110

    
111
Protocol
112
--------
113

    
114
The protocol used is JSON_ over HTTP designed after the REST_ principle.
115
HTTP Basic authentication as per :rfc:`2617` is supported.
116

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

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

    
124

    
125
A note on JSON as used by RAPI
126
++++++++++++++++++++++++++++++
127

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

    
135
.. highlight:: ruby
136

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

    
145
  require "json"
146

    
147
  # Insert code to get response here
148
  response = "\"1234\""
149

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

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

    
157

    
158
PUT or POST?
159
------------
160

    
161
According to :rfc:`2616` the main difference between PUT and POST is
162
that POST can create new resources but PUT can only create the resource
163
the URI was pointing to on the PUT request.
164

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

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

    
172

    
173
Generic parameter types
174
-----------------------
175

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

    
178
``bool``
179
++++++++
180

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

    
184
Generic parameters
185
------------------
186

    
187
A few parameter mean the same thing across all resources which implement
188
it.
189

    
190
``bulk``
191
++++++++
192

    
193
Bulk-mode means that for the resources which usually return just a list
194
of child resources (e.g. ``/2/instances`` which returns just instance
195
names), the output will instead contain detailed data for all these
196
subresources. This is more efficient than query-ing the sub-resources
197
themselves.
198

    
199
``dry-run``
200
+++++++++++
201

    
202
The boolean *dry-run* argument, if provided and set, signals to Ganeti
203
that the job should not be executed, only the pre-execution checks will
204
be done.
205

    
206
This is useful in trying to determine (without guarantees though, as in
207
the meantime the cluster state could have changed) if the operation is
208
likely to succeed or at least start executing.
209

    
210
``force``
211
+++++++++++
212

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

    
216
Parameter details
217
-----------------
218

    
219
Some parameters are not straight forward, so we describe them in details
220
here.
221

    
222
.. _rapi-ipolicy:
223

    
224
``ipolicy``
225
+++++++++++
226

    
227
The instance policy specification is a dict with the following fields:
228

    
229
.. pyassert::
230

    
231
  constants.IPOLICY_ALL_KEYS == set([constants.ISPECS_MINMAX,
232
                                     constants.ISPECS_STD,
233
                                     constants.IPOLICY_DTS,
234
                                     constants.IPOLICY_VCPU_RATIO,
235
                                     constants.IPOLICY_SPINDLE_RATIO])
236

    
237

    
238
.. pyassert::
239

    
240
  (set(constants.ISPECS_PARAMETER_TYPES.keys()) ==
241
   set([constants.ISPEC_MEM_SIZE,
242
        constants.ISPEC_DISK_SIZE,
243
        constants.ISPEC_DISK_COUNT,
244
        constants.ISPEC_CPU_COUNT,
245
        constants.ISPEC_NIC_COUNT,
246
        constants.ISPEC_SPINDLE_USE]))
247

    
248
.. |ispec-min| replace:: :pyeval:`constants.ISPECS_MIN`
249
.. |ispec-max| replace:: :pyeval:`constants.ISPECS_MAX`
250
.. |ispec-std| replace:: :pyeval:`constants.ISPECS_STD`
251

    
252

    
253
:pyeval:`constants.ISPECS_MINMAX`
254
  A list of dictionaries, each with the following two fields:
255

    
256
  |ispec-min|, |ispec-max|
257
    A sub- `dict` with the following fields, which sets the limit of the
258
    instances:
259

    
260
    :pyeval:`constants.ISPEC_MEM_SIZE`
261
      The size in MiB of the memory used
262
    :pyeval:`constants.ISPEC_DISK_SIZE`
263
      The size in MiB of the disk used
264
    :pyeval:`constants.ISPEC_DISK_COUNT`
265
      The numbers of disks used
266
    :pyeval:`constants.ISPEC_CPU_COUNT`
267
      The numbers of cpus used
268
    :pyeval:`constants.ISPEC_NIC_COUNT`
269
      The numbers of nics used
270
    :pyeval:`constants.ISPEC_SPINDLE_USE`
271
      The numbers of virtual disk spindles used by this instance. They
272
      are not real in the sense of actual HDD spindles, but useful for
273
      accounting the spindle usage on the residing node
274
|ispec-std|
275
  A sub- `dict` with the same fields as |ispec-min| and |ispec-max| above,
276
  which sets the standard values of the instances.
277
:pyeval:`constants.IPOLICY_DTS`
278
  A `list` of disk templates allowed for instances using this policy
279
:pyeval:`constants.IPOLICY_VCPU_RATIO`
280
  Maximum ratio of virtual to physical CPUs (`float`)
281
:pyeval:`constants.IPOLICY_SPINDLE_RATIO`
282
  Maximum ratio of instances to their node's ``spindle_count`` (`float`)
283

    
284
Usage examples
285
--------------
286

    
287
You can access the API using your favorite programming language as long
288
as it supports network connections.
289

    
290
Ganeti RAPI client
291
++++++++++++++++++
292

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

    
295
Shell
296
+++++
297

    
298
.. highlight:: shell-example
299

    
300
Using ``wget``::
301

    
302
   $ wget -q -O - https://%CLUSTERNAME%:5080/2/info
303

    
304
or ``curl``::
305

    
306
  $ curl https://%CLUSTERNAME%:5080/2/info
307

    
308
Note: with ``curl``, the request method (GET, POST, PUT) can be specified
309
using the ``-X`` command line option, and the username/password can be
310
specified with the ``-u`` option. In case of POST requests with a body, the
311
Content-Type can be set to JSON (as per the Protocol_ section) using the
312
parameter ``-H "Content-Type: application/json"``.
313

    
314
Python
315
++++++
316

    
317
.. highlight:: python
318

    
319
::
320

    
321
  import urllib2
322
  f = urllib2.urlopen('https://CLUSTERNAME:5080/2/info')
323
  print f.read()
324

    
325

    
326
JavaScript
327
++++++++++
328

    
329
.. warning:: While it's possible to use JavaScript, it poses several
330
   potential problems, including browser blocking request due to
331
   non-standard ports or different domain names. Fetching the data on
332
   the webserver is easier.
333

    
334
.. highlight:: javascript
335

    
336
::
337

    
338
  var url = 'https://CLUSTERNAME:5080/2/info';
339
  var info;
340
  var xmlreq = new XMLHttpRequest();
341
  xmlreq.onreadystatechange = function () {
342
    if (xmlreq.readyState != 4) return;
343
    if (xmlreq.status == 200) {
344
      info = eval("(" + xmlreq.responseText + ")");
345
      alert(info);
346
    } else {
347
      alert('Error fetching cluster info');
348
    }
349
    xmlreq = null;
350
  };
351
  xmlreq.open('GET', url, true);
352
  xmlreq.send(null);
353

    
354
Resources
355
---------
356

    
357
.. highlight:: javascript
358

    
359
``/``
360
+++++
361

    
362
The root resource. Has no function, but for legacy reasons the ``GET``
363
method is supported.
364

    
365
``/2``
366
++++++
367

    
368
Has no function, but for legacy reasons the ``GET`` method is supported.
369

    
370
.. _rapi-res-info:
371

    
372
``/2/info``
373
+++++++++++
374

    
375
Cluster information resource.
376

    
377
.. rapi_resource_details:: /2/info
378

    
379

    
380
.. _rapi-res-info+get:
381

    
382
``GET``
383
~~~~~~~
384

    
385
Returns cluster information.
386

    
387
Example::
388

    
389
  {
390
    "config_version": 2000000,
391
    "name": "cluster",
392
    "software_version": "2.0.0~beta2",
393
    "os_api_version": 10,
394
    "export_version": 0,
395
    "candidate_pool_size": 10,
396
    "enabled_hypervisors": [
397
      "fake"
398
    ],
399
    "hvparams": {
400
      "fake": {}
401
     },
402
    "default_hypervisor": "fake",
403
    "master": "node1.example.com",
404
    "architecture": [
405
      "64bit",
406
      "x86_64"
407
    ],
408
    "protocol_version": 20,
409
    "beparams": {
410
      "default": {
411
        "auto_balance": true,
412
        "vcpus": 1,
413
        "memory": 128
414
       }
415
      },
416
417
  }
418

    
419

    
420
.. _rapi-res-redistribute-config:
421

    
422
``/2/redistribute-config``
423
++++++++++++++++++++++++++
424

    
425
Redistribute configuration to all nodes.
426

    
427
.. rapi_resource_details:: /2/redistribute-config
428

    
429

    
430
.. _rapi-res-redistribute-config+put:
431

    
432
``PUT``
433
~~~~~~~
434

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

    
437
Job result:
438

    
439
.. opcode_result:: OP_CLUSTER_REDIST_CONF
440

    
441

    
442
.. _rapi-res-features:
443

    
444
``/2/features``
445
+++++++++++++++
446

    
447
.. rapi_resource_details:: /2/features
448

    
449

    
450
.. _rapi-res-features+get:
451

    
452
``GET``
453
~~~~~~~
454

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

    
458
.. pyassert::
459

    
460
  rlib2.ALL_FEATURES == set([rlib2._INST_CREATE_REQV1,
461
                             rlib2._INST_REINSTALL_REQV1,
462
                             rlib2._NODE_MIGRATE_REQV1,
463
                             rlib2._NODE_EVAC_RES1])
464

    
465
:pyeval:`rlib2._INST_CREATE_REQV1`
466
  Instance creation request data version 1 supported
467
:pyeval:`rlib2._INST_REINSTALL_REQV1`
468
  Instance reinstall supports body parameters
469
:pyeval:`rlib2._NODE_MIGRATE_REQV1`
470
  Whether migrating a node (``/2/nodes/[node_name]/migrate``) supports
471
  request body parameters
472
:pyeval:`rlib2._NODE_EVAC_RES1`
473
  Whether evacuating a node (``/2/nodes/[node_name]/evacuate``) returns
474
  a new-style result (see resource description)
475

    
476

    
477
.. _rapi-res-modify:
478

    
479
``/2/modify``
480
++++++++++++++++++++++++++++++++++++++++
481

    
482
Modifies cluster parameters.
483

    
484
.. rapi_resource_details:: /2/modify
485

    
486

    
487
.. _rapi-res-modify+put:
488

    
489
``PUT``
490
~~~~~~~
491

    
492
Returns a job ID.
493

    
494
Body parameters:
495

    
496
.. opcode_params:: OP_CLUSTER_SET_PARAMS
497

    
498
Job result:
499

    
500
.. opcode_result:: OP_CLUSTER_SET_PARAMS
501

    
502

    
503
.. _rapi-res-groups:
504

    
505
``/2/groups``
506
+++++++++++++
507

    
508
The groups resource.
509

    
510
.. rapi_resource_details:: /2/groups
511

    
512

    
513
.. _rapi-res-groups+get:
514

    
515
``GET``
516
~~~~~~~
517

    
518
Returns a list of all existing node groups.
519

    
520
Example::
521

    
522
    [
523
      {
524
        "name": "group1",
525
        "uri": "\/2\/groups\/group1"
526
      },
527
      {
528
        "name": "group2",
529
        "uri": "\/2\/groups\/group2"
530
      }
531
    ]
532

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

    
537
Returned fields: :pyeval:`utils.CommaJoin(sorted(rlib2.G_FIELDS))`.
538

    
539
Example::
540

    
541
    [
542
      {
543
        "name": "group1",
544
        "node_cnt": 2,
545
        "node_list": [
546
          "node1.example.com",
547
          "node2.example.com"
548
        ],
549
        "uuid": "0d7d407c-262e-49af-881a-6a430034bf43",
550
551
      },
552
      {
553
        "name": "group2",
554
        "node_cnt": 1,
555
        "node_list": [
556
          "node3.example.com"
557
        ],
558
        "uuid": "f5a277e7-68f9-44d3-a378-4b25ecb5df5c",
559
560
      },
561
562
    ]
563

    
564

    
565
.. _rapi-res-groups+post:
566

    
567
``POST``
568
~~~~~~~~
569

    
570
Creates a node group.
571

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

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

    
577
Body parameters:
578

    
579
.. opcode_params:: OP_GROUP_ADD
580

    
581
Earlier versions used a parameter named ``name`` which, while still
582
supported, has been renamed to ``group_name``.
583

    
584
Job result:
585

    
586
.. opcode_result:: OP_GROUP_ADD
587

    
588

    
589
.. _rapi-res-groups-group_name:
590

    
591
``/2/groups/[group_name]``
592
++++++++++++++++++++++++++
593

    
594
Returns information about a node group.
595

    
596
.. rapi_resource_details:: /2/groups/[group_name]
597

    
598

    
599
.. _rapi-res-groups-group_name+get:
600

    
601
``GET``
602
~~~~~~~
603

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

    
607
Returned fields: :pyeval:`utils.CommaJoin(sorted(rlib2.G_FIELDS))`.
608

    
609
.. _rapi-res-groups-group_name+delete:
610

    
611
``DELETE``
612
~~~~~~~~~~
613

    
614
Deletes a node group.
615

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

    
618
Job result:
619

    
620
.. opcode_result:: OP_GROUP_REMOVE
621

    
622

    
623
.. _rapi-res-groups-group_name-modify:
624

    
625
``/2/groups/[group_name]/modify``
626
+++++++++++++++++++++++++++++++++
627

    
628
Modifies the parameters of a node group.
629

    
630
.. rapi_resource_details:: /2/groups/[group_name]/modify
631

    
632

    
633
.. _rapi-res-groups-group_name-modify+put:
634

    
635
``PUT``
636
~~~~~~~
637

    
638
Returns a job ID.
639

    
640
Body parameters:
641

    
642
.. opcode_params:: OP_GROUP_SET_PARAMS
643
   :exclude: group_name
644

    
645
Job result:
646

    
647
.. opcode_result:: OP_GROUP_SET_PARAMS
648

    
649

    
650
.. _rapi-res-groups-group_name-rename:
651

    
652
``/2/groups/[group_name]/rename``
653
+++++++++++++++++++++++++++++++++
654

    
655
Renames a node group.
656

    
657
.. rapi_resource_details:: /2/groups/[group_name]/rename
658

    
659

    
660
.. _rapi-res-groups-group_name-rename+put:
661

    
662
``PUT``
663
~~~~~~~
664

    
665
Returns a job ID.
666

    
667
Body parameters:
668

    
669
.. opcode_params:: OP_GROUP_RENAME
670
   :exclude: group_name
671

    
672
Job result:
673

    
674
.. opcode_result:: OP_GROUP_RENAME
675

    
676

    
677
.. _rapi-res-groups-group_name-assign-nodes:
678

    
679
``/2/groups/[group_name]/assign-nodes``
680
+++++++++++++++++++++++++++++++++++++++
681

    
682
Assigns nodes to a group.
683

    
684
.. rapi_resource_details:: /2/groups/[group_name]/assign-nodes
685

    
686
.. _rapi-res-groups-group_name-assign-nodes+put:
687

    
688
``PUT``
689
~~~~~~~
690

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

    
693
Body parameters:
694

    
695
.. opcode_params:: OP_GROUP_ASSIGN_NODES
696
   :exclude: group_name, force, dry_run
697

    
698
Job result:
699

    
700
.. opcode_result:: OP_GROUP_ASSIGN_NODES
701

    
702
.. _rapi-res-groups-group_name-tags:
703

    
704
``/2/groups/[group_name]/tags``
705
+++++++++++++++++++++++++++++++
706

    
707
Manages per-nodegroup tags.
708

    
709
.. rapi_resource_details:: /2/groups/[group_name]/tags
710

    
711

    
712
.. _rapi-res-groups-group_name-tags+get:
713

    
714
``GET``
715
~~~~~~~
716

    
717
Returns a list of tags.
718

    
719
Example::
720

    
721
    ["tag1", "tag2", "tag3"]
722

    
723
.. _rapi-res-groups-group_name-tags+put:
724

    
725
``PUT``
726
~~~~~~~
727

    
728
Add a set of tags.
729

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

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

    
735

    
736
.. _rapi-res-groups-group_name-tags+delete:
737

    
738
``DELETE``
739
~~~~~~~~~~
740

    
741
Delete a tag.
742

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

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

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

    
750

    
751
.. _rapi-res-networks:
752

    
753
``/2/networks``
754
+++++++++++++++
755

    
756
The networks resource.
757

    
758
.. rapi_resource_details:: /2/networks
759

    
760

    
761
.. _rapi-res-networks+get:
762

    
763
``GET``
764
~~~~~~~
765

    
766
Returns a list of all existing networks.
767

    
768
Example::
769

    
770
    [
771
      {
772
        "name": "network1",
773
        "uri": "\/2\/networks\/network1"
774
      },
775
      {
776
        "name": "network2",
777
        "uri": "\/2\/networks\/network2"
778
      }
779
    ]
780

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

    
785
Returned fields: :pyeval:`utils.CommaJoin(sorted(rlib2.NET_FIELDS))`.
786

    
787
Example::
788

    
789
    [
790
      {
791
        'external_reservations': '10.0.0.0, 10.0.0.1, 10.0.0.15',
792
        'free_count': 13,
793
        'gateway': '10.0.0.1',
794
        'gateway6': None,
795
        'group_list': ['default(bridged, prv0)'],
796
        'inst_list': [],
797
        'mac_prefix': None,
798
        'map': 'XX.............X',
799
        'name': 'nat',
800
        'network': '10.0.0.0/28',
801
        'network6': None,
802
        'reserved_count': 3,
803
        'tags': ['nfdhcpd'],
804
805
      },
806
807
    ]
808

    
809

    
810
.. _rapi-res-networks+post:
811

    
812
``POST``
813
~~~~~~~~
814

    
815
Creates a network.
816

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

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

    
822
Body parameters:
823

    
824
.. opcode_params:: OP_NETWORK_ADD
825

    
826
Job result:
827

    
828
.. opcode_result:: OP_NETWORK_ADD
829

    
830

    
831
.. _rapi-res-networks-network_name:
832

    
833
``/2/networks/[network_name]``
834
++++++++++++++++++++++++++++++
835

    
836
Returns information about a network.
837

    
838
.. rapi_resource_details:: /2/networks/[network_name]
839

    
840

    
841
.. _rapi-res-networks-network_name+get:
842

    
843
``GET``
844
~~~~~~~
845

    
846
Returns information about a network, similar to the bulk output from
847
the network list.
848

    
849
Returned fields: :pyeval:`utils.CommaJoin(sorted(rlib2.NET_FIELDS))`.
850

    
851

    
852
.. _rapi-res-networks-network_name+delete:
853

    
854
``DELETE``
855
~~~~~~~~~~
856

    
857
Deletes a network.
858

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

    
861
Job result:
862

    
863
.. opcode_result:: OP_NETWORK_REMOVE
864

    
865

    
866
.. _rapi-res-networks-network_name-modify:
867

    
868
``/2/networks/[network_name]/modify``
869
+++++++++++++++++++++++++++++++++++++
870

    
871
Modifies the parameters of a network.
872

    
873
.. rapi_resource_details:: /2/networks/[network_name]/modify
874

    
875

    
876
.. _rapi-res-networks-network_name-modify+put:
877

    
878
``PUT``
879
~~~~~~~
880

    
881
Returns a job ID.
882

    
883
Body parameters:
884

    
885
.. opcode_params:: OP_NETWORK_SET_PARAMS
886

    
887
Job result:
888

    
889
.. opcode_result:: OP_NETWORK_SET_PARAMS
890

    
891

    
892
.. _rapi-res-networks-network_name-connect:
893

    
894
``/2/networks/[network_name]/connect``
895
++++++++++++++++++++++++++++++++++++++
896

    
897
Connects a network to a nodegroup.
898

    
899
.. rapi_resource_details:: /2/networks/[network_name]/connect
900

    
901

    
902
.. _rapi-res-networks-network_name-connect+put:
903

    
904
``PUT``
905
~~~~~~~
906

    
907
Returns a job ID. It supports the ``dry-run`` arguments.
908

    
909
Body parameters:
910

    
911
.. opcode_params:: OP_NETWORK_CONNECT
912

    
913
Job result:
914

    
915
.. opcode_result:: OP_NETWORK_CONNECT
916

    
917

    
918
.. _rapi-res-networks-network_name-disconnect:
919

    
920
``/2/networks/[network_name]/disconnect``
921
+++++++++++++++++++++++++++++++++++++++++
922

    
923
Disonnects a network from a nodegroup.
924

    
925
.. rapi_resource_details:: /2/networks/[network_name]/disconnect
926

    
927

    
928
.. _rapi-res-networks-network_name-disconnect+put:
929

    
930
``PUT``
931
~~~~~~~
932

    
933
Returns a job ID. It supports the ``dry-run`` arguments.
934

    
935
Body parameters:
936

    
937
.. opcode_params:: OP_NETWORK_DISCONNECT
938

    
939
Job result:
940

    
941
.. opcode_result:: OP_NETWORK_DISCONNECT
942

    
943

    
944
.. _rapi-res-networks-network_name-tags:
945

    
946
``/2/networks/[network_name]/tags``
947
+++++++++++++++++++++++++++++++++++
948

    
949
Manages per-network tags.
950

    
951
.. rapi_resource_details:: /2/networks/[network_name]/tags
952

    
953

    
954
.. _rapi-res-networks-network_name-tags+get:
955

    
956
``GET``
957
~~~~~~~
958

    
959
Returns a list of tags.
960

    
961
Example::
962

    
963
    ["tag1", "tag2", "tag3"]
964

    
965

    
966
.. _rapi-res-networks-network_name-tags+put:
967

    
968
``PUT``
969
~~~~~~~
970

    
971
Add a set of tags.
972

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

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

    
978

    
979
.. _rapi-res-networks-network_name-tags+delete:
980

    
981
``DELETE``
982
~~~~~~~~~~
983

    
984
Delete a tag.
985

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

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

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

    
993

    
994
.. _rapi-res-instances-multi-alloc:
995

    
996
``/2/instances-multi-alloc``
997
++++++++++++++++++++++++++++
998

    
999
Tries to allocate multiple instances.
1000

    
1001
.. rapi_resource_details:: /2/instances-multi-alloc
1002

    
1003

    
1004
.. _rapi-res-instances-multi-alloc+post:
1005

    
1006
``POST``
1007
~~~~~~~~
1008

    
1009
The parameters:
1010

    
1011
.. opcode_params:: OP_INSTANCE_MULTI_ALLOC
1012

    
1013
Job result:
1014

    
1015
.. opcode_result:: OP_INSTANCE_MULTI_ALLOC
1016

    
1017

    
1018
.. _rapi-res-instances:
1019

    
1020
``/2/instances``
1021
++++++++++++++++
1022

    
1023
The instances resource.
1024

    
1025
.. rapi_resource_details:: /2/instances
1026

    
1027

    
1028
.. _rapi-res-instances+get:
1029

    
1030
``GET``
1031
~~~~~~~
1032

    
1033
Returns a list of all available instances.
1034

    
1035
Example::
1036

    
1037
    [
1038
      {
1039
        "name": "web.example.com",
1040
        "uri": "\/instances\/web.example.com"
1041
      },
1042
      {
1043
        "name": "mail.example.com",
1044
        "uri": "\/instances\/mail.example.com"
1045
      }
1046
    ]
1047

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

    
1052
Returned fields: :pyeval:`utils.CommaJoin(sorted(rlib2.I_FIELDS))`.
1053

    
1054
Example::
1055

    
1056
    [
1057
      {
1058
        "status": "running",
1059
        "disk_usage": 20480,
1060
        "nic.bridges": [
1061
          "xen-br0"
1062
        ],
1063
        "name": "web.example.com",
1064
        "tags": ["tag1", "tag2"],
1065
        "beparams": {
1066
          "vcpus": 2,
1067
          "memory": 512
1068
        },
1069
        "disk.sizes": [
1070
          20480
1071
        ],
1072
        "pnode": "node1.example.com",
1073
        "nic.macs": ["01:23:45:67:89:01"],
1074
        "snodes": ["node2.example.com"],
1075
        "disk_template": "drbd",
1076
        "admin_state": true,
1077
        "os": "debian-etch",
1078
        "oper_state": true,
1079
1080
      },
1081
1082
    ]
1083

    
1084

    
1085
.. _rapi-res-instances+post:
1086

    
1087
``POST``
1088
~~~~~~~~
1089

    
1090
Creates an instance.
1091

    
1092
If the optional bool *dry-run* argument is provided, the job will not be
1093
actually executed, only the pre-execution checks will be done. Query-ing
1094
the job result will return, in both dry-run and normal case, the list of
1095
nodes selected for the instance.
1096

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

    
1099
Body parameters:
1100

    
1101
``__version__`` (int, required)
1102
  Must be ``1`` (older Ganeti versions used a different format for
1103
  instance creation requests, version ``0``, but that format is no
1104
  longer supported)
1105

    
1106
.. opcode_params:: OP_INSTANCE_CREATE
1107

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

    
1112
Job result:
1113

    
1114
.. opcode_result:: OP_INSTANCE_CREATE
1115

    
1116

    
1117
.. _rapi-res-instances-instance_name:
1118

    
1119
``/2/instances/[instance_name]``
1120
++++++++++++++++++++++++++++++++
1121

    
1122
Instance-specific resource.
1123

    
1124
.. rapi_resource_details:: /2/instances/[instance_name]
1125

    
1126

    
1127
.. _rapi-res-instances-instance_name+get:
1128

    
1129
``GET``
1130
~~~~~~~
1131

    
1132
Returns information about an instance, similar to the bulk output from
1133
the instance list.
1134

    
1135
Returned fields: :pyeval:`utils.CommaJoin(sorted(rlib2.I_FIELDS))`.
1136

    
1137

    
1138
.. _rapi-res-instances-instance_name+delete:
1139

    
1140
``DELETE``
1141
~~~~~~~~~~
1142

    
1143
Deletes an instance.
1144

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

    
1147
Job result:
1148

    
1149
.. opcode_result:: OP_INSTANCE_REMOVE
1150

    
1151

    
1152
.. _rapi-res-instances-instance_name-info:
1153

    
1154
``/2/instances/[instance_name]/info``
1155
+++++++++++++++++++++++++++++++++++++++
1156

    
1157
.. rapi_resource_details:: /2/instances/[instance_name]/info
1158

    
1159

    
1160
.. _rapi-res-instances-instance_name-info+get:
1161

    
1162
``GET``
1163
~~~~~~~
1164

    
1165
Requests detailed information about the instance. An optional parameter,
1166
``static`` (bool), can be set to return only static information from the
1167
configuration without querying the instance's nodes. The result will be
1168
a job id.
1169

    
1170
Job result:
1171

    
1172
.. opcode_result:: OP_INSTANCE_QUERY_DATA
1173

    
1174

    
1175
.. _rapi-res-instances-instance_name-reboot:
1176

    
1177
``/2/instances/[instance_name]/reboot``
1178
+++++++++++++++++++++++++++++++++++++++
1179

    
1180
Reboots URI for an instance.
1181

    
1182
.. rapi_resource_details:: /2/instances/[instance_name]/reboot
1183

    
1184

    
1185
.. _rapi-res-instances-instance_name-reboot+post:
1186

    
1187
``POST``
1188
~~~~~~~~
1189

    
1190
Reboots the instance.
1191

    
1192
The URI takes optional ``type=soft|hard|full`` and
1193
``ignore_secondaries=0|1`` parameters.
1194

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

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

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

    
1207
Job result:
1208

    
1209
.. opcode_result:: OP_INSTANCE_REBOOT
1210

    
1211

    
1212
.. _rapi-res-instances-instance_name-shutdown:
1213

    
1214
``/2/instances/[instance_name]/shutdown``
1215
+++++++++++++++++++++++++++++++++++++++++
1216

    
1217
Instance shutdown URI.
1218

    
1219
.. rapi_resource_details:: /2/instances/[instance_name]/shutdown
1220

    
1221

    
1222
.. _rapi-res-instances-instance_name-shutdown+put:
1223

    
1224
``PUT``
1225
~~~~~~~
1226

    
1227
Shutdowns an instance.
1228

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

    
1231
.. opcode_params:: OP_INSTANCE_SHUTDOWN
1232
   :exclude: instance_name, dry_run
1233

    
1234
Job result:
1235

    
1236
.. opcode_result:: OP_INSTANCE_SHUTDOWN
1237

    
1238

    
1239
.. _rapi-res-instances-instance_name-startup:
1240

    
1241
``/2/instances/[instance_name]/startup``
1242
++++++++++++++++++++++++++++++++++++++++
1243

    
1244
Instance startup URI.
1245

    
1246
.. rapi_resource_details:: /2/instances/[instance_name]/startup
1247

    
1248

    
1249
.. _rapi-res-instances-instance_name-startup+put:
1250

    
1251
``PUT``
1252
~~~~~~~
1253

    
1254
Startup an instance.
1255

    
1256
The URI takes an optional ``force=1|0`` parameter to start the
1257
instance even if secondary disks are failing.
1258

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

    
1261
Job result:
1262

    
1263
.. opcode_result:: OP_INSTANCE_STARTUP
1264

    
1265

    
1266
.. _rapi-res-instances-instance_name-reinstall:
1267

    
1268
``/2/instances/[instance_name]/reinstall``
1269
++++++++++++++++++++++++++++++++++++++++++
1270

    
1271
Installs the operating system again.
1272

    
1273
.. rapi_resource_details:: /2/instances/[instance_name]/reinstall
1274

    
1275

    
1276
.. _rapi-res-instances-instance_name-reinstall+post:
1277

    
1278
``POST``
1279
~~~~~~~~
1280

    
1281
Returns a job ID.
1282

    
1283
Body parameters:
1284

    
1285
``os`` (string, required)
1286
  Instance operating system.
1287
``start`` (bool, defaults to true)
1288
  Whether to start instance after reinstallation.
1289
``osparams`` (dict)
1290
  Dictionary with (temporary) OS parameters.
1291

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

    
1296

    
1297
.. _rapi-res-instances-instance_name-replace-disks:
1298

    
1299
``/2/instances/[instance_name]/replace-disks``
1300
++++++++++++++++++++++++++++++++++++++++++++++
1301

    
1302
Replaces disks on an instance.
1303

    
1304
.. rapi_resource_details:: /2/instances/[instance_name]/replace-disks
1305

    
1306

    
1307
.. _rapi-res-instances-instance_name-replace-disks+post:
1308

    
1309
``POST``
1310
~~~~~~~~
1311

    
1312
Returns a job ID.
1313

    
1314
Body parameters:
1315

    
1316
.. opcode_params:: OP_INSTANCE_REPLACE_DISKS
1317
   :exclude: instance_name
1318

    
1319
Ganeti 2.4 and below used query parameters. Those are deprecated and
1320
should no longer be used.
1321

    
1322
Job result:
1323

    
1324
.. opcode_result:: OP_INSTANCE_REPLACE_DISKS
1325

    
1326

    
1327
.. _rapi-res-instances-instance_name-activate-disks:
1328

    
1329
``/2/instances/[instance_name]/activate-disks``
1330
+++++++++++++++++++++++++++++++++++++++++++++++
1331

    
1332
Activate disks on an instance.
1333

    
1334
.. rapi_resource_details:: /2/instances/[instance_name]/activate-disks
1335

    
1336

    
1337
.. _rapi-res-instances-instance_name-activate-disks+put:
1338

    
1339
``PUT``
1340
~~~~~~~
1341

    
1342
Takes the bool parameter ``ignore_size``. When set ignore the recorded
1343
size (useful for forcing activation when recorded size is wrong).
1344

    
1345
Job result:
1346

    
1347
.. opcode_result:: OP_INSTANCE_ACTIVATE_DISKS
1348

    
1349

    
1350
.. _rapi-res-instances-instance_name-deactivate-disks:
1351

    
1352
``/2/instances/[instance_name]/deactivate-disks``
1353
+++++++++++++++++++++++++++++++++++++++++++++++++
1354

    
1355
Deactivate disks on an instance.
1356

    
1357
.. rapi_resource_details:: /2/instances/[instance_name]/deactivate-disks
1358

    
1359

    
1360
.. _rapi-res-instances-instance_name-deactivate-disks+put:
1361

    
1362
``PUT``
1363
~~~~~~~
1364

    
1365
Takes no parameters.
1366

    
1367
Job result:
1368

    
1369
.. opcode_result:: OP_INSTANCE_DEACTIVATE_DISKS
1370

    
1371

    
1372
.. _rapi-res-instances-instance_name-recreate-disks:
1373

    
1374
``/2/instances/[instance_name]/recreate-disks``
1375
+++++++++++++++++++++++++++++++++++++++++++++++++
1376

    
1377
Recreate disks of an instance.
1378

    
1379
.. rapi_resource_details:: /2/instances/[instance_name]/recreate-disks
1380

    
1381

    
1382
.. _rapi-res-instances-instance_name-recreate-disks+post:
1383

    
1384
``POST``
1385
~~~~~~~~
1386

    
1387
Returns a job ID.
1388

    
1389
Body parameters:
1390

    
1391
.. opcode_params:: OP_INSTANCE_RECREATE_DISKS
1392
   :exclude: instance_name
1393

    
1394
Job result:
1395

    
1396
.. opcode_result:: OP_INSTANCE_RECREATE_DISKS
1397

    
1398

    
1399
.. _rapi-res-instances-instance_name-disk-disk_index-grow:
1400

    
1401
``/2/instances/[instance_name]/disk/[disk_index]/grow``
1402
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
1403

    
1404
Grows one disk of an instance.
1405

    
1406
.. rapi_resource_details:: /2/instances/[instance_name]/disk/[disk_index]/grow
1407

    
1408

    
1409
.. _rapi-res-instances-instance_name-disk-disk_index-grow+post:
1410

    
1411
``POST``
1412
~~~~~~~~
1413

    
1414
Returns a job ID.
1415

    
1416
Body parameters:
1417

    
1418
.. opcode_params:: OP_INSTANCE_GROW_DISK
1419
   :exclude: instance_name, disk
1420

    
1421
Job result:
1422

    
1423
.. opcode_result:: OP_INSTANCE_GROW_DISK
1424

    
1425

    
1426
.. _rapi-res-instances-instance_name-prepare-export:
1427

    
1428
``/2/instances/[instance_name]/prepare-export``
1429
+++++++++++++++++++++++++++++++++++++++++++++++++
1430

    
1431
Prepares an export of an instance.
1432

    
1433
.. rapi_resource_details:: /2/instances/[instance_name]/prepare-export
1434

    
1435

    
1436
.. _rapi-res-instances-instance_name-prepare-export+put:
1437

    
1438
``PUT``
1439
~~~~~~~
1440

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

    
1443
Job result:
1444

    
1445
.. opcode_result:: OP_BACKUP_PREPARE
1446

    
1447

    
1448
.. _rapi-res-instances-instance_name-export:
1449

    
1450
``/2/instances/[instance_name]/export``
1451
+++++++++++++++++++++++++++++++++++++++++++++++++
1452

    
1453
Exports an instance.
1454

    
1455
.. rapi_resource_details:: /2/instances/[instance_name]/export
1456

    
1457

    
1458
.. _rapi-res-instances-instance_name-export+put:
1459

    
1460
``PUT``
1461
~~~~~~~
1462

    
1463
Returns a job ID.
1464

    
1465
Body parameters:
1466

    
1467
.. opcode_params:: OP_BACKUP_EXPORT
1468
   :exclude: instance_name
1469
   :alias: target_node=destination
1470

    
1471
Job result:
1472

    
1473
.. opcode_result:: OP_BACKUP_EXPORT
1474

    
1475

    
1476
.. _rapi-res-instances-instance_name-migrate:
1477

    
1478
``/2/instances/[instance_name]/migrate``
1479
++++++++++++++++++++++++++++++++++++++++
1480

    
1481
Migrates an instance.
1482

    
1483
.. rapi_resource_details:: /2/instances/[instance_name]/migrate
1484

    
1485

    
1486
.. _rapi-res-instances-instance_name-migrate+put:
1487

    
1488
``PUT``
1489
~~~~~~~
1490

    
1491
Returns a job ID.
1492

    
1493
Body parameters:
1494

    
1495
.. opcode_params:: OP_INSTANCE_MIGRATE
1496
   :exclude: instance_name, live
1497

    
1498
Job result:
1499

    
1500
.. opcode_result:: OP_INSTANCE_MIGRATE
1501

    
1502

    
1503
.. _rapi-res-instances-instance_name-failover:
1504

    
1505
``/2/instances/[instance_name]/failover``
1506
+++++++++++++++++++++++++++++++++++++++++
1507

    
1508
Does a failover of an instance.
1509

    
1510
.. rapi_resource_details:: /2/instances/[instance_name]/failover
1511

    
1512

    
1513
.. _rapi-res-instances-instance_name-failover+put:
1514

    
1515
``PUT``
1516
~~~~~~~
1517

    
1518
Returns a job ID.
1519

    
1520
Body parameters:
1521

    
1522
.. opcode_params:: OP_INSTANCE_FAILOVER
1523
   :exclude: instance_name
1524

    
1525
Job result:
1526

    
1527
.. opcode_result:: OP_INSTANCE_FAILOVER
1528

    
1529

    
1530
.. _rapi-res-instances-instance_name-rename:
1531

    
1532
``/2/instances/[instance_name]/rename``
1533
++++++++++++++++++++++++++++++++++++++++
1534

    
1535
Renames an instance.
1536

    
1537
.. rapi_resource_details:: /2/instances/[instance_name]/rename
1538

    
1539

    
1540
.. _rapi-res-instances-instance_name-rename+put:
1541

    
1542
``PUT``
1543
~~~~~~~
1544

    
1545
Returns a job ID.
1546

    
1547
Body parameters:
1548

    
1549
.. opcode_params:: OP_INSTANCE_RENAME
1550
   :exclude: instance_name
1551

    
1552
Job result:
1553

    
1554
.. opcode_result:: OP_INSTANCE_RENAME
1555

    
1556

    
1557
.. _rapi-res-instances-instance_name-modify:
1558

    
1559
``/2/instances/[instance_name]/modify``
1560
++++++++++++++++++++++++++++++++++++++++
1561

    
1562
Modifies an instance.
1563

    
1564
.. rapi_resource_details:: /2/instances/[instance_name]/modify
1565

    
1566

    
1567
.. _rapi-res-instances-instance_name-modify+put:
1568

    
1569
``PUT``
1570
~~~~~~~
1571

    
1572
Returns a job ID.
1573

    
1574
Body parameters:
1575

    
1576
.. opcode_params:: OP_INSTANCE_SET_PARAMS
1577
   :exclude: instance_name
1578

    
1579
Job result:
1580

    
1581
.. opcode_result:: OP_INSTANCE_SET_PARAMS
1582

    
1583

    
1584
.. _rapi-res-instances-instance_name-snapshot:
1585

    
1586
``/2/instances/[instance_name]/snapshot``
1587
+++++++++++++++++++++++++++++++++++++++++
1588

    
1589
Takes snapshot of an instance's disk (must be ext template).
1590

    
1591
.. rapi_resource_details:: /2/instances/[instance_name]/snapshot
1592

    
1593

    
1594
.. _rapi-res-instances-instance_name-snapshot+put:
1595

    
1596
``PUT``
1597
~~~~~~~
1598

    
1599
Returns a job ID.
1600

    
1601
Body parameters:
1602

    
1603
.. opcode_params:: OP_INSTANCE_SNAPSHOT
1604
   :exclude: instance_name
1605

    
1606
Job result:
1607

    
1608
.. opcode_result:: OP_INSTANCE_SNAPSHOT
1609

    
1610

    
1611
.. _rapi-res-instances-instance_name-console:
1612

    
1613
``/2/instances/[instance_name]/console``
1614
++++++++++++++++++++++++++++++++++++++++
1615

    
1616
Request information for connecting to instance's console.
1617

    
1618
.. rapi_resource_details:: /2/instances/[instance_name]/console
1619

    
1620

    
1621
.. _rapi-res-instances-instance_name-console+get:
1622

    
1623
``GET``
1624
~~~~~~~
1625

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

    
1629
.. pyassert::
1630

    
1631
   constants.CONS_ALL == frozenset([
1632
     constants.CONS_MESSAGE,
1633
     constants.CONS_SSH,
1634
     constants.CONS_VNC,
1635
     constants.CONS_SPICE,
1636
     ])
1637

    
1638
.. pyassert::
1639

    
1640
  frozenset(objects.InstanceConsole.GetAllSlots()) == frozenset([
1641
    "command",
1642
    "display",
1643
    "host",
1644
    "instance",
1645
    "kind",
1646
    "message",
1647
    "port",
1648
    "user",
1649
    ])
1650

    
1651

    
1652
``instance``
1653
  Instance name
1654
``kind``
1655
  Console type, one of :pyeval:`constants.CONS_SSH`,
1656
  :pyeval:`constants.CONS_VNC`, :pyeval:`constants.CONS_SPICE`
1657
  or :pyeval:`constants.CONS_MESSAGE`
1658
``message``
1659
  Message to display (:pyeval:`constants.CONS_MESSAGE` type only)
1660
``host``
1661
  Host to connect to (:pyeval:`constants.CONS_SSH`,
1662
  :pyeval:`constants.CONS_VNC` or :pyeval:`constants.CONS_SPICE` only)
1663
``port``
1664
  TCP port to connect to (:pyeval:`constants.CONS_VNC` or
1665
  :pyeval:`constants.CONS_SPICE` only)
1666
``user``
1667
  Username to use (:pyeval:`constants.CONS_SSH` only)
1668
``command``
1669
  Command to execute on machine (:pyeval:`constants.CONS_SSH` only)
1670
``display``
1671
  VNC display number (:pyeval:`constants.CONS_VNC` only)
1672

    
1673

    
1674
.. _rapi-res-instances-instance_name-tags:
1675

    
1676
``/2/instances/[instance_name]/tags``
1677
+++++++++++++++++++++++++++++++++++++
1678

    
1679
Manages per-instance tags.
1680

    
1681
.. rapi_resource_details:: /2/instances/[instance_name]/tags
1682

    
1683

    
1684
.. _rapi-res-instances-instance_name-tags+get:
1685

    
1686
``GET``
1687
~~~~~~~
1688

    
1689
Returns a list of tags.
1690

    
1691
Example::
1692

    
1693
    ["tag1", "tag2", "tag3"]
1694

    
1695

    
1696
.. _rapi-res-instances-instance_name-tags+put:
1697

    
1698
``PUT``
1699
~~~~~~~
1700

    
1701
Add a set of tags.
1702

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

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

    
1708

    
1709
.. _rapi-res-instances-instance_name-tags+delete:
1710

    
1711
``DELETE``
1712
~~~~~~~~~~
1713

    
1714
Delete a tag.
1715

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

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

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

    
1723

    
1724
.. _rapi-res-jobs:
1725

    
1726
``/2/jobs``
1727
+++++++++++
1728

    
1729
The ``/2/jobs`` resource.
1730

    
1731
.. rapi_resource_details:: /2/jobs
1732

    
1733

    
1734
.. _rapi-res-jobs+get:
1735

    
1736
``GET``
1737
~~~~~~~
1738

    
1739
Returns a dictionary of jobs.
1740

    
1741
Returns: a dictionary with jobs id and uri.
1742

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

    
1747
Returned fields for bulk requests (unlike other bulk requests, these
1748
fields are not the same as for per-job requests):
1749
:pyeval:`utils.CommaJoin(sorted(rlib2.J_FIELDS_BULK))`.
1750

    
1751

    
1752
.. _rapi-res-jobs-job_id:
1753

    
1754
``/2/jobs/[job_id]``
1755
++++++++++++++++++++
1756

    
1757
Individual job URI.
1758

    
1759
.. rapi_resource_details:: /2/jobs/[job_id]
1760

    
1761

    
1762
.. _rapi-res-jobs-job_id+get:
1763

    
1764
``GET``
1765
~~~~~~~
1766

    
1767
Returns a dictionary with job parameters, containing the fields
1768
:pyeval:`utils.CommaJoin(sorted(rlib2.J_FIELDS))`.
1769

    
1770
The result includes:
1771

    
1772
- id: job ID as a number
1773
- status: current job status as a string
1774
- ops: involved OpCodes as a list of dictionaries for each opcodes in
1775
  the job
1776
- opstatus: OpCodes status as a list
1777
- opresult: OpCodes results as a list
1778

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

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

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

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

    
1796
.. pyassert::
1797

    
1798
   errors.ECODE_ALL == set([errors.ECODE_RESOLVER, errors.ECODE_NORES,
1799
     errors.ECODE_INVAL, errors.ECODE_STATE, errors.ECODE_NOENT,
1800
     errors.ECODE_EXISTS, errors.ECODE_NOTUNIQUE, errors.ECODE_FAULT,
1801
     errors.ECODE_ENVIRON, errors.ECODE_TEMP_NORES])
1802

    
1803
:pyeval:`errors.ECODE_RESOLVER`
1804
  Resolver errors. This usually means that a name doesn't exist in DNS,
1805
  so if it's a case of slow DNS propagation the operation can be retried
1806
  later.
1807

    
1808
:pyeval:`errors.ECODE_NORES`
1809
  Not enough resources (iallocator failure, disk space, memory,
1810
  etc.). If the resources on the cluster increase, the operation might
1811
  succeed.
1812

    
1813
:pyeval:`errors.ECODE_TEMP_NORES`
1814
  Simliar to :pyeval:`errors.ECODE_NORES`, but indicating the operation
1815
  should be attempted again after some time.
1816

    
1817
:pyeval:`errors.ECODE_INVAL`
1818
  Wrong arguments (at syntax level). The operation will not ever be
1819
  accepted unless the arguments change.
1820

    
1821
:pyeval:`errors.ECODE_STATE`
1822
  Wrong entity state. For example, live migration has been requested for
1823
  a down instance, or instance creation on an offline node. The
1824
  operation can be retried once the resource has changed state.
1825

    
1826
:pyeval:`errors.ECODE_NOENT`
1827
  Entity not found. For example, information has been requested for an
1828
  unknown instance.
1829

    
1830
:pyeval:`errors.ECODE_EXISTS`
1831
  Entity already exists. For example, instance creation has been
1832
  requested for an already-existing instance.
1833

    
1834
:pyeval:`errors.ECODE_NOTUNIQUE`
1835
  Resource not unique (e.g. MAC or IP duplication).
1836

    
1837
:pyeval:`errors.ECODE_FAULT`
1838
  Internal cluster error. For example, a node is unreachable but not set
1839
  offline, or the ganeti node daemons are not working, etc. A
1840
  ``gnt-cluster verify`` should be run.
1841

    
1842
:pyeval:`errors.ECODE_ENVIRON`
1843
  Environment error (e.g. node disk error). A ``gnt-cluster verify``
1844
  should be run.
1845

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

    
1849

    
1850
.. _rapi-res-jobs-job_id+delete:
1851

    
1852
``DELETE``
1853
~~~~~~~~~~
1854

    
1855
Cancel a not-yet-started job.
1856

    
1857

    
1858
.. _rapi-res-jobs-job_id-wait:
1859

    
1860
``/2/jobs/[job_id]/wait``
1861
+++++++++++++++++++++++++
1862

    
1863
.. rapi_resource_details:: /2/jobs/[job_id]/wait
1864

    
1865

    
1866
.. _rapi-res-jobs-job_id-wait+get:
1867

    
1868
``GET``
1869
~~~~~~~
1870

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

    
1874
``fields``
1875
  The job fields on which to watch for changes
1876

    
1877
``previous_job_info``
1878
  Previously received field values or None if not yet available
1879

    
1880
``previous_log_serial``
1881
  Highest log serial number received so far or None if not yet
1882
  available
1883

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

    
1887

    
1888
.. _rapi-res-nodes:
1889

    
1890
``/2/nodes``
1891
++++++++++++
1892

    
1893
Nodes resource.
1894

    
1895
.. rapi_resource_details:: /2/nodes
1896

    
1897

    
1898
.. _rapi-res-nodes+get:
1899

    
1900
``GET``
1901
~~~~~~~
1902

    
1903
Returns a list of all nodes.
1904

    
1905
Example::
1906

    
1907
    [
1908
      {
1909
        "id": "node1.example.com",
1910
        "uri": "\/nodes\/node1.example.com"
1911
      },
1912
      {
1913
        "id": "node2.example.com",
1914
        "uri": "\/nodes\/node2.example.com"
1915
      }
1916
    ]
1917

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

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

    
1924
Example::
1925

    
1926
    [
1927
      {
1928
        "pinst_cnt": 1,
1929
        "mfree": 31280,
1930
        "mtotal": 32763,
1931
        "name": "www.example.com",
1932
        "tags": [],
1933
        "mnode": 512,
1934
        "dtotal": 5246208,
1935
        "sinst_cnt": 2,
1936
        "dfree": 5171712,
1937
        "offline": false,
1938
1939
      },
1940
1941
    ]
1942

    
1943

    
1944
.. _rapi-res-nodes-node_name:
1945

    
1946
``/2/nodes/[node_name]``
1947
+++++++++++++++++++++++++++++++++
1948

    
1949
Returns information about a node.
1950

    
1951
.. rapi_resource_details:: /2/nodes/[node_name]
1952

    
1953

    
1954
.. _rapi-res-nodes-node_name+get:
1955

    
1956
``GET``
1957
~~~~~~~
1958

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

    
1961

    
1962

    
1963
.. _rapi-res-nodes-node_name-powercycle:
1964

    
1965
``/2/nodes/[node_name]/powercycle``
1966
+++++++++++++++++++++++++++++++++++
1967

    
1968
Powercycles a node.
1969

    
1970
.. rapi_resource_details:: /2/nodes/[node_name]/powercycle
1971

    
1972

    
1973
.. _rapi-res-nodes-node_name-powercycle+post:
1974

    
1975
``POST``
1976
~~~~~~~~
1977

    
1978
Returns a job ID.
1979

    
1980
Job result:
1981

    
1982
.. opcode_result:: OP_NODE_POWERCYCLE
1983

    
1984

    
1985
.. _rapi-res-nodes-node_name-evacuate:
1986

    
1987
``/2/nodes/[node_name]/evacuate``
1988
+++++++++++++++++++++++++++++++++
1989

    
1990
Evacuates instances off a node.
1991

    
1992
.. rapi_resource_details:: /2/nodes/[node_name]/evacuate
1993

    
1994

    
1995
.. _rapi-res-nodes-node_name-evacuate+post:
1996

    
1997
``POST``
1998
~~~~~~~~
1999

    
2000
Returns a job ID. The result of the job will contain the IDs of the
2001
individual jobs submitted to evacuate the node.
2002

    
2003
Body parameters:
2004

    
2005
.. opcode_params:: OP_NODE_EVACUATE
2006
   :exclude: nodes
2007

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

    
2012
Job result:
2013

    
2014
.. opcode_result:: OP_NODE_EVACUATE
2015

    
2016

    
2017
.. _rapi-res-nodes-node_name-migrate:
2018

    
2019
``/2/nodes/[node_name]/migrate``
2020
+++++++++++++++++++++++++++++++++
2021

    
2022
Migrates all primary instances from a node.
2023

    
2024
.. rapi_resource_details:: /2/nodes/[node_name]/migrate
2025

    
2026

    
2027
.. _rapi-res-nodes-node_name-migrate+post:
2028

    
2029
``POST``
2030
~~~~~~~~
2031

    
2032
If no mode is explicitly specified, each instances' hypervisor default
2033
migration mode will be used. Body parameters:
2034

    
2035
.. opcode_params:: OP_NODE_MIGRATE
2036
   :exclude: node_name
2037

    
2038
The query arguments used up to and including Ganeti 2.4 are deprecated
2039
and should no longer be used. The new request format can be detected by
2040
the presence of the :pyeval:`rlib2._NODE_MIGRATE_REQV1` feature string.
2041

    
2042
Job result:
2043

    
2044
.. opcode_result:: OP_NODE_MIGRATE
2045

    
2046

    
2047
.. _rapi-res-nodes-node_name-role:
2048

    
2049
``/2/nodes/[node_name]/role``
2050
+++++++++++++++++++++++++++++
2051

    
2052
Manages node role.
2053

    
2054
.. rapi_resource_details:: /2/nodes/[node_name]/role
2055

    
2056
The role is always one of the following:
2057

    
2058
  - drained
2059
  - master-candidate
2060
  - offline
2061
  - regular
2062

    
2063
Note that the 'master' role is a special, and currently it can't be
2064
modified via RAPI, only via the command line (``gnt-cluster
2065
master-failover``).
2066

    
2067

    
2068
.. _rapi-res-nodes-node_name-role+get:
2069

    
2070
``GET``
2071
~~~~~~~
2072

    
2073
Returns the current node role.
2074

    
2075
Example::
2076

    
2077
    "master-candidate"
2078

    
2079

    
2080
.. _rapi-res-nodes-node_name-role+put:
2081

    
2082
``PUT``
2083
~~~~~~~
2084

    
2085
Change the node role.
2086

    
2087
The request is a string which should be PUT to this URI. The result will
2088
be a job id.
2089

    
2090
It supports the bool ``force`` argument.
2091

    
2092
Job result:
2093

    
2094
.. opcode_result:: OP_NODE_SET_PARAMS
2095

    
2096

    
2097
.. _rapi-res-nodes-node_name-modify:
2098

    
2099
``/2/nodes/[node_name]/modify``
2100
+++++++++++++++++++++++++++++++
2101

    
2102
Modifies the parameters of a node.
2103

    
2104
.. rapi_resource_details:: /2/nodes/[node_name]/modify
2105

    
2106

    
2107
.. _rapi-res-nodes-node_name-modify+post:
2108

    
2109
``POST``
2110
~~~~~~~~
2111

    
2112
Returns a job ID.
2113

    
2114
Body parameters:
2115

    
2116
.. opcode_params:: OP_NODE_SET_PARAMS
2117
   :exclude: node_name
2118

    
2119
Job result:
2120

    
2121
.. opcode_result:: OP_NODE_SET_PARAMS
2122

    
2123

    
2124
.. _rapi-res-nodes-node_name-storage:
2125

    
2126
``/2/nodes/[node_name]/storage``
2127
++++++++++++++++++++++++++++++++
2128

    
2129
Manages storage units on the node.
2130

    
2131
.. rapi_resource_details:: /2/nodes/[node_name]/storage
2132

    
2133

    
2134
.. _rapi-res-nodes-node_name-storage+get:
2135

    
2136
``GET``
2137
~~~~~~~
2138

    
2139
FIXME: enable ".. pyassert::" again when all storage types are
2140
implemented::
2141

    
2142
   constants.VALID_STORAGE_TYPES == set([constants.ST_FILE,
2143
                                         constants.ST_LVM_PV,
2144
                                         constants.ST_LVM_VG])
2145

    
2146
Requests a list of storage units on a node. Requires the parameters
2147
``storage_type`` (one of :pyeval:`constants.ST_FILE`,
2148
:pyeval:`constants.ST_LVM_PV` or :pyeval:`constants.ST_LVM_VG`) and
2149
``output_fields``. The result will be a job id, using which the result
2150
can be retrieved.
2151

    
2152

    
2153
.. _rapi-res-nodes-node_name-storage-modify:
2154

    
2155
``/2/nodes/[node_name]/storage/modify``
2156
+++++++++++++++++++++++++++++++++++++++
2157

    
2158
Modifies storage units on the node.
2159

    
2160
.. rapi_resource_details:: /2/nodes/[node_name]/storage/modify
2161

    
2162

    
2163
.. _rapi-res-nodes-node_name-storage-modify+put:
2164

    
2165
``PUT``
2166
~~~~~~~
2167

    
2168
Modifies parameters of storage units on the node. Requires the
2169
parameters ``storage_type`` (one of :pyeval:`constants.ST_FILE`,
2170
:pyeval:`constants.ST_LVM_PV` or :pyeval:`constants.ST_LVM_VG`)
2171
and ``name`` (name of the storage unit).  Parameters can be passed
2172
additionally. Currently only :pyeval:`constants.SF_ALLOCATABLE` (bool)
2173
is supported. The result will be a job id.
2174

    
2175
Job result:
2176

    
2177
.. opcode_result:: OP_NODE_MODIFY_STORAGE
2178

    
2179

    
2180
.. _rapi-res-nodes-node_name-storage-repair:
2181

    
2182
``/2/nodes/[node_name]/storage/repair``
2183
+++++++++++++++++++++++++++++++++++++++
2184

    
2185
Repairs a storage unit on the node.
2186

    
2187
.. rapi_resource_details:: /2/nodes/[node_name]/storage/repair
2188

    
2189

    
2190
.. _rapi-res-nodes-node_name-storage-repair+put:
2191

    
2192
``PUT``
2193
~~~~~~~
2194

    
2195
.. pyassert::
2196

    
2197
   constants.VALID_STORAGE_OPERATIONS == {
2198
    constants.ST_LVM_VG: set([constants.SO_FIX_CONSISTENCY]),
2199
    }
2200

    
2201
Repairs a storage unit on the node. Requires the parameters
2202
``storage_type`` (currently only :pyeval:`constants.ST_LVM_VG` can be
2203
repaired) and ``name`` (name of the storage unit). The result will be a
2204
job id.
2205

    
2206
Job result:
2207

    
2208
.. opcode_result:: OP_REPAIR_NODE_STORAGE
2209

    
2210

    
2211
.. _rapi-res-nodes-node_name-tags:
2212

    
2213
``/2/nodes/[node_name]/tags``
2214
+++++++++++++++++++++++++++++
2215

    
2216
Manages per-node tags.
2217

    
2218
.. rapi_resource_details:: /2/nodes/[node_name]/tags
2219

    
2220

    
2221
.. _rapi-res-nodes-node_name-tags+get:
2222

    
2223
``GET``
2224
~~~~~~~
2225

    
2226
Returns a list of tags.
2227

    
2228
Example::
2229

    
2230
    ["tag1", "tag2", "tag3"]
2231

    
2232

    
2233
.. _rapi-res-nodes-node_name-tags+put:
2234

    
2235
``PUT``
2236
~~~~~~~
2237

    
2238
Add a set of tags.
2239

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

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

    
2245

    
2246
.. _rapi-res-nodes-node_name-tags+delete:
2247

    
2248
``DELETE``
2249
~~~~~~~~~~
2250

    
2251
Deletes tags.
2252

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

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

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

    
2260

    
2261
.. _rapi-res-query-resource:
2262

    
2263
``/2/query/[resource]``
2264
+++++++++++++++++++++++
2265

    
2266
Requests resource information. Available fields can be found in man
2267
pages and using ``/2/query/[resource]/fields``. The resource is one of
2268
:pyeval:`utils.CommaJoin(constants.QR_VIA_RAPI)`. See the :doc:`query2
2269
design document <design-query2>` for more details.
2270

    
2271
.. rapi_resource_details:: /2/query/[resource]
2272

    
2273

    
2274
.. _rapi-res-query-resource+get:
2275

    
2276
``GET``
2277
~~~~~~~
2278

    
2279
Returns list of included fields and actual data. Takes a query parameter
2280
named "fields", containing a comma-separated list of field names. Does
2281
not support filtering.
2282

    
2283

    
2284
.. _rapi-res-query-resource+put:
2285

    
2286
``PUT``
2287
~~~~~~~
2288

    
2289
Returns list of included fields and actual data. The list of requested
2290
fields can either be given as the query parameter "fields" or as a body
2291
parameter with the same name. The optional body parameter "filter" can
2292
be given and must be either ``null`` or a list containing filter
2293
operators.
2294

    
2295

    
2296
.. _rapi-res-query-resource-fields:
2297

    
2298
``/2/query/[resource]/fields``
2299
++++++++++++++++++++++++++++++
2300

    
2301
Request list of available fields for a resource. The resource is one of
2302
:pyeval:`utils.CommaJoin(constants.QR_VIA_RAPI)`. See the
2303
:doc:`query2 design document <design-query2>` for more details.
2304

    
2305
.. rapi_resource_details:: /2/query/[resource]/fields
2306

    
2307

    
2308
.. _rapi-res-query-resource-fields+get:
2309

    
2310
``GET``
2311
~~~~~~~
2312

    
2313
Returns a list of field descriptions for available fields. Takes an
2314
optional query parameter named "fields", containing a comma-separated
2315
list of field names.
2316

    
2317

    
2318
.. _rapi-res-os:
2319

    
2320
``/2/os``
2321
+++++++++
2322

    
2323
OS resource.
2324

    
2325
.. rapi_resource_details:: /2/os
2326

    
2327

    
2328
.. _rapi-res-os+get:
2329

    
2330
``GET``
2331
~~~~~~~
2332

    
2333
Return a list of all OSes.
2334

    
2335
Can return error 500 in case of a problem. Since this is a costly
2336
operation for Ganeti 2.0, it is not recommended to execute it too often.
2337

    
2338
Example::
2339

    
2340
    ["debian-etch"]
2341

    
2342

    
2343
.. _rapi-res-tags:
2344

    
2345
``/2/tags``
2346
+++++++++++
2347

    
2348
Manages cluster tags.
2349

    
2350
.. rapi_resource_details:: /2/tags
2351

    
2352

    
2353
.. _rapi-res-tags+get:
2354

    
2355
``GET``
2356
~~~~~~~
2357

    
2358
Returns the cluster tags.
2359

    
2360
Example::
2361

    
2362
    ["tag1", "tag2", "tag3"]
2363

    
2364

    
2365
.. _rapi-res-tags+put:
2366

    
2367
``PUT``
2368
~~~~~~~
2369

    
2370
Adds a set of tags.
2371

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

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

    
2377

    
2378
.. _rapi-res-tags+delete:
2379

    
2380
``DELETE``
2381
~~~~~~~~~~
2382

    
2383
Deletes tags.
2384

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

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

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

    
2392

    
2393
.. _rapi-res-version:
2394

    
2395
``/version``
2396
++++++++++++
2397

    
2398
The version resource.
2399

    
2400
This resource should be used to determine the remote API version and to
2401
adapt clients accordingly.
2402

    
2403
.. rapi_resource_details:: /version
2404

    
2405

    
2406
.. _rapi-res-version+get:
2407

    
2408
``GET``
2409
~~~~~~~
2410

    
2411
Returns the remote API version. Ganeti 1.2 returned ``1`` and Ganeti 2.0
2412
returns ``2``.
2413

    
2414

    
2415
.. _rapi-access-permissions:
2416

    
2417
Access permissions
2418
------------------
2419

    
2420
The following list describes the access permissions required for each
2421
resource. See :ref:`rapi-users` for more details.
2422

    
2423
.. rapi_access_table::
2424

    
2425

    
2426
.. vim: set textwidth=72 :
2427
.. Local Variables:
2428
.. mode: rst
2429
.. fill-column: 72
2430
.. End: