diff --git a/etc/shaker.conf b/etc/shaker.conf index 793d628..9d36ed2 100644 --- a/etc/shaker.conf +++ b/etc/shaker.conf @@ -87,7 +87,8 @@ # From shaker.engine.config # -# Address for server connections (host:port) (string value) +# Address for server connections (host:port), defaults to +# env[SHAKER_SERVER_ENDPOINT]. (string value) #server_endpoint = # @@ -109,15 +110,16 @@ # Authentication region name, defaults to env[OS_REGION_NAME]. (string value) #os_region_name = RegionOne -# Name or ID of external network. If not set the network is chosen randomly. -# (string value) +# Name or ID of external network, defaults to env[SHAKER_EXTERNAL_NET]. If no +# value provided then Shaker picks any of available external networks. (string +# value) #external_net = -# Name of image to use. The default is created by shaker-image-builder (string +# Name of image to use. The default is created by shaker-image-builder. (string # value) #image_name = shaker-image -# Name of image flavor. The default is created by shaker-image-builder (string +# Name of image flavor. The default is created by shaker-image-builder. (string # value) #flavor_name = shaker-flavor @@ -125,20 +127,21 @@ # From shaker.engine.config # -# Scenario file name (string value) +# Scenario file name, defaults to env[SHAKER_SCENARIO]. (string value) #scenario = # Report template in Jinja format (string value) #report_template = shaker/resources/report_template.jinja2 -# Report file name. If not specified print to stdout (string value) +# Report file name, defaults to env[SHAKER_REPORT]. If no value provided the +# report is printed to stdout. (string value) #report = # # From shaker.engine.config # -# Agent unique id (string value) +# Agent unique id, defaults to env[SHAKER_AGENT_ID]. (string value) #agent_id = # diff --git a/shaker/engine/config.py b/shaker/engine/config.py index 9a13407..dabe934 100644 --- a/shaker/engine/config.py +++ b/shaker/engine/config.py @@ -21,64 +21,84 @@ from shaker.engine import utils COMMON_OPTS = [ cfg.StrOpt('server-endpoint', + default=utils.env('SHAKER_SERVER_ENDPOINT'), required=True, - help='Address for server connections (host:port)'), + help='Address for server connections (host:port), ' + 'defaults to env[SHAKER_SERVER_ENDPOINT].'), ] OPENSTACK_OPTS = [ cfg.StrOpt('os-auth-url', metavar='', default=utils.env('OS_AUTH_URL'), + sample_default='', + required=True, help='Authentication URL, defaults to env[OS_AUTH_URL].'), cfg.StrOpt('os-tenant-name', metavar='', default=utils.env('OS_TENANT_NAME'), + sample_default='', + required=True, help='Authentication tenant name, defaults to ' 'env[OS_TENANT_NAME].'), cfg.StrOpt('os-username', metavar='', default=utils.env('OS_USERNAME'), + sample_default='', + required=True, help='Authentication username, defaults to env[OS_USERNAME].'), cfg.StrOpt('os-password', metavar='', default=utils.env('OS_PASSWORD'), + sample_default='', + required=True, help='Authentication password, defaults to env[OS_PASSWORD].'), cfg.StrOpt('os-region-name', metavar='', default=utils.env('OS_REGION_NAME') or 'RegionOne', + required=True, help='Authentication region name, defaults to ' 'env[OS_REGION_NAME].'), cfg.StrOpt('external-net', - help='Name or ID of external network. If not set the network ' - 'is chosen randomly.'), + default=utils.env('SHAKER_EXTERNAL_NET'), + help='Name or ID of external network, defaults to ' + 'env[SHAKER_EXTERNAL_NET]. If no value provided then ' + 'Shaker picks any of available external networks.'), cfg.StrOpt('image-name', - default='shaker-image', + default=utils.env('SHAKER_IMAGE') or 'shaker-image', help='Name of image to use. The default is created by ' - 'shaker-image-builder'), + 'shaker-image-builder.'), cfg.StrOpt('flavor-name', - default='shaker-flavor', + default=utils.env('SHAKER_FLAVOR') or 'shaker-flavor', help='Name of image flavor. The default is created by ' - 'shaker-image-builder'), + 'shaker-image-builder.'), ] SERVER_OPTS = [ cfg.StrOpt('scenario', + default=utils.env('SHAKER_SCENARIO'), required=True, - help='Scenario file name'), + help='Scenario file name, defaults to env[SHAKER_SCENARIO].'), cfg.StrOpt('report-template', - default='shaker/resources/report_template.jinja2', + default=(utils.env('SHAKER_REPORT_TEMPLATE') or + 'shaker/resources/report_template.jinja2'), help='Report template in Jinja format'), cfg.StrOpt('report', - help='Report file name. If not specified print to stdout'), + default=utils.env('SHAKER_REPORT'), + help='Report file name, defaults to env[SHAKER_REPORT]. ' + 'If no value provided the report is printed to stdout.'), ] + AGENT_OPTS = [ cfg.StrOpt('agent-id', + default=utils.env('SHAKER_AGENT_ID'), required=True, - help='Agent unique id'), + help='Agent unique id, defaults to env[SHAKER_AGENT_ID].'), ] IMAGE_BUILDER_OPTS = [ cfg.StrOpt('image-builder-template', - default='shaker/resources/image_builder_template.yaml', + default=(utils.env('SHAKER_IMAGE_BUILDER_TEMPLATE') or + 'shaker/resources/image_builder_template.yaml'), help='Heat template for the image builder.'), ] diff --git a/shaker/engine/image_builder.py b/shaker/engine/image_builder.py index bc7c25c..07bb28f 100644 --- a/shaker/engine/image_builder.py +++ b/shaker/engine/image_builder.py @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import logging as std_logging import uuid from oslo_config import cfg @@ -33,16 +34,23 @@ LOG = logging.getLogger(__name__) def init(): # init conf and logging conf = cfg.CONF - conf.register_cli_opts(config.OPENSTACK_OPTS) - conf.register_cli_opts(config.IMAGE_BUILDER_OPTS) - conf.register_opts(config.OPENSTACK_OPTS) - conf.register_opts(config.IMAGE_BUILDER_OPTS) + opts = config.OPENSTACK_OPTS + config.IMAGE_BUILDER_OPTS + conf.register_cli_opts(opts) + conf.register_opts(opts) logging.register_options(conf) logging.set_defaults() - conf(project='shaker') + + try: + conf(project='shaker') + utils.validate_required_opts(conf, opts) + except cfg.RequiredOptError as e: + print('Error: %s' % e) + conf.print_usage() + exit(1) logging.setup(conf, 'shaker') LOG.info('Logging enabled') + conf.log_opt_values(LOG, std_logging.DEBUG) openstack_client = openstack.OpenStackClient( username=cfg.CONF.os_username, password=cfg.CONF.os_password, diff --git a/shaker/engine/server.py b/shaker/engine/server.py index 80b20eb..819e7e3 100644 --- a/shaker/engine/server.py +++ b/shaker/engine/server.py @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import logging as std_logging import time import uuid @@ -197,17 +198,15 @@ def execute(execution, agents): def main(): # init conf and logging conf = cfg.CONF - conf.register_cli_opts(config.COMMON_OPTS) - conf.register_cli_opts(config.OPENSTACK_OPTS) - conf.register_cli_opts(config.SERVER_OPTS) - conf.register_opts(config.COMMON_OPTS) - conf.register_opts(config.OPENSTACK_OPTS) - conf.register_opts(config.SERVER_OPTS) + opts = config.COMMON_OPTS + config.OPENSTACK_OPTS + config.SERVER_OPTS + conf.register_cli_opts(opts) + conf.register_opts(opts) logging.register_options(conf) logging.set_defaults() try: conf(project='shaker') + utils.validate_required_opts(conf, opts) except cfg.RequiredOptError as e: print('Error: %s' % e) conf.print_usage() @@ -215,6 +214,7 @@ def main(): logging.setup(conf, 'shaker') LOG.info('Logging enabled') + conf.log_opt_values(LOG, std_logging.DEBUG) scenario = read_scenario() deployment = deploy.Deployment(cfg.CONF.os_username, diff --git a/shaker/engine/utils.py b/shaker/engine/utils.py index f6ff853..28d6931 100644 --- a/shaker/engine/utils.py +++ b/shaker/engine/utils.py @@ -16,6 +16,7 @@ import os import random +from oslo_config import cfg from oslo_log import log as logging import six @@ -32,7 +33,15 @@ def env(*_vars, **kwargs): value = os.environ.get(v) if value: return value - return kwargs.get('default', '') + return kwargs.get('default', None) + + +def validate_required_opts(conf, opts): + # all config parameters default to ENV values, that's why standard + # check of required options doesn't work and needs to be done manually + for opt in opts: + if opt.required and not conf[opt.dest]: + raise cfg.RequiredOptError(opt.name) def read_file(file_name):