VPSHUB/aliyun.php

939 lines
32 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
require_once __DIR__ . '/app/db_helper.php';
require_once __DIR__ . '/app/logger.php';
/**
* 阿里云ECS和轻量应用服务器API适配器
* 支持ECS云服务器和轻量应用服务器(SWAS)的查询和管理
*/
/**
* URL编码函数RFC3986规范
*/
function aliyunEncode($str) {
$res = urlencode($str);
$res = preg_replace('/\+/', '%20', $res);
$res = preg_replace('/\*/', '%2A', $res);
$res = preg_replace('/%7E/', '~', $res);
return $res;
}
/**
* 生成阿里云API签名 (HMAC-SHA1)
*/
function generateAliyunSignature($method, $params, $secretKey) {
// 按参数名排序
ksort($params);
// 构建规范化请求字符串
$canonicalizedQueryString = '';
foreach ($params as $key => $value) {
if ($canonicalizedQueryString !== '') {
$canonicalizedQueryString .= '&';
}
$canonicalizedQueryString .= aliyunEncode($key) . '=' . aliyunEncode($value);
}
// 构造待签名字符串
$stringToSign = $method . '&%2F&' . aliyunEncode($canonicalizedQueryString);
// 计算HMAC-SHA1签名
$signature = base64_encode(hash_hmac('sha1', $stringToSign, $secretKey . '&', true));
return $signature;
}
/**
* 发送阿里云API请求
* @param string $configId 配置ID
* @param string $action API动作
* @param array $params 请求参数
* @param string $region 区域
* @param string $serviceType 服务类型: ecs 或 swas
* @return array|null
*/
function aliyunApiRequest($configId, $action, $params = [], $region = 'cn-hangzhou', $serviceType = 'ecs') {
$db = getVpsDB();
$config = $db->queryOne('SELECT * FROM configs WHERE id = ?', [$configId]);
if (!$config) {
Logger::error("配置ID {$configId} 不存在", 'aliyunApiRequest');
return null;
}
$accessKeyId = $config['account'];
$accessKeySecret = $config['api_key'];
Logger::debug("[aliyunApiRequest] Config ID: {$configId}, AccessKeyId: " . substr($accessKeyId, 0, 8) . "***", 'aliyunApiRequest');
// 确定API域名
if (!$region || empty($region)) {
Logger::error("Region参数为空无法构建API域名", 'aliyunApiRequest');
return ['status' => 400, 'error' => 'Region参数为空'];
}
if ($serviceType === 'swas') {
$host = 'swas.' . $region . '.aliyuncs.com';
} else {
$host = 'ecs.' . $region . '.aliyuncs.com';
}
// 公共参数
$commonParams = [
'Action' => $action,
'Version' => ($serviceType === 'swas') ? '2020-06-01' : '2014-05-26',
'Format' => 'JSON',
'AccessKeyId' => $accessKeyId,
'SignatureMethod' => 'HMAC-SHA1',
'SignatureVersion' => '1.0',
'SignatureNonce' => uniqid(),
'Timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
'RegionId' => $region,
];
// 合并参数
$allParams = array_merge($commonParams, $params);
// 生成签名
$signature = generateAliyunSignature(
'GET',
$allParams,
$accessKeySecret
);
$allParams['Signature'] = $signature;
// 构建URL
$url = 'https://' . $host . '/?' . http_build_query($allParams);
Logger::debug("[aliyunApiRequest] URL: {$url}", 'aliyunApiRequest');
Logger::debug("[aliyunApiRequest] Action: {$action}, Region: {$region}, ServiceType: {$serviceType}", 'aliyunApiRequest');
// 发送请求
$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}", 'aliyunApiRequest');
return ['status' => 0, 'error' => $curlError];
}
if ($httpCode !== 200) {
Logger::error("HTTP请求失败: {$httpCode}, 响应: {$response}", 'aliyunApiRequest');
// 尝试解析错误响应
$errorResult = json_decode($response, true);
if ($errorResult && isset($errorResult['Message'])) {
return ['status' => $httpCode, 'error' => $errorResult['Message'], 'code' => $errorResult['Code'] ?? 'Unknown'];
}
return ['status' => $httpCode, 'error' => 'HTTP请求失败 (' . $httpCode . ')'];
}
$result = json_decode($response, true);
if (!$result) {
Logger::error("JSON解析失败", 'aliyunApiRequest');
return ['status' => 500, 'error' => '响应解析失败'];
}
// 检查响应
if (isset($result['Code'])) {
Logger::error("API错误: {$result['Code']} - {$result['Message']}", 'aliyunApiRequest');
return ['status' => 400, 'error' => $result['Message'], 'code' => $result['Code']];
}
return ['status' => 200, 'data' => $result, 'region' => $region, 'service_type' => $serviceType];
}
/**
* 获取所有可用区域列表ECS
*/
function getAliyunRegions($configId) {
return [
'cn-qingdao', // 华北1青岛
'cn-beijing', // 华北2北京
'cn-zhangjiakou', // 华北3张家口
'cn-huhehaote', // 华北5呼和浩特
'cn-wulanchabu', // 华北6乌兰察布
'cn-hangzhou', // 华东1杭州
'cn-shanghai', // 华东2上海
'cn-nanjing', // 华东5南京
'cn-fuzhou', // 华东6福州
'cn-shenzhen', // 华南1深圳
'cn-heyuan', // 华南2河源
'cn-guangzhou', // 华南3广州
'cn-chengdu', // 西南1成都
'cn-hongkong', // 中国香港
'ap-southeast-1', // 新加坡
'ap-southeast-5', // 印度尼西亚(雅加达)
'ap-northeast-1', // 日本(东京)
'ap-northeast-2', // 韩国(首尔)
'ap-southeast-3', // 马来西亚(吉隆坡)
'ap-southeast-6', // 菲律宾(马尼拉)
'ap-southeast-7', // 泰国(曼谷)
'us-west-1', // 美国(硅谷)
'us-east-1', // 美国(弗吉尼亚)
'eu-central-1', // 德国(法兰克福)
'eu-west-1', // 英国(伦敦)
'me-east-1', // 阿联酋(迪拜)
'me-central-1', // 沙特(利雅得)
];
}
/**
* 获取轻量应用服务器可用区域列表
*/
function getAliyunSwasRegions($configId) {
return [
'cn-qingdao', // 华北1青岛
'cn-beijing', // 华北2北京
'cn-zhangjiakou', // 华北3张家口
'cn-huhehaote', // 华北5呼和浩特
'cn-wulanchabu', // 华北6乌兰察布
'cn-hangzhou', // 华东1杭州
'cn-shanghai', // 华东2上海
'cn-nanjing', // 华东5南京
'cn-fuzhou', // 华东6福州
'cn-shenzhen', // 华南1深圳
'cn-heyuan', // 华南2河源
'cn-guangzhou', // 华南3广州
'cn-chengdu', // 西南1成都
'cn-hongkong', // 中国香港
'ap-southeast-1', // 新加坡
'ap-northeast-1', // 日本(东京)
'us-west-1', // 美国(硅谷)
'eu-central-1', // 德国(法兰克福)
];
}
/**
* 获取ECS实例列表单个区域
*/
function aliyunGetEcsList($configId, $region, $maxResults = 100, $nextToken = null) {
$params = [
'MaxResults' => $maxResults,
];
if ($nextToken) {
$params['NextToken'] = $nextToken;
}
return aliyunApiRequest($configId, 'DescribeInstances', $params, $region, 'ecs');
}
/**
* 获取轻量应用服务器实例列表(单个区域)
*/
function aliyunGetSwasList($configId, $region, $pageNumber = 1, $pageSize = 100) {
$params = [
'PageNumber' => $pageNumber,
'PageSize' => $pageSize,
];
return aliyunApiRequest($configId, 'ListInstances', $params, $region, 'swas');
}
/**
* 获取ECS实例详细信息
*/
function aliyunGetEcsDetails($configId, $instanceId, $region = null, $updateDb = true) {
$params = [
'InstanceIds' => json_encode([$instanceId]),
];
$result = aliyunApiRequest($configId, 'DescribeInstances', $params, $region, 'ecs');
// 如果获取成功且需要更新数据库
if ($updateDb && $result && isset($result['status']) && $result['status'] === 200) {
$instances = $result['data']['Instances']['Instance'] ?? [];
if (!empty($instances)) {
updateAliyunEcsToDatabase($configId, $instances[0]);
}
}
return $result;
}
/**
* 获取轻量应用服务器实例详细信息
*/
function aliyunGetSwasDetails($configId, $instanceId, $region = null, $updateDb = true) {
$params = [
'InstanceIds' => json_encode([$instanceId]),
];
$result = aliyunApiRequest($configId, 'ListInstances', $params, $region, 'swas');
// 如果获取成功且需要更新数据库
if ($updateDb && $result && isset($result['status']) && $result['status'] === 200) {
$instances = $result['data']['Instances'] ?? [];
if (!empty($instances)) {
updateAliyunSwasToDatabase($configId, $instances[0]);
}
}
return $result;
}
/**
* 获取ECS实例状态
*/
function aliyunGetEcsStatus($configId, $instanceId, $region = null, $updateDb = true) {
$params = [
'InstanceId.1' => $instanceId,
];
$result = aliyunApiRequest($configId, 'DescribeInstanceStatus', $params, $region, 'ecs');
// 如果获取成功且需要更新数据库
if ($updateDb && $result && isset($result['status']) && $result['status'] === 200) {
$instanceStatusSet = $result['data']['InstanceStatuses']['InstanceStatus'] ?? [];
if (!empty($instanceStatusSet)) {
$statusInfo = $instanceStatusSet[0];
$rawStatus = $statusInfo['Status'] ?? 'UNKNOWN';
// 状态映射
$statusMap = [
'Pending' => 'process',
'Running' => 'on',
'Starting' => 'process',
'Stopping' => 'process',
'Stopped' => 'off',
'Rebooting' => 'process',
'Unknown' => 'unknown'
];
$status = $statusMap[$rawStatus] ?? 'unknown';
updateVpsStatusInDatabaseAliyun($configId, $instanceId, $status);
}
}
return $result;
}
/**
* 获取轻量应用服务器实例状态
*/
function aliyunGetSwasStatus($configId, $instanceId, $region = null, $updateDb = true) {
$params = [
'InstanceIds' => json_encode([$instanceId]),
];
$result = aliyunApiRequest($configId, 'ListInstanceStatus', $params, $region, 'swas');
// 如果获取成功且需要更新数据库
if ($updateDb && $result && isset($result['status']) && $result['status'] === 200) {
$instanceStatusSet = $result['data']['InstanceStatuses'] ?? [];
if (!empty($instanceStatusSet)) {
$statusInfo = $instanceStatusSet[0];
$rawStatus = $statusInfo['Status'] ?? 'UNKNOWN';
// 状态映射
$statusMap = [
'Pending' => 'process',
'Starting' => 'process',
'Running' => 'on',
'Stopping' => 'process',
'Stopped' => 'off',
'Resetting' => 'process',
'Upgrading' => 'process',
'Disabled' => 'off',
'Unknown' => 'unknown'
];
$status = $statusMap[$rawStatus] ?? 'unknown';
updateVpsStatusInDatabaseAliyun($configId, $instanceId, $status);
}
}
return $result;
}
/**
* 启动ECS实例
*/
function aliyunPowerOn($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'];
Logger::info("[aliyunPowerOn] 从数据库获取到 region: {$region}", 'aliyunPowerOn');
} else {
Logger::error("[aliyunPowerOn] 无法从数据库获取 regionconfig_id: {$configId}, instance_id: {$instanceId}", 'aliyunPowerOn');
return ['status' => 400, 'error' => '无法获取实例区域信息'];
}
}
$params = [
'InstanceId' => $instanceId,
];
$result = aliyunApiRequest($configId, 'StartInstance', $params, $region, 'ecs');
// 开机操作后立即获取状态并更新数据库
if ($result && isset($result['status']) && $result['status'] === 200) {
sleep(2);
aliyunGetEcsStatus($configId, $instanceId, $region, true);
}
return $result;
}
/**
* 启动轻量应用服务器
*/
function aliyunSwasPowerOn($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'];
Logger::info("[aliyunSwasPowerOn] 从数据库获取到 region: {$region}", 'aliyunSwasPowerOn');
} else {
Logger::error("[aliyunSwasPowerOn] 无法从数据库获取 regionconfig_id: {$configId}, instance_id: {$instanceId}", 'aliyunSwasPowerOn');
return ['status' => 400, 'error' => '无法获取实例区域信息'];
}
}
$params = [
'InstanceId' => $instanceId,
];
$result = aliyunApiRequest($configId, 'StartInstance', $params, $region, 'swas');
// 开机操作后立即获取状态并更新数据库
if ($result && isset($result['status']) && $result['status'] === 200) {
sleep(2);
aliyunGetSwasStatus($configId, $instanceId, $region, true);
}
return $result;
}
/**
* 停止ECS实例
*/
function aliyunPowerOff($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("[aliyunPowerOff] 无法从数据库获取 region", 'aliyunPowerOff');
return ['status' => 400, 'error' => '无法获取实例区域信息'];
}
}
$params = [
'InstanceId' => $instanceId,
];
$result = aliyunApiRequest($configId, 'StopInstance', $params, $region, 'ecs');
// 关机操作后立即获取状态并更新数据库
if ($result && isset($result['status']) && $result['status'] === 200) {
sleep(2);
aliyunGetEcsStatus($configId, $instanceId, $region, true);
}
return $result;
}
/**
* 停止轻量应用服务器
*/
function aliyunSwasPowerOff($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("[aliyunSwasPowerOff] 无法从数据库获取 region", 'aliyunSwasPowerOff');
return ['status' => 400, 'error' => '无法获取实例区域信息'];
}
}
$params = [
'InstanceId' => $instanceId,
];
$result = aliyunApiRequest($configId, 'StopInstance', $params, $region, 'swas');
// 关机操作后立即获取状态并更新数据库
if ($result && isset($result['status']) && $result['status'] === 200) {
sleep(2);
aliyunGetSwasStatus($configId, $instanceId, $region, true);
}
return $result;
}
/**
* 重启ECS实例
*/
function aliyunReboot($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("[aliyunReboot] 无法从数据库获取 region", 'aliyunReboot');
return ['status' => 400, 'error' => '无法获取实例区域信息'];
}
}
$params = [
'InstanceId' => $instanceId,
];
$result = aliyunApiRequest($configId, 'RebootInstance', $params, $region, 'ecs');
// 重启操作后立即获取状态并更新数据库
if ($result && isset($result['status']) && $result['status'] === 200) {
sleep(3);
aliyunGetEcsStatus($configId, $instanceId, $region, true);
}
return $result;
}
/**
* 重启轻量应用服务器
*/
function aliyunSwasReboot($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("[aliyunSwasReboot] 无法从数据库获取 region", 'aliyunSwasReboot');
return ['status' => 400, 'error' => '无法获取实例区域信息'];
}
}
$params = [
'InstanceId' => $instanceId,
];
$result = aliyunApiRequest($configId, 'RebootInstance', $params, $region, 'swas');
// 重启操作后立即获取状态并更新数据库
if ($result && isset($result['status']) && $result['status'] === 200) {
sleep(3);
aliyunGetSwasStatus($configId, $instanceId, $region, true);
}
return $result;
}
/**
* 将ECS信息更新到数据库
*/
function updateAliyunEcsToDatabase($configId, $instance) {
$listDb = getVpsListDB();
$vpsId = $instance['InstanceId'];
$region = $instance['RegionId'] ?? '';
$zoneId = $instance['ZoneId'] ?? '';
// 提取CPU和内存信息
$cpuCores = $instance['Cpu'] ?? null;
// 注意阿里云API返回的Memory单位是MB需要转换为GB
$memorySize = isset($instance['Memory']) ? round($instance['Memory'] / 1024, 2) . 'G' : null;
// 提取系统盘信息
$diskSize = null;
if (isset($instance['SystemDisk']) && isset($instance['SystemDisk']['Size'])) {
$diskSize = $instance['SystemDisk']['Size'] . 'G';
}
// 提取带宽信息
$bandwidth = null;
if (isset($instance['InternetMaxBandwidthOut'])) {
$bandwidth = $instance['InternetMaxBandwidthOut'] . 'Mbps';
}
// 提取操作系统信息
$osType = $instance['OSName'] ?? ($instance['ImageId'] ?? null);
// 提取IP地址
$ipAddress = null;
if (isset($instance['PublicIpAddress']) && !empty($instance['PublicIpAddress']['IpAddress'])) {
$ipAddress = $instance['PublicIpAddress']['IpAddress'][0];
} elseif (isset($instance['EipAddress']) && isset($instance['EipAddress']['IpAddress'])) {
$ipAddress = $instance['EipAddress']['IpAddress'];
}
// 提取实例名称
$productName = $instance['InstanceName'] ?? null;
// 提取到期时间
$nextduedate = null;
if (isset($instance['ExpiredTime'])) {
$expiredTime = $instance['ExpiredTime'];
if ($expiredTime !== '' && $expiredTime !== null) {
$nextduedate = strtotime($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 = ?',
[
$zoneId,
$ipAddress,
$productName,
$cpuCores,
$memorySize,
$diskSize,
$bandwidth,
$osType,
$nextduedate,
$existing['id']
]
);
Logger::info("[updateAliyunEcsToDatabase] ECS {$vpsId} 详细信息已更新", 'updateAliyunEcsToDatabase');
} 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,
$zoneId,
$ipAddress,
$productName,
$cpuCores,
$memorySize,
$diskSize,
$bandwidth,
$osType,
$nextduedate
]
);
Logger::info("[updateAliyunEcsToDatabase] ECS {$vpsId} 新记录已插入", 'updateAliyunEcsToDatabase');
}
}
/**
* 将轻量应用服务器信息更新到数据库
*/
function updateAliyunSwasToDatabase($configId, $instance) {
$listDb = getVpsListDB();
$vpsId = $instance['InstanceId'];
$region = $instance['RegionId'] ?? '';
// 提取CPU和内存信息从ResourceSpec中获取
$cpuCores = isset($instance['ResourceSpec']) ? $instance['ResourceSpec']['Cpu'] : null;
$memorySize = isset($instance['ResourceSpec']) ? $instance['ResourceSpec']['Memory'] . 'G' : null;
// 提取磁盘信息
$diskSize = isset($instance['ResourceSpec']) ? $instance['ResourceSpec']['DiskSize'] . 'G' : null;
// 提取带宽信息
$bandwidth = isset($instance['ResourceSpec']) ? $instance['ResourceSpec']['Bandwidth'] . 'Mbps' : null;
// 提取操作系统信息
$osType = null;
if (isset($instance['Image'])) {
$osType = $instance['Image']['OsType'] ?? null;
}
// 提取IP地址
$ipAddress = $instance['PublicIpAddress'] ?? null;
// 提取实例名称
$productName = $instance['InstanceName'] ?? null;
// 提取到期时间
$nextduedate = null;
if (isset($instance['ExpiredTime'])) {
$expiredTime = $instance['ExpiredTime'];
if ($expiredTime !== '' && $expiredTime !== null) {
$nextduedate = strtotime($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("[updateAliyunSwasToDatabase] SWAS {$vpsId} 详细信息已更新", 'updateAliyunSwasToDatabase');
} 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("[updateAliyunSwasToDatabase] SWAS {$vpsId} 新记录已插入", 'updateAliyunSwasToDatabase');
}
}
/**
* 更新VPS状态到数据库
*/
function updateVpsStatusInDatabaseAliyun($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("[updateVpsStatusInDatabaseAliyun] VPS {$vpsId} 状态已更新为: {$status}", 'updateVpsStatusInDatabaseAliyun');
} else {
$listDb->execute(
'INSERT INTO vps_list (config_id, vps_id, status, last_check) VALUES (?, ?, ?, CURRENT_TIMESTAMP)',
[$configId, $vpsId, $status]
);
Logger::info("[updateVpsStatusInDatabaseAliyun] VPS {$vpsId} 新记录已插入,状态: {$status}", 'updateVpsStatusInDatabaseAliyun');
}
}
/**
* 刷新指定配置的ECS列表遍历所有区域
*/
function refreshAliyunEcsListForConfig($configId) {
$db = getVpsDB();
$config = $db->queryOne('SELECT * FROM configs WHERE id = ?', [$configId]);
if (!$config || $config['site_type'] !== 'aliyun') {
return false;
}
// 先获取区域列表
$regions = getAliyunRegions($configId);
$totalInstances = 0;
Logger::info("[refreshAliyunEcsListForConfig] 开始遍历所有区域获取ECS列表", 'refreshAliyunEcsListForConfig');
foreach ($regions as $region) {
try {
$nextToken = null;
do {
$result = aliyunGetEcsList($configId, $region, 100, $nextToken);
if ($result && isset($result['status']) && $result['status'] === 200) {
$instances = $result['data']['Instances']['Instance'] ?? [];
if (!empty($instances)) {
Logger::info("[refreshAliyunEcsListForConfig] 区域 {$region} 找到 " . count($instances) . " 台ECS", 'refreshAliyunEcsListForConfig');
foreach ($instances as $instance) {
updateAliyunEcsToDatabase($configId, $instance);
// 获取状态
aliyunGetEcsStatus($configId, $instance['InstanceId'], $region, true);
$totalInstances++;
// 避免频繁请求
usleep(300000); // 300毫秒
}
}
// 检查是否有下一页
$nextToken = $result['data']['NextToken'] ?? null;
} else {
Logger::warning("[refreshAliyunEcsListForConfig] 区域 {$region} 获取失败: " . ($result['msg'] ?? '未知错误'), 'refreshAliyunEcsListForConfig');
break;
}
} while ($nextToken);
} catch (Exception $e) {
Logger::error("[refreshAliyunEcsListForConfig] 区域 {$region} 异常: " . $e->getMessage(), 'refreshAliyunEcsListForConfig');
}
// 区域之间稍作延迟
usleep(500000); // 500毫秒
}
Logger::info("[refreshAliyunEcsListForConfig] ECS列表刷新完成共获取 {$totalInstances} 台实例", 'refreshAliyunEcsListForConfig');
return true;
}
/**
* 刷新指定配置的轻量应用服务器列表(遍历所有区域)
*/
function refreshAliyunSwasListForConfig($configId) {
$db = getVpsDB();
$config = $db->queryOne('SELECT * FROM configs WHERE id = ?', [$configId]);
if (!$config || $config['site_type'] !== 'aliyun_swas') {
return false;
}
// 先获取区域列表
$regions = getAliyunSwasRegions($configId);
$totalInstances = 0;
Logger::info("[refreshAliyunSwasListForConfig] 开始遍历所有区域获取轻量应用服务器列表", 'refreshAliyunSwasListForConfig');
foreach ($regions as $region) {
try {
$pageNumber = 1;
do {
$result = aliyunGetSwasList($configId, $region, $pageNumber, 100);
if ($result && isset($result['status']) && $result['status'] === 200) {
$instances = $result['data']['Instances'] ?? [];
$totalCount = $result['data']['TotalCount'] ?? 0;
$pageSize = $result['data']['PageSize'] ?? 10;
if (!empty($instances)) {
Logger::info("[refreshAliyunSwasListForConfig] 区域 {$region} 找到 " . count($instances) . " 台轻量服务器", 'refreshAliyunSwasListForConfig');
foreach ($instances as $instance) {
updateAliyunSwasToDatabase($configId, $instance);
// 获取状态
aliyunGetSwasStatus($configId, $instance['InstanceId'], $region, true);
$totalInstances++;
// 避免频繁请求
usleep(300000); // 300毫秒
}
}
// 检查是否有下一页
$totalPages = ceil($totalCount / $pageSize);
$pageNumber++;
if ($pageNumber > $totalPages) {
break;
}
} else {
Logger::warning("[refreshAliyunSwasListForConfig] 区域 {$region} 获取失败: " . ($result['msg'] ?? '未知错误'), 'refreshAliyunSwasListForConfig');
break;
}
} while (true);
} catch (Exception $e) {
Logger::error("[refreshAliyunSwasListForConfig] 区域 {$region} 异常: " . $e->getMessage(), 'refreshAliyunSwasListForConfig');
}
// 区域之间稍作延迟
usleep(500000); // 500毫秒
}
Logger::info("[refreshAliyunSwasListForConfig] 轻量应用服务器列表刷新完成,共获取 {$totalInstances} 台实例", 'refreshAliyunSwasListForConfig');
return true;
}
/**
* 刷新所有阿里云配置的实例列表ECS + SWAS
*/
function refreshAllAliyunVpsLists() {
$db = getVpsDB();
$configs = $db->query('SELECT * FROM configs WHERE site_type IN (?, ?)', ['aliyun', 'aliyun_swas']);
$successCount = 0;
foreach ($configs as $config) {
if ($config['site_type'] === 'aliyun') {
// 刷新ECS列表
if (refreshAliyunEcsListForConfig($config['id'])) {
$successCount++;
}
} elseif ($config['site_type'] === 'aliyun_swas') {
// 刷新轻量应用服务器列表
if (refreshAliyunSwasListForConfig($config['id'])) {
$successCount++;
}
}
}
return $successCount;
}
?>