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