diff --git a/graffiti/api/controllers/v1/capability_type.py b/graffiti/api/controllers/v1/capability_type.py index 60bce62..5b3c7b3 100644 --- a/graffiti/api/controllers/v1/capability_type.py +++ b/graffiti/api/controllers/v1/capability_type.py @@ -18,6 +18,8 @@ from pecan.rest import RestController from wsme.api import Response from wsmeext.pecan import wsexpose +from graffiti.api.controllers.v1.capability_type_derived import\ + CapabilityTypeDerivedController from graffiti.api.model.v1.capability_type import CapabilityType from graffiti.api.model.v1.dao.captype_dao_factory \ import CapabilityTypeDAOFactory @@ -29,6 +31,9 @@ import six class CapabilityTypeController(RestController): + + derived_properties = CapabilityTypeDerivedController() + def __init__(self): super(RestController, self).__init__() self.status = 200 diff --git a/graffiti/api/controllers/v1/capability_type_derived.py b/graffiti/api/controllers/v1/capability_type_derived.py new file mode 100644 index 0000000..4a7858e --- /dev/null +++ b/graffiti/api/controllers/v1/capability_type_derived.py @@ -0,0 +1,50 @@ +# Copyright (c) 2014 Hewlett-Packard Development Company, L.P. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from pecan.rest import RestController + +from wsmeext.pecan import wsexpose + +from graffiti.api.model.v1.capability_type_derived_prop import \ + CapabilityTypeDerivedProperties +from graffiti.api.model.v1.dao.captype_dao_factory \ + import CapabilityTypeDAOFactory +from oslo.config import cfg + + +import six + + +class CapabilityTypeDerivedController(RestController): + + def __init__(self): + super(RestController, self).__init__() + self.status = 200 + self._cap_controller = None + self._load_controller() + + def _load_controller(self): + dao_type = cfg.CONF.DEFAULT.persistence_type + self._cap_controller = CapabilityTypeDAOFactory.create(dao_type) + + @wsexpose + def options(): + pass + + @wsexpose(CapabilityTypeDerivedProperties, six.text_type, six.text_type) + def get_one(self, name, namespace): + captype = self._cap_controller.\ + get_capability_type_with_derived_properties(name, namespace) + return captype diff --git a/graffiti/api/model/v1/capability_type_derived_prop.py b/graffiti/api/model/v1/capability_type_derived_prop.py new file mode 100644 index 0000000..972b649 --- /dev/null +++ b/graffiti/api/model/v1/capability_type_derived_prop.py @@ -0,0 +1,36 @@ +# Copyright (c) 2014 Hewlett-Packard Development Company, L.P. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import wsme +from wsme import types + +from graffiti.api.model.v1.derived_property_type import DerivedPropertyType +from graffiti.api.model.v1.derived_type import DerivedType +from graffiti.api.model.v1.property_type import PropertyType +from graffiti.common.db_utils import DbTransformer + + +class CapabilityTypeDerivedProperties(types.Base, DbTransformer): + + name = wsme.wsattr(types.text, mandatory=True) + namespace = wsme.wsattr(types.text, mandatory=True) + description = wsme.wsattr(types.text, mandatory=False) + properties = wsme.wsattr({types.text: PropertyType}, mandatory=False) + derived_properties = wsme.wsattr({types.text: DerivedPropertyType}, + mandatory=False) + derived_from = wsme.wsattr(DerivedType, mandatory=False) + + def __init__(self, **kwargs): + super(CapabilityTypeDerivedProperties, self).__init__(**kwargs) diff --git a/graffiti/api/model/v1/dao/captype_dao.py b/graffiti/api/model/v1/dao/captype_dao.py index 98bf37f..5dc7c17 100644 --- a/graffiti/api/model/v1/dao/captype_dao.py +++ b/graffiti/api/model/v1/dao/captype_dao.py @@ -26,6 +26,9 @@ class CapabilityTypeDAOBase(object): def get_capability_type(self, name, namespace): return None + def get_capability_type_with_derived_properties(self, name, namespace): + return None + def find_capability_types(self, query_string): return [] diff --git a/graffiti/api/model/v1/dao/captype_db_dao.py b/graffiti/api/model/v1/dao/captype_db_dao.py index b3f62ae..91fb74e 100644 --- a/graffiti/api/model/v1/dao/captype_db_dao.py +++ b/graffiti/api/model/v1/dao/captype_db_dao.py @@ -14,9 +14,13 @@ # limitations under the License. from graffiti.api.model.v1.capability_type import CapabilityType +from graffiti.api.model.v1.capability_type_derived_prop import \ + CapabilityTypeDerivedProperties from graffiti.api.model.v1.dao.captype_dao import CapabilityTypeDAOBase +from graffiti.api.model.v1.derived_property_type import DerivedPropertyType from graffiti.api.model.v1.derived_type import DerivedType from graffiti.api.model.v1.property_type import PropertyType + from graffiti.db import api as dbapi import json from wsme.rest.json import fromjson @@ -49,6 +53,40 @@ class DBCapabilityTypeDAO(CapabilityTypeDAOBase): return model_captype + def _to_model_derived(self, db_captype, derived_props): + model_captype = CapabilityTypeDerivedProperties.to_model(db_captype) + + if db_captype.parent_name == 'null': + model_captype.derived_from = None + else: + model_captype.derived_from = DerivedType( + name=db_captype.parent_name, + namespace=db_captype.parent_namespace) + + property_types = {} + db_properties = json.loads(db_captype.properties_text) + for id in db_properties: + property_types[id] = fromjson(PropertyType, db_properties[id]) + model_captype.properties = property_types + + if derived_props: + derived_property_types = {} + for key in derived_props: + props = derived_props[key] + db_properties = json.loads(props) + for id in db_properties: + derived_props_model = fromjson( + DerivedPropertyType, + db_properties[id]) + derived_props_model.derived_from_capability_namespace =\ + key.namespace + derived_props_model.derived_from_capability_name = key.name + derived_property_types[id] = derived_props_model + + model_captype.derived_properties = derived_property_types + + return model_captype + def _to_dict(self, model_captype): captype_dict = model_captype.to_dict() @@ -77,6 +115,23 @@ class DBCapabilityTypeDAO(CapabilityTypeDAOBase): return self._to_model(db_capability_type) + def get_capability_type_with_derived_properties(self, name, namespace): + cap_type_prop_dict = dbapi.capability_type_get_with_derived_properties( + name, + namespace) + db_capability_type = cap_type_prop_dict['cap_type'] + + derived_props = None + if 'derived_properties' in cap_type_prop_dict.keys(): + derived_props = cap_type_prop_dict['derived_properties'] + + if not db_capability_type: + res = CapabilityType(CapabilityType(), status_code=404, + error="CapabilityType Not Found") + return res + + return self._to_model_derived(db_capability_type, derived_props) + def find_capability_types(self, query_string): # TODO(wko): add support for query_string db_capability_types = dbapi.capability_type_get_all() diff --git a/graffiti/api/model/v1/derived_property_type.py b/graffiti/api/model/v1/derived_property_type.py new file mode 100644 index 0000000..9acc071 --- /dev/null +++ b/graffiti/api/model/v1/derived_property_type.py @@ -0,0 +1,37 @@ +# Copyright (c) 2014 Hewlett-Packard Development Company, L.P. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from graffiti.api.model.v1.property_type import PropertyType +import wsme +from wsme import types + + +class DerivedPropertyType(PropertyType): + '''mandatory is set to False instead of True, since wsme will complain + while deserializing the properties to model. derived properties are + dynamically added after the model is deserialized from persistence + ''' + derived_from_capability_namespace = wsme.wsattr( + types.text, mandatory=False) + derived_from_capability_name = wsme.wsattr(types.text, mandatory=False) + + _wsme_attr_order = ('type', 'description', 'default', 'required', + 'minimum', 'maximum', 'minLength', 'maxLength', + 'pattern', 'confidential', 'items', 'uniqueItems', + 'additionalItems', 'derived_from_capability_name', + 'derived_from_capability_namespace') + + def __init__(self, **kwargs): + super(DerivedPropertyType, self).__init__(**kwargs) diff --git a/graffiti/db/api.py b/graffiti/db/api.py index f8a3515..487839c 100644 --- a/graffiti/db/api.py +++ b/graffiti/db/api.py @@ -16,6 +16,7 @@ # import copy from oslo.config import cfg +from graffiti.api.model.v1.derived_type import DerivedType from graffiti.common import exception as exc from graffiti.db import models from graffiti.openstack.common.db import exception as db_exc @@ -192,6 +193,41 @@ def capability_type_get(name, namespace): return query.filter_by(name=name, namespace=namespace).first() +def capability_type_get_with_derived_properties(name, namespace): + cap_type_prop_dict = dict() + db_capability_type = capability_type_get(name, namespace) + if db_capability_type.parent_name and db_capability_type.parent_namespace: + property_dict = dict() + property_dict = __get_derived_properties( + db_capability_type.parent_name, + db_capability_type.parent_namespace, + property_dict + ) + cap_type_prop_dict['derived_properties'] = property_dict + + cap_type_prop_dict['cap_type'] = db_capability_type + return cap_type_prop_dict + + +def __get_derived_properties(name, namespace, property_dict): + db_capability_type = capability_type_get(name, namespace) + properties_text = db_capability_type.properties_text + if properties_text: + derived_type = DerivedType() + derived_type.name = name + derived_type.namespace = namespace + property_dict[derived_type] = properties_text + + if db_capability_type.parent_name and db_capability_type.parent_namespace: + __get_derived_properties( + db_capability_type.parent_name, + db_capability_type.parent_namespace, + property_dict + ) + + return property_dict + + def capability_type_get_all(): return _entity_get_all(models.CapabilityType)