Skip to content

Commit 966b9b3

Browse files
committed
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>
1 parent 6aac9db commit 966b9b3

File tree

3 files changed

+80
-13
lines changed

3 files changed

+80
-13
lines changed

src/bin/Makefile.am

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ bin_PROGRAMS = copy erase files
66
copy_SOURCES = copy.c util.c util.h
77
copy_CPPFLAGS = -D_DEFAULT_SOURCE -D_GNU_SOURCE
88
copy_CFLAGS = -W -Wall -Wextra
9-
copy_CFLAGS += $(libite_CFLAGS) $(sysrepo_CFLAGS)
10-
copy_LDADD = $(libite_LIBS) $(sysrepo_LIBS)
9+
copy_CFLAGS += $(libite_CFLAGS) $(libyang_CFLAGS) $(sysrepo_CFLAGS)
10+
copy_LDADD = $(libite_LIBS) $(libyang_LIBS) $(sysrepo_LIBS)
1111

1212
erase_SOURCES = erase.c util.c util.h
1313
erase_CPPFLAGS = -D_DEFAULT_SOURCE -D_GNU_SOURCE

src/bin/configure.ac

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ AC_PROG_INSTALL
1515
PKG_PROG_PKG_CONFIG
1616

1717
PKG_CHECK_MODULES([libite], [libite >= 2.5.0])
18+
PKG_CHECK_MODULES([libyang], [libyang >= 3.0.0])
1819
PKG_CHECK_MODULES([sysrepo], [sysrepo >= 2.2.36])
1920

2021
# Misc variable replacements for below Summary
@@ -55,8 +56,8 @@ cat <<EOF
5556
System environment....: ${sysconfig_path:-${sysconfig}}
5657
C Compiler............: $CC $CFLAGS $CPPFLAGS $LDFLAGS $LIBS
5758
Linker................: $LD $LLDP_LDFLAGS $LLDP_BIN_LDFLAGS $LDFLAGS $LIBS
58-
CFLAGS................: $libite_CFLAGS $sysrepo_CFLAGS
59-
LIBS..................: $libite_LIBS $sysrepo_LIBS
59+
CFLAGS................: $libite_CFLAGS $libyang_CFLAGS $sysrepo_CFLAGS
60+
LIBS..................: $libite_LIBS $libyang_LIBS $sysrepo_LIBS
6061

6162
------------- Compiler version --------------
6263
$($CC --version || true)

src/bin/copy.c

Lines changed: 75 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,40 @@ static const char *infix_ds(const char *text, struct infix_ds **ds)
177177
return text;
178178
}
179179

180+
/*
181+
* Load configuration from a file and replace running datastore.
182+
* This triggers all sysrepo change callbacks, unlike sr_copy_config().
183+
*/
184+
static int replace_running(sr_conn_ctx_t *conn, sr_session_ctx_t *sess,
185+
const char *file, int timeout)
186+
{
187+
uint32_t flags = LYD_PARSE_NO_STATE | LYD_PARSE_ONLY;
188+
struct lyd_node *data = NULL;
189+
const struct ly_ctx *ctx;
190+
LY_ERR err;
191+
int rc;
192+
193+
ctx = sr_acquire_context(conn);
194+
err = lyd_parse_data_path(ctx, file, LYD_JSON, flags, 0, &data);
195+
sr_release_context(conn);
196+
197+
if (err) {
198+
fprintf(stderr, ERRMSG "unable to load %s\n", file);
199+
lyd_free_all(data);
200+
return SR_ERR_INTERNAL;
201+
}
202+
203+
/* Replace running config (triggers callbacks, takes ownership on success) */
204+
rc = sr_replace_config(sess, NULL, data, timeout * 1000);
205+
if (rc) {
206+
emsg(sess, ERRMSG "unable to replace configuration, err %d: %s\n",
207+
rc, sr_strerror(rc));
208+
lyd_free_all(data);
209+
}
210+
211+
return rc;
212+
}
213+
180214

181215
static int copy(const char *src, const char *dst, const char *remote_user)
182216
{
@@ -229,12 +263,24 @@ static int copy(const char *src, const char *dst, const char *remote_user)
229263
fprintf(stderr, ERRMSG "unable to open transaction to %s\n", dst);
230264
} else {
231265
sr_nacm_set_user(sess, user);
232-
rc = sr_copy_config(sess, NULL, srcds->datastore, timeout * 1000);
233-
if (rc)
234-
emsg(sess, ERRMSG "unable to copy configuration, err %d: %s\n",
235-
rc, sr_strerror(rc));
236-
else
237-
set_owner(dstds->path, user);
266+
267+
/*
268+
* When copying TO running-config, use sr_replace_config()
269+
* to trigger change callbacks. Otherwise use sr_copy_config()
270+
* for direct datastore copy without callbacks.
271+
*/
272+
if (dstds->datastore == SR_DS_RUNNING && srcds->path) {
273+
rc = replace_running(conn, sess, srcds->path, timeout);
274+
if (!rc)
275+
set_owner(dstds->path, user);
276+
} else {
277+
/* Direct copy for other datastores (no callbacks needed) */
278+
rc = sr_copy_config(sess, NULL, srcds->datastore, timeout * 1000);
279+
if (rc)
280+
emsg(sess, ERRMSG "unable to copy configuration, err %d: %s\n", rc, sr_strerror(rc));
281+
else
282+
set_owner(dstds->path, user);
283+
}
238284
}
239285
rc = sr_disconnect(conn);
240286

@@ -320,9 +366,29 @@ static int copy(const char *src, const char *dst, const char *remote_user)
320366
if (rc) {
321367
fprintf(stderr, ERRMSG "failed downloading %s", src);
322368
} else {
323-
rc = systemf("sysrepocfg -d %s -I%s -f json", dstds->sysrepocfg, fn);
324-
if (rc)
325-
fprintf(stderr, ERRMSG "failed loading %s from %s", dst, src);
369+
/* Use replace_config() for running-config (triggers callbacks), sysrepocfg for others */
370+
if (dstds->datastore == SR_DS_RUNNING) {
371+
if (sr_connect(SR_CONN_DEFAULT, &conn)) {
372+
fprintf(stderr, ERRMSG "connection to datastore failed\n");
373+
rc = 1;
374+
} else {
375+
sr_log_syslog("klishd", SR_LL_WRN);
376+
if (sr_session_start(conn, SR_DS_RUNNING, &sess)) {
377+
fprintf(stderr, ERRMSG "unable to open transaction to %s\n", dst);
378+
rc = 1;
379+
} else {
380+
sr_nacm_set_user(sess, user);
381+
rc = replace_running(conn, sess, fn, timeout);
382+
if (!rc)
383+
set_owner(dstds->path, user);
384+
}
385+
sr_disconnect(conn);
386+
}
387+
} else {
388+
rc = systemf("sysrepocfg -d %s -I%s -f json", dstds->sysrepocfg, fn);
389+
if (rc)
390+
fprintf(stderr, ERRMSG "failed loading %s from %s", dst, src);
391+
}
326392
}
327393
} else {
328394
if (strstr(src, "://") && strstr(dst, "://")) {

0 commit comments

Comments
 (0)