1#!/usr/bin/env perl
2
3use strict;
4use warnings;
5
6our $home;
7
8BEGIN {
9  use FindBin;
10  FindBin::again();
11
12  $home = ($ENV{NETDISCO_HOME} || $ENV{HOME});
13
14  # try to find a localenv if one isn't already in place.
15  if (!exists $ENV{PERL_LOCAL_LIB_ROOT}) {
16      use File::Spec;
17      my $localenv = File::Spec->catfile($FindBin::RealBin, 'localenv');
18      exec($localenv, $0, @ARGV) if -f $localenv;
19      $localenv = File::Spec->catfile($home, 'perl5', 'bin', 'localenv');
20      exec($localenv, $0, @ARGV) if -f $localenv;
21
22      die "Sorry, can't find libs required for App::Netdisco.\n"
23        if !exists $ENV{PERLBREW_PERL};
24  }
25}
26
27BEGIN {
28  use Path::Class;
29
30  # stuff useful locations into @INC and $PATH
31  unshift @INC,
32    dir($FindBin::RealBin)->parent->subdir('lib')->stringify,
33    dir($FindBin::RealBin, 'lib')->stringify;
34}
35
36use App::Netdisco;
37use Dancer ':script';
38use Dancer::Plugin::DBIC 'schema';
39
40use App::Netdisco::JobQueue 'jq_insert';
41use App::Netdisco::Util::Device 'get_device';
42
43use NetAddr::IP::Lite ':lower';
44use Try::Tiny;
45
46=head1 NAME
47
48nd-import-topology - Import a Nedisco 1.x Manual Topology File
49
50=head1 USAGE
51
52 ~/bin/localenv nd-import-topology /path/to/netdisco-topology.txt
53
54=head1 DESCRIPTION
55
56This helper script will read and import the content of a Netdisco 1.x format
57Manual Topology file into the Netdisco 2.x database's C<topology> table.
58
59It's safe to run the script multiple times on the same file - any new data
60will be imported.
61
62The file syntax must be like so:
63
64 left-device
65   link:left-port,right-device,right-port
66
67The devices can be either host names or IPs. Data will be imported even if the
68devices are currently unknown to Netdisco. All imported devices will have a
69C<discover> job queued for them.
70
71=cut
72
73my $file = $ARGV[0];
74die "missing topology file name on command line\n" unless $file;
75
76chomp $file;
77my $dev = undef; # current device
78print "Loading topology information from $file\n";
79
80open (DEVS,'<', $file)
81  or die "topo_load_file($file): $!\n";
82
83while (my $line = <DEVS>) {
84    chomp $line;
85    $line =~ s/(?<!\\)#.*//;
86    $line =~ s/\\#/#/g;
87    $line =~ s/^\s+//g;
88    $line =~ s/\s+$//g;
89    next if $line =~ m/^\s*$/;
90
91    if ($line =~ m/^link:(.*)/){
92        my ($from_port, $to, $to_port) = split(m/,/, $1);
93
94        unless (defined $dev) {
95            print " Skipping $line. No device yet defined!\n";
96            next;
97        }
98
99        # save Link info
100        try {
101            schema('netdisco')->txn_do(sub {
102              schema('netdisco')->resultset('Topology')->create({
103                dev1  => $dev,
104                port1 => $from_port,
105                dev2  => get_device($to)->ip,
106                port2 => $to_port,
107              });
108            });
109        };
110    }
111    elsif ($line =~ /^alias:(.*)/) {
112        # ignore aliases
113    }
114    else {
115        my $ip = NetAddr::IP::Lite->new($line)
116          or next;
117        next if $ip->addr eq '0.0.0.0';
118
119        $dev = get_device($ip->addr)->ip;
120        print " Set device: $dev\n";
121
122        jq_insert({
123          action => 'discover',
124          device => $dev,
125        });
126    }
127}
128
129close (DEVS);
130