provider static, todo: project env with provider static

This commit is contained in:
amartynov 2014-06-18 15:11:47 +04:00
parent 0ffdd8261c
commit 10eaf25454
23 changed files with 606 additions and 547 deletions

View File

@ -63,7 +63,7 @@ class Server < Handler
@list = case args[2] @list = case args[2]
when "chef" when "chef"
get("/servers/chef").map {|l| {"chef_node_name" => l}} get("/servers/chef").map {|l| {"chef_node_name" => l}}
when "ec2", "openstack" when "ec2", "openstack", "static"
get("/servers/#{args[2]}") get("/servers/#{args[2]}")
else else
@options_parser.invalid_list_command @options_parser.invalid_list_command
@ -149,7 +149,7 @@ class Server < Handler
:key => args[6] :key => args[6]
} }
q[:public_ip] = self.options[:public_ip] unless self.options[:public_ip].nil? q[:public_ip] = self.options[:public_ip] unless self.options[:public_ip].nil?
post_chunk "/server/add", q post "/server/add", q
end end
def pause_handler args def pause_handler args

View File

@ -8,7 +8,7 @@ class ServerOptions < CommonOptions
super(args, def_options) super(args, def_options)
self.header = I18n.t("headers.server") self.header = I18n.t("headers.server")
self.banner_header = "server" self.banner_header = "server"
self.list_params = ["[chef|ec2|openstack]"] self.list_params = ["[chef|ec2|openstack|static]"]
self.create_params = ["PROJECT_ID", "DEPLOY_ENV"] self.create_params = ["PROJECT_ID", "DEPLOY_ENV"]
node_params = ["NODE_NAME"] node_params = ["NODE_NAME"]
self.delete_params = node_params self.delete_params = node_params

View File

@ -25,12 +25,12 @@ module DeployEnvCommands
raise InvalidRecord.new "Invalid networks '#{n.join("', '")}'" unless n.empty? raise InvalidRecord.new "Invalid networks '#{n.join("', '")}'" unless n.empty?
filter = nil filter = nil
if p.name == ::Version2_0::Provider::Ec2::PROVIDER if p.name == ::Provider::Ec2::PROVIDER
unless subnets.empty? unless subnets.empty?
subnets = [ subnets[0] ] if subnets.size > 1 subnets = [ subnets[0] ] if subnets.size > 1
filter = {"vpc-id" => networks.detect{|n| n["name"] == subnets[0]}["vpcId"] } filter = {"vpc-id" => networks.detect{|n| n["name"] == subnets[0]}["vpcId"] }
end end
elsif p.name == ::Version2_0::Provider::Openstack::PROVIDER elsif p.name == ::Provider::Openstack::PROVIDER
if subnets.empty? if subnets.empty?
raise InvalidRecord.new "Subnets array can not be empty" raise InvalidRecord.new "Subnets array can not be empty"
end end

View File

@ -7,7 +7,7 @@ module ImageCommands
if filters.empty? if filters.empty?
[] []
else else
::Version2_0::Provider::ProviderFactory.get(provider).images(filters) ::Provider::ProviderFactory.get(provider).images(filters)
end end
end end
end end

View File

