Class: Ovirt::Vm

Inherits:
Template show all
Includes:
CloudInitViaFloppyPayload
Defined in:
lib/ovirt/vm.rb

Constant Summary

Constants inherited from Template

Template::ALLOWED_CLONE_TYPES, Template::CLONE_ATTRIBUTES_WITH_HASHES, Template::CLONE_ATTRIBUTES_WITH_SCALARS, Template::REQUIRED_CLONE_PARAMETERS

Instance Attribute Summary collapse

Attributes inherited from Base

#attributes, #operations, #relationships, #service

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Template

#create_vm, #getCfg, #os_type, parse_node_extended

Methods inherited from Base

#[], all, all_xml_objects, api_endpoint, #api_endpoint, #class_suffix, create_from_xml, element_name, element_names, find_by_href, find_by_id, find_by_name, has_first_node?, hash_from_id_and_href, href_from_creation_status_link, #keys, #method_missing, object_to_id, #operation, parse_attribute, parse_boolean, parse_first_node, parse_first_node_with_hash, parse_first_text, #relationship, #reload, #replace, set_value, #update, #update!, xml_to_actions, xml_to_hash, xml_to_nokogiri, xml_to_relationships

Constructor Details

#initialize(*args) ⇒ Vm

Returns a new instance of Vm.



15
16
17
18
19
# File 'lib/ovirt/vm.rb', line 15

def initialize(*args)
  super

  @creation_status_link = @relationships.delete(:creation_status)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Ovirt::Base

Instance Attribute Details

Returns the value of attribute creation_status_link.



13
14
15
# File 'lib/ovirt/vm.rb', line 13

def creation_status_link
  @creation_status_link
end

Class Method Details

.parse_xml(xml) ⇒ Object



270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'lib/ovirt/vm.rb', line 270

def self.parse_xml(xml)
  hash = super
  node = xml_to_nokogiri(xml)

  parse_first_node(node, :placement_policy, hash,
                   :node => [:affinity])

  parse_first_node_with_hash(node, 'placement_policy/host', hash[:placement_policy][:host] = {},
                             :attribute => [:id])

  parse_first_node(node, :memory_policy, hash,
                   :node_to_i => [:guaranteed])

  hash[:guest_info] = {}
  node.xpath('guest_info').each do |gi|
    ips = hash[:guest_info][:ips] = []
    gi.xpath('ips/ip').each do |ip|
      ips << {:address => ip[:address]}
    end
  end

  hash
end

Instance Method Details

#attach_floppy(files) ⇒ Object

Attaches the files as a floppy drive payload.

files

Hash of file_name => content that will be attached as a floppy



230
231
232
# File 'lib/ovirt/vm.rb', line 230

def attach_floppy(files)
  attach_payload("floppy" => files || {})
end

#attach_payload(payloads) ⇒ Object

Attaches a payload.

payloads

Hash of payload_type => => content that will be

attached.  Acceptable payload_types are floppy or cdrom.


159
160
161
# File 'lib/ovirt/vm.rb', line 159

def attach_payload(payloads)
  send("attach_payload_#{payload_version}".to_sym, payloads)
end

#attach_payload_3_0(payloads) ⇒ Object



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/ovirt/vm.rb', line 172

def attach_payload_3_0(payloads)
  update! do |xml|
    xml.payloads do
      payloads.each do |type, files|
        xml.payload(:type => type) do
          files.each do |file_name, content|
            xml.file(:name => file_name) do
              xml.content content
            end
          end
        end
      end
    end
  end
end

#attach_payload_3_3(payloads) ⇒ Object



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/ovirt/vm.rb', line 188

def attach_payload_3_3(payloads)
  update! do |xml|
    xml.payloads do
      payloads.each do |type, files|
        xml.payload(:type => type) do
          xml.files do
            files.each do |file_name, content|
              xml.file do
                xml.name file_name
                xml.content content
              end
            end
          end
        end
      end
    end
  end
end

#boot_from_cdrom(iso_file_name) ⇒ Object



252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
# File 'lib/ovirt/vm.rb', line 252

def boot_from_cdrom(iso_file_name)
  start do |xml|
    xml.vm do
      xml.os do
        xml.boot(:dev => 'cdrom')
      end
      xml.cdroms do
        xml.cdrom do
          xml.file(:id => iso_file_name)
        end
      end
    end
  end
rescue Ovirt::Error => err
  raise VmNotReadyToBoot, [err.message, err] if err.message =~ /disks .+ are locked/
  raise
end

#boot_from_networkObject



239
240
241
242
243
244
245
246
247
248
249
250
# File 'lib/ovirt/vm.rb', line 239

def boot_from_network
  start do |xml|
    xml.vm do
      xml.os do
        xml.boot(:dev => 'network')
      end
    end
  end
