fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/42429?usp=email )
Change subject: [REST] Implement eNB/MME selection by addr-port ......................................................................
[REST] Implement eNB/MME selection by addr-port
Change-Id: If02c8de1e1b7214bba868eee35233a79d0704dc5 Related: SYS#7066 --- M contrib/osmo-s1gw-cli.py M doc/manuals/chapters/cli.adoc M src/rest_server.erl 3 files changed, 94 insertions(+), 25 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/erlang/osmo-s1gw refs/changes/29/42429/1
diff --git a/contrib/osmo-s1gw-cli.py b/contrib/osmo-s1gw-cli.py index 5c37bdc..50b545d 100755 --- a/contrib/osmo-s1gw-cli.py +++ b/contrib/osmo-s1gw-cli.py @@ -117,14 +117,14 @@ with self.send_post_req('mme-list', mme_info) as f: return f.status
- def mme_info(self, name: str) -> RESTResponse: + def mme_info(self, mme_id: str) -> RESTResponse: ''' MmeInfo :: Get information about a specific MME ''' - with self.send_get_req(f'mme/name:{name}') as f: + with self.send_get_req(f'mme/{mme_id}') as f: return json.load(f)
- def mme_delete(self, name: str) -> int: - ''' MmeInfo :: Get information about a specific MME ''' - with self.send_delete_req(f'mme/name:{name}') as f: + def mme_delete(self, mme_id: str) -> int: + ''' MmeDelete :: Delete an MME from the pool ''' + with self.send_delete_req(f'mme/{mme_id}') as f: return f.status
def enb_list(self) -> RESTResponse: @@ -349,6 +349,17 @@ self.iface.mme_add(mme_info)
@staticmethod + def gen_mme_id(opts) -> str: + ''' Generate the MmeId parameter value (for URL) ''' + if opts.name is not None: + return f'name:{opts.name}' + elif opts.addr is not None: + return f'addr:{opts.addr}-36412' + elif opts.addr_port is not None: + return f'addr:{opts.addr_port}' + raise ValueError # shall not happen + + @staticmethod def add_mme_id_group(parser): ''' Add argparse group for the MmeId parameter ''' mme_id_group = parser.add_argument_group('MME ID') @@ -356,7 +367,12 @@ mme_id_group.add_argument('-N', '--name', type=str, help='MME name (example: mme0)') - # TODO: address/port + mme_id_group.add_argument('-a', '--addr', + type=str, metavar='ADDR', + help='MME address (example: 192.168.1.1)') + mme_id_group.add_argument('-ap', '--addr-port', + type=str, metavar='ADDR-PORT', + help='MME address/port (example: 192.168.1.1-36412)') return mme_id_group
mme_info_parser = cmd2.Cmd2ArgumentParser() @@ -366,14 +382,14 @@ @cmd2.with_category(CAT_MME) def do_mme_info(self, opts) -> None: ''' Get information about a specific MME ''' - data = self.iface.mme_info(opts.name) + data = self.iface.mme_info(self.gen_mme_id(opts)) self.mme_info_print(data)
@cmd2.with_argparser(mme_info_parser) @cmd2.with_category(CAT_MME) def do_mme_delete(self, opts) -> None: ''' Delete an MME from the pool ''' - self.iface.mme_delete(opts.name) + self.iface.mme_delete(self.gen_mme_id(opts))
@staticmethod def enb_list_item(item: dict) -> dict: @@ -429,6 +445,8 @@ return f'enb-sctp-aid:{opts.enb_sctp_aid}' elif opts.mme_sctp_aid is not None: return f'mme-sctp-aid:{opts.mme_sctp_aid}' + elif opts.enb_conn is not None: + return f'enb-conn:{opts.enb_conn}' raise ValueError # shall not happen
@staticmethod @@ -451,6 +469,9 @@ enb_id_group.add_argument('--mme-sctp-aid', type=int, metavar='AID', help='MME association identifier (example: 42)') + enb_id_group.add_argument('--enb-conn', + type=str, metavar='ADDR-PORT', + help='eNB connection address/port (example: 192.168.1.1-34650)') return enb_id_group
enb_info_parser = cmd2.Cmd2ArgumentParser() diff --git a/doc/manuals/chapters/cli.adoc b/doc/manuals/chapters/cli.adoc index 93c7fe4..1b677f5 100644 --- a/doc/manuals/chapters/cli.adoc +++ b/doc/manuals/chapters/cli.adoc @@ -213,13 +213,16 @@
==== `mme_info`
-Show configuration details for a specific MME, selected by name. +Show configuration details for a specific MME.
---- -Usage: mme_info [-h] -N NAME +Usage: mme_info [-h] (-N NAME | -a ADDR | -ap ADDR-PORT)
MME ID: - -N, --name NAME MME name (example: mme0) + -N, --name NAME MME name (example: mme0) + -a, --addr ADDR MME remote address (default port: 36412) + -ap, --addr-port ADDR-PORT + MME remote address/port (example: 192.168.1.1-36412) ----
Example: @@ -236,13 +239,16 @@
==== `mme_delete`
-Remove an MME from the pool, selected by name. +Remove an MME from the pool.
---- -Usage: mme_delete [-h] -N NAME +Usage: mme_delete [-h] (-N NAME | -a ADDR | -ap ADDR-PORT)
MME ID: - -N, --name NAME MME name (example: mme0) + -N, --name NAME MME name (example: mme0) + -a, --addr ADDR MME remote address (default port: 36412) + -ap, --addr-port ADDR-PORT + MME remote address/port (example: 192.168.1.1-36412) ----
Example: @@ -282,14 +288,16 @@
---- Usage: enb_info [-h] (-H HANDLE | -P PID | -G GENBID | - --enb-sctp-aid AID | --mme-sctp-aid AID) + --enb-sctp-aid AID | --mme-sctp-aid AID | + --enb-conn ADDR-PORT)
eNB ID: - -H, --handle HANDLE eNB handle (example: 0) - -P, --pid PID eNB process ID (example: 0.33.1) - -G, --genbid GENBID Global-eNB-ID (example: 262-42-1337) - --enb-sctp-aid AID eNB SCTP association identifier - --mme-sctp-aid AID MME SCTP association identifier + -H, --handle HANDLE eNB handle (example: 0) + -P, --pid PID eNB process ID (example: 0.33.1) + -G, --genbid GENBID Global-eNB-ID (example: 262-42-1337) + --enb-sctp-aid AID eNB SCTP association identifier + --mme-sctp-aid AID MME SCTP association identifier + --enb-conn ADDR-PORT eNB connection address/port (example: 192.168.1.1-34650) ----
Example: selecting by handle. @@ -310,8 +318,8 @@
==== `enb_delete`
-Force-disconnect an eNB, terminating its SCTP connection. The same -selectors as `enb_info` are accepted. +Force-disconnect an eNB, terminating its SCTP connection. Accepts the +same selectors as `enb_info`.
==== `enb_erab_list`
@@ -321,7 +329,8 @@ Usage: enb_erab_list [-h] [-f] [-S {pid,state,mme_ue_id,erab_id}] [--reverse] (-H HANDLE | -P PID | -G GENBID | - --enb-sctp-aid AID | --mme-sctp-aid AID) + --enb-sctp-aid AID | --mme-sctp-aid AID | + --enb-conn ADDR-PORT)
optional arguments: -f, --full Print full table including PFCP and GTP-U F-TEID columns diff --git a/src/rest_server.erl b/src/rest_server.erl index 550da3e..f6eee94 100644 --- a/src/rest_server.erl +++ b/src/rest_server.erl @@ -272,6 +272,25 @@ <<"swagger_ui">> => osmo_s1gw:get_env(rest_srv_swagger_ui, ?ENV_DEFAULT_REST_SRV_SWAGGER_UI)}.
+%% parse address/port from a string like "192.168.1.1-36412" +-spec parse_addr_port(Data) -> {ok, {Addr, Port}} | error + when Data :: binary() | string(), + Addr :: inet:ip_address(), + Port :: inet:port_number(). +parse_addr_port(Data) when is_binary(Data) -> + parse_addr_port(binary_to_list(Data)); + +parse_addr_port(Data) when is_list(Data) -> + case string:split(Data, "-") of + [AddrStr, PortStr] -> + case {inet:parse_address(AddrStr), string:to_integer(PortStr)} of + {{ok, Addr}, {Port, []}} -> {ok, {Addr, Port}}; + _ -> error + end; + _ -> error + end. + + -spec sockopts_to_map([gen_sctp:option()]) -> map(). sockopts_to_map(SockOpts) -> maps:from_list([{atom_to_binary(K), V} || {K, V} <- SockOpts]). @@ -368,7 +387,19 @@ MmeName = binary_to_list(Val), mme_registry:fetch_mme_info(MmeName);
-%% TODO: '^addr:[0-9a-f:.]+-[0-9]+$' +fetch_mme_info(<< "addr:", Val/bytes >>) -> + case parse_addr_port(Val) of + {ok, {Addr, Port}} -> + Fun = fun(#{raddr := R, rport := P}) -> R =:= Addr andalso P =:= Port end, + case lists:filter(Fun, mme_registry:fetch_mme_list()) of + [MmeInfo | _] -> {ok, MmeInfo}; + [] -> error + end; + error -> + ?LOG_ERROR("Failed to parse MME addr:port from ~p", [Val]), + error + end; + fetch_mme_info(ID) -> ?LOG_ERROR("Unhandled MME ID ~p", [ID]), error. @@ -454,7 +485,15 @@ Aid = binary_to_integer(Val), enb_registry:fetch_enb_list({mme_sctp_aid, Aid});
-%% TODO: '^enb-conn:[0-9:.]+-[0-9]+$' +fetch_enb_info(<< "enb-conn:", Val/bytes >>) -> + case parse_addr_port(Val) of + {ok, AddrPort} -> + enb_registry:fetch_enb_list({enb_addr_port, AddrPort}); + error -> + ?LOG_ERROR("Failed to parse eNB addr:port from ~p", [Val]), + error + end; + fetch_enb_info(ID) -> ?LOG_ERROR("Unhandled eNB ID ~p", [ID]), error.