From b2659ea76a34df1e0c42e0bc254e61091ffb758e Mon Sep 17 00:00:00 2001 From: Christopher Moussa Date: Wed, 2 Mar 2022 10:54:06 -0800 Subject: [PATCH 1/6] flux-accounting DB: add plugin_factor_table Add a new table to the flux-accounting DB, plugin_factor_table, which will hold the various factors and their associated weights to be used in the multi-factor priority plugin. Insert the two factors, fairshare and queue, as rows into the plugin_factor_table. --- .../python/fluxacct/accounting/create_db.py | 22 +++++++++++++++++++ .../accounting/test/test_create_db.py | 1 + 2 files changed, 23 insertions(+) diff --git a/src/bindings/python/fluxacct/accounting/create_db.py b/src/bindings/python/fluxacct/accounting/create_db.py index 16a7efbd..3a0a4f37 100755 --- a/src/bindings/python/fluxacct/accounting/create_db.py +++ b/src/bindings/python/fluxacct/accounting/create_db.py @@ -174,5 +174,27 @@ def create_db( PRIMARY KEY (queue) );""" ) + logging.info("Created queue_table successfully") + + # Plugin Weight Table + # stores the weights for all of the priority factors in the multi-factor + # priority plugin + logging.info("Creating plugin_factor_table in DB...") + conn.execute( + """ + CREATE TABLE IF NOT EXISTS plugin_factor_table ( + factor tinytext NOT NULL, + weight int(11) DEFAULT 1, + PRIMARY KEY (factor) + );""" + ) + logging.info("Created plugin_factor_table successfully") + conn.execute( + "INSERT INTO plugin_factor_table (factor, weight) VALUES ('fairshare', 100000);" + ) + conn.execute( + "INSERT INTO plugin_factor_table (factor, weight) VALUES ('queue', 10000);" + ) + conn.commit() conn.close() diff --git a/src/bindings/python/fluxacct/accounting/test/test_create_db.py b/src/bindings/python/fluxacct/accounting/test/test_create_db.py index 4cb4b95b..e4219441 100755 --- a/src/bindings/python/fluxacct/accounting/test/test_create_db.py +++ b/src/bindings/python/fluxacct/accounting/test/test_create_db.py @@ -54,6 +54,7 @@ def test_01_tables_exist(self): "job_usage_factor_table", "t_half_life_period_table", "queue_table", + "plugin_factor_table", ] self.assertEqual(list_of_tables, expected) From 577b8a59f3f903b26c50374319299cb4e258cdcf Mon Sep 17 00:00:00 2001 From: Christopher Moussa Date: Wed, 2 Mar 2022 10:55:02 -0800 Subject: [PATCH 2/6] accounting: add plugin_factor_table commands Add commands to view and edit the weights of each factor in the plugin_factor_table. --- .../python/fluxacct/accounting/Makefile.am | 1 + .../accounting/plugin_factor_subcommands.py | 53 +++++++++++++++++++ src/cmd/flux-account.py | 30 +++++++++++ 3 files changed, 84 insertions(+) create mode 100644 src/bindings/python/fluxacct/accounting/plugin_factor_subcommands.py diff --git a/src/bindings/python/fluxacct/accounting/Makefile.am b/src/bindings/python/fluxacct/accounting/Makefile.am index 5207751e..fdfffb13 100644 --- a/src/bindings/python/fluxacct/accounting/Makefile.am +++ b/src/bindings/python/fluxacct/accounting/Makefile.am @@ -3,6 +3,7 @@ acctpy_PYTHON = \ user_subcommands.py \ bank_subcommands.py \ queue_subcommands.py \ + plugin_factor_subcommands.py \ job_archive_interface.py \ create_db.py diff --git a/src/bindings/python/fluxacct/accounting/plugin_factor_subcommands.py b/src/bindings/python/fluxacct/accounting/plugin_factor_subcommands.py new file mode 100644 index 00000000..ee59342d --- /dev/null +++ b/src/bindings/python/fluxacct/accounting/plugin_factor_subcommands.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 + +############################################################### +# Copyright 2020 Lawrence Livermore National Security, LLC +# (c.f. AUTHORS, NOTICE.LLNS, COPYING) +# +# This file is part of the Flux resource manager framework. +# For details, see https://github.com/flux-framework. +# +# SPDX-License-Identifier: LGPL-3.0 +############################################################### +import sqlite3 + + +def view_factor(conn, factor): + cur = conn.cursor() + try: + # get the information pertaining to a plugin weight in the DB + cur.execute("SELECT * FROM plugin_factor_table WHERE factor=?", (factor,)) + rows = cur.fetchall() + headers = [description[0] for description in cur.description] + if not rows: + print("Factor not found in plugin_factor_table") + else: + # print column names of plugin_factor_table + for header in headers: + print(header.ljust(18), end=" ") + print() + for row in rows: + for col in list(row): + print(str(col).ljust(18), end=" ") + print() + except sqlite3.OperationalError as e_database_error: + print(e_database_error) + + +def edit_factor(conn, factor, weight=None): + try: + update_stmt = "UPDATE plugin_factor_table SET weight=? WHERE factor=?" + updated_weight = int(weight) # check that the weight is of type int + + conn.execute( + update_stmt, + ( + weight, + factor, + ), + ) + + # commit changes + conn.commit() + except ValueError: + raise ValueError("Weight must be an integer") diff --git a/src/cmd/flux-account.py b/src/cmd/flux-account.py index ac14ff57..507b98bd 100755 --- a/src/cmd/flux-account.py +++ b/src/cmd/flux-account.py @@ -18,6 +18,7 @@ from fluxacct.accounting import job_archive_interface as jobs from fluxacct.accounting import create_db as c from fluxacct.accounting import queue_subcommands as qu +from fluxacct.accounting import plugin_factor_subcommands as p def add_path_arg(parser): @@ -376,6 +377,29 @@ def add_delete_queue_arg(subparsers): subparser_delete_queue.add_argument("queue", help="queue name", metavar="QUEUE") +def add_view_factor_arg(subparsers): + subparser_view_factor = subparsers.add_parser( + "view-plugin-factor", help="view a plugin factor and its associated weight" + ) + subparser_view_factor.set_defaults(func="view_factor") + subparser_view_factor.add_argument( + "factor", type=str, help="factor name", metavar="FACTOR" + ) + + +def add_edit_factor_arg(subparsers): + subparser_edit_factor = subparsers.add_parser( + "edit-plugin-factor", help="edit a plugin factor's associated weight" + ) + subparser_edit_factor.set_defaults(func="edit_factor") + subparser_edit_factor.add_argument( + "factor", type=str, help="factor name", metavar="FACTOR" + ) + subparser_edit_factor.add_argument( + "--weight", type=int, help="associated weight", default=None, metavar="WEIGHT" + ) + + def add_arguments_to_parser(parser, subparsers): add_path_arg(parser) add_output_file_arg(parser) @@ -394,6 +418,8 @@ def add_arguments_to_parser(parser, subparsers): add_view_queue_arg(subparsers) add_edit_queue_arg(subparsers) add_delete_queue_arg(subparsers) + add_view_factor_arg(subparsers) + add_edit_factor_arg(subparsers) def set_db_location(args): @@ -498,6 +524,10 @@ def select_accounting_function(args, conn, output_file, parser): args.max_time_per_job, args.priority, ) + elif args.func == "view_factor": + p.view_factor(conn, args.factor) + elif args.func == "edit_factor": + p.edit_factor(conn, args.factor, args.weight) else: print(parser.print_usage()) From 9ff0e481039b25960a39ada0e7a17d5027dca460 Mon Sep 17 00:00:00 2001 From: Christopher Moussa Date: Tue, 8 Mar 2022 10:05:23 -0800 Subject: [PATCH 3/6] plugin: add bulk update of plugin factors Add a new RPC to flux-account-priority-update.py which will fetch all plugin factors and their associated weights from the flux-accounting DB's plugin_factor_table and send it to the multi-factor priority plugin, where it will be unpacked and stored in a map. The key-value pair contains the plugin factor and its associated weight to be used in the priority calculation of a job. --- src/cmd/flux-account-priority-update.py | 14 +++++++ src/plugins/mf_priority.cpp | 51 ++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/src/cmd/flux-account-priority-update.py b/src/cmd/flux-account-priority-update.py index b5aa7e5e..bed77a5b 100755 --- a/src/cmd/flux-account-priority-update.py +++ b/src/cmd/flux-account-priority-update.py @@ -51,6 +51,7 @@ def bulk_update(path): data = {} bulk_user_data = [] bulk_q_data = [] + bulk_factor_data = [] # fetch all rows from association_table (will print out tuples) for row in cur.execute( @@ -90,6 +91,19 @@ def bulk_update(path): flux.Flux().rpc("job-manager.mf_priority.rec_q_update", json.dumps(data)).get() + # fetch all factors and their associated weights from the plugin_factor_table + for row in cur.execute("SELECT * FROM plugin_factor_table"): + # create a JSON payload with the results of the query + single_factor_data = { + "factor": str(row[0]), + "weight": int(row[1]), + } + bulk_factor_data.append(single_factor_data) + + data = {"data": bulk_factor_data} + + flux.Flux().rpc("job-manager.mf_priority.rec_fac_update", json.dumps(data)).get() + flux.Flux().rpc("job-manager.mf_priority.reprioritize") # close DB connection diff --git a/src/plugins/mf_priority.cpp b/src/plugins/mf_priority.cpp index 6a30be46..b1219e96 100644 --- a/src/plugins/mf_priority.cpp +++ b/src/plugins/mf_priority.cpp @@ -37,6 +37,7 @@ extern "C" { std::map> users; std::map queues; std::map users_def_bank; +std::map plugin_factors; struct bank_info { double fairshare; @@ -340,6 +341,53 @@ static void reprior_cb (flux_t *h, } +/* + * Unpack a payload from an external bulk update service and place it in a + * map datastructure. + */ +static void rec_f_cb (flux_t *h, + flux_msg_handler_t *mh, + const flux_msg_t *msg, + void *arg) +{ + char *factor = NULL; + int weight = 0; + json_t *data, *jtemp = NULL; + json_error_t error; + int num_data = 0; + + if (flux_request_unpack (msg, NULL, "{s:o}", "data", &data) < 0) { + flux_log_error (h, "failed to unpack custom_priority.trigger msg"); + goto error; + } + + if (flux_respond (h, msg, NULL) < 0) + flux_log_error (h, "flux_respond"); + + if (!data || !json_is_array (data)) { + flux_log (h, LOG_ERR, "mf_priority: invalid bulk_update payload"); + goto error; + } + num_data = json_array_size (data); + + for (int i = 0; i < num_data; i++) { + json_t *el = json_array_get(data, i); + + if (json_unpack_ex (el, &error, 0, + "{s:s, s:i}", + "factor", &factor, + "weight", &weight) < 0) + flux_log (h, LOG_ERR, "mf_priority unpack: %s", error.text); + + plugin_factors[factor] = weight; + } + + return; +error: + flux_respond_error (h, msg, errno, flux_msg_last_error (msg)); +} + + /* * Unpack the urgency and userid from a submitted job and call * priority_calculation (), which will return a new job priority to be packed. @@ -810,7 +858,8 @@ extern "C" int flux_plugin_init (flux_plugin_t *p) if (flux_plugin_register (p, "mf_priority", tab) < 0 || flux_jobtap_service_register (p, "rec_update", rec_update_cb, p) || flux_jobtap_service_register (p, "reprioritize", reprior_cb, p) - || flux_jobtap_service_register (p, "rec_q_update", rec_q_cb, p) < 0) + || flux_jobtap_service_register (p, "rec_q_update", rec_q_cb, p) + || flux_jobtap_service_register (p, "rec_fac_update", rec_f_cb, p) < 0) return -1; struct queue_info *q; From b55c62aae94c4ae8c423633e3dc61be4197ecc19 Mon Sep 17 00:00:00 2001 From: Christopher Moussa Date: Tue, 8 Mar 2022 10:07:17 -0800 Subject: [PATCH 4/6] plugin: use plugin_factors map to fetch weights Instead of hard-coding the weights for all of the priority factors in the priority_calculation() function, fetch the weights stored in the plugin_factors map, which contains information about the various priority factors and their associated weights defined in the flux-accounting DB plugin_factor_table. If for some reason the weight of either factor cannot be found, a weight of 0 will be used in the priority calculation of a job. --- src/plugins/mf_priority.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plugins/mf_priority.cpp b/src/plugins/mf_priority.cpp index b1219e96..73676cfa 100644 --- a/src/plugins/mf_priority.cpp +++ b/src/plugins/mf_priority.cpp @@ -85,8 +85,9 @@ int64_t priority_calculation (flux_plugin_t *p, int fshare_weight, queue_weight; struct bank_info *b; - fshare_weight = 100000; - queue_weight = 10000; + // fetch associated weights of all of the priority factors + fshare_weight = plugin_factors["fairshare"]; + queue_weight = plugin_factors["queue"]; if (urgency == FLUX_JOB_URGENCY_HOLD) return FLUX_JOB_PRIORITY_MIN; From 16bd4531e41548aff15439cbcf84599ffd07d3af Mon Sep 17 00:00:00 2001 From: Christopher Moussa Date: Tue, 8 Mar 2022 10:09:34 -0800 Subject: [PATCH 5/6] t: add plugin_factor RPC to fake payloads --- t/t1001-mf-priority-basic.t | 7 +++++++ t/t1002-mf-priority-small-no-tie.t | 9 ++++++++- t/t1003-mf-priority-small-tie.t | 9 ++++++++- t/t1004-mf-priority-small-tie-all.t | 9 ++++++++- t/t1005-max-jobs-limits.t | 9 ++++++++- t/t1012-mf-priority-load.t | 7 +++++++ t/t1014-mf-priority-dne.t | 7 +++++++ 7 files changed, 53 insertions(+), 4 deletions(-) diff --git a/t/t1001-mf-priority-basic.t b/t/t1001-mf-priority-basic.t index e827790d..07d67792 100755 --- a/t/t1001-mf-priority-basic.t +++ b/t/t1001-mf-priority-basic.t @@ -77,6 +77,13 @@ test_expect_success 'create fake_payload.py' ' ] } flux.Flux().rpc("job-manager.mf_priority.rec_q_update", json.dumps(bulk_queue_data)).get() + bulk_fac_data = { + "data" : [ + {"factor": "fairshare", "weight": 100000}, + {"factor": "queue", "weight": 10000} + ] + } + flux.Flux().rpc("job-manager.mf_priority.rec_fac_update", json.dumps(bulk_fac_data)).get() EOF ' diff --git a/t/t1002-mf-priority-small-no-tie.t b/t/t1002-mf-priority-small-no-tie.t index a5b9d346..1ab7fec7 100755 --- a/t/t1002-mf-priority-small-no-tie.t +++ b/t/t1002-mf-priority-small-no-tie.t @@ -41,7 +41,7 @@ test_expect_success 'send the user information to the plugin' ' flux python ${SEND_PAYLOAD} fake_small_no_tie.json ' -test_expect_success 'add a default queue and send it to the plugin' ' +test_expect_success 'add a default queue and plugin weights and send it to the plugin' ' cat <<-EOF >fake_payload.py import flux import json @@ -58,6 +58,13 @@ test_expect_success 'add a default queue and send it to the plugin' ' ] } flux.Flux().rpc("job-manager.mf_priority.rec_q_update", json.dumps(bulk_queue_data)).get() + bulk_fac_data = { + "data" : [ + {"factor": "fairshare", "weight": 100000}, + {"factor": "queue", "weight": 10000} + ] + } + flux.Flux().rpc("job-manager.mf_priority.rec_fac_update", json.dumps(bulk_fac_data)).get() EOF flux python fake_payload.py ' diff --git a/t/t1003-mf-priority-small-tie.t b/t/t1003-mf-priority-small-tie.t index 7848144c..8504cd19 100755 --- a/t/t1003-mf-priority-small-tie.t +++ b/t/t1003-mf-priority-small-tie.t @@ -42,7 +42,7 @@ test_expect_success 'send the user information to the plugin' ' flux python ${SEND_PAYLOAD} fake_small_tie.json ' -test_expect_success 'add a default queue and send it to the plugin' ' +test_expect_success 'add a default queue and plugin weights and send it to the plugin' ' cat <<-EOF >fake_payload.py import flux import json @@ -59,6 +59,13 @@ test_expect_success 'add a default queue and send it to the plugin' ' ] } flux.Flux().rpc("job-manager.mf_priority.rec_q_update", json.dumps(bulk_queue_data)).get() + bulk_fac_data = { + "data" : [ + {"factor": "fairshare", "weight": 100000}, + {"factor": "queue", "weight": 10000} + ] + } + flux.Flux().rpc("job-manager.mf_priority.rec_fac_update", json.dumps(bulk_fac_data)).get() EOF flux python fake_payload.py ' diff --git a/t/t1004-mf-priority-small-tie-all.t b/t/t1004-mf-priority-small-tie-all.t index 59c889de..57d30cf9 100755 --- a/t/t1004-mf-priority-small-tie-all.t +++ b/t/t1004-mf-priority-small-tie-all.t @@ -43,7 +43,7 @@ test_expect_success 'send the user information to the plugin' ' flux python ${SEND_PAYLOAD} fake_small_tie_all.json ' -test_expect_success 'add a default queue and send it to the plugin' ' +test_expect_success 'add a default queue and plugin weights and send it to the plugin' ' cat <<-EOF >fake_payload.py import flux import json @@ -60,6 +60,13 @@ test_expect_success 'add a default queue and send it to the plugin' ' ] } flux.Flux().rpc("job-manager.mf_priority.rec_q_update", json.dumps(bulk_queue_data)).get() + bulk_fac_data = { + "data" : [ + {"factor": "fairshare", "weight": 100000}, + {"factor": "queue", "weight": 10000} + ] + } + flux.Flux().rpc("job-manager.mf_priority.rec_fac_update", json.dumps(bulk_fac_data)).get() EOF flux python fake_payload.py ' diff --git a/t/t1005-max-jobs-limits.t b/t/t1005-max-jobs-limits.t index ea8cd0db..85ef8a10 100755 --- a/t/t1005-max-jobs-limits.t +++ b/t/t1005-max-jobs-limits.t @@ -52,7 +52,7 @@ test_expect_success 'update plugin with sample test data' ' flux python ${SEND_PAYLOAD} fake_user.json ' -test_expect_success 'add a default queue and send it to the plugin' ' +test_expect_success 'add a default queue and plugin weights and send it to the plugin' ' cat <<-EOF >fake_payload.py import flux import json @@ -69,6 +69,13 @@ test_expect_success 'add a default queue and send it to the plugin' ' ] } flux.Flux().rpc("job-manager.mf_priority.rec_q_update", json.dumps(bulk_queue_data)).get() + bulk_fac_data = { + "data" : [ + {"factor": "fairshare", "weight": 100000}, + {"factor": "queue", "weight": 10000} + ] + } + flux.Flux().rpc("job-manager.mf_priority.rec_fac_update", json.dumps(bulk_fac_data)).get() EOF flux python fake_payload.py ' diff --git a/t/t1012-mf-priority-load.t b/t/t1012-mf-priority-load.t index 20d344fa..0b71ff77 100755 --- a/t/t1012-mf-priority-load.t +++ b/t/t1012-mf-priority-load.t @@ -49,6 +49,13 @@ test_expect_success 'create fake_payload.py' ' ] } flux.Flux().rpc("job-manager.mf_priority.rec_q_update", json.dumps(bulk_queue_data)).get() + bulk_factor_data = { + "data" : [ + {"factor": "fairshare", "weight": 100000}, + {"factor": "queue", "weight": 10000} + ] + } + flux.Flux().rpc("job-manager.mf_priority.rec_fac_update", json.dumps(bulk_factor_data)).get() flux.Flux().rpc("job-manager.mf_priority.reprioritize") EOF ' diff --git a/t/t1014-mf-priority-dne.t b/t/t1014-mf-priority-dne.t index cb86c53c..83b3e83a 100755 --- a/t/t1014-mf-priority-dne.t +++ b/t/t1014-mf-priority-dne.t @@ -62,6 +62,13 @@ test_expect_success 'send the user/bank information to the plugin without reprio ] } flux.Flux().rpc("job-manager.mf_priority.rec_q_update", json.dumps(bulk_queue_data)).get() + bulk_fac_data = { + "data" : [ + {"factor": "fairshare", "weight": 100000}, + {"factor": "queue", "weight": 10000} + ] + } + flux.Flux().rpc("job-manager.mf_priority.rec_fac_update", json.dumps(bulk_fac_data)).get() EOF flux python fake_payload.py ' From 7ad1f14c6513463c5ac5c03acceb3fff8f1284c8 Mon Sep 17 00:00:00 2001 From: Christopher Moussa Date: Wed, 2 Mar 2022 10:55:19 -0800 Subject: [PATCH 6/6] test: add tests for plugin_factor commands --- .../python/fluxacct/accounting/Makefile.am | 3 +- .../test/test_plugin_factor_subcommands.py | 68 ++++++++++++++ t/Makefile.am | 3 +- t/t1007-flux-account.t | 22 +++++ t/t1015-mf-priority-weights.t | 92 +++++++++++++++++++ 5 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 src/bindings/python/fluxacct/accounting/test/test_plugin_factor_subcommands.py create mode 100755 t/t1015-mf-priority-weights.t diff --git a/src/bindings/python/fluxacct/accounting/Makefile.am b/src/bindings/python/fluxacct/accounting/Makefile.am index fdfffb13..c1f56df3 100644 --- a/src/bindings/python/fluxacct/accounting/Makefile.am +++ b/src/bindings/python/fluxacct/accounting/Makefile.am @@ -17,7 +17,8 @@ TESTSCRIPTS = \ test/test_example.py \ test/test_job_archive_interface.py \ test/test_user_subcommands.py \ - test/test_queue_subcommands.py + test/test_queue_subcommands.py \ + test/test_plugin_factor_subcommands.py dist_check_SCRIPTS = \ $(TESTSCRIPTS) diff --git a/src/bindings/python/fluxacct/accounting/test/test_plugin_factor_subcommands.py b/src/bindings/python/fluxacct/accounting/test/test_plugin_factor_subcommands.py new file mode 100644 index 00000000..4cb0024d --- /dev/null +++ b/src/bindings/python/fluxacct/accounting/test/test_plugin_factor_subcommands.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 + +############################################################### +# Copyright 2020 Lawrence Livermore National Security, LLC +# (c.f. AUTHORS, NOTICE.LLNS, COPYING) +# +# This file is part of the Flux resource manager framework. +# For details, see https://github.com/flux-framework. +# +# SPDX-License-Identifier: LGPL-3.0 +############################################################### +import unittest +import os +import sqlite3 + +from fluxacct.accounting import create_db as c +from fluxacct.accounting import plugin_factor_subcommands as p + + +class TestAccountingCLI(unittest.TestCase): + @classmethod + def setUpClass(self): + # create test accounting database + c.create_db("TestPluginFactorSubcommands.db") + global acct_conn + global cur + + acct_conn = sqlite3.connect("TestPluginFactorSubcommands.db") + cur = acct_conn.cursor() + + # edit the weight for the fairshare factor + def test_01_edit_fairshare_factor_successfully(self): + p.edit_factor(acct_conn, factor="fairshare", weight=1500) + cur.execute("SELECT weight FROM plugin_factor_table WHERE factor='fairshare'") + row = cur.fetchone() + + self.assertEqual(row[0], 1500) + + # edit the weight for the queue factor + def test_02_edit_queue_factor_successfully(self): + p.edit_factor(acct_conn, factor="queue", weight=200) + cur.execute("SELECT weight FROM plugin_factor_table WHERE factor='queue'") + row = cur.fetchone() + + self.assertEqual(row[0], 200) + + # try to edit a factor with a bad type + def test_03_edit_factor_bad_type(self): + with self.assertRaises(ValueError): + p.edit_factor(acct_conn, factor="fairshare", weight="foo") + + # remove database and log file + @classmethod + def tearDownClass(self): + acct_conn.close() + os.remove("TestPluginFactorSubcommands.db") + + +def suite(): + suite = unittest.TestSuite() + + return suite + + +if __name__ == "__main__": + from pycotap import TAPTestRunner + + unittest.main(testRunner=TAPTestRunner()) diff --git a/t/Makefile.am b/t/Makefile.am index 1252baea..e01b9c6f 100644 --- a/t/Makefile.am +++ b/t/Makefile.am @@ -15,7 +15,8 @@ TESTSCRIPTS = \ t1011-job-archive-interface.t \ t1012-mf-priority-load.t \ t1013-mf-priority-queues.t \ - t1014-mf-priority-dne.t + t1014-mf-priority-dne.t \ + t1015-mf-priority-weights.t dist_check_SCRIPTS = \ $(TESTSCRIPTS) \ diff --git a/t/t1007-flux-account.t b/t/t1007-flux-account.t index a6a9d7fe..17f0e007 100755 --- a/t/t1007-flux-account.t +++ b/t/t1007-flux-account.t @@ -167,6 +167,28 @@ test_expect_success 'remove a queue from the queue_table' ' grep "Queue not found in queue_table" deleted_queue.out ' +test_expect_success 'view plugin factor information' ' + flux account -p ${DB_PATH} view-plugin-factor fairshare > fshare_factor.test && + grep "fairshare 100000" fshare_factor.test +' + +test_expect_success 'edit a plugin factor successfully' ' + flux account -p ${DB_PATH} edit-plugin-factor fairshare --weight=1234 && + flux account -p ${DB_PATH} view-plugin-factor fairshare > fshare_factor_edited.test && + grep "fairshare 1234" fshare_factor_edited.test +' + +test_expect_success 'try to edit a plugin factor with a bad type' ' + test_must_fail flux account -p ${DB_PATH} edit-plugin-factor fairshare --weight=foo > bad_type.out 2>&1 && + test_debug "bad_type.out" && + grep "edit-plugin-factor: error: argument --weight: invalid int value:" bad_type.out +' + +test_expect_success 'try to view a plugin factor that does not exist' ' + flux account -p ${DB_PATH} view-plugin-factor foo > no_such_factor.out && + grep "Factor not found in plugin_factor_table" no_such_factor.out +' + test_expect_success 'remove flux-accounting DB' ' rm $(pwd)/FluxAccountingTest.db ' diff --git a/t/t1015-mf-priority-weights.t b/t/t1015-mf-priority-weights.t new file mode 100755 index 00000000..de778aad --- /dev/null +++ b/t/t1015-mf-priority-weights.t @@ -0,0 +1,92 @@ +#!/bin/bash + +test_description='Test configuring plugin weights and their effects on priority calculation' + +. `dirname $0`/sharness.sh +MULTI_FACTOR_PRIORITY=${FLUX_BUILD_DIR}/src/plugins/.libs/mf_priority.so +DB_PATH=$(pwd)/FluxAccountingTest.db + +export TEST_UNDER_FLUX_NO_JOB_EXEC=y +export TEST_UNDER_FLUX_SCHED_SIMPLE_MODE="limited=1" +test_under_flux 1 job + +flux setattr log-stderr-level 1 + +test_expect_success 'load multi-factor priority plugin' ' + flux jobtap load -r .priority-default ${MULTI_FACTOR_PRIORITY} +' + +test_expect_success 'check that mf_priority plugin is loaded' ' + flux jobtap list | grep mf_priority +' + +test_expect_success 'create flux-accounting DB' ' + flux account -p $(pwd)/FluxAccountingTest.db create-db +' + +test_expect_success 'add some banks to the DB' ' + flux account -p ${DB_PATH} add-bank root 1 && + flux account -p ${DB_PATH} add-bank --parent-bank=root account1 1 +' + +test_expect_success 'add a default queue to the DB' ' + flux account -p ${DB_PATH} add-queue default --priority=100 +' + +test_expect_success 'add a user to the DB' ' + username=$(whoami) && + uid=$(id -u) && + flux account -p ${DB_PATH} add-user --username=$username --userid=$uid --bank=account1 --shares=1 +' + +test_expect_success 'view queue information' ' + flux account -p ${DB_PATH} view-plugin-factor fairshare > fshare_weight.test && + grep "fairshare 100000" fshare_weight.test && + flux account -p ${DB_PATH} view-plugin-factor queue > queue_weight.test && + grep "queue 10000" queue_weight.test +' + +test_expect_success 'send the user, queue, and plugin factor weight information to the plugin' ' + flux account-priority-update -p $(pwd)/FluxAccountingTest.db +' + +test_expect_success 'submit a job using default fshare and queue factor weights' ' + jobid1=$(flux mini submit -n1 hostname) && + flux job wait-event -f json $jobid1 priority | jq '.context.priority' > job1.test && + cat <<-EOF >job1.expected && + 1050000 + EOF + test_cmp job1.expected job1.test +' + +test_expect_success 'edit plugin factor weights to give fairshare all the weight' ' + flux account -p ${DB_PATH} edit-plugin-factor fairshare --weight=1000 && + flux account -p ${DB_PATH} edit-plugin-factor queue --weight=0 && + flux account-priority-update -p $(pwd)/FluxAccountingTest.db +' + +test_expect_success 'submit a job using the new fshare and queue factor weights' ' + jobid2=$(flux mini submit -n1 hostname) && + flux job wait-event -f json $jobid2 priority | jq '.context.priority' > job2.test && + cat <<-EOF >job2.expected && + 500 + EOF + test_cmp job2.expected job2.test +' + +test_expect_success 'edit plugin factor weights to give queue all the weight' ' + flux account -p ${DB_PATH} edit-plugin-factor fairshare --weight=0 && + flux account -p ${DB_PATH} edit-plugin-factor queue --weight=1000 && + flux account-priority-update -p $(pwd)/FluxAccountingTest.db +' + +test_expect_success 'submit a job using the new fshare and queue factor weights' ' + jobid3=$(flux mini submit -n1 hostname) && + flux job wait-event -f json $jobid3 priority | jq '.context.priority' > job3.test && + cat <<-EOF >job3.expected && + 100000 + EOF + test_cmp job3.expected job3.test +' + +test_done