Skip to content

Commit 5f79e80

Browse files
committed
confd: Add support for dependency tracking between modules
1 parent e850e52 commit 5f79e80

File tree

2 files changed

+155
-21
lines changed

2 files changed

+155
-21
lines changed

src/confd/src/core.c

Lines changed: 149 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -93,17 +93,139 @@ int core_post_hook(sr_session_ctx_t *session, uint32_t sub_id, const char *modul
9393
return SR_ERR_OK;
9494
}
9595

96+
static confd_dependency_t add_dependencies(struct lyd_node **diff, const char *xpath, const char *value)
97+
{
98+
struct lyd_node *new_node = NULL;
99+
struct lyd_node *target = NULL;
100+
struct lyd_node *root = NULL;
101+
int rc;
102+
103+
if (!lydx_get_xpathf(*diff, "%s", xpath)) {
104+
/* Create the path, potentially creating a new tree */
105+
rc = lyd_new_path(NULL, LYD_CTX(*diff), xpath, value, LYD_NEW_PATH_UPDATE, &new_node);
106+
if (rc != LY_SUCCESS || !new_node) {
107+
ERROR("lyd_new_path failed with rc=%d", rc);
108+
return CONFD_DEP_ERROR;
109+
}
110+
111+
root = new_node;
112+
while (root->parent)
113+
root = lyd_parent(root);
114+
115+
rc = lyd_merge_siblings(diff, root, LYD_MERGE_DESTRUCT);
116+
if (rc != LY_SUCCESS) {
117+
ERROR("lyd_merge_siblings failed with rc=%d", rc);
118+
lyd_free_tree(root);
119+
return CONFD_DEP_ERROR;
120+
}
121+
122+
target = lydx_get_xpathf(*diff, "%s", xpath);
123+
if (target) {
124+
lyd_new_meta(LYD_CTX(target), target, NULL,
125+
"yang:operation", "replace", false, NULL);
126+
} else {
127+
return CONFD_DEP_ERROR;
128+
}
129+
130+
return CONFD_DEP_ADDED;
131+
}
132+
133+
return CONFD_DEP_DONE;
134+
}
135+
136+
static confd_dependency_t handle_dependencies(struct lyd_node **diff, struct lyd_node *config)
137+
{
138+
struct lyd_node *dkeys, *dkey, *hostname;
139+
confd_dependency_t result = CONFD_DEP_DONE;
140+
const char *key_name;
141+
142+
dkeys = lydx_get_descendant(*diff, "keystore", "symmetric-keys", "symmetric-key", NULL);
143+
144+
LYX_LIST_FOR_EACH(dkeys, dkey, "symmetric-key") {
145+
struct ly_set *ifaces;
146+
uint32_t i;
147+
148+
key_name = lydx_get_cattr(dkey, "name");
149+
ifaces = lydx_find_xpathf(config, "/ietf-interfaces:interfaces/interface[infix-interfaces:wifi/secret='%s']", key_name);
150+
if (ifaces && ifaces->count > 0) {
151+
for (i = 0; i < ifaces->count; i++) {
152+
struct lyd_node *iface = ifaces->dnodes[i];
153+
const char *ifname;
154+
char xpath[256];
155+
ifname = lydx_get_cattr(iface, "name");
156+
snprintf(xpath, sizeof(xpath), "/ietf-interfaces:interfaces/interface[name='%s']/infix-interfaces:wifi/secret", ifname);
157+
result = add_dependencies(diff, xpath, key_name);
158+
if (result == CONFD_DEP_ERROR) {
159+
ERROR("Failed to add wifi node to diff for interface %s", ifname);
160+
ly_set_free(ifaces, NULL);
161+
return result;
162+
}
163+
}
164+
ly_set_free(ifaces, NULL);
165+
}
166+
}
167+
168+
dkeys = lydx_get_descendant(*diff, "keystore", "asymmetric-keys", "asymmetric-key", NULL);
169+
LYX_LIST_FOR_EACH(dkeys, dkey, "asymmetric-key") {
170+
struct ly_set *hostkeys;
171+
uint32_t i;
172+
173+
key_name = lydx_get_cattr(dkey, "name");
174+
hostkeys = lydx_find_xpathf(config, "/infix-services:ssh/hostkey[.='%s']", key_name);
175+
if (hostkeys && hostkeys->count > 0) {
176+
for (i = 0; i < hostkeys->count; i++) {
177+
char xpath[256];
178+
snprintf(xpath, sizeof(xpath), "/infix-services:ssh/hostkey[.='%s']", key_name);
179+
result = add_dependencies(diff, xpath, key_name);
180+
if (result == CONFD_DEP_ERROR) {
181+
ERROR("Failed to add ssh hostkey to diff for key %s", key_name);
182+
ly_set_free(hostkeys, NULL);
183+
return result;
184+
}
185+
}
186+
ly_set_free(hostkeys, NULL);
187+
}
188+
}
189+
190+
hostname = lydx_get_xpathf(*diff, "/ietf-system:system/hostname");
191+
if (hostname) {
192+
struct lyd_node *mdns, *dhcp_server;
193+
194+
dhcp_server = lydx_get_xpathf(config, "/infix-dhcp-server:dhcp-server/enabled");
195+
if(dhcp_server && lydx_is_enabled(dhcp_server, "enabled")) {
196+
result = add_dependencies(diff, "/infix-dhcp-server:dhcp-server/enabled", "true");
197+
if (result == CONFD_DEP_ERROR) {
198+
ERROR("Failed to add dhcp-server to diff on hostname change");
199+
return result;
200+
}
201+
}
202+
mdns = lydx_get_xpathf(config, "/infix-services:mdns");
203+
if (mdns && lydx_is_enabled(mdns, "enabled")) {
204+
result = add_dependencies(diff, "/infix-services:mdns/enabled", "true");
205+
if (result == CONFD_DEP_ERROR) {
206+
ERROR("Failed to add mdns to diff on hostname change");
207+
return result;
208+
}
209+
}
210+
}
211+
212+
return result;
213+
}
214+
96215
static int change_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *module_name,
97216
const char *xpath, sr_event_t event, uint32_t request_id, void *_confd)
98217
{
218+
<<<<<<< HEAD
99219
struct confd *confd = _confd;
100220
char *output = NULL;
101221
struct lyd_node *diff = NULL, *config = NULL;
102222
sr_data_t *cfg = NULL;
103-
223+
confd_dependency_t result;
104224
int rc = SR_ERR_OK;
105225
static uint32_t last_id = 0;
106226
static uint32_t last_event = -1;
227+
int max_dep = 10;
228+
107229
if (request_id == last_id && last_event == event)
108230
return SR_ERR_OK;
109231
last_id = request_id;
@@ -121,28 +243,34 @@ static int change_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *mod
121243

122244
config = cfg->tree;
123245
}
124-
125-
// For logging: Write to file instead of using ERROR() to avoid truncation
126-
if (diff) {
127-
FILE *f = fopen("/tmp/sysrepo_diff.json", "w");
128-
if (f) {
129-
lyd_print_file(f, diff, LYD_JSON,
130-
LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_ALL);
131-
fclose(f);
132-
ERROR("req_id=%u event=%d module=%s - Full diff written to /tmp/sysrepo_diff.json",
133-
request_id, event, module_name);
134-
} else {
135-
// Fallback: print to memory but limit what we log
136-
lyd_print_mem(&output, diff, LYD_JSON, LYD_PRINT_WITHSIBLINGS);
137-
if (output) {
138-
// Only log first 500 chars to avoid truncation
139-
ERROR("req_id=%u event=%d module=%s - Diff (truncated): %.500s...",
140-
request_id, event, module_name, output);
141-
free(output);
142-
}
143-
}
246+
while ((result = handle_dependencies(&diff, config)) != CONFD_DEP_DONE) {
247+
if (result == CONFD_DEP_ERROR) {
248+
ERROR("Failed to add dependencies");
249+
break;
250+
}
144251
}
145252

253+
config = cfg->tree;
254+
while ((result = handle_dependencies(&diff, config)) != CONFD_DEP_DONE) {
255+
if (max_dep == 0) {
256+
ERROR("Max dependency depth reached");
257+
return SR_ERR_INTERNAL;
258+
}
259+
if (result == CONFD_DEP_ERROR) {
260+
ERROR("Failed to add dependencies");
261+
return SR_ERR_INTERNAL;
262+
}
263+
max_dep--;
264+
}
265+
#if 0
266+
/* Debug: print diff to file */
267+
FILE *f = fopen("/tmp/confd-diff.json", "w");
268+
if (f) {
269+
lyd_print_file(f, diff, LYD_JSON, LYD_PRINT_WITHSIBLINGS);
270+
fclose(f);
271+
}
272+
#endif
273+
}
146274
/* ietf-interfaces */
147275
ietf_interfaces_change(session, config, diff, event, confd);
148276

src/confd/src/core.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include <jansson.h>
2626

27+
#include <srx/lyx.h>
2728
#include <srx/common.h>
2829
#include <srx/helpers.h>
2930
#include <srx/systemv.h>
@@ -100,6 +101,11 @@ static inline char *xpath_base(const char *xpath)
100101

101102
return path;
102103
}
104+
typedef enum {
105+
CONFD_DEP_DONE = 0,
106+
CONFD_DEP_ADDED = 1,
107+
CONFD_DEP_ERROR = 2
108+
} confd_dependency_t;
103109

104110
#define REGISTER_CHANGE(s,m,x,f,c,a,u) \
105111
if ((rc = register_change(s, m, x, f, c, a, u))) \

0 commit comments

Comments
 (0)