Basic Information
| Item | Content |
|---|---|
| name | huawei-cloud-migration-windows-ecs |
| description | Automated orchestration Skill for migrating Huawei Cloud SMS (Server Migration Service) Windows hosts to ECS. Supports Windows Server 2008/2008R2/2012/2012R2/2016/2019/2022/2025 and Win7/8.1/10/11 (64-bit). Public network/private network migration templates and environment variable templates + pre-task reminder (if Host_Information/migration_* is not set, configure the environment variables before migration); dual CLI (unified_migrate.py deploy Agent + sms_task.py target/migration task/sync/cutover) + environment cleanup orchestration (cleanup_environment.py); KooCLI 7.2.x tested compatible (BatchStartServers equivalent cutover, EVS disk verification fallback, automatic fallback when sync/cutover enumeration is not supported); batch host information read from environment variable Host_Information(JSON template) (CSV-compatible fallback); source must be cleaned before deployment (CleanupSourcePhase); private network Squid/gost proxy (CONNECT only migration ports); resource ownership system (OwnerID fingerprint); 71+ security rules (including red lines O1-O6); target orchestration automatically creates data disks (1:1); task name ≤16 to prevent SMS.7711. Trigger words: Windows migration, SMS migration, migrate Windows server, Windows to ECS, migrate Windows, Windows server migration, batch migration, public network migration, private network migration, create target VM, create migration task, host-migration, clean up environment |
Basic Migration Logic
Phase A: unified_migrate.py — 清理 + 部署 Agent 并注册源端
阶段链: WinRMPhase → CleanupSourcePhase(清残留) → InstallAgentPhase → ConfigurePhase → VerifyPhase
Phase B: sms_task.py — 目标编排 → 迁移任务 → 同步 → 割接 → 回收
子命令: discover / prepare-target / create / start / wait / sync / cutover / cleanup / release / delete
环境清理: cleanup_environment.py — ①打通 gost → ②清源端 → ③清代理
- Source cleanup is mandatory before migration: The engine has hardcoded
CleanupSourcePhase(first establish WinRM, use gost for private network, then clean up residual files, finally deploy the Agent fresh). - Py3 GUI configuration must be in an interactive session: scheduled tasks carry
/it; without a desktop session (explorer/Session>0) it fails fast directly. - Host information no longer comes from Excel; batch mode reads from environment variable
Host_Information(see below).
Key Source-Side Constraints
| Constraint Item | Requirement |
|---|---|
| File system / disk | NTFS, basic disk; ≤23 disks; the system volume must be on disk 1 |
| Partition space | Partition >600MB → available ≥320MB; <600MB → available ≥40MB |
| CPU / memory | CPU<80%; memory>256MB (during migration) |
| Agent version | Server 2012+ → Py3 GUI(AutoIt/exe automation); 2008/2008R2/7 → Py2 CLI |
| Prohibited | RAID / BitLocker / dynamic disks / shared file systems / ZRAM / AD / multi-node databases |
| Network ports | 22 / 8899 / 8900 / 443 (source → SMS); 5985/5986 WinRM; target SG allows only migration ports |
Migration Host Information Source (Host_Information Environment Variable)
Batch migration host information is read from environment variable Host_Information(JSON array template), and no longer reads Excel/CSV.
Template (Chinese keys/English keys both acceptable; the array may contain two types of objects: source hosts and proxy hosts; multiple sources + one proxy allowed):
export Host_Information='[
{
"主机名": "xxxx", "公网IP": "xxxx", "内网IP": "xxxx", "端口号": "5985",
"用户名": "xxxx", "密码": "xxxx",
"region_id": "xxxx", "region_name": "xxxx",
"project_id": "xxxx", "project_name": "xxxx",
"os_type": "WINDOWS", "use_public_ip": "false"
},
{
"代理主机名": "xxxx", "公网IP": "xxxx", "内网IP": "xxxx", "端口号": "22",
"用户名": "xxxx", "密码": "xxxx",
"region_id": "xxxx", "region_name": "xxxx"
}
]'
- Source object:
主机名 / 公网IP / 内网IP / 端口号(WinRM) / 用户名 / 密码 / region_id / region_name / project_id / project_name / os_type / use_public_ip。 - Proxy object (private network only):
代理主机名 / 公网IP / 内网IP / 端口号(SSH) / 用户名 / 密码 / region_id / region_name。 - Public network batch:
hostuses the public IP; private network batch:hostObtain the private network IP; the gost forwarding target uses the private network IP; the proxy connection information is taken from the proxy object (fallbackconfig.proxy_server)。 - Old
config/hosts.csvis retained as a compatible fallback; when a CSV path is explicitly passed, it is still executed as CSV.
Prerequisite task: environment variable check (mandatory)
AI/assistant behavior conventions (after this skill is triggered, before executing any migration action):
- First check whether
migration_Access_Key / migration_Secret_Access_Key / migration_password / migration_domain / Host_Informationis set; - Not set → immediately remind the customer to configure the environment variables first, and provide the template/script below; do not start any migration orchestration before configuration;
unified_migrate.pyautomatically intercepts on startup (preflight_check.pyindependent check),--skip-preflightis an escape hatch (used only when all parameters have been embedded in migrate.yaml).
Before executing any migration (public/private network, single host/batch)Before, you must first confirm that the environment variables required for migration are set. If the customer has not set them yet,you must first remind the customer to configure the environment variables, then continue the migration; do not directly execute migration orchestration before configuration.
The environment variable template is built in(scripts/windows_migration/config/, in placeholder form, permission 600):
env.public.sh.example—— public network environment variable template (usage:cp env.public.sh.example env.public.sh→ fill in values →source)env.private.sh.example—— private network environment variable template (two Host_Information objects: source and proxy; usage same as above)- Usage:
cp env.public.sh.example env.public.sh→ fill in real values →source env.public.sh
# 云侧凭证(必设)
export migration_Access_Key="<ak>" # 永久凭证
export migration_Secret_Access_Key="<sk>"
export migration_password="<windows-admin-password>" # Windows 源端 Administrator 密码
export migration_domain="<云账号domain>" # IAM 账号 domain
# 主机信息(批量必设;单台模式可从 migrate.yaml source 段读取,仍建议设置)
export Host_Information='[ ... ]' # JSON 数组主机信息,见上节模板
Quick self-check (if any one is missing, it is unconfigured):
env | grep -E '^(migration_Access_Key|migration_Secret_Access_Key|migration_password|migration_domain|Host_Information)=' >/dev/null && echo "环境变量已配置" || echo "缺少环境变量,请先配置"
Standard reminder when not set (for the AI/assistant to output to the customer):
Please configure the migration environment variables first:
migration_Access_Key、migration_Secret_Access_Key、migration_password、migration_domainas well asHost_Information(JSON array host information). No migration action will start before configuration.
Migration target templates: public network / private network
All runtime parameters (scenario, source, proxy, OBS, SMS tasks, target orchestration) are injected by config/migrate.yaml ,
switching between public and private networks only requires changing the key items in migrate.yaml + the Host_Information template, with zero changes to the engine code.
The migrate.yaml template is built in(scripts/windows_migration/config/, in placeholder form, permission 600):
migrate.public.yaml—— public network template (proxy_mode=false, use_eip=true, allow source public IP/32)migrate.private.yaml—— private network template (proxy_mode=true+gost, use_eip=false, allow source private IP/32)- Usage:
cp migrate.public.yaml migrate.yaml(or directly--config config/migrate.public.yaml) → replace with real values
Target one: public network migration (public)
- Applicable: the source Windows host can directly connect to Huawei Cloud OBS/SMS (has a public IP / can route to the internet).
- Target side: automatically create VPC/subnet/security group (least privilege)/ECS/EIP (use_eip=true).
config/migrate.yaml Key items:
scenario: public # public=公网直连
source:
host: "<源端公网IP>" # 公网直连用公网IP
username: "Administrator"
winrm_port: 5985
sms_agent:
proxy_mode: false # 公网不走代理
proxy_server:
host: "" # 公网留空
proxyopt:
skip: true
sms_task:
use_public_ip: true # 公网迁移
sg_source_cidrs: ["<源端公网IP>/32"] # 【红线】仅放行源端公网IP/32
use_eip: true # 绑定 EIP
Host_Information template (public network: contains only the source object,use_public_ip="true"):
export Host_Information='[
{
"主机名": "win-src-1", "公网IP": "<源端公网IP>", "内网IP": "<源端内网IP>",
"端口号": "5985", "用户名": "Administrator", "密码": "<密码>",
"region_id": "cn-north-4", "region_name": "华北-北京四",
"os_type": "WINDOWS", "use_public_ip": "true"
}
]'
Execute:
cd scripts/windows_migration/
python3 unified_migrate.py --scenario public --batch env --workers 10
Target two: private network migration (private)
- Applicable: the source cannot directly connect to Huawei Cloud and needs forwarding through a jump host (Squid/gost proxy); the task layer uses private network IPs.
- Target side: automatically create VPC/subnet/security group/ECS (use_eip=false, no EIP bound).
config/migrate.yaml Key items:
scenario: private # private=私网代理
source:
host: "<源端内网IP>" # 私网用内网IP(gost 转发目标)
username: "Administrator"
winrm_port: 5985
sms_agent:
proxy_mode: true # 私网走 gost+Squid
proxy_server:
host: "<跳板机公网IP>"
ssh_port: 22
ssh_username: "root"
ssh_password: "<跳板机密码>"
squid_port: 3128
gost_listen_port: 15985
proxyopt:
skip: false
sms_task:
use_public_ip: false # 私网迁移
sg_source_cidrs: ["<源端内网IP>/32"] # 【红线】私网放行源端内网IP/32,否则 ATTACH_AGENT_IMAGE 失败
use_eip: false # 私网不绑 EIP
Host_Information template (private network: source object + proxy object):
export Host_Information='[
{
"主机名": "win-src-1", "公网IP": "<源端公网IP>", "内网IP": "<源端内网IP>",
"端口号": "5985", "用户名": "Administrator", "密码": "<密码>",
"region_id": "cn-north-4", "region_name": "华北-北京四",
"os_type": "WINDOWS", "use_public_ip": "false"
},
{
"代理主机名": "jump-1", "公网IP": "<跳板机公网IP>", "内网IP": "<跳板机内网IP>",
"端口号": "22", "用户名": "root", "密码": "<跳板机密码>",
"region_id": "cn-north-4", "region_name": "华北-北京四"
}
]'
Execute:
cd scripts/windows_migration/
python3 unified_migrate.py --scenario private --batch env --workers 10
# 迁移结束清理(源端 + 代理;先打通 gost 再清源端)
python3 cleanup_environment.py --config config/migrate.yaml --yes
Quick start (dual CLI)
cd scripts/windows_migration/
# Phase A(自动含源端清理)
python3 unified_migrate.py --scenario public --config config/migrate.yaml --json # 公网直连
python3 unified_migrate.py --scenario private --config config/migrate.yaml # 私网代理
# 批量(环境变量 Host_Information 已 export;CSV 兼容:--batch config/hosts.csv)
python3 unified_migrate.py --scenario public --batch env --workers 10
python3 unified_migrate.py --scenario private --batch env --workers 10
# 未传 --batch 但已设置 Host_Information 时,自动进入批量模式
# Phase B(每个变更子命令可用 --yes 免确认;破坏性命令需属主)
python3 sms_task.py discover --config config/migrate.yaml
python3 sms_task.py prepare-target --config config/migrate.yaml
python3 sms_task.py create --yes && python3 sms_task.py start --yes
python3 sms_task.py wait --config config/migrate.yaml # 短分段轮询至 SUCCESS
# 同步/割接(KooCLI 7.2.x 兼容):
# sync(默认 syncing)→ 枚举不支持时自动回退跳过(任务已 MIGRATE_SUCCESS 无需增量同步)
# cutover(官方 cutover)→ 枚举不支持时自动回退 = “启动目的端 ECS”(BatchStartServers,等效割接)
python3 sms_task.py sync --yes && python3 sms_task.py cutover --yes
python3 sms_task.py cleanup --yes && python3 sms_task.py release --resource-type <eip|sg> --resource-id <id> --yes
# 环境清理(源端 + 代理;先打通 gost 再清源端)
python3 cleanup_environment.py --config config/migrate.yaml --yes
Agent restart and bidirectional check (measured in private network scenarios)
- ProhibitedLaunching directly as a SYSTEM / regular background process
C:\SMS-Agent-Py3\SMS-Agent.exe: without an interactive desktop it will "appear hung" (process exists, logs stop being written, the console never shows the source side). - Manual execution is prohibited
schtasks /run /tn ConfigureSMSAgent: the.secrets.datwritten by ConfigurePhase is a one-time file (automatically deleted after being read by AutoIt/exe); when running /run manually, the secrets have already disappeared → the log showsinvalid AK or SK→ actually not registered. The bat that executes the exe has already added a pre-check guard for missing secrets. - Correct restart method: rerun the official recovery entry point(rebuild secrets and read back for verification → re-upload exe → recreate scheduled task → automatic Verify; for private networks use gost+Squid):
Exit code 0 = recovery successful; after re-registration,python3 agent_recover.py --scenario private --config config/migrate.yaml # 私网 python3 agent_recover.py --scenario public --config config/migrate.yaml # 公网source_idchanges, refer to the latest return from the console.
Two-way check (both steps pass ⇒ Agent started successfully):
- Direction 1 (source-side process + heartbeat):
Get-Process SMS-Agentprocess exists; Info log last written <5min ago and no new failures in Error log. (During startup,HwDiskMon.sys PermissionErroris a known harmless item) - Direction 2 (console registration):
hcloud SMS ListServers --cli-region=<region>: count≥1, target IP exists,connected=true、state=waiting, all checks OK.
Security rules and ownership system
See all 71 rules in
references/safety-rules.md; the core red lines are the following 12 + ownership red lines.
| # | Rule |
|---|---|
| 1 | Destructive operations on the source side are prohibited (snapshot/shutdown/disk modification) |
| 2 | Weak passwords are prohibited (target admin_pass meets complexity) |
| 3 | Skipping syncing verification is prohibited (must wait for replication to complete) |
| 4 | Manually creating ECS is prohibited (must go through this skill's orchestration) |
| 5 | Security group 0.0.0.0/0 wide open is prohibited (only allow ports required for migration) |
| 6 | AK/SK not written to disk, not output, not logged, not stored in database |
| 7 | WinRM prefers HTTPS(5986), HTTP(5985) only on intranet |
| 8 | Windows uses MIGRATE_BLOCK, does not use MIGRATE_FILE |
| 9 | Source must be NTFS, basic disk, disk≤23, CPU<80%, memory>256MB, system volume on disk 1 |
| 10 | 2012+ Py3 GUI Agent;2008/7 Py2 CLI Agent |
| 11 | GPT partition target disk +1GB; RAID/BitLocker/AD/multi-node database prohibited |
| 12 | Task name ≤16 characters + character set validation (SMS.7711) |
Resource ownership red lines (OwnerID fingerprint):
owner_id = base32(HMAC(migration_ak, SALT || project_id))[:8]
is_owned = Tag(owner_id)==derived 或 名称含 derived 或 config/owned_resources.json 精确 ID
- O1 Any change/delete to non-owner resources is prohibited, only read-only reuse; O2 Adding rules to non-owner SGs is prohibited
- O3 Delete-type operations requireowner + explicit user confirmation; O4 Security group 0.0.0.0/0 is always rejected; O5 Non-owner ECS must not be stopped/started; O6 Credentials not written to disk, masked in logs
Prevent resource waste: VPC/subnet stable-name reuse, security group rule fingerprint merging (N machines→1 SG), EIP idle reuse with owner priority,release returned immediately after use.
Directory structure
huawei-cloud-migration-windows-ecs/
├── SKILL.md / README.md # 主文档与速览
├── requirements.txt # Python 依赖清单
├── scripts/windows_migration/ # ★ 唯一迁移执行引擎
│ ├── unified_migrate.py # Phase A:Agent 部署编排(public/private/批量,主机信息取 Host_Information)
│ ├── sms_task.py # Phase B:控制面编排(discover→prepare→create→start→…→release)
│ ├── preflight_check.py # 迁移前置环境变量检查(unified_migrate 启动自动拦截)
│ ├── cleanup_environment.py # 环境清理编排(①gost→②源端→③代理)
│ ├── cleanup_windows.py # 源端残留清理命令清单(单一来源,幂等)
│ ├── agent_recover.py # Agent 官方恢复入口(WinRM→ConfigurePhase→VerifyPhase)
│ ├── run_migration.sh / run_sms_task.sh # 运行包装脚本
│ ├── config/ # migrate.public/private.yaml + env.*.sh.example 模板(占位符,600)
│ ├── core/ # config/hostinfo/ownership/sms_client/target_provider/winrm/executor
│ ├── phases/ # 10 阶段(含 cleanup_source_phase 部署前必清)
│ ├── scenarios/ # public/private 场景编排
│ ├── proxyopt/ # 私网跳板机:Squid/gost/HTTP/precache(config 驱动)
│ └── scripts/py3|py2/ # configure exe/au3、Py2 CLI 配置工具
├── references/ # 安全规则/流程/排障/Agent 指南(问题统一归档 troubleshooting.md)
└── templates/ # pre/post 迁移检查脚本
Reference documents
- Security rules list:
references/safety-rules.md(71 rules) - Process details:
references/migration-workflow.md; troubleshooting and issue handling collection (unified archive):references/troubleshooting.md - Windows Agent installation/automation:
references/sms-agent-guide.md、references/sms-agent-automation-guide.md