2015-12-18 10:51:38 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Icinga\Module\Director\Forms;
|
|
|
|
|
2016-03-07 01:10:56 +01:00
|
|
|
use Exception;
|
2016-03-21 19:23:17 +01:00
|
|
|
use Icinga\Application\Config;
|
|
|
|
use Icinga\Data\ResourceFactory;
|
|
|
|
use Icinga\Module\Director\Db;
|
2016-03-13 23:48:22 +01:00
|
|
|
use Icinga\Module\Director\Db\Migrations;
|
2016-02-18 20:47:06 +01:00
|
|
|
use Icinga\Module\Director\KickstartHelper;
|
2015-12-18 10:51:38 +01:00
|
|
|
use Icinga\Module\Director\Web\Form\QuickForm;
|
|
|
|
|
|
|
|
class KickstartForm extends QuickForm
|
|
|
|
{
|
2016-03-21 19:23:17 +01:00
|
|
|
protected $config;
|
|
|
|
|
|
|
|
protected $storeConfigLabel;
|
2015-12-18 10:51:38 +01:00
|
|
|
|
2016-03-13 23:48:22 +01:00
|
|
|
protected $createDbLabel;
|
|
|
|
|
2016-03-21 19:23:17 +01:00
|
|
|
protected $migrateDbLabel;
|
|
|
|
|
2015-12-18 10:51:38 +01:00
|
|
|
public function setup()
|
|
|
|
{
|
2016-03-21 19:23:17 +01:00
|
|
|
$this->storeConfigLabel = $this->translate('Store configuration');
|
|
|
|
$this->createDbLabel = $this->translate('Create database schema');
|
|
|
|
$this->migrateDbLabel = $this->translate('Apply schema migrations');
|
|
|
|
|
|
|
|
$this->addResourceConfigElements();
|
|
|
|
if (!$this->config()->get('db', 'resource')
|
|
|
|
|| ($this->config()->get('db', 'resource') !== $this->getResourceName())) {
|
|
|
|
$this->addResourceDisplayGroup();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-03-13 23:48:22 +01:00
|
|
|
if (!$this->migrations()->hasSchema()) {
|
|
|
|
|
|
|
|
$this->addHtmlHint($this->translate(
|
|
|
|
'No database schema has been created yet'
|
2016-03-21 19:23:17 +01:00
|
|
|
), array('name' => 'HINT_schema'));
|
2016-03-13 23:48:22 +01:00
|
|
|
|
2016-03-21 19:23:17 +01:00
|
|
|
$this->addResourceDisplayGroup();
|
2016-03-13 23:48:22 +01:00
|
|
|
$this->setSubmitLabel($this->createDbLabel);
|
2016-03-21 19:23:17 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($this->migrations()->hasPendingMigrations()) {
|
|
|
|
|
|
|
|
$this->addHtmlHint($this->translate(
|
|
|
|
'There are pending database migrations'
|
|
|
|
), array('name' => 'HINT_schema'));
|
|
|
|
|
|
|
|
$this->addResourceDisplayGroup();
|
|
|
|
$this->setSubmitLabel($this->migrateDbLabel);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($this->getDb()->hasDeploymentEndpoint()) {
|
|
|
|
$hint = sprintf($this->translate(
|
|
|
|
'Your database looks good, you are ready to %s'
|
|
|
|
), $this->getView()->qlink(
|
|
|
|
'start working with the Icinga Director',
|
|
|
|
'director',
|
|
|
|
null,
|
|
|
|
array('data-base-target' => '_main')
|
|
|
|
));
|
|
|
|
|
|
|
|
$this->addHtmlHint($hint, array('name' => 'HINT_ready'));
|
|
|
|
|
|
|
|
return;
|
2016-03-13 23:48:22 +01:00
|
|
|
}
|
|
|
|
|
2016-03-21 19:23:17 +01:00
|
|
|
$this->addResourceDisplayGroup();
|
|
|
|
|
2015-12-18 10:51:38 +01:00
|
|
|
$this->addHtmlHint(
|
|
|
|
$this->translate(
|
2016-03-21 19:23:17 +01:00
|
|
|
'Your installation of Icinga Director has not yet been prepared for'
|
|
|
|
. ' deployments. This kickstart wizard will assist you with setting'
|
|
|
|
. ' up the connection to your Icinga 2 server.'
|
2016-03-22 02:27:17 +01:00
|
|
|
),
|
|
|
|
array('name' => 'HINT_kickstart')
|
|
|
|
// http://docs.icinga.org/icinga2/latest/doc/module/icinga2/chapter/object-types#objecttype-apilistener
|
2015-12-18 10:51:38 +01:00
|
|
|
);
|
2015-12-21 13:11:38 +01:00
|
|
|
|
|
|
|
$this->addElement('text', 'endpoint', array(
|
|
|
|
'label' => $this->translate('Endpoint Name'),
|
2016-03-07 01:10:56 +01:00
|
|
|
'description' => $this->translate(
|
|
|
|
'This is the name of the Endpoint object (and certificate name) you'
|
|
|
|
. ' created for your ApiListener object. In case you are unsure what'
|
|
|
|
. ' this means please make sure to read the documentation first'
|
|
|
|
),
|
2015-12-21 13:11:38 +01:00
|
|
|
'required' => true,
|
|
|
|
));
|
|
|
|
|
2015-12-18 10:51:38 +01:00
|
|
|
$this->addElement('text', 'host', array(
|
|
|
|
'label' => $this->translate('Icinga Host'),
|
2016-03-07 01:10:56 +01:00
|
|
|
'description' => $this->translate(
|
|
|
|
'IP address / hostname of your Icinga node. Please note that this'
|
|
|
|
. ' information will only be used for the very first connection to'
|
|
|
|
. ' your Icinga instance. The Director then relies on a correctly'
|
|
|
|
. ' configured Endpoint object. Correctly configures means that either'
|
|
|
|
. ' it\'s name is resolvable or that it\'s host property contains'
|
|
|
|
. ' either an IP address or a resolvable host name. Your Director must'
|
|
|
|
. ' be able to reach this endpoint'
|
|
|
|
),
|
|
|
|
'required' => false,
|
2015-12-18 10:51:38 +01:00
|
|
|
));
|
|
|
|
|
|
|
|
$this->addElement('text', 'port', array(
|
|
|
|
'label' => $this->translate('Port'),
|
|
|
|
'value' => '5665',
|
2016-03-07 01:10:56 +01:00
|
|
|
'description' => $this->translate(
|
|
|
|
'The port you are going to use. The default port 5665 will be used'
|
|
|
|
. ' if none is set'
|
|
|
|
),
|
|
|
|
'required' => false,
|
2015-12-18 10:51:38 +01:00
|
|
|
));
|
|
|
|
|
|
|
|
$this->addElement('text', 'username', array(
|
|
|
|
'label' => $this->translate('API user'),
|
2016-03-07 01:10:56 +01:00
|
|
|
'description' => $this->translate(
|
|
|
|
'Your Icinga 2 API username'
|
|
|
|
),
|
2015-12-18 10:51:38 +01:00
|
|
|
'required' => true,
|
|
|
|
));
|
|
|
|
|
|
|
|
$this->addElement('password', 'password', array(
|
2016-03-21 19:23:17 +01:00
|
|
|
'label' => $this->translate('Password'),
|
2016-03-07 01:10:56 +01:00
|
|
|
'description' => $this->translate(
|
|
|
|
'The corresponding password'
|
|
|
|
),
|
2016-03-21 19:23:17 +01:00
|
|
|
'required' => true,
|
|
|
|
));
|
|
|
|
|
|
|
|
$this->addKickstartDisplayGroup();
|
|
|
|
$this->setSubmitLabel($this->translate('Run import'));
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function onSetup()
|
|
|
|
{
|
|
|
|
if ($this->hasBeenSubmitted()) {
|
|
|
|
// Do not hinder the form from being stored
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ($resourceName = $this->getResourceName()) {
|
|
|
|
$resourceConfig = ResourceFactory::getResourceConfig($resourceName);
|
|
|
|
if (! isset($resourceConfig->charset)
|
|
|
|
|| $resourceConfig->charset !== 'utf8'
|
|
|
|
) {
|
|
|
|
$this->getElement('resource')
|
|
|
|
->addError('Please change the encoding for the director database to utf8');
|
|
|
|
}
|
|
|
|
|
|
|
|
$resource = $this->getResource();
|
|
|
|
$db = $resource->getDbAdapter();
|
|
|
|
|
|
|
|
try {
|
|
|
|
$query = $db->select()->from('dual', '(1)');
|
|
|
|
$db->fetchOne($query);
|
|
|
|
|
|
|
|
} catch (Exception $e) {
|
|
|
|
$this->getElement('resource')
|
|
|
|
->addError('Could not connect to database: ' . $e->getMessage());
|
|
|
|
|
|
|
|
$hint = $this->translate(
|
|
|
|
'Please make sure that your database grants enough permissions'
|
|
|
|
. ' and that you deployed the correct %s.'
|
|
|
|
);
|
|
|
|
|
|
|
|
$this->addHtmlHint($hint, array('name' => 'HINT_db_perms'));
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function addResourceConfigElements()
|
|
|
|
{
|
|
|
|
$config = $this->config();
|
|
|
|
$resources = $this->enumResources();
|
|
|
|
|
|
|
|
if (!$this->getResourceName()) {
|
|
|
|
$this->addHtmlHint($this->translate(
|
|
|
|
'No database resource has been configured yet. Please choose a'
|
|
|
|
. ' resource to complete your config'
|
|
|
|
), array('name' => 'HINT_no_resource'));
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->addElement('select', 'resource', array(
|
|
|
|
'required' => true,
|
|
|
|
'label' => $this->translate('DB Resource'),
|
|
|
|
'multiOptions' => $this->optionalEnum($resources),
|
|
|
|
'class' => 'autosubmit',
|
|
|
|
'value' => $config->get('db', 'resource')
|
2015-12-18 10:51:38 +01:00
|
|
|
));
|
2016-03-21 19:23:17 +01:00
|
|
|
|
|
|
|
if (empty($resources)) {
|
|
|
|
$this->getElement('resource')->addError(
|
|
|
|
$this->translate('This has to be a MySQL or PostgreSQL database')
|
|
|
|
);
|
|
|
|
|
|
|
|
$hint = $this->translate('Please click %s to create new DB resources');
|
|
|
|
$link = $this->getView()->qlink(
|
|
|
|
$this->translate('here'),
|
|
|
|
'config/resource',
|
|
|
|
null,
|
|
|
|
array('data-base-target' => '_main')
|
|
|
|
);
|
|
|
|
$this->addHtmlHint(sprintf($hint, $link));
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->setSubmitLabel($this->storeConfigLabel);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function addResourceDisplayGroup()
|
|
|
|
{
|
|
|
|
$elements = array(
|
|
|
|
'HINT_no_resource',
|
|
|
|
'HINT_ready',
|
|
|
|
'resource',
|
|
|
|
'HINT_schema',
|
|
|
|
'HINT_db_perms'
|
|
|
|
);
|
|
|
|
|
|
|
|
$this->addDisplayGroup($elements, 'config', array(
|
|
|
|
'decorators' => array(
|
|
|
|
'FormElements',
|
|
|
|
array('HtmlTag', array('tag' => 'dl')),
|
|
|
|
'Fieldset',
|
|
|
|
),
|
|
|
|
'order' => 40,
|
|
|
|
'legend' => $this->translate('Database backend')
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function addKickstartDisplayGroup()
|
|
|
|
{
|
|
|
|
$elements = array(
|
|
|
|
'HINT_kickstart', 'endpoint', 'host', 'port', 'username', 'password'
|
|
|
|
);
|
|
|
|
|
|
|
|
$this->addDisplayGroup($elements, 'wizard', array(
|
|
|
|
'decorators' => array(
|
|
|
|
'FormElements',
|
|
|
|
array('HtmlTag', array('tag' => 'dl')),
|
|
|
|
'Fieldset',
|
|
|
|
),
|
|
|
|
'order' => 60,
|
|
|
|
'legend' => $this->translate('Kickstart wizard')
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function storeResourceConfig()
|
|
|
|
{
|
|
|
|
$config = $this->config();
|
|
|
|
$value = $this->getValue('resource');
|
|
|
|
|
|
|
|
$config->setSection('db', array('resource' => $value));
|
|
|
|
|
|
|
|
try {
|
|
|
|
$config->saveIni();
|
|
|
|
$this->setSuccessMessage($this->translate('Configuration has been stored'));
|
|
|
|
} catch (Exception $e) {
|
|
|
|
$this->getElement('resource')->addError(
|
|
|
|
sprintf(
|
|
|
|
$this->translate('Unable to store the configuration to "%s"'),
|
|
|
|
$config->getConfigFile()
|
|
|
|
)
|
|
|
|
)->removeDecorator('description');
|
|
|
|
$this->addHtmlHint(
|
|
|
|
'<pre>' . $config . '</pre>'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2015-12-18 10:51:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function onSuccess()
|
|
|
|
{
|
2016-03-07 01:10:56 +01:00
|
|
|
try {
|
2016-03-21 19:23:17 +01:00
|
|
|
if ($this->getSubmitLabel() === $this->storeConfigLabel) {
|
|
|
|
$this->storeResourceConfig();
|
|
|
|
return parent::onSuccess();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($this->getSubmitLabel() === $this->createDbLabel
|
|
|
|
|| $this->getSubmitLabel() === $this->migrateDbLabel) {
|
2016-03-13 23:48:22 +01:00
|
|
|
$this->migrations()->applyPendingMigrations();
|
|
|
|
return parent::onSuccess();
|
|
|
|
}
|
2016-03-21 19:23:17 +01:00
|
|
|
|
|
|
|
$values = $this->getValues();
|
|
|
|
$kickstart = new KickstartHelper($this->getDb());
|
|
|
|
unset($values['resource']);
|
|
|
|
$kickstart->setConfig($values)->run();
|
2016-03-07 01:10:56 +01:00
|
|
|
parent::onSuccess();
|
|
|
|
} catch (Exception $e) {
|
2016-03-13 23:48:22 +01:00
|
|
|
$this->addError($e->getMessage());
|
2016-03-07 01:10:56 +01:00
|
|
|
}
|
2015-12-18 10:51:38 +01:00
|
|
|
}
|
|
|
|
|
2016-03-21 19:23:17 +01:00
|
|
|
protected function getResourceName()
|
2015-12-18 10:51:38 +01:00
|
|
|
{
|
2016-03-21 19:23:17 +01:00
|
|
|
if ($this->hasBeenSent()) {
|
|
|
|
$resource = $this->getSentValue('resource');
|
|
|
|
$resources = $this->enumResources();
|
|
|
|
if (in_array($resource, $resources)) {
|
|
|
|
return $resource;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return $this->config()->get('db', 'resource');
|
2015-12-18 10:51:38 +01:00
|
|
|
}
|
2016-03-21 19:23:17 +01:00
|
|
|
}
|
2015-12-18 10:51:38 +01:00
|
|
|
|
2016-03-21 19:23:17 +01:00
|
|
|
protected function getDb()
|
|
|
|
{
|
|
|
|
return Db::fromResourceName($this->getResourceName());
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getResource()
|
|
|
|
{
|
|
|
|
return ResourceFactory::create($this->getResourceName());
|
2015-12-18 10:51:38 +01:00
|
|
|
}
|
2016-03-13 23:48:22 +01:00
|
|
|
|
|
|
|
protected function migrations()
|
|
|
|
{
|
2016-03-21 19:23:17 +01:00
|
|
|
return new Migrations($this->getDb());
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setModuleConfig(Config $config)
|
|
|
|
{
|
|
|
|
$this->config = $config;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function config()
|
|
|
|
{
|
|
|
|
if ($this->config === null) {
|
|
|
|
$this->config = Config::module('director');
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->config;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function enumResources()
|
|
|
|
{
|
|
|
|
$resources = array();
|
|
|
|
$allowed = array('mysql', 'pgsql');
|
|
|
|
|
|
|
|
foreach (ResourceFactory::getResourceConfigs() as $name => $resource) {
|
|
|
|
if ($resource->type === 'db' && in_array($resource->db, $allowed)) {
|
|
|
|
$resources[$name] = $name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $resources;
|
2016-03-13 23:48:22 +01:00
|
|
|
}
|
2015-12-18 10:51:38 +01:00
|
|
|
}
|