use strict;
use vars qw( @ISA );
#use FS::Record qw( qsearch qsearchs );
-use FS::Record qw( qsearchs );
+use FS::Record qw( qsearchs dbh );
use FS::svc_domain;
@ISA = qw(FS::Record);
=cut
+sub insert {
+ my $self = shift;
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ my $error = $self->SUPER::insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
+ unless ( $self->rectype =~ /^(SOA|_mstr)$/ ) {
+ my $error = $self->increment_serial;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+ '';
+
+}
+
=item delete
Delete this record from the database.
=cut
+sub delete {
+ my $self = shift;
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ my $error = $self->SUPER::delete;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
+ unless ( $self->rectype =~ /^(SOA|_mstr)$/ ) {
+ my $error = $self->increment_serial;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+ '';
+
+}
+
=item replace OLD_RECORD
Replaces the OLD_RECORD with this one in the database. If there is an error,
=cut
+sub replace {
+ my $self = shift;
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ my $error = $self->SUPER::replace(@_);
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
+ unless ( $self->rectype eq 'SOA' ) {
+ my $error = $self->increment_serial;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+ '';
+
+}
+
=item check
Checks all fields to make sure this is a valid example. If there is
''; #no error
}
+=item increment_serial
+
+=cut
+
+sub increment_serial {
+ my $self = shift;
+
+ my $soa = qsearchs('domain_record', {
+ svcnum => $self->svcnum,
+ reczone => '@', #or full domain ?
+ recaf => 'IN',
+ rectype => 'SOA',
+ } ) or return "soa record not found; can't increment serial";
+
+ my $data = $soa->recdata;
+ $data =~ s/(\(\D*)(\d+)/$1.($2+1)/e; #well, it works.
+
+ my %hash = $soa->hash;
+ $hash{recdata} = $data;
+ my $new = new FS::domain_record \%hash;
+ $new->replace($soa);
+}
+
=back
=head1 VERSION
-$Id: domain_record.pm,v 1.7 2002-04-20 11:57:35 ivan Exp $
+$Id: domain_record.pm,v 1.8 2002-05-22 18:44:01 ivan Exp $
=head1 BUGS
'';
-};
+}
=item delete
Reblesses the object into the FS::part_export::EXPORTTYPE class, where
EXPORTTYPE is the object's I<exporttype> field. There should be better docs
-on how to create new exports, but until then, see L</NEW EXPORT CLASSES>.
+on how to create new exports (and they should live in their own files and be
+autoloaded-on-demand), but until then, see L</NEW EXPORT CLASSES>.
=cut
my $self = shift;
my $exporttype = $self->exporttype;
my $class = ref($self). "::$exporttype";
- eval "use $class;" or die $@;
+ eval "use $class;";
bless($self, $class);
}
'bind' => {
'desc' =>'Batch export to BIND named',
'options' => \%bind_options,
- 'notes' => 'bind export notes',
+ 'notes' => 'bind export notes File::Rsync dependancy, run bind.export',
},
'bind_slave' => {
'desc' =>'Batch export to slave BIND named',
'options' => \%bind_slave_options,
- 'notes' => 'bind export notes (secondary munge)',
+ 'notes' => 'bind export notes (secondary munge) File::Rsync dependancy, run bind.export',
},
if defined( $FS::Record::dbdef->table('svc_acct_sm') )
&& qsearch('svc_acct_sm', { 'domsvc' => $self->svcnum } );
- return "Can't delete a domain with (domain_record) zone entries!"
- if qsearch('domain_record', { 'svcnum' => $self->svcnum } );
+ #return "Can't delete a domain with (domain_record) zone entries!"
+ # if qsearch('domain_record', { 'svcnum' => $self->svcnum } );
- $self->SUPER::delete;
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ my $error = $self->SUPER::delete;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
+ foreach my $domain_record ( reverse $self->domain_record ) {
+ my $error = $domain_record->delete;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
}
=item replace OLD_RECORD
}
+=item domain_record
+
+=cut
+
+sub domain_record {
+ my $self = shift;
+
+ my %order = (
+ SOA => 1,
+ NS => 2,
+ MX => 3,
+ CNAME => 4,
+ A => 5,
+ );
+
+ sort { $order{$a->rectype} <=> $order{$b->rectype} }
+ qsearch('domain_record', { svcnum => $self->svcnum } );
+
+}
+
=item whois
Returns the Net::Whois::Domain object (see L<Net::Whois>) for this domain, or
=head1 VERSION
-$Id: svc_domain.pm,v 1.28 2002-05-18 09:51:30 ivan Exp $
+$Id: svc_domain.pm,v 1.29 2002-05-22 18:44:01 ivan Exp $
=head1 BUGS
use strict;
use File::Path;
+use File::Rsync;
+use Net::SSH qw(ssh);
use FS::UID qw(adminsuidsetup datasrc);
use FS::Record qw(qsearch qsearchs);
use FS::part_export;
my @exports = qsearch('part_export', { 'exporttype' => 'bind' } );
my @sexports = qsearch('part_export', { 'exporttype' => 'bind_slave' } );
+my $rsync = File::Rsync->new({
+ rsh => 'ssh',
+# dry_run => 1,
+});
+
foreach my $export ( @exports ) {
- my $prefix = "$spooldir/". $export->machine;
+ my $machine = $export->machine;
+ my $prefix = "$spooldir/$machine";
#prevent old domain files from piling up
#rmtree "$prefix" or die "can't rmtree $prefix.db: $!";
}
+ $rsync->exec( {
+ src => "$prefix/",
+ recursive => 1,
+ dest => "root\@$machine:$zonepath/",
+ exclude => [qw( *.import named.conf.HEADER named.conf )],
+ } ) or die "rsync to $machine failed: ". join(" / ", $rsync->err);
+ # warn $rsync->out;
+
+ $rsync->exec( {
+ src => "$prefix/named.conf",
+ dest => "root\@$machine:". $export->option('named_conf'),
+ } ) or die "rsync to $machine failed: ". join(" / ", $rsync->err);
+# warn $rsync->out;
+
+ ssh("root\@$machine", 'ndc reload');
+
}
+
close NAMED_CONF;
foreach my $sexport ( @sexports ) { #false laziness with above
- my $prefix = "$spooldir/". $sexport->machine;
+ my $machine = $sexport->machine;
+ my $prefix = "$spooldir/$machine";
#prevent old domain files from piling up
#rmtree "$prefix" or die "can't rmtree $prefix.db: $!";
}
+ $rsync->exec( {
+ src => "$prefix/named.conf",
+ dest => "root\@$machine:". $sexport->option('named_conf'),
+ } ) or die "rsync to $machine failed: ". join(" / ", $rsync->err);
+# warn $rsync->out;
+
+ ssh("root\@$machine", 'ndc reload');
+
}
close NAMED_CONF;
--- /dev/null
+<%
+
+my $recnum = $cgi->param('recnum');
+
+my $old = qsearchs('agent',{'recnum'=>$recnum}) if $recnum;
+
+my $new = new FS::domain_record ( {
+ map {
+ $_, scalar($cgi->param($_));
+ } fields('domain_record')
+} );
+
+my $error;
+if ( $recnum ) {
+ $error=$new->replace($old);
+} else {
+ $error=$new->insert;
+ $recnum=$new->getfield('recnum');
+}
+
+if ( $error ) {
+# $cgi->param('error', $error);
+# print $cgi->redirect(popurl(2). "agent.cgi?". $cgi->query_string );
+ #no edit screen to send them back to
+ eidiot($error);
+} else {
+ my $svcnum = $new->svcnum;
+ print $cgi->redirect(popurl(3). "view/svc_domain.cgi?$svcnum");
+}
+
+%>
$query =~ /^(\d+)$/;
my $svcnum = $1;
-my $svc_acct = qsearchs('svc_acct',{'svcnum'=>$svcnum});
-die "Unknown svcnum!" unless $svc_acct;
+#my $svc_acct = qsearchs('svc_acct',{'svcnum'=>$svcnum});
+#die "Unknown svcnum!" unless $svc_acct;
my $cust_svc = qsearchs('cust_svc',{'svcnum'=>$svcnum});
+die "Unknown svcnum!" unless $cust_svc;
&eidiot(qq!This account has already been audited. Cancel the
<A HREF="!. popurl(2). qq!view/cust_pkg.cgi?! . $cust_svc->getfield('pkgnum') .
qq!pkgnum"> package</A> instead.!)
if $cust_svc->pkgnum ne '' && $cust_svc->pkgnum ne '0';
+my $svc_x = $cust_svc->svc_x;
+
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
local $SIG{QUIT} = 'IGNORE';
local $FS::UID::AutoCommit = 0;
-my $error = $svc_acct->cancel;
-$error ||= $svc_acct->delete;
+my $error = $svc_x->cancel;
+$error ||= $svc_x->delete;
$error ||= $cust_svc->delete;
if ( $error ) {
--- /dev/null
+<%
+
+#untaint recnum
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/ || die "Illegal recnum";
+my $recnum = $1;
+
+my $domain_record = qsearchs('domain_record',{'recnum'=>$recnum});
+
+my $error = $domain_record->delete;
+eidiot($error) if $error;
+
+print $cgi->redirect($p. "view/svc_domain.cgi?". $domain_record->svcnum);
+
+%>
<%
-#untaint paynum
+#untaint exportnum
my($query) = $cgi->keywords;
$query =~ /^(\d+)$/ || die "Illegal exportnum";
my $exportnum = $1;
? ( "View this package (#$pkgnum)" => "${p}view/cust_pkg.cgi?$pkgnum",
"View this customer (#$custnum)" => "${p}view/cust_main.cgi?$custnum",
)
- : ( "Cancel this (unaudited) account" =>
+ : ( "Cancel this (unaudited) domain" =>
"${p}misc/cancel-unaudited.cgi?$svcnum" )
),
"Main menu" => $p,
qq!<BR>Catch all email <A HREF="${p}misc/catchall.cgi?$svcnum">(change)</A>:!,
$email ? "<B>$email</B>." : "<I>(none)<I>",
qq!<BR><BR><A HREF="http://www.geektools.com/cgi-bin/proxy.cgi?query=$domain;targetnic=auto">View whois information.</A>!,
- '<BR><BR>', ntable("",2),
+ '<BR><BR>',
+ '<SCRIPT>function areyousure(href) {
+ if ( confirm("Remove this record?") == true )
+ window.location.href = href;
+ }
+ </SCRIPT>',
+ ntable("",2),
'<tr><th>Zone</th><th>Type</th><th>Data</th></tr>',
;
-foreach my $domain_record ( qsearch('domain_record', { svcnum => $svcnum } ) ) {
+
+foreach my $domain_record ( $svc_domain->domain_record ) {
print '<tr><td>'. $domain_record->reczone. '</td>'.
'<td>'. $domain_record->recaf. ' '. $domain_record->rectype. '</td>'.
- '<td>'. $domain_record->recdata. '</td></tr>';
+ '<td>'. $domain_record->recdata;
+ print qq! (<A HREF="javascript:areyousure('${p}misc/delete-domain_record.cgi?!
+ .$domain_record->recnum. qq!')">delete</A>)!
+ unless $domain_record->rectype eq 'SOA';
+ print '</td></tr>';
}
-print '</table>'.
- '<BR>'. joblisting({'svcnum'=>$svcnum}, 1).
+print '</table><BR>'.
+ qq!<FORM METHOD="POST" ACTION="${p}edit/process/domain_record.cgi">!.
+ qq!<INPUT TYPE="hidden" NAME="svcnum" VALUE="$svcnum">!.
+ '<INPUT TYPE="text" NAME="reczone"> '.
+ '<INPUT TYPE="hidden" NAME="recaf" VALUE="IN">IN '.
+ '<SELECT NAME="rectype">'.
+ join('', map qq!<OPTION VALUE="$_">$_</OPTION>!, qw(A NS CNAME MX) ).
+ '</SELECT>'.
+ ' <INPUT TYPE="text" NAME="recdata"> <INPUT TYPE="submit" VALUE="Add">'.
+ '<BR><BR>'. joblisting({'svcnum'=>$svcnum}, 1).
'</BODY></HTML>';
%>