Reverted back to using set through for password configs, also fixes issue #90, other teenie cleanups
This commit is contained in:
parent
725cad4615
commit
bd7fbd5474
@ -69,9 +69,9 @@ class IgnoreMissingConfigParser(ConfigParser.RawConfigParser):
|
||||
|
||||
|
||||
class StackConfigParser(IgnoreMissingConfigParser):
|
||||
def __init__(self, cache):
|
||||
def __init__(self):
|
||||
IgnoreMissingConfigParser.__init__(self)
|
||||
self.configs_fetched = cache
|
||||
self.configs_fetched = dict()
|
||||
|
||||
def _resolve_value(self, section, option, value_gotten):
|
||||
if section == 'host' and option == 'ip':
|
||||
@ -100,6 +100,12 @@ class StackConfigParser(IgnoreMissingConfigParser):
|
||||
self.configs_fetched[key] = value
|
||||
return value
|
||||
|
||||
def set(self, section, option, value):
|
||||
key = cfg_helpers.make_id(section, option)
|
||||
LOG.audit("Setting config value [%s] for param [%s]" % (value, key))
|
||||
self.configs_fetched[key] = value
|
||||
IgnoreMissingConfigParser.set(self, section, option, value)
|
||||
|
||||
def _resolve_replacements(self, value):
|
||||
LOG.debug("Performing simple replacement on [%s]", value)
|
||||
|
||||
|
@ -261,18 +261,9 @@ 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",
|
||||
'the service admin token',
|
||||
)
|
||||
mp['ADMIN_PASSWORD'] = pw_gen.get_password(
|
||||
'horizon_keystone_admin',
|
||||
'the horizon and keystone admin',
|
||||
20)
|
||||
mp['SERVICE_PASSWORD'] = pw_gen.get_password(
|
||||
'service_password',
|
||||
'service authentication',
|
||||
)
|
||||
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')
|
||||
|
||||
#components of the auth endpoint
|
||||
keystone_auth_host = config.getdefaulted('keystone', 'keystone_auth_host', host_ip)
|
||||
|
@ -43,6 +43,9 @@ PASSWORDS_MAKES = {
|
||||
'MYSQL_PASSWORD': 'sql',
|
||||
}
|
||||
|
||||
#install root
|
||||
INSTALL_ROOT = 'INSTALL_ROOT'
|
||||
|
||||
#default ports
|
||||
EC2_PORT = 8773
|
||||
S3_PORT = 3333
|
||||
@ -55,9 +58,10 @@ QUOTED_PAT = re.compile(r"^\s*[\"](.*)[\"]\s*$")
|
||||
|
||||
|
||||
class RcWriter(object):
|
||||
def __init__(self, cfg, pw_gen):
|
||||
def __init__(self, cfg, pw_gen, root_dir):
|
||||
self.cfg = cfg
|
||||
self.pw_gen = pw_gen
|
||||
self.root_dir = root_dir
|
||||
|
||||
def _make_export(self, export_name, value):
|
||||
escaped_val = sh.shellquote(value)
|
||||
@ -93,7 +97,7 @@ class RcWriter(object):
|
||||
def _get_password_envs(self):
|
||||
to_set = dict()
|
||||
for (out_name, key) in PASSWORDS_MAKES.items():
|
||||
to_set[out_name] = self.pw_gen.get_password(key, do_prompt=False)
|
||||
to_set[out_name] = self.pw_gen.extract(key)
|
||||
return to_set
|
||||
|
||||
def _get_general_envs(self):
|
||||
@ -101,6 +105,7 @@ class RcWriter(object):
|
||||
for (out_name, cfg_data) in CFG_MAKE.items():
|
||||
(section, key) = (cfg_data)
|
||||
to_set[out_name] = self.cfg.get(section, key)
|
||||
to_set[INSTALL_ROOT] = self.root_dir
|
||||
return to_set
|
||||
|
||||
def _generate_passwords(self):
|
||||
|
@ -19,11 +19,9 @@ from optparse import OptionParser, OptionGroup
|
||||
|
||||
from devstack import log as logging
|
||||
from devstack import settings
|
||||
from devstack import shell as sh
|
||||
from devstack import version
|
||||
|
||||
HELP_WIDTH = 80
|
||||
DEF_OS_DIR = "openstack"
|
||||
LOG = logging.getLogger("devstack.opts")
|
||||
|
||||
|
||||
@ -61,16 +59,13 @@ def parse():
|
||||
dest="action",
|
||||
metavar="ACTION",
|
||||
help="required action to perform: %s" % (_format_list(settings.ACTIONS)))
|
||||
default_dir = sh.joinpths(sh.gethomedir(), DEF_OS_DIR)
|
||||
base_group.add_option("-d", "--directory",
|
||||
action="store",
|
||||
type="string",
|
||||
dest="dir",
|
||||
metavar="DIR",
|
||||
default=default_dir,
|
||||
help=("empty root DIR for install or "
|
||||
"DIR with existing components for start/stop/uninstall "
|
||||
"(default: %default)"))
|
||||
"DIR with existing components for start/stop/uninstall"))
|
||||
base_group.add_option("-i", "--ignore-deps",
|
||||
action="store_false",
|
||||
dest="ensure_deps",
|
||||
|
@ -1,18 +1,34 @@
|
||||
#!/usr/bin/env python
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright (C) 2012 Yahoo! Inc. All Rights Reserved.
|
||||
# Copyright (C) 2012 Dreamhost Inc. All Rights Reserved.
|
||||
#
|
||||
# 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 ConfigParser
|
||||
import binascii
|
||||
import getpass
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
|
||||
from devstack import cfg_helpers
|
||||
|
||||
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',
|
||||
}
|
||||
|
||||
|
||||
@ -29,12 +45,19 @@ def generate_random(length):
|
||||
|
||||
class PasswordGenerator(object):
|
||||
|
||||
def __init__(self, kv_cache, cfg,
|
||||
prompt_user=True):
|
||||
def __init__(self, cfg, prompt_user=True):
|
||||
self.cfg = cfg
|
||||
self.config_cache = kv_cache
|
||||
self.prompt_user = prompt_user
|
||||
|
||||
def _valid_password(self, pw):
|
||||
# FIXME: More efficient way to look for whitespace?
|
||||
if re.match(r"^(\s+)$", pw) or \
|
||||
re.match(r"^(\s+)(\S+)(\s+)$", pw) or \
|
||||
re.match(r"^(\S+)(\s+)$", pw) or \
|
||||
re.match(r"^(\s+)(\S+)$", pw):
|
||||
return False
|
||||
return True
|
||||
|
||||
def _prompt_user(self, prompt_text):
|
||||
LOG.debug('Asking the user for a %r password', prompt_text)
|
||||
message = ("Enter a password to use for %s "
|
||||
@ -43,20 +66,19 @@ class PasswordGenerator(object):
|
||||
rc = ""
|
||||
while True:
|
||||
rc = getpass.getpass(message)
|
||||
if len(rc) == 0:
|
||||
if len(rc) == 0 or self._valid_password(rc):
|
||||
break
|
||||
# FIXME: More efficient way to look for whitespace?
|
||||
if re.match(r"^(\s+)$", rc):
|
||||
LOG.warning("Whitespace not allowed as a password!")
|
||||
elif re.match(r"^(\s+)(\S+)(\s+)$", rc) or \
|
||||
re.match(r"^(\S+)(\s+)$", rc) or \
|
||||
re.match(r"^(\s+)(\S+)$", rc):
|
||||
LOG.warning("Whitespace can not start or end a password!")
|
||||
else:
|
||||
break
|
||||
LOG.warn("Invalid password \"%s\" (please try again)" % (rc))
|
||||
return rc
|
||||
|
||||
def get_password(self, option, prompt_text=None, length=8, do_prompt=True):
|
||||
def extract(self, option):
|
||||
return self.cfg.get(PW_SECTION, option)
|
||||
|
||||
def _set_through(self, option, value):
|
||||
self.cfg.set(PW_SECTION, option, value)
|
||||
|
||||
def get_password(self, option, prompt_text=None, length=8):
|
||||
"""Returns a password identified by the configuration location."""
|
||||
|
||||
if not prompt_text:
|
||||
@ -64,18 +86,16 @@ class PasswordGenerator(object):
|
||||
|
||||
LOG.debug('Looking for password %s (%s)', option, prompt_text)
|
||||
|
||||
cache_key = cfg_helpers.make_id(PW_SECTION, option)
|
||||
password = self.config_cache.get(cache_key)
|
||||
|
||||
# Look in the configuration file(s)
|
||||
password = None
|
||||
from_config = False
|
||||
if not password:
|
||||
try:
|
||||
password = self.cfg.get(PW_SECTION, option)
|
||||
except ConfigParser.Error:
|
||||
password = ''
|
||||
password = self.cfg.get(PW_SECTION, option)
|
||||
if password:
|
||||
from_config = True
|
||||
|
||||
# Optionally ask the user
|
||||
if not password and self.prompt_user and do_prompt:
|
||||
if not password and self.prompt_user:
|
||||
password = self._prompt_user(prompt_text)
|
||||
|
||||
# If we still don't have a value, make one up.
|
||||
@ -84,8 +104,8 @@ class PasswordGenerator(object):
|
||||
option, prompt_text)
|
||||
password = generate_random(length)
|
||||
|
||||
# Update the cache so that other parts of the
|
||||
# code can find the value.
|
||||
self.config_cache[cache_key] = password
|
||||
# Update via set through to the config
|
||||
if not from_config:
|
||||
self._set_through(option, password)
|
||||
|
||||
return password
|
||||
|
@ -164,7 +164,6 @@ class ActionRunner(object):
|
||||
self.force = kargs.get('force', False)
|
||||
self.ignore_deps = kargs.get('ignore_deps', False)
|
||||
self.ref_components = kargs.get("ref_components")
|
||||
self.rc_file = sh.abspth(settings.OSRC_FN)
|
||||
self.gen_rc = action in _RC_FILE_MAKE_ACTIONS
|
||||
|
||||
def _get_components(self):
|
||||
@ -233,13 +232,6 @@ class ActionRunner(object):
|
||||
def _pre_run(self, instances, component_order):
|
||||
if not sh.isdir(self.directory):
|
||||
sh.mkdir(self.directory)
|
||||
if self.rc_file:
|
||||
try:
|
||||
LOG.info("Attempting to load rc file at [%s] which has your environment settings." % (self.rc_file))
|
||||
am_loaded = env_rc.RcReader().load(self.rc_file)
|
||||
LOG.info("Loaded [%s] settings from rc file [%s]" % (am_loaded, self.rc_file))
|
||||
except IOError:
|
||||
LOG.warn('Error reading rc file located at [%s]. Skipping loading it.' % (self.rc_file))
|
||||
LOG.info("Verifying that the components are ready to rock-n-roll.")
|
||||
for component in component_order:
|
||||
inst = instances[component]
|
||||
@ -248,15 +240,15 @@ class ActionRunner(object):
|
||||
for component in component_order:
|
||||
inst = instances[component]
|
||||
inst.warm_configs()
|
||||
if self.gen_rc and self.rc_file:
|
||||
writer = env_rc.RcWriter(self.cfg, self.pw_gen)
|
||||
if not sh.isfile(self.rc_file):
|
||||
LOG.info("Generating a file at [%s] that will contain your environment settings." % (self.rc_file))
|
||||
writer.write(self.rc_file)
|
||||
if self.gen_rc:
|
||||
writer = env_rc.RcWriter(self.cfg, self.pw_gen, self.directory)
|
||||
if not sh.isfile(settings.OSRC_FN):
|
||||
LOG.info("Generating a file at [%s] that will contain your environment settings." % (settings.OSRC_FN))
|
||||
writer.write(settings.OSRC_FN)
|
||||
else:
|
||||
LOG.info("Updating a file at [%s] that contains your environment settings." % (self.rc_file))
|
||||
am_upd = writer.update(self.rc_file)
|
||||
LOG.info("Updated [%s] settings in rc file [%s]" % (am_upd, self.rc_file))
|
||||
LOG.info("Updating a file at [%s] that contains your environment settings." % (settings.OSRC_FN))
|
||||
am_upd = writer.update(settings.OSRC_FN)
|
||||
LOG.info("Updated [%s] settings in rc file [%s]" % (am_upd, settings.OSRC_FN))
|
||||
|
||||
def _run_instances(self, instances, component_order):
|
||||
component_order = self._apply_reverse(component_order)
|
||||
|
@ -155,12 +155,10 @@ def get_packager(distro, keep_packages):
|
||||
return cls(distro, keep_packages)
|
||||
|
||||
|
||||
def get_config(cfg_fn=None, kv_cache=None):
|
||||
def get_config(cfg_fn=None):
|
||||
if not cfg_fn:
|
||||
cfg_fn = sh.canon_path(settings.STACK_CONFIG_LOCATION)
|
||||
if kv_cache is None:
|
||||
kv_cache = dict()
|
||||
config_instance = cfg.StackConfigParser(kv_cache)
|
||||
config_instance = cfg.StackConfigParser()
|
||||
config_instance.read(cfg_fn)
|
||||
return config_instance
|
||||
|
||||
|
@ -88,9 +88,9 @@ def configure_logging(verbosity_level=1, dry_run=False):
|
||||
|
||||
# Adjust logging verbose level based on the command line switch.
|
||||
log_level = logging.INFO
|
||||
if verbosity_level >= 2:
|
||||
if verbosity_level >= 3:
|
||||
log_level = logging.DEBUG
|
||||
elif dry_run:
|
||||
elif verbosity_level == 2 or dry_run:
|
||||
log_level = logging.AUDIT
|
||||
root_logger.setLevel(log_level)
|
||||
|
||||
|
38
stack
38
stack
@ -22,6 +22,8 @@ import traceback
|
||||
|
||||
from devstack import cfg_helpers
|
||||
from devstack import date
|
||||
from devstack import env
|
||||
from devstack import env_rc
|
||||
from devstack import log as logging
|
||||
from devstack import opts
|
||||
from devstack import passwords
|
||||
@ -87,19 +89,39 @@ def dump_config(config_cache):
|
||||
map_print(entries)
|
||||
|
||||
|
||||
def load_rc_files():
|
||||
fns = [settings.OSRC_FN]
|
||||
for fn in fns:
|
||||
try:
|
||||
LOG.debug("Attempting to load rc file at [%s] which has your environment settings." % (fn))
|
||||
am_loaded = env_rc.RcReader().load(fn)
|
||||
LOG.debug("Loaded [%s] settings from rc file [%s]" % (am_loaded, fn))
|
||||
except IOError:
|
||||
LOG.warn('Error reading rc file located at [%s]. Skipping loading it.' % (fn))
|
||||
return len(fns)
|
||||
|
||||
|
||||
def run(args):
|
||||
|
||||
(distro, platform) = utils.determine_distro()
|
||||
if distro is None:
|
||||
print("Unsupported platform " + utils.color_text(platform, "red") + "!")
|
||||
return False
|
||||
|
||||
action = args.pop("action").strip().lower()
|
||||
if not (action in settings.ACTIONS):
|
||||
print(utils.color_text("No valid action specified!", "red"))
|
||||
return False
|
||||
|
||||
loaded_rcs = False
|
||||
rootdir = args.pop("dir")
|
||||
if not rootdir:
|
||||
print(utils.color_text("No root directory specified!", "red"))
|
||||
return False
|
||||
load_rc_files()
|
||||
loaded_rcs = True
|
||||
rootdir = env.get_key(env_rc.INSTALL_ROOT)
|
||||
if not rootdir:
|
||||
print(utils.color_text("No root directory specified!", "red"))
|
||||
return False
|
||||
|
||||
#welcome!
|
||||
(repeat_string, line_max_len) = utils.welcome(_WELCOME_MAP.get(action))
|
||||
@ -108,12 +130,16 @@ def run(args):
|
||||
#here on out we should be using the logger (and not print)
|
||||
start_time = time.time()
|
||||
|
||||
# if we didn't load them before, load them now
|
||||
if not loaded_rcs:
|
||||
load_rc_files()
|
||||
loaded_rcs = True
|
||||
|
||||
# Stash the dryrun value (if any) into the global configuration
|
||||
sh.set_dryrun(args['dryrun'])
|
||||
|
||||
config_kv_cache = dict()
|
||||
config = common.get_config(kv_cache=config_kv_cache)
|
||||
pw_gen = passwords.PasswordGenerator(config_kv_cache, config, args['prompt_for_passwords'])
|
||||
config = common.get_config()
|
||||
pw_gen = passwords.PasswordGenerator(config, args['prompt_for_passwords'])
|
||||
pkg_manager = common.get_packager(distro, args['keep_old'])
|
||||
|
||||
components = utils.parse_components(args.pop("components"))
|
||||
@ -125,7 +151,7 @@ def run(args):
|
||||
LOG.info("It took (%s) to complete action [%s]" % (common.format_secs_taken((time.time() - start_time)), action))
|
||||
LOG.info("After action [%s] your settings which were created or read are:" % (action))
|
||||
|
||||
dump_config(config_kv_cache)
|
||||
dump_config(config.configs_fetched)
|
||||
return True
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user