rescue Ovirt::Error => err
  raise VmNotReadyToBoot, [err.message, err] if err.message =~ /disks .+ are locked/
  raise
end

#boot_order=(devices) ⇒ Object



83
84
85
86
87
88
89
90
91
92
# File 'lib/ovirt/vm.rb', line 83

def boot_order=(devices)
  devices = [devices].flatten
  update! do |xml|
    xml.os do
      devices.each do |d|
        xml.boot(:dev => d)
      end
    end
  end
end

#cloud_init=(content) ⇒ Object



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/ovirt/vm.rb', line 139

def cloud_init=(content)
  if service.version[:major].to_i == 3 && service.version[:minor].to_i < 4
    super  # Use legacy method defined in CloudInitViaFloppyPayload
  else
    begin
      update! do |xml|
        xml.initialization do
          converted_cloud_init(content).each { |k, v| xml.send(k, v) }
        end
      end
    rescue Ovirt::UsageError => err
      raise CloudInitSyntaxError, err.message
    end
  end
end

#cpu_topology=(cpu_hash) ⇒ Object

cpu_hash needs to look like { :cores => 1, :sockets => 1 }



95
96
97
98
99
100
101
102
# File 'lib/ovirt/vm.rb', line 95

def cpu_topology=(cpu_hash)
  update! do |xml|
    xml.cpu do
      xml.topology(cpu_hash)
    end
    xml.memory self[:memory]  # HACK: RHEVM BUG: RHEVM resets it to 10GB, unless we set it
  end
end

#create_device(device_type) ⇒ Object



294
295
296
297
298
299
300
301
302
# File 'lib/ovirt/vm.rb', line 294

def create_device(device_type)
  builder = Nokogiri::XML::Builder.new do |xml|
    xml.send(device_type) { yield xml if block_given? }
  end
  data = builder.doc.root.to_xml
  path = "#{api_endpoint}/#{device_type.pluralize}"

  @service.resource_post(path, data)
end

#create_disk(options = {}) ⇒ Object



313
314
315
316
317
318
319
320
321
322
323
324
325
326
# File 'lib/ovirt/vm.rb', line 313

def create_disk(options = {})
  create_device("disk") do |xml|
    [:name, :interface, :format, :size, :type].each do |key|
      next if options[key].blank?
      xml.send("#{key}_", options[key])
    end

    [:sparse, :bootable, :wipe_after_delete, :propagate_errors].each do |key|
      xml.send("#{key}_", options[key]) unless options[key].nil?
    end

    xml.storage_domains { xml.storage_domain(:id => options[:storage]) } if options[:storage]
  end
end

#create_nic(options = {}) ⇒ Object



304
305
306
307
308
309
310
311
# File 'lib/ovirt/vm.rb', line 304

def create_nic(options = {})
  create_device("nic") do |xml|
    xml.name      options[:name]
    xml.interface options[:interface] unless options[:interface].blank?
    xml.network(:id => options[:network_id]) unless options[:network_id].blank?
    xml.mac(:address => options[:mac_address]) unless options[:mac_address].blank?
  end
end

#create_snapshot(desc) ⇒ Object



328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
# File 'lib/ovirt/vm.rb', line 328

def create_snapshot(desc)
  builder = Nokogiri::XML::Builder.new do |xml|
    xml.snapshot do
      xml.description desc
    end
  end
  data     = builder.doc.root.to_xml
  path     = "#{api_endpoint}/snapshots"
  response = @service.resource_post(path, data)
  snap     = Snapshot.create_from_xml(@service, response)

  while snap[:snapshot_status] == "locked"
    sleep 2
    snap.reload
  end
  snap
end

#create_template(options = {}) ⇒ Object



346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
# File 'lib/ovirt/vm.rb', line 346

def create_template(options = {})
  builder = Nokogiri::XML::Builder.new do |xml|
    xml.template do
      xml.name options[:name]
      xml.vm(:id => self[:id])
    end
  end
  data     = builder.doc.root.to_xml
  response = @service.resource_post(:templates, data)

  Template.create_from_xml(@service, response)
rescue Ovirt::Error => err
  raise TemplateAlreadyExists, err.message if err.message.include?("Template name already exists")
  raise
end

#creation_statusObject



21
22
23
24
# File 'lib/ovirt/vm.rb', line 21

def creation_status
  return nil if @creation_status_link.blank?
  @service.status(@creation_status_link)
end

#description=(value) ⇒ Object



104
105
106
107
108
109
# File 'lib/ovirt/vm.rb', line 104

def description=(value)
  update! do |xml|
    xml.description value.to_s
    xml.memory self[:memory]  # HACK: RHEVM BUG: RHEVM resets it to 10GB, unless we set it
  end
end

