Browse Source

Improve handling of blocked servers.

- Detection improved
- Blocking reason is shown
- A de-block button is offered (implementation in smpl does not work now!)
- Prevent double server entries in Connections page

Improve implementation of API call "set_config".

De []<==>{} conversion of IPV6-IPs only for the INI file.
tags/0.6.0
shypike 16 years ago
parent
commit
ff7e09a467
  1. 6
      main/interfaces/Default/templates/connection_info.tmpl
  2. 6
      main/interfaces/Plush/templates/connection_info.tmpl
  3. 7
      main/interfaces/smpl/templates/connection_info.tmpl
  4. 5
      main/interfaces/smpl/templates/main.tmpl
  5. 8
      main/language/fr-fr.txt
  6. 10
      main/language/nl-du.txt
  7. 10
      main/language/us-en.txt
  8. 9
      main/sabnzbd/config.py
  9. 92
      main/sabnzbd/downloader.py
  10. 51
      main/sabnzbd/interface.py
  11. 6
      main/sabnzbd/scheduler.py

6
main/interfaces/Default/templates/connection_info.tmpl

@ -23,7 +23,11 @@ $T('logging'):
<ul>
<!--#for $server in $servers#-->
<li>
$server[0]:$server[1]: $server[2]<!--#if not $server[5]#--> ($T('server-blocked'))<!--#end if#-->
$server[0]:$server[1]: $server[2]
<!--#if not $server[5]#-->
<a href="./unblock_server?server=$server[0]:$server[1]&session=$session">($T('server-blocked'))</a>
&nbsp;&nbsp;$server[6]
<!--#end if#-->
<ul>
<!--#for $thrd in $server[3]#-->
<li>$T('thread') #$thrd[0] -&gt; $thrd[1] -&gt; $thrd[2] -&gt; $thrd[3]</li>

6
main/interfaces/Plush/templates/connection_info.tmpl

@ -17,7 +17,11 @@
<!--#if $servers#-->
<!--#for $server in $servers#-->
<fieldset class="EntryFieldSet">
<legend id="<!--#if int($server[4])#-->configbox_server_encrypted<!--#else#-->configbox_server_decrypted<!--#end if#-->">$server[0]:$server[1]:$server[2]<!--#if not $server[5]#--> ($T('server-blocked'))<!--#end if#-->
<legend id="<!--#if int($server[4])#-->configbox_server_encrypted<!--#else#-->configbox_server_decrypted<!--#end if#-->">$server[0]:$server[1]:$server[2]
<!--#if not $server[5]#-->
<a href="./unblock_server?server=$server[0]:$server[1]&session=$session">($T('server-blocked'))</a>
&nbsp;&nbsp;$server[6]
<!--#end if#-->
</legend>
<small><!--#if $server[3]#--><ol class="numbered_list">
<!--#for $thrd in $server[3]#-->

7
main/interfaces/smpl/templates/connection_info.tmpl

@ -15,7 +15,12 @@ $T('logging'):
<!--#for $server in $servers#-->
<li>
$server[0]:$server[1]: $server[2] <!--#if int($server[4])#--><img src="static/images/nuvola/kgpg.png" /><!--#end if#-->
<!--#if not $server[5]#--> ($T('server-blocked'))<!--#end if#-->
<!--#if not $server[5]#-->
<!--#set $srv_id= "unblock_server('" + $server[0] + "','" + str($server[1]) + "');"#-->
<a class="config" onClick="$srv_id">
($T('server-blocked'))</a>
&nbsp;&nbsp;$server[6]
<!--#end if#-->
<ul>
<!--#for $thrd in $server[3]#-->

5
main/interfaces/smpl/templates/main.tmpl

