233 lines
6.6 KiB
TypeScript
Executable File
233 lines
6.6 KiB
TypeScript
Executable File
#!/usr/bin/env ts-node
|
|
|
|
/**
|
|
* Script to initialize the four topology VLANs for the datacenter network
|
|
*
|
|
* VLANs to create:
|
|
* - VLAN 10: MGMT (10.10.10.0/24, gateway 10.10.10.1)
|
|
* - VLAN 20: VM-LAN (10.20.0.0/22, gateway 10.20.0.1)
|
|
* - VLAN 30: CEPH-PUBLIC (10.30.0.0/24, gateway 10.30.0.1)
|
|
* - VLAN 99: OOB-MGMT (10.99.99.0/24, gateway 10.99.99.1)
|
|
*
|
|
* Usage:
|
|
* ts-node scripts/init-topology-vlans.ts <siteId>
|
|
* or
|
|
* node dist/scripts/init-topology-vlans.js <siteId>
|
|
*/
|
|
|
|
import { createVlan } from '../src/services/vlanService';
|
|
import prisma from '../src/lib/db';
|
|
import logger from '../src/lib/logger';
|
|
import { OmadaVlanCreate } from '../src/types/omada';
|
|
|
|
interface TopologyVlan {
|
|
name: string;
|
|
vlanId: number;
|
|
subnet: string;
|
|
gateway: string;
|
|
description: string;
|
|
}
|
|
|
|
const TOPOLOGY_VLANS: TopologyVlan[] = [
|
|
{
|
|
name: 'MGMT',
|
|
vlanId: 10,
|
|
subnet: '10.10.10.0/24',
|
|
gateway: '10.10.10.1',
|
|
description: 'Proxmox host management, SSH, APIs',
|
|
},
|
|
{
|
|
name: 'VM-LAN',
|
|
vlanId: 20,
|
|
subnet: '10.20.0.0/22',
|
|
gateway: '10.20.0.1',
|
|
description: 'Default VM / container network',
|
|
},
|
|
{
|
|
name: 'CEPH-PUBLIC',
|
|
vlanId: 30,
|
|
subnet: '10.30.0.0/24',
|
|
gateway: '10.30.0.1',
|
|
description: 'Ceph "public" network (client/public side)',
|
|
},
|
|
{
|
|
name: 'OOB-MGMT',
|
|
vlanId: 99,
|
|
subnet: '10.99.99.0/24',
|
|
gateway: '10.99.99.1',
|
|
description: 'iDRAC/IPMI, PDUs, router mgmt, console',
|
|
},
|
|
];
|
|
|
|
async function initializeTopologyVlans(siteIdOrName: string): Promise<void> {
|
|
try {
|
|
logger.info('Starting topology VLAN initialization', { siteIdOrName });
|
|
|
|
// Find site in database
|
|
const site = await prisma.site.findFirst({
|
|
where: {
|
|
OR: [
|
|
{ id: siteIdOrName },
|
|
{ omadaSiteId: siteIdOrName },
|
|
{ name: siteIdOrName },
|
|
],
|
|
},
|
|
});
|
|
|
|
if (!site) {
|
|
throw new Error(`Site not found: ${siteIdOrName}`);
|
|
}
|
|
|
|
logger.info('Found site', { siteId: site.id, siteName: site.name, omadaSiteId: site.omadaSiteId });
|
|
|
|
const results = [];
|
|
|
|
for (const vlanConfig of TOPOLOGY_VLANS) {
|
|
try {
|
|
// Check if VLAN already exists in database
|
|
const existingVlan = await prisma.vlan.findFirst({
|
|
where: {
|
|
siteId: site.id,
|
|
vlanId: vlanConfig.vlanId,
|
|
},
|
|
});
|
|
|
|
if (existingVlan) {
|
|
logger.warn('VLAN already exists in database, skipping', {
|
|
vlanId: vlanConfig.vlanId,
|
|
vlanName: vlanConfig.name,
|
|
existingVlanId: existingVlan.id,
|
|
});
|
|
results.push({
|
|
vlan: vlanConfig.name,
|
|
status: 'skipped',
|
|
reason: 'Already exists in database',
|
|
});
|
|
continue;
|
|
}
|
|
|
|
// Create VLAN via Omada API
|
|
const omadaVlanConfig: OmadaVlanCreate = {
|
|
name: vlanConfig.name,
|
|
vlanId: vlanConfig.vlanId,
|
|
subnet: vlanConfig.subnet,
|
|
gateway: vlanConfig.gateway,
|
|
dhcpEnabled: false, // Disable DHCP by default, can be enabled later if needed
|
|
description: vlanConfig.description,
|
|
enabled: true,
|
|
};
|
|
|
|
logger.info('Creating VLAN', {
|
|
siteId: site.omadaSiteId,
|
|
vlanConfig: omadaVlanConfig,
|
|
});
|
|
|
|
const omadaVlan = await createVlan(site.omadaSiteId, omadaVlanConfig);
|
|
|
|
// Store in database
|
|
const dbVlan = await prisma.vlan.create({
|
|
data: {
|
|
omadaVlanId: omadaVlan.id,
|
|
siteId: site.id,
|
|
name: omadaVlan.name,
|
|
vlanId: vlanConfig.vlanId,
|
|
subnet: vlanConfig.subnet,
|
|
gateway: vlanConfig.gateway,
|
|
dhcpEnabled: false,
|
|
description: vlanConfig.description,
|
|
},
|
|
});
|
|
|
|
logger.info('VLAN created successfully', {
|
|
vlanId: vlanConfig.vlanId,
|
|
vlanName: vlanConfig.name,
|
|
dbVlanId: dbVlan.id,
|
|
});
|
|
|
|
results.push({
|
|
vlan: vlanConfig.name,
|
|
status: 'created',
|
|
vlanId: vlanConfig.vlanId,
|
|
dbVlanId: dbVlan.id,
|
|
});
|
|
|
|
// Log audit
|
|
await prisma.auditLog.create({
|
|
data: {
|
|
action: 'create_vlan',
|
|
targetType: 'site',
|
|
targetId: site.id,
|
|
details: {
|
|
siteName: site.name,
|
|
vlanName: vlanConfig.name,
|
|
vlanId: vlanConfig.vlanId,
|
|
script: 'init-topology-vlans',
|
|
},
|
|
},
|
|
});
|
|
} catch (error) {
|
|
logger.error('Error creating VLAN', {
|
|
vlanName: vlanConfig.name,
|
|
vlanId: vlanConfig.vlanId,
|
|
error: error instanceof Error ? error.message : String(error),
|
|
});
|
|
|
|
results.push({
|
|
vlan: vlanConfig.name,
|
|
status: 'error',
|
|
error: error instanceof Error ? error.message : String(error),
|
|
});
|
|
}
|
|
}
|
|
|
|
// Print summary
|
|
console.log('\n=== Topology VLAN Initialization Summary ===');
|
|
console.log(`Site: ${site.name} (${site.omadaSiteId})`);
|
|
console.log('\nResults:');
|
|
results.forEach((result) => {
|
|
if (result.status === 'created') {
|
|
console.log(` ✓ ${result.vlan} (VLAN ${result.vlanId}) - Created`);
|
|
} else if (result.status === 'skipped') {
|
|
console.log(` ⊘ ${result.vlan} - Skipped (${result.reason})`);
|
|
} else {
|
|
console.log(` ✗ ${result.vlan} - Error: ${result.error}`);
|
|
}
|
|
});
|
|
|
|
const successCount = results.filter((r) => r.status === 'created').length;
|
|
const skippedCount = results.filter((r) => r.status === 'skipped').length;
|
|
const errorCount = results.filter((r) => r.status === 'error').length;
|
|
|
|
console.log(`\nSummary: ${successCount} created, ${skippedCount} skipped, ${errorCount} errors`);
|
|
|
|
if (errorCount > 0) {
|
|
process.exit(1);
|
|
}
|
|
} catch (error) {
|
|
logger.error('Fatal error initializing topology VLANs', {
|
|
error: error instanceof Error ? error.message : String(error),
|
|
});
|
|
console.error('Error:', error instanceof Error ? error.message : String(error));
|
|
process.exit(1);
|
|
} finally {
|
|
await prisma.$disconnect();
|
|
}
|
|
}
|
|
|
|
// Main execution
|
|
const siteIdOrName = process.argv[2];
|
|
|
|
if (!siteIdOrName) {
|
|
console.error('Usage: ts-node scripts/init-topology-vlans.ts <siteId|siteName>');
|
|
console.error('\nExample:');
|
|
console.error(' ts-node scripts/init-topology-vlans.ts "Default"');
|
|
console.error(' ts-node scripts/init-topology-vlans.ts <omada-site-id>');
|
|
process.exit(1);
|
|
}
|
|
|
|
initializeTopologyVlans(siteIdOrName).catch((error) => {
|
|
console.error('Unhandled error:', error);
|
|
process.exit(1);
|
|
});
|
|
|