Ejemplo n.º 1
0
 def loadYangFolder(self):
     modules = []
     path = '.'
     repos = repository.FileRepository(path)
     ctx = context.Context(repos)
     for filename in glob.glob(self.folderPath + '/*.yang'):
         filename = os.path.abspath(filename)
         fd = io.open(filename, "r", encoding="utf-8")
         text = fd.read()
         m = syntax.re_filename.search(filename)
         module = None
         if m is not None:
             name, rev, in_format = m.groups()
             name = os.path.basename(name)
             module = ctx.add_module(filename,
                                     text,
                                     in_format,
                                     name,
                                     rev,
                                     expect_failure_error=False)
         else:
             module = ctx.add_module(filename, text)
         if module is not None:
             modules.append(module)
     ctx.validate()
     return modules
Ejemplo n.º 2
0
def check_update(ctx, newmod):
    oldpath = os.pathsep.join(ctx.opts.old_path)
    olddir = os.path.dirname(ctx.opts.check_update_from)
    if olddir == '':
        olddir = '.'
    oldpath += os.pathsep + olddir
    oldrepo = repository.FileRepository(oldpath, use_env=False)
    oldctx = context.Context(oldrepo)
    oldctx.opts = ctx.opts
    oldctx.lax_xpath_checks = ctx.lax_xpath_checks
    oldctx.lax_quote_checks = ctx.lax_quote_checks

    if ctx.opts.verbose:
        print("Loading old modules from:")
        for d in oldrepo.dirs:
            print("  %s" % d)
        print("")

    for p in plugin.plugins:
        p.setup_ctx(oldctx)

    for oldfilename in [ctx.opts.check_update_from] + ctx.opts.old_deviation:
        try:
            fd = io.open(oldfilename, "r", encoding="utf-8")
            text = fd.read()
        except IOError as ex:
            sys.stderr.write("error %s: %s\n" % (oldfilename, ex))
            sys.exit(1)
        if oldfilename in ctx.opts.old_deviation:
            oldctx.add_module(oldfilename, text)
        else:
            oldmod = oldctx.add_module(oldfilename, text)
    oldctx.validate()

    ctx.errors.extend(oldctx.errors)

    if oldmod is None:
        return

    for epos, etag, eargs in ctx.errors:
        if (epos.ref in (newmod.pos.ref, oldmod.pos.ref)
                and error.is_error(error.err_level(etag))):
            return

    if ctx.opts.verbose:
        print("Loaded old modules:")
        for x in oldrepo.get_modules_and_revisions(oldctx):
            (m, r, (fmt, filename)) = x
            print("  %s" % filename)
        print("")

    chk_module(ctx, oldmod, newmod)
Ejemplo n.º 3
0
 def loadYangFile(self):
     filename = self.filePath
     path = '.'
     repos = repository.FileRepository(path)
     ctx = context.Context(repos)
     fd = io.open(filename, "r", encoding="utf-8")
     text = fd.read()
     m = syntax.re_filename.search(filename)
     if m is not None:
         name, rev, in_format = m.groups()
         name = os.path.basename(name)
         module = ctx.add_module(filename,
                                 text,
                                 in_format,
                                 name,
                                 rev,
                                 expect_failure_error=False)
     else:
         module = ctx.add_module(filename, text)
     ctx.validate()
     return module
