diff --git a/CHANGELOG.md b/CHANGELOG.md index fd607723..54b51188 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Clixon CHANGELOG +- Yang anyxml and extensions basic support added + +- Added yang dir with ietf-netconf and clixon-config yang specs for internal usage. + - Added state data: Netconf operation introduced; Error when adding state data in . diff --git a/clixon.conf.cpp.cpp b/clixon.conf.cpp.cpp index 1a6f441d..f0a5afb0 100644 --- a/clixon.conf.cpp.cpp +++ b/clixon.conf.cpp.cpp @@ -95,8 +95,6 @@ CLICON_BACKEND_PIDFILE localstatedir/APPNAME/APPNAME.pidfile # Set if all configuration changes are committed directly, commit command unnecessary # CLICON_AUTOCOMMIT 0 -# CLICON_COMMIT_ORDER 0 - # Name of master plugin (both frontend and backend). Master plugin has special # callbacks for frontends. See clicon user manual for more info. # CLICON_MASTER_PLUGIN master diff --git a/lib/src/clixon_yang_parse.l b/lib/src/clixon_yang_parse.l index a19328b5..8364885a 100644 --- a/lib/src/clixon_yang_parse.l +++ b/lib/src/clixon_yang_parse.l @@ -179,7 +179,11 @@ clixon_yang_parsewrap(void) yang-version { BEGIN(ARGUMENT); return K_YANG_VERSION; } yin-element { BEGIN(ARGUMENT); return K_YIN_ELEMENT; } -. { return K_UNKNOWN; } +: { return *yytext; } +; { return *yytext; } +. { clixon_yang_parselval.string = strdup(yytext); + return CHAR;} + ; { BEGIN(KEYWORD); return *yytext; } \{ { BEGIN(KEYWORD); return *yytext; } diff --git a/lib/src/clixon_yang_parse.y b/lib/src/clixon_yang_parse.y index 31c59afd..73b8dc12 100644 --- a/lib/src/clixon_yang_parse.y +++ b/lib/src/clixon_yang_parse.y @@ -239,7 +239,9 @@ ystack_push(struct clicon_yang_yacc_arg *yy, yang_node *yn) * Note: consumes 'argument' which assumes it is malloced and not freed by caller */ static yang_stmt * -ysp_add(struct clicon_yang_yacc_arg *yy, enum rfc_6020 keyword, char *argument) +ysp_add(struct clicon_yang_yacc_arg *yy, + enum rfc_6020 keyword, + char *argument) { struct ys_stack *ystack = yy->yy_stack; yang_stmt *ys = NULL; @@ -453,7 +455,8 @@ body_stmts : body_stmts body_stmt { clicon_debug(2,"body-stmts -> body-stmts | body_stmt { clicon_debug(2,"body-stmts -> body-stmt");} ; -body_stmt : feature_stmt { clicon_debug(2,"body-stmt -> feature-stmt");} +body_stmt : extension_stmt { clicon_debug(2,"body-stmt -> extension-stmt");} + | feature_stmt { clicon_debug(2,"body-stmt -> feature-stmt");} | identity_stmt { clicon_debug(2,"body-stmt -> identity-stmt");} | typedef_stmt { clicon_debug(2,"body-stmt -> typedef-stmt");} | grouping_stmt { clicon_debug(2,"body-stmt -> grouping-stmt");} @@ -467,6 +470,7 @@ data_def_stmt : container_stmt { clicon_debug(2,"data-def-stmt -> containe | leaf_list_stmt { clicon_debug(2,"data-def-stmt -> leaf-list-stmt");} | list_stmt { clicon_debug(2,"data-def-stmt -> list-stmt");} | choice_stmt { clicon_debug(2,"data-def-stmt -> choice-stmt");} + | anyxml_stmt { clicon_debug(2,"data-def-stmt -> anyxml-stmt");} | uses_stmt { clicon_debug(2,"data-def-stmt -> uses-stmt");} ; @@ -633,16 +637,17 @@ short_case_stmt : container_stmt { clicon_debug(2,"short-case-substmt -> conta | leaf_stmt { clicon_debug(2,"short-case-substmt -> leaf-stmt"); } | leaf_list_stmt { clicon_debug(2,"short-case-substmt -> leaf-list-stmt"); } | list_stmt { clicon_debug(2,"short-case-substmt -> list-stmt"); } + | anyxml_stmt { clicon_debug(2,"short-case-substmt -> anyxml-stmt");} ; /* case */ case_stmt : K_CASE id_arg_str ';' - { if (ysp_add(_yy, Y_CASE, $2) == NULL) _YYERROR("19"); + { if (ysp_add(_yy, Y_CASE, $2) == NULL) _YYERROR("22"); clicon_debug(2,"case-stmt -> CASE id-arg-str ;"); } | K_CASE id_arg_str - { if (ysp_add_push(_yy, Y_CASE, $2) == NULL) _YYERROR("20"); } + { if (ysp_add_push(_yy, Y_CASE, $2) == NULL) _YYERROR("23"); } '{' case_substmts '}' - { if (ystack_pop(_yy) < 0) _YYERROR("21"); + { if (ystack_pop(_yy) < 0) _YYERROR("24"); clicon_debug(2,"case-stmt -> CASE id-arg-str { case-substmts }"); } ; @@ -663,15 +668,42 @@ case_substmt : when_stmt { clicon_debug(2,"case-substmt -> when-stmt ; +/* anyxml */ +anyxml_stmt : K_ANYXML id_arg_str ';' + { if (ysp_add(_yy, Y_ANYXML, $2) == NULL) _YYERROR("25"); + clicon_debug(2,"anyxml-stmt -> ANYXML id-arg-str ;"); } + | K_ANYXML id_arg_str + { if (ysp_add_push(_yy, Y_ANYXML, $2) == NULL) _YYERROR("26"); } + '{' anyxml_substmts '}' + { if (ystack_pop(_yy) < 0) _YYERROR("27"); + clicon_debug(2,"anyxml-stmt -> ANYXML id-arg-str { anyxml-substmts }"); } + ; + +anyxml_substmts : anyxml_substmts anyxml_substmt + { clicon_debug(2,"anyxml-substmts -> anyxml-substmts anyxml-substmt"); } + | anyxml_substmt + { clicon_debug(2,"anyxml-substmts -> anyxml-substmt"); } + ; + +anyxml_substmt : when_stmt { clicon_debug(2,"anyxml-substmt -> when-stmt"); } + | if_feature_stmt { clicon_debug(2,"anyxml-substmt -> if-feature-stmt"); } + | must_stmt { clicon_debug(2,"anyxml-substmt -> must-stmt"); } + | config_stmt { clicon_debug(2,"anyxml-substmt -> config-stmt"); } + | mandatory_stmt { clicon_debug(2,"anyxml-substmt -> mandatory-stmt"); } + | status_stmt { clicon_debug(2,"anyxml-substmt -> status-stmt"); } + | description_stmt { clicon_debug(2,"anyxml-substmt -> description-stmt"); } + | reference_stmt { clicon_debug(2,"anyxml-substmt -> reference-stmt"); } + | ustring ':' ustring ';' { clicon_debug(2,"anyxml-substmt -> anyxml extension"); } + ; /* uses */ uses_stmt : K_USES identifier_ref_arg_str ';' - { if (ysp_add(_yy, Y_USES, $2) == NULL) _YYERROR("19"); + { if (ysp_add(_yy, Y_USES, $2) == NULL) _YYERROR("28"); clicon_debug(2,"uses-stmt -> USES id-arg-str ;"); } | K_USES identifier_ref_arg_str - { if (ysp_add_push(_yy, Y_USES, $2) == NULL) _YYERROR("20"); } + { if (ysp_add_push(_yy, Y_USES, $2) == NULL) _YYERROR("29"); } '{' uses_substmts '}' - { if (ystack_pop(_yy) < 0) _YYERROR("21"); + { if (ystack_pop(_yy) < 0) _YYERROR("30"); clicon_debug(2,"uses-stmt -> USES id-arg-str { uses-substmts }"); } ; @@ -694,12 +726,12 @@ uses_substmt : when_stmt { clicon_debug(2,"uses-substmt -> when-stmt /* refine XXX need further refining */ refine_stmt : K_REFINE id_arg_str ';' - { if (ysp_add(_yy, Y_REFINE, $2) == NULL) _YYERROR("21"); + { if (ysp_add(_yy, Y_REFINE, $2) == NULL) _YYERROR("31"); clicon_debug(2,"refine-stmt -> REFINE id-arg-str ;"); } | K_REFINE id_arg_str - { if (ysp_add_push(_yy, Y_REFINE, $2) == NULL) _YYERROR("22"); } + { if (ysp_add_push(_yy, Y_REFINE, $2) == NULL) _YYERROR("32"); } '{' refine_substmts '}' - { if (ystack_pop(_yy) < 0) _YYERROR("23"); + { if (ystack_pop(_yy) < 0) _YYERROR("33"); clicon_debug(2,"refine-stmt -> REFINE id-arg-str { refine-substmts }"); } ; @@ -720,9 +752,9 @@ refine_substmt : must_stmt { clicon_debug(2,"refine-substmt -> must-stmt"); uses_augment_stmt : augment_stmt; augment_stmt : K_AUGMENT string - { if (ysp_add_push(_yy, Y_AUGMENT, $2) == NULL) _YYERROR("22"); } + { if (ysp_add_push(_yy, Y_AUGMENT, $2) == NULL) _YYERROR("34"); } '{' augment_substmts '}' - { if (ystack_pop(_yy) < 0) _YYERROR("23"); + { if (ystack_pop(_yy) < 0) _YYERROR("35"); clicon_debug(2,"augment-stmt -> AUGMENT string { augment-substmts }"); } ; @@ -744,12 +776,12 @@ augment_substmt : when_stmt { clicon_debug(2,"augment-substmt -> when-s /* when */ when_stmt : K_WHEN string ';' - { if (ysp_add(_yy, Y_WHEN, $2) == NULL) _YYERROR("21"); + { if (ysp_add(_yy, Y_WHEN, $2) == NULL) _YYERROR("36"); clicon_debug(2,"when-stmt -> WHEN string ;"); } | K_WHEN string - { if (ysp_add_push(_yy, Y_WHEN, $2) == NULL) _YYERROR("22"); } + { if (ysp_add_push(_yy, Y_WHEN, $2) == NULL) _YYERROR("37"); } '{' when_substmts '}' - { if (ystack_pop(_yy) < 0) _YYERROR("23"); + { if (ystack_pop(_yy) < 0) _YYERROR("38"); clicon_debug(2,"when-stmt -> WHEN string { when-substmts }"); } ; @@ -766,12 +798,12 @@ when_substmt : description_stmt { clicon_debug(2,"when-substmt -> description-s /* rpc */ rpc_stmt : K_RPC id_arg_str ';' - { if (ysp_add(_yy, Y_RPC, $2) == NULL) _YYERROR("21"); + { if (ysp_add(_yy, Y_RPC, $2) == NULL) _YYERROR("39"); clicon_debug(2,"rpc-stmt -> RPC id-arg-str ;"); } | K_RPC id_arg_str - { if (ysp_add_push(_yy, Y_RPC, $2) == NULL) _YYERROR("22"); } + { if (ysp_add_push(_yy, Y_RPC, $2) == NULL) _YYERROR("40"); } '{' rpc_substmts '}' - { if (ystack_pop(_yy) < 0) _YYERROR("23"); + { if (ystack_pop(_yy) < 0) _YYERROR("41"); clicon_debug(2,"rpc-stmt -> RPC id-arg-str { rpc-substmts }"); } ; @@ -794,9 +826,9 @@ rpc_substmt : if_feature_stmt { clicon_debug(2,"rpc-substmt -> if-feature-stm /* input */ input_stmt : K_INPUT - { if (ysp_add_push(_yy, Y_INPUT, NULL) == NULL) _YYERROR("24"); } + { if (ysp_add_push(_yy, Y_INPUT, NULL) == NULL) _YYERROR("42"); } '{' input_substmts '}' - { if (ystack_pop(_yy) < 0) _YYERROR("25"); + { if (ystack_pop(_yy) < 0) _YYERROR("43"); clicon_debug(2,"input-stmt -> INPUT { input-substmts }"); } ; @@ -814,18 +846,18 @@ input_substmt : typedef_stmt { clicon_debug(2,"input-substmt -> typedef- /* output */ output_stmt : K_OUTPUT /* XXX reuse input-substatements since they are same */ - { if (ysp_add_push(_yy, Y_OUTPUT, NULL) == NULL) _YYERROR("24"); } + { if (ysp_add_push(_yy, Y_OUTPUT, NULL) == NULL) _YYERROR("44"); } '{' input_substmts '}' - { if (ystack_pop(_yy) < 0) _YYERROR("25"); + { if (ystack_pop(_yy) < 0) _YYERROR("45"); clicon_debug(2,"output-stmt -> OUTPUT { input-substmts }"); } ; /* Typedef */ typedef_stmt : K_TYPEDEF id_arg_str - { if (ysp_add_push(_yy, Y_TYPEDEF, $2) == NULL) _YYERROR("24"); } + { if (ysp_add_push(_yy, Y_TYPEDEF, $2) == NULL) _YYERROR("46"); } '{' typedef_substmts '}' - { if (ystack_pop(_yy) < 0) _YYERROR("25"); + { if (ystack_pop(_yy) < 0) _YYERROR("47"); clicon_debug(2,"typedef-stmt -> TYPEDEF id-arg-str { typedef-substmts }"); } ; @@ -847,13 +879,13 @@ typedef_substmt : type_stmt { clicon_debug(2,"typedef-substmt -> type-s /* Type */ type_stmt : K_TYPE identifier_ref_arg_str ';' - { if (ysp_add(_yy, Y_TYPE, $2) == NULL) _YYERROR("26"); + { if (ysp_add(_yy, Y_TYPE, $2) == NULL) _YYERROR("48"); clicon_debug(2,"type-stmt -> TYPE identifier-ref-arg-str ;");} | K_TYPE identifier_ref_arg_str - { if (ysp_add_push(_yy, Y_TYPE, $2) == NULL) _YYERROR("27"); + { if (ysp_add_push(_yy, Y_TYPE, $2) == NULL) _YYERROR("49"); } '{' type_body_stmts '}' - { if (ystack_pop(_yy) < 0) _YYERROR("28"); + { if (ystack_pop(_yy) < 0) _YYERROR("50"); clicon_debug(2,"type-stmt -> TYPE identifier-ref-arg-str { type-body-stmts }");} ; @@ -892,9 +924,9 @@ type_body_stmt/* numerical-restrictions */ /* Grouping */ grouping_stmt : K_GROUPING id_arg_str - { if (ysp_add_push(_yy, Y_GROUPING, $2) == NULL) _YYERROR("29"); } + { if (ysp_add_push(_yy, Y_GROUPING, $2) == NULL) _YYERROR("51"); } '{' grouping_substmts '}' - { if (ystack_pop(_yy) < 0) _YYERROR("30"); + { if (ystack_pop(_yy) < 0) _YYERROR("52"); clicon_debug(2,"grouping-stmt -> GROUPING id-arg-str { grouping-substmts }"); } ; @@ -915,13 +947,13 @@ grouping_substmt : status_stmt { clicon_debug(2,"grouping-substmt -> st /* length-stmt */ length_stmt : K_LENGTH string ';' /* XXX length-arg-str */ - { if (ysp_add(_yy, Y_LENGTH, $2) == NULL) _YYERROR("31"); + { if (ysp_add(_yy, Y_LENGTH, $2) == NULL) _YYERROR("53"); clicon_debug(2,"length-stmt -> LENGTH string ;"); } | K_LENGTH string - { if (ysp_add_push(_yy, Y_LENGTH, $2) == NULL) _YYERROR("32"); } + { if (ysp_add_push(_yy, Y_LENGTH, $2) == NULL) _YYERROR("54"); } '{' length_substmts '}' - { if (ystack_pop(_yy) < 0) _YYERROR("33"); + { if (ystack_pop(_yy) < 0) _YYERROR("55"); clicon_debug(2,"length-stmt -> LENGTH string { length-substmts }"); } ; @@ -940,13 +972,13 @@ length_substmt : error_message_stmt { clicon_debug(2,"length-substmt -> error-m /* Pattern */ pattern_stmt : K_PATTERN string ';' - { if (ysp_add(_yy, Y_PATTERN, $2) == NULL) _YYERROR("34"); + { if (ysp_add(_yy, Y_PATTERN, $2) == NULL) _YYERROR("56"); clicon_debug(2,"pattern-stmt -> PATTERN string ;"); } | K_PATTERN string - { if (ysp_add_push(_yy, Y_PATTERN, $2) == NULL) _YYERROR("35"); } + { if (ysp_add_push(_yy, Y_PATTERN, $2) == NULL) _YYERROR("57"); } '{' pattern_substmts '}' - { if (ystack_pop(_yy) < 0) _YYERROR("36"); + { if (ystack_pop(_yy) < 0) _YYERROR("58"); clicon_debug(2,"pattern-stmt -> PATTERN string { pattern-substmts }"); } ; @@ -962,18 +994,49 @@ pattern_substmt : reference_stmt { clicon_debug(2,"pattern-substmt -> refere | { clicon_debug(2,"pattern-substmt -> "); } ; -/* Feature */ -feature_stmt : K_FEATURE id_arg_str ';' - { if (ysp_add(_yy, Y_FEATURE, $2) == NULL) _YYERROR("50"); - clicon_debug(2,"feature-stmt -> FEATURE id-arg-str ;"); } +/* Extension */ +extension_stmt: K_EXTENSION id_arg_str ';' + { if (ysp_add(_yy, Y_EXTENSION, $2) == NULL) _YYERROR("59"); + clicon_debug(2,"extenstion-stmt -> EXTENSION id-arg-str ;"); } + | K_EXTENSION id_arg_str + { if (ysp_add_push(_yy, Y_EXTENSION, $2) == NULL) _YYERROR("60"); } + '{' extension_substmts '}' + { if (ystack_pop(_yy) < 0) _YYERROR("61"); + clicon_debug(2,"extension-stmt -> FEATURE id-arg-str { extension-substmts }"); } + ; - | K_FEATURE id_arg_str - { if (ysp_add_push(_yy, Y_FEATURE, $2) == NULL) _YYERROR("51"); } - '{' feature_substmts '}' - { if (ystack_pop(_yy) < 0) _YYERROR("52"); - clicon_debug(2,"feature-stmt -> FEATURE id-arg-str { feature-substmts }"); } + +/* extension substmts */ +extension_substmts : extension_substmts extension_substmt + { clicon_debug(2,"extension-substmts -> extension-substmts extension-substmt"); } + | extension_substmt + { clicon_debug(2,"extension-substmts -> extension-substmt"); } ; +extension_substmt : argument_stmt { clicon_debug(2,"extension-substmt -> argument-stmt"); } + | status_stmt { clicon_debug(2,"extension-substmt -> status-stmt"); } + | description_stmt { clicon_debug(2,"extension-substmt -> description-stmt"); } + | reference_stmt { clicon_debug(2,"extension-substmt -> reference-stmt"); } + | unknown_stmt { clicon_debug(2,"extension-substmt -> unknown-stmt");} + | { clicon_debug(2,"extension-substmt -> "); } + ; + +argument_stmt : K_ARGUMENT id_arg_str ';' + | K_ARGUMENT id_arg_str '{' '}' + ; + +/* Feature */ +feature_stmt : K_FEATURE id_arg_str ';' + { if (ysp_add(_yy, Y_FEATURE, $2) == NULL) _YYERROR("62"); + clicon_debug(2,"feature-stmt -> FEATURE id-arg-str ;"); } + | K_FEATURE id_arg_str + { if (ysp_add_push(_yy, Y_FEATURE, $2) == NULL) _YYERROR("63"); } + '{' feature_substmts '}' + { if (ystack_pop(_yy) < 0) _YYERROR("64"); + clicon_debug(2,"feature-stmt -> FEATURE id-arg-str { feature-substmts }"); } + ; + +/* feature substmts */ feature_substmts : feature_substmts feature_substmt { clicon_debug(2,"feature-substmts -> feature-substmts feature-substmt"); } | feature_substmt @@ -990,13 +1053,13 @@ feature_substmt : if_feature_stmt { clicon_debug(2,"feature-substmt -> if-fea /* Identity */ identity_stmt : K_IDENTITY string ';' /* XXX identifier-arg-str */ - { if (ysp_add(_yy, Y_IDENTITY, $2) == NULL) _YYERROR("53"); + { if (ysp_add(_yy, Y_IDENTITY, $2) == NULL) _YYERROR("65"); clicon_debug(2,"identity-stmt -> IDENTITY string ;"); } | K_IDENTITY string - { if (ysp_add_push(_yy, Y_IDENTITY, $2) == NULL) _YYERROR("54"); } + { if (ysp_add_push(_yy, Y_IDENTITY, $2) == NULL) _YYERROR("66"); } '{' identity_substmts '}' - { if (ystack_pop(_yy) < 0) _YYERROR("55"); + { if (ystack_pop(_yy) < 0) _YYERROR("67"); clicon_debug(2,"identity-stmt -> IDENTITY string { identity-substmts }"); } ; @@ -1016,13 +1079,13 @@ identity_substmt : base_stmt { clicon_debug(2,"identity-substmt -> base- /* range-stmt */ range_stmt : K_RANGE string ';' /* XXX range-arg-str */ - { if (ysp_add(_yy, Y_RANGE, $2) == NULL) _YYERROR("56"); + { if (ysp_add(_yy, Y_RANGE, $2) == NULL) _YYERROR("68"); clicon_debug(2,"range-stmt -> RANGE string ;"); } | K_RANGE string - { if (ysp_add_push(_yy, Y_RANGE, $2) == NULL) _YYERROR("57"); } + { if (ysp_add_push(_yy, Y_RANGE, $2) == NULL) _YYERROR("69"); } '{' range_substmts '}' - { if (ystack_pop(_yy) < 0) _YYERROR("58"); + { if (ystack_pop(_yy) < 0) _YYERROR("70"); clicon_debug(2,"range-stmt -> RANGE string { range-substmts }"); } ; @@ -1041,13 +1104,12 @@ range_substmt : error_message_stmt { clicon_debug(2,"range-substmt -> error-me /* enum-stmt */ enum_stmt : K_ENUM string ';' - { if (ysp_add(_yy, Y_ENUM, $2) == NULL) _YYERROR("59"); + { if (ysp_add(_yy, Y_ENUM, $2) == NULL) _YYERROR("71"); clicon_debug(2,"enum-stmt -> ENUM string ;"); } - | K_ENUM string - { if (ysp_add_push(_yy, Y_ENUM, $2) == NULL) _YYERROR("60"); } + { if (ysp_add_push(_yy, Y_ENUM, $2) == NULL) _YYERROR("72"); } '{' enum_substmts '}' - { if (ystack_pop(_yy) < 0) _YYERROR("61"); + { if (ystack_pop(_yy) < 0) _YYERROR("73"); clicon_debug(2,"enum-stmt -> ENUM string { enum-substmts }"); } ; @@ -1067,13 +1129,12 @@ enum_substmt : value_stmt { clicon_debug(2,"enum-substmt -> value-stm /* bit-stmt */ bit_stmt : K_BIT string ';' - { if (ysp_add(_yy, Y_BIT, $2) == NULL) _YYERROR("62"); + { if (ysp_add(_yy, Y_BIT, $2) == NULL) _YYERROR("74"); clicon_debug(2,"bit-stmt -> BIT string ;"); } - | K_BIT string - { if (ysp_add_push(_yy, Y_BIT, $2) == NULL) _YYERROR("63"); } + { if (ysp_add_push(_yy, Y_BIT, $2) == NULL) _YYERROR("75"); } '{' bit_substmts '}' - { if (ystack_pop(_yy) < 0) _YYERROR("64"); + { if (ystack_pop(_yy) < 0) _YYERROR("76"); clicon_debug(2,"bit-stmt -> BIT string { bit-substmts }"); } ; @@ -1092,13 +1153,13 @@ bit_substmt : position_stmt { clicon_debug(2,"bit-substmt -> positition /* mus-stmt */ must_stmt : K_MUST string ';' - { if (ysp_add(_yy, Y_MUST, $2) == NULL) _YYERROR("65"); + { if (ysp_add(_yy, Y_MUST, $2) == NULL) _YYERROR("77"); clicon_debug(2,"must-stmt -> MUST string ;"); } | K_MUST string - { if (ysp_add_push(_yy, Y_MUST, $2) == NULL) _YYERROR("66"); } + { if (ysp_add_push(_yy, Y_MUST, $2) == NULL) _YYERROR("78"); } '{' must_substmts '}' - { if (ystack_pop(_yy) < 0) _YYERROR("67"); + { if (ystack_pop(_yy) < 0) _YYERROR("79"); clicon_debug(2,"must-stmt -> MUST string { must-substmts }"); } ; @@ -1116,13 +1177,13 @@ must_substmt : error_message_stmt { clicon_debug(2,"must-substmt -> error-mes /* error-message-stmt */ error_message_stmt : K_ERROR_MESSAGE string ';' - { if (ysp_add(_yy, Y_ERROR_MESSAGE, $2) == NULL) _YYERROR("68"); } + { if (ysp_add(_yy, Y_ERROR_MESSAGE, $2) == NULL) _YYERROR("80"); } /* import */ import_stmt : K_IMPORT id_arg_str - { if (ysp_add_push(_yy, Y_IMPORT, $2) == NULL) _YYERROR("69"); } + { if (ysp_add_push(_yy, Y_IMPORT, $2) == NULL) _YYERROR("81"); } '{' import_substmts '}' - { if (ystack_pop(_yy) < 0) _YYERROR("70"); + { if (ystack_pop(_yy) < 0) _YYERROR("82"); clicon_debug(2,"import-stmt -> IMPORT id-arg-str { import-substmts }");} ; @@ -1139,144 +1200,144 @@ import_substmt : prefix_stmt { clicon_debug(2,"import-stmt -> prefix-stmt"); } /* Simple statements */ yang_version_stmt : K_YANG_VERSION string ';' /* XXX yang-version-arg-str */ - { if (ysp_add(_yy, Y_YANG_VERSION, $2) == NULL) _YYERROR("71"); + { if (ysp_add(_yy, Y_YANG_VERSION, $2) == NULL) _YYERROR("83"); clicon_debug(2,"yang-version-stmt -> YANG-VERSION string"); } ; fraction_digits_stmt : K_FRACTION_DIGITS string ';' /* XXX: fraction-digits-arg-str */ - { if (ysp_add(_yy, Y_FRACTION_DIGITS, $2) == NULL) _YYERROR("72"); + { if (ysp_add(_yy, Y_FRACTION_DIGITS, $2) == NULL) _YYERROR("84"); clicon_debug(2,"fraction-digits-stmt -> FRACTION-DIGITS string"); } ; if_feature_stmt : K_IF_FEATURE identifier_ref_arg_str ';' - { if (ysp_add(_yy, Y_IF_FEATURE, $2) == NULL) _YYERROR("73"); + { if (ysp_add(_yy, Y_IF_FEATURE, $2) == NULL) _YYERROR("85"); clicon_debug(2,"if-feature-stmt -> IF-FEATURE identifier-ref-arg-str"); } ; value_stmt : K_VALUE integer_value ';' - { if (ysp_add(_yy, Y_VALUE, $2) == NULL) _YYERROR("74"); + { if (ysp_add(_yy, Y_VALUE, $2) == NULL) _YYERROR("86"); clicon_debug(2,"value-stmt -> VALUE integer-value"); } ; position_stmt : K_POSITION integer_value ';' - { if (ysp_add(_yy, Y_POSITION, $2) == NULL) _YYERROR("75"); + { if (ysp_add(_yy, Y_POSITION, $2) == NULL) _YYERROR("87"); clicon_debug(2,"position-stmt -> POSITION integer-value"); } ; status_stmt : K_STATUS string ';' /* XXX: status-arg-str */ - { if (ysp_add(_yy, Y_STATUS, $2) == NULL) _YYERROR("76"); + { if (ysp_add(_yy, Y_STATUS, $2) == NULL) _YYERROR("88"); clicon_debug(2,"status-stmt -> STATUS string"); } ; config_stmt : K_CONFIG config_arg_str ';' - { if (ysp_add(_yy, Y_CONFIG, $2) == NULL) _YYERROR("77"); + { if (ysp_add(_yy, Y_CONFIG, $2) == NULL) _YYERROR("89"); clicon_debug(2,"config-stmt -> CONFIG config-arg-str"); } ; base_stmt : K_BASE identifier_ref_arg_str ';' - { if (ysp_add(_yy, Y_BASE, $2)== NULL) _YYERROR("78"); + { if (ysp_add(_yy, Y_BASE, $2)== NULL) _YYERROR("90"); clicon_debug(2,"base-stmt -> BASE identifier-ref-arg-str"); } ; path_stmt : K_PATH string ';' /* XXX: path-arg-str */ - { if (ysp_add(_yy, Y_PATH, $2)== NULL) _YYERROR("79"); + { if (ysp_add(_yy, Y_PATH, $2)== NULL) _YYERROR("91"); clicon_debug(2,"path-stmt -> PATH string"); } ; require_instance_stmt : K_REQUIRE_INSTANCE string ';' /* XXX: require-instance-arg-str */ - { if (ysp_add(_yy, Y_REQUIRE_INSTANCE, $2)== NULL) _YYERROR("90"); + { if (ysp_add(_yy, Y_REQUIRE_INSTANCE, $2)== NULL) _YYERROR("92"); clicon_debug(2,"require-instance-stmt -> REQUIRE-INSTANCE string"); } ; units_stmt : K_UNITS string ';' - { if (ysp_add(_yy, Y_UNITS, $2)== NULL) _YYERROR("91"); + { if (ysp_add(_yy, Y_UNITS, $2)== NULL) _YYERROR("93"); clicon_debug(2,"units-stmt -> UNITS string"); } ; default_stmt : K_DEFAULT string ';' - { if (ysp_add(_yy, Y_DEFAULT, $2)== NULL) _YYERROR("92"); + { if (ysp_add(_yy, Y_DEFAULT, $2)== NULL) _YYERROR("94"); clicon_debug(2,"default-stmt -> DEFAULT string"); } ; contact_stmt : K_CONTACT string ';' - { if (ysp_add(_yy, Y_CONTACT, $2)== NULL) _YYERROR("93"); + { if (ysp_add(_yy, Y_CONTACT, $2)== NULL) _YYERROR("95"); clicon_debug(2,"contact-stmt -> CONTACT string"); } ; revision_date_stmt : K_REVISION_DATE string ';' /* XXX date-arg-str */ - { if (ysp_add(_yy, Y_REVISION_DATE, $2) == NULL) _YYERROR("94"); + { if (ysp_add(_yy, Y_REVISION_DATE, $2) == NULL) _YYERROR("96"); clicon_debug(2,"revision-date-stmt -> date;"); } ; include_stmt : K_INCLUDE id_arg_str ';' - { if (ysp_add(_yy, Y_INCLUDE, $2)== NULL) _YYERROR("95"); + { if (ysp_add(_yy, Y_INCLUDE, $2)== NULL) _YYERROR("97"); clicon_debug(2,"include-stmt -> id-arg-str"); } | K_INCLUDE id_arg_str '{' revision_date_stmt '}' - { if (ysp_add(_yy, Y_INCLUDE, $2)== NULL) _YYERROR("96"); + { if (ysp_add(_yy, Y_INCLUDE, $2)== NULL) _YYERROR("98"); clicon_debug(2,"include-stmt -> id-arg-str { revision-date-stmt }"); } ; namespace_stmt : K_NAMESPACE string ';' /* XXX uri-str */ - { if (ysp_add(_yy, Y_NAMESPACE, $2)== NULL) _YYERROR("97"); + { if (ysp_add(_yy, Y_NAMESPACE, $2)== NULL) _YYERROR("99"); clicon_debug(2,"namespace-stmt -> NAMESPACE string"); } ; prefix_stmt : K_PREFIX string ';' /* XXX prefix-arg-str */ - { if (ysp_add(_yy, Y_PREFIX, $2)== NULL) _YYERROR("98"); + { if (ysp_add(_yy, Y_PREFIX, $2)== NULL) _YYERROR("100"); clicon_debug(2,"prefix-stmt -> PREFIX string ;");} ; description_stmt: K_DESCRIPTION string ';' - { if (ysp_add(_yy, Y_DESCRIPTION, $2)== NULL) _YYERROR("99"); + { if (ysp_add(_yy, Y_DESCRIPTION, $2)== NULL) _YYERROR("101"); clicon_debug(2,"description-stmt -> DESCRIPTION string ;");} ; organization_stmt: K_ORGANIZATION string ';' - { if (ysp_add(_yy, Y_ORGANIZATION, $2)== NULL) _YYERROR("100"); + { if (ysp_add(_yy, Y_ORGANIZATION, $2)== NULL) _YYERROR("102"); clicon_debug(2,"organization-stmt -> ORGANIZATION string ;");} ; min_elements_stmt: K_MIN_ELEMENTS integer_value ';' - { if (ysp_add(_yy, Y_MIN_ELEMENTS, $2)== NULL) _YYERROR("101"); + { if (ysp_add(_yy, Y_MIN_ELEMENTS, $2)== NULL) _YYERROR("103"); clicon_debug(2,"min-elements-stmt -> MIN-ELEMENTS integer ;");} ; max_elements_stmt: K_MAX_ELEMENTS integer_value ';' - { if (ysp_add(_yy, Y_MAX_ELEMENTS, $2)== NULL) _YYERROR("101"); + { if (ysp_add(_yy, Y_MAX_ELEMENTS, $2)== NULL) _YYERROR("104"); clicon_debug(2,"max-elements-stmt -> MIN-ELEMENTS integer ;");} ; reference_stmt: K_REFERENCE string ';' - { if (ysp_add(_yy, Y_REFERENCE, $2)== NULL) _YYERROR("101"); + { if (ysp_add(_yy, Y_REFERENCE, $2)== NULL) _YYERROR("105"); clicon_debug(2,"reference-stmt -> REFERENCE string ;");} ; mandatory_stmt: K_MANDATORY string ';' { yang_stmt *ys; - if ((ys = ysp_add(_yy, Y_MANDATORY, $2))== NULL) _YYERROR("102"); + if ((ys = ysp_add(_yy, Y_MANDATORY, $2))== NULL) _YYERROR("106"); clicon_debug(2,"mandatory-stmt -> MANDATORY mandatory-arg-str ;");} ; presence_stmt: K_PRESENCE string ';' { yang_stmt *ys; - if ((ys = ysp_add(_yy, Y_PRESENCE, $2))== NULL) _YYERROR("102"); + if ((ys = ysp_add(_yy, Y_PRESENCE, $2))== NULL) _YYERROR("107"); clicon_debug(2,"presence-stmt -> PRESENCE string ;");} ; ordered_by_stmt: K_ORDERED_BY string ';' { yang_stmt *ys; - if ((ys = ysp_add(_yy, Y_ORDERED_BY, $2))== NULL) _YYERROR("102"); + if ((ys = ysp_add(_yy, Y_ORDERED_BY, $2))== NULL) _YYERROR("108"); clicon_debug(2,"ordered-by-stmt -> ORDERED-BY ordered-by-arg ;");} ; key_stmt : K_KEY id_arg_str ';' /* XXX key_arg_str */ - { if (ysp_add(_yy, Y_KEY, $2)== NULL) _YYERROR("103"); + { if (ysp_add(_yy, Y_KEY, $2)== NULL) _YYERROR("109"); clicon_debug(2,"key-stmt -> KEY id-arg-str ;");} ; unique_stmt : K_UNIQUE id_arg_str ';' /* XXX key_arg_str */ - { if (ysp_add(_yy, Y_UNIQUE, $2)== NULL) _YYERROR("104"); + { if (ysp_add(_yy, Y_UNIQUE, $2)== NULL) _YYERROR("110"); clicon_debug(2,"key-stmt -> KEY id-arg-str ;");} ; @@ -1287,10 +1348,10 @@ integer_value : string { $$=$1; } ; identifier_ref_arg_str : string - { if (($$=prefix_id_join(NULL, $1)) == NULL) _YYERROR("105"); + { if (($$=prefix_id_join(NULL, $1)) == NULL) _YYERROR("111"); clicon_debug(2,"identifier-ref-arg-str -> string"); } | string ':' string - { if (($$=prefix_id_join($1, $3)) == NULL) _YYERROR("106"); + { if (($$=prefix_id_join($1, $3)) == NULL) _YYERROR("112"); clicon_debug(2,"identifier-ref-arg-str -> prefix : string"); } ; diff --git a/test/test2.sh b/test/test2.sh index 8fba9063..7710981a 100755 --- a/test/test2.sh +++ b/test/test2.sh @@ -87,7 +87,7 @@ new "netconf discard-changes" expecteof "$clixon_netconf -qf $clixon_cf" "]]>]]>" "^]]>]]>$" new "netconf edit state operation should fail" -expecteof "$clixon_netconf -qf $clixon_cf" "eth1eth]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $clixon_cf" "eth1eth]]>]]>" "^invalid-value" new "netconf lock/unlock" expecteof "$clixon_netconf -qf $clixon_cf" "]]>]]>]]>]]>" "^]]>]]>]]>]]>$" diff --git a/yang/clixon-config@2017-07-02.yang b/yang/clixon-config@2017-07-02.yang new file mode 100644 index 00000000..ed704545 --- /dev/null +++ b/yang/clixon-config@2017-07-02.yang @@ -0,0 +1,179 @@ + module clixon-config { + + prefix cc; + + organization + "Clicon / Clixon"; + + contact + "Olof Hagsand "; + + description + "Clixon configuration file + ***** BEGIN LICENSE BLOCK ***** + Copyright (C) 2009-2017 Olof Hagsand and Benny Holmgren + + This file is part of CLIXON + + Licensed under the Apache License, Version 2.0 (the \"License\"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an \"AS IS\" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + Alternatively, the contents of this file may be used under the terms of + the GNU General Public License Version 3 or later (the \"GPL\"), + in which case the provisions of the GPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of the GPL, and not to allow others to + use your version of this file under the terms of Apache License version 2, + indicate your decision by deleting the provisions above and replace them with + the notice and other provisions required by the GPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the Apache License version 2 or the GPL. + + ***** END LICENSE BLOCK *****"; + + revision 2017-07-02 { + description + "Initial revision"; + } + leaf CLICON_CONFIGFILE{ + type string; + default "sysconfdir/$APPNAME.conf"; + description "Location of configuration-file for default values (this file)"; + } + leaf CLICON_YANG_DIR { + type string; + default "prefix/share/$APPNAME/yang"; + description "Location of YANG module and submodule files. Only if CLICON_DBSPEC_TYPE is YANG"; + } + leaf CLICON_YANG_MODULE_MAIN { + type string; + default "clicon"; + description "Option used to construct initial yang file: + [@] + This option is only relevant if CLICON_DBSPEC_TYPE is YANG"; + } + leaf CLICON_YANG_MODULE_REVISION { + type string; + description "Option used to construct initial yang file: + [@]"; + } + leaf CLICON_BACKEND_DIR { + type string; + default "libdir/$APPNAME/backend"; + description "Location of backend .so plugins"; + } + leaf CLICON_NETCONF_DIR { + type string; + default "libdir/$APPNAME/netconf"; + description "Location of netconf (frontend) .so plugins"; + } + leaf CLICON_RESTCONF_DIR { + type string; + default "libdir/$APPNAME/restconf"; + description "Location of restconf (frontend) .so plugins"; + } + leaf CLICON_CLI_DIR { + type string; + default "libdir/$APPNAME/cli"; + description "Location of cli frontend .so plugins"; + } + leaf CLICON_CLISPEC_DIR { + type string; + default "libdir/$APPNAME/clispec"; + description "Location of frontend .cli cligen spec files"; + } + leaf CLICON_USE_STARTUP_CONFIG { + type int32; + default 0; + description "Enabled uses \"startup\" configuration on boot"; + } + leaf CLICON_SOCK_FAMILY { + type string; + default "UNIX"; + description "Address family for communicating with clixon_backend (UNIX|IPv4|IPv6)"; + } + leaf CLICON_SOCK { + type string; + default "localstatedir/$APPNAME/$APPNAME.sock"; + description "If family above is AF_UNIX: Unix socket for communicating with + clixon_backend. If family above is AF_INET: IPv4 address"; + } + leaf CLICON_SOCK_PORT { + type int32; + default 4535; + description "Inet socket port for communicating with clixon_backend (only IPv4|IPv6)"; + } + leaf CLICON_BACKEND_PIDFILE { + type string; + default "localstatedir/$APPNAME/$APPNAME.pidfile"; + description "Process-id file"; + } + leaf CLICON_SOCK_GROUP { + type string; + default "clicon"; + description "Group membership to access clixon_backend unix socket"; + } + leaf CLICON_AUTOCOMMIT { + type int32; + default 0; + description "Set if all configuration changes are committed directly, + commit command unnecessary"; + } + leaf CLICON_MASTER_PLUGIN { + type string; + default "master"; + description "Name of master plugin (both frontend and backend). + Master plugin has special callbacks for frontends. + See clicon user manual for more info."; + } + leaf CLICON_CLI_MODE { + type string; + default "base"; + description "Startup CLI mode. This should match the CLICON_MODE in your startup clispec file"; + } + leaf CLICON_CLI_GENMODEL { + type int32; + default 1; + description "Generate code for CLI completion of existing db symbols. + Add name=\"myspec\" in datamodel spec and reference as @myspec"; + } + leaf CLICON_CLI_GENMODEL_COMPLETION { + type int32; + default 0; + description "Generate code for CLI completion of existing db symbols"; + } + leaf CLICON_CLI_GENMODEL_TYPE { + type string; + default "VARS"; + description "How to generate and show CLI syntax: VARS|ALL"; + } + leaf CLICON_XMLDB_DIR { + type string; + default "localstatedir/$APPNAME"; + description "Directory where \"running\", \"candidate\" and \"startup\" are placed"; + } + leaf CLICON_XMLDB_PLUGIN { + type string; + default "libdir/xmldb/text.so"; + description "XMLDB datastore plugin filename (see datastore/ and clixon_xml_db.[ch])"; + } + leaf CLICON_CLI_VARONLY { + type int32; + default 1; + description "Dont include keys in cvec in cli vars callbacks, ie a & k in 'a k ' ignored"; + } + + leaf CLICON_RESTCONF_PATH { + type string; + default "/www-data/fastcgi_restconf.sock"; + description "FastCGI unix socket. Should be specified in webserver + Eg in nginx: fastcgi_pass unix:/www-data/clicon_restconf.sock;"; + } +} diff --git a/yang/ietf-netconf@2011-06-01.yang b/yang/ietf-netconf@2011-06-01.yang new file mode 100644 index 00000000..9fac6c58 --- /dev/null +++ b/yang/ietf-netconf@2011-06-01.yang @@ -0,0 +1,926 @@ + module ietf-netconf { + + // the namespace for NETCONF XML definitions is unchanged + // from RFC 4741, which this document replaces + namespace "urn:ietf:params:xml:ns:netconf:base:1.0"; + + prefix nc; + + import ietf-inet-types { + prefix inet; + } + + organization + "IETF NETCONF (Network Configuration) Working Group"; + + contact + "WG Web: + WG List: + + WG Chair: Bert Wijnen + + + WG Chair: Mehmet Ersue + + + Editor: Martin Bjorklund + + + Editor: Juergen Schoenwaelder + + + Editor: Andy Bierman + "; + + description + "NETCONF Protocol Data Types and Protocol Operations. + + Copyright (c) 2011 IETF Trust and the persons identified as + the document authors. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 6241; see + the RFC itself for full legal notices."; + revision 2011-06-01 { + description + "Initial revision"; + reference + "RFC 6241: Network Configuration Protocol"; + } + + extension get-filter-element-attributes { + description + "If this extension is present within an 'anyxml' + statement named 'filter', which must be conceptually + defined within the RPC input section for the + and protocol operations, then the + following unqualified XML attribute is supported + within the element, within a or + protocol operation: + + type : optional attribute with allowed + value strings 'subtree' and 'xpath'. + If missing, the default value is 'subtree'. + + If the 'xpath' feature is supported, then the + following unqualified XML attribute is + also supported: + + select: optional attribute containing a + string representing an XPath expression. + The 'type' attribute must be equal to 'xpath' + if this attribute is present."; + } + + // NETCONF capabilities defined as features + feature writable-running { + description + "NETCONF :writable-running capability; + If the server advertises the :writable-running + capability for a session, then this feature must + also be enabled for that session. Otherwise, + this feature must not be enabled."; + reference "RFC 6241, Section 8.2"; + } + + feature candidate { + description + "NETCONF :candidate capability; + If the server advertises the :candidate + capability for a session, then this feature must + also be enabled for that session. Otherwise, + this feature must not be enabled."; + reference "RFC 6241, Section 8.3"; + } + + feature confirmed-commit { + if-feature candidate; + description + "NETCONF :confirmed-commit:1.1 capability; + If the server advertises the :confirmed-commit:1.1 + capability for a session, then this feature must + also be enabled for that session. Otherwise, + this feature must not be enabled."; + + reference "RFC 6241, Section 8.4"; + } + + feature rollback-on-error { + description + "NETCONF :rollback-on-error capability; + If the server advertises the :rollback-on-error + capability for a session, then this feature must + also be enabled for that session. Otherwise, + this feature must not be enabled."; + reference "RFC 6241, Section 8.5"; + } + + feature validate { + description + "NETCONF :validate:1.1 capability; + If the server advertises the :validate:1.1 + capability for a session, then this feature must + also be enabled for that session. Otherwise, + this feature must not be enabled."; + reference "RFC 6241, Section 8.6"; + } + + feature startup { + description + "NETCONF :startup capability; + If the server advertises the :startup + capability for a session, then this feature must + also be enabled for that session. Otherwise, + this feature must not be enabled."; + reference "RFC 6241, Section 8.7"; + } + + feature url { + description + "NETCONF :url capability; + If the server advertises the :url + capability for a session, then this feature must + also be enabled for that session. Otherwise, + this feature must not be enabled."; + reference "RFC 6241, Section 8.8"; + } + + feature xpath { + description + "NETCONF :xpath capability; + If the server advertises the :xpath + capability for a session, then this feature must + also be enabled for that session. Otherwise, + this feature must not be enabled."; + reference "RFC 6241, Section 8.9"; + } + + // NETCONF Simple Types + + typedef session-id-type { + type uint32 { + range "1..max"; + } + description + "NETCONF Session Id"; + } + + typedef session-id-or-zero-type { + type uint32; + description + "NETCONF Session Id or Zero to indicate none"; + } + typedef error-tag-type { + type enumeration { + enum in-use { + description + "The request requires a resource that + already is in use."; + } + enum invalid-value { + description + "The request specifies an unacceptable value for one + or more parameters."; + } + enum too-big { + description + "The request or response (that would be generated) is + too large for the implementation to handle."; + } + enum missing-attribute { + description + "An expected attribute is missing."; + } + enum bad-attribute { + description + "An attribute value is not correct; e.g., wrong type, + out of range, pattern mismatch."; + } + enum unknown-attribute { + description + "An unexpected attribute is present."; + } + enum missing-element { + description + "An expected element is missing."; + } + enum bad-element { + description + "An element value is not correct; e.g., wrong type, + out of range, pattern mismatch."; + } + enum unknown-element { + description + "An unexpected element is present."; + } + enum unknown-namespace { + description + "An unexpected namespace is present."; + } + enum access-denied { + description + "Access to the requested protocol operation or + data model is denied because authorization failed."; + } + enum lock-denied { + description + "Access to the requested lock is denied because the + lock is currently held by another entity."; + } + enum resource-denied { + description + "Request could not be completed because of + insufficient resources."; + } + enum rollback-failed { + description + "Request to roll back some configuration change (via + rollback-on-error or operations) + was not completed for some reason."; + + } + enum data-exists { + description + "Request could not be completed because the relevant + data model content already exists. For example, + a 'create' operation was attempted on data that + already exists."; + } + enum data-missing { + description + "Request could not be completed because the relevant + data model content does not exist. For example, + a 'delete' operation was attempted on + data that does not exist."; + } + enum operation-not-supported { + description + "Request could not be completed because the requested + operation is not supported by this implementation."; + } + enum operation-failed { + description + "Request could not be completed because the requested + operation failed for some reason not covered by + any other error condition."; + } + enum partial-operation { + description + "This error-tag is obsolete, and SHOULD NOT be sent + by servers conforming to this document."; + } + enum malformed-message { + description + "A message could not be handled because it failed to + be parsed correctly. For example, the message is not + well-formed XML or it uses an invalid character set."; + } + } + description "NETCONF Error Tag"; + reference "RFC 6241, Appendix A"; + } + + typedef error-severity-type { + type enumeration { + enum error { + description "Error severity"; + } + enum warning { + description "Warning severity"; + } + } + description "NETCONF Error Severity"; + reference "RFC 6241, Section 4.3"; + } + + typedef edit-operation-type { + type enumeration { + enum merge { + description + "The configuration data identified by the + element containing this attribute is merged + with the configuration at the corresponding + level in the configuration datastore identified + by the target parameter."; + } + enum replace { + description + "The configuration data identified by the element + containing this attribute replaces any related + configuration in the configuration datastore + identified by the target parameter. If no such + configuration data exists in the configuration + datastore, it is created. Unlike a + operation, which replaces the + entire target configuration, only the configuration + actually present in the config parameter is affected."; + } + enum create { + description + "The configuration data identified by the element + containing this attribute is added to the + configuration if and only if the configuration + data does not already exist in the configuration + datastore. If the configuration data exists, an + element is returned with an + value of 'data-exists'."; + } + enum delete { + description + "The configuration data identified by the element + containing this attribute is deleted from the + configuration if and only if the configuration + data currently exists in the configuration + datastore. If the configuration data does not + exist, an element is returned with + an value of 'data-missing'."; + } + enum remove { + description + "The configuration data identified by the element + containing this attribute is deleted from the + configuration if the configuration + data currently exists in the configuration + datastore. If the configuration data does not + exist, the 'remove' operation is silently ignored + by the server."; + } + } + default "merge"; + description "NETCONF 'operation' attribute values"; + reference "RFC 6241, Section 7.2"; + } + + // NETCONF Standard Protocol Operations + + rpc get-config { + description + "Retrieve all or part of a specified configuration."; + + reference "RFC 6241, Section 7.1"; + + input { + container source { + description + "Particular configuration to retrieve."; + + choice config-source { + mandatory true; + description + "The configuration to retrieve."; + leaf candidate { + if-feature candidate; + type empty; + description + "The candidate configuration is the config source."; + } + leaf running { + type empty; + description + "The running configuration is the config source."; + } + leaf startup { + if-feature startup; + type empty; + description + "The startup configuration is the config source. + This is optional-to-implement on the server because + not all servers will support filtering for this + datastore."; + } + } + } + + anyxml filter { + description + "Subtree or XPath filter to use."; + nc:get-filter-element-attributes; + } + } + + output { + anyxml data { + description + "Copy of the source datastore subset that matched + the filter criteria (if any). An empty data container + indicates that the request did not produce any results."; + } + } + } + + rpc edit-config { + description + "The operation loads all or part of a specified + configuration to the specified target configuration."; + + reference "RFC 6241, Section 7.2"; + + input { + container target { + description + "Particular configuration to edit."; + + choice config-target { + mandatory true; + description + "The configuration target."; + + leaf candidate { + if-feature candidate; + type empty; + description + "The candidate configuration is the config target."; + } + leaf running { + if-feature writable-running; + type empty; + description + "The running configuration is the config source."; + } + } + } + + leaf default-operation { + type enumeration { + enum merge { + description + "The default operation is merge."; + } + enum replace { + description + "The default operation is replace."; + } + enum none { + description + "There is no default operation."; + } + } + default "merge"; + description + "The default operation to use."; + } + + leaf test-option { + if-feature validate; + type enumeration { + enum test-then-set { + description + "The server will test and then set if no errors."; + } + enum set { + description + "The server will set without a test first."; + } + + enum test-only { + description + "The server will only test and not set, even + if there are no errors."; + } + } + default "test-then-set"; + description + "The test option to use."; + } + + leaf error-option { + type enumeration { + enum stop-on-error { + description + "The server will stop on errors."; + } + enum continue-on-error { + description + "The server may continue on errors."; + } + enum rollback-on-error { + description + "The server will roll back on errors. + This value can only be used if the 'rollback-on-error' + feature is supported."; + } + } + default "stop-on-error"; + description + "The error option to use."; + } + + choice edit-content { + mandatory true; + description + "The content for the edit operation."; + + anyxml config { + description + "Inline Config content."; + } + leaf url { + if-feature url; + type inet:uri; + description + "URL-based config content."; + } + } + } + } + + rpc copy-config { + description + "Create or replace an entire configuration datastore with the + contents of another complete configuration datastore."; + + reference "RFC 6241, Section 7.3"; + + input { + container target { + description + "Particular configuration to copy to."; + + choice config-target { + mandatory true; + description + "The configuration target of the copy operation."; + + leaf candidate { + if-feature candidate; + type empty; + description + "The candidate configuration is the config target."; + } + leaf running { + if-feature writable-running; + type empty; + description + "The running configuration is the config target. + This is optional-to-implement on the server."; + } + leaf startup { + if-feature startup; + type empty; + description + "The startup configuration is the config target."; + } + leaf url { + if-feature url; + type inet:uri; + description + "The URL-based configuration is the config target."; + } + } + } + + container source { + description + "Particular configuration to copy from."; + + choice config-source { + mandatory true; + description + "The configuration source for the copy operation."; + + leaf candidate { + if-feature candidate; + type empty; + description + "The candidate configuration is the config source."; + } + leaf running { + type empty; + description + "The running configuration is the config source."; + } + leaf startup { + if-feature startup; + type empty; + description + "The startup configuration is the config source."; + } + leaf url { + if-feature url; + type inet:uri; + description + "The URL-based configuration is the config source."; + } + anyxml config { + description + "Inline Config content: element. Represents + an entire configuration datastore, not + a subset of the running datastore."; + } + } + } + } + } + + rpc delete-config { + description + "Delete a configuration datastore."; + + reference "RFC 6241, Section 7.4"; + + input { + container target { + description + "Particular configuration to delete."; + + choice config-target { + mandatory true; + description + "The configuration target to delete."; + + leaf startup { + if-feature startup; + type empty; + description + "The startup configuration is the config target."; + } + leaf url { + if-feature url; + type inet:uri; + description + "The URL-based configuration is the config target."; + } + } + } + } + } + + rpc lock { + description + "The lock operation allows the client to lock the configuration + system of a device."; + reference "RFC 6241, Section 7.5"; + + input { + container target { + description + "Particular configuration to lock."; + + choice config-target { + mandatory true; + description + "The configuration target to lock."; + + leaf candidate { + if-feature candidate; + type empty; + description + "The candidate configuration is the config target."; + } + leaf running { + type empty; + description + "The running configuration is the config target."; + } + leaf startup { + if-feature startup; + type empty; + description + "The startup configuration is the config target."; + } + } + } + } + } + + rpc unlock { + description + "The unlock operation is used to release a configuration lock, + previously obtained with the 'lock' operation."; + + reference "RFC 6241, Section 7.6"; + + input { + container target { + description + "Particular configuration to unlock."; + + choice config-target { + mandatory true; + description + "The configuration target to unlock."; + + leaf candidate { + if-feature candidate; + type empty; + description + "The candidate configuration is the config target."; + } + leaf running { + type empty; + description + "The running configuration is the config target."; + } + leaf startup { + if-feature startup; + type empty; + description + "The startup configuration is the config target."; + } + } + } + } + } + + rpc get { + description + "Retrieve running configuration and device state information."; + + reference "RFC 6241, Section 7.7"; + + input { + anyxml filter { + description + "This parameter specifies the portion of the system + configuration and state data to retrieve."; + nc:get-filter-element-attributes; + } + } + + output { + anyxml data { + description + "Copy of the running datastore subset and/or state + data that matched the filter criteria (if any). + An empty data container indicates that the request did not + produce any results."; + } + } + } + + rpc close-session { + description + "Request graceful termination of a NETCONF session."; + + reference "RFC 6241, Section 7.8"; + } + + rpc kill-session { + description + "Force the termination of a NETCONF session."; + + reference "RFC 6241, Section 7.9"; + + input { + leaf session-id { + type session-id-type; + mandatory true; + description + "Particular session to kill."; + } + } + } + + rpc commit { + if-feature candidate; + + description + "Commit the candidate configuration as the device's new + current configuration."; + + reference "RFC 6241, Section 8.3.4.1"; + + input { + leaf confirmed { + if-feature confirmed-commit; + type empty; + description + "Requests a confirmed commit."; + reference "RFC 6241, Section 8.3.4.1"; + } + + leaf confirm-timeout { + if-feature confirmed-commit; + type uint32 { + range "1..max"; + } + units "seconds"; + default "600"; // 10 minutes + description + "The timeout interval for a confirmed commit."; + reference "RFC 6241, Section 8.3.4.1"; + } + + leaf persist { + if-feature confirmed-commit; + type string; + description + "This parameter is used to make a confirmed commit + persistent. A persistent confirmed commit is not aborted + if the NETCONF session terminates. The only way to abort + a persistent confirmed commit is to let the timer expire, + or to use the operation. + + The value of this parameter is a token that must be given + in the 'persist-id' parameter of or + operations in order to confirm or cancel + the persistent confirmed commit. + + The token should be a random string."; + reference "RFC 6241, Section 8.3.4.1"; + } + + leaf persist-id { + if-feature confirmed-commit; + type string; + description + "This parameter is given in order to commit a persistent + confirmed commit. The value must be equal to the value + given in the 'persist' parameter to the operation. + If it does not match, the operation fails with an + 'invalid-value' error."; + reference "RFC 6241, Section 8.3.4.1"; + } + + } + } + + rpc discard-changes { + if-feature candidate; + + description + "Revert the candidate configuration to the current + running configuration."; + reference "RFC 6241, Section 8.3.4.2"; + } + + rpc cancel-commit { + if-feature confirmed-commit; + description + "This operation is used to 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."; + reference "RFC 6241, Section 8.4.4.1"; + + input { + leaf persist-id { + type string; + description + "This parameter is given in order to cancel a persistent + confirmed commit. The value must be equal to the value + given in the 'persist' parameter to the operation. + If it does not match, the operation fails with an + 'invalid-value' error."; + } + } + } + + rpc validate { + if-feature validate; + + description + "Validates the contents of the specified configuration."; + + reference "RFC 6241, Section 8.6.4.1"; + + input { + container source { + description + "Particular configuration to validate."; + + choice config-source { + mandatory true; + description + "The configuration source to validate."; + + leaf candidate { + if-feature candidate; + type empty; + description + "The candidate configuration is the config source."; + } + leaf running { + type empty; + description + "The running configuration is the config source."; + } + leaf startup { + if-feature startup; + type empty; + description + "The startup configuration is the config source."; + } + leaf url { + if-feature url; + type inet:uri; + description + "The URL-based configuration is the config source."; + } + anyxml config { + description + "Inline Config content: element. Represents + an entire configuration datastore, not + a subset of the running datastore."; + } + } + } + } + } +}