diff --git a/application/classes/database.php b/application/classes/database.php
index b4bda30..75a78f4 100644
--- a/application/classes/database.php
+++ b/application/classes/database.php
@@ -13,5 +13,6 @@
abstract class Database extends Kohana_Database {
// Enable TSM SHOW commands
const SHOW = 5;
+ const SET = 6;
}
?>
diff --git a/application/classes/database/tsm.php b/application/classes/database/tsm.php
index 83136a5..2292121 100644
--- a/application/classes/database/tsm.php
+++ b/application/classes/database/tsm.php
@@ -10,7 +10,7 @@
* @copyright (c) 2010 phpTSMadmin Development Team
* @license http://phptsmadmin.sf.net/license.html
*/
-class Database_TSM extends Database {
+abstract class Database_TSM extends Database {
// Database in use by each connection
protected static $_current_databases = array();
@@ -24,25 +24,33 @@ class Database_TSM extends Database {
protected $_identifier = '';
// Our TSM Message Format
- private $msg_format = '[A-Z]{3}[0-9]{4}[I|E|W|S]';
+ protected $msg_format = '[A-Z]{3}[0-9]{4}[I|E|W|S]';
// Our Message Codes stored in the last query
- private $_query_msg_codes = array();
+ protected $_query_msg_codes = array();
// Our return code error messages we can ignore
- private $ignore_codes = array(
+ protected $ignore_codes = array(
'ANS8001I', // Return code %s.
);
// Our return code error messages we can ignore
- private $nodata_codes = array(
+ protected $nodata_codes = array(
'ANR2034E', // SELECT: No match found using this criteria.
);
+ protected $execute_stdout = '';
+ protected $execute_stderr = '';
+ protected $execute_rc = NULL;
+
// Our required abstract methods
public function begin($mode = NULL) {}
public function commit() {}
public function rollback() {}
public function set_charset($charset) {}
+ public function list_tables($like = NULL) {}
+
+ // Required methods
+ abstract protected function execute($sql);
/**
* Return the caching defined in the current configuration.
@@ -55,82 +63,6 @@ class Database_TSM extends Database {
return ($this->_config['caching'] AND isset($this->_config['cache'][$table])) ? $this->_config['cache'][$table] : FALSE;
}
- public function connect() {
- if ($this->_connection)
- return;
-
- // Extract the connection parameters, adding required variabels
- extract($this->_config['connection'] + array(
- 'database' => '',
- 'hostname' => '',
- 'username' => '',
- 'password' => '',
- 'persistent' => FALSE,
- ));
-
- // Get user login details from user session - these are set by login
- if (! $username)
- $username = Session::instance()->get_once(Kohana::config('auth.session_key'));
- if (! $password)
- $password = Session::instance()->get_once('password');
-
- // Prevent this information from showing up in traces
- unset($this->_config['connection']['username'], $this->_config['connection']['password']);
-
- if (! file_exists(Kohana::config('config.client'))) {
- system_message(array('title'=>'Cant find DSMADMC',
- 'body'=>sprintf('Unable to find the dsmadmc at %s',Kohana::config('client.config')),
- 'type'=>'error'));
-
- return FALSE;
- }
-
- if (! $username OR ! $password)
- Request::current()->redirect('/login?need_login=1');
-
- try {
- if ($persistent) {
- // Create a persistent connection
- throw new Kohana_Exception('Cant do persistant connections');
-
- } else {
- // Create a connection and force it to be a new link
- $this->_connection = sprintf('%s %s -id=%s -password=%s -displ=list -editor=no -dataonly=YES %s %s ',
- Kohana::config('config.client'),
- $database ? '-server='.$database : '',
- $username,
- $password,
- Kohana::config('config.client_errorlogname') ? sprintf('-errorlogname=%s',Kohana::config('config.client_errorlogname')) : '',
- $database ? sprintf('-se=%s',$database) : ''
- );
-
- $result = $this->query(Database::SELECT,'SELECT server_name,platform,version,release,level,sublevel FROM status');
-
- if ($result)
- return TSM::instance()->set($username,$password,$result);
- else
- Request::current()->redirect(Request::detect_uri());
- }
-
- } catch (ErrorException $e) {
- // No connection exists
- $this->_connection = NULL;
-
- throw new Database_Exception(':error', array(
- ':error' => sprintf('%s error in %s (%s)',$e->getMessage(),$e->getFile(),$e->getLine()),
- ),
- $e->getCode());
- }
-
- // \xFF is a better delimiter, but the PHP driver uses underscore
- $this->_connection_id = sha1($hostname.'_'.$username.'_'.$password);
-
- if ( ! empty($this->_config['charset'])) {
- // Set the character set
- $this->set_charset($this->_config['charset']);
- }
- }
-
private function clear() {
$this->_query_msg_codes = array();
}
@@ -144,35 +76,15 @@ class Database_TSM extends Database {
// Benchmark this query for the current instance
$benchmark = Profiler::start("Database ({$this->_instance})", $sql);
- // We need to escape any back slashes, since the exec will transpose them
- // @todo Is there a better way of doing this?
- $sql = str_replace('\\','\\\\',$sql);
-
// Execute the query
- $stderr = exec($this->_connection.'"'.$sql.'"',$stdout,$rc);
+ $result = $this->execute($sql);
- // Work out our message codes
- $result = array();
- foreach ($stdout as $line)
- if (! preg_match('/^('.$this->msg_format.')\s+/',$line,$matches))
- array_push($result,$line);
- elseif (! in_array($matches[1],$this->ignore_codes))
- array_push($this->_query_msg_codes,$matches[1]);
-
- // If we got a no data code
- if (array_intersect($this->_query_msg_codes,$this->nodata_codes)) {
- $result = array();
- $rc = 0;
- }
-
- if ($stderr AND $rc) {
+ if ($this->execute_stderr AND $this->execute_rc) {
+ // This benchmark is worthless
if (isset($benchmark))
- {
- // This benchmark is worthless
Profiler::delete($benchmark);
- }
- SystemMessage::TSM_Error($stdout,$sql);
+ SystemMessage::TSM_Error(sprintf('%s (%s)',$this->execute_stdout,$this->execute_stderr),$sql);
Request::current()->redirect('welcome');
}
@@ -189,91 +101,8 @@ class Database_TSM extends Database {
throw new Kohana_Exception('Database INSERTS are not supported');
elseif ($type === Database::SHOW)
return new Database_TSM_Show($result, $sql, $as_object, $params);
- }
-
- public function list_tables($like = NULL) {
- if (is_string($like))
- // Search for table names
- $result = $this->query(Database::SELECT, 'SHOW TABLES LIKE '.$this->quote($like), FALSE);
- else
- // Find all table names
- $result = $this->query(Database::SELECT, 'SHOW TABLES', FALSE);
-
- $tables = array();
- foreach ($result as $row)
- $tables[] = reset($row);
-
- return $tables;
- }
-
- public function list_columns($table, $like = NULL, $add_prefix = TRUE) {
- // Quote the table name
- $table = ($add_prefix === TRUE) ? $this->quote_table($table) : $table;
-
- if (is_string($like))
- // Search for column names
- $result = $this->query(Database::SELECT, 'SHOW FULL COLUMNS FROM '.$table.' LIKE '.$this->quote($like), FALSE);
- else
- // Find all column names
- $result = $this->query(Database::SELECT, sprintf('SELECT * FROM SYSCAT.COLUMNS WHERE TABNAME=\'%s\'',$table), FALSE);
-
- $count = 0;
- $columns = array();
- foreach ($result as $row) {
- list($type, $length) = $this->_parse_type($row['TYPENAME']);
-
- $column = $this->datatype($type);
-
- $column['column_name'] = $row['COLNAME'];
- $column['data_type'] = $type;
- $column['is_nullable'] = ($row['NULLS'] == 'TRUE');
- $column['ordinal_position'] = ++$count;
-
- switch (strtolower($column['data_type'])) {
- case 'float':
- if (isset($length))
- list($column['numeric_precision'], $column['numeric_scale']) = explode(',', $length);
- break;
-
- case 'int':
- if (isset($length))
- // MySQL attribute
- $column['display'] = $length;
- break;
-
- case 'string':
- switch ($column['data_type']) {
- case 'binary':
- case 'varbinary':
- $column['character_maximum_length'] = $length;
- break;
-
- case 'char':
- case 'varchar':
- $column['character_maximum_length'] = $length;
- case 'text':
- case 'tinytext':
- case 'mediumtext':
- case 'longtext':
- $column['collation_name'] = $row['Collation'];
- break;
-
- case 'enum':
- case 'set':
- $column['collation_name'] = $row['Collation'];
- $column['options'] = explode('\',\'', substr($length, 1, -1));
- break;
- }
-
- break;
- }
-
- // TSM attributes
- $column['comment'] = $row['REMARKS'];
- $columns[$row['COLNAME']] = $column;
- }
-
- return $columns;
+ elseif ($type === Database::SET)
+ return new Database_TSM_Set($result, $sql, $as_object, $params);
}
public function escape($value) {
@@ -283,5 +112,5 @@ class Database_TSM extends Database {
// SQL standard is to use single-quotes for all values
return "'$value'";
}
-
-} // End Database_TSM
+}
+?>
diff --git a/application/classes/database/tsm/db2.php b/application/classes/database/tsm/db2.php
new file mode 100644
index 0000000..dbc0439
--- /dev/null
+++ b/application/classes/database/tsm/db2.php
@@ -0,0 +1,162 @@
+_connection)
+ return;
+
+ // Extract the connection parameters, adding required variabels
+ extract($this->_config['connection'] + array(
+ 'database' => '',
+ 'hostname' => '',
+ 'username' => '',
+ 'port' => '',
+ 'password' => '',
+ 'persistent' => FALSE,
+ ));
+
+ // Get user login details from user session - these are set by login
+ if (! $username)
+ $username = Session::instance()->get_once(Kohana::config('auth.session_key'));
+ if (! $password)
+ $password = Session::instance()->get_once('password');
+
+ // Prevent this information from showing up in traces
+ unset($this->_config['connection']['username'], $this->_config['connection']['password']);
+
+ if (! $username OR ! $password)
+ Request::current()->redirect('/login?need_login=1');
+
+ try {
+ if ($persistent) {
+ // Create a persistent connection
+ throw new Kohana_Exception('Cant do persistant connections');
+
+ } else {
+ // Create a connection and force it to be a new link
+ $constring = sprintf('DATABASE=%s;HOSTNAME=%s;PORT=%s;PROTOCOL=%s;UID=%s;PWD=%s',
+ $database,$hostname,$port,'TCPIP',$username,$password);
+
+ $this->_connection = db2_connect($constring,NULL,NULL);
+
+ if ($this->_connection) {
+ $result = DB::query(Database::SET,'SET SCHEMA='.$database)->execute(Kohana::config('config.client_type'));
+ $result = $this->query(Database::SELECT,'SELECT server_name,platform,version,release,level,sublevel FROM status');
+
+ return TSM::instance()->set($username,$password,$result);
+
+ } else
+ Request::current()->redirect(Request::detect_uri());
+ }
+
+ } catch (ErrorException $e) {
+ // No connection exists
+ $this->_connection = NULL;
+
+ throw new Database_Exception(':error', array(
+ ':error' => sprintf('%s error in %s (%s)',$e->getMessage(),$e->getFile(),$e->getLine()),
+ ),
+ $e->getCode());
+ }
+
+ // \xFF is a better delimiter, but the PHP driver uses underscore
+ $this->_connection_id = sha1($hostname.'_'.$username.'_'.$password);
+
+ if ( ! empty($this->_config['charset'])) {
+ // Set the character set
+ $this->set_charset($this->_config['charset']);
+ }
+ }
+
+ protected function execute($sql) {
+ $result = @db2_exec($this->_connection,$sql);
+ $this->execute_stderr = db2_stmt_errormsg();
+ $this->execute_rc = db2_stmt_error();
+
+ return $result;
+ }
+
+ public function list_columns($table, $like = NULL, $add_prefix = TRUE) {
+ // Make sure the database is connected
+ $this->_connection or $this->connect();
+
+ // Quote the table name
+ $table = ($add_prefix === TRUE) ? $this->quote_table($table) : $table;
+
+ if (is_string($like))
+ // Search for column names
+ throw new Kohana_Exception('Like queries not implemented');
+ else
+ // Find all column names
+ $result = db2_columns($this->_connection,NULL,NULL,$table);
+
+ $count = 0;
+ $columns = array();
+ while ($row = db2_fetch_assoc($result)) {
+ list($type, $length) = $this->_parse_type($row['TYPE_NAME']);
+
+ $column = $this->datatype($type);
+
+ $column['column_name'] = $row['COLUMN_NAME'];
+ $column['data_type'] = $type;
+ $column['is_nullable'] = ($row['IS_NULLABLE'] == 'YES');
+ $column['ordinal_position'] = ++$count;
+
+ switch (strtolower($column['data_type'])) {
+ case 'float':
+ if (isset($length))
+ list($column['numeric_precision'], $column['numeric_scale']) = explode(',', $length);
+ break;
+
+ case 'int':
+ if (isset($length))
+ // MySQL attribute
+ $column['display'] = $length;
+ break;
+
+ case 'string':
+ switch ($column['data_type']) {
+ case 'binary':
+ case 'varbinary':
+ $column['character_maximum_length'] = $length;
+ break;
+
+ case 'char':
+ case 'varchar':
+ $column['character_maximum_length'] = $length;
+ case 'text':
+ case 'tinytext':
+ case 'mediumtext':
+ case 'longtext':
+ $column['collation_name'] = $row['Collation'];
+ break;
+
+ case 'enum':
+ case 'set':
+ $column['collation_name'] = $row['Collation'];
+ $column['options'] = explode('\',\'', substr($length, 1, -1));
+ break;
+ }
+
+ break;
+ }
+
+ // TSM attributes
+ $column['comment'] = $row['REMARKS'];
+ $columns[$row['COLUMN_NAME']] = $column;
+ }
+
+ return $columns;
+ }
+}
+?>
diff --git a/application/classes/database/tsm/dsmadmc.php b/application/classes/database/tsm/dsmadmc.php
new file mode 100644
index 0000000..31a15d5
--- /dev/null
+++ b/application/classes/database/tsm/dsmadmc.php
@@ -0,0 +1,186 @@
+_connection)
+ return;
+
+ // Extract the connection parameters, adding required variabels
+ extract($this->_config['connection'] + array(
+ 'database' => '',
+ 'hostname' => '',
+ 'username' => '',
+ 'password' => '',
+ 'persistent' => FALSE,
+ ));
+
+ // Get user login details from user session - these are set by login
+ if (! $username)
+ $username = Session::instance()->get_once(Kohana::config('auth.session_key'));
+ if (! $password)
+ $password = Session::instance()->get_once('password');
+
+ // Prevent this information from showing up in traces
+ unset($this->_config['connection']['username'], $this->_config['connection']['password']);
+
+ if (! file_exists(Kohana::config('config.client'))) {
+ system_message(array('title'=>'Cant find DSMADMC',
+ 'body'=>sprintf('Unable to find the dsmadmc at %s',Kohana::config('client.config')),
+ 'type'=>'error'));
+
+ return FALSE;
+ }
+
+ if (! $username OR ! $password)
+ Request::current()->redirect('/login?need_login=1');
+
+ try {
+ if ($persistent) {
+ // Create a persistent connection
+ throw new Kohana_Exception('Cant do persistant connections');
+
+ } else {
+ // Create a connection and force it to be a new link
+ $this->_connection = sprintf('%s %s -id=%s -password=%s -displ=list -editor=no -dataonly=YES %s %s ',
+ Kohana::config('config.client'),
+ $database ? '-server='.$database : '',
+ $username,
+ $password,
+ Kohana::config('config.client_errorlogname') ? sprintf('-errorlogname=%s',Kohana::config('config.client_errorlogname')) : '',
+ $database ? sprintf('-se=%s',$database) : ''
+ );
+
+ $result = $this->query(Database::SELECT,'SELECT server_name,platform,version,release,level,sublevel FROM status');
+
+ if ($result)
+ return TSM::instance()->set($username,$password,$result);
+ else
+ Request::current()->redirect(Request::detect_uri());
+ }
+
+ } catch (ErrorException $e) {
+ // No connection exists
+ $this->_connection = NULL;
+
+ throw new Database_Exception(':error', array(
+ ':error' => sprintf('%s error in %s (%s)',$e->getMessage(),$e->getFile(),$e->getLine()),
+ ),
+ $e->getCode());
+ }
+
+ // \xFF is a better delimiter, but the PHP driver uses underscore
+ $this->_connection_id = sha1($hostname.'_'.$username.'_'.$password);
+
+ if ( ! empty($this->_config['charset'])) {
+ // Set the character set
+ $this->set_charset($this->_config['charset']);
+ }
+ }
+
+ protected function execute($sql) {
+ $this->execute_stdout = '';
+
+ // We need to escape any back slashes, since the exec will transpose them
+ // @todo Is there a better way of doing this?
+ $sql = str_replace('\\','\\\\',$sql);
+
+ $this->execute_stderr = exec($this->_connection.'"'.$sql.'"',$this->execute_stdout,$this->execute_rc);
+
+ // Work out our message codes
+ $result = array();
+ foreach ($this->execute_stdout as $line)
+ if (! preg_match('/^('.$this->msg_format.')\s+/',$line,$matches))
+ array_push($result,$line);
+ elseif (! in_array($matches[1],$this->ignore_codes))
+ array_push($this->_query_msg_codes,$matches[1]);
+
+ // If we got a no data code
+ if (array_intersect($this->_query_msg_codes,$this->nodata_codes)) {
+ $result = array();
+ $this->execute_rc = 0;
+ }
+
+ return $result;
+ }
+
+ public function list_columns($table, $like = NULL, $add_prefix = TRUE) {
+ // Quote the table name
+ $table = ($add_prefix === TRUE) ? $this->quote_table($table) : $table;
+
+ if (is_string($like))
+ // Search for column names
+ throw new Kohana_Exception('Like queries not implemented');
+ else
+ // Find all column names
+ $result = $this->query(Database::SELECT, sprintf('SELECT * FROM SYSCAT.COLUMNS WHERE TABNAME=\'%s\'',$table), FALSE);
+
+ $count = 0;
+ $columns = array();
+ foreach ($result as $row) {
+ list($type, $length) = $this->_parse_type($row['TYPENAME']);
+
+ $column = $this->datatype($type);
+
+ $column['column_name'] = $row['COLNAME'];
+ $column['data_type'] = $type;
+ $column['is_nullable'] = ($row['NULLS'] == 'TRUE');
+ $column['ordinal_position'] = ++$count;
+
+ switch (strtolower($column['data_type'])) {
+ case 'float':
+ if (isset($length))
+ list($column['numeric_precision'], $column['numeric_scale']) = explode(',', $length);
+ break;
+
+ case 'int':
+ if (isset($length))
+ // MySQL attribute
+ $column['display'] = $length;
+ break;
+
+ case 'string':
+ switch ($column['data_type']) {
+ case 'binary':
+ case 'varbinary':
+ $column['character_maximum_length'] = $length;
+ break;
+
+ case 'char':
+ case 'varchar':
+ $column['character_maximum_length'] = $length;
+ case 'text':
+ case 'tinytext':
+ case 'mediumtext':
+ case 'longtext':
+ $column['collation_name'] = $row['Collation'];
+ break;
+
+ case 'enum':
+ case 'set':
+ $column['collation_name'] = $row['Collation'];
+ $column['options'] = explode('\',\'', substr($length, 1, -1));
+ break;
+ }
+
+ break;
+ }
+
+ // TSM attributes
+ $column['comment'] = $row['REMARKS'];
+ $columns[$row['COLNAME']] = $column;
+ }
+
+ return $columns;
+ }
+}
+?>
diff --git a/application/classes/database/tsm/result.php b/application/classes/database/tsm/result.php
index 2d06764..d1d3dbd 100644
--- a/application/classes/database/tsm/result.php
+++ b/application/classes/database/tsm/result.php
@@ -15,19 +15,32 @@ class Database_TSM_Result extends Database_Result {
parent::__construct($result, $sql, $as_object, $params);
$start = FALSE;
- foreach ($result as $line) {
- if (! trim($line)) {
- if ($start)
- $this->_internal_row++;
+ // Is this a DB2 result?
+ if (is_resource($result) AND function_exists('db2_fetch_object')) {
+ // If we are running a DB2 set command, we can return
+ if (preg_match('/^SET/',$sql))
+ return;
- continue;
+ while ($r = db2_fetch_object($result))
+ $this->_rows[$this->_internal_row++] = (array)$r;
+
+ // Is this an DSMADMC result?
+ } elseif (is_array($result))
+ foreach ($result as $line) {
+ if (! trim($line)) {
+ if ($start)
+ $this->_internal_row++;
+
+ continue;
+ }
+
+ list($k,$v) = explode(':',$line,2);
+
+ $this->_rows[$this->_internal_row][trim($k)] = trim($v);
+ $start = TRUE;
}
-
- list($k,$v) = explode(':',$line,2);
-
- $this->_rows[$this->_internal_row][trim($k)] = trim($v);
- $start = TRUE;
- }
+ else
+ throw new Kohana_Exception('Unknown result :result',array(':result'=>$result));
$this->_total_rows = $this->_internal_row;
$this->_internal_row = 0;
diff --git a/application/classes/database/tsm/set.php b/application/classes/database/tsm/set.php
new file mode 100644
index 0000000..55c6d1f
--- /dev/null
+++ b/application/classes/database/tsm/set.php
@@ -0,0 +1,15 @@
+
diff --git a/application/classes/model/auth/userdefault.php b/application/classes/model/auth/userdefault.php
index e59b14c..0d67e6e 100644
--- a/application/classes/model/auth/userdefault.php
+++ b/application/classes/model/auth/userdefault.php
@@ -13,5 +13,12 @@ class Model_Auth_UserDefault extends Model_Auth_User {
protected $_disable_wild_select = TRUE;
protected $_disable_join_table_name = TRUE;
protected $_disable_limit = TRUE;
+
+ protected function _initialize() {
+ // Set out DB connection configuration.
+ $this->_db_group = Kohana::config('config.client_type');
+
+ parent::_initialize();
+ }
}
?>
diff --git a/application/classes/model/domain.php b/application/classes/model/domain.php
index f245204..f90945e 100644
--- a/application/classes/model/domain.php
+++ b/application/classes/model/domain.php
@@ -22,6 +22,16 @@ class Model_DOMAIN extends ORMTSM {
'SCHEDULE_CLIENT'=>array('foreign_key'=>'DOMAIN_NAME','far_key'=>'DOMAIN_NAME')
);
+ protected $_tsm = array(
+ 'db2'=>array(
+ '_has_many'=>array(
+ 'MGMTCLASS'=>array('foreign_key'=>'DOMAIN_NAME','far_key'=>'DOMAIN_NAME'),
+ 'NODE'=>array('foreign_key'=>'DOMAINNAME','far_key'=>'DOMAIN_NAME'),
+ 'SCHEDULE_CLIENT'=>array('foreign_key'=>'DOMAIN_NAME','far_key'=>'DOMAIN_NAME')
+ ),
+ ),
+ );
+
// Pools used by a domain.
private $pools = array();
diff --git a/application/classes/model/filespace.php b/application/classes/model/filespace.php
index 9e83a1d..2139fd5 100644
--- a/application/classes/model/filespace.php
+++ b/application/classes/model/filespace.php
@@ -17,9 +17,29 @@ class Model_FILESPACE extends ORMTSM {
'FILESPACE_NAME'=>'ASC',
);
+ protected $_has_one = array(
+ 'NODE'=>array('foreign_key'=>'NODE_NAME','far_key'=>'NODE_NAME'),
+ );
+
protected $_has_many = array(
- 'VOLUMEUSAGE'=>array('foreign_key'=>array('NODE_NAME'=>'NODE_NAME','FILESPACE_NAME'=>'FILESPACE_NAME')),
- 'OCCUPANCY'=>array('foreign_key'=>array('NODE_NAME'=>'NODE_NAME','FILESPACE_NAME'=>'FILESPACE_NAME')),
+ );
+
+ protected $_tsm = array(
+ 'db2'=>array(
+ '_primary_key'=>'FSNAME',
+ '_sorting'=>array(
+ 'NODEID'=>'ASC',
+ 'FSNAME'=>'ASC',
+ ),
+ '_has_one'=>array(
+ 'NODE'=>array('foreign_key'=>'NODEID','far_key'=>'NODEID'),
+ ),
+ 'translate'=>array(
+ 'FILESPACE_NAME'=>'FSNAME',
+ 'BACKUP_END'=>'BACKSTART',
+ 'PCT_UTIL'=>NULL,
+ ),
+ ),
);
protected $_display_filters = array(
@@ -29,16 +49,17 @@ class Model_FILESPACE extends ORMTSM {
);
public function utilsation() {
- return $this->CAPACITY * ($this->PCT_UTIL/100);
+ return $this->CAPACITY*($this->PCT_UTIL/100);
}
// $dtype must be Bkup or Arch
public function storagepools($dtype) {
$pool = array();
- foreach ($this->OCCUPANCY
+ foreach ($this->NODE->OCC
->select('STGPOOL_NAME')
->where('TYPE','=',$dtype)
+ ->and_where('FILESPACE_NAME','=',$this->FILESPACE_NAME)
->group_by('STGPOOL_NAME')
->order_by('STGPOOL_NAME')
->find_all() as $oo)
@@ -49,11 +70,19 @@ class Model_FILESPACE extends ORMTSM {
}
public function pool_logical_util($pool,$btype) {
- return $this->OCCUPANCY->where('STGPOOL_NAME','=',$pool)->where('TYPE','=',$btype)->find()->LOGICAL_MB;
+ return $this->NODE->OCC
+ ->where('STGPOOL_NAME','=',$pool)
+ ->and_where('TYPE','=',$btype)
+ ->and_where('FILESPACE_NAME','=',$this->FILESPACE_NAME)
+ ->find()->LOGICAL_MB;
}
public function pool_numvols($pool,$ctype) {
- return $this->VOLUMEUSAGE->where('STGPOOL_NAME','=',$pool)->where('COPY_TYPE','=',$ctype)->find_all()->count();
+ return $this->NODE->VOLUMEUSAGE
+ ->where('STGPOOL_NAME','=',$pool)
+ ->and_where('COPY_TYPE','=',$ctype)
+ ->and_where('FILESPACE_NAME','=',$this->FILESPACE_NAME)
+ ->find_all()->count();
}
}
?>
diff --git a/application/classes/model/node.php b/application/classes/model/node.php
index 56f621c..59887ea 100644
--- a/application/classes/model/node.php
+++ b/application/classes/model/node.php
@@ -27,6 +27,61 @@ class Model_NODE extends ORMTSM {
'CLIENTOPT'=>array('foreign_key'=>'OPTIONSET_NAME','far_key'=>'OPTION_SET'),
'SUMMARY'=>array('foreign_key'=>'ENTITY','far_key'=>'NODE_NAME'),
'EVENT'=>array('foreign_key'=>'NODE_NAME','far_key'=>'NODE_NAME'),
+ 'OCC'=>array('foreign_key'=>'NODE_NAME','far_key'=>'NODE_NAME'),
+ );
+
+ protected $_tsm = array(
+ 'db2'=>array(
+ '_primary_key'=>'NODENAME',
+ '_sorting'=>array(
+ 'NODENAME'=>'ASC',
+ ),
+ '_has_one'=>array(
+ 'DOMAIN'=>array('foreign_key'=>'DOMAIN_NAME','far_key'=>'DOMAINNAME'),
+ ),
+ '_has_many'=>array(
+ 'FILESPACE'=>array('foreign_key'=>'NODEID','far_key'=>'NODEID'),
+ 'VOLUMEUSAGE'=>array('foreign_key'=>'NODE_NAME','far_key'=>'NODENAME'),
+ 'ASSOCIATION'=>array('foreign_key'=>'NODE_NAME','far_key'=>'NODENAME'),
+ 'MGMTCLASS'=>array('foreign_key'=>'DOMAIN_NAME','far_key'=>'DOMAIN_NAME'),
+ 'CLIENTOPT'=>array('foreign_key'=>'OPTIONSET_NAME','far_key'=>'OPTIONSET'),
+ 'SUMMARY'=>array('foreign_key'=>'ENTITY','far_key'=>'NODENAME'),
+ 'EVENT'=>array('foreign_key'=>'NODE_NAME','far_key'=>'NODENAME'),
+ 'OCC'=>array('foreign_key'=>'NODE_NAME','far_key'=>'NODENAME'),
+ ),
+ 'translate'=>array(
+ 'NODE_NAME'=>'NODENAME',
+ 'CLIENT_VERSION'=>'CLNTVERSION',
+ 'CLIENT_RELEASE'=>'CLNTRELEASE',
+ 'CLIENT_LEVEL'=>'CLNTLEVEL',
+ 'CLIENT_SUBLEVEL'=>'CLNTSUBLEVEL',
+ 'PLATFORM_NAME'=>'OSNAME',
+ 'CLIENT_OS_LEVEL'=>'CLNTOSLEVEL',
+ 'LASTACC_TIME'=>'LACDATE',
+ 'REG_TIME'=>'REGDATE',
+ 'PWSET_TIME'=>'PWSETDATE',
+ 'LASTSESS_SENT'=>'SESSSENT',
+ 'LASTSESS_RECVD'=>'SESSRECVD',
+ 'LASTSESS_DURATION'=>'SESSDURATION',
+ 'LASTSESS_IDLEWAIT'=>'SESSIDLEWAIT',
+ 'LASTSESS_COMMWAIT'=>'SESSCOMMWAIT',
+ 'LASTSESS_MEDIAWAIT'=>'SESSMEDIAWAIT',
+ 'TCP_ADDRESS'=>NULL,
+ 'EMAIL_ADDRESS'=>NULL,
+ 'REG_ADMIN'=>'REGISTRAR',
+ 'PASSEXP'=>NULL,
+ 'INVALID_PW_COUNT'=>'INVPWCOUNT',
+ 'LOCKED'=>'LOCKSTATE',
+ 'DOMAIN_NAME'=>'DOMAINNAME',
+ 'OPTION_SET'=>'OPTIONSET',
+ 'COLLOCGROUP_NAME'=>NULL,
+ 'COMPRESSION'=>'COMPRESS',
+ 'ARCHDELETE'=>'ARCHDEL',
+ 'BACKDELETE'=>'BACKDEL',
+ 'KEEP_MP'=>NULL,
+ 'MAX_MP_ALLOWED'=>'MAXNUMMP',
+ ),
+ ),
);
protected $_display_filters = array(
@@ -196,10 +251,9 @@ class Model_NODE extends ORMTSM {
public function getStorageModeFiles($dtype,$ptype,$spo='') {
$count = 0;
- foreach ($this->FILESPACE->find_all() as $fo)
- foreach ($fo->OCCUPANCY->where('TYPE','=',$dtype)->find_all() as $oa)
- if ((! $spo OR $oa->STGPOOL_NAME == $spo) AND $oa->STGPOOL->POOLTYPE == $ptype)
- $count += $oa->NUM_FILES;
+ foreach ($this->OCC->where('TYPE','=',$dtype)->find_all() as $oa)
+ if ((! $spo OR $oa->STGPOOL_NAME == $spo) AND $oa->STGPOOL->POOLTYPE == $ptype)
+ $count += $oa->NUM_FILES;
return $count;
}
@@ -219,10 +273,9 @@ class Model_NODE extends ORMTSM {
public function getStorageModeData($dtype,$ptype,$spo='') {
$count = 0;
- foreach ($this->FILESPACE->find_all() as $fo)
- foreach ($fo->OCCUPANCY->where('TYPE','=',$dtype)->find_all() as $oa)
- if ((! $spo OR $oa->STGPOOL_NAME == $spo) AND $oa->STGPOOL->POOLTYPE == $ptype)
- $count += $oa->LOGICAL_MB;
+ foreach ($this->OCC->where('TYPE','=',$dtype)->find_all() as $oa)
+ if ((! $spo OR $oa->STGPOOL_NAME == $spo) AND $oa->STGPOOL->POOLTYPE == $ptype)
+ $count += $oa->LOGICAL_MB;
return $count;
}
diff --git a/application/classes/model/occupancy.php b/application/classes/model/occ.php
similarity index 83%
rename from application/classes/model/occupancy.php
rename to application/classes/model/occ.php
index a69b027..1e636e8 100644
--- a/application/classes/model/occupancy.php
+++ b/application/classes/model/occ.php
@@ -8,8 +8,9 @@
* @author Deon George
* @copyright (c) 2010 phpTSMadmin Development Team
* @license http://phptsmadmin.sf.net/license.html
+ * @node This has been renamed to OCC from OCCUPANCY, as DB2/FILESPACES has an OCCUPANCY column
*/
-class Model_OCCUPANCY extends ORMTSM {
+class Model_OCC extends ORMTSM {
protected $_table_name = 'OCCUPANCY';
protected $_primary_key = 'NODE_NAME'; // We need a primary key to detect that the object is loaded.
protected $_sorting = array(
diff --git a/application/classes/ormtsm.php b/application/classes/ormtsm.php
index 4927c22..f04b383 100644
--- a/application/classes/ormtsm.php
+++ b/application/classes/ormtsm.php
@@ -25,6 +25,39 @@ class ORMTSM extends ORM {
protected $_formated = FALSE;
protected $_formats = array();
+ protected $_tsm = array();
+
+ /**
+ *
+ * Configuration to enable PLA to work with DSMADMC & DB2 connections
+ * This is required, because the schema is different between each
+ * connection?
+ */
+ protected function _initialize() {
+ // Set out DB connection configuration.
+ $this->_db_group = Kohana::config('config.client_type');
+
+ // Adjustments for DSMADMC or DB2 connections
+ if (array_key_exists(Kohana::config('config.client_type'),$this->_tsm))
+ foreach ($this->_tsm[Kohana::config('config.client_type')] as $k => $v)
+ if (preg_match('/^_/',$k))
+ $this->{$k} = $v;
+
+ if ($this->_db_group == 'db2')
+ $this->_disable_join_table_name = FALSE;
+
+ parent::_initialize();
+ }
+
+ public function __get($column) {
+ // Get a substited column name - need for DB2/DSMADMC schema differences
+ if (isset($this->_tsm[Kohana::config('config.client_type')]['translate']) AND array_key_exists($column,$this->_tsm[Kohana::config('config.client_type')]['translate'])) {
+ return is_null($c=$this->_tsm[Kohana::config('config.client_type')]['translate'][$column]) ? NULL : parent::__get($c);
+}
+ else
+ return parent::__get($column);
+ }
+
public function find() {
// Check if we can preload our data and havent already done it
if ($time = $this->isCacheable() AND is_null(Cache::instance()->get($cache_key = 'PRELOAD:'.$this->_table_name))) {
diff --git a/application/classes/systemmessage.php b/application/classes/systemmessage.php
index 5324687..e2b2125 100644
--- a/application/classes/systemmessage.php
+++ b/application/classes/systemmessage.php
@@ -14,7 +14,7 @@ class SystemMessage extends lnApp_SystemMessage {
static public function TSM_Error($error,$sql) {
SystemMessage::add(array(
'title'=>_('Error while talking to TSM'),
- 'body'=>_('Running SQL').': '.$sql.'
'.implode('
',$error),
+ 'body'=>_('Running SQL').': '.$sql.'
'.(is_array($error) ? implode('
',$error) : $error),
'type'=>'error',
));
}
diff --git a/application/config/config.php b/application/config/config.php
index 635d7d2..d9f4ae7 100644
--- a/application/config/config.php
+++ b/application/config/config.php
@@ -13,6 +13,7 @@
return array(
'cache_type' => 'file',
'client' => '/opt/tivoli/tsm/client/ba/bin/dsmadmc',
+ 'client_type' => 'db2',
'client_errorlogname' => '/tmp/pta-tsm-errorlog.log',
'date_format' => 'd-m-Y',
'tsmdatatypes' => array('Bkup'=>'BACKUP','Arch'=>'ARCHIVE'),
diff --git a/application/config/database.php b/application/config/database.php
index 9ccc8c0..fd4d24d 100644
--- a/application/config/database.php
+++ b/application/config/database.php
@@ -13,9 +13,9 @@
return array
(
- 'default' => array
+ 'dsmadmc' => array
(
- 'type' => 'tsm',
+ 'type' => 'tsm_dsmadmc',
'connection' => array(
/**
* The following options are available for MySQL:
@@ -32,7 +32,71 @@ return array
'username' => FALSE,
'password' => FALSE,
//'persistent' => FALSE, // Unused
- 'database' => 'local',
+ ),
+ 'table_prefix' => '',
+ 'charset' => 'utf8',
+ 'caching' => TRUE,
+ 'cache' => array(
+ 'ASSOCIATIONS' => 1200,
+ 'AR_COPYGROUPS' => 1200,
+ 'BU_COPYGROUPS' => 1200,
+ 'CLIENT_SCHEDULES' => 1200,
+ 'CLIENTOPTS' => 1200,
+ 'DEVCLASSES' => 1200,
+ 'DOMAINS' => 1200,
+ 'DRIVES' => 1200,
+ 'EVENTS' => 1200,
+ 'FILESPACES' => 1200,
+ 'LIBRARIES' => 1200,
+ 'LIBVOLUMES' => 1200,
+ 'MEDIA' => 1200,
+ 'MGMTCLASSES' => 1200,
+ 'NODES' => 1200,
+ 'OCCUPANCY' => 1200,
+ 'PATHS' => 1200,
+ 'SCHEMA' => 604800,
+ 'STGPOOLS' => 1200,
+ 'SUMMARY' => 180,
+ 'VOLHISTORY' => 1200,
+ 'VOLUMES' => 1200,
+ 'VOLUMEUSAGE' => 1200,
+ ),
+ 'cachepreload' => array(
+ 'DEVCLASSES' => 1200,
+ 'DOMAINS' => 1200,
+ 'DRIVES' => 1200,
+ 'LIBVOLUMES' => 1200,
+ 'LIBRARIES' => 1200,
+ 'MEDIA' => 1200,
+ 'NODES' => 1200,
+ 'STGPOOLS' => 1200,
+ 'VOLHISTORY' => 1200,
+ 'VOLUMES' => 1200,
+ ),
+ 'profiling' => TRUE,
+ ),
+
+ 'db2' => array
+ (
+ 'type' => 'tsm_db2',
+ 'connection' => array(
+ /**
+ * The following options are available for DB2:
+ *
+ * string hostname server hostname, or socket
+ * string database database name
+ * string username database username
+ * string password database password
+ * boolean persistent use persistent connections?
+ *
+ * Ports and sockets may be appended to the hostname.
+ */
+ 'hostname' => 'localhost',
+ 'port' => '60000',
+ 'username' => FALSE,
+ 'password' => FALSE,
+ 'persistent' => FALSE,
+ 'database' => 'TSMDB1',
),
'table_prefix' => '',
'charset' => 'utf8',
diff --git a/application/config/userguide.php b/application/config/userguide.php
index f5c3179..60b4839 100644
--- a/application/config/userguide.php
+++ b/application/config/userguide.php
@@ -20,16 +20,16 @@ return array(
'copyright' => '© 2008–2011 phpTSMadmin Development Team',
),
'cache' => array(
- 'enabled' => FALSE,
+ 'enabled' => TRUE,
),
'database' => array(
- 'enabled' => FALSE,
+ 'enabled' => TRUE,
),
'kohana' => array(
- 'enabled' => FALSE,
+ 'enabled' => TRUE,
),
'orm' => array(
- 'enabled' => FALSE,
+ 'enabled' => TRUE,
),
'userguide' => array(
'enabled' => FALSE,
diff --git a/application/guide/pta/db2.md b/application/guide/pta/db2.md
new file mode 100644
index 0000000..e52cfbd
--- /dev/null
+++ b/application/guide/pta/db2.md
@@ -0,0 +1,10 @@
+-1. extract /.../COI/PackageSteps/DB2/FILES/ese/db2/linuxamd64/FILES/BASE_CLIENT_9.7.0.2_linuxamd64_x86_64.tar.gz
+1. extract /.../COI/PackageSteps/DB2/FILES/ese/db2/linuxamd64/FILES/APPLICATION_DEVELOPMENT_TOOLS_9.7.0.2_linuxamd64_x86_64.tar.gz
+2. link /opt/tivoli/tsm/db2/includes to extracted developer files
+3. yum install gcc --enabler=updates
+4. install php-pear (from webtatic)
+5. install php-devel (from webtatic)
+6. pecl install ibm_db2 (as root)
+7. create php.d/db2.ini
+8. run db2set DB2COMM=tcpip as tsminst1
+9. open TCP port to enable remote connections db2 UPDATE DBM CFG USING SVCENAME DB2_tsminst1
diff --git a/application/guide/pta/menu.md b/application/guide/pta/menu.md
index 22f16f4..22a4392 100644
--- a/application/guide/pta/menu.md
+++ b/application/guide/pta/menu.md
@@ -1,2 +1,3 @@
## [PTA]()
- [Installation](install)
+- [DB2](db2)