#!/usr/local/bin/perl
# 
#
# okaload.pl
# 
# Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
#
#    NAME
#      okaload.pl
#
#    DESCRIPTION
#      load/unload OKA kernel drivers
#
#    NOTES
#      okaload start
#          load OKA kernel drivers. If the drivers are already loaded,
#          no action is taken.
#      okaload stop 
#          unload OKA kernel drivers
#      okaload check
#          basic verification that OKA drivers are up.
#
#      User output should be done in this file when possible to ensure
#      cross platform similarity in command look and feel. However, it is 
#      understood that some OSD actions are specific to one platform only,
#      in which case it makes sense to do the output there.
#
# 

use strict;
use Getopt::Std;
use Cwd 'abs_path';
use IO::Handle;
use acfslib;
use okalib;
use osds_okaload;

# acfsutil command line option switch.
use Config;
my ($is_check) = 0;                   # 'check' sub commands do not get logged
my ($optc) = '-';                     # use a '-' or '/' for acfsutil switches
$optc = '/' if ($Config{osname} =~ /Win/);

sub main
{
  my ($sub_command);      # start or stop
  my ($return_code);      # as the name implies 
  # user options
  my (%opt);                 # user options hash - used by getopts()
  # user options.
  my (%flags) = ( start => 's',
                  stop  => 's',
                  check => 's',
                );

  # supplied by the front end driver and 'guaranteed' to be there.
  # command is what the user actually typed in (sans directories).
  $COMMAND = $ARGV[0];

  # supplied by user
  $sub_command = $ARGV[1];

  # We don't log the check sub_command because it would fill the log with
  # mostly useless information.
  if ((defined($sub_command)) && ($sub_command eq "check"))
  {
    $is_check = 1;
  }

  if (! $is_check)
  {
    # process the command line for acfsutil cmdlog
    # We could just use "acfsutil cmdlog -s @ARGV"
    # but that wouldn't give us the absolute command path name;
    my ($opt, $opts);

    $opts = "";
    foreach $opt (@ARGV)
    {
      $opts = abs_path($0) if $opts eq "";  # command name
      $opts .= " $opt";
    }

    # acfsutil cmdlog - $optc handles the Windows/Unix cmd switch '-' or '/'.
    # the 's' option logs the start of the command.
    #my ($log_cmd) = sprintf "$ACFSUTIL cmdlog %ss $opts", $optc;
    #system($log_cmd);
  }

  if (!defined($sub_command))
  {
    # does not return
    usage();
  }

  if (!(($sub_command eq "start") || 
       ($sub_command eq "stop") || ($sub_command eq "check")))
  {
    # does not return
    usage();
  }

  # parse user options
  %opt=();
  getopts($flags{$sub_command}, \%opt) or usage($sub_command);
  if ($opt{'s'})
  {
    # do not generate console output - default is not silent.
    $SILENT = 1;
  }

  # command parsing complete

  # verify root access
  if (!lib_am_root())
  {
    lib_error_print_noalert(9130, "Root access required");
    okaload_exit(USM_FAIL);
  }

  if ($sub_command eq 'start')
  {
    if (!lib_oka_supported())
    {
      # OSD specific message generated in lib_oka_supported().
      okaload_exit(USM_FAIL);
    }

    # load the OKA drivers
    $return_code = start();
  }
  elsif ($sub_command eq 'stop')
  {
    # unload the OKA drivers
    $return_code = stop($sub_command);
  }
  else
  {
    # check the OKA drivers
    $return_code = check();
  }

  okaload_exit($return_code);
}

# If the drivers are already loaded, no action is taken
#
sub start
{
  my ($driver);
  my ($return_code);

  lib_inform_print_noalert(641, "Checking for existing OKA installation." );

  # No drivers to load if they are not installed on the system
  if (!lib_check_oka_drivers_installed())
  {
    
    lib_error_print_noalert(642, "OKA not installed");
    return USM_FAIL;
  }

  lib_inform_print_noalert(643, "Validating OKA installation files " .
		   "for operating system.");

  # Make sure that the  drivers are correct for this operating system
  if (!osds_verify_correct_oka_driver_version())
  {
    lib_error_print_noalert(644,
                "OKA drivers not correct for this operating system - cannot load.");
    return USM_FAIL;
  }
  
  lib_inform_print_noalert(637, "Loading installed OKA drivers.");
  

  $return_code = lib_load_oka_drivers();

  if ($return_code)
  {
    lib_error_print_noalert(645, "Not all OKA drivers have been loaded.");
    return USM_FAIL;
  }

  # make sure that the OKA drivers have created the required infrastructure. 
  lib_inform_print_noalert(9327, "Verifying OKA devices.");
  $return_code = lib_verify_oka_devices();
  if ($return_code == USM_FAIL)
  {
    # osds_verify_oka_devices() will print the specific error(s);
    return USM_FAIL;
  }

  lib_inform_print_noalert(9322, "completed");

  print("start command completed\n");

  return USM_SUCCESS;
}

# The most common reason for the failure to unload a driver is if
# some component is currently using it
#
sub stop
{
  my ($sub_command) = @_;

  my ($return_val) = lib_unload_oka_drivers(undef, $sub_command);

  if ($return_val != USM_SUCCESS)
  {
    return USM_FAIL;
  }

  print("stop command completed\n");

  return USM_SUCCESS;
}


# check
#
# If our node is loaded and our drivers are loaded we assume 
# that our resource is online.
# This function always return USM_SUCCESS but the real output
# is at either
# "oracka resource online"
#         or
# "oracka resource offline"
#
sub check
{
  if ( osds_check_oka_loaded() )
  {
    print("oracka resource online\n");
  }
  else
  {
    print ("oracka resource offline\n");
  }

  return USM_SUCCESS;
} 

sub usage
{
  my ($sub_command) = @_;

  lib_error_print_noalert(9228, "usage: %s {start|stop} [-s]", $COMMAND);
  okaload_exit(USM_FAIL);
}

# okaload_exit does not return
#
sub okaload_exit
{
  my ($ret) = @_;

  if (! $is_check)
  {
    # acfsutil cmdlog - $optc handles the Windows/Unix cmd switch '-' or '/'.
    # the 't' option logs the termination of the command.
    #my ($cmd) = sprintf "$ACFSUTIL cmdlog %st $ret $COMMAND", $optc;
    #system($cmd);
  }
  exit $ret;
}
  
main();

