Alon Bar-Lev has uploaded a new change for review. Change subject: packaging: setup: reusable postresql provisioning ......................................................................
packaging: setup: reusable postresql provisioning took the simple approach... each installer will use provisioning as-is, it may cause postgres multiple restarts and such, but it keeps loosely coupled components. Change-Id: Ieff824fa5115954925f8fd7cabf59d535f39e96c Signed-off-by: Alon Bar-Lev <[email protected]> --- M packaging/setup/ovirt_engine_setup/constants.py A packaging/setup/ovirt_engine_setup/postgres.py A packaging/setup/plugins/ovirt-engine-setup/ovirt-engine-common/provisioning/__init__.py A packaging/setup/plugins/ovirt-engine-setup/ovirt-engine-common/provisioning/postgres.py M packaging/setup/plugins/ovirt-engine-setup/ovirt-engine/provisioning/postgres.py 5 files changed, 688 insertions(+), 507 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/21/23121/1 diff --git a/packaging/setup/ovirt_engine_setup/constants.py b/packaging/setup/ovirt_engine_setup/constants.py index f3f4914..f39ed5a 100644 --- a/packaging/setup/ovirt_engine_setup/constants.py +++ b/packaging/setup/ovirt_engine_setup/constants.py @@ -496,7 +496,6 @@ DB_CONNECTION_SETUP = 'osetup.db.connection.setup' DB_CONNECTION_CUSTOMIZATION = 'osetup.db.connection.customization' DB_CONNECTION_STATUS = 'osetup.db.connection.status' - DB_HOST_LOCATION_CUSTOMIZATION = 'osetup.db.hostlocation.customization' DB_CREDENTIALS_AVAILABLE_EARLY = 'osetup.db.connection.credentials.early' DB_CREDENTIALS_AVAILABLE_LATE = 'osetup.db.connection.credentials.late' DB_CONNECTION_AVAILABLE = 'osetup.db.connection.available' diff --git a/packaging/setup/ovirt_engine_setup/postgres.py b/packaging/setup/ovirt_engine_setup/postgres.py new file mode 100644 index 0000000..7add279 --- /dev/null +++ b/packaging/setup/ovirt_engine_setup/postgres.py @@ -0,0 +1,556 @@ +# +# ovirt-engine-setup -- ovirt engine setup +# Copyright (C) 2013 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + + +import datetime +import os +import platform +import random +import re +import time +import gettext +_ = lambda m: gettext.dgettext(message=m, domain='ovirt-engine-setup') + + +from otopi import base +from otopi import util +from otopi import transaction +from otopi import filetransaction +from otopi import constants as otopicons + + +from ovirt_engine_setup import constants as osetupcons +from ovirt_engine_setup import database +from ovirt_engine_setup import util as osetuputil + + [email protected] +class AlternateUser(object): + def __init__(self, user): + self._user = osetuputil.getUid(user) + + def __enter__(self): + os.seteuid(self._user) + + def __exit__(self, exc_type, exc_value, traceback): + os.seteuid(os.getuid()) + + [email protected] +class Provisioning(base.Base): + + _PASSWORD_CHARS = ( + '0123456789' + + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + + 'abcdefghijklmnopqrstuvwxyz' + ) + + _RE_POSTGRES_PGHBA_LOCAL = re.compile( + flags=re.VERBOSE, + pattern=r""" + ^ + (?P<host>local) + \s+ + .* + \s+ + (?P<param>\w+) + $ + """, + ) + + _RE_KEY_VALUE = re.compile( + flags=re.VERBOSE, + pattern=r""" + ^ + \s* + (?P<key>\w+) + \s* + = + \s* + (?P<value>\w+) + """, + ) + + @property + def environment(self): + return self._plugin.environment + + @property + def command(self): + return self._plugin.command + + @property + def services(self): + return self._plugin.services + + @property + def databaseRenamed(self): + return self._renamedDBResources + + def _setDatabaseResources(self, environment): + dbstatement = database.Statement( + dbenvkeys=self._dbenvkeys, + environment=environment, + ) + hasDatabase = dbstatement.execute( + statement=""" + select count(*) as count + from pg_database + where datname = %(database)s + """, + args=dict( + database=self.environment[ + self._dbenvkeys['database'] + ], + ), + ownConnection=True, + transaction=False, + )[0]['count'] != 0 + hasUser = dbstatement.execute( + statement=""" + select count(*) as count + from pg_user + where usename = %(user)s + """, + args=dict( + user=self.environment[ + self._dbenvkeys['user'] + ], + ), + ownConnection=True, + transaction=False, + )[0]['count'] != 0 + + generate = hasDatabase or hasUser + existing = False + + if hasDatabase and hasUser: + dbovirtutils = database.OvirtUtils( + plugin=self, + dbenvkeys=self._dbenvkeys, + environment=environment, + ) + if dbovirtutils.isNewDatabase( + database=self.environment[ + self._dbenvkeys['database'] + ], + ): + self.logger.debug('Found empty database') + generate = False + existing = True + else: + generate = True + + if generate: + self.logger.debug('Existing resources found, generating names') + suffix = '_%s' % datetime.datetime.now().strftime('%Y%m%d%H%M%S') + self.environment[self._dbenvkeys['database']] += suffix + self.environment[self._dbenvkeys['user']] += suffix + self._renamedDBResources = True + + return existing + + def _performDatabase( + self, + environment, + op, + ): + statements = [ + ( + """ + {op} role {user} + with + login + encrypted password %(password)s + """ + ).format( + op=op, + user=self.environment[ + self._dbenvkeys['user'] + ], + ), + + ( + """ + {op} database {database} + owner {to} {user} + {encoding} + """ + ).format( + op=op, + to='to' if op == 'alter' else '', + database=self.environment[ + self._dbenvkeys['database'] + ], + user=self.environment[ + self._dbenvkeys['user'] + ], + encoding=""" + template template0 + encoding 'UTF8' + lc_collate 'en_US.UTF-8' + lc_ctype 'en_US.UTF-8' + """ if op != 'alter' else '', + ), + ] + + dbstatement = database.Statement( + dbenvkeys=self._dbenvkeys, + environment=environment, + ) + for statement in statements: + dbstatement.execute( + statement=statement, + args=dict( + password=self.environment[ + self._dbenvkeys['password'] + ], + ), + ownConnection=True, + transaction=False, + ) + + def _initDbIfRequired(self): + if not os.path.exists( + self.environment[ + osetupcons.ProvisioningEnv.POSTGRES_PG_VERSION + ] + ): + self.logger.info(_('Initializing PostgreSQL')) + + setup = self.command.get( + command='postgresql-setup', + optional=True + ) + if setup is not None: + # new method (post-systemd) + self._plugin.execute( + ( + setup, + 'initdb', + ), + ) + else: + # old method (pre-systemd) + self._plugin.execute( + ( + os.path.join( + osetupcons.FileLocations.SYSCONFDIR, + 'init.d', + self.environment[ + osetupcons.ProvisioningEnv.POSTGRES_SERVICE + ], + ), + 'initdb', + ), + ) + + def _updateMaxConnections( + self, + transaction, + maxconn, + ): + with open( + self.environment[ + osetupcons.ProvisioningEnv.POSTGRES_CONF + ] + ) as f: + content = f.read().splitlines() + + needUpdate = True + for l in content: + m = self._RE_KEY_VALUE.match(l) + if ( + m is not None and + m.group('key') == 'max_connections' and + int(m.group('value')) >= int(maxconn) + ): + needUpdate = False + break + + if needUpdate: + content = osetuputil.editConfigContent( + content=content, + params={ + 'max_connections': maxconn, + }, + ) + + transaction.append( + filetransaction.FileTransaction( + name=self.environment[ + osetupcons.ProvisioningEnv.POSTGRES_CONF + ], + content=content, + modifiedList=self.environment[ + otopicons.CoreEnv.MODIFIED_FILES + ], + ), + ) + self.environment[ + osetupcons.CoreEnv.UNINSTALL_UNREMOVABLE_FILES + ].append( + self.environment[ + osetupcons.ProvisioningEnv.POSTGRES_CONF + ] + ) + + def _setPgHbaLocalPeer( + self, + transaction, + ): + content = [] + with open( + self.environment[ + osetupcons.ProvisioningEnv.POSTGRES_PG_HBA + ] + ) as f: + for line in f.read().splitlines(): + matcher = self._RE_POSTGRES_PGHBA_LOCAL.match(line) + if matcher is not None: + line = line.replace( + matcher.group('param'), + 'ident', # we cannot use peer <psql-9 + ) + content.append(line) + + transaction.append( + filetransaction.FileTransaction( + name=self.environment[ + osetupcons.ProvisioningEnv.POSTGRES_PG_HBA + ], + content=content, + visibleButUnsafe=True, + ) + ) + + def _addPgHbaDatabaseAccess( + self, + transaction, + ): + lines = [ + # we cannot use all for address <psql-9 + ( + '{host:7} ' + '{user:15} ' + '{database:15} ' + '{address:23} ' + '{auth}' + ).format( + host='host', + user=self.environment[ + self._dbenvkeys['user'] + ], + database=self.environment[ + self._dbenvkeys['database'] + ], + address=address, + auth='md5', + ) + for address in ('0.0.0.0/0', '::0/0') + ] + + content = [] + with open( + self.environment[ + osetupcons.ProvisioningEnv.POSTGRES_PG_HBA + ] + ) as f: + for line in f.read().splitlines(): + if line not in lines: + content.append(line) + + # order is important, add after local + # so we be first + if line.lstrip().startswith('local'): + content.extend(lines) + + transaction.append( + filetransaction.FileTransaction( + name=self.environment[ + osetupcons.ProvisioningEnv.POSTGRES_PG_HBA + ], + content=content, + modifiedList=self.environment[ + otopicons.CoreEnv.MODIFIED_FILES + ], + ) + ) + self.environment[ + osetupcons.CoreEnv.UNINSTALL_UNREMOVABLE_FILES + ].append( + self.environment[ + osetupcons.ProvisioningEnv.POSTGRES_PG_HBA + ] + ) + + def _restart(self): + for state in (False, True): + self.services.state( + name=self.environment[ + osetupcons.ProvisioningEnv.POSTGRES_SERVICE + ], + state=state, + ) + + def _waitForDatabase(self, environment=None): + dbovirtutils = database.OvirtUtils( + plugin=self, + dbenvkeys=self._dbenvkeys, + ) + for i in range(60): + try: + self.logger.debug('Attempting to connect database') + dbovirtutils.tryDatabaseConnect(environment=environment) + break + except RuntimeError: + self.logger.debug( + 'Database connection failed', + exc_info=True, + ) + time.sleep(1) + except Exception: + self.logger.debug( + 'Database connection failed, unknown exception', + exc_info=True, + ) + raise + + def __init__( + self, + plugin, + dbenvkeys, + defaults, + ): + super(Provisioning, self).__init__() + self._plugin = plugin + self._dbenvkeys = dbenvkeys + self._defaults = defaults + self._renamedDBResources = False + + def detectCommands(self): + self.command.detect('postgresql-setup') + + def supported(self): + return platform.linux_distribution( + full_distribution_name=0 + )[0] in ('redhat', 'fedora', 'centos') + + def validate(self): + if not self.services.exists( + name=self.environment[ + osetupcons.ProvisioningEnv.POSTGRES_SERVICE + ] + ): + raise RuntimeError( + _( + 'Database configuration was requested, ' + 'however, postgresql service was not found. ' + 'This may happen because postgresql database ' + 'is not installed on system.' + ) + ) + + def generatePassword(self): + return ''.join([random.choice(self._PASSWORD_CHARS) for i in range(8)]) + + def applyEnvironment(self): + for k in ('user', 'database', 'port', 'secured', 'hostValidation'): + self.environment[self._dbenvkeys[k]] = self._defaults[k] + self.environment[self._dbenvkeys['password']] = self.generatePassword() + + def provision(self): + if not self.supported(): + raise RuntimeError( + _( + 'Unsupported distribution for ' + 'postgresql proisioning' + ) + ) + + self._initDbIfRequired() + + self.logger.info( + _("Creating PostgreSQL '{database}' database").format( + database=self.environment[self._dbenvkeys['database']], + ) + ) + localtransaction = transaction.Transaction() + try: + localtransaction.prepare() + + self._setPgHbaLocalPeer( + transaction=localtransaction, + ) + + self._restart() + + with AlternateUser( + user=self.environment[ + osetupcons.SystemEnv.USER_POSTGRES + ], + ): + usockenv = { + self._dbenvkeys['host']: '', # usock + self._dbenvkeys['port']: '', + self._dbenvkeys['secured']: False, + self._dbenvkeys['hostValidation']: False, + self._dbenvkeys['user']: 'postgres', + self._dbenvkeys['password']: '', + self._dbenvkeys['database']: 'template1', + } + self._waitForDatabase( + environment=usockenv, + ) + existing = self._setDatabaseResources( + environment=usockenv, + ) + self._performDatabase( + environment=usockenv, + op=( + 'alter' if existing + else 'create' + ), + ) + finally: + # restore everything + localtransaction.abort() + + self.logger.info(_('Configuring PostgreSQL')) + with transaction.Transaction() as localtransaction: + self._updateMaxConnections( + transaction=localtransaction, + maxconn=self.environment[ + osetupcons.ProvisioningEnv.POSTGRES_MAX_CONN + ], + ) + self._addPgHbaDatabaseAccess( + transaction=localtransaction, + ) + + self.services.startup( + name=self.environment[ + osetupcons.ProvisioningEnv.POSTGRES_SERVICE + ], + state=True, + ) + + self._restart() + self._waitForDatabase() + + +# vim: expandtab tabstop=4 shiftwidth=4 diff --git a/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine-common/provisioning/__init__.py b/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine-common/provisioning/__init__.py new file mode 100644 index 0000000..42fd126 --- /dev/null +++ b/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine-common/provisioning/__init__.py @@ -0,0 +1,33 @@ +# +# ovirt-engine-setup -- ovirt engine setup +# Copyright (C) 2013 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + + +"""Provisioning plugin.""" + + +from otopi import util + + +from . import postgres + + [email protected] +def createPlugins(context): + postgres.Plugin(context=context) + + +# vim: expandtab tabstop=4 shiftwidth=4 diff --git a/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine-common/provisioning/postgres.py b/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine-common/provisioning/postgres.py new file mode 100644 index 0000000..8804c1a --- /dev/null +++ b/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine-common/provisioning/postgres.py @@ -0,0 +1,66 @@ +# +# ovirt-engine-setup -- ovirt engine setup +# Copyright (C) 2013 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + + +"""Local Postgres plugin.""" + + +import gettext +_ = lambda m: gettext.dgettext(message=m, domain='ovirt-engine-setup') + + +from otopi import util +from otopi import plugin + + +from ovirt_engine_setup import constants as osetupcons + + [email protected] +class Plugin(plugin.PluginBase): + """Local Postgres plugin.""" + + def __init__(self, context): + super(Plugin, self).__init__(context=context) + + @plugin.event( + stage=plugin.Stages.STAGE_INIT, + ) + def _init(self): + self.environment.setdefault( + osetupcons.ProvisioningEnv.POSTGRES_CONF, + osetupcons.Defaults.DEFAULT_POSTGRES_PROVISIONING_PG_CONF + ) + self.environment.setdefault( + osetupcons.ProvisioningEnv.POSTGRES_PG_HBA, + osetupcons.Defaults.DEFAULT_POSTGRES_PROVISIONING_PG_HBA + ) + self.environment.setdefault( + osetupcons.ProvisioningEnv.POSTGRES_PG_VERSION, + osetupcons.Defaults.DEFAULT_POSTGRES_PROVISIONING_PG_VERSION + ) + self.environment.setdefault( + osetupcons.ProvisioningEnv.POSTGRES_SERVICE, + osetupcons.Defaults.DEFAULT_POSTGRES_PROVISIONING_SERVICE + ) + self.environment.setdefault( + osetupcons.ProvisioningEnv.POSTGRES_MAX_CONN, + osetupcons.Defaults.DEFAULT_POSTGRES_PROVISIONING_MAX_CONN + ) + + +# vim: expandtab tabstop=4 shiftwidth=4 diff --git a/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine/provisioning/postgres.py b/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine/provisioning/postgres.py index 3f676a0..f6441b1 100644 --- a/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine/provisioning/postgres.py +++ b/packaging/setup/plugins/ovirt-engine-setup/ovirt-engine/provisioning/postgres.py @@ -19,345 +19,41 @@ """Local Postgres plugin.""" -import os -import platform -import re -import random -import datetime -import time import gettext _ = lambda m: gettext.dgettext(message=m, domain='ovirt-engine-setup') from otopi import util -from otopi import transaction -from otopi import filetransaction from otopi import plugin -from otopi import constants as otopicons from ovirt_engine_setup import constants as osetupcons -from ovirt_engine_setup import database from ovirt_engine_setup import dialog -from ovirt_engine_setup import util as osetuputil +from ovirt_engine_setup import postgres @util.export class Plugin(plugin.PluginBase): """Local Postgres plugin.""" - _PASSWORD_CHARS = ( - '0123456789' + - 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + - 'abcdefghijklmnopqrstuvwxyz' - ) - - _RE_POSTGRES_PGHBA_LOCAL = re.compile( - flags=re.VERBOSE, - pattern=r""" - ^ - (?P<host>local) - \s+ - .* - \s+ - (?P<param>\w+) - $ - """ - ) - - class _alternateUser(object): - def __init__(self, user): - self._user = osetuputil.getUid(user) - - def __enter__(self): - os.seteuid(self._user) - - def __exit__(self, exc_type, exc_value, traceback): - os.seteuid(os.getuid()) - - def _generatePassword(self): - return ''.join([random.choice(self._PASSWORD_CHARS) for i in range(8)]) - - def _initDB(self): - self.logger.info(_('Initializing PostgreSQL')) - - setup = self.command.get( - command='postgresql-setup', - optional=True - ) - if setup is not None: - # new method (post-systemd) - self.execute( - ( - setup, - 'initdb', - ), - ) - else: - # old method (pre-systemd) - self.execute( - ( - os.path.join( - osetupcons.FileLocations.SYSCONFDIR, - 'init.d', - self.environment[ - osetupcons.ProvisioningEnv.POSTGRES_SERVICE - ], - ), - 'initdb', - ), - ) - - def _updateMaxConnections( - self, - transaction, - filename, - maxconn, - ): - with open(filename, 'r') as f: - content = osetuputil.editConfigContent( - content=f.read().splitlines(), - params={ - 'max_connections': maxconn, - }, - ) - - transaction.append( - filetransaction.FileTransaction( - name=filename, - content=content, - modifiedList=self.environment[ - otopicons.CoreEnv.MODIFIED_FILES - ], - ), - ) - self.environment[ - osetupcons.CoreEnv.UNINSTALL_UNREMOVABLE_FILES - ].append(filename) - - def _setPgHbaLocalPeer( - self, - transaction, - filename, - ): - content = [] - with open(filename, 'r') as f: - for line in f.read().splitlines(): - matcher = self._RE_POSTGRES_PGHBA_LOCAL.match(line) - if matcher is not None: - line = line.replace( - matcher.group('param'), - 'ident', # we cannot use peer <psql-9 - ) - content.append(line) - - transaction.append( - filetransaction.FileTransaction( - name=filename, - content=content, - visibleButUnsafe=True, - ) - ) - - def _addPgHbaDatabaseAccess( - self, - transaction, - filename, - ): - lines = [ - # we cannot use all for address <psql-9 - ( - '{host:7} ' - '{user:15} ' - '{database:15} ' - '{address:23} ' - '{auth}' - ).format( - host='host', - user=self.environment[ - osetupcons.DBEnv.USER - ], - database=self.environment[ - osetupcons.DBEnv.DATABASE - ], - address=address, - auth='md5', - ) - for address in ('0.0.0.0/0', '::0/0') - ] - - content = [] - with open(filename, 'r') as f: - for line in f.read().splitlines(): - if line not in lines: - content.append(line) - - # order is important, add after local - # so we be first - if line.lstrip().startswith('local'): - content.extend(lines) - - transaction.append( - filetransaction.FileTransaction( - name=filename, - content=content, - modifiedList=self.environment[ - otopicons.CoreEnv.MODIFIED_FILES - ], - ) - ) - self.environment[ - osetupcons.CoreEnv.UNINSTALL_UNREMOVABLE_FILES - ].append(filename) - - def _waitDatabase(self, environment=None): - dbovirtutils = database.OvirtUtils( - plugin=self, - dbenvkeys=osetupcons.Const.ENGINE_DB_ENV_KEYS, - ) - for i in range(60): - try: - self.logger.debug('Attempting to connect database') - dbovirtutils.tryDatabaseConnect(environment=environment) - break - except RuntimeError: - self.logger.debug( - 'Database connection failed', - exc_info=True, - ) - time.sleep(1) - except Exception: - self.logger.debug( - 'Database connection failed, unknown exception', - exc_info=True, - ) - raise - - def _setDatabaseResources(self, environment): - dbstatement = database.Statement( - dbenvkeys=osetupcons.Const.ENGINE_DB_ENV_KEYS, - environment=environment, - ) - hasDatabase = dbstatement.execute( - statement=""" - select count(*) as count - from pg_database - where datname = %(database)s - """, - args=dict( - database=self.environment[ - osetupcons.DBEnv.DATABASE - ], - ), - ownConnection=True, - transaction=False, - )[0]['count'] != 0 - hasUser = dbstatement.execute( - statement=""" - select count(*) as count - from pg_user - where usename = %(user)s - """, - args=dict( - user=self.environment[ - osetupcons.DBEnv.USER - ], - ), - ownConnection=True, - transaction=False, - )[0]['count'] != 0 - - generate = hasDatabase or hasUser - existing = False - - if hasDatabase and hasUser: - dbovirtutils = database.OvirtUtils( - plugin=self, - dbenvkeys=osetupcons.Const.ENGINE_DB_ENV_KEYS, - environment=environment, - ) - if dbovirtutils.isNewDatabase( - database=self.environment[ - osetupcons.DBEnv.DATABASE - ], - ): - self.logger.debug('Found empty database') - generate = False - existing = True - else: - generate = True - - if generate: - self.logger.debug('Existing resources found, generating names') - suffix = '_%s' % datetime.datetime.now().strftime('%Y%m%d%H%M%S') - self.environment[osetupcons.DBEnv.DATABASE] += suffix - self.environment[osetupcons.DBEnv.USER] += suffix - self._renamedDBResources = True - - return existing - - def _performDatabase( - self, - environment, - op, - user, - password, - databaseName, - ): - statements = [ - ( - """ - {op} role {user} - with - login - encrypted password %(password)s - """ - ).format( - op=op, - user=user, - ), - - ( - """ - {op} database {database} - owner {to} {user} - {encoding} - """ - ).format( - op=op, - to='to' if op == 'alter' else '', - database=databaseName, - user=user, - encoding=""" - template template0 - encoding 'UTF8' - lc_collate 'en_US.UTF-8' - lc_ctype 'en_US.UTF-8' - """ if op != 'alter' else '', - ), - ] - - dbstatement = database.Statement( - dbenvkeys=osetupcons.Const.ENGINE_DB_ENV_KEYS, - environment=environment, - ) - for statement in statements: - dbstatement.execute( - statement=statement, - args=dict( - password=password, - ), - ownConnection=True, - transaction=False, - ) - def __init__(self, context): super(Plugin, self).__init__(context=context) self._enabled = False self._renamedDBResources = False - self._distribution = platform.linux_distribution( - full_distribution_name=0 - )[0] + self._provisioning = postgres.Provisioning( + plugin=self, + dbenvkeys=osetupcons.Const.ENGINE_DB_ENV_KEYS, + defaults={ + 'user': osetupcons.Defaults.DEFAULT_DB_USER, + 'database': osetupcons.Defaults.DEFAULT_DB_DATABASE, + 'port': osetupcons.Defaults.DEFAULT_DB_PORT, + 'secured': osetupcons.Defaults.DEFAULT_DB_SECURED, + 'hostValidation': ( + osetupcons.Defaults. + DEFAULT_DB_SECURED_HOST_VALIDATION + ), + }, + ) @plugin.event( stage=plugin.Stages.STAGE_INIT, @@ -366,26 +62,6 @@ self.environment.setdefault( osetupcons.ProvisioningEnv.POSTGRES_PROVISIONING_ENABLED, None - ) - self.environment.setdefault( - osetupcons.ProvisioningEnv.POSTGRES_CONF, - osetupcons.Defaults.DEFAULT_POSTGRES_PROVISIONING_PG_CONF - ) - self.environment.setdefault( - osetupcons.ProvisioningEnv.POSTGRES_PG_HBA, - osetupcons.Defaults.DEFAULT_POSTGRES_PROVISIONING_PG_HBA - ) - self.environment.setdefault( - osetupcons.ProvisioningEnv.POSTGRES_PG_VERSION, - osetupcons.Defaults.DEFAULT_POSTGRES_PROVISIONING_PG_VERSION - ) - self.environment.setdefault( - osetupcons.ProvisioningEnv.POSTGRES_SERVICE, - osetupcons.Defaults.DEFAULT_POSTGRES_PROVISIONING_SERVICE - ) - self.environment.setdefault( - osetupcons.ProvisioningEnv.POSTGRES_MAX_CONN, - osetupcons.Defaults.DEFAULT_POSTGRES_PROVISIONING_MAX_CONN ) @plugin.event( @@ -403,13 +79,12 @@ ), ) def _setup(self): - self.command.detect('postgresql-setup') + self._provisioning.detectCommands() - self._enabled = self._distribution in ('redhat', 'fedora', 'centos') + self._enabled = self._provisioning.supported() @plugin.event( stage=plugin.Stages.STAGE_CUSTOMIZATION, - name=osetupcons.Stages.DB_HOST_LOCATION_CUSTOMIZATION, before=( osetupcons.Stages.DIALOG_TITLES_E_DATABASE, osetupcons.Stages.DB_CONNECTION_CUSTOMIZATION, @@ -427,7 +102,8 @@ dialog=self.dialog, name='OVESETUP_PROVISIONING_POSTGRES_LOCATION', note=_( - 'Where is the database located? (@VALUES@) [@DEFAULT@]: ' + 'Where is the Engine database located? ' + '(@VALUES@) [@DEFAULT@]: ' ), prompt=True, true=_('Local'), @@ -453,7 +129,8 @@ 'automatically for the engine to run. This may ' 'conflict with existing applications.\n' 'Would you like Setup to automatically configure ' - 'postgresql, or prefer to perform that ' + 'postgresql and create Engine database, ' + 'or prefer to perform that ' 'manually? (@VALUES@) [@DEFAULT@]: ' ), prompt=True, @@ -462,51 +139,18 @@ default=True, ) - self._enabled = self.environment[ + if self.environment[ osetupcons.ProvisioningEnv.POSTGRES_PROVISIONING_ENABLED - ] - - if self._enabled: - - self.environment[ - osetupcons.DBEnv.USER - ] = osetupcons.Defaults.DEFAULT_DB_USER - - self.environment[ - osetupcons.DBEnv.PASSWORD - ] = self._generatePassword() - - self.environment[otopicons.CoreEnv.LOG_FILTER].append( - self.environment[ - osetupcons.DBEnv.PASSWORD - ] - ) - - self.environment[ - osetupcons.DBEnv.DATABASE - ] = osetupcons.Defaults.DEFAULT_DB_DATABASE - - self.environment[ - osetupcons.DBEnv.SECURED - ] = osetupcons.Defaults.DEFAULT_DB_SECURED - - self.environment[ - osetupcons.DBEnv.SECURED_HOST_VALIDATION - ] = osetupcons.Defaults.DEFAULT_DB_SECURED_HOST_VALIDATION + ]: + self._provisioning.applyEnvironment() + self._enabled = True @plugin.event( stage=plugin.Stages.STAGE_CUSTOMIZATION, - before=( - osetupcons.Stages.DIALOG_TITLES_E_DATABASE, - osetupcons.Stages.DB_CONNECTION_CUSTOMIZATION, - ), - after=( - osetupcons.Stages.DIALOG_TITLES_S_DATABASE, - osetupcons.Stages.DB_HOST_LOCATION_CUSTOMIZATION, - ), - condition=lambda self: ( - self.environment[osetupcons.DBEnv.HOST] == 'localhost' - ) + priority=plugin.Stages.PRIORITY_LAST, + condition=lambda self: self.environment[ + osetupcons.DBEnv.HOST + ] == 'localhost', ) def _customization_firewall(self): self.environment[osetupcons.NetEnv.FIREWALLD_SERVICES].extend([ @@ -521,19 +165,7 @@ condition=lambda self: self._enabled, ) def _validation(self): - if not self.services.exists( - name=self.environment[ - osetupcons.ProvisioningEnv.POSTGRES_SERVICE - ] - ): - raise RuntimeError( - _( - 'Database configuration was requested, ' - 'however, postgresql service was not found. ' - 'This may happen because postgresql database ' - 'is not installed on system.' - ) - ) + self._provisioning.validate() @plugin.event( stage=plugin.Stages.STAGE_MISC, @@ -547,112 +179,7 @@ condition=lambda self: self._enabled, ) def _misc(self): - - if not os.path.exists( - self.environment[ - osetupcons.ProvisioningEnv.POSTGRES_PG_VERSION - ] - ): - self._initDB() - - self.logger.info(_('Creating PostgreSQL database')) - localtransaction = transaction.Transaction() - try: - localtransaction.prepare() - - self._setPgHbaLocalPeer( - transaction=localtransaction, - filename=self.environment[ - osetupcons.ProvisioningEnv.POSTGRES_PG_HBA - ], - ) - - # restart to take effect - for state in (False, True): - self.services.state( - name=self.environment[ - osetupcons.ProvisioningEnv.POSTGRES_SERVICE - ], - state=state, - ) - - with self._alternateUser( - user=self.environment[ - osetupcons.SystemEnv.USER_POSTGRES - ], - ): - usockenv = { - osetupcons.DBEnv.HOST: '', # usock - osetupcons.DBEnv.PORT: '', - osetupcons.DBEnv.SECURED: False, - osetupcons.DBEnv.SECURED_HOST_VALIDATION: False, - osetupcons.DBEnv.USER: 'postgres', - osetupcons.DBEnv.PASSWORD: '', - osetupcons.DBEnv.DATABASE: 'template1', - } - self._waitDatabase( - environment=usockenv, - ) - existing = self._setDatabaseResources( - environment=usockenv, - ) - self._performDatabase( - environment=usockenv, - op=( - 'alter' if existing - else 'create' - ), - user=self.environment[ - osetupcons.DBEnv.USER - ], - password=self.environment[ - osetupcons.DBEnv.PASSWORD - ], - databaseName=self.environment[ - osetupcons.DBEnv.DATABASE - ], - ) - finally: - # restore everything - localtransaction.abort() - - self.logger.info(_('Configuring PostgreSQL')) - localtransaction = transaction.Transaction() - with localtransaction: - self._addPgHbaDatabaseAccess( - transaction=localtransaction, - filename=self.environment[ - osetupcons.ProvisioningEnv.POSTGRES_PG_HBA - ], - ) - - self._updateMaxConnections( - transaction=localtransaction, - filename=self.environment[ - osetupcons.ProvisioningEnv.POSTGRES_CONF - ], - maxconn=self.environment[ - osetupcons.ProvisioningEnv.POSTGRES_MAX_CONN - ], - ) - - # restart to take effect - for state in (False, True): - self.services.state( - name=self.environment[ - osetupcons.ProvisioningEnv.POSTGRES_SERVICE - ], - state=state, - ) - - self.services.startup( - name=self.environment[ - osetupcons.ProvisioningEnv.POSTGRES_SERVICE - ], - state=True, - ) - - self._waitDatabase() + self._provisioning.provision() @plugin.event( stage=plugin.Stages.STAGE_CLOSEUP, @@ -662,12 +189,12 @@ after=( osetupcons.Stages.DIALOG_TITLES_S_SUMMARY, ), - condition=lambda self: self._renamedDBResources, + condition=lambda self: self._provisioning.databaseRenamed, ) def _closeup(self): self.dialog.note( text=_( - 'Database resources:\n' + 'Engine database resources:\n' ' Database name: {database}\n' ' Database user name: {user}\n' ).format( -- To view, visit http://gerrit.ovirt.org/23121 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ieff824fa5115954925f8fd7cabf59d535f39e96c Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Alon Bar-Lev <[email protected]> _______________________________________________ Engine-patches mailing list [email protected] http://lists.ovirt.org/mailman/listinfo/engine-patches
