<h1 class="pagehead">Device Port Control</h1>
% $m->comp('SELF:switch') if $cmd =~ /^(up|down)$/;
% $m->comp('SELF:log') if $cmd eq 'log';
% $m->comp('SELF:err') if $cmd eq 'err';
% $m->comp('SELF:vlan') if $cmd eq 'vlan';
% $m->comp('SELF:reasons') unless $cmd eq 'err' or $cmd eq 'vlan';
<%args>
$debug => 0
$cmd  => undef
$type => undef
$ip   => undef
$port => undef
$log  => undef
$log_num => 5
$reason => ''
$vlan => undef
$location => undef
</%args>
<%shared>
# scope
my ($arg_ip,$arg_port,$log,$arg_cmd,$port,$err,$db_port,$arg_reason,$arg_log_num,$arg_vlan);
my $user      = $m->session->{user};
my $userip    = $r->connection->client_ip; 
my $port_ctl  = $m->session->{user_port_ctl};
my $secure    = &is_secure;
my $timeout   = $netdisco::CONFIG{portctl_timeout} || 60;
my $odd = 1 ;
my %Reasons = ( ''            => ['Select a Reason',''],
                %netdisco::PORT_CONTROL_REASONS);
</%shared>
<%init>
# Check Authorization - User in portcontrol list in config file, and connected via https
if ($cmd =~ /^(up|down|switch|vlan)$/ and !$secure) {
    my $url = url_secure($r->uri);
    $m->redirect($url);
}
if ($cmd =~ /^(up|down|switch|vlan)$/ and !$port_ctl) {
    $m->session->{_login_msg} = "Please log in as a user with port control privileges.";
    my $url = $m->interp->apply_escapes( $r->uri, 'u' );
    $m->redirect("login.html?done=$url");
}

$arg_cmd = $cmd;  $arg_ip = $ip;  $arg_port = $port; 
$arg_reason = $reason; $arg_log_num = $log_num;
$arg_vlan = $vlan;

if ($cmd eq 'switch' and !$reason and ($type ne 'vlan' and $type ne 'location')){
    $cmd = 'err';
    $err .= "You must select a reason for bringing the port $type <BR>\n";
}

my $dbport;
if ($cmd =~ /^(up|down|switch|vlan)$/ && $type ne 'location'){
    $dbport = sql_hash('device_port',['*'],{'ip'=>$ip, 'port'=>$port});
    my $remote_ip   = $dbport->{remote_ip};
    my $remote_type = $dbport->{remote_type};
    my $is_uplink   = (defined $remote_ip and !(defined $remote_type and $remote_type =~ /ip.phone/i)) ? 1 : 0;

    unless (defined $dbport and scalar(keys %$dbport)){
        $cmd = 'err';
        $err .= "That Port doesn't exist!<BR>\n";
    } 

    if ($is_uplink) {
        $cmd = 'err';
        $err .= "You cannot shutoff uplink ports. <BR>\n"; 
    }
}

if ($cmd eq 'switch' and $type =~ /^(up|down|vlan|location)$/) {
    my $dir = $type;
    $dir = 'enable' if $type eq 'up';
    $dir = 'disable' if $type eq 'down';

    my ($action,$subaction);
    if ($type =~ /(up|down)/) {
        $action = 'portcontrol';
        $subaction = "$type-$reason";
    }
    if ($type eq 'vlan') {
        $action = 'vlan';
        $subaction = $vlan;
    }
    if ($type eq 'location') {
        $action = 'location';
        $subaction = $location;
    }
    
    # Add to admin queue
    insert_or_update('admin',{},
                               {'device'=>$ip,'action'=>$action,'status'=>'queued','port'=>$port,
                                'username' => $user, 'userip', $userip, 'debug' => $debug, 'subaction' => $subaction,
                                'log' => $log}
                              ); 

    my $job_id = sql_scalar('admin',["currval('admin_job_seq')"]);

    # Wait for a response from admin daemon
    my $now = time; my $job;
    my $timeout_time = $now + $timeout;
    my $done = 0;
    my $status;
    while (!$done){
        # Poll every two seconds
        sleep(2);
    
        # Check to see if daemon done
        $job = sql_hash('admin',['job','extract(epoch from entered) as entered','extract(epoch from finished) as finished',
                        'extract(epoch from started) as started','status','log'],
                        {'job'=>$job_id}
                       );

        if (! defined $job || !defined($job->{job})){
            $err = "Problem entering job $job_id into admin queue.<BR>\n";
            last;
        }   

        $status = $job->{status};
        $done++ if $status =~ /^(done|error)$/;
        $done++ if $status !~ /^(running|queued)$/;

        $now = time;
        if (!$done and $now >= $timeout_time and $status =~ /^(running|queued)$/){
            my $url = $r->uri . "?ip=$ip&port=$port&cmd=log";
            $err = "Timeout! Job is $status in the admin queue. Check the <A HREF=\"$url\">port log entry</A> in a couple minutes to double-check it worked.<BR>\n";
            $cmd = 'err';
            last;
        } elsif (!$done and $now >= $timeout_time){
            $err = "Error.  There was a problem with entering the job in the admin queue.  Check to see the admin daemon is running, then check it's log file for problems.\n";
            $cmd = 'err';
            last;
        }
    }   

    if (!$err and $status eq 'done'){
        $cmd = 'log';
        if ($type eq 'location') {
            $err = "Location was successfully set.<BR>\n";
        } else {
            $err = "Port was successfully $dir.<BR>\n";
        }
    } elsif (!$err and $status eq 'error'){
        $cmd = 'err';
        $err = "[Failed] <P>$job->{log}<BR>\n";
    } else {
        $cmd = 'err';
        $err = "[Failed] I don't know what happened to the job.  Status: $job->{status}. <P>Log: $job->{log}<BR>.\n" unless ($err);
    }

}
</%init>
<%method log>
% my $logs = sql_rows('device_port_log', ['id','log','reason','username','userip','action','extract(epoch from creation) as creation'] , 
%       {'ip'=>$arg_ip, 'port'=>$arg_port || ''} );
% my $queue = sql_rows('admin', ['extract(epoch from entered) as entered','extract(epoch from started) as started','action','subaction','username','userip'],
%       {'device'=>$arg_ip, 'port'=>$arg_port || '', 'status'=>'queued'} );
% my $count = 0;
% if ($err) {
<h2 class="subheader"><%$err%></h2>
% }
<h2 class="subheader">Log Entries for <A HREF="device.html?ip=<%$arg_ip |u%>&port=<% $arg_port|u%>"><%$arg_ip%>/<%$arg_port%></A>
<& SELF:back &></h2>
% if (@$queue) {
<h2 class="subheader">Queued Actions for <%$arg_ip%>/<%$arg_port%>
(Check admin daemon status)</h2>
<TABLE WIDTH=85% CELLSPACING=0 CELLPADDING=2 BORDER=0>
<TR>
    <TH>User</TH>
    <TH>Action</TH>
    <TH>Queued</TH>
    <TH>Started</TH>
</TR>
%   foreach my $entry (@$queue) {
<TR>
    <TD><%$entry->{username}%> @ <%$entry->{userip}%></TD>
    <TD><%$entry->{action}%> <%$entry->{subaction}%></TD>
    <TD><%scalar localtime($entry->{entered})%></TD>
    <TD><%$entry->{started} ? scalar localtime($entry->{started}) : "No"%></TD>
</TR>
%   }
</TABLE>
% }
<FORM ACTION="<%$r->uri%>" METHOD=GET>
<INPUT TYPE="HIDDEN" NAME="cmd" VALUE="log">
<INPUT TYPE="HIDDEN" NAME="ip" VALUE="<%$arg_ip |h%>">
<INPUT TYPE="HIDDEN" NAME="port" VALUE="<%$arg_port|h%>">
<TABLE WIDTH=85% CELLSPACING=0 CELLPADDING=2 BORDER=0>
<TR>
    <TH>User</TH>
    <TH>Action</TH>
    <TH>Date</TH>
    <TH>Reason / VLAN</TH>
    <TH>Log</TH>
</TR>
% foreach my $entry (sort {$b->{creation} <=> $a->{creation} } @$logs) {
<TR CLASS="match-<% ++$odd % 2 %>">
    <TD><%$entry->{username}%> @ <%$entry->{userip}%></TD>
    <TD><%$entry->{action}%></TD>
    <TD><%scalar localtime($entry->{creation})%></TD>
%   if ( $entry->{action} eq 'vlan' || $entry->{action} eq 'location' ) {
    <TD><%$entry->{reason}%></TD>
%   } else {
    <TD><A HREF="#<%$entry->{reason}%>"><%$Reasons{$entry->{reason}}->[0]%></A></TD>
%   }
    <TD><TEXTAREA ROWS=3 COLS=30 WRAP=soft><%$entry->{log}%></TEXTAREA>
    </TD>
</TR>

% $count++;
% last unless ($arg_log_num eq 'All' or $count < $arg_log_num);
%}
</TABLE>
Log Entires to Show : <SELECT NAME="log_num">
% foreach my $num (qw/1 3 5 10 20 50 100 All/){
    <OPTION VALUE="<%$num%>" <%$num eq $arg_log_num ? 'SELECTED' : ''%>><%$num%>
%  }
</SELECT>
<INPUT TYPE="submit" CLASS="navbutton" VALUE="Refresh">
</FORM>
</%method>
%#
%# switch()
%#
<%method switch>
<FORM ACTION="<%$r->uri%>" METHOD="post">
<INPUT TYPE="HIDDEN" NAME="cmd" VALUE="switch">
<INPUT TYPE="HIDDEN" NAME="type" VALUE="<%$arg_cmd |h%>">
<INPUT TYPE="HIDDEN" NAME="port" VALUE="<%$arg_port |h%>">
<INPUT TYPE="HIDDEN" NAME="ip" VALUE="<%$arg_ip |h%>">
<TABLE BORDER=0 CELLSPACING=0 CLASS="box">
<TR CLASS="match-1">
    <TD>Port :</TD>
    <TD CLASS="tr-data-1"><A HREF="device.html?ip=<%$arg_ip |u%>&port=<% $arg_port|u%>"><% $arg_ip %>[<% $arg_port %>]</A></TD>
</TR>
<TR CLASS="match-0">
    <TD>User :</TD>
    <TD CLASS="tr-data-0"><U><%$user%></U> at <%$userip%> <BR><u><% scalar localtime %></u>
    </TD>
</TR>
<TR CLASS="match-1">
    <TD>Reason :<BR>&nbsp;</TD>
    <TD CLASS="tr-data-1"><SELECT NAME="reason" SIZE=1>
% $arg_reason = 'other' if $arg_cmd eq 'up';
% foreach my $this_r (sort keys %Reasons){
        <OPTION VALUE="<%$this_r |h%>" <%$this_r eq $arg_reason ? 'SELECTED' : ''%>> \
%   if ($this_r){        
[<%$this_r%>] \
%   }
<%$Reasons{$this_r}->[0]%> 
%}
    </SELECT>
    <BR><FONT SIZE=-3>See below for descriptions.</FONT>
    </TD>
</TR>
<TR CLASS="match-0">
    <TD>Log:</TD>
    <TD CLASS="tr-data-0"><TEXTAREA NAME="log" ROWS=3 COLS=40 WRAP=soft></TEXTAREA>
    <BR>Enter a useful description why the port is being turned <% $arg_cmd eq 'down' ? 'off' : 'on' %>.
    </TD>
