diff --git a/bumblebee/modules/vpn.py b/bumblebee/modules/vpn.py new file mode 100644 index 0000000..149e547 --- /dev/null +++ b/bumblebee/modules/vpn.py @@ -0,0 +1,92 @@ +# pylint: disable=C0111,R0903 + +""" Displays the VPN profile that is currently in use. + + Left click opens a popup menu that lists all available VPN profiles and allows to establish + a VPN connection using that profile. + + Prerequisites: + * nmcli needs to be installed and configured properly. + To quickly test, whether nmcli is working correctly, type "nmcli -g NAME,TYPE,DEVICE con" which + lists all the connection profiles that are configured. Make sure that your VPN profile is in that list! + + e.g: to import a openvpn profile via nmcli: + sudo nmcli connection import type openvpn file +""" + +import logging +import bumblebee.input +import bumblebee.output +import bumblebee.engine +import functools + +class Module(bumblebee.engine.Module): + def __init__(self, engine, config): + super(Module, self).__init__(engine, config, + bumblebee.output.Widget(full_text=self.vpn_status) + ) + + self._connected_vpn_profile = None + self._selected_vpn_profile = None + + res = bumblebee.util.execute("nmcli -g NAME,TYPE c") + lines = res.splitlines() + + self._vpn_profiles = [] + for line in lines: + info = line.split(':') + if info[1] == "vpn": + self._vpn_profiles.append(info[0]) + + engine.input.register_callback(self, button=bumblebee.input.LEFT_MOUSE, + cmd=self.popup) + + def update(self, widgets): + try: + res = bumblebee.util.execute("nmcli -g NAME,TYPE,DEVICE con") + lines = res.splitlines() + self._connected_vpn_profile = None + for line in lines: + info = line.split(':') + if info[1] == "vpn" and info[2] != "": + self._connected_vpn_profile = info[0] + + except Exception as e: + logging.exception("Couldn't get VPN status") + self._connected_vpn_profile = None + + def vpn_status(self, widget): + if self._connected_vpn_profile is None: + return "off" + return self._connected_vpn_profile + + def _on_vpn_disconnect(self): + try: + bumblebee.util.execute("nmcli c down " + self._connected_vpn_profile) + self._connected_vpn_profile = None + except Exception as e: + logging.exception("Couldn't disconnect VPN connection") + + def _on_vpn_connect(self, name): + self._selected_vpn_profile = name + + try: + bumblebee.util.execute("nmcli c up " + self._selected_vpn_profile) + self._connected_vpn_profile = name + except Exception as e: + logging.exception("Couldn't establish VPN connection") + self._connected_vpn_profile = None + + def popup(self, widget): + menu = bumblebee.popup_v2.PopupMenu() + + if self._connected_vpn_profile is not None: + menu.add_menuitem("Disconnect", callback=self._on_vpn_disconnect) + for vpn_profile in self._vpn_profiles: + if self._connected_vpn_profile is not None and self._connected_vpn_profile == vpn_profile: + continue + menu.add_menuitem(vpn_profile, callback=functools.partial(self._on_vpn_connect, vpn_profile)) + menu.show(widget) + + def state(self, widget): + return [] diff --git a/themes/icons/awesome-fonts.json b/themes/icons/awesome-fonts.json index eb4a623..ff97533 100644 --- a/themes/icons/awesome-fonts.json +++ b/themes/icons/awesome-fonts.json @@ -199,5 +199,8 @@ "pihole": { "enabled": { "prefix": "" }, "disabled": { "prefix": "" } + }, + "vpn": { + "prefix": "" } }