Beispiel #1
0
def v_chk_path_refs(ctx, statement):
  """
    Check path references for absolute / relative paths as appropriate.
    This function is called with the following statements:
      * path
      * augment
  """
  path = statement.arg
  if path[0] == '/':
    abspath = True
  else:
    abspath = False
  components = yangpath.split_paths(path)
  # consider the namespace in the first component
  # assumes that if the namespace matches the module namespace, then
  # relative path should be used (intra-module )
  if ":" in components[0]:
    (namespace, barepath) = components[0].split(':')
  else:
    namespace = statement.i_module.i_prefix
    barepath = components[0]
  mod_prefix = statement.i_module.i_prefix
  if namespace == mod_prefix and abspath:
    err_add(ctx.errors, statement.pos, 'OC_RELATIVE_PATH',
      (statement.keyword, statement.arg))
Beispiel #2
0
def v_chk_required_substmt(ctx, stmt):
    if stmt.keyword in _required_substatements:
        (required, s) = _required_substatements[stmt.keyword]
        for r in required:
            if stmt.search_one(r) is None:
                err_add(ctx.errors, stmt.pos, 'IETF_MISSING_REQUIRED_SUBSTMT',
                        (s, stmt.keyword, r))
Beispiel #3
0
Datei: lint.py Projekt: SDTN/Test
def v_chk_namespace(ctx, stmt, namespace_prefixes):
    if namespace_prefixes != []:
        for prefix in namespace_prefixes:
            if stmt.arg == prefix + stmt.i_module.arg:
                return
        err_add(ctx.errors, stmt.pos, 'LINT_BAD_NAMESPACE_VALUE',
                namespace_prefixes[0] + stmt.i_module.arg)
Beispiel #4
0
def chk_revision(oldmod, newmod, ctx):
    oldrev = get_latest_revision(oldmod)
    newrev = get_latest_revision(newmod)
    if newrev is None:
        err_add(ctx.errors, newmod.pos, 'CHK_NO_REVISION', ())
    elif (oldrev is not None) and (oldrev >= newrev):
        err_add(ctx.errors, newmod.pos, 'CHK_BAD_REVISION', (newrev, oldrev))
Beispiel #5
0
def chk_children(oldch, newchs, newp, ctx):
    newch = None
    for ch in newchs:
        if ch.arg == oldch.arg:
            newch = ch
            break
    if newch is None:
        err_def_removed(oldch, newp, ctx)
        return

    if newch.keyword != oldch.keyword:
        err_add(ctx.errors, newch.pos, 'CHK_CHILD_KEYWORD_CHANGED',
                (oldch.keyword, newch.arg, newch.keyword))
        return
    chk_status(oldch, newch, ctx)
    chk_if_feature(oldch, newch, ctx)
    chk_config(oldch, newch, ctx)
    chk_must(oldch, newch, ctx)
    chk_when(oldch, newch, ctx)
    if newch.keyword == 'leaf':
        chk_leaf(oldch, newch, ctx)
    elif newch.keyword == 'leaf-list':
        chk_leaf_list(oldch, newch, ctx)
    elif newch.keyword == 'container':
        chk_container(oldch, newch, ctx)
    elif newch.keyword == 'list':
        chk_list(oldch, newch, ctx)
    elif newch.keyword == 'choice':
        chk_choice(oldch, newch, ctx)
    elif newch.keyword == 'case':
        chk_case(oldch, newch, ctx)
    elif newch.keyword == 'input':
        chk_input_output(oldch, newch, ctx)
    elif newch.keyword == 'output':
        chk_input_output(oldch, newch, ctx)
Beispiel #6
0
def chk_i_children(old, new, ctx):
    for oldch in old.i_children:
        chk_child(oldch, new, ctx)
    # chk_child removes all old children
    for newch in new.i_children:
        if statements.is_mandatory_node(newch):
            err_add(ctx.errors, newch.pos, 'CHK_NEW_MANDATORY', newch.arg)
Beispiel #7
0
def chk_children(oldch, newchs, newp, ctx):
    newch = None
    for ch in newchs:
        if ch.arg == oldch.arg:
            newch = ch
            break
    if newch is None:
        err_def_removed(oldch, newp, ctx)
        return
    newchs.remove(newch)
    if newch.keyword != oldch.keyword:
        err_add(ctx.errors, newch.pos, 'CHK_CHILD_KEYWORD_CHANGED',
                (oldch.keyword, newch.arg, newch.keyword))
        return
    chk_status(oldch, newch, ctx)
    chk_if_feature(oldch, newch, ctx)
    chk_config(oldch, newch, ctx)
    chk_must(oldch, newch, ctx)
    chk_when(oldch, newch, ctx)
    if newch.keyword == 'leaf':
        chk_leaf(oldch, newch, ctx)
    elif newch.keyword == 'leaf-list':
        chk_leaf_list(oldch, newch, ctx)
    elif newch.keyword == 'container':
        chk_container(oldch, newch, ctx)
    elif newch.keyword == 'list':
        chk_list(oldch, newch, ctx)
    elif newch.keyword == 'choice':
        chk_choice(oldch, newch, ctx)
    elif newch.keyword == 'case':
        chk_case(oldch, newch, ctx)
    elif newch.keyword == 'input':
        chk_input_output(oldch, newch, ctx)
    elif newch.keyword == 'output':
        chk_input_output(oldch, newch, ctx)
