292 lines
8.2 KiB
Python
292 lines
8.2 KiB
Python
|
from . import settings
|
||
|
|
||
|
|
||
|
class ServiceBackend(object):
|
||
|
"""
|
||
|
Service management backend base class
|
||
|
|
||
|
It uses the _unit of work_ design principle, which allows bulk operations to
|
||
|
be conviniently supported. Each backend generates the configuration for all
|
||
|
the changes of all modified objects, reloading the daemon just once.
|
||
|
"""
|
||
|
verbose_name = None
|
||
|
model = None
|
||
|
related_models = () # ((model, accessor__attribute),)
|
||
|
script_method = methods.BashSSH
|
||
|
function_method = methods.Python
|
||
|
type = 'task' # 'sync'
|
||
|
ignore_fields = []
|
||
|
|
||
|
# TODO type: 'script', execution:'task'
|
||
|
|
||
|
__metaclass__ = plugins.PluginMount
|
||
|
|
||
|
def __unicode__(self):
|
||
|
return type(self).__name__
|
||
|
|
||
|
def __str__(self):
|
||
|
return unicode(self)
|
||
|
|
||
|
def __init__(self):
|
||
|
self.cmds = []
|
||
|
|
||
|
@classmethod
|
||
|
def get_name(cls):
|
||
|
return cls.__name__
|
||
|
|
||
|
@classmethod
|
||
|
def is_main(cls, obj):
|
||
|
opts = obj._meta
|
||
|
return cls.model == '%s.%s' % (opts.app_label, opts.object_name)
|
||
|
|
||
|
@classmethod
|
||
|
def get_related(cls, obj):
|
||
|
opts = obj._meta
|
||
|
model = '%s.%s' % (opts.app_label, opts.object_name)
|
||
|
for rel_model, field in cls.related_models:
|
||
|
if rel_model == model:
|
||
|
related = obj
|
||
|
for attribute in field.split('__'):
|
||
|
related = getattr(related, attribute)
|
||
|
return related
|
||
|
return None
|
||
|
|
||
|
@classmethod
|
||
|
def get_backends(cls):
|
||
|
return cls.plugins
|
||
|
|
||
|
@classmethod
|
||
|
def get_choices(cls):
|
||
|
backends = cls.get_backends()
|
||
|
choices = ( (b.get_name(), b.verbose_name or b.get_name()) for b in backends )
|
||
|
return sorted(choices, key=lambda e: e[1])
|
||
|
|
||
|
def get_banner(self):
|
||
|
time = datetime.now().strftime("%h %d, %Y %I:%M:%S")
|
||
|
return "Generated by Orchestra %s" % time
|
||
|
|
||
|
def append(self, *cmd):
|
||
|
# aggregate commands acording to its execution method
|
||
|
if isinstance(cmd[0], basestring):
|
||
|
method = self.script_method
|
||
|
cmd = cmd[0]
|
||
|
else:
|
||
|
method = self.function_method
|
||
|
cmd = partial(*cmd)
|
||
|
if not self.cmds or self.cmds[-1][0] != method:
|
||
|
self.cmds.append((method, [cmd]))
|
||
|
else:
|
||
|
self.cmds[-1][1].append(cmd)
|
||
|
|
||
|
def execute(self, server):
|
||
|
from .models import BackendLog
|
||
|
state = BackendLog.STARTED if self.cmds else BackendLog.SUCCESS
|
||
|
log = BackendLog.objects.create(backend=self.get_name(), state=state, server=server)
|
||
|
for method, cmds in self.cmds:
|
||
|
method(log, server, cmds)
|
||
|
if log.state != BackendLog.SUCCESS:
|
||
|
break
|
||
|
return log
|
||
|
|
||
|
|
||
|
def ServiceController(ServiceBackend):
|
||
|
def save(self, obj)
|
||
|
raise NotImplementedError
|
||
|
|
||
|
def delete(self, obj):
|
||
|
raise NotImplementedError
|
||
|
|
||
|
def commit(self):
|
||
|
"""
|
||
|
apply the configuration, usually reloading a service
|
||
|
reloading a service is done in a separated method in order to reload
|
||
|
the service once in bulk operations
|
||
|
"""
|
||
|
pass
|
||
|
|
||
|
|
||
|
class ServiceMonitor(ServiceBackend):
|
||
|
TRAFFIC = 'traffic'
|
||
|
DISK = 'disk'
|
||
|
MEMORY = 'memory'
|
||
|
CPU = 'cpu'
|
||
|
|
||
|
def prepare(self):
|
||
|
pass
|
||
|
|
||
|
def store(self, stdout):
|
||
|
""" object_id value """
|
||
|
for line in stdout.readlines():
|
||
|
line = line.strip()
|
||
|
object_id, value = line.split()
|
||
|
# TODO date
|
||
|
MonitorHistory.store(self.model, object_id, value, date)
|
||
|
|
||
|
def monitor(self, obj):
|
||
|
raise NotImplementedError
|
||
|
|
||
|
def trigger(self, obj):
|
||
|
raise NotImplementedError
|
||
|
|
||
|
def execute(self, server):
|
||
|
log = super(MonitorBackend, self).execute(server)
|
||
|
|
||
|
return log
|
||
|
|
||
|
|
||
|
class AccountDisk(MonitorBackend):
|
||
|
model = 'accounts.Account'
|
||
|
resource = MonitorBackend.DISK
|
||
|
verbose_name = 'Disk'
|
||
|
|
||
|
def monitor(self, user):
|
||
|
context = self.get_context(user)
|
||
|
self.append("du -s %(home)s | {\n"
|
||
|
" read value\n"
|
||
|
" echo '%(username)s' $value\n"
|
||
|
"}" % context)
|
||
|
|
||
|
def process(self, output):
|
||
|
# TODO transaction
|
||
|
for line in output.readlines():
|
||
|
username, value = line.strip().slpit()
|
||
|
History.store(object_id=user_id, value=value)
|
||
|
|
||
|
|
||
|
class MailmanTraffic(MonitorBackend):
|
||
|
model = 'lists.List'
|
||
|
resource = MonitorBackend.TRAFFIC
|
||
|
|
||
|
def process(self, output):
|
||
|
for line in output.readlines():
|
||
|
listname, value = line.strip().slpit()
|
||
|
|
||
|
def monitor(self, mailinglist):
|
||
|
self.append("LISTS=$(grep -v 'post to mailman' /var/log/mailman/post"
|
||
|
" | grep size | cut -d'<' -f2 | cut -d'>' -f1 | sort | uniq"
|
||
|
" | while read line; do \n"
|
||
|
" grep \"$line\" post | head -n1 | awk {'print $8\" \"$11'}"
|
||
|
" | sed 's/size=//' | sed 's/,//'\n"
|
||
|
"done)")
|
||
|
self.append('SUBS=""\n'
|
||
|
'while read LIST; do\n'
|
||
|
' NAME=$(echo "$LIST" | awk {\'print $1\'})\n'
|
||
|
' SIZE=$(echo "$LIST" | awk {\'print $2\'})\n'
|
||
|
' if [[ ! $(echo -e "$SUBS" | grep "$NAME") ]]; then\n'
|
||
|
' SUBS="${SUBS}${NAME} $(list_members "$NAME" | wc -l)\n"\n'
|
||
|
' fi\n'
|
||
|
' SUBSCRIBERS=$(echo -e "$SUBS" | grep "$NAME" | awk {\'print $2\'})\n'
|
||
|
' echo "$NAME $(($SUBSCRIBERS*$SIZE))"\n'
|
||
|
'done <<< "$LISTS"')
|
||
|
|
||
|
|
||
|
class MailDisk(MonitorBackend):
|
||
|
model = 'email.Mailbox'
|
||
|
resource = MonitorBackend.DISK
|
||
|
verbose_name = _("Mail disk")
|
||
|
|
||
|
def process(self, output):
|
||
|
pass
|
||
|
|
||
|
def monitor(self, mail):
|
||
|
pass
|
||
|
|
||
|
|
||
|
class MysqlDisk(MonitorBackend):
|
||
|
model = 'database.Database'
|
||
|
resource = MonitorBackend.DISK
|
||
|
verbose_name = _("MySQL disk")
|
||
|
|
||
|
def process(self, output):
|
||
|
pass
|
||
|
|
||
|
def monitor(self, db):
|
||
|
pass
|
||
|
|
||
|
|
||
|
class OpenVZDisk(MonitorBackend):
|
||
|
model = 'vps.VPS'
|
||
|
resource = MonitorBackend.DISK
|
||
|
|
||
|
|
||
|
class OpenVZMemory(MonitorBackend):
|
||
|
model = 'vps.VPS'
|
||
|
resource = MonitorBackend.MEMORY
|
||
|
|
||
|
|
||
|
class OpenVZTraffic(MonitorBackend):
|
||
|
model = 'vps.VPS'
|
||
|
resource = MonitorBackend.TRAFFIC
|
||
|
|
||
|
|
||
|
class Apache2Traffic(MonitorBackend):
|
||
|
model = 'websites.Website'
|
||
|
resource = MonitorBackend.TRAFFIC
|
||
|
verbose_name = _("Apache2 Traffic")
|
||
|
|
||
|
def monitor(self, site):
|
||
|
context = self.get_context(site)
|
||
|
self.append("""
|
||
|
awk 'BEGIN {
|
||
|
ini = "%(start_date)s";
|
||
|
end = "%(end_date)s";
|
||
|
|
||
|
months["Jan"]="01";
|
||
|
months["Feb"]="02";
|
||
|
months["Mar"]="03";
|
||
|
months["Apr"]="04";
|
||
|
months["May"]="05";
|
||
|
months["Jun"]="06";
|
||
|
months["Jul"]="07";
|
||
|
months["Aug"]="08";
|
||
|
months["Sep"]="09";
|
||
|
months["Oct"]="10";
|
||
|
months["Nov"]="11";
|
||
|
months["Dec"]="12";
|
||
|
} {
|
||
|
date = substr($4,2)
|
||
|
year = substr(date,8,4)
|
||
|
month = months[substr(date,4,3)];
|
||
|
day = substr(date,1,2)
|
||
|
hour = substr(date,13,2)
|
||
|
minute = substr(date,16,2)
|
||
|
second = substr(date,19,2);
|
||
|
line_date = year month day hour minute second
|
||
|
if ( line_date > ini && line_date < end)
|
||
|
if ( $10 == "" )
|
||
|
sum+=$9
|
||
|
else
|
||
|
sum+=$10;
|
||
|
} END {
|
||
|
print sum;
|
||
|
}' %(log_file)s | {
|
||
|
read value
|
||
|
echo %(site_name)s $value
|
||
|
}
|
||
|
""" % context)
|
||
|
|
||
|
def trigger(self, site):
|
||
|
pass
|
||
|
|
||
|
def get_context(self, site):
|
||
|
return {
|
||
|
'log_file': os.path.join(settings.WEBSITES_BASE_APACHE_LOGS, site.unique_name)
|
||
|
|
||
|
}
|
||
|
|
||
|
# start_date and end_date expected format: YYYYMMDDhhmmss
|
||
|
|
||
|
function get_traffic(){
|
||
|
|
||
|
|
||
|
RESULT=$(get_traffic)
|
||
|
|
||
|
if [[ $RESULT ]]; then
|
||
|
echo $RESULT
|
||
|
else
|
||
|
echo 0
|
||
|
fi
|
||
|
|
||
|
return 0
|
||
|
|