如何使 junos_config Ansible 模块支持非 ASCII 字符?

4
我正在使用Ansible 2.2.1.0中的junos_config模块,它可以将纯文本配置文件用于配置Juniper网络设备。在此过程中似乎使用了lxml。然而问题在于,这个纯文本文件包含了非ASCII字符,导致Ansible出现以下错误:
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ValueError: All strings must be XML compatible: Unicode or ASCII, no NULL bytes or control characters
fatal: [10.10.10.111]: FAILED! => {"changed": false, "failed": true, "module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_FZ42iu/ansible_module_junos_config.py\", line 344, in <module>\n    main()\n  File \"/tmp/ansible_FZ42iu/ansible_module_junos_config.py\", line 335, in main\n    run(module, result)\n  File \"/tmp/ansible_FZ42iu/ansible_module_junos_config.py\", line 293, in run\n    return load_config(module, result)\n  File \"/tmp/ansible_FZ42iu/ansible_module_junos_config.py\", line 258, in load_config\n    diff = module.config.load_config(candidate, **kwargs)\n  File \"/tmp/ansible_FZ42iu/ansible_modlib.zip/ansible/module_utils/netcfg.py\", line 58, in load_config\n  File \"/tmp/ansible_FZ42iu/ansible_modlib.zip/ansible/module_utils/junos.py\", line 201, in load_config\n  File \"/usr/local/lib/python2.7/dist-packages/jnpr/junos/utils/config.py\", line 388, in load\n    return try_load(rpc_contents, rpc_xattrs)\n  File \"/usr/local/lib/python2.7/dist-packages/jnpr/junos/utils/config.py\", line 350, in try_load\n    got = self.rpc.load_config(rpc_contents, **rpc_xattrs)\n  File \"/usr/local/lib/python2.7/dist-packages/jnpr/junos/rpcmeta.py\", line 79, in load_config\n    rpc.append(E('configuration-text', contents))\n  File \"/usr/local/lib/python2.7/dist-packages/lxml/builder.py\", line 236, in __call__\n    v = t(elem, item)\n  File \"/usr/local/lib/python2.7/dist-packages/lxml/builder.py\", line 185, in add_text\n    elem.text = (elem.text or \"\") + item\n  File \"src/lxml/lxml.etree.pyx\", line 1031, in lxml.etree._Element.text.__set__ (src/lxml/lxml.etree.c:53225)\n  File \"src/lxml/apihelpers.pxi\", line 715, in lxml.etree._setNodeText (src/lxml/lxml.etree.c:24420)\n  File \"src/lxml/apihelpers.pxi\", line 703, in lxml.etree._createTextNode (src/lxml/lxml.etree.c:24283)\n  File \"src/lxml/apihelpers.pxi\", line 1443, in lxml.etree._utf8 (src/lxml/lxml.etree.c:31502)\nValueError: All strings must be XML compatible: Unicode or ASCII, no NULL bytes or control characters\n", "module_stdout": "", "msg": "MODULE FAILURE"}

我尝试在junos_config模块中使用# -*- coding: utf-8 -*-,但这没有帮助。我还尝试将Python的PYTHONIOENCODING设置为utf8junos_config模块的配置文件如下所示:
groups {
    replace: classes {
        /* Configured by Ansible £ */
        system {
            login {
                class test {
                    idle-timeout 1;
                    permissions network;
                    allow-commands "show route.*|quit|exit";
                    deny-commands .*;
                }
            }
        }
    }
}

当模块包含字符£时,会出现无法加载配置:所有字符串必须是XML兼容的:Unicode或ASCII,没有NULL字节或控制字符错误消息。
如何使junos_config(或lxml)支持非ASCII字符?

1
你能添加一个带有“坏”字符的示例配置文件吗? - Konstantin Suvorov
@KonstantinSuvorov 添加了一个带有“坏”字符的示例配置文件。如果我删除 £ 字符,则模块将正确运行。 - Martin
1
我会尝试强制使用Python3:http://docs.ansible.com/ansible/latest/python_3_support.html,考虑到这个检查:https://github.com/lxml/lxml/blob/572e10843774a5d6300125d89bdc423d53c92971/src/lxml/apihelpers.pxi#L1431 意味着lxml中没有Python2的UTF-8支持。 - lossleader
1
@lossleader 没错了,谢谢!您可以将您的评论发布为答案,这样我就可以接受了。 - Martin
2个回答

2
如果没有源代码、配置文件或有问题的字符串,我认为您的问题是一个非 ASCII 和非 UTF-8 字符。从错误信息中可以看出:

ValueError:所有字符串必须与 XML 兼容:Unicode 或 ASCII,没有 NULL 字节或控制字符

我猜测它是一个控制字符。经过一些调查,我发现了这个答案https://dev59.com/3Yfca4cB1Zd3GeqPlaPJ#28380315,也许它有帮助。使用 hexdump filename 命令可以检查是否存在空字节等问题。另一个解决方案是使用 gedit 重新创建/保存文件。在那里,您可以将所需的编码设置为 utf-8(至少适用于新文件)。

我在我的初始帖子中添加了一个junos_config模块配置文件的示例。 - Martin

1
很不幸,lxml在Python2中仅支持ASCII字符集,但在Python3中支持ASCII和UTF-8。幸运的是,Ansible-2.2包含了Python-3支持的技术预览版,所以如果启用Python3解释器,该模块应该可以正常工作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接