Skip to content

Commit

Permalink
Merge pull request #11 from TimSimpsonR/set_failed_if_mysql_install_f…
Browse files Browse the repository at this point in the history
…ails

Set the service status to FAILED if the MySQL install failed.
  • Loading branch information
Tim Simpson committed Jul 10, 2012
2 parents 4a20371 + ffb9f67 commit 7b788da
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 32 deletions.
58 changes: 28 additions & 30 deletions src/nova/guest/mysql/MySqlApp.cc
@@ -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"
Expand Down Expand Up @@ -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) {
Expand Down
6 changes: 6 additions & 0 deletions src/nova/guest/mysql/MySqlAppStatus.cc
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions src/nova/guest/mysql/MySqlAppStatus.h
Expand Up @@ -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();
Expand Down
10 changes: 8 additions & 2 deletions tests/nova/guest/mysql/MySqlAppStatus_tests.cc
Expand Up @@ -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);
Expand All @@ -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 {
Expand All @@ -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
{
Expand Down

0 comments on commit 7b788da

Please sign in to comment.