* Fixed: Configure option CLICON_RESTCONF_PATH was marked as obsolete but was still used.
* `CLICON_RESTCONF_PATH` is now obsolete for sure
* Instead if you use fgci/nginx:
* Use `restconf/fcgi-socket`
* Ensure `<CLICON_FEATURE>clixon-restconf:fcgi</CLICON_FEATURE>` is set
* Added default values to restconf-config and save fcgi-socket-path in memory
This commit is contained in:
parent
1808015cf6
commit
50ac510803
10 changed files with 163 additions and 96 deletions
|
|
@ -64,6 +64,11 @@ Users may have to change how they access the system
|
|||
* Fixed: Configure option `CLICON_RESTCONF_PRETTY` was marked as obsolete but was still used.
|
||||
* `CLICON_RESTCONF_PRETTY` is now obsolete for sure
|
||||
* Instead restconf/pretty is used with API function restconf_pretty_get()
|
||||
* Fixed: Configure option `CLICON_RESTCONF_PATH` was marked as obsolete but was still used.
|
||||
* `CLICON_RESTCONF_PATH` is now obsolete for sure
|
||||
* Instead if you use fgci/nginx:
|
||||
* Use `restconf/fcgi-socket`
|
||||
* Ensure `<CLICON_FEATURE>clixon-restconf:fcgi</CLICON_FEATURE>` is set
|
||||
|
||||
### Minor features
|
||||
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ struct restconf_handle {
|
|||
clicon_hash_t *rh_params; /* restconf parameters, including http headers */
|
||||
clixon_auth_type_t rh_auth_type; /* authentication type */
|
||||
int rh_pretty; /* pretty-print for http replies */
|
||||
char *rh_fcgi_socket; /* if-feature fcgi, XXX: use WITH_RESTCONF_FCGI ? */
|
||||
};
|
||||
|
||||
/*! Creates and returns a clicon config handle for other CLICON API calls
|
||||
|
|
@ -115,6 +116,10 @@ restconf_handle_init(void)
|
|||
int
|
||||
restconf_handle_exit(clicon_handle h)
|
||||
{
|
||||
struct restconf_handle *rh = handle(h);
|
||||
|
||||
if (rh->rh_fcgi_socket)
|
||||
free(rh->rh_fcgi_socket);
|
||||
clicon_handle_exit(h); /* frees h and options (and streams) */
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -240,3 +245,36 @@ restconf_pretty_set(clicon_handle h,
|
|||
rh->rh_pretty = pretty;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! Get restconf fcgi socket path
|
||||
* @param[in] h Clicon handle
|
||||
* @retval socketpath
|
||||
*/
|
||||
char*
|
||||
restconf_fcgi_socket_get(clicon_handle h)
|
||||
{
|
||||
struct restconf_handle *rh = handle(h);
|
||||
|
||||
return rh->rh_fcgi_socket;
|
||||
}
|
||||
|
||||
/*! Set restconf fcgi socketpath
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] name Data name
|
||||
* @param[in] val Data value as null-terminated string
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
* Currently using clixon runtime data but there is risk for colliding names
|
||||
*/
|
||||
int
|
||||
restconf_fcgi_socket_set(clicon_handle h,
|
||||
char *socketpath)
|
||||
{
|
||||
struct restconf_handle *rh = handle(h);
|
||||
|
||||
if ((rh->rh_fcgi_socket = strdup(socketpath)) == NULL){
|
||||
clicon_err(OE_RESTCONF, errno, "strdup");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,5 +51,7 @@ clixon_auth_type_t restconf_auth_type_get(clicon_handle h);
|
|||
int restconf_auth_type_set(clicon_handle h, clixon_auth_type_t type);
|
||||
int restconf_pretty_get(clicon_handle h);
|
||||
int restconf_pretty_set(clicon_handle h, int pretty);
|
||||
char *restconf_fcgi_socket_get(clicon_handle h);
|
||||
int restconf_fcgi_socket_set(clicon_handle h, char *socketpath);
|
||||
|
||||
#endif /* _RESTCONF_HANDLE_H_ */
|
||||
|
|
|
|||
|
|
@ -754,7 +754,15 @@ restconf_config_init(clicon_handle h,
|
|||
char *bstr;
|
||||
cvec *nsc = NULL;
|
||||
int auth_type;
|
||||
yang_stmt *yspec;
|
||||
|
||||
if ((yspec = clicon_dbspec_yang(h)) == NULL){
|
||||
clicon_err(OE_FATAL, 0, "No DB_SPEC");
|
||||
goto done;
|
||||
}
|
||||
/* Apply default values (removed in clear function) */
|
||||
if (xml_default_recurse(xrestconf, 0) < 0)
|
||||
goto done;
|
||||
if ((x = xpath_first(xrestconf, nsc, "enable")) != NULL &&
|
||||
(enable = xml_body(x)) != NULL){
|
||||
if (strcmp(enable, "false") == 0){
|
||||
|
|
@ -778,6 +786,11 @@ restconf_config_init(clicon_handle h,
|
|||
else if (strcmp(bstr, "false") == 0)
|
||||
restconf_pretty_set(h, 0);
|
||||
}
|
||||
if ((x = xpath_first(xrestconf, nsc, "fcgi-socket")) != NULL &&
|
||||
(bstr = xml_body(x)) != NULL){
|
||||
if (restconf_fcgi_socket_set(h, bstr) < 0)
|
||||
goto done;
|
||||
}
|
||||
retval = 1;
|
||||
done:
|
||||
return retval;
|
||||
|
|
|
|||
|
|
@ -125,6 +125,90 @@ fcgi_params_set(clicon_handle h,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Try to get config: inline, config-file or query backend
|
||||
*/
|
||||
static int
|
||||
restconf_main_config(clicon_handle h,
|
||||
yang_stmt *yspec,
|
||||
const char *inline_config)
|
||||
{
|
||||
int retval = -1;
|
||||
struct passwd *pw;
|
||||
cxobj *xconfig = NULL;
|
||||
cxobj *xrestconf = NULL;
|
||||
uint32_t id = 0;
|
||||
cxobj *xerr = NULL;
|
||||
int configure_done = 0; /* First try local then backend */
|
||||
cvec *nsc = NULL;
|
||||
int ret;
|
||||
|
||||
/* 1. try inline configure option */
|
||||
if (inline_config != NULL && strlen(inline_config)){
|
||||
clicon_debug(1, "restconf_main_fcgi using restconf inline config");
|
||||
if ((ret = clixon_xml_parse_string(inline_config, YB_MODULE, yspec, &xrestconf, &xerr)) < 0)
|
||||
goto done;
|
||||
if (ret == 0){
|
||||
clixon_netconf_error(xerr, "Inline restconf config", NULL);
|
||||
goto done;
|
||||
}
|
||||
/* Replace parent w first child */
|
||||
if (xml_rootchild(xrestconf, 0, &xrestconf) < 0)
|
||||
goto done;
|
||||
}
|
||||
else if (clicon_option_bool(h, "CLICON_BACKEND_RESTCONF_PROCESS") == 0){
|
||||
/* 2. If not read from backend, try to get restconf config from local config-file */
|
||||
xrestconf = clicon_conf_restconf(h);
|
||||
}
|
||||
/* 3. If no local config, or it is disabled, try to query backend of config. */
|
||||
else {
|
||||
/* Loop to wait for backend starting, try again if not done */
|
||||
while (1){
|
||||
if (clicon_hello_req(h, &id) < 0){
|
||||
if (errno == ENOENT){
|
||||
fprintf(stderr, "waiting");
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
clicon_err(OE_UNIX, errno, "clicon_session_id_get");
|
||||
goto done;
|
||||
}
|
||||
clicon_session_id_set(h, id);
|
||||
break;
|
||||
}
|
||||
if ((nsc = xml_nsctx_init(NULL, CLIXON_RESTCONF_NS)) == NULL)
|
||||
goto done;
|
||||
if ((pw = getpwuid(getuid())) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "getpwuid");
|
||||
goto done;
|
||||
}
|
||||
if (clicon_rpc_get_config(h, pw->pw_name, "running", "/restconf", nsc, &xconfig) < 0)
|
||||
goto done;
|
||||
if ((xerr = xpath_first(xconfig, NULL, "/rpc-error")) != NULL){
|
||||
clixon_netconf_error(xerr, "Get backend restconf config", NULL);
|
||||
goto done;
|
||||
}
|
||||
/* Extract restconf configuration */
|
||||
xrestconf = xpath_first(xconfig, nsc, "restconf");
|
||||
}
|
||||
configure_done = 0;
|
||||
if (xrestconf != NULL &&
|
||||
(configure_done = restconf_config_init(h, xrestconf)) < 0)
|
||||
goto done;
|
||||
if (!configure_done){ /* Query backend of config. */
|
||||
clicon_err(OE_DAEMON, EFAULT, "Restconf daemon config not found or disabled");
|
||||
goto done;
|
||||
}
|
||||
retval = 0;
|
||||
done:
|
||||
if (nsc)
|
||||
cvec_free(nsc);
|
||||
if (inline_config != NULL && strlen(inline_config) && xrestconf)
|
||||
xml_free(xrestconf);
|
||||
if (xconfig)
|
||||
xml_free(xconfig);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* XXX Need global variable to for SIGCHLD signal handler
|
||||
*/
|
||||
static clicon_handle _CLICON_HANDLE = NULL;
|
||||
|
|
@ -221,20 +305,11 @@ main(int argc,
|
|||
int finish = 0;
|
||||
char *str;
|
||||
clixon_plugin_t *cp = NULL;
|
||||
uint32_t id = 0;
|
||||
cvec *nsctx_global = NULL; /* Global namespace context */
|
||||
size_t cligen_buflen;
|
||||
size_t cligen_bufthreshold;
|
||||
int dbg = 0;
|
||||
int ret;
|
||||
cxobj *xrestconf1 = NULL; /* Inline */
|
||||
cxobj *xrestconf2 = NULL; /* Local config file */
|
||||
cxobj *xconfig3 = NULL;
|
||||
cxobj *xrestconf3 = NULL; /* Config from backend */
|
||||
int configure_done = 0; /* First try local then backend */
|
||||
cvec *nsc = NULL;
|
||||
cxobj *xerr = NULL;
|
||||
struct passwd *pw;
|
||||
char *wwwuser;
|
||||
char *inline_config = NULL;
|
||||
|
||||
|
|
@ -457,83 +532,13 @@ main(int argc,
|
|||
if (clixon_plugin_start_all(h) < 0)
|
||||
goto done;
|
||||
|
||||
/* 1. try inline configure option */
|
||||
if (inline_config != NULL && strlen(inline_config)){
|
||||
clicon_debug(1, "restconf_main_fcgi using restconf inline config");
|
||||
if ((ret = clixon_xml_parse_string(inline_config, YB_MODULE, yspec, &xrestconf1, &xerr)) < 0)
|
||||
goto done;
|
||||
if (ret == 0){
|
||||
clixon_netconf_error(xerr, "Inline restconf config", NULL);
|
||||
goto done;
|
||||
}
|
||||
/* Replace parent w first child */
|
||||
if (xml_rootchild(xrestconf1, 0, &xrestconf1) < 0)
|
||||
goto done;
|
||||
if ((ret = restconf_config_init(h, xrestconf1)) < 0)
|
||||
goto done;
|
||||
if (ret == 1)
|
||||
configure_done = 1;
|
||||
}
|
||||
else if (clicon_option_bool(h, "CLICON_BACKEND_RESTCONF_PROCESS") == 0){
|
||||
/* 2. If not read from backend, try to get restconf config from local config-file */
|
||||
if ((xrestconf2 = clicon_conf_restconf(h)) != NULL){
|
||||
if ((ret = restconf_config_init(h, xrestconf2)) < 0)
|
||||
goto done;
|
||||
if (ret == 1)
|
||||
configure_done = 1;
|
||||
}
|
||||
}
|
||||
/* 3. If no local config, or it is disabled, try to query backend of config. */
|
||||
else {
|
||||
/* Loop to wait for backend starting, try again if not done */
|
||||
while (1){
|
||||
if (clicon_hello_req(h, &id) < 0){
|
||||
if (errno == ENOENT){
|
||||
fprintf(stderr, "waiting");
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
clicon_err(OE_UNIX, errno, "clicon_session_id_get");
|
||||
goto done;
|
||||
}
|
||||
clicon_session_id_set(h, id);
|
||||
break;
|
||||
}
|
||||
if ((nsc = xml_nsctx_init(NULL, CLIXON_RESTCONF_NS)) == NULL)
|
||||
goto done;
|
||||
if ((pw = getpwuid(getuid())) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "getpwuid");
|
||||
goto done;
|
||||
}
|
||||
if (clicon_rpc_get_config(h, pw->pw_name, "running", "/restconf", nsc, &xconfig3) < 0)
|
||||
goto done;
|
||||
if ((xerr = xpath_first(xconfig3, NULL, "/rpc-error")) != NULL){
|
||||
clixon_netconf_error(xerr, "Get backend restconf config", NULL);
|
||||
goto done;
|
||||
}
|
||||
/* Extract restconf configuration */
|
||||
if ((xrestconf3 = xpath_first(xconfig3, nsc, "restconf")) != NULL){
|
||||
if ((ret = restconf_config_init(h, xrestconf3)) < 0)
|
||||
goto done;
|
||||
if (ret == 1)
|
||||
configure_done = 1;
|
||||
}
|
||||
}
|
||||
if (!configure_done){ /* Query backend of config. */
|
||||
clicon_err(OE_DAEMON, EFAULT, "Restconf daemon config not found or disabled");
|
||||
/* Try to get config: inline, config-file or query backend */
|
||||
if (restconf_main_config(h, yspec, inline_config) < 0)
|
||||
goto done;
|
||||
}
|
||||
/* XXX see restconf_config_init access directly */
|
||||
if ((sockpath = clicon_option_str(h, "CLICON_RESTCONF_PATH")) == NULL){
|
||||
clicon_err(OE_CFG, errno, "No CLICON_RESTCONF_PATH in clixon configure file");
|
||||
if ((sockpath = restconf_fcgi_socket_get(h)) == NULL){
|
||||
clicon_err(OE_CFG, 0, "No restconf fcgi-socket (have you set FEATURE fcgi in config?)");
|
||||
goto done;
|
||||
}
|
||||
/* XXX CLICON_RESTCONF_PATH is marked as obsolete and should use
|
||||
* fcgi-socket in clixon-restconf.yang instead */
|
||||
if ((sockpath = clicon_option_str(h, "CLICON_RESTCONF_PATH")) == NULL){
|
||||
clicon_err(OE_CFG, errno, "No CLICON_RESTCONF_PATH in clixon configure file");
|
||||
goto done;
|
||||
}
|
||||
if (FCGX_Init() != 0){ /* How to cleanup memory after this? */
|
||||
clicon_err(OE_CFG, errno, "FCGX_Init");
|
||||
goto done;
|
||||
|
|
@ -649,12 +654,6 @@ main(int argc,
|
|||
} /* while */
|
||||
retval = 0;
|
||||
done:
|
||||
if (xrestconf1)
|
||||
xml_free(xrestconf1);
|
||||
if (xconfig3)
|
||||
xml_free(xconfig3);
|
||||
if (nsc)
|
||||
cvec_free(nsc);
|
||||
stream_child_freeall(h);
|
||||
restconf_terminate(h);
|
||||
return retval;
|
||||
|
|
|
|||
|
|
@ -226,8 +226,13 @@ function restconf_config()
|
|||
AUTH=$1
|
||||
PRETTY=$2
|
||||
|
||||
if [ ${WITH_RESTCONF} = "fcgi" ]; then
|
||||
FEATURES="<CLICON_FEATURE>clixon-restconf:fcgi</CLICON_FEATURE>"
|
||||
else
|
||||
FEATURES=""
|
||||
fi
|
||||
if [ $RCPROTO = http ]; then
|
||||
echo "<restconf><enable>true</enable><auth-type>$AUTH</auth-type><pretty>$PRETTY</pretty><debug>$DBG</debug><socket><namespace>default</namespace><address>0.0.0.0</address><port>80</port><ssl>false</ssl></socket></restconf>"
|
||||
echo "${FEATURES}<restconf><enable>true</enable><auth-type>$AUTH</auth-type><pretty>$PRETTY</pretty><debug>$DBG</debug><socket><namespace>default</namespace><address>0.0.0.0</address><port>80</port><ssl>false</ssl></socket></restconf>"
|
||||
else
|
||||
certdir=$dir/certs
|
||||
if [ ! -f ${dir}/clixon-server-crt.pem ]; then
|
||||
|
|
@ -240,7 +245,7 @@ function restconf_config()
|
|||
cacerts $cakey $cacert
|
||||
servercerts $cakey $cacert $srvkey $srvcert
|
||||
fi
|
||||
echo "<restconf><enable>true</enable><auth-type>$AUTH</auth-type><pretty>$PRETTY</pretty><server-cert-path>${certdir}/clixon-server-crt.pem</server-cert-path><server-key-path>${certdir}/clixon-server-key.pem</server-key-path><server-ca-cert-path>${certdir}/clixon-ca-crt.pem</server-ca-cert-path><debug>$DBG</debug><socket><namespace>default</namespace><address>0.0.0.0</address><port>443</port><ssl>true</ssl></socket></restconf>"
|
||||
echo "${FEATURES}<restconf><enable>true</enable><auth-type>$AUTH</auth-type><pretty>$PRETTY</pretty><server-cert-path>${certdir}/clixon-server-crt.pem</server-cert-path><server-key-path>${certdir}/clixon-server-key.pem</server-key-path><server-ca-cert-path>${certdir}/clixon-ca-crt.pem</server-ca-cert-path><debug>$DBG</debug><socket><namespace>default</namespace><address>0.0.0.0</address><port>443</port><ssl>true</ssl></socket></restconf>"
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -537,7 +537,9 @@ function testrun()
|
|||
}
|
||||
|
||||
# Go thru all combinations of IPv4/IPv6, http/https, local/backend config
|
||||
if ${HAVE_LIBEVHTP}; then
|
||||
if [ "${WITH_RESTCONF}" = "fcgi" ]; then
|
||||
protos="http"
|
||||
elif ${HAVE_LIBEVHTP}; then
|
||||
protos="http" # No plain http for http/2 only
|
||||
fi
|
||||
if [ "${WITH_RESTCONF}" = "native" ]; then
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@
|
|||
# Magic line must be first in script (see README.md)
|
||||
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||
|
||||
if ! ${HAVE_LIBEVHTP}; then
|
||||
# Does not work with evhtpnative http/2-only
|
||||
if [ "${WITH_RESTCONF}" = "native" -a ${HAVE_LIBEVHTP} = false ]; then
|
||||
echo "...skipped: LIBEVHTP is false, must run with http/1 (evhtp)"
|
||||
if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@
|
|||
# Magic line must be first in script (see README.md)
|
||||
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||
|
||||
if ! ${HAVE_LIBEVHTP}; then
|
||||
# Does not work with evhtpnative http/2-only
|
||||
if [ "${WITH_RESTCONF}" = "native" -a ${HAVE_LIBEVHTP} = false ]; then
|
||||
echo "...skipped: LIBEVHTP is false, must run with http/1 (evhtp)"
|
||||
if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@
|
|||
# Magic line must be first in script (see README.md)
|
||||
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||
|
||||
if ! ${HAVE_LIBEVHTP}; then
|
||||
# Does not work with evhtpnative http/2-only
|
||||
if [ "${WITH_RESTCONF}" = "native" -a ${HAVE_LIBEVHTP} = false ]; then
|
||||
echo "...skipped: LIBEVHTP is false, must run with http/1 (evhtp)"
|
||||
if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||
fi
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue