diff --git a/resource/modules/resource_match.cpp b/resource/modules/resource_match.cpp index 358ed7e09..9edda2d88 100644 --- a/resource/modules/resource_match.cpp +++ b/resource/modules/resource_match.cpp @@ -237,6 +237,11 @@ static void set_property_request_cb (flux_t *h, const flux_msg_t *msg, void *arg); +static void remove_property_request_cb (flux_t *h, + flux_msg_handler_t *w, + const flux_msg_t *msg, + void *arg); + static void get_property_request_cb (flux_t *h, flux_msg_handler_t *w, const flux_msg_t *msg, @@ -278,6 +283,10 @@ static const struct flux_msg_handler_spec htab[] = {FLUX_MSGTYPE_REQUEST, "sched-fluxion-resource.stats-clear", stat_clear_cb, FLUX_ROLE_USER}, {FLUX_MSGTYPE_REQUEST, "sched-fluxion-resource.next_jobid", next_jobid_request_cb, 0}, {FLUX_MSGTYPE_REQUEST, "sched-fluxion-resource.set_property", set_property_request_cb, 0}, + {FLUX_MSGTYPE_REQUEST, + "sched-fluxion-resource.remove_property", + remove_property_request_cb, + 0}, {FLUX_MSGTYPE_REQUEST, "sched-fluxion-resource.get_property", get_property_request_cb, 0}, {FLUX_MSGTYPE_REQUEST, "sched-fluxion-resource.notify", notify_request_cb, 0}, {FLUX_MSGTYPE_REQUEST, "sched-fluxion-resource.disconnect", disconnect_request_cb, 0}, @@ -2529,6 +2538,49 @@ static void set_property_request_cb (flux_t *h, flux_log_error (h, "%s: flux_respond_error", __FUNCTION__); } +static void remove_property_request_cb (flux_t *h, + flux_msg_handler_t *w, + const flux_msg_t *msg, + void *arg) +{ + const char *rp = NULL, *kv = NULL; + std::string resource_path = "", property_key = ""; + std::shared_ptr ctx = getctx ((flux_t *)arg); + std::map>::const_iterator it; + std::pair::iterator, bool> ret; + vtx_t v; + + if (flux_request_unpack (msg, NULL, "{s:s s:s}", "resource_path", &rp, "key", &kv) < 0) + goto error; + + resource_path = rp; + property_key = kv; + + it = ctx->db->metadata.by_path.find (resource_path); + + if (it == ctx->db->metadata.by_path.end ()) { + errno = ENOENT; + flux_log_error (h, + "%s: Couldn't find %s in resource graph.", + __FUNCTION__, + resource_path.c_str ()); + goto error; + } + + for (auto &v : it->second) { + ctx->db->resource_graph[v].properties.erase (property_key); + } + + if (flux_respond_pack (h, msg, "{}") < 0) + flux_log_error (h, "%s", __FUNCTION__); + + return; + +error: + if (flux_respond_error (h, msg, errno, NULL) < 0) + flux_log_error (h, "%s: flux_respond_error", __FUNCTION__); +} + static void get_property_request_cb (flux_t *h, flux_msg_handler_t *w, const flux_msg_t *msg, diff --git a/src/cmd/flux-ion-resource.py b/src/cmd/flux-ion-resource.py index e184e079b..46080a032 100755 --- a/src/cmd/flux-ion-resource.py +++ b/src/cmd/flux-ion-resource.py @@ -86,6 +86,10 @@ def rpc_set_property(self, sp_resource_path, sp_keyval): payload = {"sp_resource_path": sp_resource_path, "sp_keyval": sp_keyval} return self.handle.rpc("sched-fluxion-resource.set_property", payload).get() + def rpc_remove_property(self, rp_resource_path, rp_key): + payload = {"resource_path": rp_resource_path, "key": rp_key} + return self.handle.rpc("sched-fluxion-resource.remove_property", payload).get() + def rpc_get_property(self, gp_resource_path, gp_key): payload = {"gp_resource_path": gp_resource_path, "gp_key": gp_key} return self.handle.rpc("sched-fluxion-resource.get_property", payload).get() @@ -334,6 +338,14 @@ def set_property_action(args): rmod.rpc_set_property(sp_resource_path, sp_keyval) +def remove_property_action(args): + """ + Action for remove-property sub-command + """ + rmod = ResourceModuleInterface() + rmod.rpc_remove_property(args.rp_resource_path, args.rp_key) + + def get_property_action(args): """ Action for get-property sub-command @@ -537,6 +549,7 @@ def mkparser(name, help_desc): parser_sp = mkparser( "set-property", "Set property-key=value for specified resource." ) + parser_rp = mkparser("remove-property", "Remove property for specified resource.") parser_gp = mkparser( "get-property", "Get value for specified resource and property-key." ) @@ -587,6 +600,22 @@ def mkparser(name, help_desc): ) parser_sp.set_defaults(func=set_property_action) + # Positional arguments for remove-property sub-command + # + parser_rp.add_argument( + "rp_resource_path", + metavar="ResourcePath", + type=str, + help="remove-property resource_path property-key=val", + ) + parser_rp.add_argument( + "rp_key", + metavar="PropertyKey", + type=str, + help="remove-property resource_path property-key", + ) + parser_rp.set_defaults(func=remove_property_action) + # Positional argument for get-property sub-command # parser_gp.add_argument( diff --git a/t/t4006-properties.t b/t/t4006-properties.t index c0e023377..e1d7eccb6 100755 --- a/t/t4006-properties.t +++ b/t/t4006-properties.t @@ -29,14 +29,16 @@ load-file=${grug} load-format=grug \ prune-filters=ALL:core subsystems=containment policy=high ' -test_expect_success 'set/get property basic test works' " +test_expect_success 'set/get/remove property basic test works' " flux ion-resource set-property /tiny0/rack0/node0 class=one && flux ion-resource get-property /tiny0/rack0/node0 class > sp.0 && echo \"class = ['one']\" > expected && - test_cmp expected sp.0 + test_cmp expected sp.0 && + flux ion-resource remove-property /tiny0/rack0/node0 class && + test_expect_code 3 flux ion-resource get-property /tiny0/rack0/node0 class " -test_expect_success 'set/get property multiple resources works' " +test_expect_success 'set/get/remove property multiple resources works' " flux ion-resource set-property /tiny0/rack0/node0 nodeprop=1 && flux ion-resource set-property /tiny0/rack0/node0/socket1 sockprop=abc && flux ion-resource set-property /tiny0/rack0/node1/socket0/core17 coreprop=z && @@ -48,10 +50,16 @@ test_expect_success 'set/get property multiple resources works' " sockprop = ['abc'] coreprop = ['z'] EOF - test_cmp expected sp.1 + test_cmp expected sp.1 && + flux ion-resource remove-property /tiny0/rack0/node0 nodeprop && + flux ion-resource remove-property /tiny0/rack0/node0/socket1 sockprop && + flux ion-resource remove-property /tiny0/rack0/node1/socket0/core17 coreprop && + test_expect_code 3 flux ion-resource get-property /tiny0/rack0/node0 nodeprop && + test_expect_code 3 flux ion-resource get-property /tiny0/rack0/node0/socket1 sockprop && + test_expect_code 3 flux ion-resource get-property /tiny0/rack0/node1/socket0/core17 coreprop " -test_expect_success 'set/get property multiple properties works' " +test_expect_success 'set/get/remove property multiple properties works' " flux ion-resource set-property /tiny0/rack0/node0 prop1=a && flux ion-resource set-property /tiny0/rack0/node0 prop2=foo && flux ion-resource set-property /tiny0/rack0/node0 prop3=123 && @@ -69,15 +77,31 @@ test_expect_success 'set/get property multiple properties works' " prop4 = ['bar'] prop5 = ['baz'] EOF - test_cmp expected sp.2 + test_cmp expected sp.2 && + flux ion-resource remove-property /tiny0/rack0/node0 prop1 && + test_expect_code 3 flux ion-resource get-property /tiny0/rack0/node0 prop1 && + flux ion-resource get-property /tiny0/rack0/node0 prop2 | grep foo && + flux ion-resource remove-property /tiny0/rack0/node0 prop2 && + test_expect_code 3 flux ion-resource get-property /tiny0/rack0/node0 prop2 && + flux ion-resource get-property /tiny0/rack0/node0 prop3 | grep 123 && + flux ion-resource remove-property /tiny0/rack0/node0 prop3 && + test_expect_code 3 flux ion-resource get-property /tiny0/rack0/node0 prop3 && + flux ion-resource get-property /tiny0/rack0/node0 prop4 | grep bar && + flux ion-resource get-property /tiny0/rack0/node0 prop5 | grep baz && + flux ion-resource remove-property /tiny0/rack0/node0 prop4 && + test_expect_code 3 flux ion-resource get-property /tiny0/rack0/node0 prop4 && + flux ion-resource remove-property /tiny0/rack0/node0 prop5 && + test_expect_code 3 flux ion-resource get-property /tiny0/rack0/node0 prop5 " test_expect_success 'test with no path works' ' - test_expect_code 3 flux ion-resource set-property /dont/exist random=1 + test_expect_code 3 flux ion-resource set-property /dont/exist random=1 && + test_expect_code 3 flux ion-resource remove-property /dont/exist random=1 ' test_expect_success 'test with no property works' ' - test_expect_code 3 flux ion-resource get-property /tiny0/rack0/node0 dontexist + test_expect_code 3 flux ion-resource get-property /tiny0/rack0/node0 dontexist && + flux ion-resource remove-property /tiny0/rack0/node0 dontexist ' test_expect_success 'test with malformed inputs works' '