Beispiel #8
0
def chk_revision(oldmod, newmod, ctx):
    oldrev = get_latest_revision(oldmod)
    newrev = get_latest_revision(newmod)
    if newrev is None:
        err_add(ctx.errors, newmod.pos, 'CHK_NO_REVISION', ())
    elif (oldrev is not None) and (oldrev >= newrev):
        err_add(ctx.errors, newmod.pos, 'CHK_BAD_REVISION', (newrev, oldrev))
Beispiel #9
0
def v_chk_namespace(ctx, stmt, namespace_prefixes):
    if namespace_prefixes != []:
        for prefix in namespace_prefixes:
            if stmt.arg == prefix + stmt.i_module.arg:
                return
        err_add(ctx.errors, stmt.pos, 'LINT_BAD_NAMESPACE_VALUE',
                namespace_prefixes[0] + stmt.i_module.arg)
Beispiel #10
0
def chk_i_children(old, new, ctx):
    for oldch in old.i_children:
        chk_child(oldch, new, ctx)
    # chk_child removes all old children
    for newch in new.i_children:
        if statements.is_mandatory_node(newch):
            err_add(ctx.errors, newch.pos, 'CHK_NEW_MANDATORY', newch.arg)
def v_chk_recommended_substmt(ctx, stmt):
    if stmt.keyword in _recommended_substatements:
        for r in _recommended_substatements[stmt.keyword]:
            if stmt.search_one(r) is None:
                err_add(ctx.errors, stmt.pos,
                        'IETF_MISSING_RECOMMENDED_SUBSTMT',
                        (stmt.keyword, r))
Beispiel #12
0
def v_chk_leaf_mirroring(ctx, statement):
  """
    Check that all config leaves are included in the state container
  """

  # Skip the check if the container is not a parent of other containers
  if statement.search_one('container') is None:
    return

  containers = statement.search('container')
  # Only perform this check if this is a container that has both a config
  # and state container
  c_config, c_state = None, None
  for c in containers:
    if c.arg == 'config':
      c_config = c
    elif c.arg == 'state':
      c_state = c
    if not None in [c_config, c_state]:
      break

  if None in [c_config, c_state]:
    return

  config_elem_names = [i.arg for i in c_config.substmts
                          if not i.arg == 'config' and
                            i.keyword in INSTANTIATED_DATA_KEYWORDS]
  state_elem_names = [i.arg for i in c_state.substmts
                          if not i.arg == 'state' and
                            i.keyword in INSTANTIATED_DATA_KEYWORDS]

  for elem in config_elem_names:
    if not elem in state_elem_names:
      err_add(ctx.errors, statement.parent.pos, 'OC_OPSTATE_APPLIED_CONFIG',
        (elem, statements.mk_path_str(statement, False)))
Beispiel #13
0
 def post_validate_ctx(self, ctx, modules):
     if not ctx.opts.ietf:
         return
     for mod in modules:
         if (self.mmap[mod.arg]['found_2119_keywords']
             and not self.mmap[mod.arg]['found_8174']):
             pos = self.mmap[mod.arg]['description_pos']
             err_add(ctx.errors, pos, 'IETF_MISSING_RFC8174', ())
Beispiel #14
0
def v_chk_recommended_substmt(ctx, stmt):
    if stmt.keyword in _recommended_substatements:
        (recommended, s) = _recommended_substatements[stmt.keyword]
        for r in recommended:
            if stmt.search_one(r) is None:
                err_add(ctx.errors, stmt.pos,
                        'LINT_MISSING_RECOMMENDED_SUBSTMT',
                        (s, stmt.keyword, r))
Beispiel #15
0
 def cmp_node(optr, nptr):
     if optr.parent is None:
         return
     if (optr.i_module.i_modulename == nptr.i_module.i_modulename and
         optr.arg == nptr.arg):
         return cmp_node(optr.parent, nptr.parent)
     else:
         err_add(ctx.errors, new.pos, 'CHK_LEAFREF_PATH_CHANGED', ())
Beispiel #16
0
def v_chk_required_substmt(ctx, stmt):
    if stmt.keyword in _required_substatements:
        (required, s) = _required_substatements[stmt.keyword]
        for r in required:
            if stmt.search_one(r) is None:
                err_add(ctx.errors, stmt.pos,
                        'IETF_MISSING_REQUIRED_SUBSTMT',
                        (s, stmt.keyword, r))
Beispiel #17
0
 def v_chk_prefix(self, ctx, stmt):
     if stmt.parent.keyword != 'module':
         return
     r = '.+3gpp$'
     if re.match(r, stmt.arg) is None:
         err_add(ctx.errors, stmt.pos, '3GPP_BAD_PREFIX_VALUE', ())
     if len(stmt.arg) > 13:
         err_add(ctx.errors, stmt.pos, '3GPP_TOO_LONG_PREFIX', ())
Beispiel #18
0
 def cmp_node(optr, nptr):
     if optr.parent is None:
         return
     if (optr.i_module.i_modulename == nptr.i_module.i_modulename and
         optr.arg == nptr.arg):
         return cmp_node(optr.parent, nptr.parent)
     else:
         err_add(ctx.errors, new.pos, 'CHK_LEAFREF_PATH_CHANGED', ())
Beispiel #19
0
def chk_range(old, new, oldts, newts, ctx):
    ots = old.i_type_spec
    nts = new.i_type_spec
    if (type(ots) == types.RangeTypeSpec and type(nts) == types.RangeTypeSpec):
        tmperrors = []
        types.validate_ranges(tmperrors, new.pos, ots.ranges, new)
        if tmperrors != []:
            err_add(ctx.errors, new.pos, 'CHK_RESTRICTION_CHANGED', 'range')
