- # 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
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/
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/
WORKDIR /
CMD ["sleep", "9125d"]
-
# 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.
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))
# 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.
# 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)
--- /dev/null
+# ==================================================================================
+# 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