#!/usr/bin/env python
#
# Copyright 2006-2016 Hunan Kylin, Inc.  All Rights Reserved.
# 
# NOTICE: ALL INFORMATION CONTAINED HEREIN IS, AND REMAINS THE PROPERTY OF
# HUNAN KYLIN, INC. AND ITS SUPPLIERS, IF ANY. THE INTELLECTUAL AND
# TECHNICAL CONCEPTS CONTAINED HEREIN ARE PROPRIETARY TO HUNAN KYLIN, INC.
# AND ITS SUPPLIERS AND MAY BE COVERED BY U.S. AND FOREIGN PATENTS, PATENTS IN
# PROCESS, AND ARE PROTECTED BY TRADE SECRET OR COPYRIGHT LAW. DISSEMINATION
# OF THIS INFORMATION OR REPRODUCTION OF THIS MATERIAL IS STRICTLY FORBIDDEN
# UNLESS PRIOR WRITTEN PERMISSION IS OBTAINED FROM HUNAN KYLIN, INC.
#
# -*- coding: utf-8 -*-

#
# Main source file for the "ksvd-dump-net-config" executable.
# Prints the network configuration either from file, or from the
# hardware configuration
#

import sys
import errno
import traceback
from os.path import join, dirname, abspath, basename

# Find our python libraries
sys.path.append(join(dirname(dirname(abspath(sys.argv[0]))), 'etc/python'))

import KsvdUtil
from KsvdUtil import xl_
import KsvdEnv
import KsvdApp
import KsvdNetConfig
import KsvdScreen



class KsvdAutoNetworkConfigApp(KsvdApp.KsvdApp):
	#
	# Initialize the application framework
	#
	def __init__(self, appArgs):
		KsvdApp.KsvdApp.__init__(
			self,
			appArgs)

	#
	# Options other than the standard ones (-v, -V, -i, -l)
	#
	def AddOptions(self):
		self.parser.add_option(
			'-f', '--file',
			help = xl_('Auto-configuration file to use.'),
			default = '',
			metavar = 'FILE')
		self.parser.add_option(
			'-F', '--force',
			action = 'store_true',
			default = False,
			help = xl_('Force a new configuration from auto-config file.'))
		self.parser.add_option(
			'-n', '--nowrite',
			action = 'store_true',
			default = False,
			help = xl_('Dry run. Do not actually create new configuration.'))
		self.parser.add_option(
			'-s', '--start',
			action = 'store_true',
			default = False,
			help = xl_('Start System Services after creating configuration.'))

	#
	# Create a network configuration from the auto-config file
	#
	def InvokeApp(self):
		# Is the file specified  at all?
		# (Error if not specified)
		if not len(self.options.file):
			KsvdScreen.PrintError(xl_(
				'A network auto-configuration file must be specified.'))
			return errno.EINVAL

		# Is the file there at all?
		# (Error if not there, but not necessarily an error in the broader realm.
		#  This condition should be pre-screened by the caller of this utility.)
		if not KsvdUtil.FileExists(self.options.file):
			KsvdScreen.PrintError(xl_(
				'The specified network auto-configuration file does not exist.'))
			return errno.ENOENT

		# An auto-config file exists:
		# Is the auto-config file newer than current configuration?
		useNewConfig = KsvdNetConfig.AutoConfigIsNewer() or self.options.force
		if useNewConfig:
			# Does the file compile?
			# (Considered an error if it does not compile)
			sys.path.append(dirname(abspath(self.options.file)))
			if basename(abspath(self.options.file)).endswith('.py'):
				moduleName = basename(abspath(self.options.file))[:-3]
			else:
				moduleName = basename(abspath(self.options.file))
			try:
				config = __import__(moduleName, globals(), locals(), ['host'], -1)
			except:
				traceString = traceback.format_exc()
				KsvdScreen.PrintError(xl_(
					'There is an error in the format of the auto-configuration file.'
					'\n%(trace)s')
					%{'trace':traceString})
				return errno.EBADF

			# Is this a non-configuration? (the default KsvdConfig.py file)
			if config.host == None:
				if not KsvdNetConfig.NetworkConfigExists():
					# If the auto-config file is a non-configuration and there is no .pkl file,
					# warn, but don't treat as an error.
					if not self.options.quiet:
						KsvdScreen.PrintWarning(xl_(
							'There is no valid configuration in the auto-configuration file.'))
					return 0
				# If a newer non-configuration and a .pkl file does exist, this is an upgrade, so
				# use the older .pkl file anyway.
				useNewConfig = False

		if not useNewConfig:
			if self.options.start:
				# Restore original configuration and use it.
				currNetCfg = KsvdNetConfig.RestoreConfigFromFile()
				if not currNetCfg:
					KsvdScreen.PrintError(xl_(
						'Errors found in current configuration. Nothing done.'))
					return errno.EIO
		else:
			# Create a new configuration:
			# Is the file a "valid" configuration? (Error if invalid)
			problem = config.host.ValidityCheck()
			if problem != None:
				KsvdScreen.PrintError(xl_(
					'There is an error in the content of the auto-configuration file.'
					'\n%(problem)s')%{'problem': problem})
				return errno.EFAULT

			# Create the configuration
			currNetCfg = config.host.CreateConfiguration()

			# (Over-)Write the configuraion (.pkl "pickle" file)
			if not currNetCfg:
				KsvdScreen.PrintError(xl_(
					'Errors found in current configuration. Nothing done.'))
				return errno.EIO
			if self.options.nowrite and not self.options.quiet:
				KsvdScreen.PrintWarning(xl_(
					'--nowrite option selected. Nothing done.'))
				return 0
			currNetCfg.somethingHasChanged = True
			KsvdScreen.PrintWarning(xl_('KsvdConfig.py newer than KsvdNetConfig.pkl OR force = True, write new info to KsvdNetConfig.pkl from KsvdConfig.py'))
			currNetCfg.StoreNetworkConfiguration(networkTestNeeded = False)

		# Start up Networking and Ksvd if called for
		if self.options.start:
			return currNetCfg.StartNetworkAndConfigureKsvd()
		return 0

# Run this program, that's all.
KsvdAutoNetworkConfigApp(appArgs = sys.argv).RunApp()

