ovirt-engine-sdk 4.0.1 → 4.4.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.adoc CHANGED
@@ -1,4 +1,5 @@
1
1
  = oVirt Engine API Ruby SDK
2
+ :reference: http://www.rubydoc.info/gems/ovirt-engine-sdk/OvirtSDK4
2
3
 
3
4
  == Introduction
4
5
 
@@ -11,67 +12,763 @@ just installed the gem then you will have everything already, but if you
11
12
  downloaded the source then you will need to generate it, follow the
12
13
  instructions in the `README.adoc` file of the parent directory.
13
14
 
15
+ == Installation
16
+
17
+ The SDK can be installed in Fedora 24 and CentOS 7 using the RPM packages
18
+ provided by the oVirt project. To do so install the oVirt release package:
19
+
20
+ # dnf install http://resources.ovirt.org/pub/yum-repo/ovirt-release41.rpm
21
+
22
+ Then install the SDK package:
23
+
24
+ # dnf install rubygem-ovirt-engine-sdk4
25
+
26
+ For other operating systems (and also for Fedora and CentOS) you can
27
+ install the SDK using the `gem` command, which will download the source
28
+ from https://rubygems.org[RubyGems], build and install it:
29
+
30
+ $ gem install ovirt-engine-sdk
31
+
32
+ The SDK uses http://www.xmlsoft.org[libxml2] for parsing and rendering
33
+ XML and https://curl.haxx.se/libcurl[libcurl] for HTTP transfers. The
34
+ parts of the SDK that interact with those libraries are written in C.
35
+ This means that before building you must make sure you have the C
36
+ compiler and the required header and libraries files installed in your
37
+ system. For example, if you are using distributions like Fedora, or
38
+ CentOS:
39
+
40
+ # dnf -y install \
41
+ gcc \
42
+ libcurl-devel \
43
+ libxml2-devel \
44
+ redhat-rpm-config \
45
+ ruby \
46
+ ruby-devel \
47
+ rubygems \
48
+ rubygems-devel
49
+
50
+ NOTE: The installation of the `ruby`, `ruby-devel`, `rubygems` and
51
+ `rubygems-devel` packages is necessary if you are going to use the Ruby
52
+ version included in your distribution. If you are using tools like
53
+ `rbenv` or `rvm` then this is not necessary.
54
+
55
+ If you are using distributions like Debian, or Ubuntu:
56
+
57
+ # apt-get --assume-yes install \
58
+ gcc \
59
+ libcurl4-openssl-dev \
60
+ libxml2-dev \
61
+ ruby \
62
+ ruby-dev
63
+
64
+ NOTE: The installation of the `ruby` and `ruby-dev` packages is
65
+ necessary if you are going to use the Ruby version included in your
66
+ distribution. If you are using tools like `rbenv` or `rvm` then this is
67
+ not necessary.
68
+
69
+ Some Linux distributions, like Debian and Ubuntu, provide multiple
70
+ versions of `libcurl`, compiled with support for different TLS
71
+ libraries: OpenSSL, NSS and GnuTLS. Currently the SDK only supports
72
+ OpenSSL, so make sure that you have that version of `libcurl` installed.
73
+ For example, in Ubuntu 16.04 if you have the NSS version installed, you
74
+ will have to remove it and then install the OpenSSL version:
75
+
76
+ # apt-get --assume-yes remove libcurl4-nss-dev
77
+ # apt-get --assume-yes install libcurl4-openssl-dev
78
+
79
+ NOTE: The examples above use the `dnf` command, which is the default in
80
+ Fedora 24. In CentOS 7 you may need to use the `yum` command, as `dnf`
81
+ is optional.
82
+
14
83
  == Usage
15
84
 