Beispiel #20
0
def chk_i_children(old, new, ctx):
    for oldch in old.i_children:
        chk_child(oldch, new, ctx)

    old_child_args = [oldch.arg for oldch in old.i_children]
    added_new_children = [new_child for new_child in new.i_children if new_child.arg not in old_child_args]
    for newch in added_new_children:
        if statements.is_mandatory_node(newch):
            err_add(ctx.errors, newch.pos, 'CHK_NEW_MANDATORY', newch.arg)
Beispiel #21
0
def chk_decimal64(old, new, oldts, newts, ctx):
    oldbasets = get_base_type(oldts)
    newbasets = get_base_type(newts)
    if newbasets.fraction_digits != oldbasets.fraction_digits:
        err_add(ctx.errors, new.pos, 'CHK_DEF_CHANGED',
                ('fraction-digits', newts.fraction_digits,
                 oldts.fraction_digits))
    # a decimal64 can only be restricted with range
    chk_range(old, new, oldts, newts, ctx)
Beispiel #22
0
def chk_decimal64(old, new, oldts, newts, ctx):
    oldbasets = get_base_type(oldts)
    newbasets = get_base_type(newts)
    if newbasets.fraction_digits != oldbasets.fraction_digits:
        err_add(ctx.errors, new.pos, 'CHK_DEF_CHANGED',
                ('fraction-digits', newts.fraction_digits,
                 oldts.fraction_digits))
    # a decimal64 can only be restricted with range
    chk_range(old, new, oldts, newts, ctx)
Beispiel #23
0
def v_unused_complex_type(ctx, stmt):
    """Adds warnings for complex types which are defined not
    at the top-level of the module and unused
    """
    if stmt.parent.parent is not None:
        # this is a locally scoped complex type
        if stmt.i_is_unused == True:
            err_add(ctx.errors, stmt.pos,
                    'UNUSED_COMPLEX_TYPE', stmt.arg)
Beispiel #24
0
def chk_enumeration(old, new, oldts, newts, ctx):
    # verify that all old enums are still in new, with the same values
    for (name, val) in oldts.enums:
        n = util.keysearch(name, 0, newts.enums)
        if n is None:
            err_add(ctx.errors, new.pos, 'CHK_DEF_REMOVED',
                    ('enum', name, old.pos))
        elif n[1] != val:
            err_add(ctx.errors, new.pos, 'CHK_ENUM_VALUE_CHANGED',
                    (name, val, n[1]))
Beispiel #25
0
def chk_bits(old, new, oldts, newts, ctx):
    # verify that all old bits are still in new, with the same positions
    for (name, pos) in oldts.bits:
        n = util.keysearch(name, 0, newts.bits)
        if n is None:
            err_add(ctx.errors, new.pos, 'CHK_DEF_REMOVED',
                    ('bit', name, old.pos))
        elif n[1] != pos:
            err_add(ctx.errors, new.pos, 'CHK_BIT_POSITION_CHANGED',
                    (name, pos, n[1]))
Beispiel #26
0
def chk_range(old, new, oldts, newts, ctx):
    ots = old.i_type_spec
    nts = new.i_type_spec
    if (type(ots) == types.RangeTypeSpec and
        type(nts) == types.RangeTypeSpec):
        tmperrors = []
        types.validate_ranges(tmperrors, new.pos, ots.ranges, new)
        if tmperrors != []:
            err_add(ctx.errors, new.pos, 'CHK_RESTRICTION_CHANGED',
                    'range')
Beispiel #27
0
def chk_enumeration(old, new, oldts, newts, ctx):
    # verify that all old enums are still in new, with the same values
    for (name, val) in oldts.enums:
        n = util.keysearch(name, 0, newts.enums)
        if n is None:
            err_add(ctx.errors, new.pos, 'CHK_DEF_REMOVED',
                    ('enum', name, old.pos))
        elif n[1] != val:
            err_add(ctx.errors, new.pos, 'CHK_ENUM_VALUE_CHANGED',
                    (name, val, n[1]))
Beispiel #28
0
def chk_bits(old, new, oldts, newts, ctx):
    # verify that all old bits are still in new, with the same positions
    for (name, pos) in oldts.bits:
        n = util.keysearch(name, 0, newts.bits)
        if n is None:
            err_add(ctx.errors, new.pos, 'CHK_DEF_REMOVED',
                    ('bit', name, old.pos))
        elif n[1] != pos:
            err_add(ctx.errors, new.pos, 'CHK_BIT_POSITION_CHANGED',
                    (name, pos, n[1]))
Beispiel #29
0
def v_chk_module_name(ctx, stmt, modulename_prefixes):
    if modulename_prefixes != []:
        for prefix in modulename_prefixes:
            if stmt.arg.find(prefix + '-') == 0:
                return
        err_add(ctx.errors, stmt.pos, 'LINT_BAD_MODULENAME_PREFIX',
                (modulename_prefixes[0], stmt.arg))
    elif stmt.arg.find('-') == -1:
        # can't check much, but we can check that a prefix is used
        err_add(ctx.errors, stmt.pos, 'LINT_NO_MODULENAME_PREFIX', ())
