Permalink
Browse files

OpenVPN management plugin added

  • Loading branch information...
1 parent a4486d5 commit 9a6c2ee5e07a51c93b4e81da0cd39e947eee95cb @ivoronin ivoronin committed Apr 18, 2012
@@ -0,0 +1,18 @@
+# coding=utf-8
+"""OpenVPN Plugin for Ajenti"""
+MODULES = ['main', 'widget', 'config', 'backend', ]
+
+DEPS = [
+ (['any'],
+ [
+ ('app', 'openvpn', 'openvpn'),
+ ])
+]
+
+NAME = 'OpenVPN'
+PLATFORMS = ['any']
+DESCRIPTION = 'OpenVPN Management'
+VERSION = '1'
+GENERATION = 1
+AUTHOR = 'Ilya Voronin'
+HOMEPAGE = 'https://github.com/ivoronin'
View
@@ -0,0 +1,81 @@
+# coding=utf-8
+"""OpenVPN plugin backend"""
+from ajenti.com import Plugin
+from ajenti.utils.error import ConfigurationError
+import manager
+
+class OpenVPNBackend(Plugin):
+ """
+ OpenVPN plugin and widget backend
+ @ivar _m: manager instance
+ """
+ icon = "/dl/openvpn/icon.png"
+ text = "OpenVPN"
+
+ def __init__(self, *args, **kwargs):
+ """
+ Initializes instance variables, creates manager instance and tests connection
+ @return: Nothing
+ """
+ # Retrieve configuration settings
+ addr = self.app.get_config(self).addr
+ password = self.app.get_config(self).password
+ if not addr:
+ raise ConfigurationError("No address specified")
+ # Check if addr is a "host:port" string
+ (host, colon, port) = addr.partition(":")
+ try:
+ if colon:
+ # IPv4/IPv6
+ self._m = manager.manager(host = host, port = int(port), password = password)
+ else:
+ # UNIX Socket
+ self._m = manager.manager(path = addr, password = password)
+ # Test connection
+ self.getpid()
+ except Exception, e:
+ raise ConfigurationError(str(e))
+
+ def _execute(self, func, *args):
+ """
+ OpenVPN management interface is unable to handle more than one connection.
+ This method is used to connect and disconnect (if was not connected manually) every
+ time plugin wants to execute a command.
+ @param func: Function to call
+ @param args: Argument List
+ @return: Function result
+ """
+ if not self._m.connected:
+ self._m.connect()
+ result = self._execute(func, *args)
+ self._m.disconnect()
+ else:
+ result = func(*args)
+ return result
+
+ def connect(self):
+ self._m.connect()
+
+ def disconnect(self):
+ self._m.disconnect()
+
+ def getstatus(self):
+ return self._execute(self._m.status)
+
+ def getstats(self):
+ return self._execute(self._m.stats)
+
+ def killbyaddr(self, addr):
+ return self._execute(self._m.killbyaddr, addr)
+
+ def restartcond(self):
+ return self._execute(self._m.signal, "SIGUSR1")
+
+ def restarthard(self):
+ return self._execute(self._m.signal, "SIGHUP")
+
+ def getmessages(self):
+ return self._execute(self._m.messages)
+
+ def getpid(self):
+ return self._execute(self._m.pid)
View
@@ -0,0 +1,17 @@
+# coding=utf-8
+"""OpenVPN plugin configuration backend"""
+from ajenti.api import ModuleConfig
+from backend import OpenVPNBackend
+
+class OpenVPNConfig(ModuleConfig):
+ """OpenVPN config"""
+ target = OpenVPNBackend
+ platform = ['any']
+
+ labels = {
+ 'addr': 'Management address (host:port or path to UNIX socket)',
+ 'password': 'Management password'
+ }
+
+ addr = ''
+ password = ''
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -0,0 +1,82 @@
+<xml>
+ <toolbar>
+ <button id="condRestart" icon="/dl/core/ui/stock/refresh.png" text="Conditional restart"
+ warning="perform conditional restart. All sessions will be dropped. Are you sure?"/>
+ <button id="hardRestart" icon="/dl/core/ui/stock/service-restart.png" text="Hard restart"
+ warning="perform hard restart. All sessions will be dropped. Are you sure?"/>
+ </toolbar>
+
+ <tabcontrol id="tabs" active="0">
+ <tabheader pid="tabs" text="Status" id="0"/>
+ <tabheader pid="tabs" text="Messages" id="1"/>
+ <tabbody pid="tabs" id="0">
+ <label size="5" text="Load statistics"/>
+ <pad>
+ <lt>
+ <ltr>
+ <ltd>
+ <hcontainer>
+ <image file="/dl/core/ui/stock/service-run.png"/>
+ <label id="nclients"/>
+ </hcontainer>
+ </ltd>
+ <ltd>
+ <hcontainer>
+ <image file="/dl/openvpn/in.png"/>
+ <label id="bytesin"/>
+ </hcontainer>
+ </ltd>
+ <ltd >
+ <hcontainer>
+ <image file="/dl/openvpn/out.png"/>
+ <label id="bytesout"/>
+ </hcontainer>
+ </ltd>
+ </ltr>
+ </lt>
+ </pad>
+ <label size="5" text="Active VPN Clients"/>
+ <pad>
+ <dt id="clients" width="100%">
+ <dtr header="True">
+ <dth/>
+ <dth>
+ <label text="Common Name"/>
+ </dth>
+ <dth>
+ <label text="Real Address"/>
+ </dth>
+ <dth>
+ <label text="Virtual Address"/>
+ </dth>
+ <dth>
+ <label text="Bytes Recieved"/>
+ </dth>
+ <dth>
+ <label text="Bytes Sent"/>
+ </dth>
+ <dth>
+ <label text="Connected Since"/>
+ </dth>
+ <dth/>
+ </dtr>
+ </dt>
+ </pad>
+ </tabbody>
+ <tabbody pid="tabs" id="1">
+ <dt id="messages" width="100%">
+ <dtr header="True">
+ <dth width="160">
+ <label text="Timestamp"/>
+ </dth>
+ <dth>
+ <label text="Flags"/>
+ </dth>
+ <dth>
+ <label text="Text"/>
+ </dth>
+ </dtr>
+ </dt>
+ </tabbody>
+ </tabcontrol>
+</xml>
@@ -0,0 +1,24 @@
+<xml>
+ <lt width="90%">
+ <ltr>
+ <ltd width="40%" spacing="0">
+ <hcontainer>
+ <image file="/dl/core/ui/stock/service-run.png" />
+ <label text="Clients:"/><label id="nclients" />
+ </hcontainer>
+ </ltd>
+ <ltd width="30%" spacing="0">
+ <hcontainer>
+ <image file="/dl/openvpn/in.png" />
+ <label id="bytesin" />
+ </hcontainer>
+ </ltd>
+ <ltd width="30%" spacing="0">
+ <hcontainer>
+ <image file="/dl/openvpn/out.png" />
+ <label id="bytesout" />
+ </hcontainer>
+ </ltd>
+ </ltr>
+ </lt>
+</xml>
View
@@ -0,0 +1,74 @@
+# coding=utf-8
+"""OpenVPN plugin"""
+from ajenti.api import event, CategoryPlugin
+from ajenti.ui import UI
+from ajenti.utils import str_fsize
+from time import ctime, sleep
+from backend import OpenVPNBackend
+
+class OpenVPNPlugin(CategoryPlugin):
+ """OpenVPN plugin
+ @ivar _b: Backend instance"""
+ text = "OpenVPN"
+ icon = "/dl/openvpn/icon.png"
+ folder = "servers"
+
+ def on_init(self):
+ self._b = OpenVPNBackend(self.app)
+
+ @event("button/click")
+ def on_button_click(self, event, params, vars=None):
+ try:
+ if params[0] == "disconnect":
+ # Disconnect tooltip clicked
+ self.put_message("info", self._b.killbyaddr(params[1]))
+ elif params[0] == "condRestart":
+ # "Condional Restart" button clicked
+ self.put_message("info", self._b.restartcond())
+ sleep(2) # Give OpenVPN some time to reload
+ elif params[0] == "hardRestart":
+ # "Hard Restart" button clicked
+ self.put_message("info", self._b.restarthard())
+ sleep(2) # Give OpenVPN some time to reload
+ except Exception, e:
+ self.put_message("err", e)
+
+ def get_ui(self):
+ ui = self.app.inflate("openvpn:main")
+
+ try:
+ self._b.connect()
+ status = self._b.getstatus()
+ stats = self._b.getstats()
+ messages = self._b.getmessages()
+ self._b.disconnect()
+ except Exception, e:
+ self.put_message("err", e)
+ return ui
+
+ ui.find("nclients").set("text", "Clients: {0}".format(stats["nclients"]))
+ ui.find("bytesin").set( "text", "Bytes in: {0}".format(str_fsize(float(stats["bytesin"]))))
+ ui.find("bytesout").set("text", "Bytes out: {0}".format(str_fsize(float(stats["bytesout"]))))
+
+ map(lambda c: ui.append("clients", UI.DTR(
+ UI.Icon(icon="/dl/core/ui/stock/user.png"),
+ UI.Label(text=c["cn"]),
+ UI.Label(text=c["raddress"]),
+ UI.Label(text=c["vaddress"]),
+ UI.Label(text=str_fsize(float(c["brecv"]))),
+ UI.Label(text=str_fsize(float(c["bsent"]))),
+ UI.Label(text=c["connsince"]),
+ UI.TipIcon(
+ icon="/dl/core/ui/stock/delete.png",
+ text="Disconnect",
+ warning="Disconnect {0} ({1})?".format(c["cn"], c["raddress"]),
+ id="disconnect/{0}".format(c["raddress"]))
+ )), status["clients"])
+
+ map(lambda m: ui.append("messages", UI.DTR(
+ UI.Label(text=ctime(float(m[0]))),
+ UI.Label(text=m[1]),
+ UI.Label(text=m[2])
+ )), messages)
+
+ return ui
Oops, something went wrong.

0 comments on commit 9a6c2ee

Please sign in to comment.