hostnames registration application for I2P
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

129 lines
3.5 KiB

#!/usr/bin/python
import os
import sys
import pwd
import argparse
import datetime
import time
import hashlib
import base64
import configobj
import daemon
import daemon.pidlockfile
from i2p import samclasses
from i2p import socket
def check():
all_hosts = i2phost.objects.all()
# determine SAM interface address
if 'sam_addr' in config:
sam_addr = config['sam_addr']
else:
log.warning('SAM address isn\'t specified in config, falling back to localhost')
sam_addr = '127.0.0.1:7656'
S = samclasses.BaseSession(sam_addr)
log.info('starting check')
for host in all_hosts:
log.debug('testing %s', host.name)
# get b32 address from full dest key
dest = host.b64hash
raw_key = base64.b64decode(dest.encode('utf-8'), '-~')
hash = hashlib.sha256(raw_key)
b32dest = base64.b32encode(hash.digest()).lower().replace('=', '')+'.b32.i2p'
# do name lookup query with b32 address
# it success only if host is alive
try:
a = S._namelookup(b32dest)
except socket.NetworkError, e:
log.debug('%s: %s', host.name, e.args[0][0])
continue
log.info('alive host: %s', host.name)
# update lastseen timestamp
host.last_seen = datetime.datetime.now()
host.save()
S.close()
log.info('check finished')
def main():
while True:
check()
if args.debug or args.verbose:
sys.exit(0)
else:
time.sleep(float(config['check_interval']))
# parse command line options
parser = argparse.ArgumentParser(
description='Hosts checker for py-i2phosts.',
epilog='Report bugs to http://zzz.i2p/topics/733')
parser.add_argument('-d', '--debug', action='store_true',
help='set loglevel to debug and write messages to stdout'),
parser.add_argument('-v', '--verbose', action='store_true',
help='set loglevel to info and write messages to stdout'),
parser.add_argument('-c', '--config', default='/etc/py-i2phosts/checker.conf', dest='config_file',
help='config file to use')
args = parser.parse_args()
# read config
config = configobj.ConfigObj(args.config_file)
if 'include' in config:
config_included = configobj.ConfigObj(config['include'])
config.merge(config_included)
# django setup
DJANGO_SETTINGS_MODULE = 'settings'
if 'DJANGO_PROJECT_PATH' in config:
DJANGO_PROJECT_PATH = config['DJANGO_PROJECT_PATH']
else:
DJANGO_PROJECT_PATH = os.path.dirname(sys.argv[0]) + '/web'
sys.path.insert(1, DJANGO_PROJECT_PATH)
os.environ['DJANGO_SETTINGS_MODULE'] = DJANGO_SETTINGS_MODULE
from web.postkey.models import i2phost
from web.lib.utils import get_logger
# configure logger
if args.debug == True:
log_level = 'debug'
log_file = None
elif args.verbose == True:
log_level = 'info'
log_file = None
else:
if 'log_level' in config:
log_level = config['log_level']
else:
sys.stderr.write('"log_level" missing in config\n')
sys.exit(1)
if 'log_file' in config:
log_file = config['log_file']
else:
sys.stderr.write('"log_file missing in config\n')
sys.exit(1)
if not args.debug and not args.verbose:
# get pid object for daemon
if 'pid_file' in config:
pid = daemon.pidlockfile.TimeoutPIDLockFile(config['pid_file'], 10)
else:
sys.stderr.write('"pid_file" missing in config\n')
sys.exit(1)
# create daemon context
d = daemon.DaemonContext(pidfile=pid, umask=077)
# write stderr to logfile # FIXME: and how we will deal with log rotation?
logfile = open(config['log_file'], 'a')
d.stderr = logfile
d.stdout = logfile
# drop privileges when started as root
if os.getuid() == 0:
runas = '_pyi2phosts'
pw_entry = pwd.getpwnam(runas)
d.uid = pw_entry[2]
d.gid = pw_entry[3]
d.open() # become daemon
log = get_logger(filename=log_file, log_level=log_level)
main()