Beispiel #30
0
def v_chk_module_name(ctx, stmt, modulename_prefixes):
    if modulename_prefixes != []:
        for prefix in modulename_prefixes:
            if stmt.arg.find(prefix + '-') == 0:
                return
        err_add(ctx.errors, stmt.pos, 'LINT_BAD_MODULENAME_PREFIX',
                (modulename_prefixes[0], stmt.arg))
    elif stmt.arg.find('-') == -1:
        # can't check much, but we can check that a prefix is used
        err_add(ctx.errors, stmt.pos, 'LINT_NO_MODULENAME_PREFIX', ())
Beispiel #31
0
def chk_presence(old, new, ctx):
    oldpresence = old.search_one('presence')
    newpresence = new.search_one('presence')
    if oldpresence is None and newpresence is None:
        pass
    elif oldpresence is None and newpresence is not None:
        err_def_added(newpresence, ctx)
    elif oldpresence is not None and newpresence is None:
        err_def_removed(oldpresence, new, ctx)
    elif oldpresence.arg != newpresence.arg:
        err_add(ctx.errors, newpresence.pos, 'CHK_UNDECIDED_PRESENCE', ())
Beispiel #32
0
def v_type_abstract(ctx, stmt):
    """ Check the base complex type, if present, is also abstract."""
    if (stmt.arg == 'true'):
        stmt.parent.i_is_abstract = True
        # check whether the complex type extends another one
        if stmt.parent.i_base_type is not None:
            if not stmt.parent.i_base_type.i_is_abstract:
                err_add(ctx.errors, stmt.pos, 'ABSTRACT_NOT_ALLOWED',
                    (stmt.parent.i_base_type.arg, stmt.parent.arg))
    else:
        stmt.parent.i_is_abstract = False                
Beispiel #33
0
def validate_complex_type(ctx, stmt):
    """Validates a reffered complex type."""
    if stmt.i_complex_type is None:
        err_add(ctx.errors, stmt.pos,
                'COMPLEX_TYPE_NOT_FOUND', (stmt.arg, stmt.i_module.arg))
        return
    else:
        # ensure the complex type is validated
        if stmt.i_complex_type.is_grammatically_valid == True:
            v_type_complex_type(ctx, stmt.i_complex_type)
        stmt.i_complex_type.i_is_unused = False
Beispiel #34
0
def chk_identityref(old, new, oldts, newts, ctx):
    # verify that the bases are the same
    extra = [n for n in newts.idbases]
    for oidbase in oldts.idbases:
        for nidbase in newts.idbases:
            if (nidbase.i_module.i_modulename == oidbase.i_module.i_modulename
                    and nidbase.arg.split(':')[-1]
                    == oidbase.arg.split(':')[-1]):
                extra.remove(nidbase)
    for n in extra:
        err_add(ctx.errors, n.pos, 'CHK_DEF_ADDED', ('base', n.arg))
Beispiel #35
0
def chk_presence(old, new, ctx):
    oldpresence = old.search_one('presence')
    newpresence = new.search_one('presence')
    if oldpresence is None and newpresence is None:
        pass
    elif oldpresence is None and newpresence is not None:
        err_def_added(newpresence, ctx)
    elif oldpresence is not None and newpresence is None:
        err_def_removed(oldpresence, new, ctx)
    elif oldpresence.arg != newpresence.arg:
        err_add(ctx.errors, newpresence.pos, 'CHK_UNDECIDED_PRESENCE', ())
Beispiel #36
0
  def check_top_level_data_definitions(ctx, stmt):
    """Check that the module has no data elements at the root.

    Args:
      ctx: pyang.Context for the validation
      stmt: pyang.Statement for the matching module
    """
    data_definitions = [i.arg for i in stmt.substmts if i.keyword
                        in INSTANTIATED_DATA_KEYWORDS]
    if data_definitions:
      err_add(ctx.errors, stmt.pos, "OC_MODULE_DATA_DEFINITIONS",
              (stmt.arg, ", ".join(data_definitions)))
Beispiel #37
0
def chk_identityref(old, new, oldts, newts, ctx):
    # verify that the bases are the same
    extra = [n for n in newts.idbases]
    for oidbase in oldts.idbases:
        for nidbase in newts.idbases:
            if (nidbase.i_module.i_modulename ==
                    oidbase.i_module.i_modulename and
                    nidbase.arg.split(':')[-1] == oidbase.arg.split(':')[-1]):
                extra.remove(nidbase)
    for n in extra:
        err_add(ctx.errors, n.pos, 'CHK_DEF_ADDED',
                ('base', n.arg))
Beispiel #38
0
  def check_top_level_data_definitions(ctx, stmt):
    """Check that the module has no data elements at the root.

    Args:
      ctx: pyang.Context for the validation
      stmt: pyang.Statement for the matching module
    """
    data_definitions = [i.arg for i in stmt.substmts if i.keyword
                        in INSTANTIATED_DATA_KEYWORDS]
    if data_definitions:
      err_add(ctx.errors, stmt.pos, "OC_MODULE_DATA_DEFINITIONS",
              (stmt.arg, ", ".join(data_definitions)))
Beispiel #39
0
def chk_status(old, new, ctx):
    oldstatus = old.search_one('status')
    newstatus = new.search_one('status')
    if oldstatus is None or oldstatus.arg == 'current':
        # any new status is ok
        return
    if newstatus is None:
        err_add(ctx.errors, new.pos, 'CHK_INVALID_STATUS',
                ("(implicit) current", oldstatus.arg))
    elif ((newstatus.arg == 'current') or
          (oldstatus.arg == 'obsolete' and newstatus.arg != 'obsolete')):
        err_add(ctx.errors, newstatus.pos, 'CHK_INVALID_STATUS',
                (newstatus.arg, oldstatus.arg))
