Move the password prompts back out of the central location

to live with the component code that uses the passwords.
This commit is contained in:
Doug Hellmann 2012-03-15 14:43:35 -04:00
parent 7e9dc5f7fc
commit 6b49b0bfe9
9 changed files with 116 additions and 75 deletions

View File

@ -14,7 +14,6 @@
# License for the specific language governing permissions and limitations
# under the License.
from devstack import exceptions as excp
from devstack import log as logging
from devstack import settings
@ -31,39 +30,7 @@ def make_id(section, option):
def fetch_run_type(config):
run_type = config.getdefaulted("default", "run_type", settings.RUN_TYPE_DEF)
run_type = config.getdefaulted("default", "run_type",
settings.RUN_TYPE_DEF)
run_type = run_type.upper()
return run_type
def fetch_dbdsn(config, pw_gen, dbname=''):
#check the dsn cache
user = config.get("db", "sql_user")
host = config.get("db", "sql_host")
port = config.get("db", "port")
pw = pw_gen.get_password("sql")
#form the dsn (from components we have...)
#dsn = "<driver>://<username>:<password>@<host>:<port>/<database>"
if not host:
msg = "Unable to fetch a database dsn - no sql host found"
raise excp.BadParamException(msg)
driver = config.get("db", "type")
if not driver:
msg = "Unable to fetch a database dsn - no db driver type found"
raise excp.BadParamException(msg)
dsn = driver + "://"
if user:
dsn += user
if pw:
dsn += ":" + pw
if user or pw:
dsn += "@"
dsn += host
if port:
dsn += ":" + port
if dbname:
dsn += "/" + dbname
else:
dsn += "/"
LOG.debug("For database [%s] fetched dsn [%s]" % (dbname, dsn))
return dsn

View File

