On 12/21/2012 01:41 PM, Cleber Rosa wrote:
A utility designed to perform a complete autotest database creation
and initialization at once.
Currently, to get an autotest server running one needs to either run
the "install-autotest-server.sh" script, or follow a long list of
steps. This tool will allow users of say, autotest-server distro
specific packages to just run a command and have it setup.
This is awesome, slowly we're making the install process a lot better. I
have some comments below:
Signed-off-by: Cleber Rosa <[email protected]>
---
contrib/install-autotest-server.sh | 50 +----
installation_support/autotest-database-turnkey | 279 +++++++++++++++++++++++++
installation_support/common.py | 14 ++
3 files changed, 302 insertions(+), 41 deletions(-)
create mode 100755 installation_support/autotest-database-turnkey
create mode 100644 installation_support/common.py
diff --git a/contrib/install-autotest-server.sh
b/contrib/install-autotest-server.sh
index 83dbe2b..1c2d8c3 100755
--- a/contrib/install-autotest-server.sh
+++ b/contrib/install-autotest-server.sh
@@ -324,11 +324,12 @@ chmod 775 $ATHOME
}
check_mysql_password() {
-print_log "INFO" "Verifying MySQL root password"
+print_log "INFO" "Setting MySQL root password"
mysqladmin -u root password $MYSQLPW > /dev/null 2>&1
-DB=$(echo "use autotest_web;" | mysql --user=root --password=$MYSQLPW 2>&1)
-if [ "$(echo $DB | grep 'Access denied')" != "" ]
+print_log "INFO" "Verifying MySQL root password"
+$ATHOME/installation_support/autotest-database-turnkey --check-credentials
--root-password=$MYSQLPW
+if [ $? != 0 ]
then
print_log "ERROR" "MySQL already has a different root password"
exit 1
@@ -336,15 +337,12 @@ fi
}
create_autotest_database() {
-if [ "$(echo $DB | grep 'Unknown database')" != "" ]
+print_log "INFO" "Creating MySQL databases for autotest"
+$ATHOME/installation_support/autotest-database-turnkey -s --root-password=$MYSQLPW -p
$MYSQLPW > /dev/null 2>&1
+if [ $? != 0 ]
then
- print_log "INFO" "Creating MySQL databases for autotest"
- cat << SQLEOF | mysql --user=root --password=$MYSQLPW >> $LOG
-create database autotest_web;
-grant all privileges on autotest_web.* TO 'autotest'@'localhost' identified by
"$MYSQLPW";
-grant SELECT on autotest_web.* TO 'nobody'@'%';
-grant SELECT on autotest_web.* TO 'nobody'@'localhost';
-SQLEOF
+ print_log "ERROR" "Error creating MySQL database"
+ exit 1
fi
}
@@ -388,32 +386,6 @@ else
fi
}
-configure_autotest() {
-print_log "INFO" "Setting up the autotest configuration files"
-
-# TODO: notify_email in [SCHEDULER] section of global_config.ini
-
-cat << EOF | su - autotest >> $LOG 2>&1
-/usr/local/bin/substitute please_set_this_password "$MYSQLPW"
$ATHOME/global_config.ini
-EOF
-}
-
-setup_databse_schema() {
-TABLES=$(echo "use autotest_web; show tables;" | mysql --user=root
--password=$MYSQLPW 2>&1)
-
-if [ "$(echo $TABLES | grep tko_test_view_outer_joins)" = "" ]
-then
- print_log "INFO" "Setting up the database schemas"
- cat << EOF | su - autotest >> $LOG 2>&1
-yes yes | $ATHOME/database/migrate.py --database=AUTOTEST_WEB sync
-yes no | /usr/local/autotest/frontend/manage.py syncdb
-/usr/local/autotest/frontend/manage.py syncdb
-EOF
-else
- print_log "INFO" "Database schemas are already in place"
-fi
-}
-
restart_mysql_deb() {
print_log "INFO" "Re-starting MySQL server"
service mysql restart >> $LOG
@@ -601,8 +573,6 @@ full_install() {
create_autotest_database
build_external_packages
configure_webserver_rh
- configure_autotest
- setup_databse_schema
restart_mysql_rh
patch_python27_bug
build_web_rpc_client
@@ -622,8 +592,6 @@ full_install() {
create_autotest_database
build_external_packages
configure_webserver_deb
- configure_autotest
- setup_databse_schema
restart_mysql_deb
build_web_rpc_client
import_tests
diff --git a/installation_support/autotest-database-turnkey
b/installation_support/autotest-database-turnkey
new file mode 100755
index 0000000..a981b9a
--- /dev/null
+++ b/installation_support/autotest-database-turnkey
@@ -0,0 +1,279 @@
+#!/usr/bin/env python
+
+
+"""
+This script attemps to make it trivial to create the Autotest server database
+and populate with the needed schema, all in one simple command
+"""
+
+
+import os
+import re
+import logging
+import optparse
+
+import MySQLdb
+import django.core.management
+
+try:
+ import autotest.common as common
+except ImportError:
+ import common
+
+from autotest.client.shared import global_config
+from autotest.database.migrate import MigrationManager
+from autotest.database.database_connection import DatabaseConnection
+from autotest.frontend import setup_django_environment
+
+
+DB_ADMIN_USER = 'root'
+
+
+def database_already_exists(database, user, password, hostname='localhost'):
+ '''
+ Detects if the given password exist by trying to connect to it
+ '''
+ try:
+ connection = MySQLdb.connect(user=user, passwd=password, db=database,
+ host=hostname)
+ return True
+ except MySQLdb.OperationalError:
+ return False
+
+
+def admin_credentials_valid(password, hostname='localhost'):
+ '''
+ Checks if the database admin (root) credential is valid
+ '''
+ try:
+ connection = MySQLdb.connect(user=DB_ADMIN_USER, passwd=password)
+ return True
+ except:
+ return False
Catching all exceptions here might mask the fact that there are other
problems going on with the database rather than just invalid
credentials, as I see. Isn't it better to catch a more specific error
and handle other problems differently (maybe even terminating the
script, and saying something about the error)?
+
+def create_database(database, root_password='',
+ hostname='localhost', conn=None, transaction=False):
+ if conn is None:
+ if not admin_credentials_valid(root_password, hostname):
+ logging.error("Failed to logon as the database admin user")
+ return False
+ conn = MySQLdb.connect(user=DB_ADMIN_USER, passwd=root_password)
+
+ if database_already_exists(database, DB_ADMIN_USER, root_password,
+ hostname):
+ logging.info("Database already exists, doing nothing")
+ return True
+
+ if transaction:
+ conn.begin()
+
+ curs = conn.cursor()
+ try:
+ curs.execute("CREATE DATABASE %s" % database)
+ except MySQLdb.ProgrammingError, MySQLdb.OperationalError:
+ conn.rollback()
+ return False
+
+ if transaction:
+ conn.commit()
+
+ return True
+
+
+def database_setup(database, user, password, root_password,
+ hostname='localhost'):
+ '''
+ Attempts to create database AND users AND set privileges
+ '''
+ # To actually give the privileges, we use the root user
+ if not admin_credentials_valid(root_password, hostname):
+ logging.error("Failed to logon as the database admin user")
+ return False
+
+ conn = MySQLdb.connect(user=DB_ADMIN_USER, passwd=root_password)
+ conn.begin()
+ curs = conn.cursor()
+
+ if not create_database(database, hostname=hostname,
+ root_password=root_password, conn=conn):
+ conn.rollback()
+ return False
+
+
+ GRANT_CMDS = ["grant all privileges on %(database)s.* TO "
+ "'%(user)s'@'localhost' identified by '%(password)s'",
+ "grant SELECT on %(database)s.* TO 'nobody'@'%%'",
+ "grant SELECT on %(database)s.* TO 'nobody'@'localhost'"]
+ for cmd in GRANT_CMDS:
+ cmd_ = cmd % locals()
^ What's the purpose of passing locals() to the db command?
+ try:
+ curs.execute(cmd_)
+ except:
+ conn.rollback()
+ return False
+
+ conn.commit()
+ return True
+
+
+def set_global_config_value(section, key, value):
+ '''
+ Sets a value on the configuration file
+
+ It does so by reading all lines an rewriting the one needed. This is
+ far from efficient and should only be used to perform changes to a
+ handful of configuration values
+ '''
global_config.ini is a .ini file, that can be parsed and modified using
ConfigParser (which seems much simpler and robust), so I didn't quite
understand why to do things this way. I'm taking your word that this was
really necessary... but I'd like to read some words on the why.
_______________________________________________
Autotest-kernel mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/autotest-kernel