2014-11-30 04:59:27 -05:00
|
|
|
<?php
|
|
|
|
|
|
2014-11-30 09:56:58 -05:00
|
|
|
namespace Icinga\Module\Businessprocess\Storage;
|
2014-11-30 04:59:27 -05:00
|
|
|
|
2016-11-23 04:44:24 -05:00
|
|
|
use DirectoryIterator;
|
|
|
|
|
use Icinga\Application\Benchmark;
|
2014-11-30 04:59:27 -05:00
|
|
|
use Icinga\Application\Icinga;
|
2015-11-20 06:35:09 -05:00
|
|
|
use Icinga\Authentication\Auth;
|
2015-02-12 19:57:12 -05:00
|
|
|
use Icinga\Exception\ConfigurationError;
|
2014-11-30 09:56:58 -05:00
|
|
|
use Icinga\Module\Businessprocess\BpNode;
|
2016-11-23 04:44:24 -05:00
|
|
|
use Icinga\Module\Businessprocess\BusinessProcess;
|
2014-11-30 04:59:27 -05:00
|
|
|
use Icinga\Exception\SystemPermissionException;
|
|
|
|
|
|
|
|
|
|
class LegacyStorage extends Storage
|
|
|
|
|
{
|
2016-11-23 04:44:24 -05:00
|
|
|
/** @var string */
|
2014-11-30 04:59:27 -05:00
|
|
|
protected $configDir;
|
|
|
|
|
|
2016-11-23 04:44:24 -05:00
|
|
|
/** @var int */
|
2014-11-30 06:26:28 -05:00
|
|
|
protected $parsing_line_number;
|
|
|
|
|
|
2016-11-23 04:44:24 -05:00
|
|
|
/** @var string */
|
2015-02-12 19:57:12 -05:00
|
|
|
protected $currentFilename;
|
|
|
|
|
|
2014-11-30 04:59:27 -05:00
|
|
|
public function getConfigDir()
|
|
|
|
|
{
|
|
|
|
|
if ($this->configDir === null) {
|
2016-11-23 04:44:24 -05:00
|
|
|
$this->prepareDefaultConfigDir();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $this->configDir;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function prepareDefaultConfigDir()
|
|
|
|
|
{
|
|
|
|
|
$dir = Icinga::app()
|
|
|
|
|
->getModuleManager()
|
|
|
|
|
->getModule('businessprocess')
|
|
|
|
|
->getConfigDir();
|
|
|
|
|
|
|
|
|
|
// TODO: This is silly. We need Config::requireDirectory().
|
|
|
|
|
if (! is_dir($dir)) {
|
|
|
|
|
if (! is_dir(dirname($dir))) {
|
|
|
|
|
if (! @mkdir(dirname($dir))) {
|
|
|
|
|
throw new SystemPermissionException('Could not create config directory "%s"', dirname($dir));
|
2014-11-30 04:59:27 -05:00
|
|
|
}
|
|
|
|
|
}
|
2016-11-23 04:44:24 -05:00
|
|
|
if (! mkdir($dir)) {
|
|
|
|
|
throw new SystemPermissionException('Could not create config directory "%s"', $dir);
|
2014-11-30 04:59:27 -05:00
|
|
|
}
|
|
|
|
|
}
|
2016-11-23 04:44:24 -05:00
|
|
|
$dir = $dir . '/processes';
|
|
|
|
|
if (! is_dir($dir)) {
|
|
|
|
|
if (! mkdir($dir)) {
|
|
|
|
|
throw new SystemPermissionException('Could not create config directory "%s"', $dir);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->configDir = $dir;
|
2014-11-30 04:59:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
|
|
|
|
public function listProcesses()
|
|
|
|
|
{
|
|
|
|
|
$files = array();
|
2015-11-20 06:35:09 -05:00
|
|
|
|
2014-11-30 04:59:27 -05:00
|
|
|
foreach (new DirectoryIterator($this->getConfigDir()) as $file) {
|
|
|
|
|
if($file->isDot()) continue;
|
|
|
|
|
$filename = $file->getFilename();
|
|
|
|
|
if (substr($filename, -5) === '.conf') {
|
|
|
|
|
$name = substr($filename, 0, -5);
|
2014-12-01 07:57:57 -05:00
|
|
|
$header = $this->readHeader($file->getPathname(), $name);
|
2015-11-20 06:35:09 -05:00
|
|
|
if (! $this->headerPermissionsAreSatisfied($header)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-16 04:08:00 -04:00
|
|
|
if ($header['Title'] === null) {
|
|
|
|
|
$files[$name] = $name;
|
|
|
|
|
} else {
|
|
|
|
|
$files[$name] = sprintf('%s (%s)', $header['Title'], $name);
|
|
|
|
|
}
|
2014-11-30 04:59:27 -05:00
|
|
|
}
|
|
|
|
|
}
|
2015-11-02 11:25:51 -05:00
|
|
|
|
|
|
|
|
natsort($files);
|
2014-11-30 04:59:27 -05:00
|
|
|
return $files;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-20 06:35:09 -05:00
|
|
|
protected function headerPermissionsAreSatisfied($header)
|
|
|
|
|
{
|
|
|
|
|
if (Icinga::app()->isCli()) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
$header['Allowed users'] === null
|
|
|
|
|
&& $header['Allowed groups'] === null
|
|
|
|
|
&& $header['Allowed roles'] === null
|
|
|
|
|
) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$auth = Auth::getInstance();
|
|
|
|
|
if (! $auth->isAuthenticated()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$user = $auth->getUser();
|
|
|
|
|
$username = $user->getUsername();
|
|
|
|
|
|
|
|
|
|
if ($header['Owner'] === $username) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($header['Allowed users'] !== null) {
|
|
|
|
|
$users = $this->splitCommaSeparated($header['Allowed users']);
|
|
|
|
|
foreach ($users as $allowedUser) {
|
|
|
|
|
if ($username === $allowedUser) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($header['Allowed groups'] !== null) {
|
|
|
|
|
$groups = $this->splitCommaSeparated($header['Allowed groups']);
|
|
|
|
|
foreach ($groups as $group) {
|
|
|
|
|
if ($user->isMemberOf($group)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($header['Allowed roles'] !== null) {
|
|
|
|
|
// TODO: not implemented yet
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function splitCommaSeparated($string)
|
|
|
|
|
{
|
|
|
|
|
return preg_split('/\s*,\s*/', $string, -1, PREG_SPLIT_NO_EMPTY);
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-01 07:57:57 -05:00
|
|
|
protected function readHeader($file, $name)
|
|
|
|
|
{
|
|
|
|
|
$fh = fopen($file, 'r');
|
|
|
|
|
$cnt = 0;
|
|
|
|
|
$header = array(
|
2015-11-20 06:35:09 -05:00
|
|
|
'Title' => null,
|
|
|
|
|
'Owner' => null,
|
|
|
|
|
'Allowed users' => null,
|
|
|
|
|
'Allowed groups' => null,
|
|
|
|
|
'Allowed roles' => null,
|
|
|
|
|
'Backend' => null,
|
|
|
|
|
'Statetype' => 'soft',
|
|
|
|
|
'SLA Hosts' => null
|
2014-12-01 07:57:57 -05:00
|
|
|
);
|
|
|
|
|
while ($cnt < 15 && false !== ($line = fgets($fh))) {
|
|
|
|
|
$cnt++;
|
|
|
|
|
if (preg_match('/^\s*#\s+(.+?)\s*:\s*(.+)$/', $line, $m)) {
|
|
|
|
|
if (array_key_exists($m[1], $header)) {
|
|
|
|
|
$header[$m[1]] = $m[2];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-11-22 18:42:22 -05:00
|
|
|
|
|
|
|
|
fclose($fh);
|
2014-12-01 07:57:57 -05:00
|
|
|
return $header;
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-30 04:59:27 -05:00
|
|
|
/**
|
|
|
|
|
*/
|
2015-03-02 12:23:19 -05:00
|
|
|
public function storeProcess(BusinessProcess $process)
|
2014-11-30 04:59:27 -05:00
|
|
|
{
|
2015-03-02 12:23:19 -05:00
|
|
|
$filename = $this->getFilename($process->getName());
|
|
|
|
|
$content = $process->toLegacyConfigString();
|
|
|
|
|
file_put_contents(
|
|
|
|
|
$filename,
|
|
|
|
|
$content
|
|
|
|
|
);
|
2014-11-30 04:59:27 -05:00
|
|
|
}
|
|
|
|
|
|
2015-03-16 04:08:00 -04:00
|
|
|
public function getSource($name)
|
|
|
|
|
{
|
|
|
|
|
return file_get_contents($this->getFilename($name));
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-12 19:57:12 -05:00
|
|
|
public function getFilename($name)
|
|
|
|
|
{
|
|
|
|
|
return $this->getConfigDir() . '/' . $name . '.conf';
|
|
|
|
|
}
|
2014-11-30 04:59:27 -05:00
|
|
|
|
2015-03-03 05:44:19 -05:00
|
|
|
public function loadFromString($name, $string)
|
|
|
|
|
{
|
|
|
|
|
$bp = new BusinessProcess();
|
|
|
|
|
$bp->setName($name);
|
|
|
|
|
$this->parseString($string, $bp);
|
2016-11-23 04:44:24 -05:00
|
|
|
// $this->loadHeader($name, $bp);
|
2015-03-03 05:44:19 -05:00
|
|
|
return $bp;
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-23 04:44:24 -05:00
|
|
|
/**
|
|
|
|
|
* @inheritdoc
|
|
|
|
|
*/
|
2015-03-16 04:08:00 -04:00
|
|
|
public function deleteProcess($name)
|
|
|
|
|
{
|
2016-11-23 04:44:24 -05:00
|
|
|
return @unlink($this->getFilename($name));
|
2015-03-16 04:08:00 -04:00
|
|
|
}
|
|
|
|
|
|
2015-03-03 05:44:19 -05:00
|
|
|
/**
|
|
|
|
|
* @return BusinessProcess
|
|
|
|
|
*/
|
|
|
|
|
public function loadProcess($name)
|
2014-11-30 04:59:27 -05:00
|
|
|
{
|
2015-03-16 04:08:00 -04:00
|
|
|
Benchmark::measure('Loading business process ' . $name);
|
2014-11-30 04:59:27 -05:00
|
|
|
$bp = new BusinessProcess();
|
2014-12-02 05:35:50 -05:00
|
|
|
$bp->setName($name);
|
2015-03-03 05:44:19 -05:00
|
|
|
$this->parseFile($name, $bp);
|
|
|
|
|
$this->loadHeader($name, $bp);
|
2015-03-16 04:08:00 -04:00
|
|
|
Benchmark::measure('Business process ' . $name . ' loaded');
|
2015-03-03 05:44:19 -05:00
|
|
|
return $bp;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-22 18:43:17 -05:00
|
|
|
public function hasProcess($name)
|
|
|
|
|
{
|
|
|
|
|
$file = $this->getFilename($name);
|
|
|
|
|
if (! is_file($file)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$name = substr($file, 0, -5);
|
|
|
|
|
$header = $this->readHeader($file, $name);
|
|
|
|
|
return $this->headerPermissionsAreSatisfied($header);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-03 05:44:19 -05:00
|
|
|
protected function loadHeader($name, $bp)
|
|
|
|
|
{
|
|
|
|
|
// TODO: do not open twice, this is quick and dirty based on existing code
|
|
|
|
|
$file = $this->currentFilename = $this->getFilename($name);
|
|
|
|
|
$header = $this->readHeader($file, $name);
|
|
|
|
|
$bp->setTitle($header['Title']);
|
|
|
|
|
if ($header['Backend']) {
|
2015-03-16 04:08:00 -04:00
|
|
|
$bp->setBackendName($header['Backend']);
|
|
|
|
|
}
|
|
|
|
|
if ($header['Statetype'] === 'soft') {
|
|
|
|
|
$bp->useSoftStates();
|
2015-03-03 05:44:19 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function parseFile($name, $bp)
|
|
|
|
|
{
|
|
|
|
|
$file = $this->currentFilename = $this->getFilename($name);
|
2014-11-30 04:59:27 -05:00
|
|
|
$fh = @fopen($file, 'r');
|
|
|
|
|
if (! $fh) {
|
2015-10-01 16:38:43 -04:00
|
|
|
throw new SystemPermissionException('Could not open "%s"', $file);
|
2014-11-30 04:59:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->parsing_line_number = 0;
|
|
|
|
|
while ($line = fgets($fh)) {
|
2015-03-03 05:44:19 -05:00
|
|
|
$this->parseLine($line, $bp);
|
|
|
|
|
}
|
2014-11-30 04:59:27 -05:00
|
|
|
|
2015-03-03 05:44:19 -05:00
|
|
|
fclose($fh);
|
|
|
|
|
unset($this->parsing_line_number);
|
|
|
|
|
unset($this->currentFilename);
|
|
|
|
|
}
|
2014-11-30 04:59:27 -05:00
|
|
|
|
2015-03-03 05:44:19 -05:00
|
|
|
protected function parseString($string, $bp)
|
|
|
|
|
{
|
|
|
|
|
foreach (preg_split('/\n/', $string) as $line) {
|
|
|
|
|
$this->parseLine($line, $bp);
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-11-30 04:59:27 -05:00
|
|
|
|
2015-03-03 05:44:19 -05:00
|
|
|
protected function parseLine(& $line, $bp)
|
|
|
|
|
{
|
|
|
|
|
$line = trim($line);
|
2014-11-30 04:59:27 -05:00
|
|
|
|
2015-03-03 05:44:19 -05:00
|
|
|
$this->parsing_line_number++;
|
2014-11-30 04:59:27 -05:00
|
|
|
|
2015-03-03 05:44:19 -05:00
|
|
|
if (empty($line)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if ($line[0] === '#') {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2014-11-30 04:59:27 -05:00
|
|
|
|
2015-03-03 05:44:19 -05:00
|
|
|
// TODO: substr?
|
|
|
|
|
if (preg_match('~^display~', $line)) {
|
|
|
|
|
list($display, $name, $desc) = preg_split('~\s*;\s*~', substr($line, 8), 3);
|
|
|
|
|
$node = $bp->getNode($name)->setAlias($desc)->setDisplay($display);
|
|
|
|
|
if ($display > 0) {
|
|
|
|
|
$bp->addRootNode($name);
|
2014-11-30 04:59:27 -05:00
|
|
|
}
|
2015-09-11 08:05:08 -04:00
|
|
|
return;
|
2015-03-03 05:44:19 -05:00
|
|
|
}
|
2014-11-30 04:59:27 -05:00
|
|
|
|
2015-03-03 05:44:19 -05:00
|
|
|
if (preg_match('~^external_info~', $line)) {
|
|
|
|
|
list($name, $script) = preg_split('~\s*;\s*~', substr($line, 14), 2);
|
|
|
|
|
$node = $bp->getNode($name)->setInfoCommand($script);
|
2015-09-11 08:05:08 -04:00
|
|
|
return;
|
2015-03-03 05:44:19 -05:00
|
|
|
}
|
2014-11-30 04:59:27 -05:00
|
|
|
|
2015-03-03 05:44:19 -05:00
|
|
|
// New feature:
|
|
|
|
|
// if (preg_match('~^extra_info~', $line)) {
|
|
|
|
|
// list($name, $script) = preg_split('~\s*;\s*~', substr($line, 14), 2);
|
|
|
|
|
// $node = $this->getNode($name)->setExtraInfo($script);
|
|
|
|
|
// }
|
2014-11-30 04:59:27 -05:00
|
|
|
|
2015-03-03 05:44:19 -05:00
|
|
|
if (preg_match('~^info_url~', $line)) {
|
|
|
|
|
list($name, $url) = preg_split('~\s*;\s*~', substr($line, 9), 2);
|
|
|
|
|
$node = $bp->getNode($name)->setInfoUrl($url);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2015-09-11 08:05:08 -04:00
|
|
|
|
2015-03-03 05:44:19 -05:00
|
|
|
list($name, $value) = preg_split('~\s*=\s*~', $line, 2);
|
2014-11-30 04:59:27 -05:00
|
|
|
|
2015-03-03 05:44:19 -05:00
|
|
|
if (strpos($name, ';') !== false) {
|
|
|
|
|
$this->parseError('No semicolon allowed in varname');
|
|
|
|
|
}
|
2015-01-28 13:59:10 -05:00
|
|
|
|
2015-03-03 05:44:19 -05:00
|
|
|
$op = '&';
|
2015-10-05 10:42:04 -04:00
|
|
|
if (preg_match_all('~([\|\+&\!])~', $value, $m)) {
|
2015-03-03 05:44:19 -05:00
|
|
|
$op = implode('', $m[1]);
|
|
|
|
|
for ($i = 1; $i < strlen($op); $i++) {
|
|
|
|
|
if ($op[$i] !== $op[$i - 1]) {
|
|
|
|
|
$this->parseError('Mixing operators is not allowed');
|
2015-02-12 19:57:12 -05:00
|
|
|
}
|
2014-11-30 04:59:27 -05:00
|
|
|
}
|
2015-03-03 05:44:19 -05:00
|
|
|
}
|
|
|
|
|
$op = $op[0];
|
|
|
|
|
$op_name = $op;
|
2015-01-28 13:59:10 -05:00
|
|
|
|
2015-03-03 05:44:19 -05:00
|
|
|
if ($op === '+') {
|
|
|
|
|
if (! preg_match('~^(\d+)\s*of:\s*(.+?)$~', $value, $m)) {
|
|
|
|
|
$this->parseError('syntax: <var> = <num> of: <var1> + <var2> [+ <varn>]*');
|
|
|
|
|
}
|
|
|
|
|
$op_name = $m[1];
|
|
|
|
|
$value = $m[2];
|
2014-11-30 04:59:27 -05:00
|
|
|
}
|
2015-10-05 10:37:10 -04:00
|
|
|
$cmps = preg_split('~\s*\\' . $op . '\s*~', $value, -1, PREG_SPLIT_NO_EMPTY);
|
2015-11-22 18:46:18 -05:00
|
|
|
$childNames = array();
|
2014-11-30 04:59:27 -05:00
|
|
|
|
2015-11-22 18:46:18 -05:00
|
|
|
foreach ($cmps as $val) {
|
2015-03-03 05:44:19 -05:00
|
|
|
if (strpos($val, ';') !== false) {
|
|
|
|
|
if ($bp->hasNode($val)) continue;
|
2015-02-06 18:22:52 -05:00
|
|
|
|
2015-03-03 05:44:19 -05:00
|
|
|
list($host, $service) = preg_split('~;~', $val, 2);
|
|
|
|
|
if ($service === 'Hoststatus') {
|
|
|
|
|
$bp->createHost($host);
|
|
|
|
|
} else {
|
|
|
|
|
$bp->createService($host, $service);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ($val[0] === '@' && strpos($val, ':') !== false) {
|
|
|
|
|
list($config, $nodeName) = preg_split('~:\s*~', substr($val, 1), 2);
|
|
|
|
|
$bp->createImportedNode($config, $nodeName);
|
|
|
|
|
$val = $nodeName;
|
|
|
|
|
}
|
2015-11-22 18:46:18 -05:00
|
|
|
|
|
|
|
|
$childNames[] = $val;
|
2015-02-06 18:49:32 -05:00
|
|
|
}
|
2015-02-06 18:22:52 -05:00
|
|
|
|
2015-03-03 05:44:19 -05:00
|
|
|
$node = new BpNode($bp, (object) array(
|
|
|
|
|
'name' => $name,
|
|
|
|
|
'operator' => $op_name,
|
2015-11-22 18:46:18 -05:00
|
|
|
'child_names' => $childNames
|
2015-03-03 05:44:19 -05:00
|
|
|
));
|
2015-11-22 18:46:18 -05:00
|
|
|
|
2015-03-03 05:44:19 -05:00
|
|
|
$bp->addNode($name, $node);
|
2014-11-30 04:59:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function parseError($msg)
|
|
|
|
|
{
|
2015-02-12 19:57:12 -05:00
|
|
|
throw new ConfigurationError(
|
2014-11-30 04:59:27 -05:00
|
|
|
sprintf(
|
|
|
|
|
'Parse error on %s:%s: %s',
|
2015-02-12 19:57:12 -05:00
|
|
|
$this->currentFilename,
|
2014-11-30 04:59:27 -05:00
|
|
|
$this->parsing_line_number,
|
|
|
|
|
$msg
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|