rbovirt 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rbovirt might be problematic. Click here for more details.
- data/.document +5 -0
- data/Gemfile +15 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/lib/ovirt/base_object.rb +12 -0
- data/lib/ovirt/cluster.rb +22 -0
- data/lib/ovirt/datacenter.rb +20 -0
- data/lib/ovirt/host.rb +19 -0
- data/lib/ovirt/storage_domain.rb +21 -0
- data/lib/ovirt/template.rb +30 -0
- data/lib/ovirt/vm.rb +109 -0
- data/lib/rbovirt.rb +248 -0
- data/rbovirt.gemspec +72 -0
- data/test/helper.rb +18 -0
- data/test/test_rbovirt.rb +112 -0
- metadata +171 -0
data/.document
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
gem "nokogiri"
|
6
|
+
gem "rest-client"
|
7
|
+
|
8
|
+
# Add dependencies to develop your gem here.
|
9
|
+
# Include everything needed to run rake, tests, features, etc.
|
10
|
+
group :development do
|
11
|
+
gem "shoulda", ">= 0"
|
12
|
+
gem "bundler", "~> 1.0.0"
|
13
|
+
gem "jeweler", "~> 1.6.4"
|
14
|
+
gem "rcov", ">= 0"
|
15
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Amos Benari
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
= rbovirt
|
2
|
+
|
3
|
+
A Ruby client for oVirt.
|
4
|
+
|
5
|
+
== Contributing to rbovirt
|
6
|
+
|
7
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
8
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
9
|
+
* Fork the project
|
10
|
+
* Start a feature/bugfix branch
|
11
|
+
* Commit and push until you are happy with your contribution
|
12
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
13
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
14
|
+
|
15
|
+
== Copyright
|
16
|
+
|
17
|
+
Copyright (c) 2012 Amos Benari. See LICENSE.txt for
|
18
|
+
further details.
|
19
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "rbovirt"
|
18
|
+
gem.homepage = "http://github.com/abenari/rbovirt"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{A Ruby client for oVirt REST API}
|
21
|
+
gem.description = %Q{A Ruby client for oVirt REST API}
|
22
|
+
gem.email = "abenari@redhat.com"
|
23
|
+
gem.authors = ["Amos Benari"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
27
|
+
|
28
|
+
require 'rake/testtask'
|
29
|
+
Rake::TestTask.new(:test) do |test|
|
30
|
+
test.libs << 'lib' << 'test'
|
31
|
+
test.pattern = 'test/**/test_*.rb'
|
32
|
+
test.verbose = true
|
33
|
+
end
|
34
|
+
|
35
|
+
require 'rcov/rcovtask'
|
36
|
+
Rcov::RcovTask.new do |test|
|
37
|
+
test.libs << 'test'
|
38
|
+
test.pattern = 'test/**/test_*.rb'
|
39
|
+
test.verbose = true
|
40
|
+
test.rcov_opts << '--exclude "gems/*"'
|
41
|
+
end
|
42
|
+
|
43
|
+
task :default => :test
|
44
|
+
|
45
|
+
require 'rake/rdoctask'
|
46
|
+
Rake::RDocTask.new do |rdoc|
|
47
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
48
|
+
|
49
|
+
rdoc.rdoc_dir = 'rdoc'
|
50
|
+
rdoc.title = "rbovirt #{version}"
|
51
|
+
rdoc.rdoc_files.include('README*')
|
52
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
53
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module OVIRT
|
2
|
+
class Cluster < BaseObject
|
3
|
+
attr_reader :description, :datacenter, :version
|
4
|
+
|
5
|
+
def initialize(client, xml)
|
6
|
+
super(client, xml[:id], xml[:href], (xml/'name').first.text)
|
7
|
+
parse_xml_attributes!(xml)
|
8
|
+
self
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def parse_xml_attributes!(xml)
|
14
|
+
@description = ((xml/'description').first.text rescue nil)
|
15
|
+
@version =((xml/'version').first[:major].strip rescue nil)
|
16
|
+
unless (xml/'data_center').empty?
|
17
|
+
@datacenter = Link::new(@client, (xml/'data_center').first[:id], (xml/'data_center').first[:href])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
module OVIRT
|
3
|
+
class DataCenter < BaseObject
|
4
|
+
attr_reader :description, :status
|
5
|
+
|
6
|
+
def initialize(client, xml)
|
7
|
+
super(client, xml[:id], xml[:href], (xml/'name').first.text)
|
8
|
+
parse_xml_attributes!(xml)
|
9
|
+
self
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def parse_xml_attributes!(xml)
|
15
|
+
@description = ((xml/'description').first.text rescue nil)
|
16
|
+
@status = (xml/'status').first.text
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
data/lib/ovirt/host.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module OVIRT
|
2
|
+
class Host < BaseObject
|
3
|
+
attr_reader :description, :status, :cluster
|
4
|
+
|
5
|
+
def initialize(client, xml)
|
6
|
+
super(client, xml[:id], xml[:href], (xml/'name').first.text)
|
7
|
+
parse_xml_attributes!(xml)
|
8
|
+
self
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def parse_xml_attributes!(xml)
|
14
|
+
@description = ((xml/'description').first.text rescue nil)
|
15
|
+
@status = (xml/'status').first.text
|
16
|
+
@clister = Link::new(@client, (xml/'cluster').first[:id], (xml/'cluster').first[:href])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module OVIRT
|
2
|
+
class StorageDomain < BaseObject
|
3
|
+
attr_reader :available, :used, :kind, :address, :path
|
4
|
+
|
5
|
+
def initialize(client, xml)
|
6
|
+
super(client, xml[:id], xml[:href], (xml/'name').first.text)
|
7
|
+
parse_xml_attributes!(xml)
|
8
|
+
self
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def parse_xml_attributes!(xml)
|
14
|
+
@available = (xml/'available').first.text
|
15
|
+
@used = (xml/'used').first.text
|
16
|
+
@kind = (xml/'storage/type').first.text
|
17
|
+
@address = ((xml/'storage/address').first.text rescue nil)
|
18
|
+
@path = ((xml/'storage/path').first.text rescue nil)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module OVIRT
|
2
|
+
class Template < BaseObject
|
3
|
+
attr_reader :description, :status, :cluster
|
4
|
+
|
5
|
+
def initialize(client, xml)
|
6
|
+
super(client, xml[:id], xml[:href], (xml/'name').first.text)
|
7
|
+
parse_xml_attributes!(xml)
|
8
|
+
self
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.to_xml(vm_id, opts={})
|
12
|
+
builder = Nokogiri::XML::Builder.new do
|
13
|
+
template_ {
|
14
|
+
name_ opts[:name] || "t-#{Time.now.to_i}"
|
15
|
+
description opts[:description] || ''
|
16
|
+
vm(:id => vm_id)
|
17
|
+
}
|
18
|
+
end
|
19
|
+
Nokogiri::XML(builder.to_xml).root.to_s
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def parse_xml_attributes!(xml)
|
25
|
+
@description = ((xml/'description').first.text rescue nil)
|
26
|
+
@status = (xml/'status').first.text
|
27
|
+
@cluster = Link::new(@client, (xml/'cluster').first[:id], (xml/'cluster').first[:href])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/ovirt/vm.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
module OVIRT
|
2
|
+
# NOTE: Injected file will be available in floppy drive inside
|
3
|
+
# the instance. (Be sure you 'modprobe floppy' on Linux)
|
4
|
+
FILEINJECT_PATH = "user-data.txt"
|
5
|
+
|
6
|
+
class VM < BaseObject
|
7
|
+
attr_reader :description, :status, :memory, :profile, :display, :host, :cluster, :template, :macs
|
8
|
+
attr_reader :storage, :cores, :username, :creation_time
|
9
|
+
attr_reader :ip, :vnc
|
10
|
+
|
11
|
+
def initialize(client, xml)
|
12
|
+
super(client, xml[:id], xml[:href], (xml/'name').first.text)
|
13
|
+
@username = client.credentials[:username]
|
14
|
+
parse_xml_attributes!(xml)
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.to_xml(template_name, cluster_name, opts={})
|
19
|
+
builder = Nokogiri::XML::Builder.new do
|
20
|
+
vm{
|
21
|
+
name_ opts[:name] || "i-#{Time.now.to_i}"
|
22
|
+
template_{
|
23
|
+
name_(template_name)
|
24
|
+
}
|
25
|
+
cluster_{
|
26
|
+
name_(cluster_name)
|
27
|
+
}
|
28
|
+
type_ opts[:hwp_id] || 'Server'
|
29
|
+
memory opts[:hwp_memory] ? (opts[:hwp_memory].to_i*1024*1024).to_s : (512*1024*1024).to_s
|
30
|
+
cpu {
|
31
|
+
topology( :cores => (opts[:hwp_cpu] || '1'), :sockets => '1' )
|
32
|
+
}
|
33
|
+
os{
|
34
|
+
boot(:dev=>'network')
|
35
|
+
boot(:dev=>'hd')
|
36
|
+
}
|
37
|
+
display_{
|
38
|
+
type_('vnc')
|
39
|
+
}
|
40
|
+
if(opts[:user_data] && !opts[:user_data].empty?)
|
41
|
+
custom_properties {
|
42
|
+
custom_property({
|
43
|
+
:name => "floppyinject",
|
44
|
+
:value => "#{OVIRT::FILEINJECT_PATH}:#{opts[:user_data]}",
|
45
|
+
:regexp => "^([^:]+):(.*)$"})
|
46
|
+
}
|
47
|
+
end
|
48
|
+
}
|
49
|
+
end
|
50
|
+
Nokogiri::XML(builder.to_xml).root.to_s
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.disk_xml(storage_domain_id,opts={})
|
54
|
+
builder = Nokogiri::XML::Builder.new do
|
55
|
+
disk_{
|
56
|
+
storage_domains_{
|
57
|
+
storage_domain_(:id => storage_domain_id)
|
58
|
+
}
|
59
|
+
size_(opts[:size] || 8589934592)
|
60
|
+
type_(opts[:type] || 'system')
|
61
|
+
bootable_(opts[:bootable] || 'true')
|
62
|
+
interface_(opts[:interface] || 'virtio')
|
63
|
+
format_(opts[:format] || 'cow')
|
64
|
+
sparse_(opts[:sparse] || 'true')
|
65
|
+
}
|
66
|
+
end
|
67
|
+
Nokogiri::XML(builder.to_xml).root.to_s
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.nic_xml(opts={})
|
71
|
+
builder = Nokogiri::XML::Builder.new do
|
72
|
+
nic{
|
73
|
+
name_(opts[:name] || 'eth0')
|
74
|
+
network{
|
75
|
+
name_(opts[:network] || 'ovirtmgmt')
|
76
|
+
}
|
77
|
+
}
|
78
|
+
end
|
79
|
+
Nokogiri::XML(builder.to_xml).root.to_s
|
80
|
+
end
|
81
|
+
private
|
82
|
+
|
83
|
+
def parse_xml_attributes!(xml)
|
84
|
+
@description = ((xml/'description').first.text rescue '')
|
85
|
+
@status = (xml/'status').first.text
|
86
|
+
@memory = (xml/'memory').first.text
|
87
|
+
@profile = (xml/'type').first.text
|
88
|
+
@template = Link::new(@client, (xml/'template').first[:id], (xml/'template').first[:href])
|
89
|
+
@host = Link::new(@client, (xml/'host').first[:id], (xml/'host').first[:href]) rescue nil
|
90
|
+
@cluster = Link::new(@client, (xml/'cluster').first[:id], (xml/'cluster').first[:href])
|
91
|
+
@display = {
|
92
|
+
:type => (xml/'display/type').first.text,
|
93
|
+
:address => ((xml/'display/address').first.text rescue nil),
|
94
|
+
:port => ((xml/'display/port').first.text rescue nil),
|
95
|
+
:monitors => (xml/'display/monitors').first.text
|
96
|
+
}
|
97
|
+
@cores = ((xml/'cpu/topology').first[:cores] rescue nil)
|
98
|
+
@storage = ((xml/'disks/disk/size').first.text rescue nil)
|
99
|
+
@macs = (xml/'nics/nic/mac').collect { |mac| mac[:address] }
|
100
|
+
@creation_time = (xml/'creation_time').text
|
101
|
+
@ip = ((xml/'guest_info/ip').first[:address] rescue nil)
|
102
|
+
@vnc = {
|
103
|
+
:address => ((xml/'display/address').first.text rescue "127.0.0.1"),
|
104
|
+
:port => ((xml/'display/port').first.text rescue "5890")
|
105
|
+
} unless @ip
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
data/lib/rbovirt.rb
ADDED
@@ -0,0 +1,248 @@
|
|
1
|
+
require "ovirt/base_object"
|
2
|
+
require "ovirt/cluster"
|
3
|
+
require "ovirt/datacenter"
|
4
|
+
require "ovirt/host"
|
5
|
+
require "ovirt/storage_domain"
|
6
|
+
require "ovirt/template"
|
7
|
+
require "ovirt/vm"
|
8
|
+
|
9
|
+
require "nokogiri"
|
10
|
+
require "rest_client"
|
11
|
+
|
12
|
+
module OVIRT
|
13
|
+
|
14
|
+
class OvirtVersionUnsupportedException < StandardError; end
|
15
|
+
class OvirtException < StandardError
|
16
|
+
def initialize(message)
|
17
|
+
@message = message
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
def message
|
22
|
+
@message
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Client
|
27
|
+
|
28
|
+
attr_reader :credentials, :api_entrypoint, :datacenter_id
|
29
|
+
|
30
|
+
def initialize(username, password, api_entrypoint, datacenter_id=nil)
|
31
|
+
@credentials = { :username => username, :password => password }
|
32
|
+
@datacenter_id = datacenter_id
|
33
|
+
@api_entrypoint = api_entrypoint
|
34
|
+
end
|
35
|
+
|
36
|
+
def vm(vm_id)
|
37
|
+
headers = {:accept => "application/xml; detail=disks; detail=nics; detail=hosts"}
|
38
|
+
vm = http_get("/vms/%s" % vm_id, headers).root
|
39
|
+
OVIRT::VM::new(self, vm)
|
40
|
+
end
|
41
|
+
|
42
|
+
def vms(opts={})
|
43
|
+
headers = {:accept => "application/xml; detail=disks; detail=nics; detail=hosts"}
|
44
|
+
search= opts[:search] || ("datacenter=$s" % current_datacenter.name)
|
45
|
+
http_get("/vms?search=%s" % search, headers).xpath('/vms/vm').collect do |vm|
|
46
|
+
OVIRT::VM::new(self, vm)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def vm_action(id, action, opts={})
|
51
|
+
xml_response = http_post("/vms/%s/%s" % [id, action],'<action/>', opts)
|
52
|
+
return (xml_response/'action/status').first.text.strip.upcase=="COMPLETE"
|
53
|
+
end
|
54
|
+
|
55
|
+
def destroy_vm(id)
|
56
|
+
http_delete("/vms/%s" % id)
|
57
|
+
end
|
58
|
+
|
59
|
+
def api_version
|
60
|
+
result_xml = http_get("/")
|
61
|
+
(result_xml/'/api/product_info/version')
|
62
|
+
end
|
63
|
+
|
64
|
+
def api_version?(major)
|
65
|
+
api_version.first[:major].strip == major
|
66
|
+
end
|
67
|
+
|
68
|
+
def cluster_version?(cluster_id, major)
|
69
|
+
result_xml = http_get("/clusters/%s" % cluster_id)
|
70
|
+
(result_xml/'/cluster/version').first[:major].strip == major
|
71
|
+
end
|
72
|
+
|
73
|
+
def create_vm(template_name, opts)
|
74
|
+
cluster_name = opts[:cluster_name] || clusters.first.name
|
75
|
+
result_xml = http_post("/vms",OVIRT::VM.to_xml(template_name, cluster_name, opts))
|
76
|
+
OVIRT::VM::new(self, result_xml.root)
|
77
|
+
end
|
78
|
+
|
79
|
+
def add_disk(vm_id, opts={})
|
80
|
+
storage_domain_id = opts[:storage_domain] || storagedomains.first.id
|
81
|
+
result_xml = http_post("/vms/%s/disks" % vm_id, VM.disk_xml(storage_domain_id, opts))
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
def add_nic(vm_id, opts={})
|
86
|
+
http_post("/vms/%s/nics" % vm_id, VM.nic_xml( opts))
|
87
|
+
end
|
88
|
+
|
89
|
+
def create_template(vm_id, opts)
|
90
|
+
template = http_post("/templates", Template.to_xml(vm_id, opts))
|
91
|
+
OVIRT::Template::new(self, template.root)
|
92
|
+
end
|
93
|
+
|
94
|
+
def destroy_template(id)
|
95
|
+
http_delete("/templates/%s" % id)
|
96
|
+
end
|
97
|
+
|
98
|
+
def templates(opts={})
|
99
|
+
search= opts[:search] || ("datacenter=$s" % current_datacenter.name)
|
100
|
+
http_get("/templates?serach=%s" % search).xpath('/templates/template').collect do |t|
|
101
|
+
OVIRT::Template::new(self, t)
|
102
|
+
end.compact
|
103
|
+
end
|
104
|
+
|
105
|
+
def template(template_id)
|
106
|
+
template = http_get("/templates/%s" % template_id)
|
107
|
+
OVIRT::Template::new(self, template.root)
|
108
|
+
end
|
109
|
+
|
110
|
+
def datacenters(opts={})
|
111
|
+
datacenters = http_get("/datacenters")
|
112
|
+
datacenters.xpath('/data_centers/data_center').collect do |dc|
|
113
|
+
OVIRT::DataCenter::new(self, dc)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def clusters(opts={})
|
118
|
+
headers = {:accept => "application/xml; detail=datacenters"}
|
119
|
+
search= opts[:search] || ("datacenter=$s" % current_datacenter.name)
|
120
|
+
http_get("/clusters?serach=%s" % search, headers).xpath('/clusters/cluster').collect do |cl|
|
121
|
+
OVIRT::Cluster.new(self, cl)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def cluster(cluster_id)
|
126
|
+
headers = {:accept => "application/xml; detail=datacenters"}
|
127
|
+
cluster_xml = http_get("/clusters/%s" % cluster_id, headers)
|
128
|
+
OVIRT::Cluster.new(self, cluster_xml)
|
129
|
+
end
|
130
|
+
|
131
|
+
def current_datacenter
|
132
|
+
@current_datacenter ||= self.datacenter_id ? datacenter(self.datacenter_id) : datacenters.first
|
133
|
+
end
|
134
|
+
|
135
|
+
def datacenter(datacenter_id)
|
136
|
+
begin
|
137
|
+
datacenter = http_get("/datacenters/%s" % datacenter_id)
|
138
|
+
OVIRT::DataCenter::new(self, datacenter.root)
|
139
|
+
rescue
|
140
|
+
handle_fault $!
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def host(host_id, opts={})
|
145
|
+
xml_response = http_get("/hosts/%s" % host_id)
|
146
|
+
OVIRT::Host::new(self, xml_response.root)
|
147
|
+
end
|
148
|
+
|
149
|
+
def hosts(opts={})
|
150
|
+
search= opts[:search] || ("datacenter=$s" % current_datacenter.name)
|
151
|
+
http_get("/hosts?search=%s" % search).xpath('/hosts/host').collect do |h|
|
152
|
+
OVIRT::Host::new(self, h)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def storagedomain(sd_id)
|
157
|
+
sd = http_get("/storagedomains/%s" % sd_id)
|
158
|
+
OVIRT::StorageDomain::new(self, sd.root)
|
159
|
+
end
|
160
|
+
|
161
|
+
def storagedomains(opts={})
|
162
|
+
search= opts[:search] ||''
|
163
|
+
http_get("/storagedomains?search=%s" % search).xpath('/storage_domains/storage_domain').collect do |sd|
|
164
|
+
OVIRT::StorageDomain::new(self, sd)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
private
|
169
|
+
|
170
|
+
def http_get(suburl, headers={})
|
171
|
+
begin
|
172
|
+
Nokogiri::XML(RestClient::Resource.new(@api_entrypoint)[suburl].get(http_headers(headers)))
|
173
|
+
rescue
|
174
|
+
handle_fault $!
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def http_post(suburl, body, headers={})
|
179
|
+
begin
|
180
|
+
Nokogiri::XML(RestClient::Resource.new(@api_entrypoint)[suburl].post(body, http_headers(headers)))
|
181
|
+
rescue
|
182
|
+
handle_fault $!
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def http_delete(suburl)
|
187
|
+
begin
|
188
|
+
headers = {:accept => 'application/xml'}.merge(auth_header)
|
189
|
+
Nokogiri::XML(RestClient::Resource.new(@api_entrypoint)[suburl].delete(headers))
|
190
|
+
rescue
|
191
|
+
handle_fault $!
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def auth_header
|
196
|
+
# This is the method for strict_encode64:
|
197
|
+
encoded_credentials = ["#{@credentials[:username]}:#{@credentials[:password]}"].pack("m0").gsub(/\n/,'')
|
198
|
+
{ :authorization => "Basic " + encoded_credentials }
|
199
|
+
end
|
200
|
+
|
201
|
+
def base_url
|
202
|
+
url = URI.parse(@api_entrypoint)
|
203
|
+
"#{url.scheme}://#{url.host}:#{url.port}"
|
204
|
+
end
|
205
|
+
|
206
|
+
def self.parse_response(response)
|
207
|
+
Nokogiri::XML(response)
|
208
|
+
end
|
209
|
+
|
210
|
+
def has_datacenter?(vm)
|
211
|
+
value=!(vm/'data_center').empty?
|
212
|
+
value
|
213
|
+
end
|
214
|
+
|
215
|
+
def http_headers(headers ={})
|
216
|
+
headers.merge({
|
217
|
+
:content_type => 'application/xml',
|
218
|
+
:accept => 'application/xml'
|
219
|
+
}).merge(auth_header)
|
220
|
+
end
|
221
|
+
|
222
|
+
def handle_fault(f)
|
223
|
+
if f.is_a?(RestClient::BadRequest)
|
224
|
+
fault = (Nokogiri::XML(f.http_body)/'//fault/detail')
|
225
|
+
fault = fault.text.gsub(/\[|\]/, '') if fault
|
226
|
+
end
|
227
|
+
fault ||= f.message
|
228
|
+
raise OvirtException::new(fault)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
class Link
|
233
|
+
attr_accessor :id, :href, :client
|
234
|
+
|
235
|
+
def initialize(client, id, href)
|
236
|
+
@id, @href = id, href
|
237
|
+
@client = client
|
238
|
+
end
|
239
|
+
|
240
|
+
def follow
|
241
|
+
xml = Client::parse_response(OVIRT::client(@client.base_url)[@href].get(@client.auth_header))
|
242
|
+
object_class = ::OVIRT.const_get(xml.root.name.camelize)
|
243
|
+
object_class.new(@client, (xml.root))
|
244
|
+
end
|
245
|
+
|
246
|
+
end
|
247
|
+
|
248
|
+
end
|
data/rbovirt.gemspec
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{rbovirt}
|
8
|
+
s.version = "0.0.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Amos Benari"]
|
12
|
+
s.date = %q{2012-01-15}
|
13
|
+
s.description = %q{A Ruby client for oVirt REST API}
|
14
|
+
s.email = %q{abenari@redhat.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
"Gemfile",
|
22
|
+
"LICENSE.txt",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"lib/ovirt/base_object.rb",
|
27
|
+
"lib/ovirt/cluster.rb",
|
28
|
+
"lib/ovirt/datacenter.rb",
|
29
|
+
"lib/ovirt/host.rb",
|
30
|
+
"lib/ovirt/storage_domain.rb",
|
31
|
+
"lib/ovirt/template.rb",
|
32
|
+
"lib/ovirt/vm.rb",
|
33
|
+
"lib/rbovirt.rb",
|
34
|
+
"rbovirt.gemspec",
|
35
|
+
"test/helper.rb",
|
36
|
+
"test/test_rbovirt.rb"
|
37
|
+
]
|
38
|
+
s.homepage = %q{http://github.com/abenari/rbovirt}
|
39
|
+
s.licenses = ["MIT"]
|
40
|
+
s.require_paths = ["lib"]
|
41
|
+
s.rubygems_version = %q{1.3.7}
|
42
|
+
s.summary = %q{A Ruby client for oVirt REST API}
|
43
|
+
|
44
|
+
if s.respond_to? :specification_version then
|
45
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
46
|
+
s.specification_version = 3
|
47
|
+
|
48
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
49
|
+
s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
|
50
|
+
s.add_runtime_dependency(%q<rest-client>, [">= 0"])
|
51
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
52
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
53
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
|
54
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
55
|
+
else
|
56
|
+
s.add_dependency(%q<nokogiri>, [">= 0"])
|
57
|
+
s.add_dependency(%q<rest-client>, [">= 0"])
|
58
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
59
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
60
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
61
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
62
|
+
end
|
63
|
+
else
|
64
|
+
s.add_dependency(%q<nokogiri>, [">= 0"])
|
65
|
+
s.add_dependency(%q<rest-client>, [">= 0"])
|
66
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
67
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
68
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
69
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
data/test/helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'test/unit'
|
11
|
+
require 'shoulda'
|
12
|
+
|
13
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
15
|
+
require 'rbovirt'
|
16
|
+
|
17
|
+
class Test::Unit::TestCase
|
18
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestRbovirt < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
user="admin@internal"
|
7
|
+
password="123123"
|
8
|
+
hostname = "ovirt.sat.lab.tlv.redhat.com"
|
9
|
+
port = "8080"
|
10
|
+
url = "http://#{hostname}:#{port}/api"
|
11
|
+
@blank_template_id = "00000000-0000-0000-0000-000000000000"
|
12
|
+
@client = ::OVIRT::Client.new(user, password, url)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_should_return_a_version
|
16
|
+
assert @client.api_version
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_should_return_datacenters
|
20
|
+
assert @client.datacenters
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_should_return_clusters
|
24
|
+
assert @client.clusters
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_should_return_templates
|
28
|
+
assert @client.templates
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_should_create_template
|
32
|
+
name = 't'+Time.now.to_i.to_s
|
33
|
+
params = {}
|
34
|
+
params[:name] = name
|
35
|
+
params[:cluster_name] = "test"
|
36
|
+
vm = @client.create_vm("Blank",params)
|
37
|
+
|
38
|
+
@client.add_disk(vm.id)
|
39
|
+
@client.add_nic(vm.id)
|
40
|
+
while @client.vm(vm.id).status !~ /down/i do
|
41
|
+
end
|
42
|
+
template_name = "test_template"
|
43
|
+
assert template = @client.create_template(vm.id, :name => template_name, :description => "test_template")
|
44
|
+
while @client.vm(vm.id).status !~ /down/i do
|
45
|
+
end
|
46
|
+
assert @client.destroy_template(template.id)
|
47
|
+
@client.destroy_vm(vm.id)
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_should_return_a_template
|
51
|
+
assert @client.template(@blank_template_id)
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def test_should_return_vms
|
56
|
+
assert @client.vms
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_should_return_a_vm
|
60
|
+
name = 'a'+Time.now.to_i.to_s
|
61
|
+
params = {}
|
62
|
+
params[:name] = name
|
63
|
+
params[:cluster_name] = "test"
|
64
|
+
vm = @client.create_vm("Blank",params)
|
65
|
+
assert @client.vm(vm.id)
|
66
|
+
@client.destroy_vm(vm.id)
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_should_start_vm
|
70
|
+
name = 'r'+Time.now.to_i.to_s
|
71
|
+
params = {}
|
72
|
+
params[:name] = name
|
73
|
+
params[:cluster_name] = "test"
|
74
|
+
vm = @client.create_vm("Blank",params)
|
75
|
+
@client.add_disk(vm.id)
|
76
|
+
@client.add_nic(vm.id)
|
77
|
+
while @client.vm(vm.id).status !~ /down/i do
|
78
|
+
end
|
79
|
+
assert @client.vm_action(vm.id, :start)
|
80
|
+
@client.vm_action(vm.id, :shutdown)
|
81
|
+
while @client.vm(vm.id).status !~ /down/i do
|
82
|
+
end
|
83
|
+
@client.destroy_vm(vm.id)
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_should_stop_vm
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_should_destroy_vm
|
91
|
+
name = 'd'+Time.now.to_i.to_s
|
92
|
+
params = {}
|
93
|
+
params[:name] = name
|
94
|
+
params[:cluster_name] = "test"
|
95
|
+
vm = @client.create_vm("Blank",params)
|
96
|
+
assert @client.destroy_vm(vm.id)
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_should_return_storage
|
100
|
+
assert @client.storagedomains
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_should_create_a_vm
|
104
|
+
name = 'c'+Time.now.to_i.to_s
|
105
|
+
params = {}
|
106
|
+
params[:name] = name
|
107
|
+
params[:cluster_name] = "test"
|
108
|
+
assert vm = @client.create_vm("Blank",params)
|
109
|
+
@client.destroy_vm(vm.id)
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
metadata
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rbovirt
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Amos Benari
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-01-15 00:00:00 +02:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
prerelease: false
|
23
|
+
name: nokogiri
|
24
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
requirement: *id001
|
34
|
+
type: :runtime
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
prerelease: false
|
37
|
+
name: rest-client
|
38
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
requirement: *id002
|
48
|
+
type: :runtime
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
prerelease: false
|
51
|
+
name: shoulda
|
52
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
requirement: *id003
|
62
|
+
type: :development
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
prerelease: false
|
65
|
+
name: bundler
|
66
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ~>
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
hash: 23
|
72
|
+
segments:
|
73
|
+
- 1
|
74
|
+
- 0
|
75
|
+
- 0
|
76
|
+
version: 1.0.0
|
77
|
+
requirement: *id004
|
78
|
+
type: :development
|
79
|
+
- !ruby/object:Gem::Dependency
|
80
|
+
prerelease: false
|
81
|
+
name: jeweler
|
82
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ~>
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
hash: 7
|
88
|
+
segments:
|
89
|
+
- 1
|
90
|
+
- 6
|
91
|
+
- 4
|
92
|
+
version: 1.6.4
|
93
|
+
requirement: *id005
|
94
|
+
type: :development
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
prerelease: false
|
97
|
+
name: rcov
|
98
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
hash: 3
|
104
|
+
segments:
|
105
|
+
- 0
|
106
|
+
version: "0"
|
107
|
+
requirement: *id006
|
108
|
+
type: :development
|
109
|
+
description: A Ruby client for oVirt REST API
|
110
|
+
email: abenari@redhat.com
|
111
|
+
executables: []
|
112
|
+
|
113
|
+
extensions: []
|
114
|
+
|
115
|
+
extra_rdoc_files:
|
116
|
+
- LICENSE.txt
|
117
|
+
- README.rdoc
|
118
|
+
files:
|
119
|
+
- .document
|
120
|
+
- Gemfile
|
121
|
+
- LICENSE.txt
|
122
|
+
- README.rdoc
|
123
|
+
- Rakefile
|
124
|
+
- VERSION
|
125
|
+
- lib/ovirt/base_object.rb
|
126
|
+
- lib/ovirt/cluster.rb
|
127
|
+
- lib/ovirt/datacenter.rb
|
128
|
+
- lib/ovirt/host.rb
|
129
|
+
- lib/ovirt/storage_domain.rb
|
130
|
+
- lib/ovirt/template.rb
|
131
|
+
- lib/ovirt/vm.rb
|
132
|
+
- lib/rbovirt.rb
|
133
|
+
- rbovirt.gemspec
|
134
|
+
- test/helper.rb
|
135
|
+
- test/test_rbovirt.rb
|
136
|
+
has_rdoc: true
|
137
|
+
homepage: http://github.com/abenari/rbovirt
|
138
|
+
licenses:
|
139
|
+
- MIT
|
140
|
+
post_install_message:
|
141
|
+
rdoc_options: []
|
142
|
+
|
143
|
+
require_paths:
|
144
|
+
- lib
|
145
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
146
|
+
none: false
|
147
|
+
requirements:
|
148
|
+
- - ">="
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
hash: 3
|
151
|
+
segments:
|
152
|
+
- 0
|
153
|
+
version: "0"
|
154
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
155
|
+
none: false
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
hash: 3
|
160
|
+
segments:
|
161
|
+
- 0
|
162
|
+
version: "0"
|
163
|
+
requirements: []
|
164
|
+
|
165
|
+
rubyforge_project:
|
166
|
+
rubygems_version: 1.3.7
|
167
|
+
signing_key:
|
168
|
+
specification_version: 3
|
169
|
+
summary: A Ruby client for oVirt REST API
|
170
|
+
test_files: []
|
171
|
+
|