dbus_to_python() 只需要 1 个参数?
问题描述
我正在尝试通过 Python dbus
模块控制 firewalld
.
I'm attempting to control firewalld
via the Python dbus
module.
我想为我当前的运行时和我的永久配置添加一个 IP 地址到受信任区域.
I'd like to add an ip address to the trusted zone for both my current runtime as well as my permanent configuration.
这是 firewalld
的 dbus 接口的文档:http://manpages.ubuntu.com/manpages/wily/man5/firewalld.dbus.5.html
Here's the documentation for firewalld
's dbus interface:
http://manpages.ubuntu.com/manpages/wily/man5/firewalld.dbus.5.html
工作原理:运行时配置
我可以将它添加到运行时配置中,这样就可以了:
I'm able to add it to the runtime configuration just fine with this:
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)
很简单.
什么不起作用:永久配置
事实证明,将其添加到永久配置中更加困难.以下是我迄今为止以交互方式尝试过的方法:
Adding it to the permanent configuration has proved to be more difficult. Here's what I've tried so far interactively:
>>> 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')
完全相同的堆栈跟踪.
I also tried checking permanentProxy.getDescription()
, which returned the description as it should have, and I tried permanentProxy.setDescription('test')
which failed with the exact same stack trace as permanentProxy.addSource('aaa.xxx.yyy.zzz')
.
我会得出结论,错误在于 python dbus
模块并假设它以某种方式无法正确处理参数,除了 runtimeProxy.addSource('trusted', ip)
涉及两个参数并且可以完美运行.config.getZoneByName('trusted')
甚至和permanentProxy.addSource('aaa.xxx.yyy.zzz')`有相同的签名,正好一个字符串,完美运行.
I would jump to the conclusion that the bug lies in the python dbus
module and assume it somehow doesn't handle arguments properly, except for the fact that runtimeProxy.addSource('trusted', ip)
involved two arguments and works perfectly. config.getZoneByName('trusted')
even has the same signature as permanentProxy.addSource('aaa.xxx.yyy.zzz')`, exactly one string, and works perfectly.
所以也许我错过了一些奇怪的东西?但我不知道那会是什么......
So maybe there's something weird I'm missing? But I don't know what that would be...
我尝试了更多但没有成功的东西
我考虑了可能 addSource
应该在没有字符串参数的情况下调用的可能性,并且可能以某种方式或某种咖喱,所以我尝试了这个:
I considered the possibility that maybe addSource
is supposed to be called without the string argument at all and maybe curries somehow or something, so I tried this:
>>> 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 个参数,但还说我给了它两个参数(实际上我只给了它一个,那么如何无论如何它会想出两个吗?)
This is just even weirder now... I have one Traceback within another traceback insisting that I need to pass in at least 2 arguments, but also saying I gave it two arguments (and I actually only gave it one, so how'd it come up with two anyways?)
我又尝试了几件事但没有成功:
A few more things I tried without success:
>>> 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
并认为它需要更少的参数,但如果你给它更少的参数,比如它想要,它会通过那个错误的检查,然后它会正确解决并失败,因为你的参数不匹配.
This really seems like a bug in dbus
... somehow it's initially resolving addSource
incorrectly and thinking that it needs fewer arguments, but if you give it fewer arguments like it wants, it'll pass that erroneous check, and then it'll properly resolve and fail because your arguments don't match it.
这就是我的理论.有人看到我没有的东西吗?如果真的有的话,有什么方法可以解决这个错误吗?IE... 是否有某种我可以在 dbus 上使用的内部方法来强制它调用正确的方法?
That's my theory anyways. Is someone seeing something I'm not? Is there some way I can work around this bug, if there really is one? IE... is there some kind of internal method I can use on dbus that will force it to call the proper method?
解决方案
以下对我有用:
>>> 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
,可以看到源地址已按预期添加:
At this point, if I look in /etc/firewalld/zones/trusted.xml
, I can see that the source address has been added as expected:
<?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>
...表示我已成功更改持久化配置.
...indicating that I have successfully changed the persistent configuration.
如果我在第二个 get_object
调用中使用文字路径而不是 config.getZoneByName
的返回值,上述方法也有效.
The above also works if I use a literal path in the second get_object
call, instead of the return value from config.getZoneByName
.
为了它的价值,我正在跑步:
For what it's worth, I'm running:
- 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:
You're not seeing anything newer because you're on CentOS, rather than Fedora. It looks like the easiest way of solving this particular task may be to use the firewall
python module that ships with FirewallD. The following works for me on 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 执行此操作,如下所示:
Browsing through the source to the firewall.client
module, you can do this via straight dbus like this:
>>> zone = bus.get_object('org.fedoraproject.FirewallD1', path)
>>> settings = zone.getSettings()
>>> settings[11].append('192.168.20.0/24')
>>> zone.update(settings)
这个也在 CentOS 下工作得很好...但是你最好使用 firewall
模块.
This also works fine under CentOS...but you're much better off using the firewall
module.
相关文章