Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
7c40430
properly checking if autoscaling should be used based on --autoscalin…
shatterednirvana Oct 18, 2012
415a9da
mocking out getting our local IP address, which doesn't work on Mac O…
shatterednirvana Oct 21, 2012
eb70d6e
Merge pull request #70 from AppScale/master
nlake44 Oct 22, 2012
9a933c4
now explicitly stating timeout to avoid SessionExpired exceptions fro…
shatterednirvana Oct 23, 2012
dc6abc1
Merge pull request #73 from shatterednirvana/zookeeper-fixes
nlake44 Oct 23, 2012
a1783c1
Merge pull request #74 from shatterednirvana/autoscaler-appserver-flag
nlake44 Oct 23, 2012
a39101c
Correct number of arguments added
nlake44 Oct 24, 2012
83d4c21
Fixes from code review
nlake44 Oct 24, 2012
ac8b0aa
Fixes from code review
nlake44 Oct 24, 2012
1031ddd
Fixes from code review
nlake44 Oct 24, 2012
7501e4b
Fixes syntax error
nlake44 Oct 24, 2012
b0c8cd7
Added useful comments for exceptions
nlake44 Oct 24, 2012
68e82df
Added comments and removed useless line
nlake44 Oct 24, 2012
4b0b965
Merge pull request #75 from nlake44/nginx_config
shatterednirvana Oct 24, 2012
67fd51c
Fixed issue
nlake44 Oct 24, 2012
bcc9213
Code review changes, and syntax fix
nlake44 Oct 25, 2012
ad3e336
Merge branch 'badapp3' of github.com:nlake44/appscale into testing
Oct 25, 2012
1edf405
Merge pull request #76 from nlake44/tq_connect2
shatterednirvana Oct 25, 2012
5d5aa39
Updated doc for function
nlake44 Oct 25, 2012
04ae94c
Fixed conflict on djinn.rb
nlake44 Oct 25, 2012
a01e251
Commenting fixes
nlake44 Oct 25, 2012
8a346bb
Print exception class for bad parsing of yaml
nlake44 Oct 25, 2012
e9f6043
Print exception message for bad parsing of yaml
nlake44 Oct 25, 2012
1b0ffb8
Print exception message for bad parsing of yaml
nlake44 Oct 25, 2012
3f957d0
Merge pull request #71 from nlake44/badapp3
shatterednirvana Oct 25, 2012
fbdd679
bumped version number to 1.6.3
shatterednirvana Oct 30, 2012
21fc86b
bumped version number in helperfunctions
shatterednirvana Oct 30, 2012
fb97247
updated RELEASE with info about the bugs fixed in 1.6.3
shatterednirvana Oct 30, 2012
89cfb86
more updates to RELEASE doc
shatterednirvana Oct 30, 2012
ba80b7c
copied in old 1.5 release info
shatterednirvana Oct 30, 2012
9979329
Merge pull request #80 from shatterednirvana/1.6.3
nlake44 Oct 30, 2012
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 77 additions & 43 deletions AppController/djinn.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,26 @@

# Imports for AppController libraries
$:.unshift File.join(File.dirname(__FILE__), "lib")
require 'helperfunctions'
require 'app_controller_client'
require 'blobstore'
require 'custom_exceptions'
require 'ejabberd'
require 'error_app'
require 'collectd'
require 'cron_helper'
require 'godinterface'
require 'haproxy'
require 'collectd'
require 'nginx'
require 'helperfunctions'
require 'infrastructure_manager_client'
require 'neptune_manager_client'
require 'pbserver'
require 'blobstore'
require 'nginx'
require 'rabbitmq'
require 'app_controller_client'
require 'user_app_client'
require 'ejabberd'
require 'repo'
require 'user_app_client'
require 'zkinterface'
require 'godinterface'
require 'infrastructure_manager_client'
require 'neptune_manager_client'


class AppScaleException < Exception
end


WANT_OUTPUT = true

Expand Down Expand Up @@ -1543,7 +1542,6 @@ def write_zookeeper_locations