Ejemplo n.º 4
0
    def __init__(self, session, parent, name, type_):
        self.type_ = type_
        self.name = name
        self._get_hook = {}
        self._set_hook = {}
        self.session = session
        super(TAIObject, self).__init__(parent)

        d = self.session.get_context().get_searchdirs()
        repo = repository.FileRepository(d[0])
        ctx = context.Context(repo)

        m = self.session.get_context().get_module('goldstone-tai')
        v = m.print_mem(ly.LYS_IN_YANG, 0)

        ctx.add_module(None, v)
        mod = ctx.get_module('goldstone-tai')
        self.config = mod.search_one('grouping', 'tai-{}-config'.format(type_))
        self.state = mod.search_one('grouping', 'tai-{}-state'.format(type_))

        @self.command(FuzzyCompleter(TAICompleter(self.config, self.state)))
        def get(args):
            if len(args) != 1:
                raise InvalidInput('usage: get <name>')
            self.session.session_switch_ds(sr.SR_DS_OPERATIONAL)
            try:
                items = self.session.get_items('{}/state/{}'.format(
                    self.xpath(), args[0]))
                for i in range(items.val_cnt()):
                    item = items.val(i)
                    if args[0] in self._get_hook:
                        print(self._get_hook[args[0]](item))
                    else:
                        print(item.val_to_string())
            except RuntimeError:
                err = self.session.get_error()
                if err.error_cnt() > 0:
                    idx = err.error_cnt() - 1
                    print('err: {}, xpath: {}'.format(err.message(idx),
                                                      err.xpath(idx)))
            self.session.session_switch_ds(sr.SR_DS_RUNNING)

        @self.command(TAICompleter(self.config))
        def set(args):
            if len(args) != 2:
                raise InvalidInput('usage: set <name> <value>')
            if args[0] in self._set_hook:
                v = self._set_hook[args[0]](args[1])
            else:
                v = args[1]
            self.session.set_item_str(
                '{}/config/{}'.format(self.xpath(), args[0]), v)
            self.session.apply_changes()

        @self.command()
        def show(args):
            if len(args) != 0:
                raise InvalidInput('usage: show[cr]')
            self.session.session_switch_ds(sr.SR_DS_OPERATIONAL)
            tree = self.session.get_subtree(self.xpath(), TIMEOUT_MS)
            d = json.loads(tree.print_mem(ly.LYD_JSON, 0))
            print(d)
            self.session.session_switch_ds(sr.SR_DS_RUNNING)
Ejemplo n.º 5
0
from pyang import repository, context
import argparse
import os

parser = argparse.ArgumentParser(
    description='rename a list of yang model files by the revision information'
)
parser.add_argument('yang_files',
                    type=str,
                    nargs='+',
                    help='list of yang files')
args = parser.parse_args()

repos = repository.FileRepository(".")
for fname in args.yang_files:
    targ_module = os.path.basename(fname).split(".")[0]
    if '@' in targ_module:
        targ_module = targ_module.split('@')[0]
    ctx = context.Context(repos)
    fd = open(fname, 'r')
    text = fd.read()
    ctx.add_module(fname, text)
    for ((m, r), v) in ctx.modules.items():
        if m == targ_module:
            targ_dir = os.path.dirname(fname)
            if len(targ_dir) == 0:
                os.rename(fname, targ_module + '@' + r + '.yang')
            else:
                os.rename(fname,
                          targ_dir + '/' + targ_module + '@' + r + '.yang')
            break
Ejemplo n.º 6
0
    def __init__(self, conn, parent, name, type_):
        self.type_ = type_
        self.name = name
        self._get_hook = {}
        self._set_hook = {}
        self.session = conn.start_session()
        super(TAIObject, self).__init__(parent)

        d = self.session.get_ly_ctx().get_searchdirs()
        repo = repository.FileRepository(d[0])
        ctx = context.Context(repo)

        m = self.session.get_ly_ctx().get_module('goldstone-tai')
        v = m.print_mem("yang")

        ctx.add_module(None, v)
        mod = ctx.get_module('goldstone-tai')
        self.config = mod.search_one('grouping', 'tai-{}-config'.format(type_))
        self.state = mod.search_one('grouping', 'tai-{}-state'.format(type_))

        @self.command(FuzzyCompleter(TAICompleter(self.config, self.state)))
        def get(args):
            if len(args) != 1:
                raise InvalidInput('usage: get <name>')
            self.session.switch_datastore('operational')
            try:
                items = self.session.get_items('{}/state/{}'.format(
                    self.xpath(), args[0]))
                for item in items:
                    if args[0] in self._get_hook:
                        print(self._get_hook[args[0]](item.value))
                    else:
                        print(item.value)
            except sr.errors.SysrepoCallbackFailedError as e:
                print(e)

        @self.command(TAICompleter(self.config))
        def set(args):
            if len(args) != 2:
                raise InvalidInput('usage: set <name> <value>')
            if args[0] in self._set_hook:
                v = self._set_hook[args[0]](args[1])
            else:
                v = args[1]
            self.session.switch_datastore('running')

            if type(self) != Module:
                try:
                    self.session.get_data(self.parent.xpath())
                except sr.SysrepoNotFoundError:
                    self.session.set_item(f'{self.parent.xpath()}/config/name',
                                          self.parent.name)

            try:
                self.session.get_data(self.xpath())
            except sr.SysrepoNotFoundError:
                self.session.set_item(f'{self.xpath()}/config/name', self.name)

            self.session.set_item(f'{self.xpath()}/config/{args[0]}', v)

            self.session.apply_changes()

        @self.command()
        def show(args):
            if len(args) != 0:
                raise InvalidInput('usage: show[cr]')
            self.session.switch_datastore('operational')
            print(self.session.get_data(self.xpath()))
            self.session.switch_datastore('running')
