diff options
-rw-r--r-- | .github/workflows/check-open-prs-conflict.yml | 17 | ||||
-rw-r--r-- | .github/workflows/cla-check.yml | 19 | ||||
-rw-r--r-- | CODEOWNERS | 2 | ||||
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | debian/control | 3 | ||||
-rw-r--r-- | functions/interpreter/vyatta-cfg-run | 70 | ||||
-rw-r--r-- | src/vy_adapter.cpp | 262 | ||||
-rw-r--r-- | src/vy_adapter.h | 33 |
8 files changed, 385 insertions, 23 deletions
diff --git a/.github/workflows/check-open-prs-conflict.yml b/.github/workflows/check-open-prs-conflict.yml new file mode 100644 index 0000000..52b1193 --- /dev/null +++ b/.github/workflows/check-open-prs-conflict.yml @@ -0,0 +1,17 @@ +name: "Open PRs Conflicts checker" +on: + push: + branches: + - current + - sagitta + - circinus + workflow_dispatch: + +permissions: + contents: read + pull-requests: write + +jobs: + check-pr-conflict-call: + uses: vyos/.github/.github/workflows/check-open-prs-conflict.yml@current + secrets: inherit diff --git a/.github/workflows/cla-check.yml b/.github/workflows/cla-check.yml new file mode 100644 index 0000000..3c1aeee --- /dev/null +++ b/.github/workflows/cla-check.yml @@ -0,0 +1,19 @@ +name: "CLA Check" + +permissions: + actions: write + contents: read + pull-requests: write + statuses: write + +on: + pull_request: + types: [opened, synchronize, closed] + issue_comment: + types: [created] + +jobs: + call-cla-assistant: + uses: vyos/vyos-cla-signatures/.github/workflows/cla-reusable.yml@current + secrets: + CLA_PAT: ${{ secrets.CLA_PAT }} @@ -1 +1 @@ -* @vyos/reviewers
\ No newline at end of file +# * @vyos/reviewers
\ No newline at end of file diff --git a/Makefile.am b/Makefile.am index 2170f95..6ef8d64 100644 --- a/Makefile.am +++ b/Makefile.am @@ -52,6 +52,7 @@ src_libvyatta_cfg_la_SOURCES += src/cnode/cnode-algorithm.cpp src_libvyatta_cfg_la_SOURCES += src/cparse/cparse.cpp src_libvyatta_cfg_la_SOURCES += src/cparse/cparse_lex.c src_libvyatta_cfg_la_SOURCES += src/commit/commit-algorithm.cpp +src_libvyatta_cfg_la_SOURCES += src/vy_adapter.cpp CLEANFILES = src/cli_parse.c src/cli_parse.h src/cli_def.c src/cli_val.c CLEANFILES += src/cparse/cparse.cpp src/cparse/cparse.h CLEANFILES += src/cparse/cparse_lex.c @@ -61,6 +62,7 @@ LDADD += $(GOBJECT_LIBS) vincludedir = $(includedir)/vyatta-cfg vinclude_HEADERS = src/cli_cstore.h +vinclude_HEADERS += src/vy_adapter.h vcincdir = $(vincludedir)/cstore vcinc_HEADERS = src/cstore/cstore-c.h diff --git a/debian/control b/debian/control index 136b2e8..0655d78 100644 --- a/debian/control +++ b/debian/control @@ -12,7 +12,8 @@ Architecture: any Depends: sed (>= 4.1.5), procps (>= 1:3.2.7-3), coreutils (>= 5.97-5.3), - vyatta-bash | bash (>= 4.1), + vyatta-bash (>= 4.1), + bash-completion (= 1:2.8-6), bsdutils (>=1:2.13), libvyatta-cfg1 (>=${binary:Version}), unionfs-fuse, diff --git a/functions/interpreter/vyatta-cfg-run b/functions/interpreter/vyatta-cfg-run index d1dbd51..dc69d6c 100644 --- a/functions/interpreter/vyatta-cfg-run +++ b/functions/interpreter/vyatta-cfg-run @@ -103,39 +103,59 @@ vyatta_config_show () vyatta_config_commit () { - if ! vyatta_cli_shell_api sessionChanged; then - echo "No configuration changes to commit" - return 1; + if test -f "/var/run/vyconf_backend"; then + echo $$ + if ! /usr/libexec/vyos/vyconf/bin/vy_session_changed; then + echo "No configuration changes to commit" + return 1; + fi + else + if ! vyatta_cli_shell_api sessionChanged; then + echo "No configuration changes to commit" + return 1; + fi fi + local comment="commit" - local next=0 - local -a args=() - for arg in "$@"; do - if [ "$next" == "1" ]; then - comment=$arg - next=0; - elif [ "$arg" == "comment" ]; then - next=1 - elif [ "$arg" == "confirm" ]; then - echo Use commit-confirm command + if [ $# -gt 0 ] ; then + if [ $# = 1 ] || [ $# -gt 2 ] || [ "$1" != "comment" ]; then + if [ "$1" == "confirm" ]; then + echo "Use commit-confirm command" + return 1 + fi + echo "Error: commit accepts either no arguments, or optional 'comment'" \ + "with comment text as second argument." + echo -e "\tUsage: 'commit [comment COMMENTTEXT]'" return 1; - else - args[${#args[@]}]="$arg" fi - done + comment="$2" + fi export COMMIT_COMMENT="$comment" export COMMIT_VIA=cli - /opt/vyatta/sbin/my_commit "${args[@]}" 2>&1 + if test -f "/var/run/vyconf_backend"; then + /usr/libexec/vyos/vyconf/bin/vy_commit 2>&1 + else + /opt/vyatta/sbin/my_commit 2>&1 + fi unset COMMIT_VIA unset COMMIT_COMMENT + eval "${vyos_libexec_dir}/reset_section.py vpp --pid $$" } vyatta_config_commit-confirm () { - if ! vyatta_cli_shell_api sessionChanged; then - echo "No configuration changes to commit" - return 1; + if test -f "/var/run/vyconf_backend"; then + echo $$ + if ! /usr/libexec/vyos/vyconf/bin/vy_session_changed; then + echo "No configuration changes to commit" + return 1; + fi + else + if ! vyatta_cli_shell_api sessionChanged; then + echo "No configuration changes to commit" + return 1; + fi fi local -a args=() local first=1 @@ -285,6 +305,10 @@ up () really_exit() { + if test -f "/var/run/vyconf_backend"; then + local exit_cmd="${vyos_libexec_dir}/teardown-config-session.py $$" + eval "sudo sg vyattacfg \"$exit_cmd\"" + fi if vyatta_cli_shell_api sessionUnsaved; then echo "Warning: configuration changes have not been saved." @@ -354,7 +378,11 @@ vyatta_cfg_cmd_run () elif [[ "$cmd" == "show" ]]; then vyatta_config_show "${@:2}" else - cmd="/opt/vyatta/sbin/my_$cmd" + if test -f "/var/run/vyconf_backend"; then + cmd="${vyconf_bin_dir}/vy_$cmd" + else + cmd="/opt/vyatta/sbin/my_$cmd" + fi output=$($cmd "${@:2}") fi vyatta_cfg_print_output "$output" diff --git a/src/vy_adapter.cpp b/src/vy_adapter.cpp new file mode 100644 index 0000000..cf2f50e --- /dev/null +++ b/src/vy_adapter.cpp @@ -0,0 +1,262 @@ +/* Copyright 2024 VyOS maintainers and contributors <maintainers@vyos.io> + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <cstring> +#include <cstdlib> +#include <vector> +#include <string> +#include <sstream> +#include <iostream> +#include <cstdint> +#include <cassert> +#include <algorithm> +#include <list> +#include <fcntl.h> +#include <unistd.h> + +#include <cstore/cstore.hpp> +#include <vy_adapter.h> + +using namespace cstore; + +enum PIPES { READ, WRITE }; + +extern FILE *out_stream; + +class stdout_redirect { + public: + stdout_redirect(): old_stdout(0), redirecting(false) { + out_pipe[READ] = 0; + out_pipe[WRITE] = 0; + if (pipe(out_pipe) == -1) { + return; + } + + old_stdout = dup(fileno(stdout)); + setbuf(stdout, NULL); + dup2(out_pipe[WRITE], fileno(stdout)); + + redirecting = true; + } + + std::string get_redirected_output() { + if (!redirecting) { + return ""; + } + + char buffer[1024]; + ssize_t bytesRead = 0; + std::string redirected_output = "\n"; + fcntl(out_pipe[READ], F_SETFL, O_NONBLOCK); + while ((bytesRead = read(out_pipe[READ], buffer, sizeof(buffer))) > 0) { + redirected_output.append(buffer, bytesRead); + } + + return redirected_output; + } + + ~stdout_redirect() { + if (!redirecting) { + return; + } + + dup2(old_stdout, fileno(stdout)); + + if (old_stdout > 0) { + close(old_stdout); + } + if (out_pipe[READ] > 0) { + close(out_pipe[READ]); + } + if (out_pipe[WRITE] > 0) { + close(out_pipe[WRITE]); + } + } + + private: + int out_pipe[2]; + int old_stdout; + bool redirecting; +}; + +struct cstore_obj { + Cstore *cstore; + std::list<char *> output; +}; + +static struct cstore_obj* create_handle() { + struct cstore_obj *h = new cstore_obj; + h->cstore = Cstore::createCstore(false); + return h; +}; + +const char *out_data_copy(std::string msg, cstore_obj *o) +{ + size_t len = msg.length(); + char *out_data = (char *) malloc(len + 1); + o->output.push_back(out_data); + msg.copy(out_data, len); + out_data[len] = '\0'; + return out_data; +} + +static uint64_t uint_of_voidptr(void* p) +{ + assert (((uintptr_t) p & 1) == 0); + return (uint64_t) p | 1; +} + +static void *voidptr_of_uint(uint64_t v) +{ + return (void *)(uintptr_t)(v & ~1); +} + +static cstore_obj *cstore_obj_of_handle(uint64_t handle) +{ + return (cstore_obj *) voidptr_of_uint(handle); +} + +uint64_t +vy_cstore_init(void) +{ + cstore_obj *handle = create_handle(); + return uint_of_voidptr(handle); +} + +void +vy_cstore_free(uint64_t handle) +{ + cstore_obj *h = cstore_obj_of_handle(handle); + for (char * x: h->output) { + free(x); + } + delete h->cstore; + delete h; +} + +int +vy_in_session(uint64_t handle) +{ + Cstore *h = cstore_obj_of_handle(handle)->cstore; + return h->inSession() ? 1 : 0; +} + +const char * +vy_validate_path(uint64_t handle, const void** path_ptr, size_t len) +{ + cstore_obj *obj = cstore_obj_of_handle(handle); + Cstore *cstore = obj->cstore; + const char **path = (const char **) path_ptr; + Cpath path_comps = Cpath(path, len); + const char *out_data; + std::string out_str = ""; + int res; + + out_stream = stdout; + stdout_redirect redirect = stdout_redirect(); + + res = cstore->validateSetPath(path_comps); + if (!res) { + out_str = "\nInvalid set path: " + path_comps.to_string() + "\n"; + out_str.append(redirect.get_redirected_output()); + } + + out_data = out_data_copy(out_str, obj); + out_stream = NULL; + return out_data; +} + +const char * +vy_set_path(uint64_t handle, const void** path_ptr, size_t len) +{ + cstore_obj *obj = cstore_obj_of_handle(handle); + Cstore *cstore = obj->cstore; + const char **path = (const char **) path_ptr; + Cpath path_comps = Cpath(path, len); + const char *out_data; + std::string out_str = ""; + int res; + + out_stream = stdout; + stdout_redirect redirect = stdout_redirect(); + + res = cstore->setCfgPath(path_comps); + if (!res) { + out_str = "\nSet config path failed: " + path_comps.to_string() + "\n"; + out_str.append(redirect.get_redirected_output()); + } + + out_data = out_data_copy(out_str, obj); + out_stream = NULL; + return out_data; +} + +const char * +vy_legacy_set_path(uint64_t handle, const void** path_ptr, size_t len) +{ + cstore_obj *obj = cstore_obj_of_handle(handle); + Cstore *cstore = obj->cstore; + const char **path = (const char **) path_ptr; + Cpath path_comps = Cpath(path, len); + const char *out_data; + std::string out_str = ""; + int res; + + out_stream = stdout; + stdout_redirect redirect = stdout_redirect(); + + res = cstore->validateSetPath(path_comps); + if (!res) { + out_str = "\nInvalid set path: " + path_comps.to_string() + "\n"; + out_str.append(redirect.get_redirected_output()); + goto out; + } + + res = cstore->setCfgPath(path_comps); + if (!res) { + out_str = "\nSet config path failed: " + path_comps.to_string() + "\n"; + out_str.append(redirect.get_redirected_output()); + } + +out: + out_data = out_data_copy(out_str, obj); + out_stream = NULL; + return out_data; +} + +const char * +vy_delete_path(uint64_t handle, const void** path_ptr, size_t len) +{ + cstore_obj *obj = cstore_obj_of_handle(handle); + Cstore *cstore = obj->cstore; + const char **path = (const char **) path_ptr; + Cpath path_comps = Cpath(path, len); + const char *out_data; + std::string out_str = ""; + int res; + + out_stream = stdout; + stdout_redirect redirect = stdout_redirect(); + + res = cstore->deleteCfgPath(path_comps); + if (!res) { + out_str = "\nDelete failed: " + path_comps.to_string() + "\n"; + out_str.append(redirect.get_redirected_output()); + } + + out_data = out_data_copy(out_str, obj); + out_stream = NULL; + return out_data; +} diff --git a/src/vy_adapter.h b/src/vy_adapter.h new file mode 100644 index 0000000..636c303 --- /dev/null +++ b/src/vy_adapter.h @@ -0,0 +1,33 @@ +/* Copyright 2024 VyOS maintainers and contributors <maintainers@vyos.io> + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _VY_ADAPTER_H_ +#define _VY_ADAPTER_H_ +#ifdef __cplusplus +extern "C" { +#endif + +uint64_t vy_cstore_init(void); +void vy_cstore_free(uint64_t); +int vy_in_session(uint64_t); +const char *vy_validate_path(uint64_t, const void **, size_t); +const char *vy_set_path(uint64_t, const void **, size_t); +const char *vy_legacy_set_path(uint64_t, const void **, size_t); +const char *vy_delete_path(uint64_t, const void **, size_t); + +#ifdef __cplusplus +} +#endif +#endif |