Giuseppe Lavagetto has uploaded a new change for review.
https://gerrit.wikimedia.org/r/261375
Change subject: [WiP] add native ipvs manager
......................................................................
[WiP] add native ipvs manager
Change-Id: Ic3274ca243584c1bc06d31b8f70d228399146170
---
M pybal/ipvs.py
A pybal/ipvs/__init__.py
A pybal/ipvs/native.py
3 files changed, 174 insertions(+), 5 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/operations/debs/pybal
refs/changes/75/261375/1
diff --git a/pybal/ipvs.py b/pybal/ipvs.py
index 06e73ee..cd0d2db 100644
--- a/pybal/ipvs.py
+++ b/pybal/ipvs.py
@@ -5,8 +5,9 @@
LVS state/configuration classes for PyBal
"""
from . import util
-
+from ipvs import native
import os
+
log = util.log
@@ -37,8 +38,6 @@
stdin.close()
# FIXME: Check return code and act on failure
-
-
@staticmethod
def subCommandService(service):
@@ -155,8 +154,6 @@
"""Class that maintains the state of a single LVS service
instance."""
- ipvsManager = IPVSManager
-
SVC_PROTOS = ('tcp', 'udp')
SVC_SCHEDULERS = ('rr', 'wrr', 'lc', 'wlc', 'lblc', 'lblcr', 'dh', 'sh',
'sed', 'nq')
@@ -178,6 +175,11 @@
self.configuration = configuration
+ if configuration.getboolean('native_ipvs', False):
+ self.ipvsManager = native.IPVSManager
+ else:
+ self.ipvsManager = IPVSManager
+
self.ipvsManager.DryRun = configuration.getboolean('dryrun', False)
self.ipvsManager.Debug = configuration.getboolean('debug', False)
diff --git a/pybal/ipvs/__init__.py b/pybal/ipvs/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/pybal/ipvs/__init__.py
diff --git a/pybal/ipvs/native.py b/pybal/ipvs/native.py
new file mode 100644
index 0000000..49cd996
--- /dev/null
+++ b/pybal/ipvs/native.py
@@ -0,0 +1,167 @@
+# Use github.com/lavagetto/gnlpy, not the facebook's one
+from gnlpy import ipvs as netlink
+from pybal import util
+import socket
+
+log = util.log
+
+
+class IpvsCommand(object):
+ _protocols = {
+ 'tcp': socket.IPPROTO_TCP,
+ 'udp': socket.IPPROTO_UDP
+ }
+
+ def run(self, client):
+ raise NotImplementedError()
+
+ def log(self):
+ raise NotImplementedError()
+
+
+class IpvsCommandService(netlink.Service, IpvsCommand):
+
+ def __init__(self, service):
+ self._action = 'add'
+ # Let's call the init of the service
+ super(IpvsCommandService, self).__init__(
+ IpvsCommandService._from_tuple(service),
+ validate=True)
+
+ @staticmethod
+ def _from_tuple(tup):
+ return {
+ 'proto': tup[0],
+ 'vip': tup[1],
+ 'port': tup[2],
+ 'sched': tup[3] if len(tup) > 3 else 'rr'
+ }
+
+ def log(self):
+ if self.action == 'add':
+ log.debug("Adding service '%s://%s:%d' with scheduler %s",
+ self.proto_, self.vip_, self.port_, self.sched_)
+ elif self.action == 'del':
+ log.debug("Removing service '%s://%s:%d'", self.proto_, self.vip_,
+ self.port_)
+
+ def proto(self):
+ return self._protocols.get(self.proto_, socket.IPPROTO_TCP)
+
+ def run(self, client):
+ if self.action == 'add':
+ client.add_service(self.vip_, self.port_, protocol=self.proto(),
+ sched_name=self.sched_)
+ elif self.action == 'del':
+ client.del_service(self.vip_, self.port_, protocol=proto)
+ else:
+ raise ValueError("Action %s is not supported", self.action)
+
+
+class IpvsCommandServer(netlink.Server, IpvsCommand):
+
+ def __init__(self, server, service):
+ """
+ Manages addition of a server to a pool
+ """
+ self.action = 'add'
+ self.ip_ = server.ip or socket.gethostbyname(server.host)
+ self.weight_ = server.weight or 1
+ self.port_ = server.port
+ self.fwd_method_ = netlink.IPVS_ROUTING
+ self.service = IpvsCommandService(service)
+ self.validate()
+
+ def log(self):
+ log.debug("%s server %s to service %s:%d with weight %d",
+ self.action.upper(), self.ip_, self.vip_, self.port_,
+ self.weight_)
+
+ def run(self, client):
+ if self.action == 'add':
+ client.add_dest(self.service.vip(), self.port_, self.ip_,
+ protocol=self.service.proto(), weight=self.weight_,
+ method=self.fwd_method_)
+ elif self.action == 'del':
+ client.del_dest(self.service.vip(), self.port_, self.ip_,
+ protocol=self.service.proto())
+ elif self.action == 'edit':
+ client.update_dest(self.service.vip(), self.port_, self.ip_,
+ protocol=self.service.proto(),
+ weight=self.weight_, method=self.fwd_method_)
+ else:
+ raise ValueError("Action %s is not supported", self.action)
+
+
+class IPVSManager(object):
+ """Class that provides the ability to manage ipvs pools via the netlink
library"""
+
+ DryRun = True
+
+ Debug = False
+
+ @staticmethod
+ def get_client(cls):
+ return netlink.IpvsClient()
+
+ @classmethod
+ def modifyState(cls, cmdList):
+ client = cls.get_client()
+ for cmd in cmdList:
+ if cls.Debug:
+ cmd.log()
+ if not cls.DryRun:
+ cmd.run(client)
+
+ @classmethod
+ def commandRemoveService(cls, service):
+ """Returns an ipvsadm command to remove a single service."""
+ srv = IpvsCommandService(service)
+ srv.action = 'del'
+ return srv
+
+ @classmethod
+ def commandAddService(cls, service):
+ """Returns an ipvsadm command to add a specified service.
+
+ Arguments:
+ service: tuple(protocol, address, port, ...)
+ """
+ srv = IpvsCommandService(service)
+ return srv
+
+ @classmethod
+ def commandRemoveServer(cls, service, server):
+ """Returns an ipvsadm command to remove a server from a service.
+
+ Arguments:
+ service: tuple(protocol, address, port, ...)
+ server: Server
+ """
+ host = IpvsCommandServer(server, service)
+ host.action = 'del'
+ return host
+
+ @classmethod
+ def commandAddServer(cls, service, server):
+ """Returns an ipvsadm command to add a server to a service.
+
+ Arguments:
+ service: tuple(protocol, address, port, ...)
+ server: Server
+ """
+ host = IpvsCommandServer(server, service)
+ return host
+
+ @classmethod
+ def commandEditServer(cls, service, server):
+ """Returns an ipvsadm command to edit the parameters of a
+ server.
+
+ Arguments:
+ service: tuple(protocol, address, port, ...)
+ server: Server
+ """
+ host = IpvsCommandServer(server, service)
+ host.action = 'edit'
+ return host
--
To view, visit https://gerrit.wikimedia.org/r/261375
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ic3274ca243584c1bc06d31b8f70d228399146170
Gerrit-PatchSet: 1
Gerrit-Project: operations/debs/pybal
Gerrit-Branch: master
Gerrit-Owner: Giuseppe Lavagetto <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits