Alex Lourie has uploaded a new change for review. Change subject: packaging: setup: remote DB installation over otopi ......................................................................
packaging: setup: remote DB installation over otopi Change-Id: Ib9b24feb5bf063fb47ab10efaa4f16e1762c8b2c Signed-off-by: Alex Lourie <[email protected]> --- M packaging/common_utils.py M packaging/ovirt-engine-dwh-setup.py 2 files changed, 215 insertions(+), 89 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-dwh refs/changes/13/18813/1 diff --git a/packaging/common_utils.py b/packaging/common_utils.py index 26dca97..d512552 100755 --- a/packaging/common_utils.py +++ b/packaging/common_utils.py @@ -584,7 +584,7 @@ return True return False -def createReadOnlyUser(db_dict, PGPASS_FILE): +def createReadOnlyUser(database, user, password, secured): # Check whether we can create DB: global DB_ADMIN @@ -596,34 +596,7 @@ if not canCreateDb: return (False, errorMsg) - # Ask user how would the user be created - createReadUser = askYesNo( - question=( - '\nThis utility can configure a read only user for DB access. ' - 'Would you like to do so?' - ) - ) - - if not createReadUser: - logging.debug('Skipping creation of read only DB user.') - print 'Skipping creationg of read only DB user.' - return (True, '') - - user = askQuestion( - question='Provide a username for read-only user' - ) - - password = getpass.getpass( - prompt='Provide a password for read-only user: ' - ) - - secured = askYesNo( - question=( - 'Should postgresql be setup with secure connection?' - ) - ) - - updatePgHba(db_dict['name'], user) + updatePgHba(database, user) configurePostgres(user, secured) if secured: createCertificate() @@ -631,11 +604,11 @@ createUser( user=user, password=password, - database=db_dict['name'], + database=database, ) updateReadOnly( user=user, - database=db_dict['name'], + database=database, ) return (True, '') @@ -803,16 +776,16 @@ def getDbSize(db_dict, PGPASS_FILE): # Returns db size in MB - sql = "SELECT pg_database_size(\'%s\')" % db_dict['name'] + sql = "SELECT pg_database_size(\'%s\')" % db_dict['dbname'] # Work with db credentials copy, rename db name to template1 db_copy = db_dict.copy() - db_copy['name'] = 'template1' + db_copy['dbname'] = 'template1' out, rc = parseRemoteSqlCommand( db_dict=db_copy, sqlQuery=sql, failOnError=True, - errMsg=ERR_DB_GET_SPACE % db_dict['name'], + errMsg=ERR_DB_GET_SPACE % db_dict['dbname'], envDict={'ENGINE_PGPASS': PGPASS_FILE} ) size = int(out[0]['pg_database_size']) @@ -861,7 +834,7 @@ if not proceed or not askYesNo( proceed.format( - db=db_dict['name'] + db=db_dict['dbname'] ) ): raise UserWarning( @@ -878,7 +851,7 @@ db_dict = DB connection object """ - logging.debug("%s DB Backup started", db_dict['name']) + logging.debug("%s DB Backup started", db_dict['dbname']) # Run backup cmd = [ @@ -895,7 +868,7 @@ '-p', db_dict['port'], '-Fc', '-f', backup_file, - db_dict['name'], + db_dict['dbname'], ] execCmd( cmdList=cmd, @@ -903,7 +876,7 @@ msg='Error during DB backup.', envDict={'ENGINE_PGPASS': PGPASS_FILE} ) - logging.debug("%s DB Backup completed successfully", db_dict['name']) + logging.debug("%s DB Backup completed successfully", db_dict['dbname']) def getUsernameId(username): @@ -930,7 +903,7 @@ ).format( host=db_dict['host'], port=db_dict['port'], - database='*' if mode == 'all' else db_dict['name'], + database='*' if mode == 'all' else db_dict['dbname'], user=db_dict['username'], password=db_dict['password'], ), @@ -944,6 +917,24 @@ ''.join([random.choice(string.digits) for i in xrange(4)]), ''.join([random.choice(string.letters) for i in xrange(4)]), ) + + +def createDB(db_dict): + sql_query_set = [ + ( + '"DROP DATABASE {database};"'.format( + database=db_dict['dbname'], + ) + ), + ( + '"CREATE DATABASE {database} owner {owner};"'.format( + database=db_dict['dbname'], + owner=db_dict['username'], + ) + ), + ] + for sql_query in sql_query_set: + runPostgresSuQuery(sql_query) def createUser(user, password, option='', database=''): @@ -1096,26 +1087,7 @@ ), ] for sql_query in sql_query_set: - sql_command = [ - EXEC_PSQL, - '-U', 'postgres', - '-c', - sql_query, - ] - cmd = [ - EXEC_SU, - '-l', - 'postgres', - '-c', - '{command}'.format( - command=' '.join(sql_command), - ) - ] - - execCmd( - cmdList=cmd, - failOnError=True - ) + runPostgresSuQuery(sql_query) return True @@ -1187,3 +1159,34 @@ def restorePgHba(): return configHbaIdent('ident', 'md5') +def runPostgresSuQuery(query, database=None, failOnError=True): + sql_command = [ + EXEC_PSQL, + '-U', 'postgres', + ] + if database is not None: + sql_command.extend( + ( + '-d', database + ) + ) + sql_command.extend( + ( + '-c', query, + ) + ) + cmd = [ + EXEC_SU, + '-l', + 'postgres', + '-c', + '{command}'.format( + command=' '.join(sql_command), + ) + ] + + return execCmd( + cmdList=cmd, + failOnError=failOnError + ) + diff --git a/packaging/ovirt-engine-dwh-setup.py b/packaging/ovirt-engine-dwh-setup.py index 56d1e84..8b337fb 100755 --- a/packaging/ovirt-engine-dwh-setup.py +++ b/packaging/ovirt-engine-dwh-setup.py @@ -19,6 +19,9 @@ import glob import shutil import argparse +import getpass +import types +import cracklib import common_utils as utils from decorators import transactionDisplay log_file = None @@ -26,7 +29,7 @@ DWH_PACKAGE_NAME="ovirt-engine-dwh" PATH_DB_SCRIPTS="/usr/share/ovirt-engine-dwh/db-scripts" PATH_WATCHDOG="/usr/share/ovirt-engine-dwh/etl/ovirt_engine_dwh_watchdog.cron" -EXEC_CREATE_DB="%s/ovirt-engine-history-db-install.sh" % PATH_DB_SCRIPTS +EXEC_CREATE_SCHEMA="create_schema.sh" EXEC_UPGRADE_DB="upgrade.sh" FILE_DB_CONN = "/etc/ovirt-engine/ovirt-engine-dwh/Default.properties" FILE_ENGINE_CONF_DEFAULTS = "/usr/share/ovirt-engine/conf/engine.conf.defaults" @@ -93,19 +96,40 @@ password=db_dict['password'], option='createdb', ) - utils.updatePgHba(db_dict['name'], db_dict['username']) + utils.createDB(db_dict['dbname'], db_dict['username']) + utils.updatePgHba(db_dict['dbname'], db_dict['username']) utils.restartPostgres() install = 'local' else: install = 'remote' + print 'Remote installation is selected.\n' + ( + db_dict['host'], + db_dict['port'], + db_dict['username'], + db_dict['password'], + ) = getDbCredentials() + if not utils.dbExists(db_dict, PGPASS_TEMP): + raise RuntimeError ( + ( + 'Remote installation failed. Please perform ' + '\tcreate role {role} with login ' + 'encrypted password {password};\n' + '\tcreate {db} owner {role}\n' + 'on the remote DB, verify it and rerun the setup.' + ).format( + role=db_dict['username'], + db=db_dict['dbname'], + password=db_dict['password'], + ) + ) cmd = [ - EXEC_CREATE_DB, + os.path.join(PATH_DB_SCRIPTS, EXEC_CREATE_SCHEMA), '-l', dbLogFilename, '-u', db_dict['username'], '-s', db_dict['host'], '-p', db_dict['port'], - '-r', install, ] # Create db using shell command @@ -131,13 +155,13 @@ currDir = os.getcwd() try: cmd = [ - os.path.join(PATH_DB_SCRIPTS, EXEC_UPGRADE_DB), - "-s", db_dict["host"], - "-p", db_dict["port"], - "-u", db_dict["username"], - "-d", db_dict["name"], - "-l", "/var/log/ovirt-engine/%s" % dbLogFilename, - ] + os.path.join(PATH_DB_SCRIPTS, EXEC_UPGRADE_DB), + "-s", db_dict["host"], + "-p", db_dict["port"], + "-u", db_dict["username"], + "-d", db_dict["name"], + "-l", "/var/log/ovirt-engine/%s" % dbLogFilename, + ] os.chdir(PATH_DB_SCRIPTS) output, rc = utils.execCmd( cmdList=cmd, @@ -149,6 +173,63 @@ os.chdir(currDir) raise +def getPassFromUser(string): + """ + get a single password from the user + """ + userInput = getpass.getpass(string) + if type(userInput) != types.StringType or len(userInput) == 0: + print "Cannot accept an empty password" + return getPassFromUser(string) + + try: + cracklib.FascistCheck(userInput) + except: + print "Warning: Weak Password." + + return userInput + +def getDbCredentials( + hostdefault='', + portdefault='', + userdefault='', +): + """ + get db params from user + """ + print ( + 'Remote installation selected. Make sure that DBA creates a user ' + 'and the database in the following fashion:' + '\tcreate role <role> with login ' + 'encrypted password <password>;\n' + '\tcreate ovirt_engine_history owner <role>;\n' + ) + + dbhost = utils.askQuestion( + question='Enter the host name for the DB server: ', + default=hostdefault, + ) + + dbport = utils.askQuestion( + question='Enter the port of the remote DB server: ', + default=portdefault or '5432', + ) + + dbuser = utils.askQuestion( + question='Provide a remote DB user: ', + default=userdefault, + ) + + userInput = getPassFromUser( + 'Please choose a password for the db user: ' + ) + # We do not need verification for the re-entered password + userInput2 = getpass.getpass("Re-type password: ") + if userInput != userInput2: + print "ERROR: passwords don't match" + return getDbCredentials(dbhost, dbport, dbuser) + + return (dbhost, dbport, dbuser, userInput) def getDbDictFromOptions(): if os.path.exists(FILE_DATABASE_CONFIG): @@ -159,7 +240,7 @@ dhandler = utils.TextConfigFileHandler(FILE_DATABASE_DWH_CONFIG) dhandler.open() db_dict = { - 'name': ( + 'dbname': ( dhandler.getParam('DWH_DATABASE') or DB_NAME ), @@ -173,6 +254,10 @@ dhandler.getParam('DWH_PASSWORD') or utils.generatePassword() ), + 'readonly': ( + dhandler.getParam('DWH_READONLY_USER') or + None + ), 'engine_user': handler.getParam('ENGINE_DB_USER'), 'engine_pass': handler.getParam('ENGINE_DB_PASSWORD').replace('"', ''), } @@ -180,11 +265,12 @@ dhandler.close() else: db_dict = { - 'name': DB_NAME, + 'dbname': DB_NAME, 'host': utils.getDbHostName(), 'port': utils.getDbPort(), 'username': utils.getDbAdminUser(), 'password': utils.getPassFromFile(utils.getDbAdminUser()), + 'readonly': None, } return db_dict @@ -265,17 +351,24 @@ os.makedirs(dwh_path) os.chmod(dwh_path, 0644) with open(FILE_DATABASE_DWH_CONFIG, 'w') as fdwh: - fdwh.write( - ( - 'DWH_USER={user}\n' - 'DWH_PASSWORD={password}\n' - 'DWH_DATABASE={database}' - ).format( - user=db_dict['username'], - password=db_dict['password'], - database=db_dict['name'], - ) + content = ( + 'DWH_USER={user}\n' + 'DWH_PASSWORD={password}\n' + 'DWH_DATABASE={database}\n' + ).format( + user=db_dict['username'], + password=db_dict['password'], + database=db_dict['dbname'], ) + + if db_dict['readonly'] is not None: + content += ( + 'DWH_READONLY_USER={readonly}\n' + ).format( + readonly=db_dict['readonly'], + ) + + fdwh.write(content) # Get minimal supported version from oVirt Engine minimalVersion = utils.getVDCOption("MinimalETLVersion") @@ -299,6 +392,43 @@ PGPASS_TEMP = utils.createTempPgpass(db_dict) if utils.localHost(db_dict['host']): pg_updated = utils.configHbaIdent() + + # Handle postgres configuration for the read-only user + # on local installations only + + readUserCreated = False + errMsg = '' + if db_dict['readonly'] is None: + # Ask user how would the user be created + createReadUser = utils.askYesNo( + question=( + '\nThis utility can configure a read only user for DB access. ' + 'Would you like to do so?' + ) + ) + + if not createReadUser: + logging.debug('Skipping creation of read only DB user.') + print 'Skipping creationg of read only DB user.' + else: + user = utils.askQuestion( + question='Provide a username for read-only user' + ) + password = getpass.getpass( + prompt='Provide a password for read-only user: ' + ) + secured = utils.askYesNo( + question=( + 'Should postgresql be setup with secure connection?' + ) + ) + readUserCreated, errMsg = utils.createReadOnlyUser( + db_dict['dbname'], + user, + password, + secured, + ) + if dbExists(db_dict): try: doBackup = utils.performBackup(db_dict, DB_BACKUPS_DIR, PGPASS_TEMP) @@ -328,13 +458,6 @@ else: createDB(db_dict) - # Handle postgres configuration for the read-only user - # on local installations only - - readUserCreated = False - errMsg = '' - if utils.localHost(db_dict["host"]): - readUserCreated, errMsg = utils.createReadOnlyUser(db_dict, PGPASS_TEMP) # Start Services utils.startEngine() -- To view, visit http://gerrit.ovirt.org/18813 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ib9b24feb5bf063fb47ab10efaa4f16e1762c8b2c Gerrit-PatchSet: 1 Gerrit-Project: ovirt-dwh Gerrit-Branch: master Gerrit-Owner: Alex Lourie <[email protected]> _______________________________________________ Engine-patches mailing list [email protected] http://lists.ovirt.org/mailman/listinfo/engine-patches
