зеркало из https://github.com/mozilla/labs-vcap.git
Application debug modes.
Includes the addition of a global cloud controller route, `/info/runtimes', which responds with all runtime information from the DEAs. Also includes some renovations for how we store app metadata. Change-Id: I11b076b6c53b962acfa58407b7ebe857060bb08a
This commit is contained in:
Родитель
6d3f1529cc
Коммит
7867815b2d
|
@ -225,6 +225,13 @@ class AppsController < ApplicationController
|
|||
changed = app.changed
|
||||
CloudController.logger.debug "app: #{app.id} Updating #{changed.inspect}"
|
||||
|
||||
# reject attempts to start in debug mode if debugging is disabled
|
||||
if body_params[:debug] and app.state == 'STARTED' and !AppConfig[:allow_debug]
|
||||
raise CloudError.new(CloudError::APP_DEBUG_DISALLOWED)
|
||||
end
|
||||
|
||||
app.metadata[:debug] = body_params[:debug] if body_params
|
||||
|
||||
# 'app.save' can actually raise an exception, if whatever is
|
||||
# invalid happens all the way down at the DB layer.
|
||||
begin
|
||||
|
|
|
@ -19,6 +19,10 @@ class DefaultController < ApplicationController
|
|||
render :json => info
|
||||
end
|
||||
|
||||
def runtime_info
|
||||
render :json => AppConfig[:runtimes]
|
||||
end
|
||||
|
||||
def service_info
|
||||
svcs = Service.active_services.select {|svc| svc.visible_to_user?(user)}
|
||||
CloudController.logger.debug("Global service listing found #{svcs.length} services.")
|
||||
|
|
|
@ -12,6 +12,10 @@ class App < ActiveRecord::Base
|
|||
|
||||
before_validation :normalize_legacy_staging_strings!
|
||||
|
||||
serialize :metadata, Hash
|
||||
|
||||
after_initialize :set_defaults
|
||||
|
||||
after_create :add_owner_as_collaborator
|
||||
|
||||
scope :started, lambda { where("apps.state = ?", 'STARTED') }
|
||||
|
@ -78,6 +82,10 @@ class App < ActiveRecord::Base
|
|||
result
|
||||
end
|
||||
|
||||
def set_defaults
|
||||
self.metadata ||= {}
|
||||
end
|
||||
|
||||
def total_memory
|
||||
instances * memory
|
||||
end
|
||||
|
@ -93,7 +101,11 @@ class App < ActiveRecord::Base
|
|||
:services => bound_services,
|
||||
:version => generate_version,
|
||||
:env => environment,
|
||||
:meta => {:version => lock_version, :created => Time.now.to_i} }
|
||||
:meta => metadata.merge({
|
||||
:version => lock_version,
|
||||
:created => Time.now.to_i
|
||||
})
|
||||
}
|
||||
end
|
||||
|
||||
# Called by AppManager when staging this app.
|
||||
|
@ -338,16 +350,6 @@ class App < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def metadata
|
||||
json = read_attribute(:metadata_json)
|
||||
return {} if json.blank?
|
||||
Yajl::Parser.parse(json, :symbolize_keys => true)
|
||||
end
|
||||
|
||||
def metadata=(hash)
|
||||
write_attribute(:metadata_json, Yajl::Encoder.encode(hash))
|
||||
end
|
||||
|
||||
def environment
|
||||
json_crypt = read_attribute(:environment_json)
|
||||
return [] if json_crypt.blank?
|
||||
|
|
|
@ -191,6 +191,7 @@ class AppManager
|
|||
f = Fiber.new do
|
||||
message = start_message.dup
|
||||
message[:executableUri] = download_app_uri(message[:executableUri])
|
||||
message[:debug] = @app.metadata[:debug]
|
||||
(index...max_to_start).each do |i|
|
||||
message[:index] = i
|
||||
dea_id = find_dea_for(message)
|
||||
|
@ -323,8 +324,8 @@ class AppManager
|
|||
raise e # re-raise here to propogate to the API call.
|
||||
end
|
||||
|
||||
# Returns an array of hashes containing 'index', 'state', and 'since'(timestamp)
|
||||
# for all instances running, or trying to run, the app.
|
||||
# Returns an array of hashes containing 'index', 'state', 'since'(timestamp),
|
||||
# and 'debug_port' for all instances running, or trying to run, the app.
|
||||
def find_instances
|
||||
return [] unless app.started?
|
||||
instances = app.instances
|
||||
|
@ -370,7 +371,8 @@ class AppManager
|
|||
indices[index] = {
|
||||
:index => index,
|
||||
:state => instance_json[:state],
|
||||
:since => instance_json[:state_timestamp]
|
||||
:since => instance_json[:state_timestamp],
|
||||
:debug_port => instance_json[:debug_port]
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -81,6 +81,8 @@ staging:
|
|||
max_staging_runtime: 120 # secs
|
||||
secure: false
|
||||
|
||||
allow_debug: false
|
||||
|
||||
# admin support
|
||||
admins: [derek@gmail.com, foobar@vmware.com]
|
||||
https_required: false
|
||||
|
@ -105,3 +107,19 @@ builtin_services:
|
|||
token: "0xdeadbeef"
|
||||
rabbitmq:
|
||||
token: "0xdeadbeef"
|
||||
|
||||
# used for /info/runtimes endpoint (served unfiltered as JSON)
|
||||
runtimes:
|
||||
ruby18:
|
||||
version: 1.8.7
|
||||
ruby19:
|
||||
version: 1.9.2
|
||||
node:
|
||||
version: 0.4.[2-9]
|
||||
java:
|
||||
version: 1.6.0
|
||||
debug_modes:
|
||||
- run
|
||||
- wait
|
||||
erlangR14B02:
|
||||
version: ".* 5.8.3"
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
CloudController::Application.routes.draw do
|
||||
get 'info' => 'default#info', :as => :cloud_info
|
||||
get 'info/services' => 'default#service_info', :as => :cloud_service_info
|
||||
get 'info/runtimes' => 'default#runtime_info', :as => :cloud_runtime_info
|
||||
get 'users' => 'users#list', :as => :list_users
|
||||
post 'users' => 'users#create', :as => :create_user
|
||||
get 'users/*email' => 'users#info', :as => :user_info
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
class RenameAppMetadataJsonToMetadata < ActiveRecord::Migration
|
||||
def self.up
|
||||
rename_column :apps, :metadata_json, :metadata
|
||||
end
|
||||
|
||||
def self.down
|
||||
rename_column :apps, :metadata, :metadata_json
|
||||
end
|
||||
end
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20110521014004) do
|
||||
ActiveRecord::Schema.define(:version => 20110707170643) do
|
||||
|
||||
create_table "app_collaborations", :force => true do |t|
|
||||
t.integer "app_id"
|
||||
|
@ -32,7 +32,7 @@ ActiveRecord::Schema.define(:version => 20110521014004) do
|
|||
t.string "package_state", :default => "PENDING"
|
||||
t.string "package_hash"
|
||||
t.text "environment_json"
|
||||
t.text "metadata_json"
|
||||
t.text "metadata"
|
||||
t.boolean "external_secret", :default => false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
|
|
|
@ -39,6 +39,7 @@ class CloudError < StandardError
|
|||
APP_FILE_ERROR = [306, HTTP_INTERNAL_SERVER_ERROR, "Error retrieving file '%s'"]
|
||||
APP_INVALID_RUNTIME = [307, HTTP_BAD_REQUEST, "Invalid runtime specification [%s] for framework: '%s'"]
|
||||
APP_INVALID_FRAMEWORK = [308, HTTP_BAD_REQUEST, "Invalid framework description: '%s'"]
|
||||
APP_DEBUG_DISALLOWED = [309, HTTP_BAD_REQUEST, "Cloud controller has disallowed debugging."]
|
||||
|
||||
# Bits
|
||||
RESOURCES_UNKNOWN_PACKAGE_TYPE = [400, HTTP_BAD_REQUEST, "Unknown package type requested: \"%\""]
|
||||
|
|
|
@ -43,6 +43,11 @@ runtimes:
|
|||
version: 1.6.0
|
||||
version_flag: '-version'
|
||||
environment:
|
||||
debug_env:
|
||||
run:
|
||||
- JAVA_OPTS="$JAVA_OPTS -Xdebug -Xrunjdwp:transport=dt_socket,address=$VCAP_DEBUG_PORT,server=y,suspend=n"
|
||||
wait:
|
||||
- JAVA_OPTS="$JAVA_OPTS -Xdebug -Xrunjdwp:transport=dt_socket,address=$VCAP_DEBUG_PORT,server=y,suspend=y"
|
||||
php:
|
||||
executable: php
|
||||
version: 5.3.[2-6]
|
||||
|
|
|
@ -399,7 +399,8 @@ module DEA
|
|||
:state_timestamp => instance[:state_timestamp],
|
||||
:file_uri => "http://#{@local_ip}:#{@file_viewer_port}/droplets/",
|
||||
:credentials => @file_auth,
|
||||
:staged => instance[:staged]
|
||||
:staged => instance[:staged],
|
||||
:debug_port => instance[:debug_port]
|
||||
}
|
||||
if include_stats && instance[:state] == :RUNNING
|
||||
response[:stats] = {
|
||||
|
@ -494,6 +495,7 @@ module DEA
|
|||
users = message_json['users']
|
||||
runtime = message_json['runtime']
|
||||
framework = message_json['framework']
|
||||
debug = message_json['debug']
|
||||
|
||||
# Limits processing
|
||||
mem = DEFAULT_APP_MEM
|
||||
|
@ -560,16 +562,26 @@ module DEA
|
|||
end
|
||||
|
||||
start_operation = proc do
|
||||
port = VCAP.grab_ephemeral_port
|
||||
|
||||
@logger.debug('Completed download')
|
||||
@logger.info("Starting up instance #{instance[:log_id]} on port:#{port}")
|
||||
|
||||
port = VCAP.grab_ephemeral_port
|
||||
instance[:port] = port
|
||||
|
||||
starting = "Starting up instance #{instance[:log_id]} on port:#{port}"
|
||||
|
||||
if debug
|
||||
debug_port = VCAP.grab_ephemeral_port
|
||||
instance[:debug_port] = debug_port
|
||||
instance[:debug_mode] = debug
|
||||
|
||||
@logger.info("#{starting} with debugger:#{debug_port}")
|
||||
else
|
||||
@logger.info(starting)
|
||||
end
|
||||
|
||||
@logger.debug("Clients: #{@num_clients}")
|
||||
@logger.debug("Reserved Memory Usage: #{@reserved_mem} MB of #{@max_memory} MB TOTAL")
|
||||
|
||||
instance[:port] = port
|
||||
|
||||
manifest_file = File.join(instance[:dir], 'droplet.yaml')
|
||||
manifest = {}
|
||||
manifest = File.open(manifest_file) { |f| YAML.load(f) } if File.file?(manifest_file)
|
||||
|
@ -856,7 +868,7 @@ module DEA
|
|||
if state && state['state'] == 'RUNNING'
|
||||
block.call(true)
|
||||
timer.cancel
|
||||
else
|
||||
elsif instance[:debug_mode] != "wait"
|
||||
attempts += 1
|
||||
if attempts > 600 || instance[:state] != :STARTING # 5 minutes or instance was stopped
|
||||
block.call(false)
|
||||
|
@ -1048,6 +1060,12 @@ module DEA
|
|||
env_hash.to_json
|
||||
end
|
||||
|
||||
def debug_env(instance)
|
||||
return unless instance[:debug_port]
|
||||
return unless envs = @runtimes[instance[:runtime]]['debug_env']
|
||||
envs[instance[:debug_mode]]
|
||||
end
|
||||
|
||||
def setup_instance_env(instance, app_env, services)
|
||||
env = []
|
||||
|
||||
|
@ -1056,6 +1074,12 @@ module DEA
|
|||
env << "VCAP_SERVICES='#{create_services_for_env(services)}'"
|
||||
env << "VCAP_APP_HOST='#{@local_ip}'"
|
||||
env << "VCAP_APP_PORT='#{instance[:port]}'"
|
||||
env << "VCAP_DEBUG_PORT='#{instance[:debug_port]}'"
|
||||
|
||||
if vars = debug_env(instance)
|
||||
@logger.info("Debugger environment variables: #{vars.inspect}")
|
||||
env += vars
|
||||
end
|
||||
|
||||
# LEGACY STUFF
|
||||
env << "VMC_WARNING_WARNING='All VMC_* environment variables are deprecated, please use VCAP_* versions.'"
|
||||
|
|
Загрузка…
Ссылка в новой задаче