summaryrefslogtreecommitdiffstats
path: root/tosca2heat/heat-translator/translator/common
diff options
context:
space:
mode:
Diffstat (limited to 'tosca2heat/heat-translator/translator/common')
-rw-r--r--tosca2heat/heat-translator/translator/common/exception.py5
-rw-r--r--tosca2heat/heat-translator/translator/common/flavors.py64
-rw-r--r--tosca2heat/heat-translator/translator/common/images.py91
-rw-r--r--tosca2heat/heat-translator/translator/common/utils.py67
4 files changed, 217 insertions, 10 deletions
diff --git a/tosca2heat/heat-translator/translator/common/exception.py b/tosca2heat/heat-translator/translator/common/exception.py
index be86116..f16d3d7 100644
--- a/tosca2heat/heat-translator/translator/common/exception.py
+++ b/tosca2heat/heat-translator/translator/common/exception.py
@@ -43,6 +43,11 @@ class ToscaClassImportError(TOSCAException):
'exists and has no language definition errors.')
+class UnsupportedTypeError(TOSCAException):
+ msg_fmt = _('Type "%(type)s" is valid TOSCA type but translation '
+ 'support is not yet available.')
+
+
class ToscaClassAttributeError(TOSCAException):
msg_fmt = _('Class attribute referenced not found. '
'%(message)s. Check to see that it is defined.')
diff --git a/tosca2heat/heat-translator/translator/common/flavors.py b/tosca2heat/heat-translator/translator/common/flavors.py
new file mode 100644
index 0000000..c44f883
--- /dev/null
+++ b/tosca2heat/heat-translator/translator/common/flavors.py
@@ -0,0 +1,64 @@
+# 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 logging
+
+try:
+ import novaclient.client
+ client_available = True
+except ImportError:
+ client_available = False
+ pass
+
+log = logging.getLogger('heat-translator')
+
+
+PREDEF_FLAVORS = {
+ 'm1.xlarge': {'mem_size': 16384, 'disk_size': 160, 'num_cpus': 8},
+ 'm1.large': {'mem_size': 8192, 'disk_size': 80, 'num_cpus': 4},
+ 'm1.medium': {'mem_size': 4096, 'disk_size': 40, 'num_cpus': 2},
+ 'm1.small': {'mem_size': 2048, 'disk_size': 20, 'num_cpus': 1},
+ 'm1.tiny': {'mem_size': 512, 'disk_size': 1, 'num_cpus': 1},
+ 'm1.micro': {'mem_size': 128, 'disk_size': 0, 'num_cpus': 1},
+ 'm1.nano': {'mem_size': 64, 'disk_size': 0, 'num_cpus': 1}
+}
+
+SESSION = None
+
+FLAVORS = {}
+
+
+def get_flavors():
+ global FLAVORS
+
+ if FLAVORS:
+ return FLAVORS
+
+ if SESSION is not None and client_available:
+ try:
+ client = novaclient.client.Client("2", session=SESSION)
+ except Exception as e:
+ # Handles any exception coming from openstack
+ log.warn(_('Choosing predefined flavors since received '
+ 'Openstack Exception: %s') % str(e))
+ else:
+ for flv in client.flavors.list(detailed=True):
+ FLAVORS[str(flv.name)] = {
+ "mem_size": flv.ram,
+ "disk_size": flv.disk,
+ "num_cpus": flv.vcpus
+ }
+
+ if not FLAVORS:
+ FLAVORS = PREDEF_FLAVORS
+
+ return FLAVORS
diff --git a/tosca2heat/heat-translator/translator/common/images.py b/tosca2heat/heat-translator/translator/common/images.py
new file mode 100644
index 0000000..f9fa4f1
--- /dev/null
+++ b/tosca2heat/heat-translator/translator/common/images.py
@@ -0,0 +1,91 @@
+# 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 logging
+
+try:
+ import glanceclient.client
+ client_available = True
+except ImportError:
+ client_available = False
+ pass
+
+log = logging.getLogger('heat-translator')
+
+
+PREDEF_IMAGES = {
+ 'ubuntu-software-config-os-init': {'architecture': 'x86_64',
+ 'type': 'Linux',
+ 'distribution': 'Ubuntu',
+ 'version': '14.04'},
+ 'ubuntu-12.04-software-config-os-init': {'architecture': 'x86_64',
+ 'type': 'Linux',
+ 'distribution': 'Ubuntu',
+ 'version': '12.04'},
+ 'fedora-amd64-heat-config': {'architecture': 'x86_64',
+ 'type': 'Linux',
+ 'distribution': 'Fedora',
+ 'version': '18.0'},
+ 'F18-x86_64-cfntools': {'architecture': 'x86_64',
+ 'type': 'Linux',
+ 'distribution': 'Fedora',
+ 'version': '19'},
+ 'Fedora-x86_64-20-20131211.1-sda': {'architecture': 'x86_64',
+ 'type': 'Linux',
+ 'distribution': 'Fedora',
+ 'version': '20'},
+ 'cirros-0.3.1-x86_64-uec': {'architecture': 'x86_64',
+ 'type': 'Linux',
+ 'distribution': 'CirrOS',
+ 'version': '0.3.1'},
+ 'cirros-0.3.2-x86_64-uec': {'architecture': 'x86_64',
+ 'type': 'Linux',
+ 'distribution': 'CirrOS',
+ 'version': '0.3.2'},
+ 'rhel-6.5-test-image': {'architecture': 'x86_64',
+ 'type': 'Linux',
+ 'distribution': 'RHEL',
+ 'version': '6.5'}
+}
+
+SESSION = None
+
+IMAGES = {}
+
+
+def get_images():
+ global IMAGES
+
+ if IMAGES:
+ return IMAGES
+
+ if SESSION is not None and client_available:
+ try:
+ client = glanceclient.client.Client("2", session=SESSION)
+ except Exception as e:
+ # Handles any exception coming from openstack
+ log.warn(_('Choosing predefined images since received '
+ 'Openstack Exception: %s') % str(e))
+ else:
+ for image in client.images.list():
+ image_name = image.name.encode('ascii', 'ignore')
+ metadata = ["architecture", "type", "distribution", "version"]
+ if any(key in image.keys() for key in metadata):
+ IMAGES[image_name] = {}
+ for key in metadata:
+ if key in image.keys():
+ IMAGES[image_name][key] = image[key]
+
+ if not IMAGES:
+ IMAGES = PREDEF_IMAGES
+
+ return IMAGES
diff --git a/tosca2heat/heat-translator/translator/common/utils.py b/tosca2heat/heat-translator/translator/common/utils.py
index 459b5ee..874c8ec 100644
--- a/tosca2heat/heat-translator/translator/common/utils.py
+++ b/tosca2heat/heat-translator/translator/common/utils.py
@@ -18,8 +18,11 @@ import numbers
import os
import re
import requests
+import six
from six.moves.urllib.parse import urlparse
+import tempfile
import yaml
+import zipfile
from toscaparser.utils.gettextutils import _
import toscaparser.utils.yamlparser
@@ -193,7 +196,7 @@ class YamlUtils(object):
def get_dict(yaml_file):
'''Returns the dictionary representation of the given YAML spec.'''
try:
- return yaml.load(open(yaml_file))
+ return yaml.safe_load(open(yaml_file))
except IOError:
return None
@@ -213,7 +216,7 @@ class YamlUtils(object):
class TranslationUtils(object):
@staticmethod
- def compare_tosca_translation_with_hot(tosca_file, hot_file, params):
+ def compare_tosca_translation_with_hot(tosca_file, hot_files, params):
'''Verify tosca translation against the given hot specification.
inputs:
@@ -234,16 +237,28 @@ class TranslationUtils(object):
if not a_file:
tosca_tpl = tosca_file
- expected_hot_tpl = os.path.join(
- os.path.dirname(os.path.abspath(__file__)), hot_file)
+ expected_hot_templates = []
+ for hot_file in hot_files:
+ expected_hot_templates.append(os.path.join(
+ os.path.dirname(os.path.abspath(__file__)), hot_file))
tosca = ToscaTemplate(tosca_tpl, params, a_file)
translate = TOSCATranslator(tosca, params)
- output = translate.translate()
- output_dict = toscaparser.utils.yamlparser.simple_parse(output)
- expected_output_dict = YamlUtils.get_dict(expected_hot_tpl)
- return CompareUtils.diff_dicts(output_dict, expected_output_dict)
+ basename = os.path.basename(hot_files[0])
+ output_hot_templates = translate.translate_to_yaml_files_dict(basename)
+ output_dict = {}
+ for output_hot_template_name in output_hot_templates:
+ output_dict[output_hot_template_name] = \
+ toscaparser.utils.yamlparser.simple_parse(
+ output_hot_templates[output_hot_template_name])
+
+ expected_output_dict = {}
+ for expected_hot_template in expected_hot_templates:
+ expected_output_dict[os.path.basename(expected_hot_template)] = \
+ YamlUtils.get_dict(expected_hot_template)
+
+ return CompareUtils.diff_dicts(expected_output_dict, output_dict)
class UrlUtils(object):
@@ -262,12 +277,17 @@ class UrlUtils(object):
def str_to_num(value):
"""Convert a string representation of a number into a numeric type."""
- if isinstance(value, numbers.Number):
+ if isinstance(value, numbers.Number) \
+ or isinstance(value, six.integer_types) \
+ or isinstance(value, float):
return value
try:
return int(value)
except ValueError:
- return float(value)
+ try:
+ return float(value)
+ except ValueError:
+ return None
def check_for_env_variables():
@@ -317,3 +337,30 @@ def get_token_id(access_dict):
if access_dict is None:
return None
return access_dict['access']['token']['id']
+
+
+def decompress(zip_file, dir=None):
+ """Decompress Zip file
+
+ Decompress any zip file. For example, TOSCA CSAR
+
+ inputs:
+ zip_file: file in zip format
+ dir: directory to decompress zip. If not provided an unique temporary
+ directory will be generated and used.
+ return:
+ dir: absolute path to the decopressed directory
+ """
+ if not dir:
+ dir = tempfile.NamedTemporaryFile().name
+ with zipfile.ZipFile(zip_file, "r") as zf:
+ zf.extractall(dir)
+ return dir
+
+
+def get_dict_value(dict_item, key, get_files):
+ if key in dict_item:
+ return get_files.append(dict_item[key])
+ for k, v in dict_item.items():
+ if isinstance(v, dict):
+ get_dict_value(v, key, get_files)