# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
import logging
import os.path
from os import listdir
import re
from cs.CsDatabag import CsDataBag
from .CsProcess import CsProcess
from .CsFile import CsFile
from . import CsHelper

HAPROXY_CONF_T = "/etc/haproxy/haproxy.cfg.new"
HAPROXY_CONF_P = "/etc/haproxy/haproxy.cfg"

SSL_CERTS_DIR = "/etc/cloudstack/ssl/"

class CsLoadBalancer(CsDataBag):
    """ Manage Load Balancer entries """

    def process(self):
        if "config" not in list(self.dbag.keys()):
            return
        if 'configuration' not in list(self.dbag['config'][0].keys()):
            return
        if 'ssl_certs' in list(self.dbag['config'][0].keys()):
            self._create_pem_for_sslcert(self.dbag['config'][0]['ssl_certs'])

        config = self.dbag['config'][0]['configuration']
        file1 = CsFile(HAPROXY_CONF_T)
        file1.empty()
        for x in config:
            [file1.append(w, -1) for w in x.split('\n')]

        file1.commit()
        file2 = CsFile(HAPROXY_CONF_P)
        if not file2.compare(file1):
            # Verify new haproxy config before haproxy restart/reload
            haproxy_err = self._verify_haproxy_config(HAPROXY_CONF_T)
            if haproxy_err:
                raise Exception("haproxy config is invalid with error \n%s" % haproxy_err)

            CsHelper.copy(HAPROXY_CONF_T, HAPROXY_CONF_P)

            proc = CsProcess(['/run/haproxy.pid'])
            if not proc.find():
                logging.debug("CsLoadBalancer:: will restart HAproxy!")
                CsHelper.service("haproxy", "restart")
            else:
                logging.debug("CsLoadBalancer:: will reload HAproxy!")
                CsHelper.service("haproxy", "reload")

        add_rules = self.dbag['config'][0]['add_rules']
        remove_rules = self.dbag['config'][0]['remove_rules']
        stat_rules = self.dbag['config'][0]['stat_rules']
        self._configure_firewall(add_rules, remove_rules, stat_rules)

    def _configure_firewall(self, add_rules, remove_rules, stat_rules):
        firewall = self.config.get_fw()

        logging.debug("CsLoadBalancer:: configuring firewall. Add rules ==> %s" % add_rules)
        logging.debug("CsLoadBalancer:: configuring firewall. Remove rules ==> %s" % remove_rules)
        logging.debug("CsLoadBalancer:: configuring firewall. Stat rules ==> %s" % stat_rules)

        for rules in add_rules:
            path = rules.split(':')
            ip = path[0]
            port = path[1]
            firewall.append(["filter", "", "-A INPUT -p tcp -m tcp -d %s --dport %s -m state --state NEW -j ACCEPT" % (ip, port)])

        for rules in remove_rules:
            path = rules.split(':')
            ip = path[0]
            port = path[1]
            firewall.append(["filter", "", "-D INPUT -p tcp -m tcp -d %s --dport %s -m state --state NEW -j ACCEPT" % (ip, port)])

        for rules in stat_rules:
            path = rules.split(':')
            ip = path[0]
            port = path[1]
            firewall.append(["filter", "", "-A INPUT -p tcp -m tcp -d %s --dport %s -m state --state NEW -j ACCEPT" % (ip, port)])

    def _create_pem_for_sslcert(self, ssl_certs):
        logging.debug("CsLoadBalancer:: creating new pem files in %s and cleaning up it" % SSL_CERTS_DIR)
        if not os.path.exists(SSL_CERTS_DIR):
            CsHelper.execute("mkdir -p %s" % SSL_CERTS_DIR)
        cert_names = []
        for cert in ssl_certs:
            cert_names.append(cert['name'] + ".pem")
            file = CsFile("%s/%s.pem" % (SSL_CERTS_DIR, cert['name']))
            file.empty()
            file.add("%s\n" % cert['cert'].replace("\r\n", "\n"))
            if 'chain' in cert.keys():
                file.add("%s\n" % cert['chain'].replace("\r\n", "\n"))
            file.add("%s\n" % cert['key'].replace("\r\n", "\n"))
            file.commit()
        for f in listdir(SSL_CERTS_DIR):
            if f not in cert_names:
                CsHelper.execute("rm -rf %s/%s" % (SSL_CERTS_DIR, f))

    def _verify_haproxy_config(self, config):
        ret = CsHelper.execute2("haproxy -c -f %s" % config)
        if ret.returncode:
            stdout, stderr = ret.communicate()
            logging.error("haproxy config is invalid with error: %s" % stderr)
            return stderr
        return ""