</TR>
<TR CLASS="match-1">
    <TD COLSPAN=2 CLASS="tr-data-1">
        <INPUT TYPE="submit" CLASS="navbutton" VALUE="Turn Port <%$arg_cmd eq 'down' ? 'off' : 'on'%>">
        Debug: <INPUT TYPE="checkbox" NAME="debug" VALUE="1">
        <P><I>Note</I>: This can take up to 1 minute.  Do not hit refresh on your browser.
    </TD>
</TR>
</TABLE>
</FORM>
<& SELF:back &>    
</%method>
%#
%# vlan()
%#
<%method vlan>
<FORM ACTION="<%$r->uri%>" METHOD="post">
<INPUT TYPE="HIDDEN" NAME="cmd" VALUE="switch">
<INPUT TYPE="HIDDEN" NAME="type" VALUE="vlan">
<INPUT TYPE="HIDDEN" NAME="port" VALUE="<%$arg_port |h%>">
<INPUT TYPE="HIDDEN" NAME="ip" VALUE="<%$arg_ip |h%>">
<TABLE BORDER=0 CELLSPACING=0 CLASS="box">
<TR CLASS="match-1">
    <TD>Port :</TD>
    <TD CLASS="tr-data-1"><A HREF="device.html?ip=<%$arg_ip |u%>&port=<% $arg_port|u%>"><% $arg_ip %>[<% $arg_port %>]</A></TD>
</TR>
<TR CLASS="match-0">
    <TD>User :</TD>
    <TD CLASS="tr-data-0"><U><%$user%></U> at <%$userip%> <BR><u><% scalar localtime %></u>
    </TD>
</TR>
<TR CLASS="match-1">
    <TD>Log:</TD>
    <TD CLASS="tr-data-0"><TEXTAREA NAME="log" ROWS=3 COLS=40 WRAP=soft></TEXTAREA>
    <BR>Enter a useful description why the VLAN is being changed.
    </TD>
</TR>
<TR CLASS="match-0">
    <TD>VLAN:</TD>
%# TODO - need to list VLANs
    <TD CLASS="tr-data-0"><INPUT NAME="vlan" SIZE=5 MAXLENGTH=5> Enter new VLAN </TD>
</TR>
<TR CLASS="match-1">
    <TD COLSPAN=2 CLASS="tr-data-1">
        <INPUT TYPE="submit" CLASS="navbutton" VALUE="Change VLAN">
        Debug: <INPUT TYPE="checkbox" NAME="debug" VALUE="1">
        <P><I>Note</I>: This can take up to 1 minute.  Do not hit refresh on your browser.
    </TD>
</TR>
</TABLE>
</FORM>
<& SELF:back &>    
</%method>
%#
%# reasons()
%#
<%method reasons>
<h2 class="subheader">Reason Descriptions</h2>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3>
<TR>
    <TH>Reason</TH>
    <TH>Description</TH>
</TR>
<TR>
    <TD COLSPAN=2><HR NOSHADE></TD>
</TR>
% foreach my $this_r (sort keys %Reasons){
%    next unless $this_r;
%    my $long = $Reasons{$this_r}->[1];
%    $long =~ s!\s+! !g;
<TR>
    <TD><A NAME="<%$this_r%>"><B><%$this_r%></B></A></TD>
    <TD><%$long%></TD>
</TR>
% }
</TABLE>
</%method>
<%method err>
% $err =~ s/\n/<BR>\n/g;
<% $err %>
    <& SELF:back &>
</%method>
<%method back>
<FORM ACTION="device.html" METHOD="get">
<INPUT TYPE="hidden" NAME="ip" VALUE="<%$arg_ip |h%>">
<INPUT TYPE="hidden" NAME="port" VALUE="all">
<INPUT TYPE="submit" CLASS="navbutton" VALUE="Back to Device View">
</FORM>
</%method>
%#
%# title()
%#
<%method title>
- Port Control \
</%method>
%# $Id$
%# vim:syntax=mason
