diff --git a/docs/reference/commands/command-flags.md b/docs/reference/commands/command-flags.md index 9aea448c..5b9f60c0 100644 --- a/docs/reference/commands/command-flags.md +++ b/docs/reference/commands/command-flags.md @@ -88,6 +88,7 @@ Accepted by all subcommands. | `--on-error` | string | `continue` | Error strategy: `continue` or `abort` | | `--client-options` | string | `timeout:60` | Comma-separated client options passed to the Solr client (short: `-c`) | | `--kill-running-processes` | flag | off | Kill other running `solr-orbit` processes before starting (short: `-k`) | +| `--allow-user-managed` | flag | off | Skip the SolrCloud-mode requirement check and run against a user-managed (non-cloud) target anyway (use at your own risk) | | `--preserve-install` | flag | off | Keep the Solr installation after the run (provisioned pipelines only) | ### Provisioning diff --git a/docs/user-guide/working-with-workloads/running-workloads.md b/docs/user-guide/working-with-workloads/running-workloads.md index 3af8fd33..32a0c561 100644 --- a/docs/user-guide/working-with-workloads/running-workloads.md +++ b/docs/user-guide/working-with-workloads/running-workloads.md @@ -30,7 +30,7 @@ solr-orbit run [--pipeline PIPELINE] [--target-hosts HOSTS] \ ``` {: .important } -When using the `benchmark-only` pipeline, the target Solr cluster must be running in **SolrCloud (ZooKeeper) mode** — standalone/user-managed mode is not supported. For Solr 9.x, start Solr with the `-c` flag (e.g. `bin/solr start -c` or `docker run -d -p 8983:8983 solr:9 -c`). For Solr 10.0.0 and later, SolrCloud is the default. +When using the `benchmark-only` pipeline, the target Solr cluster must be running in **SolrCloud (ZooKeeper) mode** — standalone/user-managed mode is not supported. For Solr 9.x, start Solr with the `-c` flag (e.g. `bin/solr start -c` or `docker run -d -p 8983:8983 solr:9 -c`). For Solr 10.0.0 and later, SolrCloud is the default. To bypass this check and run against a user-managed (non-cloud) target anyway, pass `--allow-user-managed` (use at your own risk; some operations only work in SolrCloud mode). --- diff --git a/solrorbit/benchmark.py b/solrorbit/benchmark.py index 574991e3..e7df5fa7 100644 --- a/solrorbit/benchmark.py +++ b/solrorbit/benchmark.py @@ -701,6 +701,14 @@ def add_workload_source(subparser): default=False, help="If any processes is running, it is going to kill them and allow solr-orbit to continue to run." ) + test_run_parser.add_argument( + "--allow-user-managed", + action="store_true", + default=False, + help="Skip the SolrCloud (ZooKeeper) mode requirement check and run against a user-managed " + "(non-cloud) target anyway (default: false). Use at your own risk; some operations only " + "work in SolrCloud mode." + ) test_run_parser.add_argument( "--latency-percentiles", help=f"A comma-separated list of percentiles to report for latency " @@ -1155,6 +1163,7 @@ def configure_test(arg_parser, args, cfg): "worker_coordinator", "worker_ips", opts.csv_to_list(args.worker_ips)) + cfg.add(config.Scope.applicationOverride, "solr", "allow.user.managed", args.allow_user_managed) cfg.add(config.Scope.applicationOverride, "workload", "test.mode.enabled", args.test_mode) cfg.add(config.Scope.applicationOverride, "workload", "load.test.clients", int(args.load_test_qps)) if args.redline_test: diff --git a/solrorbit/test_run_orchestrator.py b/solrorbit/test_run_orchestrator.py index 9b6f02c0..425d8304 100644 --- a/solrorbit/test_run_orchestrator.py +++ b/solrorbit/test_run_orchestrator.py @@ -381,6 +381,13 @@ def _check_cloud_mode(cfg): """Fail fast with a clear error if the target Solr cluster is not in SolrCloud mode.""" from solrorbit.client import SolrAdminClient, SolrClientError # local import to avoid circular + if cfg.opts("solr", "allow.user.managed", mandatory=False, default_value=False): + logging.getLogger(__name__).warning( + "Skipping SolrCloud-mode requirement check (--allow-user-managed). " + "Some operations may fail if the target is not in SolrCloud mode." + ) + return + configured_hosts = cfg.opts("client", "hosts") hosts = configured_hosts.default if not hosts: diff --git a/tests/test_execution_orchestrator_test.py b/tests/test_execution_orchestrator_test.py index 81360ef3..ce6158bf 100644 --- a/tests/test_execution_orchestrator_test.py +++ b/tests/test_execution_orchestrator_test.py @@ -32,6 +32,7 @@ import pytest from solrorbit import config, exceptions, test_run_orchestrator +from solrorbit.utils import opts @pytest.fixture @@ -127,3 +128,26 @@ def test_runs_a_default_pipeline(benchmark_only_pipeline): test_run_orchestrator.run(cfg) benchmark_only_pipeline.target.assert_called_once_with(cfg) + + +def test_check_cloud_mode_skipped_when_allow_user_managed(): + # --allow-user-managed must bypass the check entirely, without touching the network + cfg = config.Config() + cfg.add(config.Scope.benchmark, "client", "hosts", ["localhost:8983"]) + cfg.add(config.Scope.benchmark, "solr", "allow.user.managed", True) + + with mock.patch("solrorbit.client.SolrAdminClient") as admin_client: + test_run_orchestrator._check_cloud_mode(cfg) + + admin_client.assert_not_called() + + +def test_check_cloud_mode_raises_for_standalone_solr(): + cfg = config.Config() + cfg.add(config.Scope.benchmark, "client", "hosts", opts.TargetHosts("localhost:8983")) + cfg.add(config.Scope.benchmark, "solr", "allow.user.managed", False) + + with mock.patch("solrorbit.client.SolrAdminClient") as admin_client: + admin_client.return_value.is_cloud_mode.return_value = False + with pytest.raises(exceptions.SystemSetupError, match="not running in SolrCloud"): + test_run_orchestrator._check_cloud_mode(cfg)