This example assumes that the reader has some familiarity with YANG data definitions and the C++ programming language.
Build YANG modules in SAFplus
An application programmer defines a YANG module describing his service:
module myService { namespace "http://www.myCompany.com/ns/myService"; prefix "myService"; import SAFplusTypes { prefix "SAFplusTypes"; }
And then creates a YANG container to define configuration parameters (in this case a string and an integer corresponding to the content directory and port for a simple web service).
container serviceCfg { leaf port { description "What TCP port to listen on"; type uint16; default 8000; } leaf homeLocation { description "What directory on the server contains the pages"; type string; default "/srv/web"; } }
Now let’s create some statistics in YANG:
container serviceStats { description "Statistics on the use of this service"; container accessCounts { description "How much is the service being used"; SAFplusTypes:c-existing "SAFplus::MgtHistoryStat<int>"; uses SAFplusTypes:intStatistic; config false; } container bytesTransmitted { description "How many bytes are transmitted by the service"; SAFplusTypes:c-existing "SAFplus::MgtHistoryStat<int>"; uses SAFplusTypes:intStatistic; config false; } }
“SAFplusTypes:c-existing” is a YANG extension that means “use an existing class, do not generate a new one”. “SAFplusTypes:intStatistic” is a YANG datatype that SAFplus provides.
Now you can create an XML file that defines the initial configuration:
<myService> <serviceCfg> <port>8080</port> </serviceCfg> </myService>
You can then load (and save) this xml configuration to a database using a SAFplus tool. We’ll save it to a database called “appData”.
Next let’s look at the C++ code.
C++ code is generated to match your YANG description:
class MyServiceModule : public SAFplus::MgtModule { public: ::myService::ServiceCfg serviceCfg; ::myService::ServiceStats serviceStats; }
ServiceCfg and ServiceStats are also generated (but will not be shown here for brevity).
Now let’s look at your “main” program:
// Include the classes generated from your YANG #include <myService/MyServiceModule.hxx> // Declare an instance of the generated YANG module myService::MyServiceModule mgt; // Load the management data from disk SAFplus::MgtDatabase *db = SAFplus::MgtDatabase::getInstance(); db->initializeDB("appData"); // Specify the database file // Tell SAFplus where in the database this module is located. This allows you to put multiple modules inside a single XML file (remember XML files can only have one top level node). mgt.assignPrefix("/myService"); mgt.read(db); // Next bind this data into the cluster-wide management tree so accesses into the NETCONF server running as a separate process on any node will be routed to this application. SAFplus::myHandle = SAFplus::Handle::create(); mgt.bind(SAFplus::myHandle,&mgt.serviceCfg); mgt.bind(SAFplus::myHandle,&mgt.serviceStats); // Now you can -- USE the management configuration data in a manner that is very natural c++: startHttpDaemon(mgt.serviceCfg.port); // And let's inject data into the access count statistic. mgt.serviceStats.accessCounts = currentAccessCount;
So management data access is completely abstracted from the northbound protocol (NETCONF). This allows us to easily support multiple northbound protocols, and makes your C++ code simple to write, understand, and maintain.
This example is exerpted from an application that was then run on 2 separate network elements. The defined data is accessible from a management system running in the NOC through any NETCONF compatible client. SAFplus supplies a graphical CLI which is shown below displaying the serviceCfg and plotting the statistics that were created by this example.