16
- To use the SDK require the `ovirtsdk4` file. That will give you
17
- access to all the classes of the SDK, and in particular to the
18
- {OvirtSDK4::Connection} class. This is the entry point of the SDK,
19
- and gives you access to the root of the tree of services of the API:
85
+ === Modules and classes
86
+
87
+ All the classes of the SDK are inside the {reference}[OvirtSDK4] module.
88
+ Within the module there are several kinds of classes:
89
+
90
+ Connection::
91
+
92
+ The {reference}/Connection[Connection] class, as is the mechanism to
93
+ connect to the server and to get the reference to the root of the
94
+ services tree.
95
+
96
+ Errors::
97
+
98
+ The {reference}/Error[Error] class is the base exception class that the
99
+ SDK will raise when it needs to report any error.
100
+ +
101
+ For certain kinds of errors there are specific error classes, extending
102
+ the base error class:
103
+ +
104
+ * {reference}/AuthError[AuthError] - Raised when authentication or
105
+ authorization fail.
106
+ +
107
+ * {reference}/ConnectionError[ConnectionError] - Raised when the name of
108
+ the server can't be resolved, and when the server is down or
109
+ unreachable.
110
+ +
111
+ * {reference}/NotFoundError[NotFoundError] - Raised when the requested
112
+ object doesn't exist.
113
+ +
114
+ * {reference}/TimeoutError[TimeoutError] - Raised when an operation times
115
+ out.
20
116
 
117
+ Types::
118
+
119
+ These classes implement the _types_ used by the API. For example, the
120
+ {reference}/Vm[Vm] Ruby class is the implementation of the virtual
121
+ machine type. These classes are just containers of data, they don't
122
+ contain any logic.
123
+ +
124
+ Instances of these classes are used as parameters and return values of
125
+ _service methods_. The conversion to/from the underlying representation
126
+ is handled transparently by the SDK.
127
+
128
+ Services::
129
+
130
+ These classes implement the _services_ supported by the API. For
131
+ example, the {reference}/VmsService[VmsService] Ruby class is the
132
+ implementation of the service that manages the collection of virtual
133
+ machines of the system.
134
+ +
135
+ Instances of these classes are automatically created by the SDK when a
136
+ service is located. For example, a new instance of the `VmsService`
137
+ class will be automatically created by the SDK when doing the following:
138
+ +
21
139
  [source,ruby]
22
140
  ----
23
- require 'ovirtsdk4'
141
+ vms_service = connection.system_service.vms_service
142
+ ----
143
+ +
144
+ Avoid creating instances of these classes manually, as the parameters of
145
+ the constructors, and in general all the methods except the _service
146
+ locators_ and _service methods_ (described later) may change in the
147
+ future.
148
+
149
+ There are other classes, like HTTP client classes, readers and writers.
150
+ These are used to implement the HTTP communication, and for XML
151
+ parsing and rendering. Refrain from using them, as they are internal
152
+ implementation details that may change in the future: backwards
153
+ compatibility isn't guaranteed.
154
+
155
+ === Connecting to the server
24
156
 
157
+ To connect to the server require the `ovirtsdk4` file. That will give to
158
+ the {reference}/Connection[Connection] class. This is the entry point of
159
+ the SDK, and gives you access to the root of the tree of services of the
160
+ API:
161
+
162
+ [source,ruby]
163
+ ----
25
164
  # Create a connection to the server:
26
- connection = OvirtSDK4::Connection.new({
27
- :url => 'https://engine.example.com/ovirt-engine/api',
28
- :username => 'admin@internal',
29
- :password => '...',
30
- :ca_file => 'ca.pem',
31
- })
32
-
33
- # Get the reference to the system service:
165
+ connection = OvirtSDK4::Connection.new(
166
+ url: 'https://engine.example.com/ovirt-engine/api',
167
+ username: 'admin@internal',
168
+ password: '...',
169
+ ca_file: 'ca.pem',
170
+ )
171
+
172
+ # Get the reference to the root of the tree of services:
34
173
  system_service = connection.system_service
174
+ ----
175
+
176
+ The connection holds expensive resources, including a pool of HTTP
177
+ connections to the server and an authentication token. It is very
178
+ important to free these resources when they are no longer in use:
35
179
 
