You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@deltacloud.apache.org by mf...@redhat.com on 2010/12/20 17:41:22 UTC
Initial import of new RHEV-M driver (rev 2)
Hi,
I managed some RHEV-M setup on my desk and actually fixed all
bugs from RHEV Mock API.
So for now, this driver *should* work with latest RHEV API.
Things supported:
* Create VM and managing VMs
* POST /api/instances
* POST /api/instances/:id/stop
* POST /api/instances/:id/start
* POST /api/instances/:id/reboot
* DELETE /api/instances/:id
* Realms are now reported correctly
-- Michal
[PATCH core 2/2] Fixed a lot bugs inside RHEV driver Added support for creating VMs
Posted by mf...@redhat.com.
From: Michal Fojtik <mf...@redhat.com>
---
.../lib/deltacloud/drivers/rhevm2/rhevm2_driver.rb | 75 ++++++++++++++------
.../lib/deltacloud/drivers/rhevm2/rhevm_client.rb | 66 +++++++++++-------
2 files changed, 94 insertions(+), 47 deletions(-)
diff --git a/server/lib/deltacloud/drivers/rhevm2/rhevm2_driver.rb b/server/lib/deltacloud/drivers/rhevm2/rhevm2_driver.rb
index f1655d1..25b3345 100644
--- a/server/lib/deltacloud/drivers/rhevm2/rhevm2_driver.rb
+++ b/server/lib/deltacloud/drivers/rhevm2/rhevm2_driver.rb
@@ -36,13 +36,13 @@ class RHEVM2Driver < Deltacloud::BaseDriver
define_hardware_profile 'SERVER' do
cpu 1
- memory [ 1*1024 .. 32*1024 ]
+ memory ( 512 .. 32*1024 )
architecture 'x86_64'
end
define_hardware_profile 'DESKTOP' do
cpu 1
- memory [ 1*1024 .. 32*1024 ]
+ memory ( 512 .. 32*1024 )
architecture 'x86_64'
end
@@ -55,7 +55,7 @@ class RHEVM2Driver < Deltacloud::BaseDriver
def provider_uri
# 'http://localhost:8099/rhevm-api-mock/' || @RHEVM_URI
- 'http://localhost:8080'
+ 'https://10.34.2.122:8443/rhevm-api-powershell'
end
# FIX: This is state table from EC2, fix it pls to
@@ -64,9 +64,10 @@ class RHEVM2Driver < Deltacloud::BaseDriver
define_instance_states do
start.to( :pending ) .automatically
pending.to( :running ) .automatically
- pending.to( :stopping ) .on( :stop )
pending.to( :stopped ) .automatically
+ pending.to( :finish ) .on(:destroy)
stopped.to( :running ) .on( :start )
+ stopped.to( :finish ) .on( :destroy )
running.to( :running ) .on( :reboot )
running.to( :stopping ) .on( :stop )
shutting_down.to( :stopped ) .automatically
@@ -98,7 +99,7 @@ class RHEVM2Driver < Deltacloud::BaseDriver
templates = templates.select{|t| opts[:id] == t.id}
end
templates.each do |t|
- img_arr << convert_image(t)
+ img_arr << convert_image(client, t)
end
end
img_arr = filter_on( img_arr, :architecture, opts )
@@ -125,6 +126,13 @@ class RHEVM2Driver < Deltacloud::BaseDriver
end
end
+ def start_instance(credentials, id)
+ client = new_client(credentials)
+ safely do
+ client.vm_action(:start, id)
+ end
+ end
+
def stop_instance(credentials, id)
client = new_client(credentials)
safely do
@@ -132,17 +140,30 @@ class RHEVM2Driver < Deltacloud::BaseDriver
end
end
- def start_instance(credentials, id)
+ def destroy_instance(credentials, id)
client = new_client(credentials)
safely do
- client.vm_action(:start, id)
+ client.delete_vm(id)
end
end
- def shutdown_instance(credentials, id)
+ def create_instance(credentials, image_id, opts={})
client = new_client(credentials)
safely do
- client.vm_action(:shutdown, id)
+ cluster = get_cluster_from_realm(client, opts[:realm_id] || 'Default')
+ vm_name = opts[:name] ? "<name>#{opts[:name]}</name>" : ""
+ vm_template = "<template id='#{image_id}'/>"
+ vm_cluster = opts[:realm_id] ? "<cluster id='#{cluster.id}'/>" : "<cluster id='Default'/>"
+ # This cause Internal Server Error on RHEV-API side
+ # vm_memory = opts[:hwp_memory] ? "<memory>#{opts[:hwp_memory].to_i*1024}</memory>" : ''
+ convert_instance(client, RHEVM::Vm::new(client, client.create_vm(
+ "<vm>"+
+ vm_name +
+ vm_template +
+ vm_cluster +
+ # vm_memory +
+ "</vm>"
+ ).xpath('vm')))
end
end
@@ -153,10 +174,15 @@ class RHEVM2Driver < Deltacloud::BaseDriver
RHEVM::Client.new(credentials.user, credentials.password, provider_uri, opts)
end
+ def get_cluster_from_realm(client, datacenter_id)
+ clusters = client.clusters
+ clusters.select { |c| c.datacenter_id }.first
+ end
+
# I can't test this method, since 'cluster' is not a part of Mock driver
def get_realm_from_cluster(client, cluster_id)
cluster = client.clusters(:id => cluster_id)
- datacenter = client.datacenter(:id => cluster.datacenter_id)
+ datacenter = client.datacenters(:id => cluster.datacenter_id)
convert_realm(datacenter)
end
@@ -164,18 +190,16 @@ class RHEVM2Driver < Deltacloud::BaseDriver
# FIXME: Remove 'DOWN', it's used just because RHEV Mock driver
# has no 'state' property in XML.
#
- # FIXME2: This call will now throw 500 because I'm unable to fetch realm
- # for instance.
- #
state = convert_state(inst.status=='' ? 'DOWN' : inst.status)
+ instance_realm = get_realm_from_cluster(client, inst.cluster)
Instance.new(
:id => inst.id,
:name => inst.name,
:state => state,
:image_id => inst.template,
# Realm aka DataCenter could be retrieved from Cluster
- :realm_id => get_realm_from_cluster(client, inst.cluster),
- :owner_id => 'self',
+ :realm_id => instance_realm ? instance_realm.id : nil,
+ :owner_id => client.username,
:launch_time => inst.creation_time,
:instance_profile => InstanceProfile::new(inst.profile),
:hardware_profile_id => inst.profile,
@@ -192,37 +216,44 @@ class RHEVM2Driver < Deltacloud::BaseDriver
# FIXME: This will need to be fixed regarding to state-machine
def convert_state(state)
case state
- when 'POWERING_UP', 'WAIT_FOR_LAUNCH', 'REBOOT_IN_PROGRESS', 'SAVING_STATE',
+ when 'WAIT_FOR_LAUNCH', 'REBOOT_IN_PROGRESS', 'SAVING_STATE',
'RESTORING_STATE', 'POWERING_DOWN' then
'PENDING'
when 'UNASSIGNED', 'DOWN', 'POWERING_DOWN', 'PAUSED', 'NOT_RESPONDING', 'SAVING_STATE',
'SUSPENDED', 'IMAGE_ILLEGAL', 'IMAGE_LOCKED', 'UNKNOWN' then
'STOPPED'
- when 'UP', 'MIGRATING_TO', 'MIGRATING_FROM'
+ when 'POWERING_UP', 'UP', 'MIGRATING_TO', 'MIGRATING_FROM'
'RUNNING'
end
end
- def convert_image(img)
+ def convert_image(client, img)
Image.new(
:id => img.id,
:name => img.name,
:description => img.description,
- :owner_id => 'self',
+ :owner_id => client.username,
:architecture => 'x86_64', # All RHEV-M VMs are x86_64
:status => img.status
)
end
- def convert_realm(realm)
+ def convert_realm(dc)
Realm.new(
- :id => realm.id,
- :name => realm.name,
+ :id => dc.id,
+ :name => dc.name,
:state => 'AVAILABLE',
:limit => :unlimited
)
end
+# def catched_exceptions_list
+# {
+# :auth => RestClient::Unauthorized,
+# :error => RestClient::InternalServerError,
+# :glob => [ /RestClient::(\w+)/ ]
+# }
+# end
end
diff --git a/server/lib/deltacloud/drivers/rhevm2/rhevm_client.rb b/server/lib/deltacloud/drivers/rhevm2/rhevm_client.rb
index 856844c..25d886a 100644
--- a/server/lib/deltacloud/drivers/rhevm2/rhevm_client.rb
+++ b/server/lib/deltacloud/drivers/rhevm2/rhevm_client.rb
@@ -1,9 +1,4 @@
-require 'rubygems'
-
-#gem 'rest-client'
-
require 'base64'
-require 'logger'
require 'restclient'
require 'nokogiri'
@@ -11,17 +6,18 @@ module RHEVM
class Client
attr_reader :base_uri
+ attr_reader :host
attr_reader :entry_points
- attr_reader :logger
+ attr_reader :username
# Define a list of supported collections which will be handled automatically
# by method_missing
@@COLLECTIONS = [ :templates, :clusters, :storagedomains, :vms, :datacenters ]
def initialize(username, password, base_uri, opts={})
- @logger = opts[:verbose] ? Logger.new(STDERR) : []
@username, @password = username, password
- URI.parse(base_uri)
+ uri = URI.parse(base_uri)
+ @host = "#{uri.scheme}://#{uri.host}:#{uri.port}"
@base_uri = base_uri
@entry_points = {}
discover_entry_points()
@@ -30,14 +26,14 @@ module RHEVM
def method_missing(method_name, *args)
opts = args[0] if args[0].class.eql?(Hash)
opts ||= {}
- puts opts.inspect
if @@COLLECTIONS.include?(method_name.to_sym)
if opts[:id]
- object = Nokogiri::XML(get("%s/%s" % @entry_points[method_name.to_s], opts[:id]))
+ puts "[GET] #{@entry_points[method_name.to_s]}#{opts[:id]}"
+ object = Nokogiri::XML(get("#{@entry_points[method_name.to_s]}#{opts[:id]}"))
element = method_name.to_s
element = 'data_centers' if method_name.eql?(:datacenters)
+ puts ">>>> #{element}"
inst = RHEVM.const_get(element.classify)
- puts inst.inspect
return inst::new(self, object)
else
objects = Nokogiri::XML(get(@entry_points[method_name.to_s]))
@@ -57,34 +53,55 @@ module RHEVM
end
def vm_action(action, vm)
- Nokogiri::XML(post("/vms/%s/" % action.to_s))
+ response = post("#{@base_uri}/vms/#{vm}/%s" % action)
+ Nokogiri::XML(response)
+ end
+
+ def create_vm(opts="")
+ Nokogiri::XML(post("#{@base_uri}/vms", opts))
+ end
+
+ def delete_vm(id)
+ delete("#{@base_uri}/vms/#{id}")
end
protected
+ def delete(uri)
+ headers = {
+ :authorization => "Basic " + Base64.encode64("#{@username}:#{@password}"),
+ :accept => 'application/xml',
+ }
+ RestClient.delete(uri, headers).to_s
+ end
+
def get(uri)
headers = {
:authorization => "Basic " + Base64.encode64("#{@username}:#{@password}"),
- :accept => "application/xml"
+ :accept => 'application/xml',
}
- @logger << "GET #{uri}\n"
- RestClient.get(uri, headers).to_s()
+ response = RestClient.get(uri, headers).to_s
+ puts "=====\n#{response}\n====="
+ response
end
- def post(uri, params={})
+ def post(uri, params="")
headers = {
:authorization => "Basic " + Base64.encode64("#{@username}:#{@password}"),
- :accept => "application/xml"
+ :accept => 'application/xml',
+ :content_type => 'application/xml'
}
- @logger << "POST #{uri}\n"
- RestClient.post(uri, params, headers).to_s
+ params = "<action/>" if params.size==0
+ response = RestClient.post(uri, params, headers).to_s
+ puts "=====\n#{response}\n====="
+ response
end
def discover_entry_points()
return if @discovered
doc = Nokogiri.XML(get(@base_uri))
doc.xpath('api/link').each() do |link|
- @entry_points[link['rel']] = @base_uri + link['href']
+ @entry_points[link['rel']] = @host + link['href']
end
@discovered = true
end
@@ -101,10 +118,9 @@ module RHEVM
attr_accessor(:id, :href, :name)
def initialize(client, xml)
- client.logger << "#{xml}\n"
@client = client
@id = xml[:id]
- @href = @client.base_uri + xml[:href]
+ @href = "#{@client.base_uri}#{xml[:href]}"
@name = xml.xpath('name').text
end
end
@@ -132,8 +148,8 @@ module RHEVM
@status = xml.xpath('status').text
@memory = xml.xpath('memory').text
@profile = xml.xpath('type').text
- @sockets = xml.xpath('cpu/topology').first[:sockets]
- @cores = xml.xpath('cpu/topology').first[:cores]
+ @sockets = xml.xpath('cpu/topology').first[:sockets] rescue ''
+ @cores = xml.xpath('cpu/topology').first[:cores] rescue ''
@bootdevs = []
xml.xpath('os/boot').each do |boot|
@bootdevs << boot[:dev]
@@ -141,7 +157,7 @@ module RHEVM
@host = xml.xpath('host')[:id]
@cluster = xml.xpath('cluster').first[:id]
@template = xml.xpath('template').first[:id]
- @vmpool = xml.xpath('vmpool').first[:id]
+ @vmpool = xml.xpath('vmpool').first[:id] if xml.xpath('vmpool').size >0
@creation_time = xml.xpath('creation_time').text
end
end
--
1.7.3.3
[PATCH core 1/2] Initial import of RHEV REST API driver
Posted by mf...@redhat.com.
From: Michal Fojtik <mf...@redhat.com>
---
.../lib/deltacloud/drivers/rhevm2/rhevm2_driver.rb | 231 ++++++++++++++++++++
.../lib/deltacloud/drivers/rhevm2/rhevm_client.rb | 217 ++++++++++++++++++
server/lib/drivers.rb | 1 +
3 files changed, 449 insertions(+), 0 deletions(-)
create mode 100644 server/lib/deltacloud/drivers/rhevm2/rhevm2_driver.rb
create mode 100644 server/lib/deltacloud/drivers/rhevm2/rhevm_client.rb
diff --git a/server/lib/deltacloud/drivers/rhevm2/rhevm2_driver.rb b/server/lib/deltacloud/drivers/rhevm2/rhevm2_driver.rb
new file mode 100644
index 0000000..f1655d1
--- /dev/null
+++ b/server/lib/deltacloud/drivers/rhevm2/rhevm2_driver.rb
@@ -0,0 +1,231 @@
+#
+# Copyright (C) 2009 Red Hat, Inc.
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership. The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+require 'deltacloud/base_driver'
+require 'deltacloud/drivers/rhevm2/rhevm_client'
+
+module Deltacloud
+ module Drivers
+ module RHEVM2
+
+class RHEVM2Driver < Deltacloud::BaseDriver
+
+ feature :instances, :user_name
+
+ # FIXME: These values are just for ilustration
+ # Also I choosed 'SERVER' and 'DESKTOP' names
+ # because they are referred by VM (API type)
+ #
+ # Values like RAM or STORAGE are reported by VM
+ # so they are not static.
+
+ define_hardware_profile 'SERVER' do
+ cpu 1
+ memory [ 1*1024 .. 32*1024 ]
+ architecture 'x86_64'
+ end
+
+ define_hardware_profile 'DESKTOP' do
+ cpu 1
+ memory [ 1*1024 .. 32*1024 ]
+ architecture 'x86_64'
+ end
+
+ # Instead of setting a URL for RHEV provider
+ # do it here in driver, so it can be altered by HTTP headers
+ #
+ def provider_uri=(uri)
+ @RHEVM_URI = uri
+ end
+
+ def provider_uri
+ # 'http://localhost:8099/rhevm-api-mock/' || @RHEVM_URI
+ 'http://localhost:8080'
+ end
+
+ # FIX: This is state table from EC2, fix it pls to
+ # match RHEV-M model
+ #
+ define_instance_states do
+ start.to( :pending ) .automatically
+ pending.to( :running ) .automatically
+ pending.to( :stopping ) .on( :stop )
+ pending.to( :stopped ) .automatically
+ stopped.to( :running ) .on( :start )
+ running.to( :running ) .on( :reboot )
+ running.to( :stopping ) .on( :stop )
+ shutting_down.to( :stopped ) .automatically
+ stopped.to( :finish ) .automatically
+ end
+
+ #
+ # Realms
+ #
+
+ def realms(credentials, opts=nil)
+ client = new_client(credentials)
+ realm_arr = []
+ safely do
+ datacenters = client.datacenters
+ datacenters.each do |d|
+ realm_arr << convert_realm(d)
+ end
+ end
+ realm_arr
+ end
+
+ def images(credentials, opts={})
+ client = new_client(credentials)
+ img_arr = []
+ safely do
+ templates = client.templates
+ if (!opts.nil? && opts[:id])
+ templates = templates.select{|t| opts[:id] == t.id}
+ end
+ templates.each do |t|
+ img_arr << convert_image(t)
+ end
+ end
+ img_arr = filter_on( img_arr, :architecture, opts )
+ img_arr.sort_by{|e| [e.owner_id, e.name]}
+ end
+
+ def instances(credentials, opts={})
+ client = new_client(credentials)
+ inst_arr = []
+ safely do
+ vms = client.vms
+ vms.each do |vm|
+ inst_arr << convert_instance(client, vm)
+ end
+ end
+ inst_arr = filter_on( inst_arr, :id, opts )
+ filter_on( inst_arr, :state, opts )
+ end
+
+ def reboot_instance(credentials, id)
+ client = new_client(credentials)
+ safely do
+ client.vm_action(:reboot, id)
+ end
+ end
+
+ def stop_instance(credentials, id)
+ client = new_client(credentials)
+ safely do
+ client.vm_action(:suspend, id)
+ end
+ end
+
+ def start_instance(credentials, id)
+ client = new_client(credentials)
+ safely do
+ client.vm_action(:start, id)
+ end
+ end
+
+ def shutdown_instance(credentials, id)
+ client = new_client(credentials)
+ safely do
+ client.vm_action(:shutdown, id)
+ end
+ end
+
+ private
+
+ def new_client(credentials)
+ opts = {:verbose => true}
+ RHEVM::Client.new(credentials.user, credentials.password, provider_uri, opts)
+ end
+
+ # I can't test this method, since 'cluster' is not a part of Mock driver
+ def get_realm_from_cluster(client, cluster_id)
+ cluster = client.clusters(:id => cluster_id)
+ datacenter = client.datacenter(:id => cluster.datacenter_id)
+ convert_realm(datacenter)
+ end
+
+ def convert_instance(client, inst)
+ # FIXME: Remove 'DOWN', it's used just because RHEV Mock driver
+ # has no 'state' property in XML.
+ #
+ # FIXME2: This call will now throw 500 because I'm unable to fetch realm
+ # for instance.
+ #
+ state = convert_state(inst.status=='' ? 'DOWN' : inst.status)
+ Instance.new(
+ :id => inst.id,
+ :name => inst.name,
+ :state => state,
+ :image_id => inst.template,
+ # Realm aka DataCenter could be retrieved from Cluster
+ :realm_id => get_realm_from_cluster(client, inst.cluster),
+ :owner_id => 'self',
+ :launch_time => inst.creation_time,
+ :instance_profile => InstanceProfile::new(inst.profile),
+ :hardware_profile_id => inst.profile,
+ :actions=>instance_actions_for( state )
+ )
+ end
+
+ # STATES:
+ #
+ # UNASSIGNED, DOWN, UP, POWERING_UP, POWERED_DOWN, PAUSED, MIGRATING_FROM, MIGRATING_TO,
+ # UNKNOWN, NOT_RESPONDING, WAIT_FOR_LAUNCH, REBOOT_IN_PROGRESS, SAVING_STATE, RESTORING_STATE,
+ # SUSPENDED, IMAGE_ILLEGAL, IMAGE_LOCKED or POWERING_DOWN
+ #
+ # FIXME: This will need to be fixed regarding to state-machine
+ def convert_state(state)
+ case state
+ when 'POWERING_UP', 'WAIT_FOR_LAUNCH', 'REBOOT_IN_PROGRESS', 'SAVING_STATE',
+ 'RESTORING_STATE', 'POWERING_DOWN' then
+ 'PENDING'
+ when 'UNASSIGNED', 'DOWN', 'POWERING_DOWN', 'PAUSED', 'NOT_RESPONDING', 'SAVING_STATE',
+ 'SUSPENDED', 'IMAGE_ILLEGAL', 'IMAGE_LOCKED', 'UNKNOWN' then
+ 'STOPPED'
+ when 'UP', 'MIGRATING_TO', 'MIGRATING_FROM'
+ 'RUNNING'
+ end
+ end
+
+ def convert_image(img)
+ Image.new(
+ :id => img.id,
+ :name => img.name,
+ :description => img.description,
+ :owner_id => 'self',
+ :architecture => 'x86_64', # All RHEV-M VMs are x86_64
+ :status => img.status
+ )
+ end
+
+ def convert_realm(realm)
+ Realm.new(
+ :id => realm.id,
+ :name => realm.name,
+ :state => 'AVAILABLE',
+ :limit => :unlimited
+ )
+ end
+
+
+end
+
+ end
+ end
+end
diff --git a/server/lib/deltacloud/drivers/rhevm2/rhevm_client.rb b/server/lib/deltacloud/drivers/rhevm2/rhevm_client.rb
new file mode 100644
index 0000000..856844c
--- /dev/null
+++ b/server/lib/deltacloud/drivers/rhevm2/rhevm_client.rb
@@ -0,0 +1,217 @@
+require 'rubygems'
+
+#gem 'rest-client'
+
+require 'base64'
+require 'logger'
+require 'restclient'
+require 'nokogiri'
+
+module RHEVM
+
+ class Client
+ attr_reader :base_uri
+ attr_reader :entry_points
+ attr_reader :logger
+
+ # Define a list of supported collections which will be handled automatically
+ # by method_missing
+ @@COLLECTIONS = [ :templates, :clusters, :storagedomains, :vms, :datacenters ]
+
+ def initialize(username, password, base_uri, opts={})
+ @logger = opts[:verbose] ? Logger.new(STDERR) : []
+ @username, @password = username, password
+ URI.parse(base_uri)
+ @base_uri = base_uri
+ @entry_points = {}
+ discover_entry_points()
+ end
+
+ def method_missing(method_name, *args)
+ opts = args[0] if args[0].class.eql?(Hash)
+ opts ||= {}
+ puts opts.inspect
+ if @@COLLECTIONS.include?(method_name.to_sym)
+ if opts[:id]
+ object = Nokogiri::XML(get("%s/%s" % @entry_points[method_name.to_s], opts[:id]))
+ element = method_name.to_s
+ element = 'data_centers' if method_name.eql?(:datacenters)
+ inst = RHEVM.const_get(element.classify)
+ puts inst.inspect
+ return inst::new(self, object)
+ else
+ objects = Nokogiri::XML(get(@entry_points[method_name.to_s]))
+ objects_arr = []
+ element = method_name.to_s
+ # FIXME:
+ # This is an exception/or bug in RHEV-M API:
+ # (uri is /datacenters but root element it 'data_centers')
+ element = 'data_centers' if method_name.eql?(:datacenters)
+ (objects/"#{element}/#{element.singularize}").each do |item|
+ inst = RHEVM.const_get(element.classify)
+ objects_arr << inst.new(self, item)
+ end
+ return objects_arr
+ end
+ end
+ end
+
+ def vm_action(action, vm)
+ Nokogiri::XML(post("/vms/%s/" % action.to_s))
+ end
+
+ protected
+
+ def get(uri)
+ headers = {
+ :authorization => "Basic " + Base64.encode64("#{@username}:#{@password}"),
+ :accept => "application/xml"
+ }
+ @logger << "GET #{uri}\n"
+ RestClient.get(uri, headers).to_s()
+ end
+
+ def post(uri, params={})
+ headers = {
+ :authorization => "Basic " + Base64.encode64("#{@username}:#{@password}"),
+ :accept => "application/xml"
+ }
+ @logger << "POST #{uri}\n"
+ RestClient.post(uri, params, headers).to_s
+ end
+
+ def discover_entry_points()
+ return if @discovered
+ doc = Nokogiri.XML(get(@base_uri))
+ doc.xpath('api/link').each() do |link|
+ @entry_points[link['rel']] = @base_uri + link['href']
+ end
+ @discovered = true
+ end
+
+ private
+
+ def singularize(str)
+ str.gsub(/s$/, '')
+ end
+
+ end
+
+ class BaseModel
+ attr_accessor(:id, :href, :name)
+
+ def initialize(client, xml)
+ client.logger << "#{xml}\n"
+ @client = client
+ @id = xml[:id]
+ @href = @client.base_uri + xml[:href]
+ @name = xml.xpath('name').text
+ end
+ end
+
+ class StorageDomain < BaseModel
+ attr_accessor(:type, :status, :master, :storage_type, :address, :path, :host)
+
+ def initialize(client, xml)
+ super(client, xml)
+ @type = xml.xpath('type').text
+ @status = xml.xpath('master').text
+ @storage_type = xml.xpath('storage/type')
+ @address = xml.xpath('storage/address').text
+ @path = xml.xpath('storage/path').text
+ @host = xml.xpath('host')[:id]
+ end
+ end
+
+ class Vm < BaseModel
+ attr_accessor(:status, :memory, :sockets, :cores, :bootdevs, :host, :cluster, :template, :vmpool, :profile)
+ attr_accessor(:creation_time)
+
+ def initialize(client, xml)
+ super(client, xml)
+ @status = xml.xpath('status').text
+ @memory = xml.xpath('memory').text
+ @profile = xml.xpath('type').text
+ @sockets = xml.xpath('cpu/topology').first[:sockets]
+ @cores = xml.xpath('cpu/topology').first[:cores]
+ @bootdevs = []
+ xml.xpath('os/boot').each do |boot|
+ @bootdevs << boot[:dev]
+ end
+ @host = xml.xpath('host')[:id]
+ @cluster = xml.xpath('cluster').first[:id]
+ @template = xml.xpath('template').first[:id]
+ @vmpool = xml.xpath('vmpool').first[:id]
+ @creation_time = xml.xpath('creation_time').text
+ end
+ end
+
+ class Template < BaseModel
+ attr_accessor(:status, :memory, :name, :description)
+
+ def initialize(client, xml)
+ super(client, xml)
+ @status = (xml/'status').text
+ @memory = (xml/'memory').text
+ @description = (xml/'description').text
+ end
+ end
+
+ class DataCenter < BaseModel
+ attr_accessor :name, :storage_type, :description
+
+ def initialize(client, xml)
+ super(client, xml)
+ @name, @storage_type, @description = (xml/'name').text, (xml/'storage_type').text, (xml/'description').text
+ end
+ end
+
+ class Cluster < BaseModel
+ attr_accessor :name, :datacenter_id, :cpu
+
+ def initialize(client, xml)
+ super(client, xml)
+ @name = (xml/'name').text
+ @datacenter_id = (xml/'data_center').first['id']
+ @cpu = (xml/'cpu').first['id']
+ @name = (xml/'name').text
+ end
+ end
+
+end
+
+class String
+
+ unless method_defined?(:classify)
+ # Create a class name from string
+ def classify
+ self.singularize.camelize
+ end
+ end
+
+ unless method_defined?(:camelize)
+ # Camelize converts strings to UpperCamelCase
+ def camelize
+ self.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
+ end
+ end
+
+ unless method_defined?(:singularize)
+ # Strip 's' character from end of string
+ def singularize
+ self.gsub(/s$/, '')
+ end
+ end
+
+ # Convert string to float if string value seems like Float
+ def convert
+ return self.to_f if self.strip =~ /^([\d\.]+$)/
+ self
+ end
+
+ # Simply converts whitespaces and - symbols to '_' which is safe for Ruby
+ def sanitize
+ self.strip.gsub(/(\W+)/, '_')
+ end
+
+end
diff --git a/server/lib/drivers.rb b/server/lib/drivers.rb
index 420621c..a164f28 100644
--- a/server/lib/drivers.rb
+++ b/server/lib/drivers.rb
@@ -21,6 +21,7 @@ module Deltacloud
:rackspace => { :name => "Rackspace" },
:gogrid => { :name => "Gogrid" },
:rhevm => { :name => "RHEVM" },
+ :rhevm2 => { :name => "RHEVM2" },
:rimuhosting => { :name => "RimuHosting"},
:opennebula => { :name => "Opennebula", :class => "OpennebulaDriver" },
:terremark => { :name => "Terremark"},
--
1.7.3.3