return {'snapshot': retval}
+ @wsgi.serializers(xml=SnapshotTemplate)
+ def update(self, req, id, body):
+ """Update a snapshot."""
+ context = req.environ['cinder.context']
+
+ if not body:
+ raise exc.HTTPUnprocessableEntity()
+
+ if not 'snapshot' in body:
+ raise exc.HTTPUnprocessableEntity()
+
+ snapshot = body['snapshot']
+ update_dict = {}
+
+ valid_update_keys = (
+ 'display_name',
+ 'display_description',
+ )
+
+ for key in valid_update_keys:
+ if key in snapshot:
+ update_dict[key] = snapshot[key]
+
+ try:
+ snapshot = self.volume_api.get_snapshot(context, id)
+ self.volume_api.update_snapshot(context, snapshot, update_dict)
+ except exception.NotFound:
+ raise exc.HTTPNotFound()
+
+ snapshot.update(update_dict)
+
+ return {'snapshot': _translate_snapshot_detail_view(context, snapshot)}
+
def create_resource(ext_mgr):
return wsgi.Resource(SnapshotsController(ext_mgr))
"""Return volume search options allowed by non-admin."""
return ('display_name', 'status')
+ @wsgi.serializers(xml=VolumeTemplate)
+ def update(self, req, id, body):
+ """Update a volume."""
+ context = req.environ['cinder.context']
+
+ if not body:
+ raise exc.HTTPUnprocessableEntity()
+
+ if not 'volume' in body:
+ raise exc.HTTPUnprocessableEntity()
+
+ volume = body['volume']
+ update_dict = {}
+
+ valid_update_keys = (
+ 'display_name',
+ 'display_description',
+ )
+
+ for key in valid_update_keys:
+ if key in volume:
+ update_dict[key] = volume[key]
+
+ try:
+ volume = self.volume_api.get(context, id)
+ self.volume_api.update(context, volume, update_dict)
+ except exception.NotFound:
+ raise exc.HTTPNotFound()
+
+ volume.update(update_dict)
+
+ return {'volume': _translate_volume_detail_view(context, volume)}
+
def create_resource(ext_mgr):
return wsgi.Resource(VolumeController(ext_mgr))
def stub_snapshot_get_all_by_project(self, context):
return [stub_snapshot(1)]
+
+
+def stub_snapshot_update(self, context, *args, **param):
+ pass
self.assertEqual(resp_dict['snapshot']['display_description'],
snapshot['display_description'])
+ def test_snapshot_update(self):
+ self.stubs.Set(volume.api.API, "get_snapshot", stub_snapshot_get)
+ self.stubs.Set(volume.api.API, "update_snapshot",
+ fakes.stub_snapshot_update)
+ updates = {
+ "display_name": "Updated Test Name",
+ }
+ body = {"snapshot": updates}
+ req = fakes.HTTPRequest.blank('/v1/snapshots/%s' % UUID)
+ res_dict = self.controller.update(req, UUID, body)
+ expected = {'snapshot': {
+ 'id': UUID,
+ 'volume_id': 12,
+ 'status': 'available',
+ 'size': 100,
+ 'created_at': None,
+ 'display_name': 'Updated Test Name',
+ 'display_description': 'Default description',
+ }}
+ self.assertEquals(expected, res_dict)
+
+ def test_snapshot_update_missing_body(self):
+ body = {}
+ req = fakes.HTTPRequest.blank('/v1/snapshots/%s' % UUID)
+ self.assertRaises(webob.exc.HTTPUnprocessableEntity,
+ self.controller.update, req, UUID, body)
+
+ def test_snapshot_update_invalid_body(self):
+ body = {'display_name': 'missing top level snapshot key'}
+ req = fakes.HTTPRequest.blank('/v1/snapshots/%s' % UUID)
+ self.assertRaises(webob.exc.HTTPUnprocessableEntity,
+ self.controller.update, req, UUID, body)
+
+ def test_snapshot_update_not_found(self):
+ self.stubs.Set(volume.api.API, "get_snapshot", stub_snapshot_get)
+ updates = {
+ "display_name": "Updated Test Name",
+ }
+ body = {"snapshot": updates}
+ req = fakes.HTTPRequest.blank('/v1/snapshots/not-the-uuid')
+ self.assertRaises(webob.exc.HTTPNotFound, self.controller.update, req,
+ 'not-the-uuid', body)
+
def test_snapshot_delete(self):
self.stubs.Set(volume.api.API, "get_snapshot", stub_snapshot_get)
self.stubs.Set(volume.api.API, "delete_snapshot", stub_snapshot_delete)
req,
body)
+ def test_volume_update(self):
+ self.stubs.Set(volume_api.API, "update", fakes.stub_volume_update)
+ updates = {
+ "display_name": "Updated Test Name",
+ }
+ body = {"volume": updates}
+ req = fakes.HTTPRequest.blank('/v1/volumes/1')
+ res_dict = self.controller.update(req, '1', body)
+ expected = {'volume': {
+ 'status': 'fakestatus',
+ 'display_description': 'displaydesc',
+ 'availability_zone': 'fakeaz',
+ 'display_name': 'Updated Test Name',
+ 'attachments': [{
+ 'id': '1',
+ 'volume_id': '1',
+ 'server_id': 'fakeuuid',
+ 'device': '/',
+ }],
+ 'volume_type': 'vol_type_name',
+ 'snapshot_id': None,
+ 'metadata': {},
+ 'id': '1',
+ 'created_at': datetime.datetime(1, 1, 1, 1, 1, 1),
+ 'size': 1,
+ }}
+ self.assertEquals(res_dict, expected)
+
+ def test_update_empty_body(self):
+ body = {}
+ req = fakes.HTTPRequest.blank('/v1/volumes/1')
+ self.assertRaises(webob.exc.HTTPUnprocessableEntity,
+ self.controller.update,
+ req, '1', body)
+
+ def test_update_invalid_body(self):
+ body = {'display_name': 'missing top level volume key'}
+ req = fakes.HTTPRequest.blank('/v1/volumes/1')
+ self.assertRaises(webob.exc.HTTPUnprocessableEntity,
+ self.controller.update,
+ req, '1', body)
+
+ def test_update_not_found(self):
+ self.stubs.Set(volume_api.API, "get", fakes.stub_volume_get_notfound)
+ updates = {
+ "display_name": "Updated Test Name",
+ }
+ body = {"volume": updates}
+ req = fakes.HTTPRequest.blank('/v1/volumes/1')
+ self.assertRaises(webob.exc.HTTPNotFound,
+ self.controller.update,
+ req, '1', body)
+
def test_volume_list(self):
self.stubs.Set(volume_api.API, 'get_all',
fakes.stub_volume_get_all_by_project)
def delete_volume(self, volume_id):
return self.api_delete('/volumes/%s' % volume_id)
+
+ def put_volume(self, volume_id, volume):
+ return self.api_put('/volumes/%s' % volume_id, volume)['volume']
self.assertEqual(created_volume_id, found_volume['id'])
self.assertEqual(availability_zone, found_volume['availability_zone'])
+ def test_create_and_update_volume(self):
+ # Create vol1
+ created_volume = self.api.post_volume({'volume': {
+ 'size': 1, 'display_name': 'vol1'}})
+ self.assertEqual(created_volume['display_name'], 'vol1')
+ created_volume_id = created_volume['id']
+
+ # update volume
+ body = {'volume': {'display_name': 'vol-one'}}
+ updated_volume = self.api.put_volume(created_volume_id, body)
+ self.assertEqual(updated_volume['display_name'], 'vol-one')
+
+ # check for update
+ found_volume = self.api.get_volume(created_volume_id)
+ self.assertEqual(created_volume_id, found_volume['id'])
+ self.assertEqual(found_volume['display_name'], 'vol-one')
+
if __name__ == "__main__":
unittest.main()
"volume:delete_snapshot": [],
"volume:get_snapshot": [],
"volume:get_all_snapshots": [],
+ "volume:update_snapshot": [],
"volume_extension:volume_admin_actions:reset_status": [["rule:admin_api"]],
"volume_extension:snapshot_admin_actions:reset_status": [["rule:admin_api"]],
"""Test volume can be created from a snapshot."""
volume_src = self._create_volume()
self.volume.create_volume(self.context, volume_src['id'])
- snapshot_id = self._create_snapshot(volume_src['id'])
+ snapshot_id = self._create_snapshot(volume_src['id'])['id']
self.volume.create_snapshot(self.context, volume_src['id'],
snapshot_id)
volume_dst = self._create_volume(0, snapshot_id)
snap['project_id'] = 'fake'
snap['volume_id'] = volume_id
snap['status'] = "creating"
- return db.snapshot_create(context.get_admin_context(), snap)['id']
+ return db.snapshot_create(context.get_admin_context(), snap)
def test_create_delete_snapshot(self):
"""Test snapshot can be created and deleted."""
volume = self._create_volume()
self.volume.create_volume(self.context, volume['id'])
- snapshot_id = self._create_snapshot(volume['id'])
+ snapshot_id = self._create_snapshot(volume['id'])['id']
self.volume.create_snapshot(self.context, volume['id'], snapshot_id)
self.assertEqual(snapshot_id,
db.snapshot_get(context.get_admin_context(),
"""Test volume can't be deleted with dependent snapshots."""
volume = self._create_volume()
self.volume.create_volume(self.context, volume['id'])
- snapshot_id = self._create_snapshot(volume['id'])
+ snapshot_id = self._create_snapshot(volume['id'])['id']
self.volume.create_snapshot(self.context, volume['id'], snapshot_id)
self.assertEqual(snapshot_id,
db.snapshot_get(context.get_admin_context(),
"""Test snapshot can be created and deleted."""
volume = self._create_volume()
self.volume.create_volume(self.context, volume['id'])
- snapshot_id = self._create_snapshot(volume['id'])
+ snapshot_id = self._create_snapshot(volume['id'])['id']
self.volume.create_snapshot(self.context, volume['id'], snapshot_id)
snapshot = db.snapshot_get(context.get_admin_context(),
snapshot_id)
volume = self._create_volume()
volume_id = volume['id']
self.volume.create_volume(self.context, volume_id)
- snapshot_id = self._create_snapshot(volume_id)
+ snapshot_id = self._create_snapshot(volume_id)['id']
self.volume.create_snapshot(self.context, volume_id, snapshot_id)
self.mox.StubOutWithMock(self.volume.driver, 'delete_snapshot')
volume = db.volume_get(self.context, volume['id'])
self.assertEqual(volume['status'], "in-use")
+ def test_volume_api_update(self):
+ # create a raw vol
+ volume = self._create_volume()
+ # use volume.api to update name
+ volume_api = cinder.volume.api.API()
+ update_dict = {'display_name': 'test update name'}
+ volume_api.update(self.context, volume, update_dict)
+ # read changes from db
+ vol = db.volume_get(context.get_admin_context(), volume['id'])
+ self.assertEquals(vol['display_name'], 'test update name')
+
+ def test_volume_api_update_snapshot(self):
+ # create raw snapshot
+ volume = self._create_volume()
+ snapshot = self._create_snapshot(volume['id'])
+ self.assertEquals(snapshot['display_name'], None)
+ # use volume.api to update name
+ volume_api = cinder.volume.api.API()
+ update_dict = {'display_name': 'test update name'}
+ volume_api.update_snapshot(self.context, snapshot, update_dict)
+ # read changes from db
+ snap = db.snapshot_get(context.get_admin_context(), snapshot['id'])
+ self.assertEquals(snap['display_name'], 'test update name')
+
class DriverTestCase(test.TestCase):
"""Base Test class for Drivers."""
{"method": "delete_snapshot",
"args": {"snapshot_id": snapshot['id']}})
+ @wrap_check_policy
+ def update_snapshot(self, context, snapshot, fields):
+ self.db.snapshot_update(context, snapshot['id'], fields)
+
@wrap_check_policy
def get_volume_metadata(self, context, volume):
"""Get all metadata associated with a volume."""