def update_api_status()
return
if my_node.is_appengine?
repo_host = my_node.private_ip
else
Expand Down Expand Up @@ -2129,7 +2127,7 @@ def change_job()
retval = 0
while retries > 0
replication = @creds["replication"]
Djinn.log_run("MASTER_IP='localhost' LOCAL_DB_IP='localhost' python2.6 #{prime_script} #{replication}; echo $? > /tmp/retval")
Djinn.log_run("APPSCALE_HOME='#{APPSCALE_HOME}' MASTER_IP='localhost' LOCAL_DB_IP='localhost' python2.6 #{prime_script} #{replication}; echo $? > /tmp/retval")
retval = `cat /tmp/retval`.to_i
break if retval == 0
Djinn.log_debug("Fail to create initial table. Retry #{retries} times.")
Expand Down Expand Up @@ -2245,7 +2243,7 @@ def start_pbserver
zoo_connection = get_zk_connection_string(@nodes)
PbServer.start(db_master_ip, @userappserver_private_ip, my_ip, table, zoo_connection)
HAProxy.create_pbserver_config(my_node.private_ip, PbServer::PROXY_PORT, table)
Nginx.create_pbserver_config(my_ip, PbServer::PROXY_PORT)
Nginx.create_pbserver_config(my_node.private_ip, PbServer::PROXY_PORT)
Nginx.restart()

# TODO check the return value
Expand Down Expand Up @@ -2741,6 +2739,26 @@ def stop_shadow()
Djinn.log_debug("Stopping Shadow role")
end

#
# Swaps out an application with one that relays an error message to the
# developer. It will take the application that currently exists in the
# application folder, deletes it, and places a templated app that prints out the
# given error message.
#
# Args:
# app_name: Name of application to construct an error application for
# err_msg: A String message that will be displayed as
# the reason why we couldn't start their application.
#
# Returns:
# Returns: Nothing
#
def place_error_app(app_name, err_msg)
Djinn.log_debug("Placing error application for #{app_name} because of: #{err_msg}")
ea = ErrorApp.new(app_name, err_msg)
ea.generate()
end

def start_appengine()
@state = "Preparing to run AppEngine apps if needed"
Djinn.log_debug("Starting appengine - pbserver is at [#{@userappserver_private_ip}]")
Expand Down Expand Up @@ -2803,7 +2821,9 @@ def start_appengine()
app_path = "#{app_dir}/#{app}.tar.gz"
FileUtils.mkdir_p(app_dir)

copy_app_to_local(app)
if !copy_app_to_local(app)
place_error_app(app, "ERROR: Failed to copy app: #{app}")
end
HelperFunctions.setup_app(app)


Expand All @@ -2813,15 +2833,16 @@ def start_appengine()
end
app_number = @nginx_port - Nginx::START_PORT
proxy_port = HAProxy.app_listen_port(app_number)
login_ip = get_login.public_ip
login_ip = get_login.private_ip
if my_node.is_login? and !my_node.is_appengine?
success = Nginx.write_fullproxy_app_config(app, app_number, my_public,
my_private, proxy_port, login_ip, get_all_appengine_nodes())
if success
Nginx.reload
else
Djinn.log_debug("ERROR: Failure to create valid nginx config file for application #{app} full proxy.")
next
err_msg = "ERROR: Failure to create valid nginx config file" + \
" for application #{app} full proxy."
place_error_app(app, err_msg)
end
@nginx_port += 1
@haproxy_port += 1
Expand All @@ -2831,14 +2852,22 @@ def start_appengine()
if my_node.is_appengine?
app_number = @nginx_port - Nginx::START_PORT
start_port = HelperFunctions::APP_START_PORT
static_handlers = HelperFunctions.parse_static_data(app)
begin
static_handlers = HelperFunctions.parse_static_data(app)
rescue Exception => e
# This specific exception may be a json parse error
error_msg = "ERROR: Unable to parse app.yaml file for #{app}." + \
" Exception of #{e.class} with message #{e.message}"
place_error_app(app, error_msg)
end
proxy_port = HAProxy.app_listen_port(app_number)
login_ip = get_login.public_ip
success = Nginx.write_app_config(app, app_number, my_public,
login_ip = get_login.private_ip
success = Nginx.write_app_config(app, app_number, my_public, my_private,
proxy_port, static_handlers, login_ip)
if not success
Djinn.log_debug("ERROR: Failure to create valid nginx config file for application #{app}.")
next
if !success
error_msg = "ERROR: Failure to create valid nginx config file " + \
"for application #{app}."
place_error_app(app, error_msg)
end
Collectd.write_app_config(app)

Expand All @@ -2859,14 +2888,14 @@ def start_appengine()
@userappserver_private_ip, get_load_balancer_ip(), my_private,
app_version, app_language, @nginx_port, xmpp_ip)
if pid == -1
Djinn.log_debug("ERROR: Unable to start application #{app}.")
next
place_error_app(app, "ERROR: Unable to start application " + \
"#{app}. Please check the application logs.")
end

