def test_external_snapshot(
            self, mock_has_snapshot, mock_create_volume,
            mock_libvirt_version, mock_create_snapshot):
        mock_has_snapshot.return_value = False
        mock_libvirt_version.return_value = 1002012

        environment = Environment.create('test_env_extsnap')
        node = Node.node_create(name='test_node', environment=environment)
        vol_volume_name = factories.fuzzy_string()
        vol = Volume.volume_create(vol_volume_name,
                                   capacity=1000000000,
                                   format='qcow2',
                                   environment=environment)
        DiskDevice.node_attach_volume(node=node, volume=vol)
        environment.define()

        snap_name = factories.fuzzy_string('snap_')
        snap_description = factories.fuzzy_string('description_')

        node.snapshot(name=snap_name, description=snap_description,
                      external=True)

        mock_create_volume.assert_called_with(snap_name)
        mock_create_snapshot.assert_called_with(
            node=node, name=snap_name, description=snap_description,
            disk_only=False, external=True)
    def test_update_disks_from_snapshot_with_children(
            self, mock_has_snapshot, mock_volume_define,
            mock_libvirt_version,
            mock_get_snapshot, mock_create_snapshot):
        mock_has_snapshot.return_value = False
        mock_libvirt_version.return_value = 1002012
        volume_path_template = '/var/lib/libvirt/images/{0}'

        environment = Environment.create('test_env_extsnap')
        node = Node.node_create(name='test_node', environment=environment)
        vol_volume_name = factories.fuzzy_string()
        vol = Volume.volume_create(vol_volume_name,
                                   capacity=1000000000,
                                   format='qcow2',
                                   environment=environment)
        vol.uuid = volume_path_template.format(vol_volume_name)
        DiskDevice.node_attach_volume(node=node, volume=vol)
        environment.define()

        snap_name = factories.fuzzy_string('snap_')
        snap_description = factories.fuzzy_string('description_')
        snapshot_volume_name = '{0}.{1}'.format(vol_volume_name,
                                                snap_name)
        mock_get_snapshot.return_value = mock.Mock(
            get_type='external', children_num=1,
            disks={'sda': volume_path_template.format(snap_name)})

        node.snapshot(name=snap_name, description=snap_description,
                      external=True)
        vol1 = environment.get_volume(name=snapshot_volume_name)
        vol1.uuid = volume_path_template.format(snap_name)
        vol1.save()

        node._update_disks_from_snapshot(snap_name)
        self.assertEqual(node.disk_devices[0].volume, vol)
    def test_external_snapshot_erase(
            self, mock_has_snapshot, mock_volume_define,
            mock_libvirt_version, mock_delete_snapshot,
            mock_get_snapshot, mock_create_snapshot):
        mock_has_snapshot.return_value = False
        mock_libvirt_version.return_value = 1002012
        mock_get_snapshot.return_value = mock.Mock(get_type='external',
                                                   children_num=0)

        environment = Environment.create('test_env_extsnap')
        node = Node.node_create(name='test_node', environment=environment)
        vol_volume_name = factories.fuzzy_string()
        vol = Volume.volume_create(vol_volume_name,
                                   capacity=1000000000,
                                   format='qcow2',
                                   environment=environment)
        DiskDevice.node_attach_volume(node=node, volume=vol)
        environment.define()

        snap_name = factories.fuzzy_string('snap_')
        snap_description = factories.fuzzy_string('description_')

        node.snapshot(name=snap_name, description=snap_description,
                      external=True)

        mock_has_snapshot.return_value = True

        node.erase_snapshot(snap_name)

        mock_delete_snapshot.assert_called_with(node=node, name=snap_name)
        self.assertEqual(node.disk_devices[0].volume, vol)
    def test_node_set_snapshot_current(self, mock_conn):
        xml_fuzzy = factories.fuzzy_string()
        xml = '''<domainsnapshot>
  <name>{0}</name>
  <domain>
    <cpu mode="host-model" />
  </domain>
</domainsnapshot>'''.format(xml_fuzzy)
        snapshot = mock.Mock()
        snapshot.getXMLDesc.return_value = xml
        domain = mock.Mock()
        domain.isActive.return_value = False
        domain.snapshotCreateXML.return_value = True
        domain.snapshotCurrent.return_value = snapshot
        domain.snapshotLookupByName.return_value = snapshot
        mock_conn.return_value.lookupByUUIDString.return_value = domain
        node = mock.Mock(uuid='test_node')
        snapshot_name = factories.fuzzy_string()

        dd = DevopsDriver()
        dd.node_set_snapshot_current(node, snapshot_name)

        domain.snapshotCreateXML.assert_called_with(
            xml, libvirt.VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
            libvirt.VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)
    def test_external_snapshot_volume_creation(self, mock_volume_define):
        mock_volume_define.return_value = None

        environment = Environment.create('test_env_extsnap')
        node = Node.node_create(name='test_node', environment=environment)
        vol_volume_name = factories.fuzzy_string()
        vol = Volume.volume_create(vol_volume_name,
                                   capacity=1000000000,
                                   format='qcow2',
                                   environment=environment)
        DiskDevice.node_attach_volume(node=node, volume=vol)
        environment.define()

        snapshot_name = factories.fuzzy_string('snap_')
        snapshot_volume_name = '{0}.{1}'.format(vol_volume_name,
                                                snapshot_name)

        node.snapshot_create_volume(snapshot_name)

        vol1 = environment.get_volume(name=snapshot_volume_name)

        self.assertEqual(len(node.disk_devices), 1)
        self.assertEqual(vol1.name, snapshot_volume_name)
        self.assertEqual(vol1.format, 'qcow2')
        self.assertEqual(vol1.environment, environment)
        self.assertEqual(vol1.backing_store, vol)
        self.assertEqual(vol1, node.disk_devices[0].volume)
        mock_volume_define.assert_called_with(vol1)
    def test_node_create_snapshot_external_domain_not_active(
            self, mock_conn, mock_os, mock_set_snapshot_current,
            mock_get_snapshots, mock_snapshot_exists, mock_snapshot_xml):
        mock_snapshot_exists.return_value = False
        mock_get_snapshots.return_value = [mock.Mock(get_type='external')]
        node = mock.Mock(uuid='test_node')
        mock_os.path.exists.return_value = False

        domain = mock.Mock()
        domain.isActive.return_value = False
        domain.snapshotCreateXML.return_value = True
        mock_conn.return_value.lookupByUUIDString.return_value = domain

        snapshot_name = factories.fuzzy_string()
        description = factories.fuzzy_string('description_')
        xml_fuzzy = factories.fuzzy_string()
        xml = '<{0}/>'.format(xml_fuzzy)
        mock_snapshot_xml.return_value = xml
        disk_only = False
        external = True

        dd = DevopsDriver()
        dd.node_create_snapshot(node, name=snapshot_name, disk_only=disk_only,
                                description=description, external=external)

        mock_snapshot_xml.assert_called_with(snapshot_name, description, node,
                                             disk_only, external, '/path/snap')
        self.assertEqual(mock_os.makedirs.called, True)
        self.assertEqual(domain.snapshotCreateXML.called, True)
        domain.snapshotCreateXML.assert_called_with(
            xml, libvirt.VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY |
            libvirt.VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT)
        mock_set_snapshot_current.assert_called_with(node, snapshot_name)
    def test_external_snapshot_memory_snapshot_exists(self, mock_os):
        self.domain_set_active(True)
        name = factories.fuzzy_string('snapshot_')
        external_dir = factories.fuzzy_string('/extsnap/')
        description = factories.fuzzy_string('test_description_')
        mem_filename = "{0}/snapshot-memory-{1}_{2}.{3}".format(
            external_dir, self.node.environment.name,
            self.node.name, name)

        def mock_exists(*args):
            return True if args[0] == mem_filename else False
        mock_os.path.exists = mock_exists
        expected = '''
<domainsnapshot>
    <name>{0}</name>
    <description>{1}</description>
    <memory file="{2}/snapshot-memory-{3}_{4}.{5}-0" snapshot="external"/>
    <disks>
        <disk file="{6}" name="{7}" snapshot="external"/>
    </disks>
</domainsnapshot>'''.format(name, description, external_dir,
                            self.node.environment.name, self.node.name, name,
                            self.disk1_volume_path, self.disk1.target_dev)
        self.check_snaphot_xml(name, description, expected, disk_only=False,
                               external=True, external_dir=external_dir)
    def test_snapshot_with_existing_name_force_delete(self, mock_has_snapshot,
                                                      mock_delete_snapshot,
                                                      mock_create_snapshot):
        mock_has_snapshot.return_value = True

        environment = Environment.create('test_env_extsnap')
        node = Node.node_create(name='test_node', environment=environment)
        environment.define()

        snap_name = factories.fuzzy_string('snap_')
        snap_description = factories.fuzzy_string('description_')

        node.snapshot(
            name=snap_name,
            force=True,
            description=snap_description,
            disk_only=True)

        self.assertEqual(mock_delete_snapshot.called, True)
        mock_delete_snapshot.assert_called_with(node=node, name=snap_name)
        mock_create_snapshot.assert_called_with(
            node=node,
            name=snap_name,
            description=snap_description,
            disk_only=True,
            external=False)
    def test_snapshot(self):
        name = factories.fuzzy_string('test_snapshot_')
        description = factories.fuzzy_string('test_description_')
        expected = '''
<domainsnapshot>
    <name>{0}</name>
    <description>{1}</description>
</domainsnapshot>'''.format(name, description)
        self.check_snaphot_xml(name, description, expected)
Beispiel #10
0
    def test_snapshot(self):
        name = factories.fuzzy_string('test_snapshot_')
        description = factories.fuzzy_string('test_description_')
        expected = '''
<domainsnapshot>
    <name>{0}</name>
    <description>{1}</description>
</domainsnapshot>'''.format(name, description)
        self.check_snaphot_xml(name, description, expected)
 def setUp(self):
     super(TestSnapshotXml, self).setUp()
     self.node.name = factories.fuzzy_string('testname_')
     self.node.environment.name = factories.fuzzy_string('testenv_')
     self.disk1_volume_path = factories.fuzzy_string('/volumes/')
     self.disk1 = mock.Mock()
     self.disk1.device = 'disk'
     self.disk1.target_dev = factories.fuzzy_string()
     self.disk1.volume.get_path.return_value = self.disk1_volume_path
     self.node.disk_devices = [self.disk1]
    def test_node_revert_snapshot_shutoff(
            self, mock_conn, mock_set_snapshot_current,
            mock_node_active, mock_node_destroy):
        snapshot_name = factories.fuzzy_string('name_')
        domain_name = factories.fuzzy_string('domain_')
        disk1_path = factories.fuzzy_string('/path/to/')
        snapshot1_path = factories.fuzzy_string('/path/to/')
        domain_xml_tmpl = '''  <domain>
    <name>{0}</name>
    <cpu mode='host-model'/>
    <devices>
      <disk type='file' device='disk' snapshot='external'>
        <driver name='qemu' type='raw'/>
        <source file='{1}'/>
        <target dev='vda' bus='virtio'/>
      </disk>
    </devices>
  </domain>'''
        domain_xml = domain_xml_tmpl.format(domain_name, disk1_path)
        snapshot_xml = '''<domainsnapshot>
  <name>{0}</name>
  <state>shutoff</state>
  <memory snapshot='no'/>
  <disks>
    <disk name='vda' snapshot='external'>
      <driver type='qcow2'/>
      <source file='{1}'/>
    </disk>
  </disks>
  {2}
</domainsnapshot>'''.format(snapshot_name, snapshot1_path, domain_xml)
        snapshot = mock.Mock()
        snapshot.numChildren.return_value = 0
        snapshot.getXMLDesc.return_value = snapshot_xml
        domain = mock.Mock()
        domain.snapshotCreateXML.return_value = True
        domain.snapshotCurrent.return_value = snapshot
        domain.snapshotLookupByName.return_value = snapshot
        mock_conn.return_value.lookupByUUIDString.return_value = domain
        node = mock.Mock(uuid='test_node')
        mock_node_active.return_value = False

        dd = DevopsDriver()
        dd.node_revert_snapshot(node, snapshot_name)

        domain_xml_expected = domain_xml_tmpl.format(domain_name,
                                                     snapshot1_path)

        self.assertEqual(mock_node_destroy.called, False)
        mock_conn().defineXML.assert_called_with(
            '{0}\n'.format(ET.tostring(ET.fromstring(domain_xml_expected))))
        mock_set_snapshot_current.assert_called_with(node, snapshot_name)
    def test_external_snapshot_revert_with_children_revert_present(
            self, mock_revert_snapshot_recreate_disks,
            mock_revert_snapshot, mock_get_snapshot, mock_has_snapshot,
            mock_destroy, mock_update_disks_from_snapshot):
        revert_postfix = '-revert3'

        def get_snapshot(node, snapname):
            if snapname.endswith(revert_postfix):
                return mock.Mock(get_type='external', children_num=0)
            else:
                return mock.Mock(get_type='external', children_num=1)

        mock_has_snapshot.return_value = True
        mock_get_snapshot.side_effect = get_snapshot
        environment = Environment.create('test_env_extsnap')
        node = Node.node_create(name='test_node', environment=environment)
        environment.define()
        snapshot_name = factories.fuzzy_string('snap_')
        node.revert(name=snapshot_name, destroy=False)

        revert_snapshot_name = '{0}{1}'.format(snapshot_name, revert_postfix)
        mock_update_disks_from_snapshot.assert_called_with(
            revert_snapshot_name)
        mock_revert_snapshot_recreate_disks.assert_called_with(
            node, revert_snapshot_name)
        mock_revert_snapshot.assert_called_with(node=node,
                                                name=revert_snapshot_name)
    def test_external_disk_only(self):
        self.domain_set_active(True)
        name = factories.fuzzy_string('snapshot_')
        external_dir = factories.fuzzy_string('/extsnap/')
        description = None
        expected = '''
<domainsnapshot>
    <name>{0}</name>
    <memory snapshot="no"/>
    <disks>
        <disk file="{1}" name="{2}" snapshot="external"/>
    </disks>
</domainsnapshot>'''.format(name, self.disk1_volume_path,
                            self.disk1.target_dev)
        self.check_snaphot_xml(name, description, expected, disk_only=True,
                               external=True, external_dir=external_dir)
    def test_node_delete_snapshot_external(self, mock_conn,
                                           mock_delete_snapshot_files):
        domain_xml = '''<domain>
    <name>{0}</name>
    <cpu mode='host-model'/>
    <devices>
      <disk type='file' device='disk' snapshot='external'>
        <driver name='qemu' type='raw'/>
        <source file='{1}'/>
        <target dev='vda' bus='virtio'/>
      </disk>
      <disk type='file' device='disk' snapshot='external'>
        <driver name='qemu' type='raw'/>
        <source file='{2}'/>
        <target dev='vdb' bus='virtio'/>
      </disk>
    </devices>
  </domain>'''.format(factories.fuzzy_string('name_'),
                      factories.fuzzy_string('/path/to/'),
                      factories.fuzzy_string('/path/to/'))
        snapshot_xml = '''<domainsnapshot>
  <memory snapshot="external"/>
  <disks/>
  {0}
</domainsnapshot>'''.format(domain_xml)
        snapshot = mock.Mock()
        snapshot.numChildren.return_value = 0
        snapshot.getXMLDesc.return_value = snapshot_xml
        snapshot.delete.return_value = True
        domain = mock.Mock()
        domain.isActive.return_value = True
        domain.snapshotCreateXML.return_value = True
        domain.snapshotCurrent.return_value = snapshot
        domain.snapshotLookupByName.return_value = snapshot
        mock_conn.return_value.lookupByUUIDString.return_value = domain
        mock_conn.return_value.defineXML.return_value = True
        node = mock.Mock(uuid='test_node')

        dd = DevopsDriver()
        dd.node_delete_snapshot(node, 'snapname')

        self.assertEqual(domain.destroy.called, True)
        mock_delete_snapshot_files.assert_called_with(snapshot)
        snapshot.delete.assert_called_with(2)
        mock_conn().defineXML.assert_called_with(
            '{0}\n'.format(ET.tostring(ET.fromstring(domain_xml))))
    def test_external_snapshot(self):
        self.domain_set_active(True)
        name = factories.fuzzy_string('snapshot_')
        external_dir = factories.fuzzy_string('/extsnap/')
        description = factories.fuzzy_string('test_description_')
        expected = '''
<domainsnapshot>
    <name>{0}</name>
    <description>{1}</description>
    <memory file="{2}/snapshot-memory-{3}_{4}.{5}" snapshot="external"/>
    <disks>
        <disk file="{6}" name="{7}" snapshot="external"/>
    </disks>
</domainsnapshot>'''.format(name, description, external_dir,
                            self.node.environment.name, self.node.name, name,
                            self.disk1_volume_path, self.disk1.target_dev)
        self.check_snaphot_xml(name, description, expected, disk_only=False,
                               external=True, external_dir=external_dir)
    def test_node_set_snapshot_current_host_passthrough(self, mock_conn):
        xml_fuzzy = factories.fuzzy_string()
        cpu_model = factories.fuzzy_string()
        domain_cpu = '''<cpu mode="host-passthrough">
<model>{0}</model>
<vendor>Intel</vendor>
</cpu>'''.format(cpu_model)
        domain_xml = '''<domain>
{0}
</domain>'''.format(domain_cpu)
        snapshot_cpu = '<cpu mode="host-passthrough" />'
        snapshot_xml_tmpl = '''<domainsnapshot>
<name>{0}</name>
<domain>
{1}
</domain>
</domainsnapshot>'''
        snapshot_xml = snapshot_xml_tmpl.format(xml_fuzzy, snapshot_cpu)
        snapshot = mock.Mock()
        snapshot.getXMLDesc.return_value = snapshot_xml
        domain = mock.Mock()
        domain.isActive.return_value = False
        domain.snapshotCreateXML.return_value = True
        domain.snapshotCurrent.return_value = snapshot
        domain.snapshotLookupByName.return_value = snapshot
        domain.XMLDesc.return_value = domain_xml
        mock_conn.return_value.lookupByUUIDString.return_value = domain
        snapshot.getDomain.return_value = domain
        node = mock.Mock(uuid='test_node')
        snapshot_name = factories.fuzzy_string()

        dd = DevopsDriver()
        dd.node_set_snapshot_current(node, snapshot_name)

        domain.snapshotCreateXML.assert_called_with(
            snapshot_xml_tmpl.format(xml_fuzzy, domain_cpu),
            libvirt.VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
            libvirt.VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)
    def test_external_snapshot_with_children_erase(
            self, mock_has_snapshot, mock_get_snapshot, mock_delete_snapshot):
        mock_has_snapshot.return_value = True
        mock_get_snapshot.return_value = mock.Mock(
            get_type='external', children_num=1)

        environment = Environment.create('test_env_extsnap')
        node = Node.node_create(name='test_node', environment=environment)
        environment.define()

        snap_name = factories.fuzzy_string('snap_')
        node.erase_snapshot(snap_name)

        self.assertEqual(mock_delete_snapshot.called, False)
        mock_get_snapshot.assert_called_with(node, snap_name)
    def test_external_snapshot_revert_no_children(
            self, mock_revert_snapshot_recreate_disks,
            mock_revert_snapshot, mock_get_snapshot, mock_has_snapshot,
            mock_destroy, mock_update_disks_from_snapshot):
        mock_has_snapshot.return_value = True
        mock_get_snapshot.return_value = mock.Mock(get_type='external',
                                                   children_num=0)

        environment = Environment.create('test_env_extsnap')
        node = Node.node_create(name='test_node', environment=environment)
        environment.define()
        snapshot_name = factories.fuzzy_string('snap_')
        node.revert(name=snapshot_name, destroy=False)

        mock_update_disks_from_snapshot.assert_called_with(snapshot_name)
        mock_revert_snapshot_recreate_disks.assert_called_with(
            node, snapshot_name)
        mock_revert_snapshot.assert_called_with(node=node, name=snapshot_name)
    def test_delete_snapshot_files(self, mock_os, mock_conn):
        mock_os.path.isfile.return_value = True
        mock_os.remove.return_value = True

        memory_file = factories.fuzzy_string('/path/to/')
        snapshot_xml = '''<domainsnapshot>
  <memory file="{0}" snapshot="external"/>
  <domain>
    <cpu mode='host-model'/>
  </domain>
</domainsnapshot>'''.format(memory_file)
        snapshot = mock.Mock()
        snapshot.getXMLDesc.return_value = snapshot_xml

        dd = DevopsDriver()
        dd._delete_snapshot_files(snapshot)

        mock_os.remove.assert_called_with(memory_file)
    def test_node_revert_snapshot_recreate_disks(self, mock_conn):
        disk1_file = factories.fuzzy_string('/var/lib/libvirt/images/')
        disk2_file = factories.fuzzy_string('/var/lib/libvirt/images/')
        snapshot_xml = '''<domainsnapshot>
  <memory snapshot="no"/>
  <disks>
    <disk name='vda' snapshot='external'>
      <source file='{0}'/>
    </disk>
    <disk name='vdb' snapshot='external'>
      <source file='{1}'/>
    </disk>
  </disks>
  <domain>
    <cpu mode='host-model'/>
  </domain>
</domainsnapshot>'''.format(disk1_file, disk2_file)
        snapshot = mock.Mock()
        snapshot.getXMLDesc.return_value = snapshot_xml
        snapshot.numChildren.return_value = 0

        domain = mock.Mock()
        domain.isActive.return_value = True
        domain.snapshotCreateXML.return_value = True
        domain.snapshotCurrent.return_value = False
        domain.snapshotLookupByName.return_value = snapshot
        mock_conn.return_value.lookupByUUIDString.return_value = domain

        pool = mock.Mock()
        pool.createXML.return_value = mock.Mock()

        def define_volume(*args):
            volume_xml = '<{0}/>'.format(args[0])
            volume = mock.Mock()
            volume.XMLDesc.return_value = volume_xml
            volume.storagePoolLookupByVolume.return_value = pool
            volume.detele.return_value = True
            return volume

        volume1 = define_volume(disk1_file)
        volume2 = define_volume(disk2_file)

        def return_volume(*args):
            if args[0] == disk1_file:
                return volume1
            elif args[0] == disk2_file:
                return volume2

        mock_conn.return_value.storageVolLookupByKey.side_effect = \
            return_volume
        node = mock.Mock(uuid='test_node')

        dd = DevopsDriver()
        dd.node_revert_snapshot_recreate_disks(node, 'snapname')

        self.assertEqual(volume1.delete.called, True)
        self.assertEqual(volume2.delete.called, True)
        mock_conn().storageVolLookupByKey.assert_has_calls(
            [mock.call(disk1_file), mock.call(disk2_file)],
            any_order=True)
        pool.createXML.assert_has_calls(
            [mock.call(volume1.XMLDesc()),
                mock.call(volume2.XMLDesc())],
            any_order=True)
    def test_node_revert_snapshot_has_children(
            self, mock_conn, mock_set_snapshot_current,
            mock_node_active, mock_node_destroy):
        snapshot_name = factories.fuzzy_string('name_')
        domain_name = factories.fuzzy_string('domain_')
        memory_snapshot_path = factories.fuzzy_string('/path/to/')
        disk1_path = factories.fuzzy_string('/path/to/')
        disk2_path = factories.fuzzy_string('/path/to/')
        snapshot1_path = factories.fuzzy_string('/path/to/')
        snapshot2_path = factories.fuzzy_string('/path/to/')
        domain_xml_tmpl = '''  <domain>
    <name>{0}</name>
    <cpu mode='host-model'/>
    <devices>
      <disk type='file' device='disk' snapshot='external'>
        <driver name='qemu' type='raw'/>
        <source file='{1}'/>
        <target dev='vda' bus='virtio'/>
      </disk>
      <disk type='file' device='disk' snapshot='external'>
        <driver name='qemu' type='raw'/>
        <source file='{2}'/>
        <target dev='vdb' bus='virtio'/>
      </disk>
    </devices>
  </domain>'''
        domain_xml = domain_xml_tmpl.format(
            domain_name, disk1_path, disk2_path)
        snapshot_xml = '''<domainsnapshot>
  <name>{0}</name>
  <description>Snapshot of OS install and updates</description>
  <state>running</state>
  <creationTime>1270477159</creationTime>
  <parent>
    <name>bare-os-install</name>
  </parent>
  <memory file='{1}' snapshot='external'/>
  <disks>
    <disk name='vda' snapshot='external'>
      <driver type='qcow2'/>
      <source file='{2}'/>
    </disk>
    <disk name='vdb' snapshot='external'>
      <driver type='qcow2'/>
      <source file='{3}'/>
    </disk>
  </disks>
  {4}
</domainsnapshot>'''.format(snapshot_name, memory_snapshot_path,
                            snapshot1_path, snapshot2_path, domain_xml)
        snapshot = mock.Mock()
        snapshot.numChildren.return_value = 1
        snapshot.getXMLDesc.return_value = snapshot_xml
        domain = mock.Mock()
        domain.isActive.return_value = True
        domain.snapshotCreateXML.return_value = True
        domain.snapshotCurrent.return_value = snapshot
        domain.snapshotLookupByName.return_value = snapshot
        mock_conn.return_value.lookupByUUIDString.return_value = domain
        node = mock.Mock(uuid='test_node')
        mock_node_active.return_value = True

        dd = DevopsDriver()
        dd.node_revert_snapshot(node, snapshot_name)

        mock_node_destroy.assert_called_with(node)
        mock_conn().restoreFlags.assert_called_with(
            memory_snapshot_path,
            dxml='{0}\n'.format(ET.tostring(ET.fromstring(domain_xml))),
            flags=libvirt.VIR_DOMAIN_SAVE_PAUSED)
        mock_set_snapshot_current.assert_called_with(node, snapshot_name)