zabbix_manager 5.1.5 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +55 -9
- data/LICENSE +1 -1
- data/README.md +241 -24
- data/lib/zabbix_manager/classes/actions.rb +19 -17
- data/lib/zabbix_manager/classes/applications.rb +11 -22
- data/lib/zabbix_manager/classes/configurations.rb +20 -10
- data/lib/zabbix_manager/classes/discovery_rules.rb +23 -0
- data/lib/zabbix_manager/classes/errors.rb +18 -27
- data/lib/zabbix_manager/classes/events.rb +8 -3
- data/lib/zabbix_manager/classes/graphs.rb +48 -37
- data/lib/zabbix_manager/classes/host_groups.rb +64 -0
- data/lib/zabbix_manager/classes/host_interfaces.rb +261 -0
- data/lib/zabbix_manager/classes/hosts.rb +232 -76
- data/lib/zabbix_manager/classes/http_tests.rb +32 -0
- data/lib/zabbix_manager/classes/items.rb +206 -72
- data/lib/zabbix_manager/classes/maintenance.rb +8 -3
- data/lib/zabbix_manager/classes/media_types.rb +18 -0
- data/lib/zabbix_manager/classes/problems.rb +51 -62
- data/lib/zabbix_manager/classes/proxies.rb +45 -14
- data/lib/zabbix_manager/classes/proxy_groups.rb +16 -0
- data/lib/zabbix_manager/classes/roles.rb +46 -41
- data/lib/zabbix_manager/classes/screens.rb +36 -24
- data/lib/zabbix_manager/classes/scripts.rb +16 -12
- data/lib/zabbix_manager/classes/server.rb +8 -1
- data/lib/zabbix_manager/classes/templates.rb +26 -51
- data/lib/zabbix_manager/classes/triggers.rb +251 -67
- data/lib/zabbix_manager/classes/user_groups.rb +63 -0
- data/lib/zabbix_manager/classes/user_macros.rb +110 -0
- data/lib/zabbix_manager/classes/users.rb +16 -23
- data/lib/zabbix_manager/classes/value_maps.rb +52 -0
- data/lib/zabbix_manager/client.rb +183 -137
- data/lib/zabbix_manager/configuration.rb +107 -0
- data/lib/zabbix_manager/http_transport.rb +240 -0
- data/lib/zabbix_manager/log_sanitizer.rb +58 -0
- data/lib/zabbix_manager/monitoring/device.rb +393 -0
- data/lib/zabbix_manager/monitoring/expressions.rb +36 -0
- data/lib/zabbix_manager/monitoring/line.rb +175 -0
- data/lib/zabbix_manager/monitoring/line_items.rb +110 -0
- data/lib/zabbix_manager/monitoring/line_lifecycle.rb +169 -0
- data/lib/zabbix_manager/monitoring/line_plan.rb +113 -0
- data/lib/zabbix_manager/monitoring/thresholds.rb +182 -0
- data/lib/zabbix_manager/monitoring/traffic_items.rb +132 -0
- data/lib/zabbix_manager/monitoring/validation.rb +92 -0
- data/lib/zabbix_manager/monitoring.rb +265 -0
- data/lib/zabbix_manager/resource.rb +235 -0
- data/lib/zabbix_manager/traffic.rb +238 -0
- data/lib/zabbix_manager/version.rb +1 -1
- data/lib/zabbix_manager.rb +110 -145
- data/zabbix_manager.gemspec +12 -15
- metadata +67 -30
- data/lib/zabbix_manager/basic/basic_alias.rb +0 -20
- data/lib/zabbix_manager/basic/basic_func.rb +0 -84
- data/lib/zabbix_manager/basic/basic_init.rb +0 -35
- data/lib/zabbix_manager/basic/basic_logic.rb +0 -195
- data/lib/zabbix_manager/classes/drules.rb +0 -41
- data/lib/zabbix_manager/classes/hostgroups.rb +0 -20
- data/lib/zabbix_manager/classes/hostinterfaces.rb +0 -29
- data/lib/zabbix_manager/classes/httptests.rb +0 -40
- data/lib/zabbix_manager/classes/mediatypes.rb +0 -79
- data/lib/zabbix_manager/classes/unusable.rb +0 -11
- data/lib/zabbix_manager/classes/usergroups.rb +0 -53
- data/lib/zabbix_manager/classes/usermacros.rb +0 -136
- data/lib/zabbix_manager/classes/valuemaps.rb +0 -32
|
@@ -1,95 +1,229 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class ZabbixManager
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
# 监控项查询与写入;通用 CRUD 使用名称,专用 upsert 使用 hostid + key_。
|
|
5
|
+
class Items < Resource
|
|
6
|
+
DEFAULT_OPTIONS = {
|
|
7
|
+
delay: "1m",
|
|
8
|
+
history: "1h",
|
|
9
|
+
status: 0,
|
|
10
|
+
value_type: 3
|
|
11
|
+
}.freeze
|
|
12
|
+
ITEM_TYPES = [0, 2, 3, 5, 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22].freeze
|
|
13
|
+
REQUIRED_INTERFACE_TYPES = [0, 12, 16, 17, 20].freeze
|
|
14
|
+
REQUIRED_PARAMS_TYPES = [11, 13, 14, 15, 21, 22].freeze
|
|
15
|
+
|
|
16
|
+
# 返回监控项对应的 Zabbix API 模块名。
|
|
17
|
+
#
|
|
18
|
+
# @return [String]
|
|
6
19
|
def method_name
|
|
7
20
|
"item"
|
|
8
21
|
end
|
|
9
22
|
|
|
10
|
-
#
|
|
11
|
-
|
|
12
|
-
|
|
23
|
+
# 返回创建监控项时的克制默认值。
|
|
24
|
+
#
|
|
25
|
+
# @return [Hash]
|
|
26
|
+
def default_options
|
|
27
|
+
DEFAULT_OPTIONS.dup
|
|
13
28
|
end
|
|
14
29
|
|
|
15
|
-
#
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
# 通过 Zabbix API 获取或创建 Item 对象
|
|
54
|
-
def get_or_create(data)
|
|
55
|
-
log "[DEBUG] 调用 #{method_name}.get_or_create 方法,参数: #{data.inspect}"
|
|
56
|
-
|
|
57
|
-
if (id = get_id(name: data[:name], hostid: data[:hostid]))
|
|
58
|
-
id
|
|
59
|
-
else
|
|
60
|
-
create(data)
|
|
61
|
-
end
|
|
30
|
+
# 使用主机和名称组成通用 CRUD 的查询边界。
|
|
31
|
+
#
|
|
32
|
+
# @param data [Hash] 包含 name 和 hostid 的监控项属性
|
|
33
|
+
# @raise [ApiError] Zabbix API 明确返回业务错误
|
|
34
|
+
# @raise [TransportError] HTTP 或网络请求失败,可能无法确认远端结果
|
|
35
|
+
# @return [Hash] 名称和所属主机组成的精确过滤条件
|
|
36
|
+
def identity_filter(data)
|
|
37
|
+
attributes = data.deep_symbolize_keys
|
|
38
|
+
{ name: attributes.fetch(:name), hostid: attributes.fetch(:hostid) }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# 查询主机监控项,可按稳定 key 集合过滤并选择关联对象。
|
|
42
|
+
# @return [Array<Hash>]
|
|
43
|
+
def for_host(hostid, keys: nil, output: "extend", select_preprocessing: nil, select_tags: nil)
|
|
44
|
+
raise Invalid, "hostid is required" if hostid.blank?
|
|
45
|
+
|
|
46
|
+
params = { hostids: hostid, output: output }
|
|
47
|
+
params[:filter] = { key_: keys } if keys.present?
|
|
48
|
+
params[:selectPreprocessing] = select_preprocessing if select_preprocessing
|
|
49
|
+
params[:selectTags] = select_tags if select_tags
|
|
50
|
+
@client.api_request(method: "item.get", params: params)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# 按主机和稳定 key 查询唯一监控项。
|
|
54
|
+
# @return [Hash, nil]
|
|
55
|
+
def find_by_key(hostid:, key:)
|
|
56
|
+
result = for_host(hostid, keys: key, output: "extend", select_preprocessing: "extend")
|
|
57
|
+
raise Conflict, "multiple items use key #{key} on host #{hostid}" if result.length > 1
|
|
58
|
+
|
|
59
|
+
result.first
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# 按 hostid + key_ 幂等创建或更新监控项。
|
|
63
|
+
# @return [Integer]
|
|
64
|
+
def upsert_by_key(data)
|
|
65
|
+
apply_item(*plan_item(validate_item!(data)))
|
|
62
66
|
end
|
|
63
67
|
|
|
64
|
-
#
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
+
# 先校验整批数据,再按稳定 key 逐项幂等写入。
|
|
69
|
+
# @yieldparam effective [Array<Hash>] 合并已有配置或创建默认值后的有效属性;块失败时不写入
|
|
70
|
+
# @return [Array<Integer>]
|
|
71
|
+
def upsert_many(collection)
|
|
72
|
+
items = Array(collection).map { |data| validate_item!(data) }
|
|
73
|
+
identities = items.map { |item| [item[:hostid].to_s, item[:key_].to_s] }
|
|
74
|
+
duplicate = identities.tally.find { |_identity, count| count > 1 }&.first
|
|
75
|
+
raise Invalid, "duplicate hostid + key_ identity #{duplicate.join(":")}" if duplicate
|
|
76
|
+
|
|
77
|
+
plans = items.map { |item| plan_item(item) }
|
|
78
|
+
if block_given?
|
|
79
|
+
effective = plans.map do |attributes, current|
|
|
80
|
+
if current && !%w[type value_type].all? { |field| current.key?(field) }
|
|
81
|
+
raise ProtocolError, "item.get must include type and value_type for effective configuration validation"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
current ? current.deep_symbolize_keys.merge(attributes).deep_dup : attributes.deep_dup
|
|
85
|
+
end
|
|
86
|
+
yield effective
|
|
87
|
+
end
|
|
88
|
+
plans.map { |attributes, current| apply_item(attributes, current) }
|
|
68
89
|
end
|
|
69
90
|
|
|
70
|
-
#
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
91
|
+
# 批量启用或停用监控项。
|
|
92
|
+
# @return [Array<Integer>]
|
|
93
|
+
def set_status(hostid:, itemids:, enabled:)
|
|
94
|
+
validate_boolean!(enabled, "enabled")
|
|
95
|
+
ids = normalized_ids(itemids)
|
|
96
|
+
verify_host_ownership!(hostid, ids)
|
|
97
|
+
result = @client.api_request(
|
|
98
|
+
method: "item.update",
|
|
99
|
+
params: ids.map { |itemid| { itemid: itemid, status: enabled ? 0 : 1 } }
|
|
100
|
+
)
|
|
101
|
+
response_ids(result, expected: ids)
|
|
102
|
+
end
|
|
74
103
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
104
|
+
# 批量删除明确指定的监控项。
|
|
105
|
+
# @return [Array<Integer>]
|
|
106
|
+
def delete_many(hostid:, itemids:)
|
|
107
|
+
ids = normalized_ids(itemids)
|
|
108
|
+
verify_host_ownership!(hostid, ids)
|
|
109
|
+
result = @client.api_request(method: "item.delete", params: ids)
|
|
110
|
+
response_ids(result, expected: ids)
|
|
111
|
+
end
|
|
78
112
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
113
|
+
# 返回主机中可能表示接口流量的已启用监控项。
|
|
114
|
+
# 方向和接口精确匹配由 Monitoring 业务层负责。
|
|
115
|
+
# @return [Array<Hash>]
|
|
116
|
+
def monitored_traffic_candidates(hostid)
|
|
117
|
+
@client.api_request(
|
|
118
|
+
method: "item.get",
|
|
119
|
+
params: {
|
|
83
120
|
hostids: [hostid],
|
|
84
|
-
|
|
121
|
+
monitored: true,
|
|
122
|
+
output: %w[itemid hostid name key_ type snmp_oid value_type status units],
|
|
123
|
+
selectPreprocessing: "extend",
|
|
124
|
+
sortfield: "name",
|
|
125
|
+
sortorder: "ASC"
|
|
85
126
|
}
|
|
86
127
|
)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# 按主机接口幂等创建或更新 DNS 解析监控项,并返回监控项 ID。
|
|
131
|
+
# DNS 名称会进入 item key,因此拒绝可能改变 key 参数结构的分隔符。
|
|
132
|
+
# @return [Integer]
|
|
133
|
+
def upsert_dns_item(hostid:, interfaceid:, dns_name:)
|
|
134
|
+
name = dns_name.to_s.strip
|
|
135
|
+
raise Invalid, "dns_name is required" if name.blank?
|
|
136
|
+
raise Invalid, "dns_name contains unsupported item key delimiters" if name.match?(/[\[\],]/)
|
|
137
|
+
|
|
138
|
+
upsert_by_key(
|
|
139
|
+
hostid: hostid,
|
|
140
|
+
interfaceid: interfaceid,
|
|
141
|
+
name: "【DNS域名解析监控】#{name}",
|
|
142
|
+
key_: "net.dns.record[,#{name},A,2,2]",
|
|
143
|
+
type: 0,
|
|
144
|
+
value_type: 1,
|
|
145
|
+
delay: "1m",
|
|
146
|
+
history: "90d",
|
|
147
|
+
timeout: "3s"
|
|
148
|
+
)
|
|
149
|
+
end
|
|
87
150
|
|
|
88
|
-
|
|
89
|
-
filtered_result = result.select { |item| item["snmp_oid"].match?(/(1.3.6.1.2.1.31.1.1.1.(6|10|15)|1.3.6.1.2.1.2.2.1.8)./) }
|
|
151
|
+
private
|
|
90
152
|
|
|
91
|
-
|
|
92
|
-
|
|
153
|
+
# 创建必填字段必须在整批写入开始前校验。
|
|
154
|
+
def plan_item(attributes)
|
|
155
|
+
current = find_by_key(hostid: attributes[:hostid], key: attributes[:key_])
|
|
156
|
+
validate_item_type!(attributes[:type]) if attributes.key?(:type)
|
|
157
|
+
response_identifier(current["itemid"]) if current
|
|
158
|
+
unless current
|
|
159
|
+
attributes = default_options.merge(attributes)
|
|
160
|
+
validate_create_item!(attributes)
|
|
161
|
+
end
|
|
162
|
+
[attributes, current]
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def apply_item(attributes, current)
|
|
166
|
+
if current
|
|
167
|
+
itemid = current.fetch("itemid")
|
|
168
|
+
result = @client.api_request(method: "item.update", params: attributes.except(:hostid).merge(itemid: itemid))
|
|
169
|
+
response_id(result, expected: [itemid])
|
|
170
|
+
else
|
|
171
|
+
result = @client.api_request(method: "item.create", params: attributes)
|
|
172
|
+
response_id(result)
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# 规范化并校验幂等写入所需字段。
|
|
177
|
+
# @return [Hash]
|
|
178
|
+
# @api private
|
|
179
|
+
def validate_item!(data)
|
|
180
|
+
attributes = data.deep_symbolize_keys
|
|
181
|
+
raise Invalid, "hostid is required" if attributes[:hostid].blank?
|
|
182
|
+
raise Invalid, "key_ is required" if attributes[:key_].blank?
|
|
183
|
+
raise Invalid, "name is required" if attributes[:name].blank?
|
|
184
|
+
|
|
185
|
+
attributes
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# 校验 item.create 的通用必填字段和 SNMP 条件字段。
|
|
189
|
+
def validate_create_item!(attributes)
|
|
190
|
+
raise Invalid, "type is required when creating an item" if attributes[:type].blank?
|
|
191
|
+
raise Invalid, "value_type is required when creating an item" if attributes[:value_type].blank?
|
|
192
|
+
|
|
193
|
+
type = validate_item_type!(attributes[:type])
|
|
194
|
+
|
|
195
|
+
if REQUIRED_INTERFACE_TYPES.include?(type) && attributes[:interfaceid].blank?
|
|
196
|
+
raise Invalid, "interfaceid is required for item type #{type}"
|
|
197
|
+
end
|
|
198
|
+
if REQUIRED_PARAMS_TYPES.include?(type) && attributes[:params].blank?
|
|
199
|
+
raise Invalid, "params is required for item type #{type}"
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
raise Invalid,
|
|
203
|
+
"master_itemid is required for a dependent item" if type == 18 && attributes[:master_itemid].blank?
|
|
204
|
+
raise Invalid, "url is required for an HTTP item" if type == 19 && attributes[:url].blank?
|
|
205
|
+
return unless type == 20
|
|
206
|
+
|
|
207
|
+
raise Invalid, "snmp_oid is required for an SNMP item" if attributes[:snmp_oid].blank?
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def validate_item_type!(value)
|
|
211
|
+
type = integer_attribute(value, "type")
|
|
212
|
+
raise Invalid, "unsupported item type #{type}" unless ITEM_TYPES.include?(type)
|
|
213
|
+
|
|
214
|
+
type
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# 回查监控项归属,阻止共享高权限令牌跨主机修改。
|
|
218
|
+
def verify_host_ownership!(hostid, ids)
|
|
219
|
+
raise Invalid, "hostid is required" if hostid.blank?
|
|
220
|
+
|
|
221
|
+
result = @client.api_request(
|
|
222
|
+
method: "item.get", params: { hostids: hostid, itemids: ids, output: ["itemid"] }
|
|
223
|
+
)
|
|
224
|
+
owned_ids = result.map { |item| item.fetch("itemid").to_s }
|
|
225
|
+
foreign_ids = ids - owned_ids
|
|
226
|
+
raise Conflict, "items do not belong to host #{hostid}: #{foreign_ids.join(", ")}" if foreign_ids.any?
|
|
93
227
|
end
|
|
94
228
|
end
|
|
95
229
|
end
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class ZabbixManager
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
# 原生维护期资源;时间段、目标主机和群组由调用方显式定义。
|
|
5
|
+
class Maintenance < Resource
|
|
6
|
+
# 返回维护期对象对应的 Zabbix API 方法前缀。
|
|
7
|
+
#
|
|
8
|
+
# @return [String]
|
|
6
9
|
def method_name
|
|
7
10
|
"maintenance"
|
|
8
11
|
end
|
|
9
12
|
|
|
10
|
-
#
|
|
13
|
+
# 返回维护期对象用于业务识别的字段名。
|
|
14
|
+
#
|
|
15
|
+
# @return [String]
|
|
11
16
|
def identify
|
|
12
17
|
"name"
|
|
13
18
|
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class ZabbixManager
|
|
4
|
+
# 原生通知媒介资源;仅提供最小默认值,不推断端点、凭据或版本字段。
|
|
5
|
+
class MediaTypes < Resource
|
|
6
|
+
# 返回媒介类型对象对应的 Zabbix API 方法前缀。
|
|
7
|
+
# @return [String] API 方法前缀
|
|
8
|
+
def method_name
|
|
9
|
+
"mediatype"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# 返回媒介类型的最小默认属性;端点和凭据等版本相关字段由调用方显式提供。
|
|
13
|
+
# @return [Hash] 媒介类型默认属性
|
|
14
|
+
def default_options
|
|
15
|
+
{ type: 0 }
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -1,88 +1,77 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class ZabbixManager
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
#
|
|
4
|
+
# 原生问题查询与事件确认;问题身份使用 eventid,确认动作属于远端写入。
|
|
5
|
+
class Problems < Resource
|
|
6
|
+
# 返回问题对象对应的 Zabbix API 方法前缀。
|
|
7
|
+
#
|
|
8
|
+
# @return [String]
|
|
9
9
|
def method_name
|
|
10
10
|
"problem"
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
#
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
# 使用触发问题的事件 ID 作为对象身份。
|
|
14
|
+
#
|
|
15
|
+
# @return [String]
|
|
16
|
+
def key
|
|
17
|
+
"eventid"
|
|
16
18
|
end
|
|
17
19
|
|
|
18
|
-
#
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
filter: {
|
|
24
|
-
identify.to_sym => data[identify.to_sym]
|
|
25
|
-
},
|
|
26
|
-
output: "extend"
|
|
27
|
-
})
|
|
20
|
+
# 返回事件 ID 集合字段名。
|
|
21
|
+
#
|
|
22
|
+
# @return [String]
|
|
23
|
+
def keys
|
|
24
|
+
"eventids"
|
|
28
25
|
end
|
|
29
26
|
|
|
30
|
-
#
|
|
27
|
+
# 获取问题及其确认、标签和抑制信息,并支持附加查询参数。
|
|
28
|
+
#
|
|
29
|
+
# @param data [Hash] 问题过滤条件及附加 API 参数
|
|
30
|
+
# @raise [ApiError] Zabbix API 返回业务错误时抛出
|
|
31
|
+
# @raise [TransportError] Zabbix 服务端返回非成功 HTTP 状态时抛出
|
|
32
|
+
# @return [Array<Hash>] 匹配的问题完整数据
|
|
31
33
|
def get_full_data(data)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
data = data.deep_symbolize_keys
|
|
35
|
+
params = {
|
|
36
|
+
recent: false,
|
|
37
|
+
sortfield: ["eventid"],
|
|
38
|
+
sortorder: "DESC",
|
|
39
|
+
output: "extend",
|
|
40
|
+
selectAcknowledges: "extend",
|
|
41
|
+
selectTags: "extend",
|
|
42
|
+
selectSuppressionData: "extend"
|
|
43
|
+
}.merge(data.except(:name).compact)
|
|
44
|
+
params[:filter] = { identify.to_sym => data[identify.to_sym] } if data[identify.to_sym].present?
|
|
35
45
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
eventids: data[:eventids] || nil,
|
|
41
|
-
groupids: data[:groupids] || nil,
|
|
42
|
-
hostids: data[:hostids] || nil,
|
|
43
|
-
objectids: data[:objectids] || nil,
|
|
44
|
-
applicationids: data[:applicationids] || nil,
|
|
45
|
-
tags: data[:tags] || nil,
|
|
46
|
-
time_from: data[:time_from] || nil,
|
|
47
|
-
time_till: data[:time_till] || nil,
|
|
48
|
-
eventid_from: data[:eventid_from] || nil,
|
|
49
|
-
eventid_till: data[:eventid_till] || nil,
|
|
50
|
-
recent: data[:recent] || false,
|
|
51
|
-
sortfield: data[:sortfield] || ["eventid"],
|
|
52
|
-
sortorder: data[:sortorder] || "DESC",
|
|
53
|
-
countOutput: data[:countOutput] || nil,
|
|
54
|
-
output: "extend",
|
|
55
|
-
selectAcknowledges: "extend",
|
|
56
|
-
selectTags: "extend",
|
|
57
|
-
selectSuppressionData: "extend"
|
|
58
|
-
})
|
|
46
|
+
@client.api_request(
|
|
47
|
+
method: "#{method_name}.get",
|
|
48
|
+
params: params
|
|
49
|
+
)
|
|
59
50
|
end
|
|
60
51
|
|
|
61
|
-
#
|
|
52
|
+
# 获取全部问题对象的完整数据。
|
|
53
|
+
#
|
|
54
|
+
# @raise [ApiError] Zabbix API 返回业务错误时抛出
|
|
55
|
+
# @raise [TransportError] Zabbix 服务端返回非成功 HTTP 状态时抛出
|
|
56
|
+
# @return [Array<Hash>] 匹配的问题对象列表
|
|
62
57
|
def all
|
|
63
58
|
get_full_data({})
|
|
64
59
|
end
|
|
65
60
|
|
|
66
|
-
#
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
event_ids << item["eventid"]
|
|
74
|
-
end
|
|
75
|
-
return if event_ids.empty?
|
|
61
|
+
# 批量确认事件,可指定确认动作和附加消息。
|
|
62
|
+
# @param eventids [Array<String, Integer>, String, Integer] 待确认的事件 ID
|
|
63
|
+
# @param action [Integer] Zabbix 确认动作位掩码
|
|
64
|
+
# @param message [String, nil] 可选确认消息
|
|
65
|
+
# @return [Hash] 事件确认结果
|
|
66
|
+
def acknowledge_events(eventids, action: 2, message: nil)
|
|
67
|
+
ids = normalized_ids(eventids)
|
|
76
68
|
|
|
77
69
|
result = @client.api_request(
|
|
78
70
|
method: "event.acknowledge",
|
|
79
|
-
params: {
|
|
80
|
-
eventids: event_ids,
|
|
81
|
-
action: 2,
|
|
82
|
-
message: "本次告警符合自动刷新规则,已通过接口处理且刷新时间为:#{Time.now}"
|
|
83
|
-
}
|
|
71
|
+
params: { eventids: ids, action: action, message: message }.compact
|
|
84
72
|
)
|
|
85
|
-
result
|
|
73
|
+
response_ids(result, expected: ids)
|
|
74
|
+
result
|
|
86
75
|
end
|
|
87
76
|
end
|
|
88
77
|
end
|
|
@@ -1,31 +1,62 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class ZabbixManager
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
# 原生代理资源;按服务器版本选择 name 或 host 作为名称字段。
|
|
5
|
+
class Proxies < Resource
|
|
6
|
+
# 返回 Zabbix API 中代理对象的方法名前缀。
|
|
7
|
+
#
|
|
8
|
+
# @return [String] 代理对象的方法名前缀
|
|
6
9
|
def method_name
|
|
7
10
|
"proxy"
|
|
8
11
|
end
|
|
9
12
|
|
|
10
|
-
#
|
|
13
|
+
# 返回用于唯一识别代理对象的字段名。
|
|
14
|
+
#
|
|
15
|
+
# @return [String] 代理对象的标识字段名
|
|
11
16
|
def identify
|
|
12
|
-
"host"
|
|
17
|
+
Gem::Version.new(@client.api_version) >= Gem::Version.new("7.0") ? "name" : "host"
|
|
13
18
|
end
|
|
14
19
|
|
|
15
|
-
#
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def is_readable(data)
|
|
20
|
+
# 检查当前凭证是否可读取指定代理。
|
|
21
|
+
#
|
|
22
|
+
# @param data [Array] 要检查的 proxyid 数组
|
|
23
|
+
# @raise [ApiError] Zabbix API 返回业务错误时抛出
|
|
24
|
+
# @raise [TransportError] Zabbix 服务返回非成功 HTTP 状态时抛出
|
|
25
|
+
# @return [Boolean] 指定代理是否可读
|
|
26
|
+
def isreadable(data)
|
|
23
27
|
@client.api_request(method: "proxy.isreadable", params: data)
|
|
24
28
|
end
|
|
25
29
|
|
|
26
|
-
#
|
|
27
|
-
|
|
30
|
+
# 检查当前凭证是否可写入指定代理。
|
|
31
|
+
#
|
|
32
|
+
# @param data [Array] 要检查的 proxyid 数组
|
|
33
|
+
# @raise [ApiError] Zabbix API 返回业务错误时抛出
|
|
34
|
+
# @raise [TransportError] Zabbix 服务返回非成功 HTTP 状态时抛出
|
|
35
|
+
# @return [Boolean] 指定代理是否可写
|
|
36
|
+
def iswritable(data)
|
|
28
37
|
@client.api_request(method: "proxy.iswritable", params: data)
|
|
29
38
|
end
|
|
39
|
+
|
|
40
|
+
# 按代理名称查询唯一代理 ID,空名称返回 nil,重名时拒绝选择。
|
|
41
|
+
#
|
|
42
|
+
# @param proxy [String] 代理名称
|
|
43
|
+
# @return [String, nil] 唯一代理 ID,未找到时返回 nil
|
|
44
|
+
def get_proxy_id(proxy)
|
|
45
|
+
return nil if proxy.blank?
|
|
46
|
+
|
|
47
|
+
# 请求后端接口,只支持单个代理节点
|
|
48
|
+
result = @client.api_request(
|
|
49
|
+
method: "proxy.get",
|
|
50
|
+
params: {
|
|
51
|
+
output: ["proxyid", identify],
|
|
52
|
+
filter: {
|
|
53
|
+
identify.to_sym => proxy
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
raise Conflict, "proxy lookup is ambiguous for #{proxy}" if result.length > 1
|
|
58
|
+
|
|
59
|
+
result.first&.fetch("proxyid", nil)
|
|
60
|
+
end
|
|
30
61
|
end
|
|
31
62
|
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class ZabbixManager
|
|
4
|
+
# Zabbix 7.0 起提供的原生代理组资源。
|
|
5
|
+
class ProxyGroups < Resource
|
|
6
|
+
# @return [String] 原生 API 方法前缀
|
|
7
|
+
def method_name
|
|
8
|
+
"proxygroup"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# @return [String] 原生代理组 ID 字段
|
|
12
|
+
def key
|
|
13
|
+
"proxy_groupid"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|