Module: Veewee::Provider::Core::BoxCommand
- Included in:
- Box, Kvm::Box, Parallels::Box, Vmfusion::Box
- Defined in:
- lib/veewee/provider/core/box/scp.rb,
lib/veewee/provider/core/box/ssh.rb,
lib/veewee/provider/core/box/vnc.rb,
lib/veewee/provider/core/box/copy.rb,
lib/veewee/provider/core/box/exec.rb,
lib/veewee/provider/core/box/halt.rb,
lib/veewee/provider/core/box/issh.rb,
lib/veewee/provider/core/box/sudo.rb,
lib/veewee/provider/core/box/build.rb,
lib/veewee/provider/core/box/wincp.rb,
lib/veewee/provider/core/box/winrm.rb,
lib/veewee/provider/core/box/floppy.rb,
lib/veewee/provider/core/box/poweroff.rb,
lib/veewee/provider/core/box/validate_tags.rb
Defined Under Namespace
Classes: Platform
Instance Method Summary collapse
- #check_output_run(command, expected_string) ⇒ Object
- #check_output_sudorun(command, expected_string) ⇒ Object
- #checks_linux ⇒ Object
- #checks_windows ⇒ Object
- #copy_to_box(localfile, remotefile, options = {}) ⇒ Object
- #create_floppy(floppy_filename) ⇒ Object
- #create_wget_vbs_command {|bootstrap_bat.join(" && "), chunk_num += 1| ... } ⇒ Object
-
#escape_and_echo(file_contents) ⇒ Object
escape WIN BATCH special chars and prefixes each line with an echo.
- #exec(command, options = {}) ⇒ Object
- #halt(options = {}) ⇒ Object
- #issh(command = nil, options = {}) ⇒ Object
- #poweroff(options = {}) ⇒ Object
- #run_hook(name) ⇒ Object
- #scp(localfile, remotefile, options = {}) ⇒ Object
- #send_vnc_keycode(vnc, keycode) ⇒ Object
- #ssh(command = nil, options = {}) ⇒ Object
- #ssh_command_string ⇒ Object
- #string_to_vnccode(thestring) ⇒ Object
- #sudo(scriptname) ⇒ Object
- #validate_tags(tags, options) ⇒ Object
- #vnc_type(sequence, host, display = 20) ⇒ Object
- #wget_vbs ⇒ Object
- #wget_vbs_file ⇒ Object
- #wincp(localfile, remotefile, options = {}) ⇒ Object
- #winrm(command = nil, options = {}) ⇒ Object
- #winrm_command_string ⇒ Object
Instance Method Details
#check_output_run(command, expected_string) ⇒ Object
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/veewee/provider/core/box/validate_tags.rb', line 76 def check_output_run(command,expected_string) result = { :command => command, :expected_string => expected_string, :output => nil } begin sshresult = self.exec(command, {:exitcode => '*',:mute => true}) result[:output] = sshresult.stdout result[:match] = ! sshresult.stdout.match(/#{expected_string}/).nil? rescue result[:match] = false end return result end |
#check_output_sudorun(command, expected_string) ⇒ Object
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/veewee/provider/core/box/validate_tags.rb', line 58 def check_output_sudorun(command,expected_string) result = { :command => command, :expected_string => expected_string, :output => nil } begin self.exec("echo '#{command}' > /tmp/validation.sh && chmod a+x /tmp/validation.sh", :mute => true) sshresult = self.exec(self.sudo("/tmp/validation.sh"),:mute => true) result[:output] = sshresult.stdout result[:match] = ! sshresult.stdout.match(/#{expected_string}/).nil? rescue result[:match] = false end return result end |
#checks_linux ⇒ Object
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 |
# File 'lib/veewee/provider/core/box/validate_tags.rb', line 92 def checks_linux return [ { :description => 'Checking user', :tags => [ 'virtualbox','kvm', 'parallels'], :command => 'who am i', :expected_string => definition.ssh_user, :sudo => false }, { :description => 'Checking sudo', :tags => [ 'virtualbox','kvm', 'parallels'], :command => 'whoami', :expected_string => 'root', :sudo => true }, { :description => 'Checking ruby', :tags => [ 'virtualbox','kvm', 'parallels','ruby'], :command => '. /etc/profile ;ruby --version 2> /dev/null 1> /dev/null; echo $?', :expected_string => "0", :sudo => false }, { :description => 'Checking gem', :tags => [ 'virtualbox','kvm', 'parallels','gem'], :command => '. /etc/profile ;gem --version 2> /dev/null 1> /dev/null; echo $?', :expected_string => "0", :sudo => false }, { :description => 'Checking chef', :tags => [ 'chef'], :command => '. /etc/profile ;chef-client --version 2> /dev/null 1>/dev/null; echo $?', :expected_string => "0", :sudo => false }, { :description => 'Checking puppet', :tags => [ 'puppet'], :command => '. /etc/profile ;puppet --version 2> /dev/null 1>/dev/null; echo $?', :expected_string => "0", :sudo => false }, { :description => 'Checking shared folder', :tags => [ 'vagrant'], :command => 'mount|grep veewee-validation; echo $?', :expected_string => "0", :sudo => false } ] end |
#checks_windows ⇒ Object
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 |
# File 'lib/veewee/provider/core/box/validate_tags.rb', line 139 def checks_windows return [ { :description => 'Checking user', :tags => [ 'virtualbox','kvm','vmfusion'], :command => 'whoami', :expected_string => definition.ssh_user, :sudo => false }, { :description => 'Checking ruby', :tags => [ 'virtualbox','kvm','vmfusion'], :command => 'ruby --version > %TEMP%\devnull && echo %ERRORLEVEL%', :expected_string => "0", :sudo => false }, { :description => 'Checking gem', :tags => [ 'virtualbox','kvm','vmfusion'], :command => 'gem --version > %TEMP%\devnull && echo %ERRORLEVEL%', :expected_string => "0", :sudo => false }, { :description => 'Checking chef', :tags => [ 'chef'], :command => 'chef-client --version > %TEMP%\devnull && echo %ERRORLEVEL%', :expected_string => "0", :sudo => false }, ] end |
#copy_to_box(localfile, remotefile, options = {}) ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# File 'lib/veewee/provider/core/box/copy.rb', line 6 def copy_to_box(localfile,remotefile,={}) raise Veewee::Error,"Box is not running" unless self.running? if definition.winrm_user && definition.winrm_password # prefer winrm then self.wincp(localfile,remotefile,) elsif definition.os_type_id =~ /^Windows/ then raise "Trying to transfer #{localfile} to windows machine without 'winrm_user' and 'winrm_password' set in definition." else self.scp(localfile,remotefile,) end end |
#create_floppy(floppy_filename) ⇒ Object
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/veewee/provider/core/box/floppy.rb', line 5 def create_floppy(floppy_filename) # Todo Check for java # Todo check output of commands # Todo allow for .erb templates # Check for floppy unless definition.floppy_files.nil? require 'tmpdir' temp_dir=Dir.mktmpdir definition.floppy_files.each do |filename| full_filename=full_filename=File.join(definition.path,filename) FileUtils.cp("#{full_filename}","#{temp_dir}") end javacode_dir=File.(File.join(__FILE__,'..','..','..','..','..','java')) floppy_file=File.join(definition.path,floppy_filename) if File.exists?(floppy_file) env.logger.info "Removing previous floppy file" FileUtils.rm(floppy_file) end command="java -jar \"#{javacode_dir}/dir2floppy.jar\" \"#{temp_dir}\" \"#{floppy_file}\"" shell_exec("#{command}") end end |
#create_wget_vbs_command {|bootstrap_bat.join(" && "), chunk_num += 1| ... } ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/veewee/provider/core/box/wincp.rb', line 56 def create_wget_vbs_command(&block) bootstrap_bat = [] chunk_num = 0 wget_vbs.each_line do |line| # escape WIN BATCH special chars line.gsub!(/[(<|>)^]/).each{|m| "^#{m}"} # windows commands are limited to 2047 characters if((bootstrap_bat + [line]).join(" && ").size > 2047 ) yield bootstrap_bat.join(" && "), chunk_num += 1 bootstrap_bat = [] end bootstrap_bat << ">> #{wget_vbs_file} (echo.#{line.chomp.strip})" end yield bootstrap_bat.join(" && "), chunk_num += 1 bootstrap_bat = [] end |
#escape_and_echo(file_contents) ⇒ Object
escape WIN BATCH special chars and prefixes each line with an echo
119 120 121 |
# File 'lib/veewee/provider/core/box/wincp.rb', line 119 def escape_and_echo(file_contents) file_contents.gsub(/^(.*)$/, 'echo.\1').gsub(/([(<|>)^])/, '^\1') end |
#exec(command, options = {}) ⇒ Object
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 |
# File 'lib/veewee/provider/core/box/exec.rb', line 16 def exec(command,={}) raise Veewee::Error,"Box is not running" unless self.running? if definition.winrm_user && definition.winrm_password begin =.merge() self.when_winrm_login_works(self.ip_address,.merge()) do result = self.winrm_execute(self.ip_address,command,) return result end rescue RuntimeError => ex env.ui.error "Error executing command #{command} : #{ex}" raise Veewee::WinrmError, ex end else # definition.ssh_user && definition.ssh_password begin =.merge() self.when_ssh_login_works(self.ip_address,) do begin env.logger.info "About to execute remote command #{command} on box #{name} - #{self.ip_address} - #{}" result=self.ssh_execute(self.ip_address,command,) return result rescue RuntimeError => ex env.ui.error "Error executing command #{command} : #{ex}" raise Veewee::SshError, ex end end rescue Net::SSH::AuthenticationFailed => ex # may want to catch winrm auth fails as well env.ui.error "Authentication failure" raise Veewee::SshError, "Authentication failure\n"+ex.inspect end end end |
#halt(options = {}) ⇒ Object
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/veewee/provider/core/box/halt.rb', line 7 def halt(={}) if self.running? if ["force"]==true self.poweroff else if definition.winrm_user && definition.winrm_password # prefer winrm self.exec("#{definition.shutdown_cmd}") else self.exec("echo '#{definition.shutdown_cmd}' > /tmp/shutdown.sh") self.exec("chmod +x /tmp/shutdown.sh") self.exec(sudo("/tmp/shutdown.sh")) end end else raise Veewee::Error,"Box is not running" end end |
#issh(command = nil, options = {}) ⇒ Object
7 8 9 |
# File 'lib/veewee/provider/core/box/issh.rb', line 7 def issh(command=nil,={}) self.ssh(command,.merge({:interactive => true})) end |
#poweroff(options = {}) ⇒ Object
6 7 |
# File 'lib/veewee/provider/core/box/poweroff.rb', line 6 def poweroff(={}) end |
#run_hook(name) ⇒ Object
8 9 10 11 12 13 14 15 16 17 18 19 20 |
# File 'lib/veewee/provider/core/box/build.rb', line 8 def run_hook(name) hooks = definition.instance_variable_get(:@hooks) if ! hooks.nil? hook = hooks[name] if hook.nil? ui.info "Hook ##{name} is not defined" else raise Veewee::Error, "Hook is not callable" if ! hook.respond_to?(:call) ui.info "Running ##{name} hook" hook.call end end end |
#scp(localfile, remotefile, options = {}) ⇒ Object
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/veewee/provider/core/box/scp.rb', line 7 def scp(localfile,remotefile,={}) raise Veewee::Error,"Box is not running" unless self.running? begin =.merge() self.when_ssh_login_works(self.ip_address,) do begin env.logger.info "About to transfer #{localfile} to #{remotefile} to the box #{name} - #{self.ip_address} - #{.inspect}" self.ssh_transfer_file(self.ip_address,localfile,remotefile,) rescue RuntimeError => ex ui.error("Error transfering file #{localfile} failed, possible not enough permissions to write? #{ex}",:prefix => false) raise Veewee::SshError,ex end end rescue Net::SSH::AuthenticationFailed => ex ui.error("Authentication failure",:prefix => false) raise Veewee::SshError,ex end end |
#send_vnc_keycode(vnc, keycode) ⇒ Object
36 37 38 39 40 41 42 43 44 45 |
# File 'lib/veewee/provider/core/box/vnc.rb', line 36 def send_vnc_keycode(vnc,keycode) if keycode.is_a?(Symbol) vnc.key_press keycode sleep 1 else vnc.type_string keycode,{:wait => 0.1} end end |
#ssh(command = nil, options = {}) ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/veewee/provider/core/box/ssh.rb', line 10 def ssh(command=nil,={}) raise Veewee::Error,"Box is not running" unless self.running? host_ip=self.ip_address if ([:interactive]==true) unless host_ip.nil? || host_ip=="" ssh_command="ssh #{()} #{host_ip} #{Shellwords.escape(command) if command}" fg_exec(ssh_command,) else ui.error("Can't ssh into '#{@name} as we couldn't figure out it's ip-address",:prefix => false) end else ={:user => definition.ssh_user,:password => definition.ssh_password, :port => definition.ssh_host_port} [:keys] = ssh_key_to_a(definition.ssh_key) if definition.ssh_key ssh_execute(host_ip, command, ) end end |
#ssh_command_string ⇒ Object
7 8 9 |
# File 'lib/veewee/provider/core/box/exec.rb', line 7 def ssh_command_string "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p #{[:port]} -l #{definition.ssh_user} #{self.ip_address}" end |
#string_to_vnccode(thestring) ⇒ Object
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 |
# File 'lib/veewee/provider/core/box/vnc.rb', line 48 def string_to_vnccode(thestring) # https://github.com/aquasync/ruby-vnc/blob/master/data/keys.yaml special=Hash.new # Specific veewee special['<Wait>'] = :wait # VNC Codes special['<Enter>'] = :return special['<Return>'] = :return special['<Esc>'] = :escape # These still need some work! special['<Backspace>'] = :backspace special['<Spacebar>'] = ' ' special['<Tab>'] = :tab # Hmm, what would the equivalent be here special['<KillX>'] = '1d 38 0e'; special['<Up>'] = :up special['<Down>'] = :down special['<PageUp>'] = :page_up special['<PageDown>'] = :page_down special['<End>'] = :end special['<Insert>'] = :insert special['<Delete>'] = :delete special['<Left>'] = :left special['<Right>'] = :right special['<Home>'] = :home special['<F1>'] = :f1 special['<F2>'] = :f2 special['<F3>'] = :f3 special['<F4>'] = :f4 special['<F5>'] = :f5 special['<F6>'] = :f6 special['<F7>'] = :f7 special['<F8>'] = :f8 special['<F9>'] = :f9 special['<F10>'] = :f10 keycodes=Array.new thestring.gsub!(/ /,"<Spacebar>") until thestring.length == 0 nospecial=true; special.keys.each { |key| if thestring.start_with?(key) #take thestring #check if it starts with a special key + pop special string keycodes<<special[key]; thestring=thestring.slice(key.length,thestring.length-key.length) nospecial=false; break; end } if nospecial code = thestring.slice(0,1) keycodes << code #pop one thestring=thestring.slice(1,thestring.length-1) end end return keycodes end |
#sudo(scriptname) ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 |
# File 'lib/veewee/provider/core/box/sudo.rb', line 6 def sudo(scriptname) if definition.ssh_user=="root" return "#{scriptname}" else command=definition.sudo_cmd newcommand=command.gsub(/%p/,"#{definition.ssh_password}") newcommand.gsub!(/%u/,"#{definition.ssh_user}") newcommand.gsub!(/%f/,"#{scriptname}") return newcommand end end |
#validate_tags(tags, options) ⇒ Object
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 |
# File 'lib/veewee/provider/core/box/validate_tags.rb', line 6 def (,) unless self.exists? ui.error "Error:: You tried to validate box '#{name}' but it does not exist" exit -1 end unless self.running? ui.error "Error:: You tried to validate box '#{name}' but it is not running" exit -1 end if definition.winrm_user && definition.winrm_password # prefer winrm checks = checks_windows else checks = checks_linux end # Some reject here based on tags checks.reject! { |c| tagged = false c[:tags].each do |t| tagged = true if .include?(t) end ! tagged } # Assume clean exitcode exitcode = 0 # Loop over checks checks.each do |check| if check[:sudo] result = check_output_sudorun(check[:command],check[:expected_string]) else result = check_output_run(check[:command],check[:expected_string]) end if result[:match] ui.success("#{check[:description]} - OK") else ui.error("#{check[:description]} - FAILED") ui.error("Command: #{check[:command]}") ui.error("Expected string #{check[:expected_string]}") ui.error("Output: #{check[:output]}") exitcode = -1 end end exit -1 if exitcode < 0 end |
#vnc_type(sequence, host, display = 20) ⇒ Object
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/veewee/provider/core/box/vnc.rb', line 12 def vnc_type(sequence,host,display=20) counter=0 env.logger.info "Opening VNC #{host} on display #{display}" Net::VNC.open("#{host}:#{display}",{:wait => 0.001}) do |vnc| sequence.each { |s| counter=counter+1 ui.info "Typing:[#{counter}]: "+s keycodes=string_to_vnccode(s) keycodes.each do |keycode| if keycode==:wait sleep 1 else send_vnc_keycode(vnc,keycode) end end } ui.info "Done typing." ui.info "" end end |
#wget_vbs ⇒ Object
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 |
# File 'lib/veewee/provider/core/box/wincp.rb', line 73 def wget_vbs wget_vbs = <<-WGET url = WScript.Arguments.Named("url") path = WScript.Arguments.Named("path") Set objXMLHTTP = CreateObject("MSXML2.ServerXMLHTTP") Set wshShell = CreateObject( "WScript.Shell" ) Set objUserVariables = wshShell.Environment("USER") rem http proxy is optional rem attempt to read from HTTP_PROXY env var first On Error Resume Next If NOT (objUserVariables("HTTP_PROXY") = "") Then objXMLHTTP.setProxy 2, objUserVariables("HTTP_PROXY") rem fall back to named arg ElseIf NOT (WScript.Arguments.Named("proxy") = "") Then objXMLHTTP.setProxy 2, WScript.Arguments.Named("proxy") End If On Error Goto 0 objXMLHTTP.open "GET", url, false objXMLHTTP.send() If objXMLHTTP.Status = 200 Then Set objADOStream = CreateObject("ADODB.Stream") objADOStream.Open objADOStream.Type = 1 objADOStream.Write objXMLHTTP.ResponseBody objADOStream.Position = 0 Set objFSO = Createobject("Scripting.FileSystemObject") If objFSO.Fileexists(path) Then objFSO.DeleteFile path Set objFSO = Nothing objADOStream.SaveToFile path objADOStream.Close Set objADOStream = Nothing End if Set objXMLHTTP = Nothing WGET #escape_and_echo(win_wget) wget_vbs end |
#wget_vbs_file ⇒ Object
52 53 54 |
# File 'lib/veewee/provider/core/box/wincp.rb', line 52 def wget_vbs_file "%TEMP%\\\\wget.vbs" end |
#wincp(localfile, remotefile, options = {}) ⇒ Object
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 |
# File 'lib/veewee/provider/core/box/wincp.rb', line 9 def wincp(localfile,remotefile,={}) raise Veewee::Error,"Box is not running" unless self.running? if self.exec("cmd.exe /C dir #{wget_vbs_file} > NUL",{:exitcode=>"*"}).status != 0 env.ui.warn "Creating wget.vbs" create_wget_vbs_command do |command_chunk, chunk_num| self.exec(%Q!cmd.exe /C echo "Rendering #{wget_vbs_file} chunk #{chunk_num}" && #{command_chunk}!) end end # Calculate an available kickstart port which we will use for wincp definition.kickstart_port = "7000" if definition.kickstart_port.nil? guessed_port=guess_free_port(definition.kickstart_port.to_i,7199).to_s if guessed_port.to_s!=definition.kickstart_port env.ui.warn "Changing wincp port from #{definition.kickstart_port} to #{guessed_port}" definition.kickstart_port=guessed_port.to_s end urlpath = localfile.to_slug urlpath = urlpath.start_with?('/') ? urlpath : '/' + urlpath begin self.when_winrm_login_works(self.ip_address,.merge()) do env.ui.warn "Spinning up an allow_for_http_request on http://#{host_ip_as_seen_by_guest}:#{definition.kickstart_port}#{localfile} at URL #{urlpath}" allow_for_http_request( localfile, urlpath, { :port => definition.kickstart_port, :timeout => 300, } ) env.ui.info "Going to try and copy #{localfile} to #{remotefile.inspect}" self.exec("cmd.exe /C cscript %TEMP%\\wget.vbs /url:http://#{host_ip_as_seen_by_guest}:#{definition.kickstart_port}#{urlpath} /path:#{remotefile}") # while true do # sleep 0.1 # used to debug # end end end end |
#winrm(command = nil, options = {}) ⇒ Object
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 |
# File 'lib/veewee/provider/core/box/winrm.rb', line 8 def winrm(command=nil,={}) raise Veewee::Error,"Box is not running" unless self.running? ={:user => definition.winrm_user,:password => definition.winrm_password, :port => definition.winrm_host_port, :exitcode => '*'} if (command.nil?) env.ui.info "This is a simple interactive shell" env.ui.info "To exit interactive mode, use 'quit!'" while 1 command = ui.ask("veewee>") case command.strip when 'quit!' env.ui.info 'Bye!' break else winrm_execute(self.ip_address,command,.merge()) end end else winrm_execute(self.ip_address,command,.merge()) end end |
#winrm_command_string ⇒ Object
11 12 13 14 |
# File 'lib/veewee/provider/core/box/exec.rb', line 11 def winrm_command_string "knife winrm -m #{self.ip_address} -P #{[:port]} -x #{definition.winrm_user}" + " -P #{definition.winrm_password} COMMAND" end |