Ejemplo n.º 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))
Ejemplo n.º 2
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))
Ejemplo n.º 3
0
  def check_relative_paths(ctx, stmt):
    """Check whether relative paths are used within a module.

    Args:
      ctx: pyang.Context for the validation
      stmt: pyang.Statement object for the statement the validation function
      is called for.
    """
    path = stmt.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 = components[0].split(":")[0]
    else:
      namespace = stmt.i_module.i_prefix

    mod_prefix = stmt.i_module.i_prefix

    if namespace == mod_prefix and abspath:
      # Don't throw a warning if the absolute path is within the
      # current module if the statement is within a typedef. This
      # allows types to be defined that refer to an element of a
      # module without errors being generated.
      is_typedef = False
      if stmt.parent is not None and stmt.parent.parent is not None:
        if stmt.parent.parent.keyword == "typedef":
          is_typedef = True

      if not is_typedef:
        err_add(ctx.errors, stmt.pos, "OC_RELATIVE_PATH",
                (stmt.keyword, stmt.arg))
Ejemplo n.º 4
0
  def check_relative_paths(ctx, stmt):
    """Check whether relative paths are used within a module.

    Args:
      ctx: pyang.Context for the validation
      stmt: pyang.Statement object for the statement the validation function
      is called for.
    """
    path = stmt.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 = components[0].split(":")[0]
    else:
      namespace = stmt.i_module.i_prefix

    mod_prefix = stmt.i_module.i_prefix

    if namespace == mod_prefix and abspath:
      # Don't throw a warning if the absolute path is within the
      # current module if the statement is within a typedef. This
      # allows types to be defined that refer to an element of a
      # module without errors being generated.
      is_typedef = False
      if stmt.parent is not None and stmt.parent.parent is not None:
        if stmt.parent.parent.keyword == "typedef":
          is_typedef = True

      if not is_typedef:
        err_add(ctx.errors, stmt.pos, "OC_RELATIVE_PATH",
                (stmt.keyword, stmt.arg))
Ejemplo n.º 5
0
  def check_opstate(ctx, stmt):
    """Check operational state validation rules.

    Args:
      ctx: pyang.Context for validation
      stmt: pyang.Statement for a leaf or leaf-list
    """
    pathstr = statements.mk_path_str(stmt)

    # 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
    is_key = False
    if stmt.parent.keyword == "list" and stmt.keyword == "leaf":
      key_stmt = stmt.parent.search_one("key")
      if key_stmt is not None:
        if " " in key_stmt.arg:
          key_parts = [i for i in key_stmt.arg.split(" ")]
        else:
          key_parts = [key_stmt.arg]

        if stmt.arg in key_parts:
          is_key = True

    if is_key:
      keytype = stmt.search_one("type")
      if keytype.arg != "leafref":
        err_add(ctx.errors, stmt.pos, "OC_OPSTATE_KEY_LEAFREF",
                stmt.arg)

      keypath = keytype.search_one("path")
      keypathelem = yangpath.split_paths(keypath.arg)
      for i in range(0,len(keypathelem)):
        if keypathelem[i] in ["config", "state"]:
          if len(keypathelem[i+1:]) > 1:
            err_add(ctx.errors, stmt.pos, "OC_OPSTATE_KEY_LEAFREF_DIRECT",
                    stmt.arg)

      return

    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, stmt.pos, "OC_OPSTATE_CONTAINER_COUNT",
              (pathstr))

    # for elements in a config or state container, make sure they have the
    # correct config property
    if stmt.parent.keyword == "container":
      if stmt.parent.arg == "config":
        if stmt.i_config is False:
          err_add(ctx.errors, stmt.pos, "OC_OPSTATE_CONFIG_PROPERTY",
                  (stmt.arg, "config", "true"))
      elif stmt.parent.arg == "state":
        if stmt.i_config is True:
          err_add(ctx.errors, stmt.parent.pos, "OC_OPSTATE_CONFIG_PROPERTY",
                  (stmt.arg, "state", "false"))
      else:
        valid_enclosing_state = False

        if stmt.i_config is False:
          # Allow nested containers within a state container
          path_elements = yangpath.split_paths(pathstr)
          if u"state" in path_elements:
            valid_enclosing_state = True

        if valid_enclosing_state is False:
          err_add(ctx.errors, stmt.pos, "OC_OPSTATE_CONTAINER_NAME",
                  (stmt.arg, pathstr))
Ejemplo n.º 6
0
  def check_opstate(ctx, stmt):
    """Check operational state validation rules.

    Args:
      ctx: pyang.Context for validation
      stmt: pyang.Statement for a leaf or leaf-list
    """
    pathstr = statements.mk_path_str(stmt)

    # 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
    is_key = False
    if stmt.parent.keyword == "list" and stmt.keyword == "leaf":
      key_stmt = stmt.parent.search_one("key")
      if key_stmt is not None:
        if " " in key_stmt.arg:
          key_parts = [unicode(i) for i in key_stmt.arg.split(" ")]
        else:
          key_parts = [unicode(key_stmt.arg)]

        if stmt.arg in key_parts:
          is_key = True

    if is_key:
      keytype = stmt.search_one("type")
      if keytype.arg != "leafref":
        err_add(ctx.errors, stmt.pos, "OC_OPSTATE_KEY_LEAFREF",
                stmt.arg)
      return

    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, stmt.pos, "OC_OPSTATE_CONTAINER_COUNT",
              (pathstr))

    # for elements in a config or state container, make sure they have the
    # correct config property
    if stmt.parent.keyword == "container":
      if stmt.parent.arg == "config":
        if stmt.i_config is False:
          err_add(ctx.errors, stmt.pos, "OC_OPSTATE_CONFIG_PROPERTY",
                  (stmt.arg, "config", "true"))
      elif stmt.parent.arg == "state":
        if stmt.i_config is True:
          err_add(ctx.errors, stmt.parent.pos, "OC_OPSTATE_CONFIG_PROPERTY",
                  (stmt.arg, "state", "false"))
      else:
        valid_enclosing_state = False

        if stmt.i_config is False:
          # Allow nested containers within a state container
          path_elements = yangpath.split_paths(pathstr)
          if u"state" in path_elements:
            valid_enclosing_state = True

        if valid_enclosing_state is False:
          err_add(ctx.errors, stmt.pos, "OC_OPSTATE_CONTAINER_NAME",
                  (stmt.arg, pathstr))