lib/chef/knife/openstack_server_create.rb in knife-openstack-0.7.1 vs lib/chef/knife/openstack_server_create.rb in knife-openstack-0.8.0

- old
+ new

@@ -1,8 +1,9 @@ # # Author:: Seth Chisamore (<schisamo@opscode.com>) # Author:: Matt Ray (<matt@opscode.com>) +# Author:: Chirag Jog (<chirag@clogeny.com>) # Copyright:: Copyright (c) 2011-2013 Opscode, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -16,16 +17,18 @@ # See the License for the specific language governing permissions and # limitations under the License. # require 'chef/knife/openstack_base' +require 'chef/knife/winrm_base' class Chef class Knife class OpenstackServerCreate < Knife include Knife::OpenstackBase + include Chef::Knife::WinrmBase deps do require 'fog' require 'readline' require 'chef/json_compat' @@ -128,10 +131,26 @@ :long => "--[no-]host-key-verify", :description => "Verify host key, enabled by default", :boolean => true, :default => true + option :bootstrap_protocol, + :long => "--bootstrap-protocol protocol", + :description => "Protocol to bootstrap Windows servers. options: winrm", + :default => nil + + option :bootstrap_proxy, + :long => "--bootstrap-proxy PROXY_URL", + :description => "The proxy server for the node being bootstrapped", + :proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_proxy] = v } + + option :server_create_timeout, + :long => "--server-create-timeout timeout", + :description => "How long to wait until the server is ready; default is 600 seconds", + :default => 600, + :proc => Proc.new { |v| Chef::Config[:knife][:server_create_timeouts] = v} + 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}") @@ -155,15 +174,45 @@ false ensure tcp_socket && tcp_socket.close end + def tcp_test_winrm(hostname, port) + TCPSocket.new(hostname, port) + return true + rescue SocketError + sleep 2 + false + rescue Errno::ETIMEDOUT + false + rescue Errno::EPERM + false + rescue Errno::ECONNREFUSED + sleep 2 + false + rescue Errno::EHOSTUNREACH + sleep 2 + false + rescue Errno::ENETUNREACH + sleep 2 + false + end + + def load_winrm_deps + require 'winrm' + require 'em-winrm' + require 'chef/knife/bootstrap_windows_winrm' + require 'chef/knife/core/windows_bootstrap_context' + require 'chef/knife/winrm' + end def run $stdout.sync = true validate! - + if locate_config_value(:bootstrap_protocol) == 'winrm' + load_winrm_deps + end #servers require a name, generate one if not passed node_name = get_node_name(config[:chef_node_name]) server_def = { :name => node_name, @@ -202,11 +251,11 @@ msg_pair("Instance ID", server.id) print "\n#{ui.color("Waiting for server", :magenta)}" # wait for it to be ready to do stuff - server.wait_for { print "."; ready? } + server.wait_for(Integer(locate_config_value(:server_create_timeout))) { print "."; ready? } puts("\n") msg_pair("Flavor", server.flavor['id']) msg_pair("Image", server.image['id']) @@ -251,19 +300,22 @@ if bootstrap_ip_address.nil? ui.error("No IP address available for bootstrapping.") exit 1 end - print "\n#{ui.color("Waiting for sshd", :magenta)}" - - print(".") until tcp_test_ssh(bootstrap_ip_address) { - sleep @initial_sleep_delay ||= 10 - puts("done") - } - - bootstrap_for_node(server, bootstrap_ip_address).run - + if locate_config_value(:bootstrap_protocol) == 'winrm' + print "\n#{ui.color("Waiting for winrm", :magenta)}" + print(".") until tcp_test_winrm(bootstrap_ip_address, locate_config_value(:winrm_port)) + bootstrap_for_windows_node(server, bootstrap_ip_address).run + else + print "\n#{ui.color("Waiting for sshd", :magenta)}" + print(".") until tcp_test_ssh(bootstrap_ip_address) { + sleep @initial_sleep_delay ||= 10 + puts("done") + } + bootstrap_for_node(server, bootstrap_ip_address).run + end puts "\n" msg_pair("Instance Name", server.name) msg_pair("Instance ID", server.id) msg_pair("Flavor", server.flavor['id']) msg_pair("Image", server.image['id']) @@ -273,28 +325,44 @@ msg_pair("Private IP Address", primary_private_ip_address(server.addresses)) if primary_private_ip_address(server.addresses) msg_pair("Environment", config[:environment] || '_default') msg_pair("Run List", config[:run_list].join(', ')) end - def bootstrap_for_node(server, bootstrap_ip_address) - bootstrap = Chef::Knife::Bootstrap.new + def bootstrap_for_windows_node(server, bootstrap_ip_address) + bootstrap = Chef::Knife::BootstrapWindowsWinrm.new bootstrap.name_args = [bootstrap_ip_address] + bootstrap.config[:winrm_user] = locate_config_value(:winrm_user) || 'Administrator' + bootstrap.config[:winrm_password] = locate_config_value(:winrm_password) + bootstrap.config[:winrm_transport] = locate_config_value(:winrm_transport) + bootstrap.config[:winrm_port] = locate_config_value(:winrm_port) + bootstrap_common_params(bootstrap, server.name) + end + + def bootstrap_common_params(bootstrap, server_name) + bootstrap.config[:chef_node_name] = config[:chef_node_name] || server_name bootstrap.config[:run_list] = config[:run_list] - bootstrap.config[:ssh_user] = config[:ssh_user] - bootstrap.config[:ssh_password] = server.password - bootstrap.config[:identity_file] = config[:identity_file] - bootstrap.config[:host_key_verify] = config[:host_key_verify] - bootstrap.config[:chef_node_name] = server.name bootstrap.config[:prerelease] = config[:prerelease] bootstrap.config[:bootstrap_version] = locate_config_value(:bootstrap_version) bootstrap.config[:distro] = locate_config_value(:distro) - bootstrap.config[:use_sudo] = true unless config[:ssh_user] == 'root' bootstrap.config[:template_file] = locate_config_value(:template_file) + bootstrap.config[:bootstrap_proxy] = locate_config_value(:bootstrap_proxy) bootstrap.config[:environment] = config[:environment] + bootstrap.config[:encrypted_data_bag_secret] = config[:encrypted_data_bag_secret] + bootstrap.config[:encrypted_data_bag_secret_file] = config[:encrypted_data_bag_secret_file] # let ohai know we're using OpenStack Chef::Config[:knife][:hints] ||= {} Chef::Config[:knife][:hints]['openstack'] ||= {} bootstrap + end + + def bootstrap_for_node(server, bootstrap_ip_address) + bootstrap = Chef::Knife::Bootstrap.new + bootstrap.name_args = [bootstrap_ip_address] + bootstrap.config[:ssh_user] = config[:ssh_user] + 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_common_params(bootstrap, server.name) end def flavor @flavor ||= connection.flavors.get(locate_config_value(:flavor)) end