Add CSAR processing support

Add support for processing CSAR files and include necessary unit tests.

Note: Since CSAR files used do not already exist on github a temporary
URL has been used. Once the patch merges a follow-on patch will be
submitted to update the URL to a github URL.

Change-Id: Ibf44be1368ed0144ecf415068b0ca5aea5aa6134
Partially-Implements: blueprint tosca-csar-translation
This commit is contained in:
Vahid Hashemian
2015-09-28 14:53:44 -07:00
parent 6751659cd7
commit 30603c67a9
6 changed files with 67 additions and 25 deletions

View File

@@ -11,18 +11,26 @@
# under the License. # under the License.
import os.path import os.path
import requests
import tempfile import tempfile
import yaml import yaml
import zipfile import zipfile
from toscaparser.common.exception import ValidationError from toscaparser.common.exception import ValidationError
from toscaparser.utils.gettextutils import _ from toscaparser.utils.gettextutils import _
from toscaparser.utils.urlutils import UrlUtils
try: # Python 2.x
from BytesIO import BytesIO
except ImportError: # Python 3.x
from io import BytesIO
class CSAR(object): class CSAR(object):
def __init__(self, csar_file): def __init__(self, csar_file, a_file=True):
self.csar_file = csar_file self.csar_file = csar_file
self.a_file = a_file
self.is_validated = False self.is_validated = False
def validate(self): def validate(self):
@@ -31,10 +39,18 @@ class CSAR(object):
self.is_validated = True self.is_validated = True
# validate that the file exists # validate that the file exists
if not os.path.isfile(self.csar_file): if self.a_file and not os.path.isfile(self.csar_file):
err_msg = (_('The file %s does not exist.') % self.csar_file) err_msg = (_('The file %s does not exist.') % self.csar_file)
raise ValidationError(message=err_msg) raise ValidationError(message=err_msg)
if not self.a_file: # a URL
if not UrlUtils.validate_url(self.csar_file):
err_msg = (_('The URL %s does not exist.') % self.csar_file)
raise ValidationError(message=err_msg)
else:
response = requests.get(self.csar_file)
self.csar_file = BytesIO(response.content)
# validate that it is a valid zip file # validate that it is a valid zip file
if not zipfile.is_zipfile(self.csar_file): if not zipfile.is_zipfile(self.csar_file):
err_msg = (_('The file %s is not a valid zip file.') err_msg = (_('The file %s is not a valid zip file.')

Binary file not shown.

Binary file not shown.

View File

@@ -58,10 +58,10 @@ topology_template:
configure: configure:
implementation: Scripts/MYSQLDatabase/configure.sh implementation: Scripts/MYSQLDatabase/configure.sh
inputs: inputs:
db_name: { get_property: [ SELF, db_name ] } db_name: { get_property: [ SELF, name ] }
db_user: { get_property: [ SELF, db_user ] } db_user: { get_property: [ SELF, user ] }
db_password: { get_property: [ SELF, db_password ] } db_password: { get_property: [ SELF, password ] }
db_root_password: { get_property: [ mysql_dbms, dbms_root_password ] } db_root_password: { get_property: [ mysql_dbms, root_password ] }
mysql_dbms: mysql_dbms:
type: tosca.nodes.DBMS type: tosca.nodes.DBMS
@@ -87,20 +87,21 @@ topology_template:
Standard: Standard:
create: Scripts/WebServer/install.sh create: Scripts/WebServer/install.sh
start: Scripts/WebServer/start.sh start: Scripts/WebServer/start.sh
server:
type: tosca.nodes.Compute server:
capabilities: type: tosca.nodes.Compute
host: capabilities:
properties: host:
disk_size: 10 GB properties:
num_cpus: { get_input: cpus } disk_size: 10 GB
mem_size: 4096 MB num_cpus: { get_input: cpus }
os: mem_size: 4096 MB
properties: os:
architecture: x86_64 properties:
type: Linux architecture: x86_64
distribution: Fedora type: Linux
version: 18.0 distribution: Fedora
version: 18.0
outputs: outputs:
website_url: website_url:

View File

@@ -423,3 +423,14 @@ class ToscaTemplateTest(TestCase):
'tosca_single_instance_wordpress_with_url_import.yaml') 'tosca_single_instance_wordpress_with_url_import.yaml')
tosca = ToscaTemplate(tosca_tpl, False) tosca = ToscaTemplate(tosca_tpl, False)
self.assertTrue(tosca.topology_template.custom_defs) self.assertTrue(tosca.topology_template.custom_defs)
def test_csar_parsing_wordpress(self):
csar_archive = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
'data/CSAR/csar_wordpress.zip')
self.assertTrue(ToscaTemplate(csar_archive))
def test_csar_parsing_elk_url_based(self):
csar_archive = ('https://ibm.box.com/shared/static/'
'k9vtus4jes1epl7vfojbcscgsd80inzv.zip')
self.assertTrue(ToscaTemplate(csar_archive, False))

View File

@@ -12,15 +12,15 @@
import logging import logging
import os
from toscaparser.common.exception import InvalidTemplateVersion from toscaparser.common.exception import InvalidTemplateVersion
from toscaparser.common.exception import MissingRequiredFieldError from toscaparser.common.exception import MissingRequiredFieldError
from toscaparser.common.exception import UnknownFieldError from toscaparser.common.exception import UnknownFieldError
import toscaparser.imports
from toscaparser.prereq.csar import CSAR
from toscaparser.topology_template import TopologyTemplate from toscaparser.topology_template import TopologyTemplate
from toscaparser.tpl_relationship_graph import ToscaGraph from toscaparser.tpl_relationship_graph import ToscaGraph
import toscaparser.imports
import toscaparser.utils.urlutils
import toscaparser.utils.yamlparser import toscaparser.utils.yamlparser
@@ -49,9 +49,9 @@ class ToscaTemplate(object):
'''Load the template data.''' '''Load the template data.'''
def __init__(self, path, a_file=True, parsed_params=None): def __init__(self, path, a_file=True, parsed_params=None):
self.tpl = YAML_LOADER(path, a_file)
self.path = path
self.a_file = a_file self.a_file = a_file
self.path = self._get_path(path)
self.tpl = YAML_LOADER(self.path, self.a_file)
self.parsed_params = parsed_params self.parsed_params = parsed_params
self._validate_field() self._validate_field()
self.version = self._tpl_version() self.version = self._tpl_version()
@@ -151,3 +151,17 @@ class ToscaTemplate(object):
raise InvalidTemplateVersion( raise InvalidTemplateVersion(
what=version, what=version,
valid_versions=', '. join(self.VALID_TEMPLATE_VERSIONS)) valid_versions=', '. join(self.VALID_TEMPLATE_VERSIONS))
def _get_path(self, path):
if path.lower().endswith('.yaml'):
return path
elif path.lower().endswith('.zip'):
# a CSAR archive
csar = CSAR(path, self.a_file)
csar.validate()
folder = csar.decompress()
self.a_file = True # the file has been decompressed locally
return os.path.join(folder, csar.get_main_template())
else:
raise ValueError(_("%(path)s is not a valid file.")
% {'path': path})