dbus_to_python() 只需要 1 个参数?

Posted

技术标签:

【中文标题】dbus_to_python() 只需要 1 个参数?【英文标题】:dbus_to_python() takes exactly 1 argument? 【发布时间】:2016-03-29 04:49:57 【问题描述】:

我正在尝试通过 Python dbus 模块控制 firewalld

我想为我当前的运行时和我的永久配置添加一个 IP 地址到受信任区域。

这是firewalld的dbus接口的文档: http://manpages.ubuntu.com/manpages/wily/man5/firewalld.dbus.5.html

工作原理:运行时配置

我可以将它添加到运行时配置中,这样就可以了:

def trustIP(ip):
    ''' firewalld must already be running '''
    from dbus import SystemBus
    bus = SystemBus()
    runtimeProxy = bus.get_object('org.fedoraproject.FirewallD1',
                                 '/org/fedoraproject/FirewallD1')
    runtimeProxy.addSource('trusted', ip)

很简单。

什么不起作用:永久配置

事实证明,将其添加到永久配置中更加困难。以下是我迄今为止以交互方式尝试过的方法:

>>> from dbus import SystemBus
>>> bus = SystemBus()

# First I need to find out which object is for the trusted zone...
>>> config = bus.get_object('org.fedoraproject.FirewallD1',
                           '/org/fedoraproject/FirewallD1/config')
>>> config.getZoneByName('trusted')
dbus.ObjectPath('/org/fedoraproject/FirewallD1/config/zone/7')

>>> permanentProxy = bus.get_object('org.fedoraproject.FirewallD1', 
                                   '/org/fedoraproject/FirewallD1/config/zone/7')

# A quick check to make sure I have the right object:
>>> permanentProxy.getShort()
dbus.String(u'Trusted')

# Exactly what I expected, so move on and...
>>> permanentProxy.addSource('aaa.xxx.yyy.zzz')  # Actual ip removed...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/site-packages/dbus/proxies.py", line 145, in __call__
    **keywords)
  File "/usr/lib64/python2.7/site-packages/dbus/connection.py", line 651, in call_blocking
    message, timeout)
dbus.exceptions.DBusException:
    org.freedesktop.DBus.Python.dbus.exceptions.DBusException:
        dbus_to_python() takes exactly 1 argument (2 given)

我还尝试检查permanentProxy.getDescription(),它返回了应有的描述,我尝试了permanentProxy.setDescription('test'),它失败了,堆栈跟踪与permanentProxy.addSource('aaa.xxx.yyy.zzz')完全相同。

