From 298a08d6566dea918e40d570c7ece89a36a5103d Mon Sep 17 00:00:00 2001 From: prabhu-das Date: Tue, 24 Jun 2014 13:48:57 +0530 Subject: [PATCH 1/6] knife-ec2 master to knife-ec2 knife-cloud sync --- .../chefbootstrap/ssh_bootstrap_protocol.rb | 91 ++++++++++++++----- lib/chef/knife/cloud/command.rb | 2 +- lib/chef/knife/cloud/fog/service.rb | 2 +- lib/chef/knife/cloud/server/create_command.rb | 4 +- spec/unit/ssh_bootstrap_protocol_spec.rb | 3 + 5 files changed, 74 insertions(+), 28 deletions(-) diff --git a/lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb b/lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb index 5fb22d1..07a9685 100644 --- a/lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb +++ b/lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb @@ -21,11 +21,12 @@ require 'chef/knife/core/windows_bootstrap_context' require 'chef/knife/bootstrap' + class Chef class Knife class Cloud class SshBootstrapProtocol < BootstrapProtocol - + def initialize(config) @bootstrap = (config[:image_os_type] == 'linux') ? Chef::Knife::Bootstrap.new : Chef::Knife::BootstrapWindowsSsh.new super @@ -47,40 +48,82 @@ def init_bootstrap_options def wait_for_server_ready print "\n#{ui.color("Waiting for sshd to host (#{@config[:bootstrap_ip_address]})", :magenta)}" - print(".") until tcp_test_ssh(@config[:bootstrap_ip_address]) { - sleep @initial_sleep_delay ||= 10 - puts("done") - } + + # The ssh_gateway & subnet_id are currently supported only in EC2. + if config[:ssh_gateway] + print(".") until tunnel_test_ssh(@config[:bootstrap_ip_address]) { + @initial_sleep_delay = locate_config_value(:subnet_id) ? 40 : 10 + sleep @initial_sleep_delay + puts("done") + } + else + print(".") until tcp_test_ssh(@config[:bootstrap_ip_address]) { + @initial_sleep_delay = locate_config_value(:subnet_id) ? 40 : 10 + sleep @initial_sleep_delay + puts("done") + } + end end def tcp_test_ssh(hostname) tcp_socket = TCPSocket.new(hostname, 22) readable = IO.select([tcp_socket], nil, nil, 5) if readable - Chef::Log.debug("sshd accepting connections on #{hostname}, banner is #{tcp_socket.gets}") - yield - true + ssh_banner = tcp_socket.gets + if ssh_banner.nil? or ssh_banner.empty? + false + else + Chef::Log.debug("ssh accepting connections on #{hostname}, banner is #{tcp_socket.gets}") + yield + true + end else false end - rescue Errno::ETIMEDOUT - false - rescue Errno::EPERM - false - rescue Errno::ECONNREFUSED - sleep 2 - false - rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH - sleep 2 - false - rescue Errno::ENETUNREACH - sleep 2 - false - ensure - tcp_socket && tcp_socket.close + rescue Errno::ETIMEDOUT + Chef::Log.debug("ssh timed out: #{hostname}") + false + rescue Errno::EPERM + Chef::Log.debug("ssh timed out: #{hostname}") + false + rescue Errno::ECONNREFUSED + Chef::Log.debug("ssh failed to connect: #{hostname}") + sleep 2 + false + rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH + Chef::Log.debug("ssh failed to connect: #{hostname}") + sleep 2 + false + rescue Errno::ENETUNREACH + Chef::Log.debug("ssh failed to connect: #{hostname}") + sleep 2 + false + # This happens on some mobile phone networks + rescue Errno::ECONNRESET + Chef::Log.debug("ssh reset its connection: #{hostname}") + sleep 2 + false + ensure + tcp_socket && tcp_socket.close + end + end + + def tunnel_test_ssh(hostname, &block) + gw_host, gw_user = @config[:ssh_gateway].split('@').reverse + gw_host, gw_port = gw_host.split(':') + gateway = Net::SSH::Gateway.new(gw_host, gw_user, :port => gw_port || 22) + status = false + gateway.open(hostname, config[:ssh_port]) do |local_tunnel_port| + status = tcp_test_ssh('localhost', local_tunnel_port, &block) + end + status + rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, IOError + sleep 2 + false + rescue Errno::EPERM, Errno::ETIMEDOUT + false end - end end end end diff --git a/lib/chef/knife/cloud/command.rb b/lib/chef/knife/cloud/command.rb index 212f86f..7e4fc76 100644 --- a/lib/chef/knife/cloud/command.rb +++ b/lib/chef/knife/cloud/command.rb @@ -32,7 +32,7 @@ def run begin # Set dafult config set_default_config - + # validate compulsory params validate! diff --git a/lib/chef/knife/cloud/fog/service.rb b/lib/chef/knife/cloud/fog/service.rb index 2a0cc86..34c084f 100644 --- a/lib/chef/knife/cloud/fog/service.rb +++ b/lib/chef/knife/cloud/fog/service.rb @@ -93,10 +93,10 @@ def create_server(options = {}) def delete_server(server_name) begin server = get_server(server_name) - msg_pair("Instance Name", get_server_name(server)) msg_pair("Instance ID", server.id) + puts "ser" puts "\n" ui.confirm("Do you really want to delete this server") diff --git a/lib/chef/knife/cloud/server/create_command.rb b/lib/chef/knife/cloud/server/create_command.rb index 6d07d9b..38acff8 100644 --- a/lib/chef/knife/cloud/server/create_command.rb +++ b/lib/chef/knife/cloud/server/create_command.rb @@ -51,7 +51,7 @@ def validate_params! error_message = "" raise CloudExceptions::ValidationError, error_message if errors.each{|e| ui.error(e); error_message = "#{error_message} #{e}."}.any? end - + def before_exec_command begin post_connection_validations @@ -86,7 +86,7 @@ def after_exec_command raise e rescue => e error_message = "Check if --bootstrap-protocol and --image-os-type is correct. #{e.message}" - ui.fatal(error_message) + ui.fatal(error_message) cleanup_on_failure raise e, error_message end diff --git a/spec/unit/ssh_bootstrap_protocol_spec.rb b/spec/unit/ssh_bootstrap_protocol_spec.rb index 3ede113..8783197 100644 --- a/spec/unit/ssh_bootstrap_protocol_spec.rb +++ b/spec/unit/ssh_bootstrap_protocol_spec.rb @@ -76,12 +76,15 @@ end describe "#tcp_test_ssh" do + it "return true" do tcpSocket = double() allow(tcpSocket).to receive(:close).and_return(true) allow(tcpSocket).to receive(:gets).and_return(true) allow(TCPSocket).to receive(:new).and_return(tcpSocket) allow(IO).to receive(:select).and_return(true) + allow(tcpSocket.gets).to receive(:nil?).and_return(false) + allow(tcpSocket.gets).to receive(:empty?).and_return(false) expect(@instance.tcp_test_ssh("localhost"){}).to be(true) end From 2661838fae8a6dea89062d30ee67538d26cf5c37 Mon Sep 17 00:00:00 2001 From: prabhu-das Date: Tue, 24 Jun 2014 18:06:51 +0530 Subject: [PATCH 2/6] fixing vpc_mode issue --- lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb b/lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb index 07a9685..bd053f1 100644 --- a/lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb +++ b/lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb @@ -52,13 +52,13 @@ def wait_for_server_ready # The ssh_gateway & subnet_id are currently supported only in EC2. if config[:ssh_gateway] print(".") until tunnel_test_ssh(@config[:bootstrap_ip_address]) { - @initial_sleep_delay = locate_config_value(:subnet_id) ? 40 : 10 + @initial_sleep_delay = !!locate_config_value(:subnet_id) ? 40 : 10 sleep @initial_sleep_delay puts("done") } else print(".") until tcp_test_ssh(@config[:bootstrap_ip_address]) { - @initial_sleep_delay = locate_config_value(:subnet_id) ? 40 : 10 + @initial_sleep_delay = !!locate_config_value(:subnet_id) ? 40 : 10 sleep @initial_sleep_delay puts("done") } From 5cef1a353613b7e4f2a463ba6c113f81a9ca8244 Mon Sep 17 00:00:00 2001 From: prabhu-das Date: Tue, 24 Jun 2014 13:48:57 +0530 Subject: [PATCH 3/6] knife-ec2 master to knife-ec2 knife-cloud sync --- .../chefbootstrap/ssh_bootstrap_protocol.rb | 91 ++++++++++++++----- lib/chef/knife/cloud/command.rb | 2 +- lib/chef/knife/cloud/fog/service.rb | 2 +- lib/chef/knife/cloud/server/create_command.rb | 4 +- spec/unit/ssh_bootstrap_protocol_spec.rb | 3 + 5 files changed, 74 insertions(+), 28 deletions(-) diff --git a/lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb b/lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb index c26dc44..5646d0e 100644 --- a/lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb +++ b/lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb @@ -21,11 +21,12 @@ require 'chef/knife/core/windows_bootstrap_context' require 'chef/knife/bootstrap' + class Chef class Knife class Cloud class SshBootstrapProtocol < BootstrapProtocol - + def initialize(config) @bootstrap = (config[:image_os_type] == 'linux') ? Chef::Knife::Bootstrap.new : Chef::Knife::BootstrapWindowsSsh.new super @@ -46,40 +47,82 @@ def init_bootstrap_options def wait_for_server_ready print "\n#{ui.color("Waiting for sshd to host (#{@config[:bootstrap_ip_address]})", :magenta)}" - print(".") until tcp_test_ssh(@config[:bootstrap_ip_address]) { - sleep @initial_sleep_delay ||= 10 - puts("done") - } + + # The ssh_gateway & subnet_id are currently supported only in EC2. + if config[:ssh_gateway] + print(".") until tunnel_test_ssh(@config[:bootstrap_ip_address]) { + @initial_sleep_delay = locate_config_value(:subnet_id) ? 40 : 10 + sleep @initial_sleep_delay + puts("done") + } + else + print(".") until tcp_test_ssh(@config[:bootstrap_ip_address]) { + @initial_sleep_delay = locate_config_value(:subnet_id) ? 40 : 10 + sleep @initial_sleep_delay + puts("done") + } + end end def tcp_test_ssh(hostname) tcp_socket = TCPSocket.new(hostname, 22) readable = IO.select([tcp_socket], nil, nil, 5) if readable - Chef::Log.debug("sshd accepting connections on #{hostname}, banner is #{tcp_socket.gets}") - yield - true + ssh_banner = tcp_socket.gets + if ssh_banner.nil? or ssh_banner.empty? + false + else + Chef::Log.debug("ssh accepting connections on #{hostname}, banner is #{tcp_socket.gets}") + yield + true + end else false end - rescue Errno::ETIMEDOUT - false - rescue Errno::EPERM - false - rescue Errno::ECONNREFUSED - sleep 2 - false - rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH - sleep 2 - false - rescue Errno::ENETUNREACH - sleep 2 - false - ensure - tcp_socket && tcp_socket.close + rescue Errno::ETIMEDOUT + Chef::Log.debug("ssh timed out: #{hostname}") + false + rescue Errno::EPERM + Chef::Log.debug("ssh timed out: #{hostname}") + false + rescue Errno::ECONNREFUSED + Chef::Log.debug("ssh failed to connect: #{hostname}") + sleep 2 + false + rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH + Chef::Log.debug("ssh failed to connect: #{hostname}") + sleep 2 + false + rescue Errno::ENETUNREACH + Chef::Log.debug("ssh failed to connect: #{hostname}") + sleep 2 + false + # This happens on some mobile phone networks + rescue Errno::ECONNRESET + Chef::Log.debug("ssh reset its connection: #{hostname}") + sleep 2 + false + ensure + tcp_socket && tcp_socket.close + end + end + + def tunnel_test_ssh(hostname, &block) + gw_host, gw_user = @config[:ssh_gateway].split('@').reverse + gw_host, gw_port = gw_host.split(':') + gateway = Net::SSH::Gateway.new(gw_host, gw_user, :port => gw_port || 22) + status = false + gateway.open(hostname, config[:ssh_port]) do |local_tunnel_port| + status = tcp_test_ssh('localhost', local_tunnel_port, &block) + end + status + rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, IOError + sleep 2 + false + rescue Errno::EPERM, Errno::ETIMEDOUT + false end - end end end end diff --git a/lib/chef/knife/cloud/command.rb b/lib/chef/knife/cloud/command.rb index 212f86f..7e4fc76 100644 --- a/lib/chef/knife/cloud/command.rb +++ b/lib/chef/knife/cloud/command.rb @@ -32,7 +32,7 @@ def run begin # Set dafult config set_default_config - + # validate compulsory params validate! diff --git a/lib/chef/knife/cloud/fog/service.rb b/lib/chef/knife/cloud/fog/service.rb index 2a0cc86..34c084f 100644 --- a/lib/chef/knife/cloud/fog/service.rb +++ b/lib/chef/knife/cloud/fog/service.rb @@ -93,10 +93,10 @@ def create_server(options = {}) def delete_server(server_name) begin server = get_server(server_name) - msg_pair("Instance Name", get_server_name(server)) msg_pair("Instance ID", server.id) + puts "ser" puts "\n" ui.confirm("Do you really want to delete this server") diff --git a/lib/chef/knife/cloud/server/create_command.rb b/lib/chef/knife/cloud/server/create_command.rb index 4799d15..0e35a71 100644 --- a/lib/chef/knife/cloud/server/create_command.rb +++ b/lib/chef/knife/cloud/server/create_command.rb @@ -51,7 +51,7 @@ def validate_params! error_message = "" raise CloudExceptions::ValidationError, error_message if errors.each{|e| ui.error(e); error_message = "#{error_message} #{e}."}.any? end - + def before_exec_command begin post_connection_validations @@ -86,7 +86,7 @@ def after_exec_command raise e rescue => e error_message = "Check if --bootstrap-protocol and --image-os-type is correct. #{e.message}" - ui.fatal(error_message) + ui.fatal(error_message) cleanup_on_failure raise e, error_message end diff --git a/spec/unit/ssh_bootstrap_protocol_spec.rb b/spec/unit/ssh_bootstrap_protocol_spec.rb index 3ede113..8783197 100644 --- a/spec/unit/ssh_bootstrap_protocol_spec.rb +++ b/spec/unit/ssh_bootstrap_protocol_spec.rb @@ -76,12 +76,15 @@ end describe "#tcp_test_ssh" do + it "return true" do tcpSocket = double() allow(tcpSocket).to receive(:close).and_return(true) allow(tcpSocket).to receive(:gets).and_return(true) allow(TCPSocket).to receive(:new).and_return(tcpSocket) allow(IO).to receive(:select).and_return(true) + allow(tcpSocket.gets).to receive(:nil?).and_return(false) + allow(tcpSocket.gets).to receive(:empty?).and_return(false) expect(@instance.tcp_test_ssh("localhost"){}).to be(true) end From b3ea9276477b8b0adaf71f9f7628eec4ebbb3982 Mon Sep 17 00:00:00 2001 From: prabhu-das Date: Tue, 24 Jun 2014 18:06:51 +0530 Subject: [PATCH 4/6] fixing vpc_mode issue --- lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb b/lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb index 5646d0e..ab8461f 100644 --- a/lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb +++ b/lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb @@ -51,13 +51,13 @@ def wait_for_server_ready # The ssh_gateway & subnet_id are currently supported only in EC2. if config[:ssh_gateway] print(".") until tunnel_test_ssh(@config[:bootstrap_ip_address]) { - @initial_sleep_delay = locate_config_value(:subnet_id) ? 40 : 10 + @initial_sleep_delay = !!locate_config_value(:subnet_id) ? 40 : 10 sleep @initial_sleep_delay puts("done") } else print(".") until tcp_test_ssh(@config[:bootstrap_ip_address]) { - @initial_sleep_delay = locate_config_value(:subnet_id) ? 40 : 10 + @initial_sleep_delay = !!locate_config_value(:subnet_id) ? 40 : 10 sleep @initial_sleep_delay puts("done") } From aae0ef2d1b222f465519a53f42a989cb5c0005b0 Mon Sep 17 00:00:00 2001 From: prabhu-das Date: Fri, 18 Jul 2014 21:44:45 +0530 Subject: [PATCH 5/6] Added changes related to ssh_gateway configuration for bootstrap --- .../cloud/chefbootstrap/bootstrap_options.rb | 10 +- .../chefbootstrap/ssh_bootstrap_protocol.rb | 128 ++++++++++++------ lib/chef/knife/cloud/server/create_command.rb | 2 +- spec/unit/server_create_command_spec.rb | 4 +- spec/unit/ssh_bootstrap_protocol_spec.rb | 12 +- 5 files changed, 106 insertions(+), 50 deletions(-) diff --git a/lib/chef/knife/cloud/chefbootstrap/bootstrap_options.rb b/lib/chef/knife/cloud/chefbootstrap/bootstrap_options.rb index a24eb5a..bb38876 100644 --- a/lib/chef/knife/cloud/chefbootstrap/bootstrap_options.rb +++ b/lib/chef/knife/cloud/chefbootstrap/bootstrap_options.rb @@ -54,13 +54,19 @@ def self.included(includer) :short => "-p PORT", :long => "--ssh-port PORT", :description => "The ssh port", - :proc => Proc.new { |key| Chef::Config[:knife][:ssh_port] = key } + :proc => Proc.new { |key| Chef::Config[:knife][:ssh_port] = key }, + :default => "22" option :ssh_gateway, :long => "--ssh-gateway GATEWAY", - :description => "The ssh gateway", + :description => "The ssh gateway server. Any proxies configured in your ssh config are automatically used by default.", :proc => Proc.new { |key| Chef::Config[:knife][:ssh_gateway] = key } + option :ssh_gateway_identity, + :long => "--ssh-gateway-identity IDENTITY_FILE", + :description => "The private key for ssh gateway server", + :proc => Proc.new { |key| Chef::Config[:knife][:ssh_gateway_identity] = key } + option :forward_agent, :long => "--forward-agent", :description => "Enable SSH agent forwarding", diff --git a/lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb b/lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb index ab8461f..eb24929 100644 --- a/lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb +++ b/lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb @@ -21,7 +21,6 @@ require 'chef/knife/core/windows_bootstrap_context' require 'chef/knife/bootstrap' - class Chef class Knife class Cloud @@ -35,10 +34,11 @@ def initialize(config) def init_bootstrap_options bootstrap.config[:ssh_user] = @config[:ssh_user] bootstrap.config[:ssh_password] = @config[:ssh_password] - bootstrap.config[:ssh_port] = @config[:ssh_port] + bootstrap.config[:ssh_port] = locate_config_value(:ssh_port) bootstrap.config[:identity_file] = @config[:identity_file] bootstrap.config[:host_key_verify] = @config[:host_key_verify] bootstrap.config[:use_sudo] = true unless @config[:ssh_user] == 'root' + bootstrap.config[:template_file] = @config[:template_file] bootstrap.config[:ssh_gateway] = locate_config_value(:ssh_gateway) bootstrap.config[:forward_agent] = locate_config_value(:forward_agent) bootstrap.config[:use_sudo_password] = locate_config_value(:use_sudo_password) @@ -48,15 +48,17 @@ def init_bootstrap_options def wait_for_server_ready print "\n#{ui.color("Waiting for sshd to host (#{@config[:bootstrap_ip_address]})", :magenta)}" + ssh_gateway = get_ssh_gateway_for(@config[:bootstrap_ip_address]) + # The ssh_gateway & subnet_id are currently supported only in EC2. - if config[:ssh_gateway] - print(".") until tunnel_test_ssh(@config[:bootstrap_ip_address]) { + if ssh_gateway + print(".") until tunnel_test_ssh(ssh_gateway, @config[:bootstrap_ip_address]) { @initial_sleep_delay = !!locate_config_value(:subnet_id) ? 40 : 10 sleep @initial_sleep_delay puts("done") } else - print(".") until tcp_test_ssh(@config[:bootstrap_ip_address]) { + print(".") until tcp_test_ssh(@config[:bootstrap_ip_address], locate_config_value(:ssh_port)) { @initial_sleep_delay = !!locate_config_value(:subnet_id) ? 40 : 10 sleep @initial_sleep_delay puts("done") @@ -64,36 +66,57 @@ def wait_for_server_ready end end - def tcp_test_ssh(hostname) - tcp_socket = TCPSocket.new(hostname, 22) - readable = IO.select([tcp_socket], nil, nil, 5) - if readable - ssh_banner = tcp_socket.gets - if ssh_banner.nil? or ssh_banner.empty? - false + def get_ssh_gateway_for(hostname) + if locate_config_value(:ssh_gateway) + # The ssh_gateway specified in the knife config (if any) takes + # precedence over anything in the SSH configuration + Chef::Log.debug("Using ssh gateway #{locate_config_value(:ssh_gateway)} from knife config") + locate_config_value(:ssh_gateway) + else + # Next, check if the SSH configuration has a ProxyCommand + # directive for this host. If there is one, parse out the + # host from the proxy command + ssh_proxy = Net::SSH::Config.for(hostname)[:proxy] + if ssh_proxy.respond_to?(:command_line_template) + # ssh gateway_hostname nc %h %p + proxy_pattern = /ssh\s+(\S+)\s+nc/ + matchdata = proxy_pattern.match(ssh_proxy.command_line_template) + if matchdata.nil? + Chef::Log.debug("Unable to determine ssh gateway for '#{hostname}' from ssh config template: #{ssh_proxy.command_line_template}") + nil + else + # Return hostname extracted from command line template + Chef::Log.debug("Using ssh gateway #{matchdata[1]} from ssh config") + matchdata[1] + end else - Chef::Log.debug("ssh accepting connections on #{hostname}, banner is #{tcp_socket.gets}") - yield - true + # Return nil if we cannot find an ssh_gateway + Chef::Log.debug("No ssh gateway found, making a direct connection") + nil end - else - false end - rescue Errno::ETIMEDOUT - Chef::Log.debug("ssh timed out: #{hostname}") - false - rescue Errno::EPERM + end + + def tcp_test_ssh(hostname, ssh_port) + begin + tcp_socket = TCPSocket.new(hostname, ssh_port) + readable = IO.select([tcp_socket], nil, nil, 5) + if readable + ssh_banner = tcp_socket.gets + if ssh_banner.nil? or ssh_banner.empty? + false + else + Chef::Log.debug("ssh accepting connections on #{hostname}, banner is #{tcp_socket.gets}") + yield + true + end + else + false + end + rescue Errno::EPERM, Errno::ETIMEDOUT Chef::Log.debug("ssh timed out: #{hostname}") false - rescue Errno::ECONNREFUSED - Chef::Log.debug("ssh failed to connect: #{hostname}") - sleep 2 - false - rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH - Chef::Log.debug("ssh failed to connect: #{hostname}") - sleep 2 - false - rescue Errno::ENETUNREACH + rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, IOError Chef::Log.debug("ssh failed to connect: #{hostname}") sleep 2 false @@ -107,22 +130,49 @@ def tcp_test_ssh(hostname) end end - def tunnel_test_ssh(hostname, &block) - gw_host, gw_user = @config[:ssh_gateway].split('@').reverse - gw_host, gw_port = gw_host.split(':') - gateway = Net::SSH::Gateway.new(gw_host, gw_user, :port => gw_port || 22) - status = false - gateway.open(hostname, config[:ssh_port]) do |local_tunnel_port| - status = tcp_test_ssh('localhost', local_tunnel_port, &block) - end - status + def tunnel_test_ssh(ssh_gateway, hostname, &block) + begin + status = false + gateway = configure_ssh_gateway(ssh_gateway) + gateway.open(hostname, locate_config_value(:ssh_port)) do |local_tunnel_port| + status = tcp_test_ssh('localhost', local_tunnel_port, &block) + end + status rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, IOError sleep 2 false rescue Errno::EPERM, Errno::ETIMEDOUT false + end end + def configure_ssh_gateway(ssh_gateway) + gw_host, gw_user = ssh_gateway.split('@').reverse + gw_host, gw_port = gw_host.split(':') + gateway_options = { :port => gw_port || 22 } + + # Load the SSH config for the SSH gateway host. + # Set the gateway user if it was not part of the + # SSH gateway string, and use any configured + # SSH keys. + ssh_gateway_config = Net::SSH::Config.for(gw_host) + gw_user ||= ssh_gateway_config[:user] + + # Always use the gateway keys from the SSH Config + gateway_keys = ssh_gateway_config[:keys] + + # Use the keys specificed on the command line if available (overrides SSH Config) + if locate_config_value(:ssh_gateway_identity) + gateway_keys = Array(locate_config_value(:ssh_gateway_identity)) + end + + unless gateway_keys.nil? + gateway_options[:keys] = gateway_keys + end + + Net::SSH::Gateway.new(gw_host, gw_user, gateway_options) + end + end end end end diff --git a/lib/chef/knife/cloud/server/create_command.rb b/lib/chef/knife/cloud/server/create_command.rb index 0e35a71..c94d465 100644 --- a/lib/chef/knife/cloud/server/create_command.rb +++ b/lib/chef/knife/cloud/server/create_command.rb @@ -143,7 +143,7 @@ def ssh_override_winrm config[:ssh_user] = locate_config_value(:winrm_user) end # unchanged ssh_port and changed winrm_port, override ssh_port - if locate_config_value(:ssh_port).nil? && + if locate_config_value(:ssh_port).eql?(options[:ssh_port][:default]) && !locate_config_value(:winrm_port).eql?(options[:winrm_port][:default]) config[:ssh_port] = locate_config_value(:winrm_port) end diff --git a/spec/unit/server_create_command_spec.rb b/spec/unit/server_create_command_spec.rb index 2d8ae86..efd350b 100644 --- a/spec/unit/server_create_command_spec.rb +++ b/spec/unit/server_create_command_spec.rb @@ -168,9 +168,9 @@ class ServerCreate < Chef::Knife::Cloud::ServerCreateCommand it "set ssh_port value by using -p option for ssh bootstrap protocol or linux image" do # Currently -p option set config[:winrm_port] - # default value of config[:ssh_port] is nil + # default value of config[:ssh_port] is 22 @instance.config[:winrm_port] = "1234" - @instance.config[:ssh_port] = nil + @instance.config[:ssh_port] = "22" @instance.before_bootstrap expect(@instance.config[:ssh_port]).to eq("1234") diff --git a/spec/unit/ssh_bootstrap_protocol_spec.rb b/spec/unit/ssh_bootstrap_protocol_spec.rb index 8783197..cf70b83 100644 --- a/spec/unit/ssh_bootstrap_protocol_spec.rb +++ b/spec/unit/ssh_bootstrap_protocol_spec.rb @@ -85,32 +85,32 @@ allow(IO).to receive(:select).and_return(true) allow(tcpSocket.gets).to receive(:nil?).and_return(false) allow(tcpSocket.gets).to receive(:empty?).and_return(false) - expect(@instance.tcp_test_ssh("localhost"){}).to be(true) + expect(@instance.tcp_test_ssh("localhost","22"){}).to be(true) end it "raise ETIMEDOUT error" do allow(TCPSocket).to receive(:new).and_raise(Errno::ETIMEDOUT) - expect(@instance.tcp_test_ssh("localhost"){}).to be(false) + expect(@instance.tcp_test_ssh("localhost","22"){}).to be(false) end it "raise EPERM error" do allow(TCPSocket).to receive(:new).and_raise(Errno::EPERM) - expect(@instance.tcp_test_ssh("localhost"){}).to be(false) + expect(@instance.tcp_test_ssh("localhost","22"){}).to be(false) end it "raise ECONNREFUSED error" do allow(TCPSocket).to receive(:new).and_raise(Errno::ECONNREFUSED) - expect(@instance.tcp_test_ssh("localhost"){}).to be(false) + expect(@instance.tcp_test_ssh("localhost","22"){}).to be(false) end it "raise EHOSTUNREACH error" do allow(TCPSocket).to receive(:new).and_raise(Errno::EHOSTUNREACH) - expect(@instance.tcp_test_ssh("localhost"){}).to be(false) + expect(@instance.tcp_test_ssh("localhost","22"){}).to be(false) end it "raise ENETUNREACH error" do allow(TCPSocket).to receive(:new).and_raise(Errno::ENETUNREACH) - expect(@instance.tcp_test_ssh("localhost"){}).to be(false) + expect(@instance.tcp_test_ssh("localhost","22"){}).to be(false) end end end From b61156cbbc5d2c25bfa7ff0104ce178562207caa Mon Sep 17 00:00:00 2001 From: prabhu-das Date: Tue, 22 Jul 2014 12:42:15 +0530 Subject: [PATCH 6/6] removed unwanted puts log --- lib/chef/knife/cloud/fog/service.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/chef/knife/cloud/fog/service.rb b/lib/chef/knife/cloud/fog/service.rb index 34c084f..d978488 100644 --- a/lib/chef/knife/cloud/fog/service.rb +++ b/lib/chef/knife/cloud/fog/service.rb @@ -96,7 +96,6 @@ def delete_server(server_name) msg_pair("Instance Name", get_server_name(server)) msg_pair("Instance ID", server.id) - puts "ser" puts "\n" ui.confirm("Do you really want to delete this server")