Beispiel #40
0
def v_chk_include(ctx, stmt):
    latest = stmt.i_orig_module.i_latest_revision
    if latest is None:
        return
    submodulename = stmt.arg
    r = stmt.search_one("revision-date")
    if r is not None:
        rev = r.arg
    else:
        rev = None
    subm = ctx.get_module(submodulename, rev)
    if subm is not None and subm.i_latest_revision is not None and subm.i_latest_revision > latest:
        err_add(ctx.errors, stmt.pos, "LINT_BAD_REVISION", (latest, submodulename, subm.i_latest_revision))
Beispiel #41
0
def chk_status(old, new, ctx):
    oldstatus = old.search_one('status')
    newstatus = new.search_one('status')
    if oldstatus is None or oldstatus.arg == 'current':
        # any new status is ok
        return
    if newstatus is None:
        err_add(ctx.errors, new.pos, 'CHK_INVALID_STATUS',
                ("(implicit) current", oldstatus.arg))
    elif ((newstatus.arg == 'current') or
          (oldstatus.arg == 'obsolete' and newstatus.arg != 'obsolete')):
        err_add(ctx.errors, newstatus.pos, 'CHK_INVALID_STATUS',
                (newstatus.arg, oldstatus.arg))
Beispiel #42
0
    def check_bad_types(ctx, stmt):
        """Check validation rules for bad types that should not
    be used in OpenConfig models.

    Args:
      ctx: pyang.Context for validation
      stmt: pyang.Statement representing a leaf or leaf-list
    """
        elemtype = stmt.search_one("type")
        if elemtype is None or elemtype.arg not in BAD_TYPES:
            return

        err_add(ctx.errors, stmt.pos, "OC_BAD_TYPE", (elemtype.arg))
Beispiel #43
0
def chk_range(old, new, oldts, newts, ctx):
    ots = old.i_type_spec
    nts = new.i_type_spec
    if not isinstance(nts, types.RangeTypeSpec):
        return
    if isinstance(ots, types.RangeTypeSpec):
        tmperrors = []
        types.validate_ranges(tmperrors, new.pos, ots.ranges, new)
        if tmperrors:
            err_add(ctx.errors, new.pos, 'CHK_RESTRICTION_CHANGED', 'range')
    else:
        err_add(ctx.errors, nts.ranges_pos, 'CHK_DEF_ADDED',
                ('range', str(nts.ranges)))
Beispiel #44
0
def v_chk_opstate_paths(ctx, statement):
  """
    Check elements for compliance with the opstate structure. Called for leaves
    and leaf-lists.

    Particularly:
      * Skip checks for YANG list keys
      * Check that there is a single 'config' and 'state' container in the
        path
      * Check that elements in a 'config' container are r/w, and 'state' are ro
  """

  pathstr = statements.mk_path_str(statement, False)
  # print "examining path to %s: %s" % (statement.arg, pathstr)

  # leaves that are list keys are exempt from this check.  YANG
  # requires them at the top level of the list, i.e., not allowed
  # in a descendent container
  if statement.keyword == 'leaf' and hasattr(statement, 'i_is_key'):
    keytype = statement.search_one ('type')
    if keytype.arg != 'leafref':
      err_add(ctx.errors, statement.pos, 'OC_OPSTATE_KEY_LEAFREF',
        statement.arg)
    # print "leaf %s is a key, skipping" % statement.arg
    return

  #path_elements = [c.encode('ascii', 'ignore') for c in yangpath.split_paths(pathstr)]
  path_elements = yangpath.split_paths(pathstr)
  # count number of 'config' and 'state' elements in the path
  confignum = path_elements.count('config')
  statenum = path_elements.count('state')
  if confignum != 1 and statenum != 1:
    err_add(ctx.errors, statement.pos, 'OC_OPSTATE_CONTAINER_COUNT',
      (pathstr))

  # for elements in a config or state container, make sure they have the
  # correct config property
  if statement.parent.keyword == 'container':
    # print "%s %s in container: %s (%s)" % (statement.keyword, pathstr,
    #  str(statement.parent.arg), statement.i_config)
    if statement.parent.arg == 'config':
      if statement.i_config is False:
        err_add(ctx.errors, statement.pos, 'OC_OPSTATE_CONFIG_PROPERTY',
          (statement.arg, 'config', 'true'))
    elif statement.parent.arg == 'state' or statement.parent.arg == 'counters':
      if statement.i_config is True:
        err_add(ctx.errors, statement.parent.pos, 'OC_OPSTATE_CONFIG_PROPERTY',
          (statement.arg, 'state', 'false'))
    else:
      err_add(ctx.errors, statement.pos, 'OC_OPSTATE_CONTAINER_NAME',
      (statement.arg, pathstr))
