source: trunk/cgi-bin/consistency-check.pl@ 905

Last change on this file since 905 was 901, checked in by Kris Deugau, 8 years ago

/trunk

Major update to consistency-check.pl due to ongoing changes in back end

  • Property svn:executable set to *
  • Property svn:keywords set to Date Rev Author
File size: 4.6 KB
Line 
1#!/usr/bin/perl
2# ipdb/cgi-bin/consistency-check.pl
3# Does full check to see if the data in the db is consistent and complete.
4# Note this can't account for slightly squirrelly or pretzelly legacy data;
5# that has to be hand-verified when this script chokes on it and spits up
6# errors.
7###
8# SVN revision info
9# $Date: 2017-02-10 17:01:25 +0000 (Fri, 10 Feb 2017) $
10# SVN revision $Rev: 901 $
11# Last update by $Author: kdeugau $
12###
13# Copyright (C) 2004-2010,2014,2017 - Kris Deugau
14
15use strict;
16use warnings;
17
18use DBI;
19use NetAddr::IP;
20use Data::Dumper;
21
22# don't remove! required for GNU/FHS-ish install from tarball
23##uselib##
24
25use MyIPDB;
26
27# Convenience for calling from admin tools
28print "Content-type: text/plain\n\n";
29
30my ($dbh,$errstr) = connectDB_My;
31die $errstr if !$dbh;
32# May as well. We need a number of globals.
33initIPDBGlobals($dbh);
34
35my %idlist;
36my $sth = $dbh->prepare("SELECT id FROM allocations WHERE type='mm' ORDER BY cidr");
37$sth->execute;
38while (my ($mid) = $sth->fetchrow_array) {
39 checkcontainer($mid, \%idlist, 0);
40}
41
42print "\nChecking that all allocations are referenced:\n";
43$sth = $dbh->prepare("SELECT id FROM allocations");
44$sth->execute;
45my $i = 0;
46while (my ($id) = $sth->fetchrow_array) {
47 delete $idlist{$id};
48 $i++;
49}
50print " $i allocations confirmed referenced\n";
51$i = 0;
52$sth = $dbh->prepare("SELECT id FROM freeblocks");
53$sth->execute;
54while (my ($id) = $sth->fetchrow_array) {
55 delete $idlist{'fb'.$id};
56 $i++;
57}
58print " $i freeblocks confirmed referenced\n";
59foreach (keys %idlist) {
60 if (/^fb/) {
61 print " Unreferenced free block ID $_, $idlist{$_}\n";
62 } else {
63 print " Unreferenced block ID $_, $idlist{$_}\n";
64 }
65}
66
67print "\nChecking for correctness on 'defined' CustIDs:\n";
68$sth = $dbh->prepare("SELECT cidr,type,custid FROM allocations WHERE NOT (type='cn' OR type LIKE '_r') ORDER BY cidr");
69$sth->execute;
70while (my($cidr,$type,$custid) = $sth->fetchrow_array) {
71 print "$cidr ($disp_alloctypes{$type}) has incorrect CustID $custid\n"
72 if $custid ne $def_custids{$type};
73}
74print "Done predefined CustID correctness check.\n\n";
75
76print "Checking for customer blocks with 'bad' CustIDs:\n";
77# Make sure cn-type ("customer netblock") blocks have "real" CustIDs.
78$sth = $dbh->prepare("SELECT cidr,custid,description FROM allocations WHERE type='cn' AND (custid='$IPDB::defcustid' OR custid='STAFF') ORDER BY cidr");
79$sth->execute;
80while (my ($cidr,$custid,$desc) = $sth->fetchrow_array) {
81 print "cn block $cidr ($desc) has incorrect CustID $custid\n";
82}
83print "Done checking customer blocks\n";
84
85exit;
86
87
88# All we need to check on is "do the allocations and free blocks within a container completely make up the container?"
89sub checkcontainer {
90 my $cid = shift;
91 my $idlist = shift;
92 my $depth = shift;
93
94 # snarf the container's CIDR
95 my $sth = $dbh->prepare("SELECT cidr,type FROM allocations WHERE id = ?");
96 $sth->execute($cid);
97 my ($ccidr,$ctype) = $sth->fetchrow_array();
98 # note that we've "seen" the ID/CIDR
99 $idlist->{$cid} = $ccidr;
100 $ccidr = NetAddr::IP->new($ccidr);
101
102 $depth++;
103 print "error: gone too deep ($depth). breaking off\n" if $depth > 6;
104 my $indent = ' ' x $depth;
105 print $indent."Checking $disp_alloctypes{$ctype} $ccidr ($cid)\n";
106
107 $sth = $dbh->prepare(qq(
108 SELECT id, cidr, type, network(cidr) AS net, broadcast(cidr) AS bcast FROM allocations WHERE parent_id = ?
109 UNION
110 SELECT id, cidr, 'f' AS type, network(cidr) AS net, broadcast(cidr) AS bcast FROM freeblocks WHERE parent_id = ?
111 ORDER BY cidr
112 ));
113 $sth->execute($cid, $cid) or die $dbh->errstr;
114 my $prev = $ccidr;
115 while (my ($childid, $childcidr, $childtype, $childnet, $childbcast) = $sth->fetchrow_array) {
116 # note that we've "seen" the ID/CIDR, flagging freeblocks
117 $idlist->{$childid} = $childcidr if $childtype ne 'f';
118 $idlist->{'fb'.$childid} = $childcidr if $childtype eq 'f';
119 checkcontainer($childid, $idlist, $depth) if $childtype =~ /.[cm]/;
120 my $prevn = $prev->broadcast->numeric + 1;
121 my $cur = new NetAddr::IP $childnet;
122 if ($cur->numeric == $prevn) {
123 $prev = $cur;
124 next;
125 }
126 if ($ccidr->numeric == $prev->numeric) {
127 # check if cur starts with master
128 if ($cur->numeric > $prev->numeric) {
129 print $indent." Gap from start of parent $ccidr to first block $cur\n";
130 } elsif ($cur->numeric < $prev->numeric) {
131 print $indent." BIG problem! Current block $cur begins before parent $ccidr!\n";
132 }
133 } else {
134 if ($cur->numeric < ($prev->numeric + 1)) {
135 print $indent." Block ".$prev->network." overlaps block $cur\n";
136 } elsif ($cur->numeric > ($prev->numeric + 1)) {
137 print $indent." Gap between end of block ".$prev->network." and block $cur\n";
138 }
139 }
140
141 $prev = $cur;
142 $prev--;
143 }
144}
Note: See TracBrowser for help on using the repository browser.