* A new "hello world" example is added

* The directory `docker/system` has been moved to `docker/main`
This commit is contained in:
Olof hagsand 2019-04-17 11:26:05 +02:00
parent d46ca41c8b
commit 14d319dd9b
21 changed files with 382 additions and 11 deletions

1
.gitignore vendored
View file

@ -14,6 +14,7 @@ docker/Makefile
docker/*/Makefile
etc/Makefile
example/Makefile
example/*/Makefile
lib/Makefile
lib/*/Makefile
test/Makefile

View file

@ -35,6 +35,7 @@
### API changes on existing features (you may need to change your code)
* The directory `docker/system` has been moved to `docker/main`, to reflect that it runs the main example.
* xmldb_get() removed "config" parameter:
* Change all calls to dbget from: `xmldb_get(h, db, xpath, 0|1, &xret, msd)` to `xmldb_get(h, db, xpath, &xret, msd)`
* Structural change: removed datastore plugin and directory, and merged into regular clixon lib code.
@ -101,6 +102,7 @@
### Minor changes
* A new "hello world" example is added
* Optimized validation of large lists
* New xmldb_get1() returning actual cache - not a copy. This has lead to some householding instead of just deleting the copy
* xml_diff rewritten to work linearly instead of O(2)

5
configure vendored
View file

@ -4447,7 +4447,7 @@ _ACEOF
ac_config_files="$ac_config_files Makefile lib/Makefile lib/src/Makefile lib/clixon/Makefile apps/Makefile apps/cli/Makefile apps/backend/Makefile apps/netconf/Makefile apps/restconf/Makefile include/Makefile etc/Makefile etc/clixonrc example/Makefile example/main/Makefile extras/rpm/Makefile docker/Makefile docker/system/Makefile docker/base/Makefile util/Makefile yang/Makefile yang/clixon/Makefile yang/standard/Makefile doc/Makefile test/Makefile"
ac_config_files="$ac_config_files Makefile lib/Makefile lib/src/Makefile lib/clixon/Makefile apps/Makefile apps/cli/Makefile apps/backend/Makefile apps/netconf/Makefile apps/restconf/Makefile include/Makefile etc/Makefile etc/clixonrc example/Makefile example/main/Makefile example/hello/Makefile extras/rpm/Makefile docker/Makefile docker/main/Makefile docker/base/Makefile util/Makefile yang/Makefile yang/clixon/Makefile yang/standard/Makefile doc/Makefile test/Makefile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@ -5155,9 +5155,10 @@ do
"etc/clixonrc") CONFIG_FILES="$CONFIG_FILES etc/clixonrc" ;;
"example/Makefile") CONFIG_FILES="$CONFIG_FILES example/Makefile" ;;
"example/main/Makefile") CONFIG_FILES="$CONFIG_FILES example/main/Makefile" ;;
"example/hello/Makefile") CONFIG_FILES="$CONFIG_FILES example/hello/Makefile" ;;
"extras/rpm/Makefile") CONFIG_FILES="$CONFIG_FILES extras/rpm/Makefile" ;;
"docker/Makefile") CONFIG_FILES="$CONFIG_FILES docker/Makefile" ;;
"docker/system/Makefile") CONFIG_FILES="$CONFIG_FILES docker/system/Makefile" ;;
"docker/main/Makefile") CONFIG_FILES="$CONFIG_FILES docker/main/Makefile" ;;
"docker/base/Makefile") CONFIG_FILES="$CONFIG_FILES docker/base/Makefile" ;;
"util/Makefile") CONFIG_FILES="$CONFIG_FILES util/Makefile" ;;
"yang/Makefile") CONFIG_FILES="$CONFIG_FILES yang/Makefile" ;;

View file

@ -249,9 +249,10 @@ AC_OUTPUT(Makefile
etc/clixonrc
example/Makefile
example/main/Makefile
example/hello/Makefile
extras/rpm/Makefile
docker/Makefile
docker/system/Makefile
docker/main/Makefile
docker/base/Makefile
util/Makefile
yang/Makefile

View file

@ -6,6 +6,7 @@
* [Is Clixon extendible?](#is-clixon-extendible)
* [Which programming language is used?](#which-programming-language-is-used)
* [How to best understand Clixon?](#how-to-best-understand-clixon)
* [Hello world?](#hello-world)
* [How do you build and install Clixon (and the example)?](how-do-you-build-and-install-clixon)
* [How do I run Clixon example commands?](#how-do-i-run-clixon-example-commands)
* [Do I need to setup anything? (IMPORTANT)](#do-i-need-to-setup-anything))
@ -67,6 +68,10 @@ specification uses [CLIgen](http://github.com/olofhagsand/cligen)
## How to best understand Clixon?
Run the Clixon example, in the [example](../example) directory.
## Hello world?
One of the examples is [a hello world example](../example/hello). Please start with that.
## How do you build and install Clixon?
Clixon:
```

View file

@ -41,7 +41,7 @@ LIBS = @LIBS@
SHELL = /bin/sh
SUBDIRS = base
SUBDIRS += system
SUBDIRS += main
#SUBDIRS += cluster
.PHONY: all clean distclean depend install-include install uninstall test $(SUBDIRS)

View file

@ -3,5 +3,5 @@
This directory contains sub-directories with examples of Clixon docker images:
* [base](base/README.md) Clixon base image
* [system](system/README.md) Example and test application
* [main](main/README.md) Main example and test application

View file

@ -8,7 +8,7 @@ The clixon docker base image can be used to build clixon
applications. It has all the whole code for a clixon release which it
downloads from git.
See [clixon-system](../system/README.md) for a more complete clixon image.
See [clixon-system](../main/README.md) for a more complete clixon image.
## Build and push
@ -20,7 +20,7 @@ You may also do `make push` if you want to push the image, but you may then cons
## Example run
The base container is a minimal and primitive example. Look at the [clixon-system](../system) for a more stream-lined application.
The base container is a minimal and primitive example. Look at the [clixon-system](../main) for a more stream-lined application.
The following shows a simple example of how to run the example
application. First, the container is started with the backend running:

View file

@ -2,3 +2,5 @@
Clixon have the following examples:
* [Main example](main/README.md)
* [Hello world](hello/README.md)

167
example/hello/Makefile.in Normal file
View file

@ -0,0 +1,167 @@
#
# ***** BEGIN LICENSE BLOCK *****
#
# Copyright (C) 2009-2019 Olof Hagsand and Benny Holmgren
#
# This file is part of CLIXON
#
# 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.
#
# Alternatively, the contents of this file may be used under the terms of
# the GNU General Public License Version 3 or later (the "GPL"),
# in which case the provisions of the GPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of the GPL, and not to allow others to
# use your version of this file under the terms of Apache License version 2,
# indicate your decision by deleting the provisions above and replace them with
# the notice and other provisions required by the GPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the Apache License version 2 or the GPL.
#
# ***** END LICENSE BLOCK *****
#
VPATH = @srcdir@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
prefix = @prefix@
bindir = @bindir@
includedir = @includedir@
datarootdir = @datarootdir@
sysconfdir = @sysconfdir@
datarootdir = @datarootdir@
localstatedir = @localstatedir@
libdir = @exec_prefix@/lib
APPNAME = hello
# Here is where example yang appears
CLIXON_DATADIR = @CLIXON_DATADIR@
# Install here if you want default clixon location:
CLIXON_DEFAULT_CONFIG = @CLIXON_DEFAULT_CONFIG@
CC = @CC@
CFLAGS = @CFLAGS@ -rdynamic -fPIC
INSTALLFLAGS = @INSTALLFLAGS@
with_restconf = @with_restconf@
INCLUDES = -I$(includedir) @INCLUDES@
CPPFLAGS = @CPPFLAGS@ -fPIC
BE_PLUGIN = $(APPNAME)_backend.so
CLI_PLUGIN = $(APPNAME)_cli.so
NETCONF_PLUGIN = $(APPNAME)_netconf.so
RESTCONF_PLUGIN = $(APPNAME)_restconf.so
PLUGINS = $(BE_PLUGIN) $(CLI_PLUGIN) $(NETCONF_PLUGIN)
ifeq ($(with_restconf),yes)
PLUGINS += $(RESTCONF_PLUGIN)
endif
.PHONY: all clean depend install
all: $(PLUGINS)
.SUFFIXES: .c .o
# implicit rule
.c.o:
$(CC) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) -c $<
CLISPECS = $(APPNAME)_cli.cli
YANGSPECS = clixon-hello@2019-04-17.yang
# CLI frontend plugin (see also install rule)
#CLI_SRC = $(APPNAME)_cli.c
CLI_OBJ = $(CLI_SRC:%.c=%.o)
$(CLI_PLUGIN): $(CLI_OBJ)
$(CC) -Wall -shared -o $@ -lc $^
# Backend plugin (see also install rule)
#BE_SRC = $(APPNAME)_backend.c
BE_OBJ = $(BE_SRC:%.c=%.o)
$(BE_PLUGIN): $(BE_OBJ)
$(CC) -Wall -shared -o $@ -lc $<
# NETCONF frontend plugin (see also install rule)
#NETCONF_SRC = $(APPNAME)_netconf.c
NETCONF_OBJ = $(NETCONF_SRC:%.c=%.o)
$(NETCONF_PLUGIN): $(NETCONF_OBJ)
$(CC) -Wall -shared -o $@ -lc $^
# See configure.ac for disabling restconf
# RESTCONF frontend plugin (see also install rule)
#RESTCONF_SRC = $(APPNAME)_restconf.c
RESTCONF_OBJ = $(RESTCONF_SRC:%.c=%.o)
$(RESTCONF_PLUGIN): $(RESTCONF_OBJ)
$(CC) -Wall -shared -o $@ -lc $^
SRC = $(BE_SRC) $(CLI_SRC) $(NETCONF_SRC)
SRC += $(RESTCONF_SRC)
OBJS = $(BE_OBJ) $(CLI_OBJ) $(NETCONF_OBJ)
OBJS += $(RESTCONF_OBJ)
clean:
rm -f $(PLUGINS) $(OBJS)
distclean: clean
rm -f Makefile *~ .depend
install: $(YANGSPECS) $(CLISPECS) $(PLUGINS) $(APPNAME).xml
install -m 0644 $(APPNAME).xml $(DESTDIR)$(CLIXON_DEFAULT_CONFIG)
install -d -m 0755 $(DESTDIR)$(libdir)/$(APPNAME)
install -d -m 0755 $(DESTDIR)$(libdir)/$(APPNAME)/clispec
install -m 0644 $(CLISPECS) $(DESTDIR)$(libdir)/$(APPNAME)/clispec
install -d -m 0755 $(DESTDIR)$(datarootdir)/$(APPNAME)/yang
install -m 0644 $(YANGSPECS) $(DESTDIR)$(DESTDIR)$(CLIXON_DATADIR)
install -d -m 0755 $(DESTDIR)$(localstatedir)/$(APPNAME)
# Uncomment for installing config file in /usr/local/etc instead
# install -d -m 0755 $(DESTDIR)$(sysconfdir)
# install -m 0644 $(APPNAME).xml $(DESTDIR)$(sysconfdir)
# Uncomment for installing cli plugin (see CLI_SRC)
# install -d -m 0755 $(DESTDIR)$(libdir)/$(APPNAME)/cli
# install -m 0644 $(INSTALLFLAGS) $(CLI_PLUGIN) $(DESTDIR)$(libdir)/$(APPNAME)/cli
# Uncomment for installing backend plugin (see BE_SRC)
# install -d -m 0755 $(DESTDIR)$(libdir)/$(APPNAME)/backend
# install -m 0644 $(INSTALLFLAGS) $(BE_PLUGIN) $(DESTDIR)$(libdir)/$(APPNAME)/backend
# Uncomment for installing netconf plugin (see NETCONF_SRC)
# install -d -m 0755 $(DESTDIR)$(libdir)/$(APPNAME)/netconf
# install -m 0644 $(INSTALLFLAGS) $(NETCONF_PLUGIN) $(DESTDIR)$(libdir)/$(APPNAME)/netconf
# Uncomment for installing restconf plugin (see RESTCONF_SRC). The conditional is
# because it is an option to disable restconf
#ifeq ($(with_restconf),yes)
# install -d -m 0755 $(DESTDIR)$(libdir)/$(APPNAME)/restconf
# install -m 0644 $(INSTALLFLAGS) $(RESTCONF_PLUGIN) $(DESTDIR)$(libdir)/$(APPNAME)/restconf
#endif
uninstall:
rm -rf $(DESTDIR)$(CLIXON_DEFAULT_CONFIG)
rm -rf $(DESTDIR)$(libdir)/$(APPNAME)
rm -rf $(DESTDIR)$(localstatedir)/$(APPNAME)
rm -rf $(DESTDIR)$(datarootdir)/$(APPNAME)
install-include:
depend:
$(CC) $(DEPENDFLAGS) $(INCLUDES) $(CFLAGS) -MM $(SRC) > .depend
#include .depend

111
example/hello/README.md Normal file
View file

@ -0,0 +1,111 @@
# Clixon hello world example
* [Content](#content)
* [Compile and run](#compile)
* [Using the CLI](#using-the-cli)
* [Netconf](#netconf)
* [Restconf](#restconf)
* [Next steps](#next-steps)
## Content
This directory contains a Clixon example which includes a simple example. It contains the following files:
* `hello.xml` The configuration file. See [yang/clixon-config@<date>.yang](../../yang/clixon-config@2019-03-05.yang) for the documentation of all available fields.
* `clixon-hello@2019-04-17.yang` The yang spec of the example.
* `hello_cli.cli` CLIgen specification.
* `Makefile.in` Example makefile where plugins are built and installed
* `README.md` This file
## Compile and run
Before you start,
* Make [group setup](../../doc/FAQ.md#do-i-need-to-setup-anything-important)
```
make && sudo make install
```
Start backend in the background:
```
sudo clixon_backend
```
Start cli:
```
clixon_cli
```
## Using the CLI
The example CLI allows you to modify and view the data model using `set`, `delete` and `show` via generated code.
The following example shows how to add a very simple configuration `hello world` using the generated CLI. The config is added to the candidate database, shown, committed to running, and then deleted.
```
olof@vandal> clixon_cli
cli> set <?>
hello
cli> set hello world
cli> show configuration
hello world;
cli> commit
cli> delete <?>
all Delete whole candidate configuration
hello
cli> delete hello
cli> show configuration
cli> commit
cli> quit
olof@vandal>
```
## Netconf
Clixon also provides a Netconf interface. The following example starts a netconf client form the shell, adds the hello world config, commits it, and shows it:
```
olof@vandal> clixon_netconf -q
<rpc><edit-config><target><candidate/></target><config><hello xmlns="urn:example:hello"><world/></hello></config></edit-config></rpc>]]>]]>
<rpc-reply><ok/></rpc-reply>]]>]]>
<rpc><commit/></rpc>]]>]]>
<rpc-reply><ok/></rpc-reply>]]>]]>
<rpc><get-config><source><running/></source></get-config></rpc>]]>]]>
<rpc-reply><data><hello xmlns="urn:example:hello"><world/></hello></data></rpc-reply>]]>]]>
olof@vandal>
```
## Restconf
Clixon also provides a Restconf interface. A reverse proxy needs to be configured. There are [instructions how to setup Nginx](../../doc/FAQ.md#how-do-i-use-restconf) for Clixon.
Start restconf daemon
```
sudo su -c "/www-data/clixon_restconf" -s /bin/sh www-data &
```
Start sending restconf commands (using Curl):
```
olof@vandal> curl -X POST http://localhost/restconf/data -d '{"clixon-hello:hello":{"world":null}}'
olof@vandal> curl -X GET http://localhost/restconf/data
{
"data": {
"clixon-hello:hello": {
"world": null
}
}
}
```
## Next steps
The hello world example only has a Yang spec and a template CLI
spec. For more advanced applications, customized backend, cli, netconf
and restconf code callbacks becomes necessary.
Further, you may want to add upgrade, RPC:s, state data, notification
streams, authentication and authorization. The [main example](../main)
contains examples for such capabilities.
There are also [container examples](../../docker) and lots more.

View file

@ -0,0 +1,14 @@
module clixon-hello {
yang-version 1.1;
namespace "urn:example:hello";
prefix he;
revision 2019-04-17 {
description
"Clixon hello world example";
}
container hello{
container world{
presence true;
}
}
}

13
example/hello/hello.xml Normal file
View file

@ -0,0 +1,13 @@
<clixon-config xmlns="http://clicon.org/config">
<CLICON_CONFIGFILE>/usr/local/etc/example.xml</CLICON_CONFIGFILE>
<CLICON_FEATURE>*:*</CLICON_FEATURE>
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
<CLICON_YANG_MODULE_MAIN>clixon-hello</CLICON_YANG_MODULE_MAIN>
<CLICON_CLI_MODE>hello</CLICON_CLI_MODE>
<CLICON_CLISPEC_DIR>/usr/local/lib/hello/clispec</CLICON_CLISPEC_DIR>
<CLICON_SOCK>/usr/local/var/hello.sock</CLICON_SOCK>
<CLICON_BACKEND_PIDFILE>/usr/local/var/hello.pidfile</CLICON_BACKEND_PIDFILE>
<CLICON_XMLDB_DIR>/usr/local/var/hello</CLICON_XMLDB_DIR>
<CLICON_STARTUP_MODE>init</CLICON_STARTUP_MODE>
<CLICON_MODULE_LIBRARY_RFC7895>false</CLICON_MODULE_LIBRARY_RFC7895>
</clixon-config>

View file

@ -0,0 +1,54 @@
# Common CLI syntax for both server and PMNode operatio mode
CLICON_MODE="hello";
CLICON_PROMPT="cli> ";
# Reference generated data model
set @datamodel, cli_set();
merge @datamodel, cli_merge();
create @datamodel, cli_create();
delete("Delete a configuration item") @datamodel, cli_del();
validate("Validate changes"), cli_validate();
commit("Commit the changes"), cli_commit();
quit("Quit"), cli_quit();
delete("Delete a configuration item") all("Delete whole candidate configuration"), delete_all("candidate");
startup("Store running as startup config"), db_copy("running", "startup");
no("Negate or remove") debug("Debugging parts of the system"), cli_debug_cli((int32)0);
debug("Debugging parts of the system"), cli_debug_cli((int32)1);{
level("Set debug level: 1..n") <level:int32>("Set debug level (0..n)"), cli_debug_backend();
}
discard("Discard edits (rollback 0)"), discard_changes();
compare("Compare running and candidate"), compare_dbs((int32)1);
show("Show a particular state of the system"){
xpath("Show configuration") <xpath:string>("XPATH expression"), show_conf_xpath("candidate");
version("Show version"), cli_show_version("candidate", "text", "/");
compare("Compare candidate and running databases"), compare_dbs((int32)0);{
xml("Show comparison in xml"), compare_dbs((int32)0);
text("Show comparison in text"), compare_dbs((int32)1);
}
configuration("Show configuration"), cli_show_config("candidate", "text", "/");{
xml("Show configuration as XML"), cli_show_config("candidate", "xml", "/");{
@datamodel, cli_show_auto("candidate", "xml");
}
cli("Show configuration as CLI commands"), cli_show_config("candidate", "cli", "/");{
@datamodel, cli_show_auto("candidate", "cli");
}
netconf("Show configuration as netconf edit-config operation"), cli_show_config("candidate", "netconf", "/");{
@datamodel, cli_show_auto("candidate", "netconf");
}
text("Show configuration as text"), cli_show_config("candidate","text","/");{
@datamodel, cli_show_auto("candidate", "text");
}
json("Show configuration as JSON"), cli_show_config("candidate", "json", "/");{
@datamodel, cli_show_auto("candidate", "json");
}
}
}
save("Save candidate configuration to XML file") <filename:string>("Filename (local filename)"), save_config_file("candidate","filename");
load("Load configuration from XML file") <filename:string>("Filename (local filename)"),load_config_file("filename", "replace");{
replace("Replace candidate with file contents"), load_config_file("filename", "replace");
merge("Merge file with existent candidate"), load_config_file("filename", "merge");
}

View file

@ -15,7 +15,7 @@
## Content
This directory contains a Clixon example which includes a simple example. It contains the following files:
* `example.xml` The configuration file. See [yang/clixon-config@<date>.yang](../../yang/clixon-config@2018-10-21.yang) for the documentation of all available fields.
* `example.xml` The configuration file. See [yang/clixon-config@<date>.yang](../../yang/clixon-config@2019-03-05.yang) for the documentation of all available fields.
* `clixon-example@2019-01-13.yang` The yang spec of the example.
* `example_cli.cli` CLIgen specification.
* `example_cli.c` CLI callback plugin containing functions called in the cli file above: a generic callback (`mycallback`) and an example RPC call (`example_client_rpc`).