forked from LibreSchool/doraemon
PHP rewrite, first release
This commit is contained in:
parent
9653ef9014
commit
cc8a26960a
97
da_integrare.spec
Normal file
97
da_integrare.spec
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
Summary: apache/mod_php stack for Doraemon
|
||||||
|
Name: doraemon
|
||||||
|
Version: 1.3.0.1
|
||||||
|
Release: 1%{?dist}
|
||||||
|
License: GPL
|
||||||
|
URL: %{url_prefix}/%{name}
|
||||||
|
BuildArch: noarch
|
||||||
|
|
||||||
|
Source0: %{name}-%{version}.tar.gz
|
||||||
|
|
||||||
|
|
||||||
|
BuildRequires: nethserver-devtools
|
||||||
|
|
||||||
|
BuildRequires: systemd
|
||||||
|
Requires(post): systemd
|
||||||
|
Requires(preun): systemd
|
||||||
|
Requires(postun): systemd
|
||||||
|
|
||||||
|
Requires: httpd, php, sudo, php-xml, php-mcrypt, nethserver-httpd-admin
|
||||||
|
Requires: nethserver-base, nethserver-php
|
||||||
|
Requires: nethserver-lang-en
|
||||||
|
|
||||||
|
%description
|
||||||
|
Runs an Apache instance on port 3000 that serves
|
||||||
|
the doraemon web application
|
||||||
|
|
||||||
|
%prep
|
||||||
|
%setup
|
||||||
|
|
||||||
|
|
||||||
|
# Nethgui:
|
||||||
|
cd %{_builddir}/nethgui-%{nethgui_commit}
|
||||||
|
|
||||||
|
%build
|
||||||
|
perl createlinks
|
||||||
|
mkdir -p root/%{_nseventsdir}/%{name}-update
|
||||||
|
|
||||||
|
%install
|
||||||
|
(cd root ; find . -depth -print | cpio -dump %{buildroot})
|
||||||
|
rm -f %{name}-%{version}-%{release}-filelist
|
||||||
|
%{genfilelist} %{buildroot} \
|
||||||
|
> %{name}-%{version}-%{release}-filelist
|
||||||
|
mkdir -p %{buildroot}/%{_localstatedir}/log/doraemon
|
||||||
|
mkdir -p %{buildroot}/%{_localstatedir}/cache/doraemon
|
||||||
|
|
||||||
|
# Copy the server-manager dir
|
||||||
|
mkdir -p %{buildroot}%{_nsuidir}
|
||||||
|
cp -av nethserver-manager %{buildroot}%{_nsuidir}/nethserver-manager
|
||||||
|
|
||||||
|
%files -f %{name}-%{version}-%{release}-filelist
|
||||||
|
%defattr(-,root,root)
|
||||||
|
%doc %{extradocs}
|
||||||
|
|
||||||
|
%{_nsuidir}/nethserver-manager
|
||||||
|
|
||||||
|
|
||||||
|
%dir %{_nseventsdir}/%{name}-update
|
||||||
|
%dir %{_sysconfdir}/httpd/doraemon.d
|
||||||
|
|
||||||
|
%attr(0750,srvmgr,srvmgr) %dir %{_localstatedir}/cache/doraemon
|
||||||
|
%attr(0644,root,root) %ghost %{_sysconfdir}/init/doraemon.conf
|
||||||
|
%attr(0644,root,root) %ghost %{_sysconfdir}/httpd/doraemon/httpd.conf
|
||||||
|
%attr(0700,root,root) %dir %{_localstatedir}/log/doraemon
|
||||||
|
%attr(0644,root,root) %config %ghost %{_localstatedir}/log/doraemon/access_log
|
||||||
|
%attr(0644,root,root) %config %ghost %{_localstatedir}/log/doraemon/error_log
|
||||||
|
%config(noreplace) /etc/sysconfig/doraemon
|
||||||
|
|
||||||
|
%post
|
||||||
|
%systemd_post doraemon.service
|
||||||
|
|
||||||
|
%preun
|
||||||
|
%systemd_preun doraemon.service
|
||||||
|
|
||||||
|
%postun
|
||||||
|
%systemd_postun
|
||||||
|
|
||||||
|
%changelog
|
||||||
|
* Tue Oct 27 2015 Emiliano Vavassori <syntaxerrormmm-AT-gmail.com> - 1.2.1-2.ns6
|
||||||
|
- Packing corrections to rpm to fix upgrading issue
|
||||||
|
|
||||||
|
* Tue Oct 27 2015 Emiliano Vavassori <syntaxerrormmm-AT-gmail.com> - 1.2.1-1.ns6
|
||||||
|
- Packing new minor correction on how packages are extracted from db
|
||||||
|
|
||||||
|
* Mon Sep 11 2015 Emiliano Vavassori <syntaxerrormmm-AT-gmail.com> - 1.2.0-1.ns6
|
||||||
|
- Packing new version with ansible dynamic inventory support, epoptes server role support.
|
||||||
|
|
||||||
|
* Mon Sep 07 2015 Emiliano Vavassori <syntaxerrormmm-AT-gmail.com> - 1.1.1-1.ns6
|
||||||
|
- Packing new version with correct roles.
|
||||||
|
|
||||||
|
* Sun Sep 06 2015 Emiliano Vavassori <syntaxerrormmm-AT-gmail.com> - 1.1.0-1.ns6
|
||||||
|
- Packing new version with new functionalities.
|
||||||
|
|
||||||
|
* Wed Jul 15 2015 Emiliano Vavassori <syntaxerrormmm-AT-gmail.com> - 1.0.0-2.ns6
|
||||||
|
- Added logrotate file.
|
||||||
|
|
||||||
|
* Mon Jul 13 2015 Emiliano Vavassori <syntaxerrormmm-AT-gmail.com> - 1.0.0-1.ns6
|
||||||
|
- Unique binary for both ansiblehelper and mac2hostname.
|
@ -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()
|
|
391
doraemon/EsmithDatabase.php
Normal file
391
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
254
doraemon/index.php
Normal file
254
doraemon/index.php
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
<?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'] = $result['Addpkg'];
|
||||||
|
if (is_string($result['Delpkg'])) $return['Delpkg'] = $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 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');
|
||||||
|
$content = file_get_contents($theFile);
|
||||||
|
if (false !== $content) {
|
||||||
|
echo $content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ROUTE_mgmtkey() {
|
||||||
|
global $config_db;
|
||||||
|
$theFile = $config_db->getProp(CONFIG_KEY,'ManagementKeyFile');
|
||||||
|
$content = file_get_contents($theFile);
|
||||||
|
if (false !== $content) {
|
||||||
|
echo $content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ROUTE_epoptes_srv() {
|
||||||
|
global $hosts_db;
|
||||||
|
$hosts = $hosts_db->getAllByProp('Role','docenti');
|
||||||
|
if (count($hosts) == 0) {
|
||||||
|
echo 'none';
|
||||||
|
} else {
|
||||||
|
$host = array_pop($hosts);
|
||||||
|
echo json_encode($host);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
global $get_params;
|
||||||
|
if (isset($get_params['role'])) {
|
||||||
|
$items = $hosts_db->getAllByProp('Role', $get_params['role']);
|
||||||
|
} else {
|
||||||
|
$items = $hosts_db->getAll();
|
||||||
|
}
|
||||||
|
$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');
|
||||||
|
$content = trim(file_get_contents($theFile));
|
||||||
|
if (false === $content) {
|
||||||
|
echo 'no file'; return;
|
||||||
|
}
|
||||||
|
if (!$client = getClient()) {
|
||||||
|
echo 'no client'; return;
|
||||||
|
}
|
||||||
|
$key = md5($client['name']);
|
||||||
|
$padlenght = 16 - (strlen($content) % 16);
|
||||||
|
$content_padded = 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;
|
||||||
|
$mac = getClientMac();
|
||||||
|
if (!$mac) return false;
|
||||||
|
$base = $config_db->getProp(CONFIG_KEY,'NamingBase');
|
||||||
|
$role = $config_db->getProp(CONFIG_KEY,'DefaultRole');
|
||||||
|
echo newHostname($mac, $base, $role);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ROUTE_mac2hostname() {
|
||||||
|
global $config_db;
|
||||||
|
global $get_params;
|
||||||
|
$mac = getClientMac();
|
||||||
|
if (!$mac) {
|
||||||
|
echo 'Usage: GET /mac2hostname?mac=XX_XX_XX_XX_XX_XX[&base=YYY][&role=ZZZ]';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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');
|
||||||
|
}
|
||||||
|
|
||||||
|
echo newHostname($mac, $base, $role);
|
||||||
|
}
|
||||||
|
|
||||||
|
function newHostname($mac, $base, $role) {
|
||||||
|
global $config_db;
|
||||||
|
global $hosts_db;
|
||||||
|
if(!preg_match('/^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/', $mac)) {
|
||||||
|
echo "invalid mac address";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($client=getClient($mac)) {
|
||||||
|
echo $client['name'];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$domainName = $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);
|
||||||
|
if ($domainName != '') {
|
||||||
|
$hostname .= '.' . $domainname;
|
||||||
|
}
|
||||||
|
} while ($hosts_db->getKey($hostname));
|
||||||
|
|
||||||
|
$hosts_db->setKey($hostname, 'remote', array(
|
||||||
|
'MacAddress' => $mac,
|
||||||
|
'Role' => $role,
|
||||||
|
'Description' => ''
|
||||||
|
));
|
||||||
|
|
||||||
|
echo $hostname;
|
||||||
|
}
|
||||||
|
|
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
|
@ -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
|
0
root/etc/httpd/doraemon/.gitignore
vendored
Normal file
0
root/etc/httpd/doraemon/.gitignore
vendored
Normal file
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
|
||||||
|
}
|
8
root/etc/sysconfig/doraemon
Normal file
8
root/etc/sysconfig/doraemon
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#
|
||||||
|
# This file can be used to set additional environment variables for
|
||||||
|
# the httpd-admin process, or pass additional options to the
|
||||||
|
# httpd-admin executable. See httpd-admin.service unit.
|
||||||
|
#
|
||||||
|
|
||||||
|
LANG=C
|
||||||
|
|
9
root/usr/lib/systemd/system/doraemon-reload.service
Normal file
9
root/usr/lib/systemd/system/doraemon-reload.service
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Graceful restart of doraemon service
|
||||||
|
Documentation=https://github.com/bglug-it/doraemon
|
||||||
|
Requisite=doraemon.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=/usr/sbin/httpd -f /etc/httpd/doraemon/httpd.conf -k graceful
|
||||||
|
|
9
root/usr/lib/systemd/system/doraemon-reload.timer
Normal file
9
root/usr/lib/systemd/system/doraemon-reload.timer
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Delayed graceful restart of doraemon service
|
||||||
|
Documentation=https://github.com/bglug-it/doraemon
|
||||||
|
Conflicts=doraemon-reload.service
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
OnActiveSec=5
|
||||||
|
|
||||||
|
|
14
root/usr/lib/systemd/system/doraemon.service
Normal file
14
root/usr/lib/systemd/system/doraemon.service
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Doraemon httpd instance
|
||||||
|
Documentation=https://github.com/bglug-it/doraemon
|
||||||
|
After=network.target remote-fs.target nss-lookup.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
EnvironmentFile=/etc/sysconfig/doraemon
|
||||||
|
ExecStart=/usr/sbin/httpd -f /etc/httpd/doraemon/httpd.conf -c 'MaxConnectionsPerChild 12' -DFOREGROUND
|
||||||
|
ExecReload=/usr/sbin/httpd -f /etc/httpd/doraemon/httpd.conf -k graceful
|
||||||
|
LimitNOFILE=4096
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
1
root/usr/sbin/doraemon
Symbolic link
1
root/usr/sbin/doraemon
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
httpd
|
Loading…
x
Reference in New Issue
Block a user