mirror of
https://github.com/kernelkit/infix.git
synced 2026-08-01 05:13:01 +02:00
cli: fix 'copy FILE running-config' use-case
When copying to the running datastore we cannot use sr_copy_config(), instead we must use sr_replace_config(). This fix covers both the case of 'copy startup-config running-config' and 'copy FILE running-config'. Fixes #1203 Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
+2
-2
@@ -6,8 +6,8 @@ bin_PROGRAMS = copy erase files
|
|||||||
copy_SOURCES = copy.c util.c util.h
|
copy_SOURCES = copy.c util.c util.h
|
||||||
copy_CPPFLAGS = -D_DEFAULT_SOURCE -D_GNU_SOURCE
|
copy_CPPFLAGS = -D_DEFAULT_SOURCE -D_GNU_SOURCE
|
||||||
copy_CFLAGS = -W -Wall -Wextra
|
copy_CFLAGS = -W -Wall -Wextra
|
||||||
copy_CFLAGS += $(libite_CFLAGS) $(sysrepo_CFLAGS)
|
copy_CFLAGS += $(libite_CFLAGS) $(libyang_CFLAGS) $(sysrepo_CFLAGS)
|
||||||
copy_LDADD = $(libite_LIBS) $(sysrepo_LIBS)
|
copy_LDADD = $(libite_LIBS) $(libyang_LIBS) $(sysrepo_LIBS)
|
||||||
|
|
||||||
erase_SOURCES = erase.c util.c util.h
|
erase_SOURCES = erase.c util.c util.h
|
||||||
erase_CPPFLAGS = -D_DEFAULT_SOURCE -D_GNU_SOURCE
|
erase_CPPFLAGS = -D_DEFAULT_SOURCE -D_GNU_SOURCE
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ AC_PROG_INSTALL
|
|||||||
PKG_PROG_PKG_CONFIG
|
PKG_PROG_PKG_CONFIG
|
||||||
|
|
||||||
PKG_CHECK_MODULES([libite], [libite >= 2.5.0])
|
PKG_CHECK_MODULES([libite], [libite >= 2.5.0])
|
||||||
|
PKG_CHECK_MODULES([libyang], [libyang >= 3.0.0])
|
||||||
PKG_CHECK_MODULES([sysrepo], [sysrepo >= 2.2.36])
|
PKG_CHECK_MODULES([sysrepo], [sysrepo >= 2.2.36])
|
||||||
|
|
||||||
# Misc variable replacements for below Summary
|
# Misc variable replacements for below Summary
|
||||||
@@ -55,8 +56,8 @@ cat <<EOF
|
|||||||
System environment....: ${sysconfig_path:-${sysconfig}}
|
System environment....: ${sysconfig_path:-${sysconfig}}
|
||||||
C Compiler............: $CC $CFLAGS $CPPFLAGS $LDFLAGS $LIBS
|
C Compiler............: $CC $CFLAGS $CPPFLAGS $LDFLAGS $LIBS
|
||||||
Linker................: $LD $LLDP_LDFLAGS $LLDP_BIN_LDFLAGS $LDFLAGS $LIBS
|
Linker................: $LD $LLDP_LDFLAGS $LLDP_BIN_LDFLAGS $LDFLAGS $LIBS
|
||||||
CFLAGS................: $libite_CFLAGS $sysrepo_CFLAGS
|
CFLAGS................: $libite_CFLAGS $libyang_CFLAGS $sysrepo_CFLAGS
|
||||||
LIBS..................: $libite_LIBS $sysrepo_LIBS
|
LIBS..................: $libite_LIBS $libyang_LIBS $sysrepo_LIBS
|
||||||
|
|
||||||
------------- Compiler version --------------
|
------------- Compiler version --------------
|
||||||
$($CC --version || true)
|
$($CC --version || true)
|
||||||
|
|||||||
+74
-9
@@ -177,6 +177,39 @@ static const char *infix_ds(const char *text, struct infix_ds **ds)
|
|||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load configuration from a file and replace running datastore.
|
||||||
|
* This triggers all sysrepo change callbacks, unlike sr_copy_config().
|
||||||
|
*/
|
||||||
|
static int replace_running(sr_conn_ctx_t *conn, sr_session_ctx_t *sess,
|
||||||
|
const char *file, int timeout)
|
||||||
|
{
|
||||||
|
uint32_t flags = LYD_PARSE_NO_STATE | LYD_PARSE_ONLY;
|
||||||
|
struct lyd_node *data = NULL;
|
||||||
|
const struct ly_ctx *ctx;
|
||||||
|
LY_ERR err;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
ctx = sr_acquire_context(conn);
|
||||||
|
err = lyd_parse_data_path(ctx, file, LYD_JSON, flags, 0, &data);
|
||||||
|
sr_release_context(conn);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
fprintf(stderr, ERRMSG "unable to load %s, error %d: %s\n", file, err, ly_errmsg(ctx));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Replace running config (triggers callbacks, takes ownership on success) */
|
||||||
|
rc = sr_replace_config(sess, NULL, data, timeout * 1000);
|
||||||
|
if (rc) {
|
||||||
|
emsg(sess, ERRMSG "unable to replace configuration, err %d: %s\n",
|
||||||
|
rc, sr_strerror(rc));
|
||||||
|
lyd_free_all(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int copy(const char *src, const char *dst, const char *remote_user)
|
static int copy(const char *src, const char *dst, const char *remote_user)
|
||||||
{
|
{
|
||||||
@@ -229,12 +262,24 @@ static int copy(const char *src, const char *dst, const char *remote_user)
|
|||||||
fprintf(stderr, ERRMSG "unable to open transaction to %s\n", dst);
|
fprintf(stderr, ERRMSG "unable to open transaction to %s\n", dst);
|
||||||
} else {
|
} else {
|
||||||
sr_nacm_set_user(sess, user);
|
sr_nacm_set_user(sess, user);
|
||||||
rc = sr_copy_config(sess, NULL, srcds->datastore, timeout * 1000);
|
|
||||||
if (rc)
|
/*
|
||||||
emsg(sess, ERRMSG "unable to copy configuration, err %d: %s\n",
|
* When copying TO running-config, use sr_replace_config()
|
||||||
rc, sr_strerror(rc));
|
* to trigger change callbacks. Otherwise use sr_copy_config()
|
||||||
else
|
* for direct datastore copy without callbacks.
|
||||||
set_owner(dstds->path, user);
|
*/
|
||||||
|
if (dstds->datastore == SR_DS_RUNNING && srcds->path) {
|
||||||
|
rc = replace_running(conn, sess, srcds->path, timeout);
|
||||||
|
if (!rc)
|
||||||
|
set_owner(dstds->path, user);
|
||||||
|
} else {
|
||||||
|
/* Direct copy for other datastores (no callbacks needed) */
|
||||||
|
rc = sr_copy_config(sess, NULL, srcds->datastore, timeout * 1000);
|
||||||
|
if (rc)
|
||||||
|
emsg(sess, ERRMSG "unable to copy configuration, err %d: %s\n", rc, sr_strerror(rc));
|
||||||
|
else
|
||||||
|
set_owner(dstds->path, user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rc = sr_disconnect(conn);
|
rc = sr_disconnect(conn);
|
||||||
|
|
||||||
@@ -320,9 +365,29 @@ static int copy(const char *src, const char *dst, const char *remote_user)
|
|||||||
if (rc) {
|
if (rc) {
|
||||||
fprintf(stderr, ERRMSG "failed downloading %s", src);
|
fprintf(stderr, ERRMSG "failed downloading %s", src);
|
||||||
} else {
|
} else {
|
||||||
rc = systemf("sysrepocfg -d %s -I%s -f json", dstds->sysrepocfg, fn);
|
/* Use replace_config() for running-config (triggers callbacks), sysrepocfg for others */
|
||||||
if (rc)
|
if (dstds->datastore == SR_DS_RUNNING) {
|
||||||
fprintf(stderr, ERRMSG "failed loading %s from %s", dst, src);
|
if (sr_connect(SR_CONN_DEFAULT, &conn)) {
|
||||||
|
fprintf(stderr, ERRMSG "connection to datastore failed\n");
|
||||||
|
rc = 1;
|
||||||
|
} else {
|
||||||
|
sr_log_syslog("klishd", SR_LL_WRN);
|
||||||
|
if (sr_session_start(conn, SR_DS_RUNNING, &sess)) {
|
||||||
|
fprintf(stderr, ERRMSG "unable to open transaction to %s\n", dst);
|
||||||
|
rc = 1;
|
||||||
|
} else {
|
||||||
|
sr_nacm_set_user(sess, user);
|
||||||
|
rc = replace_running(conn, sess, fn, timeout);
|
||||||
|
if (!rc)
|
||||||
|
set_owner(dstds->path, user);
|
||||||
|
}
|
||||||
|
sr_disconnect(conn);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rc = systemf("sysrepocfg -d %s -I%s -f json", dstds->sysrepocfg, fn);
|
||||||
|
if (rc)
|
||||||
|
fprintf(stderr, ERRMSG "failed loading %s from %s", dst, src);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (strstr(src, "://") && strstr(dst, "://")) {
|
if (strstr(src, "://") && strstr(dst, "://")) {
|
||||||
|
|||||||
Reference in New Issue
Block a user