# 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. from rally.common import cfg OPTS = {"openstack": [ cfg.FloatOpt("neutron_create_loadbalancer_timeout", default=float(500), deprecated_group="benchmark", help="Neutron create loadbalancer timeout"), cfg.FloatOpt("neutron_create_loadbalancer_poll_interval", default=float(2), deprecated_group="benchmark", help="Neutron create loadbalancer poll interval"), cfg.BoolOpt("pre_newton_neutron", default=False, help="Whether Neutron API is older then OpenStack Newton or " "not. Based on the option, some external fields for " "identifying resources can be applied."), cfg.ListOpt("neutron_bind_l2_agent_types", # default to agent types used in gate jobs default=[ "Open vSwitch agent", "Linux bridge agent", ], help="Neutron L2 agent types to find hosts to bind"), ]}
def run(argv, categories): if len(argv) > 1 and argv[1] in ["version", "--version"]: _print_version() return 0 parser = lambda subparsers: _add_command_parsers(categories, subparsers) category_opt = cfg.SubCommandOpt("category", title="Command categories", help="Available categories", handler=parser) CONF.register_cli_opt(category_opt) help_msg = ("Additional custom plugin locations. Multiple files or " "directories may be specified. All plugins in the specified" " directories and subdirectories will be imported. Plugins in" " /opt/rally/plugins and ~/.rally/plugins will always be " "imported.") CONF.register_cli_opt(cfg.ListOpt("plugin-paths", default=os.environ.get( "RALLY_PLUGIN_PATHS"), help=help_msg)) # NOTE(andreykurilin): this dirty hack is done to unblock the gates. # Currently, we are using oslo.config for CLI purpose (don't do this!) # and it makes the things too complicated. # To discover which CLI method can be affected by warnings and which not # (based on suppress_warnings decorator) we need to obtain a desired # CLI method. It can be done only after initialization of oslo_config # which is located in rally.api.API init method. # Initialization of rally.api.API can produce a warning (for example, # from pymysql), so suppressing of warnings later will not work in such # case (it is what actually had happened now in our CI with the latest # release of PyMySQL). # # https://bitbucket.org/zzzeek/sqlalchemy/issues/4120/mysql-5720-warns-on-tx_isolation try: import pymysql warnings.filterwarnings("ignore", category=pymysql.Warning) except ImportError: pass try: rapi = api.API(config_args=argv[1:], skip_db_check=True) except exceptions.RallyException as e: print(e) return(2) if CONF.category.name == "bash-completion": print(_generate_bash_completion_script()) return(0) fn = CONF.category.action_fn fn_args = [encodeutils.safe_decode(arg) for arg in CONF.category.action_args] # api instance always is the first argument fn_args.insert(0, rapi) fn_kwargs = {} for k in CONF.category.action_kwargs: v = getattr(CONF.category, "action_kwarg_" + k) if v is None: continue if isinstance(v, str): v = encodeutils.safe_decode(v) fn_kwargs[k] = v # call the action with the remaining arguments # check arguments try: validate_args(fn, *fn_args, **fn_kwargs) except MissingArgs as e: # NOTE(mikal): this isn't the most helpful error message ever. It is # long, and tells you a lot of things you probably don't want to know # if you just got a single arg wrong. print(fn.__doc__) CONF.print_help() print("Missing arguments:") for missing in e.missing: for arg in fn.args: if arg[1].get("dest", "").endswith(missing): print(" " + arg[0][0]) break return(1) try: validate_deprecated_args(argv, fn) # skip db check for db and plugin commands if CONF.category.name not in ("db", "plugin"): rapi.check_db_revision() if getattr(fn, "_suppress_warnings", False): with warnings.catch_warnings(): warnings.simplefilter("ignore") ret = fn(*fn_args, **fn_kwargs) else: ret = fn(*fn_args, **fn_kwargs) return ret except (IOError, TypeError, ValueError, exceptions.RallyException, jsonschema.ValidationError) as e: known_errors = (exceptions.InvalidTaskConfig, ) if logging.is_debug() and not isinstance(e, known_errors): LOG.exception("Unexpected exception in CLI") else: print(e) return getattr(e, "error_code", 1) except sqlalchemy.exc.OperationalError as e: if logging.is_debug(): LOG.exception("Something went wrong with database") print(e) print("Looks like Rally can't connect to its DB.") print("Make sure that connection string in rally.conf is proper:") print(CONF.database.connection) return 1 except Exception: print("Command failed, please check log for more info") raise