pid_file_name = "/etc/appscale/#{app}-#{@appengine_port}.pid"
HelperFunctions.write_file(pid_file_name, pid)

location = "http://#{my_public}:#{@appengine_port}#{warmup_url}"
location = "http://#{my_private}:#{@appengine_port}#{warmup_url}"
wget_cmd = "wget #{WGET_OPTIONS} #{location}"

Djinn.log_run(wget_cmd)
Expand All @@ -2875,7 +2904,7 @@ def start_appengine()
}

HAProxy.update_app_config(app, app_number,
@app_info_map[app][:appengine], my_public)
@app_info_map[app][:appengine], my_private)
Nginx.reload
HAProxy.reload
Collectd.restart
Expand Down Expand Up @@ -2903,7 +2932,7 @@ def start_appengine()
login_ip = get_login.public_ip

Thread.new {
haproxy_location = "http://#{my_public}:#{haproxy}#{warmup_url}"
haproxy_location = "http://#{my_private}:#{haproxy}#{warmup_url}"
nginx_location = "http://#{my_public}:#{nginx}#{warmup_url}"

wget_haproxy = "wget #{WGET_OPTIONS} #{haproxy_location}"
Expand Down Expand Up @@ -2944,7 +2973,7 @@ def scale_appservers
return
end

if @creds["autoscale"]
if @creds["autoscale"] == "true"
Djinn.log_debug("Examining AppServers to autoscale them")
perform_scaling_for_appservers()
else
Expand Down Expand Up @@ -3209,7 +3238,7 @@ def add_appserver_process(app)
my_private = my_node.private_ip
Djinn.log_debug("port apps error contains - #{@app_info_map[app][:appengine]}")
HAProxy.update_app_config(app, app_number, @app_info_map[app][:appengine],
my_public)
my_private)

Djinn.log_debug("Adding #{app_language} app #{app} on #{HelperFunctions.local_ip}:#{@appengine_port} ")
xmpp_ip = get_login.public_ip
Expand All @@ -3221,7 +3250,7 @@ def add_appserver_process(app)
pid_file_name = "#{APPSCALE_HOME}/.appscale/#{app}-#{@appengine_port}.pid"
HelperFunctions.write_file(pid_file_name, pid)

location = "http://#{my_public}:#{@appengine_port}#{warmup_url}"
location = "http://#{my_private}:#{@appengine_port}#{warmup_url}"
wget_cmd = "wget #{WGET_OPTIONS} #{location}"

Djinn.log_run(wget_cmd)
Expand All @@ -3234,10 +3263,8 @@ def add_appserver_process(app)

# add_instance_info = uac.add_instance(app, my_public, @nginx_port)

login_ip = get_login.public_ip

Thread.new {
haproxy_location = "http://#{my_public}:#{haproxy_port}#{warmup_url}"
haproxy_location = "http://#{my_private}:#{haproxy_port}#{warmup_url}"
nginx_location = "http://#{my_public}:#{nginx_port}#{warmup_url}"

wget_haproxy = "wget #{WGET_OPTIONS} #{haproxy_location}"
Expand Down Expand Up @@ -3294,7 +3321,7 @@ def remove_appserver_process(app)
@app_info_map[app][:appengine].delete(port)

HAProxy.update_app_config(app, app_number, @app_info_map[app][:appengine],
my_public)
my_private)
HAProxy.reload
end

Expand Down Expand Up @@ -3441,19 +3468,26 @@ def start_sisyphus

my_public = my_node.public_ip
my_private = my_node.private_ip
login_ip = get_login.public_ip

static_handlers = HelperFunctions.parse_static_data(app)
public_login_ip = get_login.public_ip
private_login_ip = get_login.private_ip

begin
static_handlers = HelperFunctions.parse_static_data(app)
rescue Exception => e
error_msg = "ERROR: Unable to parse app.yaml file for #{app}." + \
" Exception of type #{e.class}. Exception message #{e.message}"
place_error_app(app, error_msg)
end
proxy_port = HAProxy.app_listen_port(app_number)
Nginx.write_app_config(app, app_number, my_public, proxy_port, static_handlers, login_ip)
Nginx.write_app_config(app, app_number, my_public, my_private, proxy_port, static_handlers, private_login_ip)
HAProxy.write_app_config(app, app_number, num_servers, my_private)
Collectd.write_app_config(app)

