
__author__ = 'Miroslav Bauer'


import os
import sys
import pwd
import grp
import ConfigParser


def _load_configuration():
	''' Load configuration from config file in /etc/datamorph '''
	path = "/etc/datamorph/datamorph.conf"
	if os.path.exists(path):
		cp = ConfigParser.ConfigParser()
		cp.read(path)
		return cp
	print >> sys.stderr, 'Could not find configuration file %s:' % path
	exit(1)


c = _load_configuration()


# Defaults
# --------------------------------------------------------------
DEFAULT_CTRL_ENDPOINT      = '/tmp/datamorph.ctl'
DEFAULT_CTRL_PROTO         = 'ipc'
DEFAULT_ALLOWED_IDS        = ['RECEIVER']
DEFAULT_NUM_WORKERS        = 4
DEFAULT_FILES_OWNER        = 'root'
DEFAULT_RESOURCE_CONFIG    = '/etc/datamorph/agents.cfg'
DEFAULT_RESCHEDULE_TRIES   = 2
DEFAULT_LOG_LEVEL          = 20
DEFAULT_SAGA_LOG_LEVEL     = 0
DEFAULT_LOG_FILE           = '/var/log/datamorph.log'
DEFAULT_ERRORLOG_FILE      = '/var/log/datamorph-error.log'
DEFAULT_CACHING_ENABLED    = False
DEFAULT_HEARTBEAT_INTERVAL = 60


# General configuration
# --------------------------------------------------------------
section = 'general'
FILES_OWNER = c.get(section, 'files_owner') if c.has_option(section, 'files_owner') else DEFAULT_FILES_OWNER
try:
	FILES_OWNER_UID = pwd.getpwnam(FILES_OWNER).pw_uid
	FILES_OWNER_GID = grp.getgrnam(FILES_OWNER).gr_gid
except KeyError, e:
	print >> sys.stderr, e
	exit(1)
RESOURCE_CONFIG = c.get(section, 'resource_config') if c.has_option(section, 'resource_config') else DEFAULT_RESOURCE_CONFIG
if not os.path.isfile(RESOURCE_CONFIG):
	print >> sys.stderr, 'Resouce config file missing: %s' % RESOURCE_CONFIG
	exit(1)

CACHING_ENABLED    = c.getboolean(section, 'caching_enabled') if c.has_option(section, 'caching_enabled') else DEFAULT_CACHING_ENABLED
HEARTBEAT_INTERVAL = c.getint(section, 'heartbeat_interval') if c.has_option(section, 'heartbeat_interval') else DEFAULT_HEARTBEAT_INTERVAL


# Request handler configuration
# --------------------------------------------------------------
section = 'requestapi'
CTRL_PROTO    = c.get(section, 'ctrl_proto') if c.has_option(section, 'ctrl_proto') else DEFAULT_CTRL_PROTO
CTRL_ENDPOINT = c.get(section, 'ctrl_endpoint') if c.has_option(section, 'ctrl_endpoint') else DEFAULT_CTRL_ENDPOINT
ALLOWED_IDS   = c.get(section, 'allowed_ids').split(' ')  if c.has_option(section, 'allowed_ids') else DEFAULT_ALLOWED_IDS
NUM_WORKERS = c.get(section, 'num_workers') if c.has_option(section, 'num_workers') else DEFAULT_NUM_WORKERS


# Scheduler configuration
# --------------------------------------------------------------
section = 'scheduler'
RESCHEDULE_TRIES = c.getint(section, 'reschedule_tries') if c.has_option(section, 'reschedule_tries') else DEFAULT_RESCHEDULE_TRIES
RES_WEIGHT_PREPARING_JOBS = c.getint(section, 'res_weight_preparing_jobs') if c.has_option(section, 'res_weight_preparing_jobs') else 100
RES_WEIGHT_EXECUTING_JOBS = c.getint(section, 'res_weight_executing_jobs') if c.has_option(section, 'res_weight_executing_jobs') else 100
RES_WEIGHT_UNSTAGING_JOBS = c.getint(section, 'res_weight_unstaging_jobs') if c.has_option(section, 'res_weight_unstaging_jobs') else 100
RES_WEIGHT_RELIABILITY = c.getint(section, 'res_weight_reliability') if c.has_option(section, 'res_weight_reliability_jobs') else 100
RES_WEIGHT_EXEC_TIME_AVG = c.getint(section, 'res_weight_exec_time_avg') if c.has_option(section, 'res_weight_exec_time_avg') else 100
RES_WEIGHT_TRANSFER_SPEED_AVG = c.getint(section, 'res_weight_transfer_speed_avg') if c.has_option(section, 'res_weight_transfer_speed_avg') else 100
RES_WEIGHT_LAST_JOB_ASSIGNMENT_TIME = c.getint(section, 'res_weight_last_job_assignment_time') if c.has_option(section, 'res_weight_last_job_assignment_time') else 100

RES_STAT_WEIGHT = {
	'preparing_jobs'           : RES_WEIGHT_PREPARING_JOBS,
	'executing_jobs'           : RES_WEIGHT_EXECUTING_JOBS,
	'unstaging_jobs'           : RES_WEIGHT_UNSTAGING_JOBS,
	'jobs_failed'              : 1,
	'jobs_processed'           : 1,
	'reliability'              : RES_WEIGHT_RELIABILITY,
	'exec_time_avg'            : RES_WEIGHT_EXEC_TIME_AVG,
	'transfer_speed_avg'       : RES_WEIGHT_TRANSFER_SPEED_AVG,
	'last_job_assignment_time' : RES_WEIGHT_LAST_JOB_ASSIGNMENT_TIME,
}


# Logging configuration
# --------------------------------------------------------------
section = 'logging'
LOG_LEVEL      = c.getint(section, 'log_level') if c.has_option(section, 'log_level') else DEFAULT_LOG_LEVEL
SAGA_LOG_LEVEL = c.getint(section, 'saga_log_level') if c.has_option(section, 'saga_log_level') else DEFAULT_SAGA_LOG_LEVEL
LOG_FILE       = c.get(section, 'log_file') if c.has_option(section, 'log_file') else DEFAULT_LOG_FILE
ERRORLOG_FILE  = c.get(section, 'errorlog_file') if c.has_option(section, 'errorlog_file') else DEFAULT_ERRORLOG_FILE


# Constants not configurable from main config file
# ==============================================================

# Timeouts
# --------------------------------------------------------------
WAITING_TIMEOUT = 30 #s

# Jobs configuration
# --------------------------------------------------------------
JOB_EXTERNAL_STATE = {
        'queued'      : 1,
        'scheduled'   : 2,
        'preparing'   : 3,
        'executing'   : 4,
        'finishing'   : 5,
        'rescheduled' : 6,
        'finished'    : 8
}

# Resource configuration
# ---------------------------------------------------------------

RES_SAVE_PATH = '/tmp/datamorph/ressave-'

RES_STATE = {
	'offline'      : 0,
	'online'       : 1,
	'inaccessible' : 2
}
