| #!/usr/bin/env ruby |
| |
| # Licensed to the Apache Software Foundation (ASF) under one or more |
| # contributor license agreements. See the NOTICE file distributed with |
| # this work for additional information regarding copyright ownership. The |
| # ASF licenses this file to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance with the |
| # License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| # License for the specific language governing permissions and limitations |
| # under the License. |
| # |
| |
| $top_srcdir = File::expand_path(File.join(File.dirname(__FILE__), '..')) |
| |
| require 'rubygems' |
| require 'optparse' |
| require 'yaml' |
| |
| # See if we can require +name+ and return +true+ if the library is there, |
| # +false+ otherwise. Note that, as a side effect, the library will be |
| # loaded |
| def library_present?(name) |
| begin |
| require name |
| true |
| rescue LoadError |
| false |
| end |
| end |
| |
| DEFAULT_CONFIG = "~/.deltacloud/config" |
| |
| options = { |
| :env => 'development', |
| :logdir => "/var/log/deltacloud-core" |
| } |
| optparse = OptionParser.new do |opts| |
| |
| opts.banner = <<BANNER |
| Usage: |
| deltacloudd -i <driver> [options] |
| |
| Options: |
| BANNER |
| opts.on( '-i', '--driver DRIVER', 'Driver to use') do |driver| |
| ENV["API_DRIVER"] = driver |
| end |
| opts.on( '-r', '--hostname HOSTNAME', |
| 'Bind to HOST address (default: localhost)') do |host| |
| ENV["API_HOST"] = host |
| end |
| opts.on( '-p', '--port PORT', 'Use PORT (default: 3001)') do |port| |
| ENV["API_PORT"] = port |
| end |
| opts.on( '-P', '--provider PROVIDER', 'Use PROVIDER (default is set in the driver)') do |provider| |
| ENV['API_PROVIDER'] = provider |
| end |
| opts.on('-f', '--frontends FRONTENDS', 'Enable different frontends (cimi, ec2, deltacloud)') do |frontend| |
| ENV['API_FRONTEND'] = frontend |
| end |
| opts.on( '-c', '--config [FILE]', 'Read provider and other config from FILE (default: ~/.deltacloud/config)') do |config| |
| options[:config] = File::expand_path(config || DEFAULT_CONFIG) |
| end |
| opts.on( '-e', '--env ENV', 'Environment (default: "development")') { |env| options[:env] = env } |
| opts.on( '-d', '--daemon', 'Run daemonized in the background, logging to SYSLOG (default: "disabled")') do |
| options[:daemon] = true |
| end |
| opts.on( '-u', '--user USER', 'User to run daemon as. Use with -d (default: "nobody")') { |user| options[:user] = user } |
| opts.on( '-g', '--group GROUP', 'Group to run daemon as. Use with -d (default: "nobody")') { |group| options[:group] = group } |
| opts.on( '-b', '--pid PID', 'File to store PID (default: tmp/pids/thin.pid)') { |pid| options[:pid] = pid } |
| opts.on( '-l', '--drivers', 'List available drivers') { |env| options[:drivers] = true } |
| opts.on( '-L', '--log FILE', 'Log requests to a file (default: disabled)') { |log| ENV['API_LOG'] = log } |
| opts.on( '-s', '--ssl', 'Enable SSL (default: disabled)') { |ssl| options[:ssl] = true } |
| opts.on( '-k', '--ssl-key KEY', 'SSL key file to use') { |key| options[:ssl_key] = key } |
| opts.on( '-C', '--ssl-cert CERT', 'SSL certificate file to use') { |cert| options[:ssl_cert] = cert } |
| opts.on( '-t', '--timeout TIMEOUT', 'Timeout for single request (default: 60)') do |timeout| |
| ENV["API_TIMEOUT"] = timeout |
| end |
| opts.on( '-V', '--verbose', 'Set verbose logging on') do |verbose| |
| ENV["API_VERBOSE"] ||= 'true' |
| end |
| opts.on( '-w', '--webrick', 'Force the use of WEBRick as a server') do |opt| |
| options[:webrick] = true |
| end |
| opts.on('--logdir LOGDIR', "Directory for log files, defaults to #{options[:logdir]}") do |opt| |
| options[:logdir] = opt |
| end |
| opts.on( '-h', '--help', '') { options[:help] = true } |
| |
| opts.separator <<EOS |
| |
| Config file: |
| |
| Server configuration can be specified in a YAML file; the file must |
| contain a hash, where the keys are driver names; each driver entry is |
| also a hash. Possible keys are |
| :provider - the provider to use for this driver |
| :user - the user name for this driver |
| :password - the password for this driver |
| |
| Note that specifying :user and :password turns off authentication on the |
| server, and any request is forwarded to the backend cloud with the |
| specified credentials. |
| |
| Note, for SSL you need to have API_SSL_KEY and API_SSL_CERT environment |
| variables set. |
| EOS |
| end |
| |
| optparse.parse! |
| |
| if options[:help] |
| puts optparse |
| exit(0) |
| end |
| |
| unless options[:drivers] or ENV["API_DRIVER"] |
| puts "You need to specify a driver to use (-i <driver>)" |
| puts "To list all available drivers try: deltacloudd --drivers" |
| exit(1) |
| end |
| |
| if options[:drivers] |
| $:.unshift File.join($top_srcdir, 'lib') |
| server_dir = ENV['API_FRONTEND'] == 'cimi' ? 'cimi' : 'deltacloud' |
| load File.join($top_srcdir, 'lib', server_dir, 'api.rb') |
| puts "Available drivers:\n\n" |
| puts Deltacloud.drivers.keys.join("\n") |
| puts |
| exit(0) |
| end |
| |
| |
| if options[:ssl] |
| unless options[:ssl_key] |
| puts "You need to set SSL key using '-k /path/to/keyfile.key'" |
| exit(1) |
| end |
| unless options[:ssl_cert] |
| puts "You need to set SSL certificate using '-C /path/to/certificate.crt'" |
| exit(1) |
| end |
| end |
| |
| if options[:config] |
| cfg = YAML::load(File.read(options[:config])) |
| if cfg.keys.any? { |k| k.is_a?(Symbol) } |
| puts "The config file #{options[:config]} uses symbols as keys" |
| puts " Change them to be ordinary strings" |
| exit(1) |
| end |
| if c = cfg[ENV["API_DRIVER"]] |
| ENV["API_PROVIDER"] ||= c["provider"] |
| ENV["API_USER"] ||= c["user"] |
| ENV["API_PASSWORD"] ||= c["password"] |
| end |
| end |
| |
| ENV["API_HOST"] = "localhost" unless ENV["API_HOST"] |
| ENV["API_PORT"] = "3001" unless ENV["API_PORT"] |
| |
| have_thin = options[:webrick].nil? && library_present?('thin') |
| have_rerun = library_present?('rerun') |
| |
| if !options[:daemon] || options[:daemon] && !have_thin |
| msg = "Starting Deltacloud API :: #{ENV["API_DRIVER"]} " |
| msg << ":: #{ENV['API_PROVIDER']} " if ENV['API_PROVIDER'] |
| api_uri = ENV['API_FRONTEND'] == 'cimi' ? 'cimi/cloudEntryPoint' : 'api' |
| if options[:ssl] |
| msg << ":: https://#{ENV["API_HOST"]}:#{ENV["API_PORT"]}/#{api_uri}" |
| else |
| msg << ":: http://#{ENV["API_HOST"]}:#{ENV["API_PORT"]}/#{api_uri}" |
| end |
| puts msg |
| puts |
| end |
| |
| if ENV['API_USER'] && ENV['API_PASSWORD'] |
| puts "Warning: API_USER and API_PASSWORD set in environment" |
| puts " anybody can access this server with your credentials" |
| puts |
| end |
| |
| unless have_thin |
| require 'rack' |
| |
| puts "To start Deltacloud as a daemon, install 'thin' (gem install thin)\n\n" if options[:daemon] |
| |
| # Read in config.ru and convert it to an instance of Rack::Builder |
| cfgfile = File.read(File.join($top_srcdir, 'config.ru')) |
| inner_app = eval("Rack::Builder.new {(" + cfgfile + "\n )}.to_app", |
| nil, 'config.ru') |
| |
| app = Rack::Builder.new { |
| use Rack::CommonLogger # apache-like logging |
| use Rack::Reloader #if options[:env] == "development" |
| run inner_app |
| }.to_app |
| |
| # There's a bug with string ports on JRuby so convert to int |
| # http://jira.codehaus.org/browse/JRUBY-4868 |
| port = ENV["API_PORT"].to_i |
| puts "=> Ctrl-C to shutdown server" |
| Dir::chdir($top_srcdir) |
| Rack::Server::start(:app => app, |
| :server => :webrick, |
| :Host => ENV["API_HOST"], |
| :Port => port, |
| :AccessLog => []) |
| else |
| argv_opts = ARGV.clone |
| argv_opts << ['start'] unless Thin::Runner.commands.include?(options[0]) |
| argv_opts << ['--address', ENV["API_HOST"] ] |
| argv_opts << ['--port', ENV["API_PORT"] ] |
| argv_opts << ['--rackup', File.join($top_srcdir, 'config.ru') ] |
| argv_opts << ['-e', options[:env] ] |
| argv_opts << ['--timeout', ENV["API_TIMEOUT"] || '60'] |
| argv_opts << ['--threaded', '-D' ] |
| if options[:ssl] |
| argv_opts << [ '--ssl', '--ssl-key-file', options[:ssl_key], '--ssl-cert-file', options[:ssl_cert]] |
| end |
| |
| if options[:daemon] |
| options[:env] = "production" |
| argv_opts << [ "--daemonize", "--user", options[:user] || 'nobody', "--tag", "deltacloud-#{ENV['API_DRIVER']}"] |
| argv_opts << [ "--pid", options[:pid]] if options[:pid] |
| argv_opts << [ "--group", options[:group] || 'nobody' ] |
| argv_opts << [ "--log", File.join(options[:logdir], "#{ENV['API_DRIVER']}.log")] |
| end |
| argv_opts.flatten! |
| |
| if have_rerun && options[:env] == "development" |
| argv_opts.unshift "thin" |
| command = argv_opts.join(" ") |
| Dir::chdir($top_srcdir) |
| rerun = Rerun::Runner.new(command, |
| :dir => File::join($top_srcdir, "lib")) |
| rerun.start |
| rerun.join |
| else |
| thin = Thin::Runner.new(argv_opts) |
| thin.run! |
| end |
| end |