[19994, 19995, 19996].each { |port|
Djinn.log_debug("Starting #{app_language} app #{app} on " +
"#{HelperFunctions.local_ip}:#{port}")
pid = HelperFunctions.run_app(app, port, @userappserver_private_ip,
my_public, my_private, app_version, app_language, nginx_port, login_ip)
my_public, my_private, app_version, app_language, nginx_port, public_login_ip)
pid_file_name = "#{APPSCALE_HOME}/.appscale/#{app}-#{port}.pid"
HelperFunctions.write_file(pid_file_name, pid)
}
Expand Down
2 changes: 2 additions & 0 deletions AppController/djinnServer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ def on_init
`rm -f #{APPSCALE_HOME}/.appscale/status-*`
`rm -f #{APPSCALE_HOME}/.appscale/database_info`
`rm -f /tmp/mysql.sock`


Nginx.clear_sites_enabled
Collectd.clear_sites_enabled
HAProxy.clear_sites_enabled
Expand Down
14 changes: 14 additions & 0 deletions AppController/lib/custom_exceptions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Programmer: Navraj Chohan

# A class of exceptions that can be thrown if the AppController is put into an
# unrecoverable state, or a state that we would not normally expect a perfectly
# working AppScale system to get into.
class AppScaleException < Exception
end

# A class of exceptions that can be thrown if the AppController
# (or its associated libraries) attempts to execute shell commands which
# do not return properly (specifically, not having a return value of zero).
class FailedShellExec < Exception
end

87 changes: 87 additions & 0 deletions AppController/lib/error_app.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#!/usr/bin/ruby -w

require 'fileutils'

$:.unshift File.join(File.dirname(__FILE__))
require 'custom_exceptions'
require 'helperfunctions'

$:.unshift File.join(File.dirname(__FILE__), "..")
require 'djinn'


# This class generates a Python Google App Engine application that
# relays an error message to the user as to why their app failed to come up.
class ErrorApp

#
# Constructor
#
# Args:
# app_name: Name of the application to construct an error application for.
# error_msg: A String message that will be displayed as the reason
# why we couldn't start their application.
def initialize(app_name, error_msg)
@app_name = app_name
@error_msg = error_msg
@dir_path = "/var/apps/#{app_name}/app/"
end

#
# This function places an updated app.yaml and error.py into the application
# and retars the application file.
#
# Args: None
def generate()
app_yaml = <<CONFIG
application: #{@app_name}
version: 1
runtime: python
api_version: 1

handlers:
- url: .*
script: #{@app_name}.py
CONFIG

script = <<SCRIPT
from google.appengine.ext import webapp
import cgi
import datetime
import wsgiref.handlers
class MainPage(webapp.RequestHandler):
def get(self):
self.response.out.write('<html><body>')
self.response.out.write("""<p>Your application failed to start</p>""")
self.response.out.write("""<p>#{@error_msg}</p>""")
self.response.out.write("""<p>If this is an AppScale issue please report it on <a href="https://github.com/AppScale/appscale/issues">http://github.com/AppScale/appscale/issues</a></p>""")
self.response.out.write('</body></html>')

application = webapp.WSGIApplication([
('/', MainPage),
], debug=True)


def main():
wsgiref.handlers.CGIHandler().run(application)


if __name__ == '__main__':
main()

SCRIPT

HelperFunctions.write_file(@dir_path + 'app.yaml', app_yaml)
HelperFunctions.write_file(@dir_path + "#{@app_name}.py", script)

Djinn.log_run("rm #{@dir_path}/#{@app_name}.tar.gz")
Dir.chdir(@dir_path) do
Djinn.log_debug("Running: tar zcvf #{@dir_path}/#{@app_name}.tar.gz #{@dir_path}")
Djinn.log_run("tar zcvf #{@app_name}.tar.gz app.yaml #{@app_name}.py")
end

return true
end

end

2 changes: 1 addition & 1 deletion AppController/lib/helperfunctions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class BadConfigurationException < Exception
module HelperFunctions


VER_NUM = "1.5"
VER_NUM = "1.6.3"


APPSCALE_HOME = ENV['APPSCALE_HOME']
Expand Down
Loading