#destroyObject



51
52
53
54
55
56
57
58
59
# File 'lib/ovirt/vm.rb', line 51

def destroy
  # TODO: If VM was running, wait for it to stop
  begin
    stop
  rescue VmIsNotRunning
  end

  super
end

#detach_floppyObject

Detaches the floppy drive payload.



235
236
237
# File 'lib/ovirt/vm.rb', line 235

def detach_floppy
  detach_payload("floppy")
end

#detach_payload(types) ⇒ Object

Detaches a payload

types

A payload type or Array of payload types to detach. Acceptable types are floppy or cdrom.



211
212
213
# File 'lib/ovirt/vm.rb', line 211

def detach_payload(types)
  send("detach_payload_#{payload_version}".to_sym, Array(types))
end

#detach_payload_3_0(types) ⇒ Object



215
216
217
218
219
220
221
# File 'lib/ovirt/vm.rb', line 215

def detach_payload_3_0(types)
  # HACK: The removal of payloads is not supported until possibly RHEVM 3.1.1
  #       https://bugzilla.redhat.com/show_bug.cgi?id=882649
  #       For now, just set the payload to blank content.
  payload = types.each_with_object({}) { |t, h| h[t] = {} }
  attach_payload(payload)
end

#detach_payload_3_3(_types) ⇒ Object



223
224
225
# File 'lib/ovirt/vm.rb', line 223

def detach_payload_3_3(_types)
  update!(&:payloads)
end

#host_affinity=(host, affinity = :migratable) ⇒ Object



111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/ovirt/vm.rb', line 111

def host_affinity=(host, affinity = :migratable)
  update! do |xml|
    xml.memory self[:memory]  # HACK: RHEVM BUG: RHEVM resets it to 10GB, unless we set it
    xml.placement_policy do
      if host.nil?
        xml.host
      else
        xml.host(:id => self.class.object_to_id(host))
      end
      xml.affinity affinity.to_s
    end
  end
end

#memory=(value) ⇒ Object



125
126
127
128
129
# File 'lib/ovirt/vm.rb', line 125

def memory=(value)
  update! do |xml|
    xml.memory value
  end
end

#memory_reserve=(value) ⇒ Object



131
132
133
134
135
136
137
# File 'lib/ovirt/vm.rb', line 131

def memory_reserve=(value)
  update! do |xml|
    xml.memory_policy do
      xml.guaranteed(value)
    end
  end
end

#move(storage_domain) ⇒ Object

Raises:



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/ovirt/vm.rb', line 61

def move(storage_domain)
  response = operation(:move) do |xml|
    xml.storage_domain(:id => self.class.object_to_id(storage_domain))
  end

  # Sample Response
  # <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  # <action id="13be9571-61a0-40ef-be6c-50696f61cab1" href="/api/vms/5819ddca-47c0-47d8-8b75-c5b8d1f2b354/move/13be9571-61a0-40ef-be6c-50696f61cab1">
  #   <link rel="parent" href="/api/vms/5819ddca-47c0-47d8-8b75-c5b8d1f2b354"/>
  #   <link rel="replay" href="/api/vms/5819ddca-47c0-47d8-8b75-c5b8d1f2b354/move"/>
  #   <async>true</async>
  #   <storage_domain id="08d61895-b465-406f-955c-72fd9ddbbe05"/>
  #   <status>
  #     <state>pending</state>
  #   </status>
  # </action>
  doc    = Nokogiri::XML(response)
  action = doc.xpath("//action").first
  raise Ovirt::Error, "No Action in Response: #{response.inspect}" if action.nil?
  action['href']
end

#payload_versionObject



163
164
165
166
167
168
169
170
# File 'lib/ovirt/vm.rb', line 163

def payload_version
  version = service.version

  if version[:major].to_i >= 3
    return "3_0" if version[:minor].to_i < 3
    return "3_3"
  end
end

#shutdownObject



44
45
46
47
48
49
# File 'lib/ovirt/vm.rb', line 44

def shutdown
  operation(:shutdown)
rescue Ovirt::Error => err
  raise VmIsNotRunning, err.message if err.message.include?("VM is not running")
  raise
end

#startObject



26
27
28
29
30
31
32
33
34
35
# File 'lib/ovirt/vm.rb', line 26

def start
  if block_given?
    operation(:start) { |xml| yield xml }
  else
    operation(:start)
  end
rescue Ovirt::Error => err
  raise VmAlreadyRunning, err.message if err.message.include?("VM is running.")
  raise
end

#stopObject



37
38
39
40
41
42
# File 'lib/ovirt/vm.rb', line 37

def stop
  operation(:stop)
rescue Ovirt::Error => err
  raise VmIsNotRunning, err.message if err.message.include?("VM is not running")
  raise
end