== Overview == This document describes how to develop management aware applications using SAFplus Management. It assumes that SAFplus Management has been installed on your system. For information on how to install SAFplus Management, see [[SAFplus Management User's Guide]]. This document should be used in conjunction with the SAFplus Management example web services application available via download or in our source tree at (.../examples/eval/websvc). The next section of the document will show you how to compile and run this example application. Once that is complete, the "Development" section will explain how the application works and how to extend it. === Getting Started === ==== Using an existing example provided by OpenClovis ==== The example program creates a small web server and lets the user use NETCONF to configure user access to it. To build you must first install a small web server library used in this example: {{{ sudo apt-get install libmicrohttpd-dev }}} Next, download the example source code file "SAFplusMgtEval.tgz" from download.openclovis.com and detar it: {{{ wget http://download.openclovis.com/files/examples/SAFplusMgtEval.tgz tar xvfz SAFplusMgtEval.tgz }}} Finally, let's build and run it to ensure that SAFplus is properly installed {{{ cd eval/websvc make }}} ==== Build your own MGT-enabled application ==== Before building your own MGT-enabled application, you must be familiar with YANG - A Data Modeling Language for Network Configuration Protocol (NETCONF) (https://tools.ietf.org/html/rfc6020) Follow these steps below: 1. Create the yang model adapting to your requirements 2. Generate the C++ headers and source files: see the SAFplus-MGT/pyplugin/README 3. Change directory to your generated codes folder which contains main.c and Make there == Running == Next stop safplus_mgt if it is running: {{{ pkill -9 safplus_mgt }}} and set up the SAFPLUS_MODULES_PATH to point to our module and the OpenClovis common modules (alongside the other environment variables you set up in [[SAFplus Management User's Guide#Environment_Variables|SAFplus Management User's Guide#Environment Variables]]: {{{ export SAFPLUS_MODULES_PATH=/home/clovis/eval/websvc/target/share/modules/openclovis:/opt/safplus/7.0/mgt/share/netconf/modules }}} Now restart safplus_mgt: == RESTCONF configuration == 1. RESTCONF server must create X.509 certificates (i.e using OpenSSL) {{{ /opt/safplus/7.0/mgt $ openssl genrsa -out ./server.key 1024 /opt/safplus/7.0/mgt $ openssl req -days 365 -out ./server.pem -new -x509 -key ./server.key -subj "/O=www.example.com/" }}} 1.#2 RESTCONF server must be authenticated client use TLS certificates and standard HTTP Authentication scheme (HTTPs). a.#1 Create a PAM service restconf (/etc/pam.d/resconf): {{{#!highlight xml # check authorization auth required pam_unix.so account required pam_unix.so }}} a.#2 The authentication also supports via plugin (using PAM by default) and point to this custom by exporting environment variable SAFPLUS_MGT_AUTH. The custom plugin must derived from base class MgtAuthenticationPlugin_1 as following: {{{#!highlight c++ class MgtCustomPlugin: public MgtAuthenticationPlugin_1 { public: virtual bool isAuthenticated(const std::string &user, const std::string &password); }; }}} {{{ /opt/safplus/7.0/mgt $ ./mgt_start }}} Your module needs to be loaded by safplus_mgt. You should see the following log: {{{ Mon Mar 7 13:05:16.812 2016 [mgtNetconfYuma.cxx:905] (.13310.13323 : MGT.MOD.LOAD:00042 : DEBUG) Found YANG file [/home/clovis/eval/websvc/target/share/modules/openclovis/myService.yang] Mon Mar 7 13:05:16.814 2016 [mgtNetconfYuma.cxx:465] (.13310.13323 : MGT.MGT.YUMA:00043 : DEBUG) Registering [container] callbacks for xpath: [/myService] Mon Mar 7 13:05:16.814 2016 [mgtNetconfYuma.cxx:735] (.13310.13323 : MGT.MGT.YUMA:00044 : DEBUG) Registering 'get' callback for node: [myService:myService] }}} Now, in a different window run our "websvc" application. You need to set up the standard SAFPLUS runtime environment variables, as described in the installation. {{{ $ export LD_LIBRARY_PATH=/opt/safplus/7.0/mgt/target/lib:/opt/safplus/7.0/sdk/target/x86_64-linux-gnu/lib:/opt/safplus/7.0/sdk/target/x86_64-linux-gnu/plugin:~/eval/websvc/target $ export SAFPLUS_BACKPLANE_INTERFACE=eth0 $ ~/eval/websvc/target/mgtApp }}} The application should start up and near the bottom you should see the following log: {{{ Mon Mar 7 12:48:22.963 2016 [clMgtRoot.cxx:98] (.13008.13008 : .MGT.LOAD:00026 : INFO) Bound xpath [/myService] to local object }}} This log indicates that your application bound itself to the NETCONF myService module. Now you should be able to access our application via the "myService" module in any NETCONF client. For example, from the safplus_cli {{{ /> add module /home/clovis/eval/websvc/target/share/modules/openclovis/myService.yang /> add element loc clovis clovis localhost /loc> cd myService /loc/myService> ls /networkElement/loc/myService: myService config statistics subscribers /loc/myService> ls config /networkElement/loc/myService/config: config homeLocation:/srv/http port:8080 }}} Please see the [[SAFplus Management User's Guide]] for a detailed description of CLI commands. == Development == == Debugging == === Debugging the initial startup of your application === * '''Be tolerant of long instantiation times''' The SAFplus AMF will restart an application that exceeds its "instantiation timeout" (30 seconds by default). This will disrupt debugging efforts. To fix this issue, change the component's instantiation timeout. This can be accomplished in a variety of ways... to do it via XML file, look for your the definition in your component (tags: component->instantiate->timeout) and change it to a very large number. For example: {{{#!highlight xml ... ./mycomp 1000000000 ... }}} * '''Start gdb instead of your program''' Rename your program 'X' to X.bin. Next create an executable script X with this content: {{{#!highlight bash #!/bin/bash echo /usr/bin/gnome-terminal --disable-factory --window --command "gdb --args $0.bin $1 $2 $3 $4 $5 $6 $7 $8 $9" exec /usr/bin/gnome-terminal --disable-factory --window --command "gdb --args $0.bin $1 $2 $3 $4 $5 $6 $7 $8 $9" }}} Now when SAFplus AMF starts your program, it will pop up a terminal window and run your program inside gdb. It is important that the process id (PID) of the terminal be the same PID that SAFplus AMF started so that it can monitor your program. This is the purpose of the "exec" prefix and the --disable-factory flag. If your process forks another process and quits, the AMF will see this as a failure (your process quit, after all) and restart it. This can result in repeated restarts. == Troubleshooting == * '''My module does not show up in the safplus_cli''' First ensure that your module is found by safplus_mgt. Look in safplus_mgt log (stdout) for a log like: {{{ Mon Mar 7 12:48:24.445 2016 [mgtNetconfYuma.cxx:905] (.12976.12989 : MGT.MOD.LOAD:00049 : DEBUG) Found YANG file [/home/clovis/eval/websvc/target/share/modules/openclovis/myService.yang] }}} If your module is not found, ensure that its location has been added to the SAFPLUS_MODULES_PATH directory. You should see something like this: {{{ Mon Mar 7 12:48:24.431 2016 [mgtNetconfYuma.cxx:899] (.12976.12989 : MGT.MOD.CHK:00048 : DEBUG) Lookup YANG file at directory [/home/clovis/eval/websvc/target/share/modules/openclovis] }}} If your module is found, ensure that safplus_mgt properly loaded your module. Look in netconfd.log or the safplus_mgt log for errors like {{{ Mon Mar 7 12:48:24.447 2016 [mgtNetconfYuma.cxx:909] (.12976.12989 : MGT.MOD.LOAD:00050 : WARN) Parse YANG file [/home/clovis/eval/websvc/target/share/modules/openclovis/myService.yang] failed, error [0x14c] Mon Mar 7 12:48:24.448 2016 [mgtNetconfYuma.cxx:918] (.12976.12989 : MGT.MOD.INIT:00051 : WARN) Register callback for module [myService.yang] failed, error [0xec] }}} {{{ Error: 'myService.yang' import of module 'SAFplusTypes' failed myService.yang:5.3: error(236): module not found Load module 'myService' failed (module not found) }}} If this is the problem, related logs should describe the exact nature of the problem. the problem could be a missing dependency (as shown above) or a syntax error in your module. === SNMP issues === {{{ $ snmpwalk -v 2c -c clovis 127.0.0.1 MYSERVICE-MIB::myService MYSERVICE-MIB::subscribers = No Such Object available on this agent at this OID }}} This can be caused by some of reasons and each have a particular solutions. In case, you did not find out a root cause. Please try with a tip as following: 1. Make sure your MIB named with the following conventions: a. Use all uppercase letters, and use hyphens to separate segments of the file name. a. Include MIB as the last segment of the name. a. Append a .txt file extension. {{{ Thu Mar 17 10:31:44.586 2016 [mgtMain.cxx:243] (node0.16697.16709 : MGT.MGT.SNMP:00088 : ERROR) Warning: Failed to connect to the agentx master agent (tcp:localhost:3456): }}} ===== Reasons ===== 1. snmpd could not running due to permission i.e root privilege => change default port listening from '''161''' to '''1610''' in ./share/snmp/snmpd.conf 1. snmpd deamon did not running via mgt_start script, lead to missing configuration on subgagent socket listening (i.e tcp:localhost:3456). 1. subagent should be connect to master Agent via socket connection that configured at configuration file (i.e ./share/snmp/subagent.conf or located by exporting variable environment SNMPCONFPATH)