From 3ac561534b999d16bb09b84d9a92faa021c05d99 Mon Sep 17 00:00:00 2001 From: Fabrice Bellingard Date: Sun, 20 May 2012 16:48:03 +0200 Subject: [PATCH] SONAR-3218 / SONAR-3146 Improve the Sonar migration service - Offers better mechanism to prevent any parallel executions - Provides information on the time already spent - Adapt UI & WS to use this mechanism --- .../app/controllers/api/server_controller.rb | 14 ++- .../app/controllers/setup_controller.rb | 39 +++--- .../app/models/database_migration_manager.rb | 114 ++++++++++++++++++ .../app/views/setup/db_uptodate.html.erb | 11 ++ .../WEB-INF/app/views/setup/dbdown.html.erb | 9 ++ .../WEB-INF/app/views/setup/dbdown.rhtml | 6 - .../WEB-INF/app/views/setup/failed.html.erb | 7 ++ .../WEB-INF/app/views/setup/form.html.erb | 14 +++ .../webapp/WEB-INF/app/views/setup/form.rhtml | 33 ----- .../views/setup/migration_running.html.erb | 15 +++ .../app/views/setup/not_upgradable.html.erb | 5 - .../src/main/webapp/stylesheets/style.css | 7 ++ 12 files changed, 208 insertions(+), 66 deletions(-) create mode 100644 sonar-server/src/main/webapp/WEB-INF/app/models/database_migration_manager.rb create mode 100644 sonar-server/src/main/webapp/WEB-INF/app/views/setup/db_uptodate.html.erb create mode 100644 sonar-server/src/main/webapp/WEB-INF/app/views/setup/dbdown.html.erb delete mode 100644 sonar-server/src/main/webapp/WEB-INF/app/views/setup/dbdown.rhtml create mode 100644 sonar-server/src/main/webapp/WEB-INF/app/views/setup/failed.html.erb create mode 100644 sonar-server/src/main/webapp/WEB-INF/app/views/setup/form.html.erb delete mode 100644 sonar-server/src/main/webapp/WEB-INF/app/views/setup/form.rhtml create mode 100644 sonar-server/src/main/webapp/WEB-INF/app/views/setup/migration_running.html.erb delete mode 100644 sonar-server/src/main/webapp/WEB-INF/app/views/setup/not_upgradable.html.erb diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/server_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/server_controller.rb index 7ab010d6465..e81924ec968 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/server_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/server_controller.rb @@ -66,12 +66,14 @@ class Api::ServerController < Api::ApiController def setup begin - if !DatabaseVersion.production? - raise "Upgrade is not supported. Please use a production-ready database." - end - - DatabaseVersion.upgrade_and_start unless DatabaseVersion.uptodate? - hash={:status => 'ok'} + # Ask the DB migration manager to start the migration + # => No need to check for authorizations (actually everybody can run the upgrade) + # nor concurrent calls (this is handled directly by DatabaseMigrationManager) + DatabaseMigrationManager.instance.start_migration + + hash={:status => 'ok', + :migration_status => DatabaseMigrationManager.instance.status, + :message => DatabaseMigrationManager.instance.message} respond_to do |format| format.json{ render :json => jsonp(hash) } format.xml { render :xml => hash.to_xml(:skip_types => true, :root => 'setup') } diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/setup_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/setup_controller.rb index a3d79c8e4f5..2cac046bdbc 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/setup_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/setup_controller.rb @@ -25,26 +25,33 @@ class SetupController < ApplicationController verify :method => :post, :only => [ :setup_database ], :redirect_to => { :action => :index } def index - if DatabaseVersion.uptodate? - redirect_to home_path - elsif ActiveRecord::Base.connected? - render :template => (DatabaseVersion.production? ? 'setup/form' : 'setup/not_upgradable'), :layout => 'nonav' - else - render :template => 'setup/dbdown', :layout => 'nonav' + if DatabaseMigrationManager.instance.requires_migration? + if ActiveRecord::Base.connected? + render :template => 'setup/form', :layout => 'nonav' + else + render :template => 'setup/dbdown', :layout => 'nonav' + end + elsif DatabaseMigrationManager.instance.migration_running? + render :template => 'setup/migration_running', :layout => 'nonav' + elsif DatabaseMigrationManager.instance.migration_failed? + render :template => 'setup/failed', :layout => 'nonav' + else + # migration succeeded, or no need for migration + render :template => 'setup/db_uptodate', :layout => 'nonav' end end - def maintenance - render :template => 'setup/maintenance', :layout => 'nonav' + def setup_database + # Ask the DB migration manager to start the migration + # => No need to check for authorizations (actually everybody can run the upgrade) + # nor concurrent calls (this is handled directly by DatabaseMigrationManager) + DatabaseMigrationManager.instance.start_migration + # and return some text that will actually never be displayed + render :text => DatabaseMigrationManager.instance.message end - def setup_database - if !DatabaseVersion.production? - render :text => 'Upgrade is not supported. Please use a production-ready database.', :status => 500 - else - # do not forget that this code is also in /api/server/setup (see api/server_controller.rb) - DatabaseVersion.upgrade_and_start unless DatabaseVersion.uptodate? - redirect_to home_path - end + def maintenance + render :template => 'setup/maintenance', :layout => 'nonav' end + end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/database_migration_manager.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/database_migration_manager.rb new file mode 100644 index 00000000000..4f3072cac33 --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/database_migration_manager.rb @@ -0,0 +1,114 @@ +# +# Sonar, entreprise quality control tool. +# Copyright (C) 2008-2012 SonarSource +# mailto:contact AT sonarsource DOT com +# +# Sonar is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 3 of the License, or (at your option) any later version. +# +# Sonar is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with Sonar; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 +# + +# +# Class taht centralizes the management the DB migration +# + +require 'singleton' +require 'thread' + +class DatabaseMigrationManager + + # mixin the singleton module to ensure we have only one instance of the class + # it will be accessible with "DatabaseMigrationManager.instance" + include Singleton + + # the status of the migration + @status + MIGRATION_NEEDED = "MIGRATION_NEEDED" + MIGRATION_RUNNING = "MIGRATION_RUNNING" + MIGRATION_FAILED = "MIGRATION_FAILED" + MIGRATION_SUCCEEDED = "MIGRATION_SUCCEEDED" + NO_MIGRATION = "NO_MIGRATION" + + # the corresponding message that can be given to the user + @message + + # the time when the migration was started + @start_time + + def initialize + if DatabaseVersion.uptodate? + @status = NO_MIGRATION + @message = "Database is up-to-date, no migration needed." + else + if DatabaseVersion.production? + @status = MIGRATION_NEEDED + @message = "Migration required." + else + @status = MIGRATION_FAILED + @message = "Upgrade is not supported. Please use a production-ready database." + end + end + end + + def message + @message + end + + def status + @status + end + + def requires_migration? + @status==MIGRATION_NEEDED + end + + def migration_running? + @status==MIGRATION_RUNNING + end + + def migration_failed? + @status==MIGRATION_FAILED + end + + def migration_start_time + @start_time + end + + def start_migration + # Use an exclusive block of code to ensure that only 1 thread will be able to proceed with the migration + can_start_migration = false + Thread.exclusive do + if requires_migration? + @status = MIGRATION_RUNNING + @message = "Database migration is currently running." + can_start_migration = true + end + end + + if can_start_migration + # launch the upgrade + begin + @start_time = Time.now + DatabaseVersion.upgrade_and_start + @status = MIGRATION_SUCCEEDED + @message = "The migration succeeded." + rescue Exception => e + @status = MIGRATION_FAILED + @message = "The migration failed: " + e.clean_message + ".
Please check the logs." + # rethrow the exception so that it is logged and so that the whole system knows that a problem occured + raise + end + end + end + +end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/setup/db_uptodate.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/setup/db_uptodate.html.erb new file mode 100644 index 00000000000..7029edacb8d --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/setup/db_uptodate.html.erb @@ -0,0 +1,11 @@ + + +
+ <%= image_tag 'accept.png' -%> + Database is up-to-date. +
+
+ You will be redirected shortly to Sonar. +
+ (if this doesn't happen, you can click here to be redirected.) +
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/setup/dbdown.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/setup/dbdown.html.erb new file mode 100644 index 00000000000..c98fee7d30b --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/setup/dbdown.html.erb @@ -0,0 +1,9 @@ +
+ <%= image_tag 'warning.png' -%> + Fail to connect to database +
+
+ Database connection cannot be established. Please check database status and JDBC settings. +
+ <%= button_to "Try again", { :action => "index" }, :method => :get %> +
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/setup/dbdown.rhtml b/sonar-server/src/main/webapp/WEB-INF/app/views/setup/dbdown.rhtml deleted file mode 100644 index fe3786216d4..00000000000 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/setup/dbdown.rhtml +++ /dev/null @@ -1,6 +0,0 @@ -

Fail to connect to database

-
- Database connection cannot be established. Please check database status and JDBC settings. -

-<%= button_to "Try again", { :action => "index" }, :method => :get %> -
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/setup/failed.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/setup/failed.html.erb new file mode 100644 index 00000000000..5c4306fc70d --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/setup/failed.html.erb @@ -0,0 +1,7 @@ +
+ <%= image_tag 'exclamation.png' -%> + Impossible to upgrade database +
+
+ <%= DatabaseMigrationManager.instance.message -%> +
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/setup/form.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/setup/form.html.erb new file mode 100644 index 00000000000..51052b9e739 --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/setup/form.html.erb @@ -0,0 +1,14 @@ +
+

Upgrade database

+
+

Important

+ +
+ <%= button_to_remote "Upgrade", + :url => { :action => 'setup_database' }, + :loading => "window.location.reload();" -%> +
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/setup/form.rhtml b/sonar-server/src/main/webapp/WEB-INF/app/views/setup/form.rhtml deleted file mode 100644 index 3e765f936a8..00000000000 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/setup/form.rhtml +++ /dev/null @@ -1,33 +0,0 @@ - - -
- -

Upgrade database

-
-

Important

-

-

-

-
-
- -
-
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/setup/migration_running.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/setup/migration_running.html.erb new file mode 100644 index 00000000000..cee75c53e0c --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/setup/migration_running.html.erb @@ -0,0 +1,15 @@ + + +<% + start_time = DatabaseMigrationManager.instance.migration_start_time +%> + +
+ <%= image_tag 'loading.gif' -%> + Database upgrade is currently running. +
+
+ Started : <%= l start_time -%> +
+ Duration: <%= distance_of_time_in_words(start_time, Time.now) -%> +
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/setup/not_upgradable.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/setup/not_upgradable.html.erb deleted file mode 100644 index bd3c0f12e17..00000000000 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/setup/not_upgradable.html.erb +++ /dev/null @@ -1,5 +0,0 @@ -

Not supported

- -
- Upgrade is not supported. Please use a production-ready database. -
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/stylesheets/style.css b/sonar-server/src/main/webapp/stylesheets/style.css index 6a4174cc180..6889c394644 100644 --- a/sonar-server/src/main/webapp/stylesheets/style.css +++ b/sonar-server/src/main/webapp/stylesheets/style.css @@ -522,6 +522,13 @@ h4, .h4 { padding: 4px; } +/* ------------------- SETUP / MIGRATION PAGES ------------------- */ +.migration { + background-image: url("../images/sonar.png"); + background-repeat: no-repeat; + background-position: top right; +} + /* ------------------- LOGIN FORM ------------------- */ #login_form { border: 1px solid #4b9fd5; -- 2.39.5