LoveIsGrief eb28f47053
i2p: Add helper to modify the tunnel config
We will want to set the 'interface' property of certain tunnels to 0.0.0.0 and
the handle the rest with the firewall. This is just prep to do so.

Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
2019-04-29 14:58:38 -07:00

120 lines
3.6 KiB
Python

# This file is part of FreedomBox.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import os
import re
import augeas
I2P_CONF_DIR = '/var/lib/i2p/i2p-config'
FILE_TUNNEL_CONF = os.path.join(I2P_CONF_DIR, 'i2ptunnel.config')
TUNNEL_IDX_REGEX = re.compile(r'tunnel.(\d+).name$')
class TunnelEditor(object):
"""
:type aug: augeas.Augeas
"""
def __init__(self, conf_filename=None, idx=None):
self.conf_filename = conf_filename or FILE_TUNNEL_CONF
self.idx = idx
self.aug = None
@property
def lines(self):
if self.aug:
return self.aug.match('/files{}/*'.format(self.conf_filename))
else:
return []
def read_conf(self):
"""Return an instance of Augeaus for processing APT configuration."""
self.aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
augeas.Augeas.NO_MODL_AUTOLOAD)
self.aug.set('/augeas/load/Properties/lens', 'Properties.lns')
self.aug.set('/augeas/load/Properties/incl[last() + 1]', self.conf_filename)
self.aug.load()
return self
def write_conf(self):
self.aug.save()
return self
def set_tunnel_idx(self, name):
"""
Finds the index of the tunnel with the given name.
Chainable method.
:type name: basestring
"""
for prop in self.aug.match('/files{}/*'.format(self.conf_filename)):
match = TUNNEL_IDX_REGEX.search(prop)
if match and self.aug.get(prop) == name:
self.idx = int(match.group(1))
return self
raise ValueError('No tunnel with that name')
def calc_prop_path(self, tunnel_prop):
"""
Calculates the property name as found in the properties files
:type tunnel_prop: str
:rtype: basestring
"""
calced_prop_path = '/files{filepath}/tunnel.{idx}.{tunnel_prop}'.format(
idx=self.idx, tunnel_prop=tunnel_prop,
filepath=self.conf_filename
)
return calced_prop_path
def set_tunnel_prop(self, tunnel_prop, value):
"""
Updates a tunnel's property.
The idx has to be set and the property has to exist in the config file and belong to the tunnel's properties.
see calc_prop_path
Chainable method.
:param tunnel_prop:
:type tunnel_prop: str
:param value:
:type value: basestring | int
:return:
:rtype:
"""
if self.idx is None:
raise ValueError('Please init the tunnel index before calling this method')
calc_prop_path = self.calc_prop_path(tunnel_prop)
self.aug.set(calc_prop_path, value)
return self
def __getitem__(self, tunnel_prop):
ret = self.aug.get(self.calc_prop_path(tunnel_prop))
if ret is None:
raise KeyError('Unknown property {}'.format(tunnel_prop))
return ret
def __setitem__(self, tunnel_prop, value):
self.aug.set(self.calc_prop_path(tunnel_prop), value)