working BIND import
authorivan <ivan>
Sat, 20 Apr 2002 11:57:36 +0000 (11:57 +0000)
committerivan <ivan>
Sat, 20 Apr 2002 11:57:36 +0000 (11:57 +0000)
FS/FS/domain_record.pm
FS/FS/part_export.pm
bin/passwd.import [new file with mode: 0755]
bin/svc_domain.erase [new file with mode: 0755]
bin/svc_domain.import
httemplate/docs/legacy.html

index 24db4c2..6f4dd02 100644 (file)
@@ -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
 
index 406b270..49e2130 100644 (file)
@@ -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 (executable)
index 0000000..8b5826b
--- /dev/null
@@ -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", <<END;
+Enter part number to import.
+END
+my($shell_svcpart)=&getpart;
+
+print "\n\n", <<END;
+Enter the location and name of your _user_ passwd file, for example
+"mail.isp.com:/etc/passwd" or "nis.isp.com:/etc/global/passwd"
+END
+my($loc_passwd)=&getvalue(":");
+iscp("root\@$loc_passwd", "$spooldir/passwd.import");
+
+print "\n\n", <<END;
+Enter the location and name of your _user_ shadow file, for example
+"mail.isp.com:/etc/shadow" or "bsd.isp.com:/etc/master.passwd"
+END
+my($loc_shadow)=&getvalue(":");
+iscp("root\@$loc_shadow", "$spooldir/shadow.import");
+
+sub menu_svc {
+  ( join "\n", map "$_: ".$part_svc{$_}->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 (<SHADOW>) {
+  chop;
+  my($username,$password)=split(/:/);
+  #$password =~ s/^\!$/\*/;
+  #$password =~ s/\!+/\*SUSPENDED\* /;
+  $password{$username}=$password;
+}
+
+while (<PASSWD>) {
+  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 (executable)
index 0000000..c023661
--- /dev/null
@@ -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;
+}
index 10fe5b5..95d2ead 100644 (file)
@@ -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 (<NAMED_CONF>) {
-  next unless /^\s*options/;
+sub usage {
+  die "Usage:\n\n  svc_domain.import user\n";
 }
-my $directory;
-while (<NAMED_CONF>) {
-  last if /^\s*directory\s+\"([\/\w+]+)\";/;
-} 
-$directory = $1 or die "can't locate directory in named.conf!";
-while (<NAMED_CONF>) {
-  next unless /^\s*zone\s+\"([\w\.\-]+)\"\s+\{/;
-  my $zone = $1;
-  while (<NAMED_CONF>) {
-    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 (<ZONE>) {
-        # (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";
 }
+#########
 
index 5f59bb8..cceeb05 100755 (executable)
@@ -3,8 +3,10 @@
 </head>
 <body>
   <h1>Importing legacy data</h1>
-<font size="+2">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.</font>
+<font size="+2">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.</font>
 <ul>
+  <li><a name="svc_domain">bin/svc_domain.import</a> - Import domain information from BIND named
+  <li><a name="svc_acct">bin/passwd.import</a> - Just import `passwd' and `shadow' or `master.passwd', no RADIUS import.
   <li><a name="svc_acct">bin/svc_acct.import</a> - Import `passwd', ( `shadow' or `master.passwd' ) and RADIUS `users'.  Before running bin/svc_acct.import, you need <a href="../browse/part_svc.cgi">services</a> (with table svc_acct) as follows:
     <ul>
       <li>Most accounts probably have entries in passwd and users (with Port-Limit nonexistant or 1)