dbus_to_python() принимает ровно 1 аргумент?

Я пытаюсь управлять firewalld через модуль Python dbus.

Я хотел бы добавить IP-адрес в доверенную зону как для моей текущей среды выполнения, так и для моей постоянной конфигурации.

Вот документация по интерфейсу dbus firewalld: 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, который заставит его вызывать правильный метод?


person ArtOfWarfare    schedule 22.12.2015    source источник
comment
Глядя в источник... я нашел dbus.connection.Connection.call_blocking, который в строке 651 вызывает self.send_message_with_reply_and_block... который не определен в классе, поэтому должен быть унаследован от его суперкласса, _dbus_bindings.Connection... который мне не удалось найти источник пока. dbus.freedesktop.org/doc/dbus-python/api   -  person ArtOfWarfare    schedule 23.12.2015
comment
Я только что понял, что неудачное преобразование из dbus в python ... возможно, мой вызов проходит успешно, и он просто не сообщает мне, что он был успешным?   -  person ArtOfWarfare    schedule 23.12.2015


Ответы (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.

Что бы это ни стоило, я бегу:

  • Федора 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. Похоже, что самый простой способ решить эту конкретную задачу — использовать модуль firewall python, который поставляется с FirewallD. На 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.

person larsks    schedule 23.12.2015
comment
У меня dbus 1.6.12... yum не говорит, что доступно что-то новее. Модуль Python 1.1.1. firewalld — это 0.3.9 — также самая новая версия, доступная согласно yum. И CentOS 7. В любом случае, выполнение того же кода, что и вы, у меня не сработало - я получил еще одну трассировку стека dbus. Кроме того, файл, который вы упомянули, не существует. Все, что находится в каталоге /etc/firewalld/zones, это public.xml. Я обновлю несколько вещей и посмотрю, исправит ли это что-нибудь для меня. - person ArtOfWarfare; 23.12.2015
comment
Вы случайно не знаете, как мне обновиться до версии, которую вы используете? yum не позволяет мне обновляться, потому что, согласно ему, у меня уже есть самая новая версия... это говорит о том, что мне нужно добавить к ней другой репозиторий или что-то в этом роде. - person ArtOfWarfare; 23.12.2015
comment
Ваше обновление отлично работает для меня - спасибо! Все это кажется мне смехотворно недостаточно документированным - пока вы не упомянули об этом, я понятия не имел, что этот firewall модуль вообще существует. Как вы узнали, что он существует? - person ArtOfWarfare; 23.12.2015
comment
Я просмотрел исходный код /usr/bin/firewall-cmd, потому что, если вы ищете примеры API FirewallD, это хорошее место для начала. - person larsks; 23.12.2015
comment
Есть ли способ заменить dbus в моем первом примере (рабочий пример для временного доверия ip) на firewall? - person ArtOfWarfare; 23.12.2015
comment
Я только что понял, что есть также функция runtimeToPermanent(), которую определяет org.fedoraproject.FirewallD1... возможно, она просто использовалась. - person ArtOfWarfare; 23.12.2015