def init(self): self.title = _('Configure') self.icon = 'wrench' self.category = '' self.order = 50 self.append(self.ui.inflate('configurator:main')) self.binder = Binder(ajenti.config.tree, self.find('ajenti-config')) self.ccmgr = ClassConfigManager.get() self.classconfig_binding = Binder(self.ccmgr, self.find('classconfigs')) self.classconfig_rows = {} def post_classconfig_bind(object, collection, item, ui): self.classconfig_rows[item] = ui editor = item.classconfig_editor.new(self.ui) ui.find('container').append(editor) binder = DictAutoBinding(item, 'classconfig', editor.find('bind')) binder.populate() def save(): binder.update() item.save_classconfig() self.context.notify('info', _('Saved')) ui.find('save').on('click', save) self.find('classconfigs').find('classes').post_item_bind = post_classconfig_bind self.find('users').new_item = lambda c: UserData() def post_user_bind(object, collection, item, ui): box = ui.find('permissions') box.empty() ui.find('name-edit').visible = item.name != 'root' ui.find('name-label').visible = item.name == 'root' for prov in PermissionProvider.get_all(): line = self.ui.create('tab', title=prov.get_name()) box.append(line) for perm in prov.get_permissions(): line.append( self.ui.create('checkbox', id=perm[0], text=perm[1], value=(perm[0] in item.permissions)) ) self.find('users').post_item_bind = post_user_bind def post_user_update(object, collection, item, ui): box = ui.find('permissions') for prov in PermissionProvider.get_all(): for perm in prov.get_permissions(): has = box.find(perm[0]).value if has and not perm[0] in item.permissions: item.permissions.append(perm[0]) if not has and perm[0] in item.permissions: item.permissions.remove(perm[0]) if ui.find('password').value: item.password = ui.find('password').value self.find('users').post_item_update = post_user_update self.refresh()
class TestPlugin (SectionPlugin): def init(self): self.title = 'GeT3' # those are not class attributes and can be only set in or after init() self.icon = 'question' self.category = 'Software' """ UI Inflater searches for the named XML layout and inflates it into an UIElement object tree """ settings = filter(lambda x: '_settings.py' in x , os.listdir("/home/django/get3/GeT3/settings/")) self.instances = [GetIstance(a) for a in settings] self.append(self.ui.inflate('ajenti_get:main')) self.binder = Binder(self, self.find('bindroot')) self.refresh() self.binder.populate() def refresh(self): """ Changing element properties automatically results in an UI updated being issued to client """ #self.find('counter-label').text = 'Counter: %i' % self.counter #@on('increment-button', 'click') #def on_button(self): """ This method is called every time a child element with ID 'increment-button' fires a 'click' event """ #self.counter += 1 #self.refresh()
class Supervisor (SectionPlugin): def init(self): self.title = 'Supervisor' self.icon = 'play' self.category = _('Software') self.append(self.ui.inflate('supervisor:main')) self.mgr = SupervisorServiceManager.get() self.binder = Binder(None, self.find('main')) self.find('programs').new_item = lambda c: ProgramData() self.config = SupervisorConfig(path=platform_select( default='/etc/supervisor/supervisord.conf', centos='/etc/supervisord.conf', )) self.find('servicebar').name = platform_select( centos='supervisord', default='supervisor', ) self.find('servicebar').reload() def on_page_load(self): self.refresh() def refresh(self): self.config.load() self.mgr.fill(self.config.tree.programs) self.binder.setup(self.config.tree).populate() @on('save', 'click') def on_save(self): self.binder.update() self.config.save() self.refresh()
class Netatalk(SectionPlugin): config_path = "/etc/afp.conf" def init(self): self.title = "Netatalk" self.icon = "folder-close" self.category = "Software" self.append(self.ui.inflate("netatalk:main")) if not os.path.exists(self.config_path): open(self.config_path, "w").close() self.binder = Binder(None, self.find("config")) self.find("shares").new_item = lambda c: ShareData() self.config = NetatalkConfig(path=self.config_path) def on_page_load(self): self.refresh() def refresh(self): self.config.load() self.binder.reset(self.config.tree).autodiscover().populate() @on("save", "click") def on_save(self): self.binder.update() self.config.save() self.refresh()
def init(self): self.title = _('File Manager') self.category = _('Tools') self.icon = 'folder-open' self.backend = FMBackend().get() self.append(self.ui.inflate('fm:main')) self.controller = Controller() self.controller.new_tab(self.classconfig['root']) def post_item_bind(object, collection, item, ui): ui.find('name').on('click', self.on_item_click, object, item) ui.find('edit').on('click', self.edit, item.fullpath) self.find('items').post_item_bind = post_item_bind def post_bc_bind(object, collection, item, ui): ui.find('name').on('click', self.on_bc_click, object, item) self.find('breadcrumbs').post_item_bind = post_bc_bind self.binder = Binder(self.controller, self.find('filemanager')).autodiscover().populate() self.clipboard = [] self.binder_c = Binder(self, self.find('bind-clipboard')).autodiscover().populate() self.tabs = self.find('tabs') self.find('dialog').buttons = [ {'id': 'save', 'text': _('Save')}, {'id': 'cancel', 'text': _('Cancel')}, ]
class PluginsPlugin (SectionPlugin): def init(self): self.title = _('Plugins') self.icon = 'cogs' self.category = '' self.order = 60 # In case you didn't notice it yet, this is the Plugins Plugin Plugin self.append(self.ui.inflate('plugins:main')) def post_plugin_bind(object, collection, item, ui): if not item.crash: ui.find('crash').visible = False def post_dep_bind(object, collection, item, ui): if not item.satisfied(): installer = ui.find('fix') if item.__class__ == ModuleDependency: installer.package = 'python-module-' + item.module_name if item.__class__ == BinaryDependency: installer.package = item.binary_name installer.recheck() self.find('plugins').post_item_bind = post_plugin_bind self.find('dependencies').post_item_bind = post_dep_bind self.binder = Binder(None, self.find('bind-root')) def on_page_load(self): self.context.endpoint.send_progress(_('Gathering plugin list')) self.plugins = sorted(manager.get_all().values()) self.binder.setup(self).populate()
def init(self): self.title = _("Packages") self.icon = "gift" self.category = _("System") self.mgr = PackageManager.get() self.append(self.ui.inflate("packages:main")) def post_item_bind(object, collection, item, ui): ui.find("install").on("click", self.on_install, item) ui.find("remove").on("click", self.on_remove, item) ui.find("cancel").on("click", self.on_cancel, item) ui.find("install").visible = item.action is None ui.find("remove").visible = item.action is None and item.state == "i" ui.find("cancel").visible = item.action is not None self.find("upgradeable").post_item_bind = post_item_bind self.find("search").post_item_bind = post_item_bind self.find("pending").post_item_bind = post_item_bind self.binder = Binder(None, self.find("bind-root")) self.binder_p = Binder(self, self.find("bind-pending")) self.binder_s = CollectionAutoBinding([], None, self.find("search")).populate() self.pending = {} self.installation_running = False self.action_queue = []
class PureFTPDExtension (BaseExtension): default_config = { 'created': False, 'password': None, } name = 'FTP' def init(self): self.append(self.ui.inflate('vh-pureftpd:ext')) self.binder = Binder(self, self) if not 'username' in self.config: self.config['username'] = self.website.slug if not 'system_user' in self.config: self.config['system_user'] = "" if not 'system_group' in self.config: self.config['system_group'] = "" if not self.config['created']: self.config['password'] = str(uuid.uuid4()) self.config['path'] = self.website.root self.config['created'] = True self.refresh() def refresh(self): self.binder.setup().populate() def update(self): self.binder.update()
class VSFTPDExtension (BaseExtension): default_config = { 'created': False, 'user': None, 'password': None, } name = 'FTP' def init(self): self.append(self.ui.inflate('vh-vsftpd:ext')) self.binder = Binder(self, self) self.config['username'] = self.website.slug if not self.config['created']: self.config['password'] = str(uuid.uuid4()) self.config['created'] = True self.refresh() def refresh(self): self.binder.setup().populate() def update(self): pass
def init(self): self.title = _('Packages') self.icon = 'gift' self.category = _('System') self.mgr = PackageManager.get() self.append(self.ui.inflate('packages:main')) def post_item_bind(object, collection, item, ui): ui.find('install').on('click', self.on_install, item) ui.find('remove').on('click', self.on_remove, item) ui.find('cancel').on('click', self.on_cancel, item) ui.find('install').visible = item.action is None ui.find('remove').visible = item.action is None and item.state == 'i' ui.find('cancel').visible = item.action is not None self.find('upgradeable').post_item_bind = post_item_bind self.find('search').post_item_bind = post_item_bind self.find('pending').post_item_bind = post_item_bind self.binder = Binder(None, self.find('bind-root')) self.binder_p = Binder(self, self.find('bind-pending')) self.binder_s = CollectionAutoBinding([], None, self.find('search')).populate() self.pending = {} self.installation_running = False self.action_queue = []
class Squid (SectionPlugin): def init(self): self.title = _('Squid') self.icon = 'exchange' self.category = _('Software') self.append(self.ui.inflate('squid:main')) self.binder = Binder(None, self.find('config')) self.find('acl').new_item = lambda c: ACLData() self.find('http_access').new_item = lambda c: HTTPAccessData() self.find('http_port').new_item = lambda c: HTTPPortData() self.find('https_port').new_item = lambda c: HTTPSPortData() self.config = SquidConfig(path='/etc/squid3/squid.conf') def on_page_load(self): self.refresh() def refresh(self): self.config.load() self.binder.reset(self.config.tree).autodiscover().populate() @on('save', 'click') def on_save(self): self.binder.update() self.config.save() self.refresh()
class DHCPDPlugin (SectionPlugin): def init(self): self.title = _('DHCP Server') self.icon = 'sitemap' self.category = _('Software') self.append(self.ui.inflate('dhcpd:main')) self.config = DHCPDConfig(path='/etc/dhcp/dhcpd.conf') self.binder = Binder(None, self) for x in self.nearest(lambda x: x.bind == 'ranges'): x.new_item = lambda c: RangeData() for x in self.nearest(lambda x: x.bind == 'options'): x.new_item = lambda c: OptionData() self.find('subnets').new_item = lambda c: SubnetData() def on_page_load(self): self.config.load() self.binder.reset(self.config.tree).autodiscover().populate() @on('save', 'click') def save(self): self.binder.update() self.config.save()
class Exports (SectionPlugin): config_path = '/etc/exports' def init(self): self.title = _('NFS Exports') self.icon = 'hdd' self.category = _('Software') self.append(self.ui.inflate('exports:main')) if not os.path.exists(self.config_path): open(self.config_path, 'w').close() self.config = ExportsConfig(path=self.config_path) self.binder = Binder(None, self) self.find('exports').new_item = lambda c: ExportData() self.find('clients').new_item = lambda c: ClientData() def on_page_load(self): self.config.load() self.binder.reset(self.config.tree).autodiscover().populate() @on('save', 'click') def save(self): self.binder.update() self.config.save() self.context.notify('info', _('Saved'))
class PluginsPlugin (SectionPlugin): def init(self): self.title = 'Plugins' self.icon = 'cogs' self.category = '' self.order = 50 # In case you didn't notice it yet, this is the Plugins Plugin Plugin self.append(self.ui.inflate('plugins:main')) def post_plugin_bind(object, collection, item, ui): if not item.crash: ui.find('crash').visible = False def post_dep_bind(object, collection, item, ui): if not item.satisfied(): installer = ui.find('fix') if item.__class__ == ModuleDependency: installer.package = 'python-module-' + item.module_name if item.__class__ == BinaryDependency: installer.package = item.binary_name installer.recheck() self.find('plugins').post_item_bind = post_plugin_bind self.find('dependencies').post_item_bind = post_dep_bind self.binder = Binder(self, self.find('bind-root')) self.refresh() def refresh(self): self.plugins = sorted(manager.get_all().values()) self.binder.reset().autodiscover().populate()
def init(self): self.title = _("File Manager") self.category = _("Tools") self.icon = "folder-open" self.backend = FMBackend().get() self.append(self.ui.inflate("fm:main")) self.controller = Controller() self.controller.new_tab(self.classconfig["root"]) def post_item_bind(object, collection, item, ui): ui.find("name").on("click", self.on_item_click, object, item) ui.find("edit").on("click", self.edit, item.fullpath) self.find("items").post_item_bind = post_item_bind def post_bc_bind(object, collection, item, ui): ui.find("name").on("click", self.on_bc_click, object, item) self.find("breadcrumbs").post_item_bind = post_bc_bind self.binder = Binder(self.controller, self.find("filemanager")).autodiscover().populate() self.clipboard = [] self.binder_c = Binder(self, self.find("filemanager")).autodiscover().populate() self.tabs = self.find("tabs") self.find("dialog").buttons = [{"id": "save", "text": _("Save")}, {"id": "cancel", "text": _("Cancel")}]
class Squid (SectionPlugin): def init(self): self.title = 'Squid' self.icon = 'exchange' self.category = _('Software') self.append(self.ui.inflate('squid:main')) self.find('servicebar').name = platform_select( debian='squid3', centos='squid', default='squid', ) self.find('servicebar').reload() self.binder = Binder(None, self.find('config')) self.find('acl').new_item = lambda c: ACLData(name='new') self.find('http_access').new_item = lambda c: HTTPAccessData() self.find('http_port').new_item = lambda c: HTTPPortData() self.find('https_port').new_item = lambda c: HTTPSPortData() for e in self.nearest(lambda x: x.id == 'options'): e.new_item = lambda c: ArgumentData() self.config = SquidConfig(path='/etc/squid3/squid.conf') def on_page_load(self): self.refresh() def refresh(self): self.config.load() self.binder.setup(self.config.tree).populate() @on('save', 'click') def on_save(self): self.binder.update() self.config.save() self.refresh()
class Netatalk (SectionPlugin): config_path = '/etc/afp.conf' def init(self): self.title = 'Netatalk' self.icon = 'folder-close' self.category = _('Software') self.append(self.ui.inflate('netatalk:main')) if not os.path.exists(self.config_path): open(self.config_path, 'w').close() self.binder = Binder(None, self.find('config')) self.find('shares').new_item = lambda c: ShareData() self.config = NetatalkConfig(path=self.config_path) def on_page_load(self): self.refresh() def refresh(self): self.config.load() self.binder.reset(self.config.tree).autodiscover().populate() @on('save', 'click') def on_save(self): self.binder.update() self.config.save() self.refresh()
class NetworkPlugin(SectionPlugin): platforms = ["debian", "centos"] def init(self): self.title = _("Network") self.icon = "globe" self.category = _("System") self.net_config = INetworkConfig.get() self.append(self.ui.inflate("network:main")) def post_interface_bind(o, c, i, u): i.add_bits(self.ui) for bit in i.bits: u.find("bits").append(self.ui.create("tab", children=[bit], title=bit.title)) u.find("up").on("click", self.on_up, i) u.find("down").on("click", self.on_down, i) u.find("restart").on("click", self.on_restart, i) def post_interface_update(o, c, i, u): for bit in i.bits: bit.apply() self.find("interfaces").post_item_bind = post_interface_bind self.find("interfaces").post_item_update = post_interface_update self.binder = Binder(self.net_config, self) def on_page_load(self): self.refresh() def refresh(self): self.net_config.rescan() sensor = Sensor.find("traffic") for i in self.net_config.interface_list: i.tx, i.rx = sensor.value(i.name) self.binder.reset().autodiscover().populate() return def on_up(self, iface=None): self.net_config.up(iface) self.refresh() def on_down(self, iface=None): self.net_config.down(iface) self.refresh() def on_restart(self, iface=None): self.on_down(iface) self.on_up(iface) @on("save", "click") def on_save(self): self.binder.update() self.net_config.save() self.refresh() self.context.notify("info", _("Saved"))
class TaskManager (SectionPlugin): def init(self): self.title = _('Processes') self.icon = 'th-list' self.category = _('System') self.append(self.ui.inflate('taskmgr:main')) def post_item_bind(object, collection, item, ui): ui.find('term').on('click', self.on_term, item) ui.find('kill').on('click', self.on_kill, item) self.find('processes').post_item_bind = post_item_bind self.binder = Binder(None, self) self.sorting = '_cpu' self.sorting_reverse = True for x in ['_cpu', 'pid', '_sort_ram', '_sort_name']: self.find('sort-by-' + x).on('click', self.sort, x) def on_page_load(self): self.refresh() def sort(self, by): if self.sorting == by: self.sorting_reverse = not self.sorting_reverse else: self.sorting_reverse = by in ['_cpu', '_ram'] self.sorting = by self.refresh() def refresh(self): self.processes = list(psutil.process_iter()) for p in self.processes: try: p._name = p.name p._cmd = ' '.join(p.cmdline) p._cpu = p.get_cpu_percent(interval=0) p._ram = '%i K' % int(p.get_memory_info()[0] / 1024) p._ppid = p.ppid p._sort_ram = p.get_memory_info()[0] p._sort_name = p.name.lower() try: p._username = p.username except: p._username = '******' except psutil.NoSuchProcess: self.processes.remove(p) self.processes = sorted(self.processes, key=lambda x: getattr(x, self.sorting), reverse=self.sorting_reverse) self.binder.setup(self).populate() def on_term(self, p): os.kill(p.pid, 15) self.refresh() def on_kill(self, p): os.kill(p.pid, 9) self.refresh()
class WebserverPlugin (SectionPlugin): service_name = '' service_buttons = [] hosts_available_dir = '' hosts_enabled_dir = '' template = '' supports_host_activation = True def init(self): self.append(self.ui.inflate('webserver_common:main')) self.binder = Binder(None, self) self.find_type('servicebar').buttons = self.service_buttons self.hosts_dir = AvailabilitySymlinks( self.hosts_available_dir, self.hosts_enabled_dir, self.supports_host_activation ) def delete_host(host, c): c.remove(host) self.hosts_dir.delete(host.name) def on_host_bind(o, c, host, u): host.__old_name = host.name def on_host_update(o, c, host, u): if host.__old_name != host.name: self.hosts_dir.rename(host.__old_name, host.name) host.save() def new_host(c): name = 'untitled' while os.path.exists(self.hosts_dir.get_path(name)): name += '_' self.hosts_dir.open(name, 'w').write(self.template) return WebserverHost(self, self.hosts_dir, name) self.find('hosts').delete_item = delete_host self.find('hosts').new_item = new_host self.find('hosts').post_item_bind = on_host_bind self.find('hosts').post_item_update = on_host_update self.find('header-active-checkbox').visible = \ self.find('body-active-line').visible = \ self.supports_host_activation def on_page_load(self): self.refresh() @on('save-button', 'click') def save(self): self.binder.update() self.refresh() self.context.notify('info', 'Saved') def refresh(self): self.hosts = [WebserverHost(self, self.hosts_dir, x) for x in self.hosts_dir.list_available()] self.binder.reset(self).autodiscover().populate() self.find_type('servicebar').reload()
class BIND9Plugin (SectionPlugin): def init(self): self.title = 'BIND9' self.icon = 'globe' self.category = _('Software') self.append(self.ui.inflate('bind9:main')) self.config = BIND9Config(path='/etc/bind/named.conf') self.binder = Binder(None, self) self.find('zones').new_item = lambda c: ZoneData() def post_zone_bind(o, c, i, u): path = i.file if not path.startswith('/'): path = '/etc/bind/' + path exists = os.path.exists(path) u.find('no-file').visible = not exists u.find('file').visible = exists if exists: u.find('editor').value = open(path).read() def on_save_zone(): open(path, 'w').write(u.find('editor').value) self.context.notify('info', _('Zone saved')) def on_create_zone(): open(path, 'w').write("""$TTL 604800 @ IN SOA ns. root.ns. ( 1 ; Serial 604800 ; Refresh 86400 ; Retry 2419200 ; Expire 604800 ) ; Negative Cache TTL ; @ IN NS ns. example.com. IN A 127.0.0.1 example.com. IN AAAA ::1 """) post_zone_bind(o, c, i, u) u.find('save-zone').on('click', on_save_zone) u.find('create-zone').on('click', on_create_zone) self.find('zones').post_item_bind = post_zone_bind def on_page_load(self): self.refresh() def refresh(self): self.config.load() self.binder.reset(self.config.tree).autodiscover().populate() @on('save', 'click') def save(self): self.binder.update() self.config.save() self.refresh() self.context.notify('info', _('Saved'))
def init(self): self.title = _('Configure') self.icon = 'wrench' self.category = '' self.order = 50 self.append(self.ui.inflate('configurator:main')) self.binder = Binder(ajenti.config.tree, self.find('ajenti-config')) self.ccmgr = ClassConfigManager.get() self.classconfig_binding = Binder(self.ccmgr, self.find('classconfigs')) def post_classconfig_bind(object, collection, item, ui): def configure(): self.configure_plugin(item, notify=False) ui.find('configure').on('click', configure) self.find('classconfigs').find('classes').post_item_bind = post_classconfig_bind self.find('users').new_item = lambda c: UserData() def post_user_bind(object, collection, item, ui): provider = UserManager.get(manager.context).get_sync_provider() editable = item.name != 'root' renameable = editable and provider.allows_renaming deletable = renameable ui.find('name-edit').visible = renameable ui.find('name-label').visible = not renameable ui.find('delete').visible = deletable box = ui.find('permissions') box.empty() p = PermissionProvider.get_all() for prov in p: line = self.ui.create('tab', title=prov.get_name()) box.append(line) for perm in prov.get_permissions(): line.append( self.ui.create('checkbox', id=perm[0], text=perm[1], value=(perm[0] in item.permissions)) ) self.find('users').post_item_bind = post_user_bind def post_user_update(object, collection, item, ui): box = ui.find('permissions') for prov in PermissionProvider.get_all(): for perm in prov.get_permissions(): has = box.find(perm[0]).value if has and not perm[0] in item.permissions: item.permissions.append(perm[0]) if not has and perm[0] in item.permissions: item.permissions.remove(perm[0]) if ui.find('password').value: item.password = ui.find('password').value self.find('users').post_item_update = post_user_update
class NetworkPlugin (SectionPlugin): platforms = ['debian', 'centos'] def init(self): self.title = _('Network') self.icon = 'globe' self.category = _('System') self.net_config = INetworkConfig.get() self.append(self.ui.inflate('network:main')) def post_interface_bind(o, c, i, u): i.add_bits(self.ui) for bit in i.bits: u.find('bits').append(self.ui.create( 'tab', children=[bit], title=bit.title, )) u.find('up').on('click', self.on_up, i) u.find('down').on('click', self.on_down, i) def post_interface_update(o, c, i, u): for bit in i.bits: bit.apply() self.find('interfaces').post_item_bind = post_interface_bind self.find('interfaces').post_item_update = post_interface_update self.binder = Binder(self.net_config, self) def on_page_load(self): self.refresh() def refresh(self): self.net_config.rescan() sensor = Sensor.find('traffic') for i in self.net_config.interface_list: i.tx, i.rx = sensor.value(i.name) self.binder.reset().autodiscover().populate() return def on_up(self, iface=None): self.net_config.up(iface) self.refresh() def on_down(self, iface=None): self.net_config.down(iface) self.refresh() @on('save', 'click') def on_save(self): self.binder.update() self.net_config.save() self.refresh() self.context.notify('info', _('Saved'))
class MySQLExtension (BaseExtension): default_config = { 'created': False, 'name': None, 'user': None, 'password': None, } name = 'MySQL' def init(self): self.append(self.ui.inflate('vh-mysql:ext')) self.binder = Binder(self, self) self.refresh() self.db = MySQLDB.get() @staticmethod def selftest(): try: MySQLDB.get().query_databases() except: pass def refresh(self): self.binder.setup().populate() self.find('db-name').value = self.website.slug def update(self): self.binder.update() def on_destroy(self): if self.config['created']: self.on_delete() @on('create', 'click') def on_create(self): try: self.db.query_databases() except Exception, e: self.context.notify('error', str(e)) self.context.launch('configure-plugin', plugin=self.db) return dbname = self.find('db-name').value for db in self.db.query_databases(): if db.name == dbname: self.context.notify('error', 'This DB name is already used') return self.config['username'] = self.website.slug self.config['password'] = str(uuid.uuid4()) self.config['name'] = dbname try: self.db.query_create(self.config['name']) except Exception, e: self.context.notify('error', str(e)) return
class SNMPDPlugin (SectionPlugin): service_name = platform_select( default='snmpd', ) def init(self): self.title = 'SNMP' self.icon = 'exchange' self.category = _('Software') self.append(self.ui.inflate('snmpd:main')) self.find('servicebar').name = self.service_name self.find('servicebar').reload() self.snmp_config = SNMPConfig(path=platform_select( default='/etc/snmp/snmp.conf', )) self.binder = Binder(None, self) def on_page_load(self): self.refresh() def refresh(self): self.snmp_config.load() enabled_mibs = [] for mib in self.snmp_config.tree.mibs: for x in mib.name.strip('-+:').split(':'): enabled_mibs.append(x) self.mibs = [] for dirpath, dirname, filenames in os.walk('/usr/share/mibs', followlinks=True): for x in filenames: if not x.startswith('.'): mib = MIBData() mib.name = x mib.selected = x in enabled_mibs self.mibs.append(mib) self.mibs = sorted(self.mibs, key=lambda x: x.name) self.binder.setup(self).populate() @on('save', 'click') def save(self): self.binder.update() mib = MIBData() mib.name = ':'.join([x.name for x in self.mibs if x.selected]) for x in list(self.snmp_config.tree.mibs): self.snmp_config.tree.mibs.remove(x) self.snmp_config.tree.mibs.append(mib) self.snmp_config.save() self.refresh() self.context.notify('info', _('Saved')) ServiceMultiplexor.get().get_one(self.service_name).restart()
class Cron(SectionPlugin): def init(self): self.title = "Cron" self.icon = "time" self.category = _("System") self.append(self.ui.inflate("cron:main")) def create_task(cls): logging.info("[cron] created a %s" % cls.__name__) return cls() def remove_task(i, c): c.remove(i) logging.info("[cron] removed %s" % getattr(i, "command", None)) self.binder = Binder(None, self.find("config")) self.find("normal_tasks").new_item = lambda c: create_task(CrontabNormalTaskData) self.find("special_tasks").new_item = lambda c: create_task(CrontabSpecialTaskData) self.find("env_settings").new_item = lambda c: create_task(CrontabEnvSettingData) self.find("normal_tasks").delete_item = remove_task self.find("special_tasks").delete_item = remove_task self.find("env_settings").delete_item = remove_task self.current_user = "******" def on_page_load(self): self.refresh() @on("user-select", "click") def on_user_select(self): self.current_user = self.find("users").value logging.info("[cron] selected user %s" % self.current_user) self.refresh() def refresh(self): users_select = self.find("users") users_select.value = self.current_user users = [ x.name for x in PasswdConfig(path="/etc/passwd").load().tree.users if int(x.uid) >= 500 or x.name == "root" ] users_select.values = users_select.labels = users self.config = CronManager.get().load_tab(self.current_user) self.binder.setup(self.config.tree).populate() @on("save", "click") def on_save(self): self.binder.update() logging.info("[cron] edited tasks") try: CronManager.get().save_tab(self.current_user, self.config) self.refresh() except Exception, e: self.context.notify("error", e.message)
class Filesystems (SectionPlugin): def init(self): self.title = _('Filesystems') self.icon = 'hdd' self.category = _('System') self.append(self.ui.inflate('fstab:main')) self.find('type').labels = ['Auto', 'EXT2', 'EXT3', 'EXT4', 'NTFS', 'FAT', 'ZFS', 'ReiserFS', 'Samba', 'None', 'Loop'] self.find('type').values = ['auto', 'ext2', 'ext3', 'ext4', 'ntfs', 'vfat', 'zfs', 'reiser', 'smb', 'none', 'loop'] self.fstab_config = FSTabConfig(path='/etc/fstab') self.mounts = MountsBackend.get() self.binder = Binder(None, self) self.find('fstab').find('filesystems').new_item = lambda c: FilesystemData() def post_mount_bind(object, collection, item, ui): ui.find('umount').on('click', self.on_umount, item) self.find('mounts').find('filesystems').post_item_bind = post_mount_bind def on_page_load(self): self.refresh() def on_umount(self, mount): subprocess.call(['umount', mount.mountpoint]) self.context.notify('info', _('Unmounted')) self.refresh() @on('mount-all', 'click') def on_mount_all(self): self.save() if subprocess.call(['mount', '-a']): self.context.notify('error', _('mount -a failed')) self.refresh() @on('refresh', 'click') def refresh(self): self.reload_disks() self.fstab_config.load() self.fstab = self.fstab_config.tree self.mounts.reload() self.binder.reset(self).autodiscover().populate() def reload_disks(self): lst = disks.list_devices(by_uuid=True, by_id=True, by_label=True) self.find('device').labels = [x[0] for x in lst] self.find('device').values = [x[1] for x in lst] @on('save', 'click') def save(self): self.binder.update() self.fstab_config.save() self.context.notify('info', _('Saved'))
class Cron (SectionPlugin): def init(self): self.title = 'Cron' self.icon = 'time' self.category = _('System') self.append(self.ui.inflate('cron:main')) def create_task(cls): logging.info('[cron] created a %s' % cls.__name__) return cls() def remove_task(i, c): c.remove(i) logging.info('[cron] removed %s' % getattr(i, 'command', None)) self.binder = Binder(None, self.find('config')) self.find('normal_tasks').new_item = lambda c: create_task(CrontabNormalTaskData) self.find('special_tasks').new_item = lambda c: create_task(CrontabSpecialTaskData) self.find('env_settings').new_item = lambda c: create_task(CrontabEnvSettingData) self.find('normal_tasks').delete_item = remove_task self.find('special_tasks').delete_item = remove_task self.find('env_settings').delete_item = remove_task self.current_user = '******' def on_page_load(self): self.refresh() @on('user-select', 'click') def on_user_select(self): self.current_user = self.find('users').value logging.info('[cron] selected user %s' % self.current_user) self.refresh() def refresh(self): users_select = self.find('users') users_select.value = self.current_user users = [x.name for x in PasswdConfig(path='/etc/passwd').load().tree.users] users_select.values = users_select.labels = users self.config = CronManager.get().load_tab(self.current_user) self.binder.setup(self.config.tree).populate() @on('save', 'click') def on_save(self): self.binder.update() logging.info('[cron] edited tasks') try: CronManager.get().save_tab(self.current_user, self.config) self.refresh() except Exception as e: self.context.notify('error', e.message)
class LinuxBasicNetworkConfigSet (NetworkConfigBit): cls = 'linux-basic' title = 'Basic' def init(self): self.append(self.ui.inflate('network:bit-linux-basic')) self.binder = Binder(self.iface, self) def refresh(self): self.binder.reset(self.iface).autodiscover().populate() def apply(self): self.binder.update()
class LinuxDHCPNetworkConfigSet (NetworkConfigBit): cls = 'linux-dhcp' title = 'DHCP' def init(self): self.append(self.ui.inflate('network:bit-linux-dhcp')) self.binder = Binder(None, self) def refresh(self): self.binder.setup(self.iface).populate() def apply(self): self.binder.update()
class BIND9Plugin (SectionPlugin): config_root = platform_select( debian='/etc/bind/', centos='/etc/named/', ) config_path = platform_select( debian='/etc/bind/named.conf', centos='/etc/named.conf', ) def init(self): self.title = 'BIND9' self.icon = 'globe' self.category = _('Software') self.append(self.ui.inflate('bind9:main')) self.config = BIND9Config(path=self.config_path) self.binder = Binder(None, self) self.find('zones').new_item = lambda c: ZoneData() def post_zone_bind(o, c, i, u): path = i.file if not path.startswith('/'): path = self.config_root + path exists = os.path.exists(path) u.find('no-file').visible = not exists u.find('file').visible = exists if exists: u.find('editor').value = open(path).read() def on_save_zone(): open(path, 'w').write(u.find('editor').value) self.context.notify('info', _('Zone saved')) def on_create_zone(): open(path, 'w').write("""$TTL 604800 @ IN SOA ns. root.ns. ( 1 ; Serial 604800 ; Refresh 86400 ; Retry 2419200 ; Expire 604800 ) ; Negative Cache TTL ; @ IN NS ns. example.com. IN A 127.0.0.1 example.com. IN AAAA ::1 """) post_zone_bind(o, c, i, u) u.find('save-zone').on('click', on_save_zone) u.find('create-zone').on('click', on_create_zone) self.find('zones').post_item_bind = post_zone_bind def on_page_load(self): self.refresh() def refresh(self): self.config.load() self.binder.reset(self.config.tree).autodiscover().populate() @on('save', 'click') def save(self): self.binder.update() self.config.save() self.refresh() self.context.notify('info', _('Saved'))
class CSFSection (SectionPlugin): def init(self): self.title = _('CSF Firewall') self.icon = 'fire' self.category = _('System') self.backend = CSFBackend.get() self.append(self.ui.inflate('csf:main')) self.config = CSFConfig(path='/etc/csf/csf.conf') self.list_allow = [] self.list_deny = [] self.list_tempallow = [] self.list_tempban = [] def delete_rule(csf_option, i): self.save() subprocess.call(['csf', csf_option, i.value.split('#')[0]]) self.refresh() self.find('list_allow').on_delete = lambda i, c: delete('-ar', i) self.find('list_deny').on_delete = lambda i, c: delete('-dr', i) self.find('list_tempallow').on_delete = lambda i, c: delete('-tr', i) self.find('list_tempban').on_delete = lambda i, c: delete('-tr', i) def add_rule(csf_option, address): self.save() p = subprocess.Popen(['csf', csf_option, address], stdout=subprocess.PIPE) o, e = p.communicate() self.context.notify('info', o) self.refresh() self.find('list_allow-add').on('click', lambda: add_rule('-a', self.find('permanent-lists-add-address').value)) self.find('list_deny-add').on('click', lambda: add_rule('-d', self.find('permanent-lists-add-address').value)) self.find('list_tempallow-add').on('click', lambda: add_rule('-ta', self.find('temporary-lists-add-address').value)) self.find('list_tempban-add').on('click', lambda: add_rule('-td', self.find('temporary-lists-add-address').value)) self.binder = Binder(None, self) self.binder_lists = Binder(self, self.find('lists')) def on_page_load(self): self.refresh() def refresh(self): self.config.load() self.list_allow = self.backend.read_list('allow') self.list_deny = self.backend.read_list('deny') self.list_tempallow = self.backend.read_list('tempallow') self.list_tempban = self.backend.read_list('tempban') self.binder.setup(self.config.tree).populate() self.binder_lists.populate() @on('apply', 'click') def on_apply(self): self.backend.apply() self.context.notify('info', _('Applied')) @on('save', 'click') def save(self): self.binder.update() self.config.save() self.backend.write_list('allow', self.list_allow) self.backend.write_list('deny', self.list_deny) self.backend.write_list('tempallow', self.list_tempallow) self.backend.write_list('tempban', self.list_tempban) self.binder.setup(self.config.tree).populate() self.context.notify('info', _('Saved')) try: self.backend.test_config() self.context.notify('info', _('Self-test OK')) except Exception, e: self.context.notify('error', str(e))
class Filesystems(SectionPlugin): def init(self): self.title = _('Filesystems') self.icon = 'hdd' self.category = _('System') self.append(self.ui.inflate('fstab:main')) self.find('type').labels = [ 'Auto', 'EXT2', 'EXT3', 'EXT4', 'NTFS', 'FAT', 'ZFS', 'ReiserFS', 'Samba', 'None', 'Loop' ] self.find('type').values = [ 'auto', 'ext2', 'ext3', 'ext4', 'ntfs', 'vfat', 'zfs', 'reiser', 'smb', 'none', 'loop' ] self.fstab_config = FSTabConfig(path='/etc/fstab') self.mounts = MountsBackend.get() self.binder = Binder(None, self) self.find('fstab').find( 'filesystems').new_item = lambda c: FilesystemData() def post_mount_bind(object, collection, item, ui): ui.find('umount').on('click', self.on_umount, item) self.find('mounts').find( 'filesystems').post_item_bind = post_mount_bind def on_page_load(self): self.refresh() def on_umount(self, mount): subprocess.call(['umount', mount.mountpoint]) self.context.notify('info', _('Unmounted')) self.refresh() @on('mount-all', 'click') def on_mount_all(self): self.save() if subprocess.call(['mount', '-a']): self.context.notify('error', _('mount -a failed')) self.refresh() @on('refresh', 'click') def refresh(self): self.binder.unpopulate() self.reload_disks() self.fstab_config.load() self.fstab = self.fstab_config.tree self.mounts.reload() self.binder.setup(self).populate() def reload_disks(self): lst = disks.list_devices(by_uuid=True, by_id=True, by_label=True) self.find('device').labels = [x[0] for x in lst] self.find('device').values = [x[1] for x in lst] @on('save', 'click') def save(self): self.binder.update() self.fstab_config.save() self.context.notify('info', _('Saved'))
class SanickioskScreensaverPrefs(SectionPlugin): default_classconfig = { 'enable_browser': False, 'home_url': 'http://*****:*****@on('save', 'click') def save(self): self.binder.update() self.save_classconfig() self.context.notify( 'info', _('Настройките са запаметени. Моля, рестартирайте киоска.')) self.binder.populate() #all_vars = '\n'.join([k + '="' + str(v) + '"' for k,v in self.classconfig.iteritems()]) for k, v in self.classconfig.iteritems(): if k == 'enable_browser': enable_browser = "X-GNOME-Autostart-enabled=%s" % str( v).lower() if k == 'home_url': home_url = v.lower() if enable_browser == "X-GNOME-Autostart-enabled=true": ajenti_config = "/etc/ajenti/config.json" #Disable Video Mode subprocess.call([ 'sed', '-i', r's/\\"enable_videos\\": true/\\"enable_videos\\": false/g', ajenti_config ]) subprocess.call([ 'sed', '-i', r's/X-GNOME-Autostart-enabled=true/X-GNOME-Autostart-enabled=false/g', "/home/kiosk/.config/autostart/2-videos.desktop" ]) #Disable Photo Mode subprocess.call([ 'sed', '-i', r's/\\"photos_enable\\": true/\\"photos_enable\\": false/g', ajenti_config ]) subprocess.call([ 'sed', '-i', r's/X-GNOME-Autostart-enabled=true/X-GNOME-Autostart-enabled=false/g', "/home/kiosk/.config/autostart/2-photos.desktop" ]) cfg = ( "[Desktop Entry]\n" "Type=Application\n" "Exec=chromium-browser --kiosk --no-first-run --disable-infobars --disable-session-crashed-bubble %s\n" "Hidden=false\n" "NoDisplay=false\n" "%s\n" "Name[en_US]=2-browser\n" "Name=2-browser\n" "Comment[en_US]=\n" "Comment=") % (home_url, enable_browser) open('/home/kiosk/.config/autostart/2-browser.desktop', 'w').write(cfg) #save
def edit(self, path): self.find('dialog').visible = True self.item = Item(path) self.item.read() self.binder_d = Binder(self.item, self.find('dialog')).autodiscover().populate()
class Firewall(SectionPlugin): platforms = ['centos', 'debian'] def init(self): self.title = _('Firewall') self.icon = 'fire' self.category = _('System') self.append(self.ui.inflate('iptables:main')) self.fw_mgr = FirewallManager.get() self.config = IPTablesConfig(path=self.fw_mgr.config_path_ajenti) self.binder = Binder(None, self.find('config')) self.find('tables').new_item = lambda c: TableData() self.find('chains').new_item = lambda c: ChainData() self.find('rules').new_item = lambda c: RuleData() self.find('options').new_item = lambda c: OptionData() self.find('options').binding = OptionsBinding self.find('options').filter = lambda i: not i.name in ['j', 'jump'] def post_rule_bind(o, c, i, u): u.find('add-option').on('change', self.on_add_option, c, i, u) action = '' j_option = i.get_option('j', 'jump') if j_option: action = j_option.arguments[0].value u.find('action').text = action u.find('action').style = 'iptables-action iptables-%s' % action u.find('action-select').value = action u.find('title').text = i.comment if i.comment else i.summary def post_rule_update(o, c, i, u): action = u.find('action-select').value j_option = i.get_option('j', 'jump') if j_option: j_option.arguments[0].value = action else: if action: o = OptionData.create_destination() o.arguments[0].value = action i.options.append(o) self.find('rules').post_item_bind = post_rule_bind self.find('rules').post_item_update = post_rule_update self.find('add-option').values = self.find('add-option').labels = [ _('Add option') ] + sorted(OptionData.templates.keys()) def on_page_load(self): if not os.path.exists(self.fw_mgr.config_path_ajenti): if not os.path.exists(self.fw_mgr.config_path): open(self.fw_mgr.config_path, 'w').write(""" *mangle :PREROUTING ACCEPT [0:0] :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :POSTROUTING ACCEPT [0:0] COMMIT *nat :PREROUTING ACCEPT [0:0] :INPUT ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :POSTROUTING ACCEPT [0:0] COMMIT *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] COMMIT """) open(self.fw_mgr.config_path_ajenti, 'w').write(open(self.fw_mgr.config_path).read()) self.config.load() self.refresh() @on('load-current', 'click') def on_load_current(self): subprocess.call('iptables-save > %s' % self.fw_mgr.config_path, shell=True) self.config.load() self.refresh() def refresh(self): self.find('autostart').text = (_('Disable') if self.fw_mgr.get_autostart_state() else _('Enable')) + _(' autostart') actions = ['ACCEPT', 'DROP', 'REJECT', 'LOG', 'MASQUERADE', 'DNAT', 'SNAT'] + \ list(set(itertools.chain.from_iterable([[c.name for c in t.chains] for t in self.config.tree.tables]))) self.find('action-select').labels = actions self.find('action-select').values = actions self.find('chain-action-select').labels = actions self.find('chain-action-select').values = actions self.binder.setup(self.config.tree).populate() @on('autostart', 'click') def on_autostart_change(self): self.fw_mgr.set_autostart_state(not self.fw_mgr.get_autostart_state()) self.refresh() def on_add_option(self, options, rule, ui): o = OptionData.create(ui.find('add-option').value) ui.find('add-option').value = '' rule.options.append(o) self.binder.populate() @on('save', 'click') def save(self): self.binder.update() for t in self.config.tree.tables: for c in t.chains: for r in c.rules: r.verify() self.config.save() open(self.fw_mgr.config_path, 'w').write(''.join( l.split('#')[0] + '\n' for l in open(self.fw_mgr.config_path_ajenti).read().splitlines())) self.refresh() self.context.notify('info', _('Saved')) @on('edit', 'click') def raw_edit(self): self.context.launch('notepad', path=self.fw_mgr.config_path_ajenti) @on('apply', 'click') def apply(self): self.save() cmd = 'cat %s | iptables-restore' % self.fw_mgr.config_path if subprocess.call(cmd, shell=True) != 0: self.context.launch('terminal', command=cmd) else: self.context.notify('info', _('Applied successfully'))
class Users(SectionPlugin): def init(self): self.title = _('Users') self.icon = 'group' self.category = _('System') self.append(self.ui.inflate('users:main')) def _filterOnlyUsers(x): u = int(x.uid) return u >= 500 def _filterOnlySystemUsers(x): u = int(x.uid) return u < 500 def _sorter(x): g = int(x.gid) if g >= 500: return g - 10000 return g self.find('users').filter = _filterOnlyUsers self.find('system-users').filter = _filterOnlySystemUsers self.find('groups').sorting = _sorter self.config = PasswdConfig(path='/etc/passwd') self.config_g = GroupConfig(path='/etc/group') self.binder = Binder(None, self.find('passwd-config')) self.binder_system = Binder(None, self.find('passwd-config-system')) self.binder_g = Binder(None, self.find('group-config')) self.mgr = UsersBackend.get() def post_item_bind(object, collection, item, ui): ui.find('change-password').on('click', self.change_password, item, ui) ui.find('remove-password').on('click', self.remove_password, item) if not os.path.exists(item.home): ui.find('create-home-dir').on('click', self.create_home_dir, item, ui) ui.find('create-home-dir').visible = True self.find('users').post_item_bind = post_item_bind self.find('system-users').post_item_bind = post_item_bind def on_page_load(self): self.refresh() def refresh(self): self.config.load() self.config_g.load() self.binder.setup(self.config.tree).populate() self.binder_system.setup(self.config.tree).populate() self.binder_g.setup(self.config_g.tree) self.find('group-members').labels = self.find( 'group-members').values = [x.name for x in self.config.tree.users] self.binder_g.populate() @on('add-user', 'click') def on_add_user(self): self.find('input-username').visible = True @on('input-username', 'submit') def on_add_user_done(self, value): self.mgr.add_user(value) self.refresh() @on('add-group', 'click') def on_add_group(self): self.find('input-groupname').visible = True @on('input-groupname', 'submit') def on_add_group_done(self, value): self.mgr.add_group(value) self.refresh() @on('save-users', 'click') def save_users(self): self.binder.update() self.config.save() @on('save-system-users', 'click') def save_system_users(self): self.binder_system.update() self.config.save() @on('save-groups', 'click') def save_groups(self): self.binder_g.update() self.config_g.save() def create_home_dir(self, user, ui): self.mgr.make_home_dir(user) self.context.notify('info', _('Home dir for %s was created') % user.name) ui.find('create-home-dir').visible = False def change_password(self, user, ui): new_password = ui.find('new-password').value if new_password: try: self.mgr.change_password(user, new_password) self.context.notify( 'info', _('Password for %s was changed') % user.name) ui.find('new-password').value = '' except Exception, e: self.context.notify('error', _('Error: "%s"') % e.message) else:
class MailPlugin (SectionPlugin): def init(self): self.title = _('Mail') self.icon = 'envelope' self.category = 'Web' self.manager = MailManager.get() if not self.manager.is_configured: self.append(self.ui.inflate('vh-mail:not-configured')) else: self.post_init() @on('initial-enable', 'click') def on_initial_enable(self): self.post_init() self.manager.save() self.refresh() def post_init(self): self.empty() self.append(self.ui.inflate('vh-mail:main')) self.binder = Binder(None, self) def post_mb_bind(object, collection, item, ui): ui.find('size').text = str_fsize(self.manager.get_usage(item)) def post_mb_update(object, collection, item, ui): if ui.find('password').value: item.password = ui.find('password').value self.find('mailboxes').post_item_bind = post_mb_bind self.find('mailboxes').post_item_update = post_mb_update self.find('mailboxes').filter = \ lambda mb: self.context.session.identity in ['root', mb.owner] self.find('targets').new_item = lambda c: ForwardingTarget.create() self.binder.setup(self.manager.config) def _fetch_new_mailbox_name(self, cls): mb = cls.create() mb.local = self.find('new-mailbox-local').value mb.domain = self.find('new-mailbox-domain').value or \ self.find('new-mailbox-domain-custom').value if not mb.local: self.context.notify('error', _('Invalid mailbox name')) return if not mb.domain: self.context.notify('error', _('Invalid mailbox domain')) return if cls == ForwardingMailbox: for existing in self.manager.config.forwarding_mailboxes: if existing.name == mb.name: self.context.notify( 'error', _('This address is already taken') ) return else: for existing in self.manager.config.mailboxes: if existing.name == mb.name: self.context.notify( 'error', _('This address is already taken') ) return self.find('new-mailbox-local').value = '' return mb @on('new-mailbox', 'click') def on_new_mailbox(self): self.binder.update() mb = self._fetch_new_mailbox_name(Mailbox) if not mb: return mb.owner = self.context.session.identity mb.password = '' self.manager.config.mailboxes.append(mb) self.manager.save() self.binder.populate() @on('new-forwarding-mailbox', 'click') def on_new_forwarding_mailbox(self): self.binder.update() mb = self._fetch_new_mailbox_name(ForwardingMailbox) if not mb: return mb.owner = self.context.session.identity self.manager.config.forwarding_mailboxes.append(mb) self.manager.save() self.binder.populate() def on_page_load(self): self.refresh() def refresh(self): if not self.manager.is_configured: return domains = [] for ws in VHManager.get().config.websites: if self.context.session.identity in ['root', ws.owner]: domains += [d.domain for d in ws.domains] domains = sorted(list(set(domains))) if self.find('new-mailbox-domain'): self.find('new-mailbox-domain').labels = \ domains + [_('Custom domain')] self.find('new-mailbox-domain').values = domains + [None] if self.manager.is_configured: self.binder.unpopulate().populate() if os.path.exists(self.manager.config.dkim_private_key): pubkey = subprocess.check_output([ 'openssl', 'rsa', '-in', self.manager.config.dkim_private_key, '-pubout' ]) pubkey = filter(None, pubkey.split('-'))[1].replace('\n', '') dns = '@\t\t\t\t10800 IN TXT "v=spf1 a -all"\n' dns += '_domainkey\t\t10800 IN TXT "o=~; r=postmaster@<domain>"\n' dns += '%s._domainkey\t10800 IN TXT "v=DKIM1; k=rsa; p=%s"\n' % ( self.manager.config.dkim_selector, pubkey ) dns += '_dmarc\t\t\t10800 IN TXT "v=DMARC1; p=quarantine"\n' self.find('dkim-domain-entry').value = dns else: self.find('dkim-domain-entry').value = _('No valid key exists') @on('generate-dkim-key', 'click') def on_generate_dkim_key(self): self.binder.update() self.manager.generate_dkim_key() self.binder.populate() self.save() @on('generate-tls-cert', 'click') def on_generate_tls_cert(self): self.binder.update() self.manager.generate_tls_cert() self.binder.populate() self.save() @on('save', 'click') def save(self): self.binder.update() self.manager.save() self.refresh() self.context.notify('info', _('Saved'))
class Packages (SectionPlugin): platforms = ['debian', 'centos', 'freebsd', 'arch'] def init(self): self.title = _('Packages') self.icon = 'gift' self.category = _('System') self.mgr = PackageManager.get() self.append(self.ui.inflate('packages:main')) def post_item_bind(object, collection, item, ui): ui.find('install').on('click', self.on_install, item) ui.find('remove').on('click', self.on_remove, item) ui.find('cancel').on('click', self.on_cancel, item) ui.find('install').visible = item.action is None ui.find('remove').visible = item.action is None and item.state == 'i' ui.find('cancel').visible = item.action is not None self.find('upgradeable').post_item_bind = post_item_bind self.find('search').post_item_bind = post_item_bind self.find('pending').post_item_bind = post_item_bind self.binder = Binder(None, self.find('bind-root')) self.binder_p = Binder(self, self.find('bind-pending')) self.binder_s = CollectionAutoBinding([], None, self.find('search')).populate() self.pending = {} self.installation_running = False self.action_queue = [] def refresh(self): self.fill(self.mgr.upgradeable) self.binder.setup(self.mgr).populate() self.binder_s.unpopulate().populate() self._pending = self.pending.values() self.binder_p.setup(self).populate() def run(self, tasks): if self.installation_running: self.action_queue += tasks self.context.notify('info', _('Enqueueing package installation')) return self.installation_running = True def callback(): self.installation_running = False if self.action_queue: self.run(self.action_queue) self.action_queue = [] return self.context.notify('info', _('Installation complete!')) self.mgr.do(tasks, callback=callback) @intent('install-package') @restrict('packages:modify') def intent_install(self, package): p = PackageInfo() p.name, p.action = package, 'i' self.run([p]) def on_page_load(self): self.context.endpoint.send_progress(_('Querying package manager')) self.mgr.refresh() self.refresh() @restrict('packages:modify') def on_install(self, package): package.action = 'i' self.pending[package.name] = package self.refresh() @restrict('packages:modify') def on_cancel(self, package): package.action = None if package.name in self.pending: del self.pending[package.name] self.refresh() @restrict('packages:modify') def on_remove(self, package): package.action = 'r' self.pending[package.name] = package self.refresh() @on('get-lists-button', 'click') @restrict('packages:refresh') def on_get_lists(self): self.mgr.get_lists() @on('apply-button', 'click') @restrict('packages:modify') def on_apply(self): self.run(self.pending.values()) self.pending = {} self.refresh() @on('upgrade-all-button', 'click') @restrict('packages:modify') def on_upgrade_all(self): for p in self.mgr.upgradeable: p.action = 'i' self.pending[p.name] = p self.refresh() @on('cancel-all-button', 'click') @restrict('packages:modify') def on_cancel_all(self): self.pending = {} self.refresh() def fill(self, packages): for p in packages: if p.name in self.pending: p.action = self.pending[p.name].action @on('search-button', 'click') def on_search(self): query = self.find('search-box').value results = self.mgr.search(query) if self.binder_s: self.binder_s.unpopulate() if len(results) > 100: self.find('search-counter').text = _('%i found, 100 shown') % len(results) results = results[:100] else: self.find('search-counter').text = _('%i found') % len(results) self.fill(results) self.binder_s = CollectionAutoBinding(results, None, self.find('search')).populate()
class DBPlugin(SectionPlugin): service_name = '' service_buttons = [] has_users = True def init(self): self.append(self.ui.inflate('db_common:main')) self.binder = Binder(None, self) self.find_type('servicebar').buttons = self.service_buttons def delete_db(db, c): self.query_drop(db) self.refresh() self.find('databases').delete_item = delete_db def delete_user(user, c): self.query_drop_user(user) self.refresh() self.find('users').delete_item = delete_user def on_page_load(self): self.refresh() @on('sql-run', 'click') def on_sql_run(self): try: result = self.query_sql( self.find('sql-db').value, self.find('sql-input').value) self.context.notify('info', _('Query finished')) except Exception as e: self.context.notify('error', str(e)) return tbl = self.find('sql-output') tbl.empty() if len(result) > 200: self.context.notify( 'info', _('Output cut from %i rows to 200') % len(result)) result = result[:200] for row in result: erow = self.ui.create('dtr') tbl.append(erow) for cell in row: ecell = self.ui.create('dtd') ecell.append(self.ui.create('label', text=str(cell))) erow.append(ecell) @on('add-db', 'click') def on_add_db(self): self.find('db-name-dialog').value = '' self.find('db-name-dialog').visible = True @on('add-user', 'click') def on_add_user(self): self.find('add-user-dialog').visible = True def refresh(self): self.databases = [] self.users = [] try: self.databases = self.query_databases() if self.has_users: self.users = self.query_users() except Exception as e: import traceback traceback.print_exc() self.context.notify('error', str(e)) if hasattr(self, 'config_class'): self.context.launch('configure-plugin', plugin=self.config_class.get()) return self.binder.unpopulate() self.find('sql-db').labels = self.find('sql-db').values = [ x.name for x in self.databases ] self.binder.setup(self).populate() self.find_type('servicebar').reload() @on('db-name-dialog', 'submit') def on_db_name_dialog_submit(self, value=None): try: self.query_create(value) except Exception as e: self.context.notify('error', str(e)) return self.refresh() @on('add-user-dialog', 'button') def on_add_user_dialog(self, button=None): d = self.find('add-user-dialog') d.visible = False if button == 'ok': u = User() u.name = d.find('name').value u.host = d.find('host').value u.password = d.find('password').value try: self.query_create_user(u) except Exception as e: self.context.notify('error', str(e)) return self.refresh() def query_sql(self, db, sql): raise NotImplementedError() def query_databases(self): raise NotImplementedError() def query_drop(self, db): raise NotImplementedError() def query_create(self, name): raise NotImplementedError() def query_users(self): raise NotImplementedError() def query_create_user(self, user): raise NotImplementedError() def query_drop_user(self, user): raise NotImplementedError()
class Samba(SectionPlugin): def init(self): self.title = 'Samba' self.icon = 'folder-close' self.category = _('Software') self.append(self.ui.inflate('samba:main')) self.find('servicebar').name = platform_select( debian='samba', ubuntu='smbd', centos='smb', default='samba', ) self.find('servicebar').reload() self.binder = Binder(None, self.find('config')) self.find('shares').new_item = lambda c: ShareData() self.config = SambaConfig(path='/etc/samba/smb.conf') def post_item_bind(object, collection, item, ui): ui.find('disconnect').on('click', self.on_disconnect, item) self.find('connections').post_item_bind = post_item_bind def post_user_bind(object, collection, item, ui): def delete_user(): self.usermgr.delete(item.username) self.refresh() ui.find('delete').on('click', delete_user) def set_password(): if self.usermgr.set_password(item.username, ui.find('password').value): self.context.notify('info', _('Password updated')) ui.find('password').value = '' else: self.context.notify('error', _('Password update failed')) ui.find('password-set').on('click', set_password) self.find('user-list').post_item_bind = post_user_bind self.usermgr = SambaUsers() self.binder_u = Binder(self.usermgr, self.find('users')) self.monitor = SambaMonitor() self.binder_m = Binder(self.monitor, self.find('status')) def on_page_load(self): self.refresh() def on_disconnect(self, connection): connection.disconnect() self.refresh() def refresh(self): self.config.load() self.monitor.refresh() self.usermgr.load() self.binder.setup(self.config.tree).populate() self.binder_m.setup(self.monitor).populate() self.binder_u.setup(self.usermgr).populate() users_dropdown = self.find('add-user-list') users = [ x.name for x in PasswdConfig(path='/etc/passwd').load().tree.users ] for u in self.usermgr.users: if u.username in users: users.remove(u.username) users_dropdown.values = users_dropdown.labels = users @on('add-user', 'click') def on_add_user(self): self.usermgr.create(self.find('add-user-list').value) self.refresh() @on('save', 'click') def on_save(self): self.binder.update() self.config.save() self.refresh()
class GitPlugin (SectionPlugin): def init(self): self.title = _('Git') self.icon = 'folder-close' self.category = 'Software' self.append(self.ui.inflate('git:main')) self.binder = Binder(None, self) self.user = None # Find User for user in ['gitolite3', 'gitolite2', 'gitolite']: try: pwn = getpwnam(user) self.user = pwn break except: pass if self.user == None: exit(-1) # Set Conf & Key Directory self.confdir = os.path.join(self.user.pw_dir, '.gitolite/conf/') self.keydir = os.path.join(self.user.pw_dir, '.gitolite/keydir/') # Event for new items self.find('usercollection').new_item = lambda c: User('newuser', '') self.find('repocollection').new_item = lambda c: Repository('newrepo') # Remove old Gitolite.conf and replace our version os.remove(self.confdir + 'gitolite.conf') with open((self.confdir + 'gitolite.conf'), 'w+') as file: file.write('include "*.conf"') def on_page_load(self): self.refresh() def refresh(self): self.refresh_users() self.refresh_repositories() self.binder.setup(self).populate() def reload(self): subprocess.call('su -c "gitolite compile" ' + self.user.pw_name, shell=True) self.context.notify('info', _('Saved')) # # Repositories # def refresh_repositories(self): self.repositories = [] userlist = [] for user in self.users: userlist.append(user.name) self.find('rwusers').values = userlist self.find('rwusers').labels = userlist self.find('rousers').values = userlist self.find('rousers').labels = userlist for file in os.listdir(self.confdir): if os.path.isfile(self.confdir + file) and not 'gitolite.conf' in file: with open(self.confdir + file) as content: content = content.read() repo = Repository('') # Repository Name match = re.search(r'repo[\s]+([A-z0-9]+)', content, re.I) repo.name = match.group(1) #Repository Users(read-write) match = re.search(r'RW\+[\s]+\=[\s]+([^\n]+)', content, re.I) repo.rwusers = match is not None and match.group(1) or '' #Repository Users(read-only) match = re.search(r'R[\s]+\=[\s]+([^\n]+)', content, re.I) repo.rousers = match is not None and match.group(1) or '' self.repositories.append(repo) @on('save-repositories', 'click') def save_repositories(self): self.binder.update() files = [] for file in os.listdir(self.confdir): if os.path.isfile(self.confdir + file) and not "gitolite.conf" in file: files.append(file) for repo in self.repositories: with open((self.confdir + repo.name + '.conf'), 'w+') as file: content = 'repo ' content += repo.name content += '\n' rwusers = repo.rwusers.strip() if len(rwusers) > 0: content += '\tRW+\t=\t' + rwusers + '\n' rousers = repo.rousers.strip() if len(rousers) > 0: content += '\tR\t=\t' + rousers + '\n' file.write(content) if (repo.name + '.conf') in files: files.remove(repo.name + '.conf') for file in files: os.remove(self.confdir + file) self.reload() # # Users # def refresh_users(self): self.users = [] for file in os.listdir(self.keydir): with open(self.keydir + file) as content: username = file.replace('.pub', '') pubkey = content.read() self.users.append(User(username, pubkey)) @on('save-users', 'click') def save_users(self): self.binder.update() files = [] for file in os.listdir(self.keydir): files.append(file) for user in self.users: with open((self.keydir + user.name + '.pub'), 'w+') as file: file.write(user.pubkey) if (user.name + '.pub') in files: files.remove(user.name + '.pub') for file in files: os.remove(self.keydir + file) self.reload();
class FileManager (SectionPlugin): default_classconfig = {'root': '/', 'start': '/'} classconfig_editor = FileManagerConfigEditor classconfig_root = True def init(self): self.title = _('File Manager') self.category = _('Tools') self.icon = 'folder-open' self.backend = FMBackend().get() self.append(self.ui.inflate('fm:main')) self.controller = Controller() def post_item_bind(object, collection, item, ui): ui.find('name').on('click', self.on_item_click, object, item) ui.find('edit').on('click', self.edit, item.fullpath) self.find('items').post_item_bind = post_item_bind def post_bc_bind(object, collection, item, ui): ui.find('name').on('click', self.on_bc_click, object, item) self.find('breadcrumbs').post_item_bind = post_bc_bind self.clipboard = [] self.tabs = self.find('tabs') def on_first_page_load(self): self.new_tab() self.binder = Binder(self.controller, self.find('filemanager')).populate() self.binder_c = Binder(self, self.find('bind-clipboard')).populate() def on_page_load(self): self.refresh() def refresh_clipboard(self): self.binder_c.setup().populate() @on('tabs', 'switch') def on_tab_switch(self): if self.tabs.active == (len(self.controller.tabs) - 1): self.new_tab() self.refresh() @intent('fm:browse') def new_tab(self, path=None): dir = path or self.classconfig.get('start', None) or '/' if not dir.startswith(self.classconfig['root']): dir = self.classconfig['root'] self.controller.new_tab(dir) if not self.active: self.activate() @on('close', 'click') def on_tab_close(self): if len(self.controller.tabs) > 2: self.controller.tabs.pop(self.tabs.active) self.tabs.active = 0 self.refresh() @on('new-file', 'click') def on_new_file(self): destination = self.controller.tabs[self.tabs.active].path logging.info('[fm] new file in %s' % destination) path = os.path.join(destination, 'new file') try: open(path, 'w').close() self._chown_new(path) except OSError as e: self.context.notify('error', str(e)) self.refresh() @on('new-dir', 'click') def on_new_directory(self): destination = self.controller.tabs[self.tabs.active].path logging.info('[fm] new directory in %s' % destination) path = os.path.join(destination, 'new directory') if not os.path.exists(path): try: os.mkdir(path) os.chmod(path, 0755) self._chown_new(path) except OSError as e: self.context.notify('error', str(e)) self.refresh() def _chown_new(self, path): uid = self.classconfig.get('new_owner', 'root') or 'root' gid = self.classconfig.get('new_group', 'root') or 'root' try: uid = int(uid) except: uid = pwd.getpwnam(uid)[2] try: gid = int(gid) except: gid = grp.getgrnam(gid)[2] os.chown(path, uid, gid) def upload(self, name, file): destination = self.controller.tabs[self.tabs.active].path logging.info('[fm] uploading %s to %s' % (name, destination)) try: output = open(os.path.join(destination, name), 'w') while True: data = file.read(1024 * 1024) if not data: break gevent.sleep(0) output.write(data) output.close() except OSError as e: self.context.notify('error', str(e)) self.refresh() @on('mass-cut', 'click') def on_cut(self): l = self._get_checked() for i in l: i.action = 'cut' self.clipboard += l self.refresh_clipboard() @on('mass-copy', 'click') def on_copy(self): l = self._get_checked() for i in l: i.action = 'copy' self.clipboard += l self.refresh_clipboard() @on('mass-delete', 'click') def on_delete(self): def callback(task): self.context.notify('info', _('Files deleted')) self.refresh() self.backend.remove(self._get_checked(), cb=callback) @on('paste', 'click') def on_paste(self): tab = self.controller.tabs[self.tabs.active] for_move = [] for_copy = [] for i in self.clipboard: if i.action == 'cut': for_move.append(i) else: for_copy.append(i) try: if for_move: def callback(task): self.context.notify('info', _('Files moved')) self.refresh() self.backend.move(for_move, tab.path, callback) if for_copy: def callback(task): self.context.notify('info', _('Files copied')) self.refresh() self.backend.copy(for_copy, tab.path, callback) self.clipboard = [] except Exception as e: self.context.notify('error', str(e)) self.refresh_clipboard() @on('select-all', 'click') def on_select_all(self): self.binder.update() tab = self.controller.tabs[self.tabs.active] for item in tab.items: item.checked = not item.checked self.binder.populate() self.context.notify('info', _('Selected %i items') % len(tab.items)) def _get_checked(self): self.binder.update() tab = self.controller.tabs[self.tabs.active] r = [] for item in tab.items: if item.checked: r.append(item) item.checked = False self.refresh() return r @on('clear-clipboard', 'click') def on_clear_clipboard(self): self.clipboard = [] self.refresh_clipboard() def on_item_click(self, tab, item): path = os.path.join(tab.path, item.name) if not os.path.isdir(path): self.edit(path) if not path.startswith(self.classconfig['root']): return tab.navigate(path) self.refresh() def edit(self, path): self.find('dialog').visible = True self.item = Item(path) self.item.read() self.binder_d = Binder(self.item, self.find('dialog')).populate() # Unpack u = Unpacker.find(self.item.fullpath.lower()) unpack_btn = self.find('dialog').find('unpack') unpack_btn.visible = u is not None def cb(): self.context.notify('info', _('Unpacked')) self.refresh() def unpack(): u.unpack(self.item.fullpath, cb=cb) logging.info('[fm] unpacking %s' % self.item.fullpath) unpack_btn.on('click', lambda: unpack()) # Edit edit_btn = self.find('dialog').find('edit') if self.item.size > 1024 * 1024 * 5: edit_btn.visible = False def edit(): self.context.launch('notepad', path=self.item.fullpath) edit_btn.on('click', lambda: edit()) @on('dialog', 'button') def on_close_dialog(self, button): self.find('dialog').visible = False if button == 'save': self.binder_d.update() try: self.item.write() except Exception as e: self.context.notify('error', str(e)) self.refresh() if self.find('chmod-recursive').value: cmd = 'chown -Rv "%s:%s" "%s"; chmod -Rv %o "%s"' % ( self.item.owner, self.item.group, self.item.fullpath, self.item.mode, self.item.fullpath, ) self.context.launch('terminal', command=cmd) logging.info('[fm] modifying %s: %o %s:%s' % (self.item.fullpath, self.item.mode, self.item.owner, self.item.group)) def on_bc_click(self, tab, item): if not item.path.startswith(self.classconfig['root']): return tab.navigate(item.path) self.refresh() def refresh(self, _=None): for tab in self.controller.tabs: tab.refresh() self.binder.populate()
class MailPlugin(SectionPlugin): def init(self): self.title = _('Mail') self.icon = 'envelope' self.category = 'Web' self.manager = MailManager.get() if not self.manager.is_configured: self.append(self.ui.inflate('vh-mail:not-configured')) else: self.post_init() @on('initial-enable', 'click') def on_initial_enable(self): self.post_init() self.manager.save() self.refresh() def post_init(self): self.empty() self.append(self.ui.inflate('vh-mail:main')) self.binder = Binder(None, self) def post_mb_bind(object, collection, item, ui): ui.find('size').text = str_fsize(self.manager.get_usage(item)) def post_mb_update(object, collection, item, ui): if ui.find('password').value: item.password = ui.find('password').value self.find('mailboxes').post_item_bind = post_mb_bind self.find('mailboxes').post_item_update = post_mb_update self.binder.setup(self.manager.config) @on('new-mailbox', 'click') def on_new_mailbox(self): self.binder.update() mb = Mailbox.create() mb.local = self.find('new-mailbox-local').value mb.domain = self.find('new-mailbox-domain').value or self.find( 'new-mailbox-domain-custom').value mb.password = '' self.find('new-mailbox-local').value = '' if not mb.local: self.context.error(_('Invalid mailbox name')) if not mb.domain: self.context.error(_('Invalid mailbox domain')) self.manager.config.mailboxes.append(mb) self.manager.save() self.binder.populate() def on_page_load(self): self.refresh() def refresh(self): domains = [] for ws in VHManager.get().config.websites: domains += [d.domain for d in ws.domains] domains = sorted(list(set(domains))) self.find('new-mailbox-domain').labels = domains + [_('Custom domain')] self.find('new-mailbox-domain').values = domains + [None] if self.manager.is_configured: self.binder.unpopulate().populate() @on('save', 'click') def save(self): self.binder.update() self.manager.save() self.refresh() self.context.notify('info', _('Saved'))
class FileManager(SectionPlugin): default_classconfig = {'root': '/'} classconfig_editor = FileManagerConfigEditor classconfig_root = True def init(self): self.title = _('File Manager') self.category = _('Tools') self.icon = 'folder-open' self.backend = FMBackend().get() self.append(self.ui.inflate('fm:main')) self.controller = Controller() def post_item_bind(object, collection, item, ui): ui.find('name').on('click', self.on_item_click, object, item) ui.find('edit').on('click', self.edit, item.fullpath) self.find('items').post_item_bind = post_item_bind def post_bc_bind(object, collection, item, ui): ui.find('name').on('click', self.on_bc_click, object, item) self.find('breadcrumbs').post_item_bind = post_bc_bind self.clipboard = [] self.tabs = self.find('tabs') def on_first_page_load(self): self.controller.new_tab(self.classconfig['root']) self.binder = Binder( self.controller, self.find('filemanager')).autodiscover().populate() self.binder_c = Binder( self, self.find('bind-clipboard')).autodiscover().populate() def refresh_clipboard(self): self.binder_c.reset().autodiscover().populate() @on('tabs', 'switch') def on_tab_switch(self): if self.tabs.active == (len(self.controller.tabs) - 1): self.controller.new_tab(self.classconfig['root']) self.refresh() @on('close', 'click') def on_tab_close(self): if len(self.controller.tabs) > 2: self.controller.tabs.pop(self.tabs.active) self.tabs.active = 0 self.refresh() @on('new-file', 'click') def on_new_file(self): open( os.path.join(self.controller.tabs[self.tabs.active].path, 'new file'), 'w').close() self.refresh() def upload(self, name, file): open(os.path.join(self.controller.tabs[self.tabs.active].path, name), 'w').write(file.read()) self.refresh() @on('new-dir', 'click') def on_new_directory(self): path = os.path.join(self.controller.tabs[self.tabs.active].path, 'new directory') if not os.path.exists(path): os.mkdir(path) self.refresh() @on('mass-cut', 'click') def on_cut(self): l = self._get_checked() for i in l: i.action = 'cut' self.clipboard += l self.refresh_clipboard() @on('mass-copy', 'click') def on_copy(self): l = self._get_checked() for i in l: i.action = 'copy' self.clipboard += l self.refresh_clipboard() @on('mass-delete', 'click') def on_delete(self): self.backend.remove(self._get_checked()) self.refresh() @on('paste', 'click') def on_paste(self): tab = self.controller.tabs[self.tabs.active] for_move = [] for_copy = [] for i in self.clipboard: if i.action == 'cut': for_move.append(i) else: for_copy.append(i) try: if for_move: self.backend.move(for_move, tab.path) if for_copy: self.backend.copy(for_copy, tab.path) self.clipboard = [] except Exception as e: self.context.notify('error', str(e)) self.refresh_clipboard() self.refresh() @on('select-all', 'click') def on_select_all(self): self.binder.update() tab = self.controller.tabs[self.tabs.active] for item in tab.items: item.checked = True self.binder.populate() self.context.notify('info', _('Selected %i items') % len(tab.items)) def _get_checked(self): self.binder.update() tab = self.controller.tabs[self.tabs.active] r = [] for item in tab.items: if item.checked: r.append(item) item.checked = False self.refresh() return r @on('clear-clipboard', 'click') def on_clear_clipboard(self): self.clipboard = [] self.refresh_clipboard() def on_item_click(self, tab, item): path = os.path.join(tab.path, item.name) if not os.path.isdir(path): self.edit(path) if not path.startswith(self.classconfig['root']): return tab.navigate(path) self.refresh() def edit(self, path): self.find('dialog').visible = True self.item = Item(path) self.item.read() self.binder_d = Binder(self.item, self.find('dialog')).autodiscover().populate() @on('dialog', 'button') def on_close_dialog(self, button): self.find('dialog').visible = False if button == 'save': self.binder_d.update() self.item.write() self.refresh() if self.find('chmod-recursive').value: cmd = 'chown -Rv "%s:%s" "%s"; chmod -Rv %o "%s"' % ( self.item.owner, self.item.group, self.item.fullpath, self.item.mode, self.item.fullpath, ) self.context.launch('terminal', command=cmd) def on_bc_click(self, tab, item): if not item.path.startswith(self.classconfig['root']): return tab.navigate(item.path) self.refresh() def refresh(self): for tab in self.controller.tabs: tab.refresh() self.binder.populate()
def init(self): self.title = _('Configure') self.icon = 'wrench' self.category = '' self.order = 50 self.append(self.ui.inflate('configurator:main')) self.binder = Binder(ajenti.config.tree, self.find('ajenti-config')) self.ccmgr = ClassConfigManager.get() if Licensing.licensing_active: self.find('licensing').append(LicensingUI.new(self.ui)) else: self.find('licensing').delete() self.classconfig_binding = Binder(self.ccmgr, self.find('classconfigs')) def post_classconfig_bind(object, collection, item, ui): def configure(): self.configure_plugin(item, notify=False) ui.find('configure').on('click', configure) self.find('classconfigs').find('classes') \ .post_item_bind = post_classconfig_bind self.find('users').new_item = lambda c: UserData() def post_user_bind(object, collection, item, ui): provider = UserManager.get().get_sync_provider() editable = item.name != 'root' renameable = editable and provider.allows_renaming deletable = renameable ui.find('name-edit').visible = renameable ui.find('name-label').visible = not renameable ui.find('delete').visible = deletable box = ui.find('permissions') box.empty() p = PermissionProvider.get_all() for prov in p: line = self.ui.create('tab', title=prov.get_name()) box.append(line) for perm in prov.get_permissions(): line.append( self.ui.create('checkbox', id=perm[0], text=perm[1], value=(perm[0] in item.permissions))) def copy(): self.save() newuser = deepcopy(item) newuser.name += '_' collection[newuser.name] = newuser self.refresh() ui.find('copy').on('click', copy) self.find('users').post_item_bind = post_user_bind def post_user_update(object, collection, item, ui): box = ui.find('permissions') for prov in PermissionProvider.get_all(): for perm in prov.get_permissions(): has = box.find(perm[0]).value if has and not perm[0] in item.permissions: item.permissions.append(perm[0]) if not has and perm[0] in item.permissions: item.permissions.remove(perm[0]) if ui.find('password').value: item.password = ui.find('password').value self.find('users').post_item_update = post_user_update
class LetsEncryptPlugin(SectionPlugin): pwd = os.path.join(os.path.dirname(os.path.realpath(__file__)), '') nginx_config_dir = platform_select( debian='/etc/nginx.custom.d', centos='/etc/nginx.custom.d', mageia='/etc/nginx.custom.d', freebsd='/usr/local/etc/nginx.custom.d', arch='/etc/nginx/sites-available', osx='/opt/local/etc/nginx', ) crontab_dir = platform_select( debian='/etc/cron.d', centos='/etc/cron.d', mageia='/etc/cron.d', freebsd='/usr/local/etc/cron.d', arch='/etc/cron.d', osx='/opt/local/etc/cron.d', ) has_domains = False def init(self): self.title = 'LetsEncrypt' # those are not class attributes and can be only set in or after init() self.icon = 'lock' self.category = 'Security' """ UI Inflater searches for the named XML layout and inflates it into an UIElement object tree """ self.append(self.ui.inflate('letsencrypt:main')) self.settings = Settings() self.binder = Binder(self.settings, self) self.binder.populate() def on_page_load(self): filepath = self.settings.basedir + self.settings.domainfile domains = '' if os.path.isfile(filepath): domains = os.linesep.join(self.read_domain_file()) cron = self.check_cron() self.find('domains').value = str(domains) self.find('cronjob').value = cron def write_domain_file(self): filepath = self.settings.basedir + self.settings.domainfile if not self.find('domains').value: self.context.notify('info', 'No domains specified') self.has_domains = False return file = open(filepath, 'w') if file.write(self.find('domains').value) is None: self.has_domains = True else: self.context.notify('error', 'Domain file write error') file.close() def read_domain_file(self): filepath = self.settings.basedir + self.settings.domainfile if not open(filepath): self.context.notify('error', 'Domain file could not be read') file = open(filepath) with file as f: lines = f.readlines() return lines def create_folders(self): uid = pwd.getpwnam("www-data").pw_uid gid = grp.getgrnam("www-data").gr_gid if not os.path.exists(self.settings.basedir): os.makedirs(self.settings.basedir) os.chown(self.settings.basedir, uid, gid) if not os.path.exists(self.settings.wellknown): os.makedirs(self.settings.wellknown) os.chown(self.settings.wellknown, uid, gid) def create_custom_config(self): template = """ BASEDIR=$basedir WELLKNOWN=$wellknown """ dict = { 'basedir': self.settings.basedir, 'wellknown': self.settings.wellknown } filename = 'config' filepath = self.settings.basedir + filename file = open(filepath, 'w') src = Template(template) if file.write(src.safe_substitute(dict)) is not None: self.context.notify('info', 'Letsencrypt error') file.close() def create_wellknown(self): if not self.check_nginx_custom_dir(): return False template = """ server { server_name $domains; listen *:80; location $location { alias $alias; } } """ dict = { 'location': '/.well-known/acme-challenge', 'alias': self.settings.wellknown, 'domains': " ".join(self.read_domain_file()) } filepath = self.nginx_config_dir + '/' + self.settings.nginx_config file = open(filepath, 'w') src = Template(template) if file.write(src.safe_substitute(dict)) is not None: self.context.notify('info', 'WELLKNOWN config write error') file.close() def create_cron(self): file = open(self.crontab_dir + '/' + self.settings.cronfile, 'w') template = "0 0 1 * * " + self.pwd + 'libs/letsencrypt.sh/letsencrypt.sh -c' if not file.write(template): self.context.notify('info', 'Cron job error') file.close() def remove_cron(self): if os.path.isfile(self.crontab_dir + '/' + self.settings.cronfile): if os.remove(self.crontab_dir + '/' + self.settings.cronfile): return True else: self.context.notify('info', 'Cron remove error') return False def check_cron(self): if os.path.isfile(self.crontab_dir + '/' + self.settings.cronfile): return True return False def check_nginx_custom_dir(self): if not os.path.isdir(self.nginx_config_dir): if os.makedirs(self.nginx_config_dir): return True else: self.context.notify('error', 'NGINX custom dir write error') return False def request_certificates(self): params = [self.pwd + 'libs/letsencrypt.sh/letsencrypt.sh', '-c'] if self.find('renewal').value: params.append('--force') p = subprocess.Popen(params, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = p.communicate() if out: self.context.notify('info', 'OUT: ' + out) if err: self.context.notify('info', 'ERR: ' + err) def save(self): self.binder.update() self.binder.populate() self.create_folders() self.write_domain_file() if not self.has_domains: return self.create_custom_config() self.create_wellknown() if self.settings.cronjob: self.create_cron() else: self.remove_cron() @on('save', 'click') def save_button(self): self.save() @on('request', 'click') def request_button(self): self.save() self.request_certificates()
class Configurator(SectionPlugin): def init(self): self.title = _('Configure') self.icon = 'wrench' self.category = '' self.order = 50 self.append(self.ui.inflate('configurator:main')) self.binder = Binder(ajenti.config.tree, self.find('ajenti-config')) self.ccmgr = ClassConfigManager.get() if Licensing.licensing_active: self.find('licensing').append(LicensingUI.new(self.ui)) else: self.find('licensing').delete() self.classconfig_binding = Binder(self.ccmgr, self.find('classconfigs')) def post_classconfig_bind(object, collection, item, ui): def configure(): self.configure_plugin(item, notify=False) ui.find('configure').on('click', configure) self.find('classconfigs').find('classes') \ .post_item_bind = post_classconfig_bind self.find('users').new_item = lambda c: UserData() def post_user_bind(object, collection, item, ui): provider = UserManager.get().get_sync_provider() editable = item.name != 'root' renameable = editable and provider.allows_renaming deletable = renameable ui.find('name-edit').visible = renameable ui.find('name-label').visible = not renameable ui.find('delete').visible = deletable box = ui.find('permissions') box.empty() p = PermissionProvider.get_all() for prov in p: line = self.ui.create('tab', title=prov.get_name()) box.append(line) for perm in prov.get_permissions(): line.append( self.ui.create('checkbox', id=perm[0], text=perm[1], value=(perm[0] in item.permissions))) def copy(): self.save() newuser = deepcopy(item) newuser.name += '_' collection[newuser.name] = newuser self.refresh() ui.find('copy').on('click', copy) self.find('users').post_item_bind = post_user_bind def post_user_update(object, collection, item, ui): box = ui.find('permissions') for prov in PermissionProvider.get_all(): for perm in prov.get_permissions(): has = box.find(perm[0]).value if has and not perm[0] in item.permissions: item.permissions.append(perm[0]) if not has and perm[0] in item.permissions: item.permissions.remove(perm[0]) if ui.find('password').value: item.password = ui.find('password').value self.find('users').post_item_update = post_user_update def on_page_load(self): self.refresh() @on('sync-users-button', 'click') def on_sync_users(self): self.save() prov = UserManager.get().get_sync_provider() try: prov.test() prov.sync() except Exception as e: self.context.notify('error', str(e)) self.refresh() @on('configure-sync-button', 'click') def on_configure_sync(self): self.save() if UserManager.get().get_sync_provider( ).classconfig_editor is not None: self.configure_plugin(UserManager.get().get_sync_provider(), notify=False) self.refresh() def refresh(self): self.binder.unpopulate() self.find('sync-providers').labels = [ x.title for x in UserSyncProvider.get_classes() ] self.find('sync-providers').values = [ x.id for x in UserSyncProvider.get_classes() ] provider = UserManager.get().get_sync_provider() self.find('sync-providers').value = provider.id self.find('users-dt').addrow = _('Add') if provider.id == '' else None self.find('sync-users-button').visible = provider.id != '' self.find('password').visible = provider.id == '' self.find('configure-sync-button').visible = \ provider.classconfig_editor is not None try: provider.test() sync_ok = True except Exception as e: self.context.notify('error', str(e)) sync_ok = False self.find('sync-status-ok').visible = sync_ok self.find('sync-status-fail').visible = not sync_ok languages = sorted(ajenti.locales.list_locales()) self.find('language').labels = [_('Auto'), 'en_US'] + languages self.find('language').values = ['', 'en_US'] + languages self.binder.setup().populate() self.ccmgr.reload() self.classconfig_binding.setup().populate() @on('save-button', 'click') @restrict('configurator:configure') def save(self): self.binder.update() UserManager.get().set_sync_provider(self.find('sync-providers').value) UserManager.get().hash_passwords() self.refresh() ajenti.config.save() self.context.notify( 'info', _('Saved. Please restart Ajenti for changes to take effect.')) @on('fake-ssl', 'click') def on_gen_ssl(self): host = self.find('fake-ssl-host').value if host == '': self.context.notify('error', _('Please supply hostname')) else: self.gen_ssl(host) @on('restart-button', 'click') def on_restart(self): ajenti.restart() @intent('configure-plugin') def configure_plugin(self, plugin=None, notify=True): self.find('tabs').active = 1 self.refresh() if plugin and notify: self.context.notify( 'info', _('Please configure %s plugin!') % plugin.classconfig_editor.title) self.activate() dialog = self.find('classconfigs').find('dialog') dialog.find('container').empty() dialog.visible = True editor = plugin.classconfig_editor.new(self.ui) dialog.find('container').append(editor) if editor.find('bind'): logging.warn('%s uses old dictbinding classconfig editor layout') binder = DictAutoBinding(plugin, 'classconfig', editor.find('bind')) else: binder = Binder(plugin, editor) binder.populate() def save(button=None): dialog.visible = False binder.update() plugin.save_classconfig() self.save() dialog.on('button', save) @intent('setup-fake-ssl') def gen_ssl(self, host): self.save() subprocess.call(['ajenti-ssl-gen', host, '-f']) ajenti.config.load() self.refresh()
def init(self): self.append(self.ui.inflate('vh-mysql:ext')) self.binder = Binder(self, self) self.refresh() self.db = MySQLDB.get()
class WebserverPlugin (SectionPlugin): service_name = '' service_buttons = [] hosts_available_dir = '' hosts_enabled_dir = '' template = '' supports_host_activation = True def log(self, msg): logging.info('[%s] %s' % (self.service_name, msg)) def init(self): self.append(self.ui.inflate('webserver_common:main')) self.binder = Binder(None, self) self.find_type('servicebar').buttons = self.service_buttons self.hosts_dir = AvailabilitySymlinks( self.hosts_available_dir, self.hosts_enabled_dir, self.supports_host_activation ) def delete_host(host, c): self.log('removed host %s' % host.name) c.remove(host) self.hosts_dir.delete(host.name) def on_host_bind(o, c, host, u): host.__old_name = host.name def on_host_update(o, c, host, u): if host.__old_name != host.name: self.log('renamed host %s to %s' % (host.__old_name, host.name)) self.hosts_dir.rename(host.__old_name, host.name) host.save() def new_host(c): name = 'untitled' while os.path.exists(self.hosts_dir.get_path(name)): name += '_' self.log('created host %s' % name) self.hosts_dir.open(name, 'w').write(self.template) return WebserverHost(self, self.hosts_dir, name) self.find('hosts').delete_item = delete_host self.find('hosts').new_item = new_host self.find('hosts').post_item_bind = on_host_bind self.find('hosts').post_item_update = on_host_update self.find('header-active-checkbox').visible = \ self.find('body-active-line').visible = \ self.supports_host_activation def on_page_load(self): self.refresh() @on('save-button', 'click') def save(self): self.log('saving hosts') self.binder.update() self.refresh() self.context.notify('info', 'Saved') def refresh(self): self.hosts = [WebserverHost(self, self.hosts_dir, x) for x in self.hosts_dir.list_available()] self.binder.setup(self).populate() self.find_type('servicebar').reload()
class MySQLExtension(BaseExtension): default_config = { 'databases': [], 'users': [], } name = 'MySQL' def init(self): self.append(self.ui.inflate('vh-mysql:ext')) self.binder = Binder(self, self) self.refresh() self.db = MySQLDB.get() @staticmethod def selftest(): try: MySQLDB.get().query_databases() except: pass def refresh(self): if not 'databases' in self.config: if self.config['created']: self.config['databases'] = [{ 'name': self.config['name'], }] self.config['users'] = [{ 'name': self.config['user'], 'password': self.config['password'], }] else: self.config['databases'] = [] self.config['users'] = [] del self.config['created'] del self.config['name'] del self.config['user'] del self.config['password'] def post_db_bind(object, collection, item, ui): ui.find('detach').on('click', self.on_detach_db, item) self.find('databases').post_item_bind = post_db_bind def post_user_bind(object, collection, item, ui): ui.find('detach').on('click', self.on_detach_user, item) self.find('users').post_item_bind = post_user_bind self.binder.setup().populate() self.find('db-name').value = self.website.slug self.find('db-username').value = self.website.slug self.find('db-password').value = str(uuid.uuid4()) self.find('databases').delete_item = lambda i, c: self.on_delete_db(i) self.find('users').delete_item = lambda i, c: self.on_delete_user(i) def update(self): self.binder.update() def on_destroy(self): pass @on('create-db', 'click') def on_create_db(self): try: self.db.query_databases() except Exception, e: self.context.notify('error', str(e)) self.context.launch('configure-plugin', plugin=self.db) return dbname = self.find('db-name').value for db in self.db.query_databases(): if db.name == dbname: self.context.notify('error', _('This database name is already used')) return db_cfg = {'name': dbname} try: self.db.query_create(db_cfg['name']) except Exception, e: self.context.notify('error', str(e)) return
def init(self): self.append(self.ui.inflate('network:bit-linux-ifupdown')) self.binder = Binder(None, self)
class NetworkPlugin(SectionPlugin): platforms = ['debian', 'centos'] def init(self): self.title = _('Network') self.icon = 'globe' self.category = _('System') self.net_config = INetworkConfig.get() self.append(self.ui.inflate('network:main')) def post_interface_bind(o, c, i, u): i.add_bits(self.ui) for bit in i.bits: u.find('bits').append( self.ui.create( 'tab', children=[bit], title=bit.title, )) u.find('up').on('click', self.on_up, i) u.find('down').on('click', self.on_down, i) u.find('restart').on('click', self.on_restart, i) def post_interface_update(o, c, i, u): for bit in i.bits: bit.apply() self.find('interfaces').post_item_bind = post_interface_bind self.find('interfaces').post_item_update = post_interface_update self.binder = Binder(self.net_config, self) def on_page_load(self): self.refresh() def refresh(self): self.net_config.rescan() sensor = Sensor.find('traffic') for i in self.net_config.interface_list: i.tx, i.rx = sensor.value(i.name) self.binder.reset().autodiscover().populate() return def on_up(self, iface=None): self.save() self.net_config.up(iface) self.refresh() def on_down(self, iface=None): self.save() self.net_config.down(iface) self.refresh() def on_restart(self, iface=None): self.save() self.on_down(iface) self.on_up(iface) @on('save', 'click') def save(self): self.binder.update() self.net_config.save() self.refresh() self.context.notify('info', _('Saved'))
class NTPDPlugin(SectionPlugin): def get_tz_debian(self): return open('/etc/timezone').read().strip() def get_tz_nondebian(self): return os.path.realpath( '/etc/localtime')[len('/usr/share/zoneinfo/'):] if os.path.islink( '/etc/localtime') else '' def set_tz_debian(self, timezone): open('/etc/timezone', 'w').write(timezone + '\n') def set_tz_nondebian(self, timezone): tz = os.path.join('/usr/share/zoneinfo/', timezone) if os.path.exists('/etc/localtime'): os.unlink('/etc/localtime') os.symlink(tz, '/etc/localtime') openntpd = isopenntpd() service_name = platform_select( default='openntpd' if openntpd else 'ntp', centos='openntpd' if openntpd else 'ntpd', mageia='ntpd', ) get_tz = platform_select( debian=get_tz_debian, default=get_tz_nondebian, ) set_tz = platform_select( debian=set_tz_debian, default=set_tz_nondebian, ) def init(self): self.title = _('Date & Time') self.icon = 'time' self.category = _('System') self.append(self.ui.inflate('ntpd:main')) self.find('servicebar').name = self.service_name self.find('servicebar').reload() self.config = NTPDConfig(path=platform_select( default=open_ntpd_conf if self.openntpd else ntpd_conf, centos='/usr/local/etc/ntpd.conf' if self.openntpd else ntpd_conf, freebsd='/usr/local/etc/ntpd.conf' if self.openntpd else ntpd_conf, )) self.binder = Binder(None, self) self.available_zones = [] for d, dirs, files in os.walk('/usr/share/zoneinfo', followlinks=False): for f in files: if f != 'zone.tab': self.available_zones.append(os.path.join(d, f)) self.available_zones = [ x[len('/usr/share/zoneinfo/'):] for x in self.available_zones ] self.available_zones.sort() self.find('servers').new_item = lambda c: ServerData() def on_page_load(self): self.refresh() def refresh(self): self.config.load() self.now = int(time.time()) self.timezone = self.get_tz() self.binder.setup(self).populate() @on('set', 'click') def on_set(self): self.binder.update() d = datetime.fromtimestamp(self.now) s = d.strftime('%m%d%H%M%Y') self.set_tz(self.timezone) subprocess.call(['date', s]) self.refresh() @on('sync', 'click') def on_sync(self): self.binder.update() if len(self.config.tree.servers) == 0: self.context.notify('error', _('No servers defined')) return server = self.config.tree.servers[0].address output = subprocess.check_output(['ntpdate', '-u', server]) self.context.notify('info', _('Done')) self.context.notify('info', output) self.refresh() @on('save', 'click') def save(self): self.binder.update() self.config.save() self.refresh() self.context.notify('info', _('Saved')) ServiceMultiplexor.get().get_one(self.service_name).restart()
class fail2ban(SectionPlugin): def init(self): self.title = 'fail2ban' self.icon = 'shield' self.category = _('Software') self.f2b_v = subprocess.check_output(['fail2ban-client', '--version']).splitlines()[0] self.append(self.ui.inflate('fail2ban:main')) self.binder = Binder(self, self) self.update_status = True def on_config_update(o, c, config, u): if config.__old_name != config.name: if os.path.exists(os.path.join(c.path, config.name)): self.context.notify('error', _( 'File with name {0} already exists in {1}.').format(config.name, c.path)) self.update_status = False config.name = config.__old_name return logging.debug('renamed config file %s to %s' % (config.__old_name, config.name)) os.unlink(config.configfile) config.save() self.update_status = True def on_config_bind(o, c, config, u): config.__old_name = config.name def new_config(c): new_fn = 'untitled{0}.conf' s_fn = new_fn.format('') filename = os.path.join(c.path, s_fn) i = 1 while os.path.exists(filename): s_fn = new_fn.format('_' + str(i)) filename = os.path.join(c.path, s_fn) i += 1 try: logging.debug('add config %s' % filename) conf = f2b_Config(s_fn, c.path) conf.config = config_templates[c.type] return conf.save() except IOError as e: print('Error writing file {0} in {1}'.format(filename, c.path)) def delete_config(config, c): filename = config.configfile logging.debug('removed config %s' % config.configfile) c.remove(config) os.unlink(filename) self.find('configlist').post_item_update = on_config_update self.find('configlist').post_item_bind = on_config_bind self.find('configlist').new_item = new_config self.find('configlist').delete_item = delete_config def on_page_load(self): self.refresh() def refresh(self): self.configurations = [ f2b_Configs(k, d).update() for k, d in config_dirs.iteritems() if os.path.isdir(d) ] self.binder.setup(self).populate() @on('save-button', 'click') def save(self): self.binder.update() if self.update_status: self.context.notify('info', _('Saved')) self.update_status = True self.binder.setup(self).populate() @on('check-regex', 'click') def check_regex(self): self.find('check-status').text = '' log_fname = self.find('log-filename').value filter_fname = self.find('filter-filename').value log_as_text = self.find('log-file').value filter_as_text = self.find('filter-file').value if not (log_fname or log_as_text) or not (filter_fname or filter_as_text): logging.debug('Filter checker. Some parameters are empty.') self.context.notify('error', _('Some parameters are empty.')) return with open(filter_fname + '.tmp', 'w') as rt: rt.write(self.find('filter-file').value) rt_name = rt.name rt.close() p = subprocess.Popen(['fail2ban-regex', '--full-traceback', log_fname, rt_name], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) out, err = p.communicate() self.find('check-status').text = out os.unlink(rt_name) @on('open-filter-button', 'click') def open_filter(self): self.find('openfilterdialog').show() @on('openfilterdialog', 'button') def on_open_filter_dialog(self, button): self.find('openfilterdialog').visible = False @on('openfilterdialog', 'select') def on_filter_file_select(self, path=None): if not path: return self.find('openfilterdialog').visible = False self.find('filter-filename').value = path self.find('filter-file').value = ''.join(open(path).readlines()) @on('open-log-button', 'click') def open_log(self): self.find('openlogdialog').show() @on('openlogdialog', 'button') def on_open_log_dialog(self, button): self.find('openlogdialog').visible = False @on('openlogdialog', 'select') def on_log_file_select(self, path=None): if not path: return self.find('openlogdialog').visible = False self.find('log-filename').value = path self.find('log-file').value = ''.join(open(path).readlines()) @on('save-filter-button', 'click') def save_filter(self): try: open(self.find('filter-filename').value, 'w').write(self.find('filter-file').value) except IOError as e: self.context.notify('error', _('Could not save config file. %s') % str(e)) logging.error(e.message)
class Firewall (SectionPlugin): def init(self): self.title = 'Firewall' self.icon = 'fire' self.category = 'System' self.append(self.ui.inflate('iptables:main')) self.fw_mgr = FirewallManager.get() self.config = IPTablesConfig(path=self.fw_mgr.config_path) self.binder = Binder(None, self.find('config')) self.find('tables').new_item = lambda c: TableData() self.find('chains').new_item = lambda c: ChainData() self.find('rules').new_item = lambda c: RuleData() self.find('options').new_item = lambda c: OptionData() self.find('options').binding = OptionsBinding self.find('options').filter = lambda i: not i.name in ['j', 'jump'] def post_rule_bind(o, c, i, u): u.find('add-option').on('change', self.on_add_option, c, i, u) actions = ['ACCEPT', 'DROP', 'REJECT', 'LOG', 'MASQUERADE', 'DNAT', 'SNAT'] + \ list(set(itertools.chain.from_iterable([[c.name for c in t.chains] for t in self.config.tree.tables]))) u.find('action-select').labels = actions u.find('action-select').values = actions action = '' j_option = i.get_option('j', 'jump') if j_option: action = j_option.arguments[0].value u.find('action').text = action u.find('action').style = 'iptables-action iptables-%s' % action u.find('action-select').value = action def post_rule_update(o, c, i, u): action = u.find('action-select').value j_option = i.get_option('j', 'jump') if j_option: j_option.arguments[0].value = action else: o = OptionData.create_destination() o.arguments[0].value = action i.options.append(o) self.find('rules').post_item_bind = post_rule_bind self.find('rules').post_item_update = post_rule_update self.find('add-option').values = self.find('add-option').labels = ['Add option'] + sorted(OptionData.templates.keys()) def on_page_load(self): if not os.path.exists(self.fw_mgr.config_path): subprocess.call('iptables-save > %s' % self.fw_mgr.config_path, shell=True) self.config.load() self.refresh() def refresh(self): self.binder.reset(self.config.tree).autodiscover().populate() self.find('autostart').text = ('Disable' if self.fw_mgr.get_autostart_state() else 'Enable') + ' autostart' @on('autostart', 'click') def on_autostart_change(self): self.fw_mgr.set_autostart_state(not self.fw_mgr.get_autostart_state()) self.refresh() def on_add_option(self, options, rule, ui): o = OptionData.create(ui.find('add-option').value) ui.find('add-option').value = '' rule.options.append(o) self.binder.populate() @on('save', 'click') def save(self): self.binder.update() self.config.save() self.refresh() @on('edit', 'click') def raw_edit(self): self.context.launch('notepad', path='/etc/iptables.up.rules') @on('apply', 'click') def apply(self): self.save() cmd = 'cat /etc/iptables.up.rules | iptables-restore' if subprocess.call(cmd, shell=True) != 0: self.context.launch('terminal', command=cmd) else: self.context.notify('info', 'Saved')
class CTDB(SectionPlugin): nodes_file = '/etc/ctdb/nodes' addresses_file = '/etc/ctdb/public_addresses' def init(self): self.title = _('Samba Cluster') self.icon = 'folder-close' self.category = _('Software') self.append(self.ui.inflate('ctdb:main')) self.config_path = { 'debian': '/etc/default/ctdb', 'centos': '/etc/sysconfig/ctdb', 'mageia': '/etc/sysconfig/ctdb' }[ajenti.platform] self.config = CTDBConfig(path=self.config_path) self.config.load() self.binder = Binder(None, self.find('main-config')) self.n_binder = Binder(None, self.find('nodes-config')) self.a_binder = Binder(None, self.find('addresses-config')) self.find('nodes').new_item = lambda c: NodeData() self.find('addresses').new_item = lambda c: self.new_address() def new_address(self): a = PublicAddressData() a.address = '192.168.0.1/24' return a def on_page_load(self): n_path = self.config.tree.nodes_file self.nodes_config = CTDBNodesConfig(path=n_path) if not os.path.exists(n_path): open(n_path, 'w').close() self.nodes_config.load() a_path = self.config.tree.public_addresses_file self.addresses_config = CTDBPublicAddressesConfig(path=a_path) if not os.path.exists(a_path): open(a_path, 'w').close() self.addresses_config.load() self.config.load() self.binder.setup(self.config.tree).populate() self.n_binder.setup(self.nodes_config.tree).populate() self.a_binder.setup(self.addresses_config.tree).populate() self.refresh() @on('refresh', 'click') def refresh(self): try: self.find('status').value = subprocess.check_output( ['ctdb', 'status']) self.find('status-ip').value = subprocess.check_output( ['ctdb', 'ip']) except: self.find('status').value = _('Failed to obtain CTDB status') @on('save', 'click') def save(self): self.binder.update() self.n_binder.update() self.a_binder.update() self.config.save() self.nodes_config.save() self.addresses_config.save() self.context.notify('info', _('Saved'))
class Configurator(SectionPlugin): def init(self): self.title = _('Configure') self.icon = 'wrench' self.category = '' self.order = 50 self.append(self.ui.inflate('configurator:main')) self.binder = Binder(ajenti.config.tree, self.find('ajenti-config')) self.ccmgr = ClassConfigManager.get() self.classconfig_binding = Binder(self.ccmgr, self.find('classconfigs')) self.classconfig_rows = {} def post_classconfig_bind(object, collection, item, ui): self.classconfig_rows[item] = ui editor = item.classconfig_editor.new(self.ui) ui.find('container').append(editor) binder = DictAutoBinding(item, 'classconfig', editor.find('bind')) binder.populate() def save(): binder.update() item.save_classconfig() self.context.notify('info', _('Saved')) ui.find('save').on('click', save) self.find('classconfigs').find( 'classes').post_item_bind = post_classconfig_bind self.find('users').new_item = lambda c: UserData() def post_user_bind(object, collection, item, ui): box = ui.find('permissions') box.empty() ui.find('name-edit').visible = item.name != 'root' ui.find('name-label').visible = item.name == 'root' for prov in PermissionProvider.get_all(): line = self.ui.create('tab', title=prov.get_name()) box.append(line) for perm in prov.get_permissions(): line.append( self.ui.create('checkbox', id=perm[0], text=perm[1], value=(perm[0] in item.permissions))) self.find('users').post_item_bind = post_user_bind def post_user_update(object, collection, item, ui): box = ui.find('permissions') for prov in PermissionProvider.get_all(): for perm in prov.get_permissions(): has = box.find(perm[0]).value if has and not perm[0] in item.permissions: item.permissions.append(perm[0]) if not has and perm[0] in item.permissions: item.permissions.remove(perm[0]) if ui.find('password').value: item.password = ui.find('password').value self.find('users').post_item_update = post_user_update def on_page_load(self): self.refresh() def refresh(self): self.binder.reset().autodiscover().populate() self.ccmgr.reload() self.classconfig_binding.reset().autodiscover().populate() @on('save-button', 'click') @restrict('configurator:configure') def save(self): self.binder.update() for user in ajenti.config.tree.users.values(): if not '|' in user.password: user.password = UserManager.get().hash_password(user.password) self.binder.populate() ajenti.config.save() self.context.notify( 'info', _('Saved. Please restart Ajenti for changes to take effect.')) @on('fake-ssl', 'click') def on_gen_ssl(self): host = self.find('fake-ssl-host').value if host == '': self.context.notify('error', _('Please supply hostname')) else: self.gen_ssl(host) @on('restart-button', 'click') def on_restart(self): ajenti.restart() @intent('configure-plugin') def configure_plugin(self, plugin=None): self.find('tabs').active = 1 self.refresh() #if plugin in self.classconfig_rows: # self.classconfig_rows[plugin].children[0].expanded = True # print self.classconfig_rows[plugin].children[0] if plugin: self.context.notify( 'info', _('Please configure %s plugin!') % plugin.classconfig_editor.title) self.activate() @intent('setup-fake-ssl') def gen_ssl(self, host): self.save() subprocess.call(['ajenti-ssl-gen', host, '-f']) ajenti.config.load() self.refresh()
class Tasks(SectionPlugin): def init(self): self.title = _('Tasks') self.icon = 'cog' self.category = _('Tools') self.append(self.ui.inflate('tasks:main')) self.manager = TaskManager.get(manager.context) self.binder = Binder(None, self) def post_td_bind(object, collection, item, ui): if item.get_class(): params_ui = self.ui.inflate(item.get_class().ui) item.binder = DictAutoBinding(item, 'params', params_ui.find('bind')) item.binder.populate() ui.find('slot').empty() ui.find('slot').append(params_ui) def post_td_update(object, collection, item, ui): if hasattr(item, 'binder'): item.binder.update() def post_rt_bind(object, collection, item, ui): def abort(): item.abort() self.refresh() ui.find('abort').on('click', abort) self.find('task_definitions').post_item_bind = post_td_bind self.find('task_definitions').post_item_update = post_td_update self.find('running_tasks').post_item_bind = post_rt_bind self.find('job_definitions').new_item = lambda c: JobDefinition() def on_page_load(self): self.refresh() @on('refresh', 'click') def refresh(self): self.binder.reset(self.manager) self.manager.refresh() dd = self.find('task-classes') dd.labels = [] dd.values = [] for task in Task.get_classes(): if not task.hidden: dd.labels.append(task.name) dd.values.append(task.classname) dd = self.find('task-selector') dd.labels = [_.name for _ in self.manager.task_definitions] dd.values = [_.id for _ in self.manager.task_definitions] self.find('run-task-selector').labels = dd.labels self.find('run-task-selector').values = dd.values self.binder.autodiscover().populate() @on('run-task', 'click') def on_run_task(self): self.manager.run(task_id=self.find('run-task-selector').value, context=self.context) self.refresh() @on('create-task', 'click') def on_create_task(self): cls = self.find('task-classes').value td = TaskDefinition(task_class=cls) td.name = td.get_class().name self.manager.task_definitions.append(td) self.refresh() @on('save', 'click') def on_save(self): self.binder.update() self.manager.save() self.refresh()
def on_first_page_load(self): self.new_tab() self.binder = Binder(self.controller, self.find('filemanager')).populate() self.binder_c = Binder(self, self.find('bind-clipboard')).populate()