@ -22,6 +22,7 @@ from devstack import shell as sh
from devstack import utils
#id
# FIXME: This should probably come from the persona
TYPE = settings.DB
LOG = logging.getLogger("devstack.components.db")
@ -43,7 +44,8 @@ SQL_RESET_PW_LINKS = [
BASE_ERROR = 'Currently we do not know how to [%s] for database type [%s]'
#config keys we warm up so u won't be prompted later
WARMUP_PWS = ['sql']
PASSWORD_PROMPT = 'the database user'
WARMUP_PWS = [('sql', PASSWORD_PROMPT)]
class DBUninstaller(comp.PkgUninstallComponent):
@ -52,8 +54,8 @@ class DBUninstaller(comp.PkgUninstallComponent):
self.runtime = DBRuntime(*args, **kargs)
def warm_configs(self):
for pw_key in WARMUP_PWS:
self.pw_gen.get_password(pw_key)
for key, prompt in WARMUP_PWS:
self.pw_gen.get_password(key, prompt)
def pre_uninstall(self):
dbtype = self.cfg.get("db", "type")
@ -67,7 +69,7 @@ class DBUninstaller(comp.PkgUninstallComponent):
LOG.info("Ensuring your database is started before we operate on it.")
self.runtime.restart()
params = {
'OLD_PASSWORD': self.pw_gen.get_password('sql'),
'OLD_PASSWORD': self.pw_gen.get_password('sql', PASSWORD_PROMPT),
'NEW_PASSWORD': RESET_BASE_PW,
'USER': self.cfg.getdefaulted("db", "sql_user", 'root'),
}
@ -89,7 +91,7 @@ class DBInstaller(comp.PkgInstallComponent):
#in pre-install and post-install sections
host_ip = self.cfg.get('host', 'ip')
out = {
'PASSWORD': self.pw_gen.get_password("sql"),
'PASSWORD': self.pw_gen.get_password("sql", PASSWORD_PROMPT),
'BOOT_START': ("%s" % (True)).lower(),
'USER': self.cfg.getdefaulted("db", "sql_user", 'root'),
'SERVICE_HOST': host_ip,
@ -98,8 +100,8 @@ class DBInstaller(comp.PkgInstallComponent):
return out
def warm_configs(self):
for pw_key in WARMUP_PWS:
self.pw_gen.get_password(pw_key)
for key, prompt in WARMUP_PWS:
self.pw_gen.get_password(key, prompt)
def _configure_db_confs(self):
dbtype = self.cfg.get("db", "type")
@ -143,7 +145,7 @@ class DBInstaller(comp.PkgInstallComponent):
LOG.info("Ensuring your database is started before we operate on it.")
self.runtime.restart()
params = {
'NEW_PASSWORD': self.pw_gen.get_password("sql"),
'NEW_PASSWORD': self.pw_gen.get_password("sql", PASSWORD_PROMPT),
'USER': self.cfg.getdefaulted("db", "sql_user", 'root'),
'OLD_PASSWORD': RESET_BASE_PW,
}
@ -162,7 +164,7 @@ class DBInstaller(comp.PkgInstallComponent):
LOG.info("Ensuring your database is started before we operate on it.")
self.runtime.restart()
params = {
'PASSWORD': self.pw_gen.get_password("sql"),
'PASSWORD': self.pw_gen.get_password("sql", PASSWORD_PROMPT),
'USER': user,
}
cmds = [{'cmd': grant_cmd}]
@ -243,7 +245,7 @@ def drop_db(cfg, pw_gen, distro, dbname):
if dbactions and dbactions.get('drop_db'):
dropcmd = dbactions.get('drop_db')
params = dict()
params['PASSWORD'] = pw_gen.get_password("sql")
params['PASSWORD'] = pw_gen.get_password("sql", PASSWORD_PROMPT)
params['USER'] = cfg.getdefaulted("db", "sql_user", 'root')
params['DB'] = dbname
cmds = list()
@ -263,7 +265,7 @@ def create_db(cfg, pw_gen, distro, dbname):
if dbactions and dbactions.get('create_db'):
createcmd = dbactions.get('create_db')
params = dict()
params['PASSWORD'] = pw_gen.get_password("sql")
params['PASSWORD'] = pw_gen.get_password("sql", PASSWORD_PROMPT)
params['USER'] = cfg.getdefaulted("db", "sql_user", 'root')
params['DB'] = dbname
cmds = list()
@ -275,3 +277,36 @@ def create_db(cfg, pw_gen, distro, dbname):
else:
msg = BASE_ERROR % ('create', dbtype)
raise NotImplementedError(msg)
def fetch_dbdsn(config, pw_gen, dbname=''):
"""Return the database connection string, including password."""
user = config.get("db", "sql_user")
host = config.get("db", "sql_host")
port = config.get("db", "port")
pw = pw_gen.get_password("sql", PASSWORD_PROMPT)
#form the dsn (from components we have...)
#dsn = "<driver>://<username>:<password>@<host>:<port>/<database>"
if not host:
msg = "Unable to fetch a database dsn - no sql host found"
raise excp.BadParamException(msg)
driver = config.get("db", "type")
if not driver:
msg = "Unable to fetch a database dsn - no db driver type found"
raise excp.BadParamException(msg)
dsn = driver + "://"
if user:
dsn += user
if pw:
dsn += ":" + pw
if user or pw:
dsn += "@"
dsn += host
if port:
dsn += ":" + port
if dbname:
dsn += "/" + dbname
else:
dsn += "/"
LOG.debug("For database [%s] fetched dsn [%s]" % (dbname, dsn))
return dsn

View File

@ -17,7 +17,6 @@
import io
from devstack import cfg
from devstack import cfg_helpers
from devstack import component as comp
from devstack import log as logging
from devstack import settings
@ -173,7 +172,7 @@ class GlanceInstaller(comp.PythonInstallComponent):
mp = dict()
mp['DEST'] = self.appdir
mp['SYSLOG'] = self.cfg.getboolean("default", "syslog")
mp['SQL_CONN'] = cfg_helpers.fetch_dbdsn(self.cfg, self.pw_gen, DB_NAME)
mp['SQL_CONN'] = db.fetch_dbdsn(self.cfg, self.pw_gen, DB_NAME)
mp['SERVICE_HOST'] = self.cfg.get('host', 'ip')
mp['HOST_IP'] = self.cfg.get('host', 'ip')
mp.update(keystone.get_shared_params(self.cfg, self.pw_gen, 'glance'))

View File

@ -19,7 +19,6 @@ import io
from urlparse import urlunparse
from devstack import cfg
from devstack import cfg_helpers
from devstack import component as comp
from devstack import log as logging
from devstack import settings
@ -192,7 +191,7 @@ class KeystoneInstaller(comp.PythonInstallComponent):
mp['BIN_DIR'] = self.bindir
mp['CONFIG_FILE'] = sh.joinpths(self.cfgdir, ROOT_CONF)
if config_fn == ROOT_CONF:
mp['SQL_CONN'] = cfg_helpers.fetch_dbdsn(self.cfg, self.pw_gen, DB_NAME)
mp['SQL_CONN'] = db.fetch_dbdsn(self.cfg, self.pw_gen, DB_NAME)
mp['KEYSTONE_DIR'] = self.appdir
mp.update(get_shared_params(self.cfg, self.pw_gen))
elif config_fn == MANAGE_DATA_CONF:
@ -250,9 +249,19 @@ def get_shared_params(config, pw_gen, service_user_name=None):
mp['DEMO_TENANT_NAME'] = mp['DEMO_USER_NAME']
#tokens and passwords
mp['SERVICE_TOKEN'] = pw_gen.get_password("service_token")
mp['ADMIN_PASSWORD'] = pw_gen.get_password('horizon_keystone_admin', length=20)
mp['SERVICE_PASSWORD'] = pw_gen.get_password('service_password')
mp['SERVICE_TOKEN'] = pw_gen.get_password(
"service_token",
'the service admin token',
)
mp['ADMIN_PASSWORD'] = pw_gen.get_password(
'horizon_keystone_admin',
'the horizon and keystone admin',
length=20,
)
mp['SERVICE_PASSWORD'] = pw_gen.get_password(
'service_password',
'service authentication',
)
#components of the auth endpoint
keystone_auth_host = config.getdefaulted('keystone', 'keystone_auth_host', host_ip)

View File

@ -17,7 +17,6 @@
import io
from devstack import cfg
from devstack import cfg_helpers
from devstack import component as comp
from devstack import log as logging
from devstack import settings
@ -110,7 +109,7 @@ class MelangeInstaller(comp.PythonInstallComponent):
with io.BytesIO(contents) as stream:
config = cfg.IgnoreMissingConfigParser()
config.readfp(stream)
db_dsn = cfg_helpers.fetch_dbdsn(self.cfg, self.pw_gen, DB_NAME)
db_dsn = db.fetch_dbdsn(self.cfg, self.pw_gen, DB_NAME)
old_dbsn = config.get('DEFAULT', 'sql_connection')
if db_dsn != old_dbsn:
config.set('DEFAULT', 'sql_connection', db_dsn)

View File

@ -16,7 +16,6 @@
from urlparse import urlunparse
from devstack import cfg_helpers
from devstack import component as comp
from devstack import date
from devstack import exceptions
@ -610,7 +609,7 @@ class NovaConfConfigurator(object):
nova_conf.add('my_ip', hostip)
#setup your sql connection
db_dsn = cfg_helpers.fetch_dbdsn(self.cfg, self.pw_gen, DB_NAME)
db_dsn = db.fetch_dbdsn(self.cfg, self.pw_gen, DB_NAME)
nova_conf.add('sql_connection', db_dsn)
#configure anything libvirt releated?

View File

@ -17,7 +17,6 @@
import io
from devstack import cfg
from devstack import cfg_helpers
from devstack import component as comp
from devstack import log as logging
from devstack import settings
@ -148,7 +147,7 @@ class QuantumInstaller(comp.PkgInstallComponent):
config.readfp(stream)
db_dsn = config.get("DATABASE", "sql_connection")
if db_dsn:
generated_dsn = cfg_helpers.fetch_dbdsn(self.cfg, self.pw_gen, DB_NAME)
generated_dsn = db.fetch_dbdsn(self.cfg, self.pw_gen, DB_NAME)
if generated_dsn != db_dsn:
config.set("DATABASE", "sql_connection", generated_dsn)
with io.BytesIO() as outputstream:

View File

@ -23,17 +23,6 @@ import re
LOG = logging.getLogger("devstack.passwords")
PW_SECTION = 'passwords'
HELPFUL_DESCRIPTIONS = {
'sql': 'the database user',
'rabbit': 'the rabbit user',
'horizon_keystone_admin': 'the horizon and keystone admin',
'service_password': 'service authentication',
"service_token": 'the service admin token',
}
def get_pw_usage(option):
return HELPFUL_DESCRIPTIONS.get(option, '???')
def generate_random(length):
@ -78,12 +67,8 @@ class PasswordGenerator(object):
def _set_through(self, option, value):
self.cfg.set(PW_SECTION, option, value)
def get_password(self, option, prompt_text=None, length=8):
def get_password(self, option, prompt_text, length=8):
"""Returns a password identified by the configuration location."""
if not prompt_text:
prompt_text = get_pw_usage(option)
LOG.debug('Looking for password %s (%s)', option, prompt_text)
# Look in the configuration file(s)

49
tests/test_db.py Normal file
View File

@ -0,0 +1,49 @@
from ConfigParser import ConfigParser
import mox
from devstack.components import db
from devstack import passwords
def test_fetch_dbdsn_full():
cfg = ConfigParser()
cfg.add_section('db')
cfg.set('db', 'sql_user', 'sql_user')
cfg.set('db', 'sql_host', 'sql_host')
cfg.set('db', 'port', '55')
cfg.set('db', 'type', 'mysql')
cfg.add_section('passwords')
cfg.set('passwords', 'sql', 'password')
dsn = db.fetch_dbdsn(cfg, passwords.PasswordGenerator(cfg, False))
assert dsn == 'mysql://sql_user:password@sql_host:55/'
def test_fetch_dbdsn_no_user():
cfg = ConfigParser()
cfg.add_section('db')
cfg.set('db', 'sql_user', '')
cfg.set('db', 'sql_host', 'sql_host')
cfg.set('db', 'port', '55')
cfg.set('db', 'type', 'mysql')
cfg.add_section('passwords')
cfg.set('passwords', 'sql', 'password')
dsn = db.fetch_dbdsn(cfg, passwords.PasswordGenerator(cfg, False))
assert dsn == 'mysql://:password@sql_host:55/'
def test_fetch_dbdsn_dbname():
cfg = ConfigParser()
cfg.add_section('db')
cfg.set('db', 'sql_user', 'sql_user')
cfg.set('db', 'sql_host', 'sql_host')
cfg.set('db', 'port', '55')
cfg.set('db', 'type', 'mysql')
cfg.add_section('passwords')
cfg.set('passwords', 'sql', 'password')
pw_gen = passwords.PasswordGenerator(cfg, False)
dsn = db.fetch_dbdsn(cfg, pw_gen, 'dbname')
assert dsn == 'mysql://sql_user:password@sql_host:55/dbname'