fluke/devops-service/commands/server.rb

245 lines
7.6 KiB
Ruby
Raw Normal View History

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
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-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-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
def self.unbootstrap s, cert_path
2014-05-08 15:34:26 +04:00
i = 0
begin
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
return e.message
2014-05-08 15:34:26 +04:00
end
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)
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
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
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