36
- # Always remember to close the connection when finished:
180
+ [source,ruby]
181
+ ----
182
+ # Close the connection to the server:
37
183
  connection.close
38
184
  ----
39
185
 
186
+ The connection and all the services that have been obtained from it
187
+ can't be used after the connection has been closed.
188
+
40
189
  The `ca.pem` file is required when connecting to a server protected
41
190
  with TLS. In an usual oVirt installation it will be in
42
191
  `/etc/pki/ovirt-engine/ca.pem`. If you don't specify `ca_file`, then
43
- the system wide CA certificate store will be used.
192
+ system wide CA certificate store will be used.
193
+
194
+ If something fails when trying to create the connection (authentication
195
+ failure, communication failure, etc) the SDK will raise a
196
+ {reference}/Error[Error] exception containing the details.
197
+
198
+ === Using _types_
199
+
200
+ The type classes are pure data containers, they don't have any logic or
201
+ operations. Instances can be created and modified at will.
202
+
203
+ Creating or modifying one of this instances does *not* have any effect
204
+ in the server side, unless they are explicitly passed to a call to one
205
+ of the service methods described below. Changes in the server side are
206
+ *not* automatically reflected in the instances that already exist in
207
+ memory.
208
+
209
+ The constructors of these classes have multiple optional arguments, one
210
+ for each attribute of the type. This is intended to simplify creation of
211
+ objects using nested calls to multiple constructors. For example, to
212
+ create an instance of a virtual machine, with an specification of the
213
+ cluster and template that it should use, and the memory it should have:
214
+
215
+ [source,ruby]
216
+ ----
217
+ vm = OvirtSDK4::Vm.new(
218
+ name: 'myvm',
219
+ cluster: OvirtSDK4::Cluster.new(
220
+ name: 'mycluster'
221
+ ),
222
+ template: OvirtSDK4::Template.new(
223
+ name: 'mytemplate'
224
+ ),
225
+ memory: 1073741824
226
+ )
227
+ ----
228
+
229
+ The hashes passed to these constructors are processed recursively. For
230
+ example, in the above code instead of explicitly calling the constructor
231
+ for the `Cluster` and `Template` classes it is also possible to use
232
+ plain hashes:
233
+
234
+ [source,ruby]
235
+ ----
236
+ vm = OvirtSDK4::Vm.new(
237
+ name: 'myvm',
238
+ cluster: {
239
+ name: 'mycluster'
240
+ },
241
+ template: {
242
+ name: 'mytemplate'
243
+ },
244
+ memory: 1073741824
245
+ )
246
+ ----
247
+
248
+ The SDK will internally convert those hashes to the required classes, so
249
+ the result will be exactly the same.
250
+
251
+ Using the constructors in this way is recommended, but not mandatory.
252
+ You can also create the instance with no arguments in the call to the
253
+ constructor, and then populate the object step by step, using the
254
+ setters, or using a mix of both approaches:
255
+
256
+ [source,ruby]
257
+ ----
258
+ vm = OvirtSDK4::Vm.new
259
+ vm.name = 'myvm'
260
+ vm.cluster = OvirtSDK4::Cluster.new(name: 'mycluster')
261
+ vm.template = OvirtSDK4::Template.new(name: 'mytemplate')
262
+ vm.memory = 1073741824
263
+ ----
264
+
265
+ Attributes that are defined as lists of objects in the specification of
266
+ the API are implemented as Ruby arrays. For example, the
267
+ `custom_properties` attributes of the
268
+ http://ovirt.github.io/ovirt-engine-api-model/master/#types/vm[Vm] type
269
+ is defined as a list of objects of type `CustomProperty`, so when using
270
+ it in the SDK it will be a Ruby array:
271
+
272
+ [source,ruby]
273
+ ----
274
+ vm = OvirtSDK4::Vm.new(
275
+ name: 'myvm',
276
+ custom_properties: [
277
+ OvirtSDK4::CustomProperty.new(...),
278
+ OvirtSDK4::CustomProperty.new(...),
279
+ ...
280
+ ]
281
+ )
282
+ ----
283
+
284
+ Attributes that are defined as enumerated values in the specification of
285
+ the API are implemented as constatns within a module that has the same
286
+ name than the enumerated type. For example, the `status` attribute of
287
+ the `Vm` type is defined using the
288
+ http://ovirt.github.io/ovirt-engine-api-model/master/#types/vm_status[VmStatus]
289
+ enum:
290
+
291
+ [source,ruby]
292
+ ----
293
+ case vm.status
294
+ when OvirtSDK4::VmStatus::DOWN
295
+ ...
296
+ when OvirtSDK4::VmStatus::IMAGE_LOCKED
297
+ ...
298
+ end
299
+ ----
300
+
301
+ NOTE: In the specification of the API the values of enum types appear in
302
+ lower case, because that is what is used in the XML or JSON documents,
303
+ but in Ruby it is common practice to use upper case for this kind of
304
+ constants, so that is how they are defined in the Ruby SDK: all upper
305
+ case.
306
+
307
+ Reading the attributes of instances of types is done using the
308
+ corresponding attribute readers:
309
+
310
+ [source,ruby]
311
+ ----
312
+ puts "vm.name: #{vm.name}"
313
+ puts "vm.memory: #{vm.memory}"
314
+ vm.custom_properties.each do |custom_property|
315
+ ...
316
+ end
317
+ ----
318
+
319
+ === Using _links_
320
+
321
+ Some of the attributes of types are defined as _links_ in the
322
+ specification of the API. This is done to indicate that their value
323
+ won't usually be populated when retrieving the representation of that
324
+ object, only a link will be returned instead. For example, when
325
+ retrieving a virtual machine, the XML returned by the server will look
326
+ like this:
327
+
328
+ [source,xml]
329
+ ----
330
+ <vm id="123" href="/ovirt-engine/api/vms/123">
331
+ <name>myvm</name>
332
+ <link rel="diskattachments" href="/ovirt-engine/api/vms/123/diskattachments/>
333
+ ...
334
+ </vm>
335
+ ----
336
+
337
+ That link is available as `vm.disk_attachments`, but it doesn't contain
338
+ the actual disk attachments. To get the actual data the
339
+ {reference}/Connection[Connection] class provides a
340
+ {reference}/Connection#follow_link-instance_method[follow_link] method
341
+ that uses the value of the `href` XML attribute to retrieve the actual
342
+ data. For example, to retrieve the details of the disks of the virtual
343
+ machine, you can first follow the link to the disk attachments, and then
344
+ follow the link to each of the disks:
345
+
346
+ [source,ruby]
347
+ ----
348
+ # Retrieve the virtual machine:
349
+ vm = vm_service.get
350
+
351
+ # Follow the link to the disk attachments, and then to the disks:
352
+ attachments = connection.follow_link(vm.disk_attachments)
353
+ attachments.each do |attachment|
354
+ disk = connection.follow_link(attachment.disk)
355
+ puts "disk.alias: #{disk.alias}"
356
+ end
357
+ ----
358
+
359
+ === Locating services
360
+
361
+ The API provides a set of _services_, each associated to a particular
362
+ path within the URL space of the server. For example, the service that
363
+ manages the collection of virtual machines of the system lives in
364
+ `/vms`, and the service that manages the virtual machine with identifier
365
+ `123` lives in `/vms/123`.
44
366
 
