def clean_for_disk(self, disk): if not self.metadatas: raise SnapshotNotStarted() elif disk not in self.metadatas["disks"]: raise DiskNotSnapshot(disk) snapshot_path = os.path.abspath( self.metadatas["disks"][disk]["snapshot"]) disk_path = os.path.abspath(self.metadatas["disks"][disk]["src"]) # Do not commit and pivot if our snapshot is not the current top disk current_disk_path = (get_xml_block_of_disk( self.dom.XMLDesc(), disk).xpath("source")[0].get("file")) if os.path.abspath(current_disk_path) != snapshot_path: logger.warning( "It seems that the domain configuration (and specifically the " "one related to its disks) has been changed. The current disk " "will not be committed nor pivoted with the external " "snapshot, to not break the backing chain.\n\n" "You might want to manually check, where your domain image is " "stored, if no temporary file is remaining ({}).".format( os.path.dirname(current_disk_path))) return if self.dom.isActive(): self.blockcommit_disk(disk) else: self._qemu_img_commit(disk_path, snapshot_path) self._manually_pivot_disk(disk, disk_path) os.remove(snapshot_path) self.metadatas["disks"].pop(disk) self._callbacks_registrer.callbacks.pop(snapshot_path, None)
def create_temp_snapshot_files(self, tmpdir): tmpdir = tmpdir.mkdir("snaps") self.snapshot_helper.dom.set_storage_basedir( os.path.abspath(str(tmpdir))) snapshots = {} # swap disk and snapshots, to just change the domain basedir for disk, prop in self.snapshot_helper.disks.items(): dom_disk_path = (get_xml_block_of_disk( self.snapshot_helper.dom.XMLDesc(), disk)).xpath("source")[0].get("file") tmpdir.join(os.path.basename(dom_disk_path)).write("") prop["snapshot"] = dom_disk_path disk_path = tmpdir.join("{}.qcow2.{}".format(disk, "123")) prop["src"] = str(disk_path) snapshots[disk] = prop["snapshot"] return snapshots
def _manually_pivot_disk(self, disk, src): """ Replace the disk src :param disk: disk name :param src: new disk path """ dom_xml = defusedxml.lxml.fromstring(self.dom.XMLDesc()) disk_xml = get_xml_block_of_disk(dom_xml, disk) disk_xml.xpath("source")[0].set("file", src) if self.conn.getLibVersion() >= 3000000: # update a disk is broken in libvirt < 3.0 return self.dom.updateDeviceFlags( defusedxml.lxml.tostring(disk_xml).decode(), libvirt.VIR_DOMAIN_AFFECT_CONFIG) else: return self.conn.defineXML( defusedxml.lxml.tostring(dom_xml).decode())
def create_temp_snapshot_files(self, tmpdir): tmpdir = tmpdir.mkdir("snaps") self.snapshot_helper.dom.set_storage_basedir( os.path.abspath(str(tmpdir)) ) snapshots = {} # swap disk and snapshots, to just change the domain basedir for disk, prop in self.snapshot_helper.disks.items(): dom_disk_path = ( get_xml_block_of_disk(self.snapshot_helper.dom.XMLDesc(), disk) ).xpath("source")[0].get("file") tmpdir.join(os.path.basename(dom_disk_path)).write("") prop["snapshot"] = dom_disk_path disk_path = tmpdir.join("{}.qcow2.{}".format(disk, "123")) prop["src"] = str(disk_path) snapshots[disk] = prop["snapshot"] return snapshots
def _manually_pivot_disk(self, disk, src): """ Replace the disk src :param disk: disk name :param src: new disk path """ dom_xml = defusedxml.lxml.fromstring(self.dom.XMLDesc()) disk_xml = get_xml_block_of_disk(dom_xml, disk) disk_xml.xpath("source")[0].set("file", src) if self.conn.getLibVersion() >= 3000000: # update a disk is broken in libvirt < 3.0 return self.dom.updateDeviceFlags( defusedxml.lxml.tostring(disk_xml).decode(), libvirt.VIR_DOMAIN_AFFECT_CONFIG ) else: return self.conn.defineXML( defusedxml.lxml.tostring(dom_xml).decode() )
def clean_for_disk(self, disk): if not self.metadatas: raise SnapshotNotStarted() elif disk not in self.metadatas["disks"]: raise DiskNotSnapshot(disk) snapshot_path = os.path.abspath( self.metadatas["disks"][disk]["snapshot"] ) disk_path = os.path.abspath(self.metadatas["disks"][disk]["src"]) # Do not commit and pivot if our snapshot is not the current top disk current_disk_path = get_xml_block_of_disk( self.dom.XMLDesc(), disk ).xpath("source")[0].get("file") if os.path.abspath(current_disk_path) != snapshot_path: logger.warning( "It seems that the domain configuration (and specifically the " "one related to its disks) has been changed. The current disk " "will not be committed nor pivoted with the external " "snapshot, to not break the backing chain.\n\n" "You might want to manually check, where your domain image is " "stored, if no temporary file is remaining ({}).".format( os.path.dirname(current_disk_path) ) ) return if self.dom.isActive(): self.blockcommit_disk(disk) else: self._qemu_img_commit(disk_path, snapshot_path) self._manually_pivot_disk(disk, disk_path) os.remove(snapshot_path) self.metadatas["disks"].pop(disk) if not self.metadatas["disks"] and self._callback_id is not None: self._deregister_callback()
def post_backup_cleaning_snapshot(self, disk, disk_path, snapshot_path): snapshot_path = os.path.abspath(snapshot_path) # Do not commit and pivot if our snapshot is not the current top disk current_disk_path = get_xml_block_of_disk( self.dom.XMLDesc(), disk).xpath("source")[0].get("file") if os.path.abspath(current_disk_path) != snapshot_path: logger.warning( "It seems that the domain configuration (and specifically the " "one related to its disks) has been changed. The current disk " "will not be committed nor pivoted with the external " "snapshot, to not break the backing chain.\n\n" "You might want to manually check, where your domain image is " "stored, if no temporary file is remaining ({}).".format( os.path.dirname(current_disk_path))) return if self.dom.isActive(): self._blockcommit_disk(disk) else: self._qemu_img_commit(disk_path, snapshot_path) self._manually_pivot_disk(disk, disk_path)
def get_src_for_disk(self, dom_xml, disk): elem = get_xml_block_of_disk(dom_xml, disk) return elem.xpath("source")[0].get("file")