def add_server(self, server=None, backend=None): '''Add server with ipaddr in backend section''' self.cfg.reload() if backend: backend = backend.strip() LOG.debug('HAProxyAPI.add_server') LOG.debug(' %s' % haproxy.naming('backend', backend=backend)) bnds = self.cfg.sections(haproxy.naming('backend', backend=backend)) if not bnds: if backend: raise exceptions.NotFound('Backend not found: %s' % (backend, )) else: raise exceptions.Empty('No listeners to add server to') #with self.svc.trans(exit='running'): #with self.cfg.trans(exit='working'): server.setdefault("check", True) server = rename(server) for bnd in bnds: self.cfg.backends[bnd]['server'][self._server_name( server)] = server self.cfg.save() self.svc.reload()
def create_listener(self, port=None, protocol=None, server_port=None, server_protocol=None, backend=None): ''' ''' LOG.debug('create_listener: %s, %s, %s, %s, %s, %s', self, port, protocol, server_port, server_protocol, backend) if protocol: protocol = protocol.lower() ln = haproxy.naming('listen', protocol, port) bnd = haproxy.naming('backend', server_protocol or protocol, server_port or port, backend=backend) return ln, bnd listener = backend = None LOG.debug( 'HAProxyAPI.create_listener: listener = `%s`, backend = `%s`', ln, bnd) try: if self.cfg.listener[ln]: raise 'Duplicate' except Exception, e: if 'Duplicate' in e: raise exceptions.Duplicate('Listener %s:%s already exists' % (protocol, port))
def add_server(self, server=None, backend=None): '''Add server with ipaddr in backend section''' self.cfg.reload() if backend: backend = backend.strip() LOG.debug('HAProxyAPI.add_server') LOG.debug(' %s' % haproxy.naming('backend', backend=backend)) bnds = self.cfg.sections(haproxy.naming('backend', backend=backend)) if not bnds: if backend: raise exceptions.NotFound('Backend not found: %s' % (backend, )) else: raise exceptions.Empty('No listeners to add server to') #with self.svc.trans(exit='running'): #with self.cfg.trans(exit='working'): server.setdefault("check", True) server = rename(server) for bnd in bnds: self.cfg.backends[bnd]['server'][self._server_name(server)] = server self.cfg.save() self.svc.reload()
def add_server(self, ipaddr=None, backend=None): '''Add server with ipaddr in backend section''' self.cfg.reload() if backend: backend=backend.strip() if ipaddr: ipaddr=ipaddr.strip() LOG.debug('HAProxyAPI.add_server') LOG.debug(' %s' % haproxy.naming('backend', backend=backend)) bnds = self.cfg.sections(haproxy.naming('backend', backend=backend)) if not bnds: if backend: raise exceptions.NotFound('Backend not found: %s' % (backend, )) else: raise exceptions.Empty('No listeners to add server to') #with self.svs.trans(exit='running'): #with self.cfg.trans(exit='working'): if True: for bnd in bnds: server = { 'address': ipaddr, 'port': bnd.split(':')[-1], 'check': True } self.cfg.backends[bnd]['server'][ipaddr.replace('.', '-')] = server self.cfg.save() self.svs.reload()
def remove_server(self, server, backend=None): """ Removes server with ipaddr from backend section. :param server: Server configuration. :type server: dict :param server: Backend name. :type backend: str Example:: TBD. """ if backend: backend = backend.strip() srv_name = self._server_name(server) for bd in self.cfg.sections(haproxy.naming('backend', backend=backend)): if ':' in srv_name: if srv_name in self.cfg.backends[bd]['server']: del self.cfg.backends[bd]['server'][srv_name] else: for srv_name_ in list(self.cfg.backends[bd]['server']): if srv_name_.startswith(srv_name): del self.cfg.backends[bd]['server'][srv_name_] self.cfg.save() if self.svc.status() == 0: self.svc.reload()
def list_listeners(self): ''' @return: Listeners list @rtype: [{ <port>, <protocol>, <server_port>, <server_protocol>, <backend>, <servers>: [<ipaddr>, ...] }, ...]''' self.cfg.reload() res = [] for ln in self.cfg.sections(haproxy.naming('listen')): listener = self.cfg.listener[ln] bnd_name = listener['default_backend'] bnd_role = ':'.join(bnd_name.split(':')[2:4]) #example`role:1234` bnd = self.cfg.backends[bnd_name] res.append({ 'port': listener['bind'].replace('*:', ''), 'protocol': listener['mode'], 'server_port': bnd_name.split(':')[-1], 'server_protocol': bnd['mode'], 'backend': bnd_role, }) return res
def delete_listener(self, port=None, protocol=None): ''' Delete listen section(s) by port (and)or protocol ''' ln = haproxy.naming('listen', protocol, port) if not self.cfg.sections(ln): raise exceptions.NotFound('Listen `%s` not found can`t remove it' % ln) try: default_backend = self.cfg.listener[ln]['default_backend'] except: default_backend = None for path in self.cfg.sections(ln): del self.cfg['listen'][ln] LOG.debug('HAProxyAPI.delete_listener: removed listener `%s`' % ln) if default_backend: has_ref = False for ln in self.cfg.listener: try: if self.cfg.listener[ln]['default_backend'] == default_backend: has_ref = True break except: pass if not has_ref: #it not used in other section, so will be deleting del self.cfg.backends[default_backend] try: iptables.FIREWALL.remove({ "jump": "ACCEPT", "protocol": "tcp", "match": "tcp", "dport": port }) except Exception, e: raise exceptions.NotFound(e)
def list_listeners(self): """ :returns: Listeners list :rtype: list Method returns object of the following structure:: [{ <port>, <protocol>, <server_port>, <server_protocol>, <backend>, <servers>: [<ipaddr>, ...] }, ...] """ self.cfg.reload() res = [] for ln in self.cfg.sections(haproxy.naming('listen')): listener = self.cfg.listener[ln] bnd_name = listener['default_backend'] bnd_role = ':'.join(bnd_name.split(':')[2:4]) #example`role:1234` bnd = self.cfg.backends[bnd_name] res.append({ 'port': listener['bind'].replace('*:',''), 'protocol': listener['mode'], 'server_port': bnd_name.split(':')[-1], 'server_protocol': bnd['mode'], 'backend': bnd_role, }) return res
def create_listener(self, port=None, protocol=None, server_port=None, server_protocol=None, backend=None): ''' ''' LOG.debug('create_listener: %s, %s, %s, %s, %s, %s', self, port, protocol, server_port, server_protocol, backend) if protocol: protocol = protocol.lower() ln = haproxy.naming('listen', protocol, port) bnd = haproxy.naming('backend', server_protocol or protocol, server_port or port, backend=backend) listener = backend = None LOG.debug('HAProxyAPI.create_listener: listener = `%s`, backend = `%s`', ln, bnd) try: if self.cfg.listener[ln]: raise 'Duplicate' except Exception, e: if 'Duplicate' in e: raise exceptions.Duplicate('Listener %s:%s already exists' % (protocol, port))
def test_create_listener(self): self.api.create_listener(protocol=self.protocol, port=self.port, server_protocol=self.server_protocol, server_port=self.server_port, backend=self.backend) self.assertEqual(self.api.svs.status(), 0) ln = hap_serv.naming('listen', self.protocol, self.port) bnd = hap_serv.naming('backend', self.server_protocol, self.server_port, backend=self.backend) self.assertEqual(self.api.cfg.backends[bnd]['timeout']['check'], '3s') self.assertEqual(self.api.cfg.listener[ln]['mode'], self.protocol) self.api.cfg.reload() self.assertEqual(self.api.cfg.backends[bnd]['timeout']['check'], '3s') self.assertEqual(self.api.cfg.listener[ln]['mode'], self.protocol) self.assertEqual(self.api.cfg.backends[bnd]['mode'], self.server_protocol)
def remove_server(self, ipaddr, backend=None): '''Remove server from backend section with ipaddr''' if ipaddr: ipaddr = ipaddr.strip() if backend: backend = backend.strip() srv_name = self._server_name(ipaddr) for bd in self.cfg.sections(haproxy.naming('backend', backend=backend)): if ipaddr and srv_name in self.cfg.backends[bd]['server']: del self.cfg.backends[bd]['server'][srv_name] self.cfg.save() self.svs.reload()
def list_servers(self, backend=None): ''' List all servers, or servers from particular backend @rtype: [<ipaddr>, ...] ''' if backend: backend = backend.strip() list_section = self.cfg.sections(haproxy.naming('backend', backend=backend)) res = [] for bnd in list_section: for srv_name in self.cfg.backends[bnd]['server']: res.append(self.cfg.backends[bnd]['server'][srv_name]['address']) res = list(set(res)) return res
def configure_healthcheck(self, target=None, interval=None, timeout=None, unhealthy_threshold=None, healthy_threshold=None): """ APIDOC TBD. """ try: if interval == 'None': interval = None int(interval) interval = '%ss' % interval except: pass try: if timeout == 'None': timeout = None int(timeout) timeout = '%ss' % timeout except: pass bnds = haproxy.naming('backend', backend=target) if not self.cfg.sections(bnds): raise exceptions.NotFound('Backend `%s` not found' % bnds) for bnd in self.cfg.sections(bnds): if timeout: if isinstance(timeout, dict): self.cfg['backend'][bnd]['timeout'] = timeout else: self.cfg['backend'][bnd]['timeout'] = { 'check': str(timeout) } default_server = { 'inter': interval, 'fall': unhealthy_threshold, 'rise': healthy_threshold } self.cfg['backend'][bnd]['default-server'] = default_server for srv in self.cfg['backend'][bnd]['server']: server = self.cfg['backend'][bnd]['server'][srv] server.update({'check': True}) self.cfg['backend'][bnd]['server'][srv] = server #with self.svc.trans(exit='running'): # with self.cfg.trans(enter='reload', exit='working'): self.cfg.save() self.svc.reload()
def reset_healthcheck(self, target): '''Return to defaults for `tartget` backend sections''' target = target.strip() bnds = haproxy.naming('backend', backend=target) if not self.cfg.sections(bnds): raise exceptions.NotFound('Backend `%s` not found' % target) for bnd in self.cfg.sections(bnds): backend = self.cfg['backend'][bnd] backend.update(HEALTHCHECK_DEFAULTS) self.cfg['backend'][bnd] = backend #with self.svc.trans(exit='running'): # with self.cfg.trans(enter='reload', exit='working'): #TODO: with... self.cfg.save() self.svc.reload()
def list_servers(self, backend=None): ''' List all servers, or servers from particular backend @rtype: [<ipaddr>, ...] ''' if backend: backend = backend.strip() list_section = self.cfg.sections( haproxy.naming('backend', backend=backend)) res = [] for bnd in list_section: for srv_name in self.cfg.backends[bnd]['server']: res.append(srv_name) #res.append(self.cfg.backends[bnd]['server'][srv_name]['host']) res = list(set(res)) return res
def list_servers(self, backend=None): """ Lists all servers or servers from particular backend. :returns: List of IP addresses. :rtype: [<ipaddr>, ...] """ if backend: backend = backend.strip() list_section = self.cfg.sections(haproxy.naming('backend', backend=backend)) res = [] for bnd in list_section: for srv_name in self.cfg.backends[bnd]['server']: res.append(srv_name) #res.append(self.cfg.backends[bnd]['server'][srv_name]['host']) res = list(set(res)) return res
def remove_server(self, server, backend=None): '''Remove server from backend section with ipaddr''' if backend: backend = backend.strip() srv_name = self._server_name(server) for bd in self.cfg.sections(haproxy.naming('backend', backend=backend)): if ':' in srv_name: if srv_name in self.cfg.backends[bd]['server']: del self.cfg.backends[bd]['server'][srv_name] else: for srv_name_ in list(self.cfg.backends[bd]['server']): if srv_name_.startswith(srv_name): del self.cfg.backends[bd]['server'][srv_name_] self.cfg.save() if self.svc.status() == 0: self.svc.reload()
def configure_healthcheck(self, target=None, interval=None, timeout=None, unhealthy_threshold=None, healthy_threshold=None): """ APIDOC TBD. """ try: if interval == 'None': interval=None int(interval) interval = '%ss' % interval except: pass try: if timeout == 'None': timeout=None int(timeout) timeout = '%ss' % timeout except: pass bnds = haproxy.naming('backend', backend=target) if not self.cfg.sections(bnds): raise exceptions.NotFound('Backend `%s` not found' % bnds) for bnd in self.cfg.sections(bnds): if timeout: if isinstance(timeout, dict): self.cfg['backend'][bnd]['timeout'] = timeout else: self.cfg['backend'][bnd]['timeout'] = {'check': str(timeout)} default_server = { 'inter': interval, 'fall': unhealthy_threshold, 'rise': healthy_threshold } self.cfg['backend'][bnd]['default-server'] = default_server for srv in self.cfg['backend'][bnd]['server']: server = self.cfg['backend'][bnd]['server'][srv] server.update({'check' : True}) self.cfg['backend'][bnd]['server'][srv] = server #with self.svc.trans(exit='running'): # with self.cfg.trans(enter='reload', exit='working'): self.cfg.save() self.svc.reload()
def delete_listener(self, port=None, protocol=None): """ Removes listen section(s) by port (and)or protocol. """ ln = haproxy.naming('listen', protocol, port) if not self.cfg.sections(ln): raise exceptions.NotFound('Listen `%s` not found can`t remove it' % ln) try: default_backend = self.cfg.listener[ln]['default_backend'] except: default_backend = None for path in self.cfg.sections(ln): del self.cfg['listen'][ln] LOG.debug('HAProxyAPI.delete_listener: removed listener `%s`' % ln) if default_backend: has_ref = False for ln in self.cfg.listener: try: if self.cfg.listener[ln][ 'default_backend'] == default_backend: has_ref = True break except: pass if not has_ref: #it not used in other section, so will be deleting del self.cfg.backends[default_backend] try: if iptables.enabled(): iptables.FIREWALL.remove({ "jump": "ACCEPT", "protocol": "tcp", "match": "tcp", "dport": port }) except Exception, e: raise exceptions.NotFound(e)
def make_proxy(self, port, backend_port=None, backends=None, check_timeout=None, maxconn=None, **default_server_params): """ Add listener and backend sections to the haproxy conf and restart the service. :param port: listener port :type port: int :param backend_port: port for backend server to listen on :type backend_port: int :param backends: list of dicts, each dict represents role or server :type backends: list # :param roles: role ids (ints) or dicts with "id" key # :type roles: list # :param servers: server ips # :type servers: list :param check_timeout: ``timeout check`` - additional read timeout, e.g. "3s" :type check_timeout: str :param maxconn: set ``maxconn`` of the frontend :type maxconn: str :param **default_server_params: following kwargs will be applied to the ``default-server`` key of the backend :param check_interval: value for ``inter``, e.g. "3s" :type check_interval: str :param fall_threshold: value for ``fall`` :type fall_threshold: int :param rise_threshold: value for ``rise`` :type rise_threshold: int :param server_maxconn: value for ``maxconn``, not to confuse with the frontend's ``maxconn`` :type server_maxconn: str :param down: value for ``disabled`` :type down: bool :param backup: value for ``backup`` :type backup: bool :returns: ? .. note:: official documentation on the global parameters and server \ options can be found at \ http://cbonte.github.com/haproxy-dconv/configuration-1.4.html """ # args preprocessing: default values and short forms if not backend_port: backend_port = port # new: backends instead of separate roles/hosts args if not backends: backends = [] roles = filter(lambda spec: "farm_role_id" in spec, backends) servers = filter(lambda spec: "host" in spec, backends) roles = map(lambda x: {"farm_role_id": x} if isinstance(x, int) else dict(x), roles) servers = map(lambda x: {"host": x} if isinstance(x, str) else dict(x), servers) # create a single server list with proper params for each server # 1. extract servers from the roles and apply role params to them roles_servers = [] for role in roles: role_id, role_params = role.pop("farm_role_id"), role role_servers = map(lambda ip: {"host": ip}, get_role_servers(role_id)) LOG.debug("get_role_servers response: %s", pformat(role_servers)) # for testing on a single machine purposes / get_servers retunrs "host:port" for server in role_servers: if ':' in server["host"]: host, port_ = server["host"].split(':') server["host"] = host server["port"] = port_ #/ [server.update(role_params) for server in role_servers] roles_servers.extend(role_servers) # 2. get all servers together, enable healthchecks, ensure `port` and # convert some keys servers.extend(roles_servers) [server.setdefault("check", True) for server in servers] [server.setdefault("port", backend_port) for server in servers] servers = map(rename, servers) LOG.debug(" Backend servers:\n" + pformat(servers)) # construct listener and backend sections for the conf listener_name = haproxy.naming('listen', "tcp", port) backend_name = haproxy.naming('backend', "tcp", port) listener = { 'mode': "tcp", 'balance': 'roundrobin', 'bind': '*:%s' % port, 'default_backend': backend_name, } if maxconn: listener["maxconn"] = maxconn backend = { "mode": "tcp", "server": {}, } backend.update(HEALTHCHECK_DEFAULTS) if check_timeout: backend["timeout"]["check"] = check_timeout backend["default-server"].update(rename(default_server_params)) for server in servers: backend['server'][self._server_name(server)] = server # update the cfg self.cfg['listen'][listener_name] = listener if not self.cfg.backend or not backend_name in self.cfg.backend: self.cfg['backend'][backend_name] = backend if iptables.enabled(): iptables.FIREWALL.ensure( [{"jump": "ACCEPT", "protocol": "tcp", "match": "tcp", "dport": port}] ) self.cfg.save() if self.svc.status() == 0: self.svc.reload()
def make_proxy(self, port, backend_port=None, backends=None, check_timeout=None, maxconn=None, **default_server_params): """ Add listener and backend sections to the haproxy conf and restart the service. :param port: listener port :type port: int :param backend_port: port for backend server to listen on :type backend_port: int :param backends: list of dicts, each dict represents role or server :type backends: list # :param roles: role ids (ints) or dicts with "id" key # :type roles: list # :param servers: server ips # :type servers: list :param check_timeout: ``timeout check`` - additional read timeout, e.g. "3s" :type check_timeout: str :param maxconn: set ``maxconn`` of the frontend :type maxconn: str :param **default_server_params: following kwargs will be applied to the ``default-server`` key of the backend :param check_interval: value for ``inter``, e.g. "3s" :type check_interval: str :param fall_threshold: value for ``fall`` :type fall_threshold: int :param rise_threshold: value for ``rise`` :type rise_threshold: int :param server_maxconn: value for ``maxconn``, not to confuse with the frontend's ``maxconn`` :type server_maxconn: str :param down: value for ``disabled`` :type down: bool :param backup: value for ``backup`` :type backup: bool :returns: ? .. note:: official documentation on the global parameters and server \ options can be found at \ http://cbonte.github.com/haproxy-dconv/configuration-1.4.html """ # args preprocessing: default values and short forms if not backend_port: backend_port = port # new: backends instead of separate roles/hosts args if not backends: backends = [] roles = filter(lambda spec: "farm_role_id" in spec, backends) servers = filter(lambda spec: "host" in spec, backends) roles = map( lambda x: {"farm_role_id": x} if isinstance(x, int) else dict(x), roles) servers = map(lambda x: {"host": x} if isinstance(x, str) else dict(x), servers) # create a single server list with proper params for each server # 1. extract servers from the roles and apply role params to them roles_servers = [] for role in roles: role_id, role_params = role.pop("farm_role_id"), role role_servers = map(lambda ip: {"host": ip}, get_role_servers(role_id)) LOG.debug("get_role_servers response: %s", pformat(role_servers)) # for testing on a single machine purposes / get_servers retunrs "host:port" for server in role_servers: if ':' in server["host"]: host, port_ = server["host"].split(':') server["host"] = host server["port"] = port_ #/ [server.update(role_params) for server in role_servers] roles_servers.extend(role_servers) # 2. get all servers together, enable healthchecks, ensure `port` and # convert some keys servers.extend(roles_servers) [server.setdefault("check", True) for server in servers] [server.setdefault("port", backend_port) for server in servers] servers = map(rename, servers) LOG.debug(" Backend servers:\n" + pformat(servers)) # construct listener and backend sections for the conf listener_name = haproxy.naming('listen', "tcp", port) backend_name = haproxy.naming('backend', "tcp", port) listener = { 'mode': "tcp", 'balance': 'roundrobin', 'bind': '*:%s' % port, 'default_backend': backend_name, } if maxconn: listener["maxconn"] = maxconn backend = { "mode": "tcp", "server": {}, } backend.update(HEALTHCHECK_DEFAULTS) if check_timeout: backend["timeout"]["check"] = check_timeout backend["default-server"].update(rename(default_server_params)) for server in servers: backend['server'][self._server_name(server)] = server # update the cfg self.cfg['listen'][listener_name] = listener if not self.cfg.backend or not backend_name in self.cfg.backend: self.cfg['backend'][backend_name] = backend iptables.FIREWALL.ensure([{ "jump": "ACCEPT", "protocol": "tcp", "match": "tcp", "dport": port }]) self.cfg.save() if self.svc.status() == 0: self.svc.reload()