Class: RemoteSystem
Overview
Copyright © 2013-2015 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
Returns the value of attribute host.
Instance Method Summary collapse
-
#connect ⇒ Object
Tries to connect to the remote system as root (without a password or passphrase) and raises an Machinery::Errors::SshConnectionFailed exception when it’s not successful.
-
#initialize(host) ⇒ RemoteSystem
constructor
A new instance of RemoteSystem.
-
#read_file(file) ⇒ Object
Reads 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
Methods inherited from System
#check_requirement, #create_archive, for, #has_command?, #run_script
Constructor Details
#initialize(host) ⇒ RemoteSystem
Returns a new instance of RemoteSystem.
21 22 23 24 25 |
# File 'lib/remote_system.rb', line 21 def initialize(host) @host = host connect end |
Instance Attribute Details
#host ⇒ Object
Returns the value of attribute host.
19 20 21 |
# File 'lib/remote_system.rb', line 19 def host @host end |
Instance Method Details
#connect ⇒ Object
Tries to connect to the remote system as root (without a password or passphrase) and raises an Machinery::Errors::SshConnectionFailed exception when it’s not successful.
78 79 80 81 82 83 84 85 86 87 |
# File 'lib/remote_system.rb', line 78 def connect LoggedCheetah.run "ssh", "-q", "-o", "BatchMode=yes", "root@#{host}" rescue Cheetah::ExecutionFailed raise Machinery::Errors::SshConnectionFailed.new( "Could not establish SSH connection to host '#{host}'. Please make sure that " \ "you can connect non-interactively as root, e.g. using ssh-agent.\n\n" \ "To copy your default ssh key to the machine run:\n" \ "ssh-copy-id root@#{host}" ) end |
#read_file(file) ⇒ Object
Reads a file from the System. Returns nil if it does not exist.
106 107 108 109 110 111 112 113 114 115 |
# File 'lib/remote_system.rb', line 106 def read_file(file) run_command("cat", file, stdout: :capture) rescue Cheetah::ExecutionFailed => e if e.status.exitstatus == 1 # File not found, return nil return else raise end end |
#requires_root? ⇒ Boolean
27 28 29 |
# File 'lib/remote_system.rb', line 27 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.
93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/remote_system.rb', line 93 def retrieve_files(filelist, destination) source="root@#{host}:/" begin LoggedCheetah.run("rsync", "-e", "ssh", "--chmod=go-rwx", "--files-from=-", source, destination, :stdout => :capture, :stdin => filelist.join("\n") ) 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
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 |
# File 'lib/remote_system.rb', line 31 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 = LoggedCheetah end cheetah_class.run("ssh", "root@#{host}", "LC_ALL=C", *piped_args, ) end |