@@ -0,0 +1,35 @@
|
||||
"""Check configured infrastructure without changing production data."""
|
||||
import json,uuid
|
||||
from django.core.management.base import BaseCommand,CommandError
|
||||
from django.db import connection
|
||||
from django.db.migrations.executor import MigrationExecutor
|
||||
from django.core.cache import cache
|
||||
from config.celery import app
|
||||
|
||||
class Command(BaseCommand):
|
||||
help='Prüft Datenbank, Migrationen, Redis, Broker und optional Worker.'
|
||||
def add_arguments(self,p):p.add_argument('--workers',action='store_true')
|
||||
def handle(self,*args,**options):
|
||||
results={}
|
||||
try:
|
||||
with connection.cursor() as c:c.execute('SELECT 1');c.fetchone()
|
||||
results['database']=connection.vendor
|
||||
executor=MigrationExecutor(connection)
|
||||
pending=executor.migration_plan(executor.loader.graph.leaf_nodes())
|
||||
results['migrations']='pending' if pending else 'ok'
|
||||
except Exception as e:results['database']='ERROR '+type(e).__name__
|
||||
try:
|
||||
key='doctor:'+str(uuid.uuid4());cache.set(key,'ok',30)
|
||||
results['cache']='ok' if cache.get(key)=='ok' else 'ERROR readback'
|
||||
cache.delete(key)
|
||||
except Exception as e:results['cache']='ERROR '+type(e).__name__
|
||||
try:
|
||||
with app.connection_for_read() as conn:conn.ensure_connection(max_retries=0,timeout=5)
|
||||
results['broker']='ok'
|
||||
except Exception as e:results['broker']='ERROR '+type(e).__name__
|
||||
if options['workers']:
|
||||
try:results['workers']='ok' if app.control.ping(timeout=3) else 'ERROR no response'
|
||||
except Exception as e:results['workers']='ERROR '+type(e).__name__
|
||||
self.stdout.write(json.dumps(results,indent=2))
|
||||
if any(v.startswith('ERROR') or v=='pending' for v in results.values()):
|
||||
raise CommandError('Infrastrukturprüfung fehlgeschlagen; keine Zugangsdaten werden ausgegeben.')
|
||||
@@ -0,0 +1,20 @@
|
||||
import secrets
|
||||
from django.core.management.base import BaseCommand,CommandError
|
||||
from django.db import transaction
|
||||
from monitoring.models import Segment,Server,AgentCredential,Audit
|
||||
from monitoring.auth import digest
|
||||
class Command(BaseCommand):
|
||||
help='Register host or rotate its token; prints the secret once. Keep output private.'
|
||||
def add_arguments(self,p):
|
||||
p.add_argument('name');p.add_argument('--segment',required=True);p.add_argument('--address',default='');p.add_argument('--rotate',action='store_true')
|
||||
@transaction.atomic
|
||||
def handle(self,*args,**o):
|
||||
seg,_=Segment.objects.get_or_create(name=o['segment'])
|
||||
s,created=Server.objects.get_or_create(name=o['name'],defaults={'segment':seg,'address':o['address']})
|
||||
if not created and not o['rotate']: raise CommandError('Already registered; use --rotate to revoke old credentials')
|
||||
AgentCredential.objects.filter(server=s).update(active=False)
|
||||
token=secrets.token_urlsafe(48)
|
||||
AgentCredential.objects.create(server=s,digest=digest(token))
|
||||
Audit.objects.create(actor='management-command',action='register_agent',details={'server':str(s.pk),'rotated':not created})
|
||||
self.stdout.write('SERVER_ID='+str(s.pk))
|
||||
self.stdout.write('AGENT_TOKEN='+token)
|
||||
@@ -0,0 +1,23 @@
|
||||
import uuid
|
||||
from datetime import timedelta
|
||||
from django.core.management.base import BaseCommand,CommandError
|
||||
from django.utils import timezone
|
||||
from monitoring.models import Segment,Server,Event
|
||||
from monitoring.ingest import ingest
|
||||
from monitoring.tasks import evaluate_alarms
|
||||
class Command(BaseCommand):
|
||||
help='Create isolated, explicitly named demo servers. Never deletes real data.'
|
||||
def handle(self,*args,**kwargs):
|
||||
seg,_=Segment.objects.get_or_create(name='DEMO · Produktion',defaults={'cidr':'Demo-Netz'})
|
||||
for i,name in enumerate(['DEMO-django-01','DEMO-celery-01','DEMO-ai-01']):
|
||||
s,created=Server.objects.get_or_create(name=name,defaults={'segment':seg,'address':'Demodaten'})
|
||||
if not created: continue
|
||||
now=timezone.now();batch=[]
|
||||
for h in range(24):
|
||||
at=now-timedelta(hours=23-h)
|
||||
def event(kind,p):return {'id':uuid.uuid4(),'kind':kind,'occurred_at':at,'payload':p}
|
||||
batch.append(event('metric',{'cpu':89 if i==1 else 25+h%15,'ram':52+i*8,'disk':40+i*5,'services':{'django':True}}))
|
||||
batch.append(event('task-succeeded',{'uuid':str(uuid.uuid4()),'name':'demo.documents.index','hostname':name,'runtime':1.5+i}))
|
||||
ingest(s.pk,batch)
|
||||
evaluate_alarms()
|
||||
self.stdout.write('Demo servers created. Login with a separately created user.')
|
||||
Reference in New Issue
Block a user