Class: Machinery::RemoteSystem
Overview
Copyright © 2013-2016 SUSE LLC
This program is free software; you can redistribute it and/or modify it under the terms of version 3 of the GNU General Public License as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, contact SUSE LLC.
To contact SUSE about this file by physical or electronic mail, you may find current contact information at www.suse.com
Instance Attribute Summary collapse
-
#host ⇒ Object
readonly
Returns the value of attribute host.
-
#remote_user ⇒ Object
readonly
Returns the value of attribute remote_user.
-
#ssh_identity_file ⇒ Object
readonly
Returns the value of attribute ssh_identity_file.
-
#ssh_port ⇒ Object
readonly
Returns the value of attribute ssh_port.
Attributes inherited from System
Instance Method Summary collapse
- #check_retrieve_files_dependencies ⇒ Object
- #connect ⇒ Object
-
#initialize(host, opts = {}) ⇒ RemoteSystem
constructor
A new instance of RemoteSystem.
-
#inject_file(source, destination) ⇒ Object
Copies a file to the system.
-
#read_file(file, options = {}) ⇒ Object
Reads a file from the System.
-
#remove_file(file) ⇒ Object
Removes a file from the system.
- #requires_root? ⇒ Boolean
-
#retrieve_files(filelist, destination) ⇒ Object
Retrieves files specified in filelist from the remote system and raises an Machinery::Errors::RsyncFailed exception when it’s not successful.
- #run_command(*args) ⇒ Object
- #type ⇒ Object
Methods inherited from System
#arch, #check_create_archive_dependencies, #check_requirement, #create_archive, for, #has_command?, #managed_files_database, #run_command_with_progress, #run_script, #run_script_with_progress
Constructor Details
#initialize(host, opts = {}) ⇒ RemoteSystem
Returns a new instance of RemoteSystem.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/remote_system.rb', line 25 def initialize(host, opts = {}) = { remote_user: "root", ssh_port: nil, ssh_identity_file: nil }.merge(opts) @host = host @remote_user = [:remote_user] @ssh_port = [:ssh_port] @ssh_identity_file = [:ssh_identity_file] connect end |
Instance Attribute Details
#host ⇒ Object (readonly)
Returns the value of attribute host.
19 20 21 |
# File 'lib/remote_system.rb', line 19 def host @host end |
#remote_user ⇒ Object (readonly)
Returns the value of attribute remote_user.
19 20 21 |
# File 'lib/remote_system.rb', line 19 def remote_user @remote_user end |
#ssh_identity_file ⇒ Object (readonly)
Returns the value of attribute ssh_identity_file.
19 20 21 |
# File 'lib/remote_system.rb', line 19 def ssh_identity_file @ssh_identity_file end |
#ssh_port ⇒ Object (readonly)
Returns the value of attribute ssh_port.
19 20 21 |
# File 'lib/remote_system.rb', line 19 def ssh_port @ssh_port end |
Instance Method Details
#check_retrieve_files_dependencies ⇒ Object
141 142 143 144 |
# File 'lib/remote_system.rb', line 141 def check_retrieve_files_dependencies Machinery::LocalSystem.validate_existence_of_command("rsync", "rsync") check_requirement("rsync", "--version") end |
#connect ⇒ Object
44 45 46 47 |
# File 'lib/remote_system.rb', line 44 def connect check_connection check_sudo if sudo_required? end |
#inject_file(source, destination) ⇒ Object
Copies a file to the system
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/remote_system.rb', line 163 def inject_file(source, destination) destination = "#{remote_user}@#{host}:#{destination}" cmd = [ *build_command(:scp), source, destination ] begin Machinery::LoggedCheetah.run(*cmd) rescue Cheetah::ExecutionFailed => e raise Machinery::Errors::InjectFileFailed.new( "Could not inject file '#{source}' to host '#{host}'.\nError: #{e}" ) end end |
#read_file(file, options = {}) ⇒ Object
Reads a file from the System. Returns nil if it does not exist.
147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/remote_system.rb', line 147 def read_file(file, = {}) = { stdout: :capture, privileged: .fetch(:privileged, false) } run_command("cat", file, ) rescue Cheetah::ExecutionFailed => e if e.status.exitstatus == 1 # File not found, return nil return else raise end end |
#remove_file(file) ⇒ Object
Removes a file from the system
182 183 184 185 186 187 188 |
# File 'lib/remote_system.rb', line 182 def remove_file(file) run_command("rm", file) rescue Cheetah::ExecutionFailed => e raise Machinery::Errors::RemoveFileFailed.new( "Could not remove file '#{file}' on host '#{host}'.\nError: #{e}" ) end |
#requires_root? ⇒ Boolean
40 41 42 |
# File 'lib/remote_system.rb', line 40 def requires_root? false end |
#retrieve_files(filelist, destination) ⇒ Object
Retrieves files specified in filelist from the remote system and raises an Machinery::Errors::RsyncFailed exception when it’s not successful. Destination is the directory where to put the files.
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 |
# File 'lib/remote_system.rb', line 112 def retrieve_files(filelist, destination) source = "#{remote_user}@#{host}:/" rsync_path = if sudo_required? "sudo -n rsync" else "rsync" end cmd = [ "rsync", "-e", build_command(:ssh).join(" "), "--chmod=go-rwx", "--files-from=-", "--rsync-path=#{rsync_path}", source, destination, stdout: :capture, stdin: filelist.join("\n") ] begin Machinery::LoggedCheetah.run(*cmd) rescue Cheetah::ExecutionFailed => e raise Machinery::Errors::RsyncFailed.new( "Could not rsync files from host '#{host}'.\n" \ "Error: #{e}" ) end end |
#run_command(*args) ⇒ Object
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 |
# File 'lib/remote_system.rb', line 49 def run_command(*args) = args.last.is_a?(Hash) ? args.pop : {} # There are three valid ways how to call Cheetah.run, whose interface this # method mimics. The following code ensures that the "commands" variable # consistently (in all three cases) contains an array of arrays specifying # commands and their arguments. # # See comment in Cheetah.build_commands for more detailed explanation: # # https://github.com/openSUSE/cheetah/blob/0cd3f88c1210305e87dfc4852bb83040e82d783f/lib/cheetah.rb#L395 # commands = args.all? { |a| a.is_a?(Array) } ? args : [args] # When ssh executes commands, it passes them through shell expansion. For # example, compare # # $ echo '$HOME' # $HOME # # with # # $ ssh localhost echo '$HOME' # /home/dmajda # # To mitigate that and maintain usual Cheetah semantics, we need to protect # the command and its arguments using another layer of escaping. escaped_commands = commands.map do |command| command.map { |c| Shellwords.escape(c) } end # Arrange the commands in a way that allows piped commands trough ssh. piped_args = escaped_commands[0..-2].flat_map do |command| [*command, "|"] end + escaped_commands.last if [:disable_logging] cheetah_class = Cheetah else cheetah_class = Machinery::LoggedCheetah end sudo = ["sudo", "-n"] if [:privileged] && sudo_required? cmds = [ *build_command(:ssh), "#{remote_user}@#{host}", "-o", \ "LogLevel=ERROR", sudo, "LANGUAGE=", "LC_ALL=#{locale}", *piped_args, ].compact.flatten begin cheetah_class.run(*cmds) rescue Cheetah::ExecutionFailed => e ssh_error_regex = /Connection refused|Connection reset by peer|Broken pipe|Network is unreachable/ if e.stderr && e.stderr =~ ssh_error_regex raise Machinery::Errors::SshConnectionDisrupted.new("\nSSH ERROR: #{e.stderr}") else raise end end end |
#type ⇒ Object
21 22 23 |
# File 'lib/remote_system.rb', line 21 def type "remote" end |