diff options
author | YohanPipereau <ypiperea@cisco.com> | 2019-06-17 14:55:16 +0200 |
---|---|---|
committer | YohanPipereau <ypiperea@cisco.com> | 2019-06-17 15:27:32 +0200 |
commit | b7b52e85c1b05a456119c11b9cf8e79d660194cc (patch) | |
tree | 3c218784e367bfdb43363fd2b04a4254d48c13a9 | |
parent | ec995e056d985f9ef54f92adbcbe626967912592 (diff) |
[gnmi] Remove gNMI from sweetcomb
Reasons for removing it:
-This gNMI server has been upgraded to a more stable form.
-It should live in a separate project because gNMI server is only
dependant of sysrepo not of VPP or sweetcomb.
-There were strange dependencies to this implementation like an XML parser
library.
-Capabilities RPC was answering wrong version number (1001 instead of
0.7.0) and encodings (ASCII vs JSON).
-Error codes were not return to client in case of problem of configuration.
Typically for element not found.
-This server uses sysrepo C API though bindings for C++ can be obtained.
-Documentation was missing.
-Set RPC could not identify a key in a YANG list because a YANG library
must be used for this not just a JSON parser.
-It would be difficult to adapt this server to support more encodings
than JSON. The new gNMI server offers an easier way to add encodings.
-Log control level has been implemented in the new gNMI server.
-Subscribe RPC has been added to the new server.
Link to the new gNMI server:
https://github.com/YohanPipereau/sysrepo_gnxi
Change-Id: If57ab23c776430552d9d70fea6681db1b56af525
Signed-off-by: YohanPipereau <ypiperea@cisco.com>
-rw-r--r-- | Makefile | 47 | ||||
-rw-r--r-- | src/cmake/FindGRPC.cmake | 76 | ||||
-rw-r--r-- | src/cmake/FindJSONCPP.cmake | 56 | ||||
-rw-r--r-- | src/cmake/FindPUGIXML.cmake | 52 | ||||
-rw-r--r-- | src/gnmi/CMakeLists.txt | 88 | ||||
-rw-r--r-- | src/gnmi/eventreciverbase.h | 78 | ||||
-rw-r--r-- | src/gnmi/gnmidata.cpp | 113 | ||||
-rw-r--r-- | src/gnmi/gnmidata.h | 64 | ||||
-rw-r--r-- | src/gnmi/gnmiserver.cpp | 483 | ||||
-rw-r--r-- | src/gnmi/gnmiserver.h | 88 | ||||
-rw-r--r-- | src/gnmi/log.cpp | 28 | ||||
-rw-r--r-- | src/gnmi/log.h | 35 | ||||
-rw-r--r-- | src/gnmi/main.cpp | 222 | ||||
-rw-r--r-- | src/gnmi/proto/CMakeLists.txt | 41 | ||||
-rw-r--r-- | src/gnmi/proto/gnmi.proto | 457 | ||||
-rw-r--r-- | src/gnmi/proto/gnmi_ext.proto | 74 | ||||
-rw-r--r-- | src/gnmi/sysrepoapi.cpp | 419 | ||||
-rw-r--r-- | src/gnmi/sysrepoapi.h | 109 | ||||
-rw-r--r-- | src/gnmi/sysrepoapipool.cpp | 42 | ||||
-rw-r--r-- | src/gnmi/sysrepoapipool.h | 48 | ||||
-rw-r--r-- | src/gnmi/xml2json.cpp | 326 | ||||
-rw-r--r-- | src/gnmi/xml2json.h | 91 |
22 files changed, 4 insertions, 3033 deletions
@@ -16,10 +16,6 @@ # -> libnetconf2 -> libyang # -> libssh (>=0.6.4) # -# gnmi -> libsysrepo -# -> protobuf (>=3) -# -> libjsoncpp -# # sysrepo -> libyang # -> libredblack or libavl # -> libev @@ -65,9 +61,6 @@ LIBSSH_DEB = zlib1g-dev #Sum dependencies DEB_DEPENDS = ${BUILD_DEB} ${NETOPEER2_DEB} ${CHECKSTYLE_DEB} ${SCVPP_DEB} ${SYSREPO_DEB} ${LIBSSH_DEB} -#Dependencies for grpc -DEB_GNMI_DEPENDS = libpugixml-dev libjsoncpp-dev libtool pkg-config - #Dependencies for automatic test DEB_TEST_DEPENDS = python3-pip python-pip libcurl4-openssl-dev libssh-dev \ libxml2-dev libxslt1-dev libtool-bin @@ -89,16 +82,14 @@ SYSREPO_RPM = libev-devel bison flex pcre-devel protobuf-c-devel protobuf-c-comp RPM_DEPENDS = ${BUILD_RPM} ${NETOPEER2_RPM} ${CHECKSTYLE_RPM} ${SCVPP_RPM} \ ${SYSREPO_RPM} -#Dependencies for grpc -RPM_GNMI_DEPENDS = pugixml jsoncpp libtool pugixml-devel jsoncpp-devel ${GRPC_RPM} - #Dependencies for automatic test RPM_TEST_DEPENDS = python36-devel python36-pip python-pip libxml2-devel \ libxslt-devel libtool which cmake3 -.PHONY: help install-dep install-dep-extra install-vpp install-models uninstall-models \ - install-dep-gnmi-extra build-scvpp build-plugins build-gnmi build-package docker \ - docker-test test clean distclean _clean_dl _libssh _libyang _libnetconf2 _sysrepo _netopeer2 +.PHONY: help install-dep install-dep-extra install-vpp install-models \ + uninstall-models build-scvpp build-plugins build-package docker \ + docker-test test clean distclean _clean_dl _libssh _libyang \ + _libnetconf2 _sysrepo _netopeer2 help: @echo "Make Targets:" @@ -107,13 +98,11 @@ help: @echo " install-vpp - install released vpp" @echo " install-models - install YANG models" @echo " uninstall-models - uninstall YANG models" - @echo " install-dep-gnmi-extra - install software extra dependencips from source code for gNMI" @echo " install-test-extra - install software extra dependencies from source code for YDK" @echo " build-scvpp - build scvpp" @echo " test-scvpp - unit test for scvpp" @echo " build-plugins - build plugins" @echo " test-plugins - integration test for sweetcomb plugins" - @echo " build-gnmi - build gNMIServer" @echo " build-package - build rpm or deb package" @echo " docker - build sweetcomb in docker enviroment, with optional arguments :" @echo " VPP_VERSION=release [master|release] specifies VPP version to be used" @@ -242,26 +231,6 @@ _clean_dl: install-dep-extra: _clean_dl _libssh _libyang _libnetconf2 _sysrepo _netopeer2 @cd ../ && rm -rf $(BR)/downloads -#Protobuf must not be compiled with multiple core, it requires too much memory -#gRPC can be compiled with cmake or autotools. autotools has been choosen -#if cmake is choosen use SSL, ZLIB distribution package and compile protobuf separately -install-dep-gnmi-extra: -ifeq ($(filter ubuntu debian,$(OS_ID)),$(OS_ID)) - @sudo -E apt-get $(APT_ARGS) -y --force-yes install $(DEB_GNMI_DEPENDS) -else ifeq ($(OS_ID),centos) - @sudo -E yum install -y $(RPM_GNMI_DEPENDS) -else - $(error "This option currently works only on Ubuntu, Debian, Centos or openSUSE systems") -endif - @rm -rf $(BR)/downloads - @mkdir -p $(BR)/downloads/&&cd $(BR)/downloads/\ - && git clone --depth=1 -b v1.16.1 https://github.com/grpc/grpc \ - && cd grpc && git submodule update --init \ - && cd third_party/protobuf \ - && ./autogen.sh && ./configure && make install \ - && cd ../.. make && make install \ - &&cd .. && rm -rf $(BR)/downloads - install-vpp: @echo "please install vpp as vpp's guide from source if failed" ifeq ($(PKG),deb) @@ -295,12 +264,6 @@ build-plugins: test-plugins: install-models @test/run_test.py --dir ./test/ -build-gnmi: - @mkdir -p $(BR)/build-gnmi/; cd $(BR)/build-gnmi/; \ - cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX:PATH=/usr $(WS_ROOT)/src/gnmi/;make; \ - make install; - @# NEW INSTRUCTIONS TO BUILD-GNMI MUST BE DECLARED ON A NEW LINE WITH '@' - build-package: @mkdir -p $(BR)/build-package/; cd $(BR)/build-package/;\ $(cmake) -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr \ @@ -339,13 +302,11 @@ clean: @if [ -d $(BR)/build-scvpp ] ; then cd $(BR)/build-scvpp && make clean; fi @if [ -d $(BR)/build-plugins ] ; then cd $(BR)/build-plugins && make clean; fi @if [ -d $(BR)/build-package ] ; then cd $(BR)/build-package && make clean; fi - @if [ -d $(BR)/build-gnmi ] ; then cd $(BR)/build-gnmi && make clean; fi distclean: @rm -rf $(BR)/build-scvpp @rm -rf $(BR)/build-plugins @rm -rf $(BR)/build-package - @rm -rf $(BR)/build-gnmi docker: @scripts/docker.sh diff --git a/src/cmake/FindGRPC.cmake b/src/cmake/FindGRPC.cmake deleted file mode 100644 index e45f969..0000000 --- a/src/cmake/FindGRPC.cmake +++ /dev/null @@ -1,76 +0,0 @@ -# From https://github.com/wastl/cmarmotta/blob/master/cmake/FindGRPC.cmake -# -# - Try to find gRPC -# Once done this will define -# -# GRPC_CPP_PLUGIN - Absolute path to grpc c++ plugin -# GRPCPP_LIBRARY - -# GPR_LIBRARY - -# -# VPP_FOUND - system has VPP -# VPP_INCLUDE_DIRS - the VPP include directory -# VPP_LIBRARIES - Link these to use LibSSH - -#Absolute path to grpc_cpp_plugin -find_program(GRPC_CPP_PLUGIN grpc_cpp_plugin) - -find_library(GRPC_LIBRARY NAMES grpc) -find_library(GRPCPP_LIBRARY NAMES grpc++) -find_library(GPR_LIBRARY NAMES gpr) -set(GRPC_LIBRARIES ${GRPCPP_LIBRARY} ${GRPC_LIBRARY} ${GPR_LIBRARY}) - -function(PROTOBUF_GENERATE_GRPC_CPP SRCS HDRS) - if(NOT ARGN) - message(SEND_ERROR "Error: PROTOBUF_GENERATE_GRPC_CPP() called without any proto files") - return() - endif() - - if(PROTOBUF_GENERATE_CPP_APPEND_PATH) # This variable is common for all types of output. - # Create an include path for each file specified - foreach(FIL ${ARGN}) - get_filename_component(ABS_FIL ${FIL} ABSOLUTE) - get_filename_component(ABS_PATH ${ABS_FIL} PATH) - list(FIND _protobuf_include_path ${ABS_PATH} _contains_already) - if(${_contains_already} EQUAL -1) - list(APPEND _protobuf_include_path -I ${ABS_PATH}) - endif() - endforeach() - else() - set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR}) - endif() - - if(DEFINED PROTOBUF_IMPORT_DIRS) - foreach(DIR ${PROTOBUF_IMPORT_DIRS}) - get_filename_component(ABS_PATH ${DIR} ABSOLUTE) - list(FIND _protobuf_include_path ${ABS_PATH} _contains_already) - if(${_contains_already} EQUAL -1) - list(APPEND _protobuf_include_path -I ${ABS_PATH}) - endif() - endforeach() - endif() - - set(${SRCS}) - set(${HDRS}) - foreach(FIL ${ARGN}) - get_filename_component(ABS_FIL ${FIL} ABSOLUTE) - get_filename_component(FIL_WE ${FIL} NAME_WE) - - list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.grpc.pb.cc") - list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.grpc.pb.h") - - add_custom_command( - OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.grpc.pb.cc" - "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.grpc.pb.h" - COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} - ARGS --grpc_out=${CMAKE_CURRENT_BINARY_DIR} - --plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN} - ${_protobuf_include_path} ${ABS_FIL} - DEPENDS ${ABS_FIL} ${PROTOBUF_PROTOC_EXECUTABLE} - COMMENT "Running gRPC C++ protocol buffer compiler on ${FIL}" - VERBATIM) - endforeach() - - set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE) - set(${SRCS} ${${SRCS}} PARENT_SCOPE) - set(${HDRS} ${${HDRS}} PARENT_SCOPE) -endfunction() diff --git a/src/cmake/FindJSONCPP.cmake b/src/cmake/FindJSONCPP.cmake deleted file mode 100644 index a342f08..0000000 --- a/src/cmake/FindJSONCPP.cmake +++ /dev/null @@ -1,56 +0,0 @@ -# - Try to find LibJSONCPP -# Once done this will define -# -# LIBJSONCPP_FOUND - system has LibJSONCPP -# LIBJSONCPP_INCLUDE_DIRS - the LibJSONCPP include directory -# LIBJSONCPP_LIBRARIES - Link these to use LIBJSONCPP - - -if (LIBJSONCPP_LIBRARIES AND LIBJSONCPP_INCLUDE_DIRS) - # in cache already - set(LIBJSONCPP_FOUND TRUE) -else (LIBJSONCPP_LIBRARIES AND LIBJSONCPP_INCLUDE_DIRS) - - find_path(LIBJSONCPP_INCLUDE_DIR - NAMES - json/json.h - PATHS - /usr/include - /usr/local/include - /usr/include/jsoncpp - /opt/local/include - ${CMAKE_INCLUDE_PATH} - ${CMAKE_INSTALL_PREFIX}/include - ) - - find_library(LIBJSONCPP_LIBRARY - NAMES - jsoncpp - PATHS - /usr/lib - /usr/lib64 - /usr/lib/x86_64-linux-gnu - /usr/local/lib - /usr/local/lib64 - /opt/local/lib - ${CMAKE_LIBRARY_PATH} - ${CMAKE_INSTALL_PREFIX}/lib - ) - - if (LIBJSONCPP_INCLUDE_DIR AND LIBJSONCPP_LIBRARY) - set(LIBJSONCPP_FOUND TRUE) - else (LIBJSONCPP_INCLUDE_DIR AND LIBJSONCPP_LIBRARY) - set(LIBJSONCPP_FOUND FALSE) - endif (LIBJSONCPP_INCLUDE_DIR AND LIBJSONCPP_LIBRARY) - - set(LIBJSONCPP_INCLUDE_DIRS ${LIBJSONCPP_INCLUDE_DIR}) - set(LIBJSONCPP_LIBRARIES ${LIBJSONCPP_LIBRARY}) - - # show the LIBJSONCPP_INCLUDE_DIRS and LIBJSONCPP_LIBRARIES variables only in the advanced view - mark_as_advanced(LIBJSONCPP_INCLUDE_DIRS LIBJSONCPP_LIBRARIES) - -endif (LIBJSONCPP_LIBRARIES AND LIBJSONCPP_INCLUDE_DIRS) - - - - diff --git a/src/cmake/FindPUGIXML.cmake b/src/cmake/FindPUGIXML.cmake deleted file mode 100644 index dc7c86b..0000000 --- a/src/cmake/FindPUGIXML.cmake +++ /dev/null @@ -1,52 +0,0 @@ -# - Try to find LibPUGIXML -# Once done this will define -# -# LIBPUGIXML_FOUND - system has LibPUGIXML -# LIBPUGIXML_INCLUDE_DIRS - the LibPUGIXML include directory -# LIBPUGIXML_LIBRARIES - Link these to use LIBPUGIXML - -if (LIBPUGIXML_LIBRARIES AND LIBPUGIXML_INCLUDE_DIRS) - # in cache already - set(LIBPUGIXML_FOUND TRUE) -else (LIBPUGIXML_LIBRARIES AND LIBPUGIXML_INCLUDE_DIRS) - - find_path(LIBPUGIXML_INCLUDE_DIR - NAMES - pugixml.hpp - PATHS - /usr/include - /usr/local/include - /opt/local/include - ${CMAKE_INCLUDE_PATH} - ${CMAKE_INSTALL_PREFIX}/include - ) - - find_library(LIBPUGIXML_LIBRARY - NAMES - pugixml - PATHS - /usr/lib - /usr/lib64 - /usr/local/lib - /usr/local/lib64 - /opt/local/lib - ${CMAKE_LIBRARY_PATH} - ${CMAKE_INSTALL_PREFIX}/lib - ) - - if (LIBPUGIXML_INCLUDE_DIR AND LIBPUGIXML_LIBRARY) - set(LIBPUGIXML_FOUND TRUE) - else (LIBPUGIXML_INCLUDE_DIR AND LIBPUGIXML_LIBRARY) - set(LIBPUGIXML_FOUND FALSE) - endif (LIBPUGIXML_INCLUDE_DIR AND LIBPUGIXML_LIBRARY) - - set(LIBPUGIXML_INCLUDE_DIRS ${LIBPUGIXML_INCLUDE_DIR}) - set(LIBPUGIXML_LIBRARIES ${LIBPUGIXML_LIBRARY}) - - # show the LIBPUGIXML_INCLUDE_DIRS and LIBPUGIXML_LIBRARIES variables only in the advanced view - mark_as_advanced(LIBPUGIXML_INCLUDE_DIRS LIBPUGIXML_LIBRARIES) - -endif (LIBPUGIXML_LIBRARIES AND LIBPUGIXML_INCLUDE_DIRS) - - - diff --git a/src/gnmi/CMakeLists.txt b/src/gnmi/CMakeLists.txt deleted file mode 100644 index 6a28529..0000000 --- a/src/gnmi/CMakeLists.txt +++ /dev/null @@ -1,88 +0,0 @@ -# -# Copyright (c) 2019 PANTHEON.tech. -# -# 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. -# - -cmake_minimum_required(VERSION 2.8) -project(gNMI-server) - -#C++11 is required by gNMI -set(CMAKE_CXX_STANDARD 11) - -# DEPENDENCIES -############## - -# Cmake find modules -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../cmake") - -find_package(PUGIXML REQUIRED) #use FindPUGIXML.cmake -find_package(JSONCPP REQUIRED) #use FindJSONCPP.cmake -find_package(PkgConfig) #official cmake module -pkg_check_modules(SYSREPO REQUIRED libsysrepo) #PkgConfig cmake module maccro - -if(LIBPUGIXML_FOUND) - message ("PUGIXML found") -else() - message (FATAL_ERROR "Cannot find PUGIXML") -endif() - -if(LIBJSONCPP_FOUND) - message ("LIBJSONCPP found") -else() - message (FATAL_ERROR "Cannot find LIBJSONCPP") -endif() - -# DEPENDENCIES & COMPILATION OF GNMI PROTO -########################################## - -# set compiler and linker flags -set(RIGOROUS_C_FLAGS "-Wlogical-op -Wold-style-cast -Wuseless-cast") -set(CMAKE_CXX_FLAGS "-Wall -Wextra -std=c++11 ${RIGOROUS_C_FLAGS}") -set(CMAKE_CXX_FLAGS_RELEASE "-Wall -Wextra -std=c++11 -DNDEBUG -O2 ${RIGOROUS_C_FLAGS}") -set(CMAKE_CXX_FLAGS_DEBUG "-Wall -Wextra -std=c++11 -g -O0 ${RIGOROUS_C_FLAGS}") - -add_subdirectory(proto) - -# COMPILER & LINKER -################### - -# Generate a compile_commands.json with compile options -set(CMAKE_EXPORT_COMPILE_COMMANDS 1) - -set(GNMI_SRC main.cpp - log.cpp - gnmiserver.cpp - sysrepoapi.cpp - sysrepoapipool.cpp - xml2json.cpp - gnmidata.cpp) - -add_executable(gnmi_server ${GNMI_SRC}) - -target_include_directories(gnmi_server PRIVATE ${PROTOBUF_INCLUDE_DIR} - ${CMAKE_CURRENT_BINARY_DIR}/proto - ${LIBPUGIXML_INCLUDE_DIR} - ${LIBJSONCPP_INCLUDE_DIR} - ${SYSREPO_INCLUDE_DIRS}) - -# link gnmi_server executable with protobuf, grpc, pugixml, sysrepo libraries -target_link_libraries(gnmi_server gnmi - ${LIBPUGIXML_LIBRARY} - ${LIBJSONCPP_LIBRARY} - ${SYSREPO_LIBRARIES}) - -# INSTALL -######### - -install(TARGETS gnmi_server RUNTIME DESTINATION bin) diff --git a/src/gnmi/eventreciverbase.h b/src/gnmi/eventreciverbase.h deleted file mode 100644 index 13f79ff..0000000 --- a/src/gnmi/eventreciverbase.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2019 PANTHEON.tech. - * - * 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. - */ - -#ifndef EVENTRECIVERBASE_H -#define EVENTRECIVERBASE_H - -#include <exception> -#include <iostream> - -class EventReceiverBase -{ -public: - virtual ~EventReceiverBase() {} -}; - -template<typename T> -class EventReceiver : public virtual EventReceiverBase -{ -public: - virtual void receiveWriteEvent(T *psender) = 0; -}; - -class EventSender -{ -public: - - template<typename T> - void registerReciver(T *receiver) { - pReceiver = receiver; - } - - void registerStream(void *stream) { - this->stream = stream; - } - - void *getStream() { - return stream; - } - - template<typename T> - void sendEvent(T* pSender) { - if (nullptr == pReceiver) { - throw std::runtime_error("Receiver is not register."); - } - - EventReceiver<T> *pCastedReceiver = - dynamic_cast<EventReceiver<T>*>(pReceiver); - pCastedReceiver->receiveWriteEvent(pSender); - } - -private: - EventReceiverBase *pReceiver = nullptr; - void *stream = nullptr; -}; - -template<typename T> -class BaseSender : public virtual EventSender -{ -public: - void send() { - sendEvent((T*) this); - } -}; - -#endif // EVENTRECIVERBASE_H diff --git a/src/gnmi/gnmidata.cpp b/src/gnmi/gnmidata.cpp deleted file mode 100644 index ae2bb18..0000000 --- a/src/gnmi/gnmidata.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2019 PANTHEON.tech. - * - * 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. - */ - -#include "gnmidata.h" - -gNMIData::ValueType gNMIData::dataType() const -{ - return dtype; -} - -void gNMIData::clean() -{ - dtype = ValueType::UnknownVal; - strData = ""; - intData = 0; - xpath = ""; -} - -void gNMIData::setXPath(const std::string& str, xPathType type) -{ - std::size_t pos = 0; - - xpath = str; - - if (xPathType::gNMIPath == type) { - return; - } - - while (std::string::npos != (pos = xpath.find(":", pos))) { - xpath.replace(pos, std::string(":").length(), "/"); - } -} - -void gNMIData::setValue(const std::string& str) -{ - dtype = ValueType::dStringVal; - strData = str; -} - -void gNMIData::setValue(int val) -{ - dtype = ValueType::dIntVal; - intData = val; -} - -std::string gNMIData::getXPath(gNMIData::xPathType type) const -{ - switch (type) { - case xPathType::gNMIPath: - return xpath; - - case xPathType::sysrepoPath: - return convertToSyrepoPath(); - - default: - break; - } - - return xpath; -} - -std::string gNMIData::getStr() const -{ - switch (dtype) { - case ValueType::dIntVal: - return std::to_string(getInt()); - - case ValueType::dStringVal: - return strData; - - case ValueType::UnknownVal: - default: - //TODO: I`m not sure with N/Al - return "N/A"; - } - - return "N/A"; -} - -int gNMIData::getInt() const -{ - return intData; -} - -std::string gNMIData::convertToSyrepoPath() const -{ - std::string str = xpath; - std::size_t pos = 0; - int i = 0; - - while (std::string::npos != (pos = str.find("/", pos))) { - if (1 == i++) { - str.replace(pos, std::string("/").length(), ":"); - break; - } - pos++; - } - - return str; -} diff --git a/src/gnmi/gnmidata.h b/src/gnmi/gnmidata.h deleted file mode 100644 index 82c60c8..0000000 --- a/src/gnmi/gnmidata.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2019 PANTHEON.tech. - * - * 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. - */ - -#ifndef GNMIDATA_H -#define GNMIDATA_H - -#include <string> - -/** - * @todo write docs - */ -class gNMIData -{ -public: - enum class ValueType { - dStringVal, - dIntVal, - UnknownVal - }; - - enum class xPathType { - gNMIPath, - sysrepoPath, - }; - -public: - gNMIData() = default; - ~gNMIData() = default; - - ValueType dataType() const; - void clean(); - - void setXPath(const std::string &str, xPathType type = xPathType::gNMIPath); - void setValue(const std::string &str); - void setValue(int val); - - std::string getXPath(xPathType type = xPathType::gNMIPath) const; - std::string getStr() const; - int getInt() const; - -private: - std::string convertToSyrepoPath() const; - -private: - ValueType dtype = ValueType::UnknownVal; - int intData; - std::string strData; - std::string xpath; -}; - -#endif // GNMIDATA_H diff --git a/src/gnmi/gnmiserver.cpp b/src/gnmi/gnmiserver.cpp deleted file mode 100644 index 44ce6c5..0000000 --- a/src/gnmi/gnmiserver.cpp +++ /dev/null @@ -1,483 +0,0 @@ -/* - * Copyright (c) 2019 PANTHEON.tech. - * - * 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. - */ - -#include "gnmiserver.h" -#include "log.h" -#include "xml2json.h" - -#include <iostream> -#include <exception> -#include <chrono> -#include <ctime> -#include <ratio> -#include <list> - -#include <sysrepo.h> -#include <sysrepo/xpath.h> - -gNMIServer::gNMIServer(SysrepoAPI& sysrepo) - : sysrepo(sysrepo) -{ -} - -grpc::Status gNMIServer::Capabilities(grpc::ServerContext* context, - const gnmi::CapabilityRequest* request, - gnmi::CapabilityResponse* reply) -{ - DEBUG("Capabilities message"); - - if (0 < request->extension_size()) { - //TODO; - } - - sysrepo.createSession(); - const auto &ss = sysrepo.getSchemas(); - - for (const auto schema : ss) { - auto model = reply->add_supported_models(); - model->set_name(schema.moduleName); - model->set_version(schema.revision); - } - - reply->add_supported_encodings(gnmi::Encoding::ASCII); - - //FIXME: I`m not sure, if this is a correct version of gnmi. - reply->set_gnmi_version(std::to_string(gnmi::kGnmiServiceFieldNumber)); - - sysrepo.closeSession(); - - return Status::OK; -} - -grpc::Status gNMIServer::Get(grpc::ServerContext* context, - const gnmi::GetRequest* request, - gnmi::GetResponse* reply) -{ - DEBUG("Get message"); - - std::cout << gnmi::GetRequest_DataType_Name(request->type()) << std::endl; - - try { - sysrepo.createSession(); - - auto &prefix = request->prefix(); - dataPrefix = convertToXPath(prefix); - DEBUG("Prefix: %s", dataPrefix.c_str()); - - DEBUG("Data type: %s", - request->DataType_Name(request->type()).c_str()); - DEBUG("Encoding: %s", gnmi::Encoding_Name(request->encoding()).c_str()); - - for (const auto &model : request->use_models()) { - DEBUG("Model, name: %s, organization: %s, version: %s", - model.name().c_str(), model.organization().c_str(), - model.version().c_str()); - } - -// for (const auto &extension : request->extension()) { -// DEBUG(ex); -// } - - if (0 < request->path().size()) { - for (const auto &path : request->path()) { - std::string strPath = convertToXPath(path); - vData.clean(); - vData.setXPath(dataPrefix + strPath); - sysrepo.addData(vData); - sysrepo.getItemMessage(); - - auto notification = reply->add_notification(); - - notification->set_timestamp(getTimeNanosec()); - auto elem = notification->mutable_prefix(); - xpathTogNMIEl(dataPrefix, *elem); - - const auto &oData = sysrepo.getOutputData(); - - for (const auto &data : oData) { - auto nupdate = notification->add_update(); - xpathTogNMIEl(data.getXPath(), *nupdate->mutable_path()); - auto uval = nupdate->mutable_val(); - uval->set_string_val(data.getStr()); - } - } - } - - sysrepo.cleanData(); - sysrepo.closeSession(); - } catch (...) { - sysrepo.cleanData(); - sysrepo.closeSession(); - return Status::CANCELLED; - } - - return Status::OK; -} - -//TODO: Need handle INVALID operation, somehow, but how???? -grpc::Status gNMIServer::Set(grpc::ServerContext* context, - const gnmi::SetRequest* request, - gnmi::SetResponse* reply) -{ - DEBUG("Set message"); - std::string path; - - reply->set_timestamp(getTimeNanosec()); - - auto prefix = reply->mutable_prefix(); - prefix->add_elem(); - - try { - sysrepo.createSession(SR_DS_RUNNING); - - dataPrefix = convertToXPath(request->prefix()); - - if (0 < request->delete__size()) { - for (const auto &del : request->delete_()) { - vData.clean(); - path = convertToXPath(del); - vData.setXPath(dataPrefix + path); - DEBUG("Delete: %s", vData.getXPath().c_str()); - sysrepo.addData(vData); - } - sysrepo.setItemMessage(); - - const auto &oData = sysrepo.getOutputData(); - for (const auto &data : oData) { - auto updateResult = reply->add_response(); - updateResult->set_op(gnmi::UpdateResult::DELETE); - xpathTogNMIEl(data.getXPath(), *updateResult->mutable_path()); - } - - sysrepo.cleanData(); - } - - if (0 < request->replace_size()) { - for (const auto &replace : request->replace()) { - vData.clean(); - handleUpdateMessage(replace); - DEBUG("Replace : %s", vData.getXPath().c_str()); - sysrepo.addData(vData); - } - sysrepo.setItemMessage(); - - const auto &oData = sysrepo.getOutputData(); - for (const auto &data : oData) { - auto updateResult = reply->add_response(); - updateResult->set_op(gnmi::UpdateResult::REPLACE); - xpathTogNMIEl(data.getXPath(), *updateResult->mutable_path()); - } - - sysrepo.cleanData(); - } - - if (0 < request->update_size()) { - for (const auto &update : request->update()) { - vData.clean(); - handleUpdateMessage(update); - DEBUG("Update: %s", vData.getXPath().c_str()); -// sysrepo.addData(vData); - XML2JSON json; - json.setData(vData.getStr()); - json.setPrefix(vData.getXPath()); - auto &gdatas = json.getgNMIData(); - for (const auto &gdata : gdatas) { - DEBUG("Data xpath: %s, data: %s", gdata.getXPath().c_str(), - gdata.getStr().c_str()); - sysrepo.addData(gdata); - } -// DEBUG("%s", json.getXML().c_str()); - } - sysrepo.setItemMessage(); - - const auto &oData = sysrepo.getOutputData(); - for (const auto &data : oData) { - auto updateResult = reply->add_response(); - updateResult->set_op(gnmi::UpdateResult::UPDATE); - xpathTogNMIEl(data.getXPath(), *updateResult->mutable_path()); - } - - sysrepo.cleanData(); - } - - //TODO: Need some special handling for sysrepo - sysrepo.commit(); - sysrepo.closeSession(); - } catch (...) { - sysrepo.cleanData(); - sysrepo.closeSession(); - return Status::CANCELLED; - } - - return Status::OK; -} - -grpc::Status gNMIServer::Subscribe(grpc::ServerContext* context, - ServerReaderWriter<gnmi::SubscribeResponse, - gnmi::SubscribeRequest>* stream) -{ - DEBUG("Subscribe message"); - - gnmi::SubscribeRequest request; - - try { - sysrepo.registerReciver<gNMIServer>(this); - sysrepo.registerStream(stream); - - sysrepo.createSession(SR_DS_RUNNING); - while (stream->Read(&request)) { - switch (request.request_case()) { - case gnmi::SubscribeRequest::kAliases: - break; - - case gnmi::SubscribeRequest::kPoll: - break; - - case gnmi::SubscribeRequest::kSubscribe: - subscibeList(request.subscribe()); - break; - - case gnmi::SubscribeRequest::REQUEST_NOT_SET: - break; - - default: - DEBUG("Unknown request case."); - break; - } - } - } catch (...) { - sysrepo.cleanData(); - sysrepo.closeSession(); - return Status::CANCELLED; - } - - sysrepo.cleanData(); - sysrepo.closeSession(); - DEBUG("Subscribe message end"); - - return Status::OK; -} - -void gNMIServer::subscibeList(const gnmi::SubscriptionList& slist) -{ - std::string prefix = convertToXPath(slist.prefix()); - - if (0 < slist.subscription_size()) { - for (const auto &sub : slist.subscription()) { - vData.clean(); - vData.setXPath(prefix + convertToXPath(sub.path())); - //TODO: Call sysrepo event - - DEBUG("Subs Mode: %s", - gnmi::SubscriptionMode_Name(sub.mode()).c_str()); - DEBUG("Subs xpath: %s", vData.getXPath().c_str()); - sysrepo.addData(vData); - sysrepo.eventSubscribeMessage(); - } - } - - DEBUG("Subscribe list mode: %s", slist.Mode_Name(slist.mode()).c_str()); - - if (0 < slist.use_models_size()) { - for (const auto &umod : slist.use_models()) { - DEBUG("Name: %s, Organization: %s, Version: %s", - umod.name().c_str(), umod.organization().c_str(), - umod.version().c_str()); - } - } - - DEBUG("Encoding: %s", gnmi::Encoding_Name(slist.encoding()).c_str()); - - DEBUG("Update only: %d", slist.updates_only()); -} - -void gNMIServer::receiveWriteEvent(SysrepoAPI* psender) -{ - gnmi::SubscribeResponse response; - ServerReaderWriter<gnmi::SubscribeResponse, gnmi::SubscribeRequest>* stream; - - stream = (ServerReaderWriter<gnmi::SubscribeResponse, - gnmi::SubscribeRequest>*) psender->getStream(); - - auto sData = psender->getOutputData(); - auto update = response.mutable_update(); - - update->set_timestamp(getTimeNanosec()); - auto elem = update->mutable_prefix(); - - xpathTogNMIEl("/", *elem); - for (const auto &data : sData) { - DEBUG("XPath: %s, value: %s", - data.getXPath().c_str(), data.getStr().c_str()); - auto nupdate = update->add_update(); - xpathTogNMIEl(data.getXPath(), *nupdate->mutable_path()); - auto val = nupdate->mutable_val(); - val->set_string_val(data.getStr()); - } - - psender->cleanData(); - stream->Write(response); -} - -void gNMIServer::parsePathMsg(const gnmi::Path& path) -{ - if (0 >= path.elem_size()) { - DEBUG("Path is empty"); - return; - } - -} - -std::string gNMIServer::convertToXPath(const gnmi::Path& path) -{ - std::string str = "/"; - - if (0 < path.elem_size()) { - for (const auto &elm : path.elem()) { - str += elm.name(); - - for (const auto &el : elm.key()) { - str += "[" + el.first + "='" + el.second + "']"; - } - - str += "/"; - } - } - str.pop_back(); - - return str; -} - -void gNMIServer::printPath(const gnmi::Path& path) -{ - if (0 < path.element().size()) { - for (const auto &element : path.element()) { - DEBUG("Element: %s", element.c_str()); - } - } - - if (0 < path.elem_size()) { - for (const auto &elm : path.elem()) { - DEBUG("Elm name: %ss", elm.name().c_str()); - for (const auto &el : elm.key()) { - DEBUG("El key: %s, val: %s", el.first.c_str(), - el.second.c_str()); - } - } - } -} - -void gNMIServer::handleUpdateMessage(const gnmi::Update& msg) -{ - vData.setXPath(dataPrefix + convertToXPath(msg.path())); - - if (msg.has_val()) { - handleTypeValueMsg(msg.val()); - } -} - -void gNMIServer::handleTypeValueMsg(const gnmi::TypedValue& msg) -{ - DEBUG("Val case: %d", msg.value_case()); - - switch (msg.value_case()) { - case gnmi::TypedValue::ValueCase::kStringVal: - vData.setValue(msg.string_val()); - break; - - case gnmi::TypedValue::ValueCase::kIntVal: - break; - - case gnmi::TypedValue::ValueCase::kUintVal: - break; - - case gnmi::TypedValue::ValueCase::kBoolVal: - break; - - case gnmi::TypedValue::ValueCase::kBytesVal: - break; - - case gnmi::TypedValue::ValueCase::kFloatVal: - break; - - case gnmi::TypedValue::ValueCase::kDecimalVal: - break; - - case gnmi::TypedValue::ValueCase::kLeaflistVal: - break; - - case gnmi::TypedValue::ValueCase::kAnyVal: - break; - - case gnmi::TypedValue::ValueCase::kJsonVal: - break; - - case gnmi::TypedValue::ValueCase::kJsonIetfVal: - vData.setValue(msg.json_ietf_val()); - break; - - case gnmi::TypedValue::ValueCase::kAsciiVal: - break; - - case gnmi::TypedValue::ValueCase::kProtoBytes: - break; - - case gnmi::TypedValue::ValueCase::VALUE_NOT_SET: - break; - - default: - DEBUG("Unknown type."); - break; - } -} - -void gNMIServer::xpathTogNMIEl(const std::string& str, gnmi::Path& path) -{ - sr_xpath_ctx_t state; - std::string tmp(str); - const char *xpath = tmp.c_str(); - char *name; - - if ((name = sr_xpath_next_node((char *)xpath, &state)) == NULL) { - DEBUG("Empty XPATH, xpath: %s", xpath); - return; - } - - do { - auto pathEl = path.add_elem(); - pathEl->set_name(name); - - const char *key_name; - while ((key_name = sr_xpath_next_key_name(NULL, &state)) != NULL) { - std::string key(key_name); - const char *key_value = sr_xpath_next_key_value(NULL, &state); - (*pathEl->mutable_key())[key] = key_value; - } - } while ((name = sr_xpath_next_node(NULL, &state)) != NULL); - - sr_xpath_recover(&state); -} - - -uint64_t gNMIServer::getTimeNanosec() -{ - using namespace std::chrono; - - std::uint64_t tm = high_resolution_clock::now().time_since_epoch() / - nanoseconds(1); - - return tm; -} diff --git a/src/gnmi/gnmiserver.h b/src/gnmi/gnmiserver.h deleted file mode 100644 index 7dc1339..0000000 --- a/src/gnmi/gnmiserver.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2019 PANTHEON.tech. - * - * 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. - */ - -#ifndef GNMISERVER_H -#define GNMISERVER_H - -#include <grpcpp/grpcpp.h> - -#include "gnmi.pb.h" -#include "gnmi.grpc.pb.h" -#include "sysrepoapi.h" -#include "gnmidata.h" -#include "eventreciverbase.h" - -#include <string> - -using grpc::Server; -using grpc::ServerBuilder; -using grpc::ServerContext; -using grpc::ServerReaderWriter; -using grpc::Status; - -using gnmi::gNMI; -using gnmi::CapabilityRequest; -using gnmi::CapabilityResponse; -using gnmi::GetRequest; -using gnmi::GetResponse; -using gnmi::SetRequest; -using gnmi::SetResponse; -using gnmi::SubscribeRequest; -using gnmi::SubscribeResponse; - -/** - * @todo write docs - */ -class gNMIServer final : public gNMI::Service, - public virtual EventReceiver<SysrepoAPI> -{ -public: - gNMIServer(SysrepoAPI &sysrepo); - - Status Capabilities(ServerContext* context, - const CapabilityRequest* request, - CapabilityResponse* reply) override; - Status Get(ServerContext* context, const GetRequest* request, - GetResponse* reply) override; - Status Set(ServerContext* context, const SetRequest* request, - SetResponse* reply) override; - Status Subscribe(ServerContext* context, - ServerReaderWriter<SubscribeResponse, - SubscribeRequest>* stream) override; - - void receiveWriteEvent(SysrepoAPI * psender) override; - -private: - void parsePathMsg(const gnmi::Path &path); - void printPath(const gnmi::Path &path); - std::string convertToXPath(const gnmi::Path &path); - - void subscibeList(const gnmi::SubscriptionList &slist); - - void handleUpdateMessage(const gnmi::Update &msg); - void handleTypeValueMsg(const gnmi::TypedValue &msg); - - void xpathTogNMIEl(const std::string &str, gnmi::Path &path); - - uint64_t getTimeNanosec(); - -private: - SysrepoAPI &sysrepo; - gNMIData vData; - std::string dataPrefix; -}; - -#endif // GNMISERVER_H diff --git a/src/gnmi/log.cpp b/src/gnmi/log.cpp deleted file mode 100644 index 86d26b5..0000000 --- a/src/gnmi/log.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2019 PANTHEON.tech. - * - * 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. - */ - -#include "log.h" - -void init_log(int option) -{ - openlog(NULL, option, LOG_DAEMON); -} - -void close_log() -{ - closelog(); -} - diff --git a/src/gnmi/log.h b/src/gnmi/log.h deleted file mode 100644 index 0bb01f0..0000000 --- a/src/gnmi/log.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2019 PANTHEON.tech. - * - * 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. - */ - -#ifndef __LOG_H__ -#define __LOG_H__ - -#include <stdio.h> -#include <syslog.h> - -#define ERROR(fmt, ...) \ - do { syslog(LOG_ERR, "%s:%d:%s():[ERROR]:" fmt "\n", __FILE__, \ - __LINE__, __func__, ##__VA_ARGS__); } while (0) - -#define DEBUG(fmt, ...) \ - do { syslog(LOG_DEBUG, "%s:%d:%s():[DEBUG]:" fmt "\n", __FILE__, \ - __LINE__, __func__, ##__VA_ARGS__); } while (0) - -void init_log(int option); - -void close_log(); - -#endif diff --git a/src/gnmi/main.cpp b/src/gnmi/main.cpp deleted file mode 100644 index 8115732..0000000 --- a/src/gnmi/main.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (c) 2019 PANTHEON.tech. - * - * 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. - */ - -#include "log.h" -#include "gnmiserver.h" -#include "sysrepoapipool.h" - -#include <argp.h> -#include <iostream> -#include <sstream> -#include <fstream> -#include <string> -#include <map> -#include <arpa/inet.h> - -const char *argp_program_version = "0.0.1"; -// const char *argp_program_bug_address = "<your@email.address>"; -static char doc[] = "gNMI server implementation/integration for FD.io vpp "; -static char args_doc[] = ""; -static struct argp_option options[] = { - {"address", 'a', "x.x.x.x", 0, "Destination IPv4 address"}, - {"port", 'p', "port", 0, "Destination port"}, - {"sysrepo", 's', "name", 0, "Sysrepo name"}, - {"ssl/tls", 't', NULL, 0, "Enable ssl/tls"}, - {"serverKey", 'k', "file", 0, "Server Key"}, - {"serverCerts", 'c', "file", 0, "Server Certs"}, - {"rootCert", 'r', "file", 0, "Root Cert"}, - { 0 } -}; - -struct arguments { - std::string ip_address; - std::string port; - std::string sysrepo_name; - bool enable_ssltls; - std::string server_key; - std::string server_certs; - std::string root_cert; - - arguments() : ip_address{}, port{}, sysrepo_name{}, enable_ssltls{false}, - server_key{}, server_certs{}, root_cert{} {} -}; - -static error_t check_ip(const std::string &str) -{ - struct sockaddr_in sa; - int rc = inet_pton(AF_INET, str.c_str(), &(sa.sin_addr)); - if (1 != rc) { - ERROR("Wrong IPv4 address format."); - return ARGP_KEY_ERROR; - } - - return ARGP_KEY_ARG; -} - -static error_t parse_opt(int key, char *arg, struct argp_state *state) -{ - error_t rc = 0; - struct arguments *arguments = (struct arguments*) state->input; - - switch (key) { - case 'a': - arguments->ip_address = std::string(arg); - rc = check_ip(arguments->ip_address); - break; - - case 'p': - arguments->port = std::string(arg); - break; - - case 't': - arguments->enable_ssltls = true; - break; - - case 's': - arguments->sysrepo_name = std::string(arg); - break; - - case 'k': - arguments->server_key = std::string(arg); - break; - - case 'c': - arguments->server_certs = std::string(arg); - break; - - case 'r': - arguments->root_cert = std::string(arg); - break; - - case ARGP_KEY_ARG: - return rc; - - default: - return ARGP_ERR_UNKNOWN; - } - - return rc; -} - -static struct argp argp = { options, parse_opt, args_doc, doc, 0, 0, 0 }; -SysrepoApiPool sysrepoPoll; - -static std::string read_cert(const std::string &file) -{ - std::ifstream fo(file); - std::stringstream str; - - str << fo.rdbuf(); - - return str.str(); -} - -void RunServer(const struct arguments &arg) -{ - std::string server_address = std::string(arg.ip_address) + - std::string(":") + std::string(arg.port); - gNMIServer service(sysrepoPoll.get(arg.sysrepo_name)); - ServerBuilder builder; - - try { - if (arg.enable_ssltls) { - grpc::SslServerCredentialsOptions::PemKeyCertPair pkcp; - - pkcp.private_key = read_cert(arg.server_key); - pkcp.cert_chain = read_cert(arg.server_certs); - - grpc::SslServerCredentialsOptions ssl_opts; - ssl_opts.pem_root_certs = ""; - ssl_opts.pem_key_cert_pairs.push_back(pkcp); - ssl_opts.pem_root_certs = read_cert(arg.root_cert); - - auto creds = grpc::SslServerCredentials(ssl_opts); - - builder.AddListeningPort(server_address, creds); - } else { - - // Listen on the given address without any authentication mechanism. - builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); - } - // Register "service" as the instance through which we'll communicate with - // clients. In this case it corresponds to an *synchronous* service. - builder.RegisterService(&service); - // Finally assemble the server. - // builder. - std::unique_ptr<Server> server(builder.BuildAndStart()); - - if (server != nullptr) - { - std::cout << "Server listening on " << server_address << std::endl; - // Wait for the server to shutdown. Note that some other thread must be - // responsible for shutting down the server for this call to ever return. - server->Wait(); - } - else - { - throw std::logic_error("Failed to create Server."); - } - } catch(...) { - ERROR("Failed to create Server."); - exit(-1); - } - -} - -int main(int argc, char **argv) -{ - struct arguments arguments; - - init_log(LOG_PERROR); - - error_t rc = argp_parse(&argp, argc, argv, 0, 0, &arguments); - if (ARGP_KEY_ARG != rc) { - argp_help(&argp, stdout, ARGP_HELP_SEE, argv[0]); - exit(-1); - } - - if (arguments.ip_address.empty() || arguments.port.empty()) { - ERROR("IP address and port must be set."); - argp_help(&argp, stdout, ARGP_HELP_SEE, argv[0]); - exit(-1); - } - - if (arguments.enable_ssltls) { - if (arguments.server_key.empty()) { - ERROR("Server key must be set."); - argp_help(&argp, stdout, ARGP_HELP_SEE, argv[0]); - exit(-1); - } - - if (arguments.server_certs.empty()) { - ERROR("Server certificate must be set."); - argp_help(&argp, stdout, ARGP_HELP_SEE, argv[0]); - exit(-1); - } - } - - auto &sysrepo = sysrepoPoll.get(arguments.sysrepo_name); - sysrepo.connect(); - - std::string destination = std::string(arguments.ip_address) + - std::string(":") + std::string(arguments.port); - - RunServer(arguments); - - close_log(); - - return 0; -} diff --git a/src/gnmi/proto/CMakeLists.txt b/src/gnmi/proto/CMakeLists.txt deleted file mode 100644 index e68a2c9..0000000 --- a/src/gnmi/proto/CMakeLists.txt +++ /dev/null @@ -1,41 +0,0 @@ -# DEPENDENCIES -############## - -# Require at least Protobuf 3 for gNMI -find_package(Protobuf 3.0.0 REQUIRED) #official cmake module -include_directories(${PROTOBUF_INCLUDE_DIRS}) -include_directories(${CMAKE_CURRENT_BINARY_DIR}) - -message(STATUS "Using protobuf ${protobuf_VERSION}") - -# Require at least gRPC 1.12.0, maybe earlier can be used - -# Official gRPCConfig.cmake installed by gRPC only if compiled with cmake -# Use our own FindGRPC.cmake instead -find_package(GRPC 1.12.0 REQUIRED) - -get_filename_component(gnmi_proto "gnmi.proto" ABSOLUTE) -get_filename_component(gnmi_ext_proto "gnmi_ext.proto" ABSOLUTE) - -# GENERATION OF SOURCE FILES -############################ - -# Official generator -protobuf_generate_cpp(gnmi_proto_srcs gnmi_proto_hdrs ${gnmi_proto}) -protobuf_generate_cpp(gnmi_ext_proto_srcs gnmi_ext_proto_hdrs ${gnmi_ext_proto}) - -# Custom generator: Official `protobuf_generate_cpp` can't use grpc plugins -PROTOBUF_GENERATE_GRPC_CPP(gnmi_grpc_srcs gnmi_grpc_hdrs ${gnmi_proto}) -PROTOBUF_GENERATE_GRPC_CPP(gnmi_ext_grpc_srcs gnmi_ext_grpc_hdrs ${gnmi_ext_proto}) - -# LINK OPTIONS FOR GNMI-SERVER -############################## - -# Include generated protobuf C++ files -include_directories("${CMAKE_CURRENT_BINARY_DIR}") - -#Create a new library named gnmi -add_library(gnmi ${gnmi_grpc_srcs} ${gnmi_ext_grpc_srcs} ${gnmi_proto_srcs} ${gnmi_ext_proto_srcs}) - -#Link our new gnmi library with grpc and protobuf libraries -target_link_libraries(gnmi ${GRPCPP_LIBRARY} ${PROTOBUF_LIBRARIES}) diff --git a/src/gnmi/proto/gnmi.proto b/src/gnmi/proto/gnmi.proto deleted file mode 100644 index 99acce6..0000000 --- a/src/gnmi/proto/gnmi.proto +++ /dev/null @@ -1,457 +0,0 @@ -// -// Copyright 2016 Google Inc. All Rights Reserved. -// -// 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. -// -syntax = "proto3"; - -import "google/protobuf/any.proto"; -import "google/protobuf/descriptor.proto"; -import "gnmi_ext.proto"; - -// Package gNMI defines a service specification for the gRPC Network Management -// Interface. This interface is defined to be a standard interface via which -// a network management system ("client") can subscribe to state values, -// retrieve snapshots of state information, and manipulate the state of a data -// tree supported by a device ("target"). -// -// This document references the gNMI Specification which can be found at -// http://github.com/openconfig/reference/blob/master/rpc/gnmi -package gnmi; - -// Define a protobuf FileOption that defines the gNMI service version. -extend google.protobuf.FileOptions { - // The gNMI service semantic version. - string gnmi_service = 1001; -} - -// gNMI_service is the current version of the gNMI service, returned through -// the Capabilities RPC. -option (gnmi_service) = "0.7.0"; - -service gNMI { - // Capabilities allows the client to retrieve the set of capabilities that - // is supported by the target. This allows the target to validate the - // service version that is implemented and retrieve the set of models that - // the target supports. The models can then be specified in subsequent RPCs - // to restrict the set of data that is utilized. - // Reference: gNMI Specification Section 3.2 - rpc Capabilities(CapabilityRequest) returns (CapabilityResponse); - // Retrieve a snapshot of data from the target. A Get RPC requests that the - // target snapshots a subset of the data tree as specified by the paths - // included in the message and serializes this to be returned to the - // client using the specified encoding. - // Reference: gNMI Specification Section 3.3 - rpc Get(GetRequest) returns (GetResponse); - // Set allows the client to modify the state of data on the target. The - // paths to modified along with the new values that the client wishes - // to set the value to. - // Reference: gNMI Specification Section 3.4 - rpc Set(SetRequest) returns (SetResponse); - // Subscribe allows a client to request the target to send it values - // of particular paths within the data tree. These values may be streamed - // at a particular cadence (STREAM), sent one off on a long-lived channel - // (POLL), or sent as a one-off retrieval (ONCE). - // Reference: gNMI Specification Section 3.5 - rpc Subscribe(stream SubscribeRequest) returns (stream SubscribeResponse); -} - -// Notification is a re-usable message that is used to encode data from the -// target to the client. A Notification carries two types of changes to the data -// tree: -// - Deleted values (delete) - a set of paths that have been removed from the -// data tree. -// - Updated values (update) - a set of path-value pairs indicating the path -// whose value has changed in the data tree. -// Reference: gNMI Specification Section 2.1 -message Notification { - int64 timestamp = 1; // Timestamp in nanoseconds since Epoch. - Path prefix = 2; // Prefix used for paths in the message. - // An alias for the path specified in the prefix field. - // Reference: gNMI Specification Section 2.4.2 - string alias = 3; - repeated Update update = 4; // Data elements that have changed values. - repeated Path delete = 5; // Data elements that have been deleted. - // This notification contains a set of paths that are always updated together - // referenced by a globally unique prefix. - bool atomic = 6; -} - -// Update is a re-usable message that is used to store a particular Path, -// Value pair. -// Reference: gNMI Specification Section 2.1 -message Update { - Path path = 1; // The path (key) for the update. - Value value = 2 [deprecated=true]; // The value (value) for the update. - TypedValue val = 3; // The explicitly typed update value. - uint32 duplicates = 4; // Number of coalesced duplicates. -} - -// TypedValue is used to encode a value being sent between the client and -// target (originated by either entity). -message TypedValue { - // One of the fields within the val oneof is populated with the value - // of the update. The type of the value being included in the Update - // determines which field should be populated. In the case that the - // encoding is a particular form of the base protobuf type, a specific - // field is used to store the value (e.g., json_val). - oneof value { - string string_val = 1; // String value. - int64 int_val = 2; // Integer value. - uint64 uint_val = 3; // Unsigned integer value. - bool bool_val = 4; // Bool value. - bytes bytes_val = 5; // Arbitrary byte sequence value. - float float_val = 6; // Floating point value. - Decimal64 decimal_val = 7; // Decimal64 encoded value. - ScalarArray leaflist_val = 8; // Mixed type scalar array value. - google.protobuf.Any any_val = 9; // protobuf.Any encoded bytes. - bytes json_val = 10; // JSON-encoded text. - bytes json_ietf_val = 11; // JSON-encoded text per RFC7951. - string ascii_val = 12; // Arbitrary ASCII text. - // Protobuf binary encoded bytes. The message type is not included. - // See the specification at - // github.com/openconfig/reference/blob/master/rpc/gnmi/protobuf-vals.md - // for a complete specification. - bytes proto_bytes = 13; - } -} - -// Path encodes a data tree path as a series of repeated strings, with -// each element of the path representing a data tree node name and the -// associated attributes. -// Reference: gNMI Specification Section 2.2.2. -message Path { - // Elements of the path are no longer encoded as a string, but rather within - // the elem field as a PathElem message. - repeated string element = 1 [deprecated=true]; - string origin = 2; // Label to disambiguate path. - repeated PathElem elem = 3; // Elements of the path. - string target = 4; // The name of the target - // (Sec. 2.2.2.1) -} - -// PathElem encodes an element of a gNMI path, along ith any attributes (keys) -// that may be associated with it. -// Reference: gNMI Specification Section 2.2.2. -message PathElem { - string name = 1; // The name of the element in the path. - map<string, string> key = 2; // Map of key (attribute) name to value. -} - -// Value encodes a data tree node's value - along with the way in which -// the value is encoded. This message is deprecated by gNMI 0.3.0. -// Reference: gNMI Specification Section 2.2.3. -message Value { - option deprecated = true; - bytes value = 1; // Value of the variable being transmitted. - Encoding type = 2; // Encoding used for the value field. -} - -// Encoding defines the value encoding formats that are supported by the gNMI -// protocol. These encodings are used by both the client (when sending Set -// messages to modify the state of the target) and the target when serializing -// data to be returned to the client (in both Subscribe and Get RPCs). -// Reference: gNMI Specification Section 2.3 -enum Encoding { - JSON = 0; // JSON encoded text. - BYTES = 1; // Arbitrarily encoded bytes. - PROTO = 2; // Encoded according to out-of-band agreed Protobuf. - ASCII = 3; // ASCII text of an out-of-band agreed format. - JSON_IETF = 4; // JSON encoded text as per RFC7951. -} - -// Error message previously utilised to return errors to the client. Deprecated -// in favour of using the google.golang.org/genproto/googleapis/rpc/status -// message in the RPC response. -// Reference: gNMI Specification Section 2.5 -message Error { - option deprecated = true; - uint32 code = 1; // Canonical gRPC error code. - string message = 2; // Human readable error. - google.protobuf.Any data = 3; // Optional additional information. -} - -// Decimal64 is used to encode a fixed precision decimal number. The value -// is expressed as a set of digits with the precision specifying the -// number of digits following the decimal point in the digit set. -message Decimal64 { - int64 digits = 1; // Set of digits. - uint32 precision = 2; // Number of digits following the decimal point. -} - -// ScalarArray is used to encode a mixed-type array of values. -message ScalarArray { - // The set of elements within the array. Each TypedValue message should - // specify only elements that have a field identifier of 1-7 (i.e., the - // values are scalar values). - repeated TypedValue element = 1; -} - -// SubscribeRequest is the message sent by the client to the target when -// initiating a subscription to a set of paths within the data tree. The -// request field must be populated and the initial message must specify a -// SubscriptionList to initiate a subscription. The message is subsequently -// used to define aliases or trigger polled data to be sent by the target. -// Reference: gNMI Specification Section 3.5.1.1 -message SubscribeRequest { - oneof request { - SubscriptionList subscribe = 1; // Specify the paths within a subscription. - Poll poll = 3; // Trigger a polled update. - AliasList aliases = 4; // Aliases to be created. - } - // Extension messages associated with the SubscribeRequest. See the - // gNMI extension specification for further definition. - repeated gnmi_ext.Extension extension = 5; -} - -// Poll is sent within a SubscribeRequest to trigger the device to -// send telemetry updates for the paths that are associated with the -// subscription. -// Reference: gNMI Specification Section Section 3.5.1.4 -message Poll { -} - -// SubscribeResponse is the message used by the target within a Subscribe RPC. -// The target includes a Notification message which is used to transmit values -// of the path(s) that are associated with the subscription. The same message -// is to indicate that the target has sent all data values once (is -// synchronized). -// Reference: gNMI Specification Section 3.5.1.4 -message SubscribeResponse { - oneof response { - Notification update = 1; // Changed or sampled value for a path. - // Indicate target has sent all values associated with the subscription - // at least once. - bool sync_response = 3; - // Deprecated in favour of google.golang.org/genproto/googleapis/rpc/status - Error error = 4 [deprecated=true]; - } - // Extension messages associated with the SubscribeResponse. See the - // gNMI extension specification for further definition. - repeated gnmi_ext.Extension extension = 5; -} - -// SubscriptionList is used within a Subscribe message to specify the list of -// paths that the client wishes to subscribe to. The message consists of a -// list of (possibly prefixed) paths, and options that relate to the -// subscription. -// Reference: gNMI Specification Section 3.5.1.2 -message SubscriptionList { - Path prefix = 1; // Prefix used for paths. - repeated Subscription subscription = 2; // Set of subscriptions to create. - // Whether target defined aliases are allowed within the subscription. - bool use_aliases = 3; - QOSMarking qos = 4; // DSCP marking to be used. - // Mode of the subscription. - enum Mode { - STREAM = 0; // Values streamed by the target (Sec. 3.5.1.5.2). - ONCE = 1; // Values sent once-off by the target (Sec. 3.5.1.5.1). - POLL = 2; // Values sent in response to a poll request (Sec. 3.5.1.5.3). - } - Mode mode = 5; - // Whether elements of the schema that are marked as eligible for aggregation - // should be aggregated or not. - bool allow_aggregation = 6; - // The set of schemas that define the elements of the data tree that should - // be sent by the target. - repeated ModelData use_models = 7; - // The encoding that the target should use within the Notifications generated - // corresponding to the SubscriptionList. - Encoding encoding = 8; - // An optional field to specify that only updates to current state should be - // sent to a client. If set, the initial state is not sent to the client but - // rather only the sync message followed by any subsequent updates to the - // current state. For ONCE and POLL modes, this causes the server to send only - // the sync message (Sec. 3.5.2.3). - bool updates_only = 9; -} - -// Subscription is a single request within a SubscriptionList. The path -// specified is interpreted (along with the prefix) as the elements of the data -// tree that the client is subscribing to. The mode determines how the target -// should trigger updates to be sent. -// Reference: gNMI Specification Section 3.5.1.3 -message Subscription { - Path path = 1; // The data tree path. - SubscriptionMode mode = 2; // Subscription mode to be used. - uint64 sample_interval = 3; // ns between samples in SAMPLE mode. - // Indicates whether values that not changed should be sent in a SAMPLE - // subscription. - bool suppress_redundant = 4; - // Specifies the maximum allowable silent period in nanoseconds when - // suppress_redundant is in use. The target should send a value at least once - // in the period specified. - uint64 heartbeat_interval = 5; -} - -// SubscriptionMode is the mode of the subscription, specifying how the -// target must return values in a subscription. -// Reference: gNMI Specification Section 3.5.1.3 -enum SubscriptionMode { - TARGET_DEFINED = 0; // The target selects the relevant mode for each element. - ON_CHANGE = 1; // The target sends an update on element value change. - SAMPLE = 2; // The target samples values according to the interval. -} - -// QOSMarking specifies the DSCP value to be set on transmitted telemetry -// updates from the target. -// Reference: gNMI Specification Section 3.5.1.2 -message QOSMarking { - uint32 marking = 1; -} - -// Alias specifies a data tree path, and an associated string which defines an -// alias which is to be used for this path in the context of the RPC. The alias -// is specified as a string which is prefixed with "#" to disambiguate it from -// data tree element paths. -// Reference: gNMI Specification Section 2.4.2 -message Alias { - Path path = 1; // The path to be aliased. - string alias = 2; // The alias value, a string prefixed by "#". -} - -// AliasList specifies a list of aliases. It is used in a SubscribeRequest for -// a client to create a set of aliases that the target is to utilize. -// Reference: gNMI Specification Section 3.5.1.6 -message AliasList { - repeated Alias alias = 1; // The set of aliases to be created. -} - -// SetRequest is sent from a client to the target to update values in the data -// tree. Paths are either deleted by the client, or modified by means of being -// updated, or replaced. Where a replace is used, unspecified values are -// considered to be replaced, whereas when update is used the changes are -// considered to be incremental. The set of changes that are specified within -// a single SetRequest are considered to be a transaction. -// Reference: gNMI Specification Section 3.4.1 -message SetRequest { - Path prefix = 1; // Prefix used for paths in the message. - repeated Path delete = 2; // Paths to be deleted from the data tree. - repeated Update replace = 3; // Updates specifying elements to be replaced. - repeated Update update = 4; // Updates specifying elements to updated. - // Extension messages associated with the SetRequest. See the - // gNMI extension specification for further definition. - repeated gnmi_ext.Extension extension = 5; -} - -// SetResponse is the response to a SetRequest, sent from the target to the -// client. It reports the result of the modifications to the data tree that were -// specified by the client. Errors for this RPC should be reported using the -// https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto -// message in the RPC return. The gnmi.Error message can be used to add additional -// details where required. -// Reference: gNMI Specification Section 3.4.2 -message SetResponse { - Path prefix = 1; // Prefix used for paths. - // A set of responses specifying the result of the operations specified in - // the SetRequest. - repeated UpdateResult response = 2; - Error message = 3 [deprecated=true]; // The overall status of the transaction. - int64 timestamp = 4; // Timestamp of transaction (ns since epoch). - // Extension messages associated with the SetResponse. See the - // gNMI extension specification for further definition. - repeated gnmi_ext.Extension extension = 5; -} - -// UpdateResult is used within the SetResponse message to communicate the -// result of an operation specified within a SetRequest message. -// Reference: gNMI Specification Section 3.4.2 -message UpdateResult { - // The operation that was associated with the Path specified. - enum Operation { - INVALID = 0; - DELETE = 1; // The result relates to a delete of Path. - REPLACE = 2; // The result relates to a replace of Path. - UPDATE = 3; // The result relates to an update of Path. - } - // Deprecated timestamp for the UpdateResult, this field has been - // replaced by the timestamp within the SetResponse message, since - // all mutations effected by a set should be applied as a single - // transaction. - int64 timestamp = 1 [deprecated=true]; - Path path = 2; // Path associated with the update. - Error message = 3 [deprecated=true]; // Status of the update operation. - Operation op = 4; // Update operation type. -} - -// GetRequest is sent when a client initiates a Get RPC. It is used to specify -// the set of data elements for which the target should return a snapshot of -// data. The use_models field specifies the set of schema modules that are to -// be used by the target - where use_models is not specified then the target -// must use all schema models that it has. -// Reference: gNMI Specification Section 3.3.1 -message GetRequest { - Path prefix = 1; // Prefix used for paths. - repeated Path path = 2; // Paths requested by the client. - // Type of elements within the data tree. - enum DataType { - ALL = 0; // All data elements. - CONFIG = 1; // Config (rw) only elements. - STATE = 2; // State (ro) only elements. - // Data elements marked in the schema as operational. This refers to data - // elements whose value relates to the state of processes or interactions - // running on the device. - OPERATIONAL = 3; - } - DataType type = 3; // The type of data being requested. - Encoding encoding = 5; // Encoding to be used. - repeated ModelData use_models = 6; // The schema models to be used. - // Extension messages associated with the GetRequest. See the - // gNMI extension specification for further definition. - repeated gnmi_ext.Extension extension = 7; -} - -// GetResponse is used by the target to respond to a GetRequest from a client. -// The set of Notifications corresponds to the data values that are requested -// by the client in the GetRequest. -// Reference: gNMI Specification Section 3.3.2 -message GetResponse { - repeated Notification notification = 1; // Data values. - Error error = 2 [deprecated=true]; // Errors that occurred in the Get. - // Extension messages associated with the GetResponse. See the - // gNMI extension specification for further definition. - repeated gnmi_ext.Extension extension = 3; -} - -// CapabilityRequest is sent by the client in the Capabilities RPC to request -// that the target reports its capabilities. -// Reference: gNMI Specification Section 3.2.1 -message CapabilityRequest { - // Extension messages associated with the CapabilityRequest. See the - // gNMI extension specification for further definition. - repeated gnmi_ext.Extension extension = 1; -} - -// CapabilityResponse is used by the target to report its capabilities to the -// client within the Capabilities RPC. -// Reference: gNMI Specification Section 3.2.2 -message CapabilityResponse { - repeated ModelData supported_models = 1; // Supported schema models. - repeated Encoding supported_encodings = 2; // Supported encodings. - string gNMI_version = 3; // Supported gNMI version. - // Extension messages associated with the CapabilityResponse. See the - // gNMI extension specification for further definition. - repeated gnmi_ext.Extension extension = 4; -} - -// ModelData is used to describe a set of schema modules. It can be used in a -// CapabilityResponse where a target reports the set of modules that it -// supports, and within the SubscribeRequest and GetRequest messages to specify -// the set of models from which data tree elements should be reported. -// Reference: gNMI Specification Section 3.2.3 -message ModelData { - string name = 1; // Name of the model. - string organization = 2; // Organization publishing the model. - string version = 3; // Semantic version of the model. -} - diff --git a/src/gnmi/proto/gnmi_ext.proto b/src/gnmi/proto/gnmi_ext.proto deleted file mode 100644 index 01b2864..0000000 --- a/src/gnmi/proto/gnmi_ext.proto +++ /dev/null @@ -1,74 +0,0 @@ -// -// Copyright 2018 Google Inc. All Rights Reserved. -// -// 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. -// -syntax = "proto3"; - -// Package gnmi_ext defines a set of extensions messages which can be optionally -// included with the request and response messages of gNMI RPCs. A set of -// well-known extensions are defined within this file, along with a registry for -// extensions defined outside of this package. -package gnmi_ext; - -// The Extension message contains a single gNMI extension. -message Extension { - oneof ext { - RegisteredExtension registered_ext = 1; // A registered extension. - // Well known extensions. - MasterArbitration master_arbitration = 2; // Master arbitration extension. - } -} - -// The RegisteredExtension message defines an extension which is defined outside -// of this file. -message RegisteredExtension { - ExtensionID id = 1; // The unique ID assigned to this extension. - bytes msg = 2; // The binary-marshalled protobuf extension payload. -} - -// RegisteredExtension is an enumeration acting as a registry for extensions -// defined by external sources. -enum ExtensionID { - EID_UNSET = 0; - // New extensions are to be defined within this enumeration - their definition - // MUST link to a reference describing their implementation. - - // An experimental extension that may be used during prototyping of a new - // extension. - EID_EXPERIMENTAL = 999; -} - -// MasterArbitration is used to select the master among multiple gNMI clients -// with the same Roles. The client with the largest election_id is honored as -// the master. -// The document about gNMI master arbitration can be found at -// https://github.com/openconfig/reference/blob/master/rpc/gnmi/gnmi-master-arbitration.md -message MasterArbitration { - Role role = 1; - Uint128 election_id = 2; -} - -// Representation of unsigned 128-bit integer. -message Uint128 { - uint64 high = 1; - uint64 low = 2; -} - -// There can be one master for each role. The role is identified by its id. -message Role { - string id = 1; - // More fields can be added if needed, for example, to specify what paths the - // role can read/write. -} - diff --git a/src/gnmi/sysrepoapi.cpp b/src/gnmi/sysrepoapi.cpp deleted file mode 100644 index dcf7668..0000000 --- a/src/gnmi/sysrepoapi.cpp +++ /dev/null @@ -1,419 +0,0 @@ -/* - * Copyright (c) 2019 PANTHEON.tech. - * - * 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. - */ - -#include "sysrepoapi.h" -#include "log.h" - -#include <exception> -#include <iostream> - -void event_notif_cb(const sr_ev_notif_type_t notif_type, - const char *xpath, const sr_val_t *values, - const size_t value_cnt, time_t timestamp, - void *private_ct) -{ - if (NULL == xpath || NULL == values || NULL == private_ct) { - ERROR("Error, NULL detect."); - return; - } - - SysrepoAPI *sapi = (SysrepoAPI*) private_ct; - - for (size_t i = 0; i < value_cnt; i++ ) { - sapi->setOutVal(*(values + i)); - } - - sapi->sendEvent(sapi); -} - -SysrepoAPI::SysrepoAPI() -{ - sr_log_stderr(SR_LL_DBG); -} - -SysrepoAPI::~SysrepoAPI() -{ - if (nullptr != subscription) { - sr_unsubscribe(sess, subscription); - } - - if (nullptr != sess) { - sr_session_stop(sess); - } - - if (nullptr != conn) { - sr_disconnect(conn); - } -} - -void SysrepoAPI::setSysrepoName(const std::string& sysrepo_name) -{ - this->sysrepo_name = sysrepo_name; -} - -void SysrepoAPI::connect() -{ - int rc = sr_connect(sysrepo_name.c_str(), SR_CONN_DEFAULT, &conn); - if (SR_ERR_OK != rc) { - ERROR("Failed connect to sysrepo."); - throw std::runtime_error("Failed connect to sysrepo."); - } -} - -void SysrepoAPI::createSession(sr_datastore_e sesType) -{ - int rc = SR_ERR_OK; - - if (nullptr == conn) { - ERROR("Error, nullptr detect."); - throw std::runtime_error("Error, nullptr detect."); - } - - closeSession(); - - rc = sr_session_start(conn, sesType, SR_SESS_DEFAULT, &sess); - if (SR_ERR_OK != rc) { - ERROR("Failed connect to sysrepo session."); - throw std::runtime_error("Failed connect to sysrepo session."); - } -} - -void SysrepoAPI::closeSession() -{ - if (nullptr != sess) { - sr_session_stop(sess); - sess = nullptr; - } -} - -void SysrepoAPI::commit() -{ - int rc = SR_ERR_OK; - - if (nullptr == sess) { - ERROR("Error, nullptr detect."); - throw std::runtime_error("Error, nullptr detect."); - } - - rc = sr_commit(sess); - if (SR_ERR_OK != rc) { - ERROR("Failed commit change to sysrepo."); - throw std::runtime_error("Failed commit change to sysrepo."); - } -} - -void SysrepoAPI::addData(const gNMIData& data) -{ - inputData.push_back(data); -} - -void SysrepoAPI::getItemMessage() -{ - if (nullptr == sess) { - ERROR("Error, nullptr detect."); - throw std::runtime_error("Error, nullptr detect."); - } - - for (const auto &data : inputData) { - sr_val_t *value = nullptr; - sr_val_iter_t *iter = nullptr; -// size_t count; - DEBUG("Path: %s", data.getXPath(gNMIData::xPathType::sysrepoPath).c_str()); - - int rc = sr_get_items_iter(sess, data.getXPath(gNMIData::xPathType::sysrepoPath).c_str(), - &iter); -// int rc = sr_get_item(sess, data.getXPath(gNMIData::xPathType::sysrepoPath).c_str(), -// &value); - if (SR_ERR_OK != rc) { - ERROR("Failed get item from sysrepo."); - throw std::runtime_error("Failed get item from sysrepo."); - } - - while (SR_ERR_OK == sr_get_item_next(sess, iter, &value)) { - sr_print_val(value); - -// sr_print_val(value); - - gNMIData oData; - - oData.setXPath(value->xpath, gNMIData::xPathType::sysrepoPath); - oData.setValue(sr_val_to_str(value)); - - outpuData.push_back(oData); - - sr_free_val(value); - } - } -} - -void SysrepoAPI::setItemMessage() -{ - int rc = SR_ERR_OK; - -// sr_xpath_ctx_t state = {0}; - - if (nullptr == sess) { - ERROR("Error, nullptr detect."); - throw std::runtime_error("Error, nullptr detect."); - } - - for (const auto &data : inputData) { - DEBUG("Set path: %s", data.getXPath(gNMIData::xPathType::sysrepoPath).c_str()); - DEBUG("Val: %s", data.getStr().c_str()); - -// if (gNMIData::ValueType::dStringVal == data.dataType()) { - rc = sr_set_item_str(sess, - data.getXPath(gNMIData::xPathType::sysrepoPath).c_str(), - data.getStr().c_str(), SR_EDIT_DEFAULT); -// } else { -// sr_val_t value = { 0 }; -// setSrVal(value, data); -// -// rc = sr_set_item(sess, data.getXPath(gNMIData::xPathType::sysrepoPath).c_str(), -// &value, SR_EDIT_DEFAULT); -// } - if (SR_ERR_OK != rc) { - ERROR("Failed set item to sysrepo."); - throw std::runtime_error("Failed set item to sysrepo."); - } - - //TODO: Hmm, this is duplication copy, I`m not sure with this solution. - outpuData.push_back(data); - } -} - -void SysrepoAPI::rpcSend(const std::string& xpath, sr_val_t &input) -{ - int rc = SR_ERR_OK; - sr_val_t *output = nullptr; - size_t output_cnt = 0; - - if (nullptr == sess) { - ERROR("Error, nullptr detect."); - throw std::runtime_error("Error, nullptr detect."); - } - - rc = sr_rpc_send(sess, xpath.c_str(), &input, 1, &output, &output_cnt); - if (SR_ERR_OK != rc) { - ERROR("RPC message failed: %s.", sr_strerror(rc)); - throw std::runtime_error("RPC message failed."); - } -} - -void SysrepoAPI::eventSubscribeMessage() -{ - int rc = SR_ERR_OK; - - if (nullptr == sess) { - ERROR("Error, nullptr detect."); - throw std::runtime_error("Error, nullptr detect."); - } - - for (const auto &data : inputData) { - DEBUG("Register subscribe path: %s", - data.getXPath(gNMIData::xPathType::sysrepoPath).c_str()); - rc = sr_event_notif_subscribe(sess, - data.getXPath(gNMIData::xPathType::sysrepoPath).c_str(), - event_notif_cb, this, SR_SUBSCR_DEFAULT, - &subscription); - if (SR_ERR_OK != rc) { - ERROR("Event notification subscribe failed: %s.", sr_strerror(rc)); - throw std::runtime_error("Event notification subscribe failed."); - } - } -} - -const std::list<SysrepSchema> &SysrepoAPI::getSchemas() -{ - int rc = SR_ERR_OK; - sr_schema_t *schemas = nullptr; - size_t schema_cnt = 0; - - if (nullptr == sess) { - ERROR("Error, nullptr detect."); - throw std::runtime_error("Error, nullptr detect."); - } - - rc = sr_list_schemas(sess, &schemas, &schema_cnt); - if (SR_ERR_OK != rc) { - ERROR("List schemas failed: %s.", sr_strerror(rc)); - throw std::runtime_error("List schemas failed failed."); - } - - for (size_t i = 0; i < schema_cnt; i++) { -// DEBUG("Module: %s, xpath: %s, prefix: %s, r yang: %s, revison: %s", -// schemas[i].module_name, schemas[i].ns, schemas[i].prefix, -// schemas[i].revision.file_path_yang, schemas[i].revision.revision); - SysrepSchema schema; - - if (NULL != schemas[i].module_name) { - schema.moduleName = std::string(schemas[i].module_name); - } - - if (NULL != schemas[i].revision.revision) { - schema.revision = std::string(schemas[i].revision.revision); - } - schemaList.push_back(schema); - } - - sr_free_schemas(schemas, schema_cnt); - - return schemaList; -} - -std::list<gNMIData> SysrepoAPI::getOutputData() const -{ - return outpuData; -} - -void SysrepoAPI::cleanData() -{ - inputData.clear(); - outpuData.clear(); - schemaList.clear(); -} - -enum sr_type_e SysrepoAPI::convergNMITypeToSysrepo(gNMIData::ValueType type) -{ - switch (type) { - case gNMIData::ValueType::dStringVal: - return SR_STRING_T; - - case gNMIData::ValueType::dIntVal: - return SR_INT32_T; - - case gNMIData::ValueType::UnknownVal: - default: - return SR_UNKNOWN_T; - } - - return SR_UNKNOWN_T; -} - -gNMIData::ValueType SysrepoAPI::convergSysrepoTypeTogNMI(sr_type_e type) -{ - switch (type) { - case SR_STRING_T: - return gNMIData::ValueType::dStringVal; - - case SR_INT8_T: - case SR_INT16_T: - case SR_INT32_T: - case SR_INT64_T: - case SR_UINT8_T: - case SR_UINT16_T: - case SR_UINT32_T: - case SR_UINT64_T: - return gNMIData::ValueType::dIntVal; - - case SR_ANYDATA_T: - case SR_ANYXML_T: - case SR_BINARY_T: - case SR_BITS_T: - case SR_BOOL_T: - case SR_CONTAINER_PRESENCE_T: - case SR_CONTAINER_T: - case SR_DECIMAL64_T: - case SR_ENUM_T: - case SR_IDENTITYREF_T: - case SR_INSTANCEID_T: - case SR_LEAF_EMPTY_T: - case SR_LIST_T: - case SR_TREE_ITERATOR_T: - case SR_UNKNOWN_T: - return gNMIData::ValueType::UnknownVal; - - default: - return gNMIData::ValueType::UnknownVal; - } - - return gNMIData::ValueType::UnknownVal; -} - -void SysrepoAPI::setSrVal(sr_val_t& value, const gNMIData& gData) -{ - value.type = convergNMITypeToSysrepo(gData.dataType()); - - switch (gData.dataType()) { - case gNMIData::ValueType::dStringVal: - value.data.string_val = (char *) gData.getStr().c_str(); - DEBUG("Val: %s", value.data.string_val); - break; - - case gNMIData::ValueType::dIntVal: - value.data.int32_val = gData.getInt(); - DEBUG("Val: %d", value.data.int32_val); - break; - - case gNMIData::ValueType::UnknownVal: - default: - DEBUG("Unknown value."); - //TODO: - break; - } -} - -void SysrepoAPI::setOutVal(const sr_val_t& value) -{ -// auto key = convergSysrepoTypeTogNMI(value.type); - std::string str; - - //TODO: Need rewrite, only for test - switch (value.type) { - case SR_STRING_T: - str = std::string(value.data.string_val); - break; - - case SR_INT8_T: - str = std::to_string(value.data.int8_val); - break; - - case SR_INT16_T: - str = std::to_string(value.data.int16_val); - break; - - case SR_INT32_T: - str = std::to_string(value.data.int32_val); - break; - - case SR_INT64_T: - str = std::to_string(value.data.int64_val); - break; - - case SR_UINT8_T: - str = std::to_string(value.data.uint8_val); - break; - case SR_UINT16_T: - str = std::to_string(value.data.uint16_val); - break; - case SR_UINT32_T: - str = std::to_string(value.data.uint32_val); - break; - case SR_UINT64_T: - str = std::to_string(value.data.uint64_val); - break; - - default: - //TODO: Need implement. - break; - } - - gNMIData sData; - sData.setXPath(value.xpath, gNMIData::xPathType::sysrepoPath); - sData.setValue(str); - - outpuData.push_back(sData); -} diff --git a/src/gnmi/sysrepoapi.h b/src/gnmi/sysrepoapi.h deleted file mode 100644 index 8ebcf95..0000000 --- a/src/gnmi/sysrepoapi.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2019 PANTHEON.tech. - * - * 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. - */ - -#ifndef SYSREPOAPI_H -#define SYSREPOAPI_H - -#include "gnmidata.h" -#include "eventreciverbase.h" - -#include <sysrepo.h> -#include <sysrepo/values.h> -#include <string> -#include <list> - -#include <iostream> - -struct SysrepoValue -{ - void setXPath(const std::string &str) { - std::string tmp = str; - std::size_t pos = 0; - - while (std::string::npos != (pos = tmp.find(":", pos))) { - tmp.replace(pos, std::string(":").length(), "/"); - } - - xpath = tmp; - } - - std::string xpath; - std::string value; -}; - -struct SysrepSchema -{ - std::string moduleName; - std::string revision; -}; - -/** - * @todo write docs - */ -class SysrepoAPI : public virtual BaseSender<SysrepoAPI> -{ -public: - /** - * Default constructor - */ - SysrepoAPI(); - - /** - * Destructor - */ - ~SysrepoAPI(); - - void setSysrepoName(const std::string &sysrepo_name); - - void connect(); - void createSession(sr_datastore_e sesType = SR_DS_RUNNING); - void closeSession(); - void commit(); - - void addData(const gNMIData &data); - void getItemMessage(); - void setItemMessage(); - void rpcSend(const std::string &xpath, sr_val_t &input); - void eventSubscribeMessage(); - const std::list<SysrepSchema> &getSchemas(); -// void print_value(); - - std::list<gNMIData> getOutputData() const; - void cleanData(); - -private: - friend void event_notif_cb(const sr_ev_notif_type_t notif_type, - const char *xpath, const sr_val_t *values, - const size_t value_cnt, time_t timestamp, - void *private_ct); - enum sr_type_e convergNMITypeToSysrepo(gNMIData::ValueType type); - gNMIData::ValueType convergSysrepoTypeTogNMI(sr_type_e type); - void setSrVal(sr_val_t &value, const gNMIData &gData); - void setOutVal(const sr_val_t &value); - -private: - std::string sysrepo_name = "app"; - sr_conn_ctx_t *conn = nullptr; - sr_session_ctx_t *sess = nullptr; - sr_subscription_ctx_t *subscription = nullptr; - - std::list<gNMIData> inputData; - std::list<gNMIData> outpuData; - std::list<SysrepSchema> schemaList; - -}; - -#endif // SYSREPOAPI_H diff --git a/src/gnmi/sysrepoapipool.cpp b/src/gnmi/sysrepoapipool.cpp deleted file mode 100644 index 7e94a56..0000000 --- a/src/gnmi/sysrepoapipool.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2019 PANTHEON.tech. - * - * 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. - */ - -#include "sysrepoapipool.h" - -SysrepoApiPool::SysrepoApiPool() - : pool{} -{ - -} - -SysrepoApiPool::~SysrepoApiPool() -{ - -} - -SysrepoAPI & SysrepoApiPool::get(const std::string &name) -{ - auto &sapi = pool[name]; - sapi.setSysrepoName(name); - - return sapi; -} - -void SysrepoApiPool::remove(const std::string &name) -{ - pool.erase(name); -} - diff --git a/src/gnmi/sysrepoapipool.h b/src/gnmi/sysrepoapipool.h deleted file mode 100644 index ddc3260..0000000 --- a/src/gnmi/sysrepoapipool.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2019 PANTHEON.tech. - * - * 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. - */ - -#ifndef SYSREPOAPIPOOL_H -#define SYSREPOAPIPOOL_H - -#include "sysrepoapi.h" - -#include <map> -#include <string> - -/** - * @todo write docs - */ -class SysrepoApiPool -{ -public: - /** - * Default constructor - */ - SysrepoApiPool(); - - /** - * Destructor - */ - ~SysrepoApiPool(); - - SysrepoAPI &get(const std::string &name); - void remove(const std::string &name); - -private: - std::map<std::string, SysrepoAPI> pool; -}; - -#endif // SYSREPOAPIPOOL_H diff --git a/src/gnmi/xml2json.cpp b/src/gnmi/xml2json.cpp deleted file mode 100644 index 15dac41..0000000 --- a/src/gnmi/xml2json.cpp +++ /dev/null @@ -1,326 +0,0 @@ -/* - * Copyright (c) 2019 PANTHEON.tech. - * - * 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. - */ - -#include "xml2json.h" -#include "log.h" - -#include <exception> -#include <sstream> -#include <iostream> - -XML2JSON::XML2JSON(const XML2JSON& other) -{ - -} - -XML2JSON::~XML2JSON() -{ - -} - -void XML2JSON::setData(const std::string& data, XML2JSON::string_type_t type) -{ - switch (type) { - case string_type_t::JSONSTRING: - { - Json::Reader read; - DEBUG("JSONSTRING: %s", data.c_str()); - - read.parse(data, jsonRoot); - DEBUG("Root size: %d", jsonRoot.size()); - } - break; - - case string_type_t::XMLSTRING: - { - int rc = 0; - rc = xmlDoc.load_string(data.c_str(), - pugi::parse_default | pugi::parse_comments); - if (0 != rc) { - ERROR("Error parse xml string."); - throw std::logic_error("Error parse xml string."); - } - } - break; - - default: - throw std::logic_error("Unknown type."); - break; - } -} - -void XML2JSON::setPrefix(const std::string& prefix) -{ - this->prefix = prefix; -} - -std::string XML2JSON::getJson() -{ - switch (type) { - case string_type_t::JSONSTRING: - //TODO: - return std::string(""); - - case string_type_t::XMLSTRING: - //TODO: - return std::string(""); - - default: - break; - } - - throw std::logic_error("Unknown type."); -} - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" -std::string XML2JSON::getXML() -{ - std::ostringstream stream; - - switch (type) { - case string_type_t::JSONSTRING: - createXML(); - - case string_type_t::XMLSTRING: - xmlDoc.print(stream); - DEBUG("XML doc: %s", xmlDoc.path().c_str()); - return stream.str(); - - default: - break; - } - - throw std::logic_error("Unknown type."); -} -#pragma GCC diagnostic pop - -const std::list<gNMIData> & XML2JSON::getgNMIData() -{ - createGNMIData(); - - return gnmiData; -} - -void XML2JSON::parseJSON() -{ -// parseJSONValueType(jsonRoot); -} - -void XML2JSON::parseJSONValueType(const Json::Value& value, - pugi::xml_node &node) -{ - switch (value.type()) { - case Json::nullValue: - break; - - case Json::intValue: - DEBUG("Value: %d", value.asInt()); - node.append_child(pugi::node_pcdata).set_value( - std::to_string(value.asInt()).c_str()); - break; - - case Json::uintValue: - DEBUG("Value: %d", value.asUInt()); - node.append_child(pugi::node_pcdata).set_value( - std::to_string(value.asUInt()).c_str()); - break; - - case Json::realValue: - DEBUG("Value: %f", value.asFloat()); - node.append_child(pugi::node_pcdata).set_value( - std::to_string(value.asFloat()).c_str()); - break; - - case Json::stringValue: - DEBUG("Value: %s", value.asString().c_str()); - node.append_child(pugi::node_pcdata).set_value( - value.asString().c_str()); - break; - - case Json::booleanValue: - DEBUG("Value: %d", value.asBool()); - node.append_child(pugi::node_pcdata).set_value( - std::to_string(value.asBool()).c_str()); - break; - - case Json::arrayValue: - parseJSONArray(value, node); - break; - - case Json::objectValue: - parseJSONObject(value, node); - break; - - default: - DEBUG("Unknown value type."); - break; - } -} - -void XML2JSON::parseJSONValueType(const Json::Value& value, - const std::string& prefix) -{ - switch (value.type()) { - case Json::nullValue: - { - gNMIData data; - std::string tmp(prefix); - tmp.pop_back(); - data.setXPath(tmp); - gnmiData.push_back(data); - } - break; - - case Json::intValue: - // DEBUG("Value: %d", value.asInt()); - { - gNMIData data; - std::string tmp(prefix); - tmp.pop_back(); - data.setXPath(tmp); - data.setValue(value.asInt()); - gnmiData.push_back(data); - } - break; - - case Json::uintValue: - // DEBUG("Value: %d", value.asUInt()); - { - gNMIData data; - std::string tmp(prefix); - tmp.pop_back(); - data.setXPath(tmp); - data.setValue(value.asUInt()); - gnmiData.push_back(data); - } - break; - - case Json::realValue: - // DEBUG("Value: %f", value.asFloat()); - { - gNMIData data; - std::string tmp(prefix); - tmp.pop_back(); - data.setXPath(tmp); - data.setValue(value.asFloat()); - gnmiData.push_back(data); - } - break; - - case Json::stringValue: - // DEBUG("Value: %s", value.asString().c_str()); - { - gNMIData data; - std::string tmp(prefix); - tmp.pop_back(); - data.setXPath(tmp); - data.setValue(value.asString()); - gnmiData.push_back(data); - } - break; - - case Json::booleanValue: - // DEBUG("Value: %d", value.asBool()); - { - gNMIData data; - std::string tmp(prefix); - tmp.pop_back(); - data.setXPath(tmp); - data.setValue(value.asBool() ? "true" : "false"); - gnmiData.push_back(data); - } - break; - - case Json::arrayValue: - parseJSONArray(value, prefix); - break; - - case Json::objectValue: - parseJSONObject(value, prefix); - break; - - default: - DEBUG("Unknown value type."); - break; - } -} - -void XML2JSON::parseJSONArray(const Json::Value& value, pugi::xml_node &node) -{ - if (Json::arrayValue != value.type()) { - ERROR("Wrong JSON Value type"); - throw std::logic_error("Wrong JSON Value type"); - } - - for (const auto &elm : value) { - parseJSONValueType(elm, node); - } -} - -void XML2JSON::parseJSONArray(const Json::Value& value, - const std::string& prefix) -{ - if (Json::arrayValue != value.type()) { - ERROR("Wrong JSON Value type"); - throw std::logic_error("Wrong JSON Value type"); - } - - for (const auto &elm : value) { - parseJSONValueType(elm, prefix); - } -} - -void XML2JSON::parseJSONObject(const Json::Value& value, pugi::xml_node &node) -{ - if (Json::objectValue != value.type()) { - ERROR("Wrong JSON Value type"); - throw std::logic_error("Wrong JSON Value type"); - } - - for (const auto &name : value.getMemberNames()) { - DEBUG("Name: %s", name.c_str()); - auto child = node.append_child(name.c_str()); - parseJSONValueType(value.get(name, value), child); - } -} - -void XML2JSON::parseJSONObject(const Json::Value& value, - const std::string& prefix) -{ - if (Json::objectValue != value.type()) { - ERROR("Wrong JSON Value type"); - throw std::logic_error("Wrong JSON Value type"); - } - - for (const auto &name : value.getMemberNames()) { - DEBUG("Name: %s", name.c_str()); - std::string tmp = prefix + name + "/"; - parseJSONValueType(value.get(name, value), tmp); - } -} - -void XML2JSON::createXML() -{ -// auto elm = xmlDoc.append_child(pugi::xml_node_type::node_document); - parseJSONValueType(jsonRoot, xmlDoc); -} - -void XML2JSON::createGNMIData() -{ - std::string prefix = this->prefix + "/"; - parseJSONValueType(jsonRoot, prefix); -} diff --git a/src/gnmi/xml2json.h b/src/gnmi/xml2json.h deleted file mode 100644 index fd99a2d..0000000 --- a/src/gnmi/xml2json.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2019 PANTHEON.tech. - * - * 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. - */ - -#ifndef XML2JSON_H -#define XML2JSON_H - -#include <string> -#include <list> - -#include <json/json.h> -#include <pugixml.hpp> - -#include "gnmidata.h" - -/** - * @todo write docs - */ -class XML2JSON -{ -public: - enum class string_type_t { - XMLSTRING, - JSONSTRING - }; - -public: - /** - * Default constructor - */ - XML2JSON() = default; - - /** - * Copy Constructor - * - * @param other TODO - */ - XML2JSON(const XML2JSON& other); - - /** - * Destructor - */ - ~XML2JSON(); - - /** - * @todo write docs - * - * @param other TODO - * @return TODO - */ -// XML2JSON& operator=(const XML2JSON& other); - - void setData(const std::string &data, string_type_t type = string_type_t::JSONSTRING); - void setPrefix(const std::string &prefix); - std::string getJson(); - std::string getXML(); - const std::list<gNMIData> &getgNMIData(); - -private: - void parseJSON(); - void parseJSONValueType(const Json::Value &value, pugi::xml_node &node); - void parseJSONValueType(const Json::Value &value, const std::string &prefix); - void parseJSONArray(const Json::Value &value, pugi::xml_node &node); - void parseJSONArray(const Json::Value &value, const std::string &prefix); - void parseJSONObject(const Json::Value &value, pugi::xml_node &node); - void parseJSONObject(const Json::Value &value, const std::string &prefix); - - void createXML(); - void createGNMIData(); - -private: - std::string prefix = "/"; - string_type_t type = string_type_t::JSONSTRING; - Json::Value jsonRoot; - pugi::xml_document xmlDoc; - std::list<gNMIData> gnmiData; -}; - -#endif // XML2JSON_H |