This file is indexed.

/usr/lib/one/ruby/TMScript.rb is in opennebula 3.2.1-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# -------------------------------------------------------------------------- #
# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org)             #
#                                                                            #
# Licensed 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 'pp'
require 'open3'
require 'CommandManager'

=begin rdoc

TMPlugin holds the name of the scripts that will be used for each
TransferManager script command. It is basically a hash where keys
are the names of the commands (uppercase) and contain the path of
the script that will be executed for that command.

It also contains some methods to execute the scripts, get the output
of the script (success/failure, error and log messages).

=end
class TMPlugin < Hash
    # If a +scripts_file+ is supplied commands are loaded from it.
    def initialize(scripts_file=nil)
        # Pass nil default value to hash initialization or it will use
        # scripts file as the default value if the key does not exist
        super(nil)
        load_scripts(scripts_file) if scripts_file
    end
   
    # Executes the script associated with the +command+ using
    # specified arguments. +logger+ is a proc that takes a message
    # as its unique argument.
    #
    # Returns:
    # * It will return +nil+ if the +command+ is not defined.
    # * LocalCommand object (exit code and
    #   error message in case of failure)
    #
    # Note: the exit code will be written like this:
    #   ExitCode: 0
    def execute(logger, command, *args)
        # Command is not defined
        return nil if !self[command]
        
        # Generates the line to call the script with all the
        # arguments provided.
        cmd=[self[command], *args].join(" ")

        local_command = LocalCommand.run(cmd, logger)

        logger.call(local_command.stdout) if logger

        local_command
    end
    
    private
    
    # Loads definitions of commands from the configuration file
    def load_scripts(scripts_file)
        scripts_text=""
        
        if File.exist?(scripts_file)
            scripts_text = File.read(scripts_file)
        else
            STDERR.puts("Can not open #{scripts_file}")
            STDERR.flush
            return
        end
        
        one_location=ENV['ONE_LOCATION']

        if one_location == nil 
            tm_commands_location = "/usr/lib/one/tm_commands/"
        else
            tm_commands_location = one_location + "/lib/tm_commands/"
        end
        
        scripts_text.each_line {|line|
            case line
            when /^\s*(#.*)?$/
                # skip empty or commented lines
                next
            when /^\s*(\w+)\s*=\s*(.*)\s*$/
                command = $1.strip.upcase
                path    = $2.strip

                # Prepend default location for tm commands if the path does not
                # start with /
                path = tm_commands_location+path if path[0]!=?/
                
                self[command] = path
            else
                STDERR.puts("Can not parse line: #{line}")
            end
        }
    end
end

# This class will parse and execute TransferManager scripts.
class TMScript
    attr_accessor :lines
    
    # +script_text+ contains the script to be executed.
    # +logger+ is a lambda that receives a message and sends it
    # to OpenNebula server
    def initialize(script_text, logger=nil)
        @lines  = Array.new
        @logger = logger

        parse_script(script_text)
    end
    
    # Executes the script using the TMPlugin specified by +plugin+.
    # Returns an array where first element tells if succeded and the
    # second one is the error message in case of failure.
    def execute(plugin)
        return [true,""] if @lines.empty?
        
        result = @lines.each {|line|
            res = plugin.execute(@logger, *line)

            if !res
                @logger.call("COMMAND not found: #{line.join(" ")}.") if @logger

                res = [false, "COMMAND not found: #{line.join(" ")}."]
            else
                if res.code == 0
                    res = [true, ""]
                else
                    res = [false, res.get_error_message]
                end
            end

            # do not continue if command failed
            break res if !res[0]
        }
        
        result
    end
    
    private
    
    # Gets commands from the script and populates +@lines+
    def parse_script(script_text)
        script_text.each_line {|line|
            # skip if the line is commented
            next if line.match(/^\s*#/)
            # skip if the line is empty
            next if line.match(/^\s*$/)
            
            command=line.split(" ")
            command[0].upcase!
            @lines<< command
        }
    end
end


if $0 == __FILE__

=begin
    require 'one_log'
    
    logger=ONELog.new
    
    log_proc=lambda{|message|
        logger.log("TRANSFER", "0", message)
    }
    
    log_proc.call(<<-EOT)
        Multiple
        lines log
        
        thingy
    EOT
    
=end

    log_proc=lambda{|message|
        puts message
    }

    script_text="

    CLONE localhost:/tmp/source.img ursa:/tmp/one_jfontan/0/hda.img


    CLONE localhost:/tmp/source.img ursa:/tmp/one_jfontan/1/hda.img

    WRONG the program for WRONG does not exist
    ERROR a command not in plugin

    "

    plugin=TMPlugin.new
    plugin["OTHER"]="./tm_clone.sh"
    plugin["CLONE"]="echo"
    plugin["WRONG"]="it_does_not_exist"
 
    scr=TMScript.new(script_text, log_proc)
    pp scr.lines


    scr.execute(plugin)
end