From 0ff43c9cba40315b22145f2dffecd6c5c6c621c5 Mon Sep 17 00:00:00 2001 From: Roman Vasilets Date: Thu, 25 Jun 2015 19:47:10 +0300 Subject: [PATCH] Add ability to specify directory with murano package files Currently we are able to specify murano package in the Murano context by specifying murano package address. Now we add ability to specify non-zipped murano package to Murano context. Add function that helps to pack a directory with murano package files into zipfile correctly. Change-Id: Iba95025c10181109f402824e781afedcdd549b5e --- .../Classes/HelloReporter.yaml | 25 ++++++++++++++ .../io.murano.apps.HelloReporter/UI/ui.yaml | 23 +++++++++++++ .../manifest.yaml | 10 ++++++ rally-jobs/rally-murano.yaml | 18 ++++++++++ rally/common/fileutils.py | 33 +++++++++++++++++++ .../context/murano/murano_packages.py | 22 ++++++++++--- .../scenarios/murano/environments.py | 3 +- .../murano/create_and_deploy_environment.json | 22 ++++++++++++- .../murano/create_and_deploy_environment.yaml | 17 +++++++++- tests/unit/common/test_fileutils.py | 20 +++++++++++ .../context/murano/test_murano_packages.py | 22 +++++++++++-- 11 files changed, 204 insertions(+), 11 deletions(-) create mode 100644 rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/Classes/HelloReporter.yaml create mode 100644 rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/UI/ui.yaml create mode 100644 rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/manifest.yaml diff --git a/rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/Classes/HelloReporter.yaml b/rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/Classes/HelloReporter.yaml new file mode 100644 index 0000000000..2eca9d0dfa --- /dev/null +++ b/rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/Classes/HelloReporter.yaml @@ -0,0 +1,25 @@ +Namespaces: + =: io.murano.apps + std: io.murano + sys: io.murano.system + + +Name: HelloReporter + +Extends: std:Application + +Properties: + name: + Contract: $.string().notNull() + +Workflow: + initialize: + Body: + - $.environment: $.find(std:Environment).require() + + deploy: + Body: + - If: not $.getAttr(deployed, false) + Then: + - $.environment.reporter.report($this, 'Starting deployment! Hello!') + - $.setAttr(deployed, True) diff --git a/rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/UI/ui.yaml b/rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/UI/ui.yaml new file mode 100644 index 0000000000..2d572f5f72 --- /dev/null +++ b/rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/UI/ui.yaml @@ -0,0 +1,23 @@ +Version: 2 + +Application: + ?: + type: io.murano.apps.HelloReporter + name: $.appConfiguration.name + +Forms: + - appConfiguration: + fields: + - name: name + type: string + label: Application Name + description: >- + Enter a desired name for the application. Just A-Z, a-z, 0-9, dash and + underline are allowed + - name: unitNamingPattern + type: string + required: false + hidden: true + widgetMedia: + js: ['muranodashboard/js/support_placeholder.js'] + css: {all: ['muranodashboard/css/support_placeholder.css']} diff --git a/rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/manifest.yaml b/rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/manifest.yaml new file mode 100644 index 0000000000..47e4d510f2 --- /dev/null +++ b/rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/manifest.yaml @@ -0,0 +1,10 @@ +Format: 1.0 +Type: Application +FullName: io.murano.apps.HelloReporter +Name: HelloReporter +Description: | + HelloReporter test app. +Author: 'Mirantis, Inc' +Tags: [App, Test, HelloWorld] +Classes: + io.murano.apps.HelloReporter: HelloReporter.yaml diff --git a/rally-jobs/rally-murano.yaml b/rally-jobs/rally-murano.yaml index 866c828522..b69431fef3 100644 --- a/rally-jobs/rally-murano.yaml +++ b/rally-jobs/rally-murano.yaml @@ -46,3 +46,21 @@ sla: failure_rate: max: 0 + - + args: + packages_per_env: 2 + runner: + type: "constant" + times: 8 + concurrency: 2 + context: + users: + tenants: 2 + users_per_tenant: 2 + murano_packages: + app_package: "/home/jenkins/.rally/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/" + roles: + - "admin" + sla: + failure_rate: + max: 0 diff --git a/rally/common/fileutils.py b/rally/common/fileutils.py index 1b57f9f4aa..c29ee24bb4 100644 --- a/rally/common/fileutils.py +++ b/rally/common/fileutils.py @@ -14,6 +14,8 @@ # under the License. import os +import tempfile +import zipfile def _read_env_file(path, except_env=None): @@ -82,3 +84,34 @@ def update_globals_file(key, value): os.makedirs(dir) expanded_path = os.path.join(dir, "globals") update_env_file(expanded_path, key, "%s\n" % value) + + +def pack_dir(source_directory, zip_name=None): + """Archive content of the directory into .zip + + Zip content of the source folder excluding root directory + into zip archive. When zip_name is specified it would be used + as a destination for the archive otherwise method would + try to use temporary file as a destination for the archive. + + :param source_directory: root of the newly created archive. + Directory is added recursively. + :param zip_name: destination zip file name. + :raises IOError: whenever there is IO issues. + :returns: path to the newly created zip archive either specified via + zip_name or a temporary one. + """ + + if not zip_name: + fp = tempfile.NamedTemporaryFile(delete=False) + zip_name = fp.name + zipf = zipfile.ZipFile(zip_name, mode="w") + try: + for root, dirs, files in os.walk(source_directory): + for f in files: + abspath = os.path.join(root, f) + relpath = os.path.relpath(abspath, source_directory) + zipf.write(abspath, relpath) + finally: + zipf.close() + return zip_name diff --git a/rally/plugins/openstack/context/murano/murano_packages.py b/rally/plugins/openstack/context/murano/murano_packages.py index 19fe112c21..da9e963e7b 100644 --- a/rally/plugins/openstack/context/murano/murano_packages.py +++ b/rally/plugins/openstack/context/murano/murano_packages.py @@ -13,13 +13,16 @@ # License for the specific language governing permissions and limitations # under the License. +import os import zipfile +from rally.common import fileutils from rally.common.i18n import _ from rally.common.i18n import _LE from rally.common import log as logging from rally.common import utils from rally import consts +from rally import exceptions from rally import osclients from rally.plugins.openstack.context.cleanup import manager as resource_manager from rally.task import context @@ -46,18 +49,27 @@ class PackageGenerator(context.Context): @utils.log_task_wrapper(LOG.info, _("Enter context: `Murano packages`")) def setup(self): - if not zipfile.is_zipfile(self.config["app_package"]): - msg = (_LE("There is no zip archive by this path: %s") - % self.config["app_package"]) - raise OSError(msg) + is_config_app_dir = False + if zipfile.is_zipfile(self.config["app_package"]): + zip_name = self.config["app_package"] + elif os.path.isdir(self.config["app_package"]): + is_config_app_dir = True + zip_name = fileutils.pack_dir(self.config["app_package"]) + else: + msg = (_LE("There is no zip archive or directory by this path:" + " %s") % self.config["app_package"]) + raise exceptions.ContextSetupFailure(msg=msg, + ctx="murano_packages") for user, tenant_id in utils.iterate_per_tenants( self.context["users"]): clients = osclients.Clients(user["endpoint"]) self.context["tenants"][tenant_id]["packages"] = [] + if is_config_app_dir: + self.context["tenants"][tenant_id]["murano_ctx"] = zip_name package = clients.murano().packages.create( {"categories": ["Web"], "tags": ["tag"]}, - {"file": open(self.config["app_package"])}) + {"file": open(zip_name)}) self.context["tenants"][tenant_id]["packages"].append(package) diff --git a/rally/plugins/openstack/scenarios/murano/environments.py b/rally/plugins/openstack/scenarios/murano/environments.py index 11cb13b730..2385492aeb 100644 --- a/rally/plugins/openstack/scenarios/murano/environments.py +++ b/rally/plugins/openstack/scenarios/murano/environments.py @@ -16,14 +16,13 @@ from rally.common import log as logging from rally import consts from rally.plugins.openstack.scenarios.murano import utils -from rally.plugins.openstack.scenarios.vm import utils as vm_utils from rally.task.scenarios import base from rally.task import validation LOG = logging.getLogger(__name__) -class MuranoEnvironments(utils.MuranoScenario, vm_utils.VMScenario): +class MuranoEnvironments(utils.MuranoScenario): """Benchmark scenarios for Murano environments.""" @validation.required_clients("murano") @validation.required_services(consts.Service.MURANO) diff --git a/samples/tasks/scenarios/murano/create_and_deploy_environment.json b/samples/tasks/scenarios/murano/create_and_deploy_environment.json index 93d8491114..52dc1335db 100644 --- a/samples/tasks/scenarios/murano/create_and_deploy_environment.json +++ b/samples/tasks/scenarios/murano/create_and_deploy_environment.json @@ -15,7 +15,27 @@ "users_per_tenant": 2 }, "murano_packages": { - "app_package": "rally/rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter.zip" + "app_package": "rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter.zip" + }, + "roles": ["admin"] + } + }, + { + "args": { + "packages_per_env": 2 + }, + "runner": { + "type": "constant", + "times": 2, + "concurrency": 2 + }, + "context": { + "users": { + "tenants": 2, + "users_per_tenant": 2 + }, + "murano_packages": { + "app_package": "rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/" }, "roles": ["admin"] } diff --git a/samples/tasks/scenarios/murano/create_and_deploy_environment.yaml b/samples/tasks/scenarios/murano/create_and_deploy_environment.yaml index 6b465f1052..ca1dc564d1 100644 --- a/samples/tasks/scenarios/murano/create_and_deploy_environment.yaml +++ b/samples/tasks/scenarios/murano/create_and_deploy_environment.yaml @@ -12,6 +12,21 @@ tenants: 2 users_per_tenant: 2 murano_packages: - app_package: "rally/rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter.zip" + app_package: "rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter.zip" + roles: + - "admin" + - + args: + packages_per_env: 2 + runner: + type: "constant" + times: 2 + concurrency: 2 + context: + users: + tenants: 2 + users_per_tenant: 2 + murano_packages: + app_package: "rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/" roles: - "admin" diff --git a/tests/unit/common/test_fileutils.py b/tests/unit/common/test_fileutils.py index 56776c6bf6..55892cba37 100644 --- a/tests/unit/common/test_fileutils.py +++ b/tests/unit/common/test_fileutils.py @@ -45,3 +45,23 @@ class FileUtilsTestCase(test.TestCase): "FAKE_ENV=new_value")] mock_file.return_value.readlines.assert_called_once_with() mock_file.return_value.write.assert_has_calls(calls) + + +class PackDirTestCase(test.TestCase): + + @mock.patch("os.walk") + @mock.patch("zipfile.ZipFile") + def test_pack_dir(self, mock_zip_file, mock_walk): + mock_walk.side_effect = [ + [("foo_root", [], ["file1", "file2", "file3"])]] + fileutils.pack_dir("rally-jobs/extra/murano/HelloReporter", + "fake_dir/package.zip") + mock_zip_file.assert_called_once_with("fake_dir/package.zip", + mode="w") + mock_walk.assert_called_once_with( + "rally-jobs/extra/murano/HelloReporter") + mock_zip_file.return_value.assert_has_calls( + [mock.call.write("foo_root/file1", "../../../../foo_root/file1"), + mock.call.write("foo_root/file2", "../../../../foo_root/file2"), + mock.call.write("foo_root/file3", "../../../../foo_root/file3"), + mock.call.close()]) diff --git a/tests/unit/plugins/openstack/context/murano/test_murano_packages.py b/tests/unit/plugins/openstack/context/murano/test_murano_packages.py index f3a38dbc7c..3685119b2e 100644 --- a/tests/unit/plugins/openstack/context/murano/test_murano_packages.py +++ b/tests/unit/plugins/openstack/context/murano/test_murano_packages.py @@ -80,14 +80,32 @@ class MuranoGeneratorTestCase(test.TestCase): @mock.patch("%s.osclients" % CTX) @mock.patch("%s.resource_manager.cleanup" % CTX) - def test_cleanup(self, mock_cleanup, mock_osclients): + def test_cleanup_with_zip(self, mock_cleanup, mock_osclients): mock_app = mock.Mock(id="fake_app_id") (mock_osclients.Clients().murano(). packages.create.return_value) = mock_app murano_ctx = murano_packages.PackageGenerator(self._get_context()) murano_ctx.setup() - murano_ctx.cleanup() + + mock_cleanup.assert_called_once_with(names=["murano.packages"], + users=murano_ctx.context["users"]) + + @mock.patch("%s.osclients" % CTX) + @mock.patch("%s.resource_manager.cleanup" % CTX) + def test_cleanup_with_dir(self, mock_cleanup, mock_osclients): + mock_app = mock.Mock(id="fake_app_id") + (mock_osclients.Clients().murano(). + packages.create.return_value) = mock_app + ctx_dict = self._get_context() + app_dir = ("rally-jobs/extra/murano/applications/" + "HelloReporter/io.murano.apps.HelloReporter/") + ctx_dict["config"]["murano_packages"]["app_package"] = app_dir + + murano_ctx = murano_packages.PackageGenerator(ctx_dict) + murano_ctx.setup() + murano_ctx.cleanup() + mock_cleanup.assert_called_once_with(names=["murano.packages"], users=murano_ctx.context["users"])