45
- Once you have the reference to the system service you can use it to get
46
- references to other services, and call their methods. For example, to
47
- retrieve the list of virtual machines of the system you can use the
48
- `vms_service` method, which returns a reference to the service that
49
- manages the virtual machines:
367
+ In the SDK the root of that tree of services is implemented by the
368
+ _system service_. It is obtained calling the
369
+ {reference}/Connection#system_service-instance_method[system_service]
370
+ method of the connection:
371
+
372
+ [source,ruby]
373
+ ----
374
+ system_service = connection.system_service
375
+ ----
376
+
377
+ Once you have the reference to this system service you can use it to get
378
+ references to other services, calling the `+*_service+` methods (called
379
+ _service locators_) of the previous service. For example, to get a
380
+ reference to the service that manages the collection of virtual machines
381
+ of the system use the
382
+ {reference}/SystemService#vms_service-instance_method[vms_service]
383
+ service locator:
50
384
 
51
385
  [source,ruby]
52
386
  ----
53
- # Get the reference to the "vms" service:
54
387
  vms_service = system_service.vms_service
55
388
  ----
56
389
 
57
- This service is an instance of {OvirtSDK4::VmsService}, and it has
58
- a `list` method that returns an array of virtual machines, which are
59
- instances of the {OvirtSDK4::Vm} class:
390
+ To get a reference to the service that manages the virtual machine with
391
+ identifier `123`, use the
392
+ {reference}/VmsService#vm_service-instance_method[vm_service] service
393
+ locator of the service that manages the collection of virtual machines.
394
+ It receives as a parameter the identifier of the virtual machine:
60
395
 
