Skip to content

Commit

Permalink
Support for yang actions in path API (#717)
Browse files Browse the repository at this point in the history
* Support for yang actions in path API

 * Add support for parsing yang 1.1 module capabilities
 * Tests, docs
 * Added --libydk option to generate.py

* Codacy
  • Loading branch information
Abhi Keshav authored Mar 21, 2018
1 parent cb5e26e commit abfc981
Show file tree
Hide file tree
Showing 36 changed files with 1,199 additions and 101 deletions.
29 changes: 23 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,26 @@ Centos (Fedora-based):

**Install prebuilt libydk binary:**
```
$ sudo yum install epel-release libssh-devel gcc-c++
$ sudo yum install epel-release
$ sudo yum install libssh-devel gcc-c++
$ sudo yum install https://devhub.cisco.com/artifactory/rpm-ydk/0.7.0/libydk-0.7.0-1.x86_64.rpm
# Upgrade compiler to gcc 5.*
$ yum install centos-release-scl -y > /dev/null
$ yum install devtoolset-4-gcc* -y > /dev/null
$ ln -sf /opt/rh/devtoolset-4/root/usr/bin/gcc /usr/bin/cc
$ ln -sf /opt/rh/devtoolset-4/root/usr/bin/g++ /usr/bin/c++
```
**To build from source:**
```
$ sudo yum install epel-release
$ sudo yum install libxml2-devel libxslt-devel libssh-devel libtool gcc-c++ pcre-devel cmake3 clang libcurl-devel rpm-build redhat-lsb
$ sudo yum install epel-release
$ sudo yum install libxml2-devel libxslt-devel libssh-devel libtool gcc-c++ pcre-devel cmake3 clang libcurl-devel rpm-build redhat-lsb
# Upgrade compiler to gcc 5.*
$ yum install centos-release-scl -y > /dev/null
$ yum install devtoolset-4-gcc* -y > /dev/null
$ ln -sf /opt/rh/devtoolset-4/root/usr/bin/gcc /usr/bin/cc
$ ln -sf /opt/rh/devtoolset-4/root/usr/bin/g++ /usr/bin/c++
```

## macOS
Expand Down Expand Up @@ -149,6 +162,7 @@ Options:
--version show program's version number and exit
-h, --help show this help message and exit
-p, --python Select Python language. This is currently the default option
-l, --libydk Generate the libydk core package (required for using YDK Python, Go, C++)
-c, --cpp Select C++ language
-g, --go Select Go language
--core Generate the core for the selected language
Expand Down Expand Up @@ -230,12 +244,15 @@ First, generate the core and install it:

First generate and install ``libydk`` (**required for C++, Go or Python**):
```
$ ./generate.py --cpp --core
$ ./generate.py --libydk
$ cd gen-api/cpp/ydk/build
$ make && sudo make install
$ make
# To create the ``libydk`` binary package to use for later installation, run the below command after the above
# To create the libydk binary package to use for later installation, run the below command
$ make package
# To install the compiled libydk code, run the below command after the above
$ [sudo] make install
```

For python:
Expand Down
21 changes: 17 additions & 4 deletions generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ def generate_adhoc_bundle(adhoc_bundle_name, adhoc_bundle_files):
return adhoc_bundle_file.name


def preconfigure_generated_cpp_code(output_directory):
def preconfigure_generated_cpp_code(output_directory, generate_libydk):
cpp_sdk_root = os.path.join(output_directory)
cmake_build_dir = os.path.join(output_directory, 'build')
if os.path.exists(cmake_build_dir):
Expand All @@ -250,7 +250,10 @@ def preconfigure_generated_cpp_code(output_directory):
except subprocess.CalledProcessError as e:
print('\nERROR: Failed to configure build!\n')
sys.exit(e.returncode)
print('\nSuccessfully generated code at {0}.\nTo build and install, run "make && [sudo] make install" from {1}'.format(output_directory, cmake_build_dir))
make_command = 'To build and install, run "make && [sudo] make install" from {0}'.format(cmake_build_dir)
if generate_libydk:
make_command = make_command+'\n\nTo build the libydk package, run "make && make package" from {0}'.format(cmake_build_dir)
print('\nSuccessfully generated code at {0}.\n\n{1}'.format(output_directory, make_command))
print('\n=================================================')
print('Successfully generated C++ YDK at %s' % (cpp_sdk_root,))
print('Please refer to the README for information on how to use YDK\n')
Expand Down Expand Up @@ -316,6 +319,12 @@ def _get_time_taken(start_time):
default=False,
help="Generate Go SDK")

