fluke/devops-service/app/api2/handlers/server.rb

270 lines
9.5 KiB
Ruby
Raw Normal View History

2014-12-22 14:22:04 +03:00
require 'rufus-scheduler'
require "uri"
require "commands/status"
require "commands/server"
require "commands/bootstrap_templates"
require "commands/knife_commands"
require "providers/provider_factory"
require "db/mongo/models/server"
require "workers/create_server_worker"
require "workers/bootstrap_worker"
module Devops
2015-07-17 20:22:29 +03:00
module API2_0
2014-12-22 14:22:04 +03:00
module Handler
class Server
extend StatusCommands
extend ServerCommands
extend BootstrapTemplatesCommands
scheduler = Rufus::Scheduler.new
2015-07-17 20:22:29 +03:00
def servers fields, reserved
Devops::DB.connector.servers(nil, nil, nil, reserved, fields).map {|s| s.to_hash}
2014-12-22 14:22:04 +03:00
end
2015-07-17 20:22:29 +03:00
def chef_servers
KnifeCommands.chef_node_list
2014-12-22 14:22:04 +03:00
end
2015-07-17 20:22:29 +03:00
def provider_servers provider
::Provider::ProviderFactory.get(provider).servers
2014-12-22 14:22:04 +03:00
end
2015-07-27 15:40:10 +03:00
def server id
get_server_by_key(id, @params[:key])
2014-12-22 14:22:04 +03:00
end
2015-07-27 15:40:10 +03:00
def delete id, key
s = get_server_by_key(params[:id], key)
### Authorization
Devops::Db.connector.check_project_auth s.project, s.deploy_env, request.env['REMOTE_USER']
delete_server(s, Devops::Db.connector, logger)
2014-12-22 14:22:04 +03:00
end
2015-07-27 15:40:10 +03:00
def create_server_stream out, body
status = []
prepare_create_server(body).each do |s|
res = create_server_proc.call(out, s, provider, Devops::Db.connector)
status.push res
end
status
2014-12-22 14:22:04 +03:00
end
2015-07-27 15:40:10 +03:00
def create_server body
dir = DevopsConfig[:report_dir_v2]
files = []
uri = URI.parse(request.url)
prepare_create_server(body).each do |s|
h = s.to_hash
h["options"] = s.options
jid = CreateServerWorker.perform_async(dir, env.provider, h, @request.env['REMOTE_USER'], DevopsConfig.config)
Worker.set_status jid, Worker::STATUS::IN_QUEUE
#logger.info "Job '#{jid}' has been started"
uri.path = "#{DevopsConfig[:url_prefix]}/v2.0/report/" + jid
files.push uri.to_s
end
sleep 1
files
2014-12-22 14:22:04 +03:00
end
2015-07-27 15:40:10 +03:00
def prepare_create_server body
user = @request.env['REMOTE_USER']
key_name = body["key"]
new_key = Devops::Db.connector.key(key_name) unless key_name.nil?
p = Devops::Db.connector.check_project_auth(body["project"], body["deploy_env"], user)
env = p.deploy_env(body["deploy_env"])
provider = ::Provider::ProviderFactory.get(env.provider)
server_name = body["name"]
check_chef_node_name(server_name, provider) unless server_name.nil?
groups = body["groups"]
unless groups.nil?
buf = groups - provider.groups.keys
halt_response("Invalid security groups '#{buf.join("', '")}' for provider '#{provider.name}'") if buf.empty?
end
Server.extract_servers(provider, p, env, body, user, Devops::Db.connector)
2014-12-22 14:22:04 +03:00
end
2015-07-27 15:40:10 +03:00
def pause_server node_name, key
s = Server.get_server_by_key(node_name, key)
## Authorization
Devops::Db.connector.check_project_auth s.project, s.deploy_env, @request.env['REMOTE_USER']
provider = ::Provider::ProviderFactory.get(s.provider)
r = provider.pause_server s
if r.nil?
"Server with instance ID '#{s.id}' and node name '#{node_name}' is paused"
else
raise ConflictException.new("Server with instance ID '#{s.id}' and node name '#{node_name}' can not be paused, It in state '#{r}'", 409)
end
2014-12-22 14:22:04 +03:00
end
2015-07-27 15:40:10 +03:00
def unpause_server node_name, key
s = Server.get_server_by_key(params[:node_name], key)
## Authorization
Devops::Db.connector.check_project_auth s.project, s.deploy_env, @request.env['REMOTE_USER']
provider = ::Provider::ProviderFactory.get(s.provider)
r = provider.unpause_server s
if r.nil?
"Server with instance ID '#{s.id}' and node name '#{node_name}' is unpaused"
else
raise ConflictException.new("Server with instance ID '#{s.id}' and node name '#{node_name}' can not be unpaused, It in state '#{r}'")
end
end
def reserve_server node_name, key
s = get_server_by_key(node_name, key)
Devops::Db.connector.check_project_auth s.project, s.deploy_env, @request.env['REMOTE_USER']
raise ConflictException.new("Server '#{node_name}' already reserved") unless s.reserved_by.nil?
s.reserved_by = user
Devops::Db.connector.server_update(s)
end
def unreserve_server node_name, key
s = get_server_by_key(node_name, key)
Devops::Db.connector.check_project_auth s.project, s.deploy_env, @request.env['REMOTE_USER']
raise ConflictException.new("Server '#{node_name}' is not reserved") if s.reserved_by.nil?
s.reserved_by = nil
Devops::Db.connector.server_update(s)
2014-12-22 14:22:04 +03:00
end
# TODO: check bootstrap template name
2015-07-27 15:40:10 +03:00
def bootstrap_server_stream out, body
s = prepare_create_server body
status = []
cert = Devops::Db.connector.key s.key
logger.debug "Bootstrap certificate path: #{cert.path}"
bootstrap s, out, cert.path, logger
str = nil
r = if check_server(s)
Devops::Db.connector.server_set_chef_node_name s
str = "Server with id '#{s.id}' is bootstraped"
logger.info str
0
else
str = "Server with id '#{s.id}' is not bootstraped"
logger.warn str
1
end
status.push r
out << str
out << "\n"
status
end
def bootstrap_server body
s = prepare_create_server body
dir = DevopsConfig[:report_dir_v2]
files = []
uri = URI.parse(@request.url)
h = s.to_hash
h["options"] = s.options
h["_id"] = s.id
jid = BootstrapWorker.perform_async(dir, d.provider, h, @request.env['REMOTE_USER'], DevopsConfig.config)
Worker.set_status jid, Worker::STATUS::IN_QUEUE
logger.info "Job '#{jid}' has been started"
uri.path = "#{DevopsConfig[:url_prefix]}/v2.0/report/" + jid
uri.query = nil
uri.fragment = nil
files.push uri.to_s
sleep 1
files
2014-12-22 14:22:04 +03:00
end
2015-07-27 15:40:10 +03:00
def prepare_bootstrap_server body
id = body["instance_id"]
name = body["name"]
s = Devops::Db.connector.server_by_instance_id(id)
p = Devops::Db.connector.check_project_auth s.project, s.deploy_env, @request.env['REMOTE_USER']
d = p.deploy_env s.deploy_env
provider = ::Provider::ProviderFactory.get(s.provider)
check_chef_node_name(name, provider) unless name.nil?
s.options = {
:run_list => rl || d.run_list,
2014-12-22 14:22:04 +03:00
}
2015-07-27 15:40:10 +03:00
unless t.nil?
templates = get_templates
halt_response("Invalid bootstrap template '#{t}', available values: #{templates.join(", ")}", 400) unless templates.include?(t)
s.options[:bootstrap_template] = t
end
s.chef_node_name = name || provider.create_default_chef_node_name(s)
s
end
def add_server body
project = body["project"]
deploy_env = body["deploy_env"]
p = Devops::Db.connector.check_project_auth project, deploy_env, @request.env['REMOTE_USER']
d = p.deploy_env(deploy_env)
cert = Devops::Db.connector.key(body["key"])
provider = ::Provider::ProviderFactory.get("static")
s = Devops::Model::Server.new
s.provider = provider.name
s.project = project
s.deploy_env = deploy_env
s.remote_user = body["remote_user"]
s.private_ip = body["private_ip"]
s.public_ip = body["public_ip"]
s.static = true
s.id = "static_#{cert.id}-#{Time.now.to_i}"
s.key = cert.id
Devops::Db.connector.server_insert s
"Server '#{s.id}' has been added"
2014-12-22 14:22:04 +03:00
end
2015-07-27 15:40:10 +03:00
def get_server_by_key id, key
2015-05-29 16:57:31 +03:00
mongo = Devops::Db.connector
key == "instance" ? mongo.server_by_instance_id(id) : mongo.server_by_chef_node_name(id)
2014-12-22 14:22:04 +03:00
end
2015-07-27 15:40:10 +03:00
def check_chef_node_name name, provider
2015-05-29 16:57:31 +03:00
mongo = Devops::Db.connector
mongo.server_by_chef_node_name name
2014-12-22 14:22:04 +03:00
halt(400, "Server with name '#{name}' already exist")
rescue RecordNotFound => e
# server not found - OK
s = provider.servers.detect {|s| s["name"] == name}
halt(400, "#{provider.name} node with name '#{name}' already exist") unless s.nil?
s = KnifeCommands.chef_node_list.detect {|n| n == name}
halt(400, "Chef node with name '#{name}' already exist") unless s.nil?
s = KnifeCommands.chef_client_list.detect {|c| c == name}
halt(400, "Chef client with name '#{name}' already exist") unless s.nil?
end
end
class ExpireHandler
include ServerCommands
def initialize server, logger
@server = server
@logger = logger
end
def call(job)
@logger.info("Removing node '#{@server.chef_node_name}' form project '#{@server.project}' and env '#{@server.deploy_env}'")
begin
2015-05-29 16:57:31 +03:00
delete_server(@server, Devops::Db.connector, @logger)
2014-12-22 14:22:04 +03:00
rescue => e
logger.error "ExpiredHandler error: " + e.message
end
end
end
end
end
end