#!/usr/local/bin/perl
# 
#
# afdload.pl
# 
# Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
#
#    NAME
#      afdload.pl - <one-line expansion of the name>
#
#    DESCRIPTION
#      <short description of component this file declares/defines>
#
#    NOTES
#      <other useful comments, qualifications, etc.>
#
# 

use strict;
use Getopt::Std;
use Cwd 'abs_path';
use IO::Handle;
use acfslib;
use afdlib;
use osds_afdload;

# 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 = shift(@ARGV);

  # supplied by user
  $sub_command = shift(@ARGV);

  # 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 (!defined($sub_command))
  {
    # does not return
    usage("", CLSAGFW_AE_FAIL);
  }

  if ($sub_command eq "-h")
  {
    usage("", USM_SUCCESS);
  }
  elsif (!(($sub_command eq "start") || ($sub_command eq "stop") 
                                     || ($sub_command eq "check")))
  {
    #If we are here. This is an invalid option.
    #Removing leading "-" in $sub_command. I'm getting the following error:
    $sub_command =~ s/^[-]+//;
    if (!($sub_command eq "help"))
    {
      lib_error_print(532, "invalid option: %s", $sub_command);
    }
    # does not return
    usage("", CLSAGFW_AE_FAIL);
  }

  # parse user options
  %opt=();
  getopts($flags{$sub_command}, \%opt) or usage($sub_command, CLSAGFW_AE_FAIL);
  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(9130, "Root access required");
    afdload_exit(USM_FAIL);
  }

  if ($sub_command eq 'start')
  {
    if (!lib_asmlib_installed() || !lib_afd_supported())
    {
      # OSD specific message generated in lib_afd_supported().
      afdload_exit(USM_FAIL);
    }

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

  afdload_exit($return_code);
}

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

  lib_inform_print(641, "Checking for existing AFD installation." );

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

  lib_inform_print(643, "Validating AFD installation files " .
		   "for operating system.");

  # Make sure that the  drivers are correct for this operating system
  if (!osds_verify_correct_afd_driver_version())
  {
    lib_error_print(644,
                "AFD drivers not correct for this operating system - cannot load.");
    return USM_FAIL;
  }
  
  lib_inform_print(9393, "Verifying ASM administrator setup.");

  # if the asmadmin name has changed, re-create the udev entries
  osds_check_afd_asmadmin_changed();


  lib_inform_print(637, "Loading installed AFD drivers.");
  

  $return_code = lib_load_afd_drivers();

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

  # Post driver load, create /dev/oracleafd/disks
  $return_code = lib_afd_post_load_setup();
  if ($return_code != USM_SUCCESS)
  {
    # lib_afd_post_load_setup() will print the specific error, if any;
    return USM_FAIL;
  }

  lib_inform_print(9322, "completed");

  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_afd_drivers(undef, $sub_command);

  if ($return_val == USM_SUCCESS)
  {
    # delete /dev/oracleafd/disks if driver unload was successful
    lib_afd_delete_oracleafd_disks();
  }

  return (($return_val == USM_SUCCESS) ? USM_SUCCESS : USM_FAIL);
}


# check
#
# If we can talk to the control devices, we assume that the drivers
# are loaded and the resource is online.
#
sub check
{
  my ($ret) = USM_FAIL;

  if (afdlib_control_devices_accessible())
  {
    $ret = USM_SUCCESS;
  }

  return $ret;
} 

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

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

# afdload_exit does not return
#
sub afdload_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();