@ -711,6 +711,11 @@ function loadtitle() {
d.addErrback(handleServerError);
}
function unblock_server(host, port)
{
d = doSimpleXMLHttpRequest('connections/unblock_server?server='+host+':'+port+'&session='+session);
}
function getBookmarks()
{
d = doSimpleXMLHttpRequest('tapi?mode=newzbin&name=get_bookmarks&session='+session);

8
main/language/fr-fr.txt

@ -586,12 +586,14 @@ warn-noRead@1 Ne peut lire %s
error-except Exception ?
error-noInit@3 Echec de l'initialisation %s@%s:%s
error-serverFailed@4 Echec de la connexion à %s@%s:%s, message=%s
error-serverLogin@2 Echec de la connexion au serveur %s:%s
error-serverNoConn@3 Ne peut se connecter au serveur %s:%s [%s]
error-serverLogin@1 Echec de la connexion au serveur %s
error-serverNoConn@2 Ne peut se connecter au serveur %s [%s]
error-serverTooMany@2 Trop de connexions au serveur %s:%s
warn-ignoreServer@2 Le serveur %s sera ignoré pendant %s minutes
warn-noActiveServers Aucun serveur primaire défini, pas de téléchargement possible !
warn-noConnectServer@3 Impossible de se connecter au serveur %s:%s [%s]
warn-noConnectServer@2 Impossible de se connecter au serveur %s [%s]
error-accountSharing Probable account sharing
error-serverCred@1 Server %s requires user/password
warn-thread@3 Thread %s@%s:%s:
error-mailAuth Echec de l'autentification au serveur de mail
error-mailNoConn Echec de la connexion au serveur de mail

10
main/language/nl-du.txt

@ -146,7 +146,7 @@ thread Verbinding
emailResult Test resultaat email
lastWarnings Recentste meldingen
clearWarnings Wissen
server-blocked geblokkeerd
server-blocked Deblokkeren
# Configuration
configuration Instellingen
@ -582,12 +582,14 @@ warn-noRead@1 Kan %s niet lezen
error-except Exception?
error-noInit@3 Kan geen verbinding maken %s@%s:%s
error-serverFailed@4 Verbinding %s@%s:%s mislukt, bericht=%s
error-serverLogin@2 Kan niet aanmelden bij server %s:%s
error-serverNoConn@3 Kan geen verbinding maken met server %s:%s [%s]
error-serverLogin@1 Kan niet aanmelden bij server %s
error-serverNoConn@2 Kan geen verbinding maken met server %s [%s]
error-serverTooMany@2 Te veel verbindingen met server %s:%s
warn-ignoreServer@2 Server %s wordt gedurende %s minuten genegeerd
warn-noActiveServers Geen aktieve primaire servers, download niet mogelijk!
warn-noConnectServer@3 Kan geen verbinding maken met server %s:%s [%s]
warn-noConnectServer@2 Kan geen verbinding maken met server %s [%s]
error-accountSharing Mogelijk delen van account
error-serverCred@1 Server %s heeft gebruikersnaam/wachtwoord nodig
warn-thread@3 Verbinding %s@%s:%s:
error-mailAuth Kan niet aanmelden bij email server
error-mailNoConn Kan geen verbinding maken met email server

10
main/language/us-en.txt

@ -148,7 +148,7 @@ thread Thread
emailResult Email Test Result
lastWarnings Lastest Warnings
clearWarnings clear
server-blocked blocked
server-blocked Unblock
# Configuration
configuration Configuration
@ -582,12 +582,14 @@ warn-noRead@1 Cannot read %s
error-except Exception?
error-noInit@3 Failed to initialize %s@%s:%s
error-serverFailed@4 Connecting %s@%s:%s failed, message=%s
error-serverLogin@2 Failed login for server %s:%s
error-serverNoConn@3 Cannot connect to server %s:%s [%s]
error-serverLogin@1 Failed login for server %s
error-serverNoConn@2 Cannot connect to server %s [%s]
error-serverTooMany@2 Too many connections to server %s:%s
warn-ignoreServer@2 Server %s will be ignored for %s minutes
warn-noActiveServers No active primary servers defined, will not download!
warn-noConnectServer@3 Cannot connect to server %s:%s [%s]
warn-noConnectServer@2 Cannot connect to server %s [%s]
error-accountSharing Probable account sharing
error-serverCred@1 Server %s requires user/password
warn-thread@3 Thread %s@%s:%s:
error-mailAuth Failed to authenticate to mail server
error-mailNoConn Failed to connect to mail server

9
main/sabnzbd/config.py

@ -681,12 +681,13 @@ def save_config(force=False):
except:
CFG[section] = {}
for subsec in database[section]:
subsec_mod = subsec.replace('[', '{').replace(']','}')
try:
CFG[section][subsec]
CFG[section][subsec_mod]
except:
CFG[section][subsec] = {}
CFG[section][subsec_mod] = {}
items = database[section][subsec].get_dict()
CFG[section][subsec] = items
CFG[section][subsec_mod] = items
else:
for option in database[section]:
sec, kw = database[section][option].ident()
@ -727,7 +728,7 @@ def define_servers():
try:
for server in CFG['servers']:
svr = CFG['servers'][server]
ConfigServer(server, svr)
ConfigServer(server.replace('{', '[').replace('}', ']'), svr)
except KeyError:
pass

92
main/sabnzbd/downloader.py

@ -22,6 +22,7 @@ sabnzbd.downloader - download engine
import time
import select
import logging
import datetime
from threading import Thread
from nntplib import NNTPPermanentError
@ -162,6 +163,10 @@ def delayed():
global __DOWNLOADER
if __DOWNLOADER: return __DOWNLOADER.delayed
def unblock(server):
global __DOWNLOADER
if __DOWNLOADER: return __DOWNLOADER.unblock(server)
#------------------------------------------------------------------------------
class Server:
@ -185,6 +190,7 @@ class Server:
self.idle_threads = []
self.active = True
self.bad_cons = 0
self.errormsg = ''
for i in range(threads):
self.idle_threads.append(NewsWrapper(self, i+1))
@ -238,6 +244,7 @@ class Downloader(Thread):
self.write_fds = {}
self.servers = []
self._timers = {}
primary = False
for server in config.get_servers():
@ -292,7 +299,6 @@ class Downloader(Thread):
return primary
def stop(self):
self.shutdown = True
osx.sendGrowlMsg("SABnzbd",T('grwl-shutdown-begin-msg'),osx.NOTIFICATION['startup'])
@ -362,9 +368,9 @@ class Downloader(Thread):
# disable it now and send a re-enable plan to the scheduler
server.bad_cons = 0
server.active = False
self.init_server(server.id, None)
server.errormsg = T('warn-ignoreServer@2') % ('', _PENALTY_TIMEOUT)
logging.warning(T('warn-ignoreServer@2'), server.id, _PENALTY_TIMEOUT)
sabnzbd.scheduler.plan_server(self.init_server, [None, server.id], _PENALTY_TIMEOUT)
self.plan_server(server.id, _PENALTY_TIMEOUT)
if server.restart:
if not server.busy_threads:
@ -545,36 +551,46 @@ class Downloader(Thread):
penalty = 0
msg = error.response
ecode = msg[:3]
if ecode in ('481', '482', '381') or (ecode == '502' and clues_login(msg)):
logging.debug('Server login problem: %s, %s', ecode, msg)
if ((ecode in ('502', '400')) and clues_too_many(msg)) or \
(ecode == '481' and clues_too_many(msg)):
# Too many connections: remove this thread and reduce thread-setting for server
if server.active:
server.errormsg = T('error-serverTooMany@2') % ('', '')
logging.error(T('error-serverTooMany@2'), server.host, server.port)
self.__reset_nw(nw, None, warn=False, destroy=True)
server.threads -= 1
elif ecode in ('502', '481') and clues_too_many_ip(msg):
# Account sharing?
if server.active:
server.errormsg = T('error-accountSharing')
name = ' (%s:%s)' % (server.host, server.port)
logging.error(T('error-accountSharing') + name)
penalty = _PENALTY_SHARE
elif ecode in ('481', '482', '381') or (ecode == '502' and clues_login(msg)):
# Cannot login, block this server
if server.active:
logging.error(T('error-serverLogin@2'), server.host, server.port)
server.errormsg = T('error-serverLogin@1') % ''
logging.error(T('error-serverLogin@1'), '%s:%s' % (server.host, server.port))
block = True
elif (ecode in ('502', '400')) and clues_too_many(msg):
# Too many connections: remove this thread and reduce thread-setting for server
logging.error(T('error-serverTooMany@2'), server.host, server.port)
self.__reset_nw(nw, None, warn=False, destroy=True)
server.threads -= 1
elif (ecode == '502') and clues_too_many_ip(msg):
# Account sharing?
logging.info("Probable account sharing")
penalty = _PENALTY_SHARE
elif ecode == '502':
# Cannot connect (other reasons), block this server
if server.active:
logging.warning(T('warn-noConnectServer@3'), server.host, server.port, msg)
server.errormsg = T('warn-noConnectServer@2') % ('', msg)
logging.warning(T('warn-noConnectServer@2'), '%s:%s' % (server.host, server.port), msg)
penalty = _PENALTY_502
else:
# Unknown error, just keep trying
logging.error(T('error-serverNoConn@3'), server.host, server.port, msg)
penalty = _PENALTY_UNKNOWN
if server.active:
server.errormsg = T('error-serverNoConn@2') % ('', msg)
logging.error(T('error-serverNoConn@2'), '%s:%s' % (server.host, server.port, msg))
penalty = _PENALTY_UNKNOWN
if block or (penalty and server.optional):
if server.active:
server.active = False
self.init_server(server, None)
if penalty and server.optional:
logging.info('Server %s ignored for %s minutes', server.id, penalty)
sabnzbd.scheduler.plan_server(self.init_server, [None, server.id], penalty)
self.plan_server(server.id, penalty)
self.__reset_nw(nw, None, warn=False)
continue
except:
@ -610,7 +626,11 @@ class Downloader(Thread):
nw.server.port, article.article)
elif code == '480':
msg = 'Server %s:%s requires user/password' % (nw.server.host, nw.server.port)
if server.active:
server.active = False
server.errormsg = T('error-serverCred@1') % ''
self.plan_server(server.id, 0)
msg = T('error-serverCred@1') % ('%s:%s' % (nw.server.host, nw.server.port))
self.__reset_nw(nw, msg)
if done:
@ -699,6 +719,38 @@ class Downloader(Thread):
logging.error(T('error-except'))
self.__reset_nw(nw, "server broke off connection")
#------------------------------------------------------------------------------
# Timed restart of servers admin.
# For each server all planned events are kept in a list.
# When the first timer of a server fires, all other existing timers
# are neutralized.
# Each server has a dictionary entry, consisting of a list of timestamps.
def plan_server(self, server_id, interval):
""" Plan the restart of a server in 'interval' minutes """
logging.debug('Set planned server resume %s in %s mins', server_id, interval)
if server_id not in self._timers:
self._timers[server_id] = []
stamp = datetime.datetime.now()
self._timers[server_id].append(stamp)
if interval:
sabnzbd.scheduler.plan_server(self.trigger_server, [server_id, stamp], interval)
def trigger_server(self, server_id, timestamp):
""" Called by scheduler, start server if timer still valid """
logging.debug('Trigger planned server resume %s', server_id)
if server_id in self._timers:
if timestamp in self._timers[server_id]:
del self._timers[server_id]
self.init_server(server_id, server_id)
def unblock(self, server_id):
if server_id in self._timers:
logging.debug('Unblock server %s', server_id)
del self._timers[server_id]
self.init_server(server_id, server_id)
#------------------------------------------------------------------------------
def clues_login(text):

