
Huawei Cloud Flexus L Server Ops
- 75 installs
- 19 repo stars
- Updated July 31, 2026
- huaweicloud/huaweicloud-skills
Operate Huawei Cloud Flexus L instances via API: query instances and traffic packages, batch start/stop/reboot, reset passwords, and modify info.
About
Provides day-to-day operations for Flexus L instances using the Huawei Cloud SDK: query instance lists and details, batch start/stop/reboot, reset passwords, modify info, and check traffic packages. A developer uses it for lifecycle management and traffic monitoring of running instances.
- Batch start/stop/reboot and password reset
- Traffic package queries via BSS service
Huawei Cloud Flexus L Server Ops by the numbers
- 75 all-time installs (skills.sh)
- +4 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #638 of 1,042 Cloud & Infrastructure skills by installs in the Skillselion catalog
- Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/huaweicloud/huaweicloud-skills --skill huawei-cloud-flexus-l-server-opsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 75 |
|---|---|
| repo stars | ★ 19 |
| Last updated | July 31, 2026 |
| Repository | huaweicloud/huaweicloud-skills ↗ |
What it does
Operate Huawei Cloud Flexus L instances via API: query instances and traffic packages, batch start/stop/reboot, reset passwords, and modify info.
Files
⚠️ Security Execution Rules (Highest Priority): 1. All scripts MUST be executed via skill action=exec, NEVER run directly in shell 2. NEVER print script contents or commands containing AK/SK/Token in conversation 3. NEVER create temporary script files, prefer inline execution (python -c) 4. On execution failure, only return error info, do NOT rewrite scripts or print full commands 5. AK/SK/Token MUST be passed via environment variables, NEVER appear in conversation 6. ⚠️ ABSOLUTELY NEVER expose, log, or print AK/SK/Token values in any form - this is a critical security requirement
Huawei Cloud Flexus L Instance Operations
Overview
This skill provides complete operational capabilities for Huawei Cloud Flexus L instances, covering instance lifecycle management, configuration modification, monitoring queries, and other core scenarios.
Architecture
OpenClaw Agent → Flexus L Ops Skill → Huawei Cloud SDK → Huawei Cloud Services
│ │ │
│ │ ├─ Flexus L (instance/lifecycle/password)
│ │ └─ BSS (traffic query)
│ │
└─ scripts/ └─ huaweicloudsdk{core,ecs,bss,config}Core Components:
- Flexus L Service: Elastic Cloud Server, provides instance management, lifecycle control, password reset, etc.
- BSS Service: Business Support System, provides traffic package usage query
- Python SDK: Official Huawei Cloud SDK, encapsulates API call logic
- Operation Scripts: 6 independent scripts, each corresponding to one operation
Applicable Scenarios
Typical Problem Scenarios: 1. Instance Status View: Need to quickly view the running status of all Flexus L instances under the account 2. Batch Operations: Need to perform start, stop, reboot operations on multiple servers 3. Configuration Modification: Need to modify instance name, description, hostname, and other basic information 4. Password Management: Need to reset instance login password 5. Traffic Monitoring: Need to view traffic package remaining amount and usage
Trigger Keywords:
| English Keyword | Chinese Keyword |
|---|---|
| Flexus L | Flexus L |
| Huawei Cloud Ops | 华为云运维 |
| Query Instance | 查询实例 |
| Start/Stop/Reboot | 开机/关机/重启 |
| Reset Password | 重置密码 |
| Update Info | 修改信息 |
| Query Traffic | 查流量 |
| Traffic Package | 流量包 |
| List All Servers | 查所有服务器 |
| My Servers | 我的服务器有哪些 |
| List All Instances | 列出所有实例 |
Prerequisites
1. Python Environment and dependencies
- Python >= 3.8
- huaweicloudsdkcore >= 3.0.0
- huaweicloudsdkecs >= 3.0.0
- huaweicloudsdkbss >= 3.0.0
- huaweicloudsdkconfig >= 3.0.0
- requests >= 2.31.0
2. Install Huawei Cloud SDK
pip3 install huaweicloudsdkcore huaweicloudsdkecs huaweicloudsdkconfig huaweicloudsdkbss \
-i https://repo.huaweicloud.com/repository/pypi/simple⚠️ Important: Script Usage Rules
Different operations MUST use the corresponding script. Do NOT use other scripts' commands.
| Operation | Must Use Script | Correct Command | ❌ Wrong Command |
|---|---|---|---|
| Query Flexus L instances | query_instances.py | query_instances.py list | ~~password_unified.py list~~ |
| Query instance details | query_instances.py | query_instances.py detail -i <ID> | ~~lifecycle.py list~~ |
| Start/Stop/Reboot | lifecycle.py | lifecycle.py stop --instance-id <ID> | ~~query_instances.py stop~~ |
| Reset password | password_unified.py | password_unified.py reset --instance-id <ID> --password <pwd> | ~~lifecycle.py reset~~ |
| Modify server info | update_server.py | update_server.py --instance-id <ID> --name <name> | ~~query_instances.py update~~ |
Operation Feedback Requirement
After any lifecycle operation (start/stop/reboot), MUST query and report the final status to user.
Example feedback format:
✅ Operation completed
Instance: your-instance-name
Status: Running
Public IP: <IP>This ensures the user knows the operation has completed successfully.
Scripts Description
Functional Scripts (4 scripts)
| Script | Function | Commands |
|---|---|---|
| query_instances.py | Instance query tool ⭐ | list, detail, free-resources, traffic, traffic-region |
| lifecycle.py | Lifecycle management | stop, start, reboot |
| password_unified.py | Password reset | test, list, reset |
| update_server.py | Modify server info | --name, --description, --hostname |
Helper Scripts (2 scripts)
| Script | Function |
|---|---|
| auth.py | Authentication management |
| params.py | Parameter processing |
Core Commands
See Execution Flow for operation steps.
Parameters
Required Parameters:
| Operation | Required Parameters | Description |
|---|---|---|
| Query Instance Details | instance-id | Instance ID |
| Start/Stop/Reboot | instance-id | Instance ID (supports multiple) |
| Reset Password | instance-id, password | Instance ID + new password |
| Modify Info | instance-id + (name/description/hostname) | Instance ID + at least one modification |
| Query Traffic by Region | target-region | Target region code |
| Query Traffic by ID | traffic_ids | Traffic package ID list |
Optional Parameters:
| Parameter | Description | Required | Default | Example |
|---|---|---|---|---|
| --region | Target region code (supports Chinese names) | No | cn-north-4 | --region cn-north-4 |
| --ak | Huawei Cloud Access Key AK (can be temporary AK) | No | HW_ACCESS_KEY env var | --ak AXXX... |
| --sk | Huawei Cloud Access Key SK (can be temporary SK) | No | HW_SECRET_KEY env var | --sk SXXX... |
| --security-token | Security token for temporary credentials (required when using temporary AK/SK) | No | HW_SECURITY_TOKEN env var | --security-token XXXX... |
Region Parameter Support:
- Region code:
cn-north-4 - Full name:
North-China-Beijing4 - Short name:
Beijing4,Guangzhou,Shanghai
Execution Flow
Step 1: Check Existing Credentials (Automatic)
Get credentials from environment variables first, automatic check, no need to ask user.
Decision Logic:
| Credential Status | Next Step |
|---|---|
| ✅ HW_ACCESS_KEY + HW_SECRET_KEY + HW_SECURITY_TOKEN exist | Execute script directly (Recommended: Temporary AK/SK authentication, higher security level, pass --ak --sk --security-token parameters) |
| ✅ HW_ACCESS_KEY + HW_SECRET_KEY exist (no Token) | Execute script directly (Permanent AK/SK authentication, pass --ak --sk parameters) |
| ❌ Environment variables not found | Prompt user to configure credentials (prefer environment variables, do NOT ask directly) |
| ❌ Authentication failed | Prompt user to check or reconfigure credentials (prefer environment variables, do NOT ask directly) |
⚠️ Security Recommendations:
1. Prefer temporary credentials: Strongly recommend using temporary AK/SK + Security Token method for higher security, credentials expire automatically 2. Environment variable configuration: Credentials should be configured via environment variables (HW_ACCESS_KEY, HW_SECRET_KEY, HW_SECURITY_TOKEN) 3. Sensitive information protection: AK/SK are sensitive information, do NOT input or disclose in conversation
Credential Missing or Authentication Failed Message:
❌ Credentials not configured or authentication failed
Please configure Huawei Cloud credentials. For security, we recommend using temporary AK/SK + Security Token method via environment variables:
- HW_ACCESS_KEY: Access Key AK
- HW_SECRET_KEY: Secret Key SK
- HW_SECURITY_TOKEN: Security Token (Recommended)
⚠️ Security Note: Temporary credentials are more secure, please prefer using them!Note: We prioritize obtaining credentials from environment variables and NEVER ask users to input AK/SK directly. However, we still support parsing credentials if user voluntarily provides them via other methods (e.g., conversation input, config file).
Step 2: Select Operation
After credentials are verified, ask user what operation to perform:
Step 3: Execute Operation
⚠️ Instance Validation (When user provides instance ID/name):
python3 {baseDir}/scripts/query_instances.py free-resources --ak "$HW_ACCESS_KEY" --sk "$HW_SECRET_KEY" [--security-token "$HW_SECURITY_TOKEN"]- ✅ Found in list → Proceed with operation
- ❌ Not found → Tell user: "This is NOT a Flexus L instance. This skill only supports Flexus L instances." Then refer to Finding Server ID section for guidance.
⚠️ Important Notes:
1. Instance Type Confirmation: Before executing any operation, remind user that this skill only supports Flexus L instances
2. Server ID Guidance: If user hasn't specified a server ID to operate on, guide user to query all instances or specific server
4.1 List Instances
Query all instances across regions:
python3 {baseDir}/scripts/query_instances.py list --ak "$HW_ACCESS_KEY" --sk "$HW_SECRET_KEY" [--security-token "$HW_SECURITY_TOKEN"]Query instances in specific region:
python3 {baseDir}/scripts/query_instances.py list --region cn-north-4 --ak "$HW_ACCESS_KEY" --sk "$HW_SECRET_KEY" [--security-token "$HW_SECURITY_TOKEN"]4.2 Query Instance Details
Required Parameters:
- Instance ID (required)
- Region code (optional, default cn-north-4)
python3 {baseDir}/scripts/query_instances.py detail --instance-id <ID> --region cn-north-4 --ak "$HW_ACCESS_KEY" --sk "$HW_SECRET_KEY" [--security-token "$HW_SECURITY_TOKEN"]⚠️ Error Handling: If query fails with "server not found" and user didn't specify region, tell user to check region, instance type, and ID.
4.3 Batch Start
Required Parameters:
- Instance ID (required, supports multiple)
- Region code (optional, default cn-north-4)
python3 {baseDir}/scripts/lifecycle.py start --instance-id <ID1> --instance-id <ID2> --region cn-north-4 --ak "$HW_ACCESS_KEY" --sk "$HW_SECRET_KEY" [--security-token "$HW_SECURITY_TOKEN"]4.4 Batch Stop
⚠️ Dangerous Operation: Must Confirm Twice
🔒 Instance Type Restriction: This operation ONLY supports Flexus L instances, NOT all ECS instances. Must verify instance type before execution.
Required Parameters:
- Instance ID (required, supports multiple)
- Region code (optional, default cn-north-4)
Must confirm twice before execution:
- Tell user the consequences of stopping (service interruption, data loss risk)
- If stopping the server currently running OpenClaw, must warn additionally (conversation interruption, need manual restart)
- Only execute after user replies "confirm stop"
python3 {baseDir}/scripts/lifecycle.py stop --instance-id <ID1> --instance-id <ID2> --region cn-north-4 --ak "$HW_ACCESS_KEY" --sk "$HW_SECRET_KEY" [--security-token "$HW_SECURITY_TOKEN"]4.5 Batch Reboot
⚠️ Dangerous Operation: Must Confirm Twice
🔒 Instance Type Restriction: This operation ONLY supports Flexus L instances, NOT all ECS instances. Must verify instance type before execution.
Required Parameters:
- Instance ID (required, supports multiple)
- Region code (optional, default cn-north-4)
- Reboot type (optional): SOFT (normal reboot, default) or HARD (forced reboot)
Must confirm twice before execution:
- Tell user the consequences of rebooting (brief service interruption, memory data loss)
- If rebooting the server currently running OpenClaw, must warn additionally (brief conversation interruption, auto recovery)
- Only execute after user replies "confirm reboot"
python3 {baseDir}/scripts/lifecycle.py reboot --instance-id <ID1> --instance-id <ID2> --region cn-north-4 --ak "$HW_ACCESS_KEY" --sk "$HW_SECRET_KEY" [--security-token "$HW_SECURITY_TOKEN"]4.6 Reset Password
Required Parameters:
- Instance ID (required)
- New password (required)
- Length 8-26 characters
- Must contain at least 3 of: uppercase, lowercase, numbers, special characters
- Cannot contain username or reversed username
- Cannot contain 3 or more consecutive identical characters
- Region code (optional, default cn-north-4)
⚠️ Important: After resetting password, the instance MUST be rebooted for the new password to take effect.
Must confirm with user before reboot:
- Inform user that password reset is successful
- Warn user about consequences: brief service interruption, memory data loss
- If rebooting the server currently running OpenClaw, must warn additionally (brief conversation interruption, auto recovery)
- Only execute reboot after user replies "confirm reboot"
python3 {baseDir}/scripts/password_unified.py reset --instance-id <ID> --password <new_password> --region cn-north-4 --ak "$HW_ACCESS_KEY" --sk "$HW_SECRET_KEY" [--security-token "$HW_SECURITY_TOKEN"]Reboot Command:
python3 {baseDir}/scripts/lifecycle.py reboot --instance-id <ID> --region cn-north-4 --ak "$HW_ACCESS_KEY" --sk "$HW_SECRET_KEY" [--security-token "$HW_SECURITY_TOKEN"]4.7 Modify Instance Information
Required Parameters:
- Instance ID (required)
- Region code (optional, default cn-north-4)
- Modification parameters (at least one):
- name: Instance name (1-64 characters, supports Chinese, letters, numbers, _-, .)
- description: Description (0-85 characters, cannot contain <>)
- hostname: Hostname (1-64 characters)
python3 {baseDir}/scripts/update_server.py --instance-id <ID> --name "new_name" --region cn-north-4 --ak "$HW_ACCESS_KEY" --sk "$HW_SECRET_KEY" [--security-token "$HW_SECURITY_TOKEN"]4.8 Query Traffic Package
Option 1: Query by Traffic Package ID
Required Parameters:
- Traffic package ID (required)
⚠️ Special Note: Traffic package query uses Beijing-1 region (cn-north-1) by default, traffic package ID can be from any region
python3 {baseDir}/scripts/query_instances.py traffic <traffic_id_1> <traffic_id_2> --ak "$HW_ACCESS_KEY" --sk "$HW_SECRET_KEY" [--security-token "$HW_SECURITY_TOKEN"]Option 2: Query by Region ⭐ Recommended
Required Parameters:
- Target region (required)
python3 {baseDir}/scripts/query_instances.py traffic-region --target-region cn-east-3 --ak "$HW_ACCESS_KEY" --sk "$HW_SECRET_KEY" [--security-token "$HW_SECURITY_TOKEN"]Finding Server ID
If user asks "how to find server ID" or "don't know server ID", first provide console lookup steps:
You can find server ID through the following ways:
Option 1: Via Huawei Cloud Console
1. Login to Huawei Cloud Console
2. Go to Flexus Application Server L instance list
3. Click instance name to enter details page
4. In basic information, click "Cloud Host VM"
5. View cloud host ID in cloud host information
6. Click copy button after ID to quickly copy
Help Document: https://support.huaweicloud.com/intl/zh-cn/flexusl_faq/faq_01_0003.htmlThen append the following, offer automatic query option:
Option 2: I can also help query all servers under your account
Would you like me to list all instances under your account? I can query directly for you.If user agrees, execute list all instances:
python3 {baseDir}/scripts/query_instances.py list --ak "$HW_ACCESS_KEY" --sk "$HW_SECRET_KEY" [--security-token "$HW_SECURITY_TOKEN"]Region Support
Common Region Codes
| Region Code | Region Name |
|---|---|
| cn-north-4 | North China-Beijing 4 |
| cn-north-1 | North China-Beijing 1 |
| cn-south-1 | South China-Guangzhou |
| cn-east-3 | East China-Shanghai 1 |
| ap-southeast-1 | China-Hong Kong |
| ap-southeast-2 | Asia Pacific-Singapore |
Region Name Conversion
This skill supports automatic region name conversion, can use Chinese names or English codes:
# Use region code
python3 {baseDir}/scripts/query_instances.py list --region cn-north-4 --ak "$HW_ACCESS_KEY" --sk "$HW_SECRET_KEY" [--security-token "$HW_SECURITY_TOKEN"]
# Use region name (auto-convert)
python3 {baseDir}/scripts/query_instances.py list --region "North-China-Beijing4" --ak "$HW_ACCESS_KEY" --sk "$HW_SECRET_KEY" [--security-token "$HW_SECURITY_TOKEN"]
python3 {baseDir}/scripts/query_instances.py list --region "Beijing4" --ak "$HW_ACCESS_KEY" --sk "$HW_SECRET_KEY" [--security-token "$HW_SECURITY_TOKEN"]
python3 {baseDir}/scripts/query_instances.py list --region "Guangzhou" --ak "$HW_ACCESS_KEY" --sk "$HW_SECRET_KEY" [--security-token "$HW_SECURITY_TOKEN"]Traffic Package Query Special Note
⚠️ Traffic package query uses Beijing-1 region (cn-north-1) by default
- Traffic package query does not support --region parameter
- Traffic package ID can be from any region
- Automatically uses Beijing-1 region for query
Notes
- Instance ID is the cloud host ID corresponding to Flexus L instance
- Region defaults to cn-north-4 (Beijing 4)
- AK/SK Security Requirements:
- ✅ Must be stored via environment variables (HW_ACCESS_KEY, HW_SECRET_KEY, HW_SECURITY_TOKEN)
- ❌ Do not store in any configuration files
- Stop/Reboot Security Requirements:
- ✅ Must confirm twice - No direct execution without user confirmation
- ✅ Must be Flexus L instances only - Cannot operate on all ECS instances, must verify instance type
- ✅ Must inform operation consequences
- ✅ If current server, must give additional warning
- ❌ Never execute batch operations on all ECS instances - Only Flexus L instances are supported
References
Skill Reference Documents
This skill includes the following reference documents:
- IAM Policies - Detailed IAM permission configuration
- Verification Method - Skill verification method
Huawei Cloud Official Documentation
IAM Policies
Overview
This skill requires specific IAM permissions. Ensure your account has the following permissions.
Required Permissions
Flexus L Permissions
Note: Flexus L uses ECS service internally, so ECS permissions are required.
{
"Version": "1.1",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecs:servers:list",
"ecs:servers:get",
"ecs:servers:start",
"ecs:servers:stop",
"ecs:servers:reboot",
"ecs:serverPasswords:reset"
]
}
]
}BSS Permissions (Traffic Query)
{
"Version": "1.1",
"Statement": [
{
"Effect": "Allow",
"Action": [
"bss:resourceUsage:get"
]
}
]
}Permission Configuration Steps
Step 1: Create Custom Policy
1. Login to Huawei Cloud Console 2. Go to IAM Console 3. Select "Permission Management" → "Custom Policies" 4. Click "Create Custom Policy" 5. Enter policy name (e.g., FlexusL-Ops-Policy) 6. Select "JSON" view 7. Paste the above permission policy 8. Click "OK"
Step 2: Attach Policy to User
1. Go to IAM Console 2. Select "Users" → Find target user 3. Click "Authorize" 4. Select the custom policy just created 5. Click "OK"
Permission Verification
Verify ECS Permissions
python3 {baseDir}/scripts/cli.py testInsufficient Permission Handling
If permission denied: 1. Check if IAM policy is correctly attached to user 2. Verify AK/SK is valid 3. Confirm region configuration is correct 4. Check ErrorCode in error message
Least Privilege Principle
Follow the least privilege principle: only grant necessary permissions, avoid granting excessive permissions.
Verification Method
Overview
This document describes how to verify the skill is correctly installed and configured.
Verification Steps
1. Verify Python Environment
python3 --version
# Should output: Python 3.8.x or higher2. Verify SDK Installation
python3 -c "from huaweicloudsdkcore.exceptions import exceptions; print('✅ SDK installed successfully')"3. Verify AK/SK Configuration
env | grep CLOUD_SDK
# Should output:
# CLOUD_SDK_AK=xxx
# CLOUD_SDK_SK=xxx4. Verify Connection
python3 {baseDir}/scripts/query_instances.py listSuccess Output:
📋 Querying Flexus L instances...
✅ Query successful, credentials are valid5. Verify Instance Query
python3 {baseDir}/scripts/query_instances.py listSuccess Output:
📋 Querying Flexus L instances...
Instance ID Name Status Region
xxx xxx Running cn-north-4Common Issues
Issue 1: SDK Import Failed
Error: ModuleNotFoundError: No module named 'huaweicloudsdkcore'
Solution:
pip3 install -e . --break-system-packages -i https://repo.huaweicloud.com/repository/pypi/simpleIssue 2: Credentials Not Configured
Error: ❌ Credentials not detected
Solution:
export CLOUD_SDK_AK="your_access_key"
export CLOUD_SDK_SK="your_secret_key"Issue 3: Insufficient Permissions
Error: ❌ Insufficient permissions
Solution: Refer to iam-policies.md to configure permissions
Issue 4: Region Not Found
Error: ❌ Region not found
Solution: Use correct region code, e.g., cn-north-4
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Unified authentication module - All scripts get credentials and clients through AuthManager
Environment variables:
- HW_ACCESS_KEY (AK)
- HW_SECRET_KEY (SK)
- HW_SECURITY_TOKEN (Security Token, optional)
"""
import os
from typing import Optional, Tuple
from huaweicloudsdkcore.auth.credentials import BasicCredentials, GlobalCredentials
from huaweicloudsdkcore.http.http_config import HttpConfig
from huaweicloudsdkecs.v2 import EcsClient, ListServersDetailsRequest
from huaweicloudsdkecs.v2.region.ecs_region import EcsRegion
from huaweicloudsdkbss.v2 import BssClient
from huaweicloudsdkbss.v2.region.bss_region import BssRegion
from huaweicloudsdkconfig.v1 import ConfigClient
from huaweicloudsdkconfig.v1.region.config_region import ConfigRegion
class AuthManager:
"""AK/SK Authentication Manager"""
ENV_AK = "HW_ACCESS_KEY"
ENV_SK = "HW_SECRET_KEY"
ENV_TOKEN = "HW_SECURITY_TOKEN"
def __init__(self, ak: Optional[str] = None, sk: Optional[str] = None, security_token: Optional[str] = None, project_id: Optional[str] = None):
"""Initialize authentication manager, supports long-term and temporary credentials"""
self.ak = ak or os.environ.get(self.ENV_AK)
self.sk = sk or os.environ.get(self.ENV_SK)
self.security_token = security_token or os.environ.get(self.ENV_TOKEN)
self.project_id = project_id
# If Security Token exists, AK/SK are also temporary
self.is_temporary = bool(self.security_token)
def get_basic_credentials(self):
"""Get regional service credentials (ECS, Flexus L, etc.)"""
try:
if self.security_token:
# Temporary credentials: AK/SK + Security Token
credentials = BasicCredentials(self.ak, self.sk, self.project_id).with_security_token(self.security_token)
else:
# Long-term credentials: permanent AK/SK
credentials = BasicCredentials(self.ak, self.sk, self.project_id)
return credentials
except Exception as e:
raise ValueError(f"Failed to create BasicCredentials: {e}")
def get_global_credentials(self):
"""Get global service credentials (BSS, Config, IAM, etc.)"""
try:
if self.security_token:
# Temporary credentials
credentials = GlobalCredentials(self.ak, self.sk).with_security_token(self.security_token)
else:
# Long-term credentials
credentials = GlobalCredentials(self.ak, self.sk)
return credentials
except Exception as e:
raise ValueError(f"Failed to create GlobalCredentials: {e}")
def get_ecs_client(self, region: str):
"""Get ECS client (for Flexus L instance operations)"""
return EcsClient.new_builder() \
.with_credentials(self.get_basic_credentials()) \
.with_region(EcsRegion.value_of(region)) \
.build()
def get_bss_client(self, region: str = "cn-north-1"):
"""Get BSS client (for traffic package queries)"""
return BssClient.new_builder() \
.with_credentials(self.get_global_credentials()) \
.with_region(BssRegion.value_of(region)) \
.build()
def get_config_client(self, region: str = "cn-north-4"):
"""Get Config client (for resource configuration queries)"""
config = HttpConfig.get_default_config()
config.ignore_ssl_verification = True
return ConfigClient.new_builder() \
.with_http_config(config) \
.with_credentials(self.get_global_credentials()) \
.with_region(ConfigRegion.value_of(region)) \
.build()
def get_credentials(self) -> Tuple[Optional[str], Optional[str], Optional[str]]:
"""Get current credential tuple (AK, SK, SecurityToken)"""
return (self.ak, self.sk, self.security_token)
def is_configured(self) -> bool:
"""Check if AK/SK is configured"""
return bool(self.ak and self.sk)
def has_security_token(self) -> bool:
"""Check if Security Token exists (indicates temporary credentials)"""
return bool(self.security_token)
def is_temporary_credentials(self) -> bool:
"""Check if using temporary credentials (AK/SK + Security Token)"""
return self.is_temporary
def validate(self) -> Tuple[bool, str]:
"""Validate credentials"""
if not self.is_configured():
return (False, "ERROR: AK/SK environment variables not detected")
try:
client = self.get_ecs_client("cn-north-4")
client.list_servers_details(ListServersDetailsRequest(limit=1))
auth_type = "AK/SK/Security Token" if self.security_token else "AK/SK"
return (True, f"SUCCESS: Credentials validated ({auth_type})")
except Exception as e:
error_msg = str(e)
if "401" in error_msg or "Unauthorized" in error_msg:
return (False, "ERROR: Credentials invalid or expired")
elif "403" in error_msg:
return (False, "ERROR: Insufficient permissions")
return (False, f"ERROR: Validation failed: {error_msg}")
#!/usr/bin/env python3
# coding: utf-8
"""Flexus L instance lifecycle management (start/stop/reboot)"""
import os
import sys
from huaweicloudsdkcore.exceptions import exceptions
from huaweicloudsdkecs.v2 import (
BatchStartServersRequest, BatchStartServersRequestBody, BatchStartServersOption,
BatchStopServersRequest, BatchStopServersRequestBody, BatchStopServersOption,
BatchRebootServersRequest, BatchRebootServersRequestBody, BatchRebootSeversOption,
ServerId
)
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from auth import AuthManager
def manage_servers(action: str, server_ids: list, region: str = "cn-north-4", reboot_type: str = "SOFT", auth: AuthManager = None):
"""Manage Flexus L instance lifecycle (start/stop/reboot)"""
action = action.lower()
if action not in ["start", "stop", "reboot"]:
raise ValueError(f"Invalid action: {action}, must be start/stop/reboot")
auth = auth or AuthManager()
if not auth.is_configured():
raise ValueError("Please set environment variables HW_ACCESS_KEY, HW_SECRET_KEY, HW_SECURITY_TOKEN or provide --ak --sk parameters")
client = auth.get_ecs_client(region)
server_id_list = [ServerId(id=sid) for sid in server_ids]
try:
if action == "start":
request = BatchStartServersRequest(body=BatchStartServersRequestBody(
os_start=BatchStartServersOption(servers=server_id_list)))
response = client.batch_start_servers(request)
elif action == "stop":
request = BatchStopServersRequest(body=BatchStopServersRequestBody(
os_stop=BatchStopServersOption(servers=server_id_list)))
response = client.batch_stop_servers(request)
else: # reboot
request = BatchRebootServersRequest(body=BatchRebootServersRequestBody(
reboot=BatchRebootSeversOption(servers=server_id_list, type=reboot_type)))
response = client.batch_reboot_servers(request)
return {"success": True, "response": str(response), "action": action, "server_ids": server_ids}
except exceptions.ClientRequestException as e:
return {"success": False, "error": {"status_code": e.status_code, "request_id": e.request_id,
"error_code": e.error_code, "error_msg": e.error_msg}}
def main():
"""Command line entry: parse arguments and execute lifecycle operations"""
if len(sys.argv) < 2:
print("Usage: python lifecycle.py <action> --instance-id <ID> [--instance-id <ID2>...] [--region <region>] [--type SOFT|HARD] [--ak <AK>] [--sk <SK>] [--security-token <TOKEN>]")
print("Actions: start / stop / reboot")
sys.exit(1)
action, server_ids, region, reboot_type = sys.argv[1].lower(), [], "cn-north-4", "SOFT"
ak, sk, security_token = None, None, None
i = 2
while i < len(sys.argv):
if sys.argv[i] == "--instance-id" and i + 1 < len(sys.argv):
server_ids.append(sys.argv[i + 1])
i += 2
elif sys.argv[i] == "--region" and i + 1 < len(sys.argv):
region, i = sys.argv[i + 1], i + 2
elif sys.argv[i] == "--type" and i + 1 < len(sys.argv):
reboot_type, i = sys.argv[i + 1].upper(), i + 2
elif sys.argv[i] == "--ak" and i + 1 < len(sys.argv):
ak, i = sys.argv[i + 1], i + 2
elif sys.argv[i] == "--sk" and i + 1 < len(sys.argv):
sk, i = sys.argv[i + 1], i + 2
elif sys.argv[i] == "--security-token" and i + 1 < len(sys.argv):
security_token, i = sys.argv[i + 1], i + 2
else:
i += 1
if not server_ids or action not in ["start", "stop", "reboot"]:
print("ERROR: Invalid parameters. Please provide --instance-id")
sys.exit(1)
auth = AuthManager(ak=ak, sk=sk, security_token=security_token)
action_name = "Starting" if action == "start" else "Stopping" if action == "stop" else "Rebooting"
print(f"{action_name} {len(server_ids)} server(s)...")
result = manage_servers(action, server_ids, region, reboot_type, auth)
if result["success"]:
print(f"SUCCESS: {action.upper()} operation submitted")
else:
print(f"ERROR: Operation failed: {result['error']['error_msg']}")
sys.exit(1)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Parameter conversion module (region/status)"""
from typing import Dict
class RegionConverter:
"""Region code converter"""
# Region name to code mapping (Chinese names supported for user input)
REGION_MAP = {
"华北-北京四": "cn-north-4", "北京四": "cn-north-4", "Beijing4": "cn-north-4",
"华南-广州": "cn-south-1", "广州": "cn-south-1", "Guangzhou": "cn-south-1",
"华东-上海一": "cn-east-3", "上海一": "cn-east-3", "上海": "cn-east-3", "Shanghai": "cn-east-3",
"西南-贵阳一": "cn-southwest-2", "贵阳一": "cn-southwest-2", "贵阳": "cn-southwest-2",
"中国-香港": "ap-southeast-1", "香港": "ap-southeast-1", "HongKong": "ap-southeast-1",
"亚太-新加坡": "ap-southeast-2", "新加坡": "ap-southeast-2", "Singapore": "ap-southeast-2",
}
# Code to Chinese name mapping (for display purposes)
REGION_NAME_MAP = {
"cn-north-4": "华北-北京四", "cn-south-1": "华南-广州", "cn-east-3": "华东-上海一",
"cn-southwest-2": "西南-贵阳一", "ap-southeast-1": "中国-香港", "ap-southeast-2": "亚太-新加坡",
}
@classmethod
def to_code(cls, region: str) -> str:
"""Convert region name to region code"""
if region in cls.REGION_NAME_MAP:
return region
return cls.REGION_MAP.get(region, cls.REGION_MAP.get(region.lower(), region))
@classmethod
def to_name(cls, code: str) -> str:
"""Convert region code to region name"""
return cls.REGION_NAME_MAP.get(code, code)
class StatusConverter:
"""Server status converter"""
STATUS_MAP = {
"ACTIVE": "Running", "SHUTOFF": "Stopped", "BUILD": "Building", "ERROR": "Error",
"REBOOT": "Rebooting", "HARD_REBOOT": "Hard Rebooting", "MIGRATING": "Migrating",
}
@classmethod
def to_display(cls, status: str) -> str:
"""Convert status code to display name"""
return cls.STATUS_MAP.get(status, status)
@classmethod
def to_code(cls, status: str) -> str:
"""Convert display name to status code"""
for code, name in cls.STATUS_MAP.items():
if name == status:
return code
return status.upper()
#!/usr/bin/env python3
# coding: utf-8
"""Flexus L instance password reset tool"""
import os
import sys
from huaweicloudsdkecs.v2 import (
ListServersDetailsRequest, ShowServerRequest,
BatchResetServersPasswordRequest, BatchResetServersPasswordRequestBody, ServerId
)
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from auth import AuthManager
class FlexusLClient:
"""Flexus L instance client"""
def __init__(self, auth: AuthManager = None, region: str = "cn-north-4"):
"""Initialize client"""
self.auth = auth or AuthManager()
if not self.auth.is_configured():
raise ValueError("Please provide AK/SK/Security_Token")
self.region = region
def list_servers(self, limit: int = 100):
"""List servers"""
client = self.auth.get_ecs_client(self.region)
return client.list_servers_details(ListServersDetailsRequest(limit=limit)).to_dict()
def get_server(self, server_id: str):
"""Get server details"""
client = self.auth.get_ecs_client(self.region)
return client.show_server(ShowServerRequest(server_id=server_id)).to_dict()
def reset_password(self, server_ids: list, new_password: str):
"""Reset instance login password"""
client = self.auth.get_ecs_client(self.region)
request = BatchResetServersPasswordRequest(body=BatchResetServersPasswordRequestBody(
servers=[ServerId(id=sid) for sid in server_ids], new_password=new_password))
response = client.batch_reset_servers_password(request)
return True
def validate_password(password: str) -> bool:
"""Validate password complexity (8-26 chars, at least 3 character types, no weak passwords)"""
if not 8 <= len(password) <= 26:
print(f"ERROR: Password length must be 8-26 characters (current: {len(password)})")
return False
has_upper = any(c.isupper() for c in password)
has_lower = any(c.islower() for c in password)
has_digit = any(c.isdigit() for c in password)
has_special = any(not c.isalnum() for c in password)
if sum([has_upper, has_lower, has_digit, has_special]) < 3:
print("ERROR: Password must contain at least 3 character types (upper/lower/digit/special)")
return False
for i in range(len(password) - 2):
if password[i] == password[i+1] == password[i+2]:
print("ERROR: Password cannot contain 3 consecutive identical characters")
return False
common_usernames = ["admin", "root", "user", "test", "password"]
for username in common_usernames:
if username in password.lower() or username[::-1] in password.lower():
print(f"ERROR: Password cannot contain common username: {username}")
return False
if password.lower() in ["password", "12345678", "qwertyui", "abcdefgh"]:
print("ERROR: Cannot use common weak passwords")
return False
return True
def main():
"""Command line entry: parse arguments and execute password operations"""
if len(sys.argv) < 2:
print("Usage: python password_unified.py <command> [args] [--ak <AK>] [--sk <SK>] [--security-token <TOKEN>]")
print("Commands: test (test connection) / list (list servers) / reset --instance-id <ID> --password <PWD> (reset password)")
sys.exit(1)
region = os.environ.get("CLOUD_SDK_REGION") or os.environ.get("HUAWEICLOUD_SDK_REGION") or "cn-north-4"
ak, sk, security_token = None, None, None
cmd = None
i = 1
while i < len(sys.argv):
arg = sys.argv[i]
if arg == "--ak" and i + 1 < len(sys.argv):
ak, i = sys.argv[i + 1], i + 2
elif arg == "--sk" and i + 1 < len(sys.argv):
sk, i = sys.argv[i + 1], i + 2
elif arg == "--security-token" and i + 1 < len(sys.argv):
security_token, i = sys.argv[i + 1], i + 2
elif arg == "--region" and i + 1 < len(sys.argv):
region, i = sys.argv[i + 1], i + 2
elif not arg.startswith("--"):
if cmd is None:
cmd = arg.lower()
i += 1
else:
i += 1
if cmd is None:
print("ERROR: No command specified")
sys.exit(1)
auth = AuthManager(ak=ak, sk=sk, security_token=security_token)
client = FlexusLClient(auth=auth, region=region)
try:
if cmd == "test":
client.list_servers(limit=1)
print("SUCCESS: Connection successful")
elif cmd == "list":
servers = client.list_servers().get('servers', [])
print(f"\nFound {len(servers)} server(s):\n")
for i, s in enumerate(servers, 1):
print(f"{i}. {s.get('name', 'N/A'):<30} {s.get('id', 'N/A'):<40} {s.get('status', 'N/A')}")
elif cmd == "reset":
# Get --instance-id and --password from args
server_id, password = None, None
j = 1
while j < len(sys.argv):
if sys.argv[j] == "--instance-id" and j + 1 < len(sys.argv):
server_id = sys.argv[j + 1]
j += 2
elif sys.argv[j] == "--password" and j + 1 < len(sys.argv):
password = sys.argv[j + 1]
j += 2
else:
j += 1
if not server_id or not password:
print("ERROR: Usage: python password_unified.py reset --instance-id <ID> --password <PWD>")
sys.exit(1)
if not validate_password(password):
sys.exit(1)
print(f"Resetting password for: {server_id}")
client.reset_password([server_id], password)
print(f"SUCCESS: Password reset successful")
else:
print(f"ERROR: Unknown command: {cmd}")
sys.exit(1)
except Exception as e:
print(f"ERROR: {e}")
sys.exit(1)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
# coding: utf-8
"""Flexus L instance query tool (list/detail/traffic)"""
import os
import sys
import argparse
from datetime import datetime, timezone, timedelta
from huaweicloudsdkconfig.v1 import ListAllResourcesRequest
from huaweicloudsdkbss.v2 import ListFreeResourceUsagesRequest, ListFreeResourceUsagesReq
from huaweicloudsdkecs.v2 import ShowServerRequest
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from auth import AuthManager
from params import RegionConverter
MEASURE_UNITS = {10: "GB"}
def utc_to_beijing(utc_str: str) -> str:
"""Convert UTC time to Beijing time"""
if not utc_str or utc_str == 'N/A':
return 'N/A'
try:
if utc_str.endswith('Z'):
utc_str = utc_str[:-1] + '+00:00'
dt = datetime.fromisoformat(utc_str)
return dt.astimezone(timezone(timedelta(hours=8))).strftime('%Y-%m-%d %H:%M:%S')
except:
return utc_str
class InstanceQueryClient:
"""Instance query client"""
def __init__(self, ak=None, sk=None, security_token=None, region="cn-north-4"):
"""Initialize query client"""
self.region = RegionConverter.to_code(region)
self.auth = AuthManager(ak=ak, sk=sk, security_token=security_token)
def _get_flexus_name_by_ecs_id(self, ecs_id: str) -> str:
"""Find Flexus L instance name by ECS ID"""
try:
config_client = self.auth.get_config_client(self.region)
request = ListAllResourcesRequest(type="hcss.l-instance")
response = config_client.list_all_resources(request)
for r in response.resources:
props = r.properties or {}
for sub in props.get("resources", []):
if sub.get("logical_resource_type") == "huaweicloudinternal_ecs_instance":
if sub.get("physical_resource_id") == ecs_id:
return r.name
except:
pass
return "N/A"
def list_all_regions(self, resource_type="hcss.l-instance"):
"""List Flexus L instances across all regions"""
print(f"Querying resources (type: {resource_type})...\n")
config_client = self.auth.get_config_client(self.region)
request = ListAllResourcesRequest(type=resource_type)
response = config_client.list_all_resources(request)
resources = response.resources
if not resources:
print(f"No {resource_type} resources found")
return
print(f"\n{'='*120}")
print(f"Query result: {len(resources)} resource(s)")
print(f"{'='*120}")
print(f"{'No.':<6} {'Instance Name':<50} {'Instance ID':<42} {'Region':<15} {'Status':<10}")
print("-" * 120)
for i, r in enumerate(resources, 1):
print(f"{i:<6} {getattr(r, 'name', 'N/A')[:48]:<50} {getattr(r, 'id', 'N/A'):<42} {getattr(r, 'region_id', 'N/A'):<15} {getattr(r, 'status', 'N/A'):<10}")
print("=" * 120)
def query_instance(self, instance_id: str):
"""Query single instance details"""
print(f"Querying cloud host: {instance_id}")
client = self.auth.get_ecs_client(self.region)
server = client.show_server(ShowServerRequest(server_id=instance_id)).server
# Find corresponding Flexus L instance name
flexus_name = self._get_flexus_name_by_ecs_id(instance_id)
print("\n" + "=" * 60)
print(f"Instance Name: {flexus_name}")
print(f"Cloud Host Name: {server.name}")
print(f"Cloud Host ID: {server.id}")
print(f"Status: {server.status}")
print(f"Region: {self.region}")
print(f"Created: {utc_to_beijing(server.created)}")
if hasattr(server, 'addresses') and server.addresses:
print("\nNetwork Info:")
for net, addrs in server.addresses.items():
for a in addrs:
print(f" {net}: {a.addr}")
print("=" * 60)
def list_free_resources(self, resource_type="hcss.l-instance"):
"""List Flexus L instance resources (with traffic package ID)"""
print(f"Querying Flexus L instance resources...\n")
config_client = self.auth.get_config_client(self.region)
request = ListAllResourcesRequest(type=resource_type)
response = config_client.list_all_resources(request)
instances = []
for r in response.resources:
props = r.properties or {}
cbc_id = ecs_id = None
for sub in props.get("resources", []):
if sub.get("logical_resource_type") == "huaweicloudinternal_cbc_freeresource":
cbc_id = sub.get("physical_resource_id")
if sub.get("logical_resource_type") == "huaweicloudinternal_ecs_instance":
ecs_id = sub.get("physical_resource_id")
if cbc_id:
instances.append({"name": r.name, "ecs_id": ecs_id, "cbc_id": cbc_id})
if not instances:
print(f"No resources found")
return
print(f"\n{'='*130}")
print(f"Query result: {len(instances)} instance(s)")
print(f"{'='*130}")
print(f"{'No.':<6} {'Instance Name':<30} {'Cloud Host ID':<40} {'Traffic Package ID':<40}")
print("-" * 130)
for i, inst in enumerate(instances, 1):
print(f"{i:<6} {inst['name'][:28]:<30} {inst['ecs_id'] or '-':<40} {inst['cbc_id']:<40}")
print("=" * 130)
def query_traffic(self, traffic_ids: list):
"""Query traffic package usage"""
print(f"Querying {len(traffic_ids)} traffic package(s)...\n")
bss_client = self.auth.get_bss_client()
request = ListFreeResourceUsagesRequest(body=ListFreeResourceUsagesReq(free_resource_ids=traffic_ids))
response = bss_client.list_free_resource_usages(request)
print(f"{'='*100}")
print(f"{'Traffic Package ID':<40} {'Used':<15} {'Total':<15} {'Remaining':<15} {'Usage Rate':<10}")
print("=" * 100)
for item in response.free_resources:
unit = MEASURE_UNITS.get(getattr(item, 'measure_id', 10), "GB")
orig = getattr(item, 'original_amount', 0)
amt = getattr(item, 'amount', 0)
used = orig - amt
rate = f"{(used/orig*100):.1f}%" if orig > 0 else "0%"
print(f"{item.free_resource_id:<40} {f'{used:.2f} {unit}':<15} {f'{orig:.2f} {unit}':<15} {f'{amt:.2f} {unit}':<15} {rate:<10}")
print("=" * 100)
def query_traffic_by_region(self, target_region: str, resource_type="hcss.l-instance"):
"""Query traffic packages by region"""
print(f"Querying traffic packages in {target_region} region...\n")
config_client = self.auth.get_config_client(self.region)
bss_client = self.auth.get_bss_client()
request = ListAllResourcesRequest(type=resource_type)
response = config_client.list_all_resources(request)
instances = []
for r in response.resources:
if getattr(r, 'region_id', None) != target_region:
continue
props = r.properties or {}
cbc_id = None
for sub in props.get("resources", []):
if sub.get("logical_resource_type") == "huaweicloudinternal_cbc_freeresource":
cbc_id = sub.get("physical_resource_id")
if cbc_id:
instances.append({"name": r.name, "cbc_id": cbc_id})
if not instances:
print(f"No resources found")
return
traffic_ids = [i["cbc_id"] for i in instances]
request = ListFreeResourceUsagesRequest(body=ListFreeResourceUsagesReq(free_resource_ids=traffic_ids))
usage_resp = bss_client.list_free_resource_usages(request)
usages = {u.free_resource_id: u for u in usage_resp.free_resources}
print(f"\n{'='*120}")
print(f"Traffic query for {target_region}: {len(instances)} instance(s)")
print(f"{'='*120}")
print(f"{'No.':<6} {'Instance Name':<30} {'Used':<15} {'Total':<15} {'Remaining':<15} {'Usage Rate':<10}")
print("-" * 120)
for i, inst in enumerate(instances, 1):
u = usages.get(inst["cbc_id"])
if u:
unit = MEASURE_UNITS.get(getattr(u, 'measure_id', 10), "GB")
orig = getattr(u, 'original_amount', 0)
amt = getattr(u, 'amount', 0)
used = orig - amt
rate = f"{(used/orig*100):.1f}%" if orig > 0 else "0%"
print(f"{i:<6} {inst['name'][:28]:<30} {f'{used:.2f} {unit}':<15} {f'{orig:.2f} {unit}':<15} {f'{amt:.2f} {unit}':<15} {rate:<10}")
print("=" * 120)
def main():
"""Command line entry: parse arguments and execute query operations"""
parser = argparse.ArgumentParser(description="Flexus L instance query tool")
parser.add_argument("--ak", help="Access Key")
parser.add_argument("--sk", help="Secret Key")
parser.add_argument("--security-token", help="Security Token")
parser.add_argument("--region", "-r", default="cn-north-4", help="Region")
subparsers = parser.add_subparsers(dest="cmd")
subparsers.add_parser("list", help="List all resources")
subparsers.add_parser("free-resources", help="List Flexus L instances and traffic package IDs")
detail_p = subparsers.add_parser("detail", help="Query instance details")
detail_p.add_argument("--instance-id", "-i", required=True)
traffic_p = subparsers.add_parser("traffic", help="Query traffic package usage")
traffic_p.add_argument("traffic_ids", nargs="+", help="Traffic package IDs")
tr_p = subparsers.add_parser("traffic-region", help="Query traffic packages by region")
tr_p.add_argument("--target-region", "-t", required=True)
args = parser.parse_args()
if not args.cmd:
parser.print_help()
sys.exit(1)
client = InstanceQueryClient(ak=args.ak, sk=args.sk, security_token=args.security_token, region=args.region)
if args.cmd == "list":
client.list_all_regions()
elif args.cmd == "detail":
client.query_instance(args.instance_id)
elif args.cmd == "free-resources":
client.list_free_resources()
elif args.cmd == "traffic":
client.query_traffic(args.traffic_ids)
elif args.cmd == "traffic-region":
client.query_traffic_by_region(args.target_region)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
# coding: utf-8
"""Flexus L instance information update tool"""
import os
import sys
import re
from huaweicloudsdkcore.exceptions import exceptions
from huaweicloudsdkecs.v2 import (
UpdateServerRequest, UpdateServerRequestBody, UpdateServerOption
)
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from auth import AuthManager
def validate_name(name: str) -> tuple:
"""Validate name (1-64 characters, supports Chinese/letters/numbers/_-.)"""
if not name or len(name) > 64:
return False, "Name length must be 1-64 characters"
if not re.match(r'^[\u4e00-\u9fa5a-zA-Z0-9_\-\.]+$', name):
return False, "Name can only contain Chinese, letters, numbers, _, -, ."
return True, ""
def validate_description(desc: str) -> tuple:
"""Validate description (0-85 characters, cannot contain <>)"""
if len(desc) > 85:
return False, "Description length cannot exceed 85 characters"
if '<' in desc or '>' in desc:
return False, "Description cannot contain < or >"
return True, ""
def validate_hostname(hostname: str) -> tuple:
"""Validate hostname (1-64 characters, DNS compliant)"""
if not hostname or len(hostname) > 64:
return False, "Hostname length must be 1-64 characters"
if hostname.startswith('.') or hostname.startswith('-') or hostname.endswith('.') or hostname.endswith('-'):
return False, "Hostname cannot start or end with . or -"
if '..' in hostname or '--' in hostname or '.-' in hostname or '-.' in hostname:
return False, "Invalid hostname format"
for seg in hostname.split('.'):
if not seg or not re.match(r'^[a-zA-Z0-9\-]+$', seg):
return False, f"Invalid hostname segment: '{seg}'"
return True, ""
def update_server(server_id: str, region: str = "cn-north-4", name: str = None,
description: str = None, hostname: str = None, auth: AuthManager = None):
"""Update server information (name/description/hostname)"""
auth = auth or AuthManager()
if not auth.is_configured():
raise ValueError("Please set environment variables HW_ACCESS_KEY, HW_SECRET_KEY, HW_SECURITY_TOKEN or provide --ak --sk parameters")
if not any([name, description is not None, hostname]):
raise ValueError("Please provide at least one modification parameter")
for val, fn in [(name, validate_name), (description, validate_description), (hostname, validate_hostname)]:
if val is not None:
ok, err = fn(val)
if not ok:
raise ValueError(err)
client = auth.get_ecs_client(region)
kwargs = {k: v for k, v in [('name', name), ('description', description), ('hostname', hostname)] if v is not None}
try:
request = UpdateServerRequest(server_id=server_id, body=UpdateServerRequestBody(server=UpdateServerOption(**kwargs)))
response = client.update_server(request)
return {"success": True, "response": str(response)}
except exceptions.ClientRequestException as e:
return {"success": False, "error": {"status_code": e.status_code, "error_msg": e.error_msg}}
def main():
"""Command line entry: parse arguments and execute update operations"""
if len(sys.argv) < 2:
print("Usage: python update_server.py --instance-id <ID> [--name <name>] [--description <desc>] [--hostname <hostname>] [--region <region>] [--ak <AK>] [--sk <SK>] [--security-token <TOKEN>]")
sys.exit(1)
server_id, region, name, desc, hostname = None, "cn-north-4", None, None, None
ak, sk, security_token = None, None, None
i = 1
while i < len(sys.argv):
arg = sys.argv[i]
if arg == "--instance-id" and i + 1 < len(sys.argv):
server_id, i = sys.argv[i + 1], i + 2
elif arg == "--region" and i + 1 < len(sys.argv):
region, i = sys.argv[i + 1], i + 2
elif arg == "--name" and i + 1 < len(sys.argv):
name, i = sys.argv[i + 1], i + 2
elif arg == "--description" and i + 1 < len(sys.argv):
desc, i = sys.argv[i + 1], i + 2
elif arg == "--hostname" and i + 1 < len(sys.argv):
hostname, i = sys.argv[i + 1], i + 2
elif arg == "--ak" and i + 1 < len(sys.argv):
ak, i = sys.argv[i + 1], i + 2
elif arg == "--sk" and i + 1 < len(sys.argv):
sk, i = sys.argv[i + 1], i + 2
elif arg == "--security-token" and i + 1 < len(sys.argv):
security_token, i = sys.argv[i + 1], i + 2
else:
i += 1
if not server_id:
print("ERROR: Please provide --instance-id")
sys.exit(1)
auth = AuthManager(ak=ak, sk=sk, security_token=security_token)
print(f"Updating server: {server_id}")
result = update_server(server_id, region, name, desc, hostname, auth)
if result["success"]:
print("SUCCESS: Update successful")
else:
print(f"ERROR: Update failed: {result['error']['error_msg']}")
sys.exit(1)
if __name__ == "__main__":
main()