#!/usr/bin/env python3
# Copyright (c) 2009 Arastra, Inc.  All rights reserved.
# Arastra, Inc. Confidential and Proprietary.

"""Initializes Sysdb by executing LoadConfig and then LoadExtensionStatus.

This script is run by Sysdb at the time that the Sysdb process starts."""

import Tac
import os, sys, EosInit
import LoadExtensionStatus

statusFileDefault = "/var/run/extension-status"
statusFile = os.environ.get( "BOOT_EXT_STATUS_FILE", statusFileDefault )
extensionsDirDefault = "/mnt/flash/.extensions"
extensionsDir = os.environ.get( "EXTENSIONS_DIR", extensionsDirDefault )

def main():
   import optparse # pylint: disable=import-outside-toplevel,deprecated-module
   parser = optparse.OptionParser()
   parser.add_option( "-s", "--sysname", action="store", default="ar",
                      help="System name (default: %default)" )
   parser.add_option( "", "--ssoStandby", action="store_true",
                      help="SSO standby mode" )
   options, args = parser.parse_args()
   if args:
      parser.error( "unexpected arguments" )

   exitcode = 0

   if not options.ssoStandby:
      # timeout settable for tests
      timeout = os.environ.get( "EOSINIT_CONFIG_AGENT_TIMEOUT" )
      timeoutArg = [ "--timeout=" + timeout ] if timeout is not None else [ ]
      
      try:
         Tac.run( [ sys.executable, "/usr/bin/wfw", "--sysname", options.sysname,
                    "ConfigAgent" ] + timeoutArg )
      except Tac.SystemCommandError as e: # pylint: disable=unused-variable
         sys.stderr.write( "Warning: ConfigAgent failed to warm up; "
                           "other failures likely.\n" )
      try:
         # pylint: disable-next=consider-using-with
         outputFile = open( EosInit.startupConfigOutputPath, 'w' )
         Tac.run( [ sys.executable, "/usr/bin/LoadConfig", "--sysname",
                    options.sysname ] + timeoutArg, stdout=outputFile )
      except Tac.SystemCommandError as e:
         exitcode = e.error

      # Now try loading .fragment files. These have no effect on
      # running-config -- they just identify which fragments exist,
      # and which config cmds are associated with each fragment.
      try:
         sys.stderr.write( "Launching LoadFragmentFiles" )
         # LoadFragmentFiles is a script created in CliFragment/ package.
         # can't output to a file if we use asDaemon, so inherit instead
         Tac.run( [ sys.executable, "/usr/bin/LoadFragmentFiles", "--sysname",
                    options.sysname ] + timeoutArg,
                  stdout=Tac.INHERIT,
                  stderr=Tac.INHERIT,
                  # We don't want to wait for it, because nothing critical in
                  # switch startup depends on this. It must complete before we
                  # make any committed changes to fragment configs, but that
                  # can be deferred until fragment loading completes.
                  # Another reason to not wait for it is that (unlike loading
                  # startup-config) the fragment implementation depends on
                  # fragment management code, which may depend on startup-config
                  # being loaded, or Sysdb being initialized or... which may
                  # depend in turn on SysdbInit completing. Sysdb isn't marked
                  # 'initialized' until after SysdbInit completely returns.
                  asDaemon=True )
      except Tac.SystemCommandError as e:
         # Failure of loading fragment configs is not sufficient cause to
         # kill Sysdb (the actual config was already stored in startup-config),
         # but we must print a warning
         sys.stderr.write(
            "LoadFragmentFiles failed with code {e.error}, '{e.output}'" )
   # For help in debugging, it would be good to know that we've progressed
   # beyond the Tac.run(). 
   sys.stderr.write( f"LoadFragmentFiles completed (earlier exitcode: {exitcode})" )
   try:
      Tac.run( [ sys.executable, "/usr/bin/" + LoadExtensionStatus.name(),
                 "--sysname", options.sysname, "--config", statusFile, "--dir",
                 extensionsDir ] )
   except Tac.SystemCommandError as e:
      # If SysdbInit returns a non-zero error code Sysdb will die.  We don't
      # consider failure to load the extension status into Sysdb a serious
      # enough condition to kill Sysdb, so we ignore this error.
      # pylint: disable-next=consider-using-f-string
      sys.stderr.write( "LoadExtensionsStatus exited with code %d\n" % e.error )
    
   sys.exit( exitcode )

if __name__ == '__main__':
   main()