parser.add_argument(
"-l", "--libydk",
action="store_true",
default=False,
help="Generate libydk core package")

parser.add_argument(
"-v", "--verbose",
action="store_true",
Expand Down Expand Up @@ -366,7 +375,11 @@ def _get_time_taken(start_time):
output_directory = options.output_directory

language = ''
if options.cpp:
if options.libydk:
options.cpp = True
options.core = True
language = 'cpp'
elif options.cpp:
language = 'cpp'
elif options.go:
language = 'go'
Expand Down Expand Up @@ -426,7 +439,7 @@ def _get_time_taken(start_time):
print('\nCreating {0} package...\n'.format(language))

if options.cpp:
preconfigure_generated_cpp_code(output_directory)
preconfigure_generated_cpp_code(output_directory, options.libydk)
elif options.go:
# todo: implement go packaging with the output_directory
pass
Expand Down
15 changes: 14 additions & 1 deletion sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,27 @@ sdk
├── _docsgen_common # Common documents for C++, Python, Go
├── cpp
│   ├── core # C++ core
│   | ├── docsgen # Core documentation
│   | ├-- src # Source code
│   | ├-- samples # Samples
│   | └── tests # Core tests
│   ├── install
│   ├── packages
│   ├── samples
│   └── tests
│   └── tests # C++ bundle tests
├── go
│   ├── core # Go core
│   | ├── docsgen # Core documentation
│   | ├-- samples # Samples
│   | ├-- tests # Core & bundle tests
│   | └── ydk # Source code
│   └── packages
└── python
├── core # Python core
│   | ├── docsgen # Core documentation
│   | ├-- samples # Samples
│   | ├-- tests # Core & bundle tests
│   | └── ydk # Source code
└── packages
```
24 changes: 24 additions & 0 deletions sdk/cpp/core/docsgen/api/path/nodes/data_node.rst
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,20 @@ DataNode
:raises: :cpp:class:`YInvalidArgumentError<YInvalidArgumentError>` In case the argument is invalid.
:raises: :cpp:class:`YPathError<YPathError>` In case the path is invalid.

.. cpp:function:: virtual DataNode& create_action(const std::string& path)

Creates a :cpp:class:`DataNode<DataNode>` representing a YANG 1.1 action corresponding to the path and set its value.

This methods creates a :cpp:class:`DataNode<DataNode>` tree based on the path passed in. The path expression must identify a single node.

The returned :cpp:class:`DataNode<DataNode>` is the last node created (the terminal part of the path).

:param path: The XPath expression identifying the node.
:param value: The string representation of the value to set.
:return: Pointer to :cpp:class:`DataNode<DataNode>` created.
:raises: :cpp:class:`YInvalidArgumentError<YInvalidArgumentError>` In case the argument is invalid.
:raises: :cpp:class:`YPathError<YPathError>` In case the path is invalid.

.. cpp:function:: virtual void set_value(const std::string& value)

Set the value of this :cpp:class:`DataNode<DataNode>`.
Expand Down Expand Up @@ -104,6 +118,16 @@ DataNode

:return: Pointer to the root :cpp:class:`DataNode<DataNode>` of this tree.

.. cpp:function:: virtual std::shared_ptr<DataNode> operator()(const Session& session)

Execute/Invoke the action contained in the DataNode through the given Session and return the output of the action as a DataNode.

:param session: The Session.
:return: Pointer to the :cpp:class:`DataNode<DataNode>` or ``nullptr`` if none exists.

.. cpp:function:: virtual bool has_action() const

:return: `true` if the DataNode contains any action node created by invoking ``create_action``.

.. cpp:function:: virtual void add_annotation(const Annotation& an)

Expand Down
7 changes: 7 additions & 0 deletions sdk/cpp/core/docsgen/api/path/sessions/netconf_session.rst
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ NetconfSession
:param rpc: Reference to the :cpp:class:`Rpc<Rpc>` node.
:return: Shared pointer to the :cpp:class:`DataNode<DataNode>` representing the output.

.. cpp:function:: virtual std::shared_ptr<path::DataNode> invoke(path::DataNode& datanode) const

Invokes or executes the given DataNode containing a YANG 1.1 action and returns a :cpp:class:`DataNode<DataNode>` pointer if the action has an output modeled in YANG.

:param datanode: Reference to the :cpp:class:`DataNode<DataNode>` node.
:return: Pointer to the :cpp:class:`DataNode<DataNode>` representing the output.

.. cpp:function:: std::vector<std::string> get_capabilities() const

Returns a vector of the client's capabilities
Expand Down
2 changes: 1 addition & 1 deletion sdk/cpp/core/docsgen/api/path/sessions/session.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Session

:return: Reference to the :cpp:class:`RootSchemaNode<RootSchemaNode>` or ``nullptr`` if one could not be created.

.. cpp:function:: virtual std::shared_ptr<path::DataNode> invoke(Rpc& rpc) const
.. cpp:function:: virtual std::shared_ptr<path::DataNode> invoke(path::Rpc& rpc) const

Invokes or executes the given rpc and returns a :cpp:class:`DataNode<DataNode>` pointer if the Rpc has an output modeled in YANG.

Expand Down
24 changes: 24 additions & 0 deletions sdk/cpp/core/src/common_utilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
//
//////////////////////////////////////////////////////////////////

#include <set>

#include "common_utilities.hpp"
#include "entity_data_node_walker.hpp"
#include "xml_subtree_codec.hpp"
Expand Down Expand Up @@ -142,4 +144,26 @@ string get_xml_subtree_filter_payload(Entity & entity, const ServiceProvider & p
YLOG_DEBUG("Encoding the subtree filter request using XML subtree codec");
return xml_subtree_codec.encode(entity, provider.get_session().get_root_schema());
}

vector<string> get_union(vector<string> & v1, vector<string> & v2)
{
set<string> all;
YLOG_DEBUG("Performing union of vectors with {} & {} elements", v1.size(), v2.size());
for(auto& s: v1)
{
all.insert(s);
}
for(auto& s: v2)
{
all.insert(s);
}
YLOG_DEBUG("Union contains {} elements", all.size());
vector<string> v;
for(auto& s: all)
{
YLOG_DEBUG("Adding unioned element: {}", s);
v.push_back(s);
}
return v;
}
}
4 changes: 2 additions & 2 deletions sdk/cpp/core/src/common_utilities.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
#ifndef YDK_UTILITIES
#define YDK_UTILITIES

#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>

Expand All @@ -45,6 +43,8 @@ namespace ydk
std::shared_ptr<Entity> read_datanode(Entity & filter, std::shared_ptr<path::DataNode> read_data_node);
std::string get_data_payload(Entity & entity, const ServiceProvider & provider);
std::string get_xml_subtree_filter_payload(Entity & entity, const ServiceProvider & provider);

std::vector<std::string> get_union(std::vector<std::string> & v1, std::vector<std::string> & v2);
}

#endif /* YDK_UTILITIES */
Loading

0 comments on commit abfc981

Please sign in to comment.