Skip to content

Commit

Permalink
sysrepo UPDATE revert installing mdoules on error
Browse files Browse the repository at this point in the history
Refs #3236
  • Loading branch information
michalvasko committed Jan 31, 2024
1 parent 500b71b commit b292faa
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 17 deletions.
1 change: 1 addition & 0 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ typedef struct {

/* additional members */
const struct lys_module *ly_mod;
int installed;
} sr_int_install_mod_t;

/**
Expand Down
69 changes: 61 additions & 8 deletions src/context_change.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,9 @@ sr_lycc_check_add_modules(sr_conn_ctx_t *conn, const struct ly_ctx *new_ctx)
}

sr_error_info_t *
sr_lycc_add_modules(sr_conn_ctx_t *conn, const sr_int_install_mod_t *new_mods, uint32_t new_mod_count)
sr_lycc_add_modules(sr_conn_ctx_t *conn, sr_int_install_mod_t *new_mods, uint32_t new_mod_count)
{
sr_error_info_t *err_info = NULL;
sr_error_info_t *err_info = NULL, *tmp_err;
const struct lys_module *ly_mod;
uint32_t i;
sr_datastore_t ds;
Expand All @@ -233,36 +233,89 @@ sr_lycc_add_modules(sr_conn_ctx_t *conn, const sr_int_install_mod_t *new_mods, u
/* find plugin */
if ((err_info = sr_ds_handle_find(new_mods[i].module_ds.plugin_name[ds], conn,
(const struct sr_ds_handle_s **)&ds_handle))) {
return err_info;
goto cleanup;
}

if (!ds_handle->init) {
/* call conn_init */
if ((err_info = ds_handle->plugin->conn_init_cb(conn, &ds_handle->plg_data))) {
return err_info;
goto cleanup;
}
ds_handle->init = 1;
}

/* call install */
if ((err_info = ds_handle->plugin->install_cb(ly_mod, ds, new_mods[i].owner, new_mods[i].group,
new_mods[i].perm, ds_handle->plg_data))) {
return err_info;
goto cleanup;
}

/* call init */
if ((err_info = ds_handle->plugin->init_cb(ly_mod, ds, ds_handle->plg_data))) {
return err_info;
goto cleanup;
}
}

/* store module YANG with all submodules and imports */
if ((err_info = sr_store_module_yang_r(ly_mod))) {
return err_info;
goto cleanup;
}

new_mods[i].installed = 1;
}

return NULL;
cleanup:
if (err_info && (tmp_err = sr_lycc_add_modules_revert(conn, new_mods, new_mod_count))) {
sr_errinfo_merge(&err_info, tmp_err);
}
return err_info;
}

sr_error_info_t *
sr_lycc_add_modules_revert(sr_conn_ctx_t *conn, const sr_int_install_mod_t *new_mods, uint32_t new_mod_count)
{
sr_error_info_t *err_info = NULL;
const struct lys_module *ly_mod;
uint32_t i;
sr_datastore_t ds;
struct sr_ds_handle_s *ds_handle;
struct ly_set del_set = {0};

for (i = 0; i < new_mod_count; ++i) {
ly_mod = new_mods[i].ly_mod;

if (!new_mods[i].installed) {
continue;
}

/* init module for all DS plugins */
for (ds = 0; ds < SR_DS_READ_COUNT; ++ds) {
if ((ds == SR_DS_RUNNING) && !new_mods[i].module_ds.plugin_name[ds]) {
/* disabled */
continue;
}

/* find plugin */
if ((err_info = sr_ds_handle_find(new_mods[i].module_ds.plugin_name[ds], conn,
(const struct sr_ds_handle_s **)&ds_handle))) {
goto cleanup;
}

/* call uninstall */
if ((err_info = ds_handle->plugin->uninstall_cb(ly_mod, ds, ds_handle->plg_data))) {
goto cleanup;
}
}

/* remove YANG module(s) */
if ((err_info = sr_remove_module_yang_r(ly_mod, conn->ly_ctx, &del_set))) {
goto cleanup;
}
}

cleanup:
ly_set_erase(&del_set, NULL);
return err_info;
}