Beispiel #45
0
    def check_module_rawtext(ctx, stmt):
        """Perform validation of a module"s raw text.

    Args:
      ctx: The pyang.Context for the current validation.
      stmt: The pyang.Statement for a module that we are parsing
        Function is called once per module to reduce the number of
        iterations through the module.
    """
        try:
            mod_filename = stmt.pos.ref.split("/")[-1]
            mod_filename = mod_filename.split(".")[0]
        except IndexError:
            err_add(ctx.errors, stmt.pos, "OC_LINTER_ERROR",
                    "Can't determine a module name for %s" % stmt.pos)

        handle = None
        for mod in ctx.repository.get_modules_and_revisions(ctx):
            # stmt.pos.ref gives the reference to the file that this
            # key statement was within
            if mod[0] == mod_filename:
                handle = mod
                break

        if handle is not None:
            try:
                module = ctx.repository.get_module_from_handle(handle[2])
            except (AttributeError, IndexError) as e:
                err_add(ctx.errors, stmt.pos, "OC_LINTER_ERROR",
                        "Can't find module %s: %s" % (stmt.pos.ref, e))
                return
        else:
            err_add(ctx.errors, stmt.pos, "OC_LINTER_ERROR",
                    "Couldn't open module %s" % stmt.pos.ref)
            return

        key_re = re.compile(
            r"^([ ]+)?key([ ]+)(?P<arg>[^\"][a-zA-Z0-9\-_]+);$")
        quoted_re = re.compile(r"^\".*\"$")

        ln_count = 0
        for ln in module[2].split("\n"):
            ln_count += 1

            # Remove the newline from the module
            ln = ln.rstrip("\n")
            if key_re.match(ln):
                key_arg = key_re.sub(r"\g<arg>", ln)
                if not quoted_re.match(key_arg):
                    # Need to create a fake position object for the
                    # key statement because of this pre-initialisation
                    # module parse.
                    pos = error.Position(stmt.pos.ref)
                    pos.line = ln_count

                    # Generate an error as the key argument is not
                    # quoted.
                    err_add(ctx.errors, pos, "OC_KEY_ARGUMENT_UNQUOTED",
                            key_arg)
            ln_count += 1
    def _add_i_deviation(self, ctx, stmt):
        if not hasattr(stmt.i_module, 'is_deviation_module'):
            stmt.i_module.is_deviation_module = True
        t = stmt.i_target_node
        if t is None:
            return
        stmt = stmt.search_one('deviate')

        if stmt.arg == 'not-supported':
            if ((t.parent.keyword == 'list') and
                (t in t.parent.i_key)):
                err_add(self.ctx.errors, stmt.pos, 'BAD_DEVIATE_KEY',
                        (t.i_module.arg, t.arg))
                return
            if not hasattr(t.parent, 'i_not_supported'):
                t.parent.i_not_supported = []
            t.parent.i_not_supported.append(t)
            self._add_deviation(t, 'not_supported', stmt.i_module, stmt)
        elif stmt.arg == 'add':
            for c in stmt.substmts:
                if c.keyword in statements._singleton_keywords:
                    if t.search_one(c.keyword) != None:
                        err_add(self.ctx.errors, c.pos, 'BAD_DEVIATE_ADD',
                                (c.keyword, t.i_module.arg, t.arg))
                    elif t.keyword not in statements._valid_deviations[c.keyword]:
                        err_add(self.ctx.errors, c.pos, 'BAD_DEVIATE_TYPE',
                                c.keyword)
                    else:
                        self._add_deviation(t, 'add', stmt.i_module, c)
                else:
                    if t.keyword not in statements._valid_deviations[c.keyword]:
                        err_add(self.ctx.errors, c.pos, 'BAD_DEVIATE_TYPE',
                                c.keyword)
                    else:
                        self._add_deviation(t, 'add', stmt.i_module, c)
        else:  # delete or replace
            for c in stmt.substmts:
                if (c.keyword == 'config'
                    and stmt.arg == 'replace'
                    and hasattr(t, 'i_config')):
                    self._add_deviation_r(t, 'replace', stmt.i_module, c)
                if c.keyword in statements._singleton_keywords:
                    old = t.search_one(c.keyword)
                else:
                    old = t.search_one(c.keyword, c.arg)
                if old is None:
                    err_add(self.ctx.errors, c.pos, 'BAD_DEVIATE_DEL',
                            (c.keyword, t.i_module.arg, t.arg))
                else:
                    self._add_deviation(t, stmt.arg, stmt.i_module, c)
Beispiel #47
0
def chk_type(old, new, ctx):
    oldts = old.i_type_spec
    newts = new.i_type_spec
    if oldts is None or newts is None:
        return
    # verify that the base type is the same
    if oldts.name != newts.name:
        err_add(ctx.errors, new.pos, 'CHK_BASE_TYPE_CHANGED',
                (oldts.name, newts.name))
        return

    # check the allowed restriction changes
    if oldts.name in chk_type_func:
        chk_type_func[oldts.name](old, new, oldts, newts, ctx)
Beispiel #48
0
  def check_bad_types(ctx, stmt):
    """Check validation rules for bad types that should not
    be used in OpenConfig models.

    Args:
      ctx: pyang.Context for validation
      stmt: pyang.Statement representing a leaf or leaf-list
    """
    elemtype = stmt.search_one("type")
    if elemtype is None or elemtype.arg not in BAD_TYPES:
      return

    err_add(ctx.errors, stmt.pos, "OC_BAD_TYPE",
            (elemtype.arg))
