Merge "Add a verification about the protect property of plan's parameter"

This commit is contained in:
Jenkins 2017-05-24 13:05:29 +00:00 committed by Gerrit Code Review
commit c24b80e8ce
5 changed files with 88 additions and 10 deletions

View File

@ -30,6 +30,7 @@ from karbor import objects
from karbor.objects import base as objects_base
import karbor.policy
from karbor.services.operationengine import api as operationengine_api
from karbor.services.protection import api as protection_api
from karbor import utils
import six
@ -136,6 +137,7 @@ class PlansController(wsgi.Controller):
def __init__(self):
self.operationengine_api = operationengine_api.API()
self.protection_api = protection_api.API()
super(PlansController, self).__init__()
def show(self, req, id):
@ -273,6 +275,7 @@ class PlansController(wsgi.Controller):
self.validate_name_and_description(plan)
self.validate_plan_resources(plan)
self.validate_plan_parameters(context, plan)
resources = plan.get('resources', None)
if resources:
@ -401,6 +404,38 @@ class PlansController(wsgi.Controller):
"a plan.")
raise exception.InvalidInput(reason=msg)
def validate_plan_parameters(self, context, plan):
parameters = plan["parameters"]
if not parameters:
return
try:
provider = self.protection_api.show_provider(
context, plan["provider_id"])
except exception:
msg = _("The provider could not be found.")
raise exc.HTTPBadRequest(explanation=msg)
options_schema = provider.get(
"extended_info_schema", {}).get("options_schema", None)
if options_schema is None:
msg = _("The option_schema of plugin must be provided.")
raise exc.HTTPBadRequest(explanation=msg)
for resource_key, parameter_value in parameters.items():
if "#" in resource_key:
resource_type, resource_id = resource_key.split("#")
if not uuidutils.is_uuid_like(resource_id):
msg = _("The resource_id must be a uuid.")
raise exc.HTTPBadRequest(explanation=msg)
else:
resource_type = resource_key
if resource_type not in constants.RESOURCE_TYPES:
msg = _("The key of plan parameters is invalid.")
raise exc.HTTPBadRequest(explanation=msg)
properties = options_schema[resource_type]["properties"]
if not set(properties.keys()) > set(parameter_value.keys()):
msg = _("The protect property of plan parameters "
"is invalid.")
raise exc.HTTPBadRequest(explanation=msg)
def create_resource():
return wsgi.Resource(PlansController())

View File

@ -29,7 +29,7 @@ class CheckpointsTest(karbor_base.KarborBaseTest):
backup_name = "volume-backup-{id}".format(id=volume.id)
parameters = {
"OS::Cinder::Volume": {
"incremental": "full",
"backup_mode": "full",
"force": False
},
volume_parameter_key: {

View File

@ -23,10 +23,28 @@ import webob.request
from karbor.api.openstack import wsgi as os_wsgi
from karbor import context
from karbor.services.protection.protection_plugins.volume \
import volume_plugin_cinder_schemas as cinder_schemas
FAKE_UUID = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
FAKE_UUIDS = {}
PROVIDER_OS = {
"description": "This provider uses OpenStack's own services "
"(swift, cinder) as storage",
"extended_info_schema": {
"options_schema": {
"OS::Cinder::Volume": cinder_schemas.OPTIONS_SCHEMA
},
"saved_info_schema": {
"OS::Cinder::Volume": cinder_schemas.SAVED_INFO_SCHEMA
},
"restore_schema": {
"OS::Cinder::Volume": cinder_schemas.RESTORE_SCHEMA
}
},
"id": "cf56bd3e-97a7-4078-b6d5-f36246333fd9",
"name": "OS Infra Provider"
}
class Context(object):

View File

@ -28,9 +28,9 @@ DEFAULT_NAME = 'My 3 tier application'
DEFAULT_DESCRIPTION = 'My 3 tier application protection plan'
DEFAULT_PROVIDER_ID = 'efc6a88b-9096-4bb6-8634-cda182a6e12a'
DEFAULT_PROJECT_ID = '39bb894794b741e982bd26144d2949f6'
DEFAULT_RESOURCES = [{'id': 'key1',
"type": "value1", "name": "name1"}]
DEFAULT_PARAMETERS = {"OS::Nova::Server": {"consistency": "os"}}
DEFAULT_RESOURCES = [{'id': 'efc6a88b-9096-4bb6-8634-cda182a6e144',
"type": "OS::Cinder::Volume", "name": "name1"}]
DEFAULT_PARAMETERS = {"OS::Cinder::Volume": {"backup_name": "name"}}
class PlanApiTest(base.TestCase):
@ -39,12 +39,15 @@ class PlanApiTest(base.TestCase):
self.controller = plans.PlansController()
self.ctxt = context.RequestContext('demo', 'fakeproject', True)
@mock.patch(
'karbor.services.protection.rpcapi.ProtectionAPI.show_provider')
@mock.patch(
'karbor.objects.plan.Plan.create')
def test_plan_create(self, mock_plan_create):
def test_plan_create(self, mock_plan_create, mock_provider):
plan = self._plan_in_request_body()
body = {"plan": plan}
req = fakes.HTTPRequest.blank('/v1/plans')
mock_provider.return_value = fakes.PROVIDER_OS
self.controller.create(req, body)
self.assertTrue(mock_plan_create.called)
@ -81,6 +84,23 @@ class PlanApiTest(base.TestCase):
self.assertRaises(exception.InvalidInput, self.controller.create,
req, body)
@mock.patch(
'karbor.services.protection.rpcapi.ProtectionAPI.show_provider')
def test_plan_create_InvalidParameters(self, mock_provider):
parameters = {"OS::Cinder::Volume": {"test": "os"}}
plan = self._plan_in_request_body(
name=DEFAULT_NAME,
description=DEFAULT_DESCRIPTION,
provider_id=DEFAULT_PROVIDER_ID,
status=constants.PLAN_STATUS_SUSPENDED,
project_id=DEFAULT_PROJECT_ID,
parameters=parameters)
body = {"plan": plan}
mock_provider.return_value = fakes.PROVIDER_OS
req = fakes.HTTPRequest.blank('/v1/plans')
self.assertRaises(exc.HTTPBadRequest, self.controller.create,
req, body)
@mock.patch(
'karbor.api.v1.plans.PlansController._plan_get')
@mock.patch(

View File

@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import mock
from oslo_utils import uuidutils
from webob import exc
@ -186,18 +187,22 @@ class ScheduledOperationApiTest(base.TestCase):
req = fakes.HTTPRequest.blank('/v1/triggers')
return controller.create(req, create_trigger_param)
def _create_plan(self, provider_id):
@mock.patch(
'karbor.services.protection.rpcapi.ProtectionAPI.show_provider')
def _create_plan(self, provider_id, mock_provider):
create_plan_param = {
'plan': {
'name': '123',
'provider_id': provider_id,
'resources': [
{'id': '123', 'type': '123', 'name': '123'}
{'id': '39bb894794b741e982bd26144d2949f6',
'type': 'OS::Cinder::Volume', 'name': '123'}
],
'parameters': {"OS::Nova::Server": {"consistency": "os"}},
'parameters': {"OS::Cinder::Volume": {"backup_name": "test"}},
}
}
controller = plan_api.PlansController()
req = fakes.HTTPRequest.blank('/v1/triggers')
mock_provider.return_value = fakes.PROVIDER_OS
req = fakes.HTTPRequest.blank('/v1/plans')
plan = controller.create(req, create_plan_param)
return plan['plan']