feat(infra): Phase 3 & 4 completion, deploy AWX playbooks & Zabbix monitoring
This commit is contained in:
183
scripts/setup_awx_resources.py
Normal file
183
scripts/setup_awx_resources.py
Normal file
@@ -0,0 +1,183 @@
|
||||
import paramiko
|
||||
|
||||
ssh = paramiko.SSHClient()
|
||||
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
ssh.connect('140.44.4.11', username='root', key_filename=r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet', timeout=10)
|
||||
|
||||
orm_provisioning_code = """
|
||||
from awx.main.models import (
|
||||
Organization, Inventory, Group, Host, Credential, Project, JobTemplate, Schedule
|
||||
)
|
||||
|
||||
# 1. Organization
|
||||
org, created = Organization.objects.get_or_create(name='Snarfnet Homelab', defaults={'description': 'Snarfnet Homelab Infrastructure Automation'})
|
||||
print(f"Organization: {org.name} (id={org.id}, created={created})")
|
||||
|
||||
# 2. Inventory
|
||||
inv, created = Inventory.objects.get_or_create(
|
||||
name='Snarfnet Master Inventory',
|
||||
defaults={'organization': org, 'description': 'Master Inventory across all 28 Homelab hosts'}
|
||||
)
|
||||
if not inv.organization:
|
||||
inv.organization = org
|
||||
inv.save()
|
||||
print(f"Inventory: {inv.name} (id={inv.id}, created={created})")
|
||||
|
||||
# 3. Groups & Hosts definition
|
||||
GROUPS = {
|
||||
'k3s_aerodrome_masters': {
|
||||
'vars': {'ansible_user': 'root', 'cluster': 'aerodrome', 'node_role': 'master'},
|
||||
'hosts': {
|
||||
'sninfr2lnxctl01': '140.44.4.11',
|
||||
'sninfr2lnxctl02': '140.44.4.12',
|
||||
'sninfr2lnxctl03': '140.44.4.13',
|
||||
}
|
||||
},
|
||||
'k3s_aerodrome_workers': {
|
||||
'vars': {'ansible_user': 'root', 'cluster': 'aerodrome', 'node_role': 'worker'},
|
||||
'hosts': {
|
||||
'sninfr2lnxwrk01': '140.44.4.21',
|
||||
'sninfr2lnxwrk02': '140.44.4.22',
|
||||
'sninfr2lnxwrk03': '140.44.4.23',
|
||||
'sninfr2lnxwrk04': '140.44.4.24',
|
||||
'sninfr2lnxwrk05': '140.44.4.25',
|
||||
'sninfr2lnxwrk06': '140.44.4.26',
|
||||
'sninfr2lnxwrk07': '140.44.4.27',
|
||||
}
|
||||
},
|
||||
'k3s_spaceport_masters': {
|
||||
'vars': {'ansible_user': 'root', 'cluster': 'spaceport', 'node_role': 'master'},
|
||||
'hosts': {
|
||||
'sninfr0lnxctl01': '140.44.4.41',
|
||||
'sninfr0lnxctl02': '140.44.4.42',
|
||||
'sninfr0lnxctl03': '140.44.4.43',
|
||||
'sninfr0lnxctl04': '140.44.4.44',
|
||||
}
|
||||
},
|
||||
'k3s_spaceport_workers': {
|
||||
'vars': {'ansible_user': 'root', 'cluster': 'spaceport', 'node_role': 'worker'},
|
||||
'hosts': {
|
||||
'sninfr0lnxwrk01': '140.44.4.51',
|
||||
'sninfr0lnxwrk02': '140.44.4.52',
|
||||
'sninfr0lnxwrk03': '140.44.4.53',
|
||||
'sninfr0lnxwrk04': '140.44.4.54',
|
||||
'sninfr0lnxwrk05': '140.44.4.55',
|
||||
'sninfr0lnxwrk06': '140.44.4.56',
|
||||
}
|
||||
},
|
||||
'swarm_shipyard': {
|
||||
'vars': {'ansible_user': 'snarf', 'ansible_become': True, 'cluster': 'shipyard'},
|
||||
'hosts': {
|
||||
'snshpd4lnxswm01': '140.44.4.71',
|
||||
'snshpd4lnxswm02': '140.44.4.72',
|
||||
'snshpd4lnxswm03': '140.44.4.73',
|
||||
'snshpd4lnxswm04': '140.44.4.74',
|
||||
'snshpd4lnxswm05': '140.44.4.75',
|
||||
}
|
||||
},
|
||||
'ai_pi_cluster': {
|
||||
'vars': {'ansible_user': 'snarf', 'ansible_become': True},
|
||||
'hosts': {
|
||||
'sninfr4lnxaih01': '140.44.4.7',
|
||||
'sninfr4lnxaih02': '140.44.4.8',
|
||||
}
|
||||
},
|
||||
'smart_home_nodes': {
|
||||
'vars': {'ansible_user': 'snarf', 'ansible_become': True},
|
||||
'hosts': {
|
||||
'homeassistant': '14.4.4.20',
|
||||
'nutserver': '14.4.4.44',
|
||||
}
|
||||
},
|
||||
'synology_nas': {
|
||||
'vars': {},
|
||||
'hosts': {
|
||||
'sn_nas': '14.10.10.71',
|
||||
'snarfnas': '14.10.10.72',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
import yaml
|
||||
for grp_name, data in GROUPS.items():
|
||||
grp, _ = Group.objects.get_or_create(name=grp_name, inventory=inv)
|
||||
grp.variables = yaml.dump(data.get('vars', {}))
|
||||
grp.save()
|
||||
|
||||
for h_name, ip in data.get('hosts', {}).items():
|
||||
h, _ = Host.objects.get_or_create(name=h_name, inventory=inv)
|
||||
h.variables = yaml.dump({'ansible_host': ip})
|
||||
h.save()
|
||||
if not grp.hosts.filter(id=h.id).exists():
|
||||
grp.hosts.add(h)
|
||||
|
||||
print(f"Total Hosts in '{inv.name}': {inv.hosts.count()}")
|
||||
print(f"Total Groups in '{inv.name}': {inv.groups.count()}")
|
||||
|
||||
# 4. Project
|
||||
proj, created = Project.objects.get_or_create(
|
||||
name='Snarfnet Infrastructure Playbooks',
|
||||
defaults={
|
||||
'organization': org,
|
||||
'scm_type': 'git',
|
||||
'scm_url': 'https://git.snarfnet.net/Snarf/SnarfCode.git',
|
||||
'scm_branch': 'main',
|
||||
'scm_clean': True,
|
||||
'scm_delete_on_update': True,
|
||||
'scm_update_on_launch': True,
|
||||
'description': 'Snarfnet Ansible Playbooks from local Gitea'
|
||||
}
|
||||
)
|
||||
print(f"Project: {proj.name} (id={proj.id}, created={created})")
|
||||
|
||||
# 5. Credentials lookup
|
||||
cred_root = Credential.objects.filter(name__icontains='root').first()
|
||||
cred_snarf = Credential.objects.filter(name__icontains='snarf').first()
|
||||
print(f"Root Credential: {cred_root.name if cred_root else 'None'}")
|
||||
print(f"Snarf Credential: {cred_snarf.name if cred_snarf else 'None'}")
|
||||
|
||||
# 6. Job Templates
|
||||
TEMPLATES = [
|
||||
{
|
||||
'name': 'Daily Drift & Agent Health Audit',
|
||||
'playbook': 'ansible/playbooks/daily_drift_audit.yml',
|
||||
'desc': 'Verifies time synchronization, Zabbix agent, and SSH access daily'
|
||||
},
|
||||
{
|
||||
'name': 'Weekly OS & Security Patching',
|
||||
'playbook': 'ansible/playbooks/weekly_os_patching.yml',
|
||||
'desc': 'Rolling serial-1 apt update and dist-upgrade with reboot verification'
|
||||
},
|
||||
{
|
||||
'name': 'Aerodrome K3s Pre-Upgrade Check',
|
||||
'playbook': 'ansible/playbooks/k3s_aerodrome_precheck.yml',
|
||||
'desc': 'Validates Aerodrome masters and creates on-demand etcd snapshot'
|
||||
}
|
||||
]
|
||||
|
||||
for t in TEMPLATES:
|
||||
jt, created = JobTemplate.objects.get_or_create(
|
||||
name=t['name'],
|
||||
defaults={
|
||||
'project': proj,
|
||||
'inventory': inv,
|
||||
'playbook': t['playbook'],
|
||||
'description': t['desc'],
|
||||
'job_type': 'run',
|
||||
}
|
||||
)
|
||||
if cred_root and not jt.credentials.filter(id=cred_root.id).exists():
|
||||
jt.credentials.add(cred_root)
|
||||
if cred_snarf and not jt.credentials.filter(id=cred_snarf.id).exists():
|
||||
jt.credentials.add(cred_snarf)
|
||||
print(f"Job Template: {jt.name} (id={jt.id}, created={created})")
|
||||
|
||||
print("AWX Provisioning Complete!")
|
||||
"""
|
||||
|
||||
cmd = f"kubectl exec -i -n awx -c awx-task deployment/awx-task -- awx-manage shell_plus --quiet << 'EOF'\n{orm_provisioning_code}\nEOF"
|
||||
stdin, stdout, stderr = ssh.exec_command(cmd)
|
||||
print(stdout.read().decode())
|
||||
print(stderr.read().decode())
|
||||
|
||||
ssh.close()
|
||||
Reference in New Issue
Block a user