@ -142,17 +142,19 @@ module ServerCommands
return status return status
end end
def unbootstrap s, cert_path def self.unbootstrap s, cert_path
i = 0 i = 0
begin begin
`ssh -i #{cert_path} -q #{s.remote_user}@#{s.private_ip} rm -Rf /etc/chef` r = `ssh -i #{cert_path} -q #{s.remote_user}@#{s.private_ip} rm -Rf /etc/chef`
raise unless $?.success? raise(r) unless $?.success?
rescue => e rescue => e
logger.error "Unbootstrap eeror: " + e.message logger.error "Unbootstrap error: " + e.message
i += 1 i += 1
sleep(1) sleep(1)
retry unless i == 5 retry unless i == 5
return e.message
end end
nil
end end
def delete_server s, mongo, logger def delete_server s, mongo, logger
@ -163,26 +165,16 @@ module ServerCommands
return msg, nil return msg, nil
end end
r = delete_from_chef_server(s.chef_node_name) r = delete_from_chef_server(s.chef_node_name)
info = if s.static provider = ::Provider::ProviderFactory.get(s.provider)
cert = mongo.key(s.key).path
unbootstrap(s, cert)
mongo.server_delete s.id
msg = "Static server '#{s.id}' with name '#{s.chef_node_name}' for project '#{s.project}-#{s.deploy_env}' is removed"
logger.info msg
msg
else
provider = ::Version2_0::Provider::ProviderFactory.get(s.provider)
begin begin
r[:server] = provider.delete_server s.id r[:server] = provider.delete_server s
rescue Fog::Compute::OpenStack::NotFound, Fog::Compute::AWS::NotFound rescue Fog::Compute::OpenStack::NotFound, Fog::Compute::AWS::NotFound
r[:server] = "Server with id '#{s.id}' not found in '#{provider.name}' servers" r[:server] = "Server with id '#{s.id}' not found in '#{provider.name}' servers"
logger.warn r[:server] logger.warn r[:server]
end end
mongo.server_delete s.id mongo.server_delete s.id
msg = "Server '#{s.id}' with name '#{s.chef_node_name}' for project '#{s.project}-#{s.deploy_env}' is removed" info = "Server '#{s.id}' with name '#{s.chef_node_name}' for project '#{s.project}-#{s.deploy_env}' is removed"
logger.info msg logger.info info
msg
end
r.each{|key, log| logger.info("#{key} - #{log}")} r.each{|key, log| logger.info("#{key} - #{log}")}
return info, r return info, r
end end
@ -193,7 +185,7 @@ module ServerCommands
str << "Server '#{s.chef_node_name}' with id '#{s.id}' is not created\n" 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") str << delete_from_chef_server(s.chef_node_name).values.join("\n")
begin begin
str << provider.delete_server(s.id) unless s.static str << provider.delete_server(s)
rescue => e rescue => e
str << e.message str << e.message
end end

View File

@ -34,3 +34,7 @@ config[:aws_secret_access_key] = "secret_access_key"
config[:aws_ssh_key] = "ssh_key" config[:aws_ssh_key] = "ssh_key"
config[:aws_certificate] = "/path/to/.ssh/ec2.pem" config[:aws_certificate] = "/path/to/.ssh/ec2.pem"
config[:aws_availability_zone] = "aws_zone" config[:aws_availability_zone] = "aws_zone"
# static settings
config[:static_ssh_key] = "ssh_key" # or nil
config[:static_certificate] = "/path/to/.ssh/static.pem"

View File

@ -44,7 +44,7 @@ class DeployEnv < MongoModel
check_expires!(self.expires) check_expires!(self.expires)
end end
p = ::Version2_0::Provider::ProviderFactory.get(self.provider) p = ::Provider::ProviderFactory.get(self.provider)
check_flavor!(p, self.flavor) check_flavor!(p, self.flavor)
check_image!(p, self.image) check_image!(p, self.image)
check_subnets_and_groups!(p, self.subnets, self.groups) check_subnets_and_groups!(p, self.subnets, self.groups)

View File

@ -65,7 +65,7 @@ class DeployEnvMulti < MongoModel
end end
end end
p = ::Version2_0::Provider::ProviderFactory.get(server["provider"]) p = ::Provider::ProviderFactory.get(server["provider"])
check_flavor!(p, server["flavor"]) check_flavor!(p, server["flavor"])
check_image!(p, server["image"]) check_image!(p, server["image"])
check_subnets_and_groups!(p, server["subnets"], server["groups"]) check_subnets_and_groups!(p, server["subnets"], server["groups"])

View File

@ -43,7 +43,7 @@ class MongoModel
end end
def check_provider provider=self.provider def check_provider provider=self.provider
unless ::Version2_0::Provider::ProviderFactory.providers.include?(provider) or provider == "static" unless ::Provider::ProviderFactory.providers.include?(provider)
raise InvalidRecord.new "Invalid provider '#{provider}'" raise InvalidRecord.new "Invalid provider '#{provider}'"
end end
end end

