Completed: Yang deviation [deviation statement not yet support #211](https://github.com/clicon/clixon/issues/211)
This commit is contained in:
parent
5a72626aa4
commit
af04ec9e9d
5 changed files with 201 additions and 86 deletions
|
|
@ -34,10 +34,8 @@ Expected: June 2021
|
||||||
|
|
||||||
### New features
|
### New features
|
||||||
|
|
||||||
* Yang Deviation/deviate [deviation statement not yet support #211](https://github.com/clicon/clixon/issues/211)
|
* Yang deviation [deviation statement not yet support #211](https://github.com/clicon/clixon/issues/211)
|
||||||
* See RFC7950 Sec 5.6.3
|
* See RFC7950 Sec 5.6.3
|
||||||
* Implemented: "not-supported" and "add"
|
|
||||||
* Not yet: "replace" and "delete"
|
|
||||||
|
|
||||||
### Minor features
|
### Minor features
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -770,11 +770,21 @@ send_msg_notify_xml(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Look for a text pattern in an input string, one char at a time
|
/*! Look for a text pattern in an input string, one char at a time
|
||||||
* @param[in] tag What to look for
|
* @param[in] tag What to look for
|
||||||
* @param[in] ch New input character
|
* @param[in] ch New input character
|
||||||
* @param[in,out] state A state integer holding how far we have parsed.
|
* @param[in,out] state A state integer holding how far we have parsed.
|
||||||
* @retval 0 No, we havent detected end tag
|
* @retval 0 No, we havent detected end tag
|
||||||
* @retval 1 Yes, we have detected end tag!
|
* @retval 1 Yes, we have detected end tag!
|
||||||
|
* @code
|
||||||
|
* int state = 0;
|
||||||
|
* char ch;
|
||||||
|
* while (1) {
|
||||||
|
* // read ch
|
||||||
|
* if (detect_endtag("mypattern", ch, &state)) {
|
||||||
|
* // mypattern is matched
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
detect_endtag(char *tag,
|
detect_endtag(char *tag,
|
||||||
|
|
|
||||||
|
|
@ -517,7 +517,8 @@ ys_prune(yang_stmt *yp,
|
||||||
* @param[in] ys Yang node to remove
|
* @param[in] ys Yang node to remove
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @see ys_prune if parent and position is known
|
* @see ys_prune if parent and position is know
|
||||||
|
* @see ys_free Deallocate yang node
|
||||||
* @note Do not call this in a loop of yang children (unless you know what you are doing)
|
* @note Do not call this in a loop of yang children (unless you know what you are doing)
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
|
|
@ -1608,6 +1609,7 @@ yang_deviation(yang_stmt *ys,
|
||||||
yang_stmt *yd;
|
yang_stmt *yd;
|
||||||
yang_stmt *yc;
|
yang_stmt *yc;
|
||||||
yang_stmt *yc1;
|
yang_stmt *yc1;
|
||||||
|
yang_stmt *ytc;
|
||||||
char *devop;
|
char *devop;
|
||||||
clicon_handle h = (clicon_handle)arg;
|
clicon_handle h = (clicon_handle)arg;
|
||||||
enum rfc_6020 kw;
|
enum rfc_6020 kw;
|
||||||
|
|
@ -1648,8 +1650,7 @@ yang_deviation(yang_stmt *ys,
|
||||||
else if (strcmp(devop, "add") == 0){
|
else if (strcmp(devop, "add") == 0){
|
||||||
yc = NULL;
|
yc = NULL;
|
||||||
while ((yc = yn_each(yd, yc)) != NULL) {
|
while ((yc = yn_each(yd, yc)) != NULL) {
|
||||||
/* If a property can only appear once, the property MUST NOT
|
/* If a property can only appear once, the property MUST NOT exist in the target node. */
|
||||||
exist in the target node. */
|
|
||||||
kw = yang_keyword_get(yc);
|
kw = yang_keyword_get(yc);
|
||||||
if (yang_find(ytarget, kw, NULL) != NULL){
|
if (yang_find(ytarget, kw, NULL) != NULL){
|
||||||
if (yang_cardinality_interval(h,
|
if (yang_cardinality_interval(h,
|
||||||
|
|
@ -1674,8 +1675,48 @@ yang_deviation(yang_stmt *ys,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strcmp(devop, "replace") == 0){
|
else if (strcmp(devop, "replace") == 0){
|
||||||
|
yc = NULL;
|
||||||
|
while ((yc = yn_each(yd, yc)) != NULL) {
|
||||||
|
/* The properties to replace MUST exist in the target node.*/
|
||||||
|
kw = yang_keyword_get(yc);
|
||||||
|
if ((ytc = yang_find(ytarget, kw, NULL)) == NULL){
|
||||||
|
clicon_err(OE_YANG, 0, "deviation %s: \"%s %s\" replaced but node does not exist in target %s",
|
||||||
|
nodeid,
|
||||||
|
yang_key2str(kw), yang_argument_get(yc),
|
||||||
|
yang_argument_get(ytarget));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* Remove old */
|
||||||
|
if (ys_prune_self(ytc) < 0)
|
||||||
|
goto done;
|
||||||
|
if (ys_free(ytc) < 0)
|
||||||
|
goto done;
|
||||||
|
/* Make a copy of deviate child and insert. */
|
||||||
|
if ((yc1 = ys_dup(yc)) == NULL)
|
||||||
|
goto done;
|
||||||
|
if (yn_insert(ytarget, yc1) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (strcmp(devop, "delete") == 0){
|
else if (strcmp(devop, "delete") == 0){
|
||||||
|
yc = NULL;
|
||||||
|
while ((yc = yn_each(yd, yc)) != NULL) {
|
||||||
|
/* The substatement's keyword MUST match a corresponding keyword in the target node, and the
|
||||||
|
* argument's string MUST be equal to the corresponding keyword's argument string in the
|
||||||
|
* target node. */
|
||||||
|
kw = yang_keyword_get(yc);
|
||||||
|
if ((ytc = yang_find(ytarget, kw, NULL)) == NULL){
|
||||||
|
clicon_err(OE_YANG, 0, "deviation %s: \"%s %s\" replaced but node does not exist in target %s",
|
||||||
|
nodeid,
|
||||||
|
yang_key2str(kw), yang_argument_get(yc),
|
||||||
|
yang_argument_get(ytarget));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (ys_prune_self(ytc) < 0)
|
||||||
|
goto done;
|
||||||
|
if (ys_free(ytc) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else{ /* Shouldnt happen, lex/yacc takes it */
|
else{ /* Shouldnt happen, lex/yacc takes it */
|
||||||
clicon_err(OE_YANG, EINVAL, "%s: invalid deviate operator", devop);
|
clicon_err(OE_YANG, EINVAL, "%s: invalid deviate operator", devop);
|
||||||
|
|
|
||||||
|
|
@ -1508,12 +1508,6 @@ notification_substmt : if_feature_stmt { _PARSE_DEBUG("notification-substmt ->
|
||||||
| { _PARSE_DEBUG("notification-substmt -> "); }
|
| { _PARSE_DEBUG("notification-substmt -> "); }
|
||||||
;
|
;
|
||||||
|
|
||||||
/* deviation /oc-sys:system/oc-sys:config/oc-sys:hostname {
|
|
||||||
deviate not-supported;
|
|
||||||
}
|
|
||||||
* XXX abs-schema-nodeid-str is too difficult, it needs the + semantics
|
|
||||||
|
|
||||||
*/
|
|
||||||
deviation_stmt : K_DEVIATION string
|
deviation_stmt : K_DEVIATION string
|
||||||
{ if (ysp_add_push(_yy, Y_DEVIATION, $2, NULL) == NULL) _YYERROR("deviation_stmt"); }
|
{ if (ysp_add_push(_yy, Y_DEVIATION, $2, NULL) == NULL) _YYERROR("deviation_stmt"); }
|
||||||
'{' deviation_substmts '}'
|
'{' deviation_substmts '}'
|
||||||
|
|
@ -1569,13 +1563,13 @@ deviate_add_substmt : units_stmt { _PARSE_DEBUG("deviate-add-substmt -> units
|
||||||
|
|
||||||
|
|
||||||
deviate_delete_stmt : K_DEVIATE D_DELETE ';'
|
deviate_delete_stmt : K_DEVIATE D_DELETE ';'
|
||||||
{ if (ysp_add(_yy, Y_DEVIATE, strdup("add") /* D_NOT_SUPPORTED*/, NULL) == NULL) _YYERROR("notification_stmt");
|
{ if (ysp_add(_yy, Y_DEVIATE, strdup("delete"), NULL) == NULL) _YYERROR("notification_stmt");
|
||||||
_PARSE_DEBUG("deviate-delete-stmt -> DEVIATE add ;"); }
|
_PARSE_DEBUG("deviate-delete-stmt -> DEVIATE delete ;"); }
|
||||||
| K_DEVIATE D_DELETE
|
| K_DEVIATE D_DELETE
|
||||||
{ if (ysp_add_push(_yy, Y_DEVIATE, strdup("add"), NULL) == NULL) _YYERROR("deviate_stmt"); }
|
{ if (ysp_add_push(_yy, Y_DEVIATE, strdup("delete"), NULL) == NULL) _YYERROR("deviate_stmt"); }
|
||||||
'{' deviate_delete_substmts '}'
|
'{' deviate_delete_substmts '}'
|
||||||
{ if (ystack_pop(_yy) < 0) _YYERROR("deviate_stmt");
|
{ if (ystack_pop(_yy) < 0) _YYERROR("deviate_stmt");
|
||||||
_PARSE_DEBUG("deviate-delete-stmt -> DEVIATE add { deviate-substmts }"); }
|
_PARSE_DEBUG("deviate-delete-stmt -> DEVIATE delete { deviate-delete-substmts }"); }
|
||||||
;
|
;
|
||||||
|
|
||||||
deviate_delete_substmts : deviate_delete_substmts deviate_delete_substmt
|
deviate_delete_substmts : deviate_delete_substmts deviate_delete_substmt
|
||||||
|
|
@ -1590,15 +1584,14 @@ deviate_delete_substmt : units_stmt { _PARSE_DEBUG("deviate-delete-substmt -> un
|
||||||
| { _PARSE_DEBUG("deviate-delete-substmt -> "); }
|
| { _PARSE_DEBUG("deviate-delete-substmt -> "); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
deviate_replace_stmt : K_DEVIATE D_REPLACE ';'
|
deviate_replace_stmt : K_DEVIATE D_REPLACE ';'
|
||||||
{ if (ysp_add(_yy, Y_DEVIATE, strdup("add") /* D_NOT_SUPPORTED*/, NULL) == NULL) _YYERROR("notification_stmt");
|
{ if (ysp_add(_yy, Y_DEVIATE, strdup("replace"), NULL) == NULL) _YYERROR("notification_stmt");
|
||||||
_PARSE_DEBUG("deviate-replace-stmt -> DEVIATE add ;"); }
|
_PARSE_DEBUG("deviate-replace-stmt -> DEVIATE replace ;"); }
|
||||||
| K_DEVIATE D_REPLACE
|
| K_DEVIATE D_REPLACE
|
||||||
{ if (ysp_add_push(_yy, Y_DEVIATE, strdup("add"), NULL) == NULL) _YYERROR("deviate_stmt"); }
|
{ if (ysp_add_push(_yy, Y_DEVIATE, strdup("replace"), NULL) == NULL) _YYERROR("deviate_stmt"); }
|
||||||
'{' deviate_replace_substmts '}'
|
'{' deviate_replace_substmts '}'
|
||||||
{ if (ystack_pop(_yy) < 0) _YYERROR("deviate_stmt");
|
{ if (ystack_pop(_yy) < 0) _YYERROR("deviate_stmt");
|
||||||
_PARSE_DEBUG("deviate-replace-stmt -> DEVIATE add { deviate-substmts }"); }
|
_PARSE_DEBUG("deviate-replace-stmt -> DEVIATE replace { deviate-replace-substmts }"); }
|
||||||
;
|
;
|
||||||
|
|
||||||
deviate_replace_substmts : deviate_replace_substmts deviate_replace_substmt
|
deviate_replace_substmts : deviate_replace_substmts deviate_replace_substmt
|
||||||
|
|
@ -1688,40 +1681,40 @@ yang_stmt : action_stmt { _PARSE_DEBUG("yang-stmt -> action-stmt");
|
||||||
| leaf_stmt { _PARSE_DEBUG("yang-stmt -> leaf-stmt");}
|
| leaf_stmt { _PARSE_DEBUG("yang-stmt -> leaf-stmt");}
|
||||||
| length_stmt { _PARSE_DEBUG("yang-stmt -> length-stmt");}
|
| length_stmt { _PARSE_DEBUG("yang-stmt -> length-stmt");}
|
||||||
| list_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| list_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
||||||
| mandatory_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| mandatory_stmt { _PARSE_DEBUG("yang-stmt -> mandatory-stmt");}
|
||||||
| max_elements_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| max_elements_stmt { _PARSE_DEBUG("yang-stmt -> max-elements-stmt");}
|
||||||
| min_elements_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| min_elements_stmt { _PARSE_DEBUG("yang-stmt -> min-elements-stmt");}
|
||||||
| modifier_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| modifier_stmt { _PARSE_DEBUG("yang-stmt -> modifier-stmt");}
|
||||||
| module_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| module_stmt { _PARSE_DEBUG("yang-stmt -> module-stmt");}
|
||||||
| must_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| must_stmt { _PARSE_DEBUG("yang-stmt -> must-stmt");}
|
||||||
| namespace_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| namespace_stmt { _PARSE_DEBUG("yang-stmt -> namespace-stmt");}
|
||||||
| notification_stmt { _PARSE_DEBUG("yang-stmt -> notification-stmt");}
|
| notification_stmt { _PARSE_DEBUG("yang-stmt -> notification-stmt");}
|
||||||
| ordered_by_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| ordered_by_stmt { _PARSE_DEBUG("yang-stmt -> ordered-by-stmt");}
|
||||||
| organization_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| organization_stmt { _PARSE_DEBUG("yang-stmt -> organization-stmt");}
|
||||||
| output_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| output_stmt { _PARSE_DEBUG("yang-stmt -> output-stmt");}
|
||||||
| path_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| path_stmt { _PARSE_DEBUG("yang-stmt -> path-stmt");}
|
||||||
| pattern_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| pattern_stmt { _PARSE_DEBUG("yang-stmt -> pattern-stmt");}
|
||||||
| position_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| position_stmt { _PARSE_DEBUG("yang-stmt -> position-stmt");}
|
||||||
| prefix_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| prefix_stmt { _PARSE_DEBUG("yang-stmt -> prefix-stmt");}
|
||||||
| presence_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| presence_stmt { _PARSE_DEBUG("yang-stmt -> presence-stmt");}
|
||||||
| range_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| range_stmt { _PARSE_DEBUG("yang-stmt -> range-stmt");}
|
||||||
| reference_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| reference_stmt { _PARSE_DEBUG("yang-stmt -> reference-stmt");}
|
||||||
| refine_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| refine_stmt { _PARSE_DEBUG("yang-stmt -> refine-stmt");}
|
||||||
| require_instance_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| require_instance_stmt { _PARSE_DEBUG("yang-stmt -> require-instance-stmt");}
|
||||||
| revision_date_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| revision_date_stmt { _PARSE_DEBUG("yang-stmt -> revision-date-stmt");}
|
||||||
| revision_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| revision_stmt { _PARSE_DEBUG("yang-stmt -> revision-stmt");}
|
||||||
| rpc_stmt { _PARSE_DEBUG("yang-stmt -> rpc-stmt");}
|
| rpc_stmt { _PARSE_DEBUG("yang-stmt -> rpc-stmt");}
|
||||||
| status_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| status_stmt { _PARSE_DEBUG("yang-stmt -> status-stmt");}
|
||||||
| submodule_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| submodule_stmt { _PARSE_DEBUG("yang-stmt -> submodule-stmt");}
|
||||||
| typedef_stmt { _PARSE_DEBUG("yang-stmt -> typedef-stmt");}
|
| typedef_stmt { _PARSE_DEBUG("yang-stmt -> typedef-stmt");}
|
||||||
| type_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| type_stmt { _PARSE_DEBUG("yang-stmt -> type-stmt");}
|
||||||
| unique_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| unique_stmt { _PARSE_DEBUG("yang-stmt -> unique-stmt");}
|
||||||
| units_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| units_stmt { _PARSE_DEBUG("yang-stmt -> units-stmt");}
|
||||||
| uses_augment_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| uses_augment_stmt { _PARSE_DEBUG("yang-stmt -> uses-augment-stmt");}
|
||||||
| uses_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| uses_stmt { _PARSE_DEBUG("yang-stmt -> uses-stmt");}
|
||||||
| value_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| value_stmt { _PARSE_DEBUG("yang-stmt -> value-stmt");}
|
||||||
| when_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| when_stmt { _PARSE_DEBUG("yang-stmt -> when-stmt");}
|
||||||
| yang_version_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");}
|
| yang_version_stmt { _PARSE_DEBUG("yang-stmt -> yang-version-stmt");}
|
||||||
/* | yin_element_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");} */
|
/* | yin_element_stmt { _PARSE_DEBUG("yang-stmt -> list-stmt");} */
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,11 +35,15 @@ module example-base{
|
||||||
prefix base;
|
prefix base;
|
||||||
namespace "urn:example:base";
|
namespace "urn:example:base";
|
||||||
container system {
|
container system {
|
||||||
must "daytime or time";
|
must "daytime or time"; /* deviate delete removes this */
|
||||||
leaf daytime{ /* not supported removes this */
|
leaf daytime{ /* deviate not-supported removes this */
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
leaf time{
|
||||||
type string;
|
type string;
|
||||||
}
|
}
|
||||||
list name-server {
|
list name-server {
|
||||||
|
max-elements 1; /* deviate replace replaces to "max.elements 3" here */
|
||||||
key name;
|
key name;
|
||||||
leaf name {
|
leaf name {
|
||||||
type string;
|
type string;
|
||||||
|
|
@ -52,7 +56,7 @@ module example-base{
|
||||||
}
|
}
|
||||||
leaf type {
|
leaf type {
|
||||||
type string;
|
type string;
|
||||||
/* add rule adds default here */
|
/* deviate add adds "default admin" here */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -60,13 +64,17 @@ module example-base{
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Args:
|
# Args:
|
||||||
# 0: daytime implemented: true/false
|
# 1: daytime implemented: true/false
|
||||||
# 1: admin type default: true/false
|
# 2: admin type default: true/false
|
||||||
|
# 3: mustdate default: true/false
|
||||||
|
# 4: maxelement of name-server is 1: true/false (if false the # is 3)
|
||||||
function testrun()
|
function testrun()
|
||||||
{
|
{
|
||||||
daytime=$1
|
daytime=$1
|
||||||
admindefault=$2
|
admindefault=$2
|
||||||
|
mustdate=$3
|
||||||
|
maxel1=$4
|
||||||
|
|
||||||
new "test params: -f $cfg"
|
new "test params: -f $cfg"
|
||||||
|
|
||||||
if [ "$BE" -ne 0 ]; then
|
if [ "$BE" -ne 0 ]; then
|
||||||
|
|
@ -82,29 +90,55 @@ function testrun()
|
||||||
new "wait backend"
|
new "wait backend"
|
||||||
wait_backend
|
wait_backend
|
||||||
|
|
||||||
if ! $daytime; then # Not supported - dont continue
|
new "Add user bob"
|
||||||
new "Add example-base daytime - should not be supported"
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><system xmlns=\"urn:example:base\"><user><name>bob</name></user></system></config></edit-config></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><system xmlns=\"urn:example:base\"><daytime>Sept17</daytime></system></config></edit-config></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>unknown-element</error-tag><error-info><bad-element>daytime</bad-element></error-info><error-severity>error</error-severity><error-message>Failed to find YANG spec of XML node: daytime with parent: system in namespace: urn:example:base</error-message></rpc-error></rpc-reply>]]>]]"
|
|
||||||
|
if $mustdate; then # fail since there is neither date or daytime (delete rule)
|
||||||
|
new "netconf validate expect error"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>operation-failed</error-tag><error-severity>error</error-severity><error-message>must xpath validation failed</error-message></rpc-error></rpc-reply>]]>]]>$"
|
||||||
else
|
else
|
||||||
|
new "netconf validate ok"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]"
|
||||||
|
fi
|
||||||
|
|
||||||
|
new "Add time"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><system xmlns=\"urn:example:base\"><time>yes</time></system></config></edit-config></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]"
|
||||||
|
|
||||||
|
new "netconf validate ok"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]"
|
||||||
|
|
||||||
|
if $daytime; then # not-supported rule
|
||||||
new "Add example-base daytime - supported"
|
new "Add example-base daytime - supported"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><system xmlns=\"urn:example:base\"><daytime>Sept17</daytime></system></config></edit-config></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]"
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><system xmlns=\"urn:example:base\"><daytime>Sept17</daytime></system></config></edit-config></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]"
|
||||||
|
else # Not supported
|
||||||
|
new "Add example-base daytime - expect error not supported"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><system xmlns=\"urn:example:base\"><daytime>Sept17</daytime></system></config></edit-config></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>unknown-element</error-tag><error-info><bad-element>daytime</bad-element></error-info><error-severity>error</error-severity><error-message>Failed to find YANG spec of XML node: daytime with parent: system in namespace: urn:example:base</error-message></rpc-error></rpc-reply>]]>]]"
|
||||||
|
fi # daytime supported
|
||||||
|
|
||||||
new "Add user bob"
|
new "netconf commit"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><system xmlns=\"urn:example:base\"><user><name>bob</name></user></system></config></edit-config></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]"
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><commit/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf commit"
|
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><commit/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
|
||||||
|
|
||||||
if $admindefault; then
|
if $admindefault; then # add rule
|
||||||
new "Get type admin expected"
|
new "Get type admin expected"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get-config><source><running/></source><filter type=\"xpath\" select=\"/base:system/base:user[base:name='bob']\" xmlns:base=\"urn:example:base\"/></get-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><data><system xmlns=\"urn:example:base\"><user><name>bob</name><type>admin</type></user></system></data></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get-config><source><running/></source><filter type=\"xpath\" select=\"/base:system/base:user[base:name='bob']\" xmlns:base=\"urn:example:base\"/></get-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><data><system xmlns=\"urn:example:base\"><user><name>bob</name><type>admin</type></user></system></data></rpc-reply>]]>]]>$"
|
||||||
# XXX Cannot select a default value??
|
# XXX Cannot select a default value??
|
||||||
# expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get-config><source><running/></source><filter type=\"xpath\" select=\"/base:system/base:user[base:name='bob']/base:type\" xmlns:base=\"urn:example:base\"/></get-config></rpc>]]>]]>" foo
|
# expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get-config><source><running/></source><filter type=\"xpath\" select=\"/base:system/base:user[base:name='bob']/base:type\" xmlns:base=\"urn:example:base\"/></get-config></rpc>]]>]]>" foo
|
||||||
else
|
else
|
||||||
new "Get type none expected"
|
new "Get type none expected"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get-config><source><running/></source><filter type=\"xpath\" select=\"/base:system/base:user[base:name='bob']/base:type\" xmlns:base=\"urn:example:base\"/></get-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><data/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get-config><source><running/></source><filter type=\"xpath\" select=\"/base:system/base:user[base:name='bob']/base:type\" xmlns:base=\"urn:example:base\"/></get-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><data/></rpc-reply>]]>]]>$"
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Add 2 name-servers
|
||||||
|
new "Add two name-servers"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><system xmlns=\"urn:example:base\"><name-server><name>aa</name></name-server><name-server><name>bb</name></name-server></system></config></edit-config></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]"
|
||||||
|
if $maxel1; then # add two and check if it fails
|
||||||
|
new "netconf validate 2 element fail"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><rpc-error><error-type>protocol</error-type><error-tag>operation-failed</error-tag><error-app-tag>too-many-elements</error-app-tag><error-severity>error</error-severity><error-path>/system/name-server</error-path></rpc-error></rpc-reply>]]>]]>$"
|
||||||
|
else
|
||||||
|
new "netconf validate 2 elements ok"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$BE" -ne 0 ]; then
|
if [ "$BE" -ne 0 ]; then
|
||||||
new "Kill backend"
|
new "Kill backend"
|
||||||
# Check if premature kill
|
# Check if premature kill
|
||||||
|
|
@ -128,8 +162,8 @@ module example-deviations{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
new "daytime supported"
|
new "1. daytime supported"
|
||||||
testrun true false
|
testrun true false true true
|
||||||
|
|
||||||
# Example from RFC 7950 Sec 7.20.3.3
|
# Example from RFC 7950 Sec 7.20.3.3
|
||||||
cat <<EOF > $fyangdev
|
cat <<EOF > $fyangdev
|
||||||
|
|
@ -145,10 +179,10 @@ module example-deviations{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
new "daytime not supported"
|
new "2. daytime not supported"
|
||||||
testrun false false
|
testrun false false true true
|
||||||
|
|
||||||
# Example from RFC 7950 Sec 7.20.3.3
|
# Add example from RFC 7950 Sec 7.20.3.3
|
||||||
cat <<EOF > $fyangdev
|
cat <<EOF > $fyangdev
|
||||||
module example-deviations{
|
module example-deviations{
|
||||||
yang-version 1.1;
|
yang-version 1.1;
|
||||||
|
|
@ -164,8 +198,47 @@ module example-deviations{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
new "deviate add, check admin default"
|
new "3. deviate add, check admin default"
|
||||||
testrun true true
|
testrun true true true true
|
||||||
|
|
||||||
|
# Delete example from RFC 7950 Sec 7.20.3.3
|
||||||
|
cat <<EOF > $fyangdev
|
||||||
|
module example-deviations{
|
||||||
|
yang-version 1.1;
|
||||||
|
prefix md;
|
||||||
|
namespace "urn:example:deviations";
|
||||||
|
import example-base {
|
||||||
|
prefix base;
|
||||||
|
}
|
||||||
|
deviation /base:system/base:name-server {
|
||||||
|
deviate replace {
|
||||||
|
max-elements 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
new "4. deviate replace"
|
||||||
|
testrun true false true false
|
||||||
|
|
||||||
|
# Replace example from RFC 7950 Sec 7.20.3.3
|
||||||
|
cat <<EOF > $fyangdev
|
||||||
|
module example-deviations{
|
||||||
|
yang-version 1.1;
|
||||||
|
prefix md;
|
||||||
|
namespace "urn:example:deviations";
|
||||||
|
import example-base {
|
||||||
|
prefix base;
|
||||||
|
}
|
||||||
|
deviation /base:system {
|
||||||
|
deviate delete {
|
||||||
|
must "daytime or time";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
new "5. deviate delete"
|
||||||
|
testrun true false false true
|
||||||
|
|
||||||
rm -rf "$dir"
|
rm -rf "$dir"
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue