Merge "Add a verification about the protect property of plan's parameter"
This commit is contained in:
commit
c24b80e8ce
|
@ -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())
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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']
|
||||
|
|
Loading…
Reference in New Issue