Permalink
Browse files

Set the service status to FAILED if the MySQL install failed.

* Added some comments to the hard to follow MySqlAppStatus tests.
  • Loading branch information...
1 parent 4a20371 commit ffb9f67fa0fbe4bc54297bcd23079358b394090c @TimSimpsonR TimSimpsonR committed Jul 10, 2012
@@ -1,5 +1,6 @@
#include "nova/guest/mysql/MySqlApp.h"
#include "nova/guest/apt.h"
+#include <exception>
#include <boost/format.hpp>
#include <fstream>
#include "nova/utils/io.h"
@@ -173,38 +174,35 @@ void MySqlApp::install_and_secure(AptGuest & apt, int memory_mb) {
NOVA_LOG_INFO("Updating status to BUILDING...");
status->begin_mysql_install();
- // You may wonder why there's no try / catch around this section which
- // would change status to a failure state if something went wrong.
- // The reason why is that the Reddwarf compute manager will time out the
- // instance. If we added a catch here, it would be harder to test this
- // ability of the Reddwarf compute manager. We may find a way to add error
- // handling here anyway as it would speed up acknowledgement of failures,
- // but the bigger priority is making sure the manager retains the ability
- // to determine when a guest is misbehaving.
-
- NOVA_LOG_INFO("Preparing Guest as MySQL Server");
- install_mysql(apt);
-
- string admin_password = mysql::generate_password();
-
- NOVA_LOG_INFO("Generating root password...");
- generate_root_password(local_db);
- NOVA_LOG_INFO("Removing anonymous users...");
- remove_anonymous_user(local_db);
- NOVA_LOG_INFO("Removing root access...");
- remove_remote_root_access(local_db);
- NOVA_LOG_INFO("Creating admin user...");
- create_admin_user(local_db, admin_password);
- NOVA_LOG_INFO("Flushing privileges");
- local_db.get_connection()->flush_privileges();
- local_db.get_connection()->close();
+ try {
+ NOVA_LOG_INFO("Preparing Guest as MySQL Server");
+ install_mysql(apt);
- internal_stop_mysql();
- write_mycnf(apt, memory_mb, admin_password);
- start_mysql();
+ string admin_password = mysql::generate_password();
+
+ NOVA_LOG_INFO("Generating root password...");
+ generate_root_password(local_db);
+ NOVA_LOG_INFO("Removing anonymous users...");
+ remove_anonymous_user(local_db);
+ NOVA_LOG_INFO("Removing root access...");
+ remove_remote_root_access(local_db);
+ NOVA_LOG_INFO("Creating admin user...");
+ create_admin_user(local_db, admin_password);
+ NOVA_LOG_INFO("Flushing privileges");
+ local_db.get_connection()->flush_privileges();
+ local_db.get_connection()->close();
- status->end_install_or_restart();
- NOVA_LOG_INFO("Dbaas preparation complete.");
+ internal_stop_mysql();
+ write_mycnf(apt, memory_mb, admin_password);
+ start_mysql();
+
+ status->end_install_or_restart();
+ NOVA_LOG_INFO("Dbaas preparation complete.");
+ } catch(const std::exception & e) {
+ NOVA_LOG_ERROR2("Error installing MySQL!: %s", e.what());
+ status->end_failed_install();
+ throw;
+ }
}
void MySqlApp::install_mysql(AptGuest & apt) {
@@ -105,6 +105,12 @@ optional<string> MySqlAppStatus::find_mysql_pid_file() const {
return rtn;
}
+void MySqlAppStatus::end_failed_install() {
+ boost::lock_guard<boost::mutex> lock(nova_db_mutex);
+ this->restart_mode = false;
+ this->set_status(FAILED);
+}
+
void MySqlAppStatus::end_install_or_restart() {
boost::lock_guard<boost::mutex> lock(nova_db_mutex);
this->restart_mode = false;
@@ -71,6 +71,10 @@ namespace nova { namespace guest { namespace mysql {
/* Called before restarting MYSQL. */
void begin_mysql_restart();
+ /* Called when MySQL failed to install. Updates Nova DB to
+ * FAILED. */
+ void end_failed_install();
+
/* Called after MySQL is installed or restarted. Updates the Nova
* DB with the actual MySQL status. */
void end_install_or_restart();
@@ -150,7 +150,7 @@ BOOST_AUTO_TEST_CASE(When_row_is_in_build_state) {
BOOST_AUTO_TEST_CASE(When_row_is_in_fail_state) {
CHECK_POINT();
- updater.set_status(MySqlAppStatus::FAILED);
+ updater.end_failed_install();
BOOST_CHECK_EQUAL(updater.is_mysql_installed(), false);
BOOST_CHECK_EQUAL(!updater.get_status_from_nova_db(), false);
@@ -166,6 +166,9 @@ BOOST_AUTO_TEST_CASE(When_row_is_in_fail_state) {
}
BOOST_AUTO_TEST_CASE(After_mysql_is_marked_as_installed_and_mysql_pingable) {
+ // This class mocks MySQL being pingable and working, by making
+ // "on_execute" not throw anything. So this simulates what happens in
+ // the code when MySQL can be pinged.
struct Mock : public virtual MySqlAppStatusDefaultTestContext {
virtual void on_execute(std::stringstream & out, int call_number)
const {
@@ -190,7 +193,10 @@ BOOST_AUTO_TEST_CASE(After_mysql_is_marked_as_installed_and_mysql_pingable) {
BOOST_AUTO_TEST_CASE(After_mysql_is_marked_as_installed_and_mysql_blocked) {
updater.begin_mysql_install(); // Just to be different.
-
+ // This class mocks MySQL being pingable and working for the first call,
+ // but the second time throws an exception. This is simulates what happens
+ // when MySQL is "blocked" - the first ping fails, but the second
+ // process calls work.
struct Mock : public virtual MySqlAppStatusDefaultTestContext {
virtual void on_execute(std::stringstream & out, int call_number) const
{

0 comments on commit ffb9f67

Please sign in to comment.