Empty yang type. Relaxed yang types for unions, eg two strings with different length.
This commit is contained in:
parent
bc2b606167
commit
319e7707d8
14 changed files with 64 additions and 113 deletions
|
|
@ -29,6 +29,8 @@
|
|||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
- Empty yang type. Relaxed yang types for unions, eg two strings with different length.
|
||||
|
||||
Dec 2016: Dual license: both GPLv3 and APLv2
|
||||
|
||||
Feb 2016: Forked new clixon repository from clicon
|
||||
|
|
|
|||
|
|
@ -495,7 +495,7 @@ compare_dbs(clicon_handle h, cvec *cvv, cg_var *arg)
|
|||
* cvv[2] = "bgp"
|
||||
* arg = "/interfaces/interface/%s/type"
|
||||
* op: OP_MERGE
|
||||
* @see cli_callback_xmlkeyfmt_generate where arg is generated
|
||||
* @see cli_callback_generate where arg is generated
|
||||
*/
|
||||
static int
|
||||
cli_dbxml(clicon_handle h,
|
||||
|
|
@ -508,17 +508,20 @@ cli_dbxml(clicon_handle h,
|
|||
char *xkfmt; /* xml key format */
|
||||
char *xk = NULL; /* xml key */
|
||||
cg_var *cval;
|
||||
char *val = NULL;
|
||||
int len;
|
||||
|
||||
xkfmt = cv_string_get(arg);
|
||||
if (xmlkeyfmt2key(xkfmt, cvv, &xk) < 0)
|
||||
goto done;
|
||||
cval = cvec_i(cvv, cvec_len(cvv)-1);
|
||||
if ((val = cv2str_dup(cval)) == NULL){
|
||||
len = cvec_len(cvv);
|
||||
if (len > 1){
|
||||
cval = cvec_i(cvv, len-1);
|
||||
if ((str = cv2str_dup(cval)) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cv2str_dup");
|
||||
goto done;
|
||||
}
|
||||
if (clicon_rpc_change(h, "candidate", op, xk, val) < 0)
|
||||
}
|
||||
if (clicon_rpc_change(h, "candidate", op, xk, str) < 0)
|
||||
goto done;
|
||||
if (clicon_autocommit(h)) {
|
||||
if (clicon_rpc_commit(h, "candidate", "running", 0, 0) < 0)
|
||||
|
|
|
|||
|
|
@ -72,104 +72,31 @@
|
|||
/*=====================================================================
|
||||
* YANG generate CLI
|
||||
*=====================================================================*/
|
||||
#if 0 /* examples/ntp */
|
||||
ntp("Network Time Protocol"),cli_set("ntp");{
|
||||
logging("Configure NTP message logging"),cli_set("ntp.logging");{
|
||||
status (<status:bool>),cli_set("ntp.logging $status:bool");
|
||||
/*
|
||||
This is an example yang module:
|
||||
module m {
|
||||
container x {
|
||||
list m1 {
|
||||
key "a";
|
||||
leaf a {
|
||||
type string;
|
||||
}
|
||||
server("Configure NTP Server") (<ipv4addr:ipv4addr>("IPv4 address of peer")),cli_set("ntp.server[] $!ipv4addr:ipv4addr");
|
||||
leaf b {
|
||||
type string;
|
||||
}
|
||||
#endif
|
||||
#if 0 /* examples/datamodel */
|
||||
|
||||
WITH COMPLETION:
|
||||
a (<x:number>|<x:number expand_dbvar_auto("candidate a[] $!x")>),cli_set("a[] $!x");{
|
||||
b,cli_set("a[].b $!x");{
|
||||
y (<y:string>|<y:string expand_dbvar_auto("candidate a[].b $!x $y")>),cli_set("a[].b $!x $y");
|
||||
}
|
||||
z (<z:string>|<z:string expand_dbvar_auto("candidate a[] $!x $z")>),cli_set("a[] $!x $z");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_CLIGEN_MAX2STR /* XXX cligen 3.6 feature */
|
||||
|
||||
/*! Print max value of a CLIgen variable type as string
|
||||
* @param[in] type CLIgen variable type
|
||||
* @param[out] str Max value printed in this string
|
||||
* @param[in] size Length of 'str'
|
||||
* @retval len How many bytes printed
|
||||
* @see cvtype_max2str_dup
|
||||
* You can use str=NULL to get the expected length.
|
||||
* The number of (potentially if str=NULL) written bytes is returned.
|
||||
*/
|
||||
static int
|
||||
cvtype_max2str(enum cv_type type, char *str, size_t size)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
switch (type){
|
||||
case CGV_INT8:
|
||||
len = snprintf(str, size, "%" PRId8, INT8_MAX);
|
||||
break;
|
||||
case CGV_INT16:
|
||||
len = snprintf(str, size, "%" PRId16, INT16_MAX);
|
||||
break;
|
||||
case CGV_INT32:
|
||||
len = snprintf(str, size, "%" PRId32, INT32_MAX);
|
||||
break;
|
||||
case CGV_INT64:
|
||||
len = snprintf(str, size, "%" PRId64, INT64_MAX);
|
||||
break;
|
||||
case CGV_UINT8:
|
||||
len = snprintf(str, size, "%" PRIu8, UINT8_MAX);
|
||||
break;
|
||||
case CGV_UINT16:
|
||||
len = snprintf(str, size, "%" PRIu16, UINT16_MAX);
|
||||
break;
|
||||
case CGV_UINT32:
|
||||
len = snprintf(str, size, "%" PRIu32, UINT32_MAX);
|
||||
break;
|
||||
case CGV_UINT64:
|
||||
len = snprintf(str, size, "%" PRIu64, UINT64_MAX);
|
||||
break;
|
||||
case CGV_DEC64:
|
||||
len = snprintf(str, size, "%" PRId64 ".0", INT64_MAX);
|
||||
break;
|
||||
case CGV_BOOL:
|
||||
len = snprintf(str, size, "true");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/*! Print max value of a CLIgen variable type as string
|
||||
*
|
||||
* The string should be freed after use.
|
||||
* @param[in] type CLIgen variable type
|
||||
* @retval str Malloced string containing value. Should be freed after use.
|
||||
* @see cvtype_max2str
|
||||
*/
|
||||
static char *
|
||||
cvtype_max2str_dup(enum cv_type type)
|
||||
You can see which CLISPEC it generates via clixon_cli -D 1:
|
||||
Jan 2 11:17:58: yang2cli: buf
|
||||
} x,cli_set("/x");{
|
||||
m1 (<a:string>|<a:string expand_dbvar("candidate /x/m1/%s/a")>),cli_set("/x/m1/%s");
|
||||
{
|
||||
int len;
|
||||
char *str;
|
||||
|
||||
if ((len = cvtype_max2str(type, NULL, 0)) < 0)
|
||||
return NULL;
|
||||
if ((str = (char *)malloc (len+1)) == NULL)
|
||||
return NULL;
|
||||
memset (str, '\0', len+1);
|
||||
if ((cvtype_max2str(type, str, len+1)) < 0){
|
||||
free(str);
|
||||
return NULL;
|
||||
b (<b:string>|<b:string expand_dbvar("candidate /x/m1/%s/b")>),cli_set("/x/m1/%s/b");
|
||||
}
|
||||
return str;
|
||||
}
|
||||
#endif /* HAVE_CLIGEN_MAX2STR */
|
||||
}
|
||||
*/
|
||||
|
||||
/*! Create cligen variable expand entry with xmlkey format string as argument
|
||||
* @param[in] h clicon handle
|
||||
|
|
|
|||
|
|
@ -377,6 +377,9 @@ main(int argc, char **argv)
|
|||
/* Join rest of argv to a single command */
|
||||
restarg = clicon_strjoin(argc, argv, " ", __FUNCTION__);
|
||||
|
||||
/* If several cligen object variables match same preference, select first */
|
||||
cligen_match_cgvar_same(1);
|
||||
|
||||
/* Call start function in all plugins before we go interactive
|
||||
Pass all args after the standard options to plugin_start
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -81,9 +81,9 @@ static int xml2csv(FILE *f, cxobj *x, cvec *cvv);
|
|||
* Returns an expand-type list of commands as used by cligen 'expand'
|
||||
* functionality.
|
||||
*
|
||||
* Assume callback given in a cligen spec: a <x:int expand_dbvar_auto("arg")
|
||||
* Assume callback given in a cligen spec: a <x:int expand_dbvar("arg")
|
||||
* @param[in] h clicon handle
|
||||
* @param[in] name Name of this function (eg "expand_dbvar-auto")
|
||||
* @param[in] name Name of this function (eg "expand_dbvar")
|
||||
* @param[in] cvv The command so far. Eg: cvec [0]:"a 5 b"; [1]: x=5;
|
||||
* @param[in] arg Argument given at the callback "<db> <xmlkeyfmt>"
|
||||
* @param[out] len len of return commands & helptxt
|
||||
|
|
@ -121,7 +121,7 @@ expand_dbvar(void *h,
|
|||
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
|
||||
goto done;
|
||||
}
|
||||
/* In the example, str = "candidate a[].b[] $!x $!y" */
|
||||
/* In the example, str = "candidate /x/m1/%s/b" */
|
||||
if ((vec = clicon_strsplit(str, " ", &nvec, __FUNCTION__)) == NULL){
|
||||
clicon_err(OE_PLUGIN, errno, "clicon_strsplit");
|
||||
goto done;
|
||||
|
|
|
|||
|
|
@ -170,7 +170,8 @@ Q: How do you use netconf?
|
|||
--------------------------
|
||||
|
||||
As an alternative to cli configuration, you can use netconf
|
||||
directly. Easiesty is to just pipe netconf commands to the
|
||||
directly. Easiest is to just pipe netconf commands to the
|
||||
clixon_netconf application.
|
||||
Example:
|
||||
echo "<rpc><get-config><source><candidate/></source><configuration/></get-config></rpc>]]>]]>" | clixon_netconf -f /usr/local/etc/routing.conf
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ enum clicon_msg_type{
|
|||
2. uint32: length of value string
|
||||
3. string: name of database to change (eg "running")
|
||||
4. string: key
|
||||
5. string: value
|
||||
5. string: value (can be NULL)
|
||||
*/
|
||||
CLICON_MSG_XMLPUT, /* Send database entries as XML to backend daemon
|
||||
1. uint32: operation: LV_SET/LV_DELETE
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ clicon_rpc_change(clicon_handle h,
|
|||
op,
|
||||
key,
|
||||
val,
|
||||
strlen(val)+1,
|
||||
val?strlen(val)+1:0,
|
||||
__FUNCTION__)) == NULL)
|
||||
goto done;
|
||||
if (clicon_rpc_msg(h, msg, NULL, NULL, NULL, __FUNCTION__) < 0)
|
||||
|
|
|
|||
|
|
@ -199,7 +199,9 @@ clicon_msg_change_encode(char *db,
|
|||
op, str_len, db, key);
|
||||
p = 0;
|
||||
len = sizeof(*msg) + 2*sizeof(uint32_t) + strlen(db) + 1 +
|
||||
strlen(key) + 1 + str_len;
|
||||
strlen(key) + str_len;
|
||||
if (str_len)
|
||||
len++; /* if str not null add end of string */
|
||||
if ((msg = (struct clicon_msg *)chunk(len, label)) == NULL){
|
||||
clicon_err(OE_PROTO, errno, "%s: chunk", __FUNCTION__);
|
||||
return NULL;
|
||||
|
|
@ -221,8 +223,10 @@ clicon_msg_change_encode(char *db,
|
|||
p += strlen(db)+1;
|
||||
strncpy(msg->op_body+p, key, len-p-hdrlen);
|
||||
p += strlen(key)+1;
|
||||
if (str_len){
|
||||
memcpy(msg->op_body+p, str, str_len);
|
||||
p += str_len;
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -221,6 +221,7 @@ yang2xmlkeyfmt(yang_stmt *ys,
|
|||
* @param[in] cvv cligen variable vector, one for every wildchar in xkfmt
|
||||
* @param[out] xk XML key, eg /aaa/17. Free after use
|
||||
* @note first and last elements of cvv are not used,..
|
||||
* @see cli_dbxml where this function is called
|
||||
*/
|
||||
int
|
||||
xmlkeyfmt2key(char *xkfmt,
|
||||
|
|
@ -247,7 +248,7 @@ xmlkeyfmt2key(char *xkfmt,
|
|||
j,
|
||||
cvec_len(cvv),
|
||||
cv_string_get(cvec_i(cvv, 0)));
|
||||
// goto done;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
if ((cb = cbuf_new()) == NULL){
|
||||
|
|
@ -1689,7 +1690,7 @@ xmldb_put_xkey_local(clicon_handle h,
|
|||
case OP_MERGE:
|
||||
case OP_REPLACE:
|
||||
if (y->ys_keyword == Y_LEAF || y->ys_keyword == Y_LEAF_LIST){
|
||||
if (db_set(filename, xk, val, strlen(val)+1) < 0)
|
||||
if (db_set(filename, xk, val, val?strlen(val)+1:0) < 0)
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
/*
|
||||
* Yang 1.0 parser according to RFC6020.
|
||||
* It is hopefully useful but not complete
|
||||
* RFC7950 defines Yang version 1.1
|
||||
*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
/*
|
||||
* Yang 1.0 parser according to RFC6020.
|
||||
* It is hopefully useful but not complete
|
||||
* RFC7950 defines Yang version 1.1
|
||||
*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
/*
|
||||
* Yang 1.0 parser according to RFC6020.
|
||||
* It is hopefully useful but not complete
|
||||
* RFC7950 defines Yang version 1.1
|
||||
*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ static const struct map_str2int ytmap[] = {
|
|||
{"uint16", CGV_UINT16},
|
||||
{"uint32", CGV_UINT32},
|
||||
{"uint64", CGV_UINT64},
|
||||
{"union", CGV_VOID}, /* Is replaced by actual type */
|
||||
{"union", CGV_REST}, /* Is replaced by actual type */
|
||||
{NULL, -1}
|
||||
};
|
||||
|
||||
|
|
@ -912,6 +912,7 @@ yang_type_get(yang_stmt *ys,
|
|||
clicon_err(OE_DB, 0, "%s: mandatory type object is not found", __FUNCTION__);
|
||||
goto done;
|
||||
}
|
||||
/* XXX: here we seem to have some problems if type is union */
|
||||
type = ytype_id(ytype);
|
||||
if (origtype)
|
||||
*origtype = type;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue