Example #1
0
    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)
Example #2
0
    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
Example #3
0
    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())
Example #4
0
    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
Example #5
0
    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()
            )
Example #6
0
    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()
Example #7
0
    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)
Example #8
0
 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")
Example #9
0
 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")