From 53ba1707f0da9d64aae53a43d59a5257dd4e12ce Mon Sep 17 00:00:00 2001 From: kjaniak Date: Thu, 25 Oct 2018 14:25:13 +0200 Subject: [PATCH] Publish HV-VES documentation including perf3gpp Change-Id: I8d3e926ce6bc99f981d52eb72fcbe92e8ce67cde Signed-off-by: kjaniak Issue-ID: DCAEGEN2-859 --- docs/sections/apis/ves-hv/MeasDataCollection.proto | 78 ++++ docs/sections/apis/ves-hv/Perf3gppFields.proto | 37 ++ docs/sections/apis/ves-hv/index.rst | 84 +++- .../services/ves-hv/ONAP_VES_HV_Architecture.png | Bin 0 -> 46724 bytes docs/sections/services/ves-hv/WTP.yaml | 45 ++ docs/sections/services/ves-hv/architecture.rst | 18 + docs/sections/services/ves-hv/authorization.rst | 26 ++ docs/sections/services/ves-hv/deployment.rst | 88 ++++ docs/sections/services/ves-hv/design.rst | 47 +- docs/sections/services/ves-hv/example-event.rst | 15 + docs/sections/services/ves-hv/index.rst | 15 +- docs/sections/services/ves-hv/repositories.rst | 22 + .../services/ves-hv/run-time-configuration.rst | 59 +++ docs/sections/services/ves-hv/troubleshooting.rst | 506 +++++++++++++++++++++ 14 files changed, 998 insertions(+), 42 deletions(-) create mode 100644 docs/sections/apis/ves-hv/MeasDataCollection.proto create mode 100644 docs/sections/apis/ves-hv/Perf3gppFields.proto create mode 100644 docs/sections/services/ves-hv/ONAP_VES_HV_Architecture.png create mode 100644 docs/sections/services/ves-hv/WTP.yaml create mode 100644 docs/sections/services/ves-hv/architecture.rst create mode 100644 docs/sections/services/ves-hv/authorization.rst create mode 100644 docs/sections/services/ves-hv/deployment.rst create mode 100644 docs/sections/services/ves-hv/example-event.rst create mode 100644 docs/sections/services/ves-hv/repositories.rst create mode 100644 docs/sections/services/ves-hv/run-time-configuration.rst create mode 100644 docs/sections/services/ves-hv/troubleshooting.rst diff --git a/docs/sections/apis/ves-hv/MeasDataCollection.proto b/docs/sections/apis/ves-hv/MeasDataCollection.proto new file mode 100644 index 00000000..978cb28a --- /dev/null +++ b/docs/sections/apis/ves-hv/MeasDataCollection.proto @@ -0,0 +1,78 @@ +/* + * ============LICENSE_START======================================================= + * dcaegen2-collectors-veshv + * ================================================================================ + * Copyright (C) 2018 NOKIA + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +syntax = "proto3"; +package org.onap.ves; + +// Definition for RTPM, structure aligned with 3GPP PM format optimized for RTPM delivery pre-standard TS 28.550 V2.0.0 (2018-09). +// Some field details are taken from 3GPP TS 32.436 V15.0.0 (2018-06) ASN.1 file. +// Note (2018-09): work is in progress for 3GPP TS 28.550. Changes will be made, if needed, to align with final version. +// Differences/additions to 3GPP TS 28.550 are marked with "%%". + +message MeasDataCollection // top-level message +{ + // %% Combined messageFileHeader, measData (single instance), messageFileFooter (not needed: timestamp = collectionBeginTime + granularityPeriod). + string formatVersion = 1; // required, current value "28.550 2.0" + uint32 granularityPeriod = 2; // required, duration in seconds, %% moved from MeasInfo (single reporting period per event) + string measuredEntityUserName = 3; // network function user definable name ("userLabel") defined for the measured entity in 3GPP TS 28.622 + string measuredEntityDn = 4; // DN as per 3GPP TS 32.300 + string measuredEntitySoftwareVersion = 5; + repeated string measObjInstIdList = 6; // %%: optional, monitored object LDNs as per 3GPP TS 32.300 and 3GPP TS 32.432 + repeated MeasInfo measInfo = 7; +} + +message MeasInfo +{ + oneof MeasInfoId { // measurement group identifier + uint32 iMeasInfoId = 1; // identifier as integer (%%: more compact) + string measInfoId = 2; // identifier as string (more generic) + } + + oneof MeasTypes { // measurement identifiers associated with the measurement results + IMeasTypes iMeasTypes = 3; // identifiers as integers (%%: more compact) + SMeasTypes measTypes = 4; // identifiers as strings (more generic) + } + // Needed only because GPB does not support repeated fields directly inside 'oneof' + message IMeasTypes { repeated uint32 iMeasType = 1; } + message SMeasTypes { repeated string measType = 1; } + + string jobId = 5; + repeated MeasValue measValues = 6; // performance measurements grouped by measurement object +} + +message MeasValue +{ + oneof MeasObjInstId { // monitored object LDN as per 3GPP TS 32.300 and 3GPP TS 32.432 + string measObjInstId = 1; // LDN itself + uint32 measObjInstIdListIdx = 2; // %%: index into measObjInstIdList (zero-based) + } + repeated MeasResult measResults = 3; + bool suspectFlag = 4; + map measObjAddlFlds = 5; // %%: optional per-object data (name/value HashMap) +} + +message MeasResult +{ + uint32 p = 1; // Index in the MeasTypes array (zero-based), needed only if measResults has fewer elements than MeasTypes + oneof xValue { + sint64 iValue = 2; + double rValue = 3; + bool isNull = 4; + } +} diff --git a/docs/sections/apis/ves-hv/Perf3gppFields.proto b/docs/sections/apis/ves-hv/Perf3gppFields.proto new file mode 100644 index 00000000..453d1062 --- /dev/null +++ b/docs/sections/apis/ves-hv/Perf3gppFields.proto @@ -0,0 +1,37 @@ +/* + * ============LICENSE_START======================================================= + * dcaegen2-collectors-veshv + * ================================================================================ + * Copyright (C) 2018 NOKIA + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +syntax = "proto3"; +package org.onap.ves; +import "MeasDataCollection.proto"; // for 3GPP PM format + +message Perf3gppFields +{ + string perf3gppFieldsVersion = 1; // required, current value "1.0" + MeasDataCollection measDataCollection = 2; // required + // Based on 3GPP TS 28.550 + // Logical mapping from 3GPP to ONAP header fields: + // 3GPP MeasFileHeader ONAP/VES CommonEventHeader + // senderName sourceName + // senderType nfNamingCode + nfcNamingCode + // vendorName nfVendorName + // collectionBeginTime startEpochMicrosec + // timestamp lastEpochMicrosec + map eventAddlFlds = 3; // optional per-event data (name/value HashMap) +} diff --git a/docs/sections/apis/ves-hv/index.rst b/docs/sections/apis/ves-hv/index.rst index 799f92d4..b707d9fd 100644 --- a/docs/sections/apis/ves-hv/index.rst +++ b/docs/sections/apis/ves-hv/index.rst @@ -8,7 +8,7 @@ HV-VES (High Volume VES) :Date: 2018-10-05 .. contents:: - :depth: 3 + :depth: 4 .. Overview @@ -18,42 +18,98 @@ Component description can be found under `HV-VES Collector`_. .. _HV-VES Collector: ../../services/ves-hv/index.html +.. _tcp_endpoint: TCP Endpoint ============ HV-VES is exposed as NodePort service on Kubernetes cluster on port 30222/tcp. -It uses plain TCP connections tunneled in SSL/TLS or can be run in insecure manner without data encryption on the socket. +It uses plain, insecure TCP connection without socket data encryption. In Casablanca release, there is an experimental option to enable SSL/TLS (see :ref:`authorization`). Without TLS client authentication/authorization is not possible. -Connections are stream-based (as opposed to request-based) and long running. +Connections are stream-based (as opposed to request-based) and long-running. Communication is wrapped with thin Wire Transfer Protocol, which mainly provides delimitation. .. literalinclude:: WTP.asn :language: asn -Payload is binary-encoded, currently using Google Protocol Buffers representation of the VES Common Header. +Payload is binary-encoded, using Google Protocol Buffers (GPB) representation of the VES Event. .. literalinclude:: VesEvent.proto :language: protobuf -The PROTO file, which contains the VES CommonHeader, comes with a binary-type Payload parameter, where domain-specific -data shall be placed. Domain-specific data are encoded as well with GPB, and they do require a domain-specific -PROTO file to decode the data. +HV-VES makes routing decisions based mostly on the content of the **Domain** parameter in the VES Common Event Header. -HV-VES makes routing decisions based mostly on the content of the **Domain** parameter in VES Common Header. +The PROTO file, which contains the VES CommonEventHeader, comes with a binary-type Payload (eventFields) parameter, where domain-specific +data should be placed. Domain-specific data are encoded as well with GPB. A domain-specific PROTO file is required to decode the data. +Domain **perf3gpp** +=================== -Healthcheck -=========== +The purpose of the **perf3gpp** domain is to deliver performance measurements from a network function (NF) to ONAP in 3GPP format. +The first application of this domain is frequent periodic delivery of structured RAN PM data commonly referred to as Real Time PM (RTPM). +The equipment sends an event right after collecting the PM data for a granularity period. -Inside HV-VES docker container runs small http service for healthcheck - exact port for this service can be configured -at deployment using `--health-check-api-port` command line option. +The characteristics of each event in the **perf3gpp** domain: -This service exposes single endpoint **GET /health/ready** which returns **HTTP 200 OK** in case HV-VES is healthy -and ready for connections. Otherwise it returns **HTTP 503 Service Unavailable** with short reason of unhealthiness. +- Single measured entity, for example, BTS +- Single granularity period (collection *begin time* and *duration*) +- Optional top-level grouping in one or more PM groups +- Grouping in one or more measured objects, for example, cells +- One or more reported PM values for each measured object +Due to the single granularity period per event, single equipment supporting multiple concurrent granularity periods might send more than one event at a given reporting time. +The **perf3gpp** domain is based on 3GPP specifications: +- `3GPP TS 28.550 `_ +- `3GPP TS 32.431 `_ +- `3GPP TS 32.436 `_ +The event structure is changed in comparison to the one presented in 3GPP technical specifications. The 3GPP structure is enhanced to provide support for efficient transport. +Definitions for the **perf3gpp** domain are stored in Perf3gppFields.proto and MeasDataCollection.proto, listed below: + +.. literalinclude:: Perf3gppFields.proto + :language: protobuf + +.. literalinclude:: MeasDataCollection.proto + :language: protobuf + + +API towards DMaaP +================= + +HV-VES Collector forwards incoming messages to a particular DMaaP Kafka topic based on the domain and configuration. Every Kafka record is comprised of a key and a value. In case of HV-VES: + +- **Kafka record key** is a GPB-encoded `CommonEventHeader`. +- **Kafka record value** is a GPB-encoded `VesEvent` (`CommonEventHeader` and domain-specific `eventFields`). + +In both cases raw bytes might be extracted using ``org.apache.kafka.common.serialization.ByteArrayDeserializer``. The resulting bytes might be further passed to ``parseFrom`` methods included in classes generated from GPB definitions. WTP is not used here - it is only used in communication between PNF/VNF and the collector. + + +.. _hv_ves_behaviors: + +HV-VES behaviors +================ + +Connections with HV-VES are stream-based (as opposed to request-based) and long-running. In case of interrupted or closed connection, the collector logs such event but does not try to reconnect to client. +Communication is wrapped with thin Wire Transfer Protocol, which mainly provides delimitation. Wire Transfer Protocol Frame: + +- is dropped after decoding and validating and only GPB is used in further processing. +- has to start with **MARKER_BYTE**, as defined in protocol specification (see :ref:`tcp_endpoint`). If **MARKER_BYTE** is invalid, HV-VES disconnects from client. + +HV-VES decodes only CommonEventHeader from GPB message received. Collector does not decode or validate the rest of the GPB message and publishes it to Kafka topic intact. +Kafka topic for publishing events with specific domain can be configured through Consul service as described in :ref:`run_time_configuration`. +In case of Kafka service unavailability, the collector drops currently handled messages and disconnects the client. + +Messages handling: + +- HV-VES Collector skips messages with unknown/invalid GPB CommonEventHeader format. +- HV-VES Collector skips messages with unsupported domain. Domain is unsupported if there is no route for it in configuration (see :ref:`run_time_configuration`). +- HV-VES Collector skips messages with invalid Wire Frame format, unsupported WTP version or inconsistencies of data in the frame (other than invalid **MARKER_BYTE**). +- HV-VES Collector interrupts connection when it encounters a message with too big GPB payload. Default maximum size and ways to change it are described in :ref:`deployment`. + +.. note:: xNF (VNF/PNF) can split messages bigger than 1 MiB and set `sequence` field in CommonEventHeader accordingly. It is advised to use smaller than 1 MiB messages for GPBs encoding/decoding efficiency. + +- Skipped messages (for any of the above reasons) might not leave any trace in HV-VES logs. diff --git a/docs/sections/services/ves-hv/ONAP_VES_HV_Architecture.png b/docs/sections/services/ves-hv/ONAP_VES_HV_Architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..7652b9706d83e9a33b892cc3af96e3bd5b9e5d0f GIT binary patch literal 46724 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
+1m>Im1p?V_q-Nj~7q3Wztji+WX^THedtv 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 URL of ves configuration on consul + -d,--first-request-delay Delay of first request to consul in + seconds + -H,--health-check-api-port Health check rest api listen port + -I,--request-interval Interval of consul configuration + requests in seconds + -i,--idle-timeout-sec Idle timeout for remote hosts. After + given time without any data exchange + the + connection might be closed. + -k,--key-store Key store in PKCS12 format + -kp,--key-store-password Key store password + -l,--ssl-disable Disable SSL encryption + -m,--max-payload-size Maximum supported payload size in + bytes + -p,--listen-port Listen port + -t,--trust-store File with trusted certificate bundle + in PKCS12 format + -tp,--trust-store-password Trust store password + -u,--dummy If present will start in dummy mode + (dummy external services) + All parameters can be specified as environment variables using + upper-snake-case full name with prefix `VESHV_`. + + +This log message is printed when you do not specify the required parameters (via command line, or in environment variables). +As described in the above log message, there are a few required parameters: +**listen port**, **config url** and either **trust store password** and **key store password** if you want to use SSL, or only **ssl disable** if not. + +To get rid of this error, specify the required parameters. For example: + +- Via command line: + +:: + + --listen-port 6061 --config-url http://consul-url/key-path --key-store-password password --trust-store-password password + +- By defining environment variables: + +:: + + export VESHV_LISTEN_PORT=6061 + export VESHV_CONFIG_URL=http://consul-url/key-path + export VESHV_KEY_STORE_PASSWORD=password + export VESHV_TRUST_STORE_PASSWORD=password + +**NOTE** + +Command line arguments have priority over environment variables. If you configure a parameter in both ways, **HV-VES** applies the one from the command line. + +For more information about **HV-VES** configuration parameters, see :ref:`deployment`. + +Configuration errors +-------------------- + +**Consul service not responding** + +:: + + ap.dcae.collectors.veshv.impl.adapters.HttpAdapter | 2018-10-16T13:13:01.155Z | ERROR | Failed to get resource on path: http://localhost:8500/v1/hv/veshv-config (Connection refused: localhost/127.0.0.1:8500) | | reactor-http-client-epoll-8 + ap.dcae.collectors.veshv.impl.adapters.HttpAdapter | 2018-10-16T13:13:01.155Z | DEBUG | Nested exception: | java.net.ConnectException: Connection refused + ... 10 common frames omitted + Wrapped by: io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: localhost/127.0.0.1:8500 + at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method) + at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:717) + at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:327) + at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:340) + at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:616) + at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:563) + at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:480) + at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:442) + at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884) + at java.lang.Thread.run(Thread.java:748) + | reactor-http-client-epoll-8 + rs.veshv.impl.adapters.ConsulConfigurationProvider | 2018-10-16T13:13:01.163Z | WARN | Could not get fresh configuration | java.net.ConnectException: Connection refused + ... 10 common frames omitted + Wrapped by: io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: localhost/127.0.0.1:8500 + at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method) + at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:717) + at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:327) + at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:340) + at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:616) + at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:563) + at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:480) + at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:442) + at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884) + at java.lang.Thread.run(Thread.java:748) + | reactor-http-client-epoll-8 + + + +The above three logs indicate that **HV-VES** cannot connect to the Consul service under url given in **--consul-url** parameter. +Make sure Consul is up and running and the **ip + port** combination is correct. + +==== + +**Missing configuration on Consul** + +:: + + ap.dcae.collectors.veshv.impl.adapters.HttpAdapter | 2018-10-16T13:52:20.585Z | ERROR | Failed to get resource on path: http://consul:8500/v1/kv/veshv-config (HTTP request failed with code: 404. + Failing URI: /v1/kv/veshv-config) | | reactor-http-nio-1 + ap.dcae.collectors.veshv.impl.adapters.HttpAdapter | 2018-10-16T13:52:20.586Z | DEBUG | Nested exception: | reactor.ipc.netty.http.client.HttpClientException: HTTP request failed with code: 404. + Failing URI: /v1/kv/veshv-config + | reactor-http-nio-1 + rs.veshv.impl.adapters.ConsulConfigurationProvider | 2018-10-16T13:52:20.591Z | WARN | Could not get fresh configuration | reactor.ipc.netty.http.client.HttpClientException: HTTP request failed with code: 404. + Failing URI: /v1/kv/veshv-config + | reactor-http-nio-1 + + +**HV-VES** logs this information when connected to Consul, but cannot find any json configuration under given key which in this case is **veshv-config**. +For more information, see :ref:`run_time_configuration` + +==== + +**Invalid configuration format** + +:: + + rs.veshv.impl.adapters.ConsulConfigurationProvider | 2018-10-16T14:06:14.792Z | INFO | Obtained new configuration from consul: + { + "invalidKey": "value" + } | | reactor-http-nio-1 + rs.veshv.impl.adapters.ConsulConfigurationProvider | 2018-10-16T14:06:14.796Z | WARN | Could not get fresh configuration | java.lang.NullPointerException: null + at org.glassfish.json.JsonObjectBuilderImpl$JsonObjectImpl.getString(JsonObjectBuilderImpl.java:257) + at org.onap.dcae.collectors.veshv.impl.adapters.ConsulConfigurationProvider.createCollectorConfiguration(ConsulConfigurationProvider.kt:113) + at org.onap.dcae.collectors.veshv.impl.adapters.ConsulConfigurationProvider.access$createCollectorConfiguration(ConsulConfigurationProvider.kt:44) + at org.onap.dcae.collectors.veshv.impl.adapters.ConsulConfigurationProvider$invoke$6.invoke(ConsulConfigurationProvider.kt:80) + at org.onap.dcae.collectors.veshv.impl.adapters.ConsulConfigurationProvider$invoke$6.invoke(ConsulConfigurationProvider.kt:44) + at org.onap.dcae.collectors.veshv.impl.adapters.ConsulConfigurationProvider$sam$java_util_function_Function$0.apply(ConsulConfigurationProvider.kt) + at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:100) + at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:108) + at reactor.core.publisher.FluxFlatMap$FlatMapMain.tryEmitScalar(FluxFlatMap.java:432) + at reactor.core.publisher.FluxFlatMap$FlatMapMain.onNext(FluxFlatMap.java:366) + at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:108) + at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:108) + at reactor.core.publisher.FluxFlatMap$FlatMapMain.tryEmit(FluxFlatMap.java:484) + at reactor.core.publisher.FluxFlatMap$FlatMapInner.onNext(FluxFlatMap.java:916) + at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:115) + at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1083) + at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:241) + at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:76) + at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:108) + at reactor.core.publisher.FluxFilter$FilterSubscriber.onNext(FluxFilter.java:97) + at reactor.ipc.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:213) + at reactor.ipc.netty.channel.FluxReceive.onInboundNext(FluxReceive.java:329) + at reactor.ipc.netty.channel.ChannelOperations.onInboundNext(ChannelOperations.java:311) + at reactor.ipc.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:605) + at reactor.ipc.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:138) + at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) + at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) + at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) + at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:438) + at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:310) + at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:284) + at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:253) + at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) + at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) + at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) + at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434) + at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) + at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) + at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965) + at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) + at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:628) + at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:563) + at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:480) + at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:442) + at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884) + at java.lang.Thread.run(Thread.java:748) + | reactor-http-nio-1 + + +This log is printed when you upload a configuration in an invalid format (for example, with missing fields). In the first log you can see that configuration on Consul is: + +.. code-block:: json + + { + "invalidKey": "value" + } + +The above is not a valid **HV-VES** configuration, therefore **HV-VES** does not apply it and becomes **unhealthy**. +For more information on **Consul configuration**, see :ref:`run_time_configuration`. + + +Message handling errors +----------------------- + +**Handling messages when invalid kafka url is specified** + +:: + + | reactor-tcp-server-epoll-6 + org.apache.kafka.clients.ClientUtils | 2018-10-19T08:29:36.917Z | WARN | Removing server invalid-kafka:9093 from bootstrap.servers as DNS resolution failed for invalid-kafka | | reactor-tcp-server-epoll-6 + org.apache.kafka.clients.producer.KafkaProducer | 2018-10-19T08:29:36.918Z | INFO | [Producer clientId=producer-1] Closing the Kafka producer with timeoutMillis = 0 ms. | | reactor-tcp-server-epoll-6 + org.onap.dcae.collectors.veshv.impl.VesHvCollector | 2018-10-19T08:29:36.962Z | WARN | Error while handling message stream: org.apache.kafka.common.KafkaException (Failed to construct kafka producer) | | reactor-tcp-server-epoll-6 + org.onap.dcae.collectors.veshv.impl.VesHvCollector | 2018-10-19T08:29:36.966Z | DEBUG | Detailed stack trace | org.apache.kafka.common.config.ConfigException: No resolvable bootstrap urls given in bootstrap.servers + at org.apache.kafka.clients.ClientUtils.parseAndValidateAddresses(ClientUtils.java:64) + at org.apache.kafka.clients.producer.KafkaProducer.(KafkaProducer.java:396) + ... 24 common frames omitted + Wrapped by: org.apache.kafka.common.KafkaException: Failed to construct kafka producer + at org.apache.kafka.clients.producer.KafkaProducer.(KafkaProducer.java:441) + at org.apache.kafka.clients.producer.KafkaProducer.(KafkaProducer.java:285) + at reactor.kafka.sender.internals.ProducerFactory.createProducer(ProducerFactory.java:33) + at reactor.kafka.sender.internals.DefaultKafkaSender.lambda$new$0(DefaultKafkaSender.java:90) + at reactor.core.publisher.MonoCallable.subscribe(MonoCallable.java:57) + at reactor.core.publisher.MonoPeekFuseable.subscribe(MonoPeekFuseable.java:74) + at reactor.core.publisher.Mono.subscribe(Mono.java:3088) + at reactor.core.publisher.MonoProcessor.add(MonoProcessor.java:531) + at reactor.core.publisher.MonoProcessor.subscribe(MonoProcessor.java:444) + at reactor.core.publisher.MonoFlatMapMany.subscribe(MonoFlatMapMany.java:49) + at reactor.core.publisher.FluxPeek.subscribe(FluxPeek.java:80) + at reactor.core.publisher.FluxFilter.subscribe(FluxFilter.java:52) + at reactor.core.publisher.FluxMap.subscribe(FluxMap.java:62) + at reactor.core.publisher.FluxDefer.subscribe(FluxDefer.java:55) + at reactor.core.publisher.FluxPeek.subscribe(FluxPeek.java:83) + at reactor.core.publisher.FluxDoFinally.subscribe(FluxDoFinally.java:73) + at reactor.core.publisher.FluxOnErrorResume.subscribe(FluxOnErrorResume.java:47) + at reactor.core.publisher.MonoIgnoreElements.subscribe(MonoIgnoreElements.java:37) + at reactor.ipc.netty.channel.ChannelOperations.applyHandler(ChannelOperations.java:381) + at reactor.ipc.netty.channel.ChannelOperations.onHandlerStart(ChannelOperations.java:296) + at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163) + at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404) + at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:315) + at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884) + at java.lang.Thread.run(Thread.java:748) + | reactor-tcp-server-epoll-6 + p.dcae.collectors.veshv.impl.socket.NettyTcpServer | 2018-10-19T08:29:36.971Z | INFO | Connection from /172.26.0.6:55574 has been closed | | reactor-tcp-server-epoll-6 + + +**HV-VES** responds with the above when it handles a message and currently applied configuration has invalid Kafka bootstrap server defined. +The configuration read from Consul in this case: + +.. code-block:: json + + { + "dmaap.kafkaBootstrapServers": "invalid-kafka:9093", + "collector.routing": [ + { + "fromDomain": "perf3gpp", + "toTopic": "HV_VES_PERF3GPP" + }, + { + "fromDomain": "heartbeat", + "toTopic": "HV_VES_HEARTBEAT" + } + ] + } + +where **invalid-kafka:9093** is not an existing **ip+port** combination. + + +==== + +**First creation of topics on kafka** + + +On the first try of creating and publishing to a given kafka topic, **HV-VES** logs the following warnings and creates the requested topics anyway. + +:: + + org.apache.kafka.clients.NetworkClient | 2018-10-22T10:11:53.396Z | WARN | [Producer clientId=producer-1] Error while fetching metadata with correlation id 1 : {HV_VES_PERF3GPP=LEADER_NOT_AVAILABLE} | | kafka-producer-network-thread | producer-1 + org.apache.kafka.clients.NetworkClient | 2018-10-22T10:11:53.524Z | WARN | [Producer clientId=producer-1] Error while fetching metadata with correlation id 3 : {HV_VES_PERF3GPP=LEADER_NOT_AVAILABLE} | | kafka-producer-network-thread | producer-1 + org.apache.kafka.clients.NetworkClient | 2018-10-22T10:11:53.636Z | WARN | [Producer clientId=producer-1] Error while fetching metadata with correlation id 4 : {HV_VES_PERF3GPP=LEADER_NOT_AVAILABLE} | | kafka-producer-network-thread | producer-1 + org.apache.kafka.clients.NetworkClient | 2018-10-22T10:11:53.749Z | WARN | [Producer clientId=producer-1] Error while fetching metadata with correlation id 5 : {HV_VES_PERF3GPP=LEADER_NOT_AVAILABLE} | | kafka-producer-network-thread | producer-1 + +==== + +**Kafka service became unavailable after producer for a given topic was successfully created** + + +After receiving a **Ves Common Event**, **HV-VES** creates a producer for a given topic and keeps it for the whole lifetime of an application. +If Kafka service becomes unreachable after the producer creation, you will see the following logs when trying to establish another connection with the Kafka server. + +:: + + org.apache.kafka.clients.NetworkClient | 2018-10-22T10:04:08.604Z | WARN | [Producer clientId=producer-1] Connection to node 1001 could not be established. Broker may not be available. | | kafka-producer-network-thread | producer-1 + org.apache.kafka.clients.NetworkClient | 2018-10-22T10:04:11.896Z | WARN | [Producer clientId=producer-1] Connection to node 1001 could not be established. Broker may not be available. | | kafka-producer-network-thread | producer-1 + org.apache.kafka.clients.NetworkClient | 2018-10-22T10:04:14.968Z | WARN | [Producer clientId=producer-1] Connection to node 1001 could not be established. Broker may not be available. | | kafka-producer-network-thread | producer-1 + org.apache.kafka.clients.NetworkClient | 2018-10-22T10:04:18.040Z | WARN | [Producer clientId=producer-1] Connection to node 1001 could not be established. Broker may not be available. | | kafka-producer-network-thread | producer-1 + org.apache.kafka.clients.NetworkClient | 2018-10-22T10:04:21.111Z | WARN | [Producer clientId=producer-1] Connection to node 1001 could not be established. Broker may not be available. | | kafka-producer-network-thread | producer-1 + reactor.kafka.sender.internals.DefaultKafkaSender | 2018-10-22T10:04:23.519Z | ERROR | error {} | org.apache.kafka.common.errors.TimeoutException: Expiring 1 record(s) for HV_VES_PERF3GPP-0: 30050 ms has passed since batch creation plus linger time + | kafka-producer-network-thread | producer-1 + cae.collectors.veshv.impl.adapters.kafka.KafkaSink | 2018-10-22T10:04:23.522Z | WARN | Failed to send message to Kafka | org.apache.kafka.common.errors.TimeoutException: Expiring 1 record(s) for HV_VES_PERF3GPP-0: 30050 ms has passed since batch creation plus linger time + | single-1 + org.onap.dcae.collectors.veshv.impl.VesHvCollector | 2018-10-22T10:04:23.528Z | WARN | Error while handling message stream: org.apache.kafka.common.errors.TimeoutException (Expiring 1 record(s) for HV_VES_PERF3GPP-0: 30050 ms has passed since batch creation plus linger time) | | single-1 + +To resolve this issue, **HV-VES** restart is required. + +==== + +**Message with too big payload size** + +:: + + g.onap.dcae.collectors.veshv.impl.VesHvCollector | 2018-10-19T08:53:18.349Z | WARN | Error while handling message stream: org.onap.dcae.collectors.veshv.impl.wire.WireFrameException (PayloadSizeExceeded: payload size exceeds the limit (1048576 bytes)) | | single-1 + org.onap.dcae.collectors.veshv.impl.VesHvCollector | 2018-10-19T08:53:18.349Z | DEBUG | Detailed stack trace | org.onap.dcae.collectors.veshv.impl.wire.WireFrameException: PayloadSizeExceeded: payload size exceeds the limit (1048576 bytes) + at org.onap.dcae.collectors.veshv.impl.wire.WireChunkDecoder$onError$1$1.invoke(WireChunkDecoder.kt:67) + at org.onap.dcae.collectors.veshv.impl.wire.WireChunkDecoder$onError$1$1.invoke(WireChunkDecoder.kt:38) + at arrow.effects.IO$Companion$invoke$1.invoke(IO.kt:28) + at arrow.effects.IO$Companion$invoke$1.invoke(IO.kt:22) + at arrow.effects.IORunLoop.step(IORunLoop.kt:50) + at arrow.effects.IO.unsafeRunTimed(IO.kt:109) + at arrow.effects.IO.unsafeRunSync(IO.kt:106) + at org.onap.dcae.collectors.veshv.impl.wire.WireChunkDecoder$generateFrames$1.accept(WireChunkDecoder.kt:61) + at org.onap.dcae.collectors.veshv.impl.wire.WireChunkDecoder$generateFrames$1.accept(WireChunkDecoder.kt:38) + at reactor.core.publisher.FluxGenerate.lambda$new$1(FluxGenerate.java:56) + at reactor.core.publisher.FluxGenerate$GenerateSubscription.slowPath(FluxGenerate.java:262) + at reactor.core.publisher.FluxGenerate$GenerateSubscription.request(FluxGenerate.java:204) + at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.request(FluxPeekFuseable.java:138) + at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:1454) + at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:1328) + at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onSubscribe(FluxPeekFuseable.java:172) + at reactor.core.publisher.FluxGenerate.subscribe(FluxGenerate.java:83) + at reactor.core.publisher.FluxPeekFuseable.subscribe(FluxPeekFuseable.java:86) + at reactor.core.publisher.FluxDefer.subscribe(FluxDefer.java:55) + at reactor.core.publisher.Flux.subscribe(Flux.java:6877) + at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:418) + at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onNext(FluxConcatMap.java:241) + at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:185) + at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:185) + at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:108) + at reactor.ipc.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:213) + at reactor.ipc.netty.channel.FluxReceive.onInboundNext(FluxReceive.java:329) + at reactor.ipc.netty.channel.ChannelOperations.onInboundNext(ChannelOperations.java:311) + at reactor.ipc.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:138) + at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) + at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) + at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) + at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286) + at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) + at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) + at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) + at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434) + at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) + at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) + at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965) + at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:808) + at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:410) + at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:310) + at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884) + at java.lang.Thread.run(Thread.java:748) + | single-1 + p.dcae.collectors.veshv.impl.socket.NettyTcpServer | 2018-10-19T08:53:18.351Z | INFO | Connection from /172.26.0.6:56924 has been closed | | single-1 + + + +The above log is printed when the message payload size is too big. **HV-VES** does not handle messages that exceed specified payload size. Default value is **1048576 bytes (1MiB)**, but it can be configured via cmd or by environment variables. + + + +==== + +**Other invalid messages** + + +Messages with **invalid wire frame** or **invalid gpb** data are ommitted and **HV-VES** only logs the connection-related logs as follows: + +:: + + p.dcae.collectors.veshv.impl.socket.NettyTcpServer | 2018-10-19T09:03:03.345Z | INFO | Handling connection from /172.26.0.6:57432 | | reactor-tcp-server-epoll-5 + p.dcae.collectors.veshv.impl.socket.NettyTcpServer | 2018-10-19T09:04:03.351Z | INFO | Idle timeout of 60 s reached. Closing connection from /172.26.0.6:57432... | | reactor-tcp-server-epoll-5 + p.dcae.collectors.veshv.impl.socket.NettyTcpServer | 2018-10-19T09:04:03.353Z | INFO | Connection from /172.26.0.6:57432 has been closed | | reactor-tcp-server-epoll-5 + p.dcae.collectors.veshv.impl.socket.NettyTcpServer | 2018-10-19T09:04:03.354Z | DEBUG | Channel (/172.26.0.6:57432) closed successfully. | | reactor-tcp-server-epoll-5 + + +For more information, see the :ref:`hv_ves_behaviors` section. + +Authorization related errors +---------------------------- + +**WARNING: SSL/TLS authorization is a part of an experimental feature for ONAP Casablanca release and should be treated as unstable and subject to change in future releases.** +**For more information, see** :ref:`authorization`. + +**Key or trust store missing** + +:: + + org.onap.dcae.collectors.veshv.main | 2018-10-22T06:51:54.191Z | ERROR | Failed to start a server | java.io.FileNotFoundException: /etc/ves-hv/server.p12 (No such file or directory) + at java.io.FileInputStream.open0(Native Method) + at java.io.FileInputStream.open(FileInputStream.java:195) + at java.io.FileInputStream.(FileInputStream.java:138) + at org.onap.dcae.collectors.veshv.ssl.boundary.UtilsKt$streamFromFile$1.invoke(utils.kt:79) + at org.onap.dcae.collectors.veshv.ssl.boundary.UtilsKt$streamFromFile$1.invoke(utils.kt) + at org.onap.dcae.collectors.veshv.ssl.impl.SslFactories.loadKeyStoreFromFile(SslFactories.kt:50) + at org.onap.dcae.collectors.veshv.ssl.impl.SslFactories.keyManagerFactory(SslFactories.kt:43) + at org.onap.dcae.collectors.veshv.ssl.boundary.ServerSslContextFactory.jdkContext(ServerSslContextFactory.kt:42) + at org.onap.dcae.collectors.veshv.ssl.boundary.SslContextFactory.createSslContextWithConfiguredCerts(SslContextFactory.kt:49) + at org.onap.dcae.collectors.veshv.ssl.boundary.SslContextFactory.createSslContext(SslContextFactory.kt:39) + at org.onap.dcae.collectors.veshv.impl.socket.NettyTcpServer.configureServer(NettyTcpServer.kt:61) + at org.onap.dcae.collectors.veshv.impl.socket.NettyTcpServer.access$configureServer(NettyTcpServer.kt:46) + at org.onap.dcae.collectors.veshv.impl.socket.NettyTcpServer$start$1$ctx$1.invoke(NettyTcpServer.kt:52) + at org.onap.dcae.collectors.veshv.impl.socket.NettyTcpServer$start$1$ctx$1.invoke(NettyTcpServer.kt:46) + at org.onap.dcae.collectors.veshv.impl.socket.NettyTcpServer$sam$java_util_function_Consumer$0.accept(NettyTcpServer.kt) + at reactor.ipc.netty.tcp.TcpServer.(TcpServer.java:149) + at reactor.ipc.netty.tcp.TcpServer$Builder.build(TcpServer.java:278) + at org.onap.dcae.collectors.veshv.impl.socket.NettyTcpServer$start$1.invoke(NettyTcpServer.kt:53) + at org.onap.dcae.collectors.veshv.impl.socket.NettyTcpServer$start$1.invoke(NettyTcpServer.kt:46) + at arrow.effects.IO$Companion$invoke$1.invoke(IO.kt:28) + at arrow.effects.IO$Companion$invoke$1.invoke(IO.kt:22) + at arrow.effects.IORunLoop.step(IORunLoop.kt:50) + at arrow.effects.IO.unsafeRunTimed(IO.kt:109) + at arrow.effects.IO.unsafeRunSync(IO.kt:106) + at org.onap.dcae.collectors.veshv.utils.arrow.EffectsKt.unsafeRunEitherSync(effects.kt:50) + at org.onap.dcae.collectors.veshv.main.MainKt.main(main.kt:41) + | main + + +The above error is logged when key store is not provided. Similarly, when trust store is not provided, **/etc/ves-hv/trust.p12** file missing is logged. +**server.p12** and **trust.p12** are default names of key and trust stores. They can be changed by specifying **--trust-store** or **--key-store** command line arguments on deployment. + +==== + +**Invalid credentials** + +:: + + org.onap.dcae.collectors.veshv.main | 2018-10-22T06:59:24.039Z | ERROR | Failed to start a server | java.security.UnrecoverableKeyException: failed to decrypt safe contents entry: javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption. + ... 23 common frames omitted + Wrapped by: java.io.IOException: keystore password was incorrect + at sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:2059) + at java.security.KeyStore.load(KeyStore.java:1445) + at org.onap.dcae.collectors.veshv.ssl.impl.SslFactories.loadKeyStoreFromFile(SslFactories.kt:51) + at org.onap.dcae.collectors.veshv.ssl.impl.SslFactories.keyManagerFactory(SslFactories.kt:43) + at org.onap.dcae.collectors.veshv.ssl.boundary.ServerSslContextFactory.jdkContext(ServerSslContextFactory.kt:42) + at org.onap.dcae.collectors.veshv.ssl.boundary.SslContextFactory.createSslContextWithConfiguredCerts(SslContextFactory.kt:49) + at org.onap.dcae.collectors.veshv.ssl.boundary.SslContextFactory.createSslContext(SslContextFactory.kt:39) + at org.onap.dcae.collectors.veshv.impl.socket.NettyTcpServer.configureServer(NettyTcpServer.kt:61) + at org.onap.dcae.collectors.veshv.impl.socket.NettyTcpServer.access$configureServer(NettyTcpServer.kt:46) + at org.onap.dcae.collectors.veshv.impl.socket.NettyTcpServer$start$1$ctx$1.invoke(NettyTcpServer.kt:52) + at org.onap.dcae.collectors.veshv.impl.socket.NettyTcpServer$start$1$ctx$1.invoke(NettyTcpServer.kt:46) + at org.onap.dcae.collectors.veshv.impl.socket.NettyTcpServer$sam$java_util_function_Consumer$0.accept(NettyTcpServer.kt) + at reactor.ipc.netty.tcp.TcpServer.(TcpServer.java:149) + at reactor.ipc.netty.tcp.TcpServer$Builder.build(TcpServer.java:278) + at org.onap.dcae.collectors.veshv.impl.socket.NettyTcpServer$start$1.invoke(NettyTcpServer.kt:53) + at org.onap.dcae.collectors.veshv.impl.socket.NettyTcpServer$start$1.invoke(NettyTcpServer.kt:46) + at arrow.effects.IO$Companion$invoke$1.invoke(IO.kt:28) + at arrow.effects.IO$Companion$invoke$1.invoke(IO.kt:22) + at arrow.effects.IORunLoop.step(IORunLoop.kt:50) + at arrow.effects.IO.unsafeRunTimed(IO.kt:109) + at arrow.effects.IO.unsafeRunSync(IO.kt:106) + at org.onap.dcae.collectors.veshv.utils.arrow.EffectsKt.unsafeRunEitherSync(effects.kt:50) + at org.onap.dcae.collectors.veshv.main.MainKt.main(main.kt:41) + | main + + +Key or trust store password provided in configuration is invalid. + +==== + +**Invalid key store file** + +:: + + org.onap.dcae.collectors.veshv.main | 2018-10-22T09:11:38.200Z | ERROR | Failed to start a server | java.io.IOException: DerInputStream.getLength(): lengthTag=111, too big. + at sun.security.util.DerInputStream.getLength(DerInputStream.java:599) + at sun.security.util.DerValue.init(DerValue.java:391) + at sun.security.util.DerValue.(DerValue.java:332) + at sun.security.util.DerValue.(DerValue.java:345) + at sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1938) + at java.security.KeyStore.load(KeyStore.java:1445) + at org.onap.dcae.collectors.veshv.ssl.impl.SslFactories.loadKeyStoreFromFile(SslFactories.kt:51) + at org.onap.dcae.collectors.veshv.ssl.impl.SslFactories.keyManagerFactory(SslFactories.kt:43) + at org.onap.dcae.collectors.veshv.ssl.boundary.ServerSslContextFactory.jdkContext(ServerSslContextFactory.kt:42) + at org.onap.dcae.collectors.veshv.ssl.boundary.SslContextFactory.createSslContextWithConfiguredCerts(SslContextFactory.kt:49) + at org.onap.dcae.collectors.veshv.ssl.boundary.SslContextFactory.createSslContext(SslContextFactory.kt:39) + at org.onap.dcae.collectors.veshv.impl.socket.NettyTcpServer.configureServer(NettyTcpServer.kt:61) + at org.onap.dcae.collectors.veshv.impl.socket.NettyTcpServer.access$configureServer(NettyTcpServer.kt:46) + at org.onap.dcae.collectors.veshv.impl.socket.NettyTcpServer$start$1$ctx$1.invoke(NettyTcpServer.kt:52) + at org.onap.dcae.collectors.veshv.impl.socket.NettyTcpServer$start$1$ctx$1.invoke(NettyTcpServer.kt:46) + at org.onap.dcae.collectors.veshv.impl.socket.NettyTcpServer$sam$java_util_function_Consumer$0.accept(NettyTcpServer.kt) + at reactor.ipc.netty.tcp.TcpServer.(TcpServer.java:149) + at reactor.ipc.netty.tcp.TcpServer$Builder.build(TcpServer.java:278) + at org.onap.dcae.collectors.veshv.impl.socket.NettyTcpServer$start$1.invoke(NettyTcpServer.kt:53) + at org.onap.dcae.collectors.veshv.impl.socket.NettyTcpServer$start$1.invoke(NettyTcpServer.kt:46) + at arrow.effects.IO$Companion$invoke$1.invoke(IO.kt:28) + at arrow.effects.IO$Companion$invoke$1.invoke(IO.kt:22) + at arrow.effects.IORunLoop.step(IORunLoop.kt:50) + at arrow.effects.IO.unsafeRunTimed(IO.kt:109) + at arrow.effects.IO.unsafeRunSync(IO.kt:106) + at org.onap.dcae.collectors.veshv.utils.arrow.EffectsKt.unsafeRunEitherSync(effects.kt:50) + at org.onap.dcae.collectors.veshv.main.MainKt.main(main.kt:41) + | main + +The above is logged when provided keystore has invalid or corrupted content. +This log also appears when you try to use key store/trust store in archive format other than **PKCS12** (the only supported by **HV-VES** store type). + + -- 2.16.6