per address block ip auto assignment and auto router selection
authorjeff <jeff>
Sat, 27 Sep 2008 03:01:44 +0000 (03:01 +0000)
committerjeff <jeff>
Sat, 27 Sep 2008 03:01:44 +0000 (03:01 +0000)
FS/FS/Conf.pm
FS/FS/Schema.pm
FS/FS/addr_block.pm
FS/FS/svc_broadband.pm
httemplate/browse/addr_block.cgi
httemplate/edit/process/addr_block/manual_flag.cgi [new file with mode: 0755]
httemplate/edit/svc_broadband.cgi

index 274b109..79e9feb 100644 (file)
@@ -731,6 +731,13 @@ worry that config_items is freeside-specific and icky.
   },
   
   {
+    'key'         => 'auto_router',
+    'section'     => '',
+    'description' => 'Automatically choose the correct router/block based on supplied ip address when possible while provisioning broadband services',
+    'type'        => 'checkbox',
+  },
+  
+  {
     'key'         => 'hidecancelledpackages',
     'section'     => 'UI',
     'description' => 'Prevent cancelled packages from showing up in listings (though they will still be in the database)',
index 5c9f624..0b121db 100644 (file)
@@ -1586,6 +1586,7 @@ sub tables_hashref {
         'ip_gateway', 'varchar', '', 15, '', '', 
         'ip_netmask', 'int', '', '', '', '', 
         'agentnum',   'int', 'NULL', '', '', '', 
+        'manual_flag', 'char', 'NULL', 1, '', '', 
       ],
       'primary_key' => 'blocknum',
       'unique'      => [ [ 'blocknum', 'routernum' ] ],
index 9d523e1..0fe2476 100755 (executable)
@@ -48,6 +48,8 @@ block is assigned.
 
 =item ip_netmask - the netmask of the block, expressed as an integer.
 
+=item manual_flag - prohibit automatic ip assignment from this block when true. 
+
 =item agentnum - optional agent number (see L<FS::agent>)
 
 =back
@@ -124,6 +126,7 @@ sub check {
     $self->ut_number('routernum')
     || $self->ut_ip('ip_gateway')
     || $self->ut_number('ip_netmask')
+    || $self->ut_enum('manual_flag', [ '', 'Y' ])
     || $self->ut_agentnum_acl('agentnum', 'Broadband global configuration')
   ;
   return $error if $error;
@@ -202,13 +205,16 @@ sub cidr {
 
 Returns a NetAddr::IP object corresponding to the first unassigned address 
 in the block (other than the network, broadcast, or gateway address).  If 
-there are no free addresses, returns false.
+there are no free addresses, returns false.  There are never free addresses
+when manual_flag is true.
 
 =cut
 
 sub next_free_addr {
   my $self = shift;
 
+  return '' if $self->manual_flag;
+
   my $conf = new FS::Conf;
   my @excludeaddr = $conf->config('exclude_ip_addr');
   
index fa90437..b808527 100755 (executable)
@@ -203,7 +203,7 @@ sub check {
 
   my $error =
     $self->ut_numbern('svcnum')
-    || $self->ut_foreign_key('blocknum', 'addr_block', 'blocknum')
+    || $self->ut_numbern('blocknum')
     || $self->ut_textn('description')
     || $self->ut_number('speed_up')
     || $self->ut_number('speed_down')
@@ -231,7 +231,12 @@ sub check {
     return "Invalid pkgnum" unless $cust_pkg;
   }
     
-  if ($cust_pkg) {
+  if ($self->blocknum) {
+    $error = $self->ut_foreign_key('blocknum', 'addr_block', 'blocknum');
+    return $error if $error;
+  }
+
+  if ($cust_pkg && $self->blocknum) {
     my $addr_agentnum = $self->addr_block->agentnum;
     if ($addr_agentnum && $addr_agentnum != $cust_pkg->cust_main->agentnum) {
       return "Address block does not service this customer";
@@ -239,6 +244,8 @@ sub check {
   }
 
   if (not($self->ip_addr) or $self->ip_addr eq '0.0.0.0') {
+    return "Must supply either address or block"
+      unless $self->blocknum;
     my $next_addr = $self->addr_block->next_free_addr;
     if ($next_addr) {
       $self->ip_addr($next_addr->addr);
@@ -247,6 +254,19 @@ sub check {
     }
   }
 
+  if (not($self->blocknum)) {
+    return "Must supply either address or block"
+      unless ($self->ip_addr and $self->ip_addr ne '0.0.0.0');
+    my @block = grep { $_->NetAddr->contains($self->NetAddr) }
+                 map { $_->addr_block }
+                 $self->allowed_routers;
+    if (scalar(@block)) {
+      $self->blocknum($block[0]->blocknum);
+    }else{
+      return "Address not with available block.";
+    }
+  }
+
   # This should catch errors in the ip_addr.  If it doesn't,
   # they'll almost certainly not map into the block anyway.
   my $self_addr = $self->NetAddr; #netmask is /32
index 945f8da..241bb93 100644 (file)
@@ -13,6 +13,7 @@
                                      'Router',
                                      'Action(s)',
                                      '',
+                                     '',
                                    ],
                 'fields'        => [ 'NetAddr',
                                      sub { my $block = shift;
                                          },
                                      $allocate_text,
                                      sub { shift->router ? '' : '<FONT SIZE="-2">(split)</FONT>' },
+                                     sub { '<FONT SIZE="-2">('. (shift->manual_flag ? 'allow' : 'prevent'). ' automatic ip assignment)</FONT>' },
                                    ],
                 'links'         => [ '',
                                      '',
                                      [ 'javascript:void(0)', '' ],
                                      $split_link,
+                                     $autoassign_link,
                                    ],
                 'link_onclicks' => [ '',
                                      '',
@@ -133,4 +136,11 @@ my $split_link = sub {
   $ref;
 }; 
 
+my $autoassign_link = sub {
+  my $block = shift;
+  my $url = "$path/manual_flag.cgi?manual_flag=";
+  $url .=  $block->manual_flag ? '' : 'Y';
+  [ "$url;blocknum=", 'blocknum' ];
+}; 
+
 </%init>
diff --git a/httemplate/edit/process/addr_block/manual_flag.cgi b/httemplate/edit/process/addr_block/manual_flag.cgi
new file mode 100755 (executable)
index 0000000..dc0cbbb
--- /dev/null
@@ -0,0 +1,30 @@
+<% $cgi->redirect(popurl(4). "browse/addr_block.cgi?". $cgi->query_string ) %>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+  unless $curuser->access_right('Broadband configuration')
+      || $curuser->access_right('Broadband global configuration');
+
+my $error = '';
+$cgi->param('blocknum') =~ /^(\d+)$/ or die "invalid blocknum";
+my $blocknum = $1;
+
+my $addr_block = qsearchs({ 'table'     => 'addr_block',
+                            'hashref'   => { blocknum => $blocknum },
+                            'extra_sql' => ' AND '. $curuser->agentnums_sql(
+                              'null_right' => 'Broadband global configuration'
+                            ),
+                         })
+  or $error = "Unknown blocknum: $blocknum";
+
+$addr_block->manual_flag($cgi->param('manual_flag'))
+  unless $error;
+
+$error ||= $addr_block->replace;
+
+$cgi->param('error', $error)
+  if $error;
+
+</%init>
index 25fb009..e60c76c 100644 (file)
@@ -8,7 +8,7 @@
                                  'speed_down'   => 'Download speed',
                                  'speed_up'     => 'Upload speed',
                                  'blocknum'     => 'Router/Block',
-                                 'block_disp'   => 'Router/Block',
+                                 'block_label'  => 'Router/Block',
                                  'mac_addr'     => 'MAC address',
                                  'latitude'     => 'Latitude',
                                  'longitude'    => 'Longitude',
@@ -29,12 +29,16 @@ die "access denied"
 # If it's stupid but it works, it's still stupid.
 #  -Kristian
 
+my $conf = new FS::Conf;
+
 my @fields = (
   qw( description ip_addr speed_down speed_up blocknum ),
   { field=>'block_label', type=>'fixed' },
   qw( mac_addr latitude longitude altitude vlan_profile authkey )
 );
 
+my $fixedblock = '';
+
 my $callback = sub {
   my ($cgi, $object, $fieldref) = @_;
 
@@ -48,6 +52,8 @@ my $callback = sub {
   if ($columndef->columnflag eq 'F') {
     $fieldref->{'type'} = 'fixed';
     $fieldref->{'value'} = $columndef->columnvalue;
+    $fixedblock = $fieldref->{value}
+      if $fieldref->{field} eq 'blocknum';
   }
 
   if ($object->svcnum) { 
@@ -60,9 +66,22 @@ my $callback = sub {
 
   } else { 
 
-    $fieldref->{type} = 'hidden' if $fieldref->{field} eq 'block_label';
+    if ($fieldref->{field} eq 'block_label') {
+      if ($fixedblock) {
+        $object->blocknum($fixedblock);
+        $fieldref->{value} = $object->addr_block->label;
+      }else{
+        $fieldref->{type} = 'hidden';
+      }
+    }
 
     if ($fieldref->{field} eq 'blocknum') {
+      if ( $fixedblock or $conf->exists('auto_router') ) {
+        $fieldref->{type} = 'hidden';
+        $fieldref->{value} = $fixedblock;
+        return;
+      }
+
       my $cust_pkg = qsearchs( 'cust_pkg', {pkgnum => $cgi->param('pkgnum')} );
       die "No cust_pkg entry!" unless $cust_pkg;