From 796808f7118febcb31bf06214882ab1ad762dc7b Mon Sep 17 00:00:00 2001 From: udaij12 <32673964+udaij12@users.noreply.github.com> Date: Mon, 20 Nov 2023 13:44:27 -0800 Subject: [PATCH] Fixed workflow store pathing issue #2792 (#2797) * fixed workflow store pathing * fixed lint * doc change and added test * fixed test * added new test * fixed properties file --- docs/server.md | 12 +++- .../org/pytorch/serve/util/ConfigManager.java | 2 + .../pytorch/serve/util/ConfigManagerTest.java | 28 ++++++++++ .../resources/config_test_workflow.properties | 55 +++++++++++++++++++ ts/model_server.py | 7 +-- 5 files changed, 97 insertions(+), 7 deletions(-) create mode 100644 frontend/server/src/test/resources/config_test_workflow.properties diff --git a/docs/server.md b/docs/server.md index 40d37e155f..6d68d4bf0c 100644 --- a/docs/server.md +++ b/docs/server.md @@ -25,7 +25,7 @@ To try out TorchServe serving now, you can load the custom MNIST model, with thi After this deep dive, you might also be interested in: * [Logging](logging.md): logging options that are available -* [Metrics](metrics.md): details on metrics collection +* [Metrics](metrics.md): details on metrics collection * [REST API Description](rest_api.md): more detail about the server's endpoints @@ -68,7 +68,7 @@ optional arguments: MODEL_STORE. --log-config LOG_CONFIG Log4j configuration file for TorchServe - --ncs, --no-config-snapshots + --ncs, --no-config-snapshots Disable snapshot feature --workflow-store WORKFLOW_STORE Workflow store location where workflow can be loaded. Defaults to model-store @@ -107,6 +107,14 @@ There are no default required arguments to start the server 1. **start**: optional, A more descriptive way to start the server. 1. **stop**: optional, Stop the server if it is already running. +#### Argument Priority: +Arguments can be set in multiple locations (ex: command line, config.properties). The following is the priority: +1. Command line +2. Config properties +3. Default settings + +Example: Setting `model-store` in config.properties and through command line will result in the the command line location being used and overriding the config.properties. + ## Advanced Features ### Custom Services diff --git a/frontend/server/src/main/java/org/pytorch/serve/util/ConfigManager.java b/frontend/server/src/main/java/org/pytorch/serve/util/ConfigManager.java index ff25a37719..ec1be05489 100644 --- a/frontend/server/src/main/java/org/pytorch/serve/util/ConfigManager.java +++ b/frontend/server/src/main/java/org/pytorch/serve/util/ConfigManager.java @@ -210,6 +210,8 @@ private ConfigManager(Arguments args) throws IOException { String workflowStore = args.getWorkflowStore(); if (workflowStore != null) { prop.setProperty(TS_WORKFLOW_STORE, workflowStore); + } else if (prop.getProperty(TS_WORKFLOW_STORE) == null) { + prop.setProperty(TS_WORKFLOW_STORE, prop.getProperty(TS_MODEL_STORE)); } String[] models = args.getModels(); diff --git a/frontend/server/src/test/java/org/pytorch/serve/util/ConfigManagerTest.java b/frontend/server/src/test/java/org/pytorch/serve/util/ConfigManagerTest.java index 6cfe4b2850..9cb04debf1 100644 --- a/frontend/server/src/test/java/org/pytorch/serve/util/ConfigManagerTest.java +++ b/frontend/server/src/test/java/org/pytorch/serve/util/ConfigManagerTest.java @@ -77,4 +77,32 @@ public void testNoEnvVars() throws ReflectiveOperationException, IOException { Assert.assertEquals(4, configManager.getJsonIntValue("noop", "1.0", "batchSize", 1)); Assert.assertEquals(4, configManager.getJsonIntValue("vgg16", "1.0", "maxWorkers", 1)); } + + @Test + public void testWorkflowState() throws ReflectiveOperationException, IOException { + System.setProperty("tsConfigFile", "src/test/resources/config_test_env.properties"); + ConfigManager.Arguments args = new ConfigManager.Arguments(); + args.setModels(new String[] {"noop_v0.1"}); + args.setSnapshotDisabled(true); + ConfigManager.init(args); + ConfigManager configManager = ConfigManager.getInstance(); + String workingDir = configManager.getModelServerHome(); + Assert.assertEquals( + workingDir + "/frontend/archive/src/test/resources/workflows", + configManager.getWorkflowStore()); + } + + @Test + public void testNoWorkflowState() throws ReflectiveOperationException, IOException { + System.setProperty("tsConfigFile", "src/test/resources/config_test_workflow.properties"); + ConfigManager.Arguments args = new ConfigManager.Arguments(); + args.setModels(new String[] {"noop_v0.1"}); + args.setSnapshotDisabled(true); + ConfigManager.init(args); + ConfigManager configManager = ConfigManager.getInstance(); + String workingDir = configManager.getModelServerHome(); + Assert.assertEquals( + workingDir + "/frontend/archive/src/test/resources/models", + configManager.getWorkflowStore()); + } } diff --git a/frontend/server/src/test/resources/config_test_workflow.properties b/frontend/server/src/test/resources/config_test_workflow.properties new file mode 100644 index 0000000000..4caf51a3a4 --- /dev/null +++ b/frontend/server/src/test/resources/config_test_workflow.properties @@ -0,0 +1,55 @@ +# debug=true +# vmargs=-Xmx128m -XX:-UseLargePages -XX:+UseG1GC -XX:MaxMetaspaceSize=32M -XX:MaxDirectMemorySize=10m -XX:+ExitOnOutOfMemoryError +inference_address=https://127.0.0.1:8443 +management_address=unix:/tmp/management.sock +metrics_address=https://127.0.0.1:8445 +# model_server_home=../.. +model_store=../archive/src/test/resources/models +# workflow_store=../archive/src/test/resources/workflows +load_models=noop-v0.1,noop-v1.0 +# number_of_netty_threads=0 +# netty_client_threads=0 +# default_workers_per_model=0 +# job_queue_size=100 +async_logging=true +default_response_timeout=120 +unregister_model_timeout=120 +# number_of_gpu=1 +# cors_allowed_origin +# cors_allowed_methods +# cors_allowed_headers +# keystore=src/test/resources/keystore.p12 +# keystore_pass=changeit +# keystore_type=PKCS12 +private_key_file=src/test/resources/key.pem +certificate_file=src/test/resources/certs.pem +# max_response_size=6553500 +max_request_size=10485760 +# blacklist_env_vars=.*USERNAME.*|.*PASSWORD.* +# enable_envvars_config=false +# decode_input_request=true +models={\ + "noop": {\ + "1.0": {\ + "defaultVersion": true,\ + "marName": "noop.mar",\ + "minWorkers": 1,\ + "maxWorkers": 1,\ + "batchSize": 4,\ + "maxBatchDelay": 100,\ + "responseTimeout": 120\ + }\ + },\ + "vgg16": {\ + "1.0": {\ + "defaultVersion": true,\ + "marName": "vgg16.mar",\ + "minWorkers": 1,\ + "maxWorkers": 4,\ + "batchSize": 8,\ + "maxBatchDelay": 100,\ + "responseTimeout": 120\ + }\ + }\ +} +metrics_config=src/test/resources/metrics_default.yaml diff --git a/ts/model_server.py b/ts/model_server.py index 2a50932fa5..5e3334dbab 100644 --- a/ts/model_server.py +++ b/ts/model_server.py @@ -10,6 +10,7 @@ import tempfile from builtins import str from typing import Dict + import psutil from ts.arg_parser import ArgParser @@ -104,8 +105,7 @@ def start() -> None: sys.exit(1) ts_conf_file = ts_config - platform_path_separator = { - "Windows": "", "Darwin": ".:", "Linux": ".:"} + platform_path_separator = {"Windows": "", "Darwin": ".:", "Linux": ".:"} class_path = "{}{}".format( platform_path_separator[platform.system()], os.path.join(ts_home, "ts", "frontend", "*"), @@ -177,9 +177,6 @@ def start() -> None: cmd.append("-w") cmd.append(args.workflow_store) - else: - cmd.append("-w") - cmd.append(args.model_store) if args.no_config_snapshots: cmd.append("-ncs")