sr_error_info_t *
Expand Down
13 changes: 12 additions & 1 deletion src/context_change.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,18 @@ sr_error_info_t *sr_lycc_check_add_modules(sr_conn_ctx_t *conn, const struct ly_
* @param[in] new_mod_count Count of @p new_mods.
* @return err_info, NULL on success.
*/
sr_error_info_t *sr_lycc_add_modules(sr_conn_ctx_t *conn, const sr_int_install_mod_t *new_mods, uint32_t new_mod_count);
sr_error_info_t *sr_lycc_add_modules(sr_conn_ctx_t *conn, sr_int_install_mod_t *new_mods, uint32_t new_mod_count);

/**
* @brief Revert adding new modules.
*
* @param[in] conn Connection to use.
* @param[in] new_mods Array of new modules.
* @param[in] new_mod_count Count of @p new_mods.
* @return err_info, NULL on success.
*/
sr_error_info_t *sr_lycc_add_modules_revert(sr_conn_ctx_t *conn, const sr_int_install_mod_t *new_mods,
uint32_t new_mod_count);

/**
* @brief Check that modules can be removed.
Expand Down
3 changes: 3 additions & 0 deletions src/plugins/ds_json.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ srpds_json_store_(const struct lys_module *mod, sr_datastore_t ds, const struct
if (fd > -1) {
close(fd);
}
if (err_info && creat) {
unlink(path);
}
free(path);
free(bck_path);
return err_info;
Expand Down
43 changes: 35 additions & 8 deletions src/sysrepo.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
* @brief sysrepo API routines
*
* @copyright
* Copyright (c) 2018 - 2023 Deutsche Telekom AG.
* Copyright (c) 2018 - 2023 CESNET, z.s.p.o.
* Copyright (c) 2018 - 2024 Deutsche Telekom AG.
* Copyright (c) 2018 - 2024 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
Expand Down Expand Up @@ -1419,14 +1419,15 @@ static int
_sr_install_modules(sr_conn_ctx_t *conn, const char *search_dirs, const char *data, const char *data_path,
LYD_FORMAT format, sr_int_install_mod_t **new_mods, uint32_t *new_mod_count)
{
sr_error_info_t *err_info = NULL;
sr_error_info_t *err_info = NULL, *tmp_err;
struct ly_ctx *new_ctx = NULL, *old_ctx = NULL;
struct lyd_node *mod_data = NULL, *sr_mods = NULL;
struct lyd_node *mod_data = NULL, *sr_mods = NULL, *sr_del_mods = NULL;
sr_int_install_mod_t *nmod;
struct sr_data_update_s data_info = {0};
sr_lock_mode_t ctx_mode = SR_LOCK_NONE;
uint32_t i, search_dir_count = 0;
int installed;
int installed, mod_shm_changed = 0;
struct ly_set mod_set = {0};

/* create new temporary context */
if ((err_info = sr_ly_ctx_init(conn, &new_ctx))) {
Expand Down Expand Up @@ -1508,23 +1509,49 @@ _sr_install_modules(sr_conn_ctx_t *conn, const char *search_dirs, const char *da

/* update SHM modules */
if ((err_info = sr_shmmod_store_modules(&conn->mod_shm, sr_mods))) {
goto cleanup;
goto error1;
}
mod_shm_changed = 1;

/* finish adding the modules */
if ((err_info = sr_lycc_add_modules(conn, *new_mods, *new_mod_count))) {
goto cleanup;
goto error1;
}

/* store new data if they differ */
if ((err_info = sr_lycc_store_data_if_differ(conn, new_ctx, sr_mods, &data_info))) {
goto cleanup;
goto error2;
}

/* update content ID and safely switch the context */
SR_CONN_MAIN_SHM(conn)->content_id = ly_ctx_get_modules_hash(new_ctx);
sr_conn_ctx_switch(conn, &new_ctx, &old_ctx);

goto cleanup;

error2:
/* revert adding the modules */
if ((tmp_err = sr_lycc_add_modules_revert(conn, *new_mods, *new_mod_count))) {
sr_errinfo_merge(&err_info, tmp_err);
}

error1:
/* revert lydmods data */
for (i = 0; i < *new_mod_count; ++i) {
ly_set_add(&mod_set, (*new_mods)[i].ly_mod, 1, NULL);
}
lyd_free_siblings(sr_mods);
if ((tmp_err = sr_lydmods_change_del_module(conn->ly_ctx, new_ctx, &mod_set, conn, &sr_del_mods, &sr_mods))) {
sr_errinfo_merge(&err_info, tmp_err);
}
ly_set_erase(&mod_set, NULL);
lyd_free_siblings(sr_del_mods);

/* revert SHM module changes */
if (mod_shm_changed && (tmp_err = sr_shmmod_store_modules(&conn->mod_shm, sr_mods))) {
sr_errinfo_merge(&err_info, tmp_err);
}

cleanup:
sr_lycc_update_data_clear(&data_info);
lyd_free_siblings(mod_data);
Expand Down

0 comments on commit b292faa

Please sign in to comment.