virtuoso 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/.yardopts +1 -0
- data/Gemfile +20 -0
- data/Gemfile.lock +37 -0
- data/README.md +68 -0
- data/Rakefile +20 -0
- data/lib/virtuoso.rb +22 -0
- data/lib/virtuoso/api/hypervisor.rb +30 -0
- data/lib/virtuoso/api/vm.rb +90 -0
- data/lib/virtuoso/error.rb +9 -0
- data/lib/virtuoso/version.rb +3 -0
- data/lib/virtuoso/virtualbox.rb +6 -0
- data/lib/virtuoso/virtualbox/hypervisor.rb +21 -0
- data/lib/virtuoso/virtualbox/vm.rb +85 -0
- data/test/test_helper.rb +30 -0
- data/test/virtuoso/api/vm_test.rb +70 -0
- data/test/virtuoso/virtuoso_test.rb +18 -0
- data/virtuoso.gemspec +26 -0
- metadata +129 -0
data/.gitignore
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
-m markdown
|
data/Gemfile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in virtuoso.gemspec
|
4
|
+
gem "virtuoso", :path => "."
|
5
|
+
|
6
|
+
# Use libvirt-rb straight from git, since Virtuoso dev requires
|
7
|
+
# the latest and greatest
|
8
|
+
gem "libvirt", :git => "git://github.com/mitchellh/libvirt-rb.git"
|
9
|
+
|
10
|
+
# Gems required for testing only.
|
11
|
+
group :development do
|
12
|
+
gem "protest", "~> 0.4.0"
|
13
|
+
gem "mocha", "~> 0.9.8"
|
14
|
+
|
15
|
+
# Not JRuby, which doesn't like bluecloth
|
16
|
+
platforms :ruby, :mri do
|
17
|
+
gem "yard", "~> 0.6.1"
|
18
|
+
gem "bluecloth", "~> 2.0.9"
|
19
|
+
end
|
20
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
GIT
|
2
|
+
remote: git://github.com/mitchellh/libvirt-rb.git
|
3
|
+
revision: d06c4aef6e52723816b76b4e46b5f8cc985d5d8a
|
4
|
+
specs:
|
5
|
+
libvirt (0.2.1.dev)
|
6
|
+
ffi (~> 0.6.3)
|
7
|
+
nokogiri (~> 1.4.3)
|
8
|
+
|
9
|
+
PATH
|
10
|
+
remote: .
|
11
|
+
specs:
|
12
|
+
virtuoso (0.0.1)
|
13
|
+
libvirt (~> 0.2)
|
14
|
+
|
15
|
+
GEM
|
16
|
+
remote: http://rubygems.org/
|
17
|
+
specs:
|
18
|
+
bluecloth (2.0.9)
|
19
|
+
ffi (0.6.3)
|
20
|
+
rake (>= 0.8.7)
|
21
|
+
mocha (0.9.10)
|
22
|
+
rake
|
23
|
+
nokogiri (1.4.4)
|
24
|
+
protest (0.4.2)
|
25
|
+
rake (0.8.7)
|
26
|
+
yard (0.6.3)
|
27
|
+
|
28
|
+
PLATFORMS
|
29
|
+
ruby
|
30
|
+
|
31
|
+
DEPENDENCIES
|
32
|
+
bluecloth (~> 2.0.9)
|
33
|
+
libvirt!
|
34
|
+
mocha (~> 0.9.8)
|
35
|
+
protest (~> 0.4.0)
|
36
|
+
virtuoso!
|
37
|
+
yard (~> 0.6.1)
|
data/README.md
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# Virtuoso
|
2
|
+
|
3
|
+
Virtuoso is a Ruby library that provides dead simple virtual machine
|
4
|
+
management across many hypervisors, using the powerful [libvirt](http://libvirt.org)
|
5
|
+
library underneath. Libvirt is an extremely powerful library, and the
|
6
|
+
focus of Virtuoso is to provide an extremely simple, common API for
|
7
|
+
managing virtual machines at the cost of sacrificing some of libvirt's
|
8
|
+
power.
|
9
|
+
|
10
|
+
Currently supported hypervisors:
|
11
|
+
|
12
|
+
- VirtualBox
|
13
|
+
|
14
|
+
Since Virtuoso is built on top of [libvirt](http://libvirt.org), it isn't
|
15
|
+
too difficult to add support for another hypervisor. The reason a libvirt-supported
|
16
|
+
hypervisor may not be supportd by Virtuoso at this time is most likely
|
17
|
+
because I don't have experience using that hypervisor. Open an issue if
|
18
|
+
you'd like to see support for another hypervisor.
|
19
|
+
|
20
|
+
## Installation
|
21
|
+
|
22
|
+
The library is packaged as a gem:
|
23
|
+
|
24
|
+
gem install virtuoso
|
25
|
+
|
26
|
+
Additionally, you may need to install libvirt, the C-library used to
|
27
|
+
interface with the various hypervisors. On OS X the recommended way is
|
28
|
+
using [homebrew](http://github.com/mxcl/homebrew):
|
29
|
+
|
30
|
+
brew install libvirt
|
31
|
+
|
32
|
+
If you're on linux, your package manager should contain a compatible
|
33
|
+
version of libvirt.
|
34
|
+
|
35
|
+
## Project Status and Warning
|
36
|
+
|
37
|
+
**Warning:** This project is extremely _alpha_. The API will most definitely
|
38
|
+
change multiple times in the near future and the project itself will be
|
39
|
+
a fast moving target. This status will be updated in time as the project
|
40
|
+
matures.
|
41
|
+
|
42
|
+
## Usage
|
43
|
+
|
44
|
+
Below is an example of starting a VM with VirtualBox. All drivers (for
|
45
|
+
different hypervisors) are required to conform to the same API, so the
|
46
|
+
usage is the same for all other hypervisors.
|
47
|
+
|
48
|
+
require 'virtuoso'
|
49
|
+
|
50
|
+
# Connect to a libvirt instance. Virtuoso instantiates the proper
|
51
|
+
# hypervisor.
|
52
|
+
hypervisor = Virtuoso.connect("vbox:///session")
|
53
|
+
|
54
|
+
# Create a new VM within the hypervisor and start it
|
55
|
+
vm = hypervisor.new_vm
|
56
|
+
vm.name = "My Virtuoso VM"
|
57
|
+
vm.disk_image = "/home/mitchellh/lucid.vmdk"
|
58
|
+
vm.save
|
59
|
+
vm.start
|
60
|
+
|
61
|
+
# Watch it booting...
|
62
|
+
sleep 5
|
63
|
+
|
64
|
+
# Stop and destroy it
|
65
|
+
vm.stop
|
66
|
+
sleep 3
|
67
|
+
vm.destroy
|
68
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
require 'bundler/setup'
|
4
|
+
Bundler::GemHelper.install_tasks
|
5
|
+
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc "Run the test suite."
|
9
|
+
task :test do
|
10
|
+
$:.unshift File.expand_path("../test", __FILE__)
|
11
|
+
files = ENV["TEST"] ? [ENV["TEST"]] : Dir["test/**/*_test.rb"]
|
12
|
+
files.each { |f| load f }
|
13
|
+
end
|
14
|
+
|
15
|
+
begin
|
16
|
+
# Documentation task
|
17
|
+
require 'yard'
|
18
|
+
YARD::Rake::YardocTask.new
|
19
|
+
rescue LoadError
|
20
|
+
end
|
data/lib/virtuoso.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'libvirt'
|
2
|
+
|
3
|
+
module Virtuoso
|
4
|
+
autoload :Error, "virtuoso/error"
|
5
|
+
autoload :VirtualBox, "virtuoso/virtualbox"
|
6
|
+
|
7
|
+
# Holds all the "abstract" classes for specifying and documenting
|
8
|
+
# the Virtuoso API.
|
9
|
+
module API
|
10
|
+
autoload :Hypervisor, "virtuoso/api/hypervisor"
|
11
|
+
autoload :VM, "virtuoso/api/vm"
|
12
|
+
end
|
13
|
+
|
14
|
+
# Connects to a hypervisor given by the URL to a libvirt instance,
|
15
|
+
# and returns the proper hypervisor class based on the connection.
|
16
|
+
def self.connect(url=nil)
|
17
|
+
mapping = { "VBOX" => :VirtualBox }
|
18
|
+
conn = Libvirt.connect(url)
|
19
|
+
raise Error::UnsupportedHypervisorError, "Unsupported hypervisor: #{conn.hypervisor}" if !mapping[conn.hypervisor]
|
20
|
+
const_get(mapping[conn.hypervisor]).const_get(:Hypervisor).new(conn)
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Virtuoso
|
2
|
+
module API
|
3
|
+
# Base class specifying the API for all hypervisors. Every feature in
|
4
|
+
# this base class must be overloaded by any hypervisors.
|
5
|
+
class Hypervisor
|
6
|
+
# The libvirt connection instance.
|
7
|
+
attr_reader :connection
|
8
|
+
|
9
|
+
# Initializes a hypervisor with the given libvirt connection. The
|
10
|
+
# connection should be established through {Virtuoso.connect}, which
|
11
|
+
# also chooses the correct hypervisor.
|
12
|
+
def initialize(connection)
|
13
|
+
@connection = connection
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns a new {VM} instance that can be used to create a new virtual
|
17
|
+
# machine.
|
18
|
+
#
|
19
|
+
# @return [VM]
|
20
|
+
def new_vm; end
|
21
|
+
|
22
|
+
# Searches for a VM with the given ID and returns it if it finds it,
|
23
|
+
# and otherwise returns nil. The exact semantics of the find are up to
|
24
|
+
# the hypervisor but typically it searches by both name and UUID.
|
25
|
+
#
|
26
|
+
# @return [VM]
|
27
|
+
def find(id); end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Virtuoso
|
2
|
+
module API
|
3
|
+
# Base class specifying the API that all VMs within a hypervisor must
|
4
|
+
# conform to.
|
5
|
+
class VM
|
6
|
+
# The libvirt connection instance.
|
7
|
+
attr_reader :connection
|
8
|
+
|
9
|
+
# The libvirt domain object.
|
10
|
+
attr_reader :domain
|
11
|
+
|
12
|
+
# The name of the VM.
|
13
|
+
attr_accessor :name
|
14
|
+
|
15
|
+
# The memory for the VM.
|
16
|
+
attr_accessor :memory
|
17
|
+
|
18
|
+
# The disk image to use as the main boot drive.
|
19
|
+
attr_accessor :disk_image
|
20
|
+
|
21
|
+
# Initializes a VM with the given libvirt connection.
|
22
|
+
def initialize(connection, domain=nil)
|
23
|
+
@connection = connection
|
24
|
+
@domain = domain
|
25
|
+
|
26
|
+
# Set reasonable defaults for fields if we can
|
27
|
+
@name = "My Virtuoso VM"
|
28
|
+
@memory = 524288 # 512 MB
|
29
|
+
|
30
|
+
# Load in the proper data
|
31
|
+
reload if domain
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns the current state of the VM. This is expected to always
|
35
|
+
# return the current, up-to-date state (therefore it is _not_ cached
|
36
|
+
# and updated only on {#reload}). The state is meant to be returned
|
37
|
+
# as a symbol.
|
38
|
+
#
|
39
|
+
# @return [Symbol]
|
40
|
+
def state; end
|
41
|
+
|
42
|
+
# Saves the VM. If the VM is new, this is expected to create it
|
43
|
+
# initially, otherwise this is expected to update the existing
|
44
|
+
# VM.
|
45
|
+
def save; end
|
46
|
+
|
47
|
+
# Destroys the VM, deleting any information about it. This will not
|
48
|
+
# destroy any disk images, nor will it stop the VM if it is running.
|
49
|
+
def destroy; end
|
50
|
+
|
51
|
+
# Starts the VM.
|
52
|
+
def start; end
|
53
|
+
|
54
|
+
# Stops the VM.
|
55
|
+
def stop; end
|
56
|
+
|
57
|
+
# Reloads information from about a VM which exists. Since Virtuoso
|
58
|
+
# can't enforce any sort of VM locking, it is possible a VM changes
|
59
|
+
# in the background by some other process while it is being modified.
|
60
|
+
# In that case, when you attempt to save, your changes will either
|
61
|
+
# overwrite the previous settings, or fail altogether (if someone else
|
62
|
+
# destroyed the VM, for example). It is up to the developer to be
|
63
|
+
# knowledgeable about his or her environment and account for this
|
64
|
+
# accordingly. If you know that a VM changed, or you're just being
|
65
|
+
# careful, {#reload} may be called to reload the data associated
|
66
|
+
# with this VM and bring it up to date.
|
67
|
+
def reload; end
|
68
|
+
|
69
|
+
protected
|
70
|
+
|
71
|
+
# A helper method for subclasses to mark methods which require an
|
72
|
+
# existing VM to function (these are methods like `start` and `stop`).
|
73
|
+
# This method will raise an {Error::NewVMError} if an existing VM
|
74
|
+
# is not set.
|
75
|
+
def requires_existing_vm
|
76
|
+
raise Error::NewVMError if !domain
|
77
|
+
end
|
78
|
+
|
79
|
+
# A helper method for subclasses to set a domain object to represent
|
80
|
+
# this VM. This properly sets up the object and reloads it for the
|
81
|
+
# most up to date information.
|
82
|
+
def set_domain(domain)
|
83
|
+
@domain = domain
|
84
|
+
@domain_spec = nil
|
85
|
+
|
86
|
+
reload if domain
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Virtuoso
|
2
|
+
# Any exceptions which are thrown by Virtuoso (not lower-level libraries)
|
3
|
+
# exist in this module.
|
4
|
+
module Error
|
5
|
+
class VirtuosoError < StandardError; end
|
6
|
+
class UnsupportedHypervisorError < StandardError; end
|
7
|
+
class NewVMError < VirtuosoError; end
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Virtuoso
|
2
|
+
module VirtualBox
|
3
|
+
# VirtualBox driver, allowing the control and management of
|
4
|
+
# VirtualBox virtual machines.
|
5
|
+
class Hypervisor < API::Hypervisor
|
6
|
+
def new_vm
|
7
|
+
VM.new(connection)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Searches for a VM by name or UUID.
|
11
|
+
#
|
12
|
+
# @param [String] id Name or UUID
|
13
|
+
# @return [VM]
|
14
|
+
def find(id)
|
15
|
+
result = connection.domains.find(id)
|
16
|
+
return nil if !result
|
17
|
+
VM.new(connection, result)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Virtuoso
|
2
|
+
module VirtualBox
|
3
|
+
# VirtualBox VM.
|
4
|
+
class VM < API::VM
|
5
|
+
def state
|
6
|
+
domain ? domain.state : :new
|
7
|
+
end
|
8
|
+
|
9
|
+
def save
|
10
|
+
# Setup the basic settings for the VM
|
11
|
+
d = Libvirt::Spec::Domain.new
|
12
|
+
d.hypervisor = :vbox
|
13
|
+
d.name = name
|
14
|
+
d.memory = memory
|
15
|
+
d.vcpu = 1
|
16
|
+
d.features = [:acpi, :pae]
|
17
|
+
d.clock.offset = :localtime
|
18
|
+
d.os.type = :hvm
|
19
|
+
d.os.arch = :i386
|
20
|
+
d.os.boot = [:cdrom, :hd]
|
21
|
+
|
22
|
+
# Attach the main hard disk
|
23
|
+
disk = Libvirt::Spec::Device.get(:disk).new
|
24
|
+
disk.type = :file
|
25
|
+
disk.device = :disk
|
26
|
+
disk.source = disk_image
|
27
|
+
disk.target_dev = :hda
|
28
|
+
disk.target_bus = :ide
|
29
|
+
d.devices << disk
|
30
|
+
|
31
|
+
# Attach a basic NAT network interface
|
32
|
+
nat = Libvirt::Spec::Device.get(:interface).new
|
33
|
+
nat.type = :user
|
34
|
+
nat.mac_address = "08:00:27:8f:7a:9f"
|
35
|
+
nat.model_type = "82540EM"
|
36
|
+
d.devices << nat
|
37
|
+
|
38
|
+
# Attach video information
|
39
|
+
video = Libvirt::Spec::Device.get(:video).new
|
40
|
+
model = Libvirt::Spec::Device::VideoModel.new
|
41
|
+
model.type = :vbox
|
42
|
+
model.vram = 12
|
43
|
+
model.heads = 1
|
44
|
+
model.accel3d = false
|
45
|
+
model.accel2d = false
|
46
|
+
video.models << model
|
47
|
+
d.devices << video
|
48
|
+
|
49
|
+
# At this point, assuming the virtuoso settings are correct, we
|
50
|
+
# should have a bootable VM spec, so define it and reload the VM
|
51
|
+
# information.
|
52
|
+
@domain = connection.domains.define(d)
|
53
|
+
reload
|
54
|
+
end
|
55
|
+
|
56
|
+
def destroy
|
57
|
+
requires_existing_vm
|
58
|
+
@domain.undefine
|
59
|
+
@domain = nil
|
60
|
+
end
|
61
|
+
|
62
|
+
def start
|
63
|
+
requires_existing_vm
|
64
|
+
domain.start
|
65
|
+
end
|
66
|
+
|
67
|
+
def stop
|
68
|
+
requires_existing_vm
|
69
|
+
domain.stop
|
70
|
+
end
|
71
|
+
|
72
|
+
def reload
|
73
|
+
# Load the main disk image path. We assume this is the first "disk"
|
74
|
+
# device, though this assumption is probably pretty weak.
|
75
|
+
spec = domain.spec
|
76
|
+
disk = spec.devices.find { |d| d.is_a?(Libvirt::Spec::Device::Disk) }
|
77
|
+
self.disk_image = disk.source
|
78
|
+
|
79
|
+
# Load the basic attributes
|
80
|
+
self.name = spec.name
|
81
|
+
self.memory = spec.memory
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require "test/unit/assertions"
|
2
|
+
require "protest"
|
3
|
+
require "mocha"
|
4
|
+
require "virtuoso"
|
5
|
+
|
6
|
+
class Protest::TestCase
|
7
|
+
include Test::Unit::Assertions
|
8
|
+
include Mocha::API
|
9
|
+
|
10
|
+
# Get Mocha integrated properly into the tests
|
11
|
+
alias :original_run :run
|
12
|
+
def run(report)
|
13
|
+
original_run(report)
|
14
|
+
mocha_verify
|
15
|
+
ensure
|
16
|
+
mocha_teardown
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns a connection to a libvirt test hypervisor.
|
20
|
+
def test_connection
|
21
|
+
Libvirt.connect("test:///default")
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns a domain object from the libvirt test hypervisor.
|
25
|
+
def test_domain
|
26
|
+
test_connection.domains.first
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
Protest.report_with(:progress)
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
Protest.describe("API::VM") do
|
4
|
+
setup do
|
5
|
+
@klass = Virtuoso::API::VM
|
6
|
+
end
|
7
|
+
|
8
|
+
context "requiring an existing VM" do
|
9
|
+
setup do
|
10
|
+
@impl = Class.new(@klass) do
|
11
|
+
def save
|
12
|
+
@domain = true
|
13
|
+
end
|
14
|
+
|
15
|
+
def start
|
16
|
+
requires_existing_vm
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
@instance = @impl.new(test_connection)
|
21
|
+
end
|
22
|
+
|
23
|
+
should "raise an exception if an existing VM is not set" do
|
24
|
+
assert_raises(Virtuoso::Error::NewVMError) { @instance.start }
|
25
|
+
end
|
26
|
+
|
27
|
+
should "not raise an exception if an existing VM is set" do
|
28
|
+
assert_nothing_raised {
|
29
|
+
@instance.save
|
30
|
+
@instance.start
|
31
|
+
}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "initializing a VM" do
|
36
|
+
context "reloading" do
|
37
|
+
setup do
|
38
|
+
@impl = Class.new(@klass) do
|
39
|
+
def reload
|
40
|
+
throw :reloaded, :reload
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
should "reload if a domain is given" do
|
46
|
+
result = catch :reloaded do
|
47
|
+
@impl.new(test_connection, test_domain)
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
|
51
|
+
assert_equal :reload, result
|
52
|
+
end
|
53
|
+
|
54
|
+
should "not load if a domain is not given" do
|
55
|
+
result = catch :reloaded do
|
56
|
+
@impl.new(test_connection)
|
57
|
+
nil
|
58
|
+
end
|
59
|
+
|
60
|
+
assert !result
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "with a VM object" do
|
66
|
+
setup do
|
67
|
+
@instance = @klass.new(test_connection)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
Protest.describe("Virtuoso") do
|
4
|
+
setup do
|
5
|
+
@klass = Virtuoso
|
6
|
+
end
|
7
|
+
|
8
|
+
context "connecting" do
|
9
|
+
should "raise an exception if an unsupported hypervisor is connected to" do
|
10
|
+
assert_raises(Virtuoso::Error::UnsupportedHypervisorError) {
|
11
|
+
@klass.connect("test:///default")
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
# TODO: To test other connections, hypervisor must be present... so we
|
16
|
+
# can't guarantee and test that yet.
|
17
|
+
end
|
18
|
+
end
|
data/virtuoso.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "virtuoso/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "virtuoso"
|
7
|
+
s.version = Virtuoso::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Mitchell Hashimoto"]
|
10
|
+
s.email = ["mitchell.hashimoto@gmail.com"]
|
11
|
+
s.homepage = "http://rubygems.org/gems/virtuoso"
|
12
|
+
s.summary = "Dead simple virtual machine management for many hypervisors."
|
13
|
+
s.description = "Dead simple virtual machine management for many hypervisors."
|
14
|
+
|
15
|
+
s.rubyforge_project = "virtuoso"
|
16
|
+
|
17
|
+
s.add_dependency "libvirt", "~> 0.2"
|
18
|
+
|
19
|
+
s.add_development_dependency "protest", "~> 0.4.0"
|
20
|
+
s.add_development_dependency "mocha", "~> 0.9.8"
|
21
|
+
|
22
|
+
s.files = `git ls-files`.split("\n")
|
23
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
24
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
25
|
+
s.require_paths = ["lib"]
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: virtuoso
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Mitchell Hashimoto
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-12-07 00:00:00 -08:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: libvirt
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ~>
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
- 2
|
30
|
+
version: "0.2"
|
31
|
+
type: :runtime
|
32
|
+
prerelease: false
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: protest
|
36
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
38
|
+
requirements:
|
39
|
+
- - ~>
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
- 4
|
44
|
+
- 0
|
45
|
+
version: 0.4.0
|
46
|
+
type: :development
|
47
|
+
prerelease: false
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: mocha
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ~>
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
segments:
|
57
|
+
- 0
|
58
|
+
- 9
|
59
|
+
- 8
|
60
|
+
version: 0.9.8
|
61
|
+
type: :development
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: *id003
|
64
|
+
description: Dead simple virtual machine management for many hypervisors.
|
65
|
+
email:
|
66
|
+
- mitchell.hashimoto@gmail.com
|
67
|
+
executables: []
|
68
|
+
|
69
|
+
extensions: []
|
70
|
+
|
71
|
+
extra_rdoc_files: []
|
72
|
+
|
73
|
+
files:
|
74
|
+
- .gitignore
|
75
|
+
- .yardopts
|
76
|
+
- Gemfile
|
77
|
+
- Gemfile.lock
|
78
|
+
- README.md
|
79
|
+
- Rakefile
|
80
|
+
- lib/virtuoso.rb
|
81
|
+
- lib/virtuoso/api/hypervisor.rb
|
82
|
+
- lib/virtuoso/api/vm.rb
|
83
|
+
- lib/virtuoso/error.rb
|
84
|
+
- lib/virtuoso/version.rb
|
85
|
+
- lib/virtuoso/virtualbox.rb
|
86
|
+
- lib/virtuoso/virtualbox/hypervisor.rb
|
87
|
+
- lib/virtuoso/virtualbox/vm.rb
|
88
|
+
- test/test_helper.rb
|
89
|
+
- test/virtuoso/api/vm_test.rb
|
90
|
+
- test/virtuoso/virtuoso_test.rb
|
91
|
+
- virtuoso.gemspec
|
92
|
+
has_rdoc: true
|
93
|
+
homepage: http://rubygems.org/gems/virtuoso
|
94
|
+
licenses: []
|
95
|
+
|
96
|
+
post_install_message:
|
97
|
+
rdoc_options: []
|
98
|
+
|
99
|
+
require_paths:
|
100
|
+
- lib
|
101
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
102
|
+
none: false
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
hash: -4389485739309843364
|
107
|
+
segments:
|
108
|
+
- 0
|
109
|
+
version: "0"
|
110
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
none: false
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
hash: -4389485739309843364
|
116
|
+
segments:
|
117
|
+
- 0
|
118
|
+
version: "0"
|
119
|
+
requirements: []
|
120
|
+
|
121
|
+
rubyforge_project: virtuoso
|
122
|
+
rubygems_version: 1.3.7
|
123
|
+
signing_key:
|
124
|
+
specification_version: 3
|
125
|
+
summary: Dead simple virtual machine management for many hypervisors.
|
126
|
+
test_files:
|
127
|
+
- test/test_helper.rb
|
128
|
+
- test/virtuoso/api/vm_test.rb
|
129
|
+
- test/virtuoso/virtuoso_test.rb
|