Beispiel #49
0
    def _add_i_deviation(self, ctx, stmt):
        if not hasattr(stmt.i_module, 'is_deviation_module'):
            stmt.i_module.is_deviation_module = True
        t = stmt.i_target_node
        if t is None:
            return
        stmt = stmt.search_one('deviate')

        if stmt.arg == 'not-supported':
            if ((t.parent.keyword == 'list') and
                (t in t.parent.i_key)):
                err_add(self.ctx.errors, stmt.pos, 'BAD_DEVIATE_KEY',
                        (t.i_module.arg, t.arg))
                return
            if not hasattr(t.parent, 'i_not_supported'):
                t.parent.i_not_supported = []
            t.parent.i_not_supported.append(t)
            self._add_deviation(t, 'not_supported', stmt.i_module, stmt)
        elif stmt.arg == 'add':
            for c in stmt.substmts:
                if c.keyword in statements._singleton_keywords:
                    if t.search_one(c.keyword) != None:
                        err_add(self.ctx.errors, c.pos, 'BAD_DEVIATE_ADD',
                                (c.keyword, t.i_module.arg, t.arg))
                    elif t.keyword not in statements._valid_deviations[c.keyword]:
                        err_add(self.ctx.errors, c.pos, 'BAD_DEVIATE_TYPE',
                                c.keyword)
                    else:
                        self._add_deviation(t, 'add', stmt.i_module, c)
                else:
                    if t.keyword not in statements._valid_deviations[c.keyword]:
                        err_add(self.ctx.errors, c.pos, 'BAD_DEVIATE_TYPE',
                                c.keyword)
                    else:
                        self._add_deviation(t, 'add', stmt.i_module, c)
        else:  # delete or replace
            for c in stmt.substmts:
                if (c.keyword == 'config'
                    and stmt.arg == 'replace'
                    and hasattr(t, 'i_config')):
                    self._add_deviation_r(t, 'replace', stmt.i_module, c)
                if c.keyword in statements._singleton_keywords:
                    old = t.search_one(c.keyword)
                else:
                    old = t.search_one(c.keyword, c.arg)
                if old is None:
                    err_add(self.ctx.errors, c.pos, 'BAD_DEVIATE_DEL',
                            (c.keyword, t.i_module.arg, t.arg))
                else:
                    self._add_deviation(t, stmt.arg, stmt.i_module, c)
Beispiel #50
0
def v_reference_instance_list(ctx, stmt):
    """Verify that the complex-type referred to by an instance-list statement
    with config true must have a defined key
    """
    if stmt.i_config:
        ct = stmt.i_complex_type
        if ct is None:
            return
        while ct is not None:
            if hasattr(ct, 'i_key'):
                return
            ct = ct.i_base_type
        err_add(ctx.errors, stmt.pos, 'KEY_REQUIRED',
            (stmt.i_complex_type.arg, stmt.pos))
Beispiel #51
0
def chk_type(old, new, ctx):
    oldts = old.i_type_spec
    newts = new.i_type_spec
    if oldts is None or newts is None:
        return
    # verify that the base type is the same
    if oldts.name != newts.name:
        err_add(ctx.errors, new.pos, 'CHK_BASE_TYPE_CHANGED',
                (oldts.name, newts.name))
        return

    # check the allowed restriction changes
    if oldts.name in chk_type_func:
        chk_type_func[oldts.name](old, new, oldts, newts, ctx)
Beispiel #52
0
  def check_module_rawtext(ctx, stmt):
    """Perform validation of a module"s raw text.

    Args:
      ctx: The pyang.Context for the current validation.
      stmt: The pyang.Statement for a module that we are parsing
        Function is called once per module to reduce the number of
        iterations through the module.
    """
    try:
      mod_filename = os.path.realpath(stmt.pos.ref).split("/")[-1]
      mod_filename = mod_filename.split(".")[0]
    except IndexError:
      err_add(ctx.errors, stmt.pos, "OC_LINTER_ERROR",
              "Can't determine a module name for %s" % stmt.pos)

    handle = None
    for mod in ctx.repository.get_modules_and_revisions(ctx):
      # stmt.pos.ref gives the reference to the file that this
      # key statement was within
      if mod[0] == mod_filename:
        handle = mod
        break

    if handle is not None:
      try:
        module = ctx.repository.get_module_from_handle(handle[2])
      except (AttributeError, IndexError) as e:
        err_add(ctx.errors, stmt.pos, "OC_LINTER_ERROR",
                "Can't find module %s: %s" % (stmt.pos.ref, unicode(e)))
        return
    else:
      err_add(ctx.errors, stmt.pos, "OC_LINTER_ERROR",
              "Couldn't open module %s" % stmt.pos.ref)
      return

    key_re = re.compile(r"^([ ]+)?key([ ]+)(?P<arg>[^\"][a-zA-Z0-9\-_]+);$")
    quoted_re = re.compile(r"^\".*\"$")

    ln_count = 0
    for ln in module[2].split("\n"):
      ln_count += 1

      # Remove the newline from the module
      ln = ln.rstrip("\n")
      if key_re.match(ln):
        key_arg = key_re.sub(r"\g<arg>", ln)
        if not quoted_re.match(key_arg):
          # Need to create a fake position object for the
          # key statement because of this pre-initialisation
          # module parse.
          pos = error.Position(stmt.pos.ref)
          pos.line = ln_count

          # Generate an error as the key argument is not
          # quoted.
          err_add(ctx.errors, pos, "OC_KEY_ARGUMENT_UNQUOTED",
                  key_arg)
      ln_count += 1
Beispiel #53
0
 def v_chk_description(self, ctx, s):
     arg = re.sub(r'\s+', ' ', s.arg)
     if s.parent.keyword == 'module' or s.parent.keyword == 'submodule':
         m = re_rfc8174.search(arg)
         if m is not None:
             self.found_8174 = True
             arg = arg[:m.start()] + arg[m.end():]
         if re_tlp.search(arg) is None:
             err_add(ctx.errors, s.pos,
                     'IETF_MISSING_TRUST_LEGAL_PROVISIONING', ())
     if not self.found_2119_keywords:
         if re_2119_keywords.search(arg) is not None:
             self.found_2119_keywords = True
             if not self.found_8174:
                 err_add(ctx.errors, s.pos, 'IETF_MISSING_RFC8174', ())
