fixeria has submitted this change. ( https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/41105?usp=email )
Change subject: [REST] Implement {Enb,Erab}Delete ......................................................................
[REST] Implement {Enb,Erab}Delete
Change-Id: I3576814f44d87551fdac6236ddbec6215ba07455 Related: SYS#7066 --- M contrib/openapi.yaml M contrib/osmo-s1gw-cli.py M priv/openapi.json M src/rest_server.erl 4 files changed, 121 insertions(+), 1 deletion(-)
Approvals: laforge: Looks good to me, but someone else must approve fixeria: Looks good to me, approved Jenkins Builder: Verified osmith: Looks good to me, but someone else must approve
diff --git a/contrib/openapi.yaml b/contrib/openapi.yaml index adf3e58..e7934b2 100644 --- a/contrib/openapi.yaml +++ b/contrib/openapi.yaml @@ -91,6 +91,16 @@ $ref: '#/components/schemas/EnbItem' '404': description: Unsuccessful outcome (eNB not found) + delete: + summary: Force disconnect an eNB + operationId: EnbDelete + parameters: + - $ref: '#/components/parameters/EnbId' + responses: + '200': + description: Successful outcome (eNB disconnected) + '404': + description: Unsuccessful outcome (eNB not found)
/enb/{EnbId}/erab-list: get: @@ -135,6 +145,16 @@ $ref: '#/components/schemas/ErabItem' '404': description: Unsuccessful outcome (E-RAB not found) + delete: + summary: Terminate an E-RAB FSM process + operationId: ErabDelete + parameters: + - $ref: '#/components/parameters/ErabId' + responses: + '200': + description: Successful outcome (E-RAB FSM terminated) + '404': + description: Unsuccessful outcome (E-RAB not found)
components: responses: diff --git a/contrib/osmo-s1gw-cli.py b/contrib/osmo-s1gw-cli.py index 99b62da..ac4b1c6 100755 --- a/contrib/osmo-s1gw-cli.py +++ b/contrib/osmo-s1gw-cli.py @@ -112,6 +112,11 @@ with self.send_get_req(f'enb/{enb_id}') as f: return json.load(f)
+ def enb_delete(self, enb_id: str) -> int: + ''' EnbDelete :: Force disconnect an eNB ''' + with self.send_delete_req(f'enb/{enb_id}') as f: + return f.status + def enb_erab_list(self, enb_id: str) -> RESTResponse: ''' EnbErabList :: Get E-RAB list for a specific eNB ''' with self.send_get_req(f'enb/{enb_id}/erab-list') as f: @@ -127,6 +132,11 @@ with self.send_get_req(f'erab/pid:{pid}') as f: return json.load(f)
+ def erab_delete(self, pid: str) -> int: + ''' ErabDelete :: Terminate an E-RAB FSM process ''' + with self.send_delete_req(f'erab/pid:{pid}') as f: + return f.status +
class OsmoS1GWCli(cmd2.Cmd): DESC = 'Interactive CLI for OsmoS1GW' @@ -299,6 +309,13 @@ data = self.iface.enb_info(enb_id) self.enb_info_print(data)
+ @cmd2.with_argparser(enb_info_parser) + @cmd2.with_category(CAT_ENB) + def do_enb_delete(self, opts) -> None: + ''' Force disconnect an eNB ''' + enb_id = self.gen_enb_id(opts) + self.iface.enb_delete(enb_id) + @staticmethod def erab_list_item(item: dict) -> dict: ''' Generate a table row for the given E-RAB (brief) ''' @@ -374,6 +391,12 @@ data = self.iface.erab_info(opts.pid) self.erab_info_print(data)
+ @cmd2.with_argparser(erab_info_parser) + @cmd2.with_category(CAT_ERAB) + def do_erab_delete(self, opts) -> None: + ''' Terminate an E-RAB FSM process ''' + self.iface.erab_delete(opts.pid) +
ap = argparse.ArgumentParser(prog='osmo-s1gw-cli', description=OsmoS1GWCli.DESC)
diff --git a/priv/openapi.json b/priv/openapi.json index bfe82a3..94c0287 100644 --- a/priv/openapi.json +++ b/priv/openapi.json @@ -139,6 +139,23 @@ "description": "Unsuccessful outcome (eNB not found)" } } + }, + "delete": { + "summary": "Force disconnect an eNB", + "operationId": "EnbDelete", + "parameters": [ + { + "$ref": "#/components/parameters/EnbId" + } + ], + "responses": { + "200": { + "description": "Successful outcome (eNB disconnected)" + }, + "404": { + "description": "Unsuccessful outcome (eNB not found)" + } + } } }, "/enb/{EnbId}/erab-list": { @@ -209,6 +226,23 @@ "description": "Unsuccessful outcome (E-RAB not found)" } } + }, + "delete": { + "summary": "Terminate an E-RAB FSM process", + "operationId": "ErabDelete", + "parameters": [ + { + "$ref": "#/components/parameters/ErabId" + } + ], + "responses": { + "200": { + "description": "Successful outcome (E-RAB FSM terminated)" + }, + "404": { + "description": "Unsuccessful outcome (E-RAB not found)" + } + } } } }, diff --git a/src/rest_server.erl b/src/rest_server.erl index e1333c0..2ea51f6 100644 --- a/src/rest_server.erl +++ b/src/rest_server.erl @@ -39,9 +39,11 @@ pfcp_heartbeat/1, enb_list/1, enb_info/1, + enb_delete/1, enb_erab_list/1, erab_list/1, - erab_info/1 + erab_info/1, + erab_delete/1 ]).
-include_lib("kernel/include/logger.hrl"). @@ -108,6 +110,20 @@ end.
+%% EnbDelete :: Force disconnect an eNB +enb_delete(#{path_parameters := PP}) -> + [{<< "EnbId" >>, << ID/bytes >>}] = PP, + case fetch_enb_info(ID) of + [EnbInfo | _] -> + Pid = maps:get(pid, EnbInfo), + shutdown(sctp_proxy, Pid); + [] -> + {404, [], undefined}; + error -> + {500, [], undefined} + end. + + %% EnbErabList :: Get E-RAB list for a specific eNB enb_erab_list(#{path_parameters := PP}) -> [{<< "EnbId" >>, << ID/bytes >>}] = PP, @@ -140,6 +156,19 @@ end.
+%% ErabDelete :: Terminate an E-RAB FSM process +erab_delete(#{path_parameters := PP}) -> + [{<< "ErabId" >>, << ID/bytes >>}] = PP, + case ID of + << "pid:", Val/bytes >> -> + Pid = parse_pid(Val), + shutdown(erab_fsm, Pid); + _ -> + ?LOG_ERROR("Unhandled E-RAB ID ~p", [ID]), + {400, [], undefined} + end. + + %% ------------------------------------------------------------------ %% private API %% ------------------------------------------------------------------ @@ -337,6 +366,20 @@ list_to_pid("<" ++ Data ++ ">").
+-spec shutdown(module(), pid()) -> erf:response(). +shutdown(Module, Pid) -> + ?LOG_NOTICE("Shutting down ~p process (pid ~p)", [Module, Pid]), + try Module:shutdown(Pid) of + ok -> {200, [], undefined} + catch + exit:noproc -> {404, [], undefined}; + exit:{noproc, _} -> {404, [], undefined}; + Exception:Type -> + ?LOG_ERROR("Caught an exception: ~p:~p", [Exception, Type]), + {500, [], undefined} + end. + + %% Convert the given response map to a format acceptable by the erf -spec rsp_map(map()) -> map(). rsp_map(M) ->