From: Michal Fojtik <[email protected]>
Signed-off-by: Michal fojtik <[email protected]> --- .../lib/deltacloud/drivers/rhevm/rhevm_client.rb | 78 +++++++++++++++++++- .../lib/deltacloud/drivers/rhevm/rhevm_driver.rb | 7 ++ 2 files changed, 84 insertions(+), 1 deletions(-) diff --git a/server/lib/deltacloud/drivers/rhevm/rhevm_client.rb b/server/lib/deltacloud/drivers/rhevm/rhevm_client.rb index 26bf471..ca8e3d9 100644 --- a/server/lib/deltacloud/drivers/rhevm/rhevm_client.rb +++ b/server/lib/deltacloud/drivers/rhevm/rhevm_client.rb @@ -23,10 +23,27 @@ require 'json' module RHEVM + # + # NOTE: Change this if you want to use Windows machine to (/c/something) + # + FILEINJECT_PATH = "/tmp/deltacloud.txt" + def self.client(url) RestClient::Resource.new(url) end + class BackendVersionUnsupportedException < StandardError; end + class RHEVMBackendException < StandardError + def initialize(message) + @message = message + super + end + + def message + @message + end + end + class Client attr_reader :credentials, :api_entrypoint @@ -66,6 +83,32 @@ module RHEVM return true end + def api_version?(major) + headers = { + :content_type => 'application/xml', + :accept => 'application/xml' + } + headers.merge!(auth_header) + result_xml = Nokogiri::XML(RHEVM::client(@api_entrypoint)["/"].get(headers)) + (result_xml/'/api/system_version').first[:major].strip == major + end + + def cluster_version?(cluster_id, major) + headers = { + :content_type => 'application/xml', + :accept => 'application/xml' + } + headers.merge!(auth_header) + result_xml = Nokogiri::XML(RHEVM::client(@api_entrypoint)["/clusters/%s" % cluster_id].get(headers)) + (result_xml/'/cluster/version').first[:major].strip == major + end + + def escape_user_data(data) + # Replace " with ' to keep quotes in XML attribute safe + data.gsub!(/"/, "'") + data + end + def create_vm(template_id, opts={}) opts ||= {} builder = Nokogiri::XML::Builder.new do @@ -78,6 +121,30 @@ module RHEVM cpu { topology( :cores => (opts[:hwp_cpu] || '1'), :sockets => '1' ) } + if opts[:user_data] and not opts[:user_data].empty? + if api_version?('3') and cluster_version?((opts[:realm_id] || clusters.first.id), '3') + # + # Clone is necessary to keep provisioning same as original template + # https://bugzilla.redhat.com/show_bug.cgi?id=733695 + # + disks { + clone_ "true" + } + custom_properties { + # + # FIXME: 'regexp' parameter is just a temporary workaround. This + # is a reported and verified bug and should be fixed in next + # RHEV-M release. + # + custom_property({ + :name => "fileinject", + :value => "#{RHEVM::FILEINJECT_PATH}:#{escape_user_data(Base64.decode64(opts[:user_data]))}", + :regexp => "^.*:.*$"}) + } + else + raise BackendVersionUnsupportedException.new + end + end } end headers = opts[:headers] || {} @@ -86,7 +153,16 @@ module RHEVM :accept => 'application/xml', }) headers.merge!(auth_header) - vm = RHEVM::client(@api_entrypoint)["/vms"].post(Nokogiri::XML(builder.to_xml).root.to_s, headers) + begin + vm = RHEVM::client(@api_entrypoint)["/vms"].post(Nokogiri::XML(builder.to_xml).root.to_s, headers) + rescue + if $!.respond_to?(:http_body) + fault = (Nokogiri::XML($!.http_body)/'/fault/detail').first + fault = fault.text.gsub(/\[|\]/, '') if fault + end + fault ||= $!.message + raise RHEVMBackendException::new(fault) + end RHEVM::VM::new(self, Nokogiri::XML(vm).root) end diff --git a/server/lib/deltacloud/drivers/rhevm/rhevm_driver.rb b/server/lib/deltacloud/drivers/rhevm/rhevm_driver.rb index d402bc8..93ba4a5 100644 --- a/server/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +++ b/server/lib/deltacloud/drivers/rhevm/rhevm_driver.rb @@ -37,6 +37,8 @@ class RHEVMDriver < Deltacloud::BaseDriver constraint :max_length, 50 end + feature :instances, :user_data + USER_NAME_MAX = feature(:instances, :user_name).constraints[:max_length] # FIXME: These values are just for ilustration @@ -192,6 +194,11 @@ class RHEVMDriver < Deltacloud::BaseDriver params[:hwp_id] = opts[:hwp_id] if opts[:hwp_id] params[:hwp_memory] = opts[:hwp_memory] if opts[:hwp_memory] params[:hwp_cpu] = opts[:hwp_cpu] if opts[:hwp_cpu] + if opts[:user_data] + # NOTE: Injected data will be Base64 encoded to pass through XML + # attribute. You *need* to decode this file using a script inside guest. + params[:user_data] = opts[:user_data].gsub(/\n/,'') + end convert_instance(client, client.create_vm(image_id, params)) end end -- 1.7.4.1
