From 70296e8b75f0c19f386f3debd3ca39eeef922cda Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Wed, 29 Mar 2023 12:41:15 +0200 Subject: [PATCH] B #6162: Use stdin for datastore drivers in marketplace The import action in the marketplace requires to execute the export datastore action. This commits enables to use stdin to for datastore action with -i options (same as DATASTORE_MAD) (cherry picked from commit dc91241f055bd3f35ce18266058b25cb6b4e11f0) --- src/market_mad/one_market.rb | 160 +++++++++++++++++++++-------------- 1 file changed, 98 insertions(+), 62 deletions(-) diff --git a/src/market_mad/one_market.rb b/src/market_mad/one_market.rb index 62174bd4ca..7e07a67be9 100755 --- a/src/market_mad/one_market.rb +++ b/src/market_mad/one_market.rb @@ -53,7 +53,7 @@ end $LOAD_PATH << RUBY_LIB_LOCATION -require "OpenNebulaDriver" +require 'OpenNebulaDriver' require 'getoptlong' require 'base64' require 'rexml/document' @@ -66,11 +66,11 @@ class MarketPlaceDriver < OpenNebulaDriver # Market Driver Protocol constants ACTION = { - :import => "IMPORT", - :delete => "DELETE", - :log => "LOG", - :monitor => "MONITOR", - :export => "EXPORT" #For Datastore export action + :import => 'IMPORT', + :delete => 'DELETE', + :log => 'LOG', + :monitor => 'MONITOR', + :export => 'EXPORT' # For Datastore export action } # XPATHs for driver messages @@ -78,11 +78,12 @@ class MarketPlaceDriver < OpenNebulaDriver MARKETPLACEAPP_XPATH = '/MARKET_DRIVER_ACTION_DATA/MARKETPLACEAPP' # Register default actions for the protocol - def initialize(market_type, options={}) + def initialize(market_type, options = {}) @options={ :concurrency => 10, :threaded => true, :retries => 0, + :stdin => false, :local_actions => { ACTION[:import] => nil, ACTION[:delete] => nil, @@ -91,9 +92,9 @@ class MarketPlaceDriver < OpenNebulaDriver } }.merge!(options) - super("market/", @options) + super('market/', @options) - if market_type == nil + if market_type.nil? @types = Dir["#{@local_scripts_path}/*/"].map do |d| d.split('/')[-1] end @@ -105,11 +106,11 @@ class MarketPlaceDriver < OpenNebulaDriver @local_ds_scripts_path = File.join(@local_scripts_base_path, 'datastore/') - @one = OpenNebula::Client.new() + @one = OpenNebula::Client.new - register_action(ACTION[:import].to_sym, method("import")) - register_action(ACTION[:delete].to_sym, method("delete")) - register_action(ACTION[:monitor].to_sym,method("monitor")) + register_action(ACTION[:import].to_sym, method('import')) + register_action(ACTION[:delete].to_sym, method('delete')) + register_action(ACTION[:monitor].to_sym, method('monitor')) end ############################################################################ @@ -123,7 +124,7 @@ class MarketPlaceDriver < OpenNebulaDriver xml = decode(drv_message) if xml.nil? - failure(:import, id, "Cannot decode driver message") + failure(:import, id, 'Cannot decode driver message') return end @@ -132,7 +133,7 @@ class MarketPlaceDriver < OpenNebulaDriver mp_mad = xml['MARKETPLACE/MARKET_MAD'] if type.nil? || origin.nil? || mp_mad.nil? - failure(:import, id, "Wrong driver message format") + failure(:import, id, 'Wrong driver message format') return end @@ -140,26 +141,29 @@ class MarketPlaceDriver < OpenNebulaDriver #----------------------------------------------------------------------- # Export marketplace origin to a file path, IMAGE #----------------------------------------------------------------------- - when "IMAGE" then + when 'IMAGE' # ------------ Execute export action from Datastore ---------------- ds_mad = xml['DATASTORE/DS_MAD'] if ds_mad.nil? - failure(:import, id, "Wrong driver message format") + failure(:import, id, 'Wrong driver message format') return end - ds_msg = ""\ + ds_msg = ''\ "#{xml.element_xml('IMAGE')}"\ "#{xml.element_xml('DATASTORE')}"\ - "" + '' - ds_msg64 = Base64::strict_encode64(ds_msg) + result, info = do_action(id, + nil, + ds_mad, + :export, + Base64.strict_encode64(ds_msg), + false, + @options[:stdin]) - result, info = do_action(id, nil, ds_mad, :export, - "#{ds_msg64} #{id}", false) - - if ( result == RESULT[:failure] ) + if result == RESULT[:failure] failure(:import, id, "Error exporting image to file: #{info}") return end @@ -177,6 +181,7 @@ class MarketPlaceDriver < OpenNebulaDriver end # --------------- Import image app into the marketplace ---------------- + # rubocop:disable Style/RedundantInterpolation xml.add_element('/MARKET_DRIVER_ACTION_DATA', 'IMPORT_SOURCE' => "#{info_doc['IMPORT_SOURCE']}", 'MD5' => "#{info_doc['MD5']}", @@ -184,10 +189,15 @@ class MarketPlaceDriver < OpenNebulaDriver 'FORMAT' => "#{info_doc['FORMAT']}", 'DISPOSE' => "#{info_doc['DISPOSE']}", 'DISPOSE_CMD' => "#{info_doc['DISPOSE_CMD']}") + # rubocop:enable Style/RedundantInterpolation - mp_msg64 = Base64::strict_encode64(xml.to_xml) - - rc, info = do_action(id, mp_mad, nil, :import, "#{mp_msg64} #{id}",true) + rc, info = do_action(id, + mp_mad, + nil, + :import, + Base64.strict_encode64(xml.to_xml), + true, + false) send_message(ACTION[:import], rc, id, info) end @@ -199,14 +209,14 @@ class MarketPlaceDriver < OpenNebulaDriver xml = decode(drv_message) if xml.nil? - failure(:import, id, "Cannot decode driver message") + failure(:import, id, 'Cannot decode driver message') return end mp_mad = xml['MARKETPLACE/MARKET_MAD'] if mp_mad.nil? - failure(:delete, id, "Wrong driver message format") + failure(:delete, id, 'Wrong driver message format') return end @@ -217,7 +227,8 @@ class MarketPlaceDriver < OpenNebulaDriver mp_mad, nil, :delete, - "#{drv_message} #{id}", + drv_message, + false, false) send_message(ACTION[:delete], rc, id, info) @@ -233,18 +244,24 @@ class MarketPlaceDriver < OpenNebulaDriver xml = decode(drv_message) if xml.nil? - failure(:monitor, id, "Cannot decode driver message") + failure(:monitor, id, 'Cannot decode driver message') return end mp_mad = xml['MARKETPLACE/MARKET_MAD'] if mp_mad.nil? - failure(:monitor, id, "Wrong driver message format") + failure(:monitor, id, 'Wrong driver message format') return end - rc, info = do_action(id,mp_mad,nil,:monitor,"#{drv_message} #{id}",true) + rc, info = do_action(id, + mp_mad, + nil, + :monitor, + drv_message, + true, + false) send_message(ACTION[:monitor], rc, id, info) end @@ -252,43 +269,55 @@ class MarketPlaceDriver < OpenNebulaDriver private # Check if the selected marketplace driver is enabled in the configuration - def is_available?(market, id, action) + def available?(market, id, action) if @types.include?(market) - return true + true else send_message(ACTION[action], RESULT[:failure], id, - "Marketplace driver '#{market}' not available") - return false + "Marketplace driver '#{market}' not available") + false end end - #Execute marketplace or datastore actions for + # Execute marketplace or datastore actions for # @param id of the app # @param market driver to use # @param datastore driver to use # @param action to invoke from the driver - # @param arguments for the action + # @param drv_action message for the driver, it will be append with id + # @param encode base64 encode returning info + # @param stdin use stdin to pass drv_action and not command line argument + # # @return result and info of the action - def do_action(id, market, datastore, action, arguments, encode) - + # rubocop:disable Metric/ParameterLists + def do_action(id, market, datastore, action, drv_action, encode, stdin) if !datastore.nil? path = File.join(@local_ds_scripts_path, datastore) else - return if not is_available?(market, id, action) + return unless available?(market, id, action) + path = File.join(@local_scripts_path, market) end - cmd = File.join(path, ACTION[action].downcase) - cmd << " " << arguments + if stdin + arguments = " - #{id}" + else + arguments = " #{drv_action} #{id}" + drv_action = nil + end - rc = LocalCommand.run(cmd, log_method(id)) + cmd = File.join(path, ACTION[action].downcase) + cmd << arguments + + rc = LocalCommand.run(cmd, log_method(id), drv_action) result, info = get_info_from_execution(rc) - info = Base64::strict_encode64(info) if encode && result != RESULT[:failure] + info = Base64.strict_encode64(info) if encode && result != RESULT[:failure] - return result, info + [result, info] end + # rubocop:enable Metric/ParameterLists # Decodes the core message and returns the app and market information as # xml documents @@ -299,12 +328,13 @@ class MarketPlaceDriver < OpenNebulaDriver doc = nil if doc.xml_nil? - return doc + doc end def failure(asym, id, message) send_message(ACTION[asym], RESULT[:failure], id, message) end + end ################################################################################ @@ -314,34 +344,40 @@ end ################################################################################ opts = GetoptLong.new( - [ '--threads', '-t', GetoptLong::OPTIONAL_ARGUMENT ], - [ '--market-types', '-m', GetoptLong::OPTIONAL_ARGUMENT ], - [ '--timeout', '-w', GetoptLong::OPTIONAL_ARGUMENT ], - [ '--proxy' '-p', GetoptLong::OPTIONAL_ARGUMENT ] + ['--threads', '-t', GetoptLong::OPTIONAL_ARGUMENT], + ['--market-types', '-m', GetoptLong::OPTIONAL_ARGUMENT], + ['--timeout', '-w', GetoptLong::OPTIONAL_ARGUMENT], + ['--proxy', '-p', GetoptLong::OPTIONAL_ARGUMENT], + ['--stdin', '-i', GetoptLong::NO_ARGUMENT] ) mp_type = nil threads = 15 timeout = nil +stdin = false begin opts.each do |opt, arg| case opt - when '--threads' - threads = arg.to_i - when '--market-types' - mp_type = arg.split(',').map {|a| a.strip } - when '--timeout' - timeout = arg.to_i - when '--proxy' - ENV['http_proxy'] = arg + when '--threads' + threads = arg.to_i + when '--market-types' + mp_type = arg.split(',').map {|a| a.strip } + when '--timeout' + timeout = arg.to_i + when '--proxy' + ENV['http_proxy'] = arg + when '--stdin' + stdin = true end end -rescue +rescue StandardError exit(-1) end mp_driver = MarketPlaceDriver.new(mp_type, :concurrency => threads, - :timeout => timeout) + :timeout => timeout, + :stdin => stdin) mp_driver.start_driver +