Skip to content
This repository has been archived by the owner on Oct 16, 2019. It is now read-only.

Commit

Permalink
Beginning work on device XML parsing, starting with Disk
Browse files Browse the repository at this point in the history
  • Loading branch information
mitchellh committed Nov 27, 2010
1 parent 150a6db commit 96e1cfa
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 100 deletions.
21 changes: 21 additions & 0 deletions lib/libvirt/spec/device.rb
Expand Up @@ -3,6 +3,27 @@ module Spec
module Device
autoload :Disk, 'libvirt/spec/device/disk'
autoload :Emulator, 'libvirt/spec/device/emulator'

# Loads a device from an XML string. This will automatically find
# the proper class to load and return that.
#
# @return [Device]
def self.load!(xml)
xml = Nokogiri::XML(xml).root if !xml.is_a?(Nokogiri::XML::Element)
get(xml.name).new(xml)
end

# Returns the class of a device based on the name. If
# `:disk` were given, for example, then a {Disk} class
# would be returned. Note that since the class is returned,
# and not an instance, it is up to the caller to instantiate
# the returned class.
#
# @param [Symbol] name
# @return [Class]
def self.get(name)
const_get(name.to_s.capitalize)
end
end
end
end
19 changes: 15 additions & 4 deletions lib/libvirt/spec/device/disk.rb
Expand Up @@ -5,6 +5,8 @@ module Device
# cdrom, or paravirtualized driver is specified via the disk
# element.
class Disk
include Util

attr_accessor :type
attr_accessor :source
attr_accessor :target_dev
Expand All @@ -15,11 +17,20 @@ class Disk
attr_accessor :shareable
attr_accessor :serial

# Initialize a new disk element with the given type. Examples
# of valid `type`s are "disk," "floppy," and "cdrom."
def initialize(type)
@type = type
# Initializes a new disk element. If an XML string is passed
# then that will be used to initialize the attributes of the
# device.
def initialize(xml)
@shareable = false

load!(xml) if xml
end

# Loads data from XML.
def load!(xml)
xml = Nokogiri::XML(xml).root if !xml.is_a?(Nokogiri::XML::Element)
try(xml.xpath("//disk[@type]"), :preserve => true) { |result| self.type = result["type"].to_sym }
raise_if_unparseables(xml.xpath("//disk/*"))
end

# Returns the XML representation of this device.
Expand Down
9 changes: 9 additions & 0 deletions lib/libvirt/spec/domain.rb
Expand Up @@ -65,6 +65,15 @@ def load!(xml)
try(root.xpath("//domain/clock")) { |result| self.clock = Clock.new(result) }
try(root.xpath("//domain/os")) { |result| self.os = OSBooting.new(result) }

try(root.xpath("//domain/devices")) do |result|
self.devices = []

result.children.each do |device|
next if device.text?
self.devices << Device.load!(device)
end
end

raise_if_unparseables(root.xpath("//domain/*"))
end

Expand Down
21 changes: 21 additions & 0 deletions test/libvirt/spec/device_test.rb
@@ -0,0 +1,21 @@
require 'test_helper'

Protest.describe("Domain devices") do
setup do
@klass = Libvirt::Spec::Device
end

should "parse from XML" do
@instance = @klass.load!("<disk type='file'></disk>")
assert @instance.is_a?(Libvirt::Spec::Device::Disk)
assert_equal :file, @instance.type
end

should "be able to get defined classes by name" do
assert_equal Libvirt::Spec::Device::Disk, @klass.get(:disk)
end

should "raise an exception if an unknown device name is given" do
assert_raises(NameError) { @klass.get(:foo) }
end
end
103 changes: 8 additions & 95 deletions test/libvirt/spec/devices/disk_test.rb
Expand Up @@ -5,103 +5,16 @@
@klass = Libvirt::Spec::Device::Disk
end

context "outputting XML" do
setup do
@instance = @klass.new(:file)
context "initialization and parsing XML" do
should "parse the type" do
@instance = @klass.new("<disk type='file'></disk>")
assert_equal :file, @instance.type
end

should "output given type for type in XML" do
assert_xpath @instance.type.to_s, @instance.to_xml, "//disk/@type"
end

context "source" do
should "not output source if not specified" do
@instance.source = nil
assert_not_element @instance.to_xml, "//disk/source"
end

should "output source attr as dev for block devices" do
@instance.type = :block
@instance.source = "foo"
assert_xpath @instance.source, @instance.to_xml, "//disk/source/@dev"
end

should "output source attr as file for other devices" do
@instance.type = :file
@instance.source = "foo"
assert_xpath @instance.source, @instance.to_xml, "//disk/source/@file"
end
end

context "target" do
should "not output target if not specified" do
@instance.target_dev = nil
assert_not_element @instance.to_xml, "//disk/target"
end

should "not output target if only bus is given" do
@instance.target_dev = nil
@instance.target_bus = "foo"
assert_not_element @instance.to_xml, "//disk/target"
end

should "output specified dev on target" do
@instance.target_dev = "foo"
assert_xpath @instance.target_dev, @instance.to_xml, "//disk/target/@dev"
end

should "output specified bus on target" do
@instance.target_dev = "foo"
@instance.target_bus = "bar"
assert_xpath @instance.target_bus, @instance.to_xml, "//disk/target/@bus"
end
end

context "driver" do
should "not output if no name is given" do
@instance.driver = nil
assert_not_element @instance.to_xml, "//disk/driver"
end

should "output with specified driver" do
@instance.driver = "foo"
assert_xpath @instance.driver, @instance.to_xml, "//disk/driver/@name"
end

should "output with specified type if given" do
@instance.driver = "foo"
@instance.driver_type = "bar"
assert_xpath @instance.driver_type, @instance.to_xml, "//disk/driver/@type"
end

should "output with specified cache if given" do
@instance.driver = "foo"
@instance.driver_cache = "bar"
assert_xpath @instance.driver_cache, @instance.to_xml, "//disk/driver/@cache"
end
end

context "shareable" do
should "not be sharable initially" do
assert_not_element @instance.to_xml, "//disk/shareable"
end

should "be shareable if specified" do
@instance.shareable = true
assert_element @instance.to_xml, "//disk/shareable"
end
end

context "serial" do
should "not have serial if not specified" do
@instance.serial = nil
assert_not_element @instance.to_xml, "//disk/serial"
end

should "have serial if specified" do
@instance.serial = "foobar"
assert_xpath @instance.serial, @instance.to_xml, "//disk/serial"
end
should "raise an exception if unsupported tags exist" do
assert_raises(Libvirt::Exception::UnparseableSpec) {
@klass.new("<disk><foo/></disk>")
}
end
end
end
2 changes: 1 addition & 1 deletion test/libvirt/spec/domain/clock_test.rb
Expand Up @@ -13,7 +13,7 @@

should "raise an exception if unsupported tags exist" do
assert_raises(Libvirt::Exception::UnparseableSpec) {
@instance = @klass.new("<clock offset='foo'><foo/></clock>")
@klass.new("<clock offset='foo'><foo/></clock>")
}
end
end
Expand Down
6 changes: 6 additions & 0 deletions test/libvirt/spec/domain_test.rb
Expand Up @@ -124,5 +124,11 @@
@instance = @klass.new("<domain><os><type>hvm</type></domain>")
assert_equal :hvm, @instance.os.type
end

should "parse the devices" do
@instance = @klass.new("<domain><devices><disk type='file'></disk></devices></domain>")
assert_equal 1, @instance.devices.length
assert_equal :file, @instance.devices.first.type
end
end
end

0 comments on commit 96e1cfa

Please sign in to comment.