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