Implementation of tosca.node.ObjectStorage

Added tosca.node.ObjectStorage in TOSCA_defintions.yaml
Implementation in toscalib and hot
Implemented unit testcases in hot and tosca

Added testcase to compare hot generated output for
object store template with expected template

Change-Id: I93a380e7d2e3a1febd9830f3f6f53eb8ecda347b
Implements: blueprint tosca-object-storage
This commit is contained in:
srinivas_tadepalli 2015-03-30 19:35:31 +05:30
parent 5a8dfe40f6
commit 99739b10b4
8 changed files with 281 additions and 1 deletions

View File

@ -0,0 +1,70 @@
# 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 translator.hot.tosca.tosca_object_storage import ToscaObjectStorage
from translator.toscalib.nodetemplate import NodeTemplate
from translator.toscalib.tests.base import TestCase
import translator.toscalib.utils.yamlparser
class ToscaObjectStoreTest(TestCase):
def _tosca_objectstore_test(self, tpl_snippet, expectedprops):
nodetemplates = (translator.toscalib.utils.yamlparser.
simple_parse(tpl_snippet)['node_templates'])
name = list(nodetemplates.keys())[0]
try:
nodetemplate = NodeTemplate(name, nodetemplates)
tosca_object_store = ToscaObjectStorage(nodetemplate)
tosca_object_store.handle_properties()
if not self._compare_properties(tosca_object_store.properties,
expectedprops):
raise Exception(_("Hot Properties are not"
" same as expected properties"))
except Exception:
# for time being rethrowing. Will be handled future based
# on new development
raise
def _compare_properties(self, hotprops, expectedprops):
return all(item in hotprops.items() for item in expectedprops.items())
def test_node_objectstorage_with_properties(self):
tpl_snippet = '''
node_templates:
server:
type: tosca.nodes.ObjectStorage
properties:
store_name: test
store_size: 1024
store_maxsize: 1 MB
'''
expectedprops = {'name': 'test',
'X-Container-Meta': {'Quota-Bytes': 1000000}}
self._tosca_objectstore_test(
tpl_snippet,
expectedprops)
def test_node_objectstorage_with_few_properties(self):
tpl_snippet = '''
node_templates:
server:
type: tosca.nodes.ObjectStorage
properties:
store_name: test
store_size: 1024
'''
expectedprops = {'name': 'test',
'X-Container-Meta': {'Quota-Bytes': 1024}}
self._tosca_objectstore_test(
tpl_snippet,
expectedprops)

View File

@ -0,0 +1,53 @@
#
# 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 translator.hot.syntax.hot_resource import HotResource
from translator.toscalib.elements.constraints import Constraint
class ToscaObjectStorage(HotResource):
'''Translate TOSCA node type tosca.nodes.ObjectStorage.'''
def __init__(self, nodetemplate):
super(ToscaObjectStorage, self).__init__(nodetemplate,
type='OS::Swift::Container')
pass
def handle_properties(self):
tosca_props = self._get_tosca_props(
self.nodetemplate.get_properties_objects())
objectstore_props = {}
container_quota = {}
skip_check = False
for key, value in tosca_props.items():
if key == "store_name":
objectstore_props["name"] = value
elif key == "store_size" or key == "store_maxsize":
#currently heat is not supporting dynamically increase
#the container quota-size.
#if both defined in tosca template, consider store_maxsize.
if skip_check:
continue
quota_size = None
if "store_maxsize" in tosca_props.keys():
quota_size = tosca_props["store_maxsize"]
else:
quota_size = tosca_props["store_size"]
container_quota["Quota-Bytes"] = \
Constraint.get_num_from_scalar_unit_size(quota_size)
objectstore_props["X-Container-Meta"] = container_quota
skip_check = True
objectstore_props["X-Container-Read"] = '".r:*"'
self.properties = objectstore_props

View File

@ -23,6 +23,7 @@ from translator.hot.tosca.tosca_dbms import ToscaDbms
from translator.hot.tosca.tosca_network_network import ToscaNetwork
from translator.hot.tosca.tosca_network_port import ToscaNetworkPort
from translator.hot.tosca.tosca_nodejs import ToscaNodejs
from translator.hot.tosca.tosca_object_storage import ToscaObjectStorage
from translator.hot.tosca.tosca_webserver import ToscaWebserver
from translator.hot.tosca.tosca_wordpress import ToscaWordpress
from translator.toscalib.functions import GetAttribute
@ -57,7 +58,8 @@ TOSCA_TO_HOT_TYPE = {'tosca.nodes.Compute': ToscaCompute,
'tosca.nodes.BlockStorage': ToscaBlockStorage,
'tosca.nodes.SoftwareComponent.Nodejs': ToscaNodejs,
'tosca.nodes.network.Network': ToscaNetwork,
'tosca.nodes.network.Port': ToscaNetworkPort}
'tosca.nodes.network.Port': ToscaNetworkPort,
'tosca.nodes.ObjectStorage': ToscaObjectStorage}
TOSCA_TO_HOT_REQUIRES = {'container': 'server', 'host': 'server',
'dependency': 'depends_on', "connects": 'depends_on'}

