From e66a3daf6139e56fe6f6439d771fcc7888f2849e Mon Sep 17 00:00:00 2001 From: Zeke Morton Date: Mon, 9 Oct 2023 15:05:25 -0700 Subject: [PATCH 1/6] reapi: track match success and update info for match allocate Problem: reapi_cli_t::match_allocate does not return or track whether a match was successful or not. It also sets the job info with an unset value for overhead. Check return code from traverser run to determine if a match is successful. If a match is not successful, increase the job counter and return 0. errno is set with the correct error value to be handled by the calling function. Move code blocks that set overhead value ov above blocks where job info is created. --- .../reapi/bindings/c++/reapi_cli_impl.hpp | 60 ++++++++++++------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/resource/reapi/bindings/c++/reapi_cli_impl.hpp b/resource/reapi/bindings/c++/reapi_cli_impl.hpp index 6a1dab1c2..9cf6ed9a4 100644 --- a/resource/reapi/bindings/c++/reapi_cli_impl.hpp +++ b/resource/reapi/bindings/c++/reapi_cli_impl.hpp @@ -64,6 +64,7 @@ int reapi_cli_t::match_allocate (void *h, bool orelse_reserve, std::shared_ptr job_info = nullptr; struct timeval start_time, end_time; std::stringstream o; + bool matched = false; try { Flux::Jobspec::Jobspec job {jobspec}; @@ -99,6 +100,19 @@ int reapi_cli_t::match_allocate (void *h, bool orelse_reserve, rc = -1; goto out; } + + if ( (rc != 0) && (errno == ENOMEM)) { + m_err_msg += __FUNCTION__; + m_err_msg += ": ERROR: Memory error for " + + std::to_string (rq->get_job_counter ()); + rc = -1; + goto out; + } + + // Check for an unsuccessful match + if (rc == 0) { + matched = true; + } if ( (rc = rq->writers->emit (o)) < 0) { m_err_msg += __FUNCTION__; @@ -109,28 +123,6 @@ int reapi_cli_t::match_allocate (void *h, bool orelse_reserve, R = o.str (); - - reserved = (at != 0)? true : false; - st = (reserved)? - job_lifecycle_t::RESERVED : job_lifecycle_t::ALLOCATED; - if (reserved) - rq->set_reservation (jobid); - else - rq->set_allocation (jobid); - - job_info = std::make_shared (jobid, st, at, "", "", ov); - if (job_info == nullptr) { - errno = ENOMEM; - m_err_msg += __FUNCTION__; - m_err_msg += ": ERROR: can't allocate memory: " - + std::string (strerror (errno))+ "\n"; - rc = -1; - goto out; - } - - rq->set_job (jobid, job_info); - rq->incr_job_counter (); - if ( (rc = gettimeofday (&end_time, NULL)) < 0) { m_err_msg += __FUNCTION__; m_err_msg += ": ERROR: gettimeofday: " @@ -140,6 +132,30 @@ int reapi_cli_t::match_allocate (void *h, bool orelse_reserve, ov = get_elapsed_time (start_time, end_time); + if (matched) { + reserved = (at != 0)? true : false; + st = (reserved)? + job_lifecycle_t::RESERVED : job_lifecycle_t::ALLOCATED; + if (reserved) + rq->set_reservation (jobid); + else + rq->set_allocation (jobid); + + job_info = std::make_shared (jobid, st, at, "", "", ov); + if (job_info == nullptr) { + errno = ENOMEM; + m_err_msg += __FUNCTION__; + m_err_msg += ": ERROR: can't allocate memory: " + + std::string (strerror (errno))+ "\n"; + rc = -1; + goto out; + } + rq->set_job (jobid, job_info); + + } + + rq->incr_job_counter (); + out: return rc; } From c19ddaf7badce4823705fca548ee930c36e94d10 Mon Sep 17 00:00:00 2001 From: Zeke Morton Date: Mon, 9 Oct 2023 15:14:41 -0700 Subject: [PATCH 2/6] reapi: add overloaded info function to reapi_cli_t Problem: current info function only provides a subset of fields from job_info_t. Add an overloaded info function that mutates job parameter to job_info_t value corresponding to jobid. --- resource/reapi/bindings/c++/reapi_cli.hpp | 2 ++ resource/reapi/bindings/c++/reapi_cli_impl.hpp | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/resource/reapi/bindings/c++/reapi_cli.hpp b/resource/reapi/bindings/c++/reapi_cli.hpp index 0ff9ed84b..10b67aeea 100644 --- a/resource/reapi/bindings/c++/reapi_cli.hpp +++ b/resource/reapi/bindings/c++/reapi_cli.hpp @@ -141,6 +141,8 @@ class reapi_cli_t : public reapi_t { static int find (void *h, std::string criteria, json_t *&o ); static int info (void *h, const uint64_t jobid, std::string &mode, bool &reserved, int64_t &at, double &ov); + static int info (void *h, const uint64_t jobid, + std::shared_ptr &job); static int stat (void *h, int64_t &V, int64_t &E,int64_t &J, double &load, double &min, double &max, double &avg); static const std::string &get_err_message (); diff --git a/resource/reapi/bindings/c++/reapi_cli_impl.hpp b/resource/reapi/bindings/c++/reapi_cli_impl.hpp index 9cf6ed9a4..861d5ba52 100644 --- a/resource/reapi/bindings/c++/reapi_cli_impl.hpp +++ b/resource/reapi/bindings/c++/reapi_cli_impl.hpp @@ -250,6 +250,22 @@ int reapi_cli_t::info (void *h, const uint64_t jobid, std::string &mode, return 0; } +int reapi_cli_t::info (void *h, const uint64_t jobid, + std::shared_ptr &job) +{ + resource_query_t *rq = static_cast (h); + + if ( !(rq->job_exists (jobid))) { + m_err_msg += __FUNCTION__; + m_err_msg += ": ERROR: nonexistent job " + + std::to_string (jobid) + "\n"; + return -1; + } + + job = rq->get_job (jobid); + return 0; +} + int reapi_cli_t::stat (void *h, int64_t &V, int64_t &E,int64_t &J, double &load, double &min, double &max, double &avg) { From e8e98629b561f750635b01977b630bed98480d42 Mon Sep 17 00:00:00 2001 From: Zeke Morton Date: Tue, 10 Oct 2023 16:31:32 -0700 Subject: [PATCH 3/6] reapi: add accessors for traverser pre/post order count Problem: new resource query and potentially other tools using this api may need access to the traverser pre and post order counts. Accessors for these fields do not exist. Create accessors for these fields in reapi_cli_t and resource_query_t. --- resource/reapi/bindings/c++/reapi_cli.hpp | 6 ++++- .../reapi/bindings/c++/reapi_cli_impl.hpp | 24 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/resource/reapi/bindings/c++/reapi_cli.hpp b/resource/reapi/bindings/c++/reapi_cli.hpp index 10b67aeea..66cd2efba 100644 --- a/resource/reapi/bindings/c++/reapi_cli.hpp +++ b/resource/reapi/bindings/c++/reapi_cli.hpp @@ -72,6 +72,8 @@ class resource_query_t { const std::shared_ptr &get_job (const uint64_t jobid); const bool reservation_exists (const uint64_t jobid); const bool allocation_exists (const uint64_t jobid); + const unsigned int preorder_count (); + const unsigned int postorder_count (); /* Mutators */ void clear_resource_query_err_msg (); @@ -142,7 +144,9 @@ class reapi_cli_t : public reapi_t { static int info (void *h, const uint64_t jobid, std::string &mode, bool &reserved, int64_t &at, double &ov); static int info (void *h, const uint64_t jobid, - std::shared_ptr &job); + std::shared_ptr &job); + static unsigned int preorder_count (void *h); + static unsigned int postorder_count (void *h); static int stat (void *h, int64_t &V, int64_t &E,int64_t &J, double &load, double &min, double &max, double &avg); static const std::string &get_err_message (); diff --git a/resource/reapi/bindings/c++/reapi_cli_impl.hpp b/resource/reapi/bindings/c++/reapi_cli_impl.hpp index 861d5ba52..b07abfa51 100644 --- a/resource/reapi/bindings/c++/reapi_cli_impl.hpp +++ b/resource/reapi/bindings/c++/reapi_cli_impl.hpp @@ -266,6 +266,20 @@ int reapi_cli_t::info (void *h, const uint64_t jobid, return 0; } +unsigned int reapi_cli_t::preorder_count (void *h) +{ + resource_query_t *rq = static_cast (h); + + return rq->preorder_count (); +} + +unsigned int reapi_cli_t::postorder_count (void *h) +{ + resource_query_t *rq = static_cast (h); + + return rq->postorder_count (); +} + int reapi_cli_t::stat (void *h, int64_t &V, int64_t &E,int64_t &J, double &load, double &min, double &max, double &avg) { @@ -637,6 +651,16 @@ const bool resource_query_t::reservation_exists (const uint64_t jobid) return reservations.find (jobid) != reservations.end (); } +const unsigned int resource_query_t::preorder_count () +{ + return traverser->get_total_preorder_count (); +} + +const unsigned int resource_query_t::postorder_count () +{ + return traverser->get_total_postorder_count (); +} + void resource_query_t::clear_resource_query_err_msg () { m_err_msg = ""; From 6c7ca2e214244047265506c0ec8ae0f8b14554af Mon Sep 17 00:00:00 2001 From: Zeke Morton Date: Tue, 10 Oct 2023 16:36:55 -0700 Subject: [PATCH 4/6] rq: rq2 structure with match allocate Problem: resource query does not utilize reapi. This means that new functionality must be implemented in both places and that reapi is not tested with automated ci tests and code coverage. Create a new resource query that uses reapi. --- resource/.gitignore | 1 + resource/utilities/CMakeLists.txt | 8 + resource/utilities/rq2.cpp | 631 ++++++++++++++++++++++++++++++ resource/utilities/rq2.hpp | 28 ++ 4 files changed, 668 insertions(+) create mode 100644 resource/utilities/rq2.cpp create mode 100644 resource/utilities/rq2.hpp diff --git a/resource/.gitignore b/resource/.gitignore index d4ca2a927..8e886d40e 100644 --- a/resource/.gitignore +++ b/resource/.gitignore @@ -6,3 +6,4 @@ schema/test/schema_test01 schema/test/schema_test02 utilities/grug2dot utilities/resource-query +utilities/rq2 diff --git a/resource/utilities/CMakeLists.txt b/resource/utilities/CMakeLists.txt index 8d8064ed2..7f5c6a050 100644 --- a/resource/utilities/CMakeLists.txt +++ b/resource/utilities/CMakeLists.txt @@ -19,6 +19,14 @@ target_link_libraries(resource-query Boost::filesystem Boost::headers ) +add_executable(rq2 + rq2.cpp + rq2.hpp + ) +target_link_libraries(rq2 + resource + PkgConfig::LIBEDIT + ) add_subdirectory(test) diff --git a/resource/utilities/rq2.cpp b/resource/utilities/rq2.cpp new file mode 100644 index 000000000..9043128c6 --- /dev/null +++ b/resource/utilities/rq2.cpp @@ -0,0 +1,631 @@ +/*****************************************************************************\ + * Copyright 2022 Lawrence Livermore National Security, LLC + * (c.f. AUTHORS, NOTICE.LLNS, LICENSE) + * + * This file is part of the Flux resource manager framework. + * For details, see https://github.com/flux-framework. + * + * SPDX-License-Identifier: LGPL-3.0 +\*****************************************************************************/ + +#include "resource/reapi/bindings/c++/reapi_cli.hpp" +#include "resource/reapi/bindings/c++/reapi_cli_impl.hpp" +#include "rq2.hpp" +#include +#include +#include +#include +#include +#include + +namespace fs = boost::filesystem; +using namespace Flux; +using namespace Flux::resource_model; +using namespace Flux::resource_model::detail; + +typedef int cmd_func_f (resource_query_t &, + std::vector &, + json_t *, std::ostream &); + +#define OPTIONS "L:f:W:S:P:F:g:o:p:t:r:edh" +static const struct option longopts[] = { + {"load-file", required_argument, 0, 'L'}, + {"load-format", required_argument, 0, 'f'}, + {"load-allowlist", required_argument, 0, 'W'}, + {"match-subsystems", required_argument, 0, 'S'}, + {"match-policy", required_argument, 0, 'P'}, + {"match-format", required_argument, 0, 'F'}, + {"graph-format", required_argument, 0, 'g'}, + {"graph-output", required_argument, 0, 'o'}, + {"prune-filters", required_argument, 0, 'p'}, + {"test-output", required_argument, 0, 't'}, + {"reserve-vtx-vec", required_argument, 0, 'r'}, + {"elapse-time", no_argument, 0, 'e'}, + {"disable-prompt", no_argument, 0, 'd'}, + {"help", no_argument, 0, 'h'}, + { 0, 0, 0, 0 }, +}; + +struct command_t { + std::string name; + std::string abbr; + cmd_func_f *cmd; + std::string note; +}; + +command_t commands[] = { + { "match", "m", match, "Allocate or reserve matching resources (subcmd: " +"allocate | allocate_with_satisfiability | allocate_orelse_reserve) | " +"satisfiability: " +"resource-query> match allocate jobspec"}, + { "help", "h", help, "Print help message: resource-query> help" }, + { "quit", "q", quit, "Quit the session: resource-query> quit" }, + { "NA", "NA", (cmd_func_f *)NULL, "NA" } +}; + + +static void usage (int code) +{ + std::cerr << +"usage: resource-query [OPTIONS...]\n" +"\n" +"Command-line utility that takes in an HPC resource request written in\n" +"Flux's Canonical Job Specification (or simply a jobspec) (RFC 14) and\n" +"selects the best-matching compute and other resources in accordance\n" +"with a selection policy.\n" +"\n" +"Read in a resource-graph generation recipe written in the GRUG format\n" +"and populate the resource-graph data store representing the compute and\n" +"other HPC resources and their relationships (RFC 4).\n" +"\n" +"Provide a simple command-line interface (cli) to allow users to allocate\n" +"or reserve the resource set in this resource-graph data store \n" +"using a jobspec as an input.\n" +"Traverse the resource graph in a predefined order for resource selection.\n" +"Currently only support one traversal type: depth-first traversal on the\n" +"dominant subsystem and up-walk traversal on one or more auxiliary \n" +"subsystems.\n" +"\n" +"OPTIONS allow for using a predefined matcher that is configured\n" +"to use a different set of subsystems as its dominant and/or auxiliary\n" +"ones to perform the matches on.\n" +"\n" +"OPTIONS also allow for instantiating a different resource-matching\n" +"selection policy--e.g., select resources with high or low IDs first.\n" +"\n" +"OPTIONS allow for exporting the filtered graph of the used matcher\n" +"in a selected graph format at the end of the cli session.\n" +"\n" +"To see cli commands, type in \"help\" in the cli: i.e.,\n" +" % resource-query> help\n" +"\n" +"\n" +"\n" +"OPTIONS:\n" +" -h, --help\n" +" Display this usage information\n" +"\n" +" -L, --load-file=filepath\n" +" Input file from which to load the resource graph data store\n" +" (default=conf/default)\n" +"\n" +" -f, --load-format=\n" +" Format of the load file (default=grug)\n" +"\n" +" -W, --load-allowlist=\n" +" Allowlist of resource types to be loaded\n" +" Resources that are not included in this list will be filtered out\n" +"\n" +" -S, --match-subsystems=" + "\n" +" Set the predefined matcher to use. Available matchers are:\n" +" CA: Containment Aware\n" +" IBA: InfiniBand connection-Aware\n" +" IBBA: InfiniBand Bandwidth-Aware\n" +" PFS1BA: Parallel File System 1 Bandwidth-aware\n" +" PA: Power-Aware\n" +" C+IBA: Containment- and InfiniBand connection-Aware\n" +" C+PFS1BA: Containment- and PFS1 Bandwidth-Aware\n" +" C+PA: Containment- and Power-Aware\n" +" IB+IBBA: InfiniBand connection and Bandwidth-Aware\n" +" C+P+IBA: Containment-, Power- and InfiniBand connection-Aware\n" +" VA: Virtual Hierarchy-Aware\n" +" V+PFS1BA: Virtual Hierarchy and PFS1 Bandwidth-Aware \n" +" ALL: Aware of everything.\n" +" (default=CA).\n" +"\n" +" -P, --match-policy=\n" +" Set the resource match selection policy. Available policies are:\n" +" low: Select resources with low ID first\n" +" high: Select resources with high ID first\n" +" lonode: Select resources with lowest node ID first, \n" +" low ID first otherwise (e.g., node-local resource types) \n" +" hinode: Select resources with highest node ID first, \n" +" high ID first otherwise (e.g., node-local resource types) \n" +" lonodex: Same as lonode except each node is exclusively allocated \n" +" hinodex: Same as hinode except each node is exclusively allocated \n" +" first: Select the first matching resources and stop the search\n" +" locality: Select contiguous resources first in their ID space\n" +" variation: Allocate resources based on performance classes.\n" +" (perf_class must be set using set-property).\n" +" (default=first).\n" +"\n" +" -F, --match-format=\n" +" Specify the emit format of the matched resource set.\n" +" (default=simple).\n" +"\n" +" -p, --prune-filters=\n" +" Install a planner-based filter at each High-Level (HL) resource\n" +" vertex which tracks the state of the Low-Level (LL) resources\n" +" in aggregate, residing under its subtree. If a jobspec requests\n" +" 1 node with 4 cores, and the visiting compute-node vertex has\n" +" only a total of 2 available cores in aggregate at its\n" +" subtree, this filter allows the traverser to prune a further descent\n" +" to accelerate the search.\n" +" Use the ALL keyword for HL-resource if you want LL-resource to be\n" +" tracked at all of the HL-resource vertices. Examples:\n" +" rack:node,node:core\n" +" ALL:core,cluster:node,rack:node\n" +" (default=ALL:core).\n" +"\n" +" -g, --graph-format=\n" +" Specify the graph format of the output file\n" +" (default=dot).\n" +"\n" +" -r, --reserve-vtx-vec=\n" +" Reserve the graph vertex size to optimize resource graph loading.\n" +" The size value must be a non-zero integer up to 2000000.\n" +"\n" +" -e, --elapse-time\n" +" Print the elapse time per scheduling operation.\n" +"\n" +" -d, --disable-prompt\n" +" Don't print the prompt.\n" +"\n" +" -o, --graph-output=\n" +" Set the basename of the graph output file\n" +" For AT&T Graphviz dot, .dot\n" +" For GraphML, .graphml.\n" +"\n" +" -t, --test-output=\n" +" Set the output filename where allocated or reserved resource\n" +" information is stored into.\n" +"\n"; + exit (code); +} + +static int string_to_graph_format (std::string st, Flux::resource_model::emit_format_t &format) +{ + int rc = 0; + if (boost::iequals (st, std::string ("dot"))) + format = Flux::resource_model::emit_format_t::GRAPHVIZ_DOT; + else if (boost::iequals (st, std::string ("graphml"))) + format = Flux::resource_model::emit_format_t::GRAPH_ML; + else + rc = -1; + return rc; +} + +static int graph_format_to_ext (Flux::resource_model::emit_format_t format, std::string &st) +{ + int rc = 0; + switch (format) { + case Flux::resource_model::emit_format_t::GRAPHVIZ_DOT: + st = "dot"; + break; + case Flux::resource_model::emit_format_t::GRAPH_ML: + st = "graphml"; + break; + default: + rc = -1; + } + return rc; +} + +static void print_sat_info (resource_query_t &ctx, + std::ostream &out, bool sat, double elapse, + bool print_elapse) +{ + unsigned int pre = reapi_cli_t::preorder_count (&ctx); + unsigned int post = reapi_cli_t::postorder_count (&ctx); + std::string satstr = sat? "Satisfiable" : "Unsatisfiable"; + out << "INFO:" << " =============================" << std::endl; + out << "INFO: " << satstr << " request" << std::endl; + out << "INFO:" << " =============================" << std::endl; + if (print_elapse) { + std::cout << "INFO:" << " ELAPSE=" << std::to_string (elapse) + << std::endl; + std::cout << "INFO:" << " PREORDER VISIT COUNT=" << pre + << std::endl; + std::cout << "INFO:" << " POSTORDER VISIT COUNT=" << post + << std::endl; + } +} + +static void print_schedule_info (resource_query_t &ctx, + std::ostream &out, uint64_t jobid, + const std::string &jobspec_fn, bool matched, + int64_t at, bool sat, double elapse, + bool print_elapse) +{ + unsigned int pre = reapi_cli_t::preorder_count (&ctx); + unsigned int post = reapi_cli_t::postorder_count (&ctx); + if (matched) { + job_lifecycle_t st; + std::shared_ptr job = nullptr; + std::string mode = (at == 0)? "ALLOCATED" : "RESERVED"; + std::string scheduled_at = (at == 0)? "Now" : std::to_string (at); + out << "INFO:" << " =============================" << std::endl; + out << "INFO:" << " JOBID=" << jobid << std::endl; + out << "INFO:" << " RESOURCES=" << mode << std::endl; + out << "INFO:" << " SCHEDULED AT=" << scheduled_at << std::endl; + if (print_elapse) { + std::cout << "INFO:" << " ELAPSE=" << std::to_string (elapse) + << std::endl; + std::cout << "INFO:" << " PREORDER VISIT COUNT=" << pre + << std::endl; + std::cout << "INFO:" << " POSTORDER VISIT COUNT=" << post + << std::endl; + } + out << "INFO:" << " =============================" << std::endl; + st = (at == 0)? job_lifecycle_t::ALLOCATED : job_lifecycle_t::RESERVED; + if (reapi_cli_t::info (&ctx, jobid, job) == 0) + job->jobspec_fn = jobspec_fn; + } else { + out << "INFO:" << " =============================" << std::endl; + out << "INFO: " << "No matching resources found" << std::endl; + if (!sat) + out << "INFO: " << "Unsatisfiable request" << std::endl; + out << "INFO:" << " JOBID=" << jobid << std::endl; + if (print_elapse) { + out << "INFO:" << " ELAPSE=" << std::to_string (elapse) + << std::endl; + std::cout << "INFO:" << " PREORDER VISIT COUNT=" << pre + << std::endl; + std::cout << "INFO:" << " POSTORDER VISIT COUNT=" << post + << std::endl; + } + out << "INFO:" << " =============================" << std::endl; + } +} + +bool r_fname_set (json_t *params) +{ + return (json_object_get (params, "r_fname") != NULL); +} + +std::ofstream open_fs (json_t *params) { + std::string r_fname = json_string_value (json_object_get (params, "r_fname")); + std::ofstream r_out; + + r_out.exceptions (std::ofstream::failbit | + std::ofstream::badbit); + + r_out.open (r_fname); + + return r_out; +} +int match (resource_query_t &ctx, std::vector &args, + json_t *params, std::ostream &out) +{ + int rc = 0; + int64_t at = 0; + bool orelse_reserve = false; + bool reserved = false; + bool sat = true; + bool matched = true; + std::string R = ""; + double ov = 0.0; + std::stringstream o; + struct timeval st, et; + + if ( (gettimeofday (&st, NULL)) < 0) { + std::cerr << "ERROR: gettimeofday: " << strerror (errno) << std::endl; + return 0; + } + + if (args.size () != 3) { + std::cerr << "ERROR: malformed command" << std::endl; + return 0; + } + std::string subcmd = args[1]; + if (!(subcmd == "allocate" || subcmd == "allocate_orelse_reserve" + || subcmd == "allocate_with_satisfiability" + || subcmd == "satisfiability")) { + std::cerr << "ERROR: unknown subcmd " << args[1] << std::endl; + return 0; + } + + if (subcmd == "allocate_orelse_reserve") { + orelse_reserve = true; + } + + uint64_t jobid = ctx.get_job_counter (); + std::string &jobspec_fn = args[2]; + std::ifstream jobspec_in (jobspec_fn); + if (!jobspec_in) { + std::cerr << "ERROR: can't open " << jobspec_fn << std::endl; + return 0; + } + std::string jobspec ( (std::istreambuf_iterator (jobspec_in) ), + (std::istreambuf_iterator () ) ); + + rc = reapi_cli_t::match_allocate (&ctx, orelse_reserve, jobspec, jobid, reserved, R, at, ov); + + // check for match success + if ( (errno == ENODEV) || (errno == EBUSY) || (errno == EINVAL)) + matched = false; + + // check for satisfiability + if (errno == ENODEV) + sat = false; + + if (reapi_cli_t::get_err_message () != "") { + std::cerr << reapi_cli_t::get_err_message () << std::endl; + reapi_cli_t::clear_err_message (); + } + + out << R; + + if ( (gettimeofday (&et, NULL)) < 0) { + std::cerr << "ERROR: gettimeofday: " << strerror (errno) << std::endl; + return 0; + } + + if (subcmd != "satisfiability") + print_schedule_info (ctx, out, jobid, + jobspec_fn, matched, at, sat, + ov, json_object_get (params, "elapse_time")); + else + print_sat_info (ctx, out, sat, ov, + json_object_get (params, "elapse_time")); + + jobspec_in.close (); + + return 0; +} + +int quit (resource_query_t &ctx, std::vector &args, + json_t *params, std::ostream &out) +{ + return -1; +} + +int help (resource_query_t &ctx, std::vector &args, + json_t *params, std::ostream &out) +{ + bool multi = true; + bool found = false; + std::string cmd = "unknown"; + + if (args.size () == 2) { + multi = false; + cmd = args[1]; + } + + for (int i = 0; commands[i].name != "NA"; ++i) { + if (multi || cmd == commands[i].name || cmd == commands[i].abbr) { + std::cout << "INFO: " << commands[i].name << " (" + << commands[i].abbr << ")" << " -- " + << commands[i].note << std::endl; + found = true; + } + } + if (!multi && !found) + std::cout << "ERROR: unknown command: " << cmd << std::endl; + + return 0; +} + +cmd_func_f *find_cmd (const std::string &cmd_str) +{ + for (int i = 0; commands[i].name != "NA"; ++i) { + if (cmd_str == commands[i].name) + return commands[i].cmd; + else if (cmd_str == commands[i].abbr) + return commands[i].cmd; + } + return (cmd_func_f *)NULL; +} + +static void process_args (json_t *options, + int argc, char *argv[]) +{ + int rc = 0; + int ch = 0; + std::string token; + Flux::resource_model::emit_format_t format; + + + /* set defaults specific for resource query */ + json_object_set_new (options, "match_format", json_string ("simple")); + + while ( (ch = getopt_long (argc, argv, OPTIONS, longopts, NULL)) != -1) { + switch (ch) { + case 'h': /* --help */ + usage (0); + break; + case 'L': /* --load-file */ + json_object_set_new (options, "load_file", json_string (optarg)); + if (!fs::exists (optarg)) { + std::cerr << "[ERROR] file does not exist for --load-file: "; + std::cerr << optarg << std::endl; + usage (1); + } else if (fs::is_directory (optarg)) { + std::cerr << "[ERROR] path passed to --load-file is a directory: "; + std::cerr << optarg << std::endl; + usage (1); + } + break; + case 'f': /* --load-format */ + json_object_set_new (options, "load_format", json_string (optarg)); + if (!known_resource_reader (optarg)) { + std::cerr << "[ERROR] unknown format for --load-format: "; + std::cerr << optarg << std::endl; + usage (1); + } + break; + case 'W': /* --hwloc-allowlist */ + token = optarg; + if (token.find_first_not_of (' ') != std::string::npos) { + if (!json_object_get (options,"load_allowlist")) { + json_object_set_new (options, "load_allowlist", json_string ("")); + } + json_object_set_new (options, "load_allowlist", + json_pack ("s++", + json_object_get (options,"load_allowlist"), + "cluster,", token.c_str ())); + } + break; + case 'S': /* --match-subsystems */ + json_object_set_new (options, "matcher_name", json_string (optarg)); + break; + case 'P': /* --match-policy */ + json_object_set_new (options, "matcher_policy", json_string (optarg)); + break; + case 'F': /* --match-format */ + json_object_set_new (options, "match_format", json_string (optarg)); + if (!known_match_format (optarg)) { + std::cerr << "[ERROR] unknown format for --match-format: "; + std::cerr << optarg << std::endl; + usage (1); + } + break; + case 'g': /* --graph-format */ + rc = string_to_graph_format (optarg, format); + if ( rc != 0) { + std::cerr << "[ERROR] unknown format for --graph-format: "; + std::cerr << optarg << std::endl; + usage (1); + } + graph_format_to_ext (format, token); + json_object_set_new (options, "o_fext", json_string (token.c_str ())); + break; + case 'o': /* --graph-output */ + json_object_set_new (options, "o_fname", json_string (optarg)); + break; + case 'p': /* --prune-filters */ + token = optarg; + if (token.find_first_not_of (' ') != std::string::npos) { + if (!json_object_get (options,"prune_filters")) { + json_object_set_new (options, "prune_filters", json_string (token.c_str ())); + } else { + json_object_set_new (options, "prune_filters", + json_pack ("s++", + json_object_get (options,"prune_filters"), + ",", token.c_str ())); + } + + } + break; + case 't': /* --test-output */ + json_object_set_new (options, "r_fname", json_string (optarg)); + break; + case 'r': /* --reserve-vtx-vec */ + // If atoi fails, it defaults to 0, which is fine for us + json_object_set_new (options, "match_format", json_integer (atoi (optarg))); + if ( (atoi (optarg) < 0) + || (atoi (optarg) > 2000000)) { + json_object_set_new (options, "match_format", json_integer (0)); + std::cerr + << "WARN: out of range specified for --reserve-vtx-vec: "; + std::cerr << optarg << std::endl; + } + break; + case 'e': /* --elapse-time */ + json_object_set_new (options, "elapse_time", json_true ()); + break; + case 'd': /* --disable-prompt */ + json_object_set_new (options, "disable_prompt", json_true ()); + break; + default: + usage (1); + break; + } + } + + if (optind != argc) + usage (1); +} + +void get_rgraph (std::string &rgraph, json_t* options) +{ + const char *load_file = json_string_value (json_object_get (options, "load_file")); + if (load_file == NULL) { + load_file = "conf/default"; + } + std::ifstream ifs (load_file); + rgraph = std::string( (std::istreambuf_iterator (ifs) ), + (std::istreambuf_iterator () ) ); + ifs.close(); +} + +static void control_loop (resource_query_t &ctx, json_t *params, + std::ostream &out) +{ + cmd_func_f *cmd = NULL; + while (1) { + char *line = json_object_get (params, "disable_prompt")? readline ("") + : readline ("resource-query> "); + if (line == NULL) + continue; + else if (*line) + add_history (line); + + std::vector tokens; + std::istringstream iss (line); + std::copy (std::istream_iterator (iss), + std::istream_iterator (), + back_inserter (tokens)); + free(line); + if (tokens.empty ()) + continue; + + std::string &cmd_str = tokens[0]; + if (!(cmd = find_cmd (cmd_str))) + continue; + if (cmd (ctx, tokens, params, out) != 0) + break; + } +} + +int main (int argc, char *argv[]) +{ + json_t *json_options = json_object (); + std::string rgraph; + resource_query_t *ctx = nullptr; + int match_out, info_out = 0; + std::string options; + + process_args (json_options, argc, argv); + get_rgraph (rgraph, json_options); + options = json_dumps (json_options, JSON_COMPACT); + + try { + ctx = new resource_query_t (rgraph, options); + } catch (std::bad_alloc &e) { + errno = ENOMEM; + std::cerr << "Memory error\n"; + return EXIT_FAILURE; + } catch (std::runtime_error &e) { + errno = EPROTO; + std::cerr << ": Runtime error: " + + std::string (e.what ()) + "\n"; + return EXIT_FAILURE; + } + + std::ofstream out_file; + + if (r_fname_set (json_options)) + { + out_file = open_fs (json_options); + } + + std::ostream &out = (r_fname_set (json_options))? out_file + : std::cout; + + control_loop (*ctx, json_options, out); + + return EXIT_SUCCESS; +} diff --git a/resource/utilities/rq2.hpp b/resource/utilities/rq2.hpp new file mode 100644 index 000000000..f22326121 --- /dev/null +++ b/resource/utilities/rq2.hpp @@ -0,0 +1,28 @@ +/*****************************************************************************\ + * Copyright 2022 Lawrence Livermore National Security, LLC + * (c.f. AUTHORS, NOTICE.LLNS, LICENSE) + * + * This file is part of the Flux resource manager framework. + * For details, see https://github.com/flux-framework. + * + * SPDX-License-Identifier: LGPL-3.0 +\*****************************************************************************/ + +#include +#include +#include +#include +#include "resource/reapi/bindings/c++/reapi_cli.hpp" +#include "resource/reapi/bindings/c++/reapi_cli_impl.hpp" + +using namespace Flux; +using namespace Flux::resource_model; +using namespace Flux::resource_model::detail; + +int match (resource_query_t &ctx, std::vector &args, json_t *params, + std::ostream &out); +int help (resource_query_t &ctx, std::vector &args, json_t *params, + std::ostream &out); +int quit (resource_query_t &ctx, std::vector &args, json_t *params, + std::ostream &out); + From 922b6dc011c6b5bbe8450c38f6bc20e900255b97 Mon Sep 17 00:00:00 2001 From: Zeke Morton Date: Wed, 11 Oct 2023 16:29:21 -0700 Subject: [PATCH 5/6] tests: add tests for rq2 Problem: rq2 needs tests to verify that it can be a drop in replacement for rq1 Add some simple tests for current functionality. Generate the expected files using rq1 --- t/CMakeLists.txt | 1 + t/data/resource/commands/rq2/cmds01.in | 6 +++ t/data/resource/commands/rq2/cmds02.in | 7 ++++ t/data/resource/expected/rq2/001.R.out | 44 +++++++++++++++++++++ t/data/resource/expected/rq2/002.R.out | 54 ++++++++++++++++++++++++++ t/t3036-rq2.t | 32 +++++++++++++++ 6 files changed, 144 insertions(+) create mode 100644 t/data/resource/commands/rq2/cmds01.in create mode 100644 t/data/resource/commands/rq2/cmds02.in create mode 100644 t/data/resource/expected/rq2/001.R.out create mode 100644 t/data/resource/expected/rq2/002.R.out create mode 100755 t/t3036-rq2.t diff --git a/t/CMakeLists.txt b/t/CMakeLists.txt index 6bbedd349..06096be9e 100644 --- a/t/CMakeLists.txt +++ b/t/CMakeLists.txt @@ -63,6 +63,7 @@ set(ALL_TESTS t3033-resource-nodex.t t3034-resource-pconstraints.t t3035-resource-remove.t + t3036-rq2.t t3300-system-dontblock.t t3301-system-latestart.t t4000-match-params.t diff --git a/t/data/resource/commands/rq2/cmds01.in b/t/data/resource/commands/rq2/cmds01.in new file mode 100644 index 000000000..f744123e0 --- /dev/null +++ b/t/data/resource/commands/rq2/cmds01.in @@ -0,0 +1,6 @@ +match allocate @TEST_SRCDIR@/data/resource/jobspecs/basics/test001.yaml +match allocate @TEST_SRCDIR@/data/resource/jobspecs/basics/test001.yaml +match allocate @TEST_SRCDIR@/data/resource/jobspecs/basics/test001.yaml +match allocate @TEST_SRCDIR@/data/resource/jobspecs/basics/test001.yaml +match allocate @TEST_SRCDIR@/data/resource/jobspecs/basics/test001.yaml +quit diff --git a/t/data/resource/commands/rq2/cmds02.in b/t/data/resource/commands/rq2/cmds02.in new file mode 100644 index 000000000..d27ba2797 --- /dev/null +++ b/t/data/resource/commands/rq2/cmds02.in @@ -0,0 +1,7 @@ +match allocate_orelse_reserve @TEST_SRCDIR@/data/resource/jobspecs/basics/test001.yaml +match allocate_orelse_reserve @TEST_SRCDIR@/data/resource/jobspecs/basics/test001.yaml +match allocate_orelse_reserve @TEST_SRCDIR@/data/resource/jobspecs/basics/test001.yaml +match allocate_orelse_reserve @TEST_SRCDIR@/data/resource/jobspecs/basics/test001.yaml +match allocate_orelse_reserve @TEST_SRCDIR@/data/resource/jobspecs/basics/test001.yaml +match allocate @TEST_SRCDIR@/data/resource/jobspecs/basics/test001.yaml +quit diff --git a/t/data/resource/expected/rq2/001.R.out b/t/data/resource/expected/rq2/001.R.out new file mode 100644 index 000000000..ace32b6a8 --- /dev/null +++ b/t/data/resource/expected/rq2/001.R.out @@ -0,0 +1,44 @@ + ---------------core35[1:x] + ------------socket1[1:x] + ---------node1[1:s] + ------rack0[1:s] + ---tiny0[1:s] +INFO: ============================= +INFO: JOBID=1 +INFO: RESOURCES=ALLOCATED +INFO: SCHEDULED AT=Now +INFO: ============================= + ---------------core35[1:x] + ------------socket1[1:x] + ---------node0[1:s] + ------rack0[1:s] + ---tiny0[1:s] +INFO: ============================= +INFO: JOBID=2 +INFO: RESOURCES=ALLOCATED +INFO: SCHEDULED AT=Now +INFO: ============================= + ---------------core17[1:x] + ------------socket0[1:x] + ---------node1[1:s] + ------rack0[1:s] + ---tiny0[1:s] +INFO: ============================= +INFO: JOBID=3 +INFO: RESOURCES=ALLOCATED +INFO: SCHEDULED AT=Now +INFO: ============================= + ---------------core17[1:x] + ------------socket0[1:x] + ---------node0[1:s] + ------rack0[1:s] + ---tiny0[1:s] +INFO: ============================= +INFO: JOBID=4 +INFO: RESOURCES=ALLOCATED +INFO: SCHEDULED AT=Now +INFO: ============================= +INFO: ============================= +INFO: No matching resources found +INFO: JOBID=5 +INFO: ============================= diff --git a/t/data/resource/expected/rq2/002.R.out b/t/data/resource/expected/rq2/002.R.out new file mode 100644 index 000000000..2646cfd1e --- /dev/null +++ b/t/data/resource/expected/rq2/002.R.out @@ -0,0 +1,54 @@ + ---------------core35[1:x] + ------------socket1[1:x] + ---------node1[1:s] + ------rack0[1:s] + ---tiny0[1:s] +INFO: ============================= +INFO: JOBID=1 +INFO: RESOURCES=ALLOCATED +INFO: SCHEDULED AT=Now +INFO: ============================= + ---------------core35[1:x] + ------------socket1[1:x] + ---------node0[1:s] + ------rack0[1:s] + ---tiny0[1:s] +INFO: ============================= +INFO: JOBID=2 +INFO: RESOURCES=ALLOCATED +INFO: SCHEDULED AT=Now +INFO: ============================= + ---------------core17[1:x] + ------------socket0[1:x] + ---------node1[1:s] + ------rack0[1:s] + ---tiny0[1:s] +INFO: ============================= +INFO: JOBID=3 +INFO: RESOURCES=ALLOCATED +INFO: SCHEDULED AT=Now +INFO: ============================= + ---------------core17[1:x] + ------------socket0[1:x] + ---------node0[1:s] + ------rack0[1:s] + ---tiny0[1:s] +INFO: ============================= +INFO: JOBID=4 +INFO: RESOURCES=ALLOCATED +INFO: SCHEDULED AT=Now +INFO: ============================= + ---------------core35[1:x] + ------------socket1[1:x] + ---------node1[1:s] + ------rack0[1:s] + ---tiny0[1:s] +INFO: ============================= +INFO: JOBID=5 +INFO: RESOURCES=RESERVED +INFO: SCHEDULED AT=3600 +INFO: ============================= +INFO: ============================= +INFO: No matching resources found +INFO: JOBID=6 +INFO: ============================= diff --git a/t/t3036-rq2.t b/t/t3036-rq2.t new file mode 100755 index 000000000..6db76035b --- /dev/null +++ b/t/t3036-rq2.t @@ -0,0 +1,32 @@ +#!/bin/sh + +test_description='Test resource graph remove subgraph' + +. $(dirname $0)/sharness.sh + +cmd_dir="${SHARNESS_TEST_SRCDIR}/data/resource/commands/rq2" +exp_dir="${SHARNESS_TEST_SRCDIR}/data/resource/expected/rq2" +jgf="${SHARNESS_TEST_SRCDIR}/data/resource/jgfs/tiny.json" +query="../../resource/utilities/rq2" + +cmds001="${cmd_dir}/cmds01.in" +test001_desc="match allocate test" +test_expect_success "${test001_desc}" ' + sed "s~@TEST_SRCDIR@~${SHARNESS_TEST_SRCDIR}~g" ${cmds001} > cmds001 && + ${query} -L ${jgf} -f jgf -t 001.R.out \ + < cmds001 && + test_cmp 001.R.out ${exp_dir}/001.R.out +' + +cmds002="${cmd_dir}/cmds02.in" +test002_desc="match allocate_orelse_reserve test" +test_expect_success "${test002_desc}" ' + sed "s~@TEST_SRCDIR@~${SHARNESS_TEST_SRCDIR}~g" ${cmds002} > cmds002 && + ${query} -L ${jgf} -f jgf -t 002.R.out \ + < cmds002 && + test_cmp 002.R.out ${exp_dir}/002.R.out +' + + + +test_done From e4f265d83f0436439f50556668c158d8cc6d3662 Mon Sep 17 00:00:00 2001 From: Zeke Morton Date: Fri, 13 Oct 2023 11:06:24 -0700 Subject: [PATCH 6/6] tests: update golang tests and output Problem: a recent fix to reapi changed the output of the golang bindings tests. This changed a value that was once static to a value that changes with every run. Use a sed command to remove this value from the output of the test. Edited tests to use orelse_reserve flag. --- resource/reapi/bindings/go/src/test/main.go | 18 +++++++++++++++--- t/data/resource/expected/golang/001.R.out | 14 ++++++++++++-- t/data/resource/expected/golang/002.R.out | 21 ++++++++++++++++----- t/t9001-golang-basic.t | 2 ++ 4 files changed, 45 insertions(+), 10 deletions(-) diff --git a/resource/reapi/bindings/go/src/test/main.go b/resource/reapi/bindings/go/src/test/main.go index 797984475..cdb5e6d5b 100644 --- a/resource/reapi/bindings/go/src/test/main.go +++ b/resource/reapi/bindings/go/src/test/main.go @@ -21,7 +21,7 @@ import ( func main() { jgfPtr := flag.String("jgf", "", "path to jgf") jobspecPtr := flag.String("jobspec", "", "path to jobspec") - reserve := flag.Bool("reserve", false, "or else reserve?") + reserve := false flag.Parse() jgf, err := os.ReadFile(*jgfPtr) @@ -44,13 +44,24 @@ func main() { } fmt.Printf("Jobspec:\n %s\n", jobspec) - reserved, allocated, at, overhead, jobid, err := cli.MatchAllocate(*reserve, string(jobspec)) + reserved, allocated, at, overhead, jobid, err := cli.MatchAllocate(reserve, string(jobspec)) if err != nil { fmt.Printf("Error in ReapiClient MatchAllocate: %v\n", err) return } printOutput(reserved, allocated, at, jobid, err) - reserved, allocated, at, overhead, jobid, err = cli.MatchAllocate(*reserve, string(jobspec)) + + reserve = true + reserved, allocated, at, overhead, jobid, err = cli.MatchAllocate(reserve, string(jobspec)) + fmt.Println("Errors so far: \n", cli.GetErrMsg()) + + if err != nil { + fmt.Printf("Error in ReapiClient MatchAllocate: %v\n", err) + return + } + printOutput(reserved, allocated, at, jobid, err) + + reserved, allocated, at, overhead, jobid, err = cli.MatchAllocate(reserve, string(jobspec)) fmt.Println("Errors so far: \n", cli.GetErrMsg()) if err != nil { @@ -58,6 +69,7 @@ func main() { return } printOutput(reserved, allocated, at, jobid, err) + err = cli.Cancel(1, false) if err != nil { fmt.Printf("Error in ReapiClient Cancel: %v\n", err) diff --git a/t/data/resource/expected/golang/001.R.out b/t/data/resource/expected/golang/001.R.out index 7a9f056cf..2ad689bae 100644 --- a/t/data/resource/expected/golang/001.R.out +++ b/t/data/resource/expected/golang/001.R.out @@ -47,8 +47,18 @@ jobid: 2 reserved: false allocated: {"graph": {"nodes": [{"id": "43", "metadata": {"type": "core", "basename": "core", "name": "core35", "id": 35, "uniq_id": 43, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket1/core35"}}}, {"id": "5", "metadata": {"type": "socket", "basename": "socket", "name": "socket1", "id": 1, "uniq_id": 5, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket1"}}}, {"id": "2", "metadata": {"type": "node", "basename": "node", "name": "node0", "id": 0, "uniq_id": 2, "rank": -1, "exclusive": false, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0"}}}, {"id": "1", "metadata": {"type": "rack", "basename": "rack", "name": "rack0", "id": 0, "uniq_id": 1, "rank": -1, "exclusive": false, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0"}}}, {"id": "0", "metadata": {"type": "cluster", "basename": "tiny", "name": "tiny0", "id": 0, "uniq_id": 0, "rank": -1, "exclusive": false, "unit": "", "size": 1, "paths": {"containment": "/tiny0"}}}], "edges": [{"source": "5", "target": "43", "metadata": {"name": {"containment": "contains"}}}, {"source": "2", "target": "5", "metadata": {"name": {"containment": "contains"}}}, {"source": "1", "target": "2", "metadata": {"name": {"containment": "contains"}}}, {"source": "0", "target": "1", "metadata": {"name": {"containment": "contains"}}}]}} +at: 0 +error: +Errors so far: + + + ----Match Allocate output--- +jobid: 3 +reserved: false +allocated: {"graph": {"nodes": [{"id": "61", "metadata": {"type": "core", "basename": "core", "name": "core17", "id": 17, "uniq_id": 61, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket0/core17"}}}, {"id": "6", "metadata": {"type": "socket", "basename": "socket", "name": "socket0", "id": 0, "uniq_id": 6, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket0"}}}, {"id": "3", "metadata": {"type": "node", "basename": "node", "name": "node1", "id": 1, "uniq_id": 3, "rank": -1, "exclusive": false, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1"}}}, {"id": "1", "metadata": {"type": "rack", "basename": "rack", "name": "rack0", "id": 0, "uniq_id": 1, "rank": -1, "exclusive": false, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0"}}}, {"id": "0", "metadata": {"type": "cluster", "basename": "tiny", "name": "tiny0", "id": 0, "uniq_id": 0, "rank": -1, "exclusive": false, "unit": "", "size": 1, "paths": {"containment": "/tiny0"}}}], "edges": [{"source": "6", "target": "61", "metadata": {"name": {"containment": "contains"}}}, {"source": "3", "target": "6", "metadata": {"name": {"containment": "contains"}}}, {"source": "1", "target": "3", "metadata": {"name": {"containment": "contains"}}}, {"source": "0", "target": "1", "metadata": {"name": {"containment": "contains"}}}]}} + at: 0 error: Cancel output: -Info output jobid 1: false, 0, 0.000000, CANCELED, -Info output jobid 2: false, 0, 0.000000, +Info output jobid 1: false, 0, CANCELED, +Info output jobid 2: false, 0, diff --git a/t/data/resource/expected/golang/002.R.out b/t/data/resource/expected/golang/002.R.out index 7917bce3d..757eb4a47 100644 --- a/t/data/resource/expected/golang/002.R.out +++ b/t/data/resource/expected/golang/002.R.out @@ -42,10 +42,21 @@ Errors so far: ----Match Allocate output--- jobid: 2 -reserved: false -allocated: -at: 0 +reserved: true +allocated: {"graph": {"nodes": [{"id": "21", "metadata": {"type": "core", "basename": "core", "name": "core13", "id": 13, "uniq_id": 21, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket0/core13"}}}, {"id": "22", "metadata": {"type": "core", "basename": "core", "name": "core14", "id": 14, "uniq_id": 22, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket0/core14"}}}, {"id": "23", "metadata": {"type": "core", "basename": "core", "name": "core15", "id": 15, "uniq_id": 23, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket0/core15"}}}, {"id": "24", "metadata": {"type": "core", "basename": "core", "name": "core16", "id": 16, "uniq_id": 24, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket0/core16"}}}, {"id": "25", "metadata": {"type": "core", "basename": "core", "name": "core17", "id": 17, "uniq_id": 25, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket0/core17"}}}, {"id": "80", "metadata": {"type": "gpu", "basename": "gpu", "name": "gpu0", "id": 0, "uniq_id": 80, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket0/gpu0"}}}, {"id": "85", "metadata": {"type": "memory", "basename": "memory", "name": "memory1", "id": 1, "uniq_id": 85, "rank": -1, "exclusive": true, "unit": "", "size": 2, "paths": {"containment": "/tiny0/rack0/node0/socket0/memory1"}}}, {"id": "86", "metadata": {"type": "memory", "basename": "memory", "name": "memory2", "id": 2, "uniq_id": 86, "rank": -1, "exclusive": true, "unit": "", "size": 2, "paths": {"containment": "/tiny0/rack0/node0/socket0/memory2"}}}, {"id": "87", "metadata": {"type": "memory", "basename": "memory", "name": "memory3", "id": 3, "uniq_id": 87, "rank": -1, "exclusive": true, "unit": "", "size": 2, "paths": {"containment": "/tiny0/rack0/node0/socket0/memory3"}}}, {"id": "4", "metadata": {"type": "socket", "basename": "socket", "name": "socket0", "id": 0, "uniq_id": 4, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket0"}}}, {"id": "39", "metadata": {"type": "core", "basename": "core", "name": "core31", "id": 31, "uniq_id": 39, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket1/core31"}}}, {"id": "40", "metadata": {"type": "core", "basename": "core", "name": "core32", "id": 32, "uniq_id": 40, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket1/core32"}}}, {"id": "41", "metadata": {"type": "core", "basename": "core", "name": "core33", "id": 33, "uniq_id": 41, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket1/core33"}}}, {"id": "42", "metadata": {"type": "core", "basename": "core", "name": "core34", "id": 34, "uniq_id": 42, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket1/core34"}}}, {"id": "43", "metadata": {"type": "core", "basename": "core", "name": "core35", "id": 35, "uniq_id": 43, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket1/core35"}}}, {"id": "81", "metadata": {"type": "gpu", "basename": "gpu", "name": "gpu1", "id": 1, "uniq_id": 81, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket1/gpu1"}}}, {"id": "89", "metadata": {"type": "memory", "basename": "memory", "name": "memory5", "id": 5, "uniq_id": 89, "rank": -1, "exclusive": true, "unit": "", "size": 2, "paths": {"containment": "/tiny0/rack0/node0/socket1/memory5"}}}, {"id": "90", "metadata": {"type": "memory", "basename": "memory", "name": "memory6", "id": 6, "uniq_id": 90, "rank": -1, "exclusive": true, "unit": "", "size": 2, "paths": {"containment": "/tiny0/rack0/node0/socket1/memory6"}}}, {"id": "91", "metadata": {"type": "memory", "basename": "memory", "name": "memory7", "id": 7, "uniq_id": 91, "rank": -1, "exclusive": true, "unit": "", "size": 2, "paths": {"containment": "/tiny0/rack0/node0/socket1/memory7"}}}, {"id": "5", "metadata": {"type": "socket", "basename": "socket", "name": "socket1", "id": 1, "uniq_id": 5, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket1"}}}, {"id": "2", "metadata": {"type": "node", "basename": "node", "name": "node0", "id": 0, "uniq_id": 2, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0"}}}, {"id": "57", "metadata": {"type": "core", "basename": "core", "name": "core13", "id": 13, "uniq_id": 57, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket0/core13"}}}, {"id": "58", "metadata": {"type": "core", "basename": "core", "name": "core14", "id": 14, "uniq_id": 58, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket0/core14"}}}, {"id": "59", "metadata": {"type": "core", "basename": "core", "name": "core15", "id": 15, "uniq_id": 59, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket0/core15"}}}, {"id": "60", "metadata": {"type": "core", "basename": "core", "name": "core16", "id": 16, "uniq_id": 60, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket0/core16"}}}, {"id": "61", "metadata": {"type": "core", "basename": "core", "name": "core17", "id": 17, "uniq_id": 61, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket0/core17"}}}, {"id": "82", "metadata": {"type": "gpu", "basename": "gpu", "name": "gpu0", "id": 0, "uniq_id": 82, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket0/gpu0"}}}, {"id": "93", "metadata": {"type": "memory", "basename": "memory", "name": "memory1", "id": 1, "uniq_id": 93, "rank": -1, "exclusive": true, "unit": "", "size": 2, "paths": {"containment": "/tiny0/rack0/node1/socket0/memory1"}}}, {"id": "94", "metadata": {"type": "memory", "basename": "memory", "name": "memory2", "id": 2, "uniq_id": 94, "rank": -1, "exclusive": true, "unit": "", "size": 2, "paths": {"containment": "/tiny0/rack0/node1/socket0/memory2"}}}, {"id": "95", "metadata": {"type": "memory", "basename": "memory", "name": "memory3", "id": 3, "uniq_id": 95, "rank": -1, "exclusive": true, "unit": "", "size": 2, "paths": {"containment": "/tiny0/rack0/node1/socket0/memory3"}}}, {"id": "6", "metadata": {"type": "socket", "basename": "socket", "name": "socket0", "id": 0, "uniq_id": 6, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket0"}}}, {"id": "75", "metadata": {"type": "core", "basename": "core", "name": "core31", "id": 31, "uniq_id": 75, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket1/core31"}}}, {"id": "76", "metadata": {"type": "core", "basename": "core", "name": "core32", "id": 32, "uniq_id": 76, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket1/core32"}}}, {"id": "77", "metadata": {"type": "core", "basename": "core", "name": "core33", "id": 33, "uniq_id": 77, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket1/core33"}}}, {"id": "78", "metadata": {"type": "core", "basename": "core", "name": "core34", "id": 34, "uniq_id": 78, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket1/core34"}}}, {"id": "79", "metadata": {"type": "core", "basename": "core", "name": "core35", "id": 35, "uniq_id": 79, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket1/core35"}}}, {"id": "83", "metadata": {"type": "gpu", "basename": "gpu", "name": "gpu1", "id": 1, "uniq_id": 83, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket1/gpu1"}}}, {"id": "97", "metadata": {"type": "memory", "basename": "memory", "name": "memory5", "id": 5, "uniq_id": 97, "rank": -1, "exclusive": true, "unit": "", "size": 2, "paths": {"containment": "/tiny0/rack0/node1/socket1/memory5"}}}, {"id": "98", "metadata": {"type": "memory", "basename": "memory", "name": "memory6", "id": 6, "uniq_id": 98, "rank": -1, "exclusive": true, "unit": "", "size": 2, "paths": {"containment": "/tiny0/rack0/node1/socket1/memory6"}}}, {"id": "99", "metadata": {"type": "memory", "basename": "memory", "name": "memory7", "id": 7, "uniq_id": 99, "rank": -1, "exclusive": true, "unit": "", "size": 2, "paths": {"containment": "/tiny0/rack0/node1/socket1/memory7"}}}, {"id": "7", "metadata": {"type": "socket", "basename": "socket", "name": "socket1", "id": 1, "uniq_id": 7, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket1"}}}, {"id": "3", "metadata": {"type": "node", "basename": "node", "name": "node1", "id": 1, "uniq_id": 3, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1"}}}, {"id": "1", "metadata": {"type": "rack", "basename": "rack", "name": "rack0", "id": 0, "uniq_id": 1, "rank": -1, "exclusive": false, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0"}}}, {"id": "0", "metadata": {"type": "cluster", "basename": "tiny", "name": "tiny0", "id": 0, "uniq_id": 0, "rank": -1, "exclusive": false, "unit": "", "size": 1, "paths": {"containment": "/tiny0"}}}], "edges": [{"source": "4", "target": "21", "metadata": {"name": {"containment": "contains"}}}, {"source": "4", "target": "22", "metadata": {"name": {"containment": "contains"}}}, {"source": "4", "target": "23", "metadata": {"name": {"containment": "contains"}}}, {"source": "4", "target": "24", "metadata": {"name": {"containment": "contains"}}}, {"source": "4", "target": "25", "metadata": {"name": {"containment": "contains"}}}, {"source": "4", "target": "80", "metadata": {"name": {"containment": "contains"}}}, {"source": "4", "target": "85", "metadata": {"name": {"containment": "contains"}}}, {"source": "4", "target": "86", "metadata": {"name": {"containment": "contains"}}}, {"source": "4", "target": "87", "metadata": {"name": {"containment": "contains"}}}, {"source": "2", "target": "4", "metadata": {"name": {"containment": "contains"}}}, {"source": "5", "target": "39", "metadata": {"name": {"containment": "contains"}}}, {"source": "5", "target": "40", "metadata": {"name": {"containment": "contains"}}}, {"source": "5", "target": "41", "metadata": {"name": {"containment": "contains"}}}, {"source": "5", "target": "42", "metadata": {"name": {"containment": "contains"}}}, {"source": "5", "target": "43", "metadata": {"name": {"containment": "contains"}}}, {"source": "5", "target": "81", "metadata": {"name": {"containment": "contains"}}}, {"source": "5", "target": "89", "metadata": {"name": {"containment": "contains"}}}, {"source": "5", "target": "90", "metadata": {"name": {"containment": "contains"}}}, {"source": "5", "target": "91", "metadata": {"name": {"containment": "contains"}}}, {"source": "2", "target": "5", "metadata": {"name": {"containment": "contains"}}}, {"source": "1", "target": "2", "metadata": {"name": {"containment": "contains"}}}, {"source": "6", "target": "57", "metadata": {"name": {"containment": "contains"}}}, {"source": "6", "target": "58", "metadata": {"name": {"containment": "contains"}}}, {"source": "6", "target": "59", "metadata": {"name": {"containment": "contains"}}}, {"source": "6", "target": "60", "metadata": {"name": {"containment": "contains"}}}, {"source": "6", "target": "61", "metadata": {"name": {"containment": "contains"}}}, {"source": "6", "target": "82", "metadata": {"name": {"containment": "contains"}}}, {"source": "6", "target": "93", "metadata": {"name": {"containment": "contains"}}}, {"source": "6", "target": "94", "metadata": {"name": {"containment": "contains"}}}, {"source": "6", "target": "95", "metadata": {"name": {"containment": "contains"}}}, {"source": "3", "target": "6", "metadata": {"name": {"containment": "contains"}}}, {"source": "7", "target": "75", "metadata": {"name": {"containment": "contains"}}}, {"source": "7", "target": "76", "metadata": {"name": {"containment": "contains"}}}, {"source": "7", "target": "77", "metadata": {"name": {"containment": "contains"}}}, {"source": "7", "target": "78", "metadata": {"name": {"containment": "contains"}}}, {"source": "7", "target": "79", "metadata": {"name": {"containment": "contains"}}}, {"source": "7", "target": "83", "metadata": {"name": {"containment": "contains"}}}, {"source": "7", "target": "97", "metadata": {"name": {"containment": "contains"}}}, {"source": "7", "target": "98", "metadata": {"name": {"containment": "contains"}}}, {"source": "7", "target": "99", "metadata": {"name": {"containment": "contains"}}}, {"source": "3", "target": "7", "metadata": {"name": {"containment": "contains"}}}, {"source": "1", "target": "3", "metadata": {"name": {"containment": "contains"}}}, {"source": "0", "target": "1", "metadata": {"name": {"containment": "contains"}}}]}} + +at: 3600 +error: +Errors so far: + + + ----Match Allocate output--- +jobid: 3 +reserved: true +allocated: {"graph": {"nodes": [{"id": "21", "metadata": {"type": "core", "basename": "core", "name": "core13", "id": 13, "uniq_id": 21, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket0/core13"}}}, {"id": "22", "metadata": {"type": "core", "basename": "core", "name": "core14", "id": 14, "uniq_id": 22, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket0/core14"}}}, {"id": "23", "metadata": {"type": "core", "basename": "core", "name": "core15", "id": 15, "uniq_id": 23, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket0/core15"}}}, {"id": "24", "metadata": {"type": "core", "basename": "core", "name": "core16", "id": 16, "uniq_id": 24, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket0/core16"}}}, {"id": "25", "metadata": {"type": "core", "basename": "core", "name": "core17", "id": 17, "uniq_id": 25, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket0/core17"}}}, {"id": "80", "metadata": {"type": "gpu", "basename": "gpu", "name": "gpu0", "id": 0, "uniq_id": 80, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket0/gpu0"}}}, {"id": "85", "metadata": {"type": "memory", "basename": "memory", "name": "memory1", "id": 1, "uniq_id": 85, "rank": -1, "exclusive": true, "unit": "", "size": 2, "paths": {"containment": "/tiny0/rack0/node0/socket0/memory1"}}}, {"id": "86", "metadata": {"type": "memory", "basename": "memory", "name": "memory2", "id": 2, "uniq_id": 86, "rank": -1, "exclusive": true, "unit": "", "size": 2, "paths": {"containment": "/tiny0/rack0/node0/socket0/memory2"}}}, {"id": "87", "metadata": {"type": "memory", "basename": "memory", "name": "memory3", "id": 3, "uniq_id": 87, "rank": -1, "exclusive": true, "unit": "", "size": 2, "paths": {"containment": "/tiny0/rack0/node0/socket0/memory3"}}}, {"id": "4", "metadata": {"type": "socket", "basename": "socket", "name": "socket0", "id": 0, "uniq_id": 4, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket0"}}}, {"id": "39", "metadata": {"type": "core", "basename": "core", "name": "core31", "id": 31, "uniq_id": 39, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket1/core31"}}}, {"id": "40", "metadata": {"type": "core", "basename": "core", "name": "core32", "id": 32, "uniq_id": 40, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket1/core32"}}}, {"id": "41", "metadata": {"type": "core", "basename": "core", "name": "core33", "id": 33, "uniq_id": 41, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket1/core33"}}}, {"id": "42", "metadata": {"type": "core", "basename": "core", "name": "core34", "id": 34, "uniq_id": 42, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket1/core34"}}}, {"id": "43", "metadata": {"type": "core", "basename": "core", "name": "core35", "id": 35, "uniq_id": 43, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket1/core35"}}}, {"id": "81", "metadata": {"type": "gpu", "basename": "gpu", "name": "gpu1", "id": 1, "uniq_id": 81, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket1/gpu1"}}}, {"id": "89", "metadata": {"type": "memory", "basename": "memory", "name": "memory5", "id": 5, "uniq_id": 89, "rank": -1, "exclusive": true, "unit": "", "size": 2, "paths": {"containment": "/tiny0/rack0/node0/socket1/memory5"}}}, {"id": "90", "metadata": {"type": "memory", "basename": "memory", "name": "memory6", "id": 6, "uniq_id": 90, "rank": -1, "exclusive": true, "unit": "", "size": 2, "paths": {"containment": "/tiny0/rack0/node0/socket1/memory6"}}}, {"id": "91", "metadata": {"type": "memory", "basename": "memory", "name": "memory7", "id": 7, "uniq_id": 91, "rank": -1, "exclusive": true, "unit": "", "size": 2, "paths": {"containment": "/tiny0/rack0/node0/socket1/memory7"}}}, {"id": "5", "metadata": {"type": "socket", "basename": "socket", "name": "socket1", "id": 1, "uniq_id": 5, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0/socket1"}}}, {"id": "2", "metadata": {"type": "node", "basename": "node", "name": "node0", "id": 0, "uniq_id": 2, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node0"}}}, {"id": "57", "metadata": {"type": "core", "basename": "core", "name": "core13", "id": 13, "uniq_id": 57, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket0/core13"}}}, {"id": "58", "metadata": {"type": "core", "basename": "core", "name": "core14", "id": 14, "uniq_id": 58, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket0/core14"}}}, {"id": "59", "metadata": {"type": "core", "basename": "core", "name": "core15", "id": 15, "uniq_id": 59, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket0/core15"}}}, {"id": "60", "metadata": {"type": "core", "basename": "core", "name": "core16", "id": 16, "uniq_id": 60, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket0/core16"}}}, {"id": "61", "metadata": {"type": "core", "basename": "core", "name": "core17", "id": 17, "uniq_id": 61, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket0/core17"}}}, {"id": "82", "metadata": {"type": "gpu", "basename": "gpu", "name": "gpu0", "id": 0, "uniq_id": 82, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket0/gpu0"}}}, {"id": "93", "metadata": {"type": "memory", "basename": "memory", "name": "memory1", "id": 1, "uniq_id": 93, "rank": -1, "exclusive": true, "unit": "", "size": 2, "paths": {"containment": "/tiny0/rack0/node1/socket0/memory1"}}}, {"id": "94", "metadata": {"type": "memory", "basename": "memory", "name": "memory2", "id": 2, "uniq_id": 94, "rank": -1, "exclusive": true, "unit": "", "size": 2, "paths": {"containment": "/tiny0/rack0/node1/socket0/memory2"}}}, {"id": "95", "metadata": {"type": "memory", "basename": "memory", "name": "memory3", "id": 3, "uniq_id": 95, "rank": -1, "exclusive": true, "unit": "", "size": 2, "paths": {"containment": "/tiny0/rack0/node1/socket0/memory3"}}}, {"id": "6", "metadata": {"type": "socket", "basename": "socket", "name": "socket0", "id": 0, "uniq_id": 6, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket0"}}}, {"id": "75", "metadata": {"type": "core", "basename": "core", "name": "core31", "id": 31, "uniq_id": 75, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket1/core31"}}}, {"id": "76", "metadata": {"type": "core", "basename": "core", "name": "core32", "id": 32, "uniq_id": 76, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket1/core32"}}}, {"id": "77", "metadata": {"type": "core", "basename": "core", "name": "core33", "id": 33, "uniq_id": 77, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket1/core33"}}}, {"id": "78", "metadata": {"type": "core", "basename": "core", "name": "core34", "id": 34, "uniq_id": 78, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket1/core34"}}}, {"id": "79", "metadata": {"type": "core", "basename": "core", "name": "core35", "id": 35, "uniq_id": 79, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket1/core35"}}}, {"id": "83", "metadata": {"type": "gpu", "basename": "gpu", "name": "gpu1", "id": 1, "uniq_id": 83, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket1/gpu1"}}}, {"id": "97", "metadata": {"type": "memory", "basename": "memory", "name": "memory5", "id": 5, "uniq_id": 97, "rank": -1, "exclusive": true, "unit": "", "size": 2, "paths": {"containment": "/tiny0/rack0/node1/socket1/memory5"}}}, {"id": "98", "metadata": {"type": "memory", "basename": "memory", "name": "memory6", "id": 6, "uniq_id": 98, "rank": -1, "exclusive": true, "unit": "", "size": 2, "paths": {"containment": "/tiny0/rack0/node1/socket1/memory6"}}}, {"id": "99", "metadata": {"type": "memory", "basename": "memory", "name": "memory7", "id": 7, "uniq_id": 99, "rank": -1, "exclusive": true, "unit": "", "size": 2, "paths": {"containment": "/tiny0/rack0/node1/socket1/memory7"}}}, {"id": "7", "metadata": {"type": "socket", "basename": "socket", "name": "socket1", "id": 1, "uniq_id": 7, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1/socket1"}}}, {"id": "3", "metadata": {"type": "node", "basename": "node", "name": "node1", "id": 1, "uniq_id": 3, "rank": -1, "exclusive": true, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0/node1"}}}, {"id": "1", "metadata": {"type": "rack", "basename": "rack", "name": "rack0", "id": 0, "uniq_id": 1, "rank": -1, "exclusive": false, "unit": "", "size": 1, "paths": {"containment": "/tiny0/rack0"}}}, {"id": "0", "metadata": {"type": "cluster", "basename": "tiny", "name": "tiny0", "id": 0, "uniq_id": 0, "rank": -1, "exclusive": false, "unit": "", "size": 1, "paths": {"containment": "/tiny0"}}}], "edges": [{"source": "4", "target": "21", "metadata": {"name": {"containment": "contains"}}}, {"source": "4", "target": "22", "metadata": {"name": {"containment": "contains"}}}, {"source": "4", "target": "23", "metadata": {"name": {"containment": "contains"}}}, {"source": "4", "target": "24", "metadata": {"name": {"containment": "contains"}}}, {"source": "4", "target": "25", "metadata": {"name": {"containment": "contains"}}}, {"source": "4", "target": "80", "metadata": {"name": {"containment": "contains"}}}, {"source": "4", "target": "85", "metadata": {"name": {"containment": "contains"}}}, {"source": "4", "target": "86", "metadata": {"name": {"containment": "contains"}}}, {"source": "4", "target": "87", "metadata": {"name": {"containment": "contains"}}}, {"source": "2", "target": "4", "metadata": {"name": {"containment": "contains"}}}, {"source": "5", "target": "39", "metadata": {"name": {"containment": "contains"}}}, {"source": "5", "target": "40", "metadata": {"name": {"containment": "contains"}}}, {"source": "5", "target": "41", "metadata": {"name": {"containment": "contains"}}}, {"source": "5", "target": "42", "metadata": {"name": {"containment": "contains"}}}, {"source": "5", "target": "43", "metadata": {"name": {"containment": "contains"}}}, {"source": "5", "target": "81", "metadata": {"name": {"containment": "contains"}}}, {"source": "5", "target": "89", "metadata": {"name": {"containment": "contains"}}}, {"source": "5", "target": "90", "metadata": {"name": {"containment": "contains"}}}, {"source": "5", "target": "91", "metadata": {"name": {"containment": "contains"}}}, {"source": "2", "target": "5", "metadata": {"name": {"containment": "contains"}}}, {"source": "1", "target": "2", "metadata": {"name": {"containment": "contains"}}}, {"source": "6", "target": "57", "metadata": {"name": {"containment": "contains"}}}, {"source": "6", "target": "58", "metadata": {"name": {"containment": "contains"}}}, {"source": "6", "target": "59", "metadata": {"name": {"containment": "contains"}}}, {"source": "6", "target": "60", "metadata": {"name": {"containment": "contains"}}}, {"source": "6", "target": "61", "metadata": {"name": {"containment": "contains"}}}, {"source": "6", "target": "82", "metadata": {"name": {"containment": "contains"}}}, {"source": "6", "target": "93", "metadata": {"name": {"containment": "contains"}}}, {"source": "6", "target": "94", "metadata": {"name": {"containment": "contains"}}}, {"source": "6", "target": "95", "metadata": {"name": {"containment": "contains"}}}, {"source": "3", "target": "6", "metadata": {"name": {"containment": "contains"}}}, {"source": "7", "target": "75", "metadata": {"name": {"containment": "contains"}}}, {"source": "7", "target": "76", "metadata": {"name": {"containment": "contains"}}}, {"source": "7", "target": "77", "metadata": {"name": {"containment": "contains"}}}, {"source": "7", "target": "78", "metadata": {"name": {"containment": "contains"}}}, {"source": "7", "target": "79", "metadata": {"name": {"containment": "contains"}}}, {"source": "7", "target": "83", "metadata": {"name": {"containment": "contains"}}}, {"source": "7", "target": "97", "metadata": {"name": {"containment": "contains"}}}, {"source": "7", "target": "98", "metadata": {"name": {"containment": "contains"}}}, {"source": "7", "target": "99", "metadata": {"name": {"containment": "contains"}}}, {"source": "3", "target": "7", "metadata": {"name": {"containment": "contains"}}}, {"source": "1", "target": "3", "metadata": {"name": {"containment": "contains"}}}, {"source": "0", "target": "1", "metadata": {"name": {"containment": "contains"}}}]}} + +at: 7200 error: Cancel output: -Info output jobid 1: false, 0, 0.000000, CANCELED, -Info output jobid 2: false, 0, 0.000000, +Info output jobid 1: false, 0, CANCELED, +Info output jobid 2: true, 3600, diff --git a/t/t9001-golang-basic.t b/t/t9001-golang-basic.t index 7695f646f..27a497d03 100755 --- a/t/t9001-golang-basic.t +++ b/t/t9001-golang-basic.t @@ -23,12 +23,14 @@ main="../../resource/reapi/bindings/go/src/test/main" test001_desc="match allocate 1 slot: 1 socket: 1 core (pol=default)" test_expect_success "${test001_desc}" ' ${main} --jgf=${jgf} --jobspec=${jobspec1} > 001.R.out && + sed -i -E "s/, 0\.[0-9]+//g" 001.R.out && test_cmp 001.R.out ${exp_dir}/001.R.out ' test002_desc="match allocate 2 slots: 2 sockets: 5 cores 1 gpu 6 memory" test_expect_success "${test002_desc}" ' ${main} --jgf=${jgf} --jobspec=${jobspec2} > 002.R.out && + sed -i -E "s/, 0\.[0-9]+//g" 002.R.out && test_cmp 002.R.out ${exp_dir}/002.R.out '