# 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 ""