View File

@ -0,0 +1,46 @@
# 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 os
from translator.common.utils import CompareUtils
from translator.hot.tosca_translator import TOSCATranslator
from translator.toscalib.tests.base import TestCase
from translator.toscalib.tosca_template import ToscaTemplate
class ToscaObjectStoreTemplateTest(TestCase):
def test_single_template_objectstore(self):
tosca_yaml_file = "../toscalib/tests/data/storage/" + \
"tosca_single_object_store.yaml"
tosca_tpl = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
tosca_yaml_file)
parsed_params = {'objectstore_name': 'test_obj_store'}
tosca = ToscaTemplate(tosca_tpl)
translate = TOSCATranslator(tosca, parsed_params)
hot_translated_output = translate.translate()
#load expected hot yaml file
hot_yaml_file = "../toscalib/tests/data/hot_output/" + \
"hot_single_object_store.yaml"
hot_tpl = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
hot_yaml_file)
with open(hot_tpl) as f:
hot_expected_output = f.read()
#compare generated and expected hot templates
status = CompareUtils.compare_hot_yamls(hot_translated_output,
hot_expected_output)
self.assertEqual(status, True)

View File

@ -285,6 +285,33 @@ tosca.nodes.network.Port:
nodes. It indicates which network this port will connect to.
type: tosca.capabilities.network.Linkable
tosca.nodes.ObjectStorage:
derived_from: tosca.nodes.Root
description: >
The TOSCA ObjectStorage node represents storage that provides the ability
to store data as objects (or BLOBs of data) without consideration for the
underlying filesystem or devices
properties:
store_name:
type: string
required: yes
description: >
The logical name of the object store (or container).
store_size:
type: scalar-unit.size
required: no
constraints:
- greater_or_equal: 0 GB
description: >
The requested initial storage size.
store_maxsize:
type: scalar-unit.size
required: no
constraints:
- greater_or_equal: 0 GB
description: >
The requested maximum storage size.
##########################################################################
# Relationship Type.
# A Relationship Type is a reusable entity that defines the type of one

View File

@ -0,0 +1,19 @@
heat_template_version: 2013-05-23
description: >
Tosca template for testing a objectstorage template.
parameters:
objectstore_name:
type: string
default: test_obj_store
resources:
obj_store_server:
type: OS::Swift::Container
properties:
X-Container-Meta:
Quota-Bytes: 1000000000
X-Container-Read: ".r:*"
name:
get_param: objectstore_name
outputs: {}

View File

@ -0,0 +1,16 @@
tosca_definitions_version: tosca_simple_yaml_1_0_0
description: >
Tosca template for testing a objectstorage template.
inputs:
objectstore_name:
type: string
node_templates:
obj_store_server:
type: tosca.nodes.ObjectStorage
properties:
store_name: { get_input: objectstore_name }
store_size: 1024
store_maxsize: 1 GB

View File

@ -506,3 +506,50 @@ class ToscaTemplateValidationTest(TestCase):
tpl_snippet,
exception.ValidationError,
expectedmessage)
def test_node_template_objectstorage_without_required_property(self):
tpl_snippet = '''
node_templates:
server:
type: tosca.nodes.ObjectStorage
properties:
store_maxsize: 1 GB
'''
expectedmessage = ('Properties of template server is missing '
'required field: '
'"[\'store_name\']".')
self._single_node_template_content_test(
tpl_snippet,
exception.MissingRequiredFieldError,
expectedmessage)
def test_node_template_objectstorage_with_invalid_scalar_unit(self):
tpl_snippet = '''
node_templates:
server:
type: tosca.nodes.ObjectStorage
properties:
store_name: test
store_maxsize: -1
'''
expectedmessage = ('"-1" is not a valid scalar-unit')
self._single_node_template_content_test(
tpl_snippet,
ValueError,
expectedmessage)
def test_node_template_objectstorage_with_invalid_scalar_type(self):
tpl_snippet = '''
node_templates:
server:
type: tosca.nodes.ObjectStorage
properties:
store_name: test
store_maxsize: 1 XB
'''
expectedmessage = ('"1 XB" is not a valid scalar-unit')
self._single_node_template_content_test(
tpl_snippet,
ValueError,
expectedmessage)