From 91e44bfa2b77764a828221e1914fd67b815a569a Mon Sep 17 00:00:00 2001 From: Sangeetha KR Date: Mon, 31 May 2021 00:52:03 +0530 Subject: [PATCH] Issue ID: RIC-791 Push Dockerfile to staging repo Updated tag for container-release-it-test-nanobot.yaml Updated Dockerfile Updated Container-tag.yaml Fixed KubernetesEntity Added SDLWrappper Signed-off-by: Sangeetha KR Change-Id: I420300879aaecfd380ec2a415222c44b2ae38820 --- releases/container-release-it-test-nanobot.yaml | 2 +- ric_robot_suite/docker/nanobot/Dockerfile | 29 ++-- ric_robot_suite/docker/nanobot/container-tag.yaml | 2 +- .../ric-python-utils/ricutils/KubernetesEntity.py | 10 +- .../ric-python-utils/ricutils/SDLWrapper.py | 174 +++++++++++++++++++++ 5 files changed, 190 insertions(+), 27 deletions(-) create mode 100644 ric_robot_suite/ric-python-utils/ricutils/SDLWrapper.py diff --git a/releases/container-release-it-test-nanobot.yaml b/releases/container-release-it-test-nanobot.yaml index 7ea03bc..aa32d54 100644 --- a/releases/container-release-it-test-nanobot.yaml +++ b/releases/container-release-it-test-nanobot.yaml @@ -7,4 +7,4 @@ project: it/test ref: e3a2b6fed94e2caab5f9f2424beace6e4cea0013 containers: - name: it-test-nanobot - version: 0.0.3 + version: 0.0.4 diff --git a/ric_robot_suite/docker/nanobot/Dockerfile b/ric_robot_suite/docker/nanobot/Dockerfile index 3d57ad5..e4d04cc 100644 --- a/ric_robot_suite/docker/nanobot/Dockerfile +++ b/ric_robot_suite/docker/nanobot/Dockerfile @@ -1,17 +1,3 @@ - # Copyright (c) 2019 AT&T Intellectual Property. - # Copyright (c) 2020 HCL Technologies. - # Licensed under the Apache License, Version 2.0 (the "License"); - # you may not use this file except in compliance with the License. - # You may obtain a copy of the License at - # - # http://www.apache.org/licenses/LICENSE-2.0 - # - # Unless required by applicable law or agreed to in writing, software - # distributed under the License is distributed on an "AS IS" BASIS, - # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - # See the License for the specific language governing permissions and - # limitations under the License. - FROM python:3.8-alpine AS nanobot-build RUN apk update && apk add --no-cache git build-base libffi-dev libxml2 libxslt libxml2-dev libxslt-dev openssl-dev @@ -47,8 +33,8 @@ cd build && \ cmake -DPACK_EXTERNALS=1 -DDEV_PKG=1 .. && \ make install - RUN mkdir -p /opt/e2 - RUN cp /rmr/build/src/support/rmr_probe /opt/e2/ + #RUN mkdir -p /opt/e2 + #RUN cp /rmr/build/src/support/rmr_probe /opt/e2/ @@ -70,11 +56,15 @@ COPY --from=nanobot-build /usr/local/bin/robot /usr/local/bin RUN apk add wget - RUN mkdir -p /robot/lib/python - WORKDIR ric-python-utils/ricutils - RUN wget -o SDLWrapper.py "https://gerrit.o-ran-sc.org/r/gitweb?p=ric-plt/xapp-frame-py.git;a=blob_plain;f=ricxappframe/xapp_sdl.py" + RUN mkdir -p /robot/lib/python + RUN mkdir -p /opt/e2 + #WORKDIR ric-python-utils/ricutils + #RUN wget -o SDLWrapper.py "https://gerrit.o-ran-sc.org/r/gitweb?p=ric-plt/xapp-frame-py.git;a=blob_plain;f=ricxappframe/xapp_sdl.py" # ONAP eteutils # we only need a few things from this so we won't install the whole thing. + COPY ric-python-utils/ricutils/KubernetesEntity.py /robot/lib/python + COPY ric-python-utils/ricutils/SDLWrapper.py /robot/lib/python + COPY --from=nanobot-build /rmr/build/src/support/rmr_probe /opt/e2 COPY --from=nanobot-build /tmp/python-testing-utils/eteutils/StringTemplater.py /robot/lib/python COPY --from=nanobot-build /tmp/python-testing-utils/eteutils/UUID.py /robot/lib/python COPY ric-python-utils/ricutils/*.py /robot/lib/python/ @@ -106,4 +96,3 @@ WORKDIR / CMD ["sleep", "9125d"] - diff --git a/ric_robot_suite/docker/nanobot/container-tag.yaml b/ric_robot_suite/docker/nanobot/container-tag.yaml index 5e9a251..c70f025 100644 --- a/ric_robot_suite/docker/nanobot/container-tag.yaml +++ b/ric_robot_suite/docker/nanobot/container-tag.yaml @@ -1,2 +1,2 @@ --- -tag: 0.0.3 +tag: 0.0.4 diff --git a/ric_robot_suite/ric-python-utils/ricutils/KubernetesEntity.py b/ric_robot_suite/ric-python-utils/ricutils/KubernetesEntity.py index 74bddb3..ad34f17 100644 --- a/ric_robot_suite/ric-python-utils/ricutils/KubernetesEntity.py +++ b/ric_robot_suite/ric-python-utils/ricutils/KubernetesEntity.py @@ -53,7 +53,7 @@ class KubernetesEntity(object): # that the typical check here sfst.replicas == sfst.ready_replicas return self._k8sApp.read_namespaced_stateful_set(namespace = namespace or self._ns, name=name) - + def Service(self, name, namespace=None): # as above, we'll rely on this to throw if the svc dne. @@ -98,7 +98,7 @@ class KubernetesEntity(object): d = self.Deployment(name, namespace or self._ns) labels = d.spec.selector.match_labels pods = self._k8sCore.list_namespaced_pod(namespace or self._ns, - label_selector=",".join(map(lambda k: k + "=" + labels[k], + label_selector=",".join(map(lambda k: k + "=" + labels[k], labels))) return list(map(lambda i: i.metadata.name, pods.items)) @@ -122,7 +122,7 @@ class KubernetesEntity(object): # after performance here. ctx=ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) c = client.Configuration() - + async def ExecCoroutine(): # base64.channel.k8s.io is also a valid subprotocol, but i don't see any # reason to support it. @@ -136,12 +136,12 @@ class KubernetesEntity(object): # i really don't want to be bothered with asyncio exception handling # for that vanishingly improbable case. output[channels[message[0]]].extend(message[1:-1].decode('utf-8').split('\n')) - + ctx.load_verify_locations(c.ssl_ca_cert) if(c.cert_file and c.key_file): ctx.load_cert_chain(c.cert_file, c.key_file) uri = 'wss://%s%s' % (c.host.lstrip('https://'), path) asyncio.get_event_loop().run_until_complete(ExecCoroutine()) - + return(output) diff --git a/ric_robot_suite/ric-python-utils/ricutils/SDLWrapper.py b/ric_robot_suite/ric-python-utils/ricutils/SDLWrapper.py new file mode 100644 index 0000000..ece4a95 --- /dev/null +++ b/ric_robot_suite/ric-python-utils/ricutils/SDLWrapper.py @@ -0,0 +1,174 @@ +# ================================================================================== +# Copyright (c) 2020 Nokia +# Copyright (c) 2020 AT&T Intellectual Property. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ================================================================================== + +""" +sdl functionality +""" + +import msgpack +from ricsdl.syncstorage import SyncStorage + +class SDLWrapper: + """ + Provides convenient wrapper methods for using the SDL Python interface. + Optionally uses msgpack for binary (de)serialization: + see https://msgpack.org/index.html + + Published as a standalone module (and kept separate from the Xapp + framework classes) so these features can be used outside Xapps. + """ + + def __init__(self, use_fake_sdl=False): + """ + init + + Parameters + ---------- + use_fake_sdl: bool (optional, default False) + if this is True, then use SDL's in-memory backend, + which is very useful for testing since it allows use + of SDL without a running SDL or Redis instance. + This can be used while developing an xapp and also + for monkeypatching during unit testing; e.g., the xapp + framework unit tests do this. + """ + if use_fake_sdl: + self._sdl = SyncStorage(fake_db_backend="dict") + else: + self._sdl = SyncStorage() + + + def set(self, ns, key, value, usemsgpack=True): + """ + Stores a key-value pair, + optionally serializing the value to bytes using msgpack. + + TODO: discuss whether usemsgpack should *default* to True or + False here. This seems like a usage statistic question (that we + don't have enough data for yet). Are more uses for an xapp to + write/read their own data, or will more xapps end up reading data + written by some other thing? I think it's too early to know. + + Parameters + ---------- + ns: string + SDL namespace + key: string + SDL key + value: + Object or byte array to store. See the `usemsgpack` parameter. + usemsgpack: boolean (optional, default is True) + Determines whether the value is serialized using msgpack before storing. + If usemsgpack is True, the msgpack function `packb` is invoked + on the value to yield a byte array that is then sent to SDL. + Stated differently, if usemsgpack is True, the value can be anything + that is serializable by msgpack. + If usemsgpack is False, the value must be bytes. + """ + if usemsgpack: + value = msgpack.packb(value, use_bin_type=True) + self._sdl.set(ns, {key: value}) + + def get(self, ns, key, usemsgpack=True): + """ + Gets the value for the specified namespace and key, + optionally deserializing stored bytes using msgpack. + + Parameters + ---------- + ns: string + SDL namespace + key: string + SDL key + usemsgpack: boolean (optional, default is True) + If usemsgpack is True, the byte array stored by SDL is deserialized + using msgpack to yield the original object that was stored. + If usemsgpack is False, the byte array stored by SDL is returned + without further processing. + + Returns + ------- + Value + See the usemsgpack parameter for an explanation of the returned value type. + Answers None if the key is not found. + """ + result = None + ret_dict = self._sdl.get(ns, {key}) + if key in ret_dict: + result = ret_dict[key] + if usemsgpack: + result = msgpack.unpackb(result, raw=False) + return result + + def find_and_get(self, ns, prefix, usemsgpack=True): + """ + Gets all key-value pairs in the specified namespace + with keys that start with the specified prefix, + optionally deserializing stored bytes using msgpack. + + Parameters + ---------- + ns: string + SDL namespace + prefix: string + the key prefix + usemsgpack: boolean (optional, default is True) + If usemsgpack is True, every byte array stored by SDL is deserialized + using msgpack to yield the original value that was stored. + If usemsgpack is False, every byte array stored by SDL is returned + without further processing. + + Returns + ------- + Dictionary of key-value pairs + Each key has the specified prefix. + See the usemsgpack parameter for an explanation of the returned value types. + Answers an empty dictionary if no keys matched the prefix. + """ + + # note: SDL "*" usage is inconsistent with real python regex, where it would be ".*" + ret_dict = self._sdl.find_and_get(ns, "{0}*".format(prefix)) + if usemsgpack: + ret_dict = {k: msgpack.unpackb(v, raw=False) for k, v in ret_dict.items()} + return ret_dict + + def delete(self, ns, key): + """ + Deletes the key-value pair with the specified key in the specified namespace. + + Parameters + ---------- + ns: string + SDL namespace + key: string + SDL key + """ + self._sdl.remove(ns, {key}) + + + def healthcheck(self): + """ + Checks if the sdl connection is healthy. + + Returns + ------- + bool + """ + return self._sdl.is_active() + #if self._sdl.is_active(): + # return True + #return False -- 2.16.6