From: ivan Date: Sat, 20 Apr 2002 11:57:36 +0000 (+0000) Subject: working BIND import X-Git-Tag: freeside_1_4_0_pre12~33 X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=commitdiff_plain;h=4d5485150720c91d9945c3ae3cad9427ece23833 working BIND import --- diff --git a/FS/FS/domain_record.pm b/FS/FS/domain_record.pm index 24db4c2f4..6f4dd0287 100644 --- a/FS/FS/domain_record.pm +++ b/FS/FS/domain_record.pm @@ -114,7 +114,7 @@ sub check { $self->recaf =~ /^(IN)$/ or return "Illegal recaf: ". $self->recaf; $self->recaf($1); - $self->rectype =~ /^(SOA|NS|MX|A|PTR|CNAME)$/ + $self->rectype =~ /^(SOA|NS|MX|A|PTR|CNAME|_mstr)$/ or return "Illegal rectype (only SOA NS MX A PTR CNAME recognized): ". $self->rectype; $self->rectype($1); @@ -148,6 +148,9 @@ sub check { $self->recdata =~ /^([a-z0-9\.\-]+)$/i or return "Illegal data for CNAME record: ". $self->recdata; $self->recdata($1); + } elsif ( $self->rectype eq '_mstr' ) { + $self->recdata =~ /^((\d{1,3}\.){3}\d{1,3})$/ + or return "Illegal data for _master pseudo-record: ". $self->recdata; } else { die "ack!"; } @@ -159,7 +162,7 @@ sub check { =head1 VERSION -$Id: domain_record.pm,v 1.6 2002-04-20 10:49:33 ivan Exp $ +$Id: domain_record.pm,v 1.7 2002-04-20 11:57:35 ivan Exp $ =head1 BUGS diff --git a/FS/FS/part_export.pm b/FS/FS/part_export.pm index 406b270ed..49e21307b 100644 --- a/FS/FS/part_export.pm +++ b/FS/FS/part_export.pm @@ -580,7 +580,12 @@ sub exporttype2svcdb { }, - 'svc_domain' => {}, + 'svc_domain' => { + 'bind' => 'Batch export to BIND named', + 'options' => { + }, + 'notes' => 'bind export notes', + }, 'svc_acct_sm' => {}, diff --git a/bin/passwd.import b/bin/passwd.import new file mode 100755 index 000000000..8b5826bfe --- /dev/null +++ b/bin/passwd.import @@ -0,0 +1,110 @@ +#!/usr/bin/perl -Tw +# $Id: passwd.import,v 1.1 2002-04-20 11:57:35 ivan Exp $ + +use strict; +use vars qw(%part_svc); +use Date::Parse; +use Term::Query qw(query); +use Net::SCP qw(iscp); +use FS::UID qw(adminsuidsetup datasrc); +use FS::Record qw(qsearch); +use FS::svc_acct; +use FS::part_svc; + +my $user = shift or die &usage; +adminsuidsetup $user; + +push @FS::svc_acct::shells, qw(/bin/sync /sbin/shuddown /bin/halt); #others? + +my($spooldir)="/usr/local/etc/freeside/export.". datasrc; + +#$FS::svc_acct::nossh_hack = 1; +$FS::svc_acct::noexport_hack = 1; + +### + +%part_svc=map { $_->svcpart, $_ } qsearch('part_svc',{'svcdb'=>'svc_acct'}); + +die "No services with svcdb svc_acct!\n" unless %part_svc; + +print "\n\n", &menu_svc, "\n", <svc, sort keys %part_svc ). "\n"; +} +sub getpart { + $^W=0; # Term::Query isn't -w-safe + my $return = query "Enter part number:", 'irk', [ keys %part_svc ]; + $^W=1; + $return; +} +sub getvalue { + my $prompt = shift; + $^W=0; # Term::Query isn't -w-safe + my $return = query $prompt, ''; + $^W=1; + $return; +} + +print "\n\n"; + +### + +open(PASSWD,"<$spooldir/passwd.import"); +open(SHADOW,"<$spooldir/shadow.import"); + +my(%password); +while () { + chop; + my($username,$password)=split(/:/); + #$password =~ s/^\!$/\*/; + #$password =~ s/\!+/\*SUSPENDED\* /; + $password{$username}=$password; +} + +while () { + chop; + my($username,$x,$uid,$gid,$finger,$dir,$shell)=split(/:/); + my($password)=$upassword{$username} || $password{$username}; + + $svcpart = $shell_svcpart; + + my($svc_acct) = new FS::svc_acct ({ + 'svcpart' => $svcpart, + 'username' => $username, + '_password' => $password, + 'uid' => $uid, + 'gid' => $gid, + 'finger' => $finger, + 'dir' => $dir, + 'shell' => $shell, + %{$allparam{$username}}, + }); + my($error); + $error=$svc_acct->insert; + die $error if $error; + + delete $upassword{$username}; +} + +sub usage { + die "Usage:\n\n passwd.import user\n"; +} + diff --git a/bin/svc_domain.erase b/bin/svc_domain.erase new file mode 100755 index 000000000..c0236614b --- /dev/null +++ b/bin/svc_domain.erase @@ -0,0 +1,17 @@ +#!/usr/bin/perl -w +# +# $Id: svc_domain.erase,v 1.1 2002-04-20 11:57:35 ivan Exp $ + +use strict; +use FS::UID qw(adminsuidsetup); +use FS::Record qw(qsearch); + +use FS::domain_record; +use FS::svc_domain; + +adminsuidsetup(shift @ARGV) or die "Usage: svc_domain.erase user\n"; + +foreach my $record ( qsearch('domain_record',{}), qsearch('svc_domain', {} ) ) { + my $error = $record->delete; + die $error if $error; +} diff --git a/bin/svc_domain.import b/bin/svc_domain.import index 10fe5b584..95d2ead78 100644 --- a/bin/svc_domain.import +++ b/bin/svc_domain.import @@ -1,13 +1,17 @@ #!/usr/bin/perl -w # -# $Id: svc_domain.import,v 1.3 2001-11-05 12:07:10 ivan Exp $ +# $Id: svc_domain.import,v 1.4 2002-04-20 11:57:35 ivan Exp $ use strict; use vars qw( %d_part_svc ); use Term::Query qw(query); -use Net::SCP qw(iscp); +#use BIND::Conf_Parser; +#use DNS::ZoneParse; + +#use Net::SCP qw(iscp); +use Net::SCP qw(scp); use FS::UID qw(adminsuidsetup datasrc); -#use FS::Record qw(qsearch qsearchs); +use FS::Record qw(qsearch); #qsearchs); #use FS::svc_acct_sm; use FS::svc_domain; use FS::domain_record; @@ -17,7 +21,8 @@ use FS::domain_record; my $user = shift or die &usage; adminsuidsetup $user; -my($spooldir)="/usr/local/etc/freeside/export.". datasrc; +use vars qw($spooldir); +$spooldir = "/usr/local/etc/freeside/export.". datasrc; %d_part_svc = map { $_->svcpart, $_ } qsearch('part_svc',{'svcdb'=>'svc_domain'}); @@ -25,8 +30,9 @@ my($spooldir)="/usr/local/etc/freeside/export.". datasrc; print "\n\n", ( join "\n", map "$_: ".$d_part_svc{$_}->svc, sort keys %d_part_svc ), "\n\n"; +use vars qw($domain_svcpart); $^W=0; #Term::Query isn't -w-safe -my $domain_svcpart = +$domain_svcpart = query "Enter part number for domains: ", 'irk', [ keys %d_part_svc ]; $^W=1; @@ -35,9 +41,19 @@ Enter the location and name of your primary named.conf file, for example "ns.isp.com:/var/named/named.conf" END my($named_conf)=&getvalue(":"); - iscp("root\@$named_conf","$spooldir/named.conf.import"); - -my $named_machine = (split(/:/, $named_conf))[0]; + #iscp("root\@$named_conf","$spooldir/named.conf.import"); + scp("root\@$named_conf","$spooldir/named.conf.import"); + +use vars qw($named_machine); +$named_machine = (split(/:/, $named_conf))[0]; + +sub getvalue { + my $prompt = shift; + $^W=0; # Term::Query isn't -w-safe + my $return = query $prompt, ''; + $^W=1; + $return; +} print "\n\n"; @@ -45,48 +61,120 @@ print "\n\n"; $FS::svc_domain::whois_hack=1; -open(NAMED_CONF,"<$spooldir/named.conf.import") - or die "Can't open $spooldir/named.conf.import: $!"; +my $p = Parser->new; +$p->parse_file("$spooldir/named.conf.import"); + +print "\nBIND import completed.\n"; + +## -while () { - next unless /^\s*options/; +sub usage { + die "Usage:\n\n svc_domain.import user\n"; } -my $directory; -while () { - last if /^\s*directory\s+\"([\/\w+]+)\";/; -} -$directory = $1 or die "can't locate directory in named.conf!"; -while () { - next unless /^\s*zone\s+\"([\w\.\-]+)\"\s+\{/; - my $zone = $1; - while () { - my $type; - if ( /^\s*type\s+(master|slave)\s*\;/ ) { - $type = $1; - } - if ( /^\s*file\s+\"([\w\.\-]+)\"\s*\;/ && $type eq 'master' ) { - - # - # (add svc_domain) - my $file = $1; - iscp("root\@$named_machine:$directory/$file","$spooldir/$file.import"); - open(ZONE,"<$spooldir/$file.import") - or die "Can't open $spooldir/$file.import: $!"; - while () { - # (add domain_record) + +######## +BEGIN { + + package Parser; + use BIND::Conf_Parser; + use vars qw(@ISA $named_dir); + @ISA = qw(BIND::Conf_Parser); + + sub handle_option { + my($self, $option, $argument) = @_; + return unless $option eq "directory"; + $named_dir = $argument; + } + + sub handle_zone { + my($self, $name, $class, $type, $options) = @_; + return unless $class eq 'in'; + + my $domain = new FS::svc_domain( { + svcpart => $main::domain_svcpart, + domain => $name, + action => 'N', + } ); + my $error = $domain->insert; + die $error if $error; + + if ( $type eq 'slave' ) { + + #use Data::Dumper; + #print Dumper($options); + #exit; + + foreach my $master ( @{ $options->{masters} } ) { + my $domain_record = new FS::domain_record( { + 'svcnum' => $domain->svcnum, + 'reczone' => '@', + 'recaf' => 'IN', + 'rectype' => '_mstr', + 'recdata' => $master, + } ); + my $error = $domain_record->insert; + die $error if $error; } - # + } elsif ( $type eq 'master' ) { + + my $file = $options->{file}; + + use File::Basename; + my $basefile = basename($file); + my $sourcefile = $file; + $sourcefile = "$named_dir/$sourcefile" unless $file =~ /^\//; + use Net::SCP qw(iscp scp); + scp("root\@$main::named_machine:$sourcefile", + "$main::spooldir/$basefile.import"); + + use DNS::ZoneParse; + my $zone = DNS::ZoneParse->new("$main::spooldir/$basefile.import"); + + my $dump = $zone->Dump; + + #use Data::Dumper; + #print "$name: ". Dumper($dump); + #exit; + + foreach my $rectype ( keys %$dump ) { + if ( $rectype =~ /^SOA$/i ) { + my $rec = $dump->{$rectype}; + my $domain_record = new FS::domain_record( { + 'svcnum' => $domain->svcnum, + 'reczone' => $rec->{origin}, + 'recaf' => 'IN', + 'rectype' => $rectype, + 'recdata' => + $rec->{primary}. ' '. $rec->{email}. ' ( '. + join(' ', map $rec->{$_}, + qw( serial refresh retry expire minimumTTL ) ). + ' )', + } ); + my $error = $domain_record->insert; + die $error if $error; + } else { + #die $dump->{$rectype}; + foreach my $rec ( @{ $dump->{$rectype} } ) { + my $domain_record = new FS::domain_record( { + 'svcnum' => $domain->svcnum, + 'reczone' => $rec->{name}, + 'recaf' => $rec->{class}, + 'rectype' => $rectype, + 'recdata' => ( $rectype =~ /^MX$/i + ? $rec->{priority}. ' '. $rec->{host} + : $rec->{host} ), + } ); + my $error = $domain_record->insert; + die $error if $error; + } + } + } } - last if /^\s*\}\s*\;/; } -} - -## -sub usage { - die "Usage:\n\n svc_domain.import user\n"; } +######### diff --git a/httemplate/docs/legacy.html b/httemplate/docs/legacy.html index 5f59bb83f..cceeb05d0 100755 --- a/httemplate/docs/legacy.html +++ b/httemplate/docs/legacy.html @@ -3,8 +3,10 @@

Importing legacy data

-NOTE: This file is OUT OF DATE with the landing of the new export code. Importing your legacy data will most probably involve some hacking on the example scripts noted below. Contributions to the import process are welcome. +In most cases, legacy data import all cases will require writing custom code to deal with your particular legacy data. The example scripts here will not work "out-of-the-box". Importing your legacy data will most probably involve some hacking on the example scripts noted below. Contributions to the import process are welcome.
    +
  • bin/svc_domain.import - Import domain information from BIND named +
  • bin/passwd.import - Just import `passwd' and `shadow' or `master.passwd', no RADIUS import.
  • bin/svc_acct.import - Import `passwd', ( `shadow' or `master.passwd' ) and RADIUS `users'. Before running bin/svc_acct.import, you need services (with table svc_acct) as follows:
    • Most accounts probably have entries in passwd and users (with Port-Limit nonexistant or 1)