$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] 无法从数据库获取 region,config_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] 无法从数据库获取 region,config_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; } ?>