def test_vol_update_glance_metadata(self): ctxt = context.get_admin_context() db.volume_create(ctxt, { 'id': fake.VOLUME_ID, 'volume_type_id': fake.VOLUME_TYPE_ID }) db.volume_create(ctxt, { 'id': fake.VOLUME2_ID, 'volume_type_id': fake.VOLUME_TYPE_ID }) db.volume_glance_metadata_create(ctxt, fake.VOLUME_ID, 'key1', 'value1') db.volume_glance_metadata_create(ctxt, fake.VOLUME2_ID, 'key1', 'value1') db.volume_glance_metadata_create(ctxt, fake.VOLUME2_ID, 'key2', 'value2') db.volume_glance_metadata_create(ctxt, fake.VOLUME2_ID, 'key3', 123) expected_metadata_1 = { 'volume_id': fake.VOLUME_ID, 'key': 'key1', 'value': 'value1' } metadata = db.volume_glance_metadata_get(ctxt, fake.VOLUME_ID) self.assertEqual(1, len(metadata)) for key, value in expected_metadata_1.items(): self.assertEqual(value, metadata[0][key]) expected_metadata_2 = ({ 'volume_id': fake.VOLUME2_ID, 'key': 'key1', 'value': 'value1' }, { 'volume_id': fake.VOLUME2_ID, 'key': 'key2', 'value': 'value2' }, { 'volume_id': fake.VOLUME2_ID, 'key': 'key3', 'value': '123' }) metadata = db.volume_glance_metadata_get(ctxt, fake.VOLUME2_ID) self.assertEqual(3, len(metadata)) for expected, meta in zip(expected_metadata_2, metadata): for key, value in expected.items(): self.assertEqual(value, meta[key]) self.assertRaises(exception.GlanceMetadataExists, db.volume_glance_metadata_create, ctxt, fake.VOLUME_ID, 'key1', 'value1a') metadata = db.volume_glance_metadata_get(ctxt, fake.VOLUME_ID) self.assertEqual(1, len(metadata)) for key, value in expected_metadata_1.items(): self.assertEqual(value, metadata[0][key])
def test_vol_delete_glance_metadata(self): ctxt = context.get_admin_context() db.volume_create(ctxt, {'id': 1}) db.volume_glance_metadata_delete_by_volume(ctxt, 1) vol_metadata = db.volume_glance_metadata_create( ctxt, 1, 'key1', 'value1') db.volume_glance_metadata_delete_by_volume(ctxt, 1) metadata = db.volume_glance_metadata_get(ctxt, 1) self.assertEqual(len(metadata), 0) db.volume_glance_metadata_delete_by_volume(ctxt, 1) metadata = db.volume_glance_metadata_get(ctxt, 1) self.assertEqual(len(metadata), 0)
def test_vol_update_glance_metadata(self): ctxt = context.get_admin_context() db.volume_create(ctxt, {'id': 1}) db.volume_create(ctxt, {'id': 2}) vol_metadata = db.volume_glance_metadata_create( ctxt, 1, 'key1', 'value1') vol_metadata = db.volume_glance_metadata_create( ctxt, 2, 'key1', 'value1') vol_metadata = db.volume_glance_metadata_create( ctxt, 2, 'key2', 'value2') vol_metadata = db.volume_glance_metadata_create(ctxt, 2, 'key3', 123) expected_metadata_1 = { 'volume_id': '1', 'key': 'key1', 'value': 'value1' } metadata = db.volume_glance_metadata_get(ctxt, 1) self.assertEqual(len(metadata), 1) for key, value in expected_metadata_1.items(): self.assertEqual(metadata[0][key], value) expected_metadata_2 = ({ 'volume_id': '2', 'key': 'key1', 'value': 'value1' }, { 'volume_id': '2', 'key': 'key2', 'value': 'value2' }, { 'volume_id': '2', 'key': 'key3', 'value': '123' }) metadata = db.volume_glance_metadata_get(ctxt, 2) self.assertEqual(len(metadata), 3) for expected, meta in zip(expected_metadata_2, metadata): for key, value in expected.iteritems(): self.assertEqual(meta[key], value) self.assertRaises(exception.GlanceMetadataExists, db.volume_glance_metadata_create, ctxt, 1, 'key1', 'value1a') metadata = db.volume_glance_metadata_get(ctxt, 1) self.assertEqual(len(metadata), 1) for key, value in expected_metadata_1.items(): self.assertEqual(metadata[0][key], value)
def obj_load_attr(self, attrname): if attrname not in self.OPTIONAL_FIELDS: raise exception.ObjectActionError( action='obj_load_attr', reason=_('attribute %s not lazy-loadable') % attrname) if not self._context: raise exception.OrphanedObjectError(method='obj_load_attr', objtype=self.obj_name()) if attrname == 'metadata': self.metadata = db.volume_metadata_get(self._context, self.id) elif attrname == 'admin_metadata': self.admin_metadata = {} if self._context.is_admin: self.admin_metadata = db.volume_admin_metadata_get( self._context, self.id) elif attrname == 'glance_metadata': self.glance_metadata = db.volume_glance_metadata_get( self._context, self.id) elif attrname == 'volume_type': self.volume_type = objects.VolumeType.get_by_id( self._context, self.volume_type_id) elif attrname == 'volume_attachment': attachments = objects.VolumeAttachmentList.get_all_by_volume_id( self._context, self.id) self.volume_attachment = attachments elif attrname == 'consistencygroup': consistencygroup = objects.ConsistencyGroup.get_by_id( self._context, self.consistencygroup_id) self.consistencygroup = consistencygroup elif attrname == 'snapshots': self.snapshots = objects.SnapshotList.get_all_for_volume( self._context, self.id) self.obj_reset_changes(fields=[attrname])
def _usage_from_volume(context, volume_ref, **kw): usage_info = dict( tenant_id=volume_ref['project_id'], user_id=volume_ref['user_id'], availability_zone=volume_ref['availability_zone'], volume_id=volume_ref['id'], volume_type=volume_ref['volume_type_id'], display_name=volume_ref['display_name'], launched_at=null_safe_str(volume_ref['launched_at']), created_at=null_safe_str(volume_ref['created_at']), status=volume_ref['status'], snapshot_id=volume_ref['snapshot_id'], size=volume_ref['size'], replication_status=volume_ref['replication_status'], replication_extended_status=volume_ref['replication_extended_status'], replication_driver_data=volume_ref['replication_driver_data'], metadata=volume_ref.get('volume_metadata'), ) usage_info.update(kw) try: usage_info.update( dict(glance_metadata=db.volume_glance_metadata_get( context, volume_ref['id']))) except exception.GlanceMetadataNotFound: pass except exception.VolumeNotFound: LOG.debug("Can not find volume %s at notify usage", volume_ref['id']) pass return usage_info
def obj_load_attr(self, attrname): if attrname not in self.OPTIONAL_FIELDS: raise exception.ObjectActionError( action='obj_load_attr', reason=_('attribute %s not lazy-loadable') % attrname) if not self._context: raise exception.OrphanedObjectError(method='obj_load_attr', objtype=self.obj_name()) if attrname == 'metadata': self.metadata = db.volume_metadata_get(self._context, self.id) elif attrname == 'admin_metadata': self.admin_metadata = {} if self._context.is_admin: self.admin_metadata = db.volume_admin_metadata_get( self._context, self.id) elif attrname == 'glance_metadata': try: # NOTE(dulek): We're using alias here to have conversion from # list to dict done there. self.volume_glance_metadata = db.volume_glance_metadata_get( self._context, self.id) except exception.GlanceMetadataNotFound: # NOTE(dulek): DB API raises when volume has no # glance_metadata. Silencing this because at this level no # metadata is a completely valid result. self.glance_metadata = {} elif attrname == 'volume_type': # If the volume doesn't have volume_type, VolumeType.get_by_id # would trigger a db call which raise VolumeTypeNotFound exception. self.volume_type = (objects.VolumeType.get_by_id( self._context, self.volume_type_id) if self.volume_type_id else None) elif attrname == 'volume_attachment': attachments = objects.VolumeAttachmentList.get_all_by_volume_id( self._context, self.id) self.volume_attachment = attachments elif attrname == 'consistencygroup': consistencygroup = objects.ConsistencyGroup.get_by_id( self._context, self.consistencygroup_id) self.consistencygroup = consistencygroup elif attrname == 'snapshots': self.snapshots = objects.SnapshotList.get_all_for_volume( self._context, self.id) elif attrname == 'cluster': # If this volume doesn't belong to a cluster (cluster_name is # empty), then cluster field will be None. if self.cluster_name: self.cluster = objects.Cluster.get_by_id( self._context, name=self.cluster_name) else: self.cluster = None elif attrname == 'group': group = objects.Group.get_by_id(self._context, self.group_id) self.group = group self.obj_reset_changes(fields=[attrname])
def test_volume_glance_metadata_copy_to_volume(self): vol1 = db.volume_create(self.ctxt, {}) vol2 = db.volume_create(self.ctxt, {}) db.volume_glance_metadata_create(self.ctxt, vol1['id'], 'm1', 'v1') snapshot = db.snapshot_create(self.ctxt, {'volume_id': vol1['id']}) db.volume_glance_metadata_copy_to_snapshot(self.ctxt, snapshot['id'], vol1['id']) db.volume_glance_metadata_copy_to_volume(self.ctxt, vol2['id'], snapshot['id']) metadata = db.volume_glance_metadata_get(self.ctxt, vol2['id']) metadata = dict([(m['key'], m['value']) for m in metadata]) self.assertEqual(metadata, {'m1': 'v1'})
def test_vol_glance_metadata_copy_from_volume_to_volume(self): ctxt = context.get_admin_context() db.volume_create(ctxt, {'id': 1}) db.volume_create(ctxt, {'id': 100, 'source_volid': 1}) vol_meta = db.volume_glance_metadata_create(ctxt, 1, 'key1', 'value1') db.volume_glance_metadata_copy_from_volume_to_volume(ctxt, 1, 100) expected_meta = {'key': 'key1', 'value': 'value1'} for meta in db.volume_glance_metadata_get(ctxt, 100): for (key, value) in expected_meta.items(): self.assertEqual(meta[key], value)
def test_volume_glance_metadata_copy_to_volume(self): vol1 = db.volume_create(self.ctxt, {}) vol2 = db.volume_create(self.ctxt, {}) db.volume_glance_metadata_create(self.ctxt, vol1['id'], 'm1', 'v1') snapshot = objects.Snapshot(self.ctxt, volume_id=vol1['id']) snapshot.create() db.volume_glance_metadata_copy_to_snapshot(self.ctxt, snapshot.id, vol1['id']) db.volume_glance_metadata_copy_to_volume(self.ctxt, vol2['id'], snapshot.id) metadata = db.volume_glance_metadata_get(self.ctxt, vol2['id']) metadata = {m['key']: m['value'] for m in metadata} self.assertEqual({'m1': 'v1'}, metadata)
def test_create_snapshot_from_bootable_volume_fail(self, mock_qemu_info): """Test create snapshot from bootable volume. But it fails to volume_glance_metadata_copy_to_snapshot. As a result, status of snapshot is changed to ERROR. """ # create bootable volume from image volume = self._create_volume_from_image() volume_id = volume['id'] self.assertEqual('available', volume['status']) self.assertTrue(volume['bootable']) image_info = imageutils.QemuImgInfo() image_info.virtual_size = '1073741824' mock_qemu_info.return_value = image_info # get volume's volume_glance_metadata ctxt = context.get_admin_context() vol_glance_meta = db.volume_glance_metadata_get(ctxt, volume_id) self.assertTrue(vol_glance_meta) snap = create_snapshot(volume_id) snap_stat = snap.status self.assertTrue(snap.id) self.assertTrue(snap_stat) # set to return DB exception with mock.patch.object(db, 'volume_glance_metadata_copy_to_snapshot')\ as mock_db: mock_db.side_effect = exception.MetadataCopyFailure( reason="Because of DB service down.") # create snapshot from bootable volume self.assertRaises(exception.MetadataCopyFailure, self.volume.create_snapshot, ctxt, snap) # get snapshot's volume_glance_metadata self.assertRaises(exception.GlanceMetadataNotFound, db.volume_snapshot_glance_metadata_get, ctxt, snap.id) # ensure that status of snapshot is 'error' self.assertEqual(fields.SnapshotStatus.ERROR, snap.status) # cleanup resource snap.destroy() db.volume_destroy(ctxt, volume_id)
def test_vol_glance_metadata_copy_from_volume_to_volume(self): ctxt = context.get_admin_context() db.volume_create(ctxt, {'id': fake.VOLUME_ID}) db.volume_create(ctxt, { 'id': fake.VOLUME2_ID, 'source_volid': fake.VOLUME_ID }) db.volume_glance_metadata_create(ctxt, fake.VOLUME_ID, 'key1', 'value1') db.volume_glance_metadata_copy_from_volume_to_volume( ctxt, fake.VOLUME_ID, fake.VOLUME2_ID) expected_meta = {'key': 'key1', 'value': 'value1'} for meta in db.volume_glance_metadata_get(ctxt, fake.VOLUME2_ID): for (key, value) in expected_meta.items(): self.assertEqual(value, meta[key])
def _usage_from_volume(context, volume_ref, **kw): now = timeutils.utcnow() launched_at = volume_ref['launched_at'] or now created_at = volume_ref['created_at'] or now volume_status = volume_ref['status'] if volume_status == 'error_managing_deleting': volume_status = 'deleting' usage_info = dict( tenant_id=volume_ref['project_id'], host=volume_ref['host'], user_id=volume_ref['user_id'], availability_zone=volume_ref['availability_zone'], volume_id=volume_ref['id'], volume_type=volume_ref['volume_type_id'], display_name=volume_ref['display_name'], launched_at=launched_at.isoformat(), created_at=created_at.isoformat(), status=volume_status, snapshot_id=volume_ref['snapshot_id'], size=volume_ref['size'], replication_status=volume_ref['replication_status'], replication_extended_status=volume_ref['replication_extended_status'], replication_driver_data=volume_ref['replication_driver_data'], metadata=volume_ref.get('volume_metadata'), ) usage_info.update(kw) try: attachments = db.volume_attachment_get_all_by_volume_id( context, volume_ref['id']) usage_info['volume_attachment'] = attachments glance_meta = db.volume_glance_metadata_get(context, volume_ref['id']) if glance_meta: usage_info['glance_metadata'] = glance_meta except exception.GlanceMetadataNotFound: pass except exception.VolumeNotFound: LOG.debug("Can not find volume %s at notify usage", volume_ref['id']) return usage_info
def test_create_snapshot_from_bootable_volume(self, mock_qemu_info): """Test create snapshot from bootable volume.""" # create bootable volume from image volume = self._create_volume_from_image() volume_id = volume['id'] self.assertEqual('available', volume['status']) self.assertTrue(volume['bootable']) image_info = imageutils.QemuImgInfo() image_info.virtual_size = '1073741824' mock_qemu_info.return_value = image_info # get volume's volume_glance_metadata ctxt = context.get_admin_context() vol_glance_meta = db.volume_glance_metadata_get(ctxt, volume_id) self.assertTrue(bool(vol_glance_meta)) # create snapshot from bootable volume snap = create_snapshot(volume_id) self.volume.create_snapshot(ctxt, snap) # get snapshot's volume_glance_metadata snap_glance_meta = db.volume_snapshot_glance_metadata_get( ctxt, snap.id) self.assertTrue(bool(snap_glance_meta)) # ensure that volume's glance metadata is copied # to snapshot's glance metadata self.assertEqual(len(vol_glance_meta), len(snap_glance_meta)) vol_glance_dict = {x.key: x.value for x in vol_glance_meta} snap_glance_dict = {x.key: x.value for x in snap_glance_meta} self.assertDictEqual(vol_glance_dict, snap_glance_dict) # ensure that snapshot's status is changed to 'available' self.assertEqual(fields.SnapshotStatus.AVAILABLE, snap.status) # cleanup resource snap.destroy() db.volume_destroy(ctxt, volume_id)