View File

@ -191,12 +191,16 @@ class MongoConnector
end end
end end
def servers_find q
@servers.find(create_query(q)).to_a.map{|bs| Server.create_from_bson bs}
end
def servers p=nil, env=nil, names=nil def servers p=nil, env=nil, names=nil
q = {} q = {}
q["project"] = p unless p.nil? or p.empty? q["project"] = p unless p.nil? or p.empty?
q["deploy_env"] = env unless env.nil? or env.empty? q["deploy_env"] = env unless env.nil? or env.empty?
q["chef_node_name"] = {"$in" => names} unless names.nil? or names.class != Array q["chef_node_name"] = {"$in" => names} unless names.nil? or names.class != Array
@servers.find(create_query(q)).to_a.map{|bs| Server.create_from_bson bs} servers_find(q)
end end
def servers_by_names names def servers_by_names names

View File

@ -29,7 +29,8 @@ class DevopsService < Sinatra::Base
[:keys_dir, :scripts_dir].each {|key| d = @@config[key]; FileUtils.mkdir_p(d) unless File.exists?(d) } [:keys_dir, :scripts_dir].each {|key| d = @@config[key]; FileUtils.mkdir_p(d) unless File.exists?(d) }
mongo = DevopsService.mongo mongo = DevopsService.mongo
mongo.create_root_user mongo.create_root_user
::Version2_0::Provider::ProviderFactory.all.each do |p| ::Provider::ProviderFactory.all.each do |p|
next if p.certificate_path.nil?
begin begin
mongo.key p.ssh_key, Key::SYSTEM mongo.key p.ssh_key, Key::SYSTEM
rescue RecordNotFound => e rescue RecordNotFound => e

View File

@ -1,7 +1,6 @@
require "fog" require "fog"
module Version2_0 module Provider
module Provider
class BaseProvider class BaseProvider
attr_accessor :ssh_key, :certificate_path, :connection_options attr_accessor :ssh_key, :certificate_path, :connection_options
@ -24,5 +23,4 @@ module Version2_0
end end
end end
end
end end

View File

