dictionary controllers for namespace and capability_type
Change-Id: I931425d6fe6f95d0d616d5e3f6efe852b2863b53
This commit is contained in:
parent
cd9adfe81d
commit
99287f3f00
77
config.py
77
config.py
|
@ -13,6 +13,8 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
from oslo.config import cfg
|
||||||
|
|
||||||
# Server Specific Configurations
|
# Server Specific Configurations
|
||||||
server = {
|
server = {
|
||||||
'port': '21075',
|
'port': '21075',
|
||||||
|
@ -59,9 +61,84 @@ wsme = {
|
||||||
'debug': True
|
'debug': True
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# Custom Configurations must be in Python dictionary format::
|
# Custom Configurations must be in Python dictionary format::
|
||||||
#
|
#
|
||||||
# foo = {'bar':'baz'}
|
# foo = {'bar':'baz'}
|
||||||
#
|
#
|
||||||
# All configurations are accessible at::
|
# All configurations are accessible at::
|
||||||
# pecan.conf
|
# pecan.conf
|
||||||
|
|
||||||
|
# oslo config
|
||||||
|
keystone_group = cfg.OptGroup('keystone')
|
||||||
|
keystone_opts = [
|
||||||
|
cfg.StrOpt('auth_url',
|
||||||
|
default='http://192.168.40.10:5000/v2.0',
|
||||||
|
help='keystone authorization url'),
|
||||||
|
cfg.StrOpt('username',
|
||||||
|
default='admin',
|
||||||
|
help='keystone username'),
|
||||||
|
cfg.StrOpt('password',
|
||||||
|
default='secretword',
|
||||||
|
help='keystone password'),
|
||||||
|
cfg.StrOpt('tenant_name',
|
||||||
|
default='admin',
|
||||||
|
help='keystone tenant name')
|
||||||
|
|
||||||
|
]
|
||||||
|
cfg.CONF.register_group(keystone_group)
|
||||||
|
cfg.CONF.register_opts(keystone_opts, group=keystone_group)
|
||||||
|
|
||||||
|
# DEFAULT group
|
||||||
|
default_controller_group = cfg.OptGroup('DEFAULT')
|
||||||
|
default_controller_opts = [
|
||||||
|
cfg.StrOpt(
|
||||||
|
'persistence_type',
|
||||||
|
default="memory",
|
||||||
|
help=("persistence options. "
|
||||||
|
"values = 'memory' or 'file' or 'db"))
|
||||||
|
]
|
||||||
|
|
||||||
|
cfg.CONF.register_group(default_controller_group)
|
||||||
|
cfg.CONF.register_opts(default_controller_opts,
|
||||||
|
group=default_controller_group)
|
||||||
|
|
||||||
|
# FILE_PERSISTENCE group
|
||||||
|
file_controller_group = cfg.OptGroup('FILE_PERSISTENCE')
|
||||||
|
file_controller_opts = [
|
||||||
|
cfg.StrOpt(
|
||||||
|
'dictionary_folder',
|
||||||
|
default="/tmp/graffiti-dictionary/",
|
||||||
|
help=("Absolute path of the file for persisting dictionary")
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
cfg.CONF.register_group(file_controller_group)
|
||||||
|
cfg.CONF.register_opts(file_controller_opts,
|
||||||
|
group=file_controller_group)
|
||||||
|
|
||||||
|
|
||||||
|
# Used for remote debugging, like pychcharms or pydev
|
||||||
|
# To enable remote debugging in pycharms, requires that you put the
|
||||||
|
# pycharm-debug.egg in the python path. E.g.
|
||||||
|
#
|
||||||
|
# Include the pycharm-debug.egg archive.
|
||||||
|
# e.g. /home/<USERNAME>/pycharm-3.1.1/pycharm-debug.egg
|
||||||
|
# You can do it in a number of ways, for example:
|
||||||
|
# Add the archive to PYTHONPATH.e,g,
|
||||||
|
# export PYTHONPATH+=.:/home/<USERNAME>/pycharm-3.1.1/pycharm-debug.egg
|
||||||
|
# Append the archive to sys.path. e.g.
|
||||||
|
# import sys
|
||||||
|
# sys.path.append('/home/<USERNANE>/pycharm-3.1.1/pycharm-debug.egg')
|
||||||
|
# Just copy the pydev from the archive to the directory where your remote
|
||||||
|
# script resides.
|
||||||
|
#
|
||||||
|
# You will need to setup a debug configuration in your pycharms and start the
|
||||||
|
# debugger BEFORE starting pecan
|
||||||
|
# This is because the following code connects from here to your pycharms
|
||||||
|
# (or your pydev)
|
||||||
|
pydevd = {
|
||||||
|
'enabled': True,
|
||||||
|
'port': 22075,
|
||||||
|
'bindhost': 'localhost'
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
[DEFAULT]
|
||||||
|
|
||||||
|
#Allowed values= memory, file, db. Default value is memory
|
||||||
|
persistence_type=memory
|
||||||
|
|
||||||
|
[FILE_PERSISTENCE]
|
||||||
|
dictionary_folder=/tmp/graffiti-dictionary/
|
|
@ -26,6 +26,22 @@ CONF = cfg.CONF
|
||||||
|
|
||||||
def setup_app(config):
|
def setup_app(config):
|
||||||
|
|
||||||
|
if hasattr(config, 'pydevd') and config.pydevd.enabled:
|
||||||
|
try:
|
||||||
|
print(
|
||||||
|
'Remote debug set to true(config.pydevd). '
|
||||||
|
'Attempting connection'
|
||||||
|
)
|
||||||
|
import pydevd
|
||||||
|
pydevd.settrace(
|
||||||
|
config.pydevd.bindhost,
|
||||||
|
port=config.pydevd.port,
|
||||||
|
stdoutToServer=True,
|
||||||
|
stderrToServer=True,
|
||||||
|
suspend=False)
|
||||||
|
except Exception as e:
|
||||||
|
print "Debug Connection Error:", e
|
||||||
|
|
||||||
model.init_model()
|
model.init_model()
|
||||||
app_conf = dict(config.app)
|
app_conf = dict(config.app)
|
||||||
|
|
||||||
|
|
|
@ -15,42 +15,122 @@
|
||||||
|
|
||||||
from pecan.rest import RestController
|
from pecan.rest import RestController
|
||||||
|
|
||||||
|
from wsme.api import Response
|
||||||
from wsmeext.pecan import wsexpose
|
from wsmeext.pecan import wsexpose
|
||||||
|
|
||||||
|
from graffiti.api.controllers.v1.captype_controller_factory \
|
||||||
|
import CapTypeControllerFactory
|
||||||
from graffiti.api.model.v1.capability_type import CapabilityType
|
from graffiti.api.model.v1.capability_type import CapabilityType
|
||||||
|
from ns_controller_factory import NSControllerFactory
|
||||||
|
from oslo.config import cfg
|
||||||
|
|
||||||
|
|
||||||
import six
|
import six
|
||||||
|
|
||||||
capability_types = []
|
|
||||||
|
|
||||||
|
|
||||||
class CapabilityTypeController(RestController):
|
class CapabilityTypeController(RestController):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(RestController, self).__init__()
|
super(RestController, self).__init__()
|
||||||
self.status = 200
|
self.status = 200
|
||||||
|
self._cap_controller = None
|
||||||
|
self._ns_controller = None
|
||||||
|
self._load_controller()
|
||||||
|
|
||||||
|
def _load_controller(self):
|
||||||
|
controller_type = cfg.CONF.DEFAULT.persistence_type
|
||||||
|
self._cap_controller = CapTypeControllerFactory.create(controller_type)
|
||||||
|
self._ns_controller = NSControllerFactory.get()
|
||||||
|
|
||||||
@wsexpose
|
@wsexpose
|
||||||
def options():
|
def options():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@wsexpose(CapabilityType, six.text_type)
|
@wsexpose(CapabilityType, six.text_type, six.text_type)
|
||||||
def get_one(self, name):
|
def get_one(self, name, namespace):
|
||||||
global capability_types
|
captype = self._cap_controller.get_capability_type(name, namespace)
|
||||||
|
return captype
|
||||||
|
|
||||||
for capability_type in capability_types:
|
@wsexpose([CapabilityType], six.text_type)
|
||||||
if capability_type.name.lower() == name.lower():
|
def get_all(self, query_string=None):
|
||||||
return capability_type
|
captype_list = self._cap_controller.find_capability_types(query_string)
|
||||||
|
return captype_list
|
||||||
res = CapabilityType(CapabilityType(), status_code=404,
|
|
||||||
error="CapabilityType Not Found")
|
|
||||||
return res
|
|
||||||
|
|
||||||
@wsexpose([CapabilityType])
|
|
||||||
def get_all(self):
|
|
||||||
global capability_types
|
|
||||||
return capability_types
|
|
||||||
|
|
||||||
@wsexpose(CapabilityType, body=CapabilityType)
|
@wsexpose(CapabilityType, body=CapabilityType)
|
||||||
def post(self, capability_type):
|
def post(self, capability_type):
|
||||||
global capability_types
|
"""Create Capability Type
|
||||||
capability_types.append(capability_type)
|
@type capability_type:
|
||||||
|
graffiti.api.model.v1.capability_type.CapabilityType
|
||||||
|
@param capability_type: Capability type
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Check if namespace exists
|
||||||
|
namespace_found = self.__check_existing_namespace(
|
||||||
|
capability_type.namespace
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check if derived capability type exists
|
||||||
|
derived_checked = self.__check_derived_capability(
|
||||||
|
capability_type.derived_from
|
||||||
|
)
|
||||||
|
|
||||||
|
if namespace_found and derived_checked:
|
||||||
|
self._cap_controller.set_capability_type(
|
||||||
|
capability_type
|
||||||
|
)
|
||||||
|
return capability_type
|
||||||
|
else:
|
||||||
|
res = Response(
|
||||||
|
CapabilityType(),
|
||||||
|
status_code=404,
|
||||||
|
error="Provided namespace %s doesnt exist" %
|
||||||
|
capability_type.namespace)
|
||||||
|
return res
|
||||||
|
|
||||||
|
@wsexpose(CapabilityType, six.text_type, six.text_type,
|
||||||
|
body=CapabilityType)
|
||||||
|
def put(self, name, namespace, capability_type):
|
||||||
|
|
||||||
|
# Check if namespace exists
|
||||||
|
namespace_found = self.__check_existing_namespace(
|
||||||
|
capability_type.namespace
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check if derived capability type exists
|
||||||
|
derived_checked = self.__check_derived_capability(
|
||||||
|
capability_type.derived_from
|
||||||
|
)
|
||||||
|
|
||||||
|
if namespace_found and derived_checked:
|
||||||
|
self._cap_controller.put_capability_type(
|
||||||
|
name, namespace, capability_type
|
||||||
|
)
|
||||||
|
return capability_type
|
||||||
|
else:
|
||||||
|
res = Response(
|
||||||
|
CapabilityType(),
|
||||||
|
status_code=404,
|
||||||
|
error="Provided namespace %s doesnt exist" %
|
||||||
|
capability_type.namespace)
|
||||||
|
return res
|
||||||
|
|
||||||
|
@wsexpose(CapabilityType, six.text_type, six.text_type)
|
||||||
|
def delete(self, name, namespace):
|
||||||
|
captype = self._cap_controller.delete_capability_type(
|
||||||
|
name,
|
||||||
|
namespace
|
||||||
|
)
|
||||||
|
return captype
|
||||||
|
|
||||||
|
def __check_derived_capability(self, derived_from):
|
||||||
|
derived_checked = True
|
||||||
|
if derived_from:
|
||||||
|
derived_checked = False
|
||||||
|
derived_cap_found = self._cap_controller.get_capability_type(
|
||||||
|
derived_from.name, derived_from.namespace)
|
||||||
|
if derived_cap_found:
|
||||||
|
derived_checked = True
|
||||||
|
|
||||||
|
return derived_checked
|
||||||
|
|
||||||
|
def __check_existing_namespace(self, namespace_name):
|
||||||
|
return self._ns_controller.get_namespace(namespace_name)
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
|
||||||
|
class CapabilityTypeControllerBase(object):
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(CapabilityTypeControllerBase, self).__init__(**kwargs)
|
||||||
|
self._type = 'None'
|
||||||
|
|
||||||
|
def get_capability_type(self, name, namespace):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_type(self):
|
||||||
|
return self._type
|
||||||
|
|
||||||
|
def find_capability_types(self, query_string):
|
||||||
|
return []
|
||||||
|
|
||||||
|
def set_capability_type(self, capability_type=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def put_capability_type(self, name, namespace, capability_type=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def delete_capability_type(self, name, namespace):
|
||||||
|
pass
|
|
@ -0,0 +1,42 @@
|
||||||
|
# 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.controllers.v1.captype_db_controller \
|
||||||
|
import DBCapabilityTypeController
|
||||||
|
from graffiti.api.controllers.v1.captype_file_controller \
|
||||||
|
import FileCapabilityTypeController
|
||||||
|
from graffiti.api.controllers.v1.captype_mem_controller \
|
||||||
|
import MemCapabilityTypeController
|
||||||
|
|
||||||
|
|
||||||
|
class CapTypeControllerFactory(object):
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(CapTypeControllerFactory, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create(controller_type, **kwargs):
|
||||||
|
if controller_type.lower() == 'memory':
|
||||||
|
print "Dictionary persistence = memory"
|
||||||
|
return MemCapabilityTypeController(**kwargs)
|
||||||
|
elif controller_type.lower() == "db":
|
||||||
|
print "Dictionary persistence = db"
|
||||||
|
return DBCapabilityTypeController(**kwargs)
|
||||||
|
elif controller_type.lower() == "file":
|
||||||
|
print "Dictionary persistence = File"
|
||||||
|
return FileCapabilityTypeController(**kwargs)
|
||||||
|
|
||||||
|
return None
|
|
@ -0,0 +1,39 @@
|
||||||
|
# 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 captype_controller import CapabilityTypeControllerBase
|
||||||
|
|
||||||
|
|
||||||
|
# TODO(Wayne): Implement the db controller
|
||||||
|
class DBCapabilityTypeController(CapabilityTypeControllerBase):
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(DBCapabilityTypeController, self).__init__(**kwargs)
|
||||||
|
self._type = 'DBCapabilityTypeController'
|
||||||
|
|
||||||
|
def get_capability_type(self, name, namespace):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def find_capability_types(self, query_string):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def set_capability_type(self, capability_type=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def put_capability_type(self, name, namespace, capability_type=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def delete_capability_type(self, name, namespace):
|
||||||
|
pass
|
|
@ -0,0 +1,84 @@
|
||||||
|
# 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 captype_controller import CapabilityTypeControllerBase
|
||||||
|
from graffiti.api.model.v1.capability_type import CapabilityType
|
||||||
|
import json
|
||||||
|
from oslo.config import cfg
|
||||||
|
from wsme.rest.json import fromjson
|
||||||
|
from wsme.rest.json import tojson
|
||||||
|
|
||||||
|
|
||||||
|
class FileCapabilityTypeController(CapabilityTypeControllerBase):
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(FileCapabilityTypeController, self).__init__(**kwargs)
|
||||||
|
self._type = 'FileCapabilityTypeController'
|
||||||
|
self._graffiti_folder = cfg.CONF.FILE_PERSISTENCE.dictionary_folder
|
||||||
|
self._filename = "dictionary.json"
|
||||||
|
self._dictionaryfile = self._graffiti_folder + self._filename
|
||||||
|
self._capability_types = self.__file_to_memory()
|
||||||
|
|
||||||
|
def get_capability_type(self, name, namespace):
|
||||||
|
id = namespace + ":" + name
|
||||||
|
return self._capability_types[id]
|
||||||
|
|
||||||
|
def find_capability_types(self, query_string):
|
||||||
|
return self._capability_types.itervalues()
|
||||||
|
|
||||||
|
def set_capability_type(self, capability_type):
|
||||||
|
id = capability_type.namespace + ":" + capability_type.name
|
||||||
|
self._capability_types[id] = capability_type
|
||||||
|
self.__memory_to_file()
|
||||||
|
return capability_type
|
||||||
|
|
||||||
|
def put_capability_type(self, name, namespace, capability_type):
|
||||||
|
id = namespace + ":" + name
|
||||||
|
self._capability_types[id] = capability_type
|
||||||
|
self.__memory_to_file()
|
||||||
|
return capability_type
|
||||||
|
|
||||||
|
def delete_capability_type(self, name, namespace):
|
||||||
|
id = namespace + ":" + name
|
||||||
|
capability_type = None
|
||||||
|
if self._capability_types[id]:
|
||||||
|
capability_type = self._capability_types[id]
|
||||||
|
self._capability_types.pop(id)
|
||||||
|
self.__memory_to_file()
|
||||||
|
return capability_type
|
||||||
|
|
||||||
|
def __file_to_memory(self):
|
||||||
|
try:
|
||||||
|
capability_types = {}
|
||||||
|
with open(self._dictionaryfile, "r") as gfile:
|
||||||
|
doc = json.load(gfile)
|
||||||
|
for id in doc:
|
||||||
|
capability_types[id] = fromjson(CapabilityType, doc[id])
|
||||||
|
return capability_types
|
||||||
|
|
||||||
|
except IOError:
|
||||||
|
with open(self._dictionaryfile, "w+") as gfile:
|
||||||
|
gfile.write("")
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def __memory_to_file(self):
|
||||||
|
file_capability_types = {}
|
||||||
|
for (id, capability_type) in self._capability_types.items():
|
||||||
|
json_data = tojson(CapabilityType, capability_type)
|
||||||
|
file_capability_types[id] = json_data
|
||||||
|
|
||||||
|
with open(self._dictionaryfile, "w+") as gfile:
|
||||||
|
json.dump(file_capability_types, gfile)
|
|
@ -0,0 +1,52 @@
|
||||||
|
# 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 captype_controller import CapabilityTypeControllerBase
|
||||||
|
|
||||||
|
|
||||||
|
class MemCapabilityTypeController(CapabilityTypeControllerBase):
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(MemCapabilityTypeController, self).__init__(**kwargs)
|
||||||
|
self._type = 'MemCapabilityTypeController'
|
||||||
|
self._capability_types = {}
|
||||||
|
|
||||||
|
def get_capability_type(self, name, namespace):
|
||||||
|
id = namespace + ":" + name
|
||||||
|
return self._capability_types[id]
|
||||||
|
|
||||||
|
def find_capability_types(self, query_string):
|
||||||
|
return self._capability_types.itervalues()
|
||||||
|
|
||||||
|
def set_capability_type(self, capability_type):
|
||||||
|
id = capability_type.namespace + ":" + capability_type.name
|
||||||
|
self._capability_types[id] = capability_type
|
||||||
|
|
||||||
|
return capability_type
|
||||||
|
|
||||||
|
def put_capability_type(self, name, namespace, capability_type):
|
||||||
|
id = namespace + ":" + name
|
||||||
|
self._capability_types[id] = capability_type
|
||||||
|
|
||||||
|
return capability_type
|
||||||
|
|
||||||
|
def delete_capability_type(self, name, namespace):
|
||||||
|
id = namespace + ":" + name
|
||||||
|
capability_type = None
|
||||||
|
if self._capability_types[id]:
|
||||||
|
capability_type = self._capability_types[id]
|
||||||
|
self._capability_types.pop(id)
|
||||||
|
|
||||||
|
return capability_type
|
|
@ -17,40 +17,55 @@ from pecan.rest import RestController
|
||||||
|
|
||||||
from wsmeext.pecan import wsexpose
|
from wsmeext.pecan import wsexpose
|
||||||
|
|
||||||
|
from graffiti.api.controllers.v1.ns_controller_factory\
|
||||||
|
import NSControllerFactory
|
||||||
from graffiti.api.model.v1.namespace import Namespace
|
from graffiti.api.model.v1.namespace import Namespace
|
||||||
|
from oslo.config import cfg
|
||||||
import six
|
import six
|
||||||
|
|
||||||
namespaces = []
|
|
||||||
|
|
||||||
|
|
||||||
class NamespaceController(RestController):
|
class NamespaceController(RestController):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(RestController, self).__init__()
|
super(RestController, self).__init__()
|
||||||
self.status = 200
|
self.status = 200
|
||||||
|
self._controller = self._load_controller()
|
||||||
|
|
||||||
|
def _load_controller(self):
|
||||||
|
controller_type = cfg.CONF.DEFAULT.persistence_type
|
||||||
|
_controller = NSControllerFactory.create(controller_type)
|
||||||
|
return _controller
|
||||||
|
|
||||||
@wsexpose
|
@wsexpose
|
||||||
def options():
|
def options(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@wsexpose(Namespace, six.text_type)
|
@wsexpose(Namespace, six.text_type)
|
||||||
def get_one(self, name):
|
def get_one(self, namespace_name):
|
||||||
global namespaces
|
namespace = self._controller.get_namespace(namespace_name)
|
||||||
|
return namespace
|
||||||
for namespace in namespaces:
|
|
||||||
if namespace.name.lower() == name.lower():
|
|
||||||
return namespace
|
|
||||||
|
|
||||||
res = Namespace(Namespace(), status_code=404,
|
|
||||||
error="Namespace Not Found")
|
|
||||||
return res
|
|
||||||
|
|
||||||
@wsexpose([Namespace])
|
@wsexpose([Namespace])
|
||||||
def get_all(self):
|
def get_all(self, query_string=None):
|
||||||
global namespaces
|
namespace_list = self._controller.find_namespaces(query_string)
|
||||||
return namespaces
|
return namespace_list
|
||||||
|
|
||||||
@wsexpose(Namespace, body=Namespace)
|
@wsexpose(Namespace, body=Namespace)
|
||||||
def post(self, namespace):
|
def post(self, namespace):
|
||||||
global namespaces
|
"""Create Namespace
|
||||||
namespaces.append(namespace)
|
:namespace param:
|
||||||
|
graffiti.api.model.v1.namespace.Namespace
|
||||||
|
"""
|
||||||
|
|
||||||
|
self._controller.set_namespace(namespace)
|
||||||
|
return namespace
|
||||||
|
|
||||||
|
@wsexpose(Namespace, six.text_type, body=Namespace)
|
||||||
|
def put(self, namespace_name, namespace):
|
||||||
|
self._controller.put_namespace(namespace_name, namespace)
|
||||||
|
return namespace
|
||||||
|
|
||||||
|
@wsexpose(Namespace, six.text_type)
|
||||||
|
def delete(self, namespace_name):
|
||||||
|
print "namespace", namespace_name
|
||||||
|
namespace = self._controller.delete_namespace(namespace_name)
|
||||||
|
return namespace
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
|
||||||
|
class NSTypeControllerBase(object):
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(NSTypeControllerBase, self).__init__(**kwargs)
|
||||||
|
self._type = 'None'
|
||||||
|
|
||||||
|
def get_namespace(self, namespace_name):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_type(self):
|
||||||
|
return self._type
|
||||||
|
|
||||||
|
def find_namespaces(self, query_string):
|
||||||
|
return []
|
||||||
|
|
||||||
|
def set_namespace(self, namespace):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def put_namespace(self, namespace_name, namespace):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def delete_namespace(self, namespace_name):
|
||||||
|
pass
|
|
@ -0,0 +1,57 @@
|
||||||
|
# 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.controllers.v1.ns_db_controller \
|
||||||
|
import DBNSController
|
||||||
|
from graffiti.api.controllers.v1.ns_file_controller \
|
||||||
|
import FileNSController
|
||||||
|
from graffiti.api.controllers.v1.ns_mem_controller \
|
||||||
|
import MemNSController
|
||||||
|
from oslo.config import cfg
|
||||||
|
|
||||||
|
|
||||||
|
class NSControllerFactory(object):
|
||||||
|
|
||||||
|
__controller = None
|
||||||
|
__controller_type = cfg.CONF.DEFAULT.persistence_type
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(NSControllerFactory, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create(controller_type, **kwargs):
|
||||||
|
if controller_type.lower() == 'memory':
|
||||||
|
print "Namespace persistence = memory"
|
||||||
|
NSControllerFactory.__controller = MemNSController(**kwargs)
|
||||||
|
return NSControllerFactory.__controller
|
||||||
|
elif controller_type.lower() == "db":
|
||||||
|
print "Namespace persistence = db"
|
||||||
|
NSControllerFactory.__controller = DBNSController(**kwargs)
|
||||||
|
return NSControllerFactory.__controller
|
||||||
|
elif controller_type.lower() == "file":
|
||||||
|
print "Namespace persistence = File"
|
||||||
|
NSControllerFactory.__controller = FileNSController(**kwargs)
|
||||||
|
return NSControllerFactory.__controller
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get():
|
||||||
|
if NSControllerFactory.__controller:
|
||||||
|
return NSControllerFactory.__controller
|
||||||
|
else:
|
||||||
|
return NSControllerFactory.create(
|
||||||
|
NSControllerFactory.__controller_type)
|
|
@ -0,0 +1,43 @@
|
||||||
|
# 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 ns_controller import NSTypeControllerBase
|
||||||
|
|
||||||
|
|
||||||
|
# TODO(Wayne): Implement the db controller
|
||||||
|
class DBNSController(NSTypeControllerBase):
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(DBNSController, self).__init__(**kwargs)
|
||||||
|
self._type = 'DBNSController'
|
||||||
|
|
||||||
|
def get_type(self):
|
||||||
|
return self._type
|
||||||
|
|
||||||
|
def get_namespace(self, namespace_name):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def find_namespaces(self, query_string):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def set_namespace(self, namespace):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def put_namespace(self, namespace_name, namespace):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def delete_namespace(self, namespace_name):
|
||||||
|
pass
|
|
@ -0,0 +1,80 @@
|
||||||
|
# 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.namespace import Namespace
|
||||||
|
import json
|
||||||
|
from ns_controller import NSTypeControllerBase
|
||||||
|
from oslo.config import cfg
|
||||||
|
from wsme.rest.json import fromjson
|
||||||
|
from wsme.rest.json import tojson
|
||||||
|
|
||||||
|
|
||||||
|
class FileNSController(NSTypeControllerBase):
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(FileNSController, self).__init__(**kwargs)
|
||||||
|
self._type = 'FileNSController'
|
||||||
|
self._graffiti_folder = cfg.CONF.FILE_PERSISTENCE.dictionary_folder
|
||||||
|
self._filename = "namespaces.json"
|
||||||
|
self._namespacefile = self._graffiti_folder + self._filename
|
||||||
|
self._namespaces = self.__file_to_memory()
|
||||||
|
|
||||||
|
def get_namespace(self, namespace_name):
|
||||||
|
return self._namespaces[namespace_name]
|
||||||
|
|
||||||
|
def find_namespaces(self, query_string):
|
||||||
|
return self._namespaces.itervalues()
|
||||||
|
|
||||||
|
def set_namespace(self, namespace):
|
||||||
|
self._namespaces[namespace.name] = namespace
|
||||||
|
self.__memory_to_file()
|
||||||
|
return namespace
|
||||||
|
|
||||||
|
def put_namespace(self, namespace_name, namespace):
|
||||||
|
self._namespaces[namespace_name] = namespace
|
||||||
|
self.__memory_to_file()
|
||||||
|
return namespace
|
||||||
|
|
||||||
|
def delete_namespace(self, namespace_name):
|
||||||
|
namespace = None
|
||||||
|
if self._namespaces[namespace_name]:
|
||||||
|
namespace = self._namespaces[namespace_name]
|
||||||
|
self._namespaces.pop(namespace_name)
|
||||||
|
self.__memory_to_file()
|
||||||
|
return namespace
|
||||||
|
|
||||||
|
def __file_to_memory(self):
|
||||||
|
try:
|
||||||
|
namespaces = {}
|
||||||
|
with open(self._namespacefile, "r") as gfile:
|
||||||
|
doc = json.load(gfile)
|
||||||
|
for namespace in doc:
|
||||||
|
namespaces[namespace] = fromjson(Namespace, doc[namespace])
|
||||||
|
return namespaces
|
||||||
|
|
||||||
|
except IOError:
|
||||||
|
with open(self._namespacefile, "w+") as gfile:
|
||||||
|
gfile.write("")
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def __memory_to_file(self):
|
||||||
|
namespaces = {}
|
||||||
|
for (namespace_name, namespace) in self._namespaces.items():
|
||||||
|
json_data = tojson(Namespace, namespace)
|
||||||
|
namespaces[namespace_name] = json_data
|
||||||
|
|
||||||
|
with open(self._namespacefile, "w+") as gfile:
|
||||||
|
json.dump(namespaces, gfile)
|
|
@ -0,0 +1,49 @@
|
||||||
|
# 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 ns_controller import NSTypeControllerBase
|
||||||
|
|
||||||
|
|
||||||
|
class MemNSController(NSTypeControllerBase):
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(MemNSController, self).__init__(**kwargs)
|
||||||
|
self._type = 'MemNSController'
|
||||||
|
self._namespaces = {}
|
||||||
|
|
||||||
|
def get_type(self):
|
||||||
|
return self._type
|
||||||
|
|
||||||
|
def get_namespace(self, namespace_name):
|
||||||
|
return self._namespaces[namespace_name]
|
||||||
|
|
||||||
|
def find_namespaces(self, query_string):
|
||||||
|
return self._namespaces.itervalues()
|
||||||
|
|
||||||
|
def set_namespace(self, namespace):
|
||||||
|
self._namespaces[namespace.name] = namespace
|
||||||
|
return namespace
|
||||||
|
|
||||||
|
def put_namespace(self, namespace_name, namespace):
|
||||||
|
self._namespaces[namespace.name] = namespace
|
||||||
|
return namespace
|
||||||
|
|
||||||
|
def delete_namespace(self, namespace_name):
|
||||||
|
namespace = None
|
||||||
|
if self._namespaces[namespace_name]:
|
||||||
|
namespace = self._namespaces[namespace_name]
|
||||||
|
self._namespaces.pop(namespace_name)
|
||||||
|
|
||||||
|
return namespace
|
|
@ -13,15 +13,19 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
import pecan
|
||||||
from pecan.rest import RestController
|
from pecan.rest import RestController
|
||||||
|
|
||||||
|
|
||||||
from wsme.api import Response
|
from wsme.api import Response
|
||||||
from wsmeext.pecan import wsexpose
|
from wsmeext.pecan import wsexpose
|
||||||
|
|
||||||
from graffiti.api.model.v1.resource import Resource
|
from graffiti.api.model.v1.resource import Resource
|
||||||
|
from graffiti.api.plugins.glance_image import GlanceImage
|
||||||
|
|
||||||
from graffiti.api.model.v1.resource_controller_factory import \
|
|
||||||
ResourceControllerFactory
|
from graffiti.api.model.v1.resource_dao_factory import \
|
||||||
|
ResourceDAOFactory
|
||||||
|
|
||||||
from graffiti.common.utils import _
|
from graffiti.common.utils import _
|
||||||
|
|
||||||
|
@ -29,6 +33,8 @@ from oslo.config import cfg
|
||||||
|
|
||||||
import six
|
import six
|
||||||
|
|
||||||
|
import keystoneclient.v2_0.client as ksclient
|
||||||
|
|
||||||
|
|
||||||
resource_controller_group = cfg.OptGroup('resource_controller')
|
resource_controller_group = cfg.OptGroup('resource_controller')
|
||||||
resource_controller_opts = [
|
resource_controller_opts = [
|
||||||
|
@ -42,6 +48,11 @@ cfg.CONF.register_opts(resource_controller_opts,
|
||||||
|
|
||||||
|
|
||||||
class ResourceController(RestController):
|
class ResourceController(RestController):
|
||||||
|
|
||||||
|
# TODO(Lakshmi): Lookup supported types from plugin registry
|
||||||
|
local_resource_type = 'GFT:Local'
|
||||||
|
glance_resource_type = 'OS::Glance:Image'
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(ResourceController, self).__init__()
|
super(ResourceController, self).__init__()
|
||||||
|
|
||||||
|
@ -53,37 +64,98 @@ class ResourceController(RestController):
|
||||||
controller_type = cfg.CONF.resource_controller.type
|
controller_type = cfg.CONF.resource_controller.type
|
||||||
controller_type = controller_type if controller_type else 'Local'
|
controller_type = controller_type if controller_type else 'Local'
|
||||||
|
|
||||||
_controller = ResourceControllerFactory.create(controller_type)
|
_controller = ResourceDAOFactory.create(controller_type)
|
||||||
|
|
||||||
return _controller
|
return _controller
|
||||||
|
|
||||||
@wsexpose()
|
@wsexpose()
|
||||||
def options():
|
def options(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@wsexpose(Resource, six.text_type)
|
@wsexpose(Resource, six.text_type, six.text_type, six.text_type,
|
||||||
def get_one(self, id):
|
six.text_type)
|
||||||
res = self._controller.get_resource(id)
|
def get_one(self, resource_id, resource_type=None, param1=None,
|
||||||
if res:
|
param2=None):
|
||||||
|
print "args:", resource_id, resource_type, param1, param2
|
||||||
|
error_str = None
|
||||||
|
if not resource_type:
|
||||||
|
res = self._controller.get_resource(resource_id)
|
||||||
return res
|
return res
|
||||||
|
elif resource_type.lower() == \
|
||||||
|
ResourceController.glance_resource_type.lower():
|
||||||
|
auth_token = pecan.request.headers.get('X-Auth-Token')
|
||||||
|
endpoint_id = param1
|
||||||
|
image_id = resource_id
|
||||||
|
glance_public_url = None
|
||||||
|
keystone = ksclient.Client(
|
||||||
|
auth_url=cfg.CONF.keystone.auth_url,
|
||||||
|
username=cfg.CONF.keystone.username,
|
||||||
|
password=cfg.CONF.keystone.password,
|
||||||
|
tenant_name=cfg.CONF.keystone.tenant_name)
|
||||||
|
for endpoint in keystone.endpoints.list():
|
||||||
|
if endpoint.id == endpoint_id:
|
||||||
|
glance_public_url = endpoint.publicurl
|
||||||
|
|
||||||
res = Response(Resource(), status_code=404, error="Resource Not Found")
|
# TODO(Lakshmi): Load plugins with plugin framework
|
||||||
|
if auth_token and glance_public_url:
|
||||||
|
glance_plugin = GlanceImage(
|
||||||
|
glance_public_url,
|
||||||
|
keystone.auth_token
|
||||||
|
)
|
||||||
|
res = glance_plugin.get_resource(image_id)
|
||||||
|
if res:
|
||||||
|
return res
|
||||||
|
else:
|
||||||
|
error_str = "Resource not found"
|
||||||
|
else:
|
||||||
|
error_str = "auth_token and/or endpointid not found"
|
||||||
|
|
||||||
|
res = Response(Resource(), status_code=404, error=error_str)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
@wsexpose([Resource], six.text_type)
|
@wsexpose([Resource], six.text_type)
|
||||||
def get_all(self, query_string=None):
|
def get_all(self, query_string=None):
|
||||||
|
|
||||||
res_list = self._controller.find_resources(query_string)
|
res_list = self._controller.find_resources(query_string)
|
||||||
if res_list:
|
if res_list:
|
||||||
return res_list
|
return res_list.itervalues()
|
||||||
|
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@wsexpose(Resource, six.text_type, body=Resource)
|
@wsexpose(Resource, six.text_type, body=Resource)
|
||||||
def put(self, id, resource):
|
def put(self, resource_id, resource):
|
||||||
|
"""Modify resource
|
||||||
self._controller.set_resource(id, resource_definition=resource)
|
:resource param: graffiti.api.model.v1.resource.Resource
|
||||||
|
"""
|
||||||
|
resource_type = resource.type
|
||||||
|
if not resource_type:
|
||||||
|
resource_type = ResourceController.local_resource_type
|
||||||
|
if resource_type.lower() == \
|
||||||
|
ResourceController.local_resource_type.lower():
|
||||||
|
self._controller.set_resource(
|
||||||
|
resource_id,
|
||||||
|
resource_definition=resource
|
||||||
|
)
|
||||||
|
elif resource_type.lower() == \
|
||||||
|
ResourceController.glance_resource_type.lower():
|
||||||
|
auth_token = pecan.request.headers.get('X-Auth-Token')
|
||||||
|
endpoint_id = resource.provider.id
|
||||||
|
glance_public_url = None
|
||||||
|
keystone = ksclient.Client(
|
||||||
|
auth_url=cfg.CONF.keystone.auth_url,
|
||||||
|
username=cfg.CONF.keystone.username,
|
||||||
|
password=cfg.CONF.keystone.password,
|
||||||
|
tenant_name=cfg.CONF.keystone.tenant_name)
|
||||||
|
for endpoint in keystone.endpoints.list():
|
||||||
|
if endpoint.id == endpoint_id:
|
||||||
|
glance_public_url = endpoint.publicurl
|
||||||
|
|
||||||
|
# TODO(Lakshmi): Load plugins with plugin framework
|
||||||
|
if auth_token and glance_public_url:
|
||||||
|
glance_plugin = GlanceImage(
|
||||||
|
glance_public_url,
|
||||||
|
keystone.auth_token
|
||||||
|
)
|
||||||
|
glance_plugin.update_resource(resource)
|
||||||
return resource
|
return resource
|
||||||
|
|
||||||
@wsexpose(Resource, body=Resource)
|
@wsexpose(Resource, body=Resource)
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
#import json
|
# import json
|
||||||
|
|
||||||
from pecan.hooks import PecanHook
|
from pecan.hooks import PecanHook
|
||||||
|
|
||||||
|
|
|
@ -16,11 +16,17 @@
|
||||||
import wsme
|
import wsme
|
||||||
from wsme import types
|
from wsme import types
|
||||||
|
|
||||||
|
from graffiti.api.model.v1.derived_type import DerivedType
|
||||||
|
from graffiti.api.model.v1.property_type import PropertyType
|
||||||
|
|
||||||
|
|
||||||
class CapabilityType(types.Base):
|
class CapabilityType(types.Base):
|
||||||
|
|
||||||
name = wsme.wsattr(types.text, mandatory=True)
|
name = wsme.wsattr(types.text, mandatory=True)
|
||||||
namespace = wsme.wsattr(types.text, mandatory=True)
|
namespace = wsme.wsattr(types.text, mandatory=True)
|
||||||
description = wsme.wsattr(types.text, mandatory=False)
|
description = wsme.wsattr(types.text, mandatory=False)
|
||||||
|
properties = wsme.wsattr({types.text: PropertyType}, mandatory=False)
|
||||||
|
derived_from = wsme.wsattr(DerivedType, mandatory=False)
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super(CapabilityType, self).__init__(**kwargs)
|
super(CapabilityType, self).__init__(**kwargs)
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
# 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
|
||||||
|
|
||||||
|
|
||||||
|
class DerivedType(types.Base):
|
||||||
|
name = wsme.wsattr(types.text, mandatory=True)
|
||||||
|
namespace = wsme.wsattr(types.text, mandatory=True)
|
||||||
|
|
||||||
|
_wsme_attr_order = ('name', 'namespace')
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(DerivedType, self).__init__(**kwargs)
|
|
@ -13,6 +13,7 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
import wsme
|
import wsme
|
||||||
from wsme import types
|
from wsme import types
|
||||||
|
|
||||||
|
@ -20,7 +21,7 @@ from wsme import types
|
||||||
class Namespace(types.Base):
|
class Namespace(types.Base):
|
||||||
name = wsme.wsattr(types.text, mandatory=True)
|
name = wsme.wsattr(types.text, mandatory=True)
|
||||||
scope = wsme.wsattr(types.text, mandatory=True)
|
scope = wsme.wsattr(types.text, mandatory=True)
|
||||||
owner = wsme.wsattr(types.text, mandatory=True)
|
owner = wsme.wsattr(types.text, mandatory=False)
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super(Namespace, self).__init__(**kwargs)
|
super(Namespace, self).__init__(**kwargs)
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
# 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
|
||||||
|
|
||||||
|
|
||||||
|
class ItemType(types.Base):
|
||||||
|
type = wsme.wsattr(types.text, mandatory=True)
|
||||||
|
enum = wsme.wsattr([types.text], mandatory=False)
|
||||||
|
|
||||||
|
_wsme_attr_order = ('type', 'enum')
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(ItemType, self).__init__(**kwargs)
|
|
@ -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 graffiti.api.model.v1.property_item_type import ItemType
|
||||||
|
import wsme
|
||||||
|
from wsme import types
|
||||||
|
|
||||||
|
|
||||||
|
class PropertyType(types.Base):
|
||||||
|
type = wsme.wsattr(types.text, mandatory=True)
|
||||||
|
description = wsme.wsattr(types.text, mandatory=False)
|
||||||
|
default = wsme.wsattr(types.text, mandatory=False)
|
||||||
|
required = wsme.wsattr(bool, mandatory=False, default=False)
|
||||||
|
|
||||||
|
# fields for type = string
|
||||||
|
minimum = wsme.wsattr(int, mandatory=False)
|
||||||
|
maximum = wsme.wsattr(int, mandatory=False)
|
||||||
|
|
||||||
|
# fields for type = integer, number
|
||||||
|
minLength = wsme.wsattr(int, mandatory=False)
|
||||||
|
maxLength = wsme.wsattr(int, mandatory=False)
|
||||||
|
pattern = wsme.wsattr(types.text, mandatory=False)
|
||||||
|
confidential = wsme.wsattr(bool, mandatory=False)
|
||||||
|
|
||||||
|
# fields for type = array
|
||||||
|
items = wsme.wsattr(ItemType, mandatory=False)
|
||||||
|
uniqueItems = wsme.wsattr(bool, mandatory=False)
|
||||||
|
minItems = wsme.wsattr(int, mandatory=False)
|
||||||
|
maxItems = wsme.wsattr(int, mandatory=False)
|
||||||
|
additionalItems = wsme.wsattr(bool, mandatory=False)
|
||||||
|
|
||||||
|
_wsme_attr_order = ('type', 'description', 'default', 'required',
|
||||||
|
'minimum', 'maximum', 'minLength', 'maxLength',
|
||||||
|
'pattern', 'confidential', 'items', 'uniqueItems',
|
||||||
|
'additionalItems')
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(PropertyType, self).__init__(**kwargs)
|
|
@ -14,10 +14,10 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
class ResourceControllerBase(object):
|
class ResourceDAOBase(object):
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super(ResourceControllerBase, self).__init__(**kwargs)
|
super(ResourceDAOBase, self).__init__(**kwargs)
|
||||||
|
|
||||||
self._type = 'None'
|
self._type = 'None'
|
||||||
|
|
||||||
|
@ -34,12 +34,12 @@ class ResourceControllerBase(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class LocalResourceController(ResourceControllerBase):
|
class LocalResourceDAO(ResourceDAOBase):
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super(LocalResourceController, self).__init__(**kwargs)
|
super(LocalResourceDAO, self).__init__(**kwargs)
|
||||||
|
|
||||||
self._type = 'LocalResourceController'
|
self._type = 'LocalResourceDAO'
|
||||||
|
|
||||||
self._resources = dict()
|
self._resources = dict()
|
||||||
self._last_id = 0
|
self._last_id = 0
|
|
@ -13,17 +13,17 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from graffiti.api.model.v1.resource_controller import LocalResourceController
|
from graffiti.api.model.v1.resource_dao import LocalResourceDAO
|
||||||
|
|
||||||
|
|
||||||
class ResourceControllerFactory(object):
|
class ResourceDAOFactory(object):
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super(ResourceControllerFactory, self).__init__(**kwargs)
|
super(ResourceDAOFactory, self).__init__(**kwargs)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create(controller_type, **kwargs):
|
def create(dao_type, **kwargs):
|
||||||
if controller_type.lower() == 'local':
|
if dao_type.lower() == 'local':
|
||||||
return LocalResourceController(**kwargs)
|
return LocalResourceDAO(**kwargs)
|
||||||
|
|
||||||
return None
|
return None
|
|
@ -0,0 +1 @@
|
||||||
|
__author__ = 'lakshmi'
|
|
@ -0,0 +1,95 @@
|
||||||
|
# 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 glanceclient import Client
|
||||||
|
from graffiti.api.model.v1.capability import Capability
|
||||||
|
from graffiti.api.model.v1.property import Property
|
||||||
|
from graffiti.api.model.v1.resource import Resource
|
||||||
|
|
||||||
|
|
||||||
|
class GlanceImage(object):
|
||||||
|
|
||||||
|
def __init__(self, glance_endpoint, auth_token):
|
||||||
|
self.glance_endpoint = glance_endpoint
|
||||||
|
self.auth_token = auth_token
|
||||||
|
self.glance = Client('1', endpoint=glance_endpoint, token=auth_token)
|
||||||
|
self.separator = "."
|
||||||
|
|
||||||
|
def get_resource(self, image_id):
|
||||||
|
# glance_image_properties = {
|
||||||
|
# "GLANCE.MySQL.Port": "3605",
|
||||||
|
# "GLANCE.MySQL.Home": "/opt/mysql",
|
||||||
|
# "GLANCE.Apache.Port": "8080",
|
||||||
|
# "GLANCE.Apache.docroot": "/var/apache/static"
|
||||||
|
# }
|
||||||
|
image = self.glance.images.get(image_id)
|
||||||
|
glance_image_properties = image.properties
|
||||||
|
image_resource = Resource()
|
||||||
|
image_capability = Capability()
|
||||||
|
image_capabilities = []
|
||||||
|
image_resource.capabilities = image_capabilities
|
||||||
|
|
||||||
|
image_resource.id = image_id
|
||||||
|
image_resource.type = 'image'
|
||||||
|
# image_resource.name = "ubuntu 12.04"
|
||||||
|
image_resource.name = image.name
|
||||||
|
|
||||||
|
for key in glance_image_properties:
|
||||||
|
# replace if check with pattern matching
|
||||||
|
if key.count(self.separator) == 2:
|
||||||
|
(namespace, capability_type, prop_name) = key.split(".")
|
||||||
|
image_properties = []
|
||||||
|
image_property = Property()
|
||||||
|
image_property.name = prop_name
|
||||||
|
image_property.value = glance_image_properties[key]
|
||||||
|
|
||||||
|
image_capability = None
|
||||||
|
for capability in image_resource.capabilities:
|
||||||
|
if capability.capability_type_namespace == namespace and \
|
||||||
|
capability.capability_type == capability_type:
|
||||||
|
image_capability = capability
|
||||||
|
|
||||||
|
if not image_capability:
|
||||||
|
image_capability = Capability()
|
||||||
|
image_resource.capabilities.append(image_capability)
|
||||||
|
|
||||||
|
image_capability.capability_type_namespace = namespace
|
||||||
|
image_capability.capability_type = capability_type
|
||||||
|
image_properties.append(image_property)
|
||||||
|
|
||||||
|
image_capability.properties = image_properties
|
||||||
|
|
||||||
|
return image_resource
|
||||||
|
|
||||||
|
def update_resource(self, resource):
|
||||||
|
"""Update Glance Image
|
||||||
|
:type param: graffiti.api.model.v1.resource.Resource
|
||||||
|
"""
|
||||||
|
|
||||||
|
image_properties = {}
|
||||||
|
for capability in resource.capabilities:
|
||||||
|
properties = capability.properties
|
||||||
|
capability_type = capability.capability_type
|
||||||
|
capability_type_namespace = capability.capability_type_namespace
|
||||||
|
for property in properties:
|
||||||
|
prop_name = capability_type_namespace + \
|
||||||
|
self.separator + \
|
||||||
|
capability_type + \
|
||||||
|
self.separator + \
|
||||||
|
property.name
|
||||||
|
image_properties[prop_name] = property.value
|
||||||
|
|
||||||
|
image = self.glance.images.get(resource.id)
|
||||||
|
image.update(properties=image_properties, purge_props=False)
|
|
@ -18,10 +18,39 @@
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import fixtures
|
import fixtures
|
||||||
|
from oslo.config import cfg
|
||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
_TRUE_VALUES = ('True', 'true', '1', 'yes')
|
_TRUE_VALUES = ('True', 'true', '1', 'yes')
|
||||||
|
|
||||||
|
# DEFAULT group
|
||||||
|
default_controller_group = cfg.OptGroup('DEFAULT')
|
||||||
|
default_controller_opts = [
|
||||||
|
cfg.StrOpt(
|
||||||
|
'persistence_type',
|
||||||
|
default="memory",
|
||||||
|
help=("persistence options. "
|
||||||
|
"values = 'memory' or 'file' or 'db"))
|
||||||
|
]
|
||||||
|
|
||||||
|
cfg.CONF.register_group(default_controller_group)
|
||||||
|
cfg.CONF.register_opts(default_controller_opts,
|
||||||
|
group=default_controller_group)
|
||||||
|
|
||||||
|
# FILE_PERSISTENCE group
|
||||||
|
file_controller_group = cfg.OptGroup('FILE_PERSISTENCE')
|
||||||
|
file_controller_opts = [
|
||||||
|
cfg.StrOpt(
|
||||||
|
'dictionary_folder',
|
||||||
|
default="/tmp/graffiti-dictionary-test/",
|
||||||
|
help=("Absolute path of the file for persisting dictionary")
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
cfg.CONF.register_group(file_controller_group)
|
||||||
|
cfg.CONF.register_opts(file_controller_opts,
|
||||||
|
group=file_controller_group)
|
||||||
|
|
||||||
|
|
||||||
class TestCase(testtools.TestCase):
|
class TestCase(testtools.TestCase):
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,12 @@ from graffiti.api.tests import base
|
||||||
from graffiti.api.controllers.root import RootController
|
from graffiti.api.controllers.root import RootController
|
||||||
from graffiti.api.controllers.versions import V1Controller
|
from graffiti.api.controllers.versions import V1Controller
|
||||||
|
|
||||||
from graffiti.api.model.v1.resource_controller_factory \
|
from graffiti.api.controllers.v1.captype_controller_factory \
|
||||||
import ResourceControllerFactory
|
import CapTypeControllerFactory
|
||||||
|
from graffiti.api.controllers.v1.ns_controller_factory \
|
||||||
|
import NSControllerFactory
|
||||||
|
from graffiti.api.model.v1.resource_dao_factory \
|
||||||
|
import ResourceDAOFactory
|
||||||
|
|
||||||
|
|
||||||
class TestControllerV1(base.TestCase):
|
class TestControllerV1(base.TestCase):
|
||||||
|
@ -35,14 +39,48 @@ class TestControllerV1(base.TestCase):
|
||||||
root = RootController()
|
root = RootController()
|
||||||
self.assertIn(hasattr(root, 'v1'), [True])
|
self.assertIn(hasattr(root, 'v1'), [True])
|
||||||
|
|
||||||
|
def test_v1_namespace_exists(self):
|
||||||
|
v1 = V1Controller()
|
||||||
|
self.assertIn(hasattr(v1, 'namespace'), [True])
|
||||||
|
|
||||||
|
def test_v1_namespace_controller_factory__memory(self):
|
||||||
|
rc = NSControllerFactory.create('memory')
|
||||||
|
self.assertEquals(rc.get_type(), 'MemNSController')
|
||||||
|
|
||||||
|
# TODO(Lakshmi): Create folder before any tests run
|
||||||
|
# def test_v1_namespace_controller_factory__file(self):
|
||||||
|
# rc = NSControllerFactory.create('file')
|
||||||
|
# self.assertEquals(rc.get_type(), 'FileNSController')
|
||||||
|
|
||||||
|
def test_v1_namespace_controller_factory__db(self):
|
||||||
|
rc = NSControllerFactory.create('db')
|
||||||
|
self.assertEquals(rc.get_type(), 'DBNSController')
|
||||||
|
|
||||||
|
def test_v1_capability_type_exists(self):
|
||||||
|
v1 = V1Controller()
|
||||||
|
self.assertIn(hasattr(v1, 'capability_type'), [True])
|
||||||
|
|
||||||
|
def test_v1_capability_type_controller_factory__memory(self):
|
||||||
|
rc = CapTypeControllerFactory.create('memory')
|
||||||
|
self.assertEquals(rc.get_type(), 'MemCapabilityTypeController')
|
||||||
|
|
||||||
|
# TODO(Lakshmi): Create folder before any tests run
|
||||||
|
# def test_v1_capability_type_controller_factory__file(self):
|
||||||
|
# rc = CapTypeControllerFactory.create('file')
|
||||||
|
# self.assertEquals(rc.get_type(), 'FileCapabilityTypeController')
|
||||||
|
|
||||||
|
def test_v1_capability_type_controller_factory__db(self):
|
||||||
|
rc = CapTypeControllerFactory.create('db')
|
||||||
|
self.assertEquals(rc.get_type(), 'DBCapabilityTypeController')
|
||||||
|
|
||||||
def test_v1_resource_exists(self):
|
def test_v1_resource_exists(self):
|
||||||
v1 = V1Controller()
|
v1 = V1Controller()
|
||||||
self.assertIn(hasattr(v1, 'resource'), [True])
|
self.assertIn(hasattr(v1, 'resource'), [True])
|
||||||
|
|
||||||
def test_v1_resource_controller_factory__local(self):
|
def test_v1_resource_controller_factory__local(self):
|
||||||
rc = ResourceControllerFactory.create('local')
|
rc = ResourceDAOFactory.create('local')
|
||||||
self.assertEquals(rc.get_type(), 'LocalResourceController')
|
self.assertEquals(rc.get_type(), 'LocalResourceDAO')
|
||||||
|
|
||||||
def test_v1_resource_controller_factory__unknown(self):
|
def test_v1_resource_controller_factory__unknown(self):
|
||||||
rc = ResourceControllerFactory.create('invalid_controller')
|
rc = ResourceDAOFactory.create('invalid_controller')
|
||||||
self.assertTrue(rc is None)
|
self.assertTrue(rc is None)
|
||||||
|
|
|
@ -3,3 +3,4 @@ Babel>=0.9.6
|
||||||
pecan>=0.4.4
|
pecan>=0.4.4
|
||||||
WSME>=0.6
|
WSME>=0.6
|
||||||
oslo.config
|
oslo.config
|
||||||
|
python-glanceclient
|
||||||
|
|
Loading…
Reference in New Issue