我会得出这样的结论,即错误存在于 python dbus 模块中,并假设它以某种方式无法正确处理参数,除了 runtimeProxy.addSource('trusted', ip) 涉及两个参数并且工作正常的事实。 config.getZoneByName('trusted') 甚至和permanentProxy.addSource('aaa.xxx.yyy.zzz')`有相同的签名,正好是一个字符串,完美运行。

所以也许我错过了一些奇怪的东西?但我不知道那会是什么......

我尝试了更多但没有成功的东西

我考虑过可能addSource 应该在没有字符串参数的情况下被调用,并且可能会以某种方式进行咖喱,所以我尝试了这个:

>>> permanentProxy.addSource()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/site-packages/dbus/proxies.py", line 145, in __call__
    **keywords)
  File "/usr/lib64/python2.7/site-packages/dbus/connection.py", line 651, in call_blocking
    message, timeout)
dbus.exceptions.DBusException: org.freedesktop.DBus.Python.TypeError: Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/slip/dbus/service.py", line 123, in reply_handler
    result = method(self, *p, **k)
TypeError: addSource() takes at least 2 arguments (2 given)

这现在更奇怪了...我在另一个回溯中有一个回溯坚持我需要传递至少 2 个参数,但还说我给了它两个参数(实际上我只给了它一个,那么如何无论如何它会想出两个吗?)

我又尝试了几件事但没有成功:

>>> permanentProxy.addSource(dbus_interface='org.fedoraproject.FirewallD1.config.zone')
ERROR:dbus.connection:Unable to set arguments () according to signature u's': <type 'exceptions.TypeError'>: More items found in D-Bus signature than in Python arguments
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/site-packages/dbus/proxies.py", line 145, in __call__
    **keywords)
  File "/usr/lib64/python2.7/site-packages/dbus/connection.py", line 641, in call_blocking
    message.append(signature=signature, *args)
TypeError: More items found in D-Bus signature than in Python arguments

>>> permanentProxy.addSource('aaa.xxx.yyy.zzz', dbus_interface='org.fedoraproject.FirewallD1.config.zone')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/site-packages/dbus/proxies.py", line 145, in __call__
    **keywords)
  File "/usr/lib64/python2.7/site-packages/dbus/connection.py", line 651, in call_blocking
    message, timeout)
dbus.exceptions.DBusException:
    org.freedesktop.DBus.Python.dbus.exceptions.DBusException:
        dbus_to_python() takes exactly 1 argument (2 given)

>>> from dbus import Interface
>>> Interface(permanentProxy, 'org.fedoraproject.FirewallD1.config.zone').addSource('aaa.xxx.yyy.zzz')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/site-packages/dbus/proxies.py", line 145, in __call__
    **keywords)
  File "/usr/lib64/python2.7/site-packages/dbus/connection.py", line 651, in call_blocking
    message, timeout)
dbus.exceptions.DBusException:
    org.freedesktop.DBus.Python.dbus.exceptions.DBusException:
        dbus_to_python() takes exactly 1 argument (2 given)

啊!

这看起来确实像 dbus 中的一个错误...不知何故它最初错误地解析了 addSource 并认为它需要更少的参数,但是如果你给它更少的参数,它会通过那个错误的检查,然后它会正确解决并失败,因为您的参数不匹配。

这就是我的理论。有人看到我没有的东西吗?如果真的有的话,有什么方法可以解决这个错误吗? IE... 是否有某种我可以在 dbus 上使用的内部方法来强制它调用正确的方法?

【问题讨论】:

查看源代码...我找到了dbus.connection.Connection.call_blocking,它在第651行调用self.send_message_with_reply_and_block...它没有在类上定义,因此必须从其超类@987654341继承@... 我还没有设法找到来源。 dbus.freedesktop.org/doc/dbus-python/api 我刚刚意识到失败的转换是从 dbus 到 python...也许我的调用是成功的,只是没有告诉我它已经成功? 【参考方案1】:

以下对我有用:

>>> import dbus
>>> bus = dbus.SystemBus()
>>> config = bus.get_object('org.fedoraproject.FirewallD1',
...                            '/org/fedoraproject/FirewallD1/config')
>>> path = config.getZoneByName('trusted')
>>> zone = bus.get_object('org.fedoraproject.FirewallD1', path)
>>> zone.addSource('192.168.1.0/24')

此时,如果我查看/etc/firewalld/zones/trusted.xml,可以看到源地址已按预期添加:

<?xml version="1.0" encoding="utf-8"?>
<zone target="ACCEPT">
  <short>Trusted</short>
  <description>All network connections are accepted.</description>
  <interface name="docker0"/>
  <interface name="virbr0"/>
  <source address="192.168.1.0/24"/>
</zone>

...表示我已成功更改持久化配置。

如果我在第二个 get_object 调用中使用文字路径而不是 config.getZoneByName 的返回值,上述方法也有效。

为了它的价值,我正在跑步:

Fedora 23 firewalld-0.3.14.2-4.fc23.noarch dbus-1.10.6-1.fc23.x86_64 dbus-python-1.2.0-12.fc23.x86_64

更新

您没有看到任何更新,因为您使用的是 CentOS,而不是 Fedora。看起来解决这个特定任务的最简单方法可能是使用 FirewallD 附带的firewall python 模块。以下适用于 CentOS 7:

>>> from firewall.client import *
>>> client = FirewallClient()
>>> zone = client.config().getZoneByName('public')
>>> settings = zone.getSettings()
>>> settings.addSource('192.168.1.0/24')
>>> zone.update(settings)

另一个更新

浏览firewall.client模块的源代码,您可以像这样通过直接dbus做到这一点:

>>> zone = bus.get_object('org.fedoraproject.FirewallD1', path)
>>> settings = zone.getSettings()
>>> settings[11].append('192.168.20.0/24')
>>> zone.update(settings)

这个在 CentOS 下工作得很好...但是你最好使用 firewall 模块。

【讨论】:

我有 dbus 1.6.12... yum 没有说有什么更新的可用。 Python 模块是 1.1.1。 firewalld 是 0.3.9 - 也是 yum 提供的最新版本。还有 CentOS 7。无论如何,执行与您没有为我工作的完全相同的代码 - 我得到了另一个 dbus 堆栈跟踪。此外,您提到的文件不存在。 /etc/firewalld/zones 目录中的所有内容都是public.xml。我会更新一些东西,看看是否能为我解决任何问题。 您知道我如何更新到您正在使用的版本吗? yum 不让我更新,因为据它说,我已经有了最新版本......这表明我需要向它添加不同的存储库或其他东西。 您的更新非常适合我 - 谢谢!在我看来,这些东西的记录都非常荒谬——在你提到它之前,我不知道这个 firewall 模块甚至存在。你怎么知道它存在? 我查看了 /usr/bin/firewall-cmd 的源代码,因为如果您正在寻找 FirewallD API 的示例,那似乎是一个不错的起点。 有没有办法将我的第一个示例(临时信任 ip 的工作示例)中的 dbus 替换为 firewall

以上是关于dbus_to_python() 只需要 1 个参数?的主要内容,如果未能解决你的问题,请参考以下文章

"HK"日常之制作一只QQ刷屏

JavaScript 之 call apply bind

C++ STL transform 函数说明

卷积的参数计算

echarts中颜色渐变写法

9.2