
Huawei Cloud Flexus L Server Openclaw Deployment
- 90 installs
- 19 repo stars
- Updated July 31, 2026
- huaweicloud/huaweicloud-skills
Create a Huawei Cloud Flexus L instance, deploy the OpenClaw AI agent platform on it, and install models and channels post-deployment.
About
Automates one-click deployment of the OpenClaw AI agent platform on a Flexus L instance, with instance creation plus model and channel installation via COC (WeCom, Feishu, DingTalk, QQ). A developer uses it to provision and configure OpenClaw end to end.
- Automated instance creation plus COC model/channel install
- Prerequisite Gateway and UniAgent status checks
Huawei Cloud Flexus L Server Openclaw Deployment by the numbers
- 90 all-time installs (skills.sh)
- +4 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #588 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-openclaw-deploymentAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 90 |
|---|---|
| repo stars | ★ 19 |
| Last updated | July 31, 2026 |
| Repository | huaweicloud/huaweicloud-skills ↗ |
What it does
Create a Huawei Cloud Flexus L instance, deploy the OpenClaw AI agent platform on it, and install models and channels post-deployment.
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 7. When using skill action=exec, credentials are automatically inherited from environment variables (HW_ACCESS_KEY, HW_SECRET_KEY, HW_SECURITY_TOKEN), no need to pass them as command line arguments
huawei-cloud-flexus-l-server-openclaw-deployment
Overview
This skill supports one-click deployment of the OpenClaw AI Agent platform to Huawei Cloud Flexus L Instance. It provides a complete OpenClaw instance management workflow, from initial deployment to post-deployment configuration, including:
- Automated instance creation
- Model installation via COC (Cloud Operations Center)
- Channel installation via COC (WeCom, Feishu, DingTalk, QQ)
- Automatic prerequisite checks before installation (Gateway and UniAgent status)
Use Cases
| Scenario | Description |
|---|---|
| Enterprise AI Assistant Setup | Enterprises need to quickly deploy an AI Agent platform for internal Q&A, customer service, etc. |
| Multi-Channel Bot Integration | Need to integrate multiple messaging channels (WeCom, Feishu, DingTalk) into a unified AI assistant |
| Quick LLM Integration | Existing OpenClaw instance needs to quickly switch or add different LLMs (DeepSeek, Qwen, etc.) |
| Automated Operations Deployment | Need to automatically batch deploy OpenClaw instances to multiple regions via scripts |
Typical Use Cases
User may say: 1. "I want to install OpenClaw on a Flexus L instance" 2. "I want to configure DeepSeek model on my deployed OpenClaw" 3. "Help me deploy OpenClaw with Feishu channel configured"
Prerequisites
Account Requirements
- Huawei Cloud AK/SK credentials with the following permissions:
- Create Flexus L Instances
- Access COC (Cloud Operations Center) services
Credential Acquisition Methods:
This skill supports obtaining Huawei Cloud credentials through the following methods (in order of priority from high to low):
Credential Types:
- Long-term AK/SK: Permanent credentials, no security_token required
- Temporary AK/SK: Temporary credentials with limited validity period, security_token required
1. Environment Variables (Default) (highest priority)
HW_ACCESS_KEY: Huawei Cloud Access Key AKHW_SECRET_KEY: Huawei Cloud Access Key SKHW_SECURITY_TOKEN: Security token (optional, only required for temporary credentials)
2. User-specified Configuration File or Other Environment Variables (used when default environment variables are not available)
- Configuration file path or other environment variables specified by user during interaction
3. Interactive Input (when neither of the above methods is provided)
- The program will prompt the user to enter AK/SK and other credential information
Important Notes:
- Long-term AK/SK: Permanent credentials that never expire, no security_token needed
- Temporary AK/SK: Obtained through IAM interface with limited validity period, must provide security_token
Architecture Diagram
This skill is built on multiple Huawei Cloud services, involving the following cloud services and components:
User/Agent ──────▶│ Flexus L Instance │──────▶│ OpenClaw App │──────▶│ Model Config │ ──────▶│ Channel Config │
(Skill caller) (Target Host) (AI Agent Platform) (API_BASE/KEY) (WeCom/Feishu/DingTalk/QQ) Component Description:
- User/Agent: Skill caller that triggers OpenClaw deployment operations via natural language or API
- Flexus L Instance: Huawei Cloud Elastic Cloud Server, serving as the target host for OpenClaw deployment
- OpenClaw App: AI Agent collaboration platform running on the Flexus L instance
- Model Config: Configuration for external LLM services (API_BASE, API_KEY, MODEL_IDS, PROVIDER)
- Channel Config: Messaging channel configuration (WeCom, Feishu, DingTalk, QQ)
---
How to Use This Skill
Command Execution and Instructions
1. Deploy OpenClaw Instance (Create Huawei Cloud Flexus L Instance and deploy OpenClaw AI Agent platform) - Two Command Modes:
Command 1: Interactive Mode (The program will prompt for required parameters step by step)
python scripts/caller.py deployCommand 2: Non-Interactive Mode
# Using long-term AK/SK (no security-token needed)
python scripts/caller.py deploy --name openclaw-{timestamp} --region cn-north-4 --ak <AK> --sk <SK> --non-interactive
# Using temporary AK/SK (security-token required)
python scripts/caller.py deploy --name openclaw-{timestamp} --region cn-north-4 --ak <Temporary AK> --sk <Temporary SK> --security-token <Security Token> --non-interactiveParameter Description:
| Parameter | Description | Required (Non-interactive) | Default (Interactive) | Example |
|---|---|---|---|---|
| --name | OpenClaw instance name | No | openclaw-{timestamp} | --name openclaw-1780689482000 |
| --region | Target region ID where L instance (OpenClaw deployed server) is located | No | cn-north-4 | --region cn-north-4 |
| --ak | Huawei Cloud Access Key AK (supports both long-term and temporary) | Yes | Prompted | --ak AXXX... |
| --sk | Huawei Cloud Access Key SK (supports both long-term and temporary) | Yes | Prompted | --sk SXXX... |
| --security-token | Security token for temporary credentials (optional, only required for temporary AK/SK) | No | Prompted | --security-token XXXX... |
| --non-interactive | Enable non-interactive mode | No | false | --non-interactive |
Note: OpenClaw only supports deployment in the following regions before June 2026 (before deploying to other regions, you can remind users to check the official website for the latest supported regions): China North-Beijing-4 (cn-north-4), China East-Shanghai-1 (cn-east-3), China South-Guangzhou (cn-south-1), China Southwest-Guiyang-1 (cn-southwest-2)
Command Examples:
# Example 1: Deploy with default configuration (interactive, will prompt for required parameters)
python scripts/caller.py deploy
# Example 2: Non-interactive mode deployment (suitable for automation scripts, creates directly without user confirmation)
python scripts/caller.py deploy --name openclaw-1780689482000 --region cn-north-4 --ak <Temporary AK> --sk <Temporary SK> --security-token <Security Token> --non-interactiveDefault Configuration for Huawei Cloud Flexus L Instance when Deploying OpenClaw Instance
| Configuration Item | Default Value | Description |
|---|---|---|
| Image | OpenClaw 2026.1.30 | OpenClaw application image version |
| Plan Spec | hf.small.1.linux or ahf.small.1.linux | hf.small.1.linux for Beijing/Shanghai/Guangzhou, ahf.small.1.linux for Guiyang |
| Charging Mode | Monthly subscription | prePaid mode |
| EVS Disk | 50GB | System disk size |
| CBR Backup | 50GB | Cloud backup capacity |
| HSS Host Security | Enabled | Host security service |
Execution Result and Status Code Description:
- On success, returns order ID and instance ID (resource ID, used for subsequent model and channel installation)
- Instance creation takes approximately 2 minutes, progress can be viewed in Huawei Cloud console. During instance creation, the installation of models and channels will not be affected, and subsequent commands can be executed directly.
Status Code Description: Status codes "200", "201", "202" all indicate successful instance creation. ---
2. Configure (Install) Large Model Parameters on L Instance with OpenClaw Installed - Two Command Modes (Requires deploying OpenClaw instance first)
Command 1: Interactive Mode (The program will prompt for resource ID, region, model and other parameters step by step)
python scripts/caller.py maasCommand 2: Non-Interactive Mode
# Using long-term AK/SK (no security-token needed)
python scripts/caller.py maas --resource-id <Instance Resource ID> --region-id cn-north-4 --model-params '<Model configuration parameters>' --ak <AK> --sk <SK> --non-interactive
# Using temporary AK/SK (security-token required)
python scripts/caller.py maas --resource-id <Instance Resource ID> --region-id cn-north-4 --model-params '<Model configuration parameters>' --ak <Temporary AK> --sk <Temporary SK> --security-token <Security Token> --non-interactiveParameter Description:
| Parameter | Description | Required (Non-interactive) | Default (Interactive) | Example |
|---|---|---|---|---|
| --resource-id | L instance resource ID (instance ID returned after deploying OpenClaw instance) | Yes | Prompted | --resource-id 0e1234567890abcdef |
| --region-id | Region ID where L instance is located, consistent with the region selected when deploying the instance | Yes | Prompted | --region-id cn-north-4 |
| --model-params | Model configuration parameters (JSON format), note: parameters must use valid JSON format, keys and values must be wrapped in double quotes | Yes | Prompted | --model-params '{"provider":"huawei","api_key":"your_maas_api_key","model_ids":["deepseek-v3.2"]}' |
| --ak | Huawei Cloud Access Key AK (supports both long-term and temporary) | Yes | Prompted | --ak AXXX... |
| --sk | Huawei Cloud Access Key SK (supports both long-term and temporary) | Yes | Prompted | --sk SXXX... |
| --security-token | Security token for temporary credentials (optional, only required for temporary AK/SK) | No | Prompted | --security-token XXXX... |
| --timeout | Script execution timeout (seconds) | No | 600 | --timeout 900 |
| --non-interactive | Enable non-interactive mode | No | false | --non-interactive |
model-params Field Description:
| Field | Description | Required |
|---|---|---|
| provider | Model provider name (e.g., "huawei") or API address (e.g., "https://api.openai.com/v1") | Yes |
| api_key | Model API key | Yes |
| model_ids | Array of model IDs to install (non-empty), e.g., ["gpt-4", "gpt-3.5-turbo"] | Yes |
Command Examples:
# Example 1: Install Huawei Cloud MaaS platform models with long-term AK/SK
python scripts/caller.py maas \
--resource-id 0e1234567890abcdef \
--region-id cn-north-4 \
--model-params '{"provider":"huawei","api_key":"your_maas_api_key","model_ids":["deepseek-v3.2","qwen3-235b-a22b"]}' \
--ak <Temporary AK> --sk <Temporary SK> --security-token <Security Token> --non-interactive
# Example 2: Install Huawei Cloud MaaS platform models with temporary AK/SK
python scripts/caller.py maas \
--resource-id 0e1234567890abcdef \
--region-id cn-north-4 \
--model-params '{"provider":"huawei","api_key":"your_maas_api_key","model_ids":["deepseek-v3.2","qwen3-235b-a22b"]}' \
--ak <Temporary AK> --sk <Temporary SK> --security-token <Security Token> --non-interactive
# Example 3: Install custom OpenAI compatible models with long-term AK/SK
python scripts/caller.py maas \
--resource-id 0e1234567890abcdef \
--region-id cn-north-4 \
--model-params '{"provider":"https://api.openai.com/v1","api_key":"your_openai_key","model_ids":["gpt-4"]}' \
--ak <Temporary AK> --sk <Temporary SK> --security-token <Security Token> --non-interactiveStatus Code Description: Status codes "200", "201", "202" all indicate successful model installation.
3. channel - Configure (Install) Channels on L Instance with OpenClaw Installed - Two Command Modes (Requires deploying OpenClaw instance first)
Command 1: Interactive Mode
python scripts/caller.py channelCommand 2: Non-Interactive Mode
# Using long-term AK/SK (no security-token needed)
python scripts/caller.py channel --resource-id <Instance Resource ID> --region-id cn-north-4 --channel-list '<JSON array>' --ak <AK> --sk <SK> --non-interactive
# Using temporary AK/SK (security-token required)
python scripts/caller.py channel --resource-id <Instance Resource ID> --region-id cn-north-4 --channel-list '<JSON array>' --ak <Temporary AK> --sk <Temporary SK> --security-token <Security Token> --non-interactiveParameter Description:
| Parameter | Description | Required (Non-interactive) | Default (Interactive) | Example |
|---|---|---|---|---|
| --resource-id | L instance resource ID (instance ID returned after deploying OpenClaw instance) | Yes | Prompted | --resource-id 0e1234567890abcdef |
| --region-id | Region ID where instance is located, consistent with the region selected when deploying the instance | Yes | Prompted | --region-id cn-north-4 |
| --channel-list | Channel configuration (JSON array format) | Yes | Prompted | '[{"channel":"wecom","id":"xxx","secret":"xxx"},{"channel":"feishu","id":"yyy","secret":"yyy"}]' |
| --ak | Huawei Cloud Access Key AK (supports both long-term and temporary) | Yes | Prompted | --ak AXXX... |
| --sk | Huawei Cloud Access Key SK (supports both long-term and temporary) | Yes | Prompted | --sk SXXX... |
| --security-token | Security token for temporary credentials (optional, only required for temporary AK/SK) | No | Prompted | --security-token XXXX... |
| --timeout | Script execution timeout (seconds) | No | 600 | --timeout 900 |
| --non-interactive | Enable non-interactive mode | No | false | --non-interactive |
channel JSON Object Field Description:
| Field | Description | Required |
|---|---|---|
| channel | Channel type: wecom (WeCom), feishu (Feishu), dingtalk (DingTalk), qqbot (QQ) | Yes |
| id | Bot ID/APP ID/Client ID | Yes |
| secret | Bot secret/APP secret/Client secret | Yes |
Command Examples:
# Example 1: Install multiple channels (WeCom + Feishu) using long-term AK/SK
python scripts/caller.py channel \
--resource-id 0e1234567890abcdef \
--region-id cn-north-4 \
--channel-list '[{"channel":"wecom","id":"xxx","secret":"xxx"},{"channel":"feishu","id":"yyy","secret":"yyy"}]' \
--ak <AK> --sk <SK> --non-interactive
# Example 2: Install multiple channels (WeCom + Feishu) using temporary AK/SK
python scripts/caller.py channel \
--resource-id 0e1234567890abcdef \
--region-id cn-north-4 \
--channel-list '[{"channel":"wecom","id":"xxx","secret":"xxx"},{"channel":"feishu","id":"yyy","secret":"yyy"}]' \
--ak <Temporary AK> --sk <Temporary SK> --security-token <Security Token> --non-interactiveStatus Code Description: Status codes "200", "201", "202" all indicate successful channel installation.
Web UI Access
Web UI access needs to be manually enabled in Huawei Cloud console, operation steps: 1. Log in to Huawei Cloud Flexus Application Server L Instance Console
- 🔗 Console URL: https://console.huaweicloud.com/smb/?/resource/list
2. Find your OpenClaw instance in the instance list 3. Click the instance name to enter the details page 4. In the left menu of the details page, find and click "Application Details" option, then enter the "Basic Configuration" tab 5. In the "Basic Configuration" tab, find the "Access OpenClaw Web Interface" option at the top left, click the "Enable" button. You will then get the URL address to access the OpenClaw Web interface.
Code Structure, File Responsibilities and Key Functions
This skill uses a modular architecture for easier maintenance:
scripts/
├── caller.py # Main entry - command line argument parsing, parameter parsing, command routing
├── lib.py # Core library - L instance creation, COC script management
├── utils.py # Utility functions - input prompts, credential configuration, region information
├── deploy.py # Deployment module - `do_deploy_openclaw()` function for OpenClaw instance creation
├── models.py # Model module - remote COC large model installation (with prerequisite checks), related functions `do_install_maas()`, `_check_prerequisites()`
├── channels.py # Channel module - remote COC channel installation (with prerequisite checks), related functions `do_install_channel()`, `_check_prerequisites()`
├── gateway.py # Gateway module - gateway status query (only for prerequisite checks), related functions `do_check_gateway()`
└── uniagent.py # UniAgent module - UniAgent status query (only for prerequisite checks), `do_check_uniagent()`Parameter Confirmation
Deployment Parameters
- --name: OpenClaw instance name, optional parameter, default is
openclaw-{timestamp} - --region: Target region ID, optional parameter, default is
cn-north-4 - --ak: Huawei Cloud temporary Access Key AK, required parameter
- --sk: Huawei Cloud temporary Access Key SK, required parameter
- --security-token: Security token for temporary credentials (required), required parameter
- --non-interactive: Enable non-interactive mode, optional parameter
Model Configuration Parameters
- --resource-id: L instance resource ID (instance ID returned after deploying OpenClaw instance), required parameter
- --region-id: Region ID where L instance is located, consistent with the region selected when deploying the instance, required parameter
- --model-params: Model configuration parameters (JSON format), required parameter
provider: Model provider name (e.g., "huawei") or API address (e.g., "https://api.openai.com/v1")api_key: Model API keymodel_ids: Array of model IDs to install (non-empty)- --ak: Huawei Cloud temporary Access Key AK, required parameter
- --sk: Huawei Cloud temporary Access Key SK, required parameter
- --security-token: Security token for temporary credentials (required), required parameter
- --timeout: Script execution timeout (seconds), optional parameter, default 600 seconds
Channel Configuration Parameters
- --resource-id: L instance resource ID (instance ID returned after deploying OpenClaw instance), required parameter
- --region-id: Region ID where L instance is located, consistent with the region selected when deploying the instance, required parameter
- --channel-list: Channel configuration (JSON array format), optional parameter
channel: Channel type:wecom(WeCom),feishu(Feishu),dingtalk(DingTalk),qqbot(QQ), requiredid: Bot ID, requiredsecret: Bot secret, required- --ak: Huawei Cloud temporary Access Key AK, required parameter
- --sk: Huawei Cloud temporary Access Key SK, required parameter
- --security-token: Security token for temporary credentials (required), required parameter
- --timeout: Script execution timeout (seconds), optional parameter, default 600 seconds
Environment Variable Support
All parameters can also be provided through environment variables:
HW_ACCESS_KEY: Huawei Cloud AK (corresponds to --ak parameter)HW_SECRET_KEY: Huawei Cloud SK (corresponds to --sk parameter)HW_SECURITY_TOKEN: Temporary credential security token (corresponds to --security-token parameter)HW_PROJECT_ID: Huawei Cloud Project ID (optional)
Common Issues Quick Solutions
| Issue | Solution |
|---|---|
| Instance creation failed | Check AK/SK permissions, ensure permission to create Flexus L instances |
| Model installation failed | Check if UniAgent status is ONLINE, if API Key is correct, if model-params parameter strictly uses JSON format |
| Channel installation failed | Check if bot parameters are correct, if bot is created on platform, if channel-list parameter strictly uses JSON array format |
IAM Permission Policy Reference
This document describes the Huawei Cloud IAM permission policies required for the OpenClaw one-click deployment skill.
Permission Requirements
1. Flexus L Instance Related Permissions
{
"Version": "1.1",
"Statement": [
{
"Action": [
"hcss:instance:create",
"hcss:instance:list",
"hcss:instance:get",
"hcss:instance:delete"
],
"Effect": "Allow",
"Resource": "*"
}
]
}2. COC (Cloud Operations Center) Related Permissions
{
"Version": "1.1",
"Statement": [
{
"Action": [
"coc:script:create",
"coc:script:execute",
"coc:script:query",
"coc:script:delete"
],
"Effect": "Allow",
"Resource": "*"
}
]
}3. IAM Related Permissions (Project ID Retrieval)
{
"Version": "1.1",
"Statement": [
{
"Action": [
"iam:project:list",
"iam:project:get"
],
"Effect": "Allow",
"Resource": "*"
}
]
}Recommended Policy Combination
Combine the above permissions into a complete custom policy:
{
"Version": "1.1",
"Statement": [
{
"Action": [
"hcss:instance:create",
"hcss:instance:list",
"hcss:instance:get",
"hcss:instance:delete",
"coc:script:create",
"coc:script:execute",
"coc:script:query",
"coc:script:delete",
"iam:project:list",
"iam:project:get"
],
"Effect": "Allow",
"Resource": "*"
}
]
}Permission Configuration Steps
1. Log in to Huawei Cloud console 2. Navigate to "IAM" -> "Users" -> Select target user 3. Click "Permissions" -> "Grant Permissions" 4. Select "Custom Policy" -> "Create Custom Policy" 5. Paste the above policy content and save 6. Grant the policy to the target user
Precautions
- Follow the principle of least privilege and only grant necessary permissions
- Regularly review and update permission policies
- Ensure AK/SK are stored securely when using them, avoid hard-coding
Skill Verification Method
This document describes the verification methods and test steps for the OpenClaw one-click deployment skill.
Verification Process
Phase 1: Environment Preparation Verification
Verification Items:
- [ ] Python version >= 3.8
- [ ] Dependencies installed (
pip install -r requirements.txt) - [ ] Huawei Cloud AK/SK configured
- [ ] Network connectivity normal
Verification Commands:
# Check Python version
python --version
# Check dependency installation
python -c "from huaweicloudsdkcore.signer.signer import Signer; print('SDK OK')"Note: AK/SK can be provided via command-line arguments (`--ak` and `--sk`) or entered in interactive mode
Phase 2: Deployment Functionality Verification
Verification Items:
- [ ] Instance created successfully
- [ ] Instance status normal
- [ ] Instance specification meets expectations
Verification Commands:
# Deploy instance (use smaller specification for test environment)
python scripts/caller.py deploy --name test-openclaw --region cn-north-4 --ak <AK> --sk <SK>
# Verify instance status (via Huawei Cloud console or API)Expected Results:
- Instance created successfully, status is "running"
- Instance specification is
hf.small.1.linux(Beijing/Shanghai/Guangzhou) orahf.small.1.linux(Guiyang) - Disk configuration is 50GB EVS
Phase 3: Model Installation Verification
Verification Items:
- [ ] UniAgent status is ONLINE
- [ ] Model installed successfully
- [ ] Model can be invoked normally
Verification Commands:
# Install model
python scripts/caller.py maas --resource-id <instance_id> --region-id cn-north-4 --model-params '{"provider":"huawei","api_key":"your_api_key","model_ids":["deepseek-v3.2"]}' --ak <AK> --sk <SK> --non-interactive
# Verify model status (via OpenClaw Web UI)Expected Results:
- UniAgent status check passed
- Model installation task executed successfully
- Model displayed in OpenClaw model list
Phase 4: Channel Installation Verification
Verification Items:
- [ ] Channel installed successfully
- [ ] Channel status normal
- [ ] Message sending and receiving normal
Verification Commands:
# Install channel
python scripts/caller.py channel --resource-id <instance_id> --region-id cn-north-4 --channel-list '[{"channel":"wecom","id":"xxx","secret":"xxx"}]' --ak <AK> --sk <SK> --non-interactiveExpected Results:
- Channel installation task executed successfully
- Channel displayed in OpenClaw channel list
- Can normally receive and send messages
Phase 5: Web UI Access Verification
Verification Items:
- [ ] Security group rules configured correctly
- [ ] Web UI accessible normally
- [ ] Login function normal
Verification Steps: 1. Log in to Huawei Cloud console 2. Configure security group rules to open port 18789 3. Access http://<public_ip>:18789 4. Verify login page displays normally
Common Issue Troubleshooting
Issue 1: AK/SK Verification Failed
Symptom:
Error: AK/SK verification failed, please check if credentials are correctTroubleshooting Steps: 1. Confirm AK/SK environment variables are set correctly 2. Confirm AK/SK have not expired 3. Confirm AK/SK have sufficient permissions
Issue 2: UniAgent Status Abnormal
Symptom:
UniAgent status: OFFLINE
Please ensure UniAgent is started and onlineTroubleshooting Steps: 1. Wait for instance to fully start (usually takes 5-10 minutes) 2. Check UniAgent status via Huawei Cloud console 3. Try restarting UniAgent service
Issue 3: Model Installation Timeout
Symptom:
Error: Execution timeout, please check network connection or increase timeout durationTroubleshooting Steps: 1. Increase timeout parameter --timeout 1200 2. Check instance network connection 3. Confirm model parameters are correct
Automated Test Script
You can create the following test script to automate the verification process:
#!/bin/bash
echo "=== OpenClaw Deployment Verification ==="
echo ""
echo "1. Checking Python version..."
python --version
echo ""
echo "2. Checking SDK installation..."
python -c "from huaweicloudsdkcore.signer.signer import Signer; print('SDK OK')"
echo ""
echo "=== Verification completed ==="Verification Matrix
| Verification Item | Success Criteria | Failure Handling |
|---|---|---|
| Environment Preparation | Python >= 3.8, dependencies installed successfully | Check Python version, reinstall dependencies |
| Credential Configuration | AK/SK provided via parameters or interactive input | Check if credentials are provided correctly |
| Instance Deployment | Instance created successfully, status running | Check permissions and network |
| Model Installation | Model installed successfully, can be invoked normally | Check UniAgent status and model parameters |
| Channel Installation | Channel installed successfully, can send and receive messages | Check channel configuration parameters |
#!/usr/bin/env python3
# coding: utf-8
"""
Huawei Cloud Flexus L Instance One-Click OpenClaw Deployment - Main Entry (Simplified Version)
"""
import argparse
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from scripts.utils import REGION_IDS
from scripts.deploy import do_deploy_openclaw
from scripts.models import do_install_maas
from scripts.channels import do_install_channel
CONSOLE_URL = "https://console.huaweicloud.com/smb/?/resource/list"
def show_main_menu():
"""
Display main menu for user to select operation type
Returns:
int: User's choice (0-4), where 0=Exit, 1=Deploy, 2=Models, 3=Channels, 4=WebUI
"""
print("=" * 60)
print(" OpenClaw One-Click Deployment Tool (Simplified)")
print("=" * 60)
print("Please select an operation:")
print("")
print(" 1. One-click deploy OpenClaw to Huawei Cloud Flexus L instance")
print(" 2. Add models to existing OpenClaw instance")
print(" 3. Add channels to existing OpenClaw instance")
print(" 4. View OpenClaw Web UI access instructions")
print(" 0. Exit")
print("")
print("=" * 60)
while True:
try:
choice = input("Please enter your choice (0-4): ")
choice = int(choice)
if choice in [0, 1, 2, 3, 4]:
return choice
else:
print("Invalid input, please enter a number between 0-4")
except ValueError:
print("Invalid input, please enter a number")
def show_webui_info():
"""
Display Web UI access instructions
Returns:
None
"""
print("=" * 60)
print(" OpenClaw Web UI Access Instructions")
print("=" * 60)
print("")
print("Web UI access requires manual security group configuration in Huawei Cloud console.")
print("")
print("Steps:")
print("1. Login to Huawei Cloud Flexus Application Server L instance console")
print(f" 🔗 Console URL: {CONSOLE_URL}")
print("")
print("2. Find your OpenClaw instance in the instance list")
print("")
print("3. Click the instance name to view details")
print("")
print('4. Find "Security" or "Network" option in the left menu')
print("")
print("5. Configure security group rules to open port 18789")
print("")
print("Access URL: http://<instance-public-ip>:18789")
print("")
print("=" * 60)
print("Security Note: Once the port is opened, OpenClaw Web UI will be accessible. Please evaluate security risks before proceeding.")
print("=" * 60)
def main():
"""
Main entry point for OpenClaw deployment tool
Returns:
None
"""
parser = argparse.ArgumentParser(
description="Huawei Cloud Flexus L Instance One-Click OpenClaw Deployment (Simplified Version)",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
# Interactive mode (show menu for selection)
python scripts/caller.py
# Create OpenClaw instance with long-term AK/SK
python scripts/caller.py deploy --name my-openclaw --region cn-north-4 --ak <AK> --sk <SK>
# Create OpenClaw instance with temporary AK/SK (requires security-token)
python scripts/caller.py deploy --name my-openclaw --region cn-north-4 --ak <Temporary-AK> --sk <Temporary-SK> --security-token <Security-Token>
# Install models on remote L instance via COC
python scripts/caller.py maas --resource-id <instance_id> --region-id cn-north-4 --model-params <json> --ak <AK> --sk <SK>
# Install channels on remote L instance via COC
python scripts/caller.py channel --resource-id <instance_id> --region-id cn-north-4 --channel-list <json> --ak <AK> --sk <SK>
""",
)
subparsers = parser.add_subparsers(dest='command', help='Available commands')
deploy_parser = subparsers.add_parser('deploy', help='Deploy OpenClaw instance')
deploy_parser.add_argument('--name', help='Instance name (optional, auto-generated if not provided)')
deploy_parser.add_argument('--region', choices=REGION_IDS, help='Region ID (optional, default cn-north-4)')
deploy_parser.add_argument('--ak', help='Huawei Cloud AK (supports both long-term and temporary AK, optional, will prompt for input if not provided)')
deploy_parser.add_argument('--sk', help='Huawei Cloud SK (supports both long-term and temporary SK, optional, will prompt for input if not provided)')
deploy_parser.add_argument('--security-token', help='Huawei Cloud Security Token (optional, only required for temporary AK/SK, will prompt for input if not provided)')
deploy_parser.add_argument('--non-interactive', action='store_true', help='Non-interactive mode, execute without confirmation')
maas_parser = subparsers.add_parser('maas', help='Install models on remote L instance via COC')
maas_parser.add_argument('--resource-id', help='L instance resource ID (required)')
maas_parser.add_argument('--region-id', choices=REGION_IDS, help='Region ID (optional, default cn-north-4)')
maas_parser.add_argument('--model-params', help='Model parameters JSON (optional)')
maas_parser.add_argument('--timeout', type=int, help='Timeout in seconds (optional, default 600)')
maas_parser.add_argument('--execute-user', default='root', help='Execute user (optional, default root)')
maas_parser.add_argument('--ak', help='Huawei Cloud AK (supports both long-term and temporary AK, optional, will prompt for input if not provided)')
maas_parser.add_argument('--sk', help='Huawei Cloud SK (supports both long-term and temporary SK, optional, will prompt for input if not provided)')
maas_parser.add_argument('--security-token', help='Huawei Cloud Security Token (optional, only required for temporary AK/SK, will prompt for input if not provided)')
maas_parser.add_argument('--non-interactive', action='store_true', help='Non-interactive mode, execute without confirmation')
channel_parser = subparsers.add_parser('channel', help='Install channels on remote L instance via COC')
channel_parser.add_argument('--resource-id', help='L instance resource ID (required)')
channel_parser.add_argument('--region-id', choices=REGION_IDS, help='Region ID (optional, default cn-north-4)')
channel_parser.add_argument('--channel-list', help='Channel list JSON (optional)')
channel_parser.add_argument('--timeout', type=int, help='Timeout in seconds (optional, default 600)')
channel_parser.add_argument('--execute-user', default='root', help='Execute user (optional, default root)')
channel_parser.add_argument('--ak', help='Huawei Cloud AK (supports both long-term and temporary AK, optional, will prompt for input if not provided)')
channel_parser.add_argument('--sk', help='Huawei Cloud SK (supports both long-term and temporary SK, optional, will prompt for input if not provided)')
channel_parser.add_argument('--security-token', help='Huawei Cloud Security Token (optional, only required for temporary AK/SK, will prompt for input if not provided)')
channel_parser.add_argument('--non-interactive', action='store_true', help='Non-interactive mode, execute without confirmation')
args = parser.parse_args()
try:
if args.command == 'maas':
do_install_maas(args)
elif args.command == 'channel':
do_install_channel(args)
elif args.command == 'deploy':
do_deploy_openclaw(args)
else:
choice = show_main_menu()
if choice == 0:
print("Exit program")
sys.exit(0)
elif choice == 1:
args.command = 'deploy'
do_deploy_openclaw(args)
elif choice == 2:
args.command = 'maas'
do_install_maas(args)
elif choice == 3:
args.command = 'channel'
do_install_channel(args)
elif choice == 4:
show_webui_info()
except KeyboardInterrupt:
print("\n\nUser interrupted operation")
sys.exit(0)
if __name__ == '__main__':
main()
#!/usr/bin/env python3
# coding: utf-8
"""
Huawei Cloud Flexus L Instance One-Click OpenClaw Deployment - Channel Installation Module
"""
import json
import re
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from scripts.lib import install_channel_remote, install_channel_local, query_uniagent_status
from scripts.utils import prompt_for_input, REGION_IDS
def _check_prerequisites(resource_id, region_id, ak, sk, security_token):
"""
Check prerequisites (UniAgent status)
Args:
resource_id: L instance resource ID
region_id: Region ID
ak: Huawei Cloud AK (supports both long-term and temporary AK)
sk: Huawei Cloud SK (supports both long-term and temporary SK)
security_token: Security token for temporary credentials (optional, only required for temporary AK/SK)
Returns:
bool: True if check passed, False if check failed
"""
print("\nChecking UniAgent status...")
result = query_uniagent_status(resource_id, ak, sk, security_token)
if not result.get("ok"):
print(f" [FAIL] UniAgent status check failed: {result.get('error', {}).get('message', 'Unknown error')}")
return False
data = result.get("result", {})
resources = data.get("data", [])
if not resources:
print(" [FAIL] Instance information not found")
return False
for resource in resources:
agent_state = resource.get("agent_state", "")
if agent_state == "ONLINE":
print(" [OK] UniAgent status: ONLINE")
return True
else:
print(f" [FAIL] UniAgent status: {agent_state}")
print(" Please ensure UniAgent is started and online")
return False
return False
def do_install_channel(args):
"""
Execute channel installation
Args:
args: Command line argument object with the following attributes:
- resource_id: L instance resource ID (command line arg --resource-id)
- region_id: Region ID (command line arg --region-id)
- channel_list: Channel configuration JSON (command line arg --channel-list)
- timeout: Timeout duration (command line arg --timeout)
- execute_user: Execute user (command line arg --execute-user)
- ak: Huawei Cloud AK (supports both long-term and temporary AK) (command line arg --ak)
- sk: Huawei Cloud SK (supports both long-term and temporary SK) (command line arg --sk)
- security_token: Security token for temporary credentials (optional, only required for temporary AK/SK) (command line arg --security-token)
- non_interactive: Whether non-interactive mode (command line arg --non-interactive)
Returns:
None
"""
print("=" * 60)
print(" OpenClaw Channel Installation")
print("=" * 60)
ak = getattr(args, 'ak', None)
sk = getattr(args, 'sk', None)
security_token = getattr(args, 'security_token', None)
if not ak or not sk:
print("\nHuawei Cloud credentials not configured, entering interactive configuration...")
print("Please configure Huawei Cloud credentials:")
print(" - Long-term AK/SK: No security_token required")
print(" - Temporary AK/SK: Security token required")
print("-" * 40)
ak = prompt_for_input("Huawei Cloud AK (HW_ACCESS_KEY)", required=True)
sk = prompt_for_input("Huawei Cloud SK (HW_SECRET_KEY)", required=True, hide_input=True)
security_token = prompt_for_input("Security Token (optional, only for temporary credentials)", required=False)
resource_id = args.resource_id if hasattr(args, 'resource_id') and args.resource_id else None
region_id = args.region_id if hasattr(args, 'region_id') and args.region_id else None
channel_list = args.channel_list if hasattr(args, 'channel_list') and args.channel_list else ""
timeout = args.timeout if hasattr(args, 'timeout') and args.timeout else 600
non_interactive = args.non_interactive if hasattr(args, 'non_interactive') else False
if not resource_id:
resource_id = prompt_for_input("L instance resource ID", required=True)
if not region_id:
region_id = prompt_for_input("Region ID", required=False, default="cn-north-4", choices=REGION_IDS)
if not channel_list:
print("\nChannel list format example:")
print(' [{"channel":"wecom","id":"xxx","secret":"xxx"}]')
print("\nChannel JSON object fields:")
print(" - channel: Channel type (required): 'wecom', 'feishu', 'dingtalk', 'qqbot'")
print(" - id: Bot ID/APP ID/Client ID (required)")
print(" - secret: Bot secret/APP secret/Client secret (required)")
channel_list = prompt_for_input("Channel configuration JSON (optional, press Enter to skip)", required=False)
def normalize_json_string(input_str):
"""
Automatically convert non-standard JSON (no quotes/single quotes) to standard double-quoted JSON
Args:
input_str: Input JSON string, can be non-standard format without quotes
Returns:
str: Standard JSON string with double quotes
Examples:
Input: [{key:val}, {key:val}]
Output: [{"key":"val"}, {"key":"val"}]
"""
if not input_str or input_str.strip() == "":
return ""
raw_str = input_str.strip()
try:
# 如果已经是标准JSON,直接格式化返回
parsed = json.loads(raw_str)
return json.dumps(parsed, ensure_ascii=False)
except json.JSONDecodeError:
# 修复非标准JSON:自动添加双引号
processed = re.sub(r'([{\[,])\s*([a-zA-Z0-9_]+)\s*:', r'\1"\2":', raw_str)
processed = re.sub(r':\s*([a-zA-Z0-9_\-\.]+)\s*([,}\]])', r':"\1"\2', processed)
# 验证修复后的结果
try:
parsed = json.loads(processed)
return json.dumps(parsed, ensure_ascii=False)
except json.JSONDecodeError as e:
print(f"\n[ERROR] Channel list JSON format invalid: {e}")
print(f"Input: {input_str}")
raise SystemExit("Please provide valid JSON with DOUBLE quotes.")
if channel_list:
channel_list = normalize_json_string(channel_list)
if not timeout:
timeout = int(prompt_for_input("Timeout (seconds)", required=False, default="600"))
print(f"\nInstallation configuration:")
print(f" Resource ID: {resource_id}")
print(f" Region: {region_id}")
print(f" Channel list: {channel_list or 'Default'}")
print(f" Timeout: {timeout} seconds")
if not non_interactive:
confirm = prompt_for_input("Confirm installation?", required=False, default="y", choices=["y", "n"])
if confirm.lower() != "y":
print("\nInstallation cancelled")
return
print("\nChecking prerequisites...")
if not _check_prerequisites(resource_id, region_id, ak, sk, security_token):
print("\nPrerequisite check failed. Please resolve issues and retry")
return
print("\nStarting channel installation...")
result = install_channel_remote(resource_id, region_id, channel_list, timeout, "root", ak, sk, security_token)
if result.get("ok"):
print(f"\n[OK] {result['text']}")
if result.get("result"):
print(f" Execution ID: {result['result'].get('execute_uuid', 'Unknown')}")
print(f" Status: {result['result'].get('status', 'Unknown')}")
if result['result'].get('output'):
print(f" Output: {result['result']['output'][:200]}...")
else:
print(f"\n[FAIL] Installation failed")
if result.get("error"):
print(f" Error code: {result['error'].get('code')}")
print(f" Error message: {result['error'].get('message')}")#!/usr/bin/env python3
# coding: utf-8
"""
Huawei Cloud Flexus L Instance One-Click OpenClaw Deployment - Deployment Module
"""
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from scripts.lib import create_openclaw_instance
from scripts.utils import print_region_list, prompt_for_input, REGION_IDS, get_region_id_by_name, REGIONS
def do_deploy_openclaw(args):
"""
Execute OpenClaw instance deployment
Args:
args: Command line argument object with the following attributes:
- name: Instance name (command line arg --name)
- region: Region ID (command line arg --region)
- ak: Huawei Cloud AK (supports both long-term and temporary AK) (command line arg --ak)
- sk: Huawei Cloud SK (supports both long-term and temporary SK) (command line arg --sk)
- security_token: Security token for temporary credentials (optional, only required for temporary AK/SK) (command line arg --security-token)
- non_interactive: Whether non-interactive mode (command line arg --non-interactive)
Returns:
None
"""
print("=" * 60)
print(" OpenClaw Instance One-Click Deployment")
print("=" * 60)
ak = getattr(args, 'ak', None)
sk = getattr(args, 'sk', None)
security_token = getattr(args, 'security_token', None)
if not ak or not sk:
print("\nHuawei Cloud credentials not configured, entering interactive configuration...")
print("Please configure Huawei Cloud credentials:")
print(" - Long-term AK/SK: No security_token required")
print(" - Temporary AK/SK: Security token required")
print("-" * 40)
ak = prompt_for_input("Huawei Cloud AK (HW_ACCESS_KEY)", required=True)
sk = prompt_for_input("Huawei Cloud SK (HW_SECRET_KEY)", required=True, hide_input=True)
security_token = prompt_for_input("Security Token (optional, only for temporary credentials)", required=False)
instance_name = args.name if hasattr(args, 'name') and args.name else None
region = args.region if hasattr(args, 'region') and args.region else None
if not instance_name:
instance_name = prompt_for_input("Instance name (optional, press Enter to auto-generate)", required=False)
if not region:
print_region_list()
print("Tip: You can enter region ID (e.g. cn-southwest-2) or Chinese name (e.g. 西南-贵阳一)")
user_input = prompt_for_input("Target region", required=False, default="cn-north-4")
region = get_region_id_by_name(user_input)
while region not in REGION_IDS:
print(f"Error: '{region}' is not a valid region.")
print_region_list()
user_input = prompt_for_input("Please re-enter target region", required=False, default="cn-north-4")
region = get_region_id_by_name(user_input)
region_name = REGIONS.get(region, region)
print(f"\nDeployment configuration:")
print(f" Instance name: {instance_name or 'Auto-generated'}")
print(f" Target region: {region} ({region_name})")
non_interactive = getattr(args, 'non_interactive', False)
if not non_interactive:
confirm = prompt_for_input("Confirm deployment?", required=False, default="y", choices=["y", "n"])
if confirm.lower() != "y":
print("\nDeployment cancelled")
return
else:
print(" Non-interactive mode: Auto-confirming")
print("\nStarting to create OpenClaw instance...")
result = create_openclaw_instance(instance_name, region, ak, sk,security_token)
if result.get("ok"):
print(f"\n[OK] {result['text']}")
if result.get("result"):
print(f" Order ID: {result['result'].get('order_id', 'Unknown')}")
print(f" Instance ID: {result['result'].get('instance_ids', ['Unknown'])[0]}")
print("\nDeployment completed!")
print("Tip: Instance creation takes a few minutes, please wait patiently.")
else:
print(f"\n[FAIL] Deployment failed")
if result.get("error"):
print(f" Error code: {result['error'].get('code')}")
print(f" Error message: {result['error'].get('message')}")
#!/usr/bin/env python3
# coding: utf-8
"""
Huawei Cloud Flexus L Instance One-Click OpenClaw Deployment - Gateway Status Query Module
"""
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from scripts.lib import check_gateway_status_remote
from scripts.utils import prompt_for_input, REGION_IDS
def do_check_gateway(args):
"""
Execute gateway status query
Args:
args: Command line argument object with the following attributes:
- resource_id: L instance resource ID
- region_id: Region ID
- ak: Huawei Cloud AK (supports both long-term and temporary AK)
- sk: Huawei Cloud SK (supports both long-term and temporary SK)
- security_token: Security token for temporary credentials (optional, only required for temporary AK/SK)
Returns:
None
"""
print("=" * 60)
print(" OpenClaw Gateway Status Query")
print("=" * 60)
ak = getattr(args, 'ak', None)
sk = getattr(args, 'sk', None)
security_token = getattr(args, 'security_token', None)
if not ak or not sk:
print("\nHuawei Cloud credentials not configured, entering interactive configuration...")
print("Please configure Huawei Cloud credentials:")
print(" - Long-term AK/SK: No security_token required")
print(" - Temporary AK/SK: Security token required")
print("-" * 40)
ak = prompt_for_input("Huawei Cloud AK (HW_ACCESS_KEY)", required=True)
sk = prompt_for_input("Huawei Cloud SK (HW_SECRET_KEY)", required=True, hide_input=True)
security_token = prompt_for_input("Security Token (optional, only for temporary credentials)", required=False)
resource_id = args.resource_id if hasattr(args, 'resource_id') and args.resource_id else None
region_id = args.region_id if hasattr(args, 'region_id') and args.region_id else None
if not resource_id:
resource_id = prompt_for_input("L instance resource ID", required=True)
if not region_id:
region_id = prompt_for_input("Region ID", required=False, default="cn-north-4", choices=REGION_IDS)
print(f"\nQuery configuration:")
print(f" Resource ID: {resource_id}")
print(f" Region: {region_id}")
print("\nQuerying gateway status...")
result = check_gateway_status_remote(resource_id, region_id, 600, "root", ak, sk,security_token)
if result.get("ok"):
print(f"\n[OK] {result['text']}")
if result.get("result"):
print(f" Execution ID: {result['result'].get('execute_uuid', 'Unknown')}")
print(f" Status: {result['result'].get('status', 'Unknown')}")
if result['result'].get('output'):
print(f" Output:\n{result['result']['output']}")
else:
print(f"\n[FAIL] Query failed")
if result.get("error"):
print(f" Error code: {result['error'].get('code')}")
print(f" Error message: {result['error'].get('message')}")
#!/usr/bin/env python3
# Copyright (c) Huawei Technologies CO., LTD. 2022-2025. All rights reserved.
# coding=utf-8
"""
Huawei Cloud Flexus L Instance One-Click OpenClaw Deployment Core Module
Contains:
1. L instance creation functionality
2. COC script management functionality (create script, execute script)
3. Model installation functionality
4. Channel installation functionality
"""
import json
import os
import requests
import uuid
from datetime import datetime
from urllib.parse import urlparse
from typing import Any, Optional, List, Dict
class Credentials:
def __init__(self, ak, sk, security_token=None):
self.ak = ak
self.sk = sk
self.security_token = security_token
def get_project_id_by_region(region: str, ak: str, sk: str, security_token: str = None) -> Optional[str]:
"""
Get Project ID for specified region via AK/SK
Args:
region: Target region, e.g. cn-north-4, cn-southwest-2
ak: Huawei Cloud AK (supports both long-term and temporary AK)
sk: Huawei Cloud SK (supports both long-term and temporary SK)
security_token: Security token for temporary credentials (optional, only required for temporary AK/SK)
Returns:
Project ID string, or None if failed
"""
if not ak or not sk:
print("Error: Credentials not configured")
return None
iam_endpoint = f"https://iam.{region}.myhuaweicloud.com/v3/projects"
try:
from huaweicloudsdkcore.signer.signer import Signer
from huaweicloudsdkcore.sdk_request import SdkRequest
credentials = Credentials(ak, sk, security_token)
signer = Signer(credentials)
request = SdkRequest()
request.method = "GET"
request.schema = "https"
request.host = f"iam.{region}.myhuaweicloud.com"
request.resource_path = "/v3/projects"
request.body = ""
request.header_params = {
"Content-Type": "application/json",
"Client-Request-Id": str(uuid.uuid4())
}
if security_token:
request.header_params["X-Security-Token"] = security_token
request.query_params = []
signed_request = signer.sign(request)
headers = {}
for key, value in signed_request.header_params.items():
if isinstance(value, bytes):
headers[key] = value.decode('iso-8859-1')
else:
headers[key] = str(value)
print(f"Getting Project ID - Request URL: {iam_endpoint}")
resp = requests.get(iam_endpoint, headers=headers, timeout=30)
if resp.status_code == 200:
data = resp.json()
projects = data.get('projects', [])
if projects:
for project in projects:
project_name = project.get('name', '')
if project_name == region:
return project.get('id')
return projects[0].get('id')
else:
print("Error: Project not found")
return None
else:
print(f"Failed to get Project ID - Status code: {resp.status_code}, Response: {resp.text}")
return None
except ImportError as e:
print(f"SDK import failed: {str(e)}")
return None
except Exception as e:
print(f"Error getting Project ID: {str(e)}")
return None
def get_coc_client(ak: str, sk: str, security_token: str = None):
"""
Create and return COC client
Args:
ak: Huawei Cloud AK (supports both long-term and temporary AK)
sk: Huawei Cloud SK (supports both long-term and temporary SK)
security_token: Security token for temporary credentials (optional, only required for temporary AK/SK)
Returns:
CocClient instance
"""
from huaweicloudsdkcore.auth.credentials import GlobalCredentials
from huaweicloudsdkcoc.v1.region.coc_region import CocRegion
from huaweicloudsdkcoc.v1 import CocClient
if not ak or not sk:
raise ValueError("COC credentials not configured, please provide AK and SK parameters. For temporary credentials, also provide security_token.")
region = os.environ.get("HUAWEICLOUD_REGION", "cn-north-4")
if security_token is None:
credentials = GlobalCredentials(ak, sk)
else:
credentials = GlobalCredentials(ak, sk).with_security_token(security_token)
client = CocClient.new_builder() \
.with_credentials(credentials) \
.with_region(CocRegion.value_of(region)) \
.build()
return client
def create_openclaw_instance(instance_name = None, region = None, ak = None, sk = None, security_token = None):
"""
Create Huawei Cloud Flexus L instance (dedicated for OpenClaw)
API Reference: https://support.huaweicloud.com/api-flexusl/create_instance_0001.html
Args:
instance_name: Instance name, optional, auto-generated as openclaw-timestamp if not specified
region: Target region, optional, defaults to cn-north-4 if not specified
ak: Huawei Cloud AK (supports both long-term and temporary AK), required
sk: Huawei Cloud SK (supports both long-term and temporary SK), required
security_token: Security token for temporary credentials (optional, only required for temporary AK/SK)
Returns:
dict: Result dictionary containing ok, text, result, error fields
"""
if not ak or not sk:
return {
"ok": False,
"text": "Authentication temporary credentials not configured",
"result": None,
"error": {
"code": "CONFIG_ERROR",
"message": "Please provide AK and SK parameters. For temporary credentials, also provide security_token."
}
}
target_region = region if region else "cn-north-4"
project_id = get_project_id_by_region(target_region, ak, sk, security_token)
if not project_id:
return {
"ok": False,
"text": "Failed to get Project ID",
"result": None,
"error": {
"code": "PROJECT_ID_ERROR",
"message": f"Cannot get Project ID for region {target_region}, please verify credentials"
}
}
if not instance_name:
instance_name = f"openclaw-{datetime.now().strftime('%Y%m%d%H%M%S')}"
endpoint = "https://hcss.cn-north-4.myhuaweicloud.com/v1/light-instances"
if target_region == "cn-southwest-2":
plan_spec = "ahf.small.1.linux"
else:
plan_spec = "hf.small.1.linux"
request_body = {
"instance_name": instance_name,
"plan_spec": plan_spec,
"image_ref": {
"image_name": "OpenClaw",
"image_version": "2026.1.30"
},
"region": target_region,
"charging_mode": "prePaid",
"period_type": "month",
"period_num": 1,
"purchase_quantity": 1,
"description": "OpenClaw one-click deployment",
"is_auto_renew": True,
"is_auto_pay": True,
"extra_resources": [
{"type": "evs", "size": 50},
{"type": "cbr", "size": 50},
{"type": "hss"}
]
}
try:
from huaweicloudsdkcore.signer.signer import Signer
from huaweicloudsdkcore.sdk_request import SdkRequest
credentials = Credentials(ak, sk, security_token)
signer = Signer(credentials)
parsed_url = urlparse(endpoint)
body_str = json.dumps(request_body, ensure_ascii=False, separators=(',', ':'))
request = SdkRequest()
request.method = "POST"
request.schema = parsed_url.scheme
request.host = parsed_url.hostname
request.resource_path = parsed_url.path
request.body = body_str
request.header_params = {
"X-Project-Id": project_id,
"Content-Type": "application/json",
"Client-Request-Id": str(uuid.uuid4())
}
if security_token:
request.header_params["X-Security-Token"] = security_token
request.query_params = []
signed_request = signer.sign(request)
headers = {}
for key, value in signed_request.header_params.items():
if isinstance(value, bytes):
headers[key] = value.decode('iso-8859-1')
else:
headers[key] = str(value)
print(f"Authorization info: {headers.get('Authorization')}")
print(f"Request headers: {headers}")
print(f"Request body: {body_str}")
resp = requests.request(
"POST",
endpoint,
headers=headers,
data=body_str.encode('utf-8'),
verify=True
)
print(f"Status code: {resp.status_code}")
print(f"Response: {resp.text}")
if resp.status_code in [200, 201, 202]:
response_data = resp.json()
return {
"ok": True,
"text": f"Instance creation request submitted, instance ID: {response_data.get('instance_id', 'Unknown')}",
"result": response_data,
"error": None
}
else:
return {
"ok": False,
"text": f"Instance creation failed: {resp.reason}",
"result": None,
"error": {
"code": str(resp.status_code),
"message": resp.text
}
}
except ImportError as e:
return {
"ok": False,
"text": "SDK import failed",
"result": None,
"error": {
"code": "SDK_ERROR",
"message": f"Please install huaweicloudsdkcore: {str(e)}"
}
}
except Exception as e:
return {
"ok": False,
"text": f"Error creating instance: {str(e)}",
"result": None,
"error": {
"code": "UNKNOWN_ERROR",
"message": str(e)
}
}
VALID_SCRIPT_TYPES = ["SHELL", "PYTHON", "BAT"]
VALID_RISK_LEVELS = ["LOW", "MEDIUM", "HIGH"]
VALID_ROTATION_STRATEGIES = ["CONTINUE", "STOP"]
def _error(code: str, message: str) -> dict:
"""
Create error response
Args:
code: Error code
message: Error message
Returns:
dict: Standard error response dictionary
"""
return {
"ok": False,
"text": "",
"result": None,
"error": {"code": code, "message": message},
}
def coc_create_script(
name: str,
script_type: str,
content: str,
description: str,
risk_level: str = "LOW",
version: str = "1.0.0",
ak: str = None,
sk: str = None,
security_token: str = None
) -> dict[str, Any]:
"""
Create custom script in COC
Args:
name: Script name
script_type: Script type (SHELL/PYTHON/BAT)
content: Script content
description: Script description
risk_level: Risk level (LOW/MEDIUM/HIGH), default LOW
version: Script version, default 1.0.0
ak: Huawei Cloud AK (supports both long-term and temporary AK)
sk: Huawei Cloud SK (supports both long-term and temporary SK)
security_token: Security token for temporary credentials (optional, only required for temporary AK/SK)
Returns:
{
"ok": True,
"text": "Script created successfully: SC2023102521413701c4a8a62",
"result": { original API result },
"error": None
}
"""
if not name:
return _error("INPUT_ERROR", "name parameter is required")
if script_type not in VALID_SCRIPT_TYPES:
return _error("INPUT_ERROR", f"script_type must be one of {VALID_SCRIPT_TYPES}")
if not content:
return _error("INPUT_ERROR", "content parameter is required")
if not description:
return _error("INPUT_ERROR", "description parameter is required")
if risk_level not in VALID_RISK_LEVELS:
return _error("INPUT_ERROR", f"risk_level must be one of {VALID_RISK_LEVELS}")
try:
client = get_coc_client(ak, sk,security_token)
except ValueError as e:
return _error("CONFIG_ERROR", str(e))
try:
from huaweicloudsdkcoc.v1 import CreateScriptRequest
from huaweicloudsdkcoc.v1.model.script_properties_model import ScriptPropertiesModel
from huaweicloudsdkcoc.v1.model.add_script_model import AddScriptModel
request = CreateScriptRequest()
properties = ScriptPropertiesModel(
risk_level=risk_level,
version=version
)
request.body = AddScriptModel(
name=name,
type=script_type,
content=content,
description=description,
properties=properties
)
response = client.create_script(request)
script_uuid = response.data if hasattr(response, 'data') else str(response)
return {
"ok": True,
"text": f"Script created successfully: {script_uuid}",
"result": {"script_uuid": script_uuid},
"error": None,
}
except Exception as e:
error_msg = str(e)
if "error_code" in error_msg.lower() or "error_msg" in error_msg.lower():
return _error("API_ERROR", error_msg)
return _error("UNKNOWN_ERROR", error_msg)
def coc_execute_script(
script_uuid: str,
execute_user: str,
timeout: int,
success_rate: float,
target_instances: List[Dict[str, str]],
rotation_strategy: str = "CONTINUE",
wait_for_complete: bool = True,
ak: str = None,
sk: str = None,
security_token: str = None
) -> dict[str, Any]:
"""
Execute custom script on target instances
Args:
script_uuid: Script UUID to execute
execute_user: User to execute script (e.g., root)
timeout: Execution timeout (seconds, 5 < timeout < 1800)
success_rate: Success rate (supports one decimal, e.g., 1 or 100)
target_instances: Target instance list, each instance contains:
- resource_id: Instance ID (required)
- region_id: Server region (required)
- provider: Resource provider (not needed for ECS, defaults to "HCSS" for L instances)
- type: Resource type (not needed for ECS, defaults to "L-INSTANCE" for L instances)
rotation_strategy: Rotation strategy (CONTINUE/STOP), default CONTINUE
wait_for_complete: Whether to wait for execution completion and get logs, default True
ak: Huawei Cloud AK (supports both long-term and temporary AK)
sk: Huawei Cloud SK (supports both long-term and temporary SK)
security_token: Security token for temporary credentials (optional, only required for temporary AK/SK)
Returns:
{
"ok": True,
"text": "Script execution started: SCT2023083109562601af694bf",
"result": {
"execute_uuid": "SCT2023083109562601af694bf",
"status": "SUCCESS",
"output": "Script execution output log...",
"error": "Error message (if any)"
},
"error": None
}
"""
if not script_uuid:
return _error("INPUT_ERROR", "script_uuid parameter is required")
if not execute_user:
return _error("INPUT_ERROR", "execute_user parameter is required")
if timeout <= 5 or timeout >= 1800:
return _error("INPUT_ERROR", "timeout must be between 5 and 1800 seconds")
if success_rate < 0 or success_rate > 100:
return _error("INPUT_ERROR", "success_rate must be between 0 and 100")
if not target_instances or not isinstance(target_instances, list):
return _error("INPUT_ERROR", "target_instances parameter is required")
if rotation_strategy not in VALID_ROTATION_STRATEGIES:
return _error("INPUT_ERROR", f"rotation_strategy must be one of {VALID_ROTATION_STRATEGIES}")
try:
client = get_coc_client(ak, sk, security_token)
except ValueError as e:
return _error("CONFIG_ERROR", str(e))
try:
import time
from huaweicloudsdkcoc.v1 import ExecuteScriptRequest
from huaweicloudsdkcoc.v1.model.script_execute_model import ScriptExecuteModel
from huaweicloudsdkcoc.v1.model.script_execute_param import ScriptExecuteParam
from huaweicloudsdkcoc.v1.model.execute_instances_batch_info import ExecuteInstancesBatchInfo
from huaweicloudsdkcoc.v1.model.execute_resource_instance import ExecuteResourceInstance
request = ExecuteScriptRequest()
request.script_uuid = script_uuid
execute_param = ScriptExecuteParam(
timeout=timeout,
success_rate=success_rate,
execute_user=execute_user
)
listTargetInstancesExecuteBatches = []
for instance_info in target_instances:
instance_kwargs = {
"resource_id": instance_info.get("resource_id", ""),
"region_id": instance_info.get("region_id", "cn-north-4")
}
provider = instance_info.get("provider")
instance_type = instance_info.get("type")
if provider:
instance_kwargs["provider"] = provider
if instance_type:
instance_kwargs["type"] = instance_type
instance = ExecuteResourceInstance(**instance_kwargs)
listTargetInstancesExecuteBatches.append(instance)
listExecuteBatchesbody = [
ExecuteInstancesBatchInfo(
batch_index=1,
target_instances=listTargetInstancesExecuteBatches,
rotation_strategy=rotation_strategy
)
]
request.body = ScriptExecuteModel(
execute_batches=listExecuteBatchesbody,
execute_param=execute_param
)
response = client.execute_script(request)
execute_uuid = response.data if hasattr(response, 'data') else str(response)
if not wait_for_complete:
return {
"ok": True,
"text": f"Script execution started: {execute_uuid}",
"result": {"execute_uuid": execute_uuid},
"error": None,
}
max_wait_time = timeout + 60
wait_interval = 5
elapsed_time = 0
status = ""
while elapsed_time < max_wait_time:
query_result = coc_query_execution(execute_uuid, ak, sk, security_token)
data = query_result.get("data", {})
if not data:
# Query failed, log and continue
error_msg = query_result.get("error", {}).get("message", "Unknown error") if isinstance(query_result, dict) else "Query failed"
print(f"Failed to query execution status: {error_msg}")
time.sleep(wait_interval)
elapsed_time += wait_interval
continue
# Extract status and output from new format
instances = data.get("execute_instances", [])
if instances:
status = instances[0].get("status", "")
output = instances[0].get("message", "")
error = output if status == "ABNORMAL" else ""
else:
status = data.get("status", "")
output = data.get("message", "")
error = output if status == "ABNORMAL" else ""
# If status is UNKNOWN and waited for some time (e.g., 30 seconds), return error
if status == "UNKNOWN" and elapsed_time > 60:
return {
"ok": False,
"text": f"Script execution status unknown, possibly execution ID does not exist or API not responding",
"result": {"execute_uuid": execute_uuid, "status": status},
"error": {"code": "UNKNOWN_STATUS", "message": "Execution status unknown, possibly execution ID does not exist or API not responding"}
}
if status in ["SUCCESS", "FAILED", "TIMEOUT", "CANCELLED", "FINISHED", "ABNORMAL"]:
result_data = {
"execute_uuid": execute_uuid,
"status": status,
"output": output,
"error": error
}
if status in ["SUCCESS", "FINISHED"]:
return {
"ok": True,
"text": f"Script executed successfully: {execute_uuid}",
"result": result_data,
"error": None,
}
else:
error_msg = f"Script execution failed, status: {status}"
if error:
error_msg += f", error: {error[:200]}" if len(error) > 200 else f", error: {error}"
elif output:
error_msg += f", output: {output[:200]}" if len(output) > 200 else f", output: {output}"
return {
"ok": False,
"text": error_msg,
"result": result_data,
"error": {"code": "EXECUTE_FAILED", "message": error_msg}
}
time.sleep(wait_interval)
elapsed_time += wait_interval
return {
"ok": False,
"text": f"Script execution timeout (waited more than {max_wait_time} seconds)",
"result": {"execute_uuid": execute_uuid},
"error": {"code": "TIMEOUT", "message": "Script execution timeout"}
}
except Exception as e:
error_msg = str(e)
if "error_code" in error_msg.lower() or "error_msg" in error_msg.lower():
return _error("API_ERROR", error_msg)
return _error("UNKNOWN_ERROR", error_msg)
def coc_list_scripts(page: int = 1, limit: int = 10, ak: str = None, sk: str = None, security_token: str = None) -> dict[str, Any]:
"""
List COC scripts
Args:
page: Page number (starting from 1)
limit: Number per page
ak: Huawei Cloud AK (supports both long-term and temporary AK)
sk: Huawei Cloud SK (supports both long-term and temporary SK)
security_token: Security token for temporary credentials (optional, only required for temporary AK/SK)
Returns:
{
"ok": True,
"text": "Script list obtained",
"result": {
"scripts": [...],
"total": 100
},
"error": None
}
"""
try:
client = get_coc_client(ak, sk, security_token)
except ValueError as e:
return _error("CONFIG_ERROR", str(e))
try:
from huaweicloudsdkcoc.v1 import ListScriptsRequest
request = ListScriptsRequest()
request.page = page
request.limit = limit
response = client.list_scripts(request)
scripts = []
total = 0
if hasattr(response, 'data'):
data = response.data
if hasattr(data, 'data'):
for script in data.data:
risk_level = ""
version = ""
if hasattr(script, 'properties') and script.properties:
props = script.properties
risk_level = props.risk_level if hasattr(props, 'risk_level') else ""
version = props.version if hasattr(props, 'version') else ""
scripts.append({
"script_uuid": script.script_uuid if hasattr(script, 'script_uuid') else "",
"name": script.name if hasattr(script, 'name') else "",
"type": script.type if hasattr(script, 'type') else "",
"description": script.description if hasattr(script, 'description') else "",
"risk_level": risk_level,
"version": version,
"create_time": script.gmt_created if hasattr(script, 'gmt_created') else ""
})
if hasattr(data, 'total'):
total = data.total
return {
"ok": True,
"text": f"Found {total} scripts",
"result": {
"scripts": scripts,
"total": total
},
"error": None,
}
except Exception as e:
error_msg = str(e)
if "error_code" in error_msg.lower() or "error_msg" in error_msg.lower():
return _error("API_ERROR", error_msg)
return _error("UNKNOWN_ERROR", error_msg)
def coc_query_execution(execute_uuid: str, ak: str = None, sk: str = None, security_token: str = None) -> dict[str, Any]:
"""
Query script execution status
Args:
execute_uuid: Execution UUID (format: SCT2023083109562601af694bf)
ak: Huawei Cloud AK (supports both long-term and temporary AK)
sk: Huawei Cloud SK (supports both long-term and temporary SK)
security_token: Security token for temporary credentials (optional, only required for temporary AK/SK)
Returns:
{
"data": {
"batch_index": 1,
"total_instances": 1,
"execute_instances": [{
"id": 40304358,
"cmd_uuid": "xxx",
"job_sign": null,
"status": "FINISHED",
"message": "Execution log...",
"gmt_created": 1779934038727,
"gmt_finished": 1779934107670,
"execute_costs": 68943,
"target_instance": {
"resource_id": "xxx",
"agent_sn": "xxx",
"agent_status": null,
"agent_version": "1.1.8",
"region_id": "cn-north-4",
"project_id": null,
"properties": {
"host_name": "dify-test-001",
"fixed_ip": null,
"floating_ip": null,
"region_id": "cn-north-4",
"zone_id": null,
"application": null,
"group": null,
"project_id": null
},
"custom_attributes": null,
"provider": "hcss",
"type": "l-instance"
}
}]
}
}
"""
if not execute_uuid:
return _error("INPUT_ERROR", "execute_uuid parameter is required")
try:
client = get_coc_client(ak, sk, security_token)
except ValueError as e:
return _error("CONFIG_ERROR", str(e))
try:
from huaweicloudsdkcoc.v1 import GetScriptJobBatchRequest
request = GetScriptJobBatchRequest()
request.batch_index = 1
request.execute_uuid = execute_uuid
request.limit = 50
response = client.get_script_job_batch(request)
result_dict = {}
if hasattr(response, 'data') and response.data is not None:
data = response.data
if hasattr(data, 'batch_index'):
result_dict['batch_index'] = data.batch_index
if hasattr(data, 'total_instances'):
result_dict['total_instances'] = data.total_instances
if hasattr(data, 'execute_instances') and data.execute_instances:
instances = []
for instance in data.execute_instances:
instance_dict = {}
if hasattr(instance, 'id'):
instance_dict['id'] = instance.id
if hasattr(instance, 'cmd_uuid'):
instance_dict['cmd_uuid'] = instance.cmd_uuid
if hasattr(instance, 'status'):
instance_dict['status'] = instance.status
if hasattr(instance, 'message'):
instance_dict['message'] = instance.message
if hasattr(instance, 'execute_costs'):
instance_dict['execute_costs'] = instance.execute_costs
if hasattr(instance, 'gmt_created'):
instance_dict['gmt_created'] = instance.gmt_created
if hasattr(instance, 'gmt_finished'):
instance_dict['gmt_finished'] = instance.gmt_finished
if hasattr(instance, 'target_instance') and instance.target_instance:
target = instance.target_instance
target_dict = {}
if hasattr(target, 'resource_id'):
target_dict['resource_id'] = target.resource_id
if hasattr(target, 'agent_sn'):
target_dict['agent_sn'] = target.agent_sn
if hasattr(target, 'agent_status'):
target_dict['agent_status'] = target.agent_status
if hasattr(target, 'agent_version'):
target_dict['agent_version'] = target.agent_version
if hasattr(target, 'region_id'):
target_dict['region_id'] = target.region_id
if hasattr(target, 'project_id'):
target_dict['project_id'] = target.project_id
if hasattr(target, 'properties') and target.properties:
props = target.properties
props_dict = {}
if hasattr(props, 'host_name'):
props_dict['host_name'] = props.host_name
if hasattr(props, 'fixed_ip'):
props_dict['fixed_ip'] = props.fixed_ip
if hasattr(props, 'floating_ip'):
props_dict['floating_ip'] = props.floating_ip
if hasattr(props, 'region_id'):
props_dict['region_id'] = props.region_id
if hasattr(props, 'zone_id'):
props_dict['zone_id'] = props.zone_id
if hasattr(props, 'application'):
props_dict['application'] = props.application
if hasattr(props, 'group'):
props_dict['group'] = props.group
if hasattr(props, 'project_id'):
props_dict['project_id'] = props.project_id
target_dict['properties'] = props_dict
if hasattr(target, 'custom_attributes'):
target_dict['custom_attributes'] = target.custom_attributes
if hasattr(target, 'provider'):
target_dict['provider'] = target.provider
if hasattr(target, 'type'):
target_dict['type'] = target.type
instance_dict['target_instance'] = target_dict
if hasattr(instance, 'job_sign'):
instance_dict['job_sign'] = instance.job_sign
instances.append(instance_dict)
result_dict['execute_instances'] = instances
else:
result_dict['status'] = 'UNKNOWN'
result_dict['message'] = 'Execution record does not exist or data is empty'
return {
"data": result_dict
}
except Exception as e:
error_msg = str(e)
if "error_code" in error_msg.lower() or "error_msg" in error_msg.lower():
return _error("API_ERROR", error_msg)
return _error("UNKNOWN_ERROR", error_msg)
SCRIPT_TEMPLATES = {
"install_maas": {
"name": "OpenClaw-MaaS-Model-Installation",
"type": "SHELL",
"description": "Install MaaS models on OpenClaw instance",
"risk_level": "MEDIUM",
"content": '''#!/bin/bash
curl -sSL https://documentation-samples.obs.cn-north-4.myhuaweicloud.com/solution-as-code-publicbucket/solution-as-code-moudle/deploying-clawdbot-agents/userdata/multi_model.sh | bash -s '${modelParams}'
if [ -d "/home/openclaw" ]; then
export PNPM_HOME="/home/openclaw/.local/share/pnpm"
export NVM_DIR="/home/openclaw/.nvm"
ln -sf /home/openclaw/.nvm/versions/node/v22.22.1/bin/node /usr/local/bin/node
ln -sf /home/openclaw/.nvm/versions/node/v22.22.1/bin/npm /usr/local/bin/npm
CMD_NAME=/home/openclaw/.local/share/pnpm/openclaw
sudo -i -u openclaw env DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus $CMD_NAME gateway restart >> /var/manage_operate.log 2>&1
GATEWAY_STATUS_OUTPUT=$(sudo -i -u openclaw env DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus $CMD_NAME gateway status 2>&1)
else
ln -sf /root/.nvm/versions/node/v22.22.0/bin/node /usr/local/bin/node
ln -sf /root/.nvm/versions/node/v22.22.0/bin/npm /usr/local/bin/npm
CMD_NAME=/root/.local/share/pnpm/openclaw
/root/.local/share/pnpm/openclaw gateway restart >> /var/manage_operate.log 2>&1
GATEWAY_STATUS_OUTPUT=$($CMD_NAME gateway status 2>&1)
fi'''
},
"install_channel": {
"name": "OpenClaw-Channel-Installation",
"type": "SHELL",
"description": "Install channels on OpenClaw instance (WeChat Work/Feishu/DingTalk/QQ)",
"risk_level": "MEDIUM",
"content": '''#!/bin/bash
curl -sSL https://documentation-samples.obs.cn-north-4.myhuaweicloud.com/solution-as-code-publicbucket/solution-as-code-moudle/deploying-clawdbot-agents/userdata/multi_channel.sh | bash -s '${channelList}'
if [ -d "/home/openclaw" ]; then
export PNPM_HOME="/home/openclaw/.local/share/pnpm"
export NVM_DIR="/home/openclaw/.nvm"
ln -sf /home/openclaw/.nvm/versions/node/v22.22.1/bin/node /usr/local/bin/node
ln -sf /home/openclaw/.nvm/versions/node/v22.22.1/bin/npm /usr/local/bin/npm
CMD_NAME=/home/openclaw/.local/share/pnpm/openclaw
sudo -i -u openclaw env DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus $CMD_NAME gateway restart >> /var/manage_operate.log 2>&1
GATEWAY_STATUS_OUTPUT=$(sudo -i -u openclaw env DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus $CMD_NAME gateway status 2>&1)
else
ln -sf /root/.nvm/versions/node/v22.22.0/bin/node /usr/local/bin/node
ln -sf /root/.nvm/versions/node/v22.22.0/bin/npm /usr/local/bin/npm
CMD_NAME=/root/.local/share/pnpm/openclaw
/root/.local/share/pnpm/openclaw gateway restart >> /var/manage_operate.log 2>&1
GATEWAY_STATUS_OUTPUT=$($CMD_NAME gateway status 2>&1)
fi'''
},
"check_gateway": {
"name": "OpenClaw-Gateway-Status",
"type": "SHELL",
"description": "Query OpenClaw gateway status",
"risk_level": "LOW",
"content": '''#!/bin/bash
curl -sSL https://documentation-samples.obs.cn-north-4.myhuaweicloud.com/solution-as-code-publicbucket/solution-as-code-moudle/deploying-clawdbot-agents/userdata/openclaw_gateway_manager.sh | bash -s status'''
}
}
def install_maas_models_remote(
resource_id: str,
region_id: str,
model_params: str = "",
timeout: int = 600,
execute_user: str = "root",
ak: str = None,
sk: str = None,
security_token: str = None
) -> dict[str, Any]:
"""
Install MaaS models on remote L instance via COC
Args:
resource_id: L instance resource ID
region_id: L instance region
model_params: Model parameters string, format: {"provider":"huawei","api_key":"xxx","model_ids":["model1","model2"]}
timeout: Execution timeout (seconds), default 600
execute_user: Execute user, default root
ak: Huawei Cloud AK (supports both long-term and temporary AK)
sk: Huawei Cloud SK (supports both long-term and temporary SK)
security_token: Security token for temporary credentials (optional, only required for temporary AK/SK)
Returns:
{
"ok": True,
"text": "Script execution started: SCT2023083109562601af694bf",
"result": {...},
"error": None
}
"""
import time
script_info = SCRIPT_TEMPLATES["install_maas"]
content = script_info["content"].replace("${modelParams}", model_params)
create_result = coc_create_script(
name=f"{script_info['name']}-{int(time.time())}",
script_type=script_info["type"],
content=content,
description=script_info["description"],
risk_level=script_info["risk_level"],
ak=ak,
sk=sk,
security_token=security_token
)
if not create_result.get("ok"):
return create_result
script_uuid = create_result.get("result", {}).get("script_uuid")
target_instances = [{
"resource_id": resource_id,
"region_id": region_id,
"provider": "HCSS",
"type": "L-INSTANCE"
}]
execute_result = coc_execute_script(
script_uuid=script_uuid,
execute_user=execute_user,
timeout=timeout,
success_rate=100.0,
target_instances=target_instances,
rotation_strategy="CONTINUE",
ak=ak,
sk=sk,
security_token=security_token
)
return execute_result
def install_channel_remote(
resource_id: str,
region_id: str,
channel_list: str = "",
timeout: int = 600,
execute_user: str = "root",
ak: str = None,
sk: str = None,
security_token: str = None
) -> dict[str, Any]:
"""
Install channels on remote L instance via COC
Args:
resource_id: L instance resource ID
region_id: L instance region
channel_list: Channel configuration JSON array string, format: [{"channel":"wecom","id":"xxx","secret":"xxx",...}]
Channel JSON object fields:
- channel: Channel type (required): 'wecom' (WeCom), 'feishu' (Feishu), 'dingtalk' (DingTalk), 'qqbot' (QQ)
- id: Bot ID/APP ID/Client ID (required)
- secret: Bot secret/APP secret/Client secret (required)
timeout: Execution timeout (seconds), default 600
execute_user: Execute user, default root
ak: Huawei Cloud AK (supports both long-term and temporary AK)
sk: Huawei Cloud SK (supports both long-term and temporary SK)
security_token: Security token for temporary credentials (optional, only required for temporary AK/SK)
Returns:
{
"ok": True,
"text": "Script execution started: SCT2023083109562601af694bf",
"result": {...},
"error": None
}
"""
import time
import random
import string
if channel_list:
try:
channels = json.loads(channel_list)
for channel in channels:
# Generate account_id if not provided
if "account_id" not in channel or not channel["account_id"]:
timestamp = int(time.time() * 1000)
channel["account_id"] = f"bot-{timestamp}"
# Generate bot_name if not provided
if "bot_name" not in channel or not channel["bot_name"]:
random_chars = ''.join(random.choices(string.ascii_lowercase, k=4))
channel["bot_name"] = f"bot-{random_chars}"
# Convert back to JSON string
channel_list = json.dumps(channels, ensure_ascii=False)
except json.JSONDecodeError as e:
print(f"Warning: Failed to parse channel_list JSON: {e}")
# Keep original channel_list if parsing fails
script_info = SCRIPT_TEMPLATES["install_channel"]
content = script_info["content"].replace("${channelList}", channel_list)
create_result = coc_create_script(
name=f"{script_info['name']}-{int(time.time())}",
script_type=script_info["type"],
content=content,
description=script_info["description"],
risk_level=script_info["risk_level"],
ak=ak,
sk=sk,
security_token=security_token
)
if not create_result.get("ok"):
return create_result
script_uuid = create_result.get("result", {}).get("script_uuid")
target_instances = [{
"resource_id": resource_id,
"region_id": region_id,
"provider": "HCSS",
"type": "L-INSTANCE"
}]
execute_result = coc_execute_script(
script_uuid=script_uuid,
execute_user=execute_user,
timeout=timeout,
success_rate=100.0,
target_instances=target_instances,
rotation_strategy="CONTINUE",
ak=ak,
sk=sk,
security_token=security_token
)
return execute_result
def install_maas_models_local(model_params=""):
"""
Install models on local OpenClaw instance (via local bash execution)
Args:
model_params: Model parameters, e.g. custom vendor model name, format: provider/model-name
Returns:
None: Directly prints execution result
"""
import subprocess
try:
print("Starting model installation...")
install_command = f"curl -sSL https://documentation-samples.obs.cn-north-4.myhuaweicloud.com/solution-as-code-publicbucket/solution-as-code-moudle/deploying-clawdbot-agents/userdata/multi_model.sh | bash -s {model_params}"
print(f"Executing command: {install_command}")
result = subprocess.run(
install_command,
shell=True,
capture_output=True,
text=True
)
print(f"Command execution completed, exit code: {result.returncode}")
if result.stdout:
print(f"Standard output:\n{result.stdout}")
if result.stderr:
print(f"Error output:\n{result.stderr}")
if os.path.exists("/home/openclaw"):
print("\nDetected OpenClaw installed in /home/openclaw")
subprocess.run("ln -sf /home/openclaw/.nvm/versions/node/v22.22.1/bin/node /usr/local/bin/node", shell=True)
subprocess.run("ln -sf /home/openclaw/.nvm/versions/node/v22.22.1/bin/npm /usr/local/bin/npm", shell=True)
cmd_name = "/home/openclaw/.local/share/pnpm/openclaw"
restart_cmd = f"sudo -i -u openclaw env DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus {cmd_name} gateway restart >> /var/manage_operate.log 2>&1"
subprocess.run(restart_cmd, shell=True)
status_cmd = f"sudo -i -u openclaw env DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus {cmd_name} gateway status 2>&1"
status_result = subprocess.run(status_cmd, shell=True, capture_output=True, text=True)
print(f"Gateway status:\n{status_result.stdout}")
elif os.path.exists("/root/.local/share/pnpm/openclaw"):
print("\nDetected OpenClaw installed in /root")
subprocess.run("ln -sf /root/.nvm/versions/node/v22.22.0/bin/node /usr/local/bin/node", shell=True)
subprocess.run("ln -sf /root/.nvm/versions/node/v22.22.0/bin/npm /usr/local/bin/npm", shell=True)
cmd_name = "/root/.local/share/pnpm/openclaw"
subprocess.run(f"{cmd_name} gateway restart >> /var/manage_operate.log 2>&1", shell=True)
status_result = subprocess.run(f"{cmd_name} gateway status 2>&1", shell=True, capture_output=True, text=True)
print(f"Gateway status:\n{status_result.stdout}")
if result.returncode == 0:
return {
"ok": True,
"text": "Model installation completed",
"result": {
"stdout": result.stdout,
"stderr": result.stderr,
"returncode": result.returncode
},
"error": None
}
else:
return {
"ok": False,
"text": "Model installation failed",
"result": None,
"error": {
"code": str(result.returncode),
"message": result.stderr or result.stdout
}
}
except Exception as e:
return {
"ok": False,
"text": f"Error installing models: {str(e)}",
"result": None,
"error": {
"code": "UNKNOWN_ERROR",
"message": str(e)
}
}
def install_channel_local(channel_list=""):
"""
Install channels on local OpenClaw instance (via local bash execution)
Args:
channel_list: Channel list parameters, e.g. wecom dingtalk
Returns:
None: Directly prints execution result
"""
import subprocess
try:
print("Starting channel installation...")
install_command = f"curl -sSL https://documentation-samples.obs.cn-north-4.myhuaweicloud.com/solution-as-code-publicbucket/solution-as-code-moudle/deploying-clawdbot-agents/userdata/multi_channel.sh | bash -s {channel_list}"
print(f"Executing command: {install_command}")
result = subprocess.run(
install_command,
shell=True,
capture_output=True,
text=True
)
print(f"Command execution completed, exit code: {result.returncode}")
if result.stdout:
print(f"Standard output:\n{result.stdout}")
if result.stderr:
print(f"Error output:\n{result.stderr}")
if os.path.exists("/home/openclaw"):
print("\nDetected OpenClaw installed in /home/openclaw")
subprocess.run("ln -sf /home/openclaw/.nvm/versions/node/v22.22.1/bin/node /usr/local/bin/node", shell=True)
subprocess.run("ln -sf /home/openclaw/.nvm/versions/node/v22.22.1/bin/npm /usr/local/bin/npm", shell=True)
cmd_name = "/home/openclaw/.local/share/pnpm/openclaw"
restart_cmd = f"sudo -i -u openclaw env DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus {cmd_name} gateway restart >> /var/manage_operate.log 2>&1"
subprocess.run(restart_cmd, shell=True)
status_cmd = f"sudo -i -u openclaw env DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus {cmd_name} gateway status 2>&1"
status_result = subprocess.run(status_cmd, shell=True, capture_output=True, text=True)
print(f"Gateway status:\n{status_result.stdout}")
elif os.path.exists("/root/.local/share/pnpm/openclaw"):
print("\nDetected OpenClaw installed in /root")
subprocess.run("ln -sf /root/.nvm/versions/node/v22.22.0/bin/node /usr/local/bin/node", shell=True)
subprocess.run("ln -sf /root/.nvm/versions/node/v22.22.0/bin/npm /usr/local/bin/npm", shell=True)
cmd_name = "/root/.local/share/pnpm/openclaw"
subprocess.run(f"{cmd_name} gateway restart >> /var/manage_operate.log 2>&1", shell=True)
status_result = subprocess.run(f"{cmd_name} gateway status 2>&1", shell=True, capture_output=True, text=True)
print(f"Gateway status:\n{status_result.stdout}")
if result.returncode == 0:
return {
"ok": True,
"text": "Channel installation completed",
"result": {
"stdout": result.stdout,
"stderr": result.stderr,
"returncode": result.returncode
},
"error": None
}
else:
return {
"ok": False,
"text": "Channel installation failed",
"result": None,
"error": {
"code": str(result.returncode),
"message": result.stderr or result.stdout
}
}
except Exception as e:
return {
"ok": False,
"text": f"Error installing channels: {str(e)}",
"result": None,
"error": {
"code": "UNKNOWN_ERROR",
"message": str(e)
}
}
def check_gateway_status_remote(
resource_id: str,
region_id: str,
timeout: int = 600,
execute_user: str = "root",
ak: str = None,
sk: str = None,
security_token: str = None
) -> dict[str, Any]:
"""
Query OpenClaw gateway status on remote L instance via COC
Args:
resource_id: L instance resource ID
region_id: L instance region
timeout: Execution timeout (seconds), default 600
execute_user: Execute user, default root
ak: Huawei Cloud AK (supports both long-term and temporary AK)
sk: Huawei Cloud SK (supports both long-term and temporary SK)
security_token: Security token for temporary credentials (optional, only required for temporary AK/SK)
Returns:
{
"ok": True,
"text": "Script execution started: SCT2023083109562601af694bf",
"result": {...},
"error": None
}
"""
import time
script_info = SCRIPT_TEMPLATES["check_gateway"]
content = script_info["content"]
create_result = coc_create_script(
name=f"{script_info['name']}-{int(time.time())}",
script_type=script_info["type"],
content=content,
description=script_info["description"],
risk_level=script_info["risk_level"],
ak=ak,
sk=sk,
security_token=security_token
)
if not create_result.get("ok"):
return create_result
script_uuid = create_result.get("result", {}).get("script_uuid")
target_instances = [{
"resource_id": resource_id,
"region_id": region_id,
"provider": "HCSS",
"type": "L-INSTANCE"
}]
execute_result = coc_execute_script(
script_uuid=script_uuid,
execute_user=execute_user,
timeout=timeout,
success_rate=100.0,
target_instances=target_instances,
rotation_strategy="CONTINUE",
ak=ak,
sk=sk,
security_token=security_token
)
return execute_result
def query_uniagent_status(
resource_id: str,
ak: str,
sk: str,
security_token: str = None
) -> dict[str, Any]:
"""
Query L instance UniAgent status via COC API
Args:
resource_id: L instance resource ID
ak: Huawei Cloud AK (supports both long-term and temporary AK)
sk: Huawei Cloud SK (supports both long-term and temporary SK)
security_token: Security token for temporary credentials (optional, only required for temporary AK/SK)
Returns:
{
"ok": True,
"text": "Query successful",
"result": {...},
"error": None
}
"""
if not resource_id:
return _error("INPUT_ERROR", "resource_id parameter is required")
if not ak or not sk:
return _error("CONFIG_ERROR", "Please provide AK and SK parameters. For temporary credentials, also provide security_token.")
region = os.environ.get("HUAWEICLOUD_REGION", "cn-north-4")
try:
from huaweicloudsdkcore.auth.credentials import GlobalCredentials
from huaweicloudsdkcore.signer.signer import Signer
from huaweicloudsdkcore.sdk_request import SdkRequest
from urllib.parse import urlparse
credentials = Credentials(ak, sk, security_token)
signer = Signer(credentials)
endpoint = "https://coc.myhuaweicloud.com/v1/resources"
query_params = {
"resource_id_list": resource_id,
"limit": "100",
"provider": "hcss",
"type": "l-instance"
}
url_with_params = endpoint + "?" + "&".join([f"{k}={v}" for k, v in query_params.items()])
parsed_url = urlparse(url_with_params)
request = SdkRequest()
request.method = "GET"
request.schema = parsed_url.scheme
request.host = parsed_url.hostname
request.resource_path = parsed_url.path
request.query_params = [[k, v] for k, v in query_params.items()]
request.header_params = {
"Content-Type": "application/json",
"Client-Request-Id": str(uuid.uuid4())
}
if security_token:
request.header_params["X-Security-Token"] = security_token
signed_request = signer.sign(request)
headers = {}
for key, value in signed_request.header_params.items():
if isinstance(value, bytes):
headers[key] = value.decode('iso-8859-1')
else:
headers[key] = str(value)
print(f"Request URL: {url_with_params}")
print(f"Request headers: {headers}")
resp = requests.request(
"GET",
url_with_params,
headers=headers,
verify=True
)
print(f"Response status code: {resp.status_code}")
print(f"Response content: {resp.text}")
if resp.status_code in [200, 202]:
response_data = resp.json()
return {
"ok": True,
"text": "UniAgent status query successful",
"result": response_data,
"error": None
}
else:
return {
"ok": False,
"text": f"Query failed: {resp.reason}",
"result": None,
"error": {
"code": str(resp.status_code),
"message": resp.text
}
}
except ImportError as e:
return _error("SDK_ERROR", f"Please install huaweicloudsdkcore: {str(e)}")
except Exception as e:
error_msg = str(e)
return _error("UNKNOWN_ERROR", error_msg)
#!/usr/bin/env python3
# coding: utf-8
"""
Huawei Cloud Flexus L Instance One-Click OpenClaw Deployment - Model Installation Module
"""
import json
import re
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from scripts.lib import install_maas_models_remote, install_maas_models_local, query_uniagent_status, check_gateway_status_remote
from scripts.utils import prompt_for_input, REGION_IDS
def _check_prerequisites(resource_id, region_id, ak, sk, security_token):
"""
Check prerequisites (UniAgent status)
Args:
resource_id: L instance resource ID
region_id: Region ID
ak: Huawei Cloud AK (supports both long-term and temporary AK)
sk: Huawei Cloud SK (supports both long-term and temporary SK)
security_token: Security token for temporary credentials (optional, only required for temporary AK/SK)
Returns:
bool: True if check passed, False if check failed
"""
print("\nChecking UniAgent status...")
result = query_uniagent_status(resource_id, ak, sk, security_token)
if not result.get("ok"):
print(f" [FAIL] UniAgent status check failed: {result.get('error', {}).get('message', 'Unknown error')}")
return False
data = result.get("result", {})
resources = data.get("data", [])
if not resources:
print(" [FAIL] Instance information not found")
return False
for resource in resources:
agent_state = resource.get("agent_state", "")
if agent_state == "ONLINE":
print(" [OK] UniAgent status: ONLINE")
return True
else:
print(f" [FAIL] UniAgent status: {agent_state}")
print(" Please ensure UniAgent is started and online")
return False
return False
def do_install_maas(args):
"""
Execute model installation
Args:
args: Command line argument object with the following attributes:
- resource_id: L instance resource ID (command line arg --resource-id)
- region_id: Region ID (command line arg --region-id)
- model_params: Model parameters JSON (command line arg --model-params), must use valid JSON format with double quotes for keys and values
- timeout: Timeout duration (command line arg --timeout)
- execute_user: Execute user (command line arg --execute-user)
- ak: Huawei Cloud AK (supports both long-term and temporary AK) (command line arg --ak)
- sk: Huawei Cloud SK (supports both long-term and temporary SK) (command line arg --sk)
- security_token: Security token for temporary credentials (optional, only required for temporary AK/SK) (command line arg --security-token)
- non_interactive: Whether non-interactive mode (command line arg --non-interactive)
Returns:
None
"""
print("=" * 60)
print(" OpenClaw Model Installation")
print("=" * 60)
ak = getattr(args, 'ak', None)
sk = getattr(args, 'sk', None)
security_token = getattr(args, 'security_token', None)
if not ak or not sk:
print("\nHuawei Cloud credentials not configured, entering interactive configuration...")
print("Please configure Huawei Cloud credentials:")
print(" - Long-term AK/SK: No security_token required")
print(" - Temporary AK/SK: Security token required")
print("-" * 40)
ak = prompt_for_input("Huawei Cloud AK (HW_ACCESS_KEY)", required=True)
sk = prompt_for_input("Huawei Cloud SK (HW_SECRET_KEY)", required=True, hide_input=True)
security_token = prompt_for_input("Security Token (optional, only for temporary credentials)", required=False)
resource_id = args.resource_id if hasattr(args, 'resource_id') and args.resource_id else None
region_id = args.region_id if hasattr(args, 'region_id') and args.region_id else None
model_params = args.model_params if hasattr(args, 'model_params') and args.model_params else ""
timeout = args.timeout if hasattr(args, 'timeout') and args.timeout else 600
non_interactive = args.non_interactive if hasattr(args, 'non_interactive') else False
if not resource_id:
resource_id = prompt_for_input("L instance resource ID", required=True)
if not region_id:
region_id = prompt_for_input("Region ID", required=False, default="cn-north-4", choices=REGION_IDS)
if not model_params:
print("\nModel parameters format example:")
print(' {"provider":"huawei","api_key":"your_api_key","model_ids":["model1","model2"]}')
model_params = prompt_for_input("Model parameters JSON (optional, press Enter to skip)", required=False)
def normalize_json_string(input_str):
"""
Convert non-standard JSON string (no quotes/single quotes) to standard double-quoted JSON format
Args:
input_str: Input JSON string, can be non-standard format without quotes
Returns:
str: Standard JSON string with double quotes
Examples:
Input: {provider:huawei,api_key:your_maas_api_key,model_ids:[deepseek-v3.2]}
Output: {"provider":"huawei","api_key":"your_maas_api_key","model_ids":["deepseek-v3.2"]}
"""
if not input_str or input_str.strip() == "":
return ""
raw_str = input_str.strip()
try:
parsed = json.loads(raw_str)
return json.dumps(parsed, ensure_ascii=False)
except json.JSONDecodeError:
processed = re.sub(r'([{,])\s*([a-zA-Z0-9_]+)\s*:', r'\1"\2":', raw_str)
processed = re.sub(r':\s*([a-zA-Z0-9_\-\.]+)\s*([,}\]])', r':"\1"\2', processed)
processed = re.sub(r'\[\s*([a-zA-Z0-9_\-\.]+)\s*\]', r'["\1"]', processed)
try:
parsed = json.loads(processed)
return json.dumps(parsed, ensure_ascii=False)
except json.JSONDecodeError as e:
print(f"\n[WARNING] Model parameters JSON format cannot be auto-fixed: {e}")
print(f" Original parameters: {input_str}")
print(f" Attempted fix: {processed}")
raise SystemExit("Please provide valid JSON format parameters (keys and values must be wrapped in double quotes)")
if model_params:
model_params = normalize_json_string(model_params)
if not timeout:
timeout = int(prompt_for_input("Timeout (seconds)", required=False, default="600"))
print(f"\nInstallation configuration:")
print(f" Resource ID: {resource_id}")
print(f" Region: {region_id}")
print(f" Model parameters: {model_params or 'Default'}")
print(f" Timeout: {timeout} seconds")
if not non_interactive:
confirm = prompt_for_input("Confirm installation?", required=False, default="y", choices=["y", "n"])
if confirm.lower() != "y":
print("\nInstallation cancelled")
return
print("\nChecking prerequisites...")
if not _check_prerequisites(resource_id, region_id, ak, sk, security_token):
print("\nPrerequisite check failed, please resolve and retry")
return
print("\nStarting model installation...")
result = install_maas_models_remote(resource_id, region_id, model_params, timeout, "root", ak, sk, security_token)
if result.get("ok"):
print(f"\n[OK] {result['text']}")
if result.get("result"):
print(f" Execution ID: {result['result'].get('execute_uuid', 'Unknown')}")
print(f" Status: {result['result'].get('status', 'Unknown')}")
if result['result'].get('output'):
print(f" Output: {result['result']['output'][:200]}...")
else:
print(f"\n[FAIL] Installation failed")
if result.get("error"):
print(f" Error code: {result['error'].get('code')}")
print(f" Error message: {result['error'].get('message')}")[project]
name = "huawei-cloud-flexus-l-server-openclaw-deployment"
version = "1.0.0"
dependencies = [
"requests>=2.31.0",
"huaweicloudsdkcore>=3.1.0",
]
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"
[tool.setuptools]
py_modules = [
"caller",
"lib",
"utils",
"deploy",
"models",
"channels",
"gateway",
"uniagent"
]
[tool.setuptools.package-data]
"*" = ["*"]
#!/usr/bin/env python3
# coding: utf-8
"""
Huawei Cloud Flexus L Instance One-Click OpenClaw Deployment - UniAgent Status Query Module
"""
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from scripts.lib import query_uniagent_status
from scripts.utils import prompt_for_input
def do_check_uniagent(args):
"""
Execute UniAgent status query
Args:
args: Command line argument object with the following attributes:
- resource_id: L instance resource ID
- ak: Huawei Cloud AK (supports both long-term and temporary AK)
- sk: Huawei Cloud SK (supports both long-term and temporary SK)
- security_token: Security token for temporary credentials (optional, only required for temporary AK/SK)
Returns:
None
"""
print("=" * 60)
print(" UniAgent Status Query")
print("=" * 60)
ak = getattr(args, 'ak', None)
sk = getattr(args, 'sk', None)
security_token = getattr(args, 'security_token', None)
if not ak or not sk:
print("\nHuawei Cloud credentials not configured, entering interactive configuration...")
print("Please configure Huawei Cloud credentials:")
print(" - Long-term AK/SK: No security_token required")
print(" - Temporary AK/SK: Security token required")
print("-" * 40)
ak = prompt_for_input("Huawei Cloud AK (HW_ACCESS_KEY)", required=True)
sk = prompt_for_input("Huawei Cloud SK (HW_SECRET_KEY)", required=True, hide_input=True)
security_token = prompt_for_input("Security Token (optional, only for temporary credentials)", required=False)
resource_id = args.resource_id if hasattr(args, 'resource_id') and args.resource_id else None
if not resource_id:
resource_id = prompt_for_input("L instance resource ID", required=True)
print(f"\nQuery configuration:")
print(f" Resource ID: {resource_id}")
print("\nQuerying UniAgent status...")
result = query_uniagent_status(resource_id, ak, sk, security_token)
if result.get("ok"):
print(f"\n[OK] {result['text']}")
if result.get("result"):
data = result['result']
resources = data.get("data", [])
if resources:
for resource in resources:
print(f" Resource ID: {resource.get('resource_id', 'Unknown')}")
print(f" UniAgent status: {resource.get('agent_state', 'Unknown')}")
print(f" Instance name: {resource.get('name', 'Unknown')}")
else:
print(f"\n[FAIL] Query failed")
if result.get("error"):
print(f" Error code: {result['error'].get('code')}")
print(f" Error message: {result['error'].get('message')}")
#!/usr/bin/env python3
# coding: utf-8
"""
Huawei Cloud Flexus L Instance One-Click OpenClaw Deployment - Utility Functions Module
"""
import os
REGIONS = {
"cn-north-4": "华北-北京四",
"cn-east-3": "华东-上海一",
"cn-south-1": "华南-广州",
"cn-southwest-2": "西南-贵阳一",
}
REGION_IDS = list(REGIONS.keys())
def print_region_list():
"""
Print region list
Returns:
None
"""
print("\nHuawei Cloud Flexus L instance supported regions:")
print("-" * 50)
print(f"{'Region ID':<20} {'Region Name':<25}")
print("-" * 50)
for region_id, name in REGIONS.items():
print(f"{region_id:<20} {name:<25}")
print("-" * 50)
def get_region_id_by_name(input_str: str) -> str:
"""
Convert user input to standard region ID
Args:
input_str: User input, can be region ID or Chinese name
Returns:
Standard region ID, or original input if not matched
"""
if input_str in REGION_IDS:
return input_str
for region_id, name in REGIONS.items():
if input_str == name:
return region_id
if input_str in name:
return region_id
return input_str
def prompt_for_input(prompt, required=True, default=None, choices=None, hide_input=False):
"""
Interactive prompt for user input
Args:
prompt: Prompt message
required: Whether required, default True
default: Default value, optional
choices: Available choices list, optional
hide_input: Whether to hide input (for password), default False
Returns:
str: User input value
"""
while True:
if default and choices:
display_prompt = f"{prompt} [{', '.join(choices)}, default: {default}]: "
elif default:
display_prompt = f"{prompt} [default: {default}]: "
elif choices:
display_prompt = f"{prompt} [{', '.join(choices)}]: "
else:
display_prompt = f"{prompt}: "
if hide_input:
try:
from getpass import getpass
user_input = getpass(display_prompt).strip()
except ImportError:
user_input = input(display_prompt).strip()
else:
user_input = input(display_prompt).strip()
if user_input:
if choices and user_input not in choices:
print(f"Invalid option, please choose from: {', '.join(choices)}")
continue
return user_input
elif default:
return default
elif not required:
return None
else:
print("This parameter cannot be empty, please enter")
def setup_credentials_interactive():
"""
Interactive setup of Huawei Cloud temporary credentials
Args:
None
Returns:
tuple: (ak, sk, security_token, region) credentials tuple
"""
print("\nPlease configure Huawei Cloud credentials:")
print(" - Long-term AK/SK: No security_token required")
print(" - Temporary AK/SK: Security token required")
print("-" * 40)
ak = prompt_for_input("Huawei Cloud AK (HW_ACCESS_KEY)", required=True)
sk = prompt_for_input("Huawei Cloud SK (HW_SECRET_KEY)", required=True, hide_input=True)
security_token = prompt_for_input("Security Token (optional, only for temporary credentials)", required=False)
region = prompt_for_input("Region ID", required=False, default="cn-north-4")
print(f"\n[OK] Temporary credentials configured")
print(f" AK: {ak[:4]}...{ak[-4:]}")
print(f" SK: {'*' * len(sk)}")
if security_token:
print(f" Security Token: {'*' * len(security_token)}")
else:
print(f" Security Token: None (using long-term credentials)")
print(f" Region: {region} ({REGIONS.get(region, '')})")
return ak, sk, security_token, region