Ejemplo n.º 7
0
def run(args=None, extra_plugin_dirs=None):
    """
    The main CLI entrypoint
    :param args: explicitly passed arguments for using pyayng from python
    :param extra_plugin_dirs: additional plugin dirs (from calling app)
    """

    usage = """%prog [options] [<filename>...]

Validates the YANG module in <filename> (or stdin), and all its dependencies."""

    plugindirs = extra_plugin_dirs or []
    # check for --plugindir
    idx = 1
    while '--plugindir' in sys.argv[idx:]:
        idx = idx + sys.argv[idx:].index('--plugindir')
        plugindirs.append(sys.argv[idx+1])
        idx = idx + 1
    plugin.init(plugindirs)

    fmts = {}
    xforms = {}
    for p in plugin.plugins:
        p.add_output_format(fmts)
        p.add_transform(xforms)

    optlist = [
        # use capitalized versions of std options help and version
        optparse.make_option("-h", "--help",
                             action="help",
                             help="Show this help message and exit"),
        optparse.make_option("-v", "--version",
                             action="version",
                             help="Show version number and exit"),
        optparse.make_option("-V", "--verbose",
                             action="store_true"),
        optparse.make_option("-e", "--list-errors",
                             dest="list_errors",
                             action="store_true",
                             help="Print a listing of all error and warning " \
                                 "codes and exit."),
        optparse.make_option("--print-error-code",
                             dest="print_error_code",
                             action="store_true",
                             help="On errors, print the error code instead " \
                             "of the error message."),
        optparse.make_option("--print-error-basename",
                             dest="print_error_basename",
                             action="store_true",
                             help="On errors, print the basename of files " \
                             "of the error message."),
        optparse.make_option("--msg-template",
                             dest="msg_template",
                             type="string",
                             help="Template used to display error messages. " \
                             "This is a python new-style format string used " \
                             "to format the message information with keys " \
                             "file, line, code, type and msg. " \
                             "Example: --msg-template='{file} || {line} || " \
                             "{code} || {type} || {level} || {msg}'"),
        optparse.make_option("-W",
                             dest="warnings",
                             action="append",
                             default=[],
                             metavar="WARNING",
                             help="If WARNING is 'error', treat all warnings " \
                                 "as errors, except any listed WARNING. " \
                                 "If WARNING is 'none', do not report any " \
                                 "warnings."),
        optparse.make_option("-E",
                             dest="errors",
                             action="append",
                             default=[],
                             metavar="WARNING",
                             help="Treat each WARNING as an error.  For a " \
                                 "list of warnings, use --list-errors."),
        optparse.make_option("--ignore-error",
                             dest="ignore_error_tags",
                             action="append",
                             default=[],
                             metavar="ERROR",
                             help="Ignore ERROR.  Use with care.  For a " \
                                 "list of errors, use --list-errors."),
        optparse.make_option("--ignore-errors",
                             dest="ignore_errors",
                             action="store_true",
                             help="Ignore all errors.  Use with care."),
        optparse.make_option("--canonical",
                             dest="canonical",
                             action="store_true",
                             help="Validate the module(s) according to the " \
                             "canonical YANG order."),
        optparse.make_option("--max-line-length",
                             type="int",
                             dest="max_line_len"),
        optparse.make_option("--max-identifier-length",
                             type="int",
                             dest="max_identifier_len"),
        optparse.make_option("-t", "--transform", dest="transforms",
                             default=[], action="append",
                             help="Apply transform TRANSFORM.  Supported " \
                                  "transforms are: " + ', '.join(xforms)),
        optparse.make_option("-f", "--format",
                             dest="format",
                             help="Convert to FORMAT.  Supported formats " \
                             "are: " +  ', '.join(fmts)),
        optparse.make_option("-o", "--output",
                             dest="outfile",
                             help="Write the output to OUTFILE instead " \
                             "of stdout."),
        optparse.make_option("-F", "--features",
                             metavar="FEATURES",
                             dest="features",
                             default=[],
                             action="append",
                             help="Features to support, default all. " \
                             "<modname>:[<feature>,]*"),
        optparse.make_option("", "--max-status",
                             metavar="MAXSTATUS",
                             dest="max_status",
                             help="Max status to support, one of: " \
                             "current, deprecated, obsolete"),
        optparse.make_option("", "--deviation-module",
                             metavar="DEVIATION",
                             dest="deviations",
                             default=[],
                             action="append",
                             help="Deviation module"),
        optparse.make_option("-p", "--path",
                             dest="path",
                             default=[],
                             action="append",
                             help=os.pathsep + "-separated search path for yin"
                             " and yang modules"),
        optparse.make_option("--plugindir",
                             dest="plugindir",
                             help="Load pyang plugins from PLUGINDIR"),
        optparse.make_option("--strict",
                             dest="strict",
                             action="store_true",
                             help="Force strict YANG compliance."),
        optparse.make_option("--lax-quote-checks",
                             dest="lax_quote_checks",
                             action="store_true",
                             help="Lax check of backslash in quoted strings."),
        optparse.make_option("--lax-xpath-checks",
                             dest="lax_xpath_checks",
                             action="store_true",
                             help="Lax check of XPath expressions."),
        optparse.make_option("--trim-yin",
                             dest="trim_yin",
                             action="store_true",
                             help="In YIN input modules, trim whitespace "
                             "in textual arguments."),
        optparse.make_option("-L", "--hello",
                             dest="hello",
                             action="store_true",
                             help="Filename of a server's hello message is "
                             "given instead of module filename(s)."),
        optparse.make_option("--implicit-hello-deviations",
                             dest="implicit_hello_deviations",
                             action="store_true",
                             help="Attempt to parse all deviations from hello "
                             "message regardless of declaration."),
        optparse.make_option("--keep-comments",
                             dest="keep_comments",
                             action="store_true",
                             help="Pyang will not discard comments; \
                                   has effect if the output plugin can \
                                   handle comments."),
        optparse.make_option("--no-path-recurse",
                             dest="no_path_recurse",
                             action="store_true",
                             help="Do not recurse into directories in the \
                                   yang path."),
        ]

    optparser = optparse.OptionParser(usage, add_help_option = False)
    optparser.version = '%prog ' + pyang.__version__
    optparser.add_options(optlist)

    for p in plugin.plugins:
        p.add_opts(optparser)

    (o, args) = optparser.parse_args(args)

    if o.outfile is not None and o.format is None:
        sys.stderr.write("no format specified\n")
        sys.exit(1)

    filenames = args

    # Parse hello if present
    if o.hello:
        if len(filenames) > 1:
            sys.stderr.write("multiple hello files given\n")
            sys.exit(1)
        if filenames:
            try:
                fd = open(filenames[0], "rb")
            except IOError as ex:
                sys.stderr.write("error %s: %s\n" % (filenames[0], ex))
                sys.exit(1)
        elif sys.version < "3":
            fd = sys.stdin
        else:
            fd = sys.stdin.buffer
        hel = hello.HelloParser().parse(fd)

    path = os.pathsep.join(o.path)

    # add standard search path
    if len(o.path) == 0:
        path = "."
    else:
        path += os.pathsep + "."

    repos = repository.FileRepository(path, no_path_recurse=o.no_path_recurse,
                                      verbose=o.verbose)

    ctx = context.Context(repos)

    ctx.opts = o
    ctx.canonical = o.canonical
    ctx.max_line_len = o.max_line_len
    ctx.max_identifier_len = o.max_identifier_len
    ctx.trim_yin = o.trim_yin
    ctx.lax_xpath_checks = o.lax_xpath_checks
    ctx.lax_quote_checks = o.lax_quote_checks
    ctx.strict = o.strict
    ctx.max_status = o.max_status

    # make a map of features to support, per module
    if o.hello:
        for mn, rev in hel.yang_modules():
            ctx.features[mn] = hel.get_features(mn)
    for f in ctx.opts.features:
        (modulename, features) = parse_features_string(f)
        ctx.features[modulename] = features

    for p in plugin.plugins:
        p.setup_ctx(ctx)

    if o.list_errors is True:
        for tag in error.error_codes:
            (level, fmt) = error.error_codes[tag]
            if error.is_warning(level):
                print("Warning: %s" % tag)
            elif error.allow_warning(level):
                print("Minor Error:   %s" % tag)
            else:
                print("Error:   %s" % tag)
            print("Message: %s" % fmt)
            print("")
        sys.exit(0)

    # patch the error spec so that -W errors are treated as warnings
    for w in o.warnings:
        if w in error.error_codes:
            (level, wstr) = error.error_codes[w]
            if error.allow_warning(level):
                error.error_codes[w] = (4, wstr)

    xform_objs = []
    for transform in o.transforms:
        if transform not in xforms:
            sys.stderr.write("unsupported transform '%s'\n" % transform)
        else:
            xform_obj = xforms[transform]
            xform_obj.setup_xform(ctx)
            xform_objs.append(xform_obj)
    if len(xform_objs) != len(o.transforms):
        sys.exit(1)

    if o.format is not None:
        if o.format not in fmts:
            sys.stderr.write("unsupported format '%s'\n" % o.format)
            sys.exit(1)
        emit_obj = fmts[o.format]
        if o.keep_comments and emit_obj.handle_comments:
            ctx.keep_comments = True
        emit_obj.setup_fmt(ctx)
    else:
        emit_obj = None

    xform_and_emit_objs = xform_objs[:]
    if emit_obj is not None:
        xform_and_emit_objs.append(emit_obj)

    for p in plugin.plugins:
        p.pre_load_modules(ctx)

    exit_code = 0
    modules = []

    if o.hello:
        ctx.capabilities = hel.registered_capabilities()
        modules_missing = False
        for mn, rev in hel.yang_modules():
            mod = ctx.search_module(error.Position(''), mn, rev)
            if mod is None:
                emarg = mn
                if rev:
                    emarg += "@" + rev
                sys.stderr.write(
                    "module '%s' specified in hello not found.\n" % emarg)
                modules_missing = True
            else:
                modules.append(mod)
        if modules_missing is True:
            sys.exit(1)
    else:
        if len(filenames) == 0:
            text = sys.stdin.read()
            module = ctx.add_module('<stdin>', text)
            if module is None:
                exit_code = 1
            else:
                modules.append(module)
        if (len(filenames) > 1 and
            emit_obj is not None and
            not emit_obj.multiple_modules):
            sys.stderr.write("too many files to convert\n")
            sys.exit(1)

        for filename in filenames:
            try:
                fd = io.open(filename, "r", encoding="utf-8")
                text = fd.read()
                if o.verbose:
                    util.report_file_read(filename, "(CL)")
            except IOError as ex:
                sys.stderr.write("error %s: %s\n" % (filename, ex))
                sys.exit(1)
            except UnicodeDecodeError as ex:
                s = str(ex).replace('utf-8', 'utf8')
                sys.stderr.write("%s: unicode error: %s\n" % (filename, s))
                sys.exit(1)
            m = syntax.re_filename.search(filename)
            ctx.yin_module_map = {}
            if m is not None:
                name, rev, in_format = m.groups()
                name = os.path.basename(name)
                module = ctx.add_module(filename, text, in_format, name, rev,
                                        expect_failure_error=False)
            else:
                module = ctx.add_module(filename, text)
            if module is None:
                exit_code = 1
            else:
                modules.append(module)

    modulenames = []
    for m in modules:
        modulenames.append(m.arg)
        for s in m.search('include'):
            modulenames.append(s.arg)

    # apply deviations
    for filename in ctx.opts.deviations:
        try:
            fd = io.open(filename, "r", encoding="utf-8")
            text = fd.read()
        except IOError as ex:
            sys.stderr.write("error %s: %s\n" % (filename, ex))
            sys.exit(1)
        except UnicodeDecodeError as ex:
            s = str(ex).replace('utf-8', 'utf8')
            sys.stderr.write("%s: unicode error: %s\n" % (filename, s))
            sys.exit(1)
        m = ctx.add_module(filename, text)
        if m is not None:
            ctx.deviation_modules.append(m)
    if o.hello and o.implicit_hello_deviations:
        for deviation_module in hel.yang_implicit_deviation_modules():
            m = ctx.search_module(error.Position(''), deviation_module)
            if m is not None:
                ctx.deviation_modules.append(m)

    for p in plugin.plugins:
        p.pre_validate_ctx(ctx, modules)

    if len(xform_and_emit_objs) > 0 and len(modules) > 0:
        for obj in xform_and_emit_objs:
            obj.pre_validate(ctx, modules)

    ctx.validate()

    for m in modules:
        m.prune()

    # transform modules
    if len(xform_objs) > 0 and len(modules) > 0:
        for xform_obj in xform_objs:
            try:
                if not xform_obj.transform(ctx, modules):
                    for module in modules:
                        module.i_is_validated = False
                        statements.validate_module(ctx, module)
            except error.TransformError as e:
                if e.msg != "":
                    sys.stderr.write(e.msg + '\n')
                sys.exit(e.exit_code)

    # verify the given features
    for m in modules:
        if m.arg in ctx.features:
            for f in ctx.features[m.arg]:
                if f not in m.i_features:
                    sys.stderr.write("unknown feature %s in module %s\n" %
                                     (f, m.arg))
                    sys.exit(1)

    if len(xform_and_emit_objs) > 0 and len(modules) > 0:
        for obj in xform_and_emit_objs:
            obj.post_validate(ctx, modules)

    for p in plugin.plugins:
        p.post_validate_ctx(ctx, modules)

    def keyfun(e):
        if e[0].ref == filenames[0]:
            return 0
        else:
            return 1

    ctx.errors.sort(key=lambda e: (e[0].ref, e[0].line))
    if len(filenames) > 0:
        # first print error for the first filename given
        ctx.errors.sort(key=keyfun)

    if o.ignore_errors:
        ctx.errors = []

    for epos, etag, eargs in ctx.errors:
        if etag in o.ignore_error_tags:
            continue
        if (ctx.implicit_errors is False and
            epos.top.arg not in modulenames and
            (not hasattr(epos.top, 'i_modulename') or
             epos.top.i_modulename not in modulenames) and
            epos.ref not in filenames):
            # this module was added implicitly (by import); skip this error
            # the code includes submodules
            continue
        elevel = error.err_level(etag)
        if error.is_warning(elevel) and etag not in o.errors:
            kind = "warning"
            if 'error' in o.warnings and etag not in o.warnings:
                kind = "error"
                exit_code = 1
            elif 'none' in o.warnings:
                continue
        else:
            kind = "error"
            exit_code = 1
        emsg = etag if o.print_error_code else error.err_to_str(etag, eargs)

        if o.msg_template is not None:
            try:
                sys.stderr.write(str(o.msg_template).format(
                    file=epos.ref, line=epos.line,
                    code=etag, type=kind,
                    msg=error.err_to_str(etag, eargs),
                    level=elevel) + '\n')
            except KeyError as error_msg:
                sys.stderr.write(
                    "unsupported key %s in msg-template\n" % error_msg)
                sys.exit(1)
        else:
            sys.stderr.write('%s: %s: %s\n' %
                             (epos.label(o.print_error_basename), kind, emsg))

    if emit_obj is not None and len(modules) > 0:
        tmpfile = None
        if o.outfile is None:
            if sys.version < '3':
                fd = codecs.getwriter('utf8')(sys.stdout)
            else:
                fd = sys.stdout
        else:
            tmpfile = o.outfile + ".tmp"
            if sys.version < '3':
                fd = codecs.open(tmpfile, "w+", encoding="utf-8")
            else:
                fd = io.open(tmpfile, "w+", encoding="utf-8")
        try:
            emit_obj.emit(ctx, modules, fd)
        except error.EmitError as e:
            if e.msg != "":
                sys.stderr.write(e.msg + '\n')
            if tmpfile is not None:
                fd.close()
                os.remove(tmpfile)
            sys.exit(e.exit_code)
        except:
            if tmpfile is not None:
                fd.close()
                os.remove(tmpfile)
            raise
        if tmpfile is not None:
            fd.close()
            os.rename(tmpfile, o.outfile)

    sys.exit(exit_code)