SettingsController   C
last analyzed

Complexity

Total Complexity 54

Size/Duplication

Total Lines 477
Duplicated Lines 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
eloc 222
c 5
b 0
f 0
dl 0
loc 477
rs 6.4799
wmc 54

12 Methods

Rating   Name   Duplication   Size   Complexity  
A check_empty_config() 0 15 3
A get_param() 0 11 3
A check_icingaweb_path() 0 15 5
A check_api() 0 18 3
A get_db_list() 0 11 4
B check_db() 0 52 9
A get_php_binary() 0 19 5
A indexAction() 0 61 2
A satelliteAction() 0 12 1
A createschemaAction() 0 55 4
B checkSnmpTrapd() 0 46 10
B updateschemaAction() 0 64 5

How to fix   Complexity   

Complex Class

Complex classes like SettingsController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SettingsController, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Icinga\Module\Trapdirector\Controllers;
4
5
use Icinga\Data\ResourceFactory;
6
use Icinga\Web\Url;
7
use Icinga\Application\Icinga;
8
use Icinga\Exception\ProgrammingError;
9
use RunTimeException;
10
use Exception;
11
12
use Icinga\Module\Trapdirector\TrapsController;
13
use Icinga\Module\Trapdirector\Forms\TrapsConfigForm;
14
use Icinga\Module\Trapdirector\Icinga2API;
15
use Icinga\Module\Trapdirector\TrapsActions\DBException;
16
17
use Trapdirector\Trap;
18
19
class SettingsController extends TrapsController
20
{
21
  
22
  /**
23
   * get param dberror or idoerror
24
   * set errorDetected
25
   */
26
  private function get_param()
27
  {
28
      $dberrorMsg=$this->params->get('dberror');
29
      if ($dberrorMsg != '')
30
      {
31
          $this->view->errorDetected=$dberrorMsg;
32
      }
33
      $dberrorMsg=$this->params->get('idodberror');
34
      if ($dberrorMsg != '')
35
      {
36
          $this->view->errorDetected=$dberrorMsg;
37
      }
38
  }
39
  
40
  /**
41
   * Check empty configuration (and create one if needed)
42
   * Setup : configErrorDetected
43
   */
44
  private function check_empty_config()
45
  {
46
      $this->view->configErrorDetected == NULL; // Displayed error on various conifugration errors.
47
      if ($this->Config()->isEmpty() == true)
48
      {
49
          $this->Config()->setSection('config'); // Set base config section.
50
          try
51
          {
52
              $this->Config()->saveIni();
53
              $this->view->configErrorDetected='Configuration is empty : you can run install script with parameters (see Automatic installation below)';
54
              //$emptyConfig=1;
55
          }
56
          catch (Exception $e)
57
          {
58
              $this->view->configErrorDetected=$e->getMessage();
59
          }
60
          
61
      }
62
  }
63
  
64
  /**
65
   * Check database and IDO database
66
   * Setup : 
67
   * db_error : numerical error (trap db) 0=OK
68
   * message : message (trap db)
69
   * ido_db_error : numerical error 0=OK
70
   * ido_message : message
71
   */
72
  private function check_db()
73
  {
74
      $db_message=array( // index => ( message OK, message NOK, optional link if NOK )
75
          0	=>	array('Database configuration OK','',''),
76
          1	=>	array('Database set in config.ini','No database in config.ini',''),
77
          2	=>	array('Database exists in Icingaweb2 config','Database does not exist in Icingaweb2 : ',
78
              Url::fromPath('config/resource')),
79
          3	=>	array('Database credentials OK','Database does not exist/invalid credentials/no schema : ',
80
              Url::fromPath('trapdirector/settings/createschema')),
81
          4	=>	array('Schema is set','Schema is not set for ',
82
              Url::fromPath('trapdirector/settings/createschema')),
83
          5	=>	array('Schema is up to date','Schema is outdated :',
84
              Url::fromPath('trapdirector/settings/updateschema')),
85
      );
86
      
87
      try {
88
          $this->getUIDatabase()->testGetDb(); // Get DB in test mode
89
          $dberror=array(0,'');
90
      } catch (DBException $e) {
91
          $dberror = $e->getArray();
92
      }
93
      
94
      $this->view->db_error=$dberror[0];
95
      switch ($dberror[0])
96
      {
97
          case 2:
98
          case 4:
99
              $db_message[$dberror[0]][1] .= $dberror[1];
100
              break;
101
          case 3:
102
              $db_message[$dberror[0]][1] .= $dberror[1] . ', Message : ' . $dberror[2];
103
              break;
104
          case 5:
105
              $db_message[$dberror[0]][1] .= ' version '. $dberror[1] . ', version needed : ' .$dberror[2];
106
              break;
107
          case 0:
108
          case 1:
109
              break;
110
          default:
111
              new ProgrammingError('Out of bond result from database test');
112
      }
113
      $this->view->message=$db_message;
114
      
115
      try {
116
          $this->getUIDatabase()->testGetIdoDb(); // Get DB in test mode
117
          $dberror=array(0,'');
118
      } catch (DBException $e) {
119
          $dberror = $e->getArray();
120
      }
121
      
122
      $this->view->ido_db_error=$dberror[0];
123
      $this->view->ido_message='IDO Database : ' . $dberror[1];
124
  }
125
  
126
  /**
127
   * Check API parameters
128
   * Setup : 
129
   * apimessage
130
   */
131
  private function check_api()
132
  {
133
      if ($this->Config()->get('config', 'icingaAPI_host') != '')
134
      {
135
          $apitest=new Icinga2API($this->Config()->get('config', 'icingaAPI_host'),$this->Config()->get('config', 'icingaAPI_port'));
136
          $apitest->setCredentials($this->Config()->get('config', 'icingaAPI_user'), $this->Config()->get('config', 'icingaAPI_password'));
137
          try {
138
              list($this->view->apimessageError,$this->view->apimessage)=$apitest->test($this->getModuleConfig()::getapiUserPermissions());
139
              //$this->view->apimessageError=false;
140
          } catch (RuntimeException $e) {
141
              $this->view->apimessage='API config : ' . $e->getMessage();
142
              $this->view->apimessageError=true;
143
          }
144
      }
145
      else
146
      {
147
          $this->view->apimessage='API parameters not configured';
148
          $this->view->apimessageError=true;
149
      }
150
  }
151
152
  /**
153
   * Check icingaweb2 etc path
154
   * Setup : 
155
   * icingaEtcWarn : 0 if same than in trap_in.php, 1 if not
156
   * icingaweb2_etc : path 
157
   */
158
  private function check_icingaweb_path()
159
  {
160
      $this->view->icingaEtcWarn=0;
161
      $icingaweb2_etc=$this->Config()->get('config', 'icingaweb2_etc');
162
      if ($icingaweb2_etc != "/etc/icingaweb2/" && $icingaweb2_etc != '')
163
      {
164
          $output=array();
165
          
166
          exec('cat ' . $this->module->getBaseDir() .'/bin/trap_in.php | grep "\$icingaweb2Etc=" ',$output);
167
          
168
          
169
          if (! isset($output[0]) || ! preg_match('#"'. $icingaweb2_etc .'"#',$output[0]))
170
          {
171
              $this->view->icingaEtcWarn=1;
172
              $this->view->icingaweb2_etc=$icingaweb2_etc;
173
          }
174
      }
175
      
176
  }
177
  
178
  /**
179
   * Get db list filtered by $allowed
180
   * @param array $allowed : array of allowed database
181
   * @return array : resource list
182
   */
183
  private function get_db_list($allowed)
184
  {
185
      $resources = array();
186
      foreach (ResourceFactory::getResourceConfigs() as $name => $resource) 
187
      {
188
          if ($resource->get('type') === 'db' && in_array($resource->get('db'), $allowed)) 
189
          {
190
              $resources[$name] = $name;
191
          }
192
      }
193
      return $resources;
194
  }
195
  
196
  /**
197
   * Get php binary with path or NULL if not found.
198
   * @return string|NULL
199
   */
200
  private function get_php_binary()
201
  {
202
      $phpBinary= array( PHP_BINARY, PHP_BINDIR . "/php", '/usr/bin/php');
203
204
      foreach ($phpBinary as $phpBin )
205
      {
206
          $output=array();
207
          $retCode=255;
208
          $input="154865134987aaaa";
209
          exec("$phpBin -r \"echo '$input';\"",$output,$retCode);
210
          
211
          if (! isset($output[0])) $output[0]="NO OUT";
212
          
213
          if ($retCode == 0 && preg_match("/$input/",$output[0]) == 1)
214
          {
215
              return $phpBin;
216
          }          
217
      }
218
      return NULL;
219
  }
220
  
221
  /**
222
   * Index of configuration
223
   * Params setup in $this->view :
224
   * errorDetected : if db or ido was detected by another page
225
   * configErrorDetected : error if empty configuration (or error wrting a new one).
226
   * db_error : numerical error (trap db) 0=OK
227
   * message : message (trap db)
228
   * ido_db_error : numerical error 0=OK
229
   * ido_message : message
230
   * apimessage
231
   * icingaEtcWarn : 0 if same than in trap_in.php, 1 if not
232
   * icingaweb2_etc : path 
233
   **/
234
  public function indexAction()
235
  {
236
      
237
    // CHeck permissions : display tests in any case, but no configuration.
238
	$this->view->configPermission=$this->checkModuleConfigPermission(1);
239
	// But check read permission
240
	$this->checkReadPermission();
241
	
242
	$this->view->tabs = $this->Module()->getConfigTabs()->activate('config');	
243
	
244
	// Get message : sent on configuration problems detected by controllers
245
    $this->get_param();
246
    
247
    // Test if configuration exists, if not create for installer script
248
	$this->check_empty_config();
249
250
	// Test Database
251
    $this->check_db();
252
	
253
	//********* Test API
254
    $this->check_api();
255
	
256
	//*********** Test snmptrapd alive and options
257
	list ($this->view->snmptrapdError, $this->view->snmptrapdMessage) = $this->checkSnmpTrapd();
258
259
	// List DB in $ressources
260
	$resources = $this->get_db_list(array('mysql', 'pgsql')); 
261
262
	// Check standard Icingaweb2 path
263
	$this->check_icingaweb_path();
264
265
	$phpBinary = $this->get_php_binary();
266
	if ($phpBinary === null)
267
	{
268
	    $phpBinary = ' PHP BINARY NOT FOUND ';
269
	    
270
	}
271
	
272
	// Setup path for mini documentation
273
	$this->view->traps_in_config= $phpBinary . ' ' . $this->Module()->getBaseDir() . '/bin/trap_in.php';
274
	
275
	$this->view->installer= $this->Module()->getBaseDir() . '/bin/installer.sh '
276
	    . ' -c all ' 
277
	    . ' -d ' . $this->Module()->getBaseDir()
278
	    . ' -p ' . $phpBinary
279
	    . ' -a ' . exec('whoami')
280
	    . ' -w ' . Icinga::app()->getConfigDir();
281
	        
282
	// ******************* configuration form setup*******************
283
	$this->view->form = $form = new TrapsConfigForm();
284
	
285
	// set default paths;
286
	$this->view->form->setPaths($this->Module()->getBaseDir(),Icinga::app()->getConfigDir());
287
	
288
	// set default ido database
289
	$this->view->form->setDefaultIDODB($this->Config()->module('monitoring','backends')->get('icinga','resource'));
290
	
291
	// Make form handle request.
292
	$form->setIniConfig($this->Config())
293
		->setDBList($resources)
294
		->handleRequest();
295
        
296
  }
297
298
  /**
299
   * Satellite configuration
300
   * Params setup in $this->view :
301
   * errorDetected : if db or ido was detected by another page
302
   * configErrorDetected : error if empty configuration (or error wrting a new one).
303
   * db_error : numerical error (trap db) 0=OK
304
   * message : message (trap db)
305
   * ido_db_error : numerical error 0=OK
306
   * ido_message : message
307
   * apimessage
308
   * icingaEtcWarn : 0 if same than in trap_in.php, 1 if not
309
   * icingaweb2_etc : path
310
   **/
311
  public function satelliteAction()
312
  {
313
      
314
      // CHeck permissions
315
      $this->view->configPermission=$this->checkModuleConfigPermission();
316
      
317
      // Setup tabs
318
      $this->view->tabs = $this->Module()->getConfigTabs()->activate('satellite');	
319
      
320
      $this->view->masterHASet = FALSE;
321
      
322
      $this->view->masterHAConf = array ('name' => 'masterHA1', 'icingaweb2 user'=>'User1');
323
  }
324
  
325
  
326
  public function createschemaAction()
327
  {
328
	$this->checkModuleConfigPermission();
329
	$this->getTabs()->add('create_schema',array(
330
		'active'	=> true,
331
		'label'		=> $this->translate('Create Schema'),
332
		'url'		=> Url::fromRequest()
333
	));
334
	// check if needed
335
	
336
	try 
337
	{
338
	    $this->getUIDatabase()->testGetDb(); // Get DB in test mode
339
	    printf('Schema already exists');
340
	    
341
	} 
342
	catch (DBException $e) 
343
	{
344
345
		printf('Creating schema : <br>');
346
347
		// Get module database name
348
		$dbName=$this->Config()->get('config', 'database');
349
350
        $dbResource = ResourceFactory::getResourceConfig($dbName);
351
        $dbType=$dbResource->get('db');
352
        switch ($dbType) {
353
          case 'mysql':
354
              $dbFileExt='sql';
355
              break;
356
          case 'pgsql':
357
              $dbFileExt='pgsql';
358
              break;
359
          default:
360
              printf("Database configuration error : Unsuported DB");
361
              return;
362
        } 
363
364
		printf('<pre>');
365
		require_once $this->Module()->getBaseDir() .'/bin/trap_class.php';
366
		
367
		$icingaweb2_etc=$this->Config()->get('config', 'icingaweb2_etc');
368
		$debug_level=4;
369
		$Trap = new Trap($icingaweb2_etc);
370
		$Trap->setLogging($debug_level,'display');
371
		
372
		$prefix=$this->Config()->get('config', 'database_prefix');
373
		// schema file : <path>/SQL/schema_v<verion>.<dbtype>
374
		$schema=$this->Module()->getBaseDir() . 
375
		'/SQL/schema_v'. $this->getModuleConfig()->getDbCurVersion() . '.' . $dbFileExt;
376
		
377
		$Trap->trapsDB->create_schema($schema,$prefix);
378
		echo '</pre>';
379
	}
380
	echo '<br><br>Return to <a href="' . Url::fromPath('trapdirector/settings') .'" class="link-button icon-wrench"> settings page </a>';
381
  }
382
383
  public function updateschemaAction()
384
  {
385
	  $this->checkModuleConfigPermission();
386
      $this->getTabs()->add('get',array(
387
    		'active'	=> true,
388
    		'label'		=> $this->translate('Update Schema'),
389
    		'url'		=> Url::fromRequest()
390
    	));
391
	  // check if needed
392
	  $dberror=array();
0 ignored issues
show
Unused Code introduced by
The assignment to $dberror is dead and can be removed.
Loading history...
393
      try
394
      {
395
          $this->getUIDatabase()->testGetDb(); // Get DB in test mode
396
          echo 'Schema already exists and is up to date<br>';
397
          return;
398
      }
399
      catch (DBException $e)
400
      {
401
          $dberror=$e->getArray(); 
402
      }
403
	  
404
	  echo 'Return to <a href="' . Url::fromPath('trapdirector/settings') .'" class="link-button icon-wrench"> settings page </a><br><br>';
405
	  
406
	  if ($dberror[0] != 5)
407
	  {
408
	      echo 'Database does not exists or is not setup correctly<br>';
409
	      return;
410
	  }
411
      // setup
412
	  require_once($this->Module()->getBaseDir() .'/bin/trap_class.php');
413
	  $icingaweb2_etc=$this->Config()->get('config', 'icingaweb2_etc');
414
	  $debug_level=4;
415
	  $Trap = new Trap($icingaweb2_etc);
416
	  
417
	  
418
	  $prefix=$this->Config()->get('config', 'database_prefix');
419
	  $updateSchema=$this->Module()->getBaseDir() . '/SQL/';
420
	  
421
	  $target_version=$dberror[2];
422
	  
423
	  if ($this->params->get('msgok') == null) {
424
	      // Check for messages and display if any
425
              echo "Upgrade databse is going to start.<br>Don't forget to backup your database before update<br>";
426
	      $Trap->setLogging(2,'syslog');
427
	      $message = $Trap->trapsDB->update_schema($updateSchema,$target_version,$prefix,true);
428
	      if ($message != '')
429
	      {
430
	          echo 'Note :<br><pre>';
431
	          echo $message;
432
	          echo '</pre>';
433
	          echo '<br>';
434
	          echo '<a  class="link-button" style="font-size:large;font-weight:bold" href="' . Url::fromPath('trapdirector/settings/updateschema') .'?msgok=1">Click here to update</a>';
435
	          echo '<br>';
436
	          return;
437
	      }
438
	  }
439
	  
440
	  $Trap->setLogging($debug_level,'display');
441
	  
442
	  echo 'Updating schema to '. $target_version . ': <br>';
443
	  echo '<pre>';
444
	  	  
445
	  $Trap->trapsDB->update_schema($updateSchema,$target_version,$prefix);
446
	  echo '</pre>';
447
  }  
448
449
  
450
  private function checkSnmpTrapd()
451
  {
452
      $psOutput=array();
453
      // First check is someone is listening to port 162. As not root, we can't have pid... 
454
      $sspath = exec('which ss 2>/dev/null');
455
      if(empty($sspath))
456
      {
457
          // RHEL based systems
458
          $sspath = '/usr/sbin/ss';
459
      }
460
      if(!is_executable("$sspath"))
461
      {
462
          return array(1,"Can not execute $sspath");
463
      }
464
      exec("$sspath -lun | grep ':162 '",$psOutput);
465
      if (count($psOutput) == 0)
466
      {
467
          return array(1,'Port UDP/162 is not open : is snmptrapd running?');
468
      }
469
      $psOutput=array();
470
      $selinux_state = '';
471
      if(is_executable('/usr/sbin/getenforce'))
472
      {
473
          $selinux_state = exec('/usr/sbin/getenforce 2>/dev/null');
474
      }
475
      if($selinux_state !== 'Enforcing')
476
      {
477
          exec('ps --no-headers -o command -C snmptrapd',$psOutput);
478
          if (count($psOutput) == 0)
479
          {
480
              return array(1,"UDP/162 : OK, but no snmptrapd process (?)");
481
          }
482
          // Assume there is only one line... TODO : see if there is a better way to do this
483
          $line = preg_replace('/^.*snmptrapd /','',$psOutput[0]);
484
          if (!preg_match('/-n/',$line))
485
              return array(1,'snmptrapd has no -n option : '.$line);
486
          if (!preg_match('/-O[^ ]*n/',$line))
487
              return array(1,'snmptrapd has no -On option : '.$line);
488
          if (!preg_match('/-O[^ ]*e/',$line))
489
              return array(1,'snmptrapd has no -Oe option : '.$line);
490
491
          return array(0,'snmptrapd listening to UDP/162, options : '.$line);
492
      }
493
      else
494
      {
495
          return array(0,'A daemon (hidden by SELinux) is listening on UDP/162');
496
      }
497
  }
498
}
499