@ -1,8 +1,6 @@
require "providers/base_provider" require "providers/base_provider"
#require 'xml'
module Version2_0 module Provider
module Provider
# Provider for Amazon EC2 # Provider for Amazon EC2
class Ec2 < BaseProvider class Ec2 < BaseProvider
@ -30,14 +28,6 @@ module Version2_0
PROVIDER PROVIDER
end end
def compute
connection_compute(connection_options)
end
def network
nil
end
def flavors def flavors
self.compute.flavors.all.map do |f| self.compute.flavors.all.map do |f|
{ {
@ -164,31 +154,31 @@ module Version2_0
"#{self.ssh_key}-#{s.project}-#{s.deploy_env}-#{Time.now.to_i}" "#{self.ssh_key}-#{s.project}-#{s.deploy_env}-#{Time.now.to_i}"
end end
def delete_server id def delete_server s
r = self.compute.terminate_instances(id) r = self.compute.terminate_instances(s.id)
i = r.body["instancesSet"][0] i = r.body["instancesSet"][0]
old_state = i["previousState"]["name"] old_state = i["previousState"]["name"]
state = i["currentState"]["name"] state = i["currentState"]["name"]
return r.status == 200 ? "Server with id '#{id}' changed state '#{old_state}' to '#{state}'" : r.body return r.status == 200 ? "Server with id '#{s.id}' changed state '#{old_state}' to '#{state}'" : r.body
end end
def pause_server id def pause_server s
s = self.server id es = self.server s.id
if s["state"] == "running" if es["state"] == "running"
self.compute.stop_instances [ id ] self.compute.stop_instances [ s.id ]
return nil return nil
else else
return s["state"] return es["state"]
end end
end end
def unpause_server id def unpause_server s
s = self.server id es = self.server s.id
if s["state"] == "stopped" if es["state"] == "stopped"
self.compute.start_instances [ id ] self.compute.start_instances [ s.id ]
return nil return nil
else else
return s["state"] return es["state"]
end end
end end
@ -242,6 +232,9 @@ module Version2_0
r r
end end
private
def compute
connection_compute(connection_options)
end end
end end
end end

View File

@ -1,7 +1,6 @@
require "providers/base_provider" require "providers/base_provider"
module Version2_0 module Provider
module Provider
# Provider for 'openstack' # Provider for 'openstack'
class Openstack < BaseProvider class Openstack < BaseProvider
@ -29,14 +28,6 @@ module Version2_0
PROVIDER PROVIDER
end end
def compute
connection_compute(self.connection_options)
end
def network
connection_network(self.connection_options)
end
def groups filter=nil def groups filter=nil
convert_groups(compute.list_security_groups.body["security_groups"]) convert_groups(compute.list_security_groups.body["security_groups"])
end end
@ -168,23 +159,23 @@ module Version2_0
"#{self.ssh_key}-#{s.project}-#{s.deploy_env}-#{Time.now.to_i}" "#{self.ssh_key}-#{s.project}-#{s.deploy_env}-#{Time.now.to_i}"
end end
def delete_server id def delete_server s
r = self.compute.delete_server(id) r = self.compute.delete_server(s.id)
return r.status == 204 ? "Server with id '#{id}' terminated" : r.body return r.status == 204 ? "Server with id '#{s.id}' terminated" : r.body
end end
def pause_server id def pause_server s
begin begin
self.compute.pause_server id self.compute.pause_server s.id
rescue Excon::Errors::Conflict => e rescue Excon::Errors::Conflict => e
return "pause" return "pause"
end end
return nil return nil
end end
def unpause_server id def unpause_server s
begin begin
self.compute.unpause_server id self.compute.unpause_server s.id
rescue Excon::Errors::Conflict => e rescue Excon::Errors::Conflict => e
return "unpause" return "unpause"
end end
@ -212,6 +203,13 @@ module Version2_0
res res
end end
def compute
connection_compute(self.connection_options)
end end
def network
connection_network(self.connection_options)
end
end end
end end

View File

@ -1,5 +1,4 @@
module Version2_0 module Provider
module Provider
class ProviderFactory class ProviderFactory
@@providers = nil @@providers = nil
@ -24,10 +23,10 @@ module Version2_0
def self.init def self.init
conf = DevopsService.config conf = DevopsService.config
@@providers = {} @@providers = {}
["ec2", "openstack"].each do |p| ["ec2", "openstack", "static"].each do |p|
begin begin
require "providers/#{p}" require "providers/#{p}"
o = Version2_0::Provider.const_get(p.capitalize).new(conf) o = Provider.const_get(p.capitalize).new(conf)
@@providers[p] = o if o.configured? @@providers[p] = o if o.configured?
rescue => e rescue => e
next next
@ -38,5 +37,4 @@ module Version2_0
end end
end end
end
end end

View File

@ -0,0 +1,63 @@
require "providers/base_provider"
require "commands/server"
module Provider
class Static < BaseProvider
PROVIDER = "static"
def initialize config
self.certificate_path = config[:static_certificate]
self.ssh_key = "static"
@@mongo ||= MongoConnector.new(config[:mongo_db], config[:mongo_host], config[:mongo_port], config[:mongo_user], config[:mongo_password])
end
def configured?
true
end
def name
PROVIDER
end
def flavors
[]
end
def images filters
[]
end
def networks
[]
end
def servers
@@mongo.servers_find({:provider => PROVIDER}).map{|s| s.to_hash}
end
def create_default_chef_node_name s
"static-#{s.project}-#{s.deploy_env}-#{Time.now.to_i}"
end
def create_server s, out
out << "Unsupported operation: ca not create server for provider 'static'"
false
end
def delete_server s
cert = @@mongo.key(s.key).path
res = ::ServerCommands.unbootstrap(s, cert)
m = "Static server with id '#{s.id}' and name '#{s.chef_node_name}' "
return m + (res.nil? ? "has been unbootstraped" : "can not be unbootstraped: #{res}")
end
def pause_server s
nil
end
def unpause_server s
nil
end
end
end

View File

@ -68,7 +68,7 @@ module Version2_0
end end
def check_provider provider def check_provider provider
list = ::Version2_0::Provider::ProviderFactory.providers list = ::Provider::ProviderFactory.providers
halt_response("Invalid provider '#{provider}', available providers: '#{list.join("', '")}'", 404) unless list.include?(provider) halt_response("Invalid provider '#{provider}', available providers: '#{list.join("', '")}'", 404) unless list.include?(provider)
end end

View File

@ -41,7 +41,7 @@ module Version2_0
check_headers :accept check_headers :accept
check_privileges("flavor", "r") check_privileges("flavor", "r")
check_provider(params[:provider]) check_provider(params[:provider])
p = ::Version2_0::Provider::ProviderFactory.get params[:provider] p = ::Provider::ProviderFactory.get params[:provider]
json p.flavors json p.flavors
end end

View File

@ -53,7 +53,7 @@ module Version2_0
check_headers :accept check_headers :accept
check_privileges("group", "r") check_privileges("group", "r")
check_provider(params[:provider]) check_provider(params[:provider])
p = ::Version2_0::Provider::ProviderFactory.get params[:provider] p = ::Provider::ProviderFactory.get params[:provider]
json p.groups(params) json p.groups(params)
end end

View File

@ -41,7 +41,7 @@ module Version2_0
check_headers :accept check_headers :accept
check_privileges("network", "r") check_privileges("network", "r")
check_provider(params[:provider]) check_provider(params[:provider])
p = ::Version2_0::Provider::ProviderFactory.get params[:provider] p = ::Provider::ProviderFactory.get params[:provider]
json p.networks_detail json p.networks_detail
end end

View File

@ -476,7 +476,7 @@ module Version2_0
project = BaseRoutes.mongo.project(params[:id]) project = BaseRoutes.mongo.project(params[:id])
env = project.deploy_env params[:env] env = project.deploy_env params[:env]
user = request.env['REMOTE_USER'] user = request.env['REMOTE_USER']
provider = ::Version2_0::Provider::ProviderFactory.get(env.provider) provider = ::Provider::ProviderFactory.get(env.provider)
header = "Test project '#{project.id}' and environment '#{env.identifier}'" header = "Test project '#{project.id}' and environment '#{env.identifier}'"
logger.info header logger.info header
servers = extract_servers(provider, project, env, {}, user, BaseRoutes.mongo) servers = extract_servers(provider, project, env, {}, user, BaseRoutes.mongo)

View File

@ -26,7 +26,7 @@ module Version2_0
get "/providers" do get "/providers" do
check_headers :accept check_headers :accept
check_privileges("provider", "r") check_privileges("provider", "r")
json ::Version2_0::Provider::ProviderFactory.providers json ::Provider::ProviderFactory.providers
end end
end end

View File

@ -139,7 +139,7 @@ module Version2_0
# } # }
# ] # ]
get "/servers/:provider" do get "/servers/:provider" do
json ::Version2_0::Provider::ProviderFactory.get(params[:provider]).servers json ::Provider::ProviderFactory.get(params[:provider]).servers
end end
# Get server info by :name # Get server info by :name
@ -223,7 +223,7 @@ module Version2_0
p = BaseRoutes.mongo.check_project_auth(project_name, env_name, user) p = BaseRoutes.mongo.check_project_auth(project_name, env_name, user)
env = p.deploy_env(env_name) env = p.deploy_env(env_name)
provider = ::Version2_0::Provider::ProviderFactory.get(env.provider) provider = ::Provider::ProviderFactory.get(env.provider)
check_chef_node_name(server_name, provider) unless server_name.nil? check_chef_node_name(server_name, provider) unless server_name.nil?
unless groups.nil? unless groups.nil?
buf = groups - provider.groups.keys buf = groups - provider.groups.keys
@ -286,8 +286,8 @@ module Version2_0
s = get_server(params[:node_name], @key) s = get_server(params[:node_name], @key)
## Authorization ## Authorization
BaseRoutes.mongo.check_project_auth s.project, s.deploy_env, request.env['REMOTE_USER'] BaseRoutes.mongo.check_project_auth s.project, s.deploy_env, request.env['REMOTE_USER']
provider = ::Version2_0::Provider::ProviderFactory.get(s.provider) provider = ::Provider::ProviderFactory.get(s.provider)
r = provider.pause_server s.id r = provider.pause_server s
if r.nil? if r.nil?
create_response("Server with instance ID '#{s.id}' and node name '#{params[:node_name]}' is paused") create_response("Server with instance ID '#{s.id}' and node name '#{params[:node_name]}' is paused")
else else
@ -313,8 +313,8 @@ module Version2_0
s = get_server(params[:node_name], @key) s = get_server(params[:node_name], @key)
## Authorization ## Authorization
BaseRoutes.mongo.check_project_auth s.project, s.deploy_env, request.env['REMOTE_USER'] BaseRoutes.mongo.check_project_auth s.project, s.deploy_env, request.env['REMOTE_USER']
provider = ::Version2_0::Provider::ProviderFactory.get(s.provider) provider = ::Provider::ProviderFactory.get(s.provider)
r = provider.unpause_server s.id r = provider.unpause_server s
if r.nil? if r.nil?
create_response("Server with instance ID '#{s.id}' and node name '#{params[:node_name]}' is unpaused") create_response("Server with instance ID '#{s.id}' and node name '#{params[:node_name]}' is unpaused")
else else
@ -401,27 +401,34 @@ module Version2_0
p = BaseRoutes.mongo.check_project_auth s.project, s.deploy_env, request.env['REMOTE_USER'] p = BaseRoutes.mongo.check_project_auth s.project, s.deploy_env, request.env['REMOTE_USER']
d = p.deploy_env s.deploy_env d = p.deploy_env s.deploy_env
provider = ::Provider::ProviderFactory.get(s.provider)
s.options = { s.options = {
:run_list => rl || d.run_list, :run_list => rl || d.run_list,
} }
s.options[:bootstrap_template] = t unless t.nil? s.options[:bootstrap_template] = t unless t.nil?
status = []
stream() do |out| stream() do |out|
begin begin
s.chef_node_name = name || "static_#{s.key}-#{Time.now.to_i}" s.chef_node_name = name || provider.create_default_chef_node_name(s)
cert = BaseRoutes.mongo.key s.key cert = BaseRoutes.mongo.key s.key
logger.debug "Bootstrap certificate path: #{cert.path}" logger.debug "Bootstrap certificate path: #{cert.path}"
bootstrap s, out, cert.path, logger bootstrap s, out, cert.path, logger
str = nil str = nil
if check_server(s) r = if check_server(s)
BaseRoutes.mongo.server_update s BaseRoutes.mongo.server_update s
str = "Server with id '#{s.id}' is bootstraped" str = "Server with id '#{s.id}' is bootstraped"
logger.info str logger.info str
0
else else
str = "Server with id '#{s.id}' is not bootstraped" str = "Server with id '#{s.id}' is not bootstraped"
logger.warn str logger.warn str
1
end end
status.push r
out << str out << str
out << "\n" out << "\n"
out << create_status(status)
rescue IOError => e rescue IOError => e
logger.error e.message logger.error e.message
end end
@ -461,8 +468,9 @@ module Version2_0
d = p.deploy_env(deploy_env) d = p.deploy_env(deploy_env)
cert = BaseRoutes.mongo.key(key) cert = BaseRoutes.mongo.key(key)
provider = ::Provider::ProviderFactory.get("static")
s = Server.new s = Server.new
s.provider = "static" s.provider = provider.name
s.project = project s.project = project
s.deploy_env = deploy_env s.deploy_env = deploy_env
s.remote_user = remote_user s.remote_user = remote_user