diff --git a/configs/aarch64_defconfig b/configs/aarch64_defconfig index 887fa2b4..620cf446 100644 --- a/configs/aarch64_defconfig +++ b/configs/aarch64_defconfig @@ -131,6 +131,7 @@ BR2_PACKAGE_FINIT_PLUGIN_RTC=y BR2_PACKAGE_FINIT_PLUGIN_TTY=y BR2_PACKAGE_FINIT_PLUGIN_URANDOM=y BR2_PACKAGE_IFUPDOWN_NG=y +BR2_PACKAGE_KLINFIX=y BR2_PACKAGE_KLISH=y BR2_PACKAGE_KLISH_PLUGIN_SYSREPO=y BR2_PACKAGE_P_NET=y diff --git a/configs/amd64_defconfig b/configs/amd64_defconfig index 5356cafe..60170bdc 100644 --- a/configs/amd64_defconfig +++ b/configs/amd64_defconfig @@ -134,6 +134,7 @@ BR2_PACKAGE_FINIT_PLUGIN_RTC=y BR2_PACKAGE_FINIT_PLUGIN_TTY=y BR2_PACKAGE_FINIT_PLUGIN_URANDOM=y BR2_PACKAGE_IFUPDOWN_NG=y +BR2_PACKAGE_KLINFIX=y BR2_PACKAGE_KLISH=y BR2_PACKAGE_KLISH_PLUGIN_SYSREPO=y BR2_PACKAGE_P_NET=y diff --git a/package/Config.in b/package/Config.in index a0a0a24f..f9e24aff 100644 --- a/package/Config.in +++ b/package/Config.in @@ -6,6 +6,7 @@ source "$BR2_EXTERNAL_INFIX_PATH/package/faux/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/finit/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/ifupdown2/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/ifupdown-ng/Config.in" +source "$BR2_EXTERNAL_INFIX_PATH/package/klinfix/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/klish/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/klish-plugin-sysrepo/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/mdnsd/Config.in" diff --git a/package/klinfix/Config.in b/package/klinfix/Config.in new file mode 100644 index 00000000..933d1289 --- /dev/null +++ b/package/klinfix/Config.in @@ -0,0 +1,8 @@ +config BR2_PACKAGE_KLINFIX + bool "klinfix" + select BR2_PACKAGE_KLISH + select BR2_PACKAGE_KLISH_PLUGIN_SYSREPO + select BR2_PACKAGE_SYSREPO + help + A plugin to klish with an opinionated config and some + command extensions, suitable for systems running Infix. diff --git a/package/klinfix/klinfix.mk b/package/klinfix/klinfix.mk new file mode 100644 index 00000000..d2f88539 --- /dev/null +++ b/package/klinfix/klinfix.mk @@ -0,0 +1,14 @@ +################################################################################ +# +# klinfix +# +################################################################################ + +KLINFIX_VERSION = 1.0 +KLINFIX_LICENSE = BSD-3-Clause +KLINFIX_SITE_METHOD = local +KLINFIX_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/klinfix +KLINFIX_DEPENDENCIES = klish-plugin-sysrepo +KLINFIX_AUTORECONF = YES + +$(eval $(autotools-package)) diff --git a/package/klish-plugin-sysrepo/Config.in b/package/klish-plugin-sysrepo/Config.in index b61e20b9..b9c735e8 100644 --- a/package/klish-plugin-sysrepo/Config.in +++ b/package/klish-plugin-sysrepo/Config.in @@ -13,6 +13,7 @@ config BR2_PACKAGE_KLISH_PLUGIN_SYSREPO config BR2_PACKAGE_KLISH_PLUGIN_SYSREPO_XML bool "install xml" depends on BR2_PACKAGE_KLISH_PLUGIN_SYSREPO + depends on !BR2_PACKAGE_KLINFIX default y help Install the default XML spec bundled with the project, which diff --git a/package/klish/Config.in b/package/klish/Config.in index 9f55b085..e3f03e0e 100644 --- a/package/klish/Config.in +++ b/package/klish/Config.in @@ -12,6 +12,7 @@ config BR2_PACKAGE_KLISH config BR2_PACKAGE_KLISH_DEFAULT_XML bool "install xml" depends on BR2_PACKAGE_KLISH + depends on !BR2_PACKAGE_KLINFIX default y help Install a small XML spec containing a definition of an diff --git a/src/klinfix/.gitignore b/src/klinfix/.gitignore new file mode 100644 index 00000000..e9e8e747 --- /dev/null +++ b/src/klinfix/.gitignore @@ -0,0 +1,33 @@ +*~ +*.o +*.la +*.lo +*.so +.deps +.libs + +/aclocal.m4 +/autom4te.cache/ +/aux +/clixon.xml +/compile +/config.h +/config.h.in +/config.guess +/config.log +/config.status +/config.sub +/configure +/depcomp +/install-sh +/libtool +/ltmain.sh +/m4 +/missing + +GPATH +GRTAGS +GTAGS +Makefile +Makefile.in + diff --git a/src/klinfix/Makefile.am b/src/klinfix/Makefile.am new file mode 100644 index 00000000..cb106dee --- /dev/null +++ b/src/klinfix/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = src xml +DISTCLEANFILES = *~ *.d +ACLOCAL_AMFLAGS = -I m4 diff --git a/src/klinfix/README.md b/src/klinfix/README.md new file mode 100644 index 00000000..7dfcc518 --- /dev/null +++ b/src/klinfix/README.md @@ -0,0 +1,74 @@ +Infix Extensions to klish-plugin-sysrepo +---------------------------------------- + +Tailor `klish` and `klish-plugin-sysrepo` to suit Infix. The resulting +CLI is, in many respects, still very similar to Juniper's JunOS, since +that is also the primary inspiration for klish, with some additions +and modifications. + +Broadly speaking, the CLI is split up in two major modes: + +- Admin/Exec: This is the default mode, where operational commands can + be issued. +- Configure: Where a new candidate configuration is prepared. + + +### Admin/Exec Mode + +The following table lists the available commands: + +| Command | Description | Hotkey | +|--------------------|---------------------------------------|--------| +| `configure` | Enter configuration mode | | +| `copy ` | Copy `` to `` | | +| `exit` | Exit | `C-d` | +| `logout` | Alias for `exit` | | +| `shell` | Start system shell | | +| `show ` | Show various configuration and status | | + +#### Copy Command + +`copy ` + +Where `` is one of: +- `factory-config` +- `startup-config` +- `running-config` + +And `` is one of: +- `startup-config` +- `running-config` + +#### Show Command + +`show ` + +The following table lists the available items: + +| Item | Description | +|------------------|--------------------------------------| +| `running-config` | Show the active system configuration | +| | | + + +### Configure + +The following table lists the available commands: + +| Command | Description | Hotkey | +|------------|--------------------------------------------------------------|--------| +| `abort` | Abandon candidate | `C-d` | +| `check` | Validate candidate | | +| `commit` | Commit current candidate to running-config | | +| `delete` | Delete configuration setting(s) | | +| `diff` | Summarize uncommitted changes | | +| `do` | Execute operational mode command | | +| `edit` | Descend to the specified configuration node | | +| `exit` | Ascend to the parent configuration node, or abort (from top) | | +| `leave` | Finalize candidate and apply to running-config | `C-z` | +| `no` | Alias for delete | | +| `rollback` | Restore candidate to running-config | | +| `set` | Set configuration setting | | +| `show` | Show configuration | | +| `top` | Ascend to the configuration root | | +| `up` | Ascend to the parent configuration node | `C-c` | diff --git a/src/klinfix/autogen.sh b/src/klinfix/autogen.sh new file mode 100755 index 00000000..69ad0e18 --- /dev/null +++ b/src/klinfix/autogen.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +autoreconf -W portability -vifm diff --git a/src/klinfix/configure.ac b/src/klinfix/configure.ac new file mode 100644 index 00000000..06f0af1d --- /dev/null +++ b/src/klinfix/configure.ac @@ -0,0 +1,33 @@ +AC_PREREQ(2.61) +AC_INIT([klinfix], [1.0.0], + [https://github.com/kernelkit/infix/issues]) +AM_INIT_AUTOMAKE(1.11 foreign subdir-objects) +AM_SILENT_RULES(yes) + +LT_INIT + +AC_CONFIG_FILES([ + Makefile + src/Makefile + xml/Makefile +]) + +AC_PROG_CC +AC_PROG_INSTALL + +# Check for pkg-config first, warn if it's not installed +PKG_PROG_PKG_CONFIG + +PKG_CHECK_MODULES([sysrepo], [sysrepo >= 2.2.60]) +AC_CHECK_LIB([klish], [kplugin_new],, AC_MSG_ERROR([Klish not found])) + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +KLISHLIBDIR=`eval echo $libdir/klish` +AC_SUBST(KLISHLIBDIR) + +KLISHCONFDIR=`eval echo $sysconfdir/klish` +AC_SUBST(KLISHCONFDIR) + +AC_OUTPUT diff --git a/src/klinfix/src/Makefile.am b/src/klinfix/src/Makefile.am new file mode 100644 index 00000000..5e236e85 --- /dev/null +++ b/src/klinfix/src/Makefile.am @@ -0,0 +1,9 @@ +CFLAGS = -Wall -Wextra -Werror -Wno-unused-parameter + +pluginsdir = $(KLISHLIBDIR)/plugins +plugins_LTLIBRARIES = kplugin-klinfix.la + +kplugin_klinfix_la_CFLAGS = $(sysrepo_CFLAGS) $(klish_CFLAGS) $(CFLAGS) +kplugin_klinfix_la_LIBADD = $(sysrepo_LIBS) $(klish_LIBS) +kplugin_klinfix_la_LDFLAGS = -module -avoid-version -shared +kplugin_klinfix_la_SOURCES = klinfix.c diff --git a/src/klinfix/src/klinfix.c b/src/klinfix/src/klinfix.c new file mode 100644 index 00000000..8abd910f --- /dev/null +++ b/src/klinfix/src/klinfix.c @@ -0,0 +1,155 @@ +#include +#include + +#include +#include + +#include +#include + +const uint8_t kplugin_klinfix_major = 1; +const uint8_t kplugin_klinfix_minor = 0; + +int klix_ds_from_str(const char *text, sr_datastore_t *ds) +{ + size_t len = strlen(text); + + if (!strncmp("startup-config", text, len)) + *ds = SR_DS_STARTUP; + else if (!strncmp("running-config", text, len)) + *ds = SR_DS_RUNNING; + else if (!strncmp("candidate-config", text, len)) + *ds = SR_DS_CANDIDATE; + else if (!strncmp("operational-config", text, len)) + *ds = SR_DS_OPERATIONAL; + else if (!strncmp("factory-config", text, len)) + *ds = SR_DS_FACTORY_DEFAULT; + else + return -1; + + return 0; +} + +int klix_copy(kcontext_t *ctx) +{ + kpargv_t *pargv = kcontext_pargv(ctx); + sr_datastore_t srcds, dstds; + kparg_t *srcarg, *dstarg; + sr_session_ctx_t *sess; + sr_conn_ctx_t *conn; + int err; + + srcarg = kpargv_find(pargv, "src"); + dstarg = kpargv_find(pargv, "dst"); + if (!srcarg || !dstarg) + goto err; + + if (klix_ds_from_str(kparg_value(srcarg), &srcds)) { + fprintf(stderr, + "Error: \"%s\" is not the name of any known datastore\n", + kparg_value(srcarg)); + goto err; + } + if (klix_ds_from_str(kparg_value(dstarg), &dstds)) { + fprintf(stderr, + "Error: \"%s\" is not the name of any known datastore\n", + kparg_value(dstarg)); + goto err; + } + + switch (srcds) { + case SR_DS_STARTUP: + case SR_DS_RUNNING: + case SR_DS_FACTORY_DEFAULT: + break; + default: + fprintf(stderr, + "Error: \"%s\" is not a valid source datastore\n", + kparg_value(srcarg)); + goto err; + } + + switch (dstds) { + case SR_DS_STARTUP: + case SR_DS_RUNNING: + break; + default: + fprintf(stderr, + "Error: \"%s\" is not a valid destination datastore\n", + kparg_value(dstarg)); + goto err; + } + + if (sr_connect(SR_CONN_DEFAULT, &conn)) { + fprintf(stderr, "Error: Connection to datastore failed\n"); + goto err; + } + if (sr_session_start(conn, dstds, &sess)) { + fprintf(stderr, "Error: Unable to open transaction to %s\n", + kparg_value(dstarg)); + goto err_disconnect; + } + + err = sr_copy_config(sess, NULL, srcds, 0); + if (err) { + fprintf(stderr, "Error: Unable to copy configuration (%d)\n", + err); + goto err_disconnect; + } + + sr_disconnect(conn); + return 0; + +err_disconnect: + sr_disconnect(conn); +err: + return -1; +} + +int klix_commit(kcontext_t *ctx) +{ + sr_session_ctx_t *sess; + sr_conn_ctx_t *conn; + int err; + + if (sr_connect(SR_CONN_DEFAULT, &conn)) { + fprintf(stderr, "Error: Connection to datastore failed\n"); + goto err; + } + + if (sr_session_start(conn, SR_DS_RUNNING, &sess)) { + fprintf(stderr, + "Error: Unable to open transaction to running-config\n"); + goto err_disconnect; + } + + err = sr_copy_config(sess, NULL, SR_DS_CANDIDATE, 0); + if (err) { + fprintf(stderr, + "Error: Unable to commit candidate to running (%d)\n", + err); + goto err; + } + + sr_disconnect(conn); + return 0; + +err_disconnect: + sr_disconnect(conn); +err: + return -1; +} + +int kplugin_klinfix_fini(kcontext_t *ctx) +{ + return 0; +} + +int kplugin_klinfix_init(kcontext_t *ctx) +{ + kplugin_t *plugin = kcontext_plugin(ctx); + + kplugin_add_syms(plugin, ksym_new("klix_copy", klix_copy)); + kplugin_add_syms(plugin, ksym_new("klix_commit", klix_commit)); + return 0; +} diff --git a/src/klinfix/xml/Makefile.am b/src/klinfix/xml/Makefile.am new file mode 100644 index 00000000..1bd6bfa9 --- /dev/null +++ b/src/klinfix/xml/Makefile.am @@ -0,0 +1,2 @@ +klishconfdir = $(KLISHCONFDIR) +klishconf_DATA = $(wildcard *.xml) diff --git a/src/klinfix/xml/infix.xml b/src/klinfix/xml/infix.xml new file mode 100644 index 00000000..927ff1dc --- /dev/null +++ b/src/klinfix/xml/infix.xml @@ -0,0 +1,215 @@ + + + + + + + + + ShowBrackets = y + ShowSemicolons = y + FirstKeyWithStatement = n + MultiKeysWithStatement = y + Colorize = y + Indent = 2 + + + + + factory-config + startup-config + running-config + + + + + + + startup-config + running-config + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %u@%h:exec> + + + + /bin/sh -l + + + + pop + + + pop + + + + replace configure + + + + + + + + + + + + + + + + + + + + + %u@%h:configure> + + + + + + + + + + + replace main + + + + + replace main + + + + + + replace main + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +