* Ensured you can add multiple callbacks for any RPC, including basic ones.

* Extra RPC:s will be called _after_ the basic ones.
  * One specific usecase is hook for `copy-config` (see [doc/ROADMAP.md] that can be implemented thus way.
* `rpc_callback_register` added a namespace parameter. Example:
   ```
     rpc_callback_register(h, empty_rpc, NULL, "urn:example:clixon", "empty");
   ```
This commit is contained in:
Olof hagsand 2019-03-10 17:27:52 +01:00
parent 748c7282ea
commit b1c74b5f1f
18 changed files with 755 additions and 514 deletions

File diff suppressed because it is too large Load diff

View file

@ -60,5 +60,6 @@ struct client_entry{
*/
int backend_client_rm(clicon_handle h, struct client_entry *ce);
int from_client(int fd, void *arg);
int backend_rpc_init(clicon_handle h);
#endif /* _BACKEND_CLIENT_H_ */

View file

@ -330,8 +330,6 @@ startup_validate(clicon_handle h,
goto done;
}
/*! Do a diff between candidate and running, then start a commit transaction
*
* The code reverts changes if the commit fails. But if the revert
@ -408,25 +406,33 @@ candidate_commit(clicon_handle h,
goto done;
}
/*! Commit changes from candidate to running
* @param[in] h Clicon handle
* @param[out] cbret Return xml value cligen buffer
* @retval 0 OK. This may indicate both ok and err msg back to client
* @retval -1 (Local) Error
* NACM: The server MUST determine the exact nodes in the running
/*! Commit the candidate configuration as the device's new current configuration
*
* @param[in] h Clicon handle
* @param[in] xe Request: <rpc><xn></rpc>
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
* @param[in] arg client-entry
* @param[in] regarg User argument given at rpc_callback_register()
* @retval 0 OK
* @retval -1 Error
* @note NACM: The server MUST determine the exact nodes in the running
* configuration datastore that are actually different and only check
* "create", "update", and "delete" access permissions for this set of
* nodes, which could be empty.
*/
int
from_client_commit(clicon_handle h,
int mypid,
cbuf *cbret)
cxobj *xe,
cbuf *cbret,
void *arg,
void *regarg)
{
int retval = -1;
int piddb;
cbuf *cbx = NULL; /* Assist cbuf */
int ret;
int retval = -1;
struct client_entry *ce = (struct client_entry *)arg;
int mypid = ce->ce_pid;
int piddb;
cbuf *cbx = NULL; /* Assist cbuf */
int ret;
/* Check if target locked by other client */
piddb = xmldb_islocked(h, "running");
@ -457,22 +463,30 @@ from_client_commit(clicon_handle h,
return retval; /* may be zero if we ignoring errors from commit */
} /* from_client_commit */
/*! Discard all changes in candidate / revert to running
* @param[in] h Clicon handle
* @param[in] mypid Process/session id of calling client
* @param[out] cbret Return xml value cligen buffer
/*! Revert the candidate configuration to the current running configuration.
*
* @param[in] h Clicon handle
* @param[in] xe Request: <rpc><xn></rpc>
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
* @param[in] arg client-entry
* @param[in] regarg User argument given at rpc_callback_register()
* @retval 0 OK. This may indicate both ok and err msg back to client
* @retval -1 (Local) Error
* @retval 0 OK
* @retval -1 Error
* NACM: No datastore permissions are needed.
*/
int
from_client_discard_changes(clicon_handle h,
int mypid,
cbuf *cbret)
cxobj *xe,
cbuf *cbret,
void *arg,
void *regarg)
{
int retval = -1;
int piddb;
cbuf *cbx = NULL; /* Assist cbuf */
int retval = -1;
struct client_entry *ce = (struct client_entry *)arg;
int mypid = ce->ce_pid;
int piddb;
cbuf *cbx = NULL; /* Assist cbuf */
/* Check if target locked by other client */
piddb = xmldb_islocked(h, "candidate");
@ -500,22 +514,60 @@ from_client_discard_changes(clicon_handle h,
return retval; /* may be zero if we ignoring errors from commit */
}
/*! Handle an incoming validate message from a client.
* @param[in] h Clicon handle
* @param[in] db Database name
* @param[out] cbret Return xml value cligen buffer
* @retval 0 OK. This may indicate both ok and err msg back to client (eg invalid)
* @retval -1 (Local) Error
/*! Cancel an ongoing confirmed commit.
* If the confirmed commit is persistent, the parameter 'persist-id' must be
* given, and it must match the value of the 'persist' parameter.
*
* @param[in] h Clicon handle
* @param[in] xe Request: <rpc><xn></rpc>
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
* @param[in] arg client-entry
* @param[in] regarg User argument given at rpc_callback_register()
* @retval 0 OK. This may indicate both ok and err msg back to client
* @retval 0 OK
* @retval -1 Error
* @see RFC 6241 Sec 8.4
*/
int
from_client_cancel_commit(clicon_handle h,
cxobj *xe,
cbuf *cbret,
void *arg,
void *regarg)
{
int retval = -1;
retval = 0;
// done:
return retval;
}
/*! Validates the contents of the specified configuration.
* @param[in] h Clicon handle
* @param[in] xe Request: <rpc><xn></rpc>
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
* @param[in] arg client-entry
* @param[in] regarg User argument given at rpc_callback_register()
* @retval 0 OK. This may indicate both ok and err msg back to client
* (eg invalid)
* @retval -1 Error
*/
int
from_client_validate(clicon_handle h,
char *db,
cbuf *cbret)
cxobj *xe,
cbuf *cbret,
void *arg,
void *regarg)
{
int retval = -1;
transaction_data_t *td = NULL;
int ret;
char *db;
if ((db = netconf_db_find(xe, "source")) == NULL){
if (netconf_missing_element(cbret, "protocol", "source", NULL) < 0)
goto done;
goto ok;
}
if (strcmp(db, "candidate") != 0 && strcmp(db, "tmp") != 0){
if (netconf_invalid_value(cbret, "protocol", "No such database")< 0)
goto done;
@ -552,3 +604,4 @@ from_client_validate(clicon_handle h,
transaction_free(td);
return retval;
} /* from_client_validate */

View file

@ -40,10 +40,12 @@
/*
* Prototypes
*/
int from_client_validate(clicon_handle h, char *db, cbuf *cbret);
int from_client_commit(clicon_handle h, int pid, cbuf *cbret);
int from_client_discard_changes(clicon_handle h, int pid, cbuf *cbret);
int startup_validate(clicon_handle h, char *db, cbuf *cbret);
int candidate_commit(clicon_handle h, char *db, cbuf *cbret);
int from_client_commit(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void *regarg);
int from_client_discard_changes(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void *regarg);
int from_client_cancel_commit(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void *regarg);
int from_client_validate(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void *regarg);
#endif /* _BACKEND_COMMIT_H_ */

View file

@ -635,6 +635,10 @@ main(int argc,
if (xmldb_setopt(h, "nacm_xtree", (void*)clicon_nacm_ext(h)) < 0)
goto done;
/* Initialize server socket and save it to handle */
if (backend_rpc_init(h) < 0)
goto done;
/* Save modules state of the backend (server). Compare with startup XML */
if (startup_module_state(h, yspec) < 0)
goto done;