61
396
  [source,ruby]
62
397
  ----
63
- # Retrieve the virtual machines:
398
+ vm_service = vms_service.vms_service('123')
399
+ ----
400
+
401
+ IMPORTANT: Calling the service locators doesn't send any request to the
402
+ server. The Ruby objects that they return are pure services, they
403
+ don't contain any data. For example, the `vm_service` Ruby object
404
+ obtained in the previous example is *not* the representation of a
405
+ virtual machine. It is the service that can be used to retrieve, update,
406
+ delete, start and stop that virtual machine.
407
+
408
+ === Using services
409
+
410
+ Once you have located the service you are interested on, you can start
411
+ calling its _service methods_, the methods that send requests to the
412
+ server and do the real work.
413
+
414
+ The services that manage collections of object usually have the `list`
415
+ and `add` methods.
416
+
417
+ The services that manage a single object usually have the `get`,
418
+ `update` and `remove` methods.
419
+
420
+ Both kinds of services can also have additional _action methods_, which
421
+ perform actions other than retrieving, creating, updating or removing.
422
+ Most frequently they are available in services that manage a single
423
+ object.
424
+
425
+ ==== Using the _get_ methods
426
+
427
+ These service methods are used to retrieve the representation of a
428
+ single object. For example, to retrieve the representation of the
429
+ virtual machine with identifier `123`:
430
+
431
+ [source,ruby]
432
+ ----
433
+ # Find the service that manages the virtual machine:
434
+ vms_service = system_service.vms_service
435
+ vm_service = vms_service.vm_service('123')
436
+
437
+ # Retrieve the representation of the virtual machine:
438
+ vm = vm_service.get
439
+ ----
440
+
441
+ The result will be an instance of the corresponding type. For example,
442
+ in this case, the result will be an instance of the Ruby class
443
+ {reference}/Vm[Vm].
444
+
445
+ The `get` methods of some services support additional parameters that
446
+ control how to retrieve the representation of the object, or what
447
+ representation to retrieve in case there are multiple representations.
448
+ For example, for virtual machines you may want to retrieve its current
449
+ state, or the state that will be used the next time it is started, as
450
+ they may be different. To do so the `get` method of the service that
451
+ manages a virtual machine supports a
452
+ http://ovirt.github.io/ovirt-engine-api-model/master/#services/vm/methods/get/parameters/next_run[next_run]
453
+ boolean parameter:
454
+
455
+ [source,ruby]
456
+ ----
457
+ # Retrieve the representation of the virtual machine, not the
458
+ # current one, but the one that will be used after the next
459
+ # boot:
460
+ vm = vm_service.get(next_run: true)
461
+ ----
462
+
463
+ Check the {reference}[reference] documentation of the SDK to find out
464
+ the details.
465
+
466
+ If the object can't be retrieved, for whatever reason, the SDK will
467
+ raise an {reference}/Error[Error] exception, containing the details of
468
+ the failure. This includes the situation when the object doesn't
469
+ actually exist. Note that the exception will be raised when calling the
470
+ `get` service method, the call to the service locator method never
471
+ fails, even if the object doesn't exist, because it doesn't send any
472
+ request to the server. For example:
473
+
474
+ [source,ruby]
475
+ ----
476
+ # Find the service that manages a virtual machine that does
477
+ # not exist. This will succeed.
478
+ vm_service = vms_service.vm_service('junk')
479
+
480
+ # Retrieve the virtual machine. This will raise an exception.
481
+ vm = vm_service.get
482
+ ----
483
+
484
+ ==== Using the _list_ methods
485
+
486
+ These service methods are used to retrieve the representations of the
487
+ objects of the collection. For example, to retrieve the complete
488
+ collection of virtual machines of the system:
489
+
490
+ [source,ruby]
491
+ ----
492
+ # Find the service that manages the collection of virtual
493
+ # machines:
494
+ vms_service = system_service.vms_service
64
495
  vms = vms_service.list
