| 
									
										
										
										
											2015-08-05 14:05:14 +03:00
										 |  |  | require 'set' | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  | require "commands/knife_commands" | 
					
						
							| 
									
										
										
										
											2014-11-20 15:08:42 +03:00
										 |  |  | require "commands/deploy" | 
					
						
							| 
									
										
										
										
											2015-07-16 17:18:55 +03:00
										 |  |  | require "exceptions/record_not_found" | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | module ServerCommands | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-20 15:08:42 +03:00
										 |  |  |   include DeployCommands | 
					
						
							| 
									
										
										
										
											2015-08-10 13:01:34 +03:00
										 |  |  | =begin | 
					
						
							| 
									
										
										
										
											2014-11-20 15:08:42 +03:00
										 |  |  |   def create_server_proc | 
					
						
							| 
									
										
										
										
											2015-07-30 15:37:43 +03:00
										 |  |  |     lambda do |out, s, provider| | 
					
						
							|  |  |  |       mongo = ::Devops::Db.connector | 
					
						
							| 
									
										
										
										
											2014-11-20 15:08:42 +03:00
										 |  |  |       begin | 
					
						
							|  |  |  |         out << "Create server...\n" | 
					
						
							|  |  |  |         out.flush if out.respond_to?(:flush) | 
					
						
							|  |  |  |         unless provider.create_server(s, out) | 
					
						
							|  |  |  |           return 3
 | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2015-07-30 15:37:43 +03:00
										 |  |  |         s.create | 
					
						
							| 
									
										
										
										
											2014-11-20 15:08:42 +03:00
										 |  |  |         out.flush if out.respond_to?(:flush) | 
					
						
							| 
									
										
										
										
											2015-07-30 15:37:43 +03:00
										 |  |  |         DevopsLogger.logger.info "Server with parameters: #{s.to_hash.inspect} is running" | 
					
						
							| 
									
										
										
										
											2014-11-20 15:08:42 +03:00
										 |  |  |         key = mongo.key(s.key) | 
					
						
							| 
									
										
										
										
											2015-07-30 15:37:43 +03:00
										 |  |  |         return two_phase_bootstrap(s, out, provider, key.path) | 
					
						
							| 
									
										
										
										
											2015-08-04 13:20:35 +03:00
										 |  |  |       rescue => e | 
					
						
							| 
									
										
										
										
											2015-07-30 15:37:43 +03:00
										 |  |  |         DevopsLogger.logger.error e.message | 
					
						
							|  |  |  |         DevopsLogger.logger.warn roll_back(s, provider) | 
					
						
							| 
									
										
										
										
											2014-11-20 15:08:42 +03:00
										 |  |  |         mongo.server_delete s.id | 
					
						
							|  |  |  |         return 5
 | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2015-08-10 13:01:34 +03:00
										 |  |  | =end | 
					
						
							| 
									
										
										
										
											2014-11-20 15:08:42 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 14:05:14 +03:00
										 |  |  |   def create_server project, env, params, user, out | 
					
						
							|  |  |  |     provider = ::Provider::ProviderFactory.get(env.provider) | 
					
						
							|  |  |  |     mongo = ::Devops::Db.connector | 
					
						
							|  |  |  |     begin | 
					
						
							|  |  |  |       out << "Create server...\n" | 
					
						
							|  |  |  |       out.flush if out.respond_to?(:flush) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       s = Devops::Model::Server.new | 
					
						
							|  |  |  |       s.provider = provider.name | 
					
						
							|  |  |  |       s.project = project.id | 
					
						
							|  |  |  |       s.deploy_env = env.identifier | 
					
						
							|  |  |  |       s.run_list = params["run_list"] || [] | 
					
						
							|  |  |  |       s.chef_node_name = params["name"] | 
					
						
							|  |  |  |       s.key = params["key"] || provider.ssh_key | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       i = mongo.image env.image | 
					
						
							|  |  |  |       s.remote_user = i.remote_user | 
					
						
							|  |  |  |       s.created_by = user | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return 3 unless s.create(provider, env.image, env.flavor, env.subnets, env.groups, out) | 
					
						
							|  |  |  |       out.flush if out.respond_to?(:flush) | 
					
						
							|  |  |  |       DevopsLogger.logger.info "Server with parameters: #{s.to_hash.inspect} is running" | 
					
						
							|  |  |  |       unless params["without_bootstrap"] | 
					
						
							|  |  |  |         s.run_list = Set.new.merge(project.run_list).merge(env.run_list).merge(s.run_list) | 
					
						
							| 
									
										
										
										
											2014-10-22 15:01:55 +04:00
										 |  |  |         key = mongo.key(s.key) | 
					
						
							|  |  |  |         s.chef_node_name = provider.create_default_chef_node_name(s) if s.chef_node_name.nil? | 
					
						
							| 
									
										
										
										
											2015-08-05 14:05:14 +03:00
										 |  |  |         return two_phase_bootstrap(s, provider.run_list, i.bootstrap_template, key.path, out) | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         return 0
 | 
					
						
							| 
									
										
										
										
											2014-10-22 15:01:55 +04:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2015-08-05 14:05:14 +03:00
										 |  |  |     rescue => e | 
					
						
							|  |  |  |       DevopsLogger.logger.error e.message | 
					
						
							|  |  |  |       DevopsLogger.logger.warn roll_back(s, provider) | 
					
						
							|  |  |  |       mongo.server_delete s.id | 
					
						
							|  |  |  |       return 5
 | 
					
						
							| 
									
										
										
										
											2014-10-22 15:01:55 +04:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 14:05:14 +03:00
										 |  |  |   def two_phase_bootstrap s, provider_run_list, bootstrap_template, cert_path, out | 
					
						
							| 
									
										
										
										
											2015-08-10 13:35:52 +03:00
										 |  |  |     provider = ::Provider::ProviderFactory.get(s.provider) | 
					
						
							| 
									
										
										
										
											2015-07-30 15:37:43 +03:00
										 |  |  |     mongo = ::Devops::Db.connector | 
					
						
							| 
									
										
										
										
											2015-08-04 13:20:35 +03:00
										 |  |  |     out << "\n\nBootstrap...\n" | 
					
						
							| 
									
										
										
										
											2015-07-30 15:37:43 +03:00
										 |  |  |     out.flush if out.respond_to?(:flush) | 
					
						
							| 
									
										
										
										
											2015-08-05 14:05:14 +03:00
										 |  |  |     status = bootstrap(s, out, bootstrap_template, provider_run_list, cert_path) | 
					
						
							| 
									
										
										
										
											2015-07-30 15:37:43 +03:00
										 |  |  |     out.flush if out.respond_to?(:flush) | 
					
						
							|  |  |  |     if status == 0
 | 
					
						
							|  |  |  |       DevopsLogger.logger.info "Server with id '#{s.id}' is bootstraped" | 
					
						
							|  |  |  |       if check_server(s) | 
					
						
							|  |  |  |         out << "Server #{s.chef_node_name} is created" | 
					
						
							| 
									
										
										
										
											2014-11-20 15:08:42 +03:00
										 |  |  |       else | 
					
						
							|  |  |  |         out << roll_back(s, provider) | 
					
						
							|  |  |  |         mongo.server_delete s.id | 
					
						
							| 
									
										
										
										
											2015-07-30 15:37:43 +03:00
										 |  |  |         return 5
 | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       out << "\n" | 
					
						
							|  |  |  |       out.flush if out.respond_to?(:flush) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 14:05:14 +03:00
										 |  |  |       run_list = s.run_list + provider_run_list | 
					
						
							|  |  |  |       out << "\nRun list: #{run_list.inspect}" | 
					
						
							|  |  |  | #      s.options[:run_list] += run_list | 
					
						
							|  |  |  |       KnifeCommands.set_run_list(s.chef_node_name, run_list) | 
					
						
							| 
									
										
										
										
											2015-07-30 15:37:43 +03:00
										 |  |  |       status = deploy_server(out, s, cert_path) | 
					
						
							|  |  |  |       if status != 0
 | 
					
						
							|  |  |  |         msg = "Failed on chef-client with project run list, server with id '#{s.id}'" | 
					
						
							|  |  |  |         DevopsLogger.logger.error msg | 
					
						
							|  |  |  |         out << "\n" + msg + "\n" | 
					
						
							| 
									
										
										
										
											2014-11-20 15:08:42 +03:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2015-07-30 15:37:43 +03:00
										 |  |  |     else | 
					
						
							|  |  |  |       msg = "Failed while bootstraping server with id '#{s.id}'" | 
					
						
							|  |  |  |       DevopsLogger.logger.error msg | 
					
						
							|  |  |  |       out << "\n" + msg + "\n" | 
					
						
							|  |  |  |       out << roll_back(s, provider) | 
					
						
							|  |  |  |       mongo.server_delete s.id | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |     return status | 
					
						
							| 
									
										
										
										
											2014-11-20 15:08:42 +03:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2014-10-22 15:01:55 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  |   def delete_from_chef_server node_name | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       :chef_node => KnifeCommands.chef_node_delete(node_name), | 
					
						
							|  |  |  |       :chef_client => KnifeCommands.chef_client_delete(node_name) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-06 12:37:56 +03:00
										 |  |  |   def self.delete_etc_chef s, cert_path | 
					
						
							|  |  |  |     cmd = "ssh -i #{cert_path} -t -q #{s.remote_user}@#{s.private_ip}" | 
					
						
							|  |  |  |     cmd += " sudo " unless s.remote_user == "root" | 
					
						
							|  |  |  |     cmd += "rm -Rf /etc/chef" | 
					
						
							|  |  |  |     r = `#{cmd}` | 
					
						
							|  |  |  |     raise(r) unless $?.success? | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  |   def check_server s | 
					
						
							|  |  |  |     KnifeCommands.chef_node_list.include?(s.chef_node_name) and KnifeCommands.chef_client_list.include?(s.chef_node_name) | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 14:05:14 +03:00
										 |  |  |   def bootstrap s, out, bootstrap_template, run_list, cert_path | 
					
						
							| 
									
										
										
										
											2015-07-30 15:37:43 +03:00
										 |  |  |     out << "Before bootstrap hooks...\n" | 
					
						
							|  |  |  |     res = s.run_hook(:before_bootstrap, out) | 
					
						
							|  |  |  |     out << "Done\n" | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  |     if s.private_ip.nil? | 
					
						
							|  |  |  |       out << "Error: Private IP is null" | 
					
						
							|  |  |  |       return false | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2015-08-05 14:05:14 +03:00
										 |  |  |     out << "\nBootstrap with run list: #{run_list.inspect}\n" | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  |     ja = { | 
					
						
							|  |  |  |       :provider => s.provider, | 
					
						
							|  |  |  |       :devops_host => `hostname`.strip | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     bootstrap_options = [ | 
					
						
							|  |  |  |       "-x #{s.remote_user}", | 
					
						
							|  |  |  |       "-i #{cert_path}", | 
					
						
							| 
									
										
										
										
											2015-08-05 14:05:14 +03:00
										 |  |  |       "--json-attributes '#{ja.to_json}'", | 
					
						
							|  |  |  |       "-N #{s.chef_node_name}" | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  |     ] | 
					
						
							|  |  |  |     bootstrap_options.push "--sudo" unless s.remote_user == "root" | 
					
						
							| 
									
										
										
										
											2015-08-05 14:05:14 +03:00
										 |  |  |     bootstrap_options.push "-d #{bootstrap_template}" if bootstrap_template | 
					
						
							|  |  |  |     bootstrap_options.push "-r #{run_list.join(",")}" unless run_list.empty? | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  |     ip = s.private_ip | 
					
						
							|  |  |  |     unless s.public_ip.nil? || s.public_ip.strip.empty? | 
					
						
							|  |  |  |       ip = s.public_ip | 
					
						
							|  |  |  |       out << "\nPublic IP is present\n" | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |     out << "\nWaiting for SSH..." | 
					
						
							| 
									
										
										
										
											2014-10-22 15:01:55 +04:00
										 |  |  |     out.flush if out.respond_to?(:flush) | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  |     i = 0
 | 
					
						
							| 
									
										
										
										
											2014-10-22 15:01:55 +04:00
										 |  |  |     cmd = "ssh -i #{cert_path} -q #{s.remote_user}@#{ip} 'exit' 2>&1" | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  |     begin | 
					
						
							| 
									
										
										
										
											2014-10-22 15:01:55 +04:00
										 |  |  |       sleep(5) | 
					
						
							|  |  |  |       res = `#{cmd}` | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  |       i += 1
 | 
					
						
							| 
									
										
										
										
											2014-10-22 15:01:55 +04:00
										 |  |  |       if i == 120
 | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  |         out << "\nCan not connect to #{s.remote_user}@#{ip}" | 
					
						
							|  |  |  |         out << "\n" + res | 
					
						
							| 
									
										
										
										
											2015-07-30 15:37:43 +03:00
										 |  |  |         DevopsLogger.logger.error "Can not connect with command 'ssh -i #{cert_path} #{s.remote_user}@#{ip}':\n#{res}" | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  |         return false | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2014-10-22 15:01:55 +04:00
										 |  |  |       raise ArgumentError.new("Can not connect with command '#{cmd}' ") unless $?.success? | 
					
						
							|  |  |  |     rescue ArgumentError => e | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  |       retry | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-30 15:37:43 +03:00
										 |  |  |     r = KnifeCommands.knife_bootstrap(out, ip, bootstrap_options) | 
					
						
							|  |  |  |     if r == 0
 | 
					
						
							|  |  |  |       out << "Chef node name: #{s.chef_node_name}\n" | 
					
						
							|  |  |  |       ::Devops::Db.connector.server_set_chef_node_name s | 
					
						
							|  |  |  |       out << "Chef node name has been updated\n" | 
					
						
							|  |  |  |       out << "After bootstrap hooks...\n" | 
					
						
							|  |  |  |       res = s.run_hook(:after_bootstrap, out) | 
					
						
							|  |  |  |       out << "Done\n" | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |     r | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-18 15:11:47 +04:00
										 |  |  |   def self.unbootstrap s, cert_path | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  |     i = 0
 | 
					
						
							|  |  |  |     begin | 
					
						
							| 
									
										
										
										
											2014-06-18 15:11:47 +04:00
										 |  |  |       r = `ssh -i #{cert_path} -q #{s.remote_user}@#{s.private_ip} rm -Rf /etc/chef` | 
					
						
							|  |  |  |       raise(r) unless $?.success? | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  |     rescue => e | 
					
						
							| 
									
										
										
										
											2015-07-30 15:37:43 +03:00
										 |  |  |       DevopsLogger.logger.error "Unbootstrap error: " + e.message | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  |       i += 1
 | 
					
						
							|  |  |  |       sleep(1) | 
					
						
							|  |  |  |       retry unless i == 5
 | 
					
						
							| 
									
										
										
										
											2014-06-18 15:11:47 +04:00
										 |  |  |       return e.message | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2014-06-18 15:11:47 +04:00
										 |  |  |     nil | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-30 15:37:43 +03:00
										 |  |  |   def delete_server s | 
					
						
							|  |  |  |     mongo = ::Devops::Db.connector | 
					
						
							| 
									
										
										
										
											2014-10-22 15:01:55 +04:00
										 |  |  |     if s.static? | 
					
						
							|  |  |  |       if !s.chef_node_name.nil? | 
					
						
							| 
									
										
										
										
											2015-07-30 15:37:43 +03:00
										 |  |  |         cert = mongo.key s.key | 
					
						
							| 
									
										
										
										
											2014-10-22 15:01:55 +04:00
										 |  |  |         ServerCommands.unbootstrap(s, cert.path) | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  |       mongo.server_delete s.id | 
					
						
							| 
									
										
										
										
											2014-10-22 15:01:55 +04:00
										 |  |  |       msg = "Static server '#{s.id}' is removed" | 
					
						
							| 
									
										
										
										
											2015-07-30 15:37:43 +03:00
										 |  |  |       DevopsLogger.logger.info msg | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  |       return msg, nil | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |     r = delete_from_chef_server(s.chef_node_name) | 
					
						
							| 
									
										
										
										
											2014-06-18 15:11:47 +04:00
										 |  |  |     provider = ::Provider::ProviderFactory.get(s.provider) | 
					
						
							|  |  |  |     begin | 
					
						
							|  |  |  |       r[:server] = provider.delete_server s | 
					
						
							|  |  |  |     rescue Fog::Compute::OpenStack::NotFound, Fog::Compute::AWS::NotFound | 
					
						
							|  |  |  |       r[:server] = "Server with id '#{s.id}' not found in '#{provider.name}' servers" | 
					
						
							| 
									
										
										
										
											2015-07-30 15:37:43 +03:00
										 |  |  |       DevopsLogger.logger.warn r[:server] | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2014-06-18 15:11:47 +04:00
										 |  |  |     mongo.server_delete s.id | 
					
						
							|  |  |  |     info = "Server '#{s.id}' with name '#{s.chef_node_name}' for project '#{s.project}-#{s.deploy_env}' is removed" | 
					
						
							| 
									
										
										
										
											2015-07-30 15:37:43 +03:00
										 |  |  |     DevopsLogger.logger.info info | 
					
						
							|  |  |  |     r.each{|key, log| DevopsLogger.logger.info("#{key} - #{log}")} | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  |     return info, r | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-23 17:58:49 +04:00
										 |  |  |   def roll_back s, provider | 
					
						
							|  |  |  |     str = "" | 
					
						
							|  |  |  |     unless s.id.nil? | 
					
						
							|  |  |  |       str << "Server '#{s.chef_node_name}' with id '#{s.id}' is not created\n" | 
					
						
							|  |  |  |       str << delete_from_chef_server(s.chef_node_name).values.join("\n") | 
					
						
							|  |  |  |       begin | 
					
						
							| 
									
										
										
										
											2014-06-18 15:11:47 +04:00
										 |  |  |         str << provider.delete_server(s) | 
					
						
							| 
									
										
										
										
											2014-05-23 17:58:49 +04:00
										 |  |  |       rescue => e | 
					
						
							|  |  |  |         str << e.message | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       str << "\nRolled back\n" | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |     return str | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-08 15:34:26 +04:00
										 |  |  | end |