51
main/sabnzbd/interface.py

@ -245,6 +245,7 @@ _MSG_NO_FILE = 'no file given'
_MSG_NO_PATH = 'file does not exist'
_MSG_OUTPUT_FORMAT = 'Format not supported'
_MSG_NO_SUCH_CONFIG = 'Config item does not exist'
_MSG_BAD_SERVER_PARMS = 'Incorrect server settings'
def remove_callable(dic):
""" Remove all callable items from dictionary """
@ -483,9 +484,13 @@ class MainPage:
output = kwargs.get('output')
if mode == 'set_config':
res = config.set_config(kwargs)
if not res:
return report(output, _MSG_NO_SUCH_CONFIG)
if kwargs.get('section') == 'servers':
handle_server_api(output, kwargs)
else:
res = config.set_config(kwargs)
if not res:
return report(output, _MSG_NO_SUCH_CONFIG)
config.save_config()
if mode in ('get_config', 'set_config'):
res, data = config.get_dconfig(kwargs.get('section'), kwargs.get('keyword'))
@ -1766,9 +1771,7 @@ def handle_server(kwargs, root=None):
if msg:
return msg
# Replace square by curly brackets to avoid clash
# between INI format and IPV6 notation
server = '%s:%s' % (host.replace('[','{').replace(']','}'), port)
server = '%s:%s' % (host, port)
svr = None
old_server = kwargs.get('server')
@ -1793,6 +1796,31 @@ def handle_server(kwargs, root=None):
raise dcRaiser(root, kwargs)
def handle_server_api(output, kwargs):
""" Special handler for API-call 'set_config'
"""
name = kwargs.get('keyword')
if not name:
name = kwargs.get('name')
if not name:
host = kwargs.get('host')
port = kwargs.get('port', '119')
if host:
name = '%s:%s' % (host, port)
else:
return False
server = config.get_config('servers', name)
if server:
server.set_dict(kwargs)
old_name = name
else:
config.ConfigServer(name, kwargs)
old_name = None
downloader.update_server(old_name, name)
#------------------------------------------------------------------------------
class ConfigRss:
@ -2363,7 +2391,7 @@ class ConnectionInfo:
connected += 1
busy.sort()
header['servers'].append((server.host, server.port, connected, busy, server.ssl, server.active))
header['servers'].append((server.host, server.port, connected, busy, server.ssl, server.active, server.errormsg))
wlist = []
for w in sabnzbd.GUIHANDLER.content():
@ -2430,6 +2458,15 @@ class ConnectionInfo:
raise dcRaiser(self.__root, kwargs)
@cherrypy.expose
def unblock_server(self, **kwargs):
msg = check_session(kwargs)
if msg: return msg
downloader.unblock(kwargs.get('server'))
# Short sleep so that UI shows new server status
time.sleep(1.0)
raise dcRaiser(self.__root, kwargs)
def Protected():
return badParameterResponse("Configuration is locked")

6
main/sabnzbd/scheduler.py

@ -320,7 +320,7 @@ def pause_int():
#------------------------------------------------------------------------------
def plan_server(action, parms, penalty):
""" Plan to re-activate server after "penalty" minutes
def plan_server(action, parms, interval):
""" Plan to re-activate server after "interval" minutes
"""
__SCHED.add_single_task(action, '', penalty*60, kronos.method.sequential, parms, None)
__SCHED.add_single_task(action, '', interval*60, kronos.method.sequential, parms, None)

Loading…
Cancel
Save