496
+ ----
497
+
498
+ The result will be a Ruby array containing the instances of the
499
+ corresponding types. For example, in this case, the result will be a
500
+ list of instances of the Ruby class {reference}/Vm[Vm].
501
+
502
+ The `list` methods of some services support additional parameters. For
503
+ example, almost all the top level collections support a `search`
504
+ parameter that can be used ask the server to filter the results, and a
505
+ `max` parameter that can be used to limit the number of results returned
506
+ by the server. For example, to get the list of virtual machines whose
507
+ name starts with `my`, and to get at most 10 results:
508
+
509
+ [source,ruby]
510
+ ----
511
+ vms = vms_service.list(search: 'name=my*', max: 10)
512
+ ----
65
513
 
66
- # Print the names and identifiers of the virtual machines:
67
- vms.each do |vm|
68
- puts "#{vm.name}: #{vm.id}"
514
+ NOTE: Not all the `list` methods support these parameters, and some
515
+ `list` methods may support other additional parameters. Check the
516
+ {reference}[reference] documentation of the SDK to find out the details.
517
+
518
+ If list of results is empty, for whatever reason, the returned value
519
+ will be an empty Ruby array, it will never be `nil`.
520
+
521
+ If there is an error while trying to retrieve the result, then the SDK
522
+ will raise an {reference}/Error[Error] exception containing the details
523
+ of the failure.
524
+
525
+ ==== Using the _add_ methods
526
+
527
+ These service methods add new elements to collections. They receive an
528
+ instance of the relevant type describing the object to add, send the
529
+ request to add it, and return an instance of the type describing the
530
+ added object.
531
+
532
+ For example, to add a new virtual machine named `myvm`:
533
+
534
+ [source,ruby]
535
+ ----
536
+ # Add the virtual machine:
537
+ vm = vms_service.add(
538
+ OvirtSDK4::Vm.new(
539
+ name: 'myvm',
540
+ cluster: {
541
+ name: 'mycluster'
542
+ },
543
+ template: {
544
+ name: 'mytemplate'
545
+ }
546
+ )
547
+ )
548
+ ----
549
+
550
+ If the object can't be created, for whatever reason, the SDK will
551
+ raise an {reference}/Error[Error] exception containing the details of
552
+ the failure. It will never return `nil`.
553
+
554
+ It is very important to understand that the Ruby object returned by this
555
+ `add` method is an instance of the relevant type, it isn't a service,
556
+ just a container of data. In this particular example the returned object
557
+ will be an instance of the {reference}/Vm[Vm] class. If once the
558
+ virtual machine is created you need to perform some operation on it,
559
+ like retrieving it again, or starting it, you will first need to find
560
+ the service that manages it, calling the corresponding service locator:
561
+
562
+ [source,ruby]
563
+ ----
564
+ # Add the virtual machine:
565
+ vm = vms_service.add(
566
+ ...
567
+ )
568
+
569
+ # Find the service that manages the virtual machine:
570
+ vm_service = vms_service.vm_service(vm.id)
571
+
572
+ # Perform some other operation on the virtual machine, like
573
+ # starting it:
574
+ vm_service.start
575
+ ----
576
+
577
+ Note that the creation of most objects is an asynchronous task. That
578
+ means, for example, that when creating a new virtual machine the `add`
579
+ method will return *before* the virtual machine is completely created
580
+ and ready to be used. It is good practice to poll the status of the
581
+ object till it is completely created. For a virtual machine that means
582
+ checking till the status is _down_. So the recommended approach to create
583
+ a virtual machine is the following:
584
+
585
+ [source,ruby]
586
+ ----
587
+ # Add the virtual machine:
588
+ vm = vms_service.add(
589
+ ...
590
+ )
591
+
592
+ # Find the service that manages the virtual machine:
593
+ vm_service = vms_service.vm_service(vm.id)
594
+
595
+ # Wait till the virtual machine is down, which indicats that all the
596
+ # disks have been created:
597
+ loop do
598
+ sleep(5)
599
+ vm = vm_service.get
600
+ break if vm.status == OvirtSDK4::VmStatus::DOWN
69
601
  end