Beispiel #54
0
def chk_when(old, new, ctx):
    oldwhen = old.search('when')
    newwhen = new.search('when')
    # remove all common whens
    for oldw in old.search('when'):
        neww = new.search_one('when', arg = oldw.arg)
        if neww is not None:
            newwhen.remove(neww)
            oldwhen.remove(oldw)
    if len(oldwhen) == 0:
        for neww in newwhen:
            err_add(ctx.errors, neww.pos, 'CHK_NEW_WHEN', ())
    else:
        for neww in newwhen:
            err_add(ctx.errors, neww.pos, 'CHK_UNDECIDED_WHEN', ())
Beispiel #55
0
 def v_chk_description(self, ctx, s):
     arg = re.sub(r'\s+', ' ', s.arg)
     if s.parent.keyword == 'module' or s.parent.keyword == 'submodule':
         m = re_rfc8174.search(arg)
         if m is not None:
             self.found_8174 = True
             arg = arg[:m.start()] + arg[m.end():]
         if re_tlp.search(arg) is None:
             err_add(ctx.errors, s.pos,
                     'IETF_MISSING_TRUST_LEGAL_PROVISIONING', ())
     if not self.found_2119_keywords:
         if re_2119_keywords.search(arg) is not None:
             self.found_2119_keywords = True
             if not self.found_8174:
                 err_add(ctx.errors, s.pos, 'IETF_MISSING_RFC8174', ())
def v_set_subid(ctx, stmt):
    if stmt.parent.search_one((smi_module_name, 'oid')) is not None:
        err_add(ctx.errors, stmt.pos, 'SMIv2_SUBID_AND_OID', ())
        return
        
    def find_ancestor_oid(s):
        if s.parent is None:
            return None
        if hasattr(s.parent, 'i_smi_oid'):
            return s.parent.i_smi_oid
        return find_ancestor_oid(s.parent)
    oid = find_ancestor_oid(stmt.parent)
    if oid is None:
        err_add(ctx.errors, stmt.pos, 'SMIv2_BAD_SUBID', ())
        return
    stmt.parent.i_smi_oid = oid + [int(stmt.arg)]
Beispiel #57
0
def v_yang_data(ctx, stmt):

    def ensure_container(s):
        if len(s.i_children) != 1:
            return False
        ch = s.i_children[0]
        if ch.keyword == 'choice':
            for c in ch.i_children:
                if not ensure_container(c):
                    return False
        elif ch.keyword != 'container':
            return False
        return True

    if not ensure_container(stmt):
        err_add(ctx.errors, stmt.pos, 'RESTCONF_YANG_DATA_CHILD', ())
Beispiel #58
0
def v_chk_ocmodule(ctx, statement):
  """
    Check characteristics of an entire OpenConfig module.
    Particularly:
      * Module should include an "openconfig-extensions:openconfig-version"
        statement, which should match semantic versioning patterns.
      * Module should not define any data elements at the top level.
      * Module name should be "openconfig-".
  """

  data_definitions = [i.arg for i in statement.substmts if i.keyword in
                      INSTANTIATED_DATA_KEYWORDS]
  if len(data_definitions):
    err_add(ctx.errors, statement.pos, 'OC_MODULE_DATA_DEFINITIONS',
      (statement.arg, ", ".join(data_definitions)))

  version = None
  for s in statement.substmts:
    if isinstance(s.keyword, tuple) and s.keyword[1] == 'openconfig-version':
      version = s
  if version is None:
    err_add(ctx.errors, statement.pos, 'OC_MODULE_MISSING_VERSION',
      statement.arg)
    return

  if not re.match("^[0-9]+\.[0-9]+\.[0-9]+$", version.arg):
    err_add(ctx.errors, statement.pos, 'OC_INVALID_SEMVER',
      version.arg)

  match_revision = False
  for revision_stmt in statement.search('revision'):
    reference_stmt = revision_stmt.search_one('reference')
    if reference_stmt is not None and \
              reference_stmt.arg == version.arg:
      match_revision = True

  if match_revision is False:
    err_add(ctx.errors, statement.pos, 'OC_MISSING_SEMVER_REVISION',
      version.arg)

  top_groupings = []
  for grouping in statement.search('grouping'):
    if re.match(".*\-top$", grouping.arg):
      top_groupings.append(grouping.arg)
  if not len(top_groupings):
    err_add(ctx.errors, statement.pos, 'OC_MISSING_STANDARD_GROUPING',
      (statement.arg, "-top"))
Beispiel #59
0
def chk_default(old, new, ctx):
    newdefault = new.search_one('default')
    olddefault = old.search_one('default')
    if olddefault is None and newdefault is None:
        return
    if olddefault is not None and newdefault is None:
        err_def_removed(olddefault, new, ctx)
    elif olddefault is None and newdefault is not None:
        # default added, check old implicit default
        oldtype = old.search_one('type')
        if (oldtype.i_typedef is not None and
            hasattr(oldtype.i_typedef, 'i_default_str') and
            oldtype.i_typedef.i_default_str is not None and
            oldtype.i_typedef.i_default_str != newdefault.arg):
            err_add(ctx.errors, newdefault.pos, 'CHK_IMPLICIT_DEFAULT', ())
    elif olddefault.arg != newdefault.arg:
        err_def_changed(olddefault, newdefault, ctx)