forked from LibreSchool/doraemon
Compare commits
33 Commits
Author | SHA1 | Date | |
---|---|---|---|
139c70322c | |||
45a944090b | |||
5b16daa4af | |||
4b0ecef735 | |||
9589d3b63a | |||
e42fdd96c0 | |||
671e8286f4 | |||
2786dfea1c | |||
2cfc4add84 | |||
77ab09a73a | |||
28d81f3a29 | |||
85c4306e74 | |||
e9f8e8a5f4 | |||
d425ad55a2 | |||
eccdbb68d4 | |||
d7873ef7ea | |||
1d06549e8f | |||
1e6057929f | |||
744ef03534 | |||
048e5a82da | |||
cfe38a1321 | |||
9b9db0f626 | |||
04097ff49d | |||
fee905ac79 | |||
4e1b2c2199 | |||
e5aa2bcb71 | |||
52904028d6 | |||
34457e9692 | |||
3d81fd12e3 | |||
91840647e5 | |||
eee2c83d90 | |||
b1502803ff | |||
cc8a26960a |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
*.sh
|
*.sh
|
||||||
*.tar.*
|
*.tar.*
|
||||||
|
*.rpm
|
||||||
|
15
createlinks.pl
Normal file
15
createlinks.pl
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
use esmith::Build::CreateLinks qw(:all);
|
||||||
|
use File::Basename;
|
||||||
|
use File::Path;
|
||||||
|
|
||||||
|
|
||||||
|
$event = "doraemon-reboot";
|
||||||
|
event_actions($event, 'doraemon-reboot' => 50);
|
||||||
|
|
||||||
|
$event = "doraemon-shutdown";
|
||||||
|
event_actions($event, 'doraemon-shutdown' => 50);
|
||||||
|
|
||||||
|
$event = "doraemon-wake";
|
||||||
|
event_actions($event, 'doraemon-wake' => 50);
|
@ -1 +0,0 @@
|
|||||||
private
|
|
16
doraemon.ini
16
doraemon.ini
@ -1,16 +0,0 @@
|
|||||||
[Daemon]
|
|
||||||
Database = /var/lib/doraemon/doraemon.db
|
|
||||||
LogFile = /var/log/doraemon.log
|
|
||||||
PIDFile = /var/run/doraemon.pid
|
|
||||||
BindAddress = 0.0.0.0
|
|
||||||
Port = 3000
|
|
||||||
|
|
||||||
[NameSettings]
|
|
||||||
Base = lab
|
|
||||||
Role = client
|
|
||||||
Digits = 2
|
|
||||||
|
|
||||||
[Files]
|
|
||||||
Domain = /etc/domain.yml
|
|
||||||
MgmtKey = /home/amgmt/.ssh/id_rsa.pub
|
|
||||||
VaultPassFile = /home/amgmt/.ansible/vault.txt
|
|
@ -1,6 +0,0 @@
|
|||||||
/var/log/doraemon.log {
|
|
||||||
daily
|
|
||||||
rotate 15
|
|
||||||
compress
|
|
||||||
missingok
|
|
||||||
}
|
|
234
doraemon.py
234
doraemon.py
@ -1,234 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""Helps a client to join domain and maintain itself."""
|
|
||||||
__author__ = 'BgLUG'
|
|
||||||
__email__ = 'info@bglug.it'
|
|
||||||
|
|
||||||
from contextlib import contextmanager, closing
|
|
||||||
from subprocess import Popen, PIPE
|
|
||||||
from sqlite3 import connect
|
|
||||||
from bottle import Bottle, request
|
|
||||||
from json import dumps
|
|
||||||
from ConfigParser import ConfigParser
|
|
||||||
from Crypto.Hash import MD5
|
|
||||||
from Crypto.Cipher import AES
|
|
||||||
import base64
|
|
||||||
import json
|
|
||||||
import sys
|
|
||||||
import re
|
|
||||||
import os
|
|
||||||
|
|
||||||
class MyApp:
|
|
||||||
def __init__(self, configfile = '/etc/mac2hostname.ini'):
|
|
||||||
if not os.path.isfile(configfile):
|
|
||||||
print "Cannot find main file, %s. Exiting." % configfile
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# Loads configurations
|
|
||||||
config = ConfigParser()
|
|
||||||
config.read(configfile)
|
|
||||||
# Populates private properties with configuration
|
|
||||||
self.__dbfile = config.get('Daemon', 'Database') if config.has_option('Daemon', 'Database') else '/var/lib/doraemon/doraemon.db'
|
|
||||||
self.__logdir = config.get('Daemon', 'LogFile') if config.has_option('Daemon', 'LogFile') else '/var/log/doraemon.log'
|
|
||||||
self.__pidfile = config.get('Daemon', 'PIDFile') if config.has_option('Daemon', 'PIDFile') else '/var/run/doraemon.pid'
|
|
||||||
self.__bindaddress = config.get('Daemon', 'BindAddress') if config.has_option('Daemon', 'BindAddress') else '127.0.0.1'
|
|
||||||
self.__port = config.getint('Daemon', 'Port') if config.has_option('Daemon',
|
|
||||||
'Port') else 8080
|
|
||||||
self.__defaultbase = config.get('NameSettings', 'Base') if config.has_option('NameSettings', 'Base') else 'client'
|
|
||||||
self.__defaultrole = config.get('NameSettings', 'Role') if config.has_option('NameSettings', 'Role') else 'client'
|
|
||||||
self.__namedigits = config.get('NameSettings', 'Digits') if config.has_option('NameSettings', 'Digits') else '2'
|
|
||||||
self.__domainfile = config.get('Files', 'Domain') if config.has_option('Files', 'Domain') else None
|
|
||||||
self.__mgmtfile = config.get('Files', 'MgmtKey') if config.has_option('Files', 'MgmtKey') else None
|
|
||||||
self.__vaultpassfile = config.get('Files', 'VaultPassFile') if config.has_option('Files', 'VaultPassFile') else None
|
|
||||||
self.__app = Bottle()
|
|
||||||
# Applies routes
|
|
||||||
self.__route()
|
|
||||||
# Assures table creation
|
|
||||||
self.__init_tables()
|
|
||||||
|
|
||||||
@contextmanager
|
|
||||||
def __getcursor(self):
|
|
||||||
with connect(self.__dbfile) as connection:
|
|
||||||
with closing(connection.cursor()) as cursor:
|
|
||||||
yield cursor
|
|
||||||
|
|
||||||
# Private methods
|
|
||||||
def __route(self):
|
|
||||||
self.__app.get('/mac2hostname', callback=self.mac2hostname)
|
|
||||||
self.__app.get('/whatsmyhostname', callback=self.whatsmyhostname)
|
|
||||||
self.__app.get('/hosts', callback=self.hosts)
|
|
||||||
self.__app.get('/domain', callback=self.domain)
|
|
||||||
self.__app.get('/mgmtkey', callback=self.mgmtkey)
|
|
||||||
self.__app.get('/vaultpass', callback=self.vaultpass)
|
|
||||||
self.__app.get('/ansible_list', callback=self.ansible_list)
|
|
||||||
self.__app.get('/ansible_host', callback=self.ansible_host)
|
|
||||||
self.__app.get('/epoptes-srv', callback=self.epoptes_srv)
|
|
||||||
|
|
||||||
def __init_tables(self):
|
|
||||||
with self.__getcursor() as cursor:
|
|
||||||
cursor.execute('CREATE TABLE IF NOT EXISTS client (id INT PRIMARY KEY,'
|
|
||||||
'hostname TEXT NOT NULL UNIQUE, mac TEXT UNIQUE, role TEXT)')
|
|
||||||
cursor.execute('CREATE INDEX IF NOT EXISTS idxmac ON client(mac)')
|
|
||||||
|
|
||||||
def __getmac(self, ip):
|
|
||||||
Popen(['ping', '-c1', '-t2', ip], stdout=PIPE).communicate()
|
|
||||||
arp = Popen(['arp', '-n', ip], stdout=PIPE).communicate()[0]
|
|
||||||
return re.search(r'(([\da-fA-F]{1,2}\:){5}[\da-fA-F]{1,2})', arp).group(1).lower()
|
|
||||||
|
|
||||||
def __normalizemac(self, mac):
|
|
||||||
return ':'.join(x.zfill(2) for x in mac.split('_')).lower()
|
|
||||||
|
|
||||||
def __gethostname(self, mac, base = None, role = None):
|
|
||||||
if base == None:
|
|
||||||
base = self.__defaultbase
|
|
||||||
if role == None:
|
|
||||||
role = self.__defaultrole
|
|
||||||
|
|
||||||
with self.__getcursor() as cursor:
|
|
||||||
(newid,) = cursor.execute('SELECT COALESCE(MAX(id) + 1, 1) FROM client').fetchone()
|
|
||||||
# Constucts the hostname format
|
|
||||||
formatstring = '%s-%0' + self.__namedigits + 'd'
|
|
||||||
data = (newid, formatstring % (base, newid), mac, role)
|
|
||||||
# Since MAC is Unique, this fails with the same MAC address
|
|
||||||
cursor.execute('INSERT OR IGNORE INTO client VALUES (?, ?, ?, ?)', data)
|
|
||||||
(hostname,) = cursor.execute('SELECT hostname FROM client WHERE mac = "%s"' % mac).fetchone()
|
|
||||||
return hostname
|
|
||||||
|
|
||||||
# This should be used only after registration of the client
|
|
||||||
# (whatsmyhostname)
|
|
||||||
def __getrole(self):
|
|
||||||
macaddress = self.__normalizemac(self.__getmac(request['REMOTE_ADDR']))
|
|
||||||
hostname = self.__gethostname(macaddress)
|
|
||||||
|
|
||||||
with self.__getcursor() as cursor:
|
|
||||||
(role,) = cursor.execute("SELECT role FROM client WHERE hostname = '%s' AND mac = '%s'" % (hostname, macaddress)).fetchone()
|
|
||||||
return role
|
|
||||||
|
|
||||||
# Variables returned to the client
|
|
||||||
def __rolevars(self, role=None):
|
|
||||||
retval = {'role': role, 'addpkg': [], 'delpkg': []}
|
|
||||||
try:
|
|
||||||
db = Popen(['/sbin/e-smith/db', 'roles', 'getjson'], stdout=PIPE).communicate()[0]
|
|
||||||
for data in json.loads(db):
|
|
||||||
if data['name'] == role:
|
|
||||||
retval['addpkg'] = re.split(r'[\s,;]+', data['props']['Addpkg'])
|
|
||||||
retval['delpkg'] = re.split(r'[\s,;]+', data['props']['Delpkg'])
|
|
||||||
continue
|
|
||||||
except: pass
|
|
||||||
return retval
|
|
||||||
|
|
||||||
# Instance methods AKA routes
|
|
||||||
def mac2hostname(self):
|
|
||||||
# Ensure required parameters have been passed
|
|
||||||
if not request.query.mac:
|
|
||||||
return "Usage: GET /mac2hostname?mac=XX_XX_XX_XX_XX_XX[&base=YYY][&role=ZZZ]"
|
|
||||||
# Sets up variables for possible parameters
|
|
||||||
mac = self.__normalizemac(request.query.mac)
|
|
||||||
base = request.query.base or self.__defaultbase
|
|
||||||
role = request.query.role or self.__defaultrole
|
|
||||||
return self.__gethostname(mac, base, role)
|
|
||||||
|
|
||||||
def whatsmyhostname(self):
|
|
||||||
# No required parameters
|
|
||||||
ip = request.query.ip or request['REMOTE_ADDR']
|
|
||||||
base = request.query.base or self.__defaultbase
|
|
||||||
role = request.query.role or self.__defaultrole
|
|
||||||
return self.__gethostname(self.__getmac(ip), base, role)
|
|
||||||
|
|
||||||
def hosts(self):
|
|
||||||
# Default where clause: no where specifications
|
|
||||||
where = ''
|
|
||||||
# If a role parameter is passed, list the hosts for that role
|
|
||||||
if request.query.role:
|
|
||||||
where = "WHERE role = '%s'" % request.query.role
|
|
||||||
with self.__getcursor() as cursor:
|
|
||||||
return dumps([dict((meta[0], data)
|
|
||||||
for meta, data in zip(cursor.description, row))
|
|
||||||
for row in cursor.execute('SELECT role, hostname, mac FROM client '
|
|
||||||
+ where + 'ORDER BY role ASC, hostname ASC')], indent=4)
|
|
||||||
|
|
||||||
def domain(self):
|
|
||||||
with open(self.__domainfile, 'r') as f:
|
|
||||||
return f.read()
|
|
||||||
|
|
||||||
def mgmtkey(self):
|
|
||||||
with open(self.__mgmtfile, 'r') as f:
|
|
||||||
return f.read()
|
|
||||||
|
|
||||||
def vaultpass(self):
|
|
||||||
with open(self.__vaultpassfile, 'r') as f:
|
|
||||||
ip = request.query.ip or request['REMOTE_ADDR']
|
|
||||||
base = request.query.base or self.__defaultbase
|
|
||||||
role = request.query.role or self.__defaultrole
|
|
||||||
hostname = self.__gethostname(self.__getmac(ip), base, role)
|
|
||||||
# Encryption key
|
|
||||||
key = MD5.new(hostname).digest()
|
|
||||||
# Secret
|
|
||||||
secret = f.read().strip()
|
|
||||||
# Creating a secret that is multiple of 16 in length
|
|
||||||
i = 16 - (len(secret) % 16)
|
|
||||||
lengthy_secret = secret + i * 'x'
|
|
||||||
cipher = AES.new(key, AES.MODE_ECB)
|
|
||||||
crypted = cipher.encrypt(lengthy_secret)
|
|
||||||
# Encode in base64 because of unicode strings
|
|
||||||
return base64.b64encode(crypted)
|
|
||||||
|
|
||||||
def ansible_list(self):
|
|
||||||
# Faking calls
|
|
||||||
if request.query.role:
|
|
||||||
role = request.query.role
|
|
||||||
else:
|
|
||||||
role = self.__getrole()
|
|
||||||
|
|
||||||
result = {
|
|
||||||
'localhost': {
|
|
||||||
'hosts': [ 'localhost' ],
|
|
||||||
'vars': {
|
|
||||||
'ansible_connection': 'local'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'_meta': {
|
|
||||||
'hostvars': {
|
|
||||||
'localhost': self.__rolevars(role)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dumps(result)
|
|
||||||
|
|
||||||
def ansible_host(self):
|
|
||||||
# Ignoring 'host' parameter, since it should always be 'localhost'.
|
|
||||||
# Instead, for testing purposes, if asked for a role, use it
|
|
||||||
if request.query.role:
|
|
||||||
role = request.query.role
|
|
||||||
else:
|
|
||||||
role = self.__getrole()
|
|
||||||
return dumps(self.__rolevars(role))
|
|
||||||
|
|
||||||
def epoptes_srv(self):
|
|
||||||
hostname = None
|
|
||||||
try:
|
|
||||||
with self.__getcursor() as cursor:
|
|
||||||
(hostname,) = cursor.execute('SELECT hostname FROM client WHERE role = \'docenti\' ORDER BY id DESC LIMIT 1').fetchone()
|
|
||||||
except TypeError:
|
|
||||||
return 'none'
|
|
||||||
|
|
||||||
return hostname
|
|
||||||
|
|
||||||
def start(self):
|
|
||||||
# Opens up a PID file
|
|
||||||
pid = os.getpid()
|
|
||||||
pidfile = open(self.__pidfile, 'w')
|
|
||||||
pidfile.write('%s' % pid)
|
|
||||||
pidfile.close()
|
|
||||||
|
|
||||||
# Runs Bottle, at last.
|
|
||||||
self.__app.run(host=self.__bindaddress, port=self.__port)
|
|
||||||
|
|
||||||
# Main body
|
|
||||||
if __name__ == '__main__':
|
|
||||||
cfgfile = '/etc/doraemon.ini'
|
|
||||||
if len(sys.argv) > 1:
|
|
||||||
cfgfile = sys.argv[1]
|
|
||||||
app = MyApp(cfgfile)
|
|
||||||
app.start()
|
|
172
doraemon.spec
172
doraemon.spec
@ -1,85 +1,165 @@
|
|||||||
Summary: Helps client to join domain and maintain itself
|
Summary: Helps client to join domain and maintain itself
|
||||||
Name: doraemon
|
Name: doraemon
|
||||||
Version: 1.2.1
|
Version: 2.0.4
|
||||||
Release: 2.ns6
|
Release: 1.ns6
|
||||||
URL: https://github.com/bglug-it/doraemon/
|
URL: https://github.com/bglug-it/doraemon/
|
||||||
License: GPLv2+
|
License: GPLv2+
|
||||||
|
Packager: Paolo Asperti <paolo@asperti.com>
|
||||||
Group: System Environment/Daemons
|
Group: System Environment/Daemons
|
||||||
BuildRoot: %{_tmppath}/%{name}-root
|
BuildRoot: %{_tmppath}/%{name}-root
|
||||||
Requires: python python-bottle python-crypto2.6 nethserver-base
|
BuildRequires: nethserver-devtools > 1.0.1
|
||||||
Requires(post): chkconfig nethserver-base
|
BuildRequires: hunspell-en
|
||||||
Requires(preun): chkconfig initscripts nethserver-base
|
Requires: httpd, php, sudo, php-xml, php-mcrypt
|
||||||
Source0: doraemon-1.2.1.tar.gz
|
Requires: nethserver-base, nethserver-php
|
||||||
|
Requires: net-tools
|
||||||
|
Requires: upstart
|
||||||
|
Source0: %{name}-%{version}.tar.gz
|
||||||
BuildArch: noarch
|
BuildArch: noarch
|
||||||
|
|
||||||
%description
|
%description
|
||||||
Helps client on a domain network to get information for its maintenance.
|
Helps client on a domain network to get information for its maintenance.
|
||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup -q
|
%setup
|
||||||
|
|
||||||
%build
|
%build
|
||||||
|
%{makedocs}
|
||||||
|
perl createlinks.pl
|
||||||
|
|
||||||
%install
|
%install
|
||||||
rm -rf %{buildroot}
|
rm -Rf $RPM_BUILD_ROOT
|
||||||
install -d %{buildroot}
|
(cd root ; find . -depth -print | cpio -dump %{buildroot})
|
||||||
install -d -m 755 %{buildroot}%{_sysconfdir}
|
rm -f %{name}-%{version}-%{release}-filelist
|
||||||
install -m 644 doraemon.ini %{buildroot}%{_sysconfdir}/%{name}.ini
|
%{genfilelist} %{buildroot} > %{name}-%{version}-%{release}-filelist
|
||||||
# Installo il servizio
|
mkdir -p %{buildroot}%{_localstatedir}/log/doraemon
|
||||||
install -d -m 755 %{buildroot}%{_initrddir}
|
mkdir -p %{buildroot}%{_localstatedir}/cache/doraemon
|
||||||
install -m 755 initrd %{buildroot}%{_initrddir}/%{name}
|
|
||||||
# Installo lo script vero e proprio
|
|
||||||
install -d -m 755 %{buildroot}%{_bindir}
|
%pre
|
||||||
install -m 755 doraemon.py %{buildroot}%{_bindir}/%{name}.py
|
#if [ "$1" = 1 ]; then
|
||||||
# Cartella del database
|
# #installation
|
||||||
install -d %{buildroot}%{_sharedstatedir}/%{name}
|
#fi
|
||||||
# File per il rotate
|
if [ "$1" = 2 ]; then
|
||||||
install -d %{buildroot}%{_sysconfdir}/logrotate.d
|
#upgrade
|
||||||
install -m 644 doraemon.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/%{name}
|
/sbin/service %{name} stop >/dev/null 2>&1 || :
|
||||||
# File di Nethserver
|
/sbin/stop %{name} >/dev/null 2>&1 || :
|
||||||
install -d %{buildroot}%{_sysconfdir}/e-smith/db/configuration/defaults/%{name}
|
DATABASE=/var/lib/doraemon/doraemon.db
|
||||||
install -m 644 type %{buildroot}%{_sysconfdir}/e-smith/db/configuration/defaults/%{name}/type
|
INI=/etc/doraemon.ini
|
||||||
install -m 644 status %{buildroot}%{_sysconfdir}/e-smith/db/configuration/defaults/%{name}/status
|
if [ -f $INI ]; then
|
||||||
install -m 644 access %{buildroot}%{_sysconfdir}/e-smith/db/configuration/defaults/%{name}/access
|
DATABASE=$(awk -F "=" '/Database/ {print $2}' $INI)
|
||||||
install -m 644 TCPPort %{buildroot}%{_sysconfdir}/e-smith/db/configuration/defaults/%{name}/TCPPort
|
PORT=$(awk -F "=" '/Port/ {print $2}' $INI)
|
||||||
|
BASE=$(awk -F "=" '/Base/ {print $2}' $INI)
|
||||||
|
ROLE=$(awk -F "=" '/Role/ {print $2}' $INI)
|
||||||
|
DIGITS=$(awk -F "=" '/Digits/ {print $2}' $INI)
|
||||||
|
DOMAIN=$(awk -F "=" '/Domain/ {print $2}' $INI)
|
||||||
|
MGMTKEY=$(awk -F "=" '/MgmtKey/ {print $2}' $INI)
|
||||||
|
VAULTPASSFILE=$(awk -F "=" '/VaultPassFile/ {print $2}' $INI)
|
||||||
|
rm $INI
|
||||||
|
/sbin/e-smith/db configuration set %{name} service \
|
||||||
|
status enabled \
|
||||||
|
TCPPort $PORT \
|
||||||
|
access private \
|
||||||
|
DefaultRole $ROLE \
|
||||||
|
DomainFile $DOMAIN \
|
||||||
|
ManagementKeyFile $MGMTKEY \
|
||||||
|
NamingBase $BASE \
|
||||||
|
NamingDigits $DIGITS \
|
||||||
|
VaultPassFile $VAULTPASSFILE
|
||||||
|
else
|
||||||
|
/sbin/e-smith/db configuration set %{name} service \
|
||||||
|
status enabled \
|
||||||
|
TCPPort 3000 \
|
||||||
|
access private \
|
||||||
|
DefaultRole client \
|
||||||
|
DomainFile /etc/domain.yml \
|
||||||
|
ManagementKeyFile /home/amgmt/.ssh/id_rsa.pub \
|
||||||
|
NamingBase lab \
|
||||||
|
NamingDigits 2 \
|
||||||
|
VaultPassFile /home/amgmt/.ansible/vault.txt
|
||||||
|
fi
|
||||||
|
if [ -f $DATABASE ]; then
|
||||||
|
sqlite3 -separator " " $DATABASE \
|
||||||
|
"select * from client" | while read id hostname mac role; do
|
||||||
|
/sbin/e-smith/db hosts set $hostname local \
|
||||||
|
MacAddress $mac Role $role
|
||||||
|
done
|
||||||
|
rm $DATABASE
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
%post
|
%post
|
||||||
|
/etc/e-smith/events/actions/initialize-default-databases
|
||||||
|
[ -e /usr/sbin/doraemon ] && [ ! -L /usr/sbin/doraemon ] && rm /usr/sbin/doraemon
|
||||||
|
[ ! -L /usr/sbin/doraemon ] && ln -s httpd /usr/sbin/doraemon
|
||||||
if [ "$1" = 1 ]; then
|
if [ "$1" = 1 ]; then
|
||||||
/sbin/chkconfig --add %{name}
|
#installation
|
||||||
/sbin/service %{name} start >/dev/null 2>&1
|
/sbin/e-smith/db configuration set %{name} service status enabled TCPPort 3000 access private DefaultRole client DomainFile /etc/domain.yml ManagementKeyFile /home/amgmt/.ssh/id_rsa.pub NamingBase lab NamingDigits 2 VaultPassFile /home/amgmt/.ansible/vault.txt
|
||||||
/sbin/e-smith/db configuration set %{name} service status enabled TCPPort 3000 access private
|
/sbin/e-smith/expand-template /etc/sudoers
|
||||||
|
/sbin/e-smith/expand-template /etc/httpd/doraemon/httpd.conf
|
||||||
|
/sbin/start %{name} >/dev/null 2>&1 || :
|
||||||
|
/sbin/e-smith/signal-event runlevel-adjust
|
||||||
|
/sbin/e-smith/signal-event firewall-adjust
|
||||||
|
fi
|
||||||
|
if [ "$1" = 2 ]; then
|
||||||
|
#upgrade
|
||||||
|
# TODO: this won't be needed in the next version
|
||||||
|
/sbin/e-smith/expand-template /etc/sudoers
|
||||||
|
/sbin/e-smith/expand-template /etc/httpd/doraemon/httpd.conf
|
||||||
|
/sbin/start %{name} >/dev/null 2>&1 || :
|
||||||
/sbin/e-smith/signal-event runlevel-adjust
|
/sbin/e-smith/signal-event runlevel-adjust
|
||||||
/sbin/e-smith/signal-event firewall-adjust
|
/sbin/e-smith/signal-event firewall-adjust
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
%preun
|
%preun
|
||||||
|
#if [ "$1" = 1 ]; then
|
||||||
|
# #upgrade
|
||||||
|
#fi
|
||||||
if [ "$1" = 0 ]; then
|
if [ "$1" = 0 ]; then
|
||||||
|
#uninstallation
|
||||||
|
/sbin/stop %{name} >/dev/null 2>&1 || :
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
%postun
|
||||||
|
#if [ "$1" = 1 ]; then
|
||||||
|
# #upgrade
|
||||||
|
#fi
|
||||||
|
if [ "$1" = 0 ]; then
|
||||||
|
#uninstallation
|
||||||
/sbin/e-smith/db configuration delete %{name}
|
/sbin/e-smith/db configuration delete %{name}
|
||||||
/sbin/service %{name} stop >/dev/null 2>&1
|
/sbin/e-smith/expand-template /etc/sudoers
|
||||||
chkconfig --del %{name}
|
|
||||||
/sbin/e-smith/signal-event runlevel-adjust
|
/sbin/e-smith/signal-event runlevel-adjust
|
||||||
/sbin/e-smith/signal-event firewall-adjust
|
/sbin/e-smith/signal-event firewall-adjust
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
%clean
|
%clean
|
||||||
rm -rf %{buildroot}
|
rm -rf %{buildroot}
|
||||||
|
|
||||||
%files
|
%files -f %{name}-%{version}-%{release}-filelist
|
||||||
%defattr(644,root,root,755)
|
%defattr(0644,root,root,755)
|
||||||
%doc README.md LICENSE
|
%doc README.md LICENSE.txt
|
||||||
%config(noreplace) %{_sysconfdir}/%{name}.ini
|
%attr(0644,srvmgr,srvmgr) %ghost %{_localstatedir}/log/doraemon/access_log
|
||||||
%attr(755,-,-) %{_initrddir}/%{name}
|
%attr(0644,srvmgr,srvmgr) %ghost %{_localstatedir}/log/doraemon/error_log
|
||||||
%attr(755,-,-) %{_bindir}/%{name}.py
|
|
||||||
|
|
||||||
%dir %attr(755,-,-) %{_sharedstatedir}/%{name}
|
|
||||||
%{_sysconfdir}/logrotate.d/%{name}
|
|
||||||
%dir %attr(755,-,-) %{_sysconfdir}/e-smith/db/configuration/defaults/%{name}
|
|
||||||
%{_sysconfdir}/e-smith/db/configuration/defaults/%{name}/status
|
|
||||||
%{_sysconfdir}/e-smith/db/configuration/defaults/%{name}/type
|
|
||||||
%{_sysconfdir}/e-smith/db/configuration/defaults/%{name}/access
|
|
||||||
%{_sysconfdir}/e-smith/db/configuration/defaults/%{name}/TCPPort
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Sun Jun 17 2018 Emiliano Vavassori <syntaxerrormmm-AT-gmail.com> - 2.0.4-1
|
||||||
|
- FIX: Doraemon doesn't start after installation
|
||||||
|
|
||||||
|
* Sun Jun 17 2018 Emiliano Vavassori <syntaxerrormmm-AT-gmail.com> - 2.0.3-1
|
||||||
|
- FIX: whatsmyhostname correctly parse role variable
|
||||||
|
- Minor aesthetic syntax fixes
|
||||||
|
|
||||||
|
* Sun Oct 8 2017 Paolo Asperti <paolo@asperti.com> - 2.0.2-1
|
||||||
|
- FIX: bug in WOL
|
||||||
|
- FIX: small language typos
|
||||||
|
|
||||||
|
* Wed Nov 9 2016 Paolo Asperti <paolo@asperti.com> - 2.0.1-1
|
||||||
|
- PHP porting
|
||||||
|
- Added a basic UI
|
||||||
|
|
||||||
* Tue Oct 27 2015 Emiliano Vavassori <syntaxerrormmm-AT-gmail.com> - 1.2.1-2.ns6
|
* Tue Oct 27 2015 Emiliano Vavassori <syntaxerrormmm-AT-gmail.com> - 1.2.1-2.ns6
|
||||||
- Packing corrections to rpm to fix upgrading issue
|
- Packing corrections to rpm to fix upgrading issue
|
||||||
|
|
||||||
|
79
initrd
79
initrd
@ -1,79 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# chkconfig: 2345 20 80
|
|
||||||
# description: Manage assignation of hostnames for clients
|
|
||||||
# pidfile: /var/run/doraemon.pid
|
|
||||||
# config: /etc/doraemon.ini
|
|
||||||
|
|
||||||
### BEGIN INIT INFO
|
|
||||||
# Provides: doraemon
|
|
||||||
# Required-Start: $remote_fs $syslog
|
|
||||||
# Required-Stop: $remote_fs $syslog
|
|
||||||
# Default-Start: 2 3 4 5
|
|
||||||
# Default-Stop: 0 1 6
|
|
||||||
# Short-Description: Helps client to join the domain and maintain itself
|
|
||||||
# Description: Helps client to join the domain and maintain itself
|
|
||||||
### END INIT INFO
|
|
||||||
|
|
||||||
# Change the next 3 lines to suit where you install your script and what you want to call it
|
|
||||||
DAEMON=/usr/bin/doraemon.py
|
|
||||||
DAEMON_NAME=doraemon
|
|
||||||
|
|
||||||
# Add any command line options for your daemon here
|
|
||||||
DAEMON_OPTS=""
|
|
||||||
|
|
||||||
# This next line determines what user the script runs as.
|
|
||||||
# Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python.
|
|
||||||
#DAEMON_USER=mac2hostname
|
|
||||||
#DAEMON_GROUP=mac2hostname
|
|
||||||
|
|
||||||
# The process ID of the script when it runs is stored here:
|
|
||||||
LOGFILE=/var/log/$DAEMON_NAME.log
|
|
||||||
PIDFILE=/var/run/$DAEMON_NAME.pid
|
|
||||||
lockfile=/var/lock/subsys/$DAEMON_NAME
|
|
||||||
|
|
||||||
. /etc/rc.d/init.d/functions
|
|
||||||
. /etc/sysconfig/network
|
|
||||||
|
|
||||||
[ "$NETWORKING" = "no" ] && exit 0
|
|
||||||
|
|
||||||
do_start () {
|
|
||||||
echo -n $"Starting $DAEMON_NAME: "
|
|
||||||
daemon --pidfile=$PIDFILE "python $DAEMON >>$LOGFILE 2>/dev/null &"
|
|
||||||
RETVAL=$?
|
|
||||||
echo
|
|
||||||
[ $RETVAL -eq 0 ] && touch $lockfile
|
|
||||||
return $RETVAL
|
|
||||||
}
|
|
||||||
|
|
||||||
do_stop () {
|
|
||||||
echo -n $"Stopping $DAEMON_NAME: "
|
|
||||||
killproc -p $PIDFILE python
|
|
||||||
RETVAL=$?
|
|
||||||
echo
|
|
||||||
[ $RETVAL -eq 0 ] && rm -f $lockfile
|
|
||||||
return $RETVAL
|
|
||||||
}
|
|
||||||
|
|
||||||
case "$1" in
|
|
||||||
|
|
||||||
start|stop)
|
|
||||||
do_${1}
|
|
||||||
;;
|
|
||||||
|
|
||||||
restart|reload|force-reload)
|
|
||||||
do_stop
|
|
||||||
do_start
|
|
||||||
;;
|
|
||||||
|
|
||||||
status)
|
|
||||||
status -p $PIDFILE python
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
|
|
||||||
esac
|
|
||||||
exit 0
|
|
@ -0,0 +1 @@
|
|||||||
|
client
|
@ -0,0 +1 @@
|
|||||||
|
/etc/domain.yml
|
@ -0,0 +1 @@
|
|||||||
|
/home/amgmt/.ssh/id_rsa.pub
|
@ -0,0 +1 @@
|
|||||||
|
lab
|
@ -0,0 +1 @@
|
|||||||
|
2
|
@ -0,0 +1 @@
|
|||||||
|
/home/amgmt/.ansible/vault.txt
|
@ -0,0 +1 @@
|
|||||||
|
public
|
34
root/etc/e-smith/events/actions/doraemon-reboot
Executable file
34
root/etc/e-smith/events/actions/doraemon-reboot
Executable file
@ -0,0 +1,34 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
package esmith;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use Errno;
|
||||||
|
use esmith::DB::db;
|
||||||
|
use IO::File;
|
||||||
|
use English;
|
||||||
|
|
||||||
|
my $db_hosts = esmith::DB::db->open('hosts') || die("Could not open e-smith db (" . esmith::DB::db->error . ")\n");
|
||||||
|
|
||||||
|
my $event = $ARGV[0];
|
||||||
|
|
||||||
|
defined $ARGV[1] || die "No host specified";
|
||||||
|
my $host = $ARGV[1];
|
||||||
|
|
||||||
|
reboot_host($host);
|
||||||
|
|
||||||
|
exit 0;
|
||||||
|
|
||||||
|
sub reboot_host
|
||||||
|
{
|
||||||
|
my ($hostName) = @_;
|
||||||
|
#------------------------------------------------------------
|
||||||
|
# Reboot the host
|
||||||
|
#------------------------------------------------------------
|
||||||
|
|
||||||
|
my $h = $db_hosts->get($hostName) or die "No host record for $hostName";
|
||||||
|
|
||||||
|
system("/usr/bin/sudo -u amgmt /usr/bin/ssh -o StrictHostKeyChecking=no amgmt\@$hostName /usr/bin/sudo /sbin/reboot") == 0
|
||||||
|
or die "Error rebooting $hostName";
|
||||||
|
|
||||||
|
}
|
20
root/etc/e-smith/events/actions/doraemon-reboot-all
Executable file
20
root/etc/e-smith/events/actions/doraemon-reboot-all
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
package esmith;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use Errno;
|
||||||
|
use esmith::DB::db;
|
||||||
|
use IO::File;
|
||||||
|
use English;
|
||||||
|
|
||||||
|
my $db_hosts = esmith::DB::db->open('hosts') || die("Could not open e-smith db (" . esmith::DB::db->error . ")\n");
|
||||||
|
|
||||||
|
my @items = $db_hosts->get_all('local');
|
||||||
|
foreach my $item (@items) {
|
||||||
|
my $hostName = $item->key;
|
||||||
|
system("/usr/bin/sudo -u amgmt /usr/bin/ssh -o StrictHostKeyChecking=no amgmt\@$hostName /usr/bin/sudo /sbin/reboot &") == 0
|
||||||
|
or die "Error rebooting $hostName";
|
||||||
|
}
|
||||||
|
|
||||||
|
exit 0;
|
34
root/etc/e-smith/events/actions/doraemon-shutdown
Executable file
34
root/etc/e-smith/events/actions/doraemon-shutdown
Executable file
@ -0,0 +1,34 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
package esmith;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use Errno;
|
||||||
|
use esmith::DB::db;
|
||||||
|
use IO::File;
|
||||||
|
use English;
|
||||||
|
|
||||||
|
my $db_hosts = esmith::DB::db->open('hosts') || die("Could not open e-smith db (" . esmith::DB::db->error . ")\n");
|
||||||
|
|
||||||
|
my $event = $ARGV[0];
|
||||||
|
|
||||||
|
defined $ARGV[1] || die "No host specified";
|
||||||
|
my $host = $ARGV[1];
|
||||||
|
|
||||||
|
shutdown_host($host);
|
||||||
|
|
||||||
|
exit 0;
|
||||||
|
|
||||||
|
sub shutdown_host
|
||||||
|
{
|
||||||
|
my ($hostName) = @_;
|
||||||
|
#------------------------------------------------------------
|
||||||
|
# Shutdown the host
|
||||||
|
#------------------------------------------------------------
|
||||||
|
|
||||||
|
my $h = $db_hosts->get($hostName) or die "No host record for $hostName";
|
||||||
|
|
||||||
|
system("/usr/bin/sudo -u amgmt /usr/bin/ssh -o StrictHostKeyChecking=no amgmt\@$hostName /usr/bin/sudo /sbin/poweroff") == 0
|
||||||
|
or die "Error shutting down $hostName";
|
||||||
|
|
||||||
|
}
|
20
root/etc/e-smith/events/actions/doraemon-shutdown-all
Executable file
20
root/etc/e-smith/events/actions/doraemon-shutdown-all
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
package esmith;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use Errno;
|
||||||
|
use esmith::DB::db;
|
||||||
|
use IO::File;
|
||||||
|
use English;
|
||||||
|
|
||||||
|
my $db_hosts = esmith::DB::db->open('hosts') || die("Could not open e-smith db (" . esmith::DB::db->error . ")\n");
|
||||||
|
|
||||||
|
my @items = $db_hosts->get_all('local');
|
||||||
|
foreach my $item (@items) {
|
||||||
|
my $hostName = $item->key;
|
||||||
|
system("/usr/bin/sudo -u amgmt /usr/bin/ssh -o StrictHostKeyChecking=no amgmt\@$hostName /usr/bin/sudo /sbin/poweroff &") == 0
|
||||||
|
or die "Error shutting down $hostName";
|
||||||
|
}
|
||||||
|
|
||||||
|
exit 0;
|
35
root/etc/e-smith/events/actions/doraemon-wake
Executable file
35
root/etc/e-smith/events/actions/doraemon-wake
Executable file
@ -0,0 +1,35 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
package esmith;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use Errno;
|
||||||
|
use esmith::DB::db;
|
||||||
|
use IO::File;
|
||||||
|
use English;
|
||||||
|
|
||||||
|
my $db_hosts = esmith::DB::db->open('hosts') || die("Could not open e-smith db (" . esmith::DB::db->error . ")\n");
|
||||||
|
|
||||||
|
my $event = $ARGV[0];
|
||||||
|
|
||||||
|
defined $ARGV[1] || die "No host specified";
|
||||||
|
my $host = $ARGV[1];
|
||||||
|
|
||||||
|
wake_host($host);
|
||||||
|
|
||||||
|
exit 0;
|
||||||
|
|
||||||
|
sub wake_host
|
||||||
|
{
|
||||||
|
my ($hostName) = @_;
|
||||||
|
#------------------------------------------------------------
|
||||||
|
# Wake up the host
|
||||||
|
#------------------------------------------------------------
|
||||||
|
|
||||||
|
my @h = $db_hosts->get($hostName) or die "No host record for $hostName";
|
||||||
|
my $client = $h[0];
|
||||||
|
my $mac = $client->prop('MacAddress');
|
||||||
|
system("/sbin/ether-wake -b -i lan0 $mac") == 0
|
||||||
|
or die "Error waking up $hostName";
|
||||||
|
|
||||||
|
}
|
21
root/etc/e-smith/events/actions/doraemon-wake-all
Executable file
21
root/etc/e-smith/events/actions/doraemon-wake-all
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
package esmith;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use Errno;
|
||||||
|
use esmith::DB::db;
|
||||||
|
use IO::File;
|
||||||
|
use English;
|
||||||
|
|
||||||
|
my $db_hosts = esmith::DB::db->open('hosts') || die("Could not open e-smith db (" . esmith::DB::db->error . ")\n");
|
||||||
|
|
||||||
|
my @items = $db_hosts->get_all('local');
|
||||||
|
foreach my $item (@items) {
|
||||||
|
my $hostName = $item->key;
|
||||||
|
my $mac = $item->prop('MacAddress');
|
||||||
|
system("/sbin/ether-wake -b -i lan0 $mac &") == 0
|
||||||
|
or die "Error waking up $hostName";
|
||||||
|
}
|
||||||
|
|
||||||
|
exit 0;
|
@ -0,0 +1 @@
|
|||||||
|
../actions/doraemon-reboot-all
|
1
root/etc/e-smith/events/doraemon-reboot/S50doraemon-reboot
Symbolic link
1
root/etc/e-smith/events/doraemon-reboot/S50doraemon-reboot
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../actions/doraemon-reboot
|
@ -0,0 +1 @@
|
|||||||
|
../actions/doraemon-shutdown-all
|
1
root/etc/e-smith/events/doraemon-shutdown/S50doraemon-shutdown
Symbolic link
1
root/etc/e-smith/events/doraemon-shutdown/S50doraemon-shutdown
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../actions/doraemon-shutdown
|
1
root/etc/e-smith/events/doraemon-wake-all/S50doraemon-wake-all
Symbolic link
1
root/etc/e-smith/events/doraemon-wake-all/S50doraemon-wake-all
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../actions/doraemon-wake-all
|
1
root/etc/e-smith/events/doraemon-wake/S50doraemon-wake
Symbolic link
1
root/etc/e-smith/events/doraemon-wake/S50doraemon-wake
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../actions/doraemon-wake
|
@ -0,0 +1,3 @@
|
|||||||
|
TEMPLATE_PATH='upstart-job'
|
||||||
|
OUTPUT_FILENAME='/etc/init/doraemon.conf'
|
||||||
|
MORE_DATA={ name => 'doraemon', description => 'Apache instance that runs the doraemon service', author => 'Paolo Asperti <paolo@asperti.com>', daemon_bin => '/usr/sbin/doraemon', daemon_args => '-f /etc/httpd/doraemon/httpd.conf', respawn => 1, 'expect' => 'fork', stop_on => 'stopping network', start_on => 'started network' }
|
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
#
|
||||||
|
# 00template_defaults
|
||||||
|
#
|
||||||
|
|
||||||
|
$localAccess = '';
|
||||||
|
$port = ${'doraemon'}{TCPPort} || "3000";
|
||||||
|
|
||||||
|
"";
|
||||||
|
}
|
@ -0,0 +1,127 @@
|
|||||||
|
{
|
||||||
|
|
||||||
|
$OUT .= <<HERE;
|
||||||
|
Listen $port
|
||||||
|
HostnameLookups off
|
||||||
|
|
||||||
|
ServerAdmin root@$DomainName
|
||||||
|
ServerRoot /etc/httpd
|
||||||
|
ServerTokens ProductOnly
|
||||||
|
|
||||||
|
User srvmgr
|
||||||
|
Group srvmgr
|
||||||
|
|
||||||
|
ErrorLog /var/log/doraemon/error_log
|
||||||
|
LogLevel warn
|
||||||
|
HERE
|
||||||
|
|
||||||
|
foreach (qw(
|
||||||
|
env
|
||||||
|
log_config
|
||||||
|
mime
|
||||||
|
negotiation
|
||||||
|
include
|
||||||
|
autoindex
|
||||||
|
dir
|
||||||
|
alias
|
||||||
|
rewrite
|
||||||
|
access
|
||||||
|
authz_host
|
||||||
|
expires
|
||||||
|
headers
|
||||||
|
setenvif
|
||||||
|
ssl
|
||||||
|
))
|
||||||
|
{
|
||||||
|
next unless -f "/usr/lib/httpd/modules/mod_${_}.so" ||
|
||||||
|
-f "/usr/lib64/httpd/modules/mod_${_}.so";
|
||||||
|
$OUT .= "LoadModule ${_}_module modules/mod_${_}.so\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$OUT .= <<HERE;
|
||||||
|
PidFile /var/run/doraemon.pid
|
||||||
|
ScoreBoardFile /var/run/doraemon.scoreboard
|
||||||
|
UseCanonicalName off
|
||||||
|
LogFormat "%h %l %u %t \\"%r\\" %>s %b" common
|
||||||
|
LogFormat "%{User-agent}i" agent
|
||||||
|
|
||||||
|
CustomLog /var/log/doraemon/access_log common
|
||||||
|
|
||||||
|
KeepAlive On
|
||||||
|
MaxKeepAliveRequests 100
|
||||||
|
KeepAliveTimeout 15
|
||||||
|
|
||||||
|
MaxClients 150
|
||||||
|
MaxRequestsPerChild 100
|
||||||
|
|
||||||
|
MinSpareServers 1
|
||||||
|
MaxSpareServers 5
|
||||||
|
StartServers 1
|
||||||
|
Timeout 300
|
||||||
|
|
||||||
|
DefaultIcon /icons/unknown.gif
|
||||||
|
DirectoryIndex index.htm index.html index.shtml index.cgi
|
||||||
|
IndexOptions FancyIndexing VersionSort NameWidth=*
|
||||||
|
IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t
|
||||||
|
AccessFileName .htaccess
|
||||||
|
|
||||||
|
AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip
|
||||||
|
AddIconByType (TXT,/icons/text.gif) text/*
|
||||||
|
AddIconByType (IMG,/icons/image2.gif) image/*
|
||||||
|
AddIconByType (SND,/icons/sound2.gif) audio/*
|
||||||
|
AddIconByType (VID,/icons/movie.gif) video/*
|
||||||
|
DefaultType text/plain
|
||||||
|
TypesConfig /etc/mime.types
|
||||||
|
|
||||||
|
AddEncoding x-compress Z
|
||||||
|
AddEncoding x-gzip gz
|
||||||
|
|
||||||
|
AddIcon /icons/binary.gif .bin .exe
|
||||||
|
AddIcon /icons/binhex.gif .hqx
|
||||||
|
AddIcon /icons/tar.gif .tar
|
||||||
|
AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv
|
||||||
|
AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip
|
||||||
|
AddIcon /icons/a.gif .ps .ai .eps
|
||||||
|
AddIcon /icons/layout.gif .html .shtml .htm .pdf
|
||||||
|
AddIcon /icons/text.gif .txt
|
||||||
|
AddIcon /icons/c.gif .c
|
||||||
|
AddIcon /icons/p.gif .pl .py
|
||||||
|
AddIcon /icons/f.gif .for
|
||||||
|
AddIcon /icons/dvi.gif .dvi
|
||||||
|
AddIcon /icons/uuencoded.gif .uu
|
||||||
|
AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl
|
||||||
|
AddIcon /icons/tex.gif .tex
|
||||||
|
AddIcon /icons/bomb.gif core
|
||||||
|
|
||||||
|
AddIcon /icons/back.gif ..
|
||||||
|
AddIcon /icons/hand.right.gif README
|
||||||
|
AddIcon /icons/folder.gif ^^DIRECTORY^^
|
||||||
|
AddIcon /icons/blank.gif ^^BLANKICON^^
|
||||||
|
|
||||||
|
AddLanguage en .en
|
||||||
|
AddLanguage fr .fr
|
||||||
|
AddLanguage de .de
|
||||||
|
AddLanguage da .da
|
||||||
|
AddLanguage el .el
|
||||||
|
AddLanguage it .it
|
||||||
|
|
||||||
|
LanguagePriority en it de fr
|
||||||
|
|
||||||
|
AddType text/html .shtml
|
||||||
|
AddType application/x-pkcs7-crl .crl
|
||||||
|
|
||||||
|
AddType application/x-x509-ca-cert .crt
|
||||||
|
|
||||||
|
BrowserMatch "Mozilla/2" nokeepalive
|
||||||
|
BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0
|
||||||
|
BrowserMatch "RealPlayer 4\.0" force-response-1.0
|
||||||
|
BrowserMatch "Java/1\.0" force-response-1.0
|
||||||
|
BrowserMatch "JDK/1\.0" force-response-1.0
|
||||||
|
|
||||||
|
AddHandler cgi-script .cgi
|
||||||
|
AddHandler server-parsed .shtml
|
||||||
|
AddHandler imap-file map
|
||||||
|
|
||||||
|
HERE
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
# First, we configure the "default" to be a very restrictive set of
|
||||||
|
# permissions.
|
||||||
|
|
||||||
|
<Directory />
|
||||||
|
Options None
|
||||||
|
AllowOverride None
|
||||||
|
order deny,allow
|
||||||
|
deny from all
|
||||||
|
allow from none
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
<Directory /var/www/icons>
|
||||||
|
Allow from all
|
||||||
|
</Directory>
|
||||||
|
|
@ -0,0 +1,23 @@
|
|||||||
|
|
||||||
|
DocumentRoot /usr/share/doraemon
|
||||||
|
Alias /icons/ /var/www/icons/
|
||||||
|
|
||||||
|
<Directory /usr/share/doraemon/>
|
||||||
|
Options +Indexes
|
||||||
|
Order Deny,Allow
|
||||||
|
Deny from all
|
||||||
|
Allow from { $localAccess || 'all' }
|
||||||
|
AddType application/x-httpd-php .php
|
||||||
|
Options +FollowSymlinks
|
||||||
|
RewriteEngine on
|
||||||
|
RewriteBase /
|
||||||
|
RewriteRule ^(js/|fonts/|css/|images/|icons/|.+\.php) - [PT,L]
|
||||||
|
RewriteRule ^favicon.ico$ images/favicon.ico [L]
|
||||||
|
RewriteRule ^(.*)$ index.php/$1 [L]
|
||||||
|
php_value session.save_path /var/cache/doraemon
|
||||||
|
php_flag magic_quotes_gpc off
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
Include conf.d/php.conf
|
15
root/etc/e-smith/templates/etc/sudoers/50doraemon
Normal file
15
root/etc/e-smith/templates/etc/sudoers/50doraemon
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
$OUT = 'srvmgr ALL=NOPASSWD: /bin/cat ';
|
||||||
|
|
||||||
|
use esmith::ConfigDB;
|
||||||
|
my $confdb = esmith::ConfigDB->open;
|
||||||
|
my $backup = $confdb->get('doraemon') or die "No doraemon db entry found\n";
|
||||||
|
my $VaultPassFile = $backup->prop('VaultPassFile') || '/home/amgmt/.ansible/vault.txt';
|
||||||
|
my $ManagementKeyFile = $backup->prop('ManagementKeyFile') || '/home/amgmt/.ssh/id_rsa.pub';
|
||||||
|
my $DomainFile = $backup->prop('DomainFile') || '/etc/domain.yml';
|
||||||
|
|
||||||
|
$OUT = 'srvmgr ALL=NOPASSWD: /bin/cat ' . $VaultPassFile . '
|
||||||
|
srvmgr ALL=NOPASSWD: /bin/cat ' . $ManagementKeyFile .'
|
||||||
|
srvmgr ALL=NOPASSWD: /bin/cat ' . $DomainFile;
|
||||||
|
|
||||||
|
}
|
162
root/etc/httpd/doraemon/httpd.conf
Normal file
162
root/etc/httpd/doraemon/httpd.conf
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
# ================= DO NOT MODIFY THIS FILE =================
|
||||||
|
#
|
||||||
|
# Manual changes will be lost when this file is regenerated.
|
||||||
|
#
|
||||||
|
# Please read the developer's guide, which is available
|
||||||
|
# at https://dev.nethesis.it/projects/nethserver/wiki/NethServer
|
||||||
|
# original work from http://www.contribs.org/development/
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 Nethesis S.r.l.
|
||||||
|
# http://www.nethesis.it - support@nethesis.it
|
||||||
|
#
|
||||||
|
Listen 3000
|
||||||
|
HostnameLookups off
|
||||||
|
|
||||||
|
ServerAdmin root
|
||||||
|
ServerRoot /etc/httpd
|
||||||
|
ServerTokens ProductOnly
|
||||||
|
|
||||||
|
User srvmgr
|
||||||
|
Group srvmgr
|
||||||
|
|
||||||
|
ErrorLog /var/log/doraemon/error_log
|
||||||
|
LogLevel warn
|
||||||
|
LoadModule env_module modules/mod_env.so
|
||||||
|
LoadModule log_config_module modules/mod_log_config.so
|
||||||
|
LoadModule mime_module modules/mod_mime.so
|
||||||
|
LoadModule negotiation_module modules/mod_negotiation.so
|
||||||
|
LoadModule include_module modules/mod_include.so
|
||||||
|
LoadModule autoindex_module modules/mod_autoindex.so
|
||||||
|
LoadModule dir_module modules/mod_dir.so
|
||||||
|
LoadModule alias_module modules/mod_alias.so
|
||||||
|
LoadModule rewrite_module modules/mod_rewrite.so
|
||||||
|
LoadModule authz_host_module modules/mod_authz_host.so
|
||||||
|
LoadModule expires_module modules/mod_expires.so
|
||||||
|
LoadModule headers_module modules/mod_headers.so
|
||||||
|
LoadModule setenvif_module modules/mod_setenvif.so
|
||||||
|
LoadModule ssl_module modules/mod_ssl.so
|
||||||
|
PidFile /var/run/doraemon.pid
|
||||||
|
ScoreBoardFile /var/run/doraemon.scoreboard
|
||||||
|
UseCanonicalName off
|
||||||
|
LogFormat "%h %l %u %t \"%r\" %>s %b" common
|
||||||
|
LogFormat "%{User-agent}i" agent
|
||||||
|
|
||||||
|
CustomLog /var/log/doraemon/access_log common
|
||||||
|
|
||||||
|
KeepAlive On
|
||||||
|
MaxKeepAliveRequests 100
|
||||||
|
KeepAliveTimeout 15
|
||||||
|
|
||||||
|
MaxClients 150
|
||||||
|
MaxRequestsPerChild 100
|
||||||
|
|
||||||
|
MinSpareServers 1
|
||||||
|
MaxSpareServers 5
|
||||||
|
StartServers 1
|
||||||
|
Timeout 300
|
||||||
|
|
||||||
|
DefaultIcon /icons/unknown.gif
|
||||||
|
DirectoryIndex index.htm index.html index.shtml index.cgi
|
||||||
|
IndexOptions FancyIndexing VersionSort NameWidth=*
|
||||||
|
IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t
|
||||||
|
AccessFileName .htaccess
|
||||||
|
|
||||||
|
AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip
|
||||||
|
AddIconByType (TXT,/icons/text.gif) text/*
|
||||||
|
AddIconByType (IMG,/icons/image2.gif) image/*
|
||||||
|
AddIconByType (SND,/icons/sound2.gif) audio/*
|
||||||
|
AddIconByType (VID,/icons/movie.gif) video/*
|
||||||
|
DefaultType text/plain
|
||||||
|
TypesConfig /etc/mime.types
|
||||||
|
|
||||||
|
AddEncoding x-compress Z
|
||||||
|
AddEncoding x-gzip gz
|
||||||
|
|
||||||
|
AddIcon /icons/binary.gif .bin .exe
|
||||||
|
AddIcon /icons/binhex.gif .hqx
|
||||||
|
AddIcon /icons/tar.gif .tar
|
||||||
|
AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv
|
||||||
|
AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip
|
||||||
|
AddIcon /icons/a.gif .ps .ai .eps
|
||||||
|
AddIcon /icons/layout.gif .html .shtml .htm .pdf
|
||||||
|
AddIcon /icons/text.gif .txt
|
||||||
|
AddIcon /icons/c.gif .c
|
||||||
|
AddIcon /icons/p.gif .pl .py
|
||||||
|
AddIcon /icons/f.gif .for
|
||||||
|
AddIcon /icons/dvi.gif .dvi
|
||||||
|
AddIcon /icons/uuencoded.gif .uu
|
||||||
|
AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl
|
||||||
|
AddIcon /icons/tex.gif .tex
|
||||||
|
AddIcon /icons/bomb.gif core
|
||||||
|
|
||||||
|
AddIcon /icons/back.gif ..
|
||||||
|
AddIcon /icons/hand.right.gif README
|
||||||
|
AddIcon /icons/folder.gif ^^DIRECTORY^^
|
||||||
|
AddIcon /icons/blank.gif ^^BLANKICON^^
|
||||||
|
|
||||||
|
AddLanguage en .en
|
||||||
|
AddLanguage fr .fr
|
||||||
|
AddLanguage de .de
|
||||||
|
AddLanguage da .da
|
||||||
|
AddLanguage el .el
|
||||||
|
AddLanguage it .it
|
||||||
|
|
||||||
|
LanguagePriority en it de fr
|
||||||
|
|
||||||
|
AddType text/html .shtml
|
||||||
|
AddType application/x-pkcs7-crl .crl
|
||||||
|
|
||||||
|
AddType application/x-x509-ca-cert .crt
|
||||||
|
|
||||||
|
BrowserMatch "Mozilla/2" nokeepalive
|
||||||
|
BrowserMatch "MSIE 4.0b2;" nokeepalive downgrade-1.0 force-response-1.0
|
||||||
|
BrowserMatch "RealPlayer 4.0" force-response-1.0
|
||||||
|
BrowserMatch "Java/1.0" force-response-1.0
|
||||||
|
BrowserMatch "JDK/1.0" force-response-1.0
|
||||||
|
|
||||||
|
AddHandler cgi-script .cgi
|
||||||
|
AddHandler server-parsed .shtml
|
||||||
|
AddHandler imap-file map
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# First, we configure the "default" to be a very restrictive set of
|
||||||
|
# permissions.
|
||||||
|
|
||||||
|
<Directory />
|
||||||
|
Options None
|
||||||
|
AllowOverride None
|
||||||
|
order deny,allow
|
||||||
|
deny from all
|
||||||
|
allow from none
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
<Directory /var/www/icons>
|
||||||
|
Allow from all
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
|
||||||
|
DocumentRoot /usr/share/doraemon
|
||||||
|
Alias /icons/ /var/www/icons/
|
||||||
|
|
||||||
|
<Directory /usr/share/doraemon/>
|
||||||
|
Options +Indexes
|
||||||
|
Order Deny,Allow
|
||||||
|
Deny from all
|
||||||
|
Allow from all
|
||||||
|
AddType application/x-httpd-php .php
|
||||||
|
Options +FollowSymlinks
|
||||||
|
RewriteEngine on
|
||||||
|
RewriteBase /
|
||||||
|
RewriteRule ^(js/|fonts/|css/|images/|icons/|.+\.php) - [PT,L]
|
||||||
|
RewriteRule ^favicon.ico$ images/favicon.ico [L]
|
||||||
|
RewriteRule ^(.*)$ index.php/$1 [L]
|
||||||
|
php_value session.save_path /var/cache/doraemon
|
||||||
|
php_flag magic_quotes_gpc off
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Include conf.d/php.conf
|
12
root/etc/init/doraemon-reload.conf
Normal file
12
root/etc/init/doraemon-reload.conf
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#
|
||||||
|
# doraemon-reload task
|
||||||
|
#
|
||||||
|
# Signals an Apache graceful restart for doraemon instance
|
||||||
|
#
|
||||||
|
|
||||||
|
# service job, runs asynchronously
|
||||||
|
|
||||||
|
script
|
||||||
|
sleep 5
|
||||||
|
exec /usr/sbin/doraemon -f /etc/httpd/doraemon/httpd.conf -k graceful
|
||||||
|
end script
|
42
root/etc/init/doraemon.conf
Normal file
42
root/etc/init/doraemon.conf
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# ================= DO NOT MODIFY THIS FILE =================
|
||||||
|
#
|
||||||
|
# Manual changes will be lost when this file is regenerated.
|
||||||
|
#
|
||||||
|
# Please read the developer's guide, which is available
|
||||||
|
# at https://dev.nethesis.it/projects/nethserver/wiki/NethServer
|
||||||
|
# original work from http://www.contribs.org/development/
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 Nethesis S.r.l.
|
||||||
|
# http://www.nethesis.it - support@nethesis.it
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# 10base doraemon - Apache instance that runs the doraemon service
|
||||||
|
#
|
||||||
|
|
||||||
|
description "Apache instance that runs the doraemon service"
|
||||||
|
author "Paolo Asperti <paolo@asperti.com>"
|
||||||
|
respawn
|
||||||
|
respawn limit 10 5
|
||||||
|
expect fork
|
||||||
|
start on started network
|
||||||
|
stop on stopping network
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# 20pre_start
|
||||||
|
#
|
||||||
|
pre-start script
|
||||||
|
STAT=`/sbin/e-smith/config getprop doraemon status`
|
||||||
|
if test "x$STAT" = "xenabled" \
|
||||||
|
-a -f "/etc/e-smith/db/configuration/defaults/doraemon/status" \
|
||||||
|
-a -x /usr/sbin/doraemon; then
|
||||||
|
exit 0;
|
||||||
|
fi
|
||||||
|
stop; exit 0;
|
||||||
|
end script
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# 30script
|
||||||
|
#
|
||||||
|
exec /usr/sbin/doraemon -f /etc/httpd/doraemon/httpd.conf
|
9
root/etc/logrotate.d/doraemon
Normal file
9
root/etc/logrotate.d/doraemon
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/var/log/doraemon/*log {
|
||||||
|
missingok
|
||||||
|
notifempty
|
||||||
|
sharedscripts
|
||||||
|
delaycompress
|
||||||
|
postrotate
|
||||||
|
/sbin/reload doraemon > /dev/null 2>/dev/null || true
|
||||||
|
endscript
|
||||||
|
}
|
391
root/usr/share/doraemon/EsmithDatabase.php
Normal file
391
root/usr/share/doraemon/EsmithDatabase.php
Normal file
@ -0,0 +1,391 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2011 Nethesis S.r.l.
|
||||||
|
*
|
||||||
|
* This script is part of NethServer.
|
||||||
|
*
|
||||||
|
* NethServer is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* NethServer is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with NethServer. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read and write parameters into SME DB
|
||||||
|
*
|
||||||
|
* Ths class implements an interface to SME database executing the command /sbin/e-smith/db with sudo.
|
||||||
|
* The class needs /etc/sudoers configurazione. In the sudoers file you must have something like this:
|
||||||
|
* <code>
|
||||||
|
* Cmnd_Alias SME = /sbin/e-smith/db, /sbin/e-smith/signal-event
|
||||||
|
* www ALL=NOPASSWD: SME
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @author Giacomo Sanchietti <giacomo.sanchietti@nethesis.it>
|
||||||
|
* @author Davide Principi <davide.principi@nethesis.it>
|
||||||
|
* @since 1.0
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class EsmithDatabase
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var SME DB database command
|
||||||
|
* */
|
||||||
|
private $command = "/usr/bin/sudo /sbin/e-smith/db";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var $db Database name, it's translated into the db file path. For example: /home/e-smith/db/testdb
|
||||||
|
* */
|
||||||
|
private $db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This static class variable shares a socket connection to smwingsd
|
||||||
|
*
|
||||||
|
* @var resource
|
||||||
|
*/
|
||||||
|
private static $socket;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an object to access a SME Configuration database file
|
||||||
|
* with $user's privileges.
|
||||||
|
*
|
||||||
|
* @param string $database Database name
|
||||||
|
*/
|
||||||
|
public function __construct($database)
|
||||||
|
{
|
||||||
|
if ( ! $database)
|
||||||
|
sprintf("%s: You must provide a valid database name.", get_class($this));
|
||||||
|
|
||||||
|
$this->db = $database;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAll($type = NULL)
|
||||||
|
{
|
||||||
|
$output = "";
|
||||||
|
|
||||||
|
$ret = $this->dbRead('getjson', array(), $output);
|
||||||
|
if ($ret !== 0) {
|
||||||
|
sprintf("%s: internal database command failed!", __CLASS__);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = json_decode($output, TRUE);
|
||||||
|
if ( ! is_array($data)) {
|
||||||
|
sprintf("%s: unexpected json string `%s`", __CLASS__, substr($output, 0, 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = array();
|
||||||
|
|
||||||
|
foreach ($data as $item) {
|
||||||
|
// Apply type check filter:
|
||||||
|
if (isset($type) && $type !== $item['type']) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$props = isset($item['props']) ? $item['props'] : array();
|
||||||
|
$result[$item['name']] = array_merge($props, array('type' => $item['type']));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAllByProp($propName = NULL, $propValue = NULL)
|
||||||
|
{
|
||||||
|
$output = "";
|
||||||
|
|
||||||
|
$ret = $this->dbRead('getjson', array(), $output);
|
||||||
|
if ($ret !== 0) {
|
||||||
|
sprintf("%s: internal database command failed!", __CLASS__);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = json_decode($output, TRUE);
|
||||||
|
if ( ! is_array($data)) {
|
||||||
|
sprintf("%s: unexpected json string `%s`", __CLASS__, substr($output, 0, 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = array();
|
||||||
|
|
||||||
|
foreach ($data as $item) {
|
||||||
|
$item['props']['type'] = $item['type'];
|
||||||
|
$item['props']['name'] = $item['name'];
|
||||||
|
|
||||||
|
if (isset($propName) && isset($propValue)) {
|
||||||
|
if (isset($item['props'][$propName]) && $propValue == $item['props'][$propName]) {
|
||||||
|
$result[$item['name']] = $item['props'];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$result[$item['name']] = $item['props'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getKey($key)
|
||||||
|
{
|
||||||
|
$output = '';
|
||||||
|
|
||||||
|
$ret = $this->dbRead('getjson', array($key), $output);
|
||||||
|
if ($ret !== 0) {
|
||||||
|
sprintf("%s: internal database command failed", __CLASS__);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = json_decode($output, TRUE);
|
||||||
|
|
||||||
|
if ($data === 1) {
|
||||||
|
// Key has not been found
|
||||||
|
return array();
|
||||||
|
} elseif ( ! is_array($data)) {
|
||||||
|
sprintf("%s: unexpected json string `%s`", __CLASS__, substr($output, 0, 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
$data['props']['type'] = $data['type'];
|
||||||
|
$data['props']['name'] = $data['name'];
|
||||||
|
return $data['props'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getKeyValue($key)
|
||||||
|
{
|
||||||
|
$output = '';
|
||||||
|
|
||||||
|
$ret = $this->dbRead('getjson', array($key), $output);
|
||||||
|
if ($ret !== 0) {
|
||||||
|
sprintf("%s: internal database command failed", __CLASS__);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = json_decode($output, TRUE);
|
||||||
|
|
||||||
|
if ($data === 1) {
|
||||||
|
// Key has not been found
|
||||||
|
return array();
|
||||||
|
} elseif ( ! is_array($data)) {
|
||||||
|
sprintf("%s: unexpected json string `%s`", __CLASS__, substr($output, 0, 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data['type'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setKey($key, $type, $props)
|
||||||
|
{
|
||||||
|
$output = NULL;
|
||||||
|
$ret = $this->dbExec('set', $this->prepareArguments($key, $type, $props), $output);
|
||||||
|
return ($ret == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deleteKey($key)
|
||||||
|
{
|
||||||
|
$output = NULL;
|
||||||
|
$output = NULL;
|
||||||
|
$ret = $this->dbExec('delete', $this->prepareArguments($key), $output);
|
||||||
|
return ($ret == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the type of a key
|
||||||
|
* Act like: /sbin/e-smith/db dbfile gettype key
|
||||||
|
*
|
||||||
|
* @param string $key the key to retrieve
|
||||||
|
* @access public
|
||||||
|
* @return string the type of the key
|
||||||
|
*/
|
||||||
|
public function getType($key)
|
||||||
|
{
|
||||||
|
$output = NULL;
|
||||||
|
$ret = $this->dbRead('gettype', array($key), $output);
|
||||||
|
return trim($output);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the type of a key
|
||||||
|
* Act like: /sbin/e-smith/db dbfile settype key type
|
||||||
|
*
|
||||||
|
* @param string $key the key to change
|
||||||
|
* @param string $type the new type
|
||||||
|
* @access public
|
||||||
|
* @return bool true on success, FALSE otherwise
|
||||||
|
*/
|
||||||
|
public function setType($key, $type)
|
||||||
|
{
|
||||||
|
$output = NULL;
|
||||||
|
$ret = $this->dbExec('settype', $this->prepareArguments($key, $type), $output);
|
||||||
|
return ($ret == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getProp($key, $prop)
|
||||||
|
{
|
||||||
|
$output = NULL;
|
||||||
|
$ret = $this->dbRead('getprop', array($key, $prop), $output);
|
||||||
|
return trim($output);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setProp($key, $props)
|
||||||
|
{
|
||||||
|
$output = NULL;
|
||||||
|
$ret = $this->dbExec('setprop', $this->prepareArguments($key, $props), $output);
|
||||||
|
return ($ret == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delProp($key, $props)
|
||||||
|
{
|
||||||
|
$output = NULL;
|
||||||
|
$ret = $this->dbExec('delprop', array_merge(array($key), array_values($props)), $output);
|
||||||
|
return ($ret == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the db command
|
||||||
|
* @param string $command The command to invoke
|
||||||
|
* @param array $args The command arguments
|
||||||
|
* @param string &$output The output from the command process
|
||||||
|
* @return int The command exit code
|
||||||
|
*/
|
||||||
|
private function dbExec($command, $args, &$output)
|
||||||
|
{
|
||||||
|
// prepend the database name and command
|
||||||
|
array_unshift($args, $this->db, $command);
|
||||||
|
$exitCode = 0;
|
||||||
|
$oArr = array();
|
||||||
|
exec($this->command . ' ' . implode(' ', array_map('escapeshellarg', $args)), $oArr, $exitCode);
|
||||||
|
$output = implode("\n", $oArr);
|
||||||
|
return $exitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read db data from memory cache daemon
|
||||||
|
* @param string $command The command to invoke
|
||||||
|
* @param array $args The command arguments
|
||||||
|
* @param string &$output The output from the read socket
|
||||||
|
* @return int The command exit code
|
||||||
|
*/
|
||||||
|
private function dbRead($command, $args, &$output)
|
||||||
|
{
|
||||||
|
if ( ! isset(self::$socket) ) {
|
||||||
|
$socketPath = '/var/run/smwingsd.sock';
|
||||||
|
$errno = 0;
|
||||||
|
$errstr = '';
|
||||||
|
self::$socket = fsockopen('unix://' . $socketPath, -1, $errno, $errstr);
|
||||||
|
if( ! is_resource(self::$socket)) {
|
||||||
|
sprintf("Invalid socket (%d): %s. Fall back to exec().", $errno, $errstr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! is_resource(self::$socket)) {
|
||||||
|
return $this->dbExec($command, call_user_func_array(array($this, 'prepareArguments'), $args), $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepend the database name and command
|
||||||
|
array_unshift($args, $this->db, $command);
|
||||||
|
|
||||||
|
$ret = $this->sendMessage(self::$socket, 0x10, $args);
|
||||||
|
if ( ! $ret ) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
$ret = $this->recvMessage(self::$socket);
|
||||||
|
if ( ! $ret ) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ($command === 'getjson') {
|
||||||
|
$output = $ret;
|
||||||
|
} else {
|
||||||
|
$output = json_decode($ret, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function sendMessage($socket, $type, $args = array())
|
||||||
|
{
|
||||||
|
$payload = json_encode($args);
|
||||||
|
$data = pack('CN', (int) $type, strlen($payload)) . $payload;
|
||||||
|
$written = fwrite($socket, $data);
|
||||||
|
if ($written !== strlen($data)) {
|
||||||
|
echo 'Socket write error';
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function recvMessage($socket)
|
||||||
|
{
|
||||||
|
$buf = $this->safeRead($socket, 5);
|
||||||
|
if ($buf === FALSE) {
|
||||||
|
echo 'Socket read error';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$header = unpack('Ctype/Nsize', $buf);
|
||||||
|
if ( ! is_array($header)) {
|
||||||
|
echo 'Invalid message header';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$message = $this->safeRead($socket, $header['size']);
|
||||||
|
if ($message === FALSE) {
|
||||||
|
echo 'Socket read error';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($header['type'] & 0x02) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $message;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function safeRead($socket, $size)
|
||||||
|
{
|
||||||
|
$buffer = "";
|
||||||
|
$count = 0;
|
||||||
|
while($count < $size) {
|
||||||
|
if(feof($socket)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
$chunk = fread($socket, $size - $count);
|
||||||
|
$count += strlen($chunk);
|
||||||
|
if($chunk === FALSE) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
$buffer .= $chunk;
|
||||||
|
}
|
||||||
|
return $buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take arbitrary arguments and flattenize to an array
|
||||||
|
*
|
||||||
|
* @param mixed $_
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function prepareArguments()
|
||||||
|
{
|
||||||
|
$args = array();
|
||||||
|
|
||||||
|
foreach (func_get_args() as $arg) {
|
||||||
|
if (is_array($arg)) {
|
||||||
|
foreach ($arg as $propName => $propValue) {
|
||||||
|
$args[] = $propName;
|
||||||
|
$args[] = $propValue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$args[] = (String) $arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $args;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
261
root/usr/share/doraemon/index.php
Normal file
261
root/usr/share/doraemon/index.php
Normal file
@ -0,0 +1,261 @@
|
|||||||
|
<?php
|
||||||
|
include_once("EsmithDatabase.php");
|
||||||
|
define('CONFIG_KEY', 'doraemon');
|
||||||
|
|
||||||
|
$hosts_db = new EsmithDatabase('hosts');
|
||||||
|
$roles_db = new EsmithDatabase('roles');
|
||||||
|
$config_db = new EsmithDatabase('configuration');
|
||||||
|
|
||||||
|
$uri = $_SERVER['REQUEST_URI'];
|
||||||
|
// add leading '/' to uri string, works if $uri is empty
|
||||||
|
$uri = (substr($uri, 0, 1) == '/') ? $uri : '/' . $uri;
|
||||||
|
$pos = strpos($uri, '?');
|
||||||
|
if (false !== $pos) {
|
||||||
|
$route = substr($uri, 0, (int) $pos);
|
||||||
|
} else {
|
||||||
|
$route = $uri;
|
||||||
|
}
|
||||||
|
// remove trailing '/'
|
||||||
|
$route = rtrim($route, '/');
|
||||||
|
|
||||||
|
$query_string = $_SERVER['QUERY_STRING'];
|
||||||
|
$get_params = array();
|
||||||
|
parse_str($query_string, $get_params);
|
||||||
|
|
||||||
|
// determine internal function name (all lowercase, dash2underscore, named ROUTE_routename )
|
||||||
|
$function = preg_replace(':\-:', '_', strtolower($route));
|
||||||
|
$function = preg_replace(':^/:', 'ROUTE_', $function);
|
||||||
|
|
||||||
|
if (function_exists($function)) {
|
||||||
|
$function();
|
||||||
|
} else {
|
||||||
|
die('Go away.');
|
||||||
|
}
|
||||||
|
|
||||||
|
function varsForRole($role, $json=true) {
|
||||||
|
global $roles_db;
|
||||||
|
$result = $roles_db->getKey($role);
|
||||||
|
$return = array('role'=>$role,'delpkg'=>'','addpkg'=>'');
|
||||||
|
if (is_array($result)) {
|
||||||
|
if (is_string($result['Addpkg']))
|
||||||
|
$return['addpkg'] = preg_split("/[\s,]+/", $result['Addpkg']);
|
||||||
|
if (is_string($result['Delpkg']))
|
||||||
|
$return['delpkg'] = preg_split("/[\s,]+/", $result['Delpkg']);
|
||||||
|
}
|
||||||
|
if ($json) {
|
||||||
|
return json_encode($return);
|
||||||
|
} else {
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getClient($mac=false) {
|
||||||
|
global $hosts_db;
|
||||||
|
if (!$mac) {
|
||||||
|
$mac = getClientMac();
|
||||||
|
if (!$mac)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$hosts = $hosts_db->getAllByProp('MacAddress',$mac);
|
||||||
|
if (count($hosts)>0) {
|
||||||
|
return array_pop($hosts);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getClientMac($ip=false) {
|
||||||
|
if (false === $ip) {
|
||||||
|
$ip = $_SERVER['REMOTE_ADDR'];
|
||||||
|
}
|
||||||
|
$result = pingHost($ip,1);
|
||||||
|
if (!$result)
|
||||||
|
return false;
|
||||||
|
$macAddr=false;
|
||||||
|
$arptable=`arp -n $ip`;
|
||||||
|
$lines=explode("\n", $arptable);
|
||||||
|
foreach($lines as $line) {
|
||||||
|
$cols=preg_split('/\s+/', trim($line));
|
||||||
|
if ($cols[0]==$ip)
|
||||||
|
{
|
||||||
|
return $cols[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function newHostname($mac, $base, $role) {
|
||||||
|
global $config_db, $hosts_db;
|
||||||
|
if(!preg_match('/^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/', $mac)) {
|
||||||
|
echo "invalid mac address";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($client=getClient($mac)) {
|
||||||
|
echo $client['name'];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$domainName = (string)$config_db->getKeyValue('DomainName');
|
||||||
|
$digits = $config_db->getProp(CONFIG_KEY,'NamingDigits');
|
||||||
|
$formatstring = '%s-%0'.$digits.'d';
|
||||||
|
$nr=0;
|
||||||
|
$hostname = '';
|
||||||
|
do {
|
||||||
|
$nr++;
|
||||||
|
$hostname = sprintf($formatstring, $base, $nr);
|
||||||
|
# TODO: we'll use the hostname in future, maybe
|
||||||
|
# if (trim($domainName) != '') {
|
||||||
|
# $hostname .= '.' . $domainName;
|
||||||
|
# }
|
||||||
|
} while ($hosts_db->getKey($hostname));
|
||||||
|
|
||||||
|
$hosts_db->setKey($hostname, 'local', array(
|
||||||
|
'MacAddress' => $mac,
|
||||||
|
'Role' => $role,
|
||||||
|
'Description' => ''
|
||||||
|
));
|
||||||
|
|
||||||
|
echo $hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pingHost($host, $timeout=1) {
|
||||||
|
$pingresult = exec("/bin/ping -c 1 -t 2 -W $timeout $host", $output, $retvar);
|
||||||
|
return (0 == $retvar);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ROUTE_domain() {
|
||||||
|
global $config_db;
|
||||||
|
$theFile = $config_db->getProp(CONFIG_KEY,'DomainFile');
|
||||||
|
passthru("/usr/bin/sudo /bin/cat $theFile");
|
||||||
|
}
|
||||||
|
|
||||||
|
function ROUTE_mgmtkey() {
|
||||||
|
global $config_db;
|
||||||
|
$theFile = $config_db->getProp(CONFIG_KEY,'ManagementKeyFile');
|
||||||
|
passthru("/usr/bin/sudo /bin/cat $theFile");
|
||||||
|
}
|
||||||
|
|
||||||
|
function ROUTE_epoptes_srv() {
|
||||||
|
global $hosts_db;
|
||||||
|
$hosts = $hosts_db->getAllByProp('Role','docenti');
|
||||||
|
ksort($hosts);
|
||||||
|
if (count($hosts) == 0) {
|
||||||
|
echo 'none';
|
||||||
|
} else {
|
||||||
|
$host = array_pop($hosts);
|
||||||
|
echo $host['name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ROUTE_ansible_host() {
|
||||||
|
global $get_params;
|
||||||
|
if (isset($get_params['role'])) {
|
||||||
|
$role = $get_params['role'];
|
||||||
|
} elseif ($client = getClient()) {
|
||||||
|
$role = $client['Role'];
|
||||||
|
} else {
|
||||||
|
$role = 'unknown';
|
||||||
|
}
|
||||||
|
echo varsForRole($role);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ROUTE_hosts() {
|
||||||
|
global $hosts_db, $get_params;
|
||||||
|
if (isset($get_params['role'])) {
|
||||||
|
$items = $hosts_db->getAllByProp('Role', $get_params['role']);
|
||||||
|
} else {
|
||||||
|
$items = $hosts_db->getAll('local');
|
||||||
|
}
|
||||||
|
$results=array();
|
||||||
|
foreach ($items as $name=>$item) {
|
||||||
|
$results[]=array(
|
||||||
|
'mac'=>$item['MacAddress'],
|
||||||
|
'hostname'=>$name,
|
||||||
|
'role'=>$item['Role']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
echo json_encode($results);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ROUTE_ansible_list() {
|
||||||
|
global $get_params;
|
||||||
|
if (isset($get_params['role'])) {
|
||||||
|
$role = $get_params['role'];
|
||||||
|
} elseif ($client = getClient()) {
|
||||||
|
$role = $client['Role'];
|
||||||
|
} else {
|
||||||
|
$role = 'unknown';
|
||||||
|
}
|
||||||
|
$vars = varsForRole($role, false);
|
||||||
|
echo json_encode(array(
|
||||||
|
'localhost'=>array(
|
||||||
|
'hosts'=>array('localhost'),
|
||||||
|
'vars'=>array('ansible_connection'=>'local')
|
||||||
|
),
|
||||||
|
'_meta'=> array('hostvars'=>array('localhost'=>$vars))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
function ROUTE_vaultpass() {
|
||||||
|
global $config_db;
|
||||||
|
$theFile = $config_db->getProp(CONFIG_KEY,'VaultPassFile');
|
||||||
|
$oArr = array();
|
||||||
|
exec('/usr/bin/sudo /bin/cat ' . $theFile, $oArr, $exitCode);
|
||||||
|
$content = trim(implode("\n", $oArr));
|
||||||
|
if (false === $content) {
|
||||||
|
echo 'no file';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!$client = getClient()) {
|
||||||
|
echo 'no client';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$key = md5($client['name'], true);
|
||||||
|
$padlenght = 16 - (strlen($content) % 16);
|
||||||
|
$content_padded = $content . str_repeat('x', $padlenght);
|
||||||
|
$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $content_padded, MCRYPT_MODE_ECB);
|
||||||
|
echo base64_encode($ciphertext);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ROUTE_whatsmyhostname() {
|
||||||
|
global $config_db, $get_params;
|
||||||
|
if (isset($get_params['role'])) {
|
||||||
|
$role = $get_params['role'];
|
||||||
|
} else {
|
||||||
|
$role = $config_db->getProp(CONFIG_KEY,'DefaultRole');
|
||||||
|
}
|
||||||
|
if (isset($get_params['base'])) {
|
||||||
|
$base = $get_params['base'];
|
||||||
|
} else {
|
||||||
|
$base = $config_db->getProp(CONFIG_KEY,'NamingBase');
|
||||||
|
}
|
||||||
|
$mac = getClientMac();
|
||||||
|
if (!$mac) {
|
||||||
|
echo 'no-mac-address';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
newHostname($mac, $base, $role);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ROUTE_mac2hostname() {
|
||||||
|
global $config_db, $get_params;
|
||||||
|
if (isset($get_params['mac'])) {
|
||||||
|
$mac = $get_params['mac'];
|
||||||
|
} else {
|
||||||
|
echo 'Usage: GET /mac2hostname?mac=XX_XX_XX_XX_XX_XX[&base=YYY][&role=ZZZ]';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (isset($get_params['role'])) {
|
||||||
|
$role = $get_params['role'];
|
||||||
|
} else {
|
||||||
|
$role = $config_db->getProp(CONFIG_KEY,'DefaultRole');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($get_params['base'])) {
|
||||||
|
$base = $get_params['base'];
|
||||||
|
} else {
|
||||||
|
$base = $config_db->getProp(CONFIG_KEY,'NamingBase');
|
||||||
|
}
|
||||||
|
|
||||||
|
newHostname($mac, $base, $role);
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/* /usr/share/nethesis/NethServer/Language/en/NethServer_Module_Doraemon.php */
|
||||||
|
|
||||||
|
$L['Doraemon_Title'] = 'Doraemon';
|
||||||
|
$L['hostname_label'] = 'Hostname';
|
||||||
|
$L['MacAddress_label'] = 'MAC Address';
|
||||||
|
$L['shutdown_label'] = 'Shutdown';
|
||||||
|
$L['reboot_label'] = 'Reboot';
|
||||||
|
$L['wake_label'] = 'Wake Up';
|
||||||
|
$L['shutdown-all_label'] = 'Shutdown all';
|
||||||
|
$L['reboot-all_label'] = 'Reboot all';
|
||||||
|
$L['wake-all_label'] = 'Wake Up all';
|
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/* /usr/share/nethesis/NethServer/Language/en/NethServer_Module_Doraemon_Hosts.php */
|
||||||
|
|
||||||
|
$L['Hosts_Title'] = 'Hosts';
|
||||||
|
$L['Create_Host_Header'] = 'Create a new host';
|
||||||
|
$L['Update_Host_Header'] = 'Update host "${0}"';
|
||||||
|
$L['Role_label'] = 'Role';
|
||||||
|
$L['Key_label'] = 'Hostname';
|
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/* /usr/share/nethesis/NethServer/Language/it/NethServer_Module_Doraemon.php */
|
||||||
|
|
||||||
|
$L['Doraemon_Title'] = 'Doraemon';
|
||||||
|
$L['hostname_label'] = 'Hostname';
|
||||||
|
$L['MacAddress_label'] = 'MAC Address';
|
||||||
|
$L['shutdown_label'] = 'Spegni';
|
||||||
|
$L['reboot_label'] = 'Riavvia';
|
||||||
|
$L['wake_label'] = 'Accendi';
|
||||||
|
$L['shutdown-all_label'] = 'Spegni tutti';
|
||||||
|
$L['reboot-all_label'] = 'Riavvia tutti';
|
||||||
|
$L['wake-all_label'] = 'Accendi tutti';
|
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/* /usr/share/nethesis/NethServer/Language/it/NethServer_Module_Doraemon_Hosts.php */
|
||||||
|
|
||||||
|
$L['Hosts_Title'] = 'Hosts';
|
||||||
|
$L['Create_Host_Header'] = 'Crea un nuovo host';
|
||||||
|
$L['Update_Host_Header'] = 'Modifica il nome host "${0}"';
|
||||||
|
$L['Role_label'] = 'Ruolo';
|
||||||
|
$L['Key_label'] = 'Hostname';
|
17
root/usr/share/nethesis/NethServer/Module/Doraemon.php
Normal file
17
root/usr/share/nethesis/NethServer/Module/Doraemon.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
namespace NethServer\Module;
|
||||||
|
|
||||||
|
class Doraemon extends \Nethgui\Controller\TabsController
|
||||||
|
{
|
||||||
|
protected function initializeAttributes(\Nethgui\Module\ModuleAttributesInterface $base)
|
||||||
|
{
|
||||||
|
return \Nethgui\Module\SimpleModuleAttributesProvider::extendModuleAttributes($base, 'Configuration', 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function initialize()
|
||||||
|
{
|
||||||
|
parent::initialize();
|
||||||
|
$this->loadChildrenDirectory();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
36
root/usr/share/nethesis/NethServer/Module/Doraemon/Hosts.php
Normal file
36
root/usr/share/nethesis/NethServer/Module/Doraemon/Hosts.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace NethServer\Module\Doraemon;
|
||||||
|
|
||||||
|
|
||||||
|
class Hosts extends \Nethgui\Controller\TableController
|
||||||
|
{
|
||||||
|
|
||||||
|
public function initialize()
|
||||||
|
{
|
||||||
|
$columns = array(
|
||||||
|
'Key',
|
||||||
|
'MacAddress',
|
||||||
|
'Role',
|
||||||
|
'Actions',
|
||||||
|
);
|
||||||
|
|
||||||
|
$this
|
||||||
|
->setTableAdapter($this->getPlatform()->getTableAdapter('hosts', 'local'))
|
||||||
|
->setColumns($columns)
|
||||||
|
->addRowAction(new \NethServer\Module\Doraemon\Hosts\Modify('update'))
|
||||||
|
->addRowAction(new \NethServer\Module\Doraemon\Hosts\TogglePower('wake'))
|
||||||
|
->addRowAction(new \NethServer\Module\Doraemon\Hosts\TogglePower('reboot'))
|
||||||
|
->addRowAction(new \NethServer\Module\Doraemon\Hosts\TogglePower('shutdown'))
|
||||||
|
->addRowAction(new \NethServer\Module\Doraemon\Hosts\Modify('delete'))
|
||||||
|
->addTableAction(new \NethServer\Module\Doraemon\Hosts\Modify('create'))
|
||||||
|
->addTableAction(new \NethServer\Module\Doraemon\Hosts\TogglePowerAll('wake-all'))
|
||||||
|
->addTableAction(new \NethServer\Module\Doraemon\Hosts\TogglePowerAll('reboot-all'))
|
||||||
|
->addTableAction(new \NethServer\Module\Doraemon\Hosts\TogglePowerAll('shutdown-all'))
|
||||||
|
->addTableAction(new \Nethgui\Controller\Table\Help('Help'))
|
||||||
|
;
|
||||||
|
|
||||||
|
parent::initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace NethServer\Module\Doraemon\Hosts;
|
||||||
|
|
||||||
|
use Nethgui\System\PlatformInterface as Validate;
|
||||||
|
|
||||||
|
|
||||||
|
class Modify extends \Nethgui\Controller\Table\Modify
|
||||||
|
{
|
||||||
|
|
||||||
|
public function initialize()
|
||||||
|
{
|
||||||
|
$parameterSchema = array(
|
||||||
|
// was: Validate::HOSTNAME_FQDN, but we need hostname
|
||||||
|
array('hostname', Validate::HOSTNAME_SIMPLE, \Nethgui\Controller\Table\Modify::KEY),
|
||||||
|
array('MacAddress', Validate::MACADDRESS, \Nethgui\Controller\Table\Modify::FIELD),
|
||||||
|
array('Role', Validate::ANYTHING, \Nethgui\Controller\Table\Modify::FIELD),
|
||||||
|
// array('Role', Validate::ROLES_COLLECTION ??? TODO!!!, \Nethgui\Controller\Table\Modify::FIELD),
|
||||||
|
);
|
||||||
|
$this->setSchema($parameterSchema);
|
||||||
|
parent::initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function validate(\Nethgui\Controller\ValidationReportInterface $report)
|
||||||
|
{
|
||||||
|
if ($this->getIdentifier() === 'delete') {
|
||||||
|
$v = $this->createValidator()->platform('host-delete');
|
||||||
|
if ( ! $v->evaluate($this->parameters['hostname'])) {
|
||||||
|
$report->addValidationError($this, 'Key', $v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parent::validate($report);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function onParametersSaved($parameters)
|
||||||
|
{
|
||||||
|
$actionName = $this->getIdentifier();
|
||||||
|
if ($actionName === 'update') {
|
||||||
|
$actionName = 'modify';
|
||||||
|
}
|
||||||
|
$this->getPlatform()->signalEvent(sprintf('host-%s &', $actionName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function prepareView(\Nethgui\View\ViewInterface $view)
|
||||||
|
{
|
||||||
|
parent::prepareView($view);
|
||||||
|
$templates = array(
|
||||||
|
'create' => 'NethServer\Template\Doraemon\Hosts',
|
||||||
|
'update' => 'NethServer\Template\Doraemon\Hosts',
|
||||||
|
'delete' => 'Nethgui\Template\Table\Delete',
|
||||||
|
);
|
||||||
|
$view->setTemplate($templates[$this->getIdentifier()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
namespace NethServer\Module\Doraemon\Hosts;
|
||||||
|
|
||||||
|
use Nethgui\System\PlatformInterface as Validate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle host power status
|
||||||
|
*
|
||||||
|
* Fires events
|
||||||
|
* - doraemon-wake
|
||||||
|
* - doraemon-reboot
|
||||||
|
* - doraemon-shutdown
|
||||||
|
*/
|
||||||
|
class TogglePower extends \Nethgui\Controller\Table\AbstractAction
|
||||||
|
{
|
||||||
|
|
||||||
|
public function __construct($identifier = NULL)
|
||||||
|
{
|
||||||
|
if ($identifier !== 'wake' && $identifier !== 'reboot' && $identifier !== 'shutdown') {
|
||||||
|
throw new \InvalidArgumentException(sprintf('%s: module identifier must be one of "wake" or "reboot" or "shutdown".', get_class($this)), 1325579395);
|
||||||
|
}
|
||||||
|
parent::__construct($identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function bind(\Nethgui\Controller\RequestInterface $request)
|
||||||
|
{
|
||||||
|
$this->declareParameter('hostname', Validate::HOSTNAME_SIMPLE);
|
||||||
|
|
||||||
|
parent::bind($request);
|
||||||
|
$hostname = \Nethgui\array_end($request->getPath());
|
||||||
|
|
||||||
|
if ( ! $hostname) {
|
||||||
|
throw new \Nethgui\Exception\HttpException('Not found', 404, 1322148400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->parameters['hostname'] = $hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function process()
|
||||||
|
{
|
||||||
|
if ( ! $this->getRequest()->isMutation()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->getPlatform()->signalEvent(sprintf('doraemon-%s@post', $this->getIdentifier()), array($this->parameters['hostname']));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
namespace NethServer\Module\Doraemon\Hosts;
|
||||||
|
|
||||||
|
use Nethgui\System\PlatformInterface as Validate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle host power status
|
||||||
|
*
|
||||||
|
* Fires events
|
||||||
|
* - doraemon-wake-all
|
||||||
|
* - doraemon-reboot-all
|
||||||
|
* - doraemon-shutdown-all
|
||||||
|
*/
|
||||||
|
class TogglePowerAll extends \Nethgui\Controller\Table\AbstractAction
|
||||||
|
{
|
||||||
|
|
||||||
|
public function __construct($identifier = NULL)
|
||||||
|
{
|
||||||
|
if ($identifier !== 'wake-all' && $identifier !== 'reboot-all' && $identifier !== 'shutdown-all') {
|
||||||
|
throw new \InvalidArgumentException(sprintf('%s: module identifier must be one of "wake-all" or "reboot-all" or "shutdown-all".', get_class($this)), 1325579395);
|
||||||
|
}
|
||||||
|
parent::__construct($identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function process()
|
||||||
|
{
|
||||||
|
if ( ! $this->getRequest()->isMutation()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->getPlatform()->signalEvent(sprintf('doraemon-%s@post', $this->getIdentifier()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
/* @var $view \Nethgui\Renderer\Xhtml */
|
||||||
|
|
||||||
|
if ($view->getModule()->getIdentifier() == 'update') {
|
||||||
|
// disable updating of hostname
|
||||||
|
// the hostname is the key of the db item, if you change it, bad things happens
|
||||||
|
$keyFlags = $view::STATE_DISABLED;
|
||||||
|
$template = 'Update_Host_Header';
|
||||||
|
} else {
|
||||||
|
$keyFlags = 0;
|
||||||
|
$template = 'Create_Host_Header';
|
||||||
|
}
|
||||||
|
|
||||||
|
echo $view->header('hostname')->setAttribute('template', $T($template));
|
||||||
|
|
||||||
|
echo $view->panel()
|
||||||
|
->insert($view->textInput('hostname', $keyFlags))
|
||||||
|
->insert($view->textInput('MacAddress'))
|
||||||
|
->insert($view->textInput('Role'))
|
||||||
|
;
|
||||||
|
|
||||||
|
echo $view->buttonList($view::BUTTON_SUBMIT | $view::BUTTON_CANCEL | $view::BUTTON_HELP);
|
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
$view->requireFlag($view::INSET_DIALOG);
|
||||||
|
|
||||||
|
if ($view->getModule()->getIdentifier() == 'shutdown') {
|
||||||
|
$headerText = $T('Shutdown host `${0}`');
|
||||||
|
$panelText = $T('Proceed with host `${0}` shutdown?');
|
||||||
|
} elseif ($view->getModule()->getIdentifier() == 'reboot') {
|
||||||
|
$headerText = $T('Reboot host `${0}`');
|
||||||
|
$panelText = $T('Proceed with host `${0}` reboot?');
|
||||||
|
} else {
|
||||||
|
$headerText = $T('Wakeup host `${0}`');
|
||||||
|
$panelText = $T('Proceed with host `${0}` wakeup?');
|
||||||
|
}
|
||||||
|
|
||||||
|
echo $view->panel()
|
||||||
|
->insert($view->header('hostname')->setAttribute('template', $headerText))
|
||||||
|
->insert($view->textLabel('hostname')->setAttribute('template', $panelText))
|
||||||
|
;
|
||||||
|
|
||||||
|
echo $view->buttonList()
|
||||||
|
->insert($view->button('Yes', $view::BUTTON_SUBMIT))
|
||||||
|
->insert($view->button('No', $view::BUTTON_CANCEL)->setAttribute('value', $view['Cancel']))
|
||||||
|
;
|
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
$view->requireFlag($view::INSET_DIALOG);
|
||||||
|
|
||||||
|
if ($view->getModule()->getIdentifier() == 'shutdown-all') {
|
||||||
|
$headerText = $T('Shutdown all hosts');
|
||||||
|
$panelText = $T('Proceed with all hosts shutdown?');
|
||||||
|
} elseif ($view->getModule()->getIdentifier() == 'reboot-all') {
|
||||||
|
$headerText = $T('Reboot all hosts');
|
||||||
|
$panelText = $T('Proceed with all hosts reboot?');
|
||||||
|
} else {
|
||||||
|
$headerText = $T('Wakeup all hosts');
|
||||||
|
$panelText = $T('Proceed with all hosts wakeup?');
|
||||||
|
}
|
||||||
|
|
||||||
|
echo $view->header()->setAttribute('template', $headerText);
|
||||||
|
// TODO: add a text label here
|
||||||
|
// echo $view->textLabel()->setAttribute('template', $panelText);
|
||||||
|
echo $view->buttonList()
|
||||||
|
->insert($view->button('Yes', $view::BUTTON_SUBMIT))
|
||||||
|
->insert($view->button('No', $view::BUTTON_CANCEL)->setAttribute('value', $view['Cancel']))
|
||||||
|
;
|
Loading…
x
Reference in New Issue
Block a user