838 lines
27 KiB
PHP
838 lines
27 KiB
PHP
<?php
|
||
require_once __DIR__ . '/app/db_helper.php';
|
||
require_once __DIR__ . '/app/logger.php';
|
||
|
||
/**
|
||
* 腾讯云API适配器
|
||
* 支持CVM云服务器和轻量应用服务器(Lighthouse)
|
||
*/
|
||
|
||
/**
|
||
* 生成腾讯云API签名 (HMAC-SHA1)
|
||
*/
|
||
function generateTencentSignature($method, $host, $uri, $params, $secretKey) {
|
||
// 按参数名排序
|
||
ksort($params);
|
||
|
||
// 构建签名字符串
|
||
$signStr = $method . $host . $uri . '?';
|
||
$queryStr = '';
|
||
foreach ($params as $key => $value) {
|
||
if ($queryStr !== '') {
|
||
$queryStr .= '&';
|
||
}
|
||
$queryStr .= rawurlencode($key) . '=' . rawurlencode($value);
|
||
}
|
||
$signStr .= $queryStr;
|
||
|
||
// 计算HMAC-SHA1签名
|
||
$signature = base64_encode(hash_hmac('sha1', $signStr, $secretKey, true));
|
||
|
||
return $signature;
|
||
}
|
||
|
||
/**
|
||
* 发送腾讯云API请求
|
||
* @param string $configId 配置ID
|
||
* @param string $service 服务类型: cvm 或 lighthouse
|
||
* @param string $action API动作
|
||
* @param array $params 请求参数
|
||
* @param string $region 区域(可选,默认使用配置中的区域)
|
||
* @return array|null
|
||
*/
|
||
function tencentApiRequest($configId, $service, $action, $params = [], $region = null) {
|
||
$db = getVpsDB();
|
||
$config = $db->queryOne('SELECT * FROM configs WHERE id = ?', [$configId]);
|
||
|
||
if (!$config) {
|
||
Logger::error("配置ID {$configId} 不存在", 'tencentApiRequest');
|
||
return null;
|
||
}
|
||
|
||
$secretId = $config['account'];
|
||
$secretKey = $config['api_key'];
|
||
|
||
// 确定使用的区域
|
||
if (!$region) {
|
||
$region = 'ap-guangzhou';
|
||
}
|
||
|
||
// 确定API域名
|
||
$host = ($service === 'lighthouse') ? 'lighthouse.tencentcloudapi.com' : 'cvm.tencentcloudapi.com';
|
||
|
||
// 公共参数
|
||
$commonParams = [
|
||
'Action' => $action,
|
||
'Version' => ($service === 'lighthouse') ? '2020-03-24' : '2017-03-12',
|
||
'Region' => $region,
|
||
'SecretId' => $secretId,
|
||
'Timestamp' => time(),
|
||
'Nonce' => rand(10000, 99999),
|
||
];
|
||
|
||
// 合并参数
|
||
$allParams = array_merge($commonParams, $params);
|
||
|
||
// 生成签名
|
||
$signature = generateTencentSignature(
|
||
'GET',
|
||
$host,
|
||
'/',
|
||
$allParams,
|
||
$secretKey
|
||
);
|
||
|
||
$allParams['Signature'] = $signature;
|
||
|
||
// 构建URL
|
||
$url = 'https://' . $host . '/?' . http_build_query($allParams);
|
||
|
||
// 发送请求
|
||
$ch = curl_init();
|
||
curl_setopt($ch, CURLOPT_URL, $url);
|
||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
|
||
|
||
$response = curl_exec($ch);
|
||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||
$curlError = curl_error($ch);
|
||
curl_close($ch);
|
||
|
||
if ($curlError) {
|
||
Logger::error("cURL错误: {$curlError}", 'tencentApiRequest');
|
||
return ['status' => 0, 'error' => $curlError];
|
||
}
|
||
|
||
if ($httpCode !== 200) {
|
||
Logger::error("HTTP请求失败: {$httpCode}", 'tencentApiRequest');
|
||
return ['status' => $httpCode, 'error' => 'HTTP请求失败'];
|
||
}
|
||
|
||
$result = json_decode($response, true);
|
||
|
||
if (!$result) {
|
||
Logger::error("JSON解析失败", 'tencentApiRequest');
|
||
return ['status' => 500, 'error' => '响应解析失败'];
|
||
}
|
||
|
||
// 检查响应
|
||
if (isset($result['Response']['Error'])) {
|
||
$error = $result['Response']['Error'];
|
||
Logger::error("API错误: {$error['Code']} - {$error['Message']}", 'tencentApiRequest');
|
||
return ['status' => 400, 'error' => $error['Message'], 'code' => $error['Code']];
|
||
}
|
||
|
||
return ['status' => 200, 'data' => $result['Response'], 'service' => $service, 'region' => $region];
|
||
}
|
||
|
||
/**
|
||
* 获取所有可用区域列表
|
||
*/
|
||
function getTencentRegions($configId, $service) {
|
||
return [
|
||
'ap-beijing', // 北京
|
||
'ap-chengdu', // 成都
|
||
'ap-guangzhou', // 广州
|
||
'ap-hongkong', // 香港
|
||
'ap-nanjing', // 南京
|
||
'ap-shanghai', // 上海
|
||
'ap-singapore', // 新加坡
|
||
'ap-tokyo', // 东京
|
||
'eu-frankfurt', // 法兰克福
|
||
'na-siliconvalley', // 硅谷
|
||
'na-toronto', // 多伦多
|
||
];
|
||
}
|
||
|
||
/**
|
||
* 获取CVM实例列表(单个区域)
|
||
*/
|
||
function tencentGetCvmList($configId, $region, $offset = 0, $limit = 100) {
|
||
$params = [
|
||
'Offset' => $offset,
|
||
'Limit' => $limit,
|
||
];
|
||
|
||
return tencentApiRequest($configId, 'cvm', 'DescribeInstances', $params, $region);
|
||
}
|
||
|
||
/**
|
||
* 获取轻量应用服务器列表(单个区域)
|
||
*/
|
||
function tencentGetLighthouseList($configId, $region, $offset = 0, $limit = 100) {
|
||
$params = [
|
||
'Offset' => $offset,
|
||
'Limit' => $limit,
|
||
];
|
||
|
||
return tencentApiRequest($configId, 'lighthouse', 'DescribeInstances', $params, $region);
|
||
}
|
||
|
||
/**
|
||
* 获取CVM实例详细信息
|
||
*/
|
||
function tencentGetCvmDetails($configId, $instanceId, $region = null, $updateDb = true) {
|
||
$params = [
|
||
'InstanceIds.0' => $instanceId,
|
||
];
|
||
|
||
$result = tencentApiRequest($configId, 'cvm', 'DescribeInstances', $params, $region);
|
||
|
||
// 如果获取成功且需要更新数据库
|
||
if ($updateDb && $result && isset($result['status']) && $result['status'] === 200) {
|
||
$instances = $result['data']['InstanceSet'] ?? [];
|
||
|
||
if (!empty($instances)) {
|
||
updateCvmToDatabase($configId, $instances[0], 'cvm');
|
||
}
|
||
}
|
||
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* 获取轻量应用服务器详细信息
|
||
*/
|
||
function tencentGetLighthouseDetails($configId, $instanceId, $region = null, $updateDb = true) {
|
||
$params = [
|
||
'InstanceIds.0' => $instanceId,
|
||
];
|
||
|
||
$result = tencentApiRequest($configId, 'lighthouse', 'DescribeInstances', $params, $region);
|
||
|
||
// 如果获取成功且需要更新数据库
|
||
if ($updateDb && $result && isset($result['status']) && $result['status'] === 200) {
|
||
$instances = $result['data']['InstanceSet'] ?? [];
|
||
|
||
if (!empty($instances)) {
|
||
updateCvmToDatabase($configId, $instances[0], 'lighthouse');
|
||
}
|
||
}
|
||
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* 获取CVM实例状态
|
||
*/
|
||
function tencentGetCvmStatus($configId, $instanceId, $region = null, $updateDb = true) {
|
||
$params = [
|
||
'InstanceIds.0' => $instanceId,
|
||
];
|
||
|
||
$result = tencentApiRequest($configId, 'cvm', 'DescribeInstancesStatus', $params, $region);
|
||
|
||
// 如果获取成功且需要更新数据库
|
||
if ($updateDb && $result && isset($result['status']) && $result['status'] === 200) {
|
||
$statusSet = $result['data']['InstanceStatusSet'] ?? [];
|
||
|
||
if (!empty($statusSet)) {
|
||
$statusInfo = $statusSet[0];
|
||
$rawStatus = $statusInfo['InstanceState'] ?? 'UNKNOWN';
|
||
|
||
// 状态映射
|
||
$statusMap = [
|
||
'PENDING' => 'process',
|
||
'LAUNCHING' => 'process',
|
||
'RUNNING' => 'on',
|
||
'STOPPING' => 'process',
|
||
'STOPPED' => 'off',
|
||
'REBOOTING' => 'process',
|
||
'SHUTDOWN' => 'off',
|
||
'TERMINATING' => 'process',
|
||
'UNKNOWN' => 'unknown'
|
||
];
|
||
|
||
$status = $statusMap[$rawStatus] ?? 'unknown';
|
||
|
||
updateVpsStatusInDatabase($configId, $instanceId, $status);
|
||
}
|
||
}
|
||
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* 获取轻量应用服务器状态
|
||
* 注意:轻量服务器没有独立的DescribeInstancesStatus接口,需要使用DescribeInstances
|
||
*/
|
||
function tencentGetLighthouseStatus($configId, $instanceId, $region = null, $updateDb = true) {
|
||
// 轻量服务器使用DescribeInstances接口获取状态
|
||
$params = [
|
||
'InstanceIds.0' => $instanceId,
|
||
];
|
||
|
||
$result = tencentApiRequest($configId, 'lighthouse', 'DescribeInstances', $params, $region);
|
||
|
||
// 如果获取成功且需要更新数据库
|
||
if ($updateDb && $result && isset($result['status']) && $result['status'] === 200) {
|
||
$instances = $result['data']['InstanceSet'] ?? [];
|
||
|
||
if (!empty($instances)) {
|
||
$instanceInfo = $instances[0];
|
||
$rawStatus = $instanceInfo['InstanceState'] ?? 'UNKNOWN';
|
||
|
||
// 状态映射(轻量服务器状态与CVM类似)
|
||
$statusMap = [
|
||
'PENDING' => 'process',
|
||
'LAUNCHING' => 'process',
|
||
'RUNNING' => 'on',
|
||
'STOPPING' => 'process',
|
||
'STOPPED' => 'off',
|
||
'REBOOTING' => 'process',
|
||
'SHUTDOWN' => 'off',
|
||
'TERMINATING' => 'process',
|
||
'UNKNOWN' => 'unknown'
|
||
];
|
||
|
||
$status = $statusMap[$rawStatus] ?? 'unknown';
|
||
|
||
updateVpsStatusInDatabase($configId, $instanceId, $status);
|
||
}
|
||
}
|
||
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* 启动CVM实例
|
||
*/
|
||
function tencentPowerOn($configId, $instanceId, $region = null) {
|
||
// 如果未提供region,从数据库获取
|
||
if (!$region) {
|
||
$listDb = getVpsListDB();
|
||
$vpsInfo = $listDb->queryOne(
|
||
'SELECT domain FROM vps_list WHERE config_id = ? AND vps_id = ?',
|
||
[$configId, $instanceId]
|
||
);
|
||
if ($vpsInfo && !empty($vpsInfo['domain'])) {
|
||
$region = $vpsInfo['domain'];
|
||
} else {
|
||
Logger::error("[tencentPowerOn] 无法从数据库获取 region", 'tencentPowerOn');
|
||
return ['status' => 400, 'error' => '无法获取实例区域信息'];
|
||
}
|
||
}
|
||
|
||
$params = [
|
||
'InstanceIds.0' => $instanceId,
|
||
];
|
||
|
||
$result = tencentApiRequest($configId, 'cvm', 'StartInstances', $params, $region);
|
||
|
||
// 开机操作后立即获取状态并更新数据库
|
||
if ($result && isset($result['status']) && $result['status'] === 200) {
|
||
sleep(2);
|
||
tencentGetCvmStatus($configId, $instanceId, $region, true);
|
||
}
|
||
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* 启动轻量应用服务器
|
||
*/
|
||
function tencentLighthousePowerOn($configId, $instanceId, $region = null) {
|
||
// 如果未提供region,从数据库获取
|
||
if (!$region) {
|
||
$listDb = getVpsListDB();
|
||
$vpsInfo = $listDb->queryOne(
|
||
'SELECT domain FROM vps_list WHERE config_id = ? AND vps_id = ?',
|
||
[$configId, $instanceId]
|
||
);
|
||
if ($vpsInfo && !empty($vpsInfo['domain'])) {
|
||
$region = $vpsInfo['domain'];
|
||
} else {
|
||
Logger::error("[tencentLighthousePowerOn] 无法从数据库获取 region", 'tencentLighthousePowerOn');
|
||
return ['status' => 400, 'error' => '无法获取实例区域信息'];
|
||
}
|
||
}
|
||
|
||
$params = [
|
||
'InstanceIds.0' => $instanceId,
|
||
];
|
||
|
||
$result = tencentApiRequest($configId, 'lighthouse', 'StartInstances', $params, $region);
|
||
|
||
// 开机操作后立即获取状态并更新数据库
|
||
if ($result && isset($result['status']) && $result['status'] === 200) {
|
||
sleep(2);
|
||
tencentGetLighthouseStatus($configId, $instanceId, $region, true);
|
||
}
|
||
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* 停止CVM实例
|
||
*/
|
||
function tencentPowerOff($configId, $instanceId, $region = null) {
|
||
// 如果未提供region,从数据库获取
|
||
if (!$region) {
|
||
$listDb = getVpsListDB();
|
||
$vpsInfo = $listDb->queryOne(
|
||
'SELECT domain FROM vps_list WHERE config_id = ? AND vps_id = ?',
|
||
[$configId, $instanceId]
|
||
);
|
||
if ($vpsInfo && !empty($vpsInfo['domain'])) {
|
||
$region = $vpsInfo['domain'];
|
||
} else {
|
||
Logger::error("[tencentPowerOff] 无法从数据库获取 region", 'tencentPowerOff');
|
||
return ['status' => 400, 'error' => '无法获取实例区域信息'];
|
||
}
|
||
}
|
||
|
||
$params = [
|
||
'InstanceIds.0' => $instanceId,
|
||
];
|
||
|
||
$result = tencentApiRequest($configId, 'cvm', 'StopInstances', $params, $region);
|
||
|
||
// 关机操作后立即获取状态并更新数据库
|
||
if ($result && isset($result['status']) && $result['status'] === 200) {
|
||
sleep(2);
|
||
tencentGetCvmStatus($configId, $instanceId, $region, true);
|
||
}
|
||
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* 停止轻量应用服务器
|
||
*/
|
||
function tencentLighthousePowerOff($configId, $instanceId, $region = null) {
|
||
// 如果未提供region,从数据库获取
|
||
if (!$region) {
|
||
$listDb = getVpsListDB();
|
||
$vpsInfo = $listDb->queryOne(
|
||
'SELECT domain FROM vps_list WHERE config_id = ? AND vps_id = ?',
|
||
[$configId, $instanceId]
|
||
);
|
||
if ($vpsInfo && !empty($vpsInfo['domain'])) {
|
||
$region = $vpsInfo['domain'];
|
||
} else {
|
||
Logger::error("[tencentLighthousePowerOff] 无法从数据库获取 region", 'tencentLighthousePowerOff');
|
||
return ['status' => 400, 'error' => '无法获取实例区域信息'];
|
||
}
|
||
}
|
||
|
||
$params = [
|
||
'InstanceIds.0' => $instanceId,
|
||
];
|
||
|
||
$result = tencentApiRequest($configId, 'lighthouse', 'StopInstances', $params, $region);
|
||
|
||
// 关机操作后立即获取状态并更新数据库
|
||
if ($result && isset($result['status']) && $result['status'] === 200) {
|
||
sleep(2);
|
||
tencentGetLighthouseStatus($configId, $instanceId, $region, true);
|
||
}
|
||
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* 重启CVM实例
|
||
*/
|
||
function tencentReboot($configId, $instanceId, $region = null) {
|
||
// 如果未提供region,从数据库获取
|
||
if (!$region) {
|
||
$listDb = getVpsListDB();
|
||
$vpsInfo = $listDb->queryOne(
|
||
'SELECT domain FROM vps_list WHERE config_id = ? AND vps_id = ?',
|
||
[$configId, $instanceId]
|
||
);
|
||
if ($vpsInfo && !empty($vpsInfo['domain'])) {
|
||
$region = $vpsInfo['domain'];
|
||
} else {
|
||
Logger::error("[tencentReboot] 无法从数据库获取 region", 'tencentReboot');
|
||
return ['status' => 400, 'error' => '无法获取实例区域信息'];
|
||
}
|
||
}
|
||
|
||
$params = [
|
||
'InstanceIds.0' => $instanceId,
|
||
];
|
||
|
||
$result = tencentApiRequest($configId, 'cvm', 'RebootInstances', $params, $region);
|
||
|
||
// 重启操作后立即获取状态并更新数据库
|
||
if ($result && isset($result['status']) && $result['status'] === 200) {
|
||
sleep(3);
|
||
tencentGetCvmStatus($configId, $instanceId, $region, true);
|
||
}
|
||
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* 重启轻量应用服务器
|
||
*/
|
||
function tencentLighthouseReboot($configId, $instanceId, $region = null) {
|
||
// 如果未提供region,从数据库获取
|
||
if (!$region) {
|
||
$listDb = getVpsListDB();
|
||
$vpsInfo = $listDb->queryOne(
|
||
'SELECT domain FROM vps_list WHERE config_id = ? AND vps_id = ?',
|
||
[$configId, $instanceId]
|
||
);
|
||
if ($vpsInfo && !empty($vpsInfo['domain'])) {
|
||
$region = $vpsInfo['domain'];
|
||
} else {
|
||
Logger::error("[tencentLighthouseReboot] 无法从数据库获取 region", 'tencentLighthouseReboot');
|
||
return ['status' => 400, 'error' => '无法获取实例区域信息'];
|
||
}
|
||
}
|
||
|
||
$params = [
|
||
'InstanceIds.0' => $instanceId,
|
||
];
|
||
|
||
$result = tencentApiRequest($configId, 'lighthouse', 'RebootInstances', $params, $region);
|
||
|
||
// 重启操作后立即获取状态并更新数据库
|
||
if ($result && isset($result['status']) && $result['status'] === 200) {
|
||
sleep(3);
|
||
tencentGetLighthouseStatus($configId, $instanceId, $region, true);
|
||
}
|
||
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* 将CVM/轻量服务器信息更新到数据库
|
||
*/
|
||
function updateCvmToDatabase($configId, $instance, $serviceType) {
|
||
$listDb = getVpsListDB();
|
||
|
||
$vpsId = $instance['InstanceId'];
|
||
$region = $instance['Placement']['Zone'] ?? '';
|
||
|
||
// 提取CPU和内存信息
|
||
$cpuCores = $instance['CPU'] ?? null;
|
||
// 注意:腾讯云API返回的Memory单位已经是GB,不需要转换
|
||
$memorySize = isset($instance['Memory']) ? $instance['Memory'] . 'G' : null;
|
||
|
||
// 提取系统盘信息
|
||
$diskSize = null;
|
||
if (isset($instance['SystemDisk']) && isset($instance['SystemDisk']['DiskSize'])) {
|
||
$diskSize = $instance['SystemDisk']['DiskSize'] . 'G';
|
||
}
|
||
|
||
// 提取带宽信息
|
||
$bandwidth = null;
|
||
// CVM和轻量服务器都使用InternetAccessible.InternetMaxBandwidthOut
|
||
if (isset($instance['InternetAccessible']) && isset($instance['InternetAccessible']['InternetMaxBandwidthOut'])) {
|
||
$bandwidth = $instance['InternetAccessible']['InternetMaxBandwidthOut'] . 'Mbps';
|
||
}
|
||
|
||
// 提取操作系统信息
|
||
$osType = $instance['OsName'] ?? ($instance['Platform'] ?? null);
|
||
|
||
// 提取IP地址
|
||
$ipAddress = null;
|
||
if ($serviceType === 'cvm') {
|
||
if (isset($instance['PublicIpAddresses']) && !empty($instance['PublicIpAddresses'])) {
|
||
$ipAddress = $instance['PublicIpAddresses'][0];
|
||
}
|
||
} else {
|
||
// 轻量服务器的公网IP
|
||
if (isset($instance['PublicAddresses']) && !empty($instance['PublicAddresses'])) {
|
||
$ipAddress = $instance['PublicAddresses'][0];
|
||
}
|
||
}
|
||
|
||
// 提取实例名称
|
||
$productName = $instance['InstanceName'] ?? null;
|
||
|
||
// 提取到期时间
|
||
$nextduedate = null;
|
||
if (isset($instance['ExpiredTime'])) {
|
||
$nextduedate = strtotime($instance['ExpiredTime']);
|
||
}
|
||
|
||
// 检查记录是否存在
|
||
$existing = $listDb->queryOne(
|
||
'SELECT id FROM vps_list WHERE config_id = ? AND vps_id = ?',
|
||
[$configId, $vpsId]
|
||
);
|
||
|
||
if ($existing) {
|
||
// 更新现有记录
|
||
$listDb->execute(
|
||
'UPDATE vps_list SET domain = ?, ip_address = ?, product_name = ?, cpu_cores = ?, memory_size = ?, disk_size = ?, bandwidth = ?, os_type = ?, nextduedate = ?, last_check = CURRENT_TIMESTAMP WHERE id = ?',
|
||
[
|
||
$region,
|
||
$ipAddress,
|
||
$productName,
|
||
$cpuCores,
|
||
$memorySize,
|
||
$diskSize,
|
||
$bandwidth,
|
||
$osType,
|
||
$nextduedate,
|
||
$existing['id']
|
||
]
|
||
);
|
||
Logger::info("[updateCvmToDatabase] {$serviceType} {$vpsId} 详细信息已更新", 'updateCvmToDatabase');
|
||
} else {
|
||
// 插入新记录
|
||
$listDb->execute(
|
||
'INSERT INTO vps_list (config_id, vps_id, domain, ip_address, product_name, cpu_cores, memory_size, disk_size, bandwidth, os_type, status, nextduedate, last_check) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, CURRENT_TIMESTAMP)',
|
||
[
|
||
$configId,
|
||
$vpsId,
|
||
$region,
|
||
$ipAddress,
|
||
$productName,
|
||
$cpuCores,
|
||
$memorySize,
|
||
$diskSize,
|
||
$bandwidth,
|
||
$osType,
|
||
$nextduedate
|
||
]
|
||
);
|
||
Logger::info("[updateCvmToDatabase] {$serviceType} {$vpsId} 新记录已插入", 'updateCvmToDatabase');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 更新VPS状态到数据库
|
||
*/
|
||
function updateVpsStatusInDatabase($configId, $vpsId, $status) {
|
||
$listDb = getVpsListDB();
|
||
|
||
$vpsInfo = $listDb->queryOne(
|
||
'SELECT id FROM vps_list WHERE config_id = ? AND vps_id = ?',
|
||
[$configId, $vpsId]
|
||
);
|
||
|
||
if ($vpsInfo) {
|
||
$listDb->execute(
|
||
'UPDATE vps_list SET status = ?, last_check = CURRENT_TIMESTAMP WHERE id = ?',
|
||
[$status, $vpsInfo['id']]
|
||
);
|
||
Logger::info("[updateVpsStatusInDatabase] VPS {$vpsId} 状态已更新为: {$status}", 'updateVpsStatusInDatabase');
|
||
} else {
|
||
$listDb->execute(
|
||
'INSERT INTO vps_list (config_id, vps_id, status, last_check) VALUES (?, ?, ?, CURRENT_TIMESTAMP)',
|
||
[$configId, $vpsId, $status]
|
||
);
|
||
Logger::info("[updateVpsStatusInDatabase] VPS {$vpsId} 新记录已插入,状态: {$status}", 'updateVpsStatusInDatabase');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 刷新指定配置的CVM列表(遍历所有区域)
|
||
*/
|
||
function refreshTencentCvmListForConfig($configId) {
|
||
$db = getVpsDB();
|
||
$config = $db->queryOne('SELECT * FROM configs WHERE id = ?', [$configId]);
|
||
|
||
if (!$config || $config['site_type'] !== 'tencent') {
|
||
return false;
|
||
}
|
||
|
||
// 先获取区域列表
|
||
$regions = getTencentRegions($configId, 'cvm');
|
||
$totalInstances = 0;
|
||
|
||
Logger::info("[refreshTencentCvmListForConfig] 开始遍历所有区域获取CVM列表", 'refreshTencentCvmListForConfig');
|
||
|
||
foreach ($regions as $region) {
|
||
try {
|
||
$result = tencentGetCvmList($configId, $region);
|
||
|
||
if ($result && isset($result['status']) && $result['status'] === 200) {
|
||
$instances = $result['data']['InstanceSet'] ?? [];
|
||
|
||
if (!empty($instances)) {
|
||
Logger::info("[refreshTencentCvmListForConfig] 区域 {$region} 找到 " . count($instances) . " 台CVM", 'refreshTencentCvmListForConfig');
|
||
|
||
foreach ($instances as $instance) {
|
||
updateCvmToDatabase($configId, $instance, 'cvm');
|
||
|
||
// 获取状态
|
||
tencentGetCvmStatus($configId, $instance['InstanceId'], $region, true);
|
||
|
||
$totalInstances++;
|
||
|
||
// 避免频繁请求
|
||
usleep(300000); // 300毫秒
|
||
}
|
||
}
|
||
} else {
|
||
Logger::warning("[refreshTencentCvmListForConfig] 区域 {$region} 获取失败: " . ($result['msg'] ?? '未知错误'), 'refreshTencentCvmListForConfig');
|
||
}
|
||
} catch (Exception $e) {
|
||
Logger::error("[refreshTencentCvmListForConfig] 区域 {$region} 异常: " . $e->getMessage(), 'refreshTencentCvmListForConfig');
|
||
}
|
||
|
||
// 区域之间稍作延迟
|
||
usleep(500000); // 500毫秒
|
||
}
|
||
|
||
Logger::info("[refreshTencentCvmListForConfig] CVM列表刷新完成,共获取 {$totalInstances} 台实例", 'refreshTencentCvmListForConfig');
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 刷新指定配置的轻量应用服务器列表(遍历所有区域)
|
||
*/
|
||
function refreshTencentLighthouseListForConfig($configId) {
|
||
$db = getVpsDB();
|
||
$config = $db->queryOne('SELECT * FROM configs WHERE id = ?', [$configId]);
|
||
|
||
if (!$config || $config['site_type'] !== 'tencent') {
|
||
return false;
|
||
}
|
||
|
||
// 先获取区域列表
|
||
$regions = getTencentRegions($configId, 'lighthouse');
|
||
$totalInstances = 0;
|
||
|
||
Logger::info("[refreshTencentLighthouseListForConfig] 开始遍历所有区域获取轻量应用服务器列表", 'refreshTencentLighthouseListForConfig');
|
||
|
||
foreach ($regions as $region) {
|
||
try {
|
||
$result = tencentGetLighthouseList($configId, $region);
|
||
|
||
if ($result && isset($result['status']) && $result['status'] === 200) {
|
||
$instances = $result['data']['InstanceSet'] ?? [];
|
||
|
||
if (!empty($instances)) {
|
||
Logger::info("[refreshTencentLighthouseListForConfig] 区域 {$region} 找到 " . count($instances) . " 台轻量服务器", 'refreshTencentLighthouseListForConfig');
|
||
|
||
foreach ($instances as $instance) {
|
||
updateCvmToDatabase($configId, $instance, 'lighthouse');
|
||
|
||
// 获取状态
|
||
tencentGetLighthouseStatus($configId, $instance['InstanceId'], $region, true);
|
||
|
||
$totalInstances++;
|
||
|
||
// 避免频繁请求
|
||
usleep(300000); // 300毫秒
|
||
}
|
||
}
|
||
} else {
|
||
Logger::warning("[refreshTencentLighthouseListForConfig] 区域 {$region} 获取失败: " . ($result['msg'] ?? '未知错误'), 'refreshTencentLighthouseListForConfig');
|
||
}
|
||
} catch (Exception $e) {
|
||
Logger::error("[refreshTencentLighthouseListForConfig] 区域 {$region} 异常: " . $e->getMessage(), 'refreshTencentLighthouseListForConfig');
|
||
}
|
||
|
||
// 区域之间稍作延迟
|
||
usleep(500000); // 500毫秒
|
||
}
|
||
|
||
Logger::info("[refreshTencentLighthouseListForConfig] 轻量应用服务器列表刷新完成,共获取 {$totalInstances} 台实例", 'refreshTencentLighthouseListForConfig');
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 刷新所有腾讯云配置的实例列表(CVM + 轻量)
|
||
*/
|
||
function refreshAllTencentVpsLists() {
|
||
$db = getVpsDB();
|
||
$configs = $db->query('SELECT * FROM configs WHERE site_type = ?', ['tencent']);
|
||
|
||
$successCount = 0;
|
||
|
||
foreach ($configs as $config) {
|
||
// 刷新CVM列表
|
||
if (refreshTencentCvmListForConfig($config['id'])) {
|
||
$successCount++;
|
||
}
|
||
|
||
// 刷新轻量应用服务器列表
|
||
if (refreshTencentLighthouseListForConfig($config['id'])) {
|
||
$successCount++;
|
||
}
|
||
}
|
||
|
||
return $successCount;
|
||
}
|
||
|
||
/**
|
||
* 根据实例ID判断是CVM还是轻量服务器,并执行相应操作
|
||
*/
|
||
function tencentGetInstanceType($instanceId) {
|
||
// CVM实例ID格式: ins-xxxxxxxx
|
||
// 轻量服务器实例ID格式: lhins-xxxxxxxx
|
||
if (strpos($instanceId, 'lhins-') === 0) {
|
||
return 'lighthouse';
|
||
}
|
||
return 'cvm';
|
||
}
|
||
|
||
/**
|
||
* 智能开机(自动识别实例类型)
|
||
*/
|
||
function tencentSmartPowerOn($configId, $instanceId, $region = null) {
|
||
$type = tencentGetInstanceType($instanceId);
|
||
|
||
if ($type === 'lighthouse') {
|
||
return tencentLighthousePowerOn($configId, $instanceId, $region);
|
||
} else {
|
||
return tencentPowerOn($configId, $instanceId, $region);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 智能关机(自动识别实例类型)
|
||
*/
|
||
function tencentSmartPowerOff($configId, $instanceId, $region = null) {
|
||
$type = tencentGetInstanceType($instanceId);
|
||
|
||
if ($type === 'lighthouse') {
|
||
return tencentLighthousePowerOff($configId, $instanceId, $region);
|
||
} else {
|
||
return tencentPowerOff($configId, $instanceId, $region);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 智能重启(自动识别实例类型)
|
||
*/
|
||
function tencentSmartReboot($configId, $instanceId, $region = null) {
|
||
$type = tencentGetInstanceType($instanceId);
|
||
|
||
if ($type === 'lighthouse') {
|
||
return tencentLighthouseReboot($configId, $instanceId, $region);
|
||
} else {
|
||
return tencentReboot($configId, $instanceId, $region);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 智能获取状态(自动识别实例类型)
|
||
*/
|
||
function tencentSmartGetStatus($configId, $instanceId, $region = null, $updateDb = true) {
|
||
$type = tencentGetInstanceType($instanceId);
|
||
|
||
if ($type === 'lighthouse') {
|
||
return tencentGetLighthouseStatus($configId, $instanceId, $region, $updateDb);
|
||
} else {
|
||
return tencentGetCvmStatus($configId, $instanceId, $region, $updateDb);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 智能获取详情(自动识别实例类型)
|
||
*/
|
||
function tencentSmartGetDetails($configId, $instanceId, $region = null, $updateDb = true) {
|
||
$type = tencentGetInstanceType($instanceId);
|
||
|
||
if ($type === 'lighthouse') {
|
||
return tencentGetLighthouseDetails($configId, $instanceId, $region, $updateDb);
|
||
} else {
|
||
return tencentGetCvmDetails($configId, $instanceId, $region, $updateDb);
|
||
}
|
||
}
|
||
?>
|