django-orchestra/orchestra/apps/websites/resources.py
2014-07-08 15:19:15 +00:00

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