feat
This commit is contained in:
@@ -1,334 +1,317 @@
|
|||||||
/**
|
/**
|
||||||
* 服务器硬件监控页专用:对接 DC-Hardware 服务(/DC-Hardware/v1)。
|
* 服务器硬件监控页专用:对接 DC-Hardware 服务(/DC-Hardware/v1)。
|
||||||
* 与「机房设备监控」等业务区分,勿混用命名。
|
* 与「机房设备监控」等业务区分,勿混用命名。
|
||||||
*/
|
*/
|
||||||
import { request } from '@/api/request'
|
import { request } from '@/api/request'
|
||||||
|
|
||||||
const HW_PREFIX = '/DC-Hardware/v1'
|
const HW_PREFIX = '/DC-Hardware/v1'
|
||||||
|
|
||||||
/** 与 bsm-sdk 成功响应一致:业务数据在 details */
|
/** 与 bsm-sdk 成功响应一致:业务数据在 details */
|
||||||
export interface HostHardwareApiEnvelope<T = unknown> {
|
export interface HostHardwareApiEnvelope<T = unknown> {
|
||||||
code?: number | string
|
code?: number | string
|
||||||
message?: string
|
message?: string
|
||||||
details?: T
|
details?: T
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface HostHardwareDeviceDetailPayload {
|
export interface HostHardwareDeviceDetailPayload {
|
||||||
device: HostHardwareDevice
|
device: HostHardwareDevice
|
||||||
status: HostHardwareStatus | null
|
status: HostHardwareStatus | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface HostHardwareDevice {
|
export interface HostHardwareDevice {
|
||||||
id: string
|
id: string
|
||||||
name?: string
|
name?: string
|
||||||
ip: string
|
ip: string
|
||||||
/** 设备类别,如 server/switch/storage;未返回时前端可按 server 展示 */
|
/** 设备类别,如 server/switch/storage;未返回时前端可按 server 展示 */
|
||||||
type?: string
|
type?: string
|
||||||
protocol: string
|
protocol: string
|
||||||
manufacturer?: string
|
manufacturer?: string
|
||||||
model?: string
|
model?: string
|
||||||
serial_number?: string
|
serial_number?: string
|
||||||
username?: string
|
username?: string
|
||||||
password?: string
|
password?: string
|
||||||
port?: number
|
port?: number
|
||||||
snmp_port?: number
|
snmp_port?: number
|
||||||
community?: string
|
community?: string
|
||||||
snmp_version?: string
|
snmp_version?: string
|
||||||
redfish_base_url?: string
|
redfish_base_url?: string
|
||||||
redfish_tls_skip_verify?: boolean
|
redfish_tls_skip_verify?: boolean
|
||||||
ipmi_timeout_seconds?: number
|
ipmi_timeout_seconds?: number
|
||||||
snmp_timeout_seconds?: number
|
snmp_timeout_seconds?: number
|
||||||
redfish_timeout_seconds?: number
|
redfish_timeout_seconds?: number
|
||||||
ipmi_collect_enabled?: boolean
|
ipmi_collect_enabled?: boolean
|
||||||
snmp_collect_enabled?: boolean
|
snmp_collect_enabled?: boolean
|
||||||
redfish_collect_enabled?: boolean
|
redfish_collect_enabled?: boolean
|
||||||
collect_interval?: number
|
collect_interval?: number
|
||||||
asset_id?: string
|
asset_id?: string
|
||||||
server_identity?: string
|
server_identity?: string
|
||||||
enabled?: boolean
|
enabled?: boolean
|
||||||
status?: string
|
status?: string
|
||||||
tags?: string
|
tags?: string
|
||||||
description?: string
|
description?: string
|
||||||
extra_config?: string
|
extra_config?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 创建/更新 DC-Hardware 设备(与 CreateDeviceRequest 一致;密码在更新时为空则不修改) */
|
/** 创建/更新 DC-Hardware 设备(与 CreateDeviceRequest 一致;密码在更新时为空则不修改) */
|
||||||
export interface HostHardwareDeviceUpsert {
|
export interface HostHardwareDeviceUpsert {
|
||||||
name: string
|
name: string
|
||||||
ip: string
|
ip: string
|
||||||
/** 省略或空则服务端默认 server */
|
/** 省略或空则服务端默认 server */
|
||||||
type?: string
|
type?: string
|
||||||
protocol: string
|
protocol: string
|
||||||
username?: string
|
username?: string
|
||||||
password?: string
|
password?: string
|
||||||
port?: number
|
port?: number
|
||||||
snmp_port?: number
|
snmp_port?: number
|
||||||
community?: string
|
community?: string
|
||||||
snmp_version?: string
|
snmp_version?: string
|
||||||
redfish_base_url?: string
|
redfish_base_url?: string
|
||||||
redfish_tls_skip_verify?: boolean
|
redfish_tls_skip_verify?: boolean
|
||||||
location?: string
|
location?: string
|
||||||
description?: string
|
description?: string
|
||||||
tags?: string
|
tags?: string
|
||||||
asset_id?: string
|
asset_id?: string
|
||||||
server_identity?: string
|
server_identity?: string
|
||||||
extra_config?: string
|
extra_config?: string
|
||||||
ipmi_timeout_seconds?: number
|
ipmi_timeout_seconds?: number
|
||||||
snmp_timeout_seconds?: number
|
snmp_timeout_seconds?: number
|
||||||
redfish_timeout_seconds?: number
|
redfish_timeout_seconds?: number
|
||||||
ipmi_collect_enabled?: boolean
|
ipmi_collect_enabled?: boolean
|
||||||
snmp_collect_enabled?: boolean
|
snmp_collect_enabled?: boolean
|
||||||
redfish_collect_enabled?: boolean
|
redfish_collect_enabled?: boolean
|
||||||
collect_interval?: number
|
collect_interval?: number
|
||||||
}
|
/** 是否启用监控调度 */
|
||||||
|
enabled?: boolean
|
||||||
export interface HostHardwareDeviceListPayload {
|
}
|
||||||
total: number
|
|
||||||
page: string | number
|
export interface HostHardwareDeviceListPayload {
|
||||||
page_size: string | number
|
total: number
|
||||||
data: HostHardwareDevice[]
|
page: string | number
|
||||||
}
|
page_size: string | number
|
||||||
|
data: HostHardwareDevice[]
|
||||||
export interface HostHardwareStatus {
|
}
|
||||||
id?: string
|
|
||||||
device_id?: string
|
export interface HostHardwareStatus {
|
||||||
status?: string
|
id?: string
|
||||||
power_status?: string
|
device_id?: string
|
||||||
cpu_status?: string
|
status?: string
|
||||||
memory_status?: string
|
power_status?: string
|
||||||
disk_status?: string
|
cpu_status?: string
|
||||||
fan_status?: string
|
memory_status?: string
|
||||||
temperature_status?: string
|
disk_status?: string
|
||||||
network_status?: string
|
fan_status?: string
|
||||||
psu_status?: string
|
temperature_status?: string
|
||||||
raid_status?: string
|
network_status?: string
|
||||||
last_check_time?: string
|
psu_status?: string
|
||||||
error_message?: string
|
raid_status?: string
|
||||||
raw_data?: string
|
last_check_time?: string
|
||||||
}
|
error_message?: string
|
||||||
|
raw_data?: string
|
||||||
export interface HostHardwareMetricsRow {
|
}
|
||||||
id?: string
|
|
||||||
device_id?: string
|
export interface HostHardwareMetricsRow {
|
||||||
metric_name: string
|
id?: string
|
||||||
metric_type: string
|
device_id?: string
|
||||||
metric_value: number
|
metric_name: string
|
||||||
unit?: string
|
metric_type: string
|
||||||
status?: string
|
metric_value: number
|
||||||
threshold?: number
|
unit?: string
|
||||||
location?: string
|
status?: string
|
||||||
collection_time?: string
|
threshold?: number
|
||||||
}
|
location?: string
|
||||||
|
collection_time?: string
|
||||||
export interface HostHardwareLatestCollectionPayload {
|
}
|
||||||
device_id: string
|
|
||||||
collected_at?: string | null
|
export interface HostHardwareLatestCollectionPayload {
|
||||||
status: HostHardwareStatus | null
|
device_id: string
|
||||||
metrics: HostHardwareMetricsRow[]
|
collected_at?: string | null
|
||||||
timescaledb?: boolean
|
status: HostHardwareStatus | null
|
||||||
message?: string
|
metrics: HostHardwareMetricsRow[]
|
||||||
server_identity?: string
|
timescaledb?: boolean
|
||||||
}
|
message?: string
|
||||||
|
server_identity?: string
|
||||||
interface RawCollectionMetric {
|
}
|
||||||
name?: string
|
|
||||||
type?: string
|
interface RawCollectionMetric {
|
||||||
value?: number
|
name?: string
|
||||||
unit?: string
|
type?: string
|
||||||
status?: string
|
value?: number
|
||||||
threshold?: number
|
unit?: string
|
||||||
location?: string
|
status?: string
|
||||||
}
|
threshold?: number
|
||||||
|
location?: string
|
||||||
interface RawCollectionRoot {
|
}
|
||||||
metrics?: RawCollectionMetric[]
|
|
||||||
}
|
interface RawCollectionRoot {
|
||||||
|
metrics?: RawCollectionMetric[]
|
||||||
export interface NormalizedHostHardwareMetric {
|
}
|
||||||
name: string
|
|
||||||
type: string
|
export interface NormalizedHostHardwareMetric {
|
||||||
value: number
|
name: string
|
||||||
unit: string
|
type: string
|
||||||
status: string
|
value: number
|
||||||
threshold?: number
|
unit: string
|
||||||
location?: string
|
status: string
|
||||||
}
|
threshold?: number
|
||||||
|
location?: string
|
||||||
export interface HostHardwareMetricHistoryPayload {
|
}
|
||||||
device_id: string
|
|
||||||
metric_name: string
|
export interface HostHardwareMetricHistoryPayload {
|
||||||
start_time?: string
|
device_id: string
|
||||||
end_time?: string
|
metric_name: string
|
||||||
data: HostHardwareMetricsRow[]
|
start_time?: string
|
||||||
timescaledb?: boolean
|
end_time?: string
|
||||||
message?: string
|
data: HostHardwareMetricsRow[]
|
||||||
}
|
timescaledb?: boolean
|
||||||
|
message?: string
|
||||||
export interface HostHardwareStatisticsRow {
|
}
|
||||||
device_id: string
|
|
||||||
stat_date: string
|
export interface HostHardwareStatisticsRow {
|
||||||
online_time?: number
|
device_id: string
|
||||||
offline_time?: number
|
stat_date: string
|
||||||
warning_count?: number
|
online_time?: number
|
||||||
critical_count?: number
|
offline_time?: number
|
||||||
avg_temperature?: number
|
warning_count?: number
|
||||||
max_temperature?: number
|
critical_count?: number
|
||||||
min_temperature?: number
|
avg_temperature?: number
|
||||||
avg_fan_speed?: number
|
max_temperature?: number
|
||||||
avg_power_usage?: number
|
min_temperature?: number
|
||||||
max_power_usage?: number
|
avg_fan_speed?: number
|
||||||
total_check_count?: number
|
avg_power_usage?: number
|
||||||
success_check_count?: number
|
max_power_usage?: number
|
||||||
failed_check_count?: number
|
total_check_count?: number
|
||||||
availability?: number
|
success_check_count?: number
|
||||||
}
|
failed_check_count?: number
|
||||||
|
availability?: number
|
||||||
export function isHostHardwareApiSuccess(res: HostHardwareApiEnvelope | null | undefined): boolean {
|
}
|
||||||
const c = res?.code
|
|
||||||
if (c === 0 || c === '0') return true
|
export function isHostHardwareApiSuccess(res: HostHardwareApiEnvelope | null | undefined): boolean {
|
||||||
// 少数网关/代理以 200 表示业务成功
|
const c = res?.code
|
||||||
if (c === 200 || c === '200') return true
|
if (c === 0 || c === '0') return true
|
||||||
return false
|
// 少数网关/代理以 200 表示业务成功
|
||||||
}
|
if (c === 200 || c === '200') return true
|
||||||
|
return false
|
||||||
export function unwrapHostHardwareDetails<T>(
|
}
|
||||||
res: (HostHardwareApiEnvelope<T> & { data?: T }) | null | undefined,
|
|
||||||
): T | null {
|
export function unwrapHostHardwareDetails<T>(res: (HostHardwareApiEnvelope<T> & { data?: T }) | null | undefined): T | null {
|
||||||
if (!res || !isHostHardwareApiSuccess(res)) return null
|
if (!res || !isHostHardwareApiSuccess(res)) return null
|
||||||
// 部分网关/SDK 将载荷放在 data 而非 details,与 logs 等模块一致做兼容
|
// 部分网关/SDK 将载荷放在 data 而非 details,与 logs 等模块一致做兼容
|
||||||
return res.details ?? res.data ?? null
|
return res.details ?? res.data ?? null
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 按 server_identity 拉取最新一整轮采集(JWT) */
|
/** 按 server_identity 拉取最新一整轮采集(JWT) */
|
||||||
export function fetchHostHardwareLatestCollection(serverIdentity: string) {
|
export function fetchHostHardwareLatestCollection(serverIdentity: string) {
|
||||||
return request.get<HostHardwareApiEnvelope<HostHardwareLatestCollectionPayload>>(
|
return request.get<HostHardwareApiEnvelope<HostHardwareLatestCollectionPayload>>(
|
||||||
`${HW_PREFIX}/devices/by-server-identity/collection/latest`,
|
`${HW_PREFIX}/devices/by-server-identity/collection/latest`,
|
||||||
{ params: { server_identity: serverIdentity } },
|
{ params: { server_identity: serverIdentity } }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 设备详情(含最新一条 status) */
|
/** 设备详情(含最新一条 status) */
|
||||||
export function fetchHostHardwareDevice(deviceId: string) {
|
export function fetchHostHardwareDevice(deviceId: string) {
|
||||||
return request.get<HostHardwareApiEnvelope<HostHardwareDeviceDetailPayload>>(
|
return request.get<HostHardwareApiEnvelope<HostHardwareDeviceDetailPayload>>(`${HW_PREFIX}/devices/${encodeURIComponent(deviceId)}`)
|
||||||
`${HW_PREFIX}/devices/${encodeURIComponent(deviceId)}`,
|
}
|
||||||
)
|
|
||||||
}
|
/** 分页列表(可按 type / status / asset_id 筛选) */
|
||||||
|
export function fetchHostHardwareDeviceList(params?: {
|
||||||
/** 分页列表(可按 type / status / asset_id 筛选) */
|
type?: string
|
||||||
export function fetchHostHardwareDeviceList(params?: {
|
status?: string
|
||||||
type?: string
|
asset_id?: string
|
||||||
status?: string
|
page?: number
|
||||||
asset_id?: string
|
page_size?: number
|
||||||
page?: number
|
}) {
|
||||||
page_size?: number
|
return request.get<HostHardwareApiEnvelope<HostHardwareDeviceListPayload>>(`${HW_PREFIX}/devices`, {
|
||||||
}) {
|
params,
|
||||||
return request.get<HostHardwareApiEnvelope<HostHardwareDeviceListPayload>>(`${HW_PREFIX}/devices`, {
|
})
|
||||||
params,
|
}
|
||||||
})
|
|
||||||
}
|
/** 创建设备 */
|
||||||
|
export function createHostHardwareDevice(data: HostHardwareDeviceUpsert) {
|
||||||
/** 创建设备 */
|
return request.post<HostHardwareApiEnvelope<HostHardwareDevice>>(`${HW_PREFIX}/devices`, data)
|
||||||
export function createHostHardwareDevice(data: HostHardwareDeviceUpsert) {
|
}
|
||||||
return request.post<HostHardwareApiEnvelope<HostHardwareDevice>>(`${HW_PREFIX}/devices`, data)
|
|
||||||
}
|
/** 更新设备(全量必填字段;密码留空则不修改) */
|
||||||
|
export function updateHostHardwareDevice(deviceId: string, data: HostHardwareDeviceUpsert) {
|
||||||
/** 更新设备(全量必填字段;密码留空则不修改) */
|
return request.put<HostHardwareApiEnvelope<HostHardwareDevice>>(`${HW_PREFIX}/devices/${encodeURIComponent(deviceId)}`, data)
|
||||||
export function updateHostHardwareDevice(deviceId: string, data: HostHardwareDeviceUpsert) {
|
}
|
||||||
return request.put<HostHardwareApiEnvelope<HostHardwareDevice>>(
|
|
||||||
`${HW_PREFIX}/devices/${encodeURIComponent(deviceId)}`,
|
/** 异步立即采集 */
|
||||||
data,
|
export function triggerHostHardwareCollect(deviceId: string) {
|
||||||
)
|
return request.post<HostHardwareApiEnvelope<string>>(`${HW_PREFIX}/devices/${encodeURIComponent(deviceId)}/collect`)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 异步立即采集 */
|
/** 启用监控 */
|
||||||
export function triggerHostHardwareCollect(deviceId: string) {
|
export function enableHostHardwareDevice(deviceId: string) {
|
||||||
return request.post<HostHardwareApiEnvelope<string>>(`${HW_PREFIX}/devices/${encodeURIComponent(deviceId)}/collect`)
|
return request.post<HostHardwareApiEnvelope<string>>(`${HW_PREFIX}/devices/${encodeURIComponent(deviceId)}/enable`)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 启用监控 */
|
/** 禁用监控 */
|
||||||
export function enableHostHardwareDevice(deviceId: string) {
|
export function disableHostHardwareDevice(deviceId: string) {
|
||||||
return request.post<HostHardwareApiEnvelope<string>>(`${HW_PREFIX}/devices/${encodeURIComponent(deviceId)}/enable`)
|
return request.post<HostHardwareApiEnvelope<string>>(`${HW_PREFIX}/devices/${encodeURIComponent(deviceId)}/disable`)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 禁用监控 */
|
/** 单指标历史曲线(JWT) */
|
||||||
export function disableHostHardwareDevice(deviceId: string) {
|
export function fetchHostHardwareMetricHistory(deviceId: string, metricName: string, startTime?: string, endTime?: string) {
|
||||||
return request.post<HostHardwareApiEnvelope<string>>(`${HW_PREFIX}/devices/${encodeURIComponent(deviceId)}/disable`)
|
return request.get<HostHardwareApiEnvelope<HostHardwareMetricHistoryPayload>>(
|
||||||
}
|
`${HW_PREFIX}/metrics/devices/${encodeURIComponent(deviceId)}/history`,
|
||||||
|
{
|
||||||
/** 单指标历史曲线(JWT) */
|
params: {
|
||||||
export function fetchHostHardwareMetricHistory(
|
metric_name: metricName,
|
||||||
deviceId: string,
|
...(startTime ? { start_time: startTime } : {}),
|
||||||
metricName: string,
|
...(endTime ? { end_time: endTime } : {}),
|
||||||
startTime?: string,
|
},
|
||||||
endTime?: string,
|
}
|
||||||
) {
|
)
|
||||||
return request.get<HostHardwareApiEnvelope<HostHardwareMetricHistoryPayload>>(
|
}
|
||||||
`${HW_PREFIX}/metrics/devices/${encodeURIComponent(deviceId)}/history`,
|
|
||||||
{
|
/** 日汇总统计 */
|
||||||
params: {
|
export function fetchHostHardwareStatistics(deviceId: string, startDate?: string, endDate?: string) {
|
||||||
metric_name: metricName,
|
return request.get<HostHardwareApiEnvelope<HostHardwareStatisticsRow[]>>(`${HW_PREFIX}/metrics/statistics`, {
|
||||||
...(startTime ? { start_time: startTime } : {}),
|
params: {
|
||||||
...(endTime ? { end_time: endTime } : {}),
|
device_id: deviceId,
|
||||||
},
|
...(startDate ? { start_date: startDate } : {}),
|
||||||
},
|
...(endDate ? { end_date: endDate } : {}),
|
||||||
)
|
},
|
||||||
}
|
})
|
||||||
|
}
|
||||||
/** 日汇总统计 */
|
|
||||||
export function fetchHostHardwareStatistics(
|
/**
|
||||||
deviceId: string,
|
* 合并 API metrics 与 raw_data 兜底(无时序库时 metrics 可能为空)
|
||||||
startDate?: string,
|
*/
|
||||||
endDate?: string,
|
export function normalizeHostHardwareMetrics(
|
||||||
) {
|
status: HostHardwareStatus | null | undefined,
|
||||||
return request.get<HostHardwareApiEnvelope<HostHardwareStatisticsRow[]>>(
|
metricsFromApi: HostHardwareMetricsRow[] | null | undefined
|
||||||
`${HW_PREFIX}/metrics/statistics`,
|
): NormalizedHostHardwareMetric[] {
|
||||||
{
|
const fromApi = metricsFromApi ?? []
|
||||||
params: {
|
if (fromApi.length > 0) {
|
||||||
device_id: deviceId,
|
return fromApi.map((m) => ({
|
||||||
...(startDate ? { start_date: startDate } : {}),
|
name: m.metric_name,
|
||||||
...(endDate ? { end_date: endDate } : {}),
|
type: m.metric_type,
|
||||||
},
|
value: m.metric_value,
|
||||||
},
|
unit: m.unit ?? '',
|
||||||
)
|
status: m.status ?? 'ok',
|
||||||
}
|
threshold: m.threshold,
|
||||||
|
location: m.location,
|
||||||
/**
|
}))
|
||||||
* 合并 API metrics 与 raw_data 兜底(无时序库时 metrics 可能为空)
|
}
|
||||||
*/
|
const raw = status?.raw_data
|
||||||
export function normalizeHostHardwareMetrics(
|
if (!raw || typeof raw !== 'string') return []
|
||||||
status: HostHardwareStatus | null | undefined,
|
try {
|
||||||
metricsFromApi: HostHardwareMetricsRow[] | null | undefined,
|
const parsed = JSON.parse(raw) as RawCollectionRoot
|
||||||
): NormalizedHostHardwareMetric[] {
|
const arr = parsed.metrics
|
||||||
const fromApi = metricsFromApi ?? []
|
if (!Array.isArray(arr)) return []
|
||||||
if (fromApi.length > 0) {
|
return arr
|
||||||
return fromApi.map((m) => ({
|
.map((m) => ({
|
||||||
name: m.metric_name,
|
name: String(m.name ?? ''),
|
||||||
type: m.metric_type,
|
type: String(m.type ?? ''),
|
||||||
value: m.metric_value,
|
value: typeof m.value === 'number' ? m.value : Number(m.value) || 0,
|
||||||
unit: m.unit ?? '',
|
unit: String(m.unit ?? ''),
|
||||||
status: m.status ?? 'ok',
|
status: String(m.status ?? 'ok'),
|
||||||
threshold: m.threshold,
|
threshold: m.threshold,
|
||||||
location: m.location,
|
location: m.location ? String(m.location) : undefined,
|
||||||
}))
|
}))
|
||||||
}
|
.filter((m) => m.name || m.type)
|
||||||
const raw = status?.raw_data
|
} catch {
|
||||||
if (!raw || typeof raw !== 'string') return []
|
return []
|
||||||
try {
|
}
|
||||||
const parsed = JSON.parse(raw) as RawCollectionRoot
|
}
|
||||||
const arr = parsed.metrics
|
|
||||||
if (!Array.isArray(arr)) return []
|
|
||||||
return arr
|
|
||||||
.map((m) => ({
|
|
||||||
name: String(m.name ?? ''),
|
|
||||||
type: String(m.type ?? ''),
|
|
||||||
value: typeof m.value === 'number' ? m.value : Number(m.value) || 0,
|
|
||||||
unit: String(m.unit ?? ''),
|
|
||||||
status: String(m.status ?? 'ok'),
|
|
||||||
threshold: m.threshold,
|
|
||||||
location: m.location ? String(m.location) : undefined,
|
|
||||||
}))
|
|
||||||
.filter((m) => m.name || m.type)
|
|
||||||
} catch {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user