2014-05-30 03:23:09 +04:00
|
|
|
# Copyright (c) 2014 Mirantis, Inc.
|
|
|
|
#
|
|
|
|
# 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.
|
|
|
|
|
2015-08-27 04:59:50 +03:00
|
|
|
import contextlib
|
2014-05-30 03:23:09 +04:00
|
|
|
import os
|
|
|
|
import shutil
|
2015-08-18 15:37:30 +03:00
|
|
|
import string
|
2014-05-30 03:23:09 +04:00
|
|
|
import sys
|
|
|
|
import tempfile
|
|
|
|
import zipfile
|
|
|
|
|
2015-08-18 15:37:30 +03:00
|
|
|
import semantic_version
|
2015-02-04 17:10:06 +03:00
|
|
|
import yaml
|
|
|
|
|
2014-05-30 03:23:09 +04:00
|
|
|
import murano.packages.exceptions as e
|
2015-08-18 15:37:30 +03:00
|
|
|
import murano.packages.hot_package
|
|
|
|
import murano.packages.mpl_package
|
2014-05-30 03:23:09 +04:00
|
|
|
|
|
|
|
|
2015-08-27 04:59:50 +03:00
|
|
|
@contextlib.contextmanager
|
|
|
|
def load_from_file(archive_path, target_dir=None, drop_dir=False):
|
2014-05-30 03:23:09 +04:00
|
|
|
if not os.path.isfile(archive_path):
|
|
|
|
raise e.PackageLoadError('Unable to find package file')
|
|
|
|
created = False
|
|
|
|
if not target_dir:
|
|
|
|
target_dir = tempfile.mkdtemp()
|
|
|
|
created = True
|
|
|
|
elif not os.path.exists(target_dir):
|
|
|
|
os.mkdir(target_dir)
|
|
|
|
created = True
|
|
|
|
else:
|
|
|
|
if os.listdir(target_dir):
|
|
|
|
raise e.PackageLoadError('Target directory is not empty')
|
|
|
|
|
|
|
|
try:
|
|
|
|
if not zipfile.is_zipfile(archive_path):
|
2015-01-29 19:48:57 +02:00
|
|
|
raise e.PackageFormatError("Uploaded file {0} is not a "
|
|
|
|
"zip archive".format(archive_path))
|
2014-05-30 03:23:09 +04:00
|
|
|
package = zipfile.ZipFile(archive_path)
|
|
|
|
package.extractall(path=target_dir)
|
2015-08-27 04:59:50 +03:00
|
|
|
yield load_from_dir(target_dir)
|
2015-07-17 10:41:04 +08:00
|
|
|
except ValueError as err:
|
|
|
|
raise e.PackageLoadError("Couldn't load package from file: "
|
|
|
|
"{0}".format(err))
|
2014-05-30 03:23:09 +04:00
|
|
|
finally:
|
|
|
|
if drop_dir:
|
|
|
|
if created:
|
|
|
|
shutil.rmtree(target_dir)
|
|
|
|
else:
|
|
|
|
for f in os.listdir(target_dir):
|
|
|
|
os.unlink(os.path.join(target_dir, f))
|
|
|
|
|
|
|
|
|
2015-08-27 04:59:50 +03:00
|
|
|
def load_from_dir(source_directory, filename='manifest.yaml'):
|
2014-05-30 03:23:09 +04:00
|
|
|
formats = {
|
2015-08-18 15:37:30 +03:00
|
|
|
'MuranoPL': {
|
2015-10-14 17:40:39 +03:00
|
|
|
('1.0.0', '1.2.0'): murano.packages.mpl_package.MuranoPlPackage,
|
2015-08-18 15:37:30 +03:00
|
|
|
},
|
|
|
|
'Heat.HOT': {
|
|
|
|
('1.0.0', '1.0.0'): murano.packages.hot_package.HotPackage
|
|
|
|
}
|
2014-05-30 03:23:09 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if not os.path.isdir(source_directory) or not os.path.exists(
|
|
|
|
source_directory):
|
|
|
|
raise e.PackageLoadError('Invalid package directory')
|
|
|
|
full_path = os.path.join(source_directory, filename)
|
|
|
|
if not os.path.isfile(full_path):
|
|
|
|
raise e.PackageLoadError('Unable to find package manifest')
|
|
|
|
|
|
|
|
try:
|
|
|
|
with open(full_path) as stream:
|
|
|
|
content = yaml.safe_load(stream)
|
|
|
|
except Exception as ex:
|
|
|
|
trace = sys.exc_info()[2]
|
|
|
|
raise e.PackageLoadError(
|
|
|
|
"Unable to load due to '{0}'".format(str(ex))), None, trace
|
|
|
|
if content:
|
2015-08-18 15:37:30 +03:00
|
|
|
p_format_spec = str(content.get('Format') or 'MuranoPL/1.0')
|
|
|
|
if p_format_spec[0] in string.digits:
|
|
|
|
p_format_spec = 'MuranoPL/' + p_format_spec
|
|
|
|
parts = p_format_spec.split('/', 1)
|
|
|
|
if parts[0] not in formats:
|
2014-05-30 03:23:09 +04:00
|
|
|
raise e.PackageFormatError(
|
|
|
|
'Unknown or missing format version')
|
2015-08-18 15:37:30 +03:00
|
|
|
format_set = formats[parts[0]]
|
|
|
|
version = semantic_version.Version('0.0.0')
|
|
|
|
if len(parts) > 1:
|
|
|
|
version = semantic_version.Version.coerce(parts[1])
|
|
|
|
for key, value in format_set.iteritems():
|
|
|
|
min_version = semantic_version.Version(key[0])
|
|
|
|
max_version = semantic_version.Version(key[1])
|
|
|
|
if min_version <= version <= max_version:
|
2015-08-27 04:59:50 +03:00
|
|
|
return value(source_directory, content, parts[0], version)
|
2015-08-18 15:37:30 +03:00
|
|
|
raise e.PackageFormatError(
|
|
|
|
'Unsupported {0} format version {1}'.format(parts[0], version))
|