From 8e54cba99a7842d2449f61db1c4310f47ef02b43 Mon Sep 17 00:00:00 2001 From: AlanJager Date: Tue, 7 Jun 2022 17:41:59 +0800 Subject: [PATCH 01/17] [vm]: response pci result Resolves: ZSTAC-27270 Change-Id: I6d756b72726d796279786e777675747a6c6f7062 --- kvmagent/kvmagent/plugins/vm_plugin.py | 59 ++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 9 deletions(-) diff --git a/kvmagent/kvmagent/plugins/vm_plugin.py b/kvmagent/kvmagent/plugins/vm_plugin.py index d84e678f44..cc81de47e4 100644 --- a/kvmagent/kvmagent/plugins/vm_plugin.py +++ b/kvmagent/kvmagent/plugins/vm_plugin.py @@ -192,6 +192,12 @@ class StartVmResponse(kvmagent.AgentResponse): def __init__(self): super(StartVmResponse, self).__init__() self.nicInfos = [] # type:list[VmNicInfo] + self.virtualDeviceInfoList = [] # type:list[VirtualDeviceInfo] + +class VirtualDeviceInfo(): + def __init__(self): + self.pciInfo = PciAddressInfo() + self.resourceUuid = None class VmNicInfo(): def __init__(self): @@ -206,10 +212,11 @@ def __init__(self): self.slot = None self.function = None -class AttchNicResponse(kvmagent.AgentResponse): +class AttachNicResponse(kvmagent.AgentResponse): def __init__(self): - super(AttchNicResponse, self).__init__() + super(AttachNicResponse, self).__init__() self.pciAddress = PciAddressInfo() + self.virtualDeviceInfoList = [] class GetVncPortCmd(kvmagent.AgentCommand): def __init__(self): @@ -327,6 +334,7 @@ def __init__(self): class AttachDataVolumeResponse(kvmagent.AgentResponse): def __init__(self): super(AttachDataVolumeResponse, self).__init__() + self.virtualDeviceInfoList = [] # type:list[VirtualDeviceInfo] class DetachDataVolumeCmd(kvmagent.AgentCommand): @@ -4067,6 +4075,8 @@ def generate_floppy_device_id(index): cdrom = make_empty_cdrom(cdrom_config.targetDev, cdrom_config.bus , cdrom_config.unit, iso.bootOrder) e(cdrom, 'source', None, {'file': iso.path}) + e(cdrom, 'serial', iso.resourceUuid) + def make_volumes(): devices = elements['devices'] #guarantee rootVolume is the first of the set @@ -4350,6 +4360,10 @@ def make_volume(dev_letter, v, r, dataSourceOnly=False): if dataSourceOnly: return vol + if v.pciAddress: + domain, bus, slot, function = parse_pci_device_address(v.pciAddress) + e(vol, 'address', None, {'type': 'pci', 'domain': '0x%s' % domain, 'bus': '0x%s' % bus, 'slot': '0x%s' % slot, 'function': '0x%s' % function}) + Vm.set_device_address(vol, v) if v.bootOrder is not None and v.bootOrder > 0 and v.deviceId == 0: e(vol, 'boot', None, {'order': str(v.bootOrder)}) @@ -5207,18 +5221,22 @@ def detach_iso(self, req): @kvmagent.replyerror def attach_nic(self, req): cmd = jsonobject.loads(req[http.REQUEST_BODY]) - rsp = AttchNicResponse() + rsp = AttachNicResponse() vm = get_vm_by_uuid(cmd.vmUuid) vm.attach_nic(cmd) for iface in vm.domain_xmlobject.devices.get_child_node_as_list('interface'): - if iface.mac.address_ == cmd.nic.mac: - rsp.pciAddress.bus = iface.address.bus_ - rsp.pciAddress.function = iface.address.function_ - rsp.pciAddress.type = iface.address.type_ - rsp.pciAddress.domain = iface.address.domain_ - rsp.pciAddress.slot = iface.address.slot_ + if iface.mac.address_ != cmd.nic.mac: + continue + + virtualDeviceInfo = VirtualDeviceInfo() + virtualDeviceInfo.pciInfo.bus = iface.address.bus_ + virtualDeviceInfo.pciInfo.function = iface.address.function_ + virtualDeviceInfo.pciInfo.type = iface.address.type_ + virtualDeviceInfo.pciInfo.domain = iface.address.domain_ + virtualDeviceInfo.pciInfo.slot = iface.address.slot_ + rsp.virtualDeviceInfoList.append(virtualDeviceInfo) return jsonobject.dumps(rsp) @@ -5287,6 +5305,16 @@ def start_vm(self, req): vmNicInfo.macAddress = iface.mac.address_ rsp.nicInfos.append(vmNicInfo) + for disk in vm.domain_xmlobject.devices.get_child_node_as_list('disk'): + virtualDeviceInfo = VirtualDeviceInfo() + virtualDeviceInfo.pciInfo.bus = disk.address.bus_ + virtualDeviceInfo.pciInfo.function = disk.address.function_ + virtualDeviceInfo.pciInfo.type = disk.address.type_ + virtualDeviceInfo.pciInfo.domain = disk.address.domain_ + virtualDeviceInfo.pciInfo.slot = disk.address.slot_ + virtualDeviceInfo.resourceUuid = disk.serial + rsp.virtualDeviceInfoList.append(virtualDeviceInfo) + return jsonobject.dumps(rsp) def get_vm_stat_with_ps(self, uuid): @@ -5769,6 +5797,19 @@ def attach_data_volume(self, req): raise kvmagent.KvmError( 'unable to attach volume[%s] to vm[uuid:%s], vm must be running or paused' % (volume.installPath, vm.uuid)) vm.attach_data_volume(cmd.volume, cmd.addons) + + vm.refresh() + + disk, _ = vm._get_target_disk(volume) + + virtualDeviceInfo = VirtualDeviceInfo() + virtualDeviceInfo.pciInfo.bus = disk.address.bus_ + virtualDeviceInfo.pciInfo.function = disk.address.function_ + virtualDeviceInfo.pciInfo.type = disk.address.type_ + virtualDeviceInfo.pciInfo.domain = disk.address.domain_ + virtualDeviceInfo.pciInfo.slot = disk.address.slot_ + virtualDeviceInfo.resourceUuid = disk.serial + rsp.virtualDeviceInfoList.append(virtualDeviceInfo) except kvmagent.KvmError as e: logger.warn(linux.get_exception_stacktrace()) rsp.error = str(e) From 74c101a90f6e523f88b8a71d9aa20df91e6a15cf Mon Sep 17 00:00:00 2001 From: AlanJager Date: Fri, 17 Jun 2022 11:53:31 +0800 Subject: [PATCH 02/17] [vm]: memory snapshot for sblk Change-Id: I79687464747a6d667a6175666f7675716b667268 Signed-off-by: AlanJager --- kvmagent/kvmagent/plugins/vm_plugin.py | 65 +++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 7 deletions(-) diff --git a/kvmagent/kvmagent/plugins/vm_plugin.py b/kvmagent/kvmagent/plugins/vm_plugin.py index cc81de47e4..6c030b8809 100644 --- a/kvmagent/kvmagent/plugins/vm_plugin.py +++ b/kvmagent/kvmagent/plugins/vm_plugin.py @@ -2725,19 +2725,34 @@ def get_size(install_path): return VmPlugin._get_snapshot_size(install_path) logger.debug(vs_structs) - need_memory_snapshot = False + memory_snapshot_required = False for vs_struct in vs_structs: if vs_struct.live is False or vs_struct.full is True: raise kvmagent.KvmError("volume %s is not live or full snapshot specified, " "can not proceed") if vs_struct.memory: - e(snapshot, 'memory', None, attrib={'snapshot': 'external', 'file': vs_struct.installPath}) - need_memory_snapshot = True + memory_snapshot_required = True snapshot_dir = os.path.dirname(vs_struct.installPath) if not os.path.exists(snapshot_dir): os.makedirs(snapshot_dir) + memory_snapshot_path = None + if vs_struct.installPath.startswith("/dev/"): + lvm.active_lv(vs_struct.installPath) + shell.call("mkfs.ext4 -F %s" % vs_struct.installPath) + mount_path = vs_struct.installPath.replace("/dev/", "/tmp/") + if not os.path.exists(mount_path): + linux.mkdir(mount_path) + + if not linux.is_mounted(mount_path): + linux.mount(vs_struct.installPath, mount_path) + + memory_snapshot_path = mount_path + '/' + mount_path.rsplit('/', 1)[-1] + else: + memory_snapshot_path = vs_struct.installPath + + e(snapshot, 'memory', None, attrib={'snapshot': 'external', 'file': memory_snapshot_path}) memory_snapshot_struct = vs_struct continue @@ -2758,7 +2773,8 @@ def get_size(install_path): vs_struct.volumeUuid, target_disk.source.file_, vs_struct.installPath, - get_size(target_disk.source.file_))) + get_size(target_disk.source.file_), + vs_struct.memory)) self.refresh() for disk in self.domain_xmlobject.devices.get_child_node_as_list('disk'): @@ -2769,7 +2785,7 @@ def get_size(install_path): logger.debug('creating live snapshot for vm[uuid:{0}] volumes[id:{1}]:\n{2}'.format(self.uuid, disk_names, xml)) snap_flags = libvirt.VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA | libvirt.VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC - if not need_memory_snapshot: + if not memory_snapshot_required: snap_flags |= libvirt.VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY try: @@ -2807,6 +2823,11 @@ def get_size(install_path): logger.debug("after create snapshot by libvirt, expected volume[install path: %s] does%s exist." % (struct.installPath, "" if existing else " not")) + if struct.memory: + mount_path = struct.installPath.replace("/dev/", "/tmp/") + linux.umount(mount_path) + linux.rmdir_if_empty(mount_path) + def take_volume_snapshot(self, task_spec, volume, install_path, full_snapshot=False): device_id = volume.deviceId @@ -3230,6 +3251,17 @@ def _attach_nic(self, cmd): def check_device(_): self.refresh() for iface in self.domain_xmlobject.devices.get_child_node_as_list('interface'): + if iface.mac.address_ != cmd.nic.mac: + continue + + virtualDeviceInfo = VirtualDeviceInfo() + virtualDeviceInfo.pciInfo.bus = iface.address.bus_ + virtualDeviceInfo.pciInfo.function = iface.address.function_ + virtualDeviceInfo.pciInfo.type = iface.address.type_ + virtualDeviceInfo.pciInfo.domain = iface.address.domain_ + virtualDeviceInfo.pciInfo.slot = iface.address.slot_ + rsp.virtualDeviceInfoList.append(virtualDeviceInfo) + if iface.mac.address_ == cmd.nic.mac: # vf nic doesn't have internal name if cmd.nic.pciDeviceAddress is not None: @@ -5156,7 +5188,24 @@ def _start_vm(self, cmd): vm = Vm.from_StartVmCmd(cmd) if cmd.memorySnapshotPath: - vm.restore(cmd.memorySnapshotPath) + snapshot_path = None + if cmd.memorySnapshotPath.startswith("/dev/"): + if not os.path.exists(cmd.memorySnapshotPath): + lvm.active_lv(cmd.memorySnapshotPath, False) + + mount_path = cmd.memorySnapshotPath.replace("/dev/", "/tmp/") + if not linux.is_mounted(mount_path): + linux.mount(cmd.memorySnapshotPath, mount_path) + + snapshot_path = mount_path + '/' + mount_path.rsplit('/', 1)[-1] + + try: + vm.restore(snapshot_path) + finally: + linux.umount(mount_path) + linux.rmdir_if_empty(mount_path) + + lvm.deactive_lv(cmd.memorySnapshotPath) return wait_console = True if not cmd.addons or cmd.addons['noConsole'] is not True else False @@ -5305,6 +5354,7 @@ def start_vm(self, req): vmNicInfo.macAddress = iface.mac.address_ rsp.nicInfos.append(vmNicInfo) + for disk in vm.domain_xmlobject.devices.get_child_node_as_list('disk'): virtualDeviceInfo = VirtualDeviceInfo() virtualDeviceInfo.pciInfo.bus = disk.address.bus_ @@ -8912,7 +8962,7 @@ def __init__(self, volumeUuid, volume, installPath, vmInstanceUuid, previousInst class VolumeSnapshotResultStruct(object): - def __init__(self, volumeUuid, previousInstallPath, installPath, size=None): + def __init__(self, volumeUuid, previousInstallPath, installPath, size=None, memory=False): """ :type volumeUuid: str @@ -8924,6 +8974,7 @@ def __init__(self, volumeUuid, previousInstallPath, installPath, size=None): self.previousInstallPath = previousInstallPath self.installPath = installPath self.size = size + self.memory = memory @bash.in_bash From 94abf6f6bdc75e2613d104dfaf320cebb34aba0a Mon Sep 17 00:00:00 2001 From: AlanJager Date: Mon, 20 Jun 2022 17:29:44 +0800 Subject: [PATCH 03/17] [vm]: fix get pci address from xml Change-Id: I6f796f6d636e6f6b6373716b646f7564797a6374 Signed-off-by: AlanJager --- kvmagent/kvmagent/plugins/vm_plugin.py | 32 +++++++++++++------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/kvmagent/kvmagent/plugins/vm_plugin.py b/kvmagent/kvmagent/plugins/vm_plugin.py index 6c030b8809..191e15e1df 100644 --- a/kvmagent/kvmagent/plugins/vm_plugin.py +++ b/kvmagent/kvmagent/plugins/vm_plugin.py @@ -3254,14 +3254,6 @@ def check_device(_): if iface.mac.address_ != cmd.nic.mac: continue - virtualDeviceInfo = VirtualDeviceInfo() - virtualDeviceInfo.pciInfo.bus = iface.address.bus_ - virtualDeviceInfo.pciInfo.function = iface.address.function_ - virtualDeviceInfo.pciInfo.type = iface.address.type_ - virtualDeviceInfo.pciInfo.domain = iface.address.domain_ - virtualDeviceInfo.pciInfo.slot = iface.address.slot_ - rsp.virtualDeviceInfoList.append(virtualDeviceInfo) - if iface.mac.address_ == cmd.nic.mac: # vf nic doesn't have internal name if cmd.nic.pciDeviceAddress is not None: @@ -5358,11 +5350,15 @@ def start_vm(self, req): for disk in vm.domain_xmlobject.devices.get_child_node_as_list('disk'): virtualDeviceInfo = VirtualDeviceInfo() virtualDeviceInfo.pciInfo.bus = disk.address.bus_ - virtualDeviceInfo.pciInfo.function = disk.address.function_ + if xmlobject.has_element(disk.address, 'function'): + virtualDeviceInfo.pciInfo.function = disk.address.function_ virtualDeviceInfo.pciInfo.type = disk.address.type_ - virtualDeviceInfo.pciInfo.domain = disk.address.domain_ - virtualDeviceInfo.pciInfo.slot = disk.address.slot_ - virtualDeviceInfo.resourceUuid = disk.serial + if xmlobject.has_element(disk.address, 'domain'): + virtualDeviceInfo.pciInfo.domain = disk.address.domain_ + if xmlobject.has_element(disk.address, 'slot'): + virtualDeviceInfo.pciInfo.slot = disk.address.slot_ + if xmlobject.has_element(disk, 'serial'): + virtualDeviceInfo.resourceUuid = disk.serial.text_ rsp.virtualDeviceInfoList.append(virtualDeviceInfo) return jsonobject.dumps(rsp) @@ -5854,11 +5850,15 @@ def attach_data_volume(self, req): virtualDeviceInfo = VirtualDeviceInfo() virtualDeviceInfo.pciInfo.bus = disk.address.bus_ - virtualDeviceInfo.pciInfo.function = disk.address.function_ + if xmlobject.has_element(disk.address, 'function'): + virtualDeviceInfo.pciInfo.function = disk.address.function_ virtualDeviceInfo.pciInfo.type = disk.address.type_ - virtualDeviceInfo.pciInfo.domain = disk.address.domain_ - virtualDeviceInfo.pciInfo.slot = disk.address.slot_ - virtualDeviceInfo.resourceUuid = disk.serial + if xmlobject.has_element(disk.address, 'domain'): + virtualDeviceInfo.pciInfo.domain = disk.address.domain_ + if xmlobject.has_element(disk.address, 'slot'): + virtualDeviceInfo.pciInfo.slot = disk.address.slot_ + if xmlobject.has_element(disk, 'serial'): + virtualDeviceInfo.resourceUuid = disk.serial.text_ rsp.virtualDeviceInfoList.append(virtualDeviceInfo) except kvmagent.KvmError as e: logger.warn(linux.get_exception_stacktrace()) From e240bdd7660a460debdcac8690fb7dc346768f16 Mon Sep 17 00:00:00 2001 From: AlanJager Date: Mon, 20 Jun 2022 18:14:31 +0800 Subject: [PATCH 04/17] [vm]: fix set disk pci address Change-Id: I69746169787978737674706d767a6f7571716a6b Signed-off-by: AlanJager --- kvmagent/kvmagent/plugins/vm_plugin.py | 69 ++++++++++++++++---------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/kvmagent/kvmagent/plugins/vm_plugin.py b/kvmagent/kvmagent/plugins/vm_plugin.py index 191e15e1df..f1146d10c8 100644 --- a/kvmagent/kvmagent/plugins/vm_plugin.py +++ b/kvmagent/kvmagent/plugins/vm_plugin.py @@ -4156,7 +4156,7 @@ def make_backingstore(volume_path): dev_format = Vm._get_disk_target_dev_format(default_bus_type) e(disk, 'target', None, {'dev': dev_format % _dev_letter, 'bus': default_bus_type}) if default_bus_type == "ide" and cmd.imagePlatform.lower() == "other": - allocat_ide_config(disk) + allocat_ide_config(disk, _v) return disk @@ -4182,7 +4182,7 @@ def filebased_volume(_dev_letter, _v): dev_format = Vm._get_disk_target_dev_format(default_bus_type) e(disk, 'target', None, {'dev': dev_format % _dev_letter, 'bus': default_bus_type}) if default_bus_type == "ide" and cmd.imagePlatform.lower() == "other": - allocat_ide_config(disk) + allocat_ide_config(disk, _v) return disk def iscsibased_volume(_dev_letter, _v): @@ -4242,7 +4242,7 @@ def nbd_volume(_dev_letter, _v, _r = None): dev_format = Vm._get_disk_target_dev_format(default_bus_type) e(disk, 'target', None, {'dev': dev_format % _dev_letter, 'bus': default_bus_type}) if default_bus_type == "ide" and cmd.imagePlatform.lower() == "other": - allocat_ide_config(disk) + allocat_ide_config(disk, _v) return disk def ceph_volume(_dev_letter, _v): @@ -4277,7 +4277,7 @@ def build_ceph_disk(): else: disk = ceph_blk() if default_bus_type == "ide" and cmd.imagePlatform.lower() == "other": - allocat_ide_config(disk) + allocat_ide_config(disk, _v) return disk d = build_ceph_disk() @@ -4354,13 +4354,16 @@ def get_recover_path(v): qs = dict(urlparse.parse_qsl(u.query)) return qs.get("r") - def allocat_ide_config(_disk): - if len(volume_ide_configs) == 0: - err = "insufficient IDE address." - logger.warn(err) - raise kvmagent.KvmError(err) - volume_ide_config = volume_ide_configs.pop(0) - e(_disk, 'address', None, {'type': 'drive', 'bus': volume_ide_config.bus, 'unit': volume_ide_config.unit}) + def allocat_ide_config(_disk, _volume): + if _volume.pciAddress: + e(_disk, 'address', None, {'type': 'drive', 'bus': _volume.pciAddress.bus, 'unit': _volume.pciAddress.function}) + else: + if len(volume_ide_configs) == 0: + err = "insufficient IDE address." + logger.warn(err) + raise kvmagent.KvmError(err) + volume_ide_config = volume_ide_configs.pop(0) + e(_disk, 'address', None, {'type': 'drive', 'bus': volume_ide_config.bus, 'unit': volume_ide_config.unit}) def make_volume(dev_letter, v, r, dataSourceOnly=False): if r: @@ -4385,8 +4388,18 @@ def make_volume(dev_letter, v, r, dataSourceOnly=False): return vol if v.pciAddress: - domain, bus, slot, function = parse_pci_device_address(v.pciAddress) - e(vol, 'address', None, {'type': 'pci', 'domain': '0x%s' % domain, 'bus': '0x%s' % bus, 'slot': '0x%s' % slot, 'function': '0x%s' % function}) + attributes = {} + + if v.pciAddress.domain: + attributes = {'domain': '0x%s' % v.pciAddress.domain} + if v.pciAddress.bus: + attributes = {'bus': '0x%s' % v.pciAddress.bus} + if v.pciAddress.slot: + attributes = {'slot': '0x%s' % v.pciAddress.slot} + if v.pciAddress.function: + attributes = {'function': '0x%s' % v.pciAddress.function} + attributes = {'type': 'pci'} + e(vol, 'address', None, attributes) Vm.set_device_address(vol, v) if v.bootOrder is not None and v.bootOrder > 0 and v.deviceId == 0: @@ -5349,16 +5362,17 @@ def start_vm(self, req): for disk in vm.domain_xmlobject.devices.get_child_node_as_list('disk'): virtualDeviceInfo = VirtualDeviceInfo() + + # domain:bus:slot:function + # controller:bus:target:unit + virtualDeviceInfo.pciInfo.domain = disk.address.domain_ if disk.address.domain__ else disk.address.controller_ virtualDeviceInfo.pciInfo.bus = disk.address.bus_ - if xmlobject.has_element(disk.address, 'function'): - virtualDeviceInfo.pciInfo.function = disk.address.function_ + virtualDeviceInfo.pciInfo.slot = disk.address.slot_ if disk.address.slot__ else disk.address.target_ + virtualDeviceInfo.pciInfo.function = disk.address.function_ if disk.address.function__ else disk.address.unit_ virtualDeviceInfo.pciInfo.type = disk.address.type_ - if xmlobject.has_element(disk.address, 'domain'): - virtualDeviceInfo.pciInfo.domain = disk.address.domain_ - if xmlobject.has_element(disk.address, 'slot'): - virtualDeviceInfo.pciInfo.slot = disk.address.slot_ - if xmlobject.has_element(disk, 'serial'): + if disk.has_element('serial'): virtualDeviceInfo.resourceUuid = disk.serial.text_ + rsp.virtualDeviceInfoList.append(virtualDeviceInfo) return jsonobject.dumps(rsp) @@ -5850,15 +5864,16 @@ def attach_data_volume(self, req): virtualDeviceInfo = VirtualDeviceInfo() virtualDeviceInfo.pciInfo.bus = disk.address.bus_ - if xmlobject.has_element(disk.address, 'function'): - virtualDeviceInfo.pciInfo.function = disk.address.function_ + # domain:bus:slot:function + # controller:bus:target:unit + virtualDeviceInfo.pciInfo.domain = disk.address.domain_ if disk.address.domain__ else disk.address.controller_ + virtualDeviceInfo.pciInfo.bus = disk.address.bus_ + virtualDeviceInfo.pciInfo.slot = disk.address.slot_ if disk.address.slot__ else disk.address.target_ + virtualDeviceInfo.pciInfo.function = disk.address.function_ if disk.address.function__ else disk.address.unit_ virtualDeviceInfo.pciInfo.type = disk.address.type_ - if xmlobject.has_element(disk.address, 'domain'): - virtualDeviceInfo.pciInfo.domain = disk.address.domain_ - if xmlobject.has_element(disk.address, 'slot'): - virtualDeviceInfo.pciInfo.slot = disk.address.slot_ - if xmlobject.has_element(disk, 'serial'): + if disk.has_element('serial'): virtualDeviceInfo.resourceUuid = disk.serial.text_ + rsp.virtualDeviceInfoList.append(virtualDeviceInfo) except kvmagent.KvmError as e: logger.warn(linux.get_exception_stacktrace()) From 9ea99d8dddbd11142c0fa78f487fcc226c32a2b6 Mon Sep 17 00:00:00 2001 From: AlanJager Date: Wed, 22 Jun 2022 10:38:23 +0800 Subject: [PATCH 05/17] [vm]: fix restore memory snapshot fix mount_path usage use snapshot_path as memory snapshot path Change-Id: I7678686b6a65646871766a6b7a656c636b73716b Signed-off-by: AlanJager --- kvmagent/kvmagent/plugins/vm_plugin.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/kvmagent/kvmagent/plugins/vm_plugin.py b/kvmagent/kvmagent/plugins/vm_plugin.py index f1146d10c8..8749fd78bd 100644 --- a/kvmagent/kvmagent/plugins/vm_plugin.py +++ b/kvmagent/kvmagent/plugins/vm_plugin.py @@ -5194,6 +5194,7 @@ def _start_vm(self, cmd): if cmd.memorySnapshotPath: snapshot_path = None + mount_path = None if cmd.memorySnapshotPath.startswith("/dev/"): if not os.path.exists(cmd.memorySnapshotPath): lvm.active_lv(cmd.memorySnapshotPath, False) @@ -5203,14 +5204,17 @@ def _start_vm(self, cmd): linux.mount(cmd.memorySnapshotPath, mount_path) snapshot_path = mount_path + '/' + mount_path.rsplit('/', 1)[-1] + else: + snapshot_path = cmd.memorySnapshotPath try: vm.restore(snapshot_path) finally: - linux.umount(mount_path) - linux.rmdir_if_empty(mount_path) + if mount_path: + linux.umount(mount_path) + linux.rmdir_if_empty(mount_path) - lvm.deactive_lv(cmd.memorySnapshotPath) + lvm.deactive_lv(cmd.memorySnapshotPath) return wait_console = True if not cmd.addons or cmd.addons['noConsole'] is not True else False From e561616996de057172148b758b0d88ecb3a651be Mon Sep 17 00:00:00 2001 From: "hanyu.liang" Date: Tue, 28 Jun 2022 13:55:03 +0800 Subject: [PATCH 06/17] [vm_plugin]: fixed the inconsistent pci address of the data volume if the pci information of memBalloon exists in cmd, specify the pci address of memBalloon Related: ZSTAC-47558 Change-Id:a665b7475581442390bf9bd93c6aaf49 --- kvmagent/kvmagent/plugins/vm_plugin.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/kvmagent/kvmagent/plugins/vm_plugin.py b/kvmagent/kvmagent/plugins/vm_plugin.py index 8749fd78bd..b3fcf1f440 100644 --- a/kvmagent/kvmagent/plugins/vm_plugin.py +++ b/kvmagent/kvmagent/plugins/vm_plugin.py @@ -187,12 +187,14 @@ def __init__(self): self.systemSerialNumber = None self.bootMode = None self.consolePassword = None + self.memBalloon = None # type:VirtualDeviceInfo class StartVmResponse(kvmagent.AgentResponse): def __init__(self): super(StartVmResponse, self).__init__() self.nicInfos = [] # type:list[VmNicInfo] self.virtualDeviceInfoList = [] # type:list[VirtualDeviceInfo] + self.memBalloonInfo = None # type:VirtualDeviceInfo class VirtualDeviceInfo(): def __init__(self): @@ -4800,11 +4802,13 @@ def match_usb_device(addr): return False def make_balloon_memory(): - if cmd.addons['useMemBalloon'] is False: + if cmd.memBalloon is None: return devices = elements['devices'] b = e(devices, 'memballoon', None, {'model': 'virtio'}) e(b, 'stats', None, {'period': '10'}) + if cmd.memBalloon.pciInfo: + e(b, 'address', None, {'type': 'pci', 'domain': cmd.memBalloon.pciInfo.domain, 'bus': cmd.memBalloon.pciInfo.bus, 'slot': cmd.memBalloon.pciInfo.slot, 'function': cmd.memBalloon.pciInfo.function}) if kvmagent.get_host_os_type() == "debian": e(b, 'address', None, {'type': 'pci', 'controller': '0', 'bus': '0x00', 'slot': '0x04', 'function':'0x0'}) @@ -5379,6 +5383,16 @@ def start_vm(self, req): rsp.virtualDeviceInfoList.append(virtualDeviceInfo) + memBalloonPci = vm.domain_xmlobject.devices.get_child_node('memballoon') + if memBalloonPci is not None: + memBalloonInfo = VirtualDeviceInfo() + memBalloonInfo.pciInfo.domain = memBalloonPci.address.domain_ + memBalloonInfo.pciInfo.bus = memBalloonPci.address.bus_ + memBalloonInfo.pciInfo.slot = memBalloonPci.address.slot_ + memBalloonInfo.pciInfo.function = memBalloonPci.address.function_ + memBalloonInfo.pciInfo.type = memBalloonPci.address.type_ + rsp.memBalloonInfo = memBalloonInfo + return jsonobject.dumps(rsp) def get_vm_stat_with_ps(self, uuid): @@ -6176,7 +6190,7 @@ def _migrate_vm_with_block(self, vmUuid, dstHostIp, volumeDicts): os.remove(fpath) if shell_cmd.return_code == 0: return - + if shell_cmd.stderr and "Need a root block node" in shell_cmd.stderr: shell_cmd.stderr = "failed to block migrate %s, please check if volume backup job is in progress" % vmUuid @@ -8588,7 +8602,7 @@ def _clean_colo_heartbeat(self, conn, dom, event, detail, opaque): logger.debug("clean vm[uuid:%s] heartbeat, due to evnet %s" % (dom.name(), LibvirtEventManager.event_to_string(event))) heartbeat_thread.do_heart_beat = False heartbeat_thread.join() - + @bash.in_bash def _deactivate_drbd(self, conn, dom, event, detail, opaque): logger.debug("got event from libvirt, %s %s" % (dom.name(), LibvirtEventManager.event_to_string(event))) From 367f28e2b96af7d9793a25dc69c9510cff48eed2 Mon Sep 17 00:00:00 2001 From: "hanyu.liang" Date: Wed, 29 Jun 2022 10:50:02 +0800 Subject: [PATCH 07/17] [vm_plugin]: fix shareblock storage revert memory snapshot failure add deactive logic for memory volume Related: ZSTAC-47654 Change-Id:a665b7476541442390bf9bd93c6aaf49 --- kvmagent/kvmagent/plugins/vm_plugin.py | 1 + 1 file changed, 1 insertion(+) diff --git a/kvmagent/kvmagent/plugins/vm_plugin.py b/kvmagent/kvmagent/plugins/vm_plugin.py index b3fcf1f440..3c2e7b15c5 100644 --- a/kvmagent/kvmagent/plugins/vm_plugin.py +++ b/kvmagent/kvmagent/plugins/vm_plugin.py @@ -2829,6 +2829,7 @@ def get_size(install_path): mount_path = struct.installPath.replace("/dev/", "/tmp/") linux.umount(mount_path) linux.rmdir_if_empty(mount_path) + lvm.deactive_lv(struct.installPath) def take_volume_snapshot(self, task_spec, volume, install_path, full_snapshot=False): From 9dcf2c7ec815939cd2278d142117746bf22fbc97 Mon Sep 17 00:00:00 2001 From: "hanyu.liang" Date: Thu, 30 Jun 2022 15:09:39 +0800 Subject: [PATCH 08/17] [snapshotGroup]: fix the cdRom without iso does not exist serial after starting vm when starting the vm, serial is set regardless of whether the cdRom has an iso or not. Related: ZSTAC-47675 Change-Id:a665b7476751442390bf9bd93c6aaf49 --- kvmagent/kvmagent/plugins/vm_plugin.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/kvmagent/kvmagent/plugins/vm_plugin.py b/kvmagent/kvmagent/plugins/vm_plugin.py index 3c2e7b15c5..c6fecb9abd 100644 --- a/kvmagent/kvmagent/plugins/vm_plugin.py +++ b/kvmagent/kvmagent/plugins/vm_plugin.py @@ -4046,12 +4046,13 @@ def make_cdrom(): if len(empty_cdrom_configs) != max_cdrom_num: logger.error('ISO_DEVICE_LETTERS or EMPTY_CDROM_CONFIGS config error') - def make_empty_cdrom(target_dev, bus, unit, bootOrder): + def make_empty_cdrom(target_dev, bus, unit, bootOrder, resourceUuid): cdrom = e(devices, 'disk', None, {'type': 'file', 'device': 'cdrom'}) e(cdrom, 'driver', None, {'name': 'qemu', 'type': 'raw'}) e(cdrom, 'target', None, {'dev': target_dev, 'bus': default_bus_type}) e(cdrom, 'address', None, {'type': 'drive', 'bus': bus, 'unit': unit}) e(cdrom, 'readonly', None) + e(cdrom, 'serial', resourceUuid) if bootOrder is not None and bootOrder > 0: e(cdrom, 'boot', None, {'order': str(bootOrder)}) return cdrom @@ -4091,7 +4092,7 @@ def generate_floppy_device_id(index): cdrom_config = empty_cdrom_configs[iso.deviceId] if iso.isEmpty: - make_empty_cdrom(cdrom_config.targetDev, cdrom_config.bus, cdrom_config.unit, iso.bootOrder) + make_empty_cdrom(cdrom_config.targetDev, cdrom_config.bus, cdrom_config.unit, iso.bootOrder, iso.resourceUuid) continue if iso.path.startswith('ceph'): @@ -4099,11 +4100,9 @@ def generate_floppy_device_id(index): ic.iso = iso devices.append(ic.to_xmlobject(cdrom_config.targetDev, default_bus_type, cdrom_config.bus, cdrom_config.unit, iso.bootOrder)) else: - cdrom = make_empty_cdrom(cdrom_config.targetDev, cdrom_config.bus , cdrom_config.unit, iso.bootOrder) + cdrom = make_empty_cdrom(cdrom_config.targetDev, cdrom_config.bus , cdrom_config.unit, iso.bootOrder, iso.resourceUuid) e(cdrom, 'source', None, {'file': iso.path}) - e(cdrom, 'serial', iso.resourceUuid) - def make_volumes(): devices = elements['devices'] #guarantee rootVolume is the first of the set From 82c73e9a9fb1568ffdbf2d642cab2f62402ae332 Mon Sep 17 00:00:00 2001 From: AlanJager Date: Thu, 30 Jun 2022 18:34:08 +0800 Subject: [PATCH 09/17] [vm]: set memory in snapshot struct Resolves: ZSTAC-47683 Change-Id: I6c6b69796e6e626d647267696e64627673667674 --- kvmagent/kvmagent/plugins/vm_plugin.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kvmagent/kvmagent/plugins/vm_plugin.py b/kvmagent/kvmagent/plugins/vm_plugin.py index c6fecb9abd..4b19426e01 100644 --- a/kvmagent/kvmagent/plugins/vm_plugin.py +++ b/kvmagent/kvmagent/plugins/vm_plugin.py @@ -2798,7 +2798,8 @@ def get_size(install_path): memory_snapshot_struct.volumeUuid, memory_snapshot_struct.installPath, memory_snapshot_struct.installPath, - get_size(memory_snapshot_struct.installPath))) + get_size(memory_snapshot_struct.installPath), + True)) return return_structs except libvirt.libvirtError as ex: From ffa21db948b06c2c86cceabeda5e4f788bdf3f4e Mon Sep 17 00:00:00 2001 From: "hanyu.liang" Date: Fri, 1 Jul 2022 11:13:17 +0800 Subject: [PATCH 10/17] [vm_plugin]: fix vm failed to create memory snapshot umount is executed only if the path of the memory volume is /dev/ Resolves: ZSTAC-47768 Change-Id: I6c6b69796e6e626d477687696e64627673667674 --- kvmagent/kvmagent/plugins/vm_plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kvmagent/kvmagent/plugins/vm_plugin.py b/kvmagent/kvmagent/plugins/vm_plugin.py index 4b19426e01..7b6cdf00f8 100644 --- a/kvmagent/kvmagent/plugins/vm_plugin.py +++ b/kvmagent/kvmagent/plugins/vm_plugin.py @@ -2826,7 +2826,7 @@ def get_size(install_path): logger.debug("after create snapshot by libvirt, expected volume[install path: %s] does%s exist." % (struct.installPath, "" if existing else " not")) - if struct.memory: + if struct.memory and struct.installPath.startswith("/dev/"): mount_path = struct.installPath.replace("/dev/", "/tmp/") linux.umount(mount_path) linux.rmdir_if_empty(mount_path) From 53fcaac6211fe08e5e7fc14101b90275912c22da Mon Sep 17 00:00:00 2001 From: AlanJager Date: Mon, 4 Jul 2022 12:53:13 +0800 Subject: [PATCH 11/17] [vm]: set type for vm device address scsi device use a
--- kvmagent/kvmagent/plugins/vm_plugin.py | 31 +++++++++++++------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/kvmagent/kvmagent/plugins/vm_plugin.py b/kvmagent/kvmagent/plugins/vm_plugin.py index 7b6cdf00f8..c5bf839524 100644 --- a/kvmagent/kvmagent/plugins/vm_plugin.py +++ b/kvmagent/kvmagent/plugins/vm_plugin.py @@ -1854,7 +1854,22 @@ def set_device_address(disk_element, vol, vm_to_attach=None): target = disk_element.find('target') bus = target.get('bus') if target is not None else None - if bus == 'scsi': + if vol.pciAddress and vol.pciAddress.type == 'pci': + attributes = {} + + if vol.pciAddress.domain: + attributes = {'domain': '0x%s' % vol.pciAddress.domain} + if vol.pciAddress.bus: + attributes = {'bus': '0x%s' % vol.pciAddress.bus} + if vol.pciAddress.slot: + attributes = {'slot': '0x%s' % vol.pciAddress.slot} + if vol.pciAddress.function: + attributes = {'function': '0x%s' % vol.pciAddress.function} + attributes = {'type': vol.pciAddress.type} + e(vol, 'address', None, attributes) + elif vol.pciAddress and vol.pciAddress.type == 'driver': + e(disk_element, 'address', None, {'type': 'drive', 'controller': '0', 'unit': str(vol.pciAddress.function)}) + elif bus == 'scsi': occupied_units = vm_to_attach.get_occupied_disk_address_units(bus='scsi', controller=0) if vm_to_attach else [] default_unit = Vm.get_device_unit(vol.deviceId) unit = default_unit if default_unit not in occupied_units else max(occupied_units) + 1 @@ -4390,20 +4405,6 @@ def make_volume(dev_letter, v, r, dataSourceOnly=False): if dataSourceOnly: return vol - if v.pciAddress: - attributes = {} - - if v.pciAddress.domain: - attributes = {'domain': '0x%s' % v.pciAddress.domain} - if v.pciAddress.bus: - attributes = {'bus': '0x%s' % v.pciAddress.bus} - if v.pciAddress.slot: - attributes = {'slot': '0x%s' % v.pciAddress.slot} - if v.pciAddress.function: - attributes = {'function': '0x%s' % v.pciAddress.function} - attributes = {'type': 'pci'} - e(vol, 'address', None, attributes) - Vm.set_device_address(vol, v) if v.bootOrder is not None and v.bootOrder > 0 and v.deviceId == 0: e(vol, 'boot', None, {'order': str(v.bootOrder)}) From 5b1311bdc503cff02b6ae54f110a8a0b3bde2937 Mon Sep 17 00:00:00 2001 From: AlanJager Date: Mon, 4 Jul 2022 16:08:21 +0800 Subject: [PATCH 12/17] [vm]: fix typo Resolves: ZSTAC-47801 Change-Id: I666661707a69636c7174696478617864676e676e --- kvmagent/kvmagent/plugins/vm_plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kvmagent/kvmagent/plugins/vm_plugin.py b/kvmagent/kvmagent/plugins/vm_plugin.py index c5bf839524..a601bcb3a2 100644 --- a/kvmagent/kvmagent/plugins/vm_plugin.py +++ b/kvmagent/kvmagent/plugins/vm_plugin.py @@ -1866,7 +1866,7 @@ def set_device_address(disk_element, vol, vm_to_attach=None): if vol.pciAddress.function: attributes = {'function': '0x%s' % vol.pciAddress.function} attributes = {'type': vol.pciAddress.type} - e(vol, 'address', None, attributes) + e(disk_element, 'address', None, attributes) elif vol.pciAddress and vol.pciAddress.type == 'driver': e(disk_element, 'address', None, {'type': 'drive', 'controller': '0', 'unit': str(vol.pciAddress.function)}) elif bus == 'scsi': From 148b17aaf10043fedcf6decabbdea70a31ee15ed Mon Sep 17 00:00:00 2001 From: AlanJager Date: Wed, 6 Jul 2022 00:11:58 +0800 Subject: [PATCH 13/17] [vm]: fix disk missing address config Change-Id: I6b616366716d627463686e776161717a66777265 --- kvmagent/kvmagent/plugins/vm_plugin.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/kvmagent/kvmagent/plugins/vm_plugin.py b/kvmagent/kvmagent/plugins/vm_plugin.py index a601bcb3a2..7cb6e01ec3 100644 --- a/kvmagent/kvmagent/plugins/vm_plugin.py +++ b/kvmagent/kvmagent/plugins/vm_plugin.py @@ -1856,16 +1856,16 @@ def set_device_address(disk_element, vol, vm_to_attach=None): if vol.pciAddress and vol.pciAddress.type == 'pci': attributes = {} - if vol.pciAddress.domain: - attributes = {'domain': '0x%s' % vol.pciAddress.domain} + attributes['domain'] = vol.pciAddress.domain if vol.pciAddress.bus: - attributes = {'bus': '0x%s' % vol.pciAddress.bus} + attributes['bus'] = vol.pciAddress.bus if vol.pciAddress.slot: - attributes = {'slot': '0x%s' % vol.pciAddress.slot} + attributes['slot'] = vol.pciAddress.slot if vol.pciAddress.function: - attributes = {'function': '0x%s' % vol.pciAddress.function} - attributes = {'type': vol.pciAddress.type} + attributes['function'] = vol.pciAddress.function + + attributes['type'] = vol.pciAddress.type e(disk_element, 'address', None, attributes) elif vol.pciAddress and vol.pciAddress.type == 'driver': e(disk_element, 'address', None, {'type': 'drive', 'controller': '0', 'unit': str(vol.pciAddress.function)}) @@ -5213,6 +5213,8 @@ def _start_vm(self, cmd): else: snapshot_path = cmd.memorySnapshotPath + logger.debug('restoring vm:\n%s' % self.domain_xml) + try: vm.restore(snapshot_path) finally: From f0caa9f61d1cea47ea863b6fe31641883570970b Mon Sep 17 00:00:00 2001 From: AlanJager Date: Wed, 6 Jul 2022 01:27:26 +0800 Subject: [PATCH 14/17] [vm]: dumpxml before restore vm Change-Id: I6d617a616a627a6f7470756a70706579767a637a --- kvmagent/kvmagent/plugins/vm_plugin.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kvmagent/kvmagent/plugins/vm_plugin.py b/kvmagent/kvmagent/plugins/vm_plugin.py index 7cb6e01ec3..6f4ec5918b 100644 --- a/kvmagent/kvmagent/plugins/vm_plugin.py +++ b/kvmagent/kvmagent/plugins/vm_plugin.py @@ -2006,6 +2006,7 @@ def restore(self, path): def restore_from_file(conn): return conn.restoreFlags(path, self.domain_xml) + logger.debug('restoring vm:\n%s' % self.domain_xml) restore_from_file() def start(self, timeout=60, create_paused=False, wait_console=True): @@ -5213,8 +5214,6 @@ def _start_vm(self, cmd): else: snapshot_path = cmd.memorySnapshotPath - logger.debug('restoring vm:\n%s' % self.domain_xml) - try: vm.restore(snapshot_path) finally: From b3c451788db4957959f704191676c65fded3a00a Mon Sep 17 00:00:00 2001 From: AlanJager Date: Wed, 6 Jul 2022 12:08:10 +0800 Subject: [PATCH 15/17] [vm]: fix cdrom device address wrong usage Resolves: ZSTAC-47843 Change-Id: I746a62747a777175656464796e79687977697861 Signed-off-by: AlanJager --- kvmagent/kvmagent/plugins/vm_plugin.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/kvmagent/kvmagent/plugins/vm_plugin.py b/kvmagent/kvmagent/plugins/vm_plugin.py index 6f4ec5918b..6dfbb7127f 100644 --- a/kvmagent/kvmagent/plugins/vm_plugin.py +++ b/kvmagent/kvmagent/plugins/vm_plugin.py @@ -4063,11 +4063,20 @@ def make_cdrom(): if len(empty_cdrom_configs) != max_cdrom_num: logger.error('ISO_DEVICE_LETTERS or EMPTY_CDROM_CONFIGS config error') - def make_empty_cdrom(target_dev, bus, unit, bootOrder, resourceUuid): + # legacy_cdrom_config used for cdrom without deivce address + # cdrom given address record from management node side + def make_empty_cdrom(iso, legacy_cdrom_config, bootOrder, resourceUuid): cdrom = e(devices, 'disk', None, {'type': 'file', 'device': 'cdrom'}) e(cdrom, 'driver', None, {'name': 'qemu', 'type': 'raw'}) - e(cdrom, 'target', None, {'dev': target_dev, 'bus': default_bus_type}) - e(cdrom, 'address', None, {'type': 'drive', 'bus': bus, 'unit': unit}) + e(cdrom, 'target', None, {'dev': legacy_cdrom_config.targetDev, 'bus': default_bus_type}) + + if iso.pciAddress: + # domain:bus:slot:function + # controller:bus:target:unit + e(cdrom, 'address', None, {'type': 'drive', 'controller': iso.pciAddress.domain, 'bus': iso.pciAddress.bus, + 'target': iso.pciAddress.slot, 'unit': iso.pciAddress.function}) + else: + e(cdrom, 'address', None, {'type': 'drive', 'bus': legacy_cdrom_config.bus, 'unit': legacy_cdrom_config.unit}) e(cdrom, 'readonly', None) e(cdrom, 'serial', resourceUuid) if bootOrder is not None and bootOrder > 0: @@ -4109,7 +4118,7 @@ def generate_floppy_device_id(index): cdrom_config = empty_cdrom_configs[iso.deviceId] if iso.isEmpty: - make_empty_cdrom(cdrom_config.targetDev, cdrom_config.bus, cdrom_config.unit, iso.bootOrder, iso.resourceUuid) + make_empty_cdrom(iso, cdrom_config, iso.bootOrder, iso.resourceUuid) continue if iso.path.startswith('ceph'): @@ -4117,7 +4126,7 @@ def generate_floppy_device_id(index): ic.iso = iso devices.append(ic.to_xmlobject(cdrom_config.targetDev, default_bus_type, cdrom_config.bus, cdrom_config.unit, iso.bootOrder)) else: - cdrom = make_empty_cdrom(cdrom_config.targetDev, cdrom_config.bus , cdrom_config.unit, iso.bootOrder, iso.resourceUuid) + cdrom = make_empty_cdrom(iso, cdrom_config, iso.bootOrder, iso.resourceUuid) e(cdrom, 'source', None, {'file': iso.path}) def make_volumes(): From c44472ef34bdf1293a6a13b7957a5583c6f4c868 Mon Sep 17 00:00:00 2001 From: AlanJager Date: Wed, 6 Jul 2022 13:47:40 +0800 Subject: [PATCH 16/17] [vm]: use device address instead of pci address Change-Id: I75686872726a6976787a78726a6270756471666a Signed-off-by: AlanJager --- kvmagent/kvmagent/plugins/vm_plugin.py | 132 ++++++++++++------------- 1 file changed, 61 insertions(+), 71 deletions(-) diff --git a/kvmagent/kvmagent/plugins/vm_plugin.py b/kvmagent/kvmagent/plugins/vm_plugin.py index 6dfbb7127f..c3d0bb4b32 100644 --- a/kvmagent/kvmagent/plugins/vm_plugin.py +++ b/kvmagent/kvmagent/plugins/vm_plugin.py @@ -198,26 +198,32 @@ def __init__(self): class VirtualDeviceInfo(): def __init__(self): - self.pciInfo = PciAddressInfo() + self.deviceAddress = DeviceAddress() self.resourceUuid = None class VmNicInfo(): def __init__(self): - self.pciInfo = PciAddressInfo() + self.deviceAddress = DeviceAddress() self.macAddress = None -class PciAddressInfo(): +class DeviceAddress(): def __init__(self): self.type = None - self.domain = None self.bus = None + + # for pci address + self.domain = None self.slot = None self.function = None + # for dirver address + self.controller = None + self.target = None + self.unit = None + class AttachNicResponse(kvmagent.AgentResponse): def __init__(self): super(AttachNicResponse, self).__init__() - self.pciAddress = PciAddressInfo() self.virtualDeviceInfoList = [] class GetVncPortCmd(kvmagent.AgentCommand): @@ -1854,21 +1860,21 @@ def set_device_address(disk_element, vol, vm_to_attach=None): target = disk_element.find('target') bus = target.get('bus') if target is not None else None - if vol.pciAddress and vol.pciAddress.type == 'pci': + if vol.deviceAddress and vol.deviceAddress.type == 'pci': attributes = {} - if vol.pciAddress.domain: - attributes['domain'] = vol.pciAddress.domain - if vol.pciAddress.bus: - attributes['bus'] = vol.pciAddress.bus - if vol.pciAddress.slot: - attributes['slot'] = vol.pciAddress.slot - if vol.pciAddress.function: - attributes['function'] = vol.pciAddress.function - - attributes['type'] = vol.pciAddress.type + if vol.deviceAddress.domain: + attributes['domain'] = vol.deviceAddress.domain + if vol.deviceAddress.bus: + attributes['bus'] = vol.deviceAddress.bus + if vol.deviceAddress.slot: + attributes['slot'] = vol.deviceAddress.slot + if vol.deviceAddress.function: + attributes['function'] = vol.deviceAddress.function + + attributes['type'] = vol.deviceAddress.type e(disk_element, 'address', None, attributes) - elif vol.pciAddress and vol.pciAddress.type == 'driver': - e(disk_element, 'address', None, {'type': 'drive', 'controller': '0', 'unit': str(vol.pciAddress.function)}) + elif vol.deviceAddress and vol.deviceAddress.type == 'driver': + e(disk_element, 'address', None, {'type': 'drive', 'controller': vol.deviceAddress.controller, 'unit': str(vol.deviceAddress.unit)}) elif bus == 'scsi': occupied_units = vm_to_attach.get_occupied_disk_address_units(bus='scsi', controller=0) if vm_to_attach else [] default_unit = Vm.get_device_unit(vol.deviceId) @@ -4070,11 +4076,9 @@ def make_empty_cdrom(iso, legacy_cdrom_config, bootOrder, resourceUuid): e(cdrom, 'driver', None, {'name': 'qemu', 'type': 'raw'}) e(cdrom, 'target', None, {'dev': legacy_cdrom_config.targetDev, 'bus': default_bus_type}) - if iso.pciAddress: - # domain:bus:slot:function - # controller:bus:target:unit - e(cdrom, 'address', None, {'type': 'drive', 'controller': iso.pciAddress.domain, 'bus': iso.pciAddress.bus, - 'target': iso.pciAddress.slot, 'unit': iso.pciAddress.function}) + if iso.deviceAddress: + e(cdrom, 'address', None, {'type': 'drive', 'controller': iso.deviceAddress.controller, 'bus': iso.deviceAddress.bus, + 'target': iso.deviceAddress.target, 'unit': iso.deviceAddress.unit}) else: e(cdrom, 'address', None, {'type': 'drive', 'bus': legacy_cdrom_config.bus, 'unit': legacy_cdrom_config.unit}) e(cdrom, 'readonly', None) @@ -4383,8 +4387,8 @@ def get_recover_path(v): return qs.get("r") def allocat_ide_config(_disk, _volume): - if _volume.pciAddress: - e(_disk, 'address', None, {'type': 'drive', 'bus': _volume.pciAddress.bus, 'unit': _volume.pciAddress.function}) + if _volume.deviceAddress: + e(_disk, 'address', None, {'type': 'drive', 'bus': _volume.deviceAddress.bus, 'unit': _volume.deviceAddress.function}) else: if len(volume_ide_configs) == 0: err = "insufficient IDE address." @@ -4819,8 +4823,9 @@ def make_balloon_memory(): devices = elements['devices'] b = e(devices, 'memballoon', None, {'model': 'virtio'}) e(b, 'stats', None, {'period': '10'}) - if cmd.memBalloon.pciInfo: - e(b, 'address', None, {'type': 'pci', 'domain': cmd.memBalloon.pciInfo.domain, 'bus': cmd.memBalloon.pciInfo.bus, 'slot': cmd.memBalloon.pciInfo.slot, 'function': cmd.memBalloon.pciInfo.function}) + if cmd.memBalloon.deviceAddress: + e(b, 'address', None, {'type': 'pci', 'domain': cmd.memBalloon.deviceAddress.domain, 'bus': cmd.memBalloon.deviceAddress.bus, + 'slot': cmd.memBalloon.deviceAddress.slot, 'function': cmd.memBalloon.deviceAddress.function}) if kvmagent.get_host_os_type() == "debian": e(b, 'address', None, {'type': 'pci', 'controller': '0', 'bus': '0x00', 'slot': '0x04', 'function':'0x0'}) @@ -5305,11 +5310,11 @@ def attach_nic(self, req): continue virtualDeviceInfo = VirtualDeviceInfo() - virtualDeviceInfo.pciInfo.bus = iface.address.bus_ - virtualDeviceInfo.pciInfo.function = iface.address.function_ - virtualDeviceInfo.pciInfo.type = iface.address.type_ - virtualDeviceInfo.pciInfo.domain = iface.address.domain_ - virtualDeviceInfo.pciInfo.slot = iface.address.slot_ + virtualDeviceInfo.deviceAddress.bus = iface.address.bus_ + virtualDeviceInfo.deviceAddress.function = iface.address.function_ + virtualDeviceInfo.deviceAddress.type = iface.address.type_ + virtualDeviceInfo.deviceAddress.domain = iface.address.domain_ + virtualDeviceInfo.deviceAddress.slot = iface.address.slot_ rsp.virtualDeviceInfoList.append(virtualDeviceInfo) return jsonobject.dumps(rsp) @@ -5371,39 +5376,21 @@ def start_vm(self, req): vm = get_vm_by_uuid(cmd.vmInstanceUuid) for iface in vm.domain_xmlobject.devices.get_child_node_as_list('interface'): vmNicInfo = VmNicInfo() - vmNicInfo.pciInfo.bus = iface.address.bus_ - vmNicInfo.pciInfo.function = iface.address.function_ - vmNicInfo.pciInfo.type = iface.address.type_ - vmNicInfo.pciInfo.domain = iface.address.domain_ - vmNicInfo.pciInfo.slot = iface.address.slot_ + vmNicInfo.deviceAddress.bus = iface.address.bus_ + vmNicInfo.deviceAddress.function = iface.address.function_ + vmNicInfo.deviceAddress.type = iface.address.type_ + vmNicInfo.deviceAddress.domain = iface.address.domain_ + vmNicInfo.deviceAddress.slot = iface.address.slot_ vmNicInfo.macAddress = iface.mac.address_ rsp.nicInfos.append(vmNicInfo) for disk in vm.domain_xmlobject.devices.get_child_node_as_list('disk'): - virtualDeviceInfo = VirtualDeviceInfo() - - # domain:bus:slot:function - # controller:bus:target:unit - virtualDeviceInfo.pciInfo.domain = disk.address.domain_ if disk.address.domain__ else disk.address.controller_ - virtualDeviceInfo.pciInfo.bus = disk.address.bus_ - virtualDeviceInfo.pciInfo.slot = disk.address.slot_ if disk.address.slot__ else disk.address.target_ - virtualDeviceInfo.pciInfo.function = disk.address.function_ if disk.address.function__ else disk.address.unit_ - virtualDeviceInfo.pciInfo.type = disk.address.type_ - if disk.has_element('serial'): - virtualDeviceInfo.resourceUuid = disk.serial.text_ - - rsp.virtualDeviceInfoList.append(virtualDeviceInfo) + rsp.virtualDeviceInfoList.append(self.get_device_address_info(disk)) memBalloonPci = vm.domain_xmlobject.devices.get_child_node('memballoon') if memBalloonPci is not None: - memBalloonInfo = VirtualDeviceInfo() - memBalloonInfo.pciInfo.domain = memBalloonPci.address.domain_ - memBalloonInfo.pciInfo.bus = memBalloonPci.address.bus_ - memBalloonInfo.pciInfo.slot = memBalloonPci.address.slot_ - memBalloonInfo.pciInfo.function = memBalloonPci.address.function_ - memBalloonInfo.pciInfo.type = memBalloonPci.address.type_ - rsp.memBalloonInfo = memBalloonInfo + rsp.memBalloonInfo = self.get_device_address_info(memBalloonPci) return jsonobject.dumps(rsp) @@ -5876,6 +5863,22 @@ def destroy_vm(self, req): return jsonobject.dumps(rsp) + def get_device_address_info(self, device): + virtualDeviceInfo = VirtualDeviceInfo() + virtualDeviceInfo.deviceAddress.bus = device.address.bus_ if device.address.bus__ else None + virtualDeviceInfo.deviceAddress.domain = device.address.domain_ if device.address.domain__ else None + virtualDeviceInfo.deviceAddress.controller = device.address.controller_ if device.address.controller__ else None + virtualDeviceInfo.deviceAddress.slot = device.address.slot_ if device.address.slot__ else None + virtualDeviceInfo.deviceAddress.target = device.address.target_ if device.address.target__ else None + virtualDeviceInfo.deviceAddress.function = device.address.function_ if device.address.function__ else None + virtualDeviceInfo.deviceAddress.unit = device.address.unit_ if device.address.unit__ else None + virtualDeviceInfo.deviceAddress.type = device.address.type_ if device.address.type__ else None + + if device.has_element('serial'): + virtualDeviceInfo.resourceUuid = device.serial.text_ + + return virtualDeviceInfo + @kvmagent.replyerror def attach_data_volume(self, req): cmd = jsonobject.loads(req[http.REQUEST_BODY]) @@ -5891,20 +5894,7 @@ def attach_data_volume(self, req): vm.refresh() disk, _ = vm._get_target_disk(volume) - - virtualDeviceInfo = VirtualDeviceInfo() - virtualDeviceInfo.pciInfo.bus = disk.address.bus_ - # domain:bus:slot:function - # controller:bus:target:unit - virtualDeviceInfo.pciInfo.domain = disk.address.domain_ if disk.address.domain__ else disk.address.controller_ - virtualDeviceInfo.pciInfo.bus = disk.address.bus_ - virtualDeviceInfo.pciInfo.slot = disk.address.slot_ if disk.address.slot__ else disk.address.target_ - virtualDeviceInfo.pciInfo.function = disk.address.function_ if disk.address.function__ else disk.address.unit_ - virtualDeviceInfo.pciInfo.type = disk.address.type_ - if disk.has_element('serial'): - virtualDeviceInfo.resourceUuid = disk.serial.text_ - - rsp.virtualDeviceInfoList.append(virtualDeviceInfo) + rsp.virtualDeviceInfoList.append(self.get_device_address_info(disk)) except kvmagent.KvmError as e: logger.warn(linux.get_exception_stacktrace()) rsp.error = str(e) From 14a8505e62ab74bb1571e1523fae2adf312b387b Mon Sep 17 00:00:00 2001 From: AlanJager Date: Fri, 8 Jul 2022 17:14:21 +0800 Subject: [PATCH 17/17] [vm]: add lsof check before umount memory snapshot Resolves: ZSTAC-47683 Change-Id: I7a6d6e696e6d65716961727a6962776576676f73 --- kvmagent/kvmagent/plugins/vm_plugin.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/kvmagent/kvmagent/plugins/vm_plugin.py b/kvmagent/kvmagent/plugins/vm_plugin.py index c3d0bb4b32..943f14c775 100644 --- a/kvmagent/kvmagent/plugins/vm_plugin.py +++ b/kvmagent/kvmagent/plugins/vm_plugin.py @@ -5197,6 +5197,21 @@ def _prepare_ebtables_for_mocbr(self, cmd): bash.bash_r(EBTABLES_CMD + rule) bash.bash_r("ebtables-save | uniq | ebtables-restore") + def umount_snapshot_path(self, mount_path): + @linux.retry(times=15, sleep_time=1) + def wait_path_unused(path): + used_process = linux.linux_lsof(path) + if len(used_process) != 0: + raise RetryException("path %s still used: %s" % (path, used_process)) + + try: + wait_path_unused(mount_path) + finally: + used_process = linux.linux_lsof(mount_path) + if len(used_process) == 0: + linux.umount(mount_path) + linux.rm_dir_force(mount_path) + def _start_vm(self, cmd): try: vm = get_vm_by_uuid_no_retry(cmd.vmInstanceUuid, False) @@ -5232,8 +5247,7 @@ def _start_vm(self, cmd): vm.restore(snapshot_path) finally: if mount_path: - linux.umount(mount_path) - linux.rmdir_if_empty(mount_path) + self.umount_snapshot_path(mount_path) lvm.deactive_lv(cmd.memorySnapshotPath) return