from django.http import HttpResponse, HttpResponseServerError
from core.models import *
from services.hpc.models import *
from services.requestrouter.models import *
import xos.settings
import json
import os
import time

def get_service_slices(service):
    try:
       return service.slices.all()
    except:
       # this field used to be improperly named, and makemigrations won't fix it
       return service.service.all()

def HpcConfig(request):
    hpcSlice=None
    cmiSlice=None
    redirSlice=None
    demuxSlice=None

    node_slicename = request.GET.get("slicename", None)
    if not node_slicename:
        return HttpResponseServerError("Error: no slicename passed in request")

    # search for an HPC Service that owns the slicename that was passed
    # to us.
    hpc=None
    for candidate in HpcService.objects.all():
        if candidate.cmi_hostname == node_slicename:
            # A hack for standalone CMIs that aren't managed by XOS. Set
            # /etc/slicename to cmi_hostname that's configured in the
            # HPCService object.
            hpc = candidate

        for slice in get_service_slices(candidate):
            if slice.name == node_slicename:
                hpc = candidate

    if (not hpc):
        return HttpResponseServerError("Error: no HPC service")

    for slice in get_service_slices(hpc):
        if "cmi" in slice.name:
            cmiSlice = slice
        elif ("hpc" in slice.name) or ("vcoblitz" in slice.name):
            hpcSlice = slice
        elif "redir" in slice.name:
            redirSlice = slice
        elif "demux" in slice.name:
            demuxSlice = slice

    if (hpc.cmi_hostname):
        cmi_hostname = hpc.cmi_hostname
    else:
        if not cmiSlice:
            return HttpResponseServerError("Error: no CMI slice")

        if len(cmiSlice.instances.all())==0:
            return HttpResponseServerError("Error: CMI slice has no instances")

        # for now, assuming using NAT
        cmi_hostname = cmiSlice.instances.all()[0].node.name

    if not hpcSlice:
        return HttpResponseServerError("Error: no HPC slice")

    if (redirSlice==None) or (demuxSlice==None):
        # The HPC Service didn't have a dnsredir or a dnsdemux, so try looking
        # in the RequestRouterService for one.

        rr = RequestRouterService.objects.all()
        if not (rr):
            return HttpResponseServerError("Error: no RR service")

        rr = rr[0]
        try:
           slices = rr.slices.all()
        except:
           # this field used to be improperly named, and makemigrations won't fix it
           slices = rr.service.all()
        for slice in slices:
            if "redir" in slice.name:
                redirSlice = slice
            elif "demux" in slice.name:
                demuxSlice = slice

    if not redirSlice:
        return HttpResponseServerError("Error: no dnsredir slice")

    if not demuxSlice:
        return HttpResponseServerError("Error: no dnsdemux slice")

    d = {}
    d["hpc_slicename"] = hpcSlice.name
    d["redir_slicename"] = redirSlice.name
    d["demux_slicename"] = demuxSlice.name
    d["cmi_hostname"] = cmi_hostname
    d["xos_hostname"] = xos.settings.RESTAPI_HOSTNAME
    d["xos_port"] = str(xos.settings.RESTAPI_PORT)

    if hpc.hpc_port80:
        d["hpc_port80"] = "True"
    else:
        d["hpc_port80"] = "False"

    return HttpResponse("""# auto-generated by HpcConfig
ENABLE_PLC=False
ENABLE_PS=True
BASE_HRN="princeton"
RELEVANT_SERVICE_NAMES=['vcoblitz', 'coredirect', 'codnsdemux', "syndicate_comon_server"]
COBLITZ_SLICE_NAME=BASE_HRN+"_vcoblitz"
COBLITZ_SLICE_ID=70
COBLITZ_PS_SLICE_NAME="{hpc_slicename}"
DNSREDIR_SLICE_NAME=BASE_HRN+"_coredirect"
DNSREDIR_SLICE_ID=71
DNSREDIR_PS_SLICE_NAME="{redir_slicename}"
DNSDEMUX_SLICE_NAME=BASE_HRN+"_codnsdemux"
DNSDEMUX_SLICE_ID=69
DNSDEMUX_PS_SLICE_NAME="{demux_slicename}"
CMI_URL="http://{cmi_hostname}/"
CMI_HTTP_PORT="8004"
CMI_HTTPS_PORT="8003"
PUPPET_MASTER_HOSTNAME="{cmi_hostname}"
PUPPET_MASTER_PORT="8140"
PS_HOSTNAME="{xos_hostname}"
PS_PORT="{xos_port}"
COBLITZ_PORT_80={hpc_port80}
""".format(**d))

