Alex Lourie has uploaded a new change for review.

Change subject: [WIP] packaging: Added postgres listening external network
......................................................................

[WIP] packaging: Added postgres listening external network

This patch adds the interaction for the user allowing
to setup the local postgres to listen on external
connections.

The patch will check if there's 'local' db definition and
will only offer to configure it in local installation. It
will also create a read-only role with user-provided
credentials and open the required iptable ports if necessary.

1. iptables is not yet handled.
2. in 3.3 we might not have required permissions.

Change-Id: Ibdd133a392fb3dba6088a9fb12ce4ca828f24073
Bug-Url: https://bugzilla.redhat.com/737598
Signed-off-by: Alex Lourie <[email protected]>
---
M packaging/common_utils.py
M packaging/ovirt-engine-dwh-setup.py
2 files changed, 164 insertions(+), 7 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-dwh refs/changes/64/15964/1

diff --git a/packaging/common_utils.py b/packaging/common_utils.py
index 91c70c0..77a8648 100755
--- a/packaging/common_utils.py
+++ b/packaging/common_utils.py
@@ -175,25 +175,41 @@
     def delParams(self, paramsDict):
         pass
 
-def askYesNo(question=None):
+def askQuestion(question=None, yesNo=False, options=''):
     '''
     provides an interface that prompts the user
     to answer "yes/no" to a given question
     '''
     message = StringIO()
-    ask_string = "%s? (yes|no): " % question
+    if yesNo:
+        options = '(yes|no)'
+    ask_string = "{question}? {options}: ".format(
+        question=question,
+        options=options,
+    )
     logging.debug("asking user: %s" % ask_string)
     message.write(ask_string)
     message.seek(0)
     raw_answer = raw_input(message.read())
     logging.debug("user answered: %s"%(raw_answer))
     answer = raw_answer.lower()
-    if answer == "yes" or answer == "y":
-        return True
-    elif answer == "no" or answer == "n":
-        return False
+    if yesNo:
+        if answer == "yes" or answer == "y":
+            return True
+        elif answer == "no" or answer == "n":
+            return False
+        else:
+            return askQuestion(question, yesNo=True)
     else:
-        return askYesNo(question)
+        return answer or askQuestion(question, options)
+
+def askYesNo(question=None):
+    '''
+    provides an interface that prompts the user
+    to answer "yes/no" to a given question
+    '''
+    askQuestion(question, yesNo=True)
+
 
 def execSqlCmd(db_dict, sql_query, fail_on_error=False, err_msg="Failed 
running sql query"):
     logging.debug("running sql query on host: %s, port: %s, db: %s, user: %s, 
query: \'%s\'." %
@@ -500,6 +516,141 @@
         return True
     return False
 
+def createReadOnlyUser(db_dict):
+
+    # Ask user how would the user be created
+    createUser = askYesNo(
+        question=(
+            '\nThis utility can configure a read only user for DB access. '
+            'Would you like to do so'
+        )
+    )
+
+    if not createUser:
+        logging.debug('Skipping creationg of read only DB user.')
+        print 'Skipping creationg of read only DB user.'
+        return
+
+    user = askQuestion(
+        question='Provide a username for read-only user'
+    )
+
+    password = askQuestion(
+        question='Provide a password for read-only user'
+    )
+
+    # TODO: Do we have permissions for the following??
+    configurePostgres(user)
+    createDbUser(
+        db_dict=db_dict,
+        user=user,
+        password=password
+    )
+    configureIptables()
+
+def configurePostgres(user):
+    postgresConf = '/var/lib/pgsql/data/postgresql.conf'
+    pgHba = '/var/lib/pgsql/data/pg_hba.conf'
+
+    # postgres.conf
+    with open(postgresConf, 'r') as f:
+        configured = False
+        content = []
+        for line in f.read().splitlines():
+            if (
+                not configured and
+                line.startswith('#listen_addresses')
+            ):
+               content.append("listen_addresses = '*'")
+               configured = True
+
+            if line.startswith('listen_addresses'):
+                line = '#' + line
+
+            content.append(line)
+
+    # TODO: backup!!!
+    with open(postgresConf, 'w') as f:
+        f.write('\n'.join(content))
+
+    # pg_hba.conf
+    with open(pgHba, 'r') as f:
+        configured = False
+        content = []
+        userline = (
+            '{host:7} '
+            '{user:15} '
+            '{database:15} '
+            '{address:23} '
+            '{auth}'
+        ).format(
+            host='host',
+            user=user,
+            database='ovirt_engine_history',
+            address='all',
+            auth='md5',
+        )
+
+        for line in f.read().splitlines():
+            content.append(line)
+            if (
+                not configured and
+                'local' in line
+            ):
+                content.append(userline)
+                configured = True
+
+
+        if not configured:
+            content.append(userline)
+
+    # TODO: backup!!!
+    with open(pgHba, 'w') as f:
+        f.write('\n'.join(content))
+
+    restartPostgres()
+
+def configureIptables():
+    pass
+
+def createDbUser(db_dict, user, password):
+    # Basically, run psql with CREATE ROLE user WITH login encrypted password
+    querySet =(
+        (
+            'create role {user} with login encrypted password {password};'
+        ).format(
+            user=user,
+            password=password
+        ),
+        (
+            'alter user {user} set default_transaction_read_only to true;'
+        ).format(
+            user=user
+        ),
+    )
+    for query in querySet:
+        execSqlCmd(
+            db_dict=db_dict,
+            sql_query=query,
+            fail_on_error=True,
+            err_msg='Failed to execute {query}'.format(query=query),
+        )
+
+def restartPostgres():
+    cmd = [
+        'service',
+        'postgres',
+        'restart'
+    ]
+
+    execCmd(
+        cmdList=cmd,
+        failOnError=True,
+        msg='Failed to restart postgres'
+    )
+
+
+
 #TODO: Move all execution commands to execCmd
 def execCmd(cmdList, cwd=None, failOnError=False, msg=ERR_RC_CODE, 
maskList=[], useShell=False, usePipeFiles=False, envDict={}):
     """
diff --git a/packaging/ovirt-engine-dwh-setup.py 
b/packaging/ovirt-engine-dwh-setup.py
index 06a9f62..cffe116 100755
--- a/packaging/ovirt-engine-dwh-setup.py
+++ b/packaging/ovirt-engine-dwh-setup.py
@@ -193,6 +193,12 @@
             else:
                 createDB(db_dict)
 
+            # Handle postgres configuration for the read-only user
+            # on local installations only
+
+            if utils.localHost(db_dict["host"]):
+                utils.createReadOnlyUser(db_dict)
+
             # Start Services
             utils.startEngine()
             # Sleep for 20 secs to allow health applet to start


-- 
To view, visit http://gerrit.ovirt.org/15964
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ibdd133a392fb3dba6088a9fb12ce4ca828f24073
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

Reply via email to