null, 'item_types' => array( ITEM_VALUE_TYPE_FLOAT, ITEM_VALUE_TYPE_UINT64, ITEM_VALUE_TYPE_STR, ITEM_VALUE_TYPE_TEXT ) ); $ZBX_TR_EXPR_ALLOWED_FUNCTIONS['avg'] = array('args' => array( 0 => array('type' => 'sec_num','mandat' => true) ), 'item_types' => array( ITEM_VALUE_TYPE_FLOAT, ITEM_VALUE_TYPE_UINT64 ), ); $ZBX_TR_EXPR_ALLOWED_FUNCTIONS['delta'] = array('args' => array( 0 => array('type' => 'sec_num','mandat' => true) ), 'item_types' => array( ITEM_VALUE_TYPE_FLOAT, ITEM_VALUE_TYPE_UINT64 ), ); $ZBX_TR_EXPR_ALLOWED_FUNCTIONS['change'] = array('args' => null, 'item_types' => array( ITEM_VALUE_TYPE_FLOAT, ITEM_VALUE_TYPE_UINT64, ITEM_VALUE_TYPE_STR, ITEM_VALUE_TYPE_TEXT ), ); $ZBX_TR_EXPR_ALLOWED_FUNCTIONS['count'] = array('args' => array( 0 => array('type' => 'sec','mandat' => true), 1 => array('type' => 'str'), 1=>array('type' => 'str') ), 'item_types' => array( ITEM_VALUE_TYPE_FLOAT, ITEM_VALUE_TYPE_UINT64, ITEM_VALUE_TYPE_LOG, ITEM_VALUE_TYPE_STR, ITEM_VALUE_TYPE_TEXT ) ); $ZBX_TR_EXPR_ALLOWED_FUNCTIONS['date'] = array('args' => null, 'item_types' => null ); $ZBX_TR_EXPR_ALLOWED_FUNCTIONS['dayofweek']= array('args' => null, 'item_types' => null ); $ZBX_TR_EXPR_ALLOWED_FUNCTIONS['diff'] = array('args' => null, 'item_types' => array( ITEM_VALUE_TYPE_FLOAT, ITEM_VALUE_TYPE_UINT64, ITEM_VALUE_TYPE_STR, ITEM_VALUE_TYPE_TEXT ) ); $ZBX_TR_EXPR_ALLOWED_FUNCTIONS['fuzzytime'] = array('args' => null, 'item_types' => array( ITEM_VALUE_TYPE_FLOAT, ITEM_VALUE_TYPE_UINT64 ) ); $ZBX_TR_EXPR_ALLOWED_FUNCTIONS['iregexp']= array('args' => array( 0 => array('type' => 'str','mandat' => true) ), 'item_types' => array( ITEM_VALUE_TYPE_STR, ITEM_VALUE_TYPE_LOG ) ); $ZBX_TR_EXPR_ALLOWED_FUNCTIONS['last'] = array('args' => null, 'item_types' => array( ITEM_VALUE_TYPE_FLOAT, ITEM_VALUE_TYPE_UINT64, ITEM_VALUE_TYPE_STR, ITEM_VALUE_TYPE_TEXT ) ); $ZBX_TR_EXPR_ALLOWED_FUNCTIONS['max'] = array('args' => array( 0 => array('type' => 'sec_num','mandat' => true) ), 'item_types' => array( ITEM_VALUE_TYPE_FLOAT, ITEM_VALUE_TYPE_UINT64 ) ); $ZBX_TR_EXPR_ALLOWED_FUNCTIONS['min'] = array('args' => array( 0 => array('type' => 'sec_num','mandat' => true) ), 'item_types' => array( ITEM_VALUE_TYPE_FLOAT, ITEM_VALUE_TYPE_UINT64 ) ); $ZBX_TR_EXPR_ALLOWED_FUNCTIONS['nodata']= array('args' => array( 0 => array('type' => 'sec','mandat' => true) ), 'item_types' => null ); $ZBX_TR_EXPR_ALLOWED_FUNCTIONS['now'] = array('args' => null, 'item_types' => null ); $ZBX_TR_EXPR_ALLOWED_FUNCTIONS['prev'] = array('args' => null, 'item_types' => array( ITEM_VALUE_TYPE_FLOAT, ITEM_VALUE_TYPE_UINT64, ITEM_VALUE_TYPE_STR, ITEM_VALUE_TYPE_TEXT ) ); $ZBX_TR_EXPR_ALLOWED_FUNCTIONS['str'] = array('args' => array( 0 => array('type' => 'str','mandat' => true) ), 'item_types' => array( ITEM_VALUE_TYPE_STR, ITEM_VALUE_TYPE_LOG ) ); $ZBX_TR_EXPR_ALLOWED_FUNCTIONS['sum'] = array('args' => array( 0 => array('type' => 'sec_num','mandat' => true) ), 'item_types' => array( ITEM_VALUE_TYPE_FLOAT, ITEM_VALUE_TYPE_UINT64 ) ); $ZBX_TR_EXPR_ALLOWED_FUNCTIONS['logseverity']= array('args' => null, 'item_types' => array( ITEM_VALUE_TYPE_LOG ) ); $ZBX_TR_EXPR_ALLOWED_FUNCTIONS['logsource']= array('args' => array( 0=> array('type' => 'str','mandat' => true) ), 'item_types' => array( ITEM_VALUE_TYPE_LOG ) ); $ZBX_TR_EXPR_ALLOWED_FUNCTIONS['regexp']= array('args' => array( 0 => array('type' => 'str','mandat' => true) ), 'item_types' => array( ITEM_VALUE_TYPE_STR, ITEM_VALUE_TYPE_LOG ) ); $ZBX_TR_EXPR_ALLOWED_FUNCTIONS['time'] = array('args' => null, 'item_types' => null ); } INIT_TRIGGER_EXPRESSION_STRUCTURES(); /* * Function: get_severity_style * * Description: * convert severity constant in to the CSS style name * * Author: * Eugene Grigorjev (eugene.grigorjev@zabbix.com) * * Comments: * */ function get_severity_style($severity) { if($severity == TRIGGER_SEVERITY_INFORMATION) return 'information'; elseif($severity == TRIGGER_SEVERITY_WARNING) return 'warning'; elseif($severity == TRIGGER_SEVERITY_AVERAGE) return 'average'; elseif($severity == TRIGGER_SEVERITY_HIGH) return 'high'; elseif($severity == TRIGGER_SEVERITY_DISASTER) return 'disaster'; return ''; } /* * Function: get_severity_description * * Description: * convert severity constant in to the string representation * * Author: * Eugene Grigorjev (eugene.grigorjev@zabbix.com) * * Comments: * */ function get_severity_description($severity) { if($severity == TRIGGER_SEVERITY_NOT_CLASSIFIED) return S_NOT_CLASSIFIED; else if($severity == TRIGGER_SEVERITY_INFORMATION) return S_INFORMATION; else if($severity == TRIGGER_SEVERITY_WARNING) return S_WARNING; else if($severity == TRIGGER_SEVERITY_AVERAGE) return S_AVERAGE; else if($severity == TRIGGER_SEVERITY_HIGH) return S_HIGH; else if($severity == TRIGGER_SEVERITY_DISASTER) return S_DISASTER; return S_UNKNOWN; } /* * Function: get_trigger_value_style * * Description: * convert trigger value in to the CSS style name * * Author: * Eugene Grigorjev (eugene.grigorjev@zabbix.com) * * Comments: * */ function get_trigger_value_style($value) { $str_val[TRIGGER_VALUE_FALSE] = 'off'; $str_val[TRIGGER_VALUE_TRUE] = 'on'; $str_val[TRIGGER_VALUE_UNKNOWN] = 'unknown'; if(isset($str_val[$value])) return $str_val[$value]; return ''; } /* * Function: trigger_value2str * * Description: * convert trigger value in to the string representation * * Author: * Eugene Grigorjev (eugene.grigorjev@zabbix.com) * * Comments: * */ function trigger_value2str($value) { $str_val[TRIGGER_VALUE_FALSE] = S_FALSE_BIG; $str_val[TRIGGER_VALUE_TRUE] = S_TRUE_BIG; $str_val[TRIGGER_VALUE_UNKNOWN] = S_UNKNOWN_BIG; if(isset($str_val[$value])) return $str_val[$value]; return S_UNKNOWN; } /* * Function: get_trigger_priority * * Description: * retrive trigger's priority * * Author: * Artem Suharev * * Comments: * */ function get_trigger_priority($triggerid){ $sql = 'SELECT count(*) as count, priority '. ' FROM triggers '. ' WHERE triggerid='.$triggerid. ' AND status=0 '. ' AND value='.TRIGGER_VALUE_TRUE. ' GROUP BY priority'; $rows = DBfetch(DBselect($sql)); if($rows && !is_null($rows['count']) && !is_null($rows['priority']) && ($rows['count'] > 0)){ $status = $rows['priority']; } else{ $status = 0; } return $status; } /* * Function: get_realhosts_by_triggerid * * Description: * retrive real host for trigger * * Author: * Eugene Grigorjev (eugene.grigorjev@zabbix.com) * * Comments: * */ function get_realhosts_by_triggerid($triggerid) { $trigger = get_trigger_by_triggerid($triggerid); if($trigger['templateid'] > 0) return get_realhosts_by_triggerid($trigger['templateid']); return get_hosts_by_triggerid($triggerid); } function get_trigger_by_triggerid($triggerid) { $sql="select * from triggers where triggerid=$triggerid"; $result=DBselect($sql); $row=DBfetch($result); if($row) { return $row; } error("No trigger with triggerid=[$triggerid]"); return FALSE; } function &get_hosts_by_triggerid($triggerid) { return DBselect('select distinct h.* from hosts h, functions f, items i'. ' where i.itemid=f.itemid and h.hostid=i.hostid and f.triggerid='.$triggerid); } function &get_functions_by_triggerid($triggerid) { return DBselect('select * from functions where triggerid='.$triggerid); } /* * Function: get_triggers_by_hostid * * Description: * retrive selection of triggers by hostid * * Author: * Eugene Grigorjev (eugene.grigorjev@zabbix.com) * * Comments: * */ function &get_triggers_by_hostid($hostid, $show_mixed = "yes") { $db_triggers = DBselect("select distinct t.* from triggers t, functions f, items i". " where i.hostid=$hostid and f.itemid=i.itemid and f.triggerid=t.triggerid"); if($show_mixed == "yes") return $db_triggers; $triggers = array(); while($db_trigger = DBfetch($db_triggers)) { $db_hosts = get_hosts_by_triggerid($db_trigger["triggerid"]); if(DBfetch($db_hosts)) { array_push($triggers,$db_trigger["triggerid"]); } } $sql = "select distinct * from triggers where triggerid=0"; foreach($triggers as $triggerid) { $sql .= " or triggerid=$triggerid"; } return DBselect($sql); } function &get_triggers_by_templateid($triggerid) { return DBselect('select * from triggers where templateid='.$triggerid); } /* * Function: get_hosts_by_expression * * Description: * retrive selection of hosts by trigger expression * * Author: * Eugene Grigorjev (eugene.grigorjev@zabbix.com) * * Comments: * */ function &get_hosts_by_expression($expression) { global $ZBX_TR_EXPR_ALLOWED_MACROS, $ZBX_TR_EXPR_REPLACE_TO; $expr = $expression; $hosts = array(); /* Replace all {server:key.function(param)} and {MACRO} with '$ZBX_TR_EXPR_REPLACE_TO' */ while(ereg(ZBX_EREG_EXPRESSION_TOKEN_FORMAT, $expr, $arr)) { if ( $arr[ZBX_EXPRESSION_MACRO_ID] && !isset($ZBX_TR_EXPR_ALLOWED_MACROS[$arr[ZBX_EXPRESSION_MACRO_ID]]) ) { $hosts = array('0'); break; } else if( !$arr[ZBX_EXPRESSION_MACRO_ID] ) { $hosts[] = zbx_dbstr($arr[ZBX_EXPRESSION_SIMPLE_EXPRESSION_ID + ZBX_SIMPLE_EXPRESSION_HOST_ID]); } $expr = $arr[ZBX_EXPRESSION_LEFT_ID].$ZBX_TR_EXPR_REPLACE_TO.$arr[ZBX_EXPRESSION_RIGHT_ID]; } if(count($hosts) == 0) $hosts = array('0'); return DBselect('select distinct * from hosts where '.DBin_node('hostid', get_current_nodeid(false)). ' and host in ('.implode(',',$hosts).')'); } /* * Function: zbx_unquote_param * * Description: * unquote string and unescape cahrs * * Author: * Eugene Grigorjev (eugene.grigorjev@zabbix.com) * * Comments: * Double quotes used only. * Unquote string only if value directly in quotes. * Unescape only '\\' and '\"' combination * */ function zbx_unquote_param($value) { $value = trim($value); if ( !empty($value) && '"' == $value[0] ) { /* open quotes and unescape chars */ $value = substr($value, 1, strlen($value)-2); $new_val = ''; for ( $i=0, $max=strlen($value); $i < $max; $i++) { if ( $i+1 < $max && $value[$i] == '\\' && ($value[$i+1] == '\\' || $value[$i+1] == '"') ) $new_val .= $value[++$i]; else $new_val .= $value[$i]; } $value = $new_val; } return $value; } /* * Function: zbx_get_params * * Description: * parse list of quoted parameters * * Author: * Eugene Grigorjev (eugene.grigorjev@zabbix.com) * * Comments: * Double quotes used only. * */ function zbx_get_params($string) { $params = array(); $quoted = false; for( $param_s = $i = 0, $len = strlen($string); $i < $len; $i++) { switch ( $string[$i] ) { case '"': $quoted = !$quoted; break; case ',': if ( !$quoted ) { $params[] = zbx_unquote_param(substr($string, $param_s, $i - $param_s)); $param_s = $i+1; } break; case '\\': if ( $quoted && $i+1 < $len && ($string[$i+1] == '\\' || $string[$i+1] == '"')) $i++; break; } } if( $quoted ) { error('Incorrect usage of quotes. ['.$string.']'); return null; } if( $i > $param_s ) { $params[] = zbx_unquote_param(substr($string, $param_s, $i - $param_s)); } return $params; } /* * Function: validate_expression * * Description: * check trigger expression syntax and validate values * * Author: * Eugene Grigorjev (eugene.grigorjev@zabbix.com) * * Comments: * */ function validate_expression($expression) { global $ZBX_TR_EXPR_ALLOWED_MACROS, $ZBX_TR_EXPR_REPLACE_TO, $ZBX_TR_EXPR_ALLOWED_FUNCTIONS; if( empty($expression) ) { error('Expression can\'t be empty'); } $expr = $expression; $h_status = array(); /* Replace all {server:key.function(param)} and {MACRO} with '$ZBX_TR_EXPR_REPLACE_TO' */ while(ereg(ZBX_EREG_EXPRESSION_TOKEN_FORMAT, $expr, $arr)) { if ( $arr[ZBX_EXPRESSION_MACRO_ID] && !isset($ZBX_TR_EXPR_ALLOWED_MACROS[$arr[ZBX_EXPRESSION_MACRO_ID]]) ) { error('Unknown macro ['.$arr[ZBX_EXPRESSION_MACRO_ID].']'); return false; } else if( !$arr[ZBX_EXPRESSION_MACRO_ID] ) { $host = &$arr[ZBX_EXPRESSION_SIMPLE_EXPRESSION_ID + ZBX_SIMPLE_EXPRESSION_HOST_ID]; $key = &$arr[ZBX_EXPRESSION_SIMPLE_EXPRESSION_ID + ZBX_SIMPLE_EXPRESSION_KEY_ID]; $function = &$arr[ZBX_EXPRESSION_SIMPLE_EXPRESSION_ID + ZBX_SIMPLE_EXPRESSION_FUNCTION_NAME_ID]; $parameter = &$arr[ZBX_EXPRESSION_SIMPLE_EXPRESSION_ID + ZBX_SIMPLE_EXPRESSION_FUNCTION_PARAM_ID]; /* Check host */ $row=DBfetch(DBselect('select count(*) as cnt,min(status) as status,min(hostid) as hostid from hosts h where h.host='.zbx_dbstr($host). ' and '.DBin_node('h.hostid', get_current_nodeid(false)) )); if($row['cnt']==0) { error('No such host ('.$host.')'); return false; } elseif($row['cnt']!=1) { error('Too many hosts ('.$host.')'); return false; } $h_status[$row['status']][$row['hostid']] = $row['cnt']; /* Check key */ if ( !($item = DBfetch(DBselect('select i.itemid,i.value_type from hosts h,items i where h.host='.zbx_dbstr($host). ' and i.key_='.zbx_dbstr($key).' and h.hostid=i.hostid '. ' and '.DBin_node('h.hostid', get_current_nodeid(false)) ))) ) { error('No such monitored parameter ('.$key.') for host ('.$host.')'); return false; } /* Check function */ if( !isset($ZBX_TR_EXPR_ALLOWED_FUNCTIONS[$function]) ) { error('Unknown function ['.$function.']'); return false; } $fnc_valid = &$ZBX_TR_EXPR_ALLOWED_FUNCTIONS[$function]; if ( is_array($fnc_valid['item_types']) && !in_array($item['value_type'], $fnc_valid['item_types'])) { $allowed_types = array(); foreach($fnc_valid['item_types'] as $type) $allowed_types[] = item_value_type2str($type); info('Function ('.$function.') available only for items with value types ['.implode(',',$allowed_types).']'); error('Incorrect value type ['.item_value_type2str($item['value_type']).'] for function ('.$function.') of key ('.$host.':'.$key.')'); return false; } if( !is_null($fnc_valid['args']) ) { $parameter = zbx_get_params($parameter); if( !is_array($fnc_valid['args']) ) $fnc_valid['args'] = array($fnc_valid['args']); foreach($fnc_valid['args'] as $pid => $params) { if(!isset($parameter[$pid])) { if( !isset($params['mandat']) ) { continue; } else { error('Missed mandatory parameter for function ('.$function.')'); return false; } } if( 'sec' == $params['type'] && (validate_float($parameter[$pid])!=0) ) { error('['.$parameter[$pid].'] is not a float for function ('.$function.')'); return false; } if( 'sec_num' == $params['type'] && (validate_ticks($parameter[$pid])!=0) ) { error('['.$parameter[$pid].'] is not a float or counter for function ('.$function.')'); return false; } } } } $expr = $arr[ZBX_EXPRESSION_LEFT_ID].$ZBX_TR_EXPR_REPLACE_TO.$arr[ZBX_EXPRESSION_RIGHT_ID]; } if ( isset($h_status[HOST_STATUS_TEMPLATE]) && ( count($h_status) > 1 || count($h_status[HOST_STATUS_TEMPLATE]) > 1 )) { error("Incorrect trigger expression. You can't use template hosts". " in mixed expressions."); return false; } /* Replace all calculations and numbers with '$ZBX_TR_EXPR_REPLACE_TO' */ $expt_number = '('.$ZBX_TR_EXPR_REPLACE_TO.'|'.ZBX_EREG_NUMBER.')'; $expt_term = '((\('.$expt_number.'\))|('.$expt_number.'))'; $expr_format = '(('.$expt_term.ZBX_EREG_SPACES.ZBX_EREG_SIGN.ZBX_EREG_SPACES.$expt_term.')|(\('.$expt_term.'\)))'; $expr_full_format = '((\('.$expr_format.'\))|('.$expr_format.'))'; while($res = ereg($expr_full_format.'([[:print:]]*)$', $expr, $arr)) { $expr = substr($expr, 0, strpos($expr, $arr[1])).$ZBX_TR_EXPR_REPLACE_TO.$arr[58]; } if ( $ZBX_TR_EXPR_REPLACE_TO != $expr ) { error('Incorrect trigger expression. ['.str_replace($ZBX_TR_EXPR_REPLACE_TO, ' ... ', $expr).']'); return false; } return true; } function add_trigger( $expression, $description, $type, $priority, $status, $comments, $url, $deps=array(), $templateid=0) { if( !validate_expression($expression) ) return false; $triggerid=get_dbid("triggers","triggerid"); $result=DBexecute("insert into triggers". " (triggerid,description,type,priority,status,comments,url,value,error,templateid)". " values ($triggerid,".zbx_dbstr($description).",$type,$priority,$status,".zbx_dbstr($comments).",". "".zbx_dbstr($url).",2,'Trigger just added. No status update so far.',$templateid)"); if(!$result) { return $result; } add_event($triggerid,TRIGGER_VALUE_UNKNOWN); if( null == ($expression = implode_exp($expression,$triggerid)) ) { $result = false; } if($result) { DBexecute("update triggers set expression=".zbx_dbstr($expression)." where triggerid=$triggerid"); reset_items_nextcheck($triggerid); foreach($deps as $val) { $result = add_trigger_dependency($triggerid, $val); } } $trig_hosts = get_hosts_by_triggerid($triggerid); $trig_host = DBfetch($trig_hosts); if($result) { $msg = "Added trigger '".$description."'"; if($trig_host) { $msg .= " to host '".$trig_host["host"]."'"; } info($msg); } if($trig_host) {// create trigger for childs $child_hosts = get_hosts_by_templateid($trig_host["hostid"]); while($child_host = DBfetch($child_hosts)) { if( !($result = copy_trigger_to_host($triggerid, $child_host["hostid"]))) break; } } if(!$result){ if($templateid == 0) { // delete main trigger (and recursively childs) delete_trigger($triggerid); } return $result; } return $triggerid; } /****************************************************************************** * * * Comments: !!! Don't forget sync code with C !!! * * * ******************************************************************************/ function get_trigger_dependences_by_triggerid($triggerid) { $result = array(); $db_deps = DBselect("select * from trigger_depends where triggerid_down=".$triggerid); while($db_dep = DBfetch($db_deps)) $result[] = $db_dep['triggerid_up']; return $result; } /****************************************************************************** * * * Comments: !!! Don't forget sync code with C !!! * * * ******************************************************************************/ function replace_template_dependences($deps, $hostid) { foreach($deps as $id => $val) { if($db_new_dep = DBfetch(DBselect('select t.triggerid from triggers t,functions f,items i '. ' where t.templateid='.$val.' and f.triggerid=t.triggerid '. ' and f.itemid=i.itemid and i.hostid='.$hostid))) $deps[$id] = $db_new_dep['triggerid']; } return $deps; } /****************************************************************************** * * * Comments: !!! Don't forget sync code with C !!! * * * ******************************************************************************/ function copy_trigger_to_host($triggerid, $hostid, $copy_mode = false) { $trigger = get_trigger_by_triggerid($triggerid); $deps = replace_template_dependences( get_trigger_dependences_by_triggerid($triggerid), $hostid); $host_triggers = get_triggers_by_hostid($hostid, "no"); while($host_trigger = DBfetch($host_triggers)) { if($host_trigger["templateid"] != 0) continue; if(cmp_triggers($triggerid, $host_trigger["triggerid"])) continue; // link not linked trigger with same expression return update_trigger( $host_trigger["triggerid"], NULL, // expression $trigger["description"], $trigger["priority"], NULL, // status $trigger["comments"], $trigger["url"], $deps, $copy_mode ? 0 : $triggerid); } $newtriggerid=get_dbid("triggers","triggerid"); $result = DBexecute("insert into triggers". " (triggerid,description,type,priority,status,comments,url,value,expression,templateid)". " values ($newtriggerid,".zbx_dbstr($trigger['description']).','.$trigger['type'].','.$trigger['priority'].','. $trigger['status'].','.zbx_dbstr($trigger['comments']).','. zbx_dbstr($trigger["url"]).",2,'{???:???}',". ($copy_mode ? 0 : $triggerid).")"); if(!$result) return $result; $host = get_host_by_hostid($hostid); $newexpression = $trigger["expression"]; // Loop: functions $functions = get_functions_by_triggerid($triggerid); while($function = DBfetch($functions)) { $item = get_item_by_itemid($function["itemid"]); $host_items = DBselect("select * from items". " where key_=".zbx_dbstr($item["key_"]). " and hostid=".$host["hostid"]); $host_item = DBfetch($host_items); if(!$host_item) { error("Missing key '".$item["key_"]."' for host '".$host["host"]."'"); return FALSE; } $newfunctionid=get_dbid("functions","functionid"); $result = DBexecute("insert into functions (functionid,itemid,triggerid,function,parameter)". " values ($newfunctionid,".$host_item["itemid"].",$newtriggerid,". zbx_dbstr($function["function"]).",".zbx_dbstr($function["parameter"]).")"); $newexpression = str_replace( "{".$function["functionid"]."}", "{".$newfunctionid."}", $newexpression); } DBexecute("update triggers set expression=".zbx_dbstr($newexpression). " where triggerid=$newtriggerid"); // copy dependences delete_dependencies_by_triggerid($newtriggerid); foreach($deps as $dep_id) { add_trigger_dependency($newtriggerid, $dep_id); } info("Added trigger '".$trigger["description"]."' to host '".$host["host"]."'"); // Copy triggers to the child hosts $child_hosts = get_hosts_by_templateid($hostid); while($child_host = DBfetch($child_hosts)) {// recursion $result = copy_trigger_to_host($newtriggerid, $child_host["hostid"]); if(!$result){ return result; } } return $newtriggerid; } /****************************************************************************** * * * Purpose: Translate {10}>10 to something like localhost:procload.last(0)>10 * * * * Comments: !!! Don't forget sync code with C !!! * * * ******************************************************************************/ function explode_exp ($expression, $html,$template=false) { # echo "EXPRESSION:",$expression,"
"; $functionid=''; $exp=''; $state=''; for($i=0,$max=strlen($expression); $i<$max; $i++) { if($expression[$i] == '{') { $functionid=''; $state='FUNCTIONID'; continue; } if($expression[$i] == '}') { $state=''; if($functionid=="TRIGGER.VALUE") { $exp .= "{".$functionid."}"; } else if(is_numeric($functionid) && $function_data = DBfetch(DBselect('select h.host,i.key_,f.function,f.parameter,i.itemid,i.value_type'. ' from items i,functions f,hosts h'. ' where f.functionid='.$functionid.' and i.itemid=f.itemid and h.hostid=i.hostid'))) { if($template) $function_data["host"] = '{HOSTNAME}'; if($html == 0) { $exp .= "{".$function_data["host"].":".$function_data["key_"].".". $function_data["function"]."(".$function_data["parameter"].")}"; } else { $link = new CLink($function_data["host"].":".$function_data["key_"], 'history.php?action='.( $function_data["value_type"] ==0 ? 'showvalues' : 'showgraph'). '&itemid='.$function_data['itemid']); $exp .= '{'.$link->ToString().'.'.bold($function_data["function"].'(').$function_data["parameter"].bold(')').'}'; } } else { if($html == 1) $exp .= ""; $exp .= "*ERROR*"; if($html == 1) $exp .= ""; } continue; } if($state == "FUNCTIONID") { $functionid=$functionid.$expression[$i]; continue; } $exp=$exp.$expression[$i]; } # echo "EXP:",$exp,"
"; return $exp; } /* * Function: implode_exp * * Description: * Translate localhost:procload.last(0)>10 to {12}>10 * And create database representation. * * Author: * Eugene Grigorjev (eugene.grigorjev@zabbix.com) * * Comments: !!! Don't forget sync code with C !!! * */ function implode_exp ($expression, $triggerid) { global $ZBX_TR_EXPR_ALLOWED_MACROS, $ZBX_TR_EXPR_REPLACE_TO; $expr = $expression; $short_exp = $expression; /* Replace all {server:key.function(param)} and {MACRO} with '$ZBX_TR_EXPR_REPLACE_TO' */ /* build short expression {12}>10 */ while(ereg(ZBX_EREG_EXPRESSION_TOKEN_FORMAT, $expr, $arr)) { if ( $arr[ZBX_EXPRESSION_MACRO_ID] && !isset($ZBX_TR_EXPR_ALLOWED_MACROS[$arr[ZBX_EXPRESSION_MACRO_ID]]) ) { error('[ie] Unknown macro ['.$arr[ZBX_EXPRESSION_MACRO_ID].']'); return false; } else if( !$arr[ZBX_EXPRESSION_MACRO_ID] ) { $s_expr = &$arr[ZBX_EXPRESSION_SIMPLE_EXPRESSION_ID]; $host = &$arr[ZBX_EXPRESSION_SIMPLE_EXPRESSION_ID + ZBX_SIMPLE_EXPRESSION_HOST_ID]; $key = &$arr[ZBX_EXPRESSION_SIMPLE_EXPRESSION_ID + ZBX_SIMPLE_EXPRESSION_KEY_ID]; $function = &$arr[ZBX_EXPRESSION_SIMPLE_EXPRESSION_ID + ZBX_SIMPLE_EXPRESSION_FUNCTION_NAME_ID]; $parameter = &$arr[ZBX_EXPRESSION_SIMPLE_EXPRESSION_ID + ZBX_SIMPLE_EXPRESSION_FUNCTION_PARAM_ID]; $item = DBfetch(DBselect('select i.itemid from items i,hosts h'. ' where i.key_='.zbx_dbstr($key). ' and h.host='.zbx_dbstr($host). ' and h.hostid=i.hostid')); $item = $item["itemid"]; $functionid = get_dbid("functions","functionid"); if ( !DBexecute('insert into functions (functionid,itemid,triggerid,function,parameter)'. ' values ('.$functionid.','.$item.','.$triggerid.','.zbx_dbstr($function).','. zbx_dbstr($parameter).')')) { return null; } $short_exp = str_replace($s_expr,'{'.$functionid.'}',$short_exp); $expr = str_replace($s_expr,$ZBX_TR_EXPR_REPLACE_TO,$expr); continue; } $expr = $arr[ZBX_EXPRESSION_LEFT_ID].$ZBX_TR_EXPR_REPLACE_TO.$arr[ZBX_EXPRESSION_RIGHT_ID]; } return $short_exp; } function update_trigger_comments($triggerid,$comments) { return DBexecute("update triggers set comments=".zbx_dbstr($comments). " where triggerid=$triggerid"); } # Update Trigger status function update_trigger_status($triggerid,$status) { // first update status for child triggers $db_chd_triggers = get_triggers_by_templateid($triggerid); while($db_chd_trigger = DBfetch($db_chd_triggers)) { update_trigger_status($db_chd_trigger["triggerid"],$status); } add_event($triggerid,TRIGGER_VALUE_UNKNOWN); return DBexecute("update triggers set status=$status where triggerid=$triggerid"); } /* * Function: extract_numbers * * Description: * Extract from string numbers with prefixes (A-Z) * * Author: * Eugene Grigorjev (eugene.grigorjev@zabbix.com) * * Comments: !!! Don't forget sync code with C !!! * */ function extract_numbers($str) { $numbers = array(); while ( ereg(ZBX_EREG_NUMBER.'([[:print:]]*)', $str, $arr) ) { $numbers[] = $arr[1]; $str = $arr[2]; } return $numbers; } /* * Function: expand_trigger_description_constants * * Description: * substitute simple macros in data string with real values * * Author: * Eugene Grigorjev (eugene.grigorjev@zabbix.com) * * Comments: !!! Don't forget sync code with C !!! * replcae $1-9 macros * */ function expand_trigger_description_constants($description, $row) { if($row && isset($row['expression'])) { $numbers = extract_numbers(ereg_replace('(\{[0-9]+\})', 'function', $row['expression'])); $description = $row["description"]; for ( $i = 0; $i < 9; $i++ ) { $description = str_replace( '$'.($i+1), isset($numbers[$i]) ? $numbers[$i] : '', $description ); } } return $description; } /* * Function: expand_trigger_description_by_data * * Description: * substitute simple macros in data string with real values * * Author: * Eugene Grigorjev (eugene.grigorjev@zabbix.com) * * Comments: !!! Don't forget sync code with C !!! * */ function expand_trigger_description_by_data($row, $flag = ZBX_FLAG_TRIGGER) { if($row) { $description = expand_trigger_description_constants($row['description'], $row); if(is_null($row["host"])) $row["host"] = "{HOSTNAME}"; $description = str_replace("{HOSTNAME}", $row["host"],$description); if(strstr($description,"{ITEM.LASTVALUE}")) { $row2=DBfetch(DBselect('SELECT i.lastvalue, i.value_type, i.itemid '. ' FROM items i, triggers t, functions f '. ' WHERE i.itemid=f.itemid '. ' AND f.triggerid=t.triggerid '. ' AND t.triggerid='.$row['triggerid'])); if($row2['value_type']!=ITEM_VALUE_TYPE_LOG) { $description = str_replace('{ITEM.LASTVALUE}', $row2['lastvalue'],$description); } else { $row3=DBfetch(DBselect("select max(clock) as max from history_log where itemid=".$row2["itemid"])); if($row3 && !is_null($row3["max"])) { $row4=DBfetch(DBselect("select value from history_log where itemid=".$row2["itemid"]." and clock=".$row3["max"])); $description = str_replace("{ITEM.LASTVALUE}", $row4["value"],$description); } } } if(strstr($description,'{ITEM.VALUE}')) { $value=($flag==ZBX_FLAG_TRIGGER)? trigger_get_func_value($row["expression"],ZBX_FLAG_TRIGGER,1,1): trigger_get_func_value($row["expression"],ZBX_FLAG_EVENT,1,$row['clock']); $description = str_replace("{ITEM.VALUE}", $value, $description); } if(strstr($description,'{ITEM.VALUE1}')) { $value=($flag==ZBX_FLAG_TRIGGER)? trigger_get_func_value($row["expression"],ZBX_FLAG_TRIGGER,1,1): trigger_get_func_value($row["expression"],ZBX_FLAG_EVENT,1,$row['clock']); $description = str_replace("{ITEM.VALUE1}", $value, $description); } if(strstr($description,'{ITEM.VALUE2}')) { $value=($flag==ZBX_FLAG_TRIGGER)? trigger_get_func_value($row["expression"],ZBX_FLAG_TRIGGER,2,1): trigger_get_func_value($row["expression"],ZBX_FLAG_EVENT,2,$row['clock']); $description = str_replace("{ITEM.VALUE2}", $value, $description); } if(strstr($description,'{ITEM.VALUE3}')) { $value=($flag==ZBX_FLAG_TRIGGER)? trigger_get_func_value($row["expression"],ZBX_FLAG_TRIGGER,3,1): trigger_get_func_value($row["expression"],ZBX_FLAG_EVENT,3,$row['clock']); $description = str_replace("{ITEM.VALUE3}", $value, $description); } if(strstr($description,'{ITEM.VALUE4}')) { $value=($flag==ZBX_FLAG_TRIGGER)? trigger_get_func_value($row["expression"],ZBX_FLAG_TRIGGER,4,1): trigger_get_func_value($row["expression"],ZBX_FLAG_EVENT,4,$row['clock']); $description = str_replace("{ITEM.VALUE4}", $value, $description); } if(strstr($description,'{ITEM.VALUE5}')) { $value=($flag==ZBX_FLAG_TRIGGER)? trigger_get_func_value($row["expression"],ZBX_FLAG_TRIGGER,5,1): trigger_get_func_value($row["expression"],ZBX_FLAG_EVENT,5,$row['clock']); $description = str_replace("{ITEM.VALUE5}", $value, $description); } if(strstr($description,'{ITEM.VALUE6}')) { $value=($flag==ZBX_FLAG_TRIGGER)? trigger_get_func_value($row["expression"],ZBX_FLAG_TRIGGER,6,1): trigger_get_func_value($row["expression"],ZBX_FLAG_EVENT,6,$row['clock']); $description = str_replace("{ITEM.VALUE6}", $value, $description); } if(strstr($description,'{ITEM.VALUE7}')) { $value=($flag==ZBX_FLAG_TRIGGER)? trigger_get_func_value($row["expression"],ZBX_FLAG_TRIGGER,7,1): trigger_get_func_value($row["expression"],ZBX_FLAG_EVENT,7,$row['clock']); $description = str_replace("{ITEM.VALUE7}", $value, $description); } if(strstr($description,'{ITEM.VALUE8}')) { $value=($flag==ZBX_FLAG_TRIGGER)? trigger_get_func_value($row["expression"],ZBX_FLAG_TRIGGER,8,1): trigger_get_func_value($row["expression"],ZBX_FLAG_EVENT,8,$row['clock']); $description = str_replace("{ITEM.VALUE8}", $value, $description); } if(strstr($description,'{ITEM.VALUE9}')) { $value=($flag==ZBX_FLAG_TRIGGER)? trigger_get_func_value($row["expression"],ZBX_FLAG_TRIGGER,9,1): trigger_get_func_value($row["expression"],ZBX_FLAG_EVENT,9,$row['clock']); $description = str_replace("{ITEM.VALUE9}", $value, $description); } } else { $description = "*ERROR*"; } return $description; } function expand_trigger_description_simple($triggerid) { return expand_trigger_description_by_data( DBfetch( DBselect("select distinct t.description,h.host,t.expression,t.triggerid ". " from triggers t left join functions f on t.triggerid=f.triggerid ". " left join items i on f.itemid=i.itemid ". " left join hosts h on i.hostid=h.hostid ". " where t.triggerid=$triggerid") ) ); } function expand_trigger_description($triggerid) { $description=expand_trigger_description_simple($triggerid); $description=stripslashes(htmlspecialchars($description)); return $description; } function update_trigger_value_to_unknown_by_hostid($hostid) { $result = DBselect("select distinct t.triggerid". " from hosts h,items i,triggers t,functions f". " where f.triggerid=t.triggerid and f.itemid=i.itemid". " and h.hostid=i.hostid and h.hostid=$hostid"); $now = time(); while($row=DBfetch($result)) { if(!add_event($row["triggerid"],TRIGGER_VALUE_UNKNOWN,$now)) continue; DBexecute('update triggers set value='.TRIGGER_VALUE_UNKNOWN.' where triggerid='.$row["triggerid"]); } } /****************************************************************************** * * * Comments: !!! Don't forget sync code with C !!! * * * ******************************************************************************/ function add_event($triggerid, $value, $time=NULL) { if(is_null($time)) $time = time(); $result = DBselect('select value,clock from events where objectid='.$triggerid.' and object='.EVENT_OBJECT_TRIGGER. ' order by clock desc',1); $last_value = DBfetch($result); if($last_value) { if($value == $last_value['value']) return false; } $eventid = get_dbid("events","eventid"); $result = DBexecute('insert into events(eventid,source,object,objectid,clock,value) '. ' values('.$eventid.','.EVENT_SOURCE_TRIGGERS.','.EVENT_OBJECT_TRIGGER.','.$triggerid.','.$time.','.$value.')'); if($value == TRIGGER_VALUE_FALSE || $value == TRIGGER_VALUE_TRUE) { DBexesute('update alerts set retries=3,error=\'Trigger changed its status. WIll not send repeats.\''. ' where triggerid='.$triggerid.' and repeats>0 and status='.ALERT_STATUS_NOT_SENT); } return true; } function add_trigger_dependency($triggerid,$depid) { $result=insert_dependency($triggerid,$depid);; if(!$result) { return $result; } //add_additional_dependencies($triggerid,$depid); return $result; } /****************************************************************************** * * * Purpose: Delete Trigger definition * * * * Comments: !!! Don't forget sync code with C !!! * * * ******************************************************************************/ function delete_trigger($triggerid) { // first delete child triggers $db_triggers= get_triggers_by_templateid($triggerid); while($db_trigger = DBfetch($db_triggers)) {// recursion $result = delete_trigger($db_trigger["triggerid"]); if(!$result) return $result; } // get hosts before functions deletion !!! $trig_hosts = get_hosts_by_triggerid($triggerid); $result = delete_dependencies_by_triggerid($triggerid); if(!$result) return $result; DBexecute("delete from trigger_depends where triggerid_up=$triggerid"); $result=delete_function_by_triggerid($triggerid); if(!$result) return $result; $result=delete_events_by_triggerid($triggerid); if(!$result) return $result; $result=delete_services_by_triggerid($triggerid); if(!$result) return $result; $result=delete_sysmaps_elements_with_triggerid($triggerid); if(!$result) return $result; DBexecute("delete from alerts where triggerid=$triggerid"); DBexecute("update sysmaps_links set triggerid=NULL where triggerid=$triggerid"); // disable actions $db_actions = DBselect("select distinct actionid from conditions ". " where conditiontype=".CONDITION_TYPE_TRIGGER." and value=".$triggerid); while($db_action = DBfetch($db_actions)) { DBexecute("update actions set status=".ACTION_STATUS_DISABLED. " where actionid=".$db_action["actionid"]); } // delete action conditions DBexecute('delete from conditions where conditiontype='.CONDITION_TYPE_TRIGGER.' and value='.$triggerid); $trigger = get_trigger_by_triggerid($triggerid); $result = DBexecute("delete from triggers where triggerid=$triggerid"); if($result) { $msg = "Trigger '".$trigger["description"]."' deleted"; $trig_host = DBfetch($trig_hosts); if($trig_host) { $msg .= " from host '".$trig_host["host"]."'"; } info($msg); } return $result; } # Update Trigger definition /****************************************************************************** * * * Comments: !!! Don't forget sync code with C !!! * * * ******************************************************************************/ function update_trigger($triggerid,$expression=NULL,$description=NULL,$type=NULL,$priority=NULL,$status=NULL, $comments=NULL,$url=NULL,$deps=array(),$templateid=0) { $trigger = get_trigger_by_triggerid($triggerid); $trig_hosts = get_hosts_by_triggerid($triggerid); $trig_host = DBfetch($trig_hosts); $event_to_unknown = false; if(is_null($expression)){ /* Restore expression */ $expression = explode_exp($trigger["expression"],0); } else if($expression != explode_exp($trigger["expression"],0)){ $event_to_unknown = true; } if ( !validate_expression($expression) ) return false; $exp_hosts = get_hosts_by_expression($expression); if( $exp_hosts ) { $chd_hosts = get_hosts_by_templateid($trig_host["hostid"]); if(DBfetch($chd_hosts)) { $exp_host = DBfetch($exp_hosts); $db_chd_triggers = get_triggers_by_templateid($triggerid); while($db_chd_trigger = DBfetch($db_chd_triggers)) { $chd_trig_hosts = get_hosts_by_triggerid($db_chd_trigger["triggerid"]); $chd_trig_host = DBfetch($chd_trig_hosts); $newexpression = str_replace( "{".$exp_host["host"].":", "{".$chd_trig_host["host"].":", $expression); // recursion update_trigger( $db_chd_trigger["triggerid"], $newexpression, $description, $type, $priority, NULL, // status $comments, $url, replace_template_dependences($deps, $chd_trig_host['hostid']), $triggerid); } } } $result=delete_function_by_triggerid($triggerid); if(!$result) { return $result; } $expression = implode_exp($expression,$triggerid); /* errors can be ignored cose function must return NULL */ if($event_to_unknown) add_event($triggerid,TRIGGER_VALUE_UNKNOWN); reset_items_nextcheck($triggerid); $sql="update triggers set"; if(!is_null($expression)) $sql .= " expression=".zbx_dbstr($expression).","; if(!is_null($description)) $sql .= " description=".zbx_dbstr($description).","; if(!is_null($type)) $sql .= " type=$type,"; if(!is_null($priority)) $sql .= " priority=$priority,"; if(!is_null($status)) $sql .= " status=$status,"; if(!is_null($comments)) $sql .= " comments=".zbx_dbstr($comments).","; if(!is_null($url)) $sql .= " url=".zbx_dbstr($url).","; if(!is_null($templateid)) $sql .= " templateid=$templateid,"; $sql .= " value=2 where triggerid=$triggerid"; $result = DBexecute($sql); delete_dependencies_by_triggerid($triggerid); foreach($deps as $val) { $result=add_trigger_dependency($triggerid, $val); } if($result) { $trig_hosts = get_hosts_by_triggerid($triggerid); $msg = "Trigger '".$trigger["description"]."' updated"; $trig_host = DBfetch($trig_hosts); if($trig_host) { $msg .= " for host '".$trig_host["host"]."'"; } info($msg); } return $result; } function check_right_on_trigger_by_triggerid($permission,$triggerid,$accessible_hosts=null) { $trigger_data = DBfetch(DBselect('select expression from triggers where triggerid='.$triggerid)); if(!$trigger_data) return false; return check_right_on_trigger_by_expression($permission, explode_exp($trigger_data['expression'], 0), $accessible_hosts); } function check_right_on_trigger_by_expression($permission,$expression,$accessible_hosts=null) { if(is_null($accessible_hosts)) { global $USER_DETAILS; $accessible_hosts = get_accessible_hosts_by_user($USER_DETAILS, $permission, null, PERM_RES_IDS_ARRAY); } if(!is_array($accessible_hosts)) $accessible_hosts = explode(',', $accessible_hosts); $db_hosts = get_hosts_by_expression($expression); while($host_data = DBfetch($db_hosts)) { if(!in_array($host_data['hostid'], $accessible_hosts)) return false; } return true; } /****************************************************************************** * * * Comments: !!! Don't forget sync code with C !!! * * * ******************************************************************************/ function delete_dependencies_by_triggerid($triggerid) { $db_deps = DBselect('select triggerid_up, triggerid_down from trigger_depends'. ' where triggerid_down='.$triggerid); while($db_dep = DBfetch($db_deps)) { DBexecute('update triggers set dep_level=dep_level-1 where triggerid='.$db_dep['triggerid_up']); DBexecute('delete from trigger_depends'. ' where triggerid_up='.$db_dep['triggerid_up']. ' and triggerid_down='.$db_dep['triggerid_down']); } return true; } /****************************************************************************** * * * Comments: !!! Don't forget sync code with C !!! * * * ******************************************************************************/ function insert_dependency($triggerid_down,$triggerid_up) { $triggerdepid = get_dbid("trigger_depends","triggerdepid"); $result=DBexecute("insert into trigger_depends (triggerdepid,triggerid_down,triggerid_up)". " values ($triggerdepid,$triggerid_down,$triggerid_up)"); if(!$result) { return $result; } return DBexecute("update triggers set dep_level=dep_level+1 where triggerid=$triggerid_up"); } /* INCORRECT LOGIC: If 1 depends on 2, and 2 depends on 3, then add dependency 1->3 function add_additional_dependencies($triggerid_down,$triggerid_up) { $result=DBselect("select triggerid_down from trigger_depends". " where triggerid_up=$triggerid_down"); while($row=DBfetch($result)) { insert_dependency($row["triggerid_down"],$triggerid_up); add_additional_dependencies($row["triggerid_down"],$triggerid_up); } $result=DBselect("select triggerid_up from trigger_depends where triggerid_down=$triggerid_up"); while($row=DBfetch($result)) { insert_dependency($triggerid_down,$row["triggerid_up"]); add_additional_dependencies($triggerid_down,$row["triggerid_up"]); } } */ function delete_function_by_triggerid($triggerid) { return DBexecute("delete from functions where triggerid=$triggerid"); } function delete_events_by_triggerid($triggerid) { return DBexecute('delete from events where objectid='.$triggerid.' and object='.EVENT_OBJECT_TRIGGER); } /****************************************************************************** * * * Comments: !!! Don't forget sync code with C !!! * * * ******************************************************************************/ function delete_triggers_by_itemid($itemid) { $result=DBselect("select triggerid from functions where itemid=$itemid"); while($row=DBfetch($result)) { if(!delete_trigger($row["triggerid"])) { return FALSE; } } return TRUE; } /****************************************************************************** * * * Purpose: Delete Service definitions by triggerid * * * * Comments: !!! Don't forget sync code with C !!! * * * ******************************************************************************/ function delete_services_by_triggerid($triggerid) { $result = DBselect("select serviceid from services where triggerid=$triggerid"); while($row = DBfetch($result)) { delete_service($row["serviceid"]); } return TRUE; } /* * Function: cmp_triggers * * Description: * compate triggers by expression * * Author: * Eugene Grigorjev (eugene.grigorjev@zabbix.com) * * Comments: !!! Don't forget sync code with C !!! * */ function cmp_triggers($triggerid1, $triggerid2) // compare EXPRESSION !!! { $trig1 = get_trigger_by_triggerid($triggerid1); $trig2 = get_trigger_by_triggerid($triggerid2); $trig_fnc1 = get_functions_by_triggerid($triggerid1); $expr1 = $trig1["expression"]; while($fnc1 = DBfetch($trig_fnc1)) { $trig_fnc2 = get_functions_by_triggerid($triggerid2); while($fnc2 = DBfetch($trig_fnc2)){ if(strcmp($fnc1["function"],$fnc2["function"])) continue; if($fnc1["parameter"] != $fnc2["parameter"]) continue; $item1 = get_item_by_itemid($fnc1["itemid"]); $item2 = get_item_by_itemid($fnc2["itemid"]); if(strcmp($item1["key_"],$item2["key_"])) continue; $expr1 = str_replace( "{".$fnc1["functionid"]."}", "{".$fnc2["functionid"]."}", $expr1); break; } } return strcmp($expr1,$trig2["expression"]); } /* * Function: delete_template_triggers * * Description: * Delete template triggers * * Author: * Eugene Grigorjev (eugene.grigorjev@zabbix.com) * * Comments: !!! Don't forget sync code with C !!! * */ function delete_template_triggers($hostid, $templateid = null, $unlink_mode = false) { $triggers = get_triggers_by_hostid($hostid); while($trigger = DBfetch($triggers)) { if($trigger["templateid"]==0) continue; if($templateid != null) { if( !is_array($templateid)) $templateid = array($templateid); $db_tmp_hosts = get_hosts_by_triggerid($trigger["templateid"]); $tmp_host = DBfetch($db_tmp_hosts); if( !in_array($tmp_host["hostid"], $templateid) ) continue; } if($unlink_mode) { if(DBexecute("update triggers set templateid=0 where triggerid=".$trigger["triggerid"])) { info("Trigger '".$trigger["description"]."' unlinked"); } } else { delete_trigger($trigger["triggerid"]); } } return TRUE; } /* * Function: copy_template_triggers * * Description: * Copy triggers from template * * Author: * Eugene Grigorjev (eugene.grigorjev@zabbix.com) * * Comments: !!! Don't forget sync code with C !!! * */ function copy_template_triggers($hostid, $templateid = null, $copy_mode = false) { if(null == $templateid) { $templateid = array_keys(get_templates_by_hostid($hostid)); } if(is_array($templateid)) { foreach($templateid as $id) copy_template_triggers($hostid, $id, $copy_mode); // attention recursion return; } $triggers = get_triggers_by_hostid($templateid); while($trigger = DBfetch($triggers)) { copy_trigger_to_host($trigger["triggerid"], $hostid, $copy_mode); } update_template_dependences_for_host($hostid); } /* * Function: update_template_dependences_for_host * * Description: * Update template triggers * * Author: * Eugene Grigorjev (eugene.grigorjev@zabbix.com) * * Comments: !!! Don't forget sync code with C !!! * */ function update_template_dependences_for_host($hostid) { $db_triggers = get_triggers_by_hostid($hostid); while($trigger_data = DBfetch($db_triggers)) { $db_chd_triggers = get_triggers_by_templateid($trigger_data['triggerid']); while($chd_trigger_data = DBfetch($db_chd_triggers)) update_trigger($chd_trigger_data['triggerid'], /*$expression*/ NULL, /*$description*/ NULL, /*$priority*/ NULL, /*$status*/ NULL, /*$comments*/ NULL, /*$url*/ NULL, replace_template_dependences( get_trigger_dependences_by_triggerid($trigger_data['triggerid']), $hostid), $trigger_data['triggerid']); } } /* * Function: get_triggers_overview * * Description: * Retrive table with overview of triggers * * Author: * Eugene Grigorjev (eugene.grigorjev@zabbix.com) * * Comments: !!! Don't forget sync code with C !!! * */ function get_triggers_overview($groupid) { global $USER_DETAILS; $table = new CTableInfo(S_NO_TRIGGERS_DEFINED); if($groupid > 0) { $group_where = ',hosts_groups hg where hg.groupid='.$groupid.' and hg.hostid=h.hostid and'; } else { $group_where = ' where'; } $result=DBselect('select distinct t.triggerid,t.description,t.expression,t.value,t.priority,t.lastchange,h.hostid,h.host'. ' from hosts h,items i,triggers t, functions f '.$group_where. ' h.status='.HOST_STATUS_MONITORED.' and h.hostid=i.hostid and i.itemid=f.itemid and f.triggerid=t.triggerid'. ' and h.hostid in ('.get_accessible_hosts_by_user($USER_DETAILS,PERM_READ_ONLY, null, null, get_current_nodeid()).') '. ' and t.status='.TRIGGER_STATUS_ENABLED.' and i.status='.ITEM_STATUS_ACTIVE. ' order by t.description'); unset($triggers); unset($hosts); while($row = DBfetch($result)) { $row['host'] = get_node_name_by_elid($row['hostid']).$row['host']; $row['description'] = expand_trigger_description_constants($row['description'], $row); $hosts[$row['host']] = $row['host']; $triggers[$row['description']][$row['host']] = array( 'hostid' => $row['hostid'], 'triggerid' => $row['triggerid'], 'value' => $row['value'], 'lastchange' => $row['lastchange'], 'priority' => $row['priority']); } if(!isset($hosts)) { return $table; } sort($hosts); $header=array(new CCol(S_TRIGGERS,'center')); foreach($hosts as $hostname) { $header=array_merge($header,array(new CImg('vtext.php?text='.$hostname))); } $table->SetHeader($header,'vertical_header'); foreach($triggers as $descr => $trhosts) { $table_row = array(nbsp($descr)); foreach($hosts as $hostname) { $css_class = NULL; unset($tr_ov_menu); $ack = null; if(isset($trhosts[$hostname])) { unset($ack_menu); switch($trhosts[$hostname]['value']) { case TRIGGER_VALUE_TRUE: $css_class = get_severity_style($trhosts[$hostname]['priority']); if( ($ack = get_last_event_by_triggerid($trhosts[$hostname]['triggerid'])) ) $ack_menu = array(S_ACKNOWLEDGE, 'acknow.php?eventid='.$ack['eventid'], array('tw'=>'_blank')); if ( 1 == $ack['acknowledged'] ) $ack = new CImg('images/general/tick.png','ack'); else $ack = null; break; case TRIGGER_VALUE_FALSE: $css_class = 'normal'; break; default: $css_class = 'unknown_trigger'; } $style = 'cursor: pointer; '; if((time(NULL)-$trhosts[$hostname]['lastchange'])<300) $style .= 'background-image: url(images/gradients/blink1.gif); '. 'background-position: top left; '. 'background-repeat: repeate;'; elseif((time(NULL)-$trhosts[$hostname]['lastchange'])<900) $style .= 'background-image: url(images/gradients/blink2.gif); '. 'background-position: top left; '. 'background-repeat: repeate;'; unset($item_menu); $tr_ov_menu = array( /* name, url, (target [tw], statusbar [sb]), css, submenu */ array(S_TRIGGER, null, null, array('outer'=> array('pum_oheader'), 'inner'=>array('pum_iheader')) ), array(S_EVENTS, 'tr_events.php?triggerid='.$trhosts[$hostname]['triggerid'], array('tw'=>'_blank')) ); if(isset($ack_menu)) $tr_ov_menu[] = $ack_menu; $db_items = DBselect('select distinct i.itemid, i.description, i.key_, i.value_type '. ' from items i, functions f '. ' where f.itemid=i.itemid and f.triggerid='.$trhosts[$hostname]['triggerid']); while($item_data = DBfetch($db_items)) { $description = item_description($item_data['description'], $item_data['key_']); switch($item_data['value_type']) { case ITEM_VALUE_TYPE_UINT64: case ITEM_VALUE_TYPE_FLOAT: $action = 'showgraph'; $status_bar = S_SHOW_GRAPH_OF_ITEM.' \''.$description.'\''; break; case ITEM_VALUE_TYPE_LOG: case ITEM_VALUE_TYPE_STR: case ITEM_VALUE_TYPE_TEXT: default: $action = 'showlatest'; $status_bar = S_SHOW_VALUES_OF_ITEM.' \''.$description.'\''; break; } if(strlen($description) > 25) $description = substr($description,0,22).'...'; $item_menu[$action][] = array( $description, 'history.php?action='.$action.'&itemid='.$item_data['itemid'].'&period=3600', array('tw'=>'_blank', 'sb'=>$status_bar)); } if(isset($item_menu['showgraph'])) { $tr_ov_menu[] = array(S_GRAPHS, null, null, array('outer'=> array('pum_oheader'), 'inner'=>array('pum_iheader')) ); $tr_ov_menu = array_merge($tr_ov_menu, $item_menu['showgraph']); } if(isset($item_menu['showlatest'])) { $tr_ov_menu[] = array(S_VALUES, null, null, array('outer'=> array('pum_oheader'), 'inner'=>array('pum_iheader')) ); $tr_ov_menu = array_merge($tr_ov_menu, $item_menu['showlatest']); } unset($item_menu); } $status_col = new CCol(array(SPACE, $ack),$css_class); if(isset($style)) { $status_col->AddOption('style', $style); } if(isset($tr_ov_menu)) { $tr_ov_menu = new CPUMenu($tr_ov_menu,170); $status_col->OnClick($tr_ov_menu->GetOnActionJS()); $status_col->AddAction('onmouseover', 'this.old_border=this.style.border; this.style.border=\'1px dotted #0C0CF0\''); $status_col->AddAction('onmouseout', 'this.style.border=this.old_border;'); } array_push($table_row,$status_col); } $table->AddRow($table_row); } return $table; } function get_function_by_functionid($functionid) { $result=DBselect("select * from functions where functionid=$functionid"); $row=DBfetch($result); if($row) { return $row; } else { error("No function with functionid=[$functionid]"); } return $item; } function calculate_availability($triggerid,$period_start,$period_end) { $sql='select count(*) as cnt,min(clock) as minn,max(clock) as maxx from events '. ' where objectid='.$triggerid.' and object='.EVENT_OBJECT_TRIGGER; if($period_start!=0) $sql .= ' and clock>='.$period_start; if($period_end!=0) $sql .= ' and clock<='.$period_end; $row=DBfetch(DBselect($sql)); if($row["cnt"]>0) { $min=$row["minn"]; $max=$row["maxx"]; } else { if(($period_start==0)&&($period_end==0)) { $max=time(); $min=$max-24*3600; } else { $ret["true_time"] = 0; $ret["false_time"] = 0; $ret["unknown_time"] = 0; $ret["true"] = 0; $ret["false"] = 0; $ret["unknown"] = 100; return $ret; } } $result=DBselect('select clock,value from events where objectid='.$triggerid.' and object='.EVENT_OBJECT_TRIGGER .' and clock>='.$min.' and clock<='.$max); $state = -1; $true_time = 0; $false_time = 0; $unknown_time = 0; $time = $min; if(($period_start==0)&&($period_end==0)) { $max=time(); } $rows=0; while($row=DBfetch($result)) { $clock=$row["clock"]; $value=$row["value"]; $diff=$clock-$time; $time=$clock; if($state==-1) { $state=$value; if($state == 0) { $false_time+=$diff; } if($state == 1) { $true_time+=$diff; } if($state == 2) { $unknown_time+=$diff; } } else if($state==0) { $false_time+=$diff; $state=$value; } else if($state==1) { $true_time+=$diff; $state=$value; } else if($state==2) { $unknown_time+=$diff; $state=$value; } $rows++; } if($rows==0) { $trigger = get_trigger_by_triggerid($triggerid); $state = $trigger['value']; } if($state==0) { $false_time=$false_time+$max-$time; } elseif($state==1) { $true_time=$true_time+$max-$time; } elseif($state==3) { $unknown_time=$unknown_time+$max-$time; } $total_time=$true_time+$false_time+$unknown_time; if($total_time==0) { $ret["true_time"] = 0; $ret["false_time"] = 0; $ret["unknown_time"] = 0; $ret["true"] = 0; $ret["false"] = 0; $ret["unknown"] = 100; } else { $ret["true_time"] = $true_time; $ret["false_time"] = $false_time; $ret["unknown_time"] = $unknown_time; $ret["true"] = (100*$true_time)/$total_time; $ret["false"] = (100*$false_time)/$total_time; $ret["unknown"] = (100*$unknown_time)/$total_time; } return $ret; } /* * Function: trigger_depenent_rec * * Description: * check if trigger depends on other triggers having status TRUE * * Author: * Alexei Vladishev * * Comments: Recursive function * */ function trigger_dependent_rec($triggerid,&$level) { $ret = FALSE; $level++; /* Check for recursive loop */ if($level > 32) return $ret; $result = DBselect("select t.triggerid, t.value from trigger_depends d,triggers t where d.triggerid_down=$triggerid and d.triggerid_up=t.triggerid"); while($row = DBfetch($result)) { $triggerid_tmp = $row["triggerid"]; $value_tmp = $row["value"]; if(TRIGGER_VALUE_TRUE == $value_tmp || trigger_dependent_rec($triggerid_tmp, $level)) { $ret = TRUE; break; } } return $ret; } /* * Function: trigger_depenent * * Description: * check if trigger depends on other triggers having status TRUE * * Author: * Alexei Vladishev * * Comments: * */ function trigger_dependent($triggerid) { $level = 0; return trigger_dependent_rec($triggerid, $level); } /* * Function: trigger_get_N_functionid * * Description: * get functionid of Nth function of trigger expression * * Author: * Alexei Vladishev * * Comments: * */ function trigger_get_N_functionid($expression, $function) { $result = NULL; $arr=split('[\{\}]',$expression); $num=1; foreach($arr as $id) { if(is_numeric($id)) { if($num == $function) { $result = $id; break; } $num++; } } return $result; } /* * Function: trigger_get_func_value * * Description: * get historical value of Nth function of trigger expression * flag: ZBX_FLAG_EVENT - get value by clock, ZBX_FLAG_TRIGGR - get value by index * ZBX_FLAG_TRIGGER, param: 0 - last value, 1 - prev, 2 - prev prev, etc * ZBX_FLAG_EVENT, param: event timestamp * * Author: * Alexei Vladishev * * Comments: * */ function trigger_get_func_value($expression, $flag, $function, $param) { $result = NULL; $functionid=trigger_get_N_functionid($expression,$function); if(isset($functionid)) { $row=DBfetch(DBselect('select i.* from items i, functions f '. ' where i.itemid=f.itemid and f.functionid='.$functionid)); if($row) { $result=($flag == ZBX_FLAG_TRIGGER)? item_get_history($row, $param): item_get_history($row, 0, $param); } } return $result; } function get_row_for_nofalseforb($row,$cond){ $sql = 'SELECT e.eventid, e.value, e.clock as lastchange, e.clock'. ' FROM events e, triggers t '. ' WHERE e.object=0 AND e.objectid='.$row['triggerid']. ' AND t.triggerid=e.objectid '.$cond. ' ORDER by e.eventid DESC'; $res_events = DBSelect($sql,1); if(!$e_row=DBfetch($res_events)){ continue; } else{ $row = array_merge($row,$e_row); } if(!event_initial_time($row)){ if(!$eventid = first_initial_eventid($row,0)) continue; $sql = 'SELECT e.eventid, e.value, e.clock as lastchange'. ' FROM events e '. ' WHERE e.object=0 AND e.eventid='.$eventid; $res_events = DBSelect($sql,1); if(!$e_row=DBfetch($res_events)){ continue; } else{ $row = array_merge($row,$e_row); } } return $row; } ?>