Initial commit: add .gitignore and README
This commit is contained in:
232
scripts/init-topology-vlans.ts
Executable file
232
scripts/init-topology-vlans.ts
Executable file
@@ -0,0 +1,232 @@
|
||||
#!/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);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user