Skip to content

Commit

Permalink
Add availability zone checking in the api service
Browse files Browse the repository at this point in the history
This patch adds availability zone checking for api request period.
If the availability zone the request specified isn't exist in the
Cinder services, the response returned to the user will give an
error immediately.

Fixes bug: 1185714

Change-Id: I842eec7b500c3ff6a7e5d8fc5e397d61617b0eea
  • Loading branch information
Haomai Wang committed Jun 11, 2013
1 parent aa7fde5 commit 1f994f2
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 1 deletion.
4 changes: 4 additions & 0 deletions cinder/tests/api/v1/stubs.py
Expand Up @@ -129,3 +129,7 @@ def stub_snapshot_get_all_by_project(self, context):

def stub_snapshot_update(self, context, *args, **param):
pass


def stub_service_get_all_by_topic(context, topic):
return [{'availability_zone': "zone1:host1"}]
3 changes: 3 additions & 0 deletions cinder/tests/api/v1/test_volume_metadata.py
Expand Up @@ -28,6 +28,7 @@
from cinder.openstack.common import jsonutils
from cinder import test
from cinder.tests.api import fakes
from cinder.tests.api.v1 import stubs


CONF = cfg.CONF
Expand Down Expand Up @@ -95,6 +96,8 @@ def setUp(self):
self.stubs.Set(cinder.db, 'volume_get', return_volume)
self.stubs.Set(cinder.db, 'volume_metadata_get',
return_volume_metadata)
self.stubs.Set(cinder.db, 'service_get_all_by_topic',
stubs.stub_service_get_all_by_topic)

self.stubs.Set(self.volume_api, 'update_volume_metadata',
fake_update_volume_metadata)
Expand Down
13 changes: 13 additions & 0 deletions cinder/tests/api/v1/test_volumes.py
Expand Up @@ -61,6 +61,8 @@ def setUp(self):
self.stubs.Set(db, 'volume_get_all', stubs.stub_volume_get_all)
self.stubs.Set(db, 'volume_get_all_by_project',
stubs.stub_volume_get_all_by_project)
self.stubs.Set(db, 'service_get_all_by_topic',
stubs.stub_service_get_all_by_topic)
self.stubs.Set(volume_api.API, 'get', stubs.stub_volume_get)
self.stubs.Set(volume_api.API, 'delete', stubs.stub_volume_delete)

Expand Down Expand Up @@ -123,6 +125,17 @@ def test_volume_creation_fails_with_bad_size(self):
req,
body)

def test_volume_creation_fails_with_bad_availability_zone(self):
vol = {"size": '1',
"name": "Volume Test Name",
"description": "Volume Test Desc",
"availability_zone": "zonen:hostn"}
body = {"volume": vol}
req = fakes.HTTPRequest.blank('/v2/volumes')
self.assertRaises(exception.InvalidInput,
self.controller.create,
req, body)

def test_volume_create_with_image_id(self):
self.stubs.Set(volume_api.API, "create", stubs.stub_volume_create)
self.ext_mgr.extensions = {'os-image-create': 'fake'}
Expand Down
4 changes: 4 additions & 0 deletions cinder/tests/api/v2/stubs.py
Expand Up @@ -131,3 +131,7 @@ def stub_snapshot_get_all_by_project(self, context):

def stub_snapshot_update(self, context, *args, **param):
pass


def stub_service_get_all_by_topic(context, topic):
return [{'availability_zone': "zone1:host1"}]
13 changes: 13 additions & 0 deletions cinder/tests/api/v2/test_volumes.py
Expand Up @@ -65,6 +65,8 @@ def setUp(self):
stubs.stub_volume_get_all_by_project)
self.stubs.Set(volume_api.API, 'get', stubs.stub_volume_get)
self.stubs.Set(volume_api.API, 'delete', stubs.stub_volume_delete)
self.stubs.Set(db, 'service_get_all_by_topic',
stubs.stub_service_get_all_by_topic)
self.maxDiff = None

def test_volume_create(self):
Expand Down Expand Up @@ -137,6 +139,17 @@ def test_volume_creation_fails_with_bad_size(self):
req,
body)

def test_volume_creation_fails_with_bad_availability_zone(self):
vol = {"size": '1',
"name": "Volume Test Name",
"description": "Volume Test Desc",
"availability_zone": "zonen:hostn"}
body = {"volume": vol}
req = fakes.HTTPRequest.blank('/v2/volumes')
self.assertRaises(exception.InvalidInput,
self.controller.create,
req, body)

def test_volume_create_with_image_id(self):
self.stubs.Set(volume_api.API, "create", stubs.stub_volume_create)
self.ext_mgr.extensions = {'os-image-create': 'fake'}
Expand Down
2 changes: 1 addition & 1 deletion cinder/tests/integrated/test_volumes.py
Expand Up @@ -163,7 +163,7 @@ def test_create_volume_in_availability_zone(self):
"""Creates a volume in availability_zone."""

# Create volume
availability_zone = 'zone1:host1'
availability_zone = 'nova'
created_volume = self.api.post_volume(
{'volume': {'size': 1,
'availability_zone': availability_zone}})
Expand Down
23 changes: 23 additions & 0 deletions cinder/volume/api.py
Expand Up @@ -24,6 +24,7 @@

from oslo.config import cfg

from cinder import context
from cinder.db import base
from cinder import exception
from cinder import flags
Expand Down Expand Up @@ -83,6 +84,7 @@ def __init__(self, db_driver=None, image_service=None):
glance.get_default_image_service())
self.scheduler_rpcapi = scheduler_rpcapi.SchedulerAPI()
self.volume_rpcapi = volume_rpcapi.VolumeAPI()
self.availability_zones = set()
super(API, self).__init__(db_driver)

def create(self, context, size, name, description, snapshot=None,
Expand Down Expand Up @@ -184,6 +186,8 @@ def _consumed(name):

if availability_zone is None:
availability_zone = FLAGS.storage_availability_zone
else:
self._check_availabilty_zone(availability_zone)

if not volume_type and not source_volume:
volume_type = volume_types.get_default_volume_type()
Expand Down Expand Up @@ -291,6 +295,25 @@ def _cast_create_volume(self, context, request_spec, filter_properties):
request_spec=request_spec,
filter_properties=filter_properties)

def _check_availabilty_zone(self, availability_zone):
if availability_zone in self.availability_zones:
return

ctxt = context.get_admin_context()
topic = FLAGS.volume_topic
volume_services = self.db.service_get_all_by_topic(ctxt, topic)

# NOTE(haomai): In case of volume services isn't init or
# availability_zones is updated in the backend
self.availability_zones = set()
for service in volume_services:
self.availability_zones.add(service['availability_zone'])

if availability_zone not in self.availability_zones:
msg = _("Availability zone is invalid")
LOG.warn(msg)
raise exception.InvalidInput(reason=msg)

@wrap_check_policy
def delete(self, context, volume, force=False):
if context.is_admin and context.project_id != volume['project_id']:
Expand Down

0 comments on commit 1f994f2

Please sign in to comment.