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)
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)