使用Azure Python SDK v2.0.0rc6克隆运行中VM至其他资源组遇问题求助
解决Azure Python SDK v2.0.0rc6克隆VM到其他资源组的问题
看了你的代码,发现几个关键问题导致创建VM时抛出异常,我来帮你梳理下正确的步骤和修正方案:
核心问题分析
- StorageProfile参数冲突:你在创建VM时同时指定了
os_disk(attach模式)和image_reference,这两个参数是互斥的——用现有磁盘attach的话不需要镜像引用,反之亦然,这会直接触发Azure API报错。 - 直接引用源磁盘的错误:你直接用了原资源组里的
managed_disk.id来attach,但源磁盘正被原VM占用,而且目标资源组大概率没有访问原磁盘的权限。正确的做法是先从快照生成目标资源组的新托管磁盘,再用新磁盘创建VM。 - 未等待异步操作完成:创建快照是异步操作,你需要等待快照完全就绪后再进行后续步骤,否则会用到未完成的快照导致失败。
修正后的完整流程代码
1. 获取源VM和OS磁盘信息
# 获取源VM对象 source_vm = self.compute_client.virtual_machines.get( resource_group_name=source_rg_name, vm_name=virtual_machine ) os_disk_name = source_vm.storage_profile.os_disk.name # 获取源OS托管磁盘 managed_disk = self.compute_client.disks.get( resource_group_name=source_rg_name, disk_name=os_disk_name )
2. 创建OS磁盘快照并等待完成
snapshot_name = f"SNAPSHOT-{os_disk_name}" # 发起快照创建请求 snapshot_poller = self.compute_client.snapshots.create_or_update( resource_group_name=source_rg_name, snapshot_name=snapshot_name, parameters={ 'location': managed_disk.location, 'creation_data': { 'create_option': 'Copy', 'source_uri': managed_disk.id } } ) # 必须等待快照创建完成,否则后续基于快照创建磁盘会失败 snapshot = snapshot_poller.result()
3. 在目标资源组基于快照创建新的托管磁盘
target_os_disk_name = f"OS-DISK-{virtual_machine}" # 发起目标磁盘创建请求 disk_poller = self.compute_client.disks.create_or_update( resource_group_name=self.config.cybric_resource_group_name, disk_name=target_os_disk_name, parameters={ 'location': managed_disk.location, 'creation_data': { 'create_option': 'Copy', 'source_uri': snapshot.id }, 'sku': { 'name': managed_disk.sku.name # 保持和源磁盘相同的存储SKU } } ) target_os_disk = disk_poller.result()
4. 创建目标VM(修正StorageProfile)
# 准备网络配置(确保目标资源组的NIC已提前创建好) network_profile = azure.mgmt.compute.models.NetworkProfile( network_interfaces=[ azure.mgmt.compute.models.NetworkInterfaceReference( id=nic_obj['id'], primary=True ) ] ) # 构建StorageProfile:只指定OS磁盘,移除冲突的image_reference storage_profile = azure.mgmt.compute.models.StorageProfile( os_disk=azure.mgmt.compute.models.OSDisk( caching=source_vm.storage_profile.os_disk.caching, # 复用源VM的缓存设置 create_option=azure.mgmt.compute.models.DiskCreateOptionTypes.attach, name=target_os_disk_name, managed_disk=azure.mgmt.compute.models.ManagedDiskParameters( id=target_os_disk.id ) ) ) # (可选)添加数据磁盘:流程和OS磁盘一致,先快照再创建目标磁盘 data_disks = [] for idx, data_disk in enumerate(source_vm.storage_profile.data_disks): # 省略创建数据磁盘快照、目标磁盘的代码(参考OS磁盘流程) # 假设已创建好target_data_disk: data_disks.append(azure.mgmt.compute.models.DataDisk( lun=idx, create_option=azure.mgmt.compute.models.DiskCreateOptionTypes.attach, managed_disk=azure.mgmt.compute.models.ManagedDiskParameters( id=target_data_disk.id ), caching=data_disk.caching, name=target_data_disk.name )) storage_profile.data_disks = data_disks # 发起VM创建请求 vm_poller = self.compute_client.virtual_machines.create_or_update( resource_group_name=self.config.cybric_resource_group_name, vm_name=virtual_machine, parameters=azure.mgmt.compute.models.VirtualMachine( location=source_vm.location, os_profile=source_vm.os_profile, hardware_profile=source_vm.hardware_profile, network_profile=network_profile, storage_profile=storage_profile ) ) # 等待VM创建完成 target_vm = vm_poller.result()
额外注意事项
- 权限配置:确保你的服务主体或用户账号拥有原资源组的磁盘读取、快照创建权限,以及目标资源组的磁盘创建、VM创建权限。
- SKU一致性:创建目标磁盘时尽量保持和源磁盘相同的存储SKU(如Standard_LRS、Premium_LRS),避免性能或兼容性问题。
- 异步操作等待:所有
create_or_update返回的poller都需要调用result()等待操作完成,否则后续步骤会引用未就绪的资源。
内容的提问来源于stack exchange,提问作者adubbs
相关产品推荐
相关产品推荐

