summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBo Peng2021-04-27 07:33:17 +0000
committerBo Peng2021-04-27 07:33:17 +0000
commitbc7ca9fde6f4772cc4ab0b0a001cb02b7c3708b3 (patch)
tree4ba0e42f83923321b59ed5d99c723af48f5ac14c
parent41b7fe34e23849f5fe44ea83468875997133262f (diff)
Fixed incorrect display of health check and watchdog.
Patch is created by Kawamoto Masaya and modified by me.
-rw-r--r--common.php161
-rw-r--r--definePgpoolConfParam.php2
-rw-r--r--innerSummary.php3
-rw-r--r--innerWatchdog.php12
-rw-r--r--lang/en.lang.php12
-rw-r--r--lang/ja.lang.php6
-rw-r--r--templates/elements/status_nodeinfo.tpl74
-rw-r--r--templates/innerSummary.tpl56
-rw-r--r--templates/innerWatchdog.tpl24
9 files changed, 277 insertions, 73 deletions
diff --git a/common.php b/common.php
index bf1353c..f78b842 100644
--- a/common.php
+++ b/common.php
@@ -149,18 +149,15 @@ function execQuery($conn, $sql)
*/
function NodeActive($nodeNum)
{
- $params = readConfigParams(array(
- 'backend_hostname', 'backend_port', 'backend_weight',
- 'health_check_user', 'health_check_password', 'health_check_database'
- ));
+ $params = readConfigParams();
+ $perNodeParams = getPerNodeHealthCheck($nodeNum);
$conn = openDBConnection(array(
'host' => $params['backend_hostname'][$nodeNum],
'port' => $params['backend_port'][$nodeNum],
- 'dbname' => (paramExists('health_check_database') && $params['health_check_database'] != '') ?
- $params['health_check_database'] : 'template1',
- 'user' => $params['health_check_user'],
- 'password' => $params['health_check_password'],
+ 'dbname' => $perNodeParams['health_check_database'],
+ 'user' => $perNodeParams['health_check_user'],
+ 'password' => $perNodeParams['health_check_password'],
'connect_timeout' => _PGPOOL2_PG_CONNECT_TIMEOUT,
));
@@ -177,8 +174,15 @@ function NodeActive($nodeNum)
*/
function NodeStandby($nodeNum)
{
- if (isMasterSlaveMode() == FALSE || useStreaming() == FALSE) {
- return -1;
+ if (hasBackendClusteringMode()){
+ $params = readConfigParams(array('backend_clustering_mode'));
+ if ($params['backend_clustering_mode'] != 'streaming_replication') {
+ return -1;
+ }
+ } else {
+ if (isMasterSlaveMode() == FALSE || useStreaming() == FALSE) {
+ return -1;
+ }
}
$params = readConfigParams(array(
@@ -789,6 +793,82 @@ function paramExists($param)
return $rtn;
}
+function getPerNodeHealthCheck($nodeNum){
+ $rtn = array();
+ $params = readConfigParams();
+
+ $period = $params['health_check_period'];
+ if(isset($params['health_check_period' . $nodeNum])
+ && $params['health_check_period' . $nodeNum] != '')
+ {
+ $period = $params['health_check_period' . $nodeNum];
+ }
+
+ $timeout = $params['health_check_timeout'];
+ if(isset($params['health_check_timeout' . $nodeNum])
+ && $params['health_check_timeout' . $nodeNum] != '')
+ {
+ $timeout = $params['health_check_timeout' . $nodeNum];
+ }
+
+ $user = $params['health_check_user'];
+ if(isset($params['health_check_user' . $nodeNum])
+ && $params['health_check_user' . $nodeNum] != '')
+ {
+ $user = $params['health_check_user' . $nodeNum];
+ }
+
+ $password = $params['health_check_password'];
+ if(isset($params['health_check_password' . $nodeNum])
+ && $params['health_check_password' . $nodeNum] != '')
+ {
+ $password = $params['health_check_password' . $nodeNum];
+ }
+
+ $database = 'template1';
+ if(isset($params['health_check_database' . $nodeNum])
+ && $params['health_check_database' . $nodeNum] != '')
+ {
+ $database = $params['health_check_database' . $nodeNum];
+ }else{
+ $database = ($params['health_check_database'] != '') ?
+ $params['health_check_database'] : 'template1';
+ }
+
+ $max_retries = $params['health_check_max_retries'];
+ if(isset($params['health_check_max_retries' . $nodeNum])
+ && $params['health_check_max_retries' . $nodeNum] != '')
+ {
+ $max_retries = $params['health_check_max_retries' . $nodeNum];
+ }
+
+ $retry_delay = $params['health_check_retry_delay'];
+ if(isset($params['health_check_retry_delay' . $nodeNum])
+ && $params['health_check_retry_delay' . $nodeNum] != '')
+ {
+ $retry_delay = $params['health_check_retry_delay' . $nodeNum];
+ }
+
+ $connect_timeout = $params['connect_timeout'];
+ if(isset($params['connect_timeout' . $nodeNum])
+ && $params['connect_timeout' . $nodeNum] != '')
+ {
+ $connect_timeout = $params['connect_timeout' . $nodeNum];
+ }
+
+ $rtn = array(
+ 'health_check_period' => $period,
+ 'health_check_timeout' => $timeout,
+ 'health_check_user' => $user,
+ 'health_check_password' => $password,
+ 'health_check_database' => $database,
+ 'health_check_max_retries' => $max_retries,
+ 'connect_timeout' => $connect_timeout,
+ 'health_check_retry_delay' => $retry_delay
+ );
+ return $rtn;
+}
+
/* --------------------------------------------------------------------- */
/* function (mode) */
/* --------------------------------------------------------------------- */
@@ -804,26 +884,45 @@ function versions()
*/
function isReplicationMode()
{
- $params = readConfigParams(array('replication_mode'));
-
- if (isTrue($params['replication_mode'])) {
- return TRUE;
+ if (hasBackendClusteringMode()){
+ $params = readConfigParams(array('backend_clustering_mode'));
+ if ($params['backend_clustering_mode'] == 'native_replication_mode'){
+ return TRUE;
+ } else {
+ return FALSE;
+ }
} else {
- return FALSE;
- }
-}
+ $params = readConfigParams(array('replication_mode'));
+ if (isTrue($params['replication_mode'])) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ }
+}
/**
* Whether pgpool is operating in the master slave mode or not?
*/
function isMasterSlaveMode()
{
- $params = readConfigParams(array('master_slave_mode'));
-
- if (isTrue($params['master_slave_mode'])) {
- return TRUE;
+ if (hasBackendClusteringMode()){
+ $params = readConfigParams(array('backend_clustering_mode'));
+ if ($params['backend_clustering_mode'] == 'streaming_replication'
+ || $params['backend_clustering_mode'] == 'logical_replication'
+ || $params['backend_clustering_mode'] == 'slony') {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
} else {
- return FALSE;
+ $params = readConfigParams(array('master_slave_mode'));
+
+ if (isTrue($params['master_slave_mode'])) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
}
}
@@ -976,10 +1075,26 @@ function isTrue($value)
function definedHealthCheckParam($params, $param_name, $backend_num)
{
- return isset($params[$param_name . $backend_num]) ?
+ return isset($params[$param_name . $backend_num]) ?
$param_name . $backend_num : null;
}
+function isHealthCheckValid($params)
+{
+ if (isset($params["health_check_period"]) && $params["health_check_period"] != 0) {
+ return TRUE;
+ }
+
+ foreach ($params["backend_hostname"] as $backend_num => $value) {
+ if (isset($params["health_check_period" . $backend_num]) &&
+ $params["health_check_period" . $backend_num] != 0) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
function errorPage($errorCode)
{
global $tpl;
diff --git a/definePgpoolConfParam.php b/definePgpoolConfParam.php
index 7d4934c..9a4ffbe 100644
--- a/definePgpoolConfParam.php
+++ b/definePgpoolConfParam.php
@@ -102,6 +102,7 @@ $key = 'reserved_connections';
$pgpoolConfigParam[$key]['type'] = 'N';
$pgpoolConfigParam[$key]['default'] = '0';
$pgpoolConfigParam[$key]['max'] = NUM_MAX;
+$pgpoolConfigParam[$key]['min'] = 0;
$pgpoolConfigParam[$key]['restart'] = TRUE;
# - pgpool Communication Manager Connection Settings -
@@ -1370,6 +1371,7 @@ $key = 'check_temp_table';
if (_PGPOOL2_VERSION >= 4.1) {
$pgpoolConfigParam[$key]['type'] = 'C';
$pgpoolConfigParam[$key]['default'] = 'catalog';
+ $pgpoolConfigParam[$key]['regexp'] = $anyelse;
} else {
$pgpoolConfigParam[$key]['type'] = 'B';
$pgpoolConfigParam[$key]['default'] = 'on';
diff --git a/innerSummary.php b/innerSummary.php
index 8b82de8..9ab5cfe 100644
--- a/innerSummary.php
+++ b/innerSummary.php
@@ -40,7 +40,8 @@ $params = readConfigParams(array('parallel_mode',
'load_balance_mode',
'use_watchdog',
'wd_lifecheck_method',
- 'health_check_period'));
+ 'health_check_period',
+ 'backend_clustering_mode'));
$tpl->assign('params', $params);
$tpl->display('innerSummary.tpl');
diff --git a/innerWatchdog.php b/innerWatchdog.php
index 9b4c723..3e9c333 100644
--- a/innerWatchdog.php
+++ b/innerWatchdog.php
@@ -44,12 +44,20 @@ $params = readConfigParams(array('port',
'wd_lifecheck_query',
'other_pgpool_hostname',
'other_pgpool_port',
- 'other_wd_port'));
+ 'other_wd_port',
+ 'hostname',
+ 'pgpool_port'));
// get watchdog information
$watchdogInfo = array();
-if (3.5 <= _PGPOOL2_VERSION) {
+
+if (4.2 <= _PGPOOL2_VERSION) {
+ for ($i = 0; $i < count($params['hostname']); $i++) {
+ $watchdogInfo[] = getWatchdogInfo($i);
+ }
+
+} else if (3.5 <= _PGPOOL2_VERSION) {
$watchdogInfo['local'] = getWatchdogInfo(0);
for ($i = 0; $i < count($params['other_pgpool_hostname']); $i++) {
$watchdogInfo[] = getWatchdogInfo($i + 1);
diff --git a/lang/en.lang.php b/lang/en.lang.php
index bedbe70..d560463 100644
--- a/lang/en.lang.php
+++ b/lang/en.lang.php
@@ -285,6 +285,7 @@ $message = array(
'strAdminPassword' => 'Password',
'strBack' => 'Back',
'strBackendPid' => 'Backend Pid',
+ 'strBackendClusteringMode' => 'Backend Clustering Mode',
'strCancel' => 'Cancel',
'strChangePassword' => 'Change Password',
'strClear' => 'Clear',
@@ -341,7 +342,7 @@ $message = array(
'strLogShowAll' => 'Show the All Lines',
'strLogShowLines' => 'Lines',
'strMasterServer' => 'Master Server',
- 'strMasterSlaveMode' => 'Master Slave mode',
+ 'strMasterSlaveMode' => 'Master Slave Mode',
'strMeasures' => 'Measures',
'strNodeInfo' => 'Node Info.',
'strNodeStatus' => 'Node Status',
@@ -381,6 +382,7 @@ $message = array(
'strProcInfo' => 'Process Info.',
'strProcTime' => 'Process Start Time',
'strPromote' => 'Promote',
+ 'strPromotePrimary' => 'Promote',
'strProtocolMajorVersion' => 'Protocol Major Version',
'strProtocolNinorVersion' => 'Protocol Minor Version',
'strQueryCache' => 'Query Cache',
@@ -402,7 +404,7 @@ $message = array(
'strSecondaryServer' => 'Secondary Server',
'strSetting' => 'pgpoolAdmin Setting',
'strSetup' => 'Setup',
- 'strSlonyMode' => 'Slony-I mode',
+ 'strSlonyMode' => 'Slony-I Mode',
'strStandbyRunning' => 'Running as standby server',
'strStartOption' => 'Start Option',
'strStartPgpool' => 'Start pgpool',
@@ -413,7 +415,7 @@ $message = array(
'strStopPgsql' => 'Stop',
'strStopPgsqlOption' => 'Stop PostgreSQL Option',
'strStoppingNow' => 'Not Running',
- 'strStreamingRepMode' => 'Streaming Replication mode',
+ 'strStreamingRepMode' => 'Streaming Replication Mode',
'strSummary' => 'Summary',
'strSystemDb' => 'Partitioning Rule',
'strSystemCatalog' => 'System catalog',
@@ -431,6 +433,10 @@ $message = array(
'strWdInit' => 'Not Started',
'strWdStandby' => 'Standby',
'strWeight' => 'Weight',
+ 'strLogocalRepMode' => 'Logical Replication Mode',
+ 'strNativeRepMode' => 'Native Replication Mode',
+ 'strRawMode' => 'RAW Mode',
+
'e1' => 'pgmgt.conf.php not found.',
'e2' => 'Message catalog not found.',
diff --git a/lang/ja.lang.php b/lang/ja.lang.php
index b7b0488..8dc7296 100644
--- a/lang/ja.lang.php
+++ b/lang/ja.lang.php
@@ -269,6 +269,7 @@ $message = array(
'strAdminPassword' => '管理者パスワード',
'strBack' => '戻る',
'strBackendPid' => 'バックエンドプロセスID',
+ 'strBackendClusteringMode' => 'バックエンドクラスタリングモード',
'strCancel' => 'キャンセル',
'strChangePassword' => 'パスワード変更',
'strClear' => 'クリア',
@@ -365,6 +366,7 @@ $message = array(
'strProcInfo' => 'プロセス情報',
'strProcTime' => 'プロセススタート時刻',
'strPromote' => 'マスタ昇格',
+ 'strPromotePrimary' => 'プライマリ昇格',
'strProtocolMajorVersion' => 'プロトコルメジャーバージョン',
'strProtocolNinorVersion' => 'プロトコルマイナーバージョン',
'strQueryCache' => 'クエリキャッシュ',
@@ -415,6 +417,10 @@ $message = array(
'strWdInit' => '未起動',
'strWdStandby' => 'スタンバイ',
'strWeight' => 'ウェイト',
+ 'strLogocalRepMode' => 'Logical Replicationモード',
+ 'strNativeRepMode' => 'Native Replicationモード',
+ 'strRawMode' => 'RAWモード',
+ 'strSnapshotIsolationMode' => 'Snapshot Isolationモード',
'e1' => 'pgmgt.conf.phpが見つかりません',
'e2' => 'メッセージカタログが見つかりません',
diff --git a/templates/elements/status_nodeinfo.tpl b/templates/elements/status_nodeinfo.tpl
index 20d0d2b..5179569 100644
--- a/templates/elements/status_nodeinfo.tpl
+++ b/templates/elements/status_nodeinfo.tpl
@@ -18,10 +18,11 @@
<th></th>
<th><label>{$message.strIPaddress|escape}</label></th>
<th><label>{$message.strPort|escape}</label></th>
- <th colspan="2"><label>{$message.strStatus|escape}</label></th>
+ <th><label>{$message.strStatus|escape}</label></th>
{if $parallelMode == false}
<th><label>{$message.strWeight|escape}</label></th>
{/if}
+ <th colspan="2"><label>{$message.strHealthCheck|escape}</label></th>
<th></th>
<th></th>
</tr>
@@ -60,17 +61,16 @@
{elseif $nodeInfo.$node_num.is_standby === 0}
{$message.strPrimaryRunning|escape}
{/if}
+ </br>
+ postgres:
+ {if $nodeInfo.$node_num.is_active}{$message.strUp|escape}
+ {else}{$message.strDown|escape}
+ {/if}
</td>
{else}
<td align="center">-</td>
{/if}
- <td>postgres:
- {if $nodeInfo.$node_num.is_active}{$message.strUp|escape}
- {else}{$message.strDown|escape}
- {/if}
- </td>
-
{* ---------------------------------------------------------------------- *}
{* weight *}
{* ---------------------------------------------------------------------- *}
@@ -84,6 +84,22 @@
{/if}
{* ---------------------------------------------------------------------- *}
+ {* health check *}
+ {* ---------------------------------------------------------------------- *}
+ <td>
+ {$perHC = getPerNodeHealthCheck($node_num)}
+ database: {$perHC.health_check_database|escape}</br>
+ user: {$perHC.health_check_user|escape}</br>
+ period: {$perHC.health_check_period|escape}</br>
+ timeout: {$perHC.health_check_timeout|escape}
+ </td>
+ <td>
+ max retries: {$perHC.health_check_max_retries|escape}</br>
+ retry delay: {$perHC.health_check_retry_delay|escape}</br>
+ connect timeout: {$perHC.connect_timeout|escape}
+ </td>
+
+ {* ---------------------------------------------------------------------- *}
{* buttons (attch, recovery, etc.) *}
{* ---------------------------------------------------------------------- *}
@@ -114,10 +130,17 @@
{/if}
{if $nodeInfo.$node_num.promote && $nodeInfo.$node_num.is_standby == 1}
- <input type="button" name="command"
- onclick="sendCommand('promote', {$node_num|escape},
+ {if hasBackendClusteringMode()}
+ <input type="button" name="command"
+ onclick="sendCommand('promote', {$node_num|escape},
'{$message.msgRPromoteConfirm|escape}')"
- value="{$message.strPromote|escape}" />
+ value="{$message.strPromotePrimary|escape}" />
+ {else}
+ <input type="button" name="command"
+ onclick="sendCommand('promote', {$node_num|escape},
+ '{$message.msgRPromoteConfirm|escape}')"
+ value="{$message.strPromote|escape}" />
+ {/if}
{/if}
</td>
@@ -131,7 +154,7 @@
</tbody>
<tfoot>
- <tr><th colspan="8" align="right">
+ <tr><th colspan="9" align="right">
<input type="button" id="button_add_backend" onClick="addBackendButtonHandler()"
value="{$message.strAddBackend|escape}" />
</th>
@@ -146,17 +169,28 @@
<p>[ mode ]
-{if $params.replication_mode == 'on'}
- {$message.strReplicationMode|escape}
-{elseif $params.master_slave_mode == 'on'}
- {$message.strMasterSlaveMode|escape}
+{if hasBackendClusteringMode()}
+ {if $params.backend_clustering_mode == 'streaming_replication'}
+ {$message.strStreamingRepMode|escape}
+ {elseif $params.backend_clustering_mode == 'logical_replication'}
+ {$message.strLogocalRepMode|escape}
+ {elseif $params.backend_clustering_mode == 'slony'}
+ {$message.strSlonyMode|escape}
+ {elseif $params.backend_clustering_mode == 'native_replication'}
+ {$message.strNativeRepMode|escape}
+ {elseif $params.backend_clustering_mode == 'snapshot_isolation'}
+ {$message.strSnapshotIsolationMode|escape}
+ {elseif $params.backend_clustering_mode == 'raw'}
+ {$message.strRawMode|escape}
+ {/if}
+{else}
+ {if $params.replication_mode == 'on'}
+ {$message.strReplicationMode|escape}
+ {elseif $params.master_slave_mode == 'on'}
+ {$message.strMasterSlaveMode|escape}
+ {/if}
{/if}
{if $params.load_balance_mode == 'on'} / {$message.strLoadBalanceMode|escape}{/if}
{if $params.memory_cache_enabled == 'on'} / {$message.strQueryCache|escape} {$message.strOn|escape}{/if}
{if $params.use_watchdog == 'on'} / Watchdog {$message.strOn|escape}{/if}
</p>
-<p>
-[ healthcheck ]
-every {$params.health_check_period} seconds /
-retry up to {$params.health_check_max_retries} counts
-</p>
diff --git a/templates/innerSummary.tpl b/templates/innerSummary.tpl
index 356b947..86db3d6 100644
--- a/templates/innerSummary.tpl
+++ b/templates/innerSummary.tpl
@@ -27,25 +27,44 @@ td > img {
<table>
<tbody>
- <tr><td>{$message.strReplicationMode|escape}</td>
+ {if hasBackendClusteringMode()}
+ <tr><td>{$message.strBackendClusteringMode|escape}</td>
<td>
- {if $params.parallel_mode == 'on'}
- {$message.strInvalidation|escape}
- {elseif $params.replication_mode == 'on' || $params.backend_clustering_mode == 'native_replication'}
- <img src="images/check.png"> {$message.strOn|escape}
+ {if $params.backend_clustering_mode == 'streaming_replication'}
+ {$message.strStreamingRepMode|escape}
+ {elseif $params.backend_clustering_mode == 'logical_replication'}
+ {$message.strLogocalRepMode|escape}
+ {elseif $params.backend_clustering_mode == 'slony'}
+ {$message.strSlonyMode|escape}
+ {elseif $params.backend_clustering_mode == 'native_replication'}
+ {$message.strNativeRepMode|escape}
+ {elseif $params.backend_clustering_mode == 'snapshot_isolation'}
+ {$message.strSnapshotIsolationMode|escape}
+ {elseif $params.backend_clustering_mode == 'raw'}
+ {$message.strRawMode|escape}
+ {/if}
+ </td></tr>
{else}
- <img src="images/no.png"> {$message.strOff|escape}
- {/if}
- </td></tr>
+ <tr><td>{$message.strReplicationMode|escape}</td>
+ <td>
+ {if $params.parallel_mode == 'on'}
+ {$message.strInvalidation|escape}
+ {elseif $params.replication_mode == 'on'}
+ <img src="images/check.png"> {$message.strOn|escape}
+ {else}
+ <img src="images/no.png"> {$message.strOff|escape}
+ {/if}
+ </td></tr>
- <tr><td>{$message.strMasterSlaveMode|escape}</td>
- <td>
- {if $params.master_slave_mode == 'on' || $params.backend_clustering_mode == 'streaming_replication'}
- <img src="images/check.png"> {$message.strOn|escape} / {$params.master_slave_sub_mode|escape}
- {else}
- <img src="images/no.png"> {$message.strOff|escape}
+ <tr><td>{$message.strMasterSlaveMode|escape}</td>
+ <td>
+ {if $params.master_slave_mode == 'on'}
+ <img src="images/check.png"> {$message.strOn|escape} / {$params.master_slave_sub_mode|escape}
+ {else}
+ <img src="images/no.png"> {$message.strOff|escape}
+ {/if}
+ </td></tr>
{/if}
- </td></tr>
<tr><td>{$message.strParallelMode|escape}</td>
<td>
@@ -68,10 +87,11 @@ td > img {
</td></tr>
<tr><td>{$message.strHealthCheck|escape}</td>
<td>
- {if $params.health_check_period == 0}
- {$message.strInvalidation|escape}
- {else}
+
+ {if isHealthCheckValid($params)}
<img src="images/check.png"> {$message.strOn|escape}
+ {else}
+ {$message.strInvalidation|escape}
{/if}
</td></tr>
diff --git a/templates/innerWatchdog.tpl b/templates/innerWatchdog.tpl
index e22aa03..f0369ad 100644
--- a/templates/innerWatchdog.tpl
+++ b/templates/innerWatchdog.tpl
@@ -34,22 +34,34 @@
</tr>
</thead>
<tbody>
-<tr>
+{if $smarty.const._PGPOOL2_VERSION >= 4.2}
+ {section name=num loop=$params.hostname}
+ {if ($smarty.section.num.index) % 2 == 0}<tr class="even">{else}<tr class="odd">{/if}
+ <td>watchdog host {$smarty.section.num.index}</td>
+ <td>{$params.hostname[num]}</td>
+ <td>{$params.pgpool_port[num]}</td>
+ <td>{$params.wd_port[num]}</td>
+ <td>{$watchdogInfo[num]['status_str']|escape}</td>
+ </tr>
+ {/section}
+{else}
+ <tr>
<td>local</td>
<td>{$params.wd_hostname}</td>
<td>{$params.port}</td>
<td>{$params.wd_port}</td>
<td>{$watchdogInfo['local']['status_str']|escape}</td>
-</tr>
-{section name=num loop=$params.other_pgpool_hostname}
-{if ($smarty.section.num.index) % 2 == 0}<tr class="even">{else}<tr class="odd">{/if}
+ </tr>
+ {section name=num loop=$params.other_pgpool_hostname}
+ {if ($smarty.section.num.index) % 2 == 0}<tr class="even">{else}<tr class="odd">{/if}
<td>other {$smarty.section.num.index}</td>
<td>{$params.other_pgpool_hostname[num]}</td>
<td>{$params.other_pgpool_port[num]}</td>
<td>{$params.other_wd_port[num]}</td>
<td>{$watchdogInfo[num]['status_str']|escape}</td>
-</tr>
-{/section}
+ </tr>
+ {/section}
+{/if}
</tbody>
<tfoot>
<tr><th colspan="5"></th></tr>