[DRE-commits] [ruby-fog-libvirt] 01/16: Import upstream 0.0.2.

Antonio Terceiro terceiro at moszumanska.debian.org
Sat Apr 23 18:18:53 UTC 2016


This is an automated email from the git hooks/post-receive script.

terceiro pushed a commit to branch master
in repository ruby-fog-libvirt.

commit 7a1edfbb4850bfc4ce50cedde0180ae266d738e5
Author: intrigeri <intrigeri at boum.org>
Date:   Thu Aug 13 12:00:15 2015 +0000

    Import upstream 0.0.2.
---
 CONTRIBUTORS.md                                    |  23 ++
 Gemfile                                            |   9 +
 LICENSE.md                                         |  20 +
 README.md                                          |  29 ++
 Rakefile                                           | 127 ++++++
 fog-libvirt.gemspec                                |  52 +++
 lib/fog/bin/libvirt.rb                             |  58 +++
 lib/fog/libvirt.rb                                 |  18 +
 lib/fog/libvirt/compute.rb                         | 137 +++++++
 lib/fog/libvirt/models/compute/README.md           |  76 ++++
 lib/fog/libvirt/models/compute/interface.rb        |  25 ++
 lib/fog/libvirt/models/compute/interfaces.rb       |  20 +
 lib/fog/libvirt/models/compute/network.rb          |  29 ++
 lib/fog/libvirt/models/compute/networks.rb         |  20 +
 lib/fog/libvirt/models/compute/nic.rb              |  50 +++
 lib/fog/libvirt/models/compute/nics.rb             |  12 +
 lib/fog/libvirt/models/compute/node.rb             |  29 ++
 lib/fog/libvirt/models/compute/nodes.rb            |  20 +
 lib/fog/libvirt/models/compute/pool.rb             |  84 ++++
 lib/fog/libvirt/models/compute/pools.rb            |  20 +
 lib/fog/libvirt/models/compute/server.rb           | 434 +++++++++++++++++++++
 lib/fog/libvirt/models/compute/servers.rb          |  21 +
 .../models/compute/templates/network.xml.erb       |   6 +
 .../libvirt/models/compute/templates/pool.xml.erb  |   6 +
 .../models/compute/templates/server.xml.erb        |  54 +++
 .../models/compute/templates/volume.xml.erb        |  26 ++
 lib/fog/libvirt/models/compute/util/uri.rb         | 138 +++++++
 lib/fog/libvirt/models/compute/util/util.rb        |  32 ++
 lib/fog/libvirt/models/compute/volume.rb           | 127 ++++++
 lib/fog/libvirt/models/compute/volumes.rb          |  20 +
 lib/fog/libvirt/requests/compute/clone_volume.rb   |  18 +
 lib/fog/libvirt/requests/compute/create_domain.rb  |  17 +
 lib/fog/libvirt/requests/compute/create_volume.rb  |  16 +
 lib/fog/libvirt/requests/compute/define_domain.rb  |  17 +
 lib/fog/libvirt/requests/compute/define_pool.rb    |  16 +
 .../libvirt/requests/compute/destroy_interface.rb  |  18 +
 .../libvirt/requests/compute/destroy_network.rb    |  17 +
 lib/fog/libvirt/requests/compute/get_node_info.rb  |  37 ++
 lib/fog/libvirt/requests/compute/list_domains.rb   | 105 +++++
 .../libvirt/requests/compute/list_interfaces.rb    |  57 +++
 lib/fog/libvirt/requests/compute/list_networks.rb  |  55 +++
 .../libvirt/requests/compute/list_pool_volumes.rb  |  19 +
 lib/fog/libvirt/requests/compute/list_pools.rb     |  71 ++++
 lib/fog/libvirt/requests/compute/list_volumes.rb   |  88 +++++
 .../libvirt/requests/compute/mock_files/domain.xml |  40 ++
 lib/fog/libvirt/requests/compute/pool_action.rb    |  19 +
 lib/fog/libvirt/requests/compute/update_display.rb |  31 ++
 lib/fog/libvirt/requests/compute/upload_volume.rb  |  31 ++
 lib/fog/libvirt/requests/compute/vm_action.rb      |  19 +
 lib/fog/libvirt/requests/compute/volume_action.rb  |  18 +
 lib/fog/libvirt/version.rb                         |   5 +
 metadata.yml                                       | 344 ++++++++++++++++
 minitests/server/user_data_iso_test.rb             |  69 ++++
 minitests/test_helper.rb                           |  18 +
 tests/helper.rb                                    |  17 +
 tests/helpers/formats_helper.rb                    |  98 +++++
 tests/helpers/formats_helper_tests.rb              | 110 ++++++
 tests/helpers/mock_helper.rb                       |  14 +
 tests/helpers/succeeds_helper.rb                   |   9 +
 tests/libvirt/compute_tests.rb                     |  17 +
 tests/libvirt/models/compute/interface_tests.rb    |  27 ++
 tests/libvirt/models/compute/interfaces_tests.rb   |  14 +
 tests/libvirt/models/compute/network_tests.rb      |  27 ++
 tests/libvirt/models/compute/networks_tests.rb     |  13 +
 tests/libvirt/models/compute/nic_tests.rb          |  31 ++
 tests/libvirt/models/compute/nics_tests.rb         |  10 +
 tests/libvirt/models/compute/pool_tests.rb         |  27 ++
 tests/libvirt/models/compute/pools_tests.rb        |  13 +
 tests/libvirt/models/compute/server_tests.rb       |  57 +++
 tests/libvirt/models/compute/servers_tests.rb      |  14 +
 tests/libvirt/models/compute/volume_tests.rb       |  38 ++
 tests/libvirt/models/compute/volumes_tests.rb      |  14 +
 .../requests/compute/create_domain_tests.rb        |  21 +
 .../requests/compute/define_domain_tests.rb        |  11 +
 tests/libvirt/requests/compute/update_display.rb   |  13 +
 75 files changed, 3462 insertions(+)

diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
new file mode 100644
index 0000000..396d46c
--- /dev/null
+++ b/CONTRIBUTORS.md
@@ -0,0 +1,23 @@
+* Amos Benari <abenari at redhat.com>
+* brookemckim <brooke.mckim at gmail.com>
+* Carl Caum <carl at carlcaum.com>
+* Carlos Sanchez <csanchez at maestrodev.com>
+* David Wittman <david at wittman.com>
+* Dominic Cleal <dcleal at redhat.com>
+* Greg Sutcliffe <gsutclif at redhat.com>
+* James Herdman <james.herdman at me.com>
+* Josef Strzibny <strzibny at strzibny.name>
+* Kevin Menard <nirvdrum at gmail.com>
+* Konstantin Haase <konstantin.mailinglists at googlemail.com>
+* Kyle Rames <kyle.rames at rackspace.com>
+* Lance Ivy <lance at cainlevy.net>
+* Ohad Levy <ohadlevy at redhat.com>
+* Patrick Debois <Patrick.Debois at jedi.be>
+* Paul Thornthwaite <tokengeek at gmail.com>
+* Romain Vrignaud <romain at yakaz.com>
+* Ryan Davies <ryan at ryandavies.co.nz>
+* Sergio Rubio <rubiojr at frameos.org>
+* Shlomi Zadok <shlomi at ben-hanna.com>
+* Steve Smith <github at scsworld.co.uk>
+* Vincent Demeester <vincent+git at demeester.fr>
+* Wesley Beary <geemus at gmail.com>
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..23db6d7
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,9 @@
+source "https://rubygems.org"
+
+group :development, :test do
+  # This is here because gemspec doesn't support require: false
+  gem "netrc", :require => false
+  gem "octokit", :require => false
+end
+
+gemspec
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..0a31a1a
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2009-2014 [CONTRIBUTORS.md](https://github.com/fog/fog/blob/master/CONTRIBUTORS.md)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..44b78a2
--- /dev/null
+++ b/README.md
@@ -0,0 +1,29 @@
+# Fog::Libvirt
+
+fog-libvirt is a libvirt provider for [fog](https://github.com/fog/fog).
+
+[![Build Status](https://secure.travis-ci.org/fog/fog.png?branch=master)](http://travis-ci.org/fog/fog-libvirt)
+[![Dependency Status](https://gemnasium.com/fog/fog.png)](https://gemnasium.com/fog/fog-libvirt)
+[![Code Climate](https://codeclimate.com/github/fog/fog.png)](https://codeclimate.com/github/fog/fog-libvirt)
+[![Gem Version](https://fury-badge.herokuapp.com/rb/fog.png)](http://badge.fury.io/rb/fog-libvirt)
+[![Gittip](http://img.shields.io/gittip/geemus.png)](https://www.gittip.com/geemus/)
+
+## Installation
+
+fog-libvirt can be used as a module for fog or installed separately as:
+
+```
+$ sudo gem install fog-libvirt
+```
+
+## Usage
+
+See [README.md](https://github.com/fog/fog-libvirt/blob/master/lib/fog/libvirt/models/compute/README.md).
+
+## Contributing
+
+Please refer to [CONTRIBUTING.md](https://github.com/fog/fog/blob/master/CONTRIBUTING.md).
+
+## License
+
+Please refer to [LICENSE.md](https://github.com/fog/fog-libvirt/blob/master/LICENSE.md).
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000..5230dfc
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,127 @@
+require 'bundler/setup'
+require 'rake/testtask'
+require 'rubygems'
+require 'rubygems/package_task'
+require 'yard'
+require File.dirname(__FILE__) + '/lib/fog/libvirt'
+
+#############################################################################
+#
+# Helper functions
+#
+#############################################################################
+
+def name
+  @name ||= Dir['*.gemspec'].first.split('.').first
+end
+
+def version
+  Fog::Libvirt::VERSION
+end
+
+def gemspec_file
+  "#{name}.gemspec"
+end
+
+def gem_file
+  "#{name}-#{version}.gem"
+end
+
+#############################################################################
+#
+# Standard tasks
+#
+#############################################################################
+
+GEM_NAME = "#{name}"
+task :default => [:test, :minitest]
+
+Rake::TestTask.new(:minitest) do |t|
+  t.libs << '.'
+  t.libs << 'lib'
+  t.libs << 'minitests'
+  t.test_files  =  Dir.glob('minitests/**/*_test.rb')
+  t.verbose = true
+end
+
+desc 'Run tests'
+task :test do
+  mock = ENV['FOG_MOCK'] || 'true'
+  sh("export FOG_MOCK=#{mock} && bundle exec shindont tests")
+end
+
+desc 'Run mocked tests'
+task :mock do
+  sh("export FOG_MOCK=true && bundle exec shindont tests")
+end
+
+desc 'Run live tests'
+task :live do
+  sh("export FOG_MOCK=false && bundle exec shindont tests")
+end
+
+desc "Open an irb session preloaded with this library"
+task :console do
+  sh "irb -rubygems -r ./lib/fog/libvirt.rb"
+end
+
+#############################################################################
+#
+# Packaging tasks
+#
+#############################################################################
+
+task :release => ["release:prepare", "release:publish"]
+
+namespace :release do
+  task :preflight do
+    unless `git branch` =~ /^\* master$/
+      puts "You must be on the master branch to release!"
+      exit!
+    end
+    if `git tag` =~ /^\* v#{version}$/
+      puts "Tag v#{version} already exists!"
+      exit!
+    end
+  end
+
+  task :prepare => :preflight do
+    Rake::Task[:build].invoke
+    sh "gem install pkg/#{name}-#{version}.gem"
+    Rake::Task[:git_mark_release].invoke
+  end
+
+  task :publish do
+    Rake::Task[:git_push_release].invoke
+    Rake::Task[:gem_push].invoke
+  end
+end
+
+task :git_mark_release do
+  sh "git commit --allow-empty -a -m 'Release #{version}'"
+  sh "git tag v#{version}"
+end
+
+task :git_push_release do
+  sh "git push origin master"
+  sh "git push origin v#{version}"
+end
+
+task :gem_push do
+  sh "gem push pkg/#{name}-#{version}.gem"
+end
+
+desc "Build #{name}-#{version}.gem"
+task :build do
+  sh "mkdir -p pkg"
+  sh "gem build #{gemspec_file}"
+  sh "mv #{gem_file} pkg"
+end
+task :gem => :build
+
+# Include Yard tasks for rake yard
+YARDOC_LOCATION = "doc"
+YARD::Rake::YardocTask.new do |t|
+  t.files   = ['lib/**/*.rb', "README"]
+  t.options = ["--output-dir", YARDOC_LOCATION, "--title", "#{name} #{version}"]
+end
diff --git a/fog-libvirt.gemspec b/fog-libvirt.gemspec
new file mode 100644
index 0000000..f3c6b9c
--- /dev/null
+++ b/fog-libvirt.gemspec
@@ -0,0 +1,52 @@
+# coding: utf-8
+lib = File.expand_path("../lib", __FILE__)
+$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
+require "fog/libvirt/version"
+
+Gem::Specification.new do |s|
+  s.specification_version = 2 if s.respond_to? :specification_version=
+  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
+
+  s.name              = "fog-libvirt"
+  s.version           = Fog::Libvirt::VERSION
+
+  s.summary     = "Module for the 'fog' gem to support libvirt"
+  s.description = "This library can be used as a module for 'fog' or as standalone libvirt provider."
+
+  s.authors  = ["geemus (Wesley Beary)"]
+  s.email    = "geemus at gmail.com"
+  s.homepage = "http://github.com/fog/fog-libvirt"
+  s.license  = "MIT"
+
+  s.require_paths = %w[lib]
+
+  s.rdoc_options = ["--charset=UTF-8"]
+  s.extra_rdoc_files = %w[README.md]
+
+  s.add_dependency("fog-core", "~> 1.27", ">= 1.27.4")
+  s.add_dependency("fog-json")
+  s.add_dependency("fog-xml", "~> 0.1.1")
+  s.add_dependency('ruby-libvirt','~> 0.5.0')
+  s.add_dependency('mime-types','< 2.0') if RUBY_VERSION < '1.9'
+  s.add_dependency('nokogiri', '< 1.6') if RUBY_VERSION < '1.9'
+  s.add_dependency('octokit', '< 3.0') if RUBY_VERSION < '1.9'
+  s.add_dependency('rest-client', '<= 1.7.0') if RUBY_VERSION < '1.9'
+
+  # Fedora and derivates need explicit require
+  s.add_dependency("json")
+
+  s.add_development_dependency("minitest")
+  s.add_development_dependency("minitest-stub-const")
+  s.add_development_dependency("pry")
+  s.add_development_dependency("rake")
+  s.add_development_dependency("rubocop") if RUBY_VERSION > "1.9"
+  s.add_development_dependency("shindo", "~> 0.3.4")
+  s.add_development_dependency("simplecov")
+  s.add_development_dependency("yard")
+  s.add_development_dependency("mocha", "~> 1.1.0")
+
+  # Let's not ship dot files and gemfiles
+  git_files = `git ls-files`.split("\n")
+  s.files = git_files.delete_if{ |f| f =~ /^\..*/ || f =~ /^gemfiles\/*/ }
+  s.test_files = `git ls-files -- {spec,tests}/*`.split("\n")
+end
diff --git a/lib/fog/bin/libvirt.rb b/lib/fog/bin/libvirt.rb
new file mode 100644
index 0000000..8cff49d
--- /dev/null
+++ b/lib/fog/bin/libvirt.rb
@@ -0,0 +1,58 @@
+module Libvirt # deviates from other bin stuff to accomodate gem
+  class << self
+    def class_for(key)
+      case key
+      when :compute
+        Fog::Compute::Libvirt
+      else
+        raise ArgumentError, "Unrecognized service: #{key}"
+      end
+    end
+
+    def [](service)
+      @@connections ||= Hash.new do |hash, key|
+        hash[key] = case key
+        when :compute
+          Fog::Logger.warning("Libvirt[:compute] is not recommended, use Compute[:libvirt] for portability")
+          Fog::Compute.new(:provider => 'Libvirt')
+        else
+          raise ArgumentError, "Unrecognized service: #{key.inspect}"
+        end
+      end
+      @@connections[service]
+    end
+
+    def available?
+      begin
+        availability=true unless Gem::Specification::find_by_name("ruby-libvirt").nil?
+      rescue Gem::LoadError
+        availability=false
+      rescue
+        availability_gem=Gem.available?("ruby-libvirt")
+      end
+
+      if availability
+        for service in services
+          for collection in self.class_for(service).collections
+            unless self.respond_to?(collection)
+              self.class_eval <<-EOS, __FILE__, __LINE__
+                def self.#{collection}
+                  self[:#{service}].#{collection}
+                end
+              EOS
+            end
+          end
+        end
+      end
+      availability
+    end
+
+    def collections
+      services.map {|service| self[service].collections}.flatten.sort_by {|service| service.to_s}
+    end
+
+    def services
+      Fog::Libvirt.services
+    end
+  end
+end
diff --git a/lib/fog/libvirt.rb b/lib/fog/libvirt.rb
new file mode 100644
index 0000000..013b845
--- /dev/null
+++ b/lib/fog/libvirt.rb
@@ -0,0 +1,18 @@
+require 'fog/core'
+require 'fog/xml'
+require 'fog/json'
+require 'libvirt'
+
+require File.expand_path('../libvirt/version', __FILE__)
+
+module Fog
+  module Libvirt
+    extend Fog::Provider
+
+    module Compute
+      autoload :Libvirt, File.expand_path('../libvirt/compute', __FILE__)
+    end
+
+    service(:compute, 'Compute')
+  end
+end
diff --git a/lib/fog/libvirt/compute.rb b/lib/fog/libvirt/compute.rb
new file mode 100644
index 0000000..59a916f
--- /dev/null
+++ b/lib/fog/libvirt/compute.rb
@@ -0,0 +1,137 @@
+require 'fog/libvirt/models/compute/util/util'
+require 'fog/libvirt/models/compute/util/uri'
+
+module Fog
+  module Compute
+    class Libvirt < Fog::Service
+      requires   :libvirt_uri
+      recognizes :libvirt_username, :libvirt_password
+      recognizes :libvirt_ip_command
+
+      model_path 'fog/libvirt/models/compute'
+      model       :server
+      collection  :servers
+      model       :network
+      collection  :networks
+      model       :interface
+      collection  :interfaces
+      model       :volume
+      collection  :volumes
+      model       :pool
+      collection  :pools
+      model       :node
+      collection  :nodes
+      model       :nic
+      collection  :nics
+
+      request_path 'fog/libvirt/requests/compute'
+      request :list_domains
+      request :create_domain
+      request :define_domain
+      request :vm_action
+      request :list_pools
+      request :list_pool_volumes
+      request :define_pool
+      request :pool_action
+      request :list_volumes
+      request :volume_action
+      request :create_volume
+      request :upload_volume
+      request :clone_volume
+      request :list_networks
+      request :destroy_network
+      request :list_interfaces
+      request :destroy_interface
+      request :get_node_info
+      request :update_display
+
+      module Shared
+        include Fog::Compute::LibvirtUtil
+      end
+
+      class Mock
+        include Shared
+        def initialize(options={})
+          # libvirt is part of the gem => ruby-libvirt
+          require 'libvirt'
+        end
+
+        private
+
+        def client
+          return @client if defined?(@client)
+        end
+
+        #read mocks xml
+        def read_xml(file_name)
+          file_path = File.join(File.dirname(__FILE__),"requests","compute","mock_files",file_name)
+          File.read(file_path)
+        end
+      end
+
+      class Real
+        include Shared
+        attr_reader :client
+        attr_reader :uri
+        attr_reader :ip_command
+
+        def initialize(options={})
+          @uri = ::Fog::Compute::LibvirtUtil::URI.new(enhance_uri(options[:libvirt_uri]))
+          @ip_command = options[:libvirt_ip_command]
+
+          # libvirt is part of the gem => ruby-libvirt
+          begin
+            require 'libvirt'
+          rescue LoadError => e
+            retry if require('rubygems')
+            raise e.message
+          end
+
+          begin
+            if options[:libvirt_username] and options[:libvirt_password]
+              @client = ::Libvirt::open_auth(uri.uri, [::Libvirt::CRED_AUTHNAME, ::Libvirt::CRED_PASSPHRASE]) do |cred|
+                case cred['type']
+                  when ::Libvirt::CRED_AUTHNAME
+                    options[:libvirt_username]
+                  when ::Libvirt::CRED_PASSPHRASE
+                    options[:libvirt_password]
+                end
+              end
+            else
+              @client = ::Libvirt::open(uri.uri)
+            end
+
+          rescue ::Libvirt::ConnectionError
+            raise Fog::Errors::Error.new("Error making a connection to libvirt URI #{uri.uri}:\n#{$!}")
+          end
+        end
+
+        def terminate
+          @client.close if @client and !@client.closed?
+        end
+
+        def enhance_uri(uri)
+          require 'cgi'
+          append=""
+
+          # on macosx, chances are we are using libvirt through homebrew
+          # the client will default to a socket location based on it's own location (/opt)
+          # we conveniently point it to /var/run/libvirt/libvirt-sock
+          # if no socket option has been specified explicitly
+
+          if RUBY_PLATFORM =~ /darwin/
+            querystring=::URI.parse(uri).query
+            if querystring.nil?
+              append="?socket=/var/run/libvirt/libvirt-sock"
+            else
+              if !::CGI.parse(querystring).key?("socket")
+                append="&socket=/var/run/libvirt/libvirt-sock"
+              end
+            end
+          end
+          uri+append
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/models/compute/README.md b/lib/fog/libvirt/models/compute/README.md
new file mode 100644
index 0000000..e681b73
--- /dev/null
+++ b/lib/fog/libvirt/models/compute/README.md
@@ -0,0 +1,76 @@
+This model implements the connection with a libvirt URI.
+A libvirt URI can either be local or remote.
+
+To learn more on the specific libvirt URI syntax see:
+
+- [http://libvirt.org/uri.html](http://libvirt.org/uri.html)
+- [http://libvirt.org/remote.html#Remote_URI_reference](http://libvirt.org/remote.html#Remote_URI_reference)
+
+Only ssh is supported as the transport for remote URI's. TLS is NOT supported, as we can't easily login to the server
+
+## Dependencies
+
+- the interaction with libvirt is done through the official libvirt gem called 'ruby-libvirt'.
+- be aware that there is another libvirt gem called 'libvirt', which is not compatible
+- If this gem is not installed the models for libvirt will not be available
+
+- libvirt needs to be setup so that it can be used
+- for a remote ssh connection this requires to be member of the libvirt group before you can use the libvirt commands
+- verify if you can execute virsh command to see if you have correct access
+
+## Libvirt on Macosx
+
+- There is a libvirt client for Macosx, available via homebrew
+- By default this will install things in /usr/local/somewhere
+- This means that also the default locations of the libvirt-socket are assumed to be in /usr/local
+- To check the connection you need to override your libvirt socket location in the URI
+  - "qemu+ssh://patrick@myserver/system?socket=/var/run/libvirt/libvirt-sock"
+
+## Configuration
+
+The URI can be configured in two ways:
+1) via the .fog file
+:default
+  :libvirt_uri: "qemu+ssh://patrick@myserver/system?socket=/var/run/libvirt/libvirt-sock"
+
+2) you can also pass it during creation :
+f=Fog::Compute.new(:provider => "Libvirt", :libvirt_uri => "qemu+ssh://patrick@myserver/system")
+
+## IP-addresses of guests
+Libvirt does not provide a way to query guests for Ip-addresses.
+The way we solve this problem is by installing arpwatch: this watches an interface for new mac-addresses and ip-addresses requested by DHCP
+We query that logfile for the mac-address and can retrieve the ip-address
+
+vi /etc/rsyslog.d/30-arpwatch.conf
+#:msg, contains, "arpwatch:" -/var/log/arpwatch.log
+#& ~
+if $programname =='arpwatch' then /var/log/arpwatch.log
+& ~
+
+This log files needs to be readable for the users of libvirt
+
+## SSh-ing into the guests
+Once we have retrieved the ip-address of the guest we can ssh into it. This works great if the URI is local.
+But when the URI is remote our machine can't ssh directly into the guest sometimes (due to NAT or firewall issues)
+
+Luckily libvirt over ssh requires netcat to be installed on the libvirt server.
+We use this to proxy our ssh requests to the guest over the ssh connection to the libvirt server.
+Thanks to the requirement that you need ssh login to work to a libvirt server, we can login and tunnel the ssh to the guest.
+
+## Bridge configuration (slowness)
+We had noticed that sometimes it takes about 30 seconds before the server gets a DHCP response from the server.
+In our case it was because the new machine Mac-address was not allowed immediately by the bridge.
+Adding the flag 'bridge_fd 0' solved that problem.
+
+/etc/network/interfaces
+auto br0
+iface br0 inet static
+address 10.247.4.13
+netmask 255.255.255.0
+network 10.247.4.0
+broadcast 10.247.4.255
+bridge_ports eth0.4
+bridge_stp on
+bridge_maxwait 0
+bridge_fd 0
+
diff --git a/lib/fog/libvirt/models/compute/interface.rb b/lib/fog/libvirt/models/compute/interface.rb
new file mode 100644
index 0000000..a7ebde6
--- /dev/null
+++ b/lib/fog/libvirt/models/compute/interface.rb
@@ -0,0 +1,25 @@
+require 'fog/core/model'
+
+module Fog
+  module Compute
+    class Libvirt
+      class Interface < Fog::Model
+        identity :name
+        attribute :mac
+        attribute :active
+
+        def save
+          raise Fog::Errors::Error.new('Creating a new interface is not yet implemented. Contributions welcome!')
+        end
+
+        def shutdown
+          service.destroy_interface(mac)
+        end
+
+        def active?
+          active
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/models/compute/interfaces.rb b/lib/fog/libvirt/models/compute/interfaces.rb
new file mode 100644
index 0000000..48f696d
--- /dev/null
+++ b/lib/fog/libvirt/models/compute/interfaces.rb
@@ -0,0 +1,20 @@
+require 'fog/core/collection'
+require 'fog/libvirt/models/compute/interface'
+
+module Fog
+  module Compute
+    class Libvirt
+      class Interfaces < Fog::Collection
+        model Fog::Compute::Libvirt::Interface
+
+        def all(filter={})
+          load(service.list_interfaces(filter))
+        end
+
+        def get(name)
+          self.all(:name => name).first
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/models/compute/network.rb b/lib/fog/libvirt/models/compute/network.rb
new file mode 100644
index 0000000..6a80247
--- /dev/null
+++ b/lib/fog/libvirt/models/compute/network.rb
@@ -0,0 +1,29 @@
+require 'fog/core/model'
+require 'fog/libvirt/models/compute/util/util'
+
+module Fog
+  module Compute
+    class Libvirt
+      class Network < Fog::Model
+        include Fog::Compute::LibvirtUtil
+
+        identity :uuid
+        attribute :name
+        attribute :bridge_name
+        attribute :xml
+
+        def initialize(attributes = {})
+          super
+        end
+
+        def save
+          raise Fog::Errors::Error.new('Creating a new network is not yet implemented. Contributions welcome!')
+        end
+
+        def shutdown
+          service.destroy_network(uuid)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/models/compute/networks.rb b/lib/fog/libvirt/models/compute/networks.rb
new file mode 100644
index 0000000..760ccf2
--- /dev/null
+++ b/lib/fog/libvirt/models/compute/networks.rb
@@ -0,0 +1,20 @@
+require 'fog/core/collection'
+require 'fog/libvirt/models/compute/network'
+
+module Fog
+  module Compute
+    class Libvirt
+      class Networks < Fog::Collection
+        model Fog::Compute::Libvirt::Network
+
+        def all(filter={})
+          load(service.list_networks(filter))
+        end
+
+        def get(uuid)
+          self.all(:uuid => uuid).first
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/models/compute/nic.rb b/lib/fog/libvirt/models/compute/nic.rb
new file mode 100644
index 0000000..485b417
--- /dev/null
+++ b/lib/fog/libvirt/models/compute/nic.rb
@@ -0,0 +1,50 @@
+require 'fog/core/model'
+
+module Fog
+  module Compute
+    class Libvirt
+      class Nic < Fog::Model
+        identity :mac
+        attribute :id
+        attribute :type
+        attribute :network
+        attribute :bridge
+        attribute :model
+
+        attr_accessor :server
+
+        TYPES = ["network", "bridge", "user"]
+
+        def new?
+          mac.nil?
+        end
+
+        def initialize attributes
+          super defaults.merge(attributes)
+          raise Fog::Errors::Error.new("#{type} is not a supported nic type") if new? && !TYPES.include?(type)
+        end
+
+        def save
+          raise Fog::Errors::Error.new('Creating a new nic is not yet implemented. Contributions welcome!')
+          #requires :server
+          #service.attach_nic(domain , self)
+        end
+
+        def destroy
+          raise Fog::Errors::Error.new('Destroying an interface is not yet implemented. Contributions welcome!')
+          #requires :server
+          ##detach the nic
+          #service.detach_nic(domain, mac)
+        end
+
+        private
+        def defaults
+          {
+            :type  => "bridge",
+            :model => "virtio"
+          }
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/models/compute/nics.rb b/lib/fog/libvirt/models/compute/nics.rb
new file mode 100644
index 0000000..7a326f3
--- /dev/null
+++ b/lib/fog/libvirt/models/compute/nics.rb
@@ -0,0 +1,12 @@
+require 'fog/core/collection'
+require 'fog/libvirt/models/compute/nic'
+
+module Fog
+  module Compute
+    class Libvirt
+      class Nics < Fog::Collection
+        model Fog::Compute::Libvirt::Nic
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/models/compute/node.rb b/lib/fog/libvirt/models/compute/node.rb
new file mode 100644
index 0000000..02d3fc7
--- /dev/null
+++ b/lib/fog/libvirt/models/compute/node.rb
@@ -0,0 +1,29 @@
+require 'fog/core/model'
+
+module Fog
+  module Compute
+    class Libvirt
+      class Node < Fog::Model
+        identity :uuid
+
+        attribute :model
+        attribute :memory
+        attribute :cpus
+        attribute :mhz
+        attribute :nodes
+        attribute :sockets
+        attribute :cores
+        attribute :threads
+        attribute :type
+        attribute :version
+        attribute :uri
+        attribute :node_free_memory
+        attribute :max_vcpus
+        attribute :manufacturer
+        attribute :product
+        attribute :serial
+        attribute :hostname
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/models/compute/nodes.rb b/lib/fog/libvirt/models/compute/nodes.rb
new file mode 100644
index 0000000..72d6d7b
--- /dev/null
+++ b/lib/fog/libvirt/models/compute/nodes.rb
@@ -0,0 +1,20 @@
+require 'fog/core/collection'
+require 'fog/libvirt/models/compute/node'
+
+module Fog
+  module Compute
+    class Libvirt
+      class Nodes < Fog::Collection
+        model Fog::Compute::Libvirt::Node
+
+        def all(filter={ })
+          load(service.get_node_info)
+        end
+
+        def get
+          all.first
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/models/compute/pool.rb b/lib/fog/libvirt/models/compute/pool.rb
new file mode 100644
index 0000000..d186b86
--- /dev/null
+++ b/lib/fog/libvirt/models/compute/pool.rb
@@ -0,0 +1,84 @@
+require 'fog/core/model'
+
+module Fog
+  module Compute
+    class Libvirt
+      class Pool < Fog::Model
+        attr_reader :xml
+
+        identity :uuid
+
+        attribute :persistent
+        attribute :autostart
+        attribute :active
+        attribute :name
+        attribute :allocation
+        attribute :capacity
+        attribute :num_of_volumes
+        attribute :state
+
+        def initialize(attributes={} )
+          # Can be created by passing in XML
+          @xml = attributes.delete(:xml)
+          super(attributes)
+        end
+
+        def save
+          raise Fog::Errors::Error.new('Creating a new pool requires proper xml') unless xml
+          self.uuid = (persistent ? service.define_pool(xml) : service.create_pool(xml)).uuid
+          reload
+        end
+
+        # Start the pool = make it active
+        # Performs a libvirt create (= start)
+        def start
+          service.pool_action uuid, :create
+        end
+
+        # Stop the pool = make it non-active
+        # Performs a libvirt destroy (= stop)
+        def stop
+          service.pool_action uuid, :destroy
+        end
+
+        # Shuts down the pool
+        def shutdown
+          stop
+        end
+
+        # Build this storage pool
+        def build
+          service.pool_action uuid, :build
+        end
+
+        # Destroys the storage pool
+        def destroy
+          # Shutdown pool if active
+          service.pool_action uuid, :destroy if active?
+          # If this is a persistent domain we need to undefine it
+          service.pool_action uuid, :undefine if persistent?
+        end
+
+        # Is the pool active or not?
+        def active?
+          active
+        end
+
+        # Will the pool autostart or not?
+        def auto_start?
+          autostart
+        end
+
+        # Is the pool persistent or not?
+        def persistent?
+          persistent
+        end
+
+        # Retrieves the volumes of this pool
+        def volumes
+          service.list_pool_volumes uuid
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/models/compute/pools.rb b/lib/fog/libvirt/models/compute/pools.rb
new file mode 100644
index 0000000..2f3f73f
--- /dev/null
+++ b/lib/fog/libvirt/models/compute/pools.rb
@@ -0,0 +1,20 @@
+require 'fog/core/collection'
+require 'fog/libvirt/models/compute/pool'
+
+module Fog
+  module Compute
+    class Libvirt
+      class Pools < Fog::Collection
+        model Fog::Compute::Libvirt::Pool
+
+        def all(filter = {})
+          load(service.list_pools(filter))
+        end
+
+        def get(uuid)
+          self.all(:uuid => uuid).first
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/models/compute/server.rb b/lib/fog/libvirt/models/compute/server.rb
new file mode 100644
index 0000000..30d6452
--- /dev/null
+++ b/lib/fog/libvirt/models/compute/server.rb
@@ -0,0 +1,434 @@
+require 'fog/compute/models/server'
+require 'fog/libvirt/models/compute/util/util'
+require 'net/ssh/proxy/command'
+require 'fileutils'
+
+module Fog
+  module Compute
+    class Libvirt
+      class Server < Fog::Compute::Server
+        include Fog::Compute::LibvirtUtil
+        attr_reader :xml
+
+        identity :id, :aliases => 'uuid'
+
+        attribute :cpus
+        attribute :cputime
+        attribute :os_type
+        attribute :memory_size
+        attribute :max_memory_size
+        attribute :name
+        attribute :arch
+        attribute :persistent
+        attribute :domain_type
+        attribute :uuid
+        attribute :autostart
+        attribute :nics
+        attribute :volumes
+        attribute :active
+        attribute :boot_order
+        attribute :display
+
+        attribute :state
+
+        # The following attributes are only needed when creating a new vm
+        #TODO: Add depreciation warning
+        attr_accessor :iso_dir, :iso_file
+        attr_accessor :network_interface_type ,:network_nat_network, :network_bridge_name
+        attr_accessor :volume_format_type, :volume_allocation,:volume_capacity, :volume_name, :volume_pool_name, :volume_template_name, :volume_path
+        attr_accessor :password
+        attr_accessor :user_data
+
+        # Can be created by passing in :xml => "<xml to create domain/server>"
+        # or by providing :template_options => {
+        #                :name => "", :cpus => 1, :memory_size => 256 , :volume_template
+        #   }
+
+        def initialize(attributes={} )
+          @xml = attributes.delete(:xml)
+          verify_boot_order(attributes[:boot_order])
+          super defaults.merge(attributes)
+          initialize_nics
+          initialize_volumes
+          @user_data = attributes.delete(:user_data)
+        end
+
+        def new?
+          uuid.nil?
+        end
+
+        def save
+          raise Fog::Errors::Error.new('Saving an existing server may create a duplicate') unless new?
+          create_or_clone_volume unless xml or @volumes
+          create_user_data_iso if user_data
+          @xml ||= to_xml
+          self.id = (persistent ? service.define_domain(xml) : service.create_domain(xml)).uuid
+          reload
+        rescue => e
+          raise Fog::Errors::Error.new("Error saving the server: #{e}")
+        end
+
+        def start
+          return true if active?
+          action_status = service.vm_action(uuid, :create)
+          reload
+          action_status
+        end
+
+        def mac
+          nics.first.mac if nics && nics.first
+        end
+
+        def disk_path
+          volumes.first.path if volumes and volumes.first
+        end
+
+        def destroy(options={ :destroy_volumes => false})
+          poweroff unless stopped?
+          service.vm_action(uuid, :undefine)
+          volumes.each { |vol| vol.destroy } if options[:destroy_volumes]
+          true
+        end
+
+        def reboot
+          action_status = service.vm_action(uuid, :reboot)
+          reload
+          action_status
+        end
+
+        def poweroff
+          action_status = service.vm_action(uuid, :destroy)
+          reload
+          action_status
+        end
+
+        def shutdown
+          action_status = service.vm_action(uuid, :shutdown)
+          reload
+          action_status
+        end
+
+        def resume
+          action_status = service.vm_action(uuid, :resume)
+          reload
+          action_status
+        end
+
+        def suspend
+          action_status = service.vm_action(uuid, :suspend)
+          reload
+          action_status
+        end
+
+        def stopped?
+          state == "shutoff"
+        end
+
+        def ready?
+          state == "running"
+        end
+
+        #alias methods
+        alias_method :halt,    :poweroff
+        alias_method :stop,    :shutdown
+        alias_method :active?, :active
+
+        def volumes
+          # lazy loading of volumes
+          @volumes ||= (@volumes_path || []).map{|path| service.volumes.all(:path => path).first }
+        end
+
+        def private_ip_address
+          ip_address(:private)
+        end
+
+        def public_ip_address
+          ip_address(:public)
+        end
+
+        def ssh(commands)
+          requires :ssh_ip_address, :username
+
+          ssh_options={}
+          ssh_options[:password] = password unless password.nil?
+          ssh_options[:proxy]= ssh_proxy unless ssh_proxy.nil?
+
+          super(commands, ssh_options)
+        end
+
+        def ssh_proxy
+          # if this is a direct connection, we don't need a proxy to be set.
+          return nil unless connection.uri.ssh_enabled?
+          user_string= service.uri.user ? "-l #{service.uri.user}" : ""
+          Net::SSH::Proxy::Command.new("ssh #{user_string} #{service.uri.host} nc %h %p")
+        end
+
+        # Transfers a file
+        def scp(local_path, remote_path, upload_options = {})
+          requires :ssh_ip_address, :username
+
+          scp_options = {}
+          scp_options[:password] = password unless self.password.nil?
+          scp_options[:key_data] = [private_key] if self.private_key
+          scp_options[:proxy]= ssh_proxy unless self.ssh_proxy.nil?
+
+          Fog::SCP.new(ssh_ip_address, username, scp_options).upload(local_path, remote_path, upload_options)
+        end
+
+        # Sets up a new key
+        def setup(credentials = {})
+          requires :public_key, :ssh_ip_address, :username
+
+          credentials[:proxy]= ssh_proxy unless ssh_proxy.nil?
+          credentials[:password] = password unless self.password.nil?
+          credentails[:key_data] = [private_key] if self.private_key
+
+          commands = [
+            %{mkdir .ssh},
+            #              %{passwd -l #{username}}, #Not sure if we need this here
+            #              %{echo "#{Fog::JSON.encode(attributes)}" >> ~/attributes.json}
+          ]
+          if public_key
+            commands << %{echo "#{public_key}" >> ~/.ssh/authorized_keys}
+          end
+
+          # wait for domain to be ready
+          Timeout::timeout(360) do
+            begin
+              Timeout::timeout(8) do
+                Fog::SSH.new(ssh_ip_address, username, credentials.merge(:timeout => 4)).run('pwd')
+              end
+            rescue Errno::ECONNREFUSED
+              sleep(2)
+              retry
+            rescue Net::SSH::AuthenticationFailed, Timeout::Error
+              retry
+            end
+          end
+          Fog::SSH.new(ssh_ip_address, username, credentials).run(commands)
+        end
+
+        def update_display attrs = {}
+          service.update_display attrs.merge(:uuid => uuid)
+          reload
+        end
+
+        # can't use deprecate method, as the value is part of the display hash
+        def vnc_port
+          Fog::Logger.deprecation("#{self.class} => #vnc_port is deprecated, use #display[:port] instead [light_black](#{caller.first})[/]")
+          display[:port]
+        end
+
+        def generate_config_iso(user_data, &blk)
+          Dir.mktmpdir('config') do |wd|
+            generate_config_iso_in_dir(wd, user_data, &blk)
+          end
+        end
+
+        def generate_config_iso_in_dir(dir_path, user_data, &blk)
+          FileUtils.touch(File.join(dir_path, "meta-data"))
+          File.open(File.join(dir_path, 'user-data'), 'w') { |f| f.write user_data }
+
+          isofile = Tempfile.new(['init', '.iso']).path
+          unless system("genisoimage -output #{isofile} -volid cidata -joliet -rock #{File.join(dir_path, 'user-data')} #{File.join(dir_path, 'meta-data')}")
+            raise Fog::Errors::Error("Couldn't generate cloud-init iso disk.")
+          end
+          blk.call(isofile)
+        end
+
+        def create_user_data_iso
+          generate_config_iso(user_data) do |iso|
+            vol = service.volumes.create(:name => cloud_init_volume_name, :capacity => "#{File.size(iso)}b", :allocation => "0G")
+            vol.upload_image(iso)
+            @iso_file = cloud_init_volume_name
+          end
+        end
+
+        def cloud_init_volume_name
+          "#{name}-cloud-init.iso"
+        end
+
+        private
+        attr_accessor :volumes_path
+
+        # This retrieves the ip address of the mac address
+        # It returns an array of public and private ip addresses
+        # Currently only one ip address is returned, but in the future this could be multiple
+        # if the server has multiple network interface
+        def addresses(service_arg=service, options={})
+          mac=self.mac
+
+          # Aug 24 17:34:41 juno arpwatch: new station 10.247.4.137 52:54:00:88:5a:0a eth0.4
+          # Aug 24 17:37:19 juno arpwatch: changed ethernet address 10.247.4.137 52:54:00:27:33:00 (52:54:00:88:5a:0a) eth0.4
+          # Check if another ip_command string was provided
+          ip_command_global=service_arg.ip_command.nil? ? 'grep $mac /var/log/arpwatch.log|sed -e "s/new station//"|sed -e "s/changed ethernet address//g" |sed -e "s/reused old ethernet //" |tail -1 |cut -d ":" -f 4-| cut -d " " -f 3' : service_arg.ip_command
+          ip_command_local=options[:ip_command].nil? ? ip_command_global : options[:ip_command]
+
+          ip_command="mac=#{mac}; server_name=#{name}; "+ip_command_local
+
+          ip_address=nil
+
+          if service_arg.uri.ssh_enabled?
+
+            # Retrieve the parts we need from the service to setup our ssh options
+            user=service_arg.uri.user #could be nil
+            host=service_arg.uri.host
+            keyfile=service_arg.uri.keyfile
+            port=service_arg.uri.port
+
+            # Setup the options
+            ssh_options={}
+            ssh_options[:keys]=[ keyfile ] unless keyfile.nil?
+            ssh_options[:port]=port unless keyfile.nil?
+            ssh_options[:paranoid]=true if service_arg.uri.no_verify?
+
+            begin
+              result=Fog::SSH.new(host, user, ssh_options).run(ip_command)
+            rescue Errno::ECONNREFUSED
+              raise Fog::Errors::Error.new("Connection was refused to host #{host} to retrieve the ip_address for #{mac}")
+            rescue Net::SSH::AuthenticationFailed
+              raise Fog::Errors::Error.new("Error authenticating over ssh to host #{host} and user #{user}")
+            end
+
+            # Check for a clean exit code
+            if result.first.status == 0
+              ip_address=result.first.stdout.strip
+            else
+              # We got a failure executing the command
+              raise Fog::Errors::Error.new("The command #{ip_command} failed to execute with a clean exit code")
+            end
+
+          else
+            # It's not ssh enabled, so we assume it is
+            if service_arg.uri.transport=="tls"
+              raise Fog::Errors::Error.new("TlS remote transport is not currently supported, only ssh")
+            end
+
+            # Execute the ip_command locally
+            # Initialize empty ip_address string
+            ip_address=""
+
+            IO.popen("#{ip_command}") do |p|
+              p.each_line do |l|
+                ip_address+=l
+              end
+              status=Process.waitpid2(p.pid)[1].exitstatus
+              if status!=0
+                raise Fog::Errors::Error.new("The command #{ip_command} failed to execute with a clean exit code")
+              end
+            end
+
+            #Strip any new lines from the string
+            ip_address=ip_address.chomp
+          end
+
+          # The Ip-address command has been run either local or remote now
+
+          if ip_address==""
+            #The grep didn't find an ip address result"
+            ip_address=nil
+          else
+            # To be sure that the command didn't return another random string
+            # We check if the result is an actual ip-address
+            # otherwise we return nil
+            unless ip_address=~/^(\d{1,3}\.){3}\d{1,3}$/
+              raise Fog::Errors::Error.new(
+                        "The result of #{ip_command} does not have valid ip-address format\n"+
+                            "Result was: #{ip_address}\n"
+                    )
+            end
+          end
+
+          return { :public => [ip_address], :private => [ip_address]}
+        end
+
+        def ip_address(key)
+          addresses[key].nil? ? nil : addresses[key].first
+        end
+
+        def initialize_nics
+          if nics
+            nics.map! { |nic| nic.is_a?(Hash) ? service.nics.new(nic) : nic }
+          else
+            self.nics = [service.nics.new({:type => network_interface_type, :bridge => network_bridge_name, :network => network_nat_network})]
+          end
+        end
+
+        def initialize_volumes
+          if attributes[:volumes] && !attributes[:volumes].empty?
+            @volumes = attributes[:volumes].map { |vol| vol.is_a?(Hash) ? service.volumes.new(vol) : vol }
+          end
+        end
+
+        def create_or_clone_volume
+          options = {:name => volume_name || default_volume_name}
+          # Check if a disk template was specified
+          if volume_template_name
+            template_volume = service.volumes.all(:name => volume_template_name).first
+            raise Fog::Errors::Error.new("Template #{volume_template_name} not found") unless template_volume
+            begin
+              volume = template_volume.clone("#{options[:name]}")
+            rescue => e
+              raise Fog::Errors::Error.new("Error creating the volume : #{e}")
+            end
+          else
+            # If no template volume was given, let's create our own volume
+            options[:pool_name]   = volume_pool_name   if volume_pool_name
+            options[:format_type] = volume_format_type if volume_format_type
+            options[:capacity]    = volume_capacity    if volume_capacity
+            options[:allocation]  = volume_allocation  if volume_allocation
+
+            begin
+              volume = service.volumes.create(options)
+            rescue => e
+              raise Fog::Errors::Error.new("Error creating the volume : #{e}")
+            end
+          end
+          @volumes.nil? ? @volumes = [volume] : @volumes << volume
+        end
+
+        def default_iso_dir
+          "/var/lib/libvirt/images"
+        end
+
+        def default_volume_name
+          "#{name}.#{volume_format_type || 'img'}"
+        end
+
+        def defaults
+          {
+            :persistent             => true,
+            :cpus                   => 1,
+            :memory_size            => 256 *1024,
+            :name                   => randomized_name,
+            :os_type                => "hvm",
+            :arch                   => "x86_64",
+            :domain_type            => "kvm",
+            :iso_dir                => default_iso_dir,
+            :network_interface_type => "network",
+            :network_nat_network    => "default",
+            :network_bridge_name    => "br0",
+            :boot_order             => default_boot_order,
+            :display                => default_display
+          }
+        end
+
+        def default_boot_order
+          %w[hd cdrom network]
+        end
+
+        def verify_boot_order order = []
+          if order
+            order.each do |b|
+              raise "invalid boot order, possible values are: hd, network and/or cdrom" unless default_boot_order.include?(b)
+            end
+          end
+        end
+
+        def default_display
+          {:port => '-1', :listen => '127.0.0.1', :type => 'vnc', :password => '' }
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/models/compute/servers.rb b/lib/fog/libvirt/models/compute/servers.rb
new file mode 100644
index 0000000..a28db2f
--- /dev/null
+++ b/lib/fog/libvirt/models/compute/servers.rb
@@ -0,0 +1,21 @@
+require 'fog/core/collection'
+require 'fog/libvirt/models/compute/server'
+
+module Fog
+  module Compute
+    class Libvirt
+      class Servers < Fog::Collection
+        model Fog::Compute::Libvirt::Server
+
+        def all(filter={})
+          load(service.list_domains(filter))
+        end
+
+        def get(uuid)
+          data = service.list_domains(:uuid => uuid)
+          new data.first if data
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/models/compute/templates/network.xml.erb b/lib/fog/libvirt/models/compute/templates/network.xml.erb
new file mode 100644
index 0000000..91493dd
--- /dev/null
+++ b/lib/fog/libvirt/models/compute/templates/network.xml.erb
@@ -0,0 +1,6 @@
+<network>
+  <name><%= name %></name>
+  <forward mode='<%= network_mode %>'/>
+  <bridge name='<%= bridge_name %>' stp='on' delay='0' />
+  </ip>
+</network>
diff --git a/lib/fog/libvirt/models/compute/templates/pool.xml.erb b/lib/fog/libvirt/models/compute/templates/pool.xml.erb
new file mode 100644
index 0000000..816916a
--- /dev/null
+++ b/lib/fog/libvirt/models/compute/templates/pool.xml.erb
@@ -0,0 +1,6 @@
+<pool type="dir">
+    <name><%= name %></name>
+    <target>
+      <path><%= path %></path>
+    </target>
+</pool>
diff --git a/lib/fog/libvirt/models/compute/templates/server.xml.erb b/lib/fog/libvirt/models/compute/templates/server.xml.erb
new file mode 100644
index 0000000..a7036f9
--- /dev/null
+++ b/lib/fog/libvirt/models/compute/templates/server.xml.erb
@@ -0,0 +1,54 @@
+<domain type='<%= domain_type %>'>
+  <name><%= name %></name>
+  <memory><%= memory_size %></memory>
+  <vcpu><%= cpus %></vcpu>
+  <os>
+    <type arch='<%= arch %>'><%= os_type %></type>
+<% boot_order.each do |dev| -%>
+    <boot dev='<%= dev %>'/>
+<% end -%>
+  </os>
+  <features>
+    <acpi/>
+    <apic/>
+    <pae/>
+  </features>
+  <clock offset='utc'/>
+  <devices>
+<% volumes.each do |vol| -%>
+    <disk type='file' device='disk'>
+      <driver name='qemu' type='<%= vol.format_type %>'/>
+      <source file='<%= vol.path %>'/>
+      <%# we need to ensure a unique target dev -%>
+      <target dev='vd<%= ('a'..'z').to_a[volumes.index(vol)] %>' bus='virtio'/>
+    </disk>
+<% end -%>
+<% if iso_file -%>
+    <disk type='file' device='cdrom'>
+      <driver name='qemu' type='raw'/>
+      <source file='<%= "#{iso_dir}/#{iso_file}" %>'/>
+      <target dev='hdc' bus='ide'/>
+      <readonly/>
+      <address type='drive' controller='0' bus='1' unit='0'/>
+    </disk>
+<% end -%>
+<% nics.each do |nic| -%>
+    <interface type='<%= nic.type %>'>
+      <source <%= nic.type == 'bridge' ? "bridge='#{nic.bridge}'" : "network='#{nic.network}'" %> />
+      <model type='<%= nic.model %>'/>
+    </interface>
+<% end -%>
+    <serial type='pty'>
+      <target port='0'/>
+    </serial>
+    <console type='pty'>
+      <target port='0'/>
+    </console>
+    <input type='tablet' bus='usb'/>
+    <input type='mouse' bus='ps2'/>
+    <graphics type='<%= display[:type] %>' port='<%= display[:port] %>' autoport='yes' <% if display[:listen] and !(display[:listen].empty?)  %> listen='<%= display[:listen] %>'<% end %> <% if display[:password] and !(display[:password].empty?) %>passwd='<%=display[:password] %>'<% end %> />
+    <video>
+      <model type='cirrus' vram='9216' heads='1'/>
+    </video>
+  </devices>
+</domain>
diff --git a/lib/fog/libvirt/models/compute/templates/volume.xml.erb b/lib/fog/libvirt/models/compute/templates/volume.xml.erb
new file mode 100644
index 0000000..5f78e89
--- /dev/null
+++ b/lib/fog/libvirt/models/compute/templates/volume.xml.erb
@@ -0,0 +1,26 @@
+<volume>
+        <name><%= name %></name>
+        <allocation unit="<%= split_size_unit(allocation)[1] %>"><%= split_size_unit(allocation)[0] %></allocation>
+        <capacity unit="<%= split_size_unit(capacity)[1] %>"><%= split_size_unit(capacity)[0] %></capacity>
+        <target>
+          <format type="<%= format_type %>"/>
+          <permissions>
+            <owner>0</owner>
+            <group>0</group>
+            <mode>0744</mode>
+            <label>virt_image_t</label>
+          </permissions>
+        </target>
+        <% if backing_volume -%>
+        <backingStore>
+          <path><%= backing_volume.path %></path>
+          <format type="<%= backing_volume.format_type %>"/>
+          <permissions>
+            <owner>0</owner>
+            <group>0</group>
+            <mode>0744</mode>
+            <label>virt_image_t</label>
+          </permissions>
+        </backingStore>
+        <% end -%>
+</volume>
diff --git a/lib/fog/libvirt/models/compute/util/uri.rb b/lib/fog/libvirt/models/compute/util/uri.rb
new file mode 100644
index 0000000..cbb2e86
--- /dev/null
+++ b/lib/fog/libvirt/models/compute/util/uri.rb
@@ -0,0 +1,138 @@
+require 'uri'
+require 'cgi'
+
+module Fog
+  module Compute
+    module LibvirtUtil
+      class URI
+        attr_reader :uri
+
+        def initialize(uri)
+          @parsed_uri=::URI.parse(uri)
+          @uri=uri
+          return self
+        end
+
+        # Transport will be part of the scheme
+        # The part after the plus sign
+        # f.i. qemu+ssh
+        def transport
+          scheme=@parsed_uri.scheme
+          return nil if scheme.nil?
+
+          return scheme.split(/\+/)[1]
+        end
+
+        def scheme
+          return @parsed_uri.scheme
+        end
+
+        def driver
+          scheme=@parsed_uri.scheme
+          return nil if scheme.nil?
+
+          return scheme.split(/\+/).first
+        end
+
+        def ssh_enabled?
+          if remote?
+            return transport.include?("ssh")
+          else
+            return false
+          end
+        end
+
+        def remote?
+          return !transport.nil?
+        end
+
+        def user
+          @parsed_uri.user
+        end
+
+        def host
+          @parsed_uri.host
+        end
+
+        def port
+          @parsed_uri.port
+        end
+
+        def password
+          @parsed_uri.password
+        end
+
+        def name
+          value("name")
+        end
+
+        def command
+          value("command")
+        end
+
+        def socket
+          value("socket")
+        end
+
+        def keyfile
+          value("keyfile")
+        end
+
+        def netcat
+          value("netcat")
+        end
+
+        def no_verify?
+          no_verify=value("no_verify")
+          return false if no_verify.nil?
+
+          if no_verify.to_s=="0"
+            return false
+          else
+            return true
+          end
+        end
+
+        def verify?
+          return !no_verify?
+        end
+
+        def no_tty?
+          no_tty=value("no_tty")
+
+          return false if no_tty.nil?
+
+          if no_tty=="0"
+            return false
+          else
+            return true
+          end
+        end
+
+        def tty?
+          return !no_tty?
+        end
+
+        def pkipath
+          value("pkipath")
+        end
+
+        # A libvirt URI allows you to specify extra params
+        # http://libvirt.org/remote.html
+        private
+        def value(name)
+          unless @parsed_uri.query.nil?
+            params=CGI.parse(@parsed_uri.query)
+            if params.key?(name)
+              return params[name].first
+            else
+              return nil
+            end
+          else
+            return nil
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/models/compute/util/util.rb b/lib/fog/libvirt/models/compute/util/util.rb
new file mode 100644
index 0000000..28aadf7
--- /dev/null
+++ b/lib/fog/libvirt/models/compute/util/util.rb
@@ -0,0 +1,32 @@
+require 'nokogiri'
+require 'erb'
+require 'ostruct'
+require 'securerandom'
+
+module Fog
+  module Compute
+    module LibvirtUtil
+      def xml_element(xml, path, attribute=nil)
+        xml = Nokogiri::XML(xml)
+        attribute.nil? ? (xml/path).first.text : (xml/path).first[attribute.to_sym]
+      end
+
+      def xml_elements(xml, path, attribute=nil)
+         xml = Nokogiri::XML(xml)
+         attribute.nil? ? (xml/path).map : (xml/path).map{|element| element[attribute.to_sym]}
+      end
+
+      def to_xml template_name = nil
+        # figure out our ERB template filename
+        erb = template_name || self.class.to_s.split("::").last.downcase
+        path     = File.join(File.dirname(__FILE__), "..", "templates", "#{erb}.xml.erb")
+        template = File.read(path)
+        ERB.new(template, nil, '-').result(binding)
+      end
+
+      def randomized_name
+        "fog-#{(SecureRandom.random_number*10E14).to_i.round}"
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/models/compute/volume.rb b/lib/fog/libvirt/models/compute/volume.rb
new file mode 100644
index 0000000..04e604f
--- /dev/null
+++ b/lib/fog/libvirt/models/compute/volume.rb
@@ -0,0 +1,127 @@
+require 'fog/core/model'
+require 'fog/libvirt/models/compute/util/util'
+
+module Fog
+  module Compute
+    class Libvirt
+      class Volume < Fog::Model
+        attr_reader :xml
+        include Fog::Compute::LibvirtUtil
+
+        identity :id, :aliases => 'key'
+
+        attribute :pool_name
+        attribute :key
+        attribute :name
+        attribute :path
+        attribute :capacity
+        attribute :allocation
+        attribute :format_type
+        attribute :backing_volume
+
+        # Can be created by passing in :xml => "<xml to create volume>"
+        # A volume always belongs to a pool, :pool_name => "<name of pool>"
+        #
+        def initialize(attributes={ })
+          @xml = attributes.delete(:xml)
+          super(defaults.merge(attributes))
+
+          # We need a connection to calculate the pool_name
+          # This is why we do this after super
+          self.pool_name ||= default_pool_name
+        end
+
+        # Takes a pool and either :xml or other settings
+        def save
+          requires :pool_name
+
+          raise Fog::Errors::Error.new('Reserving an existing volume may create a duplicate') if key
+          @xml ||= to_xml
+          self.path = service.create_volume(pool_name, xml).path
+        end
+
+        # Destroy a volume
+        def destroy
+          service.volume_action key, :delete
+        end
+
+        # Wipes a volume , zeroes disk
+        def wipe
+          service.volume_action key, :wipe
+        end
+
+        # Clones this volume to the name provided
+        def clone(name)
+          new_volume      = self.dup
+          new_volume.key  = nil
+          new_volume.name = name
+          new_volume.save
+
+          new_volume.reload
+        end
+
+        def clone_volume(new_name)
+          requires :pool_name
+
+          new_volume      = self.dup
+          new_volume.key  = nil
+          new_volume.name = new_name
+          new_volume.path = service.clone_volume(pool_name, new_volume.to_xml, self.name).path
+
+          new_volume.reload
+        end
+
+        def upload_image(file_path)
+          requires :pool_name
+          service.upload_volume(pool_name, name, file_path)
+        end
+
+        private
+
+        def image_suffix
+          return "img" if format_type == "raw"
+          format_type
+        end
+
+        def randominzed_name
+          "#{super}.#{image_suffix}"
+        end
+
+        # Try to guess the default/first pool of no pool_name was specified
+        def default_pool_name
+          name = "default"
+          return name unless (service.pools.all(:name => name)).empty?
+
+          # we default to the first pool we find.
+          first_pool = service.pools.first
+
+          raise Fog::Errors::Error.new('No storage pools are defined') unless first_pool
+          first_pool.name
+        end
+
+        def defaults
+          {
+            :persistent  => true,
+            :format_type => "raw",
+            :name        => randomized_name,
+            :capacity    => "10G",
+            :allocation  => "1G",
+          }
+        end
+
+        def split_size_unit(text)
+          if text.kind_of? Integer
+            # if text is an integer, match will fail
+            size    = text
+            unit    = 'G'
+          else
+            matcher = text.match(/(\d+)(.+)/)
+            size    = matcher[1]
+            unit    = matcher[2]
+          end
+          [size, unit]
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/models/compute/volumes.rb b/lib/fog/libvirt/models/compute/volumes.rb
new file mode 100644
index 0000000..a29a0b4
--- /dev/null
+++ b/lib/fog/libvirt/models/compute/volumes.rb
@@ -0,0 +1,20 @@
+require 'fog/core/collection'
+require 'fog/libvirt/models/compute/volume'
+
+module Fog
+  module Compute
+    class Libvirt
+      class Volumes < Fog::Collection
+        model Fog::Compute::Libvirt::Volume
+
+        def all(filter = {})
+          load(service.list_volumes(filter))
+        end
+
+        def get(key)
+          self.all(:key => key).first
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/requests/compute/clone_volume.rb b/lib/fog/libvirt/requests/compute/clone_volume.rb
new file mode 100644
index 0000000..fe0bc71
--- /dev/null
+++ b/lib/fog/libvirt/requests/compute/clone_volume.rb
@@ -0,0 +1,18 @@
+module Fog
+  module Compute
+    class Libvirt
+      class Real
+        def clone_volume (pool_name, xml, name)
+          vol = client.lookup_storage_pool_by_name(pool_name).lookup_volume_by_name(name)
+          client.lookup_storage_pool_by_name(pool_name).create_vol_xml_from(xml, vol)
+        end
+      end
+
+      class Mock
+        def clone_volume(pool_name, xml, name)
+          Fog::Compute::Libvirt::Volume.new({:pool_name => pool_name, :xml => xml})
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/requests/compute/create_domain.rb b/lib/fog/libvirt/requests/compute/create_domain.rb
new file mode 100644
index 0000000..8bcb733
--- /dev/null
+++ b/lib/fog/libvirt/requests/compute/create_domain.rb
@@ -0,0 +1,17 @@
+module Fog
+  module Compute
+    class Libvirt
+      class Real
+        def create_domain(xml)
+          client.create_domain_xml(xml)
+        end
+      end
+
+      class Mock
+        def create_domain(xml)
+          ::Libvirt::Domain.new()
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/requests/compute/create_volume.rb b/lib/fog/libvirt/requests/compute/create_volume.rb
new file mode 100644
index 0000000..f1f90d8
--- /dev/null
+++ b/lib/fog/libvirt/requests/compute/create_volume.rb
@@ -0,0 +1,16 @@
+module Fog
+  module Compute
+    class Libvirt
+      class Real
+        def create_volume(pool_name, xml)
+          client.lookup_storage_pool_by_name(pool_name).create_vol_xml(xml)
+        end
+      end
+
+      class Mock
+        def create_volume(pool_name, xml)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/requests/compute/define_domain.rb b/lib/fog/libvirt/requests/compute/define_domain.rb
new file mode 100644
index 0000000..53b8fae
--- /dev/null
+++ b/lib/fog/libvirt/requests/compute/define_domain.rb
@@ -0,0 +1,17 @@
+module Fog
+  module Compute
+    class Libvirt
+      class Real
+        def define_domain(xml)
+          client.define_domain_xml(xml)
+        end
+      end
+
+      class Mock
+        def define_domain(xml)
+          ::Libvirt::Domain.new()
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/requests/compute/define_pool.rb b/lib/fog/libvirt/requests/compute/define_pool.rb
new file mode 100644
index 0000000..8874bf4
--- /dev/null
+++ b/lib/fog/libvirt/requests/compute/define_pool.rb
@@ -0,0 +1,16 @@
+module Fog
+  module Compute
+    class Libvirt
+      class Real
+        def define_pool(xml)
+          client.define_storage_pool_xml(xml)
+        end
+      end
+
+      class Mock
+        def define_pool(xml)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/requests/compute/destroy_interface.rb b/lib/fog/libvirt/requests/compute/destroy_interface.rb
new file mode 100644
index 0000000..5e7bfc5
--- /dev/null
+++ b/lib/fog/libvirt/requests/compute/destroy_interface.rb
@@ -0,0 +1,18 @@
+module Fog
+  module Compute
+    class Libvirt
+      class Real
+        #shutdown the interface
+        def destroy_interface(uuid)
+          client.lookup_interface_by_uuid(uuid).destroy
+        end
+      end
+
+      class Mock
+        def destroy_interface(uuid)
+          true
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/requests/compute/destroy_network.rb b/lib/fog/libvirt/requests/compute/destroy_network.rb
new file mode 100644
index 0000000..b2c4e0e
--- /dev/null
+++ b/lib/fog/libvirt/requests/compute/destroy_network.rb
@@ -0,0 +1,17 @@
+module Fog
+  module Compute
+    class Libvirt
+      class Real
+        def destroy_network(uuid)
+          client.lookup_network_by_uuid(uuid).destroy
+        end
+      end
+
+      class Mock
+        def destroy_network(uuid)
+          true
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/requests/compute/get_node_info.rb b/lib/fog/libvirt/requests/compute/get_node_info.rb
new file mode 100644
index 0000000..9d5aa67
--- /dev/null
+++ b/lib/fog/libvirt/requests/compute/get_node_info.rb
@@ -0,0 +1,37 @@
+module Fog
+  module Compute
+    class Libvirt
+      class Real
+        def get_node_info
+          node_hash = Hash.new
+          node_info = client.node_get_info
+          [:model, :memory, :cpus, :mhz, :nodes, :sockets, :cores, :threads].each do |param|
+            node_hash[param] = node_info.send(param) rescue nil
+          end
+          [:type, :version, :node_free_memory, :max_vcpus].each do |param|
+            node_hash[param] = client.send(param) rescue nil
+          end
+          node_hash[:uri] = client.uri
+          xml = client.sys_info rescue nil
+          [:uuid, :manufacturer, :product, :serial].each do |attr|
+            node_hash[attr] = node_attr(attr, xml) rescue nil
+          end if xml
+
+          node_hash[:hostname] = client.hostname
+          [node_hash]
+        end
+
+        private
+
+        def node_attr attr, xml
+          xml_element(xml, "sysinfo/system/entry[@name='#{attr}']").strip
+        end
+      end
+
+      class Mock
+        def get_node_info
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/requests/compute/list_domains.rb b/lib/fog/libvirt/requests/compute/list_domains.rb
new file mode 100644
index 0000000..c756b32
--- /dev/null
+++ b/lib/fog/libvirt/requests/compute/list_domains.rb
@@ -0,0 +1,105 @@
+module Fog
+  module Compute
+    class Libvirt
+      class Real
+        def list_domains(filter = { })
+          data=[]
+
+          if filter.key?(:uuid)
+            data << client.lookup_domain_by_uuid(filter[:uuid])
+          elsif filter.key?(:name)
+            data << client.lookup_domain_by_name(filter[:name])
+          else
+            client.list_defined_domains.each { |name| data << client.lookup_domain_by_name(name) } unless filter[:defined] == false
+            client.list_domains.each { |id| data << client.lookup_domain_by_id(id) } unless filter[:active] == false
+          end
+          data.compact.map { |d| domain_to_attributes d }
+        end
+      end
+
+      module Shared
+        private
+
+        def domain_display xml
+          attrs = {}
+          [:type, :port, :password, :listen].each do |element|
+            attrs[element] = xml_element(xml, "domain/devices/graphics",element.to_s) rescue nil
+          end
+          attrs.reject{|k,v| v.nil? or v == ""}
+        end
+
+        def domain_volumes xml
+          xml_elements(xml, "domain/devices/disk/source", "file")
+        end
+
+        def boot_order xml
+          xml_elements(xml, "domain/os/boot", "dev")
+        end
+
+        def domain_interfaces xml
+          ifs = xml_elements(xml, "domain/devices/interface")
+          ifs.map { |i|
+            nics.new({
+              :type    => i['type'],
+              :mac     => (i/'mac').first[:address],
+              :network => ((i/'source').first[:network] rescue nil),
+              :bridge  => ((i/'source').first[:bridge] rescue nil),
+              :model   => ((i/'model').first[:type] rescue nil),
+            }.reject{|k,v| v.nil?})
+          }
+        end
+
+        def domain_to_attributes(dom)
+          states= %w(nostate running blocked paused shutting-down shutoff crashed)
+          {
+            :id              => dom.uuid,
+            :uuid            => dom.uuid,
+            :name            => dom.name,
+            :max_memory_size => dom.info.max_mem,
+            :cputime         => dom.info.cpu_time,
+            :memory_size     => dom.info.memory,
+            :cpus            => dom.info.nr_virt_cpu,
+            :autostart       => dom.autostart?,
+            :os_type         => dom.os_type,
+            :active          => dom.active?,
+            :display         => domain_display(dom.xml_desc),
+            :boot_order      => boot_order(dom.xml_desc),
+            :nics            => domain_interfaces(dom.xml_desc),
+            :volumes_path    => domain_volumes(dom.xml_desc),
+            :state           => states[dom.info.state]
+          }
+        end
+      end
+
+      class Mock
+        def list_domains(filter = { })
+          dom1 = mock_domain 'fog-dom1'
+          dom2 = mock_domain 'fog-dom2'
+          dom3 = mock_domain 'a-fog-dom3'
+          [dom1, dom2, dom3]
+        end
+
+        def mock_domain name
+          xml = read_xml 'domain.xml'
+          {
+              :id              => "dom.uuid",
+              :uuid            => "dom.uuid",
+              :name            => name,
+              :max_memory_size => 8,
+              :cputime         => 7,
+              :memory_size     => 6,
+              :cpus            => 5,
+              :autostart       => false,
+              :os_type         => "RHEL6",
+              :active          => false,
+              :vnc_port        => 5910,
+              :boot_order      => boot_order(xml),
+              :nics            => domain_interfaces(xml),
+              :volumes_path    => domain_volumes(xml),
+              :state           => 'shutoff'
+          }
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/requests/compute/list_interfaces.rb b/lib/fog/libvirt/requests/compute/list_interfaces.rb
new file mode 100644
index 0000000..d938437
--- /dev/null
+++ b/lib/fog/libvirt/requests/compute/list_interfaces.rb
@@ -0,0 +1,57 @@
+module Fog
+  module Compute
+    class Libvirt
+      class Real
+        def list_interfaces(filter = { })
+          data=[]
+          if filter.keys.empty?
+            active_networks = client.list_interfaces rescue []
+            defined_networks = client.list_defined_interfaces rescue []
+            (active_networks + defined_networks).each do |ifname|
+              data << interface_to_attributes(client.lookup_interface_by_name(ifname))
+            end
+          else
+            data = [interface_to_attributes(get_interface_by_filter(filter))]
+          end
+          data.compact
+        end
+
+        private
+        # Retrieve the interface by mac or by name
+        def get_interface_by_filter(filter)
+          case filter.keys.first
+            when :mac
+              client.lookup_interface_by_mac(filter[:mac])
+            when :name
+              client.lookup_interface_by_name(filter[:name])
+          end
+        end
+
+        def interface_to_attributes(net)
+          return if net.nil? || net.name == 'lo'
+          {
+            :mac    => net.mac,
+            :name   => net.name,
+            :active => net.active?
+          }
+        end
+      end
+
+      class Mock
+        def list_interfaces(filters={ })
+          if1 = mock_interface 'if1'
+          if2 = mock_interface 'if2'
+          [if1, if2]
+        end
+
+        def mock_interface name
+          {
+              :mac    => 'aa:bb:cc:dd:ee:ff',
+              :name   => name,
+              :active => true
+          }
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/requests/compute/list_networks.rb b/lib/fog/libvirt/requests/compute/list_networks.rb
new file mode 100644
index 0000000..5f55c2a
--- /dev/null
+++ b/lib/fog/libvirt/requests/compute/list_networks.rb
@@ -0,0 +1,55 @@
+module Fog
+  module Compute
+    class Libvirt
+      class Real
+        def list_networks(filter = { })
+          data=[]
+          if filter.keys.empty?
+            (client.list_networks + client.list_defined_networks).each do |network_name|
+              data << network_to_attributes(client.lookup_network_by_name(network_name))
+            end
+          else
+            data = [network_to_attributes(get_network_by_filter(filter))]
+          end
+          data
+        end
+
+        private
+        # Retrieve the network by uuid or name
+        def get_network_by_filter(filter)
+          case filter.keys.first
+            when :uuid
+              client.lookup_network_by_uuid(filter[:uuid])
+            when :name
+              client.lookup_network_by_name(filter[:name])
+          end
+        end
+
+        def network_to_attributes(net)
+          return if net.nil?
+          {
+            :uuid        => net.uuid,
+            :name        => net.name,
+            :bridge_name => net.bridge_name
+          }
+        end
+      end
+
+      class Mock
+        def list_networks(filters={ })
+          net1 = mock_network 'net1'
+          net2 = mock_network 'net2'
+          [net1, net2]
+        end
+
+        def mock_network name
+          {
+              :uuid        => 'net.uuid',
+              :name        => name,
+              :bridge_name => 'net.bridge_name'
+          }
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/requests/compute/list_pool_volumes.rb b/lib/fog/libvirt/requests/compute/list_pool_volumes.rb
new file mode 100644
index 0000000..6faba30
--- /dev/null
+++ b/lib/fog/libvirt/requests/compute/list_pool_volumes.rb
@@ -0,0 +1,19 @@
+module Fog
+  module Compute
+    class Libvirt
+      class Real
+        def list_pool_volumes(uuid)
+          pool = client.lookup_storage_pool_by_uuid uuid
+          pool.list_volumes.map do |volume_name|
+            volume_to_attributes(pool.lookup_volume_by_name(volume_name))
+          end
+        end
+      end
+
+      class Mock
+        def list_pool_volumes(uuid)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/requests/compute/list_pools.rb b/lib/fog/libvirt/requests/compute/list_pools.rb
new file mode 100644
index 0000000..8113b6a
--- /dev/null
+++ b/lib/fog/libvirt/requests/compute/list_pools.rb
@@ -0,0 +1,71 @@
+module Fog
+  module Compute
+    class Libvirt
+      class Real
+        def list_pools(filter = { })
+          data=[]
+          if filter.key?(:name)
+            data << find_pool_by_name(filter[:name])
+          elsif filter.key?(:uuid)
+            data << find_pool_by_uuid(filter[:uuid])
+          else
+            (client.list_storage_pools + client.list_defined_storage_pools).each do |name|
+              data << find_pool_by_name(name)
+            end
+          end
+          data.compact
+        end
+
+        private
+        def pool_to_attributes(pool)
+          states=[:inactive, :building, :running, :degrated, :inaccessible]
+          {
+            :uuid           => pool.uuid,
+            :persistent     => pool.persistent?,
+            :autostart      => pool.autostart?,
+            :active         => pool.active?,
+            :name           => pool.name,
+            :allocation     => pool.info.allocation,
+            :capacity       => pool.info.capacity,
+            :num_of_volumes => pool.num_of_volumes,
+            :state          => states[pool.info.state]
+          }
+        end
+
+        def find_pool_by_name name
+          pool_to_attributes(client.lookup_storage_pool_by_name(name))
+        rescue ::Libvirt::RetrieveError
+          nil
+        end
+
+        def find_pool_by_uuid uuid
+          pool_to_attributes(client.lookup_storage_pool_by_uuid(uuid))
+        rescue ::Libvirt::RetrieveError
+          nil
+        end
+      end
+
+      class Mock
+        def list_pools(filter = { })
+          pool1 = mock_pool 'pool1'
+          pool2 = mock_pool 'pool1'
+          [pool1, pool2]
+        end
+
+        def mock_pool name
+          {
+              :uuid           => 'pool.uuid',
+              :persistent     => true,
+              :autostart      => true,
+              :active         => true,
+              :name           => name,
+              :allocation     => 123456789,
+              :capacity       => 123456789,
+              :num_of_volumes => 3,
+              :state          => :running
+          }
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/requests/compute/list_volumes.rb b/lib/fog/libvirt/requests/compute/list_volumes.rb
new file mode 100644
index 0000000..8c7ac6a
--- /dev/null
+++ b/lib/fog/libvirt/requests/compute/list_volumes.rb
@@ -0,0 +1,88 @@
+module Fog
+  module Compute
+    class Libvirt
+      class Real
+        def list_volumes(filter = { })
+          data = []
+          if filter.keys.empty?
+            raw_volumes do |pool|
+              pool.list_volumes.each do |volume_name|
+                data << volume_to_attributes(pool.lookup_volume_by_name(volume_name))
+              end
+            end
+          else
+            return [get_volume(filter)]
+          end
+          data.compact
+        end
+
+        private
+
+        def volume_to_attributes(vol)
+          format_type = xml_element(vol.xml_desc, "/volume/target/format", "type") rescue nil # not all volumes have types, e.g. LVM
+          return nil if format_type == "dir"
+
+          {
+            :pool_name   => vol.pool.name,
+            :key         => vol.key,
+            :id          => vol.key,
+            :path        => vol.path,
+            :name        => vol.name,
+            :format_type => format_type,
+            :allocation  => bytes_to_gb(vol.info.allocation),
+            :capacity    => bytes_to_gb(vol.info.capacity),
+          }
+        end
+
+        def bytes_to_gb bytes
+          bytes / 1024**3
+        end
+
+        def raw_volumes
+          client.list_storage_pools.each do |pool_name|
+            pool = client.lookup_storage_pool_by_name(pool_name)
+            yield(pool)
+          end
+        end
+
+        def get_volume filter = { }, raw = false
+          raw_volumes do |pool|
+            vol = case filter.keys.first
+                    when :name
+                      pool.lookup_volume_by_name(filter[:name]) rescue nil
+                    when :key
+                      pool.lookup_volume_by_key(filter[:key]) rescue nil
+                    when :path
+                      pool.lookup_volume_by_path(filter[:path]) rescue nil
+                  end
+            if vol
+              return raw ? vol : volume_to_attributes(vol)
+            end
+          end
+          { }
+        end
+      end
+
+      class Mock
+        def list_volumes(filters={ })
+          vol1 = mock_volume 'vol1'
+          vol2 = mock_volume 'vol2'
+          [vol1, vol2]
+        end
+
+        def mock_volume name
+          {
+              :pool_name   => 'vol.pool.name',
+              :key         => 'vol.key',
+              :id          => 'vol.key',
+              :path        => 'vol.path',
+              :name        => name,
+              :format_type => 'raw',
+              :allocation  => 123,
+              :capacity    => 123,
+          }
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/requests/compute/mock_files/domain.xml b/lib/fog/libvirt/requests/compute/mock_files/domain.xml
new file mode 100644
index 0000000..7720f1f
--- /dev/null
+++ b/lib/fog/libvirt/requests/compute/mock_files/domain.xml
@@ -0,0 +1,40 @@
+<domain type='kvm'>
+ <name>fog-449765558356062</name>
+ <memory>262144</memory>
+ <vcpu>1</vcpu>
+ <os>
+  <type arch='x86_64'>hvm</type>
+  <boot dev='hd'/>
+  <boot dev='cdrom'/>
+  <boot dev='network'/>
+ </os>
+ <features>
+   <acpi/>
+   <apic/>
+   <pae/>
+ </features>
+ <clock offset='utc'/>
+ <devices>
+  <interface type='network'>
+    <mac address="aa:bb:cc:dd:ee:ff" />
+    <source network='net1' />
+    <model type='virtio'/>
+  </interface>
+  <serial type='pty'>
+   <target port='0'/>
+  </serial>
+  <console type='pty'>
+    <target port='0'/>
+  </console>
+  <input type='mouse' bus='ps2'/>
+  <graphics type='vnc' port='-1' autoport='yes'/>
+  <video>
+   <model type='cirrus' vram='9216' heads='1'/>
+  </video>
+  <disk type='file' device='disk'>
+   <driver name='qemu' type='raw'/>
+   <source file='path/to/disk'/>
+   <target dev='vda' bus='virtio'/>
+  </disk>
+ </devices>
+</domain>
diff --git a/lib/fog/libvirt/requests/compute/pool_action.rb b/lib/fog/libvirt/requests/compute/pool_action.rb
new file mode 100644
index 0000000..942efd0
--- /dev/null
+++ b/lib/fog/libvirt/requests/compute/pool_action.rb
@@ -0,0 +1,19 @@
+module Fog
+  module Compute
+    class Libvirt
+      class Real
+        def pool_action(uuid, action)
+          pool = client.lookup_storage_pool_by_uuid uuid
+          pool.send(action)
+          true
+        end
+      end
+
+      class Mock
+        def pool_action(uuid, action)
+          true
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/requests/compute/update_display.rb b/lib/fog/libvirt/requests/compute/update_display.rb
new file mode 100644
index 0000000..a2141e1
--- /dev/null
+++ b/lib/fog/libvirt/requests/compute/update_display.rb
@@ -0,0 +1,31 @@
+module Fog
+  module Compute
+    class Libvirt
+      class Real
+        def update_display(options = { })
+          raise ArgumentError, "uuid is a required parameter" unless options.key? :uuid
+          display          = { }
+          display[:type]   = options[:type] || 'vnc'
+          display[:port]   = (options[:port] || -1).to_s
+          display[:listen] = options[:listen].to_s   if options[:listen]
+          display[:passwd] = options[:password].to_s if options[:password]
+          display[:autoport] = 'yes' if display[:port] == '-1'
+
+          builder = Nokogiri::XML::Builder.new { graphics_ (display) }
+          xml     = Nokogiri::XML(builder.to_xml).root.to_s
+
+          client.lookup_domain_by_uuid(options[:uuid]).update_device(xml, 0)
+          # if we got no exceptions, then we're good'
+          true
+        end
+      end
+
+      class Mock
+        def update_display(options = { })
+          raise ArgumentError, "uuid is a required parameter" unless options.key? :uuid
+          true
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/requests/compute/upload_volume.rb b/lib/fog/libvirt/requests/compute/upload_volume.rb
new file mode 100644
index 0000000..ace05e7
--- /dev/null
+++ b/lib/fog/libvirt/requests/compute/upload_volume.rb
@@ -0,0 +1,31 @@
+module Fog
+  module Compute
+    class Libvirt
+      class Real
+        def upload_volume(pool_name, volume_name, file_path)
+          volume = client.lookup_storage_pool_by_name(pool_name).lookup_volume_by_name(volume_name)
+          stream = client.stream
+
+          image_file = File.open(file_path, "rb")
+          volume.upload(stream, 0, image_file.size)
+          stream.sendall do |_opaque, n|
+            begin
+              r = image_file.read(n)
+              [r.length < n ? 0 : r.length, r]
+            rescue Exception => e
+              [-1, ""]
+            end
+          end
+          stream.finish
+        ensure
+          image_file.close if image_file
+        end
+      end
+
+      class Mock
+        def upload_volume(pool_name, volume_name, file_path)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/requests/compute/vm_action.rb b/lib/fog/libvirt/requests/compute/vm_action.rb
new file mode 100644
index 0000000..3078028
--- /dev/null
+++ b/lib/fog/libvirt/requests/compute/vm_action.rb
@@ -0,0 +1,19 @@
+module Fog
+  module Compute
+    class Libvirt
+      class Real
+        def vm_action(uuid, action)
+          domain = client.lookup_domain_by_uuid(uuid)
+          domain.send(action)
+          true
+        end
+      end
+
+      class Mock
+        def vm_action(uuid, action)
+          true
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/requests/compute/volume_action.rb b/lib/fog/libvirt/requests/compute/volume_action.rb
new file mode 100644
index 0000000..1a3f849
--- /dev/null
+++ b/lib/fog/libvirt/requests/compute/volume_action.rb
@@ -0,0 +1,18 @@
+module Fog
+  module Compute
+    class Libvirt
+      class Real
+        def volume_action(key, action, options={})
+          get_volume({:key => key}, true).send(action)
+          true
+        end
+      end
+
+      class Mock
+        def volume_action(action, options={})
+          true
+        end
+      end
+    end
+  end
+end
diff --git a/lib/fog/libvirt/version.rb b/lib/fog/libvirt/version.rb
new file mode 100644
index 0000000..9d3fec2
--- /dev/null
+++ b/lib/fog/libvirt/version.rb
@@ -0,0 +1,5 @@
+module Fog
+  module Libvirt
+    VERSION = '0.0.2'
+  end
+end
diff --git a/metadata.yml b/metadata.yml
new file mode 100644
index 0000000..77fdffd
--- /dev/null
+++ b/metadata.yml
@@ -0,0 +1,344 @@
+--- !ruby/object:Gem::Specification
+name: fog-libvirt
+version: !ruby/object:Gem::Version
+  version: 0.0.2
+platform: ruby
+authors:
+- geemus (Wesley Beary)
+autorequire: 
+bindir: bin
+cert_chain: []
+date: 2015-06-16 00:00:00.000000000 Z
+dependencies:
+- !ruby/object:Gem::Dependency
+  name: fog-core
+  requirement: !ruby/object:Gem::Requirement
+    requirements:
+    - - "~>"
+      - !ruby/object:Gem::Version
+        version: '1.27'
+    - - ">="
+      - !ruby/object:Gem::Version
+        version: 1.27.4
+  type: :runtime
+  prerelease: false
+  version_requirements: !ruby/object:Gem::Requirement
+    requirements:
+    - - "~>"
+      - !ruby/object:Gem::Version
+        version: '1.27'
+    - - ">="
+      - !ruby/object:Gem::Version
+        version: 1.27.4
+- !ruby/object:Gem::Dependency
+  name: fog-json
+  requirement: !ruby/object:Gem::Requirement
+    requirements:
+    - - ">="
+      - !ruby/object:Gem::Version
+        version: '0'
+  type: :runtime
+  prerelease: false
+  version_requirements: !ruby/object:Gem::Requirement
+    requirements:
+    - - ">="
+      - !ruby/object:Gem::Version
+        version: '0'
+- !ruby/object:Gem::Dependency
+  name: fog-xml
+  requirement: !ruby/object:Gem::Requirement
+    requirements:
+    - - "~>"
+      - !ruby/object:Gem::Version
+        version: 0.1.1
+  type: :runtime
+  prerelease: false
+  version_requirements: !ruby/object:Gem::Requirement
+    requirements:
+    - - "~>"
+      - !ruby/object:Gem::Version
+        version: 0.1.1
+- !ruby/object:Gem::Dependency
+  name: ruby-libvirt
+  requirement: !ruby/object:Gem::Requirement
+    requirements:
+    - - "~>"
+      - !ruby/object:Gem::Version
+        version: 0.5.0
+  type: :runtime
+  prerelease: false
+  version_requirements: !ruby/object:Gem::Requirement
+    requirements:
+    - - "~>"
+      - !ruby/object:Gem::Version
+        version: 0.5.0
+- !ruby/object:Gem::Dependency
+  name: json
+  requirement: !ruby/object:Gem::Requirement
+    requirements:
+    - - ">="
+      - !ruby/object:Gem::Version
+        version: '0'
+  type: :runtime
+  prerelease: false
+  version_requirements: !ruby/object:Gem::Requirement
+    requirements:
+    - - ">="
+      - !ruby/object:Gem::Version
+        version: '0'
+- !ruby/object:Gem::Dependency
+  name: minitest
+  requirement: !ruby/object:Gem::Requirement
+    requirements:
+    - - ">="
+      - !ruby/object:Gem::Version
+        version: '0'
+  type: :development
+  prerelease: false
+  version_requirements: !ruby/object:Gem::Requirement
+    requirements:
+    - - ">="
+      - !ruby/object:Gem::Version
+        version: '0'
+- !ruby/object:Gem::Dependency
+  name: minitest-stub-const
+  requirement: !ruby/object:Gem::Requirement
+    requirements:
+    - - ">="
+      - !ruby/object:Gem::Version
+        version: '0'
+  type: :development
+  prerelease: false
+  version_requirements: !ruby/object:Gem::Requirement
+    requirements:
+    - - ">="
+      - !ruby/object:Gem::Version
+        version: '0'
+- !ruby/object:Gem::Dependency
+  name: pry
+  requirement: !ruby/object:Gem::Requirement
+    requirements:
+    - - ">="
+      - !ruby/object:Gem::Version
+        version: '0'
+  type: :development
+  prerelease: false
+  version_requirements: !ruby/object:Gem::Requirement
+    requirements:
+    - - ">="
+      - !ruby/object:Gem::Version
+        version: '0'
+- !ruby/object:Gem::Dependency
+  name: rake
+  requirement: !ruby/object:Gem::Requirement
+    requirements:
+    - - ">="
+      - !ruby/object:Gem::Version
+        version: '0'
+  type: :development
+  prerelease: false
+  version_requirements: !ruby/object:Gem::Requirement
+    requirements:
+    - - ">="
+      - !ruby/object:Gem::Version
+        version: '0'
+- !ruby/object:Gem::Dependency
+  name: rubocop
+  requirement: !ruby/object:Gem::Requirement
+    requirements:
+    - - ">="
+      - !ruby/object:Gem::Version
+        version: '0'
+  type: :development
+  prerelease: false
+  version_requirements: !ruby/object:Gem::Requirement
+    requirements:
+    - - ">="
+      - !ruby/object:Gem::Version
+        version: '0'
+- !ruby/object:Gem::Dependency
+  name: shindo
+  requirement: !ruby/object:Gem::Requirement
+    requirements:
+    - - "~>"
+      - !ruby/object:Gem::Version
+        version: 0.3.4
+  type: :development
+  prerelease: false
+  version_requirements: !ruby/object:Gem::Requirement
+    requirements:
+    - - "~>"
+      - !ruby/object:Gem::Version
+        version: 0.3.4
+- !ruby/object:Gem::Dependency
+  name: simplecov
+  requirement: !ruby/object:Gem::Requirement
+    requirements:
+    - - ">="
+      - !ruby/object:Gem::Version
+        version: '0'
+  type: :development
+  prerelease: false
+  version_requirements: !ruby/object:Gem::Requirement
+    requirements:
+    - - ">="
+      - !ruby/object:Gem::Version
+        version: '0'
+- !ruby/object:Gem::Dependency
+  name: yard
+  requirement: !ruby/object:Gem::Requirement
+    requirements:
+    - - ">="
+      - !ruby/object:Gem::Version
+        version: '0'
+  type: :development
+  prerelease: false
+  version_requirements: !ruby/object:Gem::Requirement
+    requirements:
+    - - ">="
+      - !ruby/object:Gem::Version
+        version: '0'
+- !ruby/object:Gem::Dependency
+  name: mocha
+  requirement: !ruby/object:Gem::Requirement
+    requirements:
+    - - "~>"
+      - !ruby/object:Gem::Version
+        version: 1.1.0
+  type: :development
+  prerelease: false
+  version_requirements: !ruby/object:Gem::Requirement
+    requirements:
+    - - "~>"
+      - !ruby/object:Gem::Version
+        version: 1.1.0
+description: This library can be used as a module for 'fog' or as standalone libvirt
+  provider.
+email: geemus at gmail.com
+executables: []
+extensions: []
+extra_rdoc_files:
+- README.md
+files:
+- CONTRIBUTORS.md
+- Gemfile
+- LICENSE.md
+- README.md
+- Rakefile
+- fog-libvirt.gemspec
+- lib/fog/bin/libvirt.rb
+- lib/fog/libvirt.rb
+- lib/fog/libvirt/compute.rb
+- lib/fog/libvirt/models/compute/README.md
+- lib/fog/libvirt/models/compute/interface.rb
+- lib/fog/libvirt/models/compute/interfaces.rb
+- lib/fog/libvirt/models/compute/network.rb
+- lib/fog/libvirt/models/compute/networks.rb
+- lib/fog/libvirt/models/compute/nic.rb
+- lib/fog/libvirt/models/compute/nics.rb
+- lib/fog/libvirt/models/compute/node.rb
+- lib/fog/libvirt/models/compute/nodes.rb
+- lib/fog/libvirt/models/compute/pool.rb
+- lib/fog/libvirt/models/compute/pools.rb
+- lib/fog/libvirt/models/compute/server.rb
+- lib/fog/libvirt/models/compute/servers.rb
+- lib/fog/libvirt/models/compute/templates/network.xml.erb
+- lib/fog/libvirt/models/compute/templates/pool.xml.erb
+- lib/fog/libvirt/models/compute/templates/server.xml.erb
+- lib/fog/libvirt/models/compute/templates/volume.xml.erb
+- lib/fog/libvirt/models/compute/util/uri.rb
+- lib/fog/libvirt/models/compute/util/util.rb
+- lib/fog/libvirt/models/compute/volume.rb
+- lib/fog/libvirt/models/compute/volumes.rb
+- lib/fog/libvirt/requests/compute/clone_volume.rb
+- lib/fog/libvirt/requests/compute/create_domain.rb
+- lib/fog/libvirt/requests/compute/create_volume.rb
+- lib/fog/libvirt/requests/compute/define_domain.rb
+- lib/fog/libvirt/requests/compute/define_pool.rb
+- lib/fog/libvirt/requests/compute/destroy_interface.rb
+- lib/fog/libvirt/requests/compute/destroy_network.rb
+- lib/fog/libvirt/requests/compute/get_node_info.rb
+- lib/fog/libvirt/requests/compute/list_domains.rb
+- lib/fog/libvirt/requests/compute/list_interfaces.rb
+- lib/fog/libvirt/requests/compute/list_networks.rb
+- lib/fog/libvirt/requests/compute/list_pool_volumes.rb
+- lib/fog/libvirt/requests/compute/list_pools.rb
+- lib/fog/libvirt/requests/compute/list_volumes.rb
+- lib/fog/libvirt/requests/compute/mock_files/domain.xml
+- lib/fog/libvirt/requests/compute/pool_action.rb
+- lib/fog/libvirt/requests/compute/update_display.rb
+- lib/fog/libvirt/requests/compute/upload_volume.rb
+- lib/fog/libvirt/requests/compute/vm_action.rb
+- lib/fog/libvirt/requests/compute/volume_action.rb
+- lib/fog/libvirt/version.rb
+- minitests/server/user_data_iso_test.rb
+- minitests/test_helper.rb
+- tests/helper.rb
+- tests/helpers/formats_helper.rb
+- tests/helpers/formats_helper_tests.rb
+- tests/helpers/mock_helper.rb
+- tests/helpers/succeeds_helper.rb
+- tests/libvirt/compute_tests.rb
+- tests/libvirt/models/compute/interface_tests.rb
+- tests/libvirt/models/compute/interfaces_tests.rb
+- tests/libvirt/models/compute/network_tests.rb
+- tests/libvirt/models/compute/networks_tests.rb
+- tests/libvirt/models/compute/nic_tests.rb
+- tests/libvirt/models/compute/nics_tests.rb
+- tests/libvirt/models/compute/pool_tests.rb
+- tests/libvirt/models/compute/pools_tests.rb
+- tests/libvirt/models/compute/server_tests.rb
+- tests/libvirt/models/compute/servers_tests.rb
+- tests/libvirt/models/compute/volume_tests.rb
+- tests/libvirt/models/compute/volumes_tests.rb
+- tests/libvirt/requests/compute/create_domain_tests.rb
+- tests/libvirt/requests/compute/define_domain_tests.rb
+- tests/libvirt/requests/compute/update_display.rb
+homepage: http://github.com/fog/fog-libvirt
+licenses:
+- MIT
+metadata: {}
+post_install_message: 
+rdoc_options:
+- "--charset=UTF-8"
+require_paths:
+- lib
+required_ruby_version: !ruby/object:Gem::Requirement
+  requirements:
+  - - ">="
+    - !ruby/object:Gem::Version
+      version: '0'
+required_rubygems_version: !ruby/object:Gem::Requirement
+  requirements:
+  - - ">="
+    - !ruby/object:Gem::Version
+      version: '0'
+requirements: []
+rubyforge_project: 
+rubygems_version: 2.2.2
+signing_key: 
+specification_version: 2
+summary: Module for the 'fog' gem to support libvirt
+test_files:
+- tests/helper.rb
+- tests/helpers/formats_helper.rb
+- tests/helpers/formats_helper_tests.rb
+- tests/helpers/mock_helper.rb
+- tests/helpers/succeeds_helper.rb
+- tests/libvirt/compute_tests.rb
+- tests/libvirt/models/compute/interface_tests.rb
+- tests/libvirt/models/compute/interfaces_tests.rb
+- tests/libvirt/models/compute/network_tests.rb
+- tests/libvirt/models/compute/networks_tests.rb
+- tests/libvirt/models/compute/nic_tests.rb
+- tests/libvirt/models/compute/nics_tests.rb
+- tests/libvirt/models/compute/pool_tests.rb
+- tests/libvirt/models/compute/pools_tests.rb
+- tests/libvirt/models/compute/server_tests.rb
+- tests/libvirt/models/compute/servers_tests.rb
+- tests/libvirt/models/compute/volume_tests.rb
+- tests/libvirt/models/compute/volumes_tests.rb
+- tests/libvirt/requests/compute/create_domain_tests.rb
+- tests/libvirt/requests/compute/define_domain_tests.rb
+- tests/libvirt/requests/compute/update_display.rb
+has_rdoc: 
diff --git a/minitests/server/user_data_iso_test.rb b/minitests/server/user_data_iso_test.rb
new file mode 100644
index 0000000..d57b99d
--- /dev/null
+++ b/minitests/server/user_data_iso_test.rb
@@ -0,0 +1,69 @@
+require 'test_helper'
+
+class UserDataIsoTest < Minitest::Test
+  def setup
+    @compute = Fog::Compute[:libvirt]
+    @server = @compute.servers.new(:name => "test")
+    @test_data = "test data"
+  end
+
+  def test_contains_meta_data_file
+    @server.stubs(:system).returns(true)
+    in_a_temp_dir do |d|
+      @server.generate_config_iso_in_dir(d, @test_data) {|iso| assert File.exist?(File.join(d, 'meta-data')) }
+    end
+  end
+
+  def test_contains_user_data_file
+    @server.stubs(:system).returns(true)
+    in_a_temp_dir do |d|
+      @server.generate_config_iso_in_dir(d, @test_data) do |iso|
+        assert File.exist?(File.join(d, 'user-data'))
+        assert_equal @test_data,  File.read(File.join(d, 'user-data'))
+      end
+    end
+  end
+
+  def test_iso_is_generated
+    in_a_temp_dir do |d|
+      @server.expects(:system).with(regexp_matches(/^genisoimage/)).returns(true)
+      @server.generate_config_iso_in_dir(d, @test_data) {|iso| }
+    end
+  end
+
+  def test_volume_is_created_during_user_data_iso_generation
+    iso_path = "iso_file_path"
+    @server.stubs(:system).returns(true)
+    Fog::Compute::Libvirt::Volumes.any_instance.expects(:create).
+        with(has_entries(:name => @server.cloud_init_volume_name)).
+        returns(@compute.volumes.new)
+    Fog::Compute::Libvirt::Volume.any_instance.stubs(:upload_image)
+
+    @server.create_user_data_iso
+  end
+
+  def test_volume_is_uploaded_during_user_data_iso_generation
+    iso_path = "iso_file_path"
+    @server.stubs(:system).returns(true)
+    Fog::Compute::Libvirt::Volumes.any_instance.stubs(:create).returns(@compute.volumes.new)
+    Fog::Compute::Libvirt::Volume.any_instance.expects(:upload_image).returns(true)
+
+    @server.create_user_data_iso
+  end
+
+  def test_iso_file_is_set_during_user_data_iso_generation
+    iso_path = "iso_file_path"
+    @server.stubs(:system).returns(true)
+    Fog::Compute::Libvirt::Volumes.any_instance.stubs(:create).returns(@compute.volumes.new)
+    Fog::Compute::Libvirt::Volume.any_instance.stubs(:upload_image)
+
+    @server.create_user_data_iso
+    assert_equal @server.cloud_init_volume_name, @server.iso_file
+  end
+
+  def in_a_temp_dir
+    Dir.mktmpdir('test-dir') do |d|
+      yield d
+    end
+  end
+end
diff --git a/minitests/test_helper.rb b/minitests/test_helper.rb
new file mode 100644
index 0000000..220c848
--- /dev/null
+++ b/minitests/test_helper.rb
@@ -0,0 +1,18 @@
+require 'minitest/autorun'
+require 'mocha/mini_test'
+require 'fileutils'
+
+$: << File.join(File.dirname(__FILE__), '..', 'lib')
+
+logdir = File.join(File.dirname(__FILE__), '..', 'logs')
+FileUtils.mkdir_p(logdir) unless File.exist?(logdir)
+
+ENV['TMPDIR'] = 'test/tmp'
+FileUtils.rm_f Dir.glob 'test/tmp/*.tmp'
+
+require 'fog/libvirt'
+
+Fog.mock!
+Fog.credentials = {
+    :libvirt_uri => 'qemu://libvirt/system',
+}.merge(Fog.credentials)
diff --git a/tests/helper.rb b/tests/helper.rb
new file mode 100644
index 0000000..a6cccdb
--- /dev/null
+++ b/tests/helper.rb
@@ -0,0 +1,17 @@
+ENV['FOG_RC']         = ENV['FOG_RC'] || File.expand_path('../.fog', __FILE__)
+ENV['FOG_CREDENTIAL'] = ENV['FOG_CREDENTIAL'] || 'default'
+
+require 'fog/libvirt'
+
+Excon.defaults.merge!(:debug_request => true, :debug_response => true)
+
+require File.expand_path(File.join(File.dirname(__FILE__), 'helpers', 'mock_helper'))
+
+# This overrides the default 600 seconds timeout during live test runs
+if Fog.mocking?
+  FOG_TESTING_TIMEOUT = ENV['FOG_TEST_TIMEOUT'] || 2000
+  Fog.timeout = 2000
+  Fog::Logger.warning "Setting default fog timeout to #{Fog.timeout} seconds"
+else
+  FOG_TESTING_TIMEOUT = Fog.timeout
+end
diff --git a/tests/helpers/formats_helper.rb b/tests/helpers/formats_helper.rb
new file mode 100644
index 0000000..0053bb5
--- /dev/null
+++ b/tests/helpers/formats_helper.rb
@@ -0,0 +1,98 @@
+require "fog/schema/data_validator"
+
+# format related hackery
+# allows both true.is_a?(Fog::Boolean) and false.is_a?(Fog::Boolean)
+# allows both nil.is_a?(Fog::Nullable::String) and ''.is_a?(Fog::Nullable::String)
+module Fog
+  module Boolean; end
+  module Nullable
+    module Boolean; end
+    module Integer; end
+    module String; end
+    module Time; end
+    module Float; end
+    module Hash; end
+    module Array; end
+  end
+end
+[FalseClass, TrueClass].each {|klass| klass.send(:include, Fog::Boolean)}
+[FalseClass, TrueClass, NilClass, Fog::Boolean].each {|klass| klass.send(:include, Fog::Nullable::Boolean)}
+[NilClass, String].each {|klass| klass.send(:include, Fog::Nullable::String)}
+[NilClass, Time].each {|klass| klass.send(:include, Fog::Nullable::Time)}
+[Integer, NilClass].each {|klass| klass.send(:include, Fog::Nullable::Integer)}
+[Float, NilClass].each {|klass| klass.send(:include, Fog::Nullable::Float)}
+[Hash, NilClass].each {|klass| klass.send(:include, Fog::Nullable::Hash)}
+[Array, NilClass].each {|klass| klass.send(:include, Fog::Nullable::Array)}
+
+module Shindo
+  class Tests
+    # Generates a Shindo test that compares a hash schema to the result
+    # of the passed in block returning true if they match.
+    #
+    # The schema that is passed in is a Hash or Array of hashes that
+    # have Classes in place of values. When checking the schema the
+    # value should match the Class.
+    #
+    # Strict mode will fail if the data has additional keys. Setting
+    # +strict+ to +false+ will allow additional keys to appear.
+    #
+    # @param [Hash] schema A Hash schema
+    # @param [Hash] options Options to change validation rules
+    # @option options [Boolean] :allow_extra_keys
+    #     If +true+ does not fail when keys are in the data that are
+    #     not specified in the schema. This allows new values to
+    #     appear in API output without breaking the check.
+    # @option options [Boolean] :allow_optional_rules
+    #     If +true+ does not fail if extra keys are in the schema
+    #     that do not match the data. Not recommended!
+    # @yield Data to check with schema
+    #
+    # @example Using in a test
+    #     Shindo.tests("comparing welcome data against schema") do
+    #       data = {:welcome => "Hello" }
+    #       data_matches_schema(:welcome => String) { data }
+    #     end
+    #
+    #     comparing welcome data against schema
+    #     + data matches schema
+    #
+    # @example Example schema
+    #     {
+    #       "id" => String,
+    #       "ram" => Integer,
+    #       "disks" => [
+    #         {
+    #           "size" => Float
+    #         }
+    #       ],
+    #       "dns_name" => Fog::Nullable::String,
+    #       "active" => Fog::Boolean,
+    #       "created" => DateTime
+    #     }
+    #
+    # @return [Boolean]
+    def data_matches_schema(schema, options = {})
+      test('data matches schema') do
+        validator = Fog::Schema::DataValidator.new
+        valid = validator.validate(yield, schema, options)
+        @message = validator.message unless valid
+        valid
+      end
+    end
+
+    # @deprecated #formats is deprecated. Use #data_matches_schema instead
+    def formats(format, strict = true)
+      test('has proper format') do
+        if strict
+          options = {:allow_extra_keys => false, :allow_optional_rules => true}
+        else
+          options = {:allow_extra_keys => true, :allow_optional_rules => true}
+        end
+        validator = Fog::Schema::DataValidator.new
+        valid = validator.validate(yield, format, options)
+        @message = validator.message unless valid
+        valid
+      end
+    end
+  end
+end
diff --git a/tests/helpers/formats_helper_tests.rb b/tests/helpers/formats_helper_tests.rb
new file mode 100644
index 0000000..dba2386
--- /dev/null
+++ b/tests/helpers/formats_helper_tests.rb
@@ -0,0 +1,110 @@
+Shindo.tests('test_helper', 'meta') do
+
+  tests('comparing welcome data against schema') do
+    data = {:welcome => "Hello" }
+    data_matches_schema(:welcome => String) { data }
+  end
+
+  tests('#data_matches_schema') do
+    tests('when value matches schema expectation') do
+      data_matches_schema({"key" => String}) { {"key" => "Value"} }
+    end
+
+    tests('when values within an array all match schema expectation') do
+      data_matches_schema({"key" => [Integer]}) { {"key" => [1, 2]} }
+    end
+
+    tests('when nested values match schema expectation') do
+      data_matches_schema({"key" => {:nested_key => String}}) { {"key" => {:nested_key => "Value"}} }
+    end
+
+    tests('when collection of values all match schema expectation') do
+      data_matches_schema([{"key" => String}]) { [{"key" => "Value"}, {"key" => "Value"}] }
+    end
+
+    tests('when collection is empty although schema covers optional members') do
+      data_matches_schema([{"key" => String}], {:allow_optional_rules => true}) { [] }
+    end
+
+    tests('when additional keys are passed and not strict') do
+      data_matches_schema({"key" => String}, {:allow_extra_keys => true}) { {"key" => "Value", :extra => "Bonus"} }
+    end
+
+    tests('when value is nil and schema expects NilClass') do
+      data_matches_schema({"key" => NilClass}) { {"key" => nil} }
+    end
+
+    tests('when value and schema match as hashes') do
+      data_matches_schema({}) { {} }
+    end
+
+    tests('when value and schema match as arrays') do
+      data_matches_schema([]) { [] }
+    end
+
+    tests('when value is a Time') do
+      data_matches_schema({"time" => Time}) { {"time" => Time.now} }
+    end
+
+    tests('when key is missing but value should be NilClass (#1477)') do
+      data_matches_schema({"key" => NilClass}, {:allow_optional_rules => true}) { {} }
+    end
+
+    tests('when key is missing but value is nullable (#1477)') do
+      data_matches_schema({"key" => Fog::Nullable::String}, {:allow_optional_rules => true}) { {} }
+    end
+  end
+
+  tests('#formats backwards compatible changes') do
+
+    tests('when value matches schema expectation') do
+      formats({"key" => String}) { {"key" => "Value"} }
+    end
+
+    tests('when values within an array all match schema expectation') do
+      formats({"key" => [Integer]}) { {"key" => [1, 2]} }
+    end
+
+    tests('when nested values match schema expectation') do
+      formats({"key" => {:nested_key => String}}) { {"key" => {:nested_key => "Value"}} }
+    end
+
+    tests('when collection of values all match schema expectation') do
+      formats([{"key" => String}]) { [{"key" => "Value"}, {"key" => "Value"}] }
+    end
+
+    tests('when collection is empty although schema covers optional members') do
+      formats([{"key" => String}]) { [] }
+    end
+
+    tests('when additional keys are passed and not strict') do
+      formats({"key" => String}, false) { {"key" => "Value", :extra => "Bonus"} }
+    end
+
+    tests('when value is nil and schema expects NilClass') do
+      formats({"key" => NilClass}) { {"key" => nil} }
+    end
+
+    tests('when value and schema match as hashes') do
+      formats({}) { {} }
+    end
+
+    tests('when value and schema match as arrays') do
+      formats([]) { [] }
+    end
+
+    tests('when value is a Time') do
+      formats({"time" => Time}) { {"time" => Time.now} }
+    end
+
+    tests('when key is missing but value should be NilClass (#1477)') do
+      formats({"key" => NilClass}) { {} }
+    end
+
+    tests('when key is missing but value is nullable (#1477)') do
+      formats({"key" => Fog::Nullable::String}) { {} }
+    end
+
+  end
+
+end
diff --git a/tests/helpers/mock_helper.rb b/tests/helpers/mock_helper.rb
new file mode 100644
index 0000000..0fcaca2
--- /dev/null
+++ b/tests/helpers/mock_helper.rb
@@ -0,0 +1,14 @@
+# Use so you can run in mock mode from the command line
+#
+# FOG_MOCK=true fog
+
+if ENV["FOG_MOCK"] == "true"
+  Fog.mock!
+end
+
+# if in mocked mode, fill in some fake credentials for us
+if Fog.mock?
+  Fog.credentials = {
+    :libvirt_uri                      => 'qemu://libvirt/system',
+  }.merge(Fog.credentials)
+end
diff --git a/tests/helpers/succeeds_helper.rb b/tests/helpers/succeeds_helper.rb
new file mode 100644
index 0000000..b54589e
--- /dev/null
+++ b/tests/helpers/succeeds_helper.rb
@@ -0,0 +1,9 @@
+module Shindo
+  class Tests
+    def succeeds
+      test('succeeds') do
+        !!instance_eval(&Proc.new)
+      end
+    end
+  end
+end
diff --git a/tests/libvirt/compute_tests.rb b/tests/libvirt/compute_tests.rb
new file mode 100644
index 0000000..ae78b9a
--- /dev/null
+++ b/tests/libvirt/compute_tests.rb
@@ -0,0 +1,17 @@
+Shindo.tests('Fog::Compute[:libvirt]', ['libvirt']) do
+
+  compute = Fog::Compute[:libvirt]
+
+  tests("Compute collections") do
+    %w{ servers interfaces networks nics nodes pools volumes}.each do |collection|
+      test("it should respond to #{collection}") { compute.respond_to? collection }
+    end
+  end
+
+  tests("Compute requests") do
+    %w{ create_domain create_volume define_domain define_pool destroy_interface destroy_network get_node_info list_domains
+        list_interfaces list_networks list_pools list_pool_volumes list_volumes pool_action vm_action volume_action }.each do |request|
+      test("it should respond to #{request}") { compute.respond_to? request }
+    end
+  end
+end
diff --git a/tests/libvirt/models/compute/interface_tests.rb b/tests/libvirt/models/compute/interface_tests.rb
new file mode 100644
index 0000000..7de6917
--- /dev/null
+++ b/tests/libvirt/models/compute/interface_tests.rb
@@ -0,0 +1,27 @@
+Shindo.tests('Fog::Compute[:libvirt] | interface model', ['libvirt']) do
+
+  interfaces = Fog::Compute[:libvirt].interfaces
+  interface = interfaces.last
+
+  tests('The interface model should') do
+    tests('have the action') do
+      test('reload') { interface.respond_to? 'reload' }
+    end
+    tests('have attributes') do
+      model_attribute_hash = interface.attributes
+      attributes = [ :name, :mac, :active]
+      tests("The interface model should respond to") do
+        attributes.each do |attribute|
+          test("#{attribute}") { interface.respond_to? attribute }
+        end
+      end
+      tests("The attributes hash should have key") do
+        attributes.each do |attribute|
+          test("#{attribute}") { model_attribute_hash.key? attribute }
+        end
+      end
+    end
+    test('be a kind of Fog::Compute::Libvirt::Interface') { interface.kind_of? Fog::Compute::Libvirt::Interface }
+  end
+
+end
diff --git a/tests/libvirt/models/compute/interfaces_tests.rb b/tests/libvirt/models/compute/interfaces_tests.rb
new file mode 100644
index 0000000..a5f7f4b
--- /dev/null
+++ b/tests/libvirt/models/compute/interfaces_tests.rb
@@ -0,0 +1,14 @@
+Shindo.tests('Fog::Compute[:libvirt] | interfaces collection', ['libvirt']) do
+
+  interfaces = Fog::Compute[:libvirt].interfaces
+
+  tests('The interfaces collection') do
+    test('should not be empty') { not interfaces.empty? }
+    test('should be a kind of Fog::Compute::Libvirt::Interfaces') { interfaces.kind_of? Fog::Compute::Libvirt::Interfaces }
+    tests('should be able to reload itself').succeeds { interfaces.reload }
+    tests('should be able to get a model') do
+      tests('by instance name').succeeds { interfaces.get interfaces.first.name }
+    end
+  end
+
+end
diff --git a/tests/libvirt/models/compute/network_tests.rb b/tests/libvirt/models/compute/network_tests.rb
new file mode 100644
index 0000000..155a598
--- /dev/null
+++ b/tests/libvirt/models/compute/network_tests.rb
@@ -0,0 +1,27 @@
+Shindo.tests('Fog::Compute[:libvirt] | network model', ['libvirt']) do
+
+  networks = Fog::Compute[:libvirt].networks
+  network = networks.last
+
+  tests('The network model should') do
+    tests('have the action') do
+      test('reload') { network.respond_to? 'reload' }
+    end
+    tests('have attributes') do
+      model_attribute_hash = network.attributes
+      attributes = [ :name, :uuid, :bridge_name]
+      tests("The network model should respond to") do
+        attributes.each do |attribute|
+          test("#{attribute}") { network.respond_to? attribute }
+        end
+      end
+      tests("The attributes hash should have key") do
+        attributes.each do |attribute|
+          test("#{attribute}") { model_attribute_hash.key? attribute }
+        end
+      end
+    end
+    test('be a kind of Fog::Compute::Libvirt::Network') { network.kind_of? Fog::Compute::Libvirt::Network }
+  end
+
+end
diff --git a/tests/libvirt/models/compute/networks_tests.rb b/tests/libvirt/models/compute/networks_tests.rb
new file mode 100644
index 0000000..6edeb81
--- /dev/null
+++ b/tests/libvirt/models/compute/networks_tests.rb
@@ -0,0 +1,13 @@
+Shindo.tests('Fog::Compute[:libvirt] | networks collection', ['libvirt']) do
+
+  networks = Fog::Compute[:libvirt].networks
+
+  tests('The networks collection') do
+    test('should be a kind of Fog::Compute::Libvirt::Networks') { networks.kind_of? Fog::Compute::Libvirt::Networks }
+    tests('should be able to reload itself').succeeds { networks.reload }
+    tests('should be able to get a model') do
+      tests('by instance id').succeeds { networks.get networks.first.uuid }
+    end
+  end
+
+end
diff --git a/tests/libvirt/models/compute/nic_tests.rb b/tests/libvirt/models/compute/nic_tests.rb
new file mode 100644
index 0000000..290bec2
--- /dev/null
+++ b/tests/libvirt/models/compute/nic_tests.rb
@@ -0,0 +1,31 @@
+Shindo.tests('Fog::Compute[:libvirt] | nic model', ['libvirt']) do
+
+  nic = Fog::Compute[:libvirt].servers.all.select{|v| v.name =~ /^fog/}.first.nics.first
+
+  tests('The nic model should') do
+    tests('have the action') do
+      test('reload') { nic.respond_to? 'reload' }
+    end
+    tests('have attributes') do
+      model_attribute_hash = nic.attributes
+      attributes = [ :mac,
+        :model,
+        :type,
+        :network,
+        :bridge]
+      tests("The nic model should respond to") do
+        attributes.each do |attribute|
+          test("#{attribute}") { nic.respond_to? attribute }
+        end
+      end
+      tests("The attributes hash should have key") do
+        attributes.delete(:bridge)
+        attributes.each do |attribute|
+          test("#{attribute}") { model_attribute_hash.key? attribute }
+        end
+      end
+    end
+    test('be a kind of Fog::Compute::Libvirt::Nic') { nic.kind_of? Fog::Compute::Libvirt::Nic }
+  end
+
+end
diff --git a/tests/libvirt/models/compute/nics_tests.rb b/tests/libvirt/models/compute/nics_tests.rb
new file mode 100644
index 0000000..186dfcd
--- /dev/null
+++ b/tests/libvirt/models/compute/nics_tests.rb
@@ -0,0 +1,10 @@
+Shindo.tests('Fog::Compute[:libvirt] | nics collection', ['libvirt']) do
+
+  nics = Fog::Compute[:libvirt].servers.first.nics
+
+  tests('The nics collection') do
+    test('should not be empty') { not nics.empty? }
+    test('should be a kind of Array') { nics.kind_of? Array }
+  end
+
+end
diff --git a/tests/libvirt/models/compute/pool_tests.rb b/tests/libvirt/models/compute/pool_tests.rb
new file mode 100644
index 0000000..03946ab
--- /dev/null
+++ b/tests/libvirt/models/compute/pool_tests.rb
@@ -0,0 +1,27 @@
+Shindo.tests('Fog::Compute[:libvirt] | interface model', ['libvirt']) do
+
+  pools = Fog::Compute[:libvirt].pools
+  pool = pools.last
+
+  tests('The interface model should') do
+    tests('have the action') do
+      test('reload') { pool.respond_to? 'reload' }
+    end
+    tests('have attributes') do
+      model_attribute_hash = pool.attributes
+      attributes = [ :uuid, :name, :persistent, :active, :autostart, :allocation, :capacity, :num_of_volumes, :state]
+      tests("The interface model should respond to") do
+        attributes.each do |attribute|
+          test("#{attribute}") { pool.respond_to? attribute }
+        end
+      end
+      tests("The attributes hash should have key") do
+        attributes.each do |attribute|
+          test("#{attribute}") { model_attribute_hash.key? attribute }
+        end
+      end
+    end
+    test('be a kind of Fog::Compute::Libvirt::Pool') { pool.kind_of? Fog::Compute::Libvirt::Pool }
+  end
+
+end
diff --git a/tests/libvirt/models/compute/pools_tests.rb b/tests/libvirt/models/compute/pools_tests.rb
new file mode 100644
index 0000000..6fe3fb8
--- /dev/null
+++ b/tests/libvirt/models/compute/pools_tests.rb
@@ -0,0 +1,13 @@
+Shindo.tests('Fog::Compute[:libvirt] | pools request', ['libvirt']) do
+
+  pools = Fog::Compute[:libvirt].pools
+
+  tests('The pools collection') do
+      test('should not be empty') { not pools.empty? }
+      test('should be a kind of Fog::Compute::Libvirt::Pools') { pools.kind_of? Fog::Compute::Libvirt::Pools }
+      tests('should be able to reload itself').succeeds { pools.reload }
+      tests('should be able to get a model') do
+        tests('by instance id').succeeds { pools.get pools.first.uuid }
+      end
+    end
+end
diff --git a/tests/libvirt/models/compute/server_tests.rb b/tests/libvirt/models/compute/server_tests.rb
new file mode 100644
index 0000000..ac5d035
--- /dev/null
+++ b/tests/libvirt/models/compute/server_tests.rb
@@ -0,0 +1,57 @@
+Shindo.tests('Fog::Compute[:libvirt] | server model', ['libvirt']) do
+
+  servers = Fog::Compute[:libvirt].servers
+  server = servers.all.select{|v| v.name =~ /^fog/}.last
+
+  tests('The server model should') do
+    tests('have the action') do
+      test('reload') { server.respond_to? 'reload' }
+      %w{ start stop destroy reboot suspend }.each do |action|
+        test(action) { server.respond_to? action }
+      end
+      %w{ start reboot suspend stop destroy}.each do |action|
+        test("#{action} returns successfully") {
+          begin
+            server.send(action.to_sym)
+          rescue Libvirt::Error
+            #libvirt error is acceptable for the above actions.
+            true
+          end
+        }
+      end
+    end
+    tests('have attributes') do
+      model_attribute_hash = server.attributes
+      attributes = [ :id,
+        :cpus,
+        :cputime,
+        :os_type,
+        :memory_size,
+        :max_memory_size,
+        :name,
+        :arch,
+        :persistent,
+        :domain_type,
+        :uuid,
+        :autostart,
+        :display,
+        :nics,
+        :volumes,
+        :active,
+        :boot_order,
+        :state]
+      tests("The server model should respond to") do
+        attributes.each do |attribute|
+          test("#{attribute}") { server.respond_to? attribute }
+        end
+      end
+      tests("The attributes hash should have key") do
+        attributes.delete(:volumes)
+        attributes.each do |attribute|
+          test("#{attribute}") { model_attribute_hash.key? attribute }
+        end
+      end
+    end
+    test('be a kind of Fog::Compute::Libvirt::Server') { server.kind_of? Fog::Compute::Libvirt::Server }
+  end
+end
diff --git a/tests/libvirt/models/compute/servers_tests.rb b/tests/libvirt/models/compute/servers_tests.rb
new file mode 100644
index 0000000..905aa75
--- /dev/null
+++ b/tests/libvirt/models/compute/servers_tests.rb
@@ -0,0 +1,14 @@
+Shindo.tests('Fog::Compute[:libvirt] | servers collection', ['libvirt']) do
+
+  servers = Fog::Compute[:libvirt].servers
+
+  tests('The servers collection') do
+    test('should not be empty') { not servers.empty? }
+    test('should be a kind of Fog::Compute::Libvirt::Servers') { servers.kind_of? Fog::Compute::Libvirt::Servers }
+    tests('should be able to reload itself').succeeds { servers.reload }
+    tests('should be able to get a model') do
+      tests('by instance uuid').succeeds { servers.get servers.first.id }
+    end
+  end
+
+end
diff --git a/tests/libvirt/models/compute/volume_tests.rb b/tests/libvirt/models/compute/volume_tests.rb
new file mode 100644
index 0000000..735a5f3
--- /dev/null
+++ b/tests/libvirt/models/compute/volume_tests.rb
@@ -0,0 +1,38 @@
+Shindo.tests('Fog::Compute[:libvirt] | volume model', ['libvirt']) do
+
+  volume = Fog::Compute[:libvirt].servers.all.select{|v| v.name !~ /^fog/}.first.volumes.first
+
+  tests('The volume model should') do
+    tests('have attributes') do
+      model_attribute_hash = volume.attributes
+      attributes = [ :id,
+        :pool_name,
+        :key,
+        :name,
+        :path,
+        :capacity,
+        :allocation,
+        :format_type]
+      tests("The volume model should respond to") do
+        attributes.each do |attribute|
+          test("#{attribute}") { volume.respond_to? attribute }
+        end
+      end
+      tests("The attributes hash should have key") do
+        attributes.each do |attribute|
+          test("#{attribute}") { model_attribute_hash.key? attribute }
+        end
+      end
+    end
+    test('be a kind of Fog::Compute::Libvirt::Volume') { volume.kind_of? Fog::Compute::Libvirt::Volume }
+  end
+
+  tests('Cloning volumes should') do
+    test('respond to clone_volume') { volume.respond_to? :clone_volume }
+    new_vol = volume.clone_volume('new_vol')
+    # We'd like to test that the :name attr has changed, but it seems that's
+    # not possible, so we can at least check the new_vol xml exists properly
+    test('succeed') { volume.xml == new_vol.xml }
+  end
+
+end
diff --git a/tests/libvirt/models/compute/volumes_tests.rb b/tests/libvirt/models/compute/volumes_tests.rb
new file mode 100644
index 0000000..6f29786
--- /dev/null
+++ b/tests/libvirt/models/compute/volumes_tests.rb
@@ -0,0 +1,14 @@
+Shindo.tests('Fog::Compute[:libvirt] | volumes collection', ['libvirt']) do
+
+  volumes = Fog::Compute[:libvirt].volumes
+
+  tests('The volumes collection') do
+    test('should not be empty') { not volumes.empty? }
+    test('should be a kind of Fog::Compute::Libvirt::Volumes') { volumes.kind_of? Fog::Compute::Libvirt::Volumes }
+    tests('should be able to reload itself').succeeds { volumes.reload }
+    tests('should be able to get a model') do
+      tests('by instance uuid').succeeds { volumes.get volumes.first.id }
+    end
+  end
+
+end
diff --git a/tests/libvirt/requests/compute/create_domain_tests.rb b/tests/libvirt/requests/compute/create_domain_tests.rb
new file mode 100644
index 0000000..0f1cfe9
--- /dev/null
+++ b/tests/libvirt/requests/compute/create_domain_tests.rb
@@ -0,0 +1,21 @@
+Shindo.tests("Fog::Compute[:libvirt] | create_domain request", 'libvirt') do
+
+  compute = Fog::Compute[:libvirt]
+  xml = compute.servers.new( :nics => [{:bridge => "br180"}]).to_xml
+
+  tests("Create Domain") do
+    response = compute.create_domain(xml)
+    test("should be a kind of Libvirt::Domain") { response.kind_of?  Libvirt::Domain}
+  end
+
+  tests("Fail Creating Domain") do
+    begin
+      response = compute.create_domain(xml)
+      test("should be a kind of Libvirt::Domain") { response.kind_of?  Libvirt::Domain} #mock never raise exceptions
+    rescue => e
+      #should raise vm name already exist exception.
+      test("error should be a kind of Libvirt::Error") { e.kind_of?  Libvirt::Error}
+    end
+  end
+
+end
diff --git a/tests/libvirt/requests/compute/define_domain_tests.rb b/tests/libvirt/requests/compute/define_domain_tests.rb
new file mode 100644
index 0000000..f581642
--- /dev/null
+++ b/tests/libvirt/requests/compute/define_domain_tests.rb
@@ -0,0 +1,11 @@
+Shindo.tests("Fog::Compute[:libvirt] | define_domain request", 'libvirt') do
+
+  compute = Fog::Compute[:libvirt]
+  xml = compute.servers.new().to_xml
+
+  tests("Define Domain") do
+    response = compute.define_domain(xml)
+    test("should be a kind of Libvirt::Domain") { response.kind_of?  Libvirt::Domain}
+  end
+
+end
diff --git a/tests/libvirt/requests/compute/update_display.rb b/tests/libvirt/requests/compute/update_display.rb
new file mode 100644
index 0000000..1ca8e7f
--- /dev/null
+++ b/tests/libvirt/requests/compute/update_display.rb
@@ -0,0 +1,13 @@
+Shindo.tests('Fog::Compute[:libvirt] | update_display request', ['libvirt']) do
+
+  compute = Fog::Compute[:libvirt]
+
+  reconfig_target = 'f74d728a-5b62-7e2f-1f84-239aead298ca'
+  display_spec = {:password => 'ssaaa'}
+
+  tests('The response should') do
+    response = compute.update_display(:uuid => reconfig_target).merge(display_spec)
+    test('should be true').succeeds { response }
+  end
+
+end

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/ruby-fog-libvirt.git



More information about the Pkg-ruby-extras-commits mailing list