70
602
  ----
71
603
 
72
- You will find more usage examples in the `examples` directory.
604
+ In the above loop it is very important to retrieve the object each time,
605
+ using the `get` method, otherwise the `status` attribute won't be
606
+ updated.
607
+
608
+ ==== Using the _update_ methods
609
+
610
+ These service methods update existing objects. They receive an instance
611
+ of the relevant type describing the update to perform, send the request
612
+ to update it, and return an instance of the type describing the updated
613
+ object.
614
+
615
+ For example, to update the name of a virtual machine from `myvm` to
616
+ `newvm`:
617
+
618
+ [source,ruby]
619
+ ----
620
+ # Find the virtual machine, and then the service that
621
+ # manages it:
622
+ vm = vms_service.list(search: 'name=myvm').first
623
+ vm_service = vms_service.vm_service(vm.id)
624
+
625
+ # Update the name:
626
+ updated_vm = vms_service.update(
627
+ OvirtSDK4::Vm.new(
628
+ name: 'newvm'
629
+ )
630
+ )
631
+ ----
632
+
633
+ When performing updates, try to avoid sending the complete
634
+ representation of the object, send only the attributes that you want to
635
+ update. For example, try to *avoid* this:
636
+
637
+ [source,ruby]
638
+ ----
639
+ # Retrieve the current representation:
640
+ vm = vm_service.get
641
+
642
+ # Update the representation, in memory, no request sent
643
+ # to the server:
644
+ vm.name = 'newvm'
645
+
646
+ # Send the update. Do *not* do this.
647
+ vms_service.update(vm)
648
+ ----
649
+
650
+ The problem with that is double. First you are sending much more
651
+ information than what the server needs, thus wasting resources. Second,
652
+ and more important, the server will try to update all the attributes of
653
+ the object, even those that you didn't need to change. Usually that
654
+ isn't a problem, but has caused many unexpected bugs in the server side
655
+ in the past.
656
+
657
+ The `update` methods of some services support additional parameters that
658
+ control how or what to update. For example, for virtual machines you may
659
+ want to update its current state, or the state that will be used the
660
+ next time it is started. To do so the `update` method of the service
661
+ that manages a virtual machine supports a
662
+ http://ovirt.github.io/ovirt-engine-api-model/master/#services/vm/methods/update/parameters/next_run[next_run]
663
+ boolean parameter:
664
+
665
+ [source,ruby]
666
+ ----
667
+ # Update the memory of the virtual machine 1 GiB, but not the current
668
+ # one, the one it will have after the next boot:
669
+ vm = vm_service.update(
670
+ OvirtSDK4::Vm.new(
671
+ memory: 1073741824
672
+ ),
673
+ next_run: true
674
+ )
675
+ ----
676
+
677
+ If the update can't be performed, for whatever reason, the SDK will
678
+ raise an {reference}/Error[Error] exception containing the details of
679
+ the failure. It will never return `nil`.
680
+
681
+ The Ruby object returned by this `update` method is an instance of the
682
+ relevant type, it isn't a service, just a container of data. In this
683
+ particular example the returned object will be an instance of the
684
+ {reference}/Vm[Vm] class.
685
+
686
+ ==== Using the _remove_ methods
687
+
688
+ These service methods remove existing objects. They usually don't
689
+ receive any parameters, as they are methods of the services that manage
690
+ single objects, therefore the service already knows what object to
691
+ remove.
692
+
693
+ For example, to remove the virtual machine with identifier `123`:
694
+
695
+ [source,ruby]
696
+ ----
697
+ # Find the service that manages the virtual machine:
698
+ vm_service = vms_service.vm_service('123')
699
+
700
+ # Remove the virtual machine:
701
+ vms_service.remove
702
+ ----
703
+
704
+ The `remove` methods of some services support additional parameters that
705
+ control how or what to remove. For example, for virtual machines it is
706
+ possible to remove the virtual machine while preserving the disks.
707
+ To do so the `remove` method of the service that manages a virtual machine supports a
708
+ http://ovirt.github.io/ovirt-engine-api-model/master/#services/vm/methods/remove[detach_only]
709
+ boolean parameter:
710
+
711
+ [source,ruby]
712
+ ----
713
+ # Remove the virtual machine, but preserve the disks:
714
+ vm_service.remove(detach_only: true)
715
+ ----
716
+
717
+ The `remove` methods return `nil` if the object is removed successfully.
718
+ It does *not* return the removed object. If the object can't be removed,
719
+ for whatever reason, the SDK will raise an {reference}/Vm[Vm]
720
+ exception containing the details of the failure.
721
+
722
+ ==== Using _action_ methods
723
+
724
+ These service methods perform miscellaneous operations. For example, the
725
+ service that manages a virtual machine has methods to start and stop it:
726
+
727
+ [source,ruby]
728
+ ----
729
+ # Start the virtual machine:
730
+ vm_service.start
731
+ ----
732
+
733
+ Many of these methods include parameters that modify the operation. For
734
+ example, the method that starts a virtual machine supports a
735
+ http://ovirt.github.io/ovirt-engine-api-model/master/#services/vm/methods/start/parameters/use_cloud_init[use_cloud_init]
736
+ parameter that indicates if you want to start it using
737
+ https://cloudinit.readthedocs.io/cloud-init[cloud-init]:
738
+
739
+ [source,ruby]
740
+ ----
741
+ # Start the virtual machine:
742
+ vm_service.start(cloud_init: true)
743
+ ----
744
+
745
+ Most action methods return `nil` when they succeed, and raise a
746
+ {reference}/Error[Error] when they fail. But a few action methods return
747
+ values. For example, the service that manages a storage domains has an
748
+ http://ovirt.github.io/ovirt-engine-api-model/master/#services/storage_domain/methods/is_attachedd[is_attached]
749
+ action method that checks if the storage domain is already attached to a
750
+ data center. That method returns a boolean:
751
+
752
+ [source,ruby]
753
+ ----
754
+ # Check if the storage domain is attached to a data center:
755
+ sds_service = system_service.storage_domains_service
756
+ sd_service = sds_service.storage_domain_service('123')
757
+ if sd_service.is_attached
758
+ ...
759
+ end
760
+ ----
761
+
762
+ Check the {reference}[reference] documentation of the SDK to see the
763
+ action methods supported by each service, the parameters that they
764
+ support, and the values that they return.
765
+
766
+ == More information
767
+
768
+ The reference documentation of the API is available
769
+ http://ovirt.github.io/ovirt-engine-api-model[here].
73
770
 
74
- == Reference
771
+ The reference documentation of the SDK is available {reference}[here].
75
772
 
76
- The reference documentation is available
77
- http://www.rubydoc.info/gems/ovirt-engine-sdk[here].
773
+ There is a collection of examples that show how to use the SDK
774
+ https://github.com/oVirt/ovirt-engine-sdk-ruby/tree/master/sdk/examples[here].