├── debian
├── compat
├── pyversions
├── copyright
├── changelog.in
├── watch
├── prerm
├── rules
├── postinst
└── control
├── packaging
└── files
│ ├── .placeholder
│ ├── ajenti.service
│ ├── ajenti-bsd
│ └── config.json
├── ajenti
├── plugins
│ ├── test
│ │ ├── binder
│ │ │ ├── __init__.py
│ │ │ └── main.py
│ │ ├── events
│ │ │ ├── __init__.py
│ │ │ └── main.py
│ │ ├── http
│ │ │ ├── __init__.py
│ │ │ └── http.py
│ │ ├── simple
│ │ │ ├── __init__.py
│ │ │ └── main.py
│ │ ├── classconfig
│ │ │ ├── __init__.py
│ │ │ └── main.py
│ │ ├── notifications
│ │ │ ├── __init__.py
│ │ │ └── main.py
│ │ ├── layout
│ │ │ ├── events-main.xml
│ │ │ ├── simple-main.xml
│ │ │ ├── classconfig-main.xml
│ │ │ ├── classconfig-simple-editor.xml
│ │ │ ├── notifications-main.xml
│ │ │ ├── main.xml
│ │ │ └── binder-main.xml
│ │ ├── __init__.py
│ │ └── main.py
│ ├── dashboard
│ │ ├── layout
│ │ │ ├── welcome.xml
│ │ │ └── text.xml
│ │ ├── __init__.py
│ │ ├── welcome.py
│ │ ├── text.py
│ │ └── updater.py
│ ├── munin
│ │ ├── layout
│ │ │ └── widget.xml
│ │ ├── __init__.py
│ │ ├── widget.py
│ │ └── content
│ │ │ ├── css
│ │ │ └── plot.less
│ │ │ └── js
│ │ │ └── plot.coffee
│ ├── main
│ │ ├── content
│ │ │ ├── static
│ │ │ │ ├── icon.png
│ │ │ │ ├── error.jpeg
│ │ │ │ ├── favicon.png
│ │ │ │ ├── webapp-icon.png
│ │ │ │ ├── WebSocketMain.swf
│ │ │ │ ├── icon-connecting.png
│ │ │ │ └── fonts
│ │ │ │ │ ├── FontAwesome.otf
│ │ │ │ │ ├── opensans-bold.eot
│ │ │ │ │ ├── opensans-bold.ttf
│ │ │ │ │ ├── opensans-bold.woff
│ │ │ │ │ ├── opensans-bold.woff2
│ │ │ │ │ ├── opensans-regular.eot
│ │ │ │ │ ├── opensans-regular.ttf
│ │ │ │ │ ├── opensans-regular.woff
│ │ │ │ │ ├── opensans-regular.woff2
│ │ │ │ │ ├── pt_sans-web-bold.eot
│ │ │ │ │ ├── pt_sans-web-bold.ttf
│ │ │ │ │ ├── pt_sans-web-bold.woff
│ │ │ │ │ ├── pt_sans-web-bold.woff2
│ │ │ │ │ ├── fontawesome-webfont.eot
│ │ │ │ │ ├── fontawesome-webfont.ttf
│ │ │ │ │ ├── fontawesome-webfont.woff
│ │ │ │ │ └── fontawesome-webfont.woff2
│ │ │ ├── js
│ │ │ │ ├── controls.binding.coffee
│ │ │ │ ├── feedback.coffee
│ │ │ │ ├── ajenti-org.coffee
│ │ │ │ ├── _lib
│ │ │ │ │ └── cookies.m.js
│ │ │ │ └── profiler.coffee
│ │ │ └── css
│ │ │ │ ├── vars.i.less
│ │ │ │ ├── lib.i.less
│ │ │ │ ├── controls.dialogs.i.less
│ │ │ │ └── z-mode-tablet.less
│ │ ├── layout
│ │ │ ├── input-dialog.xml
│ │ │ ├── file-dialog.xml
│ │ │ ├── file-dialog-save.xml
│ │ │ └── passwd-main.xml
│ │ ├── controls_binding.py
│ │ ├── __init__.py
│ │ ├── controls_simple.py
│ │ ├── passwd.py
│ │ └── api.py
│ ├── packages
│ │ ├── layout
│ │ │ ├── installer.xml
│ │ │ ├── headers.xml
│ │ │ └── row.xml
│ │ ├── __init__.py
│ │ ├── pm_bsd.py
│ │ ├── pm_macports.py
│ │ └── api.py
│ ├── logs
│ │ ├── content
│ │ │ ├── css
│ │ │ │ └── logs.less
│ │ │ └── js
│ │ │ │ └── logs.coffee
│ │ ├── layout
│ │ │ ├── config.xml
│ │ │ └── main.xml
│ │ └── __init__.py
│ ├── terminal
│ │ ├── content
│ │ │ └── static
│ │ │ │ ├── SourceCodePro-Bold.otf
│ │ │ │ ├── SourceCodePro-Regular.otf
│ │ │ │ └── index.html
│ │ ├── layout
│ │ │ ├── config.xml
│ │ │ └── main.xml
│ │ ├── pyte
│ │ │ └── AUTHORS
│ │ └── __init__.py
│ ├── sensors
│ │ ├── layout
│ │ │ ├── cpu-line.xml
│ │ │ ├── cpu-widget.xml
│ │ │ ├── value-widget.xml
│ │ │ └── progressbar-widget.xml
│ │ ├── hostname.py
│ │ ├── __init__.py
│ │ ├── cpu.py
│ │ ├── uptime.py
│ │ └── load.py
│ ├── ajenti_org
│ │ ├── layout
│ │ │ ├── config.xml
│ │ │ └── main.xml
│ │ └── __init__.py
│ ├── tasks
│ │ ├── layout
│ │ │ ├── params-execute.xml
│ │ │ ├── params-deletedir.xml
│ │ │ ├── params-copydir.xml
│ │ │ └── params-rsync.xml
│ │ └── __init__.py
│ ├── notepad
│ │ ├── layout
│ │ │ ├── config.xml
│ │ │ ├── listitem.xml
│ │ │ └── main.xml
│ │ └── __init__.py
│ ├── configurator
│ │ ├── api.py
│ │ ├── __init__.py
│ │ └── layout
│ │ │ ├── ldap-sync-config.xml
│ │ │ ├── ad-sync-config.xml
│ │ │ └── licensing.xml
│ ├── services
│ │ ├── layout
│ │ │ ├── bar.xml
│ │ │ ├── widget.xml
│ │ │ └── main.xml
│ │ ├── sensor.py
│ │ ├── __init__.py
│ │ ├── sm_sysvinit_centos.py
│ │ ├── sm_osx.py
│ │ ├── sm_freebsd.py
│ │ ├── widget.py
│ │ └── api.py
│ ├── apcups
│ │ ├── layout
│ │ │ └── widget.xml
│ │ ├── __init__.py
│ │ └── widget.py
│ ├── iptables
│ │ ├── layout
│ │ │ ├── option-ports.xml
│ │ │ ├── option-address.xml
│ │ │ ├── option-match.xml
│ │ │ ├── option-interface.xml
│ │ │ ├── option-port.xml
│ │ │ ├── option-protocol.xml
│ │ │ ├── option.xml
│ │ │ ├── option-state.xml
│ │ │ ├── option-custom.xml
│ │ │ └── option-reject-with.xml
│ │ ├── __init__.py
│ │ └── content
│ │ │ └── css
│ │ │ └── iptables.less
│ ├── resources
│ │ └── __init__.py
│ ├── users
│ │ └── __init__.py
│ ├── hosts
│ │ ├── __init__.py
│ │ └── main.py
│ ├── plugins
│ │ ├── __init__.py
│ │ └── plugins.py
│ ├── taskmgr
│ │ └── __init__.py
│ ├── csf
│ │ ├── layout
│ │ │ └── list-template.xml
│ │ └── __init__.py
│ ├── power
│ │ ├── __init__.py
│ │ └── layout
│ │ │ └── widget.xml
│ ├── exports
│ │ ├── __init__.py
│ │ └── main.py
│ ├── fm
│ │ ├── __init__.py
│ │ └── layout
│ │ │ └── config.xml
│ ├── psql
│ │ └── __init__.py
│ ├── uname
│ │ ├── __init__.py
│ │ ├── layout
│ │ │ └── widget.xml
│ │ └── widget.py
│ ├── nginx
│ │ └── __init__.py
│ ├── resolv
│ │ ├── __init__.py
│ │ ├── main.py
│ │ └── layout
│ │ │ └── main.xml
│ ├── smartctl
│ │ ├── __init__.py
│ │ └── layout
│ │ │ └── widget.xml
│ ├── db_common
│ │ └── __init__.py
│ ├── webserver_common
│ │ └── __init__.py
│ ├── cron
│ │ ├── __init__.py
│ │ └── api.py
│ ├── memcache
│ │ ├── layout
│ │ │ └── widget.xml
│ │ ├── __init__.py
│ │ └── widget.py
│ ├── dhcpd
│ │ ├── __init__.py
│ │ ├── layout
│ │ │ ├── options.xml
│ │ │ └── ranges.xml
│ │ └── main.py
│ ├── ntpd
│ │ └── __init__.py
│ ├── squid
│ │ ├── __init__.py
│ │ ├── layout
│ │ │ ├── options-editor.xml
│ │ │ └── port-template.xml
│ │ └── main.py
│ ├── scripts
│ │ ├── __init__.py
│ │ └── layout
│ │ │ └── widget.xml
│ ├── snmpd
│ │ └── __init__.py
│ ├── fail2ban
│ │ └── __init__.py
│ ├── supervisor
│ │ ├── __init__.py
│ │ └── main.py
│ ├── mongo
│ │ ├── __init__.py
│ │ ├── layout
│ │ │ └── config.xml
│ │ └── main.py
│ ├── mysql
│ │ ├── __init__.py
│ │ ├── layout
│ │ │ └── config.xml
│ │ └── main.py
│ ├── openvpn
│ │ ├── __init__.py
│ │ └── layout
│ │ │ └── config.xml
│ ├── rethink
│ │ ├── __init__.py
│ │ ├── layout
│ │ │ └── config.xml
│ │ └── main.py
│ ├── bind9
│ │ └── __init__.py
│ ├── netatalk
│ │ ├── __init__.py
│ │ └── main.py
│ ├── samba
│ │ ├── __init__.py
│ │ ├── status.py
│ │ └── smbusers.py
│ ├── ctdb
│ │ └── __init__.py
│ ├── hdparm
│ │ ├── __init__.py
│ │ └── layout
│ │ │ └── widget.xml
│ ├── raid
│ │ ├── __init__.py
│ │ └── main.py
│ ├── fstab
│ │ ├── __init__.py
│ │ ├── layout
│ │ │ ├── free-widget.xml
│ │ │ ├── widget.xml
│ │ │ └── iio-widget.xml
│ │ └── widget.py
│ ├── hddtemp
│ │ ├── layout
│ │ │ └── widget.xml
│ │ ├── __init__.py
│ │ ├── sensor.py
│ │ └── widget.py
│ ├── lm_sensors
│ │ ├── __init__.py
│ │ └── layout
│ │ │ └── widget.xml
│ ├── megaraid
│ │ ├── __init__.py
│ │ ├── layout
│ │ │ └── widget.xml
│ │ ├── main.py
│ │ └── widget.py
│ ├── network
│ │ ├── layout
│ │ │ ├── bit-linux-basic.xml
│ │ │ ├── bit-linux-ifupdown.xml
│ │ │ ├── widget.xml
│ │ │ ├── bit-linux-dhcp.xml
│ │ │ └── bit-linux-ipv4.xml
│ │ ├── ncs_linux_dhcp.py
│ │ ├── ncs_linux_ipv4.py
│ │ ├── ncs_linux_basic.py
│ │ ├── ncs_linux_ifupdown.py
│ │ ├── __init__.py
│ │ └── api.py
│ ├── nsd
│ │ └── __init__.py
│ ├── ipmi
│ │ ├── __init__.py
│ │ ├── layout
│ │ │ └── widget.xml
│ │ ├── sensor.py
│ │ └── widget.py
│ ├── git
│ │ ├── __init__.py
│ │ └── layout
│ │ │ ├── main.xml
│ │ │ ├── main-userlist.xml
│ │ │ └── main-repolist.xml
│ ├── apache
│ │ └── __init__.py
│ └── codemirror
│ │ ├── __init__.py
│ │ └── content
│ │ └── js
│ │ └── controls.codearea.coffee
├── locales
│ ├── README.txt
│ └── __init__.py
├── usersync
│ ├── __init__.py
│ ├── base.py
│ ├── local.py
│ └── unix.py
├── api
│ └── helpers.py
├── profiler.py
└── feedback.py
├── setup.cfg
├── docs
├── source
│ ├── _static
│ │ └── dev
│ │ │ ├── control.png
│ │ │ ├── ui
│ │ │ └── example.png
│ │ │ ├── simple-binding.png
│ │ │ ├── ui-elements
│ │ │ ├── dt.png
│ │ │ ├── list.png
│ │ │ ├── tabs.png
│ │ │ ├── button.png
│ │ │ ├── editable.png
│ │ │ ├── formline.png
│ │ │ ├── tooltip.png
│ │ │ ├── formgroup.png
│ │ │ ├── sortabledt.png
│ │ │ └── progressbar.png
│ │ │ └── collection-binding.png
│ ├── ref
│ │ ├── ajenti.rst
│ │ ├── ajenti.ui.rst
│ │ ├── ajenti.api.rst
│ │ ├── ajenti.ipc.rst
│ │ ├── ajenti.http.rst
│ │ ├── ajenti.util.rst
│ │ ├── ajenti.users.rst
│ │ ├── ajenti.plugins.rst
│ │ ├── ajenti.api.http.rst
│ │ ├── ajenti.profiler.rst
│ │ ├── ajenti.middleware.rst
│ │ ├── ajenti.ui.binder.rst
│ │ ├── ajenti.api.sensors.rst
│ │ ├── ajenti.plugins.main.api.rst
│ │ ├── ajenti.plugins.tasks.api.rst
│ │ ├── ajenti.plugins.dashboard.api.rst
│ │ ├── ajenti.plugins.db_common.api.rst
│ │ ├── ajenti.plugins.packages.api.rst
│ │ ├── ajenti.plugins.services.api.rst
│ │ ├── ajenti.plugins.configurator.api.rst
│ │ └── ajenti.plugins.webserver_common.api.rst
│ ├── man
│ │ ├── faq.rst
│ │ └── run.rst
│ ├── _templates
│ │ └── page.html
│ ├── dev
│ │ ├── resources.rst
│ │ └── notifications.rst
│ └── index.rst
├── CHANGELOG
└── COPYRIGHT
├── requirements-rtd.txt
├── requirements.txt
├── scripts
├── install-openSUSE
├── install-rhel.sh
├── install-rhel7.sh
├── install-debian.sh
├── install-ubuntu.sh
└── install-raspbian.sh
├── MANIFEST.in
├── .gitignore
├── ajenti-ipc
├── setup.py
├── README.md
└── ajenti-ssl-gen
/debian/compat:
--------------------------------------------------------------------------------
1 | 8
2 |
--------------------------------------------------------------------------------
/debian/pyversions:
--------------------------------------------------------------------------------
1 | 2.6-
2 |
--------------------------------------------------------------------------------
/packaging/files/.placeholder:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/debian/copyright:
--------------------------------------------------------------------------------
1 | ../docs/COPYRIGHT
--------------------------------------------------------------------------------
/ajenti/plugins/test/binder/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ajenti/plugins/test/events/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ajenti/plugins/test/http/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ajenti/plugins/test/simple/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/debian/changelog.in:
--------------------------------------------------------------------------------
1 | ../docs/CHANGELOG
--------------------------------------------------------------------------------
/ajenti/plugins/test/classconfig/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ajenti/plugins/test/notifications/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [bdist_wheel]
2 | universal = 1
3 |
--------------------------------------------------------------------------------
/debian/watch:
--------------------------------------------------------------------------------
1 | version=3
2 |
3 | http://meta.ajenti.org/release/(.+)\.tar\.gz
4 |
--------------------------------------------------------------------------------
/ajenti/plugins/dashboard/layout/welcome.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/ajenti/locales/README.txt:
--------------------------------------------------------------------------------
1 | Translations are ONLY handled through Crowdin!
2 | https://crowdin.net/project/ajenti
--------------------------------------------------------------------------------
/docs/source/_static/dev/control.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/docs/source/_static/dev/control.png
--------------------------------------------------------------------------------
/ajenti/plugins/munin/layout/widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/debian/prerm:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | /etc/init.d/ajenti stop
3 | update-rc.d -f ajenti remove > /dev/null
4 | #DEBHELPER#
5 |
6 |
--------------------------------------------------------------------------------
/docs/source/_static/dev/ui/example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/docs/source/_static/dev/ui/example.png
--------------------------------------------------------------------------------
/docs/source/ref/ajenti.rst:
--------------------------------------------------------------------------------
1 | ajenti
2 | ******
3 |
4 | .. automodule:: ajenti
5 | :members:
6 | :undoc-members:
7 |
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/static/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/main/content/static/icon.png
--------------------------------------------------------------------------------
/docs/source/_static/dev/simple-binding.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/docs/source/_static/dev/simple-binding.png
--------------------------------------------------------------------------------
/docs/source/_static/dev/ui-elements/dt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/docs/source/_static/dev/ui-elements/dt.png
--------------------------------------------------------------------------------
/docs/source/ref/ajenti.ui.rst:
--------------------------------------------------------------------------------
1 | ajenti.ui
2 | *********
3 |
4 | .. automodule:: ajenti.ui
5 | :members:
6 | :undoc-members:
7 |
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/static/error.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/main/content/static/error.jpeg
--------------------------------------------------------------------------------
/ajenti/plugins/test/layout/events-main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/docs/source/_static/dev/ui-elements/list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/docs/source/_static/dev/ui-elements/list.png
--------------------------------------------------------------------------------
/docs/source/_static/dev/ui-elements/tabs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/docs/source/_static/dev/ui-elements/tabs.png
--------------------------------------------------------------------------------
/docs/source/ref/ajenti.api.rst:
--------------------------------------------------------------------------------
1 | ajenti.api
2 | **********
3 |
4 | .. automodule:: ajenti.api
5 | :members:
6 | :undoc-members:
7 |
--------------------------------------------------------------------------------
/docs/source/ref/ajenti.ipc.rst:
--------------------------------------------------------------------------------
1 | ajenti.ipc
2 | **********
3 |
4 | .. automodule:: ajenti.ipc
5 | :members:
6 | :undoc-members:
7 |
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/static/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/main/content/static/favicon.png
--------------------------------------------------------------------------------
/docs/source/_static/dev/collection-binding.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/docs/source/_static/dev/collection-binding.png
--------------------------------------------------------------------------------
/docs/source/_static/dev/ui-elements/button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/docs/source/_static/dev/ui-elements/button.png
--------------------------------------------------------------------------------
/docs/source/_static/dev/ui-elements/editable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/docs/source/_static/dev/ui-elements/editable.png
--------------------------------------------------------------------------------
/docs/source/_static/dev/ui-elements/formline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/docs/source/_static/dev/ui-elements/formline.png
--------------------------------------------------------------------------------
/docs/source/_static/dev/ui-elements/tooltip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/docs/source/_static/dev/ui-elements/tooltip.png
--------------------------------------------------------------------------------
/docs/source/ref/ajenti.http.rst:
--------------------------------------------------------------------------------
1 | ajenti.http
2 | ***********
3 |
4 | .. automodule:: ajenti.http
5 | :members:
6 | :undoc-members:
7 |
--------------------------------------------------------------------------------
/docs/source/ref/ajenti.util.rst:
--------------------------------------------------------------------------------
1 | ajenti.util
2 | ***********
3 |
4 | .. automodule:: ajenti.util
5 | :members:
6 | :undoc-members:
7 |
--------------------------------------------------------------------------------
/requirements-rtd.txt:
--------------------------------------------------------------------------------
1 | passlib
2 | python-catcher
3 | python-daemon
4 | python-exconsole>=0.1.5
5 | requests>=0.12.0
6 | reconfigure>=0.1.41
7 |
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/static/webapp-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/main/content/static/webapp-icon.png
--------------------------------------------------------------------------------
/ajenti/plugins/main/layout/input-dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/docs/source/_static/dev/ui-elements/formgroup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/docs/source/_static/dev/ui-elements/formgroup.png
--------------------------------------------------------------------------------
/docs/source/_static/dev/ui-elements/sortabledt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/docs/source/_static/dev/ui-elements/sortabledt.png
--------------------------------------------------------------------------------
/docs/source/ref/ajenti.users.rst:
--------------------------------------------------------------------------------
1 | ajenti.users
2 | ************
3 |
4 | .. automodule:: ajenti.users
5 | :members:
6 | :undoc-members:
7 |
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/static/WebSocketMain.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/main/content/static/WebSocketMain.swf
--------------------------------------------------------------------------------
/docs/CHANGELOG:
--------------------------------------------------------------------------------
1 | ajenti (__VERSION__) UNRELEASED; urgency=low
2 |
3 | * Initial pre-release.
4 |
5 | -- Eugeny Pankov __DATE__
6 |
--------------------------------------------------------------------------------
/docs/source/_static/dev/ui-elements/progressbar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/docs/source/_static/dev/ui-elements/progressbar.png
--------------------------------------------------------------------------------
/docs/source/ref/ajenti.plugins.rst:
--------------------------------------------------------------------------------
1 | ajenti.plugins
2 | **************
3 |
4 | .. automodule:: ajenti.plugins
5 | :members:
6 | :undoc-members:
7 |
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/static/icon-connecting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/main/content/static/icon-connecting.png
--------------------------------------------------------------------------------
/ajenti/plugins/main/layout/file-dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/docs/source/ref/ajenti.api.http.rst:
--------------------------------------------------------------------------------
1 | ajenti.api.http
2 | ***************
3 |
4 | .. automodule:: ajenti.api.http
5 | :members:
6 | :undoc-members:
7 |
--------------------------------------------------------------------------------
/docs/source/ref/ajenti.profiler.rst:
--------------------------------------------------------------------------------
1 | ajenti.profiler
2 | ***************
3 |
4 | .. automodule:: ajenti.profiler
5 | :members:
6 | :undoc-members:
7 |
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/static/fonts/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/main/content/static/fonts/FontAwesome.otf
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/static/fonts/opensans-bold.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/main/content/static/fonts/opensans-bold.eot
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/static/fonts/opensans-bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/main/content/static/fonts/opensans-bold.ttf
--------------------------------------------------------------------------------
/ajenti/plugins/packages/layout/installer.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/docs/source/ref/ajenti.middleware.rst:
--------------------------------------------------------------------------------
1 | ajenti.middleware
2 | *****************
3 |
4 | .. automodule:: ajenti.middleware
5 | :members:
6 | :undoc-members:
--------------------------------------------------------------------------------
/docs/source/ref/ajenti.ui.binder.rst:
--------------------------------------------------------------------------------
1 | ajenti.ui.binder
2 | ****************
3 |
4 | .. automodule:: ajenti.ui.binder
5 | :members:
6 | :undoc-members:
7 |
--------------------------------------------------------------------------------
/ajenti/plugins/logs/content/css/logs.less:
--------------------------------------------------------------------------------
1 | .control.log {
2 | width: 770px;
3 | height: 500px;
4 | font-family: monospace;
5 | overflow: scroll;
6 | }
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/static/fonts/opensans-bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/main/content/static/fonts/opensans-bold.woff
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/static/fonts/opensans-bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/main/content/static/fonts/opensans-bold.woff2
--------------------------------------------------------------------------------
/docs/source/ref/ajenti.api.sensors.rst:
--------------------------------------------------------------------------------
1 | ajenti.api.sensors
2 | ******************
3 |
4 | .. automodule:: ajenti.api.sensors
5 | :members:
6 | :undoc-members:
7 |
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/static/fonts/opensans-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/main/content/static/fonts/opensans-regular.eot
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/static/fonts/opensans-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/main/content/static/fonts/opensans-regular.ttf
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/static/fonts/opensans-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/main/content/static/fonts/opensans-regular.woff
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/static/fonts/opensans-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/main/content/static/fonts/opensans-regular.woff2
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/static/fonts/pt_sans-web-bold.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/main/content/static/fonts/pt_sans-web-bold.eot
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/static/fonts/pt_sans-web-bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/main/content/static/fonts/pt_sans-web-bold.ttf
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/static/fonts/pt_sans-web-bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/main/content/static/fonts/pt_sans-web-bold.woff
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/static/fonts/pt_sans-web-bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/main/content/static/fonts/pt_sans-web-bold.woff2
--------------------------------------------------------------------------------
/ajenti/plugins/terminal/content/static/SourceCodePro-Bold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/terminal/content/static/SourceCodePro-Bold.otf
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/static/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/main/content/static/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/static/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/main/content/static/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/static/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/main/content/static/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/ajenti/plugins/terminal/content/static/SourceCodePro-Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/terminal/content/static/SourceCodePro-Regular.otf
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/static/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gytai/ajenti/1.x/ajenti/plugins/main/content/static/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/ajenti/plugins/test/layout/simple-main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/docs/source/ref/ajenti.plugins.main.api.rst:
--------------------------------------------------------------------------------
1 | ajenti.plugins.main.api
2 | ***********************
3 |
4 | .. automodule:: ajenti.plugins.main.api
5 | :members:
6 | :undoc-members:
7 |
--------------------------------------------------------------------------------
/ajenti/plugins/sensors/layout/cpu-line.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/docs/source/ref/ajenti.plugins.tasks.api.rst:
--------------------------------------------------------------------------------
1 | ajenti.plugins.tasks.api
2 | ************************
3 |
4 | .. automodule:: ajenti.plugins.tasks.api
5 | :members:
6 | :undoc-members:
7 |
--------------------------------------------------------------------------------
/ajenti/plugins/packages/layout/headers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/docs/source/ref/ajenti.plugins.dashboard.api.rst:
--------------------------------------------------------------------------------
1 | ajenti.plugins.dashboard.api
2 | ****************************
3 |
4 | .. automodule:: ajenti.plugins.dashboard.api
5 | :members:
6 | :undoc-members:
7 |
--------------------------------------------------------------------------------
/docs/source/ref/ajenti.plugins.db_common.api.rst:
--------------------------------------------------------------------------------
1 | ajenti.plugins.db_common.api
2 | ****************************
3 |
4 | .. automodule:: ajenti.plugins.db_common.api
5 | :members:
6 | :undoc-members:
7 |
--------------------------------------------------------------------------------
/docs/source/ref/ajenti.plugins.packages.api.rst:
--------------------------------------------------------------------------------
1 | ajenti.plugins.packages.api
2 | ***************************
3 |
4 | .. automodule:: ajenti.plugins.packages.api
5 | :members:
6 | :undoc-members:
7 |
--------------------------------------------------------------------------------
/docs/source/ref/ajenti.plugins.services.api.rst:
--------------------------------------------------------------------------------
1 | ajenti.plugins.services.api
2 | ***************************
3 |
4 | .. automodule:: ajenti.plugins.services.api
5 | :members:
6 | :undoc-members:
7 |
--------------------------------------------------------------------------------
/ajenti/plugins/ajenti_org/layout/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/ajenti/plugins/tasks/layout/params-execute.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/docs/source/ref/ajenti.plugins.configurator.api.rst:
--------------------------------------------------------------------------------
1 | ajenti.plugins.configurator.api
2 | *******************************
3 |
4 | .. automodule:: ajenti.plugins.configurator.api
5 | :members:
6 | :undoc-members:
7 |
--------------------------------------------------------------------------------
/ajenti/plugins/logs/layout/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/ajenti/plugins/notepad/layout/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/ajenti/plugins/terminal/layout/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/ajenti/plugins/configurator/api.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.ui import *
3 |
4 |
5 | @p('title')
6 | @interface
7 | class ClassConfigEditor (BasePlugin, UIElement):
8 | typeid = 'configurator:classconfig-editor'
9 |
--------------------------------------------------------------------------------
/ajenti/usersync/__init__.py:
--------------------------------------------------------------------------------
1 | from base import UserSyncProvider
2 | from local import AjentiSyncProvider
3 | from unix import UNIXSyncProvider
4 | from adsync import ActiveDirectorySyncProvider
5 | from ldapsync import LDAPSyncProvider
6 |
--------------------------------------------------------------------------------
/docs/source/ref/ajenti.plugins.webserver_common.api.rst:
--------------------------------------------------------------------------------
1 | ajenti.plugins.webserver_common.api
2 | ***********************************
3 |
4 | .. automodule:: ajenti.plugins.webserver_common.api
5 | :members:
6 | :undoc-members:
7 |
--------------------------------------------------------------------------------
/ajenti/plugins/tasks/layout/params-deletedir.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/ajenti/plugins/services/layout/bar.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/ajenti/plugins/apcups/layout/widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ajenti/plugins/test/layout/classconfig-main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ajenti/plugins/main/controls_binding.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.ui import p, UIElement
3 |
4 |
5 | @plugin
6 | class BindTemplate (UIElement):
7 | typeid = 'bind:template'
8 |
9 | def init(self):
10 | self.visible = False
11 |
--------------------------------------------------------------------------------
/ajenti/plugins/sensors/layout/cpu-widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ajenti/plugins/terminal/pyte/AUTHORS:
--------------------------------------------------------------------------------
1 | Authors
2 | =======
3 |
4 | - George Shuklin
5 | - Sergei Lebedev
6 |
7 | Contributors
8 | ------------
9 |
10 | - Alexey Shamrin
11 | - Steve Cohen
12 | - Jonathan Slenders
13 | - David O'Shea
14 | - Andreas Stührk
15 |
--------------------------------------------------------------------------------
/packaging/files/ajenti.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Ajenti - an easy server administration frontend
3 |
4 | [Service]
5 | Type=forking
6 | PIDFile=/var/run/ajenti.pid
7 | ExecStart=/usr/bin/ajenti-panel -d
8 |
9 | [Install]
10 | WantedBy=multi-user.target
11 |
--------------------------------------------------------------------------------
/ajenti/plugins/iptables/layout/option-ports.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ajenti/plugins/iptables/layout/option-address.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ajenti/plugins/iptables/layout/option-match.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | gevent==1.1b4
2 | gevent-socketio
3 | gevent-websocket
4 | lxml>=2.2.4
5 | passlib
6 | psutil>=0.6.0
7 | python-catcher
8 | python-daemon
9 | python-exconsole>=0.1.5
10 | python-ldap
11 | requests>=0.12.0
12 | reconfigure>=0.1.43
13 | pyOpenSSL
14 | Pillow
15 |
--------------------------------------------------------------------------------
/ajenti/plugins/resources/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Resource Manager',
7 | icon='link',
8 | dependencies=[
9 | ],
10 | )
11 |
12 |
13 | def init():
14 | import server
15 |
--------------------------------------------------------------------------------
/ajenti/plugins/notepad/layout/listitem.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ajenti/plugins/iptables/layout/option-interface.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ajenti/plugins/logs/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Logs',
7 | icon='list',
8 | dependencies=[
9 | PluginDependency('main'),
10 | ],
11 | )
12 |
13 |
14 | def init():
15 | import main
16 |
--------------------------------------------------------------------------------
/ajenti/plugins/users/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Users',
7 | icon='group',
8 | dependencies=[
9 | PluginDependency('main'),
10 | ],
11 | )
12 |
13 |
14 | def init():
15 | import main
16 |
--------------------------------------------------------------------------------
/debian/rules:
--------------------------------------------------------------------------------
1 | #!/usr/bin/make -f
2 | # -*- makefile -*-
3 |
4 | DEB_PYTHON_SYSTEM := pysupport
5 |
6 | include /usr/share/cdbs/1/rules/debhelper.mk
7 | include /usr/share/cdbs/1/class/python-distutils.mk
8 |
9 | clean::
10 | rm -rf build build-stamp configure-stamp build/ MANIFEST
11 | dh_clean
12 |
--------------------------------------------------------------------------------
/ajenti/plugins/hosts/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Hosts',
7 | icon='sitemap',
8 | dependencies=[
9 | PluginDependency('main'),
10 | ],
11 | )
12 |
13 |
14 | def init():
15 | import main
16 |
--------------------------------------------------------------------------------
/ajenti/plugins/logs/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ajenti/plugins/plugins/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Plugins',
7 | icon='cogs',
8 | dependencies=[
9 | PluginDependency('main')
10 | ],
11 | )
12 |
13 |
14 | def init():
15 | import plugins
16 |
--------------------------------------------------------------------------------
/ajenti/plugins/main/layout/file-dialog-save.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ajenti/plugins/taskmgr/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Processes',
7 | icon='th-list',
8 | dependencies=[
9 | PluginDependency('main'),
10 | ],
11 | )
12 |
13 |
14 | def init():
15 | import main
16 |
--------------------------------------------------------------------------------
/ajenti/plugins/terminal/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Terminal',
7 | icon='list-alt',
8 | dependencies=[
9 | PluginDependency('main'),
10 | ],
11 | )
12 |
13 |
14 | def init():
15 | import main
16 |
--------------------------------------------------------------------------------
/ajenti/plugins/sensors/hostname.py:
--------------------------------------------------------------------------------
1 | import platform
2 |
3 | from ajenti.api import *
4 | from ajenti.api.sensors import Sensor
5 |
6 |
7 | @plugin
8 | class HostnameSensor (Sensor):
9 | id = 'hostname'
10 | timeout = 60
11 |
12 | def measure(self, variant=None):
13 | return platform.node()
14 |
--------------------------------------------------------------------------------
/ajenti/plugins/ajenti_org/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='ajenti.org integration',
7 | icon='group',
8 | dependencies=[
9 | PluginDependency('main'),
10 | ],
11 | )
12 |
13 |
14 | def init():
15 | import main
16 |
--------------------------------------------------------------------------------
/ajenti/plugins/csf/layout/list-template.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/ajenti/plugins/dashboard/layout/text.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
--------------------------------------------------------------------------------
/ajenti/plugins/power/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Power',
7 | icon='bolt',
8 | dependencies=[
9 | PluginDependency('main'),
10 | PluginDependency('dashboard'),
11 | ],
12 | )
13 |
14 |
15 | def init():
16 | import power
17 |
--------------------------------------------------------------------------------
/ajenti/plugins/exports/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='NFS Exports',
7 | icon='hdd',
8 | dependencies=[
9 | PluginDependency('main'),
10 | BinaryDependency('nfsstat')
11 | ],
12 | )
13 |
14 |
15 | def init():
16 | import main
17 |
--------------------------------------------------------------------------------
/ajenti/plugins/fm/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='File Manager',
7 | icon='folder-open',
8 | dependencies=[
9 | PluginDependency('main'),
10 | PluginDependency('tasks'),
11 | ],
12 | )
13 |
14 |
15 | def init():
16 | import fm
17 |
--------------------------------------------------------------------------------
/ajenti/plugins/notepad/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Notepad',
7 | icon='edit',
8 | dependencies=[
9 | PluginDependency('main'),
10 | PluginDependency('codemirror'),
11 | ],
12 | )
13 |
14 |
15 | def init():
16 | import notepad
17 |
--------------------------------------------------------------------------------
/ajenti/plugins/psql/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='PostgreSQL',
7 | icon='table',
8 | dependencies=[
9 | PluginDependency('db_common'),
10 | BinaryDependency('psql'),
11 | ],
12 | )
13 |
14 |
15 | def init():
16 | import main
17 |
--------------------------------------------------------------------------------
/ajenti/plugins/uname/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='uname widget',
7 | icon='cog',
8 | dependencies=[
9 | PluginDependency('main'),
10 | PluginDependency('dashboard'),
11 | ],
12 | )
13 |
14 |
15 | def init():
16 | import widget
17 |
--------------------------------------------------------------------------------
/ajenti/plugins/iptables/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Firewall',
7 | description='Linux iptables firewall',
8 | icon='fire',
9 | dependencies=[
10 | PluginDependency('main')
11 | ],
12 | )
13 |
14 |
15 | def init():
16 | import main
17 |
--------------------------------------------------------------------------------
/ajenti/plugins/nginx/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='NGINX',
7 | icon='globe',
8 | dependencies=[
9 | PluginDependency('webserver_common'),
10 | BinaryDependency('nginx'),
11 | ],
12 | )
13 |
14 |
15 | def init():
16 | import main
17 |
--------------------------------------------------------------------------------
/ajenti/plugins/resolv/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Nameservers',
7 | icon='globe',
8 | dependencies=[
9 | PluginDependency('main'),
10 | FileDependency('/etc/resolv.conf'),
11 | ],
12 | )
13 |
14 |
15 | def init():
16 | import main
17 |
--------------------------------------------------------------------------------
/ajenti/plugins/smartctl/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='S.M.A.R.T.',
7 | icon='hdd',
8 | dependencies=[
9 | PluginDependency('dashboard'),
10 | BinaryDependency('smartctl')
11 | ],
12 | )
13 |
14 |
15 | def init():
16 | import widget
17 |
--------------------------------------------------------------------------------
/ajenti/plugins/db_common/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Database Commons',
7 | icon='table',
8 | dependencies=[
9 | PluginDependency('main'),
10 | PluginDependency('services'),
11 | ],
12 | )
13 |
14 |
15 | def init():
16 | import api
17 |
--------------------------------------------------------------------------------
/ajenti/plugins/test/layout/classconfig-simple-editor.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/ajenti/plugins/webserver_common/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Webserver Commons',
7 | icon='cogs',
8 | dependencies=[
9 | PluginDependency('main'),
10 | PluginDependency('services'),
11 | ],
12 | )
13 |
14 |
15 | def init():
16 | import api
17 |
--------------------------------------------------------------------------------
/ajenti/usersync/base.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 |
3 |
4 | @interface
5 | class UserSyncProvider (BasePlugin):
6 | allows_renaming = False
7 | syncs_root = False
8 |
9 | def test(self):
10 | return False
11 |
12 | def check_password(self, username, password):
13 | return False
14 |
15 | def sync(self):
16 | pass
--------------------------------------------------------------------------------
/ajenti/plugins/dashboard/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Dashboard',
7 | icon='dashboard',
8 | dependencies=[
9 | PluginDependency('main')
10 | ],
11 | )
12 |
13 |
14 | def init():
15 | import dash
16 | import api
17 | import welcome
18 | import text
19 |
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/js/controls.binding.coffee:
--------------------------------------------------------------------------------
1 | class window.Controls.bind__template extends window.Control
2 | createDom: () ->
3 | @noUID = true
4 | """"""
5 |
6 | setupDom: (dom) ->
7 | super(dom)
8 | if @children.length > 0
9 | @dom = @children[0].dom
10 | @properties = @children[0].properties
--------------------------------------------------------------------------------
/ajenti/plugins/tasks/layout/params-copydir.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/ajenti/plugins/test/simple/main.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins.main.api import SectionPlugin
3 |
4 |
5 | @plugin
6 | class SimpleDemo (SectionPlugin):
7 | def init(self):
8 | self.title = 'Simple'
9 | self.icon = 'question'
10 | self.category = 'Demo'
11 |
12 | self.append(self.ui.inflate('test:simple-main'))
13 |
--------------------------------------------------------------------------------
/ajenti/plugins/cron/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Cron',
7 | description='Cron task scheduler',
8 | icon='time',
9 | dependencies=[
10 | PluginDependency('main'),
11 | BinaryDependency('crontab'),
12 | ],
13 | )
14 |
15 |
16 | def init():
17 | import main
18 |
--------------------------------------------------------------------------------
/ajenti/plugins/memcache/layout/widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/ajenti/plugins/dhcpd/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='DHCP Server',
7 | icon='sitemap',
8 | dependencies=[
9 | PluginDependency('main'),
10 | PluginDependency('services'),
11 | BinaryDependency('dhcpd'),
12 | ],
13 | )
14 |
15 |
16 | def init():
17 | import main
18 |
--------------------------------------------------------------------------------
/ajenti/plugins/iptables/layout/option-port.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ajenti/plugins/ntpd/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='NTPd control',
7 | icon='time',
8 | dependencies=[
9 | PluginDependency('main'),
10 | PluginDependency('services'),
11 | BinaryDependency('ntpd'),
12 | ],
13 | )
14 |
15 |
16 | def init():
17 | import main
18 |
--------------------------------------------------------------------------------
/ajenti/plugins/squid/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Squid',
7 | icon='exchange',
8 | dependencies=[
9 | PluginDependency('main'),
10 | PluginDependency('services'),
11 | BinaryDependency('squid3'),
12 | ],
13 | )
14 |
15 |
16 | def init():
17 | import main
18 |
--------------------------------------------------------------------------------
/ajenti/plugins/csf/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='CSF Firewall',
7 | description='Simplified Linux firewall',
8 | icon='fire',
9 | dependencies=[
10 | BinaryDependency('csf'),
11 | PluginDependency('main'),
12 | ],
13 | )
14 |
15 |
16 | def init():
17 | import main
18 |
--------------------------------------------------------------------------------
/ajenti/plugins/memcache/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Memcache',
7 | icon='cog',
8 | dependencies=[
9 | PluginDependency('main'),
10 | PluginDependency('dashboard'),
11 | BinaryDependency('memcached'),
12 | ],
13 | )
14 |
15 |
16 | def init():
17 | import widget
18 |
--------------------------------------------------------------------------------
/ajenti/plugins/scripts/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Scripts',
7 | icon='play',
8 | dependencies=[
9 | PluginDependency('main'),
10 | PluginDependency('dashboard'),
11 | PluginDependency('terminal'),
12 | ],
13 | )
14 |
15 |
16 | def init():
17 | import widget
18 |
--------------------------------------------------------------------------------
/ajenti/plugins/snmpd/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='SNMPd control',
7 | icon='exchange',
8 | dependencies=[
9 | PluginDependency('main'),
10 | PluginDependency('services'),
11 | BinaryDependency('snmpd'),
12 | ],
13 | )
14 |
15 |
16 | def init():
17 | import main
18 |
--------------------------------------------------------------------------------
/ajenti/plugins/fail2ban/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='fail2ban',
7 | icon='shield',
8 | dependencies=[
9 | PluginDependency('main'),
10 | BinaryDependency('fail2ban-client'),
11 | BinaryDependency('fail2ban-regex'),
12 | ],
13 | )
14 |
15 |
16 | def init():
17 | import main
--------------------------------------------------------------------------------
/ajenti/plugins/supervisor/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Supervisor',
7 | icon='play',
8 | dependencies=[
9 | PluginDependency('main'),
10 | PluginDependency('services'),
11 | BinaryDependency('supervisord'),
12 | ],
13 | )
14 |
15 |
16 | def init():
17 | import main
18 |
--------------------------------------------------------------------------------
/ajenti/plugins/tasks/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Tasks',
7 | icon='cog',
8 | dependencies=[
9 | PluginDependency('main'),
10 | PluginDependency('cron'),
11 | ],
12 | )
13 |
14 |
15 | def init():
16 | import api
17 | import manager
18 | import main
19 | import tasks
20 |
--------------------------------------------------------------------------------
/ajenti/plugins/iptables/layout/option-protocol.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ajenti/plugins/mongo/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='MongoDB',
7 | icon='table',
8 | dependencies=[
9 | PluginDependency('db_common'),
10 | BinaryDependency('mongod'),
11 | ModuleDependency('pymongo'),
12 | ],
13 | )
14 |
15 |
16 | def init():
17 | import api
18 | import main
19 |
--------------------------------------------------------------------------------
/ajenti/plugins/mysql/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='MySQL',
7 | icon='table',
8 | dependencies=[
9 | PluginDependency('db_common'),
10 | BinaryDependency('mysql'),
11 | BinaryDependency('mysqld_safe'),
12 | ],
13 | )
14 |
15 |
16 | def init():
17 | import api
18 | import main
19 |
--------------------------------------------------------------------------------
/ajenti/plugins/openvpn/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='OpenVPN',
7 | icon='globe',
8 | dependencies=[
9 | PluginDependency('main'),
10 | PluginDependency('services'),
11 | BinaryDependency('openvpn'),
12 | ],
13 | )
14 |
15 |
16 | def init():
17 | import backend
18 | import main
19 |
--------------------------------------------------------------------------------
/ajenti/api/helpers.py:
--------------------------------------------------------------------------------
1 | import gevent
2 | import subprocess
3 |
4 |
5 | def subprocess_call_background(*args, **kwargs):
6 | p = subprocess.Popen(*args, **kwargs)
7 | gevent.sleep(0)
8 | return p.wait()
9 |
10 |
11 | def subprocess_check_output_background(*args, **kwargs):
12 | p = subprocess.Popen(*args, stdout=subprocess.PIPE, **kwargs)
13 | gevent.sleep(0)
14 | return p.communicate()[0]
15 |
--------------------------------------------------------------------------------
/ajenti/plugins/rethink/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='RethinkDB',
7 | icon='table',
8 | dependencies=[
9 | PluginDependency('db_common'),
10 | BinaryDependency('rethinkdb'),
11 | ModuleDependency('rethinkdb'),
12 | ],
13 | )
14 |
15 |
16 | def init():
17 | import api
18 | import main
19 |
--------------------------------------------------------------------------------
/scripts/install-openSUSE:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | if [ "$(id -u)" != "0" ]; then
3 | echo "This script must be run as root" 1>&2
4 | exit 1
5 | fi
6 | echo ':: Adding Ajenti repo'
7 | rpm -ivh http://repo.ajenti.org/ajenti-repo-1.0-1.noarch.rpm
8 | echo ':: Updating Repository'
9 | zypper up
10 | echo ':: Installing package'
11 | zypper in ajenti --non-interactive
12 | echo ':: Done! Open https://:8000 in browser'
13 |
--------------------------------------------------------------------------------
/ajenti/plugins/bind9/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='BIND9',
7 | description='BIND9 DNS server',
8 | icon='globe',
9 | dependencies=[
10 | PluginDependency('main'),
11 | PluginDependency('services'),
12 | BinaryDependency('named'),
13 | ],
14 | )
15 |
16 |
17 | def init():
18 | import main
19 |
--------------------------------------------------------------------------------
/ajenti/plugins/configurator/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Ajenti Configurator',
7 | description='Configuration section for setting up Ajenti itself',
8 | icon='wrench',
9 | dependencies=[
10 | PluginDependency('main')
11 | ],
12 | )
13 |
14 |
15 | def init():
16 | import api
17 | import configurator
18 |
--------------------------------------------------------------------------------
/ajenti/plugins/iptables/layout/option.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/ajenti/plugins/netatalk/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Netatalk',
7 | description='AFP file server',
8 | icon='folder-close',
9 | dependencies=[
10 | PluginDependency('main'),
11 | PluginDependency('services'),
12 | BinaryDependency('afpd'),
13 | ],
14 | )
15 |
16 |
17 | def init():
18 | import main
19 |
--------------------------------------------------------------------------------
/ajenti/plugins/samba/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Samba',
7 | icon='folder-close',
8 | dependencies=[
9 | PluginDependency('main'),
10 | PluginDependency('services'),
11 | BinaryDependency('smbd'),
12 | BinaryDependency('smbstatus'),
13 | ],
14 | )
15 |
16 |
17 | def init():
18 | import main
19 |
--------------------------------------------------------------------------------
/ajenti/plugins/ctdb/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='CTDB',
7 | description='Clustering support for Samba',
8 | icon='folder-close',
9 | dependencies=[
10 | PluginDependency('main'),
11 | PluginDependency('services'),
12 | BinaryDependency('ctdb'),
13 | ],
14 | )
15 |
16 |
17 | def init():
18 | import main
19 |
--------------------------------------------------------------------------------
/ajenti/plugins/hdparm/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='HDD state',
7 | description='Widget for hdparm utility',
8 | icon='hdd',
9 | dependencies=[
10 | PluginDependency('main'),
11 | PluginDependency('dashboard'),
12 | BinaryDependency('hdparm')
13 | ],
14 | )
15 |
16 |
17 | def init():
18 | import widget
19 |
--------------------------------------------------------------------------------
/ajenti/plugins/mongo/layout/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/ajenti/plugins/mysql/layout/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/ajenti/plugins/openvpn/layout/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/ajenti/plugins/sensors/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Sensors',
7 | icon='leaf',
8 | dependencies=[
9 | PluginDependency('main'),
10 | PluginDependency('dashboard'),
11 | ],
12 | )
13 |
14 |
15 | def init():
16 | import hostname
17 | import uptime
18 | import load
19 | import memory
20 | import cpu
21 |
--------------------------------------------------------------------------------
/ajenti/plugins/raid/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='RAID',
7 | description='mdadm status display',
8 | icon='hdd',
9 | dependencies=[
10 | PluginDependency('main'),
11 | BinaryDependency('mdadm'),
12 | FileDependency('/proc/mdstat'),
13 | ],
14 | )
15 |
16 |
17 | def init():
18 | import api
19 | import main
20 |
--------------------------------------------------------------------------------
/ajenti/plugins/apcups/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='APC UPS Status',
7 | description='APC UPS monitoring daemon',
8 | icon='bolt',
9 | dependencies=[
10 | PluginDependency('main'),
11 | PluginDependency('dashboard'),
12 | BinaryDependency('apcaccess'),
13 | ],
14 | )
15 |
16 |
17 | def init():
18 | import widget
19 |
--------------------------------------------------------------------------------
/ajenti/plugins/fstab/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Filesystems',
7 | icon='hdd',
8 | dependencies=[
9 | PluginDependency('main'),
10 | PluginDependency('dashboard'),
11 | FileDependency('/etc/fstab'),
12 | ],
13 | )
14 |
15 |
16 | def init():
17 | import main
18 | import widget
19 | import disks
20 | import iops
--------------------------------------------------------------------------------
/ajenti/plugins/iptables/content/css/iptables.less:
--------------------------------------------------------------------------------
1 | .control.label.iptables-action {
2 | border-radius: 3px;
3 | background: #888;
4 | color: white;
5 | padding: 0 5px;
6 | font-weight: bold;
7 |
8 | &.iptables-ACCEPT {
9 | background: #62BD00;
10 | }
11 |
12 | &.iptables-REJECT {
13 | background: #F51D1D;
14 | }
15 |
16 | &.iptables-DROP {
17 | background: #E47620;
18 | }
19 | }
--------------------------------------------------------------------------------
/packaging/files/ajenti-bsd:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # PROVIDE: ajenti
4 | # REQUIRE: netif
5 | # KEYWORD: nojail
6 |
7 | . /etc/rc.subr
8 |
9 | name="ajenti"
10 | command="/usr/local/bin/ajenti-panel"
11 | start_cmd="/usr/local/bin/ajenti-panel -d --config /usr/local/etc/ajenti/config.json"
12 | procname="/usr/local/bin/ajenti-panel"
13 | command_interpreter=`readlink -f /usr/local/bin/python`
14 |
15 | load_rc_config $name
16 | run_rc_command "$1"
17 |
--------------------------------------------------------------------------------
/ajenti/plugins/hddtemp/layout/widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
15 |
--------------------------------------------------------------------------------
/ajenti/plugins/rethink/layout/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/ajenti/plugins/test/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Test',
7 | icon=None,
8 | dependencies=[
9 | PluginDependency('main'),
10 | ],
11 | )
12 |
13 |
14 | def init():
15 | import simple.main
16 | import events.main
17 | import notifications.main
18 | import binder.main
19 | import http.http
20 | import classconfig.main
21 |
--------------------------------------------------------------------------------
/ajenti/plugins/lm_sensors/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='LM-Sensors',
7 | description='lm-sensors temperature sensor widgets',
8 | icon='leaf',
9 | dependencies=[
10 | PluginDependency('main'),
11 | PluginDependency('dashboard'),
12 | BinaryDependency('sensors'),
13 | ],
14 | )
15 |
16 |
17 | def init():
18 | import main
19 |
--------------------------------------------------------------------------------
/ajenti/plugins/megaraid/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='RAID',
7 | description='LSI MegaRAID status display',
8 | icon='hdd',
9 | dependencies=[
10 | PluginDependency('main'),
11 | FileDependency('/opt/MegaRAID/MegaCli/MegaCli'),
12 | ],
13 | )
14 |
15 |
16 | def init():
17 | import api
18 | import main
19 | import widget
20 |
--------------------------------------------------------------------------------
/ajenti/plugins/megaraid/layout/widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
15 |
--------------------------------------------------------------------------------
/ajenti/plugins/munin/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Munin',
7 | icon='stethoscope',
8 | dependencies=[
9 | PluginDependency('main'),
10 | PluginDependency('dashboard'),
11 | BinaryDependency('munin-cron'),
12 | ModuleDependency('BeautifulSoup'),
13 | ],
14 | )
15 |
16 |
17 | def init():
18 | import main
19 | import widget
20 |
--------------------------------------------------------------------------------
/ajenti/plugins/hddtemp/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='HDD temperature',
7 | description='Widget for the hddtemp daemon',
8 | icon='hdd',
9 | dependencies=[
10 | PluginDependency('main'),
11 | PluginDependency('dashboard'),
12 | BinaryDependency('hddtemp')
13 | ],
14 | )
15 |
16 |
17 | def init():
18 | import widget
19 | import sensor
--------------------------------------------------------------------------------
/ajenti/plugins/network/layout/bit-linux-basic.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ajenti/plugins/nsd/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='NSD',
7 | description='NSD DNS server',
8 | icon='globe',
9 | dependencies=[
10 | PluginDependency('main'),
11 | PluginDependency('services'),
12 | BinaryDependency('nsd'),
13 | FileDependency('/etc/nsd3/nsd.conf'),
14 | ],
15 | )
16 |
17 |
18 | def init():
19 | import main
20 |
--------------------------------------------------------------------------------
/ajenti/plugins/ipmi/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='IPMI',
7 | description='Intel power management interface widgets',
8 | icon='dashboard',
9 | dependencies=[
10 | PluginDependency('main'),
11 | PluginDependency('dashboard'),
12 | BinaryDependency('ipmitool')
13 | ],
14 | )
15 |
16 |
17 | def init():
18 | import widget
19 | import sensor
--------------------------------------------------------------------------------
/ajenti/plugins/dashboard/welcome.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import plugin
2 | from ajenti.plugins.dashboard.api import DashboardWidget
3 | from ajenti.ui import UIElement
4 |
5 |
6 | @plugin
7 | class DashboardWelcome (UIElement):
8 | typeid = 'dashboard:welcome'
9 |
10 |
11 | @plugin
12 | class WelcomeWidget (DashboardWidget):
13 | name = _('Welcome')
14 | icon = 'comment'
15 |
16 | def init(self):
17 | self.append(self.ui.inflate('dashboard:welcome'))
18 |
--------------------------------------------------------------------------------
/debian/postinst:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | #DEBHELPER#
3 | update-rc.d ajenti defaults > /dev/null
4 | ajenti-ssl-gen `hostname` || true
5 | service ajenti restart > /dev/null 2>&1
6 |
7 | echo ------------------------------------------------
8 | echo Now start Ajenti with \'service ajenti restart\'
9 | echo Ajenti will listen on HTTPS port 8000 by default
10 | echo
11 | echo Default username : root
12 | echo Default password : admin
13 | echo ------------------------------------------------
14 |
--------------------------------------------------------------------------------
/ajenti/plugins/iptables/layout/option-state.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/ajenti/plugins/main/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.api.http import *
3 | from ajenti.plugins import *
4 |
5 |
6 | info = PluginInfo(
7 | title='Core',
8 | icon='link',
9 | dependencies=[
10 | ],
11 | )
12 |
13 |
14 | def init():
15 | import main
16 | import api
17 | import passwd
18 | import controls_binding
19 | import controls_containers
20 | import controls_simple
21 | import controls_inputs
22 | import controls_dialogs
23 |
--------------------------------------------------------------------------------
/ajenti/plugins/dhcpd/layout/options.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/ajenti/plugins/lm_sensors/layout/widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
17 |
--------------------------------------------------------------------------------
/scripts/install-rhel.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | if [ "$(id -u)" != "0" ]; then
3 | echo "This script must be run as root" 1>&2
4 | exit 1
5 | fi
6 |
7 | echo ':: Adding EPEL repo'
8 | rpm -ivh http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
9 |
10 | echo ':: Adding Ajenti repo'
11 | rpm -ivh http://repo.ajenti.org/ajenti-repo-1.0-1.noarch.rpm
12 |
13 | echo ':: Installing package'
14 | yum install ajenti -y
15 |
16 | echo ':: Done! Open https://:8000 in browser'
17 |
--------------------------------------------------------------------------------
/ajenti/plugins/git/__init__.py:
--------------------------------------------------------------------------------
1 |
2 | import ajenti
3 | from ajenti.api import *
4 | from ajenti.plugins import *
5 |
6 | info = PluginInfo(
7 | title = 'GIT',
8 | icon = 'folder-close',
9 | description='Git Management Tool with Gitolite3 Authorization',
10 | dependencies =
11 | [
12 | PluginDependency('main'),
13 | PluginDependency('services'),
14 | BinaryDependency('git'),
15 | BinaryDependency('gitolite')
16 | ]
17 | )
18 |
19 | def init():
20 | import main;
--------------------------------------------------------------------------------
/ajenti/plugins/ipmi/layout/widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
17 |
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/css/vars.i.less:
--------------------------------------------------------------------------------
1 | @orange: #ed930d;
2 |
3 | @fontFamily: "Open Sans", sans-serif;
4 | @fontSize: 11px;
5 | @fontSizeSmaller: 11px;
6 |
7 | @headerHeight: 32px;
8 |
9 | @tableCell: #fcfcfc;
10 | @tableBorder: #f0f0f0;
11 |
12 | @controlText: #7c8c99; //#566675;
13 | @controlTextLighter: lighten(@controlText, 20%);
14 |
15 | @controlHeight: 30px;
16 | @controlWidth: 120px;
17 | @controlWidth2: 160px;
18 | @controlWidth3: 240px;
19 |
20 | @controlBorder: #eee;
21 | @buttonColor: #fcfcfc;
--------------------------------------------------------------------------------
/ajenti/plugins/sensors/layout/value-widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
17 |
--------------------------------------------------------------------------------
/ajenti/plugins/fstab/layout/free-widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
18 |
--------------------------------------------------------------------------------
/ajenti/plugins/packages/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Package manager',
7 | icon='gift',
8 | dependencies=[
9 | PluginDependency('main'),
10 | PluginDependency('terminal')
11 | ],
12 | )
13 |
14 |
15 | def init():
16 | import main
17 | import pm_apt
18 | import pm_bsd
19 | import pm_yum
20 | import pm_pacman
21 | import pm_urpmi
22 | import pm_macports
23 | import installer
--------------------------------------------------------------------------------
/scripts/install-rhel7.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | if [ "$(id -u)" != "0" ]; then
3 | echo "This script must be run as root" 1>&2
4 | exit 1
5 | fi
6 |
7 | echo ':: Adding EPEL repo'
8 | rpm -ivh http://download.fedoraproject.org/pub/epel/beta/7/x86_64/epel-release-7-1.noarch.rpm || true
9 |
10 | echo ':: Adding Ajenti repo'
11 | rpm -ivh http://repo.ajenti.org/ajenti-repo-1.0-1.noarch.rpm
12 |
13 | echo ':: Installing package'
14 | yum install ajenti -y
15 |
16 | echo ':: Done! Open https://:8000 in browser'
17 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | recursive-include ajenti * *.*
2 | recursive-exclude ajenti *~ *.pyc
3 | recursive-exclude packaging * *.*
4 | include README
5 | include COPYRIGHT
6 | include LICENSE
7 | include Makefile
8 | include requirements.txt
9 | include packaging/files/config.json
10 | include packaging/files/ajenti
11 | include packaging/files/.placeholder
12 | prune ajenti/plugins/elements
13 | prune ajenti/plugins/ltfs
14 | prune ajenti/plugins/vh
15 | prune ajenti/plugins/test
16 | prune ajenti/plugins/test*
17 | prune ajenti/plugins/custom
--------------------------------------------------------------------------------
/ajenti/plugins/packages/pm_bsd.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from api import PackageInfo, PackageManager
3 |
4 |
5 | @plugin
6 | @rootcontext
7 | @persistent
8 | class BSDPackageManager (PackageManager):
9 | platforms = ['freebsd']
10 |
11 | def init(self):
12 | self.upgradeable = []
13 |
14 | def get_lists(self):
15 | pass
16 |
17 | def refresh(self):
18 | pass
19 |
20 | def search(self, query):
21 | return []
22 |
23 | def do(self, actions):
24 | pass
25 |
--------------------------------------------------------------------------------
/ajenti/plugins/packages/pm_macports.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from api import PackageInfo, PackageManager
3 |
4 |
5 | @plugin
6 | @rootcontext
7 | @persistent
8 | class MacPortsPackageManager (PackageManager):
9 | platforms = ['osx']
10 |
11 | def init(self):
12 | self.upgradeable = []
13 |
14 | def get_lists(self):
15 | pass
16 |
17 | def refresh(self):
18 | pass
19 |
20 | def search(self, query):
21 | return []
22 |
23 | def do(self, actions):
24 | pass
25 |
--------------------------------------------------------------------------------
/ajenti/plugins/network/layout/bit-linux-ifupdown.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/ajenti/plugins/network/ncs_linux_dhcp.py:
--------------------------------------------------------------------------------
1 | from ajenti.ui import *
2 | from ajenti.ui.binder import Binder
3 |
4 | from api import *
5 |
6 |
7 | @plugin
8 | class LinuxDHCPNetworkConfigSet (NetworkConfigBit):
9 | cls = 'linux-dhcp'
10 | title = 'DHCP'
11 |
12 | def init(self):
13 | self.append(self.ui.inflate('network:bit-linux-dhcp'))
14 | self.binder = Binder(None, self)
15 |
16 | def refresh(self):
17 | self.binder.setup(self.iface).populate()
18 |
19 | def apply(self):
20 | self.binder.update()
21 |
--------------------------------------------------------------------------------
/ajenti/plugins/network/ncs_linux_ipv4.py:
--------------------------------------------------------------------------------
1 | from ajenti.ui import *
2 | from ajenti.ui.binder import Binder
3 |
4 | from api import *
5 |
6 |
7 | @plugin
8 | class LinuxIPv4NetworkConfigSet (NetworkConfigBit):
9 | cls = 'linux-ipv4'
10 | title = 'IPv4'
11 |
12 | def init(self):
13 | self.append(self.ui.inflate('network:bit-linux-ipv4'))
14 | self.binder = Binder(None, self)
15 |
16 | def refresh(self):
17 | self.binder.setup(self.iface).populate()
18 |
19 | def apply(self):
20 | self.binder.update()
21 |
--------------------------------------------------------------------------------
/ajenti/plugins/smartctl/layout/widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
19 |
--------------------------------------------------------------------------------
/ajenti/plugins/git/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/ajenti/plugins/network/ncs_linux_basic.py:
--------------------------------------------------------------------------------
1 | from ajenti.ui import *
2 | from ajenti.ui.binder import Binder
3 |
4 | from api import *
5 |
6 |
7 | @plugin
8 | class LinuxBasicNetworkConfigSet (NetworkConfigBit):
9 | cls = 'linux-basic'
10 | title = 'Basic'
11 |
12 | def init(self):
13 | self.append(self.ui.inflate('network:bit-linux-basic'))
14 | self.binder = Binder(None, self)
15 |
16 | def refresh(self):
17 | self.binder.setup(self.iface).populate()
18 |
19 | def apply(self):
20 | self.binder.update()
21 |
--------------------------------------------------------------------------------
/ajenti/plugins/hdparm/layout/widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/ajenti/plugins/squid/layout/options-editor.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | *.mo
3 | docs/build/*
4 | *~
5 |
6 | debian/ajenti*
7 | debian/changelog
8 | dist/*.rpm
9 | dist/*.deb
10 | dist/*.gz
11 | dist/*.whl
12 | *.egg*
13 | build/*
14 | debian/files
15 | debian/*stamp*
16 |
17 | .idea/
18 | *.sublime-*
19 |
20 | .~lock.*
21 |
22 | crowdin.zip
23 |
24 | # Compiled
25 | *.coffee.js
26 | *.less.css
27 |
28 | # Compressed
29 | *.c.js
30 | *.c.css
31 |
32 | ajenti/plugins/custom*
33 | ajenti/plugins/ltfs*
34 | ajenti/plugins/elements*
35 | ajenti/plugins/test_*
36 | ajenti/plugins/vh*
37 |
38 | reconfigure
39 |
40 | src
41 |
--------------------------------------------------------------------------------
/ajenti/plugins/configurator/layout/ldap-sync-config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/ajenti/plugins/network/ncs_linux_ifupdown.py:
--------------------------------------------------------------------------------
1 | from ajenti.ui import *
2 | from ajenti.ui.binder import Binder
3 |
4 | from api import *
5 |
6 |
7 | @plugin
8 | class LinuxIfUpDownNetworkConfigSet (NetworkConfigBit):
9 | cls = 'linux-ifupdown'
10 | title = 'Scripts'
11 |
12 | def init(self):
13 | self.append(self.ui.inflate('network:bit-linux-ifupdown'))
14 | self.binder = Binder(None, self)
15 |
16 | def refresh(self):
17 | self.binder.setup(self.iface).populate()
18 |
19 | def apply(self):
20 | self.binder.update()
21 |
--------------------------------------------------------------------------------
/scripts/install-debian.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | if [ "$(id -u)" != "0" ]; then
3 | echo "This script must be run as root" 1>&2
4 | exit 1
5 | fi
6 |
7 | echo ':: Installing repo key'
8 | wget http://repo.ajenti.org/debian/key -O- | apt-key add -
9 |
10 | echo ':: Adding repo entry'
11 | echo "deb http://repo.ajenti.org/debian main main debian" > /etc/apt/sources.list.d/ajenti.list
12 |
13 | echo ':: Updating lists'
14 | apt-get update
15 |
16 | echo ':: Installing package'
17 | apt-get install -y ajenti
18 |
19 | echo ':: Done! Open https://:8000 in browser'
20 |
--------------------------------------------------------------------------------
/scripts/install-ubuntu.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | if [ "$(id -u)" != "0" ]; then
3 | echo "This script must be run as root" 1>&2
4 | exit 1
5 | fi
6 |
7 | echo ':: Installing repo key'
8 | wget http://repo.ajenti.org/debian/key -O- | apt-key add -
9 |
10 | echo ':: Adding repo entry'
11 | echo "deb http://repo.ajenti.org/debian main main ubuntu" > /etc/apt/sources.list.d/ajenti.list
12 |
13 | echo ':: Updating lists'
14 | apt-get update
15 |
16 | echo ':: Installing package'
17 | apt-get install -y ajenti
18 |
19 | echo ':: Done! Open https://:8000 in browser'
20 |
--------------------------------------------------------------------------------
/ajenti/plugins/test/notifications/main.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import plugin
2 | from ajenti.plugins.main.api import SectionPlugin
3 | from ajenti.ui import on
4 |
5 |
6 | @plugin
7 | class NotificationsDemo (SectionPlugin):
8 | def init(self):
9 | self.title = 'Notifications'
10 | self.icon = 'question'
11 | self.category = 'Demo'
12 |
13 | self.append(self.ui.inflate('test:notifications-main'))
14 |
15 | @on('show', 'click')
16 | def on_show(self):
17 | self.context.notify(self.find('style').value, self.find('text').value)
18 |
--------------------------------------------------------------------------------
/ajenti/plugins/dhcpd/layout/ranges.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/ajenti/plugins/fm/layout/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/ajenti/plugins/services/sensor.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import plugin
2 | from ajenti.api.sensors import Sensor
3 | from api import ServiceMultiplexor
4 |
5 |
6 | @plugin
7 | class ServiceSensor (Sensor):
8 | id = 'service'
9 | timeout = 5
10 |
11 | def init(self):
12 | self.sm = ServiceMultiplexor.get()
13 |
14 | def get_variants(self):
15 | return [x.name for x in self.sm.get_all()]
16 |
17 | def measure(self, variant):
18 | s = self.sm.get_one(variant)
19 | if not s:
20 | return 0
21 | return int(s.running)
22 |
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/js/feedback.coffee:
--------------------------------------------------------------------------------
1 | class Feedback
2 | configure: (@enabled, @os, @version, @edition) ->
3 | mixpanel.init(@token)
4 |
5 | emit: (evt, params) ->
6 | if @enabled
7 | params ?= {}
8 | params.os = @os
9 | params.version = @version
10 | params.edition = @edition
11 | try
12 | mixpanel.track evt, params
13 | catch e
14 | ;
15 |
16 |
17 | window.Feedback = new Feedback()
18 | window.Feedback.token = "b5e6ddf58b2d02245a7a19005d1cec48"
--------------------------------------------------------------------------------
/ajenti/plugins/network/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Network',
7 | icon='exchange',
8 | dependencies=[
9 | PluginDependency('main'),
10 | PluginDependency('dashboard'),
11 | ],
12 | )
13 |
14 |
15 | def init():
16 | import widget
17 | import api
18 | import main
19 | import nctp_linux
20 | import nc_debian
21 | import nc_centos
22 | import ncs_linux_basic
23 | import ncs_linux_ipv4
24 | import ncs_linux_dhcp
25 | import ncs_linux_ifupdown
26 |
--------------------------------------------------------------------------------
/ajenti/plugins/fstab/layout/widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
20 |
--------------------------------------------------------------------------------
/ajenti/plugins/test/layout/notifications-main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/ajenti/plugins/apache/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 | from ajenti.util import platform_select
4 |
5 |
6 | info = PluginInfo(
7 | title='Apache',
8 | description='Apache 2 web server',
9 | icon='globe',
10 | dependencies=[
11 | PluginDependency('webserver_common'),
12 | BinaryDependency(platform_select(
13 | mageia='httpd',
14 | centos='httpd',
15 | freebsd='apachectl',
16 | osx='apachectl',
17 | default='apache2',
18 | )),
19 | ],
20 | )
21 |
22 |
23 | def init():
24 | import main
25 |
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/js/ajenti-org.coffee:
--------------------------------------------------------------------------------
1 | class AjentiOrgConnector
2 | constructor: () ->
3 | if window.parent
4 | @target = window.parent
5 | @domainPolicy = '*' # TODO!
6 | @enabled = true
7 |
8 | send: (event, data) ->
9 | if @enabled
10 | data ?= {}
11 | message = event: event, data: data
12 | @target.postMessage(message, @domainPolicy)
13 |
14 | reportHeight: (h) ->
15 | @send('height', h)
16 |
17 |
18 | $ () ->
19 | window.aoConnector = new AjentiOrgConnector()
20 | window.aoConnector.send('ready')
21 |
--------------------------------------------------------------------------------
/ajenti/locales/__init__.py:
--------------------------------------------------------------------------------
1 | import gettext
2 | import os
3 |
4 | import ajenti
5 |
6 |
7 | language = ajenti.config.tree.language
8 | localedir = os.path.abspath(os.path.join(os.path.split(ajenti.__file__)[0], 'locales'))
9 | try:
10 | translation = gettext.translation(
11 | 'ajenti',
12 | localedir=localedir,
13 | languages=([language] if language else None),
14 | )
15 | except IOError: # not such translation
16 | translation = gettext.NullTranslations()
17 | translation.install(unicode=True)
18 |
19 |
20 | def list_locales():
21 | return [_ for _ in os.listdir(localedir) if len(_) == 5]
22 |
--------------------------------------------------------------------------------
/ajenti/plugins/munin/widget.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import plugin
2 | from ajenti.plugins.dashboard.api import ConfigurableWidget
3 |
4 |
5 | @plugin
6 | class MuninWidget (ConfigurableWidget):
7 | name = 'Munin'
8 | icon = 'stethoscope'
9 | hidden = True
10 |
11 | def on_prepare(self):
12 | self.append(self.ui.inflate('munin:widget'))
13 |
14 | def on_start(self):
15 | self.find('plot').url = self.config['url']
16 | if 'period' in self.config:
17 | self.find('plot').period = self.config['period']
18 |
19 | def create_config(self):
20 | return {'url': '', 'period': ''}
21 |
--------------------------------------------------------------------------------
/ajenti/plugins/sensors/layout/progressbar-widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
21 |
--------------------------------------------------------------------------------
/ajenti/plugins/fstab/layout/iio-widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
22 |
--------------------------------------------------------------------------------
/ajenti/plugins/dashboard/text.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import plugin
2 | from ajenti.plugins.dashboard.api import ConfigurableWidget
3 |
4 |
5 | @plugin
6 | class TextWidget (ConfigurableWidget):
7 | name = _('Text')
8 | icon = 'font'
9 |
10 | def on_prepare(self):
11 | self.append(self.ui.inflate('dashboard:text'))
12 |
13 | def on_start(self):
14 | self.find('text').text = self.config['text']
15 |
16 | def create_config(self):
17 | return {'text': ''}
18 |
19 | def on_config_start(self):
20 | pass
21 |
22 | def on_config_save(self):
23 | self.config['text'] = self.dialog.find('text').value
24 |
--------------------------------------------------------------------------------
/ajenti/plugins/network/layout/widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
22 |
--------------------------------------------------------------------------------
/ajenti/plugins/codemirror/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 | from ajenti.ui import *
4 |
5 |
6 | info = PluginInfo(
7 | title=_('CodeMirror code editor'),
8 | description='Adds a rich code editor support to other plugins',
9 | icon='link',
10 | dependencies=[
11 | PluginDependency('main')
12 | ],
13 | )
14 |
15 |
16 | def init():
17 |
18 | @p('width', default='auto')
19 | @p('height', default='auto')
20 | @p('mode', default='default', type=unicode)
21 | @p('value', default='', type=unicode, bindtypes=[str, unicode])
22 | @plugin
23 | class CodeArea (UIElement):
24 | typeid = 'codearea'
25 |
--------------------------------------------------------------------------------
/ajenti/plugins/munin/content/css/plot.less:
--------------------------------------------------------------------------------
1 | .control.munin-plot {
2 | overflow: hidden;
3 | border-radius: 5px;
4 | box-shadow: 0 1px 3px black;
5 |
6 | width: 493px;
7 | margin: 30px auto;
8 | position: relative;
9 |
10 | img {
11 | max-width: inherit;
12 | opacity: .75;
13 | margin: -2px;
14 | }
15 |
16 | a {
17 | position: absolute !important;
18 | right: -5px;
19 | top: -5px !important;
20 | }
21 |
22 | &.widget-mode {
23 | margin: 0;
24 | box-shadow: none;
25 |
26 |
27 | width: 340px;
28 | img { width: 344px; }
29 |
30 | a { display: none; }
31 | }
32 | }
--------------------------------------------------------------------------------
/ajenti/plugins/services/__init__.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import *
3 |
4 |
5 | info = PluginInfo(
6 | title='Services',
7 | icon='play',
8 | dependencies=[
9 | PluginDependency('main'),
10 | PluginDependency('dashboard'),
11 | ],
12 | )
13 |
14 |
15 | def init():
16 | import api
17 |
18 | try:
19 | import dbus
20 |
21 | import sm_upstart
22 | import sm_systemd
23 | except ImportError:
24 | pass
25 |
26 | import sm_sysvinit
27 | import sm_sysvinit_centos
28 | import sm_freebsd
29 | import sm_osx
30 |
31 | import main
32 | import widget
33 | import sensor
34 |
--------------------------------------------------------------------------------
/ajenti/plugins/iptables/layout/option-custom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/ajenti/plugins/iptables/layout/option-reject-with.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/ajenti/plugins/packages/layout/row.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/ajenti/plugins/notepad/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/ajenti/plugins/scripts/layout/widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
22 |
--------------------------------------------------------------------------------
/ajenti/plugins/terminal/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/docs/source/man/faq.rst:
--------------------------------------------------------------------------------
1 | FAQ
2 | ===
3 |
4 | How do I add domains/PHP/email accounts/websites?
5 | -------------------------------------------------
6 |
7 | Pure Ajenti is a **server control** panel, not a **hosting control** panel. You need the Ajenti V add-on for web-hosting stuff: http://ajenti.org/#product-ajenti-v.
8 |
9 | I forgot my password
10 | --------------------
11 |
12 | Open /etc/ajenti/config.json, look for your user entry, and replace whole password hash entry with a new plaintext password. Restart Ajenti. Click "save" under "Configuration" to rehash the password.
13 |
14 | My OS isn't supported, but I'm a brave adventurer
15 | -------------------------------------------------
16 |
17 | ::
18 |
19 | pip install ajenti
20 |
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/js/_lib/cookies.m.js:
--------------------------------------------------------------------------------
1 | function setCookie(c_name, value, exdays) {
2 | var exdate = new Date();
3 | exdate.setDate(exdate.getDate() + exdays);
4 | var c_value = escape(value) + ((exdays == null) ? "" : "; expires=" + exdate.toUTCString());
5 | document.cookie = c_name + "=" + c_value;
6 | }
7 |
8 | function getCookie(c_name) {
9 | var i, x, y, ARRcookies = document.cookie.split(";");
10 | for (i = 0; i < ARRcookies.length; i++) {
11 | x = ARRcookies[i].substr(0, ARRcookies[i].indexOf("="));
12 | y = ARRcookies[i].substr(ARRcookies[i].indexOf("=") + 1);
13 | x = x.replace(/^\s+|\s+$/g, "");
14 | if (x == c_name) {
15 | return unescape(y);
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/ajenti/plugins/hddtemp/sensor.py:
--------------------------------------------------------------------------------
1 | import os
2 | import re
3 | import subprocess
4 |
5 | from ajenti.api import *
6 | from ajenti.api.sensors import Sensor
7 |
8 |
9 | @plugin
10 | class DiskTemperatureSensor (Sensor):
11 | id = 'hdd-temp'
12 | timeout = 5
13 |
14 | def get_variants(self):
15 | r = []
16 | for s in os.listdir('/dev'):
17 | if re.match('sd.$|hd.$|scd.$|fd.$|ad.+$', s):
18 | r.append(s)
19 | return sorted(r)
20 |
21 | def measure(self, device):
22 | try:
23 | v = float('0' + subprocess.check_output(
24 | ['hddtemp', '/dev/%s' % device, '-uC', '-qn'], stderr=None).strip())
25 | return v
26 | except:
27 | return 0
28 |
--------------------------------------------------------------------------------
/scripts/install-raspbian.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | if [ "$(id -u)" != "0" ]; then
3 | echo "This script must be run as root" 1>&2
4 | exit 1
5 | fi
6 |
7 | echo ':: Installing repo key'
8 | wget http://repo.ajenti.org/debian/key -O- | apt-key add -
9 |
10 | echo ':: Adding repo entry'
11 | echo "deb http://repo.ajenti.org/debian main main debian" > /etc/apt/sources.list.d/ajenti.list
12 |
13 | echo ':: Updating lists'
14 | apt-get update
15 |
16 | echo ':: Installing packages'
17 | apt-get install -y ajenti
18 | apt-get install -y python-pip python-dev libevent-dev
19 | pip install -U gevent
20 | pip install greenlet==dev
21 | pip install psutil --upgrade
22 | /etc/init.d/ajenti restart
23 |
24 | echo ':: Done! Open https://:8000 in browser'
25 |
--------------------------------------------------------------------------------
/ajenti/plugins/munin/content/js/plot.coffee:
--------------------------------------------------------------------------------
1 | class window.Controls.munin__plot extends window.Control
2 | createDom: () ->
3 | url = '/ajenti:munin-proxy/' + encodeURIComponent(@properties.url)
4 | if @properties.period
5 | url += @properties.period + '.png'
6 | """
7 |
11 | """
12 |
13 | setupDom: (dom) ->
14 | super(dom)
15 | $(@dom).find('a').click () =>
16 | @event('widget', url: @properties.url, period: @properties.period)
17 |
18 |
--------------------------------------------------------------------------------
/ajenti/plugins/main/layout/passwd-main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/ajenti/plugins/test/events/main.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins.main.api import SectionPlugin
3 | from ajenti.ui import on
4 |
5 |
6 | @plugin
7 | class EventsDemo (SectionPlugin):
8 | def init(self):
9 | self.title = 'Event handlers'
10 | self.icon = 'question'
11 | self.category = 'Demo'
12 |
13 | self.append(self.ui.inflate('test:events-main'))
14 |
15 | def on_click(*args):
16 | self.context.notify('info', 'Directly attached event fired with arguments %s!' % repr(args))
17 |
18 | self.find('btn').on('click', on_click, 123, 456)
19 |
20 |
21 | @on('btn', 'click')
22 | def on_button_click(self):
23 | self.context.notify('info', 'Decorator-attached event fired!')
24 |
--------------------------------------------------------------------------------
/ajenti/plugins/configurator/layout/ad-sync-config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/ajenti/plugins/cron/api.py:
--------------------------------------------------------------------------------
1 | import subprocess
2 |
3 | from ajenti.api import plugin
4 | from reconfigure.configs import CrontabConfig
5 |
6 |
7 | @plugin
8 | class CronManager (object):
9 | def load_tab(self, user):
10 | self.current_user = user
11 | try:
12 | data = subprocess.check_output(['crontab', '-l', '-u', user])
13 | except Exception:
14 | data = ''
15 | config = CrontabConfig(content=data)
16 | config.load()
17 | return config
18 |
19 | def save_tab(self, user, config):
20 | data = config.save()[None]
21 | p = subprocess.Popen(['crontab', '-', '-u', user])
22 | stdout, stderr = p.communicate(data + '\n')
23 | if stderr:
24 | raise Exception(stderr)
25 |
26 |
--------------------------------------------------------------------------------
/ajenti/plugins/ipmi/sensor.py:
--------------------------------------------------------------------------------
1 | import subprocess
2 |
3 | from ajenti.api import *
4 | from ajenti.api.sensors import Sensor
5 | from ajenti.util import cache_value
6 |
7 |
8 | @plugin
9 | class IPMISensor (Sensor):
10 | id = 'ipmi'
11 | timeout = 5
12 |
13 | @cache_value(2)
14 | def _get_data(self):
15 | r = {}
16 | for l in subprocess.check_output(['ipmitool', 'sensor']).splitlines():
17 | l = l.split('|')
18 | if len(l) > 2:
19 | r[l[0].strip()] = (l[1].strip(), l[2].strip())
20 | return r
21 |
22 | def get_variants(self):
23 | return sorted(self._get_data().keys())
24 |
25 | def measure(self, variant):
26 | try:
27 | return self._get_data()[variant]
28 | except:
29 | return (0, '')
30 |
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/css/lib.i.less:
--------------------------------------------------------------------------------
1 | .button-active(@g1) {
2 | background: lighten(@g1, 25%);
3 | border-color: @orange;
4 | }
5 |
6 | .button-style(@g1) {
7 | background: @g1;
8 |
9 | &, & i::before {
10 | color: rgba(0,0,0,.45);
11 | }
12 |
13 | &:hover {
14 | background: lighten(@g1, 10%);
15 | }
16 |
17 | &:active {
18 | .button-active(@g1);
19 | }
20 |
21 | font-size: @fontSizeSmaller;
22 | font-weight: bold;
23 | text-align: center;
24 | text-transform: uppercase;
25 |
26 | .border-radius(3px);
27 | border: 2px solid @controlBorder;
28 |
29 | position: relative;
30 | }
31 |
32 | .control-inset {
33 | .size(@controlHeight - 4px, @controlWidth2 - 10px);
34 | .border-radius(3px);
35 | border: 2px solid #eee;
36 | background: white;
37 | }
--------------------------------------------------------------------------------
/ajenti/plugins/megaraid/main.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins.main.api import SectionPlugin
3 | from ajenti.ui import on
4 | from ajenti.ui.binder import Binder
5 |
6 | from reconfigure.configs import ResolvConfig
7 | from reconfigure.items.resolv import ItemData
8 |
9 | from api import RAIDManager
10 |
11 |
12 | @plugin
13 | class RAID (SectionPlugin):
14 | def init(self):
15 | self.title = 'LSI MegaRAID'
16 | self.icon = 'hdd'
17 | self.category = _('System')
18 |
19 | self.append(self.ui.inflate('megaraid:main'))
20 |
21 | self.mgr = RAIDManager.get()
22 | self.binder = Binder(None, self)
23 |
24 | def on_page_load(self):
25 | self.refresh()
26 |
27 | def refresh(self):
28 | self.mgr.refresh()
29 | self.binder.setup(self.mgr).populate()
30 |
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/css/controls.dialogs.i.less:
--------------------------------------------------------------------------------
1 | .control {
2 | &.dialog {
3 | position: fixed;
4 | left: 0;
5 | top: 0;
6 | width: 100%;
7 | height: 100%;
8 | overflow: auto;
9 | z-index: 100;
10 |
11 | &>.backdrop {
12 | background: rgba(0,0,0,0.7);
13 | width: 100%;
14 | height: 100%;
15 | overflow-x: hidden;
16 | overflow-y: auto;
17 |
18 | &>.content {
19 | width: 400px;
20 | margin: 60px auto;
21 |
22 | background: #fbfbfb;
23 | .border-radius(5px);
24 | border: 2px solid @controlBorder;
25 |
26 | &>.buttons {
27 | &>* {
28 | float:right;
29 | }
30 |
31 | padding: 8px 10px;
32 | overflow: hidden;
33 | border-top: 1px solid @controlBorder;
34 | }
35 | }
36 | }
37 |
38 | }
39 |
40 | &.dialog.wide > .backdrop > .content {
41 | width: 800px;
42 | }
43 | }
--------------------------------------------------------------------------------
/ajenti/plugins/services/layout/widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
26 |
--------------------------------------------------------------------------------
/ajenti/plugins/network/layout/bit-linux-dhcp.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/docs/COPYRIGHT:
--------------------------------------------------------------------------------
1 | Copyright (c) 2010-2014 the Ajenti developers
2 |
3 | Contributors
4 | ------------
5 |
6 | * Eugene Pankov
7 | * Dmitry Zamaruev
8 | * Valentin Bryukhanov
9 | * Andrey Fishchenko
10 | * Ilya Gorbunov
11 | * Paul Shepel
12 |
13 | Full list of contributors: https://github.com/Eugeny/ajenti/graphs/contributors
14 |
15 | Various parts
16 | -------------
17 |
18 | * CodeMirror embeddable editor (c) Marijn Haverbeke
19 | * PyTE (c) Selectel , see plugins/terminal/pyte/
20 | * FontAwesome (c) Dave Gandy
21 |
22 | Feedback
23 | --------
24 |
25 | If you use Ajenti, we would be happy if you drop us a message about your experiences.
26 |
--------------------------------------------------------------------------------
/ajenti/plugins/terminal/content/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
21 |
22 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ajenti/plugins/mongo/main.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins.db_common.api import DBPlugin
3 | from ajenti.util import platform_select
4 |
5 | from api import MongoDB
6 |
7 |
8 | @plugin
9 | class MongoDBPlugin (DBPlugin):
10 | config_class = MongoDB
11 | has_users = False
12 |
13 | service_name = platform_select(
14 | default='mongod'
15 | )
16 |
17 | def init(self):
18 | self.title = 'MongoDB'
19 | self.category = _('Software')
20 | self.icon = 'table'
21 | self.db = MongoDB.get()
22 |
23 | def query_sql(self, db, sql):
24 | return self.db.query_sql(db, sql)
25 |
26 | def query_databases(self):
27 | return self.db.query_databases()
28 |
29 | def query_drop(self, db):
30 | return self.db.query_drop(db)
31 |
32 | def query_create(self, name):
33 | return self.db.query_create(name)
34 |
--------------------------------------------------------------------------------
/ajenti/plugins/packages/api.py:
--------------------------------------------------------------------------------
1 | import subprocess
2 |
3 | from ajenti.api import *
4 |
5 |
6 | class PackageInfo (object):
7 | def __init__(self):
8 | self.name = ''
9 | self.state = 'r'
10 | self.action = None
11 | self.version = ''
12 | self.description = ''
13 |
14 | @property
15 | def _icon(self):
16 | if self.action == 'i':
17 | return 'ok-circle'
18 | if self.action == 'r':
19 | return 'remove-circle'
20 | return 'ok' if self.state == 'i' else None
21 |
22 |
23 | @interface
24 | class PackageManager (BasePlugin):
25 | def init(self):
26 | self.upgradeable = []
27 |
28 | def get_lists(self):
29 | pass
30 |
31 | def refresh(self):
32 | pass
33 |
34 | def search(self, query):
35 | return []
36 |
37 | def do(self, actions, callback=lambda: 0):
38 | pass
39 |
--------------------------------------------------------------------------------
/ajenti/plugins/rethink/main.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins.db_common.api import DBPlugin
3 | from ajenti.util import platform_select
4 |
5 | from api import RethinkDB
6 |
7 |
8 | @plugin
9 | class RethinkDBPlugin (DBPlugin):
10 | config_class = RethinkDB
11 | has_users = False
12 |
13 | service_name = platform_select(
14 | default='rethinkdb'
15 | )
16 |
17 | def init(self):
18 | self.title = 'RethinkDB'
19 | self.category = _('Software')
20 | self.icon = 'table'
21 | self.db = RethinkDB.get()
22 |
23 | def query_sql(self, db, sql):
24 | return self.db.query_sql(db, sql)
25 |
26 | def query_databases(self):
27 | return self.db.query_databases()
28 |
29 | def query_drop(self, db):
30 | return self.db.query_drop(db)
31 |
32 | def query_create(self, name):
33 | return self.db.query_create(name)
34 |
--------------------------------------------------------------------------------
/ajenti/usersync/local.py:
--------------------------------------------------------------------------------
1 | from passlib.hash import sha512_crypt
2 |
3 | import ajenti
4 | from ajenti.api import *
5 |
6 | from base import UserSyncProvider
7 |
8 |
9 | @plugin
10 | class AjentiSyncProvider (UserSyncProvider):
11 | id = ''
12 | title = _('Off')
13 | allows_renaming = True
14 | syncs_root = True
15 |
16 | def test(self):
17 | pass
18 |
19 | def check_password(self, username, password):
20 | if not username in ajenti.config.tree.users:
21 | return False
22 | type = 'plain'
23 | saved = ajenti.config.tree.users[username].password
24 | if '|' in saved:
25 | type, saved = saved.split('|')
26 |
27 | if type == 'plain':
28 | hash = password
29 | return hash == saved
30 | elif sha512_crypt.identify(saved):
31 | return sha512_crypt.verify(password, saved)
32 |
33 | def sync(self):
34 | pass
--------------------------------------------------------------------------------
/ajenti/plugins/network/layout/bit-linux-ipv4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/js/profiler.coffee:
--------------------------------------------------------------------------------
1 | class Profiler
2 | constructor: () ->
3 | @profiles = {}
4 | @results = {}
5 | @timeout = null
6 | @stack = []
7 |
8 | start: (id) ->
9 | if @profiles[id]
10 | @stack.push null
11 | else
12 | @profiles[id] ?= new Date().getTime()
13 | @stack.push id
14 |
15 | stop: (id) ->
16 | id ?= @stack.pop()
17 | if id == null
18 | return
19 | @results[id] ?= 0.0
20 | @results[id] += new Date().getTime() - @profiles[id]
21 | @profiles[id] = undefined
22 |
23 | clearTimeout @timeout
24 | @timeout = setTimeout () =>
25 | @dump()
26 | , 1000
27 |
28 | dump: () ->
29 | for id of @results
30 | console.log 'Profiled', id, @results[id] / 1000, 's'
31 | @results = {}
32 |
33 |
34 | window.profiler = new Profiler()
35 |
--------------------------------------------------------------------------------
/debian/control:
--------------------------------------------------------------------------------
1 | Source: ajenti
2 | Section: admin
3 | Priority: optional
4 | Maintainer: Eugene Pankov
5 | Build-Depends: debhelper (>=8.0.0), python-support (>= 0.6), cdbs (>= 0.4.49)
6 | XS-Python-Version: >=2.6
7 | Standards-Version: 3.9.1
8 |
9 | Package: ajenti
10 | Architecture: all
11 | Homepage: http://ajenti.org/
12 | XB-Python-Version: ${python:Versions}
13 | Depends: ${misc:Depends}, ${python:Depends}, python-lxml (>=2.2.4), python-gevent, openssl, python-gevent-socketio, python-psutil (>=0.6.0), python-reconfigure (>=0.1.46), python-daemon, python-passlib, python-requests (>=0.12.0), python-dbus, python-imaging, apt-show-versions, python-catcher, python-exconsole (>=0.1.5), python-ldap
14 | Description: Server administration web interface
15 | It provides rich functionality and support for lots of server software,
16 | along with system configuration options.
17 | Lots of additional plugins can be downloaded with plugin manager.
18 |
--------------------------------------------------------------------------------
/ajenti/plugins/logs/content/js/logs.coffee:
--------------------------------------------------------------------------------
1 | class window.Controls.logs__log extends window.Control
2 | createDom: () ->
3 | """
4 |
6 | """
7 |
8 | setupDom: (dom) ->
9 | super(dom)
10 | if @properties.path
11 | @socket = ajentiConnectSocket('/log')
12 | @socket.send(JSON.stringify(type: 'select', path: @properties.path))
13 | @socket.on 'add', @add
14 |
15 | add: (data) =>
16 | console.log 'Received: +' + data.length + ', total ' + $(@dom)[0].value.length
17 | $(@dom)[0].value += data
18 | if ($(@dom)[0].value.length > 128 * 1024)
19 | $(@dom)[0].value = $(@dom)[0].value.slice($(@dom)[0].value.length - 128 * 1024)
20 | @dom.scrollTop = @dom.scrollHeight;
21 |
22 | onBroadcast: (msg) ->
23 | if msg == 'destruct'
24 | if @socket
25 | @socket.disconnect()
--------------------------------------------------------------------------------
/ajenti/plugins/ajenti_org/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/ajenti/plugins/raid/main.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins.main.api import SectionPlugin
3 | from ajenti.ui import on
4 | from ajenti.ui.binder import Binder
5 |
6 | from reconfigure.configs import ResolvConfig
7 | from reconfigure.items.resolv import ItemData
8 |
9 | from api import RAIDManager
10 |
11 |
12 | @plugin
13 | class RAID (SectionPlugin):
14 | def init(self):
15 | self.title = _('RAID')
16 | self.icon = 'hdd'
17 | self.category = _('System')
18 |
19 | self.append(self.ui.inflate('raid:main'))
20 |
21 | def post_array_bind(o, c, i, u):
22 | u.find('recovery').visible = i.recovery
23 |
24 | self.find('arrays').post_item_bind = post_array_bind
25 |
26 | self.mgr = RAIDManager.get()
27 | self.binder = Binder(None, self)
28 |
29 | def on_page_load(self):
30 | self.refresh()
31 |
32 | def refresh(self):
33 | self.mgr.refresh()
34 | self.binder.setup(self.mgr).populate()
35 |
--------------------------------------------------------------------------------
/ajenti/plugins/squid/layout/port-template.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/ajenti/plugins/sensors/cpu.py:
--------------------------------------------------------------------------------
1 | import psutil
2 |
3 | from ajenti.api import plugin
4 | from ajenti.api.sensors import Sensor
5 | from ajenti.plugins.dashboard.api import DashboardWidget
6 |
7 |
8 | @plugin
9 | class CPUSensor (Sensor):
10 | id = 'cpu'
11 | timeout = 3
12 |
13 | def measure(self, variant=None):
14 | return [x / 100 for x in psutil.cpu_percent(interval=0, percpu=True)]
15 |
16 |
17 | @plugin
18 | class CPUWidget (DashboardWidget):
19 | name = _('CPU usage')
20 | icon = 'signal'
21 |
22 | def init(self):
23 | self.sensor = Sensor.find('cpu')
24 | self.append(self.ui.inflate('sensors:cpu-widget'))
25 | self.find('icon').icon = 'signal'
26 | self.find('name').text = _('CPU usage')
27 | for value in self.sensor.value():
28 | l = self.ui.inflate('sensors:cpu-line')
29 | l.find('progress').value = value
30 | l.find('value').text = '%i%%' % int(value * 100)
31 | self.find('lines').append(l)
32 |
--------------------------------------------------------------------------------
/ajenti/plugins/samba/status.py:
--------------------------------------------------------------------------------
1 | import os
2 | import subprocess
3 |
4 |
5 | class SambaMonitor (object):
6 | def __init__(self):
7 | self.refresh()
8 |
9 | def refresh(self):
10 | pids = {}
11 |
12 | ll = subprocess.check_output(['smbstatus', '-p']).splitlines()
13 | for l in ll[4:]:
14 | s = l.split()
15 | if len(s) > 0:
16 | pids[s[0]] = (s[1], ' '.join(s[3:]))
17 |
18 | self.connections = []
19 | ll = subprocess.check_output(['smbstatus', '-S']).splitlines()
20 | for l in ll[3:]:
21 | s = l.split()
22 | if len(s) > 0 and s[1] in pids:
23 | c = SambaConnection(s[0], s[1], *pids[s[1]])
24 | self.connections.append(c)
25 |
26 |
27 | class SambaConnection (object):
28 | def __init__(self, share, pid, user, machine):
29 | self.share, self.pid, self.user, self.machine = share, pid, user, machine
30 |
31 | def disconnect(self):
32 | os.kill(int(self.pid), 15)
33 |
--------------------------------------------------------------------------------
/ajenti/plugins/hosts/main.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins.main.api import SectionPlugin
3 | from ajenti.ui import on
4 | from ajenti.ui.binder import Binder
5 |
6 | from reconfigure.configs import HostsConfig
7 | from reconfigure.items.hosts import AliasData, HostData
8 |
9 |
10 | @plugin
11 | class Hosts (SectionPlugin):
12 | def init(self):
13 | self.title = _('Hosts')
14 | self.icon = 'sitemap'
15 | self.category = _('System')
16 |
17 | self.append(self.ui.inflate('hosts:main'))
18 |
19 | self.config = HostsConfig(path='/etc/hosts')
20 | self.binder = Binder(None, self.find('hosts-config'))
21 | self.find('aliases').new_item = lambda c: AliasData()
22 | self.find('hosts').new_item = lambda c: HostData()
23 |
24 | def on_page_load(self):
25 | self.config.load()
26 | self.binder.setup(self.config.tree).populate()
27 |
28 | @on('save', 'click')
29 | def save(self):
30 | self.binder.update()
31 | self.config.save()
32 |
--------------------------------------------------------------------------------
/ajenti/plugins/sensors/uptime.py:
--------------------------------------------------------------------------------
1 | import psutil
2 | import time
3 |
4 | from ajenti.api import plugin
5 | from ajenti.api.sensors import Sensor
6 | from ajenti.plugins.dashboard.api import DashboardWidget
7 | from ajenti.util import str_timedelta
8 |
9 |
10 | @plugin
11 | class UnixUptimeSensor (Sensor):
12 | id = 'uptime'
13 | timeout = 1
14 |
15 | def measure(self, variant):
16 | btime = 0
17 | try:
18 | btime = time.time() - psutil.BOOT_TIME
19 | except AttributeError:
20 | """psutil 2.0"""
21 | btime = time.time() - psutil.boot_time()
22 | return btime
23 |
24 | @plugin
25 | class UptimeWidget (DashboardWidget):
26 | name = _('Uptime')
27 | icon = 'off'
28 |
29 | def init(self):
30 | self.sensor = Sensor.find('uptime')
31 | self.append(self.ui.inflate('sensors:value-widget'))
32 |
33 | self.find('icon').text = 'off'
34 | self.find('name').text = 'Uptime'
35 | self.find('value').text = str_timedelta(self.sensor.value())
36 |
--------------------------------------------------------------------------------
/ajenti/plugins/uname/layout/widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
25 |
26 |
--------------------------------------------------------------------------------
/ajenti/plugins/main/content/css/z-mode-tablet.less:
--------------------------------------------------------------------------------
1 | html.mode-tablet {
2 | #header .container {
3 | margin: 0;
4 | }
5 |
6 | .control.main-sections-root > .sidebar .tab {
7 | padding: 5px 10px;
8 | font-size: 12px;
9 | margin: 0;
10 | border-radius: 3px;
11 | }
12 |
13 | .control.main-page > .content-wr {
14 | padding: 0;
15 |
16 | &>.content {
17 | margin: 0 0 60px;
18 |
19 | .sidebar {
20 | border-right: 1px solid #ccc;
21 | width: 149px;
22 | padding: 0;
23 |
24 | a {
25 | border-radius: 0;
26 | }
27 |
28 | .main-sections-category > div:first-child {
29 | margin: 10px 0 0 8px;
30 | font-size: 14px;
31 | border-bottom: 1px solid #ddd;
32 | }
33 | }
34 |
35 | .main {
36 | padding-top: 10px;
37 | }
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/ajenti/plugins/tasks/layout/params-rsync.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/ajenti/plugins/dashboard/updater.py:
--------------------------------------------------------------------------------
1 | import gevent
2 |
3 | from ajenti.api import *
4 | from ajenti.plugins.packages.api import PackageManager, PackageInfo
5 |
6 |
7 | @plugin
8 | class AjentiUpdater (BasePlugin):
9 | AJENTI_PACKAGE_NAME = 'ajenti'
10 |
11 | def run_update(self, packages):
12 | packages = packages or [self.AJENTI_PACKAGE_NAME]
13 | actions = []
14 | mgr = PackageManager.get()
15 | for name in packages:
16 | p = PackageInfo()
17 | p.name, p.action = name, 'i'
18 | actions.append(p)
19 | mgr.do(actions)
20 |
21 | def check_for_updates(self, callback):
22 | try:
23 | mgr = PackageManager.get()
24 | except NoImplementationsError:
25 | return
26 |
27 | def worker():
28 | mgr.refresh()
29 | r = []
30 | for p in mgr.upgradeable:
31 | if p.name.startswith(self.AJENTI_PACKAGE_NAME):
32 | r.append(p.name)
33 | callback(r)
34 |
35 | gevent.spawn(worker)
36 |
--------------------------------------------------------------------------------
/ajenti/plugins/apcups/widget.py:
--------------------------------------------------------------------------------
1 | import subprocess
2 |
3 | from ajenti.api import plugin
4 | from ajenti.api.sensors import Sensor
5 | from ajenti.plugins.dashboard.api import DashboardWidget
6 |
7 |
8 | @plugin
9 | class UPSChargeSensor (Sensor):
10 | id = 'ups'
11 | timeout = 2
12 |
13 | def measure(self, variant=None):
14 | data = {}
15 | for l in subprocess.check_output('apcaccess').splitlines():
16 | if l and ':' in l:
17 | k,v = l.split(':', 1)
18 | k = k.strip()
19 | v = v.strip()
20 | data[k] = v
21 |
22 | return (float(data.get('BCHARGE', '0 Percent').split()[0]) / 100.0, data.get('TIMELEFT', 'Unknown'))
23 |
24 |
25 | @plugin
26 | class UPSWidget (DashboardWidget):
27 | name = 'UPS'
28 | icon = 'bolt'
29 |
30 | def init(self):
31 | self.sensor = Sensor.find('ups')
32 | self.append(self.ui.inflate('apcups:widget'))
33 | value = self.sensor.value()
34 | self.find('charge').value = value[0]
35 | self.find('time').text = value[1]
36 |
--------------------------------------------------------------------------------
/ajenti/plugins/services/sm_sysvinit_centos.py:
--------------------------------------------------------------------------------
1 | import os
2 | import subprocess
3 |
4 | from ajenti.api import *
5 | from ajenti.api.helpers import subprocess_call_background, subprocess_check_output_background
6 | from ajenti.util import cache_value
7 |
8 | from api import ServiceManager
9 | from sm_sysvinit import SysVInitService
10 |
11 |
12 | @plugin
13 | class CentOSServiceManager (ServiceManager):
14 | platforms = ['centos']
15 |
16 | @cache_value(1)
17 | def get_all(self):
18 | r = []
19 | pending = {}
20 | for line in subprocess_check_output_background(['chkconfig', '--list']).splitlines():
21 | tokens = line.split()
22 | if len(tokens) < 3:
23 | continue
24 |
25 | name = tokens[0]
26 | s = SysVInitService(name)
27 | s.refresh()
28 | r.append(s)
29 |
30 | return r
31 |
32 | def get_one(self, name):
33 | s = SysVInitService(name)
34 | if os.path.exists(s.script):
35 | s.refresh()
36 | return s
37 | return None
38 |
--------------------------------------------------------------------------------
/ajenti/plugins/hddtemp/widget.py:
--------------------------------------------------------------------------------
1 | #coding: utf-8
2 | from ajenti.api import plugin
3 | from ajenti.api.sensors import Sensor
4 | from ajenti.plugins.dashboard.api import ConfigurableWidget
5 |
6 |
7 | @plugin
8 | class HDDTempWidget (ConfigurableWidget):
9 | name = _('HDD Temperature')
10 | icon = 'hdd'
11 |
12 | def on_prepare(self):
13 | self.sensor = Sensor.find('hdd-temp')
14 | self.append(self.ui.inflate('hddtemp:widget'))
15 |
16 | def on_start(self):
17 | self.find('device').text = self.config['device']
18 | v = self.sensor.value(self.config['device'])
19 | self.find('value').text = '%.2f °C' % v
20 |
21 | def create_config(self):
22 | return {'device': ''}
23 |
24 | def on_config_start(self):
25 | device_list = self.dialog.find('device')
26 | lst = self.sensor.get_variants()
27 | device_list.labels = lst
28 | device_list.values = lst
29 | device_list.value = self.config['device']
30 |
31 | def on_config_save(self):
32 | self.config['device'] = self.dialog.find('device').value
33 |
--------------------------------------------------------------------------------
/ajenti/plugins/power/layout/widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/ajenti/plugins/ipmi/widget.py:
--------------------------------------------------------------------------------
1 | #coding: utf-8
2 | from ajenti.api import plugin
3 | from ajenti.api.sensors import Sensor
4 | from ajenti.plugins.dashboard.api import ConfigurableWidget
5 |
6 |
7 | @plugin
8 | class IPMIWidget (ConfigurableWidget):
9 | name = _('IPMI Sensor')
10 | icon = 'dashboard'
11 |
12 | def on_prepare(self):
13 | self.sensor = Sensor.find('ipmi')
14 | self.append(self.ui.inflate('ipmi:widget'))
15 |
16 | def on_start(self):
17 | self.find('variant').text = self.config['variant']
18 | v = self.sensor.value(self.config['variant'])
19 | self.find('value').text = v[0]
20 | self.find('unit').text = v[1]
21 |
22 | def create_config(self):
23 | return {'variant': ''}
24 |
25 | def on_config_start(self):
26 | v_list = self.dialog.find('variant')
27 | lst = self.sensor.get_variants()
28 | v_list.labels = lst
29 | v_list.values = lst
30 | v_list.value = self.config['variant']
31 |
32 | def on_config_save(self):
33 | self.config['variant'] = self.dialog.find('variant').value
34 |
--------------------------------------------------------------------------------
/ajenti/plugins/test/classconfig/main.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.api.http import *
3 | from ajenti.plugins.configurator.api import ClassConfigEditor
4 | from ajenti.plugins.main.api import SectionPlugin
5 | from ajenti.ui import on
6 |
7 |
8 | @plugin
9 | class SimpleConfigEditor (ClassConfigEditor):
10 | title = 'Simple demo config'
11 | icon = 'question'
12 |
13 | def init(self):
14 | self.append(self.ui.inflate('test:classconfig-simple-editor'))
15 |
16 |
17 | @plugin
18 | class SimpleClassconfigSection (SectionPlugin):
19 | default_classconfig = {'option1': 'qwerty', 'option2': 1}
20 | classconfig_editor = SimpleConfigEditor
21 |
22 | def init(self):
23 | self.title = 'Classconfig (simple)'
24 | self.icon = 'question'
25 | self.category = 'Demo'
26 | self.append(self.ui.inflate('test:classconfig-main'))
27 |
28 | def on_page_load(self):
29 | self.find('value').text = repr(self.classconfig)
30 |
31 | @on('config', 'click')
32 | def on_config_btn(self):
33 | self.context.launch('configure-plugin', plugin=self)
34 |
--------------------------------------------------------------------------------
/docs/source/man/run.rst:
--------------------------------------------------------------------------------
1 | Running Ajenti
2 | ==============
3 |
4 | Starting service
5 | ----------------
6 |
7 | Packages install binary *ajenti-panel* and initscript *ajenti*.
8 | You can ensure the service is running::
9 |
10 | service ajenti restart
11 |
12 | or::
13 |
14 | /etc/init.d/ajenti restart
15 |
16 |
17 | Ajenti can be run in a verbose debug mode::
18 |
19 | ajenti-panel -v
20 |
21 | The panel will be available on **HTTPS** port **8000** by default. The default username is **root**, and the password is **admin**
22 |
23 | Commandline options
24 | -------------------
25 |
26 | * **-c**, **--config ** - Use given config file instead of default
27 | * **-v** - Debug/verbose logging
28 | * **-d, --daemon** - Run in background (daemon mode)
29 | * **--set-platform ** - Override OS detection
30 |
31 |
32 | Debugging
33 | ---------
34 |
35 | Running ajenti with ``-v`` enables additional logging and Exconsole emergency console (see https://github.com/Eugeny/exconsole).
36 |
37 | Exconsole can be triggered by a crash, sending SIGQUIT or pressing ``Ctrl-\`` on the controlling terminal.
--------------------------------------------------------------------------------
/ajenti/plugins/megaraid/widget.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import plugin
2 | from ajenti.plugins.dashboard.api import ConfigurableWidget
3 |
4 | from api import RAIDManager
5 |
6 |
7 | @plugin
8 | class LSIWidget (ConfigurableWidget):
9 | name = 'LSI MegaRAID'
10 | icon = 'hdd'
11 |
12 | def on_prepare(self):
13 | self.mgr = RAIDManager.get()
14 | self.append(self.ui.inflate('megaraid:widget'))
15 |
16 | def on_start(self):
17 | self.mgr.refresh()
18 | self.find('variant').text = self.config['variant']
19 | arr = self.mgr.find_array(self.config['variant'])
20 | if arr:
21 | self.find('value').text = arr.state
22 |
23 | def create_config(self):
24 | return {'variant': ''}
25 |
26 | def on_config_start(self):
27 | self.mgr.refresh()
28 | lst = list(self.mgr.list_arrays())
29 | v_list = self.dialog.find('variant')
30 | v_list.labels = lst
31 | v_list.values = lst
32 | v_list.value = self.config['variant']
33 |
34 | def on_config_save(self):
35 | self.config['variant'] = self.dialog.find('variant').value
36 |
--------------------------------------------------------------------------------
/ajenti/plugins/configurator/layout/licensing.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/ajenti/plugins/main/controls_simple.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.ui import p, UIElement
3 |
4 |
5 | @p('text', default='', bindtypes=[str, unicode, int, float, long])
6 | @p('escape', type=bool, default=True)
7 | @plugin
8 | class Label (UIElement):
9 | typeid = 'label'
10 |
11 |
12 | @p('text', default='', bindtypes=[str, unicode, int, long])
13 | @plugin
14 | class Tooltip (UIElement):
15 | typeid = 'tooltip'
16 |
17 |
18 | @p('icon', default=None, bindtypes=[str, unicode])
19 | @plugin
20 | class Icon (UIElement):
21 | typeid = 'icon'
22 |
23 |
24 | @p('text', default='', bindtypes=[str, unicode])
25 | @p('icon', default=None)
26 | @p('warning', default=None)
27 | @plugin
28 | class Button (UIElement):
29 | typeid = 'button'
30 |
31 |
32 | @p('text', default='', bindtypes=[str, unicode])
33 | @p('icon', default=None)
34 | @p('pressed', default=False, type=bool)
35 | @plugin
36 | class ToggleButton (UIElement):
37 | typeid = 'togglebutton'
38 |
39 |
40 | @p('width', default=None)
41 | @p('value', default=0, type=float, bindtypes=[int, float, long])
42 | @plugin
43 | class ProgressBar (UIElement):
44 | typeid = 'progressbar'
45 |
--------------------------------------------------------------------------------
/ajenti/plugins/test/http/http.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import plugin, BasePlugin
2 | from ajenti.api.http import HttpPlugin, url
3 |
4 |
5 | @plugin
6 | class HttpDemo (BasePlugin, HttpPlugin):
7 | @url('/ajenti:demo/notify')
8 | def get_page(self, context):
9 | if context.session.identity is None:
10 | context.respond_redirect('/')
11 | self.context.notify('info', context.query.getvalue('text', ''))
12 | context.respond_ok()
13 | return ''
14 |
15 | @url('/ajenti:demo/respond/(?P.+)')
16 | def get_response(self, context, what=None):
17 | if what == 'ok':
18 | context.respond_ok()
19 | return 'Hello!'
20 | if what == 'redirect':
21 | return context.respond_redirect('/')
22 | if what == 'server_error':
23 | return context.respond_server_error()
24 | if what == 'forbidden':
25 | return context.respond_forbidden()
26 | if what == 'not_found':
27 | return context.respond_not_found()
28 | if what == 'file':
29 | return context.file('/etc/issue')
30 | if what == 'error':
31 | raise Exception('error!')
--------------------------------------------------------------------------------
/ajenti/plugins/git/layout/main-userlist.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/ajenti/plugins/resolv/main.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins.main.api import SectionPlugin
3 | from ajenti.ui import on
4 | from ajenti.ui.binder import Binder
5 |
6 | from reconfigure.configs import ResolvConfig
7 | from reconfigure.items.resolv import ItemData
8 |
9 |
10 | @plugin
11 | class Resolv (SectionPlugin):
12 | def init(self):
13 | self.title = _('Nameservers')
14 | self.icon = 'globe'
15 | self.category = _('System')
16 |
17 | self.append(self.ui.inflate('resolv:main'))
18 | self.find('name-box').labels = [_('DNS nameserver'), _('Local domain name'), _('Search list'), _('Sort list'), _('Options')]
19 | self.find('name-box').values = ['nameserver', 'domain', 'search', 'sortlist', 'options']
20 |
21 | self.config = ResolvConfig(path='/etc/resolv.conf')
22 | self.binder = Binder(None, self.find('resolv-config'))
23 | self.find('items').new_item = lambda c: ItemData()
24 |
25 | def on_page_load(self):
26 | self.config.load()
27 | self.binder.setup(self.config.tree).populate()
28 |
29 | @on('save', 'click')
30 | def save(self):
31 | self.binder.update()
32 | self.config.save()
33 |
--------------------------------------------------------------------------------
/ajenti/plugins/main/passwd.py:
--------------------------------------------------------------------------------
1 | import ajenti
2 | from ajenti.api import *
3 | from ajenti.plugins.main.api import SectionPlugin
4 | from ajenti.ui import on
5 | from ajenti.users import UserManager
6 |
7 |
8 | @plugin
9 | class PasswordChangeSection (SectionPlugin):
10 | def init(self):
11 | self.title = _('Password')
12 | self.icon = 'lock'
13 | self.category = ''
14 | self.order = 51
15 | self.append(self.ui.inflate('main:passwd-main'))
16 |
17 | @on('save', 'click')
18 | def save(self):
19 | new_password = self.find('new-password').value
20 | if new_password != self.find('new-password-2').value:
21 | self.context.notify('error', _('Passwords don\'t match'))
22 | return
23 | old_password = self.find('old-password').value
24 | if not UserManager.get().check_password(self.context.session.identity, old_password) or not new_password or not old_password:
25 | self.context.notify('error', _('Incorrect password'))
26 | return
27 | UserManager.get().set_password(self.context.session.identity, new_password)
28 | ajenti.config.save()
29 | self.context.notify('info', _('Password changed'))
30 |
--------------------------------------------------------------------------------
/ajenti/plugins/test/main.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins.main.api import SectionPlugin
3 | from ajenti.ui import on
4 | from ajenti.ui.binder import Binder
5 |
6 |
7 | class Phone (object):
8 | def __init__(self, number):
9 | self.number = number
10 |
11 |
12 | class Person (object):
13 | def __init__(self, name, phones):
14 | self.name = name
15 | self.phones = phones
16 |
17 |
18 | class AddressBook (object):
19 | def __init__(self, persons):
20 | self.persons = persons
21 |
22 |
23 | @plugin
24 | class Test (SectionPlugin):
25 | def init(self):
26 | self.title = 'Test'
27 | self.icon = 'question'
28 | self.category = 'Demo'
29 |
30 | self.append(self.ui.inflate('test:main'))
31 |
32 | alice = Person('Alice', [Phone('123')])
33 | bob = Person('Bob', [Phone('234'), Phone('345')])
34 | book = AddressBook([alice, bob])
35 |
36 | self.find('persons-collection').new_item = lambda c: Person('New person', [])
37 | self.find('phones-collection').new_item = lambda c: Phone('123')
38 |
39 | self.binder = Binder(None, self.find('addressbook'))
40 | self.binder.setup(book).populate()
41 |
--------------------------------------------------------------------------------
/ajenti-ipc:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import httplib
3 | import socket
4 | from urllib import quote
5 | import sys
6 |
7 |
8 | class UHTTPConnection (httplib.HTTPConnection):
9 | def __init__(self, path):
10 | httplib.HTTPConnection.__init__(self, 'localhost')
11 | self.path = path
12 |
13 | def connect(self):
14 | sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
15 | try:
16 | sock.connect(self.path)
17 | except socket.error as e:
18 | if e.errno == 13:
19 | sys.stderr.write('Permission denied\n')
20 | sys.exit(4)
21 | sys.stderr.write('Could not connect: %s\n' % e)
22 | sys.exit(3)
23 | self.sock = sock
24 |
25 |
26 | if len(sys.argv) < 2:
27 | print('Usage: ajenti-ipc [arguments]')
28 | sys.exit(1)
29 |
30 | url = sys.argv[1] + '/' + '\n'.join(sys.argv[2:]).encode('base64').strip()
31 | conn = UHTTPConnection('/var/run/ajenti-ipc.sock')
32 | conn.request(
33 | 'GET',
34 | quote(url),
35 | )
36 |
37 | resp = conn.getresponse()
38 | sys.stdout.write(resp.read())
39 |
40 | sys.stderr.write('%s %s\n' % (resp.status, resp.reason))
41 | sys.exit(0 if resp.status == 200 else 2)
42 |
--------------------------------------------------------------------------------
/ajenti/plugins/netatalk/main.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | from ajenti.api import *
4 | from ajenti.ui.binder import Binder
5 | from ajenti.plugins.main.api import SectionPlugin
6 | from ajenti.ui import on
7 |
8 | from reconfigure.configs import NetatalkConfig
9 | from reconfigure.items.netatalk import ShareData
10 |
11 |
12 | @plugin
13 | class Netatalk (SectionPlugin):
14 | config_path = '/etc/afp.conf'
15 |
16 | def init(self):
17 | self.title = 'Netatalk'
18 | self.icon = 'folder-close'
19 | self.category = _('Software')
20 | self.append(self.ui.inflate('netatalk:main'))
21 |
22 | if not os.path.exists(self.config_path):
23 | open(self.config_path, 'w').write("[Global]")
24 |
25 | self.binder = Binder(None, self.find('config'))
26 | self.find('shares').new_item = lambda c: ShareData()
27 | self.config = NetatalkConfig(path=self.config_path)
28 |
29 | def on_page_load(self):
30 | self.refresh()
31 |
32 | def refresh(self):
33 | self.config.load()
34 | self.binder.setup(self.config.tree).populate()
35 |
36 | @on('save', 'click')
37 | def on_save(self):
38 | self.binder.update()
39 | self.config.save()
40 | self.refresh()
41 |
--------------------------------------------------------------------------------
/ajenti/plugins/codemirror/content/js/controls.codearea.coffee:
--------------------------------------------------------------------------------
1 | class window.Controls.codearea extends window.Control
2 | createDom: () ->
3 | """
4 |
5 |
6 | """
7 |
8 | setupDom: (dom) ->
9 | super(dom)
10 | @cm = CodeMirror @dom,
11 | value: @properties.value
12 | mode: @properties.mode
13 | lineNumbers: true
14 | matchBrackets: true
15 | $(@dom).children().css(
16 | width: @_int_to_px(@properties.width)
17 | )
18 | $(@dom).find('.CodeMirror-scroll').css(
19 | height: @_int_to_px(@properties.height)
20 | )
21 | cm = @cm
22 | jQuery(@dom).find('.CodeMirror').resizable resize: () ->
23 | cm.setSize $(this).width(), $(this).height()
24 | cm.refresh()
25 |
26 | setTimeout @cm.refresh, 1
27 |
28 | onBroadcast: (msg) ->
29 | if msg == 'visible'
30 | setTimeout @cm.refresh, 1
31 |
32 | detectUpdates: () ->
33 | r = {}
34 | value = @cm.getValue()
35 | if value != @properties.value
36 | r.value = value
37 | return r
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/ajenti/plugins/exports/main.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | from ajenti.api import *
4 | from ajenti.plugins.main.api import SectionPlugin
5 | from ajenti.ui import on
6 | from ajenti.ui.binder import Binder
7 |
8 | from reconfigure.configs import ExportsConfig
9 | from reconfigure.items.exports import ExportData, ClientData
10 |
11 |
12 | @plugin
13 | class Exports (SectionPlugin):
14 | config_path = '/etc/exports'
15 |
16 | def init(self):
17 | self.title = _('NFS Exports')
18 | self.icon = 'hdd'
19 | self.category = _('Software')
20 | self.append(self.ui.inflate('exports:main'))
21 |
22 | if not os.path.exists(self.config_path):
23 | open(self.config_path, 'w').close()
24 |
25 | self.config = ExportsConfig(path=self.config_path)
26 | self.binder = Binder(None, self)
27 | self.find('exports').new_item = lambda c: ExportData()
28 | self.find('clients').new_item = lambda c: ClientData()
29 |
30 | def on_page_load(self):
31 | self.config.load()
32 | self.binder.setup(self.config.tree).populate()
33 |
34 | @on('save', 'click')
35 | def save(self):
36 | self.binder.update()
37 | self.config.save()
38 | self.context.notify('info', _('Saved'))
39 |
--------------------------------------------------------------------------------
/docs/source/_templates/page.html:
--------------------------------------------------------------------------------
1 | {% extends "!page.html" %}
2 |
3 | {#########################}
4 | {# for disqus commenting #}
5 | {#########################}
6 |
7 | {% macro comments() %}
8 |
9 |
10 |
21 |
22 | comments powered by
23 |
24 | {% endmacro %}
25 |
26 |
27 | {%- block body %}
28 | {{ super() }}
29 |
30 | {% if disqus_shortname %}
31 | {{ comments() }}
32 | {% endif %}
33 | {%- endblock %}
--------------------------------------------------------------------------------
/docs/source/dev/resources.rst:
--------------------------------------------------------------------------------
1 | .. _dev-resources:
2 |
3 | Plugin resources
4 | ****************
5 |
6 | Plugin resource files are contained under ``content`` directory nested in the plugin directory. The ``content`` directory can optionally contain ``css``, ``js`` and ``static`` directories holding files of respective types.
7 |
8 | Ajenti will accept following filename extensions. ``injected`` resources will be added to ```` of web UI. ``cleaned`` resources will be deleted before build. ``compile`` resources will be pre-processed using applicable compiler.
9 |
10 | * ``/content/js/*.js`` - source JS (compile)
11 | * ``/content/css/*.css`` - source JS (compile)
12 | * ``/content/js/*.coffee`` - source CoffeeScript (compile)
13 | * ``/content/css/*.less`` - source LESS (compile)
14 | * ``/content/css/*.i.less`` - source LESS included somewhere else (ignored)
15 | * ``/content/js/*.m.js`` - pre-built JS (injected)
16 | * ``/content/css/*.m.css`` - pre-built CSS (injected)
17 | * ``/content/js/*.c.js`` - compiled JS (injected, cleaned)
18 | * ``/content/css/*.c.css`` - compiled CSS (injected, cleaned)
19 |
20 | Resources under ``/static/`` are served over HTTP at the following URL: ``/ajenti:static//``, e.g.: ``/ajenti:static/main/favicon.png``.
--------------------------------------------------------------------------------
/ajenti/usersync/unix.py:
--------------------------------------------------------------------------------
1 | import ajenti
2 | from ajenti.api import *
3 |
4 | from reconfigure.items.ajenti import UserData
5 |
6 | from base import UserSyncProvider
7 | from pam import authenticate
8 |
9 |
10 |
11 | @plugin
12 | class UNIXSyncProvider (UserSyncProvider):
13 | id = 'unix'
14 | title = _('OS users')
15 | syncs_root = True
16 |
17 | def test(self):
18 | pass
19 |
20 | def check_password(self, username, password):
21 | return authenticate(username, password, 'passwd')
22 |
23 | def sync(self):
24 | found_names = []
25 | for l in open('/etc/shadow').read().splitlines():
26 | l = l.split(':')
27 | if len(l) >= 2:
28 | username, pwd = l[:2]
29 | if len(pwd) > 2:
30 | found_names.append(username)
31 | if not username in ajenti.config.tree.users:
32 | u = UserData()
33 | u.name = username
34 | ajenti.config.tree.users[username] = u
35 |
36 | for user in list(ajenti.config.tree.users.values()):
37 | if not user.name in found_names and user.name != 'root':
38 | ajenti.config.tree.users.pop(user.name)
39 |
40 | ajenti.config.save()
41 |
--------------------------------------------------------------------------------
/ajenti/plugins/samba/smbusers.py:
--------------------------------------------------------------------------------
1 | import subprocess
2 |
3 |
4 | class SambaUser (object):
5 | def __init__(self):
6 | self.username = None
7 | self.sid = None
8 |
9 |
10 | class SambaUsers (object):
11 | def load(self):
12 | self.users = []
13 | for un in [s.split(':')[0] for s in subprocess.check_output(['pdbedit', '-L', '-d0']).split('\n')]:
14 | if un and not ' ' in un and not un.startswith('WARNING'):
15 | lines = subprocess.check_output(['pdbedit', '-Lv', '-d0', '-u', un]).split('\n')
16 | fields = {}
17 | for l in lines:
18 | if l and ':' in l:
19 | l = l.split(':', 1)
20 | fields[l[0]] = l[1].strip()
21 | u = SambaUser()
22 | u.username = un
23 | u.sid = fields['User SID']
24 | self.users.append(u)
25 |
26 | def create(self, un):
27 | p = subprocess.Popen(['pdbedit', '-at', '-u', un])
28 | p.communicate('\n\n\n')
29 |
30 | def delete(self, un):
31 | subprocess.call(['pdbedit', '-x', '-u', un])
32 |
33 | def set_password(self, un, pw):
34 | p = subprocess.Popen(['pdbedit', '-at', '-u', un])
35 | p.communicate('%s\n%s\n' % (pw, pw))
36 | return p.returncode == 0
37 |
--------------------------------------------------------------------------------
/ajenti/profiler.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | _profiles = {}
4 | _profiles_running = {}
5 | _profiles_stack = []
6 |
7 |
8 | def profile_start(name):
9 | """
10 | Starts a profiling interval with specific ``name``
11 | Profiling data is sent to the client with next data batch.
12 | """
13 | _profiles_running[name] = time.time()
14 | _profiles_stack.append(name)
15 |
16 |
17 | def profile_end(name=None):
18 | """
19 | Ends a profiling interval with specific ``name``
20 | """
21 | last_name = _profiles_stack.pop()
22 | name = name or last_name
23 | if not name in _profiles:
24 | _profiles[name] = 0.0
25 | _profiles[name] += time.time() - _profiles_running[name]
26 |
27 |
28 | def get_profiles():
29 | """
30 | Returns all accumulated profiling values
31 | """
32 | global _profiles
33 | r = _profiles
34 | _profiles = {}
35 | return r
36 |
37 |
38 | def profiled(namefx=None):
39 | def decorator(fx):
40 | def wrapper(*args, **kwargs):
41 | if namefx:
42 | profile_start(namefx(args, kwargs))
43 | else:
44 | profile_start('%s %s %s' % (fx.__name__, args, kwargs))
45 | r = fx(*args, **kwargs)
46 | profile_end()
47 | return r
48 |
49 | return wrapper
50 | return decorator
51 |
--------------------------------------------------------------------------------
/ajenti/plugins/test/binder/main.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins.main.api import SectionPlugin
3 | from ajenti.ui import on
4 | from ajenti.ui.binder import Binder
5 |
6 |
7 | class Person (object):
8 | def __init__(self, name, phone):
9 | self.name = name
10 | self.phone = phone
11 |
12 | def __repr__(self):
13 | return '{%s: %s}' % (self.name, self.phone)
14 |
15 |
16 | @plugin
17 | class SimpleDemo (SectionPlugin):
18 | def init(self):
19 | self.title = 'Binder'
20 | self.icon = 'question'
21 | self.category = 'Demo'
22 |
23 | self.append(self.ui.inflate('test:binder-main'))
24 |
25 | self.data = [
26 | Person('Alice', '123'),
27 | Person('Bob', '234'),
28 | ]
29 |
30 | self.dict = {
31 | 'a': 1,
32 | 'b': 2,
33 | }
34 |
35 | self.find('data').text = repr(self.data)
36 |
37 | self.binder = Binder(self, self.find('bindroot'))
38 |
39 | @on('populate', 'click')
40 | def on_populate(self):
41 | self.binder.populate()
42 |
43 | @on('unpopulate', 'click')
44 | def on_unpopulate(self):
45 | self.binder.unpopulate()
46 |
47 | @on('update', 'click')
48 | def on_update(self):
49 | self.binder.update()
50 | self.find('data').text = repr(self.data)
--------------------------------------------------------------------------------
/ajenti/plugins/dhcpd/main.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins.main.api import SectionPlugin
3 | from ajenti.ui import on
4 | from ajenti.ui.binder import Binder
5 | from ajenti.util import platform_select
6 |
7 | from reconfigure.configs import DHCPDConfig
8 | from reconfigure.items.dhcpd import SubnetData, OptionData, RangeData
9 |
10 |
11 | @plugin
12 | class DHCPDPlugin (SectionPlugin):
13 | def init(self):
14 | self.title = _('DHCP Server')
15 | self.icon = 'sitemap'
16 | self.category = _('Software')
17 |
18 | self.append(self.ui.inflate('dhcpd:main'))
19 |
20 | self.config = DHCPDConfig(path=platform_select(
21 | default='/etc/dhcp/dhcpd.conf',
22 | arch='/etc/dhcpd.conf',
23 | ))
24 |
25 | self.binder = Binder(None, self)
26 |
27 | for x in self.nearest(lambda x: x.bind == 'ranges'):
28 | x.new_item = lambda c: RangeData()
29 | for x in self.nearest(lambda x: x.bind == 'options'):
30 | x.new_item = lambda c: OptionData()
31 | self.find('subnets').new_item = lambda c: SubnetData()
32 |
33 | def on_page_load(self):
34 | self.config.load()
35 | self.binder.setup(self.config.tree).populate()
36 |
37 | @on('save', 'click')
38 | def save(self):
39 | self.binder.update()
40 | self.config.save()
41 |
--------------------------------------------------------------------------------
/ajenti/plugins/uname/widget.py:
--------------------------------------------------------------------------------
1 | import subprocess
2 |
3 | from ajenti.api import plugin
4 | from ajenti.plugins.dashboard.api import DashboardWidget
5 | from ajenti.plugins.dashboard.api import ConfigurableWidget
6 |
7 |
8 | @plugin
9 | class MyUnameWidget(ConfigurableWidget):
10 | name = _('uname')
11 | icon = 'cog'
12 | options = 'asnrvmpio'
13 |
14 | def on_prepare(self):
15 | self.append(self.ui.inflate('uname:widget'))
16 |
17 | def on_start(self):
18 | args = ''
19 | if self.config['opt_a']:
20 | args += 'a'
21 | else:
22 | for o in self.options[1:]:
23 | if self.config['opt_%s' % o]:
24 | args += o
25 |
26 | if len(args):
27 | args = '-' + args
28 | self.find('value').text = subprocess.check_output(['uname', args])
29 |
30 | def create_config(self):
31 | options = {}
32 | for o in self.options:
33 | options['opt_%s'%o] = o in 'srm'
34 | return options
35 |
36 | def on_config_start(self):
37 | for o in self.options:
38 | opt = 'opt_%s' % o
39 | self.dialog.find(opt).value = self.config[opt]
40 |
41 | def on_config_save(self):
42 | for o in self.options:
43 | opt = 'opt_%s' % o
44 | self.config[opt] = self.dialog.find(opt).value
45 |
--------------------------------------------------------------------------------
/packaging/files/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "users": {
3 | "root": {
4 | "configs": {
5 | "ajenti.plugins.dashboard.dash.Dash": "{\"widgets\": [{\"index\": 0, \"config\": null, \"container\": \"1\", \"class\": \"ajenti.plugins.sensors.memory.MemoryWidget\"}, {\"index\": 1, \"config\": null, \"container\": \"1\", \"class\": \"ajenti.plugins.sensors.memory.SwapWidget\"}, {\"index\": 2, \"config\": null, \"container\": \"1\", \"class\": \"ajenti.plugins.dashboard.welcome.WelcomeWidget\"}, {\"index\": 0, \"config\": null, \"container\": \"0\", \"class\": \"ajenti.plugins.sensors.uptime.UptimeWidget\"}, {\"index\": 1, \"config\": null, \"container\": \"0\", \"class\": \"ajenti.plugins.power.power.PowerWidget\"}, {\"index\": 2, \"config\": null, \"container\": \"0\", \"class\": \"ajenti.plugins.sensors.cpu.CPUWidget\"}]}"
6 | },
7 | "password": "sha512|$6$rounds=40000$nIVrqqz638rB8wOo$VbMv8y2lStgcsYxEuu7JfHiEd06eeiSoIbg7Hvivj9K1vPayaCbAiAqtpyOoIkNfIXFmMD0jK6Dd4WFnvywkY1",
8 | "permissions": [
9 | ]
10 | }
11 | },
12 | "bind": {
13 | "host": "0.0.0.0",
14 | "port": 8000
15 | },
16 | "authentication": true,
17 | "ssl": {
18 | "enable": false,
19 | "certificate_path": ""
20 | },
21 | "enable_feedback": true,
22 | "installation_id": null
23 | }
24 |
--------------------------------------------------------------------------------
/ajenti/plugins/services/sm_osx.py:
--------------------------------------------------------------------------------
1 | import os
2 | import subprocess
3 |
4 | from ajenti.api import *
5 | from ajenti.util import cache_value
6 |
7 | from api import Service, ServiceManager
8 |
9 |
10 | @plugin
11 | class OSXServiceManager (ServiceManager):
12 | platforms = ['osx']
13 |
14 | @cache_value(1)
15 | def get_all(self):
16 | r = []
17 | for line in subprocess.check_output(['launchctl', 'list']).splitlines()[1:]:
18 | tokens = line.split()
19 | if len(tokens) == 3:
20 | s = OSXService(tokens[2])
21 | if s.name.startswith('com.apple'):
22 | continue
23 | if not '.anonymous.' in s.name:
24 | s.running = tokens[0] != '-'
25 | r.append(s)
26 | return r
27 |
28 |
29 | class OSXService (Service):
30 | source = 'launchd'
31 |
32 | def __init__(self, name):
33 | self.name = name
34 |
35 | def refresh(self):
36 | self.running = OSXServiceManager().get_one(self.name).running
37 |
38 | def start(self):
39 | self.command('start')
40 |
41 | def stop(self):
42 | self.command('stop')
43 |
44 | def restart(self):
45 | self.command('stop')
46 | self.command('start')
47 |
48 | def command(self, cmd):
49 | subprocess.call(['launchctl', cmd, self.name])
50 |
--------------------------------------------------------------------------------
/docs/source/index.rst:
--------------------------------------------------------------------------------
1 | Ajenti documentation
2 | ====================
3 |
4 | Documentation
5 | -------------
6 |
7 | .. toctree::
8 |
9 | man/faq.rst
10 | man/install.rst
11 | man/run.rst
12 |
13 |
14 | Developers
15 | ----------
16 |
17 | .. toctree::
18 |
19 | dev/intro.rst
20 | dev/ui.rst
21 | dev/resources.rst
22 | dev/notifications.rst
23 | dev/binding.rst
24 | dev/custom-controls.rst
25 | dev/http.rst
26 | dev/dash-widgets.rst
27 |
28 |
29 | API Reference
30 | -------------
31 |
32 | .. toctree::
33 | ref/ajenti
34 | ref/ajenti.api
35 | ref/ajenti.api.http
36 | ref/ajenti.api.sensors
37 | ref/ajenti.http
38 | ref/ajenti.ipc
39 | ref/ajenti.middleware
40 | ref/ajenti.plugins
41 | ref/ajenti.profiler
42 | ref/ajenti.ui
43 | ref/ajenti.ui.binder
44 | ref/ajenti.users
45 | ref/ajenti.util
46 |
47 |
48 | Plugin API Reference
49 | --------------------
50 |
51 | .. toctree::
52 | ref/ajenti.plugins.main.api
53 | ref/ajenti.plugins.dashboard.api
54 | ref/ajenti.plugins.configurator.api
55 | ref/ajenti.plugins.db_common.api
56 | ref/ajenti.plugins.webserver_common.api
57 | ref/ajenti.plugins.packages.api
58 | ref/ajenti.plugins.services.api
59 | ref/ajenti.plugins.tasks.api
60 |
61 |
62 | Indices and tables
63 | ==================
64 |
65 | * :ref:`genindex`
66 | * :ref:`modindex`
67 | * :ref:`search`
68 |
--------------------------------------------------------------------------------
/docs/source/dev/notifications.rst:
--------------------------------------------------------------------------------
1 | .. _dev-notifications:
2 |
3 | Notifications
4 | *************
5 |
6 | Example
7 | =======
8 |
9 | Code::
10 |
11 | from ajenti.api import plugin
12 | from ajenti.plugins.main.api import SectionPlugin
13 | from ajenti.ui import on
14 |
15 |
16 | @plugin
17 | class Test (SectionPlugin):
18 | def init(self):
19 | self.title = 'Notifications'
20 | self.icon = 'smile'
21 | self.category = 'Demo'
22 |
23 | self.append(self.ui.inflate('test_notifications:main'))
24 | self.find('style').labels = self.find('style').values = ['info', 'warning', 'error']
25 |
26 | @on('show', 'click')
27 | def on_show(self):
28 | self.context.notify(self.find('style').value, self.find('text').value)
29 |
30 | Layout::
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | `Download this example `_
49 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | from distutils.core import setup
4 | from setuptools import find_packages
5 | import os
6 |
7 | import ajenti
8 |
9 | __requires = filter(None, open('requirements.txt').read().splitlines())
10 |
11 | exclusion = [
12 | 'ajenti.plugins.elements',
13 | 'ajenti.plugins.ltfs',
14 | 'ajenti.plugins.ltfs*',
15 | 'ajenti.plugins.vh',
16 | 'ajenti.plugins.vh*',
17 | 'ajenti.plugins.custom*',
18 | 'ajenti.plugins.test*',
19 | ]
20 |
21 |
22 | on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
23 |
24 | if not on_rtd:
25 | data_files=[
26 | ('/etc/ajenti', ['packaging/files/config.json']),
27 | ('/etc/init.d', ['packaging/files/ajenti']),
28 | ('/var/lib/ajenti/plugins', ['packaging/files/.placeholder']),
29 | ]
30 | else:
31 | data_files = []
32 |
33 |
34 | setup(
35 | name='ajenti',
36 | version=ajenti.__version__,
37 | install_requires=__requires,
38 | description='The server administration panel',
39 | author='Eugeny Pankov',
40 | author_email='e@ajenti.org',
41 | url='http://ajenti.org/',
42 | packages=find_packages(exclude=['reconfigure', 'reconfigure.*'] + exclusion),
43 | package_data={'': ['content/*.*', 'content/*/*.*', 'content/*/*/*.*', 'layout/*.*', 'locales/*/*/*.mo']},
44 | scripts=['ajenti-panel', 'ajenti-ssl-gen', 'ajenti-ipc'],
45 | data_files=data_files,
46 | )
47 |
--------------------------------------------------------------------------------
/ajenti/plugins/memcache/widget.py:
--------------------------------------------------------------------------------
1 | import os
2 | import socket
3 |
4 | from ajenti.api import plugin
5 | from ajenti.api.sensors import Sensor
6 | from ajenti.plugins.dashboard.api import DashboardWidget
7 | from ajenti.util import str_fsize
8 |
9 |
10 | @plugin
11 | class MemcacheSensor (Sensor):
12 | id = 'memcache'
13 | timeout = 5
14 |
15 | def measure(self, variant=None):
16 | sock_path = '/var/run/memcached.sock'
17 | if os.path.exists(sock_path):
18 | s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
19 | s.connect(sock_path)
20 | else:
21 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
22 | s.connect(('127.0.0.1', 11211))
23 | s.send('stats\r\n')
24 | data = s.recv(10240)
25 | s.close()
26 | d = dict([
27 | l.split()[1:]
28 | for l in data.splitlines() if len(l.split()) == 3
29 | ])
30 | return (int(d['bytes']), int(d['limit_maxbytes']))
31 |
32 |
33 | @plugin
34 | class MemcachedWidget (DashboardWidget):
35 | name = _('Memcache memory usage')
36 | icon = 'tasks'
37 |
38 | def init(self):
39 | self.sensor = Sensor.find('memcache')
40 | self.append(self.ui.inflate('memcache:widget'))
41 | value = self.sensor.value()
42 | self.find('value').text = str_fsize(value[0])
43 | self.find('progress').value = 1.0 * value[0] / value[1]
44 |
--------------------------------------------------------------------------------
/ajenti/plugins/sensors/load.py:
--------------------------------------------------------------------------------
1 | import subprocess
2 |
3 | from ajenti.api import plugin
4 | from ajenti.api.sensors import Sensor
5 | from ajenti.plugins.dashboard.api import DashboardWidget
6 |
7 |
8 | class BaseLoadSensor (Sensor):
9 | id = 'load'
10 | timeout = 1
11 |
12 | def get_variants(self):
13 | return ['1 min', '5 min', '15 min']
14 |
15 |
16 | @plugin
17 | class LinuxLoadSensor (BaseLoadSensor):
18 | platforms = ['debian', 'centos', 'arch', 'mageia']
19 |
20 | def measure(self, variant):
21 | idx = self.get_variants().index(variant)
22 | return float(open('/proc/loadavg').read().split()[idx])
23 |
24 |
25 | @plugin
26 | class BSDLoadSensor (BaseLoadSensor):
27 | platforms = ['freebsd', 'osx']
28 |
29 | def measure(self, variant):
30 | idx = self.get_variants().index(variant)
31 | tokens = subprocess.check_output(['uptime']).split()
32 | loads = [float(x.strip(',')) for x in tokens[-3:]]
33 | return loads[idx]
34 |
35 |
36 | @plugin
37 | class LoadWidget (DashboardWidget):
38 | name = _('Load average')
39 | icon = 'signal'
40 |
41 | def init(self):
42 | self.sensor = Sensor.find('load')
43 | self.append(self.ui.inflate('sensors:value-widget'))
44 | self.find('icon').icon = 'signal'
45 | self.find('name').text = _('Load average')
46 | self.find('value').text = ' / '.join(str(self.sensor.value(x)) for x in self.sensor.get_variants())
47 |
--------------------------------------------------------------------------------
/ajenti/plugins/services/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/ajenti/plugins/git/layout/main-repolist.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/ajenti/plugins/mysql/main.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins.db_common.api import DBPlugin
3 | from ajenti.util import platform_select
4 |
5 | from api import MySQLDB
6 |
7 |
8 | @plugin
9 | class MySQLPlugin (DBPlugin):
10 | config_class = MySQLDB
11 |
12 | service_name = platform_select(
13 | debian='mysql',
14 | osx='org.macports.mysql56-server',
15 | default='mysqld',
16 | )
17 |
18 | service_buttons = [
19 | {
20 | 'command': 'reload',
21 | 'text': _('Reload'),
22 | 'icon': 'reload',
23 | }
24 | ]
25 |
26 | def init(self):
27 | self.title = 'MySQL'
28 | self.category = _('Software')
29 | self.icon = 'table'
30 | self.db = MySQLDB.get()
31 |
32 | def query_sql(self, db, sql):
33 | return self.db.query_sql(db, sql)
34 |
35 | def query_databases(self):
36 | return self.db.query_databases()
37 |
38 | def query_drop(self, db):
39 | return self.db.query_drop(db)
40 |
41 | def query_create(self, name):
42 | return self.db.query_create(name)
43 |
44 | def query_users(self):
45 | return self.db.query_users()
46 |
47 | def query_create_user(self, user):
48 | return self.db.query_create_user(user)
49 |
50 | def query_drop_user(self, user):
51 | return self.db.query_drop_user(user)
52 |
53 | def query_grant(self, user, db):
54 | return self.db.query_grant(user, db)
55 |
--------------------------------------------------------------------------------
/ajenti/plugins/services/sm_freebsd.py:
--------------------------------------------------------------------------------
1 | import os
2 | import subprocess
3 |
4 | from ajenti.api import *
5 | from ajenti.util import cache_value
6 |
7 | from api import Service, ServiceManager
8 |
9 |
10 | @plugin
11 | class FreeBSDServiceManager (ServiceManager):
12 | platforms = ['freebsd']
13 |
14 | @cache_value(1)
15 | def get_all(self):
16 | r = []
17 | dirs = ['/etc/rc.d', '/usr/local/etc/rc.d']
18 | for line in subprocess.check_output(['service', '-l']).splitlines():
19 | if line:
20 | for d in dirs:
21 | if os.path.exists(os.path.join(d, line)):
22 | s = FreeBSDService(line, d)
23 | try:
24 | s.refresh()
25 | r.append(s)
26 | except OSError:
27 | pass
28 | return r
29 |
30 |
31 | class FreeBSDService (Service):
32 | source = 'rc.d'
33 |
34 | def __init__(self, name, dir):
35 | self.name = name
36 | self.script = os.path.join(dir, self.name)
37 |
38 | def refresh(self):
39 | self.running = subprocess.call([self.script, 'status']) == 0
40 |
41 | def start(self):
42 | self.command('start')
43 |
44 | def stop(self):
45 | self.command('stop')
46 |
47 | def restart(self):
48 | self.command('restart')
49 |
50 | def command(self, cmd):
51 | subprocess.call([self.script, cmd])
52 |
--------------------------------------------------------------------------------
/ajenti/plugins/test/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/ajenti/plugins/resolv/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/ajenti/plugins/main/api.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.ui import *
3 |
4 |
5 | @p('title')
6 | @p('icon', default=None)
7 | @p('order', default=99, doc='Sorting weight, light plugins end up higher')
8 | @p('category', default='Other', doc='Section category name')
9 | @p('active', default=False)
10 | @p('clsname', default='')
11 | @p('hidden', default=False)
12 | @track
13 | @interface
14 | class SectionPlugin (BasePlugin, UIElement):
15 | """
16 | A base class for section plugins visible on the left in the UI. Inherits :class:`ajenti.ui.UIElement`
17 | """
18 |
19 | typeid = 'main:section'
20 | hidden = False
21 |
22 | def init(self):
23 | self._first_page_load = True
24 | self._intents = {}
25 | for k, v in self.__class__.__dict__.iteritems():
26 | if hasattr(v, '_intent'):
27 | self._intents[v._intent] = getattr(self, k)
28 |
29 | def activate(self):
30 | """
31 | Activate this section
32 | """
33 | self.context.endpoint.switch_tab(self)
34 |
35 | def on_first_page_load(self):
36 | """
37 | Called before first ``on_page_load``
38 | """
39 |
40 | def on_page_load(self):
41 | """
42 | Called when this section becomes active, or the page is reloaded
43 | """
44 |
45 |
46 | def intent(id):
47 | """
48 | Registers this method as an intent with given ID
49 | """
50 | def decorator(fx):
51 | fx._intent = id
52 | return fx
53 | return decorator
54 |
--------------------------------------------------------------------------------
/ajenti/plugins/supervisor/main.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.ui.binder import Binder
3 | from ajenti.plugins.main.api import SectionPlugin
4 | from ajenti.ui import on
5 | from ajenti.util import platform_select
6 |
7 | from reconfigure.configs import SupervisorConfig
8 | from reconfigure.items.supervisor import ProgramData
9 |
10 | from client import SupervisorServiceManager
11 |
12 |
13 | @plugin
14 | class Supervisor (SectionPlugin):
15 | def init(self):
16 | self.title = 'Supervisor'
17 | self.icon = 'play'
18 | self.category = _('Software')
19 | self.append(self.ui.inflate('supervisor:main'))
20 | self.mgr = SupervisorServiceManager.get()
21 | self.binder = Binder(None, self.find('main'))
22 | self.find('programs').new_item = lambda c: ProgramData()
23 | self.config = SupervisorConfig(path=platform_select(
24 | default='/etc/supervisor/supervisord.conf',
25 | centos='/etc/supervisord.conf',
26 | ))
27 | self.find('servicebar').name = platform_select(
28 | centos='supervisord',
29 | default='supervisor',
30 | )
31 | self.find('servicebar').reload()
32 |
33 | def on_page_load(self):
34 | self.refresh()
35 |
36 | def refresh(self):
37 | self.config.load()
38 | self.mgr.fill(self.config.tree.programs)
39 | self.binder.setup(self.config.tree).populate()
40 |
41 | @on('save', 'click')
42 | def on_save(self):
43 | self.binder.update()
44 | self.config.save()
45 | self.refresh()
46 |
--------------------------------------------------------------------------------
/ajenti/plugins/plugins/plugins.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.plugins import manager, ModuleDependency, BinaryDependency
3 | from ajenti.plugins.main.api import SectionPlugin
4 | from ajenti.ui.binder import Binder
5 |
6 |
7 | @plugin
8 | class PluginsPlugin (SectionPlugin):
9 | def init(self):
10 | self.title = _('Plugins')
11 | self.icon = 'cogs'
12 | self.category = ''
13 | self.order = 60
14 |
15 | # In case you didn't notice it yet, this is the Plugins Plugin Plugin
16 | self.append(self.ui.inflate('plugins:main'))
17 |
18 | def post_plugin_bind(object, collection, item, ui):
19 | if not item.crash:
20 | ui.find('crash').visible = False
21 |
22 | def post_dep_bind(object, collection, item, ui):
23 | if not item.satisfied():
24 | installer = ui.find('fix')
25 | if item.__class__ == ModuleDependency:
26 | installer.package = 'python-module-' + item.module_name
27 | if item.__class__ == BinaryDependency:
28 | installer.package = item.binary_name
29 | installer.recheck()
30 |
31 | self.find('plugins').post_item_bind = post_plugin_bind
32 | self.find('dependencies').post_item_bind = post_dep_bind
33 |
34 | self.binder = Binder(None, self.find('bind-root'))
35 |
36 | def on_page_load(self):
37 | self.context.endpoint.send_progress(_('Gathering plugin list'))
38 | self.plugins = sorted(manager.get_all().values())
39 | self.binder.setup(self).populate()
40 |
--------------------------------------------------------------------------------
/ajenti/plugins/test/layout/binder-main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Ajenti
2 | ======
3 |
4 | [](https://crowdin.net/project/ajenti)
5 |
6 | http://ajenti.org/
7 |
8 | Ajenti is a Linux & BSD web admin panel.
9 |
10 | 
11 |
12 | 
13 |
14 | 
15 |
16 | Feature highlights
17 | ==================
18 |
19 | Easy installation
20 | -----------------
21 |
22 | Ajenti is installed through your system's package manager. Installation only takes a minute.
23 |
24 | Existing configuration
25 | ----------------------
26 |
27 | Picks up your current configuration and works on your existing system as-is, without any preparation.
28 |
29 | Caring
30 | ------
31 |
32 | Does not overwrite your config files, options and comments. All changes are non-destructive.
33 |
34 | Batteries included
35 | ------------------
36 |
37 | Includes lots of plugins for system and software configuration, monitoring and management.
38 |
39 | Extensible
40 | ----------
41 |
42 | Ajenti is easily extensible using Python. Plugin development is a quick and pleasant with Ajenti APIs.
43 |
44 | Modern
45 | ------
46 |
47 | Pleasant to look at, satisfying to click and accessible anywhere from tablets and mobile.
48 |
49 | Lightweight
50 | -----------
51 |
52 | Small memory footprint and CPU usage. Runs on low-end machines, wall plugs, routers and so on.
53 |
54 | Listening
55 | ---------
56 |
57 | We listen to your feedback and add features in the fast-paces weekly release cycle.
58 |
59 |
60 | See http://ajenti.org for more information
61 |
--------------------------------------------------------------------------------
/ajenti/plugins/fstab/widget.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import plugin
2 | from ajenti.api.sensors import Sensor
3 | from ajenti.plugins.dashboard.api import ConfigurableWidget
4 | from ajenti.util import str_fsize
5 |
6 |
7 | @plugin
8 | class DiskSpaceWidget (ConfigurableWidget):
9 | name = _('Disk space')
10 | icon = 'hdd'
11 |
12 | def on_prepare(self):
13 | self.sensor = Sensor.find('disk-usage')
14 | self.append(self.ui.inflate('fstab:widget'))
15 |
16 | def on_start(self):
17 | self.find('device').text = self.config['device']
18 | u, f, t = self.sensor.value(self.config['device'])
19 | self.find('percent').text = str_fsize(u)
20 | self.find('usage').value = float(1.0 * u / t)
21 |
22 | def create_config(self):
23 | return {'device': ''}
24 |
25 | def on_config_start(self):
26 | device_list = self.dialog.find('device')
27 | lst = self.sensor.get_variants()
28 | device_list.labels = lst
29 | device_list.values = lst
30 | device_list.value = self.config['device']
31 |
32 | def on_config_save(self):
33 | self.config['device'] = self.dialog.find('device').value
34 |
35 |
36 | @plugin
37 | class DiskFreeSpaceWidget (DiskSpaceWidget):
38 | name = _('Free disk space')
39 | icon = 'hdd'
40 |
41 | def on_prepare(self):
42 | self.sensor = Sensor.find('disk-usage')
43 | self.append(self.ui.inflate('fstab:free-widget'))
44 |
45 | def on_start(self):
46 | self.find('device').text = self.config['device']
47 | u, f, t = self.sensor.value(self.config['device'])
48 | self.find('value').text = _('%s free') % str_fsize(f)
49 |
--------------------------------------------------------------------------------
/ajenti-ssl-gen:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 | import json
5 | import subprocess
6 |
7 | if len(sys.argv) < 2:
8 | print('Usage: ajenti-ssl-gen [-f]')
9 | sys.exit(1)
10 |
11 | host = sys.argv[1]
12 | path = '/etc/ajenti'
13 | config_path = '/etc/ajenti/config.json'
14 | marker_path = '/etc/ajenti/.ssl-generated'
15 |
16 |
17 | conf = json.loads(open(config_path).read())
18 | if len(sys.argv) == 2:
19 | if os.path.exists(marker_path):
20 | print(':: SSL is already configured')
21 | sys.exit(1)
22 |
23 |
24 | script = """
25 | echo '\n:: Generating key\n';
26 | openssl genrsa -des3 -out /tmp/ajenti.key -passout pass:1234 2048;
27 | echo '\n:: Generating certificate request\n';
28 | openssl req -new -key /tmp/ajenti.key -out /tmp/ajenti.csr -passin pass:1234 -subj /C=US/ST=NA/L=Nowhere/O=Acme\\ Inc/OU=IT/CN={0}/;
29 | echo '\n:: Removing passphrase\n';
30 | cp /tmp/ajenti.key /tmp/ajenti.key.org;
31 | openssl rsa -in /tmp/ajenti.key.org -out /tmp/ajenti.key -passin pass:1234;
32 | echo '\n:: Generating certificate\n';
33 | openssl x509 -req -days 365 -in /tmp/ajenti.csr -signkey /tmp/ajenti.key -out /tmp/ajenti.crt -passin pass:1234;
34 | cat /tmp/ajenti.key /tmp/ajenti.crt > {1}/ajenti.pem;
35 | rm /tmp/ajenti.*;
36 | """.format(host, path)
37 |
38 | subprocess.call(script, shell=True)
39 |
40 | conf['ssl']['enable'] = True
41 | certificate_path = os.path.join(path, 'ajenti.pem')
42 | conf['ssl']['certificate_path'] = certificate_path
43 | os.chmod(certificate_path, 0400)
44 | open(config_path, 'w').write(json.dumps(conf, indent=4))
45 |
46 | open(marker_path, 'w').close()
47 |
48 | print(':: SSL configured!')
49 |
--------------------------------------------------------------------------------
/ajenti/plugins/squid/main.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.ui.binder import Binder
3 | from ajenti.plugins.main.api import SectionPlugin
4 | from ajenti.ui import on
5 | from ajenti.util import platform_select
6 |
7 | from reconfigure.configs import SquidConfig
8 | from reconfigure.items.squid import ACLData, HTTPAccessData, HTTPPortData, HTTPSPortData, ArgumentData
9 |
10 |
11 | @plugin
12 | class Squid (SectionPlugin):
13 | def init(self):
14 | self.title = 'Squid'
15 | self.icon = 'exchange'
16 | self.category = _('Software')
17 | self.append(self.ui.inflate('squid:main'))
18 |
19 | self.find('servicebar').name = platform_select(
20 | debian='squid3',
21 | centos='squid',
22 | default='squid',
23 | )
24 | self.find('servicebar').reload()
25 |
26 | self.binder = Binder(None, self.find('config'))
27 | self.find('acl').new_item = lambda c: ACLData(name='new')
28 | self.find('http_access').new_item = lambda c: HTTPAccessData()
29 | self.find('http_port').new_item = lambda c: HTTPPortData()
30 | self.find('https_port').new_item = lambda c: HTTPSPortData()
31 | for e in self.nearest(lambda x: x.id == 'options'):
32 | e.new_item = lambda c: ArgumentData()
33 | self.config = SquidConfig(path='/etc/squid3/squid.conf')
34 |
35 | def on_page_load(self):
36 | self.refresh()
37 |
38 | def refresh(self):
39 | self.config.load()
40 | self.binder.setup(self.config.tree).populate()
41 |
42 | @on('save', 'click')
43 | def on_save(self):
44 | self.binder.update()
45 | self.config.save()
46 | self.refresh()
47 |
--------------------------------------------------------------------------------
/ajenti/plugins/network/api.py:
--------------------------------------------------------------------------------
1 | import psutil
2 |
3 | from ajenti.api import *
4 | from ajenti.ui import *
5 |
6 |
7 | @plugin
8 | class NetworkManager (BasePlugin):
9 | def get_devices(self):
10 | return psutil.net_io_counters(pernic=True).keys()
11 |
12 |
13 | @interface
14 | class INetworkConfig (object):
15 | interfaces = {}
16 |
17 | @property
18 | def interface_list(self):
19 | return self.interfaces.values()
20 |
21 | def rescan(self):
22 | pass
23 |
24 | def save(self):
25 | pass
26 |
27 |
28 | @interface
29 | class INetworkConfigBit (object):
30 | def apply(self):
31 | pass
32 |
33 |
34 | @plugin
35 | class NetworkConfigBit (UIElement, INetworkConfigBit):
36 | cls = 'unknown'
37 | iface = None
38 | title = 'Unknown'
39 | typeid = 'box'
40 |
41 |
42 | class NetworkInterface(object):
43 | def __init__(self):
44 | self.up = False
45 | self.auto = False
46 | self.name = ''
47 | self.devclass = ''
48 | self.addressing = 'static'
49 | self.bits = []
50 | self.params = {'address': '0.0.0.0'}
51 | self.type = ''
52 | self.editable = True
53 |
54 | def __getitem__(self, idx):
55 | if idx in self.params:
56 | return self.params[idx]
57 | else:
58 | return ''
59 |
60 | def __setitem__(self, idx, val):
61 | self.params[idx] = val
62 |
63 | def add_bits(self, ui):
64 | for cls in INetworkConfigBit.get_classes():
65 | if cls.cls in self.bit_classes:
66 | b = cls.new(ui)
67 | b.iface = self
68 | b.refresh()
69 | self.bits.append(b)
70 |
--------------------------------------------------------------------------------
/ajenti/plugins/services/widget.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import plugin
2 | from ajenti.plugins.dashboard.api import ConfigurableWidget
3 | from ajenti.ui import on
4 |
5 | from api import ServiceMultiplexor
6 |
7 |
8 | @plugin
9 | class ServiceWidget (ConfigurableWidget):
10 | name = _('Service')
11 | icon = 'play'
12 |
13 | def on_prepare(self):
14 | self.mgr = ServiceMultiplexor.get()
15 | self.append(self.ui.inflate('services:widget'))
16 |
17 | def on_start(self):
18 | self.service = self.mgr.get_one(self.config['service'])
19 | if not self.service:
20 | return
21 | self.find('name').text = self.service.name
22 | self.find('icon').icon = self.service.icon
23 | self.find('start').visible = not self.service.running
24 | self.find('stop').visible = self.service.running
25 | self.find('restart').visible = self.service.running
26 |
27 | def create_config(self):
28 | return {'service': ''}
29 |
30 | def on_config_start(self):
31 | service_list = self.dialog.find('service')
32 | service_list.labels = service_list.values = [x.name for x in self.mgr.get_all()]
33 | service_list.value = self.config['service']
34 |
35 | def on_config_save(self):
36 | self.config['service'] = self.dialog.find('service').value
37 |
38 | @on('start', 'click')
39 | def on_s_start(self):
40 | self.service.start()
41 | self.on_start()
42 |
43 | @on('restart', 'click')
44 | def on_s_restart(self):
45 | self.service.restart()
46 | self.on_start()
47 |
48 | @on('stop', 'click')
49 | def on_s_stop(self):
50 | self.service.stop()
51 | self.on_start()
52 |
--------------------------------------------------------------------------------
/ajenti/plugins/services/api.py:
--------------------------------------------------------------------------------
1 | from ajenti.api import *
2 | from ajenti.util import cache_value
3 |
4 |
5 | @plugin
6 | @persistent
7 | class ServiceMultiplexor (object):
8 | """
9 | Merges together output of all available ServiceManagers.
10 | """
11 | def init(self):
12 | self.managers = ServiceManager.get_all()
13 |
14 | @cache_value(1)
15 | def get_all(self):
16 | """
17 | Returns all :class:`Service` s.
18 | """
19 | r = []
20 | for mgr in self.managers:
21 | r += mgr.get_all()
22 | return r
23 |
24 | def get_one(self, name):
25 | """
26 | Returns a :class:`Service` by name.
27 | """
28 | for mgr in self.managers:
29 | s = mgr.get_one(name)
30 | if s:
31 | return s
32 | return None
33 |
34 |
35 | @interface
36 | @persistent
37 | class ServiceManager (object):
38 | def get_all(self):
39 | return []
40 |
41 | def get_one(self, name):
42 | """
43 | Returns a :class:`Service` by name.
44 | """
45 | for s in self.get_all():
46 | if s.name == name:
47 | return s
48 | return None
49 |
50 |
51 | class Service (object):
52 | source = 'unknown'
53 | """ Marks which ServiceManager owns this object """
54 |
55 | def __init__(self):
56 | self.name = None
57 | self.running = False
58 |
59 | @property
60 | def icon(self):
61 | return 'play' if self.running else None
62 |
63 | def start(self):
64 | pass
65 |
66 | def stop(self):
67 | pass
68 |
69 | def restart(self):
70 | pass
71 |
72 | def command(self, cmd):
73 | pass
74 |
--------------------------------------------------------------------------------
/ajenti/feedback.py:
--------------------------------------------------------------------------------
1 | """
2 | Module for sending usage statistics to ajenti.org
3 | """
4 |
5 | import ajenti
6 | import requests
7 | import json
8 | import gevent
9 | import logging
10 |
11 | from ajenti.util import *
12 |
13 |
14 | HOST = 'meta.ajenti.org'
15 | URL = 'http://%s/api/v2/' % HOST
16 |
17 |
18 | enabled = True
19 |
20 |
21 | @public
22 | def start():
23 | gevent.spawn(worker)
24 |
25 |
26 | def send(url, data):
27 | id = ajenti.config.tree.installation_id
28 | if id:
29 | data['id'] = id
30 | logging.debug('Feedback >> %s (%s)' % (url, data))
31 | try:
32 | response = requests.post(URL + url, data=data)
33 | except:
34 | raise IOError()
35 | logging.debug('Feedback << %s' % response.content)
36 | return json.loads(response.content)
37 |
38 |
39 | def worker():
40 | global enabled
41 | enabled = ajenti.config.tree.enable_feedback
42 | if enabled:
43 | data = {
44 | 'version': ajenti.version,
45 | 'os': ajenti.platform,
46 | 'edition': ajenti.edition,
47 | }
48 | if not ajenti.config.tree.installation_id:
49 | logging.debug('Registering installation')
50 | enabled = False
51 | try:
52 | resp = send('register', data)
53 | if resp['status'] != 'ok':
54 | return
55 | except IOError:
56 | pass
57 | ajenti.config.tree.installation_id = resp['id']
58 | ajenti.config.save()
59 | enabled = True
60 |
61 | while True:
62 | try:
63 | send('ping', data)
64 | except IOError:
65 | pass
66 | gevent.sleep(3600 * 12)
67 |
--------------------------------------------------------------------------------